@econ-v1/domain 6.7.0 → 6.10.0

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 (286) hide show
  1. package/dist/errors/index.d.ts +96 -25
  2. package/dist/errors/index.d.ts.map +1 -1
  3. package/dist/events/index.d.ts +127 -20
  4. package/dist/events/index.d.ts.map +1 -1
  5. package/dist/index.d.ts +250 -47
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/models/agent.d.ts +25 -4
  8. package/dist/models/agent.d.ts.map +1 -1
  9. package/dist/models/app-data.d.ts +84 -0
  10. package/dist/models/app-data.d.ts.map +1 -0
  11. package/dist/models/conversation.d.ts +12 -2
  12. package/dist/models/conversation.d.ts.map +1 -1
  13. package/dist/models/delegation.d.ts +12 -3
  14. package/dist/models/delegation.d.ts.map +1 -1
  15. package/dist/models/device-boot-state.d.ts +12 -0
  16. package/dist/models/device-boot-state.d.ts.map +1 -0
  17. package/dist/models/device-identity.d.ts +11 -3
  18. package/dist/models/device-identity.d.ts.map +1 -1
  19. package/dist/models/graph.d.ts +26 -3
  20. package/dist/models/graph.d.ts.map +1 -1
  21. package/dist/models/index.d.ts +82 -14
  22. package/dist/models/index.d.ts.map +1 -1
  23. package/dist/models/json.d.ts +5 -5
  24. package/dist/models/json.d.ts.map +1 -1
  25. package/dist/models/l402.d.ts +4 -5
  26. package/dist/models/l402.d.ts.map +1 -1
  27. package/dist/models/live-query-definition.d.ts +15 -16
  28. package/dist/models/live-query-definition.d.ts.map +1 -1
  29. package/dist/models/node-app-memory.d.ts +107 -0
  30. package/dist/models/node-app-memory.d.ts.map +1 -0
  31. package/dist/models/outbox-intent.d.ts +3 -3
  32. package/dist/models/outbox-intent.d.ts.map +1 -1
  33. package/dist/models/outbox.d.ts +67 -15
  34. package/dist/models/outbox.d.ts.map +1 -1
  35. package/dist/models/owner-views.d.ts +28 -28
  36. package/dist/models/owner-views.d.ts.map +1 -1
  37. package/dist/models/payment.d.ts +28 -9
  38. package/dist/models/payment.d.ts.map +1 -1
  39. package/dist/models/query-diff.d.ts +2 -2
  40. package/dist/models/query-diff.d.ts.map +1 -1
  41. package/dist/models/release-manifest.d.ts +32 -47
  42. package/dist/models/release-manifest.d.ts.map +1 -1
  43. package/dist/models/repository-write.d.ts +3 -3
  44. package/dist/models/repository-write.d.ts.map +1 -1
  45. package/dist/models/revisioned-commands.d.ts +66 -13
  46. package/dist/models/revisioned-commands.d.ts.map +1 -1
  47. package/dist/models/revisioned.d.ts +50 -10
  48. package/dist/models/revisioned.d.ts.map +1 -1
  49. package/dist/models/settings.d.ts +2 -2
  50. package/dist/models/settings.d.ts.map +1 -1
  51. package/dist/models/sync.d.ts +18 -18
  52. package/dist/models/sync.d.ts.map +1 -1
  53. package/dist/models/wallet.d.ts +16 -16
  54. package/dist/models/wallet.d.ts.map +1 -1
  55. package/dist/queries/certificate-trust.d.ts +13 -0
  56. package/dist/queries/certificate-trust.d.ts.map +1 -0
  57. package/dist/queries/conversations.d.ts +38 -7
  58. package/dist/queries/conversations.d.ts.map +1 -1
  59. package/dist/queries/discovery.d.ts +10 -10
  60. package/dist/queries/discovery.d.ts.map +1 -1
  61. package/dist/queries/notifications.d.ts +24 -4
  62. package/dist/queries/notifications.d.ts.map +1 -1
  63. package/dist/queries/onboarding-flow.d.ts +25 -0
  64. package/dist/queries/onboarding-flow.d.ts.map +1 -0
  65. package/dist/queries/onboarding-lcd-screen.d.ts +56 -0
  66. package/dist/queries/onboarding-lcd-screen.d.ts.map +1 -0
  67. package/dist/queries/onboarding-status.d.ts +10 -10
  68. package/dist/queries/onboarding-status.d.ts.map +1 -1
  69. package/dist/queries/revisioned.d.ts +47 -13
  70. package/dist/queries/revisioned.d.ts.map +1 -1
  71. package/dist/queries/wallet.d.ts +40 -10
  72. package/dist/queries/wallet.d.ts.map +1 -1
  73. package/dist/services/abort-signal.d.ts +54 -0
  74. package/dist/services/abort-signal.d.ts.map +1 -0
  75. package/dist/services/certificate-trust-service.d.ts +42 -0
  76. package/dist/services/certificate-trust-service.d.ts.map +1 -0
  77. package/dist/services/conversation-service.d.ts +103 -15
  78. package/dist/services/conversation-service.d.ts.map +1 -1
  79. package/dist/services/conversation-sync.d.ts +9 -5
  80. package/dist/services/conversation-sync.d.ts.map +1 -1
  81. package/dist/services/device-boot-state-service.d.ts +17 -0
  82. package/dist/services/device-boot-state-service.d.ts.map +1 -0
  83. package/dist/services/device-cleanup-service.d.ts +47 -0
  84. package/dist/services/device-cleanup-service.d.ts.map +1 -0
  85. package/dist/services/discovery-probe-service.d.ts +37 -46
  86. package/dist/services/discovery-probe-service.d.ts.map +1 -1
  87. package/dist/services/gossip-service.d.ts +28 -13
  88. package/dist/services/gossip-service.d.ts.map +1 -1
  89. package/dist/services/invite-redemption-service.d.ts +43 -0
  90. package/dist/services/invite-redemption-service.d.ts.map +1 -0
  91. package/dist/services/lan-candidate-refresh-service.d.ts +22 -7
  92. package/dist/services/lan-candidate-refresh-service.d.ts.map +1 -1
  93. package/dist/services/lcd-decision-service.d.ts +58 -0
  94. package/dist/services/lcd-decision-service.d.ts.map +1 -0
  95. package/dist/services/onboarding-checkpoint-store.d.ts +54 -0
  96. package/dist/services/onboarding-checkpoint-store.d.ts.map +1 -0
  97. package/dist/services/onboarding-flow-service.d.ts +180 -0
  98. package/dist/services/onboarding-flow-service.d.ts.map +1 -0
  99. package/dist/services/onboarding-status-service.d.ts +21 -38
  100. package/dist/services/onboarding-status-service.d.ts.map +1 -1
  101. package/dist/services/outbox-service.d.ts +105 -29
  102. package/dist/services/outbox-service.d.ts.map +1 -1
  103. package/dist/services/owner-claim-service.d.ts +187 -0
  104. package/dist/services/owner-claim-service.d.ts.map +1 -0
  105. package/dist/services/owner-view-refresh-service.d.ts +40 -0
  106. package/dist/services/owner-view-refresh-service.d.ts.map +1 -0
  107. package/dist/services/owner-view-service.d.ts +49 -4
  108. package/dist/services/owner-view-service.d.ts.map +1 -1
  109. package/dist/services/peer-directory-service.d.ts +53 -17
  110. package/dist/services/peer-directory-service.d.ts.map +1 -1
  111. package/dist/services/release-manifest-verifier.d.ts +18 -20
  112. package/dist/services/release-manifest-verifier.d.ts.map +1 -1
  113. package/dist/services/revisioned-domain-service.d.ts +50 -17
  114. package/dist/services/revisioned-domain-service.d.ts.map +1 -1
  115. package/dist/services/runtime-globals.d.ts +39 -0
  116. package/dist/services/runtime-globals.d.ts.map +1 -0
  117. package/dist/services/session-service.d.ts +23 -3
  118. package/dist/services/session-service.d.ts.map +1 -1
  119. package/dist/services/sync/authoritative-mirror.d.ts +88 -15
  120. package/dist/services/sync/authoritative-mirror.d.ts.map +1 -1
  121. package/dist/services/sync/index.d.ts +17 -5
  122. package/dist/services/sync/index.d.ts.map +1 -1
  123. package/dist/services/sync/log-sync.d.ts +42 -8
  124. package/dist/services/sync/log-sync.d.ts.map +1 -1
  125. package/dist/services/sync/revision-merge.d.ts +80 -13
  126. package/dist/services/sync/revision-merge.d.ts.map +1 -1
  127. package/dist/services/sync/strategy.d.ts +11 -1
  128. package/dist/services/sync/strategy.d.ts.map +1 -1
  129. package/dist/services/transport-manager.d.ts +84 -29
  130. package/dist/services/transport-manager.d.ts.map +1 -1
  131. package/dist/services/wallet-mirror-service.d.ts +81 -18
  132. package/dist/services/wallet-mirror-service.d.ts.map +1 -1
  133. package/dist/services/wifi-provisioning-service.d.ts +146 -0
  134. package/dist/services/wifi-provisioning-service.d.ts.map +1 -0
  135. package/package.json +18 -12
  136. package/src/errors/index.js +126 -0
  137. package/src/events/index.js +124 -0
  138. package/src/index.js +566 -0
  139. package/src/models/agent.js +43 -0
  140. package/src/models/app-data.js +122 -0
  141. package/src/models/conversation.js +36 -0
  142. package/{dist → src}/models/delegation.js +18 -1
  143. package/src/models/device-boot-state.js +3 -0
  144. package/{dist → src}/models/device-identity.js +18 -2
  145. package/{dist → src}/models/graph.js +30 -3
  146. package/src/models/index.js +175 -0
  147. package/src/models/json.js +18 -0
  148. package/src/models/l402.js +9 -0
  149. package/src/models/live-query-definition.js +30 -0
  150. package/src/models/node-app-memory.js +130 -0
  151. package/src/models/outbox-intent.js +12 -0
  152. package/{dist → src}/models/outbox.js +102 -3
  153. package/src/models/owner-views.js +59 -0
  154. package/src/models/payment.js +24 -0
  155. package/src/models/query-diff.js +7 -0
  156. package/src/models/release-manifest.js +160 -0
  157. package/src/models/repository-write.js +10 -0
  158. package/src/models/revisioned-commands.js +92 -0
  159. package/src/models/revisioned.js +41 -0
  160. package/src/models/settings.js +16 -0
  161. package/src/models/sync.js +44 -0
  162. package/src/models/wallet.js +40 -0
  163. package/src/queries/certificate-trust.js +31 -0
  164. package/{dist → src}/queries/conversations.js +54 -3
  165. package/src/queries/discovery.js +34 -0
  166. package/{dist → src}/queries/notifications.js +25 -2
  167. package/src/queries/onboarding-flow.js +48 -0
  168. package/src/queries/onboarding-lcd-screen.js +100 -0
  169. package/src/queries/onboarding-status.js +34 -0
  170. package/src/queries/revisioned.js +128 -0
  171. package/{dist → src}/queries/wallet.js +35 -1
  172. package/src/services/abort-signal.js +69 -0
  173. package/src/services/certificate-trust-service.js +119 -0
  174. package/{dist → src}/services/conversation-service.js +108 -1
  175. package/src/services/conversation-sync.js +28 -0
  176. package/src/services/device-boot-state-service.js +45 -0
  177. package/src/services/device-cleanup-service.js +112 -0
  178. package/src/services/discovery-probe-service.js +196 -0
  179. package/{dist → src}/services/gossip-service.js +54 -4
  180. package/src/services/invite-redemption-service.js +64 -0
  181. package/src/services/lan-candidate-refresh-service.js +164 -0
  182. package/src/services/lcd-decision-service.js +93 -0
  183. package/src/services/onboarding-checkpoint-store.js +155 -0
  184. package/src/services/onboarding-flow-service.js +1096 -0
  185. package/src/services/onboarding-status-service.js +64 -0
  186. package/{dist → src}/services/outbox-service.js +132 -1
  187. package/src/services/owner-claim-service.js +347 -0
  188. package/src/services/owner-view-refresh-service.js +208 -0
  189. package/src/services/owner-view-service.js +87 -0
  190. package/{dist → src}/services/peer-directory-service.js +72 -3
  191. package/src/services/release-manifest-verifier.js +108 -0
  192. package/{dist → src}/services/revisioned-domain-service.js +189 -9
  193. package/src/services/runtime-globals.js +174 -0
  194. package/src/services/session-service.js +50 -0
  195. package/{dist → src}/services/sync/authoritative-mirror.js +90 -1
  196. package/src/services/sync/index.js +67 -0
  197. package/src/services/sync/log-sync.js +60 -0
  198. package/src/services/sync/revision-merge.js +119 -0
  199. package/src/services/sync/strategy.js +44 -0
  200. package/src/services/transport-manager.js +478 -0
  201. package/{dist → src}/services/wallet-mirror-service.js +226 -6
  202. package/src/services/wifi-provisioning-service.js +278 -0
  203. package/dist/errors/index.js +0 -45
  204. package/dist/errors/index.js.map +0 -1
  205. package/dist/events/index.js +0 -17
  206. package/dist/events/index.js.map +0 -1
  207. package/dist/index.js +0 -31
  208. package/dist/index.js.map +0 -1
  209. package/dist/models/agent.js +0 -17
  210. package/dist/models/agent.js.map +0 -1
  211. package/dist/models/conversation.js +0 -2
  212. package/dist/models/conversation.js.map +0 -1
  213. package/dist/models/delegation.js.map +0 -1
  214. package/dist/models/device-identity.js.map +0 -1
  215. package/dist/models/graph.js.map +0 -1
  216. package/dist/models/index.js +0 -8
  217. package/dist/models/index.js.map +0 -1
  218. package/dist/models/json.js +0 -2
  219. package/dist/models/json.js.map +0 -1
  220. package/dist/models/l402.js +0 -2
  221. package/dist/models/l402.js.map +0 -1
  222. package/dist/models/live-query-definition.js +0 -2
  223. package/dist/models/live-query-definition.js.map +0 -1
  224. package/dist/models/outbox-intent.js +0 -2
  225. package/dist/models/outbox-intent.js.map +0 -1
  226. package/dist/models/outbox.js.map +0 -1
  227. package/dist/models/owner-views.js +0 -7
  228. package/dist/models/owner-views.js.map +0 -1
  229. package/dist/models/payment.js +0 -3
  230. package/dist/models/payment.js.map +0 -1
  231. package/dist/models/query-diff.js +0 -2
  232. package/dist/models/query-diff.js.map +0 -1
  233. package/dist/models/release-manifest.js +0 -147
  234. package/dist/models/release-manifest.js.map +0 -1
  235. package/dist/models/repository-write.js +0 -2
  236. package/dist/models/repository-write.js.map +0 -1
  237. package/dist/models/revisioned-commands.js +0 -35
  238. package/dist/models/revisioned-commands.js.map +0 -1
  239. package/dist/models/revisioned.js +0 -2
  240. package/dist/models/revisioned.js.map +0 -1
  241. package/dist/models/settings.js +0 -2
  242. package/dist/models/settings.js.map +0 -1
  243. package/dist/models/sync.js +0 -2
  244. package/dist/models/sync.js.map +0 -1
  245. package/dist/models/wallet.js +0 -2
  246. package/dist/models/wallet.js.map +0 -1
  247. package/dist/queries/conversations.js.map +0 -1
  248. package/dist/queries/discovery.js +0 -27
  249. package/dist/queries/discovery.js.map +0 -1
  250. package/dist/queries/notifications.js.map +0 -1
  251. package/dist/queries/onboarding-status.js +0 -27
  252. package/dist/queries/onboarding-status.js.map +0 -1
  253. package/dist/queries/revisioned.js +0 -58
  254. package/dist/queries/revisioned.js.map +0 -1
  255. package/dist/queries/wallet.js.map +0 -1
  256. package/dist/services/conversation-service.js.map +0 -1
  257. package/dist/services/conversation-sync.js +0 -9
  258. package/dist/services/conversation-sync.js.map +0 -1
  259. package/dist/services/discovery-probe-service.js +0 -129
  260. package/dist/services/discovery-probe-service.js.map +0 -1
  261. package/dist/services/gossip-service.js.map +0 -1
  262. package/dist/services/lan-candidate-refresh-service.js +0 -79
  263. package/dist/services/lan-candidate-refresh-service.js.map +0 -1
  264. package/dist/services/onboarding-status-service.js +0 -32
  265. package/dist/services/onboarding-status-service.js.map +0 -1
  266. package/dist/services/outbox-service.js.map +0 -1
  267. package/dist/services/owner-view-service.js +0 -21
  268. package/dist/services/owner-view-service.js.map +0 -1
  269. package/dist/services/peer-directory-service.js.map +0 -1
  270. package/dist/services/release-manifest-verifier.js +0 -84
  271. package/dist/services/release-manifest-verifier.js.map +0 -1
  272. package/dist/services/revisioned-domain-service.js.map +0 -1
  273. package/dist/services/session-service.js +0 -20
  274. package/dist/services/session-service.js.map +0 -1
  275. package/dist/services/sync/authoritative-mirror.js.map +0 -1
  276. package/dist/services/sync/index.js +0 -4
  277. package/dist/services/sync/index.js.map +0 -1
  278. package/dist/services/sync/log-sync.js +0 -20
  279. package/dist/services/sync/log-sync.js.map +0 -1
  280. package/dist/services/sync/revision-merge.js +0 -46
  281. package/dist/services/sync/revision-merge.js.map +0 -1
  282. package/dist/services/sync/strategy.js +0 -2
  283. package/dist/services/sync/strategy.js.map +0 -1
  284. package/dist/services/transport-manager.js +0 -234
  285. package/dist/services/transport-manager.js.map +0 -1
  286. package/dist/services/wallet-mirror-service.js.map +0 -1
