Oddbean new post about | logout
 Sovereign Webs of Trust
Panel Discussion #2

10AM (EST)
Friday, March 29
Corny Chat
https://cornychat.com/signassist272

> “Nostr users should have control over which accounts are trusted and how content and other stuff is recommended to them, across any client.”

Join this second panel discussion in our ongoing series, bringing together Nostr developers from around the globe to iron out the deets for this upcoming NIP. 

@ManiMe 
https://yakihonne.com/article/naddr1qqgx2e3cxqenqef3x56kvd3nxymxzq3qmanlnflyzyjhgh970t8mmngrdytcp3jrmaa66u846ggg7t20cgqqxpqqqp65w7jk7e3

@straycat 
https://github.com/wds4/tapestry-protocol

@Lez 
https://github.com/lez/nips/blob/master/77.md


https://image.nostr.build/8b06e5c8b9876d76f9ef8d9e12b27466c83f9285991a33fb0812e35a11620956.jpg 
 Thank you for being part of this second panel discussion in our ongoing  Sovereign Webs of Trust series to find consensus around solving for WoT on Nostr. 
@straycat @Lez @hodlbod @Ghaz @JohnBNevin  @ManiMe 

I’d like to use this thread for “post panel” conversation and questions. (Instead of retreating prematurely to an issues thread in the NIPs GitHub repo.)

Speaking of which … 
Searching for “WoT” on NIP issues only brought up ONE result, in which @franzap and @Vitor Pamplona are basically discussing the SAME points that we did today. ☝🏼

https://github.com/nostr-protocol/nips/issues/1039

Here’s what’s on the table:

1. “is trusted” attestations should be part of a list event or each as individual events?

2. “is trusted” attestations should be private to author, private to author and “trusted” account, or public for all? (implementation and privacy concerns?)

3. “is trusted” value should be a binary or scalar? (or presented as binary but manipulated as scalar?)

4. “context of trust” (I trust so and so for X but not Y so much) should be embedded into trust attestations … or derived at “runtime” when content filters are applied?

5. What (in broad terms) would a content filter spec look like, where anybody (client, relay, DVM, or individual) could “publish” a filter for end users to “subscribe” to? Such filters could take ANY event data on nostr (including “is trusted”) to produce “recommendations” for content, accounts, and other stuff. IMHO, this is where rubber meets road for WoT on Nostr, and is often overlooked in light of implementing “is trusted” trust attestations. 

Hopefully between now and next panel we can nail a few of these, and have some new voices as well. 💜 
 @Vic ☝🏼 
 Also. Here’s what @straycat put together last night before our panel discussion. 

https://github.com/wds4/tapestry-protocol/blob/main/guides/grapevineIncorporation/NIP-proposal.md

Let’s take some time to digest this all and comment your thoughts freely on this (or mentioning this) thread.

We’re mostly all on the same boat, so consensus (barring language hurdles) should come pretty easy (lol). 
 Thanks. im looking over that thread to see what i can add 
 Here is my 2 cents for the questions:

1. App developers often make bugs, and for list events it means that it's easier to unwittingly erase the list if the user wants to add a new pubkey and cannot find the previous event on the network. Apart from that, it's easier to build graph from individual events (as VictorPamplona mentions in the github issue).

1.5 Replaceable events or static events? - Replaceable events can be updated, if trust relation changes over time. Also, event deletion seem to be not well implemented in relays.

2. Another model is private to the author + shared by relay/DVM when needed. I think the common sentiment is that we all see usecases for private trust events, but implementation is more complex. We need interactive protocol for this - as Hodlbod mentioned - or ZK proofs, and who knows what. For now, I think we should go for public, discover the possibilities and implement private model when we know more about the problem / we see what the main usecases are.

3. I would vote for an optional scalar "score" and "confidence" value. If they are absent, it's a binary true value.

4. I like the "context" term. I think it could be optional, but see a lot of value in embedding into the event, so as it can be used by filters as input. I don't see clearly what is the usecase for it derived by filters. Is it like "I trust this guy", and the algorithm tells me the context it was used in?

