@run402/sdk 4.39.1 → 4.41.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.
- package/README.md +4 -4
- package/dist/errors.d.ts +5 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/namespaces/gitvault.crypto.d.ts +10 -0
- package/dist/namespaces/gitvault.crypto.d.ts.map +1 -1
- package/dist/namespaces/gitvault.crypto.js +10 -0
- package/dist/namespaces/gitvault.crypto.js.map +1 -1
- package/dist/namespaces/gitvault.d.ts +285 -5
- package/dist/namespaces/gitvault.d.ts.map +1 -1
- package/dist/namespaces/gitvault.js +369 -8
- package/dist/namespaces/gitvault.js.map +1 -1
- package/dist/node/gitvault-apply.d.ts +1 -1
- package/dist/node/gitvault-apply.d.ts.map +1 -1
- package/dist/node/gitvault-apply.js +6 -6
- package/dist/node/gitvault-apply.js.map +1 -1
- package/dist/node/gitvault-creation-journal.js +1 -1
- package/dist/node/gitvault-creation-journal.js.map +1 -1
- package/dist/node/gitvault-deploy.js +2 -2
- package/dist/node/gitvault-deploy.js.map +1 -1
- package/dist/node/gitvault-keystore.d.ts +11 -1
- package/dist/node/gitvault-keystore.d.ts.map +1 -1
- package/dist/node/gitvault-keystore.js.map +1 -1
- package/dist/node/gitvault-mirror-backend.d.ts +88 -0
- package/dist/node/gitvault-mirror-backend.d.ts.map +1 -0
- package/dist/node/gitvault-mirror-backend.js +374 -0
- package/dist/node/gitvault-mirror-backend.js.map +1 -0
- package/dist/node/gitvault-mirror-config.d.ts +53 -0
- package/dist/node/gitvault-mirror-config.d.ts.map +1 -0
- package/dist/node/gitvault-mirror-config.js +112 -0
- package/dist/node/gitvault-mirror-config.js.map +1 -0
- package/dist/node/gitvault-mirror.d.ts +120 -0
- package/dist/node/gitvault-mirror.d.ts.map +1 -0
- package/dist/node/gitvault-mirror.js +464 -0
- package/dist/node/gitvault-mirror.js.map +1 -0
- package/dist/node/gitvault-publication.d.ts +153 -3
- package/dist/node/gitvault-publication.d.ts.map +1 -1
- package/dist/node/gitvault-publication.js +182 -13
- package/dist/node/gitvault-publication.js.map +1 -1
- package/dist/node/gitvault-recover.d.ts +136 -0
- package/dist/node/gitvault-recover.d.ts.map +1 -0
- package/dist/node/gitvault-recover.js +412 -0
- package/dist/node/gitvault-recover.js.map +1 -0
- package/dist/node/gitvault-snapshot.d.ts +8 -0
- package/dist/node/gitvault-snapshot.d.ts.map +1 -1
- package/dist/node/gitvault-snapshot.js +11 -0
- package/dist/node/gitvault-snapshot.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gitvault-mirror-and-recover — `r402s-recover`, the offline recovery engine
|
|
3
|
+
* (design D4/D5, tasks 3.1–3.5).
|
|
4
|
+
*
|
|
5
|
+
* Turns a mirrored `source/<repo_id>/` prefix (any {@link GitvaultMirrorBackend}
|
|
6
|
+
* — S3 or a local directory) plus a pin (the keystore's recovery receipt, or
|
|
7
|
+
* one supplied explicitly) into a working git repository, with NO SERVER
|
|
8
|
+
* INVOLVED: everything here reads from the {@link GitvaultMirrorBackend}
|
|
9
|
+
* alone. Only the decrypt/materialize step touches key material (design D5)
|
|
10
|
+
* — discovery, chain verification, and closure/absence adjudication run
|
|
11
|
+
* keylessly and are a first-class outcome on their own (`run402 gitvault
|
|
12
|
+
* mirror verify`), not a degraded mode of the keyed path.
|
|
13
|
+
*
|
|
14
|
+
* Reuses the SAME pure protocol functions the live SDK verifies pushes with
|
|
15
|
+
* ({@link checkChainLink}, {@link assertNoTransition}, {@link
|
|
16
|
+
* checkClaimSetEquality}, {@link gitvaultPaths}) — this file adds no new
|
|
17
|
+
* protocol semantics, exactly per the design doc's "recovery is the keyed
|
|
18
|
+
* offline subset of machinery that already exists."
|
|
19
|
+
*/
|
|
20
|
+
import { createHash } from "node:crypto";
|
|
21
|
+
import { mkdirSync } from "node:fs";
|
|
22
|
+
import { LocalError } from "../errors.js";
|
|
23
|
+
import { GITVAULT_GENESIS_EPOCH, GITVAULT_GENESIS_GENERATION, GITVAULT_MIRROR_KEYSTORE_STILL_REQUIRED_STATEMENT, GITVAULT_MIRROR_VALIDITY_NOT_FRESHNESS_STATEMENT, checkGenesisKeyBindings, checkRecoveryReceipt, deriveDigestKey, deriveObjectKey, generateEncryptionKeypair, hexToBytes, keyedCommitment, objectsetContent, openFrame, openKeyEnvelope, parseGitvaultStrict, verifyGitvaultObject, } from "../namespaces/gitvault.crypto.js";
|
|
24
|
+
import { assertNoTransition, checkChainLink, checkClaimSetEquality, gitvaultPaths, nextGeneration } from "./gitvault-publication.js";
|
|
25
|
+
import { GitvaultKeystore } from "./gitvault-keystore.js";
|
|
26
|
+
import { hardenedGit, hasObject } from "./gitvault-snapshot.js";
|
|
27
|
+
function fail(code, message, context, details, nextActions) {
|
|
28
|
+
throw new LocalError(message, context, { code, details, ...(nextActions ? { next_actions: nextActions } : {}) });
|
|
29
|
+
}
|
|
30
|
+
function sha256Hex(bytes) {
|
|
31
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* List `head/`, pin-check the genesis, and walk `prev_sha256` from genesis to
|
|
35
|
+
* the newest generation this mirror both HOLDS and can VERIFY. A signature or
|
|
36
|
+
* chain-link failure at generation K stops the walk at K-1 (`chain_break`
|
|
37
|
+
* names why); a generation simply absent from the mirror also stops the walk
|
|
38
|
+
* there, with `chain_break: null` (nothing further was ever pushed here, or
|
|
39
|
+
* hasn't been synced yet — not evidence of corruption).
|
|
40
|
+
*
|
|
41
|
+
* A PIN MISMATCH is the one hard, no-fallback refusal (`VAULT_CREATION_CONFLICT`):
|
|
42
|
+
* a substituted vault must never be silently accepted at "whatever chain
|
|
43
|
+
* verifies", because a substituted vault's own chain verifies perfectly
|
|
44
|
+
* against ITS OWN (different) creator key.
|
|
45
|
+
*/
|
|
46
|
+
export async function discoverAndVerifyChain(options) {
|
|
47
|
+
const { backend } = options;
|
|
48
|
+
const genesisBytes = await backend.get(gitvaultPaths.head(GITVAULT_GENESIS_GENERATION));
|
|
49
|
+
if (!genesisBytes)
|
|
50
|
+
fail("CHAIN_BROKEN", "the mirror holds no genesis (head/0000000000000000) — nothing to recover", "discovering gitvault vault from mirror", { destination: backend.describe() });
|
|
51
|
+
const genesis = parseGitvaultStrict(new TextDecoder().decode(genesisBytes));
|
|
52
|
+
if (genesis.object_kind !== "vault_genesis")
|
|
53
|
+
fail("CHAIN_BROKEN", "head/0000000000000000 is not a vault_genesis object", "discovering gitvault vault from mirror");
|
|
54
|
+
if (!verifyGitvaultObject(genesis, genesis.creator_signing_pubkey)) {
|
|
55
|
+
fail("GITVAULT_SIGNATURE_INVALID", "vault_genesis signature does not verify under its own claimed creator key", "discovering gitvault vault from mirror", { repo_id: genesis.repo_id });
|
|
56
|
+
}
|
|
57
|
+
const genesisSha = sha256Hex(genesisBytes);
|
|
58
|
+
const receipt = options.recovery_receipt ?? options.keystore?.readRecoveryReceipt(genesis.repo_id) ?? null;
|
|
59
|
+
let pinTrust = "unauthenticated_salvage";
|
|
60
|
+
if (receipt) {
|
|
61
|
+
const problems = checkRecoveryReceipt(receipt, genesis);
|
|
62
|
+
if (problems.length > 0) {
|
|
63
|
+
fail("VAULT_CREATION_CONFLICT", `the recovery receipt does not pin this mirror's genesis (${problems.join(", ")}) — this mirror may hold a SUBSTITUTED vault; refusing to recover from it`, "discovering gitvault vault from mirror", { repo_id: genesis.repo_id, problems, expected_genesis_sha256: receipt.genesis_sha256, observed_genesis_sha256: genesisSha }, [{ action: "verify the mirror destination and pin are the ones you intend — do not retry with a different receipt to make this pass" }]);
|
|
64
|
+
}
|
|
65
|
+
pinTrust = "receipt";
|
|
66
|
+
}
|
|
67
|
+
const chain = [];
|
|
68
|
+
let prevHash = genesisSha;
|
|
69
|
+
let prevGen = GITVAULT_GENESIS_GENERATION;
|
|
70
|
+
let chainBreak = null;
|
|
71
|
+
for (;;) {
|
|
72
|
+
const nextGen = nextGeneration(prevGen);
|
|
73
|
+
const bytes = await backend.get(gitvaultPaths.head(nextGen));
|
|
74
|
+
if (!bytes)
|
|
75
|
+
break; // natural end — the mirror holds nothing further at this generation
|
|
76
|
+
let head;
|
|
77
|
+
try {
|
|
78
|
+
head = parseGitvaultStrict(new TextDecoder().decode(bytes));
|
|
79
|
+
checkChainLink({
|
|
80
|
+
head, stored_bytes: bytes, listed_sha256: sha256Hex(bytes), expected_generation: nextGen, prev_sha256: prevHash,
|
|
81
|
+
repo_id: genesis.repo_id, writer_public_key: genesis.creator_signing_pubkey, writer_key_id: genesis.writer_key_id,
|
|
82
|
+
});
|
|
83
|
+
assertNoTransition(head);
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
chainBreak = { generation: nextGen, reason: e instanceof Error ? e.message : String(e) };
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
const headSha = sha256Hex(bytes);
|
|
90
|
+
chain.push({ generation: nextGen, head, head_sha256: headSha });
|
|
91
|
+
prevHash = headSha;
|
|
92
|
+
prevGen = nextGen;
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
repo_id: genesis.repo_id, genesis, genesis_sha256: genesisSha, pin_trust: pinTrust, chain,
|
|
96
|
+
newest_generation: prevGen, newest_head_sha256: prevHash, chain_break: chainBreak,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The required object set for one generation, resolved KEYLESSLY:
|
|
101
|
+
* `checkpoint_claim_set` is plaintext-structured (never encrypted, protocol
|
|
102
|
+
* §4.7) precisely so ITS ordered pack receipts enumerate every checkpoint
|
|
103
|
+
* pack + manifest id without decryption — closure resolution never needs a
|
|
104
|
+
* key. Walks back from `head` to the nearest checkpoint-bearing ancestor (or
|
|
105
|
+
* genesis) collecting each head's own carriers + WAL entries along the way.
|
|
106
|
+
*/
|
|
107
|
+
export async function closureForGeneration(backend, chain, targetGeneration) {
|
|
108
|
+
const byGen = new Map(chain.map((e) => [e.generation, e]));
|
|
109
|
+
const out = [];
|
|
110
|
+
let gen = targetGeneration;
|
|
111
|
+
for (;;) {
|
|
112
|
+
if (gen === GITVAULT_GENESIS_GENERATION)
|
|
113
|
+
break;
|
|
114
|
+
const entry = byGen.get(gen);
|
|
115
|
+
if (!entry)
|
|
116
|
+
fail("CHAIN_BROKEN", `generation ${gen} is not in the verified chain`, "resolving gitvault recovery closure", { generation: gen });
|
|
117
|
+
out.push({ key: gitvaultPaths.refState(entry.head.ref_state.object_id), object_id: entry.head.ref_state.object_id, kind: "ref_state" });
|
|
118
|
+
out.push({ key: gitvaultPaths.retentionRoots(entry.head.retention_roots.object_id), object_id: entry.head.retention_roots.object_id, kind: "retention_roots" });
|
|
119
|
+
if (entry.head.checkpoint) {
|
|
120
|
+
const claimSetId = entry.head.checkpoint.claim_set.object_id;
|
|
121
|
+
out.push({ key: gitvaultPaths.claimSet(claimSetId), object_id: claimSetId, kind: "checkpoint_claim_set" });
|
|
122
|
+
// The claim set's OWN content (plaintext-structured — no decryption)
|
|
123
|
+
// enumerates the manifest + every pack. Missing claim-set bytes stop
|
|
124
|
+
// enumeration here; the caller's adjudication loop reports it, and
|
|
125
|
+
// enumeration simply cannot go further without it (honest, not silent).
|
|
126
|
+
const claimBytes = await backend.get(gitvaultPaths.claimSet(claimSetId));
|
|
127
|
+
if (claimBytes) {
|
|
128
|
+
const claimSet = parseGitvaultStrict(new TextDecoder().decode(claimBytes));
|
|
129
|
+
out.push({ key: gitvaultPaths.checkpointManifest(claimSet.manifest_receipt.object_id), object_id: claimSet.manifest_receipt.object_id, kind: "checkpoint_manifest" });
|
|
130
|
+
for (const p of claimSet.ordered_pack_receipts)
|
|
131
|
+
out.push({ key: gitvaultPaths.checkpointPack(p.object_id), object_id: p.object_id, kind: "checkpoint_pack" });
|
|
132
|
+
}
|
|
133
|
+
break; // the checkpoint's recovery bundle is self-contained; no earlier WAL is needed
|
|
134
|
+
}
|
|
135
|
+
for (const w of entry.head.wal_entries)
|
|
136
|
+
out.push({ key: gitvaultPaths.wal(w.object_id), object_id: w.object_id, kind: "wal_pack" });
|
|
137
|
+
gen = generationMinusOne(gen);
|
|
138
|
+
}
|
|
139
|
+
return out;
|
|
140
|
+
}
|
|
141
|
+
function generationMinusOne(generation) {
|
|
142
|
+
return (BigInt(`0x${generation}`) - 1n).toString(16).padStart(16, "0");
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Check presence of every required object; for each ABSENT one, check the
|
|
146
|
+
* mirror's OWN stored `prune_intent` objects (plaintext-structured, keyless)
|
|
147
|
+
* for a delete-set entry naming it. Never a silent skip: every absence is
|
|
148
|
+
* adjudicated one way or the other, and the caller decides what to do with an
|
|
149
|
+
* `unexplained_absence` (typically: fall back one generation, see {@link
|
|
150
|
+
* recoverWithFallback}).
|
|
151
|
+
*/
|
|
152
|
+
export async function adjudicateAbsences(backend, required) {
|
|
153
|
+
const missing = [];
|
|
154
|
+
for (const r of required) {
|
|
155
|
+
const meta = await backend.head(r.key);
|
|
156
|
+
if (!meta)
|
|
157
|
+
missing.push(r);
|
|
158
|
+
}
|
|
159
|
+
if (missing.length === 0)
|
|
160
|
+
return [];
|
|
161
|
+
const pruneKeys = (await backend.list("prune/")).filter((k) => k.endsWith(".intent.json"));
|
|
162
|
+
const intents = [];
|
|
163
|
+
for (const key of pruneKeys) {
|
|
164
|
+
const bytes = await backend.get(key);
|
|
165
|
+
if (!bytes)
|
|
166
|
+
continue;
|
|
167
|
+
try {
|
|
168
|
+
const intent = parseGitvaultStrict(new TextDecoder().decode(bytes));
|
|
169
|
+
intents.push({ object_id: intent.object_id, delete_set: new Set((intent.core?.delete_set ?? []).map((d) => d.object_id)) });
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
/* an unreadable prune intent adjudicates nothing; the missing object stays unexplained */
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return missing.map((m) => {
|
|
176
|
+
const covering = intents.find((i) => i.delete_set.has(m.object_id));
|
|
177
|
+
return {
|
|
178
|
+
object_id: m.object_id, key: m.key,
|
|
179
|
+
adjudication: covering ? "intentionally_pruned" : "unexplained_absence",
|
|
180
|
+
prune_intent_object_id: covering?.object_id ?? null,
|
|
181
|
+
};
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Discovery + chain verification + closure/absence adjudication, WITHOUT
|
|
186
|
+
* touching any key material — `run402 gitvault mirror verify`. Reports the
|
|
187
|
+
* recoverable generation and an inventory; never decrypts, never
|
|
188
|
+
* materializes. A genuinely keyless integrity probe (design D5) — useful as a
|
|
189
|
+
* CI check that never needs a secret.
|
|
190
|
+
*/
|
|
191
|
+
export async function verifyGitvaultMirror(backend, options = {}) {
|
|
192
|
+
const discovery = await discoverAndVerifyChain({ backend, ...options });
|
|
193
|
+
const { generation, absences } = await resolveWithFallback(backend, discovery, { requireMaterializable: false });
|
|
194
|
+
const inventory = {};
|
|
195
|
+
if (generation !== GITVAULT_GENESIS_GENERATION) {
|
|
196
|
+
const required = await closureForGeneration(backend, discovery.chain, generation);
|
|
197
|
+
for (const r of required)
|
|
198
|
+
inventory[r.kind] = (inventory[r.kind] ?? 0) + 1;
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
repo_id: discovery.repo_id, genesis_sha256: discovery.genesis_sha256, pin_trust: discovery.pin_trust,
|
|
202
|
+
recovered_generation: generation, chain_break: discovery.chain_break, absences,
|
|
203
|
+
data_loss_detected: absences.some((a) => a.adjudication === "unexplained_absence"),
|
|
204
|
+
validity_not_freshness: GITVAULT_MIRROR_VALIDITY_NOT_FRESHNESS_STATEMENT,
|
|
205
|
+
keystore_still_required: GITVAULT_MIRROR_KEYSTORE_STILL_REQUIRED_STATEMENT,
|
|
206
|
+
mode: "keyless_verify", inventory,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
/** Try `discovery.newest_generation`, then fall back one generation at a time on `unexplained_absence`, recording every adjudication along the way (never a silent skip — task 3.2). */
|
|
210
|
+
async function resolveWithFallback(backend, discovery, options) {
|
|
211
|
+
const allAbsences = [];
|
|
212
|
+
let gen = discovery.newest_generation;
|
|
213
|
+
for (;;) {
|
|
214
|
+
if (gen === GITVAULT_GENESIS_GENERATION)
|
|
215
|
+
return { generation: gen, absences: allAbsences };
|
|
216
|
+
const required = await closureForGeneration(backend, discovery.chain, gen);
|
|
217
|
+
const absences = await adjudicateAbsences(backend, required);
|
|
218
|
+
allAbsences.push(...absences);
|
|
219
|
+
const unexplained = absences.filter((a) => a.adjudication === "unexplained_absence");
|
|
220
|
+
if (unexplained.length === 0)
|
|
221
|
+
return { generation: gen, absences: allAbsences };
|
|
222
|
+
if (!options.requireMaterializable) {
|
|
223
|
+
// Keyless verify still names the generation it landed on as the OLDEST
|
|
224
|
+
// one with no unexplained gap, same fallback the keyed path takes.
|
|
225
|
+
gen = generationMinusOne(gen);
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
gen = generationMinusOne(gen);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/** Open the recipient's key envelope for this genesis and decrypt K_repo — the ONE step in this whole file that touches key material. */
|
|
232
|
+
async function resolveKRepo(backend, genesis, keystore) {
|
|
233
|
+
const identity = keystore.readIdentity();
|
|
234
|
+
if (!identity?.encryption_private_key_hex) {
|
|
235
|
+
fail("VAULT_UNRECOVERABLE", "no encryption key in this keystore — recovery can verify and adjudicate but cannot decrypt or materialize anything", "materializing gitvault recovery", undefined, [
|
|
236
|
+
{ action: "restore the principal keystore (identity.json) from backup, then re-run recover" },
|
|
237
|
+
{ action: "run with --keyless (or `mirror verify`) for the verify-only outcome" },
|
|
238
|
+
]);
|
|
239
|
+
}
|
|
240
|
+
if (genesis.envelopes.length === 0)
|
|
241
|
+
fail("VAULT_CREATION_CONFLICT", "genesis carries no key envelope", "materializing gitvault recovery");
|
|
242
|
+
// Task 5.3 follow-up (gateway diagnosis confirmed 2026-08-26: a real vault
|
|
243
|
+
// can carry MORE than one key_envelope ledger row — a foreign recipient's
|
|
244
|
+
// envelope is the norm on a multi-recipient vault, never an anomaly). A
|
|
245
|
+
// genesis's own `envelopes[]` has always had exactly one entry so far (the
|
|
246
|
+
// creator's, minted at the six-stage creation — later reconcile-added
|
|
247
|
+
// envelopes are separate ledger rows, never appended to the SIGNED
|
|
248
|
+
// genesis), which is why blindly reading index 0 happened to be correct.
|
|
249
|
+
// SELECT BY FINGERPRINT EXPLICITLY instead of by position: this machine
|
|
250
|
+
// can only ever decrypt ITS OWN envelope (the recipient-only read gate
|
|
251
|
+
// means the mirror never even holds anyone else's — see
|
|
252
|
+
// `keyEnvelopeRecipientFingerprintFromKey`/`skipped_foreign_recipient` in
|
|
253
|
+
// `gitvault-mirror.ts`), so this function never looks for, and never fails
|
|
254
|
+
// on, a FOREIGN envelope being absent — that is silent-OK. A missing OWN
|
|
255
|
+
// envelope in genesis.envelopes (no entry matches our fingerprint at all)
|
|
256
|
+
// is its own distinct, honest refusal, separate from "the mirror never
|
|
257
|
+
// synced the bytes for an envelope genesis DOES name for us" below.
|
|
258
|
+
const envelopeReceipt = genesis.envelopes.find((e) => e.recipient_fingerprint === identity.encryption_fingerprint);
|
|
259
|
+
if (!envelopeReceipt) {
|
|
260
|
+
fail("GITVAULT_ENVELOPE_NOT_FOR_RECIPIENT", "genesis carries no key envelope for this machine's identity — this keystore is not a recipient of this vault", "materializing gitvault recovery", { own_fingerprint: identity.encryption_fingerprint });
|
|
261
|
+
}
|
|
262
|
+
// `key-envelopes/<epoch>/<recipient_fingerprint>.env` — the GATEWAY's real
|
|
263
|
+
// §3 wire key (`upload-sessions.ts` `UPLOADABLE_KINDS.key_envelope.key()`,
|
|
264
|
+
// mirrored by `storage-keys.ts` `objectKeyFor`), matching protocol §3
|
|
265
|
+
// exactly. The SDK's OWN `gitvault-creation-journal.ts` envelope `path`
|
|
266
|
+
// string (`envelopes/<epoch>/<fp>`) is a DIFFERENT, client-local label used
|
|
267
|
+
// only for the upload manifest ("never rides the wire") — the gateway
|
|
268
|
+
// derives its own key independently and never echoes that string back, so
|
|
269
|
+
// a mirror synced from the real objects listing never contains it.
|
|
270
|
+
const envelopeBytes = await backend.get(`key-envelopes/${envelopeReceipt.epoch}/${envelopeReceipt.recipient_fingerprint}.env`);
|
|
271
|
+
if (!envelopeBytes)
|
|
272
|
+
fail("VAULT_UNRECOVERABLE", "the mirror holds no key envelope for this genesis — cannot derive K_repo", "materializing gitvault recovery");
|
|
273
|
+
const envelope = parseGitvaultStrict(new TextDecoder().decode(envelopeBytes));
|
|
274
|
+
const bindingProblems = checkGenesisKeyBindings(genesis, envelope);
|
|
275
|
+
if (bindingProblems.length > 0)
|
|
276
|
+
fail("VAULT_CREATION_CONFLICT", `genesis key bindings do not hold for the stored envelope (${bindingProblems.join(", ")})`, "materializing gitvault recovery", { problems: bindingProblems });
|
|
277
|
+
if (envelope.recipient_fingerprint !== identity.encryption_fingerprint) {
|
|
278
|
+
fail("GITVAULT_ENVELOPE_NOT_FOR_RECIPIENT", "the stored envelope is addressed to another principal — this keystore cannot open it", "materializing gitvault recovery", { recipient_fingerprint: envelope.recipient_fingerprint });
|
|
279
|
+
}
|
|
280
|
+
const kp = generateEncryptionKeypair(hexToBytes(identity.encryption_private_key_hex));
|
|
281
|
+
return openKeyEnvelope({ envelope, recipient: kp, signer_public_key: genesis.creator_signing_pubkey });
|
|
282
|
+
}
|
|
283
|
+
async function openCarrier(backend, kRepo, repoId, kind, objectId, ciphertextSha256, key) {
|
|
284
|
+
const frame = await backend.get(key);
|
|
285
|
+
if (!frame)
|
|
286
|
+
fail("CHAIN_UNUSABLE", `${kind} ${objectId} is absent from the mirror`, "materializing gitvault recovery", { object_id: objectId });
|
|
287
|
+
const plaintext = openFrame({ k_obj: deriveObjectKey(kRepo, repoId, GITVAULT_GENESIS_EPOCH, kind, objectId), repo_id: repoId, object_kind: kind, object_id: objectId, epoch: GITVAULT_GENESIS_EPOCH, frame, expected_ciphertext_sha256: ciphertextSha256 });
|
|
288
|
+
return parseGitvaultStrict(new TextDecoder().decode(plaintext));
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Materialize the resolved generation into `out_dir` and run §4.7 restorer
|
|
292
|
+
* acceptance: scratch restore, every covered ref at its EXACT oid, `git fsck`
|
|
293
|
+
* full connectivity, recompute the three keyed commitments against the
|
|
294
|
+
* checkpoint manifest when one covers this generation. Acceptance failure is
|
|
295
|
+
* a typed non-zero exit (throws) — never a partial, silently-accepted repo.
|
|
296
|
+
*/
|
|
297
|
+
export async function recoverGitvaultMirror(options) {
|
|
298
|
+
// Task 5.3 follow-up (found via the live drill 2026-08-26): `out_dir` is
|
|
299
|
+
// "where to materialize the recovered repository" — the CLI's own
|
|
300
|
+
// documented example (`--out ./restored`) is a path that naturally does
|
|
301
|
+
// NOT already exist, same expectation as `git clone <url> restored-dir`.
|
|
302
|
+
// Every unit test happened to pass an already-`mkdtempSync`'d directory,
|
|
303
|
+
// which is exactly why nothing ever created it here. Create it FIRST,
|
|
304
|
+
// before any discovery/decrypt work, so a bad `out_dir` fails fast with a
|
|
305
|
+
// truthful, typed error instead of the misleading `GIT_UNAVAILABLE` the
|
|
306
|
+
// first `hardenedGit` call used to throw (see that function's own
|
|
307
|
+
// `GIT_CWD_MISSING` disambiguation in `gitvault-snapshot.ts` — this is the
|
|
308
|
+
// belt; that is the suspenders).
|
|
309
|
+
try {
|
|
310
|
+
mkdirSync(options.out_dir, { recursive: true });
|
|
311
|
+
}
|
|
312
|
+
catch (e) {
|
|
313
|
+
fail("GITVAULT_RECOVER_OUT_DIR_UNWRITABLE", `could not create the recovery output directory: ${options.out_dir}`, "materializing gitvault recovery", { out_dir: options.out_dir, cause: e instanceof Error ? e.message : String(e) });
|
|
314
|
+
}
|
|
315
|
+
const { backend } = options;
|
|
316
|
+
const keystore = options.keystore ?? GitvaultKeystore.open();
|
|
317
|
+
const discovery = await discoverAndVerifyChain({ backend, ...(options.recovery_receipt ? { recovery_receipt: options.recovery_receipt } : {}), keystore });
|
|
318
|
+
const { generation, absences } = await resolveWithFallback(backend, discovery, { requireMaterializable: true });
|
|
319
|
+
if (generation === GITVAULT_GENESIS_GENERATION) {
|
|
320
|
+
fail("CHECKPOINT_INCOMPLETE", "no generation could be fully materialized — every generation back to genesis has an unexplained missing object", "materializing gitvault recovery", { absences });
|
|
321
|
+
}
|
|
322
|
+
const kRepo = await resolveKRepo(backend, discovery.genesis, keystore);
|
|
323
|
+
const entry = discovery.chain.find((e) => e.generation === generation);
|
|
324
|
+
const repoId = discovery.repo_id;
|
|
325
|
+
const refState = await openCarrier(backend, kRepo, repoId, "ref_state", entry.head.ref_state.object_id, entry.head.ref_state.ciphertext_sha256, gitvaultPaths.refState(entry.head.ref_state.object_id));
|
|
326
|
+
const roots = await openCarrier(backend, kRepo, repoId, "retention_roots", entry.head.retention_roots.object_id, entry.head.retention_roots.ciphertext_sha256, gitvaultPaths.retentionRoots(entry.head.retention_roots.object_id));
|
|
327
|
+
// ── restore into scratch: newest checkpoint's packs, then every later WAL pack ──
|
|
328
|
+
const chainUpTo = discovery.chain.filter((e) => e.generation <= generation);
|
|
329
|
+
const heads = [];
|
|
330
|
+
for (let i = chainUpTo.length - 1; i >= 0; i--) {
|
|
331
|
+
heads.unshift(chainUpTo[i]);
|
|
332
|
+
if (chainUpTo[i].head.checkpoint)
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
await hardenedGit(options.out_dir, ["init", "-q", "--bare", "--object-format=sha1", "."]);
|
|
336
|
+
let manifest = null;
|
|
337
|
+
const first = heads[0];
|
|
338
|
+
if (first.head.checkpoint) {
|
|
339
|
+
const claimBytes = await backend.get(gitvaultPaths.claimSet(first.head.checkpoint.claim_set.object_id));
|
|
340
|
+
if (!claimBytes)
|
|
341
|
+
fail("CHECKPOINT_INCOMPLETE", "checkpoint claim set absent from the mirror", "materializing gitvault recovery");
|
|
342
|
+
const claimSet = parseGitvaultStrict(new TextDecoder().decode(claimBytes));
|
|
343
|
+
if (!verifyGitvaultObject(claimSet, discovery.genesis.creator_signing_pubkey))
|
|
344
|
+
fail("CHECKPOINT_INCOMPLETE", "checkpoint claim set signature fails", "materializing gitvault recovery");
|
|
345
|
+
manifest = await openCarrier(backend, kRepo, repoId, "checkpoint_manifest", claimSet.manifest_receipt.object_id, claimSet.manifest_receipt.ciphertext_sha256, gitvaultPaths.checkpointManifest(claimSet.manifest_receipt.object_id));
|
|
346
|
+
checkClaimSetEquality(claimSet, manifest, first.head.checkpoint.covers_through_generation);
|
|
347
|
+
for (const p of manifest.packs) {
|
|
348
|
+
const frame = await backend.get(gitvaultPaths.checkpointPack(p.object_id));
|
|
349
|
+
if (!frame)
|
|
350
|
+
fail("CHECKPOINT_INCOMPLETE", `checkpoint pack ${p.object_id} absent`, "materializing gitvault recovery");
|
|
351
|
+
const plain = openFrame({ k_obj: deriveObjectKey(kRepo, repoId, GITVAULT_GENESIS_EPOCH, "checkpoint_pack", p.object_id), repo_id: repoId, object_kind: "checkpoint_pack", object_id: p.object_id, epoch: GITVAULT_GENESIS_EPOCH, frame, expected_ciphertext_sha256: p.ciphertext_sha256 });
|
|
352
|
+
if (sha256Hex(plain) !== p.plaintext_sha256 || String(plain.length) !== p.plaintext_size_bytes)
|
|
353
|
+
fail("CHECKPOINT_INCOMPLETE", `checkpoint pack ${p.object_id} plaintext mismatch`, "materializing gitvault recovery");
|
|
354
|
+
await hardenedGit(options.out_dir, ["index-pack", "--stdin", "--strict"], { input: plain });
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
for (const h of heads) {
|
|
358
|
+
for (const w of h.head.wal_entries) {
|
|
359
|
+
const frame = await backend.get(gitvaultPaths.wal(w.object_id));
|
|
360
|
+
if (!frame)
|
|
361
|
+
fail("CHAIN_UNUSABLE", `WAL pack ${w.object_id} absent`, "materializing gitvault recovery", { object_id: w.object_id });
|
|
362
|
+
const plain = openFrame({ k_obj: deriveObjectKey(kRepo, repoId, GITVAULT_GENESIS_EPOCH, "wal_pack", w.object_id), repo_id: repoId, object_kind: "wal_pack", object_id: w.object_id, epoch: GITVAULT_GENESIS_EPOCH, frame, expected_ciphertext_sha256: w.ciphertext_sha256 });
|
|
363
|
+
await hardenedGit(options.out_dir, ["index-pack", "--stdin", "--strict"], { input: plain });
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
// ── every covered ref at its EXACT oid + HEAD (task 3.4) ──
|
|
367
|
+
const coverageTips = new Set(Object.values(refState.refs));
|
|
368
|
+
for (const r of roots.roots)
|
|
369
|
+
coverageTips.add(r.oid);
|
|
370
|
+
if (refState.head_target.kind === "detached")
|
|
371
|
+
coverageTips.add(refState.head_target.oid);
|
|
372
|
+
for (const tip of coverageTips) {
|
|
373
|
+
if (!(await hasObject(options.out_dir, tip)))
|
|
374
|
+
fail("CHAIN_UNUSABLE", `covered tip ${tip} does not resolve after restore`, "materializing gitvault recovery", { oid: tip });
|
|
375
|
+
}
|
|
376
|
+
for (const [ref, oid] of Object.entries(refState.refs)) {
|
|
377
|
+
await hardenedGit(options.out_dir, ["update-ref", ref, oid]);
|
|
378
|
+
}
|
|
379
|
+
if (refState.head_target.kind === "symref")
|
|
380
|
+
await hardenedGit(options.out_dir, ["symbolic-ref", "HEAD", refState.head_target.ref]);
|
|
381
|
+
else
|
|
382
|
+
await hardenedGit(options.out_dir, ["update-ref", "--no-deref", "HEAD", refState.head_target.oid]);
|
|
383
|
+
// ── git fsck --no-dangling, full connectivity (task 3.4) ──
|
|
384
|
+
const fsck = await hardenedGit(options.out_dir, ["fsck", "--no-dangling", "--full", "--strict"], { okStatuses: [1, 2] });
|
|
385
|
+
if (fsck.status !== 0)
|
|
386
|
+
fail("CHECKPOINT_INCOMPLETE", `fsck reports missing connectivity after restore: ${fsck.stderr.slice(0, 500)}`, "materializing gitvault recovery");
|
|
387
|
+
// ── recompute the three keyed commitments against the covering manifest (§4.7) ──
|
|
388
|
+
if (manifest) {
|
|
389
|
+
const kDigestRefmap = deriveDigestKey(kRepo, repoId, GITVAULT_GENESIS_EPOCH, "refmap");
|
|
390
|
+
const kDigestRootset = deriveDigestKey(kRepo, repoId, GITVAULT_GENESIS_EPOCH, "rootset");
|
|
391
|
+
const kDigestObjectset = deriveDigestKey(kRepo, repoId, GITVAULT_GENESIS_EPOCH, "objectset");
|
|
392
|
+
const { signature: _s1, ...refStateContent } = refState;
|
|
393
|
+
const { signature: _s2, ...rootsContent } = roots;
|
|
394
|
+
const refmapOk = keyedCommitment(kDigestRefmap, refStateContent) === manifest.ref_state_hmac;
|
|
395
|
+
const rootsetOk = keyedCommitment(kDigestRootset, rootsContent) === manifest.retention_roots_hmac;
|
|
396
|
+
const sortedTips = [...coverageTips].sort();
|
|
397
|
+
const restoredOids = sortedTips.length === 0 ? [] : (await hardenedGit(options.out_dir, ["rev-list", "--objects", "--no-object-names", ...sortedTips])).lines().map((l) => l.trim());
|
|
398
|
+
const objectsetOk = keyedCommitment(kDigestObjectset, objectsetContent(restoredOids)) === manifest.object_set_hmac;
|
|
399
|
+
if (!refmapOk || !rootsetOk || !objectsetOk) {
|
|
400
|
+
fail("CHECKPOINT_INCOMPLETE", `restored state does not match the checkpoint's keyed commitments (refmap ${refmapOk ? "ok" : "MISMATCH"}, rootset ${rootsetOk ? "ok" : "MISMATCH"}, objectset ${objectsetOk ? "ok" : "MISMATCH"})`, "materializing gitvault recovery", { refmapOk, rootsetOk, objectsetOk });
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
404
|
+
repo_id: repoId, genesis_sha256: discovery.genesis_sha256, pin_trust: discovery.pin_trust,
|
|
405
|
+
recovered_generation: generation, chain_break: discovery.chain_break, absences,
|
|
406
|
+
data_loss_detected: absences.some((a) => a.adjudication === "unexplained_absence"),
|
|
407
|
+
validity_not_freshness: GITVAULT_MIRROR_VALIDITY_NOT_FRESHNESS_STATEMENT,
|
|
408
|
+
keystore_still_required: GITVAULT_MIRROR_KEYSTORE_STILL_REQUIRED_STATEMENT,
|
|
409
|
+
mode: "recovered", out_dir: options.out_dir, refs: refState.refs, head_target: refState.head_target,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
//# sourceMappingURL=gitvault-recover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitvault-recover.js","sourceRoot":"","sources":["../../src/node/gitvault-recover.ts"],"names":[],"mappings":"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"}
|
|
@@ -71,6 +71,14 @@ export declare const HARDENED_GIT_ARGV_PREFIX: () => string[];
|
|
|
71
71
|
/**
|
|
72
72
|
* Run git with explicit args (no shell) in `cwd` under the hardened env.
|
|
73
73
|
* Throws `GIT_COMMAND_FAILED` on a non-ok exit.
|
|
74
|
+
*
|
|
75
|
+
* Task 5.3 follow-up (found via the live drill 2026-08-26): Node's
|
|
76
|
+
* `execFile` reports a MISSING `cwd` with the exact same `ENOENT` as a
|
|
77
|
+
* missing `git` binary, so a caller that forgot to create its working
|
|
78
|
+
* directory (e.g. `recover`'s `out_dir` before this fix) saw the misleading
|
|
79
|
+
* `GIT_UNAVAILABLE: git could not be executed` even though git itself was
|
|
80
|
+
* perfectly installed. Disambiguate BEFORE spawning: a missing `cwd` is its
|
|
81
|
+
* own distinct, honest refusal, never folded into "git is unavailable."
|
|
74
82
|
*/
|
|
75
83
|
export declare function hardenedGit(cwd: string, args: string[], options?: HardenedGitOptions): Promise<HardenedGitResult>;
|
|
76
84
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitvault-snapshot.d.ts","sourceRoot":"","sources":["../../src/node/gitvault-snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAQH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAI1E,uFAAuF;AACvF,eAAO,MAAM,6BAA6B,QAAoB,CAAC;AAC/D,wFAAwF;AACxF,eAAO,MAAM,mBAAmB,+BAA+B,CAAC;AAChE,kFAAkF;AAClF,eAAO,MAAM,wBAAwB,kBAAmB,CAAC;AAQzD,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,KAAK,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAC5B,gHAAgH;IAChH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,IAAI,MAAM,CAAC;IACf,KAAK,IAAI,MAAM,EAAE,CAAC;IAClB,6DAA6D;IAC7D,GAAG,IAAI,MAAM,EAAE,CAAC;CACjB;AAUD,6FAA6F;AAC7F,wBAAgB,cAAc,CAAC,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkBzF;AAED,sHAAsH;AACtH,eAAO,MAAM,wBAAwB,QAAO,MAAM,EAQjD,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"gitvault-snapshot.d.ts","sourceRoot":"","sources":["../../src/node/gitvault-snapshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -96,8 +96,19 @@ export const HARDENED_GIT_ARGV_PREFIX = () => [
|
|
|
96
96
|
/**
|
|
97
97
|
* Run git with explicit args (no shell) in `cwd` under the hardened env.
|
|
98
98
|
* Throws `GIT_COMMAND_FAILED` on a non-ok exit.
|
|
99
|
+
*
|
|
100
|
+
* Task 5.3 follow-up (found via the live drill 2026-08-26): Node's
|
|
101
|
+
* `execFile` reports a MISSING `cwd` with the exact same `ENOENT` as a
|
|
102
|
+
* missing `git` binary, so a caller that forgot to create its working
|
|
103
|
+
* directory (e.g. `recover`'s `out_dir` before this fix) saw the misleading
|
|
104
|
+
* `GIT_UNAVAILABLE: git could not be executed` even though git itself was
|
|
105
|
+
* perfectly installed. Disambiguate BEFORE spawning: a missing `cwd` is its
|
|
106
|
+
* own distinct, honest refusal, never folded into "git is unavailable."
|
|
99
107
|
*/
|
|
100
108
|
export function hardenedGit(cwd, args, options = {}) {
|
|
109
|
+
if (!existsSync(cwd)) {
|
|
110
|
+
return Promise.reject(new LocalError(`git working directory does not exist: ${cwd}`, "running hardened git", { code: "GIT_CWD_MISSING", details: { cwd, args } }));
|
|
111
|
+
}
|
|
101
112
|
const argv = [...HARDENED_GIT_ARGV_PREFIX(), ...args];
|
|
102
113
|
return new Promise((resolvePromise, reject) => {
|
|
103
114
|
const child = execFile("git", argv, { cwd, env: hardenedGitEnv(options.env), encoding: "buffer", maxBuffer: options.maxBuffer ?? 1024 * 1024 * 1024, windowsHide: true }, (error, stdout, stderr) => {
|