Something went wrong. Try again.
A did method that uses at uri's to resolve a did document in a pds
Something went wrong. Try again.
did-method-at resolver.test.ts
5.8 kB · 166 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167/** * End-to-end resolution test for a space-record did:at in which BOTH nested * DID positions are themselves did:at identifiers backed by plain did:plc * repos: * * - the space authority (sdid) is a did:at whose document lives in * did:plc:spacehost123's repo, and * - the member DID is a did:at whose document lives in * did:plc:memberrepo456's repo. * * All network access is mocked. Run with: * npx tsx --test resolver.test.ts */import { test, beforeEach, after } from 'node:test'import assert from 'node:assert/strict'import { parseDidAt, resolveDidAt, ResolutionError } from './resolver.ts'
// ------------------------------------------------------------- the world
const SPACE_HOST_PLC = 'did:plc:spacehost123'const MEMBER_PLC = 'did:plc:memberrepo456'const SPACE_PDS = 'https://pds.space.test'const MEMBER_PDS = 'https://pds.member.test'
// The space's DID: a record in the space host's plc repo.const SDID = `did:at:${SPACE_HOST_PLC}..at.did.document..space-doc`// The member's ("main") DID: a record in the member's plc repo.const MEMBER = `did:at:${MEMBER_PLC}..at.did.document..member-doc`// The DID under test: a record authored by MEMBER in a space hosted by SDID.const DID = `did:at:${SDID}..space..com.example.room..3jroom..${MEMBER}..at.did.document..self`
const plcDoc = (did: string, pds: string) => ({ id: did, service: [ { id: '#atproto_pds', type: 'AtprotoPersonalDataServer', serviceEndpoint: pds }, ],})
// A did:at document that delegates to a plc repo (spec §4.1).const didAtDoc = (id: string, repoPlc: string, pds: string) => ({ '@context': ['https://www.w3.org/ns/did/v1'], id, alsoKnownAs: [`at://${repoPlc}`], service: [ { id: '#atproto_pds', type: 'AtprotoPersonalDataServer', serviceEndpoint: pds }, ],})
const outerDoc = { '@context': ['https://www.w3.org/ns/did/v1'], id: DID, verificationMethod: [ { id: `${DID}#key-1`, type: 'Multikey', controller: DID, publicKeyMultibase: 'zQ3sh...' }, ],}
// ------------------------------------------------------------ mock fetch
let calls: URL[] = []
function route(u: URL): unknown | undefined { const q = (name: string) => u.searchParams.get(name) const at = u.origin + u.pathname
if (at === `https://plc.directory/${SPACE_HOST_PLC}`) { return plcDoc(SPACE_HOST_PLC, SPACE_PDS) } if (at === `https://plc.directory/${MEMBER_PLC}`) { return plcDoc(MEMBER_PLC, MEMBER_PDS) } if ( at === `${SPACE_PDS}/xrpc/com.atproto.repo.getRecord` && q('repo') === SPACE_HOST_PLC && q('collection') === 'at.did.document' && q('rkey') === 'space-doc' ) { return { value: { didDocument: didAtDoc(SDID, SPACE_HOST_PLC, SPACE_PDS) } } } if ( at === `${MEMBER_PDS}/xrpc/com.atproto.repo.getRecord` && q('repo') === MEMBER_PLC && q('collection') === 'at.did.document' && q('rkey') === 'member-doc' ) { return { value: { didDocument: didAtDoc(MEMBER, MEMBER_PLC, MEMBER_PDS) } } } if ( at === `${SPACE_PDS}/xrpc/com.atproto.space.getRecord` && q('space') === `at://${SPACE_HOST_PLC}/space/com.example.room/3jroom` && q('repo') === MEMBER_PLC && q('collection') === 'at.did.document' && q('rkey') === 'self' ) { return { value: { didDocument: outerDoc } } } return undefined}
const realFetch = globalThis.fetchglobalThis.fetch = (async (input: any) => { const u = new URL(String(input)) calls.push(u) const body = route(u) if (body === undefined) return new Response('not found', { status: 404 }) return new Response(JSON.stringify(body), { status: 200, headers: { 'content-type': 'application/json' }, })}) as typeof fetch
beforeEach(() => (calls = []))after(() => (globalThis.fetch = realFetch))
// ------------------------------------------------------------------ tests
test('parses the space DID with did:at in both DID positions', () => { assert.deepEqual(parseDidAt(DID), { authority: SDID, path: { kind: 'space', stype: 'com.example.room', skey: '3jroom', memberDid: MEMBER, rtype: 'at.did.document', rkey: 'self', }, })})
test('resolves through both nested did:ats to the space record', async () => { const result = await resolveDidAt(DID)
assert.equal(result.didDocument.id, DID) assert.deepEqual(result.didDocumentMetadata, { deactivated: false }) // Three did:at resolutions (outer + space authority + member) from the // default budget of 8. assert.equal(result.didResolutionMetadata.recursionRemaining, 5)
// The space fetch went to the space host's PDS with both did:ats collapsed // to their underlying plc repos. const spaceCall = calls.find((u) => u.pathname === '/xrpc/com.atproto.space.getRecord') assert.ok(spaceCall, 'expected a com.atproto.space.getRecord call') assert.equal(spaceCall.origin, SPACE_PDS) assert.equal( spaceCall.searchParams.get('space'), `at://${SPACE_HOST_PLC}/space/com.example.room/3jroom`, ) assert.equal(spaceCall.searchParams.get('repo'), MEMBER_PLC)
// Each nested document was fetched from its own repo's PDS. const repoCalls = calls .filter((u) => u.pathname === '/xrpc/com.atproto.repo.getRecord') .map((u) => `${u.origin} ${u.searchParams.get('rkey')}`) .sort() assert.deepEqual(repoCalls, [`${MEMBER_PDS} member-doc`, `${SPACE_PDS} space-doc`])})
test('recursion budget is shared: three did:at resolutions need budget 3', async () => { const ok = await resolveDidAt(DID, { maxRecursion: 3 }) assert.equal(ok.didResolutionMetadata.recursionRemaining, 0)
await assert.rejects(resolveDidAt(DID, { maxRecursion: 2 }), (err: ResolutionError) => { assert.equal(err.code, 'recursionLimitExceeded') return true })})