run402 4.39.0 → 4.40.0

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 (45) hide show
  1. package/cli.mjs +1 -1
  2. package/git-remote-run402.mjs +15 -1
  3. package/lib/assets.mjs +19 -26
  4. package/lib/cdn.mjs +4 -6
  5. package/lib/command-manifest.mjs +20 -0
  6. package/lib/config.mjs +30 -0
  7. package/lib/deploy-v2.mjs +15 -0
  8. package/lib/doctor.mjs +33 -0
  9. package/lib/gitvault.mjs +348 -1
  10. package/package.json +1 -1
  11. package/sdk/dist/namespaces/gitvault.crypto.d.ts +10 -0
  12. package/sdk/dist/namespaces/gitvault.crypto.d.ts.map +1 -1
  13. package/sdk/dist/namespaces/gitvault.crypto.js +10 -0
  14. package/sdk/dist/namespaces/gitvault.crypto.js.map +1 -1
  15. package/sdk/dist/namespaces/gitvault.d.ts +141 -4
  16. package/sdk/dist/namespaces/gitvault.d.ts.map +1 -1
  17. package/sdk/dist/namespaces/gitvault.js +226 -3
  18. package/sdk/dist/namespaces/gitvault.js.map +1 -1
  19. package/sdk/dist/node/gitvault-keystore.d.ts +11 -1
  20. package/sdk/dist/node/gitvault-keystore.d.ts.map +1 -1
  21. package/sdk/dist/node/gitvault-keystore.js.map +1 -1
  22. package/sdk/dist/node/gitvault-mirror-backend.d.ts +88 -0
  23. package/sdk/dist/node/gitvault-mirror-backend.d.ts.map +1 -0
  24. package/sdk/dist/node/gitvault-mirror-backend.js +374 -0
  25. package/sdk/dist/node/gitvault-mirror-backend.js.map +1 -0
  26. package/sdk/dist/node/gitvault-mirror-config.d.ts +53 -0
  27. package/sdk/dist/node/gitvault-mirror-config.d.ts.map +1 -0
  28. package/sdk/dist/node/gitvault-mirror-config.js +112 -0
  29. package/sdk/dist/node/gitvault-mirror-config.js.map +1 -0
  30. package/sdk/dist/node/gitvault-mirror.d.ts +120 -0
  31. package/sdk/dist/node/gitvault-mirror.d.ts.map +1 -0
  32. package/sdk/dist/node/gitvault-mirror.js +464 -0
  33. package/sdk/dist/node/gitvault-mirror.js.map +1 -0
  34. package/sdk/dist/node/gitvault-publication.d.ts +131 -0
  35. package/sdk/dist/node/gitvault-publication.d.ts.map +1 -1
  36. package/sdk/dist/node/gitvault-publication.js +145 -1
  37. package/sdk/dist/node/gitvault-publication.js.map +1 -1
  38. package/sdk/dist/node/gitvault-recover.d.ts +136 -0
  39. package/sdk/dist/node/gitvault-recover.d.ts.map +1 -0
  40. package/sdk/dist/node/gitvault-recover.js +412 -0
  41. package/sdk/dist/node/gitvault-recover.js.map +1 -0
  42. package/sdk/dist/node/gitvault-snapshot.d.ts +8 -0
  43. package/sdk/dist/node/gitvault-snapshot.d.ts.map +1 -1
  44. package/sdk/dist/node/gitvault-snapshot.js +11 -0
  45. package/sdk/dist/node/gitvault-snapshot.js.map +1 -1
