@quantiya/codevibe-core 2.0.75 → 2.0.76

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.
@@ -10294,7 +10294,7 @@ var SyncJournalError = class extends Error {
10294
10294
  this.code = code;
10295
10295
  this.name = "SyncJournalError";
10296
10296
  }
10297
- }, UUID8 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i, MAX_RECORD_BYTES = 1024 * 1024, MAX_ENVELOPE_BYTES = 2 * MAX_RECORD_BYTES, MAX_FILES = 256, MAX_STORE_BYTES = 32 * 1024 * 1024, MAX_RETIREMENT_INTENTS = 16, MAX_RETIREMENT_BYTES = 32 * 1024, invalid7 = () => {
10297
+ }, UUID8 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i, MAX_RECORD_BYTES = 1024 * 1024, MAX_ENVELOPE_BYTES = 2 * MAX_RECORD_BYTES, MAX_FILES = 256, MAX_STORE_BYTES = 32 * 1024 * 1024, MAX_RETIREMENT_INTENTS = 16, MAX_RETIREMENT_BYTES = 32 * 1024, MAX_INVENTORY_FILES = MAX_FILES * 4 + MAX_RETIREMENT_INTENTS * 2 + 8, MAX_DIRECTORY_ENTRIES = MAX_INVENTORY_FILES * 4 + MAX_FILES + MAX_RETIREMENT_INTENTS * 2 + 8, invalid7 = () => {
10298
10298
  throw new SyncJournalError("SYNC_JOURNAL_INVALID");
10299
10299
  }, errorCode = (error) => error?.code;
10300
10300
  function operationId(value) {
@@ -10487,7 +10487,7 @@ var sourceCursorId = (scope, stream) => stableUuid("codevibe-sync-source-cursor-
10487
10487
  }) : (this.options.assertAccount(), []);
10488
10488
  }
