@tiangong-lca/cli 0.0.25 → 0.0.26

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.
@@ -0,0 +1,230 @@
1
+ import path from 'node:path';
2
+ import { buildAliasPlanRequest } from './dataset-maintenance-alias-request.js';
3
+ import { readProtectedJsonArtifact, materializePrivateArtifactDirectoryAtomically, writePrivateImmutableJson, writePrivateImmutableText, } from './dataset-maintenance-protected-artifacts.js';
4
+ import { validateProtectedBeforeState, } from './dataset-maintenance-protected-before.js';
5
+ import { parseMaintenancePlan, sha256Json, sha256Text, stableJsonText, } from './dataset-maintenance-contract.js';
6
+ import { PROTECTED_EXECUTION_COUNTS, } from './dataset-maintenance-protected-contract.js';
7
+ import { assertProtectedPreparationPlanSha256, assertProtectedProductionProjectRef, buildProtectedApprovalRequest, buildProtectedFreeze, deriveProtectedDerivativeSnapshotTargets, } from './dataset-maintenance-protected-preparation.js';
8
+ import { fetchMaintenanceAccountRows, resolveMaintenanceRemoteContext, } from './dataset-maintenance-remote.js';
9
+ import { parseProtectedToolchainEvidence, } from './dataset-maintenance-protected-toolchain.js';
10
+ import { CliError } from './errors.js';
11
+ export const PROTECTED_FREEZE_ARTIFACTS = {
12
+ alias_plan_request: 'protected-alias-plan-request.json',
13
+ derivative_baselines: 'protected-derivative-baselines.json',
14
+ freeze: 'protected-execution-freeze.json',
15
+ approval_request: 'protected-approval-request.json',
16
+ approval_text: 'protected-approval-request.txt',
17
+ report: 'protected-freeze-report.json',
18
+ };
19
+ const DEFAULT_FREEZE_DEPENDENCIES = {
20
+ readArtifact: readProtectedJsonArtifact,
21
+ parsePlan: parseMaintenancePlan,
22
+ buildAliasPlan: buildAliasPlanRequest,
23
+ resolveContext: resolveMaintenanceRemoteContext,
24
+ fetchAccountRows: fetchMaintenanceAccountRows,
25
+ parseToolchain: parseProtectedToolchainEvidence,
26
+ deriveTargets: deriveProtectedDerivativeSnapshotTargets,
27
+ validateBefore: validateProtectedBeforeState,
28
+ buildFreeze: buildProtectedFreeze,
29
+ buildApprovalRequest: buildProtectedApprovalRequest,
30
+ writeJson: writePrivateImmutableJson,
31
+ writeText: writePrivateImmutableText,
32
+ materializeArtifacts: materializePrivateArtifactDirectoryAtomically,
33
+ };
34
+ function requiredToken(value, label) {
35
+ if (!value || value.trim() !== value) {
36
+ throw new CliError(`${label} must be a non-empty canonical string.`, {
37
+ code: 'DATASET_MAINTENANCE_PROTECTED_FREEZE_INPUT_INVALID',
38
+ exitCode: 2,
39
+ });
40
+ }
41
+ return value;
42
+ }
43
+ function assertContext(options) {
44
+ const account = options.context.account;
45
+ if (options.context.project_ref !== options.expectedProjectRef ||
46
+ account.user_id !== options.plan.account.user_id ||
47
+ account.email !== options.plan.account.email ||
48
+ account.email !== options.confirm) {
49
+ throw new CliError('Authenticated context does not match the explicitly confirmed production project and plan account.', {
50
+ code: 'DATASET_MAINTENANCE_PROTECTED_FREEZE_CONTEXT_MISMATCH',
51
+ exitCode: 1,
52
+ details: {
53
+ expected_project_ref: options.expectedProjectRef,
54
+ observed_project_ref: options.context.project_ref,
55
+ expected_user_id: options.plan.account.user_id,
56
+ observed_user_id: account.user_id,
57
+ },
58
+ });
59
+ }
60
+ return { user_id: account.user_id, email: account.email };
61
+ }
62
+ function assertCanonicalToolchainArtifact(options) {
63
+ if (options.artifactText !== `${stableJsonText(options.evidence)}\n`) {
64
+ throw new CliError('Toolchain evidence must be canonical JSON with exactly one final newline.', {
65
+ code: 'DATASET_MAINTENANCE_PROTECTED_TOOLCHAIN_NONCANONICAL',
66
+ exitCode: 2,
67
+ });
68
+ }
69
+ }
70
+ function artifactPaths(outDir) {
71
+ const resolved = path.resolve(outDir);
72
+ return Object.fromEntries(Object.entries(PROTECTED_FREEZE_ARTIFACTS).map(([key, name]) => [
73
+ key,
74
+ path.join(resolved, name),
75
+ ]));
76
+ }
77
+ function buildBaselineManifest(options) {
78
+ const snapshots = options.validation.derivative_snapshots;
79
+ return {
80
+ schema_version: 'dataset-alias-derivative-baselines.v1',
81
+ environment: 'production',
82
+ project_ref: options.context.project_ref,
83
+ account: options.account,
84
+ plan: {
85
+ plan_sha256: options.plan.plan_sha256,
86
+ operation_id: options.plan.operation_id,
87
+ },
88
+ target_count: 50,
89
+ flow_count: 23,
90
+ process_count: 27,
91
+ derivative_baseline_set_sha256: options.derivativeBaselineSetSha256,
92
+ derivative_snapshot_set_sha256: sha256Json(snapshots),
93
+ snapshots,
94
+ };
95
+ }
96
+ export async function freezeDatasetMaintenanceProtected(options, dependencies = DEFAULT_FREEZE_DEPENDENCIES) {
97
+ const planPath = requiredToken(options.planPath, 'planPath');
98
+ const toolchainEvidencePath = requiredToken(options.toolchainEvidencePath, 'toolchainEvidencePath');
99
+ const outDir = requiredToken(options.outDir, 'outDir');
100
+ const expectedProjectRef = requiredToken(options.expectedProjectRef, 'expectedProjectRef');
101
+ assertProtectedProductionProjectRef(expectedProjectRef);
102
+ const confirm = requiredToken(options.confirm, 'confirm');
103
+ const cliVersion = requiredToken(options.cliVersion, 'cliVersion');
104
+ const generatedAtUtc = (options.now ?? new Date()).toISOString();
105
+ const planArtifact = dependencies.readArtifact({
106
+ filePath: planPath,
107
+ label: 'Protected maintenance plan',
108
+ });
109
+ const plan = dependencies.parsePlan(planArtifact.value);
110
+ assertProtectedPreparationPlanSha256(plan.plan_sha256, 'plan.plan_sha256');
111
+ const planDir = path.dirname(planArtifact.resolved);
112
+ const aliasPlanRequest = dependencies.buildAliasPlan({ plan, planDir });
113
+ const toolchainArtifact = dependencies.readArtifact({
114
+ filePath: toolchainEvidencePath,
115
+ label: 'Protected toolchain evidence',
116
+ });
117
+ const toolchainEvidence = dependencies.parseToolchain(toolchainArtifact.value, {
118
+ projectRef: expectedProjectRef,
119
+ cliVersion,
120
+ });
121
+ assertCanonicalToolchainArtifact({
122
+ artifactText: toolchainArtifact.text,
123
+ evidence: toolchainEvidence,
124
+ });
125
+ const context = await dependencies.resolveContext({
126
+ env: options.env,
127
+ fetchImpl: options.fetchImpl,
128
+ timeoutMs: options.timeoutMs,
129
+ now: options.now,
130
+ });
131
+ const account = assertContext({ context, plan, expectedProjectRef, confirm });
132
+ const current = await dependencies.fetchAccountRows({
133
+ context,
134
+ userId: account.user_id,
135
+ pageSize: options.pageSize,
136
+ });
137
+ const derivativeTargets = dependencies.deriveTargets(plan, account);
138
+ const validation = await dependencies.validateBefore({
139
+ plan,
140
+ planDir,
141
+ actorUserId: account.user_id,
142
+ currentRows: current.rows,
143
+ completeness: current.completeness,
144
+ context,
145
+ derivativeMode: 'capture',
146
+ derivativeTargets,
147
+ });
148
+ const builtFreeze = dependencies.buildFreeze({
149
+ plan,
150
+ planFileSha256: planArtifact.file_sha256,
151
+ aliasPlanRequest,
152
+ projectRef: context.project_ref,
153
+ account,
154
+ toolchainEvidenceSha256: toolchainArtifact.file_sha256,
155
+ derivativeSnapshots: validation.derivative_snapshots,
156
+ });
157
+ const approvalRequest = dependencies.buildApprovalRequest({
158
+ freeze: builtFreeze.value,
159
+ freezeFileSha256: builtFreeze.file_sha256,
160
+ approvedAtUtc: generatedAtUtc,
161
+ });
162
+ const baselineManifest = buildBaselineManifest({
163
+ context,
164
+ plan,
165
+ account,
166
+ validation,
167
+ derivativeBaselineSetSha256: builtFreeze.value.sets.derivative_baseline_set_sha256,
168
+ });
169
+ const paths = artifactPaths(outDir);
170
+ const aliasPlanText = `${stableJsonText(aliasPlanRequest)}\n`;
171
+ const baselineText = `${stableJsonText(baselineManifest)}\n`;
172
+ const report = {
173
+ schema_version: 'dataset-alias-protected-freeze-report.v1',
174
+ generated_at_utc: generatedAtUtc,
175
+ status: 'ready_for_human_approval',
176
+ remote_write_mode: 'read_only',
177
+ environment: 'production',
178
+ project_ref: context.project_ref,
179
+ account,
180
+ plan_sha256: plan.plan_sha256,
181
+ operation_id: plan.operation_id,
182
+ freeze_sha256: builtFreeze.value.freeze_sha256,
183
+ approval_request_sha256: approvalRequest.value.request_sha256,
184
+ approval_text_sha256: approvalRequest.value.approval_text_sha256,
185
+ toolchain_evidence_sha256: toolchainArtifact.file_sha256,
186
+ derivative_baseline_set_sha256: builtFreeze.value.sets.derivative_baseline_set_sha256,
187
+ derivative_snapshot_set_sha256: baselineManifest.derivative_snapshot_set_sha256,
188
+ counts: PROTECTED_EXECUTION_COUNTS,
189
+ assertions: {
190
+ account_census_complete: true,
191
+ strict_before_state: true,
192
+ projected_reference_closure: true,
193
+ support_snapshots: 6,
194
+ derivative_snapshots: 50,
195
+ preflight_calls: 0,
196
+ gate_calls: 0,
197
+ admission_calls: 0,
198
+ mutation_calls: 0,
199
+ approval_artifacts: 0,
200
+ },
201
+ artifacts: paths,
202
+ artifact_sha256: {
203
+ alias_plan_request: sha256Text(aliasPlanText),
204
+ derivative_baselines: sha256Text(baselineText),
205
+ freeze: builtFreeze.file_sha256,
206
+ approval_request: approvalRequest.file_sha256,
207
+ approval_text: approvalRequest.value.approval_text_sha256,
208
+ report: null,
209
+ },
210
+ };
211
+ dependencies.materializeArtifacts(outDir, (stagingDirectory) => {
212
+ const staging = artifactPaths(stagingDirectory);
213
+ dependencies.writeText(staging.alias_plan_request, aliasPlanText);
214
+ dependencies.writeText(staging.derivative_baselines, baselineText);
215
+ dependencies.writeText(staging.freeze, builtFreeze.canonical_file_text);
216
+ dependencies.writeText(staging.approval_request, approvalRequest.canonical_file_text);
217
+ dependencies.writeText(staging.approval_text, approvalRequest.value.approval_text);
218
+ dependencies.writeJson(staging.report, report);
219
+ });
220
+ return report;
221
+ }
222
+ export const __testInternals = {
223
+ artifactPaths,
224
+ assertCanonicalToolchainArtifact,
225
+ assertContext,
226
+ buildBaselineManifest,
227
+ DEFAULT_FREEZE_DEPENDENCIES,
228
+ requiredToken,
229
+ };
230
+ //# sourceMappingURL=dataset-maintenance-protected-freeze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataset-maintenance-protected-freeze.js","sourceRoot":"","sources":["../../../src/lib/dataset-maintenance-protected-freeze.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { buildAliasPlanRequest } from './dataset-maintenance-alias-request.js';\nimport {\n readProtectedJsonArtifact,\n materializePrivateArtifactDirectoryAtomically,\n writePrivateImmutableJson,\n writePrivateImmutableText,\n} from './dataset-maintenance-protected-artifacts.js';\nimport {\n validateProtectedBeforeState,\n type ProtectedBeforeValidationResult,\n} from './dataset-maintenance-protected-before.js';\nimport {\n parseMaintenancePlan,\n sha256Json,\n sha256Text,\n stableJsonText,\n type DatasetMaintenancePlan,\n} from './dataset-maintenance-contract.js';\nimport {\n PROTECTED_EXECUTION_COUNTS,\n type ProtectedDerivativeSnapshot,\n} from './dataset-maintenance-protected-contract.js';\nimport {\n assertProtectedPreparationPlanSha256,\n assertProtectedProductionProjectRef,\n buildProtectedApprovalRequest,\n buildProtectedFreeze,\n deriveProtectedDerivativeSnapshotTargets,\n} from './dataset-maintenance-protected-preparation.js';\nimport {\n fetchMaintenanceAccountRows,\n resolveMaintenanceRemoteContext,\n type DatasetMaintenanceRemoteContext,\n} from './dataset-maintenance-remote.js';\nimport {\n parseProtectedToolchainEvidence,\n type DatasetMaintenanceProtectedToolchainEvidence,\n} from './dataset-maintenance-protected-toolchain.js';\nimport { CliError } from './errors.js';\nimport type { FetchLike } from './http.js';\n\nexport const PROTECTED_FREEZE_ARTIFACTS = {\n alias_plan_request: 'protected-alias-plan-request.json',\n derivative_baselines: 'protected-derivative-baselines.json',\n freeze: 'protected-execution-freeze.json',\n approval_request: 'protected-approval-request.json',\n approval_text: 'protected-approval-request.txt',\n report: 'protected-freeze-report.json',\n} as const;\n\nexport type FreezeDatasetMaintenanceProtectedOptions = {\n planPath: string;\n toolchainEvidencePath: string;\n outDir: string;\n expectedProjectRef: string;\n confirm: string;\n cliVersion: string;\n pageSize?: number;\n timeoutMs?: number;\n env: NodeJS.ProcessEnv;\n fetchImpl: FetchLike;\n now?: Date;\n};\n\nexport type DatasetMaintenanceProtectedBaselineManifest = {\n schema_version: 'dataset-alias-derivative-baselines.v1';\n environment: 'production';\n project_ref: string;\n account: { user_id: string; email: string };\n plan: { plan_sha256: string; operation_id: string };\n target_count: 50;\n flow_count: 23;\n process_count: 27;\n derivative_baseline_set_sha256: string;\n derivative_snapshot_set_sha256: string;\n snapshots: ProtectedDerivativeSnapshot[];\n};\n\nexport type DatasetMaintenanceProtectedFreezeReport = {\n schema_version: 'dataset-alias-protected-freeze-report.v1';\n generated_at_utc: string;\n status: 'ready_for_human_approval';\n remote_write_mode: 'read_only';\n environment: 'production';\n project_ref: string;\n account: { user_id: string; email: string };\n plan_sha256: string;\n operation_id: string;\n freeze_sha256: string;\n approval_request_sha256: string;\n approval_text_sha256: string;\n toolchain_evidence_sha256: string;\n derivative_baseline_set_sha256: string;\n derivative_snapshot_set_sha256: string;\n counts: typeof PROTECTED_EXECUTION_COUNTS;\n assertions: {\n account_census_complete: true;\n strict_before_state: true;\n projected_reference_closure: true;\n support_snapshots: 6;\n derivative_snapshots: 50;\n preflight_calls: 0;\n gate_calls: 0;\n admission_calls: 0;\n mutation_calls: 0;\n approval_artifacts: 0;\n };\n artifacts: {\n alias_plan_request: string;\n derivative_baselines: string;\n freeze: string;\n approval_request: string;\n approval_text: string;\n report: string;\n };\n artifact_sha256: {\n alias_plan_request: string;\n derivative_baselines: string;\n freeze: string;\n approval_request: string;\n approval_text: string;\n report: null;\n };\n};\n\ntype FreezeProtectedDependencies = {\n readArtifact: typeof readProtectedJsonArtifact;\n parsePlan: typeof parseMaintenancePlan;\n buildAliasPlan: typeof buildAliasPlanRequest;\n resolveContext: typeof resolveMaintenanceRemoteContext;\n fetchAccountRows: typeof fetchMaintenanceAccountRows;\n parseToolchain: typeof parseProtectedToolchainEvidence;\n deriveTargets: typeof deriveProtectedDerivativeSnapshotTargets;\n validateBefore: typeof validateProtectedBeforeState;\n buildFreeze: typeof buildProtectedFreeze;\n buildApprovalRequest: typeof buildProtectedApprovalRequest;\n writeJson: typeof writePrivateImmutableJson;\n writeText: typeof writePrivateImmutableText;\n materializeArtifacts: typeof materializePrivateArtifactDirectoryAtomically;\n};\n\nconst DEFAULT_FREEZE_DEPENDENCIES: FreezeProtectedDependencies = {\n readArtifact: readProtectedJsonArtifact,\n parsePlan: parseMaintenancePlan,\n buildAliasPlan: buildAliasPlanRequest,\n resolveContext: resolveMaintenanceRemoteContext,\n fetchAccountRows: fetchMaintenanceAccountRows,\n parseToolchain: parseProtectedToolchainEvidence,\n deriveTargets: deriveProtectedDerivativeSnapshotTargets,\n validateBefore: validateProtectedBeforeState,\n buildFreeze: buildProtectedFreeze,\n buildApprovalRequest: buildProtectedApprovalRequest,\n writeJson: writePrivateImmutableJson,\n writeText: writePrivateImmutableText,\n materializeArtifacts: materializePrivateArtifactDirectoryAtomically,\n};\n\nfunction requiredToken(value: string, label: string): string {\n if (!value || value.trim() !== value) {\n throw new CliError(`${label} must be a non-empty canonical string.`, {\n code: 'DATASET_MAINTENANCE_PROTECTED_FREEZE_INPUT_INVALID',\n exitCode: 2,\n });\n }\n return value;\n}\n\nfunction assertContext(options: {\n context: DatasetMaintenanceRemoteContext;\n plan: DatasetMaintenancePlan;\n expectedProjectRef: string;\n confirm: string;\n}): { user_id: string; email: string } {\n const account = options.context.account;\n if (\n options.context.project_ref !== options.expectedProjectRef ||\n account.user_id !== options.plan.account.user_id ||\n account.email !== options.plan.account.email ||\n account.email !== options.confirm\n ) {\n throw new CliError(\n 'Authenticated context does not match the explicitly confirmed production project and plan account.',\n {\n code: 'DATASET_MAINTENANCE_PROTECTED_FREEZE_CONTEXT_MISMATCH',\n exitCode: 1,\n details: {\n expected_project_ref: options.expectedProjectRef,\n observed_project_ref: options.context.project_ref,\n expected_user_id: options.plan.account.user_id,\n observed_user_id: account.user_id,\n },\n },\n );\n }\n return { user_id: account.user_id, email: account.email };\n}\n\nfunction assertCanonicalToolchainArtifact(options: {\n artifactText: string;\n evidence: DatasetMaintenanceProtectedToolchainEvidence;\n}): void {\n if (options.artifactText !== `${stableJsonText(options.evidence)}\\n`) {\n throw new CliError(\n 'Toolchain evidence must be canonical JSON with exactly one final newline.',\n {\n code: 'DATASET_MAINTENANCE_PROTECTED_TOOLCHAIN_NONCANONICAL',\n exitCode: 2,\n },\n );\n }\n}\n\nfunction artifactPaths(outDir: string): DatasetMaintenanceProtectedFreezeReport['artifacts'] {\n const resolved = path.resolve(outDir);\n return Object.fromEntries(\n Object.entries(PROTECTED_FREEZE_ARTIFACTS).map(([key, name]) => [\n key,\n path.join(resolved, name),\n ]),\n ) as DatasetMaintenanceProtectedFreezeReport['artifacts'];\n}\n\nfunction buildBaselineManifest(options: {\n context: DatasetMaintenanceRemoteContext;\n plan: DatasetMaintenancePlan;\n account: { user_id: string; email: string };\n validation: ProtectedBeforeValidationResult;\n derivativeBaselineSetSha256: string;\n}): DatasetMaintenanceProtectedBaselineManifest {\n const snapshots = options.validation.derivative_snapshots;\n return {\n schema_version: 'dataset-alias-derivative-baselines.v1',\n environment: 'production',\n project_ref: options.context.project_ref,\n account: options.account,\n plan: {\n plan_sha256: options.plan.plan_sha256,\n operation_id: options.plan.operation_id,\n },\n target_count: 50,\n flow_count: 23,\n process_count: 27,\n derivative_baseline_set_sha256: options.derivativeBaselineSetSha256,\n derivative_snapshot_set_sha256: sha256Json(snapshots),\n snapshots,\n };\n}\n\nexport async function freezeDatasetMaintenanceProtected(\n options: FreezeDatasetMaintenanceProtectedOptions,\n dependencies: FreezeProtectedDependencies = DEFAULT_FREEZE_DEPENDENCIES,\n): Promise<DatasetMaintenanceProtectedFreezeReport> {\n const planPath = requiredToken(options.planPath, 'planPath');\n const toolchainEvidencePath = requiredToken(\n options.toolchainEvidencePath,\n 'toolchainEvidencePath',\n );\n const outDir = requiredToken(options.outDir, 'outDir');\n const expectedProjectRef = requiredToken(options.expectedProjectRef, 'expectedProjectRef');\n assertProtectedProductionProjectRef(expectedProjectRef);\n const confirm = requiredToken(options.confirm, 'confirm');\n const cliVersion = requiredToken(options.cliVersion, 'cliVersion');\n const generatedAtUtc = (options.now ?? new Date()).toISOString();\n\n const planArtifact = dependencies.readArtifact({\n filePath: planPath,\n label: 'Protected maintenance plan',\n });\n const plan = dependencies.parsePlan(planArtifact.value);\n assertProtectedPreparationPlanSha256(plan.plan_sha256, 'plan.plan_sha256');\n const planDir = path.dirname(planArtifact.resolved);\n const aliasPlanRequest = dependencies.buildAliasPlan({ plan, planDir });\n\n const toolchainArtifact = dependencies.readArtifact({\n filePath: toolchainEvidencePath,\n label: 'Protected toolchain evidence',\n });\n const toolchainEvidence = dependencies.parseToolchain(toolchainArtifact.value, {\n projectRef: expectedProjectRef,\n cliVersion,\n });\n assertCanonicalToolchainArtifact({\n artifactText: toolchainArtifact.text,\n evidence: toolchainEvidence,\n });\n\n const context = await dependencies.resolveContext({\n env: options.env,\n fetchImpl: options.fetchImpl,\n timeoutMs: options.timeoutMs,\n now: options.now,\n });\n const account = assertContext({ context, plan, expectedProjectRef, confirm });\n\n const current = await dependencies.fetchAccountRows({\n context,\n userId: account.user_id,\n pageSize: options.pageSize,\n });\n const derivativeTargets = dependencies.deriveTargets(plan, account);\n const validation = await dependencies.validateBefore({\n plan,\n planDir,\n actorUserId: account.user_id,\n currentRows: current.rows,\n completeness: current.completeness,\n context,\n derivativeMode: 'capture',\n derivativeTargets,\n });\n const builtFreeze = dependencies.buildFreeze({\n plan,\n planFileSha256: planArtifact.file_sha256,\n aliasPlanRequest,\n projectRef: context.project_ref,\n account,\n toolchainEvidenceSha256: toolchainArtifact.file_sha256,\n derivativeSnapshots: validation.derivative_snapshots,\n });\n const approvalRequest = dependencies.buildApprovalRequest({\n freeze: builtFreeze.value,\n freezeFileSha256: builtFreeze.file_sha256,\n approvedAtUtc: generatedAtUtc,\n });\n const baselineManifest = buildBaselineManifest({\n context,\n plan,\n account,\n validation,\n derivativeBaselineSetSha256: builtFreeze.value.sets.derivative_baseline_set_sha256,\n });\n const paths = artifactPaths(outDir);\n const aliasPlanText = `${stableJsonText(aliasPlanRequest)}\\n`;\n const baselineText = `${stableJsonText(baselineManifest)}\\n`;\n const report: DatasetMaintenanceProtectedFreezeReport = {\n schema_version: 'dataset-alias-protected-freeze-report.v1',\n generated_at_utc: generatedAtUtc,\n status: 'ready_for_human_approval',\n remote_write_mode: 'read_only',\n environment: 'production',\n project_ref: context.project_ref,\n account,\n plan_sha256: plan.plan_sha256,\n operation_id: plan.operation_id,\n freeze_sha256: builtFreeze.value.freeze_sha256,\n approval_request_sha256: approvalRequest.value.request_sha256,\n approval_text_sha256: approvalRequest.value.approval_text_sha256,\n toolchain_evidence_sha256: toolchainArtifact.file_sha256,\n derivative_baseline_set_sha256: builtFreeze.value.sets.derivative_baseline_set_sha256,\n derivative_snapshot_set_sha256: baselineManifest.derivative_snapshot_set_sha256,\n counts: PROTECTED_EXECUTION_COUNTS,\n assertions: {\n account_census_complete: true,\n strict_before_state: true,\n projected_reference_closure: true,\n support_snapshots: 6,\n derivative_snapshots: 50,\n preflight_calls: 0,\n gate_calls: 0,\n admission_calls: 0,\n mutation_calls: 0,\n approval_artifacts: 0,\n },\n artifacts: paths,\n artifact_sha256: {\n alias_plan_request: sha256Text(aliasPlanText),\n derivative_baselines: sha256Text(baselineText),\n freeze: builtFreeze.file_sha256,\n approval_request: approvalRequest.file_sha256,\n approval_text: approvalRequest.value.approval_text_sha256,\n report: null,\n },\n };\n\n dependencies.materializeArtifacts(outDir, (stagingDirectory) => {\n const staging = artifactPaths(stagingDirectory);\n dependencies.writeText(staging.alias_plan_request, aliasPlanText);\n dependencies.writeText(staging.derivative_baselines, baselineText);\n dependencies.writeText(staging.freeze, builtFreeze.canonical_file_text);\n dependencies.writeText(staging.approval_request, approvalRequest.canonical_file_text);\n dependencies.writeText(staging.approval_text, approvalRequest.value.approval_text);\n dependencies.writeJson(staging.report, report);\n });\n return report;\n}\n\nexport const __testInternals = {\n artifactPaths,\n assertCanonicalToolchainArtifact,\n assertContext,\n buildBaselineManifest,\n DEFAULT_FREEZE_DEPENDENCIES,\n requiredToken,\n};\n"]}