@@ -0,0 +1,374 @@
1
+ /**
2
+ * gitvault-mirror-and-recover — mirror storage backends (design D1/D2/D7,
3
+ * task 2.2).
4
+ *
5
+ * S3-or-directory behind ONE interface, so the writer/reconcile engine
6
+ * (`gitvault-mirror.ts`) and the recovery engine (`gitvault-recover.ts`)
7
+ * never know which one they are talking to.
8
+ *
9
+ * `@run402/sdk` deliberately carries no AWS SDK dependency (see the package's
10
+ * own dependency list — every crypto primitive is a narrowly-scoped,
11
+ * individually-audited package, never a broad vendor SDK). The S3 backend
12
+ * here is therefore a MINIMAL, hand-rolled AWS Signature Version 4 client
13
+ * (Node's built-in `fetch` + `node:crypto`), covering exactly the four
14
+ * operations the mirror needs: HEAD (existence/size), PUT (create-only where
15
+ * the bucket honors `If-None-Match`), GET, and `ListObjectsV2`. This is a
16
+ * DELIBERATE, DOCUMENTED SCOPE LIMIT: it does not implement the full AWS SDK
17
+ * credential provider chain (no IMDS/EC2-role, no SSO, no assume-role) — only
18
+ * the two mechanisms design D2 names: a NAMED PROFILE read from the
19
+ * standard `~/.aws/credentials` + `~/.aws/config` files, and the AMBIENT
20
+ * environment chain (`AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`/
21
+ * `AWS_SESSION_TOKEN`). Multipart upload is out of scope too — gitvault
22
+ * objects are already capped well under S3's 5 GiB single-PUT limit by the
23
+ * protocol's own object-size bounds (§4.6/§4.7).
24
+ */
25
+ import { createHash, createHmac } from "node:crypto";
26
+ import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
27
+ import { homedir } from "node:os";
28
+ import { dirname, join } from "node:path";
29
+ import { LocalError } from "../errors.js";
30
+ function fail(code, message, context, details, nextActions) {
31
+ throw new LocalError(message, context, { code, details, ...(nextActions ? { next_actions: nextActions } : {}) });
32
+ }
33
+ // ─── Directory backend ────────────────────────────────────────────────────────
34
+ /**
35
+ * A local (or network-mounted) directory, laid out identically to the bucket
36
+ * (`<root>/source/<repo_id>/head/<gen>`, etc. — but the backend is
37
+ * repo-scoped, so `root` IS already `<destination>/source/<repo_id>`). Writes
38
+ * are atomic (temp file + rename); create-only is REAL create-only via
39
+ * `wx` (`O_CREAT|O_EXCL`) — never a silent overwrite of a differently-keyed
40
+ * torn write.
41
+ */
42
+ export class DirectoryMirrorBackend {
43
+ root;
44
+ constructor(root) {
45
+ this.root = root;
46
+ }
47
+ describe() {
48
+ return this.root;
49
+ }
50
+ resolve(key) {
51
+ if (key.includes("..") || key.startsWith("/"))
52
+ fail("GITVAULT_MIRROR_KEY_INVALID", `unsafe mirror key: ${key}`, "resolving gitvault mirror path", { key });
53
+ return join(this.root, ...key.split("/"));
54
+ }
55
+ async head(key) {
56
+ const path = this.resolve(key);
57
+ if (!existsSync(path))
58
+ return null;
59
+ const st = statSync(path);
60
+ if (!st.isFile())
61
+ return null;
62
+ return { size_bytes: String(st.size) };
63
+ }
64
+ async get(key) {
65
+ const path = this.resolve(key);
66
+ if (!existsSync(path))
67
+ return null;
68
+ try {
69
+ return new Uint8Array(readFileSync(path));
70
+ }
71
+ catch {
72
+ return null;
73
+ }
74
+ }
75
+ async putCreateOnly(key, bytes) {
76
+ const path = this.resolve(key);
77
+ if (existsSync(path))
78
+ return { created: false };
79
+ const dir = dirname(path);
80
+ mkdirSync(dir, { recursive: true });
81
+ const tmp = `${path}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
82
+ writeFileSync(tmp, bytes, { flag: "wx" });
83
+ try {
84
+ // Real create-only: `wx` on the FINAL path too, so a concurrent writer
85
+ // racing us loses the rename, not the data — the loser's temp file is
86
+ // cleaned up and it reports `created: false` (the winner's bytes are
87
+ // trusted; the caller compares hashes if it cares which one landed).
88
+ renameSync(tmp, path);
89
+ }
90
+ catch (e) {
91
+ try {
92
+ unlinkSync(tmp);
93
+ }
94
+ catch {
95
+ /* best-effort cleanup */
96
+ }
97
+ if (e.code === "EEXIST" || existsSync(path))
98
+ return { created: false };
99
+ throw e;
100
+ }
101
+ return { created: true };
102
+ }
103
+ async list(prefix = "") {
104
+ const out = [];
105
+ const walk = (dir, rel) => {
106
+ if (!existsSync(dir))
107
+ return;
108
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
109
+ if (entry.name.endsWith(".tmp"))
110
+ continue;
111
+ const childRel = rel ? `${rel}/${entry.name}` : entry.name;
112
+ const childAbs = join(dir, entry.name);
113
+ if (entry.isDirectory())
114
+ walk(childAbs, childRel);
115
+ else if (entry.isFile())
116
+ out.push(childRel);
117
+ }
118
+ };
119
+ walk(this.root, "");
120
+ return out.filter((k) => k.startsWith(prefix)).sort();
121
+ }
122
+ }
123
+ function hmacSha256(key, data) {
124
+ return createHmac("sha256", key).update(data, "utf8").digest();
125
+ }
126
+ function sha256Hex(data) {
127
+ return createHash("sha256").update(data).digest("hex");
128
+ }
129
+ function amzDate(now) {
130
+ const iso = now.toISOString().replace(/[:-]|\.\d{3}/g, "");
131
+ return { dateTime: `${iso}`, date: iso.slice(0, 8) };
132
+ }
133
+ function signingKey(secretKey, date, region, service) {
134
+ const kDate = hmacSha256(`AWS4${secretKey}`, date);
135
+ const kRegion = hmacSha256(kDate, region);
136
+ const kService = hmacSha256(kRegion, service);
137
+ return hmacSha256(kService, "aws4_request");
138
+ }
139
+ /** One SigV4-signed request against an S3-compatible endpoint. */
140
+ async function s3Request(input) {
141
+ const host = input.endpoint ? new URL(input.endpoint).host : `${input.bucket}.s3.${input.region}.amazonaws.com`;
142
+ const proto = input.endpoint ? new URL(input.endpoint).protocol.replace(":", "") : "https";
143
+ const canonicalUri = `/${input.key.split("/").map(encodeURIComponent).join("/")}`;
144
+ const query = { ...(input.query ?? {}) };
145
+ const sortedQueryKeys = Object.keys(query).sort();
146
+ const canonicalQuery = sortedQueryKeys.map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(query[k])}`).join("&");
147
+ const now = new Date();
148
+ const { date, dateTime } = amzDate(now);
149
+ const bodyHash = sha256Hex(Buffer.from(input.body ?? new Uint8Array(0)));
150
+ const headers = {
151
+ host,
152
+ "x-amz-content-sha256": bodyHash,
153
+ "x-amz-date": dateTime,
154
+ ...(input.credentials.session_token ? { "x-amz-security-token": input.credentials.session_token } : {}),
155
+ ...(input.extraHeaders ?? {}),
156
+ };
157
+ const sortedHeaderKeys = Object.keys(headers).sort();
158
+ const canonicalHeaders = sortedHeaderKeys.map((k) => `${k}:${headers[k].trim()}\n`).join("");
159
+ const signedHeaders = sortedHeaderKeys.join(";");
160
+ const canonicalRequest = [input.method, canonicalUri, canonicalQuery, canonicalHeaders, signedHeaders, bodyHash].join("\n");
161
+ const scope = `${date}/${input.region}/s3/aws4_request`;
162
+ const stringToSign = ["AWS4-HMAC-SHA256", dateTime, scope, sha256Hex(canonicalRequest)].join("\n");
163
+ const key = signingKey(input.credentials.secret_access_key, date, input.region, "s3");
164
+ const signature = createHmac("sha256", key).update(stringToSign, "utf8").digest("hex");
165
+ const authorization = `AWS4-HMAC-SHA256 Credential=${input.credentials.access_key_id}/${scope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
166
+ const url = `${proto}://${host}${canonicalUri}${canonicalQuery ? `?${canonicalQuery}` : ""}`;
167
+ return fetch(url, {
168
+ method: input.method,
169
+ headers: { ...headers, authorization },
170
+ ...(input.body ? { body: input.body } : {}),
171
+ });
172
+ }
173
+ /** Resolve a NAMED PROFILE (`~/.aws/credentials` + `~/.aws/config`) or the AMBIENT environment chain — see the module doc's documented scope limit. */
174
+ export function resolveMirrorCredentials(credential) {
175
+ if (credential.kind === "ambient") {
176
+ const accessKeyId = process.env.AWS_ACCESS_KEY_ID;
177
+ const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
178
+ if (!accessKeyId || !secretAccessKey) {
179
+ fail("GITVAULT_MIRROR_CREDENTIALS_UNRESOLVED", "no ambient AWS credentials found (AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY unset)", "resolving gitvault mirror credentials", undefined, [{ action: "export AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, or configure a named profile with `run402 gitvault mirror set ... --profile <name>`" }]);
180
+ }
181
+ return { access_key_id: accessKeyId, secret_access_key: secretAccessKey, ...(process.env.AWS_SESSION_TOKEN ? { session_token: process.env.AWS_SESSION_TOKEN } : {}) };
182
+ }
183
+ const credsPath = join(homedir(), ".aws", "credentials");
184
+ let text;
185
+ try {
186
+ text = readFileSync(credsPath, "utf8");
187
+ }
188
+ catch {
189
+ fail("GITVAULT_MIRROR_CREDENTIALS_UNRESOLVED", `no AWS credentials file at ${credsPath}`, "resolving gitvault mirror credentials", { profile: credential.profile }, [{ action: `run 'aws configure --profile ${credential.profile}', or configure the destination for --ambient credentials instead` }]);
190
+ }
191
+ const section = parseIniSection(text, credential.profile);
192
+ const accessKeyId = section.aws_access_key_id;
193
+ const secretAccessKey = section.aws_secret_access_key;
194
+ if (!accessKeyId || !secretAccessKey) {
195
+ fail("GITVAULT_MIRROR_CREDENTIALS_UNRESOLVED", `profile '${credential.profile}' is missing aws_access_key_id/aws_secret_access_key in ${credsPath}`, "resolving gitvault mirror credentials", { profile: credential.profile }, [{ action: `run 'aws configure --profile ${credential.profile}'` }]);
196
+ }
197
+ return { access_key_id: accessKeyId, secret_access_key: secretAccessKey, ...(section.aws_session_token ? { session_token: section.aws_session_token } : {}) };
198
+ }
199
+ /** A minimal INI-section parser — no dependency, no more than the shape `~/.aws/credentials` actually needs. */
200
+ function parseIniSection(text, section) {
201
+ const out = {};
202
+ let inSection = false;
203
+ for (const rawLine of text.split(/\r?\n/)) {
204
+ const line = rawLine.trim();
205
+ if (line === "" || line.startsWith("#") || line.startsWith(";"))
206
+ continue;
207
+ const header = /^\[(.+)\]$/.exec(line);
208
+ if (header) {
209
+ inSection = header[1].trim() === section;
210
+ continue;
211
+ }
212
+ if (!inSection)
213
+ continue;
214
+ const eq = line.indexOf("=");
215
+ if (eq === -1)
216
+ continue;
217
+ out[line.slice(0, eq).trim()] = line.slice(eq + 1).trim();
218
+ }
219
+ return out;
220
+ }
221
+ export class S3MirrorBackend {
222
+ bucket;
223
+ prefix;
224
+ region;
225
+ credential;
226
+ endpoint;
227
+ constructor(bucket, prefix, region, credential, endpoint) {
228
+ this.bucket = bucket;
229
+ this.prefix = prefix;
230
+ this.region = region;
231
+ this.credential = credential;
232
+ this.endpoint = endpoint;
233
+ }
234
+ describe() {
235
+ return `s3://${this.bucket}/${this.prefix}`;
236
+ }
237
+ fullKey(key) {
238
+ return this.prefix ? `${this.prefix}/${key}` : key;
239
+ }
240
+ creds() {
241
+ return resolveMirrorCredentials(this.credential);
242
+ }
243
+ async head(key) {
244
+ const r = await s3Request({ method: "HEAD", bucket: this.bucket, region: this.region, endpoint: this.endpoint, key: this.fullKey(key), credentials: this.creds() });
245
+ if (r.status === 404)
246
+ return null;
247
+ if (!r.ok)
248
+ fail("GITVAULT_MIRROR_S3_ERROR", `HEAD ${key} failed (HTTP ${r.status})`, "reading gitvault mirror object", { key, status: r.status });
249
+ const len = r.headers.get("content-length");
250
+ return { size_bytes: len ?? "0" };
251
+ }
252
+ async get(key) {
253
+ const r = await s3Request({ method: "GET", bucket: this.bucket, region: this.region, endpoint: this.endpoint, key: this.fullKey(key), credentials: this.creds() });
254
+ if (r.status === 404)
255
+ return null;
256
+ if (!r.ok)
257
+ fail("GITVAULT_MIRROR_S3_ERROR", `GET ${key} failed (HTTP ${r.status})`, "reading gitvault mirror object", { key, status: r.status });
258
+ return new Uint8Array(await r.arrayBuffer());
259
+ }
260
+ async putCreateOnly(key, bytes) {
261
+ // `If-None-Match: *` create-only PUT — the same conditional-write
262
+ // mechanism the primary vault bucket's own policy mandates (protocol
263
+ // §3). Documented as "recommended, not required" (design D7): this is
264
+ // the customer's bucket and their policy, so a provider/bucket that
265
+ // rejects the header (older buckets, some S3-compatible stores) falls
266
+ // back to read-and-compare instead of hard-failing the sync.
267
+ const r = await s3Request({
268
+ method: "PUT",
269
+ bucket: this.bucket,
270
+ region: this.region,
271
+ endpoint: this.endpoint,
272
+ key: this.fullKey(key),
273
+ credentials: this.creds(),
274
+ body: bytes,
275
+ extraHeaders: { "if-none-match": "*", "content-length": String(bytes.length) },
276
+ });
277
+ if (r.status === 412 || r.status === 409)
278
+ return { created: false };
279
+ if (r.ok)
280
+ return { created: true };
281
+ if (r.status === 400 || r.status === 501) {
282
+ // The condition itself was rejected (unsupported by this bucket/provider)
283
+ // rather than failing — read-and-compare fallback.
284
+ const existing = await this.head(key);
285
+ if (existing)
286
+ return { created: false };
287
+ const retry = await s3Request({ method: "PUT", bucket: this.bucket, region: this.region, endpoint: this.endpoint, key: this.fullKey(key), credentials: this.creds(), body: bytes, extraHeaders: { "content-length": String(bytes.length) } });
288
+ if (!retry.ok)
289
+ fail("GITVAULT_MIRROR_S3_ERROR", `PUT ${key} failed (HTTP ${retry.status})`, "writing gitvault mirror object", { key, status: retry.status });
290
+ return { created: true };
291
+ }
292
+ fail("GITVAULT_MIRROR_S3_ERROR", `PUT ${key} failed (HTTP ${r.status})`, "writing gitvault mirror object", { key, status: r.status });
293
+ }
294
+ async list(prefix = "") {
295
+ const out = [];
296
+ let continuationToken;
297
+ const fullPrefix = this.fullKey(prefix);
298
+ for (;;) {
299
+ const query = { "list-type": "2", prefix: fullPrefix };
300
+ if (continuationToken)
301
+ query["continuation-token"] = continuationToken;
302
+ const r = await s3Request({ method: "GET", bucket: this.bucket, region: this.region, endpoint: this.endpoint, key: "", query, credentials: this.creds() });
303
+ if (!r.ok)
304
+ fail("GITVAULT_MIRROR_S3_ERROR", `ListObjectsV2 failed (HTTP ${r.status})`, "listing gitvault mirror objects", { status: r.status });
305
+ const xml = await r.text();
306
+ for (const m of xml.matchAll(/<Key>([^<]*)<\/Key>/g)) {
307
+ const full = decodeXmlEntities(m[1]);
308
+ out.push(this.prefix ? full.slice(this.prefix.length + 1) : full);
309
+ }
310
+ const truncated = /<IsTruncated>true<\/IsTruncated>/.test(xml);
311
+ if (!truncated)
312
+ break;
313
+ const next = /<NextContinuationToken>([^<]*)<\/NextContinuationToken>/.exec(xml);
314
+ if (!next)
315
+ break;
316
+ continuationToken = decodeXmlEntities(next[1]);
317
+ }
318
+ return out.sort();
319
+ }
320
+ }
321
+ function decodeXmlEntities(s) {
322
+ return s.replace(/&(amp|lt|gt|quot|apos|#\d+);/g, (m, entity) => {
323
+ switch (entity) {
324
+ case "amp": return "&";
325
+ case "lt": return "<";
326
+ case "gt": return ">";
327
+ case "quot": return "\"";
328
+ case "apos": return "'";
329
+ default: return entity.startsWith("#") ? String.fromCharCode(Number(entity.slice(1))) : m;
330
+ }
331
+ });
332
+ }
333
+ // ─── Factory ──────────────────────────────────────────────────────────────────
334
+ /** Open the backend for one vault's mirror config — repo-scoped: the directory backend's root and the S3 prefix both already carry `source/<repo_id>`. */
335
+ export function openGitvaultMirrorBackend(destination, repoId, credential) {
336
+ if (destination.kind === "directory") {
337
+ return new DirectoryMirrorBackend(join(destination.path, "source", repoId));
338
+ }
339
+ if (!credential)
340
+ fail("GITVAULT_MIRROR_CREDENTIAL_REQUIRED", "an s3 mirror destination needs a credential", "opening gitvault mirror backend");
341
+ const prefix = destination.prefix ? `${destination.prefix}/source/${repoId}` : `source/${repoId}`;
342
+ return new S3MirrorBackend(destination.bucket, prefix, destination.region, credential, destination.endpoint);
343
+ }
344
+ /**
345
+ * List every `repo_id` mirrored under a destination's root (`source/<repo_id>/…`),
346
+ * WITHOUT repo-scoping the backend first — the discovery step `recover
347
+ * <source>` needs before it can even open the repo-scoped backend {@link
348
+ * openGitvaultMirrorBackend} expects. Used only to resolve which vault a bare
349
+ * destination URL (no `--repo`) names.
350
+ */
351
+ export async function discoverMirroredRepoIds(destination, credential) {
352
+ const root = destination.kind === "directory"
353
+ ? new DirectoryMirrorBackend(destination.path)
354
+ : (() => {
355
+ if (!credential)
356
+ fail("GITVAULT_MIRROR_CREDENTIAL_REQUIRED", "an s3 mirror destination needs a credential", "discovering mirrored gitvault repos");
357
+ return new S3MirrorBackend(destination.bucket, destination.prefix, destination.region, credential, destination.endpoint);
358
+ })();
359
+ const keys = await root.list("source/");
360
+ const ids = new Set();
361
+ for (const key of keys) {
362
+ const m = /^source\/(src_[0-9a-f]{32})\//.exec(key);
363
+ if (m)
364
+ ids.add(m[1]);
365
+ }
366
+ return [...ids].sort();
367
+ }
368
+ /** Best-effort recursive delete of an empty (or now-empty) mirror root — used by `mirror remove --purge` semantics if ever added; NOT called by plain `mirror remove` (design: config removal never touches the customer's bytes). Exported for tests. */
369
+ export function _rmMirrorRoot(destination, repoId) {
370
+ if (destination.kind !== "directory")
371
+ return;
372
+ rmSync(join(destination.path, "source", repoId), { recursive: true, force: true });
373
+ }
374
+ //# sourceMappingURL=gitvault-mirror-backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitvault-mirror-backend.js","sourceRoot":"","sources":["../../src/node/gitvault-mirror-backend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { GitvaultKeystore } from "./gitvault-keystore.js";
2
+ /** Where the mirror writes objects. Directory is a plain local (or network-mounted) path; S3 is `s3://<bucket>/<prefix>`. */
3
+ export type GitvaultMirrorDestination = {
4
+ kind: "directory";
5
+ path: string;
6
+ } | {
7
+ kind: "s3";
8
+ bucket: string;
9
+ prefix: string;
10
+ region: string;
11
+ endpoint?: string;
12
+ };
13
+ /** How the S3 destination authenticates. Never a raw key — see the module doc. */
14
+ export type GitvaultMirrorCredential = {
15
+ kind: "profile";
16
+ profile: string;
17
+ } | {
18
+ kind: "ambient";
19
+ };
20
+ /** `mirrors/<repo_id>.json` — the ONLY thing this file persists: where, and which named credential to resolve at use time. */
21
+ export interface GitvaultMirrorConfig {
22
+ version: 1;
23
+ repo_id: string;
24
+ destination: GitvaultMirrorDestination;
25
+ /** Present only for an `s3` destination — a directory destination needs no credential. */
26
+ credential?: GitvaultMirrorCredential;
27
+ created_at: string;
28
+ updated_at: string;
29
+ }
30
+ export declare function mirrorsDir(keystore: GitvaultKeystore): string;
31
+ export declare function mirrorConfigPath(keystore: GitvaultKeystore, repoId: string): string;
32
+ /** Read the mirror config for one vault, or `null` when none is configured. */
33
+ export declare function readMirrorConfig(keystore: GitvaultKeystore, repoId: string): GitvaultMirrorConfig | null;
34
+ /** Every repo id with a mirror configured on this machine. */
35
+ export declare function listMirroredRepoIds(keystore: GitvaultKeystore): string[];
36
+ /** Set (create or replace) the mirror destination for one vault. */
37
+ export declare function saveMirrorConfig(keystore: GitvaultKeystore, input: {
38
+ repo_id: string;
39
+ destination: GitvaultMirrorDestination;
40
+ credential?: GitvaultMirrorCredential;
41
+ }, now?: () => Date): GitvaultMirrorConfig;
42
+ /** Remove the mirror config for one vault. Never touches the mirror's own bytes — this only stops future pushes/syncs from targeting it. */
43
+ export declare function removeMirrorConfig(keystore: GitvaultKeystore, repoId: string): {
44
+ removed: boolean;
45
+ };
46
+ /** Parse `s3://<bucket>/<prefix>` or a plain filesystem path into a {@link GitvaultMirrorDestination}. */
47
+ export declare function parseMirrorDestinationUrl(url: string, options?: {
48
+ region?: string;
49
+ endpoint?: string;
50
+ }): GitvaultMirrorDestination;
51
+ /** Render a destination back to the address form a human typed (for `status`/errors). */
52
+ export declare function formatMirrorDestination(destination: GitvaultMirrorDestination): string;
53
+ //# sourceMappingURL=gitvault-mirror-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitvault-mirror-config.d.ts","sourceRoot":"","sources":["../../src/node/gitvault-mirror-config.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,gBAAgB,EAAyC,MAAM,wBAAwB,CAAC;AAMjG,6HAA6H;AAC7H,MAAM,MAAM,yBAAyB,GACjC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtF,kFAAkF;AAClF,MAAM,MAAM,wBAAwB,GAChC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB,8HAA8H;AAC9H,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,yBAAyB,CAAC;IACvC,0FAA0F;IAC1F,UAAU,CAAC,EAAE,wBAAwB,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAE7D;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGnF;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAaxG;AAED,8DAA8D;AAC9D,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAQxE;AAED,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,yBAAyB,CAAC;IAAC,UAAU,CAAC,EAAE,wBAAwB,CAAA;CAAE,EAAE,GAAG,GAAE,MAAM,IAAuB,GAAG,oBAAoB,CAehO;AAED,4IAA4I;AAC5I,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CASnG;AAED,0GAA0G;AAC1G,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,yBAAyB,CAYtI;AAED,yFAAyF;AACzF,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,yBAAyB,GAAG,MAAM,CAEtF"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * gitvault-mirror-and-recover — mirror destination config (design D1/D2,
3
+ * task 2.1).
4
+ *
5
+ * Per-vault mirror configuration lives BESIDE the keystore, in its own
6
+ * sibling directory (`<keystore root>/mirrors/<repo_id>.json`) — never in
7
+ * `run402.config.json` (that file is committed to the repository, and a
8
+ * mirror destination is a per-machine operational fact, not something to
9
+ * share with every clone) and never containing a raw secret value. The
10
+ * credential field names an AWS profile OR selects the ambient environment
11
+ * chain (`AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`/`AWS_SESSION_TOKEN`) —
12
+ * resolved at USE time by {@link ../node/gitvault-mirror-backend.js}, never
13
+ * read or cached here. D1 is the reason this file exists at all: run402
14
+ * never holds a credential to the customer's bucket, so the credential must
15
+ * live somewhere run402 code never uploads or transmits — this config file,
16
+ * read only by the client's own machine.
17
+ */
18
+ import { existsSync, readdirSync, unlinkSync } from "node:fs";
19
+ import { join } from "node:path";
20
+ import { LocalError } from "../errors.js";
21
+ import { GITVAULT_SRC_RE } from "../namespaces/gitvault.crypto.js";
22
+ import { readFileNoFollow, writeFileAtomic0600 } from "./gitvault-keystore.js";
23
+ function fail(code, message, context, details, nextActions) {
24
+ throw new LocalError(message, context, { code, details, ...(nextActions ? { next_actions: nextActions } : {}) });
25
+ }
26
+ export function mirrorsDir(keystore) {
27
+ return join(keystore.rootDir, "mirrors");
28
+ }
29
+ export function mirrorConfigPath(keystore, repoId) {
30
+ if (!GITVAULT_SRC_RE.test(repoId))
31
+ fail("GITVAULT_BAD_REPO_ID", `not a src_ id: ${repoId}`, "resolving gitvault mirror config path");
32
+ return join(mirrorsDir(keystore), `${repoId}.json`);
33
+ }
34
+ /** Read the mirror config for one vault, or `null` when none is configured. */
35
+ export function readMirrorConfig(keystore, repoId) {
36
+ const text = readFileNoFollow(mirrorConfigPath(keystore, repoId));
37
+ if (!text)
38
+ return null;
39
+ let parsed;
40
+ try {
41
+ parsed = JSON.parse(text);
42
+ }
43
+ catch (e) {
44
+ fail("GITVAULT_MIRROR_CONFIG_CORRUPT", `mirror config for ${repoId} is not valid JSON: ${e.message}`, "reading gitvault mirror config", { repo_id: repoId });
45
+ }
46
+ if (parsed.version !== 1 || parsed.repo_id !== repoId || !parsed.destination) {
47
+ fail("GITVAULT_MIRROR_CONFIG_CORRUPT", `mirror config for ${repoId} is not a version-1 gitvault mirror config`, "reading gitvault mirror config", { repo_id: repoId });
48
+ }
49
+ return parsed;
50
+ }
51
+ /** Every repo id with a mirror configured on this machine. */
52
+ export function listMirroredRepoIds(keystore) {
53
+ const dir = mirrorsDir(keystore);
54
+ if (!existsSync(dir))
55
+ return [];
56
+ return readdirSync(dir)
57
+ .filter((n) => n.endsWith(".json"))
58
+ .map((n) => n.slice(0, -5))
59
+ .filter((id) => GITVAULT_SRC_RE.test(id))
60
+ .sort();
61
+ }
62
+ /** Set (create or replace) the mirror destination for one vault. */
63
+ export function saveMirrorConfig(keystore, input, now = () => new Date()) {
64
+ if (input.destination.kind === "s3" && !input.credential) {
65
+ fail("GITVAULT_MIRROR_CREDENTIAL_REQUIRED", "an s3 mirror destination needs a credential — pass --profile <name> or --ambient", "configuring gitvault mirror");
66
+ }
67
+ const existing = readMirrorConfig(keystore, input.repo_id);
68
+ const full = {
69
+ version: 1,
70
+ repo_id: input.repo_id,
71
+ destination: input.destination,
72
+ ...(input.credential ? { credential: input.credential } : {}),
73
+ created_at: existing?.created_at ?? now().toISOString(),
74
+ updated_at: now().toISOString(),
75
+ };
76
+ writeFileAtomic0600(mirrorConfigPath(keystore, input.repo_id), JSON.stringify(full, null, 2));
77
+ return full;
78
+ }
79
+ /** Remove the mirror config for one vault. Never touches the mirror's own bytes — this only stops future pushes/syncs from targeting it. */
80
+ export function removeMirrorConfig(keystore, repoId) {
81
+ const path = mirrorConfigPath(keystore, repoId);
82
+ if (!existsSync(path))
83
+ return { removed: false };
84
+ try {
85
+ unlinkSync(path);
86
+ }
87
+ catch (e) {
88
+ fail("GITVAULT_MIRROR_CONFIG_REMOVE_FAILED", `could not remove mirror config for ${repoId}: ${e.message}`, "removing gitvault mirror config", { repo_id: repoId });
89
+ }
90
+ return { removed: true };
91
+ }
92
+ /** Parse `s3://<bucket>/<prefix>` or a plain filesystem path into a {@link GitvaultMirrorDestination}. */
93
+ export function parseMirrorDestinationUrl(url, options = {}) {
94
+ if (url.startsWith("s3://")) {
95
+ const rest = url.slice("s3://".length);
96
+ const slash = rest.indexOf("/");
97
+ const bucket = slash === -1 ? rest : rest.slice(0, slash);
98
+ const prefix = slash === -1 ? "" : rest.slice(slash + 1).replace(/\/+$/, "");
99
+ if (!bucket)
100
+ fail("GITVAULT_MIRROR_DESTINATION_INVALID", `${url} names no bucket`, "parsing gitvault mirror destination", { url });
101
+ const region = options.region ?? process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION;
102
+ if (!region)
103
+ fail("GITVAULT_MIRROR_REGION_REQUIRED", `an s3 destination needs a region — pass --region or set AWS_REGION`, "parsing gitvault mirror destination", { url });
104
+ return { kind: "s3", bucket, prefix, region, ...(options.endpoint ? { endpoint: options.endpoint } : {}) };
105
+ }
106
+ return { kind: "directory", path: url };
107
+ }
108
+ /** Render a destination back to the address form a human typed (for `status`/errors). */
109
+ export function formatMirrorDestination(destination) {
110
+ return destination.kind === "s3" ? `s3://${destination.bucket}/${destination.prefix}` : destination.path;
111
+ }
112
+ //# sourceMappingURL=gitvault-mirror-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitvault-mirror-config.js","sourceRoot":"","sources":["../../src/node/gitvault-mirror-config.ts"],"names":[],"mappings":"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"}