Context
Discovered while implementing app.certified.graph.follow in #209. That PR adds only the follow primitive; this issue tracks the additional lexicons a real social graph would need.
The recommendation is to mirror Bluesky's app.bsky.graph.* shape for each, the same way app.certified.graph.follow mirrors app.bsky.graph.follow — so feed-builders and view services that already index Bluesky's graph can index ours with the same logic.
Recommended additions
| Proposed NSID |
Bluesky parallel |
Why |
app.certified.graph.block |
app.bsky.graph.block |
Symmetric counterpart to follow — minimum bar for safety/moderation. Same shape: subject: did, createdAt. |
app.certified.graph.list + app.certified.graph.listitem |
app.bsky.graph.list + listitem |
Curated lists of accounts (mod lists, curate lists, reference lists). Required for starter packs, mute/block lists, feed audiences, etc. |
app.certified.graph.listblock |
app.bsky.graph.listblock |
Block-by-list — subscribe to someone else's block list. Multiplies moderation reach without per-account block records. |
app.certified.graph.starterpack |
app.bsky.graph.starterpack |
The natural target for the optional via strongRef on app.certified.graph.follow — wraps a list + a feed-gen ref into a shareable onboarding bundle. |
app.certified.graph.verification |
app.bsky.graph.verification |
Issuer-signed verified-account claims; complements the existing app.certified.badge.* and app.certified.link.evm identity primitives. |
Notes / open questions
subject typing: Bluesky's graph records use a raw format: did string. app.certified already has app.certified.defs#did (used by badge.award); these can either reuse that for in-namespace consistency or stay as raw format: did strings for byte-level parity with bsky. Worth picking one direction up front.
via becomes meaningful once starterpack exists. Today it's a forward-compatibility placeholder (which is exactly what bsky did when they introduced the field).
- Mute is intentionally out of scope — Bluesky doesn't ship a
mute lexicon either; mutes are AppView-private state, not public graph records.
- Don't conflate with
org.hypercerts.context.acknowledgement — that's a bidirectional "is this record part of that context?" primitive (e.g. "is my activity in your collection?"), not a social-graph follow. Different question, different indexers.
Suggested sequencing
block (smallest, highest safety value, same shape as follow)
list + listitem (unlocks the rest)
listblock + starterpack (depend on list)
verification (independent — can land any time)
Each can ship as its own PR with the same checklist that #209 followed (lexicon JSON → gen-api → tests → SCHEMAS.md → README + SKILL + ERD updates → changeset).
Discovered-from: #209
Context
Discovered while implementing
app.certified.graph.followin #209. That PR adds only thefollowprimitive; this issue tracks the additional lexicons a real social graph would need.The recommendation is to mirror Bluesky's
app.bsky.graph.*shape for each, the same wayapp.certified.graph.followmirrorsapp.bsky.graph.follow— so feed-builders and view services that already index Bluesky's graph can index ours with the same logic.Recommended additions
app.certified.graph.blockapp.bsky.graph.blockfollow— minimum bar for safety/moderation. Same shape:subject: did,createdAt.app.certified.graph.list+app.certified.graph.listitemapp.bsky.graph.list+listitemapp.certified.graph.listblockapp.bsky.graph.listblockapp.certified.graph.starterpackapp.bsky.graph.starterpackviastrongRef onapp.certified.graph.follow— wraps a list + a feed-gen ref into a shareable onboarding bundle.app.certified.graph.verificationapp.bsky.graph.verificationapp.certified.badge.*andapp.certified.link.evmidentity primitives.Notes / open questions
subjecttyping: Bluesky's graph records use a rawformat: didstring.app.certifiedalready hasapp.certified.defs#did(used bybadge.award); these can either reuse that for in-namespace consistency or stay as rawformat: didstrings for byte-level parity with bsky. Worth picking one direction up front.viabecomes meaningful oncestarterpackexists. Today it's a forward-compatibility placeholder (which is exactly what bsky did when they introduced the field).mutelexicon either; mutes are AppView-private state, not public graph records.org.hypercerts.context.acknowledgement— that's a bidirectional "is this record part of that context?" primitive (e.g. "is my activity in your collection?"), not a social-graph follow. Different question, different indexers.Suggested sequencing
block(smallest, highest safety value, same shape asfollow)list+listitem(unlocks the rest)listblock+starterpack(depend onlist)verification(independent — can land any time)Each can ship as its own PR with the same checklist that #209 followed (lexicon JSON →
gen-api→ tests → SCHEMAS.md → README + SKILL + ERD updates → changeset).Discovered-from: #209