run402 4.66.1 → 4.67.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 (41) hide show
  1. package/README.md +4 -2
  2. package/gitvault-surface.json +10 -2
  3. package/lib/cold-start.mjs +77 -0
  4. package/lib/command-manifest.mjs +6 -1
  5. package/lib/doctor.mjs +10 -0
  6. package/lib/gitvault-capabilities.mjs +12 -0
  7. package/lib/org-context.mjs +26 -0
  8. package/lib/path-lookup.mjs +24 -0
  9. package/lib/path-lookup.test.mjs +66 -0
  10. package/lib/repos.mjs +307 -10
  11. package/lib/rooms-context.mjs +17 -1
  12. package/package.json +1 -1
  13. package/sdk/dist/errors.d.ts +1 -1
  14. package/sdk/dist/errors.d.ts.map +1 -1
  15. package/sdk/dist/errors.js.map +1 -1
  16. package/sdk/dist/namespaces/gitvault.d.ts +131 -4
  17. package/sdk/dist/namespaces/gitvault.d.ts.map +1 -1
  18. package/sdk/dist/namespaces/gitvault.js +268 -8
  19. package/sdk/dist/namespaces/gitvault.js.map +1 -1
  20. package/sdk/dist/node/gitvault-address.d.ts +2 -0
  21. package/sdk/dist/node/gitvault-address.d.ts.map +1 -1
  22. package/sdk/dist/node/gitvault-address.js +13 -2
  23. package/sdk/dist/node/gitvault-address.js.map +1 -1
  24. package/sdk/dist/node/gitvault-handoff.d.ts +111 -0
  25. package/sdk/dist/node/gitvault-handoff.d.ts.map +1 -0
  26. package/sdk/dist/node/gitvault-handoff.js +277 -0
  27. package/sdk/dist/node/gitvault-handoff.js.map +1 -0
  28. package/sdk/dist/node/gitvault-keystore.d.ts +1 -1
  29. package/sdk/dist/node/gitvault-keystore.d.ts.map +1 -1
  30. package/sdk/dist/node/gitvault-restore.d.ts +46 -0
  31. package/sdk/dist/node/gitvault-restore.d.ts.map +1 -0
  32. package/sdk/dist/node/gitvault-restore.js +123 -0
  33. package/sdk/dist/node/gitvault-restore.js.map +1 -0
  34. package/sdk/dist/node/gitvault-snapshot.d.ts +87 -0
  35. package/sdk/dist/node/gitvault-snapshot.d.ts.map +1 -1
  36. package/sdk/dist/node/gitvault-snapshot.js +216 -11
  37. package/sdk/dist/node/gitvault-snapshot.js.map +1 -1
  38. package/sdk/dist/node/index.d.ts +6 -2
  39. package/sdk/dist/node/index.d.ts.map +1 -1
  40. package/sdk/dist/node/index.js +8 -1
  41. package/sdk/dist/node/index.js.map +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitvault-handoff.d.ts","sourceRoot":"","sources":["../../src/node/gitvault-handoff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,277 @@