@@ -1,4 +1,42 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @typedef {import("./json.js").JsonValue} JsonValue
5
+ */
6
+ /**
7
+ * @typedef {(typeof OUTBOX_STATES)[number]} OutboxState
8
+ */
9
+ /**
10
+ * @typedef {"acknowledged" | "replaying"} LegacyOutboxState
11
+ */
12
+ /**
13
+ * @typedef {OutboxState | LegacyOutboxState} OutboxIntentState
14
+ */
15
+ /**
16
+ * @typedef {"authoritative" | "eventual"} OutboxAuthority
17
+ */
18
+ /**
19
+ * @typedef {{ readonly expiresAt: string; readonly owner: string; }} OutboxLease
20
+ */
21
+ /**
22
+ * @typedef {{ readonly authority?: OutboxAuthority; readonly attemptCount?: number; readonly conflictReason?: string; readonly createdAt?: string; readonly domain: string; readonly id: string; readonly idempotencyKey: string; readonly lease?: OutboxLease; readonly maxAttempts?: number; readonly payload: JsonValue; readonly state: OutboxIntentState; readonly terminalReason?: string; readonly updatedAt?: string; }} OutboxIntent
23
+ */
24
+ /**
25
+ * @typedef {Omit<OutboxIntent, "attemptCount" | "createdAt" | "maxAttempts" | "state" | "updatedAt"> & { readonly attemptCount?: number; readonly createdAt?: string; readonly maxAttempts?: number; readonly state?: OutboxIntentState; readonly updatedAt?: string; }} OutboxIntentInput
26
+ */
27
+ /**
28
+ * @typedef {OutboxIntent & { readonly authority: OutboxAuthority; readonly attemptCount: number; readonly createdAt: string; readonly maxAttempts: number; readonly state: OutboxState; readonly updatedAt: string; }} OutboxEntry
29
+ */
30
+ /**
31
+ * @typedef {{ readonly maxAttempts?: number; readonly now?: string; }} OutboxIntentOptions
32
+ */
33
+ /** @type {readonly ["pending", "inflight", "acked", "failed", "conflict"]} */
1
34
  export const OUTBOX_STATES = ["pending", "inflight", "acked", "failed", "conflict"];
