diff --git a/packages/docs/content/docs/experimental/spaces/changelog.md b/packages/docs/content/docs/experimental/spaces/changelog.md index 2b0aae6..a4d3776 100644 --- a/packages/docs/content/docs/experimental/spaces/changelog.md +++ b/packages/docs/content/docs/experimental/spaces/changelog.md @@ -2,7 +2,32 @@ title: "Changelog" --- -## Latest — Proposal 0016 Alignment +## v2.11 — Final Proposal 0016 Alignment + +Aligns with the merged [Proposal 0016](https://github.com/bluesky-social/proposals/blob/main/0016-permissioned-data/README.md) specification. + +### URI scheme change + +- **`ats://` → `at://` with `space` path segment** — space URIs now use the standard `at://` scheme with a literal `space` segment: `at:///space//`. Record URIs follow: `at:///space/////`. + +### Endpoint changes + +- **`getRepoState` → `getLatestCommit`** — renamed to match the proposal. The old name is kept as a backward-compatible alias. +- **`getRepo`** (GET) — new endpoint that exports a user's repo as a CAR v1 file (two roots: signedCommit + DRISL index) +- **`listRepoOps`** now inlines record values by default via LEFT JOIN against `space_records`. Pass `excludeValues=true` for metadata-only responses. + +### Commit changes + +- **`SignedCommit.ver`** — new version field (currently `1`) for future-proofing +- **Commit context string** now includes the author's DID: `tag || space || author || rev || ikm` (was `tag || space || rev || ikm`) + +### Breaking changes + +- All space URIs now use `at://` with a `space` segment instead of `ats://`. Clients using the old scheme must update. + +--- + +## v2.10.0 — Proposal 0016 Alignment Major restructuring to align with [AT Protocol Proposal 0016](https://github.com/bluesky-social/proposals) (Permissioned Data). @@ -59,6 +84,14 @@ Major restructuring to align with [AT Protocol Proposal 0016](https://github.com --- +## v2.8.0 + +### Bug fixes + +- Spaces endpoints now use cursor-based pagination instead of offset-based + +--- + ## v2.6.0 ### New endpoints diff --git a/packages/docs/content/docs/experimental/spaces/credentials.md b/packages/docs/content/docs/experimental/spaces/credentials.md index 26bd1fe..81d6621 100644 --- a/packages/docs/content/docs/experimental/spaces/credentials.md +++ b/packages/docs/content/docs/experimental/spaces/credentials.md @@ -42,7 +42,7 @@ Note: this endpoint is a GET request (not POST). The previous `getMemberGrant` e ```ts tab="TypeScript" tab-group="language" const params = new URLSearchParams({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", }); const response = await fetch(`https://happyview.example.com/xrpc/com.atproto.space.getDelegationToken?${params}`, { headers: { @@ -59,7 +59,7 @@ const data: DelegationTokenResponse = await response.json(); ``` ```js tab="JavaScript" tab-group="language" const params = new URLSearchParams({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", }); const response = await fetch(`https://happyview.example.com/xrpc/com.atproto.space.getDelegationToken?${params}`, { headers: { @@ -73,7 +73,7 @@ const data = await response.json(); ```rust tab="Rust" tab-group="language" let response = client .get("https://happyview.example.com/xrpc/com.atproto.space.getDelegationToken") - .query(&[("space", "ats://did:plc:abc123/com.example.forum/main")]) + .query(&[("space", "at://did:plc:abc123/space/com.example.forum/main")]) .header("X-Client-Key", client_key) .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) @@ -83,7 +83,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" req, _ := http.NewRequest("GET", - "https://happyview.example.com/xrpc/com.atproto.space.getDelegationToken?space=ats%3A%2F%2Fdid%3Aplc%3Aabc123%2Fcom.example.forum%2Fmain", + "https://happyview.example.com/xrpc/com.atproto.space.getDelegationToken?space=at%3A%2F%2Fdid%3Aplc%3Aabc123%2Fspace%2Fcom.example.forum%2Fmain", nil) req.Header.Set("X-Client-Key", clientKey) req.Header.Set("Authorization", "DPoP "+accessToken) @@ -91,7 +91,7 @@ req.Header.Set("DPoP", dpopProof) resp, err := http.DefaultClient.Do(req) ``` ```sh tab="cURL" tab-group="language" -curl 'https://happyview.example.com/xrpc/com.atproto.space.getDelegationToken?space=ats%3A%2F%2Fdid%3Aplc%3Aabc123%2Fcom.example.forum%2Fmain' \ +curl 'https://happyview.example.com/xrpc/com.atproto.space.getDelegationToken?space=at%3A%2F%2Fdid%3Aplc%3Aabc123%2Fspace%2Fcom.example.forum%2Fmain' \ -H 'X-Client-Key: hvc_...' \ -H 'Authorization: DPoP ' \ -H 'DPoP: ' @@ -194,7 +194,7 @@ The JWT payload contains: | Claim | Description | |---|---| | `iss` | The space authority's DID (who signed it) | -| `sub` | The full `ats://` space URI | +| `sub` | The full `at://` space URI | | `iat` | Issued at (Unix timestamp) | | `exp` | Expiry (Unix timestamp) | | `jti` | Random nonce for replay protection | diff --git a/packages/docs/content/docs/experimental/spaces/index.md b/packages/docs/content/docs/experimental/spaces/index.md index 8fed136..ead6d27 100644 --- a/packages/docs/content/docs/experimental/spaces/index.md +++ b/packages/docs/content/docs/experimental/spaces/index.md @@ -16,12 +16,12 @@ A **space** is identified by three components: - **Type** — the space type as an NSID, describing the modality (e.g. a forum, a group chat, a photo album) - **Space key (skey)** — a short string differentiating multiple spaces of the same type -These form the space URI: `ats:////` +These form the space URI: `at:///space//` A **space record** adds three more components to the URI: the author's DID, the collection NSID, and the record key: ``` -ats://///// +at:///space///// ``` ## Feature flag @@ -100,7 +100,8 @@ The previous `dev.happyview.space.*` endpoints remain as backward-compatible ali | `com.atproto.simplespace.addMember` | POST | Add a member | | `com.atproto.simplespace.removeMember` | POST | Remove a member | | `com.atproto.simplespace.listMembers` | GET | List resolved members | -| `com.atproto.space.getRepoState` | GET | Get per-user repo state (LtHash + commit) | +| `com.atproto.space.getLatestCommit` | GET | Get per-user signed commit | +| `com.atproto.space.getRepo` | GET | Export a user's repo as a CAR file | | `com.atproto.space.listRepoOps` | GET | List record operation log entries | | `com.atproto.space.listRepos` | GET | List repos (authors) in a space | | `com.atproto.space.getDelegationToken` | GET | Get a delegation token (step 1 of credentials) | @@ -150,10 +151,12 @@ HappyView implements [AT Protocol Proposal 0016](https://github.com/bluesky-soci - **App access** — `open`, `allowList` (replaces `appAllowlist`/`appDenylist`) - **Delegation tokens** — `getDelegationToken` (GET, 60-second TTL) replaces `getMemberGrant` - **Space credentials** — `atproto-space-credential+jwt` typ, ES256, 2-hour TTL -- **Deniable commit signatures** — user signs context (space + rev + random IKM), not content hash +- **Deniable commit signatures** — user signs context (space + author + rev + random IKM), not content hash - **LtHash** — homomorphic set-hash (2048-byte state, 1024 uint16 lanes, BLAKE3 XOF) -- **Record operation log** — `listRepoOps` returns the oplog for sync -- **Repo state** — `getRepoState` returns LtHash state + signed commit +- **SignedCommit** — versioned commit struct (`ver: 1`) with hash, ikm, sig, mac, rev +- **Record operation log** — `listRepoOps` returns the oplog for sync (values inlined by default, `excludeValues` to opt out) +- **Latest commit** — `getLatestCommit` returns the signed commit for a user in a space +- **Repo export** — `getRepo` exports a user's repo as a CAR v1 file (signedCommit + DRISL index) - **Write notifications** — `registerNotify`, `notifyWrite`, `notifySpaceDeleted` - **Space-scoped blobs** — `getBlob` - **Authority DID** — spaces use `authority_did` (not `owner_did`) with a separate `creator_did` diff --git a/packages/docs/content/docs/experimental/spaces/invites.md b/packages/docs/content/docs/experimental/spaces/invites.md index b96736b..3cb0a6f 100644 --- a/packages/docs/content/docs/experimental/spaces/invites.md +++ b/packages/docs/content/docs/experimental/spaces/invites.md @@ -26,7 +26,7 @@ const response = await fetch("https://happyview.example.com/xrpc/dev.happyview.s "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", access: "write", maxUses: 10, expiresAt: "2026-06-01T00:00:00Z", @@ -51,7 +51,7 @@ const response = await fetch("https://happyview.example.com/xrpc/dev.happyview.s "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", access: "write", maxUses: 10, expiresAt: "2026-06-01T00:00:00Z", @@ -66,7 +66,7 @@ let response = client .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "access": "write", "maxUses": 10, "expiresAt": "2026-06-01T00:00:00Z" @@ -77,7 +77,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" body := bytes.NewBufferString(`{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "access": "write", "maxUses": 10, "expiresAt": "2026-06-01T00:00:00Z" @@ -97,7 +97,7 @@ curl -X POST 'https://happyview.example.com/xrpc/dev.happyview.space.createInvit -H 'DPoP: ' \ -H 'Content-Type: application/json' \ -d '{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "access": "write", "maxUses": 10, "expiresAt": "2026-06-01T00:00:00Z" @@ -205,7 +205,7 @@ curl -X POST 'https://happyview.example.com/xrpc/dev.happyview.space.acceptInvit ```json { - "uri": "ats://did:plc:abc123/com.example.forum/main", + "uri": "at://did:plc:abc123/space/com.example.forum/main", "access": "write" } ``` @@ -230,7 +230,7 @@ const response = await fetch("https://happyview.example.com/xrpc/dev.happyview.s "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", inviteId: "uuid", }), }); @@ -245,7 +245,7 @@ const response = await fetch("https://happyview.example.com/xrpc/dev.happyview.s "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", inviteId: "uuid", }), }); @@ -257,7 +257,7 @@ let response = client .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "inviteId": "uuid" })) .send() @@ -265,7 +265,7 @@ let response = client ``` ```go tab="Go" tab-group="language" body := bytes.NewBufferString(`{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "inviteId": "uuid" }`) req, _ := http.NewRequest("POST", @@ -283,7 +283,7 @@ curl -X POST 'https://happyview.example.com/xrpc/dev.happyview.space.revokeInvit -H 'DPoP: ' \ -H 'Content-Type: application/json' \ -d '{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "inviteId": "uuid" }' ``` @@ -296,7 +296,7 @@ Only the space authority or a super admin can list invites. ```ts tab="TypeScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/dev.happyview.space.listInvites?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/dev.happyview.space.listInvites?space=at://did:plc:abc123/space/com.example.forum/main", { headers: { "X-Client-Key": CLIENT_KEY, @@ -319,7 +319,7 @@ const data: { invites: Invite[] } = await response.json(); ``` ```js tab="JavaScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/dev.happyview.space.listInvites?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/dev.happyview.space.listInvites?space=at://did:plc:abc123/space/com.example.forum/main", { headers: { "X-Client-Key": CLIENT_KEY, @@ -333,7 +333,7 @@ const data = await response.json(); ```rust tab="Rust" tab-group="language" let response = client .get("https://happyview.example.com/xrpc/dev.happyview.space.listInvites") - .query(&[("space", "ats://did:plc:abc123/com.example.forum/main")]) + .query(&[("space", "at://did:plc:abc123/space/com.example.forum/main")]) .header("X-Client-Key", client_key) .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) @@ -343,7 +343,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" req, _ := http.NewRequest("GET", - "https://happyview.example.com/xrpc/dev.happyview.space.listInvites?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/dev.happyview.space.listInvites?space=at://did:plc:abc123/space/com.example.forum/main", nil) req.Header.Set("X-Client-Key", clientKey) req.Header.Set("Authorization", "DPoP "+accessToken) @@ -351,7 +351,7 @@ req.Header.Set("DPoP", dpopProof) resp, err := http.DefaultClient.Do(req) ``` ```sh tab="cURL" tab-group="language" -curl 'https://happyview.example.com/xrpc/dev.happyview.space.listInvites?space=ats://did:plc:abc123/com.example.forum/main' \ +curl 'https://happyview.example.com/xrpc/dev.happyview.space.listInvites?space=at://did:plc:abc123/space/com.example.forum/main' \ -H 'X-Client-Key: hvc_...' \ -H 'Authorization: DPoP ' \ -H 'DPoP: ' diff --git a/packages/docs/content/docs/experimental/spaces/managing-spaces.md b/packages/docs/content/docs/experimental/spaces/managing-spaces.md index 0d99f1d..e8626d4 100644 --- a/packages/docs/content/docs/experimental/spaces/managing-spaces.md +++ b/packages/docs/content/docs/experimental/spaces/managing-spaces.md @@ -114,7 +114,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.simplespace.createS ```json { - "uri": "ats://did:plc:abc123/com.example.forum/main" + "uri": "at://did:plc:abc123/space/com.example.forum/main" } ``` @@ -135,7 +135,7 @@ Additional fields are preserved as-is. ```ts tab="TypeScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/com.atproto.space.getSpace?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/com.atproto.space.getSpace?space=at://did:plc:abc123/space/com.example.forum/main", { headers: { "X-Client-Key": CLIENT_KEY, @@ -153,7 +153,7 @@ const data: GetSpaceResponse = await response.json(); ``` ```js tab="JavaScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/com.atproto.space.getSpace?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/com.atproto.space.getSpace?space=at://did:plc:abc123/space/com.example.forum/main", { headers: { "X-Client-Key": CLIENT_KEY, @@ -167,7 +167,7 @@ const data = await response.json(); ```rust tab="Rust" tab-group="language" let response = client .get("https://happyview.example.com/xrpc/com.atproto.space.getSpace") - .query(&[("space", "ats://did:plc:abc123/com.example.forum/main")]) + .query(&[("space", "at://did:plc:abc123/space/com.example.forum/main")]) .header("X-Client-Key", client_key) .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) @@ -177,7 +177,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" req, _ := http.NewRequest("GET", - "https://happyview.example.com/xrpc/com.atproto.space.getSpace?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/com.atproto.space.getSpace?space=at://did:plc:abc123/space/com.example.forum/main", nil) req.Header.Set("X-Client-Key", clientKey) req.Header.Set("Authorization", "DPoP "+accessToken) @@ -185,7 +185,7 @@ req.Header.Set("DPoP", dpopProof) resp, err := http.DefaultClient.Do(req) ``` ```sh tab="cURL" tab-group="language" -curl 'https://happyview.example.com/xrpc/com.atproto.space.getSpace?space=ats://did:plc:abc123/com.example.forum/main' \ +curl 'https://happyview.example.com/xrpc/com.atproto.space.getSpace?space=at://did:plc:abc123/space/com.example.forum/main' \ -H 'X-Client-Key: hvc_...' \ -H 'Authorization: DPoP ' \ -H 'DPoP: ' @@ -272,7 +272,7 @@ curl 'https://happyview.example.com/xrpc/com.atproto.space.listSpaces?limit=20' { "spaces": [ { - "uri": "ats://did:plc:abc123/com.example.forum/main", + "uri": "at://did:plc:abc123/space/com.example.forum/main", "isOwner": true } ], @@ -294,7 +294,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.sim "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", displayName: "Updated Forum Name", mintPolicy: "public", }), @@ -310,7 +310,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.sim "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", displayName: "Updated Forum Name", mintPolicy: "public", }), @@ -323,7 +323,7 @@ let response = client .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "displayName": "Updated Forum Name", "mintPolicy": "public" })) @@ -332,7 +332,7 @@ let response = client ``` ```go tab="Go" tab-group="language" body := bytes.NewBufferString(`{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "displayName": "Updated Forum Name", "mintPolicy": "public" }`) @@ -351,7 +351,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.simplespace.updateS -H 'DPoP: ' \ -H 'Content-Type: application/json' \ -d '{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "displayName": "Updated Forum Name", "mintPolicy": "public" }' @@ -373,7 +373,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.sim "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", }), }); ``` @@ -387,7 +387,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.sim "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", }), }); ``` @@ -398,13 +398,13 @@ let response = client .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main" + "space": "at://did:plc:abc123/space/com.example.forum/main" })) .send() .await?; ``` ```go tab="Go" tab-group="language" -body := bytes.NewBufferString(`{"space": "ats://did:plc:abc123/com.example.forum/main"}`) +body := bytes.NewBufferString(`{"space": "at://did:plc:abc123/space/com.example.forum/main"}`) req, _ := http.NewRequest("POST", "https://happyview.example.com/xrpc/com.atproto.simplespace.deleteSpace", body) req.Header.Set("X-Client-Key", clientKey) @@ -419,7 +419,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.simplespace.deleteS -H 'Authorization: DPoP ' \ -H 'DPoP: ' \ -H 'Content-Type: application/json' \ - -d '{"space": "ats://did:plc:abc123/com.example.forum/main"}' + -d '{"space": "at://did:plc:abc123/space/com.example.forum/main"}' ``` @@ -432,7 +432,7 @@ Returns the simplespace configuration for a space. Requires admin access (space ```ts tab="TypeScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/com.atproto.simplespace.getConfig?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/com.atproto.simplespace.getConfig?space=at://did:plc:abc123/space/com.example.forum/main", { headers: { "X-Client-Key": CLIENT_KEY, @@ -451,7 +451,7 @@ const data: SpaceConfig = await response.json(); ``` ```js tab="JavaScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/com.atproto.simplespace.getConfig?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/com.atproto.simplespace.getConfig?space=at://did:plc:abc123/space/com.example.forum/main", { headers: { "X-Client-Key": CLIENT_KEY, @@ -465,7 +465,7 @@ const data = await response.json(); ```rust tab="Rust" tab-group="language" let response = client .get("https://happyview.example.com/xrpc/com.atproto.simplespace.getConfig") - .query(&[("space", "ats://did:plc:abc123/com.example.forum/main")]) + .query(&[("space", "at://did:plc:abc123/space/com.example.forum/main")]) .header("X-Client-Key", client_key) .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) @@ -475,7 +475,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" req, _ := http.NewRequest("GET", - "https://happyview.example.com/xrpc/com.atproto.simplespace.getConfig?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/com.atproto.simplespace.getConfig?space=at://did:plc:abc123/space/com.example.forum/main", nil) req.Header.Set("X-Client-Key", clientKey) req.Header.Set("Authorization", "DPoP "+accessToken) @@ -483,7 +483,7 @@ req.Header.Set("DPoP", dpopProof) resp, err := http.DefaultClient.Do(req) ``` ```sh tab="cURL" tab-group="language" -curl 'https://happyview.example.com/xrpc/com.atproto.simplespace.getConfig?space=ats://did:plc:abc123/com.example.forum/main' \ +curl 'https://happyview.example.com/xrpc/com.atproto.simplespace.getConfig?space=at://did:plc:abc123/space/com.example.forum/main' \ -H 'X-Client-Key: hvc_...' \ -H 'Authorization: DPoP ' \ -H 'DPoP: ' @@ -520,7 +520,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.sim "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", mintPolicy: "public", appAccess: { type: "allowList", allowed: ["did:web:myapp.example.com"] }, }), @@ -536,7 +536,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.sim "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", mintPolicy: "public", appAccess: { type: "allowList", allowed: ["did:web:myapp.example.com"] }, }), @@ -549,7 +549,7 @@ let response = client .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "mintPolicy": "public", "appAccess": { "type": "allowList", "allowed": ["did:web:myapp.example.com"] } })) @@ -559,7 +559,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" body := bytes.NewBufferString(`{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "mintPolicy": "public", "appAccess": {"type": "allowList", "allowed": ["did:web:myapp.example.com"]} }`) @@ -578,7 +578,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.simplespace.updateC -H 'DPoP: ' \ -H 'Content-Type: application/json' \ -d '{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "mintPolicy": "public", "appAccess": {"type": "allowList", "allowed": ["did:web:myapp.example.com"]} }' diff --git a/packages/docs/content/docs/experimental/spaces/members.md b/packages/docs/content/docs/experimental/spaces/members.md index b39ce4b..105f50c 100644 --- a/packages/docs/content/docs/experimental/spaces/members.md +++ b/packages/docs/content/docs/experimental/spaces/members.md @@ -22,7 +22,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.sim "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", did: "did:plc:newmember", access: "write", isDelegation: false, @@ -49,7 +49,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.sim "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", did: "did:plc:newmember", access: "write", isDelegation: false, @@ -64,7 +64,7 @@ let response = client .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "did": "did:plc:newmember", "access": "write", "isDelegation": false @@ -75,7 +75,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" body := bytes.NewBufferString(`{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "did": "did:plc:newmember", "access": "write", "isDelegation": false @@ -95,7 +95,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.simplespace.addMemb -H 'DPoP: ' \ -H 'Content-Type: application/json' \ -d '{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "did": "did:plc:newmember", "access": "write", "isDelegation": false @@ -139,7 +139,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.sim "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", did: "did:plc:newmember", }), }); @@ -154,7 +154,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.sim "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", did: "did:plc:newmember", }), }); @@ -166,7 +166,7 @@ let response = client .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "did": "did:plc:newmember" })) .send() @@ -174,7 +174,7 @@ let response = client ``` ```go tab="Go" tab-group="language" body := bytes.NewBufferString(`{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "did": "did:plc:newmember" }`) req, _ := http.NewRequest("POST", @@ -192,7 +192,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.simplespace.removeM -H 'DPoP: ' \ -H 'Content-Type: application/json' \ -d '{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "did": "did:plc:newmember" }' ``` @@ -201,7 +201,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.simplespace.removeM ```ts tab="TypeScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/com.atproto.simplespace.listMembers?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/com.atproto.simplespace.listMembers?space=at://did:plc:abc123/space/com.example.forum/main", { headers: { "X-Client-Key": CLIENT_KEY, @@ -218,7 +218,7 @@ const data: { members: ResolvedMember[] } = await response.json(); ``` ```js tab="JavaScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/com.atproto.simplespace.listMembers?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/com.atproto.simplespace.listMembers?space=at://did:plc:abc123/space/com.example.forum/main", { headers: { "X-Client-Key": CLIENT_KEY, @@ -232,7 +232,7 @@ const data = await response.json(); ```rust tab="Rust" tab-group="language" let response = client .get("https://happyview.example.com/xrpc/com.atproto.simplespace.listMembers") - .query(&[("space", "ats://did:plc:abc123/com.example.forum/main")]) + .query(&[("space", "at://did:plc:abc123/space/com.example.forum/main")]) .header("X-Client-Key", client_key) .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) @@ -242,7 +242,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" req, _ := http.NewRequest("GET", - "https://happyview.example.com/xrpc/com.atproto.simplespace.listMembers?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/com.atproto.simplespace.listMembers?space=at://did:plc:abc123/space/com.example.forum/main", nil) req.Header.Set("X-Client-Key", clientKey) req.Header.Set("Authorization", "DPoP "+accessToken) @@ -250,7 +250,7 @@ req.Header.Set("DPoP", dpopProof) resp, err := http.DefaultClient.Do(req) ``` ```sh tab="cURL" tab-group="language" -curl 'https://happyview.example.com/xrpc/com.atproto.simplespace.listMembers?space=ats://did:plc:abc123/com.example.forum/main' \ +curl 'https://happyview.example.com/xrpc/com.atproto.simplespace.listMembers?space=at://did:plc:abc123/space/com.example.forum/main' \ -H 'X-Client-Key: hvc_...' \ -H 'Authorization: DPoP ' \ -H 'DPoP: ' @@ -284,8 +284,8 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.sim "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", - did: "ats://did:plc:org/com.example.team/engineering", + space: "at://did:plc:abc123/space/com.example.forum/main", + did: "at://did:plc:org/space/com.example.team/engineering", access: "read", isDelegation: true, }), @@ -301,8 +301,8 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.sim "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", - did: "ats://did:plc:org/com.example.team/engineering", + space: "at://did:plc:abc123/space/com.example.forum/main", + did: "at://did:plc:org/space/com.example.team/engineering", access: "read", isDelegation: true, }), @@ -315,8 +315,8 @@ let response = client .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main", - "did": "ats://did:plc:org/com.example.team/engineering", + "space": "at://did:plc:abc123/space/com.example.forum/main", + "did": "at://did:plc:org/space/com.example.team/engineering", "access": "read", "isDelegation": true })) @@ -325,8 +325,8 @@ let response = client ``` ```go tab="Go" tab-group="language" body := bytes.NewBufferString(`{ - "space": "ats://did:plc:abc123/com.example.forum/main", - "did": "ats://did:plc:org/com.example.team/engineering", + "space": "at://did:plc:abc123/space/com.example.forum/main", + "did": "at://did:plc:org/space/com.example.team/engineering", "access": "read", "isDelegation": true }`) @@ -345,8 +345,8 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.simplespace.addMemb -H 'DPoP: ' \ -H 'Content-Type: application/json' \ -d '{ - "space": "ats://did:plc:abc123/com.example.forum/main", - "did": "ats://did:plc:org/com.example.team/engineering", + "space": "at://did:plc:abc123/space/com.example.forum/main", + "did": "at://did:plc:org/space/com.example.team/engineering", "access": "read", "isDelegation": true }' diff --git a/packages/docs/content/docs/experimental/spaces/notifications.md b/packages/docs/content/docs/experimental/spaces/notifications.md index ce4c93e..ab69201 100644 --- a/packages/docs/content/docs/experimental/spaces/notifications.md +++ b/packages/docs/content/docs/experimental/spaces/notifications.md @@ -24,7 +24,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.spa "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", serviceDid: "did:web:feed.example.com", endpoint: "https://feed.example.com/webhooks/space-writes", }), @@ -44,7 +44,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.spa "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", serviceDid: "did:web:feed.example.com", endpoint: "https://feed.example.com/webhooks/space-writes", }), @@ -58,7 +58,7 @@ let response = client .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "serviceDid": "did:web:feed.example.com", "endpoint": "https://feed.example.com/webhooks/space-writes" })) @@ -68,7 +68,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" body := bytes.NewBufferString(`{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "serviceDid": "did:web:feed.example.com", "endpoint": "https://feed.example.com/webhooks/space-writes" }`) @@ -87,7 +87,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.space.registerNotif -H 'DPoP: ' \ -H 'Content-Type: application/json' \ -d '{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "serviceDid": "did:web:feed.example.com", "endpoint": "https://feed.example.com/webhooks/space-writes" }' @@ -97,7 +97,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.space.registerNotif | Field | Type | Required | Description | | ------------ | ------ | -------- | ------------------------------------------------ | -| `space` | string | Yes | Space URI (`ats://...`) | +| `space` | string | Yes | Space URI (`at://...`) | | `serviceDid` | string | Yes | DID of the service receiving notifications | | `endpoint` | string | Yes | HTTPS endpoint to deliver notifications to | @@ -144,7 +144,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.spa "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", did: "did:plc:author456", collection: "com.example.forum.post", rkey: "3jwq5dya2gy2z", @@ -161,7 +161,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.spa "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", did: "did:plc:author456", collection: "com.example.forum.post", rkey: "3jwq5dya2gy2z", @@ -175,7 +175,7 @@ const data = await response.json(); let response = client .post("https://happyview.example.com/xrpc/com.atproto.space.notifyWrite") .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "did": "did:plc:author456", "collection": "com.example.forum.post", "rkey": "3jwq5dya2gy2z", @@ -187,7 +187,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" body := bytes.NewBufferString(`{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "did": "did:plc:author456", "collection": "com.example.forum.post", "rkey": "3jwq5dya2gy2z", @@ -202,7 +202,7 @@ resp, err := http.DefaultClient.Do(req) curl -X POST 'https://happyview.example.com/xrpc/com.atproto.space.notifyWrite' \ -H 'Content-Type: application/json' \ -d '{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "did": "did:plc:author456", "collection": "com.example.forum.post", "rkey": "3jwq5dya2gy2z", @@ -214,7 +214,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.space.notifyWrite' | Field | Type | Required | Description | | ------------ | ------------- | -------- | ------------------------------------------------ | -| `space` | string | Yes | Space URI (`ats://...`) | +| `space` | string | Yes | Space URI (`at://...`) | | `did` | string | Yes | DID of the author who made the change | | `collection` | string (NSID) | Yes | Collection the record belongs to | | `rkey` | string | Yes | Record key | @@ -239,7 +239,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.spa "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", }), }); const data = await response.json(); @@ -252,7 +252,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.spa "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", }), }); const data = await response.json(); @@ -262,7 +262,7 @@ const data = await response.json(); let response = client .post("https://happyview.example.com/xrpc/com.atproto.space.notifySpaceDeleted") .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main" + "space": "at://did:plc:abc123/space/com.example.forum/main" })) .send() .await?; @@ -270,7 +270,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" body := bytes.NewBufferString(`{ - "space": "ats://did:plc:abc123/com.example.forum/main" + "space": "at://did:plc:abc123/space/com.example.forum/main" }`) req, _ := http.NewRequest("POST", "https://happyview.example.com/xrpc/com.atproto.space.notifySpaceDeleted", body) @@ -281,7 +281,7 @@ resp, err := http.DefaultClient.Do(req) curl -X POST 'https://happyview.example.com/xrpc/com.atproto.space.notifySpaceDeleted' \ -H 'Content-Type: application/json' \ -d '{ - "space": "ats://did:plc:abc123/com.example.forum/main" + "space": "at://did:plc:abc123/space/com.example.forum/main" }' ``` @@ -289,7 +289,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.space.notifySpaceDe | Field | Type | Required | Description | | ------- | ------ | -------- | ----------------------- | -| `space` | string | Yes | Space URI (`ats://...`) | +| `space` | string | Yes | Space URI (`at://...`) | **Response (200):** diff --git a/packages/docs/content/docs/experimental/spaces/records.md b/packages/docs/content/docs/experimental/spaces/records.md index 4e7425a..4ddca14 100644 --- a/packages/docs/content/docs/experimental/spaces/records.md +++ b/packages/docs/content/docs/experimental/spaces/records.md @@ -6,11 +6,11 @@ title: "Records" This API is experimental and will change. See the [Permissioned Spaces overview](../spaces.md) for context. -Space records are stored separately from public AT Protocol records. They follow the same URI pattern but use the `ats://` scheme and include the space identity: +Space records are stored separately from public AT Protocol records. They use the `at://` scheme with a `space` path segment to distinguish them from public records: ``` -ats:// did:plc:abcdefghijklmnop1234567890 / com.example.forum / main / did:plc:author / com.example.forum.post / abcdefghijklmnop1234567890 - └── space DID ───────────────────┘ └── space type ─┘ └── skey ─┘ └── author ──┘ └── collection ──────┘ └── rkey ────────────────┘ +at:// did:plc:abcdefghijklmnop1234567890 / space / com.example.forum / main / did:plc:author / com.example.forum.post / abcdefghijklmnop1234567890 + └── space DID ───────────────────┘ └── space type ─┘ └── skey ─┘ └── author ──┘ └── collection ──────┘ └── rkey ────────────────┘ ``` ## Creating a record @@ -27,7 +27,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.spa "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", collection: "com.example.forum.post", record: { $type: "com.example.forum.post", @@ -52,7 +52,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.spa "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", collection: "com.example.forum.post", record: { $type: "com.example.forum.post", @@ -70,7 +70,7 @@ let response = client .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "collection": "com.example.forum.post", "record": { "$type": "com.example.forum.post", @@ -84,7 +84,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" body := bytes.NewBufferString(`{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "collection": "com.example.forum.post", "record": { "$type": "com.example.forum.post", @@ -107,7 +107,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.space.createRecord' -H 'DPoP: ' \ -H 'Content-Type: application/json' \ -d '{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "collection": "com.example.forum.post", "record": { "$type": "com.example.forum.post", @@ -129,7 +129,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.space.createRecord' ```json { - "uri": "ats://did:plc:abc123/com.example.forum/main/did:plc:author/com.example.forum.post/3l2tkbx7225co", + "uri": "at://did:plc:abc123/space/com.example.forum/main/did:plc:author/com.example.forum.post/3l2tkbx7225co", "cid": "bafyrei..." } ``` @@ -150,7 +150,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.spa "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", collection: "com.example.forum.post", rkey: "3k2abc", record: { @@ -176,7 +176,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.spa "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", collection: "com.example.forum.post", rkey: "3k2abc", record: { @@ -195,7 +195,7 @@ let response = client .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "collection": "com.example.forum.post", "rkey": "3k2abc", "record": { @@ -210,7 +210,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" body := bytes.NewBufferString(`{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "collection": "com.example.forum.post", "rkey": "3k2abc", "record": { @@ -234,7 +234,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.space.putRecord' \ -H 'DPoP: ' \ -H 'Content-Type: application/json' \ -d '{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "collection": "com.example.forum.post", "rkey": "3k2abc", "record": { @@ -259,7 +259,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.space.putRecord' \ ```json { - "uri": "ats://did:plc:abc123/com.example.forum/main/did:plc:author/com.example.forum.post/3k2abc", + "uri": "at://did:plc:abc123/space/com.example.forum/main/did:plc:author/com.example.forum.post/3k2abc", "cid": "bafyrei..." } ``` @@ -276,7 +276,7 @@ Members with `read_self` access can only retrieve their own records. Attempting ```ts tab="TypeScript" tab-group="language" const params = new URLSearchParams({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", collection: "com.example.forum.post", rkey: "3k2abc", }); @@ -299,7 +299,7 @@ const data: GetRecordResponse = await response.json(); ``` ```js tab="JavaScript" tab-group="language" const params = new URLSearchParams({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", collection: "com.example.forum.post", rkey: "3k2abc", }); @@ -319,7 +319,7 @@ const data = await response.json(); let response = client .get("https://happyview.example.com/xrpc/com.atproto.space.getRecord") .query(&[ - ("space", "ats://did:plc:abc123/com.example.forum/main"), + ("space", "at://did:plc:abc123/space/com.example.forum/main"), ("collection", "com.example.forum.post"), ("rkey", "3k2abc"), ]) @@ -332,7 +332,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" req, _ := http.NewRequest("GET", - "https://happyview.example.com/xrpc/com.atproto.space.getRecord?space=ats://did:plc:abc123/com.example.forum/main&collection=com.example.forum.post&rkey=3k2abc", + "https://happyview.example.com/xrpc/com.atproto.space.getRecord?space=at://did:plc:abc123/space/com.example.forum/main&collection=com.example.forum.post&rkey=3k2abc", nil) req.Header.Set("X-Client-Key", clientKey) req.Header.Set("Authorization", "DPoP "+accessToken) @@ -340,7 +340,7 @@ req.Header.Set("DPoP", dpopProof) resp, err := http.DefaultClient.Do(req) ``` ```sh tab="cURL" tab-group="language" -curl 'https://happyview.example.com/xrpc/com.atproto.space.getRecord?space=ats://did:plc:abc123/com.example.forum/main&collection=com.example.forum.post&rkey=3k2abc' \ +curl 'https://happyview.example.com/xrpc/com.atproto.space.getRecord?space=at://did:plc:abc123/space/com.example.forum/main&collection=com.example.forum.post&rkey=3k2abc' \ -H 'X-Client-Key: hvc_...' \ -H 'Authorization: DPoP ' \ -H 'DPoP: ' @@ -358,7 +358,7 @@ curl 'https://happyview.example.com/xrpc/com.atproto.space.getRecord?space=ats:/ ```json { - "uri": "ats://did:plc:abc123/com.example.forum/main/did:plc:author/com.example.forum.post/3k2abc", + "uri": "at://did:plc:abc123/space/com.example.forum/main/did:plc:author/com.example.forum.post/3k2abc", "cid": "bafyrei...", "value": { "$type": "com.example.forum.post", @@ -372,7 +372,7 @@ curl 'https://happyview.example.com/xrpc/com.atproto.space.getRecord?space=ats:/ ```ts tab="TypeScript" tab-group="language" const params = new URLSearchParams({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", collection: "com.example.forum.post", limit: "20", }); @@ -399,7 +399,7 @@ const data: ListRecordsResponse = await response.json(); ``` ```js tab="JavaScript" tab-group="language" const params = new URLSearchParams({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", collection: "com.example.forum.post", limit: "20", }); @@ -419,7 +419,7 @@ const data = await response.json(); let response = client .get("https://happyview.example.com/xrpc/com.atproto.space.listRecords") .query(&[ - ("space", "ats://did:plc:abc123/com.example.forum/main"), + ("space", "at://did:plc:abc123/space/com.example.forum/main"), ("collection", "com.example.forum.post"), ("limit", "20"), ]) @@ -432,7 +432,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" req, _ := http.NewRequest("GET", - "https://happyview.example.com/xrpc/com.atproto.space.listRecords?space=ats://did:plc:abc123/com.example.forum/main&collection=com.example.forum.post&limit=20", + "https://happyview.example.com/xrpc/com.atproto.space.listRecords?space=at://did:plc:abc123/space/com.example.forum/main&collection=com.example.forum.post&limit=20", nil) req.Header.Set("X-Client-Key", clientKey) req.Header.Set("Authorization", "DPoP "+accessToken) @@ -440,7 +440,7 @@ req.Header.Set("DPoP", dpopProof) resp, err := http.DefaultClient.Do(req) ``` ```sh tab="cURL" tab-group="language" -curl 'https://happyview.example.com/xrpc/com.atproto.space.listRecords?space=ats://did:plc:abc123/com.example.forum/main&collection=com.example.forum.post&limit=20' \ +curl 'https://happyview.example.com/xrpc/com.atproto.space.listRecords?space=at://did:plc:abc123/space/com.example.forum/main&collection=com.example.forum.post&limit=20' \ -H 'X-Client-Key: hvc_...' \ -H 'Authorization: DPoP ' \ -H 'DPoP: ' @@ -486,7 +486,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.spa "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", collection: "com.example.forum.post", rkey: "3k2abc", }), @@ -502,7 +502,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.spa "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", collection: "com.example.forum.post", rkey: "3k2abc", }), @@ -515,7 +515,7 @@ let response = client .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "collection": "com.example.forum.post", "rkey": "3k2abc" })) @@ -524,7 +524,7 @@ let response = client ``` ```go tab="Go" tab-group="language" body := bytes.NewBufferString(`{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "collection": "com.example.forum.post", "rkey": "3k2abc" }`) @@ -543,7 +543,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.space.deleteRecord' -H 'DPoP: ' \ -H 'Content-Type: application/json' \ -d '{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "collection": "com.example.forum.post", "rkey": "3k2abc" }' @@ -574,7 +574,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.spa "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", writes: [ { action: "create", @@ -612,7 +612,7 @@ const response = await fetch("https://happyview.example.com/xrpc/com.atproto.spa "Content-Type": "application/json", }, body: JSON.stringify({ - space: "ats://did:plc:abc123/com.example.forum/main", + space: "at://did:plc:abc123/space/com.example.forum/main", writes: [ { action: "create", @@ -643,7 +643,7 @@ let response = client .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) .json(&serde_json::json!({ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "writes": [ { "action": "create", @@ -670,7 +670,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" body := bytes.NewBufferString(`{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "writes": [ { "action": "create", @@ -706,7 +706,7 @@ curl -X POST 'https://happyview.example.com/xrpc/com.atproto.space.applyWrites' -H 'DPoP: ' \ -H 'Content-Type: application/json' \ -d '{ - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "writes": [ { "action": "create", @@ -750,8 +750,8 @@ Each write operation has an `action` field: ```json { "results": [ - { "uri": "ats://...", "cid": "bafyrei..." }, - { "uri": "ats://...", "cid": "bafyrei..." }, + { "uri": "at://...", "cid": "bafyrei..." }, + { "uri": "at://...", "cid": "bafyrei..." }, {} ] } @@ -769,7 +769,7 @@ Pass the `swapRecord` field on `putRecord`, `deleteRecord`, or individual operat ```json { - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "collection": "com.example.forum.post", "rkey": "3k2abc", "record": { "text": "updated safely" }, @@ -785,19 +785,19 @@ The space's current revision is available as `revision` in the space object retu ```json { - "space": "ats://did:plc:abc123/com.example.forum/main", + "space": "at://did:plc:abc123/space/com.example.forum/main", "swapCommit": "3l2tkbx7225co", "writes": [...] } ``` -## Repo state +## Latest commit -Returns the per-user repo state for a space, including the current revision and deniable commit data. +Returns the per-user signed commit for a space, including the current revision and deniable commit data. ```ts tab="TypeScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/com.atproto.space.getRepoState?space=ats://did:plc:abc123/com.example.forum/main&did=did:plc:author", + "https://happyview.example.com/xrpc/com.atproto.space.getLatestCommit?space=at://did:plc:abc123/space/com.example.forum/main&did=did:plc:author", { headers: { "X-Client-Key": CLIENT_KEY, @@ -806,9 +806,10 @@ const response = await fetch( }, }, ); -interface RepoStateResponse { +interface LatestCommitResponse { rev: string | null; commit: { + ver: number; hash: string; ikm: string; sig: string; @@ -816,11 +817,11 @@ interface RepoStateResponse { rev: string; } | null; } -const data: RepoStateResponse = await response.json(); +const data: LatestCommitResponse = await response.json(); ``` ```js tab="JavaScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/com.atproto.space.getRepoState?space=ats://did:plc:abc123/com.example.forum/main&did=did:plc:author", + "https://happyview.example.com/xrpc/com.atproto.space.getLatestCommit?space=at://did:plc:abc123/space/com.example.forum/main&did=did:plc:author", { headers: { "X-Client-Key": CLIENT_KEY, @@ -833,9 +834,9 @@ const data = await response.json(); ``` ```rust tab="Rust" tab-group="language" let response = client - .get("https://happyview.example.com/xrpc/com.atproto.space.getRepoState") + .get("https://happyview.example.com/xrpc/com.atproto.space.getLatestCommit") .query(&[ - ("space", "ats://did:plc:abc123/com.example.forum/main"), + ("space", "at://did:plc:abc123/space/com.example.forum/main"), ("did", "did:plc:author"), ]) .header("X-Client-Key", client_key) @@ -847,7 +848,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" req, _ := http.NewRequest("GET", - "https://happyview.example.com/xrpc/com.atproto.space.getRepoState?space=ats://did:plc:abc123/com.example.forum/main&did=did:plc:author", + "https://happyview.example.com/xrpc/com.atproto.space.getLatestCommit?space=at://did:plc:abc123/space/com.example.forum/main&did=did:plc:author", nil) req.Header.Set("X-Client-Key", clientKey) req.Header.Set("Authorization", "DPoP "+accessToken) @@ -855,7 +856,7 @@ req.Header.Set("DPoP", dpopProof) resp, err := http.DefaultClient.Do(req) ``` ```sh tab="cURL" tab-group="language" -curl 'https://happyview.example.com/xrpc/com.atproto.space.getRepoState?space=ats://did:plc:abc123/com.example.forum/main&did=did:plc:author' \ +curl 'https://happyview.example.com/xrpc/com.atproto.space.getLatestCommit?space=at://did:plc:abc123/space/com.example.forum/main&did=did:plc:author' \ -H 'X-Client-Key: hvc_...' \ -H 'Authorization: DPoP ' \ -H 'DPoP: ' @@ -873,7 +874,7 @@ curl 'https://happyview.example.com/xrpc/com.atproto.space.getRepoState?space=at | Field | Type | Description | | -------- | ------------ | -------------------------------------------------------------- | | `rev` | string/null | Current revision for this user's repo in the space | -| `commit` | object/null | Deniable commit data (base64url-encoded `hash`, `ikm`, `sig`, `mac`, and `rev`) | +| `commit` | object/null | Deniable commit data (`ver`, base64url-encoded `hash`, `ikm`, `sig`, `mac`, and `rev`) | ## Record operation log @@ -881,7 +882,7 @@ Returns the operation log for a user in a space. Each write (create, update, del ```ts tab="TypeScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/com.atproto.space.listRepoOps?space=ats://did:plc:abc123/com.example.forum/main&did=did:plc:author", + "https://happyview.example.com/xrpc/com.atproto.space.listRepoOps?space=at://did:plc:abc123/space/com.example.forum/main&did=did:plc:author", { headers: { "X-Client-Key": CLIENT_KEY, @@ -895,7 +896,7 @@ const data = await response.json(); ``` ```js tab="JavaScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/com.atproto.space.listRepoOps?space=ats://did:plc:abc123/com.example.forum/main&did=did:plc:author", + "https://happyview.example.com/xrpc/com.atproto.space.listRepoOps?space=at://did:plc:abc123/space/com.example.forum/main&did=did:plc:author", { headers: { "X-Client-Key": CLIENT_KEY, @@ -910,7 +911,7 @@ const data = await response.json(); let response = client .get("https://happyview.example.com/xrpc/com.atproto.space.listRepoOps") .query(&[ - ("space", "ats://did:plc:abc123/com.example.forum/main"), + ("space", "at://did:plc:abc123/space/com.example.forum/main"), ("did", "did:plc:author"), ]) .header("X-Client-Key", client_key) @@ -922,7 +923,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" req, _ := http.NewRequest("GET", - "https://happyview.example.com/xrpc/com.atproto.space.listRepoOps?space=ats://did:plc:abc123/com.example.forum/main&did=did:plc:author", + "https://happyview.example.com/xrpc/com.atproto.space.listRepoOps?space=at://did:plc:abc123/space/com.example.forum/main&did=did:plc:author", nil) req.Header.Set("X-Client-Key", clientKey) req.Header.Set("Authorization", "DPoP "+accessToken) @@ -930,7 +931,7 @@ req.Header.Set("DPoP", dpopProof) resp, err := http.DefaultClient.Do(req) ``` ```sh tab="cURL" tab-group="language" -curl 'https://happyview.example.com/xrpc/com.atproto.space.listRepoOps?space=ats://did:plc:abc123/com.example.forum/main&did=did:plc:author' \ +curl 'https://happyview.example.com/xrpc/com.atproto.space.listRepoOps?space=at://did:plc:abc123/space/com.example.forum/main&did=did:plc:author' \ -H 'X-Client-Key: hvc_...' \ -H 'Authorization: DPoP ' \ -H 'DPoP: ' @@ -942,8 +943,9 @@ curl 'https://happyview.example.com/xrpc/com.atproto.space.listRepoOps?space=ats | -------- | ------- | -------- | ---------------------------------------------- | | `space` | string | Yes | The space URI | | `did` | string | Yes | The DID of the user whose ops to list | -| `limit` | integer | No | Max number of entries to return (default 100, max 1000) | -| `cursor` | string | No | Revision to start after (for pagination) | +| `limit` | integer | No | Max number of entries to return (default 100, max 1000) | +| `cursor` | string | No | Revision to start after (for pagination) | +| `excludeValues` | boolean | No | If `true`, omit record values from response (default `false`) | **Response:** @@ -959,13 +961,84 @@ curl 'https://happyview.example.com/xrpc/com.atproto.space.listRepoOps?space=ats "rkey": "3k2abc", "cid": "bafyrei...", "prev": null, + "value": { "text": "hello world" }, "createdAt": "2026-05-09T12:00:00Z" } ] } ``` -Each entry records a single write operation. The `action` is one of `create`, `update`, or `delete`. The `prev` field contains the CID of the record before the operation (for updates and deletes). +Each entry records a single write operation. The `action` is one of `create`, `update`, or `delete`. The `prev` field contains the CID of the record before the operation (for updates and deletes). The `value` field contains the record's current value (omitted for deletes or when `excludeValues=true`). + +## Repo export + +Exports a user's full repo within a space as a CAR v1 file. The file contains two roots: the signed commit and a DRISL index (flat DAG-CBOR map of `collection/rkey` to CID). Record blocks follow in lexicographic order. + +```ts tab="TypeScript" tab-group="language" +const response = await fetch( + "https://happyview.example.com/xrpc/com.atproto.space.getRepo?space=at://did:plc:abc123/space/com.example.forum/main&did=did:plc:author", + { + headers: { + "X-Client-Key": CLIENT_KEY, + "Authorization": `DPoP ${ACCESS_TOKEN}`, + "DPoP": DPOP_PROOF, + }, + }, +); +const car = await response.arrayBuffer(); +``` +```js tab="JavaScript" tab-group="language" +const response = await fetch( + "https://happyview.example.com/xrpc/com.atproto.space.getRepo?space=at://did:plc:abc123/space/com.example.forum/main&did=did:plc:author", + { + headers: { + "X-Client-Key": CLIENT_KEY, + "Authorization": `DPoP ${ACCESS_TOKEN}`, + "DPoP": DPOP_PROOF, + }, + }, +); +const car = await response.arrayBuffer(); +``` +```rust tab="Rust" tab-group="language" +let response = client + .get("https://happyview.example.com/xrpc/com.atproto.space.getRepo") + .query(&[ + ("space", "at://did:plc:abc123/space/com.example.forum/main"), + ("did", "did:plc:author"), + ]) + .header("X-Client-Key", client_key) + .header("Authorization", format!("DPoP {}", access_token)) + .header("DPoP", &dpop_proof) + .send() + .await?; +let bytes = response.bytes().await?; +``` +```go tab="Go" tab-group="language" +req, _ := http.NewRequest("GET", + "https://happyview.example.com/xrpc/com.atproto.space.getRepo?space=at://did:plc:abc123/space/com.example.forum/main&did=did:plc:author", + nil) +req.Header.Set("X-Client-Key", clientKey) +req.Header.Set("Authorization", "DPoP "+accessToken) +req.Header.Set("DPoP", dpopProof) +resp, err := http.DefaultClient.Do(req) +``` +```sh tab="cURL" tab-group="language" +curl 'https://happyview.example.com/xrpc/com.atproto.space.getRepo?space=at://did:plc:abc123/space/com.example.forum/main&did=did:plc:author' \ + -H 'X-Client-Key: hvc_...' \ + -H 'Authorization: DPoP ' \ + -H 'DPoP: ' \ + --output repo.car +``` + +**Parameters:** + +| Field | Type | Required | Description | +| ------- | ------ | -------- | ------------------------------------ | +| `space` | string | Yes | The space URI | +| `did` | string | Yes | The DID of the user whose repo to export | + +The response body is a CAR v1 file with content type `application/vnd.ipld.car`. ## Listing repos @@ -973,7 +1046,7 @@ Returns the list of users who have records in a space, along with their current ```ts tab="TypeScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/com.atproto.space.listRepos?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/com.atproto.space.listRepos?space=at://did:plc:abc123/space/com.example.forum/main", { headers: { "X-Client-Key": CLIENT_KEY, @@ -990,7 +1063,7 @@ const data: { repos: Repo[] } = await response.json(); ``` ```js tab="JavaScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/com.atproto.space.listRepos?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/com.atproto.space.listRepos?space=at://did:plc:abc123/space/com.example.forum/main", { headers: { "X-Client-Key": CLIENT_KEY, @@ -1004,7 +1077,7 @@ const data = await response.json(); ```rust tab="Rust" tab-group="language" let response = client .get("https://happyview.example.com/xrpc/com.atproto.space.listRepos") - .query(&[("space", "ats://did:plc:abc123/com.example.forum/main")]) + .query(&[("space", "at://did:plc:abc123/space/com.example.forum/main")]) .header("X-Client-Key", client_key) .header("Authorization", format!("DPoP {}", access_token)) .header("DPoP", &dpop_proof) @@ -1014,7 +1087,7 @@ let data: serde_json::Value = response.json().await?; ``` ```go tab="Go" tab-group="language" req, _ := http.NewRequest("GET", - "https://happyview.example.com/xrpc/com.atproto.space.listRepos?space=ats://did:plc:abc123/com.example.forum/main", + "https://happyview.example.com/xrpc/com.atproto.space.listRepos?space=at://did:plc:abc123/space/com.example.forum/main", nil) req.Header.Set("X-Client-Key", clientKey) req.Header.Set("Authorization", "DPoP "+accessToken) @@ -1022,7 +1095,7 @@ req.Header.Set("DPoP", dpopProof) resp, err := http.DefaultClient.Do(req) ``` ```sh tab="cURL" tab-group="language" -curl 'https://happyview.example.com/xrpc/com.atproto.space.listRepos?space=ats://did:plc:abc123/com.example.forum/main' \ +curl 'https://happyview.example.com/xrpc/com.atproto.space.listRepos?space=at://did:plc:abc123/space/com.example.forum/main' \ -H 'X-Client-Key: hvc_...' \ -H 'Authorization: DPoP ' \ -H 'DPoP: ' @@ -1051,7 +1124,7 @@ Retrieves a blob from a space. The blob is fetched from the author's PDS and pro ```ts tab="TypeScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/com.atproto.space.getBlob?space=ats://did:plc:abc123/com.example.forum/main&cid=bafyrei...", + "https://happyview.example.com/xrpc/com.atproto.space.getBlob?space=at://did:plc:abc123/space/com.example.forum/main&cid=bafyrei...", { headers: { "X-Client-Key": CLIENT_KEY, @@ -1064,7 +1137,7 @@ const blob = await response.blob(); ``` ```js tab="JavaScript" tab-group="language" const response = await fetch( - "https://happyview.example.com/xrpc/com.atproto.space.getBlob?space=ats://did:plc:abc123/com.example.forum/main&cid=bafyrei...", + "https://happyview.example.com/xrpc/com.atproto.space.getBlob?space=at://did:plc:abc123/space/com.example.forum/main&cid=bafyrei...", { headers: { "X-Client-Key": CLIENT_KEY, @@ -1079,7 +1152,7 @@ const blob = await response.blob(); let response = client .get("https://happyview.example.com/xrpc/com.atproto.space.getBlob") .query(&[ - ("space", "ats://did:plc:abc123/com.example.forum/main"), + ("space", "at://did:plc:abc123/space/com.example.forum/main"), ("cid", "bafyrei..."), ]) .header("X-Client-Key", client_key) @@ -1091,7 +1164,7 @@ let bytes = response.bytes().await?; ``` ```go tab="Go" tab-group="language" req, _ := http.NewRequest("GET", - "https://happyview.example.com/xrpc/com.atproto.space.getBlob?space=ats://did:plc:abc123/com.example.forum/main&cid=bafyrei...", + "https://happyview.example.com/xrpc/com.atproto.space.getBlob?space=at://did:plc:abc123/space/com.example.forum/main&cid=bafyrei...", nil) req.Header.Set("X-Client-Key", clientKey) req.Header.Set("Authorization", "DPoP "+accessToken) @@ -1099,7 +1172,7 @@ req.Header.Set("DPoP", dpopProof) resp, err := http.DefaultClient.Do(req) ``` ```sh tab="cURL" tab-group="language" -curl 'https://happyview.example.com/xrpc/com.atproto.space.getBlob?space=ats://did:plc:abc123/com.example.forum/main&cid=bafyrei...' \ +curl 'https://happyview.example.com/xrpc/com.atproto.space.getBlob?space=at://did:plc:abc123/space/com.example.forum/main&cid=bafyrei...' \ -H 'X-Client-Key: hvc_...' \ -H 'Authorization: DPoP ' \ -H 'DPoP: ' \ diff --git a/packages/docs/content/docs/guides/lua-scripting.md b/packages/docs/content/docs/guides/lua-scripting.md index 58cb68c..8f67d6f 100644 --- a/packages/docs/content/docs/guides/lua-scripting.md +++ b/packages/docs/content/docs/guides/lua-scripting.md @@ -71,7 +71,7 @@ When a script handles a space-scoped request, the `space` global is set to a tab | Field | Type | Description | | --------------- | ------ | --------------------------- | -| `space` | string | The full `ats://` space URI | +| `space` | string | The full `at://` space URI | | `space_id` | string | Internal space identifier | | `did` | string | The space's DID | | `authority_did` | string | The space authority's DID | diff --git a/packages/docs/content/docs/reference/architecture.md b/packages/docs/content/docs/reference/architecture.md index fc6bf1a..7b1be7c 100644 --- a/packages/docs/content/docs/reference/architecture.md +++ b/packages/docs/content/docs/reference/architecture.md @@ -325,7 +325,7 @@ sequenceDiagram | Column | Type | Description | | -------------- | ----------- | ------------------------------------------------ | -| `uri` | text (PK) | `ats://` URI of the record | +| `uri` | text (PK) | `at://` URI of the record | | `space_id` | text (FK) | References `spaces.id` | | `author_did` | text | DID of the record author | | `collection` | text | Lexicon NSID | diff --git a/packages/docs/content/docs/reference/glossary.md b/packages/docs/content/docs/reference/glossary.md index a25adab..d1dbb0c 100644 --- a/packages/docs/content/docs/reference/glossary.md +++ b/packages/docs/content/docs/reference/glossary.md @@ -56,7 +56,7 @@ Key terms used throughout the HappyView documentation. For a broader introductio **Permission template** — A predefined set of permissions that can be applied when creating a user. Templates are: **Viewer** (read-only access), **Operator** (viewer + backfill and API key management), **Manager** (operator + lexicon, record, spaces, and plugin management), and **Full Access** (all 44 permissions). -**Space** — A container for permissioned data in AT Protocol. Identified by a space DID, type NSID, and space key (skey), forming an `ats://` URI. +**Space** — A container for permissioned data in AT Protocol. Identified by a space DID, type NSID, and space key (skey), forming an `at://` URI with a `space` path segment (e.g. `at://did:plc:abc/space/com.example.forum/main`). **Space Credential** — A short-lived JWT (`typ: atproto-space-credential+jwt`, ES256, 2-hour TTL) for cross-service read access to space data. Signed by the space's P-256 keypair. Obtained by exchanging a delegation token via `com.atproto.space.getSpaceCredential`.