@indigoai-us/hq-cloud 6.15.16 → 6.15.18

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.
@@ -0,0 +1,315 @@
1
+ /**
2
+ * Regression test for `hq rescue` clobbering root-level ignore files.
3
+ *
4
+ * The bug: `.gitignore` / `.hqignore` (and friends) are release-shipped, so the
5
+ * generic USER-EDIT classifier moved a locally-tuned copy into `personal/` as a
6
+ * `.drift-<ts>-<pid>` archive and let the overlay lay the release copy down. On
7
+ * a real HQ root that silently dropped the operator's exclusion rules: the git
8
+ * mirror started walking a 62 GB `workspace/` again (killed at its 120s
9
+ * timeout, every pass), and the sync engine walked far more than intended until
10
+ * its 15-minute STS credentials expired mid-run — surfacing as a red
11
+ * "Sync failed" in the desktop app.
12
+ *
13
+ * These files are machine-local tuning, not scaffold: a rescue must never
14
+ * overwrite an edited one. The fix classifies an edited root ignore file as
15
+ * KEEP-LOCAL — left untouched on disk and excluded from the overlay — while an
16
+ * unedited one still tracks the release, and every other user-edited file is
17
+ * still rescued into `personal/` exactly as before.
18
+ *
19
+ * Runs the real (non-dry-run) rescue so the assertions are about bytes on disk,
20
+ * not just the classifier's log line. The rescue clones its source from GitHub,
21
+ * so we shim `git clone` to clone a local fixture repo instead.
22
+ */
23
+ import { describe, it, expect, beforeAll, afterAll } from "vitest";
24
+ import { execFileSync } from "child_process";
25
+ import * as fs from "fs";
26
+ import * as os from "os";
27
+ import * as path from "path";
28
+ import { runRescue } from "./rescue-core.js";
29
+ function has(bin, ...args) {
30
+ try {
31
+ execFileSync(bin, args, { stdio: "ignore" });
32
+ return true;
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ // Needs git (fixture + clone) and rsync (overlay).
39
+ const toolsAvailable = has("git", "--version") && has("rsync", "--version");
40
+ /**
41
+ * Env for a fixture run. `GH_TOKEN`/`GITHUB_TOKEN` are stripped on purpose: with
42
+ * one set, the rescue clones `https://x-access-token:<token>@github.com/...`,
43
+ * which the `https://github.com/*` shim pattern does not rewrite — the test
44
+ * would then leave its fixture and attempt a real authenticated network clone.
45
+ */
46
+ function fixtureEnv(shimDir) {
47
+ const env = {
48
+ ...process.env,
49
+ PATH: `${shimDir}:${process.env.PATH ?? ""}`,
50
+ };
51
+ delete env.GH_TOKEN;
52
+ delete env.GITHUB_TOKEN;
53
+ return env;
54
+ }
55
+ /** Run the rescue in-process, capturing its stdout/stderr. */
56
+ function runRescueCapture(argv, env) {
57
+ let stdout = "";
58
+ let stderr = "";
59
+ const origOut = process.stdout.write.bind(process.stdout);
60
+ const origErr = process.stderr.write.bind(process.stderr);
61
+ process.stdout.write = ((chunk) => {
62
+ stdout += String(chunk);
63
+ return true;
64
+ });
65
+ process.stderr.write = ((chunk) => {
66
+ stderr += String(chunk);
67
+ return true;
68
+ });
69
+ let status;
70
+ try {
71
+ status = runRescue(argv, { env }).status;
72
+ }
73
+ finally {
74
+ process.stdout.write = origOut;
75
+ process.stderr.write = origErr;
76
+ }
77
+ return { status, stdout, stderr };
78
+ }
79
+ describe.skipIf(!toolsAvailable)("rescue keeps locally-edited root ignore files", () => {
80
+ let workDir;
81
+ let upstream;
82
+ let hqRoot;
83
+ let shimDir;
84
+ let floorSha;
85
+ let out = "";
86
+ const git = (cwd, ...args) => execFileSync("git", args, {
87
+ cwd,
88
+ stdio: ["ignore", "pipe", "pipe"],
89
+ env: {
90
+ ...process.env,
91
+ GIT_AUTHOR_NAME: "t",
92
+ GIT_AUTHOR_EMAIL: "t@t",
93
+ GIT_COMMITTER_NAME: "t",
94
+ GIT_COMMITTER_EMAIL: "t@t",
95
+ },
96
+ })
97
+ .toString()
98
+ .trim();
99
+ const read = (rel) => fs.readFileSync(path.join(hqRoot, rel), "utf-8");
100
+ beforeAll(() => {
101
+ workDir = fs.mkdtempSync(path.join(os.tmpdir(), "hq-rescue-ignore-"));
102
+ // --- upstream: floor commit, then a HEAD that advances every ignore file --
103
+ upstream = path.join(workDir, "upstream");
104
+ fs.mkdirSync(path.join(upstream, "core/docs"), { recursive: true });
105
+ git(workDir, "init", "-b", "main", "upstream");
106
+ fs.writeFileSync(path.join(upstream, ".gitignore"), "release-git\n");
107
+ fs.writeFileSync(path.join(upstream, ".hqignore"), "release-hq\n");
108
+ fs.writeFileSync(path.join(upstream, ".claudeignore"), "release-claude\n");
109
+ fs.writeFileSync(path.join(upstream, ".hqinclude"), "release-include\n");
110
+ fs.writeFileSync(path.join(upstream, "core/docs/.gitignore"), "release-nested\n");
111
+ fs.writeFileSync(path.join(upstream, "core/edited.md"), "base\n");
112
+ git(upstream, "add", "-A");
113
+ git(upstream, "commit", "-m", "floor");
114
+ floorSha = git(upstream, "rev-parse", "HEAD");
115
+ // HEAD moves all four ignore files on, so "release wins" is observable.
116
+ fs.writeFileSync(path.join(upstream, ".gitignore"), "release-git\nv2\n");
117
+ fs.writeFileSync(path.join(upstream, ".hqignore"), "release-hq\nv2\n");
118
+ fs.writeFileSync(path.join(upstream, ".claudeignore"), "release-claude\nv2\n");
119
+ fs.writeFileSync(path.join(upstream, ".hqinclude"), "release-include\nv2\n");
120
+ fs.writeFileSync(path.join(upstream, "core/docs/.gitignore"), "release-nested\nv2\n");
121
+ git(upstream, "add", "-A");
122
+ git(upstream, "commit", "-m", "head");
123
+ // --- the local HQ root being rescued ------------------------------------
124
+ hqRoot = path.join(workDir, "hq");
125
+ fs.mkdirSync(path.join(hqRoot, "core/docs"), { recursive: true });
126
+ // `companies/` + `personal/` make it look like an HQ root (script guard).
127
+ fs.mkdirSync(path.join(hqRoot, "personal"), { recursive: true });
128
+ fs.mkdirSync(path.join(hqRoot, "companies"), { recursive: true });
129
+ // Root ignore files the operator tuned: differ from BOTH floor and HEAD.
130
+ // These are the regression — they must survive byte-for-byte.
131
+ fs.writeFileSync(path.join(hqRoot, ".gitignore"), "release-git\n/workspace/\n");
132
+ fs.writeFileSync(path.join(hqRoot, ".hqignore"), "release-hq\n*.mp4\n");
133
+ // Untouched root ignore file (matches floor): still tracks the release.
134
+ fs.writeFileSync(path.join(hqRoot, ".claudeignore"), "release-claude\n");
135
+ // A NESTED .gitignore is scaffold, not machine-local tuning: still rescued.
136
+ fs.writeFileSync(path.join(hqRoot, "core/docs/.gitignore"), "release-nested\nMINE\n");
137
+ // A root ignore file managed through a symlink (dotfiles repo): the
138
+ // generic top-level-symlink arm used to `skip` it, after which `rsync -a`
139
+ // replaced the receiver symlink with the release's regular file.
140
+ fs.writeFileSync(path.join(hqRoot, "personal/my-hqinclude"), "from-dotfiles\n");
141
+ fs.symlinkSync("personal/my-hqinclude", path.join(hqRoot, ".hqinclude"));
142
+ // Control: an ordinary user-edited file is still rescued into personal/.
143
+ fs.writeFileSync(path.join(hqRoot, "core/edited.md"), "MINE\n");
144
+ // --- git shim: rewrite `git clone <github-url> dest` to the fixture ------
145
+ const realGit = execFileSync("bash", ["-lc", "command -v git"]).toString().trim() ||
146
+ "/usr/bin/git";
147
+ shimDir = path.join(workDir, "shim");
148
+ fs.mkdirSync(shimDir, { recursive: true });
149
+ const shim = `#!/usr/bin/env bash
150
+ if [ "$1" = "clone" ]; then
151
+ args=()
152
+ for a in "$@"; do
153
+ case "$a" in
154
+ https://github.com/*) a=${JSON.stringify(upstream)} ;;
155
+ esac
156
+ args+=("$a")
157
+ done
158
+ exec ${JSON.stringify(realGit)} "\${args[@]}"
159
+ fi
160
+ exec ${JSON.stringify(realGit)} "$@"
161
+ `;
162
+ fs.writeFileSync(path.join(shimDir, "git"), shim, { mode: 0o755 });
163
+ const env = fixtureEnv(shimDir);
164
+ // --- run the real rescue (non-dry-run) ----------------------------------
165
+ const r = runRescueCapture([
166
+ "--hq-root",
167
+ hqRoot,
168
+ "--source",
169
+ "test/repo",
170
+ "--ref",
171
+ "main",
172
+ "--floor-sha",
173
+ floorSha,
174
+ "--yes",
175
+ "--no-backup",
176
+ ], env);
177
+ out = `${r.stdout}\n${r.stderr}`;
178
+ if (r.status !== 0)
179
+ throw new Error(`rescue failed (${r.status}):\n${out}`);
180
+ });
181
+ afterAll(() => {
182
+ if (workDir)
183
+ fs.rmSync(workDir, { recursive: true, force: true });
184
+ });
185
+ it("ran in history_floor mode against our floor", () => {
186
+ expect(out).toContain(`Baseline: ${floorSha}`);
187
+ });
188
+ it("leaves an edited root .gitignore byte-for-byte intact (the regression)", () => {
189
+ expect(read(".gitignore")).toBe("release-git\n/workspace/\n");
190
+ });
191
+ it("leaves an edited root .hqignore byte-for-byte intact (the regression)", () => {
192
+ expect(read(".hqignore")).toBe("release-hq\n*.mp4\n");
193
+ });
194
+ it("does not archive edited root ignore files into personal/", () => {
195
+ const litter = fs
196
+ .readdirSync(path.join(hqRoot, "personal"))
197
+ .filter((n) => n.startsWith(".gitignore") || n.startsWith(".hqignore"));
198
+ expect(litter, `unexpected personal/ archive: ${litter.join(", ")}`).toEqual([]);
199
+ });
200
+ it("reports edited root ignore files as keep-local, not rescue", () => {
201
+ expect(out).toContain("kept local: .gitignore");
202
+ expect(out).toContain("kept local: .hqignore");
203
+ expect(out).not.toMatch(/rescued: \.gitignore/);
204
+ expect(out).not.toMatch(/rescued: \.hqignore/);
205
+ expect(out).toMatch(/user-edit\s+\(kept local\):\s+3 files/);
206
+ expect(out).toMatch(/kept-local: 3/);
207
+ });
208
+ it("preserves a root ignore file managed as a symlink", () => {
209
+ const p = path.join(hqRoot, ".hqinclude");
210
+ expect(fs.lstatSync(p).isSymbolicLink(), ".hqinclude is no longer a symlink").toBe(true);
211
+ expect(fs.readlinkSync(p)).toBe("personal/my-hqinclude");
212
+ expect(fs.readFileSync(p, "utf-8")).toBe("from-dotfiles\n");
213
+ expect(out).toContain("kept local: .hqinclude");
214
+ });
215
+ it("still ships release updates for an UNEDITED root ignore file", () => {
216
+ expect(read(".claudeignore")).toBe("release-claude\nv2\n");
217
+ });
218
+ it("still rescues a user-edited NESTED .gitignore (carve-out is root-only)", () => {
219
+ expect(read("core/docs/.gitignore")).toBe("release-nested\nv2\n");
220
+ expect(fs.readFileSync(path.join(hqRoot, "personal/docs/.gitignore"), "utf-8")).toBe("release-nested\nMINE\n");
221
+ });
222
+ it("still rescues an ordinary user-edited file into personal/", () => {
223
+ expect(fs.readFileSync(path.join(hqRoot, "personal/edited.md"), "utf-8")).toBe("MINE\n");
224
+ expect(out).toContain("rescued: core/edited.md -> personal/edited.md");
225
+ });
226
+ });
227
+ /**
228
+ * KEEP-LOCAL must require *proof* that the operator edited the file, which only
229
+ * a floor comparison provides. In `head_compare` mode — first-ever run, a
230
+ * missing or unreachable last-sync stamp, `--no-history-check` — "differs from
231
+ * HEAD" is all we know, and an untouched ignore file from an older release
232
+ * looks identical to an edited one. Keeping it there would pin a stale file
233
+ * locally forever instead of letting it track the release, so this mode falls
234
+ * back to the pre-existing rescue behaviour.
235
+ */
236
+ describe.skipIf(!toolsAvailable)("rescue keep-local requires a floor-proven edit", () => {
237
+ let workDir;
238
+ let hqRoot;
239
+ let out = "";
240
+ const git = (cwd, ...args) => execFileSync("git", args, {
241
+ cwd,
242
+ stdio: ["ignore", "pipe", "pipe"],
243
+ env: {
244
+ ...process.env,
245
+ GIT_AUTHOR_NAME: "t",
246
+ GIT_AUTHOR_EMAIL: "t@t",
247
+ GIT_COMMITTER_NAME: "t",
248
+ GIT_COMMITTER_EMAIL: "t@t",
249
+ },
250
+ })
251
+ .toString()
252
+ .trim();
253
+ beforeAll(() => {
254
+ workDir = fs.mkdtempSync(path.join(os.tmpdir(), "hq-rescue-nofloor-"));
255
+ const upstream = path.join(workDir, "upstream");
256
+ fs.mkdirSync(upstream, { recursive: true });
257
+ git(workDir, "init", "-b", "main", "upstream");
258
+ fs.writeFileSync(path.join(upstream, ".gitignore"), "release-git\nv2\n");
259
+ git(upstream, "add", "-A");
260
+ git(upstream, "commit", "-m", "head");
261
+ hqRoot = path.join(workDir, "hq");
262
+ fs.mkdirSync(path.join(hqRoot, "personal"), { recursive: true });
263
+ fs.mkdirSync(path.join(hqRoot, "companies"), { recursive: true });
264
+ // Stale-but-untouched: an older release's copy, indistinguishable from an
265
+ // edit without a floor to compare against.
266
+ fs.writeFileSync(path.join(hqRoot, ".gitignore"), "release-git\n");
267
+ const realGit = execFileSync("bash", ["-lc", "command -v git"]).toString().trim() ||
268
+ "/usr/bin/git";
269
+ const shimDir = path.join(workDir, "shim");
270
+ fs.mkdirSync(shimDir, { recursive: true });
271
+ fs.writeFileSync(path.join(shimDir, "git"), `#!/usr/bin/env bash
272
+ if [ "$1" = "clone" ]; then
273
+ args=()
274
+ for a in "$@"; do
275
+ case "$a" in
276
+ https://github.com/*) a=${JSON.stringify(upstream)} ;;
277
+ esac
278
+ args+=("$a")
279
+ done
280
+ exec ${JSON.stringify(realGit)} "\${args[@]}"
281
+ fi
282
+ exec ${JSON.stringify(realGit)} "$@"
283
+ `, { mode: 0o755 });
284
+ // No --floor-sha: the rescue falls back to head_compare.
285
+ const r = runRescueCapture([
286
+ "--hq-root",
287
+ hqRoot,
288
+ "--source",
289
+ "test/repo",
290
+ "--ref",
291
+ "main",
292
+ "--no-history-check",
293
+ "--yes",
294
+ "--no-backup",
295
+ ], fixtureEnv(shimDir));
296
+ out = `${r.stdout}\n${r.stderr}`;
297
+ if (r.status !== 0)
298
+ throw new Error(`rescue failed (${r.status}):\n${out}`);
299
+ });
300
+ afterAll(() => {
301
+ if (workDir)
302
+ fs.rmSync(workDir, { recursive: true, force: true });
303
+ });
304
+ it("ran in head_compare mode (no usable floor)", () => {
305
+ expect(out).toContain("Baseline: HEAD compare");
306
+ });
307
+ it("does not keep-local without floor-proven evidence of an edit", () => {
308
+ expect(out).not.toContain("kept local: .gitignore");
309
+ expect(out).toMatch(/user-edit\s+\(kept local\):\s+0 files/);
310
+ });
311
+ it("lets the release update a stale root .gitignore in this mode", () => {
312
+ expect(fs.readFileSync(path.join(hqRoot, ".gitignore"), "utf-8")).toBe("release-git\nv2\n");
313
+ });
314
+ });
315
+ //# sourceMappingURL=rescue-keep-local-ignore.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rescue-keep-local-ignore.test.js","sourceRoot":"","sources":["../../src/cli/rescue-keep-local-ignore.test.ts"],"names":[],"mappings":"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"}
@@ -152,10 +152,25 @@ export interface ObjectIO {
152
152
  * (caching/refresh is the caller's concern, at the EntityContext level — see
153
153
  * the original buildClient note in s3.ts).
154
154
  */
155
+ /**
156
+ * Re-resolve one entity's context, returning credentials valid *now*. Backed by
157
+ * `resolveEntityContext`, which serves from cache and re-vends only inside its
158
+ * refresh window.
159
+ */
160
+ export type ContextRefresh = () => Promise<EntityContext>;
161
+ /** Build a {@link ContextRefresh} for a given entity uid. */
162
+ export type ContextRefresherFactory = (uid: string) => ContextRefresh;
155
163
  export declare class S3SdkObjectIO implements ObjectIO {
156
164
  private readonly client;
157
165
  private readonly bucket;
158
- constructor(ctx: EntityContext);
166
+ /**
167
+ * @param refresh Re-resolve this context's credentials. When supplied, the
168
+ * SDK is handed a credential *provider* rather than a frozen object, so a
169
+ * pass that outlives its 15-minute STS session renews instead of failing
170
+ * with `ExpiredToken`. Omit it only where the instance is known to be
171
+ * short-lived; the default factory always supplies one.
172
+ */
173
+ constructor(ctx: EntityContext, refresh?: ContextRefresh);
159
174
  putObject(input: PutObjectInput): Promise<{
160
175
  etag: string;
161
176
  }>;
@@ -300,6 +315,14 @@ export declare class PresignObjectIO implements ObjectIO {
300
315
  private mintHeadGetUrl;
301
316
  }
302
317
  export type ObjectIOFactory = (ctx: EntityContext) => ObjectIO;
318
+ /**
319
+ * The S3-SDK transport, wired so every instance can renew its own STS session.
320
+ *
321
+ * Use this rather than the bare default wherever the caller can supply a
322
+ * refresher: the bare default builds instances that expire with the 15-minute
323
+ * session that created them.
324
+ */
325
+ export declare function stsObjectIOFactory(refresherFor: ContextRefresherFactory): ObjectIOFactory;
303
326
  /**
304
327
  * Install the transport factory for the current process. Passing `null`
305
328
  * resets to the default S3 SDK transport. Called once by `runRunner` after it
@@ -314,5 +337,5 @@ export declare function resolveObjectIO(ctx: EntityContext): ObjectIO;
314
337
  * transport, reusing the one already-authenticated VaultClient and deriving
315
338
  * the per-company authority from `ctx.uid`.
316
339
  */
317
- export declare function presignObjectIOFactory(vault: PresignTransportClient): ObjectIOFactory;
340
+ export declare function presignObjectIOFactory(vault: PresignTransportClient, refresherFor?: ContextRefresherFactory): ObjectIOFactory;
318
341
  //# sourceMappingURL=object-io.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"object-io.d.ts","sourceRoot":"","sources":["../src/object-io.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"object-io.d.ts","sourceRoot":"","sources":["../src/object-io.ts"],"names":[],"mappings":"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"}
package/dist/object-io.js CHANGED
@@ -42,16 +42,17 @@ async function drainToBuffer(body) {
42
42
  }
43
43
  return Buffer.concat(chunks);
44
44
  }
45
- /**
46
- * Direct-to-S3 transport over STS-vended credentials. A fresh client per
47
- * instance so the latest credentials from the EntityContext are always used
48
- * (caching/refresh is the caller's concern, at the EntityContext level — see
49
- * the original buildClient note in s3.ts).
50
- */
51
45
  export class S3SdkObjectIO {
52
46
  client;
53
47
  bucket;
54
- constructor(ctx) {
48
+ /**
49
+ * @param refresh Re-resolve this context's credentials. When supplied, the
50
+ * SDK is handed a credential *provider* rather than a frozen object, so a
51
+ * pass that outlives its 15-minute STS session renews instead of failing
52
+ * with `ExpiredToken`. Omit it only where the instance is known to be
53
+ * short-lived; the default factory always supplies one.
54
+ */
55
+ constructor(ctx, refresh) {
55
56
  this.bucket = ctx.bucketName;
56
57
  if (!ctx.credentials) {
57
58
  // A credential-less context only exists on the presign path (HQ-59
@@ -63,13 +64,45 @@ export class S3SdkObjectIO {
63
64
  `context for ${ctx.uid}; company presign contexts must use ` +
64
65
  `PresignObjectIO. This is a transport-routing bug.`);
65
66
  }
67
+ // A frozen credential object is the whole bug: STS sessions last 15
68
+ // minutes (context.ts DEFAULT_SESSION_DURATION_SECONDS = 900), and an
69
+ // instance living longer than that signs with a dead token until S3
70
+ // answers `ExpiredToken http=400`. Hand the SDK a provider instead — it
71
+ // caches on the `expiration` we return and calls back once it passes, so
72
+ // renewal costs nothing until it is actually needed.
73
+ //
74
+ // `resolveEntityContext` is already the right thing to call back into: it
75
+ // serves from cache and re-vends only inside its 2-minute refresh window,
76
+ // so this does not add a vend per request.
77
+ const initial = ctx.credentials;
66
78
  this.client = new S3Client({
67
79
  region: ctx.region,
68
- credentials: {
69
- accessKeyId: ctx.credentials.accessKeyId,
70
- secretAccessKey: ctx.credentials.secretAccessKey,
71
- sessionToken: ctx.credentials.sessionToken,
72
- },
80
+ credentials: refresh
81
+ ? async () => {
82
+ const next = await refresh();
83
+ if (!next.credentials) {
84
+ // The refresher resolved a presign-only context. Signing with
85
+ // `undefined` would 403 with an opaque AWS error much later, so
86
+ // surface the routing bug here instead.
87
+ throw new Error(`S3SdkObjectIO refreshed ${ctx.uid} into a context with no STS ` +
88
+ `credentials; company presign contexts must use PresignObjectIO. ` +
89
+ `This is a transport-routing bug.`);
90
+ }
91
+ return {
92
+ accessKeyId: next.credentials.accessKeyId,
93
+ secretAccessKey: next.credentials.secretAccessKey,
94
+ sessionToken: next.credentials.sessionToken,
95
+ // Without this the SDK treats the credentials as eternal and
96
+ // never calls back — the frozen-credential bug in another shape.
97
+ expiration: new Date(next.expiresAt),
98
+ };
99
+ }
100
+ : {
101
+ accessKeyId: initial.accessKeyId,
102
+ secretAccessKey: initial.secretAccessKey,
103
+ sessionToken: initial.sessionToken,
104
+ expiration: new Date(ctx.expiresAt),
105
+ },
73
106
  });
74
107
  }
75
108
  async putObject(input) {
@@ -344,7 +377,9 @@ function notFoundError(key) {
344
377
  * disable every push-side conflict guard and clobber newer remote objects.
345
378
  */
346
379
  function accessDeniedError(key, detail) {
347
- return Object.assign(new Error(`Access denied for ${key}: ${detail}`), { name: "Forbidden" });
380
+ return Object.assign(new Error(`Access denied for ${key}: ${detail}`), {
381
+ name: "Forbidden",
382
+ });
348
383
  }
349
384
  /**
350
385
  * An error shaped like the AWS SDK's 412 (`name: "PreconditionFailed"`) so
@@ -354,7 +389,9 @@ function accessDeniedError(key, detail) {
354
389
  * (If-None-Match) — surface as a conflict, never overwrite.
355
390
  */
356
391
  function preconditionFailedError(key, detail) {
357
- return Object.assign(new Error(`Precondition failed for ${key}: ${detail}`), { name: "PreconditionFailed" });
392
+ return Object.assign(new Error(`Precondition failed for ${key}: ${detail}`), {
393
+ name: "PreconditionFailed",
394
+ });
358
395
  }
359
396
  /**
360
397
  * If-Match compares quoted entity-tags. Journal baselines store etags
@@ -723,8 +760,7 @@ export class PresignObjectIO {
723
760
  // presignedGetWithRetry already burned same-URL connection retries.
724
761
  // One outer pass with a freshly minted URL recovers poisoned sockets
725
762
  // that keep failing on the same signed endpoint.
726
- if (isRetryablePresignedGetError(err) &&
727
- attempt < FETCH_MAX_RETRIES) {
763
+ if (isRetryablePresignedGetError(err) && attempt < FETCH_MAX_RETRIES) {
728
764
  lastError = err;
729
765
  forceFreshUrl = true;
730
766
  continue;
@@ -837,8 +873,7 @@ export class PresignObjectIO {
837
873
  res = await presignedGetWithRetry(url, undefined, `presigned HEAD ${key}`);
838
874
  }
839
875
  catch (err) {
840
- if (isRetryablePresignedGetError(err) &&
841
- attempt < FETCH_MAX_RETRIES) {
876
+ if (isRetryablePresignedGetError(err) && attempt < FETCH_MAX_RETRIES) {
842
877
  lastError = err;
843
878
  forceFreshUrl = true;
844
879
  continue;
@@ -1082,6 +1117,16 @@ async function fetchWithRetry(url, init, what) {
1082
1117
  : new Error(`${what}: failed after ${FETCH_MAX_RETRIES} retries`);
1083
1118
  }
1084
1119
  const DEFAULT_FACTORY = (ctx) => new S3SdkObjectIO(ctx);
1120
+ /**
1121
+ * The S3-SDK transport, wired so every instance can renew its own STS session.
1122
+ *
1123
+ * Use this rather than the bare default wherever the caller can supply a
1124
+ * refresher: the bare default builds instances that expire with the 15-minute
1125
+ * session that created them.
1126
+ */
1127
+ export function stsObjectIOFactory(refresherFor) {
1128
+ return (ctx) => new S3SdkObjectIO(ctx, refresherFor(ctx.uid));
1129
+ }
1085
1130
  let activeFactory = DEFAULT_FACTORY;
1086
1131
  /**
1087
1132
  * Install the transport factory for the current process. Passing `null`
@@ -1101,7 +1146,7 @@ export function resolveObjectIO(ctx) {
1101
1146
  * transport, reusing the one already-authenticated VaultClient and deriving
1102
1147
  * the per-company authority from `ctx.uid`.
1103
1148
  */
1104
- export function presignObjectIOFactory(vault) {
1149
+ export function presignObjectIOFactory(vault, refresherFor) {
1105
1150
  // Memoize one PresignObjectIO per company for the run, so a prime() and the
1106
1151
  // transfer loop that drains its URL cache share the SAME instance. (Safe to
1107
1152
  // memoize: PresignObjectIO holds only the vault client — whose token is a
@@ -1120,7 +1165,9 @@ export function presignObjectIOFactory(vault) {
1120
1165
  // presign — keep them on the S3 SDK (STS) transport. Presign is for company
1121
1166
  // vaults (cmp_*), which is where the unbounded-grants problem lives.
1122
1167
  if (!ctx.uid.startsWith("cmp_")) {
1123
- return new S3SdkObjectIO(ctx);
1168
+ // Personal vaults are the remaining STS holder, and a personal pass over
1169
+ // a large HQ root is exactly the one that outlives a 15-minute session.
1170
+ return new S3SdkObjectIO(ctx, refresherFor?.(ctx.uid));
1124
1171
  }
1125
1172
  let io = byCompany.get(ctx.uid);
1126
1173
  if (!io) {