p2party 0.14.2 → 0.14.7

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 (126) hide show
  1. package/README.md +230 -30
  2. package/docs/getting-started.md +15 -0
  3. package/docs/protocol-v4-security.md +40 -0
  4. package/docs/references.md +28 -8
  5. package/docs/session-api.md +10 -2
  6. package/lib/api/signalingServerApi.d.ts +13 -2
  7. package/lib/api/webrtc/applyIceConfiguration.d.ts +9 -0
  8. package/lib/api/webrtc/dataChannelHandler.d.ts +10 -0
  9. package/lib/api/webrtc/deleteRoomData.d.ts +13 -0
  10. package/lib/api/webrtc/disconnectFromAllRoomsQuery.d.ts +2 -1
  11. package/lib/api/webrtc/disconnectFromRoomQuery.d.ts +2 -1
  12. package/lib/api/webrtc/disconnectQuery.d.ts +2 -1
  13. package/lib/api/webrtc/iceRepair.d.ts +3 -1
  14. package/lib/api/webrtc/index.d.ts +2 -1
  15. package/lib/api/webrtc/interfaces.d.ts +37 -0
  16. package/lib/api/webrtc/negotiationLock.d.ts +24 -0
  17. package/lib/api/webrtc/pendingOffer.d.ts +29 -0
  18. package/lib/api/webrtc/rebindDeadline.d.ts +61 -0
  19. package/lib/api/webrtc/remoteTransportChange.d.ts +142 -0
  20. package/lib/api/webrtc/retiredRemoteTransports.d.ts +70 -0
  21. package/lib/api/webrtc/roomEdgeBudget.d.ts +10 -0
  22. package/lib/api/webrtc/setDescriptionQuery.d.ts +8 -1
  23. package/lib/api/webrtc/settleOnClose.d.ts +36 -0
  24. package/lib/blindRendezvous/admissionInput.d.ts +11 -0
  25. package/lib/blindRendezvous/admissionPolicy.d.ts +217 -0
  26. package/lib/blindRendezvous/canonicalSchema.d.ts +139 -0
  27. package/lib/blindRendezvous/carrierEnvelope.d.ts +105 -0
  28. package/lib/blindRendezvous/coreReduce.d.ts +199 -0
  29. package/lib/blindRendezvous/derivations.d.ts +381 -0
  30. package/lib/blindRendezvous/identityHelloAdmission.d.ts +89 -0
  31. package/lib/blindRendezvous/identityHelloAdmissionPersistence.d.ts +133 -0
  32. package/lib/blindRendezvous/identityHelloHistoricalEvidence.d.ts +52 -0
  33. package/lib/blindRendezvous/identityHelloOpen.d.ts +167 -0
  34. package/lib/blindRendezvous/identityHelloTrial.d.ts +271 -0
  35. package/lib/blindRendezvous/localAdmissibleProject.d.ts +101 -0
  36. package/lib/blindRendezvous/localPresenceKeyBinding.d.ts +108 -0
  37. package/lib/blindRendezvous/localStableIdentityCustody.d.ts +46 -0
  38. package/lib/blindRendezvous/normativeKernel.d.ts +222 -0
  39. package/lib/blindRendezvous/operation.d.ts +137 -0
  40. package/lib/blindRendezvous/operationPayload.d.ts +134 -0
  41. package/lib/blindRendezvous/pairBootstrapSuite.d.ts +93 -0
  42. package/lib/blindRendezvous/pairCrypto.d.ts +122 -0
  43. package/lib/blindRendezvous/pairLedger.d.ts +154 -0
  44. package/lib/blindRendezvous/pairOpenBudget.d.ts +67 -0
  45. package/lib/blindRendezvous/pairOpenReservation.d.ts +157 -0
  46. package/lib/blindRendezvous/pairPlaintext.d.ts +240 -0
  47. package/lib/blindRendezvous/pairStepEnvelope.d.ts +60 -0
  48. package/lib/blindRendezvous/plannerState.d.ts +61 -0
  49. package/lib/blindRendezvous/projections.d.ts +71 -0
  50. package/lib/blindRendezvous/publicWindow.d.ts +330 -0
  51. package/lib/blindRendezvous/retainedOperationStore.d.ts +187 -0
  52. package/lib/blindRendezvous/roomInviteV2.d.ts +92 -0
  53. package/lib/blindRendezvous/roomPolicyV4.d.ts +90 -0
  54. package/lib/blindRendezvous/schemas.d.ts +221 -0
  55. package/lib/blindRendezvous/storeDescriptor.d.ts +160 -0
  56. package/lib/cryptography/aeadWasm.d.ts +18 -0
  57. package/lib/cryptography/byteInput.d.ts +12 -0
  58. package/lib/cryptography/carrierAead.d.ts +23 -0
  59. package/lib/cryptography/chacha20poly1305.d.ts +7 -0
  60. package/lib/cryptography/fips202.d.ts +10 -0
  61. package/lib/cryptography/hpke.d.ts +84 -0
  62. package/lib/cryptography/hpkeSuite.d.ts +39 -0
  63. package/lib/cryptography/hybridKem.d.ts +42 -0
  64. package/lib/cryptography/hybridKemSuite.d.ts +22 -0
  65. package/lib/cryptography/interfaces.d.ts +3 -0
  66. package/lib/cryptography/mlkem.d.ts +27 -1
  67. package/lib/cryptography/mnemonic.d.ts +65 -1
  68. package/lib/cryptography/ownedEd25519KeyMaterial.d.ts +27 -0
  69. package/lib/cryptography/webCryptoSha256.d.ts +20 -0
  70. package/lib/cryptography/x25519.d.ts +18 -0
  71. package/lib/cryptography/xchacha20poly1305.d.ts +7 -0
  72. package/lib/db/api.d.ts +6 -3
  73. package/lib/db/identityEd25519ClientBoundary.d.ts +13 -0
  74. package/lib/db/src/getDB.d.ts +2 -2
  75. package/lib/db/types.d.ts +52 -4
  76. package/lib/db.worker.js +1 -1
  77. package/lib/handlers/coverChannelRegistry.d.ts +22 -0
  78. package/lib/handlers/edgeTeardownFollowUp.d.ts +35 -0
  79. package/lib/handlers/handleChallenge.d.ts +2 -1
  80. package/lib/handlers/handleConnectToPeer.d.ts +1 -1
  81. package/lib/handlers/handleHandshake.d.ts +2 -6
  82. package/lib/handlers/handleSendMessage.d.ts +60 -7
  83. package/lib/handlers/handleWebSocketMessage.d.ts +1 -1
  84. package/lib/handlers/handshakeCore.d.ts +2 -7
  85. package/lib/handlers/handshakeFrame.d.ts +25 -0
  86. package/lib/handlers/ratchetGateWait.d.ts +13 -0
  87. package/lib/handlers/reconcile.d.ts +24 -0
  88. package/lib/handlers/requestRoom.d.ts +30 -0
  89. package/lib/handlers/roomResponse.d.ts +53 -0
  90. package/lib/index.d.ts +99 -12
  91. package/lib/index.js +1 -1
  92. package/lib/index.min.js +1 -1
  93. package/lib/index.mjs +1 -1
  94. package/lib/libcrypto.provenance.json +5 -5
  95. package/lib/libcrypto.wasm +0 -0
  96. package/lib/middleware/roomListenerMiddleware.d.ts +4 -1
  97. package/lib/reducers/commonSlice.d.ts +3 -2
  98. package/lib/reducers/keyPairSlice.d.ts +3 -6
  99. package/lib/reducers/roomSlice.d.ts +81 -5
  100. package/lib/reducers/signalingServerSlice.d.ts +3 -2
  101. package/lib/session.d.ts +6 -3
  102. package/lib/session.js +1 -1
  103. package/lib/session.mjs +1 -1
  104. package/lib/store.d.ts +4 -2
  105. package/lib/utils/constants.d.ts +12 -0
  106. package/lib/utils/correlationId.d.ts +4 -0
  107. package/lib/utils/identityRestore.d.ts +108 -0
  108. package/lib/utils/interfaces.d.ts +25 -6
  109. package/lib/utils/roomConnectAdmission.d.ts +15 -0
  110. package/lib/utils/roomLeaveCoordinator.d.ts +38 -0
  111. package/lib/utils/roomRequestCoordinator.d.ts +104 -0
  112. package/lib/utils/roomRosterReconciler.d.ts +83 -0
  113. package/lib/utils/sdpFingerprint.d.ts +6 -0
  114. package/lib/utils/signalingAttemptLifecycle.d.ts +33 -0
  115. package/lib/utils/signalingAuth.d.ts +21 -2
  116. package/lib/utils/signalingBounds.d.ts +6 -0
  117. package/lib/utils/signalingFrame.d.ts +21 -0
  118. package/lib/utils/signalingHeartbeatWatchdog.d.ts +45 -0
  119. package/lib/utils/signalingIngressQueue.d.ts +49 -0
  120. package/lib/utils/signalingPeerRequestDebouncer.d.ts +13 -0
  121. package/lib/utils/signalingRoomLifecycle.d.ts +7 -0
  122. package/lib/utils/signalingRoomOperationLifecycle.d.ts +14 -0
  123. package/lib/utils/signalingServerBoundary.d.ts +11 -0
  124. package/lib/utils/terminalSettlement.d.ts +53 -0
  125. package/lib/utils/transportIdentity.d.ts +5 -0
  126. package/package.json +1 -1
