@agenticprimitives/fabric 0.0.0-alpha.1 → 0.0.0-alpha.10

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 (147) hide show
  1. package/CLAUDE.md +22 -2
  2. package/README.md +16 -16
  3. package/dist/case-emissions.d.ts +95 -0
  4. package/dist/case-emissions.d.ts.map +1 -0
  5. package/dist/case-emissions.js +208 -0
  6. package/dist/case-emissions.js.map +1 -0
  7. package/dist/case-machine.d.ts +28 -2
  8. package/dist/case-machine.d.ts.map +1 -1
  9. package/dist/case-machine.js +34 -7
  10. package/dist/case-machine.js.map +1 -1
  11. package/dist/cloudflare/index.d.ts +1 -0
  12. package/dist/cloudflare/index.d.ts.map +1 -1
  13. package/dist/cloudflare/index.js +4 -0
  14. package/dist/cloudflare/index.js.map +1 -1
  15. package/dist/cloudflare/interaction-store.d.ts +55 -0
  16. package/dist/cloudflare/interaction-store.d.ts.map +1 -0
  17. package/dist/cloudflare/interaction-store.js +230 -0
  18. package/dist/cloudflare/interaction-store.js.map +1 -0
  19. package/dist/cloudflare/principal-gateway-do.d.ts +118 -2
  20. package/dist/cloudflare/principal-gateway-do.d.ts.map +1 -1
  21. package/dist/cloudflare/principal-gateway-do.js +182 -7
  22. package/dist/cloudflare/principal-gateway-do.js.map +1 -1
  23. package/dist/communicative-act.d.ts +24 -1
  24. package/dist/communicative-act.d.ts.map +1 -1
  25. package/dist/communicative-act.js +28 -0
  26. package/dist/communicative-act.js.map +1 -1
  27. package/dist/delivery-envelope.d.ts.map +1 -1
  28. package/dist/delivery-envelope.js +0 -1
  29. package/dist/delivery-envelope.js.map +1 -1
  30. package/dist/enum-retirement.d.ts +43 -0
  31. package/dist/enum-retirement.d.ts.map +1 -0
  32. package/dist/enum-retirement.js +93 -0
  33. package/dist/enum-retirement.js.map +1 -0
  34. package/dist/exchange-record.d.ts +35 -4
  35. package/dist/exchange-record.d.ts.map +1 -1
  36. package/dist/exchange-record.js.map +1 -1
  37. package/dist/exchange-reducer.d.ts +32 -4
  38. package/dist/exchange-reducer.d.ts.map +1 -1
  39. package/dist/exchange-reducer.js +75 -1
  40. package/dist/exchange-reducer.js.map +1 -1
  41. package/dist/exchange-state.d.ts +30 -8
  42. package/dist/exchange-state.d.ts.map +1 -1
  43. package/dist/exchange-state.js +12 -10
  44. package/dist/exchange-state.js.map +1 -1
  45. package/dist/inbox-doc.d.ts +2 -2
  46. package/dist/inbox-doc.d.ts.map +1 -1
  47. package/dist/inbox-doc.js.map +1 -1
  48. package/dist/inbox-projection.d.ts +2 -2
  49. package/dist/inbox-projection.d.ts.map +1 -1
  50. package/dist/inbox-projection.js.map +1 -1
  51. package/dist/inbox-revision.d.ts +42 -0
  52. package/dist/inbox-revision.d.ts.map +1 -0
  53. package/dist/inbox-revision.js +57 -0
  54. package/dist/inbox-revision.js.map +1 -0
  55. package/dist/index.d.ts +23 -3
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +36 -2
  58. package/dist/index.js.map +1 -1
  59. package/dist/interaction-machines.d.ts +136 -0
  60. package/dist/interaction-machines.d.ts.map +1 -0
  61. package/dist/interaction-machines.js +174 -0
  62. package/dist/interaction-machines.js.map +1 -0
  63. package/dist/interaction-profile.d.ts +126 -0
  64. package/dist/interaction-profile.d.ts.map +1 -0
  65. package/dist/interaction-profile.js +192 -0
  66. package/dist/interaction-profile.js.map +1 -0
  67. package/dist/interaction-record.d.ts +168 -0
  68. package/dist/interaction-record.d.ts.map +1 -0
  69. package/dist/interaction-record.js +108 -0
  70. package/dist/interaction-record.js.map +1 -0
  71. package/dist/interactions/machine.d.ts +2 -2
  72. package/dist/interactions/machine.d.ts.map +1 -1
  73. package/dist/interactions/machine.js +2 -2
  74. package/dist/interactions/machine.js.map +1 -1
  75. package/dist/interactions/store.d.ts +9 -0
  76. package/dist/interactions/store.d.ts.map +1 -1
  77. package/dist/interactions/store.js +57 -2
  78. package/dist/interactions/store.js.map +1 -1
  79. package/dist/messaging/board.d.ts +86 -6
  80. package/dist/messaging/board.d.ts.map +1 -1
  81. package/dist/messaging/board.js +100 -9
  82. package/dist/messaging/board.js.map +1 -1
  83. package/dist/messaging/consult-routing.d.ts +289 -0
  84. package/dist/messaging/consult-routing.d.ts.map +1 -0
  85. package/dist/messaging/consult-routing.js +455 -0
  86. package/dist/messaging/consult-routing.js.map +1 -0
  87. package/dist/messaging/consult.d.ts +158 -0
  88. package/dist/messaging/consult.d.ts.map +1 -0
  89. package/dist/messaging/consult.js +141 -0
  90. package/dist/messaging/consult.js.map +1 -0
  91. package/dist/messaging/conversation-interaction.d.ts +66 -0
  92. package/dist/messaging/conversation-interaction.d.ts.map +1 -0
  93. package/dist/messaging/conversation-interaction.js +139 -0
  94. package/dist/messaging/conversation-interaction.js.map +1 -0
  95. package/dist/messaging/delivery.d.ts +2 -2
  96. package/dist/messaging/delivery.d.ts.map +1 -1
  97. package/dist/messaging/delivery.js +8 -1
  98. package/dist/messaging/delivery.js.map +1 -1
  99. package/dist/messaging/directory.d.ts +16 -0
  100. package/dist/messaging/directory.d.ts.map +1 -1
  101. package/dist/messaging/directory.js.map +1 -1
  102. package/dist/messaging/envelope.d.ts +7 -3
  103. package/dist/messaging/envelope.d.ts.map +1 -1
  104. package/dist/messaging/envelope.js +18 -1
  105. package/dist/messaging/envelope.js.map +1 -1
  106. package/dist/messaging/hash.d.ts +8 -2
  107. package/dist/messaging/hash.d.ts.map +1 -1
  108. package/dist/messaging/hash.js +6 -0
  109. package/dist/messaging/hash.js.map +1 -1
  110. package/dist/messaging/inbox-assistant.d.ts +80 -0
  111. package/dist/messaging/inbox-assistant.d.ts.map +1 -0
  112. package/dist/messaging/inbox-assistant.js +125 -0
  113. package/dist/messaging/inbox-assistant.js.map +1 -0
  114. package/dist/messaging/index.d.ts +9 -3
  115. package/dist/messaging/index.d.ts.map +1 -1
  116. package/dist/messaging/index.js +17 -2
  117. package/dist/messaging/index.js.map +1 -1
  118. package/dist/messaging/projector.d.ts +3 -3
  119. package/dist/messaging/projector.d.ts.map +1 -1
  120. package/dist/messaging/projector.js.map +1 -1
  121. package/dist/messaging/receipts.d.ts +3 -3
  122. package/dist/messaging/receipts.d.ts.map +1 -1
  123. package/dist/messaging/receipts.js.map +1 -1
  124. package/dist/messaging/rules.d.ts +10 -3
  125. package/dist/messaging/rules.d.ts.map +1 -1
  126. package/dist/messaging/rules.js +8 -1
  127. package/dist/messaging/rules.js.map +1 -1
  128. package/dist/messaging/store.d.ts +4 -4
  129. package/dist/messaging/store.d.ts.map +1 -1
  130. package/dist/messaging/store.js +5 -3
  131. package/dist/messaging/store.js.map +1 -1
  132. package/dist/messaging/types.d.ts +52 -0
  133. package/dist/messaging/types.d.ts.map +1 -1
  134. package/dist/messaging/types.js +18 -1
  135. package/dist/messaging/types.js.map +1 -1
  136. package/dist/messaging/vault-store.d.ts +35 -2
  137. package/dist/messaging/vault-store.d.ts.map +1 -1
  138. package/dist/messaging/vault-store.js +53 -5
  139. package/dist/messaging/vault-store.js.map +1 -1
  140. package/dist/protocol-binding.d.ts +71 -0
  141. package/dist/protocol-binding.d.ts.map +1 -0
  142. package/dist/protocol-binding.js +0 -0
  143. package/dist/protocol-binding.js.map +1 -0
  144. package/dist/record-catalog.d.ts.map +1 -1
  145. package/dist/record-catalog.js +19 -0
  146. package/dist/record-catalog.js.map +1 -1
  147. package/package.json +7 -7
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consult.d.ts","sourceRoot":"","sources":["../../src/messaging/consult.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;uFACuF;AACvF,eAAO,MAAM,gBAAgB,EAAG,oBAA6B,CAAC;AAE9D;+FAC+F;AAC/F,eAAO,MAAM,sBAAsB,QAAc,CAAC;AAClD,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,wFAAwF;AACxF,eAAO,MAAM,8BAA8B,QAAqB,CAAC;AAIjE,oEAAoE;AACpE,eAAO,MAAM,sBAAsB,IAAI,CAAC;AACxC,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,+FAA+F;AAC/F,eAAO,MAAM,sBAAsB,QAAc,CAAC;AAClD,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC;0DAC0D;AAC1D,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAEhD;;0FAE0F;AAC1F,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;mEACmE;AACnE,eAAO,MAAM,gCAAgC,EAAG,qBAA8B,CAAC;AAE/E;gGACgG;AAChG,eAAO,MAAM,qBAAqB,aAAc,MAAM,KAAG,MACV,CAAC;AAEhD,qGAAqG;AACrG,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,CAE7G;AAED,iFAAiF;AACjF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAC/C,eAAO,MAAM,qBAAqB,IAAI,CAAC;AACvC,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QACP,uDAAuD;QACvD,KAAK,EAAE,MAAM,CAAC;QACd,uCAAuC;QACvC,OAAO,EAAE,MAAM,CAAC;QAChB,0FAA0F;QAC1F,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,2FAA2F;QAC3F,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;KAChC,CAAC;CACH;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,GACvC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjC;wFACwF;AACxF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CA0BtE;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,sBAAsB,CAAC;IAChC,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,gGAAgG;IAChG,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,yCAAyC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0FAA0F;IAC1F,KAAK,EAAE,gBAAgB,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,wBAAwB,GAChC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,GACrC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjC,gEAAgE;AAChE,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAE7C;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5G,wBAAwB,CAqB1B;AAED,MAAM,MAAM,4BAA4B,GACpC,aAAa,GACb,qBAAqB,GACrB,aAAa,GACb,eAAe,GACf,eAAe,GACf,uBAAuB,GACvB,+BAA+B,CAAC;AAEpC,mGAAmG;AACnG,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,eAAe,GAAG,4BAA4B,EAAE,CAWxF;AAED,8EAA8E;AAC9E,MAAM,MAAM,wBAAwB,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;AAE3F;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,2BAA2B,CAAC;IACrC,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAC;IACX,4DAA4D;IAC5D,SAAS,EAAE,SAAS,CAAC;IACrB,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,WAAW,EAAE,gBAAgB,CAAC;IAC9B,6EAA6E;IAC7E,WAAW,EAAE,CAAC,gBAAgB,CAAC,CAAC;IAChC,yEAAyE;IACzE,WAAW,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,MAAM,EAAE,wBAAwB,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,iCAAiC,GACzC,aAAa,GACb,eAAe,GACf,sBAAsB,GACtB,kBAAkB,GAClB,qBAAqB,GACrB,YAAY,CAAC;AAEjB,kDAAkD;AAClD,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,oBAAoB,GAAG,iCAAiC,EAAE,CASvG"}
@@ -0,0 +1,141 @@
1
+ /** The consult A2A skill id — the delegation's `allowedMethods` selector derives from THIS string
2
+ * (`skillSelector('discussion.consult')`, spec 269 FR-4.2). Never `A2A_ANY_SKILL`. */
3
+ export const CONSULT_SKILL_ID = 'discussion.consult';
4
+ /** Member-side per-org fixed window (spec 329 §3.2): 12 consults / hour / org. Exceeding ⇒ the
5
+ * task fails typed + audited (`a2a.consult.rateLimited`); decided with `fixedWindowAllow`. */
6
+ export const CONSULT_RATE_WINDOW_MS = 60 * 60_000;
7
+ export const CONSULT_RATE_MAX = 12;
8
+ /** Default consultability-delegation lifetime (spec 329 §2.1) — re-opt-in refreshes. */
9
+ export const CONSULT_GRANT_VALIDITY_SECONDS = 180 * 24 * 60 * 60;
10
+ // ── Org-side routing bounds (spec 329 §4 — approved defaults). Kept in THIS leaf (no board
11
+ // import) so board.ts's setTopicRouting and the routing module share one definition. ──
12
+ /** Fan-out per routed question: default 3, steward-tunable 1..5. */
13
+ export const ROUTING_FANOUT_DEFAULT = 3;
14
+ export const ROUTING_FANOUT_MIN = 1;
15
+ export const ROUTING_FANOUT_MAX = 5;
16
+ /** Per-topic routing bucket (on top of 327's dispatch bucket): 3 routed questions / 10 min. */
17
+ export const ROUTING_RATE_WINDOW_MS = 10 * 60_000;
18
+ export const ROUTING_RATE_MAX = 3;
19
+ /** Per-member consult timeout (spec 329 §4): a member agent that hasn't completed by then is
20
+ * reported as timed out in the synthesis attribution. */
21
+ export const CONSULT_MEMBER_TIMEOUT_MS = 60_000;
22
+ /** contextRef kind carried by the turn-1 status post + turn-2 synthesis (spec 329 §6;
23
+ * cbox/interaction-vocabulary.ttl `apmsg:routedConsultation`). */
24
+ export const ROUTED_CONSULTATION_CONTEXT_KIND = 'routed-consultation';
25
+ /** The org-vault record name family holding member consultability grants (spec 329 §2.1) —
26
+ * exported so W2's `find_members` eligibility read and the opt-in ceremony key identically. */
27
+ export const consultGrantRecordKey = (memberSA) => `org.consult-grant:${memberSA.toLowerCase()}`;
28
+ /** Build the routed-consultation contextRef: id = `<orgSA>/<topicId>/<questionId>` (spec 329 §6). */
29
+ export function routedConsultationContextRef(orgSA, topicId, questionId) {
30
+ return { kind: ROUTED_CONSULTATION_CONTEXT_KIND, id: `${orgSA.toLowerCase()}/${topicId}/${questionId}` };
31
+ }
32
+ /** Bounds on the carried context — the consult turn is small by construction. */
33
+ export const CONSULT_QUESTION_MAX_CHARS = 2000;
34
+ export const CONSULT_TAIL_MAX_ROWS = 8;
35
+ export const CONSULT_TAIL_CLIP = 300;
36
+ /** Parse + bound an inbound consult payload, fail-closed. Unknown/oversized context is CLIPPED
37
+ * (data, never authority — ADR-0041); a missing goal/org/topic/question id REJECTS. */
38
+ export function parseConsultRequest(input) {
39
+ if (!input || typeof input !== 'object')
40
+ return { ok: false, error: 'consult requires an object payload { goal, context }' };
41
+ const i = input;
42
+ const goal = typeof i.goal === 'string' ? i.goal.trim().slice(0, CONSULT_QUESTION_MAX_CHARS) : '';
43
+ if (!goal)
44
+ return { ok: false, error: 'consult requires goal (the question text)' };
45
+ const c = (i.context && typeof i.context === 'object' ? i.context : {});
46
+ const orgSA = String(c.orgSA ?? '').toLowerCase();
47
+ if (!/^0x[0-9a-f]{40}$/.test(orgSA))
48
+ return { ok: false, error: 'consult requires context.orgSA (the consulting org SA)' };
49
+ const topicId = String(c.topicId ?? '').trim();
50
+ const questionId = String(c.questionId ?? '').trim();
51
+ if (!topicId || !questionId)
52
+ return { ok: false, error: 'consult requires context.topicId + context.questionId' };
53
+ const tailRaw = Array.isArray(c.topicTail) ? c.topicTail : [];
54
+ const topicTail = tailRaw.slice(-CONSULT_TAIL_MAX_ROWS).flatMap((r) => {
55
+ const row = r;
56
+ const bodyText = typeof row.bodyText === 'string' ? row.bodyText.slice(0, CONSULT_TAIL_CLIP) : '';
57
+ if (!bodyText)
58
+ return [];
59
+ return [{ author: typeof row.author === 'string' ? row.author.slice(0, 120) : 'member', bodyText }];
60
+ });
61
+ const topicTitle = typeof c.topicTitle === 'string' && c.topicTitle.trim() ? c.topicTitle.trim().slice(0, 200) : undefined;
62
+ return {
63
+ ok: true,
64
+ request: {
65
+ goal,
66
+ context: { orgSA, topicId, questionId, ...(topicTitle ? { topicTitle } : {}), ...(topicTail.length ? { topicTail } : {}) },
67
+ },
68
+ };
69
+ }
70
+ /** Max answer/decline-reason length carried back to the org. */
71
+ export const CONSULT_ANSWER_MAX_CHARS = 4000;
72
+ /**
73
+ * Build the ConsultAnswer artifact body (spec 329 §3.2). IDENTITY-PINNED by construction: the
74
+ * caller supplies only the outcome — `actor` is ALWAYS the member principal, and the request
75
+ * correlation (org/topic/question) comes from the PARSED request, never planner output.
76
+ * Enforces answered XOR declined, fail-closed (ADR-0013): an empty answer without an explicit
77
+ * decline is an error, never a silent empty artifact.
78
+ */
79
+ export function buildConsultAnswer(request, opts) {
80
+ const answer = (opts.answer ?? '').trim().slice(0, CONSULT_ANSWER_MAX_CHARS);
81
+ const declined = opts.declined === true;
82
+ if (declined && answer)
83
+ return { ok: false, error: 'a consult terminal is answered XOR declined — not both' };
84
+ if (!declined && !answer)
85
+ return { ok: false, error: 'consult answer requires answer text or an explicit decline' };
86
+ const memberAddr = String(opts.member).match(/0x[0-9a-fA-F]{40}$/)?.[0];
87
+ if (!memberAddr)
88
+ return { ok: false, error: 'member must be an EVM agent (CAIP-10)' };
89
+ const declineReason = declined ? (opts.declineReason ?? '').trim().slice(0, CONSULT_ANSWER_MAX_CHARS) : '';
90
+ return {
91
+ ok: true,
92
+ answer: {
93
+ version: 'ap.consult-answer.v1',
94
+ questionId: request.context.questionId,
95
+ orgSA: request.context.orgSA,
96
+ topicId: request.context.topicId,
97
+ question: request.goal,
98
+ ...(declined ? { declined: true, ...(declineReason ? { declineReason } : {}) } : { answer }),
99
+ actor: opts.member,
100
+ respondedAt: opts.now ?? new Date().toISOString(),
101
+ },
102
+ };
103
+ }
104
+ /** TS mirror of apmsg:ConsultAnswerShape (structural; the bodyHash binding is the task rail's). */
105
+ export function validateConsultAnswer(a) {
106
+ const errors = [];
107
+ if (a.version !== 'ap.consult-answer.v1')
108
+ errors.push('bad_version');
109
+ if (!a.questionId?.trim())
110
+ errors.push('missing_question_id');
111
+ if (!/^0x[0-9a-f]{40}$/.test(a.orgSA ?? ''))
112
+ errors.push('missing_org');
113
+ if (!a.topicId?.trim())
114
+ errors.push('missing_topic');
115
+ if (!a.actor || !String(a.actor).match(/0x[0-9a-fA-F]{40}$/))
116
+ errors.push('missing_actor');
117
+ const answered = typeof a.answer === 'string' && a.answer.trim().length > 0;
118
+ if (answered && a.declined)
119
+ errors.push('answered_and_declined');
120
+ if (!answered && a.declined !== true)
121
+ errors.push('neither_answered_nor_declined');
122
+ return errors;
123
+ }
124
+ /** TS mirror of apint:ConsultationIntentShape. */
125
+ export function validateConsultationIntent(i) {
126
+ const errors = [];
127
+ if (i.version !== 'ap.consultation-intent.v1')
128
+ errors.push('bad_version');
129
+ if (i.direction !== 'receive')
130
+ errors.push('bad_direction');
131
+ if (!i.expressedBy)
132
+ errors.push('missing_expressed_by');
133
+ if (!Array.isArray(i.addressedTo) || i.addressedTo.length !== 1 || !i.addressedTo[0])
134
+ errors.push('bad_addressed_to');
135
+ if (!i.constraints || !(i.constraints.timeoutMs > 0) || !i.constraints.topicId?.trim())
136
+ errors.push('missing_constraints');
137
+ if (!['drafted', 'expressed', 'fulfilled', 'abandoned'].includes(i.status))
138
+ errors.push('bad_status');
139
+ return errors;
140
+ }
141
+ //# sourceMappingURL=consult.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consult.js","sourceRoot":"","sources":["../../src/messaging/consult.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import type { CanonicalAgentId } from '@agenticprimitives/types';
2
+ import type { ConversationDescriptorV1, ConversationId } from './types.js';
3
+ import type { InteractionId, ProfileVersion, ParticipationV1 } from '../interaction-record.js';
4
+ import type { InteractionState } from '../interaction-machines.js';
5
+ import { type ChannelV1 } from './board.js';
6
+ /** Derived from the conversation id, so the two can never disagree and no field needs adding. */
7
+ export declare function conversationInteractionId(conversationId: ConversationId | string): InteractionId;
8
+ /** The inverse, or `null` for an id that is not a conversation interaction. Null rather than a guess —
9
+ * the same rule that keeps derived-participation resolution fail-closed. */
10
+ export declare function conversationIdFromInteraction(interactionId: string): string | null;
11
+ /**
12
+ * `participantPolicy` IS `participationMode`, and noticing that is what made this a projection.
13
+ *
14
+ * `open-to-context` means "anyone in the anchored org" — membership owned elsewhere, resolved at read
15
+ * time, never copied per conversation. That is precisely `derived`. `fixed` and `owner-managed` both
16
+ * mean the participant list on the record is the membership: `asserted`.
17
+ */
18
+ export declare function participationModeOfConversation(descriptor: Pick<ConversationDescriptorV1, 'participantPolicy'>): 'asserted' | 'derived';
19
+ /**
20
+ * Which profile governs this conversation.
21
+ *
22
+ * `forum`/`discussion` are boards — `topic`. Everything else is conversation — `direct`. Neither can
23
+ * create an obligation, which is true of both today and stated rather than left to inference. A
24
+ * conversation that needs to negotiate is promoted to its own Interaction under the negotiation
25
+ * profile (ADR-0058 §14), not granted extra acts here.
26
+ */
27
+ export declare function profileVersionOfConversation(descriptor: Pick<ConversationDescriptorV1, 'profile'>): ProfileVersion;
28
+ /**
29
+ * Lifecycle state.
30
+ *
31
+ * `archived` is deliberately NOT read as an ending. Spec 340 §P settled that shelving is a display
32
+ * concern that already lives in `InboxState`; an archived conversation has still either concluded or
33
+ * not, and conflating them would mean unarchiving a board silently reopened a concluded situation.
34
+ * The descriptor carries no concluded flag today, so every live conversation is `active` — stated here
35
+ * rather than invented, because inferring a conclusion from `archived` would be exactly the wrong fix.
36
+ */
37
+ export declare function lifecycleStateOfConversation(_descriptor: Pick<ConversationDescriptorV1, 'archived'>): InteractionState;
38
+ /** Participations, for an `asserted` conversation. Empty for a `derived` one — the whole point. */
39
+ export declare function participationsOfConversation(descriptor: Pick<ConversationDescriptorV1, 'participantPolicy' | 'participants' | 'createdAt'>): readonly ParticipationV1[];
40
+ /** What an Exchange in this conversation pins — `interactionId` + `profileVersion` in one call, so a
41
+ * caller cannot set one and forget the other. */
42
+ export interface ConversationExchangePins {
43
+ interactionId: InteractionId;
44
+ profileVersion: ProfileVersion;
45
+ }
46
+ export declare function conversationPins(descriptor: Pick<ConversationDescriptorV1, 'id' | 'profile'>): ConversationExchangePins;
47
+ /** The full interaction view of a conversation — the projection, assembled. */
48
+ export interface ConversationInteractionView {
49
+ interactionId: InteractionId;
50
+ profileVersion: ProfileVersion;
51
+ principal: CanonicalAgentId;
52
+ lifecycleState: InteractionState;
53
+ participationMode: 'asserted' | 'derived';
54
+ participations: readonly ParticipationV1[];
55
+ }
56
+ export declare function interactionViewOfConversation(descriptor: ConversationDescriptorV1): ConversationInteractionView;
57
+ /** Participation mode of a board channel — `open` topics derive membership, `restricted` assert it. */
58
+ export declare function participationModeOfChannel(channel: Pick<ChannelV1, 'participationPolicy' | 'visibility'>): 'asserted' | 'derived';
59
+ /**
60
+ * The interaction view of a live board channel — the one `demo-a2a` actually serves.
61
+ *
62
+ * Zero storage change: every field is read from what the board already persists. A topic in the vault
63
+ * IS an Interaction; this is how to read it as one.
64
+ */
65
+ export declare function interactionViewOfChannel(channel: ChannelV1): ConversationInteractionView;
66
+ //# sourceMappingURL=conversation-interaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-interaction.d.ts","sourceRoot":"","sources":["../../src/messaging/conversation-interaction.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC/F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAA8B,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAIxE,iGAAiG;AACjG,wBAAgB,yBAAyB,CAAC,cAAc,EAAE,cAAc,GAAG,MAAM,GAAG,aAAa,CAEhG;AAED;6EAC6E;AAC7E,wBAAgB,6BAA6B,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAElF;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,IAAI,CAAC,wBAAwB,EAAE,mBAAmB,CAAC,GAC9D,UAAU,GAAG,SAAS,CAExB;AAED;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,IAAI,CAAC,wBAAwB,EAAE,SAAS,CAAC,GACpD,cAAc,CAIhB;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,IAAI,CAAC,wBAAwB,EAAE,UAAU,CAAC,GACtD,gBAAgB,CAElB;AAED,mGAAmG;AACnG,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,IAAI,CAAC,wBAAwB,EAAE,mBAAmB,GAAG,cAAc,GAAG,WAAW,CAAC,GAC7F,SAAS,eAAe,EAAE,CAU5B;AAED;kDACkD;AAClD,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,aAAa,CAAC;IAC7B,cAAc,EAAE,cAAc,CAAC;CAChC;AAED,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,IAAI,CAAC,wBAAwB,EAAE,IAAI,GAAG,SAAS,CAAC,GAC3D,wBAAwB,CAK1B;AAED,+EAA+E;AAC/E,MAAM,WAAW,2BAA2B;IAC1C,aAAa,EAAE,aAAa,CAAC;IAC7B,cAAc,EAAE,cAAc,CAAC;IAC/B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,cAAc,EAAE,gBAAgB,CAAC;IACjC,iBAAiB,EAAE,UAAU,GAAG,SAAS,CAAC;IAC1C,cAAc,EAAE,SAAS,eAAe,EAAE,CAAC;CAC5C;AAED,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,wBAAwB,GACnC,2BAA2B,CAU7B;AAcD,uGAAuG;AACvG,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,qBAAqB,GAAG,YAAY,CAAC,GAC7D,UAAU,GAAG,SAAS,CAExB;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,SAAS,GAAG,2BAA2B,CAkBxF"}
@@ -0,0 +1,139 @@
1
+ // The vault-backed conversation, viewed as the Interaction it already is (spec 340 W12).
2
+ //
3
+ // WHY THIS FILE EXISTS, stated plainly because it is a correction. W11 made org topics a real
4
+ // Interaction by wiring `PrincipalGatewayDO.createChannel`/`postToChannel` — the DO-SQL channel store.
5
+ // `demo-a2a`, the only app that actually serves topics, does not use that store. It uses the
6
+ // VAULT-backed board (`createBoardChannel` / `appendBoardPost` over `ConversationDescriptorV1`). So
7
+ // W11 landed in a code path no demo runs, which is the same dormancy the whole exercise was meant to
8
+ // end — this time with the added problem that a third model of "a governed conversation" now existed.
9
+ //
10
+ // THE FIX IS A PROJECTION, NOT A MIGRATION. `ConversationDescriptorV1` already carries every field the
11
+ // Interaction needs, under different names:
12
+ //
13
+ // descriptor.id → the interaction identity (derived, see below)
14
+ // descriptor.owner → the custodian (`principal`)
15
+ // descriptor.participantPolicy → `participationMode`, exactly
16
+ // descriptor.participants → the asserted list, when there is one
17
+ // descriptor.profile → which InteractionProfile applies
18
+ // descriptor.archived → shelving, NOT the lifecycle (spec 340 §P)
19
+ //
20
+ // So nothing is stored twice and nothing migrates. A conversation IS an interaction; this says how to
21
+ // read it as one. Deriving rather than storing is deliberate: a stored copy of a value computable from
22
+ // the record is the drift this ontology work exists to remove, and it would need a migration to add.
23
+ import { TOPIC_PROFILE, DIRECT_PROFILE } from '../interaction-profile.js';
24
+ import { channelParticipationPolicy } from './board.js';
25
+ const CONVERSATION_PREFIX = 'ixn_conv_';
26
+ /** Derived from the conversation id, so the two can never disagree and no field needs adding. */
27
+ export function conversationInteractionId(conversationId) {
28
+ return `${CONVERSATION_PREFIX}${conversationId}`;
29
+ }
30
+ /** The inverse, or `null` for an id that is not a conversation interaction. Null rather than a guess —
31
+ * the same rule that keeps derived-participation resolution fail-closed. */
32
+ export function conversationIdFromInteraction(interactionId) {
33
+ return interactionId.startsWith(CONVERSATION_PREFIX) ? interactionId.slice(CONVERSATION_PREFIX.length) : null;
34
+ }
35
+ /**
36
+ * `participantPolicy` IS `participationMode`, and noticing that is what made this a projection.
37
+ *
38
+ * `open-to-context` means "anyone in the anchored org" — membership owned elsewhere, resolved at read
39
+ * time, never copied per conversation. That is precisely `derived`. `fixed` and `owner-managed` both
40
+ * mean the participant list on the record is the membership: `asserted`.
41
+ */
42
+ export function participationModeOfConversation(descriptor) {
43
+ return descriptor.participantPolicy === 'open-to-context' ? 'derived' : 'asserted';
44
+ }
45
+ /**
46
+ * Which profile governs this conversation.
47
+ *
48
+ * `forum`/`discussion` are boards — `topic`. Everything else is conversation — `direct`. Neither can
49
+ * create an obligation, which is true of both today and stated rather than left to inference. A
50
+ * conversation that needs to negotiate is promoted to its own Interaction under the negotiation
51
+ * profile (ADR-0058 §14), not granted extra acts here.
52
+ */
53
+ export function profileVersionOfConversation(descriptor) {
54
+ return descriptor.profile === 'forum' || descriptor.profile === 'discussion'
55
+ ? TOPIC_PROFILE.profileVersion
56
+ : DIRECT_PROFILE.profileVersion;
57
+ }
58
+ /**
59
+ * Lifecycle state.
60
+ *
61
+ * `archived` is deliberately NOT read as an ending. Spec 340 §P settled that shelving is a display
62
+ * concern that already lives in `InboxState`; an archived conversation has still either concluded or
63
+ * not, and conflating them would mean unarchiving a board silently reopened a concluded situation.
64
+ * The descriptor carries no concluded flag today, so every live conversation is `active` — stated here
65
+ * rather than invented, because inferring a conclusion from `archived` would be exactly the wrong fix.
66
+ */
67
+ export function lifecycleStateOfConversation(_descriptor) {
68
+ return 'active';
69
+ }
70
+ /** Participations, for an `asserted` conversation. Empty for a `derived` one — the whole point. */
71
+ export function participationsOfConversation(descriptor) {
72
+ if (participationModeOfConversation(descriptor) === 'derived')
73
+ return [];
74
+ return descriptor.participants.map((agent) => ({
75
+ agent,
76
+ role: 'participant',
77
+ // The descriptor records no per-participant join time, so the conversation's own is the honest
78
+ // answer: it is when membership was first observable, and claiming a more precise one would be
79
+ // inventing provenance.
80
+ joinedAt: descriptor.createdAt,
81
+ }));
82
+ }
83
+ export function conversationPins(descriptor) {
84
+ return {
85
+ interactionId: conversationInteractionId(descriptor.id),
86
+ profileVersion: profileVersionOfConversation(descriptor),
87
+ };
88
+ }
89
+ export function interactionViewOfConversation(descriptor) {
90
+ return {
91
+ ...conversationPins(descriptor),
92
+ // The descriptor's `owner` is the store that holds this copy, which for an org board is the org —
93
+ // the same custodial rule W3 enforces, arrived at from the other direction.
94
+ principal: descriptor.owner,
95
+ lifecycleState: lifecycleStateOfConversation(descriptor),
96
+ participationMode: participationModeOfConversation(descriptor),
97
+ participations: participationsOfConversation(descriptor),
98
+ };
99
+ }
100
+ // ─── Board channels ──────────────────────────────────────────────────────────
101
+ //
102
+ // A board `ChannelV1` (this subpath) is NOT the DO-SQL `ChannelV1` in `../cloudflare/channel-store.ts`.
103
+ // Same name, two different concepts, two subpaths — noted here rather than renamed, because renaming a
104
+ // live wire type is its own change; see spec 340 §C.
105
+ //
106
+ // The board channel is the better projection source than its descriptor: it carries
107
+ // `participationPolicy` DIRECTLY (`open` = derived from org membership and never stored; `restricted` =
108
+ // `members` is the list), with `channelParticipationPolicy` already resolving the legacy `visibility`
109
+ // spelling. Reading that instead of re-deriving from `participantPolicy` means one answer, from the
110
+ // field that actually decides it.
111
+ /** Participation mode of a board channel — `open` topics derive membership, `restricted` assert it. */
112
+ export function participationModeOfChannel(channel) {
113
+ return channelParticipationPolicy(channel) === 'open' ? 'derived' : 'asserted';
114
+ }
115
+ /**
116
+ * The interaction view of a live board channel — the one `demo-a2a` actually serves.
117
+ *
118
+ * Zero storage change: every field is read from what the board already persists. A topic in the vault
119
+ * IS an Interaction; this is how to read it as one.
120
+ */
121
+ export function interactionViewOfChannel(channel) {
122
+ const mode = participationModeOfChannel(channel);
123
+ return {
124
+ ...conversationPins(channel.descriptor),
125
+ principal: channel.descriptor.owner,
126
+ lifecycleState: lifecycleStateOfConversation(channel.descriptor),
127
+ participationMode: mode,
128
+ // A restricted topic's `members` IS the participant list (legacy field name; these are discussion
129
+ // participants, not the org roster). An open topic stores none, by design.
130
+ participations: mode === 'derived'
131
+ ? []
132
+ : (channel.members ?? []).map((agent) => ({
133
+ agent: agent,
134
+ role: 'participant',
135
+ joinedAt: channel.descriptor.createdAt,
136
+ })),
137
+ };
138
+ }
139
+ //# sourceMappingURL=conversation-interaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-interaction.js","sourceRoot":"","sources":["../../src/messaging/conversation-interaction.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import type { AuditSink } from '@agenticprimitives/audit';
2
2
  import type { InboxProjector } from './projector.js';
