From f55c8ffeabbebe28ee03a0b8323ddc10c9df966e Mon Sep 17 00:00:00 2001 From: Roscoe Rubin-Rottenberg Date: Thu, 23 Oct 2025 00:02:44 -0400 Subject: [PATCH] identity documentation --- AGENTS.md | 20 +++++++++---- README.md | 53 ++++++++++++++++++++++++++--------- identity/did/atproto-data.ts | 5 ++++ identity/did/base-resolver.ts | 4 +++ identity/did/did-resolver.ts | 4 +++ identity/did/memory-cache.ts | 5 ++++ identity/did/plc-resolver.ts | 5 ++++ identity/did/util.ts | 1 + identity/did/web-resolver.ts | 5 ++++ identity/id-resolver.ts | 3 +- identity/types.ts | 4 +++ 11 files changed, 89 insertions(+), 20 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 3e09ec4..2866982 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,7 @@ # Agent Guidelines for ATP Monorepo ## Build & Test Commands + - Run all tests: `deno test -P` - Run single test file: `deno test -P path/to/file_test.ts` - Run specific test: `deno test -P --filter "test name" path/to/file_test.ts` @@ -9,13 +10,20 @@ - Check code: `deno check` ## Code Style + - **NO COMMENTS** unless explicitly requested -- Use JSDoc only for exported types/functions with `@prop`, `@param`, `@returns` tags -- Test files: `*_test.ts` pattern (e.g., `car_test.ts`), use Deno.test(), imports from `@std/assert` -- Types: Explicit types for function parameters/returns, prefer `interface` over `type` for objects -- Error handling: Use custom error classes extending base errors, include `ErrorOptions` with `cause` -- Imports: Use JSR/npm imports from deno.json, absolute imports (e.g., `@atp/crypto`, `@std/assert`) -- Naming: camelCase for vars/functions, PascalCase for classes/types, UPPER_CASE for constants +- Use JSDoc only for exported types/functions with `@prop`, `@param`, `@returns` + tags +- Test files: `*_test.ts` pattern (e.g., `car_test.ts`), use Deno.test(), + imports from `@std/assert` +- Types: Explicit types for function parameters/returns, prefer `interface` over + `type` for objects +- Error handling: Use custom error classes extending base errors, include + `ErrorOptions` with `cause` +- Imports: Use JSR/npm imports from deno.json, absolute imports (e.g., + `@atp/crypto`, `@std/assert`) +- Naming: camelCase for vars/functions, PascalCase for classes/types, UPPER_CASE + for constants - Exports: Use `export` directly, re-export from `mod.ts` for public API - Async: Prefer async/await over promises, use AsyncGenerator for streams - Formatting: 2 spaces indent, semicolons, trailing commas, 80 char soft limit diff --git a/README.md b/README.md index ec16540..931a22c 100644 --- a/README.md +++ b/README.md @@ -6,45 +6,72 @@ A suite of TypeScript libraries for the AT Protocol, built on web standards. ## Overview -This monorepo provides modular, standards-based TypeScript implementations of core AT Protocol components, based on the @atproto NPM packages. +This monorepo provides modular, standards-based TypeScript implementations of +core AT Protocol components, based on the @atproto NPM packages. -Each package is designed to work across JavaScript runtimes (Deno, Node.js, Bun, Cloudflare Workers) and can be used independently or together. +Each package is designed to work across JavaScript runtimes (Deno, Node.js, Bun, +Cloudflare Workers) and can be used independently or together. ## Packages ### [@atp/xrpc-server](./xrpc-server) -Hono-based XRPC server implementation with lexicon validation, authentication, rate limiting, and WebSocket streaming support. Works across JavaScript runtimes with comprehensive error handling and type safety. + +Hono-based XRPC server implementation with lexicon validation, authentication, +rate limiting, and WebSocket streaming support. Works across JavaScript runtimes +with comprehensive error handling and type safety. ### [@atp/xrpc](./xrpc) -XRPC client library for calling AT Protocol services with lexicon schema validation. +XRPC client library for calling AT Protocol services with lexicon schema +validation. ### [@atp/sync](./sync) -Tools for syncing data from AT Protocol, including firehose (relay) subscriptions with authentication and filtering. + +Tools for syncing data from AT Protocol, including firehose (relay) +subscriptions with authentication and filtering. ### [@atp/lex-cli](./lex-cli) -Command-line tool for generating documentation, servers, and clients from AT Protocol lexicon files. + +Command-line tool for generating documentation, servers, and clients from AT +Protocol lexicon files. ### [@atp/crypto](./crypto) -Cryptographic primitives for AT Protocol supporting P-256 and K-256 (secp256k1) elliptic curves. Includes key generation, signing, verification, DID key serialization, and hashing utilities. + +Cryptographic primitives for AT Protocol supporting P-256 and K-256 (secp256k1) +elliptic curves. Includes key generation, signing, verification, DID key +serialization, and hashing utilities. ### [@atp/identity](./identity) -Decentralized identity resolution for DIDs and handles. Resolves handles to DIDs, DIDs to DID documents, and provides caching and verification methods. + +Decentralized identity resolution for DIDs and handles. Resolves handles to +DIDs, DIDs to DID documents, and provides caching and verification methods. ### [@atp/lexicon](./lexicon) -Validation utilities for AT Protocol lexicons. Validates records, XRPC parameters, inputs, and outputs against lexicon schemas. + +Validation utilities for AT Protocol lexicons. Validates records, XRPC +parameters, inputs, and outputs against lexicon schemas. ### [@atp/repo](./repo) -Repository utilities including the Merkle Search Tree (MST) implementation. Handles signed key/value stores with CBOR-encoded data records, CAR files, and repo synchronization. + +Repository utilities including the Merkle Search Tree (MST) implementation. +Handles signed key/value stores with CBOR-encoded data records, CAR files, and +repo synchronization. ### [@atp/syntax](./syntax) -Validation and parsing for AT Protocol string formats including DIDs, handles, NSIDs, AT URIs, TIDs, record keys, and datetimes. + +Validation and parsing for AT Protocol string formats including DIDs, handles, +NSIDs, AT URIs, TIDs, record keys, and datetimes. ### [@atp/common](./common) -Shared utilities for server-oriented applications, including IPLD handling, streams, async helpers, obfuscation, retry logic, and TID generation. + +Shared utilities for server-oriented applications, including IPLD handling, +streams, async helpers, obfuscation, retry logic, and TID generation. ### [@atp/bytes](./bytes) -Simple `Uint8Array` utilities including allocation, comparison, concatenation, string conversion (with multibase encoding support), and XOR operations. Based on the uint8arrays npm package. + +Simple `Uint8Array` utilities including allocation, comparison, concatenation, +string conversion (with multibase encoding support), and XOR operations. Based +on the uint8arrays npm package. ## Installation diff --git a/identity/did/atproto-data.ts b/identity/did/atproto-data.ts index bf02134..1d834b5 100644 --- a/identity/did/atproto-data.ts +++ b/identity/did/atproto-data.ts @@ -17,12 +17,14 @@ export { getPdsEndpoint as getPds, }; +/** Resolve a did to its `did:key` signing key, stringified */ export const getKey = (doc: DidDocument): string | undefined => { const key = getSigningKey(doc); if (!key) return undefined; return getDidKeyFromMultibase(key); }; +/** Extract and format a `did:key` signing key from multibase */ export const getDidKeyFromMultibase = (key: { type: string; publicKeyMultibase: string; @@ -40,6 +42,7 @@ export const getDidKeyFromMultibase = (key: { return didKey; }; +/** Parse an atproto document ("did doc") to its atproto data*/ export const parseToAtprotoDocument = ( doc: DidDocument, ): Partial => { @@ -52,6 +55,7 @@ export const parseToAtprotoDocument = ( }; }; +/** Authenticate and verify the existance of an atproto Did Document */ export const ensureAtpDocument = (doc: DidDocument): AtprotoData => { const { did, signingKey, handle, pds } = parseToAtprotoDocument(doc); if (!did) { @@ -69,6 +73,7 @@ export const ensureAtpDocument = (doc: DidDocument): AtprotoData => { return { did, signingKey, handle, pds }; }; +/** Parse a `did:key` signing key from a Did Document */ export const ensureAtprotoKey = (doc: DidDocument): string => { const { signingKey } = parseToAtprotoDocument(doc); if (!signingKey) { diff --git a/identity/did/base-resolver.ts b/identity/did/base-resolver.ts index 29e5363..43a5118 100644 --- a/identity/did/base-resolver.ts +++ b/identity/did/base-resolver.ts @@ -13,6 +13,10 @@ import { } from "../types.ts"; import * as atprotoData from "./atproto-data.ts"; +/** + * Core functionality of did and handle resolution and validation, + * including cache handling. + */ export abstract class BaseResolver { constructor(public cache?: DidCache) {} diff --git a/identity/did/did-resolver.ts b/identity/did/did-resolver.ts index 7c20eea..4e5b2a0 100644 --- a/identity/did/did-resolver.ts +++ b/identity/did/did-resolver.ts @@ -7,6 +7,10 @@ import { BaseResolver } from "./base-resolver.ts"; import { DidPlcResolver } from "./plc-resolver.ts"; import { DidWebResolver } from "./web-resolver.ts"; +/** + * Did Resolver class combining DidPlcResolver and DidWebResolver, + * resolves did:plc and did:web dids with optional caching. + */ export class DidResolver extends BaseResolver { methods: Record; diff --git a/identity/did/memory-cache.ts b/identity/did/memory-cache.ts index 634e8e7..b3954a9 100644 --- a/identity/did/memory-cache.ts +++ b/identity/did/memory-cache.ts @@ -1,6 +1,11 @@ import { DAY, HOUR } from "@atp/common"; import type { CacheResult, DidCache, DidDocument } from "../types.ts"; +/** + * Value stored in cache for a DID doc + * @prop doc - DID Document object + * @prop updatedAt - Last time DID doc cached was updated + */ type CacheVal = { doc: DidDocument; updatedAt: number; diff --git a/identity/did/plc-resolver.ts b/identity/did/plc-resolver.ts index f47b2f2..16f6a8c 100644 --- a/identity/did/plc-resolver.ts +++ b/identity/did/plc-resolver.ts @@ -2,6 +2,11 @@ import type { DidCache } from "../types.ts"; import { BaseResolver } from "./base-resolver.ts"; import { timed } from "./util.ts"; +/** + * Did resolver for resolving DIDs to atproto + * data, specifically `did:plc` DIDs. + * Can optionally cache resolved DID docs. + */ export class DidPlcResolver extends BaseResolver { constructor( public plcUrl: string, diff --git a/identity/did/util.ts b/identity/did/util.ts index 5898ff0..dedb15b 100644 --- a/identity/did/util.ts +++ b/identity/did/util.ts @@ -1,3 +1,4 @@ +/** A timed function to abort after a certain amount of time */ export async function timed unknown>( ms: number, fn: F, diff --git a/identity/did/web-resolver.ts b/identity/did/web-resolver.ts index 1cbf055..7aa41e9 100644 --- a/identity/did/web-resolver.ts +++ b/identity/did/web-resolver.ts @@ -9,6 +9,11 @@ import { timed } from "./util.ts"; /** Path to the DID document on a `did:web` DID. */ export const DOC_PATH = "/.well-known/did.json"; +/** + * Did resolver for resolving DIDs to atproto + * data, specifically `did:web` DIDs. + * Can optionally cache resolved DID docs. + */ export class DidWebResolver extends BaseResolver { constructor( public timeout: number, diff --git a/identity/id-resolver.ts b/identity/id-resolver.ts index 1906092..b64d694 100644 --- a/identity/id-resolver.ts +++ b/identity/id-resolver.ts @@ -3,7 +3,8 @@ import { HandleResolver } from "./handle/index.ts"; import type { IdentityResolverOpts } from "./types.ts"; /** - * Combines Handle and DID resolvers into a single identity resolver class. + * A single identity resolver class combining Did resolver and Handle resolver. + * Can resolve handles and dids to atproto data with an optional cache. */ export class IdResolver { public handle: HandleResolver; diff --git a/identity/types.ts b/identity/types.ts index 8d4de09..f79fff5 100644 --- a/identity/types.ts +++ b/identity/types.ts @@ -69,6 +69,10 @@ export type CacheResult = { expired: boolean; }; +/** + * An optional configured cache for caching resolved + * did documents and getting the cached did docs. + */ export interface DidCache { cacheDid( did: string, -- 2.51.2