@@ -0,0 +1,330 @@
1
+ /**
2
+ * Public windows, buckets, immutable chunks, and checkpoints (Section 4.3).
3
+ *
4
+ * The store's whole view is public geometry: a delivery profile, an ingress
5
+ * window, a size class, a chunk index, and opaque fixed-size objects. Nothing
6
+ * here takes a room-derived input, which is what lets every room in a profile
7
+ * share one bucket and makes unrelated rooms cover for each other rather than
8
+ * members of anything.
9
+ *
10
+ * Two clocks meet in this file and must never be substituted for one another:
11
+ * `IngressWindow` is carrier geometry, and `RoomLogicalWindow` is operation
12
+ * validity under immutable room policy. Profiles with different cadences carry
13
+ * the same operation without changing its validity or the reducer's result.
14
+ *
15
+ * Scope: geometry, hashing, the append slot mapping, RFC 9162 inclusion
16
+ * verification, and the descriptor-bound checkpoint predicates. The remaining
17
+ * Section 4.3 fault proofs are assembled from these parts by a caller that also
18
+ * holds the raw evidence: `checkpointsConflict` and `chainLinksSuccessor` are
19
+ * the descriptor-free halves, and `structurallyValidCheckpoint` supplies the
20
+ * descriptor join each proof requires of both of its checkpoints.
21
+ */
22
+ import type { LibCrypto } from "../cryptography/libcrypto";
23
+ import type { StoreDescriptorV1 } from "./storeDescriptor";
24
+ export interface PublicBucketV1 {
25
+ deliveryProfileHash: Uint8Array;
26
+ ingressWindow: bigint;
27
+ sizeClass: number;
28
+ }
29
+ export interface PublicChunkBodyV1 {
30
+ version: 1;
31
+ bucket: PublicBucketV1;
32
+ chunkIndex: bigint;
33
+ previousChunkHash: Uint8Array;
34
+ fixedObjects: readonly Uint8Array[];
35
+ }
36
+ export type PublicChunkV1 = PublicChunkBodyV1 & {
37
+ storeSignature: Uint8Array;
38
+ };
39
+ export interface PublicStoreCheckpointBodyV1 {
40
+ version: 1;
41
+ storeId: Uint8Array;
42
+ descriptorHash: Uint8Array;
43
+ deliveryProfileHash: Uint8Array;
44
+ ingressWindow: bigint;
45
+ chainStartIngressWindow: bigint;
46
+ previousCheckpointHash: Uint8Array;
47
+ finalizedChunkCount: number;
48
+ finalizedChunkRoot: Uint8Array;
49
+ }
50
+ export type PublicStoreCheckpointV1 = PublicStoreCheckpointBodyV1 & {
51
+ storeSignature: Uint8Array;
52
+ };
53
+ export interface PublicCheckpointChunkLeafV1 {
54
+ sizeClass: number;
55
+ chunkIndex: bigint;
56
+ publicChunkHash: Uint8Array;
57
+ }
58
+ export interface PublicCheckpointChunkInclusionProofV1 {
59
+ version: 1;
60
+ checkpointHash: Uint8Array;
61
+ leaf: PublicCheckpointChunkLeafV1;
62
+ leafIndex: number;
63
+ siblingHashes: readonly Uint8Array[];
64
+ }
65
+ /** The size-class geometry a profile fixes; the subset this module needs. */
66
+ export interface PublicProfileGeometry {
67
+ readonly publicChunkObjectCount: number;
68
+ readonly cohortAllocationsPerWindow: number;
69
+ readonly roomSlotsPerClient: number;
70
+ readonly sizeClasses: readonly {
71
+ readonly id: number;
72
+ readonly appendScheduleLength: number;
73
+ readonly publicChunksPerWindow: number;
74
+ }[];
75
+ }
76
+ export declare class PublicWindowError extends Error {
77
+ readonly name = "PublicWindowError";
78
+ constructor(message: string);
79
+ }
80
+ export declare const ZERO32: Uint8Array;
81
+ /** `IngressWindow(profile, now) = floor(now / profile.deliveryWindowMs)` */
82
+ export declare const ingressWindow: (deliveryWindowMs: bigint, nowMs: bigint) => bigint;
83
+ /**
84
+ * `RoomLogicalWindow(roomPolicy, now) = floor(now / logicalWindowMs)`
85
+ *
86
+ * Deliberately a separate function from `ingressWindow` despite the identical
87
+ * shape: substituting one for the other would let carrier geometry decide
88
+ * operation validity.
89
+ */
90
+ export declare const roomLogicalWindow: (logicalWindowMs: bigint, nowMs: bigint) => bigint;
91
+ /** `IngressWindowStart(w) = checkedMultiply(w, deliveryWindowMs)` */
92
+ export declare const ingressWindowStartMs: (window: bigint, deliveryWindowMs: bigint) => bigint;
93
+ /**
94
+ * Retention is inclusive and has one wire meaning: a bucket finalized in
95
+ * window `w` stays readable through the END of `w + carrierRetentionWindows`,
96
+ * and may be deleted only at or after the start of the window after that.
97
+ */
98
+ export declare const bucketIsReadable: (bucketWindow: bigint, currentWindow: bigint, carrierRetentionWindows: number) => boolean;
99
+ export declare const publicBucketId: (bucket: PublicBucketV1) => Promise<Uint8Array>;
100
+ /** The transcript a store signs; the body only, never the signed form. */
101
+ export declare const publicChunkSigningHash: (body: PublicChunkBodyV1) => Promise<Uint8Array>;
102
+ /** The identity of a signed chunk, which is what a checkpoint leaf commits. */
103
+ export declare const publicChunkHash: (chunk: PublicChunkV1) => Promise<Uint8Array>;
104
+ export declare const publicStoreCheckpointSigningHash: (body: PublicStoreCheckpointBodyV1) => Promise<Uint8Array>;
105
+ export declare const publicStoreCheckpointHash: (checkpoint: PublicStoreCheckpointV1) => Promise<Uint8Array>;
106
+ /** The leaf preimage a checkpoint's Merkle tree is built over. */
107
+ export declare const publicCheckpointChunkLeafInput: (leaf: PublicCheckpointChunkLeafV1) => Uint8Array;
108
+ export interface AppendSlotCoordinates {
109
+ readonly chunkIndex: bigint;
110
+ readonly objectIndexWithinChunk: number;
111
+ readonly globalObjectOrdinal: number;
112
+ readonly roomSlotOrdinal: number;
113
+ readonly objectOrdinalWithinRoomSlot: number;
114
+ }
115
+ /**
116
+ * Where one admitted append lands, derived only from the signed lease ordinal
117
+ * and public profile geometry.
118
+ *
119
+ * This is the mapping a custody promise commits to, so it is a total function
120
+ * of public values: a store cannot move an object by claiming a different
121
+ * position, and a client can check the promise without asking anyone.
122
+ */
123
+ export declare const appendSlotCoordinates: (geometry: PublicProfileGeometry, sizeClassId: number, allocationOrdinal: number, objectOrdinalWithinAllocation: number) => AppendSlotCoordinates;
124
+ /**
125
+ * The checkpoint leaf index of one chunk: the profile-fixed sequence sorted by
126
+ * `(sizeClass, chunkIndex)`.
127
+ */
128
+ export declare const profileChunkOrdinal: (geometry: PublicProfileGeometry, sizeClassId: number, chunkIndex: bigint) => number;
129
+ /** `checkedSum(profile.sizeClasses[].publicChunksPerWindow)` */
130
+ export declare const profileFinalizedChunkCount: (geometry: PublicProfileGeometry) => number;
131
+ /**
132
+ * RFC 9162 Section 2.1.1 leaf hash: `HASH(0x00 || entry)`.
133
+ *
134
+ * The prefix bytes are the whole point — without them a leaf and an interior
135
+ * node could collide, which is the classic second-preimage attack on
136
+ * unprefixed Merkle trees.
137
+ */
138
+ export declare const rfc9162LeafHash: (entry: Uint8Array) => Promise<Uint8Array>;
139
+ /** RFC 9162 Section 2.1.1 interior node: `HASH(0x01 || left || right)`. */
140
+ export declare const rfc9162NodeHash: (left: Uint8Array, right: Uint8Array) => Promise<Uint8Array>;
141
+ /**
142
+ * RFC 9162 Merkle Tree Hash over a nonempty entry sequence.
143
+ *
144
+ * The empty case is rejected rather than returning `HASH()`: a checkpoint
145
+ * always commits the profile's complete fixed chunk sequence, so an empty
146
+ * input means the caller built the wrong sequence.
147
+ */
148
+ export declare const rfc9162MerkleTreeHash: (entries: readonly Uint8Array[]) => Promise<Uint8Array>;
149
+ /**
150
+ * The RFC 9162 audit path for one leaf: the sibling hashes from the leaf up.
151
+ *
152
+ * Exposed so a verifier can assert the received path has exactly this length —
153
+ * a missing or extra sibling is invalid, not merely unhelpful.
154
+ */
155
+ export declare const rfc9162AuditPath: (entries: readonly Uint8Array[], leafIndex: number) => Promise<Uint8Array[]>;
156
+ /** The exact number of siblings an RFC 9162 audit path has for `(index, n)`. */
157
+ export declare const rfc9162AuditPathLength: (leafIndex: number, treeSize: number) => number;
158
+ /** Recompute a root from a leaf and its audit path (RFC 9162 Section 2.1.3). */
159
+ export declare const rfc9162RootFromAuditPath: (leafEntry: Uint8Array, leafIndex: number, treeSize: number, siblingHashes: readonly Uint8Array[]) => Promise<Uint8Array>;
160
+ /**
161
+ * The complete leaf sequence a checkpoint commits: every chunk of every size
162
+ * class, sorted by `(sizeClass, chunkIndex)`, including all-dummy windows.
163
+ */
164
+ export declare const checkpointLeafEntries: (geometry: PublicProfileGeometry, chunkHashBySizeClass: ReadonlyMap<number, readonly Uint8Array[]>) => Promise<Uint8Array[]>;
165
+ export type InclusionVerdict = {
166
+ readonly valid: true;
167
+ } | {
168
+ readonly valid: false;
169
+ readonly reason: string;
170
+ };
171
+ /**
172
+ * Verify that a signed chunk occupies its committed position in a checkpoint.
173
+ *
174
+ * The signature check is the caller's: it needs the store descriptor from
175
+ * Section 4.2 to know which key to trust. Everything that can be decided from
176
+ * the geometry and the hashes is decided here, and every cross-coordinate
177
+ * relocation is rejected — a store must not be able to move an object between
178
+ * classes, chunks, or windows and still produce a passing proof.
179
+ */
180
+ export declare const verifyCheckpointChunkInclusion: (geometry: PublicProfileGeometry, checkpoint: PublicStoreCheckpointV1, chunk: PublicChunkV1, proof: PublicCheckpointChunkInclusionProofV1) => Promise<InclusionVerdict>;
181
+ /**
182
+ * Two checkpoints for one store/profile/window that are not the same object.
183
+ *
184
+ * This is the descriptor-free half of `PublicCheckpointConflictProofV1`; a
185
+ * complete proof additionally joins each embedded descriptor. Canonical order
186
+ * is bytewise-lower checkpoint hash first, so one fault has one proof rather
187
+ * than two mirror images.
188
+ */
189
+ export declare const checkpointsConflict: (first: PublicStoreCheckpointV1, second: PublicStoreCheckpointV1) => Promise<{
190
+ readonly conflicting: false;
191
+ } | {
192
+ readonly conflicting: true;
193
+ readonly canonicalOrder: readonly [PublicStoreCheckpointV1, PublicStoreCheckpointV1];
194
+ }>;
195
+ /**
196
+ * The hash-linkage half of `ChainValidSuccessor`.
197
+ *
198
+ * Structural validity under each embedded descriptor is a separate Section 4.2
199
+ * check, and the specification is explicit that structural validity alone does
200
+ * not assert predecessor continuity — which is exactly what this decides.
201
+ */
202
+ export declare const chainLinksSuccessor: (previous: PublicStoreCheckpointV1, next: PublicStoreCheckpointV1) => Promise<boolean>;
203
+ /** At the chain start the predecessor hash is exactly `ZERO32`. */
204
+ export declare const isChainStart: (checkpoint: PublicStoreCheckpointV1) => boolean;
205
+ /**
206
+ * `StructurallyValidCheckpoint(descriptor, checkpoint, profile)`.
207
+ *
208
+ * Deliberately portable: it uses the descriptor embedded in the read or proof,
209
+ * and takes no input from local carrier authorization, catalog arrival order,
210
+ * or which descriptor the verifier considers "latest". Whether the frontend may
211
+ * *contact* that store is a separate local decision — conflating the two would
212
+ * make historical evidence depend on present-day policy, so a store could
213
+ * escape a proof by being removed from a catalog.
214
+ *
215
+ * `finalizationInstantUnixMs` is the instant the checkpoint was finalized, and
216
+ * the descriptor must have been valid then — not now.
217
+ *
218
+ * Of the specification's "profile-fixed count/root checks", only the count half
219
+ * is decided here. Recomputing `finalizedChunkRoot` needs the window's chunk
220
+ * hashes, which this predicate is never given; that is
221
+ * `verifyCheckpointChunkInclusion`, and nothing composes the two, so no single
222
+ * call asserts both halves. A checkpoint accepted here may still carry a root
223
+ * no chunk sequence produces.
224
+ *
225
+ * TODO(spec): the condition list in Section 4.3 does not name a version check,
226
+ * so `checkpoint.version` is not checked here, while `StoreDescriptorAuthentic`
227
+ * does name one and `validateStoreDescriptor` enforces it. Whether the version
228
+ * byte belongs to structural validity is a question for the specification, not
229
+ * one to settle by tightening this predicate; the current behaviour is pinned
230
+ * in tests/blindRendezvous/storeHonesty.test.ts.
231
+ */
232
+ export declare const structurallyValidCheckpoint: (descriptor: StoreDescriptorV1, checkpoint: PublicStoreCheckpointV1, geometry: PublicProfileGeometry, finalizationInstantUnixMs: bigint, module?: LibCrypto) => Promise<InclusionVerdict>;
233
+ /**
234
+ * `ChainValidSuccessor(previous, next)`: both structurally valid under their
235
+ * embedded descriptors, and linked.
236
+ *
237
+ * Structural validity alone deliberately does not assert continuity — that is
238
+ * what makes a missing predecessor detectable rather than assumed.
239
+ */
240
+ export declare const chainValidSuccessor: (previous: PublicStoreCheckpointV1, previousDescriptor: StoreDescriptorV1, previousFinalizationUnixMs: bigint, next: PublicStoreCheckpointV1, nextDescriptor: StoreDescriptorV1, nextFinalizationUnixMs: bigint, geometry: PublicProfileGeometry, module?: LibCrypto) => Promise<InclusionVerdict>;
241
+ /**
242
+ * One checkpoint exactly as a client observed it: the read itself, the
243
+ * descriptor embedded beside it, and the instant that window was finalized.
244
+ *
245
+ * Deliberately not a `...V1` name: this is an in-memory bundle of three
246
+ * already-frozen objects, not a wire shape the specification has registered.
247
+ */
248
+ export interface ObservedStoreCheckpoint {
249
+ readonly checkpoint: PublicStoreCheckpointV1;
250
+ readonly descriptor: StoreDescriptorV1;
251
+ readonly finalizationInstantUnixMs: bigint;
252
+ }
253
+ /**
254
+ * What `verifyStoreCheckpointChain` detected. Exactly one outcome is blame-free
255
+ * besides success: `unverified-chain-gap` says the client did not observe
256
+ * enough, which the specification is explicit is not a fault.
257
+ */
258
+ export type StoreCheckpointChainVerdict = {
259
+ readonly outcome: "chain-verified";
260
+ readonly storeId: Uint8Array;
261
+ readonly deliveryProfileHash: Uint8Array;
262
+ readonly chainStartIngressWindow: bigint;
263
+ readonly firstIngressWindow: bigint;
264
+ readonly headIngressWindow: bigint;
265
+ readonly headCheckpointHash: Uint8Array;
266
+ readonly startsAtChainStart: boolean;
267
+ } | {
268
+ readonly outcome: "structurally-invalid-checkpoint";
269
+ readonly reason: string;
270
+ readonly index: number;
271
+ } | {
272
+ readonly outcome: "not-one-store-profile-chain";
273
+ readonly reason: string;
274
+ readonly index: number;
275
+ } | {
276
+ readonly outcome: "chain-start-conflict";
277
+ readonly reason: string;
278
+ readonly canonicalOrder: readonly [StoreDescriptorV1, StoreDescriptorV1];
279
+ } | {
280
+ readonly outcome: "checkpoint-conflict";
281
+ readonly reason: string;
282
+ readonly canonicalOrder: readonly [
283
+ PublicStoreCheckpointV1,
284
+ PublicStoreCheckpointV1
285
+ ];
286
+ } | {
287
+ readonly outcome: "chain-breach";
288
+ readonly reason: string;
289
+ readonly previous: PublicStoreCheckpointV1;
290
+ readonly next: PublicStoreCheckpointV1;
291
+ } | {
292
+ readonly outcome: "unverified-chain-gap";
293
+ readonly reason: string;
294
+ readonly afterIngressWindow: bigint;
295
+ readonly beforeIngressWindow: bigint;
296
+ };
297
+ /**
298
+ * The sequence form of the Section 4.3 checkpoint checks: one entry point a
299
+ * store client can call over the run of checkpoints it actually holds.
300
+ *
301
+ * `chainValidSuccessor` remains the specified predicate for a single pair; this
302
+ * verifies each checkpoint's structure exactly once and then decides the
303
+ * pairwise questions, so a long run costs one signature verification per
304
+ * checkpoint rather than two.
305
+ *
306
+ * Blame is reported before absence. A store must not be able to bury an
307
+ * equivocation behind a hole in what the client happened to retain, so a
308
+ * conflict, chain-start conflict, or broken predecessor anywhere in the run
309
+ * outranks a missing window; only when no fault exists does a gap become the
310
+ * verdict.
311
+ *
312
+ * What a `chain-verified` verdict is not: it says the observed run is
313
+ * internally consistent and signed, over exactly the windows supplied. It is
314
+ * not a completeness, availability, or non-equivocation claim — a store that
315
+ * showed this client one branch and another client a different one is caught
316
+ * only when the two observations meet. Nor does it assert `finalizedChunkRoot`:
317
+ * `structurallyValidCheckpoint` cannot, and this composes that, not inclusion.
318
+ *
319
+ * A `chain-verified` verdict copies the bytes it reports, so it stays true
320
+ * after the buffers a store's reply was decoded into are reused. The conflict
321
+ * and breach verdicts deliberately do not: they carry the caller's own
322
+ * checkpoint and descriptor objects, because those are the exact halves the
323
+ * specification's proofs are built from, and copying them here would only
324
+ * hide that they must be retained unmutated to stay usable as evidence.
325
+ *
326
+ * Ordering the run is the caller's job: observations must arrive sorted by
327
+ * ingress window. A store cannot cause a violation of that, so it throws
328
+ * rather than returning a verdict that would read as a detected fault.
329
+ */
330
+ export declare const verifyStoreCheckpointChain: (observations: readonly ObservedStoreCheckpoint[], geometry: PublicProfileGeometry, module?: LibCrypto) => Promise<StoreCheckpointChainVerdict>;
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Exact local persistence boundary for retained blind-rendezvous operations.
3
+ *
4
+ * This is a local storage schema, not a wire format and not part of the
5
+ * normative release registry. It preserves the exact canonical operation
6
+ * bytes needed by the existing operation validator and CoreReduce after a
7
+ * restart; it deliberately performs neither of those protocol validations.
8
+ *
9
+ * One immutable content row stores each exact operation once per room. A
10
+ * per-room/window manifest names the complete sorted unique room-wide row set
11
+ * visible at that historical decision boundary and fences its physical
12
+ * count/bytes. This intentionally simple representation makes omission and
13
+ * overcapacity explicit. A later database adapter may change its physical
14
+ * layout without changing this source-internal contract.
15
+ */
16
+ export type RetainedOperationManifestCompletenessV1 = "complete" | "incomplete-overcapacity";
17
+ /**
18
+ * Canonical local manifest for one room/window historical replay fence.
19
+ *
20
+ * `operationIds` names the complete room-wide unique retained-operation set,
21
+ * not an endpoint subset and not a decoded Core projection. Therefore the
22
+ * byte total charges a shared content row once regardless of how many window
23
+ * manifests reference it.
24
+ */
25
+ export interface RetainedOperationWindowManifestV1 {
26
+ readonly version: 1;
27
+ readonly roomContextId: Uint8Array;
28
+ readonly referenceWindow: bigint;
29
+ readonly retainThroughLogicalWindow: bigint;
30
+ readonly completeness: RetainedOperationManifestCompletenessV1;
31
+ readonly operationIds: readonly Uint8Array[];
32
+ readonly retainedOperationCount: number;
33
+ readonly retainedOperationBytes: bigint;
34
+ readonly maxRetainedValidOperationsPerRoom: number;
35
+ readonly maxRetainedValidOperationBytesPerRoom: bigint;
36
+ /** The first unique row rejected at the public capacity boundary. */
37
+ readonly firstRejectedOperationId: Uint8Array | null;
38
+ }
39
+ /**
40
+ * Immutable content-addressed row. Room membership is supplied only by the
41
+ * trusted outer-validation/store transition; this module can prove the
42
+ * OperationId/bytes relation but cannot infer RoomContextId from an operation.
43
+ */
44
+ export interface RetainedOperationContentRowV1 {
45
+ readonly version: 1;
46
+ readonly roomContextId: Uint8Array;
47
+ readonly operationId: Uint8Array;
48
+ readonly exactOperationBytes: Uint8Array;
49
+ }
50
+ export interface RetainedOperationWindowLocatorV1 {
51
+ readonly version: 1;
52
+ readonly roomContextId: Uint8Array;
53
+ readonly referenceWindow: bigint;
54
+ }
55
+ /** Exact absence is replay-unavailable, never an empty complete manifest. */
56
+ export type ExactRetainedOperationManifestRowV1 = {
57
+ readonly kind: "absent";
58
+ } | {
59
+ readonly kind: "present";
60
+ readonly exactManifestBytes: Uint8Array;
61
+ /** Non-reused adapter revision used to prevent ABA. */
62
+ readonly recordRevision: bigint;
63
+ };
64
+ /**
65
+ * Exact rows copied by one future read-only transaction.
66
+ *
67
+ * For a present manifest, `operations` must contain exactly one row for every
68
+ * named ID and no other row. Missing rows are represented by omission and fail
69
+ * validation; an absent manifest must have an empty row list.
70
+ */
71
+ export interface RetainedOperationWindowExactCaptureV1 {
72
+ readonly manifest: ExactRetainedOperationManifestRowV1;
73
+ readonly operations: readonly RetainedOperationContentRowV1[];
74
+ }
75
+ export type ValidatedRetainedOperationWindowCaptureV1 = {
76
+ readonly kind: "unavailable";
77
+ } | {
78
+ readonly kind: "available";
79
+ readonly exactManifestRow: Extract<ExactRetainedOperationManifestRowV1, {
80
+ readonly kind: "present";
81
+ }>;
82
+ readonly manifest: RetainedOperationWindowManifestV1;
83
+ readonly operations: readonly RetainedOperationContentRowV1[];
84
+ };
85
+ export interface InitializeRetainedOperationWindowOptionsV1 {
86
+ readonly roomContextId: Uint8Array;
87
+ readonly referenceWindow: bigint;
88
+ readonly retainThroughLogicalWindow: bigint;
89
+ readonly maxRetainedValidOperationsPerRoom: number;
90
+ readonly maxRetainedValidOperationBytesPerRoom: bigint;
91
+ }
92
+ export type PreparedRetainedOperationStoreMutationV1 = {
93
+ readonly kind: "initialize-window";
94
+ readonly exactNextManifestBytes: Uint8Array;
95
+ } | {
96
+ readonly kind: "insert-operation-and-replace-manifest";
97
+ readonly operation: RetainedOperationContentRowV1;
98
+ readonly exactNextManifestBytes: Uint8Array;
99
+ } | {
100
+ readonly kind: "mark-incomplete-overcapacity";
101
+ readonly firstRejectedOperationId: Uint8Array;
102
+ readonly exactNextManifestBytes: Uint8Array;
103
+ };
104
+ /**
105
+ * Closed future CAS request. The adapter compares the exact manifest
106
+ * bytes/revision and every expected content row before applying the mutation.
107
+ * Admission mutations additionally require the candidate content key to be
108
+ * absent; finding it without the matching manifest is a conflict/corruption,
109
+ * not an invitation to repair state heuristically.
110
+ */
111
+ export interface RetainedOperationStoreCasRequestV1 {
112
+ readonly version: 1;
113
+ readonly locator: RetainedOperationWindowLocatorV1;
114
+ readonly expected: RetainedOperationWindowExactCaptureV1;
115
+ readonly candidateOperationId: Uint8Array | null;
116
+ readonly mutation: PreparedRetainedOperationStoreMutationV1;
117
+ }
118
+ export type RetainedOperationStoreCasResultV1 = {
119
+ readonly status: "committed";
120
+ readonly exactManifestRow: Extract<ExactRetainedOperationManifestRowV1, {
121
+ readonly kind: "present";
122
+ }>;
123
+ } | {
124
+ readonly status: "conflict";
125
+ readonly fence: "manifest" | "operation";
126
+ };
127
+ /**
128
+ * Source-internal byte-store port for the later IndexedDB adapter.
129
+ *
130
+ * `readExactWindowCapture` must own all returned buffers and resolve only
131
+ * after its read transaction completes. `compareAndSwap` performs no crypto
132
+ * and awaits no promise while its write transaction is live.
133
+ *
134
+ * @internal
135
+ */
136
+ export interface RetainedOperationStorePortV1 {
137
+ readExactWindowCapture(locator: RetainedOperationWindowLocatorV1): Promise<RetainedOperationWindowExactCaptureV1>;
138
+ compareAndSwap(request: RetainedOperationStoreCasRequestV1): Promise<RetainedOperationStoreCasResultV1>;
139
+ }
140
+ export type RetainedOperationAdmissionPlanV1 = {
141
+ readonly kind: "unavailable";
142
+ } | {
143
+ readonly kind: "duplicate";
144
+ } | {
145
+ readonly kind: "sticky-incomplete-overcapacity";
146
+ readonly firstRejectedOperationId: Uint8Array;
147
+ } | {
148
+ readonly kind: "accept-operation";
149
+ readonly request: RetainedOperationStoreCasRequestV1;
150
+ } | {
151
+ readonly kind: "mark-incomplete-overcapacity";
152
+ readonly request: RetainedOperationStoreCasRequestV1;
153
+ };
154
+ export declare class RetainedOperationStoreError extends Error {
155
+ readonly name = "RetainedOperationStoreError";
156
+ constructor(message: string);
157
+ }
158
+ /**
159
+ * Encode one strict local manifest. The descriptor is intentionally not
160
+ * exported and the bytes carry no interoperability or protocol provenance.
161
+ */
162
+ export declare const encodeRetainedOperationWindowManifestV1: (value: RetainedOperationWindowManifestV1) => Uint8Array;
163
+ /** Decode, own, and semantically validate one exact local manifest. */
164
+ export declare const decodeRetainedOperationWindowManifestV1: (exactBytes: Uint8Array) => RetainedOperationWindowManifestV1;
165
+ /**
166
+ * Own one content row and prove only its canonical bytes/OperationId
167
+ * association. This is not signature, room, policy, temporal, or Core
168
+ * validation.
169
+ */
170
+ export declare const validateAndCopyRetainedOperationContentRowV1: (value: unknown) => Promise<RetainedOperationContentRowV1>;
171
+ export declare const validateAndCopyRetainedOperationWindowExactCaptureV1: (value: unknown) => Promise<ValidatedRetainedOperationWindowCaptureV1>;
172
+ /**
173
+ * Explicitly prepare a new empty complete window. This is the only path that
174
+ * turns expected absence into a manifest; replay reads never infer that an
175
+ * absent row means an empty room.
176
+ */
177
+ export declare const prepareRetainedOperationWindowInitializationV1: (value: unknown) => RetainedOperationStoreCasRequestV1;
178
+ /**
179
+ * Plan one deterministic retained-operation admission.
180
+ *
181
+ * The input capture is fully correlated before a candidate can affect state.
182
+ * Duplicate exact rows have zero resource delta. Once a manifest is
183
+ * incomplete, normal admission never parses a candidate or repairs/replaces
184
+ * the first-rejected witness; only a separate future full reconciliation may
185
+ * create a new complete manifest after capacity changes.
186
+ */
187
+ export declare const planRetainedOperationAdmissionV1: (captureValue: unknown, candidateValue: unknown) => Promise<RetainedOperationAdmissionPlanV1>;
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Version-safe invitation parsing.
3
+ *
4
+ * REQ-001 keeps the user-facing flow identical — one capability, one `/r`
5
+ * link, one QR code — while making the rendezvous version explicit in the
6
+ * fragment. Every deployed form (compact, `v1.`, 24-word, legacy hex) keeps its
7
+ * legacy-signaling meaning forever; blind rendezvous uses `v2.`.
8
+ *
9
+ * The two versions must never be silently interchangeable in either
10
+ * direction: an old client rejects `v2.` as unsupported rather than joining a
11
+ * different room, and a new client executes `v1.` only through the separately
12
+ * installed legacy-signaling adapter.
13
+ *
14
+ * This module deliberately does not parse whole URLs. The page extracts
15
+ * `location.hash` and passes the fragment in, exactly as today.
16
+ */
17
+ import type { RoomPolicyV4 } from "./roomPolicyV4";
18
+ export declare const BLIND_ROOM_INVITE_VERSION = 2;
19
+ export declare const BLIND_ROOM_INVITE_PREFIX = "v2.";
20
+ /**
21
+ * Bound on the canonical policy carried by a policy-bearing v2 fragment.
22
+ *
23
+ * Status: PROPOSED. The release registry freezes the final value together with
24
+ * the binary policy codec; this bound only has to be large enough for a valid
25
+ * `RoomPolicyV4` and small enough to keep a shared link scannable as a QR code.
26
+ */
27
+ export declare const MAX_INVITE_POLICY_BYTES = 512;
28
+ export type LegacyRoomInviteV1 = {
29
+ version: 1;
30
+ capability: Uint8Array;
31
+ };
32
+ export type BlindRoomInviteV2 = {
33
+ version: 2;
34
+ form: "default";
35
+ capability: Uint8Array;
36
+ } | {
37
+ version: 2;
38
+ form: "room-policy";
39
+ capability: Uint8Array;
40
+ roomPolicy: RoomPolicyV4;
41
+ };
42
+ export type ParsedRoomInvite = LegacyRoomInviteV1 | BlindRoomInviteV2;
43
+ export declare class RoomInviteParseError extends Error {
44
+ readonly name = "RoomInviteParseError";
45
+ constructor(message: string);
46
+ }
47
+ /**
48
+ * Thrown when a v1 invitation is executed in a build without the optional
49
+ * legacy-signaling adapter. It is raised before any adapter or network work
50
+ * and before capability or identity disclosure, and it never maps v1 to v2.
51
+ */
52
+ export declare class LegacySignalingAdapterUnavailableError extends Error {
53
+ readonly name = "LegacySignalingAdapterUnavailableError";
54
+ readonly code = "legacy-signaling-adapter-unavailable";
55
+ readonly inviteVersion = 1;
56
+ constructor();
57
+ }
58
+ /**
59
+ * Thrown when the legacy-named `signalingServerUrl` option is supplied with a
60
+ * v2 invitation but no exact trusted alias maps it to a signed store
61
+ * descriptor. Failing here is deliberate: silently ignoring the value or
62
+ * substituting the default store would send the user somewhere they did not
63
+ * ask for.
64
+ */
65
+ export declare class BlindStoreAliasResolutionError extends Error {
66
+ readonly name = "BlindStoreAliasResolutionError";
67
+ readonly code = "blind-store-alias-unmapped";
68
+ readonly option = "signalingServerUrl";
69
+ constructor();
70
+ }
71
+ /**
72
+ * Parse a fragment into a closed versioned result, preserving the version.
73
+ *
74
+ * A leading `#` is accepted here and only here; it is not part of the
75
+ * canonical invitation.
76
+ */
77
+ export declare const parseRoomInvite: (fragment: string) => ParsedRoomInvite;
78
+ /** The capability-only default fragment: `v2.<43-character-base64url>`. */
79
+ export declare const encodeBlindRoomInviteV2Default: (capability: Uint8Array) => string;
80
+ /**
81
+ * The policy-bearing fragment used by the advanced-room flow, so a PIN, PQ, or
82
+ * cover choice survives sharing without appearing in an HTTP query.
83
+ */
84
+ export declare const encodeBlindRoomInviteV2WithPolicy: (capability: Uint8Array, roomPolicy: RoomPolicyV4) => string;
85
+ /**
86
+ * The room policy an invitation resolves to.
87
+ *
88
+ * A bare v2 invitation resolves to the frozen default rather than to whatever
89
+ * the current application default happens to be; a policy-bearing invitation
90
+ * resolves to its exact decoded policy with no defaults merged in.
91
+ */
92
+ export declare const resolveInviteRoomPolicy: (invite: BlindRoomInviteV2) => RoomPolicyV4;