// Produces artifacts with the reference implementation for pds.js to verify. // Copied into the atproto worktree by scripts/space-reference/run.sh as a // scratch file; never committed there. import { mkdirSync, writeFileSync } from 'node:fs'; import { P256Keypair } from '@atproto/crypto'; import { cidForLex, encode } from '@atproto/lex-cbor'; import { parseCid } from '@atproto/lex-data'; import { it } from 'vitest'; import { COMMIT_MAC_TYPE, computeCommitMac, computeRecordMac, createSpaceSigHeaders, createSpaceToken, encapsulate, formatMacHeader, formatWantMacHeader, RECORD_MAC_TYPE, RepoCommit, serializeRepo, } from '../src/index.js'; const OUT = process.env.OUT_DIR ?? '/tmp/ref-space-artifacts'; const AUTHORITY = 'did:plc:refauthority'; const SPACE = `at://${AUTHORITY}/space/com.example.forum/general`; const AUTHOR = 'did:plc:refuser'; const BLOB = 'bafkreigh2akiscaildcqabsyg3dfr6chu3fgpregiymsck7e7aqa4s52zy'; it('generates reference artifacts', async () => { mkdirSync(OUT, { recursive: true }); const author = await P256Keypair.create({ exportable: true }); const authorKem = await P256Keypair.create({ exportable: true }); const authority = await P256Keypair.create({ exportable: true }); // In strict path order, which the archive requires. `com.e.p/x` sorts // before `com.example.post/aaa` byte for byte. const inputs = [ { collection: 'com.e.p', rkey: 'x', record: { $type: 'com.e.p', n: 42 } }, { collection: 'com.example.post', rkey: 'aaa', record: { $type: 'com.example.post', text: 'first' }, }, { collection: 'com.example.post', rkey: 'bbb', record: { $type: 'com.example.post', text: 'second' }, }, { collection: 'com.example.post', rkey: 'ccc', record: { $type: 'com.example.post', text: 'with a picture', image: { $type: 'blob', ref: parseCid(BLOB), mimeType: 'image/png', size: 1234, }, }, }, { collection: 'com.example.reply', rkey: 'zz', record: { $type: 'com.example.reply', deep: { nested: [1, 2, 3] } }, }, ]; const records = await Promise.all( inputs.map(async (i) => ({ collection: i.collection as any, rkey: i.rkey as any, cid: await cidForLex(i.record as any), bytes: encode(i.record as any), })), ); const rev = '3mrxrefrevaaa'; const commit = RepoCommit.fromRecords(records).toCommit({ space: SPACE, repo: AUTHOR as any, rev, }); // As the repo host would answer one syncer's getRepo: a MAC under the // secret of that syncer's key share. pds.js derives the secret itself from // the KEM key and the key share. const repoShare = await encapsulate(authorKem.did()); const commitMac = computeCommitMac(repoShare.sharedSecret, commit); const chunks: Uint8Array[] = []; for await (const chunk of serializeRepo(commit, records)) chunks.push(chunk); writeFileSync(`${OUT}/repo.star`, Buffer.concat(chunks)); const recordShare = await encapsulate(authorKem.did()); const recordUri = `${SPACE}/${AUTHOR}/com.example.post/ccc`; const recordMac = computeRecordMac( recordShare.sharedSecret, recordUri, records[3].cid, ); const delegationToken = await createSpaceToken( 'delegation', { iss: AUTHOR, sub: SPACE, aud: `${AUTHORITY}#atproto_pds` }, author, ); // The key a holder signs with, which the credential names in `cnf.kid`. const holder = await P256Keypair.create(); const credential = await createSpaceToken( 'credential', { iss: AUTHORITY, sub: SPACE, keyId: holder.did() as any }, authority, ); const useSignature = await createSpaceSigHeaders(holder, { authorization: `Atproto-Space-Credential ${credential}`, audience: AUTHOR as any, }); const b64 = (b: Uint8Array) => Buffer.from(b).toString('base64'); const hex = (b: Uint8Array) => Buffer.from(b).toString('hex'); writeFileSync( `${OUT}/manifest.json`, `${JSON.stringify( { producer: '@atproto/space', space: SPACE, author: AUTHOR, authority: AUTHORITY, userDidKey: author.did(), authorityDidKey: authority.did(), kemPrivateKeyHex: hex(await authorKem.export()), kemDidKey: authorKem.did(), rev, recordCount: records.length, commit: { ver: commit.ver, repo: commit.repo, space: commit.space, rev: commit.rev, data: { $bytes: b64(commit.data) }, }, getRepo: { wantMac: formatWantMacHeader(COMMIT_MAC_TYPE, repoShare.keyShare), keyShare: repoShare.keyShare, mac: formatMacHeader(COMMIT_MAC_TYPE, commitMac), }, getRecord: { wantMac: formatWantMacHeader(RECORD_MAC_TYPE, recordShare.keyShare), keyShare: recordShare.keyShare, record: { uri: recordUri, cid: records[3].cid.toString(), value: { ...inputs[3].record, image: { ...inputs[3].record.image, ref: { $link: BLOB } }, }, }, mac: formatMacHeader(RECORD_MAC_TYPE, recordMac), }, delegationToken, delegationAud: `${AUTHORITY}#atproto_pds`, credential, credentialKeyId: holder.did(), useSignature, expectedPaths: records.map((r) => `${r.collection}/${r.rkey}`), }, null, 2, )}\n`, ); console.log(`wrote ${OUT}/repo.star and manifest.json`); });