@engramx/client 0.15.0 → 0.16.0-rc.4

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.
Files changed (57) hide show
  1. package/README.md +255 -26
  2. package/dist/EngramClient.d.ts +235 -229
  3. package/dist/EngramClient.js +446 -1247
  4. package/dist/EngramClient.js.map +1 -1
  5. package/dist/MarketClient.d.ts +137 -0
  6. package/dist/MarketClient.js +228 -0
  7. package/dist/MarketClient.js.map +1 -0
  8. package/dist/ProfileManager.d.ts +4 -4
  9. package/dist/SessionManager.d.ts +3 -3
  10. package/dist/SessionManager.js +1 -1
  11. package/dist/SessionManager.js.map +1 -1
  12. package/dist/actionReceipt.d.ts +59 -0
  13. package/dist/actionReceipt.js +68 -2
  14. package/dist/actionReceipt.js.map +1 -1
  15. package/dist/auth.d.ts +16 -0
  16. package/dist/auth.js +38 -5
  17. package/dist/auth.js.map +1 -1
  18. package/dist/certifiedAudit.d.ts +32 -6
  19. package/dist/certifiedAudit.js +75 -14
  20. package/dist/certifiedAudit.js.map +1 -1
  21. package/dist/cli.js +100 -26
  22. package/dist/cli.js.map +1 -1
  23. package/dist/encryption.d.ts +30 -12
  24. package/dist/encryption.js +13 -15
  25. package/dist/encryption.js.map +1 -1
  26. package/dist/idl.d.ts +69 -0
  27. package/dist/idl.js +242 -0
  28. package/dist/idl.js.map +1 -0
  29. package/dist/index.d.ts +12 -18
  30. package/dist/index.js +54 -9
  31. package/dist/index.js.map +1 -1
  32. package/dist/ledgerfsHash.js +1 -1
  33. package/dist/ledgerfsHash.js.map +1 -1
  34. package/dist/lineage.js +8 -5
  35. package/dist/lineage.js.map +1 -1
  36. package/dist/memoryArchive.d.ts +384 -0
  37. package/dist/memoryArchive.js +477 -0
  38. package/dist/memoryArchive.js.map +1 -0
  39. package/dist/migrate.js +31 -4
  40. package/dist/migrate.js.map +1 -1
  41. package/dist/openEngram.d.ts +55 -0
  42. package/dist/openEngram.js +185 -0
  43. package/dist/openEngram.js.map +1 -0
  44. package/dist/pair.d.ts +33 -2
  45. package/dist/pair.js +56 -9
  46. package/dist/pair.js.map +1 -1
  47. package/dist/types.d.ts +246 -307
  48. package/dist/version.d.ts +8 -0
  49. package/dist/version.js +45 -0
  50. package/dist/version.js.map +1 -0
  51. package/dist/wire.d.ts +76 -0
  52. package/dist/wire.js +79 -0
  53. package/dist/wire.js.map +1 -0
  54. package/package.json +5 -14
  55. package/dist/bootstrap.d.ts +0 -21
  56. package/dist/bootstrap.js +0 -71
  57. package/dist/bootstrap.js.map +0 -1
@@ -5,7 +5,7 @@
5
5
  * reading/writing user identity, preferences, and accumulated knowledge
6
6
  * without callers needing to know the path layout.
7
7
  */
