@msn-control/liftoff 0.11.3 → 0.12.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/DEVELOPER.md +19 -18
- package/README.md +18 -18
- package/assets/governance/single-maintainer-gitflow/activation-v2-graph.json +1583 -0
- package/dist/adapters/credentials/github-enrollment.d.ts +51 -0
- package/dist/adapters/credentials/github-enrollment.js +226 -0
- package/dist/adapters/credentials/github-enrollment.js.map +1 -0
- package/dist/adapters/credentials/protected-input.d.ts +7 -0
- package/dist/adapters/credentials/protected-input.js +68 -0
- package/dist/adapters/credentials/protected-input.js.map +1 -0
- package/dist/adapters/filesystem/executables.d.ts +2 -0
- package/dist/adapters/filesystem/executables.js +70 -0
- package/dist/adapters/filesystem/executables.js.map +1 -0
- package/dist/adapters/filesystem/update-previews.d.ts +9 -0
- package/dist/adapters/filesystem/update-previews.js +44 -0
- package/dist/adapters/filesystem/update-previews.js.map +1 -1
- package/dist/adapters/filesystem/workstation-attempts.d.ts +13 -0
- package/dist/adapters/filesystem/workstation-attempts.js +78 -0
- package/dist/adapters/filesystem/workstation-attempts.js.map +1 -0
- package/dist/adapters/github/activation-rest.d.ts +40 -0
- package/dist/adapters/github/activation-rest.js +272 -0
- package/dist/adapters/github/activation-rest.js.map +1 -0
- package/dist/adapters/state/azure-blob.d.ts +43 -0
- package/dist/adapters/state/azure-blob.js +335 -0
- package/dist/adapters/state/azure-blob.js.map +1 -0
- package/dist/adapters/state/darwin-capabilities.d.ts +33 -0
- package/dist/adapters/state/darwin-capabilities.js +146 -0
- package/dist/adapters/state/darwin-capabilities.js.map +1 -0
- package/dist/adapters/state/darwin-native-host.d.ts +32 -0
- package/dist/adapters/state/darwin-native-host.js +294 -0
- package/dist/adapters/state/darwin-native-host.js.map +1 -0
- package/dist/adapters/state/darwin-profile.d.ts +6 -0
- package/dist/adapters/state/darwin-profile.js +56 -0
- package/dist/adapters/state/darwin-profile.js.map +1 -0
- package/dist/adapters/state/darwin-system-program.d.ts +1 -0
- package/dist/adapters/state/darwin-system-program.js +94 -0
- package/dist/adapters/state/darwin-system-program.js.map +1 -0
- package/dist/adapters/state/local-qualification.d.ts +16 -0
- package/dist/adapters/state/local-qualification.js +299 -0
- package/dist/adapters/state/local-qualification.js.map +1 -0
- package/dist/adapters/state/local.d.ts +25 -0
- package/dist/adapters/state/local.js +145 -0
- package/dist/adapters/state/local.js.map +1 -0
- package/dist/adapters/state/native-command.d.ts +21 -0
- package/dist/adapters/state/native-command.js +82 -0
- package/dist/adapters/state/native-command.js.map +1 -0
- package/dist/adapters/state/native-files.d.ts +2 -0
- package/dist/adapters/state/native-files.js +47 -0
- package/dist/adapters/state/native-files.js.map +1 -0
- package/dist/adapters/state/native-system.d.ts +38 -0
- package/dist/adapters/state/native-system.js +86 -0
- package/dist/adapters/state/native-system.js.map +1 -0
- package/dist/adapters/state/opentofu.d.ts +35 -0
- package/dist/adapters/state/opentofu.js +350 -0
- package/dist/adapters/state/opentofu.js.map +1 -0
- package/dist/adapters/state/owned-process.d.ts +43 -0
- package/dist/adapters/state/owned-process.js +252 -0
- package/dist/adapters/state/owned-process.js.map +1 -0
- package/dist/adapters/state/posix-lock-program.d.ts +1 -0
- package/dist/adapters/state/posix-lock-program.js +185 -0
- package/dist/adapters/state/posix-lock-program.js.map +1 -0
- package/dist/adapters/state/posix-native-lock.d.ts +15 -0
- package/dist/adapters/state/posix-native-lock.js +145 -0
- package/dist/adapters/state/posix-native-lock.js.map +1 -0
- package/dist/adapters/state/protected-workspace.d.ts +57 -0
- package/dist/adapters/state/protected-workspace.js +412 -0
- package/dist/adapters/state/protected-workspace.js.map +1 -0
- package/dist/application/context.d.ts +3 -0
- package/dist/application/diagnose/doctor.d.ts +5 -0
- package/dist/application/diagnose/doctor.js +21 -5
- package/dist/application/diagnose/doctor.js.map +1 -1
- package/dist/application/diagnose/generated-project.js +2 -7
- package/dist/application/diagnose/generated-project.js.map +1 -1
- package/dist/application/initialize/fixture.js +8 -1
- package/dist/application/initialize/fixture.js.map +1 -1
- package/dist/application/initialize/use-case.js +70 -36
- package/dist/application/initialize/use-case.js.map +1 -1
- package/dist/application/project/manifest.js +5 -4
- package/dist/application/project/manifest.js.map +1 -1
- package/dist/application/state-migration/execution.d.ts +32 -0
- package/dist/application/state-migration/execution.js +440 -0
- package/dist/application/state-migration/execution.js.map +1 -0
- package/dist/application/state-migration/index.d.ts +22 -0
- package/dist/application/state-migration/index.js +17 -0
- package/dist/application/state-migration/index.js.map +1 -0
- package/dist/application/state-migration/lifecycle.d.ts +3 -0
- package/dist/application/state-migration/lifecycle.js +149 -0
- package/dist/application/state-migration/lifecycle.js.map +1 -0
- package/dist/application/state-migration/planning.d.ts +7 -0
- package/dist/application/state-migration/planning.js +150 -0
- package/dist/application/state-migration/planning.js.map +1 -0
- package/dist/application/state-migration/recovery.d.ts +5 -0
- package/dist/application/state-migration/recovery.js +145 -0
- package/dist/application/state-migration/recovery.js.map +1 -0
- package/dist/application/state-migration/runtime.d.ts +32 -0
- package/dist/application/state-migration/runtime.js +188 -0
- package/dist/application/state-migration/runtime.js.map +1 -0
- package/dist/application/state-migration/service.d.ts +2 -0
- package/dist/application/state-migration/service.js +20 -0
- package/dist/application/state-migration/service.js.map +1 -0
- package/dist/application/update/inspection.d.ts +16 -2
- package/dist/application/update/inspection.js +76 -23
- package/dist/application/update/inspection.js.map +1 -1
- package/dist/application/update/migration-runtime.js +24 -11
- package/dist/application/update/migration-runtime.js.map +1 -1
- package/dist/application/update/output.d.ts +2 -0
- package/dist/application/update/output.js +11 -1
- package/dist/application/update/output.js.map +1 -1
- package/dist/application/update/revalidation-plan.d.ts +1 -0
- package/dist/application/update/revalidation-plan.js +25 -12
- package/dist/application/update/revalidation-plan.js.map +1 -1
- package/dist/application/update/revalidation.d.ts +4 -1
- package/dist/application/update/revalidation.js +62 -21
- package/dist/application/update/revalidation.js.map +1 -1
- package/dist/application/update/use-case.js +25 -17
- package/dist/application/update/use-case.js.map +1 -1
- package/dist/cli/args/definitions.js +11 -3
- package/dist/cli/args/definitions.js.map +1 -1
- package/dist/cli/args/parser.js +29 -3
- package/dist/cli/args/parser.js.map +1 -1
- package/dist/domain/governance/activation/approvals.d.ts +264 -7
- package/dist/domain/governance/activation/approvals.js +166 -23
- package/dist/domain/governance/activation/approvals.js.map +1 -1
- package/dist/domain/governance/activation/capabilities.js +5 -2
- package/dist/domain/governance/activation/capabilities.js.map +1 -1
- package/dist/domain/governance/activation/evidence.d.ts +2 -1
- package/dist/domain/governance/activation/evidence.js +64 -11
- package/dist/domain/governance/activation/evidence.js.map +1 -1
- package/dist/domain/governance/activation/graph.d.ts +11 -384
- package/dist/domain/governance/activation/graph.js +424 -379
- package/dist/domain/governance/activation/graph.js.map +1 -1
- package/dist/domain/governance/activation/inputs.d.ts +3 -1
- package/dist/domain/governance/activation/inputs.js +47 -6
- package/dist/domain/governance/activation/inputs.js.map +1 -1
- package/dist/domain/governance/activation/operations.d.ts +4 -1
- package/dist/domain/governance/activation/operations.js +110 -22
- package/dist/domain/governance/activation/operations.js.map +1 -1
- package/dist/domain/governance/activation/readiness.d.ts +10 -0
- package/dist/domain/governance/activation/readiness.js +77 -38
- package/dist/domain/governance/activation/readiness.js.map +1 -1
- package/dist/domain/governance/activation/types.d.ts +151 -9
- package/dist/domain/governance/activation/types.js +23 -1
- package/dist/domain/governance/activation/types.js.map +1 -1
- package/dist/domain/governance/activation/validators.d.ts +4 -1
- package/dist/domain/governance/activation/validators.js +419 -26
- package/dist/domain/governance/activation/validators.js.map +1 -1
- package/dist/domain/governance/policy/identity.d.ts +55 -13
- package/dist/domain/governance/policy/identity.js +28 -8
- package/dist/domain/governance/policy/identity.js.map +1 -1
- package/dist/domain/project/artifact-lifecycle.d.ts +2 -1
- package/dist/domain/project/artifact-lifecycle.js +7 -1
- package/dist/domain/project/artifact-lifecycle.js.map +1 -1
- package/dist/domain/project/catalog.d.ts +50 -1
- package/dist/domain/project/catalog.js +104 -4
- package/dist/domain/project/catalog.js.map +1 -1
- package/dist/domain/project/contracts.d.ts +9 -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/manifest/governance.d.ts +1 -1
- package/dist/domain/project/manifest/governance.js +9 -10
- package/dist/domain/project/manifest/governance.js.map +1 -1
- package/dist/domain/project/planning.js +4 -5
- package/dist/domain/project/planning.js.map +1 -1
- package/dist/domain/repair/stateful-bounded.d.ts +1 -0
- package/dist/domain/repair/stateful-bounded.js +37 -0
- package/dist/domain/repair/stateful-bounded.js.map +1 -0
- package/dist/domain/repair/stateful-invariants.d.ts +28 -0
- package/dist/domain/repair/stateful-invariants.js +278 -0
- package/dist/domain/repair/stateful-invariants.js.map +1 -0
- package/dist/domain/repair/stateful.d.ts +690 -0
- package/dist/domain/repair/stateful.js +26 -0
- package/dist/domain/repair/stateful.js.map +1 -0
- package/dist/domain/workstation/constraints.d.ts +1 -0
- package/dist/domain/workstation/constraints.js.map +1 -1
- package/dist/domain/workstation/contracts.d.ts +42 -0
- package/dist/domain/workstation/contracts.js +2 -0
- package/dist/domain/workstation/contracts.js.map +1 -0
- package/dist/domain/workstation/executables.d.ts +19 -0
- package/dist/domain/workstation/executables.js +68 -0
- package/dist/domain/workstation/executables.js.map +1 -0
- package/dist/domain/workstation/versions.d.ts +8 -0
- package/dist/domain/workstation/versions.js +145 -0
- package/dist/domain/workstation/versions.js.map +1 -0
- package/dist/framework-adapters.d.ts +2 -0
- package/dist/framework-adapters.js +148 -22
- package/dist/framework-adapters.js.map +1 -1
- package/dist/framework-validation.d.ts +6 -0
- package/dist/framework-validation.js +89 -24
- package/dist/framework-validation.js.map +1 -1
- package/dist/generators/common/base.js +57 -17
- package/dist/generators/common/base.js.map +1 -1
- package/dist/governance-activation/activation-state.js +39 -7
- package/dist/governance-activation/activation-state.js.map +1 -1
- package/dist/governance-activation/authority-records.d.ts +4 -0
- package/dist/governance-activation/authority-records.js +24 -0
- package/dist/governance-activation/authority-records.js.map +1 -0
- package/dist/governance-activation/commands.d.ts +9 -1
- package/dist/governance-activation/commands.js +392 -97
- package/dist/governance-activation/commands.js.map +1 -1
- package/dist/governance-activation/compatibility.d.ts +11 -8
- package/dist/governance-activation/compatibility.js +37 -23
- package/dist/governance-activation/compatibility.js.map +1 -1
- package/dist/governance-activation/doctor.js +40 -16
- package/dist/governance-activation/doctor.js.map +1 -1
- package/dist/governance-activation/github-config.d.ts +17 -0
- package/dist/governance-activation/github-config.js +88 -0
- package/dist/governance-activation/github-config.js.map +1 -0
- package/dist/governance-activation/github-discovery.d.ts +18 -0
- package/dist/governance-activation/github-discovery.js +229 -0
- package/dist/governance-activation/github-discovery.js.map +1 -0
- package/dist/governance-activation/github-ports.d.ts +12 -0
- package/dist/governance-activation/github-ports.js +4 -0
- package/dist/governance-activation/github-ports.js.map +1 -0
- package/dist/governance-activation/github-publication.d.ts +3 -0
- package/dist/governance-activation/github-publication.js +190 -0
- package/dist/governance-activation/github-publication.js.map +1 -0
- package/dist/governance-activation/historical-common.d.ts +98 -0
- package/dist/governance-activation/historical-common.js +269 -0
- package/dist/governance-activation/historical-common.js.map +1 -0
- package/dist/governance-activation/historical-credential-policy.d.ts +3 -0
- package/dist/governance-activation/historical-credential-policy.js +91 -0
- package/dist/governance-activation/historical-credential-policy.js.map +1 -0
- package/dist/governance-activation/historical-inputs.d.ts +6 -0
- package/dist/governance-activation/historical-inputs.js +57 -0
- package/dist/governance-activation/historical-inputs.js.map +1 -0
- package/dist/governance-activation/historical-safety.d.ts +9 -0
- package/dist/governance-activation/historical-safety.js +102 -0
- package/dist/governance-activation/historical-safety.js.map +1 -0
- package/dist/governance-activation/historical-source-metadata.d.ts +31 -0
- package/dist/governance-activation/historical-source-metadata.js +55 -0
- package/dist/governance-activation/historical-source-metadata.js.map +1 -0
- package/dist/governance-activation/historical-state.d.ts +12 -50
- package/dist/governance-activation/historical-state.js +195 -308
- package/dist/governance-activation/historical-state.js.map +1 -1
- package/dist/governance-activation/historical-v1-auxiliary.d.ts +1 -0
- package/dist/governance-activation/historical-v1-auxiliary.js +43 -0
- package/dist/governance-activation/historical-v1-auxiliary.js.map +1 -0
- package/dist/governance-activation/historical-v1-phase-contracts.d.ts +31 -0
- package/dist/governance-activation/historical-v1-phase-contracts.js +46 -0
- package/dist/governance-activation/historical-v1-phase-contracts.js.map +1 -0
- package/dist/governance-activation/historical-v2.d.ts +53 -0
- package/dist/governance-activation/historical-v2.js +313 -0
- package/dist/governance-activation/historical-v2.js.map +1 -0
- package/dist/governance-activation/history-contracts.d.ts +21 -12
- package/dist/governance-activation/history-contracts.js +99 -27
- package/dist/governance-activation/history-contracts.js.map +1 -1
- package/dist/governance-activation/inputs.d.ts +8 -2
- package/dist/governance-activation/inputs.js +41 -6
- package/dist/governance-activation/inputs.js.map +1 -1
- package/dist/governance-activation/migration-history.d.ts +43 -5
- package/dist/governance-activation/migration-history.js +231 -50
- package/dist/governance-activation/migration-history.js.map +1 -1
- package/dist/governance-activation/migration.d.ts +7 -4
- package/dist/governance-activation/migration.js +53 -252
- package/dist/governance-activation/migration.js.map +1 -1
- package/dist/governance-activation/phase-azure.d.ts +3 -0
- package/dist/governance-activation/phase-azure.js +205 -0
- package/dist/governance-activation/phase-azure.js.map +1 -0
- package/dist/governance-activation/phase-bootstrap-state.js +3 -0
- package/dist/governance-activation/phase-bootstrap-state.js.map +1 -1
- package/dist/governance-activation/phase-github.d.ts +3 -0
- package/dist/governance-activation/phase-github.js +192 -0
- package/dist/governance-activation/phase-github.js.map +1 -0
- package/dist/governance-activation/phase-governance.js +8 -2
- package/dist/governance-activation/phase-governance.js.map +1 -1
- package/dist/governance-activation/public-plans.d.ts +36 -0
- package/dist/governance-activation/public-plans.js +100 -0
- package/dist/governance-activation/public-plans.js.map +1 -0
- package/dist/governance-activation/read-only.d.ts +3 -1
- package/dist/governance-activation/read-only.js +7 -3
- package/dist/governance-activation/read-only.js.map +1 -1
- package/dist/governance-activation/reconciliation.js +10 -0
- package/dist/governance-activation/reconciliation.js.map +1 -1
- package/dist/governance-activation/seed-lifecycle.js +14 -25
- package/dist/governance-activation/seed-lifecycle.js.map +1 -1
- package/dist/governance-activation/source-of-truth.d.ts +21 -5
- package/dist/governance-activation/source-of-truth.js +102 -13
- package/dist/governance-activation/source-of-truth.js.map +1 -1
- package/dist/governance-activation/task-projection.d.ts +4 -1
- package/dist/governance-activation/task-projection.js +32 -3
- package/dist/governance-activation/task-projection.js.map +1 -1
- package/dist/governance-activation/task-writes.d.ts +42 -0
- package/dist/governance-activation/task-writes.js +250 -0
- package/dist/governance-activation/task-writes.js.map +1 -0
- package/dist/governance-activation/transition-files.d.ts +12 -0
- package/dist/governance-activation/transition-files.js +109 -0
- package/dist/governance-activation/transition-files.js.map +1 -0
- package/dist/governance-activation/transition-planning.d.ts +3 -1
- package/dist/governance-activation/transition-planning.js +158 -20
- package/dist/governance-activation/transition-planning.js.map +1 -1
- package/dist/governance-activation/transition-ports.d.ts +31 -3
- package/dist/governance-activation/transition-records.d.ts +11 -1
- package/dist/governance-activation/transition-records.js +52 -6
- package/dist/governance-activation/transition-records.js.map +1 -1
- package/dist/governance-activation/transitions.d.ts +5 -0
- package/dist/governance-activation/transitions.js +271 -37
- package/dist/governance-activation/transitions.js.map +1 -1
- package/dist/governance-assessment/engine.js +22 -15
- package/dist/governance-assessment/engine.js.map +1 -1
- package/dist/governance-assessment/project.d.ts +2 -0
- package/dist/governance-assessment/project.js +2 -1
- package/dist/governance-assessment/project.js.map +1 -1
- package/dist/interactive.d.ts +0 -1
- package/dist/interactive.js +3 -22
- package/dist/interactive.js.map +1 -1
- package/dist/openspec-profile.d.ts +2 -1
- package/dist/openspec-profile.js +11 -41
- package/dist/openspec-profile.js.map +1 -1
- package/dist/repository-governance.d.ts +10 -5
- package/dist/repository-governance.js +178 -92
- package/dist/repository-governance.js.map +1 -1
- package/dist/telemetry/contract.d.ts +1 -1
- package/dist/telemetry/contract.js +3 -0
- package/dist/telemetry/contract.js.map +1 -1
- package/dist/workstation-catalog.d.ts +13 -1
- package/dist/workstation-catalog.js +122 -0
- package/dist/workstation-catalog.js.map +1 -1
- package/dist/workstation.d.ts +69 -14
- package/dist/workstation.js +600 -215
- package/dist/workstation.js.map +1 -1
- package/docs/cli-reference.md +59 -21
- package/docs/configuration-and-manifests.md +9 -8
- package/docs/prerequisites.md +93 -18
- package/docs/repository-governance.md +68 -40
- package/docs/spec-workflows-and-agents.md +132 -13
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-ports.js","sourceRoot":"","sources":["../../src/governance-activation/github-ports.ts"],"names":[],"mappings":"AAaA,MAAM,UAAU,WAAW,CAAC,KAAsD;IAChF,OAAQ,KAEN,CAAC,QAAQ,EAAE,gBAAgB,IAAI,EAAE,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { PhaseAdapterExecutionInput, PhaseAdapterOutcome, PhasePlanBuild, PhasePlanningInput } from './transition-ports.js';
|
|
2
|
+
export declare function planGitHubPublication(input: PhasePlanningInput): Promise<PhasePlanBuild>;
|
|
3
|
+
export declare function executeGitHubPublication(input: PhaseAdapterExecutionInput): Promise<PhaseAdapterOutcome>;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { inspectGitRepository, reviewedPushUrl } from './phase-publication.js';
|
|
2
|
+
import { commandSucceeded, runGit } from './transition-process.js';
|
|
3
|
+
import { cloneState, readbackProof } from './transition-records.js';
|
|
4
|
+
import { GitHubActivationError, githubRepository, object, positiveId } from '../adapters/github/activation-rest.js';
|
|
5
|
+
import { assertGitHubAuthorized, clientFor, githubOperation, repositoryConfiguration, sourceSha } from './github-config.js';
|
|
6
|
+
export async function planGitHubPublication(input) {
|
|
7
|
+
const config = repositoryConfiguration(input.inspection);
|
|
8
|
+
const client = clientFor(input);
|
|
9
|
+
const git = await inspectGitRepository(input.inspection.projectRoot, input.runner);
|
|
10
|
+
if (git.issues.length || !git.insideWorkTree || !git.head || git.branch !== config.defaultBranch || git.status.length) {
|
|
11
|
+
throw new GitHubActivationError('publication-prerequisite', 'Publication requires a clean reviewed local commit on develop at this exact project root; no reset, rebase, or arbitrary staging is permitted.');
|
|
12
|
+
}
|
|
13
|
+
const pushUrl = `https://github.com/${config.name}.git`;
|
|
14
|
+
if (git.remotes.length) {
|
|
15
|
+
const reviewed = reviewedPushUrl(git);
|
|
16
|
+
const accepted = [pushUrl, `git@github.com:${config.name}.git`, `ssh://git@github.com/${config.name}.git`];
|
|
17
|
+
if (!accepted.includes(reviewed))
|
|
18
|
+
throw new GitHubActivationError('remote-drift', 'The existing origin differs from the explicitly approved github.com destination. It will not be replaced.');
|
|
19
|
+
}
|
|
20
|
+
const repository = await client.optional(`/repos/${config.name}`);
|
|
21
|
+
if (!repository && !config.create) {
|
|
22
|
+
throw new GitHubActivationError('repository-prerequisite', 'The approved repository is absent or unreadable. Grant access, or explicitly approve repository.create for this exact destination.');
|
|
23
|
+
}
|
|
24
|
+
const [owner, name] = config.name.split('/');
|
|
25
|
+
let ownerKind = 'organization';
|
|
26
|
+
if (!repository) {
|
|
27
|
+
const ownerInfo = await client.get(`/users/${owner}`);
|
|
28
|
+
if (ownerInfo.type === 'User') {
|
|
29
|
+
const actor = await client.get('/user');
|
|
30
|
+
if (actor.login !== owner)
|
|
31
|
+
throw new GitHubActivationError('owner-prerequisite', 'A personal repository can only be created for the authenticated approved owner.');
|
|
32
|
+
ownerKind = 'user';
|
|
33
|
+
}
|
|
34
|
+
else if (ownerInfo.type === 'Organization') {
|
|
35
|
+
const membership = await client.get(`/user/memberships/orgs/${owner}`);
|
|
36
|
+
if (membership.state !== 'active')
|
|
37
|
+
throw new GitHubActivationError('owner-prerequisite', 'An active approved organization identity with repository-create permission is required.');
|
|
38
|
+
}
|
|
39
|
+
else
|
|
40
|
+
throw new GitHubActivationError('owner-prerequisite', 'The approved repository owner is not a supported user or organization.');
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
assertRepositoryBinding(repository, config.name, config.visibility);
|
|
44
|
+
if (repository.default_branch !== config.defaultBranch) {
|
|
45
|
+
throw new GitHubActivationError('default-branch-prerequisite', 'An existing repository default branch must be reconciled to develop through a separately reviewed operation; publication will not silently change it.');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const remote = repository ? await client.optional(`/repos/${config.name}/git/ref/heads/${config.defaultBranch}`) : null;
|
|
49
|
+
const remoteHead = remote ? sourceSha(object(remote.object).sha) : null;
|
|
50
|
+
if (remoteHead && remoteHead !== git.head) {
|
|
51
|
+
const ancestor = await runGit(input.runner, input.inspection.projectRoot, ['merge-base', '--is-ancestor', remoteHead, git.head]);
|
|
52
|
+
if (!commandSucceeded(ancestor)) {
|
|
53
|
+
throw new GitHubActivationError('non-fast-forward', 'The remote branch is not a verified ancestor of the reviewed local commit. Fetch/reconcile under owner control; force-push is forbidden.');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const operations = [
|
|
57
|
+
githubOperation(input, 'github.repository.ensure', repository ? 'github-read' : 'github-repository-create', {
|
|
58
|
+
repository: config.name, name, owner, ownerKind, visibility: config.visibility, create: !repository,
|
|
59
|
+
repositoryId: repository ? positiveId(repository.id) : null, defaultBranch: config.defaultBranch
|
|
60
|
+
}),
|
|
61
|
+
...(!git.remotes.length ? [{
|
|
62
|
+
adapter: 'git', actionId: 'git.remote.bind', mutationClass: 'git-remote-bind', phaseId: input.phase.id,
|
|
63
|
+
inputs: { name: 'origin', pushUrl }, destination: { type: 'local', identity: '.git/config' },
|
|
64
|
+
remote: false, destructive: false
|
|
65
|
+
}] : []),
|
|
66
|
+
{
|
|
67
|
+
adapter: 'git', actionId: remoteHead === git.head ? 'git.verify-existing-push' : 'git.push-approved-ref',
|
|
68
|
+
mutationClass: remoteHead === git.head ? 'github-read' : 'git-push', phaseId: input.phase.id,
|
|
69
|
+
inputs: {
|
|
70
|
+
repository: config.name, branch: config.defaultBranch, localHead: git.head, remoteHead,
|
|
71
|
+
pushUrl: git.remotes.length ? reviewedPushUrl(git) : pushUrl
|
|
72
|
+
},
|
|
73
|
+
destination: { type: 'repository', identity: pushUrl, repository: config.name, ref: `refs/heads/${config.defaultBranch}` },
|
|
74
|
+
remote: true, destructive: false
|
|
75
|
+
}
|
|
76
|
+
];
|
|
77
|
+
if (!repository)
|
|
78
|
+
operations.push(githubOperation(input, 'github.repository.default-branch', 'github-write', {
|
|
79
|
+
repository: config.name, defaultBranch: config.defaultBranch
|
|
80
|
+
}));
|
|
81
|
+
return { operations };
|
|
82
|
+
}
|
|
83
|
+
function assertRepositoryBinding(repository, expected, visibility) {
|
|
84
|
+
if (githubRepository(repository.full_name).toLowerCase() !== expected.toLowerCase() ||
|
|
85
|
+
repository.private !== (visibility === 'private') || repository.archived !== false ||
|
|
86
|
+
repository.disabled === true || repository.fork === true) {
|
|
87
|
+
throw new GitHubActivationError('repository-binding', 'Repository identity, visibility, or ownership differs from the reviewed non-archived, non-fork destination.');
|
|
88
|
+
}
|
|
89
|
+
positiveId(repository.id);
|
|
90
|
+
}
|
|
91
|
+
export async function executeGitHubPublication(input) {
|
|
92
|
+
const config = repositoryConfiguration(input.inspection);
|
|
93
|
+
const client = clientFor(input);
|
|
94
|
+
const completed = [];
|
|
95
|
+
try {
|
|
96
|
+
const ensure = input.plan.operations.find((entry) => entry.actionId === 'github.repository.ensure');
|
|
97
|
+
if (!ensure)
|
|
98
|
+
throw new GitHubActivationError('publication-inventory', 'The reviewed repository binding operation is missing.');
|
|
99
|
+
await assertGitHubAuthorized(input, ensure);
|
|
100
|
+
let repository = await client.optional(`/repos/${config.name}`);
|
|
101
|
+
if (!repository) {
|
|
102
|
+
if (ensure.inputs.create !== true)
|
|
103
|
+
throw new GitHubActivationError('repository-missing', 'The reviewed existing repository is no longer visible; refusing to create a replacement.');
|
|
104
|
+
repository = await client.write('POST', ensure.inputs.ownerKind === 'user' ? '/user/repos' : `/orgs/${config.name.split('/')[0]}/repos`, {
|
|
105
|
+
name: config.name.split('/')[1], private: config.visibility === 'private', auto_init: false, has_issues: true, has_projects: false
|
|
106
|
+
});
|
|
107
|
+
completed.push(ensure);
|
|
108
|
+
}
|
|
109
|
+
if (!repository)
|
|
110
|
+
throw new GitHubActivationError('repository-readback', 'Repository creation returned no provider identity.');
|
|
111
|
+
assertRepositoryBinding(repository, config.name, config.visibility);
|
|
112
|
+
if (ensure.inputs.repositoryId !== null && repository.id !== ensure.inputs.repositoryId) {
|
|
113
|
+
throw new GitHubActivationError('repository-drift', 'The repository ID changed after review.');
|
|
114
|
+
}
|
|
115
|
+
if (!completed.includes(ensure))
|
|
116
|
+
completed.push(ensure);
|
|
117
|
+
for (const op of input.plan.operations.filter((entry) => entry.adapter === 'git')) {
|
|
118
|
+
await assertGitHubAuthorized(input, op);
|
|
119
|
+
const git = await inspectGitRepository(input.inspection.projectRoot, input.runner);
|
|
120
|
+
if (git.issues.length || git.status.length || git.branch !== config.defaultBranch) {
|
|
121
|
+
throw new GitHubActivationError('publication-drift', 'Local Git inputs changed after publication review.');
|
|
122
|
+
}
|
|
123
|
+
if (op.actionId === 'git.remote.bind') {
|
|
124
|
+
if (!git.remotes.length) {
|
|
125
|
+
const result = await runGit(input.runner, input.inspection.projectRoot, ['remote', 'add', 'origin', String(op.inputs.pushUrl)]);
|
|
126
|
+
if (!commandSucceeded(result))
|
|
127
|
+
throw new GitHubActivationError('remote-bind', 'Git could not bind the approved origin; no existing remote was replaced.');
|
|
128
|
+
}
|
|
129
|
+
else if (reviewedPushUrl(git) !== op.inputs.pushUrl)
|
|
130
|
+
throw new GitHubActivationError('remote-drift', 'Origin changed before approved binding.');
|
|
131
|
+
completed.push(op);
|
|
132
|
+
}
|
|
133
|
+
else if (op.actionId === 'git.push-approved-ref' || op.actionId === 'git.verify-existing-push') {
|
|
134
|
+
if (git.head !== op.inputs.localHead || reviewedPushUrl(git) !== op.inputs.pushUrl) {
|
|
135
|
+
throw new GitHubActivationError('publication-drift', 'Git HEAD or push URL changed after review.');
|
|
136
|
+
}
|
|
137
|
+
const remote = await client.optional(`/repos/${config.name}/git/ref/heads/${config.defaultBranch}`);
|
|
138
|
+
const sha = remote ? sourceSha(object(remote.object).sha) : null;
|
|
139
|
+
if (sha !== op.inputs.localHead) {
|
|
140
|
+
if (op.actionId !== 'git.push-approved-ref' || sha !== op.inputs.remoteHead) {
|
|
141
|
+
throw new GitHubActivationError('remote-drift', 'Remote branch changed concurrently; no force/update was attempted.');
|
|
142
|
+
}
|
|
143
|
+
const result = await runGit(input.runner, input.inspection.projectRoot, [
|
|
144
|
+
'push', String(op.inputs.pushUrl), `${sourceSha(op.inputs.localHead)}:refs/heads/${config.defaultBranch}`
|
|
145
|
+
]);
|
|
146
|
+
if (!commandSucceeded(result))
|
|
147
|
+
throw new GitHubActivationError('publication-rejected', 'GitHub rejected publication; inspect protected-branch policy and the exact ref. No bypass was attempted.');
|
|
148
|
+
}
|
|
149
|
+
completed.push(op);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const defaultOp = input.plan.operations.find((entry) => entry.actionId === 'github.repository.default-branch');
|
|
153
|
+
if (defaultOp) {
|
|
154
|
+
const live = await client.get(`/repos/${config.name}`);
|
|
155
|
+
if (live.default_branch !== config.defaultBranch) {
|
|
156
|
+
await assertGitHubAuthorized(input, defaultOp);
|
|
157
|
+
await client.write('PATCH', `/repos/${config.name}`, { default_branch: config.defaultBranch });
|
|
158
|
+
}
|
|
159
|
+
completed.push(defaultOp);
|
|
160
|
+
}
|
|
161
|
+
const current = await client.get(`/repos/${config.name}`);
|
|
162
|
+
assertRepositoryBinding(current, config.name, config.visibility);
|
|
163
|
+
const ref = await client.get(`/repos/${config.name}/git/ref/heads/${config.defaultBranch}`);
|
|
164
|
+
const head = sourceSha(object(ref.object).sha);
|
|
165
|
+
const git = await inspectGitRepository(input.inspection.projectRoot, input.runner);
|
|
166
|
+
if (head !== git.head || current.id !== repository.id || current.default_branch !== config.defaultBranch) {
|
|
167
|
+
throw new GitHubActivationError('publication-readback', 'Independent repository/ref readback differs from the reviewed local publication.');
|
|
168
|
+
}
|
|
169
|
+
const state = cloneState(input.inspection.state);
|
|
170
|
+
state.remoteBinding = {
|
|
171
|
+
id: String(current.id), name: config.name, defaultBranch: config.defaultBranch,
|
|
172
|
+
pushUrl: reviewedPushUrl(git), verifiedAt: input.now.toISOString()
|
|
173
|
+
};
|
|
174
|
+
const resourceId = `/repos/${config.name}`;
|
|
175
|
+
return {
|
|
176
|
+
status: 'completed', resultState: 'verified', stateOverride: state, completedOperations: completed,
|
|
177
|
+
evidencePayload: { kind: 'pushed.v1', head, pushUrl: reviewedPushUrl(git), repositoryId: current.id },
|
|
178
|
+
outputs: { values: { sourceSha: head, repositoryId: positiveId(current.id), repository: config.name },
|
|
179
|
+
resources: [{ provider: 'github', resourceType: 'repository', resourceId }] },
|
|
180
|
+
liveReadback: [readbackProof(input, 'github', 'repository', resourceId, {
|
|
181
|
+
id: current.id, name: config.name, head, defaultBranch: config.defaultBranch, visibility: config.visibility
|
|
182
|
+
})]
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
return { status: 'blocked', completedOperations: completed,
|
|
187
|
+
blocker: error instanceof GitHubActivationError ? error.message : 'Publication could not be verified; raw Git/provider diagnostics were withheld.' };
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=github-publication.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-publication.js","sourceRoot":"","sources":["../../src/governance-activation/github-publication.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { ApprovalEnvelope, ApprovalEvaluation, BootstrapStateRetention, EvidenceHeader, EvidenceReference, LiveReadbackProof, PhaseExecutionState, SavedTransitionPlan, TransitionOperation, TransitionOperationDestination, TransitionRollbackPlan } from '../domain/governance/activation/types.js';
|
|
2
|
+
import type { HistoricalActivationIdentity } from '../domain/governance/policy/identity.js';
|
|
3
|
+
import { historicalIdentity } from './history-contracts.js';
|
|
4
|
+
import { historicalPhaseIds, type HistoricalPhaseId } from './historical-v1-phase-contracts.js';
|
|
5
|
+
export { historicalPhaseIds, type HistoricalPhaseId };
|
|
6
|
+
export declare const historicalPhaseStates: readonly ['pending', 'blocked', 'ready', 'approved', 'running', 'verified', 'failed', 'inapplicable', 'retained', 'disposed'];
|
|
7
|
+
export declare const historicalResults: readonly ['verified', 'failed', 'inapplicable', 'retained', 'disposed'];
|
|
8
|
+
export declare const historicalMutationClasses: readonly ['none', 'read-worktree', 'write-activation-state', 'write-evidence', 'write-openspec-seed', 'write-openspec-governance', 'write-local-state', 'delete-local-state', 'write-workflows', 'write-ruleset-source', 'git-commit', 'git-push', 'github-read', 'github-write', 'github-secret-write', 'azure-read', 'azure-provider-register', 'azure-network-provision', 'azure-state-import', 'azure-resource-provision', 'github-ruleset-write'];
|
|
9
|
+
export declare const historicalGateKinds: readonly ['none', 'repository-publish', 'activation-plan', 'credential-enrollment', 'infrastructure-cost', 'enforcement', 'destructive-disposal', 'external-blocker'];
|
|
10
|
+
export declare const historicalQuestionKinds: readonly ['repository-creation-initial-commit-push', 'credential-enrollment', 'billed-infrastructure-policy-exception-cost-ceiling', 'final-enforcement', 'destructive-operation', 'external-blocker'];
|
|
11
|
+
export declare const destinationTypes: readonly ['local', 'repository', 'subscription', 'environment', 'tenant', 'external'];
|
|
12
|
+
export declare const adapterIds: readonly ['local-evidence', 'selected-spec-workflow', 'git', 'github', 'azure-opentofu', 'local-state'];
|
|
13
|
+
export declare const historicalPhaseGates: {
|
|
14
|
+
readonly 'seed-valid': 'none';
|
|
15
|
+
readonly 'seed-verified': 'none';
|
|
16
|
+
readonly 'seed-archived': 'none';
|
|
17
|
+
readonly committed: 'repository-publish';
|
|
18
|
+
readonly pushed: 'repository-publish';
|
|
19
|
+
readonly 'phase-0-complete': 'none';
|
|
20
|
+
readonly 'activation-approved': 'activation-plan';
|
|
21
|
+
readonly 'credential-ready': 'credential-enrollment';
|
|
22
|
+
readonly 'provider-ready': 'infrastructure-cost';
|
|
23
|
+
readonly 'state-path-selected': 'infrastructure-cost';
|
|
24
|
+
readonly 'existing-private-path': 'none';
|
|
25
|
+
readonly 'bootstrap-local': 'infrastructure-cost';
|
|
26
|
+
readonly 'runner-ready': 'infrastructure-cost';
|
|
27
|
+
readonly 'private-backend-proof': 'none';
|
|
28
|
+
readonly 'remote-import-verified': 'infrastructure-cost';
|
|
29
|
+
readonly 'remote-ready': 'none';
|
|
30
|
+
readonly 'application-foundation': 'infrastructure-cost';
|
|
31
|
+
readonly 'workflow-source-ready': 'none';
|
|
32
|
+
readonly 'dev-proof': 'none';
|
|
33
|
+
readonly 'staging-qualified': 'none';
|
|
34
|
+
readonly 'production-rehearsed': 'none';
|
|
35
|
+
readonly 'green-red-proof': 'none';
|
|
36
|
+
readonly 'enforcement-approved': 'enforcement';
|
|
37
|
+
readonly 'rulesets-applied': 'enforcement';
|
|
38
|
+
readonly 'live-readback': 'none';
|
|
39
|
+
readonly 'bootstrap-state-disposed': 'destructive-disposal';
|
|
40
|
+
};
|
|
41
|
+
export interface HistoricalActivationState {
|
|
42
|
+
schemaVersion: 1;
|
|
43
|
+
identity: HistoricalActivationIdentity;
|
|
44
|
+
repository: {
|
|
45
|
+
id: string;
|
|
46
|
+
name: string;
|
|
47
|
+
defaultBranch: string;
|
|
48
|
+
};
|
|
49
|
+
activeChange: {
|
|
50
|
+
id: string;
|
|
51
|
+
kind: 'openspec' | 'spec-kit';
|
|
52
|
+
} | null;
|
|
53
|
+
applicability: {
|
|
54
|
+
statePath: 'existing-private' | 'bootstrap-local' | 'none';
|
|
55
|
+
privateStagingDast: boolean;
|
|
56
|
+
credentialRequired: boolean;
|
|
57
|
+
};
|
|
58
|
+
bootstrapState?: BootstrapStateRetention;
|
|
59
|
+
phases: Record<HistoricalPhaseId, PhaseExecutionState>;
|
|
60
|
+
createdAt: string;
|
|
61
|
+
updatedAt: string;
|
|
62
|
+
}
|
|
63
|
+
export type HistoricalEvidenceHeader = Pick<EvidenceHeader, 'repositoryId' | 'phaseGraphHash' | 'phaseId' | 'phaseContractDigest' | 'inputDigest' | 'baselineSha' | 'transition' | 'producedAt' | 'producer' | 'result'> & {
|
|
64
|
+
schemaVersion: 1;
|
|
65
|
+
identity: HistoricalActivationIdentity;
|
|
66
|
+
};
|
|
67
|
+
export type HistoricalLiveReadbackProof = Omit<LiveReadbackProof, 'schemaVersion' | 'identity'> & {
|
|
68
|
+
schemaVersion: 1;
|
|
69
|
+
identity: HistoricalActivationIdentity;
|
|
70
|
+
};
|
|
71
|
+
export interface HistoricalEvidenceRecord {
|
|
72
|
+
evidenceId: string;
|
|
73
|
+
header: HistoricalEvidenceHeader;
|
|
74
|
+
payload?: unknown;
|
|
75
|
+
liveReadback?: HistoricalLiveReadbackProof[];
|
|
76
|
+
}
|
|
77
|
+
export type HistoricalApprovalEnvelope = Pick<ApprovalEnvelope, 'id' | 'phaseId' | 'gateKind' | 'baselineSha' | 'planDigest' | 'resources' | 'destinations' | 'permissions' | 'costCeiling' | 'policyExceptions' | 'destructiveScope' | 'expiresAt' | 'approvedAt' | 'approver'> & {
|
|
78
|
+
schemaVersion: 1;
|
|
79
|
+
identity: HistoricalActivationIdentity;
|
|
80
|
+
};
|
|
81
|
+
export type HistoricalSavedTransitionPlan = Pick<SavedTransitionPlan, 'phaseId' | 'createdAt' | 'expiresAt' | 'graphHash' | 'stateHash' | 'baselineDigest' | 'inputDigest' | 'transitionDigest' | 'planDigest' | 'mutationClasses' | 'operations' | 'approval' | 'rollbackPlan' | 'noSecrets'> & {
|
|
82
|
+
schemaVersion: 1;
|
|
83
|
+
identity: HistoricalActivationIdentity;
|
|
84
|
+
};
|
|
85
|
+
export declare function phaseId(value: unknown, label: string): HistoricalPhaseId;
|
|
86
|
+
export declare function assertHistoricalPhasesComplete<T>(phases: Partial<Record<HistoricalPhaseId, T>>): asserts phases is Record<HistoricalPhaseId, T>;
|
|
87
|
+
export declare function readHistoricalEvidenceReference(value: unknown, label: string): EvidenceReference;
|
|
88
|
+
export declare function validateHistoricalBootstrapState(value: unknown, label: string): BootstrapStateRetention;
|
|
89
|
+
export declare function readHistoricalEvidenceTransition(value: unknown, label: string): EvidenceHeader['transition'];
|
|
90
|
+
export declare function validateHistoricalEmbeddedPaths(value: unknown, label: string): void;
|
|
91
|
+
export declare function uniqueSorted<T>(values: T[], key: (value: T) => string, label: string): T[];
|
|
92
|
+
export declare function nullableString(value: unknown, label: string): string | null;
|
|
93
|
+
export declare function readHistoricalApprovalFields(value: unknown): Omit<HistoricalApprovalEnvelope, 'schemaVersion' | 'identity'>;
|
|
94
|
+
export declare function operationDestination(value: unknown, label: string): TransitionOperationDestination;
|
|
95
|
+
export declare function operation(value: unknown, label: string, mutationClasses?: readonly TransitionOperation['mutationClass'][]): TransitionOperation;
|
|
96
|
+
export declare function evaluation(value: unknown, label: string): ApprovalEvaluation;
|
|
97
|
+
export declare function rollbackPlan(value: unknown, label: string, mutationClasses?: readonly TransitionOperation['mutationClass'][]): TransitionRollbackPlan;
|
|
98
|
+
export declare function readHistoricalSavedTransitionPlan(value: unknown, identityReader: typeof historicalIdentity): HistoricalSavedTransitionPlan;
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { isRecord } from '../domain/governance/activation/canonical-json.js';
|
|
2
|
+
import { historyArray, historyBoolean, historyDigest, historyEnum, historyExact, historyFail, historyLiteral, historyPathParts, historyRecord, historyRecordId, historyString, historyStrings, historyTimestamp } from './history-contracts.js';
|
|
3
|
+
import { assertSafeHistoricalRecord } from './historical-safety.js';
|
|
4
|
+
import { historicalPhaseIds } from './historical-v1-phase-contracts.js';
|
|
5
|
+
export { historicalPhaseIds };
|
|
6
|
+
export const historicalPhaseStates = [
|
|
7
|
+
'pending', 'blocked', 'ready', 'approved', 'running', 'verified', 'failed', 'inapplicable', 'retained', 'disposed'
|
|
8
|
+
];
|
|
9
|
+
export const historicalResults = ['verified', 'failed', 'inapplicable', 'retained', 'disposed'];
|
|
10
|
+
export const historicalMutationClasses = [
|
|
11
|
+
'none', 'read-worktree', 'write-activation-state', 'write-evidence', 'write-openspec-seed',
|
|
12
|
+
'write-openspec-governance', 'write-local-state', 'delete-local-state', 'write-workflows',
|
|
13
|
+
'write-ruleset-source', 'git-commit', 'git-push', 'github-read', 'github-write',
|
|
14
|
+
'github-secret-write', 'azure-read', 'azure-provider-register', 'azure-network-provision',
|
|
15
|
+
'azure-state-import', 'azure-resource-provision', 'github-ruleset-write'
|
|
16
|
+
];
|
|
17
|
+
export const historicalGateKinds = [
|
|
18
|
+
'none', 'repository-publish', 'activation-plan', 'credential-enrollment', 'infrastructure-cost',
|
|
19
|
+
'enforcement', 'destructive-disposal', 'external-blocker'
|
|
20
|
+
];
|
|
21
|
+
export const historicalQuestionKinds = [
|
|
22
|
+
'repository-creation-initial-commit-push', 'credential-enrollment',
|
|
23
|
+
'billed-infrastructure-policy-exception-cost-ceiling', 'final-enforcement',
|
|
24
|
+
'destructive-operation', 'external-blocker'
|
|
25
|
+
];
|
|
26
|
+
export const destinationTypes = ['local', 'repository', 'subscription', 'environment', 'tenant', 'external'];
|
|
27
|
+
export const adapterIds = ['local-evidence', 'selected-spec-workflow', 'git', 'github', 'azure-opentofu', 'local-state'];
|
|
28
|
+
export const historicalPhaseGates = {
|
|
29
|
+
'seed-valid': 'none', 'seed-verified': 'none', 'seed-archived': 'none',
|
|
30
|
+
committed: 'repository-publish', pushed: 'repository-publish', 'phase-0-complete': 'none',
|
|
31
|
+
'activation-approved': 'activation-plan', 'credential-ready': 'credential-enrollment',
|
|
32
|
+
'provider-ready': 'infrastructure-cost', 'state-path-selected': 'infrastructure-cost',
|
|
33
|
+
'existing-private-path': 'none', 'bootstrap-local': 'infrastructure-cost',
|
|
34
|
+
'runner-ready': 'infrastructure-cost', 'private-backend-proof': 'none',
|
|
35
|
+
'remote-import-verified': 'infrastructure-cost', 'remote-ready': 'none',
|
|
36
|
+
'application-foundation': 'infrastructure-cost', 'workflow-source-ready': 'none',
|
|
37
|
+
'dev-proof': 'none', 'staging-qualified': 'none', 'production-rehearsed': 'none',
|
|
38
|
+
'green-red-proof': 'none', 'enforcement-approved': 'enforcement', 'rulesets-applied': 'enforcement',
|
|
39
|
+
'live-readback': 'none', 'bootstrap-state-disposed': 'destructive-disposal'
|
|
40
|
+
};
|
|
41
|
+
export function phaseId(value, label) {
|
|
42
|
+
return historyEnum(value, historicalPhaseIds, label);
|
|
43
|
+
}
|
|
44
|
+
export function assertHistoricalPhasesComplete(phases) {
|
|
45
|
+
for (const id of historicalPhaseIds) {
|
|
46
|
+
if (phases[id] === undefined)
|
|
47
|
+
historyFail(`phases.${id}`, 'is required.');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export function readHistoricalEvidenceReference(value, label) {
|
|
51
|
+
const item = historyExact(value, ['phaseId', 'evidenceId', 'headerDigest', 'result'], label);
|
|
52
|
+
return {
|
|
53
|
+
phaseId: phaseId(item.phaseId, `${label}.phaseId`),
|
|
54
|
+
evidenceId: historyRecordId(item.evidenceId, `${label}.evidenceId`),
|
|
55
|
+
headerDigest: historyDigest(item.headerDigest, `${label}.headerDigest`),
|
|
56
|
+
result: historyEnum(item.result, historicalResults, `${label}.result`)
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export function validateHistoricalBootstrapState(value, label) {
|
|
60
|
+
const item = historyExact(value, [
|
|
61
|
+
'status', 'remoteImportEvidenceId', 'remoteImportEvidenceDigest', 'retainedAt', 'disposeAfter',
|
|
62
|
+
'encryptedStatePathParts', 'encryptionKeyPathParts'
|
|
63
|
+
], label, ['disposedAt', 'deletionEvidenceId', 'incompleteCleanup']);
|
|
64
|
+
const status = historyEnum(item.status, ['retained', 'disposed'], `${label}.status`);
|
|
65
|
+
const retainedAt = historyTimestamp(item.retainedAt, `${label}.retainedAt`);
|
|
66
|
+
const disposeAfter = historyTimestamp(item.disposeAfter, `${label}.disposeAfter`);
|
|
67
|
+
if (Date.parse(disposeAfter) - Date.parse(retainedAt) !== 30 * 24 * 60 * 60 * 1000) {
|
|
68
|
+
historyFail(label, 'disposeAfter must be exactly 30 days after retainedAt.');
|
|
69
|
+
}
|
|
70
|
+
if (status === 'disposed' && !Object.hasOwn(item, 'disposedAt'))
|
|
71
|
+
historyFail(label, 'disposedAt is required for disposed state.');
|
|
72
|
+
return {
|
|
73
|
+
status,
|
|
74
|
+
remoteImportEvidenceId: historyRecordId(item.remoteImportEvidenceId, `${label}.remoteImportEvidenceId`),
|
|
75
|
+
remoteImportEvidenceDigest: historyDigest(item.remoteImportEvidenceDigest, `${label}.remoteImportEvidenceDigest`),
|
|
76
|
+
retainedAt, disposeAfter,
|
|
77
|
+
encryptedStatePathParts: historyArray(item.encryptedStatePathParts, `${label}.encryptedStatePathParts`)
|
|
78
|
+
.map((entry) => historyPathParts(entry, `${label}.encryptedStatePathParts`)),
|
|
79
|
+
encryptionKeyPathParts: historyArray(item.encryptionKeyPathParts, `${label}.encryptionKeyPathParts`)
|
|
80
|
+
.map((entry) => historyPathParts(entry, `${label}.encryptionKeyPathParts`)),
|
|
81
|
+
...(Object.hasOwn(item, 'disposedAt') ? { disposedAt: historyTimestamp(item.disposedAt, `${label}.disposedAt`) } : {}),
|
|
82
|
+
...(Object.hasOwn(item, 'deletionEvidenceId') ? { deletionEvidenceId: historyRecordId(item.deletionEvidenceId, `${label}.deletionEvidenceId`) } : {}),
|
|
83
|
+
...(Object.hasOwn(item, 'incompleteCleanup') ? { incompleteCleanup: historyStrings(item.incompleteCleanup, `${label}.incompleteCleanup`) } : {})
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export function readHistoricalEvidenceTransition(value, label) {
|
|
87
|
+
const item = historyExact(value, ['phaseId', 'baselineSha', 'inputDigest', 'transitionDigest'], label);
|
|
88
|
+
return {
|
|
89
|
+
phaseId: phaseId(item.phaseId, `${label}.phaseId`),
|
|
90
|
+
baselineSha: historyDigest(item.baselineSha, `${label}.baselineSha`),
|
|
91
|
+
inputDigest: historyDigest(item.inputDigest, `${label}.inputDigest`),
|
|
92
|
+
transitionDigest: historyDigest(item.transitionDigest, `${label}.transitionDigest`)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
export function validateHistoricalEmbeddedPaths(value, label) {
|
|
96
|
+
if (Array.isArray(value)) {
|
|
97
|
+
value.forEach((entry, index) => validateHistoricalEmbeddedPaths(entry, `${label}[${index}]`));
|
|
98
|
+
}
|
|
99
|
+
else if (isRecord(value)) {
|
|
100
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
101
|
+
if (key === 'pathParts' || key.endsWith('PathParts')) {
|
|
102
|
+
const parts = historyArray(entry, `${label}.${key}`);
|
|
103
|
+
if (parts.length === 0 && ['cwdPathParts', 'encryptedStatePathParts', 'encryptionKeyPathParts', 'deletedPathParts'].includes(key))
|
|
104
|
+
continue;
|
|
105
|
+
if (parts.length > 0 && Array.isArray(parts[0]))
|
|
106
|
+
parts.forEach((item) => historyPathParts(item, `${label}.${key}`));
|
|
107
|
+
else
|
|
108
|
+
historyPathParts(parts, `${label}.${key}`);
|
|
109
|
+
}
|
|
110
|
+
else
|
|
111
|
+
validateHistoricalEmbeddedPaths(entry, `${label}.${key}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
export function uniqueSorted(values, key, label) {
|
|
116
|
+
if (new Set(values.map(key)).size !== values.length)
|
|
117
|
+
historyFail(label, 'contains duplicate scope entries.');
|
|
118
|
+
return values.sort((a, b) => key(a).localeCompare(key(b), 'en'));
|
|
119
|
+
}
|
|
120
|
+
export function nullableString(value, label) {
|
|
121
|
+
return value === null ? null : historyString(value, label);
|
|
122
|
+
}
|
|
123
|
+
export function readHistoricalApprovalFields(value) {
|
|
124
|
+
const label = 'historicalApprovalEnvelope';
|
|
125
|
+
assertSafeHistoricalRecord(value, label);
|
|
126
|
+
const item = historyExact(value, [
|
|
127
|
+
'schemaVersion', 'id', 'phaseId', 'gateKind', 'identity', 'baselineSha', 'planDigest', 'resources',
|
|
128
|
+
'destinations', 'permissions', 'costCeiling', 'policyExceptions', 'destructiveScope', 'expiresAt', 'approvedAt', 'approver'
|
|
129
|
+
], label);
|
|
130
|
+
const id = phaseId(item.phaseId, `${label}.phaseId`);
|
|
131
|
+
const gateKind = historyEnum(item.gateKind, historicalGateKinds, `${label}.gateKind`);
|
|
132
|
+
if (gateKind !== historicalPhaseGates[id])
|
|
133
|
+
historyFail(label, 'approval gate does not match the historical phase.');
|
|
134
|
+
const cost = historyExact(item.costCeiling, ['currency', 'fixedMonthlyCents', 'usageMonthlyCents'], `${label}.costCeiling`);
|
|
135
|
+
const resources = historyArray(item.resources, `${label}.resources`).map((entry, index) => {
|
|
136
|
+
const resource = historyExact(entry, ['type', 'identity'], `${label}.resources[${index}]`);
|
|
137
|
+
return { type: historyString(resource.type, `${label}.resources[${index}].type`).toLowerCase(), identity: historyString(resource.identity, `${label}.resources[${index}].identity`) };
|
|
138
|
+
});
|
|
139
|
+
const destinations = historyArray(item.destinations, `${label}.destinations`).map((entry, index) => {
|
|
140
|
+
const destination = historyExact(entry, ['type', 'identity', 'repository', 'subscriptionId'], `${label}.destinations[${index}]`);
|
|
141
|
+
return {
|
|
142
|
+
type: historyEnum(destination.type, destinationTypes, `${label}.destinations[${index}].type`),
|
|
143
|
+
identity: historyString(destination.identity, `${label}.destinations[${index}].identity`),
|
|
144
|
+
repository: nullableString(destination.repository, `${label}.destinations[${index}].repository`),
|
|
145
|
+
subscriptionId: nullableString(destination.subscriptionId, `${label}.destinations[${index}].subscriptionId`)
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
return {
|
|
149
|
+
id: historyRecordId(item.id, `${label}.id`), phaseId: id, gateKind,
|
|
150
|
+
baselineSha: historyDigest(item.baselineSha, `${label}.baselineSha`),
|
|
151
|
+
planDigest: historyDigest(item.planDigest, `${label}.planDigest`),
|
|
152
|
+
resources: uniqueSorted(resources, (entry) => `${entry.type}:${entry.identity}`, `${label}.resources`),
|
|
153
|
+
destinations: uniqueSorted(destinations, (entry) => `${entry.type}:${entry.identity}`, `${label}.destinations`),
|
|
154
|
+
permissions: uniqueSorted(historyStrings(item.permissions, `${label}.permissions`).map((entry) => entry.toLowerCase()), (entry) => entry, `${label}.permissions`),
|
|
155
|
+
costCeiling: {
|
|
156
|
+
currency: historyString(cost.currency, `${label}.costCeiling.currency`),
|
|
157
|
+
fixedMonthlyCents: Math.max(0, Math.trunc(Number(cost.fixedMonthlyCents))),
|
|
158
|
+
usageMonthlyCents: Math.max(0, Math.trunc(Number(cost.usageMonthlyCents)))
|
|
159
|
+
},
|
|
160
|
+
policyExceptions: uniqueSorted(historyStrings(item.policyExceptions, `${label}.policyExceptions`), (entry) => entry, `${label}.policyExceptions`),
|
|
161
|
+
destructiveScope: uniqueSorted(historyStrings(item.destructiveScope, `${label}.destructiveScope`), (entry) => entry, `${label}.destructiveScope`),
|
|
162
|
+
expiresAt: historyTimestamp(item.expiresAt, `${label}.expiresAt`),
|
|
163
|
+
approvedAt: historyTimestamp(item.approvedAt, `${label}.approvedAt`),
|
|
164
|
+
approver: historyString(item.approver, `${label}.approver`)
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
export function operationDestination(value, label) {
|
|
168
|
+
const item = historyExact(value, ['type', 'identity'], label, ['pathParts', 'repository', 'subscriptionId', 'ref']);
|
|
169
|
+
return {
|
|
170
|
+
type: historyEnum(item.type, destinationTypes, `${label}.type`),
|
|
171
|
+
identity: historyString(item.identity, `${label}.identity`),
|
|
172
|
+
...(Object.hasOwn(item, 'pathParts') ? { pathParts: historyPathParts(item.pathParts, `${label}.pathParts`) } : {}),
|
|
173
|
+
...(Object.hasOwn(item, 'repository') ? { repository: historyString(item.repository, `${label}.repository`) } : {}),
|
|
174
|
+
...(Object.hasOwn(item, 'subscriptionId') ? { subscriptionId: historyString(item.subscriptionId, `${label}.subscriptionId`) } : {}),
|
|
175
|
+
...(Object.hasOwn(item, 'ref') ? { ref: historyString(item.ref, `${label}.ref`) } : {})
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
export function operation(value, label, mutationClasses = historicalMutationClasses) {
|
|
179
|
+
const item = historyExact(value, ['adapter', 'actionId', 'mutationClass', 'phaseId', 'inputs', 'destination', 'remote', 'destructive'], label);
|
|
180
|
+
const inputs = historyRecord(item.inputs, `${label}.inputs`);
|
|
181
|
+
validateHistoricalEmbeddedPaths(inputs, `${label}.inputs`);
|
|
182
|
+
return {
|
|
183
|
+
adapter: historyEnum(item.adapter, adapterIds, `${label}.adapter`),
|
|
184
|
+
actionId: historyString(item.actionId, `${label}.actionId`),
|
|
185
|
+
mutationClass: historyEnum(item.mutationClass, mutationClasses, `${label}.mutationClass`),
|
|
186
|
+
phaseId: phaseId(item.phaseId, `${label}.phaseId`), inputs,
|
|
187
|
+
destination: operationDestination(item.destination, `${label}.destination`),
|
|
188
|
+
remote: historyBoolean(item.remote, `${label}.remote`), destructive: historyBoolean(item.destructive, `${label}.destructive`)
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
export function evaluation(value, label) {
|
|
192
|
+
const item = historyExact(value, [
|
|
193
|
+
'phaseId', 'gateKind', 'questionKind', 'approvalRequired', 'status', 'envelopeId', 'envelopeHash', 'reasons', 'expansionReasons'
|
|
194
|
+
], label);
|
|
195
|
+
return {
|
|
196
|
+
phaseId: phaseId(item.phaseId, `${label}.phaseId`),
|
|
197
|
+
gateKind: historyEnum(item.gateKind, historicalGateKinds, `${label}.gateKind`),
|
|
198
|
+
questionKind: item.questionKind === null ? null : historyEnum(item.questionKind, historicalQuestionKinds, `${label}.questionKind`),
|
|
199
|
+
approvalRequired: historyBoolean(item.approvalRequired, `${label}.approvalRequired`),
|
|
200
|
+
status: historyEnum(item.status, ['not-required', 'approval-required', 'reused', 'expired', 'invalidated'], `${label}.status`),
|
|
201
|
+
envelopeId: item.envelopeId === null ? null : historyRecordId(item.envelopeId, `${label}.envelopeId`),
|
|
202
|
+
envelopeHash: item.envelopeHash === null ? null : historyDigest(item.envelopeHash, `${label}.envelopeHash`),
|
|
203
|
+
reasons: historyStrings(item.reasons, `${label}.reasons`), expansionReasons: historyStrings(item.expansionReasons, `${label}.expansionReasons`)
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
export function rollbackPlan(value, label, mutationClasses = historicalMutationClasses) {
|
|
207
|
+
const item = historyExact(value, ['phaseId', 'strategy', 'target', 'operations', 'retained', 'cleanupWarnings'], label);
|
|
208
|
+
return {
|
|
209
|
+
phaseId: phaseId(item.phaseId, `${label}.phaseId`),
|
|
210
|
+
strategy: historyEnum(item.strategy, ['none', 'retain', 'reverse-to', 'dispose'], `${label}.strategy`),
|
|
211
|
+
target: item.target === null ? null : phaseId(item.target, `${label}.target`),
|
|
212
|
+
operations: historyArray(item.operations, `${label}.operations`).map((entry, index) => operation(entry, `${label}.operations[${index}]`, mutationClasses)),
|
|
213
|
+
retained: historyStrings(item.retained, `${label}.retained`), cleanupWarnings: historyStrings(item.cleanupWarnings, `${label}.cleanupWarnings`)
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
export function readHistoricalSavedTransitionPlan(value, identityReader) {
|
|
217
|
+
const label = 'historicalTransitionPlan';
|
|
218
|
+
assertSafeHistoricalRecord(value, label);
|
|
219
|
+
const item = historyExact(value, [
|
|
220
|
+
'schemaVersion', 'phaseId', 'createdAt', 'expiresAt', 'identity', 'graphHash', 'stateHash',
|
|
221
|
+
'baselineDigest', 'inputDigest', 'transitionDigest', 'planDigest', 'mutationClasses', 'operations',
|
|
222
|
+
'approval', 'rollbackPlan', 'noSecrets'
|
|
223
|
+
], label);
|
|
224
|
+
const identity = identityReader(item.identity, `${label}.identity`);
|
|
225
|
+
const allowedMutationClasses = identity.activationContractVersion === 1
|
|
226
|
+
? historicalMutationClasses : [...historicalMutationClasses, 'write-seed-tasks'];
|
|
227
|
+
const graphHash = historyDigest(item.graphHash, `${label}.graphHash`);
|
|
228
|
+
if (graphHash !== identity.phaseGraphHash)
|
|
229
|
+
historyFail(label, 'graphHash contradicts the historical identity.');
|
|
230
|
+
const id = phaseId(item.phaseId, `${label}.phaseId`);
|
|
231
|
+
const operations = historyArray(item.operations, `${label}.operations`).map((entry, index) => operation(entry, `${label}.operations[${index}]`, allowedMutationClasses));
|
|
232
|
+
if (operations.some((entry) => entry.phaseId !== id))
|
|
233
|
+
historyFail(label, 'operation phase differs from its plan.');
|
|
234
|
+
const mutations = historyExact(item.mutationClasses, ['local', 'remote'], `${label}.mutationClasses`);
|
|
235
|
+
const approval = historyExact(item.approval, ['gateKind', 'required', 'evaluation', 'envelopeId', 'envelopeHash'], `${label}.approval`);
|
|
236
|
+
const approvalEvaluation = evaluation(approval.evaluation, `${label}.approval.evaluation`);
|
|
237
|
+
const gateKind = historyEnum(approval.gateKind, historicalGateKinds, `${label}.approval.gateKind`);
|
|
238
|
+
const required = historyBoolean(approval.required, `${label}.approval.required`);
|
|
239
|
+
const envelopeId = approval.envelopeId === null ? null : historyRecordId(approval.envelopeId, `${label}.approval.envelopeId`);
|
|
240
|
+
const envelopeHash = approval.envelopeHash === null ? null : historyDigest(approval.envelopeHash, `${label}.approval.envelopeHash`);
|
|
241
|
+
if (gateKind !== historicalPhaseGates[id] || required !== (gateKind !== 'none') ||
|
|
242
|
+
approvalEvaluation.phaseId !== id || approvalEvaluation.gateKind !== gateKind ||
|
|
243
|
+
approvalEvaluation.envelopeId !== envelopeId || approvalEvaluation.envelopeHash !== envelopeHash ||
|
|
244
|
+
(envelopeId === null) !== (envelopeHash === null)) {
|
|
245
|
+
historyFail(label, 'approval references or gate contradict the historical phase.');
|
|
246
|
+
}
|
|
247
|
+
const rollback = rollbackPlan(item.rollbackPlan, `${label}.rollbackPlan`, allowedMutationClasses);
|
|
248
|
+
if (rollback.phaseId !== id)
|
|
249
|
+
historyFail(label, 'rollback names another phase.');
|
|
250
|
+
return {
|
|
251
|
+
schemaVersion: historyLiteral(item.schemaVersion, 1, `${label}.schemaVersion`), phaseId: id,
|
|
252
|
+
createdAt: historyTimestamp(item.createdAt, `${label}.createdAt`),
|
|
253
|
+
expiresAt: historyTimestamp(item.expiresAt, `${label}.expiresAt`), identity, graphHash,
|
|
254
|
+
stateHash: item.stateHash === null ? null : historyDigest(item.stateHash, `${label}.stateHash`),
|
|
255
|
+
baselineDigest: historyDigest(item.baselineDigest, `${label}.baselineDigest`),
|
|
256
|
+
inputDigest: historyDigest(item.inputDigest, `${label}.inputDigest`),
|
|
257
|
+
transitionDigest: historyDigest(item.transitionDigest, `${label}.transitionDigest`),
|
|
258
|
+
planDigest: historyDigest(item.planDigest, `${label}.planDigest`),
|
|
259
|
+
mutationClasses: {
|
|
260
|
+
local: historyStrings(mutations.local, `${label}.mutationClasses.local`).map((entry) => historyEnum(entry, allowedMutationClasses, `${label}.mutationClasses.local`)),
|
|
261
|
+
remote: historyStrings(mutations.remote, `${label}.mutationClasses.remote`).map((entry) => historyEnum(entry, allowedMutationClasses, `${label}.mutationClasses.remote`))
|
|
262
|
+
},
|
|
263
|
+
operations,
|
|
264
|
+
approval: { gateKind, required, evaluation: approvalEvaluation, envelopeId, envelopeHash },
|
|
265
|
+
rollbackPlan: rollback,
|
|
266
|
+
noSecrets: historyLiteral(item.noSecrets, true, `${label}.noSecrets`)
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=historical-common.js.map
|