Hey folks, I’m going to start asking for feedback on lexicon shapes for @openmusicevent.app over the next few weeks. I’ll start with a higher-level one that should be useful outside of my app too.
I think we should discuss a community lexicon primitive for adding public, typed edges to the social graph
ATProto makes ownership of a record very clear. But there may be many people or records that semantically contributed to a record, even if that record does not live in their PDS.
In OpenMusicEvent, I have a need for this shape across a lot of domains.
A concert or event may have dozens of contributors: leads, media managers, promoters, sound techs, stage hands, etc.
A performance may have many contributors. There’s not only the primary musician or band, but also dancers, visual artists, or multiple primary musicians, like a b2b DJ set.
Outside of that domain, this is still broadly applicable. An ATProto app has developers, designers, marketing contributors, maintainers, sponsors, and so on.
So that leads me toward a broadly applicable lexicon-level shape for this. Bikeshedding welcome.
A record owner can publish this edge record between two entities:
@LexiconRecord
public struct Relationship: Equatable, Sendable {
// The record author is the asserting authority.
public var subject: Entity
public var role: RelationshipRole
public var object: Entity
public var createdAt: Date
@OpenUnion
public enum Entity: Equatable, Sendable {
case identity(DID)
case record(RecordRef)
}
}
This means the record owner’s repo can say:
- woody.fm is a
role.developerforopenmusicevent.app - overgrow.fm was a
role.djfor anapp.openmusicevent.performancerecord - A painting was
role.displayedatwickedwoods.ca/2026
If a record or identity crosses repo/PDS boundaries, we’ll want a two-way confirmation shape:
@LexiconRecord
public struct RelationshipConfirmation: Equatable, Sendable {
// Published by the subject / contributor.
public var relationship: StrongRef<Relationship>
public var status: ConfirmationStatus
public var createdAt: Date
}
So the relationship is asserted by the owner/authority, and the subject can separately confirm, reject, or revoke confirmation.
Prior Art
app.bsky.graph.followandapp.bsky.feed.likeare repo-author-as-actor edge records: the author’s repo gives the record its meaning.tools.ozone.team.defs#memberhas a DID plus a role string withknownValues, which feels close to the role vocabulary here.app.bsky.graph.verificationmodels a relationship that only counts when issued by a trusted account.
Open questions:
- Should
rolebe a plain open string withknownValues, or token refs? - Should
objectalways be required, or can it default to the record author’s identity? - Should confirmation only support accepted/rejected/revoked, or is there a better vocabulary?
- Is
Relationshiptoo broad a name for a community lexicon?