aismemory 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,206 @@
1
+ import { createServer } from 'node:http';
2
+ import { spawn } from 'node:child_process';
3
+ import { mkdtempSync, rmSync, existsSync } from 'node:fs';
4
+ import { tmpdir } from 'node:os';
5
+ import { join, resolve } from 'path';
6
+ import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
7
+ /**
8
+ * Regression: when the OAuth device-flow poll rejects (expired_token,
9
+ * access_denied, or 30-min deadline) the prior aismemory MCP would store the
10
+ * dead poll on `activeFlow` and every subsequent tool call would re-race
11
+ * against the rejected promise, propagating the same stale error. The only
12
+ * recovery was for the user to restart their AI tool — too friction-heavy for
13
+ * first-time users (they get distracted, the activation drops on the floor).
14
+ *
15
+ * After the fix, the MCP marks the flow `dead` on rejection and discards it,
16
+ * so the next tool call starts a fresh device flow inline and surfaces a new
17
+ * bond URL — no restart required.
18
+ *
19
+ * This test drives the binary against a fake AIS HTTP server that:
20
+ * - returns a unique user_code per `/v1/oauth/device/authorize` call
21
+ * - returns `expired_token` on the first `/v1/oauth/token` poll
22
+ * Two consecutive tool calls should produce two DIFFERENT user_codes in the
23
+ * surfaced bond URLs, proving the dead flow was discarded and replaced.
24
+ */
25
+ describe('aismemory MCP device-flow recovery', () => {
26
+ let fakeAisServer;
27
+ let fakeAisPort = 0;
28
+ let authorizeCalls = 0;
29
+ const issuedCodes = [];
30
+ beforeAll(async () => {
31
+ fakeAisServer = createServer((req, res) => {
32
+ req.on('data', () => { });
33
+ req.on('end', () => {
34
+ if (req.url === '/v1/oauth/device/authorize' && req.method === 'POST') {
35
+ authorizeCalls += 1;
36
+ const userCode = `TEST-${String(authorizeCalls).padStart(4, '0')}`;
37
+ issuedCodes.push(userCode);
38
+ res.writeHead(200, { 'content-type': 'application/json' });
39
+ res.end(JSON.stringify({
40
+ success: true,
41
+ data: {
42
+ device_code: `device-${authorizeCalls}`,
43
+ user_code: userCode,
44
+ verification_uri: `http://127.0.0.1:${fakeAisPort}/activate`,
45
+ verification_uri_complete: `http://127.0.0.1:${fakeAisPort}/activate?user_code=${userCode}`,
46
+ expires_in: 1800,
47
+ interval: 1, // 1s poll → bounded to 5s min by the client
48
+ agent_id: `agent-${authorizeCalls}`,
49
+ provisional_tenant_id: `tenant-${authorizeCalls}`,
50
+ provisional_token: 'provisional',
51
+ },
52
+ }));
53
+ return;
54
+ }
55
+ if (req.url === '/v1/oauth/token' && req.method === 'POST') {
56
+ // Always reject the poll so the flow dies and recovery kicks in.
57
+ res.writeHead(400, { 'content-type': 'application/json' });
58
+ res.end(JSON.stringify({ error: 'expired_token' }));
59
+ return;
60
+ }
61
+ res.writeHead(404);
62
+ res.end();
63
+ });
64
+ });
65
+ await new Promise((resolveServer) => {
66
+ fakeAisServer.listen(0, '127.0.0.1', () => {
67
+ const addr = fakeAisServer.address();
68
+ if (addr && typeof addr === 'object') {
69
+ fakeAisPort = addr.port;
70
+ }
71
+ resolveServer();
72
+ });
73
+ });
74
+ });
75
+ afterAll(async () => {
76
+ await new Promise((r) => fakeAisServer?.close(() => r()));
77
+ });
78
+ beforeEach(() => {
79
+ authorizeCalls = 0;
80
+ issuedCodes.length = 0;
81
+ });
82
+ it('starts a fresh device flow after the previous one dies', async () => {
83
+ const distPath = resolve(__dirname, '..', '..', 'dist', 'index.js');
84
+ if (!existsSync(distPath)) {
85
+ throw new Error(`dist/index.js missing — run \`pnpm build\` first (looked at ${distPath})`);
86
+ }
87
+ const fakeHome = mkdtempSync(join(tmpdir(), 'aismem-recover-'));
88
+ let proc = null;
89
+ try {
90
+ proc = spawn('node', [distPath], {
91
+ env: {
92
+ ...process.env,
93
+ HOME: fakeHome,
94
+ AIS_URL: `http://127.0.0.1:${fakeAisPort}`,
95
+ },
96
+ stdio: ['pipe', 'pipe', 'pipe'],
97
+ });
98
+ let stdoutBuf = '';
99
+ proc.stdout.on('data', (d) => { stdoutBuf += d.toString(); });
100
+ proc.stderr.on('data', () => { });
101
+ // 1. Handshake: initialize the MCP transport.
102
+ proc.stdin.write(JSON.stringify({
103
+ jsonrpc: '2.0',
104
+ id: 1,
105
+ method: 'initialize',
106
+ params: {
107
+ protocolVersion: '2024-11-05',
108
+ capabilities: {},
109
+ clientInfo: { name: 'recovery-test', version: '0.0.0' },
110
+ },
111
+ }) + '\n');
112
+ await waitFor(() => stdoutBuf.includes('"id":1'), 5000, 'initialize response');
113
+ // 2. First tool call triggers device flow #1. The poll will reject
114
+ // against the fake AIS (expired_token), marking the flow dead.
115
+ // The call surfaces BondPendingError with the first user_code.
116
+ proc.stdin.write(JSON.stringify({
117
+ jsonrpc: '2.0',
118
+ id: 2,
119
+ method: 'tools/call',
120
+ params: { name: 'whoami', arguments: {} },
121
+ }) + '\n');
122
+ await waitFor(() => stdoutBuf.includes('"id":2'), 15000, 'first whoami response');
123
+ const firstResponse = extractResponseText(stdoutBuf, 2);
124
+ // Give the poll time to actually reject — soft timeout is 7s, poll
125
+ // interval is min 5s, so the rejection lands ~5s after the call. We
126
+ // need that rejection observed before the second call so the `dead`
127
+ // flag is set when ensureCredentials runs again.
128
+ await new Promise((r) => setTimeout(r, 8000));
129
+ // 3. Second tool call — should detect the dead flow, start a fresh
130
+ // device flow, and surface a DIFFERENT user_code.
131
+ proc.stdin.write(JSON.stringify({
132
+ jsonrpc: '2.0',
133
+ id: 3,
134
+ method: 'tools/call',
135
+ params: { name: 'whoami', arguments: {} },
136
+ }) + '\n');
137
+ await waitFor(() => stdoutBuf.includes('"id":3'), 15000, 'second whoami response');
138
+ const secondResponse = extractResponseText(stdoutBuf, 3);
139
+ // Recovery proof: more than one device-flow authorize was made. Without
140
+ // the fix the MCP would re-race the dead poll forever and never call
141
+ // authorize a second time.
142
+ expect(authorizeCalls).toBeGreaterThanOrEqual(2);
143
+ expect(issuedCodes.length).toBeGreaterThanOrEqual(2);
144
+ // Both tool calls return a bond URL (no misleading "Authentication
145
+ // timed out" leak from the dead poll's stored rejection).
146
+ expect(firstResponse).toMatch(/Memory bond required/);
147
+ expect(secondResponse).toMatch(/Memory bond required/);
148
+ // The two responses must surface DIFFERENT codes — proving the second
149
+ // call doesn't keep showing the original (now-dead) code.
150
+ const firstCode = extractUserCode(firstResponse);
151
+ const secondCode = extractUserCode(secondResponse);
152
+ expect(firstCode).toBeTruthy();
153
+ expect(secondCode).toBeTruthy();
154
+ expect(firstCode).not.toEqual(secondCode);
155
+ expect(issuedCodes).toContain(firstCode);
156
+ expect(issuedCodes).toContain(secondCode);
157
+ }
158
+ finally {
159
+ proc?.kill();
160
+ try {
161
+ rmSync(fakeHome, { recursive: true, force: true });
162
+ }
163
+ catch { /* ignore */ }
164
+ }
165
+ }, 45000);
166
+ });
167
+ function waitFor(predicate, ms, label) {
168
+ return new Promise((resolveOuter, reject) => {
169
+ const start = Date.now();
170
+ const tick = () => {
171
+ if (predicate()) {
172
+ resolveOuter();
173
+ return;
174
+ }
175
+ if (Date.now() - start > ms) {
176
+ reject(new Error(`timeout waiting for ${label}`));
177
+ return;
178
+ }
179
+ setTimeout(tick, 50);
180
+ };
181
+ tick();
182
+ });
183
+ }
184
+ function extractUserCode(responseText) {
185
+ const match = /TEST-\d{4}/.exec(responseText);
186
+ return match ? match[0] : null;
187
+ }
188
+ function extractResponseText(buf, id) {
189
+ // MCP responses are newline-delimited JSON. Find the line with our id and
190
+ // pull the content[0].text payload out.
191
+ for (const line of buf.split('\n')) {
192
+ if (!line.includes(`"id":${id}`))
193
+ continue;
194
+ try {
195
+ const parsed = JSON.parse(line);
196
+ const text = parsed.result?.content?.[0]?.text;
197
+ if (typeof text === 'string')
198
+ return text;
199
+ }
200
+ catch {
201
+ /* malformed line; skip */
202
+ }
203
+ }
204
+ return '';
205
+ }
206
+ //# sourceMappingURL=device-flow-recovery.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-flow-recovery.test.js","sourceRoot":"","sources":["../../src/__tests__/device-flow-recovery.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,284 @@
1
+ /**
2
+ * Tests for the aismemory key-auth client module.
3
+ *
4
+ * Phase 1 DID-based authentication: the client reads an Ed25519 private key
5
+ * from disk, signs a challenge issued by AIS, and receives an owner JWT.
6
+ * Replaces the device-flow ceremony for every session after enrollment.
7
+ *
8
+ * Tests cover:
9
+ * - tryKeyAuth() returns null when no key file is present (so callers can
10
+ * gracefully fall back to device flow)
11
+ * - tryKeyAuth() round-trips a challenge against a fake AIS and returns
12
+ * the resulting owner JWT
13
+ * - generateAndSaveKeypair() writes a valid key file
14
+ * - readKeyFile() recovers what generateAndSaveKeypair() wrote
15
+ */
16
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
17
+ import { mkdtempSync, rmSync, existsSync, readFileSync, statSync } from 'node:fs';
18
+ import { tmpdir } from 'node:os';
19
+ import { join } from 'node:path';
20
+ import { createServer } from 'node:http';
21
+ import { createPublicKey, createPrivateKey, verify as edVerify } from 'node:crypto';
22
+ import { tryKeyAuth, generateAndSaveKeypair, readKeyFile, } from '../key-auth.js';
23
+ // ───────────────────────────────────────────────────────────────────────────
24
+ // Test fixtures
25
+ // ───────────────────────────────────────────────────────────────────────────
26
+ const TEST_USER_ID = '454e4306-423e-498d-9b85-24bafbabff9b';
27
+ const TEST_DOMAIN = 'ais.example.com';
28
+ const TEST_USER_DID = `did:web:${TEST_DOMAIN}:users:${TEST_USER_ID}`;
29
+ let tmpKeysDir;
30
+ beforeEach(() => {
31
+ tmpKeysDir = mkdtempSync(join(tmpdir(), 'aismemory-keys-test-'));
32
+ });
33
+ afterEach(() => {
34
+ if (existsSync(tmpKeysDir)) {
35
+ rmSync(tmpKeysDir, { recursive: true, force: true });
36
+ }
37
+ });
38
+ // ───────────────────────────────────────────────────────────────────────────
39
+ // Key file generation + read
40
+ // ───────────────────────────────────────────────────────────────────────────
41
+ describe('generateAndSaveKeypair', () => {
42
+ it('writes a Ed25519 key file containing matching public/private bytes', async () => {
43
+ const result = await generateAndSaveKeypair({
44
+ userId: TEST_USER_ID,
45
+ userDid: TEST_USER_DID,
46
+ keysDir: tmpKeysDir,
47
+ });
48
+ expect(result.userId).toBe(TEST_USER_ID);
49
+ expect(result.userDid).toBe(TEST_USER_DID);
50
+ expect(result.keyType).toBe('Ed25519');
51
+ expect(result.publicKey).toMatch(/^[A-Za-z0-9_-]+$/); // base64url
52
+ expect(result.privateKey).toMatch(/^[A-Za-z0-9_-]+$/);
53
+ expect(result.publicKeyJwk.kty).toBe('OKP');
54
+ expect(result.publicKeyJwk.crv).toBe('Ed25519');
55
+ // File must exist with mode 0600.
56
+ const path = join(tmpKeysDir, `${TEST_USER_DID}.json`);
57
+ expect(existsSync(path)).toBe(true);
58
+ const stat = statSync(path);
59
+ // Bottom 9 bits = perms. We only assert the user-only invariant
60
+ // (group/other have no perms). Skip on Windows where this isn't real.
61
+ if (process.platform !== 'win32') {
62
+ const perms = stat.mode & 0o777;
63
+ expect(perms).toBe(0o600);
64
+ }
65
+ const onDisk = JSON.parse(readFileSync(path, 'utf-8'));
66
+ expect(onDisk.userId).toBe(TEST_USER_ID);
67
+ });
68
+ });
69
+ describe('readKeyFile', () => {
70
+ it('returns null when no key file is present', () => {
71
+ const got = readKeyFile({ userDid: TEST_USER_DID, keysDir: tmpKeysDir });
72
+ expect(got).toBeNull();
73
+ });
74
+ it('returns the file we generated', async () => {
75
+ const written = await generateAndSaveKeypair({
76
+ userId: TEST_USER_ID,
77
+ userDid: TEST_USER_DID,
78
+ keysDir: tmpKeysDir,
79
+ });
80
+ const read = readKeyFile({ userDid: TEST_USER_DID, keysDir: tmpKeysDir });
81
+ expect(read).not.toBeNull();
82
+ expect(read?.userId).toBe(written.userId);
83
+ expect(read?.privateKey).toBe(written.privateKey);
84
+ });
85
+ });
86
+ /**
87
+ * Spawns a tiny HTTP server that simulates the AIS challenge/did-prove
88
+ * endpoints. The server actually verifies the Ed25519 signature so we know
89
+ * the client signed the correct canonical string with the right key.
90
+ */
91
+ async function startFakeAis(opts) {
92
+ const issued = { token: '' };
93
+ const server = createServer((req, res) => {
94
+ let body = '';
95
+ req.on('data', (chunk) => (body += chunk));
96
+ req.on('end', () => {
97
+ try {
98
+ if (req.method === 'POST' && req.url === '/v1/auth/challenge') {
99
+ const parsed = JSON.parse(body || '{}');
100
+ const nonce = `nonce-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
101
+ const exp = Math.floor(Date.now() / 1000) + (opts.forceExpiredChallenge ? -60 : 60);
102
+ // We don't actually HMAC here — the fake just echoes back a marker;
103
+ // the real server checks the HMAC, the fake doesn't need to.
104
+ res.statusCode = 200;
105
+ res.setHeader('Content-Type', 'application/json');
106
+ res.end(JSON.stringify({
107
+ success: true,
108
+ data: { nonce, exp, hmac: `fake-hmac-for:${parsed.userDid}` },
109
+ }));
110
+ return;
111
+ }
112
+ if (req.method === 'POST' && req.url === '/v1/auth/did-prove') {
113
+ const parsed = JSON.parse(body || '{}');
114
+ if (!parsed.userDid || !parsed.nonce || !parsed.exp || !parsed.signature) {
115
+ res.statusCode = 400;
116
+ res.end(JSON.stringify({ success: false, error: { code: 'BAD_REQUEST' } }));
117
+ return;
118
+ }
119
+ // Verify the signature against the accepted public key.
120
+ const msg = Buffer.from(`${parsed.userDid}\n${parsed.nonce}\n${parsed.exp}`, 'utf8');
121
+ const pub = createPublicKey({ key: opts.acceptedJwk, format: 'jwk' });
122
+ const ok = edVerify(null, msg, pub, Buffer.from(parsed.signature, 'base64url'));
123
+ if (!ok) {
124
+ res.statusCode = 401;
125
+ res.end(JSON.stringify({ success: false, error: { code: 'INVALID_SIGNATURE' } }));
126
+ return;
127
+ }
128
+ const token = `fake-owner-jwt-${Date.now()}`;
129
+ issued.token = token;
130
+ res.statusCode = 200;
131
+ res.setHeader('Content-Type', 'application/json');
132
+ res.end(JSON.stringify({
133
+ success: true,
134
+ data: {
135
+ bearerToken: token,
136
+ expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
137
+ },
138
+ }));
139
+ return;
140
+ }
141
+ res.statusCode = 404;
142
+ res.end(JSON.stringify({ error: 'not_found' }));
143
+ }
144
+ catch (e) {
145
+ res.statusCode = 500;
146
+ res.end(JSON.stringify({ error: e.message }));
147
+ }
148
+ });
149
+ });
150
+ await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
151
+ const addr = server.address();
152
+ if (!addr || typeof addr === 'string')
153
+ throw new Error('failed to bind');
154
+ const url = `http://127.0.0.1:${addr.port}`;
155
+ return {
156
+ url,
157
+ stop: () => new Promise((resolve) => {
158
+ server.close(() => resolve());
159
+ }),
160
+ get lastIssued() {
161
+ return issued.token || undefined;
162
+ },
163
+ };
164
+ }
165
+ describe('tryKeyAuth', () => {
166
+ it('returns null when no key file is present', async () => {
167
+ const result = await tryKeyAuth({
168
+ aisUrl: 'http://unreachable.example.com',
169
+ keysDir: tmpKeysDir,
170
+ userDid: TEST_USER_DID,
171
+ });
172
+ expect(result).toBeNull();
173
+ });
174
+ it('signs a real challenge and returns the issued bearer token', async () => {
175
+ // 1. Bootstrap a key file on disk.
176
+ const key = await generateAndSaveKeypair({
177
+ userId: TEST_USER_ID,
178
+ userDid: TEST_USER_DID,
179
+ keysDir: tmpKeysDir,
180
+ });
181
+ // 2. Stand up a fake AIS that accepts that exact public key.
182
+ const ais = await startFakeAis({ acceptedJwk: key.publicKeyJwk });
183
+ try {
184
+ // 3. Run the full challenge/prove flow.
185
+ const result = await tryKeyAuth({
186
+ aisUrl: ais.url,
187
+ keysDir: tmpKeysDir,
188
+ userDid: TEST_USER_DID,
189
+ });
190
+ expect(result).not.toBeNull();
191
+ expect(result?.userId).toBe(TEST_USER_ID);
192
+ expect(result?.userDid).toBe(TEST_USER_DID);
193
+ expect(result?.tokenType).toBe('owner');
194
+ expect(result?.token).toMatch(/^fake-owner-jwt-/);
195
+ expect(result?.expiresAt).toBeDefined();
196
+ }
197
+ finally {
198
+ await ais.stop();
199
+ }
200
+ });
201
+ it("throws when the server rejects the signature (e.g. user's key was revoked)", async () => {
202
+ // Generate two keypairs. Client has key A; server only accepts key B.
203
+ const clientKey = await generateAndSaveKeypair({
204
+ userId: TEST_USER_ID,
205
+ userDid: TEST_USER_DID,
206
+ keysDir: tmpKeysDir,
207
+ });
208
+ // Build a different keypair just to get a JWK the fake AIS will reject.
209
+ const tmpDir2 = mkdtempSync(join(tmpdir(), 'aismemory-otherkey-'));
210
+ const serverKey = await generateAndSaveKeypair({
211
+ userId: TEST_USER_ID,
212
+ userDid: TEST_USER_DID,
213
+ keysDir: tmpDir2,
214
+ });
215
+ // Voiding the unused-var lint while keeping the keypair around for clarity.
216
+ void clientKey;
217
+ rmSync(tmpDir2, { recursive: true, force: true });
218
+ const ais = await startFakeAis({ acceptedJwk: serverKey.publicKeyJwk });
219
+ try {
220
+ await expect(tryKeyAuth({
221
+ aisUrl: ais.url,
222
+ keysDir: tmpKeysDir,
223
+ userDid: TEST_USER_DID,
224
+ })).rejects.toThrow();
225
+ }
226
+ finally {
227
+ await ais.stop();
228
+ }
229
+ });
230
+ it('auto-discovers the userDid when only one key file is present', async () => {
231
+ // No userDid passed; the helper should pick the lone file.
232
+ const key = await generateAndSaveKeypair({
233
+ userId: TEST_USER_ID,
234
+ userDid: TEST_USER_DID,
235
+ keysDir: tmpKeysDir,
236
+ });
237
+ const ais = await startFakeAis({ acceptedJwk: key.publicKeyJwk });
238
+ try {
239
+ const result = await tryKeyAuth({
240
+ aisUrl: ais.url,
241
+ keysDir: tmpKeysDir,
242
+ });
243
+ expect(result).not.toBeNull();
244
+ expect(result?.userDid).toBe(TEST_USER_DID);
245
+ }
246
+ finally {
247
+ await ais.stop();
248
+ }
249
+ });
250
+ });
251
+ // ───────────────────────────────────────────────────────────────────────────
252
+ // Signing utility — verified by round-trip against Node's crypto
253
+ // ───────────────────────────────────────────────────────────────────────────
254
+ describe('canonical signing format', () => {
255
+ it("uses '<userDid>\\n<nonce>\\n<exp>' as the message body", async () => {
256
+ const key = await generateAndSaveKeypair({
257
+ userId: TEST_USER_ID,
258
+ userDid: TEST_USER_DID,
259
+ keysDir: tmpKeysDir,
260
+ });
261
+ // Re-derive the public key and verify a sample signature with the
262
+ // expected canonical form. If the implementation later changes the
263
+ // canonical bytes, this test breaks loudly.
264
+ const ais = await startFakeAis({ acceptedJwk: key.publicKeyJwk });
265
+ try {
266
+ const result = await tryKeyAuth({
267
+ aisUrl: ais.url,
268
+ keysDir: tmpKeysDir,
269
+ userDid: TEST_USER_DID,
270
+ });
271
+ expect(result).not.toBeNull();
272
+ }
273
+ finally {
274
+ await ais.stop();
275
+ }
276
+ // Smoke: private key actually loadable.
277
+ const priv = createPrivateKey({
278
+ key: { kty: 'OKP', crv: 'Ed25519', x: key.publicKeyJwk.x, d: key.privateKey },
279
+ format: 'jwk',
280
+ });
281
+ expect(priv).toBeDefined();
282
+ });
283
+ });
284
+ //# sourceMappingURL=key-auth.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-auth.test.js","sourceRoot":"","sources":["../../src/__tests__/key-auth.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,131 @@
1
+ /**
2
+ * `aismemory enable-key-auth` — one-shot enrollment for DID-based auth.
3
+ *
4
+ * Generates an Ed25519 keypair on the user's device, registers the public
5
+ * key with AIS, and writes the private key to `~/.aismemory/keys/`. After
6
+ * this runs once per device, every subsequent aismemory session authenticates
7
+ * silently with the key — no browser, no activation URL.
8
+ *
9
+ * Bootstrap requirements: the user needs a working bearer token from the
10
+ * existing device-flow credentials file (`~/.aismemory/credentials.json`).
11
+ * If absent, we tell them to run a normal aismemory session once first.
12
+ *
13
+ * Usage:
14
+ * npx aismemory enable-key-auth
15
+ * AIS_URL=https://other.example.com npx aismemory enable-key-auth
16
+ *
17
+ * Exit codes:
18
+ * 0 — key registered + saved
19
+ * 1 — bootstrap credentials missing or registration failed
20
+ */
21
+ import { readFileSync, existsSync } from 'node:fs';
22
+ import { join } from 'node:path';
23
+ import { homedir } from 'node:os';
24
+ import { generateAndSaveKeypair } from '../key-auth.js';
25
+ const PREFIX = '[aismemory enable-key-auth]';
26
+ function loadBootstrapCreds() {
27
+ const path = join(homedir(), '.aismemory', 'credentials.json');
28
+ if (!existsSync(path))
29
+ return null;
30
+ try {
31
+ return JSON.parse(readFileSync(path, 'utf-8'));
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ }
37
+ /**
38
+ * Decode a JWT payload WITHOUT verifying the signature. We trust the token
39
+ * because it came from our own credentials file — we just need its claims
40
+ * to know who we are.
41
+ */
42
+ function decodeJwtPayload(token) {
43
+ const parts = token.split('.');
44
+ if (parts.length !== 3)
45
+ throw new Error('Malformed JWT');
46
+ const json = Buffer.from(parts[1], 'base64url').toString('utf-8');
47
+ return JSON.parse(json);
48
+ }
49
+ function log(msg) {
50
+ process.stderr.write(`${PREFIX} ${msg}\n`);
51
+ }
52
+ async function main() {
53
+ const aisUrl = process.env['AIS_URL'] ?? 'https://ais.agentsandswarms.ai';
54
+ // 1. Find a bootstrap bearer token.
55
+ const creds = loadBootstrapCreds();
56
+ if (!creds) {
57
+ log('No bootstrap credentials found at ~/.aismemory/credentials.json');
58
+ log('Run `npx aismemory` first (and complete the bond URL) to get an initial token,');
59
+ log('then re-run this command.');
60
+ process.exit(1);
61
+ }
62
+ if (new Date(creds.expiresAt) <= new Date()) {
63
+ log('Bootstrap credentials at ~/.aismemory/credentials.json have expired.');
64
+ log('Run `npx aismemory` once to refresh them, then re-run this command.');
65
+ process.exit(1);
66
+ }
67
+ // 2. Extract userId from the JWT.
68
+ let payload;
69
+ try {
70
+ payload = decodeJwtPayload(creds.token);
71
+ }
72
+ catch (err) {
73
+ log(`Failed to decode bootstrap JWT: ${err.message}`);
74
+ process.exit(1);
75
+ }
76
+ const userId = payload.user_id ?? payload.sub;
77
+ if (!userId) {
78
+ log('Bootstrap JWT does not carry a user_id claim. This token may be agent-only —');
79
+ log('claim your agent to a user account first, then re-run.');
80
+ process.exit(1);
81
+ }
82
+ // Derive the userDid. The domain is the host portion of AIS_URL — strip
83
+ // the protocol so the resulting DID matches what AIS computes server-side.
84
+ const aisHost = new URL(aisUrl).host;
85
+ const userDid = `did:web:${aisHost}:users:${userId}`;
86
+ log(`AIS URL : ${aisUrl}`);
87
+ log(`userId : ${userId}`);
88
+ log(`userDid : ${userDid}`);
89
+ // 3. Generate keypair + write to disk.
90
+ const label = `${process.env['USER'] ?? 'user'}-${process.platform}`;
91
+ log('Generating Ed25519 keypair…');
92
+ const keyFile = await generateAndSaveKeypair({ userId, userDid });
93
+ // 4. POST public key to AIS.
94
+ log('Registering public key with AIS…');
95
+ const res = await fetch(`${aisUrl}/v1/users/me/keys`, {
96
+ method: 'POST',
97
+ headers: {
98
+ 'Content-Type': 'application/json',
99
+ Authorization: `Bearer ${creds.token}`,
100
+ },
101
+ body: JSON.stringify({
102
+ publicKey: keyFile.publicKeyJwk,
103
+ label,
104
+ }),
105
+ });
106
+ const body = (await res.json().catch(() => ({})));
107
+ if (!res.ok || !body.success) {
108
+ // Special-case: 409 = key already registered. Treat as success since we
109
+ // still wrote the file locally and the server already knows about us.
110
+ if (res.status === 409) {
111
+ log('Public key was already registered (server says 409 — duplicate).');
112
+ log('Local key file is up to date; no further action needed.');
113
+ process.exit(0);
114
+ }
115
+ log(`Failed to register key: HTTP ${res.status} ${body.error?.code ?? ''} ${body.error?.message ?? ''}`);
116
+ process.exit(1);
117
+ }
118
+ log('✓ Public key registered with AIS');
119
+ log(` key id : ${body.data?.id ?? '<unknown>'}`);
120
+ log(` label : ${label}`);
121
+ log('');
122
+ log('Done. Future aismemory sessions will authenticate silently with this key.');
123
+ log(`Private key lives at ~/.aismemory/keys/${userDid}.json (mode 0600).`);
124
+ log('Treat it like an SSH private key — back it up, do not share.');
125
+ process.exit(0);
126
+ }
127
+ main().catch((err) => {
128
+ log(`Fatal: ${err instanceof Error ? err.message : String(err)}`);
129
+ process.exit(1);
130
+ });
131
+ //# sourceMappingURL=enable-key-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enable-key-auth.js","sourceRoot":"","sources":["../../src/cli/enable-key-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAExD,MAAM,MAAM,GAAG,6BAA6B,CAAC;AAuB7C,SAAS,kBAAkB;IACzB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,kBAAkB,CAAC,CAAC;IAC/D,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAmB,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,KAAa;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACnE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;AACxC,CAAC;AAED,SAAS,GAAG,CAAC,GAAW;IACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,gCAAgC,CAAC;IAE1E,oCAAoC;IACpC,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,GAAG,CAAC,iEAAiE,CAAC,CAAC;QACvE,GAAG,CAAC,gFAAgF,CAAC,CAAC;QACtF,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;QAC5C,GAAG,CAAC,sEAAsE,CAAC,CAAC;QAC5E,GAAG,CAAC,qEAAqE,CAAC,CAAC;QAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,kCAAkC;IAClC,IAAI,OAAmB,CAAC;IACxB,IAAI,CAAC;QACH,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,mCAAoC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC;IAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,8EAA8E,CAAC,CAAC;QACpF,GAAG,CAAC,wDAAwD,CAAC,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,wEAAwE;IACxE,2EAA2E;IAC3E,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;IACrC,MAAM,OAAO,GAAG,WAAW,OAAO,UAAU,MAAM,EAAE,CAAC;IAErD,GAAG,CAAC,cAAc,MAAM,EAAE,CAAC,CAAC;IAC5B,GAAG,CAAC,cAAc,MAAM,EAAE,CAAC,CAAC;IAC5B,GAAG,CAAC,cAAc,OAAO,EAAE,CAAC,CAAC;IAE7B,uCAAuC;IACvC,MAAM,KAAK,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IACrE,GAAG,CAAC,6BAA6B,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IAElE,6BAA6B;IAC7B,GAAG,CAAC,kCAAkC,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,mBAAmB,EAAE;QACpD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,KAAK,CAAC,KAAK,EAAE;SACvC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,SAAS,EAAE,OAAO,CAAC,YAAY;YAC/B,KAAK;SACN,CAAC;KACH,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAwB,CAAC;IACzE,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAC7B,wEAAwE;QACxE,sEAAsE;QACtE,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,GAAG,CAAC,kEAAkE,CAAC,CAAC;YACxE,GAAG,CAAC,yDAAyD,CAAC,CAAC;YAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,GAAG,CACD,gCAAgC,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,EAAE,IAAI,IAAI,EAAE,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE,EAAE,CACpG,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,GAAG,CAAC,kCAAkC,CAAC,CAAC;IACxC,GAAG,CAAC,cAAc,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,WAAW,EAAE,CAAC,CAAC;IAClD,GAAG,CAAC,cAAc,KAAK,EAAE,CAAC,CAAC;IAC3B,GAAG,CAAC,EAAE,CAAC,CAAC;IACR,GAAG,CAAC,2EAA2E,CAAC,CAAC;IACjF,GAAG,CAAC,0CAA0C,OAAO,oBAAoB,CAAC,CAAC;IAC3E,GAAG,CAAC,8DAA8D,CAAC,CAAC;IACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,GAAG,CAAC,UAAU,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
11
11
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
12
+ import { tryKeyAuth } from './key-auth.js';
12
13
  import { CallToolRequestSchema, GetPromptRequestSchema, ListPromptsRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
13
14
  import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
14
15
  import { join } from 'path';
@@ -170,14 +171,24 @@ async function startDeviceFlow() {
170
171
  stderr(` Code : ${user_code}`);
171
172
  stderr('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
172
173
  const poll = pollForToken(device_code, interval, agent_id, provisional_tenant_id);
173
- return {
174
+ const flow = {
174
175
  device_code,
175
176
  user_code,
176
177
  verification_uri_complete,
177
178
  agent_id,
178
179
  provisional_tenant_id,
179
180
  poll,
181
+ dead: false,
180
182
  };
183
+ // Mark the flow dead as soon as its poll rejects so the next
184
+ // `ensureCredentials` call starts a fresh flow. The `.catch` here is purely
185
+ // for state-tracking — the original rejection is still observed by callers
186
+ // racing `flow.poll`. We swallow on this branch to suppress unhandled
187
+ // rejection warnings between rejection and the next ensureCredentials call.
188
+ poll.catch(() => {
189
+ flow.dead = true;
190
+ });
191
+ return flow;
181
192
  }
182
193
  async function pollForToken(device_code, interval, agent_id, provisional_tenant_id) {
183
194
  const pollInterval = Math.max(interval, 5) * 1000;
@@ -284,7 +295,30 @@ const tools = [
284
295
  },
285
296
  ];
286
297
  // ── MCP Server ──────────────────────────────────────────
298
+ /**
299
+ * Decode the user_id + tenant_id claims from a (presumed valid) JWT without
300
+ * verifying the signature. Used to derive bootstrap context after a successful
301
+ * key-auth handshake — we trust the token because the server just minted it.
302
+ */
303
+ function decodeJwtClaims(token) {
304
+ const parts = token.split('.');
305
+ if (parts.length !== 3)
306
+ return {};
307
+ try {
308
+ const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf-8'));
309
+ return { userId: payload.user_id ?? payload.sub, tenantId: payload.tenant_id };
310
+ }
311
+ catch {
312
+ return {};
313
+ }
314
+ }
287
315
  async function main() {
316
+ // Subcommand dispatch — `aismemory enable-key-auth` runs the enrollment
317
+ // CLI and exits, never touching the MCP server. Other subcommands TBD.
318
+ if (process.argv[2] === 'enable-key-auth') {
319
+ await import('./cli/enable-key-auth.js');
320
+ return; // CLI calls process.exit() itself
321
+ }
288
322
  // Lazy-auth state. We connect the MCP transport before the user has approved
289
323
  // the device flow so Claude Code's 30s connection timeout is not blocked on
290
324
  // human approval. The first tool call surfaces the bond URL via its result.
@@ -292,22 +326,68 @@ async function main() {
292
326
  let activeFlow = null;
293
327
  let postAuthDone = false;
294
328
  // Created here so `agent_load` and post-auth setup can reference it via closure.
295
- const server = new Server({ name: 'aismemory', version: '0.4.0' }, { capabilities: { tools: {}, prompts: {} } });
329
+ const server = new Server({ name: 'aismemory', version: '0.5.0' }, { capabilities: { tools: {}, prompts: {} } });
296
330
  /**
297
331
  * Wait briefly for the in-flight device-flow poll to complete. If the user
298
332
  * has already approved, this returns the fresh credentials. If not, throws
299
333
  * BondPendingError so the calling tool returns the bond URL to the agent.
334
+ *
335
+ * Recovery: if the previous flow's poll rejected (expired_token,
336
+ * access_denied, 30-min deadline, etc.), the dead flow is discarded and a
337
+ * new device flow is started inline — the user gets a fresh bond URL on
338
+ * the next tool call without having to restart the MCP process.
300
339
  */
301
340
  async function ensureCredentials(softTimeoutMs = 7000) {
302
341
  if (creds)
303
342
  return creds;
304
- if (!activeFlow)
343
+ // ── Key auth (Phase 1 DID auth) ───────────────────────────────────────
344
+ // If the user has enrolled a private key for this device, sign a
345
+ // server-issued challenge and skip the device-flow ceremony entirely.
346
+ // tryKeyAuth() returns null if no key file is present (clean fallback
347
+ // to device flow) and throws only on real failures (e.g. server says
348
+ // INVALID_SIGNATURE). On throw we log and continue to device flow —
349
+ // device flow is the recovery path for "user wiped their key file".
350
+ try {
351
+ const keyResult = await tryKeyAuth({ aisUrl: AIS_URL });
352
+ if (keyResult) {
353
+ const claims = decodeJwtClaims(keyResult.token);
354
+ const tenantId = claims.tenantId ?? '';
355
+ const resolved = await resolveAgent(keyResult.token, '', tenantId);
356
+ creds = {
357
+ token: keyResult.token,
358
+ agentId: resolved.agentId,
359
+ tenantId: resolved.tenantId || tenantId,
360
+ expiresAt: keyResult.expiresAt,
361
+ };
362
+ saveCredentials(creds);
363
+ stderr('Authenticated via DID key auth (no browser required)');
364
+ if (!postAuthDone) {
365
+ postAuthDone = true;
366
+ void runPostAuth(creds);
367
+ }
368
+ return creds;
369
+ }
370
+ }
371
+ catch (err) {
372
+ stderr(`Key auth failed: ${err instanceof Error ? err.message : String(err)}. Falling back to device flow.`);
373
+ }
374
+ if (!activeFlow || activeFlow.dead) {
305
375
  activeFlow = await startDeviceFlow();
376
+ }
306
377
  const sentinel = Symbol('bond-pending');
307
- const got = await Promise.race([
308
- activeFlow.poll,
309
- new Promise((r) => setTimeout(() => r(sentinel), softTimeoutMs)),
310
- ]);
378
+ let got;
379
+ try {
380
+ got = await Promise.race([
381
+ activeFlow.poll,
382
+ new Promise((r) => setTimeout(() => r(sentinel), softTimeoutMs)),
383
+ ]);
384
+ }
385
+ catch {
386
+ // Poll rejected (deadline / expired / denied). Start a fresh flow
387
+ // immediately and surface its new bond URL — no restart required.
388
+ activeFlow = await startDeviceFlow();
389
+ throw new BondPendingError(activeFlow.verification_uri_complete, activeFlow.user_code);
390
+ }
311
391
  if (got === sentinel) {
312
392
  throw new BondPendingError(activeFlow.verification_uri_complete, activeFlow.user_code);
313
393
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,GAEvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGtE,2DAA2D;AAE3D,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,gCAAgC,CAAC;AAC3E,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AAChD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;AASvD,2DAA2D;AAE3D,SAAS,eAAe;IACtB,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAgB,CAAC;QAC1E,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;YAC3C,MAAM,CAAC,iDAAiD,CAAC,CAAC;YAC1D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAAkB;IACzC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,2DAA2D;AAE3D,SAAS,MAAM,CAAC,GAAW;IACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,IAAY,EAAE,IAAa,EAAE,KAAc;IAChE,MAAM,OAAO,GAA2B,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;IAC/E,IAAI,KAAK;QAAE,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,EAAE,CAAC;IACxD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,GAAG,IAAI,EAAE,EAAE;QAC3C,MAAM,EAAE,MAAM;QACd,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IACH,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,IAAY,EAAE,KAAa;IAC/C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,GAAG,IAAI,EAAE,EAAE;QAC3C,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,KAAK,EAAE,EAAE;KAChD,CAAC,CAAC;IACH,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AA2CD,KAAK,UAAU,mBAAmB,CAAC,KAAa,EAAE,KAAa;IAC7D,MAAM,UAAU,GAAG,CAAC,MAAM,MAAM,CAAC,qBAAqB,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAyB,CAAC;IACnH,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,KAAK,UAAU,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACpE,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;IAC/B,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,EAAE,CAAC;QAC5C,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC;QAC/E,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,IAAI,sCAAsC,KAAK,WAAW,GAAG,qCAAqC,CAAC,CAAC;IAC7I,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,EAAE,CAAC;QAC5C,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,IAAI,+BAA+B,KAAK,gCAAgC,SAAS,IAAI,QAAQ,EAAE,CAAC,CAAC;IAC1I,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,MAAM,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,CAAsB,CAAC;IACzE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,CAAC;IAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAC3B,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,KAAK,CACzE,CAAC;IACF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzD,MAAM,IAAI,KAAK,CACb,+BAA+B,KAAK,gCAAgC,SAAS,IAAI,QAAQ,EAAE,CAC5F,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,sCAAsC,KAAK,WAAW,OAAO;aAC1D,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;aAClB,IAAI,CAAC,IAAI,CAAC,qCAAqC,CACnD,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,CAAC,CAAE,CAAC;AACrB,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,YAAY,CAAC,KAAa,EAAE,eAAuB,EAAE,gBAAwB;IAC1F,wCAAwC;IACxC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC/C,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,kCAAkC,UAAU,EAAE,CAAC,CAAC;QACvD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7D,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,YAAY,EAAE,KAAK,CAAsB,CAAC;QACnE,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;QAE5E,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,8CAA8C,eAAe,EAAE,CAAC,CAAC;YACxE,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;QAClE,CAAC;QAED,0CAA0C;QAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC9C,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;YACjF,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,CAAC,gBAAgB,KAAK,CAAC,IAAI,4BAA4B,CAAC,CAAC;gBAC/D,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;YAC3D,CAAC;YACD,MAAM,CAAC,4BAA4B,OAAO,2BAA2B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/G,CAAC;QAED,+BAA+B;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QAC1B,MAAM,CAAC,gCAAgC,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;QACtE,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,CAAC,YAAY,MAAM,CAAC,MAAM,wDAAwD,CAAC,CAAC;YAC1F,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;gBACvB,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,2CAA2C,eAAe,EAAE,CAAC,CAAC;QACrE,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAClE,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,gBAAiB,SAAQ,KAAK;IAEN;IAAyC;IAD5D,WAAW,GAAG,IAAI,CAAC;IAC5B,YAA4B,eAAuB,EAAkB,QAAgB;QACnF,KAAK,CACH,2BAA2B;YACzB,UAAU,eAAe,IAAI;YAC7B,SAAS,QAAQ,MAAM;YACvB,iFAAiF,CACpF,CAAC;QANwB,oBAAe,GAAf,eAAe,CAAQ;QAAkB,aAAQ,GAAR,QAAQ,CAAQ;QAOnF,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAYD,KAAK,UAAU,eAAe;IAC5B,MAAM,CAAC,4BAA4B,CAAC,CAAC;IAErC,MAAM,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,4BAA4B,EAAE;QAC3D,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,MAAM,EAAE;KACtD,CAAC,CAAuB,CAAC;IAE1B,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,0BAA0B,OAAO,CAAC,KAAK,EAAE,OAAO,IAAI,eAAe,EAAE,CAAC,CAAC;IACzF,CAAC;IAED,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,yBAAyB,EAAE,QAAQ,EAAE,QAAQ,EAAE,qBAAqB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAEtH,MAAM,CAAC,EAAE,CAAC,CAAC;IACX,MAAM,CAAC,wDAAwD,CAAC,CAAC;IACjE,MAAM,CAAC,oCAAoC,CAAC,CAAC;IAC7C,MAAM,CAAC,wDAAwD,CAAC,CAAC;IACjE,MAAM,CAAC,gBAAgB,yBAAyB,EAAE,CAAC,CAAC;IACpD,MAAM,CAAC,gBAAgB,SAAS,EAAE,CAAC,CAAC;IACpC,MAAM,CAAC,wDAAwD,CAAC,CAAC;IAEjE,MAAM,IAAI,GAAG,YAAY,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,qBAAqB,CAAC,CAAC;IAElF,OAAO;QACL,WAAW;QACX,SAAS;QACT,yBAAyB;QACzB,QAAQ;QACR,qBAAqB;QACrB,IAAI;KACL,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,WAAmB,EACnB,QAAgB,EAChB,QAAgB,EAChB,qBAA6B;IAE7B,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;IAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,SAAS;IAEvD,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;QAEtD,MAAM,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,iBAAiB,EAAE,EAAE,WAAW,EAAE,CAAC,CAAsB,CAAC;QAEzF,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YACzB,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAC7F,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,YAAY,EAAE,QAAQ,EAAE,qBAAqB,CAAC,CAAC;YACxG,MAAM,KAAK,GAAgB;gBACzB,KAAK,EAAE,OAAO,CAAC,YAAY;gBAC3B,OAAO;gBACP,QAAQ;gBACR,SAAS;aACV,CAAC;YACF,eAAe,CAAC,KAAK,CAAC,CAAC;YACvB,MAAM,CAAC,6BAA6B,CAAC,CAAC;YACtC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,OAAO,CAAC,KAAK,KAAK,uBAAuB;YAAE,SAAS;QACxD,IAAI,OAAO,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;YAClC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YAC9C,SAAS;QACX,CAAC;QACD,IAAI,OAAO,CAAC,KAAK,KAAK,eAAe;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACvF,IAAI,OAAO,CAAC,KAAK,KAAK,eAAe;YAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACrG,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;AAC9C,CAAC;AAED,IAAI,YAAY,GAAwB,IAAI,CAAC;AAC7C,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;AAE9C,2DAA2D;AAE3D,MAAM,KAAK,GAAW;IACpB;QACE,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,kEAAkE;QAC/E,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,6BAA6B,EAAE;gBACvE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,aAAa,EAAE;gBAClH,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,+BAA+B,EAAE;aACrG;YACD,QAAQ,EAAE,CAAC,SAAS,CAAC;SACtB;KACF;IACD;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,4CAA4C;QACzD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE;gBACtD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0BAA0B,EAAE;gBAClE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,gBAAgB,EAAE;aACtH;YACD,QAAQ,EAAE,CAAC,OAAO,CAAC;SACpB;KACF;IACD;QACE,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,kEAAkE;QAC/E,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE;KAChD;IACD;QACE,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,8FAA8F;QAC3G,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE;KAChD;IACD;QACE,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,iGAAiG;QAC9G,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE;KAChD;IACD;QACE,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,gFAAgF;QAC7F,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+CAA+C,EAAE;gBACzF,YAAY,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,gCAAgC,EAAE;aAC1G;SACF;KACF;IACD;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EACT,wKAAwK;YACxK,iMAAiM;QACnM,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,kEAAkE;iBAChF;aACF;YACD,QAAQ,EAAE,CAAC,OAAO,CAAC;SACpB;KACF;CACF,CAAC;AAEF,2DAA2D;AAE3D,KAAK,UAAU,IAAI;IACjB,6EAA6E;IAC7E,4EAA4E;IAC5E,4EAA4E;IAC5E,IAAI,KAAK,GAAuB,eAAe,EAAE,CAAC;IAClD,IAAI,UAAU,GAA4B,IAAI,CAAC;IAC/C,IAAI,YAAY,GAAG,KAAK,CAAC;IAEzB,iFAAiF;IACjF,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,EACvC,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,CAC7C,CAAC;IAEF;;;;OAIG;IACH,KAAK,UAAU,iBAAiB,CAAC,aAAa,GAAG,IAAI;QACnD,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxB,IAAI,CAAC,UAAU;YAAE,UAAU,GAAG,MAAM,eAAe,EAAE,CAAC;QAEtD,MAAM,QAAQ,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAgC;YAC5D,UAAU,CAAC,IAAI;YACf,IAAI,OAAO,CAAkB,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,CAAC;SAClF,CAAC,CAAC;QAEH,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACrB,MAAM,IAAI,gBAAgB,CAAC,UAAU,CAAC,yBAAyB,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;QACzF,CAAC;QAED,KAAK,GAAG,GAAG,CAAC;QACZ,UAAU,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,YAAY,GAAG,IAAI,CAAC;YACpB,KAAK,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,4EAA4E;IAC5E,KAAK,UAAU,WAAW,CAAC,CAAc;QACvC,IAAI,CAAC;YACH,YAAY,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YAClE,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,CACJ,iBAAiB,YAAY,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,cAAc,CAAC,MAAM,cAAc,YAAY,CAAC,KAAK,CAAC,MAAM,SAAS,CACnI,CAAC;gBACF,MAAM,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,oCAAoC,EAAE,CAAC,CAAC;YACxE,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,gEAAgE,CAAC,CAAC;YAC3E,CAAC;YAED,iBAAiB,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,QAAuB,EAAE,EAAE;gBACzE,IAAI,YAAY,EAAE,CAAC;oBACjB,YAAY,CAAC,cAAc,GAAG,QAAQ,CAAC;gBACzC,CAAC;gBACD,MAAM,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,oCAAoC,EAAE,CAAC,CAAC;gBACtE,MAAM,CAAC,mBAAmB,QAAQ,CAAC,MAAM,WAAW,CAAC,CAAC;YACxD,CAAC,CAAC,CAAC;YAEH,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE;gBAClE,gBAAgB,EAAE,CAAC;gBACnB,MAAM,CAAC,uBAAuB,CAAC,CAAC;YAClC,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,2BAA2B,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;IAED,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAE1E,MAAM,CAAC,iBAAiB,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QAC9D,OAAO,EAAE,YAAY;YACnB,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAW,EAAE,qDAAqD,EAAE,CAAC;YAClG,CAAC,CAAC,EAAE;KACP,CAAC,CAAC,CAAC;IAEJ,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QAC5D,QAAQ,EAAE,CAAC;gBACT,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,cAAc,CAAC,YAAY,CAAC,EAAE;aACvE,CAAC;KACH,CAAC,CAAC,CAAC;IAEJ,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;QACjD,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAA4B,CAAC;QAClD,eAAe,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAEpC,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,iBAAiB,EAAE,CAAC;YACpC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;YACtB,oEAAoE;YACpE,IAAI,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;YAExB,IAAI,MAAe,CAAC;YAEpB,QAAQ,IAAI,EAAE,CAAC;gBACb,KAAK,UAAU;oBACb,MAAM,GAAG,MAAM,OAAO,CAAC,cAAc,OAAO,SAAS,EAAE;wBACrD,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC;wBACrB,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,SAAS;wBAC5B,UAAU,EAAE,CAAC,CAAC,YAAY,CAAC,IAAI,GAAG;qBACnC,EAAE,KAAK,CAAC,CAAC;oBACV,eAAe,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;oBAC/D,MAAM;gBAER,KAAK,QAAQ,CAAC,CAAC,CAAC;oBACd,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;oBACrC,IAAI,CAAC,CAAC,OAAO,CAAC;wBAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;oBACxD,IAAI,CAAC,CAAC,OAAO,CAAC;wBAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;oBACxD,IAAI,CAAC,CAAC,MAAM,CAAC;wBAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;oBACtD,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,OAAO,WAAW,MAAM,EAAE,EAAE,KAAK,CAAC,CAAC;oBACvE,MAAM;gBACR,CAAC;gBAED,KAAK,QAAQ;oBACX,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;oBACtD,MAAM;gBAER,KAAK,cAAc;oBACjB,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,OAAO,eAAe,EAAE,KAAK,CAAC,CAAC;oBACnE,MAAM;gBAER,KAAK,OAAO;oBACV,MAAM,GAAG,MAAM,OAAO,CAAC,cAAc,OAAO,QAAQ,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;oBACjE,MAAM;gBAER,KAAK,SAAS;oBACZ,MAAM,GAAG,MAAM,OAAO,CAAC,cAAc,OAAO,UAAU,EAAE;wBACtD,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,eAAe;wBACxC,YAAY,EAAE,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE;qBACtC,EAAE,KAAK,CAAC,CAAC;oBACV,MAAM;gBAER,KAAK,YAAY,CAAC,CAAC,CAAC;oBAClB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;oBAC9C,IAAI,CAAC,KAAK,EAAE,CAAC;wBACX,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;oBACnD,CAAC;oBACD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;oBACvD,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC;oBACpB,iEAAiE;oBACjE,IAAI,KAAK,EAAE,CAAC;wBACV,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,CAAC;oBAChC,CAAC;oBACD,YAAY,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;oBAC9D,MAAM,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,oCAAoC,EAAE,CAAC,CAAC;oBACtE,MAAM,CAAC,4BAA4B,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;oBAClE,MAAM,GAAG;wBACP,OAAO,EAAE,IAAI;wBACb,OAAO,EAAE,MAAM,CAAC,EAAE;wBAClB,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,GAAG,EAAE,YAAY,EAAE,QAAQ,CAAC,GAAG,IAAI,IAAI;wBACvC,MAAM,EAAE,MAAM,CAAC,MAAM;wBACrB,cAAc,EAAE,YAAY,EAAE,cAAc,CAAC,MAAM,IAAI,CAAC;wBACxD,WAAW,EAAE,YAAY,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC;qBAC7C,CAAC;oBACF,MAAM;gBACR,CAAC;gBAED;oBACE,OAAO;wBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,iBAAiB,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC;wBACrF,OAAO,EAAE,IAAI;qBACd,CAAC;YACN,CAAC;YAED,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aACnE,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACzE,qEAAqE;YACrE,2DAA2D;YAC3D,IAAI,KAAK,YAAY,gBAAgB,EAAE,CAAC;gBACtC,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;oBAC1C,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;gBACrE,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,4EAA4E;IAC5E,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,CAAC,8BAA8B,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAE5E,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,0BAA0B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAClD,YAAY,GAAG,IAAI,CAAC;QACpB,KAAK,WAAW,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,qEAAqE,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,MAAM,CAAC,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /** Public key in JWK form. */
2
+ export interface Ed25519PublicJwk {
3
+ kty: 'OKP';
4
+ crv: 'Ed25519';
5
+ x: string;
6
+ }
7
+ /** Private key file shape persisted at `~/.aismemory/keys/<userDid>.json`. */
8
+ export interface KeyFile {
9
+ /** Schema version. Bump for breaking changes; readers should refuse unknown versions. */
10
+ version: 1;
11
+ userId: string;
12
+ userDid: string;
13
+ keyType: 'Ed25519';
14
+ /** base64url(raw 32-byte private key seed) */
15
+ privateKey: string;
16
+ /** base64url(raw 32-byte public key) */
17
+ publicKey: string;
18
+ /** Public key in JWK form — kept alongside `publicKey` for convenience. */
19
+ publicKeyJwk: Ed25519PublicJwk;
20
+ createdAt: string;
21
+ }
22
+ /** Credentials handed back to the caller after a successful key-auth. */
23
+ export interface KeyAuthCredentials {
24
+ userId: string;
25
+ userDid: string;
26
+ /** Bearer JWT to use in `Authorization: Bearer ...` headers. */
27
+ token: string;
28
+ /** ISO timestamp at which `token` will be rejected. */
29
+ expiresAt: string;
30
+ tokenType: 'owner';
31
+ }
32
+ /** Read a key file. Returns null if the file is absent. Throws on malformed JSON. */
33
+ export declare function readKeyFile(opts: {
34
+ userDid: string;
35
+ keysDir?: string;
36
+ }): KeyFile | null;
37
+ /**
38
+ * Generate a fresh Ed25519 keypair, write it to disk, and return the result.
39
+ * The directory is created with mode 0700 and the key file with mode 0600.
40
+ *
41
+ * This is called once per device by the `enable-key-auth` CLI bootstrap.
42
+ */
43
+ export declare function generateAndSaveKeypair(opts: {
44
+ userId: string;
45
+ userDid: string;
46
+ keysDir?: string;
47
+ }): Promise<KeyFile>;
48
+ export interface TryKeyAuthOpts {
49
+ /** AIS base URL, e.g. `https://ais.agentsandswarms.ai` */
50
+ aisUrl: string;
51
+ /** Override the default keys directory (for tests). */
52
+ keysDir?: string;
53
+ /**
54
+ * If supplied, load the key for this specific userDid. Otherwise the
55
+ * helper auto-discovers a single key file in `keysDir`.
56
+ */
57
+ userDid?: string;
58
+ /** Override fetch (for tests). */
59
+ fetchImpl?: typeof globalThis.fetch;
60
+ }
61
+ /**
62
+ * Attempt key-based authentication against AIS. Returns null if no usable
63
+ * key file exists (caller should fall back to device flow). Throws on any
64
+ * fatal error (bad signature, network failure, server rejection).
65
+ */
66
+ export declare function tryKeyAuth(opts: TryKeyAuthOpts): Promise<KeyAuthCredentials | null>;
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Key-based authentication for the aismemory client.
3
+ *
4
+ * Phase 1 of the DID-auth ladder: the user generates an Ed25519 keypair on
5
+ * their device (via `enable-key-auth`), publishes the public key to AIS once,
6
+ * and from then on signs server-issued challenges with the private key to
7
+ * obtain owner JWTs. The browser activate flow is needed only at enrollment.
8
+ *
9
+ * Threat model:
10
+ * - Private key lives at `~/.aismemory/keys/<userDid>.json`, mode 0600.
11
+ * Same handling story as an SSH private key without a passphrase.
12
+ * - The server NEVER sees the private key — only the public half.
13
+ * - Owner JWTs are NOT persisted; they live in memory for the session.
14
+ * When the JWT expires (or AIS rotates JWT_SECRET) the client silently
15
+ * re-runs challenge/prove. The user notices nothing.
16
+ */
17
+ import { generateKeyPairSync, createPrivateKey, sign as edSign, } from 'node:crypto';
18
+ import { mkdirSync, readFileSync, writeFileSync, existsSync, readdirSync, chmodSync, } from 'node:fs';
19
+ import { join } from 'node:path';
20
+ import { homedir } from 'node:os';
21
+ // ───────────────────────────────────────────────────────────────────────────
22
+ // Filesystem helpers
23
+ // ───────────────────────────────────────────────────────────────────────────
24
+ /** Default location for key files. Override via `keysDir` arg in tests. */
25
+ function defaultKeysDir() {
26
+ return join(homedir(), '.aismemory', 'keys');
27
+ }
28
+ function keyFilePath(userDid, keysDir) {
29
+ return join(keysDir ?? defaultKeysDir(), `${userDid}.json`);
30
+ }
31
+ /** Read a key file. Returns null if the file is absent. Throws on malformed JSON. */
32
+ export function readKeyFile(opts) {
33
+ const path = keyFilePath(opts.userDid, opts.keysDir);
34
+ if (!existsSync(path))
35
+ return null;
36
+ const raw = readFileSync(path, 'utf-8');
37
+ const parsed = JSON.parse(raw);
38
+ if (parsed.version !== 1) {
39
+ throw new Error(`Unsupported key file version: ${parsed.version}. Run \`aismemory enable-key-auth\` to re-enroll.`);
40
+ }
41
+ return parsed;
42
+ }
43
+ /**
44
+ * Discover a single key file in `keysDir` when the caller doesn't know which
45
+ * userDid to load. Common case: the MCP server boots, sees a single key on
46
+ * disk, and uses it. Returns null if zero or multiple keys are present.
47
+ */
48
+ function discoverSingleKeyFile(keysDir) {
49
+ const dir = keysDir ?? defaultKeysDir();
50
+ if (!existsSync(dir))
51
+ return null;
52
+ const entries = readdirSync(dir).filter((f) => f.endsWith('.json'));
53
+ if (entries.length !== 1)
54
+ return null;
55
+ const path = join(dir, entries[0]);
56
+ const parsed = JSON.parse(readFileSync(path, 'utf-8'));
57
+ if (parsed.version !== 1)
58
+ return null;
59
+ return parsed;
60
+ }
61
+ /**
62
+ * Generate a fresh Ed25519 keypair, write it to disk, and return the result.
63
+ * The directory is created with mode 0700 and the key file with mode 0600.
64
+ *
65
+ * This is called once per device by the `enable-key-auth` CLI bootstrap.
66
+ */
67
+ export async function generateAndSaveKeypair(opts) {
68
+ const dir = opts.keysDir ?? defaultKeysDir();
69
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
70
+ const { publicKey, privateKey } = generateKeyPairSync('ed25519');
71
+ // Export to JWK form so we have a canonical wire shape AND the raw bytes.
72
+ const publicJwk = publicKey.export({ format: 'jwk' });
73
+ const privateJwk = privateKey.export({ format: 'jwk' });
74
+ const file = {
75
+ version: 1,
76
+ userId: opts.userId,
77
+ userDid: opts.userDid,
78
+ keyType: 'Ed25519',
79
+ privateKey: privateJwk.d,
80
+ publicKey: publicJwk.x,
81
+ publicKeyJwk: { kty: 'OKP', crv: 'Ed25519', x: publicJwk.x },
82
+ createdAt: new Date().toISOString(),
83
+ };
84
+ const path = keyFilePath(opts.userDid, opts.keysDir);
85
+ writeFileSync(path, JSON.stringify(file, null, 2));
86
+ // chmod after write — writeFileSync's mode arg is umasked, so explicit
87
+ // chmod is the only reliable path to 0600 on POSIX.
88
+ if (process.platform !== 'win32') {
89
+ chmodSync(path, 0o600);
90
+ }
91
+ return file;
92
+ }
93
+ // ───────────────────────────────────────────────────────────────────────────
94
+ // Crypto: sign the canonical challenge string
95
+ // ───────────────────────────────────────────────────────────────────────────
96
+ /**
97
+ * Sign the canonical challenge bytes with the user's private key. Returns
98
+ * the signature as a base64url string ready for the wire.
99
+ *
100
+ * Canonical form: `<userDid>\n<nonce>\n<exp>` as UTF-8 bytes. Must match the
101
+ * server's verification (see did-auth.ts in agent-identity-service).
102
+ */
103
+ function signChallenge(args) {
104
+ // Import the raw private key bytes back into a Node KeyObject. The JWK
105
+ // round-trip is the simplest way to do this without depending on PKCS#8
106
+ // formatting nuances.
107
+ const priv = createPrivateKey({
108
+ key: {
109
+ kty: 'OKP',
110
+ crv: 'Ed25519',
111
+ x: args.publicKeyB64,
112
+ d: args.privateKeyB64,
113
+ },
114
+ format: 'jwk',
115
+ });
116
+ const msg = Buffer.from(`${args.userDid}\n${args.nonce}\n${args.exp}`, 'utf8');
117
+ return edSign(null, msg, priv).toString('base64url');
118
+ }
119
+ /**
120
+ * Attempt key-based authentication against AIS. Returns null if no usable
121
+ * key file exists (caller should fall back to device flow). Throws on any
122
+ * fatal error (bad signature, network failure, server rejection).
123
+ */
124
+ export async function tryKeyAuth(opts) {
125
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
126
+ // 1. Locate a key file.
127
+ let keyFile;
128
+ if (opts.userDid) {
129
+ keyFile = readKeyFile({ userDid: opts.userDid, keysDir: opts.keysDir });
130
+ }
131
+ else {
132
+ keyFile = discoverSingleKeyFile(opts.keysDir);
133
+ }
134
+ if (!keyFile)
135
+ return null;
136
+ // 2. Issue a challenge.
137
+ const challengeRes = await fetchImpl(`${opts.aisUrl}/v1/auth/challenge`, {
138
+ method: 'POST',
139
+ headers: { 'Content-Type': 'application/json' },
140
+ body: JSON.stringify({ userDid: keyFile.userDid }),
141
+ });
142
+ const challengeBody = (await challengeRes.json());
143
+ if (!challengeRes.ok || !challengeBody.success || !challengeBody.data) {
144
+ throw new Error(`key-auth: challenge failed (${challengeRes.status}): ${challengeBody.error?.message ?? challengeBody.error?.code ?? 'unknown'}`);
145
+ }
146
+ const { nonce, exp, hmac } = challengeBody.data;
147
+ // 3. Sign the canonical message.
148
+ const signature = signChallenge({
149
+ privateKeyB64: keyFile.privateKey,
150
+ publicKeyB64: keyFile.publicKey,
151
+ userDid: keyFile.userDid,
152
+ nonce,
153
+ exp,
154
+ });
155
+ // 4. Submit the signed proof.
156
+ const proveRes = await fetchImpl(`${opts.aisUrl}/v1/auth/did-prove`, {
157
+ method: 'POST',
158
+ headers: { 'Content-Type': 'application/json' },
159
+ body: JSON.stringify({
160
+ userDid: keyFile.userDid,
161
+ nonce,
162
+ exp,
163
+ hmac,
164
+ signature,
165
+ }),
166
+ });
167
+ const proveBody = (await proveRes.json());
168
+ if (!proveRes.ok || !proveBody.success || !proveBody.data) {
169
+ throw new Error(`key-auth: did-prove failed (${proveRes.status}): ${proveBody.error?.message ?? proveBody.error?.code ?? 'unknown'}`);
170
+ }
171
+ return {
172
+ userId: keyFile.userId,
173
+ userDid: keyFile.userDid,
174
+ token: proveBody.data.bearerToken,
175
+ expiresAt: proveBody.data.expiresAt,
176
+ tokenType: 'owner',
177
+ };
178
+ }
179
+ //# sourceMappingURL=key-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-auth.js","sourceRoot":"","sources":["../src/key-auth.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aismemory",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Persistent memory for AI agents. MCP server that connects to Agent Identity Service.",
5
5
  "type": "module",
6
6
  "bin": "dist/index.js",