1
+ /**
2
+ * gitvault — the Handoff Key (kygit-handoff design D3/D6/D10).
3
+ *
4
+ * A Handoff Key is a bearer bridge, never a K_repo derivation of its own:
5
+ * `kgh1_<base64url(handoff_id[16] || master_secret[32])>` (69 chars). Two
6
+ * HKDF-SHA-256 derivations off `master_secret` (salt = the 16 raw
7
+ * `handoff_id` bytes) produce `auth_secret` (what the gateway hashes and
8
+ * compares) and `wrap_key` (what seals/opens the small envelope carrying
9
+ * the vault's epoch key `k_e` directly — the gateway never sees either).
10
+ *
11
+ * The prefix is a REGISTRY (design D9 rule 4): `kgh1_` is the first row.
12
+ * `parseHandoffKey` refuses any other recognized-shape-but-wrong-kind
13
+ * prefix BY NAME, pointing at its own verb, rather than misreading it as a
14
+ * malformed handoff key.
15
+ *
16
+ * Reuses ONLY existing primitives — `jcs`/HKDF/HMAC/SHA-256 from
17
+ * `@noble/hashes`, the SAME `_gitvaultAeadBackend()` XChaCha20-Poly1305
18
+ * seam `sealFrame`/`openFrame` use — never a second crypto path. The wire
19
+ * envelope here is a DIFFERENT, smaller frame than `r402s/v0`'s seven-member
20
+ * object frame (design D3: "the sealed envelope lives in the gateway ROW,
21
+ * never in the vault object store — the frozen r402s/v0 protocol is
22
+ * untouched"), so it gets its own tiny header/AAD rather than reusing
23
+ * `frameAad`'s object-store-shaped seven fields.
24
+ */
25
+ import { hkdf } from "@noble/hashes/hkdf.js";
26
+ import { sha256 } from "@noble/hashes/sha2.js";
27
+ import { concatBytes, utf8ToBytes } from "@noble/hashes/utils.js";
28
+ import { xchacha20poly1305 } from "@noble/ciphers/chacha.js";
29
+ import { LocalError } from "../errors.js";
30
+ import { _gitvaultAeadBackend, fromBase64url, randomBytes, sha256Hex, toBase64url } from "../namespaces/gitvault.crypto.js";
31
+ function fail(code, message, context, details) {
32
+ throw new LocalError(message, context, { code, details });
33
+ }
34
+ /** `kgh1_` is the first row. A future `kgi1_` (KyGit Invite) is a SIBLING row here, never a branch on this one's parser. */
35
+ export const HANDOFF_KEY_PREFIXES = [{ prefix: "kgh1_", kind: "handoff", verb: "resume" }];
36
+ const HANDOFF_ID_BYTES = 16;
37
+ const MASTER_SECRET_BYTES = 32;
38
+ const HANDOFF_KEY_BODY_BYTES = HANDOFF_ID_BYTES + MASTER_SECRET_BYTES;
39
+ function bytesToUuid(bytes) {
40
+ const h = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
41
+ return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20)}`;
42
+ }
43
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
44
+ export function uuidToBytes(uuid, field = "handoff_id") {
45
+ if (!UUID_RE.test(uuid))
46
+ fail("HANDOFF_ID_INVALID", `${field} is not a canonical UUID`, "parsing handoff id", { field });
47
+ const hex = uuid.replace(/-/g, "").toLowerCase();
48
+ const out = new Uint8Array(16);
49
+ for (let i = 0; i < 16; i++)
50
+ out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
51
+ return out;
52
+ }
53
+ /**
54
+ * Assemble the printed key from a fresh 32-byte master secret and the
55
+ * gateway-minted `handoff_id`. The gateway never sees `master_secret` — the
56
+ * caller derives `auth_hash` (via {@link deriveHandoffSecrets}) and sends
57
+ * ONLY that.
58
+ */
59
+ export function assembleHandoffKey(handoffId, masterSecret = randomBytes(MASTER_SECRET_BYTES)) {
60
+ if (masterSecret.length !== MASTER_SECRET_BYTES)
61
+ fail("HANDOFF_KEY_INVALID", "master_secret must be 32 bytes", "assembling handoff key");
62
+ const idBytes = uuidToBytes(handoffId);
63
+ const body = concatBytes(idBytes, masterSecret);
64
+ return { key: `kgh1_${toBase64url(body)}`, handoff_id_bytes: idBytes, master_secret: masterSecret };
65
+ }
66
+ /**
67
+ * Parse ANY `kg**_` handoff-family key by its prefix registry. A recognized
68
+ * prefix of a DIFFERENT kind (a future `kgi1_` invite key handed to
69
+ * `resume`) refuses BY NAME pointing at its own verb — never misread as a
70
+ * malformed handoff key (design D9 rule 4).
71
+ */
72
+ export function parseHandoffKey(raw) {
73
+ const trimmed = raw.trim();
74
+ const entry = HANDOFF_KEY_PREFIXES.find((e) => trimmed.startsWith(e.prefix));
75
+ if (!entry) {
76
+ // A recognized SIBLING prefix (future kind) would be matched here once
77
+ // it joins the registry; today only `kgh1_` is registered, so any
78
+ // non-matching prefix is a plain invalid key.
79
+ fail("HANDOFF_KEY_INVALID", "not a recognized kygit key (expected a key starting kgh1_)", "parsing handoff key");
80
+ }
81
+ if (entry.kind !== "handoff") {
82
+ fail("HANDOFF_KEY_WRONG_KIND", `this key is a ${entry.kind} key — use \`kygit ${entry.verb}\` instead of resume`, "parsing handoff key", { kind: entry.kind, verb: entry.verb });
83
+ }
84
+ const body = trimmed.slice(entry.prefix.length);
85
+ let bytes;
86
+ try {
87
+ bytes = fromBase64url(body, "handoff key body");
88
+ }
89
+ catch {
90
+ fail("HANDOFF_KEY_INVALID", "the key body is not valid base64url", "parsing handoff key");
91
+ }
92
+ if (bytes.length !== HANDOFF_KEY_BODY_BYTES) {
93
+ fail("HANDOFF_KEY_INVALID", `the key decodes to ${bytes.length} bytes; expected ${HANDOFF_KEY_BODY_BYTES}`, "parsing handoff key");
94
+ }
95
+ const idBytes = bytes.subarray(0, HANDOFF_ID_BYTES);
96
+ const masterSecret = bytes.subarray(HANDOFF_ID_BYTES);
97
+ return { kind: "handoff", handoff_id_bytes: idBytes, handoff_id: bytesToUuid(idBytes), master_secret: masterSecret };
98
+ }
99
+ // ─── HKDF derivations (design D3) ────────────────────────────────────────────
100
+ const HANDOFF_AUTH_INFO = "kygit/handoff/auth/v1";
101
+ const HANDOFF_WRAP_INFO = "kygit/handoff/wrap/v1";
102
+ const HANDOFF_AUTH_HASH_LABEL = "kygit/handoff/auth-hash/v1";
103
+ /** `HKDF-SHA256(ikm=master_secret, salt=handoff_id[16], info=…)` per D3, for both `auth_secret` and `wrap_key`. */
104
+ export function deriveHandoffSecrets(handoffIdBytes, masterSecret) {
105
+ const authSecret = hkdf(sha256, masterSecret, handoffIdBytes, utf8ToBytes(HANDOFF_AUTH_INFO), 32);
106
+ const wrapKey = hkdf(sha256, masterSecret, handoffIdBytes, utf8ToBytes(HANDOFF_WRAP_INFO), 32);
107
+ const authHash = sha256(concatBytes(utf8ToBytes(HANDOFF_AUTH_HASH_LABEL), authSecret));
108
+ return { auth_secret: authSecret, wrap_key: wrapKey, auth_hash_hex: sha256Hex(authHash) };
109
+ }
110
+ /** Frame tag for this envelope format — DISTINCT from `r402s/v0`'s `"R402S0"` object frame (design D3: never stored as a vault object). */
111
+ export const HANDOFF_ENVELOPE_KIND = "kygit-handoff-envelope-v1";
112
+ const HANDOFF_FRAME_MAGIC = "KGH1";
113
+ const HANDOFF_FRAME_MAGIC_BYTES = 4;
114
+ const HANDOFF_FRAME_VERSION_BYTE = 0x01;
115
+ const HANDOFF_NONCE_BYTES = 24;
116
+ const HANDOFF_FRAME_HEADER_BYTES = HANDOFF_FRAME_MAGIC_BYTES + 1 + HANDOFF_NONCE_BYTES;
117
+ function handoffAeadSeal(key32, nonce24, aad, plaintext) {
118
+ const backend = _gitvaultAeadBackend();
119
+ if (backend)
120
+ return backend.seal(key32, nonce24, aad, plaintext);
121
+ return xchacha20poly1305(key32, nonce24, aad).encrypt(plaintext);
122
+ }
123
+ function handoffAeadOpen(key32, nonce24, aad, ctAndTag) {
124
+ try {
125
+ const backend = _gitvaultAeadBackend();
126
+ if (backend)
127
+ return backend.open(key32, nonce24, aad, ctAndTag);
128
+ return xchacha20poly1305(key32, nonce24, aad).decrypt(ctAndTag);
129
+ }
130
+ catch {
131
+ return null;
132
+ }
133
+ }
134
+ /** AAD = `handoff_id[16] ‖ kind` (design D3) — `kind` is this envelope format's own tag, UTF-8. */
135
+ function handoffEnvelopeAad(handoffIdBytes, envelopeKind) {
136
+ return concatBytes(handoffIdBytes, utf8ToBytes(envelopeKind));
137
+ }
138
+ /** Seal the handoff payload under `wrap_key`. Returns the base64url wire form + its declared kind tag. */
139
+ export function sealHandoffEnvelope(handoffIdBytes, wrapKey, payload, nonce) {
140
+ // Plain JSON, NOT the r402s/v0 no-JSON-numbers JCS profile: this envelope
141
+ // is never a vault object and only this SDK ever encodes/decodes it, so
142
+ // it needs deterministic round-tripping, not cross-implementation
143
+ // byte-canonical determinism (design D3's "the frozen protocol is
144
+ // untouched" — reusing the object-frame profile here would be exactly
145
+ // the kind of accidental protocol coupling that note warns against).
146
+ const plaintext = utf8ToBytes(JSON.stringify(payload));
147
+ const n = nonce ?? randomBytes(HANDOFF_NONCE_BYTES);
148
+ if (n.length !== HANDOFF_NONCE_BYTES)
149
+ fail("HANDOFF_ENVELOPE_INVALID", "nonce must be 24 bytes", "sealing handoff envelope");
150
+ const aad = handoffEnvelopeAad(handoffIdBytes, HANDOFF_ENVELOPE_KIND);
151
+ const ct = handoffAeadSeal(wrapKey, n, aad, plaintext);
152
+ const frame = concatBytes(utf8ToBytes(HANDOFF_FRAME_MAGIC), new Uint8Array([HANDOFF_FRAME_VERSION_BYTE]), n, ct);
153
+ return { sealed_envelope: toBase64url(frame), envelope_kind: HANDOFF_ENVELOPE_KIND };
154
+ }
155
+ /** Open a sealed handoff envelope under `wrap_key`. Throws `HANDOFF_ENVELOPE_INVALID` on any header mismatch and `HANDOFF_AEAD_AUTH_FAILURE` on a bad key/AAD/ciphertext. */
156
+ export function openHandoffEnvelope(handoffIdBytes, wrapKey, sealedEnvelopeB64u, envelopeKind = HANDOFF_ENVELOPE_KIND) {
157
+ let frame;
158
+ try {
159
+ frame = fromBase64url(sealedEnvelopeB64u, "sealed_envelope");
160
+ }
161
+ catch {
162
+ fail("HANDOFF_ENVELOPE_INVALID", "sealed_envelope is not valid base64url", "opening handoff envelope");
163
+ }
164
+ if (frame.length < HANDOFF_FRAME_HEADER_BYTES + 16) {
165
+ fail("HANDOFF_ENVELOPE_INVALID", "sealed_envelope is shorter than header + AEAD tag", "opening handoff envelope");
166
+ }
167
+ const magic = new TextDecoder().decode(frame.subarray(0, HANDOFF_FRAME_MAGIC_BYTES));
168
+ if (magic !== HANDOFF_FRAME_MAGIC || frame[HANDOFF_FRAME_MAGIC_BYTES] !== HANDOFF_FRAME_VERSION_BYTE) {
169
+ fail("HANDOFF_ENVELOPE_INVALID", "sealed_envelope header magic/version mismatch", "opening handoff envelope");
170
+ }
171
+ const nonce = frame.subarray(HANDOFF_FRAME_MAGIC_BYTES + 1, HANDOFF_FRAME_HEADER_BYTES);
172
+ const ct = frame.subarray(HANDOFF_FRAME_HEADER_BYTES);
173
+ const aad = handoffEnvelopeAad(handoffIdBytes, envelopeKind);
174
+ const opened = handoffAeadOpen(wrapKey, nonce, aad, ct);
175
+ if (opened === null)
176
+ fail("HANDOFF_AEAD_AUTH_FAILURE", "the sealed envelope failed AEAD authentication under this key", "opening handoff envelope");
177
+ let payload;
178
+ try {
179
+ payload = JSON.parse(new TextDecoder().decode(opened));
180
+ }
181
+ catch {
182
+ fail("HANDOFF_ENVELOPE_INVALID", "opened envelope is not valid JSON", "opening handoff envelope");
183
+ }
184
+ const p = payload;
185
+ if (p.v !== 1 || p.kind !== "handoff" || typeof p.repo_id !== "string" || typeof p.epoch !== "string" || typeof p.k_e_hex !== "string" || !p.checkpoint || p.note_schema !== "kygit.handoff-note.v1") {
186
+ fail("HANDOFF_ENVELOPE_INVALID", "opened envelope does not match the kygit.handoff-note.v1 payload shape", "opening handoff envelope");
187
+ }
188
+ return p;
189
+ }
190
+ export function isKygitHandoffNote(value) {
191
+ if (!value || typeof value !== "object")
192
+ return false;
193
+ const v = value;
194
+ return v.schema === "kygit.handoff-note.v1" && typeof v.summary === "string" && typeof v.created_at === "string" && !!v.from && !!v.capture;
195
+ }
196
+ // ─── Client-side secret scan (design D10 — no override flag) ────────────────
197
+ const HANDOFF_NOTE_SECRET_PREFIXES = [
198
+ /\bsk-[A-Za-z0-9]/,
199
+ /\bghp_[A-Za-z0-9]/,
200
+ /\bgho_[A-Za-z0-9]/,
201
+ /\bxox[abp]-[A-Za-z0-9]/,
202
+ /\bAKIA[A-Z0-9]{4,}/,
203
+ /-----BEGIN [A-Z ]*PRIVATE KEY-----/,
204
+ /-----BEGIN [A-Z ]*CERTIFICATE-----/,
205
+ /\bkgh1_[A-Za-z0-9_-]/,
206
+ ];
207
+ /** Shannon entropy in bits/char over `s`. */
208
+ function shannonEntropy(s) {
209
+ const counts = new Map();
210
+ for (const ch of s)
211
+ counts.set(ch, (counts.get(ch) ?? 0) + 1);
212
+ let entropy = 0;
213
+ for (const count of counts.values()) {
214
+ const p = count / s.length;
215
+ entropy -= p * Math.log2(p);
216
+ }
217
+ return entropy;
218
+ }
219
+ /** A run of ≥32 token-ish chars (letters/digits/`+/=_-`) with high per-char entropy reads as a bare secret, not prose. */
220
+ function hasHighEntropyToken(text) {
221
+ const tokenRe = /[A-Za-z0-9+/_=-]{32,}/g;
222
+ let m;
223
+ while ((m = tokenRe.exec(text))) {
224
+ const token = m[0];
225
+ if (shannonEntropy(token) >= 3.5)
226
+ return token;
227
+ }
228
+ return null;
229
+ }
230
+ /** Every string leaf in the note, `path` = dotted field name for the refusal. */
231
+ function* noteStringLeaves(note) {
232
+ yield { path: "summary", text: note.summary };
233
+ for (const [group, arr] of [
234
+ ["completed", note.completed],
235
+ ["in_progress", note.in_progress],
236
+ ["failing", note.failing],
237
+ ["tried", note.tried],
238
+ ["next_steps", note.next_steps],
239
+ ["decisions", note.decisions],
240
+ ["open_questions", note.open_questions],
241
+ ]) {
242
+ for (const [i, text] of (arr ?? []).entries())
243
+ yield { path: `${group}[${i}]`, text };
244
+ }
245
+ if (note.commands) {
246
+ for (const key of ["test", "build", "run"]) {
247
+ const v = note.commands[key];
248
+ if (v)
249
+ yield { path: `commands.${key}`, text: v };
250
+ }
251
+ }
252
+ }
253
+ /**
254
+ * Refuse a note that carries a bare secret — no override flag exists
255
+ * (design D10): a note is read by another agent, and secrets have the
256
+ * secrets API. `null` when the note is clean.
257
+ */
258
+ export function scanHandoffNoteForSecrets(note) {
259
+ for (const { path, text } of noteStringLeaves(note)) {
260
+ for (const re of HANDOFF_NOTE_SECRET_PREFIXES) {
261
+ if (re.test(text))
262
+ return { field: path, reason: `matches a known secret prefix (${re.source})` };
263
+ }
264
+ const token = hasHighEntropyToken(text);
265
+ if (token)
266
+ return { field: path, reason: `contains a high-entropy token (${token.length} chars) that reads as a bare secret` };
267
+ }
268
+ return null;
269
+ }
270
+ /** Throws `HANDOFF_NOTE_CONTAINS_SECRET` naming the field — call before the handoff commit is written. */
271
+ export function assertHandoffNoteHasNoSecret(note) {
272
+ const finding = scanHandoffNoteForSecrets(note);
273
+ if (finding) {
274
+ fail("HANDOFF_NOTE_CONTAINS_SECRET", `the handoff note's \`${finding.field}\` ${finding.reason} — edit the note; secrets belong in the secrets API, never in a note another agent will read`, "scanning handoff note", { field: finding.field });
275
+ }
276
+ }
277
+ //# sourceMappingURL=gitvault-handoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitvault-handoff.js","sourceRoot":"","sources":["../../src/node/gitvault-handoff.ts"],"names":[],"mappings":"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"}
@@ -145,7 +145,7 @@ export interface GitvaultRepoFile {
145
145
  /** The last ref transaction this principal published (5.4 fills it). */
146
146
  last_ref_transaction: Record<string, unknown> | null;
147
147
  /** How this file came to exist — creation, or a §5.1 restore from the principal's own envelope. */
148
- provenance: "created" | "restored_from_envelope";
148
+ provenance: "created" | "restored_from_envelope" | "restored_from_handoff";
149
149
  updated_at: string;
150
150
  }
