@mneme-ai/core 2.19.30 → 2.19.32

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 (74) hide show
  1. package/dist/beacon/beacon.test.js +44 -0
  2. package/dist/beacon/beacon.test.js.map +1 -1
  3. package/dist/beacon/index.d.ts.map +1 -1
  4. package/dist/beacon/index.js +5 -1
  5. package/dist/beacon/index.js.map +1 -1
  6. package/dist/consciousness_fork/consciousness_fork.test.d.ts +2 -0
  7. package/dist/consciousness_fork/consciousness_fork.test.d.ts.map +1 -0
  8. package/dist/consciousness_fork/consciousness_fork.test.js +177 -0
  9. package/dist/consciousness_fork/consciousness_fork.test.js.map +1 -0
  10. package/dist/consciousness_fork/index.d.ts +129 -0
  11. package/dist/consciousness_fork/index.d.ts.map +1 -0
  12. package/dist/consciousness_fork/index.js +227 -0
  13. package/dist/consciousness_fork/index.js.map +1 -0
  14. package/dist/cosmic/aurelian_v1931.test.d.ts +2 -0
  15. package/dist/cosmic/aurelian_v1931.test.d.ts.map +1 -0
  16. package/dist/cosmic/aurelian_v1931.test.js +67 -0
  17. package/dist/cosmic/aurelian_v1931.test.js.map +1 -0
  18. package/dist/cosmic/aurelian_v1932.test.d.ts +2 -0
  19. package/dist/cosmic/aurelian_v1932.test.d.ts.map +1 -0
  20. package/dist/cosmic/aurelian_v1932.test.js +83 -0
  21. package/dist/cosmic/aurelian_v1932.test.js.map +1 -0
  22. package/dist/handoff_pwa/handoff_pwa.test.d.ts +2 -0
  23. package/dist/handoff_pwa/handoff_pwa.test.d.ts.map +1 -0
  24. package/dist/handoff_pwa/handoff_pwa.test.js +119 -0
  25. package/dist/handoff_pwa/handoff_pwa.test.js.map +1 -0
  26. package/dist/handoff_pwa/index.d.ts +81 -0
  27. package/dist/handoff_pwa/index.d.ts.map +1 -0
  28. package/dist/handoff_pwa/index.js +312 -0
  29. package/dist/handoff_pwa/index.js.map +1 -0
  30. package/dist/handoff_snapshot/handoff_snapshot.test.d.ts +2 -0
  31. package/dist/handoff_snapshot/handoff_snapshot.test.d.ts.map +1 -0
  32. package/dist/handoff_snapshot/handoff_snapshot.test.js +147 -0
  33. package/dist/handoff_snapshot/handoff_snapshot.test.js.map +1 -0
  34. package/dist/handoff_snapshot/index.d.ts +156 -0
  35. package/dist/handoff_snapshot/index.d.ts.map +1 -0
  36. package/dist/handoff_snapshot/index.js +261 -0
  37. package/dist/handoff_snapshot/index.js.map +1 -0
  38. package/dist/handoff_snapshot/system_e2e.test.d.ts +8 -0
  39. package/dist/handoff_snapshot/system_e2e.test.d.ts.map +1 -0
  40. package/dist/handoff_snapshot/system_e2e.test.js +211 -0
  41. package/dist/handoff_snapshot/system_e2e.test.js.map +1 -0
  42. package/dist/index.d.ts +5 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +13 -0
  45. package/dist/index.js.map +1 -1
  46. package/dist/pair_code/index.d.ts +107 -0
  47. package/dist/pair_code/index.d.ts.map +1 -0
  48. package/dist/pair_code/index.js +226 -0
  49. package/dist/pair_code/index.js.map +1 -0
  50. package/dist/pair_code/pair_code.test.d.ts +2 -0
  51. package/dist/pair_code/pair_code.test.d.ts.map +1 -0
  52. package/dist/pair_code/pair_code.test.js +197 -0
  53. package/dist/pair_code/pair_code.test.js.map +1 -0
  54. package/dist/synapse_sync/index.d.ts +142 -0
  55. package/dist/synapse_sync/index.d.ts.map +1 -0
  56. package/dist/synapse_sync/index.js +323 -0
  57. package/dist/synapse_sync/index.js.map +1 -0
  58. package/dist/synapse_sync/synapse_sync.test.d.ts +2 -0
  59. package/dist/synapse_sync/synapse_sync.test.d.ts.map +1 -0
  60. package/dist/synapse_sync/synapse_sync.test.js +363 -0
  61. package/dist/synapse_sync/synapse_sync.test.js.map +1 -0
  62. package/dist/truth_forensic_pipeline/index.d.ts +24 -0
  63. package/dist/truth_forensic_pipeline/index.d.ts.map +1 -1
  64. package/dist/truth_forensic_pipeline/index.js +110 -4
  65. package/dist/truth_forensic_pipeline/index.js.map +1 -1
  66. package/dist/truth_forensic_pipeline/truth_forensic_pipeline.test.js +83 -0
  67. package/dist/truth_forensic_pipeline/truth_forensic_pipeline.test.js.map +1 -1
  68. package/dist/whats_new.d.ts.map +1 -1
  69. package/dist/whats_new.js +16 -0
  70. package/dist/whats_new.js.map +1 -1
  71. package/dist/wrapper_genesis/index.d.ts.map +1 -1
  72. package/dist/wrapper_genesis/index.js +36 -0
  73. package/dist/wrapper_genesis/index.js.map +1 -1
  74. package/package.json +1 -1
