~ knotless Search/
↑↓ move↵ open⇧↵ all results
0
0
main
Go to filet
Code
John Andersen and Claude Opus 5.5 Merge branch 'protomarket': docs/protocol 5bf1023 History
README.md

protocol: the atproto protocol of socialweb-computer

  • every record, XRPC method and stream that socialweb-computer applications speak
  • applications talk ONLY over this protocol. a shared kcp is composition and isolation, never a data channel
  • lexicon files: lexicons/ (embedded by lexicons/embed.go, Go types generated by internal/lexgen)
  • companion of ../SYSTEM.md (the whole system) and ../KCP.md (kcp objects)
  • no history here. what changed when: git log, docs/plans/*.yaml

Files In This Tree

docwhat
README.mdthis index: NSID families, where each is documented, the end-to-end sequence
market.mdthe RFP flow: rfp, bid, accept, receipt, event, offering, heartbeat, relays, submit* XRPC, streams, selection
guest-events.mdcompute.events.vm.*, compute.events.guest.*, compute.guest.subscribeEvents, secrets, agent start, guest requester (R2)
lexicons-market.mdreference rows for every lexicon under com/publicdomainrelay/temp/ except cluster.* and badgeBlueKeys
infra.mdcomputer.socialweb.infra, ephemeralInfra, k8s.*, cluster.*: the deployment records and the gateway cluster API
identity.mdnetwork.attested.*, badgeBlueKeys, associations (plan 0036), did:key ingress, sign-in
policy.mdpolicy records (gha-lite workflows), the strongRefs an RFP attaches, tangled-vouch
outside.mdlexicons we use but do not own: sh.tangled.graph.vouch, chat.atirc.*, com.atproto.*, app.bsky.*, com.fedproxy.*, OAuth scopes per role

How To Read A Lexicon Row

Every lexicon section in this tree carries the same fields.

fieldmeaning
NSIDthe full id, as in the id of the lexicon file
typerecord, query, procedure, subscription or object
key fieldsthe fields a reader acts on; the lexicon file has the rest
rkeyself, a deterministic key (named), tid, or any with the scheme the writer uses
written by / read bythe application role and the Go package
stepthe step of the end-to-end sequence where it appears

NSID Families

familyownerlexicon fileskinddoc
com.publicdomainrelay.temp.market.*uslexicons/com/publicdomainrelay/temp/market/records + XRPCmarket.md, lexicons-market.md
com.publicdomainrelay.temp.market.association, associationRequestussamerecordsflow: identity.md; rows: lexicons-market.md
com.publicdomainrelay.temp.compute.vmuslexicons/com/publicdomainrelay/temp/compute/vm.jsonrecord (RFP payload)market.md, lexicons-market.md
com.publicdomainrelay.temp.compute.events.*, compute.guest.subscribeEventsuslexicons/com/publicdomainrelay/temp/compute/event payload records, subscriptionguest-events.md
com.publicdomainrelay.temp.ingress.webRTCuslexicons/com/publicdomainrelay/temp/ingress/recordlexicons-market.md
com.publicdomainrelay.temp.cluster.*uslexicons/com/publicdomainrelay/temp/cluster/XRPC (gateway clusters)infra.md
com.publicdomainrelay.temp.badgeBlueKeysuslexicons/com/publicdomainrelay/temp/badgeBlueKeys.jsonrecord (key claim)identity.md
computer.socialweb.infra, computer.socialweb.ephemeralInfrauslexicons/computer/socialweb/records (deployments)infra.md
computer.socialweb.k8s.*uslexicons/computer/socialweb/k8s/XRPC (gateway k8s API)infra.md
network.attested.*us (vendored shape)lexicons/network/attested/object, record, queryidentity.md
com.atproto.repo.strongRefatproto (vendored copy)lexicons/com/atproto/repo/strongRef.jsonobjectoutside.md
computer.socialweb.temp.policy.*, com.publicdomainrelay.temp.market.policies.denoWorkerusnonerecords (policy)policy.md
sh.tangled.graph.vouchtanglednone hererecord (trust edge)outside.md, policy.md
chat.atirc.mint, chat.atirc.revokeatircatirc repoXRPCoutside.md
com.atproto.*, app.bsky.*atproto, BlueskyupstreamXRPC, recordsoutside.md
com.fedproxy.rbac, com.fedproxy.sshPublicKeyfedproxynone hererecordsoutside.md

NSIDs we own that have no lexicon file

They appear only as Go constants and OAuth scopes. Each doc lists them where they belong.

NSIDGo constantdoc
computer.socialweb.temp.policy.ghaliteinternal/policyengine/executor/executor.go PolicyGhaLiteNSIDpolicy.md
computer.socialweb.temp.policy.typescriptinternal/policyengine/executor/executor.go PolicyTypescriptNSIDpolicy.md
com.publicdomainrelay.temp.market.policies.denoWorkerinternal/policyengine/executor/executor.go PolicyDenoWorkerNSIDpolicy.md
com.publicdomainrelay.temp.compute.secrets (getSecrets)internal/market/requester/secrets.go SecretsNSIDlexicons-market.md
com.publicdomainrelay.temp.compute.config.wif.simpleinternal/guestidentity/bidconfig.go WIFSimpleNSIDlexicons-market.md
com.publicdomainrelay.temp.requester.associateConfirminternal/app/compose/identity.go AssociateConfirmNSIDidentity.md
com.publicdomainrelay.temp.market.bidderAssociationinternal/atproto/oauth/scope.go CollectionBidderAssociationidentity.md
com.publicdomainrelay.temp.auth.allowlist.rbacDidinternal/atproto/oauth/scope.go CollectionRBACDIDoutside.md

Go Packages

packageholds
lexiconsthe lexicon JSON, embed.FS of com, computer, network
internal/lexgenthe generator: lexicon JSON -> Go record types, Validate, decodeRecord
internal/atproto/marketgenerated market, compute, ingress, badgeBlueKeys, network.attested.signature, strongRef types; NSID constants (nsid.go), stable rkeys
internal/atproto/infragenerated computer.socialweb.infra / ephemeralInfra types (nsid.go)
internal/atproto/oauthOAuth scope sets per role (scope.go)
internal/xrpcserverthe gateway XRPC server: cluster.*, computer.socialweb.k8s.*; validates against the embedded catalog
internal/atproto/pdsclientthe PDS client: getRecord, putRecord, createRecord, listRecords, getServiceAuth, subscribeRepos
internal/eventstreamthe market event streams and the one handler sink per role
internal/market/{requester,bidder,participant}the two sides of the RFP flow
internal/policyenginethe policy engine: executor, trust (vouches, associations), bundled gha-lite workflows

End-To-End Sequence

The steps below name every record in the order it is written. Other docs refer to them as S0 to S9.

sequenceDiagram
  autonumber
  participant U as user / operator
  participant R as Requester (CLI, page, iOS, gateway)
  participant RP as requester repo
  participant B as Bidder
  participant BP as bidder repo
  participant G as guest VM
  participant A as atirc

  U->>R: S0 sign in (OAuth, scopes per role)
  U->>RP: S1 badgeBlueKeys claim, sh.tangled.graph.vouch
  R->>RP: S2 computer.socialweb.infra (or ephemeralInfra) mirror
  R->>RP: S3 policy record, compute.vm, market.rfp (signed)
  RP-->>B: firehose market.rfp (or submitRfp)
  B->>RP: getRecord vm payload + attached policies
  B->>BP: S4 market.bid + bids.free
  B->>R: submitBid
  R->>RP: S5 market.accept (+ market.association for R2)
  R->>B: submitAccept
  B->>BP: S6 market.receipt (payload = the compute.vm ref)
  B->>G: boot from cloud-init user_data
  B->>BP: S7 market.event vm.hostKeys, vm.onNetwork
  B->>R: submitEvent
  R->>RP: S8 market.event guest.* (secrets, agentStart, r2Start)
  R->>A: chat.atirc.mint (service auth)
  R->>A: S9 chat.atirc.revoke
  R->>RP: S9 market.event vm.delete
  B->>BP: S9 market.event vm.terminated
  R->>RP: S9 infra status released / ended (record kept)

<a id="step-s0"></a>

S0: sign in

  • a MarketIdentity signs in; OAuth sessions live in the app's own OpenBao (auth/atproto session/<did>)
  • the scope set depends on the role: outside.md
  • dev networks use password accounts (com.atproto.server.createSession)
  • detail: identity.md

<a id="step-s1"></a>

S1: trust

  • an operator ties a bidder or requester DID to itself with a badgeBlueKeys claim: identity.md
  • operators and users vouch for each other with sh.tangled.graph.vouch: outside.md
  • the default policy on both sides is tangled-vouch: policy.md
  • standing associations and contract-scoped ones: identity.md

<a id="step-s2"></a>

S2: declare the deployment

  • an Infra or EphemeralInfra kcp object mirrors into computer.socialweb.infra / ephemeralInfra in the owner's repo
  • the per-account index sits at rkey self. records are never deleted
  • detail: infra.md

<a id="step-s3"></a>

S3: policy, vm, rfp

  • the requester writes its policy record (gha-lite), then compute.vm and a signed market.rfp whose policies strongRefs it
  • detail: policy.md, market.md

<a id="step-s4"></a>

S4: bid

  • bidders read the RFP from the firehose or from submitRfp, run their policy, write market.bid, its payload bids.free (rkey <bid rkey>-payload) and its config compute.config.wif.simple (rkey <bid rkey>-config)
  • detail: market.md

<a id="step-s5"></a>

S5: accept

  • the requester runs its policy, picks a bid, writes market.accept (no payload record)
  • a requester that starts a guest requester (R2) also writes a contract-scoped market.association: identity.md
  • detail: market.md

<a id="step-s6"></a>

S6: receipt

  • the winner writes market.receipt (its payload is the RFP's compute.vm ref, its cid the accept's attestation CID) and boots the guest
  • detail: market.md

<a id="step-s7"></a>

S7: boot and vm events

  • vm.hostKeys, vm.onNetwork; the ComputeContract goes Held on the iroh address and host keys
  • detail: guest-events.md

<a id="step-s8"></a>

S8: guest events and atirc

  • secrets bundle, agent start, guest requester start; the requester mints an atirc child token
  • detail: guest-events.md, outside.md

<a id="step-s9"></a>

S9: release

  • atirc token revoked, vm.delete, the bidder's vm.terminated, contract-scoped records the requester wrote are deleted
  • the Infra record keeps its history: status released, then ended. user records are never deleted
  • detail: market.md, guest-events.md, infra.md

Records Policy (all families)

  • never delete user records. no sweep, retention or GC of people's repo records
  • release deletes only the app's own contract-scoped records it wrote (e.g. its association)
  • one getRecord at a deterministic rkey; listRecords only as a legacy fallback
  • full list of stable rkeys: ../SYSTEM.md

See Also