diff --git a/API_ANALYSIS.md b/API_ANALYSIS.md --- a/API_ANALYSIS.md +++ b/API_ANALYSIS.md @@ -16,14 +16,80 @@ ### Git SSH Key Management +#### Lexicon Details + +**`sh.tangled.publicKey` Record Schema** (from `core/lexicons/publicKey.json`): +```json +{ + "lexicon": 1, + "id": "sh.tangled.publicKey", + "key": "tid", + "record": { + "required": ["key", "name", "createdAt"], + "properties": { + "key": { + "type": "string", + "maxLength": 4096, + "description": "public key contents" + }, + "name": { + "type": "string", + "description": "human-readable name for this key" + }, + "createdAt": { + "type": "string", + "format": "datetime", + "description": "key upload timestamp" + } + } + } +} +``` + +**`sh.tangled.knot.listKeys` Query** (from `core/lexicons/knot/listKeys.json`): +- Query endpoint for listing public keys stored on the knot server +- Returns: Array of `{ did, key, createdAt }` +- Supports pagination with `limit` and `cursor` parameters + +#### Implementation Approach + * **`tangled ssh-key add `**: - * **Feasible (using generic ATProto record creation).** The `core/lexicons/publicKey.json` defines the `sh.tangled.publicKey` record type. To add a user's global SSH public key, the CLI would use the generic ATProto `com.atproto.repo.createRecord` procedure. The `collection` parameter would be set to `sh.tangled.publicKey`, and the public key content (`key`) and a human-readable name (`name`) would be provided as the record data. + * **Feasible (using generic ATProto record creation).** + * Uses `AtpAgent.com.atproto.repo.createRecord()` with: + - `collection: "sh.tangled.publicKey"` + - `record: { key, name, createdAt }` + * The record will be stored on the user's PDS (Personal Data Server) + * The CLI reads the public key file, validates the format, and creates the record + * **`tangled ssh-key verify`**: * **Feasible.** This command can be implemented by: - 1. Executing `ssh -T git@tangled.org` to capture the authenticated user's DID from the server response. - 2. Using the `sh.tangled.knot.listKeys` query (defined in `core/lexicons/knot/listKeys.json`) to fetch a list of public keys known to the knot server. This query returns objects that include the `did` associated with each key. - 3. Comparing the DID obtained from the SSH output with the DIDs returned by `listKeys` to confirm the key's association. - 4. Resolving the DID to a human-readable Bluesky handle using the standard AT Protocol `com.atproto.identity.resolveHandle` procedure (part of `@atproto/api`). + 1. Executing `ssh -T git@tangled.org` to capture the authenticated user's DID from the server response + 2. Parsing the DID from the SSH output + 3. Resolving the DID to a human-readable Bluesky handle using `com.atproto.identity.resolveHandle` + * Note: The `sh.tangled.knot.listKeys` query is available but may require knot server access + +#### TypeScript/JavaScript Tools + +- **`@atproto/api`**: Main SDK for AT Protocol operations + - `AtpAgent` class handles authentication and API calls + - Built-in methods for `com.atproto.repo.createRecord`, `getRecord`, `listRecords` + +- **`@atproto/lexicon`**: Schema validation library + - `Lexicons` class for loading and validating custom schemas + - Provides `assertValidRecord()` for validating record data against lexicons + +- **Direct Record Creation**: No code generation needed + ```typescript + await agent.com.atproto.repo.createRecord({ + repo: agent.session.did, + collection: 'sh.tangled.publicKey', + record: { + key: publicKeyContent, + name: keyName, + createdAt: new Date().toISOString() + } + }) + ``` ### Repository Management diff --git a/README.md b/README.md --- a/README.md +++ b/README.md @@ -35,16 +35,18 @@ ## Tech Stack (TypeScript) -| Component | Library | Purpose | -| :---------------- | :-------------------- | :------------------------------------------------------------ | -| **Framework** | **commander** | Routing (tangled repo create). | -| **API Client** | **@atproto/api** | Official XRPC client & session management. | -| **Git Context** | **git-url-parse** | **New:** Parses remote URLs to extract the Tangled DID/NSID. | -| **Git Ops** | **simple-git** | Wraps local git operations safely. | -| **Validation** | **zod** | Validates inputs & generates schemas for LLMs. | -| **Interactivity** | **@inquirer/prompts** | Modern prompts for humans. | -| **Formatting** | **cli-table3** | **New:** For gh-style pretty tables in Human Mode. | -| **OS Keychain** | **keytar** | **New:** To securely store session tokens in the OS keychain. | +| Component | Library | Purpose | +| :---------------- | :---------------------- | :--------------------------------------------------------------------------------------------- | +| **Framework** | **commander** | CLI routing and command parsing (e.g., `tangled repo create`). | +| **API Client** | **@atproto/api** | Official AT Protocol XRPC client, session management, and record operations. | +| **Lexicon Tools** | **@atproto/lexicon** | Schema validation for custom Tangled.org lexicons (e.g., `sh.tangled.publicKey`). | +| **Git Context** | **git-url-parse** | Parses remote URLs to extract the Tangled DID/NSID from `.git/config`. | +| **Git Ops** | **simple-git** | Wraps local git operations safely. | +| **Validation** | **zod** | Input validation and schema generation for LLMs. | +| **Interactivity** | **@inquirer/prompts** | Modern, user-friendly prompts for interactive flows. | +| **Formatting** | **cli-table3** | Pretty tables for "Human Mode" output (following gh CLI patterns). | +| **OS Keychain** | **@napi-rs/keyring** | Cross-platform secure storage for AT Protocol session tokens (macOS, Windows, Linux). | +| **TypeScript** | **tsx** | Fast TypeScript execution for development and testing. | ## Agent Integration (The "LLM Friendly" Layer)