35
+ /**
36
+ * @param {OutboxIntentInput} input
37
+ * @param {OutboxIntentOptions} [options]
38
+ * @returns {OutboxEntry}
39
+ */
2
40
  export function createOutboxIntent(input, options = {}) {
3
41
  const now = options.now ?? input.updatedAt ?? input.createdAt ?? new Date().toISOString();
4
42
  return validateOutboxIntent({
@@ -9,6 +47,10 @@ export function createOutboxIntent(input, options = {}) {
9
47
  updatedAt: input.updatedAt ?? now,
10
48
  });
11
49
  }
50
+ /**
51
+ * @param {unknown} value
52
+ * @returns {OutboxEntry}
53
+ */
12
54
  export function validateOutboxIntent(value) {
13
55
  if (!isRecord(value))
14
56
  throw invalid("outbox intent must be an object");
@@ -49,15 +91,23 @@ export function validateOutboxIntent(value) {
49
91
  updatedAt,
50
92
  });
51
93
  }
94
+ /**
95
+ * @param {unknown} state
96
+ * @returns {OutboxState}
97
+ */
52
98
  export function fromPublicOutboxState(state) {
53
99
  if (state === "replaying")
54
100
  return "inflight";
55
101
  if (state === "acknowledged")
56
102
  return "acked";
57
- if (OUTBOX_STATES.includes(state))
103
+ if (isOutboxState(state))
58
104
  return state;
59
105
  throw invalid("outbox state");
60
106
  }
