@ibgib/space-gib 0.0.2 → 0.0.4

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 (67) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/IMPLEMENTATION.md +9 -13
  3. package/dist/client/bootstrap.mjs +1 -1
  4. package/dist/client/bootstrap.mjs.map +1 -1
  5. package/dist/client/chunk-NCXKCVYS.mjs +42 -0
  6. package/dist/client/chunk-NCXKCVYS.mjs.map +7 -0
  7. package/dist/client/chunk-ZUEU37Z5.mjs +1920 -0
  8. package/dist/client/chunk-ZUEU37Z5.mjs.map +7 -0
  9. package/dist/client/index.html +108 -8
  10. package/dist/client/index.mjs +1 -1
  11. package/dist/client/script.mjs +1 -1
  12. package/dist/client/style.css +466 -61
  13. package/dist/respec-gib.node.mjs +5 -0
  14. package/dist/server/server.mjs +815 -316
  15. package/dist/server/server.mjs.map +4 -4
  16. package/package.json +6 -6
  17. package/src/client/AUTO-GENERATED-version.mts +1 -1
  18. package/src/client/api/space-gib-api-bridge.mts +35 -0
  19. package/src/client/components/identity-header/IMPLEMENTATION.md +45 -0
  20. package/src/client/components/identity-header/identity-header.css +74 -0
  21. package/src/client/components/identity-header/identity-header.html +10 -0
  22. package/src/client/components/identity-header/identity-header.mts +361 -0
  23. package/src/client/components/identity-manager/IMPLEMENTATION.md +100 -0
  24. package/src/client/components/identity-manager/identity-manager.css +467 -0
  25. package/src/client/components/identity-manager/identity-manager.html +113 -0
  26. package/src/client/components/identity-manager/identity-manager.mts +767 -0
  27. package/src/client/components/keystone-creator/keystone-creator.css +2 -76
  28. package/src/client/components/keystone-creator/keystone-creator.html +41 -26
  29. package/src/client/components/keystone-creator/keystone-creator.mts +178 -41
  30. package/src/client/dev-tools/base-tools.mts +252 -0
  31. package/src/client/dev-tools/common.mts +217 -0
  32. package/src/client/dev-tools/phase-1.mts +156 -0
  33. package/src/client/dev-tools/phase-2.mts +143 -0
  34. package/src/client/dev-tools/phase-3.mts +189 -0
  35. package/src/client/dev-tools/phase-4-1.mts +197 -0
  36. package/src/client/dev-tools/phase-4-10.mts +884 -0
  37. package/src/client/dev-tools/phase-4-2.mts +388 -0
  38. package/src/client/dev-tools/phase-4-3.mts +391 -0
  39. package/src/client/dev-tools/phase-4-4.mts +374 -0
  40. package/src/client/dev-tools/phase-4-5.mts +376 -0
  41. package/src/client/dev-tools/phase-4-6.mts +273 -0
  42. package/src/client/dev-tools/phase-4-7.mts +399 -0
  43. package/src/client/dev-tools/phase-4-8.mts +430 -0
  44. package/src/client/dev-tools/phase-4-9.mts +398 -0
  45. package/src/client/dev-tools/phase-4.mts +1302 -0
  46. package/src/client/dev-tools.mts +55 -1096
  47. package/src/client/index.html +108 -8
  48. package/src/client/style.css +466 -61
  49. package/src/client/ui/shell/space-gib-shell-constants.mts +0 -2
  50. package/src/client/ui/shell/space-gib-shell-service.mts +82 -10
  51. package/src/common/common-constants.mts +0 -0
  52. package/src/common/keystone-policies.json +40 -43
  53. package/src/common/keystone-policies.mts +4 -6
  54. package/src/server/path-helper.respec.mts +99 -94
  55. package/src/server/serve-gib/README.md +9 -0
  56. package/src/server/serve-gib/handlers/api/keystone/keystone-evolve.handler.mts +1 -1
  57. package/src/server/serve-gib/handlers/api/keystone/keystone-genesis.handler.mts +1 -1
  58. package/src/server/serve-gib/handlers/api/keystone/keystone-get.respec.mts +4 -4
  59. package/src/server/serve-gib/handlers/api/keystone/keystone-post.handler.mts +1 -1
  60. package/src/server/serve-gib/handlers/ws/sync-upgrade-handler-base.mts +37 -5
  61. package/src/server/serve-gib/handlers/ws/ws-helper.mts +73 -45
  62. package/dist/client/chunk-BL2SGXS4.mjs +0 -18994
  63. package/dist/client/chunk-RDTAT5G4.mjs +0 -235
  64. package/dist/client/chunk-RDTAT5G4.mjs.map +0 -7
  65. package/dist/client/chunk-RE7XSMHH.mjs +0 -31
  66. package/dist/client/chunk-RE7XSMHH.mjs.map +0 -7
  67. package/dist/client/chunk-YUSGN3J4.mjs +0 -23119
