Opensocial.community proposal

Hey folks! This is an opinionated proposal I put together for the community WG. Still a few open questions/uncertainties that I list at the ned.

Check it out here: opensocial communities proposal - Google Docs

Feel free to comment here or we can chat more in the next WG meeting.

7 Likes

Awesome! I suggest you paste the whole thing in to your post so we can quote the text. Discourse can handle tables.

How come it’s the ‘opensocial.community proposal’ and not the ‘atmospheric communities’ proposal?

Following that..

A note on naming

I know the working group has more circled around the term “group” for this thing. I find “group” to be a bit too loose/small, and I don’t feel it captures the nature of the concept as well as “community”.

More than 90% of the atmospheric member spaces created will be ~5 member groups, much like 99% of GitHub repos are single-maintainer. Community-scale groupings are an outlier.

The position of the community professionals who’ve been outspoken about this in the WG is that “community” is much too large a term for the majority of member spaces.

Especially in the context of OAuth login screens: “This app is requesting access to your [X]”. I think “Open social communities” would read nicely there!

As in “this app is requesting access to your open social community”? I think “this app is requesting access to your group space” makes just as much sense, and to be clear I don’t expect ‘open social’ to appear as a default in any public-facing auth screens, since that’d be confusing in the context of private group spaces.

opensocial.group is available btw.


My argument in favor of groups as the more appropriately generic term for these containers is that it’s weird to preemptively force “community” upon arbitrary social groupings like a teacher-mandated study group, a handful of participants in a weekend course, an industry standards committee etc.

In short: community emerges, it can’t be prescribed.

4 Likes

Very neat. Was only able to skim the doc so far, but I like what I’m seeing. It’s pretty much what I’ve done with https://colibri.social (see the Communities | Colibri Social Documentation page for a small overview). Will comment/edit once I’ve given this a proper read.

Very much agree here. Many “communities” would not be perceived as “open social” spaces to normal people I think.


Should actions be NSIDs instead? Should they be permission sets?

I feel like they should be NSIDs in case different compatible space hosts want to extend the actions.

I feel like the name “actions” is pretty misleading because it makes me thing like a Lexicon procedure. It seems like “permissions” would be more clear.


I need to do another deep read and comment on more things, but, overall, I think this is looking pretty good! Happy to have it shaping up.

Thanks for writing this up! And generally appreciate your effort to get standards in place around this stuff ahead of Bluesky launching big features around it.

I sadly won’t be able to make the meeting (2am for me) but I’ll write some notes. I think generally this is pretty complete and well-considered. It’s helpful to have the design surface articulated like this:

There are three main pieces to this:

  • Roles & access

  • Presence & discoverability

  • Moderation

I also generally agree with the design posture, but at the same time, I think preparing for iterating on this and extending it as needed is doable and makes sense. My hope would be that we don’t need to have so much of a sense of locking down this standard forever now so much as a sense that we are creating a sensible v1 starting place: authz framework (roles + authorised actions evaluated with existing records as params) and some record lexicons.

My intuition is that keeping the focus on normal record writes rather than special methods as much as possible feels cleaner and more empowering for devs in some sense. The core of this seems like a neat composition of fairly simple rules around role configurations:

There are no deny-rules or caveats. So roles’ authorization composes simply by unioning all authorized actions**.** There is no precedence, hierarchy or evaluation order.

It would be helpful to have clarity on what, if any, custom state and special computation the community host needs to do outside of record writes that are gated by role/action checks - to me, having XRPC methods implies something of this sort. (also N.B. Re ‘actions’ I agree with Zick above - I need to mentally translate it to ‘permissions’ for it to make sense to me.)

The notion of having standardised spaces like about and members is helpful, seems to conceptually follow from standard.site in terms of having shared semantics around metadata/discovery and the social graph which are definitely the most impactful in terms of interop. But if found that we needed to add another standardised space at some point, that also seems fairly straightforward.

Beyond that main point, some other small notes:

Noting that assignable doesn’t seem to be defined anywhere

On the invite space - I think as apps are responsible for surfacing invites to users, they also need to be responsible for filtering out spam in a sensible way, and I think making use of labels etc makes sense here.

On community governance I’m just trying to imagine how this works in practice - maybe a long lasting OAuth credential that is granted to a third party community governance service, or maybe (the service as an account) membership and a special role? I.e. maybe just wanting confirmation that conceptually this would be a client to the community space host.

Generally I think this all looks really solid and exciting!

1 Like

I like it overall

Perhaps it’s just a wording thing, but the write up on “about” and “members” spaces doesn’t seem to divide things very cleanly. The definition for the “about” anchors on what it stores, whereas the “members” space anchors on who can access it. If any community want’s to adjust the access to these (beyond all or nothing), it breaks those assumptions.