107
+ /**
108
+ * @param {OutboxState} state
109
+ * @returns {Exclude<OutboxIntentState, OutboxState> | OutboxState}
110
+ */
61
111
  export function toPublicOutboxState(state) {
62
112
  if (state === "inflight")
63
113
  return "replaying";
@@ -67,14 +117,22 @@ export function toPublicOutboxState(state) {
67
117
  return "failed";
68
118
  return state;
69
119
  }
120
+ /**
121
+ * @param {JsonValue} value
122
+ * @returns {string}
123
+ */
70
124
  export function canonicalOutboxPayload(value) {
71
125
  if (Array.isArray(value))
72
126
  return `[${value.map(canonicalOutboxPayload).join(",")}]`;
73
127
  if (value !== null && typeof value === "object") {
74
- return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalOutboxPayload(value[key])}`).join(",")}}`;
128
+ return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalOutboxPayload(/** @type {JsonValue} */ (value[key]))}`).join(",")}}`;
75
129
  }
76
130
  return JSON.stringify(value);
77
131
  }
132
+ /**
133
+ * @param {JsonValue} value
134
+ * @returns {JsonValue}
135
+ */
78
136
  function cloneJson(value) {
79
137
  if (Array.isArray(value))
80
138
  return value.map(cloneJson);
@@ -83,6 +141,11 @@ function cloneJson(value) {
83
141
  }
84
142
  return value;
85
143
  }
144
+ /**
145
+ * @template T
146
+ * @param {T} value
147
+ * @returns {T}
148
+ */
86
149
  function deepFreeze(value) {
87
150
  if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
88
151
  Object.freeze(value);
@@ -91,6 +154,10 @@ function deepFreeze(value) {
91
154
  }
92
155
  return value;
93
156
  }
