agentfootprint 9.36.0 → 9.37.1

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 (132) hide show
  1. package/ai-instructions/claude-code/SKILL.md +177 -353
  2. package/dist/adapters/hosting/firestoreSessions.js +28 -6
  3. package/dist/adapters/hosting/firestoreSessions.js.map +1 -1
  4. package/dist/adapters/hosting/googleAgentEngine.js +64 -0
  5. package/dist/adapters/hosting/googleAgentEngine.js.map +1 -1
  6. package/dist/adapters/memory/agentcore.js +7 -1
  7. package/dist/adapters/memory/agentcore.js.map +1 -1
  8. package/dist/adapters/memory/memoryBank.js +29 -8
  9. package/dist/adapters/memory/memoryBank.js.map +1 -1
  10. package/dist/adapters/memory/redis.js +28 -1
  11. package/dist/adapters/memory/redis.js.map +1 -1
  12. package/dist/artifacts/scopePath.js +13 -2
  13. package/dist/artifacts/scopePath.js.map +1 -1
  14. package/dist/doors/skill-graph.js +55 -6
  15. package/dist/doors/skill-graph.js.map +1 -1
  16. package/dist/esm/adapters/hosting/firestoreSessions.js +29 -7
  17. package/dist/esm/adapters/hosting/firestoreSessions.js.map +1 -1
  18. package/dist/esm/adapters/hosting/googleAgentEngine.js +64 -0
  19. package/dist/esm/adapters/hosting/googleAgentEngine.js.map +1 -1
  20. package/dist/esm/adapters/memory/agentcore.js +7 -1
  21. package/dist/esm/adapters/memory/agentcore.js.map +1 -1
  22. package/dist/esm/adapters/memory/memoryBank.d.ts +13 -3
  23. package/dist/esm/adapters/memory/memoryBank.js +29 -8
  24. package/dist/esm/adapters/memory/memoryBank.js.map +1 -1
  25. package/dist/esm/adapters/memory/redis.d.ts +25 -0
  26. package/dist/esm/adapters/memory/redis.js +28 -1
  27. package/dist/esm/adapters/memory/redis.js.map +1 -1
  28. package/dist/esm/artifacts/scopePath.d.ts +9 -1
  29. package/dist/esm/artifacts/scopePath.js +13 -2
  30. package/dist/esm/artifacts/scopePath.js.map +1 -1
  31. package/dist/esm/doors/skill-graph.d.ts +55 -6
  32. package/dist/esm/doors/skill-graph.js +55 -6
  33. package/dist/esm/doors/skill-graph.js.map +1 -1
  34. package/dist/esm/hosting/conformance/cases.d.ts +15 -0
  35. package/dist/esm/hosting/conformance/cases.js +395 -0
  36. package/dist/esm/hosting/conformance/cases.js.map +1 -0
  37. package/dist/esm/hosting/conformance/index.d.ts +11 -0
  38. package/dist/esm/hosting/conformance/index.js +11 -0
  39. package/dist/esm/hosting/conformance/index.js.map +1 -0
  40. package/dist/esm/hosting/conformance/run.d.ts +46 -0
  41. package/dist/esm/hosting/conformance/run.js +182 -0
  42. package/dist/esm/hosting/conformance/run.js.map +1 -0
  43. package/dist/esm/hosting/conformance/types.d.ts +140 -0
  44. package/dist/esm/hosting/conformance/types.js +6 -0
  45. package/dist/esm/hosting/conformance/types.js.map +1 -0
  46. package/dist/esm/hosting/errors.d.ts +34 -0
  47. package/dist/esm/hosting/errors.js +47 -0
  48. package/dist/esm/hosting/errors.js.map +1 -1
  49. package/dist/esm/hosting/index.d.ts +4 -1
  50. package/dist/esm/hosting/index.js +11 -1
  51. package/dist/esm/hosting/index.js.map +1 -1
  52. package/dist/esm/hosting/memorySessions.d.ts +5 -0
  53. package/dist/esm/hosting/memorySessions.js +25 -17
  54. package/dist/esm/hosting/memorySessions.js.map +1 -1
  55. package/dist/esm/hosting/sessionOwnership.d.ts +86 -0
  56. package/dist/esm/hosting/sessionOwnership.js +106 -0
  57. package/dist/esm/hosting/sessionOwnership.js.map +1 -0
  58. package/dist/esm/hosting/sqliteSessions.js +41 -10
  59. package/dist/esm/hosting/sqliteSessions.js.map +1 -1
  60. package/dist/esm/hosting/types.d.ts +68 -4
  61. package/dist/esm/hosting/types.js.map +1 -1
  62. package/dist/esm/memory/identity/encode.d.ts +67 -0
  63. package/dist/esm/memory/identity/encode.js +91 -0
  64. package/dist/esm/memory/identity/encode.js.map +1 -0
  65. package/dist/esm/memory/identity/index.d.ts +1 -0
  66. package/dist/esm/memory/identity/index.js +1 -0
  67. package/dist/esm/memory/identity/index.js.map +1 -1
  68. package/dist/esm/memory/identity/types.d.ts +21 -4
  69. package/dist/esm/memory/identity/types.js +27 -7
  70. package/dist/esm/memory/identity/types.js.map +1 -1
  71. package/dist/hosting/conformance/cases.js +398 -0
  72. package/dist/hosting/conformance/cases.js.map +1 -0
  73. package/dist/hosting/conformance/index.js +18 -0
  74. package/dist/hosting/conformance/index.js.map +1 -0
  75. package/dist/hosting/conformance/run.js +188 -0
  76. package/dist/hosting/conformance/run.js.map +1 -0
  77. package/dist/hosting/conformance/types.js +7 -0
  78. package/dist/hosting/conformance/types.js.map +1 -0
  79. package/dist/hosting/errors.js +49 -1
  80. package/dist/hosting/errors.js.map +1 -1
  81. package/dist/hosting/index.js +18 -2
  82. package/dist/hosting/index.js.map +1 -1
  83. package/dist/hosting/memorySessions.js +25 -17
  84. package/dist/hosting/memorySessions.js.map +1 -1
  85. package/dist/hosting/sessionOwnership.js +110 -0
  86. package/dist/hosting/sessionOwnership.js.map +1 -0
  87. package/dist/hosting/sqliteSessions.js +41 -10
  88. package/dist/hosting/sqliteSessions.js.map +1 -1
  89. package/dist/hosting/types.js.map +1 -1
  90. package/dist/memory/identity/encode.js +96 -0
  91. package/dist/memory/identity/encode.js.map +1 -0
  92. package/dist/memory/identity/index.js +5 -1
  93. package/dist/memory/identity/index.js.map +1 -1
  94. package/dist/memory/identity/types.js +27 -7
  95. package/dist/memory/identity/types.js.map +1 -1
  96. package/dist/types/adapters/hosting/firestoreSessions.d.ts.map +1 -1
  97. package/dist/types/adapters/hosting/googleAgentEngine.d.ts.map +1 -1
  98. package/dist/types/adapters/memory/agentcore.d.ts.map +1 -1
  99. package/dist/types/adapters/memory/memoryBank.d.ts +13 -3
  100. package/dist/types/adapters/memory/memoryBank.d.ts.map +1 -1
  101. package/dist/types/adapters/memory/redis.d.ts +25 -0
  102. package/dist/types/adapters/memory/redis.d.ts.map +1 -1
  103. package/dist/types/artifacts/scopePath.d.ts +9 -1
  104. package/dist/types/artifacts/scopePath.d.ts.map +1 -1
  105. package/dist/types/doors/skill-graph.d.ts +55 -6
  106. package/dist/types/doors/skill-graph.d.ts.map +1 -1
  107. package/dist/types/hosting/conformance/cases.d.ts +16 -0
  108. package/dist/types/hosting/conformance/cases.d.ts.map +1 -0
  109. package/dist/types/hosting/conformance/index.d.ts +12 -0
  110. package/dist/types/hosting/conformance/index.d.ts.map +1 -0
  111. package/dist/types/hosting/conformance/run.d.ts +47 -0
  112. package/dist/types/hosting/conformance/run.d.ts.map +1 -0
  113. package/dist/types/hosting/conformance/types.d.ts +141 -0
  114. package/dist/types/hosting/conformance/types.d.ts.map +1 -0
  115. package/dist/types/hosting/errors.d.ts +34 -0
  116. package/dist/types/hosting/errors.d.ts.map +1 -1
  117. package/dist/types/hosting/index.d.ts +4 -1
  118. package/dist/types/hosting/index.d.ts.map +1 -1
  119. package/dist/types/hosting/memorySessions.d.ts +5 -0
  120. package/dist/types/hosting/memorySessions.d.ts.map +1 -1
  121. package/dist/types/hosting/sessionOwnership.d.ts +87 -0
  122. package/dist/types/hosting/sessionOwnership.d.ts.map +1 -0
  123. package/dist/types/hosting/sqliteSessions.d.ts.map +1 -1
  124. package/dist/types/hosting/types.d.ts +68 -4
  125. package/dist/types/hosting/types.d.ts.map +1 -1
  126. package/dist/types/memory/identity/encode.d.ts +68 -0
  127. package/dist/types/memory/identity/encode.d.ts.map +1 -0
  128. package/dist/types/memory/identity/index.d.ts +1 -0
  129. package/dist/types/memory/identity/index.d.ts.map +1 -1
  130. package/dist/types/memory/identity/types.d.ts +21 -4
  131. package/dist/types/memory/identity/types.d.ts.map +1 -1
  132. package/package.json +1 -1
