@agenticprimitives/fabric 0.0.0-alpha.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 (201) hide show
  1. package/CLAUDE.md +67 -0
  2. package/LICENSE +21 -0
  3. package/README.md +21 -0
  4. package/dist/case-machine.d.ts +76 -0
  5. package/dist/case-machine.d.ts.map +1 -0
  6. package/dist/case-machine.js +83 -0
  7. package/dist/case-machine.js.map +1 -0
  8. package/dist/client/index.d.ts +114 -0
  9. package/dist/client/index.d.ts.map +1 -0
  10. package/dist/client/index.js +76 -0
  11. package/dist/client/index.js.map +1 -0
  12. package/dist/cloudflare/authority-verdict-cache.d.ts +27 -0
  13. package/dist/cloudflare/authority-verdict-cache.d.ts.map +1 -0
  14. package/dist/cloudflare/authority-verdict-cache.js +66 -0
  15. package/dist/cloudflare/authority-verdict-cache.js.map +1 -0
  16. package/dist/cloudflare/channel-store.d.ts +61 -0
  17. package/dist/cloudflare/channel-store.d.ts.map +1 -0
  18. package/dist/cloudflare/channel-store.js +124 -0
  19. package/dist/cloudflare/channel-store.js.map +1 -0
  20. package/dist/cloudflare/exchange-store.d.ts +16 -0
  21. package/dist/cloudflare/exchange-store.d.ts.map +1 -0
  22. package/dist/cloudflare/exchange-store.js +45 -0
  23. package/dist/cloudflare/exchange-store.js.map +1 -0
  24. package/dist/cloudflare/gateway-tools.d.ts +28 -0
  25. package/dist/cloudflare/gateway-tools.d.ts.map +1 -0
  26. package/dist/cloudflare/gateway-tools.js +45 -0
  27. package/dist/cloudflare/gateway-tools.js.map +1 -0
  28. package/dist/cloudflare/index.d.ts +13 -0
  29. package/dist/cloudflare/index.d.ts.map +1 -0
  30. package/dist/cloudflare/index.js +20 -0
  31. package/dist/cloudflare/index.js.map +1 -0
  32. package/dist/cloudflare/orchestration-runtime.d.ts +28 -0
  33. package/dist/cloudflare/orchestration-runtime.d.ts.map +1 -0
  34. package/dist/cloudflare/orchestration-runtime.js +35 -0
  35. package/dist/cloudflare/orchestration-runtime.js.map +1 -0
  36. package/dist/cloudflare/outbox-store.d.ts +24 -0
  37. package/dist/cloudflare/outbox-store.d.ts.map +1 -0
  38. package/dist/cloudflare/outbox-store.js +42 -0
  39. package/dist/cloudflare/outbox-store.js.map +1 -0
  40. package/dist/cloudflare/principal-gateway-do.d.ts +234 -0
  41. package/dist/cloudflare/principal-gateway-do.d.ts.map +1 -0
  42. package/dist/cloudflare/principal-gateway-do.js +369 -0
  43. package/dist/cloudflare/principal-gateway-do.js.map +1 -0
  44. package/dist/cloudflare/provenance-store.d.ts +9 -0
  45. package/dist/cloudflare/provenance-store.d.ts.map +1 -0
  46. package/dist/cloudflare/provenance-store.js +36 -0
  47. package/dist/cloudflare/provenance-store.js.map +1 -0
  48. package/dist/cloudflare/receipt-signer.d.ts +26 -0
  49. package/dist/cloudflare/receipt-signer.d.ts.map +1 -0
  50. package/dist/cloudflare/receipt-signer.js +69 -0
  51. package/dist/cloudflare/receipt-signer.js.map +1 -0
  52. package/dist/cloudflare/request-id-ledger.d.ts +13 -0
  53. package/dist/cloudflare/request-id-ledger.d.ts.map +1 -0
  54. package/dist/cloudflare/request-id-ledger.js +38 -0
  55. package/dist/cloudflare/request-id-ledger.js.map +1 -0
  56. package/dist/cloudflare/sql-vault.d.ts +10 -0
  57. package/dist/cloudflare/sql-vault.d.ts.map +1 -0
  58. package/dist/cloudflare/sql-vault.js +98 -0
  59. package/dist/cloudflare/sql-vault.js.map +1 -0
  60. package/dist/communicative-act.d.ts +47 -0
  61. package/dist/communicative-act.d.ts.map +1 -0
  62. package/dist/communicative-act.js +36 -0
  63. package/dist/communicative-act.js.map +1 -0
  64. package/dist/delivery-envelope.d.ts +38 -0
  65. package/dist/delivery-envelope.d.ts.map +1 -0
  66. package/dist/delivery-envelope.js +43 -0
  67. package/dist/delivery-envelope.js.map +1 -0
  68. package/dist/exchange-record.d.ts +131 -0
  69. package/dist/exchange-record.d.ts.map +1 -0
  70. package/dist/exchange-record.js +25 -0
  71. package/dist/exchange-record.js.map +1 -0
  72. package/dist/exchange-reducer.d.ts +25 -0
  73. package/dist/exchange-reducer.d.ts.map +1 -0
  74. package/dist/exchange-reducer.js +108 -0
  75. package/dist/exchange-reducer.js.map +1 -0
  76. package/dist/exchange-state.d.ts +56 -0
  77. package/dist/exchange-state.d.ts.map +1 -0
  78. package/dist/exchange-state.js +81 -0
  79. package/dist/exchange-state.js.map +1 -0
  80. package/dist/gateway-surface.d.ts +24 -0
  81. package/dist/gateway-surface.d.ts.map +1 -0
  82. package/dist/gateway-surface.js +33 -0
  83. package/dist/gateway-surface.js.map +1 -0
  84. package/dist/inbox-doc.d.ts +32 -0
  85. package/dist/inbox-doc.d.ts.map +1 -0
  86. package/dist/inbox-doc.js +57 -0
  87. package/dist/inbox-doc.js.map +1 -0
  88. package/dist/inbox-projection.d.ts +15 -0
  89. package/dist/inbox-projection.d.ts.map +1 -0
  90. package/dist/inbox-projection.js +28 -0
  91. package/dist/inbox-projection.js.map +1 -0
  92. package/dist/index.d.ts +19 -0
  93. package/dist/index.d.ts.map +1 -0
  94. package/dist/index.js +30 -0
  95. package/dist/index.js.map +1 -0
  96. package/dist/interactions/audited.d.ts +12 -0
  97. package/dist/interactions/audited.d.ts.map +1 -0
  98. package/dist/interactions/audited.js +67 -0
  99. package/dist/interactions/audited.js.map +1 -0
  100. package/dist/interactions/builders.d.ts +24 -0
  101. package/dist/interactions/builders.d.ts.map +1 -0
  102. package/dist/interactions/builders.js +48 -0
  103. package/dist/interactions/builders.js.map +1 -0
  104. package/dist/interactions/cards.d.ts +32 -0
  105. package/dist/interactions/cards.d.ts.map +1 -0
  106. package/dist/interactions/cards.js +20 -0
  107. package/dist/interactions/cards.js.map +1 -0
  108. package/dist/interactions/index.d.ts +15 -0
  109. package/dist/interactions/index.d.ts.map +1 -0
  110. package/dist/interactions/index.js +23 -0
  111. package/dist/interactions/index.js.map +1 -0
  112. package/dist/interactions/machine.d.ts +19 -0
  113. package/dist/interactions/machine.d.ts.map +1 -0
  114. package/dist/interactions/machine.js +31 -0
  115. package/dist/interactions/machine.js.map +1 -0
  116. package/dist/interactions/mandates.d.ts +64 -0
  117. package/dist/interactions/mandates.d.ts.map +1 -0
  118. package/dist/interactions/mandates.js +62 -0
  119. package/dist/interactions/mandates.js.map +1 -0
  120. package/dist/interactions/relationship.d.ts +29 -0
  121. package/dist/interactions/relationship.d.ts.map +1 -0
  122. package/dist/interactions/relationship.js +31 -0
  123. package/dist/interactions/relationship.js.map +1 -0
  124. package/dist/interactions/risk.d.ts +39 -0
  125. package/dist/interactions/risk.d.ts.map +1 -0
  126. package/dist/interactions/risk.js +49 -0
  127. package/dist/interactions/risk.js.map +1 -0
  128. package/dist/interactions/runs.d.ts +26 -0
  129. package/dist/interactions/runs.d.ts.map +1 -0
  130. package/dist/interactions/runs.js +80 -0
  131. package/dist/interactions/runs.js.map +1 -0
  132. package/dist/interactions/store.d.ts +20 -0
  133. package/dist/interactions/store.d.ts.map +1 -0
  134. package/dist/interactions/store.js +68 -0
  135. package/dist/interactions/store.js.map +1 -0
  136. package/dist/interactions/tickets.d.ts +68 -0
  137. package/dist/interactions/tickets.d.ts.map +1 -0
  138. package/dist/interactions/tickets.js +49 -0
  139. package/dist/interactions/tickets.js.map +1 -0
  140. package/dist/interactions/types.d.ts +160 -0
  141. package/dist/interactions/types.d.ts.map +1 -0
  142. package/dist/interactions/types.js +7 -0
  143. package/dist/interactions/types.js.map +1 -0
  144. package/dist/messaging/board.d.ts +54 -0
  145. package/dist/messaging/board.d.ts.map +1 -0
  146. package/dist/messaging/board.js +90 -0
  147. package/dist/messaging/board.js.map +1 -0
  148. package/dist/messaging/conversation.d.ts +35 -0
  149. package/dist/messaging/conversation.d.ts.map +1 -0
  150. package/dist/messaging/conversation.js +72 -0
  151. package/dist/messaging/conversation.js.map +1 -0
  152. package/dist/messaging/delivery.d.ts +19 -0
  153. package/dist/messaging/delivery.d.ts.map +1 -0
  154. package/dist/messaging/delivery.js +56 -0
  155. package/dist/messaging/delivery.js.map +1 -0
  156. package/dist/messaging/directory.d.ts +32 -0
  157. package/dist/messaging/directory.d.ts.map +1 -0
  158. package/dist/messaging/directory.js +35 -0
  159. package/dist/messaging/directory.js.map +1 -0
  160. package/dist/messaging/envelope.d.ts +14 -0
  161. package/dist/messaging/envelope.d.ts.map +1 -0
  162. package/dist/messaging/envelope.js +71 -0
  163. package/dist/messaging/envelope.js.map +1 -0
  164. package/dist/messaging/hash.d.ts +19 -0
  165. package/dist/messaging/hash.d.ts.map +1 -0
  166. package/dist/messaging/hash.js +36 -0
  167. package/dist/messaging/hash.js.map +1 -0
  168. package/dist/messaging/index.d.ts +16 -0
  169. package/dist/messaging/index.d.ts.map +1 -0
  170. package/dist/messaging/index.js +29 -0
  171. package/dist/messaging/index.js.map +1 -0
  172. package/dist/messaging/projector.d.ts +58 -0
  173. package/dist/messaging/projector.d.ts.map +1 -0
  174. package/dist/messaging/projector.js +103 -0
  175. package/dist/messaging/projector.js.map +1 -0
  176. package/dist/messaging/receipts.d.ts +5 -0
  177. package/dist/messaging/receipts.d.ts.map +1 -0
  178. package/dist/messaging/receipts.js +19 -0
  179. package/dist/messaging/receipts.js.map +1 -0
  180. package/dist/messaging/rules.d.ts +84 -0
  181. package/dist/messaging/rules.d.ts.map +1 -0
  182. package/dist/messaging/rules.js +109 -0
  183. package/dist/messaging/rules.js.map +1 -0
  184. package/dist/messaging/store.d.ts +24 -0
  185. package/dist/messaging/store.d.ts.map +1 -0
  186. package/dist/messaging/store.js +120 -0
  187. package/dist/messaging/store.js.map +1 -0
  188. package/dist/messaging/types.d.ts +166 -0
  189. package/dist/messaging/types.d.ts.map +1 -0
  190. package/dist/messaging/types.js +7 -0
  191. package/dist/messaging/types.js.map +1 -0
  192. package/dist/messaging/vault-store.d.ts +37 -0
  193. package/dist/messaging/vault-store.d.ts.map +1 -0
  194. package/dist/messaging/vault-store.js +62 -0
  195. package/dist/messaging/vault-store.js.map +1 -0
  196. package/dist/record-catalog.d.ts +22 -0
  197. package/dist/record-catalog.d.ts.map +1 -0
  198. package/dist/record-catalog.js +35 -0
  199. package/dist/record-catalog.js.map +1 -0
  200. package/package.json +82 -0
  201. package/spec.md +15 -0