157
+ /**
158
+ * @param {unknown} value
159
+ * @returns {value is JsonValue}
160
+ */
94
161
  function isJsonValue(value) {
95
162
  if (value === null || typeof value === "boolean" || typeof value === "string")
96
163
  return true;
@@ -102,26 +169,59 @@ function isJsonValue(value) {
102
169
  return false;
103
170
  return Object.values(value).every(isJsonValue);
104
171
  }
172
+ /**
173
+ * @param {unknown} value
174
+ * @returns {value is OutboxState}
175
+ */
176
+ function isOutboxState(value) {
177
+ return typeof value === "string" && OUTBOX_STATES.includes(/** @type {OutboxState} */ (value));
178
+ }
179
+ /**
180
+ * @param {unknown} value
181
+ * @returns {value is number}
182
+ */
105
183
  function isNonNegativeInteger(value) {
106
184
  return typeof value === "number" && Number.isInteger(value) && value >= 0;
107
185
  }
186
+ /**
187
+ * @param {unknown} value
188
+ * @returns {value is Record<string, unknown>}
189
+ */
108
190
  function isRecord(value) {
109
191
  return value !== null && typeof value === "object" && !Array.isArray(value);
110
192
  }
193
+ /**
194
+ * @param {string} message
195
+ * @returns {TypeError}
196
+ */
111
197
  function invalid(message) {
112
198
  return new TypeError(message);
113
199
  }
200
+ /**
201
+ * @param {unknown} value
202
+ * @param {string} label
203
+ * @returns {string}
204
+ */
114
205
  function requiredString(value, label) {
115
206
  if (typeof value !== "string" || value.trim() === "")
116
207
  throw invalid(`${label} must be a non-empty string`);
117
208
  return value;
118
209
  }
210
+ /**
211
+ * @param {unknown} value
212
+ * @param {string} label
213
+ * @returns {string}
214
+ */
119
215
  function requiredTimestamp(value, label) {
120
216
  const timestamp = requiredString(value, label);
121
217
  if (!Number.isFinite(Date.parse(timestamp)))
122
218
  throw invalid(`${label} must be an ISO timestamp`);
123
219
  return timestamp;
124
220
  }
221
+ /**
222
+ * @param {unknown} value
223
+ * @returns {OutboxLease}
224
+ */
125
225
  function validateLease(value) {
126
226
  if (!isRecord(value))
127
227
  throw invalid("outbox lease");
@@ -130,4 +230,3 @@ function validateLease(value) {
130
230
  owner: requiredString(value.owner, "outbox lease owner"),
131
231
  });
132
232
  }
