@msn-control/liftoff 0.10.4 → 0.11.1
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 +220 -77
- package/README.md +28 -28
- package/assets/supported-stack.json +3 -136
- package/dist/adapters/azure/governance-assessment.d.ts +2 -0
- package/dist/adapters/azure/governance-assessment.js +21 -0
- package/dist/adapters/azure/governance-assessment.js.map +1 -0
- package/dist/adapters/filesystem/atomic-write.d.ts +2 -0
- package/dist/adapters/filesystem/atomic-write.js +74 -0
- package/dist/adapters/filesystem/atomic-write.js.map +1 -0
- package/dist/adapters/filesystem/errors.d.ts +2 -0
- package/dist/adapters/filesystem/errors.js +8 -0
- package/dist/adapters/filesystem/errors.js.map +1 -0
- package/dist/adapters/filesystem/manifest-file.d.ts +1 -0
- package/dist/adapters/filesystem/manifest-file.js +21 -0
- package/dist/adapters/filesystem/manifest-file.js.map +1 -0
- package/dist/adapters/filesystem/project-config.d.ts +4 -0
- package/dist/adapters/filesystem/project-config.js +157 -0
- package/dist/adapters/filesystem/project-config.js.map +1 -0
- package/dist/adapters/filesystem/project-discovery.d.ts +2 -0
- package/dist/adapters/filesystem/project-discovery.js +30 -0
- package/dist/adapters/filesystem/project-discovery.js.map +1 -0
- package/dist/adapters/filesystem/project-files.d.ts +6 -0
- package/dist/adapters/filesystem/project-files.js +68 -0
- package/dist/adapters/filesystem/project-files.js.map +1 -0
- package/dist/adapters/filesystem/project-lock.d.ts +8 -0
- package/dist/adapters/filesystem/project-lock.js +164 -0
- package/dist/adapters/filesystem/project-lock.js.map +1 -0
- package/dist/adapters/filesystem/project-paths.d.ts +2 -0
- package/dist/adapters/filesystem/project-paths.js +60 -0
- package/dist/adapters/filesystem/project-paths.js.map +1 -0
- package/dist/adapters/filesystem/project-transaction.d.ts +23 -0
- package/dist/adapters/filesystem/project-transaction.js +158 -0
- package/dist/adapters/filesystem/project-transaction.js.map +1 -0
- package/dist/adapters/git/governance-assessment.d.ts +22 -0
- package/dist/adapters/git/governance-assessment.js +161 -0
- package/dist/adapters/git/governance-assessment.js.map +1 -0
- package/dist/adapters/github/governance-assessment.d.ts +2 -0
- package/dist/adapters/github/governance-assessment.js +18 -0
- package/dist/adapters/github/governance-assessment.js.map +1 -0
- package/dist/adapters/packaged-assets/package-root.d.ts +3 -0
- package/dist/adapters/packaged-assets/package-root.js +21 -0
- package/dist/adapters/packaged-assets/package-root.js.map +1 -0
- package/dist/adapters/packaged-assets/supported-stack.d.ts +4 -0
- package/dist/adapters/packaged-assets/supported-stack.js +18 -0
- package/dist/adapters/packaged-assets/supported-stack.js.map +1 -0
- package/dist/adapters/packaged-assets/template-assets.d.ts +23 -0
- package/dist/adapters/packaged-assets/template-assets.js +36 -0
- package/dist/adapters/packaged-assets/template-assets.js.map +1 -0
- package/dist/adapters/process/shell-command.d.ts +5 -0
- package/dist/adapters/process/shell-command.js +21 -0
- package/dist/adapters/process/shell-command.js.map +1 -0
- package/dist/application/context.d.ts +20 -0
- package/dist/application/context.js +2 -0
- package/dist/application/context.js.map +1 -0
- package/dist/application/diagnose/doctor.d.ts +21 -0
- package/dist/application/diagnose/doctor.js +586 -0
- package/dist/application/diagnose/doctor.js.map +1 -0
- package/dist/application/diagnose/generated-project.d.ts +1 -0
- package/dist/application/diagnose/generated-project.js +105 -0
- package/dist/application/diagnose/generated-project.js.map +1 -0
- package/dist/application/diagnose/validate.d.ts +6 -0
- package/dist/application/diagnose/validate.js +27 -0
- package/dist/application/diagnose/validate.js.map +1 -0
- package/dist/application/initialize/fixture.d.ts +2 -0
- package/dist/application/initialize/fixture.js +39 -0
- package/dist/application/initialize/fixture.js.map +1 -0
- package/dist/application/initialize/inputs.d.ts +3 -0
- package/dist/application/initialize/inputs.js +35 -0
- package/dist/application/initialize/inputs.js.map +1 -0
- package/dist/application/initialize/use-case.d.ts +23 -0
- package/dist/application/initialize/use-case.js +360 -0
- package/dist/application/initialize/use-case.js.map +1 -0
- package/dist/application/migrate/use-case.d.ts +7 -0
- package/dist/application/migrate/use-case.js +378 -0
- package/dist/application/migrate/use-case.js.map +1 -0
- package/dist/application/project/catalog.d.ts +46 -0
- package/dist/application/project/catalog.js +12 -0
- package/dist/application/project/catalog.js.map +1 -0
- package/dist/application/project/manifest.d.ts +2 -0
- package/dist/application/project/manifest.js +29 -0
- package/dist/application/project/manifest.js.map +1 -0
- package/dist/application/project/planning.d.ts +6 -0
- package/dist/application/project/planning.js +12 -0
- package/dist/application/project/planning.js.map +1 -0
- package/dist/application/update/planning.d.ts +40 -0
- package/dist/application/update/planning.js +293 -0
- package/dist/application/update/planning.js.map +1 -0
- package/dist/application/update/reporting.d.ts +42 -0
- package/dist/application/update/reporting.js +325 -0
- package/dist/application/update/reporting.js.map +1 -0
- package/dist/application/update/use-case.d.ts +8 -0
- package/dist/application/update/use-case.js +600 -0
- package/dist/application/update/use-case.js.map +1 -0
- package/dist/application/upgrade/use-case.d.ts +6 -0
- package/dist/application/upgrade/use-case.js +82 -0
- package/dist/application/upgrade/use-case.js.map +1 -0
- package/dist/args.d.ts +5 -65
- package/dist/args.js +4 -472
- package/dist/args.js.map +1 -1
- package/dist/artifact-lifecycle.d.ts +1 -21
- package/dist/artifact-lifecycle.js +1 -75
- package/dist/artifact-lifecycle.js.map +1 -1
- package/dist/catalogs.d.ts +1 -50
- package/dist/catalogs.js +1 -472
- package/dist/catalogs.js.map +1 -1
- package/dist/cli/args/contracts.d.ts +51 -0
- package/dist/cli/args/contracts.js +2 -0
- package/dist/cli/args/contracts.js.map +1 -0
- package/dist/cli/args/definitions.d.ts +6 -0
- package/dist/cli/args/definitions.js +187 -0
- package/dist/cli/args/definitions.js.map +1 -0
- package/dist/cli/args/help.d.ts +5 -0
- package/dist/cli/args/help.js +130 -0
- package/dist/cli/args/help.js.map +1 -0
- package/dist/cli/args/parser.d.ts +5 -0
- package/dist/cli/args/parser.js +145 -0
- package/dist/cli/args/parser.js.map +1 -0
- package/dist/cli/args/readers.d.ts +4 -0
- package/dist/cli/args/readers.js +19 -0
- package/dist/cli/args/readers.js.map +1 -0
- package/dist/cli/commands/diagnose.d.ts +4 -0
- package/dist/cli/commands/diagnose.js +12 -0
- package/dist/cli/commands/diagnose.js.map +1 -0
- package/dist/cli/commands/dispatch.d.ts +3 -0
- package/dist/cli/commands/dispatch.js +94 -0
- package/dist/cli/commands/dispatch.js.map +1 -0
- package/dist/cli/commands/help.d.ts +3 -0
- package/dist/cli/commands/help.js +32 -0
- package/dist/cli/commands/help.js.map +1 -0
- package/dist/cli/commands/helpers.d.ts +8 -0
- package/dist/cli/commands/helpers.js +97 -0
- package/dist/cli/commands/helpers.js.map +1 -0
- package/dist/cli/commands/initialize.d.ts +3 -0
- package/dist/cli/commands/initialize.js +7 -0
- package/dist/cli/commands/initialize.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +3 -0
- package/dist/cli/commands/migrate.js +8 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/plan.d.ts +3 -0
- package/dist/cli/commands/plan.js +34 -0
- package/dist/cli/commands/plan.js.map +1 -0
- package/dist/cli/commands/reference.d.ts +5 -0
- package/dist/cli/commands/reference.js +43 -0
- package/dist/cli/commands/reference.js.map +1 -0
- package/dist/cli/commands/update.d.ts +3 -0
- package/dist/cli/commands/update.js +9 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/commands/upgrade.d.ts +3 -0
- package/dist/cli/commands/upgrade.js +7 -0
- package/dist/cli/commands/upgrade.js.map +1 -0
- package/dist/cli/context.d.ts +1 -0
- package/dist/cli/context.js +2 -0
- package/dist/cli/context.js.map +1 -0
- package/dist/cli/project-options.d.ts +3 -0
- package/dist/cli/project-options.js +41 -0
- package/dist/cli/project-options.js.map +1 -0
- package/dist/cli.d.ts +3 -3
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands.d.ts +4 -35
- package/dist/commands.js +3 -2969
- package/dist/commands.js.map +1 -1
- package/dist/container-validation.d.ts +1 -1
- package/dist/domain/governance/activation/approvals.d.ts +351 -0
- package/dist/domain/governance/activation/approvals.js +528 -0
- package/dist/domain/governance/activation/approvals.js.map +1 -0
- package/dist/domain/governance/activation/canonical-json.d.ts +4 -0
- package/dist/domain/governance/activation/canonical-json.js +39 -0
- package/dist/domain/governance/activation/canonical-json.js.map +1 -0
- package/dist/domain/governance/activation/capabilities.d.ts +7 -0
- package/dist/domain/governance/activation/capabilities.js +33 -0
- package/dist/domain/governance/activation/capabilities.js.map +1 -0
- package/dist/domain/governance/activation/evidence.d.ts +63 -0
- package/dist/domain/governance/activation/evidence.js +444 -0
- package/dist/domain/governance/activation/evidence.js.map +1 -0
- package/dist/domain/governance/activation/graph.d.ts +397 -0
- package/dist/domain/governance/activation/graph.js +441 -0
- package/dist/domain/governance/activation/graph.js.map +1 -0
- package/dist/domain/governance/activation/inputs.d.ts +25 -0
- package/dist/domain/governance/activation/inputs.js +63 -0
- package/dist/domain/governance/activation/inputs.js.map +1 -0
- package/dist/domain/governance/activation/operations.d.ts +19 -0
- package/dist/domain/governance/activation/operations.js +181 -0
- package/dist/domain/governance/activation/operations.js.map +1 -0
- package/dist/domain/governance/activation/readiness.d.ts +27 -0
- package/dist/domain/governance/activation/readiness.js +269 -0
- package/dist/domain/governance/activation/readiness.js.map +1 -0
- package/dist/domain/governance/activation/types.d.ts +399 -0
- package/dist/domain/governance/activation/types.js +109 -0
- package/dist/domain/governance/activation/types.js.map +1 -0
- package/dist/domain/governance/activation/validators.d.ts +22 -0
- package/dist/domain/governance/activation/validators.js +1347 -0
- package/dist/domain/governance/activation/validators.js.map +1 -0
- package/dist/domain/governance/assessment/catalog.d.ts +14 -0
- package/dist/domain/governance/assessment/catalog.js +105 -0
- package/dist/domain/governance/assessment/catalog.js.map +1 -0
- package/dist/domain/governance/assessment/errors.d.ts +10 -0
- package/dist/domain/governance/assessment/errors.js +22 -0
- package/dist/domain/governance/assessment/errors.js.map +1 -0
- package/dist/domain/governance/assessment/index.d.ts +8 -0
- package/dist/domain/governance/assessment/index.js +9 -0
- package/dist/domain/governance/assessment/index.js.map +1 -0
- package/dist/domain/governance/assessment/live-normalize.d.ts +19 -0
- package/dist/domain/governance/assessment/live-normalize.js +403 -0
- package/dist/domain/governance/assessment/live-normalize.js.map +1 -0
- package/dist/domain/governance/assessment/predicates.d.ts +36 -0
- package/dist/domain/governance/assessment/predicates.js +545 -0
- package/dist/domain/governance/assessment/predicates.js.map +1 -0
- package/dist/domain/governance/assessment/report.d.ts +23 -0
- package/dist/domain/governance/assessment/report.js +266 -0
- package/dist/domain/governance/assessment/report.js.map +1 -0
- package/dist/domain/governance/assessment/sanitize.d.ts +8 -0
- package/dist/domain/governance/assessment/sanitize.js +60 -0
- package/dist/domain/governance/assessment/sanitize.js.map +1 -0
- package/dist/domain/governance/assessment/types.d.ts +174 -0
- package/dist/domain/governance/assessment/types.js +13 -0
- package/dist/domain/governance/assessment/types.js.map +1 -0
- package/dist/domain/governance/assessment/yaml.d.ts +6 -0
- package/dist/domain/governance/assessment/yaml.js +30 -0
- package/dist/domain/governance/assessment/yaml.js.map +1 -0
- package/dist/domain/governance/policy/identity.d.ts +64 -0
- package/dist/domain/governance/policy/identity.js +112 -0
- package/dist/domain/governance/policy/identity.js.map +1 -0
- package/dist/domain/migration/dependencies.d.ts +7 -0
- package/dist/domain/migration/dependencies.js +221 -0
- package/dist/domain/migration/dependencies.js.map +1 -0
- package/dist/domain/migration/inventory.d.ts +3 -0
- package/dist/domain/migration/inventory.js +15 -0
- package/dist/domain/migration/inventory.js.map +1 -0
- package/dist/domain/project/artifact-lifecycle.d.ts +69 -0
- package/dist/domain/project/artifact-lifecycle.js +137 -0
- package/dist/domain/project/artifact-lifecycle.js.map +1 -0
- package/dist/domain/project/catalog.d.ts +48 -0
- package/dist/domain/project/catalog.js +507 -0
- package/dist/domain/project/catalog.js.map +1 -0
- package/dist/domain/project/contracts.d.ts +247 -0
- package/dist/domain/project/contracts.js +2 -0
- package/dist/domain/project/contracts.js.map +1 -0
- package/dist/domain/project/errors.d.ts +3 -0
- package/dist/domain/project/errors.js +7 -0
- package/dist/domain/project/errors.js.map +1 -0
- package/dist/domain/project/infrastructure-layout.d.ts +26 -0
- package/dist/domain/project/infrastructure-layout.js +124 -0
- package/dist/domain/project/infrastructure-layout.js.map +1 -0
- package/dist/domain/project/inputs.d.ts +21 -0
- package/dist/domain/project/inputs.js +41 -0
- package/dist/domain/project/inputs.js.map +1 -0
- package/dist/domain/project/manifest/artifacts.d.ts +8 -0
- package/dist/domain/project/manifest/artifacts.js +150 -0
- package/dist/domain/project/manifest/artifacts.js.map +1 -0
- package/dist/domain/project/manifest/context.d.ts +13 -0
- package/dist/domain/project/manifest/context.js +2 -0
- package/dist/domain/project/manifest/context.js.map +1 -0
- package/dist/domain/project/manifest/fields.d.ts +6 -0
- package/dist/domain/project/manifest/fields.js +36 -0
- package/dist/domain/project/manifest/fields.js.map +1 -0
- package/dist/domain/project/manifest/governance.d.ts +8 -0
- package/dist/domain/project/manifest/governance.js +161 -0
- package/dist/domain/project/manifest/governance.js.map +1 -0
- package/dist/domain/project/manifest/project-identity.d.ts +6 -0
- package/dist/domain/project/manifest/project-identity.js +273 -0
- package/dist/domain/project/manifest/project-identity.js.map +1 -0
- package/dist/domain/project/manifest/reader.d.ts +9 -0
- package/dist/domain/project/manifest/reader.js +141 -0
- package/dist/domain/project/manifest/reader.js.map +1 -0
- package/dist/domain/project/paths.d.ts +2 -0
- package/dist/domain/project/paths.js +29 -0
- package/dist/domain/project/paths.js.map +1 -0
- package/dist/domain/project/planning.d.ts +19 -0
- package/dist/domain/project/planning.js +329 -0
- package/dist/domain/project/planning.js.map +1 -0
- package/dist/domain/project/retired-workload.d.ts +4 -0
- package/dist/domain/project/retired-workload.js +18 -0
- package/dist/domain/project/retired-workload.js.map +1 -0
- package/dist/domain/project/supported-stack.d.ts +113 -0
- package/dist/domain/project/supported-stack.js +426 -0
- package/dist/domain/project/supported-stack.js.map +1 -0
- package/dist/domain/workstation/constraints.d.ts +6 -0
- package/dist/domain/workstation/constraints.js +8 -0
- package/dist/domain/workstation/constraints.js.map +1 -0
- package/dist/file-system.d.ts +10 -44
- package/dist/file-system.js +9 -1245
- package/dist/file-system.js.map +1 -1
- package/dist/framework-adapters.d.ts +1 -1
- package/dist/framework-validation.d.ts +1 -1
- package/dist/framework-validation.js +1 -1
- package/dist/framework-validation.js.map +1 -1
- package/dist/genai-templates.d.ts +2 -9
- package/dist/genai-templates.js +4 -5
- package/dist/genai-templates.js.map +1 -1
- package/dist/generators/common/artifacts.d.ts +6 -0
- package/dist/generators/common/artifacts.js +30 -0
- package/dist/generators/common/artifacts.js.map +1 -0
- package/dist/generators/common/base.d.ts +17 -0
- package/dist/generators/common/base.js +421 -0
- package/dist/generators/common/base.js.map +1 -0
- package/dist/generators/common/dotenv-validation.d.ts +2 -0
- package/dist/generators/common/dotenv-validation.js +80 -0
- package/dist/generators/common/dotenv-validation.js.map +1 -0
- package/dist/generators/common/environments.d.ts +3 -0
- package/dist/generators/common/environments.js +15 -0
- package/dist/generators/common/environments.js.map +1 -0
- package/dist/generators/common/frontend.d.ts +15 -0
- package/dist/generators/common/frontend.js +166 -0
- package/dist/generators/common/frontend.js.map +1 -0
- package/dist/generators/common/python-settings.d.ts +2 -0
- package/dist/generators/common/python-settings.js +70 -0
- package/dist/generators/common/python-settings.js.map +1 -0
- package/dist/generators/common/spec-workflow.d.ts +28 -0
- package/dist/generators/common/spec-workflow.js +567 -0
- package/dist/generators/common/spec-workflow.js.map +1 -0
- package/dist/generators/common/values.d.ts +13 -0
- package/dist/generators/common/values.js +16 -0
- package/dist/generators/common/values.js.map +1 -0
- package/dist/generators/containers/compose.d.ts +7 -0
- package/dist/generators/containers/compose.js +196 -0
- package/dist/generators/containers/compose.js.map +1 -0
- package/dist/generators/containers/context.d.ts +1 -0
- package/dist/generators/containers/context.js +43 -0
- package/dist/generators/containers/context.js.map +1 -0
- package/dist/generators/containers/images.d.ts +7 -0
- package/dist/generators/containers/images.js +119 -0
- package/dist/generators/containers/images.js.map +1 -0
- package/dist/generators/context.d.ts +42 -0
- package/dist/generators/context.js +38 -0
- package/dist/generators/context.js.map +1 -0
- package/dist/generators/genai/backend.d.ts +20 -0
- package/dist/generators/genai/backend.js +667 -0
- package/dist/generators/genai/backend.js.map +1 -0
- package/dist/generators/genai/configuration.d.ts +3 -0
- package/dist/generators/genai/configuration.js +43 -0
- package/dist/generators/genai/configuration.js.map +1 -0
- package/dist/generators/genai/database.d.ts +7 -0
- package/dist/generators/genai/database.js +71 -0
- package/dist/generators/genai/database.js.map +1 -0
- package/dist/generators/genai/functions.d.ts +15 -0
- package/dist/generators/genai/functions.js +156 -0
- package/dist/generators/genai/functions.js.map +1 -0
- package/dist/generators/genai/index.d.ts +8 -0
- package/dist/generators/genai/index.js +11 -0
- package/dist/generators/genai/index.js.map +1 -0
- package/dist/generators/genai/patterns.d.ts +9 -0
- package/dist/generators/genai/patterns.js +309 -0
- package/dist/generators/genai/patterns.js.map +1 -0
- package/dist/generators/infrastructure/azure.d.ts +18 -0
- package/dist/generators/infrastructure/azure.js +655 -0
- package/dist/generators/infrastructure/azure.js.map +1 -0
- package/dist/generators/infrastructure/names.d.ts +23 -0
- package/dist/generators/infrastructure/names.js +51 -0
- package/dist/generators/infrastructure/names.js.map +1 -0
- package/dist/generators/standard/configuration.d.ts +3 -0
- package/dist/generators/standard/configuration.js +26 -0
- package/dist/generators/standard/configuration.js.map +1 -0
- package/dist/generators/standard/go.d.ts +17 -0
- package/dist/generators/standard/go.js +338 -0
- package/dist/generators/standard/go.js.map +1 -0
- package/dist/generators/standard/index.d.ts +12 -0
- package/dist/generators/standard/index.js +12 -0
- package/dist/generators/standard/index.js.map +1 -0
- package/dist/generators/standard/node.d.ts +20 -0
- package/dist/generators/standard/node.js +314 -0
- package/dist/generators/standard/node.js.map +1 -0
- package/dist/generators/standard/python.d.ts +18 -0
- package/dist/generators/standard/python.js +191 -0
- package/dist/generators/standard/python.js.map +1 -0
- package/dist/go-template-assets.js +3 -3
- package/dist/go-template-assets.js.map +1 -1
- package/dist/governance-activation/activation-state.d.ts +1 -1
- package/dist/governance-activation/activation-state.js +46 -9
- package/dist/governance-activation/activation-state.js.map +1 -1
- package/dist/governance-activation/approvals.d.ts +1 -188
- package/dist/governance-activation/approvals.js +1 -507
- package/dist/governance-activation/approvals.js.map +1 -1
- package/dist/governance-activation/canonical-json.d.ts +1 -3
- package/dist/governance-activation/canonical-json.js +1 -35
- package/dist/governance-activation/canonical-json.js.map +1 -1
- package/dist/governance-activation/commands.d.ts +1 -1
- package/dist/governance-activation/commands.js +72 -106
- package/dist/governance-activation/commands.js.map +1 -1
- package/dist/governance-activation/compatibility.d.ts +11 -3
- package/dist/governance-activation/compatibility.js +31 -4
- package/dist/governance-activation/compatibility.js.map +1 -1
- package/dist/governance-activation/credentials.d.ts +3 -3
- package/dist/governance-activation/credentials.js +5 -5
- package/dist/governance-activation/credentials.js.map +1 -1
- package/dist/governance-activation/doctor.d.ts +1 -1
- package/dist/governance-activation/doctor.js +28 -96
- package/dist/governance-activation/doctor.js.map +1 -1
- package/dist/governance-activation/evidence.d.ts +1 -49
- package/dist/governance-activation/evidence.js +1 -245
- package/dist/governance-activation/evidence.js.map +1 -1
- package/dist/governance-activation/git-ignore.d.ts +9 -0
- package/dist/governance-activation/git-ignore.js +76 -0
- package/dist/governance-activation/git-ignore.js.map +1 -0
- package/dist/governance-activation/graph.d.ts +1 -397
- package/dist/governance-activation/graph.js +1 -440
- package/dist/governance-activation/graph.js.map +1 -1
- package/dist/governance-activation/identity.d.ts +1 -35
- package/dist/governance-activation/identity.js +1 -88
- package/dist/governance-activation/identity.js.map +1 -1
- package/dist/governance-activation/index.d.ts +3 -0
- package/dist/governance-activation/index.js +3 -0
- package/dist/governance-activation/index.js.map +1 -1
- package/dist/governance-activation/inputs.d.ts +8 -0
- package/dist/governance-activation/inputs.js +146 -0
- package/dist/governance-activation/inputs.js.map +1 -0
- package/dist/governance-activation/migration.d.ts +4 -3
- package/dist/governance-activation/migration.js +14 -6
- package/dist/governance-activation/migration.js.map +1 -1
- package/dist/governance-activation/phase-bootstrap-state.d.ts +3 -0
- package/dist/governance-activation/phase-bootstrap-state.js +128 -0
- package/dist/governance-activation/phase-bootstrap-state.js.map +1 -0
- package/dist/governance-activation/phase-discovery.d.ts +2 -0
- package/dist/governance-activation/phase-discovery.js +88 -0
- package/dist/governance-activation/phase-discovery.js.map +1 -0
- package/dist/governance-activation/phase-governance.d.ts +4 -0
- package/dist/governance-activation/phase-governance.js +141 -0
- package/dist/governance-activation/phase-governance.js.map +1 -0
- package/dist/governance-activation/phase-publication.d.ts +8 -0
- package/dist/governance-activation/phase-publication.js +318 -0
- package/dist/governance-activation/phase-publication.js.map +1 -0
- package/dist/governance-activation/read-only.d.ts +30 -0
- package/dist/governance-activation/read-only.js +93 -0
- package/dist/governance-activation/read-only.js.map +1 -0
- package/dist/governance-activation/readiness.d.ts +1 -25
- package/dist/governance-activation/readiness.js +1 -222
- package/dist/governance-activation/readiness.js.map +1 -1
- package/dist/governance-activation/reconciliation.d.ts +1 -1
- package/dist/governance-activation/reconciliation.js +3 -3
- package/dist/governance-activation/reconciliation.js.map +1 -1
- package/dist/governance-activation/release-integrity.d.ts +1 -1
- package/dist/governance-activation/release-integrity.js +2 -2
- package/dist/governance-activation/release-integrity.js.map +1 -1
- package/dist/governance-activation/seed-lifecycle.d.ts +9 -1
- package/dist/governance-activation/seed-lifecycle.js +197 -63
- package/dist/governance-activation/seed-lifecycle.js.map +1 -1
- package/dist/governance-activation/source-of-truth.d.ts +5 -3
- package/dist/governance-activation/source-of-truth.js +32 -52
- package/dist/governance-activation/source-of-truth.js.map +1 -1
- package/dist/governance-activation/spec-kit-seed.d.ts +9 -0
- package/dist/governance-activation/spec-kit-seed.js +43 -0
- package/dist/governance-activation/spec-kit-seed.js.map +1 -0
- package/dist/governance-activation/task-projection.d.ts +1 -1
- package/dist/governance-activation/transition-planning.d.ts +15 -0
- package/dist/governance-activation/transition-planning.js +250 -0
- package/dist/governance-activation/transition-planning.js.map +1 -0
- package/dist/governance-activation/transition-ports.d.ts +150 -0
- package/dist/governance-activation/transition-ports.js +2 -0
- package/dist/governance-activation/transition-ports.js.map +1 -0
- package/dist/governance-activation/transition-process.d.ts +7 -0
- package/dist/governance-activation/transition-process.js +21 -0
- package/dist/governance-activation/transition-process.js.map +1 -0
- package/dist/governance-activation/transition-records.d.ts +56 -0
- package/dist/governance-activation/transition-records.js +208 -0
- package/dist/governance-activation/transition-records.js.map +1 -0
- package/dist/governance-activation/transitions.d.ts +6 -165
- package/dist/governance-activation/transitions.js +142 -2055
- package/dist/governance-activation/transitions.js.map +1 -1
- package/dist/governance-activation/types.d.ts +1 -390
- package/dist/governance-activation/types.js +1 -107
- package/dist/governance-activation/types.js.map +1 -1
- package/dist/governance-activation/validators.d.ts +1 -17
- package/dist/governance-activation/validators.js +1 -1304
- package/dist/governance-activation/validators.js.map +1 -1
- package/dist/governance-assessment/catalog.d.ts +1 -2
- package/dist/governance-assessment/catalog.js +18 -85
- package/dist/governance-assessment/catalog.js.map +1 -1
- package/dist/governance-assessment/command.d.ts +1 -1
- package/dist/governance-assessment/command.js +8 -12
- package/dist/governance-assessment/command.js.map +1 -1
- package/dist/governance-assessment/engine.d.ts +6 -11
- package/dist/governance-assessment/engine.js +463 -114
- package/dist/governance-assessment/engine.js.map +1 -1
- package/dist/governance-assessment/live-normalize.d.ts +1 -19
- package/dist/governance-assessment/live-normalize.js +1 -402
- package/dist/governance-assessment/live-normalize.js.map +1 -1
- package/dist/governance-assessment/live-transport.d.ts +2 -6
- package/dist/governance-assessment/live-transport.js +10 -22
- package/dist/governance-assessment/live-transport.js.map +1 -1
- package/dist/governance-assessment/live.js +55 -5
- package/dist/governance-assessment/live.js.map +1 -1
- package/dist/governance-assessment/predicates.d.ts +1 -27
- package/dist/governance-assessment/predicates.js +1 -329
- package/dist/governance-assessment/predicates.js.map +1 -1
- package/dist/governance-assessment/project.d.ts +13 -17
- package/dist/governance-assessment/project.js +59 -149
- package/dist/governance-assessment/project.js.map +1 -1
- package/dist/governance-assessment/readers.d.ts +1 -5
- package/dist/governance-assessment/readers.js +5 -13
- package/dist/governance-assessment/readers.js.map +1 -1
- package/dist/governance-assessment/report.d.ts +1 -23
- package/dist/governance-assessment/report.js +1 -265
- package/dist/governance-assessment/report.js.map +1 -1
- package/dist/governance-assessment/sanitize.d.ts +1 -8
- package/dist/governance-assessment/sanitize.js +1 -56
- package/dist/governance-assessment/sanitize.js.map +1 -1
- package/dist/governance-assessment/types.d.ts +1 -173
- package/dist/governance-assessment/types.js +1 -12
- package/dist/governance-assessment/types.js.map +1 -1
- package/dist/governance-assessment/yaml.d.ts +1 -6
- package/dist/governance-assessment/yaml.js +1 -29
- package/dist/governance-assessment/yaml.js.map +1 -1
- package/dist/init-filesystem.d.ts +1 -1
- package/dist/init-filesystem.js +126 -174
- package/dist/init-filesystem.js.map +1 -1
- package/dist/interactive.d.ts +2 -2
- package/dist/interactive.js +42 -41
- package/dist/interactive.js.map +1 -1
- package/dist/migrate-plan.d.ts +1 -1
- package/dist/migrate-plan.js +14 -8
- package/dist/migrate-plan.js.map +1 -1
- package/dist/npm-template-assets.js +5 -4
- package/dist/npm-template-assets.js.map +1 -1
- package/dist/openspec-profile.d.ts +1 -1
- package/dist/opentofu-template-assets.js +3 -3
- package/dist/opentofu-template-assets.js.map +1 -1
- package/dist/package-identity.d.ts +3 -0
- package/dist/package-identity.js +13 -2
- package/dist/package-identity.js.map +1 -1
- package/dist/planner.d.ts +1 -19
- package/dist/planner.js +1 -565
- package/dist/planner.js.map +1 -1
- package/dist/process-runner.d.ts +1 -1
- package/dist/project-dependencies.d.ts +5 -3
- package/dist/project-dependencies.js +74 -63
- package/dist/project-dependencies.js.map +1 -1
- package/dist/published-verifier.js +61 -30
- package/dist/published-verifier.js.map +1 -1
- package/dist/python-template-assets.js +6 -9
- package/dist/python-template-assets.js.map +1 -1
- package/dist/reconcile.d.ts +1 -1
- package/dist/reconcile.js +2 -2
- package/dist/reconcile.js.map +1 -1
- package/dist/repository-governance.d.ts +5 -2
- package/dist/repository-governance.js +126 -112
- package/dist/repository-governance.js.map +1 -1
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +1 -1
- package/dist/scan.d.ts +6 -2
- package/dist/scan.js +78 -30
- package/dist/scan.js.map +1 -1
- package/dist/self-upgrade.d.ts +1 -1
- package/dist/self-upgrade.js +20 -7
- package/dist/self-upgrade.js.map +1 -1
- package/dist/stable-release.js +7 -1
- package/dist/stable-release.js.map +1 -1
- package/dist/standard-templates.d.ts +2 -2
- package/dist/standard-templates.js +6 -841
- package/dist/standard-templates.js.map +1 -1
- package/dist/supported-stack.d.ts +3 -115
- package/dist/supported-stack.js +4 -438
- package/dist/supported-stack.js.map +1 -1
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/templates.d.ts +10 -20
- package/dist/templates.js +52 -3261
- package/dist/templates.js.map +1 -1
- package/dist/types.d.ts +1 -263
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/version.js +2 -6
- package/dist/version.js.map +1 -1
- package/dist/workstation-catalog.d.ts +5 -2
- package/dist/workstation-catalog.js +33 -2
- package/dist/workstation-catalog.js.map +1 -1
- package/dist/workstation.d.ts +4 -3
- package/dist/workstation.js +86 -32
- package/dist/workstation.js.map +1 -1
- package/docs/assets/liftoff-terminal.svg +3 -3
- package/docs/azure-deployment.md +107 -10
- package/docs/cli-reference.md +49 -13
- package/docs/configuration-and-manifests.md +139 -34
- package/docs/existing-repositories.md +33 -6
- package/docs/getting-started.md +44 -31
- package/docs/prerequisites.md +34 -35
- package/docs/project-structure.md +39 -46
- package/docs/repository-governance.md +90 -24
- package/docs/safety-and-consent.md +65 -12
- package/docs/spec-workflows-and-agents.md +31 -28
- package/docs/supported-stack.md +11 -9
- package/docs/troubleshooting.md +107 -49
- package/docs/workloads.md +46 -62
- package/package.json +4 -7
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/UPSTREAM_LICENSE.txt +0 -21
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/catalog.json +0 -520
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/packaged/gitignore +0 -27
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/README.md +0 -25
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/components.json +0 -22
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/eslint.config.js +0 -23
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/index.html +0 -13
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/package-lock.json +0 -6156
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/package.json +0 -60
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/public/power-apps.svg +0 -55
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/App.tsx +0 -17
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/assets/react.svg +0 -1
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/mode-toggle.tsx +0 -37
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/badge.tsx +0 -46
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/button.tsx +0 -60
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/calendar.tsx +0 -211
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/card.tsx +0 -92
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/chart.tsx +0 -355
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/checkbox.tsx +0 -32
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/command.tsx +0 -184
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/dialog.tsx +0 -141
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/dropdown-menu.tsx +0 -257
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/input.tsx +0 -21
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/label.tsx +0 -22
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/popover.tsx +0 -46
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/progress.tsx +0 -29
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/select.tsx +0 -185
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/separator.tsx +0 -26
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/skeleton.tsx +0 -13
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/table.tsx +0 -114
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/tabs.tsx +0 -66
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/textarea.tsx +0 -18
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/components/ui/tooltip.tsx +0 -61
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/hooks/use-theme.ts +0 -11
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/index.css +0 -131
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/lib/utils.ts +0 -6
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/main.tsx +0 -10
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/pages/_layout.tsx +0 -31
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/pages/home.tsx +0 -59
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/pages/not-found.tsx +0 -14
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/providers/query-provider.tsx +0 -26
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/providers/sonner-provider.tsx +0 -23
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/providers/theme-provider.tsx +0 -64
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/src/router.tsx +0 -24
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/tsconfig.app.json +0 -34
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/tsconfig.json +0 -13
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/tsconfig.node.json +0 -26
- package/assets/power-apps-code-app/3438c352483e40982f6c5c0fc36fd71f8e7adbbb/starter/vite.config.ts +0 -19
- package/assets/power-apps-code-app/README.md +0 -27
- package/dist/code-apps-plugin.d.ts +0 -13
- package/dist/code-apps-plugin.js +0 -69
- package/dist/code-apps-plugin.js.map +0 -1
- package/dist/power-apps-assets.d.ts +0 -30
- package/dist/power-apps-assets.js +0 -131
- package/dist/power-apps-assets.js.map +0 -1
- package/dist/power-apps-templates.d.ts +0 -3
- package/dist/power-apps-templates.js +0 -177
- package/dist/power-apps-templates.js.map +0 -1
- package/dist/power-apps-validation.d.ts +0 -1
- package/dist/power-apps-validation.js +0 -79
- package/dist/power-apps-validation.js.map +0 -1
|
@@ -1,23 +1,39 @@
|
|
|
1
|
-
import { canonicalJson, canonicalSha256, sha256Hex } from '../governance
|
|
2
|
-
import { currentActivationIdentity, canonicalPhaseGraph } from '../governance
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { planDigestFor } from '../governance-activation/transitions.js';
|
|
1
|
+
import { canonicalJson, canonicalSha256, sha256Hex } from '../domain/governance/activation/canonical-json.js';
|
|
2
|
+
import { currentActivationIdentity, canonicalPhaseGraph } from '../domain/governance/activation/graph.js';
|
|
3
|
+
import { canonicalApprovalEnvelopeHash, evaluateApprovalForTransitionPlan, transitionPlanForPhase } from '../domain/governance/activation/approvals.js';
|
|
4
|
+
import { inspectCurrentActivationEvidence } from '../governance-activation/read-only.js';
|
|
6
5
|
import { governanceChangeMetadataFileName, validateGovernanceChangeMetadata } from '../governance-activation/source-of-truth.js';
|
|
6
|
+
import { phaseIds } from '../domain/governance/activation/types.js';
|
|
7
7
|
import { loadAssessmentCatalog } from './catalog.js';
|
|
8
|
-
import {
|
|
8
|
+
import { inspectAssessmentProject, ordinaryGitAssessmentProject } from './project.js';
|
|
9
|
+
import { inspectAssessmentGit, repositoryName } from '../adapters/git/governance-assessment.js';
|
|
9
10
|
import { AssessmentFiles, AssessmentInputError, parseAssessmentJson } from './readers.js';
|
|
10
11
|
import { parseAssessmentWorkflow } from './yaml.js';
|
|
11
12
|
import { collectLiveAssessment } from './live.js';
|
|
12
|
-
import { classifyFinding, assembleAssessmentReport } from '
|
|
13
|
-
import { actionReferences, failOpenFlags, pinnedActions, protectedRefs, requiredCheckContexts, requiredContextBindings, securityPipeline, singleMaintainer, tagControls, workflowPermissions, observedRequiredContexts } from '
|
|
14
|
-
import { isRecord, jsonValue, notObserved, observed, sanitizeAssessmentText, source } from '
|
|
13
|
+
import { classifyFinding, assembleAssessmentReport } from '../domain/governance/assessment/report.js';
|
|
14
|
+
import { actionReferences, effectiveProtectedRefs, effectiveRequiredContextBindings, failOpenFlags, pinnedActions, protectedRefs, requiredCheckContexts, requiredContextBindings, runnerAlignment, securityPipeline, singleMaintainer, tagControls, workflowPermissions, observedRequiredContexts } from '../domain/governance/assessment/predicates.js';
|
|
15
|
+
import { isRecord, jsonValue, notObserved, observed, sanitizeAssessmentText, source } from '../domain/governance/assessment/sanitize.js';
|
|
15
16
|
const documentationPaths = [
|
|
16
17
|
['CONTRIBUTING.md'], ['docs', 'operations', 'github-governance.md'],
|
|
17
18
|
['docs', 'security', 'scanning.md'], ['docs', 'operations', 'alerting.md'],
|
|
18
19
|
['docs', 'operations', 'service-health.md'], ['docs', 'security', 'audit-evidence.md'],
|
|
19
20
|
['docs', 'ai-acceptable-use.md']
|
|
20
21
|
];
|
|
22
|
+
function activationAuthorityFingerprint(inspection) {
|
|
23
|
+
if (inspection.status === 'not-started') {
|
|
24
|
+
return canonicalSha256({ status: inspection.status });
|
|
25
|
+
}
|
|
26
|
+
const firstContext = inspection.contexts[phaseIds[0]];
|
|
27
|
+
const stable = JSON.parse(JSON.stringify({
|
|
28
|
+
status: inspection.status,
|
|
29
|
+
state: inspection.state,
|
|
30
|
+
snapshot: inspection.snapshot,
|
|
31
|
+
records: inspection.records,
|
|
32
|
+
reviewedPlans: firstContext.reviewedPlans ?? [],
|
|
33
|
+
selections: inspection.selections
|
|
34
|
+
}));
|
|
35
|
+
return canonicalSha256(stable);
|
|
36
|
+
}
|
|
21
37
|
async function localFacts(files, project, capturedAt) {
|
|
22
38
|
const workflowParts = await files.list(['.github', 'workflows'], ['.yml', '.yaml']);
|
|
23
39
|
const workflows = [];
|
|
@@ -76,6 +92,15 @@ async function localFacts(files, project, capturedAt) {
|
|
|
76
92
|
throw new Error('Active governance metadata does not match the recorded change and identity.');
|
|
77
93
|
}
|
|
78
94
|
baseline = metadata.baselineSha === '0'.repeat(64) ? null : metadata.baselineSha;
|
|
95
|
+
if (baseline && project.inputSnapshot && baseline !== project.inputSnapshot.baselineSha) {
|
|
96
|
+
project.diagnostics.push({
|
|
97
|
+
code: 'current-input-mismatch',
|
|
98
|
+
severity: 'warning',
|
|
99
|
+
source: parts.join('/'),
|
|
100
|
+
message: 'The recorded governance baseline does not match the independently recomputed current input snapshot; evidence-backed scope is withheld.'
|
|
101
|
+
});
|
|
102
|
+
baseline = null;
|
|
103
|
+
}
|
|
79
104
|
}
|
|
80
105
|
catch (error) {
|
|
81
106
|
project.diagnostics.push({
|
|
@@ -97,58 +122,45 @@ async function localFacts(files, project, capturedAt) {
|
|
|
97
122
|
};
|
|
98
123
|
}
|
|
99
124
|
function boundPlan(project, phaseId, now) {
|
|
100
|
-
|
|
125
|
+
const currentContext = project.evidenceContexts?.[phaseId];
|
|
126
|
+
const selection = project.activationSelections?.[phaseId];
|
|
127
|
+
const selected = selection?.issues.length === 0 ? selection.selected : null;
|
|
128
|
+
const payload = selected?.payload;
|
|
129
|
+
if (!project.state || !currentContext || !selected ||
|
|
130
|
+
!isRecord(payload) || typeof payload.planDigest !== 'string' ||
|
|
131
|
+
typeof payload.savedPlanDigest !== 'string' ||
|
|
132
|
+
project.identity.availability !== 'known')
|
|
101
133
|
return null;
|
|
102
|
-
const candidates =
|
|
134
|
+
const candidates = (currentContext.reviewedPlans ?? []).filter((plan) => plan.phaseId === phaseId &&
|
|
135
|
+
plan.planDigest === payload.planDigest &&
|
|
136
|
+
canonicalSha256(plan) === payload.savedPlanDigest &&
|
|
137
|
+
plan.baselineDigest === currentContext.baselineSha &&
|
|
103
138
|
canonicalJson(plan.identity) === canonicalJson(currentActivationIdentity) &&
|
|
104
139
|
Date.parse(plan.createdAt) <= now.getTime() &&
|
|
105
140
|
Date.parse(plan.createdAt) <= Date.parse(project.state.phases[phaseId].updatedAt)).sort((a, b) => Date.parse(b.createdAt) - Date.parse(a.createdAt));
|
|
106
141
|
const plan = candidates[0];
|
|
107
142
|
if (!plan || plan.baselineDigest === '0'.repeat(64) || plan.inputDigest === '1'.repeat(64) ||
|
|
143
|
+
plan.baselineDigest !== currentContext.baselineSha ||
|
|
144
|
+
plan.inputDigest !== currentContext.inputDigest ||
|
|
145
|
+
plan.transitionDigest !== currentContext.transition.transitionDigest ||
|
|
108
146
|
candidates.some((candidate) => candidate.createdAt === plan.createdAt && candidate.planDigest !== plan.planDigest))
|
|
109
147
|
return null;
|
|
110
|
-
const phase = canonicalPhaseGraph.phases.find((entry) => entry.id === phaseId);
|
|
111
|
-
if (!phase)
|
|
112
|
-
return null;
|
|
113
|
-
const authority = transitionPlanForPhase(phase, project.state, {
|
|
114
|
-
phaseId, baselineSha: plan.baselineDigest, inputDigest: plan.inputDigest, transitionDigest: plan.transitionDigest
|
|
115
|
-
});
|
|
116
|
-
if (plan.planDigest !== planDigestFor({
|
|
117
|
-
phase, transitionDigest: plan.transitionDigest, operations: plan.operations, approvalPlanDigest: authority.planDigest
|
|
118
|
-
}))
|
|
119
|
-
return null;
|
|
120
148
|
return plan;
|
|
121
149
|
}
|
|
122
150
|
export function selectBoundAssessmentEvidence(project, phaseId, now) {
|
|
123
151
|
const plan = boundPlan(project, phaseId, now);
|
|
124
|
-
|
|
152
|
+
const selection = project.activationSelections?.[phaseId];
|
|
153
|
+
const selected = selection?.issues.length === 0 ? selection.selected : null;
|
|
154
|
+
if (!plan || !project.state || !selected ||
|
|
155
|
+
selected.header.result !== project.state.phases[phaseId].state)
|
|
125
156
|
return null;
|
|
126
|
-
|
|
127
|
-
return null;
|
|
128
|
-
const phase = canonicalPhaseGraph.phases.find((entry) => entry.id === phaseId);
|
|
129
|
-
const references = project.state.phases[phaseId].evidence;
|
|
130
|
-
const candidates = project.evidence.filter((record) => record.header.phaseId === phaseId &&
|
|
131
|
-
references.some((reference) => reference.phaseId === phaseId && reference.evidenceId === record.evidenceId &&
|
|
132
|
-
reference.headerDigest === canonicalSha256(record.header) && reference.result === record.header.result));
|
|
133
|
-
const selected = selectLatestPhaseEvidence(candidates, evidenceContextForPhase(phaseId, {
|
|
134
|
-
repositoryId: project.state.repository.id, identity: currentActivationIdentity,
|
|
135
|
-
phaseGraphHash: currentActivationIdentity.phaseGraphHash, now,
|
|
136
|
-
baselineSha: plan.baselineDigest, inputDigest: plan.inputDigest, transitionDigest: plan.transitionDigest,
|
|
137
|
-
liveReadbackProviders: phase ? requiredLiveReadbackProviders(phase) : []
|
|
138
|
-
})).selected;
|
|
139
|
-
if (!selected || selected.header.result !== project.state.phases[phaseId].state)
|
|
140
|
-
return null;
|
|
141
|
-
const record = candidates.find((entry) => entry.evidenceId === selected.evidenceId &&
|
|
142
|
-
canonicalSha256(entry.header) === selected.headerDigest);
|
|
143
|
-
return record ? { ...selected, record } : null;
|
|
157
|
+
return selected;
|
|
144
158
|
}
|
|
145
159
|
function applicability(control, project, now) {
|
|
146
160
|
if (control.applicability === 'always')
|
|
147
161
|
return 'applicable';
|
|
148
|
-
if (project.project.workload.kind === 'power-apps-code-app')
|
|
149
|
-
return 'inapplicable';
|
|
150
162
|
if (control.applicability === 'api')
|
|
151
|
-
return 'applicable';
|
|
163
|
+
return project.kind === 'liftoff' ? 'applicable' : 'unknown';
|
|
152
164
|
const discovery = selectBoundAssessmentEvidence(project, 'phase-0-complete', now);
|
|
153
165
|
if (!project.state || discovery?.header.result !== 'verified')
|
|
154
166
|
return 'unknown';
|
|
@@ -156,41 +168,81 @@ function applicability(control, project, now) {
|
|
|
156
168
|
? project.state.applicability.privateStagingDast
|
|
157
169
|
: project.state.applicability.statePath === 'bootstrap-local') ? 'applicable' : 'inapplicable';
|
|
158
170
|
}
|
|
171
|
+
function approvalBindsRepository(project, approval, repository, now) {
|
|
172
|
+
const currentBaseline = project.inputSnapshot?.baselineSha ??
|
|
173
|
+
project.bindingBaseline;
|
|
174
|
+
if (!project.state || !currentBaseline)
|
|
175
|
+
return false;
|
|
176
|
+
const plan = boundPlan(project, approval.phaseId, now);
|
|
177
|
+
const phase = canonicalPhaseGraph.phases.find((entry) => entry.id === approval.phaseId);
|
|
178
|
+
const authority = plan && phase ? transitionPlanForPhase(phase, project.state, {
|
|
179
|
+
phaseId: phase.id,
|
|
180
|
+
baselineSha: plan.baselineDigest,
|
|
181
|
+
inputDigest: plan.inputDigest,
|
|
182
|
+
transitionDigest: plan.transitionDigest
|
|
183
|
+
}) : null;
|
|
184
|
+
return approval.baselineSha === currentBaseline &&
|
|
185
|
+
project.identity.availability === 'known' &&
|
|
186
|
+
Date.parse(approval.approvedAt) <= now.getTime() &&
|
|
187
|
+
Date.parse(approval.expiresAt) > now.getTime() &&
|
|
188
|
+
project.state.phases[approval.phaseId].approvals.includes(approval.id) &&
|
|
189
|
+
Boolean(plan && authority && phase?.approvalGate.required) &&
|
|
190
|
+
authority?.planDigest === approval.planDigest &&
|
|
191
|
+
!evaluateApprovalForTransitionPlan(authority, [approval], { now }).approvalRequired &&
|
|
192
|
+
plan.approval.envelopeId === approval.id &&
|
|
193
|
+
plan.approval.envelopeHash === canonicalApprovalEnvelopeHash(approval) &&
|
|
194
|
+
approval.destinations.some((destination) => destination.type === 'repository' &&
|
|
195
|
+
(destination.repository ?? destination.identity).toLowerCase() === repository.toLowerCase());
|
|
196
|
+
}
|
|
159
197
|
export function resolveAssessmentLiveScope(project, git, now) {
|
|
160
|
-
|
|
161
|
-
let
|
|
162
|
-
if (git.repository &&
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
198
|
+
let repository = git.originState === 'verified' ? git.repository : null;
|
|
199
|
+
let remoteBindingVerified = false;
|
|
200
|
+
if (git.repository && project.state?.remoteBinding) {
|
|
201
|
+
const remote = project.state.remoteBinding;
|
|
202
|
+
const bound = repositoryName(remote.name, remote.id);
|
|
203
|
+
const matchingPush = git.pushUrls.length === 1 &&
|
|
204
|
+
git.pushUrls[0] === remote.pushUrl &&
|
|
205
|
+
project.inputSnapshot?.git.pushUrls.length === 1 &&
|
|
206
|
+
project.inputSnapshot.git.pushUrls[0] === remote.pushUrl;
|
|
207
|
+
if (!bound ||
|
|
208
|
+
`${git.repository.owner}/${git.repository.name}`.toLowerCase() !==
|
|
209
|
+
`${bound.owner}/${bound.name}`.toLowerCase() ||
|
|
210
|
+
!matchingPush) {
|
|
211
|
+
project.diagnostics.push({
|
|
212
|
+
code: 'repository-binding-conflict',
|
|
213
|
+
severity: 'warning',
|
|
214
|
+
source: 'Git/activation state',
|
|
215
|
+
message: 'Git fetch/push origin and the verified remote repository binding disagree; evidence-backed provider scope is withheld.'
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
repository = { ...git.repository, id: bound.id };
|
|
220
|
+
remoteBindingVerified = true;
|
|
166
221
|
}
|
|
167
|
-
else
|
|
168
|
-
repository = { ...git.repository, id: stateRepo.id };
|
|
169
222
|
}
|
|
170
223
|
const scope = {
|
|
171
|
-
repository,
|
|
172
|
-
|
|
224
|
+
repository,
|
|
225
|
+
refs: repository ? ['develop', 'main'] : [],
|
|
226
|
+
...(repository ? { refPrefixes: ['release/', 'hotfix/'] } : {}),
|
|
227
|
+
environments: project.project ? [...project.project.workload.environments] : [],
|
|
173
228
|
runner: null, azure: []
|
|
174
229
|
};
|
|
175
230
|
if (!repository || !project.state)
|
|
176
231
|
return scope;
|
|
232
|
+
if (!remoteBindingVerified) {
|
|
233
|
+
project.diagnostics.push({
|
|
234
|
+
code: 'remote-binding-unavailable',
|
|
235
|
+
severity: 'warning',
|
|
236
|
+
source: 'activation state',
|
|
237
|
+
message: 'No matching verified remote repository binding is available; evidence-backed runner and Azure reads are withheld.'
|
|
238
|
+
});
|
|
239
|
+
return scope;
|
|
240
|
+
}
|
|
177
241
|
const fullName = `${repository.owner}/${repository.name}`;
|
|
242
|
+
const azureBindings = new Map();
|
|
243
|
+
const conflictingAzureBindings = new Set();
|
|
178
244
|
for (const approval of project.approvals) {
|
|
179
|
-
|
|
180
|
-
const phase = canonicalPhaseGraph.phases.find((entry) => entry.id === approval.phaseId);
|
|
181
|
-
const authority = plan && phase ? transitionPlanForPhase(phase, project.state, {
|
|
182
|
-
phaseId: phase.id, baselineSha: plan.baselineDigest, inputDigest: plan.inputDigest, transitionDigest: plan.transitionDigest
|
|
183
|
-
}) : null;
|
|
184
|
-
if (!project.bindingBaseline || approval.baselineSha !== project.bindingBaseline ||
|
|
185
|
-
project.identity.availability !== 'known' ||
|
|
186
|
-
Date.parse(approval.approvedAt) > now.getTime() ||
|
|
187
|
-
Date.parse(approval.expiresAt) <= now.getTime() ||
|
|
188
|
-
!project.state.phases[approval.phaseId].approvals.includes(approval.id) ||
|
|
189
|
-
!plan || !authority || !phase?.approvalGate.required || authority.planDigest !== approval.planDigest ||
|
|
190
|
-
evaluateApprovalForTransitionPlan(authority, [approval], { now }).approvalRequired ||
|
|
191
|
-
plan.approval.envelopeId !== approval.id ||
|
|
192
|
-
plan.approval.envelopeHash !== canonicalApprovalEnvelopeHash(approval) ||
|
|
193
|
-
!approval.destinations.some((destination) => destination.type === 'repository' && (destination.repository ?? destination.identity).toLowerCase() === fullName.toLowerCase()))
|
|
245
|
+
if (!approvalBindsRepository(project, approval, fullName, now))
|
|
194
246
|
continue;
|
|
195
247
|
const environments = approval.destinations.filter((destination) => destination.type === 'environment' &&
|
|
196
248
|
['dev', 'staging', 'prod'].includes(destination.identity)).map((destination) => destination.identity);
|
|
@@ -199,22 +251,79 @@ export function resolveAssessmentLiveScope(project, git, now) {
|
|
|
199
251
|
const environment = environments[0];
|
|
200
252
|
if (environment !== 'dev' && environment !== 'staging' && environment !== 'prod')
|
|
201
253
|
continue;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
254
|
+
const selected = selectBoundAssessmentEvidence(project, approval.phaseId, now);
|
|
255
|
+
const payload = selected?.payload;
|
|
256
|
+
const assessmentScope = isRecord(payload) && isRecord(payload.assessmentScope)
|
|
257
|
+
? payload.assessmentScope
|
|
258
|
+
: null;
|
|
259
|
+
if (!assessmentScope || !Array.isArray(assessmentScope.azure)) {
|
|
260
|
+
if (approval.resources.some((resource) => resource.identity.startsWith('/subscriptions/')) &&
|
|
261
|
+
!project.diagnostics.some((entry) => entry.code === 'unbound-resource-role' && entry.source === approval.phaseId)) {
|
|
262
|
+
project.diagnostics.push({
|
|
263
|
+
code: 'unbound-resource-role',
|
|
264
|
+
severity: 'warning',
|
|
265
|
+
source: approval.phaseId,
|
|
266
|
+
message: 'Approved ARM resources lacked a current body-committed evidence payload with explicit assessment environment and role; Azure reads were withheld.'
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
for (const value of assessmentScope.azure) {
|
|
272
|
+
if (!isRecord(value) ||
|
|
273
|
+
Object.keys(value).some((key) => ![
|
|
274
|
+
'subscriptionId', 'environment', 'resourceId', 'resourceType', 'role'
|
|
275
|
+
].includes(key)) ||
|
|
276
|
+
typeof value.subscriptionId !== 'string' ||
|
|
277
|
+
value.environment !== environment ||
|
|
278
|
+
typeof value.resourceId !== 'string' ||
|
|
279
|
+
typeof value.resourceType !== 'string' ||
|
|
280
|
+
!['state', 'application', 'runner-network'].includes(String(value.role))) {
|
|
205
281
|
continue;
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
282
|
+
}
|
|
283
|
+
const subscriptionId = value.subscriptionId;
|
|
284
|
+
const resourceId = value.resourceId;
|
|
285
|
+
const resourceType = value.resourceType;
|
|
286
|
+
const match = resourceId.match(/^\/subscriptions\/([a-f0-9-]{36})\/resourceGroups\/[^/]+\/providers\/([A-Za-z0-9.]+)\/([A-Za-z0-9]+)\/[^/]+(?:\/[A-Za-z0-9]+\/[^/]+)*$/iu);
|
|
287
|
+
if (!match ||
|
|
288
|
+
match[1].toLowerCase() !== subscriptionId.toLowerCase() ||
|
|
289
|
+
!approval.resources.some((resource) => resource.identity.toLowerCase() === resourceId.toLowerCase()) ||
|
|
290
|
+
!approval.destinations.some((destination) => destination.type === 'subscription' &&
|
|
291
|
+
(destination.subscriptionId ?? destination.identity).toLowerCase() === subscriptionId.toLowerCase())) {
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
const binding = {
|
|
295
|
+
subscriptionId,
|
|
296
|
+
environment: environment,
|
|
297
|
+
resourceId,
|
|
298
|
+
resourceType,
|
|
299
|
+
role: value.role
|
|
300
|
+
};
|
|
301
|
+
const key = binding.resourceId.toLowerCase();
|
|
302
|
+
const previous = azureBindings.get(key);
|
|
303
|
+
if (conflictingAzureBindings.has(key) ||
|
|
304
|
+
previous && (previous.environment !== binding.environment ||
|
|
305
|
+
previous.role !== binding.role ||
|
|
306
|
+
previous.resourceType.toLowerCase() !== binding.resourceType.toLowerCase())) {
|
|
307
|
+
azureBindings.delete(key);
|
|
308
|
+
conflictingAzureBindings.add(key);
|
|
309
|
+
project.diagnostics.push({
|
|
310
|
+
code: 'conflicting-resource-binding',
|
|
311
|
+
severity: 'warning',
|
|
312
|
+
source: binding.resourceId,
|
|
313
|
+
message: 'Conflicting body-committed ARM environment, role, or resource-type bindings were excluded before live scope deduplication.'
|
|
314
|
+
});
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
if (!previous)
|
|
318
|
+
azureBindings.set(key, binding);
|
|
213
319
|
}
|
|
214
320
|
}
|
|
215
321
|
const runnerRecord = selectBoundAssessmentEvidence(project, 'runner-ready', now);
|
|
216
|
-
const rawRunner = runnerRecord?.
|
|
217
|
-
|
|
322
|
+
const rawRunner = runnerRecord?.payload;
|
|
323
|
+
const runnerApproval = project.approvals.some((approval) => approval.phaseId === 'runner-ready' &&
|
|
324
|
+
approvalBindsRepository(project, approval, fullName, now));
|
|
325
|
+
if (runnerApproval && runnerRecord?.header.result === 'verified' &&
|
|
326
|
+
isRecord(rawRunner) && rawRunner.kind === 'runner-ready.v1' &&
|
|
218
327
|
rawRunner.organization === repository.owner && Number.isInteger(rawRunner.runnerId) && Number(rawRunner.runnerId) > 0 &&
|
|
219
328
|
(rawRunner.groupId === null || Number.isInteger(rawRunner.groupId)) &&
|
|
220
329
|
(rawRunner.networkConfigurationId === null || typeof rawRunner.networkConfigurationId === 'string')) {
|
|
@@ -224,7 +333,7 @@ export function resolveAssessmentLiveScope(project, git, now) {
|
|
|
224
333
|
networkConfigurationId: typeof rawRunner.networkConfigurationId === 'string' ? rawRunner.networkConfigurationId : null
|
|
225
334
|
};
|
|
226
335
|
}
|
|
227
|
-
scope.azure = [...
|
|
336
|
+
scope.azure = [...azureBindings.values()]
|
|
228
337
|
.sort((a, b) => a.resourceId.localeCompare(b.resourceId, 'en'));
|
|
229
338
|
return scope;
|
|
230
339
|
}
|
|
@@ -252,6 +361,34 @@ function livePredicate(live, key, evaluate) {
|
|
|
252
361
|
converted.facts = observation.value;
|
|
253
362
|
return converted;
|
|
254
363
|
}
|
|
364
|
+
function partialLivePredicate(live, key, evaluate) {
|
|
365
|
+
const observation = live.observations[key];
|
|
366
|
+
if (!observation) {
|
|
367
|
+
return {
|
|
368
|
+
observation: notObserved(`Live ${key} was not collected.`),
|
|
369
|
+
provenDifference: false
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
if (observation.availability === 'observed') {
|
|
373
|
+
return {
|
|
374
|
+
observation: livePredicate(live, key, evaluate),
|
|
375
|
+
provenDifference: false
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
if (observation.facts !== undefined) {
|
|
379
|
+
const evaluated = evaluate(observation.facts);
|
|
380
|
+
if (evaluated.value === false) {
|
|
381
|
+
return {
|
|
382
|
+
observation: {
|
|
383
|
+
...observation,
|
|
384
|
+
reason: `${observation.reason ?? 'Live collection was incomplete.'} Independently observed facts prove a difference: ${evaluated.reason}`
|
|
385
|
+
},
|
|
386
|
+
provenDifference: true
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return { observation, provenDifference: false };
|
|
391
|
+
}
|
|
255
392
|
function bool(value, reason) { return { value, reason }; }
|
|
256
393
|
function rows(value) {
|
|
257
394
|
return Array.isArray(value) && value.every(isRecord) ? value : null;
|
|
@@ -268,6 +405,18 @@ export function findAssessmentException(control, approvals, scope, baseline, res
|
|
|
268
405
|
(scope.environment === null || approval.destinations.some((entry) => entry.type === 'environment' && entry.identity === scope.environment)));
|
|
269
406
|
return found ? { id: found.id, expiresAt: found.expiresAt, envelopeDigest: canonicalApprovalEnvelopeHash(found) } : null;
|
|
270
407
|
}
|
|
408
|
+
export function rejectedAssessmentExceptionDiagnostic(control, approvals, exception) {
|
|
409
|
+
if (exception !== null ||
|
|
410
|
+
!approvals.some((approval) => approval.policyExceptions.includes(control.id))) {
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
return {
|
|
414
|
+
code: 'rejected-exception',
|
|
415
|
+
severity: 'warning',
|
|
416
|
+
source: control.id,
|
|
417
|
+
message: 'A recorded exception was rejected because its current identity, baseline, scope, resource, approval time, or expiry did not match this finding.'
|
|
418
|
+
};
|
|
419
|
+
}
|
|
271
420
|
function evidenceObservation(project, git, capturedAt) {
|
|
272
421
|
if (!project.state)
|
|
273
422
|
return notObserved('No compatible activation state is available.');
|
|
@@ -288,14 +437,78 @@ function evidenceObservation(project, git, capturedAt) {
|
|
|
288
437
|
return notObserved('Baseline/setup progress, approvals, applicability and current readback are not all established.');
|
|
289
438
|
return observed(true, source('evidence', 'governance/evidence', capturedAt, project.evidence.map((record) => record.header.phaseId)));
|
|
290
439
|
}
|
|
440
|
+
function invalidateUnstableObservations(findings, kinds, reason) {
|
|
441
|
+
for (const finding of findings) {
|
|
442
|
+
if (finding.applicability === 'inapplicable')
|
|
443
|
+
continue;
|
|
444
|
+
let invalidated = false;
|
|
445
|
+
for (const layer of finding.requiredProof) {
|
|
446
|
+
const observation = finding.observations[layer];
|
|
447
|
+
if (observation?.source && kinds.has(observation.source.kind)) {
|
|
448
|
+
finding.observations[layer] = notObserved(reason);
|
|
449
|
+
invalidated = true;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
if (!invalidated)
|
|
453
|
+
continue;
|
|
454
|
+
finding.exception = null;
|
|
455
|
+
finding.missingProof = finding.requiredProof.filter((layer) => finding.observations[layer]?.availability === 'not-observed');
|
|
456
|
+
const remaining = finding.requiredProof
|
|
457
|
+
.map((layer) => finding.observations[layer])
|
|
458
|
+
.filter((observation) => observation !== undefined);
|
|
459
|
+
const absent = remaining.some((observation) => observation.availability === 'missing');
|
|
460
|
+
const differs = remaining.some((observation) => observation.availability === 'observed' &&
|
|
461
|
+
canonicalJson(observation.value) !== canonicalJson(finding.expected));
|
|
462
|
+
finding.classification = differs
|
|
463
|
+
? 'conflicting'
|
|
464
|
+
: absent
|
|
465
|
+
? 'missing'
|
|
466
|
+
: 'not-observed';
|
|
467
|
+
finding.reasons.push(reason);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
function invalidateChangedActivationAuthority(findings, controls) {
|
|
471
|
+
const controlsById = new Map(controls.map((control) => [
|
|
472
|
+
control.id,
|
|
473
|
+
control
|
|
474
|
+
]));
|
|
475
|
+
for (const finding of findings) {
|
|
476
|
+
const control = controlsById.get(finding.controlId);
|
|
477
|
+
const evidenceDerivedApplicability = control?.applicability === 'private-dast' ||
|
|
478
|
+
control?.applicability === 'state-path';
|
|
479
|
+
if (finding.applicability === 'inapplicable' &&
|
|
480
|
+
!evidenceDerivedApplicability ||
|
|
481
|
+
!(evidenceDerivedApplicability ||
|
|
482
|
+
finding.requiredProof.includes('evidence') ||
|
|
483
|
+
finding.controlId.startsWith('azure.') ||
|
|
484
|
+
finding.controlId.startsWith('runner.') ||
|
|
485
|
+
finding.controlId.startsWith('evidence.'))) {
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
488
|
+
if (evidenceDerivedApplicability) {
|
|
489
|
+
finding.applicability = 'unknown';
|
|
490
|
+
}
|
|
491
|
+
finding.classification = 'not-observed';
|
|
492
|
+
finding.exception = null;
|
|
493
|
+
finding.missingProof = [...finding.requiredProof];
|
|
494
|
+
finding.reasons.push('Current activation inputs, evidence references, evidence bodies, or reviewed plans changed during collection; evidence-backed scope and results were withheld.');
|
|
495
|
+
for (const layer of finding.requiredProof) {
|
|
496
|
+
finding.observations[layer] = notObserved('Activation authority changed during collection.');
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
291
500
|
async function managedFindings(control, project, files, scope, capturedAt) {
|
|
292
501
|
const findings = [];
|
|
293
502
|
if (project.renderedCore.length === 0) {
|
|
294
503
|
return [classifyFinding({
|
|
295
504
|
control, scope, applicability: 'applicable',
|
|
296
505
|
observations: {
|
|
297
|
-
recorded: notObserved(
|
|
298
|
-
|
|
506
|
+
recorded: notObserved(project.kind === 'git'
|
|
507
|
+
? 'Ordinary Git repositories have no recorded Liftoff ownership inventory.'
|
|
508
|
+
: 'Historical agent selection is not recorded.'),
|
|
509
|
+
declared: notObserved(project.kind === 'git'
|
|
510
|
+
? 'No Liftoff managed handoff is inferred for an ordinary Git repository.'
|
|
511
|
+
: 'The current handoff cannot be rendered without inferring agent configuration.')
|
|
299
512
|
}
|
|
300
513
|
})];
|
|
301
514
|
}
|
|
@@ -349,7 +562,22 @@ function evaluateControl(control, project, facts, live, git, liveScope, now) {
|
|
|
349
562
|
const branch = repository?.availability === 'observed' && isRecord(repository.value) && typeof repository.value.defaultBranch === 'string'
|
|
350
563
|
? repository.value.defaultBranch : null;
|
|
351
564
|
observations.declared = declaredRules((value) => protectedRefs(value, project.state?.repository.defaultBranch ?? null));
|
|
352
|
-
|
|
565
|
+
const rules = live.observations['github.rulesets'];
|
|
566
|
+
const branches = live.observations['github.branches'];
|
|
567
|
+
const families = live.observations['github.ref-families'];
|
|
568
|
+
if (rules?.availability === 'observed' &&
|
|
569
|
+
branches?.availability === 'observed' &&
|
|
570
|
+
families?.availability === 'observed') {
|
|
571
|
+
observations.live = predicateObservation(effectiveProtectedRefs(rules.value, branches.value, families.value, branch), rules.source);
|
|
572
|
+
observations.live.facts = jsonValue({
|
|
573
|
+
rulesets: rules.value,
|
|
574
|
+
branches: branches.value,
|
|
575
|
+
refFamilies: families.value
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
else {
|
|
579
|
+
observations.live = notObserved('Complete repository/inherited rulesets, classic/effective branch protection, and bounded release/hotfix enumeration are required.');
|
|
580
|
+
}
|
|
353
581
|
break;
|
|
354
582
|
}
|
|
355
583
|
case 'single-maintainer':
|
|
@@ -381,14 +609,27 @@ function evaluateControl(control, project, facts, live, git, liveScope, now) {
|
|
|
381
609
|
: contexts.length ? predicateObservation(bool(true, `Declared contexts: ${contexts.map((entry) => entry.name).join(', ')}`), facts.ruleSource)
|
|
382
610
|
: absent('No required status check contexts were declared.', facts.ruleSource);
|
|
383
611
|
const rules = live.observations['github.rulesets'];
|
|
612
|
+
const branches = live.observations['github.branches'];
|
|
613
|
+
const families = live.observations['github.ref-families'];
|
|
384
614
|
const repository = live.observations['github.repository'];
|
|
385
615
|
const branch = repository?.availability === 'observed' && isRecord(repository.value) && typeof repository.value.defaultBranch === 'string'
|
|
386
616
|
? repository.value.defaultBranch : null;
|
|
387
|
-
const
|
|
388
|
-
|
|
617
|
+
const familyRefs = families?.availability === 'observed' && isRecord(families.value) &&
|
|
618
|
+
Array.isArray(families.value.refs)
|
|
619
|
+
? families.value.refs.filter((value) => typeof value === 'string')
|
|
620
|
+
: [];
|
|
621
|
+
const assessedRefs = [...new Set([...liveScope.refs, ...familyRefs])].sort();
|
|
622
|
+
const comparisonRefs = assessedRefs.length ? assessedRefs : ['develop', 'main'];
|
|
623
|
+
const declaredBindings = requiredContextBindings(facts.rulesets, comparisonRefs, branch);
|
|
624
|
+
const rulesetBindings = rules?.availability === 'observed'
|
|
625
|
+
? requiredContextBindings(rules.value, comparisonRefs, branch)
|
|
626
|
+
: null;
|
|
627
|
+
const enforcedBindings = rules?.availability === 'observed' && branches?.availability === 'observed'
|
|
628
|
+
? effectiveRequiredContextBindings(rules.value, branches.value, comparisonRefs, branch)
|
|
629
|
+
: rulesetBindings;
|
|
389
630
|
observations.declared.facts = jsonValue(declaredBindings);
|
|
390
|
-
const bindingsDiffer = Boolean(contexts?.length && declaredBindings &&
|
|
391
|
-
canonicalJson(declaredBindings) !== canonicalJson(
|
|
631
|
+
const bindingsDiffer = Boolean(contexts?.length && declaredBindings && rulesetBindings &&
|
|
632
|
+
canonicalJson(declaredBindings) !== canonicalJson(rulesetBindings));
|
|
392
633
|
if (bindingsDiffer) {
|
|
393
634
|
difference = 'conflicting';
|
|
394
635
|
const checks = live.observations['github.checks'];
|
|
@@ -398,8 +639,11 @@ function evaluateControl(control, project, facts, live, git, liveScope, now) {
|
|
|
398
639
|
: notObserved(`${reason} Check-run proof remains unobserved: ${checks?.reason ?? 'not collected'}`, rules?.source ?? null);
|
|
399
640
|
}
|
|
400
641
|
else {
|
|
401
|
-
observations.live = rules?.availability === 'observed' &&
|
|
402
|
-
|
|
642
|
+
observations.live = rules?.availability === 'observed' &&
|
|
643
|
+
families?.availability === 'observed' &&
|
|
644
|
+
declaredBindings &&
|
|
645
|
+
enforcedBindings
|
|
646
|
+
? livePredicate(live, 'github.checks', (value) => observedRequiredContexts(rules.value, value, branch, branches?.value))
|
|
403
647
|
: notObserved('Live rule and exact commit-bound check observations are required.');
|
|
404
648
|
}
|
|
405
649
|
observations.live.facts = jsonValue({
|
|
@@ -457,19 +701,22 @@ function evaluateControl(control, project, facts, live, git, liveScope, now) {
|
|
|
457
701
|
break;
|
|
458
702
|
case 'runner': {
|
|
459
703
|
observations.recorded = liveScope.runner ? observed(true, source('evidence', 'runner-ready repository binding', capturedAt, jsonValue(liveScope.runner))) : notObserved('No current, exact runner/group/network binding is available.');
|
|
460
|
-
observations.live = livePredicate(live, 'github.runner', (value) =>
|
|
461
|
-
&& value.groupId === liveScope.runner?.groupId && value.runnerId === liveScope.runner?.runnerId ? true : null, 'Exact repository/group/network assignment, labels and runner capacity must be observed.'));
|
|
704
|
+
observations.live = livePredicate(live, 'github.runner', (value) => runnerAlignment(value, scope.repository));
|
|
462
705
|
break;
|
|
463
706
|
}
|
|
464
|
-
case 'providers':
|
|
465
|
-
|
|
707
|
+
case 'providers': {
|
|
708
|
+
const evaluation = partialLivePredicate(live, 'azure.providers', (value) => {
|
|
466
709
|
const providers = rows(value);
|
|
467
710
|
return bool(!providers?.length ? null : providers.every((entry) => entry.registrationState === 'Registered'), 'Every explicitly required namespace must have terminal Registered readback.');
|
|
468
711
|
});
|
|
712
|
+
observations.live = evaluation.observation;
|
|
713
|
+
if (evaluation.provenDifference)
|
|
714
|
+
difference = 'conflicting';
|
|
469
715
|
expected = true;
|
|
470
716
|
break;
|
|
471
|
-
|
|
472
|
-
|
|
717
|
+
}
|
|
718
|
+
case 'storage': {
|
|
719
|
+
const evaluation = partialLivePredicate(live, 'azure.resources', (value) => {
|
|
473
720
|
const storage = rows(value)?.filter((entry) => String(entry.resourceType).toLowerCase() === 'microsoft.storage/storageaccounts');
|
|
474
721
|
if (!storage?.length)
|
|
475
722
|
return bool(null, 'No explicit environment/role-bound storage observation is available.');
|
|
@@ -481,11 +728,15 @@ function evaluateControl(control, project, facts, live, git, liveScope, now) {
|
|
|
481
728
|
});
|
|
482
729
|
return bool(values.includes(false) ? false : values.includes(null) ? null : true, 'State storage requires ZRS; application storage uses Dev LRS and Staging/Production ZRS.');
|
|
483
730
|
});
|
|
731
|
+
observations.live = evaluation.observation;
|
|
732
|
+
if (evaluation.provenDifference)
|
|
733
|
+
difference = 'conflicting';
|
|
484
734
|
expected = true;
|
|
485
735
|
break;
|
|
486
|
-
|
|
736
|
+
}
|
|
737
|
+
case 'network': {
|
|
487
738
|
observations.recorded = liveScope.azure.some((entry) => entry.role === 'runner-network') ? observed(true, source('evidence', 'approved Staging network bindings', capturedAt, jsonValue(liveScope.azure))) : notObserved('No approved Staging network bindings were available.');
|
|
488
|
-
|
|
739
|
+
const evaluation = partialLivePredicate(live, 'azure.resources', (value) => {
|
|
489
740
|
const network = rows(value)?.filter((entry) => entry.role === 'runner-network');
|
|
490
741
|
if (!network?.length)
|
|
491
742
|
return bool(null, 'No bound runner-network readback is available.');
|
|
@@ -494,7 +745,11 @@ function evaluateControl(control, project, facts, live, git, liveScope, now) {
|
|
|
494
745
|
return bool(false, 'A runner subnet still enables implicit default outbound access.');
|
|
495
746
|
return bool(null, 'Full subnet, route, DNS and exclusive NAT/Firewall proof is required; observed metadata alone is insufficient.');
|
|
496
747
|
});
|
|
748
|
+
observations.live = evaluation.observation;
|
|
749
|
+
if (evaluation.provenDifference)
|
|
750
|
+
difference = 'conflicting';
|
|
497
751
|
break;
|
|
752
|
+
}
|
|
498
753
|
case 'evidence':
|
|
499
754
|
observations.evidence = evidenceObservation(project, git, capturedAt);
|
|
500
755
|
break;
|
|
@@ -505,9 +760,15 @@ function evaluateControl(control, project, facts, live, git, liveScope, now) {
|
|
|
505
760
|
for (const layer of control.proofLayers)
|
|
506
761
|
observations[layer] = notObserved(`No supported evaluator exists for ${control.id}; the required proof is not inferred.`);
|
|
507
762
|
}
|
|
763
|
+
const exception = findAssessmentException(control, project.approvals, scope, facts.baseline, exceptionResource, now);
|
|
764
|
+
const exceptionDiagnostic = rejectedAssessmentExceptionDiagnostic(control, project.approvals, exception);
|
|
765
|
+
if (exceptionDiagnostic &&
|
|
766
|
+
!project.diagnostics.some((entry) => entry.code === 'rejected-exception' && entry.source === control.id)) {
|
|
767
|
+
project.diagnostics.push(exceptionDiagnostic);
|
|
768
|
+
}
|
|
508
769
|
return classifyFinding({
|
|
509
770
|
control, scope, expected, applicability: applicability(control, project, now), observations, difference,
|
|
510
|
-
exception
|
|
771
|
+
exception
|
|
511
772
|
});
|
|
512
773
|
}
|
|
513
774
|
export async function assessGovernance(projectRoot, options = {}) {
|
|
@@ -522,7 +783,77 @@ export async function assessGovernance(projectRoot, options = {}) {
|
|
|
522
783
|
try {
|
|
523
784
|
const loaded = loadAssessmentCatalog();
|
|
524
785
|
target = loaded.target;
|
|
525
|
-
|
|
786
|
+
let project;
|
|
787
|
+
let git;
|
|
788
|
+
let initialActivationInspection = null;
|
|
789
|
+
let initialActivationFingerprint = null;
|
|
790
|
+
try {
|
|
791
|
+
project = await inspectAssessmentProject(files);
|
|
792
|
+
git = await inspectAssessmentGit(projectRoot, options.runner);
|
|
793
|
+
}
|
|
794
|
+
catch (error) {
|
|
795
|
+
if (!(error instanceof AssessmentInputError) || error.code !== 'project-not-found') {
|
|
796
|
+
throw error;
|
|
797
|
+
}
|
|
798
|
+
git = await inspectAssessmentGit(projectRoot, options.runner);
|
|
799
|
+
if (!git.isRepository) {
|
|
800
|
+
throw new AssessmentInputError('project-not-found', 'No Liftoff manifest or valid Git worktree was found at the selected boundary.');
|
|
801
|
+
}
|
|
802
|
+
project = ordinaryGitAssessmentProject();
|
|
803
|
+
}
|
|
804
|
+
if (project.manifest) {
|
|
805
|
+
try {
|
|
806
|
+
const activation = await inspectCurrentActivationEvidence(projectRoot, project.manifest, {
|
|
807
|
+
...(options.runner ? { runner: options.runner } : {}),
|
|
808
|
+
now: captured
|
|
809
|
+
});
|
|
810
|
+
initialActivationInspection = activation;
|
|
811
|
+
initialActivationFingerprint = activationAuthorityFingerprint(activation);
|
|
812
|
+
if (activation.status === 'inspected') {
|
|
813
|
+
project.state = activation.state;
|
|
814
|
+
project.stateIdentity = jsonValue(activation.state.identity);
|
|
815
|
+
project.identity.stateSource = 'user';
|
|
816
|
+
project.inputSnapshot = activation.snapshot;
|
|
817
|
+
project.evidenceContexts = activation.contexts;
|
|
818
|
+
project.evidence = activation.records;
|
|
819
|
+
project.plans = activation.contexts[phaseIds[0]].reviewedPlans
|
|
820
|
+
? [...activation.contexts[phaseIds[0]].reviewedPlans]
|
|
821
|
+
: [];
|
|
822
|
+
project.activationSelections = activation.selections;
|
|
823
|
+
for (const [phaseId, selection] of Object.entries(activation.selections)) {
|
|
824
|
+
if (selection.selected && selection.historicalIssues?.length) {
|
|
825
|
+
project.diagnostics.push({
|
|
826
|
+
code: 'historical-evidence-ignored',
|
|
827
|
+
severity: 'info',
|
|
828
|
+
source: phaseId,
|
|
829
|
+
message: sanitizeAssessmentText(selection.historicalIssues.map((issue) => issue.message).join('; '))
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
if (selection.issues.length === 0)
|
|
833
|
+
continue;
|
|
834
|
+
project.invalidEvidence = true;
|
|
835
|
+
project.diagnostics.push({
|
|
836
|
+
code: 'invalid-current-evidence',
|
|
837
|
+
severity: 'warning',
|
|
838
|
+
source: phaseId,
|
|
839
|
+
message: sanitizeAssessmentText(selection.issues.map((issue) => issue.message).join('; '))
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
catch (error) {
|
|
845
|
+
project.identity.availability = 'unsupported';
|
|
846
|
+
project.identity.stateSource = 'unsupported';
|
|
847
|
+
project.diagnostics.push({
|
|
848
|
+
code: 'activation-history-diagnostic-only',
|
|
849
|
+
severity: 'warning',
|
|
850
|
+
source: 'activation read-only inspection',
|
|
851
|
+
message: sanitizeAssessmentText(error instanceof Error
|
|
852
|
+
? error.message
|
|
853
|
+
: 'Activation history could not be interpreted as current executable proof.')
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
}
|
|
526
857
|
projectIdentity = project.identity;
|
|
527
858
|
const disabled = project.identity.profile === 'none';
|
|
528
859
|
if (disabled)
|
|
@@ -531,7 +862,6 @@ export async function assessGovernance(projectRoot, options = {}) {
|
|
|
531
862
|
snapshot: { capturedAt: captured.toISOString(), repository: null, localHead: null, worktreeDigest: files.digest(), inputsStable: await files.stable() },
|
|
532
863
|
findings: [], diagnostics: project.diagnostics, disabled: true
|
|
533
864
|
});
|
|
534
|
-
const git = await inspectAssessmentGit(projectRoot, options.runner);
|
|
535
865
|
project.diagnostics.push(...git.issues.map((message) => ({
|
|
536
866
|
code: 'git-not-observed', severity: 'warning', message, source: 'Git metadata'
|
|
537
867
|
})));
|
|
@@ -549,21 +879,40 @@ export async function assessGovernance(projectRoot, options = {}) {
|
|
|
549
879
|
findings.push(evaluateControl(control, project, facts, live, git, scope, captured));
|
|
550
880
|
}
|
|
551
881
|
const worktreeDigest = files.digest();
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
882
|
+
let activationStable = true;
|
|
883
|
+
if (project.manifest && initialActivationInspection && initialActivationFingerprint) {
|
|
884
|
+
try {
|
|
885
|
+
const finalActivation = await inspectCurrentActivationEvidence(projectRoot, project.manifest, {
|
|
886
|
+
...(options.runner ? { runner: options.runner } : {}),
|
|
887
|
+
now: captured
|
|
888
|
+
});
|
|
889
|
+
activationStable =
|
|
890
|
+
activationAuthorityFingerprint(finalActivation) ===
|
|
891
|
+
initialActivationFingerprint;
|
|
892
|
+
}
|
|
893
|
+
catch {
|
|
894
|
+
activationStable = false;
|
|
565
895
|
}
|
|
566
896
|
}
|
|
897
|
+
const finalGit = await inspectAssessmentGit(projectRoot, options.runner);
|
|
898
|
+
const filesStable = await files.stable();
|
|
899
|
+
const gitStable = canonicalJson(git) === canonicalJson(finalGit);
|
|
900
|
+
const inputsStable = filesStable && gitStable && activationStable;
|
|
901
|
+
if (!filesStable) {
|
|
902
|
+
invalidateUnstableObservations(findings, new Set(['file', 'evidence']), 'Relevant local files changed during collection; rerun assessment for current local proof.');
|
|
903
|
+
}
|
|
904
|
+
if (!gitStable) {
|
|
905
|
+
invalidateUnstableObservations(findings, new Set(['git']), 'Relevant Git metadata changed during collection; rerun assessment for current Git proof.');
|
|
906
|
+
}
|
|
907
|
+
if (!activationStable) {
|
|
908
|
+
invalidateChangedActivationAuthority(findings, loaded.catalog.controls);
|
|
909
|
+
project.diagnostics.push({
|
|
910
|
+
code: 'activation-authority-changed',
|
|
911
|
+
severity: 'warning',
|
|
912
|
+
source: 'activation read-only inspection',
|
|
913
|
+
message: 'Current activation inputs, evidence, state references, or reviewed plans changed during collection; dependent proof was withheld.'
|
|
914
|
+
});
|
|
915
|
+
}
|
|
567
916
|
return assembleAssessmentReport({
|
|
568
917
|
projectRoot, mode: options.live ? 'live' : 'local', target, projectIdentity,
|
|
569
918
|
snapshot: { capturedAt: captured.toISOString(), repository, localHead: git.head, worktreeDigest, inputsStable },
|