@ricsam/r5d-worker 0.0.162 → 0.0.164

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.
@@ -11,6 +11,7 @@ import {
11
11
  WorkspaceConfig,
12
12
  WorkspaceError
13
13
  } from "./contracts.mjs";
14
+ import { OuterRepository, OuterSnapshotRefusal, OUTER_BRANCH, OUTER_CONFLICT_CODE } from "./outer.mjs";
14
15
  import { SessionArtifactStore, SessionArtifactChunk, RESERVED_ARTIFACT_ENV } from "./artifacts.mjs";
15
16
  import { WorkspaceFileWrite, WorkspaceFileWriteLookup } from "./file-write.mjs";
16
17
  import { WorkspaceStorageClient } from "./storage-client.mjs";
@@ -18,9 +19,12 @@ import {
18
19
  durableJson,
19
20
  ensureAuthorityGitRepositoryLayout,
20
21
  git,
22
+ gitResult,
21
23
  materializeTree,
22
24
  noSymlinkAncestors,
25
+ PLATFORM_COMMIT_EMAILS,
23
26
  privateRoot,
27
+ PROJECT_COMMIT_IDENTITY,
24
28
  readHostRegular,
25
29
  readRegular,
26
30
  selectedTree,
@@ -45,6 +49,7 @@ class WorkspaceAuthority {
45
49
  closeTask;
46
50
  actions = /* @__PURE__ */ new Set();
47
51
  repositoryInitializations = /* @__PURE__ */ new Map();
52
+ outerRepository;
48
53
  pending = 0;
49
54
  expectedCwd(config) {
50
55
  const workspaceRoot = this.config.workspaceRoot ?? this.config.root;
@@ -227,7 +232,10 @@ class WorkspaceAuthority {
227
232
  hydrations = /* @__PURE__ */ new Map();
228
233
  async ensureHydrated(identity) {
229
234
  const b = await this.bench(identity);
230
- if (b.config.rootProfile === "account") return;
235
+ if (b.config.rootProfile === "account") {
236
+ if (this.outerEnabled()) await this.synchronizeOuter(b.config.userId, { bootstrapOnly: true });
237
+ return;
238
+ }
231
239
  if (b.state.initialized) return;
232
240
  let task = this.hydrations.get(b.config.id);
233
241
  if (!task) {
@@ -312,10 +320,12 @@ class WorkspaceAuthority {
312
320
  async inspectGit(identity, command) {
313
321
  const b = await this.bench(identity);
314
322
  return this.serial(b, async () => {
315
- if (!b.state.initialized || !b.state.head) throw new WorkspaceError("not_initialized", "Initialize workspace first");
316
- const head = b.state.head;
323
+ if (!b.state.initialized) throw new WorkspaceError("not_initialized", "Initialize workspace first");
324
+ const innerHead = this.outerEnabled(b) && this.linkedWorkbench(b) ? await this.innerHead(b) : void 0;
325
+ const head = innerHead === void 0 ? b.state.head : innerHead ?? (await git(b.repo, ["hash-object", "-t", "tree", "--stdin"], "")).toString().trim();
326
+ if (!head) throw new WorkspaceError("not_initialized", "Initialize workspace first");
317
327
  const base = command.base ? GitOid.parse(command.base) : head;
318
- const treeHash = await snapshotTree(b.repo, b.config.cwd, head);
328
+ const treeHash = await snapshotTree(b.repo, b.config.cwd, innerHead === void 0 ? head : innerHead);
319
329
  if (command.method === "history") {
320
330
  const history = (await git(b.repo, ["log", "-100", "--format=%H%x00%P%x00%s%x00%an%x00%ae%x00%aI%x00%cI", head])).toString();
321
331
  return { head, treeHash, commits: history.trimEnd().split("\n").filter(Boolean).map((line) => {
@@ -363,10 +373,12 @@ class WorkspaceAuthority {
363
373
  if (owner.lockId !== this.lockId) throw new WorkspaceError("authority_lost", "Workspace authority lock changed");
364
374
  }
365
375
  serial(b, fn, admitted = false) {
376
+ return this.serialKey(this.linkedWorkbench(b) ? b.repo : b.config.id, fn, admitted);
377
+ }
378
+ serialKey(queueKey, fn, admitted = false) {
366
379
  if (this.closing && !admitted) return Promise.reject(new WorkspaceError("authority_closed", "Workspace authority is closing"));
367
380
  if (this.pending >= 32) return Promise.reject(new WorkspaceError("busy", "Workspace request budget reached"));
368
381
  this.pending++;
369
- const queueKey = this.linkedWorkbench(b) ? b.repo : b.config.id;
370
382
  const task = (this.queues.get(queueKey) ?? Promise.resolve()).catch(() => {
371
383
  }).then(async () => {
372
384
  await this.owned(admitted);
@@ -442,7 +454,14 @@ class WorkspaceAuthority {
442
454
  state.runs = Object.fromEntries(
443
455
  Object.entries(state.runs).filter(([, run]) => (run.sessionId ?? b.config.sessionId) === identity.sessionId)
444
456
  );
445
- return { workbench: { ...b.config, sessionId: identity.sessionId }, ...state, files };
457
+ let outer;
458
+ if (b.config.rootProfile === "account" && this.outerEnabled()) {
459
+ outer = structuredClone((await this.outer(b.config.userId)).state);
460
+ state.initialized = outer.initialized;
461
+ state.head = outer.head;
462
+ state.blocked = outer.blocked;
463
+ }
464
+ return { workbench: { ...b.config, sessionId: identity.sessionId }, ...state, files, ...outer ? { outer } : {} };
446
465
  });
447
466
  }
448
467
  async cleanRefreshBase(b, expectedBase) {
@@ -476,7 +495,18 @@ class WorkspaceAuthority {
476
495
  * clean workbench refresh; process/PTY liveness never gates synchronization. */
477
496
  async hydrate(identity, expectedBase) {
478
497
  const b = await this.bench(identity);
479
- if (b.config.rootProfile === "account") return { head: "", unchanged: true };
498
+ if (b.config.rootProfile === "account") {
499
+ if (!this.outerEnabled()) return { head: "", unchanged: true };
500
+ return this.synchronizeOuter(b.config.userId, expectedBase === void 0 ? { bootstrapOnly: true } : { requireHead: GitOid.parse(expectedBase) });
501
+ }
502
+ if (this.outerEnabled(b)) {
503
+ if (!b.state.initialized) {
504
+ await this.synchronizeOuter(b.config.userId, { bootstrapOnly: true });
505
+ await this.serial(b, () => this.hydrateLinkedIdle(b, identity));
506
+ }
507
+ if (expectedBase !== void 0) return this.synchronizeOuter(b.config.userId, { requireHead: GitOid.parse(expectedBase) });
508
+ return { head: b.state.head ?? "" };
509
+ }
480
510
  return this.serial(b, () => this.hydrateIdle(b, identity, expectedBase));
481
511
  }
482
512
  async hydrateIdle(b, identity, expectedBase) {
@@ -532,27 +562,7 @@ class WorkspaceAuthority {
532
562
  message: "Source synchronization interrupted; preserve workbench and inspect staged tree/retained originals before maintenance"
533
563
  };
534
564
  await this.save(b);
535
- const chunks = [];
536
- let offset = 0, snapshot = null, size = -1, hash = "";
537
- do {
538
- const chunk = await storage.read({
539
- method: "repository.bundle",
540
- repositoryId: b.config.repositoryId,
541
- snapshot,
542
- offset,
543
- limit: STORAGE_LIMITS.chunkBytes
544
- });
545
- const bytes = Buffer.from(chunk.data, "base64");
546
- if (chunk.data !== bytes.toString("base64") || bytes.length > STORAGE_LIMITS.chunkBytes || chunk.offset !== offset || chunk.nextOffset !== offset + bytes.length || !bytes.length || chunk.size > STORAGE_LIMITS.blobBytes || chunk.nextOffset > chunk.size || snapshot && (snapshot !== chunk.snapshot || size !== chunk.size || hash !== chunk.sha256))
547
- throw new WorkspaceError("invalid_bundle", "Chunk identity/size/offset changed; no checkout performed");
548
- snapshot = chunk.snapshot;
549
- size = chunk.size;
550
- hash = chunk.sha256;
551
- offset = chunk.nextOffset;
552
- chunks.push(bytes);
553
- } while (offset < size);
554
- const bundle = Buffer.concat(chunks);
555
- if (sha256(bundle) !== hash) throw new WorkspaceError("invalid_bundle", "Bundle SHA256 mismatch");
565
+ const bundle = await this.downloadBundle(storage, b.config.repositoryId);
556
566
  const file = path.join(b.directory, `${randomUUID()}.bundle`);
557
567
  await fs.writeFile(file, bundle, { mode: 384, flag: "wx" });
558
568
  await git(b.repo, ["bundle", "unbundle", file]);
@@ -776,9 +786,11 @@ class WorkspaceAuthority {
776
786
  b.state.initialized = true;
777
787
  b.state.blocked = null;
778
788
  await this.save(b);
779
- const result = await this.publishIdle(b, identity);
789
+ const result = await this.publishIdle(b, identity, this.linkedWorkbench(b) ? "Initialize project" : void 0, false, this.linkedWorkbench(b));
780
790
  if (this.linkedWorkbench(b)) {
781
791
  await fs.unlink(path.join(b.config.cwd, "README.md"));
792
+ b.state.mirroredHead = result.head;
793
+ await this.save(b);
782
794
  }
783
795
  await this.installGitPolicy(b, result.head);
784
796
  return result;
@@ -804,22 +816,7 @@ class WorkspaceAuthority {
804
816
  await git(b.config.cwd, ["reset", "--mixed", visibleHead]);
805
817
  }
806
818
  }
807
- const origin = this.githubOrigin(b);
808
- await git(b.repo, ["config", "--local", "--replace-all", "remote.origin.url", origin]);
809
- await git(b.repo, ["config", "--local", "--replace-all", "remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*"]);
810
- const localConfig = (await readRegular(path.join(b.repo, "config"), 128 * 1024)).toString("utf8");
811
- if (/^\[remote "canonical"\]\s*$/m.test(localConfig))
812
- await git(b.repo, ["config", "--local", "--remove-section", "remote.canonical"]);
813
- await git(b.repo, ["config", "--local", "--replace-all", `branch.${b.config.branch}.remote`, "origin"]);
814
- await git(b.repo, ["config", "--local", "--replace-all", `branch.${b.config.branch}.merge`, `refs/heads/${b.config.branch}`]);
815
- if (remoteTrackingHead)
816
- await git(b.repo, ["update-ref", `refs/remotes/origin/${b.config.branch}`, remoteTrackingHead]);
817
- await git(b.repo, ["config", "--local", "--replace-all", "push.default", "upstream"]);
818
- await git(b.repo, ["config", "--local", "--replace-all", "credential.helper", ""]);
819
- await git(b.repo, ["config", "--local", "--add", "credential.helper", GITHUB_CREDENTIAL_HELPER]);
820
- await git(b.repo, ["config", "--local", "--replace-all", "credential.useHttpPath", "false"]);
821
- await git(b.repo, ["config", "protocol.allow", "never"]);
822
- await git(b.repo, ["config", "protocol.https.allow", "always"]);
819
+ await this.configureLinkedRemote(b, remoteTrackingHead);
823
820
  return;
824
821
  }
825
822
  const destination = path.join(b.config.cwd, ".git");
@@ -848,6 +845,28 @@ class WorkspaceAuthority {
848
845
  await fs.writeFile(ref, `${head}
849
846
  `, { mode: 384 });
850
847
  }
848
+ /** This repository is also the common Git directory for the visible project
849
+ * worktrees. Keep their ordinary Git topology pointed at GitHub; mirroring is
850
+ * performed by WorkspaceAuthority directly and must never be exposed as the
851
+ * checkout's origin. */
852
+ async configureLinkedRemote(b, remoteTrackingHead = b.config.baseCommitHash) {
853
+ const origin = this.githubOrigin(b);
854
+ await git(b.repo, ["config", "--local", "--replace-all", "remote.origin.url", origin]);
855
+ await git(b.repo, ["config", "--local", "--replace-all", "remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*"]);
856
+ const localConfig = (await readRegular(path.join(b.repo, "config"), 128 * 1024)).toString("utf8");
857
+ if (/^\[remote "canonical"\]\s*$/m.test(localConfig))
858
+ await git(b.repo, ["config", "--local", "--remove-section", "remote.canonical"]);
859
+ await git(b.repo, ["config", "--local", "--replace-all", `branch.${b.config.branch}.remote`, "origin"]);
860
+ await git(b.repo, ["config", "--local", "--replace-all", `branch.${b.config.branch}.merge`, `refs/heads/${b.config.branch}`]);
861
+ if (remoteTrackingHead)
862
+ await git(b.repo, ["update-ref", `refs/remotes/origin/${b.config.branch}`, remoteTrackingHead]);
863
+ await git(b.repo, ["config", "--local", "--replace-all", "push.default", "upstream"]);
864
+ await git(b.repo, ["config", "--local", "--replace-all", "credential.helper", ""]);
865
+ await git(b.repo, ["config", "--local", "--add", "credential.helper", GITHUB_CREDENTIAL_HELPER]);
866
+ await git(b.repo, ["config", "--local", "--replace-all", "credential.useHttpPath", "false"]);
867
+ await git(b.repo, ["config", "protocol.allow", "never"]);
868
+ await git(b.repo, ["config", "protocol.https.allow", "always"]);
869
+ }
851
870
  /** Scoped receipt lookup never repeats a file effect; completion can clear its own crash marker. */
852
871
  async fileWriteResult(identity, input) {
853
872
  WorkspaceFileWriteLookup.parse({ method: "fileWriteResult", ...input });
@@ -1056,10 +1075,7 @@ class WorkspaceAuthority {
1056
1075
  const bytes = await readRegular(file, STORAGE_LIMITS.blobBytes), blobId = operationId;
1057
1076
  b.state.blocked = { code: "publication_unknown", operationId, commit: head, message: "Inspect the original import publication receipt" };
1058
1077
  await this.save(b);
1059
- for (let offset = 0; offset < bytes.length; offset += STORAGE_LIMITS.chunkBytes) {
1060
- const end = Math.min(bytes.length, offset + STORAGE_LIMITS.chunkBytes);
1061
- await storage.mutate({ method: "blob.append", operationId: `${operationId}-chunk-${offset}`, blobId, kind: "blob", offset, data: bytes.subarray(offset, end).toString("base64"), seal: end === bytes.length });
1062
- }
1078
+ await this.uploadBundle(storage, bytes, blobId, operationId);
1063
1079
  const result = await storage.mutate({ method: "repository.publish", operationId, repositoryId: b.config.repositoryId, branch: b.config.branch, expectedHead: null, commit: head, bundleId: blobId });
1064
1080
  if (result.head !== head) throw new WorkspaceError("invalid_receipt", "Import receipt does not match selected commit");
1065
1081
  if (this.linkedWorkbench(b)) await fs.rm(staged, { recursive: true });
@@ -1068,6 +1084,7 @@ class WorkspaceAuthority {
1068
1084
  b.state.initialized = true;
1069
1085
  b.state.head = head;
1070
1086
  b.state.blocked = null;
1087
+ b.state.mirroredHead = head;
1071
1088
  await this.save(b);
1072
1089
  return { head, workspaceHead: head };
1073
1090
  }
@@ -1075,6 +1092,10 @@ class WorkspaceAuthority {
1075
1092
  const b = await this.bench(identity);
1076
1093
  if (!input.message.trim() || input.message.length > 1e4) throw new WorkspaceError("invalid_input", "Commit message is required");
1077
1094
  return this.serial(b, () => this.productAction(b, input.id, { method: "commit", expectedHead: input.expectedHead, message: input.message }, async () => {
1095
+ if (this.outerEnabled(b)) {
1096
+ const result2 = await this.commitInnerIdle(b, identity, input.message);
1097
+ return { ...result2, treeHash: (await git(b.repo, ["rev-parse", `${result2.head}^{tree}`])).toString().trim() };
1098
+ }
1078
1099
  const result = await this.publishIdle(b, identity, input.message);
1079
1100
  if (this.linkedWorkbench(b)) {
1080
1101
  return { ...result, treeHash: (await git(b.repo, ["rev-parse", `${result.head}^{tree}`])).toString().trim() };
@@ -1088,22 +1109,24 @@ class WorkspaceAuthority {
1088
1109
  return { ...result, treeHash: (await git(b.repo, ["rev-parse", `${result.head}^{tree}`])).toString().trim() };
1089
1110
  }, async () => {
1090
1111
  await this.assertAvailable(b);
1091
- if (input.expectedHead !== void 0 && input.expectedHead !== b.state.head) throw new WorkspaceError("conflict", "Workbench head changed");
1112
+ if (input.expectedHead !== void 0 && !await this.headMatches(b, input.expectedHead)) throw new WorkspaceError("conflict", "Workbench head changed");
1092
1113
  }));
1093
1114
  }
1094
1115
  async push(identity, input) {
1095
1116
  const b = await this.bench(identity);
1096
1117
  this.validateGithubRemote(input.remote);
1097
1118
  return this.serial(b, () => this.productAction(b, input.id, { method: "push", expectedHead: input.expectedHead, url: input.remote.url, branch: input.remote.branch, expectedRemoteHead: input.remote.expectedHead }, async () => {
1119
+ const head = this.outerEnabled(b) ? await this.innerHead(b) : b.state.head;
1120
+ if (!head) throw new WorkspaceError("conflict", "The checkout has no commit to push");
1098
1121
  if (input.remote.expectedHead) {
1099
1122
  GitOid.parse(input.remote.expectedHead);
1100
- await git(b.repo, ["merge-base", "--is-ancestor", input.remote.expectedHead, b.state.head]);
1123
+ await git(b.repo, ["merge-base", "--is-ancestor", input.remote.expectedHead, head]);
1101
1124
  }
1102
- await git(b.repo, ["-c", "protocol.https.allow=always", "push", "--porcelain", ...input.remote.expectedHead !== void 0 ? [`--force-with-lease=refs/heads/${input.remote.branch}:${input.remote.expectedHead ?? ""}`] : [], "--", input.remote.url, `${b.state.head}:refs/heads/${input.remote.branch}`], void 0, void 0, { token: input.remote.token });
1103
- return { head: b.state.head, pushed: true };
1125
+ await git(b.repo, ["-c", "protocol.https.allow=always", "push", "--porcelain", ...input.remote.expectedHead !== void 0 ? [`--force-with-lease=refs/heads/${input.remote.branch}:${input.remote.expectedHead ?? ""}`] : [], "--", input.remote.url, `${head}:refs/heads/${input.remote.branch}`], void 0, void 0, { token: input.remote.token });
1126
+ return { head, pushed: true };
1104
1127
  }, async () => {
1105
1128
  await this.assertAvailable(b);
1106
- if (!b.state.head || input.expectedHead !== void 0 && input.expectedHead !== b.state.head) throw new WorkspaceError("conflict", "Workbench head changed");
1129
+ if (input.expectedHead !== void 0 && !await this.headMatches(b, input.expectedHead)) throw new WorkspaceError("conflict", "Workbench head changed");
1107
1130
  }));
1108
1131
  }
1109
1132
  async archiveBranch(identity, input) {
@@ -1136,8 +1159,11 @@ class WorkspaceAuthority {
1136
1159
  const receipt = await storage.read({ method: "operation.get", lookupId: b.state.blocked.operationId });
1137
1160
  if (receipt.state !== "completed" || b.state.blocked.commit && receipt.result?.head !== b.state.blocked.commit) throw new WorkspaceError("publication_unknown", "Reconcile the original publication before resetting");
1138
1161
  }
1139
- const canonical = await storage.read({ method: "repository.get", repositoryId: b.config.repositoryId, branch: b.config.branch });
1140
- if (!canonical.head) throw new WorkspaceError("empty_repository", "No canonical source exists to restore");
1162
+ const canonical = await storage.read({ method: "repository.get", repositoryId: b.config.repositoryId, branch: b.config.branch }).catch((error) => {
1163
+ if (this.outerEnabled(b) && error instanceof WorkspaceError && error.code === "not_found") return { head: null };
1164
+ throw error;
1165
+ });
1166
+ if (!canonical.head && !this.outerEnabled(b)) throw new WorkspaceError("empty_repository", "No canonical source exists to restore");
1141
1167
  const retained = path.join(b.directory, `reset-retained-${randomUUID()}`);
1142
1168
  await fs.mkdir(retained, { mode: 448 });
1143
1169
  await durableJson(path.join(retained, "recovery.json"), { workbench: b.config, previousState: b.state, resetId: input.id, targetHead: canonical.head });
@@ -1153,21 +1179,451 @@ class WorkspaceAuthority {
1153
1179
  b.state.initialized = false;
1154
1180
  b.state.head = null;
1155
1181
  b.state.blocked = null;
1182
+ b.state.mirroredHead = null;
1156
1183
  await this.save(b);
1157
- const result = await this.hydrateIdle(b, identity);
1184
+ const result = this.outerEnabled(b) ? await this.hydrateLinkedIdle(b, identity) : await this.hydrateIdle(b, identity);
1158
1185
  return { ...result, reset: true, retained: true };
1159
1186
  }));
1160
1187
  }
1188
+ // ---- Outer repository ---------------------------------------------------
1189
+ outerEnabled(b) {
1190
+ return !!this.options.accountStorage && (!b || b.config.rootProfile === "account" || this.linkedWorkbench(b));
1191
+ }
1192
+ outerStateFile() {
1193
+ return path.join(this.config.root, "state", "outer.json");
1194
+ }
1195
+ async outer(userId) {
1196
+ if (!this.options.accountStorage) throw new WorkspaceError("outer_unavailable", "This authority has no account storage");
1197
+ const workTree = this.config.workspaceRoot;
1198
+ if (!workTree) throw new WorkspaceError("invalid_config", "The outer repository requires a workspace root");
1199
+ if (!this.outerRepository)
1200
+ this.outerRepository = (async () => {
1201
+ const repo = await OuterRepository.open(path.join(this.config.root, "outer.git"), workTree);
1202
+ const stored = await readRegular(this.outerStateFile(), 1024 * 1024).catch((error) => {
1203
+ if (error.code === "ENOENT") return null;
1204
+ throw error;
1205
+ });
1206
+ const state = stored ? JSON.parse(stored.toString("utf8")) : { userId, initialized: false, publishedHead: null, head: null, blocked: null, conflict: null };
1207
+ if (typeof state.initialized !== "boolean" || !(state.head === null || GitOid.safeParse(state.head).success))
1208
+ throw new WorkspaceError("invalid_state", "Invalid durable outer repository state; maintenance required");
1209
+ if (!stored) await durableJson(this.outerStateFile(), state);
1210
+ return { repo, state };
1211
+ })();
1212
+ const outer = await this.outerRepository.catch((error) => {
1213
+ this.outerRepository = void 0;
1214
+ throw error;
1215
+ });
1216
+ if (outer.state.userId !== userId) throw new WorkspaceError("wrong_binding", "The outer repository belongs to another account");
1217
+ return outer;
1218
+ }
1219
+ saveOuter(state) {
1220
+ return durableJson(this.outerStateFile(), state);
1221
+ }
1222
+ async outerStatus(userId) {
1223
+ return structuredClone((await this.outer(userId)).state);
1224
+ }
1225
+ accountRepositoryId(userId) {
1226
+ return `user-workspace-${sha256(userId).slice(0, 40)}`;
1227
+ }
1228
+ provisionId(repositoryId) {
1229
+ return `provision-${sha256(repositoryId).slice(0, 48)}`;
1230
+ }
1231
+ async hasCommit(repo, commit) {
1232
+ return (await gitResult(repo, ["cat-file", "-e", `${GitOid.parse(commit)}^{commit}`])).code === 0;
1233
+ }
1234
+ async innerHead(b) {
1235
+ const { code, stdout } = await gitResult(b.config.cwd, ["rev-parse", "--verify", "--quiet", "HEAD"]);
1236
+ if (code === 1) return null;
1237
+ if (code !== 0) throw new WorkspaceError("unsafe_git", "Project checkout HEAD is unreadable");
1238
+ return GitOid.parse(stdout.toString("utf8").trim());
1239
+ }
1240
+ async headMatches(b, expected) {
1241
+ if (!this.outerEnabled(b)) return expected === b.state.head;
1242
+ return expected === b.state.mirroredHead || expected === await this.innerHead(b);
1243
+ }
1244
+ async innerTracked(b) {
1245
+ const head = await this.innerHead(b);
1246
+ if (!head) return /* @__PURE__ */ new Set();
1247
+ const listing = await git(b.repo, ["ls-tree", "-r", "--name-only", "-z", head]);
1248
+ return new Set(listing.toString("utf8").split("\0").filter(Boolean));
1249
+ }
1250
+ /** Platform snapshot commits from the per-project model sit on top of the
1251
+ * GitHub tip. Hydration peels them so a checkout's history is its own. */
1252
+ async platformSnapshot(repo, commit) {
1253
+ const header = (await git(repo, ["cat-file", "commit", commit])).toString("utf8").split("\n\n")[0] ?? "";
1254
+ const committer = /^committer .*<([^>]+)>/m.exec(header)?.[1];
1255
+ return committer !== void 0 && PLATFORM_COMMIT_EMAILS.includes(committer);
1256
+ }
1257
+ async firstParent(repo, commit) {
1258
+ const parents = (await git(repo, ["rev-list", "--parents", "-n", "1", commit])).toString("utf8").trim().split(/\s+/).slice(1);
1259
+ return parents[0] ? GitOid.parse(parents[0]) : null;
1260
+ }
1261
+ /** Every initialized project checkout beneath the workspace root, for the
1262
+ * outer walk and the measure. */
1263
+ async innerCheckouts(userId) {
1264
+ const workTree = this.config.workspaceRoot;
1265
+ const result = [];
1266
+ for (const b of this.benches.values()) {
1267
+ if (b.config.userId !== userId || !this.linkedWorkbench(b) || !b.state.initialized || b.state.blocked?.code === "archived") continue;
1268
+ const relative = path.relative(workTree, b.config.cwd);
1269
+ if (!relative || relative.startsWith("..") || path.isAbsolute(relative)) continue;
1270
+ if (!await fs.lstat(b.config.cwd).then((stat) => stat.isDirectory(), () => false)) continue;
1271
+ result.push({ bench: b, root: relative.split(path.sep).join("/"), tracked: () => this.innerTracked(b) });
1272
+ }
1273
+ return result;
1274
+ }
1275
+ /** The mirror's head for a branch, or null when it has none. Only a caller
1276
+ * that owns the repository's existence provisions it: a project repository
1277
+ * is provisioned by its seed or import under that action's own identity. */
1278
+ async remoteHead(storage, repositoryId, branch, provision = false) {
1279
+ try {
1280
+ return (await storage.read({ method: "repository.get", repositoryId, branch })).head;
1281
+ } catch (error) {
1282
+ if (!(error instanceof WorkspaceError) || error.code !== "not_found") throw error;
1283
+ if (provision) await storage.mutate({ method: "repository.provision", operationId: this.provisionId(repositoryId), repositoryId });
1284
+ return null;
1285
+ }
1286
+ }
1287
+ async downloadBundle(storage, repositoryId) {
1288
+ const chunks = [];
1289
+ let offset = 0, snapshot = null, size = -1, hash = "";
1290
+ do {
1291
+ const chunk = await storage.read({
1292
+ method: "repository.bundle",
1293
+ repositoryId,
1294
+ snapshot,
1295
+ offset,
1296
+ limit: STORAGE_LIMITS.chunkBytes
1297
+ });
1298
+ const bytes = Buffer.from(chunk.data, "base64");
1299
+ if (chunk.data !== bytes.toString("base64") || bytes.length > STORAGE_LIMITS.chunkBytes || chunk.offset !== offset || chunk.nextOffset !== offset + bytes.length || !bytes.length || chunk.size > STORAGE_LIMITS.blobBytes || chunk.nextOffset > chunk.size || snapshot && (snapshot !== chunk.snapshot || size !== chunk.size || hash !== chunk.sha256))
1300
+ throw new WorkspaceError("invalid_bundle", "Chunk identity/size/offset changed; no checkout performed");
1301
+ snapshot = chunk.snapshot;
1302
+ size = chunk.size;
1303
+ hash = chunk.sha256;
1304
+ offset = chunk.nextOffset;
1305
+ chunks.push(bytes);
1306
+ } while (offset < size);
1307
+ const bundle = Buffer.concat(chunks);
1308
+ if (sha256(bundle) !== hash) throw new WorkspaceError("invalid_bundle", "Bundle SHA256 mismatch");
1309
+ return bundle;
1310
+ }
1311
+ async uploadBundle(storage, bytes, blobId, operationId) {
1312
+ for (let offset = 0; offset < bytes.length; offset += STORAGE_LIMITS.chunkBytes) {
1313
+ const end = Math.min(bytes.length, offset + STORAGE_LIMITS.chunkBytes);
1314
+ await storage.mutate({
1315
+ method: "blob.append",
1316
+ operationId: `${operationId}-chunk-${offset}`,
1317
+ blobId,
1318
+ kind: "blob",
1319
+ offset,
1320
+ data: bytes.subarray(offset, end).toString("base64"),
1321
+ seal: end === bytes.length
1322
+ });
1323
+ }
1324
+ }
1325
+ async unbundleInto(b, bytes) {
1326
+ const file = path.join(b.directory, `${randomUUID()}.bundle`);
1327
+ await fs.writeFile(file, bytes, { mode: 384, flag: "wx" });
1328
+ try {
1329
+ await git(b.repo, ["bundle", "unbundle", file]);
1330
+ } finally {
1331
+ await fs.rm(file, { force: true });
1332
+ }
1333
+ }
1334
+ async forcePublishSupported(storage) {
1335
+ const hello = await storage.read({ method: "hello" });
1336
+ return hello.capabilities?.includes("storage-force-publish-v1") === true;
1337
+ }
1338
+ /** One synchronization cycle of the outer repository: snapshot the workspace,
1339
+ * integrate what the mirror gained, publish what changed. Serialized on its
1340
+ * own queue; project checkouts stay ordinary concurrent writers whose later
1341
+ * edits the next cycle observes. */
1342
+ async synchronizeOuter(userId, options = {}) {
1343
+ return this.serialKey("outer", () => this.synchronizeOuterIdle(userId, options));
1344
+ }
1345
+ async synchronizeOuterIdle(userId, options) {
1346
+ await this.owned();
1347
+ const { repo, state } = await this.outer(userId);
1348
+ const storage = await this.options.accountStorage(userId);
1349
+ const repositoryId = this.accountRepositoryId(userId);
1350
+ if (state.blocked?.code === "publication_unknown") {
1351
+ const { operationId: operationId2, commit } = state.blocked;
1352
+ const receipt = await storage.read({ method: "operation.get", lookupId: operationId2 }).catch((error) => {
1353
+ if (error instanceof WorkspaceError && error.code === "not_found") return null;
1354
+ throw error;
1355
+ });
1356
+ if (receipt?.state === "completed" && receipt.result?.head !== commit)
1357
+ throw new WorkspaceError("invalid_state", "Workspace publication receipt names another head; maintenance required");
1358
+ const published = receipt?.state === "completed" || await this.remoteHead(storage, repositoryId, OUTER_BRANCH) === commit;
1359
+ if (published) {
1360
+ state.publishedHead = commit;
1361
+ state.head = commit;
1362
+ }
1363
+ state.blocked = null;
1364
+ await this.saveOuter(state);
1365
+ }
1366
+ if (!state.initialized) {
1367
+ const remote2 = await this.remoteHead(storage, repositoryId, OUTER_BRANCH, true);
1368
+ if (remote2) {
1369
+ if (!await repo.has(remote2)) await repo.unbundle(await this.downloadBundle(storage, repositoryId));
1370
+ if (!await repo.isLegacyBootstrap(remote2)) await repo.checkout(remote2);
1371
+ await repo.setHead(remote2);
1372
+ }
1373
+ state.initialized = true;
1374
+ state.publishedHead = remote2;
1375
+ state.head = remote2;
1376
+ await this.saveOuter(state);
1377
+ if (options.bootstrapOnly) return { head: remote2, unchanged: true };
1378
+ } else if (options.bootstrapOnly) return { head: state.head, unchanged: true };
1379
+ if (state.conflict && !options.resolveConflict)
1380
+ throw new OuterSnapshotRefusal(OUTER_CONFLICT_CODE, "Workspace synchronization conflict awaits resolution", state.conflict.paths);
1381
+ const inners = await this.innerCheckouts(userId);
1382
+ let snapshot;
1383
+ try {
1384
+ snapshot = await repo.snapshot(inners, { allowLargeDiff: options.allowLargeDiff });
1385
+ } catch (error) {
1386
+ if (error instanceof OuterSnapshotRefusal) {
1387
+ state.blocked = { code: error.code, message: error.message, paths: error.paths };
1388
+ await this.saveOuter(state);
1389
+ }
1390
+ throw error;
1391
+ }
1392
+ if (state.conflict) {
1393
+ const marker = /^(<{7}|={7}|>{7})( |$)/m;
1394
+ for (const file of state.conflict.paths) {
1395
+ const bytes2 = await readRegular(path.join(repo.workTree, file)).catch((error) => {
1396
+ if (error.code === "ENOENT" || error.code === "ENOTDIR") return null;
1397
+ throw error;
1398
+ });
1399
+ if (bytes2 && marker.test(bytes2.toString("utf8")))
1400
+ throw new OuterSnapshotRefusal(OUTER_CONFLICT_CODE, "Conflict markers remain; resolve them before confirming", [file]);
1401
+ }
1402
+ } else if (state.blocked && state.blocked.code !== "publication_unknown") {
1403
+ state.blocked = null;
1404
+ await this.saveOuter(state);
1405
+ }
1406
+ const base = state.publishedHead;
1407
+ const baseTree = base ? await repo.treeOf(base) : await repo.emptyTree();
1408
+ let local;
1409
+ if (state.conflict) {
1410
+ local = await repo.commit(snapshot.tree, [state.conflict.ours, state.conflict.theirs], "Resolve workspace synchronization conflict");
1411
+ state.conflict = null;
1412
+ state.blocked = null;
1413
+ } else if (base && snapshot.tree === baseTree) local = base;
1414
+ else local = await repo.commit(snapshot.tree, base ? [base] : [], "Workspace snapshot");
1415
+ if (state.head !== local) {
1416
+ state.head = local;
1417
+ await repo.setHead(local);
1418
+ await this.saveOuter(state);
1419
+ }
1420
+ const integrated = async (head) => {
1421
+ if (options.requireHead && !await repo.isAncestor(options.requireHead, head))
1422
+ throw new WorkspaceError("conflict", "The required workspace head is not integrated; retry the transfer");
1423
+ return options.requireHead ? { integrated: options.requireHead } : {};
1424
+ };
1425
+ const remote = await this.remoteHead(storage, repositoryId, OUTER_BRANCH, true);
1426
+ let currentTree = snapshot.tree;
1427
+ if (remote && remote !== base) {
1428
+ if (!await repo.has(remote)) await repo.unbundle(await this.downloadBundle(storage, repositoryId));
1429
+ if (local === base) {
1430
+ await repo.apply(currentTree, await repo.treeOf(remote));
1431
+ state.publishedHead = remote;
1432
+ state.head = remote;
1433
+ await repo.setHead(remote);
1434
+ await this.saveOuter(state);
1435
+ return { head: remote, unchanged: false, ...await integrated(remote) };
1436
+ }
1437
+ const merge = await repo.merge(local, remote);
1438
+ if (merge.conflicts.length) {
1439
+ await repo.apply(currentTree, merge.tree);
1440
+ state.conflict = { ours: local, theirs: remote, tree: merge.tree, paths: merge.conflicts };
1441
+ state.blocked = { code: OUTER_CONFLICT_CODE, message: "The workspace diverged from another worker; conflict markers were written to the paths named", paths: merge.conflicts };
1442
+ await this.saveOuter(state);
1443
+ throw new OuterSnapshotRefusal(OUTER_CONFLICT_CODE, state.blocked.message, merge.conflicts);
1444
+ }
1445
+ await repo.apply(currentTree, merge.tree);
1446
+ currentTree = merge.tree;
1447
+ local = await repo.commit(merge.tree, [local, remote], "Merge workspace");
1448
+ state.head = local;
1449
+ await repo.setHead(local);
1450
+ await this.saveOuter(state);
1451
+ }
1452
+ if (local === remote) {
1453
+ state.publishedHead = local;
1454
+ await this.saveOuter(state);
1455
+ return { head: local, unchanged: true, ...await integrated(local) };
1456
+ }
1457
+ const operationId = `ws-${randomUUID()}`, blobId = `ws-${randomUUID()}`;
1458
+ const bytes = await repo.bundle(remote && await repo.has(remote) ? remote : null);
1459
+ state.blocked = { code: "publication_unknown", operationId, commit: local, message: "Workspace publication is in progress/unknown. Inspect the original storage operation; never retry under a new ID." };
1460
+ await this.saveOuter(state);
1461
+ try {
1462
+ await this.uploadBundle(storage, bytes, blobId, operationId);
1463
+ const result = await storage.mutate({
1464
+ method: "repository.publish",
1465
+ operationId,
1466
+ repositoryId,
1467
+ branch: OUTER_BRANCH,
1468
+ expectedHead: remote,
1469
+ commit: local,
1470
+ bundleId: blobId
1471
+ });
1472
+ if (result.head !== local) throw new WorkspaceError("invalid_response", "Workspace publication receipt head mismatch; inspect original operation");
1473
+ } catch (error) {
1474
+ if (error instanceof WorkspaceError && error.rejectedBeforeAdmission) {
1475
+ state.blocked = null;
1476
+ await this.saveOuter(state);
1477
+ throw error.code === "conflict" ? new WorkspaceError("mirror_advanced", "The workspace mirror advanced during publication; retried next cycle", true) : error;
1478
+ }
1479
+ throw error;
1480
+ }
1481
+ state.publishedHead = local;
1482
+ state.blocked = null;
1483
+ await this.saveOuter(state);
1484
+ return { head: local, unchanged: false, ...await integrated(local) };
1485
+ }
1486
+ /** Push a project checkout's own HEAD to its mirror. Last push wins: no merge
1487
+ * is attempted, and a rewind or rewrite replaces the mirror as readily as a
1488
+ * fast-forward. A lost acknowledgement needs no reconciliation because the
1489
+ * next cycle simply observes the mirror already holds the head. */
1490
+ async mirrorInnerIdle(b, identity) {
1491
+ if (!b.state.initialized || !this.linkedWorkbench(b) || b.state.blocked?.code === "archived") return { head: b.state.head, unchanged: true };
1492
+ const head = await this.innerHead(b);
1493
+ if (!head || head === b.state.mirroredHead) return { head, unchanged: true };
1494
+ const storage = await this.storage(b, identity);
1495
+ const remote = await this.remoteHead(storage, b.config.repositoryId, b.config.branch, true);
1496
+ if (remote !== head) {
1497
+ const ref = `refs/r5d/mirror/${b.config.branch}`;
1498
+ await git(b.repo, ["update-ref", ref, head]);
1499
+ const file = path.join(b.directory, `mirror-${randomUUID()}.bundle`);
1500
+ const known = remote !== null && await this.hasCommit(b.repo, remote);
1501
+ const rewound = known && (await gitResult(b.repo, ["merge-base", "--is-ancestor", head, remote])).code === 0;
1502
+ const exclude = known && !rewound ? [`^${remote}`] : (await gitResult(b.repo, ["rev-parse", "--verify", "--quiet", `${head}~1`])).code === 0 ? [`^${head}~1`] : [];
1503
+ await git(b.repo, ["bundle", "create", file, ref, ...exclude]);
1504
+ const bytes = await readRegular(file, STORAGE_LIMITS.blobBytes);
1505
+ await fs.rm(file, { force: true });
1506
+ const operationId = `mirror-${randomUUID()}`;
1507
+ const force = await this.forcePublishSupported(storage);
1508
+ try {
1509
+ await this.uploadBundle(storage, bytes, operationId, operationId);
1510
+ const result = await storage.mutate({
1511
+ method: "repository.publish",
1512
+ operationId,
1513
+ repositoryId: b.config.repositoryId,
1514
+ branch: b.config.branch,
1515
+ expectedHead: remote,
1516
+ commit: head,
1517
+ bundleId: operationId,
1518
+ ...force ? { force: true } : {}
1519
+ });
1520
+ if (result.head !== head) throw new WorkspaceError("invalid_response", "Mirror receipt head mismatch");
1521
+ } catch (error) {
1522
+ if (error instanceof WorkspaceError && error.rejectedBeforeAdmission) return { head, unchanged: true };
1523
+ throw error;
1524
+ }
1525
+ }
1526
+ b.state.mirroredHead = head;
1527
+ b.state.head = head;
1528
+ await this.save(b);
1529
+ return { head, unchanged: false };
1530
+ }
1531
+ /** Mirror one project checkout now, outside the periodic cycle. */
1532
+ async mirror(identity) {
1533
+ const b = await this.bench(identity);
1534
+ if (!this.outerEnabled(b) || b.config.rootProfile === "account") return { head: b.state.head, unchanged: true };
1535
+ return this.serial(b, () => this.mirrorInnerIdle(b, identity));
1536
+ }
1537
+ /** Commit the checkout's working tree to its own history on the user's behalf. */
1538
+ async commitInnerIdle(b, identity, message) {
1539
+ if (!b.state.initialized) throw new WorkspaceError("not_initialized", "Hydrate first");
1540
+ await git(b.config.cwd, ["add", "-A"]);
1541
+ const dirty = (await git(b.config.cwd, ["status", "--porcelain", "-z"])).length > 0;
1542
+ const before = await this.innerHead(b);
1543
+ if (!dirty && before) return { head: before, unchanged: true };
1544
+ await git(b.config.cwd, ["commit", "--quiet", "--allow-empty", "-m", message], void 0, void 0, void 0, { env: PROJECT_COMMIT_IDENTITY });
1545
+ const head = await this.innerHead(b);
1546
+ await this.mirrorInnerIdle(b, identity);
1547
+ return { head };
1548
+ }
1549
+ /** Install a project checkout from its mirror. Files may already be present
1550
+ * because the outer repository delivered them first; the worktree is then
1551
+ * created around them and they show as ordinary dirty content. */
1552
+ async hydrateLinkedIdle(b, identity) {
1553
+ await this.assertAvailable(b);
1554
+ if (b.state.initialized) return { head: b.state.head ?? "" };
1555
+ const storage = await this.storage(b, identity);
1556
+ const mirror = await this.remoteHead(storage, b.config.repositoryId, b.config.branch);
1557
+ if (mirror && !await this.hasCommit(b.repo, mirror)) await this.unbundleInto(b, await this.downloadBundle(storage, b.config.repositoryId));
1558
+ let visible = mirror;
1559
+ while (visible && await this.platformSnapshot(b.repo, visible)) {
1560
+ const parent = await this.firstParent(b.repo, visible);
1561
+ if (!parent) break;
1562
+ visible = parent;
1563
+ }
1564
+ if (!visible && b.config.baseCommitHash && await this.hasCommit(b.repo, b.config.baseCommitHash)) visible = b.config.baseCommitHash;
1565
+ if (!visible) throw new WorkspaceError("empty_repository", "Seed README explicitly for an empty mirrored branch");
1566
+ b.state.blocked = { code: "hydration_incomplete", message: "Checkout installation interrupted; preserve the checkout and inspect before maintenance" };
1567
+ await this.save(b);
1568
+ await this.installLinkedWorktree(b, visible, mirror && visible !== mirror ? mirror : null);
1569
+ await this.configureLinkedRemote(b);
1570
+ b.state.initialized = true;
1571
+ b.state.head = mirror ?? visible;
1572
+ b.state.mirroredHead = mirror;
1573
+ b.state.blocked = null;
1574
+ delete b.state.publishedMetadata;
1575
+ await this.save(b);
1576
+ return { head: b.state.head ?? "" };
1577
+ }
1578
+ async installLinkedWorktree(b, visible, legacySnapshot) {
1579
+ const destination = path.join(b.config.cwd, ".git");
1580
+ if (await fs.lstat(destination).then(() => true, (error) => {
1581
+ if (error.code === "ENOENT") return false;
1582
+ throw error;
1583
+ })) return;
1584
+ await fs.mkdir(b.config.cwd, { recursive: true, mode: 448 });
1585
+ await noSymlinkAncestors(b.config.cwd);
1586
+ await git(b.repo, ["update-ref", `refs/heads/${b.config.branch}`, visible]);
1587
+ if (!(await fs.readdir(b.config.cwd)).length) {
1588
+ await fs.rmdir(b.config.cwd);
1589
+ await git(b.repo, ["worktree", "add", "--force", b.config.cwd, b.config.branch]);
1590
+ if (legacySnapshot) {
1591
+ await git(b.config.cwd, ["reset", "--hard", legacySnapshot]);
1592
+ await git(b.config.cwd, ["reset", "--mixed", visible]);
1593
+ }
1594
+ return;
1595
+ }
1596
+ const staging = path.join(b.directory, `worktree-${randomUUID()}`);
1597
+ await git(b.repo, ["worktree", "add", "--no-checkout", "--force", staging, b.config.branch]);
1598
+ const pointer = /^gitdir: (.+?)\s*$/.exec((await readRegular(path.join(staging, ".git"), 4096)).toString("utf8"));
1599
+ if (!pointer || !path.isAbsolute(pointer[1])) throw new WorkspaceError("unsafe_git", "Invalid linked worktree pointer");
1600
+ const gitDirectory = path.normalize(pointer[1]);
1601
+ if (!gitDirectory.startsWith(path.join(b.repo, "worktrees") + path.sep)) throw new WorkspaceError("unsafe_git", "Linked worktree belongs to another repository");
1602
+ await fs.writeFile(destination, `gitdir: ${gitDirectory}
1603
+ `, { mode: 384, flag: "wx" });
1604
+ await fs.writeFile(path.join(gitDirectory, "gitdir"), `${destination}
1605
+ `, { mode: 384 });
1606
+ await fs.rm(staging, { recursive: true });
1607
+ await git(b.config.cwd, ["reset", "--mixed", visible]);
1608
+ }
1161
1609
  async publish(identity, options = {}) {
1162
1610
  const b = await this.bench(identity);
1163
- if (b.config.rootProfile === "account") return { head: "", unchanged: true };
1611
+ if (b.config.rootProfile === "account") {
1612
+ if (!this.outerEnabled()) return { head: "", unchanged: true };
1613
+ return this.synchronizeOuter(b.config.userId, { allowLargeDiff: options.allowLargeDiff, resolveConflict: options.allowBlockedConflict });
1614
+ }
1615
+ if (this.outerEnabled(b)) {
1616
+ const outer = await this.synchronizeOuter(b.config.userId);
1617
+ await this.serial(b, () => this.mirrorInnerIdle(b, identity));
1618
+ return outer;
1619
+ }
1164
1620
  return this.serial(b, async () => {
1165
1621
  const conflictBlocked = !!b.state.blocked && WORKBENCH_CONFLICT_CODES.has(b.state.blocked.code);
1166
1622
  await this.assertAvailable(b, options.allowBlockedConflict === true && conflictBlocked);
1167
1623
  return this.publishIdle(b, identity, "Destination workspace snapshot", options.allowLargeDiff === true);
1168
1624
  });
1169
1625
  }
1170
- async publishIdle(b, identity, message = "Destination workspace snapshot", allowLargeDiff = false) {
1626
+ async publishIdle(b, identity, message = "Destination workspace snapshot", allowLargeDiff = false, projectIdentity = false) {
1171
1627
  if (!b.state.initialized) throw new WorkspaceError("not_initialized", "Hydrate or explicitly seed first");
1172
1628
  const storage = await this.storage(b, identity);
1173
1629
  const latest = await storage.read({
@@ -1200,7 +1656,7 @@ class WorkspaceAuthority {
1200
1656
  throw new WorkspaceError("too_large", "Source diff exceeds the 5242880-byte automatic publication limit");
1201
1657
  }
1202
1658
  const commit = (await git(b.repo, ["commit-tree", tree, ...b.state.head ? ["-p", b.state.head] : []], `${message}
1203
- `)).toString().trim();
1659
+ `, void 0, void 0, projectIdentity ? { env: PROJECT_COMMIT_IDENTITY } : {})).toString().trim();
1204
1660
  await git(b.repo, ["update-ref", this.canonicalRef(b), commit]);
1205
1661
  const bundleFile = path.join(b.directory, `${randomUUID()}.bundle`);
1206
1662
  await git(b.repo, ["bundle", "create", bundleFile, this.canonicalRef(b)]);
@@ -1234,18 +1690,7 @@ class WorkspaceAuthority {
1234
1690
  message: "Publication attempt is in progress/unknown. Inspect original storage operation; NEVER retry under a new ID. Workbench and prepared commit retained."
1235
1691
  };
1236
1692
  await this.save(b);
1237
- for (let offset = 0; offset < bytes.length; offset += STORAGE_LIMITS.chunkBytes) {
1238
- const end = Math.min(bytes.length, offset + STORAGE_LIMITS.chunkBytes);
1239
- await storage.mutate({
1240
- method: "blob.append",
1241
- operationId: `${operationId}-chunk-${offset}`,
1242
- blobId,
1243
- kind: "blob",
1244
- offset,
1245
- data: bytes.subarray(offset, end).toString("base64"),
1246
- seal: end === bytes.length
1247
- });
1248
- }
1693
+ await this.uploadBundle(storage, bytes, blobId, operationId);
1249
1694
  const result = await storage.mutate({
1250
1695
  method: "repository.publish",
1251
1696
  operationId,