133
- //# sourceMappingURL=outbox.js.map
@@ -0,0 +1,59 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @typedef {(typeof OWNER_VIEW_SYNC_STRATEGIES)[keyof typeof OWNER_VIEW_SYNC_STRATEGIES]} OwnerViewSyncStrategy
5
+ */
6
+ /**
7
+ * @typedef {"offline" | "online" | "unknown"} HomeStatus
8
+ */
9
+ /**
10
+ * @typedef {{ readonly cachedAt?: string; readonly displayName: string; readonly homeNodeId: string; readonly lastSyncedAt?: string; readonly status: HomeStatus; }} HomeSummary
11
+ */
12
+ /**
13
+ * @typedef {"offline" | "online" | "unknown"} PeerStatus
14
+ */
15
+ /**
16
+ * @typedef {{ readonly displayName: string; readonly id: string; readonly lastSeenAt?: string; readonly status: PeerStatus; }} PeerDirectoryEntry
17
+ */
18
+ /**
19
+ * @typedef {{ readonly limit?: number; readonly status?: PeerStatus; }} PeerDirectoryQuery
20
+ */
21
+ /**
22
+ * @typedef {"activity" | "message" | "system"} FeedItemKind
23
+ */
24
+ /**
25
+ * @typedef {{ readonly body: string; readonly createdAt: string; readonly id: string; readonly kind: FeedItemKind; readonly read: boolean; readonly title: string; }} FeedItem
26
+ */
27
+ /**
28
+ * @typedef {{ readonly before?: string; readonly limit?: number; readonly unreadOnly?: boolean; }} FeedQuery
29
+ */
30
+ /**
31
+ * @typedef {"blocked" | "ready" | "recovering"} StorageStatus
32
+ */
33
+ /**
34
+ * @typedef {"current" | "stale" | "syncing"} SyncStatus
35
+ */
36
+ /**
37
+ * @typedef {"iroh-relay" | "lan-direct" | "lan-webtransport" | "offline" | "wan-direct" | "webrtc-direct"} OperationalTransport
38
+ */
39
+ /**
40
+ * @typedef {{ readonly cachedAt?: string; readonly outboxDepth: number; readonly storage: StorageStatus; readonly sync: SyncStatus; readonly transport: OperationalTransport; }} OperationalSummary
41
+ */
42
+ /**
43
+ * Owner-facing read views projected from the home node.
44
+ *
45
+ * Implementations MUST NOT depend on the durable, OPFS-backed local SQLite
46
+ * cache. This port models what the home node currently reports, so every
47
+ * method resolves from in-memory state or a home-node round trip. The kernel
48
+ * relies on that prohibition to keep owner-view live queries available in
49
+ * degraded mode when a browser cannot provide OPFS. A storage-backed
50
+ * projection belongs behind its own repository port instead.
51
+ *
52
+ * @typedef {{ listFeed(params: FeedQuery): Promise<readonly FeedItem[]>; listPeers(params: PeerDirectoryQuery): Promise<readonly PeerDirectoryEntry[]>; readHomeSummary(): Promise<HomeSummary | undefined>; readOperationalSummary(): Promise<OperationalSummary | undefined>; }} OwnerViewRepository
53
+ */
54
+ export const OWNER_VIEW_SYNC_STRATEGIES = {
55
+ feeds: "log",
56
+ home: "authoritative",
57
+ operations: "authoritative",
58
+ peers: "log",
59
+ };
@@ -0,0 +1,24 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @typedef {(typeof PAYMENT_DIRECTIONS)[number]} PaymentDirection
5
+ */
6
+ /**
7
+ * @typedef {(typeof PAYMENT_STATUSES)[number]} PaymentStatus
8
+ */
9
+ /**
10
+ * @typedef {{ readonly amountMsat: number; readonly createdAt: string; readonly direction: PaymentDirection; readonly failureCode?: string; readonly id: string; readonly paymentHash?: string; readonly status: PaymentStatus; readonly updatedAt: string; }} PaymentRecord
11
+ */
12
+ /**
13
+ * @typedef {{ readonly amountMsat: number; readonly invoiceId: string; readonly kind: "invoice-created"; readonly paymentHash?: string; readonly paymentRequest: string; readonly status: "created"; }} InvoiceCreatedResult
14
+ */
15
+ /**
16
+ * @typedef {{ readonly amountMsat: number; readonly kind: "payment-submitted"; readonly paymentHash?: string; readonly paymentId: string; readonly status: Exclude<PaymentStatus, "expired">; }} PaymentSubmittedResult
17
+ */
18
+ /**
19
+ * @typedef {InvoiceCreatedResult | PaymentSubmittedResult} WalletCommandResult
20
+ */
21
+ /** @type {readonly ["incoming", "outgoing"]} */
22
+ export const PAYMENT_DIRECTIONS = ["incoming", "outgoing"];
23
+ /** @type {readonly ["pending", "succeeded", "failed", "expired"]} */
24
+ export const PAYMENT_STATUSES = ["pending", "succeeded", "failed", "expired"];
@@ -0,0 +1,7 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @template TRow
5
+ * @typedef {{ readonly added: readonly TRow[]; readonly deleted: readonly TRow[]; readonly revision: number; readonly updated: readonly TRow[]; }} QueryDiff
6
+ */
7
+ export {};
@@ -0,0 +1,160 @@
1
+ // @ts-check
2
+
3
+ /** @typedef {import("./json.js").JsonObject} JsonObject */
4
+
5
+ export const RELEASE_MANIFEST_VERSION = 1;
6
+
7
+ export const RELEASE_MANIFEST_LIMITS = {
8
+ maxBuildIdLength: 128,
9
+ maxChannelLength: 64,
10
+ maxShellAssetUrlLength: 2048,
11
+ maxShellAssets: 4096,
12
+ maxShellVersionLength: 64,
13
+ maxSigningKeyIdLength: 128,
14
+ maxVersionValue: 1_000_000,
15
+ };
16
+
17
+ /** @typedef {{ readonly sha256: string, readonly url: string }} ReleaseManifestAsset */
18
+ /** @typedef {{ readonly max: number, readonly min: number }} ReleaseManifestVersionRange */
19
+ /** @typedef {{ readonly buildId: string, readonly channel: string, readonly issuedAtMs: number, readonly manifestVersion: 1, readonly protocolCompatibility: ReleaseManifestVersionRange, readonly shellAssets: readonly ReleaseManifestAsset[], readonly shellVersion: string, readonly signingKeyId: string, readonly storageSchemaCompatibility: ReleaseManifestVersionRange }} UnsignedReleaseManifest */
20
+ /** @typedef {UnsignedReleaseManifest & { readonly signature: string }} SignedReleaseManifest */
21
+
22
+ /**
23
+ * @param {UnsignedReleaseManifest} manifest
24
+ * @returns {JsonObject}
25
+ */
26
+ export function unsignedReleaseManifestToJson(manifest) {
27
+ return {
28
+ buildId: manifest.buildId,
29
+ channel: manifest.channel,
30
+ issuedAtMs: manifest.issuedAtMs,
31
+ manifestVersion: manifest.manifestVersion,
32
+ protocolCompatibility: {
33
+ max: manifest.protocolCompatibility.max,
34
+ min: manifest.protocolCompatibility.min,
35
+ },
36
+ shellAssets: manifest.shellAssets.map((asset) => ({ sha256: asset.sha256, url: asset.url })),
37
+ shellVersion: manifest.shellVersion,
38
+ signingKeyId: manifest.signingKeyId,
39
+ storageSchemaCompatibility: {
40
+ max: manifest.storageSchemaCompatibility.max,
41
+ min: manifest.storageSchemaCompatibility.min,
42
+ },
43
+ };
44
+ }
45
+
46
+ const HEX_64_BYTES = /^[0-9a-f]{128}$/u;
47
+ const SHA256_HEX = /^[0-9a-f]{64}$/u;
48
+ const CHANNEL_PATTERN = /^[a-z][a-z0-9-]{0,63}$/u;
49
+
50
+ /**
51
+ * @param {unknown} candidate
52
+ * @returns {SignedReleaseManifest | undefined}
53
+ */
54
+ export function parseSignedReleaseManifest(candidate) {
55
+ if (typeof candidate !== "object" || candidate === null || Array.isArray(candidate)) return undefined;
56
+ const value = /** @type {Record<string, unknown>} */ (candidate);
57
+
58
+ if (value.manifestVersion !== RELEASE_MANIFEST_VERSION) return undefined;
59
+
60
+ const buildId = boundedString(value.buildId, 1, RELEASE_MANIFEST_LIMITS.maxBuildIdLength);
61
+ if (buildId === undefined) return undefined;
62
+
63
+ const channel = typeof value.channel === "string" && CHANNEL_PATTERN.test(value.channel)
64
+ ? value.channel
65
+ : undefined;
66
+ if (channel === undefined || channel.length > RELEASE_MANIFEST_LIMITS.maxChannelLength) return undefined;
67
+
68
+ if (!isSafeNonNegativeInteger(value.issuedAtMs)) return undefined;
69
+
70
+ const signingKeyId = boundedString(value.signingKeyId, 1, RELEASE_MANIFEST_LIMITS.maxSigningKeyIdLength);
71
+ if (signingKeyId === undefined) return undefined;
72
+
73
+ const shellVersion = boundedString(value.shellVersion, 1, RELEASE_MANIFEST_LIMITS.maxShellVersionLength);
74
+ if (shellVersion === undefined) return undefined;
75
+
76
+ const signature = typeof value.signature === "string" && HEX_64_BYTES.test(value.signature)
77
+ ? value.signature
78
+ : undefined;
79
+ if (signature === undefined) return undefined;
80
+
81
+ const protocolCompatibility = parseVersionRange(value.protocolCompatibility);
82
+ if (protocolCompatibility === undefined) return undefined;
83
+
84
+ const storageSchemaCompatibility = parseVersionRange(value.storageSchemaCompatibility);
85
+ if (storageSchemaCompatibility === undefined) return undefined;
86
+
87
+ const shellAssets = parseShellAssets(value.shellAssets);
88
+ if (shellAssets === undefined) return undefined;
89
+
90
+ return {
91
+ buildId,
92
+ channel,
93
+ issuedAtMs: value.issuedAtMs,
94
+ manifestVersion: RELEASE_MANIFEST_VERSION,
95
+ protocolCompatibility,
96
+ shellAssets,
97
+ shellVersion,
98
+ signature,
99
+ signingKeyId,
100
+ storageSchemaCompatibility,
101
+ };
102
+ }
103
+
104
+ /**
105
+ * @param {unknown} candidate
106
+ * @returns {ReleaseManifestVersionRange | undefined}
107
+ */
108
+ function parseVersionRange(candidate) {
109
+ if (typeof candidate !== "object" || candidate === null || Array.isArray(candidate)) return undefined;
110
+ const value = /** @type {Record<string, unknown>} */ (candidate);
111
+ const { maxVersionValue } = RELEASE_MANIFEST_LIMITS;
112
+ if (
113
+ !isSafeNonNegativeInteger(value.min) ||
114
+ !isSafeNonNegativeInteger(value.max) ||
115
+ value.min > maxVersionValue ||
116
+ value.max > maxVersionValue ||
117
+ value.min > value.max
118
+ ) return undefined;
119
+ return { max: value.max, min: value.min };
120
+ }
121
+
122
+ /**
123
+ * @param {unknown} candidate
124
+ * @returns {readonly ReleaseManifestAsset[] | undefined}
125
+ */
126
+ function parseShellAssets(candidate) {
127
+ if (!Array.isArray(candidate) || candidate.length < 1) return undefined;
128
+ if (candidate.length > RELEASE_MANIFEST_LIMITS.maxShellAssets) return undefined;
129
+ /** @type {ReleaseManifestAsset[]} */
130
+ const assets = [];
131
+ for (const entry of candidate) {
132
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) return undefined;
133
+ const record = /** @type {Record<string, unknown>} */ (entry);
134
+ const url = boundedString(record.url, 1, RELEASE_MANIFEST_LIMITS.maxShellAssetUrlLength);
135
+ if (url === undefined) return undefined;
136
+ if (typeof record.sha256 !== "string" || !SHA256_HEX.test(record.sha256)) return undefined;
137
+ assets.push({ sha256: record.sha256, url });
138
+ }
139
+ return assets;
140
+ }
141
+
142
+ /**
143
+ * @param {unknown} value
144
+ * @param {number} minLength
145
+ * @param {number} maxLength
146
+ * @returns {string | undefined}
147
+ */
148
+ function boundedString(value, minLength, maxLength) {
149
+ return typeof value === "string" && value.length >= minLength && value.length <= maxLength
150
+ ? value
151
+ : undefined;
152
+ }
153
+
154
+ /**
155
+ * @param {unknown} value
156
+ * @returns {value is number}
157
+ */
158
+ function isSafeNonNegativeInteger(value) {
159
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
160
+ }
@@ -0,0 +1,10 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @typedef {import("../events/index.js").DomainEvent} DomainEvent
5
+ */
6
+ /**
7
+ * @template {DomainEvent} TEvent
8
+ * @typedef {{ commit(): Promise<{ readonly events: readonly TEvent[] }>; }} RepositoryWrite
9
+ */
10
+ export {};
@@ -0,0 +1,92 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @typedef {import("./agent.js").AgentValue} AgentValue
5
+ */
6
+ /**
7
+ * @typedef {import("./graph.js").GraphValue} GraphValue
8
+ */
9
+ /**
10
+ * @typedef {import("./json.js").JsonValue} JsonValue
11
+ */
12
+ /**
13
+ * @template {JsonValue} TValue
14
+ * @typedef {import("./revisioned.js").RevisionCommand<TValue>} RevisionCommand
15
+ */
16
+ /**
17
+ * @typedef {import("./revisioned.js").RevisionResolution} RevisionResolution
18
+ */
19
+ /**
20
+ * @typedef {import("./revisioned.js").RevisionedDomain} RevisionedDomain
21
+ */
22
+ /**
23
+ * @typedef {(typeof REVISIONED_COMMAND_NAMES)[number]} RevisionedCommandName
24
+ */
25
+ /**
26
+ * @typedef {Exclude<RevisionedCommandName, "sync.revision-conflict.resolve.v1">} RevisionUpdateCommandName
27
+ */
28
+ /**
29
+ * @template {JsonValue} [TValue=import("./json.js").JsonValue]
30
+ * @typedef {{ readonly name: RevisionUpdateCommandName; readonly payload: RevisionCommand<TValue>; }} RevisionUpdateCommand
31
+ */
32
+ /**
33
+ * @typedef {{ readonly name: "sync.revision-conflict.resolve.v1"; readonly payload: { readonly conflictId: string; readonly idempotencyKey: string; readonly resolution: RevisionResolution; }; }} ResolveRevisionConflictCommand
34
+ */
35
+ /** @type {readonly ["agents.update.v1", "graphs.update.v1", "settings.update.v1", "sync.revision-conflict.resolve.v1"]} */
36
+ export const REVISIONED_COMMAND_NAMES = [
37
+ "agents.update.v1",
38
+ "graphs.update.v1",
39
+ "settings.update.v1",
40
+ "sync.revision-conflict.resolve.v1",
41
+ ];
42
+ /**
43
+ * @template {JsonValue} TValue
44
+ * @param {RevisionedDomain} domain
45
+ * @param {RevisionCommand<TValue>} payload
46
+ * @returns {RevisionUpdateCommand<TValue>}
47
+ */
48
+ export function createRevisionedUpdateCommand(domain, payload) {
49
+ return {
50
+ name: updateCommandName(domain),
51
+ payload,
52
+ };
53
+ }
54
+ /**
55
+ * @param {RevisionCommand<AgentValue>} payload
56
+ * @returns {RevisionUpdateCommand<AgentValue>}
57
+ */
58
+ export function createAgentUpdateCommand(payload) {
59
+ return createRevisionedUpdateCommand("agent", payload);
60
+ }
61
+ /**
62
+ * @param {RevisionCommand<GraphValue>} payload
63
+ * @returns {RevisionUpdateCommand<GraphValue>}
64
+ */
65
+ export function createGraphUpdateCommand(payload) {
66
+ return createRevisionedUpdateCommand("graph", payload);
67
+ }
68
+ /**
69
+ * @param {ResolveRevisionConflictCommand["payload"]} payload
70
+ * @returns {ResolveRevisionConflictCommand}
71
+ */
72
+ export function createResolveRevisionConflictCommand(payload) {
73
+ if (payload.conflictId.trim() === "" || payload.idempotencyKey.trim() === "") {
74
+ throw new TypeError("Revision conflict resolution requires identifiers");
75
+ }
76
+ if (payload.resolution !== "mine" && payload.resolution !== "theirs") {
77
+ throw new TypeError("Invalid revision conflict resolution");
78
+ }
79
+ return { name: "sync.revision-conflict.resolve.v1", payload };
80
+ }
81
+ /**
82
+ * @param {RevisionedDomain} domain
83
+ * @returns {RevisionUpdateCommandName}
84
+ */
85
+ function updateCommandName(domain) {
86
+ switch (domain) {
87
+ case "agent": return "agents.update.v1";
88
+ case "graph": return "graphs.update.v1";
89
+ case "settings": return "settings.update.v1";
90
+ }
91
+ throw new TypeError("Unsupported revisioned domain");
92
+ }
@@ -0,0 +1,41 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @typedef {import("./json.js").JsonValue} JsonValue
5
+ */
6
+ /**
7
+ * @template TValue
8
+ * @typedef {import("./sync.js").RevisionConflict<TValue>} RevisionConflict
9
+ */
10
+ /**
11
+ * @template TValue
12
+ * @typedef {import("./sync.js").RevisionIntent<TValue>} RevisionIntent
13
+ */
14
+ /**
15
+ * @typedef {(typeof REVISIONED_DOMAINS)[number]} RevisionedDomain
16
+ */
17
+ /**
18
+ * @template {JsonValue} TValue
19
+ * @typedef {RevisionIntent<TValue> & { readonly idempotencyKey: string; }} RevisionCommand
20
+ */
21
+ /**
22
+ * @template {JsonValue} TValue
23
+ * @typedef {RevisionConflict<TValue> & { readonly conflictId: string; readonly createdAt: string; readonly domain: RevisionedDomain; readonly idempotencyKey: string; }} RevisionConflictRecord
24
+ */
25
+ /**
26
+ * @template {JsonValue} TValue
27
+ * @typedef {RevisionConflictRecord<TValue> & { readonly kind: "revision-conflict.v1"; }} RevisionConflictPayload
28
+ */
29
+ /**
30
+ * @typedef {"mine" | "theirs"} RevisionResolution
31
+ */
32
+ /**
33
+ * @template TValue
34
+ * @typedef {import("./sync.js").RevisionCommandResult<TValue>} RevisionCommandResult
35
+ */
36
+ /**
37
+ * @template TValue
38
+ * @typedef {import("./sync.js").RevisionEntity<TValue>} RevisionEntity
39
+ */
40
+ /** @type {readonly ["agent", "settings", "graph"]} */
41
+ export const REVISIONED_DOMAINS = ["agent", "settings", "graph"];
@@ -0,0 +1,16 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @typedef {import("./json.js").JsonValue} JsonValue
5
+ */
6
+ /**
7
+ * @template TValue
8
+ * @typedef {import("./sync.js").RevisionEntity<TValue>} RevisionEntity
9
+ */
10
+ /**
11
+ * @typedef {JsonValue} SettingValue
12
+ */
13
+ /**
14
+ * @typedef {RevisionEntity<SettingValue>} RevisionedSetting
15
+ */
16
+ export {};
@@ -0,0 +1,44 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * @typedef {"authoritative-mirror" | "log" | "revision-merge"} SyncStrategyKind
5
+ */
6
+ /**
7
+ * @template TPayload
8
+ * @typedef {{ readonly cursor: string; readonly id: string; readonly payload: TPayload; }} SyncDelta
9
+ */
10
+ /**
11
+ * @typedef {{ readonly domain: string; readonly now: string; }} SyncDeltaContext
12
+ */
13
+ /**
14
+ * @typedef {{ readonly applied: boolean; }} SyncApplyResult
15
+ */
16
+ /**
17
+ * @template TPayload
18
+ * @typedef {{ readonly kind: SyncStrategyKind; applyDelta(delta: SyncDelta<TPayload>, context: SyncDeltaContext): Promise<SyncApplyResult>; }} SyncStrategy
19
+ */
20
+ /**
21
+ * @template TValue
22
+ * @typedef {{ readonly id: string; readonly rev: number; readonly value: TValue; }} RevisionEntity
23
+ */
24
+ /**
25
+ * @template TValue
26
+ * @typedef {{ readonly baseRev: number; readonly id: string; readonly value: TValue; }} RevisionIntent
27
+ */
28
+ /**
29
+ * @template TValue
30
+ * @typedef {{ readonly baseRev: number; readonly id: string; readonly mine: TValue; readonly theirs: RevisionEntity<TValue>; }} RevisionConflict
31
+ */
32
+ /**
33
+ * @template TValue
34
+ * @typedef {| { readonly entity: RevisionEntity<TValue>; readonly status: "accepted" } | { readonly status: "conflict"; readonly theirs: RevisionEntity<TValue> }} RevisionCommandResult
35
+ */
36
+ /**
37
+ * @template TValue
38
+ * @typedef {{ readonly observedAt: string; readonly staleAt: string; readonly value: TValue; }} AuthoritativeSnapshot
39
+ */
40
+ /**
41
+ * @template TPayload
42
+ * @typedef {{ readonly idempotencyKey: string; readonly payload: TPayload; }} AuthoritativeCommand
43
+ */
44
+ export {};