@econ-v1/ports 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 (182) hide show
  1. package/dist/app-data.d.ts +39 -0
  2. package/dist/app-data.d.ts.map +1 -0
  3. package/dist/client-ui-preference.d.ts +23 -0
  4. package/dist/client-ui-preference.d.ts.map +1 -0
  5. package/dist/clipboard.d.ts +41 -0
  6. package/dist/clipboard.d.ts.map +1 -0
  7. package/dist/clock.d.ts +8 -8
  8. package/dist/clock.d.ts.map +1 -1
  9. package/dist/credential-handoff.d.ts +57 -0
  10. package/dist/credential-handoff.d.ts.map +1 -0
  11. package/dist/crypto.d.ts +4 -4
  12. package/dist/crypto.d.ts.map +1 -1
  13. package/dist/id.d.ts +2 -2
  14. package/dist/id.d.ts.map +1 -1
  15. package/dist/identity.d.ts +31 -25
  16. package/dist/identity.d.ts.map +1 -1
  17. package/dist/index.d.ts +226 -30
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/install-environment.d.ts +22 -32
  20. package/dist/install-environment.d.ts.map +1 -1
  21. package/dist/lcd-tree-source.d.ts +54 -0
  22. package/dist/lcd-tree-source.d.ts.map +1 -0
  23. package/dist/legacy-credential.d.ts +30 -0
  24. package/dist/legacy-credential.d.ts.map +1 -0
  25. package/dist/media-preferences.d.ts +2 -44
  26. package/dist/media-preferences.d.ts.map +1 -1
  27. package/dist/network/certificate-trust.d.ts +31 -0
  28. package/dist/network/certificate-trust.d.ts.map +1 -0
  29. package/dist/network/client-node-origin.d.ts +3 -15
  30. package/dist/network/client-node-origin.d.ts.map +1 -1
  31. package/dist/network/home-node-candidate-store.d.ts +4 -32
  32. package/dist/network/home-node-candidate-store.d.ts.map +1 -1
  33. package/dist/network/home-node-candidate.d.ts +9 -7
  34. package/dist/network/home-node-candidate.d.ts.map +1 -1
  35. package/dist/network/l402-payment.d.ts +11 -28
  36. package/dist/network/l402-payment.d.ts.map +1 -1
  37. package/dist/network/node-discovery.d.ts +5 -16
  38. package/dist/network/node-discovery.d.ts.map +1 -1
  39. package/dist/network/webrtc-signaling.d.ts +36 -52
  40. package/dist/network/webrtc-signaling.d.ts.map +1 -1
  41. package/dist/network.d.ts +65 -40
  42. package/dist/network.d.ts.map +1 -1
  43. package/dist/offline-readiness.d.ts +122 -0
  44. package/dist/offline-readiness.d.ts.map +1 -0
  45. package/dist/onboarding-access-code.d.ts +30 -0
  46. package/dist/onboarding-access-code.d.ts.map +1 -0
  47. package/dist/onboarding-checkpoint.d.ts +26 -0
  48. package/dist/onboarding-checkpoint.d.ts.map +1 -0
  49. package/dist/onboarding-presence.d.ts +12 -0
  50. package/dist/onboarding-presence.d.ts.map +1 -0
  51. package/dist/owner-claim-session.d.ts +60 -0
  52. package/dist/owner-claim-session.d.ts.map +1 -0
  53. package/dist/owner-claim.d.ts +22 -0
  54. package/dist/owner-claim.d.ts.map +1 -0
  55. package/dist/repositories/conversation-repository.d.ts +21 -20
  56. package/dist/repositories/conversation-repository.d.ts.map +1 -1
  57. package/dist/repositories/durable-event.d.ts +8 -8
  58. package/dist/repositories/durable-event.d.ts.map +1 -1
  59. package/dist/repositories/node-app-memory-repository.d.ts +168 -0
  60. package/dist/repositories/node-app-memory-repository.d.ts.map +1 -0
  61. package/dist/repositories/outbox.d.ts +33 -20
  62. package/dist/repositories/outbox.d.ts.map +1 -1
  63. package/dist/repositories/repository-mutation.d.ts +3 -1
  64. package/dist/repositories/repository-mutation.d.ts.map +1 -1
  65. package/dist/repositories/revisioned-repository.d.ts +14 -12
  66. package/dist/repositories/revisioned-repository.d.ts.map +1 -1
  67. package/dist/repositories/settings.d.ts +10 -10
  68. package/dist/repositories/settings.d.ts.map +1 -1
  69. package/dist/repositories/sync-ledger.d.ts +11 -11
  70. package/dist/repositories/sync-ledger.d.ts.map +1 -1
  71. package/dist/repositories/wallet-mirror-repository.d.ts +22 -13
  72. package/dist/repositories/wallet-mirror-repository.d.ts.map +1 -1
  73. package/dist/repositories.d.ts +52 -17
  74. package/dist/repositories.d.ts.map +1 -1
  75. package/dist/scheduler.d.ts +4 -4
  76. package/dist/scheduler.d.ts.map +1 -1
  77. package/dist/session-flag.d.ts +48 -0
  78. package/dist/session-flag.d.ts.map +1 -0
  79. package/dist/shell-cache-reset.d.ts +4 -0
  80. package/dist/shell-cache-reset.d.ts.map +1 -0
  81. package/dist/shell-version.d.ts +8 -0
  82. package/dist/shell-version.d.ts.map +1 -0
  83. package/dist/storage.d.ts +76 -34
  84. package/dist/storage.d.ts.map +1 -1
  85. package/dist/theme.d.ts +2 -24
  86. package/dist/theme.d.ts.map +1 -1
  87. package/package.json +14 -10
  88. package/src/app-data.js +42 -0
  89. package/src/client-ui-preference.js +23 -0
  90. package/src/clipboard.js +41 -0
  91. package/src/clock.js +13 -0
  92. package/src/credential-handoff.js +68 -0
  93. package/src/crypto.js +9 -0
  94. package/src/id.js +5 -0
  95. package/src/identity.js +33 -0
  96. package/src/index.js +250 -0
  97. package/src/install-environment.js +44 -0
  98. package/src/lcd-tree-source.js +56 -0
  99. package/src/legacy-credential.js +30 -0
  100. package/src/media-preferences.js +40 -0
  101. package/src/network/certificate-trust.js +25 -0
  102. package/src/network/client-node-origin.js +7 -0
  103. package/src/network/home-node-candidate-store.js +6 -0
  104. package/src/network/home-node-candidate.js +9 -0
  105. package/src/network/l402-payment.js +20 -0
  106. package/src/network/node-discovery.js +13 -0
  107. package/src/network/webrtc-signaling.js +40 -0
  108. package/src/network.js +33 -0
  109. package/src/offline-readiness.js +65 -0
  110. package/src/onboarding-access-code.js +21 -0
  111. package/src/onboarding-checkpoint.js +26 -0
  112. package/src/onboarding-presence.js +15 -0
  113. package/src/owner-claim-session.js +55 -0
  114. package/src/owner-claim.js +22 -0
  115. package/src/repositories/conversation-repository.js +20 -0
  116. package/src/repositories/durable-event.js +8 -0
  117. package/src/repositories/node-app-memory-repository.js +221 -0
  118. package/src/repositories/outbox.js +27 -0
  119. package/src/repositories/repository-mutation.js +8 -0
  120. package/src/repositories/revisioned-repository.js +17 -0
  121. package/src/repositories/settings.js +10 -0
  122. package/src/repositories/sync-ledger.js +11 -0
  123. package/src/repositories/wallet-mirror-repository.js +73 -0
  124. package/src/repositories.js +22 -0
  125. package/src/scheduler.js +6 -0
  126. package/src/session-flag.js +48 -0
  127. package/src/shell-cache-reset.js +3 -0
  128. package/src/shell-version.js +4 -0
  129. package/src/storage.js +60 -0
  130. package/src/theme.js +21 -0
  131. package/dist/clock.js +0 -2
  132. package/dist/clock.js.map +0 -1
  133. package/dist/crypto.js +0 -2
  134. package/dist/crypto.js.map +0 -1
  135. package/dist/id.js +0 -2
  136. package/dist/id.js.map +0 -1
  137. package/dist/identity.js +0 -2
  138. package/dist/identity.js.map +0 -1
  139. package/dist/index.js +0 -9
  140. package/dist/index.js.map +0 -1
  141. package/dist/install-environment.js +0 -26
  142. package/dist/install-environment.js.map +0 -1
  143. package/dist/media-preferences.js +0 -2
  144. package/dist/media-preferences.js.map +0 -1
  145. package/dist/network/client-node-origin.js +0 -18
  146. package/dist/network/client-node-origin.js.map +0 -1
  147. package/dist/network/home-node-candidate-store.js +0 -2
  148. package/dist/network/home-node-candidate-store.js.map +0 -1
  149. package/dist/network/home-node-candidate.js +0 -2
  150. package/dist/network/home-node-candidate.js.map +0 -1
  151. package/dist/network/l402-payment.js +0 -2
  152. package/dist/network/l402-payment.js.map +0 -1
  153. package/dist/network/node-discovery.js +0 -13
  154. package/dist/network/node-discovery.js.map +0 -1
  155. package/dist/network/webrtc-signaling.js +0 -30
  156. package/dist/network/webrtc-signaling.js.map +0 -1
  157. package/dist/network.js +0 -2
  158. package/dist/network.js.map +0 -1
  159. package/dist/repositories/conversation-repository.js +0 -2
  160. package/dist/repositories/conversation-repository.js.map +0 -1
  161. package/dist/repositories/durable-event.js +0 -2
  162. package/dist/repositories/durable-event.js.map +0 -1
  163. package/dist/repositories/outbox.js +0 -9
  164. package/dist/repositories/outbox.js.map +0 -1
  165. package/dist/repositories/repository-mutation.js +0 -2
  166. package/dist/repositories/repository-mutation.js.map +0 -1
  167. package/dist/repositories/revisioned-repository.js +0 -2
  168. package/dist/repositories/revisioned-repository.js.map +0 -1
  169. package/dist/repositories/settings.js +0 -2
  170. package/dist/repositories/settings.js.map +0 -1
  171. package/dist/repositories/sync-ledger.js +0 -2
  172. package/dist/repositories/sync-ledger.js.map +0 -1
  173. package/dist/repositories/wallet-mirror-repository.js +0 -53
  174. package/dist/repositories/wallet-mirror-repository.js.map +0 -1
  175. package/dist/repositories.js +0 -2
  176. package/dist/repositories.js.map +0 -1
  177. package/dist/scheduler.js +0 -2
  178. package/dist/scheduler.js.map +0 -1
  179. package/dist/storage.js +0 -14
  180. package/dist/storage.js.map +0 -1
  181. package/dist/theme.js +0 -2
  182. package/dist/theme.js.map +0 -1