5. I'm probably not the one who has dig into it deeply. Not sure if this is what you mean by spec, but I'd like to know: what are the inputs/outputs, where the filter should be ran (client / relay / DVM / phone) and when (when content is created OR when queried). Should I be able to make a relay subscription based on a content filter? 
 This seems like a halfway to federation approach which I have no issue with. My issue is that access to the data on relay should be inaccessible by relay operators unless specifically granted by user for specific time and task. This probably wont happen though since it would imply moving the filtering / trusting capabilities to the edge by necessity and i dont see relay operators wanting to give up access to peoples data. 

Anything less than this while relying on relays leaves the door open for abuse. doesnt matter if the current devs and relay runners are saints. We dont know who comes next. its a common problem. once sysadmins, dbas, SLA holders get their hands on data they cant help themselves. eventually they start poking around. they conflate "their server" with "their data"

My true concern is that out of expedience we are setting the groundwork for future abuse and social engineering.

Good luck as you proceed.
I will watch with interest. 
 Dude. You have awesome feedback. And now I have even more questions… so no … you don’t get to just “drop a comment and go”.

- first … actually nostr already has a lot of public data for anyone (relays admins) to use in developing algos and such. 
- encrypted events are becoming a thing in Nostr. These “gift wrapped” events are mostly opaque to relay operators, which will complicate everything related to server side data processing. 
- Client side data processing of encrypted events will still be possible … and Nostr SHOULD have NIP in place for “privacy agreement” or something that keeps clients transparent and honest (like a checkbox “allow client side only processing of private DMs to improve WoT score…”)
- given all this… private “is trusted” events will be the first challenge to design an implementation standard for. Yes. These will need to be encrypted (who is trusting who) AND available for server side processing (who’s in my trust network) … I’m “confident” this is  doable. 

So yea… let’s be clear and lay solid groundwork to let WoT on Nostr be sovereign by design.  
 Unfortunately I am spending all my extra cycles on learning market stuff and dealing setting up the family migration out of Canada rn. When I get through this cycle ill get back to active participation in projects as funder or dev or both. for now though my plate is full so I have to satisfy myself with yelling from the audience.

Ill jump on stage when time allows and if there is no one else to do the specific thing. Other than that. am jus pleb 4 now ser. 
 Just so you know … we’re actually on the same page here. WoT on Nostr can and should be sovereign. Only we can make it so. I’ll keep you posted.  
 My preferred solution is similar to 2 but instead of DVM we use local llm. 
 Local LLMs could be considered in the NIP design, but the NIP itself shouldn’t care (or specify) HOW or WHERE a “WoT Filter” algo should be run. A free market of choices for publishing and subscribing to “WoT filters” is how sovereignty wins. 

(A “WoT Filter” could be anything that processes Nostr data to determine “trust rank” or “recommendations” for users or content.) 
 true if there is an overarching narrative or design philosophy that pushes towards decentralized as the default path. We dont currently have that. All the filtering projects that I have seen have been focused on the central utility we call a relay. Its expedient. Its dangerous. 
 I agree with basically everything @Lez  says in response to these questions. I’m going to give my own answers one Q at a time in this thread. 
 I’ll start with Question 4, bc this is the question that deserves the most attention right now.

Question 4: “context of trust” (I trust so and so for X but not Y so much) should be embedded into trust attestations … or derived at “runtime” when content filters are applied?

Answer: CONTEXT MUST BE EMBEDDED EXPLICITLY INTO TRUST ATTESTATIONS. This is what we must all be shouting from the mountaintops if we want to move forward on WoT. Deriving context at runtime doesn’t make sense to me. How can an algorithm derive that I trust Alice in some niche context, like to comment on the symbolism of trees in 18th century French literature? What if Alice isn’t on social media, doesn’t have any posts on this niche topic for me to like or zap or whatever? What if my trust in this context is based on real world interactions that have no digital footprint? I WANT THE OPTION TO SAY WHAT I MEAN AND MEAN WHAT I SAY, flat out, for any context that matters to me.