3
- import type { MessageEnvelopeV1, MessageEventV1 } from './types.js';
3
+ import type { AnyMessageEnvelope, MessageEventV1 } from './types.js';
4
4
  import type { RuleApplication } from './rules.js';
5
5
  export interface AuditedInboxDelivery {
6
6
  /**
@@ -8,7 +8,7 @@ export interface AuditedInboxDelivery {
8
8
  * `bodyBytes` is provided the body-hash binding is enforced (§8.4); pass the
9
9
  * bytes fetched from the vault whenever the body was transported.
10
10
  */
11
- admit(envelope: MessageEnvelopeV1, event: MessageEventV1, bodyBytes?: Uint8Array): Promise<RuleApplication>;
11
+ admit(envelope: AnyMessageEnvelope, event: MessageEventV1, bodyBytes?: Uint8Array): Promise<RuleApplication>;
12
12
  }
13
13
  export declare function createAuditedInboxDelivery(opts: {
14
14
  projector: InboxProjector;
@@ -1 +1 @@
1
- {"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../src/messaging/delivery.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAmBlD,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,KAAK,CACH,QAAQ,EAAE,iBAAiB,EAC3B,KAAK,EAAE,cAAc,EACrB,SAAS,CAAC,EAAE,UAAU,GACrB,OAAO,CAAC,eAAe,CAAC,CAAC;CAC7B;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,SAAS,EAAE,cAAc,CAAC;IAC1B,KAAK,EAAE,SAAS,CAAC;IACjB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,oBAAoB,CAiCvB"}
1
+ {"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../src/messaging/delivery.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAwBlD,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,KAAK,CACH,QAAQ,EAAE,kBAAkB,EAC5B,KAAK,EAAE,cAAc,EACrB,SAAS,CAAC,EAAE,UAAU,GACrB,OAAO,CAAC,eAAe,CAAC,CAAC;CAC7B;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,SAAS,EAAE,cAAc,CAAC;IAC1B,KAAK,EAAE,SAAS,CAAC;IACjB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,oBAAoB,CAiCvB"}
@@ -3,6 +3,8 @@
3
3
  // Fail-closed ordering: validate → verify body hash → AUDIT (await) → commit.
4
4
  // If the audit write fails the message is NOT admitted (spec 291 discipline for
5
5
  // privileged outcomes); rejects are audited as `denied` before throwing.
6
+ import { isEnvelopeV2 } from './types.js';
7
+ import { performativeOf } from '../communicative-act.js';
6
8
  import { validateMessageEnvelope } from './envelope.js';
7
9
  import { verifyBodyHash } from './hash.js';
8
10
  function auditEventBase(envelope, recipient) {
@@ -14,7 +16,12 @@ function auditEventBase(envelope, recipient) {
14
16
  // Hashes/ids only — never bodies, subjects, or PII (spec 309 §9).
15
17
  context: {
16
18
  from: envelope.from,
17
- kind: envelope.kind,
19
+ // spec 340 — the audit records what the message DOES, which spans both wire versions. `kind` is
20
+ // kept when the envelope is V1 so historical rows stay comparable, and is simply absent on V2
21
+ // rather than being back-derived: `performativeForKind` is not injective, so a reconstructed
22
+ // `kind` would be a guess written into an audit trail.
23
+ performative: performativeOf(envelope),
24
+ ...(isEnvelopeV2(envelope) ? {} : { kind: envelope.kind }),
18
25
  classification: envelope.classification,
19
26
  bodyHash: envelope.bodyHash,
20
27
  conversationId: envelope.conversationId,
@@ -1 +1 @@
1
- {"version":3,"file":"delivery.js","sourceRoot":"","sources":["../../src/messaging/delivery.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,EAAE;AACF,8EAA8E;AAC9E,gFAAgF;AAChF,yEAAyE;AAKzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG3C,SAAS,cAAc,CAAC,QAA2B,EAAE,SAAiB;IACpE,OAAO;QACL,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC,UAAU,EAAE;QAClC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,KAAK,EAAE,EAAE,IAAI,EAAE,SAAkB,EAAE,EAAE,EAAE,SAAS,EAAE;QAClD,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE;QAC7C,kEAAkE;QAClE,OAAO,EAAE;YACP,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,cAAc,EAAE,QAAQ,CAAC,cAAc;YACvC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,cAAc,EAAE,QAAQ,CAAC,cAAc;SACxC;KACF,CAAC;AACJ,CAAC;AAeD,MAAM,UAAU,0BAA0B,CAAC,IAK1C;IACC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAE7C,KAAK,UAAU,MAAM,CAAC,QAA2B,EAAE,MAAc;QAC/D,MAAM,KAAK,CAAC,KAAK,CAAC;YAChB,GAAG,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC;YACtC,MAAM,EAAE,0BAA0B;YAClC,OAAO,EAAE,QAAQ;YACjB,MAAM;SACP,CAAC,CAAC;QACH,MAAM,IAAI,KAAK,CAAC,WAAW,QAAQ,CAAC,EAAE,cAAc,MAAM,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,OAAO;QACL,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,SAAS;YACpC,MAAM,MAAM,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;YACjD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,MAAM,CAAC,QAAQ,EAAE,qBAAqB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACzF,IAAI,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,EAAE;gBAAE,OAAO,MAAM,CAAC,QAAQ,EAAE,4BAA4B,CAAC,CAAC;YAC3F,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;gBAC5E,OAAO,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;YAC/C,CAAC;YAED,oEAAoE;YACpE,MAAM,KAAK,CAAC,KAAK,CAAC;gBAChB,GAAG,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC;gBACtC,MAAM,EAAE,0BAA0B;gBAClC,OAAO,EAAE,SAAS;aACnB,CAAC,CAAC;YAEH,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC/B,OAAO,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"delivery.js","sourceRoot":"","sources":["../../src/messaging/delivery.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,EAAE;AACF,8EAA8E;AAC9E,gFAAgF;AAChF,yEAAyE;AAKzE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG3C,SAAS,cAAc,CAAC,QAA4B,EAAE,SAAiB;IACrE,OAAO;QACL,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC,UAAU,EAAE;QAClC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,KAAK,EAAE,EAAE,IAAI,EAAE,SAAkB,EAAE,EAAE,EAAE,SAAS,EAAE;QAClD,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE;QAC7C,kEAAkE;QAClE,OAAO,EAAE;YACP,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,gGAAgG;YAChG,8FAA8F;YAC9F,6FAA6F;YAC7F,uDAAuD;YACvD,YAAY,EAAE,cAAc,CAAC,QAAQ,CAAC;YACtC,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC1D,cAAc,EAAE,QAAQ,CAAC,cAAc;YACvC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,cAAc,EAAE,QAAQ,CAAC,cAAc;SACxC;KACF,CAAC;AACJ,CAAC;AAeD,MAAM,UAAU,0BAA0B,CAAC,IAK1C;IACC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAE7C,KAAK,UAAU,MAAM,CAAC,QAA4B,EAAE,MAAc;QAChE,MAAM,KAAK,CAAC,KAAK,CAAC;YAChB,GAAG,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC;YACtC,MAAM,EAAE,0BAA0B;YAClC,OAAO,EAAE,QAAQ;YACjB,MAAM;SACP,CAAC,CAAC;QACH,MAAM,IAAI,KAAK,CAAC,WAAW,QAAQ,CAAC,EAAE,cAAc,MAAM,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,OAAO;QACL,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,SAAS;YACpC,MAAM,MAAM,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;YACjD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,MAAM,CAAC,QAAQ,EAAE,qBAAqB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACzF,IAAI,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,EAAE;gBAAE,OAAO,MAAM,CAAC,QAAQ,EAAE,4BAA4B,CAAC,CAAC;YAC3F,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;gBAC5E,OAAO,MAAM,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;YAC/C,CAAC;YAED,oEAAoE;YACpE,MAAM,KAAK,CAAC,KAAK,CAAC;gBAChB,GAAG,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC;gBACtC,MAAM,EAAE,0BAA0B;gBAClC,OAAO,EAAE,SAAS;aACnB,CAAC,CAAC;YAEH,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC/B,OAAO,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -17,6 +17,22 @@ export interface DirectoryListingV1 {
17
17
  roles?: string[];
18
18
  /** Where signed envelopes can be delivered (the subject's Home inbox). */
19
19
  inboxEndpoint?: string;
20
+ /** spec 329 §2.2 — member-asserted, org-scoped routing HINT (aporg:consultable): "my agent may
21
+ * be consulted for this org's discussions". The AUTHORITY is the consultability delegation —
22
+ * flag without delegation ⇒ not consultable (fail-closed); delegation without flag ⇒ not
23
+ * surfaced to routing. Absent ⇒ false. Inside the signed digest (additive optional field —
24
+ * legacy listings verify unchanged; setting/clearing it is a re-publish, i.e. re-signed). */
25
+ consultable?: boolean;
26
+ /** spec 329 §12 — the member's PRIMARY ROLE **in this organization**, self-asserted ("tax
27
+ * advisor", "financial advisor"). Org-scoped by construction: the listing IS per-org, so the
28
+ * same person holds a different role in each org they list themselves in. MEMBER-AUTHORED —
29
+ * the listing is member-signed, so nobody else can set it (a steward-assigned role is out of
30
+ * scope, §12.2). Free text, display + routing HINT only: it is never an authorization and never
31
+ * a verified credential. Distinct from the display-only {@link DirectoryListingV1.roles} list
32
+ * (unstructured, multi-valued, pre-329) — routing needs ONE primary role per org.
33
+ * Inside the signed digest (additive optional field — legacy listings verify byte-identically;
34
+ * setting/clearing it is a re-publish, i.e. re-signed). Absent ⇒ no role asserted. */
35
+ orgRole?: string;
20
36
  visibility: 'community' | 'public';
21
37
  publishedAt: string;
22
38
  expiresAt?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"directory.d.ts","sourceRoot":"","sources":["../../src/messaging/directory.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,8BAA8B,CAAC;IACrC,iEAAiE;IACjE,OAAO,EAAE,gBAAgB,CAAC;IAC1B,+EAA+E;IAC/E,OAAO,EAAE,YAAY,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,WAAW,GAAG,QAAQ,CAAC;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,cAAc,CAAC;CACvB;AAED,MAAM,MAAM,sBAAsB,GAC9B,UAAU,GACV,iBAAiB,GACjB,aAAa,GACb,sBAAsB,GACtB,gBAAgB,GAChB,kBAAkB,GAClB,gBAAgB,GAChB,eAAe,GACf,mBAAmB,CAAC;AAExB;;gEAEgE;AAChE,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,kBAAkB,GAAG,sBAAsB,EAAE,CAexF;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAI9E"}
1
+ {"version":3,"file":"directory.d.ts","sourceRoot":"","sources":["../../src/messaging/directory.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,8BAA8B,CAAC;IACrC,iEAAiE;IACjE,OAAO,EAAE,gBAAgB,CAAC;IAC1B,+EAA+E;IAC/E,OAAO,EAAE,YAAY,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;kGAI8F;IAC9F,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;;2FAQuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,WAAW,GAAG,QAAQ,CAAC;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,cAAc,CAAC;CACvB;AAED,MAAM,MAAM,sBAAsB,GAC9B,UAAU,GACV,iBAAiB,GACjB,aAAa,GACb,sBAAsB,GACtB,gBAAgB,GAChB,kBAAkB,GAClB,gBAAgB,GAChB,eAAe,GACf,mBAAmB,CAAC;AAExB;;gEAEgE;AAChE,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,kBAAkB,GAAG,sBAAsB,EAAE,CAexF;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAI9E"}
@@ -1 +1 @@
1
- {"version":3,"file":"directory.js","sourceRoot":"","sources":["../../src/messaging/directory.ts"],"names":[],"mappings":"AA8CA;;gEAEgE;AAChE,MAAM,UAAU,wBAAwB,CAAC,CAAqB;IAC5D,MAAM,MAAM,GAA6B,EAAE,CAAC;IAC5C,IAAI,CAAC,CAAC,IAAI,KAAK,8BAA8B;QAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvE,IAAI,CAAC,CAAC,CAAC,OAAO;QAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC/C,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE;QAAE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACnF,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE;QAAE,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAChE,IAAI,CAAC,CAAC,UAAU,KAAK,WAAW,IAAI,CAAC,CAAC,UAAU,KAAK,QAAQ;QAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC7F,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC/F,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACtG,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,SAAS;QAAE,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;SACjD,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;QAC/E,mEAAmE;QACnE,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,gBAAgB,CAAC,CAAqB,EAAE,KAAa;IACnE,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC;QAAE,OAAO,KAAK,CAAC;IACrE,OAAO,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AACnE,CAAC"}
1
+ {"version":3,"file":"directory.js","sourceRoot":"","sources":["../../src/messaging/directory.ts"],"names":[],"mappings":"AA8DA;;gEAEgE;AAChE,MAAM,UAAU,wBAAwB,CAAC,CAAqB;IAC5D,MAAM,MAAM,GAA6B,EAAE,CAAC;IAC5C,IAAI,CAAC,CAAC,IAAI,KAAK,8BAA8B;QAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvE,IAAI,CAAC,CAAC,CAAC,OAAO;QAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC/C,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE;QAAE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACnF,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE;QAAE,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAChE,IAAI,CAAC,CAAC,UAAU,KAAK,WAAW,IAAI,CAAC,CAAC,UAAU,KAAK,QAAQ;QAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC7F,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC/F,IAAI,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACtG,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,SAAS;QAAE,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;SACjD,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;QAC/E,mEAAmE;QACnE,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,gBAAgB,CAAC,CAAqB,EAAE,KAAa;IACnE,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC;QAAE,OAAO,KAAK,CAAC;IACrE,OAAO,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AACnE,CAAC"}
@@ -1,8 +1,12 @@
1
- import type { ConversationId, MessageEnvelopeV1, MessageId, ThreadId } from './types.js';
1
+ import type { AnyMessageEnvelope, ConversationId, MessageId, ThreadId } from './types.js';
2
2
  export declare function generateMessageId(): MessageId;
3
3
  export declare function generateConversationId(): ConversationId;
4
4
  export declare function generateThreadId(): ThreadId;
5
- export type EnvelopeValidationError = 'bad_version' | 'bad_id' | 'bad_conversation_id' | 'missing_from' | 'empty_recipients' | 'bad_created_at' | 'bad_expires_at' | 'expired_before_created' | 'bad_body_hash' | 'missing_body_content_type' | 'bad_attachment_hash' | 'too_many_context_refs' | 'bad_context_ref';
5
+ export type EnvelopeValidationError = 'bad_version' | 'bad_id' | 'bad_conversation_id' | 'missing_from' | 'empty_recipients' | 'bad_created_at' | 'bad_expires_at' | 'expired_before_created' | 'bad_body_hash' | 'missing_body_content_type' | 'bad_attachment_hash' | 'too_many_context_refs' | 'bad_context_ref'
6
+ /** V2-only (spec 340 cutover): the version says v2 but the act it performs is absent. */
7
+ | 'missing_performative'
8
+ /** V2-only: a half-migrated sender stamped v2 while still emitting the retired `kind` taxonomy. */
9
+ | 'v2_carries_retired_kind';
6
10
  /** Envelope context refs are bounded so refs stay metadata, not payload. */
7
11
  export declare const MAX_CONTEXT_REFS = 8;
8
12
  /**
@@ -10,5 +14,5 @@ export declare const MAX_CONTEXT_REFS = 8;
10
14
  * recipient admission policy are the recipient runtime's job (spec 309 §4.4).
11
15
  * Returns an empty array iff the envelope is structurally admissible.
12
16
  */
13
- export declare function validateMessageEnvelope(env: MessageEnvelopeV1): EnvelopeValidationError[];
17
+ export declare function validateMessageEnvelope(env: AnyMessageEnvelope): EnvelopeValidationError[];
14
18
  //# sourceMappingURL=envelope.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../../src/messaging/envelope.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAUzF,wBAAgB,iBAAiB,IAAI,SAAS,CAE7C;AAED,wBAAgB,sBAAsB,IAAI,cAAc,CAEvD;AAED,wBAAgB,gBAAgB,IAAI,QAAQ,CAE3C;AAED,MAAM,MAAM,uBAAuB,GAC/B,aAAa,GACb,QAAQ,GACR,qBAAqB,GACrB,cAAc,GACd,kBAAkB,GAClB,gBAAgB,GAChB,gBAAgB,GAChB,wBAAwB,GACxB,eAAe,GACf,2BAA2B,GAC3B,qBAAqB,GACrB,uBAAuB,GACvB,iBAAiB,CAAC;AAEtB,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAQlC;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,iBAAiB,GAAG,uBAAuB,EAAE,CA+BzF"}
1
+ {"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../../src/messaging/envelope.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAqB,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAW7G,wBAAgB,iBAAiB,IAAI,SAAS,CAE7C;AAED,wBAAgB,sBAAsB,IAAI,cAAc,CAEvD;AAED,wBAAgB,gBAAgB,IAAI,QAAQ,CAE3C;AAED,MAAM,MAAM,uBAAuB,GAC/B,aAAa,GACb,QAAQ,GACR,qBAAqB,GACrB,cAAc,GACd,kBAAkB,GAClB,gBAAgB,GAChB,gBAAgB,GAChB,wBAAwB,GACxB,eAAe,GACf,2BAA2B,GAC3B,qBAAqB,GACrB,uBAAuB,GACvB,iBAAiB;AACnB,yFAAyF;GACvF,sBAAsB;AACxB,mGAAmG;GACjG,yBAAyB,CAAC;AAE9B,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAQlC;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,kBAAkB,GAAG,uBAAuB,EAAE,CA6C1F"}
@@ -1,4 +1,5 @@
1
1
  // Envelope construction + structural validation (fail-closed, spec 309 §8).
2
+ import { isEnvelopeV2 } from './types.js';
2
3
  function randomSuffix() {
3
4
  const bytes = new Uint8Array(16);
4
5
  globalThis.crypto.getRandomValues(bytes);
@@ -28,8 +29,24 @@ function isIsoDate(s) {
28
29
  */
29
30
  export function validateMessageEnvelope(env) {
30
31
  const errors = [];
31
- if (env.version !== 'ap.message.v1')
32
+ // spec 340 — the ap.message.v2 cutover, reader half. BOTH wire versions are structurally
33
+ // admissible. This must ship and be DEPLOYED EVERYWHERE before any sender emits V2: a V2 envelope
34
+ // reaching a validator that only knows V1 is rejected as `bad_version`, which on a peer hop is a
35
+ // delivery failure, not a degraded read.
36
+ //
37
+ // The two shapes are checked for what each one IS, not merely tolerated: V2 must carry a
38
+ // `performative` and must NOT carry `kind`, so a half-migrated sender that stamps v2 while still
39
+ // emitting the retired taxonomy fails here instead of quietly producing an envelope whose version
40
+ // and content disagree.
41
+ if (isEnvelopeV2(env)) {
42
+ if (!env.performative)
43
+ errors.push('missing_performative');
44
+ if (env.kind !== undefined)
45
+ errors.push('v2_carries_retired_kind');
46
+ }
47
+ else if (env.version !== 'ap.message.v1') {
32
48
  errors.push('bad_version');
49
+ }
33
50
  if (!env.id?.startsWith('msg_'))
34
51
  errors.push('bad_id');
35
52
  if (!env.conversationId?.startsWith('conv_'))
@@ -1 +1 @@
1
- {"version":3,"file":"envelope.js","sourceRoot":"","sources":["../../src/messaging/envelope.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"envelope.js","sourceRoot":"","sources":["../../src/messaging/envelope.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { Hex32, MessageEnvelopeV1 } from './types.js';
1
+ import type { AnyMessageEnvelope, Hex32, MessageEnvelopeV1 } from './types.js';
2
2
  import { canonicalizeJson } from '@agenticprimitives/types';
3
3
  /** Deterministic JSON: sorted keys, `undefined` members dropped. Hoisted to `@agenticprimitives/types` as
4
4
  * `canonicalizeJson` (spec 316 Open Decision F); kept here as an alias for back-compat. */
@@ -8,8 +8,14 @@ export declare function sha256Hex32(input: string | Uint8Array): Promise<Hex32>;
8
8
  * Hash of the canonical envelope EXCLUDING `signature` — this is the payload a
9
9
  * sender signs and a recipient verifies (spec 309 §8.1). Deterministic across
10
10
  * key order and undefined optional fields.
11
+ *
12
+ * Version-agnostic BY CONSTRUCTION, and that is the property the ap.message.v2 cutover rests on: it
13
+ * canonicalizes whatever fields the envelope has. A V1 envelope hashes today exactly as it hashed
14
+ * before V2 existed, so every historical signature and delivery receipt still verifies. `version` is
15
+ * itself inside the hashed body, so V1 and V2 of otherwise-identical content are domain-separated for
16
+ * free — no envelope can be replayed across versions.
11
17
  */
12
- export declare function hashMessageEnvelope(envelope: MessageEnvelopeV1): Promise<Hex32>;
18
+ export declare function hashMessageEnvelope(envelope: AnyMessageEnvelope): Promise<Hex32>;
13
19
  /**
14
20
  * Body-hash binding (spec 309 §8.4): the envelope's `bodyHash` MUST equal the
15
21
  * digest of the vault-resident body bytes. Recipients enforce this BEFORE
@@ -1 +1 @@
1
- {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/messaging/hash.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAI5D;4FAC4F;AAC5F,eAAO,MAAM,mBAAmB,yBAAmB,CAAC;AAEpD,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,CAO5E;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,CAGrF;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,EAC7C,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC,OAAO,CAAC,CAElB"}
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/messaging/hash.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAI5D;4FAC4F;AAC5F,eAAO,MAAM,mBAAmB,yBAAmB,CAAC;AAEpD,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,CAO5E;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC,CAGtF;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,EAC7C,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC,OAAO,CAAC,CAElB"}
@@ -20,6 +20,12 @@ export async function sha256Hex32(input) {
20
20
  * Hash of the canonical envelope EXCLUDING `signature` — this is the payload a
21
21
  * sender signs and a recipient verifies (spec 309 §8.1). Deterministic across
22
22
  * key order and undefined optional fields.
23
+ *
24
+ * Version-agnostic BY CONSTRUCTION, and that is the property the ap.message.v2 cutover rests on: it
25
+ * canonicalizes whatever fields the envelope has. A V1 envelope hashes today exactly as it hashed
26
+ * before V2 existed, so every historical signature and delivery receipt still verifies. `version` is
27
+ * itself inside the hashed body, so V1 and V2 of otherwise-identical content are domain-separated for
28
+ * free — no envelope can be replayed across versions.
23
29
  */
24
30
  export async function hashMessageEnvelope(envelope) {
25
31
  const { signature: _signature, ...unsigned } = envelope;