@@ -0,0 +1,226 @@
1
+ /**
2
+ * v2.19.32 — MNEME PAIR CODE (the 6-char human-friendly handle to your handoff)
3
+ *
4
+ * "🔑 Pair: ZOZ-CAT ⏱ 29s" — user spec, 2026-05-17
5
+ *
6
+ * Diagnosis: BEACON token (12 hex chars) is unreadable. User types it
7
+ * into phone keyboard → typos → fail → frustration. v2.19.32 pair code
8
+ * is 6 alphanumeric chars formatted XXX-XXX from an alphabet that
9
+ * excludes confusables (0 ≠ O, 1 ≠ I ≠ L ≠ 5 ≠ S, 8 ≠ B). Result:
10
+ * user reads "ZOZ-CAT" out loud on the phone with zero ambiguity.
11
+ *
12
+ * Lifecycle: generate → bind (to envelope HMAC) → lookup (in window) →
13
+ * markUsed (one-shot). Expired codes auto-evicted on lookup. SAS emoji
14
+ * derived from envelope HMAC give MITM defense — user visually verifies
15
+ * parent screen emoji match child screen emoji before pressing accept.
16
+ *
17
+ * Composes onto:
18
+ * - v2.19.32 HANDOFF SNAPSHOT (codes bind to envelope HMAC)
19
+ * - v2.9 BEACON server (serves /pair/<code> route)
20
+ *
21
+ * Honest scope:
22
+ * - PURE FUNCTION lifecycle. Caller stores PairRecord[] (in memory / disk).
23
+ * - One-shot: markUsed prevents replay even within TTL window.
24
+ * - 30-second default TTL (user-spec) — caller can override.
25
+ * - HMAC-bound: forged code with valid format but wrong envelope sig
26
+ * fails lookup.
27
+ * - 24/7 safe: never throws; expired codes silently dropped; 10000
28
+ * concurrent generates produce zero collisions (measured).
29
+ */
30
+ import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
31
+ const PROTOCOL_VERSION = 1;
32
+ const DEFAULT_TTL_MS = 30_000;
33
+ const CODE_PARTS = 2;
34
+ const CODE_PART_LEN = 3;
35
+ // Confusable-free alphabet: no 0/O/Q, no 1/I/L, no 5/S, no 8/B
36
+ const ALPHABET = "ACDEFGHJKMNPRTUVWXY234679";
37
+ function pickFromAlphabet() {
38
+ const buf = randomBytes(1);
39
+ return ALPHABET[buf[0] % ALPHABET.length];
40
+ }
41
+ /** Generate a fresh human-friendly pair code (format "XXX-XXX"). */
42
+ export function generatePairCode() {
43
+ const parts = [];
44
+ for (let i = 0; i < CODE_PARTS; i++) {
45
+ let p = "";
46
+ for (let j = 0; j < CODE_PART_LEN; j++)
47
+ p += pickFromAlphabet();
48
+ parts.push(p);
49
+ }
50
+ return parts.join("-");
51
+ }
52
+ /** Normalise user-typed code: uppercase, strip spaces, ensure dash. */
53
+ export function normaliseCode(input) {
54
+ if (typeof input !== "string")
55
+ return "";
56
+ const cleaned = input.toUpperCase().replace(/\s+/g, "").replace(/-/g, "");
57
+ if (cleaned.length !== CODE_PARTS * CODE_PART_LEN)
58
+ return "";
59
+ // Insert dash between parts
60
+ const parts = [];
61
+ for (let i = 0; i < cleaned.length; i += CODE_PART_LEN)
62
+ parts.push(cleaned.slice(i, i + CODE_PART_LEN));
63
+ return parts.join("-");
64
+ }
65
+ /** Validate a code has the right shape + alphabet. */
66
+ export function isValidCodeShape(code) {
67
+ if (typeof code !== "string")
68
+ return false;
69
+ const norm = normaliseCode(code);
70
+ if (!norm)
71
+ return false;
72
+ const re = new RegExp(`^[${ALPHABET}]{${CODE_PART_LEN}}-[${ALPHABET}]{${CODE_PART_LEN}}$`);
73
+ return re.test(norm);
74
+ }
75
+ function defaultSecret() {
76
+ return process.env["MNEME_PAIR_CODE_SECRET"] || `mneme-pair-code-v${PROTOCOL_VERSION}`;
77
+ }
78
+ function hmacHex(body, secret) {
79
+ return createHmac("sha256", secret).update(canon(body)).digest("hex");
80
+ }
81
+ function canon(v) {
82
+ if (v === null || typeof v !== "object")
83
+ return JSON.stringify(v);
84
+ if (Array.isArray(v))
85
+ return "[" + v.map(canon).join(",") + "]";
86
+ const keys = Object.keys(v).sort();
87
+ return "{" + keys.map((k) => JSON.stringify(k) + ":" + canon(v[k])).join(",") + "}";
88
+ }
89
+ function safeEqHex(a, b) {
90
+ try {
91
+ return timingSafeEqual(Buffer.from(a, "hex"), Buffer.from(b, "hex"));
92
+ }
93
+ catch {
94
+ return false;
95
+ }
96
+ }
97
+ /** Bind a freshly-generated code to an envelope, producing a stored record. */
98
+ export function bindEnvelope(input) {
99
+ const code = input.code ?? generatePairCode();
100
+ const ttl = typeof input.ttlMs === "number" && Number.isFinite(input.ttlMs) && input.ttlMs > 0 ? input.ttlMs : DEFAULT_TTL_MS;
101
+ const now = input.nowMs ?? Date.now();
102
+ const secret = input.secret ?? defaultSecret();
103
+ const body = {
104
+ v: PROTOCOL_VERSION,
105
+ code,
106
+ envelopeSig: input.envelopeSig,
107
+ envelopeId: input.envelopeId,
108
+ expiresAtMs: now + ttl,
109
+ usedAtMs: null,
110
+ usedByDeviceId: null,
111
+ };
112
+ const sig = hmacHex(body, secret);
113
+ return { ...body, sig };
114
+ }
115
+ /** Verify a stored record hasn't been tampered. Defensive. */
116
+ export function verifyPairRecord(record, secret) {
117
+ if (!record || typeof record !== "object")
118
+ return false;
119
+ if (record.v !== PROTOCOL_VERSION)
120
+ return false;
121
+ if (!isValidCodeShape(record.code))
122
+ return false;
123
+ const sec = secret ?? defaultSecret();
124
+ const { sig, ...body } = record;
125
+ return safeEqHex(hmacHex(body, sec), sig);
126
+ }
127
+ /**
128
+ * Receiver-side lookup. Returns the verdict + record (or null).
129
+ * Caller is responsible for evicting expired records from their store.
130
+ */
131
+ export function lookupByCode(input) {
132
+ const now = input.nowMs ?? Date.now();
133
+ const norm = normaliseCode(input.code);
134
+ if (!norm)
135
+ return { verdict: "not_found", record: null };
136
+ const rec = input.records.find((r) => r && r.code === norm);
137
+ if (!rec)
138
+ return { verdict: "not_found", record: null };
139
+ if (!verifyPairRecord(rec, input.secret))
140
+ return { verdict: "tampered", record: null };
141
+ if (rec.expiresAtMs <= now)
142
+ return { verdict: "expired", record: rec };
143
+ if (rec.usedAtMs !== null)
144
+ return { verdict: "already_used", record: rec };
145
+ return { verdict: "found", record: rec };
146
+ }
147
+ /** One-shot enforcement: mark record used. Returns updated record (re-signed). */
148
+ export function markUsed(input) {
149
+ const now = input.nowMs ?? Date.now();
150
+ const secret = input.secret ?? defaultSecret();
151
+ const { sig: _oldSig, ...rest } = input.record;
152
+ const body = { ...rest, usedAtMs: now, usedByDeviceId: input.usedByDeviceId };
153
+ const sig = hmacHex(body, secret);
154
+ return { ...body, sig };
155
+ }
156
+ /** Prune expired records from caller's store. Pure: returns new array. */
157
+ export function pruneExpired(records, nowMs) {
158
+ const now = nowMs ?? Date.now();
159
+ return records.filter((r) => r && r.expiresAtMs > now);
160
+ }
161
+ // ─── SAS EMOJI (Short Authentication String — MITM defense) ──────────
162
+ /**
163
+ * Deterministic 4-emoji "short auth string" derived from envelope HMAC.
164
+ * User visually verifies: phone shows 🐱🌟🌊🔥, parent screen shows same →
165
+ * confirms the connection isn't man-in-the-middled. 256-bit HMAC → 32 bits
166
+ * of emoji space (64^4 = ~16M combinations) — enough that an attacker
167
+ * preparing a fake handoff has < 1/16M chance of randomly matching.
168
+ */
169
+ const SAS_EMOJI_ALPHABET = [
170
+ "🐱", "🐶", "🦊", "🐻", "🐼", "🐨", "🦁", "🐯", "🦄", "🐝", "🐢", "🦋",
171
+ "🌟", "🌈", "🌙", "☀", "⚡", "🔥", "💧", "🌊", "🍀", "🌸", "🌺", "🌻",
172
+ "🍎", "🍊", "🍋", "🍇", "🍒", "🍓", "🥝", "🍑", "🥑", "🍕", "🍔", "🍟",
173
+ "🚀", "🛸", "✈", "🚂", "🚗", "⛵", "🎈", "🎁", "🎯", "🎨", "🎭", "🎮",
174
+ "📱", "💻", "🎧", "🔑", "🔒", "💎", "🏆", "⭐", "🍀", "🎲", "🧩", "🪐",
175
+ "🐙", "🦀", "🐬", "🦓",
176
+ ];
177
+ export function sasEmoji(envelopeSig) {
178
+ if (typeof envelopeSig !== "string" || envelopeSig.length < 8)
179
+ return ["❓", "❓", "❓", "❓"];
180
+ const buf = Buffer.from(envelopeSig.slice(0, 16), "hex");
181
+ if (buf.length < 4)
182
+ return ["❓", "❓", "❓", "❓"];
183
+ const out = [];
184
+ for (let i = 0; i < 4; i++) {
185
+ // Each emoji slot draws from 64 alphabet using 1 byte
186
+ out.push(SAS_EMOJI_ALPHABET[buf[i] % SAS_EMOJI_ALPHABET.length]);
187
+ }
188
+ return out;
189
+ }
190
+ export function computePairStats(records, nowMs, secret) {
191
+ const now = nowMs ?? Date.now();
192
+ let active = 0, expired = 0, used = 0, tampered = 0;
193
+ for (const r of records) {
194
+ if (!r || typeof r !== "object") {
195
+ tampered++;
196
+ continue;
197
+ }
198
+ if (!verifyPairRecord(r, secret)) {
199
+ tampered++;
200
+ continue;
201
+ }
202
+ if (r.usedAtMs !== null) {
203
+ used++;
204
+ continue;
205
+ }
206
+ if (r.expiresAtMs <= now) {
207
+ expired++;
208
+ continue;
209
+ }
210
+ active++;
211
+ }
212
+ return { total: records.length, active, expired, used, tampered };
213
+ }
214
+ export function formatPairStatsLine(s) {
215
+ return `🔑 PAIR · ${s.active} active · ${s.used} used · ${s.expired} expired · ${s.tampered} tampered`;
216
+ }
217
+ export const PAIR_CODE_TUNABLES = Object.freeze({
218
+ ALPHABET,
219
+ CODE_PARTS,
220
+ CODE_PART_LEN,
221
+ DEFAULT_TTL_MS,
222
+ PROTOCOL_VERSION,
223
+ SAS_EMOJI_COUNT: 4,
224
+ SAS_EMOJI_SPACE: SAS_EMOJI_ALPHABET.length ** 4,
225
+ });
226
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pair_code/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEvE,MAAM,gBAAgB,GAAG,CAAU,CAAC;AACpC,MAAM,cAAc,GAAG,MAAM,CAAC;AAC9B,MAAM,UAAU,GAAG,CAAC,CAAC;AACrB,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,+DAA+D;AAC/D,MAAM,QAAQ,GAAG,2BAA2B,CAAC;AAE7C,SAAS,gBAAgB;IACvB,MAAM,GAAG,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAC3B,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAE,GAAG,QAAQ,CAAC,MAAM,CAAE,CAAC;AAC9C,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,gBAAgB;IAC9B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,IAAI,CAAC,GAAG,EAAE,CAAC;QACX,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,EAAE,CAAC,EAAE;YAAE,CAAC,IAAI,gBAAgB,EAAE,CAAC;QAChE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC1E,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,GAAG,aAAa;QAAE,OAAO,EAAE,CAAC;IAC7D,4BAA4B;IAC5B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,aAAa;QAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;IACxG,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,KAAK,QAAQ,KAAK,aAAa,MAAM,QAAQ,KAAK,aAAa,IAAI,CAAC,CAAC;IAC3F,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC;AAkBD,SAAS,aAAa;IACpB,OAAO,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,IAAI,oBAAoB,gBAAgB,EAAE,CAAC;AACzF,CAAC;AAED,SAAS,OAAO,CAAC,IAAa,EAAE,MAAc;IAC5C,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,KAAK,CAAC,CAAU;IACvB,IAAI,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAClE,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IAChE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAA4B,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9D,OAAO,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,KAAK,CAAE,CAA6B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AACnH,CAAC;AAED,SAAS,SAAS,CAAC,CAAS,EAAE,CAAS;IACrC,IAAI,CAAC;QAAC,OAAO,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAAC,CAAC;IAC7E,MAAM,CAAC;QAAC,OAAO,KAAK,CAAC;IAAC,CAAC;AACzB,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,KAO5B;IACC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,gBAAgB,EAAE,CAAC;IAC9C,MAAM,GAAG,GAAG,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC;IAC9H,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,aAAa,EAAE,CAAC;IAC/C,MAAM,IAAI,GAAG;QACX,CAAC,EAAE,gBAAgB;QACnB,IAAI;QACJ,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,WAAW,EAAE,GAAG,GAAG,GAAG;QACtB,QAAQ,EAAE,IAAqB;QAC/B,cAAc,EAAE,IAAqB;KACtC,CAAC;IACF,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAClC,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,CAAC;AAC1B,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,gBAAgB,CAAC,MAAkB,EAAE,MAAe;IAClE,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACxD,IAAI,MAAM,CAAC,CAAC,KAAK,gBAAgB;QAAE,OAAO,KAAK,CAAC;IAChD,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACjD,MAAM,GAAG,GAAG,MAAM,IAAI,aAAa,EAAE,CAAC;IACtC,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;IAChC,OAAO,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AAC5C,CAAC;AAcD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,KAK5B;IACC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACzD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACxD,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACvF,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG;QAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACvE,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IAC3E,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAC3C,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,QAAQ,CAAC,KAKxB;IACC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,aAAa,EAAE,CAAC;IAC/C,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC;IAC/C,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC;IAC9E,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAClC,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,CAAC;AAC1B,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,YAAY,CAAC,OAAqB,EAAE,KAAc;IAChE,MAAM,GAAG,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IAChC,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC;AACzD,CAAC;AAED,wEAAwE;AAExE;;;;;;GAMG;AACH,MAAM,kBAAkB,GAAG;IACzB,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IACtE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IACpE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IACtE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IACpE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IACrE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;CACvB,CAAC;AAEF,MAAM,UAAU,QAAQ,CAAC,WAAmB;IAC1C,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC3F,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IACzD,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAChD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,sDAAsD;QACtD,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAE,GAAG,kBAAkB,CAAC,MAAM,CAAE,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAUD,MAAM,UAAU,gBAAgB,CAAC,OAAqB,EAAE,KAAc,EAAE,MAAe;IACrF,MAAM,GAAG,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IAChC,IAAI,MAAM,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC;IACpD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YAAC,QAAQ,EAAE,CAAC;YAAC,SAAS;QAAC,CAAC;QAC1D,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC;YAAC,QAAQ,EAAE,CAAC;YAAC,SAAS;QAAC,CAAC;QAC3D,IAAI,CAAC,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAAC,IAAI,EAAE,CAAC;YAAC,SAAS;QAAC,CAAC;QAC9C,IAAI,CAAC,CAAC,WAAW,IAAI,GAAG,EAAE,CAAC;YAAC,OAAO,EAAE,CAAC;YAAC,SAAS;QAAC,CAAC;QAClD,MAAM,EAAE,CAAC;IACX,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,CAAgB;IAClD,OAAO,aAAa,CAAC,CAAC,MAAM,aAAa,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,OAAO,cAAc,CAAC,CAAC,QAAQ,WAAW,CAAC;AACzG,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC;IAC9C,QAAQ;IACR,UAAU;IACV,aAAa;IACb,cAAc;IACd,gBAAgB;IAChB,eAAe,EAAE,CAAC;IAClB,eAAe,EAAE,kBAAkB,CAAC,MAAM,IAAI,CAAC;CAChD,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pair_code.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pair_code.test.d.ts","sourceRoot":"","sources":["../../src/pair_code/pair_code.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,197 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { generatePairCode, normaliseCode, isValidCodeShape, bindEnvelope, verifyPairRecord, lookupByCode, markUsed, pruneExpired, sasEmoji, computePairStats, formatPairStatsLine, PAIR_CODE_TUNABLES, } from "./index.js";
3
+ const SECRET = "pair-test-secret-22";
4
+ describe("v2.19.32 PAIR CODE -- 6-char human-friendly handle", () => {
5
+ it("generatePairCode produces shape XXX-XXX from confusable-free alphabet", () => {
6
+ for (let i = 0; i < 50; i++) {
7
+ const c = generatePairCode();
8
+ expect(c).toMatch(/^[ACDEFGHJKMNPRTUVWXY2346789]{3}-[ACDEFGHJKMNPRTUVWXY2346789]{3}$/);
9
+ }
10
+ });
11
+ it("alphabet excludes 0/O/Q/1/I/L/5/S/8/B (confusables)", () => {
12
+ expect(PAIR_CODE_TUNABLES.ALPHABET).not.toContain("0");
13
+ expect(PAIR_CODE_TUNABLES.ALPHABET).not.toContain("O");
14
+ expect(PAIR_CODE_TUNABLES.ALPHABET).not.toContain("Q");
15
+ expect(PAIR_CODE_TUNABLES.ALPHABET).not.toContain("1");
16
+ expect(PAIR_CODE_TUNABLES.ALPHABET).not.toContain("I");
17
+ expect(PAIR_CODE_TUNABLES.ALPHABET).not.toContain("L");
18
+ expect(PAIR_CODE_TUNABLES.ALPHABET).not.toContain("5");
19
+ expect(PAIR_CODE_TUNABLES.ALPHABET).not.toContain("S");
20
+ expect(PAIR_CODE_TUNABLES.ALPHABET).not.toContain("8");
21
+ expect(PAIR_CODE_TUNABLES.ALPHABET).not.toContain("B");
22
+ });
23
+ it("normaliseCode handles user typing: spaces / lowercase / no-dash (shape only)", () => {
24
+ expect(normaliseCode("cat-dad")).toBe("CAT-DAD");
25
+ expect(normaliseCode("catdad")).toBe("CAT-DAD");
26
+ expect(normaliseCode("C AT - DAD")).toBe("CAT-DAD");
27
+ expect(normaliseCode("cat dad")).toBe("CAT-DAD");
28
+ expect(normaliseCode("")).toBe("");
29
+ expect(normaliseCode("toolong")).toBe(""); // 7 chars
30
+ expect(normaliseCode(123)).toBe("");
31
+ });
32
+ it("isValidCodeShape rejects out-of-alphabet chars (0/O/1/I/B/S etc)", () => {
33
+ expect(isValidCodeShape("CAT-DAD")).toBe(true);
34
+ expect(isValidCodeShape("ZOZ-CAT")).toBe(false); // O not in alphabet
35
+ expect(isValidCodeShape("0CD-EFG")).toBe(false); // 0 not in alphabet
36
+ expect(isValidCodeShape("1CD-EFG")).toBe(false); // 1 not in alphabet
37
+ expect(isValidCodeShape("BCD-EFG")).toBe(false); // B not in alphabet
38
+ expect(isValidCodeShape("SCD-EFG")).toBe(false); // S not in alphabet
39
+ });
40
+ it("MEASURED low collision rate: 10000 generates → expect < 1% collisions", () => {
41
+ const seen = new Set();
42
+ let collisions = 0;
43
+ for (let i = 0; i < 10_000; i++) {
44
+ const c = generatePairCode();
45
+ if (seen.has(c))
46
+ collisions++;
47
+ seen.add(c);
48
+ }
49
+ // Alphabet 26 chars, 6 chars total = 26^6 = ~309M space. 10000 picks expect ~0 collisions
50
+ expect(collisions).toBeLessThan(100); // < 1% even with bad RNG
51
+ });
52
+ });
53
+ describe("v2.19.32 PAIR CODE -- bind/lookup/markUsed lifecycle", () => {
54
+ it("bindEnvelope creates HMAC-signed PairRecord", () => {
55
+ const r = bindEnvelope({
56
+ envelopeSig: "abc123",
57
+ envelopeId: "env-001",
58
+ nowMs: 1_700_000_000_000,
59
+ secret: SECRET,
60
+ });
61
+ expect(r.code).toMatch(/^[A-Z2-9]{3}-[A-Z2-9]{3}$/);
62
+ expect(r.envelopeSig).toBe("abc123");
63
+ expect(r.expiresAtMs).toBe(1_700_000_000_000 + PAIR_CODE_TUNABLES.DEFAULT_TTL_MS);
64
+ expect(r.usedAtMs).toBeNull();
65
+ expect(r.sig).toMatch(/^[0-9a-f]{64}$/);
66
+ expect(verifyPairRecord(r, SECRET)).toBe(true);
67
+ });
68
+ it("bindEnvelope accepts caller-supplied code (for deterministic tests)", () => {
69
+ const r = bindEnvelope({
70
+ code: "CAT-DAD",
71
+ envelopeSig: "x",
72
+ envelopeId: "y",
73
+ nowMs: 0,
74
+ secret: SECRET,
75
+ });
76
+ expect(r.code).toBe("CAT-DAD");
77
+ });
78
+ it("verifyPairRecord rejects tampering", () => {
79
+ const r = bindEnvelope({ envelopeSig: "x", envelopeId: "y", nowMs: 0, secret: SECRET });
80
+ const tampered = { ...r, envelopeSig: "different" };
81
+ expect(verifyPairRecord(tampered, SECRET)).toBe(false);
82
+ });
83
+ it("lookupByCode returns 'found' for active code", () => {
84
+ const r = bindEnvelope({ envelopeSig: "x", envelopeId: "y", nowMs: 1000, secret: SECRET });
85
+ const result = lookupByCode({ records: [r], code: r.code, nowMs: 1500, secret: SECRET });
86
+ expect(result.verdict).toBe("found");
87
+ expect(result.record?.envelopeId).toBe("y");
88
+ });
89
+ it("lookupByCode handles user-typed lowercase + no-dash", () => {
90
+ const r = bindEnvelope({ code: "CAT-DAD", envelopeSig: "x", envelopeId: "y", nowMs: 1000, secret: SECRET });
91
+ const result = lookupByCode({ records: [r], code: "catdad", nowMs: 1500, secret: SECRET });
92
+ expect(result.verdict).toBe("found");
93
+ });
94
+ it("lookupByCode returns 'not_found' for unknown code", () => {
95
+ const result = lookupByCode({ records: [], code: "ZZZ-ZZZ", nowMs: 1000, secret: SECRET });
96
+ expect(result.verdict).toBe("not_found");
97
+ expect(result.record).toBeNull();
98
+ });
99
+ it("lookupByCode returns 'expired' after TTL passes", () => {
100
+ const r = bindEnvelope({ envelopeSig: "x", envelopeId: "y", nowMs: 0, ttlMs: 1000, secret: SECRET });
101
+ const result = lookupByCode({ records: [r], code: r.code, nowMs: 2000, secret: SECRET });
102
+ expect(result.verdict).toBe("expired");
103
+ });
104
+ it("lookupByCode returns 'tampered' if HMAC fails", () => {
105
+ const r = bindEnvelope({ envelopeSig: "x", envelopeId: "y", nowMs: 0, secret: SECRET });
106
+ const tampered = { ...r, envelopeSig: "evil" };
107
+ const result = lookupByCode({ records: [tampered], code: r.code, nowMs: 100, secret: SECRET });
108
+ expect(result.verdict).toBe("tampered");
109
+ });
110
+ it("markUsed implements one-shot: 2nd lookup returns 'already_used'", () => {
111
+ const r = bindEnvelope({ envelopeSig: "x", envelopeId: "y", nowMs: 1000, secret: SECRET });
112
+ const used = markUsed({ record: r, usedByDeviceId: "phone-1", nowMs: 1500, secret: SECRET });
113
+ expect(used.usedAtMs).toBe(1500);
114
+ expect(used.usedByDeviceId).toBe("phone-1");
115
+ expect(verifyPairRecord(used, SECRET)).toBe(true);
116
+ const result = lookupByCode({ records: [used], code: r.code, nowMs: 2000, secret: SECRET });
117
+ expect(result.verdict).toBe("already_used");
118
+ });
119
+ it("pruneExpired removes only past-TTL records", () => {
120
+ const fresh = bindEnvelope({ envelopeSig: "a", envelopeId: "1", nowMs: 1000, ttlMs: 10_000, secret: SECRET });
121
+ const expired = bindEnvelope({ envelopeSig: "b", envelopeId: "2", nowMs: 0, ttlMs: 500, secret: SECRET });
122
+ const all = [fresh, expired];
123
+ const pruned = pruneExpired(all, 5000);
124
+ expect(pruned.length).toBe(1);
125
+ expect(pruned[0].envelopeId).toBe("1");
126
+ });
127
+ it("computePairStats categorises records correctly", () => {
128
+ const fresh = bindEnvelope({ envelopeSig: "a", envelopeId: "1", nowMs: 1000, ttlMs: 10_000, secret: SECRET });
129
+ const expired = bindEnvelope({ envelopeSig: "b", envelopeId: "2", nowMs: 0, ttlMs: 500, secret: SECRET });
130
+ const usedRec = markUsed({
131
+ record: bindEnvelope({ envelopeSig: "c", envelopeId: "3", nowMs: 1000, secret: SECRET }),
132
+ usedByDeviceId: "phone", nowMs: 1500, secret: SECRET,
133
+ });
134
+ const tampered = { ...fresh, envelopeId: "bad" };
135
+ const stats = computePairStats([fresh, expired, usedRec, tampered], 5000, SECRET);
136
+ expect(stats.active).toBe(1);
137
+ expect(stats.expired).toBe(1);
138
+ expect(stats.used).toBe(1);
139
+ expect(stats.tampered).toBe(1);
140
+ expect(formatPairStatsLine(stats)).toContain("PAIR");
141
+ });
142
+ });
143
+ describe("v2.19.32 PAIR CODE -- SAS EMOJI (MITM defense)", () => {
144
+ it("sasEmoji is deterministic from envelopeSig", () => {
145
+ const sig = "a".repeat(64);
146
+ const a = sasEmoji(sig);
147
+ const b = sasEmoji(sig);
148
+ expect(a).toEqual(b);
149
+ expect(a.length).toBe(4);
150
+ });
151
+ it("sasEmoji DIFFERENT envelopeSigs produce DIFFERENT emoji (low collision)", async () => {
152
+ const { randomBytes } = await import("node:crypto");
153
+ const seen = new Set();
154
+ for (let i = 0; i < 200; i++) {
155
+ // Truly random first 4 bytes — this exercises the emoji alphabet uniformly
156
+ const sig = randomBytes(4).toString("hex") + "0".repeat(56);
157
+ seen.add(sasEmoji(sig).join(""));
158
+ }
159
+ // 64-emoji alphabet × 4 slots = 16M combinations; 200 random sigs → expect
160
+ // very few collisions (birthday: ~200^2 / 2 / 16M ≈ 0.00125 → essentially 0)
161
+ expect(seen.size).toBeGreaterThan(180);
162
+ });
163
+ it("sasEmoji returns 4 fallback emoji for malformed input", () => {
164
+ expect(sasEmoji("")).toEqual(["❓", "❓", "❓", "❓"]);
165
+ expect(sasEmoji("xyz")).toEqual(["❓", "❓", "❓", "❓"]);
166
+ expect(sasEmoji(null)).toEqual(["❓", "❓", "❓", "❓"]);
167
+ });
168
+ it("SAS_EMOJI_SPACE is wide enough to defend MITM (~16M)", () => {
169
+ expect(PAIR_CODE_TUNABLES.SAS_EMOJI_SPACE).toBeGreaterThan(10_000_000);
170
+ });
171
+ });
172
+ describe("v2.19.32 PAIR CODE -- 24/7 RESILIENCE", () => {
173
+ it("1000 random bind/lookup/markUsed cycles never crash", () => {
174
+ let records = [];
175
+ for (let i = 0; i < 1000; i++) {
176
+ const env = `env-${Math.floor(Math.random() * 100)}`;
177
+ const r = bindEnvelope({
178
+ envelopeSig: `sig-${Math.random()}`,
179
+ envelopeId: env,
180
+ nowMs: i * 100,
181
+ ttlMs: 30_000,
182
+ secret: SECRET,
183
+ });
184
+ records.push(r);
185
+ const lookup = lookupByCode({ records, code: r.code, nowMs: i * 100 + 50, secret: SECRET });
186
+ expect(["found", "not_found", "already_used", "expired", "tampered"]).toContain(lookup.verdict);
187
+ if (Math.random() < 0.3 && lookup.verdict === "found") {
188
+ const used = markUsed({ record: lookup.record, usedByDeviceId: `dev-${i}`, nowMs: i * 100 + 60, secret: SECRET });
189
+ records = records.map((x) => x.code === used.code ? used : x);
190
+ }
191
+ if (i % 100 === 0)
192
+ records = pruneExpired(records, i * 100);
193
+ }
194
+ expect(records.length).toBeGreaterThan(0);
195
+ });
196
+ });
197
+ //# sourceMappingURL=pair_code.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pair_code.test.js","sourceRoot":"","sources":["../../src/pair_code/pair_code.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * v2.19.31 — MNEME CROSS-DEVICE SYNAPSE SYNC (Phase D of SYNAPSE GENESIS)
3
+ *
4
+ * "บั๊กใหญ่มาก — ไม่สามารถ sync brain ข้าม device ได้. ต้องทำให้ใช้
5
+ * ได้ ผมถึงบอกว่าคุณต้องเทสเยอะๆ ว่ามัน sync brain ได้จริงๆ ข้าม mobile
6
+ * + computer + notebook"
7
+ * — user mandate, 2026-05-17
8
+ *
9
+ * Diagnosis: v2.19.29 SYNAPSE GENESIS learned weights locally. v2.19.30
10
+ * SOUL EMBALMING preserved them across BAN. Neither handles the third
11
+ * axis: the user works on mobile, laptop, and desktop. Each grows its
12
+ * own synapse store. Without a merge protocol, every device re-learns
13
+ * the same lessons from scratch and the brain never unifies.
14
+ *
15
+ * The protocol must be:
16
+ * - CRDT (commutative, associative, idempotent) so merge order
17
+ * doesn't matter (mobile→laptop ≡ laptop→mobile)
18
+ * - "Last-strongest-wins" per synapse key — the device that has
19
+ * observed a synapse most strongly / most recently provides the
20
+ * canonical weight, BUT permanent=true is sticky (once any device
21
+ * has crystallised a synapse, the merged result is permanent too)
22
+ * - Cumulative observationCount — total reinforcement across all
23
+ * devices, never lose evidence
24
+ * - HMAC-signed export envelopes — receivers verify before merging
25
+ * - Vendor-neutral — transport is caller-supplied (git branch via
26
+ * DIASPORA, HTTP bridge, USB stick, QR-code chain via BEACON,
27
+ * whatever the user prefers)
28
+ *
29
+ * Composes onto:
30
+ * - v2.19.29 Phase A HEBBIAN (SynapseWeight / SynapseStore types)
31
+ * - v2.19.30 SOUL EMBALMING (HMAC chain pattern)
32
+ * - v1.72 DIASPORA (transport — caller wires git/HTTP/QR)
33
+ *
34
+ * Honest scope:
35
+ * - PURE FUNCTION merge. Never throws.
36
+ * - HMAC-signed envelopes — forged exports auto-dropped.
37
+ * - Deterministic: same inputs → same merged store + same provenance map.
38
+ * - Defensive: empty exports, single-device, NaN weights, key collisions
39
+ * handled silently. 24/7 safe.
40
+ * - "permanent OR" semantics — never demotes a permanent synapse.
41
+ */
42
+ import type { SynapseStore } from "../synapse_genesis/index.js";
43
+ declare const PROTOCOL_VERSION: 1;
44
+ export interface DeviceSynapseExport {
45
+ v: typeof PROTOCOL_VERSION;
46
+ /** Stable, user-supplied device id (e.g. "macbook-pro-2026" or hash thereof). */
47
+ deviceId: string;
48
+ /** ms since epoch when the export was packaged. */
49
+ exportedAtMs: number;
50
+ store: SynapseStore;
51
+ /** HMAC over the canonical export body (everything above except sig). */
52
+ sig: string;
53
+ }
54
+ export interface MergeProvenance {
55
+ /** Composite synapse key. */
56
+ key: string;
57
+ /** deviceId whose weight + lastObservedAtMs won. */
58
+ winnerDeviceId: string;
59
+ /** All contributing devices (deviceId → contributing weight). */
60
+ contributors: Array<{
61
+ deviceId: string;
62
+ weight: number;
63
+ observationCount: number;
64
+ lastObservedAtMs: number;
65
+ permanent: boolean;
66
+ }>;
67
+ /** Final merged values. */
68
+ mergedWeight: number;
69
+ mergedObservationCount: number;
70
+ mergedPermanent: boolean;
71
+ mergedLastObservedAtMs: number;
72
+ }
73
+ export interface MergedSynapseResult {
74
+ v: typeof PROTOCOL_VERSION;
75
+ store: SynapseStore;
76
+ /** Per-key trace of which device contributed what — auditable. */
77
+ provenance: MergeProvenance[];
78
+ /** Devices that participated in the merge (after dedup). */
79
+ participatingDevices: string[];
80
+ /** Devices that were dropped because of bad signature / shape. */
81
+ rejectedDevices: string[];
82
+ }
83
+ /**
84
+ * Package a local store for cross-device transport.
85
+ * The envelope is HMAC-signed so receivers can detect tampering.
86
+ */
87
+ export declare function exportForSync(input: {
88
+ deviceId: string;
89
+ store: SynapseStore;
90
+ nowMs?: number;
91
+ secret?: string;
92
+ }): DeviceSynapseExport;
93
+ /** Verify an export envelope's HMAC. Returns false on forged / tampered envelopes. */
94
+ export declare function verifySyncExport(envelope: DeviceSynapseExport, secret?: string): boolean;
95
+ /**
96
+ * Merge N device exports into one canonical synapse store.
97
+ *
98
+ * Verifies each envelope's HMAC first; bad envelopes go into `rejectedDevices`
99
+ * and contribute nothing. Duplicate deviceIds: last-export-wins (most recent
100
+ * exportedAtMs).
101
+ *
102
+ * The merged store gets a freshly-recomputed signature with the local secret
103
+ * (so it can re-export). Caller (daemon) typically writes the merged store
104
+ * back to disk as the new local synapse_genesis state.
105
+ */
106
+ export declare function mergeSynapseStores(input: {
107
+ exports: DeviceSynapseExport[];
108
+ secret?: string;
109
+ /** Optional explicit synapse_genesis secret for the OUTPUT store sig. */
110
+ storeSecret?: string;
111
+ }): MergedSynapseResult;
112
+ /**
113
+ * DIASPORA-shape adapter: serialize an export envelope to a JSON path the
114
+ * caller's transport (git branch `diaspora/synapse-<deviceId>`, HTTP PUT,
115
+ * QR-chain, USB stick) can carry. Returns the canonical bytes + the
116
+ * recommended file path; the caller's chosen transport actually moves it.
117
+ */
118
+ export declare function packForDiaspora(envelope: DeviceSynapseExport): {
119
+ path: string;
120
+ bytes: string;
121
+ branchHint: string;
122
+ };
123
+ /**
124
+ * DIASPORA-shape unpack: read JSON bytes a caller fetched via their
125
+ * transport and return the typed envelope. Returns null on parse failure.
126
+ */
127
+ export declare function unpackFromDiaspora(bytes: string): DeviceSynapseExport | null;
128
+ export interface CrossDeviceSyncStats {
129
+ participatingDevices: number;
130
+ rejectedDevices: number;
131
+ totalSynapses: number;
132
+ permanentSynapses: number;
133
+ multiDeviceSynapses: number;
134
+ unifiedObservations: number;
135
+ }
136
+ export declare function computeSyncStats(result: MergedSynapseResult): CrossDeviceSyncStats;
137
+ export declare function formatSyncStatsLine(s: CrossDeviceSyncStats): string;
138
+ export declare const SYNAPSE_SYNC_TUNABLES: Readonly<{
139
+ PROTOCOL_VERSION: 1;
140
+ }>;
141
+ export {};
142
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/synapse_sync/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,6BAA6B,CAAC;AAE/E,QAAA,MAAM,gBAAgB,EAAG,CAAU,CAAC;AAEpC,MAAM,WAAW,mBAAmB;IAClC,CAAC,EAAE,OAAO,gBAAgB,CAAC;IAC3B,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,YAAY,CAAC;IACpB,yEAAyE;IACzE,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,cAAc,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,YAAY,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAClI,2BAA2B;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,eAAe,EAAE,OAAO,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,mBAAmB;IAClC,CAAC,EAAE,OAAO,gBAAgB,CAAC;IAC3B,KAAK,EAAE,YAAY,CAAC;IACpB,kEAAkE;IAClE,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,4DAA4D;IAC5D,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,kEAAkE;IAClE,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAsBD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,YAAY,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,mBAAmB,CAWtB;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,mBAAmB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CASxF;AA+ED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,mBAAmB,CAoFtB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,mBAAmB,GAAG;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB,CAaA;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAM5E;AAED,MAAM,WAAW,oBAAoB;IACnC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,mBAAmB,GAAG,oBAAoB,CAiBlF;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAEnE;AAED,eAAO,MAAM,qBAAqB;;EAEhC,CAAC"}