@msn-control/liftoff 0.11.1 → 0.11.2
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/DEVELOPER.md +28 -10
- package/README.md +11 -6
- package/dist/adapters/filesystem/project-transaction.d.ts +2 -1
- package/dist/adapters/filesystem/project-transaction.js +25 -6
- package/dist/adapters/filesystem/project-transaction.js.map +1 -1
- package/dist/adapters/filesystem/reviewed-update-transaction.d.ts +53 -0
- package/dist/adapters/filesystem/reviewed-update-transaction.js +864 -0
- package/dist/adapters/filesystem/reviewed-update-transaction.js.map +1 -0
- package/dist/adapters/filesystem/update-previews.d.ts +50 -0
- package/dist/adapters/filesystem/update-previews.js +613 -0
- package/dist/adapters/filesystem/update-previews.js.map +1 -0
- package/dist/adapters/process/shell-command.d.ts +1 -0
- package/dist/adapters/process/shell-command.js +7 -1
- package/dist/adapters/process/shell-command.js.map +1 -1
- package/dist/application/context.d.ts +5 -0
- package/dist/application/diagnose/doctor.js +9 -15
- package/dist/application/diagnose/doctor.js.map +1 -1
- package/dist/application/update/approval.d.ts +39 -0
- package/dist/application/update/approval.js +54 -0
- package/dist/application/update/approval.js.map +1 -0
- package/dist/application/update/command-guidance.d.ts +2 -0
- package/dist/application/update/command-guidance.js +14 -0
- package/dist/application/update/command-guidance.js.map +1 -0
- package/dist/application/update/inspection.d.ts +37 -0
- package/dist/application/update/inspection.js +235 -0
- package/dist/application/update/inspection.js.map +1 -0
- package/dist/application/update/migration-runtime.d.ts +14 -0
- package/dist/application/update/migration-runtime.js +178 -0
- package/dist/application/update/migration-runtime.js.map +1 -0
- package/dist/application/update/output.d.ts +134 -0
- package/dist/application/update/output.js +182 -0
- package/dist/application/update/output.js.map +1 -0
- package/dist/application/update/preview.d.ts +49 -0
- package/dist/application/update/preview.js +220 -0
- package/dist/application/update/preview.js.map +1 -0
- package/dist/application/update/protected-source.d.ts +25 -0
- package/dist/application/update/protected-source.js +81 -0
- package/dist/application/update/protected-source.js.map +1 -0
- package/dist/application/update/reporting.d.ts +4 -4
- package/dist/application/update/reporting.js +14 -13
- package/dist/application/update/reporting.js.map +1 -1
- package/dist/application/update/revalidation-plan.d.ts +22 -0
- package/dist/application/update/revalidation-plan.js +108 -0
- package/dist/application/update/revalidation-plan.js.map +1 -0
- package/dist/application/update/revalidation.d.ts +70 -0
- package/dist/application/update/revalidation.js +337 -0
- package/dist/application/update/revalidation.js.map +1 -0
- package/dist/application/update/review-plan.d.ts +25 -0
- package/dist/application/update/review-plan.js +89 -0
- package/dist/application/update/review-plan.js.map +1 -0
- package/dist/application/update/transaction-approval.d.ts +29 -0
- package/dist/application/update/transaction-approval.js +82 -0
- package/dist/application/update/transaction-approval.js.map +1 -0
- package/dist/application/update/use-case.d.ts +1 -0
- package/dist/application/update/use-case.js +240 -569
- package/dist/application/update/use-case.js.map +1 -1
- package/dist/application/update/write-plan.d.ts +15 -0
- package/dist/application/update/write-plan.js +115 -0
- package/dist/application/update/write-plan.js.map +1 -0
- package/dist/cli/args/definitions.js +5 -4
- package/dist/cli/args/definitions.js.map +1 -1
- package/dist/cli/args/help.js +13 -1
- package/dist/cli/args/help.js.map +1 -1
- package/dist/cli/args/parser.js +22 -7
- package/dist/cli/args/parser.js.map +1 -1
- package/dist/cli/commands/update.js +1 -0
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/domain/governance/policy/identity.d.ts +1 -1
- package/dist/domain/governance/policy/identity.js +2 -2
- package/dist/domain/governance/policy/identity.js.map +1 -1
- package/dist/domain/project/infrastructure-layout.d.ts +1 -1
- package/dist/domain/project/infrastructure-layout.js +2 -1
- package/dist/domain/project/infrastructure-layout.js.map +1 -1
- package/dist/domain/project/reviewed-update-artifacts.d.ts +2 -0
- package/dist/domain/project/reviewed-update-artifacts.js +3 -0
- package/dist/domain/project/reviewed-update-artifacts.js.map +1 -0
- package/dist/generators/common/base.js +5 -1
- package/dist/generators/common/base.js.map +1 -1
- package/dist/governance-activation/activation-state.js +4 -1
- package/dist/governance-activation/activation-state.js.map +1 -1
- package/dist/governance-activation/commands.d.ts +5 -0
- package/dist/governance-activation/commands.js +65 -3
- package/dist/governance-activation/commands.js.map +1 -1
- package/dist/governance-activation/compatibility.d.ts +21 -4
- package/dist/governance-activation/compatibility.js +47 -8
- package/dist/governance-activation/compatibility.js.map +1 -1
- package/dist/governance-activation/doctor.js +32 -5
- package/dist/governance-activation/doctor.js.map +1 -1
- package/dist/governance-activation/historical-state.d.ts +81 -0
- package/dist/governance-activation/historical-state.js +817 -0
- package/dist/governance-activation/historical-state.js.map +1 -0
- package/dist/governance-activation/history-contracts.d.ts +109 -0
- package/dist/governance-activation/history-contracts.js +303 -0
- package/dist/governance-activation/history-contracts.js.map +1 -0
- package/dist/governance-activation/inputs.d.ts +2 -0
- package/dist/governance-activation/inputs.js +13 -1
- package/dist/governance-activation/inputs.js.map +1 -1
- package/dist/governance-activation/migration-history.d.ts +97 -0
- package/dist/governance-activation/migration-history.js +388 -0
- package/dist/governance-activation/migration-history.js.map +1 -0
- package/dist/governance-activation/migration.js +1 -1
- package/dist/governance-activation/migration.js.map +1 -1
- package/dist/governance-activation/proof-records.d.ts +3 -0
- package/dist/governance-activation/proof-records.js +78 -0
- package/dist/governance-activation/proof-records.js.map +1 -0
- package/dist/governance-activation/read-only.d.ts +4 -4
- package/dist/governance-activation/read-only.js +9 -69
- package/dist/governance-activation/read-only.js.map +1 -1
- package/dist/governance-activation/seed-lifecycle.d.ts +28 -6
- package/dist/governance-activation/seed-lifecycle.js +258 -25
- package/dist/governance-activation/seed-lifecycle.js.map +1 -1
- package/dist/governance-activation/transition-planning.d.ts +2 -0
- package/dist/governance-activation/transition-planning.js +12 -3
- package/dist/governance-activation/transition-planning.js.map +1 -1
- package/dist/governance-activation/transitions.d.ts +8 -2
- package/dist/governance-activation/transitions.js +36 -11
- package/dist/governance-activation/transitions.js.map +1 -1
- package/dist/governance-assessment/engine.js +30 -3
- package/dist/governance-assessment/engine.js.map +1 -1
- package/dist/governance-assessment/project.d.ts +7 -0
- package/dist/governance-assessment/project.js +44 -4
- package/dist/governance-assessment/project.js.map +1 -1
- package/dist/repository-governance.js +25 -12
- package/dist/repository-governance.js.map +1 -1
- package/docs/cli-reference.md +101 -28
- package/docs/configuration-and-manifests.md +27 -15
- package/docs/existing-repositories.md +19 -10
- package/docs/repository-governance.md +9 -5
- package/docs/safety-and-consent.md +27 -18
- package/docs/troubleshooting.md +9 -7
- package/docs/workloads.md +5 -4
- package/package.json +1 -1
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import { realpath } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { loadManifest } from '../project/manifest.js';
|
|
4
|
+
import { canonicalSha256 } from '../../domain/governance/activation/canonical-json.js';
|
|
5
|
+
import { selectLatestPhaseEvidence } from '../../domain/governance/activation/evidence.js';
|
|
6
|
+
import { phaseById } from '../../domain/governance/activation/operations.js';
|
|
7
|
+
import { validateManifestActivationForExecution } from '../../domain/governance/activation/validators.js';
|
|
8
|
+
import { inspectGovernanceTransition } from '../../governance-activation/commands.js';
|
|
9
|
+
import { previewLocalSeedPhase } from '../../governance-activation/seed-lifecycle.js';
|
|
10
|
+
import { evidencePathParts, evidenceWriteOperation, safeTimestamp, stateWriteOperation } from '../../governance-activation/transition-records.js';
|
|
11
|
+
import { executeApplyNext } from '../../governance-activation/transitions.js';
|
|
12
|
+
import { NodeCommandRunner, formatCommand } from '../../process-runner.js';
|
|
13
|
+
import { acceptDeclaredCommandOutputs, captureRetainedProjectInputs, changedRetainedProjectInputs, localValidationOutputPolicy, outputsForLocalCommand } from './protected-source.js';
|
|
14
|
+
import { formatUpdateCommand } from './command-guidance.js';
|
|
15
|
+
import { commandShellForPlatform, formatShellCommand } from '../../adapters/process/shell-command.js';
|
|
16
|
+
const localPhases = ['seed-valid', 'seed-verified', 'seed-archived'];
|
|
17
|
+
const successfulStates = new Set(['verified', 'approved', 'inapplicable', 'retained', 'disposed']);
|
|
18
|
+
const commandTimeoutMs = 120_000;
|
|
19
|
+
const commandOutputLimit = 2 * 1024 * 1024;
|
|
20
|
+
function isLocalPhase(phaseId) {
|
|
21
|
+
return phaseId === 'seed-valid' || phaseId === 'seed-verified' || phaseId === 'seed-archived';
|
|
22
|
+
}
|
|
23
|
+
function inspectionCommands() {
|
|
24
|
+
return [
|
|
25
|
+
['rev-parse', '--show-toplevel'],
|
|
26
|
+
['rev-parse', '--verify', 'HEAD'],
|
|
27
|
+
['symbolic-ref', '--quiet', '--short', 'HEAD'],
|
|
28
|
+
['remote'],
|
|
29
|
+
['remote', 'get-url', '--push', '--all', 'origin']
|
|
30
|
+
].map((args) => ({ command: { executable: 'git', args }, cwdPathParts: [], env: {} }));
|
|
31
|
+
}
|
|
32
|
+
function executionDescription() {
|
|
33
|
+
return {
|
|
34
|
+
inspectionCommands: inspectionCommands(),
|
|
35
|
+
recordWrites: {
|
|
36
|
+
plans: 'governance/plans/<phase>-<fresh-timestamp>-<plan-digest>.json',
|
|
37
|
+
evidence: 'governance/evidence/<phase>-<fresh-timestamp>.json',
|
|
38
|
+
state: 'governance/activation-state.json',
|
|
39
|
+
limit: 'At most one new plan and evidence record per listed phase; existing records are never replaced.'
|
|
40
|
+
},
|
|
41
|
+
commandLimits: { timeoutMs: commandTimeoutMs, maxOutputBytes: commandOutputLimit },
|
|
42
|
+
outputPolicy: localValidationOutputPolicy,
|
|
43
|
+
effects: [
|
|
44
|
+
'Local validation executes project-controlled code, not a sandbox. Exact commands and environment overrides are listed per phase.',
|
|
45
|
+
'Only already available tools/dependencies are used. No dependency installation, tofu init, seed task edits, or archive replay is authorized.',
|
|
46
|
+
'Checks may write tool/test/build caches and outputs; unexpected protected-input edits are preserved and block evidence.',
|
|
47
|
+
'Repository scripts, tests, and existing outputs are bound before approval. Only listed command-specific generated outputs may change after that approved command executes.',
|
|
48
|
+
'Fresh phase plans, evidence, and activation state are the only engine writes. The coordinator separately records migration progress.'
|
|
49
|
+
],
|
|
50
|
+
boundary: 'Stop before Git publication, provider reads, credentials, or independently approved governance transitions.'
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function assertDigest(value, label) {
|
|
54
|
+
if (!/^[a-f0-9]{64}$/.test(value))
|
|
55
|
+
throw new Error(`${label} must be a complete lowercase SHA-256 binding.`);
|
|
56
|
+
}
|
|
57
|
+
export async function previewLocalRevalidation(input) {
|
|
58
|
+
validateManifestActivationForExecution(input.targetManifest);
|
|
59
|
+
assertDigest(input.protectedInputBinding, 'Protected input');
|
|
60
|
+
const projectRoot = await realpath(input.projectRoot);
|
|
61
|
+
const identity = 'activationIdentity' in input.targetManifest.governance
|
|
62
|
+
? input.targetManifest.governance.activationIdentity : undefined;
|
|
63
|
+
if (!identity)
|
|
64
|
+
throw new Error('Local revalidation requires an explicit current activation target.');
|
|
65
|
+
const phases = [];
|
|
66
|
+
const reusedPhases = [];
|
|
67
|
+
const inspection = input.inspection;
|
|
68
|
+
const canReuse = inspection && inspection.projectRoot === projectRoot &&
|
|
69
|
+
canonicalSha256(inspection.manifest) === canonicalSha256(input.targetManifest) &&
|
|
70
|
+
canonicalSha256(inspection.state.identity) === canonicalSha256(identity);
|
|
71
|
+
for (const phaseId of localPhases) {
|
|
72
|
+
const selected = canReuse && inspection.readiness.phases[phaseId].state === 'verified'
|
|
73
|
+
? selectLatestPhaseEvidence(inspection.evidence.filter((record) => record.header.phaseId === phaseId), inspection.contexts[phaseId]).selected
|
|
74
|
+
: null;
|
|
75
|
+
if (selected?.header.result === 'verified') {
|
|
76
|
+
reusedPhases.push({ phaseId, evidenceId: selected.evidenceId, headerDigest: selected.headerDigest });
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
phases.push(await previewLocalSeedPhase(projectRoot, input.targetManifest, phaseId));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const semantic = {
|
|
83
|
+
schemaVersion: 1, scope: 'local-seed-revalidation', projectRoot, targetIdentity: identity,
|
|
84
|
+
targetManifestDigest: canonicalSha256(input.targetManifest), protectedInputBinding: input.protectedInputBinding,
|
|
85
|
+
phases, reusedPhases, ...executionDescription()
|
|
86
|
+
};
|
|
87
|
+
return { ...semantic, fingerprint: canonicalSha256(semantic) };
|
|
88
|
+
}
|
|
89
|
+
function nextIncompletePhase(inspection) {
|
|
90
|
+
return inspection.graph.phases.find((phase) => !successfulStates.has(inspection.readiness.phases[phase.id].state))?.id ?? null;
|
|
91
|
+
}
|
|
92
|
+
function resumableLocalInspection(inspection) {
|
|
93
|
+
const phaseId = nextIncompletePhase(inspection);
|
|
94
|
+
if (!phaseId || !isLocalPhase(phaseId) || inspection.readiness.phases[phaseId].state !== 'running' ||
|
|
95
|
+
inspection.readiness.phases[phaseId].blockers.length)
|
|
96
|
+
return inspection;
|
|
97
|
+
// An interrupted operation is re-executed under fresh approval, never counted as proof.
|
|
98
|
+
return { ...inspection, readiness: { ...inspection.readiness, nextReadyPhase: phaseId } };
|
|
99
|
+
}
|
|
100
|
+
function commandMatches(expected, projectRoot, command, options) {
|
|
101
|
+
return canonicalSha256(expected.command) === canonicalSha256(command) &&
|
|
102
|
+
path.resolve(options?.cwd ?? projectRoot) === path.resolve(projectRoot, ...expected.cwdPathParts) &&
|
|
103
|
+
canonicalSha256(options?.env ?? {}) === canonicalSha256(expected.env) &&
|
|
104
|
+
options?.stdin === undefined && options?.signal === undefined;
|
|
105
|
+
}
|
|
106
|
+
// The coordinator supplies its approved post-commit input binding and persists progress;
|
|
107
|
+
// journal/phase-record writes must not invalidate that binding.
|
|
108
|
+
export async function executeLocalRevalidation(input) {
|
|
109
|
+
const approved = input.approvedPreview;
|
|
110
|
+
const runner = input.runner ?? new NodeCommandRunner();
|
|
111
|
+
const clock = input.clock ?? (() => new Date());
|
|
112
|
+
const phaseResults = [];
|
|
113
|
+
let current;
|
|
114
|
+
let activePhase = null;
|
|
115
|
+
let protectedSnapshot;
|
|
116
|
+
let expectedCommands = [];
|
|
117
|
+
let commandIndex = 0;
|
|
118
|
+
async function assertProtectedInputs() {
|
|
119
|
+
// Reuse only the inventory freshly checked by the coordinator, never one cached across boundaries.
|
|
120
|
+
const observed = await input.protectedInputs.assertUnchanged();
|
|
121
|
+
if (protectedSnapshot) {
|
|
122
|
+
const changed = changedRetainedProjectInputs(protectedSnapshot, observed ?? await captureRetainedProjectInputs(approved.projectRoot));
|
|
123
|
+
if (changed.length)
|
|
124
|
+
throw new Error(`Protected inputs changed during local revalidation: ${changed.join(', ')}. Edits were preserved; no stale successful evidence is authorized. Run ${formatUpdateCommand(approved.projectRoot, 'check')} again.`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const guardedRunner = {
|
|
128
|
+
async run(command, options) {
|
|
129
|
+
const metadata = inspectionCommands().some((expected) => commandMatches(expected, approved.projectRoot, command, options));
|
|
130
|
+
const expected = expectedCommands[commandIndex];
|
|
131
|
+
if (!metadata && (!expected || !commandMatches(expected, approved.projectRoot, command, options))) {
|
|
132
|
+
throw new Error(`Operation is outside the approved local revalidation command sequence: ${formatCommand(command)}. Obtain a fresh preview.`);
|
|
133
|
+
}
|
|
134
|
+
if (metadata) {
|
|
135
|
+
const result = await runner.run(command, { ...options, timeoutMs: commandTimeoutMs, maxOutputBytes: commandOutputLimit });
|
|
136
|
+
if (canonicalSha256(result.command) !== canonicalSha256(command))
|
|
137
|
+
throw new Error('The local runner returned an outcome for a different command.');
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
await assertProtectedInputs();
|
|
141
|
+
let result;
|
|
142
|
+
try {
|
|
143
|
+
result = await runner.run(command, { ...options, timeoutMs: commandTimeoutMs, maxOutputBytes: commandOutputLimit });
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
const observed = await input.protectedInputs.afterCommand?.(command, options);
|
|
147
|
+
if (protectedSnapshot) {
|
|
148
|
+
protectedSnapshot = acceptDeclaredCommandOutputs(protectedSnapshot, observed ?? await captureRetainedProjectInputs(approved.projectRoot), outputsForLocalCommand(approved.projectRoot, command, options));
|
|
149
|
+
}
|
|
150
|
+
await assertProtectedInputs();
|
|
151
|
+
}
|
|
152
|
+
if (canonicalSha256(result.command) !== canonicalSha256(command))
|
|
153
|
+
throw new Error('The local runner returned an outcome for a different command.');
|
|
154
|
+
commandIndex += 1;
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
const metadataRunner = {
|
|
159
|
+
async run(command, options) {
|
|
160
|
+
if (!inspectionCommands().some((expected) => commandMatches(expected, approved.projectRoot, command, options))) {
|
|
161
|
+
throw new Error('Revalidation inspection attempted a command outside the local Git metadata allowlist.');
|
|
162
|
+
}
|
|
163
|
+
return runner.run(command, { ...options, timeoutMs: commandTimeoutMs, maxOutputBytes: commandOutputLimit });
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const reinspect = async () => {
|
|
167
|
+
await assertProtectedInputs();
|
|
168
|
+
const inspection = await inspectGovernanceTransition(approved.projectRoot, { runner: guardedRunner, now: clock() });
|
|
169
|
+
await assertProtectedInputs();
|
|
170
|
+
return resumableLocalInspection(inspection);
|
|
171
|
+
};
|
|
172
|
+
function result(status, blockers = []) {
|
|
173
|
+
const next = current ? nextIncompletePhase(current) : null;
|
|
174
|
+
return {
|
|
175
|
+
status, phaseId: status === 'blocked' ? activePhase : null, phaseResults: [...phaseResults],
|
|
176
|
+
nextIncompletePhase: next, blockers,
|
|
177
|
+
nextAction: status === 'blocked'
|
|
178
|
+
? `Repair the named local prerequisite or review the separate setup transition, then run ${formatUpdateCommand(approved.projectRoot, 'check')} and approve a fresh plan.`
|
|
179
|
+
: next ? `Local revalidation is complete. Review ${formatShellCommand({
|
|
180
|
+
executable: 'liftoff', args: ['governance', 'plan', '--project', approved.projectRoot]
|
|
181
|
+
}, commandShellForPlatform(process.platform))} for ${next}; update did not execute it.` : 'Local revalidation is complete.'
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
const { fingerprint, ...semantic } = approved;
|
|
186
|
+
if (fingerprint !== canonicalSha256(semantic))
|
|
187
|
+
throw new Error('The approved local revalidation preview was changed.');
|
|
188
|
+
if (approved.schemaVersion !== 1 || approved.scope !== 'local-seed-revalidation' ||
|
|
189
|
+
canonicalSha256({
|
|
190
|
+
inspectionCommands: approved.inspectionCommands, recordWrites: approved.recordWrites,
|
|
191
|
+
commandLimits: approved.commandLimits, outputPolicy: approved.outputPolicy,
|
|
192
|
+
effects: approved.effects, boundary: approved.boundary
|
|
193
|
+
}) !== canonicalSha256(executionDescription())) {
|
|
194
|
+
throw new Error('The approved local inspection, record-write, or command-limit descriptions changed; obtain a fresh preview.');
|
|
195
|
+
}
|
|
196
|
+
assertDigest(input.protectedInputs.binding, 'Current protected input');
|
|
197
|
+
if (input.protectedInputs.binding !== approved.protectedInputBinding)
|
|
198
|
+
throw new Error(`Protected input binding differs from the approved preview; run ${formatUpdateCommand(approved.projectRoot, 'check')} again.`);
|
|
199
|
+
if (await realpath(approved.projectRoot) !== approved.projectRoot)
|
|
200
|
+
throw new Error('The approved project boundary changed.');
|
|
201
|
+
if (approved.phases.length > localPhases.length ||
|
|
202
|
+
approved.phases.some((phase, index) => !localPhases.includes(phase.phaseId) ||
|
|
203
|
+
index > 0 && localPhases.indexOf(approved.phases[index - 1].phaseId) >= localPhases.indexOf(phase.phaseId))) {
|
|
204
|
+
throw new Error('The approved local phase set is not a finite ordered seed revalidation plan.');
|
|
205
|
+
}
|
|
206
|
+
await assertProtectedInputs();
|
|
207
|
+
const manifest = await loadManifest(approved.projectRoot);
|
|
208
|
+
validateManifestActivationForExecution(manifest);
|
|
209
|
+
if (!('activationIdentity' in manifest.governance) || canonicalSha256(manifest) !== approved.targetManifestDigest ||
|
|
210
|
+
canonicalSha256(manifest.governance.activationIdentity) !== canonicalSha256(approved.targetIdentity)) {
|
|
211
|
+
throw new Error('The committed target manifest/activation differs from the approved revalidation preview.');
|
|
212
|
+
}
|
|
213
|
+
protectedSnapshot = await captureRetainedProjectInputs(approved.projectRoot);
|
|
214
|
+
current = await reinspect();
|
|
215
|
+
if (!current.loadedState || current.state.repository.id === 'unbound') {
|
|
216
|
+
throw new Error('Local revalidation starts only after the anchored v2 successor is committed.');
|
|
217
|
+
}
|
|
218
|
+
for (const reused of approved.reusedPhases) {
|
|
219
|
+
const selected = selectLatestPhaseEvidence(current.evidence.filter((record) => record.header.phaseId === reused.phaseId), current.contexts[reused.phaseId]).selected;
|
|
220
|
+
if (current.readiness.phases[reused.phaseId].state !== 'verified' || selected?.evidenceId !== reused.evidenceId ||
|
|
221
|
+
selected.headerDigest !== reused.headerDigest)
|
|
222
|
+
throw new Error(`Previously reviewed proof for ${reused.phaseId} is no longer current; obtain a fresh preview.`);
|
|
223
|
+
phaseResults.push({
|
|
224
|
+
phaseId: reused.phaseId, status: 'already-complete', blockers: [], savedPlan: null,
|
|
225
|
+
evidence: { evidenceId: selected.evidenceId, pathParts: evidencePathParts(selected.evidenceId), headerDigest: selected.headerDigest, result: selected.header.result }
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
for (const phase of approved.phases) {
|
|
229
|
+
activePhase = phase.phaseId;
|
|
230
|
+
await assertProtectedInputs();
|
|
231
|
+
current = await reinspect();
|
|
232
|
+
if (current.readiness.phases[phase.phaseId].state === 'verified') {
|
|
233
|
+
const selected = selectLatestPhaseEvidence(current.evidence.filter((record) => record.header.phaseId === phase.phaseId), current.contexts[phase.phaseId]).selected;
|
|
234
|
+
if (!selected || selected.header.result !== 'verified')
|
|
235
|
+
throw new Error(`No current authoritative evidence remains for ${phase.phaseId}.`);
|
|
236
|
+
phaseResults.push({
|
|
237
|
+
phaseId: phase.phaseId, status: 'already-complete', blockers: [], savedPlan: null,
|
|
238
|
+
evidence: { evidenceId: selected.evidenceId, pathParts: evidencePathParts(selected.evidenceId), headerDigest: selected.headerDigest, result: selected.header.result }
|
|
239
|
+
});
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
const next = nextIncompletePhase(current);
|
|
243
|
+
if (next !== phase.phaseId || current.readiness.nextReadyPhase !== phase.phaseId) {
|
|
244
|
+
throw new Error(`The next genuinely incomplete phase is ${next ?? 'none'}, not an executable approved ${phase.phaseId}. ${next ? current.readiness.phases[next].blockers.join(' ') : ''}`);
|
|
245
|
+
}
|
|
246
|
+
const fresh = await previewLocalSeedPhase(approved.projectRoot, current.manifest, phase.phaseId);
|
|
247
|
+
if (canonicalSha256(fresh) !== canonicalSha256(phase))
|
|
248
|
+
throw new Error(`The approved ${phase.phaseId} operations or prerequisites changed; obtain a fresh preview.`);
|
|
249
|
+
if (fresh.blockers.length)
|
|
250
|
+
throw new Error(fresh.blockers.join(' '));
|
|
251
|
+
expectedCommands = fresh.commands;
|
|
252
|
+
commandIndex = 0;
|
|
253
|
+
await input.onProgress?.({
|
|
254
|
+
status: 'running', phaseId: activePhase, phaseResults: [...phaseResults],
|
|
255
|
+
nextIncompletePhase: next, blockers: []
|
|
256
|
+
});
|
|
257
|
+
const execution = await executeApplyNext({
|
|
258
|
+
inspection: current, reinspect, runner: guardedRunner, clock, localRevalidation: true,
|
|
259
|
+
assertProtectedInputs,
|
|
260
|
+
assertReviewedPlan(plan) {
|
|
261
|
+
const node = phaseById(current.graph, phase.phaseId);
|
|
262
|
+
const context = current.contexts[phase.phaseId];
|
|
263
|
+
const expectedOperations = [
|
|
264
|
+
phase.operation,
|
|
265
|
+
evidenceWriteOperation(node, evidencePathParts(`${phase.phaseId}-${safeTimestamp(plan.createdAt)}`)),
|
|
266
|
+
stateWriteOperation(node)
|
|
267
|
+
];
|
|
268
|
+
if (plan.phaseId !== phase.phaseId || canonicalSha256(plan.identity) !== canonicalSha256(approved.targetIdentity) ||
|
|
269
|
+
plan.graphHash !== approved.targetIdentity.phaseGraphHash || plan.stateHash !== current.loadedState?.contentHash ||
|
|
270
|
+
plan.baselineDigest !== context.baselineSha || plan.inputDigest !== context.inputDigest ||
|
|
271
|
+
plan.transitionDigest !== context.transition.transitionDigest || canonicalSha256(plan.operations) !== canonicalSha256(expectedOperations)) {
|
|
272
|
+
throw new Error(`Saved transition operations for ${phase.phaseId} exceed the exact approved local preview.`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
phaseResults.push({
|
|
277
|
+
phaseId: phase.phaseId, status: execution.applied ? 'verified' : 'blocked',
|
|
278
|
+
blockers: execution.blockers, evidence: execution.evidence, savedPlan: execution.savedPlan
|
|
279
|
+
});
|
|
280
|
+
if (!execution.applied)
|
|
281
|
+
throw new Error(execution.blockers.join(' ') || execution.message);
|
|
282
|
+
if (commandIndex !== expectedCommands.length)
|
|
283
|
+
throw new Error(`The ${phase.phaseId} outcome omitted reviewed local checks.`);
|
|
284
|
+
current = await reinspect();
|
|
285
|
+
if (current.readiness.phases[phase.phaseId].state !== 'verified')
|
|
286
|
+
throw new Error(`The newly produced ${phase.phaseId} proof is not current.`);
|
|
287
|
+
}
|
|
288
|
+
await assertProtectedInputs();
|
|
289
|
+
current = await reinspect();
|
|
290
|
+
const incompleteLocal = localPhases.find((phaseId) => current.readiness.phases[phaseId].state !== 'verified');
|
|
291
|
+
if (incompleteLocal) {
|
|
292
|
+
activePhase = incompleteLocal;
|
|
293
|
+
throw new Error(`Local phase ${incompleteLocal} remains incomplete and is outside the completed approved operation set.`);
|
|
294
|
+
}
|
|
295
|
+
activePhase = null;
|
|
296
|
+
const complete = result('complete');
|
|
297
|
+
await input.onProgress?.(complete);
|
|
298
|
+
return complete;
|
|
299
|
+
}
|
|
300
|
+
catch (error) {
|
|
301
|
+
const blocker = error instanceof Error ? error.message : String(error);
|
|
302
|
+
const blockers = [blocker];
|
|
303
|
+
if (current) {
|
|
304
|
+
try {
|
|
305
|
+
current = await inspectGovernanceTransition(approved.projectRoot, { runner: metadataRunner, now: clock() });
|
|
306
|
+
for (const [index, phase] of phaseResults.entries()) {
|
|
307
|
+
if (phase.status !== 'blocked' && current.readiness.phases[phase.phaseId].state !== 'verified') {
|
|
308
|
+
phaseResults[index] = { ...phase, status: 'blocked', blockers: [
|
|
309
|
+
...current.readiness.phases[phase.phaseId].blockers,
|
|
310
|
+
'Previously observed proof is no longer current after revalidation; preserved inputs require a fresh preview.'
|
|
311
|
+
] };
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
catch (inspectionError) {
|
|
316
|
+
current = undefined;
|
|
317
|
+
blockers.push(`Current revalidation readiness cannot be inspected: ${inspectionError instanceof Error ? inspectionError.message : String(inspectionError)}`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (activePhase && !phaseResults.some((phase) => phase.phaseId === activePhase && phase.status === 'blocked')) {
|
|
321
|
+
const existing = phaseResults.findIndex((phase) => phase.phaseId === activePhase);
|
|
322
|
+
if (existing >= 0)
|
|
323
|
+
phaseResults[existing] = { ...phaseResults[existing], status: 'blocked', blockers: [blocker] };
|
|
324
|
+
else
|
|
325
|
+
phaseResults.push({ phaseId: activePhase, status: 'blocked', blockers: [blocker], evidence: null, savedPlan: null });
|
|
326
|
+
}
|
|
327
|
+
const blocked = result('blocked', blockers);
|
|
328
|
+
try {
|
|
329
|
+
await input.onProgress?.(blocked);
|
|
330
|
+
}
|
|
331
|
+
catch (progressError) {
|
|
332
|
+
return { ...blocked, blockers: [...blocked.blockers, `Revalidation progress could not be persisted: ${progressError instanceof Error ? progressError.message : String(progressError)}`] };
|
|
333
|
+
}
|
|
334
|
+
return blocked;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
//# sourceMappingURL=revalidation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revalidation.js","sourceRoot":"","sources":["../../../src/application/update/revalidation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type UpdateInspection } from './inspection.js';
|
|
2
|
+
import type { UpdatePlanSummary } from './output.js';
|
|
3
|
+
import type { CommandRunner } from '../../process-runner.js';
|
|
4
|
+
export declare function prepareUpdateReview(inspection: UpdateInspection, force: boolean, options?: {
|
|
5
|
+
runner?: CommandRunner;
|
|
6
|
+
now?: Date;
|
|
7
|
+
}): Promise<{
|
|
8
|
+
descriptor: import("./preview.js").UpdatePreviewDescriptor;
|
|
9
|
+
summary: UpdatePlanSummary;
|
|
10
|
+
writePlan: {
|
|
11
|
+
force: boolean;
|
|
12
|
+
mutations: import("../../file-system.js").ProjectFileMutation[];
|
|
13
|
+
nextManifest: import("../../types.js").LiftoffManifest;
|
|
14
|
+
written: import("../../reconcile.js").ReconcileEntry[];
|
|
15
|
+
retired: import("../../reconcile.js").ReconcileEntry[];
|
|
16
|
+
skipped: import("../../reconcile.js").ReconcileEntry[];
|
|
17
|
+
provisioned: import("./planning.js").ProvisioningEntry[];
|
|
18
|
+
hasWrites: boolean;
|
|
19
|
+
};
|
|
20
|
+
preconditions: import("../../file-system.js").ProjectFileSnapshot[];
|
|
21
|
+
revalidation: import("./revalidation-plan.js").PreparedUpdateRevalidation | undefined;
|
|
22
|
+
needsRevalidation: boolean;
|
|
23
|
+
requiresApproval: boolean;
|
|
24
|
+
}>;
|
|
25
|
+
export type ReviewedUpdatePlan = Awaited<ReturnType<typeof prepareUpdateReview>>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { liftoffVersion } from '../../version.js';
|
|
3
|
+
import { createUpdatePreviewDescriptor } from './preview.js';
|
|
4
|
+
import { uniqueUpdateSnapshots } from './inspection.js';
|
|
5
|
+
import { planUpdateWrites } from './write-plan.js';
|
|
6
|
+
import { prepareUpdateRevalidation } from './revalidation-plan.js';
|
|
7
|
+
function digest(content) {
|
|
8
|
+
return createHash('sha256').update(content).digest('hex');
|
|
9
|
+
}
|
|
10
|
+
export async function prepareUpdateReview(inspection, force, options = {}) {
|
|
11
|
+
const writePlan = planUpdateWrites(inspection, force);
|
|
12
|
+
const revalidation = await prepareUpdateRevalidation(inspection, writePlan, options);
|
|
13
|
+
const preconditions = uniqueUpdateSnapshots([
|
|
14
|
+
...inspection.snapshots,
|
|
15
|
+
...inspection.stateMigration.preconditions
|
|
16
|
+
], inspection.projectRoot).sort((left, right) => left.pathParts.join('\0').localeCompare(right.pathParts.join('\0'), 'en'));
|
|
17
|
+
const blockers = inspection.reconciliation.status === 'blocked'
|
|
18
|
+
? [...inspection.reconciliation.issues] : [];
|
|
19
|
+
if (inspection.historyMigration.status === 'eligible' && writePlan.skipped.length > 0) {
|
|
20
|
+
blockers.push(`Required target managed-core conflicts remain: ${writePlan.skipped
|
|
21
|
+
.map((entry) => entry.pathParts.join('/')).join(', ')}. Review a forceable variant or resolve unowned destinations.`);
|
|
22
|
+
}
|
|
23
|
+
const history = inspection.historyMigration;
|
|
24
|
+
const needsRevalidation = revalidation !== undefined && (revalidation.preview.phases.length > 0 ||
|
|
25
|
+
history.status === 'current' && history.history.status === 'committed' &&
|
|
26
|
+
history.history.journal.revalidation.status !== 'complete');
|
|
27
|
+
const historyWriteCount = history.status === 'eligible'
|
|
28
|
+
? (history.historyDisposition === 'create' ? history.index.files.length + 1 : 0) +
|
|
29
|
+
history.requiredRetirements.length + 2
|
|
30
|
+
: 0;
|
|
31
|
+
const descriptor = createUpdatePreviewDescriptor({
|
|
32
|
+
projectRoot: inspection.projectRoot,
|
|
33
|
+
cliVersion: liftoffVersion,
|
|
34
|
+
mode: force ? 'force' : 'normal',
|
|
35
|
+
source: {
|
|
36
|
+
repositoryRoot: inspection.repositoryRoot ?? null,
|
|
37
|
+
files: preconditions.map((snapshot) => ({
|
|
38
|
+
pathParts: snapshot.pathParts,
|
|
39
|
+
kind: snapshot.content === undefined ? 'missing' : 'file',
|
|
40
|
+
contentDigest: snapshot.content === undefined ? null : digest(snapshot.content),
|
|
41
|
+
mode: snapshot.mode ?? null
|
|
42
|
+
})),
|
|
43
|
+
migration: history.status === 'eligible' ? history.semanticPlan :
|
|
44
|
+
history.status === 'current' && history.history.status === 'committed'
|
|
45
|
+
? history.history.journal : null,
|
|
46
|
+
revalidationSource: inspection.revalidationSource ?? null,
|
|
47
|
+
retainedSource: inspection.retainedSource ?? null
|
|
48
|
+
},
|
|
49
|
+
target: {
|
|
50
|
+
manifest: JSON.stringify(writePlan.nextManifest),
|
|
51
|
+
artifacts: inspection.render.filter((artifact) => artifact.lifecycle === 'managed-core').map((artifact) => ({
|
|
52
|
+
logicalName: artifact.logicalName,
|
|
53
|
+
pathParts: artifact.pathParts,
|
|
54
|
+
contentDigest: digest(artifact.content)
|
|
55
|
+
}))
|
|
56
|
+
},
|
|
57
|
+
operations: {
|
|
58
|
+
mutations: writePlan.mutations.map((mutation) => ({
|
|
59
|
+
type: mutation.type,
|
|
60
|
+
pathParts: mutation.pathParts,
|
|
61
|
+
...(mutation.type === 'write' ? { contentDigest: digest(mutation.content), mode: mutation.mode ?? null } : {})
|
|
62
|
+
})),
|
|
63
|
+
migration: history.status === 'eligible' ? history.semanticPlan : null,
|
|
64
|
+
revalidation: revalidation?.preview ?? null,
|
|
65
|
+
provisioning: inspection.provisioningPlans.map((group) => ({
|
|
66
|
+
group: group.group,
|
|
67
|
+
blocked: group.blocked,
|
|
68
|
+
entries: group.entries.map((entry) => ({
|
|
69
|
+
status: entry.status,
|
|
70
|
+
pathParts: entry.rendered.pathParts,
|
|
71
|
+
contentDigest: digest(entry.rendered.content)
|
|
72
|
+
}))
|
|
73
|
+
}))
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
const summary = {
|
|
77
|
+
mode: descriptor.mode,
|
|
78
|
+
fingerprint: descriptor.fingerprint,
|
|
79
|
+
eligible: blockers.length === 0,
|
|
80
|
+
writeCount: writePlan.mutations.length + historyWriteCount +
|
|
81
|
+
(needsRevalidation && history.status !== 'eligible' ? 1 : 0),
|
|
82
|
+
blockers
|
|
83
|
+
};
|
|
84
|
+
return {
|
|
85
|
+
descriptor, summary, writePlan, preconditions, revalidation, needsRevalidation,
|
|
86
|
+
requiresApproval: writePlan.hasWrites || history.status === 'eligible' || needsRevalidation
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=review-plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-plan.js","sourceRoot":"","sources":["../../../src/application/update/review-plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAyB,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAGnE,SAAS,MAAM,CAAC,OAAwB;IACtC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,UAA4B,EAC5B,KAAc,EACd,OAAO,GAA2C,EAAE;IAEpD,MAAM,SAAS,GAAG,gBAAgB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACtD,MAAM,YAAY,GAAG,MAAM,yBAAyB,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IACrF,MAAM,aAAa,GAAG,qBAAqB,CAAC;QAC1C,GAAG,UAAU,CAAC,SAAS;QACvB,GAAG,UAAU,CAAC,cAAc,CAAC,aAAa;KAC3C,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAC5H,MAAM,QAAQ,GAAG,UAAU,CAAC,cAAc,CAAC,MAAM,KAAK,SAAS;QAC7D,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/C,IAAI,UAAU,CAAC,gBAAgB,CAAC,MAAM,KAAK,UAAU,IAAI,SAAS,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtF,QAAQ,CAAC,IAAI,CAAC,kDAAkD,SAAS,CAAC,OAAO;aAC9E,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;IAC1H,CAAC;IACD,MAAM,OAAO,GAAG,UAAU,CAAC,gBAAgB,CAAC;IAC5C,MAAM,iBAAiB,GAAG,YAAY,KAAK,SAAS,IAAI,CACtD,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QACtC,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,WAAW;YACpE,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,KAAK,UAAU,CAC7D,CAAC;IACF,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,KAAK,UAAU;QACrD,CAAC,CAAC,CAAC,OAAO,CAAC,kBAAkB,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9E,OAAO,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC;QACxC,CAAC,CAAC,CAAC,CAAC;IACN,MAAM,UAAU,GAAG,6BAA6B,CAAC;QAC/C,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,UAAU,EAAE,cAAc;QAC1B,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;QAChC,MAAM,EAAE;YACN,cAAc,EAAE,UAAU,CAAC,cAAc,IAAI,IAAI;YACjD,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACtC,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,IAAI,EAAE,QAAQ,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM;gBACzD,aAAa,EAAE,QAAQ,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAC/E,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,IAAI;aAC5B,CAAC,CAAC;YACH,SAAS,EAAE,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;gBAC/D,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,WAAW;oBACpE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;YACpC,kBAAkB,EAAE,UAAU,CAAC,kBAAkB,IAAI,IAAI;YACzD,cAAc,EAAE,UAAU,CAAC,cAAc,IAAI,IAAI;SAClD;QACD,MAAM,EAAE;YACN,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,YAAY,CAAC;YAChD,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,KAAK,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBAC1G,WAAW,EAAE,QAAQ,CAAC,WAAW;gBACjC,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;aACxC,CAAC,CAAC;SACJ;QACD,UAAU,EAAE;YACV,SAAS,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBAChD,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,GAAG,CAAC,QAAQ,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC/G,CAAC,CAAC;YACH,SAAS,EAAE,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI;YACtE,YAAY,EAAE,YAAY,EAAE,OAAO,IAAI,IAAI;YAC3C,YAAY,EAAE,UAAU,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACzD,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBACrC,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS;oBACnC,aAAa,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;iBAC9C,CAAC,CAAC;aACJ,CAAC,CAAC;SACJ;KACF,CAAC,CAAC;IACH,MAAM,OAAO,GAAsB;QACjC,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,QAAQ,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC;QAC/B,UAAU,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,iBAAiB;YACxD,CAAC,iBAAiB,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9D,QAAQ;KACT,CAAC;IACF,OAAO;QACL,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB;QAC9E,gBAAgB,EAAE,SAAS,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,IAAI,iBAAiB;KAC5F,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const updateTransactionApprovalSchemaVersion = 1;
|
|
2
|
+
export interface UpdateTransactionApprovalStore {
|
|
3
|
+
/** Only the explicit-approval coordinator may write transaction or checkpoint seals. */
|
|
4
|
+
write(planFingerprint: string, transactionDigest: string): Promise<void>;
|
|
5
|
+
verify(planFingerprint: string, transactionDigest: string): Promise<boolean>;
|
|
6
|
+
remove(planFingerprint: string, transactionDigest: string): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export interface UpdateTransactionApprovalBinding {
|
|
9
|
+
readonly projectRoot: string;
|
|
10
|
+
readonly planFingerprint: string;
|
|
11
|
+
readonly transactionDigest: string;
|
|
12
|
+
}
|
|
13
|
+
export interface UpdateTransactionApprovalSeal extends UpdateTransactionApprovalBinding {
|
|
14
|
+
readonly schemaVersion: typeof updateTransactionApprovalSchemaVersion;
|
|
15
|
+
readonly kind: 'liftoff-update-transaction-approval';
|
|
16
|
+
readonly projectKey: string;
|
|
17
|
+
readonly approvalId: string;
|
|
18
|
+
readonly approvedAt: string;
|
|
19
|
+
}
|
|
20
|
+
export declare class UpdateTransactionApprovalError extends Error {
|
|
21
|
+
constructor(message: string, options?: ErrorOptions);
|
|
22
|
+
}
|
|
23
|
+
export declare function validateUpdateTransactionApprovalDigests(planFingerprint: unknown, transactionDigest: unknown): void;
|
|
24
|
+
export declare function updateTransactionApprovalKey(binding: UpdateTransactionApprovalBinding): string;
|
|
25
|
+
export declare function createUpdateTransactionApprovalSeal(binding: UpdateTransactionApprovalBinding, issuance: {
|
|
26
|
+
approvalId: string;
|
|
27
|
+
approvedAt: string;
|
|
28
|
+
}): UpdateTransactionApprovalSeal;
|
|
29
|
+
export declare function validateUpdateTransactionApprovalSeal(value: unknown, expected: UpdateTransactionApprovalBinding, now: Date): UpdateTransactionApprovalSeal;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { canonicalSha256, isRecord } from '../../domain/governance/activation/canonical-json.js';
|
|
2
|
+
import { normalizeUpdatePreviewProjectRoot, updatePreviewProjectKey } from './preview.js';
|
|
3
|
+
export const updateTransactionApprovalSchemaVersion = 1;
|
|
4
|
+
export class UpdateTransactionApprovalError extends Error {
|
|
5
|
+
constructor(message, options) {
|
|
6
|
+
super(message, options);
|
|
7
|
+
this.name = 'UpdateTransactionApprovalError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function invalid(message) {
|
|
11
|
+
throw new UpdateTransactionApprovalError(message);
|
|
12
|
+
}
|
|
13
|
+
export function validateUpdateTransactionApprovalDigests(planFingerprint, transactionDigest) {
|
|
14
|
+
if (typeof planFingerprint !== 'string' || !/^[0-9a-f]{64}$/u.test(planFingerprint) ||
|
|
15
|
+
typeof transactionDigest !== 'string' || !/^[0-9a-f]{64}$/u.test(transactionDigest)) {
|
|
16
|
+
invalid('Transaction approval requires complete lowercase SHA-256 plan and transaction digests.');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function bindingFields(binding) {
|
|
20
|
+
validateUpdateTransactionApprovalDigests(binding.planFingerprint, binding.transactionDigest);
|
|
21
|
+
const projectRoot = normalizeUpdatePreviewProjectRoot(binding.projectRoot);
|
|
22
|
+
return {
|
|
23
|
+
schemaVersion: updateTransactionApprovalSchemaVersion,
|
|
24
|
+
kind: 'liftoff-update-transaction-approval',
|
|
25
|
+
projectRoot,
|
|
26
|
+
projectKey: updatePreviewProjectKey(projectRoot),
|
|
27
|
+
planFingerprint: binding.planFingerprint,
|
|
28
|
+
transactionDigest: binding.transactionDigest
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function updateTransactionApprovalKey(binding) {
|
|
32
|
+
return canonicalSha256(bindingFields(binding));
|
|
33
|
+
}
|
|
34
|
+
export function createUpdateTransactionApprovalSeal(binding, issuance) {
|
|
35
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u.test(issuance.approvalId)) {
|
|
36
|
+
invalid('Transaction approvalId must be a lowercase UUID.');
|
|
37
|
+
}
|
|
38
|
+
const time = Date.parse(issuance.approvedAt);
|
|
39
|
+
if (!Number.isFinite(time) || new Date(time).toISOString() !== issuance.approvedAt) {
|
|
40
|
+
invalid('Transaction approvedAt must be an ISO UTC timestamp.');
|
|
41
|
+
}
|
|
42
|
+
return Object.freeze({
|
|
43
|
+
...bindingFields(binding),
|
|
44
|
+
approvalId: issuance.approvalId,
|
|
45
|
+
approvedAt: issuance.approvedAt
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
export function validateUpdateTransactionApprovalSeal(value, expected, now) {
|
|
49
|
+
if (!isRecord(value))
|
|
50
|
+
invalid('Transaction approval seal must be an object.');
|
|
51
|
+
if (value.schemaVersion !== updateTransactionApprovalSchemaVersion) {
|
|
52
|
+
invalid('Unsupported or missing transaction approval schema; expected schema 1.');
|
|
53
|
+
}
|
|
54
|
+
const keys = [
|
|
55
|
+
'schemaVersion', 'kind', 'projectRoot', 'projectKey', 'planFingerprint', 'transactionDigest', 'approvalId', 'approvedAt'
|
|
56
|
+
];
|
|
57
|
+
if (Object.keys(value).length !== keys.length || keys.some((key) => !Object.hasOwn(value, key))) {
|
|
58
|
+
invalid('Transaction approval seal has missing or unrecognized fields.');
|
|
59
|
+
}
|
|
60
|
+
if (value.kind !== 'liftoff-update-transaction-approval' || typeof value.projectRoot !== 'string' ||
|
|
61
|
+
typeof value.planFingerprint !== 'string' || typeof value.transactionDigest !== 'string' ||
|
|
62
|
+
typeof value.approvalId !== 'string' || typeof value.approvedAt !== 'string') {
|
|
63
|
+
invalid('Invalid transaction approval seal; a preview receipt is not approval.');
|
|
64
|
+
}
|
|
65
|
+
const seal = createUpdateTransactionApprovalSeal({
|
|
66
|
+
projectRoot: value.projectRoot,
|
|
67
|
+
planFingerprint: value.planFingerprint,
|
|
68
|
+
transactionDigest: value.transactionDigest
|
|
69
|
+
}, { approvalId: value.approvalId, approvedAt: value.approvedAt });
|
|
70
|
+
if (seal.projectRoot !== value.projectRoot || seal.projectKey !== value.projectKey) {
|
|
71
|
+
invalid('Transaction approval seal has an inconsistent canonical project identity.');
|
|
72
|
+
}
|
|
73
|
+
if (seal.projectRoot !== normalizeUpdatePreviewProjectRoot(expected.projectRoot) ||
|
|
74
|
+
seal.planFingerprint !== expected.planFingerprint || seal.transactionDigest !== expected.transactionDigest) {
|
|
75
|
+
invalid('Transaction approval seal does not match this project, plan, and exact transaction digest.');
|
|
76
|
+
}
|
|
77
|
+
if (!Number.isFinite(now.getTime()) || Date.parse(seal.approvedAt) > now.getTime()) {
|
|
78
|
+
invalid('Transaction approval is dated in the future or the current clock is invalid.');
|
|
79
|
+
}
|
|
80
|
+
return seal;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=transaction-approval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction-approval.js","sourceRoot":"","sources":["../../../src/application/update/transaction-approval.ts"],"names":[],"mappings":"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"}
|