@aauth/bootstrap
Advanced tools
| export interface ParsedArgs { | ||
| command?: string; | ||
| positional: string[]; | ||
| flags: Record<string, string | boolean>; | ||
| /** `--help` / `-h` (silent alias) or the `help` command. */ | ||
| help: boolean; | ||
| /** `--version` (silent alias). */ | ||
| version: boolean; | ||
| } | ||
| export declare function parseArgs(argv: string[]): ParsedArgs; | ||
| //# sourceMappingURL=args.d.ts.map |
| {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAA;IACvC,4DAA4D;IAC5D,IAAI,EAAE,OAAO,CAAA;IACb,kCAAkC;IAClC,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA6BpD"} |
+44
| /** Flags that consume the following token as their value. Everything else is boolean. */ | ||
| const VALUE_FLAGS = new Set([ | ||
| 'keystore', | ||
| 'algorithm', | ||
| 'person-server', | ||
| 'agent-provider', | ||
| 'agent-id', | ||
| 'local', | ||
| 'lifetime', | ||
| ]); | ||
| export function parseArgs(argv) { | ||
| const positional = []; | ||
| const flags = {}; | ||
| let help = false; | ||
| let version = false; | ||
| for (let i = 0; i < argv.length; i++) { | ||
| const a = argv[i]; | ||
| if (a === '--help' || a === '-h') { | ||
| help = true; | ||
| } | ||
| else if (a === '--version') { | ||
| version = true; | ||
| } | ||
| else if (a.startsWith('--')) { | ||
| const key = a.slice(2); | ||
| if (VALUE_FLAGS.has(key)) { | ||
| flags[key] = argv[++i] ?? ''; | ||
| } | ||
| else { | ||
| flags[key] = true; | ||
| } | ||
| } | ||
| else if (a.startsWith('-') && a.length > 1) { | ||
| // Unknown short flag — long-form only for v1; accept as a boolean so it | ||
| // doesn't get mistaken for a positional. | ||
| flags[a.slice(1)] = true; | ||
| } | ||
| else { | ||
| positional.push(a); | ||
| } | ||
| } | ||
| return { command: positional[0], positional, flags, help, version }; | ||
| } | ||
| //# sourceMappingURL=args.js.map |
| {"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,UAAU;IACV,WAAW;IACX,eAAe;IACf,gBAAgB;IAChB,UAAU;IACV,OAAO;IACP,UAAU;CACX,CAAC,CAAA;AAYF,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,MAAM,UAAU,GAAa,EAAE,CAAA;IAC/B,MAAM,KAAK,GAAqC,EAAE,CAAA;IAClD,IAAI,IAAI,GAAG,KAAK,CAAA;IAChB,IAAI,OAAO,GAAG,KAAK,CAAA;IAEnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACjC,IAAI,GAAG,IAAI,CAAA;QACb,CAAC;aAAM,IAAI,CAAC,KAAK,WAAW,EAAE,CAAC;YAC7B,OAAO,GAAG,IAAI,CAAA;QAChB,CAAC;aAAM,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;YACtB,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzB,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;YAC9B,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;YACnB,CAAC;QACH,CAAC;aAAM,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7C,wEAAwE;YACxE,yCAAyC;YACzC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;QAC1B,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACpB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;AACrE,CAAC"} |
| export {}; | ||
| //# sourceMappingURL=args.test.d.ts.map |
| {"version":3,"file":"args.test.d.ts","sourceRoot":"","sources":["../src/args.test.ts"],"names":[],"mappings":""} |
| import { describe, it, expect } from 'vitest'; | ||
| import { parseArgs } from './args.js'; | ||
| describe('parseArgs', () => { | ||
| it('parses a bare invocation (no command)', () => { | ||
| const r = parseArgs([]); | ||
| expect(r.command).toBeUndefined(); | ||
| expect(r.positional).toEqual([]); | ||
| }); | ||
| it('parses a command with a positional URL', () => { | ||
| const r = parseArgs(['create', 'https://me.github.io']); | ||
| expect(r.command).toBe('create'); | ||
| expect(r.positional[1]).toBe('https://me.github.io'); | ||
| }); | ||
| it('parses value flags', () => { | ||
| const r = parseArgs([ | ||
| 'create', 'https://me.github.io', | ||
| '--keystore', 'secure-enclave', | ||
| '--algorithm', 'ES256', | ||
| '--person-server', 'https://person.example', | ||
| ]); | ||
| expect(r.flags.keystore).toBe('secure-enclave'); | ||
| expect(r.flags.algorithm).toBe('ES256'); | ||
| expect(r.flags['person-server']).toBe('https://person.example'); | ||
| }); | ||
| it('treats --help / -h as help, --version as version', () => { | ||
| expect(parseArgs(['list', '--help']).help).toBe(true); | ||
| expect(parseArgs(['-h']).help).toBe(true); | ||
| expect(parseArgs(['--version']).version).toBe(true); | ||
| }); | ||
| it('parses token flags including --local and --lifetime', () => { | ||
| const r = parseArgs(['token', '--local', 'claude', '--lifetime', '600']); | ||
| expect(r.command).toBe('token'); | ||
| expect(r.flags.local).toBe('claude'); | ||
| expect(r.flags.lifetime).toBe('600'); | ||
| }); | ||
| it('keeps a URL positional that follows a boolean-only context', () => { | ||
| const r = parseArgs(['delete', 'https://me.github.io']); | ||
| expect(r.positional).toEqual(['delete', 'https://me.github.io']); | ||
| expect(r.command).toBe('delete'); | ||
| }); | ||
| it('reads the skill name as the second positional', () => { | ||
| const r = parseArgs(['skill', 'github-pages']); | ||
| expect(r.command).toBe('skill'); | ||
| expect(r.positional[1]).toBe('github-pages'); | ||
| }); | ||
| }); | ||
| //# sourceMappingURL=args.test.js.map |
| {"version":3,"file":"args.test.js","sourceRoot":"","sources":["../src/args.test.ts"],"names":[],"mappings":"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"} |
| import type { BackendInfo } from '@aauth/local-keys'; | ||
| import type { SkillSummary } from './skills.js'; | ||
| /** A keystore entry as surfaced by `list` (renamed from "backend"). */ | ||
| export interface KeystoreInfo { | ||
| keystore: string; | ||
| description: string; | ||
| algorithms: string[]; | ||
| } | ||
| /** | ||
| * Add ANSI syntax colors to a pretty-printed JSON string: keys blue, strings | ||
| * green, numbers cyan, booleans/null yellow. Caller decides whether to apply it | ||
| * (TTY only) — colors must never reach a pipe, or `jq` would choke on them. | ||
| */ | ||
| export declare function colorizeJson(json: string): string; | ||
| /** Map discovered backends to the `keystore` shape used in `list` output. */ | ||
| export declare function shapeKeystores(backends: BackendInfo[]): KeystoreInfo[]; | ||
| /** The AAuth protocol spec — a URL the agent fetches itself (nothing bundled). */ | ||
| export declare const PROTOCOL_SPEC_URL = "https://raw.githubusercontent.com/dickhardt/AAuth/refs/heads/main/draft-hardt-oauth-aauth-protocol.md"; | ||
| /** | ||
| * The protocol-spec pointer, appended to *every* skill output (the list and each | ||
| * individual guide) so the agent always learns where the spec is — rather than it | ||
| * being a separate `protocol` skill it might never open. | ||
| */ | ||
| export declare function withProtocolSpec(body: string): string; | ||
| /** Render the skill list as markdown (`#` title, `##` per skill) — agents parse this best. */ | ||
| export declare function renderSkillListMarkdown(skills: SkillSummary[]): string; | ||
| export declare function topLevelHelp(version: string): string; | ||
| /** Per-command help text, keyed by command name. */ | ||
| export declare const COMMAND_HELP: Record<string, string>; | ||
| //# sourceMappingURL=render.d.ts.map |
| {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,uEAAuE;AACvE,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAcjD;AAED,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,YAAY,EAAE,CAMtE;AAED,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,0GAC2E,CAAA;AAEzG;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,8FAA8F;AAC9F,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,CAStE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAwCpD;AAED,oDAAoD;AACpD,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAkI/C,CAAA"} |
+219
| /** | ||
| * Add ANSI syntax colors to a pretty-printed JSON string: keys blue, strings | ||
| * green, numbers cyan, booleans/null yellow. Caller decides whether to apply it | ||
| * (TTY only) — colors must never reach a pipe, or `jq` would choke on them. | ||
| */ | ||
| export function colorizeJson(json) { | ||
| const RESET = '\x1b[0m'; | ||
| return json.replace(/("(?:\\.|[^"\\])*")(\s*:)?|\b(true|false|null)\b|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)/g, (match, str, colon, keyword, num) => { | ||
| if (str !== undefined) { | ||
| if (colon !== undefined) | ||
| return `\x1b[34m${str}${RESET}${colon}`; // key | ||
| return `\x1b[32m${str}${RESET}`; // string value | ||
| } | ||
| if (keyword !== undefined) | ||
| return `\x1b[33m${keyword}${RESET}`; // bool / null | ||
| if (num !== undefined) | ||
| return `\x1b[36m${num}${RESET}`; // number | ||
| return match; | ||
| }); | ||
| } | ||
| /** Map discovered backends to the `keystore` shape used in `list` output. */ | ||
| export function shapeKeystores(backends) { | ||
| return backends.map((b) => ({ | ||
| keystore: b.backend, | ||
| description: b.description, | ||
| algorithms: b.algorithms, | ||
| })); | ||
| } | ||
| /** The AAuth protocol spec — a URL the agent fetches itself (nothing bundled). */ | ||
| export const PROTOCOL_SPEC_URL = 'https://raw.githubusercontent.com/dickhardt/AAuth/refs/heads/main/draft-hardt-oauth-aauth-protocol.md'; | ||
| /** | ||
| * The protocol-spec pointer, appended to *every* skill output (the list and each | ||
| * individual guide) so the agent always learns where the spec is — rather than it | ||
| * being a separate `protocol` skill it might never open. | ||
| */ | ||
| export function withProtocolSpec(body) { | ||
| return `${body.replace(/\s+$/, '')}\n\n## AAuth protocol spec\nFetch this URL to read the full spec: ${PROTOCOL_SPEC_URL}`; | ||
| } | ||
| /** Render the skill list as markdown (`#` title, `##` per skill) — agents parse this best. */ | ||
| export function renderSkillListMarkdown(skills) { | ||
| const lines = ['# AAuth bootstrap skills', '']; | ||
| for (const s of skills) { | ||
| lines.push(`## ${s.name}`); | ||
| if (s.description) | ||
| lines.push(s.description); | ||
| lines.push(''); | ||
| } | ||
| lines.push('Run `npx @aauth/bootstrap skill <name>` to print a guide.'); | ||
| return withProtocolSpec(lines.join('\n')); | ||
| } | ||
| export function topLevelHelp(version) { | ||
| return `DESCRIPTION | ||
| AAuth bootstrap v${version} — set up an agent provider identity for AAuth. | ||
| Agents: run \`npx @aauth/bootstrap skill setup\` for end-to-end setup. | ||
| USAGE | ||
| npx @aauth/bootstrap <command> [flags] | ||
| COMMANDS | ||
| skill [name] | ||
| Agent setup guides — start here: | ||
| setup | ||
| Set up an agent identity end-to-end | ||
| github-pages | ||
| Publish to GitHub Pages | ||
| gitlab-pages | ||
| Publish to GitLab Pages | ||
| cloudflare-pages | ||
| Publish to Cloudflare Pages | ||
| netlify | ||
| Publish to Netlify | ||
| list | ||
| List agent providers, keys, and keystores | ||
| create <agent-provider-url> [--keystore <name>] [--algorithm <alg>] [--person-server <url>] | ||
| Register an agent provider (generates its first key, binds a person server) | ||
| delete <agent-provider-url> | ||
| Delete an agent provider and its keys | ||
| token [--agent-provider <url>] [--agent-id <id>] [--local <name>] [--lifetime <s>] | ||
| Generate an agent token | ||
| help [command] | ||
| Show help for a command`; | ||
| } | ||
| /** Per-command help text, keyed by command name. */ | ||
| export const COMMAND_HELP = { | ||
| list: `DESCRIPTION | ||
| List configured agent providers, their keys (with public JWKs), and the | ||
| keystores available on this machine. | ||
| USAGE | ||
| npx @aauth/bootstrap list | ||
| EXAMPLE | ||
| $ npx @aauth/bootstrap list | ||
| { | ||
| "keystores": [ | ||
| { "keystore": "software", "description": "Software keys stored in OS keychain", "algorithms": ["EdDSA", "ES256"] } | ||
| ], | ||
| "agentProviders": [ | ||
| { | ||
| "url": "https://descartes.github.io", | ||
| "agentId": "aauth:local@descartes.github.io", | ||
| "personServer": "https://person.hello.coop", | ||
| "keys": [ | ||
| { "kid": "bd3f9c…", "keystore": "software", | ||
| "publicJwk": { "kty": "OKP", "crv": "Ed25519", "x": "…", "alg": "EdDSA" } } | ||
| ] | ||
| } | ||
| ] | ||
| }`, | ||
| create: `DESCRIPTION | ||
| Register a new agent provider. One command does the whole setup: | ||
| - generates a signing key (in the chosen keystore) | ||
| - binds that key to the agent provider | ||
| - binds a person server (default: person.hello.coop, unless --person-server) | ||
| Fails if the agent provider already exists (delete it first to re-create). | ||
| USAGE | ||
| npx @aauth/bootstrap create <agent-provider-url> [flags] | ||
| FLAGS | ||
| --keystore <name> | ||
| Which keystore to use (default: software) — run \`list\` for available keystores | ||
| --algorithm <alg> | ||
| An algorithm the chosen keystore supports (see \`list\`); defaults to the keystore's default | ||
| --person-server <url> | ||
| Person server to bind (default: person.hello.coop) | ||
| EXAMPLE | ||
| $ npx @aauth/bootstrap create https://descartes.github.io | ||
| { | ||
| "agentProvider": "https://descartes.github.io", | ||
| "agentId": "aauth:local@descartes.github.io", | ||
| "personServer": "https://person.hello.coop", | ||
| "keys": [ | ||
| { "kid": "bd3f9c…", "keystore": "software", | ||
| "publicJwk": { "kty": "OKP", "crv": "Ed25519", "x": "…", "alg": "EdDSA", | ||
| "aauth": { "device": "mac-mini", "created": "2026-05-22" } } } | ||
| ] | ||
| }`, | ||
| delete: `DESCRIPTION | ||
| Delete an agent provider and its keys, including from hardware keystores. | ||
| Fails if the agent provider doesn't exist. | ||
| USAGE | ||
| npx @aauth/bootstrap delete <agent-provider-url> | ||
| EXAMPLE | ||
| $ npx @aauth/bootstrap delete https://descartes.github.io | ||
| { | ||
| "deleted": "https://descartes.github.io", | ||
| "keysDeleted": 1 | ||
| }`, | ||
| token: `DESCRIPTION | ||
| Generate an agent token — the credential an agent presents to make authenticated calls. | ||
| With one agent provider configured it needs no arguments — the agent provider and | ||
| its agent-id come from config. Output is the agent token (\`signatureKey\`) plus | ||
| the ephemeral private key (\`signingKey\`) you sign requests with — the token's \`cnf\` | ||
| binds to its public half. | ||
| USAGE | ||
| npx @aauth/bootstrap token [flags] | ||
| FLAGS | ||
| --agent-provider <url> | ||
| Pick the agent provider (default: the sole one in config) | ||
| --agent-id <id> | ||
| Override the agent id (default: the resolved provider's agent) | ||
| --local <name> | ||
| Override just the local-part → aauth:<name>@<host> | ||
| --lifetime <seconds> | ||
| Token lifetime (default: 3600) | ||
| EXAMPLE | ||
| $ npx @aauth/bootstrap token | ||
| { | ||
| "signingKey": { "kty": "OKP", "crv": "Ed25519", "x": "…", "d": "…" }, | ||
| "signatureKey": { "type": "jwt", "jwt": "eyJhbGci…" } | ||
| }`, | ||
| skill: `DESCRIPTION | ||
| Print agent setup guides — how to generate keys and publish your agent identity. | ||
| USAGE | ||
| npx @aauth/bootstrap skill [name] | ||
| No name List available skills (markdown) | ||
| <name> Print that skill's full instructions (markdown) | ||
| EXAMPLE | ||
| $ npx @aauth/bootstrap skill | ||
| # AAuth bootstrap skills | ||
| ## setup | ||
| Set up an AAuth agent provider identity — generate a signing key, bind a | ||
| person server, and publish to a hosting platform | ||
| ## github-pages | ||
| Publish AAuth agent metadata and public keys to GitHub Pages (username.github.io) | ||
| …`, | ||
| help: `DESCRIPTION | ||
| Show help for a command. | ||
| USAGE | ||
| npx @aauth/bootstrap help [command]`, | ||
| }; | ||
| //# sourceMappingURL=render.js.map |
| {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,KAAK,GAAG,SAAS,CAAA;IACvB,OAAO,IAAI,CAAC,OAAO,CACjB,sFAAsF,EACtF,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE;QAClC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,WAAW,GAAG,GAAG,KAAK,GAAG,KAAK,EAAE,CAAA,CAAC,MAAM;YACvE,OAAO,WAAW,GAAG,GAAG,KAAK,EAAE,CAAA,CAAC,eAAe;QACjD,CAAC;QACD,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,WAAW,OAAO,GAAG,KAAK,EAAE,CAAA,CAAC,cAAc;QAC7E,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,WAAW,GAAG,GAAG,KAAK,EAAE,CAAA,CAAC,SAAS;QAChE,OAAO,KAAK,CAAA;IACd,CAAC,CACF,CAAA;AACH,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,cAAc,CAAC,QAAuB;IACpD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1B,QAAQ,EAAE,CAAC,CAAC,OAAO;QACnB,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,UAAU,EAAE,CAAC,CAAC,UAAU;KACzB,CAAC,CAAC,CAAA;AACL,CAAC;AAED,kFAAkF;AAClF,MAAM,CAAC,MAAM,iBAAiB,GAC5B,uGAAuG,CAAA;AAEzG;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,qEAAqE,iBAAiB,EAAE,CAAA;AAC5H,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,uBAAuB,CAAC,MAAsB;IAC5D,MAAM,KAAK,GAAG,CAAC,0BAA0B,EAAE,EAAE,CAAC,CAAA;IAC9C,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;QAC1B,IAAI,CAAC,CAAC,WAAW;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAA;QAC5C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChB,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAA;IACvE,OAAO,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;AAC3C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,OAAO;qBACY,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAqCA,CAAA;AAC5B,CAAC;AAED,oDAAoD;AACpD,MAAM,CAAC,MAAM,YAAY,GAA2B;IAClD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;IAwBJ;IAEF,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA+BN;IAEF,MAAM,EAAE;;;;;;;;;;;;IAYN;IAEF,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4BL;IAEF,KAAK,EAAE;;;;;;;;;;;;;;;;;;;IAmBL;IAEF,IAAI,EAAE;;;;sCAI8B;CACrC,CAAA"} |
| export {}; | ||
| //# sourceMappingURL=render.test.d.ts.map |
| {"version":3,"file":"render.test.d.ts","sourceRoot":"","sources":["../src/render.test.ts"],"names":[],"mappings":""} |
| import { describe, it, expect } from 'vitest'; | ||
| import { shapeKeystores, renderSkillListMarkdown, withProtocolSpec, topLevelHelp, COMMAND_HELP, colorizeJson, } from './render.js'; | ||
| describe('shapeKeystores', () => { | ||
| it('maps BackendInfo to the keystore output shape', () => { | ||
| const backends = [ | ||
| { backend: 'software', description: 'OS keychain', algorithms: ['EdDSA', 'ES256'], deviceId: 'local' }, | ||
| { backend: 'secure-enclave', description: 'macOS Secure Enclave', algorithms: ['ES256'], deviceId: 'local' }, | ||
| ]; | ||
| expect(shapeKeystores(backends)).toEqual([ | ||
| { keystore: 'software', description: 'OS keychain', algorithms: ['EdDSA', 'ES256'] }, | ||
| { keystore: 'secure-enclave', description: 'macOS Secure Enclave', algorithms: ['ES256'] }, | ||
| ]); | ||
| }); | ||
| it('returns an empty array for no backends', () => { | ||
| expect(shapeKeystores([])).toEqual([]); | ||
| }); | ||
| }); | ||
| describe('renderSkillListMarkdown', () => { | ||
| const skills = [ | ||
| { name: 'setup', description: 'Set up an agent identity', when: '' }, | ||
| { name: 'github-pages', description: 'Publish to GitHub Pages', when: '' }, | ||
| ]; | ||
| it('renders a markdown title and a ## heading per skill (not bold, not JSON)', () => { | ||
| const md = renderSkillListMarkdown(skills); | ||
| expect(md).toContain('# AAuth bootstrap skills'); | ||
| expect(md).toContain('## setup'); | ||
| expect(md).toContain('Set up an agent identity'); | ||
| expect(md).toContain('## github-pages'); | ||
| expect(md).not.toContain('**setup**'); | ||
| expect(md.trimStart().startsWith('[')).toBe(false); // not a JSON array | ||
| }); | ||
| it('points at `skill <name>`', () => { | ||
| expect(renderSkillListMarkdown(skills)).toContain('skill <name>'); | ||
| }); | ||
| it('folds the protocol spec URL into the list (no separate protocol skill)', () => { | ||
| const md = renderSkillListMarkdown(skills); | ||
| expect(md).toContain('## AAuth protocol spec'); | ||
| expect(md).toContain('draft-hardt-oauth-aauth-protocol.md'); | ||
| }); | ||
| }); | ||
| describe('withProtocolSpec', () => { | ||
| it('appends the spec-URL footer to a skill guide body (every skill carries it)', () => { | ||
| const out = withProtocolSpec('# setup\n\nDo the thing.\n'); | ||
| expect(out).toContain('# setup'); | ||
| expect(out).toContain('Do the thing.'); | ||
| expect(out).toContain('## AAuth protocol spec'); | ||
| expect(out).toContain('draft-hardt-oauth-aauth-protocol.md'); | ||
| // footer comes after the body, with one blank line between | ||
| expect(out).toMatch(/Do the thing\.\n\n## AAuth protocol spec\n/); | ||
| }); | ||
| }); | ||
| describe('help text', () => { | ||
| it('top-level help shows the version and the v1 commands', () => { | ||
| const help = topLevelHelp('1.2.3'); | ||
| expect(help).toContain('v1.2.3'); | ||
| for (const cmd of ['list', 'create', 'delete', 'token', 'skill', 'help']) { | ||
| expect(help).toContain(cmd); | ||
| } | ||
| // GLOBAL section was dropped; --version/--help are silent aliases. | ||
| expect(help).not.toContain('GLOBAL'); | ||
| }); | ||
| it('has per-command help for every v1 command', () => { | ||
| for (const cmd of ['list', 'create', 'delete', 'token', 'skill', 'help']) { | ||
| expect(COMMAND_HELP[cmd]).toBeTruthy(); | ||
| expect(COMMAND_HELP[cmd]).toContain('DESCRIPTION'); | ||
| } | ||
| }); | ||
| it('result-bearing commands include an EXAMPLE with a sample response', () => { | ||
| for (const cmd of ['list', 'create', 'delete', 'token', 'skill']) { | ||
| expect(COMMAND_HELP[cmd]).toContain('EXAMPLE'); | ||
| expect(COMMAND_HELP[cmd]).toContain('$ npx @aauth/bootstrap'); | ||
| } | ||
| }); | ||
| }); | ||
| describe('colorizeJson', () => { | ||
| const json = JSON.stringify({ a: 'hi', n: 42, b: true, z: null }, null, 2); | ||
| it('adds ANSI codes', () => { | ||
| const out = colorizeJson(json); | ||
| expect(out).toContain('\x1b['); // has color | ||
| expect(out).not.toBe(json); | ||
| }); | ||
| it('is purely additive — stripping ANSI yields the original JSON', () => { | ||
| const stripped = colorizeJson(json).replace(/\x1b\[[0-9]*m/g, ''); | ||
| expect(stripped).toBe(json); | ||
| expect(JSON.parse(stripped)).toEqual({ a: 'hi', n: 42, b: true, z: null }); | ||
| }); | ||
| }); | ||
| //# sourceMappingURL=render.test.js.map |
| {"version":3,"file":"render.test.js","sourceRoot":"","sources":["../src/render.test.ts"],"names":[],"mappings":"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"} |
| import type { KeyAlgorithm, KeyBackend } from '@aauth/local-keys'; | ||
| /** | ||
| * Pure resolution helpers shared by the commands. Kept side-effect-free (config | ||
| * lookups are passed in) so every flag-precedence branch is unit-testable. | ||
| */ | ||
| /** Pick the agent provider: explicit flag wins, else the sole configured one. */ | ||
| export declare function resolveProvider(explicit: string | undefined, providers: string[]): { | ||
| url?: string; | ||
| error?: string; | ||
| }; | ||
| /** Keystore + algorithm with defaults: software→EdDSA, any hardware keystore→ES256. */ | ||
| export declare function resolveKeystoreAlgorithm(keystoreFlag: string | undefined, algorithmFlag: string | undefined): { | ||
| keystore: KeyBackend; | ||
| algorithm: KeyAlgorithm; | ||
| }; | ||
| /** Agent id precedence: explicit `--agent-id` > `--local`@host > config. */ | ||
| export declare function resolveAgentId(opts: { | ||
| explicit?: string; | ||
| local?: string; | ||
| host: string; | ||
| configAgentId?: string; | ||
| }): string | undefined; | ||
| /** Token lifetime in seconds; default 3600, ignoring a non-numeric flag. */ | ||
| export declare function resolveLifetime(flag: string | undefined): number; | ||
| //# sourceMappingURL=resolve.d.ts.map |
| {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAEjE;;;GAGG;AAEH,iFAAiF;AACjF,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,SAAS,EAAE,MAAM,EAAE,GAClB;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAOlC;AAED,uFAAuF;AACvF,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,aAAa,EAAE,MAAM,GAAG,SAAS,GAChC;IAAE,QAAQ,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAInD;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,GAAG,MAAM,GAAG,SAAS,CAIrB;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAIhE"} |
| /** | ||
| * Pure resolution helpers shared by the commands. Kept side-effect-free (config | ||
| * lookups are passed in) so every flag-precedence branch is unit-testable. | ||
| */ | ||
| /** Pick the agent provider: explicit flag wins, else the sole configured one. */ | ||
| export function resolveProvider(explicit, providers) { | ||
| if (explicit) | ||
| return { url: explicit }; | ||
| if (providers.length === 1) | ||
| return { url: providers[0] }; | ||
| if (providers.length === 0) { | ||
| return { error: 'No agent provider configured. Run `create <agent-provider-url>` first.' }; | ||
| } | ||
| return { error: 'Multiple agent providers configured. Pass --agent-provider <url>.' }; | ||
| } | ||
| /** Keystore + algorithm with defaults: software→EdDSA, any hardware keystore→ES256. */ | ||
| export function resolveKeystoreAlgorithm(keystoreFlag, algorithmFlag) { | ||
| const keystore = (keystoreFlag ?? 'software'); | ||
| const algorithm = (algorithmFlag ?? (keystore === 'software' ? 'EdDSA' : 'ES256')); | ||
| return { keystore, algorithm }; | ||
| } | ||
| /** Agent id precedence: explicit `--agent-id` > `--local`@host > config. */ | ||
| export function resolveAgentId(opts) { | ||
| if (opts.explicit) | ||
| return opts.explicit; | ||
| if (opts.local) | ||
| return `aauth:${opts.local}@${opts.host}`; | ||
| return opts.configAgentId; | ||
| } | ||
| /** Token lifetime in seconds; default 3600, ignoring a non-numeric flag. */ | ||
| export function resolveLifetime(flag) { | ||
| if (flag === undefined) | ||
| return 3600; | ||
| const n = parseInt(flag, 10); | ||
| return Number.isFinite(n) ? n : 3600; | ||
| } | ||
| //# sourceMappingURL=resolve.js.map |
| {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,iFAAiF;AACjF,MAAM,UAAU,eAAe,CAC7B,QAA4B,EAC5B,SAAmB;IAEnB,IAAI,QAAQ;QAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAA;IACtC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAA;IACxD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,KAAK,EAAE,wEAAwE,EAAE,CAAA;IAC5F,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,mEAAmE,EAAE,CAAA;AACvF,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,wBAAwB,CACtC,YAAgC,EAChC,aAAiC;IAEjC,MAAM,QAAQ,GAAG,CAAC,YAAY,IAAI,UAAU,CAAe,CAAA;IAC3D,MAAM,SAAS,GAAG,CAAC,aAAa,IAAI,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAiB,CAAA;IAClG,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAA;AAChC,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,cAAc,CAAC,IAK9B;IACC,IAAI,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC,QAAQ,CAAA;IACvC,IAAI,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE,CAAA;IACzD,OAAO,IAAI,CAAC,aAAa,CAAA;AAC3B,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,eAAe,CAAC,IAAwB;IACtD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IACnC,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;IAC5B,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AACtC,CAAC"} |
| export {}; | ||
| //# sourceMappingURL=resolve.test.d.ts.map |
| {"version":3,"file":"resolve.test.d.ts","sourceRoot":"","sources":["../src/resolve.test.ts"],"names":[],"mappings":""} |
| import { describe, it, expect } from 'vitest'; | ||
| import { resolveProvider, resolveKeystoreAlgorithm, resolveAgentId, resolveLifetime, } from './resolve.js'; | ||
| describe('resolveProvider', () => { | ||
| it('uses the explicit flag when given', () => { | ||
| expect(resolveProvider('https://x.example', ['https://a.example', 'https://b.example'])) | ||
| .toEqual({ url: 'https://x.example' }); | ||
| }); | ||
| it('uses the sole configured provider', () => { | ||
| expect(resolveProvider(undefined, ['https://only.example'])).toEqual({ url: 'https://only.example' }); | ||
| }); | ||
| it('errors when none configured', () => { | ||
| expect(resolveProvider(undefined, []).error).toMatch(/No agent provider/); | ||
| }); | ||
| it('errors when multiple and no flag', () => { | ||
| expect(resolveProvider(undefined, ['https://a.example', 'https://b.example']).error).toMatch(/Multiple/); | ||
| }); | ||
| }); | ||
| describe('resolveKeystoreAlgorithm', () => { | ||
| it('defaults to software + EdDSA', () => { | ||
| expect(resolveKeystoreAlgorithm(undefined, undefined)).toEqual({ keystore: 'software', algorithm: 'EdDSA' }); | ||
| }); | ||
| it('defaults a hardware keystore to ES256', () => { | ||
| expect(resolveKeystoreAlgorithm('secure-enclave', undefined)).toEqual({ keystore: 'secure-enclave', algorithm: 'ES256' }); | ||
| }); | ||
| it('respects an explicit algorithm', () => { | ||
| expect(resolveKeystoreAlgorithm('software', 'ES256')).toEqual({ keystore: 'software', algorithm: 'ES256' }); | ||
| }); | ||
| }); | ||
| describe('resolveAgentId', () => { | ||
| const host = 'me.github.io'; | ||
| it('explicit wins over everything', () => { | ||
| expect(resolveAgentId({ explicit: 'custom@x', local: 'claude', host, configAgentId: 'aauth:local@me.github.io' })) | ||
| .toBe('custom@x'); | ||
| }); | ||
| it('local builds aauth:<local>@<host>', () => { | ||
| expect(resolveAgentId({ local: 'claude', host, configAgentId: 'aauth:local@me.github.io' })) | ||
| .toBe('aauth:claude@me.github.io'); | ||
| }); | ||
| it('falls back to config', () => { | ||
| expect(resolveAgentId({ host, configAgentId: 'aauth:local@me.github.io' })).toBe('aauth:local@me.github.io'); | ||
| }); | ||
| it('undefined when nothing resolves', () => { | ||
| expect(resolveAgentId({ host })).toBeUndefined(); | ||
| }); | ||
| }); | ||
| describe('resolveLifetime', () => { | ||
| it('defaults to 3600', () => { | ||
| expect(resolveLifetime(undefined)).toBe(3600); | ||
| }); | ||
| it('parses a numeric flag', () => { | ||
| expect(resolveLifetime('600')).toBe(600); | ||
| }); | ||
| it('falls back to 3600 on non-numeric', () => { | ||
| expect(resolveLifetime('abc')).toBe(3600); | ||
| }); | ||
| }); | ||
| //# sourceMappingURL=resolve.test.js.map |
| {"version":3,"file":"resolve.test.js","sourceRoot":"","sources":["../src/resolve.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,cAAc,EACd,eAAe,GAChB,MAAM,cAAc,CAAA;AAErB,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,eAAe,CAAC,mBAAmB,EAAE,CAAC,mBAAmB,EAAE,mBAAmB,CAAC,CAAC,CAAC;aACrF,OAAO,CAAC,EAAE,GAAG,EAAE,mBAAmB,EAAE,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,sBAAsB,EAAE,CAAC,CAAA;IACvG,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC,mBAAmB,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IAC1G,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,wBAAwB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAA;IAC9G,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,wBAAwB,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAA;IAC3H,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,wBAAwB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAA;IAC7G,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,MAAM,IAAI,GAAG,cAAc,CAAA;IAC3B,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,0BAA0B,EAAE,CAAC,CAAC;aAC/G,IAAI,CAAC,UAAU,CAAC,CAAA;IACrB,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,0BAA0B,EAAE,CAAC,CAAC;aACzF,IAAI,CAAC,2BAA2B,CAAC,CAAA;IACtC,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,0BAA0B,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAA;IAC9G,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAA;IAClD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAC1B,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC3C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"} |
@@ -1,2 +0,1 @@ | ||
| import type { OnBootstrapEvent } from './log.js'; | ||
| export interface BootstrapPSOptions { | ||
@@ -6,6 +5,5 @@ agentUrl: string; | ||
| local?: string; | ||
| onEvent?: OnBootstrapEvent; | ||
| } | ||
| /** | ||
| * Configure an agent with a person server. | ||
| * Bind an agent provider to a person server. | ||
| * | ||
@@ -20,2 +18,4 @@ * Per draft-hardt-aauth-bootstrap §Self-Hosted Enrollment, publication of the | ||
| * 2. Persists agentId + personServerUrl to ~/.aauth/config.json | ||
| * 3. Caches the fetched PS metadata (public) to ~/.aauth/cache/ so fetch can | ||
| * skip the runtime /.well-known/aauth-person.json round-trip until it expires | ||
| * | ||
@@ -22,0 +22,0 @@ * No network registration call is made; signAgentToken reads personServerUrl |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"bootstrap-ps.d.ts","sourceRoot":"","sources":["../src/bootstrap-ps.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAEhD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,gBAAgB,CAAA;CAC3B;AASD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgChF"} | ||
| {"version":3,"file":"bootstrap-ps.d.ts","sourceRoot":"","sources":["../src/bootstrap-ps.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAUD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuChF"} |
+13
-27
@@ -1,4 +0,4 @@ | ||
| import { setAgentConfig, getAgentConfig } from '@aauth/local-keys'; | ||
| import { setAgentConfig, getAgentConfig, writeCachedMetadata, parseMaxAge } from '@aauth/local-keys'; | ||
| /** | ||
| * Configure an agent with a person server. | ||
| * Bind an agent provider to a person server. | ||
| * | ||
@@ -13,2 +13,4 @@ * Per draft-hardt-aauth-bootstrap §Self-Hosted Enrollment, publication of the | ||
| * 2. Persists agentId + personServerUrl to ~/.aauth/config.json | ||
| * 3. Caches the fetched PS metadata (public) to ~/.aauth/cache/ so fetch can | ||
| * skip the runtime /.well-known/aauth-person.json round-trip until it expires | ||
| * | ||
@@ -19,4 +21,4 @@ * No network registration call is made; signAgentToken reads personServerUrl | ||
| export async function bootstrapWithPS(options) { | ||
| const { agentUrl, personServerUrl, local = 'local', onEvent } = options; | ||
| const metadata = await fetchPSMetadata(personServerUrl, onEvent); | ||
| const { agentUrl, personServerUrl, local = 'local' } = options; | ||
| const { metadata, cacheControl } = await fetchPSMetadata(personServerUrl); | ||
| if (!metadata.issuer) { | ||
@@ -36,3 +38,2 @@ throw new Error('PS metadata missing required field: issuer'); | ||
| } | ||
| onEvent?.({ step: 'ps_metadata_validated', phase: 'info' }); | ||
| const agentId = `aauth:${local}@${new URL(agentUrl).hostname}`; | ||
@@ -45,31 +46,16 @@ const existing = getAgentConfig(agentUrl); | ||
| }); | ||
| onEvent?.({ step: 'agent_config_persisted', phase: 'info', agentId, personServerUrl }); | ||
| // Cache the PS metadata we just fetched (public, not a secret) so fetch can | ||
| // skip the runtime /.well-known/aauth-person.json round-trip. Honour the | ||
| // server's Cache-Control: max-age if it sent one, else the cache's default TTL. | ||
| writeCachedMetadata(new URL(personServerUrl).hostname, metadata, parseMaxAge(cacheControl)); | ||
| } | ||
| async function fetchPSMetadata(personServerUrl, onEvent) { | ||
| async function fetchPSMetadata(personServerUrl) { | ||
| const url = `${personServerUrl.replace(/\/$/, '')}/.well-known/aauth-person.json`; | ||
| onEvent?.({ step: 'ps_metadata_request', phase: 'start', url }); | ||
| const response = await fetch(url); | ||
| const headers = {}; | ||
| const ct = response.headers.get('content-type'); | ||
| if (ct) | ||
| headers['content-type'] = ct; | ||
| if (!response.ok) { | ||
| onEvent?.({ | ||
| step: 'ps_metadata_request', | ||
| phase: 'done', | ||
| status: response.status, | ||
| response: { headers }, | ||
| }); | ||
| throw new Error(`Failed to fetch PS metadata at ${url}: ${response.status}`); | ||
| } | ||
| const body = await response.json(); | ||
| onEvent?.({ | ||
| step: 'ps_metadata_request', | ||
| phase: 'done', | ||
| status: response.status, | ||
| response: { headers }, | ||
| }); | ||
| onEvent?.({ step: 'ps_metadata_body', phase: 'info', body: body }); | ||
| return body; | ||
| const metadata = await response.json(); | ||
| return { metadata, cacheControl: response.headers.get('cache-control') }; | ||
| } | ||
| //# sourceMappingURL=bootstrap-ps.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"bootstrap-ps.js","sourceRoot":"","sources":["../src/bootstrap-ps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAiBlE;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAA2B;IAC/D,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,KAAK,GAAG,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;IAEvE,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,eAAe,EAAE,OAAO,CAAC,CAAA;IAEhE,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAA;IACvE,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;IACjE,CAAC;IAED,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAC3D,MAAM,aAAa,GAAG,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IACxD,IAAI,gBAAgB,KAAK,aAAa,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CACb,cAAc,QAAQ,CAAC,MAAM,yBAAyB,eAAe,GAAG,CACzE,CAAA;IACH,CAAC;IACD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;IAE3D,MAAM,OAAO,GAAG,SAAS,KAAK,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAA;IAC9D,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;IACzC,cAAc,CAAC,QAAQ,EAAE;QACvB,GAAG,CAAC,QAAQ,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QAC7B,OAAO;QACP,eAAe;KAChB,CAAC,CAAA;IACF,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,wBAAwB,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAA;AACxF,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,eAAuB,EAAE,OAA0B;IAChF,MAAM,GAAG,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,gCAAgC,CAAA;IACjF,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAA;IAC/D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;IACjC,MAAM,OAAO,GAA2B,EAAE,CAAA;IAC1C,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;IAC/C,IAAI,EAAE;QAAE,OAAO,CAAC,cAAc,CAAC,GAAG,EAAE,CAAA;IACpC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO,EAAE,CAAC;YACR,IAAI,EAAE,qBAAqB;YAC3B,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,QAAQ,EAAE,EAAE,OAAO,EAAE;SACtB,CAAC,CAAA;QACF,MAAM,IAAI,KAAK,CAAC,kCAAkC,GAAG,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IAC9E,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAgB,CAAA;IAChD,OAAO,EAAE,CAAC;QACR,IAAI,EAAE,qBAAqB;QAC3B,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,QAAQ,EAAE,EAAE,OAAO,EAAE;KACtB,CAAC,CAAA;IACF,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAA0C,EAAE,CAAC,CAAA;IACxG,OAAO,IAAI,CAAA;AACb,CAAC"} | ||
| {"version":3,"file":"bootstrap-ps.js","sourceRoot":"","sources":["../src/bootstrap-ps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAgBpG;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAA2B;IAC/D,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,KAAK,GAAG,OAAO,EAAE,GAAG,OAAO,CAAA;IAE9D,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,eAAe,CAAC,eAAe,CAAC,CAAA;IAEzE,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAA;IAC/D,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAA;IACvE,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;IACjE,CAAC;IAED,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAC3D,MAAM,aAAa,GAAG,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IACxD,IAAI,gBAAgB,KAAK,aAAa,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CACb,cAAc,QAAQ,CAAC,MAAM,yBAAyB,eAAe,GAAG,CACzE,CAAA;IACH,CAAC;IAED,MAAM,OAAO,GAAG,SAAS,KAAK,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAA;IAC9D,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;IACzC,cAAc,CAAC,QAAQ,EAAE;QACvB,GAAG,CAAC,QAAQ,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QAC7B,OAAO;QACP,eAAe;KAChB,CAAC,CAAA;IAEF,4EAA4E;IAC5E,yEAAyE;IACzE,gFAAgF;IAChF,mBAAmB,CACjB,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC,QAAQ,EACjC,QAAQ,EACR,WAAW,CAAC,YAAY,CAAC,CAC1B,CAAA;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,eAAuB;IAEvB,MAAM,GAAG,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,gCAAgC,CAAA;IACjF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;IACjC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,kCAAkC,GAAG,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IAC9E,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAgB,CAAA;IACpD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAA;AAC1E,CAAC"} |
| import { describe, it, expect, vi, beforeAll, beforeEach, afterEach, afterAll } from 'vitest'; | ||
| import { readConfig, writeConfig, getAgentConfig } from '@aauth/local-keys'; | ||
| import { readConfig, writeConfig, getAgentConfig, readCachedMetadata, evictCachedMetadata } from '@aauth/local-keys'; | ||
| import { bootstrapWithPS } from './bootstrap-ps.js'; | ||
@@ -34,2 +34,4 @@ const PS_URL = 'https://ps.example'; | ||
| vi.unstubAllGlobals(); | ||
| // Drop the on-disk cache entry the bootstrap may have written (keyed by PS host). | ||
| evictCachedMetadata('ps.example'); | ||
| }); | ||
@@ -48,2 +50,9 @@ it('fetches metadata from the correct well-known URL', async () => { | ||
| }); | ||
| it('caches the fetched PS metadata (by PS host) so fetch can skip the runtime fetch', async () => { | ||
| mockFetch.mockResolvedValueOnce(mockMetadataResponse(validMetadata)); | ||
| await bootstrapWithPS({ agentUrl: AGENT_URL, personServerUrl: PS_URL }); | ||
| // The full fetched doc is cached verbatim, keyed by the PS host — not in config. | ||
| expect(readCachedMetadata('ps.example')).toEqual(validMetadata); | ||
| expect(getAgentConfig(AGENT_URL)).not.toHaveProperty('personServerMetadata'); | ||
| }); | ||
| it('uses the provided `local` value in agentId', async () => { | ||
@@ -50,0 +59,0 @@ mockFetch.mockResolvedValueOnce(mockMetadataResponse(validMetadata)); |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"bootstrap-ps.test.js","sourceRoot":"","sources":["../src/bootstrap-ps.test.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"bootstrap-ps.test.js","sourceRoot":"","sources":["../src/bootstrap-ps.test.ts"],"names":[],"mappings":"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"} |
+179
-402
| #!/usr/bin/env node | ||
| import { generateKey, generateKid, toPublicJwk, readKeychain, writeKeychain, listAgentUrls, discoverBackends, getBackend, readConfig, addKeyToAgent, setHosting, setAgentConfig, getAgentConfig, listConfiguredAgents, signAgentToken, resolveKey, validateUrl, ensureAgentUrls, } from '@aauth/local-keys'; | ||
| import { createRequire } from 'node:module'; | ||
| import { generateKey, generateKid, toPublicJwk, discoverBackends, getBackend, getAgentConfig, addKeyToAgent, deleteAgentProvider, listAgentProviders, readKeychain, writeKeychain, deleteKeychain, signAgentToken, validateUrl, ensureAgentUrls, KeyDeletionUnsupportedError, } from '@aauth/local-keys'; | ||
| import { bootstrapWithPS } from './bootstrap-ps.js'; | ||
| import { listSkills, getSkill } from './skills.js'; | ||
| import { bootstrapWithPS } from './bootstrap-ps.js'; | ||
| import { buildLogEmitter } from './log.js'; | ||
| import { createHash } from 'node:crypto'; | ||
| import { createRequire } from 'node:module'; | ||
| import { parseArgs } from './args.js'; | ||
| import { topLevelHelp, COMMAND_HELP, shapeKeystores, renderSkillListMarkdown, withProtocolSpec, colorizeJson, } from './render.js'; | ||
| import { resolveProvider, resolveKeystoreAlgorithm, resolveAgentId, resolveLifetime, } from './resolve.js'; | ||
| const pkg = createRequire(import.meta.url)('../package.json'); | ||
| /** Person Server used when `--ps`/`--person-server` is given without a URL. */ | ||
| const DEFAULT_PERSON_SERVER = 'https://person.hello.coop'; | ||
| function computeJkt(jwk) { | ||
| const kty = jwk.kty; | ||
| const crv = jwk.crv; | ||
| const x = jwk.x; | ||
| const y = jwk.y; | ||
| const canonical = kty === 'EC' | ||
| ? JSON.stringify({ crv, kty, x, y }) | ||
| : JSON.stringify({ crv, kty, x }); | ||
| return createHash('sha256').update(canonical).digest('base64url'); | ||
| // === output helpers (stdout = result, stderr = errors) === | ||
| function printResult(value) { | ||
| const json = JSON.stringify(value, null, 2); | ||
| // Color only at a TTY; piped/redirected or NO_COLOR stays plain so ANSI codes | ||
| // never reach `jq` or an agent reading the JSON. | ||
| const useColor = process.stdout.isTTY === true && !process.env.NO_COLOR; | ||
| console.log(useColor ? colorizeJson(json) : json); | ||
| } | ||
| function parseArgs(args) { | ||
| const flags = {}; | ||
| const positional = []; | ||
| // Alias map: short flag → canonical flag | ||
| const aliases = { ps: 'person-server' }; | ||
| for (let i = 0; i < args.length; i++) { | ||
| if (args[i].startsWith('--') && i + 1 < args.length && !args[i + 1].startsWith('--')) { | ||
| const key = aliases[args[i].slice(2)] ?? args[i].slice(2); | ||
| flags[key] = args[i + 1]; | ||
| i++; | ||
| } | ||
| else if (args[i].startsWith('--')) { | ||
| const key = aliases[args[i].slice(2)] ?? args[i].slice(2); | ||
| flags[key] = 'true'; | ||
| } | ||
| else { | ||
| positional.push(args[i]); | ||
| } | ||
| } | ||
| return { flags, positional }; | ||
| function fail(message) { | ||
| console.error(JSON.stringify({ error: message })); | ||
| process.exitCode = 1; | ||
| } | ||
| // === Commands === | ||
| function cmdDiscover(flags) { | ||
| const onEvent = buildLogEmitter(flags.log === 'true'); | ||
| onEvent?.({ step: 'backend_discovery', phase: 'start' }); | ||
| const backends = discoverBackends(); | ||
| onEvent?.({ step: 'backend_discovery', phase: 'done', backends: backends.map(b => b.backend) }); | ||
| console.log(JSON.stringify(backends, null, 2)); | ||
| // === shared helpers === | ||
| /** Read a flag's value as a string, or undefined if absent/boolean. */ | ||
| function flagStr(flags, key) { | ||
| return typeof flags[key] === 'string' ? flags[key] : undefined; | ||
| } | ||
| async function cmdGenerate(flags) { | ||
| const backend = (flags.backend || 'software'); | ||
| const algorithm = (flags.algorithm || (backend === 'software' ? 'EdDSA' : 'ES256')); | ||
| const agentUrl = flags.agent; | ||
| const kid = generateKid(); | ||
| const onEvent = buildLogEmitter(flags.log === 'true'); | ||
| const driver = getBackend(backend); | ||
| const deviceLabel = driver.getDeviceLabel(); | ||
| onEvent?.({ step: 'key_generation', phase: 'start', backend, algorithm }); | ||
| let publicJwk; | ||
| if (backend === 'software') { | ||
| const { privateJwk, publicJwk: pubJwk } = await generateKey(); | ||
| const actualKid = pubJwk.kid || kid; | ||
| publicJwk = { | ||
| ...toPublicJwk(pubJwk), | ||
| kid: actualKid, | ||
| aauth: { device: deviceLabel, created: new Date().toISOString().slice(0, 10) }, | ||
| }; | ||
| if (agentUrl) { | ||
| ensureAgentUrls(agentUrl); | ||
| const existing = readKeychain(agentUrl); | ||
| const data = existing ?? { current: actualKid, keys: {} }; | ||
| data.current = actualKid; | ||
| data.keys[actualKid] = privateJwk; | ||
| writeKeychain(agentUrl, data); | ||
| addKeyToAgent(agentUrl, actualKid, { | ||
| backend: 'software', | ||
| algorithm: 'EdDSA', | ||
| keyId: actualKid, | ||
| deviceLabel, | ||
| }); | ||
| } | ||
| /** Best-effort public JWK for a configured key (software from keychain, hardware from the device). */ | ||
| async function resolvePublicJwk(agentUrl, kid, meta) { | ||
| if (meta.backend === 'software') { | ||
| const data = readKeychain(agentUrl); | ||
| const jwk = data?.keys[kid]; | ||
| return jwk ? toPublicJwk(jwk) : null; | ||
| } | ||
| else { | ||
| const keyRef = await driver.generateKey(algorithm); | ||
| publicJwk = { | ||
| ...keyRef.publicJwk, | ||
| kid, | ||
| aauth: { device: deviceLabel, created: new Date().toISOString().slice(0, 10) }, | ||
| }; | ||
| if (agentUrl) { | ||
| ensureAgentUrls(agentUrl); | ||
| addKeyToAgent(agentUrl, kid, { | ||
| backend, | ||
| algorithm, | ||
| keyId: keyRef.keyId, | ||
| deviceLabel, | ||
| }); | ||
| } | ||
| try { | ||
| return await getBackend(meta.backend).getPublicKey(meta.keyId); | ||
| } | ||
| onEvent?.({ step: 'key_generation', phase: 'done', kid: publicJwk.kid, backend, algorithm }); | ||
| console.log(JSON.stringify({ kid: publicJwk.kid, publicJwk }, null, 2)); | ||
| } | ||
| async function cmdSignToken(flags) { | ||
| const agentUrl = flags.agent; | ||
| const lifetime = parseInt(flags.lifetime || '3600', 10); | ||
| const onEvent = buildLogEmitter(flags.log === 'true'); | ||
| if (!agentUrl) { | ||
| console.error(JSON.stringify({ error: '--agent <url> required' })); | ||
| process.exitCode = 1; | ||
| return; | ||
| catch { | ||
| return null; | ||
| } | ||
| // Resolve agent identifier from --agent-id flag or config | ||
| const agentId = flags['agent-id'] ?? getAgentConfig(agentUrl)?.agentId; | ||
| if (!agentId) { | ||
| console.error(JSON.stringify({ error: 'No agent identifier. Run bootstrap with --ps first, or pass --agent-id.' })); | ||
| process.exitCode = 1; | ||
| return; | ||
| } | ||
| onEvent?.({ step: 'sign_token', phase: 'start', agentUrl, agentId, lifetime }); | ||
| const result = await signAgentToken({ agentUrl, sub: agentId, lifetime }); | ||
| // Decode the signed agent token to surface its claims under --log. | ||
| const parts = result.signatureKey.jwt.split('.'); | ||
| let decoded; | ||
| if (parts.length >= 2) { | ||
| try { | ||
| decoded = JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf8')); | ||
| } | ||
| catch { /* ignore */ } | ||
| } | ||
| onEvent?.({ step: 'sign_token', phase: 'done', agent_token: decoded }); | ||
| console.log(JSON.stringify(result, null, 2)); | ||
| } | ||
| async function cmdPublicKey(flags) { | ||
| const agentUrl = flags.agent; | ||
| if (!agentUrl) { | ||
| const backends = discoverBackends(); | ||
| const allKeys = []; | ||
| for (const info of backends) { | ||
| const driver = getBackend(info.backend); | ||
| try { | ||
| const keys = await driver.listKeys(); | ||
| for (const k of keys) { | ||
| if (k.publicJwk && k.publicJwk.kty) { | ||
| allKeys.push({ backend: k.backend, keyId: k.keyId, publicJwk: k.publicJwk }); | ||
| } | ||
| } | ||
| } | ||
| catch { /* skip */ } | ||
| /** | ||
| * Re-attach the `aauth` metadata (device + created) that `create` publishes, so | ||
| * `list` shows the same public-key shape. `created` comes from the kid's date | ||
| * prefix (`YYYY-MM-DD_hex`); `device` from the stored key metadata. | ||
| */ | ||
| function withAauthMeta(pub, meta, kid) { | ||
| if (!pub || typeof pub !== 'object') | ||
| return pub; | ||
| const created = kid.includes('_') ? kid.split('_')[0] : undefined; | ||
| return { ...pub, aauth: { device: meta.deviceLabel, created } }; | ||
| } | ||
| // === commands === | ||
| async function cmdList() { | ||
| const keystores = shapeKeystores(discoverBackends()); | ||
| const agentProviders = []; | ||
| for (const url of listAgentProviders()) { | ||
| const cfg = getAgentConfig(url); | ||
| if (!cfg) | ||
| continue; | ||
| const keys = []; | ||
| for (const [kid, meta] of Object.entries(cfg.keys)) { | ||
| const publicJwk = withAauthMeta(await resolvePublicJwk(url, kid, meta), meta, kid); | ||
| keys.push({ kid, keystore: meta.backend, publicJwk }); | ||
| } | ||
| console.log(JSON.stringify(allKeys, null, 2)); | ||
| return; | ||
| agentProviders.push({ | ||
| url, | ||
| agentId: cfg.agentId ?? null, | ||
| personServer: cfg.personServerUrl ?? null, | ||
| keys, | ||
| }); | ||
| } | ||
| try { | ||
| const resolved = await resolveKey(agentUrl); | ||
| const driver = getBackend(resolved.backend); | ||
| const pubJwk = await driver.getPublicKey(resolved.keyId); | ||
| console.log(JSON.stringify(pubJwk, null, 2)); | ||
| } | ||
| catch (e) { | ||
| console.error(JSON.stringify({ error: e.message })); | ||
| process.exitCode = 1; | ||
| } | ||
| printResult({ keystores, agentProviders }); | ||
| } | ||
| function cmdAddAgent(flags, positional) { | ||
| const agentUrl = positional[1]; | ||
| if (!agentUrl) { | ||
| console.error(JSON.stringify({ error: 'agent URL required' })); | ||
| process.exitCode = 1; | ||
| return; | ||
| async function cmdCreate(positional, flags) { | ||
| const url = positional[1]; | ||
| if (!url) | ||
| return fail('Usage: create <agent-provider-url>'); | ||
| const urlError = validateUrl(url); | ||
| if (urlError) | ||
| return fail(`${url} — ${urlError}`); | ||
| const existing = getAgentConfig(url); | ||
| if (existing && Object.keys(existing.keys).length > 0) { | ||
| return fail(`Agent provider already exists: ${url} (delete it first to re-create)`); | ||
| } | ||
| const urlError = validateUrl(agentUrl); | ||
| if (urlError) { | ||
| console.error(JSON.stringify({ error: `${agentUrl} — ${urlError}` })); | ||
| process.exitCode = 1; | ||
| return; | ||
| const { keystore, algorithm } = resolveKeystoreAlgorithm(flagStr(flags, 'keystore'), flagStr(flags, 'algorithm')); | ||
| const personServer = flagStr(flags, 'person-server') ?? DEFAULT_PERSON_SERVER; | ||
| const local = flagStr(flags, 'local'); | ||
| const driver = getBackend(keystore); | ||
| const deviceLabel = driver.getDeviceLabel(); | ||
| const created = new Date().toISOString().slice(0, 10); | ||
| ensureAgentUrls(url); | ||
| let kid; | ||
| let publicJwk; | ||
| if (keystore === 'software') { | ||
| const { privateJwk, publicJwk: pub } = await generateKey(algorithm === 'ES256' ? 'ES256' : 'EdDSA'); | ||
| kid = pub.kid; | ||
| publicJwk = { ...pub, aauth: { device: deviceLabel, created } }; | ||
| writeKeychain(url, { current: kid, keys: { [kid]: privateJwk } }); | ||
| addKeyToAgent(url, kid, { backend: 'software', algorithm, keyId: kid, deviceLabel }); | ||
| } | ||
| ensureAgentUrls(agentUrl); | ||
| if (flags['jwks-uri']) { | ||
| const existing = getAgentConfig(agentUrl); | ||
| setAgentConfig(agentUrl, { ...existing, jwksUri: flags['jwks-uri'] }); | ||
| else { | ||
| const ref = await driver.generateKey(algorithm); | ||
| kid = generateKid(); | ||
| publicJwk = { ...ref.publicJwk, kid, aauth: { device: deviceLabel, created } }; | ||
| addKeyToAgent(url, kid, { backend: keystore, algorithm, keyId: ref.keyId, deviceLabel }); | ||
| } | ||
| if (flags.hosting) { | ||
| setHosting(agentUrl, { | ||
| platform: flags.hosting, | ||
| repo: flags.repo, | ||
| }); | ||
| } | ||
| if (flags.kid && flags.backend && flags['key-id']) { | ||
| addKeyToAgent(agentUrl, flags.kid, { | ||
| backend: flags.backend, | ||
| algorithm: (flags.algorithm || 'ES256'), | ||
| keyId: flags['key-id'], | ||
| deviceLabel: flags.device || 'unknown', | ||
| }); | ||
| } | ||
| const config = getAgentConfig(agentUrl); | ||
| console.log(JSON.stringify({ agentUrl, config }, null, 2)); | ||
| // Bind a person server (fetches + validates its metadata, persists agentId + ps). | ||
| const psError = validateUrl(personServer); | ||
| if (psError) | ||
| return fail(`person-server: ${personServer} — ${psError}`); | ||
| await bootstrapWithPS({ agentUrl: url, personServerUrl: personServer, local }); | ||
| const cfg = getAgentConfig(url); | ||
| printResult({ | ||
| agentProvider: url, | ||
| agentId: cfg?.agentId ?? null, | ||
| personServer: cfg?.personServerUrl ?? null, | ||
| keys: [{ kid, keystore, publicJwk }], | ||
| }); | ||
| } | ||
| function cmdConfig() { | ||
| console.log(JSON.stringify(readConfig(), null, 2)); | ||
| } | ||
| function cmdShow(flags = {}) { | ||
| const onEvent = buildLogEmitter(flags.log === 'true'); | ||
| console.log('@aauth/bootstrap — set up an agent identity for AAuth'); | ||
| console.log(''); | ||
| const backends = discoverBackends(); | ||
| onEvent?.({ step: 'backends_discovered', phase: 'info', backends }); | ||
| console.log('Available backends:'); | ||
| for (const b of backends) { | ||
| console.log(` ${b.backend} — ${b.description} [${b.algorithms.join(', ')}]`); | ||
| } | ||
| const agents = listConfiguredAgents(); | ||
| onEvent?.({ step: 'agents_listed', phase: 'info', agents }); | ||
| if (agents.length > 0) { | ||
| console.log('\nConfigured agents:'); | ||
| for (const url of agents) { | ||
| const ac = getAgentConfig(url); | ||
| if (!ac) | ||
| continue; | ||
| console.log(` ${url}`); | ||
| if (ac.personServerUrl) | ||
| console.log(` person-server: ${ac.personServerUrl}`); | ||
| for (const [kid, meta] of Object.entries(ac.keys)) { | ||
| console.log(` ${kid} [${meta.algorithm}] ${meta.backend} (${meta.deviceLabel})`); | ||
| } | ||
| async function cmdDelete(positional) { | ||
| const url = positional[1]; | ||
| if (!url) | ||
| return fail('Usage: delete <agent-provider-url>'); | ||
| const cfg = getAgentConfig(url); | ||
| if (!cfg) | ||
| return fail(`Agent provider not found: ${url}`); | ||
| let keysDeleted = 0; | ||
| const hardwareKeysRetained = []; | ||
| // Software keys are grouped under the agent URL in the OS keychain — wipe in one shot. | ||
| if (readKeychain(url)) | ||
| deleteKeychain(url); | ||
| for (const [kid, meta] of Object.entries(cfg.keys)) { | ||
| if (meta.backend === 'software') { | ||
| keysDeleted++; | ||
| continue; | ||
| } | ||
| } | ||
| const urls = listAgentUrls(); | ||
| onEvent?.({ step: 'keychain_scanned', phase: 'info', urls }); | ||
| if (urls.length > 0) { | ||
| console.log('\nSoftware keys in keychain:'); | ||
| for (const url of urls) { | ||
| const data = readKeychain(url); | ||
| if (!data) | ||
| continue; | ||
| for (const [kid, jwk] of Object.entries(data.keys)) { | ||
| const marker = kid === data.current ? ' (current)' : ''; | ||
| const alg = jwk.crv === 'P-256' ? 'ES256' : 'EdDSA'; | ||
| console.log(` ${url} ${kid}${marker} [${alg}]`); | ||
| const driver = getBackend(meta.backend); | ||
| try { | ||
| await driver.deleteKey?.(meta.keyId); | ||
| keysDeleted++; | ||
| } | ||
| catch (e) { | ||
| if (e instanceof KeyDeletionUnsupportedError) { | ||
| hardwareKeysRetained.push({ kid, keystore: meta.backend, keyId: meta.keyId, hint: e.hint }); | ||
| } | ||
| else { | ||
| throw e; | ||
| } | ||
| } | ||
| } | ||
| // Getting-started footer: shown for both `bootstrap` (no command) and `bootstrap show`. | ||
| console.log(''); | ||
| if (agents.length === 0) { | ||
| console.log('No agents configured yet. Quick start (use your own agent URL):'); | ||
| console.log(' npx @aauth/bootstrap generate --agent https://me.github.io --ps'); | ||
| console.log(' (generates a key, then binds the default person server person.hello.coop)'); | ||
| deleteAgentProvider(url); | ||
| const result = { deleted: url, keysDeleted }; | ||
| if (hardwareKeysRetained.length > 0) | ||
| result.hardwareKeysRetained = hardwareKeysRetained; | ||
| printResult(result); | ||
| } | ||
| async function cmdToken(flags) { | ||
| const { url, error } = resolveProvider(flagStr(flags, 'agent-provider'), listAgentProviders()); | ||
| if (error || !url) | ||
| return fail(error ?? 'No agent provider configured.'); | ||
| const agentId = resolveAgentId({ | ||
| explicit: flagStr(flags, 'agent-id'), | ||
| local: flagStr(flags, 'local'), | ||
| host: new URL(url).hostname, | ||
| configAgentId: getAgentConfig(url)?.agentId, | ||
| }); | ||
| if (!agentId) { | ||
| return fail(`No agent identifier for ${url}. Pass --agent-id, or run \`create\` to configure one.`); | ||
| } | ||
| else { | ||
| console.log('Try calling an AAuth-protected resource:'); | ||
| console.log(' npx @aauth/fetch https://whoami.aauth.dev --log'); | ||
| } | ||
| console.log(''); | ||
| console.log('Common commands:'); | ||
| console.log(' npx @aauth/bootstrap discover List available key backends'); | ||
| console.log(' npx @aauth/bootstrap generate [opts] Generate a signing key'); | ||
| console.log(' npx @aauth/bootstrap --ps [url] Configure a person server (default: person.hello.coop)'); | ||
| console.log(' npx @aauth/bootstrap sign-token Sign a one-off agent_token'); | ||
| console.log(' npx @aauth/bootstrap help Full help'); | ||
| const lifetime = resolveLifetime(flagStr(flags, 'lifetime')); | ||
| const result = await signAgentToken({ agentUrl: url, sub: agentId, lifetime }); | ||
| printResult(result); | ||
| } | ||
| function cmdSkill(name) { | ||
| if (!name) { | ||
| console.log(JSON.stringify(listSkills(), null, 2)); | ||
| console.log(renderSkillListMarkdown(listSkills())); | ||
| return; | ||
| } | ||
| const skill = getSkill(name); | ||
| if (!skill) { | ||
| console.error(JSON.stringify({ error: `Unknown skill: "${name}"` })); | ||
| process.exitCode = 1; | ||
| return; | ||
| } | ||
| console.log(skill.body); | ||
| if (!skill) | ||
| return fail(`Unknown skill: "${name}". Run \`skill\` to list available skills.`); | ||
| console.log(withProtocolSpec(skill.body)); | ||
| } | ||
| function cmdHelp() { | ||
| console.log(`Usage: npx @aauth/bootstrap <command> [options] | ||
| Commands: | ||
| discover List available key backends (JSON) | ||
| generate [options] Generate a key pair, output public JWK (JSON) | ||
| sign-token [options] Sign an agent token with ephemeral cnf (JSON) | ||
| public-key [options] Output public key(s) (JSON) | ||
| add-agent <url> [opts] Register an agent URL in config | ||
| config Dump ~/.aauth/config.json | ||
| show Human-readable status overview | ||
| skill List available skills (JSON) | ||
| skill <name> Show full skill instructions | ||
| help Show this help | ||
| --version Print version and exit | ||
| Generate options: | ||
| --backend <name> software (default), yubikey-piv, secure-enclave | ||
| --algorithm <alg> EdDSA (default for software), ES256, RS256 | ||
| --agent <url> Associate key with an agent URL | ||
| Sign-token options: | ||
| --agent <url> Agent URL (required) | ||
| --agent-id <id> Agent identifier (default: from config) | ||
| --lifetime <seconds> Token lifetime (default: 3600) | ||
| Add-agent options: | ||
| --kid <kid> Key ID to associate | ||
| --backend <name> Key backend | ||
| --key-id <id> Backend-specific key ID (slot, label, etc.) | ||
| --algorithm <alg> Key algorithm | ||
| Person server configuration (can be combined with any command): | ||
| --person-server [url] Person server URL (alias: --ps; default: https://person.hello.coop) | ||
| --local <name> Local part of agent identifier (default: "local") | ||
| Output: | ||
| --log Narrate each step on stderr (JSONL) | ||
| Examples: | ||
| npx @aauth/bootstrap discover | ||
| npx @aauth/bootstrap generate --backend yubikey-piv | ||
| npx @aauth/bootstrap generate --backend secure-enclave --agent https://me.github.io | ||
| npx @aauth/bootstrap sign-token --agent https://me.github.io | ||
| npx @aauth/bootstrap add-agent https://me.github.io | ||
| npx @aauth/bootstrap --ps (defaults to https://person.hello.coop) | ||
| npx @aauth/bootstrap --ps https://person.example | ||
| npx @aauth/bootstrap generate --agent https://me.github.io --ps | ||
| npx @aauth/bootstrap public-key --agent https://me.github.io`); | ||
| } | ||
| async function runBootstrapPS(flags) { | ||
| // The arg parser stores a value-less `--ps` as the string 'true'. Treat that | ||
| // (or an empty value) as "use the default Person Server" so `bootstrap --ps` | ||
| // works without typing the URL. | ||
| const psFlag = flags['person-server']; | ||
| if (!psFlag) | ||
| function cmdHelp(command) { | ||
| if (command && COMMAND_HELP[command]) { | ||
| console.log(COMMAND_HELP[command]); | ||
| return; | ||
| const personServerUrl = psFlag === 'true' ? DEFAULT_PERSON_SERVER : psFlag; | ||
| const urlError = validateUrl(personServerUrl); | ||
| if (urlError) { | ||
| console.error(JSON.stringify({ error: `person-server: ${personServerUrl} — ${urlError}` })); | ||
| process.exitCode = 1; | ||
| return; | ||
| } | ||
| // Resolve agent URL from --agent flag or sole configured agent | ||
| let agentUrl = flags.agent; | ||
| if (!agentUrl) { | ||
| const configured = listConfiguredAgents(); | ||
| if (configured.length === 1) { | ||
| agentUrl = configured[0]; | ||
| } | ||
| else if (configured.length === 0) { | ||
| console.error(JSON.stringify({ error: 'No agent configured. Use --agent <url> or run add-agent first.' })); | ||
| process.exitCode = 1; | ||
| return; | ||
| } | ||
| else { | ||
| console.error(JSON.stringify({ error: 'Multiple agents configured. Use --agent <url> to specify.' })); | ||
| process.exitCode = 1; | ||
| return; | ||
| } | ||
| } | ||
| const logEnabled = flags.log === 'true'; | ||
| const onEvent = buildLogEmitter(logEnabled); | ||
| if (logEnabled) { | ||
| onEvent?.({ step: 'bootstrap_started', phase: 'info', agentUrl, personServerUrl }); | ||
| // Surface the existing keypair (if any) so Step 0 can show agent identity. | ||
| const keychain = readKeychain(agentUrl); | ||
| if (keychain) { | ||
| const currentKid = keychain.current; | ||
| const jwk = keychain.keys[currentKid]; | ||
| if (jwk) { | ||
| onEvent?.({ | ||
| step: 'key_info', | ||
| phase: 'info', | ||
| kid: currentKid, | ||
| publicJwk: { kty: jwk.kty, crv: jwk.crv, x: jwk.x }, | ||
| jkt: computeJkt(jwk), | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| else { | ||
| console.error(`Configuring ${agentUrl} with person server ${personServerUrl}...`); | ||
| } | ||
| await bootstrapWithPS({ | ||
| agentUrl, | ||
| personServerUrl, | ||
| local: flags.local, | ||
| onEvent, | ||
| }); | ||
| if (logEnabled) { | ||
| onEvent?.({ | ||
| step: 'bootstrap_complete', | ||
| phase: 'info', | ||
| note: 'Person binding happens on the agent\'s first authorized request', | ||
| }); | ||
| } | ||
| else { | ||
| console.error('Person server configured. Person binding will happen on the agent\'s first authorized request.'); | ||
| } | ||
| console.log(topLevelHelp(pkg.version)); | ||
| } | ||
| // === entrypoint === | ||
| async function run() { | ||
| const { flags, positional } = parseArgs(process.argv.slice(2)); | ||
| if (flags.version === 'true') { | ||
| const { command, positional, flags, help, version } = parseArgs(process.argv.slice(2)); | ||
| if (version) { | ||
| console.log(pkg.version); | ||
| return; | ||
| } | ||
| const command = positional[0]; | ||
| if (!command) { | ||
| // No command: if --person-server is present, bootstrap; otherwise show status + getting-started | ||
| if (flags['person-server']) { | ||
| await runBootstrapPS(flags); | ||
| return; | ||
| } | ||
| cmdShow(flags); | ||
| // Bare invocation or no recognized command → top-level help. | ||
| if (!command || command === 'help') { | ||
| cmdHelp(positional[1]); | ||
| return; | ||
| } | ||
| // `<command> --help` / `-h` → that command's help. | ||
| if (help) { | ||
| cmdHelp(command); | ||
| return; | ||
| } | ||
| switch (command) { | ||
| case 'discover': | ||
| cmdDiscover(flags); | ||
| case 'list': | ||
| await cmdList(); | ||
| break; | ||
| case 'generate': | ||
| await cmdGenerate(flags); | ||
| case 'create': | ||
| await cmdCreate(positional, flags); | ||
| break; | ||
| case 'sign-token': | ||
| await cmdSignToken(flags); | ||
| case 'delete': | ||
| await cmdDelete(positional); | ||
| break; | ||
| case 'public-key': | ||
| await cmdPublicKey(flags); | ||
| case 'token': | ||
| await cmdToken(flags); | ||
| break; | ||
| case 'add-agent': | ||
| cmdAddAgent(flags, positional); | ||
| break; | ||
| case 'config': | ||
| cmdConfig(); | ||
| break; | ||
| case 'show': | ||
| cmdShow(flags); | ||
| break; | ||
| case 'skill': | ||
| cmdSkill(positional[1]); | ||
| break; | ||
| case 'help': | ||
| cmdHelp(); | ||
| break; | ||
| default: | ||
| console.error(`Unknown command: ${command}`); | ||
| cmdHelp(); | ||
| process.exitCode = 1; | ||
| fail(`Unknown command: ${command}. Run \`npx @aauth/bootstrap help\`.`); | ||
| } | ||
| // After any command, run PS bootstrap if --person-server is present | ||
| if (flags['person-server'] && process.exitCode !== 1) { | ||
| await runBootstrapPS(flags); | ||
| } | ||
| } | ||
| run().catch((err) => { | ||
| console.error(JSON.stringify({ error: err.message })); | ||
| process.exitCode = 1; | ||
| fail(err.message); | ||
| }); | ||
| //# sourceMappingURL=cli.js.map |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACZ,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,aAAa,EAEb,UAAU,EACV,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,UAAU,EACV,WAAW,EACX,eAAe,GAChB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAwB,CAAA;AAEpF,+EAA+E;AAC/E,MAAM,qBAAqB,GAAG,2BAA2B,CAAA;AAEzD,SAAS,UAAU,CAAC,GAA4B;IAC9C,MAAM,GAAG,GAAG,GAAG,CAAC,GAAa,CAAA;IAC7B,MAAM,GAAG,GAAG,GAAG,CAAC,GAAa,CAAA;IAC7B,MAAM,CAAC,GAAG,GAAG,CAAC,CAAW,CAAA;IACzB,MAAM,CAAC,GAAG,GAAG,CAAC,CAAuB,CAAA;IACrC,MAAM,SAAS,GAAG,GAAG,KAAK,IAAI;QAC5B,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACpC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;IACnC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;AACnE,CAAC;AAED,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,KAAK,GAA2B,EAAE,CAAA;IACxC,MAAM,UAAU,GAAa,EAAE,CAAA;IAC/B,yCAAyC;IACzC,MAAM,OAAO,GAA2B,EAAE,EAAE,EAAE,eAAe,EAAE,CAAA;IAC/D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrF,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;YACzD,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YACxB,CAAC,EAAE,CAAA;QACL,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;YACzD,KAAK,CAAC,GAAG,CAAC,GAAG,MAAM,CAAA;QACrB,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAA;AAC9B,CAAC;AAED,mBAAmB;AAEnB,SAAS,WAAW,CAAC,KAA6B;IAChD,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC,CAAA;IACrD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;IACxD,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAA;IACnC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAC/F,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;AAChD,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,KAA6B;IACtD,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,UAAU,CAAe,CAAA;IAC3D,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAiB,CAAA;IACnG,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAA;IAC5B,MAAM,GAAG,GAAG,WAAW,EAAE,CAAA;IACzB,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC,CAAA;IAErD,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,CAAA;IAClC,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,EAAE,CAAA;IAE3C,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAA;IAEzE,IAAI,SAAyB,CAAA;IAE7B,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;QAC3B,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,WAAW,EAAE,CAAA;QAC7D,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,IAAI,GAAG,CAAA;QACnC,SAAS,GAAG;YACV,GAAG,WAAW,CAAC,MAAM,CAAC;YACtB,GAAG,EAAE,SAAS;YACd,KAAK,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;SAC/E,CAAA;QAED,IAAI,QAAQ,EAAE,CAAC;YACb,eAAe,CAAC,QAAQ,CAAC,CAAA;YACzB,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAA;YACvC,MAAM,IAAI,GAAG,QAAQ,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,CAAA;YACzD,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA;YACxB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,UAAU,CAAA;YACjC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;YAE7B,aAAa,CAAC,QAAQ,EAAE,SAAS,EAAE;gBACjC,OAAO,EAAE,UAAU;gBACnB,SAAS,EAAE,OAAO;gBAClB,KAAK,EAAE,SAAS;gBAChB,WAAW;aACZ,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;QAClD,SAAS,GAAG;YACV,GAAG,MAAM,CAAC,SAAS;YACnB,GAAG;YACH,KAAK,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;SAC/E,CAAA;QAED,IAAI,QAAQ,EAAE,CAAC;YACb,eAAe,CAAC,QAAQ,CAAC,CAAA;YACzB,aAAa,CAAC,QAAQ,EAAE,GAAG,EAAE;gBAC3B,OAAO;gBACP,SAAS;gBACT,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,WAAW;aACZ,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAA;IAC5F,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;AACzE,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,KAA6B;IACvD,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAA;IAC5B,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,IAAI,MAAM,EAAE,EAAE,CAAC,CAAA;IACvD,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC,CAAA;IAErD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC,CAAC,CAAA;QAClE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;QACpB,OAAM;IACR,CAAC;IAED,0DAA0D;IAC1D,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IACtE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,yEAAyE,EAAE,CAAC,CAAC,CAAA;QACnH,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;QACpB,OAAM;IACR,CAAC;IAED,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAA;IAC9E,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAA;IACzE,mEAAmE;IACnE,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAChD,IAAI,OAAgB,CAAA;IACpB,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC;YAAC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAC1G,CAAC;IACD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAA;IACtE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;AAC9C,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,KAA6B;IACvD,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAA;IAC5B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAA;QACnC,MAAM,OAAO,GAAkE,EAAE,CAAA;QACjF,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACvC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAA;gBACpC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;oBACrB,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;wBACnC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAA;oBAC9E,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;QAC7C,OAAM;IACR,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAA;QAC3C,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC3C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;QACxD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;IAC9C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QAC9D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;IACtB,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAA6B,EAAE,UAAoB;IACtE,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA;IAC9B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAA;QAC9D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;QACpB,OAAM;IACR,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;IACtC,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,GAAG,QAAQ,MAAM,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAA;QACrE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;QACpB,OAAM;IACR,CAAC;IAED,eAAe,CAAC,QAAQ,CAAC,CAAA;IAEzB,IAAI,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QACtB,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;QACzC,cAAc,CAAC,QAAQ,EAAE,EAAE,GAAG,QAAS,EAAE,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IACxE,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,UAAU,CAAC,QAAQ,EAAE;YACnB,QAAQ,EAAE,KAAK,CAAC,OAAO;YACvB,IAAI,EAAE,KAAK,CAAC,IAAI;SACjB,CAAC,CAAA;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClD,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,EAAE;YACjC,OAAO,EAAE,KAAK,CAAC,OAAqB;YACpC,SAAS,EAAE,CAAC,KAAK,CAAC,SAAS,IAAI,OAAO,CAAiB;YACvD,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC;YACtB,WAAW,EAAE,KAAK,CAAC,MAAM,IAAI,SAAS;SACvC,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;IACvC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;AAC5D,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;AACpD,CAAC;AAED,SAAS,OAAO,CAAC,QAAgC,EAAE;IACjD,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC,CAAA;IAErD,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAA;IACpE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAEf,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAA;IACnC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAA;IACnE,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAA;IAClC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,MAAM,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC/E,CAAC;IAED,MAAM,MAAM,GAAG,oBAAoB,EAAE,CAAA;IACrC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IAC3D,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAA;QACnC,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAA;YAC9B,IAAI,CAAC,EAAE;gBAAE,SAAQ;YACjB,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,CAAA;YACvB,IAAI,EAAE,CAAC,eAAe;gBAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC,eAAe,EAAE,CAAC,CAAA;YAC/E,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClD,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,KAAK,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,WAAW,GAAG,CAAC,CAAA;YACrF,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAG,aAAa,EAAE,CAAA;IAC5B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;IAC5D,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAA;QAC3C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;YAC9B,IAAI,CAAC,IAAI;gBAAE,SAAQ;YACnB,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,MAAM,MAAM,GAAG,GAAG,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAA;gBACvD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAA;gBACnD,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,IAAI,GAAG,GAAG,MAAM,KAAK,GAAG,GAAG,CAAC,CAAA;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IAED,wFAAwF;IACxF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAA;QAC9E,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAA;QAChF,OAAO,CAAC,GAAG,CAAC,6EAA6E,CAAC,CAAA;IAC5F,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAA;QACvD,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAA;IAClE,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;IAC/B,OAAO,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAA;IAClF,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAA;IAC7E,OAAO,CAAC,GAAG,CAAC,gGAAgG,CAAC,CAAA;IAC7G,OAAO,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAA;IACjF,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAA;AAClE,CAAC;AAED,SAAS,QAAQ,CAAC,IAAa;IAC7B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;QAClD,OAAM;IACR,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC5B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,mBAAmB,IAAI,GAAG,EAAE,CAAC,CAAC,CAAA;QACpE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;QACpB,OAAM;IACR,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED,SAAS,OAAO;IACd,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+DA+CiD,CAAC,CAAA;AAChE,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,KAA6B;IACzD,6EAA6E;IAC7E,6EAA6E;IAC7E,gCAAgC;IAChC,MAAM,MAAM,GAAG,KAAK,CAAC,eAAe,CAAC,CAAA;IACrC,IAAI,CAAC,MAAM;QAAE,OAAM;IACnB,MAAM,eAAe,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,MAAM,CAAA;IAE1E,MAAM,QAAQ,GAAG,WAAW,CAAC,eAAe,CAAC,CAAA;IAC7C,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,kBAAkB,eAAe,MAAM,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAA;QAC3F,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;QACpB,OAAM;IACR,CAAC;IAED,+DAA+D;IAC/D,IAAI,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAA;IAC1B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,UAAU,GAAG,oBAAoB,EAAE,CAAA;QACzC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA;QAC1B,CAAC;aAAM,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,gEAAgE,EAAE,CAAC,CAAC,CAAA;YAC1G,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;YACpB,OAAM;QACR,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,2DAA2D,EAAE,CAAC,CAAC,CAAA;YACrG,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;YACpB,OAAM;QACR,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,KAAK,MAAM,CAAA;IACvC,MAAM,OAAO,GAAG,eAAe,CAAC,UAAU,CAAC,CAAA;IAE3C,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC,CAAA;QAElF,2EAA2E;QAC3E,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAA;QACvC,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAA;YACnC,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAuC,CAAA;YAC3E,IAAI,GAAG,EAAE,CAAC;gBACR,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,UAAU;oBAChB,KAAK,EAAE,MAAM;oBACb,GAAG,EAAE,UAAU;oBACf,SAAS,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE;oBACnD,GAAG,EAAE,UAAU,CAAC,GAAG,CAAC;iBACrB,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,eAAe,QAAQ,uBAAuB,eAAe,KAAK,CAAC,CAAA;IACnF,CAAC;IAED,MAAM,eAAe,CAAC;QACpB,QAAQ;QACR,eAAe;QACf,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO;KACR,CAAC,CAAA;IAEF,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,EAAE,CAAC;YACR,IAAI,EAAE,oBAAoB;YAC1B,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,iEAAiE;SACxE,CAAC,CAAA;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,gGAAgG,CAAC,CAAA;IACjH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,GAAG;IAChB,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAE9D,IAAI,KAAK,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QACxB,OAAM;IACR,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA;IAE7B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,gGAAgG;QAChG,IAAI,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC;YAC3B,MAAM,cAAc,CAAC,KAAK,CAAC,CAAA;YAC3B,OAAM;QACR,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,CAAA;QACd,OAAM;IACR,CAAC;IAED,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,UAAU;YAAE,WAAW,CAAC,KAAK,CAAC,CAAC;YAAC,MAAK;QAC1C,KAAK,UAAU;YAAE,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC;YAAC,MAAK;QAChD,KAAK,YAAY;YAAE,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;YAAC,MAAK;QACnD,KAAK,YAAY;YAAE,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;YAAC,MAAK;QACnD,KAAK,WAAW;YAAE,WAAW,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YAAC,MAAK;QACvD,KAAK,QAAQ;YAAE,SAAS,EAAE,CAAC;YAAC,MAAK;QACjC,KAAK,MAAM;YAAE,OAAO,CAAC,KAAK,CAAC,CAAC;YAAC,MAAK;QAClC,KAAK,OAAO;YAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;YAAC,MAAK;QAC5C,KAAK,MAAM;YAAE,OAAO,EAAE,CAAC;YAAC,MAAK;QAC7B;YACE,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAA;YAC5C,OAAO,EAAE,CAAA;YACT,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;IACxB,CAAC;IAED,oEAAoE;IACpE,IAAI,KAAK,CAAC,eAAe,CAAC,IAAI,OAAO,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QACrD,MAAM,cAAc,CAAC,KAAK,CAAC,CAAA;IAC7B,CAAC;AACH,CAAC;AAED,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAClB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;IACrD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;AACtB,CAAC,CAAC,CAAA"} | ||
| {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"} |
+2
-2
| { | ||
| "name": "@aauth/bootstrap", | ||
| "version": "0.11.3", | ||
| "version": "1.0.0", | ||
| "description": "CLI for bootstrapping AAuth agent keys and configuration", | ||
@@ -33,4 +33,4 @@ "type": "module", | ||
| "dependencies": { | ||
| "@aauth/local-keys": "^0.11.1" | ||
| "@aauth/local-keys": "^1.0.0" | ||
| } | ||
| } |
+28
-54
@@ -10,12 +10,13 @@ # @aauth/bootstrap | ||
| ```bash | ||
| # Generate keys, bind the default person server (person.hello.coop), and walk through hosting setup | ||
| npx @aauth/bootstrap generate --agent <your-agent-url> --ps | ||
| # Register an agent provider: generate a key, bind it, and bind the default | ||
| # person server (person.hello.coop) — all in one command. | ||
| npx @aauth/bootstrap create <your-agent-provider-url> | ||
| # ...or point at a specific person server | ||
| npx @aauth/bootstrap generate --agent <your-agent-url> --ps https://person.example | ||
| # ...or pick a keystore and person server | ||
| npx @aauth/bootstrap create <your-agent-provider-url> --keystore secure-enclave --person-server https://person.example | ||
| ``` | ||
| `--ps` with no URL binds the default person server (`https://person.hello.coop`). Once an agent exists, you can re-run just `npx @aauth/bootstrap --ps` to (re)configure its person server. | ||
| `create` detects available keystores (YubiKey PIV, macOS Secure Enclave, software), generates a key in the chosen one (default: software/EdDSA), binds it to the agent provider, and binds a person server. Then load a skill to publish your keys on GitHub Pages, GitLab Pages, Cloudflare Pages, or Netlify. | ||
| The bootstrap flow detects available key backends (YubiKey PIV, macOS Secure Enclave, software), generates keys on the strongest available backend, configures a person server for your agent, and bundles agent skills that walk you through publishing keys on platforms like GitHub Pages, GitLab Pages, Cloudflare Pages, and Netlify. | ||
| Output is **pretty-printed JSON** on stdout (pipe it to `jq`); errors are `{ "error": "…" }` on stderr with a non-zero exit. Help and `skill` output are markdown. | ||
@@ -27,46 +28,22 @@ Per [draft-hardt-aauth-bootstrap §Self-Hosted Enrollment](https://github.com/dickhardt/AAuth), publication of the JWKS is the enrollment — there is no separate enrollment step. Person binding to a user happens lazily on the agent's first authorized request, per [§Agent-Person Binding](https://github.com/dickhardt/AAuth) in the protocol spec. | ||
| ``` | ||
| npx @aauth/bootstrap <command> [options] | ||
| npx @aauth/bootstrap <command> [flags] | ||
| Commands: | ||
| discover List available key backends (JSON) | ||
| generate [options] Generate a key pair, output public JWK (JSON) | ||
| sign-token [options] Sign an agent token with ephemeral cnf (JSON) | ||
| public-key [options] Output public key(s) (JSON) | ||
| add-agent <url> [opts] Register an agent URL in config | ||
| config Dump ~/.aauth/config.json | ||
| show Human-readable status overview | ||
| skill List available skills (JSON) | ||
| skill <name> Show full skill instructions | ||
| help Show this help | ||
| list | ||
| List agent providers, their keys, and available keystores | ||
| create <agent-provider-url> [--keystore <name>] [--algorithm <alg>] [--person-server <url>] | ||
| Register an agent provider (generates its first key, binds a person server) | ||
| delete <agent-provider-url> | ||
| Delete an agent provider and its keys (incl. from software & Secure Enclave keystores) | ||
| token [--agent-provider <url>] [--agent-id <id>] [--local <name>] [--lifetime <s>] | ||
| Generate an agent token | ||
| skill [name] | ||
| Print agent setup guides (markdown) | ||
| help [command] | ||
| Show help for a command | ||
| ``` | ||
| ### Generate options | ||
| `--help` (`-h`) and `--version` work as well. Run `npx @aauth/bootstrap list` to see which keystores and algorithms this machine supports. | ||
| ``` | ||
| --backend <name> software (default), yubikey-piv, secure-enclave | ||
| --algorithm <alg> EdDSA (default for software), ES256, RS256 | ||
| --agent <url> Associate key with an agent URL | ||
| ``` | ||
| > **Note:** `delete` removes software and Secure Enclave keys for real. A YubiKey PIV key can't be wiped programmatically yet — `delete` removes the binding and reports the slot to clear manually (`ykman piv keys delete 9e`). | ||
| ### Sign-token options | ||
| ``` | ||
| --agent <url> Agent URL (required) | ||
| --agent-id <id> Agent identifier (default: from config) | ||
| --lifetime <seconds> Token lifetime (default: 3600) | ||
| ``` | ||
| ### Person server bootstrap | ||
| Can be combined with any command: | ||
| ``` | ||
| --person-server [url] Bootstrap with person server (alias: --ps; default: https://person.hello.coop) | ||
| --local <name> Local part of agent identifier (default: "local") | ||
| --login-hint <hint> Hint about who to authorize | ||
| --domain-hint <domain> Domain/org routing hint | ||
| --provider-hint <name> Upstream identity provider hint | ||
| --tenant <id> Tenant identifier | ||
| ``` | ||
| ## For AI Agents | ||
@@ -77,18 +54,15 @@ | ||
| ```bash | ||
| # 1. Detect available hardware and software backends | ||
| npx @aauth/bootstrap discover | ||
| # 1. See available keystores + anything already configured | ||
| npx @aauth/bootstrap list | ||
| # 2. Check current state (existing agents, keys, hosting) | ||
| npx @aauth/bootstrap show | ||
| # 3. Load the setup skill for step-by-step instructions | ||
| # 2. Load the setup skill for step-by-step instructions | ||
| npx @aauth/bootstrap skill setup | ||
| # 4. List available hosting platform skills | ||
| # 3. List available hosting platform skills | ||
| npx @aauth/bootstrap skill | ||
| ``` | ||
| The `discover` output tells you what key backends are available on this machine. Use that — not assumptions — to guide key generation. Hardware backends (Secure Enclave, YubiKey) are always preferred over software (OS keychain). | ||
| The `keystores` array in `list` tells you what key keystores are available on this machine. Use that — not assumptions — to guide key generation. Hardware keystores (Secure Enclave, YubiKey) are always preferred over software (OS keychain). | ||
| The `skill` commands return structured instructions for the setup flow and each hosting platform. Load and follow these rather than improvising. | ||
| The `skill` commands return markdown instructions for the setup flow and each hosting platform. Load and follow these rather than improvising. | ||
@@ -95,0 +69,0 @@ ## Related Packages |
@@ -22,3 +22,3 @@ --- | ||
| - `@aauth/local-keys` is installed | ||
| - Keys have been generated (run `npx @aauth/bootstrap show` to check) | ||
| - Keys have been generated (run `npx @aauth/bootstrap list` to check) | ||
| - Cloudflare account | ||
@@ -41,3 +41,3 @@ - `wrangler` CLI installed (`npm install -g wrangler`) and authenticated (`wrangler login`), OR a git repo connected to Cloudflare Pages | ||
| ``` | ||
| npx @aauth/bootstrap public-key | ||
| npx @aauth/bootstrap list | ||
| ``` | ||
@@ -44,0 +44,0 @@ |
@@ -23,3 +23,3 @@ --- | ||
| - `@aauth/local-keys` is installed | ||
| - Keys have been generated (run `npx @aauth/bootstrap show` to check) | ||
| - Keys have been generated (run `npx @aauth/bootstrap list` to check) | ||
| - `gh` CLI is authenticated | ||
@@ -37,6 +37,6 @@ | ||
| ``` | ||
| npx @aauth/bootstrap public-key | ||
| npx @aauth/bootstrap list | ||
| ``` | ||
| This outputs all local public keys as JSON. Each key includes an `aauth` metadata object with `device` and `created` fields. | ||
| Take the public key from `agentProviders[].keys[].publicJwk` in the output (it's also returned directly by `create` as `keys[0].publicJwk`). Each key includes an `aauth` metadata object with `device` and `created` fields. | ||
@@ -43,0 +43,0 @@ ### 3. Locate or create the GitHub Pages repo |
@@ -23,3 +23,3 @@ --- | ||
| - `@aauth/local-keys` is installed | ||
| - Keys have been generated (run `npx @aauth/bootstrap show` to check) | ||
| - Keys have been generated (run `npx @aauth/bootstrap list` to check) | ||
| - GitLab account | ||
@@ -40,3 +40,3 @@ - `glab` CLI installed and authenticated (`glab auth login`), OR `git` configured for GitLab | ||
| ``` | ||
| npx @aauth/bootstrap public-key | ||
| npx @aauth/bootstrap list | ||
| ``` | ||
@@ -43,0 +43,0 @@ |
@@ -22,3 +22,3 @@ --- | ||
| - `@aauth/local-keys` is installed | ||
| - Keys have been generated (run `npx @aauth/bootstrap show` to check) | ||
| - Keys have been generated (run `npx @aauth/bootstrap list` to check) | ||
| - Netlify account | ||
@@ -40,3 +40,3 @@ | ||
| ``` | ||
| npx @aauth/bootstrap public-key | ||
| npx @aauth/bootstrap list | ||
| ``` | ||
@@ -43,0 +43,0 @@ |
+85
-134
| --- | ||
| name: setup | ||
| description: Set up AAuth agent identity — generate signing keys, add keys from new devices, and publish to a hosting platform | ||
| when: User wants to create an AAuth agent identity, generate keys, add a key from a new device or hardware backend, or publish their agent metadata | ||
| description: Set up an AAuth agent provider identity — generate a signing key, bind a person server, and publish to a hosting platform | ||
| when: User wants to create an AAuth agent provider identity, generate a key, or publish their agent metadata | ||
| --- | ||
| # Skill: Set up AAuth agent identity | ||
| # Skill: Set up an AAuth agent provider identity | ||
| ## CRITICAL: Run discovery first — do not assume anything | ||
| ## CRITICAL: Run `list` first — do not assume anything | ||
| Before giving the user ANY guidance, you MUST run these commands and use the output to determine what is available: | ||
| Before giving the user ANY guidance, run this and use the output to see what | ||
| keystores this machine has and what is already configured: | ||
| ``` | ||
| npx @aauth/bootstrap discover | ||
| npx @aauth/bootstrap show | ||
| npx @aauth/bootstrap list | ||
| ``` | ||
| Do NOT assume which backends are available. Do NOT suggest EdDSA or OS keychain keys unless `discover` shows no hardware backends. The discovery output is the source of truth for what this machine supports. | ||
| The `keystores` array is the source of truth for what this machine supports. Do | ||
| NOT suggest a software/EdDSA key if a hardware keystore (secure-enclave, | ||
| yubikey-piv) is present — prefer hardware. | ||
| ## When to use | ||
| ## What `create` does | ||
| - First-time setup: the user wants to create an AAuth agent identity with signing keys | ||
| - Adding a key: the user has a new device (e.g. new YubiKey, new Mac) and wants to add its key to an existing agent identity | ||
| - Publishing: the user has generated keys and needs to publish them to their hosting platform | ||
| `create` is the whole first-time setup in one command. It: | ||
| ## Prerequisites | ||
| 1. generates a signing key in the chosen keystore, | ||
| 2. binds that key to the agent provider, and | ||
| 3. binds a person server (default `https://person.hello.coop`). | ||
| - `@aauth/local-keys` is installed | ||
| - For YubiKey: a YubiKey is plugged in | ||
| - For Secure Enclave: macOS with Apple Silicon | ||
| ``` | ||
| npx @aauth/bootstrap create <agent-provider-url> [--keystore <name>] [--algorithm <alg>] [--person-server <url>] | ||
| ``` | ||
| ## Key backend priority | ||
| It fails if the agent provider already exists — delete it first to re-create. | ||
| Always prefer hardware keys over software keys. Generate a key on ALL available hardware backends for redundancy — if one device is unavailable (e.g. YubiKey unplugged), the agent falls back to the next available key automatically. | ||
| ## Keystore priority | ||
| 1. **`yubikey-piv`** — YubiKey PIV slot 9e, no PIN required, ES256. Key lives in YubiKey hardware. | ||
| 2. **`secure-enclave`** — macOS Secure Enclave, ES256. Key lives in the Mac's secure hardware. | ||
| 3. **`software`** — OS keychain, EdDSA or ES256. Only use if no hardware is available. | ||
| Prefer hardware over software (the private key never leaves the device): | ||
| ## Determining the agent URL | ||
| 1. **`yubikey-piv`** — YubiKey PIV slot 9e, no PIN, ES256. | ||
| 2. **`secure-enclave`** — macOS Secure Enclave (Apple Silicon), ES256. | ||
| 3. **`software`** — OS keychain, EdDSA (default) or ES256. Use only if no hardware is present. | ||
| Before generating keys, you need the user's agent URL. This is the HTTPS URL where their agent metadata will be published. Ask the user: | ||
| Pick the keystore from the `keystores` array that `list` reported. | ||
| - If they have a domain they want to use, use that. | ||
| - If using GitHub Pages, ask for their GitHub username — the agent URL will be `https://username.github.io`. | ||
| - Run the platform detection commands (see step 4) to discover what hosting options are available and suggest accordingly. | ||
| ## Determining the agent provider URL | ||
| Do NOT pick a hosting platform or agent URL without asking the user. | ||
| The agent provider URL is the HTTPS URL where the agent metadata will be | ||
| published. Ask the user: | ||
| ## Adding a key to an existing agent | ||
| - If they have a domain, use it. | ||
| - If using GitHub Pages, ask for their GitHub username — the URL is `https://username.github.io`. | ||
| - Run the platform detection commands (below) to suggest hosting. | ||
| If the user already has an agent identity set up and wants to add a key from a new device (e.g. they got a new YubiKey, or they're on a new Mac with a Secure Enclave): | ||
| Do NOT pick a hosting platform or URL without asking the user. | ||
| 1. Check existing setup: `npx @aauth/bootstrap show` | ||
| 2. Discover backends: `npx @aauth/bootstrap discover` | ||
| 3. Generate a key on the new hardware: `npx @aauth/bootstrap generate --backend <backend> --agent <agent-url>` | ||
| 4. Add the new public key to the existing JWKS on the hosting platform (load the appropriate platform skill) | ||
| 5. The new key will be used automatically — key resolution matches any published key that has a local private key | ||
| ## First-time setup steps | ||
| ### 1. Discover available backends | ||
| ### 1. See what's available | ||
| Run: | ||
| ``` | ||
| npx @aauth/bootstrap discover | ||
| npx @aauth/bootstrap list | ||
| ``` | ||
| This returns a JSON array of available backends with their supported algorithms. You MUST run this and use the output — do not skip this step. | ||
| ### 2. Create the agent provider | ||
| ### 2. Generate keys on each available hardware backend | ||
| Pick the best available keystore and create the provider. Example with the | ||
| default software keystore: | ||
| For each hardware backend in the discovery output, generate a key and associate it with the agent URL: | ||
| ``` | ||
| npx @aauth/bootstrap generate --backend yubikey-piv --agent <agent-url> | ||
| npx @aauth/bootstrap generate --backend secure-enclave --agent <agent-url> | ||
| npx @aauth/bootstrap create https://username.github.io | ||
| ``` | ||
| Each command outputs JSON with: | ||
| - `kid` — key identifier to use in the JWKS | ||
| - `publicJwk` — the public key to publish, including `aauth.device` and `aauth.created` metadata | ||
| With a hardware keystore and a custom person server: | ||
| **Only generate a software key if no hardware backends are available:** | ||
| ``` | ||
| npx @aauth/bootstrap generate --agent <agent-url> | ||
| npx @aauth/bootstrap create https://username.github.io --keystore secure-enclave --person-server https://person.example | ||
| ``` | ||
| ### 3. Set the person server | ||
| The output includes `keys[0].publicJwk` — the public key you publish — plus the | ||
| resolved `agentId` and `personServer`. | ||
| The person server URL is included as the `ps` claim in agent tokens. Set it during setup: | ||
| ``` | ||
| npx @aauth/bootstrap add-agent <agent-url> --person-server <person-server-url> | ||
| ``` | ||
| ### 3. Choose a hosting platform | ||
| The agent MUST be configured with a person server URL. **Do not assume a default** — if the user hasn't specified one, ask them which PS to use before proceeding. | ||
| The public key must be published at `{agentProviderUrl}/.well-known/jwks.json`, | ||
| with agent metadata at `{agentProviderUrl}/.well-known/aauth-agent.json`, served | ||
| as static files over HTTPS. | ||
| ### 4. Choose a hosting platform | ||
| List the platform skills: | ||
| The generated public keys need to be published at `{agentUrl}/.well-known/jwks.json` along with agent metadata at `{agentUrl}/.well-known/aauth-agent.json`. The agent needs to serve these as static files over HTTPS. | ||
| **Load the list of supported platforms** by calling: | ||
| ```ts | ||
| import { listPlatforms } from '@aauth/local-keys' | ||
| const platforms = listPlatforms() | ||
| ``` | ||
| Or via CLI: | ||
| ``` | ||
| npx @aauth/bootstrap skill | ||
| ``` | ||
| Platform skills are in `skills/platforms/`. Each platform's front matter includes discovery metadata: | ||
| Each platform skill's front matter includes discovery metadata: | ||
| - `detect_cli` — CLI tool to check for (e.g. `gh`, `glab`, `wrangler`) | ||
| - `detect_auth` — command to check if authenticated | ||
| - `detect_existing` — command to check for an existing site (uses `{username}` placeholder) | ||
| - `pros` / `cons` — trade-offs to present to the user | ||
| - `agentUrlPattern` — what the agent URL will look like | ||
| - `detect_existing` — command to check for an existing site (uses `{username}`) | ||
| - `pros` / `cons` — trade-offs to present | ||
| - `agentUrlPattern` — what the URL will look like | ||
| **Discovery flow:** | ||
| **Discovery flow** — for each platform: run `<detect_cli>`; if it succeeds, run | ||
| `<detect_auth>`; if authenticated and `detect_existing` is set, substitute | ||
| `{username}` and run it. | ||
| For each platform, run the detection commands: | ||
| 1. Run `<detect_cli>` — if it succeeds, the CLI is available | ||
| 2. If available, run `<detect_auth>` — check if authenticated (look for "not authenticated" or similar in output to detect unauthenticated state) | ||
| 3. If authenticated and `detect_existing` is set, substitute `{username}` and run to check for an existing site | ||
| **Present results** organized by availability: Ready (CLI + auth + maybe a site) | ||
| first, then Available (CLI but not authenticated), then Not detected. Mention | ||
| that any static HTTPS host works — the required files are | ||
| `/.well-known/aauth-agent.json` and `/.well-known/jwks.json`. | ||
| **Presenting the results to the user:** | ||
| ### 4. Publish using the platform skill | ||
| Present ALL platforms to the user, organized by availability: | ||
| ``` | ||
| npx @aauth/bootstrap skill <platform-name> | ||
| ``` | ||
| 1. **Ready** — CLI installed, authenticated, possibly an existing site. Recommend these first. | ||
| 2. **Available** — CLI installed but not authenticated. Mention what command to run to log in. | ||
| 3. **Not detected** — CLI not installed. Still present these as options with their pros/cons. The user may want to install one, or may already have an account on the platform's website. | ||
| Follow the skill to publish `jwks.json` (containing `keys[0].publicJwk` from | ||
| step 2) and `aauth-agent.json`. | ||
| Also mention that any static HTTPS hosting works — the platforms with skills just have step-by-step instructions. If the user has a different hosting provider (Netlify, Vercel, S3+CloudFront, their own server, etc.), they can still publish the `.well-known/` files manually. The required files are: | ||
| - `/.well-known/aauth-agent.json` — agent metadata with `jwks_uri` | ||
| - `/.well-known/jwks.json` — public key set | ||
| ### 5. Verify | ||
| **Recommendation logic:** | ||
| - If one platform is fully ready (CLI + auth + existing site) → suggest that first | ||
| - If multiple are ready → present the choices with pros/cons and let the user choose | ||
| - If none are ready but some are available → suggest logging in to the simplest one | ||
| - If none are detected → recommend GitHub Pages (lowest barrier) but present all options | ||
| After the user chooses, register the hosting platform: | ||
| ``` | ||
| npx @aauth/bootstrap add-agent <agent-url> --hosting <platform> --repo <repo-identifier> | ||
| npx @aauth/bootstrap list | ||
| ``` | ||
| ### 5. Publish keys using the platform skill | ||
| Confirm the provider, its key, person server, and agentId are present. | ||
| Load the full instructions for the chosen platform: | ||
| ``` | ||
| npx @aauth/bootstrap skill <platform-name> | ||
| ``` | ||
| ### 6. Use it | ||
| Follow the skill instructions to publish the keys. | ||
| Mint an agent token, or just make an authenticated request: | ||
| ### 6. Verify setup | ||
| ``` | ||
| npx @aauth/bootstrap show | ||
| npx @aauth/bootstrap token | ||
| npx @aauth/fetch https://whoami.aauth.dev | ||
| ``` | ||
| This shows all configured agents, their keys, and which backends are available. | ||
| ## How key resolution works | ||
| When `@aauth/local-keys` signs an agent token, it resolves a key automatically through this fallback chain: | ||
| When `@aauth/local-keys` signs an agent token it resolves a key automatically: | ||
| 1. **Fetch JWKS** — fetches `{agentUrl}/.well-known/aauth-agent.json` to find `jwks_uri`, then fetches the JWKS. Tolerates network failure gracefully. | ||
| 1. **Fetch JWKS** — `{agentProviderUrl}/.well-known/aauth-agent.json` → `jwks_uri` → JWKS. Tolerates network failure. | ||
| 2. **Discover local keys** — scans all keystores; only keys on currently-available hardware are found. | ||
| 3. **Match JWKS against local keys** — by JWK thumbprint, preferring hardware. | ||
| 4. **Fall back to config** — `~/.aauth/config.json`, skipping unavailable keystores. | ||
| 5. **Fall back to any local hardware key**, then **any local software key** (just-created, not yet published). | ||
| 2. **Discover local keys** — scans all backends (YubiKey, Secure Enclave, OS keychain). Only keys on hardware that is currently available are found. If a YubiKey is unplugged, its keys silently don't appear. | ||
| 3. **Match JWKS against local keys** — compares JWK thumbprints between published keys and local keys. Prefers hardware matches over software. Any hardware match is used immediately. | ||
| 4. **Fall back to config** — checks `~/.aauth/config.json` for registered keys. Skips entries whose backend is unavailable (e.g. YubiKey unplugged). Verifies the key actually exists before using it. Prefers hardware over software. | ||
| 5. **Fall back to any local hardware key** — for bootstrap (key just generated, not yet published). | ||
| 6. **Fall back to any local software key** — backward compatibility with older setups. | ||
| 7. **Error** — no key found, with a helpful message to run `generate`. | ||
| Each step tolerates failure and falls through. Hardware keys are always preferred. | ||
| ## How signing works | ||
| When `createAgentToken({ delegate: 'claude' })` is called: | ||
| 1. The agent URL is resolved from the call, or defaults to the first configured agent in `~/.aauth/config.json`, or the first agent URL in the OS keychain. | ||
| 2. A signing key is resolved using the fallback chain above. | ||
| 3. An ephemeral key pair is generated (software, ES256 or EdDSA). | ||
| 4. The agent token JWT is signed by the resolved root key, with the ephemeral public key in the `cnf` claim. | ||
| 5. The ephemeral private key and signed JWT are returned. | ||
| For hardware backends, the root key signing happens in hardware — the private key never exists in process memory. | ||
| ## Notes | ||
| - Generate keys on ALL available hardware backends for redundancy. | ||
| - Software keys are a last resort — they store the private key in the OS keychain, not hardware. | ||
| - The `aauth.device` field in the public JWK is auto-derived from the machine hostname or YubiKey name. It helps identify stale keys in the JWKS but is not sensitive. | ||
| - After generating keys, publish them using the skill for your chosen hosting platform. | ||
| - v1 sets up **one key per agent provider**. Adding more keys (e.g. one per | ||
| machine for multi-device redundancy) is a planned capability, not yet a CLI | ||
| command. | ||
| - `delete <agent-provider-url>` removes the provider and wipes its software and | ||
| Secure Enclave keys. A YubiKey PIV key can't be wiped programmatically yet — | ||
| `delete` reports the slot to clear manually (`ykman piv keys delete 9e`). | ||
| - The `aauth.device` field in the public JWK is auto-derived from the machine or | ||
| YubiKey name. It helps identify stale keys; it is not sensitive. |
| export interface BootstrapEvent { | ||
| step: string; | ||
| phase: 'start' | 'done' | 'info'; | ||
| [key: string]: unknown; | ||
| } | ||
| export type OnBootstrapEvent = (event: BootstrapEvent) => void; | ||
| /** | ||
| * Build a stream-aware bootstrap event handler. | ||
| * | ||
| * When stderr is a TTY: prints TL;DR + Step 0 grouped card, then writes a | ||
| * marker file so a subsequent `fetch --log` can suppress its own TL;DR. | ||
| * | ||
| * When stderr is piped: emits NDJSON (one line per event) as before. | ||
| */ | ||
| export declare function buildLogEmitter(enabled: boolean): OnBootstrapEvent | undefined; | ||
| export declare function logEvent(enabled: boolean, event: BootstrapEvent): void; | ||
| //# sourceMappingURL=log.d.ts.map |
| {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAA;AA+K9D;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CA2E9E;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI,CAGtE"} |
-245
| import { homedir } from 'node:os'; | ||
| import { join } from 'node:path'; | ||
| import { writeFileSync, mkdirSync } from 'node:fs'; | ||
| const MARKER_PATH = join(homedir(), '.aauth', '.tldr-shown'); | ||
| // ── ANSI styling (TTY only, respects NO_COLOR) ──────────────────────────────── | ||
| const IS_TTY = process.stderr.isTTY === true || process.env.AAUTH_FORCE_PRETTY === '1'; | ||
| const COLOR_ENABLED = IS_TTY && !process.env.NO_COLOR; | ||
| const c = { | ||
| dim: (s) => COLOR_ENABLED ? `\x1b[2m${s}\x1b[0m` : s, | ||
| bold: (s) => COLOR_ENABLED ? `\x1b[1m${s}\x1b[0m` : s, | ||
| cyan: (s) => COLOR_ENABLED ? `\x1b[36m${s}\x1b[0m` : s, | ||
| magenta: (s) => COLOR_ENABLED ? `\x1b[35m${s}\x1b[0m` : s, | ||
| green: (s) => COLOR_ENABLED ? `\x1b[32m${s}\x1b[0m` : s, | ||
| yellow: (s) => COLOR_ENABLED ? `\x1b[33m${s}\x1b[0m` : s, | ||
| red: (s) => COLOR_ENABLED ? `\x1b[31m${s}\x1b[0m` : s, | ||
| }; | ||
| const RULE = '─'.repeat(80); | ||
| const section = (title) => `${c.dim('─── ')}${c.bold(title)} ${c.dim(RULE.slice(title.length + 5))}`; | ||
| // ── TL;DR block (shown once at the top of bootstrap --ps --log) ─────────────── | ||
| function renderTldr() { | ||
| return [ | ||
| section('What is AAuth?'), | ||
| '', | ||
| 'AAuth gives every agent its own cryptographic identity. The agent signs every', | ||
| 'HTTP request with a private key only it holds; resources verify the signature', | ||
| 'and decide whether to authorize. A Person Server represents the user and', | ||
| 'grants the agent permission to act on their behalf — no pre-registration, no', | ||
| 'shared secrets.', | ||
| '', | ||
| 'Protocol parties:', | ||
| '', | ||
| ` ${c.cyan('AGENT')} this CLI on your device. Identifies via an Ed25519 keypair`, | ||
| ' generated locally — the private key never leaves the OS keychain.', | ||
| ` ${c.green('RESOURCE')} the API the agent wants to call.`, | ||
| ` ${c.magenta('PERSON SERVER')} represents the user. Holds identity, decides authorization,`, | ||
| ' issues auth_tokens the resource will trust.', | ||
| ` ${c.dim('ACCESS SERVER (out of scope for this demo) policy engine that guards')}`, | ||
| ` ${c.dim('resources in federated mode.')}`, | ||
| '', | ||
| 'The user (you) approves consent in a browser the first time the PS sees', | ||
| 'this agent.', | ||
| '', | ||
| 'The flow:', | ||
| '', | ||
| ` ${c.dim('one-time')} ${c.cyan('AGENT')} generates keypair on this device`, | ||
| ` ${c.cyan('AGENT')} registers a Person Server it will delegate consent to`, | ||
| ` ${c.dim('per call')} ${c.cyan('AGENT')} ─▶ ${c.green('RESOURCE')} (401: who are you?)`, | ||
| ` ${c.cyan('AGENT')} ─▶ ${c.magenta('PERSON SERVER')} (token exchange — first time needs consent)`, | ||
| ` ${c.yellow('user')} ─▶ ${c.magenta('PERSON SERVER')} (approve in browser, first time only)`, | ||
| ` ${c.cyan('AGENT')} ─▶ ${c.green('RESOURCE')} (200: data)`, | ||
| '', | ||
| `${c.dim('Key properties: agent identity without pre-registration · proof-of-possession')}`, | ||
| `${c.dim('on every request · user consent at the Person Server, never at the resource.')}`, | ||
| '', | ||
| `${c.dim("You're about to run the one-time setup.")}`, | ||
| '', | ||
| '', | ||
| ].join('\n'); | ||
| } | ||
| function shortHex(s, n = 16) { | ||
| if (!s) | ||
| return '…'; | ||
| return s.length <= n ? s : `${s.slice(0, n)}…`; | ||
| } | ||
| function renderJwk(jwk) { | ||
| const kty = jwk.kty; | ||
| const crv = jwk.crv; | ||
| const x = jwk.x; | ||
| return `{ kty: ${JSON.stringify(kty)}, crv: ${JSON.stringify(crv)}, x: ${JSON.stringify(shortHex(x, 24))} }`; | ||
| } | ||
| function renderStep0(state, hasNewKey) { | ||
| const lines = []; | ||
| lines.push(section('0. ONE-TIME SETUP')); | ||
| lines.push(''); | ||
| // Sub-bullet 1: keypair | ||
| if (hasNewKey && state.publicJwk && state.kid) { | ||
| lines.push(' • Generate Ed25519 keypair on this device — the private key stays in the OS'); | ||
| lines.push(' keychain and never leaves. The public key thumbprint is the agent\'s identity.'); | ||
| lines.push(''); | ||
| if (state.agentUrl) | ||
| lines.push(` ${c.bold('agent')} ${state.agentUrl}`); | ||
| if (state.kid) | ||
| lines.push(` ${c.bold('kid')} ${state.kid}`); | ||
| if (state.publicJwk) | ||
| lines.push(` ${c.bold('public key')} ${renderJwk(state.publicJwk)}`); | ||
| if (state.jkt) | ||
| lines.push(` ${c.bold('jkt')} ${state.jkt}`); | ||
| lines.push(''); | ||
| } | ||
| else if (state.agentUrl) { | ||
| lines.push(' • Use the existing keypair on this device — no new key generated.'); | ||
| lines.push(' The public key thumbprint below is this agent\'s identity.'); | ||
| lines.push(''); | ||
| lines.push(` ${c.bold('agent')} ${state.agentUrl}`); | ||
| if (state.kid) | ||
| lines.push(` ${c.bold('kid')} ${state.kid} ${c.dim('(current)')}`); | ||
| if (state.publicJwk) | ||
| lines.push(` ${c.bold('public key')} ${renderJwk(state.publicJwk)}`); | ||
| if (state.jkt) | ||
| lines.push(` ${c.bold('jkt')} ${state.jkt}`); | ||
| lines.push(''); | ||
| } | ||
| // Sub-bullet 2: PS metadata | ||
| if (state.metadataUrl) { | ||
| lines.push(' • Fetch Person Server metadata to confirm it\'s reachable and well-formed.'); | ||
| lines.push(''); | ||
| const url = new URL(state.metadataUrl); | ||
| lines.push(` ${c.bold('GET')} ${url.pathname} HTTP/1.1`); | ||
| lines.push(` ${c.bold('Host:')} ${url.host}`); | ||
| lines.push(''); | ||
| const statusColor = state.metadataStatus && state.metadataStatus < 300 ? c.green : c.red; | ||
| lines.push(` ${c.dim('←')} HTTP/1.1 ${statusColor(String(state.metadataStatus ?? '?'))} ${state.metadataStatus === 200 ? 'OK' : ''}`); | ||
| lines.push(` ${c.bold('Content-Type:')} application/json`); | ||
| if (state.metadataBody) { | ||
| const body = JSON.stringify(state.metadataBody, null, 2).split('\n').map(l => ` ${l}`).join('\n'); | ||
| lines.push(body); | ||
| } | ||
| lines.push(''); | ||
| } | ||
| if (state.personServerUrl) { | ||
| lines.push(` ${c.green('✓')} Bootstrap complete. The agent will bind to a user on its first authorized request.`); | ||
| lines.push(''); | ||
| } | ||
| return lines.join('\n'); | ||
| } | ||
| // ── Marker file ────────────────────────────────────────────────────────────── | ||
| function writeTldrMarker() { | ||
| try { | ||
| mkdirSync(join(homedir(), '.aauth'), { recursive: true }); | ||
| writeFileSync(MARKER_PATH, new Date().toISOString(), 'utf8'); | ||
| } | ||
| catch { | ||
| // Non-fatal — marker is purely a UX hint | ||
| } | ||
| } | ||
| // ── Public API ──────────────────────────────────────────────────────────────── | ||
| const narrations = { | ||
| backend_discovery: (e) => e.phase === 'start' | ||
| ? 'Discovering available key backends on this machine' | ||
| : `Found ${e.backends?.length ?? 0} backend(s)`, | ||
| key_generation: (e) => e.phase === 'start' | ||
| ? `Generating ${e.algorithm} key on ${e.backend} backend` | ||
| : `Generated key — kid ${e.kid}`, | ||
| ps_metadata_request: (e) => e.phase === 'start' | ||
| ? `Agent → Person Server: GET ${e.url}` | ||
| : `Person Server metadata received (${e.status})`, | ||
| ps_metadata_validated: () => 'Person Server metadata validated', | ||
| agent_config_persisted: (e) => `Agent configured: agentId=${e.agentId}, personServerUrl=${e.personServerUrl}`, | ||
| bootstrap_started: (e) => `Configuring ${e.agentUrl} with person server ${e.personServerUrl}`, | ||
| bootstrap_complete: () => 'Person server configured.', | ||
| sign_token: (e) => e.phase === 'start' ? `Signing agent_token` : 'Agent token signed', | ||
| }; | ||
| function formatNdjson(event) { | ||
| const narration = narrations[event.step]?.(event); | ||
| const line = narration ? { ...event, narration } : event; | ||
| return JSON.stringify(line) + '\n'; | ||
| } | ||
| /** | ||
| * Build a stream-aware bootstrap event handler. | ||
| * | ||
| * When stderr is a TTY: prints TL;DR + Step 0 grouped card, then writes a | ||
| * marker file so a subsequent `fetch --log` can suppress its own TL;DR. | ||
| * | ||
| * When stderr is piped: emits NDJSON (one line per event) as before. | ||
| */ | ||
| export function buildLogEmitter(enabled) { | ||
| if (!enabled) | ||
| return undefined; | ||
| const pretty = IS_TTY; | ||
| if (!pretty) { | ||
| // Piped — keep NDJSON shape for programmatic consumers. | ||
| return (event) => { | ||
| process.stderr.write(formatNdjson(event)); | ||
| }; | ||
| } | ||
| // TTY: collect events, render TL;DR once, then render Step 0 on completion. | ||
| let printedTldr = false; | ||
| const state = {}; | ||
| let hasNewKey = false; | ||
| let rendered = false; | ||
| function maybePrintTldr() { | ||
| if (!printedTldr) { | ||
| process.stderr.write(renderTldr()); | ||
| printedTldr = true; | ||
| } | ||
| } | ||
| function finalize() { | ||
| if (rendered) | ||
| return; | ||
| rendered = true; | ||
| process.stderr.write(renderStep0(state, hasNewKey)); | ||
| writeTldrMarker(); | ||
| } | ||
| return (event) => { | ||
| maybePrintTldr(); | ||
| switch (event.step) { | ||
| case 'bootstrap_started': | ||
| state.agentUrl = event.agentUrl; | ||
| state.personServerUrl = event.personServerUrl; | ||
| break; | ||
| case 'key_generation': | ||
| if (event.phase === 'start') { | ||
| hasNewKey = true; | ||
| state.algorithm = event.algorithm; | ||
| state.backend = event.backend; | ||
| } | ||
| else if (event.phase === 'done') { | ||
| state.kid = event.kid; | ||
| } | ||
| break; | ||
| case 'ps_metadata_request': | ||
| if (event.phase === 'start') { | ||
| state.metadataUrl = event.url; | ||
| } | ||
| else if (event.phase === 'done') { | ||
| state.metadataStatus = event.status; | ||
| // Body is not in the event — fetch it from a sibling source if needed | ||
| } | ||
| break; | ||
| case 'ps_metadata_body': | ||
| // Synthetic event for the rendered metadata body — emitted from bootstrap-ps | ||
| state.metadataBody = event.body; | ||
| break; | ||
| case 'agent_config_persisted': | ||
| state.agentId = event.agentId; | ||
| state.personServerUrl = event.personServerUrl ?? state.personServerUrl; | ||
| break; | ||
| case 'key_info': | ||
| // Synthetic event with full key details (kid, publicJwk, jkt) | ||
| state.kid = event.kid ?? state.kid; | ||
| state.publicJwk = event.publicJwk; | ||
| state.jkt = event.jkt; | ||
| break; | ||
| case 'bootstrap_complete': | ||
| finalize(); | ||
| break; | ||
| } | ||
| }; | ||
| } | ||
| export function logEvent(enabled, event) { | ||
| if (!enabled) | ||
| return; | ||
| buildLogEmitter(true)?.(event); | ||
| } | ||
| //# sourceMappingURL=log.js.map |
| {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"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"} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
47
74.07%1078
3.75%2
-33.33%5
-28.57%109295
-2.65%74
-26%2
100%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated