@ibgib/core-gib 0.1.58 → 0.1.60
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.
- package/CHANGELOG.md +9 -1
- package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.mjs +6 -2
- package/dist/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-types.d.mts +1 -1
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts +1 -1
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs +7 -11
- package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-types.d.mts +24 -1
- package/dist/sync/sync-peer/sync-peer-types.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.d.mts +15 -4
- package/dist/sync/sync-peer/sync-peer-v1.d.mts.map +1 -1
- package/dist/sync/sync-peer/sync-peer-v1.mjs +120 -25
- package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-constants.d.mts +46 -0
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-constants.d.mts.map +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-constants.mjs +45 -0
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-constants.mjs.map +1 -0
- package/dist/sync/sync-peer/{sync-peer-websocket-receiver → sync-peer-websocket/sync-peer-websocket-receiver}/sync-peer-websocket-receiver-types.d.mts +2 -2
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-types.d.mts.map +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-types.mjs.map +1 -0
- package/dist/sync/sync-peer/{sync-peer-websocket-receiver → sync-peer-websocket/sync-peer-websocket-receiver}/sync-peer-websocket-receiver-v1.d.mts +11 -8
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.d.mts.map +1 -0
- package/dist/sync/sync-peer/{sync-peer-websocket-receiver → sync-peer-websocket/sync-peer-websocket-receiver}/sync-peer-websocket-receiver-v1.mjs +115 -61
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs.map +1 -0
- package/dist/sync/sync-peer/{sync-peer-websocket-receiver → sync-peer-websocket/sync-peer-websocket-receiver}/sync-websocket-peer-helpers.d.mts +3 -3
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts.map +1 -0
- package/dist/sync/sync-peer/{sync-peer-websocket-receiver → sync-peer-websocket/sync-peer-websocket-receiver}/sync-websocket-peer-helpers.mjs +6 -6
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs.map +1 -0
- package/dist/sync/sync-peer/{sync-peer-websocket-sender → sync-peer-websocket/sync-peer-websocket-sender}/sync-peer-websocket-sender-types.d.mts +1 -1
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-types.d.mts.map +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-types.mjs.map +1 -0
- package/dist/sync/sync-peer/{sync-peer-websocket-sender → sync-peer-websocket/sync-peer-websocket-sender}/sync-peer-websocket-sender-v1.d.mts +22 -4
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.d.mts.map +1 -0
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs +447 -0
- package/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs.map +1 -0
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts +22 -5
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs +263 -28
- package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs.map +1 -1
- package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts +13 -0
- package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.d.mts +12 -1
- package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
- package/dist/sync/sync-saga-coordinator.mjs +106 -12
- package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
- package/dist/sync/sync-types.d.mts +24 -0
- package/dist/sync/sync-types.d.mts.map +1 -1
- package/dist/sync/sync-types.mjs +0 -1
- package/dist/sync/sync-types.mjs.map +1 -1
- package/dist/sync/sync-withid.connect.respec.mjs +3 -3
- package/dist/sync/sync-withid.connect.respec.mjs.map +1 -1
- package/dist/sync/sync-withid.pingpong.respec.d.mts +11 -0
- package/dist/sync/sync-withid.pingpong.respec.d.mts.map +1 -0
- package/dist/sync/sync-withid.pingpong.respec.mjs +199 -0
- package/dist/sync/sync-withid.pingpong.respec.mjs.map +1 -0
- package/dist/witness/space/inner-space/inner-space-v1.d.mts.map +1 -1
- package/dist/witness/space/inner-space/inner-space-v1.mjs +1 -1
- package/dist/witness/space/inner-space/inner-space-v1.mjs.map +1 -1
- package/package.json +1 -1
- package/src/sync/docs/security-3b.md +92 -0
- package/src/sync/docs/security.md +107 -39
- package/src/sync/sync-peer/sync-peer-http-receiver/sync-peer-http-receiver-v1.mts +6 -2
- package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-types.mts +1 -1
- package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +11 -14
- package/src/sync/sync-peer/sync-peer-types.mts +28 -1
- package/src/sync/sync-peer/sync-peer-v1.mts +127 -35
- package/src/sync/sync-peer/sync-peer-websocket/README.md +42 -0
- package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-constants.mts +68 -0
- package/src/sync/sync-peer/{sync-peer-websocket-receiver → sync-peer-websocket/sync-peer-websocket-receiver}/sync-peer-websocket-receiver-types.mts +2 -2
- package/src/sync/sync-peer/{sync-peer-websocket-receiver → sync-peer-websocket/sync-peer-websocket-receiver}/sync-peer-websocket-receiver-v1.mts +128 -71
- package/src/sync/sync-peer/{sync-peer-websocket-receiver → sync-peer-websocket/sync-peer-websocket-receiver}/sync-websocket-peer-helpers.mts +8 -8
- package/src/sync/sync-peer/{sync-peer-websocket-sender → sync-peer-websocket/sync-peer-websocket-sender}/sync-peer-websocket-sender-types.mts +1 -1
- package/src/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mts +509 -0
- package/src/sync/sync-saga-context/sync-saga-context-helpers.mts +267 -36
- package/src/sync/sync-saga-context/sync-saga-context-types.mts +14 -0
- package/src/sync/sync-saga-coordinator.mts +148 -8
- package/src/sync/sync-types.mts +28 -4
- package/src/sync/sync-withid.connect.respec.mts +3 -3
- package/src/sync/sync-withid.pingpong.respec.mts +234 -0
- package/src/witness/space/inner-space/inner-space-v1.mts +4 -5
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-types.d.mts.map +0 -1
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-types.mjs.map +0 -1
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.d.mts.map +0 -1
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs.map +0 -1
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-websocket-peer-helpers.d.mts.map +0 -1
- package/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs.map +0 -1
- package/dist/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-types.d.mts.map +0 -1
- package/dist/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-types.mjs.map +0 -1
- package/dist/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.d.mts.map +0 -1
- package/dist/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs +0 -282
- package/dist/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mjs.map +0 -1
- package/src/sync/sync-peer/sync-peer-websocket-sender/sync-peer-websocket-sender-v1.mts +0 -321
- /package/dist/sync/sync-peer/{sync-peer-websocket-receiver → sync-peer-websocket/sync-peer-websocket-receiver}/sync-peer-websocket-receiver-types.mjs +0 -0
- /package/dist/sync/sync-peer/{sync-peer-websocket-sender → sync-peer-websocket/sync-peer-websocket-sender}/sync-peer-websocket-sender-types.mjs +0 -0
|
@@ -285,29 +285,29 @@ We still call `senderCoordinator.sync(...)` — the phase focus is on what `peer
|
|
|
285
285
|
|
|
286
286
|
**Goal**: With identity fully established and transport connected, sync a single ibgib `X` from source to dest. Verify S evolves correctly per turn (`sync` pool), and X's full dependency graph arrives on dest. After commit, both sender and receiver durable spaces must contain: the same evolved I, the full S dependency graph, and the full X dependency graph.
|
|
287
287
|
|
|
288
|
-
#### Phase 3A — Innerspace unit test (`sync-withid.
|
|
289
|
-
|
|
290
|
-
- [
|
|
291
|
-
- [
|
|
292
|
-
- [
|
|
293
|
-
- [
|
|
294
|
-
- [
|
|
295
|
-
- [
|
|
296
|
-
- [
|
|
297
|
-
- [
|
|
298
|
-
- [
|
|
299
|
-
- [
|
|
288
|
+
#### Phase 3A — Innerspace unit test (`sync-withid.pingpong.respec.mts`)
|
|
289
|
+
|
|
290
|
+
- [x] Create `sync-withid.pingpong.respec.mts`
|
|
291
|
+
- [x] Create `r1_alpha_v0_source` (represented by `xStone` test domain ibgib)
|
|
292
|
+
- [x] Call `senderCoordinator.sync({ domainIbGibs: [alpha], senderIdentity, senderSecret, ... })`
|
|
293
|
+
- [x] `ifWeMight` — `"alpha dep graph matches on source and dest"`: use `getDependencyGraph` + `graphsAreEquivalent`
|
|
294
|
+
- [x] `ifWeMight` — `"sessionIdentity evolved the expected number of times"`: assert `S.data.n` equals the known deterministic turn count
|
|
295
|
+
- [x] ☑ **TODO**: Manually inspect the full session keystone graph after a first run and count the exact number of outgoing turns (Init + Delta(s) + Commit), then hard-code that number into this assertion
|
|
296
|
+
- [x] `ifWeMight` — `"sender durable space has I (evolved frame)"`: assert I1 addr is in `sourceSpace`
|
|
297
|
+
- [x] `ifWeMight` — `"receiver durable space has I (evolved frame)"`: assert I1 addr is in `destSpace`
|
|
298
|
+
- [x] `ifWeMight` — `"sender durable space has full S dep graph"`: use `getDependencyGraph` on S in `sourceSpace`
|
|
299
|
+
- [x] `ifWeMight` — `"receiver durable space has full S dep graph"`: use `getDependencyGraph` on S in `destSpace`
|
|
300
300
|
|
|
301
301
|
#### Phase 3B — Space-Gib integrated (manual)
|
|
302
302
|
|
|
303
|
-
- [
|
|
304
|
-
- [
|
|
305
|
-
- [
|
|
306
|
-
- [
|
|
307
|
-
- [
|
|
308
|
-
- [
|
|
309
|
-
- [
|
|
310
|
-
- [
|
|
303
|
+
- [x] Trigger a sync of a known test ibgib via `dev-tools.mts` (add "sync - fullsync" button to a new row)
|
|
304
|
+
- [x] Confirm S evolves on each outgoing turn (inspect frame `data.n` in debugger)
|
|
305
|
+
- [x] Confirm X's full dependency graph is present on the client after commit
|
|
306
|
+
- [x] Confirm X's full dependency graph is present on the server after commit
|
|
307
|
+
- [x] Confirm S's full dependency graph is present on the client after commit
|
|
308
|
+
- [x] Confirm S's full dependency graph is present on the server after commit
|
|
309
|
+
- [x] Confirm I's evolved frame (I1) is present on the client after commit
|
|
310
|
+
- [x] Confirm I's evolved frame (I1) is present on the server after commit
|
|
311
311
|
|
|
312
312
|
|
|
313
313
|
---
|
|
@@ -320,14 +320,14 @@ The sync proper will not be called. The test only cares that the pre-connect ide
|
|
|
320
320
|
|
|
321
321
|
#### Phase 1A — Innerspace unit test
|
|
322
322
|
|
|
323
|
-
- [
|
|
323
|
+
- [x] Create `sync-withid.establish.respec.mts` with scaffold:
|
|
324
324
|
- `Metaspace_Innerspace` + two `InnerSpace_V1` (source/dest) + `SyncSagaCoordinator` pair + `newTestPeer()` factory
|
|
325
325
|
- A `senderSecret` constant (test-only plaintext)
|
|
326
326
|
- A `KeystoneService_V1` instance (new'd inline)
|
|
327
|
-
- [
|
|
328
|
-
- [
|
|
329
|
-
- [
|
|
330
|
-
- [
|
|
327
|
+
- [x] Add `respecfully` block: `"Phase 1: establishSessionIdentity"`
|
|
328
|
+
- [x] `ifWeMight` — `"creates sessionIdentity genesis (S) locally"`: assert `S^Stjp` was generated and exists in `sourceSpace`
|
|
329
|
+
- [x] `ifWeMight` — `"evolves senderIdentity (I → I1) with sync claim"`: assert `I1` frame has a proof whose `claim.verb === 'sync'` and `claim.target === S^Stjp`
|
|
330
|
+
- [x] `ifWeMight` — `"posts I1 and S to destSpace (receiver)"`: assert both addrs are retrievable from `destSpace`
|
|
331
331
|
|
|
332
332
|
#### Phase 1B — Space-Gib integrated (manual)
|
|
333
333
|
|
|
@@ -344,7 +344,7 @@ The sync proper will not be called. The test only cares that the pre-connect ide
|
|
|
344
344
|
|
|
345
345
|
#### Phase 2A — Innerspace unit test
|
|
346
346
|
|
|
347
|
-
- [x]
|
|
347
|
+
- [x] Create `sync-withid.connect.respec.mts` with a `respecfully` block: `"Phase 2: connect"`
|
|
348
348
|
- [x] `ifWeMight` — `"connect completes without error"`: call `peer.connect()` and assert no exception
|
|
349
349
|
- [x] `ifWeMight` — `"connect pool is depleted by exactly one challenge"`: assert `S.data.pools['connect'].used` increased by the expected count
|
|
350
350
|
|
|
@@ -362,19 +362,87 @@ The sync proper will not be called. The test only cares that the pre-connect ide
|
|
|
362
362
|
|
|
363
363
|
#### Phase 3A — Innerspace unit test
|
|
364
364
|
|
|
365
|
-
- [
|
|
366
|
-
- [
|
|
367
|
-
- [
|
|
368
|
-
- [
|
|
369
|
-
- [
|
|
365
|
+
- [x] Create `sync-withid.pingpong.respec.mts`
|
|
366
|
+
- [x] Create `r1_alpha_v0_source` via `TestTransformer` (represented by `xStone` test domain ibgib)
|
|
367
|
+
- [x] Call `senderCoordinator.sync({ domainIbGibs: [alpha], senderIdentity, senderSecret, ... })`
|
|
368
|
+
- [x] `ifWeMight` — `"alpha dep graph matches on source and dest"`: use `getDependencyGraph` + `graphsAreEquivalent`
|
|
369
|
+
- [x] `ifWeMight` — `"sessionIdentity evolved once per sync turn"`: assert `S.data.n` equals number of outgoing turns
|
|
370
370
|
|
|
371
371
|
#### Phase 3B — Space-Gib integrated (manual)
|
|
372
372
|
|
|
373
|
-
- [
|
|
374
|
-
- [
|
|
375
|
-
- [
|
|
376
|
-
- [
|
|
377
|
-
- [
|
|
378
|
-
- [
|
|
379
|
-
- [
|
|
380
|
-
- [
|
|
373
|
+
- [x] Trigger a sync of a known test ibgib via `dev-tools.mts` or equivalent UI
|
|
374
|
+
- [x] Confirm S evolves on each outgoing turn (inspect frame `data.n` in debugger)
|
|
375
|
+
- [x] Confirm X's full dependency graph is present on the client after commit
|
|
376
|
+
- [x] Confirm X's full dependency graph is present on the server after commit
|
|
377
|
+
- [x] Confirm S's full dependency graph is present on the client after commit
|
|
378
|
+
- [x] Confirm S's full dependency graph is present on the server after commit
|
|
379
|
+
- [x] Confirm I's full dependency graph is present on the client after commit
|
|
380
|
+
- [x] Confirm I's full dependency graph is present on the server after commit
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
### Phase 4 — Advanced Data and Conflict Scenarios
|
|
385
|
+
|
|
386
|
+
**Goal**: Extend the WebSocket peer and Space-Gib interface to manually execute and verify all advanced data and conflict scenarios currently covered by the InnerSpace unit tests.
|
|
387
|
+
|
|
388
|
+
For each scenario, verify automated innerspace tests (A) are fully functional, and create manual websocket peer tests (B) with corresponding buttons/UI elements.
|
|
389
|
+
|
|
390
|
+
#### 1. Sync InnerSpace (Basic Push Sync)
|
|
391
|
+
- [ ] Phase 4.1A — Automated InnerSpace Verification (`sync-innerspace.respec.mts`)
|
|
392
|
+
- [ ] Phase 4.1B — WebSocket Peer Manual Verification (integrated via Dev Tools)
|
|
393
|
+
* Tests basic push sync of a single timeline and its mutations from Source to Destination.
|
|
394
|
+
* Verifies that the target timeline tip and its dependency graph successfully arrive at the destination.
|
|
395
|
+
|
|
396
|
+
#### 2. Sync Constants (No TJP)
|
|
397
|
+
- [ ] Phase 4.2A — Automated InnerSpace Verification (`sync-innerspace-constants.respec.mts`)
|
|
398
|
+
- [ ] Phase 4.2B — WebSocket Peer Manual Verification (integrated via Dev Tools)
|
|
399
|
+
* Tests syncing "constants" (ibGibs without timelines/TJPs) and verifies that dependencies (linked constants) are resolved.
|
|
400
|
+
* Ensures idempotency/smart diffing (payloads are not re-sent if they already exist in the destination space).
|
|
401
|
+
|
|
402
|
+
#### 3. Sync Destination with Partial History
|
|
403
|
+
- [ ] Phase 4.3A — Automated InnerSpace Verification (`sync-innerspace-partial-update.respec.mts`)
|
|
404
|
+
- [ ] Phase 4.3B — WebSocket Peer Manual Verification (integrated via Dev Tools)
|
|
405
|
+
* Tests push synchronization when the destination already contains a partial timeline history (e.g., up to V1), but the sender has newer frames (V2).
|
|
406
|
+
* Verifies that only the delta is transmitted and correctly linked to the existing history at the destination.
|
|
407
|
+
|
|
408
|
+
#### 4. Sync Deep History Updates
|
|
409
|
+
- [ ] Phase 4.4A — Automated InnerSpace Verification (`sync-innerspace-deep-updates.respec.mts`)
|
|
410
|
+
- [ ] Phase 4.4B — WebSocket Peer Manual Verification (integrated via Dev Tools)
|
|
411
|
+
* Tests push synchronization of a timeline tip with a deep mutation history (multiple updates).
|
|
412
|
+
* Verifies that the destination receives all intermediate frames, preserving the full timeline history and graph integrity.
|
|
413
|
+
|
|
414
|
+
#### 5. Sync Destination Ahead (Remote Newer)
|
|
415
|
+
- [ ] Phase 4.5A — Automated InnerSpace Verification (`sync-innerspace-dest-ahead.respec.mts`)
|
|
416
|
+
- [ ] Phase 4.5B — WebSocket Peer Manual Verification (integrated via Dev Tools)
|
|
417
|
+
* Tests synchronization when the destination (remote) actually has a newer frame (V2) than the sender's local tip (V1).
|
|
418
|
+
* Verifies that the sender learns of the remote tip and pulls it down so both client and server converge to the dest-ahead tip.
|
|
419
|
+
|
|
420
|
+
#### 6. Sync Multiple Independent Timelines
|
|
421
|
+
- [ ] Phase 4.6A — Automated InnerSpace Verification (`sync-innerspace-multiple-timelines.respec.mts`)
|
|
422
|
+
- [ ] Phase 4.6B — WebSocket Peer Manual Verification (integrated via Dev Tools)
|
|
423
|
+
* Tests synchronization of multiple independent timelines (e.g., Timeline A and Timeline B) in a single sync coordinator call.
|
|
424
|
+
* Verifies that both timeline tips and their respective dependency graphs are transferred and updated correctly.
|
|
425
|
+
|
|
426
|
+
#### 7. Basic Divergence Conflict Resolution
|
|
427
|
+
- [ ] Phase 4.7A — Automated InnerSpace Verification (`sync-conflict-basic-divergence.respec.mts`)
|
|
428
|
+
- [ ] Phase 4.7B — WebSocket Peer Manual Verification (integrated via Dev Tools)
|
|
429
|
+
* Tests divergence when source and destination edit different fields on a shared base timeline simultaneously.
|
|
430
|
+
* Verifies that optimistic merge automatically produces a merged tip (V3) containing both edits and records the graft metadata (`graftbase`, `graftorphan`).
|
|
431
|
+
|
|
432
|
+
#### 8. Divergence with Related Timelines
|
|
433
|
+
- [ ] Phase 4.8A — Automated InnerSpace Verification (`sync-conflict-basic-multitimelines.respec.mts`)
|
|
434
|
+
- [ ] Phase 4.8B — WebSocket Peer Manual Verification (integrated via Dev Tools)
|
|
435
|
+
* Tests advanced divergence where one of the divergent updates also references/relates a new independent timeline (Beta).
|
|
436
|
+
* Verifies that during optimistic merge, the dependent timeline is synced automatically alongside the merged tip.
|
|
437
|
+
|
|
438
|
+
#### 9. Text Field Merge (LCS) Conflict Resolution
|
|
439
|
+
- [ ] Phase 4.9A — Automated InnerSpace Verification (`sync-conflict-text-merge.respec.mts`)
|
|
440
|
+
- [ ] Phase 4.9B — WebSocket Peer Manual Verification (integrated via Dev Tools)
|
|
441
|
+
* Tests automatic merging of conflicting string edits within the `ibgib.data.text` field using the LCS (Longest Common Subsequence) merge algorithm.
|
|
442
|
+
* Verifies merging of simple appends (beginning vs. end) and interleaved edits in different paragraphs.
|
|
443
|
+
|
|
444
|
+
#### 10. Advanced Multi-Round/Timeline Permutations
|
|
445
|
+
- [ ] Phase 4.10A — Automated InnerSpace Verification (`sync-conflict-adv-multitimelines.respec.mts`)
|
|
446
|
+
- [ ] Phase 4.10B — WebSocket Peer Manual Verification (integrated via Dev Tools)
|
|
447
|
+
* Tests complex multi-round/timeline permutations with parallel divergent edits across multiple rounds.
|
|
448
|
+
* Verifies that nested or sequential merges resolve correctly using the optimistic graft strategy.
|
|
@@ -8,7 +8,7 @@ import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
|
|
|
8
8
|
import { GLOBAL_LOG_A_LOT } from '../../../core-constants.mjs';
|
|
9
9
|
import { SyncPeer_V1 } from '../sync-peer-v1.mjs';
|
|
10
10
|
import { SyncSagaContextIbGib_V1 } from '../../sync-saga-context/sync-saga-context-types.mjs';
|
|
11
|
-
import {
|
|
11
|
+
import { authenticateContextIntrinsically } from '../../sync-saga-context/sync-saga-context-helpers.mjs';
|
|
12
12
|
import { IbGibSpaceAny } from '../../../witness/space/space-base-v1.mjs';
|
|
13
13
|
import {
|
|
14
14
|
InitializeSyncPeerHttpReceiverOpts,
|
|
@@ -160,13 +160,16 @@ export class SyncPeerHttpReceiver_V1
|
|
|
160
160
|
|
|
161
161
|
// Put control ibgibs into durable space
|
|
162
162
|
const allControlIbGibs = [context, ...payloadIbGibsControl];
|
|
163
|
+
if (context.signedSessionIdentity) {
|
|
164
|
+
allControlIbGibs.push(context.signedSessionIdentity);
|
|
165
|
+
}
|
|
163
166
|
for (const ibGib of allControlIbGibs) {
|
|
164
167
|
await putInSpace({ space: localSpace, ibGibs: [ibGib] });
|
|
165
168
|
await registerNewIbGib({ space: localSpace, ibGib });
|
|
166
169
|
}
|
|
167
170
|
|
|
168
171
|
// Auth verification (Bill architecture: turn-based context signing)
|
|
169
|
-
const authErrors = await
|
|
172
|
+
const authErrors = await authenticateContextIntrinsically({
|
|
170
173
|
context,
|
|
171
174
|
space: localSpace,
|
|
172
175
|
});
|
|
@@ -186,6 +189,7 @@ export class SyncPeerHttpReceiver_V1
|
|
|
186
189
|
metaspace: localMetaspace,
|
|
187
190
|
mySpace: localSpace,
|
|
188
191
|
myTempSpace: localTempSpace,
|
|
192
|
+
peer: this,
|
|
189
193
|
});
|
|
190
194
|
|
|
191
195
|
return responseCtx || undefined;
|
|
@@ -45,7 +45,7 @@ export interface SyncPeerInnerspaceOptions {
|
|
|
45
45
|
*/
|
|
46
46
|
receiverTempSpace?: IbGibSpaceAny;
|
|
47
47
|
/**
|
|
48
|
-
* The sender coordinator, used for authentication-related (
|
|
48
|
+
* The sender coordinator, used for authentication-related (keystones).
|
|
49
49
|
*/
|
|
50
50
|
senderCoordinator?: SyncSagaCoordinator;
|
|
51
51
|
}
|
|
@@ -12,14 +12,14 @@ import { SyncPeer_V1 } from '../sync-peer-v1.mjs';
|
|
|
12
12
|
import { putInSpace, registerNewIbGib } from '../../../witness/space/space-helper.mjs';
|
|
13
13
|
import { SyncSagaContextIbGib_V1, } from '../../sync-saga-context/sync-saga-context-types.mjs';
|
|
14
14
|
import { SyncPeerInnerspaceData_V1, SyncPeerInnerspaceIbGib_V1, SyncPeerInnerspaceOptions, SyncPeerInnerspaceRel8ns_V1 } from './sync-peer-innerspace-types.mjs';
|
|
15
|
-
import {
|
|
15
|
+
import { authenticateContextIntrinsically } from '../../sync-saga-context/sync-saga-context-helpers.mjs';
|
|
16
16
|
import { MetaspaceService } from '../../../witness/space/metaspace/metaspace-types.mjs';
|
|
17
17
|
import { SyncSagaCoordinator } from '../../sync-saga-coordinator.mjs';
|
|
18
18
|
import { ConnectSyncPeerOpts, InitializeSyncPeerOpts } from '../sync-peer-types.mjs';
|
|
19
19
|
import { getSyncSagaFrameDependencyGraph, putInSpace_dnasThenNonDnas } from '../../sync-helpers.mjs';
|
|
20
20
|
import { getDependencyGraph } from '../../../common/other/graph-helper.mjs';
|
|
21
21
|
import { SyncStage } from '../../sync-constants.mjs';
|
|
22
|
-
import { toDto } from '../../../common/other/ibgib-helper.mjs';import { KeystoneIbGib_V1 } from '../../../keystone/keystone-types.mjs';
|
|
22
|
+
import { toDto } from '../../../common/other/ibgib-helper.mjs'; import { KeystoneIbGib_V1 } from '../../../keystone/keystone-types.mjs';
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
const logalot = GLOBAL_LOG_A_LOT;
|
|
@@ -52,7 +52,7 @@ export interface InitializeSyncPeerInnerspaceOpts extends InitializeSyncPeerOpts
|
|
|
52
52
|
*/
|
|
53
53
|
receiverTempSpace?: IbGibSpaceAny;
|
|
54
54
|
/**
|
|
55
|
-
* The sender coordinator, used for authentication-related (
|
|
55
|
+
* The sender coordinator, used for authentication-related (keystones).
|
|
56
56
|
*/
|
|
57
57
|
senderCoordinator?: SyncSagaCoordinator;
|
|
58
58
|
}
|
|
@@ -205,6 +205,7 @@ export class SyncPeerInnerspace_V1 extends SyncPeer_V1<ConnectSyncPeerInnerspace
|
|
|
205
205
|
|
|
206
206
|
const { sagaFrame } = context;
|
|
207
207
|
|
|
208
|
+
|
|
208
209
|
// The context has already been validated, authenticated and authorized at this point.
|
|
209
210
|
|
|
210
211
|
// #region sanity validation assertions
|
|
@@ -242,8 +243,7 @@ export class SyncPeerInnerspace_V1 extends SyncPeer_V1<ConnectSyncPeerInnerspace
|
|
|
242
243
|
const msg = msgStones[0];
|
|
243
244
|
if (!msg.data) { throw new Error(`(UNEXPECTED) sync saga message ibgib.data falsy? (E: 61ec18743988ad3cbab2072d1dd69826)`); }
|
|
244
245
|
|
|
245
|
-
|
|
246
|
-
// this is where we did the i dentityIbGibs
|
|
246
|
+
// this is where we did the identityIbGibs
|
|
247
247
|
|
|
248
248
|
// send the context itself, then send the payload ibgibs separately.
|
|
249
249
|
// in this innerspace, this just means putting the control ibgibs
|
|
@@ -257,6 +257,9 @@ export class SyncPeerInnerspace_V1 extends SyncPeer_V1<ConnectSyncPeerInnerspace
|
|
|
257
257
|
const payloadIbGibsControl = [
|
|
258
258
|
msg, sagaFrame, context
|
|
259
259
|
].map(x => toDto({ ibGib: x }));
|
|
260
|
+
if (context.signedSessionIdentity) {
|
|
261
|
+
payloadIbGibsControl.push(toDto({ ibGib: context.signedSessionIdentity }));
|
|
262
|
+
}
|
|
260
263
|
if (logalot) { console.log(`${lc} putting into receiverSpace: ${receiverSpace.ib} (I: 1ba18b14a26bdd0e7800da4812898826)`); }
|
|
261
264
|
await putInSpace({
|
|
262
265
|
ibGibs: payloadIbGibsControl,
|
|
@@ -288,20 +291,14 @@ export class SyncPeerInnerspace_V1 extends SyncPeer_V1<ConnectSyncPeerInnerspace
|
|
|
288
291
|
// the payload ibgibs. so the receiver coordinator should be ready
|
|
289
292
|
// to do its thing.
|
|
290
293
|
|
|
291
|
-
//
|
|
292
|
-
const authErrors = await authenticateContext({
|
|
293
|
-
context,
|
|
294
|
-
space: receiverSpace,
|
|
295
|
-
});
|
|
296
|
-
if (authErrors.length > 0) {
|
|
297
|
-
throw new Error(`Context authentication failed: ${authErrors.join(', ')} (E: d34b8ad98d84e1ba8d8f7facd288826)`);
|
|
298
|
-
}
|
|
294
|
+
// NOTE: We have already validated/authenticated/authorized context at this point, as we called it before invoking this method (sendContextRequest)
|
|
299
295
|
|
|
300
296
|
const responseCtx = await receiverCoordinator.continueSync({
|
|
301
297
|
sagaContext: context,
|
|
302
298
|
metaspace: receiverMetaspace,
|
|
303
299
|
mySpace: receiverSpace,
|
|
304
300
|
myTempSpace: receiverTempSpace,
|
|
301
|
+
peer: this,
|
|
305
302
|
});
|
|
306
303
|
|
|
307
304
|
if (logalot) { console.log(`${lc} receiverCoordinator.continueSync responseCtx: ${responseCtx ? pretty(responseCtx) : 'undefined'} (I: fb2831decde1f2b3589021f85ab19126)`); }
|
|
@@ -328,7 +325,7 @@ export class SyncPeerInnerspace_V1 extends SyncPeer_V1<ConnectSyncPeerInnerspace
|
|
|
328
325
|
if (!msgResponse.data) { throw new Error(`(UNEXPECTED) sync saga message ibgib.data falsy? (E: 61ec18743988ad3cbab2072d1dd69826)`); }
|
|
329
326
|
|
|
330
327
|
const responsePayloadIbGibsControl = [
|
|
331
|
-
msgResponse, responseCtx.sagaFrame,
|
|
328
|
+
msgResponse, responseCtx.sagaFrame, responseCtx
|
|
332
329
|
].map(x => toDto({ ibGib: x }));
|
|
333
330
|
// ...put into sender's durable space
|
|
334
331
|
await putInSpace({
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { IbGibData_V1, IbGibRel8ns_V1, IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
|
|
6
|
+
import { IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';
|
|
6
7
|
|
|
7
8
|
import { SubjectWitness } from '../../common/pubsub/subject/subject-types.mjs';
|
|
8
9
|
import { SyncSagaContextData_V1, SyncSagaContextIbGib_V1, SyncSagaContextRel8ns_V1 } from '../sync-saga-context/sync-saga-context-types.mjs';
|
|
@@ -162,6 +163,12 @@ export interface SyncPeerWitness<TInitializeOpts extends InitializeSyncPeerOpts
|
|
|
162
163
|
*/
|
|
163
164
|
payloadIbGibsDomainReceived$: SubjectWitness<IbGib_V1>;
|
|
164
165
|
|
|
166
|
+
currentSessionIdentity: KeystoneIbGib_V1 | undefined;
|
|
167
|
+
/**
|
|
168
|
+
* convenience getter for {@link currentSessionIdentity}
|
|
169
|
+
*/
|
|
170
|
+
get currentSessionIdentityAddr(): IbGibAddr | undefined;
|
|
171
|
+
|
|
165
172
|
/**
|
|
166
173
|
* Pre-connect phase: creates the session keystone (S) locally, evolves
|
|
167
174
|
* `senderIdentity` (I → I1) with a `sync` claim targeting S, and posts
|
|
@@ -174,7 +181,7 @@ export interface SyncPeerWitness<TInitializeOpts extends InitializeSyncPeerOpts
|
|
|
174
181
|
* this reference for the remainder of the saga. The name `newSenderIdentity`
|
|
175
182
|
* (I1) is intentionally scoped only within this method to avoid confusion.
|
|
176
183
|
*/
|
|
177
|
-
establishSessionIdentity(): Promise<
|
|
184
|
+
establishSessionIdentity(): Promise<void>;
|
|
178
185
|
|
|
179
186
|
/**
|
|
180
187
|
* Establishes the connection context.
|
|
@@ -184,4 +191,24 @@ export interface SyncPeerWitness<TInitializeOpts extends InitializeSyncPeerOpts
|
|
|
184
191
|
* @param opts Connection options, including the sagaId for the upcoming sync saga.
|
|
185
192
|
*/
|
|
186
193
|
connect(opts?: { sagaId?: string }): Promise<void>;
|
|
194
|
+
|
|
195
|
+
// /**
|
|
196
|
+
// * Returns the sender's long-lived primary/domain identity.
|
|
197
|
+
// */
|
|
198
|
+
// getSenderIdentity(): KeystoneIbGib_V1 | undefined;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Evolves the session identity (S_n -> S_n+1) and signs targeting
|
|
202
|
+
* contextAddr for the **sync** verb. This is in contrast to signing for
|
|
203
|
+
* the "connect" verb, for which you use {@link signContextConnect}
|
|
204
|
+
*/
|
|
205
|
+
signContext(opts: { contextAddr: IbGibAddr }): Promise<KeystoneIbGib_V1 | undefined>;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Evolves the session identity (S_n -> S_n+1) solving the demanded connect
|
|
209
|
+
* challenges. This is NOT for signing session when doing the ping pong of
|
|
210
|
+
* sync protocol. For that, you use {@link signContext}
|
|
211
|
+
*/
|
|
212
|
+
signContextConnect(opts: { challengeUuid: string, demandedIds: string[] }): Promise<KeystoneIbGib_V1 | undefined>;
|
|
213
|
+
|
|
187
214
|
}
|
|
@@ -7,11 +7,8 @@
|
|
|
7
7
|
import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
|
|
8
8
|
import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
|
|
9
9
|
import { IbGib_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
|
|
10
|
-
import { IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';
|
|
11
|
-
import { validateIbGibIntrinsically } from '@ibgib/ts-gib/dist/V1/validate-helper.mjs';
|
|
12
10
|
|
|
13
11
|
import { GLOBAL_LOG_A_LOT } from '../../core-constants.mjs';
|
|
14
|
-
import { SYNC_MSG_REL8N_NAME, SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN } from '../sync-constants.mjs';
|
|
15
12
|
import { SubjectWitness } from '../../common/pubsub/subject/subject-types.mjs';
|
|
16
13
|
import { SyncSagaContextIbGib_V1 } from '../sync-saga-context/sync-saga-context-types.mjs';
|
|
17
14
|
import {
|
|
@@ -19,19 +16,18 @@ import {
|
|
|
19
16
|
SyncPeerRel8ns_V1, SyncPeerWitness
|
|
20
17
|
} from './sync-peer-types.mjs';
|
|
21
18
|
import { LightWitnessBase_V1 } from '../../witness/light-witness-base-v1.mjs';
|
|
22
|
-
import { IbGibSpaceAny } from '../../witness/space/space-base-v1.mjs';
|
|
23
19
|
import { newupSubject } from '../../common/pubsub/subject/subject-helper.mjs';
|
|
24
|
-
import {
|
|
20
|
+
import { authenticateContextIntrinsically, validateContextAndSagaFrame } from '../sync-saga-context/sync-saga-context-helpers.mjs';
|
|
25
21
|
import { getFromSpace } from '../../witness/space/space-helper.mjs';
|
|
26
22
|
import { getFullSyncSagaHistory, deriveSessionSecret } from '../sync-helpers.mjs';
|
|
27
|
-
import { SyncSagaFrameDependencyGraph } from '../sync-types.mjs';
|
|
23
|
+
import { SessionGenesisFrameDetails, SyncSagaFrameDependencyGraph } from '../sync-types.mjs';
|
|
28
24
|
import { KeystoneService_V1 } from '../../keystone/keystone-service-v1.mjs';
|
|
29
25
|
import { KeystoneIbGib_V1 } from '../../keystone/keystone-types.mjs';
|
|
30
|
-
import { KEYSTONE_VERB_SYNC } from '../../keystone/keystone-constants.mjs';
|
|
26
|
+
import { KEYSTONE_VERB_CONNECT, KEYSTONE_VERB_SYNC, POOL_ID_CONNECT, } from '../../keystone/keystone-constants.mjs';
|
|
27
|
+
import { getTjpAddr } from '../../common/other/ibgib-helper.mjs';
|
|
28
|
+
import { IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';
|
|
31
29
|
|
|
32
30
|
const logalot = GLOBAL_LOG_A_LOT;
|
|
33
|
-
const logalotControlDomain = false;
|
|
34
|
-
const lcControlDomain = '[ControlDomain]';
|
|
35
31
|
|
|
36
32
|
|
|
37
33
|
/**
|
|
@@ -54,6 +50,100 @@ export abstract class SyncPeer_V1<
|
|
|
54
50
|
|
|
55
51
|
public opts: TInitializeOpts | undefined;
|
|
56
52
|
public payloadIbGibsDomainReceived$!: SubjectWitness<IbGib_V1>;
|
|
53
|
+
public currentSessionIdentity: KeystoneIbGib_V1 | undefined;
|
|
54
|
+
public get currentSessionIdentityAddr(): IbGibAddr | undefined {
|
|
55
|
+
return this.currentSessionIdentity ?
|
|
56
|
+
getIbGibAddr({ ibGib: this.currentSessionIdentity }) :
|
|
57
|
+
undefined;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// public getSenderIdentity(): KeystoneIbGib_V1 | undefined {
|
|
61
|
+
// return this.opts?.senderIdentity;
|
|
62
|
+
// }
|
|
63
|
+
|
|
64
|
+
public async signContext({
|
|
65
|
+
contextAddr,
|
|
66
|
+
}: {
|
|
67
|
+
contextAddr: IbGibAddr;
|
|
68
|
+
}): Promise<KeystoneIbGib_V1 | undefined> {
|
|
69
|
+
const lc = `${this.lc}[${this.signContext.name}]`;
|
|
70
|
+
try {
|
|
71
|
+
if (!this.currentSessionIdentity) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
if (!this.opts) { throw new Error(`opts not initialized. (E: bcf5978aed789b0ebcbdc51971ebe826)`); }
|
|
75
|
+
const { fnSenderSecret, sagaId, localMetaspace, localSpace } = this.opts;
|
|
76
|
+
if (!fnSenderSecret) { throw new Error(`fnSenderSecret not initialized. (E: 207fd292a2e8c53c05fd0a74a4ae6d26)`); }
|
|
77
|
+
if (!sagaId) { throw new Error(`sagaId not initialized. (E: f2e35cc13ed873b638116188119d1826)`); }
|
|
78
|
+
|
|
79
|
+
const senderSecret = await fnSenderSecret();
|
|
80
|
+
const sessionSecret = await deriveSessionSecret({ senderSecret, sagaId });
|
|
81
|
+
|
|
82
|
+
const keystoneSvc = new KeystoneService_V1();
|
|
83
|
+
const evolved = await keystoneSvc.sign({
|
|
84
|
+
latestKeystone: this.currentSessionIdentity,
|
|
85
|
+
masterSecret: sessionSecret,
|
|
86
|
+
claim: {
|
|
87
|
+
verb: KEYSTONE_VERB_SYNC,
|
|
88
|
+
target: contextAddr,
|
|
89
|
+
},
|
|
90
|
+
metaspace: localMetaspace,
|
|
91
|
+
space: localSpace,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
this.currentSessionIdentity = evolved;
|
|
95
|
+
return evolved;
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Evolves the session identity (S_n -> S_n+1) solving the demanded connect challenges.
|
|
104
|
+
*/
|
|
105
|
+
public async signContextConnect({
|
|
106
|
+
challengeUuid,
|
|
107
|
+
demandedIds,
|
|
108
|
+
}: {
|
|
109
|
+
challengeUuid: string;
|
|
110
|
+
demandedIds: string[];
|
|
111
|
+
}): Promise<KeystoneIbGib_V1 | undefined> {
|
|
112
|
+
const lc = `${this.lc}[${this.signContextConnect.name}]`;
|
|
113
|
+
try {
|
|
114
|
+
if (!this.currentSessionIdentity) {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
if (!this.opts) { throw new Error(`opts not initialized. (E: bcf5978aed789b0ebcbdc51971ebe826)`); }
|
|
118
|
+
const { fnSenderSecret, sagaId, localMetaspace, localSpace } = this.opts;
|
|
119
|
+
if (!fnSenderSecret) { throw new Error(`fnSenderSecret not initialized. (E: 207fd292a2e8c53c05fd0a74a4ae6d26)`); }
|
|
120
|
+
if (!sagaId) { throw new Error(`sagaId not initialized. (E: f2e35cc13ed873b638116188119d1826)`); }
|
|
121
|
+
|
|
122
|
+
const senderSecret = await fnSenderSecret();
|
|
123
|
+
const sessionSecret = await deriveSessionSecret({ senderSecret, sagaId });
|
|
124
|
+
|
|
125
|
+
const keystoneSvc = new KeystoneService_V1();
|
|
126
|
+
const evolved = await keystoneSvc.sign({
|
|
127
|
+
latestKeystone: this.currentSessionIdentity,
|
|
128
|
+
masterSecret: sessionSecret,
|
|
129
|
+
poolId: POOL_ID_CONNECT,
|
|
130
|
+
requiredChallengeIds: demandedIds,
|
|
131
|
+
claim: {
|
|
132
|
+
verb: KEYSTONE_VERB_CONNECT,
|
|
133
|
+
target: challengeUuid,
|
|
134
|
+
},
|
|
135
|
+
metaspace: localMetaspace,
|
|
136
|
+
space: localSpace,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
this.currentSessionIdentity = evolved;
|
|
140
|
+
return evolved;
|
|
141
|
+
} catch (error) {
|
|
142
|
+
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
57
147
|
|
|
58
148
|
get classname(): string {
|
|
59
149
|
if (!this.data) { throw new Error(`(UNEXPECTED) this.data falsy? (E: 1ab1841e9338b54f3aa615fa37024826)`); }
|
|
@@ -127,7 +217,7 @@ export abstract class SyncPeer_V1<
|
|
|
127
217
|
* hold a reference for subsequent per-turn signing. The name
|
|
128
218
|
* `newSenderIdentity` (I1) is scoped only within this method.
|
|
129
219
|
*/
|
|
130
|
-
public async establishSessionIdentity(): Promise<
|
|
220
|
+
public async establishSessionIdentity(): Promise<void> {
|
|
131
221
|
const lc = `${this.lc}[${this.establishSessionIdentity.name}]`;
|
|
132
222
|
try {
|
|
133
223
|
if (logalot) { console.log(`${lc} starting... (I: f2a1b3c4d5e6f7a8b9c0d1e2f3a4b526)`); }
|
|
@@ -141,6 +231,9 @@ export abstract class SyncPeer_V1<
|
|
|
141
231
|
if (logalot) { console.log(`${lc} no senderIdentity/fnSenderSecret — skipping establish (I: f29348a77d1542326d14043ea4b69126)`); }
|
|
142
232
|
return undefined;
|
|
143
233
|
}
|
|
234
|
+
const senderIdentityAddr = getIbGibAddr({ ibGib: senderIdentity });
|
|
235
|
+
const senderIdentityTjpAddr = getTjpAddr({ ibGib: senderIdentity });
|
|
236
|
+
if (!senderIdentityTjpAddr) { throw new Error(`(UNEXPECTED) senderIdentityTjpAddr falsy? (E: d5d8c3ab25a83a2c127904fe96de1526)`); }
|
|
144
237
|
|
|
145
238
|
if (!sagaId) { throw new Error(`(UNEXPECTED) sagaId falsy? Must be set in initializeOpts before calling establishSessionIdentity. (E: c6ba389d51b8af07d82458f875cf9826)`); }
|
|
146
239
|
|
|
@@ -155,10 +248,19 @@ export abstract class SyncPeer_V1<
|
|
|
155
248
|
if (!this.opts.sessionConnectPoolConfig) { throw new Error(`(UNEXPECTED) opts.sessionConnectPoolConfig falsy? (E: 3351fd566eb8bbd2f821bb08c4419826)`); }
|
|
156
249
|
if (!this.opts.sessionSyncPoolConfig) { throw new Error(`(UNEXPECTED) opts.sessionSyncPoolConfig falsy? (E: dbffa810d9e7ff6079088deb5b8e7826)`); }
|
|
157
250
|
|
|
251
|
+
// session genesis keystone should have soft links to both
|
|
252
|
+
// targetAddrs and the sender identity that spawned it.
|
|
253
|
+
const frameDetails: SessionGenesisFrameDetails = {
|
|
254
|
+
senderIdentityAddr,
|
|
255
|
+
senderIdentityTjpAddr,
|
|
256
|
+
}
|
|
257
|
+
if (this.opts.targetAddrs) {
|
|
258
|
+
frameDetails.targetAddrs = this.opts.targetAddrs
|
|
259
|
+
}
|
|
158
260
|
const sessionIdentity = await keystoneSvc.genesis({
|
|
159
261
|
masterSecret: sessionSecret,
|
|
160
262
|
configs: [this.opts.sessionConnectPoolConfig, this.opts.sessionSyncPoolConfig],
|
|
161
|
-
frameDetails
|
|
263
|
+
frameDetails,
|
|
162
264
|
metaspace: localMetaspace,
|
|
163
265
|
space: localSpace,
|
|
164
266
|
});
|
|
@@ -179,7 +281,7 @@ export abstract class SyncPeer_V1<
|
|
|
179
281
|
// Step 3: Post both to the receiver (peer-specific).
|
|
180
282
|
await this.postEstablishToReceiver({ newSenderIdentity, sessionIdentity });
|
|
181
283
|
|
|
182
|
-
|
|
284
|
+
this.currentSessionIdentity = sessionIdentity;
|
|
183
285
|
} catch (error) {
|
|
184
286
|
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
185
287
|
throw error;
|
|
@@ -257,16 +359,12 @@ export abstract class SyncPeer_V1<
|
|
|
257
359
|
// }
|
|
258
360
|
// }
|
|
259
361
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
protected async authenticateValidateAuthorize({
|
|
362
|
+
protected async authenticateAndValidate({
|
|
263
363
|
context,
|
|
264
|
-
fullSagaHistory,
|
|
265
364
|
}: {
|
|
266
365
|
context: SyncSagaContextIbGib_V1,
|
|
267
|
-
fullSagaHistory: SyncSagaFrameDependencyGraph[],
|
|
268
366
|
}): Promise<void> {
|
|
269
|
-
const lc = `${this.lc}[${this.
|
|
367
|
+
const lc = `${this.lc}[${this.authenticateAndValidate.name}]`;
|
|
270
368
|
try {
|
|
271
369
|
if (logalot) { console.log(`${lc} starting... (I: add238055cd84a222c5b8c89913af526)`); }
|
|
272
370
|
|
|
@@ -274,7 +372,8 @@ export abstract class SyncPeer_V1<
|
|
|
274
372
|
const { localSpace } = this.opts;
|
|
275
373
|
|
|
276
374
|
// first authenticate, because invalid authn is a non-starter
|
|
277
|
-
|
|
375
|
+
// (already validated intrinsically)
|
|
376
|
+
const authenticationErrors = await authenticateContextIntrinsically({
|
|
278
377
|
context,
|
|
279
378
|
space: localSpace,
|
|
280
379
|
});
|
|
@@ -288,12 +387,6 @@ export abstract class SyncPeer_V1<
|
|
|
288
387
|
if (validationErrors.length > 0) {
|
|
289
388
|
throw new Error(`invalid context received. validationErrors: ${validationErrors} (E: 8b34c875c968af29bc433138e57a7826)`);
|
|
290
389
|
}
|
|
291
|
-
// we have a valid authentication that points to a valid context,
|
|
292
|
-
// but what exactly is authorized ?
|
|
293
|
-
const authorizationErrors = await authorizeContext({ context, fullSagaHistory });
|
|
294
|
-
if (authorizationErrors.length > 0) {
|
|
295
|
-
throw new Error(`invalid context authorization. authorizationErrors: ${authorizationErrors} (E: 8ddc284a758cf10ba829334c1babb826)`);
|
|
296
|
-
}
|
|
297
390
|
} catch (error) {
|
|
298
391
|
console.error(`${lc} ${extractErrorMsg(error)}`);
|
|
299
392
|
throw error;
|
|
@@ -361,14 +454,12 @@ export abstract class SyncPeer_V1<
|
|
|
361
454
|
// this is not just happening on the client, but this peer may be
|
|
362
455
|
// the one receiving the context as well.
|
|
363
456
|
|
|
364
|
-
const sagaHistory_beforeSend = await getFullSyncSagaHistory({
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
});
|
|
457
|
+
// const sagaHistory_beforeSend = await getFullSyncSagaHistory({
|
|
458
|
+
// sagaIbGib: context.sagaFrame,
|
|
459
|
+
// space: this.opts.localSpace
|
|
460
|
+
// });
|
|
368
461
|
|
|
369
|
-
await this.
|
|
370
|
-
context, fullSagaHistory: sagaHistory_beforeSend,
|
|
371
|
-
});
|
|
462
|
+
await this.authenticateAndValidate({ context });
|
|
372
463
|
|
|
373
464
|
// at this point, we have a valid, authenticated, authorized context
|
|
374
465
|
|
|
@@ -389,9 +480,10 @@ export abstract class SyncPeer_V1<
|
|
|
389
480
|
space: this.opts.localSpace
|
|
390
481
|
});
|
|
391
482
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
483
|
+
// NOTE: I think this is the wrong place for this, as we must do this in the peer **before** storing any control ibgibs. This needs to be done in the continueSync I _think_ (not sure yet)
|
|
484
|
+
// await this.authenticateValidateAuthorize({
|
|
485
|
+
// context, fullSagaHistory: sagaHistory_afterSend,
|
|
486
|
+
// });
|
|
395
487
|
|
|
396
488
|
return response;
|
|
397
489
|
} else {
|