I think it either needs to be a space for public and space for members (and what records sit in which space depends on the community), or we define under which spaces certain data is expected to be found (and who has access to those depends on the community). I’d prefer the former (fewer spaces, and allows for different community.opensocial.space objects for public vs members), but I’m open to either approach.

Thank you for writing this, Daniel! I spent today (and some of yesterday) going through it on stream, and I overall really enjoy the ideas there. The meeting is soon, but I thought I’d leave my questions anyway.

Also, here’s a few diagrams:


Some points of confusion pt.1: Terminology

  • Space Host vs Community Service Are these the same? Spotted the second one in the “Writing as the Community DID” section says:

    If a user (for instance a community admin) wishes to write as the community DID, they do so by holding an OAuth credential for the community DID and writing that record to the community service. The community service will support all com.atproto.space.* CRUD methods.**

  • “ejecting a member”: does this mean removing a member’s role?

    Two actions - assigning a role to a member and ejecting a member - are parameterized by the roles that they apply to.

  • community.lexicon.calendar.events:

    If a community wants to enable event applications, it might create a community.lexicon.calendar.events space. All community.lexicon.* records will then be published into this modality-specific space rather than into a universal “community” space.

    I’m assuming this meant community.lexicon.calendar.* records? (Also, on stream we ended up calling the events space community.lexicon.calendar.happenings to make it more clearly separate from community.lexicon.calendar.event.)

Some points of confusion pt.2: Tech stuff

Community DID Delegation

  • When you act as a community DID, that means any written record is added to the Community’s PDS, correct?
  • Is this type of “OAuth delegation” already in a spec? or is this something we need to special case?
  • Can a single OAuth flow grant both User and Community DID permissions?

Declaration Record:

  • Do we have any existing implementation of this? any suggestion on how it may look?

Broader concern #1: “Special” Roles

If “the Bluesky app will likely special case the roles admin and moderator”, could we use NSIDs/namespaces there?

I could be convinced that community.opensocial.roles.admin could be a standard role. But I do believe that only pain lies in giving a generic ability to special case a “moderator” role, and even more pain letting people starting to ““take”” names from a non-namespaced set.

Also, if the goal of special-casing admin /moderator is “special UI affordances/badges”, could we decouple those from roles? Less of a concern if we are namespacing the roles, but I’d love to be able to reach out to a “badged member” concept without needing to hardcode it.

Broader concern #2: Roles & Profile

(Also feeds into the next)

Each community has a profile that it publishes in its about space […] and includes records describing the rules of the community.

  • Could we make rules Lexicon be just a textual field, with a pointer to another record to learn more?

Broader concern #3: Moderation

This spec adds a moderation layer I have quite a few questions about. Most “pressing”:

  • “Each community is also a moderation service” is a statement I’m not sure how to parse. What does th is mean, specifically?
  • Labels are published as records by the community DID in the same space as the content. Why same space? I haven’t thought too long, but it does make me want to experiment with having them be in a different space :joy:

Overall… I really, really think moderation should be its own (sub)working group. This has the risk of becoming a whole other spec all on its own, and I’m sure we could get folks together who specifically care about this. We probably have enough!

Your questions:

A bit late, so I’ll answer more tomorrow, but re: the “do we like the invite model” question… yes! I love it, personally. It’s one of those things you think it’s very weird, until you see it in action and then it makes perfect sense! I will do weird stuff with that model though :smiling_face_with_horns:

Thank you for your hard work! Excited to build on this.

3 Likes

Yes +1 to group rather than community as the base noun.

@dholms.xyz unless you see a groups primitive as well?

This is coupled to RBAC concepts - when I’m defining roles in applications, I usually have at least one area that is the same as the role: the area for posting / talking / sharing that is specifically for that role / group.

Discourse has a “Staff” private area for this purpose by default.

The “community” emerges from / is supported by multiple groups and roles.

1 Like

This does make it somewhat simpler, for example, to implement an arbiter policy for this, because the arbiter natively acts as a straight-forward authorization engine for XRPC APIs.

So hypothetically if this were focused around writing plain records to the community DID, you could implement this proposal on top of a simplespace host just by putting an arbiter policy in front of it maybe. I haven’t traced everything through to make sure that would work yet.

Well, a community can change the access to those spaces I think without issues. For example, nothing stops you from making your about space private so that only members can see it, and nothing stops you from making your members space public so that everyone can read it.

The main need is to provide a standardized place to go and get that information, and have it in separate spaces so that it’s possible to give access to them differently.

I think this is the thing I’m most fuzzy on. I don’t have a clear idea of how the space host is also acting as an auth server and how that integrates, for example, with the ATProto client trying to make requests to it.

:100:

Rather, a community hosts an additional space for each application or modality. If a community wants to enable event applications, it might create a community.lexicon.calendar.events space. All community.lexicon.* records will then be published into this modality-specific space rather than into a universal “community” space.