@@ -0,0 +1,109 @@
1
+ // Deterministic inbox rules (spec 309 §5). Rules may ONLY mutate the
2
+ // projection (move/label/category/read-state/priority) and fire notifications.
3
+ // The action union is closed on purpose: a rule can never issue entitlements,
4
+ // grant delegation, release keys, or change custody — those verbs do not exist
5
+ // here and must never be added.
6
+ const PRIORITY_ORDER = ['low', 'normal', 'high', 'urgent'];
7
+ /** Shared context-match used by rules and `listByContext` — ONE mechanism (ADR-0013). */
8
+ export function matchesContextRef(refs, query) {
9
+ return refs.some((r) => r.kind === query.kind && (query.id === undefined || r.id === query.id));
10
+ }
11
+ export function matchesRulePredicate(predicate, envelope, item) {
12
+ if (predicate.fromAnyOf && !predicate.fromAnyOf.includes(envelope.from))
13
+ return false;
14
+ if (predicate.kindAnyOf && !predicate.kindAnyOf.includes(envelope.kind))
15
+ return false;
16
+ if (predicate.subjectContainsAnyOf) {
17
+ const subject = (envelope.subject ?? '').toLowerCase();
18
+ if (!predicate.subjectContainsAnyOf.some((s) => subject.includes(s.toLowerCase())))
19
+ return false;
20
+ }
21
+ if (predicate.labelAnyOf && !predicate.labelAnyOf.some((l) => item.labels.includes(l)))
22
+ return false;
23
+ if (predicate.priorityAtLeast !== undefined) {
24
+ if (PRIORITY_ORDER.indexOf(item.priority) < PRIORITY_ORDER.indexOf(predicate.priorityAtLeast))
25
+ return false;
26
+ }
27
+ if (predicate.hasAttachments !== undefined) {
28
+ if (((envelope.attachments?.length ?? 0) > 0) !== predicate.hasAttachments)
29
+ return false;
30
+ }
31
+ if (predicate.classificationAnyOf && !predicate.classificationAnyOf.includes(envelope.classification))
32
+ return false;
33
+ if (predicate.hasInteraction !== undefined) {
34
+ if ((envelope.interactionId !== undefined) !== predicate.hasInteraction)
35
+ return false;
36
+ }
37
+ if (predicate.contextRefAnyOf) {
38
+ const refs = envelope.contextRefs ?? [];
39
+ if (!predicate.contextRefAnyOf.some((q) => matchesContextRef(refs, q)))
40
+ return false;
41
+ }
42
+ return true;
43
+ }
44
+ /**
45
+ * Pure, deterministic rule pass over a freshly projected inbox item.
46
+ * Rules run in (order, id) order; disabled rules skip; `except` vetoes `when`;
47
+ * `stopProcessing` halts later rules after the current one's actions apply.
48
+ */
49
+ export function applyInboxRules(item, envelope, rules) {
50
+ const ordered = [...rules].sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));
51
+ let next = { ...item, labels: [...item.labels], categories: [...item.categories] };
52
+ const notifications = [];
53
+ const appliedRuleIds = [];
54
+ let suppressed = false;
55
+ for (const rule of ordered) {
56
+ if (!rule.enabled)
57
+ continue;
58
+ if (!matchesRulePredicate(rule.when, envelope, next))
59
+ continue;
60
+ if (rule.except && matchesRulePredicate(rule.except, envelope, next))
61
+ continue;
62
+ appliedRuleIds.push(rule.id);
63
+ for (const action of rule.actions) {
64
+ switch (action.type) {
65
+ case 'move':
66
+ next.folder = action.folder;
67
+ break;
68
+ case 'label':
69
+ if (!next.labels.includes(action.label))
70
+ next.labels.push(action.label);
71
+ break;
72
+ case 'category':
73
+ if (!next.categories.includes(action.category))
74
+ next.categories.push(action.category);
75
+ break;
76
+ case 'mark-read':
77
+ next.unread = false;
78
+ break;
79
+ case 'mark-unread':
80
+ next.unread = true;
81
+ break;
82
+ case 'set-priority':
83
+ next.priority = action.priority;
84
+ break;
85
+ case 'notify':
86
+ notifications.push({
87
+ version: 'ap.message.notification.v1',
88
+ messageId: next.messageId,
89
+ ruleId: rule.id,
90
+ channel: action.channel,
91
+ at: next.lastEventAt,
92
+ });
93
+ break;
94
+ case 'suppress-notification':
95
+ suppressed = true;
96
+ break;
97
+ }
98
+ }
99
+ if (rule.stopProcessing)
100
+ break;
101
+ }
102
+ return {
103
+ item: next,
104
+ notifications: suppressed ? [] : notifications,
105
+ suppressed,
106
+ appliedRuleIds,
107
+ };
108
+ }
109
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/messaging/rules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { FolderKind, InboxItemV1, MessageEnvelopeV1, MessageEventV1, MessageId } from './types.js';
2
+ /**
3
+ * Pure projection step. Given the previous inbox row (or undefined for the
4
+ * first event) and the next lifecycle event, produce the new row.
5
+ * Throws on a messageId mismatch — events never apply across messages.
6
+ */
7
+ export declare function applyMessageEvent(prev: InboxItemV1 | undefined, envelope: MessageEnvelopeV1, event: MessageEventV1): InboxItemV1;
8
+ export interface MessageStore {
9
+ /**
10
+ * Admit an envelope. Fail-closed: structurally invalid envelopes throw.
11
+ * Re-putting an identical envelope is idempotent; a DIFFERENT envelope under
12
+ * an existing id throws (blocks envelope substitution under a known id).
13
+ */
14
+ putMessage(envelope: MessageEnvelopeV1): void;
15
+ getMessage(id: MessageId): MessageEnvelopeV1 | null;
16
+ /** Append a lifecycle event. Throws for unknown messages or id mismatch. */
17
+ appendEvent(event: MessageEventV1): InboxItemV1;
18
+ listEvents(id: MessageId): MessageEventV1[];
19
+ getInboxItem(id: MessageId): InboxItemV1 | null;
20
+ listInbox(folder?: FolderKind): InboxItemV1[];
21
+ unreadCount(folder?: FolderKind): number;
22
+ }
23
+ export declare function createInMemoryMessageStore(): MessageStore;
24
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/messaging/store.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,SAAS,EACV,MAAM,YAAY,CAAC;AAiBpB;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,WAAW,GAAG,SAAS,EAC7B,QAAQ,EAAE,iBAAiB,EAC3B,KAAK,EAAE,cAAc,GACpB,WAAW,CAqDb;AAED,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,UAAU,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC9C,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,iBAAiB,GAAG,IAAI,CAAC;IACpD,4EAA4E;IAC5E,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,WAAW,CAAC;IAChD,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,cAAc,EAAE,CAAC;IAC5C,YAAY,CAAC,EAAE,EAAE,SAAS,GAAG,WAAW,GAAG,IAAI,CAAC;IAChD,SAAS,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,WAAW,EAAE,CAAC;IAC9C,WAAW,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;CAC1C;AAED,wBAAgB,0BAA0B,IAAI,YAAY,CA4CzD"}
@@ -0,0 +1,120 @@
1
+ // Single-perspective message store: one agent's copy of envelopes + lifecycle
2
+ // events + the deterministic inbox projection over them (spec 309 §5, §7).
3
+ //
4
+ // The projection is a pure reducer — replaying the same events always yields
5
+ // the same InboxItemV1. Rules / categories / delta cursors land in W2.
6
+ import { validateMessageEnvelope } from './envelope.js';
7
+ import { canonicalizeMessage } from './hash.js';
8
+ /** Where a message lands when first admitted, by perspective + kind. */
9
+ function initialFolder(envelope, event) {
10
+ switch (event.eventType) {
11
+ case 'drafted':
12
+ return 'drafts';
13
+ case 'sent':
14
+ return 'sent';
15
+ default:
16
+ // Typed requests queue for review instead of burying in mail (spec 309 §6).
17
+ return envelope.kind === 'request' ? 'pending' : 'inbox';
18
+ }
19
+ }
20
+ /**
21
+ * Pure projection step. Given the previous inbox row (or undefined for the
22
+ * first event) and the next lifecycle event, produce the new row.
23
+ * Throws on a messageId mismatch — events never apply across messages.
24
+ */
25
+ export function applyMessageEvent(prev, envelope, event) {
26
+ if (event.messageId !== envelope.id) {
27
+ throw new Error(`event ${event.messageId} does not belong to message ${envelope.id}`);
28
+ }
29
+ const base = prev ?? {
30
+ messageId: envelope.id,
31
+ conversationId: envelope.conversationId,
32
+ folder: initialFolder(envelope, event),
33
+ labels: [...(envelope.labels ?? [])],
34
+ categories: [],
35
+ contextRefs: [...(envelope.contextRefs ?? [])],
36
+ unread: event.eventType === 'admitted' || event.eventType === 'delivered',
37
+ priority: envelope.priority ?? 'normal',
38
+ lastEventAt: event.at,
39
+ interactionId: envelope.interactionId,
40
+ };
41
+ const next = { ...base, lastEventAt: event.at };
42
+ switch (event.eventType) {
43
+ case 'admitted':
44
+ case 'delivered':
45
+ next.folder = prev ? prev.folder : initialFolder(envelope, event);
46
+ next.unread = true;
47
+ break;
48
+ case 'read':
49
+ next.unread = false;
50
+ break;
51
+ case 'archived':
52
+ next.folder = 'archive';
53
+ break;
54
+ case 'deleted':
55
+ case 'tombstoned':
56
+ next.folder = 'trash';
57
+ next.bodyPreview = undefined;
58
+ break;
59
+ case 'restored':
60
+ next.folder = envelope.kind === 'request' ? 'pending' : 'inbox';
61
+ break;
62
+ case 'drafted':
63
+ next.folder = 'drafts';
64
+ next.unread = false;
65
+ break;
66
+ case 'sent':
67
+ next.folder = 'sent';
68
+ next.unread = false;
69
+ break;
70
+ case 'seen':
71
+ case 'failed':
72
+ // Notification shown / delivery failed — no folder or unread change.
73
+ break;
74
+ }
75
+ return next;
76
+ }
77
+ export function createInMemoryMessageStore() {
78
+ const envelopes = new Map();
79
+ const events = new Map();
80
+ const items = new Map();
81
+ return {
82
+ putMessage(envelope) {
83
+ const errors = validateMessageEnvelope(envelope);
84
+ if (errors.length > 0) {
85
+ throw new Error(`invalid message envelope ${envelope.id}: ${errors.join(', ')}`);
86
+ }
87
+ const existing = envelopes.get(envelope.id);
88
+ if (existing && canonicalizeMessage(existing) !== canonicalizeMessage(envelope)) {
89
+ throw new Error(`duplicate message id ${envelope.id} with different content`);
90
+ }
91
+ envelopes.set(envelope.id, envelope);
92
+ },
93
+ getMessage(id) {
94
+ return envelopes.get(id) ?? null;
95
+ },
96
+ appendEvent(event) {
97
+ const envelope = envelopes.get(event.messageId);
98
+ if (!envelope)
99
+ throw new Error(`unknown message ${event.messageId}`);
100
+ const next = applyMessageEvent(items.get(event.messageId), envelope, event);
101
+ events.set(event.messageId, [...(events.get(event.messageId) ?? []), event]);
102
+ items.set(event.messageId, next);
103
+ return next;
104
+ },
105
+ listEvents(id) {
106
+ return [...(events.get(id) ?? [])];
107
+ },
108
+ getInboxItem(id) {
109
+ return items.get(id) ?? null;
110
+ },
111
+ listInbox(folder) {
112
+ const all = [...items.values()].filter((i) => (folder ? i.folder === folder : true));
113
+ return all.sort((a, b) => b.lastEventAt.localeCompare(a.lastEventAt));
114
+ },
115
+ unreadCount(folder) {
116
+ return [...items.values()].filter((i) => i.unread && (folder ? i.folder === folder : true)).length;
117
+ },
118
+ };
119
+ }
120
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/messaging/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,166 @@
1
+ import type { CanonicalAgentId, Hex32, SignatureProof } from '@agenticprimitives/types';
2
+ import type { VaultRef, VaultClassification } from '@agenticprimitives/vault';
3
+ export type { Hex32, SignatureProof };
4
+ export type MessageId = `msg_${string}`;
5
+ export type ConversationId = `conv_${string}`;
6
+ export type ThreadId = `thr_${string}`;
7
+ export type FolderKind = 'inbox' | 'sent' | 'drafts' | 'archive' | 'trash' | 'pending' | 'custom';
8
+ export type MessagePriority = 'low' | 'normal' | 'high' | 'urgent';
9
+ export type MessageKind = 'plain' | 'request' | 'response' | 'credential-delivery' | 'receipt' | 'system' | 'tombstone';
10
+ /**
11
+ * Typed "about-ness" pointer (spec 312 §4.1): binds a message/conversation to
12
+ * an entity — an org agent, a community, a segment, a content hash, an
13
+ * attestation. Display + routing metadata only, NEVER authority. Kinds are
14
+ * app-defined (ADR-0021 — vertical vocabularies live in app kind registries).
15
+ */
16
+ export interface ContextRefV1 {
17
+ /** App-defined kind, e.g. 'org-agent' | 'community' | 'segment' | 'content-hash'. */
18
+ kind: string;
19
+ /** Stable id: CAIP-10, URI, attestation UID, content hash, app id. */
20
+ id: string;
21
+ /** Optional content/credential binding (doc hash, attestation digest…). */
22
+ hash?: Hex32;
23
+ /** Display-only label; not authoritative, not verified. */
24
+ label?: string;
25
+ }
26
+ export interface MessageAttachmentRef {
27
+ ref: VaultRef;
28
+ hash: Hex32;
29
+ contentType: string;
30
+ filename?: string;
31
+ bytes?: number;
32
+ }
33
+ /** Declares deletion/tombstone intent. NOT adversary-proof deletion (spec 309 §8.9). */
34
+ export interface RetentionPolicyRef {
35
+ policyId: string;
36
+ deleteAfter?: string;
37
+ tombstoneOnDelete: boolean;
38
+ }
39
+ /**
40
+ * The canonical message envelope. `body`/`attachments` reference vault bytes;
41
+ * `bodyHash` MUST match those bytes (enforced at delivery, spec 309 §8.4).
42
+ */
43
+ export interface MessageEnvelopeV1 {
44
+ version: 'ap.message.v1';
45
+ id: MessageId;
46
+ conversationId: ConversationId;
47
+ threadId?: ThreadId;
48
+ inReplyTo?: MessageId;
49
+ kind: MessageKind;
50
+ from: CanonicalAgentId;
51
+ to: CanonicalAgentId[];
52
+ cc?: CanonicalAgentId[];
53
+ /** BCC / hidden recipients ⇒ per-recipient envelopes; never in shared state (spec 309 §8.6). */
54
+ recipientPartition?: string;
55
+ subject?: string;
56
+ createdAt: string;
57
+ expiresAt?: string;
58
+ classification: VaultClassification;
59
+ body: VaultRef;
60
+ bodyHash: Hex32;
61
+ bodyContentType: string;
62
+ attachments?: MessageAttachmentRef[];
63
+ /** String ref into an `interactions` case (no import back-edge). */
64
+ interactionId?: string;
65
+ /** Entities this message is ABOUT (spec 312) — covered by the envelope hash,
66
+ * so refs are signed with the message. Bounded (≤ 8, enforced). */
67
+ contextRefs?: ContextRefV1[];
68
+ retention?: RetentionPolicyRef;
69
+ labels?: string[];
70
+ priority?: MessagePriority;
71
+ signature?: SignatureProof;
72
+ }
73
+ export type MessageEventType = 'drafted' | 'sent' | 'admitted' | 'delivered' | 'seen' | 'read' | 'archived' | 'deleted' | 'restored' | 'tombstoned' | 'failed';
74
+ export interface MessageEventV1 {
75
+ version: 'ap.message.event.v1';
76
+ messageId: MessageId;
77
+ actor: CanonicalAgentId;
78
+ eventType: MessageEventType;
79
+ at: string;
80
+ reason?: string;
81
+ evidenceRef?: VaultRef;
82
+ signature?: SignatureProof;
83
+ }
84
+ /** The materialized per-message inbox row (a projection over events). */
85
+ export interface InboxItemV1 {
86
+ messageId: MessageId;
87
+ conversationId: ConversationId;
88
+ folder: FolderKind;
89
+ labels: string[];
90
+ categories: string[];
91
+ /** Projected copy of the envelope's context refs (spec 312) — lets rules and
92
+ * views filter by context without re-reading envelopes. */
93
+ contextRefs: ContextRefV1[];
94
+ unread: boolean;
95
+ priority: MessagePriority;
96
+ lastEventAt: string;
97
+ bodyPreview?: string;
98
+ interactionId?: string;
99
+ }
100
+ /**
101
+ * Conversation metadata (spec 312 §4.2 — the `ConversationRef` promised in
102
+ * spec 309 §5). A projection-layer descriptor over an opaque ConversationId:
103
+ * a Slack-channel-shaped view (title, participants, context anchors). Each
104
+ * side keeps its OWN copy; a descriptor never authorizes delivery — admission
105
+ * still validates every envelope independently.
106
+ */
107
+ /** Conversation shape (spec 324 §10) — a projection profile, never authority. A `forum`-profile conversation
108
+ * is the org's discussion space that hosts `DiscussionTopicV1` partitions (the Telegram-forum shape). */
109
+ export type ConversationProfile = 'direct' | 'group' | 'discussion' | 'broadcast' | 'forum' | 'announcement' | 'support';
110
+ export interface ConversationDescriptorV1 {
111
+ version: 'ap.conversation.v1';
112
+ id: ConversationId;
113
+ /** The agent whose store owns this descriptor copy. */
114
+ owner: CanonicalAgentId;
115
+ title?: string;
116
+ participants: CanonicalAgentId[];
117
+ /** Entities this conversation is anchored to. */
118
+ contextRefs?: ContextRefV1[];
119
+ /** Who may append: fixed participant set, owner-curated, or open to anyone
120
+ * in the anchored context (org shared inbox). Projection policy only. */
121
+ participantPolicy: 'fixed' | 'owner-managed' | 'open-to-context';
122
+ createdAt: string;
123
+ archived?: boolean;
124
+ /** The OrganizationAgent that hosts this conversation, if it is an org's discussion space. */
125
+ hostOrganization?: CanonicalAgentId;
126
+ /** The conversation shape. A `forum` hosts DiscussionTopics; `direct`/`group` are DM/small-group. */
127
+ profile?: ConversationProfile;
128
+ subject?: string;
129
+ description?: string;
130
+ /** Access posture of the conversation (topics inherit it; §10). */
131
+ confidentialityMode?: 'open' | 'members-only' | 'confidential';
132
+ /** Ref to the enrollment policy governing who may participate (resolved externally; never inline authority). */
133
+ enrollmentPolicyRef?: string;
134
+ }
135
+ /**
136
+ * A DiscussionTopic (spec 324 §10) — a named partition of an org's discussion space (the Telegram-forum
137
+ * shape). What today's "channels" (`#general`, "fundraising") ACTUALLY are: DiscussionTopics inside the org's
138
+ * default `forum`-profile Conversation, NOT sibling Conversations. No `Channel`/`Space` class is added. Topics
139
+ * inherit Conversation access; a restricted topic uses a `discussion`-scoped RoleAssignment/delegation.
140
+ */
141
+ export interface DiscussionTopicV1 {
142
+ version: 'ap.discussion-topic.v1';
143
+ discussionId: string;
144
+ conversationId: ConversationId;
145
+ title: string;
146
+ description?: string;
147
+ iconRef?: VaultRef;
148
+ createdByAgent: CanonicalAgentId;
149
+ createdAt: string;
150
+ status: 'open' | 'closed' | 'archived';
151
+ pinned?: boolean;
152
+ hidden?: boolean;
153
+ }
154
+ /** A MessageThread (spec 324 §10) — a reply chain rooted at one exchange within a DiscussionTopic. */
155
+ export interface MessageThreadV1 {
156
+ version: 'ap.message-thread.v1';
157
+ discussionId: string;
158
+ conversationId: ConversationId;
159
+ /** The exchange that roots the thread (an `xch_` id; typed as string to avoid a messaging→record cycle). */
160
+ rootExchangeId: string;
161
+ rootMessageId?: MessageId;
162
+ title?: string;
163
+ createdAt: string;
164
+ status: 'open' | 'closed' | 'archived';
165
+ }
166
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/messaging/types.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACxF,OAAO,KAAK,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG9E,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC;AAEtC,MAAM,MAAM,SAAS,GAAG,OAAO,MAAM,EAAE,CAAC;AACxC,MAAM,MAAM,cAAc,GAAG,QAAQ,MAAM,EAAE,CAAC;AAC9C,MAAM,MAAM,QAAQ,GAAG,OAAO,MAAM,EAAE,CAAC;AAEvC,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;AAElG,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEnE,MAAM,MAAM,WAAW,GACnB,OAAO,GACP,SAAS,GACT,UAAU,GACV,qBAAqB,GACrB,SAAS,GACT,QAAQ,GACR,WAAW,CAAC;AAEhB;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,qFAAqF;IACrF,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,EAAE,EAAE,MAAM,CAAC;IACX,2EAA2E;IAC3E,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,QAAQ,CAAC;IACd,IAAI,EAAE,KAAK,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wFAAwF;AACxF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,eAAe,CAAC;IACzB,EAAE,EAAE,SAAS,CAAC;IACd,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,gBAAgB,CAAC;IACvB,EAAE,EAAE,gBAAgB,EAAE,CAAC;IACvB,EAAE,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACxB,gGAAgG;IAChG,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,mBAAmB,CAAC;IACpC,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,KAAK,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACrC,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;wEACoE;IACpE,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC;IAC7B,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AAED,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,MAAM,GACN,UAAU,GACV,WAAW,GACX,MAAM,GACN,MAAM,GACN,UAAU,GACV,SAAS,GACT,UAAU,GACV,YAAY,GACZ,QAAQ,CAAC;AAEb,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,qBAAqB,CAAC;IAC/B,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,gBAAgB,CAAC;IACxB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AAED,yEAAyE;AACzE,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,SAAS,CAAC;IACrB,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB;gEAC4D;IAC5D,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,eAAe,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH;0GAC0G;AAC1G,MAAM,MAAM,mBAAmB,GAC3B,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,WAAW,GAAG,OAAO,GAAG,cAAc,GAAG,SAAS,CAAC;AAE3F,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,oBAAoB,CAAC;IAC9B,EAAE,EAAE,cAAc,CAAC;IACnB,uDAAuD;IACvD,KAAK,EAAE,gBAAgB,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,iDAAiD;IACjD,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC;IAC7B;8EAC0E;IAC1E,iBAAiB,EAAE,OAAO,GAAG,eAAe,GAAG,iBAAiB,CAAC;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,8FAA8F;IAC9F,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,qGAAqG;IACrG,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,mBAAmB,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,cAAc,CAAC;IAC/D,gHAAgH;IAChH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,wBAAwB,CAAC;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,cAAc,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,cAAc,EAAE,gBAAgB,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;IACvC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,sGAAsG;AACtG,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,sBAAsB,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,cAAc,CAAC;IAC/B,4GAA4G;IAC5G,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;CACxC"}
@@ -0,0 +1,7 @@
1
+ // @agenticprimitives/messaging — wire + projection types (spec 309 §5).
2
+ //
3
+ // A message CARRIES a request / evidence / credential reference; a message is
4
+ // NEVER authority (spec 309 §4.2). Bodies live in the vault — the envelope and
5
+ // inbox state carry hashes + refs only (spec 309 §4.3).
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/messaging/types.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,wDAAwD"}
@@ -0,0 +1,37 @@
1
+ import type { Vault, VaultClassification, VaultRef } from '@agenticprimitives/vault';
2
+ import type { MessageEnvelopeV1, MessageId, Hex32 } from './types.js';
3
+ export declare const MESSAGE_BODY_RECORD_TYPE = "message.body";
4
+ export declare const MESSAGE_ATTACHMENT_RECORD_TYPE = "message.attachment";
5
+ /** 1-1 (DM) body resource — spec 322 W3 namespacing: `message.body:dm:<id>`. Changing THIS
6
+ * function cuts every 1-1 write AND read over together (they both derive from it); pre-cutover
7
+ * bodies at `message.body:<id>` are orphaned by design (no-migration doctrine). Channel bodies use
8
+ * {@link topicBodyResource} — a DIFFERENT scope family, so the delivery grant and the
9
+ * interactions grant can never reach each other's bodies (closes FAB-SSO-2). */
10
+ export declare function messageBodyResource(id: MessageId): string;
11
+ /** Topic-post body resource (spec 324 §10; renamed from channel bodies in the W6 key migration) —
12
+ * `message.body:topic:<conversationId>:<messageId>`. */
13
+ export declare function topicBodyResource(conversationId: string, id: MessageId): string;
14
+ export declare function messageAttachmentResource(id: MessageId, index: number): string;
15
+ export interface PutBodyResult {
16
+ ref: VaultRef;
17
+ bodyHash: Hex32;
18
+ }
19
+ /** One side's (sender or recipient) vault residency for message bodies. */
20
+ export interface MessageBodyStore {
21
+ /** Store body bytes for a message; returns the ref + hash the envelope binds. */
22
+ putBody(args: {
23
+ messageId: MessageId;
24
+ bytes: Uint8Array;
25
+ contentType: string;
26
+ classification: VaultClassification;
27
+ /** Override the storage resource (channel bodies — {@link topicBodyResource}); defaults to the DM namespace. */
28
+ resource?: string;
29
+ }): Promise<PutBodyResult>;
30
+ /**
31
+ * Load the body an envelope references and verify it against `bodyHash`.
32
+ * Fail-closed: missing record or hash mismatch throws — never partial bytes.
33
+ */
34
+ loadBody(envelope: MessageEnvelopeV1): Promise<Uint8Array>;
35
+ }
36
+ export declare function createVaultMessageBodyStore(vault: Vault, owner: string): MessageBodyStore;
37
+ //# sourceMappingURL=vault-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-store.d.ts","sourceRoot":"","sources":["../../src/messaging/vault-store.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACrF,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGtE,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AACvD,eAAO,MAAM,8BAA8B,uBAAuB,CAAC;AAEnE;;;;iFAIiF;AACjF,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,CAEzD;AAED;yDACyD;AACzD,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,GAAG,MAAM,CAE/E;AAED,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9E;AAqBD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,QAAQ,CAAC;IACd,QAAQ,EAAE,KAAK,CAAC;CACjB;AAED,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,iFAAiF;IACjF,OAAO,CAAC,IAAI,EAAE;QACZ,SAAS,EAAE,SAAS,CAAC;QACrB,KAAK,EAAE,UAAU,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,EAAE,mBAAmB,CAAC;QACpC,gHAAgH;QAChH,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC5D;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAwBzF"}
@@ -0,0 +1,62 @@
1
+ // Vault body residency (spec 309 §9). Message bodies and attachments are
2
+ // vault records — envelopes and projections carry `VaultRef` + hash only.
3
+ // Reads are fail-closed: bytes that do not match the envelope's `bodyHash`
4
+ // never reach the caller (ADR-0013 — a mismatch is an error, not a fallback).
5
+ import { sha256Hex32 } from './hash.js';
6
+ export const MESSAGE_BODY_RECORD_TYPE = 'message.body';
7
+ export const MESSAGE_ATTACHMENT_RECORD_TYPE = 'message.attachment';
8
+ /** 1-1 (DM) body resource — spec 322 W3 namespacing: `message.body:dm:<id>`. Changing THIS
9
+ * function cuts every 1-1 write AND read over together (they both derive from it); pre-cutover
10
+ * bodies at `message.body:<id>` are orphaned by design (no-migration doctrine). Channel bodies use
11
+ * {@link topicBodyResource} — a DIFFERENT scope family, so the delivery grant and the
12
+ * interactions grant can never reach each other's bodies (closes FAB-SSO-2). */
13
+ export function messageBodyResource(id) {
14
+ return `${MESSAGE_BODY_RECORD_TYPE}:dm:${id}`;
15
+ }
16
+ /** Topic-post body resource (spec 324 §10; renamed from channel bodies in the W6 key migration) —
17
+ * `message.body:topic:<conversationId>:<messageId>`. */
18
+ export function topicBodyResource(conversationId, id) {
19
+ return `${MESSAGE_BODY_RECORD_TYPE}:topic:${conversationId}:${id}`;
20
+ }
21
+ export function messageAttachmentResource(id, index) {
22
+ return `${MESSAGE_ATTACHMENT_RECORD_TYPE}:${id}:${index}`;
23
+ }
24
+ function toBase64(bytes) {
25
+ let bin = '';
26
+ for (const b of bytes)
27
+ bin += String.fromCharCode(b);
28
+ return btoa(bin);
29
+ }
30
+ function fromBase64(b64) {
31
+ const bin = atob(b64);
32
+ const out = new Uint8Array(bin.length);
33
+ for (let i = 0; i < bin.length; i += 1)
34
+ out[i] = bin.charCodeAt(i);
35
+ return out;
36
+ }
37
+ export function createVaultMessageBodyStore(vault, owner) {
38
+ return {
39
+ async putBody({ messageId, bytes, contentType, classification, resource: resourceOverride }) {
40
+ const bodyHash = await sha256Hex32(bytes);
41
+ const resource = resourceOverride ?? messageBodyResource(messageId);
42
+ const stored = { b64: toBase64(bytes), contentType, bodyHash };
43
+ await vault.write({ owner, resource, data: stored, classification });
44
+ return {
45
+ ref: { resource, classification, updatedAt: new Date().toISOString() },
46
+ bodyHash,
47
+ };
48
+ },
49
+ async loadBody(envelope) {
50
+ const obj = await vault.read({ owner, resource: envelope.body.resource });
51
+ if (obj === null) {
52
+ throw new Error(`message body ${envelope.body.resource} not found in vault`);
53
+ }
54
+ const bytes = fromBase64(obj.data.b64);
55
+ if ((await sha256Hex32(bytes)) !== envelope.bodyHash) {
56
+ throw new Error(`message body ${envelope.id} does not match envelope bodyHash`);
57
+ }
58
+ return bytes;
59
+ },
60
+ };
61
+ }
62
+ //# sourceMappingURL=vault-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-store.js","sourceRoot":"","sources":["../../src/messaging/vault-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export interface RecordCatalogEntry {
2
+ /** Vault resource pattern — exact name or `<prefix>:*` family (matches the canonical
3
+ * VAULT_RECORD_SCOPE prefix-wildcard semantics in the delegation package). */
4
+ pattern: string;
5
+ /** Wire discriminator of the payload (`version:` tag), or null for raw/opaque payloads. */
6
+ typeTag: string | null;
7
+ /** Ontology semantic name (T-box class IRI), or null where no artifact class exists. */
8
+ classIri: string | null;
9
+ /** Declared SHACL shape (C-box IRI) — ENFORCED by this package's TS validators. */
10
+ shapeIri: string | null;
11
+ /** Minimum classification of the record's content. */
12
+ classificationFloor: 'internal' | 'confidential';
13
+ owner: 'person' | 'org' | 'both';
14
+ }
15
+ /** Interaction-substrate records (spec 322 §1). W3 renames/splits (board.*, message.body
16
+ * namespacing, org.profile) are listed as TARGET names; pre-W3 legacy names are marked. There is
17
+ * NO data migration — existing interaction data is disposable (product decision 2026-07-10); new
18
+ * records start clean at each wave. */
19
+ export declare const RECORD_CATALOG: readonly RecordCatalogEntry[];
20
+ /** Look up the catalog entry governing a concrete resource name (exact, then prefix family). */
21
+ export declare function catalogEntryFor(resource: string): RecordCatalogEntry | undefined;
22
+ //# sourceMappingURL=record-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record-catalog.d.ts","sourceRoot":"","sources":["../src/record-catalog.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,kBAAkB;IACjC;mFAC+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,wFAAwF;IACxF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,mFAAmF;IACnF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,sDAAsD;IACtD,mBAAmB,EAAE,UAAU,GAAG,cAAc,CAAC;IACjD,KAAK,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;CAClC;AAED;;;wCAGwC;AACxC,eAAO,MAAM,cAAc,EAAE,SAAS,kBAAkB,EAkB9C,CAAC;AAEX,gGAAgG;AAChG,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAIhF"}
@@ -0,0 +1,35 @@
1
+ // The REGISTERED RECORD CATALOG (spec 322 §1) — the one table binding vault resource patterns to
2
+ // their wire type tag, ontology class/shape IRIs, and classification floor. The CATALOG — never the
3
+ // resource string — is the ontology binding: resource strings stay compact opaque locators
4
+ // (packages/vault stays dependency-free), payload tags version (`ap.*.v1`), record names never do.
5
+ // Grammar: `<domain>.<record>` for singleton docs; `<domain>.<record>:<instance>` for keyed
6
+ // families — dot separates name segments; colon appears exactly once, before an instance id.
7
+ import { CLASS, SHAPE } from '@agenticprimitives/ontology';
8
+ /** Interaction-substrate records (spec 322 §1). W3 renames/splits (board.*, message.body
9
+ * namespacing, org.profile) are listed as TARGET names; pre-W3 legacy names are marked. There is
10
+ * NO data migration — existing interaction data is disposable (product decision 2026-07-10); new
11
+ * records start clean at each wave. */
12
+ export const RECORD_CATALOG = [
13
+ // 1-1 messaging (person AND org inboxes — same doc shape)
14
+ { pattern: 'inbox.data', typeTag: null, classIri: null, shapeIri: null, classificationFloor: 'internal', owner: 'both' },
15
+ { pattern: 'message.body:*', typeTag: null, classIri: null, shapeIri: null, classificationFloor: 'confidential', owner: 'both' },
16
+ // Channel board (org) — pre-W3 legacy single doc, then the split
17
+ { pattern: 'channels.data', typeTag: null, classIri: CLASS.ChannelBoard, shapeIri: SHAPE.ChannelBoard, classificationFloor: 'internal', owner: 'org' },
18
+ { pattern: 'conversation.index', typeTag: null, classIri: CLASS.ChannelBoard, shapeIri: SHAPE.ChannelBoard, classificationFloor: 'internal', owner: 'org' },
19
+ { pattern: 'conversation.topic:*', typeTag: 'ap.conversation.v1', classIri: CLASS.Conversation, shapeIri: SHAPE.Conversation, classificationFloor: 'internal', owner: 'org' },
20
+ // Membership directory (org)
21
+ { pattern: 'directory.data', typeTag: 'ap.home.directory-listing.v1', classIri: CLASS.DirectoryListing, shapeIri: SHAPE.DirectoryListing, classificationFloor: 'internal', owner: 'org' },
22
+ // Person-side authoritative state (spec 322 §1)
23
+ { pattern: 'relationships.data', typeTag: null, classIri: null, shapeIri: null, classificationFloor: 'confidential', owner: 'person' },
24
+ { pattern: 'member.profile:*', typeTag: null, classIri: null, shapeIri: null, classificationFloor: 'internal', owner: 'person' },
25
+ // Capability ledgers (issuance METADATA only — never signed wires; spec 322 §2)
26
+ { pattern: 'grants.delivery', typeTag: null, classIri: null, shapeIri: null, classificationFloor: 'confidential', owner: 'both' },
27
+ // Org admin (reachable from NO messaging scope)
28
+ { pattern: 'org.profile', typeTag: null, classIri: null, shapeIri: null, classificationFloor: 'internal', owner: 'org' },
29
+ { pattern: 'org.invite:*', typeTag: null, classIri: null, shapeIri: null, classificationFloor: 'confidential', owner: 'org' },
30
+ ];
31
+ /** Look up the catalog entry governing a concrete resource name (exact, then prefix family). */
32
+ export function catalogEntryFor(resource) {
33
+ return RECORD_CATALOG.find((e) => e.pattern === resource || (e.pattern.endsWith('*') && resource.startsWith(e.pattern.slice(0, -1))));
34
+ }
35
+ //# sourceMappingURL=record-catalog.js.map