@@ -7261,7 +7261,7 @@ async function getGraphProjection_Live({ ibGibs, ibGibAddrs, gotten, tjpAddrsAlr
7261
7261
  rel8nNames.forEach((rel8nName) => {
7262
7262
  const rel8dAddrs = rel8ns[rel8nName] ?? [];
7263
7263
  rel8dAddrs.forEach((rel8dAddr) => {
7264
- if (!rel8dAddrsNotYetGotten.includes(rel8dAddr) && !ibGibs.some((x) => getIbGibAddr({ ibGib: x }) === rel8dAddr)) {
7264
+ if (!rel8dAddrsNotYetGotten.includes(rel8dAddr) && !ibGibs.some((x) => getIbGibAddr({ ibGib: x }) === rel8dAddr) && !isPrimitive({ gib: getIbAndGib({ ibGibAddr: rel8dAddr }).gib })) {
7265
7265
  rel8dAddrsNotYetGotten.push(rel8dAddr);
7266
7266
  }
7267
7267
  });
@@ -17650,6 +17650,8 @@ var KEYSTONE_REPLENISH_STRATEGY_VALID_VALUES = Object.values(KeystoneReplenishSt
17650
17650
  var KEYSTONE_ATOM = "keystone";
17651
17651
  var KEYSTONE_POOL_ID_REGEXP = /^\w[\w\-.]*$/;
17652
17652
  var KEYSTONE_SALT_REGEXP = /^[a-zA-Z0-9\-_]{1,64}$/;
17653
+ var KEYSTONE_USERNAME_REGEXP = /^[a-zA-Z0-9_\-.]{1,63}$/;
17654
+ var KEYSTONE_DESCRIPTION_REGEXP = /^[a-zA-Z0-9\s.,!?:;'"\-()[\]_+=@#$%&*\/]{0,128}$/;
17653
17655
  var KEYSTONE_HASH_MAX_ROUNDS = 1e3;
17654
17656
  var KEYSTONE_VERB_REVOKE = "revoke";
17655
17657
  var KEYSTONE_VERB_MANAGE = "manage";
@@ -17938,7 +17940,7 @@ async function parseKeystoneIb({ ib }) {
17938
17940
  }
17939
17941
  }
17940
17942
  }
17941
- function getDeterministicRequirements({ pool, requiredChallengeIds, targetAddr }) {
17943
+ async function getDeterministicRequirements({ pool, requiredChallengeIds, targetAddr }) {
17942
17944
  const behavior = pool.config.behavior;
17943
17945
  const mandatory = /* @__PURE__ */ new Set();
17944
17946
  let available = Object.keys(pool.challenges);
@@ -17954,19 +17956,20 @@ function getDeterministicRequirements({ pool, requiredChallengeIds, targetAddr }
17954
17956
  }
17955
17957
  available = available.filter((id) => !mandatory.has(id));
17956
17958
  }
17957
- if (behavior.targetBindingChars > 0 && targetAddr) {
17958
- const { gib } = getIbAndGib({ ibGibAddr: targetAddr });
17959
- if (gib) {
17960
- const prefixes = gib !== GIB ? gib.substring(0, behavior.targetBindingChars).toLowerCase() : "abc";
17961
- for (const char of prefixes) {
17962
- const bucket = pool.bindingMap[char] || [];
17963
- const match = bucket.find((id) => available.includes(id));
17964
- if (!match) {
17965
- throw new Error(`Entropy Exhaustion. Cannot satisfy binding for char '${char}'. (E: 341b95dc3a58be3e083d1d9c4a0c4925)`);
17966
- }
17967
- mandatory.add(match);
17968
- available = available.filter((id) => id !== match);
17959
+ if (behavior.targetBindingCount > 0 && targetAddr) {
17960
+ let sortedAvailable = [...available].sort();
17961
+ let currentHash = await hash({ s: targetAddr });
17962
+ for (let i = 0; i < behavior.targetBindingCount; i++) {
17963
+ if (sortedAvailable.length === 0) {
17964
+ throw new Error(`Entropy Exhaustion. Cannot satisfy target binding. Sorted available pool is empty. (E: 341b95dc3a58be3e083d1d9c4a0c4925)`);
17969
17965
  }
17966
+ const hashBigInt = BigInt("0x" + currentHash);
17967
+ const index = Number(hashBigInt % BigInt(sortedAvailable.length));
17968
+ const selectedId = sortedAvailable[index];
17969
+ mandatory.add(selectedId);
17970
+ sortedAvailable.splice(index, 1);
17971
+ available = available.filter((id) => id !== selectedId);
17972
+ currentHash = await hash({ s: currentHash });
17970
17973
  }
17971
17974
  }
17972
17975
  if (behavior.selectSequentially > 0) {
@@ -17980,22 +17983,6 @@ function getDeterministicRequirements({ pool, requiredChallengeIds, targetAddr }
17980
17983
  }
17981
17984
  return { mandatoryIds: mandatory, availableIds: available };
17982
17985
  }
17983
- function addToBindingMap(map, challengeId) {
17984
- const firstChar = challengeId.charAt(0).toLowerCase();
17985
- if (/[0-9a-f]/.test(firstChar)) {
17986
- if (!map[firstChar]) {
17987
- map[firstChar] = [];
17988
- }
17989
- map[firstChar].push(challengeId);
17990
- } else {
17991
- throw new Error(`invalid challengeId (${challengeId}). Must start with a hex character. (E: c96ed8460de89e28c801370a0f07f826)`);
17992
- }
17993
- }
17994
- function removeFromBindingMap(map, challengeId) {
17995
- for (const key of Object.keys(map)) {
17996
- map[key] = map[key].filter((id) => id !== challengeId);
17997
- }
17998
- }
17999
17986
  function resolveTargetPool({ pools, poolId, poolFilter, verb }) {
18000
17987
  const lc2 = `[resolveTargetPool]`;
18001
17988
  try {
@@ -18034,10 +18021,10 @@ function resolveTargetPool({ pools, poolId, poolFilter, verb }) {
18034
18021
  throw error;
18035
18022
  }
18036
18023
  }
18037
- function selectChallengeIds({ pool, targetAddr, requiredChallengeIds }) {
18024
+ async function selectChallengeIds({ pool, targetAddr, requiredChallengeIds }) {
18038
18025
  const lc2 = `[selectChallengeIds]`;
18039
18026
  try {
18040
- const { mandatoryIds, availableIds } = getDeterministicRequirements({
18027
+ const { mandatoryIds, availableIds } = await getDeterministicRequirements({
18041
18028
  pool,
18042
18029
  requiredChallengeIds,
18043
18030
  targetAddr
@@ -18073,11 +18060,6 @@ async function applyReplenishmentStrategy({ prevPools, targetPoolId, consumedIds
18073
18060
  const poolSecret = await strategy.derivePoolSecret({ masterSecret });
18074
18061
  const timestamp = Date.now().toString();
18075
18062
  const strategyType = config.behavior.replenish;
18076
- consumedIds.forEach((id) => {
18077
- if (pool.bindingMap) {
18078
- removeFromBindingMap(pool.bindingMap, id);
18079
- }
18080
- });
18081
18063
  if (strategyType === KeystoneReplenishStrategy.topUp) {
18082
18064
  consumedIds.forEach((id) => delete pool.challenges[id]);
18083
18065
  for (let i = 0; i < consumedIds.length; i++) {
@@ -18092,14 +18074,9 @@ async function applyReplenishmentStrategy({ prevPools, targetPoolId, consumedIds
18092
18074
  challengeId: newId
18093
18075
  });
18094
18076
  pool.challenges[newId] = await strategy.generateChallenge({ solution });
18095
- if (!pool.bindingMap) {
18096
- pool.bindingMap = {};
18097
- }
18098
- addToBindingMap(pool.bindingMap, newId);
18099
18077
  }
18100
18078
  } else if (strategyType === KeystoneReplenishStrategy.replaceAll) {
18101
18079
  pool.challenges = {};
18102
- pool.bindingMap = {};
18103
18080
  for (let i = 0; i < config.behavior.size; i++) {
18104
18081
  const newId = await generateOpaqueChallengeId({
18105
18082
  salt: config.salt,
@@ -18112,13 +18089,11 @@ async function applyReplenishmentStrategy({ prevPools, targetPoolId, consumedIds
18112
18089
  challengeId: newId
18113
18090
  });
18114
18091
  pool.challenges[newId] = await strategy.generateChallenge({ solution });
18115
- addToBindingMap(pool.bindingMap, newId);
18116
18092
  }
18117
18093
  } else if (strategyType === KeystoneReplenishStrategy.consume) {
18118
18094
  consumedIds.forEach((id) => delete pool.challenges[id]);
18119
18095
  } else if (strategyType === KeystoneReplenishStrategy.deleteAll) {
18120
18096
  pool.challenges = {};
18121
- pool.bindingMap = {};
18122
18097
  } else {
18123
18098
  throw new Error(`Unknown replenish strategy: ${strategyType}. Valid list: ${pretty(KEYSTONE_REPLENISH_STRATEGY_VALID_VALUES)} (E: 0acf56f1e1486240080e11e8046d0825)`);
18124
18099
  }
@@ -18230,10 +18205,14 @@ async function validateChallengePool({ pool }) {
18230
18205
  errors.push(`${lc2} pool.config.id falsy (E: 31d7943d95f877326d5f4ea14463d626)`);
18231
18206
  }
18232
18207
  if (pool.config.behavior) {
18233
- const { size } = pool.config.behavior;
18208
+ const { size, selectSequentially, selectRandomly, targetBindingCount } = pool.config.behavior;
18234
18209
  if (!size || size === 0) {
18235
18210
  errors.push(`${lc2} invalid pool.config.behavior.size (${size}). Must be positive integer. (E: b221e36ec102bdc944552248ce8fe626)`);
18236
18211
  }
18212
+ const totalRequested = (selectSequentially || 0) + (selectRandomly || 0) + (targetBindingCount || 0);
18213
+ if (totalRequested >= size) {
18214
+ errors.push(`${lc2} Total requested challenges (${totalRequested}) cannot equal or exceed pool size (${size}) to prevent full pool exposure and selection exhaustion. (E: 81cb834f826315264bca81c15fca58f1)`);
18215
+ }
18237
18216
  } else {
18238
18217
  errors.push(`${lc2} pool.config.behavior falsy (E: bede081c066c39732eefe2f92e296326)`);
18239
18218
  }
@@ -18259,6 +18238,27 @@ async function validateChallengePool({ pool }) {
18259
18238
  }
18260
18239
  }
18261
18240
  }
18241
+ function validateKeystoneMetadata({ data }) {
18242
+ const lc2 = `[validateKeystoneMetadata]`;
18243
+ const errors = [];
18244
+ const checkDetails = (details, source) => {
18245
+ if (!details)
18246
+ return;
18247
+ if (details.username !== void 0) {
18248
+ if (typeof details.username !== "string" || !KEYSTONE_USERNAME_REGEXP.test(details.username)) {
18249
+ errors.push(`${lc2} invalid username in ${source} (${details.username}). Must match ${KEYSTONE_USERNAME_REGEXP}`);
18250
+ }
18251
+ }
18252
+ if (details.description !== void 0) {
18253
+ if (typeof details.description !== "string" || !KEYSTONE_DESCRIPTION_REGEXP.test(details.description)) {
18254
+ errors.push(`${lc2} invalid description in ${source} (${details.description}). Must match ${KEYSTONE_DESCRIPTION_REGEXP}`);
18255
+ }
18256
+ }
18257
+ };
18258
+ checkDetails(data.frameDetails, "frameDetails");
18259
+ checkDetails(data.checkpointDetails, "checkpointDetails");
18260
+ return errors;
18261
+ }
18262
18262
  async function validateGenesisKeystone({ keystoneIbGib }) {
18263
18263
  const lc2 = `[${validateGenesisKeystone.name}]`;
18264
18264
  try {
@@ -18267,6 +18267,8 @@ async function validateGenesisKeystone({ keystoneIbGib }) {
18267
18267
  }
18268
18268
  const errors = [];
18269
18269
  const { data, rel8ns } = keystoneIbGib;
18270
+ const metadataErrors = validateKeystoneMetadata({ data });
18271
+ metadataErrors.forEach((x) => errors.push(x));
18270
18272
  if (data.proofs && data.proofs.length > 0) {
18271
18273
  errors.push(`${lc2} proofs already exist on genesis keystone. (E: 7a5e15f20918f1bbd8ffb62857dcd526)`);
18272
18274
  }
@@ -18306,6 +18308,8 @@ async function validateKeystoneTransition({ currentIbGib, prevIbGib }) {
18306
18308
  }
18307
18309
  const currData = currentIbGib.data;
18308
18310
  const prevData = prevIbGib.data;
18311
+ const metadataErrors = validateKeystoneMetadata({ data: currData });
18312
+ metadataErrors.forEach((x) => errors.push(x));
18309
18313
  const currDataN = currData.n ?? -2;
18310
18314
  const prevDataN = prevData.n ?? -2;
18311
18315
  if (currDataN < 0) {
@@ -18359,7 +18363,7 @@ async function verifyProofAgainstPool({ proof, pool, errors }) {
18359
18363
  errors.push(`Policy Violation: Pool ${pool.id} used for unauthorized verb ${proof.claim.verb}`);
18360
18364
  }
18361
18365
  }
18362
- const { mandatoryIds, availableIds } = getDeterministicRequirements({
18366
+ const { mandatoryIds, availableIds } = await getDeterministicRequirements({
18363
18367
  pool,
18364
18368
  requiredChallengeIds: proof.requiredChallengeIds,
18365
18369
  targetAddr: proof.claim.target
@@ -18641,7 +18645,6 @@ var KeystoneService_V1 = class _KeystoneService_V1 {
18641
18645
  const strategy = KeystoneStrategyFactory.create({ config });
18642
18646
  const poolSecret = await strategy.derivePoolSecret({ masterSecret });
18643
18647
  const challenges = {};
18644
- const bindingMap = {};
18645
18648
  const targetSize = config.behavior.size;
18646
18649
  const timestamp = Date.now().toString();
18647
18650
  for (let i = 0; i < targetSize; i++) {
@@ -18657,13 +18660,11 @@ var KeystoneService_V1 = class _KeystoneService_V1 {
18657
18660
  });
18658
18661
  const challenge = await strategy.generateChallenge({ solution });
18659
18662
  challenges[challengeId] = challenge;
18660
- addToBindingMap(bindingMap, challengeId);
18661
18663
  }
18662
18664
  challengePools.push({
18663
18665
  id: config.id,
18664
18666
  config,
18665
- challenges,
18666
- bindingMap
18667
+ challenges
18667
18668
  });
18668
18669
  }
18669
18670
  if (challengePools.length === 0) {
@@ -18712,7 +18713,7 @@ var KeystoneService_V1 = class _KeystoneService_V1 {
18712
18713
  if (logalot41) {
18713
18714
  console.log(`${lc2} Selected pool: ${pool.id} (size: ${Object.keys(pool.challenges).length}) (I: 6b26d6f4aad18380f2b3a0989b592826)`);
18714
18715
  }
18715
- const idsToSolve = selectChallengeIds({
18716
+ const idsToSolve = await selectChallengeIds({
18716
18717
  pool,
18717
18718
  targetAddr: claim.target,
18718
18719
  requiredChallengeIds
@@ -18870,7 +18871,7 @@ var KeystoneService_V1 = class _KeystoneService_V1 {
18870
18871
  verb: KEYSTONE_VERB_REVOKE,
18871
18872
  target: getIbGibAddr({ ibGib: latestKeystone })
18872
18873
  };
18873
- const idsToSolve = selectChallengeIds({
18874
+ const idsToSolve = await selectChallengeIds({
18874
18875
  pool,
18875
18876
  targetAddr: claim.target,
18876
18877
  requiredChallengeIds: []
@@ -18966,7 +18967,7 @@ var KeystoneService_V1 = class _KeystoneService_V1 {
18966
18967
  // Scope creates a cryptographic commitment to WHICH pools are being added
18967
18968
  scope: JSON.stringify({ add: newPools.map((p) => p.id) })
18968
18969
  };
18969
- const idsToSolve = selectChallengeIds({
18970
+ const idsToSolve = await selectChallengeIds({
18970
18971
  pool: adminPool,
18971
18972
  targetAddr: target
18972
18973
  });
@@ -19065,7 +19066,7 @@ var KeystoneService_V1 = class _KeystoneService_V1 {
19065
19066
  }
19066
19067
  };
19067
19068
 
19068
- // ../../libs/core-gib/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs
19069
+ // ../../libs/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-websocket-peer-helpers.mjs
19069
19070
  var logalot42 = GLOBAL_LOG_A_LOT2;
19070
19071
  var SESSION_KEYSTONE_POLICY = {
19071
19072
  COMMON: {
@@ -19080,7 +19081,7 @@ var SESSION_KEYSTONE_POLICY = {
19080
19081
  SIZE: 10,
19081
19082
  SELECT_SEQUENTIALLY: 2,
19082
19083
  SELECT_RANDOMLY: 2,
19083
- TARGET_BINDING_CHARS: 0,
19084
+ TARGET_BINDING_COUNT: 0,
19084
19085
  SERVER_DEMAND_COUNT: 3
19085
19086
  }
19086
19087
  };
@@ -19245,8 +19246,10 @@ async function validateAndRegisterEvolveKeystone({ domainAddr, keystoneIbGib, re
19245
19246
  if (intrinsicErrors && intrinsicErrors.length > 0) {
19246
19247
  throw new Error(`Intrinsic keystone validation failed: ${intrinsicErrors.join(", ")} (E: 38ea984585edc6ee88d2a698c7895826)`);
19247
19248
  }
19248
- const { tjpGib } = getGibInfo({ ibGibAddr: addr });
19249
- const expectedTjpGib = getGibInfo({ ibGibAddr: domainAddr }).punctiliarHash;
19249
+ const infoAddr = getGibInfo({ ibGibAddr: addr });
19250
+ const tjpGib = infoAddr.tjpGib ?? infoAddr.punctiliarHash;
19251
+ const infoDomain = getGibInfo({ ibGibAddr: domainAddr });
19252
+ const expectedTjpGib = infoDomain.tjpGib ?? infoDomain.punctiliarHash;
19250
19253
  if (tjpGib !== expectedTjpGib) {
19251
19254
  throw new Error(`Keystone tjpGib (${tjpGib}) does not match URL domainAddr tjpGib (${expectedTjpGib})`);
19252
19255
  }
@@ -19579,9 +19582,6 @@ var KeystoneGenesisHandler = class _KeystoneGenesisHandler extends ServeGibHandl
19579
19582
  await metaspace.put({ ibGibs: [keystoneIbGib], space });
19580
19583
  await metaspace.registerNewIbGib({ ibGib: keystoneIbGib, space });
19581
19584
  console.log(`${lc2} domain created and keystone persisted: ${addr}`);
19582
- if (logalot45) {
19583
- console.log(`${lc2} keystoneIbGib: ${pretty(keystoneIbGib)} (I: d598c6ff7a48997d585b84c19c464826)`);
19584
- }
19585
19585
  return this.ok({ success: true, addr }, 201);
19586
19586
  } catch (error) {
19587
19587
  const emsg = extractErrorMsg(error);
@@ -19820,64 +19820,82 @@ function performConnect(req, socket) {
19820
19820
  }
19821
19821
  var WebSocketFrameDecoder = class {
19822
19822
  buffer = Buffer.alloc(0);
19823
+ fragments = [];
19823
19824
  /** Adds new data chunk from TCP socket. */
19824
19825
  addChunk(chunk) {
19825
19826
  this.buffer = Buffer.concat([this.buffer, chunk]);
19826
19827
  }
19827
19828
  /**
19828
- * Parses the next complete text frame from the accumulated buffer.
19829
+ * Parses the next complete text message, assembling fragments if necessary.
19829
19830
  * Returns:
19830
- * - `string` if a complete text frame was decoded successfully (and consumes those bytes).
19831
+ * - `string` if a complete text message was assembled/decoded (and consumes those bytes).
19831
19832
  * - `null` if the buffer is incomplete or we need more data.
19832
19833
  * - `throws Error` on protocol errors or close frames.
19833
19834
  */
19834
19835
  nextFrame() {
19835
- if (this.buffer.length < 2) {
19836
- return null;
19837
- }
19838
- const opcode = this.buffer[0] & 15;
19839
- if (opcode === 8) {
19840
- throw new Error("Close frame received");
19841
- }
19842
- if (opcode !== 1) {
19843
- throw new Error(`Unsupported WebSocket opcode: 0x${opcode.toString(16)}`);
19844
- }
19845
- const secondByte = this.buffer[1];
19846
- const masked = (secondByte & 128) !== 0;
19847
- let payloadLen = secondByte & 127;
19848
- let headerLen = 2;
19849
- if (payloadLen === 126) {
19850
- if (this.buffer.length < 4) {
19836
+ while (true) {
19837
+ if (this.buffer.length < 2) {
19851
19838
  return null;
19852
19839
  }
19853
- payloadLen = this.buffer.readUInt16BE(2);
19854
- headerLen = 4;
19855
- } else if (payloadLen === 127) {
19856
- if (this.buffer.length < 10) {
19840
+ const firstByte = this.buffer[0];
19841
+ const fin = (firstByte & 128) !== 0;
19842
+ const opcode = firstByte & 15;
19843
+ if (opcode === 8) {
19844
+ throw new Error("Close frame received");
19845
+ }
19846
+ const isContinuation = opcode === 0;
19847
+ const isText = opcode === 1;
19848
+ if (!isContinuation && !isText) {
19849
+ throw new Error(`Unsupported WebSocket opcode: 0x${opcode.toString(16)}`);
19850
+ }
19851
+ if (isContinuation && this.fragments.length === 0) {
19852
+ throw new Error("Continuation frame received without an active message.");
19853
+ }
19854
+ if (isText && this.fragments.length > 0) {
19855
+ throw new Error("New message frame received before previous one completed.");
19856
+ }
19857
+ const secondByte = this.buffer[1];
19858
+ const masked = (secondByte & 128) !== 0;
19859
+ let payloadLen = secondByte & 127;
19860
+ let headerLen = 2;
19861
+ if (payloadLen === 126) {
19862
+ if (this.buffer.length < 4) {
19863
+ return null;
19864
+ }
19865
+ payloadLen = this.buffer.readUInt16BE(2);
19866
+ headerLen = 4;
19867
+ } else if (payloadLen === 127) {
19868
+ if (this.buffer.length < 10) {
19869
+ return null;
19870
+ }
19871
+ payloadLen = Number(this.buffer.readBigUInt64BE(2));
19872
+ headerLen = 10;
19873
+ }
19874
+ const maskLen = masked ? 4 : 0;
19875
+ const totalFrameLen = headerLen + maskLen + payloadLen;
19876
+ if (this.buffer.length < totalFrameLen) {
19857
19877
  return null;
19858
19878
  }
19859
- payloadLen = Number(this.buffer.readBigUInt64BE(2));
19860
- headerLen = 10;
19861
- }
19862
- const maskLen = masked ? 4 : 0;
19863
- const totalFrameLen = headerLen + maskLen + payloadLen;
19864
- if (this.buffer.length < totalFrameLen) {
19865
- return null;
19866
- }
19867
- const frameData = this.buffer.subarray(0, totalFrameLen);
19868
- this.buffer = this.buffer.subarray(totalFrameLen);
19869
- let payloadStart = headerLen;
19870
- if (masked) {
19871
- const mask = frameData.subarray(payloadStart, payloadStart + 4);
19872
- payloadStart += 4;
19873
- const payload = Buffer.from(frameData.subarray(payloadStart));
19874
- for (let i = 0; i < payload.length; i++) {
19875
- payload[i] ^= mask[i % 4];
19876
- }
19877
- return payload.toString("utf-8");
19878
- } else {
19879
- const payload = frameData.subarray(payloadStart);
19880
- return payload.toString("utf-8");
19879
+ const frameData = this.buffer.subarray(0, totalFrameLen);
19880
+ this.buffer = this.buffer.subarray(totalFrameLen);
19881
+ let payloadStart = headerLen;
19882
+ let payload;
19883
+ if (masked) {
19884
+ const mask = frameData.subarray(payloadStart, payloadStart + 4);
19885
+ payloadStart += 4;
19886
+ payload = Buffer.from(frameData.subarray(payloadStart));
19887
+ for (let i = 0; i < payload.length; i++) {
19888
+ payload[i] ^= mask[i % 4];
19889
+ }
19890
+ } else {
19891
+ payload = Buffer.from(frameData.subarray(payloadStart));
19892
+ }
19893
+ this.fragments.push(payload);
19894
+ if (fin) {
19895
+ const completePayload = Buffer.concat(this.fragments);
19896
+ this.fragments = [];
19897
+ return completePayload.toString("utf-8");
19898
+ }
19881
19899
  }
19882
19900
  }
19883
19901
  };
@@ -20063,12 +20081,10 @@ async function applyTransforms({ src, createdIbGibs_Running, dnaAddrsToApplyToSt
20063
20081
  const dnaAddrToApply = dnaAddrsToApplyToStoreVersion_MUTATES_IN_PLACE.splice(0, 1)[0];
20064
20082
  const dnaIbGib_IntermediateArray = allLocalIbGibs.filter((x) => getIbGibAddr({ ibGib: x }) === dnaAddrToApply);
20065
20083
  let dnaIbGib;
20066
- if (dnaIbGib_IntermediateArray.length === 1) {
20084
+ if (dnaIbGib_IntermediateArray.length > 0) {
20067
20085
  dnaIbGib = dnaIbGib_IntermediateArray[0];
20068
- } else if (dnaIbGib_IntermediateArray.length === 0) {
20069
- throw new Error(`dna ibGib not found in supplied allLocalIbGibs. dnaAddr: ${dnaAddrToApply}. (E: 7f56826852cf48a79ab8af16bf27e284)`);
20070
20086
  } else {
20071
- throw new Error(`More than one ibGib in allLocalIbGibs with the dna address of ${dnaAddrToApply}? (E: a726134f4cc14a4fb2ed2d39d22af17c)(UNEXPECTED)`);
20087
+ throw new Error(`dna ibGib not found in supplied allLocalIbGibs. dnaAddr: ${dnaAddrToApply}. (E: 7f56826852cf48a79ab8af16bf27e284)`);
20072
20088
  }
20073
20089
  let argTransform = clone(dnaIbGib.data);
20074
20090
  argTransform.src = src;
@@ -20998,6 +21014,23 @@ async function validateContextAndSagaFrame({ context }) {
20998
21014
  } else {
20999
21015
  errors.push(`context.sagaFrame is falsy. (E: b4edd88f4963f493789f83b29ba2df26)`);
21000
21016
  }
21017
+ if (context.sagaFrameMsg) {
21018
+ const sagaFrameMsgErrors = await validateIbGibIntrinsically({ ibGib: context.sagaFrameMsg }) ?? [];
21019
+ sagaFrameMsgErrors.forEach((x) => errors.push(x));
21020
+ if (context.sagaFrame) {
21021
+ const expectedMsgAddr = context.sagaFrame.rel8ns?.[SYNC_MSG_REL8N_NAME]?.[0];
21022
+ if (expectedMsgAddr) {
21023
+ const actualMsgAddr = getIbGibAddr({ ibGib: context.sagaFrameMsg });
21024
+ if (actualMsgAddr !== expectedMsgAddr) {
21025
+ errors.push(`context.sagaFrameMsg address (${actualMsgAddr}) does not match the stone address referenced in sagaFrame relations (${expectedMsgAddr}). (E: a983b271fcae46bbad7e82098bc24826)`);
21026
+ }
21027
+ } else {
21028
+ errors.push(`context.sagaFrame is missing the message stone relation '${SYNC_MSG_REL8N_NAME}'. (E: da872cf3a8d46dbbad89d0a68d712826)`);
21029
+ }
21030
+ }
21031
+ } else {
21032
+ errors.push(`context.sagaFrameMsg is falsy. (E: ed405a72ab0d8bbdca7b9605d8f9a26)`);
21033
+ }
21001
21034
  if (errors.length > 0) {
21002
21035
  return errors;
21003
21036
  }
@@ -21012,34 +21045,190 @@ async function validateContextAndSagaFrame({ context }) {
21012
21045
  }
21013
21046
  }
21014
21047
  }
21015
- async function authenticateContext({}) {
21016
- const lc2 = `[${authenticateContext.name}]`;
21048
+ async function authenticateContextIntrinsically({
21049
+ context,
21050
+ space
21051
+ // stageInProtocol,
21052
+ }) {
21053
+ const lc2 = `[${authenticateContextIntrinsically.name}]`;
21017
21054
  try {
21018
21055
  if (logalot53) {
21019
21056
  console.log(`${lc2} starting... (I: 3c34e8f1d6ef965f98725c88459ea926)`);
21020
21057
  }
21021
- console.warn(`${lc2}[NAG] not thrown. not implemented right now after removing all identity-related code. (W: e5fad31cfb49eef198a189a82dbcf726)`);
21022
- return [];
21023
- } catch (error) {
21024
- console.error(`${lc2} ${extractErrorMsg(error)}`);
21025
- throw error;
21026
- } finally {
21027
- if (logalot53) {
21028
- console.log(`${lc2} complete.`);
21058
+ const errors = [];
21059
+ if (!context.data) {
21060
+ throw new Error(`(UNEXPECTED) context.data falsy? (E: 3e4ddd0eb4b828ad489658d88d9a6326)`);
21029
21061
  }
21030
- }
21031
- }
21032
- async function authorizeContext({ context, fullSagaHistory }) {
21033
- const lc2 = `[${authorizeContext.name}]`;
21034
- try {
21035
- if (logalot53) {
21036
- console.log(`${lc2} starting... (I: 48c918b41ceec0cd489ca3b8819e6826)`);
21062
+ if (!context.rel8ns) {
21063
+ throw new Error(`(UNEXPECTED) context.rel8ns falsy? (E: 8026589d4fed69c828334ee842074326)`);
21037
21064
  }
21038
- console.error(`${lc2} NAG ERROR (NOT THROWN): not implemented. authorize business logic (v1 must have this, but later when we are working on admin vs. student)(E: bc3a78f2dab18ab64c36d055a4b50526)`);
21039
- return [];
21065
+ const { sagaFrame, signedSessionIdentity: currSessionIdentity } = context;
21066
+ if (!sagaFrame.data) {
21067
+ throw new Error(`(UNEXPECTED) sagaFrame.data falsy? (E: b61cc82d25984c92f75db74a5a855b26)`);
21068
+ }
21069
+ if (!currSessionIdentity) {
21070
+ console.error(`${lc2}[NAG][not thrown] sagaFrame.data.sessionIdentityTjpAddr logic needs to be added in coordinator (E: 4fc47800a1086c917a47381824280826)`);
21071
+ if (sagaFrame.data.sessionIdentityTjpAddr) {
21072
+ errors.push("Context has no session identity, but sync saga frame shows a session identity (sagaFrame.data.sessionIdentityTjpAddr is truthy). (E: 69dd6cdc2e1859c0f3d62958c4339826)");
21073
+ return errors;
21074
+ } else if (context.rel8ns.sessionIdentity) {
21075
+ errors.push("Context has no signed session identity, but context.rel8ns.sessionIdentity is truthy. (E: 96a04a8a6c88ea8bf88118f89ad8e326)");
21076
+ return errors;
21077
+ } else {
21078
+ if (logalot53) {
21079
+ console.log(`${lc2} context has no signedSessionIdentity and sync saga frame doesn't state there should be session identity. So nothing further to authenticate - returning early with no authentication errors. (I: d708735f9a2899ee98f762b8a09ed826)`);
21080
+ }
21081
+ return [];
21082
+ }
21083
+ }
21084
+ const currSessionIdentityAddr = getIbGibAddr({ ibGib: currSessionIdentity });
21085
+ const prevSessionIdentityAddrs_accordingToContextRel8ns = context.rel8ns?.sessionIdentity ?? [];
21086
+ if (prevSessionIdentityAddrs_accordingToContextRel8ns.length === 0) {
21087
+ errors.push(`context.rel8ns.sessionIdentity is falsy/empty but context.signedSessionIdentity is present. (E: 66f906421eb2468c0b33f908a3cf2826)`);
21088
+ return errors;
21089
+ }
21090
+ if (prevSessionIdentityAddrs_accordingToContextRel8ns.length > 1) {
21091
+ errors.push(`context.rel8ns.sessionIdentity has multiple identity addrs. (E: 489428bfe6fdaa4cd885b938dc4c5826)`);
21092
+ return errors;
21093
+ }
21094
+ const prevSessionIdentityAddr = prevSessionIdentityAddrs_accordingToContextRel8ns[0];
21095
+ const resGetLatestAddr = await getLatestAddrs({ addrs: [prevSessionIdentityAddr], space });
21096
+ if (!resGetLatestAddr) {
21097
+ throw new Error(`(UNEXPECTED) resGetLatestAddr for prevSessionIdentityAddr in space (${space.ib}) falsy? (E: 7b207e5cbcec9037ea5adbe822ead826)`);
21098
+ }
21099
+ if (!resGetLatestAddr.data) {
21100
+ throw new Error(`(UNEXPECTED) resGetLatestAddr.data for prevSessionIdentityAddr in space (${space.ib}) falsy? (E: de4eb8d730c8c4dcb59c8b9c79277826)`);
21101
+ }
21102
+ if (!resGetLatestAddr.data.success) {
21103
+ throw new Error(`(UNEXPECTED) resGetLatestAddr.data.success falsy? (E: c94298dfd9684ad6a87eb748459aa826)`);
21104
+ }
21105
+ const { latestAddrsMap } = resGetLatestAddr.data;
21106
+ if (!latestAddrsMap) {
21107
+ throw new Error(`(UNEXPECTED) resGetLatestAddr.data.latestAddrsMap falsy? (E: 19f1fd5fe798cf2e5fa923919169d826)`);
21108
+ }
21109
+ if (Object.keys(latestAddrsMap).length !== 1) {
21110
+ throw new Error(`(UNEXPECTED) Object.keys(latestAddrsMap).length !== 1? (E: fe526a0747589c6427a8bcc86da34a26)`);
21111
+ }
21112
+ const prevSessionIdentityAddr_latest = latestAddrsMap[prevSessionIdentityAddr];
21113
+ if (!prevSessionIdentityAddr_latest) {
21114
+ errors.push(`prevSessionIdentityAddr (${prevSessionIdentityAddr}) not found in space (${space.ib}). this should have been the incoming prevSessionIdentityAddr (E: f6d042bd6b54819998653228dee34226)`);
21115
+ return errors;
21116
+ }
21117
+ if (prevSessionIdentityAddr !== prevSessionIdentityAddr_latest) {
21118
+ if (prevSessionIdentityAddr_latest === currSessionIdentityAddr) {
21119
+ } else {
21120
+ errors.push(`context.rel8ns.sessionIdentity does not point to the most recent in the space (${space.ib}). (E: 2f8288f53c87b6aa47bd2178d9df0c26)`);
21121
+ console.log(`context: ${pretty(toDto2({ ibGib: context }))}`);
21122
+ console.log(`prevSessionIdentityAddr (context.rel8ns.sessionIdentity): ${prevSessionIdentityAddr}`);
21123
+ console.log(`prevSessionIdentityAddr_latest: ${prevSessionIdentityAddr_latest}`);
21124
+ console.log(`currSessionIdentity (context.signedSessionIdentity): ${pretty(toDto2({
21125
+ ibGib: {
21126
+ ib: currSessionIdentity.ib,
21127
+ gib: currSessionIdentity.gib,
21128
+ rel8ns: currSessionIdentity.rel8ns,
21129
+ data: {
21130
+ ...currSessionIdentity.data,
21131
+ challengePools: currSessionIdentity.data.challengePools.map((p) => {
21132
+ return { ...p, challenges: {} };
21133
+ })
21134
+ }
21135
+ }
21136
+ }))}`);
21137
+ console.log(`currSessionIdentityAddr: ${currSessionIdentityAddr}`);
21138
+ return errors;
21139
+ }
21140
+ }
21141
+ const resGetPrevSessionIdentity = await getFromSpace({ addr: prevSessionIdentityAddr, space });
21142
+ if (!resGetPrevSessionIdentity.success || resGetPrevSessionIdentity.ibGibs?.length !== 1) {
21143
+ errors.push(`could not fetch latest sender identity ${prevSessionIdentityAddr} from space (${space.ib}). (E: fd48c3e64c9fa4efd8a1f8280af18226)`);
21144
+ return errors;
21145
+ }
21146
+ const prevSessionIdentity = resGetPrevSessionIdentity.ibGibs[0];
21147
+ const sessionIdentityTjp = await getTjpIbGib({ ibGib: prevSessionIdentity, naive: true, space });
21148
+ if (!sessionIdentityTjp) {
21149
+ throw new Error(`(UNEXPECTED) couldn't get sessionIdentityTjp in space (${space.ib})? we have already gotten the identity itself in the space, so we would expect the entire timeline to exist in it. (E: 9be0382ff1c8a0e77645ea38c096f826)`);
21150
+ }
21151
+ const sessionIdentityTjpAddr = getIbGibAddr({ ibGib: sessionIdentityTjp });
21152
+ if (sessionIdentityTjpAddr !== sagaFrame.data.sessionIdentityTjpAddr) {
21153
+ throw new Error(`(UNEXPECTED) sessionIdentityTjpAddr !== sagaFrame.data.sessionIdentityTjpAddr? (E: c9a4ad5c2728fe38e86afc58e4abaf26)`);
21154
+ }
21155
+ const sessionGenesisFrameDetails = sessionIdentityTjp.data.frameDetails;
21156
+ if (!sessionGenesisFrameDetails) {
21157
+ errors.push(`Invalid session identity tjp: sessionIdentityTjp.data.frameDetails is falsy. (E: 0187f8f804a84256281720586620b826)`);
21158
+ return errors;
21159
+ }
21160
+ const { senderIdentityAddr, senderIdentityTjpAddr } = sessionGenesisFrameDetails;
21161
+ if (!senderIdentityAddr) {
21162
+ throw new Error(`sessionGenesisFrameDetails.senderIdentityAddr falsy (E: 02a0c80a3ead9e3af8af4cf3b156e826)`);
21163
+ }
21164
+ if (!senderIdentityTjpAddr) {
21165
+ throw new Error(`sessionGenesisFrameDetails.senderIdentityTjpAddr falsy (E: 271928090ff5dc56d4bb63d8d5c68826)`);
21166
+ }
21167
+ const resGetLatestAddr_senderIdentity = await getLatestAddrs({ addrs: [senderIdentityTjpAddr, senderIdentityAddr], space });
21168
+ if (!resGetLatestAddr_senderIdentity) {
21169
+ throw new Error(`(UNEXPECTED) resGetLatestAddr_senderIdentity for prevSessionIdentityAddr in space (${space.ib}) falsy? (E: 2e4ae8083b6fb7cbb8fae2a519062926)`);
21170
+ }
21171
+ if (!resGetLatestAddr_senderIdentity.data) {
21172
+ throw new Error(`(UNEXPECTED) resGetLatestAddr_senderIdentity.data for prevSessionIdentityAddr in space (${space.ib}) falsy? (E: 2e231850c2a898cc282b4b2841056826)`);
21173
+ }
21174
+ if (!resGetLatestAddr_senderIdentity.data.success) {
21175
+ throw new Error(`(UNEXPECTED) resGetLatestAddr_senderIdentity.data.success falsy? (E: e93508f03e0475925875b00746ffd826)`);
21176
+ }
21177
+ const { latestAddrsMap: latestAddrsMap_senderIdentity } = resGetLatestAddr_senderIdentity.data;
21178
+ if (!latestAddrsMap_senderIdentity) {
21179
+ throw new Error(`(UNEXPECTED) resGetLatestAddr_senderIdentity.data.latestAddrsMap falsy? (E: 87a91e3f9968ad9ba79cdfe8cd878326)`);
21180
+ }
21181
+ if (Object.keys(latestAddrsMap_senderIdentity).length !== 2 && senderIdentityTjpAddr !== senderIdentityAddr) {
21182
+ throw new Error(`(UNEXPECTED) Object.keys(latestAddrsMap_senderIdentity).length !== 2 && senderIdentityTjpAddr !== senderIdentityAddr? (E: fe46bd584853d8e1e8e2d11f52012826)`);
21183
+ }
21184
+ const senderIdentityTjpAddr_latest = latestAddrsMap_senderIdentity[senderIdentityTjpAddr];
21185
+ const senderIdentityAddr_latest = latestAddrsMap_senderIdentity[senderIdentityAddr];
21186
+ if (!senderIdentityAddr_latest) {
21187
+ throw new Error(`(UNEXPECTED) senderIdentityAddr_latest falsy? (E: e151798ae2e9241578d09948937c4b26)`);
21188
+ }
21189
+ if (senderIdentityTjpAddr_latest !== senderIdentityAddr_latest) {
21190
+ throw new Error(`senderIdentityTjpAddr_latest !== senderIdentityAddr_latest (E: 52478a1053589e72665031a853cc1826)`);
21191
+ }
21192
+ const resGetSenderIdentity_latest = await getFromSpace({
21193
+ addr: senderIdentityAddr_latest,
21194
+ space
21195
+ });
21196
+ if (!resGetSenderIdentity_latest.success || resGetSenderIdentity_latest.ibGibs?.length !== 1) {
21197
+ errors.push(`could not fetch latest sender identity ${prevSessionIdentityAddr} from space (${space.ib}). (E: 3565ff0ed458f5a2384c40b16e849826)`);
21198
+ return errors;
21199
+ }
21200
+ const senderIdentity_latest = resGetSenderIdentity_latest.ibGibs[0];
21201
+ if (!senderIdentity_latest.data.proofs) {
21202
+ errors.push(`Invalid sender identity. Proofs empty/falsy. (E: ebf488853061614d2b5b137828119526)`);
21203
+ return errors;
21204
+ }
21205
+ const syncClaim = senderIdentity_latest.data.proofs.find((p) => p.claim.verb === KEYSTONE_VERB_SYNC)?.claim;
21206
+ if (!syncClaim) {
21207
+ errors.push(`Most recent senderIdentity has no proof whose claim.verb === ${KEYSTONE_VERB_SYNC}. (E: b0f488ecccbbfe43d9a0b7c8a29d7826)`);
21208
+ return errors;
21209
+ }
21210
+ if (syncClaim.target !== sessionIdentityTjpAddr) {
21211
+ errors.push(`Most recent sender identity claim has claim.verb === ${KEYSTONE_VERB_SYNC} but DOES NOT target expected session identity addr ${prevSessionIdentityAddr}. (E: 3e7f18d99848969be8586423d5ccb826)`);
21212
+ return errors;
21213
+ }
21214
+ const keystoneSvc = new KeystoneService_V1();
21215
+ const transitionErrors = await keystoneSvc.validate({
21216
+ currentIbGib: currSessionIdentity,
21217
+ prevIbGib: prevSessionIdentity
21218
+ });
21219
+ if (transitionErrors.length > 0) {
21220
+ errors.push(`Invalid session identity transition: ${transitionErrors.join(", ")} (E: da1c81c6d3c86aec3254f48fe7514226)`);
21221
+ }
21222
+ const contextAddr = getIbGibAddr({ ibGib: context });
21223
+ const targetsThisContext = currSessionIdentity.data?.proofs?.some((p) => p.claim.target === contextAddr);
21224
+ if (!targetsThisContext) {
21225
+ errors.push(`Session identity signature does not target current context ibgib (${contextAddr}). (E: acae68938c287178c878d1b88bebb826)`);
21226
+ }
21227
+ return errors;
21040
21228
  } catch (error) {
21041
- console.error(`${lc2} ${extractErrorMsg(error)}`);
21042
- throw error;
21229
+ const emsg = `${lc2} ${extractErrorMsg(error)}`;
21230
+ console.error(emsg);
21231
+ return [`authentication produced an error: ${emsg} (E: 45e014b82af81993d936611ca6fc4d26)`];
21043
21232
  } finally {
21044
21233
  if (logalot53) {
21045
21234
  console.log(`${lc2} complete.`);
@@ -21053,6 +21242,90 @@ var SyncPeer_V1 = class _SyncPeer_V1 extends LightWitnessBase_V1 {
21053
21242
  lc = `[${_SyncPeer_V1.name}]`;
21054
21243
  opts;
21055
21244
  payloadIbGibsDomainReceived$;
21245
+ currentSessionIdentity;
21246
+ get currentSessionIdentityAddr() {
21247
+ return this.currentSessionIdentity ? getIbGibAddr({ ibGib: this.currentSessionIdentity }) : void 0;
21248
+ }
21249
+ // public getSenderIdentity(): KeystoneIbGib_V1 | undefined {
21250
+ // return this.opts?.senderIdentity;
21251
+ // }
21252
+ async signContext({ contextAddr }) {
21253
+ const lc2 = `${this.lc}[${this.signContext.name}]`;
21254
+ try {
21255
+ if (!this.currentSessionIdentity) {
21256
+ return void 0;
21257
+ }
21258
+ if (!this.opts) {
21259
+ throw new Error(`opts not initialized. (E: bcf5978aed789b0ebcbdc51971ebe826)`);
21260
+ }
21261
+ const { fnSenderSecret, sagaId, localMetaspace, localSpace } = this.opts;
21262
+ if (!fnSenderSecret) {
21263
+ throw new Error(`fnSenderSecret not initialized. (E: 207fd292a2e8c53c05fd0a74a4ae6d26)`);
21264
+ }
21265
+ if (!sagaId) {
21266
+ throw new Error(`sagaId not initialized. (E: f2e35cc13ed873b638116188119d1826)`);
21267
+ }
21268
+ const senderSecret = await fnSenderSecret();
21269
+ const sessionSecret = await deriveSessionSecret({ senderSecret, sagaId });
21270
+ const keystoneSvc = new KeystoneService_V1();
21271
+ const evolved = await keystoneSvc.sign({
21272
+ latestKeystone: this.currentSessionIdentity,
21273
+ masterSecret: sessionSecret,
21274
+ claim: {
21275
+ verb: KEYSTONE_VERB_SYNC,
21276
+ target: contextAddr
21277
+ },
21278
+ metaspace: localMetaspace,
21279
+ space: localSpace
21280
+ });
21281
+ this.currentSessionIdentity = evolved;
21282
+ return evolved;
21283
+ } catch (error) {
21284
+ console.error(`${lc2} ${extractErrorMsg(error)}`);
21285
+ throw error;
21286
+ }
21287
+ }
21288
+ /**
21289
+ * Evolves the session identity (S_n -> S_n+1) solving the demanded connect challenges.
21290
+ */
21291
+ async signContextConnect({ challengeUuid, demandedIds }) {
21292
+ const lc2 = `${this.lc}[${this.signContextConnect.name}]`;
21293
+ try {
21294
+ if (!this.currentSessionIdentity) {
21295
+ return void 0;
21296
+ }
21297
+ if (!this.opts) {
21298
+ throw new Error(`opts not initialized. (E: bcf5978aed789b0ebcbdc51971ebe826)`);
21299
+ }
21300
+ const { fnSenderSecret, sagaId, localMetaspace, localSpace } = this.opts;
21301
+ if (!fnSenderSecret) {
21302
+ throw new Error(`fnSenderSecret not initialized. (E: 207fd292a2e8c53c05fd0a74a4ae6d26)`);
21303
+ }
21304
+ if (!sagaId) {
21305
+ throw new Error(`sagaId not initialized. (E: f2e35cc13ed873b638116188119d1826)`);
21306
+ }
21307
+ const senderSecret = await fnSenderSecret();
21308
+ const sessionSecret = await deriveSessionSecret({ senderSecret, sagaId });
21309
+ const keystoneSvc = new KeystoneService_V1();
21310
+ const evolved = await keystoneSvc.sign({
21311
+ latestKeystone: this.currentSessionIdentity,
21312
+ masterSecret: sessionSecret,
21313
+ poolId: POOL_ID_CONNECT,
21314
+ requiredChallengeIds: demandedIds,
21315
+ claim: {
21316
+ verb: KEYSTONE_VERB_CONNECT,
21317
+ target: challengeUuid
21318
+ },
21319
+ metaspace: localMetaspace,
21320
+ space: localSpace
21321
+ });
21322
+ this.currentSessionIdentity = evolved;
21323
+ return evolved;
21324
+ } catch (error) {
21325
+ console.error(`${lc2} ${extractErrorMsg(error)}`);
21326
+ throw error;
21327
+ }
21328
+ }
21056
21329
  get classname() {
21057
21330
  if (!this.data) {
21058
21331
  throw new Error(`(UNEXPECTED) this.data falsy? (E: 1ab1841e9338b54f3aa615fa37024826)`);
@@ -21124,6 +21397,11 @@ var SyncPeer_V1 = class _SyncPeer_V1 extends LightWitnessBase_V1 {
21124
21397
  }
21125
21398
  return void 0;
21126
21399
  }
21400
+ const senderIdentityAddr = getIbGibAddr({ ibGib: senderIdentity });
21401
+ const senderIdentityTjpAddr = getTjpAddr({ ibGib: senderIdentity });
21402
+ if (!senderIdentityTjpAddr) {
21403
+ throw new Error(`(UNEXPECTED) senderIdentityTjpAddr falsy? (E: d5d8c3ab25a83a2c127904fe96de1526)`);
21404
+ }
21127
21405
  if (!sagaId) {
21128
21406
  throw new Error(`(UNEXPECTED) sagaId falsy? Must be set in initializeOpts before calling establishSessionIdentity. (E: c6ba389d51b8af07d82458f875cf9826)`);
21129
21407
  }
@@ -21139,10 +21417,17 @@ var SyncPeer_V1 = class _SyncPeer_V1 extends LightWitnessBase_V1 {
21139
21417
  if (!this.opts.sessionSyncPoolConfig) {
21140
21418
  throw new Error(`(UNEXPECTED) opts.sessionSyncPoolConfig falsy? (E: dbffa810d9e7ff6079088deb5b8e7826)`);
21141
21419
  }
21420
+ const frameDetails = {
21421
+ senderIdentityAddr,
21422
+ senderIdentityTjpAddr
21423
+ };
21424
+ if (this.opts.targetAddrs) {
21425
+ frameDetails.targetAddrs = this.opts.targetAddrs;
21426
+ }
21142
21427
  const sessionIdentity = await keystoneSvc.genesis({
21143
21428
  masterSecret: sessionSecret,
21144
21429
  configs: [this.opts.sessionConnectPoolConfig, this.opts.sessionSyncPoolConfig],
21145
- frameDetails: this.opts.targetAddrs ? { targetAddrs: this.opts.targetAddrs } : void 0,
21430
+ frameDetails,
21146
21431
  metaspace: localMetaspace,
21147
21432
  space: localSpace
21148
21433
  });
@@ -21158,7 +21443,7 @@ var SyncPeer_V1 = class _SyncPeer_V1 extends LightWitnessBase_V1 {
21158
21443
  space: localSpace
21159
21444
  });
21160
21445
  await this.postEstablishToReceiver({ newSenderIdentity, sessionIdentity });
21161
- return sessionIdentity;
21446
+ this.currentSessionIdentity = sessionIdentity;
21162
21447
  } catch (error) {
21163
21448
  console.error(`${lc2} ${extractErrorMsg(error)}`);
21164
21449
  throw error;
@@ -21231,8 +21516,8 @@ var SyncPeer_V1 = class _SyncPeer_V1 extends LightWitnessBase_V1 {
21231
21516
  // if (logalot) { console.log(`${lc} complete.`); }
21232
21517
  // }
21233
21518
  // }
21234
- async authenticateValidateAuthorize({ context, fullSagaHistory }) {
21235
- const lc2 = `${this.lc}[${this.authenticateValidateAuthorize.name}]`;
21519
+ async authenticateAndValidate({ context }) {
21520
+ const lc2 = `${this.lc}[${this.authenticateAndValidate.name}]`;
21236
21521
  try {
21237
21522
  if (logalot54) {
21238
21523
  console.log(`${lc2} starting... (I: add238055cd84a222c5b8c89913af526)`);
@@ -21241,7 +21526,7 @@ var SyncPeer_V1 = class _SyncPeer_V1 extends LightWitnessBase_V1 {
21241
21526
  throw new Error(`(UNEXPECTED) opts falsy in authenticateValidateAuthorize (E: b7e5a8ad99d84e1ba8d8f7facd288826)`);
21242
21527
  }
21243
21528
  const { localSpace } = this.opts;
21244
- const authenticationErrors = await authenticateContext({
21529
+ const authenticationErrors = await authenticateContextIntrinsically({
21245
21530
  context,
21246
21531
  space: localSpace
21247
21532
  });
@@ -21252,10 +21537,6 @@ var SyncPeer_V1 = class _SyncPeer_V1 extends LightWitnessBase_V1 {
21252
21537
  if (validationErrors.length > 0) {
21253
21538
  throw new Error(`invalid context received. validationErrors: ${validationErrors} (E: 8b34c875c968af29bc433138e57a7826)`);
21254
21539
  }
21255
- const authorizationErrors = await authorizeContext({ context, fullSagaHistory });
21256
- if (authorizationErrors.length > 0) {
21257
- throw new Error(`invalid context authorization. authorizationErrors: ${authorizationErrors} (E: 8ddc284a758cf10ba829334c1babb826)`);
21258
- }
21259
21540
  } catch (error) {
21260
21541
  console.error(`${lc2} ${extractErrorMsg(error)}`);
21261
21542
  throw error;
@@ -21286,24 +21567,13 @@ var SyncPeer_V1 = class _SyncPeer_V1 extends LightWitnessBase_V1 {
21286
21567
  if (!context.sagaFrame) {
21287
21568
  throw new Error(`context.sagaFrame falsy. (E: a33dd88aa108e2bad9e885885731ce26)`);
21288
21569
  }
21289
- const sagaHistory_beforeSend = await getFullSyncSagaHistory({
21290
- sagaIbGib: context.sagaFrame,
21291
- space: this.opts.localSpace
21292
- });
21293
- await this.authenticateValidateAuthorize({
21294
- context,
21295
- fullSagaHistory: sagaHistory_beforeSend
21296
- });
21570
+ await this.authenticateAndValidate({ context });
21297
21571
  const response = await this.sendContextRequest(context);
21298
21572
  if (response) {
21299
21573
  const sagaHistory_afterSend = await getFullSyncSagaHistory({
21300
21574
  sagaIbGib: context.sagaFrame,
21301
21575
  space: this.opts.localSpace
21302
21576
  });
21303
- await this.authenticateValidateAuthorize({
21304
- context,
21305
- fullSagaHistory: sagaHistory_afterSend
21306
- });
21307
21577
  return response;
21308
21578
  } else {
21309
21579
  if (logalot54) {
@@ -21354,7 +21624,48 @@ var SyncPeer_V1 = class _SyncPeer_V1 extends LightWitnessBase_V1 {
21354
21624
  }
21355
21625
  };
21356
21626
 
21357
- // ../../libs/core-gib/dist/sync/sync-peer/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs
21627
+ // ../../libs/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-constants.mjs
21628
+ var SYNC_WEB_SOCKET_MSG_TYPE_AUTH_CHALLENGE_INIT = "auth-challenge-init";
21629
+ var SYNC_WEB_SOCKET_MSG_TYPE_AUTH_INIT = "auth-init";
21630
+ var SYNC_WEB_SOCKET_MSG_TYPE_AUTH_CHALLENGE = "auth-challenge";
21631
+ var SYNC_WEB_SOCKET_MSG_TYPE_AUTH_PROOF = "auth-proof";
21632
+ var SYNC_WEB_SOCKET_MSG_TYPE_AUTH_OK = "auth-ok";
21633
+ var SYNC_WEB_SOCKET_MSG_TYPE_AUTH_FAIL = "auth-fail";
21634
+ var SYNC_WEB_SOCKET_MSG_TYPE_SYNC_FRAME = "sync-frame";
21635
+ var SYNC_WEB_SOCKET_MSG_TYPE_SYNC_FRAME_RESPONSE = "sync-frame-response";
21636
+ var SYNC_WEB_SOCKET_MSG_TYPE_SYNC_FRAME_AUTHENTICATED = "sync-frame-authenticated";
21637
+ var SYNC_WEB_SOCKET_MSG_TYPE_SYNC_FRAME_RESPONSE_AUTHENTICATED = "sync-frame-response-authenticated";
21638
+ var SYNC_WEB_SOCKET_MSG_TYPE_DOMAIN_PAYLOAD = "domain-payload";
21639
+ var SYNC_WEB_SOCKET_MSG_TYPE_SYNC_ERROR = "sync-error";
21640
+ var SyncWebSocketMsgType = {
21641
+ /** Sent by server/receiver to trigger connection authentication. */
21642
+ auth_challenge_init: SYNC_WEB_SOCKET_MSG_TYPE_AUTH_CHALLENGE_INIT,
21643
+ /** Sent by client/sender to start the authentication handshake with the target session address. */
21644
+ auth_init: SYNC_WEB_SOCKET_MSG_TYPE_AUTH_INIT,
21645
+ /** Sent by server/receiver with dynamic connect challenges to be solved. */
21646
+ auth_challenge: SYNC_WEB_SOCKET_MSG_TYPE_AUTH_CHALLENGE,
21647
+ /** Sent by client/sender with proof of session keystone evolution solving challenges. */
21648
+ auth_proof: SYNC_WEB_SOCKET_MSG_TYPE_AUTH_PROOF,
21649
+ /** Sent by server/receiver signaling successful challenge resolution and upgrade to active sync. */
21650
+ auth_ok: SYNC_WEB_SOCKET_MSG_TYPE_AUTH_OK,
21651
+ /** Sent when authentication fails. */
21652
+ auth_fail: SYNC_WEB_SOCKET_MSG_TYPE_AUTH_FAIL,
21653
+ /** Sent by client/sender to transmit the next sync transaction context without payload ibgibs. */
21654
+ sync_frame: SYNC_WEB_SOCKET_MSG_TYPE_SYNC_FRAME,
21655
+ /** Sent by server/receiver responding with the next sync transaction context. */
21656
+ sync_frame_response: SYNC_WEB_SOCKET_MSG_TYPE_SYNC_FRAME_RESPONSE,
21657
+ /** Sent by server/receiver after context is validated/authenticated to signal payload transmission. */
21658
+ sync_frame_authenticated: SYNC_WEB_SOCKET_MSG_TYPE_SYNC_FRAME_AUTHENTICATED,
21659
+ /** Sent by client/sender after response context is validated/authenticated to signal payload transmission. */
21660
+ sync_frame_response_authenticated: SYNC_WEB_SOCKET_MSG_TYPE_SYNC_FRAME_RESPONSE_AUTHENTICATED,
21661
+ /** Sent to stream a single domain payload ibgib. */
21662
+ domain_payload: SYNC_WEB_SOCKET_MSG_TYPE_DOMAIN_PAYLOAD,
21663
+ /** Sent when a sync runtime execution error occurs. */
21664
+ sync_error: SYNC_WEB_SOCKET_MSG_TYPE_SYNC_ERROR
21665
+ };
21666
+ var SYNC_WEB_SOCKET_MSG_TYPE_VALID_VALUES = Object.values(SyncWebSocketMsgType);
21667
+
21668
+ // ../../libs/core-gib/dist/sync/sync-peer/sync-peer-websocket/sync-peer-websocket-receiver/sync-peer-websocket-receiver-v1.mjs
21358
21669
  var logalot55 = GLOBAL_LOG_A_LOT2 || true;
21359
21670
  var SyncPeerWebSocketReceiver_V1 = class _SyncPeerWebSocketReceiver_V1 extends SyncPeer_V1 {
21360
21671
  lc = `[${_SyncPeerWebSocketReceiver_V1.name}]`;
@@ -21367,6 +21678,11 @@ var SyncPeerWebSocketReceiver_V1 = class _SyncPeerWebSocketReceiver_V1 extends S
21367
21678
  challengeUuid;
21368
21679
  demandedIds;
21369
21680
  sessionS_tjpAddr;
21681
+ // Runtime state variables for delayed payload streaming
21682
+ pendingContext;
21683
+ pendingPayloadAddrs;
21684
+ pendingResponsePayloadsToSend = [];
21685
+ receivedPayloads = [];
21370
21686
  constructor(initialData, initialRel8ns) {
21371
21687
  super(initialData, initialRel8ns);
21372
21688
  }
@@ -21381,13 +21697,13 @@ var SyncPeerWebSocketReceiver_V1 = class _SyncPeerWebSocketReceiver_V1 extends S
21381
21697
  try {
21382
21698
  this.challengeUuid = await getUUID();
21383
21699
  socketWrapper.send(JSON.stringify({
21384
- type: "auth-challenge-init",
21700
+ type: SyncWebSocketMsgType.auth_challenge_init,
21385
21701
  challengeUuid: this.challengeUuid
21386
21702
  }));
21387
21703
  } catch (error) {
21388
21704
  console.error(`${lc2} failed triggering challenge init: ${extractErrorMsg(error)}`);
21389
21705
  socketWrapper.send(JSON.stringify({
21390
- type: "auth-fail",
21706
+ type: SyncWebSocketMsgType.auth_fail,
21391
21707
  message: "Internal server connect error"
21392
21708
  }));
21393
21709
  }
@@ -21459,37 +21775,89 @@ var SyncPeerWebSocketReceiver_V1 = class _SyncPeerWebSocketReceiver_V1 extends S
21459
21775
  await this.handleConnectFrame(msg);
21460
21776
  return;
21461
21777
  }
21462
- if (msg.type === "domain-payload") {
21778
+ if (msg.type === SyncWebSocketMsgType.domain_payload) {
21463
21779
  const ibGib = msg.ibGib;
21464
- const tempSpace = await this.ensureLocalTempSpace();
21465
- await putInSpace({ space: tempSpace, ibGibs: [ibGib] });
21466
- } else if (msg.type === "sync-frame") {
21780
+ const validationErrors = await validateIbGibIntrinsically({ ibGib }) ?? [];
21781
+ if (validationErrors.length > 0) {
21782
+ throw new Error(`controlIbGibs invalid intrinsically. validationErrors: ${validationErrors.join("|")} (E: 5ee1787d4cc53d3d2c55f3d4f2865226)`);
21783
+ }
21784
+ const pendingPayloadAddrs = this.pendingPayloadAddrs;
21785
+ if (this.pendingContext && pendingPayloadAddrs) {
21786
+ const addr = getIbGibAddr({ ibGib });
21787
+ if (pendingPayloadAddrs.has(addr)) {
21788
+ const tempSpace = await this.ensureLocalTempSpace();
21789
+ await putInSpace({ space: tempSpace, ibGibs: [ibGib] });
21790
+ this.receivedPayloads.push(ibGib);
21791
+ pendingPayloadAddrs.delete(addr);
21792
+ if (pendingPayloadAddrs.size === 0 && this.pendingPayloadAddrs !== void 0) {
21793
+ const context = this.pendingContext;
21794
+ context.payloadIbGibsDomain = this.receivedPayloads;
21795
+ this.receivedPayloads = [];
21796
+ this.pendingContext = void 0;
21797
+ this.pendingPayloadAddrs = void 0;
21798
+ await this.executeIncomingSyncRequestAndRespond({ context });
21799
+ }
21800
+ } else {
21801
+ console.warn(`${lc2} received payload not in expected list: ${addr}`);
21802
+ }
21803
+ }
21804
+ } else if (msg.type === SyncWebSocketMsgType.sync_frame) {
21467
21805
  const context = msg.context;
21468
- const responseCtx = await this.handleIncomingSyncRequest({ context });
21469
- if (responseCtx) {
21470
- const responsePayloads = responseCtx.payloadIbGibsDomain ?? [];
21471
- for (const ibGib of responsePayloads) {
21472
- this.socketWrapper.send(JSON.stringify({
21473
- type: "domain-payload",
21474
- ibGib
21475
- }));
21806
+ const allControlIbGibs = [
21807
+ toDto2({ ibGib: context }),
21808
+ context.sagaFrame,
21809
+ context.sagaFrameMsg
21810
+ ];
21811
+ if (context.signedSessionIdentity) {
21812
+ allControlIbGibs.push(context.signedSessionIdentity);
21813
+ }
21814
+ for (const controlIbGib of allControlIbGibs) {
21815
+ const validationErrors = await validateIbGibIntrinsically({ ibGib: controlIbGib }) ?? [];
21816
+ if (validationErrors.length > 0) {
21817
+ throw new Error(`controlIbGibs invalid intrinsically. validationErrors: ${validationErrors.join("|")} (E: d40dfa87265a0b73c8ef784d1265ea26)`);
21476
21818
  }
21819
+ }
21820
+ await this.authenticateAndValidate({ context });
21821
+ for (const ibGib of allControlIbGibs) {
21822
+ await putInSpace({ space: this.opts.localSpace, ibGibs: [ibGib] });
21823
+ await registerNewIbGib({ space: this.opts.localSpace, ibGib });
21824
+ }
21825
+ const expectedPayloadAddrs = context.data?.["@payloadAddrsDomain"] || [];
21826
+ if (expectedPayloadAddrs.length > 0) {
21827
+ this.pendingContext = context;
21828
+ this.pendingPayloadAddrs = new Set(expectedPayloadAddrs);
21829
+ this.receivedPayloads = [];
21477
21830
  this.socketWrapper.send(JSON.stringify({
21478
- type: "sync-frame-response",
21479
- context: responseCtx
21831
+ type: SyncWebSocketMsgType.sync_frame_authenticated,
21832
+ contextAddr: getIbGibAddr({ ibGib: context })
21480
21833
  }));
21481
21834
  } else {
21482
- if (logalot55) {
21483
- console.log(`${lc2} synchronization session completed successfully.`);
21484
- }
21835
+ await this.executeIncomingSyncRequestAndRespond({ context });
21485
21836
  }
21837
+ } else if (msg.type === SyncWebSocketMsgType.sync_frame_response_authenticated) {
21838
+ const payloads = this.pendingResponsePayloadsToSend || [];
21839
+ this.pendingResponsePayloadsToSend = [];
21840
+ for (const ibGib of payloads) {
21841
+ this.socketWrapper.send(JSON.stringify({
21842
+ type: SyncWebSocketMsgType.domain_payload,
21843
+ ibGib
21844
+ }));
21845
+ }
21846
+ } else {
21847
+ throw new Error(`(UNEXPECTED) msg.type is ${msg.type}? not expected at this time (E: bad7c4fa1958b1976904cb884e624826)`);
21486
21848
  }
21487
21849
  } catch (error) {
21488
21850
  console.error(`${lc2} message frame handling failed: ${extractErrorMsg(error)}`);
21489
- this.socketWrapper?.send(JSON.stringify({
21490
- type: this.isAuthenticated ? "sync-error" : "auth-fail",
21491
- message: extractErrorMsg(error)
21492
- }));
21851
+ try {
21852
+ this.socketWrapper?.send(JSON.stringify({
21853
+ type: this.isAuthenticated ? SyncWebSocketMsgType.sync_error : SyncWebSocketMsgType.auth_fail,
21854
+ message: extractErrorMsg(error)
21855
+ }));
21856
+ } catch (nestedError) {
21857
+ console.error(`${lc2}[nested catch] failed to send error frame: ${extractErrorMsg(nestedError)}`);
21858
+ } finally {
21859
+ this.socketWrapper?.close();
21860
+ }
21493
21861
  }
21494
21862
  }
21495
21863
  /**
@@ -21499,7 +21867,7 @@ var SyncPeerWebSocketReceiver_V1 = class _SyncPeerWebSocketReceiver_V1 extends S
21499
21867
  const lc2 = `${this.lc}[${this.handleConnectFrame.name}]`;
21500
21868
  const metaspace = this.opts.localMetaspace;
21501
21869
  const space = this.opts.localSpace;
21502
- if (msg.type === "auth-init") {
21870
+ if (msg.type === SyncWebSocketMsgType.auth_init) {
21503
21871
  const { sAddr } = msg;
21504
21872
  if (logalot55) {
21505
21873
  console.log(`${lc2} auth-init for ${sAddr}`);
@@ -21514,11 +21882,11 @@ var SyncPeerWebSocketReceiver_V1 = class _SyncPeerWebSocketReceiver_V1 extends S
21514
21882
  const past = authorizedS.rel8ns?.past;
21515
21883
  this.sessionS_tjpAddr = past && past.length > 0 ? past[0] : getIbGibAddr({ ibGib: authorizedS });
21516
21884
  this.socketWrapper.send(JSON.stringify({
21517
- type: "auth-challenge",
21885
+ type: SyncWebSocketMsgType.auth_challenge,
21518
21886
  challengeUuid: this.challengeUuid,
21519
21887
  demandedIds: this.demandedIds
21520
21888
  }));
21521
- } else if (msg.type === "auth-proof") {
21889
+ } else if (msg.type === SyncWebSocketMsgType.auth_proof) {
21522
21890
  const { proofFrame } = msg;
21523
21891
  if (logalot55) {
21524
21892
  console.log(`${lc2} verifying auth-proof...`);
@@ -21538,57 +21906,54 @@ var SyncPeerWebSocketReceiver_V1 = class _SyncPeerWebSocketReceiver_V1 extends S
21538
21906
  demandedIds: this.demandedIds
21539
21907
  });
21540
21908
  await metaspace.put({ ibGibs: [proofFrame], space });
21909
+ await metaspace.registerNewIbGib({ ibGib: proofFrame, space });
21541
21910
  if (logalot55) {
21542
21911
  console.log(`${lc2} connect validation successful! Connection upgraded to active sync session.`);
21543
21912
  }
21544
21913
  this.isAuthenticated = true;
21545
21914
  this.socketWrapper.send(JSON.stringify({
21546
- type: "auth-ok"
21915
+ type: SyncWebSocketMsgType.auth_ok
21547
21916
  }));
21548
21917
  } else {
21549
21918
  throw new Error(`Unexpected message type ${msg.type} during connect phase (E: f67a0f47f8426c2b01af5bc3d0146b26)`);
21550
21919
  }
21551
21920
  }
21552
21921
  /**
21553
- * Executes the transaction turn through the local SyncSagaCoordinator.
21922
+ * Executes the incoming sync request through the local SyncSagaCoordinator and sends response.
21554
21923
  */
21555
- async handleIncomingSyncRequest({ context, payloadIbGibsControl = [] }) {
21556
- const lc2 = `${this.lc}[${this.handleIncomingSyncRequest.name}]`;
21924
+ async executeIncomingSyncRequestAndRespond({ context }) {
21925
+ const lc2 = `${this.lc}[${this.executeIncomingSyncRequestAndRespond.name}]`;
21557
21926
  try {
21558
21927
  if (logalot55) {
21559
- console.log(`${lc2} starting incoming sync turn...`);
21928
+ console.log(`${lc2} executing incoming sync turn...`);
21560
21929
  }
21561
21930
  if (!this.opts) {
21562
21931
  throw new Error(`opts not initialized. (E: 0c98186714e85b9a08bb9d98daada826)`);
21563
21932
  }
21564
21933
  const { localCoordinator, localMetaspace, localSpace } = this.opts;
21565
21934
  const localTempSpace = await this.ensureLocalTempSpace();
21566
- const allControlIbGibs = [context, ...payloadIbGibsControl];
21567
- for (const ibGib of allControlIbGibs) {
21568
- await putInSpace({ space: localSpace, ibGibs: [ibGib] });
21569
- await registerNewIbGib({ space: localSpace, ibGib });
21570
- }
21571
- const authErrors = await authenticateContext({
21572
- context,
21573
- space: localSpace
21574
- });
21575
- if (authErrors.length > 0) {
21576
- throw new Error(`Context authentication failed: ${authErrors.join(", ")} (E: 424bd9b03ff8a42df8b1a438ed393726)`);
21577
- }
21578
- if (context.payloadIbGibsDomain && context.payloadIbGibsDomain.length > 0) {
21579
- for (const ibGib of context.payloadIbGibsDomain) {
21580
- await putInSpace({ space: localTempSpace, ibGibs: [ibGib] });
21581
- }
21582
- }
21583
21935
  const responseCtx = await localCoordinator.continueSync({
21584
21936
  sagaContext: context,
21585
21937
  metaspace: localMetaspace,
21586
21938
  mySpace: localSpace,
21587
- myTempSpace: localTempSpace
21939
+ myTempSpace: localTempSpace,
21940
+ peer: this
21588
21941
  });
21589
- return responseCtx || void 0;
21942
+ if (responseCtx) {
21943
+ const responsePayloads = responseCtx.payloadIbGibsDomain ?? [];
21944
+ delete responseCtx.payloadIbGibsDomain;
21945
+ this.pendingResponsePayloadsToSend = responsePayloads;
21946
+ this.socketWrapper.send(JSON.stringify({
21947
+ type: SyncWebSocketMsgType.sync_frame_response,
21948
+ context: responseCtx
21949
+ }));
21950
+ } else {
21951
+ if (logalot55) {
21952
+ console.log(`${lc2} synchronization session completed successfully.`);
21953
+ }
21954
+ }
21590
21955
  } catch (error) {
21591
- console.error(`${lc2} handleIncomingSyncRequest turn execution failed: ${extractErrorMsg(error)}`);
21956
+ console.error(`${lc2} executeIncomingSyncRequestAndRespond failed: ${extractErrorMsg(error)}`);
21592
21957
  throw error;
21593
21958
  }
21594
21959
  }
@@ -21701,7 +22066,7 @@ async function appendToTimeline({ timeline, rel8nInfos, rel8nRemovalInfos, timel
21701
22066
  skipLock
21702
22067
  });
21703
22068
  }
21704
- metaspace.registerNewIbGib({ ibGib: newTimelineIbGib2, space });
22069
+ await metaspace.registerNewIbGib({ ibGib: newTimelineIbGib2, space });
21705
22070
  return newTimelineIbGib2;
21706
22071
  };
21707
22072
  const newTimelineIbGib = skipLock ? await fn() : await execInSpaceWithLocking({
@@ -22168,7 +22533,7 @@ var KeystoneConfigBuilderBase = class {
22168
22533
  replenish: this._replenish,
22169
22534
  selectSequentially: this._seq,
22170
22535
  selectRandomly: this._rand,
22171
- targetBindingChars: this._targetBinding
22536
+ targetBindingCount: this._targetBinding
22172
22537
  };
22173
22538
  }
22174
22539
  /**
@@ -22263,8 +22628,8 @@ function createStandardPoolConfig(opts) {
22263
22628
  }
22264
22629
 
22265
22630
  // ../../libs/core-gib/dist/sync/sync-saga-coordinator.mjs
22266
- var logalot58 = GLOBAL_LOG_A_LOT2;
22267
- var logalotControlDomain = false;
22631
+ var logalot58 = GLOBAL_LOG_A_LOT2 || true;
22632
+ var logalotControlDomain = true;
22268
22633
  var lcControlDomain = "[ControlDomain]";
22269
22634
  var SyncSagaCoordinator = class _SyncSagaCoordinator {
22270
22635
  lc = `[${_SyncSagaCoordinator.name}]`;
@@ -22369,7 +22734,7 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
22369
22734
  sessionSyncPoolConfig: this.defaultSessionSyncPoolConfig(),
22370
22735
  targetAddrs
22371
22736
  });
22372
- const sessionIdentity = await peer.establishSessionIdentity();
22737
+ await peer.establishSessionIdentity();
22373
22738
  await peer.connect({ sagaId });
22374
22739
  const { initFrame, initDomainGraph } = await this.createInitFrame({
22375
22740
  sagaId,
@@ -22377,7 +22742,8 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
22377
22742
  conflictStrategy,
22378
22743
  metaspace,
22379
22744
  localSpace,
22380
- tempSpace
22745
+ tempSpace,
22746
+ peer
22381
22747
  });
22382
22748
  await this.executeSagaLoop({
22383
22749
  initFrame,
@@ -22417,7 +22783,7 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
22417
22783
  * @returns next context result if another round, else if commit returns
22418
22784
  * null
22419
22785
  */
22420
- async continueSync({ sagaContext, mySpace, myTempSpace, metaspace }) {
22786
+ async continueSync({ sagaContext, mySpace, myTempSpace, metaspace, peer }) {
22421
22787
  const lc2 = `${this.lc}[${this.continueSync.name}]`;
22422
22788
  try {
22423
22789
  if (logalot58) {
@@ -22447,7 +22813,10 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
22447
22813
  sagaFrame: frame,
22448
22814
  localSpace: mySpace,
22449
22815
  payloadIbGibsDomain,
22450
- metaspace
22816
+ metaspace,
22817
+ sessionIdentityAddr: sagaContext.rel8ns?.sessionIdentity?.[0],
22818
+ peer,
22819
+ skipSign: true
22451
22820
  });
22452
22821
  const immediateValidationErrors = await validateContextAndSagaFrame({
22453
22822
  context: responseCtx
@@ -22513,102 +22882,116 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
22513
22882
  await subscription.unsubscribe();
22514
22883
  }
22515
22884
  }));
22516
- const requestCtx = await this.createSyncSagaContext({
22517
- sagaFrame: currentFrame,
22518
- /**
22519
- * init frame: empty
22520
- * ack frame: possible push offers
22521
- * delta frame: requested ibgibs or commit offer
22522
- * commit frame: empty
22523
- */
22524
- payloadIbGibsDomain: nextDomainIbGibs,
22525
- localSpace,
22526
- metaspace
22527
- });
22528
- if (logalotControlDomain) {
22529
- const domainAddrs = nextDomainIbGibs.map((p) => getIbGibAddr({ ibGib: p }));
22530
- console.log(`${lc2}${lcControlDomain} SENDER TRANSMIT -> peer.witness (I: 5b0081803698770f0bf64992220b312)`);
22531
- console.log(`${lc2}${lcControlDomain} Context: ${getIbGibAddr({ ibGib: requestCtx })}`);
22532
- console.log(`${lc2}${lcControlDomain} Frame: ${getIbGibAddr({ ibGib: currentFrame })}`);
22533
- console.log(`${lc2}${lcControlDomain} DOMAIN Payloads (${domainAddrs.length}): ${domainAddrs.join(", ") || "(none)"}`);
22534
- }
22535
- updates$.next(requestCtx);
22536
- peer.setOptionalOpts({ localSpace, localTempSpace: tempSpace });
22537
- const responseCtx = await peer.witness(requestCtx);
22538
- if (!responseCtx) {
22539
- if (currentFrame) {
22540
- const msg = await getSyncSagaMessageFromFrame({ frameIbGib: currentFrame, space: localSpace });
22541
- if (msg?.data?.stage === SyncStage.commit) {
22542
- if (logalot58) {
22543
- console.log(`${lc2} Sender sent Commit. Peer returned no response. Saga Complete. (I: 26f9ee073858ca78b8284753368b5226)`);
22885
+ try {
22886
+ const requestCtx = await this.createSyncSagaContext({
22887
+ sagaFrame: currentFrame,
22888
+ /**
22889
+ * init frame: empty
22890
+ * ack frame: possible push offers
22891
+ * delta frame: requested ibgibs or commit offer
22892
+ * commit frame: empty
22893
+ */
22894
+ payloadIbGibsDomain: nextDomainIbGibs,
22895
+ localSpace,
22896
+ metaspace,
22897
+ sessionIdentityAddr: peer.currentSessionIdentityAddr,
22898
+ peer
22899
+ });
22900
+ if (logalotControlDomain) {
22901
+ const domainAddrs = nextDomainIbGibs.map((p) => getIbGibAddr({ ibGib: p }));
22902
+ console.log(`${lc2}${lcControlDomain} SENDER TRANSMIT -> peer.witness (I: 5b0081803698770f0bf64992220b312)`);
22903
+ console.log(`${lc2}${lcControlDomain} Context: ${getIbGibAddr({ ibGib: requestCtx })}`);
22904
+ console.log(`${lc2}${lcControlDomain} Frame: ${getIbGibAddr({ ibGib: currentFrame })}`);
22905
+ console.log(`${lc2}${lcControlDomain} DOMAIN Payloads (${domainAddrs.length}): ${domainAddrs.join(", ") || "(none)"}`);
22906
+ }
22907
+ updates$.next(requestCtx);
22908
+ peer.setOptionalOpts({ localSpace, localTempSpace: tempSpace });
22909
+ const responseCtx = await peer.witness(requestCtx);
22910
+ if (!responseCtx) {
22911
+ if (currentFrame) {
22912
+ const msg = await getSyncSagaMessageFromFrame({ frameIbGib: currentFrame, space: localSpace });
22913
+ if (msg?.data?.stage === SyncStage.commit) {
22914
+ if (logalot58) {
22915
+ console.log(`${lc2} Sender sent Commit. Peer returned no response. Saga Complete. (I: 26f9ee073858ca78b8284753368b5226)`);
22916
+ }
22917
+ currentFrame = null;
22918
+ break;
22919
+ } else {
22920
+ throw new Error(`(UNEXPECTED) responseCtx falsy and currentFrame truthy, but we're not in the commit stage? This may be expected ultimately, but atow I am not seeing this as being expected. (E: cc34498962bd370deeff351fac939f26)`);
22544
22921
  }
22545
- currentFrame = null;
22546
- break;
22547
22922
  } else {
22548
- throw new Error(`(UNEXPECTED) responseCtx falsy and currentFrame truthy, but we're not in the commit stage? This may be expected ultimately, but atow I am not seeing this as being expected. (E: cc34498962bd370deeff351fac939f26)`);
22923
+ throw new Error(`(UNEXPECTED) no response and currentFrame falsy? (E: 8d1085ea2f28cfc3f9c922649864a826)`);
22549
22924
  }
22550
- } else {
22551
- throw new Error(`(UNEXPECTED) no response and currentFrame falsy? (E: 8d1085ea2f28cfc3f9c922649864a826)`);
22552
22925
  }
22553
- }
22554
- if (!responseCtx.data) {
22555
- throw new Error(`(UNEXPECTED) responseCtx.data falsy? (E: a969992bae53ab18a827ec58aec15826)`);
22556
- }
22557
- updates$.next(responseCtx);
22558
- const contextAndSagaFrameValidationErrors = await validateContextAndSagaFrame({ context: responseCtx });
22559
- if (contextAndSagaFrameValidationErrors.length > 0) {
22560
- throw new Error(`contextAndSagaFrameValidationErrors: ${contextAndSagaFrameValidationErrors} (E: 6eebe8e7fa437c00a8cde3ada3c66826)`);
22561
- }
22562
- const responsePayloadAddrsDomain = responseCtx.data[SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN] || [];
22563
- if (responsePayloadAddrsDomain.length > 0) {
22564
- responseCtx.payloadIbGibsDomain = await this.pollForDomainPayloads({
22565
- expectedAddrs: responsePayloadAddrsDomain,
22566
- pollIntervalMs: 20,
22567
- // relatively arbitrary right now
22568
- domainPayloadsMap,
22569
- tempSpace
22926
+ if (!responseCtx.data) {
22927
+ throw new Error(`(UNEXPECTED) responseCtx.data falsy? (E: a969992bae53ab18a827ec58aec15826)`);
22928
+ }
22929
+ updates$.next(responseCtx);
22930
+ const contextAndSagaFrameValidationErrors = await validateContextAndSagaFrame({ context: responseCtx });
22931
+ if (contextAndSagaFrameValidationErrors.length > 0) {
22932
+ throw new Error(`contextAndSagaFrameValidationErrors: ${contextAndSagaFrameValidationErrors} (E: 6eebe8e7fa437c00a8cde3ada3c66826)`);
22933
+ }
22934
+ const returnContextErrors = await this.validateReturnContext({
22935
+ requestCtx,
22936
+ responseCtx,
22937
+ localSpace
22570
22938
  });
22571
- }
22572
- if (!responseCtx.sagaFrame) {
22573
- throw new Error(`(UNEXPECTED) responseCtx.sagaFrame falsy? the Peer should have set this when it got the response back from the remote. (E: e650adadf9a2063ec6764a1e31d3d826)`);
22574
- }
22575
- if (logalotControlDomain) {
22576
- const responseControlAddrs = responseCtx.data?.["@payloadAddrsControl"] || [];
22577
- console.log(`${lc2}${lcControlDomain} SENDER RECEIVED <- peer.witness (I: 3dc76a9744d89a4fc3e2f076c2be4826)`);
22578
- console.log(`${lc2}${lcControlDomain} Response Context: ${getIbGibAddr({ ibGib: responseCtx })}`);
22579
- console.log(`${lc2}${lcControlDomain} Response Saga Frame: ${getIbGibAddr({ ibGib: responseCtx.sagaFrame })}`);
22580
- console.log(`${lc2}${lcControlDomain} CONTROL Payloads (${responseControlAddrs.length}): ${responseControlAddrs.join(", ") || "(none)"}`);
22581
- console.log(`${lc2}${lcControlDomain} DOMAIN Payloads (${responsePayloadAddrsDomain.length}): ${responsePayloadAddrsDomain.join(", ") || "(none)"}`);
22582
- }
22583
- const contextResult = await this.handleResponseSagaContext({
22584
- sagaContext: responseCtx,
22585
- initDomainGraph,
22586
- mySpace: localSpace,
22587
- myTempSpace: tempSpace,
22588
- metaspace
22589
- });
22590
- if (!contextResult) {
22591
- console.error(`${lc2} NAG ERROR (DOES NOT THROW): does this ever hit now? (E: e04d02efc2a8e72a88b79f1f0f95ca26)`);
22592
- break;
22593
- } else if (contextResult.nextFrameInfo?.sagaComplete) {
22594
- if (logalot58) {
22595
- console.log(`${lc2} Handler returned null (Saga End). (I: 123bf9e7dca8886de72553a8d4f29e26)`);
22939
+ if (returnContextErrors.length > 0) {
22940
+ throw new Error(`validateReturnContext errors: ${returnContextErrors.join(", ")} (E: cb8a023b9d0728cceb09fa3da0bb8226)`);
22941
+ }
22942
+ const responsePayloadAddrsDomain = responseCtx.data[SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN] || [];
22943
+ if (responsePayloadAddrsDomain.length > 0) {
22944
+ responseCtx.payloadIbGibsDomain = await this.pollForDomainPayloads({
22945
+ expectedAddrs: responsePayloadAddrsDomain,
22946
+ pollIntervalMs: 20,
22947
+ // relatively arbitrary right now
22948
+ domainPayloadsMap,
22949
+ tempSpace
22950
+ });
22596
22951
  }
22597
- break;
22598
- }
22599
- if (contextResult.errorMsg) {
22600
- throw new Error(`Couldn't handle response saga context. errorMsg: ${contextResult.errorMsg} (E: c948e81d513b2a0eb8b8afa878edc626)`);
22601
- } else if (!contextResult.nextFrameInfo) {
22602
- throw new Error(`(UNEXPECTED) contextResult.nextFrameInfo falsy? (E: c287a82e823e662a77923278e2418826)`);
22603
- }
22604
- const { frame, payloadIbGibsDomain } = contextResult.nextFrameInfo;
22605
- currentFrame = frame;
22606
- nextDomainIbGibs = [...payloadIbGibsDomain || []];
22607
- if (logalotControlDomain) {
22608
- const handlerDomainAddrs = nextDomainIbGibs.map((p) => getIbGibAddr({ ibGib: p }));
22609
- console.log(`${lc2}${lcControlDomain} HANDLER RESULT -> next iteration (I: 6b0d88c4c28857ccd812381515bd7826)`);
22610
- console.log(`${lc2}${lcControlDomain} Next Frame: ${getIbGibAddr({ ibGib: currentFrame })}`);
22611
- console.log(`${lc2}${lcControlDomain} DOMAIN for next (${handlerDomainAddrs.length}): ${handlerDomainAddrs.join(", ") || "(none)"}`);
22952
+ if (!responseCtx.sagaFrame) {
22953
+ throw new Error(`(UNEXPECTED) responseCtx.sagaFrame falsy? the Peer should have set this when it got the response back from the remote. (E: e650adadf9a2063ec6764a1e31d3d826)`);
22954
+ }
22955
+ if (logalotControlDomain) {
22956
+ const responseControlAddrs = responseCtx.data?.["@payloadAddrsControl"] || [];
22957
+ console.log(`${lc2}${lcControlDomain} SENDER RECEIVED <- peer.witness (I: 3dc76a9744d89a4fc3e2f076c2be4826)`);
22958
+ console.log(`${lc2}${lcControlDomain} Response Context: ${getIbGibAddr({ ibGib: responseCtx })}`);
22959
+ console.log(`${lc2}${lcControlDomain} Response Saga Frame: ${getIbGibAddr({ ibGib: responseCtx.sagaFrame })}`);
22960
+ console.log(`${lc2}${lcControlDomain} CONTROL Payloads (${responseControlAddrs.length}): ${responseControlAddrs.join(", ") || "(none)"}`);
22961
+ console.log(`${lc2}${lcControlDomain} DOMAIN Payloads (${responsePayloadAddrsDomain.length}): ${responsePayloadAddrsDomain.join(", ") || "(none)"}`);
22962
+ }
22963
+ const contextResult = await this.handleResponseSagaContext({
22964
+ sagaContext: responseCtx,
22965
+ initDomainGraph,
22966
+ mySpace: localSpace,
22967
+ myTempSpace: tempSpace,
22968
+ metaspace
22969
+ });
22970
+ if (!contextResult) {
22971
+ console.error(`${lc2} NAG ERROR (DOES NOT THROW): does this ever hit now? (E: e04d02efc2a8e72a88b79f1f0f95ca26)`);
22972
+ break;
22973
+ } else if (contextResult.nextFrameInfo?.sagaComplete) {
22974
+ if (logalot58) {
22975
+ console.log(`${lc2} Handler returned null (Saga End). (I: 123bf9e7dca8886de72553a8d4f29e26)`);
22976
+ }
22977
+ break;
22978
+ }
22979
+ if (contextResult.errorMsg) {
22980
+ throw new Error(`Couldn't handle response saga context. errorMsg: ${contextResult.errorMsg} (E: c948e81d513b2a0eb8b8afa878edc626)`);
22981
+ } else if (!contextResult.nextFrameInfo) {
22982
+ throw new Error(`(UNEXPECTED) contextResult.nextFrameInfo falsy? (E: c287a82e823e662a77923278e2418826)`);
22983
+ }
22984
+ const { frame, payloadIbGibsDomain } = contextResult.nextFrameInfo;
22985
+ currentFrame = frame;
22986
+ nextDomainIbGibs = [...payloadIbGibsDomain || []];
22987
+ if (logalotControlDomain) {
22988
+ const handlerDomainAddrs = nextDomainIbGibs.map((p) => getIbGibAddr({ ibGib: p }));
22989
+ console.log(`${lc2}${lcControlDomain} HANDLER RESULT -> next iteration (I: 6b0d88c4c28857ccd812381515bd7826)`);
22990
+ console.log(`${lc2}${lcControlDomain} Next Frame: ${getIbGibAddr({ ibGib: currentFrame })}`);
22991
+ console.log(`${lc2}${lcControlDomain} DOMAIN for next (${handlerDomainAddrs.length}): ${handlerDomainAddrs.join(", ") || "(none)"}`);
22992
+ }
22993
+ } finally {
22994
+ await subscription.unsubscribe();
22612
22995
  }
22613
22996
  }
22614
22997
  }
@@ -22623,7 +23006,7 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
22623
23006
  * the other ibgibs that are related to this context stone should already be
22624
23007
  * put/registered in {@link localSpace}.
22625
23008
  */
22626
- async createSyncSagaContext({ sagaFrame, payloadIbGibsDomain, metaspace, localSpace }) {
23009
+ async createSyncSagaContext({ sagaFrame, payloadIbGibsDomain, metaspace, localSpace, sessionIdentityAddr, peer, skipSign }) {
22627
23010
  const lc2 = `[${this.createSyncSagaContext.name}]`;
22628
23011
  try {
22629
23012
  if (logalot58) {
@@ -22650,6 +23033,18 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
22650
23033
  const rel8ns = {
22651
23034
  sagaFrame: [getIbGibAddr({ ibGib: sagaFrame })]
22652
23035
  };
23036
+ let sessionIdentity = void 0;
23037
+ if (sessionIdentityAddr) {
23038
+ sessionIdentityAddr = await metaspace.getLatestAddr({ addr: sessionIdentityAddr, space: localSpace }) ?? sessionIdentityAddr;
23039
+ const resGet = await getFromSpace({ addr: sessionIdentityAddr, space: localSpace });
23040
+ if (resGet.success && resGet.ibGibs?.length === 1) {
23041
+ sessionIdentity = resGet.ibGibs[0];
23042
+ rel8ns.sessionIdentity = [sessionIdentityAddr];
23043
+ } else {
23044
+ debugger;
23045
+ throw new Error(`Couldn't get sessionIdentityAddr (${sessionIdentityAddr}) in space: ${localSpace.ib} (E: 5c29e80d68dbd1749866c358be093826)`);
23046
+ }
23047
+ }
22653
23048
  const ib = await getSyncSagaContextIb({ data });
22654
23049
  const contextIbGib = await Factory_V1.stone({
22655
23050
  parentPrimitiveIb: SYNC_SAGA_CONTEXT_ATOM,
@@ -22657,6 +23052,11 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
22657
23052
  data,
22658
23053
  rel8ns
22659
23054
  });
23055
+ const contextAddr = getIbGibAddr({ ibGib: contextIbGib });
23056
+ let signedSessionIdentity = void 0;
23057
+ if (sessionIdentity && !skipSign) {
23058
+ signedSessionIdentity = await peer.signContext({ contextAddr });
23059
+ }
22660
23060
  await putInSpace({ ibGib: contextIbGib, space: localSpace });
22661
23061
  await registerNewIbGib({
22662
23062
  ibGib: contextIbGib,
@@ -22664,9 +23064,20 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
22664
23064
  fnBroadcast: void 0
22665
23065
  });
22666
23066
  contextIbGib.sagaFrame = sagaFrame;
23067
+ const { msgStones } = await getSyncSagaFrameDependencyGraph({
23068
+ sagaIbGib: sagaFrame,
23069
+ localSpace
23070
+ });
23071
+ if (msgStones.length !== 1) {
23072
+ throw new Error(`(UNEXPECTED) msgStones.length !== 1 inside createSyncSagaContext? (E: a98165cf46ab4e82b7bd5e45a273b826)`);
23073
+ }
23074
+ contextIbGib.sagaFrameMsg = msgStones[0];
22667
23075
  if (payloadIbGibsDomain && payloadIbGibsDomain.length > 0) {
22668
23076
  contextIbGib.payloadIbGibsDomain = payloadIbGibsDomain;
22669
23077
  }
23078
+ if (signedSessionIdentity) {
23079
+ contextIbGib.signedSessionIdentity = signedSessionIdentity;
23080
+ }
22670
23081
  return contextIbGib;
22671
23082
  } catch (error) {
22672
23083
  console.error(`${lc2} ${extractErrorMsg(error)}`);
@@ -22753,7 +23164,7 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
22753
23164
  * Generates the first frame containing the Knowledge Map of the Local Space.
22754
23165
  * This is sent to the Receiver to begin Gap Analysis.
22755
23166
  */
22756
- async createInitFrame({ sagaId, domainIbGibs, conflictStrategy, metaspace, localSpace, tempSpace }) {
23167
+ async createInitFrame({ sagaId, domainIbGibs, conflictStrategy, metaspace, localSpace, tempSpace, peer }) {
22757
23168
  const lc2 = `${this.lc}[${this.createInitFrame.name}]`;
22758
23169
  try {
22759
23170
  if (logalot58) {
@@ -22788,7 +23199,8 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
22788
23199
  msgStones: [initStone],
22789
23200
  conflictStrategy,
22790
23201
  metaspace,
22791
- localSpace
23202
+ localSpace,
23203
+ sessionIdentity: peer.currentSessionIdentity
22792
23204
  });
22793
23205
  if (logalot58) {
22794
23206
  console.log(`${lc2} sagaFrame (init): ${pretty(sagaFrame)} (I: b3d6a8be69248f18713cc3073cb08626)`);
@@ -22803,6 +23215,39 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
22803
23215
  }
22804
23216
  }
22805
23217
  }
23218
+ /**
23219
+ * Validates that the return context received from a peer is a valid
23220
+ * continuation of the outbound context and that the session identity
23221
+ * is consistent.
23222
+ */
23223
+ async validateReturnContext({ requestCtx, responseCtx, localSpace }) {
23224
+ const lc2 = `${this.lc}[${this.validateReturnContext.name}]`;
23225
+ const errors = [];
23226
+ try {
23227
+ if (requestCtx.sagaFrame && responseCtx.sagaFrame) {
23228
+ const requestFrameAddr = getIbGibAddr({ ibGib: requestCtx.sagaFrame });
23229
+ const responseFrameAddr = getIbGibAddr({ ibGib: responseCtx.sagaFrame });
23230
+ const isContinuation = await isPastFrame({
23231
+ olderAddr: requestFrameAddr,
23232
+ newerAddr: responseFrameAddr,
23233
+ space: localSpace
23234
+ });
23235
+ if (!isContinuation) {
23236
+ errors.push(`Response saga frame (${responseFrameAddr}) is not a valid continuation of request saga frame (${requestFrameAddr}). (E: 2c85e8d97318ff24ac8a02bd3a068226)`);
23237
+ }
23238
+ } else {
23239
+ errors.push(`Missing sagaFrame on requestCtx or responseCtx. (E: b65c68ff891000ddca8d22384a088226)`);
23240
+ }
23241
+ const expectedSessionIdAddr = requestCtx.signedSessionIdentity ? getIbGibAddr({ ibGib: requestCtx.signedSessionIdentity }) : requestCtx.rel8ns?.sessionIdentity?.[0];
23242
+ const responseSessionIdAddr = responseCtx.rel8ns?.sessionIdentity?.[0];
23243
+ if (expectedSessionIdAddr !== responseSessionIdAddr) {
23244
+ errors.push(`Session identity mismatch. Expected ${expectedSessionIdAddr}, got ${responseSessionIdAddr}. (E: ab98716bca88d2243cc822187768226)`);
23245
+ }
23246
+ } catch (error) {
23247
+ errors.push(`Error during validateReturnContext: ${extractErrorMsg(error)} (E: da878e1239aa88ee27bdfca005c28226)`);
23248
+ }
23249
+ return errors;
23250
+ }
22806
23251
  /**
22807
23252
  * Helper to poll for streaming domain payloads and put them in the
22808
23253
  * local {@link tempSpace}.
@@ -22816,7 +23261,8 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
22816
23261
  console.log(`${lc2} starting... (I: 26dce86bfca572939885798802d6e926)`);
22817
23262
  }
22818
23263
  let resultDomainPayloads = [];
22819
- let pending = [...expectedAddrs];
23264
+ const uniqueExpectedAddrs = [...new Set(expectedAddrs)];
23265
+ let pending = [...uniqueExpectedAddrs];
22820
23266
  const start = Date.now();
22821
23267
  const timeoutMs = 5 * 60 * 1e3;
22822
23268
  while (pending.length > 0) {
@@ -22842,8 +23288,8 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
22842
23288
  await delay(pollIntervalMs);
22843
23289
  }
22844
23290
  }
22845
- if (expectedAddrs.length !== resultDomainPayloads.length) {
22846
- throw new Error(`(UNEXPECTED) expectedAddrs.length !== resultDomainPayloads.length? at this point, we expect all of the payload ibgibs to have been received. (E: 03749a7478c4b8b28bfc86951887a826)`);
23291
+ if (uniqueExpectedAddrs.length !== resultDomainPayloads.length) {
23292
+ throw new Error(`(UNEXPECTED) uniqueExpectedAddrs.length !== resultDomainPayloads.length? at this point, we expect all of the payload ibgibs to have been received. (E: 03749a7478c4b8b28bfc86951887a826)`);
22847
23293
  }
22848
23294
  return resultDomainPayloads;
22849
23295
  } catch (error) {
@@ -23293,11 +23739,11 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
23293
23739
  throw new Error(`${lc2} Peer reported terminal conflicts. (E: 23a0096ee05a2ccfa89334e8f156b426)`);
23294
23740
  }
23295
23741
  const outgoingPayloadIbGibsDomain_conflicts = [];
23742
+ const activeConflicts = [];
23296
23743
  if (conflicts.length > 0) {
23297
23744
  if (logalot58) {
23298
23745
  console.log(`${lc2} [CONFLICT DEBUG] Processing ${conflicts.length} non-terminal conflicts`);
23299
23746
  }
23300
- proposeCommit = false;
23301
23747
  for (const conflict of conflicts) {
23302
23748
  const {
23303
23749
  receiverTipAddr,
@@ -23356,13 +23802,26 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
23356
23802
  const deltaPayloadIbGib = deltaGraph[deltaPayloadAddr];
23357
23803
  outgoingPayloadIbGibsDomain_conflicts.push(deltaPayloadIbGib);
23358
23804
  });
23359
- if (conflict.accretivePayloadAddrs) {
23360
- throw new Error(`(UNEXPECTED) conflict.accretivePayloadAddrs already truthy? This is expected to be falsy at this point in the sync. (E: 6b6b1846779867849cbde208f4374326)`);
23805
+ const isFastForward = latestCommonFrameAddr === receiverTipAddr;
23806
+ if (isFastForward) {
23807
+ if (logalot58) {
23808
+ console.log(`${lc2} [CONFLICT DEBUG] TJP ${tjpAddr}: Fast-forward detected (receiver behind sender). Excluding from active conflicts and sending delta payload.`);
23809
+ }
23810
+ } else {
23811
+ if (conflict.accretivePayloadAddrs) {
23812
+ throw new Error(`(UNEXPECTED) conflict.accretivePayloadAddrs already truthy? This is expected to be falsy at this point in the sync. (E: 6b6b1846779867849cbde208f4374326)`);
23813
+ }
23814
+ conflict.accretivePayloadAddrs = accretivePayloadAddrs;
23815
+ activeConflicts.push(conflict);
23361
23816
  }
23362
- conflict.accretivePayloadAddrs = accretivePayloadAddrs;
23817
+ }
23818
+ if (activeConflicts.length > 0) {
23819
+ proposeCommit = false;
23820
+ } else {
23821
+ proposeCommit = true;
23363
23822
  }
23364
23823
  if (logalot58) {
23365
- console.log(`${lc2} [CONFLICT DEBUG] Finished processing ${conflicts.length} conflicts. outgoingPayloadIbGibsDomain_conflicts.length (total outgoing payload ibgibs for ALL conflicts): ${outgoingPayloadIbGibsDomain_conflicts.length}`);
23824
+ console.log(`${lc2} [CONFLICT DEBUG] Finished processing ${conflicts.length} conflicts. Active (divergent) conflicts: ${activeConflicts.length}. outgoingPayloadIbGibsDomain_conflicts.length (total outgoing payload ibgibs for ALL conflicts): ${outgoingPayloadIbGibsDomain_conflicts.length}`);
23366
23825
  }
23367
23826
  } else {
23368
23827
  if (logalot58) {
@@ -23391,7 +23850,7 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
23391
23850
  /**
23392
23851
  * these are the modified conflicts with additional information.
23393
23852
  */
23394
- conflicts,
23853
+ conflicts: activeConflicts,
23395
23854
  /**
23396
23855
  * we're sending these domain ibgibs as payload (they were
23397
23856
  * requested by receiver and/or they are being sent as delta
@@ -24090,7 +24549,7 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
24090
24549
  /**
24091
24550
  * Evolves the saga timeline with a new frame.
24092
24551
  */
24093
- async evolveSyncSagaIbGib({ prevSagaIbGib, conflictStrategy, msgStones, localSpace, metaspace }) {
24552
+ async evolveSyncSagaIbGib({ prevSagaIbGib, conflictStrategy, msgStones, localSpace, metaspace, sessionIdentity }) {
24094
24553
  const lc2 = `${this.lc}[${this.evolveSyncSagaIbGib.name}]`;
24095
24554
  try {
24096
24555
  if (!msgStones || msgStones.length === 0) {
@@ -24148,6 +24607,13 @@ var SyncSagaCoordinator = class _SyncSagaCoordinator {
24148
24607
  isTjp: true,
24149
24608
  conflictStrategy
24150
24609
  };
24610
+ if (sessionIdentity) {
24611
+ const sessionIdentityTjpAddr = getTjpAddr({ ibGib: sessionIdentity });
24612
+ if (!sessionIdentityTjpAddr) {
24613
+ throw new Error(`(UNEXPECTED) sessionIdentity is truthy but sessionIdentityTjpAddr falsy? (E: f52004c10288987a6886f4e8fdf90826)`);
24614
+ }
24615
+ data.sessionIdentityTjpAddr = sessionIdentityTjpAddr;
24616
+ }
24151
24617
  const ib = await getSyncIb({ data });
24152
24618
  const stoneAddrs = msgStones.map((s) => getIbGibAddr({ ibGib: s }));
24153
24619
  const rel8ns = { [SYNC_MSG_REL8N_NAME]: stoneAddrs };
@@ -24314,9 +24780,26 @@ var SyncUpgradeHandlerBase = class _SyncUpgradeHandlerBase extends ServeGibHandl
24314
24780
  sagaId: void 0
24315
24781
  // Resolved dynamically inside runtime turns
24316
24782
  });
24783
+ socket.on("error", (err) => {
24784
+ if (logalot59) {
24785
+ console.warn(`[SyncUpgradeHandlerBase] Socket error: ${extractErrorMsg(err)}`);
24786
+ }
24787
+ try {
24788
+ socket.destroy();
24789
+ } catch (e) {
24790
+ }
24791
+ });
24317
24792
  const socketWrapper = {
24318
24793
  send(data) {
24319
- socket.write(encodeTextFrame(data));
24794
+ if (socket.writable) {
24795
+ try {
24796
+ socket.write(encodeTextFrame(data));
24797
+ } catch (e) {
24798
+ if (logalot59) {
24799
+ console.warn(`[SyncUpgradeHandlerBase] failed to write message frame: ${extractErrorMsg(e)}`);
24800
+ }
24801
+ }
24802
+ }
24320
24803
  },
24321
24804
  onMessage(callback) {
24322
24805
  const decoder = new WebSocketFrameDecoder();
@@ -24332,13 +24815,27 @@ var SyncUpgradeHandlerBase = class _SyncUpgradeHandlerBase extends ServeGibHandl
24332
24815
  if (logalot59) {
24333
24816
  console.warn(`[SyncUpgradeHandlerBase] closing connection due to decoder error: ${extractErrorMsg(error)}`);
24334
24817
  }
24335
- socket.write(encodeCloseFrame());
24818
+ if (socket.writable) {
24819
+ try {
24820
+ socket.write(encodeCloseFrame());
24821
+ } catch (e) {
24822
+ }
24823
+ }
24336
24824
  socket.end();
24337
24825
  }
24338
24826
  });
24339
24827
  },
24340
24828
  onClose(callback) {
24341
24829
  socket.on("close", callback);
24830
+ },
24831
+ close() {
24832
+ if (socket.writable) {
24833
+ try {
24834
+ socket.write(encodeCloseFrame());
24835
+ } catch (e) {
24836
+ }
24837
+ }
24838
+ socket.end();
24342
24839
  }
24343
24840
  };
24344
24841
  await receiverPeer.bindSocket(socketWrapper);
@@ -24351,7 +24848,9 @@ var SyncUpgradeHandlerBase = class _SyncUpgradeHandlerBase extends ServeGibHandl
24351
24848
  }
24352
24849
  async parseParamsImpl(reqCtx) {
24353
24850
  const match = reqCtx.pathname.match(this.regex);
24354
- if (!match) return void 0;
24851
+ if (!match) {
24852
+ return void 0;
24853
+ }
24355
24854
  const domainIb = decodeURIComponent(match[1]);
24356
24855
  const domainGib = decodeURIComponent(match[2]);
24357
24856
  const domainAddr = getIbGibAddr({ ib: domainIb, gib: domainGib });