151
151
  /** One `audit.log` line. */
@@ -1 +1 @@
1
- {"version":3,"file":"gitvault-keystore.d.ts","sourceRoot":"","sources":["../../src/node/gitvault-keystore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gitvault-keystore.d.ts","sourceRoot":"","sources":["../../src/node/gitvault-keystore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * `git clone --no-checkout <remoteUrl> <targetDir>` — protocol-permitting
3
+ * (this is the one gitvault git invocation allowed to touch the network),
4
+ * hooks and terminal prompts still neutralized. `targetDir` must not
5
+ * already exist (git's own clone precondition).
6
+ */
7
+ export declare function cloneGitvaultRemote(remoteUrl: string, targetDir: string): Promise<void>;
8
+ export interface GitvaultHandoffRestoreOptions {
9
+ /** The freshly cloned repository. */
10
+ dir: string;
11
+ /** The stash-shaped commit oid (design D1) — must already be reachable in `dir`'s object database (a retention root, materialized by clone). */
12
+ stash_oid: string;
13
+ /**
14
+ * `<stash_oid>`'s first parent (design D1's `base_head_oid`). When
15
+ * omitted it is read directly off the commit (`git rev-parse
16
+ * <stash_oid>^1`) — the object already carries it, so a caller resuming
17
+ * from the sealed envelope's `checkpoint.commit_oid` alone needs no
18
+ * second value to agree with it.
19
+ */
20
+ base_head_oid?: string;
21
+ /** The vault's default branch name (e.g. from the head symref, stripped of `refs/heads/`). Read from the fresh clone's `HEAD` symref when omitted; falls back to `main`. */
22
+ branch_hint?: string | null;
23
+ }
24
+ export interface GitvaultHandoffRestoreResult {
25
+ branch: string;
26
+ base_head_oid: string;
27
+ stash_oid: string;
28
+ }
29
+ /**
30
+ * Check out the base, land on a real branch (never left detached), then
31
+ * `git stash apply --index <stash_oid>` — staged, unstaged, deleted, and
32
+ * untracked changes come back distinctly (verified against real git 2.43
33
+ * plumbing during design). Every step here is LOCAL — no network — so it
34
+ * runs fully hardened.
35
+ */
36
+ export declare function applyHandoffCheckpoint(options: GitvaultHandoffRestoreOptions): Promise<GitvaultHandoffRestoreResult>;
37
+ /**
38
+ * `--to <dir>` wins; otherwise the vault's address-form name (`org/name` →
39
+ * `name`) when the claim response carried one, otherwise the vault id.
40
+ * Always absolute — `cloneGitvaultRemote` runs in `tmpdir()`, so a
41
+ * relative destination must be resolved against the CALLER's cwd first.
42
+ */
43
+ export declare function resolveResumeTargetDir(to: string | undefined, address: string | null | undefined, vaultId: string): string;
44
+ /** The commit message (the Handoff Note, verbatim) — `null` when `oid` cannot be read (e.g. not yet present). */
45
+ export declare function readGitCommitMessage(dir: string, oid: string): Promise<string | null>;
46
+ //# sourceMappingURL=gitvault-restore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitvault-restore.d.ts","sourceRoot":"","sources":["../../src/node/gitvault-restore.ts"],"names":[],"mappings":"AA2CA;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBvF;AAED,MAAM,WAAW,6BAA6B;IAC5C,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,gJAAgJ;IAChJ,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4KAA4K;IAC5K,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,6BAA6B,GAAG,OAAO,CAAC,4BAA4B,CAAC,CA4B1H;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAI1H;AAED,iHAAiH;AACjH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAM3F"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * gitvault — handoff restore (kygit-handoff design D1/D10).
3
+ *
4
+ * Restore is porcelain git, in two stages that deliberately run through
5
+ * DIFFERENT runners:
6
+ *
7
+ * 1. `git clone <remote-url> <dir>` — a REAL network operation (the vault
8
+ * is reached through the `git-remote-run402`/`git-remote-kygit` remote
9
+ * helper), so it must NOT run under `hardenedGit`'s
10
+ * `-c protocol.allow=never` (that flag exists to keep LOCAL plumbing
11
+ * calls — hash-object, commit-tree, write-tree — from ever touching
12
+ * the network by accident; a clone is the one call in this whole
13
+ * module that is SUPPOSED to). `--no-checkout` so nothing in the
14
+ * target directory's initial default-branch checkout can fire a
15
+ * template-installed hook before step 2 neutralizes hooks.
16
+ * 2. Every LOCAL-only step after that (checkout the base, apply the
17
+ * stash-shaped commit) runs through {@link hardenedGit} exactly like
18
+ * every other gitvault plumbing call — hooks, fsmonitor, and replace
19
+ * refs all disabled, argv-only, no shell.
20
+ *
21
+ * The handoff commit ITSELF needs no separate fetch: it is a `retention
22
+ * root` (design D6), and `restoreObjectsInto` — what the remote helper's
23
+ * `fetch` verb runs on every clone — materializes the vault's FULL
24
+ * retained object set, not just ref-reachable history. By the time step 1
25
+ * finishes, `<oid>` is already a loose object in the fresh clone's ODB.
26
+ */
27
+ import { execFile } from "node:child_process";
28
+ import { mkdtempSync } from "node:fs";
29
+ import { tmpdir } from "node:os";
30
+ import { isAbsolute, join, resolve } from "node:path";
31
+ import { LocalError } from "../errors.js";
32
+ import { hardenedGit, hardenedGitEnv } from "./gitvault-snapshot.js";
33
+ function fail(code, message, context, details) {
34
+ throw new LocalError(message, context, { code, details });
35
+ }
36
+ let emptyCloneHooksDir = null;
37
+ function cloneHooksDir() {
38
+ emptyCloneHooksDir ??= mkdtempSync(join(tmpdir(), "run402-gitvault-resume-clone-nohooks-"));
39
+ return emptyCloneHooksDir;
40
+ }
41
+ /**
42
+ * `git clone --no-checkout <remoteUrl> <targetDir>` — protocol-permitting
43
+ * (this is the one gitvault git invocation allowed to touch the network),
44
+ * hooks and terminal prompts still neutralized. `targetDir` must not
45
+ * already exist (git's own clone precondition).
46
+ */
47
+ export function cloneGitvaultRemote(remoteUrl, targetDir) {
48
+ return new Promise((resolvePromise, reject) => {
49
+ const argv = ["--no-replace-objects", "-c", `core.hooksPath=${cloneHooksDir()}`, "clone", "--no-checkout", "--", remoteUrl, targetDir];
50
+ execFile("git", argv, { cwd: tmpdir(), env: hardenedGitEnv(), encoding: "buffer", maxBuffer: 1024 * 1024 * 1024, windowsHide: true }, (error, _stdout, stderr) => {
51
+ if (error) {
52
+ const stderrText = Buffer.from(stderr).toString("utf8");
53
+ reject(new LocalError(`git clone ${remoteUrl} failed: ${stderrText.trim().slice(0, 1000) || error.message}`, "cloning the vault for resume", { code: "HANDOFF_CLONE_FAILED", details: { remote_url: remoteUrl, target_dir: targetDir, stderr: stderrText.slice(0, 2000) } }));
54
+ return;
55
+ }
56
+ resolvePromise();
57
+ });
58
+ });
59
+ }
60
+ function sanitizeBranchName(name) {
61
+ return name && /^[A-Za-z0-9._/-]+$/.test(name) && !name.startsWith("-") ? name : null;
62
+ }
63
+ /**
64
+ * Check out the base, land on a real branch (never left detached), then
65
+ * `git stash apply --index <stash_oid>` — staged, unstaged, deleted, and
66
+ * untracked changes come back distinctly (verified against real git 2.43
67
+ * plumbing during design). Every step here is LOCAL — no network — so it
68
+ * runs fully hardened.
69
+ */
70
+ export async function applyHandoffCheckpoint(options) {
71
+ const { dir } = options;
72
+ let baseHeadOid = options.base_head_oid ?? null;
73
+ if (!baseHeadOid) {
74
+ try {
75
+ baseHeadOid = (await hardenedGit(dir, ["rev-parse", "--verify", `${options.stash_oid}^1`])).text().trim();
76
+ }
77
+ catch (e) {
78
+ fail("HANDOFF_RESTORE_APPLY_FAILED", `could not read the base commit (first parent) off ${options.stash_oid} — it may not be present in the clone yet`, "restoring the handoff checkpoint", { stash_oid: options.stash_oid, cause: e instanceof Error ? e.message : String(e) });
79
+ }
80
+ }
81
+ let branch = sanitizeBranchName(options.branch_hint);
82
+ if (!branch) {
83
+ try {
84
+ const symref = (await hardenedGit(dir, ["symbolic-ref", "-q", "--short", "HEAD"], { okStatuses: [1] })).text().trim();
85
+ branch = sanitizeBranchName(symref);
86
+ }
87
+ catch {
88
+ branch = null;
89
+ }
90
+ }
91
+ branch ??= "main";
92
+ await hardenedGit(dir, ["checkout", "-q", baseHeadOid]);
93
+ await hardenedGit(dir, ["checkout", "-q", "-B", branch]);
94
+ try {
95
+ await hardenedGit(dir, ["stash", "apply", "--index", options.stash_oid]);
96
+ }
97
+ catch (e) {
98
+ fail("HANDOFF_RESTORE_APPLY_FAILED", `\`git stash apply --index\` failed to reconstruct the handed-off state: ${e instanceof Error ? e.message : String(e)}`, "restoring the handoff checkpoint", { base_head_oid: baseHeadOid, stash_oid: options.stash_oid, cause: e instanceof Error ? e.message : String(e) });
99
+ }
100
+ return { branch, base_head_oid: baseHeadOid, stash_oid: options.stash_oid };
101
+ }
102
+ /**
103
+ * `--to <dir>` wins; otherwise the vault's address-form name (`org/name` →
104
+ * `name`) when the claim response carried one, otherwise the vault id.
105
+ * Always absolute — `cloneGitvaultRemote` runs in `tmpdir()`, so a
106
+ * relative destination must be resolved against the CALLER's cwd first.
107
+ */
108
+ export function resolveResumeTargetDir(to, address, vaultId) {
109
+ if (to)
110
+ return isAbsolute(to) ? to : resolve(process.cwd(), to);
111
+ const name = address ? address.split("/").pop() : null;
112
+ return resolve(process.cwd(), name || vaultId);
113
+ }
114
+ /** The commit message (the Handoff Note, verbatim) — `null` when `oid` cannot be read (e.g. not yet present). */
115
+ export async function readGitCommitMessage(dir, oid) {
116
+ try {
117
+ return (await hardenedGit(dir, ["log", "-1", "--format=%B", oid])).text().replace(/\n$/, "");
118
+ }
119
+ catch {
120
+ return null;
121
+ }
122
+ }
123
+ //# sourceMappingURL=gitvault-restore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitvault-restore.js","sourceRoot":"","sources":["../../src/node/gitvault-restore.ts"],"names":[],"mappings":"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"}
@@ -303,6 +303,93 @@ export declare function capturedSetUnchanged(drift: GitvaultCapturedSetDrift): b
303
303
  export declare function captureSnapshot(options: GitvaultSnapshotOptions): Promise<GitvaultSnapshot>;
304
304
  /** `git check-attr filter` over paths; returns every path whose `filter` attribute is set (LFS included). */
305
305
  export declare function detectActiveFilters(top: string, paths: string[]): Promise<GitvaultSnapshotRefusalPath[]>;
306
+ /**
307
+ * Sensitive untracked-path denylist (design D10, verbatim). Applies to the
308
+ * UNTRACKED set only — a tracked file is the user's own committed choice and
309
+ * is never filtered by this list. `--include-sensitive <glob>` re-admits a
310
+ * named path by matching the SAME glob grammar against the candidate.
311
+ */
312
+ export declare const GITVAULT_HANDOFF_SENSITIVE_DENYLIST: readonly string[];
313
+ /**
314
+ * A slash-free glob matches the path's BASENAME at any depth (gitignore's
315
+ * "no slash" rule). A glob ending `/**` (e.g. `.aws/**`) matches the named
316
+ * directory component at ANY depth in the tree, plus everything under it —
317
+ * a deliberately broader-than-gitignore reading for a credential-directory
318
+ * denylist, where over-excluding is the safe failure mode. Any other
319
+ * slash-bearing glob matches the full relative path exactly.
320
+ */
321
+ export declare function globMatchesGitPath(glob: string, relPath: string): boolean;
322
+ /** True iff `relPath` (an untracked-not-ignored path) matches the sensitive denylist and is not re-admitted by `includeSensitive`. */
323
+ export declare function isHandoffSensitivePath(relPath: string, includeSensitive?: readonly string[]): boolean;
324
+ /** What {@link GitvaultHandoffCaptureOptions.message} learns once capture figures are known — everything a Handoff Note's `capture` block needs, before the outer commit exists. */
325
+ export interface GitvaultHandoffCaptureStats {
326
+ base_head_oid: string;
327
+ /** `HEAD`'s symref name (`refs/heads/<branch>`, stripped) — `null` on a detached HEAD. */
328
+ branch: string | null;
329
+ modified_captured: string[];
330
+ untracked_captured: string[];
331
+ sensitive_excluded: string[];
332
+ ignored_not_transferred_count: number;
333
+ }
334
+ export interface GitvaultHandoffCaptureOptions {
335
+ /** The work tree (any directory inside it). */
336
+ dir: string;
337
+ env?: GitConfigDiscoveryEnv;
338
+ /**
339
+ * The outer commit's message (the Handoff Note). A plain string is used
340
+ * verbatim (the caller has already composed and secret-scanned it). A
341
+ * FUNCTION is called with the real capture figures right before the
342
+ * outer `commit-tree` — the one point at which a Handoff Note's
343
+ * `capture` block can be filled with true numbers, since the note (and
344
+ * the commit that carries it) cannot exist before those numbers are
345
+ * known. Throwing inside it (the client-side secret scan) aborts the
346
+ * capture before the outer commit is written; the two throwaway parent
347
+ * commits (index/untracked) are already unreachable garbage at that
348
+ * point, exactly as if the capture had never run.
349
+ */
350
+ message: string | ((stats: GitvaultHandoffCaptureStats) => string);
351
+ now?: () => Date;
352
+ /** Re-admit named untracked paths the sensitive denylist would otherwise exclude. */
353
+ includeSensitive?: string[];
354
+ }
355
+ /**
356
+ * A stash-shaped checkpoint (design D1): one synthetic commit, ALWAYS
357
+ * created (a clean tree still produces it — there is one shape, one code
358
+ * path). `oid`'s tree is the worktree state of TRACKED paths only; its
359
+ * three parents are `base_head_oid` (parent 1), `index_commit_oid` (parent
360
+ * 2, tree = the real index), and `untracked_commit_oid` (parent 3,
361
+ * parentless, tree = the admitted untracked set — the EMPTY tree when
362
+ * nothing untracked survives the denylist). Restore is `git clone` at
363
+ * `base_head_oid` then `git stash apply --index <oid>`.
364
+ */
365
+ export interface GitvaultHandoffSnapshot {
366
+ oid: string;
367
+ tree_oid: string;
368
+ base_head_oid: string;
369
+ index_commit_oid: string;
370
+ untracked_commit_oid: string;
371
+ head: GitvaultHeadTarget;
372
+ top_level: string;
373
+ /** Tracked paths whose on-disk content differs from `base_head_oid`'s tree (staged, unstaged, or both) and are present in `tree_oid`. */
374
+ modified_captured: string[];
375
+ /** Untracked-not-ignored paths admitted into `untracked_commit_oid`'s tree (denylist already applied). */
376
+ untracked_captured: string[];
377
+ /** Untracked-not-ignored paths excluded by the sensitive denylist (before any `includeSensitive` re-admission). */
378
+ sensitive_excluded: string[];
379
+ /** Ignored (gitignore/exclude) files present on disk — never transferred, counted only. */
380
+ ignored_not_transferred_count: number;
381
+ captured: GitvaultCapturedFile[];
382
+ captured_digest: string;
383
+ global_excludes_path: string | null;
384
+ }
385
+ /**
386
+ * Capture a stash-shaped handoff checkpoint. Reuses every hardened-execution
387
+ * guarantee `captureSnapshot` already provides (filter-free hashing, frozen
388
+ * ignore authority, refusal-by-name for conflicted/linked/submodule/sparse/
389
+ * shallow/LFS layouts) via {@link inspectRepository} + {@link
390
+ * detectActiveFilters}; the shape below is the ONLY thing new.
391
+ */
392
+ export declare function captureHandoffSnapshot(options: GitvaultHandoffCaptureOptions): Promise<GitvaultHandoffSnapshot>;
306
393
  /**
307
394
  * Check out `oid`'s tree into `targetDir` through a temporary index
308
395
  * (`read-tree` + `checkout-index`) — filter-free, hook-free, and isolated