@@ -0,0 +1,86 @@
1
+ /**
2
+ * hosting/sessionOwnership — the ONE owner-transition rule, so four stores
3
+ * cannot each get it slightly wrong (9.36.1).
4
+ *
5
+ * Every store implementing {@link SessionLifecycle} keeps an owner index, and
6
+ * every one of them wrote the write-once rule out longhand in its own dialect:
7
+ * a `COALESCE` in SQL, a `has()` on a `Map`, a read-then-decide inside a
8
+ * transaction. Four spellings of one sentence, and all four were missing the
9
+ * same half of it — which is what a rule that lives in prose rather than in
10
+ * code eventually costs.
11
+ *
12
+ * ── The rule, whole ─────────────────────────────────────────────────────────
13
+ * An owner is a fact about the CONVERSATION, established by the first turn
14
+ * that signs for it. Given what is stored and what a turn is carrying:
15
+ *
16
+ * | stored | incoming | outcome |
17
+ * |------------|------------|-----------------------------------------------|
18
+ * | nobody | nobody | still nobody — an anonymous conversation |
19
+ * | nobody | somebody | FILLED IN — the first turn that signs, owns |
20
+ * | somebody | nobody | KEPT — a leaner turn erases nothing |
21
+ * | somebody | the same | KEPT — the ordinary turn |
22
+ * | somebody | DIFFERENT | REFUSED, by name |
23
+ *
24
+ * The last row is the one that was missing, and the difference between the
25
+ * last two rows is the whole design decision:
26
+ *
27
+ * - **A different identity is a CONTRADICTION.** Two people cannot both have
28
+ * signed for one conversation. Keeping the index and storing the payload
29
+ * anyway — which is what every store did — leaves the index naming one
30
+ * person and the conversation naming another, and the person the index
31
+ * names opens it and reads the other one's conversation.
32
+ * - **An absent identity is not a contradiction.** It claims nobody. The
33
+ * contract blesses it in as many words ("a later turn carrying a leaner
34
+ * identity must not erase it"), and refusing it would fail a flow the
35
+ * library's own documentation describes as intended, to protect against a
36
+ * claim nobody made.
37
+ *
38
+ * ── Why this is a function and not a base class ─────────────────────────────
39
+ * Stores share no ancestry and should not start now: one is a `Map`, one is a
40
+ * SQL upsert, one is a distributed transaction, one is somebody's managed
41
+ * service where the owner field is immutable. What they share is a DECISION,
42
+ * so what they share is a decision function — called at the point each of them
43
+ * already had to decide, inside whatever atomicity that store can offer.
44
+ *
45
+ * The atomicity is deliberately NOT this module's business, and cannot be: a
46
+ * read-then-decide is only as safe as the transaction it happens inside, and
47
+ * only the store knows what it has. What this owns is the answer; where it is
48
+ * safe to ask is the store's own promise, and the conformance suite is what
49
+ * checks that the store kept it (`contested-write-leaves-no-split-brain`).
50
+ */
51
+ /**
52
+ * Which owner a store should record, given what it already has and what the
53
+ * turn being written is signed by — or a refusal.
54
+ *
55
+ * Call it INSIDE whatever the store uses to make read-then-write atomic (a
56
+ * transaction, a lock, a single-threaded map), with the owner already derived
57
+ * from the stored conversation by `envelopeOwner`. The return value is the
58
+ * owner to store; a refusal means the whole `persist` must not land, including
59
+ * the envelope.
60
+ *
61
+ * **The envelope is the part that matters.** A store that catches this and
62
+ * writes the payload anyway has re-created the exact defect: the refusal
63
+ * exists to stop the CONVERSATION being replaced, not merely to protect an
64
+ * index column.
65
+ *
66
+ * Empty strings are read as "nobody" on both sides, matching `envelopeOwner`,
67
+ * so a store that keeps `''` for an unowned row cannot accidentally make it a
68
+ * principal that conflicts with everybody.
69
+ *
70
+ * @param sessionId the id being written — the caller's own string, and the
71
+ * only thing the refusal repeats back.
72
+ * @param storedOwner the owner already recorded for this session, or
73
+ * `undefined` for a session that is new or that nobody has signed for.
74
+ * @param incomingOwner the owner derived from the envelope being written —
75
+ * `envelopeOwner(envelope)`, never anything a caller supplied.
76
+ * @returns the owner to record. `undefined` means "record nobody".
77
+ * @throws SessionOwnershipConflictError when the two name DIFFERENT people.
78
+ *
79
+ * @example Inside a store's persist
80
+ * const incoming = envelopeOwner(checked);
81
+ * const owner = resolveSessionOwner(sessionId, rows.get(sessionId), incoming);
82
+ * // Only now — a refusal above must leave the stored conversation alone.
83
+ * rows.set(sessionId, checked);
84
+ * if (owner !== undefined) owners.set(sessionId, owner);
85
+ */
86
+ export declare function resolveSessionOwner(sessionId: string, storedOwner: string | undefined, incomingOwner: string | undefined): string | undefined;
@@ -0,0 +1,106 @@
1
+ /**
2
+ * hosting/sessionOwnership — the ONE owner-transition rule, so four stores
3
+ * cannot each get it slightly wrong (9.36.1).
4
+ *
5
+ * Every store implementing {@link SessionLifecycle} keeps an owner index, and
6
+ * every one of them wrote the write-once rule out longhand in its own dialect:
7
+ * a `COALESCE` in SQL, a `has()` on a `Map`, a read-then-decide inside a
8
+ * transaction. Four spellings of one sentence, and all four were missing the
9
+ * same half of it — which is what a rule that lives in prose rather than in
10
+ * code eventually costs.
11
+ *
12
+ * ── The rule, whole ─────────────────────────────────────────────────────────
13
+ * An owner is a fact about the CONVERSATION, established by the first turn
14
+ * that signs for it. Given what is stored and what a turn is carrying:
15
+ *
16
+ * | stored | incoming | outcome |
17
+ * |------------|------------|-----------------------------------------------|
18
+ * | nobody | nobody | still nobody — an anonymous conversation |
19
+ * | nobody | somebody | FILLED IN — the first turn that signs, owns |
20
+ * | somebody | nobody | KEPT — a leaner turn erases nothing |
21
+ * | somebody | the same | KEPT — the ordinary turn |
22
+ * | somebody | DIFFERENT | REFUSED, by name |
23
+ *
24
+ * The last row is the one that was missing, and the difference between the
25
+ * last two rows is the whole design decision:
26
+ *
27
+ * - **A different identity is a CONTRADICTION.** Two people cannot both have
28
+ * signed for one conversation. Keeping the index and storing the payload
29
+ * anyway — which is what every store did — leaves the index naming one
30
+ * person and the conversation naming another, and the person the index
31
+ * names opens it and reads the other one's conversation.
32
+ * - **An absent identity is not a contradiction.** It claims nobody. The
33
+ * contract blesses it in as many words ("a later turn carrying a leaner
34
+ * identity must not erase it"), and refusing it would fail a flow the
35
+ * library's own documentation describes as intended, to protect against a
36
+ * claim nobody made.
37
+ *
38
+ * ── Why this is a function and not a base class ─────────────────────────────
39
+ * Stores share no ancestry and should not start now: one is a `Map`, one is a
40
+ * SQL upsert, one is a distributed transaction, one is somebody's managed
41
+ * service where the owner field is immutable. What they share is a DECISION,
42
+ * so what they share is a decision function — called at the point each of them
43
+ * already had to decide, inside whatever atomicity that store can offer.
44
+ *
45
+ * The atomicity is deliberately NOT this module's business, and cannot be: a
46
+ * read-then-decide is only as safe as the transaction it happens inside, and
47
+ * only the store knows what it has. What this owns is the answer; where it is
48
+ * safe to ask is the store's own promise, and the conformance suite is what
49
+ * checks that the store kept it (`contested-write-leaves-no-split-brain`).
50
+ */
51
+ import { SessionOwnershipConflictError } from './errors.js';
52
+ /**
53
+ * Which owner a store should record, given what it already has and what the
54
+ * turn being written is signed by — or a refusal.
55
+ *
56
+ * Call it INSIDE whatever the store uses to make read-then-write atomic (a
57
+ * transaction, a lock, a single-threaded map), with the owner already derived
58
+ * from the stored conversation by `envelopeOwner`. The return value is the
59
+ * owner to store; a refusal means the whole `persist` must not land, including
60
+ * the envelope.
61
+ *
62
+ * **The envelope is the part that matters.** A store that catches this and
63
+ * writes the payload anyway has re-created the exact defect: the refusal
64
+ * exists to stop the CONVERSATION being replaced, not merely to protect an
65
+ * index column.
66
+ *
67
+ * Empty strings are read as "nobody" on both sides, matching `envelopeOwner`,
68
+ * so a store that keeps `''` for an unowned row cannot accidentally make it a
69
+ * principal that conflicts with everybody.
70
+ *
71
+ * @param sessionId the id being written — the caller's own string, and the
72
+ * only thing the refusal repeats back.
73
+ * @param storedOwner the owner already recorded for this session, or
74
+ * `undefined` for a session that is new or that nobody has signed for.
75
+ * @param incomingOwner the owner derived from the envelope being written —
76
+ * `envelopeOwner(envelope)`, never anything a caller supplied.
77
+ * @returns the owner to record. `undefined` means "record nobody".
78
+ * @throws SessionOwnershipConflictError when the two name DIFFERENT people.
79
+ *
80
+ * @example Inside a store's persist
81
+ * const incoming = envelopeOwner(checked);
82
+ * const owner = resolveSessionOwner(sessionId, rows.get(sessionId), incoming);
83
+ * // Only now — a refusal above must leave the stored conversation alone.
84
+ * rows.set(sessionId, checked);
85
+ * if (owner !== undefined) owners.set(sessionId, owner);
86
+ */
87
+ export function resolveSessionOwner(sessionId, storedOwner, incomingOwner) {
88
+ const stored = nonEmpty(storedOwner);
89
+ const incoming = nonEmpty(incomingOwner);
90
+ // Nothing is claimed yet: the first turn that signs owns the conversation,
91
+ // and a turn that signs for nothing leaves it unowned.
92
+ if (stored === undefined)
93
+ return incoming;
94
+ // The blessed leaner turn. It claims nobody, so it contradicts nobody, and
95
+ // the established owner stands.
96
+ if (incoming === undefined)
97
+ return stored;
98
+ if (incoming === stored)
99
+ return stored;
100
+ throw new SessionOwnershipConflictError(sessionId);
101
+ }
102
+ /** `''` is nobody, exactly as `envelopeOwner` reads it. */
103
+ function nonEmpty(value) {
104
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
105
+ }
106
+ //# sourceMappingURL=sessionOwnership.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionOwnership.js","sourceRoot":"","sources":["../../../src/hosting/sessionOwnership.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,OAAO,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,UAAU,mBAAmB,CACjC,SAAiB,EACjB,WAA+B,EAC/B,aAAiC;IAEjC,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC;IACzC,2EAA2E;IAC3E,uDAAuD;IACvD,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC1C,2EAA2E;IAC3E,gCAAgC;IAChC,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IAC1C,IAAI,QAAQ,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC;IACvC,MAAM,IAAI,6BAA6B,CAAC,SAAS,CAAC,CAAC;AACrD,CAAC;AAED,2DAA2D;AAC3D,SAAS,QAAQ,CAAC,KAAyB;IACzC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3E,CAAC"}
@@ -54,6 +54,7 @@
54
54
  */
