@empire-builder-kit/nx 1.0.0-rc.37 → 1.0.0-rc.39
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/README.md +18 -0
- package/executors.json +5 -0
- package/generators.json +10 -0
- package/package.json +20 -3
- package/src/aws-authority/index.d.ts +1 -0
- package/src/aws-authority/index.js +1 -0
- package/src/aws-authority/lambda-policy-ordering.d.ts +38 -0
- package/src/aws-authority/lambda-policy-ordering.js +56 -0
- package/src/aws-authority/stage-authority.d.ts +11 -3
- package/src/aws-authority/stage-authority.js +615 -29
- package/src/blueprints/external-sandbox.js +21 -9
- package/src/blueprints/manifest.d.ts +1 -1
- package/src/blueprints/resolver.js +28 -15
- package/src/cli/bootstrap.d.ts +1 -1
- package/src/cli/deploy-runtime.d.ts +6 -0
- package/src/cli/deploy-runtime.js +58 -0
- package/src/cli/dev-command.d.ts +16 -4
- package/src/cli/dev-command.js +63 -0
- package/src/cli/main.d.ts +7 -1
- package/src/cli/main.js +128 -20
- package/src/cli/output.d.ts +1 -1
- package/src/developer-agent/context.js +41 -9
- package/src/developer-agent/generator-planning.js +16 -2
- package/src/developer-agent/git-inspection.d.ts +6 -2
- package/src/developer-agent/git-inspection.js +78 -6
- package/src/developer-agent/model.d.ts +4 -2
- package/src/developer-agent/operation-registry.d.ts +5 -0
- package/src/developer-agent/operation-registry.js +179 -23
- package/src/developer-agent/preview-changes.d.ts +2 -0
- package/src/developer-agent/preview-changes.js +14 -2
- package/src/developer-agent/preview-source.js +3 -0
- package/src/developer-agent/validation.js +20 -8
- package/src/developer-agent/workspace-inspection.js +37 -3
- package/src/executors/deployment-plan/deployment-plan.d.ts +2 -0
- package/src/executors/deployment-plan/deployment-plan.js +51 -4
- package/src/executors/dev-doctor/dev-doctor.js +13 -6
- package/src/executors/dev-task-cleanup/dev-task-cleanup.d.ts +23 -0
- package/src/executors/dev-task-cleanup/dev-task-cleanup.js +145 -0
- package/src/executors/dev-task-cleanup/schema.json +9 -0
- package/src/executors/dev-task-cleanup/task-stack-absence.d.ts +27 -0
- package/src/executors/dev-task-cleanup/task-stack-absence.js +281 -0
- package/src/executors/dev-task-cleanup/task-stack-checkpoint.d.ts +12 -0
- package/src/executors/dev-task-cleanup/task-stack-checkpoint.js +92 -0
- package/src/executors/fleet/fleet.js +1 -1
- package/src/executors/foundation-remove-preflight/foundation-remove-preflight.js +28 -1
- package/src/executors/local-deploy/local-deploy.d.ts +8 -1
- package/src/executors/local-deploy/local-deploy.js +97 -24
- package/src/executors/local-deploy/schema.json +8 -0
- package/src/executors/router-waf-rehearsal/router-waf-rehearsal.js +30 -18
- package/src/executors/sst-lifecycle/governed-native-operation.d.ts +2 -0
- package/src/executors/sst-lifecycle/governed-native-operation.js +9 -0
- package/src/executors/sst-lifecycle/run-sst-command.d.ts +5 -0
- package/src/executors/sst-lifecycle/run-sst-command.js +220 -32
- package/src/executors/sst-lifecycle/sst-environment-source.d.ts +8 -0
- package/src/executors/sst-lifecycle/sst-environment-source.js +54 -0
- package/src/executors/sst-lifecycle/task-unlock.d.ts +15 -0
- package/src/executors/sst-lifecycle/task-unlock.js +126 -0
- package/src/foundation/capability-plan.d.ts +43 -0
- package/src/foundation/capability-plan.js +168 -0
- package/src/foundation/discovery.d.ts +14 -11
- package/src/foundation/discovery.js +32 -6
- package/src/foundation/index.d.ts +1 -0
- package/src/foundation/index.js +1 -0
- package/src/foundation/local-database-contract.d.ts +20 -0
- package/src/foundation/local-database-contract.js +262 -13
- package/src/foundation/local-private-smoke-access.d.ts +20 -0
- package/src/foundation/local-private-smoke-access.js +197 -0
- package/src/foundation/preflight.js +37 -18
- package/src/foundation/private-smoke-access.js +10 -2
- package/src/foundation/private-smoke-admission.d.ts +3 -1
- package/src/foundation/private-smoke-admission.js +29 -8
- package/src/foundation/private-smoke-control-plane.js +17 -6
- package/src/foundation/provision-database-bindings.d.ts +5 -0
- package/src/foundation/provision-database-bindings.js +41 -8
- package/src/foundation/provision-logical-database.js +13 -8
- package/src/foundation/requirements.d.ts +3 -3
- package/src/foundation/requirements.js +24 -12
- package/src/foundation/router-waf.d.ts +1 -0
- package/src/foundation/router-waf.js +14 -1
- package/src/generators/blueprint/blueprint.d.ts +5 -0
- package/src/generators/blueprint/blueprint.js +102 -0
- package/src/generators/blueprint/files.d.ts +6 -0
- package/src/generators/blueprint/files.js +217 -0
- package/src/generators/blueprint/schema.d.ts +4 -0
- package/src/generators/blueprint/schema.json +18 -0
- package/src/generators/formatting.js +24 -1
- package/src/generators/logging-registry.d.ts +2 -0
- package/src/generators/logging-registry.js +22 -0
- package/src/generators/preset/workspace-files-adopter-skills.d.ts +7 -0
- package/src/generators/preset/workspace-files-adopter-skills.js +301 -0
- package/src/generators/preset/workspace-files-ci-install.d.ts +2 -0
- package/src/generators/preset/workspace-files-ci-install.js +196 -0
- package/src/generators/preset/workspace-files-developer-agent.js +40 -13
- package/src/generators/preset/workspace-files-performance-load.js +8 -0
- package/src/generators/preset/workspace-files-stage-authority.js +40 -1
- package/src/generators/preset/workspace-files-thin-deploy.js +66 -34
- package/src/generators/preset/workspace-files-thin-docs.js +64 -18
- package/src/generators/preset/workspace-files.d.ts +4 -0
- package/src/generators/preset/workspace-files.js +159 -91
- package/src/generators/repository-policy/repository-policy.js +37 -0
- package/src/generators/slice/built-in-plan-api-contract-files.js +42 -7
- package/src/generators/slice/built-in-plan-api-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-api-files.js +47 -389
- package/src/generators/slice/built-in-plan-async-work-files.js +19 -1912
- package/src/generators/slice/built-in-plan-authorization-files.js +92 -329
- package/src/generators/slice/built-in-plan-authorization-infrastructure-files.js +36 -2
- package/src/generators/slice/built-in-plan-authorization-storage.d.ts +3 -0
- package/src/generators/slice/built-in-plan-authorization-storage.js +119 -0
- package/src/generators/slice/built-in-plan-background-work-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-background-work-files.js +15 -5
- package/src/generators/slice/built-in-plan-data-deletion-files.js +2 -830
- package/src/generators/slice/built-in-plan-data-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-data-files.js +61 -1164
- package/src/generators/slice/built-in-plan-data-lifecycle-files.js +53 -28
- package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.js +18 -2
- package/src/generators/slice/built-in-plan-data-retention-job-files.js +7 -2446
- package/src/generators/slice/built-in-plan-data-retention-launcher-files.js +30 -6
- package/src/generators/slice/built-in-plan-data-rights-files.js +6 -4482
- package/src/generators/slice/built-in-plan-database-lifecycle-files.js +4 -15
- package/src/generators/slice/built-in-plan-foundation-files.d.ts +2 -1
- package/src/generators/slice/built-in-plan-foundation-files.js +34 -10
- package/src/generators/slice/built-in-plan-frontend-files.js +2 -2
- package/src/generators/slice/built-in-plan-infrastructure-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-infrastructure-files.js +180 -522
- package/src/generators/slice/built-in-plan-key-value-cleanup.d.ts +4 -0
- package/src/generators/slice/built-in-plan-key-value-cleanup.js +100 -0
- package/src/generators/slice/built-in-plan-key-value-consumer.d.ts +4 -0
- package/src/generators/slice/built-in-plan-key-value-consumer.js +151 -0
- package/src/generators/slice/built-in-plan-key-value-deletion.d.ts +2 -0
- package/src/generators/slice/built-in-plan-key-value-deletion.js +377 -0
- package/src/generators/slice/built-in-plan-key-value-delivery.d.ts +2 -0
- package/src/generators/slice/built-in-plan-key-value-delivery.js +120 -0
- package/src/generators/slice/built-in-plan-key-value-export.d.ts +2 -0
- package/src/generators/slice/built-in-plan-key-value-export.js +595 -0
- package/src/generators/slice/built-in-plan-key-value-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-key-value-files.js +31 -0
- package/src/generators/slice/built-in-plan-key-value-holds.d.ts +2 -0
- package/src/generators/slice/built-in-plan-key-value-holds.js +189 -0
- package/src/generators/slice/built-in-plan-key-value-infrastructure.d.ts +2 -0
- package/src/generators/slice/built-in-plan-key-value-infrastructure.js +102 -0
- package/src/generators/slice/built-in-plan-key-value-performance.d.ts +5 -0
- package/src/generators/slice/built-in-plan-key-value-performance.js +530 -0
- package/src/generators/slice/built-in-plan-key-value-provider.d.ts +4 -0
- package/src/generators/slice/built-in-plan-key-value-provider.js +366 -0
- package/src/generators/slice/built-in-plan-key-value-records.d.ts +3 -0
- package/src/generators/slice/built-in-plan-key-value-records.js +232 -0
- package/src/generators/slice/built-in-plan-key-value-retention-infrastructure.d.ts +2 -0
- package/src/generators/slice/built-in-plan-key-value-retention-infrastructure.js +103 -0
- package/src/generators/slice/built-in-plan-key-value-retention-job-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-key-value-retention-job-files.js +160 -0
- package/src/generators/slice/built-in-plan-key-value-retention-maintenance.d.ts +2 -0
- package/src/generators/slice/built-in-plan-key-value-retention-maintenance.js +329 -0
- package/src/generators/slice/built-in-plan-key-value-retention-worker.d.ts +2 -0
- package/src/generators/slice/built-in-plan-key-value-retention-worker.js +477 -0
- package/src/generators/slice/built-in-plan-key-value-retention.d.ts +2 -0
- package/src/generators/slice/built-in-plan-key-value-retention.js +184 -0
- package/src/generators/slice/built-in-plan-metadata-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-metadata-files.js +140 -28
- package/src/generators/slice/built-in-plan-native-runtime-authority-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-native-runtime-authority-files.js +36 -19
- package/src/generators/slice/built-in-plan-operations-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-operations-files.js +89 -50
- package/src/generators/slice/built-in-plan-performance-files.js +84 -1010
- package/src/generators/slice/built-in-plan-project-files.js +116 -67
- package/src/generators/slice/built-in-plan-release-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-release-files.js +64 -15
- package/src/generators/slice/built-in-plan-reliability-files.js +54 -28
- package/src/generators/slice/built-in-plan-shared.d.ts +4 -2
- package/src/generators/slice/built-in-plan-shared.js +41 -19
- package/src/generators/slice/built-in-plan-sql-events.d.ts +2 -0
- package/src/generators/slice/built-in-plan-sql-events.js +257 -0
- package/src/generators/slice/built-in-plan-testing-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-testing-files.js +184 -132
- package/src/generators/slice/built-in-plan-testing-persistence-files.d.ts +2 -0
- package/src/generators/slice/built-in-plan-testing-persistence-files.js +178 -0
- package/src/generators/slice/built-in-plan-thin-release-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-thin-release-files.js +35 -2
- package/src/generators/slice/built-in-plan-verification-files.js +70 -0
- package/src/generators/slice/built-in-plan-web-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-web-files.js +206 -14
- package/src/generators/slice/built-in-plan-workload-role-files.d.ts +1 -1
- package/src/generators/slice/built-in-plan-workload-role-files.js +113 -274
- package/src/generators/slice/built-in-plan.d.ts +9 -1
- package/src/generators/slice/built-in-plan.js +49 -21
- package/src/generators/slice/data-policy-review-seed.d.ts +2 -0
- package/src/generators/slice/data-policy-review-seed.js +22 -0
- package/src/generators/slice/deployed-smoke-readiness.d.ts +2 -0
- package/src/generators/slice/deployed-smoke-readiness.js +214 -0
- package/src/generators/slice/local-source-identity.d.ts +2 -0
- package/src/generators/slice/local-source-identity.js +31 -0
- package/src/generators/slice/persistence-contract.d.ts +14 -0
- package/src/generators/slice/persistence-contract.js +32 -0
- package/src/generators/slice/slice.js +29 -24
- package/src/generators/sql/schema.d.ts +7 -0
- package/src/generators/sql/schema.json +38 -0
- package/src/generators/sql/sql.d.ts +6 -0
- package/src/generators/sql/sql.js +53 -0
- package/src/generators/upgrade/sql-seeded-reconciliation.d.ts +2 -0
- package/src/generators/upgrade/sql-seeded-reconciliation.js +170 -0
- package/src/generators/upgrade/upgrade.d.ts +2 -0
- package/src/generators/upgrade/upgrade.js +136 -9
- package/src/generators/workload/workload.js +51 -2
- package/src/local-dev/browser-verification.d.ts +37 -0
- package/src/local-dev/browser-verification.js +281 -0
- package/src/local-dev/contracts.d.ts +10 -1
- package/src/local-dev/contracts.js +114 -13
- package/src/local-dev/dev-command-core.js +24 -5
- package/src/local-dev/docker-credential-health.d.ts +14 -0
- package/src/local-dev/docker-credential-health.js +94 -0
- package/src/local-dev/environment-inspector.d.ts +7 -0
- package/src/local-dev/environment-inspector.js +42 -15
- package/src/local-dev/environment-state.js +2 -2
- package/src/local-dev/errors.d.ts +1 -1
- package/src/local-dev/errors.js +2 -0
- package/src/local-dev/fleet-client.js +2 -2
- package/src/local-dev/fleet-configuration.js +57 -25
- package/src/local-dev/fleet-inventory.js +46 -18
- package/src/local-dev/fleet-ipc.d.ts +7 -0
- package/src/local-dev/fleet-ipc.js +14 -2
- package/src/local-dev/fleet-launcher.d.ts +6 -0
- package/src/local-dev/fleet-launcher.js +14 -2
- package/src/local-dev/fleet-logs.js +50 -22
- package/src/local-dev/fleet-process.d.ts +20 -1
- package/src/local-dev/fleet-process.js +197 -41
- package/src/local-dev/fleet-runner-evidence.d.ts +5 -0
- package/src/local-dev/fleet-runner-evidence.js +56 -0
- package/src/local-dev/fleet-runtime.js +268 -229
- package/src/local-dev/fleet-session.d.ts +2 -0
- package/src/local-dev/fleet-session.js +28 -11
- package/src/local-dev/fleet-slice-runner-daemon.js +4 -0
- package/src/local-dev/fleet-state.d.ts +5 -2
- package/src/local-dev/fleet-state.js +25 -4
- package/src/local-dev/fleet-supervisor.d.ts +3 -0
- package/src/local-dev/fleet-supervisor.js +66 -11
- package/src/local-dev/fleet-web-start.d.ts +12 -0
- package/src/local-dev/fleet-web-start.js +48 -0
- package/src/local-dev/identity.js +3 -14
- package/src/local-dev/index.d.ts +1 -0
- package/src/local-dev/index.js +1 -0
- package/src/local-dev/native-completion.d.ts +9 -0
- package/src/local-dev/native-completion.js +130 -0
- package/src/local-dev/nx-workspace.d.ts +4 -2
- package/src/local-dev/nx-workspace.js +11 -6
- package/src/local-dev/personal-stage.d.ts +4 -5
- package/src/local-dev/personal-stage.js +6 -54
- package/src/local-dev/port-claims.d.ts +13 -0
- package/src/local-dev/port-claims.js +46 -0
- package/src/local-dev/ports.d.ts +14 -2
- package/src/local-dev/ports.js +78 -3
- package/src/local-dev/private-state.d.ts +6 -0
- package/src/local-dev/private-state.js +126 -34
- package/src/local-dev/process-group.d.ts +4 -0
- package/src/local-dev/process-group.js +29 -0
- package/src/local-dev/process-identity.d.ts +8 -0
- package/src/local-dev/process-identity.js +31 -1
- package/src/local-dev/proxy.js +11 -12
- package/src/local-dev/runtime-paths.js +1 -1
- package/src/local-dev/slice-claim.js +1 -1
- package/src/local-dev/slice-runner.d.ts +15 -6
- package/src/local-dev/slice-runner.js +189 -54
- package/src/local-dev/task-attachment.d.ts +17 -0
- package/src/local-dev/task-attachment.js +73 -0
- package/src/local-dev/task-authority.d.ts +10 -0
- package/src/local-dev/task-authority.js +27 -0
- package/src/local-dev/task-identity.d.ts +33 -0
- package/src/local-dev/task-identity.js +418 -0
- package/src/local-dev/task-native-writer.d.ts +18 -0
- package/src/local-dev/task-native-writer.js +329 -0
- package/src/local-dev/tls.js +3 -1
- package/src/local-dev/web-launch.d.ts +9 -0
- package/src/local-dev/web-launch.js +130 -0
- package/src/ownership/composition.d.ts +2 -1
- package/src/ownership/composition.js +1 -0
- package/src/performance/scenario.d.ts +22 -0
- package/src/performance/scenario.js +100 -92
- package/src/repository-policy/deployment-plan.d.ts +2 -2
- package/src/repository-policy/deployment-plan.js +2 -1
- package/src/repository-policy/policy.js +38 -3
- package/src/schemas/blueprint-v1.json +5 -4
- package/src/schemas/foundation-requirement-v1.json +5 -4
- package/src/schemas/testing-evidence-result-v1.json +1 -1
- package/src/secrets/operator.d.ts +3 -1
- package/src/secrets/operator.js +22 -3
- package/src/sst-environment-source-format.d.ts +3 -0
- package/src/sst-environment-source-format.js +20 -0
- package/src/supply-chain/blueprint-trust-git.js +13 -3
- package/src/supply-chain/build-output.js +15 -0
- package/src/supply-chain/generated-blueprint-trust-command.js +18 -1
- package/src/testing-evidence/fixture-scope.d.ts +2 -1
- package/src/testing-evidence/fixture-scope.js +4 -2
- package/src/testing-evidence/result.d.ts +2 -1
- package/src/testing-evidence/result.js +18 -4
- package/src/workload-roles/standard-slice.js +2 -3
- package/src/api-contract/baseline-update.js.map +0 -1
- package/src/api-contract/compatibility.js.map +0 -1
- package/src/api-contract/contract-graph.js.map +0 -1
- package/src/api-contract/evidence.js.map +0 -1
- package/src/api-contract/index.js.map +0 -1
- package/src/api-contract/model.fixtures.d.ts +0 -2
- package/src/api-contract/model.fixtures.js +0 -81
- package/src/api-contract/model.fixtures.js.map +0 -1
- package/src/api-contract/model.js.map +0 -1
- package/src/api-contract/rollout.js.map +0 -1
- package/src/authorization/compatibility.js.map +0 -1
- package/src/authorization/index.js.map +0 -1
- package/src/aws/child-environment.js.map +0 -1
- package/src/aws/identity.js.map +0 -1
- package/src/aws-authority/index.js.map +0 -1
- package/src/aws-authority/stage-authority.js.map +0 -1
- package/src/blueprints/execution.js.map +0 -1
- package/src/blueprints/external-sandbox.js.map +0 -1
- package/src/blueprints/index.js.map +0 -1
- package/src/blueprints/inputs.js.map +0 -1
- package/src/blueprints/manifest.js.map +0 -1
- package/src/blueprints/resolver.js.map +0 -1
- package/src/blueprints/transitions.js.map +0 -1
- package/src/cli/agent-command.js.map +0 -1
- package/src/cli/agent-runtime.js.map +0 -1
- package/src/cli/blueprint-authority.js.map +0 -1
- package/src/cli/blueprint-command.js.map +0 -1
- package/src/cli/bootstrap.js.map +0 -1
- package/src/cli/dev-command.js.map +0 -1
- package/src/cli/main.js.map +0 -1
- package/src/cli/output.js.map +0 -1
- package/src/cli/personal-secret-runtime.js.map +0 -1
- package/src/cli/secret-terminal.js.map +0 -1
- package/src/container-images.js.map +0 -1
- package/src/data-lifecycle/index.js.map +0 -1
- package/src/data-lifecycle/model.fixtures.d.ts +0 -2
- package/src/data-lifecycle/model.fixtures.js +0 -244
- package/src/data-lifecycle/model.fixtures.js.map +0 -1
- package/src/data-lifecycle/model.js.map +0 -1
- package/src/data-lifecycle/sensitive-artifacts.js.map +0 -1
- package/src/data-lifecycle/validation.js.map +0 -1
- package/src/database-retirement/contract.js.map +0 -1
- package/src/database-retirement/index.js.map +0 -1
- package/src/deterministic-order.js.map +0 -1
- package/src/developer-agent/context.js.map +0 -1
- package/src/developer-agent/generator-planning.js.map +0 -1
- package/src/developer-agent/generator-preview.js.map +0 -1
- package/src/developer-agent/git-inspection.js.map +0 -1
- package/src/developer-agent/handoff.js.map +0 -1
- package/src/developer-agent/index.js.map +0 -1
- package/src/developer-agent/model.js.map +0 -1
- package/src/developer-agent/operation-registry.js.map +0 -1
- package/src/developer-agent/ordering.js.map +0 -1
- package/src/developer-agent/planning.js.map +0 -1
- package/src/developer-agent/preview-changes.js.map +0 -1
- package/src/developer-agent/preview-source.js.map +0 -1
- package/src/developer-agent/validation.js.map +0 -1
- package/src/developer-agent/workspace-inspection.js.map +0 -1
- package/src/developer-agent/workspace-path.js.map +0 -1
- package/src/executors/blueprint-trust/blueprint-trust.js.map +0 -1
- package/src/executors/blueprint-verification/blueprint-verification.js.map +0 -1
- package/src/executors/deploy/deploy.js.map +0 -1
- package/src/executors/deployment-plan/deployment-plan.js.map +0 -1
- package/src/executors/dev/dev.js.map +0 -1
- package/src/executors/dev-doctor/dev-doctor.js.map +0 -1
- package/src/executors/dev-setup/dev-setup.js.map +0 -1
- package/src/executors/developer-context/developer-context.js.map +0 -1
- package/src/executors/fleet/fleet.js.map +0 -1
- package/src/executors/foundation-preflight/foundation-preflight.js.map +0 -1
- package/src/executors/foundation-profile-preflight/foundation-profile-preflight.js.map +0 -1
- package/src/executors/foundation-profile-preflight/production-database-safeguard.js.map +0 -1
- package/src/executors/foundation-remove-preflight/foundation-remove-preflight.js.map +0 -1
- package/src/executors/github-bootstrap/github-bootstrap.js.map +0 -1
- package/src/executors/infrastructure-plan/infrastructure-plan.js.map +0 -1
- package/src/executors/local-deploy/federated-credential-transport.js.map +0 -1
- package/src/executors/local-deploy/fixtures/local-deploy-state-machine.mjs +0 -53
- package/src/executors/local-deploy/local-approval.js.map +0 -1
- package/src/executors/local-deploy/local-deploy.js.map +0 -1
- package/src/executors/refresh/refresh.js.map +0 -1
- package/src/executors/remove/remove.js.map +0 -1
- package/src/executors/router-waf-rehearsal/router-waf-rehearsal.js.map +0 -1
- package/src/executors/secret-guardrails/secret-guardrails.js.map +0 -1
- package/src/executors/secret-initialize/secret-initialize.js.map +0 -1
- package/src/executors/secret-metadata/secret-metadata.js.map +0 -1
- package/src/executors/sst-lifecycle/generated-secret-retirement.js.map +0 -1
- package/src/executors/sst-lifecycle/governed-native-operation.js.map +0 -1
- package/src/executors/sst-lifecycle/logging-preflight.js.map +0 -1
- package/src/executors/sst-lifecycle/run-sst-command.js.map +0 -1
- package/src/executors/sst-lifecycle/secret-preflight.js.map +0 -1
- package/src/executors/sst-lifecycle/sst-environment-source.js.map +0 -1
- package/src/executors/unlock/unlock.js.map +0 -1
- package/src/executors/work-markers/work-markers.js.map +0 -1
- package/src/foundation/discovery.js.map +0 -1
- package/src/foundation/index.js.map +0 -1
- package/src/foundation/local-database-contract.js.map +0 -1
- package/src/foundation/logging-preflight.js.map +0 -1
- package/src/foundation/logging.js.map +0 -1
- package/src/foundation/partial-state.js.map +0 -1
- package/src/foundation/preflight.js.map +0 -1
- package/src/foundation/private-smoke-access.js.map +0 -1
- package/src/foundation/private-smoke-admission.js.map +0 -1
- package/src/foundation/private-smoke-control-plane.js.map +0 -1
- package/src/foundation/provision-database-bindings.js.map +0 -1
- package/src/foundation/provision-logical-database.js.map +0 -1
- package/src/foundation/requirements.js.map +0 -1
- package/src/foundation/router-origin-proof.js.map +0 -1
- package/src/foundation/router-waf-rate-rehearsal.js.map +0 -1
- package/src/foundation/router-waf.js.map +0 -1
- package/src/foundation/stages.js.map +0 -1
- package/src/frontend-security/index.js.map +0 -1
- package/src/frontend-security/security-headers.js.map +0 -1
- package/src/generators/feature-registry.js.map +0 -1
- package/src/generators/formatting.js.map +0 -1
- package/src/generators/function/function.js.map +0 -1
- package/src/generators/job/job.js.map +0 -1
- package/src/generators/logging-registry.js.map +0 -1
- package/src/generators/post-generation-install.js.map +0 -1
- package/src/generators/preset/dependency-overrides.js.map +0 -1
- package/src/generators/preset/generator.js.map +0 -1
- package/src/generators/preset/tool-versions.js.map +0 -1
- package/src/generators/preset/workspace-files-ci-acceptance.js.map +0 -1
- package/src/generators/preset/workspace-files-developer-agent.js.map +0 -1
- package/src/generators/preset/workspace-files-ecr-inspector.js.map +0 -1
- package/src/generators/preset/workspace-files-foundation-workload-roles.js.map +0 -1
- package/src/generators/preset/workspace-files-performance-cost.js.map +0 -1
- package/src/generators/preset/workspace-files-performance-load.js.map +0 -1
- package/src/generators/preset/workspace-files-stage-authority.js.map +0 -1
- package/src/generators/preset/workspace-files-thin-deploy.js.map +0 -1
- package/src/generators/preset/workspace-files-thin-docs.js.map +0 -1
- package/src/generators/preset/workspace-files-thin-release.js.map +0 -1
- package/src/generators/preset/workspace-files-workload-role-baseline.js.map +0 -1
- package/src/generators/preset/workspace-files.js.map +0 -1
- package/src/generators/repository-policy/repository-policy.js.map +0 -1
- package/src/generators/repository-policy/tree-policy.js.map +0 -1
- package/src/generators/service/service.js.map +0 -1
- package/src/generators/slice/built-in-plan-api-contract-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-api-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-async-work-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-authorization-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-authorization-infrastructure-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-background-work-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-data-deletion-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-data-export-infrastructure-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-data-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-data-lifecycle-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-data-retention-job-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-data-retention-launcher-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-data-rights-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-database-lifecycle-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-foundation-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-frontend-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-infrastructure-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-infrastructure-safety-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-metadata-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-native-runtime-authority-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-operations-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-performance-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-project-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-release-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-reliability-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-secret-runtime-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-shared.js.map +0 -1
- package/src/generators/slice/built-in-plan-testing-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-thin-release-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-verification-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-web-files.js.map +0 -1
- package/src/generators/slice/built-in-plan-workload-role-files.js.map +0 -1
- package/src/generators/slice/built-in-plan.js.map +0 -1
- package/src/generators/slice/slice.js.map +0 -1
- package/src/generators/upgrade/upgrade.js.map +0 -1
- package/src/generators/workload/frozen-container.js.map +0 -1
- package/src/generators/workload/performance-registration.js.map +0 -1
- package/src/generators/workload/reliability-registration.js.map +0 -1
- package/src/generators/workload/service-performance-files.js.map +0 -1
- package/src/generators/workload/workload.js.map +0 -1
- package/src/git-policy/action-pins.js.map +0 -1
- package/src/git-policy/github-bootstrap.js.map +0 -1
- package/src/git-policy/index.js.map +0 -1
- package/src/git-policy/routing.js.map +0 -1
- package/src/index.js.map +0 -1
- package/src/infrastructure-change/convergence.js.map +0 -1
- package/src/infrastructure-change/drift.js.map +0 -1
- package/src/infrastructure-change/index.js.map +0 -1
- package/src/infrastructure-change/local-capability.js.map +0 -1
- package/src/infrastructure-change/model.js.map +0 -1
- package/src/infrastructure-change/normalize.js.map +0 -1
- package/src/infrastructure-change/plan.js.map +0 -1
- package/src/infrastructure-change/risk.js.map +0 -1
- package/src/infrastructure-change/summary.js.map +0 -1
- package/src/local-dev/context-discovery.js.map +0 -1
- package/src/local-dev/contract-validation.js.map +0 -1
- package/src/local-dev/contracts.js.map +0 -1
- package/src/local-dev/control-contract.js.map +0 -1
- package/src/local-dev/dev-command-core.js.map +0 -1
- package/src/local-dev/effects.js.map +0 -1
- package/src/local-dev/environment-inspector.js.map +0 -1
- package/src/local-dev/environment-state.js.map +0 -1
- package/src/local-dev/errors.js.map +0 -1
- package/src/local-dev/fleet-client.js.map +0 -1
- package/src/local-dev/fleet-configuration.js.map +0 -1
- package/src/local-dev/fleet-inventory.js.map +0 -1
- package/src/local-dev/fleet-ipc.js.map +0 -1
- package/src/local-dev/fleet-launcher.js.map +0 -1
- package/src/local-dev/fleet-lock.js.map +0 -1
- package/src/local-dev/fleet-logs.js.map +0 -1
- package/src/local-dev/fleet-process.js.map +0 -1
- package/src/local-dev/fleet-runtime.js.map +0 -1
- package/src/local-dev/fleet-session.js.map +0 -1
- package/src/local-dev/fleet-slice-runner-daemon.js.map +0 -1
- package/src/local-dev/fleet-startup.js.map +0 -1
- package/src/local-dev/fleet-state.js.map +0 -1
- package/src/local-dev/fleet-supervisor-daemon.js.map +0 -1
- package/src/local-dev/fleet-supervisor.js.map +0 -1
- package/src/local-dev/gateway-daemon.js.map +0 -1
- package/src/local-dev/gateway.js.map +0 -1
- package/src/local-dev/identity.js.map +0 -1
- package/src/local-dev/index.js.map +0 -1
- package/src/local-dev/local-context.js.map +0 -1
- package/src/local-dev/nx-workspace.js.map +0 -1
- package/src/local-dev/personal-secret-ledger.js.map +0 -1
- package/src/local-dev/personal-stage.js.map +0 -1
- package/src/local-dev/portless.js.map +0 -1
- package/src/local-dev/ports.js.map +0 -1
- package/src/local-dev/private-state.js.map +0 -1
- package/src/local-dev/process-identity.js.map +0 -1
- package/src/local-dev/proxy.js.map +0 -1
- package/src/local-dev/runtime-paths.js.map +0 -1
- package/src/local-dev/secret-slice-claim.js.map +0 -1
- package/src/local-dev/slice-claim.js.map +0 -1
- package/src/local-dev/slice-runner.js.map +0 -1
- package/src/local-dev/tls.js.map +0 -1
- package/src/ownership/composition.js.map +0 -1
- package/src/ownership/foundation-record.js.map +0 -1
- package/src/ownership/hash.js.map +0 -1
- package/src/ownership/index.js.map +0 -1
- package/src/ownership/json-ownership.js.map +0 -1
- package/src/ownership/record.js.map +0 -1
- package/src/ownership/workspace-record.js.map +0 -1
- package/src/performance/cost-collection.js.map +0 -1
- package/src/performance/cost-controls.js.map +0 -1
- package/src/performance/evidence.js.map +0 -1
- package/src/performance/index.js.map +0 -1
- package/src/performance/load-safety.js.map +0 -1
- package/src/performance/model.js.map +0 -1
- package/src/performance/pr-artifact-budget.js.map +0 -1
- package/src/performance/runner.js.map +0 -1
- package/src/performance/scenario-endpoint.js.map +0 -1
- package/src/performance/scenario.js.map +0 -1
- package/src/performance/test-fixtures.d.ts +0 -7
- package/src/performance/test-fixtures.js +0 -167
- package/src/performance/test-fixtures.js.map +0 -1
- package/src/performance/unit-cost.js.map +0 -1
- package/src/release/index.js.map +0 -1
- package/src/release/lifecycle.js.map +0 -1
- package/src/release/manifest.js.map +0 -1
- package/src/release/rollout.js.map +0 -1
- package/src/release/source-authority.js.map +0 -1
- package/src/repository-policy/aurora-preflight.js.map +0 -1
- package/src/repository-policy/capacity-migration.js.map +0 -1
- package/src/repository-policy/deployment-plan.js.map +0 -1
- package/src/repository-policy/foundation-profile.js.map +0 -1
- package/src/repository-policy/index.js.map +0 -1
- package/src/repository-policy/policy.js.map +0 -1
- package/src/secrets/adapters.js.map +0 -1
- package/src/secrets/aws-control-plane.js.map +0 -1
- package/src/secrets/declaration-verification.js.map +0 -1
- package/src/secrets/generated-aws-control-plane.js.map +0 -1
- package/src/secrets/guardrails.js.map +0 -1
- package/src/secrets/index.js.map +0 -1
- package/src/secrets/metadata.js.map +0 -1
- package/src/secrets/model.js.map +0 -1
- package/src/secrets/operator.js.map +0 -1
- package/src/secrets/permissions.js.map +0 -1
- package/src/secrets/personal-command.js.map +0 -1
- package/src/secrets/personal-ledger.js.map +0 -1
- package/src/secrets/registry.js.map +0 -1
- package/src/secrets/verification.js.map +0 -1
- package/src/secrets/workload-access.js.map +0 -1
- package/src/sst-environment-source-format.js.map +0 -1
- package/src/supply-chain/action-pins.js.map +0 -1
- package/src/supply-chain/blueprint-trust-git.js.map +0 -1
- package/src/supply-chain/blueprint-trust-process.js.map +0 -1
- package/src/supply-chain/blueprint-trust.js.map +0 -1
- package/src/supply-chain/blueprint-verification-authority.js.map +0 -1
- package/src/supply-chain/blueprint-verification-execution.js.map +0 -1
- package/src/supply-chain/build-output-bounds.js.map +0 -1
- package/src/supply-chain/build-output.js.map +0 -1
- package/src/supply-chain/common.js.map +0 -1
- package/src/supply-chain/container-artifact-contract.js.map +0 -1
- package/src/supply-chain/container-release.js.map +0 -1
- package/src/supply-chain/ecr-applicability.js.map +0 -1
- package/src/supply-chain/ecr-scanning.js.map +0 -1
- package/src/supply-chain/ecs-deployed-image.js.map +0 -1
- package/src/supply-chain/errors.js.map +0 -1
- package/src/supply-chain/generated-blueprint-trust-command.js.map +0 -1
- package/src/supply-chain/generated-command.js.map +0 -1
- package/src/supply-chain/generated-container-release-command.js.map +0 -1
- package/src/supply-chain/generated-ecr-collector-command.js.map +0 -1
- package/src/supply-chain/generated-files.js.map +0 -1
- package/src/supply-chain/generated-scanner-command.js.map +0 -1
- package/src/supply-chain/index.js.map +0 -1
- package/src/supply-chain/inventory.js.map +0 -1
- package/src/supply-chain/license-expression.js.map +0 -1
- package/src/supply-chain/pnpm-toolchain-authority.js.map +0 -1
- package/src/supply-chain/policy.js.map +0 -1
- package/src/supply-chain/publication.js.map +0 -1
- package/src/supply-chain/sbom.js.map +0 -1
- package/src/supply-chain/scanner.js.map +0 -1
- package/src/supply-chain/vendored-source.js.map +0 -1
- package/src/testing-evidence/fixture-scope.js.map +0 -1
- package/src/testing-evidence/index.js.map +0 -1
- package/src/testing-evidence/quarantine.js.map +0 -1
- package/src/testing-evidence/result.js.map +0 -1
- package/src/testing-evidence/runner-adapter.js.map +0 -1
- package/src/testing-evidence/sensitive-artifacts.js.map +0 -1
- package/src/validation.js.map +0 -1
- package/src/work-markers/index.js.map +0 -1
- package/src/work-markers/work-markers.js.map +0 -1
- package/src/workload-roles/account-baseline.js.map +0 -1
- package/src/workload-roles/authority.js.map +0 -1
- package/src/workload-roles/aws-adapter.js.map +0 -1
- package/src/workload-roles/aws-internal-handler.js.map +0 -1
- package/src/workload-roles/aws-s3-state.js.map +0 -1
- package/src/workload-roles/aws-sdk-control-plane.js.map +0 -1
- package/src/workload-roles/boundary.js.map +0 -1
- package/src/workload-roles/convergence.js.map +0 -1
- package/src/workload-roles/effective-policy.js.map +0 -1
- package/src/workload-roles/handler.js.map +0 -1
- package/src/workload-roles/history.js.map +0 -1
- package/src/workload-roles/index.js.map +0 -1
- package/src/workload-roles/injection.js.map +0 -1
- package/src/workload-roles/manifest.js.map +0 -1
- package/src/workload-roles/provisioner.js.map +0 -1
- package/src/workload-roles/registration.js.map +0 -1
- package/src/workload-roles/stage-boundary.js.map +0 -1
- package/src/workload-roles/standard-slice.js.map +0 -1
- package/src/workspace-deployment/affected-lifecycle.js.map +0 -1
- package/src/workspace-deployment/identity.js.map +0 -1
- package/src/workspace-deployment/index.js.map +0 -1
- package/src/workspace-deployment/migration-evidence.js.map +0 -1
- package/src/workspace-deployment/migration.js.map +0 -1
- package/src/workspace-deployment/ownership.js.map +0 -1
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderTestingPersistenceFiles = renderTestingPersistenceFiles;
|
|
4
|
+
/** Disposable integration resources are independent of fleet or deployed data. */
|
|
5
|
+
function renderTestingPersistenceFiles(name, pascalName, sql) {
|
|
6
|
+
const labels = ` labels:
|
|
7
|
+
dev.empirebuilderkit.owner: test-integration
|
|
8
|
+
dev.empirebuilderkit.run: \${EBK_TEST_RUN_ID}
|
|
9
|
+
dev.empirebuilderkit.slice: ${name}`;
|
|
10
|
+
return {
|
|
11
|
+
'database/test-compose.yml': `services:
|
|
12
|
+
key-value:
|
|
13
|
+
image: amazon/dynamodb-local@sha256:ff89bd48ff32cd8d9be5fee8873b65b8854dc408f1afe881be6eb00247bc0dab
|
|
14
|
+
command: [-jar, DynamoDBLocal.jar, -inMemory, -sharedDb]
|
|
15
|
+
${labels}
|
|
16
|
+
ports:
|
|
17
|
+
- '127.0.0.1::8000'
|
|
18
|
+
${sql
|
|
19
|
+
? ` database:
|
|
20
|
+
image: postgres:17-alpine
|
|
21
|
+
environment:
|
|
22
|
+
POSTGRES_DB: postgres
|
|
23
|
+
POSTGRES_PASSWORD: ebk_test
|
|
24
|
+
POSTGRES_USER: ebk_test
|
|
25
|
+
healthcheck:
|
|
26
|
+
test: [CMD-SHELL, "pg_isready -U ebk_test -d postgres"]
|
|
27
|
+
interval: 1s
|
|
28
|
+
timeout: 3s
|
|
29
|
+
retries: 30
|
|
30
|
+
${labels}
|
|
31
|
+
ports:
|
|
32
|
+
- '127.0.0.1::5432'
|
|
33
|
+
tmpfs:
|
|
34
|
+
- /var/lib/postgresql/data
|
|
35
|
+
`
|
|
36
|
+
: ''}`,
|
|
37
|
+
'testing/local-key-value.ts': `import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
|
|
38
|
+
import { createDynamoPersistence } from '@empire-builder-kit/runtime/key-value';
|
|
39
|
+
|
|
40
|
+
const endpoint = new URL(process.env.EBK_TEST_DYNAMODB_ENDPOINT ?? 'http://invalid');
|
|
41
|
+
const tableName = process.env.EBK_TEST_DYNAMODB_TABLE;
|
|
42
|
+
if (endpoint.protocol !== 'http:' || endpoint.hostname !== '127.0.0.1' ||
|
|
43
|
+
!endpoint.port || endpoint.username || endpoint.password || endpoint.search ||
|
|
44
|
+
endpoint.hash || endpoint.pathname !== '/' ||
|
|
45
|
+
!tableName || !/^ebk-test-${name}-[a-z0-9]{1,32}-a[12]-w[0-7]$/.test(tableName)) {
|
|
46
|
+
throw new Error('Integration requires the runner-owned loopback DynamoDB endpoint and worker table.');
|
|
47
|
+
}
|
|
48
|
+
export const localKeyValueClient = new DynamoDBClient({
|
|
49
|
+
endpoint: endpoint.href, region: 'us-east-1', maxAttempts: 1,
|
|
50
|
+
credentials: { accessKeyId: 'LOCALFIXTURE', secretAccessKey: 'local-fixture-not-an-aws-credential' },
|
|
51
|
+
});
|
|
52
|
+
export const localKeyValueTable = tableName;
|
|
53
|
+
export function localKeyValueStore(stage = 'development') {
|
|
54
|
+
return createDynamoPersistence({ client: localKeyValueClient, tableName: localKeyValueTable,
|
|
55
|
+
stage, slice: '${name}', eventBusName: 'local-integration-events' });
|
|
56
|
+
}
|
|
57
|
+
`,
|
|
58
|
+
'integration/record.spec.ts': `import { ScanCommand } from '@aws-sdk/client-dynamodb';
|
|
59
|
+
import { afterAll, describe, expect, it, vi } from 'vitest';
|
|
60
|
+
import { build${pascalName}RecordFixture } from '../testing/fixtures/records.js';
|
|
61
|
+
import { localKeyValueClient, localKeyValueStore, localKeyValueTable } from '../testing/local-key-value.js';
|
|
62
|
+
import { getOwnedRecord, mutateRecord, type RecordMutationInput } from '../data/records.js';
|
|
63
|
+
|
|
64
|
+
vi.mock('../data/key-value.js', async () => {
|
|
65
|
+
const { localKeyValueStore } = await import('../testing/local-key-value.js');
|
|
66
|
+
const store = localKeyValueStore();
|
|
67
|
+
return { dataStore: () => store };
|
|
68
|
+
});
|
|
69
|
+
const seed = process.env.EBK_TEST_SEED;
|
|
70
|
+
if (!seed) throw new Error('EBK_TEST_SEED is required for reproducible integration fixtures.');
|
|
71
|
+
afterAll(() => localKeyValueClient.destroy());
|
|
72
|
+
|
|
73
|
+
describe('${name} DynamoDB integration', () => {
|
|
74
|
+
it('atomically creates a subject-owned record and durable event intent', async () => {
|
|
75
|
+
const fixture = build${pascalName}RecordFixture(seed);
|
|
76
|
+
const input: RecordMutationInput = { correlationId: fixture.id, name: fixture.name, recordId: fixture.id, now: new Date().toISOString(),
|
|
77
|
+
runScope: seed, principal: { kind: 'member', actor: { id: 'synthetic-owner', type: 'user' },
|
|
78
|
+
subject: { id: 'synthetic-owner', type: 'user' },
|
|
79
|
+
authority: { mode: 'direct' } } };
|
|
80
|
+
const created = await mutateRecord(input, true);
|
|
81
|
+
expect(created).toMatchObject({ created: true, propagation: 'pending' });
|
|
82
|
+
await expect(getOwnedRecord(fixture.id, 'synthetic-owner')).resolves.toMatchObject(fixture);
|
|
83
|
+
await expect(getOwnedRecord(fixture.id, 'different-owner')).resolves.toBeNull();
|
|
84
|
+
await expect(localKeyValueStore('production').get('application', 'records', fixture.id)).resolves.toBeNull();
|
|
85
|
+
const rows = await localKeyValueClient.send(new ScanCommand({ TableName: localKeyValueTable, ConsistentRead: true }));
|
|
86
|
+
expect(rows.LastEvaluatedKey).toBeUndefined();
|
|
87
|
+
expect(rows.Items?.filter((row) => row.kind?.S === 'outbox')).toHaveLength(1);
|
|
88
|
+
await expect(mutateRecord(input, true)).resolves.toEqual(created);
|
|
89
|
+
const repeated = await localKeyValueClient.send(new ScanCommand({ TableName: localKeyValueTable, ConsistentRead: true }));
|
|
90
|
+
expect(repeated.Items?.filter((row) => row.kind?.S === 'outbox')).toHaveLength(1);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
`,
|
|
94
|
+
'integration/performance-load-cleanup.spec.ts': `import { afterAll, describe, expect, it } from 'vitest';
|
|
95
|
+
import type { ProtectedLoadRequestAuthorizationV1 } from '@empire-builder-kit/runtime/performance';
|
|
96
|
+
import { createPerformancePersistence } from '../performance/persistence.js';
|
|
97
|
+
import { localKeyValueClient, localKeyValueStore } from '../testing/local-key-value.js';
|
|
98
|
+
|
|
99
|
+
afterAll(() => localKeyValueClient.destroy());
|
|
100
|
+
const at = Date.parse('2026-09-12T12:00:00.000Z');
|
|
101
|
+
function authorization(plan: string): ProtectedLoadRequestAuthorizationV1 {
|
|
102
|
+
return { adapterId: 'ebk-dynamodb-async-v1', configuredMaximum: 40,
|
|
103
|
+
createdAt: new Date(at).toISOString(), durationSeconds: 60, effectId: 'e'.repeat(64),
|
|
104
|
+
expiresAt: new Date(at + 3_600_000).toISOString(), hmacKeyId: 'integration-fixture', maximumRequests: 10,
|
|
105
|
+
operation: 'execute', planMaterialDigest: plan, release: { candidateDigest: 'b'.repeat(64),
|
|
106
|
+
releaseId: 'local-integration', releaseMaterialDigest: 'c'.repeat(64), sourceCommit: 'd'.repeat(40) },
|
|
107
|
+
requestOrdinal: 1, runId: 'run-' + plan.slice(0, 4),
|
|
108
|
+
saturationSignalRef: 'dynamodb:protected-run-unprocessed-effects-percent', scenarioId: 'async-key-value-burst',
|
|
109
|
+
stage: 'development', target: { accountFingerprint: 'sha256:' + 'f'.repeat(64),
|
|
110
|
+
endpoint: 'https://fixture.example.test/${name}/__ebk/performance/async-worker', region: 'us-east-1', slice: '${name}' },
|
|
111
|
+
workload: 'async-worker' };
|
|
112
|
+
}
|
|
113
|
+
const cleanup = (auth: ProtectedLoadRequestAuthorizationV1): ProtectedLoadRequestAuthorizationV1 =>
|
|
114
|
+
({ ...auth, operation: 'cleanup', effectId: null });
|
|
115
|
+
|
|
116
|
+
describe('${name} DynamoDB performance cleanup', () => {
|
|
117
|
+
it('processes an idempotent effect and tombstones cleanup against late writes', async () => {
|
|
118
|
+
const persistence = createPerformancePersistence(localKeyValueStore(), () => at);
|
|
119
|
+
const auth = authorization('1'.repeat(64));
|
|
120
|
+
await persistence.reserve(auth);
|
|
121
|
+
await expect(persistence.reserve(auth)).rejects.toThrow('replayed');
|
|
122
|
+
await expect(persistence.execute(auth.adapterId as 'ebk-dynamodb-async-v1', auth.effectId!, auth)).resolves.toEqual({ effectState: 'created' });
|
|
123
|
+
await expect(persistence.execute('ebk-dynamodb-async-v1', auth.effectId!, auth)).resolves.toEqual({ effectState: 'already-existed' });
|
|
124
|
+
await expect(persistence.processAsync()).resolves.toMatchObject({ processed: 1 });
|
|
125
|
+
await expect(persistence.cleanup(cleanup(auth))).resolves.toEqual({ removedEffectCount: 1, remainingEffectCount: 0 });
|
|
126
|
+
await expect(persistence.cleanup(cleanup(auth))).resolves.toEqual({ removedEffectCount: 0, remainingEffectCount: 0 });
|
|
127
|
+
await expect(persistence.execute('ebk-dynamodb-async-v1', auth.effectId!, auth)).rejects.toThrow('collision');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('recovers interruption between reservation and effect without touching another stage', async () => {
|
|
131
|
+
const store = localKeyValueStore();
|
|
132
|
+
const auth = authorization('2'.repeat(64));
|
|
133
|
+
await createPerformancePersistence(store, () => at).reserve(auth);
|
|
134
|
+
const restarted = createPerformancePersistence(localKeyValueStore(), () => at);
|
|
135
|
+
await expect(restarted.cleanup(cleanup(auth))).resolves.toEqual({ removedEffectCount: 0, remainingEffectCount: 0 });
|
|
136
|
+
await expect(restarted.reserve(auth)).rejects.toThrow('collision');
|
|
137
|
+
await expect(localKeyValueStore('production').get('system', 'performance-runs', auth.planMaterialDigest)).resolves.toBeNull();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('retains durable deadline telemetry until acknowledgement, independently of TTL deletion', async () => {
|
|
141
|
+
let clock = at;
|
|
142
|
+
const persistence = createPerformancePersistence(localKeyValueStore(), () => clock);
|
|
143
|
+
const auth = authorization('3'.repeat(64));
|
|
144
|
+
await persistence.reserve(auth);
|
|
145
|
+
await persistence.execute('ebk-dynamodb-async-v1', auth.effectId!, auth);
|
|
146
|
+
clock += 49 * 60 * 60 * 1_000;
|
|
147
|
+
await expect(persistence.expire()).resolves.toMatchObject({ removedEffects: 1, completeScan: true });
|
|
148
|
+
await expect(persistence.reportDeadlines(async () => { throw new Error('metric-transport'); })).rejects.toThrow('metric-transport');
|
|
149
|
+
const metrics: number[] = [];
|
|
150
|
+
await expect(persistence.reportDeadlines(async value => { metrics.push(value); })).resolves.toMatchObject({ reported: 1 });
|
|
151
|
+
expect(metrics).toEqual([1]);
|
|
152
|
+
await expect(persistence.reportDeadlines(async () => {})).resolves.toMatchObject({ reported: 0 });
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
`,
|
|
156
|
+
...(sql
|
|
157
|
+
? {
|
|
158
|
+
'integration/migrations.spec.ts': `import { Client } from 'pg';
|
|
159
|
+
import { describe, expect, it } from 'vitest';
|
|
160
|
+
|
|
161
|
+
const databaseUrl = process.env.DATABASE_URL;
|
|
162
|
+
if (!databaseUrl) throw new Error('DATABASE_URL is required for declared SQL integration proof.');
|
|
163
|
+
describe('${name} optional SQL migrations', () => {
|
|
164
|
+
it('applies committed migrations to an isolated worker database without creating a SQL framework core', async () => {
|
|
165
|
+
const client = new Client({ connectionString: databaseUrl });
|
|
166
|
+
await client.connect();
|
|
167
|
+
try {
|
|
168
|
+
const result = await client.query("SELECT to_regclass('public.data_lifecycle_outbox')::text AS intents");
|
|
169
|
+
expect(result.rows).toEqual([{ intents: 'data_lifecycle_outbox' }]);
|
|
170
|
+
} finally { await client.end(); }
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
`,
|
|
174
|
+
}
|
|
175
|
+
: {}),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=built-in-plan-testing-persistence-files.js.map
|
|
@@ -8,4 +8,4 @@ import type { DeploymentProfile } from '../../repository-policy/index.js';
|
|
|
8
8
|
*/
|
|
9
9
|
export declare const RETIRED_PREVIEW_RELEASE_PATHS: readonly ["scripts/release-lifecycle.mjs", "scripts/release-manifest.mjs", "scripts/release-rollout-proof.mjs", "scripts/release-rollout.mjs"];
|
|
10
10
|
/** @internal */
|
|
11
|
-
export declare function renderProductThinReleaseFiles(name: string, configurationSeed: string, deploymentProfile: DeploymentProfile): Readonly<Record<string, string>>;
|
|
11
|
+
export declare function renderProductThinReleaseFiles(name: string, configurationSeed: string, deploymentProfile: DeploymentProfile, sql?: boolean): Readonly<Record<string, string>>;
|
|
@@ -55,6 +55,11 @@ successful CI run for the deployed commit and assumes the stage deployment
|
|
|
55
55
|
role through GitHub OIDC. The native SST deployment receipt is post-operation
|
|
56
56
|
evidence; a provider preview is advisory and is never release authority.
|
|
57
57
|
|
|
58
|
+
For Next.js, release material excludes only the compiler-cache directory directly
|
|
59
|
+
under the declared .next output. Emitted application files and every referenced
|
|
60
|
+
runtime trace dependency remain inventoried with the same content and size checks.
|
|
61
|
+
Do not delete caches or increase evidence bounds to repair a release build.
|
|
62
|
+
|
|
58
63
|
Active stages for this deployment profile are: ${stages}. Configuration
|
|
59
64
|
declarations are typed and value-free. Evidence records provider identities and
|
|
60
65
|
digests, never secret or flag values. Flags cannot grant authorization.
|
|
@@ -66,9 +71,9 @@ smoke evidence for each accepted protected deployment.
|
|
|
66
71
|
`;
|
|
67
72
|
}
|
|
68
73
|
/** @internal */
|
|
69
|
-
function renderProductThinReleaseFiles(name, configurationSeed, deploymentProfile) {
|
|
74
|
+
function renderProductThinReleaseFiles(name, configurationSeed, deploymentProfile, sql = false) {
|
|
70
75
|
const files = {
|
|
71
|
-
...(0, built_in_plan_release_files_js_1.renderProductReleaseFiles)(name, configurationSeed),
|
|
76
|
+
...(0, built_in_plan_release_files_js_1.renderProductReleaseFiles)(name, configurationSeed, sql),
|
|
72
77
|
};
|
|
73
78
|
for (const path of exports.RETIRED_PREVIEW_RELEASE_PATHS)
|
|
74
79
|
delete files[path];
|
|
@@ -106,6 +111,34 @@ function renderProductThinReleaseFiles(name, configurationSeed, deploymentProfil
|
|
|
106
111
|
if (!Array.isArray(controls.artifactInventory)) {
|
|
107
112
|
throw new Error('Generated release artifact inventory is absent.');
|
|
108
113
|
}
|
|
114
|
+
// These handlers are native SST artifacts, not a second, nonexistent OCI image.
|
|
115
|
+
// SQL added later retains its own migration/retirement images without moving
|
|
116
|
+
// the original DynamoDB records or maintenance into the database.
|
|
117
|
+
controls.artifactInventory = controls.artifactInventory.filter((artifact) => artifact.id !== `${name}.job.data-retention` &&
|
|
118
|
+
(sql ||
|
|
119
|
+
![
|
|
120
|
+
`${name}.job.database-migration`,
|
|
121
|
+
`${name}.job.database-retirement`,
|
|
122
|
+
].includes(String(artifact.id))));
|
|
123
|
+
const lambda = controls.artifactInventory.find((artifact) => artifact.id === `${name}.lambda`);
|
|
124
|
+
const candidate = lambda?.candidate;
|
|
125
|
+
if (!candidate?.materialPaths ||
|
|
126
|
+
!candidate.sourceInputPaths ||
|
|
127
|
+
!candidate.recipePaths)
|
|
128
|
+
throw new Error('Native retention requires the exact Lambda artifact inventory.');
|
|
129
|
+
const nativeInputs = [
|
|
130
|
+
'authorization',
|
|
131
|
+
'data',
|
|
132
|
+
'secrets',
|
|
133
|
+
'jobs/data-retention/src',
|
|
134
|
+
].map((path) => `packages/${name}/${path}`);
|
|
135
|
+
candidate.materialPaths = [
|
|
136
|
+
...new Set([...candidate.materialPaths, ...nativeInputs]),
|
|
137
|
+
];
|
|
138
|
+
candidate.sourceInputPaths = [
|
|
139
|
+
...new Set([...candidate.sourceInputPaths, ...nativeInputs]),
|
|
140
|
+
];
|
|
141
|
+
candidate.recipePaths.push(`packages/${name}/jobs/data-retention/package.json`);
|
|
109
142
|
controls.artifactInventory = controls.artifactInventory.map((artifact) => artifact.classification === 'stage-specific'
|
|
110
143
|
? {
|
|
111
144
|
...artifact,
|
|
@@ -13,6 +13,7 @@ export default defineConfig({
|
|
|
13
13
|
...configDefaults.exclude,
|
|
14
14
|
'**/dist/**',
|
|
15
15
|
'e2e/**',
|
|
16
|
+
'local-e2e/**',
|
|
16
17
|
'integration/**',
|
|
17
18
|
],
|
|
18
19
|
},
|
|
@@ -348,6 +349,75 @@ test('proves the deployed product, auth, database, and event journey', async ({
|
|
|
348
349
|
await expect(signOutResponse.json()).resolves.toEqual({ ok: true });
|
|
349
350
|
expect((await page.request.get(protectedUrl)).status()).toBe(401);
|
|
350
351
|
});
|
|
352
|
+
`,
|
|
353
|
+
'scripts/verify-local-browser.mjs': `import { resolve } from 'node:path';
|
|
354
|
+
import { runLocalBrowserVerification } from '@empire-builder-kit/nx/local-dev';
|
|
355
|
+
await runLocalBrowserVerification({ workspaceRoot: resolve(import.meta.dirname, '../../..'), slice: '${name}' });
|
|
356
|
+
`,
|
|
357
|
+
'playwright.local.config.ts': `import { defineConfig } from '@playwright/test';
|
|
358
|
+
import { resolve } from 'node:path';
|
|
359
|
+
import { localBrowserLaunchArguments, resolveLocalBrowserTarget } from '@empire-builder-kit/nx/local-dev';
|
|
360
|
+
const target = await resolveLocalBrowserTarget({ workspaceRoot: resolve(import.meta.dirname, '../..'), slice: '${name}' });
|
|
361
|
+
export default defineConfig({
|
|
362
|
+
forbidOnly: true,
|
|
363
|
+
retries: 0,
|
|
364
|
+
workers: 1,
|
|
365
|
+
testDir: './local-e2e',
|
|
366
|
+
outputDir: './.ebk/evidence/local-browser-artifacts',
|
|
367
|
+
projects: [{ name: 'local-chromium', use: {
|
|
368
|
+
browserName: 'chromium',
|
|
369
|
+
ignoreHTTPSErrors: false,
|
|
370
|
+
serviceWorkers: 'block',
|
|
371
|
+
launchOptions: { args: localBrowserLaunchArguments(target) },
|
|
372
|
+
} }],
|
|
373
|
+
});
|
|
374
|
+
`,
|
|
375
|
+
'local-e2e/fixture.ts': `import { test as base, expect } from '@playwright/test';
|
|
376
|
+
import { resolve } from 'node:path';
|
|
377
|
+
import { localBrowserRequestAllowed, resolveLocalBrowserTarget } from '@empire-builder-kit/nx/local-dev';
|
|
378
|
+
export const target = await resolveLocalBrowserTarget({ workspaceRoot: resolve(import.meta.dirname, '../../..'), slice: '${name}' });
|
|
379
|
+
export const test = base.extend({
|
|
380
|
+
page: async ({ context }, use) => {
|
|
381
|
+
const page = await context.newPage();
|
|
382
|
+
const session = await context.newCDPSession(page);
|
|
383
|
+
// CDP checks every redirect hop. No process-wide certificate bypass is used.
|
|
384
|
+
session.on('Fetch.requestPaused', async ({ requestId, request }) => {
|
|
385
|
+
await session.send(localBrowserRequestAllowed(target.origin, request.url) ? 'Fetch.continueRequest' : 'Fetch.failRequest', {
|
|
386
|
+
requestId,
|
|
387
|
+
...(!localBrowserRequestAllowed(target.origin, request.url) ? { errorReason: 'BlockedByClient' } : {}),
|
|
388
|
+
}).catch(() => undefined);
|
|
389
|
+
});
|
|
390
|
+
await session.send('Fetch.enable', { patterns: [{ urlPattern: '*' }] });
|
|
391
|
+
await context.route('**/*', async (route) => {
|
|
392
|
+
let ownedPage = false;
|
|
393
|
+
try { ownedPage = route.request().frame().page() === page; } catch { /* Workers are outside this bounded proof. */ }
|
|
394
|
+
if (ownedPage && localBrowserRequestAllowed(target.origin, route.request().url())) await route.continue();
|
|
395
|
+
else await route.abort('blockedbyclient');
|
|
396
|
+
});
|
|
397
|
+
await context.routeWebSocket('**/*', (socket) => {
|
|
398
|
+
if (localBrowserRequestAllowed(target.origin, socket.url(), true)) socket.connectToServer();
|
|
399
|
+
else socket.close();
|
|
400
|
+
});
|
|
401
|
+
try { await use(page); } finally { await page.close(); await session.detach().catch(() => undefined); }
|
|
402
|
+
},
|
|
403
|
+
});
|
|
404
|
+
export { expect };
|
|
405
|
+
`,
|
|
406
|
+
'local-e2e/product.spec.ts': `import { expect, target, test } from './fixture';
|
|
407
|
+
test('proves the ready task-local web health', async ({ page }) => {
|
|
408
|
+
const response = await page.goto(new URL(target.healthPath, target.origin).href);
|
|
409
|
+
expect(response?.status()).toBe(200);
|
|
410
|
+
expect(response?.headers()['x-ebk-upstream']).toBe('local');
|
|
411
|
+
expect(response?.headers()['x-ebk-consumer-stage']).toBe(target.stage);
|
|
412
|
+
expect(await response?.json()).toMatchObject({ service: '${name}-web', stage: target.stage, status: 'ok' });
|
|
413
|
+
});
|
|
414
|
+
test('renders the Slice through its exact task HTTPS origin', async ({ page }) => {
|
|
415
|
+
const response = await page.goto(new URL(target.routePrefix, target.origin).href);
|
|
416
|
+
expect(response?.status()).toBe(200);
|
|
417
|
+
expect(response?.headers()['x-ebk-upstream']).toBe('local');
|
|
418
|
+
expect(new URL(page.url()).origin).toBe(target.origin);
|
|
419
|
+
await expect(page.getByRole('heading', { name: '${pascalName}', exact: true })).toBeVisible();
|
|
420
|
+
});
|
|
351
421
|
`,
|
|
352
422
|
'playwright.config.ts': `import { defineConfig } from '@playwright/test';
|
|
353
423
|
export default defineConfig({
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** @internal */
|
|
2
|
-
export declare function renderProductWebFiles(name: string, pascalName: string, workspace: string): Readonly<Record<string, string>>;
|
|
2
|
+
export declare function renderProductWebFiles(name: string, pascalName: string, workspace: string, sql?: boolean): Readonly<Record<string, string>>;
|
|
@@ -2,23 +2,32 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.renderProductWebFiles = renderProductWebFiles;
|
|
4
4
|
const built_in_plan_shared_js_1 = require("./built-in-plan-shared.js");
|
|
5
|
+
const sst_environment_source_format_js_1 = require("../../sst-environment-source-format.js");
|
|
5
6
|
/** @internal */
|
|
6
|
-
function renderProductWebFiles(name, pascalName, workspace) {
|
|
7
|
+
function renderProductWebFiles(name, pascalName, workspace, sql = false) {
|
|
7
8
|
return {
|
|
8
|
-
'web/next-env.d.ts':
|
|
9
|
-
/// <reference types="next/image-types/global" />
|
|
10
|
-
import "./.next/types/routes.d.ts";
|
|
11
|
-
|
|
12
|
-
// NOTE: This file should not be edited
|
|
13
|
-
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
|
14
|
-
`,
|
|
9
|
+
'web/next-env.d.ts': (0, sst_environment_source_format_js_1.generatedNextEnvironmentSource)(),
|
|
15
10
|
'web/tsconfig.json': (0, built_in_plan_shared_js_1.json)({
|
|
16
11
|
extends: '../tsconfig.json',
|
|
17
12
|
compilerOptions: {
|
|
13
|
+
// The workspace base is composite for project references; the web
|
|
14
|
+
// app is a leaf checked by Next's project-local tsc (16.3+), which
|
|
15
|
+
// enforces composite file lists and would reject the Slice imports
|
|
16
|
+
// outside web/ (TS6307).
|
|
17
|
+
composite: false,
|
|
18
18
|
incremental: true,
|
|
19
19
|
plugins: [{ name: 'next' }],
|
|
20
20
|
},
|
|
21
|
-
|
|
21
|
+
// Next 16.3 regenerates next-env.d.ts and rewrites tsconfig.json when
|
|
22
|
+
// these entries are missing; the generated files match its output so
|
|
23
|
+
// a build leaves the tracked workspace unchanged.
|
|
24
|
+
include: [
|
|
25
|
+
'next-env.d.ts',
|
|
26
|
+
'.next/types/**/*.ts',
|
|
27
|
+
'**/*.ts',
|
|
28
|
+
'**/*.tsx',
|
|
29
|
+
'.next/dev/types/**/*.ts',
|
|
30
|
+
],
|
|
22
31
|
exclude: ['node_modules'],
|
|
23
32
|
}),
|
|
24
33
|
'web/next.config.ts': `import type { NextConfig } from 'next';
|
|
@@ -39,8 +48,37 @@ function exactBuildId(): string {
|
|
|
39
48
|
|
|
40
49
|
const config: NextConfig = {
|
|
41
50
|
...(fleetOrigin ? { allowedDevOrigins: [new URL(fleetOrigin).hostname] } : {}),
|
|
51
|
+
// Generated Node ESM modules retain their .js/.cjs runtime specifiers;
|
|
52
|
+
// Webpack resolves those to the TypeScript source during Next dev/build.
|
|
53
|
+
experimental: { extensionAlias: { '.js': ['.ts', '.js'], '.cjs': ['.cts', '.cjs'] } },
|
|
42
54
|
basePath: '/${name}',
|
|
43
55
|
generateBuildId: async () => exactBuildId(),
|
|
56
|
+
async rewrites() {
|
|
57
|
+
if (!fleetOrigin || process.env.NODE_ENV !== 'development') return [];
|
|
58
|
+
const stage = process.env.EBK_STAGE;
|
|
59
|
+
if (!/^personal-[a-f0-9]{24}$/.test(stage ?? '') ||
|
|
60
|
+
process.env.EBK_CONSUMER_STAGE !== stage) {
|
|
61
|
+
throw new Error('Fleet Function routing requires the owned task stage. Restart with ebk dev up ${name}.');
|
|
62
|
+
}
|
|
63
|
+
// SST injects this Slice's API URL into its owned Next child. This is the
|
|
64
|
+
// current task API, not the optional deployed-development HTTP fallback.
|
|
65
|
+
const rawApiUrl = process.env.NEXT_PUBLIC_API_URL?.trim();
|
|
66
|
+
let apiUrl: URL;
|
|
67
|
+
try { apiUrl = new URL(rawApiUrl ?? ''); }
|
|
68
|
+
catch { throw new Error('Fleet Function routing requires the SST task API URL. Restart with ebk dev up ${name}.'); }
|
|
69
|
+
if (apiUrl.protocol !== 'https:' || apiUrl.username || apiUrl.password ||
|
|
70
|
+
apiUrl.port || apiUrl.pathname !== '/' || apiUrl.search || apiUrl.hash ||
|
|
71
|
+
!/^[a-z0-9]+\\.execute-api\\.[a-z0-9-]+\\.amazonaws\\.com(?:\\.cn)?$/.test(apiUrl.hostname)) {
|
|
72
|
+
throw new Error('Fleet Function routing requires the SST task API origin, without credentials or a path. Restart with ebk dev up ${name}.');
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
beforeFiles: [{
|
|
76
|
+
source: '/${name}/api/functions/:function',
|
|
77
|
+
destination: apiUrl.origin + '/functions/:function',
|
|
78
|
+
basePath: false,
|
|
79
|
+
}],
|
|
80
|
+
};
|
|
81
|
+
},
|
|
44
82
|
reactStrictMode: true,
|
|
45
83
|
};
|
|
46
84
|
|
|
@@ -94,12 +132,12 @@ export function proxy(request: NextRequest): NextResponse {
|
|
|
94
132
|
`,
|
|
95
133
|
'web/src/lib/server-logging.ts': `import 'server-only';
|
|
96
134
|
import { createLogger, type Logger } from '@empire-builder-kit/runtime/logging';
|
|
97
|
-
import { createNextServerContext } from '@empire-builder-kit/runtime/request-context';
|
|
135
|
+
import { createNextServerContext, type RequestContext } from '@empire-builder-kit/runtime/request-context';
|
|
98
136
|
import { recordReliabilityOperation } from '../../../reliability/metrics';
|
|
99
137
|
|
|
100
138
|
export interface ObserveNextOperationOptions {
|
|
101
139
|
feature: string;
|
|
102
|
-
handle(logger: Logger): Promise<Response> | Response;
|
|
140
|
+
handle(logger: Logger, context: RequestContext): Promise<Response> | Response;
|
|
103
141
|
operation: string;
|
|
104
142
|
request?: Request;
|
|
105
143
|
}
|
|
@@ -153,7 +191,7 @@ export async function observeNextOperation({
|
|
|
153
191
|
};
|
|
154
192
|
logger.info('${name} Next.js operation received');
|
|
155
193
|
try {
|
|
156
|
-
const response = await handle(logger);
|
|
194
|
+
const response = await handle(logger, context);
|
|
157
195
|
recordOutcome(response.status < 400 ? 'success' : 'failure');
|
|
158
196
|
logger.info('${name} Next.js operation completed', {
|
|
159
197
|
attributes: { httpStatus: response.status },
|
|
@@ -173,7 +211,7 @@ export async function observeNextOperation({
|
|
|
173
211
|
'web/open-next.config.ts': `const config = {
|
|
174
212
|
// OpenNext runs from this web directory. Point it at the slice package so it
|
|
175
213
|
// builds only this application instead of recursively invoking the Nx root.
|
|
176
|
-
buildCommand: 'pnpm exec next build web',
|
|
214
|
+
buildCommand: 'pnpm exec next build --webpack web',
|
|
177
215
|
default: {},
|
|
178
216
|
packageJsonPath: '../package.json',
|
|
179
217
|
};
|
|
@@ -210,7 +248,7 @@ export default async function Layout({ children }: Readonly<{ children: ReactNod
|
|
|
210
248
|
<p>Empire Builder Kit Product Slice</p>
|
|
211
249
|
<h1>${pascalName}</h1>
|
|
212
250
|
<div className="card">
|
|
213
|
-
<p>The web app, Lambda API,
|
|
251
|
+
<p>The web app, Lambda API, DynamoDB persistence${sql ? ', declared PostgreSQL database' : ''}, Cognito client,
|
|
214
252
|
event buffer/DLQ, dashboard, and alarms are wired and owned here.</p>
|
|
215
253
|
<a href="/${name}/sign-in">Sign in</a>
|
|
216
254
|
</div>
|
|
@@ -427,6 +465,160 @@ export async function GET(request: Request) {
|
|
|
427
465
|
},
|
|
428
466
|
});
|
|
429
467
|
}
|
|
468
|
+
`,
|
|
469
|
+
'web/src/lib/fleet-records.ts': `import 'server-only';
|
|
470
|
+
import { getSessionTokenCookieNames } from '@empire-builder-kit/runtime/auth-session';
|
|
471
|
+
import { extractBearerToken } from '@empire-builder-kit/runtime/auth-backend';
|
|
472
|
+
import { ApiContractError } from '@empire-builder-kit/runtime/api-contract';
|
|
473
|
+
import { createErrorResponse, createSuccessResponse, RuntimeError } from '@empire-builder-kit/runtime/response';
|
|
474
|
+
import type { Logger } from '@empire-builder-kit/runtime/logging';
|
|
475
|
+
import type { RequestContext } from '@empire-builder-kit/runtime/request-context';
|
|
476
|
+
import { cookies } from 'next/headers';
|
|
477
|
+
import { ${(0, built_in_plan_shared_js_1.lowerCamelIdentifier)(pascalName)}GetRecord, ${(0, built_in_plan_shared_js_1.lowerCamelIdentifier)(pascalName)}PutRecord } from '../../../api/contracts/protected';
|
|
478
|
+
import { authorize${pascalName}FleetRecordOperation } from '../../../authorization/runtime';
|
|
479
|
+
import { putRecordWithLifecycle } from '../../../data/record-correction';
|
|
480
|
+
import { getOwnedRecord } from '../../../data/records';
|
|
481
|
+
|
|
482
|
+
type RecordMethod = 'GET' | 'PUT';
|
|
483
|
+
const noStore = { 'cache-control': 'no-store' };
|
|
484
|
+
|
|
485
|
+
function fleetOrigin(request: Request): URL | null {
|
|
486
|
+
if (process.env.NODE_ENV !== 'development') return null;
|
|
487
|
+
const stage = process.env.EBK_STAGE;
|
|
488
|
+
if (!/^personal-[a-f0-9]{24}$/.test(stage ?? '') ||
|
|
489
|
+
process.env.EBK_CONSUMER_STAGE !== stage ||
|
|
490
|
+
process.env.EBK_SECURE_COOKIES !== 'true') return null;
|
|
491
|
+
try {
|
|
492
|
+
const raw = process.env.EBK_FLEET_ORIGIN ?? '';
|
|
493
|
+
const origin = new URL(raw);
|
|
494
|
+
const target = new URL(request.url);
|
|
495
|
+
const localPort = process.env.EBK_DEV_PORT ?? '';
|
|
496
|
+
const parsedLocalPort = Number(localPort);
|
|
497
|
+
if (origin.protocol !== 'https:' || origin.origin !== raw ||
|
|
498
|
+
origin.username || origin.password || origin.pathname !== '/' || origin.search || origin.hash ||
|
|
499
|
+
!(origin.hostname.endsWith('.ebk.localhost') || origin.hostname.endsWith('.test')) ||
|
|
500
|
+
!Number.isSafeInteger(parsedLocalPort) || parsedLocalPort < 1 || parsedLocalPort > 65535 ||
|
|
501
|
+
String(parsedLocalPort) !== localPort ||
|
|
502
|
+
target.protocol !== 'https:' ||
|
|
503
|
+
(target.hostname !== 'localhost' && target.hostname !== '127.0.0.1') ||
|
|
504
|
+
target.port !== localPort ||
|
|
505
|
+
target.username || target.password ||
|
|
506
|
+
request.headers.get('host') !== origin.host ||
|
|
507
|
+
request.headers.get('x-forwarded-host') !== origin.host ||
|
|
508
|
+
request.headers.get('x-forwarded-proto') !== 'https' ||
|
|
509
|
+
request.headers.get('x-forwarded-port') !== (origin.port || '443') ||
|
|
510
|
+
request.headers.get('x-forwarded-for') !== '127.0.0.1') return null;
|
|
511
|
+
const suppliedOrigin = request.headers.get('origin');
|
|
512
|
+
if (suppliedOrigin !== null && suppliedOrigin !== origin.origin) return null;
|
|
513
|
+
return origin;
|
|
514
|
+
} catch {
|
|
515
|
+
return null;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
async function boundedBody(request: Request, maxBytes: number): Promise<unknown> {
|
|
520
|
+
if (request.headers.get('content-type')?.split(';', 1)[0]?.trim().toLowerCase() !== 'application/json')
|
|
521
|
+
throw new RuntimeError({ code: 'invalid_request', message: 'JSON request body is required.', status: 400 });
|
|
522
|
+
const reader = request.body?.getReader();
|
|
523
|
+
if (!reader) throw new RuntimeError({ code: 'invalid_request', message: 'JSON request body is required.', status: 400 });
|
|
524
|
+
const chunks: Uint8Array[] = [];
|
|
525
|
+
let length = 0;
|
|
526
|
+
try {
|
|
527
|
+
for (;;) {
|
|
528
|
+
const { done, value } = await reader.read();
|
|
529
|
+
if (done) break;
|
|
530
|
+
length += value.byteLength;
|
|
531
|
+
if (length > maxBytes) throw new RuntimeError({ code: 'invalid_request', message: 'Request body is too large.', status: 400 });
|
|
532
|
+
chunks.push(value);
|
|
533
|
+
}
|
|
534
|
+
} finally {
|
|
535
|
+
reader.releaseLock();
|
|
536
|
+
}
|
|
537
|
+
try {
|
|
538
|
+
return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(Buffer.concat(chunks)));
|
|
539
|
+
} catch {
|
|
540
|
+
throw new RuntimeError({ code: 'invalid_request', message: 'JSON request body is invalid.', status: 400 });
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
async function accessToken(request: Request): Promise<{ token: string | null; cookie: boolean }> {
|
|
545
|
+
if (request.headers.has('authorization'))
|
|
546
|
+
return { token: extractBearerToken(request.headers.get('authorization') ?? undefined), cookie: false };
|
|
547
|
+
const store = await cookies();
|
|
548
|
+
const names = getSessionTokenCookieNames({ namespace: '${name}', secure: true });
|
|
549
|
+
return { token: store.get(names.access)?.value ?? null, cookie: true };
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/** Only the owned task's Next server exposes a native record path. */
|
|
553
|
+
export async function handleFleetRecord(request: Request, recordId: string, method: RecordMethod,
|
|
554
|
+
logger: Logger, context: RequestContext): Promise<Response> {
|
|
555
|
+
const origin = fleetOrigin(request);
|
|
556
|
+
if (!origin || request.method !== method)
|
|
557
|
+
return Response.json(createErrorResponse(new RuntimeError({ code: 'record_not_found',
|
|
558
|
+
message: 'The record route is unavailable.', status: 404 })), { status: 404, headers: noStore });
|
|
559
|
+
try {
|
|
560
|
+
const auth = await accessToken(request);
|
|
561
|
+
// Cookie-backed writes require the browser's exact same-origin proof.
|
|
562
|
+
if (method === 'PUT' && auth.cookie && request.headers.get('origin') !== origin.origin)
|
|
563
|
+
throw new RuntimeError({ code: 'authorization_denied', message: 'Same-origin authorization is required.', status: 403 });
|
|
564
|
+
if (method === 'PUT') {
|
|
565
|
+
const operation = ${(0, built_in_plan_shared_js_1.lowerCamelIdentifier)(pascalName)}PutRecord;
|
|
566
|
+
const path = operation.request.path.parse({ recordId }, 'request.path');
|
|
567
|
+
const body = operation.request.body.parse(
|
|
568
|
+
await boundedBody(request, operation.request.maxBodyBytes ?? 512), 'request.body');
|
|
569
|
+
const principal = await authorize${pascalName}FleetRecordOperation({
|
|
570
|
+
accessToken: auth.token, context, logger, operation, request: { path, body },
|
|
571
|
+
});
|
|
572
|
+
const value = await putRecordWithLifecycle({ correlationId: context.correlationId, principal,
|
|
573
|
+
recordId: path.recordId, name: body.name, runScope: body.runScope,
|
|
574
|
+
testExpiresAt: body.testExpiresAt });
|
|
575
|
+
const projected = operation.response.body.project({
|
|
576
|
+
id: value.id, name: value.name, runScope: value.runScope,
|
|
577
|
+
}, 'response.data');
|
|
578
|
+
return Response.json(createSuccessResponse(projected, { status: operation.response.status }),
|
|
579
|
+
{ status: operation.response.status, headers: noStore });
|
|
580
|
+
}
|
|
581
|
+
const operation = ${(0, built_in_plan_shared_js_1.lowerCamelIdentifier)(pascalName)}GetRecord;
|
|
582
|
+
if (request.body !== null)
|
|
583
|
+
throw new RuntimeError({ code: 'invalid_request', message: 'GET does not accept a body.', status: 400 });
|
|
584
|
+
const path = operation.request.path.parse({ recordId }, 'request.path');
|
|
585
|
+
const principal = await authorize${pascalName}FleetRecordOperation({
|
|
586
|
+
accessToken: auth.token, context, logger, operation, request: { path },
|
|
587
|
+
});
|
|
588
|
+
const record = await getOwnedRecord(path.recordId, principal.actor.id);
|
|
589
|
+
if (!record) throw new RuntimeError({ code: 'record_not_found',
|
|
590
|
+
message: 'The record was not found.', status: 404 });
|
|
591
|
+
const projected = operation.response.body.project({
|
|
592
|
+
id: record.id, name: record.name, runScope: record.runScope,
|
|
593
|
+
}, 'response.data');
|
|
594
|
+
return Response.json(createSuccessResponse(projected, { status: operation.response.status }),
|
|
595
|
+
{ status: operation.response.status, headers: noStore });
|
|
596
|
+
} catch (error) {
|
|
597
|
+
const normalized = error instanceof ApiContractError &&
|
|
598
|
+
error.classification === 'api-schema-validation-failed'
|
|
599
|
+
? new RuntimeError({ code: 'invalid_request',
|
|
600
|
+
message: 'The request does not satisfy the record contract.', status: 400 })
|
|
601
|
+
: error;
|
|
602
|
+
const response = createErrorResponse(normalized);
|
|
603
|
+
return Response.json(response, { status: response.status, headers: noStore });
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
`,
|
|
607
|
+
'web/src/app/api/records/[recordId]/route.ts': `import 'server-only';
|
|
608
|
+
import { observeNextOperation } from '../../../../lib/server-logging';
|
|
609
|
+
import { handleFleetRecord } from '../../../../lib/fleet-records';
|
|
610
|
+
|
|
611
|
+
type RecordRouteContext = { params: Promise<{ recordId: string }> };
|
|
612
|
+
|
|
613
|
+
export async function GET(request: Request, route: RecordRouteContext) {
|
|
614
|
+
return observeNextOperation({ feature: 'database', operation: 'get-record', request,
|
|
615
|
+
handle: async (logger, context) => handleFleetRecord(request, (await route.params).recordId, 'GET', logger, context) });
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
export async function PUT(request: Request, route: RecordRouteContext) {
|
|
619
|
+
return observeNextOperation({ feature: 'database', operation: 'put-record', request,
|
|
620
|
+
handle: async (logger, context) => handleFleetRecord(request, (await route.params).recordId, 'PUT', logger, context) });
|
|
621
|
+
}
|
|
430
622
|
`,
|
|
431
623
|
'web/src/app/page.spec.tsx': `import { renderToStaticMarkup } from 'react-dom/server';
|
|
432
624
|
import { describe, expect, it } from 'vitest';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** @internal */
|
|
2
|
-
export declare function renderStandardSliceWorkloadRoleFiles(name: string, workspace: string): Readonly<Record<string, string>>;
|
|
2
|
+
export declare function renderStandardSliceWorkloadRoleFiles(name: string, workspace: string, sql?: boolean): Readonly<Record<string, string>>;
|