I’m not saying that we can’t ALSO use proxy data or algorithms or AI or filters to derive context. But are the derived contexts trustworthy? Maybe they are, maybe they’re not. Maybe I trust them, maybe I don’t. So let’s offer BOTH approaches: explicitly-stated contextual trust, AND algorithmically-derived contextual trust. I predict the former will turn out to be more useful, but no reason we can’t just use both methods and find out. 
 Question 1: “is trusted” attestations should be part of a list event or each as individual events?

Answer: I prefer each trust attestation to be its own individual event rather than having one event contain a list of attestations. Several reasons:

1. What Lez said: a single event list can get rolled back if a client updates a list using an old version of the list. This happens sometimes with follows lists, for example.

2. I want to have a way to filter against all trust attestations OF Alice, and that isn’t really feasible using the list event method.

3. If you include all optional fields, each attestation can get pretty big, including a context, a score, and a confidence. It gets cumbersome to pack multiple attestations with lots of data into one file.

4. There may be instances where we will want to reference a single attestation by note id (or naddr or whatever). 
 Question 2: “is trusted” attestations should be private to author, private to author and “trusted” account, or public for all? (implementation and privacy concerns?)

Answer: In the long run, users should have all of the above options. But we do not necessarily have to roll out all of the privacy options at the beginning. I’m thinking that to keep things simple, we should focus at first just on public attestations. When the time is right, we can add the option of making them private, which would involve encrypting the attestation. But it’s not immediately obvious whether to encrypt all of an attestation or only part of it. For example: maybe I want to encrypt the ratee pubkey, the score and the confidence, but I want the context to be unencrypted and searchable, because I want to sell all my ratings in context X for a few sats, and I want the customer to know how many such attestations exist before paying for them. Or maybe I want the ratee pubkey unemcrypted, but the score encrypted, again bc I want to make them purchaseable. It could get complicated figuring all this out, so best to figure out the specs for public use cases first and figure out the specs for private encryption later. 
 Question 3: “is trusted” value should be a binary or scalar? (or presented as binary but manipulated as scalar?)

Answer: I prefer scalar under the hood. But too many options can overwhelm the user, so in my proof of concept, I offer a binary option, where “trust” is recorded as a score of 100, and “don’t trust” is recorded as a score of 0. When the time is right, the user can be presented either with multiple options (trust none: 0, trust some: 50, or trust completely: 100) or a scrollbar. This is an example of what I mean when I say that DESIGN and an understanding of PRODUCT are so vitally important for making web of trust take off and fly. Gotta know when to keep options hidden and when / how to unveil them. 
 Question 5: What (in broad terms) would a content filter spec look like, where anybody (client, relay, DVM, or individual) could “publish” a filter for end users to “subscribe” to? Such filters could take ANY event data on nostr (including “is trusted”) to produce “recommendations” for content, accounts, and other stuff. IMHO, this is where rubber meets road for WoT on Nostr, and is often overlooked in light of implementing “is trusted” trust attestations. 

Answer: The Grapevine is my answer to this question. It is a method to filter content based on explicit, context-based trust attestations. 

In a nutshell: the core function of the Grapevine is to calculate WEIGHTED AVERAGES over things like product ratings (just to use one example), where the weights are proportional to the Influence Score of the author of the rating, in whatever context that you consider to be most relevant. Example: If I am at a nostr e-commerce site, and I want to rank all widgets from top to bottom based on average rating, then the Grapevine calculates the average score for each widget in the same way that Amazon does, EXCEPT that not all ratings are treated equally. If my Grapevine tells me Alice is an expert in widgets, her ratings weight more heavily than a rating by Bob, who is not to be trusted when it comes to widgets, according to my Grapevine. How much weight to give to someone about whom my Grapevine knows nothing? Set a default Influence Score for that.

Weighted averages instead of just averages. Simple but effective.

I have a proof of concept to demonstrate how it works: the app: Curated Lists, which is a part of my desktop nostr client, Pretty Good Apps. It is open source and anyone is welcome to download it and give it a whirl (below). But my app is clunky and crashes and not the best UX, which is why @kinjo  is working to refactor it as a web app. In the meantime, I have screenshots to show how it works (link below).

