@msn-control/liftoff 0.10.3 → 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 +364 -20
- package/README.md +29 -29
- package/assets/governance/single-maintainer-gitflow/assessment-controls.json +39 -0
- package/assets/supported-stack.json +7 -138
- 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 -441
- package/dist/args.js.map +1 -1
- package/dist/artifact-lifecycle.d.ts +1 -21
- package/dist/artifact-lifecycle.js +1 -73
- 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 +4 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands.d.ts +4 -35
- package/dist/commands.js +3 -2812
- 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 -41
- package/dist/file-system.js +9 -1204
- 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 +107 -103
- 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 -24
- package/dist/governance-activation/readiness.js +1 -220
- 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 +10 -2
- package/dist/governance-activation/seed-lifecycle.js +244 -66
- 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 -157
- package/dist/governance-activation/transitions.js +143 -2045
- 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 +7 -0
- package/dist/governance-assessment/catalog.js +31 -0
- package/dist/governance-assessment/catalog.js.map +1 -0
- package/dist/governance-assessment/command.d.ts +10 -0
- package/dist/governance-assessment/command.js +77 -0
- package/dist/governance-assessment/command.js.map +1 -0
- package/dist/governance-assessment/engine.d.ts +14 -0
- package/dist/governance-assessment/engine.js +935 -0
- package/dist/governance-assessment/engine.js.map +1 -0
- package/dist/governance-assessment/index.d.ts +5 -0
- package/dist/governance-assessment/index.js +6 -0
- package/dist/governance-assessment/index.js.map +1 -0
- package/dist/governance-assessment/live-normalize.d.ts +1 -0
- package/dist/governance-assessment/live-normalize.js +2 -0
- package/dist/governance-assessment/live-normalize.js.map +1 -0
- package/dist/governance-assessment/live-transport.d.ts +34 -0
- package/dist/governance-assessment/live-transport.js +455 -0
- package/dist/governance-assessment/live-transport.js.map +1 -0
- package/dist/governance-assessment/live.d.ts +2 -0
- package/dist/governance-assessment/live.js +689 -0
- package/dist/governance-assessment/live.js.map +1 -0
- package/dist/governance-assessment/predicates.d.ts +1 -0
- package/dist/governance-assessment/predicates.js +2 -0
- package/dist/governance-assessment/predicates.js.map +1 -0
- package/dist/governance-assessment/project.d.ts +33 -0
- package/dist/governance-assessment/project.js +178 -0
- package/dist/governance-assessment/project.js.map +1 -0
- package/dist/governance-assessment/readers.d.ts +14 -0
- package/dist/governance-assessment/readers.js +122 -0
- package/dist/governance-assessment/readers.js.map +1 -0
- package/dist/governance-assessment/report.d.ts +1 -0
- package/dist/governance-assessment/report.js +2 -0
- package/dist/governance-assessment/report.js.map +1 -0
- package/dist/governance-assessment/sanitize.d.ts +1 -0
- package/dist/governance-assessment/sanitize.js +2 -0
- package/dist/governance-assessment/sanitize.js.map +1 -0
- package/dist/governance-assessment/types.d.ts +6 -0
- package/dist/governance-assessment/types.js +2 -0
- package/dist/governance-assessment/types.js.map +1 -0
- package/dist/governance-assessment/yaml.d.ts +1 -0
- package/dist/governance-assessment/yaml.js +2 -0
- package/dist/governance-assessment/yaml.js.map +1 -0
- 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 +5 -1
- package/dist/migrate-plan.js +87 -10
- 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 +5 -1
- package/dist/process-runner.js +164 -8
- package/dist/process-runner.js.map +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 +67 -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/release-identity.js +19 -0
- package/dist/release-identity.js.map +1 -1
- package/dist/repository-governance.d.ts +10 -2
- package/dist/repository-governance.js +240 -99
- 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/contract.d.ts +2 -0
- package/dist/telemetry/contract.js +7 -0
- package/dist/telemetry/contract.js.map +1 -1
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/templates.d.ts +10 -20
- package/dist/templates.js +52 -3238
- 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 +127 -11
- package/docs/configuration-and-manifests.md +150 -35
- 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 +45 -47
- package/docs/repository-governance.md +207 -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/telemetry.md +9 -3
- package/docs/troubleshooting.md +107 -49
- package/docs/workloads.md +53 -62
- package/package.json +6 -8
- 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 -173
- 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
|
@@ -0,0 +1,689 @@
|
|
|
1
|
+
import { NodeCommandRunner } from '../process-runner.js';
|
|
2
|
+
import { azureBinding, boolean, id, list, normalizeProtection, normalizeResource, normalizeRule, normalizeRuleset, record, sorted, text } from '../domain/governance/assessment/live-normalize.js';
|
|
3
|
+
import { LiveFailure, LiveTransport } from './live-transport.js';
|
|
4
|
+
import { isRecord, jsonValue, notObserved, observed, source } from '../domain/governance/assessment/sanitize.js';
|
|
5
|
+
import { assessmentLimits } from './types.js';
|
|
6
|
+
const families = [
|
|
7
|
+
'github.repository', 'github.actions-app', 'github.rulesets', 'github.branches', 'github.checks', 'github.environments',
|
|
8
|
+
'github.workflows', 'github.security', 'github.runner', 'azure.providers', 'azure.resources'
|
|
9
|
+
];
|
|
10
|
+
function branchName(value) {
|
|
11
|
+
let name = text(value);
|
|
12
|
+
if (name.startsWith('refs/heads/'))
|
|
13
|
+
name = name.slice('refs/heads/'.length);
|
|
14
|
+
if (!/^[A-Za-z0-9_][A-Za-z0-9_./-]{0,1023}$/u.test(name) ||
|
|
15
|
+
name.startsWith('refs/') || name.includes('..') || name.includes('//') ||
|
|
16
|
+
name.endsWith('/') || name.endsWith('.') ||
|
|
17
|
+
name.split('/').some((part) => part.startsWith('.') || part.endsWith('.lock'))) {
|
|
18
|
+
throw new LiveFailure('unsafe-ref', 'A requested ref was not a safe, exact branch name.');
|
|
19
|
+
}
|
|
20
|
+
return name;
|
|
21
|
+
}
|
|
22
|
+
function branchPrefix(value) {
|
|
23
|
+
const prefix = text(value);
|
|
24
|
+
if (prefix !== 'release/' && prefix !== 'hotfix/') {
|
|
25
|
+
throw new LiveFailure('unsafe-ref', 'Only release/ and hotfix/ branch families may be enumerated.');
|
|
26
|
+
}
|
|
27
|
+
return prefix;
|
|
28
|
+
}
|
|
29
|
+
function sha(value) {
|
|
30
|
+
const commit = text(value).toLowerCase();
|
|
31
|
+
if (!/^[a-f0-9]{40}(?:[a-f0-9]{24})?$/u.test(commit)) {
|
|
32
|
+
throw new LiveFailure('invalid-response', 'The provider did not supply a valid exact commit SHA.');
|
|
33
|
+
}
|
|
34
|
+
return commit;
|
|
35
|
+
}
|
|
36
|
+
function environmentName(value) {
|
|
37
|
+
const name = text(value);
|
|
38
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9 _.-]{0,254}$/u.test(name) || name.includes('..')) {
|
|
39
|
+
throw new LiveFailure('unsafe-environment', 'A deployment environment name was not safe for a scoped metadata read.');
|
|
40
|
+
}
|
|
41
|
+
return name;
|
|
42
|
+
}
|
|
43
|
+
function numeric(value) {
|
|
44
|
+
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0) {
|
|
45
|
+
throw new LiveFailure('invalid-response', 'Expected bounded numeric metadata was not available.');
|
|
46
|
+
}
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
function repositoryScope(value) {
|
|
50
|
+
if (!value)
|
|
51
|
+
throw new LiveFailure('repository-unbound', 'No repository binding was available; live discovery was not attempted.');
|
|
52
|
+
const owner = text(value.owner);
|
|
53
|
+
const name = text(value.name);
|
|
54
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9-]{0,38}$/u.test(owner) ||
|
|
55
|
+
!/^[A-Za-z0-9_.-]{1,100}$/u.test(name) || name === '.' || name === '..') {
|
|
56
|
+
throw new LiveFailure('unsafe-repository', 'The repository binding was not a safe GitHub owner and repository name.');
|
|
57
|
+
}
|
|
58
|
+
if (value.id !== null && (typeof value.id !== 'string' || !/^(?:[1-9]\d*|R_[A-Za-z0-9_-]{1,180})$/u.test(text(value.id)))) {
|
|
59
|
+
throw new LiveFailure('unsafe-repository', 'The expected repository identity was not a supported node ID or numeric ID.');
|
|
60
|
+
}
|
|
61
|
+
return { owner, name, id: value.id };
|
|
62
|
+
}
|
|
63
|
+
function runnerScope(value, repository) {
|
|
64
|
+
if (!value || value.groupId === null || value.networkConfigurationId === null) {
|
|
65
|
+
throw new LiveFailure('runner-unbound', 'Exact existing runner, group and network bindings were not available; organization discovery was not attempted.');
|
|
66
|
+
}
|
|
67
|
+
const organization = text(value.organization);
|
|
68
|
+
const networkConfigurationId = text(value.networkConfigurationId);
|
|
69
|
+
if (organization.toLowerCase() !== repository.owner.toLowerCase() ||
|
|
70
|
+
!/^[A-Za-z0-9_-]{1,128}$/u.test(networkConfigurationId)) {
|
|
71
|
+
throw new LiveFailure('unsafe-runner-scope', 'The runner organization or network binding did not match the verified repository scope.');
|
|
72
|
+
}
|
|
73
|
+
return { organization, runnerId: id(value.runnerId), groupId: id(value.groupId), networkConfigurationId };
|
|
74
|
+
}
|
|
75
|
+
class Observations {
|
|
76
|
+
capturedAt;
|
|
77
|
+
values = {};
|
|
78
|
+
diagnostics = [];
|
|
79
|
+
constructor(capturedAt) {
|
|
80
|
+
this.capturedAt = capturedAt;
|
|
81
|
+
}
|
|
82
|
+
fail(key, error, location = null) {
|
|
83
|
+
const failure = error instanceof LiveFailure ? error
|
|
84
|
+
: new LiveFailure('invalid-response', 'Required live metadata could not be safely normalized; raw error details were withheld.');
|
|
85
|
+
this.values[key] = notObserved(failure.message, location === null ? null :
|
|
86
|
+
source(key.startsWith('azure.') ? 'azure' : 'github', location, this.capturedAt));
|
|
87
|
+
this.diagnostics.push({
|
|
88
|
+
code: `live-${failure.code}`, severity: 'warning', source: key, message: failure.message
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
put(key, value, location, revision = null) {
|
|
92
|
+
if (Buffer.byteLength(JSON.stringify(value)) > assessmentLimits.responseBytes) {
|
|
93
|
+
throw new LiveFailure('size-limit', 'Normalized observation metadata exceeded the byte limit.');
|
|
94
|
+
}
|
|
95
|
+
const from = source(key.startsWith('azure.') ? 'azure' : 'github', location, this.capturedAt, value, revision);
|
|
96
|
+
const result = observed(value, from);
|
|
97
|
+
if (result.availability !== 'observed') {
|
|
98
|
+
throw new LiveFailure('sensitive-response', 'The normalized observation contained sensitive data and was withheld.');
|
|
99
|
+
}
|
|
100
|
+
this.values[key] = result;
|
|
101
|
+
}
|
|
102
|
+
retainFacts(key, facts, location, revision = null) {
|
|
103
|
+
const unavailable = this.values[key];
|
|
104
|
+
if (unavailable?.availability !== 'not-observed')
|
|
105
|
+
return;
|
|
106
|
+
try {
|
|
107
|
+
this.put(key, facts, location, revision);
|
|
108
|
+
const normalized = this.values[key];
|
|
109
|
+
this.values[key] = { ...unavailable, facts: normalized.value, source: normalized.source };
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
this.fail(key, error, location);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
missing(key, reason, from) {
|
|
116
|
+
this.values[key] = { availability: 'missing', value: null, source: from, reason };
|
|
117
|
+
}
|
|
118
|
+
async capture(key, location, collect, revision = null) {
|
|
119
|
+
try {
|
|
120
|
+
const value = await collect();
|
|
121
|
+
this.put(key, value, location, revision);
|
|
122
|
+
return value;
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
this.fail(key, error, location);
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
finish(refsStable) {
|
|
130
|
+
return {
|
|
131
|
+
observations: Object.fromEntries(Object.entries(this.values).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)),
|
|
132
|
+
diagnostics: sorted(this.diagnostics),
|
|
133
|
+
refsStable
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function normalizeSecurity(value) {
|
|
138
|
+
const input = record(value);
|
|
139
|
+
const features = {};
|
|
140
|
+
for (const name of [
|
|
141
|
+
'advanced_security', 'code_security', 'secret_scanning', 'secret_scanning_push_protection',
|
|
142
|
+
'secret_scanning_validity_checks', 'secret_scanning_non_provider_patterns', 'secret_scanning_ai_detection'
|
|
143
|
+
]) {
|
|
144
|
+
if (!Object.hasOwn(input, name))
|
|
145
|
+
continue;
|
|
146
|
+
const status = text(record(input[name]).status);
|
|
147
|
+
if (status !== 'enabled' && status !== 'disabled') {
|
|
148
|
+
throw new LiveFailure('unsupported-response', 'An unrecognized repository security-feature status was returned.');
|
|
149
|
+
}
|
|
150
|
+
features[name] = { status };
|
|
151
|
+
}
|
|
152
|
+
if (!Object.keys(features).length) {
|
|
153
|
+
throw new LiveFailure('security-unavailable', 'Repository security-feature visibility was not granted by the response.');
|
|
154
|
+
}
|
|
155
|
+
return features;
|
|
156
|
+
}
|
|
157
|
+
function normalizeCheck(value, commit) {
|
|
158
|
+
const check = record(value);
|
|
159
|
+
const key = String(id(check.id));
|
|
160
|
+
if (sha(check.head_sha) !== commit) {
|
|
161
|
+
throw new LiveFailure('scope-mismatch', 'A check run did not match the exact requested commit SHA.');
|
|
162
|
+
}
|
|
163
|
+
const status = text(check.status);
|
|
164
|
+
if (!['queued', 'in_progress', 'completed', 'requested', 'waiting', 'pending'].includes(status)) {
|
|
165
|
+
throw new LiveFailure('unsupported-response', 'The check-run status was not understood by this collector.');
|
|
166
|
+
}
|
|
167
|
+
const conclusion = check.conclusion === null ? null : text(check.conclusion);
|
|
168
|
+
if (conclusion !== null && ![
|
|
169
|
+
'success', 'failure', 'neutral', 'cancelled', 'skipped', 'timed_out', 'action_required', 'startup_failure', 'stale'
|
|
170
|
+
].includes(conclusion)) {
|
|
171
|
+
throw new LiveFailure('unsupported-response', 'The check-run conclusion was not understood by this collector.');
|
|
172
|
+
}
|
|
173
|
+
const app = check.app === null ? null : record(check.app);
|
|
174
|
+
const appSlug = app?.slug === undefined || app.slug === null ? null : text(app.slug);
|
|
175
|
+
return {
|
|
176
|
+
key,
|
|
177
|
+
value: {
|
|
178
|
+
name: text(check.name), appId: app === null ? null : id(app.id),
|
|
179
|
+
...(appSlug === null ? {} : { appSlug }), status, conclusion
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function normalizeEnvironment(value, selected) {
|
|
184
|
+
const input = record(value);
|
|
185
|
+
const actualName = environmentName(input.name);
|
|
186
|
+
const name = selected.find((entry) => entry.toLowerCase() === actualName.toLowerCase());
|
|
187
|
+
if (name === undefined) {
|
|
188
|
+
return { key: actualName.toLowerCase(), value: { name: actualName, reviewers: null, deploymentBranchPolicy: null } };
|
|
189
|
+
}
|
|
190
|
+
const protections = list(input.protection_rules).map(record);
|
|
191
|
+
if (protections.some((rule) => !['required_reviewers', 'wait_timer', 'branch_policy'].includes(text(rule.type)))) {
|
|
192
|
+
throw new LiveFailure('unsupported-response', 'An unrecognized environment protection rule prevents complete reviewer observation.');
|
|
193
|
+
}
|
|
194
|
+
const reviewerRules = protections.filter((rule) => rule.type === 'required_reviewers');
|
|
195
|
+
if (reviewerRules.length > 1)
|
|
196
|
+
throw new LiveFailure('invalid-response', 'Environment reviewer metadata was ambiguous.');
|
|
197
|
+
const reviewers = reviewerRules.length === 0 ? 0 : list(reviewerRules[0].reviewers).map((entry) => {
|
|
198
|
+
const reviewer = record(entry);
|
|
199
|
+
if (!['User', 'Team'].includes(text(reviewer.type))) {
|
|
200
|
+
throw new LiveFailure('unsupported-response', 'An unrecognized environment reviewer type was returned.');
|
|
201
|
+
}
|
|
202
|
+
return id(record(reviewer.reviewer).id);
|
|
203
|
+
}).length;
|
|
204
|
+
let deploymentBranchPolicy = null;
|
|
205
|
+
if (input.deployment_branch_policy !== null) {
|
|
206
|
+
const policy = record(input.deployment_branch_policy);
|
|
207
|
+
deploymentBranchPolicy = {
|
|
208
|
+
protected_branches: boolean(policy.protected_branches),
|
|
209
|
+
custom_branch_policies: boolean(policy.custom_branch_policies)
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
return { key: name.toLowerCase(), value: { name, reviewers, deploymentBranchPolicy } };
|
|
213
|
+
}
|
|
214
|
+
export async function collectLiveAssessment(scope, options = {}) {
|
|
215
|
+
const now = options.now ?? (() => new Date());
|
|
216
|
+
const results = new Observations(now().toISOString());
|
|
217
|
+
let repository;
|
|
218
|
+
try {
|
|
219
|
+
repository = repositoryScope(scope.repository);
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
for (const family of families)
|
|
223
|
+
results.fail(family, error);
|
|
224
|
+
return results.finish(scope.repository === null && scope.refs.length === 0);
|
|
225
|
+
}
|
|
226
|
+
let refs = [];
|
|
227
|
+
let refPrefixes = [];
|
|
228
|
+
let environments = [];
|
|
229
|
+
let runner = null;
|
|
230
|
+
let refsValid = true;
|
|
231
|
+
let environmentsValid = true;
|
|
232
|
+
let azureScopeValid = true;
|
|
233
|
+
try {
|
|
234
|
+
refs = [...new Set(list(scope.refs).map(branchName))].sort();
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
refsValid = false;
|
|
238
|
+
results.fail('github.branches', error);
|
|
239
|
+
results.fail('github.checks', error);
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
refPrefixes = [...new Set(list(scope.refPrefixes ?? []).map(branchPrefix))].sort();
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
refsValid = false;
|
|
246
|
+
results.fail('github.ref-families', error);
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
environments = [...new Map(list(scope.environments).map(environmentName).sort()
|
|
250
|
+
.map((name) => [name.toLowerCase(), name])).values()];
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
environmentsValid = false;
|
|
254
|
+
results.fail('github.environments', error);
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
runner = runnerScope(scope.runner, repository);
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
results.fail('github.runner', error);
|
|
261
|
+
}
|
|
262
|
+
const bindings = new Map();
|
|
263
|
+
const conflictingBindings = new Set();
|
|
264
|
+
try {
|
|
265
|
+
for (const input of list(scope.azure)) {
|
|
266
|
+
try {
|
|
267
|
+
const bound = azureBinding(record(input), environments);
|
|
268
|
+
const key = bound.resourceId.toLowerCase();
|
|
269
|
+
const previous = bindings.get(key);
|
|
270
|
+
if (conflictingBindings.has(key) || (previous && (previous.environment !== bound.environment || previous.role !== bound.role))) {
|
|
271
|
+
bindings.delete(key);
|
|
272
|
+
conflictingBindings.add(key);
|
|
273
|
+
throw new LiveFailure('unsafe-azure-scope', 'The same ARM resource had conflicting environment or role bindings.');
|
|
274
|
+
}
|
|
275
|
+
if (!previous || JSON.stringify(bound) < JSON.stringify(previous))
|
|
276
|
+
bindings.set(key, bound);
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
azureScopeValid = false;
|
|
280
|
+
results.fail('azure.resources', error);
|
|
281
|
+
results.fail('azure.providers', error);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
azureScopeValid = false;
|
|
287
|
+
results.fail('azure.resources', error);
|
|
288
|
+
results.fail('azure.providers', error);
|
|
289
|
+
}
|
|
290
|
+
const azure = [...bindings.values()].sort((a, b) => a.resourceId < b.resourceId ? -1 : a.resourceId > b.resourceId ? 1 : 0);
|
|
291
|
+
const providerScopes = [...new Map(azure.flatMap((binding) => {
|
|
292
|
+
const namespaces = binding.resourceType === 'GitHub.Network/networkSettings'
|
|
293
|
+
? [binding.namespace, 'Microsoft.Network'] : [binding.namespace];
|
|
294
|
+
return namespaces.map((namespace) => [
|
|
295
|
+
`${binding.subscriptionId.toLowerCase()}/${namespace}`,
|
|
296
|
+
{
|
|
297
|
+
subscriptionId: binding.subscriptionId, namespace,
|
|
298
|
+
providerUrl: `https://management.azure.com/subscriptions/${binding.subscriptionId}/providers/${namespace}?api-version=2021-04-01`
|
|
299
|
+
}
|
|
300
|
+
]);
|
|
301
|
+
})).values()];
|
|
302
|
+
const validatedScope = {
|
|
303
|
+
repository,
|
|
304
|
+
refs,
|
|
305
|
+
...(refPrefixes.length ? { refPrefixes } : {}),
|
|
306
|
+
environments,
|
|
307
|
+
runner,
|
|
308
|
+
azure
|
|
309
|
+
};
|
|
310
|
+
const transport = new LiveTransport(options.runner ?? new NodeCommandRunner(), now, validatedScope, new Set([...azure.map((binding) => binding.url), ...providerScopes.map((binding) => binding.providerUrl)]), (diagnostic) => results.diagnostics.push(diagnostic));
|
|
311
|
+
const repositoryUrl = transport.githubUrl('repository').href;
|
|
312
|
+
let repositoryData;
|
|
313
|
+
const repositoryValue = await results.capture('github.repository', repositoryUrl, async () => {
|
|
314
|
+
const input = record(await transport.github('repository'));
|
|
315
|
+
const numericId = id(input.id);
|
|
316
|
+
const nodeId = text(input.node_id);
|
|
317
|
+
const fullName = text(input.full_name);
|
|
318
|
+
if (fullName.toLowerCase() !== `${repository.owner}/${repository.name}`.toLowerCase() ||
|
|
319
|
+
(repository.id !== null && (repository.id.startsWith('R_') ? nodeId !== repository.id : String(numericId) !== repository.id))) {
|
|
320
|
+
throw new LiveFailure('repository-identity', 'The resolved GitHub repository did not match the expected full name and identity.');
|
|
321
|
+
}
|
|
322
|
+
const value = { id: numericId, nodeId, fullName, defaultBranch: branchName(input.default_branch) };
|
|
323
|
+
repositoryData = input;
|
|
324
|
+
return value;
|
|
325
|
+
});
|
|
326
|
+
if (!repositoryValue || !repositoryData) {
|
|
327
|
+
for (const family of families.filter((key) => key !== 'github.repository')) {
|
|
328
|
+
results.fail(family, new LiveFailure('unverified-scope', 'Repository identity was not verified; dependent live reads were withheld.'));
|
|
329
|
+
}
|
|
330
|
+
return results.finish(false);
|
|
331
|
+
}
|
|
332
|
+
transport.verifyRepository();
|
|
333
|
+
try {
|
|
334
|
+
results.put('github.security', normalizeSecurity(repositoryData.security_and_analysis), repositoryUrl);
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
results.fail('github.security', error, repositoryUrl);
|
|
338
|
+
}
|
|
339
|
+
repositoryData = undefined;
|
|
340
|
+
const heads = new Map();
|
|
341
|
+
let refsStable = refsValid;
|
|
342
|
+
const base = `https://api.github.com/repos/${repository.owner}/${repository.name}`;
|
|
343
|
+
if (refPrefixes.length) {
|
|
344
|
+
try {
|
|
345
|
+
const branchInventory = await transport.pages('branches-list', null, (value) => {
|
|
346
|
+
const name = branchName(record(value).name);
|
|
347
|
+
return { key: name, value: name };
|
|
348
|
+
});
|
|
349
|
+
const familyRefs = branchInventory.filter((name) => refPrefixes.some((prefix) => name.startsWith(prefix))).sort();
|
|
350
|
+
refs.push(...familyRefs.filter((name) => !refs.includes(name)));
|
|
351
|
+
refs.sort();
|
|
352
|
+
results.put('github.ref-families', {
|
|
353
|
+
prefixes: refPrefixes,
|
|
354
|
+
refs: familyRefs,
|
|
355
|
+
complete: true
|
|
356
|
+
}, `${base}/branches`);
|
|
357
|
+
}
|
|
358
|
+
catch (error) {
|
|
359
|
+
refsStable = false;
|
|
360
|
+
results.fail('github.ref-families', error, `${base}/branches`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
const collectActionsApp = async () => results.capture('github.actions-app', transport.githubUrl('actions-app').href, async () => {
|
|
364
|
+
const app = record(await transport.github('actions-app'));
|
|
365
|
+
const slug = text(app.slug);
|
|
366
|
+
if (slug !== 'github-actions') {
|
|
367
|
+
throw new LiveFailure('scope-mismatch', 'The public app response did not identify the requested GitHub Actions application.');
|
|
368
|
+
}
|
|
369
|
+
return { id: id(app.id), slug };
|
|
370
|
+
});
|
|
371
|
+
const collectRulesets = async () => results.capture('github.rulesets', `${base}/rulesets`, async () => {
|
|
372
|
+
const inventory = await transport.pages('rulesets', null, (value) => {
|
|
373
|
+
const input = record(value);
|
|
374
|
+
const numericId = id(input.id);
|
|
375
|
+
return {
|
|
376
|
+
key: String(numericId),
|
|
377
|
+
value: {
|
|
378
|
+
id: numericId,
|
|
379
|
+
...(Object.hasOwn(input, 'source_type') ? { source_type: text(input.source_type) } : {}),
|
|
380
|
+
...(Object.hasOwn(input, 'source') ? { source: text(input.source) } : {})
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
});
|
|
384
|
+
const rulesets = [];
|
|
385
|
+
let size = 0;
|
|
386
|
+
for (const summary of inventory.sort((a, b) => a.id - b.id)) {
|
|
387
|
+
const numericId = summary.id;
|
|
388
|
+
const details = { ...record(await transport.github('ruleset', numericId)) };
|
|
389
|
+
for (const field of ['source_type', 'source']) {
|
|
390
|
+
if (Object.hasOwn(summary, field) && Object.hasOwn(details, field) &&
|
|
391
|
+
text(summary[field]).toLowerCase() !== text(details[field]).toLowerCase()) {
|
|
392
|
+
throw new LiveFailure('scope-mismatch', 'Ruleset source identity disagreed between inventory and detail reads.');
|
|
393
|
+
}
|
|
394
|
+
if (!Object.hasOwn(details, field) && Object.hasOwn(summary, field))
|
|
395
|
+
details[field] = summary[field];
|
|
396
|
+
}
|
|
397
|
+
const ruleset = record(normalizeRuleset(details));
|
|
398
|
+
if (ruleset.id !== numericId ||
|
|
399
|
+
!['Repository', 'Organization', 'Enterprise'].includes(text(ruleset.source_type)) ||
|
|
400
|
+
(ruleset.source_type === 'Repository' &&
|
|
401
|
+
text(ruleset.source).toLowerCase() !== repositoryValue.fullName.toLowerCase()) ||
|
|
402
|
+
(ruleset.source_type === 'Organization' &&
|
|
403
|
+
text(ruleset.source).toLowerCase() !== repository.owner.toLowerCase())) {
|
|
404
|
+
throw new LiveFailure('scope-mismatch', 'Ruleset details did not match the requested repository and ruleset identity.');
|
|
405
|
+
}
|
|
406
|
+
const value = jsonValue(ruleset);
|
|
407
|
+
size += Buffer.byteLength(JSON.stringify(value));
|
|
408
|
+
if (size > assessmentLimits.responseBytes)
|
|
409
|
+
throw new LiveFailure('size-limit', 'Normalized ruleset metadata exceeded the byte limit.');
|
|
410
|
+
rulesets.push(value);
|
|
411
|
+
}
|
|
412
|
+
return sorted(rulesets);
|
|
413
|
+
});
|
|
414
|
+
const collectBranches = async () => {
|
|
415
|
+
if (!refsValid) {
|
|
416
|
+
refsStable = false;
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
if (!refs.length) {
|
|
420
|
+
const error = new LiveFailure('refs-unbound', 'No exact branch refs were supplied; branch and check discovery was not attempted.');
|
|
421
|
+
results.fail('github.branches', error);
|
|
422
|
+
results.fail('github.checks', error);
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
const branches = [];
|
|
426
|
+
let completeBranches = 0;
|
|
427
|
+
const checks = [];
|
|
428
|
+
for (const ref of refs) {
|
|
429
|
+
const branchKey = `github.branch.${ref}`;
|
|
430
|
+
const checkKey = `github.checks.${ref}`;
|
|
431
|
+
const branchUrl = transport.githubUrl('branch', ref).href;
|
|
432
|
+
let branch;
|
|
433
|
+
try {
|
|
434
|
+
const input = record(await transport.github('branch', ref));
|
|
435
|
+
if (text(input.name) !== ref)
|
|
436
|
+
throw new LiveFailure('scope-mismatch', 'Branch metadata did not match the exact requested ref.');
|
|
437
|
+
branch = { name: ref, sha: sha(record(input.commit).sha), protected: boolean(input.protected) };
|
|
438
|
+
heads.set(ref, { sha: branch.sha, protected: branch.protected });
|
|
439
|
+
transport.bindSha(branch.sha);
|
|
440
|
+
}
|
|
441
|
+
catch (error) {
|
|
442
|
+
results.fail(branchKey, error, branchUrl);
|
|
443
|
+
results.fail(checkKey, new LiveFailure('unverified-ref', 'The branch SHA could not be verified; check reads were withheld.'));
|
|
444
|
+
refsStable = false;
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
const [protection, runs] = await Promise.all([
|
|
448
|
+
results.capture(branchKey, branchUrl, async () => {
|
|
449
|
+
const effectiveRules = sorted(await transport.pages('branch-rules', null, (value) => {
|
|
450
|
+
const rule = normalizeRule(value);
|
|
451
|
+
return { key: JSON.stringify(rule), value: rule };
|
|
452
|
+
}, ref));
|
|
453
|
+
const classic = branch.protected ? normalizeProtection(await transport.github('protection', ref)) : null;
|
|
454
|
+
if (!branch.protected && effectiveRules.length) {
|
|
455
|
+
throw new LiveFailure('inconsistent-response', 'Branch protection metadata changed or contradicted the effective rules.');
|
|
456
|
+
}
|
|
457
|
+
return {
|
|
458
|
+
...branch, protection: branch.protected ? { classic, effectiveRules } : null, protectionObserved: true
|
|
459
|
+
};
|
|
460
|
+
}, branch.sha),
|
|
461
|
+
results.capture(checkKey, transport.githubUrl('checks', branch.sha).href, async () => ({
|
|
462
|
+
ref, name: ref, sha: branch.sha,
|
|
463
|
+
checks: sorted(await transport.pages('checks', 'check_runs', (value) => normalizeCheck(value, branch.sha), branch.sha))
|
|
464
|
+
}), branch.sha)
|
|
465
|
+
]);
|
|
466
|
+
if (protection !== undefined) {
|
|
467
|
+
branches.push(protection);
|
|
468
|
+
completeBranches += 1;
|
|
469
|
+
}
|
|
470
|
+
else {
|
|
471
|
+
const facts = { ...branch, protection: null, protectionObserved: false };
|
|
472
|
+
branches.push(facts);
|
|
473
|
+
results.retainFacts(branchKey, facts, branchUrl, branch.sha);
|
|
474
|
+
}
|
|
475
|
+
if (runs !== undefined)
|
|
476
|
+
checks.push(runs);
|
|
477
|
+
}
|
|
478
|
+
if (completeBranches === refs.length) {
|
|
479
|
+
try {
|
|
480
|
+
results.put('github.branches', sorted(branches), `${base}/branches`);
|
|
481
|
+
}
|
|
482
|
+
catch (error) {
|
|
483
|
+
results.fail('github.branches', error);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
results.fail('github.branches', new LiveFailure('incomplete-branches', 'One or more requested branches lacked complete protection metadata.'));
|
|
488
|
+
if (branches.length)
|
|
489
|
+
results.retainFacts('github.branches', sorted(branches), `${base}/branches`);
|
|
490
|
+
}
|
|
491
|
+
if (checks.length === refs.length) {
|
|
492
|
+
try {
|
|
493
|
+
results.put('github.checks', sorted(checks), `${base}/commits`);
|
|
494
|
+
}
|
|
495
|
+
catch (error) {
|
|
496
|
+
results.fail('github.checks', error);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
else
|
|
500
|
+
results.fail('github.checks', new LiveFailure('incomplete-checks', 'One or more requested refs lacked complete SHA-bound check metadata.'));
|
|
501
|
+
};
|
|
502
|
+
const collectEnvironments = async () => {
|
|
503
|
+
if (!environmentsValid)
|
|
504
|
+
return;
|
|
505
|
+
if (!environments.length) {
|
|
506
|
+
results.fail('github.environments', new LiveFailure('environments-unbound', 'No deployment environment scope was supplied.'));
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
await results.capture('github.environments', `${base}/environments`, async () => {
|
|
510
|
+
const inventory = await transport.pages('environments', 'environments', (value) => normalizeEnvironment(value, environments));
|
|
511
|
+
const selected = sorted(inventory.filter((entry) => environments.includes(entry.name)));
|
|
512
|
+
for (const entry of selected) {
|
|
513
|
+
if (isRecord(entry.deploymentBranchPolicy) && entry.deploymentBranchPolicy.custom_branch_policies === true) {
|
|
514
|
+
const policies = await transport.pages('environment-policies', 'branch_policies', (value) => {
|
|
515
|
+
const policy = record(value);
|
|
516
|
+
const numericId = id(policy.id);
|
|
517
|
+
const type = text(policy.type);
|
|
518
|
+
if (type !== 'branch' && type !== 'tag')
|
|
519
|
+
throw new LiveFailure('unsupported-response', 'An unknown deployment policy type was returned.');
|
|
520
|
+
return { key: String(numericId), value: { id: numericId, name: text(policy.name), type } };
|
|
521
|
+
}, entry.name);
|
|
522
|
+
entry.deploymentBranchPolicy = jsonValue({ ...entry.deploymentBranchPolicy, branchPolicies: sorted(policies) });
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
for (const name of environments) {
|
|
526
|
+
const entry = selected.find((value) => value.name === name);
|
|
527
|
+
if (entry)
|
|
528
|
+
results.put(`github.environment.${name}`, entry, `${base}/environments`);
|
|
529
|
+
else
|
|
530
|
+
results.missing(`github.environment.${name}`, 'The complete repository environment inventory did not contain the scoped environment.', source('github', `${base}/environments`, results.capturedAt, selected));
|
|
531
|
+
}
|
|
532
|
+
return sorted(selected);
|
|
533
|
+
});
|
|
534
|
+
};
|
|
535
|
+
const collectWorkflows = async () => results.capture('github.workflows', `${base}/actions/workflows`, async () => sorted(await transport.pages('workflows', 'workflows', (value) => {
|
|
536
|
+
const workflow = record(value);
|
|
537
|
+
const numericId = id(workflow.id);
|
|
538
|
+
return {
|
|
539
|
+
key: String(numericId),
|
|
540
|
+
value: { id: numericId, name: text(workflow.name), path: text(workflow.path), state: text(workflow.state) }
|
|
541
|
+
};
|
|
542
|
+
})));
|
|
543
|
+
const collectRunner = async () => {
|
|
544
|
+
if (!runner)
|
|
545
|
+
return;
|
|
546
|
+
const bound = runner;
|
|
547
|
+
const location = transport.githubUrl('runner').href;
|
|
548
|
+
await results.capture('github.runner', location, async () => {
|
|
549
|
+
const rawRunner = record(await transport.github('runner'));
|
|
550
|
+
if (id(rawRunner.id) !== bound.runnerId || id(rawRunner.runner_group_id) !== bound.groupId) {
|
|
551
|
+
throw new LiveFailure('scope-mismatch', 'The hosted runner did not match the exact bound runner and group IDs.');
|
|
552
|
+
}
|
|
553
|
+
const group = record(await transport.github('runner-group'));
|
|
554
|
+
if (id(group.id) !== bound.groupId || text(group.network_configuration_id) !== bound.networkConfigurationId) {
|
|
555
|
+
throw new LiveFailure('scope-mismatch', 'The runner group did not match the exact bound group and network IDs.');
|
|
556
|
+
}
|
|
557
|
+
const network = record(await transport.github('runner-network'));
|
|
558
|
+
if (text(network.id) !== bound.networkConfigurationId) {
|
|
559
|
+
throw new LiveFailure('scope-mismatch', 'Network metadata did not match its existing bound identity.');
|
|
560
|
+
}
|
|
561
|
+
// GitHub's assignment read is filtered to this repository, never an all-org inventory.
|
|
562
|
+
const assignedGroups = await transport.pages('runner-assignment', 'runner_groups', (value) => {
|
|
563
|
+
const group = record(value);
|
|
564
|
+
const numericId = id(group.id);
|
|
565
|
+
if (numericId === bound.groupId && group.network_configuration_id !== undefined &&
|
|
566
|
+
text(group.network_configuration_id) !== bound.networkConfigurationId) {
|
|
567
|
+
throw new LiveFailure('scope-mismatch', 'The repository assignment changed its network configuration during observation.');
|
|
568
|
+
}
|
|
569
|
+
return { key: String(numericId), value: numericId };
|
|
570
|
+
});
|
|
571
|
+
const size = rawRunner.machine_size_details === undefined || rawRunner.machine_size_details === null
|
|
572
|
+
? null : record(rawRunner.machine_size_details);
|
|
573
|
+
return {
|
|
574
|
+
organization: repository.owner, repository: repositoryValue.fullName,
|
|
575
|
+
runnerId: bound.runnerId, groupId: bound.groupId, networkConfigurationId: bound.networkConfigurationId,
|
|
576
|
+
repositoryAssigned: assignedGroups.includes(bound.groupId),
|
|
577
|
+
runner: {
|
|
578
|
+
id: bound.runnerId, name: text(rawRunner.name), status: text(rawRunner.status),
|
|
579
|
+
runnerGroupId: bound.groupId, networkConfigurationId: bound.networkConfigurationId,
|
|
580
|
+
labels: rawRunner.labels === undefined ? null
|
|
581
|
+
: sorted(list(rawRunner.labels).map((entry) => text(typeof entry === 'string' ? entry : record(entry).name))),
|
|
582
|
+
maximumRunners: rawRunner.maximum_runners === undefined ? null : numeric(rawRunner.maximum_runners),
|
|
583
|
+
publicIpEnabled: rawRunner.public_ip_enabled === undefined ? null : boolean(rawRunner.public_ip_enabled),
|
|
584
|
+
machineSize: size === null ? null : {
|
|
585
|
+
id: text(size.id), cpuCores: numeric(size.cpu_cores), memoryGb: numeric(size.memory_gb), storageGb: numeric(size.storage_gb)
|
|
586
|
+
}
|
|
587
|
+
},
|
|
588
|
+
group: {
|
|
589
|
+
id: bound.groupId, name: text(group.name), visibility: text(group.visibility),
|
|
590
|
+
networkConfigurationId: bound.networkConfigurationId,
|
|
591
|
+
allowsPublicRepositories: boolean(group.allows_public_repositories),
|
|
592
|
+
restrictedToWorkflows: boolean(group.restricted_to_workflows),
|
|
593
|
+
selectedWorkflows: sorted(list(group.selected_workflows).map(text)),
|
|
594
|
+
inherited: group.inherited === undefined ? null : boolean(group.inherited)
|
|
595
|
+
},
|
|
596
|
+
network: {
|
|
597
|
+
id: bound.networkConfigurationId, name: text(network.name), computeService: text(network.compute_service),
|
|
598
|
+
networkSettingsIds: sorted(list(network.network_settings_ids).map(text)),
|
|
599
|
+
failoverNetworkSettingsIds: network.failover_network_settings_ids === undefined ? null
|
|
600
|
+
: sorted(list(network.failover_network_settings_ids).map(text)),
|
|
601
|
+
failoverNetworkEnabled: network.failover_network_enabled === undefined ? null : boolean(network.failover_network_enabled)
|
|
602
|
+
}
|
|
603
|
+
};
|
|
604
|
+
});
|
|
605
|
+
};
|
|
606
|
+
const collectAzure = async () => {
|
|
607
|
+
if (!azure.length) {
|
|
608
|
+
if (azureScopeValid) {
|
|
609
|
+
const error = new LiveFailure('azure-unbound', 'No explicit subscription, environment and resource bindings were available; Azure discovery was not attempted.');
|
|
610
|
+
results.fail('azure.providers', error);
|
|
611
|
+
results.fail('azure.resources', error);
|
|
612
|
+
}
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
const providers = [];
|
|
616
|
+
for (const binding of providerScopes) {
|
|
617
|
+
const value = await results.capture(`azure.provider.${binding.subscriptionId}.${binding.namespace}`, binding.providerUrl, async () => {
|
|
618
|
+
const provider = record(await transport.azure(binding.providerUrl));
|
|
619
|
+
if (text(provider.namespace).toLowerCase() !== binding.namespace.toLowerCase() ||
|
|
620
|
+
(provider.id !== undefined && text(provider.id).toLowerCase() !==
|
|
621
|
+
`/subscriptions/${binding.subscriptionId}/providers/${binding.namespace}`.toLowerCase())) {
|
|
622
|
+
throw new LiveFailure('scope-mismatch', 'Provider metadata did not match the explicitly scoped subscription and namespace.');
|
|
623
|
+
}
|
|
624
|
+
return {
|
|
625
|
+
subscriptionId: binding.subscriptionId, namespace: binding.namespace, registrationState: text(provider.registrationState)
|
|
626
|
+
};
|
|
627
|
+
});
|
|
628
|
+
if (value !== undefined)
|
|
629
|
+
providers.push(value);
|
|
630
|
+
}
|
|
631
|
+
const resources = [];
|
|
632
|
+
for (const binding of azure) {
|
|
633
|
+
const value = await results.capture(`azure.resource.${binding.environment}.${binding.resourceId}`, binding.url, async () => normalizeResource(await transport.azure(binding.url), binding));
|
|
634
|
+
if (value !== undefined)
|
|
635
|
+
resources.push(value);
|
|
636
|
+
}
|
|
637
|
+
if (azureScopeValid && providers.length === providerScopes.length) {
|
|
638
|
+
try {
|
|
639
|
+
results.put('azure.providers', sorted(providers), 'https://management.azure.com (explicit subscription/provider bindings)');
|
|
640
|
+
}
|
|
641
|
+
catch (error) {
|
|
642
|
+
results.fail('azure.providers', error);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
else {
|
|
646
|
+
results.fail('azure.providers', new LiveFailure('incomplete-providers', 'Not every explicitly scoped provider could be observed.'));
|
|
647
|
+
if (providers.length) {
|
|
648
|
+
results.retainFacts('azure.providers', sorted(providers), 'https://management.azure.com (partial explicit subscription/provider bindings)');
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
if (azureScopeValid && resources.length === azure.length) {
|
|
652
|
+
try {
|
|
653
|
+
results.put('azure.resources', sorted(resources), 'https://management.azure.com (explicit environment/resource bindings)');
|
|
654
|
+
}
|
|
655
|
+
catch (error) {
|
|
656
|
+
results.fail('azure.resources', error);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
else {
|
|
660
|
+
results.fail('azure.resources', new LiveFailure('incomplete-resources', 'Not every explicitly scoped resource could be observed.'));
|
|
661
|
+
if (resources.length) {
|
|
662
|
+
results.retainFacts('azure.resources', sorted(resources), 'https://management.azure.com (partial explicit environment/resource bindings)');
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
await Promise.all([
|
|
667
|
+
collectActionsApp(), collectRulesets(), collectBranches(), collectEnvironments(), collectWorkflows(), collectRunner(), collectAzure()
|
|
668
|
+
]);
|
|
669
|
+
for (const [ref, original] of heads) {
|
|
670
|
+
try {
|
|
671
|
+
const current = record(await transport.github('branch', ref));
|
|
672
|
+
if (text(current.name) !== ref || sha(record(current.commit).sha) !== original.sha) {
|
|
673
|
+
throw new LiveFailure('ref-moved', 'A scoped branch moved during live collection; its branch and check observations were withheld.');
|
|
674
|
+
}
|
|
675
|
+
if (boolean(current.protected) !== original.protected) {
|
|
676
|
+
throw new LiveFailure('branch-changed', 'Scoped branch protection metadata changed during live collection; its snapshot was withheld.');
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
catch (error) {
|
|
680
|
+
refsStable = false;
|
|
681
|
+
results.fail(`github.branch.${ref}`, error, transport.githubUrl('branch', ref).href);
|
|
682
|
+
results.fail(`github.checks.${ref}`, error);
|
|
683
|
+
results.fail('github.branches', new LiveFailure('unstable-refs', 'Requested refs could not be verified as stable across live collection.'));
|
|
684
|
+
results.fail('github.checks', new LiveFailure('unstable-refs', 'Commit-bound check proof was withheld because ref stability was not established.'));
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
return results.finish(refsStable);
|
|
688
|
+
}
|
|
689
|
+
//# sourceMappingURL=live.js.map
|