@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
|
@@ -4,6 +4,7 @@ exports.PRODUCT_PERFORMANCE_SEEDED_PATHS = void 0;
|
|
|
4
4
|
exports.renderProductPerformanceFiles = renderProductPerformanceFiles;
|
|
5
5
|
const built_in_plan_shared_js_1 = require("./built-in-plan-shared.js");
|
|
6
6
|
const index_js_1 = require("../../performance/index.js");
|
|
7
|
+
const built_in_plan_key_value_performance_js_1 = require("./built-in-plan-key-value-performance.js");
|
|
7
8
|
exports.PRODUCT_PERFORMANCE_SEEDED_PATHS = [
|
|
8
9
|
'docs/runbooks/performance-capacity-cost.md',
|
|
9
10
|
'performance/aggregate-count-provider.ts',
|
|
@@ -14,6 +15,10 @@ exports.PRODUCT_PERFORMANCE_SEEDED_PATHS = [
|
|
|
14
15
|
];
|
|
15
16
|
/** @internal */
|
|
16
17
|
function renderProductPerformanceFiles(name, deploymentProfile = 'starter') {
|
|
18
|
+
const databaseAdapter = 'ebk-dynamodb-v1';
|
|
19
|
+
const asyncAdapter = 'ebk-dynamodb-async-v1';
|
|
20
|
+
const databaseSignal = 'dynamodb:protected-request-budget-utilization-percent';
|
|
21
|
+
const asyncSignal = 'dynamodb:protected-run-unprocessed-effects-percent';
|
|
17
22
|
const pascalName = name
|
|
18
23
|
.split('-')
|
|
19
24
|
.map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)
|
|
@@ -230,19 +235,19 @@ export function create${pascalName}PerformanceCostControls(input: {
|
|
|
230
235
|
kind: 'async-worker',
|
|
231
236
|
protectionRef: 'control:async-worker-concurrency',
|
|
232
237
|
quotaMaximum: null,
|
|
233
|
-
saturationSignalRef:
|
|
238
|
+
saturationSignalRef: asyncSignal,
|
|
234
239
|
status: 'requires-adopter-value',
|
|
235
240
|
},
|
|
236
241
|
{
|
|
237
|
-
capacityUnit: '
|
|
242
|
+
capacityUnit: 'concurrent-requests',
|
|
238
243
|
configuredMaximum: null,
|
|
239
244
|
downstreamMaximum: null,
|
|
240
|
-
failureMode: '
|
|
245
|
+
failureMode: 'request-latency-or-throttling',
|
|
241
246
|
id: 'database',
|
|
242
247
|
kind: 'database',
|
|
243
|
-
protectionRef: 'control:database-
|
|
248
|
+
protectionRef: 'control:database-request-concurrency',
|
|
244
249
|
quotaMaximum: null,
|
|
245
|
-
saturationSignalRef:
|
|
250
|
+
saturationSignalRef: databaseSignal,
|
|
246
251
|
status: 'requires-adopter-value',
|
|
247
252
|
},
|
|
248
253
|
{
|
|
@@ -319,22 +324,22 @@ export function create${pascalName}PerformanceCostControls(input: {
|
|
|
319
324
|
},
|
|
320
325
|
{
|
|
321
326
|
adapterStatus: 'managed',
|
|
322
|
-
adapterId:
|
|
327
|
+
adapterId: asyncAdapter,
|
|
323
328
|
demandShape: 'bounded-flash-burst-and-recovery',
|
|
324
329
|
disabledUntilAdopted: true,
|
|
325
330
|
estimatedCostUsdPerRequest: 0.00002,
|
|
326
|
-
id: 'async-burst',
|
|
327
|
-
saturationSignalRef:
|
|
331
|
+
id: 'async-key-value-burst',
|
|
332
|
+
saturationSignalRef: asyncSignal,
|
|
328
333
|
workload: 'async-worker',
|
|
329
334
|
},
|
|
330
335
|
{
|
|
331
336
|
adapterStatus: 'managed',
|
|
332
|
-
adapterId:
|
|
333
|
-
demandShape: '
|
|
337
|
+
adapterId: databaseAdapter,
|
|
338
|
+
demandShape: 'bounded-write-and-consistent-read',
|
|
334
339
|
disabledUntilAdopted: true,
|
|
335
340
|
estimatedCostUsdPerRequest: 0.0001,
|
|
336
|
-
id: 'database-
|
|
337
|
-
saturationSignalRef:
|
|
341
|
+
id: 'database-read-write',
|
|
342
|
+
saturationSignalRef: databaseSignal,
|
|
338
343
|
workload: 'database',
|
|
339
344
|
},
|
|
340
345
|
{
|
|
@@ -443,7 +448,7 @@ export function create${pascalName}PerformanceCostControls(input: {
|
|
|
443
448
|
accountBudgetAndAnomalyRoute: 'required-pre-v1',
|
|
444
449
|
actualBillingAndTwoUnitCosts: 'required-pre-v1',
|
|
445
450
|
coldAndWarmLambdaNextPaths: 'required-pre-v1',
|
|
446
|
-
databaseColdResumeAndIdleCost: '
|
|
451
|
+
databaseColdResumeAndIdleCost: 'not-applicable-without-sql',
|
|
447
452
|
profileTransitionRehearsal: 'required-pre-v1',
|
|
448
453
|
protectedApiAsyncDatabaseLoad: 'required-pre-v1',
|
|
449
454
|
serviceRuntimeLoad: 'required-pre-v1-adopter-integration',
|
|
@@ -452,8 +457,8 @@ export function create${pascalName}PerformanceCostControls(input: {
|
|
|
452
457
|
load: {
|
|
453
458
|
allowlistedScenarioAdapters: [
|
|
454
459
|
'ebk-api-lambda-v1',
|
|
455
|
-
|
|
456
|
-
|
|
460
|
+
asyncAdapter,
|
|
461
|
+
databaseAdapter,
|
|
457
462
|
],
|
|
458
463
|
localProtectedMutationForbidden: true,
|
|
459
464
|
productionExceptionalOnly: true,
|
|
@@ -1898,18 +1903,15 @@ import {
|
|
|
1898
1903
|
handleProtectedLoadCleanupEndpoint,
|
|
1899
1904
|
handleProtectedLoadScenarioEndpoint,
|
|
1900
1905
|
type ProtectedLoadEndpointBindingV1,
|
|
1901
|
-
type ProtectedLoadEndpointAdapterId,
|
|
1902
1906
|
type ProtectedLoadRequestAuthorizationV1,
|
|
1907
|
+
${' DYNAMODB_PROTECTED_REQUEST_BUDGET_MS,\n'}\
|
|
1903
1908
|
} from '@empire-builder-kit/runtime/performance';
|
|
1904
|
-
import {
|
|
1905
|
-
import {
|
|
1909
|
+
${`import { dataStore } from '../../../../../data/key-value';
|
|
1910
|
+
import { createPerformancePersistence } from '../../../../../performance/persistence';`}
|
|
1906
1911
|
import { Secrets } from '../../../../../secrets/declarations';
|
|
1907
1912
|
import { createStandardSliceSecretRuntime } from '../../../../../secrets/runtime';
|
|
1908
1913
|
|
|
1909
|
-
type ManagedAdapterId =
|
|
1910
|
-
ProtectedLoadEndpointAdapterId,
|
|
1911
|
-
'ebk-service-v1'
|
|
1912
|
-
>;
|
|
1914
|
+
type ManagedAdapterId = 'ebk-api-lambda-v1' | '${asyncAdapter}' | '${databaseAdapter}';
|
|
1913
1915
|
|
|
1914
1916
|
function required(name: string): string {
|
|
1915
1917
|
const value = process.env[name]?.trim();
|
|
@@ -2047,396 +2049,7 @@ function memorySaturation(): number {
|
|
|
2047
2049
|
return Math.min(100, (memory.heapUsed / memory.heapTotal) * 100);
|
|
2048
2050
|
}
|
|
2049
2051
|
|
|
2050
|
-
|
|
2051
|
-
return [
|
|
2052
|
-
effectId.slice(0, 8),
|
|
2053
|
-
effectId.slice(8, 12),
|
|
2054
|
-
'4' + effectId.slice(13, 16),
|
|
2055
|
-
'8' + effectId.slice(17, 20),
|
|
2056
|
-
effectId.slice(20, 32),
|
|
2057
|
-
].join('-');
|
|
2058
|
-
}
|
|
2059
|
-
|
|
2060
|
-
interface ProtectedPerformanceRunRow {
|
|
2061
|
-
adapterId: string;
|
|
2062
|
-
cleanupStartedAt: Date | null;
|
|
2063
|
-
createdAt: Date;
|
|
2064
|
-
expiresAt: Date;
|
|
2065
|
-
maximumRequests: number;
|
|
2066
|
-
releaseMaterialDigest: string;
|
|
2067
|
-
runId: string;
|
|
2068
|
-
scenarioId: string;
|
|
2069
|
-
sourceCommit: string;
|
|
2070
|
-
stage: string;
|
|
2071
|
-
}
|
|
2072
|
-
|
|
2073
|
-
function matchesProtectedPerformanceRun(
|
|
2074
|
-
actual: ProtectedPerformanceRunRow | undefined,
|
|
2075
|
-
authorization: ProtectedLoadRequestAuthorizationV1,
|
|
2076
|
-
): actual is ProtectedPerformanceRunRow {
|
|
2077
|
-
return (
|
|
2078
|
-
actual !== undefined &&
|
|
2079
|
-
actual.adapterId === authorization.adapterId &&
|
|
2080
|
-
actual.createdAt.toISOString() === authorization.createdAt &&
|
|
2081
|
-
actual.expiresAt.toISOString() === authorization.expiresAt &&
|
|
2082
|
-
actual.maximumRequests === authorization.maximumRequests &&
|
|
2083
|
-
actual.releaseMaterialDigest ===
|
|
2084
|
-
authorization.release.releaseMaterialDigest &&
|
|
2085
|
-
actual.runId === authorization.runId &&
|
|
2086
|
-
actual.scenarioId === authorization.scenarioId &&
|
|
2087
|
-
actual.sourceCommit === authorization.release.sourceCommit &&
|
|
2088
|
-
actual.stage === authorization.stage
|
|
2089
|
-
);
|
|
2090
|
-
}
|
|
2091
|
-
|
|
2092
|
-
export async function reserveRequest(
|
|
2093
|
-
authorization: ProtectedLoadRequestAuthorizationV1,
|
|
2094
|
-
) {
|
|
2095
|
-
return withPrimaryDatabase(
|
|
2096
|
-
{ correlationId: randomUUID() },
|
|
2097
|
-
'web-server',
|
|
2098
|
-
async (client) => {
|
|
2099
|
-
await client.query('BEGIN');
|
|
2100
|
-
try {
|
|
2101
|
-
await client.query(
|
|
2102
|
-
\`INSERT INTO performance_load_runs
|
|
2103
|
-
(plan_digest, run_id, adapter_id, scenario_id, stage,
|
|
2104
|
-
source_commit, release_material_digest, maximum_requests,
|
|
2105
|
-
created_at, expires_at)
|
|
2106
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::timestamptz,
|
|
2107
|
-
$10::timestamptz)
|
|
2108
|
-
ON CONFLICT (plan_digest) DO NOTHING\`,
|
|
2109
|
-
[
|
|
2110
|
-
authorization.planMaterialDigest,
|
|
2111
|
-
authorization.runId,
|
|
2112
|
-
authorization.adapterId,
|
|
2113
|
-
authorization.scenarioId,
|
|
2114
|
-
authorization.stage,
|
|
2115
|
-
authorization.release.sourceCommit,
|
|
2116
|
-
authorization.release.releaseMaterialDigest,
|
|
2117
|
-
authorization.maximumRequests,
|
|
2118
|
-
authorization.createdAt,
|
|
2119
|
-
authorization.expiresAt,
|
|
2120
|
-
],
|
|
2121
|
-
);
|
|
2122
|
-
const run = await client.query<ProtectedPerformanceRunRow>(
|
|
2123
|
-
\`SELECT
|
|
2124
|
-
adapter_id AS "adapterId",
|
|
2125
|
-
cleanup_started_at AS "cleanupStartedAt",
|
|
2126
|
-
created_at AS "createdAt",
|
|
2127
|
-
expires_at AS "expiresAt",
|
|
2128
|
-
maximum_requests AS "maximumRequests",
|
|
2129
|
-
release_material_digest AS "releaseMaterialDigest",
|
|
2130
|
-
run_id AS "runId",
|
|
2131
|
-
scenario_id AS "scenarioId",
|
|
2132
|
-
source_commit AS "sourceCommit",
|
|
2133
|
-
stage
|
|
2134
|
-
FROM performance_load_runs
|
|
2135
|
-
WHERE plan_digest = $1
|
|
2136
|
-
FOR UPDATE\`,
|
|
2137
|
-
[authorization.planMaterialDigest],
|
|
2138
|
-
);
|
|
2139
|
-
const actual = run.rows[0];
|
|
2140
|
-
if (
|
|
2141
|
-
!matchesProtectedPerformanceRun(actual, authorization) ||
|
|
2142
|
-
actual.cleanupStartedAt !== null
|
|
2143
|
-
) {
|
|
2144
|
-
throw new Error('protected-performance-run-collision');
|
|
2145
|
-
}
|
|
2146
|
-
const claimed = await client.query(
|
|
2147
|
-
\`INSERT INTO performance_load_requests
|
|
2148
|
-
(plan_digest, request_ordinal, effect_id)
|
|
2149
|
-
VALUES ($1, $2, $3)
|
|
2150
|
-
ON CONFLICT (plan_digest, request_ordinal) DO NOTHING\`,
|
|
2151
|
-
[
|
|
2152
|
-
authorization.planMaterialDigest,
|
|
2153
|
-
authorization.requestOrdinal,
|
|
2154
|
-
authorization.effectId,
|
|
2155
|
-
],
|
|
2156
|
-
);
|
|
2157
|
-
if (claimed.rowCount !== 1) {
|
|
2158
|
-
throw new Error('protected-performance-request-replayed');
|
|
2159
|
-
}
|
|
2160
|
-
await client.query('COMMIT');
|
|
2161
|
-
return 'claimed' as const;
|
|
2162
|
-
} catch (error) {
|
|
2163
|
-
await client.query('ROLLBACK').catch(() => undefined);
|
|
2164
|
-
throw error;
|
|
2165
|
-
}
|
|
2166
|
-
},
|
|
2167
|
-
);
|
|
2168
|
-
}
|
|
2169
|
-
|
|
2170
|
-
export async function databaseExecution(
|
|
2171
|
-
adapterId: 'ebk-async-worker-v1' | 'ebk-database-v1',
|
|
2172
|
-
effectId: string,
|
|
2173
|
-
authorization: ProtectedLoadRequestAuthorizationV1,
|
|
2174
|
-
) {
|
|
2175
|
-
return withPrimaryDatabase(
|
|
2176
|
-
{ correlationId: randomUUID() },
|
|
2177
|
-
'web-server',
|
|
2178
|
-
async (client) => {
|
|
2179
|
-
await client.query('BEGIN');
|
|
2180
|
-
try {
|
|
2181
|
-
const run = await client.query<ProtectedPerformanceRunRow>(
|
|
2182
|
-
\`SELECT
|
|
2183
|
-
adapter_id AS "adapterId",
|
|
2184
|
-
cleanup_started_at AS "cleanupStartedAt",
|
|
2185
|
-
created_at AS "createdAt",
|
|
2186
|
-
expires_at AS "expiresAt",
|
|
2187
|
-
maximum_requests AS "maximumRequests",
|
|
2188
|
-
release_material_digest AS "releaseMaterialDigest",
|
|
2189
|
-
run_id AS "runId",
|
|
2190
|
-
scenario_id AS "scenarioId",
|
|
2191
|
-
source_commit AS "sourceCommit",
|
|
2192
|
-
stage
|
|
2193
|
-
FROM performance_load_runs
|
|
2194
|
-
WHERE plan_digest = $1
|
|
2195
|
-
FOR UPDATE\`,
|
|
2196
|
-
[authorization.planMaterialDigest],
|
|
2197
|
-
);
|
|
2198
|
-
const activeRun = run.rows[0];
|
|
2199
|
-
if (
|
|
2200
|
-
!matchesProtectedPerformanceRun(activeRun, authorization) ||
|
|
2201
|
-
activeRun.cleanupStartedAt !== null
|
|
2202
|
-
) {
|
|
2203
|
-
throw new Error('protected-performance-run-cleaning');
|
|
2204
|
-
}
|
|
2205
|
-
if (adapterId === 'ebk-async-worker-v1') {
|
|
2206
|
-
const inserted = await client.query(
|
|
2207
|
-
\`INSERT INTO performance_load_async_effects
|
|
2208
|
-
(effect_id, plan_digest, run_id, expires_at)
|
|
2209
|
-
VALUES ($1, $2, $3, now() + INTERVAL '24 hours')
|
|
2210
|
-
ON CONFLICT (effect_id) DO NOTHING\`,
|
|
2211
|
-
[
|
|
2212
|
-
effectId,
|
|
2213
|
-
authorization.planMaterialDigest,
|
|
2214
|
-
authorization.runId,
|
|
2215
|
-
],
|
|
2216
|
-
);
|
|
2217
|
-
const identity = await client.query<{
|
|
2218
|
-
planDigest: string;
|
|
2219
|
-
runId: string;
|
|
2220
|
-
}>(
|
|
2221
|
-
\`SELECT
|
|
2222
|
-
plan_digest AS "planDigest",
|
|
2223
|
-
run_id AS "runId"
|
|
2224
|
-
FROM performance_load_async_effects
|
|
2225
|
-
WHERE effect_id = $1\`,
|
|
2226
|
-
[effectId],
|
|
2227
|
-
);
|
|
2228
|
-
if (
|
|
2229
|
-
identity.rows[0]?.planDigest !==
|
|
2230
|
-
authorization.planMaterialDigest ||
|
|
2231
|
-
identity.rows[0]?.runId !== authorization.runId
|
|
2232
|
-
) {
|
|
2233
|
-
throw new Error('protected-performance-effect-collision');
|
|
2234
|
-
}
|
|
2235
|
-
const pending = await client.query<{ count: string }>(
|
|
2236
|
-
\`SELECT count(*)::text AS count
|
|
2237
|
-
FROM performance_load_async_effects
|
|
2238
|
-
WHERE processed_at IS NULL AND expires_at > now()\`,
|
|
2239
|
-
);
|
|
2240
|
-
const maximum = authorization.configuredMaximum;
|
|
2241
|
-
if (!Number.isFinite(maximum) || maximum <= 0) {
|
|
2242
|
-
throw new Error('protected-performance-async-maximum-invalid');
|
|
2243
|
-
}
|
|
2244
|
-
const result = {
|
|
2245
|
-
effectState:
|
|
2246
|
-
inserted.rowCount === 1
|
|
2247
|
-
? ('created' as const)
|
|
2248
|
-
: ('already-existed' as const),
|
|
2249
|
-
saturationPercent: Math.min(
|
|
2250
|
-
100,
|
|
2251
|
-
(Number(pending.rows[0]?.count ?? 0) / maximum) * 100,
|
|
2252
|
-
),
|
|
2253
|
-
};
|
|
2254
|
-
await client.query('COMMIT');
|
|
2255
|
-
return result;
|
|
2256
|
-
}
|
|
2257
|
-
const id = effectUuid(effectId);
|
|
2258
|
-
const inserted = await client.query(
|
|
2259
|
-
\`INSERT INTO records
|
|
2260
|
-
(id, name, owner_id, run_scope, test_expires_at)
|
|
2261
|
-
VALUES (
|
|
2262
|
-
$1::uuid,
|
|
2263
|
-
'ebk-protected-performance-load',
|
|
2264
|
-
'ebk-performance',
|
|
2265
|
-
$2,
|
|
2266
|
-
now() + INTERVAL '24 hours'
|
|
2267
|
-
)
|
|
2268
|
-
ON CONFLICT (id) DO NOTHING\`,
|
|
2269
|
-
[id, authorization.planMaterialDigest],
|
|
2270
|
-
);
|
|
2271
|
-
const identity = await client.query<{
|
|
2272
|
-
name: string;
|
|
2273
|
-
ownerId: string;
|
|
2274
|
-
runScope: string;
|
|
2275
|
-
}>(
|
|
2276
|
-
\`SELECT
|
|
2277
|
-
name,
|
|
2278
|
-
owner_id AS "ownerId",
|
|
2279
|
-
run_scope AS "runScope"
|
|
2280
|
-
FROM records
|
|
2281
|
-
WHERE id = $1::uuid\`,
|
|
2282
|
-
[id],
|
|
2283
|
-
);
|
|
2284
|
-
if (
|
|
2285
|
-
identity.rows[0]?.name !== 'ebk-protected-performance-load' ||
|
|
2286
|
-
identity.rows[0]?.ownerId !== 'ebk-performance' ||
|
|
2287
|
-
identity.rows[0]?.runScope !== authorization.planMaterialDigest
|
|
2288
|
-
) {
|
|
2289
|
-
throw new Error('protected-performance-effect-collision');
|
|
2290
|
-
}
|
|
2291
|
-
const activity = await client.query<{
|
|
2292
|
-
active: string;
|
|
2293
|
-
maximum: string;
|
|
2294
|
-
}>(
|
|
2295
|
-
\`SELECT
|
|
2296
|
-
count(*)::text AS active,
|
|
2297
|
-
current_setting('max_connections') AS maximum
|
|
2298
|
-
FROM pg_stat_activity
|
|
2299
|
-
WHERE datname = current_database()\`,
|
|
2300
|
-
);
|
|
2301
|
-
const active = Number(activity.rows[0]?.active ?? 0);
|
|
2302
|
-
const maximum = Number(activity.rows[0]?.maximum ?? 0);
|
|
2303
|
-
if (!Number.isFinite(maximum) || maximum <= 0) {
|
|
2304
|
-
throw new Error('protected-performance-database-maximum-invalid');
|
|
2305
|
-
}
|
|
2306
|
-
const result = {
|
|
2307
|
-
effectState:
|
|
2308
|
-
inserted.rowCount === 1
|
|
2309
|
-
? ('created' as const)
|
|
2310
|
-
: ('already-existed' as const),
|
|
2311
|
-
saturationPercent: Math.min(100, (active / maximum) * 100),
|
|
2312
|
-
};
|
|
2313
|
-
await client.query('COMMIT');
|
|
2314
|
-
return result;
|
|
2315
|
-
} catch (error) {
|
|
2316
|
-
await client.query('ROLLBACK').catch(() => undefined);
|
|
2317
|
-
throw error;
|
|
2318
|
-
}
|
|
2319
|
-
},
|
|
2320
|
-
);
|
|
2321
|
-
}
|
|
2322
|
-
|
|
2323
|
-
export async function cleanupRun(
|
|
2324
|
-
adapterId: 'ebk-async-worker-v1' | 'ebk-database-v1',
|
|
2325
|
-
authorization: ProtectedLoadRequestAuthorizationV1,
|
|
2326
|
-
) {
|
|
2327
|
-
return withPrimaryDatabase(
|
|
2328
|
-
{ correlationId: randomUUID() },
|
|
2329
|
-
'web-server',
|
|
2330
|
-
async (client) => {
|
|
2331
|
-
await client.query('BEGIN');
|
|
2332
|
-
try {
|
|
2333
|
-
await client.query(
|
|
2334
|
-
\`INSERT INTO performance_load_runs
|
|
2335
|
-
(plan_digest, run_id, adapter_id, scenario_id, stage,
|
|
2336
|
-
source_commit, release_material_digest, maximum_requests,
|
|
2337
|
-
created_at, expires_at, cleanup_started_at)
|
|
2338
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::timestamptz,
|
|
2339
|
-
$10::timestamptz, now())
|
|
2340
|
-
ON CONFLICT (plan_digest) DO NOTHING\`,
|
|
2341
|
-
[
|
|
2342
|
-
authorization.planMaterialDigest,
|
|
2343
|
-
authorization.runId,
|
|
2344
|
-
authorization.adapterId,
|
|
2345
|
-
authorization.scenarioId,
|
|
2346
|
-
authorization.stage,
|
|
2347
|
-
authorization.release.sourceCommit,
|
|
2348
|
-
authorization.release.releaseMaterialDigest,
|
|
2349
|
-
authorization.maximumRequests,
|
|
2350
|
-
authorization.createdAt,
|
|
2351
|
-
authorization.expiresAt,
|
|
2352
|
-
],
|
|
2353
|
-
);
|
|
2354
|
-
const run = await client.query<ProtectedPerformanceRunRow>(
|
|
2355
|
-
\`SELECT
|
|
2356
|
-
adapter_id AS "adapterId",
|
|
2357
|
-
cleanup_started_at AS "cleanupStartedAt",
|
|
2358
|
-
created_at AS "createdAt",
|
|
2359
|
-
expires_at AS "expiresAt",
|
|
2360
|
-
maximum_requests AS "maximumRequests",
|
|
2361
|
-
release_material_digest AS "releaseMaterialDigest",
|
|
2362
|
-
run_id AS "runId",
|
|
2363
|
-
scenario_id AS "scenarioId",
|
|
2364
|
-
source_commit AS "sourceCommit",
|
|
2365
|
-
stage
|
|
2366
|
-
FROM performance_load_runs
|
|
2367
|
-
WHERE plan_digest = $1
|
|
2368
|
-
FOR UPDATE\`,
|
|
2369
|
-
[authorization.planMaterialDigest],
|
|
2370
|
-
);
|
|
2371
|
-
if (!matchesProtectedPerformanceRun(run.rows[0], authorization)) {
|
|
2372
|
-
throw new Error('protected-performance-run-collision');
|
|
2373
|
-
}
|
|
2374
|
-
await client.query(
|
|
2375
|
-
\`UPDATE performance_load_runs
|
|
2376
|
-
SET cleanup_started_at = COALESCE(cleanup_started_at, now())
|
|
2377
|
-
WHERE plan_digest = $1\`,
|
|
2378
|
-
[authorization.planMaterialDigest],
|
|
2379
|
-
);
|
|
2380
|
-
await client.query('COMMIT');
|
|
2381
|
-
} catch (error) {
|
|
2382
|
-
await client.query('ROLLBACK').catch(() => undefined);
|
|
2383
|
-
throw error;
|
|
2384
|
-
}
|
|
2385
|
-
|
|
2386
|
-
await client.query('BEGIN');
|
|
2387
|
-
try {
|
|
2388
|
-
const removed =
|
|
2389
|
-
adapterId === 'ebk-async-worker-v1'
|
|
2390
|
-
? await client.query(
|
|
2391
|
-
\`DELETE FROM performance_load_async_effects
|
|
2392
|
-
WHERE plan_digest = $1
|
|
2393
|
-
AND run_id = $2\`,
|
|
2394
|
-
[authorization.planMaterialDigest, authorization.runId],
|
|
2395
|
-
)
|
|
2396
|
-
: await client.query(
|
|
2397
|
-
\`DELETE FROM records
|
|
2398
|
-
WHERE owner_id = 'ebk-performance'
|
|
2399
|
-
AND name = 'ebk-protected-performance-load'
|
|
2400
|
-
AND run_scope = $1\`,
|
|
2401
|
-
[authorization.planMaterialDigest],
|
|
2402
|
-
);
|
|
2403
|
-
const remaining =
|
|
2404
|
-
adapterId === 'ebk-async-worker-v1'
|
|
2405
|
-
? await client.query<{ count: string }>(
|
|
2406
|
-
\`SELECT count(*)::text AS count
|
|
2407
|
-
FROM performance_load_async_effects
|
|
2408
|
-
WHERE plan_digest = $1
|
|
2409
|
-
AND run_id = $2\`,
|
|
2410
|
-
[authorization.planMaterialDigest, authorization.runId],
|
|
2411
|
-
)
|
|
2412
|
-
: await client.query<{ count: string }>(
|
|
2413
|
-
\`SELECT count(*)::text AS count
|
|
2414
|
-
FROM records
|
|
2415
|
-
WHERE owner_id = 'ebk-performance'
|
|
2416
|
-
AND name = 'ebk-protected-performance-load'
|
|
2417
|
-
AND run_scope = $1\`,
|
|
2418
|
-
[authorization.planMaterialDigest],
|
|
2419
|
-
);
|
|
2420
|
-
const remainingEffectCount = Number(remaining.rows[0]?.count ?? 0);
|
|
2421
|
-
if (
|
|
2422
|
-
!Number.isSafeInteger(remainingEffectCount) ||
|
|
2423
|
-
remainingEffectCount !== 0
|
|
2424
|
-
) {
|
|
2425
|
-
throw new Error('protected-performance-cleanup-incomplete');
|
|
2426
|
-
}
|
|
2427
|
-
await client.query('COMMIT');
|
|
2428
|
-
return {
|
|
2429
|
-
remainingEffectCount,
|
|
2430
|
-
removedEffectCount: removed.rowCount ?? 0,
|
|
2431
|
-
};
|
|
2432
|
-
} catch (error) {
|
|
2433
|
-
await client.query('ROLLBACK').catch(() => undefined);
|
|
2434
|
-
throw error;
|
|
2435
|
-
}
|
|
2436
|
-
},
|
|
2437
|
-
);
|
|
2438
|
-
}
|
|
2439
|
-
|
|
2052
|
+
${(0, built_in_plan_key_value_performance_js_1.renderKeyValuePerformanceEndpointFunctions)()}
|
|
2440
2053
|
function refused() {
|
|
2441
2054
|
return Response.json(
|
|
2442
2055
|
{
|
|
@@ -2461,8 +2074,8 @@ export async function runPerformanceScenarioEndpoint(
|
|
|
2461
2074
|
binding,
|
|
2462
2075
|
execute: async ({ authorization, effectId }) => {
|
|
2463
2076
|
if (
|
|
2464
|
-
adapterId === '
|
|
2465
|
-
adapterId === '
|
|
2077
|
+
adapterId === '${asyncAdapter}' ||
|
|
2078
|
+
adapterId === '${databaseAdapter}'
|
|
2466
2079
|
) {
|
|
2467
2080
|
if (!effectId) throw new Error('protected-effect-required');
|
|
2468
2081
|
return databaseExecution(adapterId, effectId, authorization);
|
|
@@ -2480,7 +2093,7 @@ export async function runPerformanceScenarioEndpoint(
|
|
|
2480
2093
|
}
|
|
2481
2094
|
|
|
2482
2095
|
export async function runPerformanceCleanupEndpoint(
|
|
2483
|
-
adapterId: '
|
|
2096
|
+
adapterId: '${asyncAdapter}' | '${databaseAdapter}',
|
|
2484
2097
|
request: Request,
|
|
2485
2098
|
) {
|
|
2486
2099
|
try {
|
|
@@ -2533,9 +2146,9 @@ vi.mock('@empire-builder-kit/runtime/performance', () => ({
|
|
|
2533
2146
|
status: 200,
|
|
2534
2147
|
})),
|
|
2535
2148
|
}));
|
|
2536
|
-
vi.mock('../../../../../
|
|
2537
|
-
|
|
2538
|
-
}))
|
|
2149
|
+
${`vi.mock('../../../../../performance/persistence', () => ({
|
|
2150
|
+
createPerformancePersistence: vi.fn(),
|
|
2151
|
+
}));`}
|
|
2539
2152
|
vi.mock('../../../../../secrets/declarations', () => ({
|
|
2540
2153
|
Secrets: { GeneratedPerformanceLoadHmacKeys: {} },
|
|
2541
2154
|
}));
|
|
@@ -2581,590 +2194,7 @@ describe('${name} protected performance secret cache lifetime', () => {
|
|
|
2581
2194
|
});
|
|
2582
2195
|
});
|
|
2583
2196
|
`,
|
|
2584
|
-
|
|
2585
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2586
|
-
import type { ProtectedLoadRequestAuthorizationV1 } from '@empire-builder-kit/runtime/performance';
|
|
2587
|
-
import { createInboxCleanupHandler } from '../async/inbox-cleanup.js';
|
|
2588
|
-
import {
|
|
2589
|
-
cleanupRun,
|
|
2590
|
-
databaseExecution,
|
|
2591
|
-
reserveRequest,
|
|
2592
|
-
} from '../web/src/app/%5F%5Febk/performance/handler.js';
|
|
2593
|
-
|
|
2594
|
-
vi.mock('server-only', () => ({}));
|
|
2595
|
-
vi.mock('../database/runtime-client.js', () => ({
|
|
2596
|
-
withPrimaryDatabase: async (
|
|
2597
|
-
_context: unknown,
|
|
2598
|
-
_workload: unknown,
|
|
2599
|
-
operation: (client: Client) => Promise<unknown>,
|
|
2600
|
-
) => {
|
|
2601
|
-
const { Client: RuntimeClient } = await import('pg');
|
|
2602
|
-
const client = new RuntimeClient({
|
|
2603
|
-
connectionString: process.env.DATABASE_URL,
|
|
2604
|
-
});
|
|
2605
|
-
await client.connect();
|
|
2606
|
-
try {
|
|
2607
|
-
return await operation(client);
|
|
2608
|
-
} finally {
|
|
2609
|
-
await client.end();
|
|
2610
|
-
}
|
|
2611
|
-
},
|
|
2612
|
-
}));
|
|
2613
|
-
|
|
2614
|
-
const databaseUrl = process.env.DATABASE_URL;
|
|
2615
|
-
if (!databaseUrl) {
|
|
2616
|
-
throw new Error(
|
|
2617
|
-
'DATABASE_URL is required for ${name} performance cleanup integration proof.',
|
|
2618
|
-
);
|
|
2619
|
-
}
|
|
2620
|
-
|
|
2621
|
-
const touchedPlanDigests = new Set<string>();
|
|
2622
|
-
|
|
2623
|
-
function authorization(input: {
|
|
2624
|
-
effectId: string | null;
|
|
2625
|
-
operation: 'cleanup' | 'execute';
|
|
2626
|
-
planMaterialDigest: string;
|
|
2627
|
-
requestOrdinal?: number;
|
|
2628
|
-
}): ProtectedLoadRequestAuthorizationV1 {
|
|
2629
|
-
return {
|
|
2630
|
-
adapterId: 'ebk-async-worker-v1',
|
|
2631
|
-
configuredMaximum: 100,
|
|
2632
|
-
createdAt: '2026-07-29T12:00:00.000Z',
|
|
2633
|
-
durationSeconds: 60,
|
|
2634
|
-
effectId: input.effectId,
|
|
2635
|
-
expiresAt: '2026-07-29T13:00:00.000Z',
|
|
2636
|
-
hmacKeyId: 'integration-v1',
|
|
2637
|
-
maximumRequests: 10,
|
|
2638
|
-
operation: input.operation,
|
|
2639
|
-
planMaterialDigest: input.planMaterialDigest,
|
|
2640
|
-
release: {
|
|
2641
|
-
candidateDigest: 'c'.repeat(64),
|
|
2642
|
-
releaseId: 'integration-release',
|
|
2643
|
-
releaseMaterialDigest: 'd'.repeat(64),
|
|
2644
|
-
sourceCommit: 'b'.repeat(40),
|
|
2645
|
-
},
|
|
2646
|
-
requestOrdinal: input.requestOrdinal ?? 1,
|
|
2647
|
-
runId: 'integration-run-' + input.planMaterialDigest.slice(0, 8),
|
|
2648
|
-
saturationSignalRef:
|
|
2649
|
-
'database:protected-async-backlog-utilization-percent',
|
|
2650
|
-
scenarioId: 'async-burst',
|
|
2651
|
-
stage: 'staging',
|
|
2652
|
-
target: {
|
|
2653
|
-
accountFingerprint: 'sha256:' + 'e'.repeat(64),
|
|
2654
|
-
endpoint:
|
|
2655
|
-
'https://performance.example.test/${name}/__ebk/performance/async-worker',
|
|
2656
|
-
region: 'us-east-1',
|
|
2657
|
-
slice: '${name}',
|
|
2658
|
-
},
|
|
2659
|
-
workload: 'async-worker',
|
|
2660
|
-
};
|
|
2661
|
-
}
|
|
2662
|
-
|
|
2663
|
-
async function withClient<Result>(
|
|
2664
|
-
operation: (client: Client) => Promise<Result>,
|
|
2665
|
-
): Promise<Result> {
|
|
2666
|
-
const client = new Client({ connectionString: databaseUrl });
|
|
2667
|
-
await client.connect();
|
|
2668
|
-
try {
|
|
2669
|
-
return await operation(client);
|
|
2670
|
-
} finally {
|
|
2671
|
-
await client.end();
|
|
2672
|
-
}
|
|
2673
|
-
}
|
|
2674
|
-
|
|
2675
|
-
// A loaded-host budget: hosted runners share four cores between Vitest,
|
|
2676
|
-
// the proof registry, and the dockerized database.
|
|
2677
|
-
async function waitForActiveStatement(
|
|
2678
|
-
client: Client,
|
|
2679
|
-
fragment: string,
|
|
2680
|
-
): Promise<void> {
|
|
2681
|
-
const deadline = Date.now() + 15_000;
|
|
2682
|
-
while (Date.now() < deadline) {
|
|
2683
|
-
const active = await client.query<{ count: string }>(
|
|
2684
|
-
\`SELECT count(*)::text AS count
|
|
2685
|
-
FROM pg_stat_activity
|
|
2686
|
-
WHERE datname = current_database()
|
|
2687
|
-
AND pid <> pg_backend_pid()
|
|
2688
|
-
AND state = 'active'
|
|
2689
|
-
AND query LIKE $1\`,
|
|
2690
|
-
['%' + fragment + '%'],
|
|
2691
|
-
);
|
|
2692
|
-
if (Number(active.rows[0]?.count ?? 0) > 0) return;
|
|
2693
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
2694
|
-
}
|
|
2695
|
-
throw new Error('Timed out waiting for the adversarial database statement.');
|
|
2696
|
-
}
|
|
2697
|
-
|
|
2698
|
-
afterEach(async () => {
|
|
2699
|
-
await withClient(async (client) => {
|
|
2700
|
-
await client
|
|
2701
|
-
.query(
|
|
2702
|
-
'DROP TRIGGER IF EXISTS ebk_performance_delay_effect ON performance_load_async_effects',
|
|
2703
|
-
)
|
|
2704
|
-
.catch(() => undefined);
|
|
2705
|
-
await client
|
|
2706
|
-
.query('DROP FUNCTION IF EXISTS ebk_performance_delay_effect()')
|
|
2707
|
-
.catch(() => undefined);
|
|
2708
|
-
for (const planDigest of touchedPlanDigests) {
|
|
2709
|
-
await client.query('DELETE FROM records WHERE run_scope = $1', [
|
|
2710
|
-
planDigest,
|
|
2711
|
-
]);
|
|
2712
|
-
await client.query(
|
|
2713
|
-
'DELETE FROM performance_load_async_effects WHERE plan_digest = $1',
|
|
2714
|
-
[planDigest],
|
|
2715
|
-
);
|
|
2716
|
-
await client.query(
|
|
2717
|
-
'DELETE FROM performance_load_requests WHERE plan_digest = $1',
|
|
2718
|
-
[planDigest],
|
|
2719
|
-
);
|
|
2720
|
-
await client.query(
|
|
2721
|
-
'DELETE FROM performance_load_runs WHERE plan_digest = $1',
|
|
2722
|
-
[planDigest],
|
|
2723
|
-
);
|
|
2724
|
-
}
|
|
2725
|
-
await client.query(
|
|
2726
|
-
"DELETE FROM cleanup_deadline_reports WHERE feature = 'performance-load'",
|
|
2727
|
-
);
|
|
2728
|
-
});
|
|
2729
|
-
touchedPlanDigests.clear();
|
|
2730
|
-
});
|
|
2731
|
-
|
|
2732
|
-
describe('${name} protected performance cleanup integration', () => {
|
|
2733
|
-
it('serializes cleanup behind an in-flight effect and rejects every late effect', async () => {
|
|
2734
|
-
const planMaterialDigest = '1'.repeat(64);
|
|
2735
|
-
const effectId = '2'.repeat(64);
|
|
2736
|
-
touchedPlanDigests.add(planMaterialDigest);
|
|
2737
|
-
const executeAuthorization = authorization({
|
|
2738
|
-
effectId,
|
|
2739
|
-
operation: 'execute',
|
|
2740
|
-
planMaterialDigest,
|
|
2741
|
-
});
|
|
2742
|
-
const cleanupAuthorization = authorization({
|
|
2743
|
-
effectId: null,
|
|
2744
|
-
operation: 'cleanup',
|
|
2745
|
-
planMaterialDigest,
|
|
2746
|
-
});
|
|
2747
|
-
|
|
2748
|
-
await reserveRequest(executeAuthorization);
|
|
2749
|
-
await withClient(async (client) => {
|
|
2750
|
-
await client.query(
|
|
2751
|
-
\`CREATE OR REPLACE FUNCTION ebk_performance_delay_effect()
|
|
2752
|
-
RETURNS trigger
|
|
2753
|
-
LANGUAGE plpgsql
|
|
2754
|
-
AS $$
|
|
2755
|
-
BEGIN
|
|
2756
|
-
PERFORM pg_sleep(1);
|
|
2757
|
-
RETURN NEW;
|
|
2758
|
-
END
|
|
2759
|
-
$$\`,
|
|
2760
|
-
);
|
|
2761
|
-
await client.query(
|
|
2762
|
-
\`CREATE TRIGGER ebk_performance_delay_effect
|
|
2763
|
-
BEFORE INSERT ON performance_load_async_effects
|
|
2764
|
-
FOR EACH ROW EXECUTE FUNCTION ebk_performance_delay_effect()\`,
|
|
2765
|
-
);
|
|
2766
|
-
});
|
|
2767
|
-
|
|
2768
|
-
const observer = new Client({ connectionString: databaseUrl });
|
|
2769
|
-
await observer.connect();
|
|
2770
|
-
try {
|
|
2771
|
-
const effect = databaseExecution(
|
|
2772
|
-
'ebk-async-worker-v1',
|
|
2773
|
-
effectId,
|
|
2774
|
-
executeAuthorization,
|
|
2775
|
-
);
|
|
2776
|
-
await waitForActiveStatement(
|
|
2777
|
-
observer,
|
|
2778
|
-
'INSERT INTO performance_load_async_effects',
|
|
2779
|
-
);
|
|
2780
|
-
const cleanup = cleanupRun(
|
|
2781
|
-
'ebk-async-worker-v1',
|
|
2782
|
-
cleanupAuthorization,
|
|
2783
|
-
);
|
|
2784
|
-
await expect(effect).resolves.toMatchObject({ effectState: 'created' });
|
|
2785
|
-
await expect(cleanup).resolves.toEqual({
|
|
2786
|
-
remainingEffectCount: 0,
|
|
2787
|
-
removedEffectCount: 1,
|
|
2788
|
-
});
|
|
2789
|
-
} finally {
|
|
2790
|
-
await observer.end();
|
|
2791
|
-
}
|
|
2792
|
-
|
|
2793
|
-
await expect(
|
|
2794
|
-
databaseExecution(
|
|
2795
|
-
'ebk-async-worker-v1',
|
|
2796
|
-
'3'.repeat(64),
|
|
2797
|
-
{
|
|
2798
|
-
...executeAuthorization,
|
|
2799
|
-
effectId: '3'.repeat(64),
|
|
2800
|
-
requestOrdinal: 2,
|
|
2801
|
-
},
|
|
2802
|
-
),
|
|
2803
|
-
).rejects.toThrow('protected-performance-run-cleaning');
|
|
2804
|
-
await expect(
|
|
2805
|
-
reserveRequest({
|
|
2806
|
-
...executeAuthorization,
|
|
2807
|
-
effectId: '3'.repeat(64),
|
|
2808
|
-
requestOrdinal: 2,
|
|
2809
|
-
}),
|
|
2810
|
-
).rejects.toThrow('protected-performance-run-collision');
|
|
2811
|
-
|
|
2812
|
-
await withClient(async (client) => {
|
|
2813
|
-
const state = await client.query<{
|
|
2814
|
-
cleanupStarted: boolean;
|
|
2815
|
-
effects: string;
|
|
2816
|
-
}>(
|
|
2817
|
-
\`SELECT
|
|
2818
|
-
run.cleanup_started_at IS NOT NULL AS "cleanupStarted",
|
|
2819
|
-
(
|
|
2820
|
-
SELECT count(*)::text
|
|
2821
|
-
FROM performance_load_async_effects AS effect
|
|
2822
|
-
WHERE effect.plan_digest = run.plan_digest
|
|
2823
|
-
) AS effects
|
|
2824
|
-
FROM performance_load_runs AS run
|
|
2825
|
-
WHERE run.plan_digest = $1\`,
|
|
2826
|
-
[planMaterialDigest],
|
|
2827
|
-
);
|
|
2828
|
-
expect(state.rows).toEqual([
|
|
2829
|
-
{ cleanupStarted: true, effects: '0' },
|
|
2830
|
-
]);
|
|
2831
|
-
});
|
|
2832
|
-
});
|
|
2833
|
-
|
|
2834
|
-
it('tombstones and proves an effect-free run absent without a local ledger', async () => {
|
|
2835
|
-
const planMaterialDigest = '4'.repeat(64);
|
|
2836
|
-
touchedPlanDigests.add(planMaterialDigest);
|
|
2837
|
-
const cleanupAuthorization = authorization({
|
|
2838
|
-
effectId: null,
|
|
2839
|
-
operation: 'cleanup',
|
|
2840
|
-
planMaterialDigest,
|
|
2841
|
-
});
|
|
2842
|
-
|
|
2843
|
-
await expect(
|
|
2844
|
-
cleanupRun('ebk-async-worker-v1', cleanupAuthorization),
|
|
2845
|
-
).resolves.toEqual({
|
|
2846
|
-
remainingEffectCount: 0,
|
|
2847
|
-
removedEffectCount: 0,
|
|
2848
|
-
});
|
|
2849
|
-
await expect(
|
|
2850
|
-
cleanupRun('ebk-async-worker-v1', cleanupAuthorization),
|
|
2851
|
-
).resolves.toEqual({
|
|
2852
|
-
remainingEffectCount: 0,
|
|
2853
|
-
removedEffectCount: 0,
|
|
2854
|
-
});
|
|
2855
|
-
await expect(
|
|
2856
|
-
reserveRequest({
|
|
2857
|
-
...cleanupAuthorization,
|
|
2858
|
-
effectId: '5'.repeat(64),
|
|
2859
|
-
operation: 'execute',
|
|
2860
|
-
}),
|
|
2861
|
-
).rejects.toThrow('protected-performance-run-collision');
|
|
2862
|
-
});
|
|
2863
|
-
|
|
2864
|
-
it('expires only framework-owned due rows and retains fresh audit state', async () => {
|
|
2865
|
-
const oldPlan = '6'.repeat(64);
|
|
2866
|
-
const freshPlan = '7'.repeat(64);
|
|
2867
|
-
const expiredEffectPlan = '8'.repeat(64);
|
|
2868
|
-
const freshEffectPlan = '9'.repeat(64);
|
|
2869
|
-
for (const digest of [
|
|
2870
|
-
oldPlan,
|
|
2871
|
-
freshPlan,
|
|
2872
|
-
expiredEffectPlan,
|
|
2873
|
-
freshEffectPlan,
|
|
2874
|
-
]) {
|
|
2875
|
-
touchedPlanDigests.add(digest);
|
|
2876
|
-
}
|
|
2877
|
-
const expiredRecordId = '10000000-0000-4000-8000-000000000001';
|
|
2878
|
-
const freshRecordId = '10000000-0000-4000-8000-000000000002';
|
|
2879
|
-
const adopterRecordId = '10000000-0000-4000-8000-000000000003';
|
|
2880
|
-
|
|
2881
|
-
await withClient(async (client) => {
|
|
2882
|
-
await client.query(
|
|
2883
|
-
\`INSERT INTO performance_load_runs
|
|
2884
|
-
(plan_digest, run_id, adapter_id, scenario_id, stage,
|
|
2885
|
-
source_commit, release_material_digest, maximum_requests,
|
|
2886
|
-
created_at, expires_at)
|
|
2887
|
-
VALUES
|
|
2888
|
-
($1, 'old-run', 'ebk-async-worker-v1', 'async-burst', 'staging',
|
|
2889
|
-
$3, $4, 10, now() - INTERVAL '32 days',
|
|
2890
|
-
now() - INTERVAL '31 days'),
|
|
2891
|
-
($2, 'fresh-run', 'ebk-async-worker-v1', 'async-burst', 'staging',
|
|
2892
|
-
$3, $4, 10, now() - INTERVAL '30 days',
|
|
2893
|
-
now() - INTERVAL '29 days')\`,
|
|
2894
|
-
[oldPlan, freshPlan, 'b'.repeat(40), 'd'.repeat(64)],
|
|
2895
|
-
);
|
|
2896
|
-
await client.query(
|
|
2897
|
-
\`INSERT INTO performance_load_requests
|
|
2898
|
-
(plan_digest, request_ordinal, effect_id)
|
|
2899
|
-
VALUES ($1, 1, NULL), ($2, 1, NULL)\`,
|
|
2900
|
-
[oldPlan, freshPlan],
|
|
2901
|
-
);
|
|
2902
|
-
await client.query(
|
|
2903
|
-
\`INSERT INTO performance_load_async_effects
|
|
2904
|
-
(effect_id, plan_digest, run_id, expires_at)
|
|
2905
|
-
VALUES
|
|
2906
|
-
($1, $2, 'expired', now() - INTERVAL '1 minute'),
|
|
2907
|
-
($3, $4, 'fresh', now() + INTERVAL '1 day')\`,
|
|
2908
|
-
['a'.repeat(64), expiredEffectPlan, 'f'.repeat(64), freshEffectPlan],
|
|
2909
|
-
);
|
|
2910
|
-
await client.query(
|
|
2911
|
-
\`INSERT INTO records
|
|
2912
|
-
(id, name, owner_id, run_scope, test_expires_at)
|
|
2913
|
-
VALUES
|
|
2914
|
-
($1::uuid, 'ebk-protected-performance-load', 'ebk-performance',
|
|
2915
|
-
$4, now() - INTERVAL '1 minute'),
|
|
2916
|
-
($2::uuid, 'ebk-protected-performance-load', 'ebk-performance',
|
|
2917
|
-
$5, now() + INTERVAL '1 day'),
|
|
2918
|
-
($3::uuid, 'adopter-performance-data', 'adopter-owner',
|
|
2919
|
-
$4, now() - INTERVAL '1 minute')\`,
|
|
2920
|
-
[
|
|
2921
|
-
expiredRecordId,
|
|
2922
|
-
freshRecordId,
|
|
2923
|
-
adopterRecordId,
|
|
2924
|
-
expiredEffectPlan,
|
|
2925
|
-
freshEffectPlan,
|
|
2926
|
-
],
|
|
2927
|
-
);
|
|
2928
|
-
});
|
|
2929
|
-
|
|
2930
|
-
const emitted: Array<{ metricName?: string; value?: number }> = [];
|
|
2931
|
-
const handler = createInboxCleanupHandler({
|
|
2932
|
-
logger: {
|
|
2933
|
-
error: vi.fn(),
|
|
2934
|
-
info: vi.fn(),
|
|
2935
|
-
} as never,
|
|
2936
|
-
metrics: {
|
|
2937
|
-
emit: (metric: { metricName?: string; value?: number }) => {
|
|
2938
|
-
emitted.push(metric);
|
|
2939
|
-
return {} as never;
|
|
2940
|
-
},
|
|
2941
|
-
} as never,
|
|
2942
|
-
now: Date.now,
|
|
2943
|
-
withDatabase: (async (
|
|
2944
|
-
_context: unknown,
|
|
2945
|
-
_workload: unknown,
|
|
2946
|
-
operation: (client: Client) => Promise<unknown>,
|
|
2947
|
-
) => withClient(operation)) as never,
|
|
2948
|
-
});
|
|
2949
|
-
await expect(handler({ id: 'performance-expiry-proof' })).resolves.toMatchObject({
|
|
2950
|
-
performanceAuditRetentionDays: 30,
|
|
2951
|
-
performanceCleanupDeadlineHours: 24,
|
|
2952
|
-
reportedPerformanceDeadlineBreaches: 0,
|
|
2953
|
-
remainingPerformanceExpired: 0,
|
|
2954
|
-
removedPerformance: 4,
|
|
2955
|
-
});
|
|
2956
|
-
expect(emitted).toContainEqual(
|
|
2957
|
-
expect.objectContaining({
|
|
2958
|
-
metricName: 'PerformanceLoadCleanupBacklog',
|
|
2959
|
-
value: 0,
|
|
2960
|
-
}),
|
|
2961
|
-
);
|
|
2962
|
-
expect(emitted).toContainEqual(
|
|
2963
|
-
expect.objectContaining({
|
|
2964
|
-
metricName: 'PerformanceLoadCleanupDeadlineBreaches',
|
|
2965
|
-
value: 0,
|
|
2966
|
-
}),
|
|
2967
|
-
);
|
|
2968
|
-
|
|
2969
|
-
await withClient(async (client) => {
|
|
2970
|
-
const effects = await client.query<{ planDigest: string }>(
|
|
2971
|
-
\`SELECT plan_digest AS "planDigest"
|
|
2972
|
-
FROM performance_load_async_effects
|
|
2973
|
-
WHERE plan_digest = ANY($1::text[])
|
|
2974
|
-
ORDER BY plan_digest\`,
|
|
2975
|
-
[[expiredEffectPlan, freshEffectPlan]],
|
|
2976
|
-
);
|
|
2977
|
-
expect(effects.rows).toEqual([{ planDigest: freshEffectPlan }]);
|
|
2978
|
-
const records = await client.query<{ id: string }>(
|
|
2979
|
-
\`SELECT id::text AS id
|
|
2980
|
-
FROM records
|
|
2981
|
-
WHERE id = ANY($1::uuid[])
|
|
2982
|
-
ORDER BY id\`,
|
|
2983
|
-
[[expiredRecordId, freshRecordId, adopterRecordId]],
|
|
2984
|
-
);
|
|
2985
|
-
expect(records.rows).toEqual([
|
|
2986
|
-
{ id: freshRecordId },
|
|
2987
|
-
{ id: adopterRecordId },
|
|
2988
|
-
]);
|
|
2989
|
-
const audits = await client.query<{
|
|
2990
|
-
planDigest: string;
|
|
2991
|
-
requests: string;
|
|
2992
|
-
}>(
|
|
2993
|
-
\`SELECT
|
|
2994
|
-
run.plan_digest AS "planDigest",
|
|
2995
|
-
count(request.request_ordinal)::text AS requests
|
|
2996
|
-
FROM performance_load_runs AS run
|
|
2997
|
-
LEFT JOIN performance_load_requests AS request
|
|
2998
|
-
ON request.plan_digest = run.plan_digest
|
|
2999
|
-
WHERE run.plan_digest = ANY($1::text[])
|
|
3000
|
-
GROUP BY run.plan_digest
|
|
3001
|
-
ORDER BY run.plan_digest\`,
|
|
3002
|
-
[[oldPlan, freshPlan]],
|
|
3003
|
-
);
|
|
3004
|
-
expect(audits.rows).toEqual([
|
|
3005
|
-
{ planDigest: freshPlan, requests: '1' },
|
|
3006
|
-
]);
|
|
3007
|
-
});
|
|
3008
|
-
});
|
|
3009
|
-
|
|
3010
|
-
it('durably retries deadline telemetry after deleting stale protected residue', async () => {
|
|
3011
|
-
const stalePlan = 'a'.repeat(64);
|
|
3012
|
-
const staleEffectId = 'b'.repeat(64);
|
|
3013
|
-
const atDeadlinePlan = 'c'.repeat(64);
|
|
3014
|
-
const atDeadlineEffectId = 'd'.repeat(64);
|
|
3015
|
-
const beforeDeadlinePlan = 'e'.repeat(64);
|
|
3016
|
-
const beforeDeadlineEffectId = 'f'.repeat(64);
|
|
3017
|
-
const staleRecordId = '10000000-0000-4000-8000-000000000004';
|
|
3018
|
-
for (const planDigest of [
|
|
3019
|
-
stalePlan,
|
|
3020
|
-
atDeadlinePlan,
|
|
3021
|
-
beforeDeadlinePlan,
|
|
3022
|
-
]) {
|
|
3023
|
-
touchedPlanDigests.add(planDigest);
|
|
3024
|
-
}
|
|
3025
|
-
await withClient(async (client) => {
|
|
3026
|
-
await client.query(
|
|
3027
|
-
\`INSERT INTO performance_load_async_effects
|
|
3028
|
-
(effect_id, plan_digest, run_id, expires_at)
|
|
3029
|
-
VALUES
|
|
3030
|
-
($1, $2, 'stale-deadline',
|
|
3031
|
-
clock_timestamp() - INTERVAL '25 hours'),
|
|
3032
|
-
($3, $4, 'exact-deadline',
|
|
3033
|
-
clock_timestamp() - INTERVAL '24 hours'),
|
|
3034
|
-
($5, $6, 'before-deadline',
|
|
3035
|
-
clock_timestamp() - INTERVAL '23 hours 59 minutes')\`,
|
|
3036
|
-
[
|
|
3037
|
-
staleEffectId,
|
|
3038
|
-
stalePlan,
|
|
3039
|
-
atDeadlineEffectId,
|
|
3040
|
-
atDeadlinePlan,
|
|
3041
|
-
beforeDeadlineEffectId,
|
|
3042
|
-
beforeDeadlinePlan,
|
|
3043
|
-
],
|
|
3044
|
-
);
|
|
3045
|
-
await client.query(
|
|
3046
|
-
\`INSERT INTO records
|
|
3047
|
-
(id, name, owner_id, run_scope, test_expires_at)
|
|
3048
|
-
VALUES ($1::uuid, 'ebk-protected-performance-load',
|
|
3049
|
-
'ebk-performance', $2, now() - INTERVAL '25 hours')\`,
|
|
3050
|
-
[staleRecordId, stalePlan],
|
|
3051
|
-
);
|
|
3052
|
-
});
|
|
3053
|
-
|
|
3054
|
-
const failedEmissions: Array<{ metricName?: string; value?: number }> = [];
|
|
3055
|
-
const failedHandler = createInboxCleanupHandler({
|
|
3056
|
-
logger: { error: vi.fn(), info: vi.fn() } as never,
|
|
3057
|
-
metrics: {
|
|
3058
|
-
emit: (metric: { metricName?: string; value?: number }) => {
|
|
3059
|
-
failedEmissions.push(metric);
|
|
3060
|
-
return metric.metricName ===
|
|
3061
|
-
'PerformanceLoadCleanupDeadlineBreaches'
|
|
3062
|
-
? undefined
|
|
3063
|
-
: ({} as never);
|
|
3064
|
-
},
|
|
3065
|
-
} as never,
|
|
3066
|
-
now: Date.now,
|
|
3067
|
-
withDatabase: (async (
|
|
3068
|
-
_context: unknown,
|
|
3069
|
-
_workload: unknown,
|
|
3070
|
-
operation: (client: Client) => Promise<unknown>,
|
|
3071
|
-
) => withClient(operation)) as never,
|
|
3072
|
-
});
|
|
3073
|
-
await expect(
|
|
3074
|
-
failedHandler({ id: 'performance-deadline-report-failure' }),
|
|
3075
|
-
).rejects.toThrow('Performance cleanup deadline metric delivery failed.');
|
|
3076
|
-
|
|
3077
|
-
await withClient(async (client) => {
|
|
3078
|
-
const state = await client.query<{
|
|
3079
|
-
effects: string;
|
|
3080
|
-
records: string;
|
|
3081
|
-
reports: string;
|
|
3082
|
-
resourceRefs: string[];
|
|
3083
|
-
}>(
|
|
3084
|
-
\`SELECT
|
|
3085
|
-
(SELECT count(*)::text
|
|
3086
|
-
FROM performance_load_async_effects
|
|
3087
|
-
WHERE effect_id = ANY($1::text[])) AS effects,
|
|
3088
|
-
(SELECT count(*)::text
|
|
3089
|
-
FROM records
|
|
3090
|
-
WHERE id = $2::uuid) AS records,
|
|
3091
|
-
(SELECT count(*)::text
|
|
3092
|
-
FROM cleanup_deadline_reports
|
|
3093
|
-
WHERE feature = 'performance-load') AS reports,
|
|
3094
|
-
(SELECT array_agg(resource_ref ORDER BY resource_ref)
|
|
3095
|
-
FROM cleanup_deadline_reports
|
|
3096
|
-
WHERE feature = 'performance-load') AS "resourceRefs"\`,
|
|
3097
|
-
[
|
|
3098
|
-
[staleEffectId, atDeadlineEffectId, beforeDeadlineEffectId],
|
|
3099
|
-
staleRecordId,
|
|
3100
|
-
],
|
|
3101
|
-
);
|
|
3102
|
-
expect(state.rows).toEqual([
|
|
3103
|
-
{
|
|
3104
|
-
effects: '0',
|
|
3105
|
-
records: '0',
|
|
3106
|
-
reports: '3',
|
|
3107
|
-
resourceRefs: [
|
|
3108
|
-
'async-effect:' + staleEffectId,
|
|
3109
|
-
'async-effect:' + atDeadlineEffectId,
|
|
3110
|
-
'record:' + staleRecordId,
|
|
3111
|
-
].sort(),
|
|
3112
|
-
},
|
|
3113
|
-
]);
|
|
3114
|
-
});
|
|
3115
|
-
expect(JSON.stringify(failedEmissions)).not.toContain(staleEffectId);
|
|
3116
|
-
expect(JSON.stringify(failedEmissions)).not.toContain(staleRecordId);
|
|
3117
|
-
expect(JSON.stringify(failedEmissions)).not.toContain(atDeadlineEffectId);
|
|
3118
|
-
expect(JSON.stringify(failedEmissions)).not.toContain(
|
|
3119
|
-
beforeDeadlineEffectId,
|
|
3120
|
-
);
|
|
3121
|
-
|
|
3122
|
-
const retryEmissions: Array<{ metricName?: string; value?: number }> = [];
|
|
3123
|
-
const retryHandler = createInboxCleanupHandler({
|
|
3124
|
-
logger: { error: vi.fn(), info: vi.fn() } as never,
|
|
3125
|
-
metrics: {
|
|
3126
|
-
emit: (metric: { metricName?: string; value?: number }) => {
|
|
3127
|
-
retryEmissions.push(metric);
|
|
3128
|
-
return {} as never;
|
|
3129
|
-
},
|
|
3130
|
-
} as never,
|
|
3131
|
-
now: Date.now,
|
|
3132
|
-
withDatabase: (async (
|
|
3133
|
-
_context: unknown,
|
|
3134
|
-
_workload: unknown,
|
|
3135
|
-
operation: (client: Client) => Promise<unknown>,
|
|
3136
|
-
) => withClient(operation)) as never,
|
|
3137
|
-
});
|
|
3138
|
-
await expect(
|
|
3139
|
-
retryHandler({ id: 'performance-deadline-report-retry' }),
|
|
3140
|
-
).rejects.toThrow('performance-load-cleanup-deadline-breached');
|
|
3141
|
-
expect(retryEmissions).toContainEqual(
|
|
3142
|
-
expect.objectContaining({
|
|
3143
|
-
metricName: 'PerformanceLoadCleanupDeadlineBreaches',
|
|
3144
|
-
value: 3,
|
|
3145
|
-
}),
|
|
3146
|
-
);
|
|
3147
|
-
expect(JSON.stringify(retryEmissions)).not.toContain(staleEffectId);
|
|
3148
|
-
expect(JSON.stringify(retryEmissions)).not.toContain(staleRecordId);
|
|
3149
|
-
expect(JSON.stringify(retryEmissions)).not.toContain(atDeadlineEffectId);
|
|
3150
|
-
expect(JSON.stringify(retryEmissions)).not.toContain(
|
|
3151
|
-
beforeDeadlineEffectId,
|
|
3152
|
-
);
|
|
3153
|
-
|
|
3154
|
-
await withClient(async (client) => {
|
|
3155
|
-
const reports = await client.query<{ count: string }>(
|
|
3156
|
-
\`SELECT count(*)::text AS count
|
|
3157
|
-
FROM cleanup_deadline_reports
|
|
3158
|
-
WHERE feature = 'performance-load'\`,
|
|
3159
|
-
);
|
|
3160
|
-
expect(reports.rows).toEqual([{ count: '0' }]);
|
|
3161
|
-
});
|
|
3162
|
-
await expect(
|
|
3163
|
-
retryHandler({ id: 'performance-deadline-after-ack' }),
|
|
3164
|
-
).resolves.toMatchObject({ reportedPerformanceDeadlineBreaches: 0 });
|
|
3165
|
-
});
|
|
3166
|
-
});
|
|
3167
|
-
`,
|
|
2197
|
+
...{},
|
|
3168
2198
|
'web/src/app/%5F%5Febk/performance/api-lambda/route.ts': `import 'server-only';
|
|
3169
2199
|
import { runPerformanceScenarioEndpoint } from '../handler';
|
|
3170
2200
|
|
|
@@ -3176,32 +2206,74 @@ export function GET(request: Request) {
|
|
|
3176
2206
|
import { runPerformanceScenarioEndpoint } from '../handler';
|
|
3177
2207
|
|
|
3178
2208
|
export function POST(request: Request) {
|
|
3179
|
-
return runPerformanceScenarioEndpoint('
|
|
2209
|
+
return runPerformanceScenarioEndpoint('${asyncAdapter}', request);
|
|
3180
2210
|
}
|
|
3181
2211
|
`,
|
|
3182
2212
|
'web/src/app/%5F%5Febk/performance/async-worker/cleanup/route.ts': `import 'server-only';
|
|
3183
2213
|
import { runPerformanceCleanupEndpoint } from '../../handler';
|
|
3184
2214
|
|
|
3185
2215
|
export function POST(request: Request) {
|
|
3186
|
-
return runPerformanceCleanupEndpoint('
|
|
2216
|
+
return runPerformanceCleanupEndpoint('${asyncAdapter}', request);
|
|
3187
2217
|
}
|
|
3188
2218
|
`,
|
|
3189
2219
|
'web/src/app/%5F%5Febk/performance/database/route.ts': `import 'server-only';
|
|
3190
2220
|
import { runPerformanceScenarioEndpoint } from '../handler';
|
|
3191
2221
|
|
|
3192
2222
|
export function POST(request: Request) {
|
|
3193
|
-
return runPerformanceScenarioEndpoint('
|
|
2223
|
+
return runPerformanceScenarioEndpoint('${databaseAdapter}', request);
|
|
3194
2224
|
}
|
|
3195
2225
|
`,
|
|
3196
2226
|
'web/src/app/%5F%5Febk/performance/database/cleanup/route.ts': `import 'server-only';
|
|
3197
2227
|
import { runPerformanceCleanupEndpoint } from '../../handler';
|
|
3198
2228
|
|
|
3199
2229
|
export function POST(request: Request) {
|
|
3200
|
-
return runPerformanceCleanupEndpoint('
|
|
2230
|
+
return runPerformanceCleanupEndpoint('${databaseAdapter}', request);
|
|
3201
2231
|
}
|
|
3202
2232
|
`,
|
|
3203
2233
|
'docs/runbooks/performance-capacity-cost.md': `# Performance, capacity, and cost
|
|
3204
2234
|
|
|
2235
|
+
${`The default database scenarios use DynamoDB, not PostgreSQL. The database
|
|
2236
|
+
request signal measures the complete protected write/consistent-read operation
|
|
2237
|
+
against a one-second budget; it is a latency proxy, not connection count or
|
|
2238
|
+
measured DynamoDB service saturation. The async signal measures this run's
|
|
2239
|
+
unprocessed synthetic effects against its configured maximum. Expired but
|
|
2240
|
+
uncleaned effects remain counted until cleanup, so the signal is conservative.
|
|
2241
|
+
The backlog observation is a run-bound sample shared for at most one second
|
|
2242
|
+
inside each warm worker process. Concurrent requests reuse that sample instead
|
|
2243
|
+
of rescanning the pending collection per request; separate processes may sample
|
|
2244
|
+
independently. This is a bounded operational signal, never authorization or a
|
|
2245
|
+
global account-wide counter. Cleanup and async processing invalidate the local
|
|
2246
|
+
sample; exact per-request identity and effect checks are never cached.
|
|
2247
|
+
Neither signal claims account-wide capacity. Cold Aurora resume and idle cost
|
|
2248
|
+
apply only after SQL is explicitly declared; default key-value tests do not
|
|
2249
|
+
prove that relational acceptance. The signed-request, release, target, quota,
|
|
2250
|
+
and exact run-cleanup requirements are unchanged.
|
|
2251
|
+
|
|
2252
|
+
Explicit run cleanup closes the exact run before removing effects in bounded
|
|
2253
|
+
chunks. A progress response is not acceptance: the harness follows signed
|
|
2254
|
+
continuations within its existing deadline and accepts only \`run-absent\` with
|
|
2255
|
+
zero remaining effects. If interrupted or timed out, retain the run identity
|
|
2256
|
+
and retry its protected cleanup; never reopen the closed run or fabricate an
|
|
2257
|
+
absence receipt. Expiry maintenance remains the bounded recovery path.
|
|
2258
|
+
|
|
2259
|
+
Native expiry cleanup drains bounded exact pages within a shared four-minute
|
|
2260
|
+
invocation budget. It inspects at most 10,000 provider receipts and 5,000
|
|
2261
|
+
performance records per invocation; limits and time exhaustion retain cursors
|
|
2262
|
+
and report continuation. Provider receipts are removed after thirty days only
|
|
2263
|
+
when terminal; uncertain effects stay retained for reconciliation. Performance
|
|
2264
|
+
effects expire after twenty-four hours, with request/run audit history retained
|
|
2265
|
+
for thirty days after run expiry. Logical request expiry, not physical deletion
|
|
2266
|
+
or DynamoDB TTL timing, prevents replay.
|
|
2267
|
+
|
|
2268
|
+
Overdue effect deletion and its deadline report commit atomically. Reports stay
|
|
2269
|
+
durable until metric emission and acknowledgement succeed; a lost acknowledgement
|
|
2270
|
+
may repeat the breach metric. A partial scan does not emit a fabricated zero
|
|
2271
|
+
backlog. Require complete-scan evidence and no continuation or pending deadline
|
|
2272
|
+
reports before retiring an old signing key. Explicit maintenance pauses retain
|
|
2273
|
+
their existing behavior and can delay cleanup; selecting a capacity profile
|
|
2274
|
+
does not resume this worker.
|
|
2275
|
+
|
|
2276
|
+
`}\
|
|
3205
2277
|
The generated policy is deliberately an unadopted seed. Replace example budgets,
|
|
3206
2278
|
unknown capacity values, owner, review date, and allocation drivers from actual
|
|
3207
2279
|
product requirements before protected promotion. Reliability remains authority
|
|
@@ -3355,10 +2427,12 @@ counts, evidence digests, account, Region, stage, workspace, Slice, period, and
|
|
|
3355
2427
|
release from that validated evidence; clean generation reports the missing live
|
|
3356
2428
|
evidence as incomplete.
|
|
3357
2429
|
|
|
3358
|
-
The generated scenarios cover API/Lambda, async worker,
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
2430
|
+
The generated scenarios cover API/Lambda, async worker, and DynamoDB-backed
|
|
2431
|
+
database operations. Cold Aurora resume and idle cost are separate acceptance
|
|
2432
|
+
cases only when SQL is declared. A Service extension becomes managed when its
|
|
2433
|
+
Service is generated. Scenarios are disabled until deliberately adopted. A
|
|
2434
|
+
clean generated Slice therefore reports incomplete rather than claiming
|
|
2435
|
+
capacity, cost, or live load evidence.
|
|
3362
2436
|
`,
|
|
3363
2437
|
};
|
|
3364
2438
|
}
|