https://github.com/wds4/pretty-good

https://github.com/wds4/pretty-good/blob/main/appDescriptions/curatedLists/overview.md 
 Concur. Not only that but the context is timestamped at a point in time, making it possible to weight/score by that relative to current time, or infer why results for the same general filter may have changed over time. 
 Exactly. The same data might be processed in different ways by different users (or different DVMs or whatever), which is why my proposed WoT NIP for creating contextual trust attestations does not include a spec for what to do with them.

https://github.com/wds4/tapestry-protocol/blob/main/guides/grapevineIncorporation/NIP-proposal.md 
 Updated NIP-77 proposal about Web-of-trust.
https://github.com/lez/nips/blob/master/77.md
It feels clean and simple to me, also extensible, but I would love to hear feedback on that.

#wot #sovwot #wotnip #nip77 #trust #hierarchy 
 Seems like  @straycat is working on something very similar, did you guys sync up?

I recently shifted my thinking around these complex kind of attestations, it's going to be hard to: (1) implement with good UX to actually make it work, (2) too many different opinions on how to go about it

As an example, bitcoinmints.com is already working today with kind 38000 which is definitely an expression of trust. The WoT implementation you suggest will not take into account these events? Another, if a very trusted friend (because met IRL) heavily zaps someone you don't know, isn't that a form of trust? Third, if someone is listed as "good guest" in kind 827919 for a couchsurfing-type app, isn't that a massive vouch even without signing a NIP-77 event?

Seems to me expressions of trust take very different forms, will be  application-specific and therefore we should accept them as such. I'm tending to think that "writes" should be as easy, heterogenous and scattered as possible and the heavy work should be done on "reads", probably via sophisticated algos/DVMs which: (1) return a viable set of evidence to be verified client side, (2) themselves have a reputation 
 Reading through Lez’s NIP now. For comparison, mine is linked below.

Both NIPs define a format for contextual trust attestations without specifying how such attestations are processed and utilized. Both NIPs allow the rater to specify a score and a confidence, and allow to specify whether trust is transitive or not, with transitive the default.

The main difference between our NIPs is how exactly context is represented. In accordance with the tapestry method, my NIP allows each individual context to be defined and represented by an individual event, which anyone can submit, which is referenced using its note id or naddr. In addition, my NIP specifies how to organize contexts into a hierarchy. The rationale is that this allows the ontology of context to be curated by your WoT. What happens if we don’t all magically agree on the meaning of a “troll” or a “bot” or something else? We need to have competing definitions and let the community decide which definition to use — perhaps different definitions at different times. Although this may seem too complicated and too much work for the user, I believe it will actually turn out to be more intuitive, LESS WORK, and LESS COMPLICATED, because most of us will be happy to delegate all of the hard work to our WoT. In addition, ORGANIZING CONTEXTS INTO HIERARCHIES IS ESSENTIAL so that trust in a parent context can be applied automatically to all child contexts; if we don’t do that, it will be necessary to do separate attestations for parent contexts but also for each and every child context, the number of which is in theory unlimited, and this would be absolutely positively definitively 100 percent unworkable and fatal to the entire endeavor.

https://github.com/wds4/tapestry-protocol/blob/main/guides/grapevineIncorporation/NIP-proposal.md 
 I think you’re exactly right to be thinking of writes and reads separately, with writes being scattered and potentially in various formats. The heavy lifting is deciding what to do with the data, and we can be flexible in our approach: no need for everyone to use the same algo, or even to know what algos are available when creating the trust attestation.

