instar 1.3.602 → 1.3.604

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 (83) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +108 -2
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  5. package/dist/config/ConfigDefaults.js +36 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/CoherenceJournal.d.ts +1 -1
  8. package/dist/core/CoherenceJournal.d.ts.map +1 -1
  9. package/dist/core/CoherenceJournal.js +12 -2
  10. package/dist/core/CoherenceJournal.js.map +1 -1
  11. package/dist/core/CredentialLocationLedger.d.ts +70 -0
  12. package/dist/core/CredentialLocationLedger.d.ts.map +1 -1
  13. package/dist/core/CredentialLocationLedger.js +126 -0
  14. package/dist/core/CredentialLocationLedger.js.map +1 -1
  15. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  16. package/dist/core/PostUpdateMigrator.js +25 -0
  17. package/dist/core/PostUpdateMigrator.js.map +1 -1
  18. package/dist/core/ThreadlinePairingReplicatedStore.d.ts +285 -0
  19. package/dist/core/ThreadlinePairingReplicatedStore.d.ts.map +1 -0
  20. package/dist/core/ThreadlinePairingReplicatedStore.js +462 -0
  21. package/dist/core/ThreadlinePairingReplicatedStore.js.map +1 -0
  22. package/dist/core/devGatedFeatures.d.ts.map +1 -1
  23. package/dist/core/devGatedFeatures.js +5 -0
  24. package/dist/core/devGatedFeatures.js.map +1 -1
  25. package/dist/core/types.d.ts +22 -0
  26. package/dist/core/types.d.ts.map +1 -1
  27. package/dist/core/types.js.map +1 -1
  28. package/dist/scaffold/templates.d.ts.map +1 -1
  29. package/dist/scaffold/templates.js +6 -0
  30. package/dist/scaffold/templates.js.map +1 -1
  31. package/dist/server/routes.d.ts.map +1 -1
  32. package/dist/server/routes.js +323 -0
  33. package/dist/server/routes.js.map +1 -1
  34. package/dist/threadline/AgentTrustManager.d.ts +201 -1
  35. package/dist/threadline/AgentTrustManager.d.ts.map +1 -1
  36. package/dist/threadline/AgentTrustManager.js +395 -2
  37. package/dist/threadline/AgentTrustManager.js.map +1 -1
  38. package/dist/threadline/CredentialShareGate.d.ts +66 -0
  39. package/dist/threadline/CredentialShareGate.d.ts.map +1 -0
  40. package/dist/threadline/CredentialShareGate.js +82 -0
  41. package/dist/threadline/CredentialShareGate.js.map +1 -0
  42. package/dist/threadline/InboundMessageGate.d.ts +46 -1
  43. package/dist/threadline/InboundMessageGate.d.ts.map +1 -1
  44. package/dist/threadline/InboundMessageGate.js +105 -0
  45. package/dist/threadline/InboundMessageGate.js.map +1 -1
  46. package/dist/threadline/PairVerifyReceipt.d.ts +69 -0
  47. package/dist/threadline/PairVerifyReceipt.d.ts.map +1 -0
  48. package/dist/threadline/PairVerifyReceipt.js +151 -0
  49. package/dist/threadline/PairVerifyReceipt.js.map +1 -0
  50. package/dist/threadline/PairingPendingStore.d.ts +55 -0
  51. package/dist/threadline/PairingPendingStore.d.ts.map +1 -0
  52. package/dist/threadline/PairingPendingStore.js +110 -0
  53. package/dist/threadline/PairingPendingStore.js.map +1 -0
  54. package/dist/threadline/ThreadlineBootstrap.d.ts +11 -0
  55. package/dist/threadline/ThreadlineBootstrap.d.ts.map +1 -1
  56. package/dist/threadline/ThreadlineBootstrap.js +5 -0
  57. package/dist/threadline/ThreadlineBootstrap.js.map +1 -1
  58. package/dist/threadline/ThreadlineCrypto.d.ts +28 -0
  59. package/dist/threadline/ThreadlineCrypto.d.ts.map +1 -1
  60. package/dist/threadline/ThreadlineCrypto.js +100 -0
  61. package/dist/threadline/ThreadlineCrypto.js.map +1 -1
  62. package/dist/threadline/ThreadlineEndpoints.d.ts +8 -0
  63. package/dist/threadline/ThreadlineEndpoints.d.ts.map +1 -1
  64. package/dist/threadline/ThreadlineEndpoints.js +5 -0
  65. package/dist/threadline/ThreadlineEndpoints.js.map +1 -1
  66. package/dist/threadline/ThreadlineMCPServer.d.ts +3 -1
  67. package/dist/threadline/ThreadlineMCPServer.d.ts.map +1 -1
  68. package/dist/threadline/ThreadlineMCPServer.js +107 -1
  69. package/dist/threadline/ThreadlineMCPServer.js.map +1 -1
  70. package/dist/threadline/client/ThreadlineClient.d.ts +10 -0
  71. package/dist/threadline/client/ThreadlineClient.d.ts.map +1 -1
  72. package/dist/threadline/client/ThreadlineClient.js +13 -0
  73. package/dist/threadline/client/ThreadlineClient.js.map +1 -1
  74. package/package.json +2 -1
  75. package/scripts/check-e2e-pairing.cjs +4 -1
  76. package/src/data/builtin-manifest.json +63 -63
  77. package/src/data/state-coherence-registry.json +26 -0
  78. package/src/scaffold/templates.ts +6 -0
  79. package/src/threadline/data/sas-wordlist-en.json +1 -0
  80. package/upgrades/1.3.603.md +39 -0
  81. package/upgrades/1.3.604.md +57 -0
  82. package/upgrades/side-effects/credential-identity-audit.md +183 -0
  83. package/upgrades/side-effects/secure-a2a-verified-pairing.md +116 -0
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoCH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAS3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAwBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAkH7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAsBtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAUT;AAyID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAg4CD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,cAAc,EAAE,cAAc,EAC9B,YAAY,CAAC,EAAE,YAAY,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAGvE,UAAU,CAAC,EAAE,MAAM,OAAO,8BAA8B,EAAE,WAAW,GAAG,IAAI,EAK5E,qBAAqB,CAAC,EAAE,MAAM,OAAO,gCAAgC,EAAE,kBAAkB,GAAG,IAAI,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,GACpD,IAAI,CA8eN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA6vdtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoCH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAS3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAwBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAkH7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAsBtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAUT;AAyID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAg4CD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,cAAc,EAAE,cAAc,EAC9B,YAAY,CAAC,EAAE,YAAY,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAGvE,UAAU,CAAC,EAAE,MAAM,OAAO,8BAA8B,EAAE,WAAW,GAAG,IAAI,EAK5E,qBAAqB,CAAC,EAAE,MAAM,OAAO,gCAAgC,EAAE,kBAAkB,GAAG,IAAI,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,GACpD,IAAI,CA8eN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAo4dtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
@@ -3426,6 +3426,20 @@ export async function startServer(options) {
3426
3426
  // answer to "who is my verified operator?" (only the local authenticated setOperator binds it).
3427
3427
  const { TOPIC_OPERATOR_KIND_REGISTRATION } = await import('../core/TopicOperatorReplicatedStore.js');
3428
3428
  replicatedKindRegistry.register(TOPIC_OPERATOR_KIND_REGISTRATION);
3429
+ // Secure A2A Verified Pairing §3.8 (FD11) — register the EIGHTH concrete replicated kind,
3430
+ // `threadline-pairing-record`, onto the registry. Unlike the WS2 memory/PII stores it
3431
+ // replicates ONLY the verified-IDENTITY RESULT of a pairing { peerFp, peerIdentityPub,
3432
+ // state:'mutual-verified', verifiedAt, verifiedOnMachine } — NEVER the SAS, shared secret, or
3433
+ // relay token (those stay machine-local BY DESIGN). Dual-registry's dynamic half (the static
3434
+ // half is CoherenceJournal.JOURNAL_KINDS, which now lists 'threadline-pairing-record').
3435
+ // Registration is INERT — emission/serve/pull stay gated behind
3436
+ // `multiMachine.stateSync.threadlinePairing.enabled` (default false ⇒ strict no-op). Machine B
3437
+ // honors a replicated record ONLY by pinning peerIdentityPub (a mismatching handshake key is
3438
+ // refused inheritance + downgraded to pending-verification); inherited = identity-verified, NOT
3439
+ // channel-ready (the outbound CredentialShareGate enforces the encrypted-path half). A revoke /
3440
+ // verification-failed propagates as a tombstone (ThreadlinePairingReplicatedStore).
3441
+ const { THREADLINE_PAIRING_KIND_REGISTRATION } = await import('../core/ThreadlinePairingReplicatedStore.js');
3442
+ replicatedKindRegistry.register(THREADLINE_PAIRING_KIND_REGISTRATION);
3429
3443
  // ── WS2 SEND-SIDE wiring (docs/specs/WS2-SEND-SIDE-EMISSION-SPEC.md). The
3430
3444
  // substrate above ships the registry + receive/serve machinery + advert; THIS
3431
3445
  // wires the SEND half that was deferred ("the journal-backed emitter is attached
@@ -9232,7 +9246,7 @@ export async function startServer(options) {
9232
9246
  // off (always, while dark) every gate read returns the enrollment-home fallback, so every
9233
9247
  // consumer is byte-for-byte today's behavior. A never-seeded ledger is the same fallback (back-
9234
9248
  // compat); only UNKNOWN mode (corrupt on-disk) raises a HIGH attention item, never throws.
9235
- const { CredentialLocationLedger, shouldBootSeedCredentialLedger } = await import('../core/CredentialLocationLedger.js');
9249
+ const { CredentialLocationLedger, shouldBootSeedCredentialLedger, shouldRunIdentityAudit } = await import('../core/CredentialLocationLedger.js');
9236
9250
  const { CredentialIdentityOracle } = await import('../core/CredentialIdentityOracle.js');
9237
9251
  const { CredentialLocationGate } = await import('../core/CredentialLocationGate.js');
9238
9252
  const credentialGateEmitAttention = telegram
@@ -9432,14 +9446,22 @@ export async function startServer(options) {
9432
9446
  // never blocked on them; failures are loud at the slot level (quarantine + attention) INSIDE
9433
9447
  // seedFromOracle. Seeding writes ONLY the local slot→account map — it moves ZERO credentials
9434
9448
  // (the executor's dryRun gate + the one-home invariant still guard every real swap). <!-- tracked: 20905 -->
9449
+ // `credSeedInFlight` closes the fresh-agent seed↔audit interleave: a never-seeded boot fires
9450
+ // seedFromOracle() fire-and-forget at t=0, and the boot identity audit fires at t≈90s. If the
9451
+ // oracle hangs past 90s the two passes could otherwise touch the in-memory assignments view at
9452
+ // their respective awaits. isSeeded() does NOT protect this (seedFromOracle bumps version at
9453
+ // 'begin', so isSeeded() flips true mid-seed), so the audit gate also checks this flag.
9454
+ let credSeedInFlight = false;
9435
9455
  if (shouldBootSeedCredentialLedger(resolveDevAgentGate(config.subscriptionPool?.credentialRepointing?.enabled, config), credentialLocationLedger.isSeeded())) {
9456
+ credSeedInFlight = true;
9436
9457
  void credentialLocationLedger
9437
9458
  .seedFromOracle()
9438
9459
  .then((outcomes) => {
9439
9460
  const assigned = outcomes.filter((o) => o.result === 'assigned').length;
9440
9461
  console.log(pc.green(` Credential location ledger seeded: ${assigned}/${outcomes.length} slot(s) mapped`));
9441
9462
  })
9442
- .catch((e) => console.warn(`[CredentialLedger] boot seed failed: ${e instanceof Error ? e.message : String(e)}`));
9463
+ .catch((e) => console.warn(`[CredentialLedger] boot seed failed: ${e instanceof Error ? e.message : String(e)}`))
9464
+ .finally(() => { credSeedInFlight = false; });
9443
9465
  }
9444
9466
  // B3b — the periodic balancer pass. tick() is a strict no-op while the feature resolves dark
9445
9467
  // (so the timer can always run; the gate lives INSIDE tick()), and on a dev agent it runs the
@@ -9457,6 +9479,54 @@ export async function startServer(options) {
9457
9479
  .finally(() => { credRebalancerTickInFlight = false; });
9458
9480
  }, credRebalancerPassMs);
9459
9481
  credRebalancerTimer.unref?.();
9482
+ // B3c — the periodic NON-DESTRUCTIVE identity audit. THE FIX for the inert-optimizer bug:
9483
+ // the rebalancer's every objective (wall-rescue AND the use-it-or-lose-it drain) only acts on
9484
+ // a DESTINATION slot whose identity was verified within `auditCadenceMs` (default 6h). Nothing
9485
+ // re-stamped verification after the boot seed (markVerified had zero callers), so every slot
9486
+ // decayed to "not recently verified" and the rebalancer went permanently inert — it decided
9487
+ // nothing because it had no eligible targets. auditIdentities() re-probes each slot and refreshes
9488
+ // its verification (and lets a since-resolvable slot EXIT quarantine), keeping the optimizer's
9489
+ // target set live. It moves ZERO credentials (ledger verification state only); never triggers a
9490
+ // swap; HOLDS a healthy slot on a transient oracle blip (never re-creates the stall). Same
9491
+ // dev-gate as the rebalancer (strict no-op / no probe on the dark fleet); reentrancy-guarded;
9492
+ // unref'd. Audit cadence = half of auditCadenceMs, capped at 30min, floored at 1min, so a
9493
+ // healthy slot is always re-confirmed well inside the verified-recent window. <!-- tracked: 20905 -->
9494
+ const credAuditCadenceMs = credResolveBalancerConfig({
9495
+ ...(config.subscriptionPool?.credentialRepointing?.balancer ?? {}),
9496
+ slotCount: credentialLocationLedger.getAssignments().length,
9497
+ }).auditCadenceMs;
9498
+ const credAuditIntervalMs = Math.max(60_000, Math.min(Math.floor(credAuditCadenceMs / 2), 30 * 60_000));
9499
+ let credAuditInFlight = false;
9500
+ const runCredentialIdentityAudit = async (trigger) => {
9501
+ // Pure, unit-tested gate (shouldRunIdentityAudit): enabled (no-op/no-probe on the dark fleet)
9502
+ // AND seeded AND not UNKNOWN-mode AND not already in flight (reentrancy guard).
9503
+ // `credSeedInFlight` is the runtime seed↔audit interleave guard (a boot seed can be mid-probe
9504
+ // when the boot audit fires); the pure predicate covers the persistent-state gates.
9505
+ if (credSeedInFlight ||
9506
+ !shouldRunIdentityAudit(resolveDevAgentGate(config.subscriptionPool?.credentialRepointing?.enabled, config), credentialLocationLedger.isSeeded(), credentialLocationLedger.isUnknownMode(), credAuditInFlight)) {
9507
+ return;
9508
+ }
9509
+ credAuditInFlight = true;
9510
+ try {
9511
+ const r = await credentialLocationLedger.auditIdentities();
9512
+ if (r.refreshed || r.recovered || r.quarantined) {
9513
+ console.log(pc.dim(` Credential identity audit (${trigger}): ${r.refreshed} refreshed, ${r.recovered} recovered, ${r.quarantined} quarantined, ${r.unresolved} unresolved`));
9514
+ }
9515
+ }
9516
+ catch (e) {
9517
+ console.warn(`[CredentialIdentityAudit] ${trigger} error: ${e instanceof Error ? e.message : String(e)}`);
9518
+ }
9519
+ finally {
9520
+ credAuditInFlight = false;
9521
+ }
9522
+ };
9523
+ // Boot one-shot (delayed so it never races the boot seed) — refreshes stale verification
9524
+ // immediately on restart so a long-running agent's rebalancer has fresh targets without
9525
+ // waiting a full cadence.
9526
+ const credAuditBootTimer = setTimeout(() => void runCredentialIdentityAudit('boot'), 90_000);
9527
+ credAuditBootTimer.unref?.();
9528
+ const credAuditTimer = setInterval(() => void runCredentialIdentityAudit('periodic'), credAuditIntervalMs);
9529
+ credAuditTimer.unref?.();
9460
9530
  // QuotaPoller — per-account live quota reader (P1.2 of the Subscription &
9461
9531
  // Auth Standard). Reads each account's 5h/weekly utilization + reset dates
9462
9532
  // via the OAuth usage endpoint (transient per-account token, never persisted)
@@ -11746,6 +11816,17 @@ export async function startServer(options) {
11746
11816
  relayUrl: config.threadline?.relayUrl,
11747
11817
  visibility: config.threadline?.visibility,
11748
11818
  capabilities: config.threadline?.capabilities,
11819
+ // Secure A2A Verified Pairing (spec §3.10). Live reader so credentialShareEnforced
11820
+ // takes effect without a restart. `enabled` rides the developmentAgent gate when
11821
+ // omitted (dev-live, dark-fleet); when off the inbound gate is a pass-through.
11822
+ getVerifiedPairingConfig: () => {
11823
+ const vp = config.threadline?.verifiedPairing;
11824
+ return {
11825
+ enabled: resolveDevAgentGate(vp?.enabled, config),
11826
+ dryRun: vp?.dryRun ?? true,
11827
+ credentialShareEnforced: vp?.credentialShareEnforced ?? false,
11828
+ };
11829
+ },
11749
11830
  });
11750
11831
  threadlineHandshake = threadline.handshakeManager;
11751
11832
  threadlineShutdown = threadline.shutdown;
@@ -11763,6 +11844,31 @@ export async function startServer(options) {
11763
11844
  console.error(`Unified trust system init failed (non-fatal): ${err instanceof Error ? err.message : err}`);
11764
11845
  }
11765
11846
  }