Minor detail: this is misleading because it implies that all community.lexicon.* records for instance would be put into one space, but it is entirely feasible that you have events that are private and only visible to some people, in which case they have to be in their own separate space.

Rather, the community service also serves as an OAuth authorization server for the community DID. Instead of requiring a password, it requires that the user authenticate using their personal account.

I think this might be a problem if it requires us to open a session to every community that we need to write records under, such as if you were an admin of a bunch of spaces, that would be really frustrating to have to go through an OAuth flow for every one.

Labels are published as records by the community DID in the same space as the content. We will likely define a new com.atproto label record type.

I’m a little confused whether the space host is making labels only as records, or also acting as a “normal” atproto labeler publishing labels over the labels endpoint. ( I can’t remember exactly what it was, but I remember there was a separate label discovery mechanism, not based on records. )

In other words, the inviting community writes the record and can’t read it back.

I think this is technically kind of wrong, since the invite is written to the community’s PDS, therefore it can always read it, even if it doesn’t have read access to the user’s invites space. But I see what it’s getting at: it’s writing to a space it doesn’t have read access.

Howdy friends :smiley: recapping the discussion from the meeting for anyone that was unable to join! Thank you to those that were able to join and everyone participating in this discussion so far, I’m VERY excited to see these things start to move and to soon see Atmospheric Groups in real apps :heart:

Deep-dive on how to model proxy/delegated permissions for communities (groups) in atproto OAuth, and on spam vectors in the PDS-hosted invite/space inbox design. No decisions; group will continue in Discourse and possibly regroup in a couple weeks.

Proxy Permissions for Community DIDs

  • Core question: how to express ‘act on behalf of community DID’ in an OAuth scope a user can consent to

  • Two approaches weighed: spec a new third-party repo-access resource, vs. app holds its own OAuth credential to the community

    • Daniel leans toward the latter: simpler, no new primitives, matches web norms

    • Ms Boba wants protocol-level support so burden isn’t on every app, even if 6 months out

  • Alternative: extend repo/RPC resource with an ‘audience’ / ‘acting as’ parameter (star or specific DID), akin to audience tokens

  • Shank noted JWT Bearer Grant (used in Habitat) lets community accept any app of a given type without per-app authorization

Invite Inbox & Spam Vectors

  • PDS-hosted space inbox creates a spam vector via notifyWrite + listRepos accumulating author rows

  • Debate: apps are better equipped to filter spam than PDSs; labeling services could tag spammy apps like spam accounts

    • Mitigations floated: retention period on write notifications, compressed (space, author) keys
  • Zicklag proposal: one level of indirection — user points to a separate inbox DID / space host designed for spam handling, keeping inbox on protocol

  • Open question raised: can a DID have multiple space hosts (e.g. one for groups, one for notifications)?

Next Steps

  • Continue both discussions, and any others, in Discourse and schedule a follow-up call in a couple weeks if needed

  • Prototype a fake OAuth consent screen for the proxy-permission flow to evaluate UX

2 Likes

Thanks for the call everyone! :pray:

Wrote a summary / recap from my perspective in a tangled string so I don’t flood this topic:

@brittanyellich.com’s is better for the quick overview. :slight_smile:

1 Like

Hey all, wasn’t able to make that call, had to catch up on the spaces proposal itself. Happy to be there for the next one if I can make it, excited to see how far we can get until then. I’ve put all the unfiltered thoughts I shared on the Muny Town Discord into a string as well, feel free to have an agent summarize them or read through my mad ramblings!

Hey folks, kicking off a deeper discussion on the proposed invites space:

I wasn’t able to make the meetings yet, but have been following along and wanted to put in some of my thoughts.

I’m +1 to “group” terminology for this generic functionality. I think this will end up a bit branded and at least power-user-visible (eg, like Standard Site). I am still thinking over what full name (and NSID domain) I this is best.

For transparency, we (Bluesky) registered this domain and we could use/donate it for this project if that is what the consensus ends up being.

My current thinking is that there should be a “group host” service which hosts space authority accounts for community groups, and fills all the roles of: PDS host, authorization server, space host, and open social API server. These would be generic protocol servers, separate from app services, but app operators might run one for ease of setup (similar to some app devs running PDS instances for easy creation). Group members with appropriate roles could log in to the group host to manage the account (within their permission) using OAuth. And also approve OAuth sessions on behalf of the group to app servers. This would resolve how permission delegation works: entirely within the group host, not needing any new auth or protocol features. Apps end up with OAuth sessions directly authorized to the group account; there aren’t “on behalf of” permissions. This is basically what dholms proposed, but phrased/framed a bit differently.

I think that role permissions should probably be NSIDs, and probably be permission-set lexicon schemas. I think they can have additional semantics beyond just the permission-set permissions if needed. Eg, could have two differently named permission sets with the same rpc or space permissions, but the group host could enforce them differently.

2 Likes