55
55
  import { checkEnvelope, envelopeOwner, envelopeTranscript } from './envelope.js';
56
56
  import { UnreadableEnvelopeError } from './errors.js';
57
+ import { resolveSessionOwner } from './sessionOwnership.js';
57
58
  import { lazyRequire } from '../lib/lazyRequire.js';
58
59
  import { SqliteUnavailableError } from '../lib/sqliteUnavailable.js';
59
60
  // ─── The refusals ────────────────────────────────────────────────────
@@ -216,14 +217,17 @@ export function sqliteSessions(options) {
216
217
  `VALUES (?, ?, ?, ?, ?, ?) ` +
217
218
  `ON CONFLICT(session_id) DO UPDATE SET format = excluded.format, ` +
218
219
  `saved_at = excluded.saved_at, envelope = excluded.envelope, ` +
219
- // WRITE ONCE — the existing owner wins, and a NULL one is filled in.
220
- // An owner is a fact about the CONVERSATION, established by the first
221
- // turn that signed for it: a later turn carrying a leaner identity must
222
- // not erase it (the session would drop out of its owner's list), and a
223
- // later turn carrying a DIFFERENT one must not take it (ownership would
224
- // transfer by writing, which undoes every check made against this index).
225
- // The argument order is the whole rule; reversing it is the bug.
226
- `owner = COALESCE(${SESSIONS_TABLE}.owner, excluded.owner), ` +
220
+ // The owner is bound, already decided — NOT `COALESCE(sessions.owner,
221
+ // excluded.owner)`, which is what this was until 9.36.1.
222
+ //
223
+ // COALESCE kept the right owner and could not refuse, so a turn signed
224
+ // by somebody else quietly won the `envelope` column beside an `owner`
225
+ // column that still named the first writer: the index said one person
226
+ // and the stored conversation said another. SQL that can only pick a
227
+ // column cannot express "and if they disagree, write nothing" — so the
228
+ // decision moved out of the statement and into `resolveSessionOwner`,
229
+ // one transaction up, where a refusal can stop the whole row.
230
+ `owner = excluded.owner, ` +
227
231
  `message_count = excluded.message_count`);