11847
+ // Secure A2A Verified Pairing §3.8 (FD11) — SEND-SIDE: attach the journal-backed
11848
+ // emitter to the trust manager's pairing-replication hooks so a local markMutualVerified
11849
+ // ALSO replicates the verified-IDENTITY RESULT to the agent's OWN machines, and a
11850
+ // verification-failed propagates a tombstone. The emitter is handed ONLY the 5-field
11851
+ // result (it has NO access to the SAS store), so the SAS / shared secret / relay token
11852
+ // can never cross. Gated on the EXPLICIT `multiMachine.stateSync.threadlinePairing.enabled`
11853
+ // (default false ⇒ NOT attached ⇒ strict no-op, single-machine behavior). Attached only
11854
+ // when the journal-backed emitter exists (journal live) AND the store is enabled.
11855
+ if (threadline.trustManager && replicatedRecordEmitter && cjOwnMachineId) {
11856
+ const pairingStoreEnabled = config.multiMachine?.stateSync
11857
+ ?.threadlinePairing?.enabled === true;
11858
+ if (pairingStoreEnabled) {
11859
+ const emitter = replicatedRecordEmitter;
11860
+ const { THREADLINE_PAIRING_STORE_KEY, deriveThreadlinePairingRecordKey, buildThreadlinePairingRecordData, buildThreadlinePairingTombstoneData, } = await import('../core/ThreadlinePairingReplicatedStore.js');
11861
+ threadline.trustManager.setPairingReplicationEmitter({
11862
+ emitVerified: (result) => emitter.emit(THREADLINE_PAIRING_STORE_KEY, deriveThreadlinePairingRecordKey(result.peerFp), (hlc, origin, observed) => buildThreadlinePairingRecordData({
11863
+ result: { ...result, state: 'mutual-verified' },
11864
+ hlc,
11865
+ origin,
11866
+ observed,
11867
+ })),
11868
+ emitRevoke: (peerFp, deletedAt) => emitter.emit(THREADLINE_PAIRING_STORE_KEY, deriveThreadlinePairingRecordKey(peerFp), (hlc, origin, observed) => buildThreadlinePairingTombstoneData({ peerFp, hlc, origin, deletedAt, observed })),
11869
+ }, cjOwnMachineId);
11870
+ }
11871
+ }
11766
11872
  if (threadlineRelayClient) {
11767
11873
  // Wire relay message delivery through ThreadlineRouter (Phase 1).
11768
11874
  // Replaces the ad-hoc handler with proper thread persistence, auto-ack,