8
- import type { EngramClient } from './EngramClient.js';
8
+ import type { EngramClient, MemoryReceipt } from './EngramClient.js';
9
9
  export interface Profile {
10
10
  /** Agent personality (SOUL.md) — may be null if not yet set */
11
11
  soul: string | null;
@@ -40,16 +40,16 @@ export declare class ProfileManager {
40
40
  /**
41
41
  * Save a preference. Appends a timestamped entry to identity/preferences.md.
42
42
  */
43
- savePreference(preference: string): Promise<bigint>;
43
+ savePreference(preference: string): Promise<MemoryReceipt | null>;
44
44
  /**
45
45
  * Save an insight or lesson learned. Appends to knowledge/lessons.md,
46
46
  * or to a domain-specific file if topic is provided.
47
47
  */
48
- saveInsight(insight: Insight): Promise<bigint>;
48
+ saveInsight(insight: Insight): Promise<MemoryReceipt | null>;
49
49
  /**
50
50
  * Save a decision with rationale. Appends to knowledge/decisions.md.
51
51
  */
52
- saveDecision(decision: string, rationale: string): Promise<bigint>;
52
+ saveDecision(decision: string, rationale: string): Promise<MemoryReceipt | null>;
53
53
  /**
54
54
  * Read the lessons file. Returns null if it doesn't exist.
55
55
  */
@@ -5,7 +5,7 @@
5
5
  * summaries to its own namespace (sessions/{platform}/), enabling
6
6
  * cross-platform continuity ("what was I working on with OpenClaw?").
7
7
  */
8
- import type { EngramClient } from './EngramClient.js';
8
+ import type { EngramClient, MemoryReceipt } from './EngramClient.js';
9
9
  export interface SessionSummary {
10
10
  platform: string;
11
11
  date: string;
@@ -15,7 +15,7 @@ export interface SessionEntry {
15
15
  path: string;
16
16
  platform: string;
17
17
  date: string;
18
- lastModifiedAt: bigint;
18
+ lastModifiedAtNs: bigint;
19
19
  }
20
20
  export declare class SessionManager {
21
21
  private readonly client;
@@ -23,7 +23,7 @@ export declare class SessionManager {
23
23
  /**
24
24
  * Write or append a session summary for the current platform and date.
25
25
  */
26
- writeSummary(platform: string, content: string, date?: string): Promise<bigint>;
26
+ writeSummary(platform: string, content: string, date?: string): Promise<MemoryReceipt | null>;
27
27
  /**
28
28
  * Read a specific session summary.
29
29
  */
@@ -46,7 +46,7 @@ export class SessionManager {
46
46
  path: f.path,
47
47
  platform: plat ?? 'unknown',
48
48
  date: dateMatch ? dateMatch[1] : 'unknown',
49
- lastModifiedAt: f.lastModifiedAt,
49
+ lastModifiedAtNs: f.lastModifiedAtNs,
50
50
  };
51
51
  })
52
52
  .sort((a, b) => {
@@ -1 +1 @@
1
- {"version":3,"file":"SessionManager.js","sourceRoot":"","sources":["../src/SessionManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SessionManager.js","sourceRoot":"","sources":["../src/SessionManager.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { Ed25519KeyIdentity } from '@icp-sdk/core/identity';
2
+ import { Principal } from '@icp-sdk/core/principal';
2
3
  /** The `ownerAuth` argument to the money-path methods (Candid: opt ActionAuth). */
3
4
  export interface ActionAuth {
4
5
  /** 32-byte raw Ed25519 public key of the owner's identity. */
@@ -24,6 +25,43 @@ export declare const actionFields: {
24
25
  * `canisterId` MUST be the target engram's principal text (the receipt is bound to it).
25
26
  */
26
27
  export declare function signAction(identity: Ed25519KeyIdentity, canisterId: string, operation: string, fields: string, nonce: bigint): Promise<ActionAuth>;
28
+ /**
29
+ * The purpose an enrolment statement names. MUST match src/shared/IdentityBinding.mo
30
+ * `ENROL_OPERATION`.
31
+ */
32
+ export declare const ENROL_OPERATION = "agent.enrol";
33
+ /**
34
+ * The message an agent's ROOT key signs to enrol one per-client key on one engram — the owner's
35
+ * decision of 2026-09-28: one root key per agent, with an enrolled key per client. It is
36
+ * `actionMessage` with a fixed purpose, bound to the engram, the enrolled key and the invite code
37
+ * being redeemed (the invite is what makes a statement single-use: the engram burns it). The nonce
38
+ * is free and is NOT a replay guard — see `pairEnrolled` for why it exists.
39
+ * ⟨CORRECTED 2026-09-29, ic402 2.16.1⟩ `pairEnrolled` is gone: the engram's verifier no longer
40
+ * refuses valid signatures, so pairing sends one statement (`EngramClient.pairAgent`).
41
+ * ⟨CORRECTED 2026-09-29, later⟩ The nonce is gone too — it existed only for that re-signing — so
42
+ * the message is `engramx.action.v1|<engram>|agent.enrol|enrolled=<key>|invite=<code>`: the
43
+ * `actionMessage` prefix and parts with no `|nonce=` suffix, built directly here.
44
+ * MUST match src/shared/IdentityBinding.mo `enrolmentMessage` byte-for-byte; the Motoko test
45
+ * test/enrolment.test.mo verifies a signature produced by `signEnrolment` below.
46
+ */
47
+ export declare function enrolmentMessage(canisterId: string, enrolledKey: string, inviteCode: string): Uint8Array;
48
+ /** The `enrolment` field of `pairAgent`'s argument (Candid: Enrolment). */
49
+ export interface Enrolment {
50
+ /** 32-byte raw Ed25519 public key of the agent's root. */
51
+ rootPubkey: Uint8Array;
52
+ /** The engram the statement is for. */
53
+ engram: Principal;
54
+ /** The per-client key being enrolled — the principal that will call `pairAgent`. */
55
+ enrolledKey: Principal;
56
+ /** 64-byte Ed25519 signature by the root over `enrolmentMessage`. */
57
+ signature: Uint8Array;
58
+ }
59
+ /**
60
+ * Sign an enrolment statement with the agent's root key. `root` must be an Ed25519 identity (the
61
+ * statement is Ed25519 by construction); `enrolledKey` is the per-client key's principal and
62
+ * `inviteCode` the code that key is about to redeem on `canisterId`.
63
+ */
64
+ export declare function signEnrolment(root: Ed25519KeyIdentity, canisterId: string, enrolledKey: Principal, inviteCode: string): Promise<Enrolment>;
27
65
  /** Encode an ActionAuth for the Candid `opt ActionAuth` argument. */
28
66
  export declare function toCandidActionAuth(a: ActionAuth): [{
29
67
  pubkey: number[];
@@ -34,6 +72,27 @@ export declare function toCandidActionAuth(a: ActionAuth): [{
34
72
  * Verify a receipt without trusting EngramX: confirm the signature is by `pubkey` over the exact
35
73
  * canonical action, and return the self-authenticating principal that key maps to — i.e. WHO
36
74
  * authorized the action. A relying party compares that principal to the engram's known owner.
75
+ *
76
+ * ⟨2026-09-29⟩ MORE PERMISSIVE THAN THE ENGRAM. `Ed25519KeyIdentity.verify` uses @noble/curves in
77
+ * its ZIP-215 mode, which checks the cofactored equation and accepts small-order keys and some
78
+ * non-canonical encodings; the engram's check (ic402 2.16.1) is strict RFC 8032 and refuses them.
79
+ * So every receipt the engram accepted verifies here, but not every receipt that verifies here
80
+ * would have been accepted. A receipt under a small-order key derives a principal that is not the
81
+ * owner's, so the comparison above still refuses it. Making this strict needs @noble/curves as a
82
+ * direct dependency (`{ zip215: false }`); that is open.
83
+ *
84
+ * ⟨2026-10-01, the owner's ruling 6 A — supersedes the paragraph above, which stays as the record⟩
85
+ * AS STRICT AS THE ENGRAM. Verified with @noble/curves (a direct dependency of this package) in
86
+ * strict RFC 8032 mode (`zip215: false`): a small-order key, a non-canonical point encoding or a
87
+ * signature with S ≥ L is refused here exactly as the engram's check (ic402 2.16.1) refuses it.
88
+ * Every receipt the engram accepted verifies here, and every receipt that verifies here the engram
89
+ * would have accepted. The principal comparison the relying party makes is now a second check, not
90
+ * the only one. Measured 2026-10-01 with @noble/curves 1.9.7: the all-zero key with R = that key and
91
+ * S = 0 verifies under ZIP-215 (and under `Ed25519KeyIdentity.verify`) for ANY message, and is
92
+ * refused here — test/action-receipt.test.ts pins it. WHAT WOULD MAKE THIS WRONG: the engram's
93
+ * verifier loosening (a newer ic402), or @noble/curves changing what `zip215: false` means.
94
+ * A malformed key or signature (wrong length, a point that does not decode) is `verified: false`,
95
+ * never a throw — a relying party reads one boolean.
37
96
  */
38
97
  export declare function verifyActionReceipt(canisterId: string, operation: string, fields: string, receipt: ActionAuth): {
39
98
  verified: boolean;
@@ -10,8 +10,8 @@
10
10
  // Scope + honesty: this only works for a DIRECT Ed25519 self-authenticating identity (the SDK/CLI
11
11
  // session key). An Internet-Identity-delegated or secp256k1 owner cannot produce a matching receipt —
12
12
  // they omit `ownerAuth` and the action proceeds as before (owner calls are already IC-authenticated).
13
- import { Ed25519KeyIdentity } from '@icp-sdk/core/identity';
14
13
  import { Principal } from '@icp-sdk/core/principal';
14
+ import { ed25519 } from '@noble/curves/ed25519.js';
15
15
  // DER-SPKI prefix for an Ed25519 public key (RFC 8410); DER = this ‖ 32-byte raw key. Kept here so
16
16
  // principal derivation needs no extra API surface and matches IdentityBinding.mo exactly.
17
17
  const ED25519_SPKI_PREFIX = Uint8Array.from([
@@ -49,18 +49,84 @@ export async function signAction(identity, canisterId, operation, fields, nonce)
49
49
  const pubkey = new Uint8Array(identity.getPublicKey().toRaw());
50
50
  return { pubkey, signature, nonce };
51
51
  }
52
+ /**
53
+ * The purpose an enrolment statement names. MUST match src/shared/IdentityBinding.mo
54
+ * `ENROL_OPERATION`.
55
+ */
56
+ export const ENROL_OPERATION = 'agent.enrol';
57
+ /**
58
+ * The message an agent's ROOT key signs to enrol one per-client key on one engram — the owner's
59
+ * decision of 2026-09-28: one root key per agent, with an enrolled key per client. It is
60
+ * `actionMessage` with a fixed purpose, bound to the engram, the enrolled key and the invite code
61
+ * being redeemed (the invite is what makes a statement single-use: the engram burns it). The nonce
62
+ * is free and is NOT a replay guard — see `pairEnrolled` for why it exists.
63
+ * ⟨CORRECTED 2026-09-29, ic402 2.16.1⟩ `pairEnrolled` is gone: the engram's verifier no longer
64
+ * refuses valid signatures, so pairing sends one statement (`EngramClient.pairAgent`).
65
+ * ⟨CORRECTED 2026-09-29, later⟩ The nonce is gone too — it existed only for that re-signing — so
66
+ * the message is `engramx.action.v1|<engram>|agent.enrol|enrolled=<key>|invite=<code>`: the
67
+ * `actionMessage` prefix and parts with no `|nonce=` suffix, built directly here.
68
+ * MUST match src/shared/IdentityBinding.mo `enrolmentMessage` byte-for-byte; the Motoko test
69
+ * test/enrolment.test.mo verifies a signature produced by `signEnrolment` below.
70
+ */
71
+ export function enrolmentMessage(canisterId, enrolledKey, inviteCode) {
72
+ return new TextEncoder().encode(`engramx.action.v1|${canisterId}|${ENROL_OPERATION}|enrolled=${enrolledKey}|invite=${inviteCode}`);
73
+ }
74
+ /**
75
+ * Sign an enrolment statement with the agent's root key. `root` must be an Ed25519 identity (the
76
+ * statement is Ed25519 by construction); `enrolledKey` is the per-client key's principal and
77
+ * `inviteCode` the code that key is about to redeem on `canisterId`.
78
+ */
79
+ export async function signEnrolment(root, canisterId, enrolledKey, inviteCode) {
80
+ const message = enrolmentMessage(canisterId, enrolledKey.toText(), inviteCode);
81
+ return {
82
+ rootPubkey: new Uint8Array(root.getPublicKey().toRaw()),
83
+ engram: Principal.fromText(canisterId),
84
+ enrolledKey,
85
+ signature: new Uint8Array(await root.sign(message)),
86
+ };
87
+ }
52
88
  /** Encode an ActionAuth for the Candid `opt ActionAuth` argument. */
53
89
  export function toCandidActionAuth(a) {
54
90
  return [{ pubkey: Array.from(a.pubkey), signature: Array.from(a.signature), nonce: a.nonce }];
55
91
  }
92
+ /** Strict RFC 8032 Ed25519 verification; a key or signature that does not decode is `false`. */
93
+ function strictVerify(signature, message, pubkey) {
94
+ try {
95
+ return ed25519.verify(signature, message, pubkey, { zip215: false });
96
+ }
97
+ catch {
98
+ return false;
99
+ }
100
+ }
56
101
  /**
57
102
  * Verify a receipt without trusting EngramX: confirm the signature is by `pubkey` over the exact
58
103
  * canonical action, and return the self-authenticating principal that key maps to — i.e. WHO
59
104
  * authorized the action. A relying party compares that principal to the engram's known owner.
105
+ *
106
+ * ⟨2026-09-29⟩ MORE PERMISSIVE THAN THE ENGRAM. `Ed25519KeyIdentity.verify` uses @noble/curves in
107
+ * its ZIP-215 mode, which checks the cofactored equation and accepts small-order keys and some
108
+ * non-canonical encodings; the engram's check (ic402 2.16.1) is strict RFC 8032 and refuses them.
109
+ * So every receipt the engram accepted verifies here, but not every receipt that verifies here
110
+ * would have been accepted. A receipt under a small-order key derives a principal that is not the
111
+ * owner's, so the comparison above still refuses it. Making this strict needs @noble/curves as a
112
+ * direct dependency (`{ zip215: false }`); that is open.
113
+ *
114
+ * ⟨2026-10-01, the owner's ruling 6 A — supersedes the paragraph above, which stays as the record⟩
115
+ * AS STRICT AS THE ENGRAM. Verified with @noble/curves (a direct dependency of this package) in
116
+ * strict RFC 8032 mode (`zip215: false`): a small-order key, a non-canonical point encoding or a
117
+ * signature with S ≥ L is refused here exactly as the engram's check (ic402 2.16.1) refuses it.
118
+ * Every receipt the engram accepted verifies here, and every receipt that verifies here the engram
119
+ * would have accepted. The principal comparison the relying party makes is now a second check, not
120
+ * the only one. Measured 2026-10-01 with @noble/curves 1.9.7: the all-zero key with R = that key and
121
+ * S = 0 verifies under ZIP-215 (and under `Ed25519KeyIdentity.verify`) for ANY message, and is
122
+ * refused here — test/action-receipt.test.ts pins it. WHAT WOULD MAKE THIS WRONG: the engram's
123
+ * verifier loosening (a newer ic402), or @noble/curves changing what `zip215: false` means.
124
+ * A malformed key or signature (wrong length, a point that does not decode) is `verified: false`,
125
+ * never a throw — a relying party reads one boolean.
60
126
  */
61
127
  export function verifyActionReceipt(canisterId, operation, fields, receipt) {
62
128
  const message = actionMessage(canisterId, operation, fields, receipt.nonce);
63
- const verified = Ed25519KeyIdentity.verify(receipt.signature, message, receipt.pubkey);
129
+ const verified = strictVerify(receipt.signature, message, receipt.pubkey);
64
130
  const principal = Principal.selfAuthenticating(derOf(receipt.pubkey)).toText();
65
131
  return { verified, principal };
66
132
  }
@@ -1 +1 @@
1
- {"version":3,"file":"actionReceipt.js","sourceRoot":"","sources":["../src/actionReceipt.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"actionReceipt.js","sourceRoot":"","sources":["../src/actionReceipt.ts"],"names":[],"mappings":"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"}
package/dist/auth.d.ts CHANGED
@@ -15,3 +15,19 @@ export declare function identityFromSeed(seed: Uint8Array): Ed25519KeyIdentity;
15
15
  * Returns the identity.
16
16
  */
17
17
  export declare function generateSessionKey(keyPath: string): Ed25519KeyIdentity;
18
+ /**
19
+ * Load the agent's ROOT key, or create it the first time. ⟨2026-09-28, owner decision: one root key
20
+ * per agent, with an enrolled key per client⟩
21
+ *
22
+ * The root is the agent's lasting identity: the registry keeps its track record under this key's
23
+ * principal, and it signs one enrolment statement per client. So, unlike a per-client session key,
24
+ * it is NEVER regenerated once it exists — a new root is a new agent with an empty record. Same
25
+ * 32-byte seed file format and the same refusals (symlink, loose permissions, wrong size) as a
26
+ * session key, because it is the more valuable of the two.
27
+ * WHAT WOULD MAKE THIS WRONG: a caller that deletes and re-creates this file to "fix" an error —
28
+ * that silently starts a new agent.
29
+ */
30
+ export declare function loadOrCreateRootKey(rootKeyPath: string): {
31
+ identity: Ed25519KeyIdentity;
32
+ created: boolean;
33
+ };
package/dist/auth.js CHANGED
@@ -2,6 +2,7 @@ import { Ed25519KeyIdentity } from '@icp-sdk/core/identity';
2
2
  import * as fs from 'fs';
3
3
  import * as path from 'path';
4
4
  import * as crypto from 'crypto';
5
+ import { VERSION } from './version.js';
5
6
  /**
6
7
  * Load or create an Ed25519 session key identity.
7
8
  *
@@ -17,23 +18,23 @@ export function loadSessionKey(keyPath) {
17
18
  // Refuse to load symlinked key files
18
19
  const lstat = fs.lstatSync(resolvedPath);
19
20
  if (lstat.isSymbolicLink()) {
20
- throw new Error(`Session key cannot be a symlink: ${resolvedPath}`);
21
+ throw new Error(`The key for this engram cannot be a symlink: ${resolvedPath}`);
21
22
  }
22
23
  // Refuse to load key files with overly permissive permissions
23
24
  const stats = fs.statSync(resolvedPath);
24
25
  const mode = stats.mode & 0o777;
25
26
  if (mode & 0o077) {
26
- throw new Error(`Session key ${resolvedPath} has insecure permissions (${mode.toString(8)}). ` +
27
+ throw new Error(`The key for this engram (${resolvedPath}) has insecure permissions (${mode.toString(8)}). ` +
27
28
  `Expected 0600. Fix with: chmod 600 ${resolvedPath}`);
28
29
  }
29
30
  const seed = fs.readFileSync(resolvedPath);
30
31
  if (seed.length !== 32) {
31
- throw new Error(`Invalid session key: expected 32 bytes, got ${seed.length}`);
32
+ throw new Error(`Invalid key for this engram: expected 32 bytes, got ${seed.length}`);
32
33
  }
33
34
  return Ed25519KeyIdentity.generate(seed);
34
35
  }
35
- throw new Error(`Session key not found. ` +
36
- `Run 'pnpm dlx @engramx/client pair <invite-code> --engram <canister-id>' to create one.`);
36
+ throw new Error(`The key for this engram was not found. ` +
37
+ `Run 'pnpm dlx @engramx/client@${VERSION} pair <invite-code> --engram <canister-id>' to create one.`);
37
38
  }
38
39
  /**
39
40
  * Create an Ed25519 identity from a raw 32-byte seed.
@@ -62,4 +63,36 @@ export function generateSessionKey(keyPath) {
62
63
  fs.writeFileSync(resolvedPath, seed, { mode: 0o600 });
63
64
  return Ed25519KeyIdentity.generate(seed);
64
65
  }
66
+ /**
67
+ * Load the agent's ROOT key, or create it the first time. ⟨2026-09-28, owner decision: one root key
68
+ * per agent, with an enrolled key per client⟩
69
+ *
70
+ * The root is the agent's lasting identity: the registry keeps its track record under this key's
71
+ * principal, and it signs one enrolment statement per client. So, unlike a per-client session key,
72
+ * it is NEVER regenerated once it exists — a new root is a new agent with an empty record. Same
73
+ * 32-byte seed file format and the same refusals (symlink, loose permissions, wrong size) as a
74
+ * session key, because it is the more valuable of the two.
75
+ * WHAT WOULD MAKE THIS WRONG: a caller that deletes and re-creates this file to "fix" an error —
76
+ * that silently starts a new agent.
77
+ */
78
+ export function loadOrCreateRootKey(rootKeyPath) {
79
+ const home = process.env['HOME'];
80
+ if (rootKeyPath.startsWith('~') && !home)
81
+ throw new Error('HOME environment variable is not set');
82
+ const resolvedPath = rootKeyPath.startsWith('~')
83
+ ? path.join(home, rootKeyPath.slice(1))
84
+ : rootKeyPath;
85
+ // lstat, not exists: a dangling symlink must reach loadSessionKey's symlink refusal rather than
86
+ // read as "no root yet" and be overwritten by a fresh one.
87
+ let present = true;
88
+ try {
89
+ fs.lstatSync(resolvedPath);
90
+ }
91
+ catch {
92
+ present = false;
93
+ }
94
+ if (present)
95
+ return { identity: loadSessionKey(rootKeyPath), created: false };
96
+ return { identity: generateSessionKey(rootKeyPath), created: true };
97
+ }
65
98
  //# sourceMappingURL=auth.js.map
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -32,16 +32,38 @@ export interface CertifiedLeaf {
32
32
  why: string;
33
33
  }
34
34
  /** Verify one leaf of a certified tree (registry format). */
35
+ /**
36
+ * Unwrap a Candid `opt blob` as agent-js delivers it — 0- or 1-element array, or bare bytes.
37
+ *
38
+ * THE DEFECT THIS EXISTS FOR. `certificate` AND `witness` are both `opt blob` on the wire
39
+ * (`CertifiedAuditHead` in registry.did and engram.did). This unwrap was applied to `certificate`
40
+ * only; `witness` was passed straight to `Uint8Array.from(witness as number[])`. That does not
41
+ * throw. `Uint8Array.from([<Uint8Array>])` coerces its one element with `Number()`, which is NaN
42
+ * for a typed array, and NaN clamps to 0 — so a perfectly good witness became the ONE-BYTE array
43
+ * `[0]`. `Cbor.decode` reads 0x00 as the integer 0 and SUCCEEDS, so the "witness is not decodable
44
+ * CBOR" guard passed it, and `reconstruct(0)` fell out of its NodeType switch into
45
+ * `throw UNREACHABLE_ERROR`. The whole failure reached the caller as a bare `Error: unreachable`
46
+ * with an async stack vitest could not map. Measured 2026-08-25.
47
+ *
48
+ * The lesson generalises past this file: an opt read as bare bytes fails SILENTLY here rather than
49
+ * at the decoder, because every step downstream accepts the corrupted value. Unwrap at one place,
50
+ * for every opt-blob field, or the next field added repeats it.
51
+ *
52
+ * WHAT WOULD MAKE THIS WRONG: it tells a wrapper from bare bytes by the FIRST ELEMENT — a wrapper
53
+ * is empty, or holds an array/Uint8Array; bare bytes hold a number. A `number[][]` would be read
54
+ * as a wrapper, but no opt-blob field on this wire has that shape.
55
+ */
56
+ export declare function optBytes(v: unknown): Uint8Array | number[] | null;
35
57
  export declare function verifyCertifiedLeaf(agent: HttpAgent, canisterId: Principal | string, reply: {
36
58
  certificate: [] | [Uint8Array | number[]] | Uint8Array | number[];
37
- witness: Uint8Array | number[];
59
+ witness: [] | [Uint8Array | number[]] | Uint8Array | number[];
38
60
  }, path: Uint8Array[]): Promise<CertifiedLeaf>;
39
61
  /** Registry audit head, tree format — pair with the registry's getCertifiedHead(). */
40
62
  export declare function verifyCertifiedRegistryHead(agent: HttpAgent, canisterId: Principal | string, reply: {
41
63
  headHash: Uint8Array | number[];
42
64
  size: bigint;
43
65
  certificate: [] | [Uint8Array | number[]];
44
- witness: Uint8Array | number[];
66
+ witness: [] | [Uint8Array | number[]] | Uint8Array | number[];
45
67
  }): Promise<{
46
68
  head: Uint8Array | null;
47
69
  size: bigint;
@@ -52,13 +74,17 @@ export declare function verifyCertifiedRegistryHead(agent: HttpAgent, canisterId
52
74
  * An engram's latest anchor, certified — pair with the registry's getCertifiedAnchor(engramId).
53
75
  *
54
76
  * The proven leaf bytes decode (standard Candid) to CertifiedAnchorLeaf v2:
55
- * { version: nat (=2); engram: principal; total: nat; head: blob; at: int;
56
- * wasmHash: text ("" = never installed by this registry); conflicts: nat; disputed: bool }
57
- * `disputed` says whether THIS head is the contradicted one; `wasmHash` attests the registry's own
77
+ * { version: nat (=2); engram: principal; total: nat; head: blob; atNs: int;
78
+ * wasmHash: text ("" = never installed by this registry); conflicts: nat; disputed: bool;
79
+ * refusedConflicts: nat }
80
+ * `disputed` says whether THIS head is the contradicted one; `refusedConflicts` counts the
81
+ * contradictory pushes refused once the engram reached the registry's per-engram cap (every
82
+ * recorded contradiction is kept forever — added 2026-09-28, owner decision on contradiction
83
+ * records); `wasmHash` attests the registry's own
58
84
  * install record (not a live probe), refreshed at each leaf write.
59
85
  */
60
86
  export declare function verifyCertifiedAnchor(agent: HttpAgent, registryId: Principal | string, engramId: Principal | string, reply: {
61
87
  leaf: unknown;
62
88
  certificate: [] | [Uint8Array | number[]];
63
- witness: Uint8Array | number[];
89
+ witness: [] | [Uint8Array | number[]] | Uint8Array | number[];
64
90
  }): Promise<CertifiedLeaf>;
@@ -63,18 +63,44 @@ export async function verifyCertifiedAuditHead(agent, canisterId, claimed) {
63
63
  import { Cbor, reconstruct, lookup_path } from '@icp-sdk/core/agent';
64
64
  const utf8 = (s) => new TextEncoder().encode(s);
65
65
  /** Verify one leaf of a certified tree (registry format). */
66
+ /**
67
+ * Unwrap a Candid `opt blob` as agent-js delivers it — 0- or 1-element array, or bare bytes.
68
+ *
69
+ * THE DEFECT THIS EXISTS FOR. `certificate` AND `witness` are both `opt blob` on the wire
70
+ * (`CertifiedAuditHead` in registry.did and engram.did). This unwrap was applied to `certificate`
71
+ * only; `witness` was passed straight to `Uint8Array.from(witness as number[])`. That does not
72
+ * throw. `Uint8Array.from([<Uint8Array>])` coerces its one element with `Number()`, which is NaN
73
+ * for a typed array, and NaN clamps to 0 — so a perfectly good witness became the ONE-BYTE array
74
+ * `[0]`. `Cbor.decode` reads 0x00 as the integer 0 and SUCCEEDS, so the "witness is not decodable
75
+ * CBOR" guard passed it, and `reconstruct(0)` fell out of its NodeType switch into
76
+ * `throw UNREACHABLE_ERROR`. The whole failure reached the caller as a bare `Error: unreachable`
77
+ * with an async stack vitest could not map. Measured 2026-08-25.
78
+ *
79
+ * The lesson generalises past this file: an opt read as bare bytes fails SILENTLY here rather than
80
+ * at the decoder, because every step downstream accepts the corrupted value. Unwrap at one place,
81
+ * for every opt-blob field, or the next field added repeats it.
82
+ *
83
+ * WHAT WOULD MAKE THIS WRONG: it tells a wrapper from bare bytes by the FIRST ELEMENT — a wrapper
84
+ * is empty, or holds an array/Uint8Array; bare bytes hold a number. A `number[][]` would be read
85
+ * as a wrapper, but no opt-blob field on this wire has that shape.
86
+ */
87
+ // EXPORTED for the regression test in packages/client/test/certified-tree.test.ts, and NOT
88
+ // re-exported from index.ts — the published surface is unchanged. The witness path cannot be
89
+ // reached from a test without a real subnet signature (Certificate.create fails first), so
90
+ // testing the unwrap directly is the only coverage this defect class can actually have.
91
+ export function optBytes(v) {
92
+ return Array.isArray(v) && (v.length === 0 || Array.isArray(v[0]) || v[0] instanceof Uint8Array)
93
+ ? v.length
94
+ ? v[0]
95
+ : null
96
+ : v;
97
+ }
66
98
  export async function verifyCertifiedLeaf(agent, canisterId, reply, path) {
67
99
  const fail = (why) => ({ valueBytes: null, verified: false, why });
68
- const raw = reply?.certificate;
69
- const certBytes = Array.isArray(raw) &&
70
- (raw.length === 0 || Array.isArray(raw[0]) || raw[0] instanceof Uint8Array)
71
- ? raw.length
72
- ? raw[0]
73
- : null
74
- : raw;
100
+ const certBytes = optBytes(reply?.certificate);
75
101
  if (!certBytes || certBytes.length === 0)
76
102
  return fail('no certificate on the reply');
77
- const witness = reply?.witness;
103
+ const witness = optBytes(reply?.witness);
78
104
  if (!witness || witness.length === 0)
79
105
  return fail('no witness on the reply');
80
106
  const principal = typeof canisterId === 'string' ? Principal.fromText(canisterId) : canisterId;
@@ -92,7 +118,19 @@ export async function verifyCertifiedLeaf(agent, canisterId, reply, path) {
92
118
  catch {
93
119
  return fail('certificate did not verify against the root key');
94
120
  }
95
- const lookup = cert.lookup_path(['canister', principal.toUint8Array(), 'certified_data']);
121
+ // ⟨2026-08-25⟩ WRAPPED, like every other step in this function. `lookup_path` can THROW rather
122
+ // than return a status: @icp-sdk's `agent/certificate.ts` raises a bare `UNREACHABLE_ERROR` from
123
+ // its tree walk, and it was the only unguarded call here — so a malformed or unexpected tree
124
+ // escaped this verifier entirely and surfaced as `Error: unreachable` with an async stack vitest
125
+ // could not map. A verifier whose failure mode is an opaque crash cannot be used to decide
126
+ // whether evidence is good, which is the whole reason it exists.
127
+ let lookup;
128
+ try {
129
+ lookup = cert.lookup_path(['canister', principal.toUint8Array(), 'certified_data']);
130
+ }
131
+ catch (e) {
132
+ return fail(`certificate tree walk failed: ${e.message}`);
133
+ }
96
134
  if (lookup.status !== LookupPathStatus.Found)
97
135
  return fail('certified_data absent from certificate');
98
136
  const certifiedData = new Uint8Array(lookupResultToBuffer(lookup));
@@ -103,12 +141,31 @@ export async function verifyCertifiedLeaf(agent, canisterId, reply, path) {
103
141
  catch {
104
142
  return fail('witness is not decodable CBOR');
105
143
  }
106
- const rootHash = new Uint8Array(await reconstruct(tree));
144
+ // ⟨2026-08-25⟩ GUARDED. `reconstruct` and `lookup_path` are the SDK's two `UNREACHABLE_ERROR`
145
+ // throw sites reachable from here (certificate.ts, one in each), and both fire on a tree whose
146
+ // node tag they do not recognise — exactly what a witness that decoded to something other than a
147
+ // hash tree produces. Unguarded, that left this verifier as the one path in the client that
148
+ // reported neither `verified: true` nor a `why`: it threw a bare `Error: unreachable` past every
149
+ // caller. A verifier that cannot say why it failed to verify is the fail-to-empty class wearing
150
+ // the instrument's uniform, so both now come back as a refusal WITH a reason.
151
+ let rootHash;
152
+ try {
153
+ rootHash = new Uint8Array(await reconstruct(tree));
154
+ }
155
+ catch {
156
+ return fail('witness is decodable CBOR but not a hash tree');
157
+ }
107
158
  if (rootHash.length !== certifiedData.length ||
108
159
  !rootHash.every((b, i) => b === certifiedData[i])) {
109
160
  return fail('witness root does not match certified_data');
110
161
  }
111
- const leaf = lookup_path(path, tree);
162
+ let leaf;
163
+ try {
164
+ leaf = lookup_path(path, tree);
165
+ }
166
+ catch {
167
+ return fail('witness tree is malformed at the requested path');
168
+ }
112
169
  if (leaf.status !== LookupPathStatus.Found)
113
170
  return fail('path not found in witness');
114
171
  return { valueBytes: new Uint8Array(lookupResultToBuffer(leaf)), verified: true, why: 'ok' };
@@ -131,9 +188,13 @@ export async function verifyCertifiedRegistryHead(agent, canisterId, reply) {
131
188
  * An engram's latest anchor, certified — pair with the registry's getCertifiedAnchor(engramId).
132
189
  *
133
190
  * The proven leaf bytes decode (standard Candid) to CertifiedAnchorLeaf v2:
134
- * { version: nat (=2); engram: principal; total: nat; head: blob; at: int;
135
- * wasmHash: text ("" = never installed by this registry); conflicts: nat; disputed: bool }
136
- * `disputed` says whether THIS head is the contradicted one; `wasmHash` attests the registry's own
191
+ * { version: nat (=2); engram: principal; total: nat; head: blob; atNs: int;
192
+ * wasmHash: text ("" = never installed by this registry); conflicts: nat; disputed: bool;
193
+ * refusedConflicts: nat }
194
+ * `disputed` says whether THIS head is the contradicted one; `refusedConflicts` counts the
195
+ * contradictory pushes refused once the engram reached the registry's per-engram cap (every
196
+ * recorded contradiction is kept forever — added 2026-09-28, owner decision on contradiction
197
+ * records); `wasmHash` attests the registry's own
137
198
  * install record (not a live probe), refreshed at each leaf write.
138
199
  */
139
200
  export async function verifyCertifiedAnchor(agent, registryId, engramId, reply) {
@@ -1 +1 @@
1
- {"version":3,"file":"certifiedAudit.js","sourceRoot":"","sources":["../src/certifiedAudit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"certifiedAudit.js","sourceRoot":"","sources":["../src/certifiedAudit.ts"],"names":[],"mappings":"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"}