On the topic of zaps: I think it is important to separate out in our minds the notion of PROXY INDICATORS of trust, like zaps, likes, etc, and EXPLICIT CONTEXT BASED TRUST ATTESTATIONS. No reason we can’t use both at the same time! The former exist in spades; it’s time for us to focus our attention on ways to represent the latter. 
 Yeah, wot is basically the same as any other content-related algorithm. Different algorithms will take different things into account, and different people will choose different algorithms, maybe by use case. That doesn't mean having data structures that are explicitly wot-focused are a bad thing, they can be a useful part of the solution. But I'm with you — if someone kind 7's all of someone's notes, that's a strong signal, and doesn't require the user to maintain anything to get the benefits. 
 Some algos will use only proxy indicators of trust, others will use only explicit trust attestations, and others will use both. 
 Absolutely, well said. If people want to work on wot-focused explicit attestations, all the best. My gut feeling tells me it's not worth putting much energy in that. I might be wrong 
 Exactly! Love the Read vs Write angle you use here. 
And indeed, easy writes are key.  Explicit trust attestations are not easy.  
 Haha, it feels a little bit like this classic xkcd: https://xkcd.com/927/

I think it's not a task of a NIP to define how we're going to use existing trust attestations, explicit (38000) or implicit ("827919") or proxy (zaps+likes). This is a field where "read" algorithms will compete. Maybe a NIP could be used to define the inputs or outputs for such algorithms, but it was not my intention with NIP-77.

I would be fine if app developers in the future chose this uniform format to express trust. I also think it's useful to have a query that returns a recursive trust graph, and algorithms can do anything on this data, possibly including other data sources. The goal is to avoid the xkcd situation as much as humanly possible.

And thanks for mentioning couchsurfing! https://www.trustroots.org wants to bring his community + reputation system to nostr, I'll contact him!  
 Haha it does remind of that xkcd 😄

Re: trustroots, that's very cool. A friend and I were also planning to eventually bring it back, clearly using WoT

Fully agree with first paragraph. I just read NIP-77 and have some feedback and questions:
 - I don't agree that "trust is transitive", why do you say this? It definitely scales down in an exponential way, anything beyond 3 hops is basically useless
 - I think very few relays will end up supporting the REQ change, better go the DVM route as hodlbod said (plus with enough data  these computations will become cpu intensive)
 - Definitely like the '*', makes it easy to bootstrap
 
I know this was brought up earlier, but what kind of UX you think is required to start populating these events with complex data like scores 1-100 + confidence 1-100?  
 On the topic of the UX of scores of 0-100 and confidence of 0-100:

The simplest UX would be a single button, like the follow button. Underneath the hood, you are leaving an attestation with a score of 100 and a confidence of 100 percent. Users will not need to know or think about what’s happening under the hood.

The next step up would be two buttons, like the follow and mute button. Underneath the hood, you are leaving an attestation with a score of 100 (follow) or 0 (mute).

The next step up would be either more buttons (e.g. scores of 0, 50, or 100) or a slider for the score, which you’d implement if users want more optionality.

Same thing for confidence: add more optionality if and when the users want it. Otherwise, don’t force them to have to make too many decisions. 
 New Founding's American Forum did a really great job with presenting this using different color codes. I'll see if I can dredge up a screenshot. 
 Not sure where to post this in this deep thread. Here is what I think is the common part of our thinking. A simple standard way to express trust. Then we can build on top, on different directions. https://github.com/lez/nips/blob/master/77.md 
 Simple, short, and sweet. 👍🏻

I have some other remarks —
should we open a discussion in your GitHub repo? 
 This looks amazing! Is there a recording of the call?  
 Not that I know of … are these recorded @ManiMe ? 
 I did not record. (not sure how to in corny…) Maybe recording and (more detailed) note taking can be handled for next discussion? 

(I would like to see more discussion panels focused on bringing developers together to crack Nostr’s particularly hard nuts …?)  

But ITMT… I figure our best best is to just contribute notes to this thread as an archive of sorts.  
 In Corny Chat, an owner of the room can enable recording in the room settings. Once allowed, any owner or moderator can start and stop a recording. If any owner or moderator is recording using this feature, a RECORDING IN PROGRESS bar is prominently displayed above to indicate this to participants of the room.

One can also record audio stream independent of Corny Chat which helps alleviate any issues that may be experienced with the service itself. Helpful as sometimes i stupidly rug the server to roll an update and depending on the kind of update it may restart various backend services that support that in app recording option.

#cornychat