10489
10489
  /** One encrypted intent/credential record per original desktop incarnation.
10490
- * This uses the account journal's existing 256-file / 32-MiB total bound. */
10490
+ * Bookkeeping shares the 32-MiB bound, but not outbound-operation slots. */
10491
10491
  desktopRegistration(register, now = Date.now) {
10492
10492
  let scope = this.sessionScope;
10493
10493
  if (!scope || typeof register != "function") return invalid7();
@@ -11123,6 +11123,14 @@ var sourceCursorId = (scope, stream) => stableUuid("codevibe-sync-source-cursor-
11123
11123
  let plan = await this.withStore((key) => this.retiredSourcePlan(key, input.expectedSessionKeyGen));
11124
11124
  if (!plan.sources.length) return { sourcesRemoved: 0, operationsRemoved: 0 };
11125
11125
  parseSyncSessionRetirementReceipt(await confirm(input), input), this.options.assertAccount();
11126
+ let total = { sourcesRemoved: 0, operationsRemoved: 0 };
11127
+ for (let page = 0; page < MAX_INVENTORY_FILES; page++) {
11128
+ let removed = await this.removeRetiredSourceBatch(plan, input.expectedSessionKeyGen);
11129
+ if (total.sourcesRemoved += removed.sourcesRemoved, total.operationsRemoved += removed.operationsRemoved, plan = await this.withStore((key) => this.retiredSourcePlan(key, input.expectedSessionKeyGen)), !plan.sources.length) return total;
11130
+ }
11131
+ throw new SyncJournalError("SYNC_OPERATION_PENDING");
11132
+ }
11133
+ async removeRetiredSourceBatch(plan, expectedSessionKeyGen) {
11126
11134
  let owners = [], fence = async () => {
11127
11135
  this.options.assertAccount();
11128
11136
  for (let owner of owners) if (!await owner.reassertOwnership()) throw new SyncJournalError("SYNC_JOURNAL_LOCK_LOST");
@@ -11137,7 +11145,7 @@ var sourceCursorId = (scope, stream) => stableUuid("codevibe-sync-source-cursor-
11137
11145
  if (owners.push(owner), this.options.assertAccount(), !await owner.reassertOwnership()) throw new SyncJournalError("SYNC_JOURNAL_LOCK_LOST");
11138
11146
  }
11139
11147
  return await this.withStore(async (key, storeFence) => {
11140
- let current = await this.retiredSourcePlan(key, input.expectedSessionKeyGen);
11148
+ let current = await this.retiredSourcePlan(key, expectedSessionKeyGen);
11141
11149
  if (current.digest !== plan.digest) throw new SyncJournalError("SYNC_OPERATION_PENDING");
11142
11150
  await fence();
11143
11151
  for (let name of current.operations)
@@ -11196,15 +11204,20 @@ var sourceCursorId = (scope, stream) => stableUuid("codevibe-sync-source-cursor-
11196
11204
  }
11197
11205
  async retiredSourcePlan(key, expectedSessionKeyGen) {
11198
11206
  if (!this.sessionScope) return invalid7();
11199
- let sources = [], operations = [], images = [], linked = /* @__PURE__ */ new Set(), outer = /* @__PURE__ */ new Set(), inner = /* @__PURE__ */ new Set(), expectedInputs = /* @__PURE__ */ new Map(), bind = (value) => {
11207
+ let sources = [], operations = [], images = [], linked = /* @__PURE__ */ new Set(), outer = /* @__PURE__ */ new Set(), inner = /* @__PURE__ */ new Set(), selectedLinks = /* @__PURE__ */ new Set(), sourceCount = 0, linkedOperationCount = 0, expectedInputs = /* @__PURE__ */ new Map(), bind = (value) => {
11200
11208
  let input = request2("CREATE_EVENT", value), digest2 = fingerprint("CREATE_EVENT", input), prior = expectedInputs.get(input.clientOperationId);
11201
11209
  if (prior !== void 0 && prior !== digest2) return invalid7();
11202
11210
  expectedInputs.set(input.clientOperationId, digest2);
11203
11211
  }, add = (name, row3, links, locks, innerLocks = []) => {
11204
- if (this.matchesScope(row3)) {
11205
- sources.push(name), images.push([name, row3]);
11206
- for (let id5 of links) linked.add(id5);
11207
- if (sources.length > MAX_FILES || linked.size > MAX_FILES) throw new SyncJournalError("SYNC_JOURNAL_FULL");
11212
+ if (!this.matchesScope(row3)) return;
11213
+ sourceCount++, images.push([name, row3]);
11214
+ for (let id5 of links) linked.add(id5);
11215
+ if (sourceCount > MAX_INVENTORY_FILES || linked.size > MAX_INVENTORY_FILES * MAX_FILES)
11216
+ throw new SyncJournalError("SYNC_JOURNAL_FULL");
11217
+ let additionalLinks = links.filter((id5) => !selectedLinks.has(id5));
11218
+ if (!(sources.length >= MAX_FILES || selectedLinks.size + additionalLinks.length > MAX_FILES)) {
11219
+ sources.push(name);
11220
+ for (let id5 of links) selectedLinks.add(id5);
11208
11221
  for (let lock of locks) outer.add(lock);
11209
11222
  for (let lock of innerLocks) inner.add(lock);
11210
11223
  }
@@ -11255,16 +11268,16 @@ var sourceCursorId = (scope, stream) => stableUuid("codevibe-sync-source-cursor-
11255
11268
  let row3 = await this.read(id5, key);
11256
11269
  if (row3) {
11257
11270
  if (this.requireScope(row3), row3.action !== "CREATE_EVENT" || row3.state === "PENDING" && row3.input.expectedSessionKeyGen !== expectedSessionKeyGen || expectedInputs.has(id5) && expectedInputs.get(id5) !== row3.fingerprint) return invalid7();
11258
- operations.push(id5 + ".json"), images.push([id5 + ".json", row3]);
11271
+ linkedOperationCount++, images.push([id5 + ".json", row3]), selectedLinks.has(id5) && operations.push(id5 + ".json");
11259
11272
  }
11260
11273
  }
11261
- if (sources.length + operations.length > MAX_FILES) throw new SyncJournalError("SYNC_JOURNAL_FULL");
11274
+ if (linkedOperationCount > MAX_FILES) throw new SyncJournalError("SYNC_JOURNAL_FULL");
11262
11275
  return {
11263
11276
  sources: sources.sort(),
11264
11277
  operations,
11265
11278
  // Even a missing operation may retain its dead sender/GC lock after an
11266
11279
  // interrupted unlink. The source's complete link set owns reclamation.
11267
- locks: [...[...outer].sort(), ...[...inner].sort(), ...[...linked].sort().map((id5) => `send-${id5}.lockdir`)],
11280
+ locks: [...[...outer].sort(), ...[...inner].sort(), ...[...selectedLinks].sort().map((id5) => `send-${id5}.lockdir`)],
11268
11281
  digest: (0, import_node_crypto14.createHash)("sha256").update((0, import_json_freeze12.canonicalize)(images)).digest("hex")
11269
11282
  };
11270
11283
  }
@@ -11523,21 +11536,21 @@ var sourceCursorId = (scope, stream) => stableUuid("codevibe-sync-source-cursor-
11523
11536
  async recordNames(suffix = ".json") {
11524
11537
  let names = [], entries = 0, directory = await import_node_fs5.promises.opendir(this.directory);
11525
11538
  for await (let entry5 of directory) {
11526
- if (++entries > MAX_FILES * 4 + MAX_RETIREMENT_INTENTS * 2 + 8) throw new SyncJournalError("SYNC_JOURNAL_FULL");
11527
- if (entry5.name.endsWith(suffix) && ((!entry5.isFile() || !UUID8.test(entry5.name.slice(0, -suffix.length))) && invalid7(), names.push(entry5.name), names.length > MAX_FILES))
11539
+ if (++entries > MAX_DIRECTORY_ENTRIES) throw new SyncJournalError("SYNC_JOURNAL_FULL");
11540
+ if (entry5.name.endsWith(suffix) && ((!entry5.isFile() || !UUID8.test(entry5.name.slice(0, -suffix.length))) && invalid7(), names.push(entry5.name), names.length > (suffix === ".json" ? MAX_FILES : MAX_INVENTORY_FILES)))
11528
11541
  throw new SyncJournalError("SYNC_JOURNAL_FULL");
11529
11542
  }
11530
11543
  return names;
11531
11544
  }
11532
11545
  async checkCapacity(additionalBytes, replacedName, retirement = !1) {
11533
- let count4 = 0, bytes = additionalBytes, entries = 0, retirements = 0, directory = await import_node_fs5.promises.opendir(this.directory);
11546
+ let operations = 0, bookkeeping = 0, bytes = additionalBytes, entries = 0, retirements = 0, allocatesOperation = replacedName === void 0 || replacedName.endsWith(".json"), directory = await import_node_fs5.promises.opendir(this.directory);
11534
11547
  for await (let entry5 of directory)
11535
- if ((++entries > MAX_FILES * 4 + MAX_RETIREMENT_INTENTS * 2 + 8 || entry5.isSymbolicLink()) && invalid7(), entry5.isFile()) {
11548
+ if ((++entries > MAX_DIRECTORY_ENTRIES || entry5.isSymbolicLink()) && invalid7(), entry5.isFile()) {
11536
11549
  let stat13 = await import_node_fs5.promises.lstat(path18.join(this.directory, entry5.name));
11537
11550
  if ((!stat13.isFile() || stat13.nlink !== 1) && invalid7(), entry5.name === replacedName) continue;
11538
- entry5.name.endsWith(".retirement") && retirements++, bytes += stat13.size, count4++;
11551
+ bytes += stat13.size, entry5.name.endsWith(".json") ? operations++ : entry5.name.endsWith(".retirement") ? retirements++ : bookkeeping++;
11539
11552
  }
11540
- if (count4 >= MAX_FILES + (retirement ? MAX_RETIREMENT_INTENTS : 0) || bytes > MAX_STORE_BYTES + (retirement ? MAX_RETIREMENT_INTENTS * MAX_RETIREMENT_BYTES : 0) || retirement && retirements >= MAX_RETIREMENT_INTENTS) throw new SyncJournalError("SYNC_JOURNAL_FULL");
11553
+ if (allocatesOperation && operations >= MAX_FILES || !allocatesOperation && !retirement && bookkeeping >= MAX_INVENTORY_FILES || bytes > MAX_STORE_BYTES + (retirement ? MAX_RETIREMENT_INTENTS * MAX_RETIREMENT_BYTES : 0) || retirement && retirements >= MAX_RETIREMENT_INTENTS) throw new SyncJournalError("SYNC_JOURNAL_FULL");
11541
11554
  }
11542
11555
  async ensureDirectory() {
11543
11556
  let current = path18.parse(this.directory).root;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-core",
3
- "version": "2.0.75",
3
+ "version": "2.0.76",
4
4
  "description": "Core library for CodeVibe plugins - shared keychain, crypto, AppSync, and auth functionality",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",