run402 4.24.0 → 4.25.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/cli.mjs +6 -6
- package/git-remote-run402.mjs +270 -0
- package/lib/command-manifest.mjs +11 -1
- package/lib/credentials.mjs +4 -0
- package/lib/domains.mjs +0 -14
- package/lib/gitvault.mjs +370 -0
- package/lib/init.mjs +143 -1
- package/lib/pay.test.mjs +0 -4
- package/package.json +8 -2
- package/sdk/dist/index.d.ts +20 -3
- package/sdk/dist/index.d.ts.map +1 -1
- package/sdk/dist/index.js +22 -3
- package/sdk/dist/index.js.map +1 -1
- package/sdk/dist/namespaces/admin.d.ts +0 -5
- package/sdk/dist/namespaces/admin.d.ts.map +1 -1
- package/sdk/dist/namespaces/admin.js +0 -9
- package/sdk/dist/namespaces/admin.js.map +1 -1
- package/sdk/dist/namespaces/assets.d.ts +1 -20
- package/sdk/dist/namespaces/assets.d.ts.map +1 -1
- package/sdk/dist/namespaces/assets.js +0 -27
- package/sdk/dist/namespaces/assets.js.map +1 -1
- package/sdk/dist/namespaces/auth.js +1 -1
- package/sdk/dist/namespaces/auth.js.map +1 -1
- package/sdk/dist/namespaces/domains.d.ts +0 -19
- package/sdk/dist/namespaces/domains.d.ts.map +1 -1
- package/sdk/dist/namespaces/domains.js +0 -19
- package/sdk/dist/namespaces/domains.js.map +1 -1
- package/sdk/dist/namespaces/gitvault.crypto.d.ts +319 -0
- package/sdk/dist/namespaces/gitvault.crypto.d.ts.map +1 -0
- package/sdk/dist/namespaces/gitvault.crypto.js +690 -0
- package/sdk/dist/namespaces/gitvault.crypto.js.map +1 -0
- package/sdk/dist/namespaces/gitvault.d.ts +473 -0
- package/sdk/dist/namespaces/gitvault.d.ts.map +1 -0
- package/sdk/dist/namespaces/gitvault.js +714 -0
- package/sdk/dist/namespaces/gitvault.js.map +1 -0
- package/sdk/dist/namespaces/gitvault.types.d.ts +481 -0
- package/sdk/dist/namespaces/gitvault.types.d.ts.map +1 -0
- package/sdk/dist/namespaces/gitvault.types.js +19 -0
- package/sdk/dist/namespaces/gitvault.types.js.map +1 -0
- package/sdk/dist/namespaces/org.d.ts +1 -3
- package/sdk/dist/namespaces/org.d.ts.map +1 -1
- package/sdk/dist/namespaces/org.js +6 -10
- package/sdk/dist/namespaces/org.js.map +1 -1
- package/sdk/dist/namespaces/pay.d.ts +0 -8
- package/sdk/dist/namespaces/pay.d.ts.map +1 -1
- package/sdk/dist/namespaces/pay.js.map +1 -1
- package/sdk/dist/namespaces/projects.d.ts +2 -2
- package/sdk/dist/namespaces/projects.d.ts.map +1 -1
- package/sdk/dist/namespaces/projects.js +4 -12
- package/sdk/dist/namespaces/projects.js.map +1 -1
- package/sdk/dist/namespaces/secrets.d.ts +0 -2
- package/sdk/dist/namespaces/secrets.d.ts.map +1 -1
- package/sdk/dist/namespaces/secrets.js +3 -10
- package/sdk/dist/namespaces/secrets.js.map +1 -1
- package/sdk/dist/namespaces/subdomains.d.ts +0 -2
- package/sdk/dist/namespaces/subdomains.d.ts.map +1 -1
- package/sdk/dist/namespaces/subdomains.js +5 -16
- package/sdk/dist/namespaces/subdomains.js.map +1 -1
- package/sdk/dist/namespaces/transfers.d.ts +0 -2
- package/sdk/dist/namespaces/transfers.d.ts.map +1 -1
- package/sdk/dist/namespaces/transfers.js +8 -10
- package/sdk/dist/namespaces/transfers.js.map +1 -1
- package/sdk/dist/namespaces/wallets.d.ts +0 -12
- package/sdk/dist/namespaces/wallets.d.ts.map +1 -1
- package/sdk/dist/namespaces/wallets.js +0 -14
- package/sdk/dist/namespaces/wallets.js.map +1 -1
- package/sdk/dist/node/gitvault-creation-journal.d.ts +222 -0
- package/sdk/dist/node/gitvault-creation-journal.d.ts.map +1 -0
- package/sdk/dist/node/gitvault-creation-journal.js +365 -0
- package/sdk/dist/node/gitvault-creation-journal.js.map +1 -0
- package/sdk/dist/node/gitvault-deploy.d.ts +211 -0
- package/sdk/dist/node/gitvault-deploy.d.ts.map +1 -0
- package/sdk/dist/node/gitvault-deploy.js +292 -0
- package/sdk/dist/node/gitvault-deploy.js.map +1 -0
- package/sdk/dist/node/gitvault-keystore.d.ts +207 -0
- package/sdk/dist/node/gitvault-keystore.d.ts.map +1 -0
- package/sdk/dist/node/gitvault-keystore.js +529 -0
- package/sdk/dist/node/gitvault-keystore.js.map +1 -0
- package/sdk/dist/node/gitvault-prune.d.ts +341 -0
- package/sdk/dist/node/gitvault-prune.d.ts.map +1 -0
- package/sdk/dist/node/gitvault-prune.js +410 -0
- package/sdk/dist/node/gitvault-prune.js.map +1 -0
- package/sdk/dist/node/gitvault-publication.d.ts +730 -0
- package/sdk/dist/node/gitvault-publication.d.ts.map +1 -0
- package/sdk/dist/node/gitvault-publication.js +1475 -0
- package/sdk/dist/node/gitvault-publication.js.map +1 -0
- package/sdk/dist/node/gitvault-snapshot.d.ts +190 -0
- package/sdk/dist/node/gitvault-snapshot.d.ts.map +1 -0
- package/sdk/dist/node/gitvault-snapshot.js +505 -0
- package/sdk/dist/node/gitvault-snapshot.js.map +1 -0
- package/sdk/dist/node/index.d.ts +11 -0
- package/sdk/dist/node/index.d.ts.map +1 -1
- package/sdk/dist/node/index.js +9 -0
- package/sdk/dist/node/index.js.map +1 -1
- package/sdk/dist/node/paid-fetch.d.ts.map +1 -1
- package/sdk/dist/node/paid-fetch.js +0 -4
- package/sdk/dist/node/paid-fetch.js.map +1 -1
- package/sdk/dist/node/sites-node.d.ts +1 -8
- package/sdk/dist/node/sites-node.d.ts.map +1 -1
- package/sdk/dist/node/sites-node.js +1 -7
- package/sdk/dist/node/sites-node.js.map +1 -1
- package/sdk/dist/scoped.d.ts +4 -35
- package/sdk/dist/scoped.d.ts.map +1 -1
- package/sdk/dist/scoped.js +9 -74
- package/sdk/dist/scoped.js.map +1 -1
- package/lib/sender-domain.mjs +0 -36
- package/sdk/dist/deprecate.d.ts +0 -23
- package/sdk/dist/deprecate.d.ts.map +0 -1
- package/sdk/dist/deprecate.js +0 -42
- package/sdk/dist/deprecate.js.map +0 -1
- package/sdk/dist/namespaces/sender-domain.d.ts +0 -47
- package/sdk/dist/namespaces/sender-domain.d.ts.map +0 -1
- package/sdk/dist/namespaces/sender-domain.js +0 -45
- package/sdk/dist/namespaces/sender-domain.js.map +0 -1
|
@@ -0,0 +1,730 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gitvault — publication (protocol rev 40 §6 + §4.4–4.7 + §5A client side;
|
|
3
|
+
* task 5.4).
|
|
4
|
+
*
|
|
5
|
+
* What lives here:
|
|
6
|
+
* - the PURE evaluators: ref transactions (§6.1 — force-with-lease only,
|
|
7
|
+
* fast-forward for non-force branch updates, immutable tags, deletes need
|
|
8
|
+
* expected-old, pairwise-distinct refs refused BEFORE evaluation, the
|
|
9
|
+
* §6.5 cardinality bounds), retention-root evolution (§4.5 — map keyed
|
|
10
|
+
* `(ref, oid)`, renewal, expiry ONLY at checkpoints against the pre-signing
|
|
11
|
+
* cutoff ticket, strict `effective + 90d < cutoff_at`), the heads-listing
|
|
12
|
+
* page contract (§6.3 / D186 — anchor echo, cursor echo, has_more/
|
|
13
|
+
* next_cursor coupling, strictly-above-anchor, gapless across pages,
|
|
14
|
+
* truthful total), chain linkage (`CHAIN_BROKEN`), and the transition
|
|
15
|
+
* fail-closed rule (`UPGRADE_REQUIRED`);
|
|
16
|
+
* - {@link GitvaultTransport} — the control-plane + bucket operations the
|
|
17
|
+
* vault needs (extends task 5.3's creation transport) — and
|
|
18
|
+
* {@link createGitvaultHttpTransport}, the `fetch`-backed implementation
|
|
19
|
+
* over the SDK kernel (upload sessions → presigned PUT with
|
|
20
|
+
* `If-None-Match: *` → finalize);
|
|
21
|
+
* - {@link GitvaultVault} — discover/verify to newest with the RESUMABLE
|
|
22
|
+
* verification budget, materialize (decrypt ref_state + retention_roots →
|
|
23
|
+
* the materialized pin), push (pack_set or a checkpoint-bearing head when
|
|
24
|
+
* the delta exceeds the 64-receipt budget, upload with receipt-compare,
|
|
25
|
+
* admission with 409 re-apply-and-retry, head read-back before any pin
|
|
26
|
+
* advances), checkpoint build + acceptance self-check, and repair (the
|
|
27
|
+
* mandatory fresh checkpoint + the exact repair-root algebra).
|
|
28
|
+
*
|
|
29
|
+
* Dual pins (§6.4) live in the keystore repo file: `head_pin` is
|
|
30
|
+
* `highest_authenticated`, `materialized_pin` is `highest_materialized` — the
|
|
31
|
+
* ONLY push base. A regression below the authenticated pin is
|
|
32
|
+
* `GENERATION_REGRESSION`; an authenticated-but-undecryptable head is
|
|
33
|
+
* `CHAIN_UNUSABLE` (read-only at the materialized pin); an admitted non-null
|
|
34
|
+
* transition is `UPGRADE_REQUIRED` (read-only past it, no publish).
|
|
35
|
+
*/
|
|
36
|
+
import type { Client } from "../kernel.js";
|
|
37
|
+
import type { GitvaultActivationToken, GitvaultCaptureBinding, GitvaultCaptureReceipt, GitvaultCheckpointBlock, GitvaultCheckpointClaimSet, GitvaultCheckpointManifest, GitvaultDigestLabel, GitvaultHead, GitvaultHeadTarget, GitvaultHeadsListingPage, GitvaultHeadsListingRequest, GitvaultRefState, GitvaultRefTransaction, GitvaultRefUpdate, GitvaultRepairDescriptor, GitvaultRetentionCutoff, GitvaultRetentionCutoffReceipt, GitvaultRetentionRoot, GitvaultRetentionRoots, GitvaultRetentionRootsReceipt, GitvaultVaultGenesis } from "../namespaces/gitvault.types.js";
|
|
38
|
+
import type { GitvaultCreationTransport } from "./gitvault-creation-journal.js";
|
|
39
|
+
import { GitvaultKeystore, type GitvaultRepoFile } from "./gitvault-keystore.js";
|
|
40
|
+
import type { GitvaultPruneIntentRecord } from "./gitvault-prune.js";
|
|
41
|
+
export declare const GITVAULT_MAX_CANONICAL_REFS = 10000;
|
|
42
|
+
export declare const GITVAULT_MAX_REF_UPDATES_PER_TRANSACTION = 1000;
|
|
43
|
+
export declare const GITVAULT_MAX_RETENTION_ROOT_ENTRIES = 50000;
|
|
44
|
+
export declare const GITVAULT_MAX_REPAIR_ADDED_ROOTS = 10000;
|
|
45
|
+
export declare const GITVAULT_MAX_WAL_RECEIPTS_PER_HEAD = 64;
|
|
46
|
+
export declare const GITVAULT_MAX_CHECKPOINT_PACKS = 4096;
|
|
47
|
+
export declare const GITVAULT_MAX_CHECKPOINT_TOTAL_STORED_BYTES = 858993459200n;
|
|
48
|
+
export declare const GITVAULT_MULTI_OBJECT_PACK_TARGET_BYTES = 201326592;
|
|
49
|
+
export declare const GITVAULT_MAX_REF_STATE_OBJECT_BYTES = 33554432;
|
|
50
|
+
export declare const GITVAULT_MAX_HEADS_PER_LISTING_PAGE = 1000;
|
|
51
|
+
export declare const GITVAULT_VERIFICATION_BUDGET_HEADS = 100000;
|
|
52
|
+
export declare const GITVAULT_RETENTION_MIN_DAYS = 90;
|
|
53
|
+
/** Default admission-conflict retries before the push gives up (each retry re-verifies + re-applies to the winner). */
|
|
54
|
+
export declare const GITVAULT_PUSH_CONFLICT_RETRIES = 5;
|
|
55
|
+
export declare function generationToBigInt(generation: string): bigint;
|
|
56
|
+
export declare function bigIntToGeneration(value: bigint): string;
|
|
57
|
+
export declare function nextGeneration(generation: string): string;
|
|
58
|
+
export type GitvaultRefMap = Record<string, string>;
|
|
59
|
+
/** A tip that left the canonical map in this transaction — it enters `retention_roots` in the same generation. */
|
|
60
|
+
export interface GitvaultDroppedTip {
|
|
61
|
+
ref: string;
|
|
62
|
+
oid: string;
|
|
63
|
+
reason: "deleted" | "force_displaced";
|
|
64
|
+
}
|
|
65
|
+
export interface GitvaultRefTransactionEvaluation {
|
|
66
|
+
refs: GitvaultRefMap;
|
|
67
|
+
dropped: GitvaultDroppedTip[];
|
|
68
|
+
}
|
|
69
|
+
export interface GitvaultEvaluateRefTransactionOptions {
|
|
70
|
+
/** Ancestry oracle: true iff `ancestor` is reachable from `descendant`. */
|
|
71
|
+
isAncestor: (ancestor: string, descendant: string) => Promise<boolean> | boolean;
|
|
72
|
+
/** `refuse` (default — user pushes): any `refs/run402/*` update is refused; `allow`: the protocol's own deploy-ref move. */
|
|
73
|
+
protocol_refs?: "refuse" | "allow";
|
|
74
|
+
}
|
|
75
|
+
/** One failing update of a refused transaction (never a silent revert). */
|
|
76
|
+
export interface GitvaultRefUpdateFailure {
|
|
77
|
+
ref: string;
|
|
78
|
+
reason: "expected_old_mismatch" | "non_fast_forward" | "tag_immutable" | "delete_requires_expected_old" | "noop";
|
|
79
|
+
expected_old_oid: string | null;
|
|
80
|
+
current_oid: string | null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Evaluate a §6.1 transaction against the materialized map. Refusals in
|
|
84
|
+
* order: pairwise-distinct refs (before evaluation), grammar, the update cap,
|
|
85
|
+
* then per-update semantics collected into ONE `REF_EXPECTED_OLD_MISMATCH`
|
|
86
|
+
* (every failing update listed), then the resulting-state cardinality.
|
|
87
|
+
*/
|
|
88
|
+
export declare function evaluateRefTransaction(current: GitvaultRefMap, transaction: GitvaultRefTransaction, options: GitvaultEvaluateRefTransactionOptions): Promise<GitvaultRefTransactionEvaluation>;
|
|
89
|
+
/** §6.5 bound: ≤ 10 000 canonical refs and the serialized map ≤ 32 MiB. */
|
|
90
|
+
export declare function assertRefMapCardinality(refs: GitvaultRefMap): void;
|
|
91
|
+
/** The §4.4 deploy-ref move: force-with-lease `refs/run402/deploys/latest` → `oid` (creation when absent). */
|
|
92
|
+
export declare function deployRefTransaction(current: GitvaultRefMap, oid: string): GitvaultRefTransaction;
|
|
93
|
+
/** `effective_admitted_at = max(prepared_at, storage creation time of the winning admission record)` (§4.10). */
|
|
94
|
+
export declare function effectiveAdmittedAt(preparedAt: string, recordStorageCreatedAt: string): string;
|
|
95
|
+
/** A root may be removed iff `effective_admitted_at + 90 days < cutoff_at` (STRICT; §4.5a). */
|
|
96
|
+
export declare function isRootEligibleForRemoval(effectiveAdmittedAtIso: string, cutoffAtIso: string, retentionDays?: number): boolean;
|
|
97
|
+
export interface GitvaultEvolveRootsOptions {
|
|
98
|
+
/** The generation being built (`g+1`) — stamped as `dropped_at_generation` on new/renewed keys. */
|
|
99
|
+
generation: string;
|
|
100
|
+
/** Tips dropped or force-displaced by this generation's transaction. */
|
|
101
|
+
dropped: Array<{
|
|
102
|
+
ref: string;
|
|
103
|
+
oid: string;
|
|
104
|
+
}>;
|
|
105
|
+
/**
|
|
106
|
+
* Present ONLY when this generation carries a checkpoint bound to a cutoff
|
|
107
|
+
* ticket: expiry is evaluated against `cutoff_at` using the resolver for each
|
|
108
|
+
* root's drop generation. Removal is PERMISSIVE — a resolver returning
|
|
109
|
+
* `null` keeps the root.
|
|
110
|
+
*/
|
|
111
|
+
checkpoint_cutoff?: {
|
|
112
|
+
cutoff_at: string;
|
|
113
|
+
effectiveAdmittedAt: (droppedAtGeneration: string) => string | null;
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
export declare function compareRoots(a: GitvaultRetentionRoot, b: GitvaultRetentionRoot): number;
|
|
117
|
+
/** roots(g+1) = roots(g) ∪ dropped (RENEWING an existing `(ref, oid)` key) ∖ {expired, only at a checkpoint with a ticket}. */
|
|
118
|
+
export declare function evolveRetentionRoots(previous: GitvaultRetentionRoot[], options: GitvaultEvolveRootsOptions): GitvaultRetentionRoot[];
|
|
119
|
+
export interface GitvaultListingProgress {
|
|
120
|
+
/** The anchor (constant across the sequence). */
|
|
121
|
+
after_generation: string;
|
|
122
|
+
/** The highest generation delivered so far (== anchor before page 1). */
|
|
123
|
+
last_generation: string;
|
|
124
|
+
/** Generations delivered so far (for the truthful-total check). */
|
|
125
|
+
delivered: number;
|
|
126
|
+
}
|
|
127
|
+
/** Validate a listing request before it is sent (the request schema, D186). */
|
|
128
|
+
export declare function validateHeadsListingRequest(request: GitvaultHeadsListingRequest): void;
|
|
129
|
+
/**
|
|
130
|
+
* Validate one page against the request and the sequence so far. Returns the
|
|
131
|
+
* advanced progress. Refusals: anchor not echoed / wrong vault / coupling
|
|
132
|
+
* violation / retired member → `GITVAULT_LISTING_PAGE_INVALID`; an entry at or
|
|
133
|
+
* below the anchor → `GENERATION_REGRESSION`; a gap within or across pages →
|
|
134
|
+
* `CHAIN_BROKEN`; an untruthful final `total` → `CHAIN_BROKEN`.
|
|
135
|
+
*/
|
|
136
|
+
export declare function verifyHeadsListingPage(page: GitvaultHeadsListingPage, request: GitvaultHeadsListingRequest, progress: GitvaultListingProgress, expectedRepoId?: string): GitvaultListingProgress;
|
|
137
|
+
/**
|
|
138
|
+
* The continuation request for `page`, or `null` when the sequence is complete.
|
|
139
|
+
* The anchor stays CONSTANT and `next_cursor` is echoed UNCHANGED — the cursor
|
|
140
|
+
* is stored and echoed, never parsed or edited (a client that re-anchors or
|
|
141
|
+
* edits a byte earns `INVALID_CURSOR` from the platform, D186).
|
|
142
|
+
*/
|
|
143
|
+
export declare function nextListingRequest(request: GitvaultHeadsListingRequest, page: GitvaultHeadsListingPage): GitvaultHeadsListingRequest | null;
|
|
144
|
+
/**
|
|
145
|
+
* §6.4: the vault's newest generation may never fall BELOW the authenticated
|
|
146
|
+
* pin. A listing (or a storage read) that says otherwise is a rollback, not a
|
|
147
|
+
* quiet vault — `GENERATION_REGRESSION`, no publish.
|
|
148
|
+
*/
|
|
149
|
+
export declare function checkGenerationRegression(listedNewestGeneration: string, pinnedGeneration: string): void;
|
|
150
|
+
/** The parameters a maintenance open requests, and that the C1 record must echo. */
|
|
151
|
+
export interface GitvaultOpenBindingRecord {
|
|
152
|
+
base_head_sha256: string;
|
|
153
|
+
prior_checkpoint_claim_set_sha256: string | null;
|
|
154
|
+
r2_cap_size_bytes: string;
|
|
155
|
+
}
|
|
156
|
+
/** `SHA-256("r402s/v0/open-binding" ‖ lp(client_open_id) ‖ lp(base_head) ‖ lp_opt(prior) ‖ lp(cap))`. */
|
|
157
|
+
export declare function openBindingDigest(clientOpenId: string, record: GitvaultOpenBindingRecord): string;
|
|
158
|
+
/**
|
|
159
|
+
* Recompute the binding from the record's OWN fields and compare it bytewise
|
|
160
|
+
* with the signed issuance digest. The error registry has no dedicated code for
|
|
161
|
+
* the fence inequality (D145), so the client surfaces
|
|
162
|
+
* `GITVAULT_OPEN_BINDING_MISMATCH`; a same-`client_open_id` retry that carries a
|
|
163
|
+
* DIFFERENT binding is the registry's `CLIENT_OPEN_ID_CONFLICT`.
|
|
164
|
+
*/
|
|
165
|
+
export declare function checkOpenBinding(clientOpenId: string, record: GitvaultOpenBindingRecord, issuanceOpenBindingSha256: string, options?: {
|
|
166
|
+
retry?: boolean;
|
|
167
|
+
}): void;
|
|
168
|
+
export interface GitvaultChainLinkInput {
|
|
169
|
+
head: GitvaultHead;
|
|
170
|
+
stored_bytes: Uint8Array;
|
|
171
|
+
/** The listing's hash for this generation. */
|
|
172
|
+
listed_sha256: string;
|
|
173
|
+
expected_generation: string;
|
|
174
|
+
prev_sha256: string;
|
|
175
|
+
repo_id: string;
|
|
176
|
+
/** The registered writer public key (V0: the genesis creator key). */
|
|
177
|
+
writer_public_key: Uint8Array | string;
|
|
178
|
+
writer_key_id: string;
|
|
179
|
+
}
|
|
180
|
+
/** Verify one link: bytes hash to the listing, strict parse, generation, prev linkage, epoch pin, repo, writer signature. */
|
|
181
|
+
export declare function checkChainLink(input: GitvaultChainLinkInput): void;
|
|
182
|
+
/**
|
|
183
|
+
* The transition fail-closed rule: a V0 client that encounters an ADMITTED
|
|
184
|
+
* non-null transition stops advancing — read-only at the materialized pin,
|
|
185
|
+
* no publish past it, `UPGRADE_REQUIRED`. Unknown kinds are a parse reject.
|
|
186
|
+
*/
|
|
187
|
+
export declare function assertNoTransition(head: GitvaultHead): void;
|
|
188
|
+
/** One object to upload — identity fixed BEFORE the PUT; the receipt is compared against it. */
|
|
189
|
+
export interface GitvaultUploadObject {
|
|
190
|
+
/**
|
|
191
|
+
* Storage path relative to the vault root (§3). CLIENT-LOCAL addressing only:
|
|
192
|
+
* the control plane derives the bucket key from `object_kind` + the ledger
|
|
193
|
+
* identity and REFUSES a manifest entry carrying an unexpected member, so
|
|
194
|
+
* this never rides the wire (5.6c).
|
|
195
|
+
*/
|
|
196
|
+
path: string;
|
|
197
|
+
object_kind: string;
|
|
198
|
+
/** `null` for path-addressed kinds (envelopes) — those ride `epoch` + `recipient_fingerprint`. */
|
|
199
|
+
object_id: string | null;
|
|
200
|
+
bytes: Uint8Array;
|
|
201
|
+
/** SHA-256 of `bytes` (ciphertext hash for frames, stored-bytes hash for plaintext kinds). */
|
|
202
|
+
sha256: string;
|
|
203
|
+
size_bytes: string;
|
|
204
|
+
/** `wal_pack` only — §4.1: the ONLY receipt kind carrying `base_generation`. */
|
|
205
|
+
base_generation?: string;
|
|
206
|
+
}
|
|
207
|
+
export interface GitvaultUploadReceipt {
|
|
208
|
+
path: string;
|
|
209
|
+
object_id: string | null;
|
|
210
|
+
sha256: string;
|
|
211
|
+
size_bytes: string;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* The control plane addresses stored objects by LEDGER IDENTITY, never by
|
|
215
|
+
* bucket path: heads and admission records have their own generation-addressed
|
|
216
|
+
* routes, and every uploadable kind is named by `object_kind` + `object_id`
|
|
217
|
+
* (or, for envelopes, `epoch` + `recipient_fingerprint`). This resolver maps
|
|
218
|
+
* the SDK's internal `gitvaultPaths` strings onto that identity so the rest of
|
|
219
|
+
* the vault can keep addressing objects the way §3 describes them.
|
|
220
|
+
*/
|
|
221
|
+
export type GitvaultWireRef = {
|
|
222
|
+
kind: "head";
|
|
223
|
+
generation: string;
|
|
224
|
+
} | {
|
|
225
|
+
kind: "admission";
|
|
226
|
+
generation: string;
|
|
227
|
+
} | {
|
|
228
|
+
kind: "object";
|
|
229
|
+
read: GitvaultObjectReadRequest;
|
|
230
|
+
};
|
|
231
|
+
/** One entry of a `POST …/object-reads` batch. */
|
|
232
|
+
export interface GitvaultObjectReadRequest {
|
|
233
|
+
object_kind: string;
|
|
234
|
+
object_id?: string;
|
|
235
|
+
epoch?: string;
|
|
236
|
+
recipient_fingerprint?: string;
|
|
237
|
+
}
|
|
238
|
+
/** `null` for a path with no wire identity (e.g. a locally-held cutoff ticket). */
|
|
239
|
+
export declare function gitvaultWireRefForPath(path: string): GitvaultWireRef | null;
|
|
240
|
+
/** The manifest entry for one upload — closed-key, exactly what the control plane validates. */
|
|
241
|
+
export declare function gitvaultManifestEntry(object: GitvaultUploadObject): GitvaultObjectReadRequest & {
|
|
242
|
+
sha256: string;
|
|
243
|
+
size_bytes: string;
|
|
244
|
+
base_generation?: string;
|
|
245
|
+
};
|
|
246
|
+
/** The stable key both sides agree on, used to pair receipts back to requests. */
|
|
247
|
+
export declare function gitvaultLedgerId(read: GitvaultObjectReadRequest): string;
|
|
248
|
+
export interface GitvaultAdmitHeadRequest {
|
|
249
|
+
repo_id: string;
|
|
250
|
+
generation: string;
|
|
251
|
+
stored_bytes: Uint8Array;
|
|
252
|
+
stored_bytes_sha256: string;
|
|
253
|
+
}
|
|
254
|
+
export type GitvaultAdmitHeadResult = {
|
|
255
|
+
outcome: "admitted";
|
|
256
|
+
admission_record_sha256: string;
|
|
257
|
+
capture_receipt: GitvaultCaptureReceipt | null;
|
|
258
|
+
} | {
|
|
259
|
+
outcome: "conflict";
|
|
260
|
+
winner: {
|
|
261
|
+
generation: string;
|
|
262
|
+
stored_bytes_sha256: string;
|
|
263
|
+
};
|
|
264
|
+
};
|
|
265
|
+
export interface GitvaultRetentionCutoffIssued {
|
|
266
|
+
ticket: GitvaultRetentionCutoff;
|
|
267
|
+
receipt: GitvaultRetentionCutoffReceipt;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Everything the vault needs from the control plane + bucket. Extends the
|
|
271
|
+
* creation transport so one implementation serves 5.3–5.6. All methods are
|
|
272
|
+
* idempotent from the state machines' point of view.
|
|
273
|
+
*/
|
|
274
|
+
/** The `resource_binding` an upload session is charged against (§7.2 / §9.3). */
|
|
275
|
+
export type GitvaultResourceBinding = {
|
|
276
|
+
kind: "ordinary_push";
|
|
277
|
+
} | {
|
|
278
|
+
kind: "maintenance_cycle";
|
|
279
|
+
maintenance_lease_id: string;
|
|
280
|
+
} | {
|
|
281
|
+
kind: "repair_attempt";
|
|
282
|
+
repair_attempt_id: string;
|
|
283
|
+
};
|
|
284
|
+
/** `POST …/maintenance-leases` — the owner's compact/prune reservation (§7.2). */
|
|
285
|
+
export interface GitvaultMaintenanceLeaseRequest {
|
|
286
|
+
repo_id: string;
|
|
287
|
+
base_head_sha256: string;
|
|
288
|
+
current_checkpoint_hash?: string | null;
|
|
289
|
+
r1_size_bytes: string;
|
|
290
|
+
r2_cap_size_bytes: string;
|
|
291
|
+
p_before_c1_size_bytes?: string;
|
|
292
|
+
p_before_c2_size_bytes?: string;
|
|
293
|
+
}
|
|
294
|
+
export interface GitvaultMaintenanceLease {
|
|
295
|
+
maintenance_lease_id: string;
|
|
296
|
+
repo_id: string;
|
|
297
|
+
base_head_sha256: string;
|
|
298
|
+
current_checkpoint_hash: string | null;
|
|
299
|
+
reservation_size_bytes: string;
|
|
300
|
+
maintenance_headroom_bytes: string;
|
|
301
|
+
/** Returned ONCE — the liveness instrument (heartbeat / release). Never logged, never cached. */
|
|
302
|
+
holder_token: string;
|
|
303
|
+
expires_at: string | null;
|
|
304
|
+
hard_deadline_at: string | null;
|
|
305
|
+
}
|
|
306
|
+
export interface GitvaultTransport extends GitvaultCreationTransport {
|
|
307
|
+
listHeads(request: GitvaultHeadsListingRequest & {
|
|
308
|
+
repo_id: string;
|
|
309
|
+
}): Promise<GitvaultHeadsListingPage>;
|
|
310
|
+
/** Session → create-only presigned PUTs (`If-None-Match: *`) → finalize; receipts in request order. */
|
|
311
|
+
uploadObjects(request: {
|
|
312
|
+
repo_id: string;
|
|
313
|
+
objects: GitvaultUploadObject[];
|
|
314
|
+
resource_binding?: GitvaultResourceBinding;
|
|
315
|
+
}): Promise<GitvaultUploadReceipt[]>;
|
|
316
|
+
admitHead(request: GitvaultAdmitHeadRequest): Promise<GitvaultAdmitHeadResult>;
|
|
317
|
+
requestRetentionCutoff(request: {
|
|
318
|
+
repo_id: string;
|
|
319
|
+
base_head_sha256: string;
|
|
320
|
+
}): Promise<GitvaultRetentionCutoffIssued>;
|
|
321
|
+
exchangeActivationToken(request: {
|
|
322
|
+
repo_id: string;
|
|
323
|
+
operation_id: string;
|
|
324
|
+
capture_receipt: GitvaultCaptureReceipt;
|
|
325
|
+
}): Promise<GitvaultActivationToken>;
|
|
326
|
+
submitOverrideCompletion(request: {
|
|
327
|
+
repo_id: string;
|
|
328
|
+
operation_id: string;
|
|
329
|
+
capture_receipt: GitvaultCaptureReceipt;
|
|
330
|
+
}): Promise<{
|
|
331
|
+
cleared: boolean;
|
|
332
|
+
}>;
|
|
333
|
+
/** The vault record — policy, allocation generation, storage + maintenance state (§9.2). */
|
|
334
|
+
getVaultRecord(request: {
|
|
335
|
+
repo_id: string;
|
|
336
|
+
}): Promise<GitvaultVaultRecord>;
|
|
337
|
+
/** Resolve a project's vault without local state (the cold-restart entry point). */
|
|
338
|
+
findVaultByProject(request: {
|
|
339
|
+
project_id: string;
|
|
340
|
+
}): Promise<GitvaultVaultRecord>;
|
|
341
|
+
acquireMaintenanceLease(request: GitvaultMaintenanceLeaseRequest): Promise<GitvaultMaintenanceLease>;
|
|
342
|
+
heartbeatMaintenanceLease(request: {
|
|
343
|
+
repo_id: string;
|
|
344
|
+
maintenance_lease_id: string;
|
|
345
|
+
holder_token: string;
|
|
346
|
+
}): Promise<{
|
|
347
|
+
maintenance_lease_id: string;
|
|
348
|
+
expires_at: string | null;
|
|
349
|
+
}>;
|
|
350
|
+
releaseMaintenanceLease(request: {
|
|
351
|
+
repo_id: string;
|
|
352
|
+
maintenance_lease_id: string;
|
|
353
|
+
holder_token: string;
|
|
354
|
+
}): Promise<{
|
|
355
|
+
maintenance_lease_id: string;
|
|
356
|
+
status: string;
|
|
357
|
+
}>;
|
|
358
|
+
/**
|
|
359
|
+
* `POST …/prune-intents` — the intent's EXACT BYTES (§7.3).
|
|
360
|
+
*
|
|
361
|
+
* The route is parsed with `express.raw` and the owner signature is verified
|
|
362
|
+
* over the bytes as sent, so the transport MUST NOT re-serialize: it puts
|
|
363
|
+
* `intent_bytes` on the wire verbatim under `Content-Type: application/json`.
|
|
364
|
+
* An implementation that accepts a parsed object here and stringifies it is
|
|
365
|
+
* signing one thing and sending another.
|
|
366
|
+
*/
|
|
367
|
+
submitPruneIntent(request: {
|
|
368
|
+
repo_id: string;
|
|
369
|
+
intent_bytes: Uint8Array;
|
|
370
|
+
}): Promise<GitvaultPruneIntentRecord & {
|
|
371
|
+
stored: boolean;
|
|
372
|
+
}>;
|
|
373
|
+
/** `GET …/prune-intents/:id` — the intent's state and, once signed, its completion. */
|
|
374
|
+
getPruneIntent(request: {
|
|
375
|
+
repo_id: string;
|
|
376
|
+
prune_intent_object_id: string;
|
|
377
|
+
}): Promise<GitvaultPruneIntentRecord | null>;
|
|
378
|
+
}
|
|
379
|
+
/** `GET /gitvault/v1/vaults/:vault_id` — the shape `reads.ts:getVaultRecord` returns. */
|
|
380
|
+
export interface GitvaultVaultRecord {
|
|
381
|
+
repo_id: string;
|
|
382
|
+
project_id: string;
|
|
383
|
+
org_id: string;
|
|
384
|
+
gitvault_policy: "required" | "grandfathered" | null;
|
|
385
|
+
gitvault_policy_version: string;
|
|
386
|
+
gitvault_policy_changed_at: string | null;
|
|
387
|
+
allocation_generation: string;
|
|
388
|
+
allocation_sha256: string | null;
|
|
389
|
+
newest_generation: string | null;
|
|
390
|
+
genesis_admitted_at: string | null;
|
|
391
|
+
latest_effective_admitted_at: string | null;
|
|
392
|
+
admitted_generations: string;
|
|
393
|
+
gc_epoch: string;
|
|
394
|
+
repair_version: string;
|
|
395
|
+
repair_fence_state: string;
|
|
396
|
+
storage: {
|
|
397
|
+
source_bytes: string;
|
|
398
|
+
open_session_reserved_bytes: string;
|
|
399
|
+
objects: Record<string, string>;
|
|
400
|
+
};
|
|
401
|
+
maintenance: {
|
|
402
|
+
lease: {
|
|
403
|
+
maintenance_lease_id: string;
|
|
404
|
+
base_head_sha256: string;
|
|
405
|
+
reservation_size_bytes: string;
|
|
406
|
+
expires_at: string | null;
|
|
407
|
+
hard_deadline_at: string | null;
|
|
408
|
+
} | null;
|
|
409
|
+
open_cycle: {
|
|
410
|
+
maintenance_cycle_id: string;
|
|
411
|
+
state: string;
|
|
412
|
+
last_cycle_progress_at: string | null;
|
|
413
|
+
} | null;
|
|
414
|
+
pending_repair_attempt_id: string | null;
|
|
415
|
+
};
|
|
416
|
+
warnings: {
|
|
417
|
+
kind: string;
|
|
418
|
+
message: string;
|
|
419
|
+
}[];
|
|
420
|
+
created_at: string | null;
|
|
421
|
+
}
|
|
422
|
+
export interface GitvaultHttpTransportOptions {
|
|
423
|
+
/** Wire shape: every vault-scoped route is `/gitvault/v1/vaults/:vault_id/...`; `vault_id` is the `repo_id` unless a mapping is supplied (D185). */
|
|
424
|
+
vaultIdFor?: (repoId: string) => string;
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* The `fetch`-backed transport over the SDK kernel. Presigned PUTs carry
|
|
428
|
+
* `If-None-Match: *` (create-only — the bucket policy demands it) and the
|
|
429
|
+
* FULL_OBJECT SHA-256 checksum header.
|
|
430
|
+
*/
|
|
431
|
+
export declare function createGitvaultHttpTransport(client: Client, options?: GitvaultHttpTransportOptions): GitvaultTransport;
|
|
432
|
+
export declare const gitvaultPaths: {
|
|
433
|
+
readonly head: (generation: string) => string;
|
|
434
|
+
readonly admission: (generation: string) => string;
|
|
435
|
+
readonly wal: (id: string) => string;
|
|
436
|
+
readonly refState: (id: string) => string;
|
|
437
|
+
readonly retentionRoots: (id: string) => string;
|
|
438
|
+
readonly checkpointManifest: (id: string) => string;
|
|
439
|
+
readonly checkpointPack: (id: string) => string;
|
|
440
|
+
readonly claimSet: (id: string) => string;
|
|
441
|
+
readonly cutoffTicket: (id: string) => string;
|
|
442
|
+
/** `verifier-receipts/<vr>.json` — plaintext-structured, uploaded before a prune intent may reference it (§7.3). */
|
|
443
|
+
readonly verifierReceipt: (id: string) => string;
|
|
444
|
+
};
|
|
445
|
+
export interface GitvaultVaultOptions {
|
|
446
|
+
keystore: GitvaultKeystore;
|
|
447
|
+
transport: GitvaultTransport;
|
|
448
|
+
repo_id: string;
|
|
449
|
+
/** The local git repository (objects for pack building / ancestry); optional for read-only use. */
|
|
450
|
+
repo_dir?: string;
|
|
451
|
+
now?: () => Date;
|
|
452
|
+
/** Verification budget per call (resumable — the verified prefix persists). */
|
|
453
|
+
verification_budget?: number;
|
|
454
|
+
conflict_retries?: number;
|
|
455
|
+
/** The signing service key resolved through the registry — when supplied, control-plane-signed messages (cutoff tickets) are signature-checked. */
|
|
456
|
+
service_public_key?: Uint8Array | string;
|
|
457
|
+
}
|
|
458
|
+
/** How a checkpoint-bearing head binds a `retention_cutoff` ticket and expires roots (§4.5a / §4.5). */
|
|
459
|
+
export interface GitvaultCutoffOptions {
|
|
460
|
+
/**
|
|
461
|
+
* `effective_admitted_at` for a root's drop generation, or `null` when this
|
|
462
|
+
* client cannot resolve it — a `null` RETAINS the root (expiry is permissive).
|
|
463
|
+
* `effective_admitted_at = max(prepared_at, the admission record's storage
|
|
464
|
+
* creation time)`; deriving it from `prepared_at` alone shortens the lane.
|
|
465
|
+
*/
|
|
466
|
+
effectiveAdmittedAt?: (droppedAtGeneration: string) => string | null;
|
|
467
|
+
}
|
|
468
|
+
export interface GitvaultVerifiedState {
|
|
469
|
+
generation: string;
|
|
470
|
+
head_sha256: string;
|
|
471
|
+
/** `null` at generation zero. */
|
|
472
|
+
head: GitvaultHead | null;
|
|
473
|
+
genesis: GitvaultVaultGenesis;
|
|
474
|
+
}
|
|
475
|
+
export interface GitvaultMaterializedState extends GitvaultVerifiedState {
|
|
476
|
+
ref_state: GitvaultRefState | null;
|
|
477
|
+
retention_roots: GitvaultRetentionRoots | null;
|
|
478
|
+
refs: GitvaultRefMap;
|
|
479
|
+
roots: GitvaultRetentionRoot[];
|
|
480
|
+
head_target: GitvaultHeadTarget;
|
|
481
|
+
}
|
|
482
|
+
export interface GitvaultPushOptions {
|
|
483
|
+
transaction: GitvaultRefTransaction;
|
|
484
|
+
/** New `HEAD` target for the published ref_state; carried forward when omitted. */
|
|
485
|
+
head_target?: GitvaultHeadTarget;
|
|
486
|
+
protocol_refs?: "refuse" | "allow";
|
|
487
|
+
/** Force the checkpoint-bearing form (purpose `ordinary_push`) regardless of delta size. */
|
|
488
|
+
checkpoint?: boolean;
|
|
489
|
+
/** Bind a fresh `retention_cutoff` ticket so expired roots may leave the map (checkpoint-bearing heads only). */
|
|
490
|
+
cutoff?: GitvaultCutoffOptions;
|
|
491
|
+
/** Built lazily at head-sign time — the deploy lane may still be computing the plan digest. */
|
|
492
|
+
capture_binding?: GitvaultCaptureBinding | (() => Promise<GitvaultCaptureBinding | null> | GitvaultCaptureBinding | null);
|
|
493
|
+
}
|
|
494
|
+
export interface GitvaultPublishResult {
|
|
495
|
+
generation: string;
|
|
496
|
+
head_sha256: string;
|
|
497
|
+
head: GitvaultHead;
|
|
498
|
+
admission_record_sha256: string;
|
|
499
|
+
capture_receipt: GitvaultCaptureReceipt | null;
|
|
500
|
+
/** `wal` = direct WAL receipts; `checkpoint` = the delta shipped as a checkpoint set. */
|
|
501
|
+
form: "wal" | "checkpoint";
|
|
502
|
+
conflicts_retried: number;
|
|
503
|
+
refs: GitvaultRefMap;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* What {@link GitvaultVault.verifyStoredCheckpoint} observed. Every boolean is
|
|
507
|
+
* a FINDING, not a promise: a `false` here is what makes a truthful negative
|
|
508
|
+
* `verifier_receipt` possible.
|
|
509
|
+
*/
|
|
510
|
+
export interface GitvaultStoredCheckpointAttestation {
|
|
511
|
+
checkpoint_head_sha256: string;
|
|
512
|
+
checkpoint_generation: string;
|
|
513
|
+
claim_set_sha256: string;
|
|
514
|
+
/** `null` in the no-removal checkpoint form — a prune needs one, so that is a refusal upstream. */
|
|
515
|
+
cutoff_ticket_sha256: string | null;
|
|
516
|
+
cutoff_at: string | null;
|
|
517
|
+
covered_tips: string[];
|
|
518
|
+
/** Covered tips that did NOT resolve from the restored set. Non-empty ⇒ the checkpoint does not verify. */
|
|
519
|
+
missing_tips: string[];
|
|
520
|
+
restored_object_set_hmac: string;
|
|
521
|
+
object_set_matches: boolean;
|
|
522
|
+
ref_state_matches: boolean;
|
|
523
|
+
retention_roots_matches: boolean;
|
|
524
|
+
/** The `rootset` commitment over this generation's roots carrier — the intent core's `retention_state_hmac`. */
|
|
525
|
+
retention_state_hmac: string;
|
|
526
|
+
}
|
|
527
|
+
export interface GitvaultBuiltCheckpoint {
|
|
528
|
+
manifest: GitvaultCheckpointManifest;
|
|
529
|
+
claim_set: GitvaultCheckpointClaimSet;
|
|
530
|
+
claim_set_receipt: GitvaultCheckpointBlock["claim_set"];
|
|
531
|
+
objects: GitvaultUploadObject[];
|
|
532
|
+
/** Plaintext packs in order (for the acceptance self-check). */
|
|
533
|
+
packs: Uint8Array[];
|
|
534
|
+
covered_tips: string[];
|
|
535
|
+
}
|
|
536
|
+
/** A transport-agnostic view of git ops the publication needs (the local repository). */
|
|
537
|
+
export declare class GitvaultVault {
|
|
538
|
+
readonly keystore: GitvaultKeystore;
|
|
539
|
+
readonly transport: GitvaultTransport;
|
|
540
|
+
readonly repoId: string;
|
|
541
|
+
readonly repoDir: string | null;
|
|
542
|
+
private readonly now;
|
|
543
|
+
private readonly budget;
|
|
544
|
+
private readonly retries;
|
|
545
|
+
private readonly servicePublicKey;
|
|
546
|
+
private genesisCache;
|
|
547
|
+
constructor(options: GitvaultVaultOptions);
|
|
548
|
+
static open(options: GitvaultVaultOptions): GitvaultVault;
|
|
549
|
+
repoFile(): GitvaultRepoFile;
|
|
550
|
+
private kRepo;
|
|
551
|
+
private epoch;
|
|
552
|
+
private git;
|
|
553
|
+
/** Fetch + pin-check the genesis (the writer key source). */
|
|
554
|
+
genesis(): Promise<{
|
|
555
|
+
genesis: GitvaultVaultGenesis;
|
|
556
|
+
sha256: string;
|
|
557
|
+
}>;
|
|
558
|
+
/**
|
|
559
|
+
* List from the authenticated pin and verify every link upward. Persists
|
|
560
|
+
* the verified prefix after each page, so a `VERIFICATION_BUDGET_EXCEEDED`
|
|
561
|
+
* continues rather than restarts. Returns the newest verified state.
|
|
562
|
+
*/
|
|
563
|
+
verifyToNewest(): Promise<GitvaultVerifiedState>;
|
|
564
|
+
private readHead;
|
|
565
|
+
/** Decrypt one encrypted carrier object by its receipt; any failure is `CHAIN_UNUSABLE`. */
|
|
566
|
+
private openCarrier;
|
|
567
|
+
/** Verify to newest, then decrypt + apply its carriers — advancing the materialized pin. */
|
|
568
|
+
materialize(): Promise<GitvaultMaterializedState>;
|
|
569
|
+
private seal;
|
|
570
|
+
/**
|
|
571
|
+
* The owner signing seed, or `GITVAULT_READ_ONLY`.
|
|
572
|
+
*
|
|
573
|
+
* Public so the prune lane signs its intent core, wrapper, and verifier
|
|
574
|
+
* receipt through the SAME refusal path every other signed object uses — a
|
|
575
|
+
* second "get the seed" helper is a second place for a read-only principal to
|
|
576
|
+
* slip through. The vault is already open by the time this is reachable, so
|
|
577
|
+
* `ensureIdentity` never MINTS here (it would refuse at `repoFile()` first).
|
|
578
|
+
*/
|
|
579
|
+
signer(): Uint8Array;
|
|
580
|
+
private writerKeyId;
|
|
581
|
+
private buildRefState;
|
|
582
|
+
private buildRetentionRoots;
|
|
583
|
+
/** Plaintext, independently non-thin packs covering `reachable(tips) ∖ reachable(base)`, split at the multi-object target. */
|
|
584
|
+
buildPacks(tips: string[], base: string[]): Promise<Uint8Array[]>;
|
|
585
|
+
/** Sorted unique object ids reachable from `tips` (the `"objectset"` content). */
|
|
586
|
+
objectSet(tips: string[]): Promise<string[]>;
|
|
587
|
+
/**
|
|
588
|
+
* The same `"objectset"` content computed in an ARBITRARY repository.
|
|
589
|
+
*
|
|
590
|
+
* The prune lane's restore-and-verify pass runs against a scratch clone-back,
|
|
591
|
+
* not the working tree, and must recompute the digest there with the same
|
|
592
|
+
* canonicalization the manifest was built with — hence one implementation,
|
|
593
|
+
* parameterized by directory, rather than a second rev-list at the call site.
|
|
594
|
+
*/
|
|
595
|
+
objectSetIn(dir: string, tips: string[]): Promise<string[]>;
|
|
596
|
+
/**
|
|
597
|
+
* Decrypt one generation's `retention_roots` carrier by its head receipt.
|
|
598
|
+
*
|
|
599
|
+
* `materialize()` opens only the NEWEST carrier; the prune lane must compare
|
|
600
|
+
* consecutive generations to see which roots LEFT the map, so it needs any
|
|
601
|
+
* generation's. Same `openCarrier` path, same `CHAIN_UNUSABLE` semantics — a
|
|
602
|
+
* carrier that cannot be opened is never silently treated as empty.
|
|
603
|
+
*/
|
|
604
|
+
openRetentionRootsAt(receipt: GitvaultRetentionRootsReceipt): Promise<GitvaultRetentionRoots>;
|
|
605
|
+
private digest;
|
|
606
|
+
/**
|
|
607
|
+
* The §1 keyed commitment under one of the five `K_digest` labels.
|
|
608
|
+
*
|
|
609
|
+
* Public because the prune lane needs `gcrootset` (over the GC root set's
|
|
610
|
+
* sorted receipts) and `rootset` (over the retention-roots carrier) and must
|
|
611
|
+
* compute them with the SAME key derivation the checkpoint manifest uses —
|
|
612
|
+
* two derivations for one commitment is how a verifier and a publisher stop
|
|
613
|
+
* agreeing. Keyed by design (§7.3): a server-comparable plaintext digest
|
|
614
|
+
* would be a confirmation oracle.
|
|
615
|
+
*/
|
|
616
|
+
keyedDigest(label: GitvaultDigestLabel, content: unknown): string;
|
|
617
|
+
/** Strip the single top-level signature — the commitment preimage shape carriers use. */
|
|
618
|
+
digestPreimage<T extends {
|
|
619
|
+
signature: string;
|
|
620
|
+
}>(o: T): Omit<T, "signature">;
|
|
621
|
+
private withoutSignature;
|
|
622
|
+
/** Coverage tips (§4.7): canonical refs ∪ unexpired roots ∪ the HEAD target (detached commit; an unborn symref contributes nothing). */
|
|
623
|
+
static coverageTips(refs: GitvaultRefMap, roots: GitvaultRetentionRoot[], headTarget: GitvaultHeadTarget): string[];
|
|
624
|
+
/**
|
|
625
|
+
* Build a checkpoint set (§4.7): manifest + packs + the owner-signed claim
|
|
626
|
+
* set, with the acceptance self-check (restore into an empty scratch, every
|
|
627
|
+
* covered tip resolves, full connectivity, all three keyed commitments
|
|
628
|
+
* recomputed). Coverage above the V0 maximum → `CHECKPOINT_SET_LIMIT_EXCEEDED`.
|
|
629
|
+
*/
|
|
630
|
+
buildCheckpoint(input: {
|
|
631
|
+
generation: string;
|
|
632
|
+
ref_state: GitvaultRefState;
|
|
633
|
+
retention_roots: GitvaultRetentionRoots;
|
|
634
|
+
}): Promise<GitvaultBuiltCheckpoint>;
|
|
635
|
+
/** §4.7 acceptance: restore from the set ALONE into an empty scratch; every covered ref resolves; fsck connectivity; recompute the three commitments. */
|
|
636
|
+
acceptCheckpoint(built: GitvaultBuiltCheckpoint, refState: GitvaultRefState, roots: GitvaultRetentionRoots): Promise<void>;
|
|
637
|
+
/**
|
|
638
|
+
* The §4.7 acceptance run against a checkpoint ALREADY IN STORAGE — the
|
|
639
|
+
* restore-and-verify pass a `verifier_receipt` attests (§7.3).
|
|
640
|
+
*
|
|
641
|
+
* `acceptCheckpoint` above proves a checkpoint the client just BUILT; this
|
|
642
|
+
* proves one the client is about to make a claim about, from the stored bytes
|
|
643
|
+
* alone. It reports the observed facts rather than throwing on a mismatch,
|
|
644
|
+
* because "the checkpoint does not verify" is exactly the finding a receipt
|
|
645
|
+
* must be able to carry as `false` — turning it into an exception would make
|
|
646
|
+
* an honest negative attestation impossible to produce.
|
|
647
|
+
*/
|
|
648
|
+
verifyStoredCheckpoint(head: GitvaultHead, headSha256: string): Promise<GitvaultStoredCheckpointAttestation>;
|
|
649
|
+
/**
|
|
650
|
+
* The whole verified chain, newest-first walk returned oldest-first, each
|
|
651
|
+
* head paired with its checkpoint claim set (`null` when it bears none).
|
|
652
|
+
*
|
|
653
|
+
* The prune lane needs EVERY generation, not just the newest: a candidate is
|
|
654
|
+
* an object some head once named and no surviving head still needs, and that
|
|
655
|
+
* is only computable over the whole chain. Reuses {@link chainFrom}, so the
|
|
656
|
+
* bytes are re-read and hash-checked against the verified chain rather than
|
|
657
|
+
* trusted from a listing.
|
|
658
|
+
*/
|
|
659
|
+
chainEntries(): Promise<Array<{
|
|
660
|
+
head: GitvaultHead;
|
|
661
|
+
head_sha256: string;
|
|
662
|
+
claim_set: GitvaultCheckpointClaimSet | null;
|
|
663
|
+
}>>;
|
|
664
|
+
private uploadAll;
|
|
665
|
+
/**
|
|
666
|
+
* Build + upload + sign + admit ONE generation over `base`. Shared by the ref
|
|
667
|
+
* transaction path (`push`) and the checkpoint-only path (`publishCheckpoint`); the
|
|
668
|
+
* caller owns the conflict loop because only it knows how to re-derive the
|
|
669
|
+
* next state from the winner.
|
|
670
|
+
*/
|
|
671
|
+
private publishGeneration;
|
|
672
|
+
/** The complete push: verify → materialize → evaluate → pack → upload → head → admit (409: re-apply to the winner, retry) → read back → advance pins. */
|
|
673
|
+
push(options: GitvaultPushOptions): Promise<GitvaultPublishResult>;
|
|
674
|
+
/**
|
|
675
|
+
* Publish an `ordinary_push` checkpoint-bearing head that changes NO ref (the
|
|
676
|
+
* canonical map and HEAD target are carried forward). With a cutoff the head
|
|
677
|
+
* binds a fresh `retention_cutoff` ticket and roots past their ≥90-day lane
|
|
678
|
+
* may leave the map; without one it is the no-removal form (§4.5a) and every
|
|
679
|
+
* root is carried.
|
|
680
|
+
*
|
|
681
|
+
* Root expiry is PERMISSIVE: a root whose `effective_admitted_at` this client
|
|
682
|
+
* cannot resolve is RETAINED. That is deliberate — `effective_admitted_at =
|
|
683
|
+
* max(prepared_at, the admission record's storage creation time)`, and a client
|
|
684
|
+
* reading only object bytes cannot see the second term. Resolving it from
|
|
685
|
+
* `prepared_at` alone would shorten the lane, which the protocol's own
|
|
686
|
+
* delayed-PUT vector calls out as the naive implementation.
|
|
687
|
+
*
|
|
688
|
+
* This is NOT `run402 gitvault compact`: the §7.2 maintenance CYCLE (purpose
|
|
689
|
+
* `maintenance_cycle`, C1/C2 roles, stage claim sets, prune intents, `R2_cap`
|
|
690
|
+
* accounting) is a separate protocol under compact authority, and gets its own
|
|
691
|
+
* method when it ships.
|
|
692
|
+
*/
|
|
693
|
+
publishCheckpoint(options?: {
|
|
694
|
+
cutoff?: GitvaultCutoffOptions | false;
|
|
695
|
+
}): Promise<GitvaultPublishResult>;
|
|
696
|
+
/** Request a `retention_cutoff` ticket and check it binds THIS base head (and the service key, when one is pinned). */
|
|
697
|
+
private issueRetentionCutoff;
|
|
698
|
+
private signHead;
|
|
699
|
+
/** Admit a signed head; on success read it back from storage and compare BEFORE any pin advances. */
|
|
700
|
+
private admit;
|
|
701
|
+
/**
|
|
702
|
+
* Publish a repair head over `base_generation` (§4.3): superseded tips that
|
|
703
|
+
* the repaired state no longer reaches enter the retention-root map with
|
|
704
|
+
* `dropped_at_generation = the repair generation`; the head carries the
|
|
705
|
+
* mandatory self-contained checkpoint. Coverage that cannot be built →
|
|
706
|
+
* `REPAIR_TARGET_UNPRESERVABLE`. A repair never crosses an admitted transition.
|
|
707
|
+
*/
|
|
708
|
+
repair(input: {
|
|
709
|
+
base_generation: string;
|
|
710
|
+
reason: GitvaultRepairDescriptor["reason"];
|
|
711
|
+
}): Promise<GitvaultPublishResult>;
|
|
712
|
+
/** Heads `base..newest` (already chain-verified by `verifyToNewest`) re-read + hash-checked from storage. */
|
|
713
|
+
private chainFrom;
|
|
714
|
+
/**
|
|
715
|
+
* Pull the newest checkpoint (if any) and every later WAL pack into
|
|
716
|
+
* `targetRepoDir` (an initialized repository), then verify every canonical
|
|
717
|
+
* ref + the HEAD target resolves. Returns the materialized refs.
|
|
718
|
+
*/
|
|
719
|
+
restoreObjectsInto(targetRepoDir: string): Promise<{
|
|
720
|
+
refs: GitvaultRefMap;
|
|
721
|
+
head_target: GitvaultHeadTarget;
|
|
722
|
+
generation: string;
|
|
723
|
+
}>;
|
|
724
|
+
}
|
|
725
|
+
/** §4.7 cross-field equality: covers_through agree; the claim set's ordered pack ids/hashes/sizes/total equal the manifest's (shared stored fields only). */
|
|
726
|
+
export declare function checkClaimSetEquality(claimSet: GitvaultCheckpointClaimSet, manifest: GitvaultCheckpointManifest, headCoversThrough: string): void;
|
|
727
|
+
/** Convenience for the deploy lane: the §6.5 capture binding. */
|
|
728
|
+
export declare function captureBinding(captureId: string, applyPlanSha256: string | null, snapshotOidHmac: string): GitvaultCaptureBinding;
|
|
729
|
+
export type { GitvaultRefUpdate };
|
|
730
|
+
//# sourceMappingURL=gitvault-publication.d.ts.map
|