228
232
  const select = db.prepare(`SELECT envelope FROM ${SESSIONS_TABLE} WHERE session_id = ?`);
229
233
  const remove = db.prepare(`DELETE FROM ${SESSIONS_TABLE} WHERE session_id = ?`);
@@ -284,8 +288,35 @@ export function sqliteSessions(options) {
284
288
  // never supplied by the caller — the port takes no owner argument and
285
289
  // gains none, because a store where owning a session is a matter of
286
290
  // asking is not an index, it is a formality.
287
- const owner = envelopeOwner(checked);
288
- insert.run(sessionId, checked.format, checked.savedAt, JSON.stringify(checked), owner ?? null, envelopeTranscript(checked).length);
291
+ const incoming = envelopeOwner(checked);
292
+ // BEGIN IMMEDIATE, not BEGIN: it takes the write lock up front, so the
293
+ // read below and the write after it cannot have another writer's turn
294
+ // between them. A deferred transaction would take the lock only at the
295
+ // INSERT — which is exactly the window where two containers persisting
296
+ // the same fresh session both read "nobody owns this" and both proceed.
297
+ // The lock waits `busy_timeout` and then fails loudly, which is the same
298
+ // bargain the rest of this store makes.
299
+ db.exec('BEGIN IMMEDIATE');
300
+ try {
301
+ const existing = selectOwner.get(sessionId);
302
+ const owner = resolveSessionOwner(sessionId, typeof existing?.owner === 'string' ? existing.owner : undefined, incoming);
303
+ insert.run(sessionId, checked.format, checked.savedAt, JSON.stringify(checked), owner ?? null, envelopeTranscript(checked).length);
304
+ db.exec('COMMIT');
305
+ }
306
+ catch (err) {
307
+ // The envelope must not land when the owner was refused — the payload
308
+ // is the half that carries somebody's conversation, and a row that
309
+ // kept the old owner beside a new conversation is the whole defect.
310
+ // ROLLBACK is best-effort: if the transaction is already gone the
311
+ // original refusal is the one worth raising, not this one.
312
+ try {
313
+ db.exec('ROLLBACK');
314
+ }
315
+ catch {
316
+ /* Already rolled back or never opened; the error below says why. */
317
+ }
318
+ throw err;
319
+ }
289
320
  },