@@ -0,0 +1,221 @@
1
+ // @ts-check
2
+ export {};
3
+ /** @typedef {"local" | "registry" | "upload"} NodeAppInstallSource */
4
+ /**
5
+ * @typedef {| "aggregate_shared_host"
6
+ * | "exact_cgroup"
7
+ * | "exact_isolate"
8
+ * | "exact_process"
9
+ * | "mapped_partial"
10
+ * | "self_reported"
11
+ * | "unavailable"} NodeAppMemoryAttribution
12
+ */
13
+ /** @typedef {"measured" | "stale" | "unavailable"} NodeAppMemoryAvailability */
14
+ /**
15
+ * @typedef {| "bun_heap_self_report"
16
+ * | "cgroup_v2"
17
+ * | "main_pid_smaps_rollup"
18
+ * | "main_pid_status_vm_rss"
19
+ * | "proc_smaps_mappings"
20
+ * | "proc_smaps_rollup"
21
+ * | "shared_host_residual"} NodeAppMemorySource
22
+ */
23
+ /**
24
+ * @typedef {| "cgroup_unavailable"
25
+ * | "non_linux"
26
+ * | "not_attributable"
27
+ * | "not_sampled"
28
+ * | "permission_denied"
29
+ * | "proc_unavailable"
30
+ * | "process_not_running"
31
+ * | "systemd_unavailable"} NodeAppMemoryUnavailableReason
32
+ */
33
+ /** @typedef {"dedicated" | "shared"} NodeAppRuntimeMode */
34
+ /**
35
+ * @typedef {| "active"
36
+ * | "consent_required"
37
+ * | "degraded"
38
+ * | "error"
39
+ * | "installed"
40
+ * | "lazy"
41
+ * | "restarting"
42
+ * | "stopped"} NodeAppStatus
43
+ */
44
+ /** @typedef {"bun" | "native"} NodeAppType */
45
+ /**
46
+ * @typedef {object} NodeAppMemoryReading
47
+ * @property {NodeAppMemoryAttribution} attribution
48
+ * @property {NodeAppMemoryAvailability} availability
49
+ * @property {string} observedAt
50
+ * @property {NodeAppMemoryUnavailableReason} [reason]
51
+ * @property {NodeAppMemorySource} source
52
+ * @property {number | null} valueKb
53
+ */
54
+ /**
55
+ * @typedef {object} NodeAppMemorySnapshot
56
+ * @property {NodeAppMemoryReading} heapTotal
57
+ * @property {NodeAppMemoryReading} heapUsed
58
+ * @property {NodeAppMemoryReading} external
59
+ * @property {NodeAppMemoryReading} heapCapacity
60
+ * @property {NodeAppMemoryReading} pss
61
+ * @property {NodeAppMemoryReading} rss
62
+ */
63
+ /**
64
+ * @typedef {object} NodeAppMemoryApp
65
+ * @property {NodeAppType} appType
66
+ * @property {string} author
67
+ * @property {string} description
68
+ * @property {string} id
69
+ * @property {NodeAppInstallSource} installSource
70
+ * @property {NodeAppMemorySnapshot} [memory]
71
+ * @property {string} name
72
+ * @property {NodeAppRuntimeMode} [runtimeMode]
73
+ * @property {NodeAppStatus} status
74
+ * @property {string} version
75
+ */
76
+ /**
77
+ * @typedef {object} NodeAppMemoryRepository
78
+ * @property {() => Promise<readonly NodeAppMemoryApp[]>} listApps
79
+ * @property {(id: string) => Promise<NodeAppMemoryApp | undefined>} readApp
80
+ * @property {() => Promise<NodeAppMemoryOverview>} readOverview
81
+ * @property {(id: string) => Promise<NodeAppHeapSnapshot>} captureMemorySnapshot
82
+ * @property {(id: string) => Promise<NodeAppHeapSnapshot | null>} readMemorySnapshotStatus
83
+ * @property {(id: string, snapshotId: string) => Promise<NodeAppMemoryDownload>} downloadMemorySnapshot
84
+ */
85
+
86
+ /** @typedef {{ arrayBuffer: () => Promise<ArrayBuffer>, readonly size: number, readonly type: string }} NodeAppMemoryDownload */
87
+
88
+ /** @typedef {"capturing" | "complete" | "failed"} NodeAppHeapSnapshotState */
89
+ /**
90
+ * @typedef {object} NodeAppHeapObjectTypeCount
91
+ * @property {number} count
92
+ * @property {string} objectType
93
+ * @property {number} sizeBytes
94
+ */
95
+ /**
96
+ * @typedef {object} NodeAppHeapSnapshotSummary
97
+ * @property {number} objectCount
98
+ * @property {readonly NodeAppHeapObjectTypeCount[]} objectTypes
99
+ */
100
+ /**
101
+ * @typedef {object} NodeAppHeapSnapshot
102
+ * @property {string} appId
103
+ * @property {string | null} completedAt
104
+ * @property {string} createdAt
105
+ * @property {string | null} error
106
+ * @property {string} id
107
+ * @property {number | null} sizeBytes
108
+ * @property {NodeAppHeapSnapshotState} state
109
+ * @property {NodeAppHeapSnapshotSummary | null} summary
110
+ */
111
+ /**
112
+ * @typedef {object} NodeAppLifecycleMemoryObservation
113
+ * @property {string} appId
114
+ * @property {string} observedAt
115
+ * @property {number} releasedKb
116
+ */
117
+
118
+ /** @typedef {"heap_used" | "not_attributable" | "pss" | "rss"} NodeAppMemoryBudgetBasis */
119
+ /** @typedef {"flat" | "growing" | "ratcheting" | "sawtooth" | "unknown"} NodeAppMemoryTrendVerdict */
120
+ /**
121
+ * Growth classification over the trailing sample window. `slopeKbPerHour`,
122
+ * `fitQuality`, `ratchetRatio`, `heapFloorSlopeKbPerHour`, and
123
+ * `hoursToBudget` are each omitted (not `null`) when the host did not
124
+ * compute them — mirroring the Rust `#[serde(skip_serializing_if =
125
+ * "Option::is_none")]` wire contract.
126
+ * @typedef {object} NodeAppMemoryTrend
127
+ * @property {boolean} aggregate
128
+ * @property {NodeAppMemoryBudgetBasis} basis
129
+ * @property {string} computedAt
130
+ * @property {number} [fitQuality]
131
+ * @property {number} [heapFloorSlopeKbPerHour]
132
+ * @property {number} [hoursToBudget]
133
+ * @property {number} [ratchetRatio]
134
+ * @property {number} sampleCount
135
+ * @property {number} [slopeKbPerHour]
136
+ * @property {NodeAppMemoryTrendVerdict} verdict
137
+ * @property {number} windowHours
138
+ */
139
+ /**
140
+ * @typedef {object} NodeAppMemoryCapabilityCallCount
141
+ * @property {string} capability
142
+ * @property {number} invocations
143
+ */
144
+ /**
145
+ * Capability call load over the same window as {@link NodeAppMemoryTrend}.
146
+ * @typedef {object} NodeAppMemoryActivityRollup
147
+ * @property {number} callsPerMinute
148
+ * @property {string} computedAt
149
+ * @property {number} errors
150
+ * @property {number} invocations
151
+ * @property {readonly NodeAppMemoryCapabilityCallCount[]} topCapabilities
152
+ * @property {number} windowHours
153
+ */
154
+ /** @typedef {"not_attributable" | "ok" | "over"} NodeAppBudgetState */
155
+ /** @typedef {"evicted" | "idle_countdown" | "running" | "sleeping" | "warm"} NodeAppLaneKind */
156
+ /** @typedef {"idle" | "pressure"} NodeAppTerminationReason */
157
+ /** @typedef {"evicting" | "ok" | "unknown"} NodeAppPressureState */
158
+ /**
159
+ * @typedef {object} NodeAppBudgetVerdict
160
+ * @property {boolean} aggregate
161
+ * @property {NodeAppMemoryBudgetBasis} basis
162
+ * @property {number | null} budgetKb
163
+ * @property {number | null} overByKb
164
+ * @property {NodeAppBudgetState} state
165
+ * @property {number | null} valueKb
166
+ */
167
+ /**
168
+ * @typedef {object} NodeAppGovernorRow
169
+ * @property {string} appId
170
+ * @property {string} appName
171
+ * @property {string} eligibility
172
+ * @property {number} idleSecs
173
+ * @property {number} inFlight
174
+ * @property {NodeAppLaneKind} lane
175
+ * @property {string} [lastStopAt]
176
+ * @property {NodeAppTerminationReason} [lastStopReason]
177
+ * @property {string} [lastWakeAt]
178
+ * @property {number} [minIdleSecs]
179
+ * @property {number} [secsRemaining]
180
+ * @property {NodeAppTerminationReason} [terminationReason]
181
+ */
182
+ /**
183
+ * @typedef {object} NodeAppDeviceMemory
184
+ * @property {number} highWaterKb
185
+ * @property {number} lowWaterKb
186
+ * @property {number | null} memAvailableKb
187
+ * @property {number | null} memTotalKb
188
+ * @property {number | null} psiSomeAvg10
189
+ * @property {number | null} platformRssKb
190
+ * @property {NodeAppPressureState} pressureState
191
+ * @property {number | null} swapFreeKb
192
+ * @property {number | null} swapTotalKb
193
+ */
194
+ /**
195
+ * `swapTotalKb`/`swapFreeKb` keep the same unmeasured-is-not-zero contract as
196
+ * `memAvailableKb`: `0` is a machine with no swap configured, `null` is a
197
+ * machine that could not be asked. A renderer MUST distinguish them — "no
198
+ * swap" and "we don't know" are different things to tell an owner. Swap IN USE
199
+ * is `swapTotalKb - swapFreeKb`, and is only meaningful when both are numbers.
200
+ */
201
+ /**
202
+ * @typedef {object} NodeAppMemoryOverviewApp
203
+ * @property {NodeAppMemoryActivityRollup} [activity]
204
+ * @property {NodeAppBudgetVerdict} budget
205
+ * @property {NodeAppGovernorRow} [governor]
206
+ * @property {string} id
207
+ * @property {Partial<NodeAppMemorySnapshot>} [memory]
208
+ * @property {NodeAppHeapSnapshot | null} [capture]
209
+ * @property {NodeAppLifecycleMemoryObservation | null} [lifecycleObservation]
210
+ * @property {string} name
211
+ * @property {NodeAppRuntimeMode} [runtimeMode]
212
+ * @property {NodeAppStatus} status
213
+ * @property {NodeAppMemoryTrend} [trend]
214
+ * @property {string} version
215
+ */
216
+ /**
217
+ * @typedef {object} NodeAppMemoryOverview
218
+ * @property {readonly NodeAppMemoryOverviewApp[]} apps
219
+ * @property {NodeAppDeviceMemory | null} device
220
+ * @property {NodeAppMemoryReading} [sharedHostResidual]
221
+ */
@@ -0,0 +1,27 @@
1
+ // @ts-check
2
+
3
+ /** @template {import("./durable-event.js").DurableEvent} [TEvent=import("./durable-event.js").DurableEvent] @typedef {import("./durable-event.js").RepositoryWriteResult<TEvent>} RepositoryWriteResult */
4
+ /** @typedef {import("./repository-mutation.js").RepositoryJsonValue} RepositoryJsonValue */
5
+ /** @typedef {"acknowledged" | "conflict" | "failed" | "pending" | "replaying"} OutboxRecordState */
6
+ /** @typedef {{ readonly createdAt: string, readonly domain: string, readonly id: string, readonly idempotencyKey: string, readonly payload: RepositoryJsonValue, readonly state: OutboxRecordState, readonly updatedAt: string }} OutboxRecord */
7
+ /** @typedef {OutboxRecord & { readonly attemptCount: number, readonly leaseExpiresAt: string, readonly leaseToken: string, readonly state: "replaying" }} OutboxReplayClaim */
8
+ /** @typedef {{ readonly attemptCount: number, readonly createdAt: string, readonly domain: string, readonly id: string, readonly lastErrorCode?: string, readonly lastErrorMessage?: string, readonly nextAttemptAt?: string, readonly settledAt?: string, readonly state: OutboxRecordState, readonly terminalErrorCode?: string, readonly terminalErrorMessage?: string, readonly updatedAt: string }} OutboxReplayStatus */
9
+ /** @typedef {{ readonly id: string, readonly leaseToken: string, readonly outcome: "acknowledged" } | { readonly error: { readonly code: string, readonly message: string }, readonly id: string, readonly leaseToken: string, readonly outcome: "conflict" | "failed" } | { readonly error: { readonly code: string, readonly message: string }, readonly id: string, readonly leaseToken: string, readonly outcome: "retry", readonly retryAt: string }} OutboxSettleInput */
10
+ /** @typedef {{ readonly occurredAt: string, readonly payload: { readonly intent: OutboxRecord }, readonly type: "outbox.state-changed" }} OutboxStateChangedEvent */
11
+ /** @typedef {{ readonly occurredAt: string, readonly payload: { readonly action: "deleted", readonly entityId: string, readonly entityType: "outbox-intent" }, readonly type: "domain.entity-changed" }} OutboxDeletedEvent */
12
+ /** @typedef {OutboxDeletedEvent | OutboxStateChangedEvent} OutboxRepositoryEvent */
13
+ /** @typedef {{ readonly domain?: string, readonly state?: OutboxRecordState }} OutboxRepositoryFilter */
14
+
15
+ export class OutboxIdempotencyConflictError extends Error {
16
+ /** @readonly @type {string} */
17
+ idempotencyKey;
18
+
19
+ /** @param {string} idempotencyKey */
20
+ constructor(idempotencyKey) {
21
+ super("Outbox idempotency key belongs to a different command");
22
+ this.name = "OutboxIdempotencyConflictError";
23
+ this.idempotencyKey = idempotencyKey;
24
+ }
25
+ }
26
+
27
+ /** @typedef {{ claimHead?(input: { readonly domain: string, readonly leaseExpiresAt: string, readonly leaseToken: string }): Promise<OutboxReplayClaim | undefined>, create(input: OutboxRecord): Promise<RepositoryWriteResult<OutboxRepositoryEvent>>, delete(id: string): Promise<RepositoryWriteResult<OutboxRepositoryEvent>>, list(filter?: OutboxRepositoryFilter): Promise<readonly OutboxRecord[]>, read(id: string): Promise<OutboxRecord | undefined>, listStatus?(filter?: { readonly domain?: string }): Promise<readonly OutboxReplayStatus[]>, settle?(input: OutboxSettleInput): Promise<RepositoryWriteResult<OutboxRepositoryEvent>>, updateState(id: string, state: OutboxRecordState): Promise<RepositoryWriteResult<OutboxRepositoryEvent>> }} OutboxRepository */
@@ -0,0 +1,8 @@
1
+ // @ts-check
2
+
3
+ /** @typedef {boolean | null | number | string} RepositoryJsonPrimitive */
4
+ /** @typedef {RepositoryJsonPrimitive | RepositoryJsonArray | RepositoryJsonObject} RepositoryJsonValue */
5
+ /** @typedef {RepositoryJsonValue[]} RepositoryJsonArray */
6
+ /** @typedef {{ readonly [key: string]: RepositoryJsonValue }} RepositoryJsonObject */
7
+
8
+ export {};
@@ -0,0 +1,17 @@
1
+ // @ts-check
2
+
3
+ /** @typedef {import("./repository-mutation.js").RepositoryJsonValue} RepositoryJsonValue */
4
+ /** @template {import("./durable-event.js").DurableEvent} [TEvent=import("./durable-event.js").DurableEvent] @typedef {import("./durable-event.js").RepositoryWriteResult<TEvent>} RepositoryWriteResult */
5
+
6
+ export const REVISIONED_REPOSITORY_DOMAINS = /** @type {const} */ (["agent", "settings", "graph"]);
7
+ /** @typedef {typeof REVISIONED_REPOSITORY_DOMAINS[number]} RevisionedRepositoryDomain */
8
+ /** @template {RepositoryJsonValue} [TValue=RepositoryJsonValue] @typedef {{ readonly id: string, readonly rev: number, readonly value: TValue }} RevisionedEntity */
9
+ /** @template {RepositoryJsonValue} [TValue=RepositoryJsonValue] @typedef {{ readonly baseRev: number, readonly id: string, readonly idempotencyKey: string, readonly value: TValue }} RevisionCommand */
10
+ /** @template {RepositoryJsonValue} [TValue=RepositoryJsonValue] @typedef {{ readonly entity: RevisionedEntity<TValue>, readonly status: "accepted" } | { readonly status: "conflict", readonly theirs: RevisionedEntity<TValue> }} RevisionCommandResult */
11
+ /** @typedef {{ readonly occurredAt: string, readonly payload: { readonly action: "created" | "updated", readonly entityId: string, readonly entityType: "agent" | "graph" | "setting" }, readonly type: "domain.entity-changed" }} RevisionedRepositoryEvent */
12
+ /** @template {RepositoryJsonValue} [TValue=RepositoryJsonValue] @typedef {{ apply(entity: RevisionedEntity<TValue>): Promise<RepositoryWriteResult<RevisionedRepositoryEvent>>, command(input: RevisionCommand<TValue>): Promise<RevisionCommandResult<TValue>>, list(): Promise<readonly RevisionedEntity<TValue>[]>, read(id: string): Promise<RevisionedEntity<TValue> | undefined> }} RevisionedRepository */
13
+ /** @typedef {RevisionedRepository} AgentRepository */
14
+ /** @typedef {RevisionedRepository} RevisionedSettingsRepository */
15
+ /** @typedef {RevisionedRepository} GraphRepository */
16
+
17
+ export {};
@@ -0,0 +1,10 @@
1
+ // @ts-check
2
+
3
+ /** @template {import("./durable-event.js").DurableEvent} [TEvent=import("./durable-event.js").DurableEvent] @typedef {import("./durable-event.js").RepositoryWriteResult<TEvent>} RepositoryWriteResult */
4
+ /** @typedef {import("./repository-mutation.js").RepositoryJsonValue} RepositoryJsonValue */
5
+ /** @typedef {{ readonly key: string, readonly updatedAt: string, readonly value: RepositoryJsonValue }} SettingRecord */
6
+ /** @typedef {{ readonly key: string, readonly value: RepositoryJsonValue }} SettingInput */
7
+ /** @typedef {{ readonly occurredAt: string, readonly payload: { readonly action: "created" | "deleted" | "updated", readonly entityId: string, readonly entityType: "setting" }, readonly type: "domain.entity-changed" }} SettingsRepositoryEvent */
8
+ /** @typedef {{ delete(key: string): Promise<RepositoryWriteResult<SettingsRepositoryEvent>>, list(): Promise<readonly SettingRecord[]>, read(key: string): Promise<SettingRecord | undefined>, set(input: SettingInput): Promise<RepositoryWriteResult<SettingsRepositoryEvent>> }} SettingsRepository */
9
+
10
+ export {};
@@ -0,0 +1,11 @@
1
+ // @ts-check
2
+
3
+ /** @template {import("./durable-event.js").DurableEvent} [TEvent=import("./durable-event.js").DurableEvent] @typedef {import("./durable-event.js").RepositoryWriteResult<TEvent>} RepositoryWriteResult */
4
+ /** @typedef {{ readonly cursor: string, readonly domain: string }} SyncLedgerInput */
5
+ /** @typedef {SyncLedgerInput & { readonly updatedAt: string }} SyncLedgerRecord */
6
+ /** @typedef {{ readonly occurredAt: string, readonly payload: SyncLedgerInput, readonly type: "sync.delta-applied" }} SyncDeltaAppliedEvent */
7
+ /** @typedef {{ readonly occurredAt: string, readonly payload: { readonly action: "deleted", readonly entityId: string, readonly entityType: "sync-cursor" }, readonly type: "domain.entity-changed" }} SyncCursorDeletedEvent */
8
+ /** @typedef {SyncCursorDeletedEvent | SyncDeltaAppliedEvent} SyncLedgerRepositoryEvent */
9
+ /** @typedef {{ delete(domain: string): Promise<RepositoryWriteResult<SyncLedgerRepositoryEvent>>, list(): Promise<readonly SyncLedgerRecord[]>, read(domain: string): Promise<SyncLedgerRecord | undefined>, setCursor(input: SyncLedgerInput): Promise<RepositoryWriteResult<SyncLedgerRepositoryEvent>> }} SyncLedgerRepository */
10
+
11
+ export {};
@@ -0,0 +1,73 @@
1
+ // @ts-check
2
+
3
+ /** @typedef {{ readonly amountMsat: number, readonly createdAt: string, readonly direction: "incoming" | "outgoing", readonly failureCode?: string, readonly id: string, readonly paymentHash?: string, readonly status: "pending" | "succeeded" | "failed" | "expired", readonly updatedAt: string }} WalletPaymentRecord */
4
+ /** @typedef {{ readonly amountMsat: number, readonly paidAt: string, readonly paymentHash?: string, readonly receiptId: string, readonly resource: string }} WalletL402Receipt */
5
+ /** @typedef {{ readonly balanceMsat: number, readonly l402: readonly WalletL402Receipt[], readonly payments: readonly WalletPaymentRecord[], readonly spendableMsat: number }} WalletSnapshotValue */
6
+ /** @typedef {{ readonly observedAt: string, readonly staleAt: string, readonly value: WalletSnapshotValue }} WalletAuthoritativeSnapshot */
7
+ /** @typedef {{ readonly amountMsat: number, readonly invoiceId: string, readonly kind: "invoice-created", readonly paymentHash?: string, readonly paymentRequest: string, readonly status: "created" } | { readonly amountMsat: number, readonly kind: "payment-submitted", readonly paymentHash?: string, readonly paymentId: string, readonly status: "pending" | "succeeded" | "failed" }} WalletCommandResult */
8
+ /** @typedef {{ readCommandResult(idempotencyKey: string): Promise<WalletCommandResult | undefined>, readSnapshot(): Promise<WalletAuthoritativeSnapshot | undefined>, writeCommandResult(idempotencyKey: string, result: WalletCommandResult): Promise<void>, writeSnapshot(snapshot: WalletAuthoritativeSnapshot): Promise<void> }} WalletMirrorRepository */
9
+
10
+ /** @param {unknown} value @returns {value is WalletSnapshotValue} */
11
+ export function isWalletSnapshotValue(value) {
12
+ if (!isRecord(value) || !hasOnlyKeys(value, ["balanceMsat", "l402", "payments", "spendableMsat"]) ||
13
+ !isNonNegativeNumber(value.balanceMsat) || !isNonNegativeNumber(value.spendableMsat)) return false;
14
+ return Array.isArray(value.payments) && value.payments.every(isWalletPaymentRecord) &&
15
+ Array.isArray(value.l402) && value.l402.every(isWalletL402Receipt);
16
+ }
17
+
18
+ /** @param {unknown} value @returns {value is WalletAuthoritativeSnapshot} */
19
+ export function isWalletAuthoritativeSnapshot(value) {
20
+ return isRecord(value) && hasOnlyKeys(value, ["observedAt", "staleAt", "value"]) &&
21
+ typeof value.observedAt === "string" && typeof value.staleAt === "string" &&
22
+ isWalletSnapshotValue(value.value);
23
+ }
24
+
25
+ /** @param {unknown} value @returns {value is WalletCommandResult} */
26
+ export function isWalletCommandResult(value) {
27
+ if (!isRecord(value) || !isNonNegativeNumber(value.amountMsat)) return false;
28
+ if (value.kind === "invoice-created") {
29
+ return hasOnlyKeys(value, ["amountMsat", "invoiceId", "kind", "paymentHash", "paymentRequest", "status"]) &&
30
+ value.status === "created" && typeof value.invoiceId === "string" && typeof value.paymentRequest === "string" &&
31
+ (value.paymentHash === undefined || typeof value.paymentHash === "string");
32
+ }
33
+ return hasOnlyKeys(value, ["amountMsat", "kind", "paymentHash", "paymentId", "status"]) &&
34
+ value.kind === "payment-submitted" &&
35
+ (value.status === "pending" || value.status === "succeeded" || value.status === "failed") &&
36
+ typeof value.paymentId === "string" &&
37
+ (value.paymentHash === undefined || typeof value.paymentHash === "string");
38
+ }
39
+
40
+ /** @param {unknown} value @returns {value is WalletPaymentRecord} */
41
+ function isWalletPaymentRecord(value) {
42
+ if (!isRecord(value) || !isNonNegativeNumber(value.amountMsat) || typeof value.createdAt !== "string" ||
43
+ typeof value.id !== "string" || typeof value.updatedAt !== "string" ||
44
+ !hasOnlyKeys(value, ["amountMsat", "createdAt", "direction", "failureCode", "id", "paymentHash", "status", "updatedAt"])) return false;
45
+ return (value.direction === "incoming" || value.direction === "outgoing") &&
46
+ (value.status === "pending" || value.status === "succeeded" || value.status === "failed" || value.status === "expired") &&
47
+ (value.failureCode === undefined || typeof value.failureCode === "string") &&
48
+ (value.paymentHash === undefined || typeof value.paymentHash === "string");
49
+ }
50
+
51
+ /** @param {unknown} value @returns {value is WalletL402Receipt} */
52
+ function isWalletL402Receipt(value) {
53
+ return isRecord(value) && hasOnlyKeys(value, ["amountMsat", "paidAt", "paymentHash", "receiptId", "resource"]) &&
54
+ isNonNegativeNumber(value.amountMsat) && typeof value.paidAt === "string" &&
55
+ typeof value.receiptId === "string" && typeof value.resource === "string" &&
56
+ (value.paymentHash === undefined || typeof value.paymentHash === "string");
57
+ }
58
+
59
+ /** @param {unknown} value @returns {value is number} */
60
+ function isNonNegativeNumber(value) {
61
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
62
+ }
63
+
64
+ /** @param {unknown} value @returns {value is Record<string, unknown>} */
65
+ function isRecord(value) {
66
+ return value !== null && typeof value === "object" && !Array.isArray(value);
67
+ }
68
+
69
+ /** @param {Record<string, unknown>} value @param {readonly string[]} allowed @returns {boolean} */
70
+ function hasOnlyKeys(value, allowed) {
71
+ const allowedKeys = new Set(allowed);
72
+ return Object.keys(value).every((key) => allowedKeys.has(key));
73
+ }
@@ -0,0 +1,22 @@
1
+ // @ts-check
2
+
3
+ /** @typedef {{ readonly entry: string, readonly integrity: Readonly<Record<string, string>>, readonly requires: readonly string[], readonly version: string }} StageManifest */
4
+ /** @typedef {"last-known" | "online-only"} AppDataOfflinePolicy */
5
+ /** @typedef {"collection" | "detail" | "snapshot"} AppDataQueryKind */
6
+ /** @typedef {"changes" | "events"} AppDataStreamKind */
7
+ /** @typedef {"cursor" | "snapshot"} AppDataSyncKind */
8
+ /** @typedef {{ readonly cursorTtlSecs?: number, readonly fullRefreshIntervalSecs?: number, readonly kind: AppDataSyncKind, readonly retentionSecs?: number }} AppDataSyncPolicy */
9
+ /** @typedef {{ readonly capability: string, readonly kind: AppDataQueryKind, readonly name: string }} AppDataQueryDeclaration */
10
+ /** @typedef {{ readonly kind: AppDataStreamKind, readonly name: string }} AppDataStreamDeclaration */
11
+ /** @typedef {{ readonly namespace: string, readonly offline: AppDataOfflinePolicy, readonly queries: readonly AppDataQueryDeclaration[], readonly streams: readonly AppDataStreamDeclaration[], readonly sync: AppDataSyncPolicy }} AppDataManifest */
12
+ /** @typedef {"stage" | "widget"} StageUiKind */
13
+ /** @typedef {{ readonly order: number, readonly section: string }} StageUiNav */
14
+ /** @typedef {{ readonly capabilities: readonly string[], readonly queries: readonly string[], readonly streams: readonly string[] }} StageUiRequirements */
15
+ /** @typedef {{ readonly composes: readonly string[], readonly icon?: string, readonly kind: StageUiKind, readonly nav?: StageUiNav, readonly requires?: StageUiRequirements, readonly title: string, readonly uiApi: 1 | 2 }} StageUiMetadata */
16
+ /** @typedef {{ readonly appName: string, readonly assetBase: string, readonly data?: AppDataManifest, readonly description?: string, readonly keywords?: readonly string[], readonly manifest: StageManifest, readonly manifestSha256: string, readonly ui: StageUiMetadata }} StageCatalogEntry */
17
+ /** @typedef {{ readonly entries: readonly StageCatalogEntry[], readonly revision: string }} StageRegistrySnapshot */
18
+ /** @typedef {{ read(): Promise<StageRegistrySnapshot | undefined>, write(snapshot: StageRegistrySnapshot): Promise<void> }} StageRegistryPort */
19
+ /** @typedef {{ readonly appName: string, readonly entryUrl: string, readonly manifestSha256: string, readonly version: string }} PreparedStageAsset */
20
+ /** @typedef {{ prepare(appName: string, manifest: StageManifest): Promise<PreparedStageAsset> }} StageAssetPort */
21
+
22
+ export {};
@@ -0,0 +1,6 @@
1
+ // @ts-check
2
+
3
+ /** @typedef {{ readonly cadenceMs?: number, readonly dueAt: string, readonly name: string, run(): Promise<void> }} ScheduledJob */
4
+ /** @typedef {{ cancel(name: string): void, register(job: ScheduledJob): void, shutdown(): Promise<void> }} SchedulerPort */
5
+
6
+ export {};
@@ -0,0 +1,48 @@
1
+ // @ts-check
2
+ export {};
3
+ /**
4
+ * Boundary port for the one boolean flag `system/pwa/src/main.ts` needs out of
5
+ * `sessionStorage` before the shell exists: the "Continue in browser" escape hatch
6
+ * (`CONTINUE_IN_BROWSER_KEY`, `system/pwa/src/boot-gate.ts`) that the install landing's
7
+ * "Continue in browser" button sets, and that the top-level boot-gate computation reads back
8
+ * on the next navigation this session.
9
+ *
10
+ * The composition root (`system/pwa/src/main.ts`) may not name `sessionStorage` directly
11
+ * (boundary rules B3/B4, `client/scripts/check-boundaries.mjs`) — this is the narrow surface
12
+ * `client/adapters-web`'s `createBrowserSessionFlag()` implements against the real global,
13
+ * constructed and called directly from `main.ts`, mirroring `ClipboardPort`'s and
14
+ * `MediaPreferencesPort`'s seams.
15
+ *
16
+ * Deliberately NOT routed through one of `client/ui`'s `configureX`/`currentX()` module-level
17
+ * slots the way `ClipboardPort`/`MediaPreferencesPort` are: those ports back calls made FROM
18
+ * `client/ui` (an onboarding screen's paste button, the shell's hover/motion checks), so
19
+ * `client/ui` needs somewhere to read an injected implementation from. Both call sites for
20
+ * this flag — `renderInstallLanding()`'s `onContinue` handler and the top-level
21
+ * `bootShellNow` computation — live in `main.ts` itself, before `<node-app-shell>` or
22
+ * `<node-install-landing>` ever mounts, so there is no `client/ui` consumer to inject into;
23
+ * the composition root simply constructs the adapter and calls it directly, the same way it
24
+ * already does for `InstallEnvironmentPort`'s `installEnv.isStandalone()`.
25
+ *
26
+ * Deliberately synchronous: the read backs `bootShellNow`, a top-level, synchronous
27
+ * computation in `main.ts` made before the kernel/RPC bridge exists (see `boot-gate.ts`'s own
28
+ * doc comment on `BootGateInputs`) — turning it async would restructure the whole boot path
29
+ * for a nicer port shape, which is not this port's job. `MediaPreferencesPort`'s two methods
30
+ * are synchronous for the identical reason: both are read before any RPC bridge exists.
31
+ *
32
+ * Both methods degrade to the SAME safe default the pre-extraction inline `try`/`catch`
33
+ * blocks in `main.ts` documented — reading or writing `sessionStorage` can throw under
34
+ * strict privacy modes (Safari private browsing, some content blockers), AND merely
35
+ * accessing the `sessionStorage` property itself can throw a `SecurityError` in other
36
+ * locked-down embedders (Firefox/Chrome "block all cookies", an `<iframe sandbox>` without
37
+ * `allow-same-origin`) — the adapter constructor guards the latter the same way its
38
+ * `getItem`/`setItem` calls guard the former, so losing the flag must never block booting
39
+ * the shell, nor may it ever throw and abort evaluation of the composition root:
40
+ * - `read()` returns `false` both when the flag was never set AND when the read itself
41
+ * failed — the "the flag never stuck" outcome, which simply shows the install landing
42
+ * again next time, exactly the pre-existing behavior.
43
+ * - `set()` swallows a failed write silently; the visitor already asked to continue in the
44
+ * browser and a storage failure must not stand in the way of that.
45
+ * @typedef {object} SessionFlagPort
46
+ * @property {(key: string) => boolean} read
47
+ * @property {(key: string) => void} set
48
+ */
@@ -0,0 +1,3 @@
1
+ // @ts-check
2
+ /** @typedef {{ reset(): void }} ShellCacheResetPort */
3
+ export {};
@@ -0,0 +1,4 @@
1
+ // @ts-check
2
+ /** @typedef {{ readonly available: string | undefined, readonly running: string | undefined }} ShellVersionReport */
3
+ /** @typedef {{ read(): Promise<ShellVersionReport> }} ShellVersionPort */
4
+ export {};
package/src/storage.js ADDED
@@ -0,0 +1,60 @@
1
+ // @ts-check
2
+
3
+ /** @typedef {import("./repositories.js").StageRegistryPort} StageRegistryPort */
4
+ /** @typedef {import("./repositories/conversation-repository.js").ConversationRepository} ConversationRepository */
5
+ /** @typedef {import("./repositories/conversation-repository.js").NotificationRepository} NotificationRepository */
6
+ /** @typedef {import("./repositories/conversation-repository.js").RepositoryEvent} RepositoryEvent */
7
+ /** @typedef {import("./repositories/outbox.js").OutboxRepository} OutboxRepository */
8
+ /** @typedef {import("./repositories/outbox.js").OutboxRepositoryEvent} OutboxRepositoryEvent */
9
+ /** @typedef {import("./repositories/settings.js").SettingsRepository} SettingsRepository */
10
+ /** @typedef {import("./repositories/settings.js").SettingsRepositoryEvent} SettingsRepositoryEvent */
11
+ /** @typedef {import("./repositories/sync-ledger.js").SyncLedgerRepository} SyncLedgerRepository */
12
+ /** @typedef {import("./repositories/sync-ledger.js").SyncLedgerRepositoryEvent} SyncLedgerRepositoryEvent */
13
+ /** @typedef {import("./repositories/revisioned-repository.js").AgentRepository} AgentRepository */
14
+ /** @typedef {import("./repositories/revisioned-repository.js").GraphRepository} GraphRepository */
15
+ /** @typedef {import("./repositories/revisioned-repository.js").RevisionedRepositoryEvent} RevisionedRepositoryEvent */
16
+ /** @typedef {import("./repositories/revisioned-repository.js").RevisionedSettingsRepository} RevisionedSettingsRepository */
17
+ /** @typedef {import("./repositories/wallet-mirror-repository.js").WalletMirrorRepository} WalletMirrorRepository */
18
+ /** @typedef {import("./offline-readiness.js").OfflineProjectionRepository} OfflineProjectionRepository */
19
+ /** @typedef {import("./offline-readiness.js").OfflineIdentityScope} OfflineIdentityScope */
20
+ /** @typedef {import("./offline-readiness.js").OfflineStageRepository} OfflineStageRepository */
21
+
22
+ export const RESET_LOCAL_STORAGE_CONFIRMATION = "RESET LOCAL CLIENT DATA";
23
+ /** @typedef {"checksum-drift" | "corrupt" | "diagnostic-failed" | "identity-source-unavailable" | "migration-failed" | "opfs-unavailable" | "quota-exceeded" | "worker-operation-timeout" | "worker-preparation-timeout" | "writer-conflict"} StorageRecoveryCode */
24
+
25
+ /** @satisfies {Readonly<Record<StorageRecoveryCode, string>>} */
26
+ export const STORAGE_RECOVERY_MESSAGES = /** @type {const} */ ({
27
+ "checksum-drift": "Local schema history does not match this client build",
28
+ corrupt: "Local SQLite data failed its integrity check",
29
+ "diagnostic-failed": "Encrypted storage diagnostic creation failed",
30
+ "identity-source-unavailable": "Protected identity metadata is temporarily unavailable",
31
+ "migration-failed": "Local SQLite schema migration failed",
32
+ "opfs-unavailable": "Persistent browser storage is unavailable",
33
+ "quota-exceeded": "Persistent browser storage quota is exhausted",
34
+ "worker-operation-timeout": "Persistent storage operation timed out",
35
+ "worker-preparation-timeout": "Protected storage request preparation timed out",
36
+ "writer-conflict": "Another client-node storage writer is active",
37
+ });
38
+
39
+ export class StorageOperationError extends Error {
40
+ /**
41
+ * @param {StorageRecoveryCode} code
42
+ */
43
+ constructor(code) {
44
+ super("Persistent storage operation failed");
45
+ this.name = "StorageOperationError";
46
+ /** @readonly */
47
+ this.code = code;
48
+ }
49
+ }
50
+
51
+ /** @typedef {{ readonly schemaVersion: number, readonly storageGeneration?: number, readonly status: "ready" }} StorageReadyState */
52
+ /** @typedef {{ readonly schemaVersion: number, readonly storageGeneration?: number, readonly status: "starting" }} StorageStartingState */
53
+ /** @typedef {{ readonly actions: { readonly exportDiagnostic: boolean, readonly reset: true, readonly retry: true }, readonly code: StorageRecoveryCode, readonly message: string, readonly schemaVersion: number, readonly storageGeneration?: number, readonly status: "recovery-required" }} StorageRecoveryRequiredState */
54
+ /** @typedef {StorageReadyState | StorageRecoveryRequiredState | StorageStartingState} StorageRecoveryState */
55
+ /** @typedef {{ readonly algorithm: "AES-GCM", readonly ciphertextBase64: string, readonly createdAt: string, readonly format: "node-client-sqlite-diagnostic-v1", readonly ivBase64: string, readonly kdf: { readonly hash: "SHA-256", readonly iterations: 310000, readonly name: "PBKDF2", readonly saltBase64: string } }} EncryptedStorageDiagnostic */
56
+ /** @typedef {{ readonly offlineProjections: OfflineProjectionRepository, readonly offlineStages: OfflineStageRepository, readonly outbox: OutboxRepository, readonly syncLedger: SyncLedgerRepository }} IdentityScopedStorageRepositoryPort */
57
+ /** @typedef {{ readonly repositories: StorageRepositoryPort, clearActiveIdentityProjections(): Promise<void>, clearScope(scope: OfflineIdentityScope): Promise<void>, close(): Promise<void>, exportEncryptedDiagnostic(options: { readonly passphrase: string }): Promise<EncryptedStorageDiagnostic>, initialize(): Promise<StorageRecoveryState>, reactivateEmptyScope(scope: OfflineIdentityScope): Promise<boolean>, referencedAssetRevisions(): Promise<readonly string[]>, refreshIdentityMetadata(): Promise<void>, recoveryState(): Promise<StorageRecoveryState>, reset(options: { readonly confirmation: string }): Promise<StorageRecoveryState>, retry(): Promise<StorageRecoveryState>, scopedRepositories(scope: OfflineIdentityScope): IdentityScopedStorageRepositoryPort, subscribeRecoveryState(listener: (state: StorageRecoveryState) => void): () => void }} StorageDatabasePort */
58
+ /** @typedef {OutboxRepositoryEvent | RepositoryEvent | RevisionedRepositoryEvent | SettingsRepositoryEvent | SyncLedgerRepositoryEvent} StorageRepositoryEvent */
59
+ /** @typedef {{ readonly conversations?: ConversationRepository, readonly events: import("./repositories/durable-event.js").DurableRepositoryEventStore<StorageRepositoryEvent>, readonly notifications?: NotificationRepository, readonly agents?: AgentRepository, readonly graphs?: GraphRepository, readonly outbox: OutboxRepository, readonly revisionedSettings?: RevisionedSettingsRepository, readonly wallet?: WalletMirrorRepository, readonly settings: SettingsRepository, readonly syncLedger: SyncLedgerRepository }} StorageRepositoryPort */
60
+ /** @typedef {StorageDatabasePort & { readonly stages: StageRegistryPort }} StoragePort */
package/src/theme.js ADDED
@@ -0,0 +1,21 @@
1
+ // @ts-check
2
+
3
+ /** @typedef {"light" | "dark"} ThemePreference */
4
+
5
+ /**
6
+ * Boundary port for the shell's dark-mode plumbing (`client/ui/src/shell/theme-init.ts`).
7
+ *
8
+ * `client/ui` may never call `localStorage` or `matchMedia` directly (boundary rules
9
+ * B2/B3, `client/scripts/check-boundaries.mjs`) — this is the narrow surface
10
+ * `client/adapters-web`'s `createBrowserThemeEnvironment()` implements against the real
11
+ * globals, and the composition root (`system/pwa/src/main.ts`) registers it (via
12
+ * `client/ui`'s `configureThemeEnvironment`) before the shell's first paint. Every method is
13
+ * synchronous and side-effect-free beyond the read/write it names — `theme-init.ts`'s
14
+ * anti-FOUC contract requires resolving the initial theme before the shadow tree's first
15
+ * paint, which is before the kernel connection (`KernelRpcClient`, itself an async
16
+ * `SharedWorker`/leader-tab bridge) even exists, so this can never be mediated through
17
+ * `@econ-v1/rpc` the way ordinary UI reads/writes are (rule S4).
18
+ */
19
+ /** @typedef {{ getStoredTheme(): ThemePreference | undefined, setStoredTheme(preference: ThemePreference): void, prefersDarkColorScheme(): boolean, watchDarkColorScheme(onChange: (matches: boolean) => void): (() => void) | undefined }} ThemeEnvironmentPort */
20
+
21
+ export {};
package/dist/clock.js DELETED
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=clock.js.map
package/dist/clock.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"clock.js","sourceRoot":"","sources":["../src/clock.ts"],"names":[],"mappings":""}
package/dist/crypto.js DELETED
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=crypto.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":""}
package/dist/id.js DELETED
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=id.js.map
package/dist/id.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"id.js","sourceRoot":"","sources":["../src/id.ts"],"names":[],"mappings":""}
package/dist/identity.js DELETED
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=identity.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":""}
package/dist/index.js DELETED
@@ -1,9 +0,0 @@
1
- export { createNullInstallEnvironment, } from "./install-environment.js";
2
- export { DEFAULT_CLIENT_NODE_ORIGIN } from "./network/client-node-origin.js";
3
- export { MAX_CLOSE_REASON_BYTES, MAX_DTLS_FINGERPRINT_BYTES, MAX_ICE_CANDIDATE_BYTES, MAX_ICE_CANDIDATES_PER_OFFER, MAX_OFFER_NONCE_BYTES, MAX_SDP_BYTES, MAX_SDP_MID_BYTES, MAX_WEBRTC_SIGNAL_MESSAGE_BYTES, MIN_OFFER_NONCE_BYTES, WEBRTC_SIGNAL_VERSION, } from "./network/webrtc-signaling.js";
4
- export { CONVERSATION_MESSAGE_STATES } from "./repositories/conversation-repository.js";
5
- export { OutboxIdempotencyConflictError } from "./repositories/outbox.js";
6
- export { REVISIONED_REPOSITORY_DOMAINS, } from "./repositories/revisioned-repository.js";
7
- export { isWalletAuthoritativeSnapshot, isWalletCommandResult, isWalletSnapshotValue, } from "./repositories/wallet-mirror-repository.js";
8
- export { RESET_LOCAL_STORAGE_CONFIRMATION, STORAGE_RECOVERY_MESSAGES } from "./storage.js";
9
- //# sourceMappingURL=index.js.map
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,4BAA4B,GAC7B,MAAM,0BAA0B,CAAC;AAqBlC,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAW7E,OAAO,EACL,sBAAsB,EACtB,0BAA0B,EAC1B,uBAAuB,EACvB,4BAA4B,EAC5B,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,+BAA+B,EAC/B,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AAsBvC,OAAO,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AAsBxF,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AA+B1E,OAAO,EACL,6BAA6B,GAC9B,MAAM,yCAAyC,CAAC;AAYjD,OAAO,EACL,6BAA6B,EAC7B,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,4CAA4C,CAAC;AAYpD,OAAO,EAAE,gCAAgC,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC"}