290
321
  // eslint-disable-next-line @typescript-eslint/require-await
291
322
  async listByUser(userId, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"sqliteSessions.js","sourceRoot":"","sources":["../../../src/hosting/sqliteSessions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sqliteSessions.js","sourceRoot":"","sources":["../../../src/hosting/sqliteSessions.ts"],"names":[],"mappings":"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"}
@@ -656,11 +656,40 @@ export type WakeReason = 'invoke' | 'resume' | 'artifact' | 'transcript';
656
656
  * Deliberately two required methods. Anything a real store also wants — a TTL,
657
657
  * a scan, a delete — is that store's own API, not a demand this port makes of
658
658
  * every store that will ever implement it.
659
+ *
660
+ * ── Claiming the port ───────────────────────────────────────────────────────
661
+ * The two required methods are what TypeScript checks. What a store has to
662
+ * *behave* like is a battery every shipped store runs against and any store
663
+ * can: `sessionLifecycleConformance`, exported from this same subpath. It was
664
+ * written after a flaw in THIS interface's semantics turned up in four
665
+ * independent adapters at once — every one of them tested, and every one of
666
+ * them tested only against its own doubles, which is precisely why none of
667
+ * them could see it. Run it against your store; a case your store cannot
668
+ * satisfy is DECLARED by name with its reason, never skipped.
659
669
  */
660
670
  export interface SessionLifecycle {
661
671
  /** The stored conversation, or `undefined` for a session that has none yet. */
662
672
  hydrate(sessionId: string): Promise<CheckpointEnvelope | undefined>;
663
- /** Store the conversation for this session. Last write wins. */
673
+ /**
674
+ * Store the conversation for this session. Last write wins — with ONE
675
+ * exception, and it is the only thing this method ever refuses.
676
+ *
677
+ * **A store that keeps an owner index refuses a turn signed by somebody
678
+ * other than the established owner** (`SessionOwnershipConflictError`,
679
+ * 9.36.1), and refuses it whole: neither the index nor the ENVELOPE changes.
680
+ * Until 9.36.1 the write-once rule protected only the index, so such a write
681
+ * kept the first writer's `owner` and stored the second writer's entire
682
+ * conversation — leaving the index naming one person and the stored
683
+ * conversation naming another. The person the index named listed it, opened
684
+ * it, and read the other one's conversation.
685
+ *
686
+ * A turn carrying a LEANER identity is not refused. It claims nobody, so it
687
+ * contradicts nobody, and the established owner stands — see `listByUser`.
688
+ *
689
+ * The composer refuses a foreign turn at the door long before this, when a
690
+ * verifier is configured. This is the store keeping the same promise for
691
+ * every caller that holds it directly, and for a door with no verifier.
692
+ */
664
693
  persist(sessionId: string, envelope: CheckpointEnvelope): Promise<void>;
665
694
  /**
666
695
  * Called once per served request, before `hydrate`, for stores that need to
@@ -688,9 +717,38 @@ export interface SessionLifecycle {
688
717
  *
689
718
  * **And established ONCE.** The first turn that signs for a conversation owns
690
719
  * it; no later write moves that — not a leaner identity (which would erase
691
- * it) and not a different one (which would transfer it). Both shipped stores
692
- * implement the index that way, and a custom one that let the last writer win
693
- * would undo every ownership check made against it one turn later.
720
+ * it) and not a different one (which would transfer it). Every shipped store
721
+ * implements the index that way, and a custom one that let the last writer
722
+ * win would undo every ownership check made against it one turn later.
723
+ *
724
+ * The two halves of "no later write moves it" are NOT symmetrical, and
725
+ * 9.36.1 exists because they were treated as if they were:
726
+ *
727
+ * - a **leaner** turn is stored, and the owner is kept. It claims nobody, so
728
+ * it contradicts nobody. Refusing it would break a flow this contract
729
+ * blesses in the sentence above.
730
+ * - a **different** turn is REFUSED — index and envelope both. Keeping the
731
+ * index while storing the payload is not "not moving" the owner; it is
732
+ * moving the CONVERSATION out from under them, which is worse. Don't
733
+ * write this rule yourself: `resolveSessionOwner(sessionId, stored,
734
+ * incoming)` is the one implementation, and it is what every shipped store
735
+ * now calls.
736
+ *
737
+ * ── Which of the two says who owns a session ────────────────────────────────
738
+ * This index is the authority for LISTING and for the session-history ops:
739
+ * `ownerOf` is the question `{ op: 'session-transcript' }` asks, and nothing
740
+ * re-derives an answer behind it. An ordinary TURN does not ask it — it
741
+ * re-derives from the envelope it has just hydrated (`envelopeOwner`), which
742
+ * is the same derivation and one round-trip cheaper, and which is what keeps
743
+ * a store with NO index protected exactly as well as one with a fast one.
744
+ *
745
+ * Those two can never name different people: that is what the refusal above
746
+ * buys, and it is the only reason a turn is safe to answer from the envelope.
747
+ * They CAN differ in one direction — an index that names somebody over a
748
+ * conversation that names nobody, which is what a leaner turn leaves behind.
749
+ * That state only ever REFUSES: the owner can still list and read the
750
+ * session, and a turn on it is refused at any verifying door, for everybody.
751
+ * Stated because it is a real asymmetry and not a bug to be surprised by.
694
752
  *
695
753
  * A conversation that ran anonymously has no owner and appears in nobody's
696
754
  * list. That is the honest consequence of deriving rather than inventing.
@@ -707,6 +765,12 @@ export interface SessionLifecycle {
707
765
  *
708
766
  * Implement it beside `listByUser` — a door that can list but not check
709
767
  * ownership can hand somebody a list and then refuse to open any of it.
768
+ *
769
+ * This is the ownership INDEX, and it is not a second source of truth beside
770
+ * the identity embedded in the stored envelope: `persist` refuses any write
771
+ * that would make the two name different people. A store that answers this
772
+ * from something a caller supplied, rather than from what it derived, has
773
+ * built a permission system out of a request field.
710
774
  */
711
775
  ownerOf?(sessionId: string): Promise<string | undefined>;
712
776
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/hosting/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA25BH;iFACiF;AACjF,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/hosting/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA29BH;iFACiF;AACjF,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * identity/encode — one identity field → one unambiguous key segment.
3
+ *
4
+ * **This module is the tenant boundary.** Every durable store in the library
5
+ * addresses rows by a string composed from `{ tenant, principal,
6
+ * conversationId }`. If two DIFFERENT tuples can spell the SAME string, one
7
+ * scope reads, overwrites and erases another scope's data — no race, no
8
+ * misconfiguration, just arithmetic. So the encoding here is **injective**
9
+ * (different tuples ⇒ different strings, always), and that property is
10
+ * load-bearing rather than tidy: it is the whole isolation guarantee.
11
+ *
12
+ * Two things could collapse two tuples into one string, and each has a rule:
13
+ *
14
+ * • **the separator.** `/` is what joins the fields, so a value containing
15
+ * one would otherwise donate a field boundary: tenant `acme/hr` and
16
+ * principal `alice` spelled the same string as tenant `acme` and
17
+ * principal `hr/alice`. Real ids hit this — a JWT `sub` is often a URI.
18
+ * `/` is therefore escaped to `%2F`, and `%` — the escape's own
19
+ * introducer — is escaped FIRST to `%25`, or a value that merely reads
20
+ * like an escape (`a%2Fb`) would land on the value that produced it
21
+ * (`a/b`) and we would have moved the collision rather than closed it.
22
+ *
23
+ * • **the absence marker.** A field that was not given still needs a
24
+ * segment, and that segment is `_`. A tenant *named* `_` is a different
25
+ * scope from *no tenant*, so a present value that spells the marker is
26
+ * escaped to `%5F`. `%5F` is unreachable any other way (every `%` in an
27
+ * encoded value is already escaped), which is what makes it safe to
28
+ * reserve.
29
+ *
30
+ * **What deliberately does NOT change.** A value containing neither `/` nor
31
+ * `%`, and which is not exactly `_`, is returned BYTE FOR BYTE. That is not a
32
+ * nicety — it is what makes this fix deployable: every existing artifact and
33
+ * memory row written under a well-behaved id keeps its address, so there is no
34
+ * migration. The only tuples that change key are the ones that were sharing a
35
+ * key with somebody else, and those were already broken.
36
+ *
37
+ * Absence has exactly ONE spelling: `undefined`, `null` and `''` all mean "not
38
+ * given". An empty string is not a name, and treating it as one would create a
39
+ * second anonymous scope rather than distinguish anything real.
40
+ */
41
+ /** The one segment that means "this field was not given". */
42
+ export declare const IDENTITY_ABSENT = "_";
43
+ /**
44
+ * Keep a PRESENT value from spelling the absence marker.
45
+ *
46
+ * For encoders that already do their own escaping (the artifact path
47
+ * segments use `encodeURIComponent`) and only need the absence law applied on
48
+ * top.
49
+ *
50
+ * **Precondition:** `escaped` comes from an escaper that escapes `%`. Without
51
+ * that, a caller-supplied `%5F` would collide with an escaped `_` and this
52
+ * function would be hiding a collision instead of closing one.
53
+ */
54
+ export declare function distinctFromAbsent(escaped: string): string;
55
+ /**
56
+ * Encode ONE identity field as a key segment that cannot be confused with any
57
+ * other field's, or with absence.
58
+ *
59
+ * @param raw the field as the caller gave it; `undefined`/`null`/`''` are
60
+ * absence.
61
+ * @returns a segment containing no `/`, never equal to another field's segment
62
+ * unless the fields were equal.
63
+ * @throws TypeError when a present field is not a string. The value is NOT
64
+ * named in the message — this function is the identity boundary, and
65
+ * an error string is the one place a tenant id must never travel.
66
+ */
67
+ export declare function encodeIdentityField(raw: string | undefined | null): string;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * identity/encode — one identity field → one unambiguous key segment.
3
+ *
4
+ * **This module is the tenant boundary.** Every durable store in the library
5
+ * addresses rows by a string composed from `{ tenant, principal,
6
+ * conversationId }`. If two DIFFERENT tuples can spell the SAME string, one
7
+ * scope reads, overwrites and erases another scope's data — no race, no
8
+ * misconfiguration, just arithmetic. So the encoding here is **injective**
9
+ * (different tuples ⇒ different strings, always), and that property is
10
+ * load-bearing rather than tidy: it is the whole isolation guarantee.
11
+ *
12
+ * Two things could collapse two tuples into one string, and each has a rule:
13
+ *
14
+ * • **the separator.** `/` is what joins the fields, so a value containing
15
+ * one would otherwise donate a field boundary: tenant `acme/hr` and
16
+ * principal `alice` spelled the same string as tenant `acme` and
17
+ * principal `hr/alice`. Real ids hit this — a JWT `sub` is often a URI.
18
+ * `/` is therefore escaped to `%2F`, and `%` — the escape's own
19
+ * introducer — is escaped FIRST to `%25`, or a value that merely reads
20
+ * like an escape (`a%2Fb`) would land on the value that produced it
21
+ * (`a/b`) and we would have moved the collision rather than closed it.
22
+ *
23
+ * • **the absence marker.** A field that was not given still needs a
24
+ * segment, and that segment is `_`. A tenant *named* `_` is a different
25
+ * scope from *no tenant*, so a present value that spells the marker is
26
+ * escaped to `%5F`. `%5F` is unreachable any other way (every `%` in an
27
+ * encoded value is already escaped), which is what makes it safe to
28
+ * reserve.
29
+ *
30
+ * **What deliberately does NOT change.** A value containing neither `/` nor
31
+ * `%`, and which is not exactly `_`, is returned BYTE FOR BYTE. That is not a
32
+ * nicety — it is what makes this fix deployable: every existing artifact and
33
+ * memory row written under a well-behaved id keeps its address, so there is no
34
+ * migration. The only tuples that change key are the ones that were sharing a
35
+ * key with somebody else, and those were already broken.
36
+ *
37
+ * Absence has exactly ONE spelling: `undefined`, `null` and `''` all mean "not
38
+ * given". An empty string is not a name, and treating it as one would create a
39
+ * second anonymous scope rather than distinguish anything real.
40
+ */
41
+ /** The one segment that means "this field was not given". */
42
+ export const IDENTITY_ABSENT = '_';
43
+ /**
44
+ * The segment for a present value that literally spells {@link IDENTITY_ABSENT}.
45
+ *
46
+ * Reserved, and reachable ONLY from the value `_`: any escaper used with
47
+ * {@link distinctFromAbsent} escapes `%` itself, so no other input can produce
48
+ * these three bytes.
49
+ */
50
+ const ABSENT_LOOKALIKE = '%5F';
51
+ /**
52
+ * Keep a PRESENT value from spelling the absence marker.
53
+ *
54
+ * For encoders that already do their own escaping (the artifact path
55
+ * segments use `encodeURIComponent`) and only need the absence law applied on
56
+ * top.
57
+ *
58
+ * **Precondition:** `escaped` comes from an escaper that escapes `%`. Without
59
+ * that, a caller-supplied `%5F` would collide with an escaped `_` and this
60
+ * function would be hiding a collision instead of closing one.
61
+ */
62
+ export function distinctFromAbsent(escaped) {
63
+ return escaped === IDENTITY_ABSENT ? ABSENT_LOOKALIKE : escaped;
64
+ }
65
+ /**
66
+ * Encode ONE identity field as a key segment that cannot be confused with any
67
+ * other field's, or with absence.
68
+ *
69
+ * @param raw the field as the caller gave it; `undefined`/`null`/`''` are
70
+ * absence.
71
+ * @returns a segment containing no `/`, never equal to another field's segment
72
+ * unless the fields were equal.
73
+ * @throws TypeError when a present field is not a string. The value is NOT
74
+ * named in the message — this function is the identity boundary, and
75
+ * an error string is the one place a tenant id must never travel.
76
+ */
77
+ export function encodeIdentityField(raw) {
78
+ if (raw === undefined || raw === null || raw === '')
79
+ return IDENTITY_ABSENT;
80
+ if (typeof raw !== 'string') {
81
+ throw new TypeError('[identity] a MemoryIdentity field must be a string or omitted. A non-string was ' +
82
+ 'given, and it is not quoted here on purpose: this value addresses a tenant, and an ' +
83
+ 'error message is the wrong place for one. Convert it at the call site so the id ' +
84
+ 'that reaches storage is the id you meant.');
85
+ }
86
+ // '%' FIRST — it introduces every escape below, so it has to be inert before
87
+ // any are emitted. Reversing these two lines re-opens the collision.
88
+ const escaped = raw.replace(/%/g, '%25').replace(/\//g, '%2F');
89
+ return distinctFromAbsent(escaped);
90
+ }
91
+ //# sourceMappingURL=encode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encode.js","sourceRoot":"","sources":["../../../../src/memory/identity/encode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAEH,6DAA6D;AAC7D,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AAEnC;;;;;;GAMG;AACH,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAE/B;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,OAAO,OAAO,KAAK,eAAe,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC;AAClE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAA8B;IAChE,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,eAAe,CAAC;IAC5E,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,SAAS,CACjB,kFAAkF;YAChF,qFAAqF;YACrF,kFAAkF;YAClF,2CAA2C,CAC9C,CAAC;IACJ,CAAC;IACD,6EAA6E;IAC7E,qEAAqE;IACrE,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC/D,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export type { MemoryIdentity } from './types.js';
2
2
  export { identityNamespace } from './types.js';
3
+ export { distinctFromAbsent, encodeIdentityField, IDENTITY_ABSENT } from './encode.js';
@@ -1,2 +1,3 @@
1
1
  export { identityNamespace } from './types.js';
2
+ export { distinctFromAbsent, encodeIdentityField, IDENTITY_ABSENT } from './encode.js';
2
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/memory/identity/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/memory/identity/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
@@ -39,11 +39,28 @@ export interface MemoryIdentity {
39
39
  }
40
40
  /**
41
41
  * Encode a MemoryIdentity as a deterministic storage namespace. Used by
42
- * storage adapters that need a single string key (Redis, localStorage,
43
- * filesystem paths). Format is stable across library versions — adapters
42
+ * storage adapters that need a single string key (Redis, SQLite columns,
43
+ * object-store keys). Format is stable across library versions — adapters
44
44
  * can safely use it for long-lived keys.
45
45
  *
46
- * Empty `tenant` / `principal` collapse to `_` so the format has a constant
47
- * shape (easy to parse, easy to list by prefix).
46
+ * **The encoding is INJECTIVE: two different identities never produce the
47
+ * same namespace.** That is the isolation guarantee itself, not a detail of
48
+ * it — a namespace two tuples share is a scope that reads and overwrites
49
+ * another scope's rows, with no race required. It held only for well-behaved
50
+ * ids before 9.36.x: `{ tenant: 'acme/hr', principal: 'alice' }` and
51
+ * `{ tenant: 'acme', principal: 'hr/alice' }` spelled one namespace, and a
52
+ * JWT `sub` is routinely a URI. Each field is now escaped by
53
+ * {@link encodeIdentityField} before it is joined, so a value can no longer
54
+ * donate a field boundary — do not "simplify" the joins back to raw
55
+ * interpolation.
56
+ *
57
+ * A missing `tenant` / `principal` / `conversationId` is the segment `_`, so
58
+ * the shape stays constant (three segments, easy to list by prefix), and a
59
+ * field whose VALUE is `_` encodes as `%5F` so "no tenant" and "the tenant
60
+ * named `_`" stay two different scopes.
61
+ *
62
+ * Building a FILESYSTEM path? Use `scopeSegments` from `artifacts/scopePath`
63
+ * instead: it encodes each field for a path (`.` included, so a field of `..`
64
+ * cannot be a directory hop). This namespace is a key, not a path.
48
65
  */
49
66
  export declare function identityNamespace(identity: MemoryIdentity): string;