@empire-builder-kit/nx 1.0.0-rc.44 → 1.0.0-rc.46
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/package.json +3 -3
- package/src/blueprints/external-sandbox.d.ts +1 -1
- package/src/cli/main.d.ts +11 -5
- package/src/cli/main.js +88 -29
- package/src/container-images.d.ts +1 -1
- package/src/container-images.js +1 -1
- package/src/developer-agent/generator-planning.js +10 -3
- package/src/developer-agent/operation-registry.js +1 -1
- package/src/executors/deployment-plan/deployment-plan.js +5 -1
- package/src/executors/deployment-plan/schema.json +1 -1
- package/src/executors/fleet/fleet.js +4 -0
- package/src/executors/fleet/schema.json +1 -1
- package/src/executors/github-bootstrap/github-bootstrap.d.ts +3 -0
- package/src/executors/github-bootstrap/github-bootstrap.js +28 -0
- package/src/executors/github-bootstrap/schema.json +14 -0
- package/src/executors/local-deploy/federated-credential-transport.d.ts +4 -3
- package/src/executors/local-deploy/federated-credential-transport.js +15 -5
- package/src/foundation/cost-estimate.d.ts +8 -3
- package/src/foundation/cost-estimate.js +42 -19
- package/src/foundation/index.d.ts +1 -0
- package/src/foundation/index.js +1 -0
- package/src/foundation/local-private-smoke-access.js +6 -0
- package/src/foundation/logging.d.ts +3 -1
- package/src/foundation/logging.js +8 -1
- package/src/foundation/observability.d.ts +42 -0
- package/src/foundation/observability.js +181 -0
- package/src/foundation/preflight.js +1 -1
- package/src/generators/function/function.js +5 -2
- package/src/generators/observability-infrastructure.d.ts +2 -0
- package/src/generators/observability-infrastructure.js +31 -0
- package/src/generators/observability-policy.d.ts +4 -0
- package/src/generators/observability-policy.js +23 -0
- package/src/generators/preset/dependency-overrides.d.ts +17 -6
- package/src/generators/preset/dependency-overrides.js +17 -6
- package/src/generators/preset/tool-versions.d.ts +2 -2
- package/src/generators/preset/tool-versions.js +2 -2
- package/src/generators/preset/workspace-files-adopter-skills.js +28 -17
- package/src/generators/preset/workspace-files-agent-development.d.ts +9 -0
- package/src/generators/preset/workspace-files-agent-development.js +42 -0
- package/src/generators/preset/workspace-files-thin-deploy.js +17 -4
- package/src/generators/preset/workspace-files-thin-docs.js +10 -22
- package/src/generators/preset/workspace-files.d.ts +1 -0
- package/src/generators/preset/workspace-files.js +120 -35
- package/src/generators/slice/built-in-plan-alarm-identity.d.ts +173 -0
- package/src/generators/slice/built-in-plan-alarm-identity.js +202 -0
- package/src/generators/slice/built-in-plan-api-contract-files.js +136 -0
- package/src/generators/slice/built-in-plan-data-files.js +10 -3
- package/src/generators/slice/built-in-plan-database-lifecycle-files.js +1 -1
- package/src/generators/slice/built-in-plan-event-contract-literal.d.ts +6 -0
- package/src/generators/slice/built-in-plan-event-contract-literal.js +52 -0
- package/src/generators/slice/built-in-plan-infrastructure-files.js +304 -144
- package/src/generators/slice/built-in-plan-key-value-retention-infrastructure.js +2 -2
- package/src/generators/slice/built-in-plan-metadata-files.js +37 -2
- package/src/generators/slice/built-in-plan-operations-files.js +106 -6
- package/src/generators/slice/built-in-plan-project-files.js +1 -0
- package/src/generators/slice/built-in-plan-release-files.js +2 -44
- package/src/generators/slice/built-in-plan-reliability-files.js +222 -236
- package/src/generators/slice/built-in-plan-shared.d.ts +29 -3
- package/src/generators/slice/built-in-plan-shared.js +29 -2
- package/src/generators/slice/built-in-plan-verification-files.js +0 -1
- package/src/generators/slice/built-in-plan-web-files.js +22 -6
- package/src/generators/slice/built-in-plan.js +2 -2
- package/src/generators/slice/slice.js +2 -0
- package/src/generators/upgrade/upgrade.d.ts +4 -3
- package/src/generators/upgrade/upgrade.js +139 -29
- package/src/generators/workload/frozen-container.d.ts +1 -1
- package/src/generators/workload/reliability-registration.d.ts +1 -1
- package/src/generators/workload/reliability-registration.js +9 -9
- package/src/generators/workload/workload.d.ts +1 -1
- package/src/generators/workload/workload.js +32 -10
- package/src/git-policy/github-bootstrap.d.ts +18 -0
- package/src/git-policy/github-bootstrap.js +99 -6
- package/src/local-dev/dev-command-core.d.ts +24 -3
- package/src/local-dev/dev-command-core.js +124 -12
- package/src/local-dev/errors.d.ts +19 -1
- package/src/local-dev/errors.js +18 -1
- package/src/local-dev/fleet-client.d.ts +64 -6
- package/src/local-dev/fleet-client.js +189 -15
- package/src/local-dev/fleet-process.d.ts +47 -2
- package/src/local-dev/fleet-process.js +248 -31
- package/src/local-dev/fleet-runtime.d.ts +37 -0
- package/src/local-dev/fleet-runtime.js +127 -69
- package/src/local-dev/fleet-session.d.ts +1 -0
- package/src/local-dev/fleet-session.js +83 -7
- package/src/local-dev/fleet-state.d.ts +5 -0
- package/src/local-dev/fleet-state.js +11 -2
- package/src/local-dev/fleet-supervisor-daemon.js +1 -5
- package/src/local-dev/fleet-supervisor.d.ts +7 -0
- package/src/local-dev/fleet-supervisor.js +83 -12
- package/src/local-dev/slice-runner.d.ts +19 -1
- package/src/local-dev/slice-runner.js +290 -91
- package/src/repository-policy/deployment-plan.d.ts +1 -1
- package/src/repository-policy/deployment-plan.js +16 -1
- package/src/secrets/generated-aws-control-plane.d.ts +11 -1
- package/src/secrets/generated-aws-control-plane.js +92 -29
- package/src/secrets/operator.d.ts +3 -2
- package/src/secrets/operator.js +27 -5
- package/src/supply-chain/blueprint-verification-authority.js +24 -3
- package/src/supply-chain/generated-files.js +9 -0
- package/src/supply-chain/sbom.js +74 -12
|
@@ -8,9 +8,9 @@ exports.WORKSPACE_SST_NPM_INTEGRITY = exports.WORKSPACE_PNPM_DESCRIPTOR = export
|
|
|
8
8
|
* existing workspace explicitly adopts the exact reviewed descriptor.
|
|
9
9
|
*/
|
|
10
10
|
exports.WORKSPACE_SST_VERSION = '4.17.1';
|
|
11
|
-
exports.WORKSPACE_NODE_VERSION = '22.23.
|
|
11
|
+
exports.WORKSPACE_NODE_VERSION = '22.23.4';
|
|
12
12
|
exports.WORKSPACE_PNPM_VERSION = '11.20.0';
|
|
13
|
-
exports.WORKSPACE_VITEST_VERSION = '4.1.
|
|
13
|
+
exports.WORKSPACE_VITEST_VERSION = '4.1.12';
|
|
14
14
|
exports.WORKSPACE_PNPM_SHA512 = '9a6f330a95b66446ea088faf1521405a8a01f07fde7124cc9958dfed52d4bb436737e65b08f85f37b46fcba375092558ac51262b816844b22f63406ed166bfee';
|
|
15
15
|
exports.WORKSPACE_PNPM_DESCRIPTOR = `pnpm@${exports.WORKSPACE_PNPM_VERSION}+sha512.${exports.WORKSPACE_PNPM_SHA512}`;
|
|
16
16
|
/**
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ADOPTER_SKILL_NAMES = void 0;
|
|
4
4
|
exports.renderAdopterSkillIndex = renderAdopterSkillIndex;
|
|
5
5
|
exports.renderAdopterSkills = renderAdopterSkills;
|
|
6
|
+
const workspace_files_agent_development_js_1 = require("./workspace-files-agent-development.js");
|
|
6
7
|
exports.ADOPTER_SKILL_NAMES = [
|
|
7
8
|
'ebk-orient-plan',
|
|
8
9
|
'ebk-build-feature',
|
|
@@ -107,6 +108,21 @@ intents commit atomically. TTL is eventual cleanup, not an authorization or
|
|
|
107
108
|
expiry decision. Events use the same stage/task; never bridge task async work
|
|
108
109
|
to deployed development.
|
|
109
110
|
|
|
111
|
+
For a cross-Slice event, the producer declares it in its seeded
|
|
112
|
+
\`contracts/events.ts\` \`EventContractSchema\`; its own queue rule then also
|
|
113
|
+
receives it, so its seeded consumer acknowledges it. The consumer adds the
|
|
114
|
+
producer's \`@<scope>/<producer>/contracts\` package to its seeded
|
|
115
|
+
\`contracts/dependencies.json\` \`consumes\` with a \`workspace:*\` dependency,
|
|
116
|
+
runs \`pnpm nx run <consumer>:contract-dependencies-sync\`, declares
|
|
117
|
+
\`{ "source": "<producer>", "events": [{ "detailType": "<Type>", "schemaVersions": [1] }] }\`
|
|
118
|
+
in its seeded \`contracts/event-subscriptions.json\`, and extends its seeded
|
|
119
|
+
\`api/event-consumer.ts\` to accept that source, type and every declared
|
|
120
|
+
version. Managed infrastructure adds one rule per source; never edit
|
|
121
|
+
\`infra/product.ts\`. \`contract-dependencies-check\` binds the declaration to
|
|
122
|
+
the producer's schema. Source and detail type are delivery filters, not
|
|
123
|
+
authentication: authorize every effect from the consumer's own data and
|
|
124
|
+
policy. Never carry product data in \`DataLifecycleChanged\`.
|
|
125
|
+
|
|
110
126
|
Add SQL only when relational constraints, transactions or joins justify it:
|
|
111
127
|
\`pnpm nx g @empire-builder-kit/nx:sql billing --reason="Ledger requires relational constraints and reporting joins"\`
|
|
112
128
|
reports the paired changes; review and repeat with \`--apply\`. The generator
|
|
@@ -125,18 +141,12 @@ not done merely because its generated file exists or the page loads.
|
|
|
125
141
|
body: `# Develop and verify
|
|
126
142
|
|
|
127
143
|
Inspect \`ebk dev doctor\` and \`ebk dev status\` using the account and Region
|
|
128
|
-
fixed by committed repository policy and the profile saved by
|
|
129
|
-
\`ebk dev configure\`.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
that identity, then continue. Never embed access keys, export, copy, or read
|
|
135
|
-
credentials from the SSO cache, or assume a separate or stronger principal.
|
|
136
|
-
Only an attended agent (local or hosted), one a human is actively directing,
|
|
137
|
-
uses that session; an unattended or background agent never receives a human
|
|
138
|
-
profile or SSO session. Resolve other readiness failures using the reported
|
|
139
|
-
prerequisite; a doctor pass is not feature proof.
|
|
144
|
+
fixed by committed repository policy and the development profile saved by
|
|
145
|
+
\`ebk dev configure\`.
|
|
146
|
+
|
|
147
|
+
${workspace_files_agent_development_js_1.AGENT_DEVELOPMENT_AUTHORITY}
|
|
148
|
+
Resolve other readiness failures using the reported prerequisite; a doctor pass
|
|
149
|
+
is not feature proof.
|
|
140
150
|
Development accepts dirty source and does not require a production
|
|
141
151
|
confirmation, release artifact or full workspace barrier.
|
|
142
152
|
|
|
@@ -178,7 +188,7 @@ browser check. Prefer \`ebk dev restart\` while iterating and reserve
|
|
|
178
188
|
\`ebk dev down\` for the completion boundary.
|
|
179
189
|
|
|
180
190
|
At the completion boundary, settle \`ebk dev down billing\`, then use
|
|
181
|
-
\`ebk deploy development billing --profile=<
|
|
191
|
+
\`ebk deploy development billing --profile=<development-profile> --expectedRoleArn=<exact-role>\`.
|
|
182
192
|
This selects Foundation then Billing. Omit Slice selectors for complete-stage
|
|
183
193
|
proof. Verify the deployed Router without hot processes or fallback serving it.
|
|
184
194
|
Check migration, smoke and cleanup outcomes; failure is not acceptance.
|
|
@@ -199,11 +209,12 @@ mutation; source policy is authoritative if deliberately changed later.
|
|
|
199
209
|
|
|
200
210
|
Use \`ebk deploy development\` for the complete active development stage, or
|
|
201
211
|
\`ebk deploy development billing\` for Foundation plus one selected Slice.
|
|
202
|
-
Pass the
|
|
203
|
-
|
|
212
|
+
Pass the development profile saved by \`ebk dev configure\` as \`--profile\`;
|
|
213
|
+
it chains the human's Identity Center source profile into the exact development
|
|
214
|
+
deployment role. Pass that role from
|
|
204
215
|
\`docs/stage-deployment-authority.md\` as \`--expectedRoleArn\`; verify
|
|
205
|
-
account, Region, stage and current caller. Refresh an expired
|
|
206
|
-
|
|
216
|
+
account, Region, stage and current caller. Refresh an expired source session
|
|
217
|
+
as in the develop/verify skill. No direct SST or AWS application
|
|
207
218
|
mutation. A development deploy runs to completion with no prompt; add
|
|
208
219
|
\`--json\` for one bounded result on stdout after the run (the receipt this run
|
|
209
220
|
wrote and each project's outcome). Staging and production refuse \`--json\`.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One canonical statement of what a coding agent may do in the development
|
|
3
|
+
* stage. The seeded README and Foundation runbook and the managed
|
|
4
|
+
* develop/verify skill interpolate it verbatim so the three copies cannot
|
|
5
|
+
* drift. Any agent, attended or unattended, may use the human's approved
|
|
6
|
+
* development profile for development-stage work; the protected stages,
|
|
7
|
+
* credential handling and denial handling stay fixed.
|
|
8
|
+
*/
|
|
9
|
+
export declare const AGENT_DEVELOPMENT_AUTHORITY = "Any coding agent, attended or unattended, may run `ebk dev up`, `restart`,\n`down`, and `ebk deploy development` through EBK/Nx with the human's approved\ndevelopment profile, within the approved task, account, Region, ownership,\ncost, and cleanup limits, without repeated confirmation. The source profile is\nthe human's IAM Identity Center login profile. The development profile is the\none `ebk dev configure` saves and `--profile` receives; it chains the source\nprofile into the exact bounded development deployment role named in\n`docs/stage-deployment-authority.md`. That role assumption is expected; it\ndoes not authorize another role or broader access. An agent on another host\nreceives no copy of either profile or of the SSO cache.\nIf the source session is expired or missing, run\n`aws sso login --profile <source-profile>`, adding `--use-device-code` in a\nheadless shell. The login needs the human's browser approval, so an agent whose\nsource session has expired with no human available stops and reports.\nBefore mutation, run `aws sts get-caller-identity --profile <development-profile>`.\n`Account` must equal the committed development account, `Arn` must be\n`arn:<partition>:sts::<account>:assumed-role/ebk-development-deploy/<session>`,\nan assumed-role session of that exact role, and the Region saved by\n`ebk dev configure` must equal the committed Region. `ebk dev up` checks only\nthe account and Region; `ebk deploy development` also enforces the role.\nNever embed keys, export or copy credentials, read the SSO cache, or broaden\ntrust or policies. A protected observer profile, meaning a read-only staging or\nproduction profile the human may hold for inspection, is never a role source,\nand neither is any other staging or production profile.\nStaging and production stay GitHub-only or human-only, and agents and CI never\nrun `ebk secret set`. A new binding or authority expansion stops for a human\ndecision. A denial from the agent host, EBK, or AWS stops that mutation and\nevery equivalent route: report the exact denial and command, and do not\nre-route through Nx, SST, raw AWS, another profile, or another role. A\nhuman-started Fleet is the fallback.";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AGENT_DEVELOPMENT_AUTHORITY = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* One canonical statement of what a coding agent may do in the development
|
|
6
|
+
* stage. The seeded README and Foundation runbook and the managed
|
|
7
|
+
* develop/verify skill interpolate it verbatim so the three copies cannot
|
|
8
|
+
* drift. Any agent, attended or unattended, may use the human's approved
|
|
9
|
+
* development profile for development-stage work; the protected stages,
|
|
10
|
+
* credential handling and denial handling stay fixed.
|
|
11
|
+
*/
|
|
12
|
+
exports.AGENT_DEVELOPMENT_AUTHORITY = `Any coding agent, attended or unattended, may run \`ebk dev up\`, \`restart\`,
|
|
13
|
+
\`down\`, and \`ebk deploy development\` through EBK/Nx with the human's approved
|
|
14
|
+
development profile, within the approved task, account, Region, ownership,
|
|
15
|
+
cost, and cleanup limits, without repeated confirmation. The source profile is
|
|
16
|
+
the human's IAM Identity Center login profile. The development profile is the
|
|
17
|
+
one \`ebk dev configure\` saves and \`--profile\` receives; it chains the source
|
|
18
|
+
profile into the exact bounded development deployment role named in
|
|
19
|
+
\`docs/stage-deployment-authority.md\`. That role assumption is expected; it
|
|
20
|
+
does not authorize another role or broader access. An agent on another host
|
|
21
|
+
receives no copy of either profile or of the SSO cache.
|
|
22
|
+
If the source session is expired or missing, run
|
|
23
|
+
\`aws sso login --profile <source-profile>\`, adding \`--use-device-code\` in a
|
|
24
|
+
headless shell. The login needs the human's browser approval, so an agent whose
|
|
25
|
+
source session has expired with no human available stops and reports.
|
|
26
|
+
Before mutation, run \`aws sts get-caller-identity --profile <development-profile>\`.
|
|
27
|
+
\`Account\` must equal the committed development account, \`Arn\` must be
|
|
28
|
+
\`arn:<partition>:sts::<account>:assumed-role/ebk-development-deploy/<session>\`,
|
|
29
|
+
an assumed-role session of that exact role, and the Region saved by
|
|
30
|
+
\`ebk dev configure\` must equal the committed Region. \`ebk dev up\` checks only
|
|
31
|
+
the account and Region; \`ebk deploy development\` also enforces the role.
|
|
32
|
+
Never embed keys, export or copy credentials, read the SSO cache, or broaden
|
|
33
|
+
trust or policies. A protected observer profile, meaning a read-only staging or
|
|
34
|
+
production profile the human may hold for inspection, is never a role source,
|
|
35
|
+
and neither is any other staging or production profile.
|
|
36
|
+
Staging and production stay GitHub-only or human-only, and agents and CI never
|
|
37
|
+
run \`ebk secret set\`. A new binding or authority expansion stops for a human
|
|
38
|
+
decision. A denial from the agent host, EBK, or AWS stops that mutation and
|
|
39
|
+
every equivalent route: report the exact denial and command, and do not
|
|
40
|
+
re-route through Nx, SST, raw AWS, another profile, or another role. A
|
|
41
|
+
human-started Fleet is the fallback.`;
|
|
42
|
+
//# sourceMappingURL=workspace-files-agent-development.js.map
|
|
@@ -541,6 +541,9 @@ writeFileSync(
|
|
|
541
541
|
function renderThinDeployWorkflow(options) {
|
|
542
542
|
const { actionPins, deploymentProfile, name, toolVersions } = options;
|
|
543
543
|
const trunkPromotion = options.productionApprovalMode === 'trunk-promotion';
|
|
544
|
+
// The starter protected pair deploys development from protected develop;
|
|
545
|
+
// in the trunk lane develop is unprotected and owns no stage.
|
|
546
|
+
const developmentFromProtectedDevelop = deploymentProfile === 'starter' && options.deliveryLane !== 'trunk';
|
|
544
547
|
return `name: Deploy
|
|
545
548
|
run-name: Deploy \${{ inputs.source_commit || github.sha }}
|
|
546
549
|
|
|
@@ -707,14 +710,17 @@ jobs:
|
|
|
707
710
|
plan_action="$action"
|
|
708
711
|
[ "$action" != rehearse ] || plan_action=deploy
|
|
709
712
|
case "$EBK_SOURCE_BRANCH" in
|
|
710
|
-
main) stage=production
|
|
713
|
+
main) stage=production ;;${options.deliveryLane === 'trunk'
|
|
714
|
+
? `
|
|
715
|
+
develop) echo 'Trunk lane protected lifecycle runs from main'; exit 1 ;;`
|
|
716
|
+
: `
|
|
711
717
|
develop)
|
|
712
718
|
if [ "$EBK_PROFILE" = starter ]; then
|
|
713
719
|
stage=development
|
|
714
720
|
else
|
|
715
721
|
stage=staging
|
|
716
722
|
fi
|
|
717
|
-
|
|
723
|
+
;;`}
|
|
718
724
|
*) echo 'Protected lifecycle must run from develop or main'; exit 1 ;;
|
|
719
725
|
esac
|
|
720
726
|
echo "action=$action" >> "$GITHUB_OUTPUT"
|
|
@@ -753,7 +759,11 @@ ${indentedScript(`set -euo pipefail\n${canonicalStageAuthorityDerivationScript()
|
|
|
753
759
|
# production authority is derived here beside the staging authority.
|
|
754
760
|
- id: production-account
|
|
755
761
|
name: Derive canonical committed production authority for trunk promotion
|
|
756
|
-
if:
|
|
762
|
+
if: >-
|
|
763
|
+
steps.route.outputs.action == 'deploy' &&
|
|
764
|
+
steps.route.outputs.stage == 'staging' &&
|
|
765
|
+
steps.policy.outputs.deployment_profile != 'starter' &&
|
|
766
|
+
steps.policy.outputs.has_slices == 'true'
|
|
757
767
|
env:
|
|
758
768
|
EBK_DEVELOPMENT_ACCOUNT: \${{ steps.policy.outputs.development_account_id }}
|
|
759
769
|
EBK_PRODUCTION_ACCOUNT: \${{ steps.policy.outputs.production_account_id }}
|
|
@@ -1665,7 +1675,10 @@ ${indentedScript(restoredCandidateValidationScript(), 10)}
|
|
|
1665
1675
|
{ echo 'Protected Blueprint authority must be one full Git object ID'; exit 1; }
|
|
1666
1676
|
test "$(git rev-parse HEAD)" = "$EBK_PROTECTED_BLUEPRINT_COMMIT" ||
|
|
1667
1677
|
{ echo 'Protected Blueprint authority differs from the exact workflow checkout'; exit 1; }
|
|
1668
|
-
case "$EBK_STAGE" in
|
|
1678
|
+
case "$EBK_STAGE" in${developmentFromProtectedDevelop
|
|
1679
|
+
? `
|
|
1680
|
+
development) protected_branch=develop ;;`
|
|
1681
|
+
: ''}
|
|
1669
1682
|
staging) protected_branch=develop ;;
|
|
1670
1683
|
production) protected_branch=main ;;
|
|
1671
1684
|
*) exit 1 ;;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.renderThinLifecycleDocumentation = renderThinLifecycleDocumentation;
|
|
4
|
+
const workspace_files_agent_development_js_1 = require("./workspace-files-agent-development.js");
|
|
4
5
|
const index_js_1 = require("../../repository-policy/index.js");
|
|
5
6
|
function renderThinLifecycleDocumentation(options) {
|
|
6
7
|
const stages = (0, index_js_1.activeDeploymentStages)(options.deploymentProfile);
|
|
@@ -18,19 +19,13 @@ The committed \`${options.deploymentProfile}\` profile activates: ${stageList}.
|
|
|
18
19
|
|
|
19
20
|
For ordinary feature work, run affected tests, typecheck, lint, and ownership
|
|
20
21
|
checks. Run \`pnpm verify\` at a milestone, not before each development edit.
|
|
21
|
-
Configure the
|
|
22
|
+
Configure the development profile and the stage deployment role described
|
|
22
23
|
in \`docs/stage-deployment-authority.md\` before deploying development through
|
|
23
|
-
\`ebk deploy development --profile=<profile> --expectedRoleArn=<role-arn>\`
|
|
24
|
-
(the root \`deploy-local\` target).
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
human approves the request in the browser, so the session stays the human's
|
|
29
|
-
own identity. In a hosted or headless shell, add \`--use-device-code\` and the
|
|
30
|
-
human approves the printed code from their own browser. Confirm
|
|
31
|
-
\`aws sts get-caller-identity\` reports that identity before continuing.
|
|
32
|
-
Never embed access keys, export, copy, or read credentials from the SSO cache,
|
|
33
|
-
or assume a separate or stronger principal. Do not invoke SST directly.
|
|
24
|
+
\`ebk deploy development --profile=<development-profile> --expectedRoleArn=<role-arn>\`
|
|
25
|
+
(the root \`deploy-local\` target).
|
|
26
|
+
|
|
27
|
+
${workspace_files_agent_development_js_1.AGENT_DEVELOPMENT_AUTHORITY}
|
|
28
|
+
Do not invoke SST directly.
|
|
34
29
|
|
|
35
30
|
Slice \`verify\` runs \`test-integration\`, which needs a running Docker engine
|
|
36
31
|
for DynamoDB Local (and PostgreSQL when SQL is declared).
|
|
@@ -143,7 +138,7 @@ removal, unlock, discovery, and secret resolution.
|
|
|
143
138
|
|
|
144
139
|
## Native lifecycle
|
|
145
140
|
|
|
146
|
-
Use \`ebk deploy development --profile=<profile> --expectedRoleArn=<role-arn>\`.
|
|
141
|
+
Use \`ebk deploy development --profile=<development-profile> --expectedRoleArn=<role-arn>\`.
|
|
147
142
|
Add Slice names, for example \`ebk deploy development billing\` with the same
|
|
148
143
|
authority options, for focused deployment after Foundation. Other Slices are
|
|
149
144
|
not redeployed; required peers must already exist. Omit Slice names for the
|
|
@@ -248,16 +243,9 @@ The resolved ${rehearsalStage} stage is rehearsed with
|
|
|
248
243
|
Use temporary IAM Identity Center credentials and the stable stage deployment
|
|
249
244
|
role. Development accepts a dirty tree and requires no acknowledgement:
|
|
250
245
|
|
|
251
|
-
\`ebk deploy development --profile=<profile> --expectedRoleArn=<role-arn>\`
|
|
246
|
+
\`ebk deploy development --profile=<development-profile> --expectedRoleArn=<role-arn>\`
|
|
252
247
|
|
|
253
|
-
|
|
254
|
-
agent (local or hosted) may run \`aws sso login --profile <profile>\`; the
|
|
255
|
-
human approves the request in the browser, so the session stays the human's
|
|
256
|
-
own identity. In a hosted or headless shell, add \`--use-device-code\` and the
|
|
257
|
-
human approves the printed code from their own browser. Confirm
|
|
258
|
-
\`aws sts get-caller-identity\` reports that identity before continuing.
|
|
259
|
-
Never embed access keys, export, copy, or read credentials from the SSO cache,
|
|
260
|
-
or assume a separate or stronger principal.
|
|
248
|
+
${workspace_files_agent_development_js_1.AGENT_DEVELOPMENT_AUTHORITY}
|
|
261
249
|
|
|
262
250
|
Local staging, when active, requires a clean commit and an interactive
|
|
263
251
|
\`approve:deploy:staging:<source-commit>\` response. Starter production requires
|
|
@@ -11,6 +11,7 @@ export interface WorkspaceFileOptions {
|
|
|
11
11
|
/** Seeded supply-chain/dependency-overrides.json data. When absent, the
|
|
12
12
|
* workspace is seeded with DEFAULT_DEPENDENCY_OVERRIDES. */
|
|
13
13
|
dependencyOverrides?: unknown;
|
|
14
|
+
observabilityPolicy?: unknown;
|
|
14
15
|
deploymentAccounts?: ConfiguredDeploymentAccounts;
|
|
15
16
|
deploymentProfile?: DeploymentProfile;
|
|
16
17
|
deploymentRegion?: string | null;
|
|
@@ -11,6 +11,7 @@ const dependency_overrides_js_1 = require("./dependency-overrides.js");
|
|
|
11
11
|
const index_js_1 = require("../../ownership/index.js");
|
|
12
12
|
const index_js_2 = require("../../frontend-security/index.js");
|
|
13
13
|
const capability_plan_js_1 = require("../../foundation/capability-plan.js");
|
|
14
|
+
const observability_js_1 = require("../../foundation/observability.js");
|
|
14
15
|
const cost_estimate_js_1 = require("../../foundation/cost-estimate.js");
|
|
15
16
|
const index_js_3 = require("../../git-policy/index.js");
|
|
16
17
|
const index_js_4 = require("../../repository-policy/index.js");
|
|
@@ -1059,6 +1060,7 @@ const SUPPLY_CHAIN_WORKSPACE_FILE_PLAN = (0, index_js_6.renderSupplyChainWorkspa
|
|
|
1059
1060
|
});
|
|
1060
1061
|
const WORKSPACE_SEEDED_PATHS = new Set([
|
|
1061
1062
|
dependency_overrides_js_1.DEPENDENCY_OVERRIDES_PATH,
|
|
1063
|
+
observability_js_1.OBSERVABILITY_POLICY_PATH,
|
|
1062
1064
|
...SUPPLY_CHAIN_WORKSPACE_FILE_PLAN.seeded,
|
|
1063
1065
|
...workspace_files_developer_agent_js_1.DEVELOPER_AGENT_WORKSPACE_SEEDED_PATHS,
|
|
1064
1066
|
'.github/CODEOWNERS',
|
|
@@ -1066,6 +1068,7 @@ const WORKSPACE_SEEDED_PATHS = new Set([
|
|
|
1066
1068
|
'CLAUDE.md',
|
|
1067
1069
|
'README.md',
|
|
1068
1070
|
'docs/architecture.md',
|
|
1071
|
+
'docs/observability.md',
|
|
1069
1072
|
'docs/git-workflow.md',
|
|
1070
1073
|
'docs/repository-operating-policy.md',
|
|
1071
1074
|
'docs/stage-deployment-authority.md',
|
|
@@ -7656,6 +7659,7 @@ console.log('Installed the repository-local EBK pre-push hook at ' + hookPath +
|
|
|
7656
7659
|
.open-next
|
|
7657
7660
|
dist
|
|
7658
7661
|
*.tsbuildinfo
|
|
7662
|
+
**/next-env.d.ts
|
|
7659
7663
|
node_modules
|
|
7660
7664
|
.sst
|
|
7661
7665
|
**/playwright/.auth
|
|
@@ -7874,6 +7878,72 @@ convention, current only as far as the copy each actor reads.
|
|
|
7874
7878
|
`,
|
|
7875
7879
|
[workspace_files_shared_operation_claims_js_1.SHARED_OPERATION_CLAIMS_PATH]: (0, workspace_files_shared_operation_claims_js_1.renderSharedOperationClaims)(name),
|
|
7876
7880
|
'ebk.repository-policy.json': json(initialRepositoryPolicy),
|
|
7881
|
+
[observability_js_1.OBSERVABILITY_POLICY_PATH]: json(options.observabilityPolicy === undefined
|
|
7882
|
+
? (0, observability_js_1.defaultObservabilityPolicy)(activeStages, {
|
|
7883
|
+
productionProfile: initialRepositoryPolicy.productionFoundation.profile,
|
|
7884
|
+
})
|
|
7885
|
+
: (0, observability_js_1.parseObservabilityPolicy)(options.observabilityPolicy, activeStages)),
|
|
7886
|
+
'docs/observability.md': `# Observability spending and diagnostics
|
|
7887
|
+
|
|
7888
|
+
The seeded ebk.observability.json is the stage-specific policy. New development
|
|
7889
|
+
uses cost-optimized, active staging uses balanced, and production gets an explicit
|
|
7890
|
+
profile initialized from its capacity choice. Later capacity changes never alter
|
|
7891
|
+
that seeded observability choice. Task diagnostics are lean, but explicit retention
|
|
7892
|
+
and dormant-log preservation still apply; local hot diagnostics remain complete.
|
|
7893
|
+
This policy never pauses work or
|
|
7894
|
+
changes database protection, encryption, backups, topology or deployment authority.
|
|
7895
|
+
|
|
7896
|
+
Cost-optimized retains 5% of marked neutral request-start/success diagnostics, WARN Lambda
|
|
7897
|
+
system logs and no dashboards. Balanced retains 25%, INFO system logs and one
|
|
7898
|
+
Foundation dashboard. Standard retains 100%, INFO system logs and Foundation plus
|
|
7899
|
+
Slice dashboards. All retain errors, warnings, security, migration/event receipts,
|
|
7900
|
+
required counters and core failure/backlog alarms. Custom metrics are not free;
|
|
7901
|
+
batching reduces ingestion bytes, not billable metric series.
|
|
7902
|
+
|
|
7903
|
+
Mixed application/security log groups retain at least 30 days (90 for new standard
|
|
7904
|
+
production). diagnosticRetentionDays is an extension default; no generated log
|
|
7905
|
+
group uses it. Shorter diagnostic retention applies only to separately declared
|
|
7906
|
+
diagnostic groups, never mixed groups. Insights, enhanced database monitoring and
|
|
7907
|
+
tracing have no control in this policy. Retain Standard class for EMF and generated
|
|
7908
|
+
receipt queries. WAF enforcement and existing request-log privacy are unchanged.
|
|
7909
|
+
|
|
7910
|
+
Upgrades from older workspaces seed explicit prior retention and verbosity; they
|
|
7911
|
+
do not silently adopt shorter retention or remove dormant log groups. Review this
|
|
7912
|
+
seeded file to opt in deliberately. Profile changes require ordinary deployment;
|
|
7913
|
+
generators never change AWS. Workspace upgrade comes before Foundation/Slices.
|
|
7914
|
+
When enabling a new canonical stage, declare it here as well as in repository policy.
|
|
7915
|
+
|
|
7916
|
+
Stage overrides: profile; routineSuccessSampleRate (0–1); diagnosticRetentionDays;
|
|
7917
|
+
protectedRetentionDays (AWS-supported, at least 30); dashboards (none, stage, slice);
|
|
7918
|
+
systemLogLevel (WARN, INFO); retainDormantComponentLogs (boolean). Declared optional
|
|
7919
|
+
components always keep their logs. Only absent provider/webhook components may
|
|
7920
|
+
omit their otherwise unused log groups and findings alarms.
|
|
7921
|
+
|
|
7922
|
+
Fractional sampling uses a server-owned ID, not client correlation/request headers.
|
|
7923
|
+
Request starts are neutral, never successful. Legacy/standard retain an entry
|
|
7924
|
+
breadcrumb even for handlers that never return; cheap profiles may omit routine
|
|
7925
|
+
starts, but failures and receipts remain unsampled.
|
|
7926
|
+
|
|
7927
|
+
Custom reliability labels belong in each Slice's seeded reliability/metric-declarations.ts.
|
|
7928
|
+
Declare finite component/feature/operation values, never user, tenant, request or
|
|
7929
|
+
resource identifiers. Keep high-cardinality context in redacted logs. Only reviewed
|
|
7930
|
+
routine INFO successes may use routineSuccess; never mark receipts or security events.
|
|
7931
|
+
Upgrades flag the new declaration requirement with a reconciliation work marker.
|
|
7932
|
+
Undeclared tuples and invalid observations produce bounded reason-only warnings;
|
|
7933
|
+
invalid latency never suppresses the valid operation counters.
|
|
7934
|
+
|
|
7935
|
+
At low traffic, fixed dashboards, alarms and metric series can dominate the bill.
|
|
7936
|
+
Profile savings primarily change dashboard inventory; fresh disabled adapters omit
|
|
7937
|
+
two dormant groups and findings alarms. Sampling/batching affect ingestion and
|
|
7938
|
+
scanning volume, while retention affects storage only where applied. No live
|
|
7939
|
+
saving or free-tier discount is implied by the list-price estimate.
|
|
7940
|
+
|
|
7941
|
+
Diagnostics are on demand. Budget CloudWatch API metric retrieval as well as
|
|
7942
|
+
alarms, storage, ingestion, scanning and custom series. Narrow queries to the
|
|
7943
|
+
exact owned stage/resources/window; account-wide repeated sweeps are not a
|
|
7944
|
+
default application behavior. Never reduce a safety check's coverage or cadence
|
|
7945
|
+
to hide its cost. Measure actual billing after deployment, not just estimates.
|
|
7946
|
+
`,
|
|
7877
7947
|
'nx.json': json({
|
|
7878
7948
|
$schema: './node_modules/nx/schemas/nx-schema.json',
|
|
7879
7949
|
defaultBase: 'develop',
|
|
@@ -8222,6 +8292,7 @@ ${foundationPlan.resources.postgres ? ' foundationDatabaseEndpointHost,' : ''}
|
|
|
8222
8292
|
foundationSsmPath,
|
|
8223
8293
|
normalizeRouterWafPolicy,
|
|
8224
8294
|
reconcileRouterWafBlockingRehearsal,
|
|
8295
|
+
resolveObservabilityPolicy,
|
|
8225
8296
|
routerWafContractDigest,
|
|
8226
8297
|
type FoundationSsmKey,
|
|
8227
8298
|
} from '@empire-builder-kit/nx/foundation';
|
|
@@ -8242,6 +8313,7 @@ import routerWafBlockingRehearsal from '../security/router-waf-blocking-rehearsa
|
|
|
8242
8313
|
import routerWafLiveEvidence from '../security/router-waf-live-evidence.json';
|
|
8243
8314
|
import routerWafPolicy from '../security/router-waf.json';
|
|
8244
8315
|
import repositoryPolicy from '../../../ebk.repository-policy.json';
|
|
8316
|
+
import observabilityPolicy from '../../../ebk.observability.json';
|
|
8245
8317
|
|
|
8246
8318
|
function identityDomainPrefix(stage: string, accountId: string): string {
|
|
8247
8319
|
if (!/^\\d{12}$/.test(accountId)) {
|
|
@@ -8277,6 +8349,11 @@ function publishFoundation(values: Partial<Record<FoundationSsmKey, any>>) {
|
|
|
8277
8349
|
|
|
8278
8350
|
export function foundation() {
|
|
8279
8351
|
const isProduction = $app.stage === 'production';
|
|
8352
|
+
const observability = resolveObservabilityPolicy({
|
|
8353
|
+
policy: observabilityPolicy,
|
|
8354
|
+
stage: $app.stage,
|
|
8355
|
+
productionProfile: process.env.EBK_PRODUCTION_FOUNDATION_PROFILE,
|
|
8356
|
+
});
|
|
8280
8357
|
${foundationPlan.resources.postgres ? " const isStaging = $app.stage === 'staging';" : ''}
|
|
8281
8358
|
const rootDomain = process.env.EBK_ROOT_DOMAIN?.trim();
|
|
8282
8359
|
const productionConfiguration = isProduction
|
|
@@ -8289,36 +8366,38 @@ ${foundationPlan.resources.network ? " const natMode = productionConfiguration?
|
|
|
8289
8366
|
if (repositoryPolicy.deploymentProfile !== normalizedRouterWafPolicy.deploymentProfile) {
|
|
8290
8367
|
throw new Error('Router WAF policy profile differs from committed repository policy.');
|
|
8291
8368
|
}
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
normalizedRouterWafPolicy.deploymentProfile
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
8369
|
+
let rehearsal: ReturnType<typeof reconcileRouterWafBlockingRehearsal> = null;
|
|
8370
|
+
if (isProduction) {
|
|
8371
|
+
const rehearsalStage = productionRehearsalStage(normalizedRouterWafPolicy.deploymentProfile);
|
|
8372
|
+
const rehearsalAccount = configuredDeploymentAccountForStage(
|
|
8373
|
+
normalizedRouterWafPolicy.deploymentProfile,
|
|
8374
|
+
repositoryPolicy.deploymentAccounts,
|
|
8375
|
+
rehearsalStage,
|
|
8376
|
+
);
|
|
8377
|
+
const rehearsalRegion = configuredDeploymentRegion(repositoryPolicy.deploymentRegion);
|
|
8378
|
+
const rehearsalRoleArn = createStageAuthorityIdentity({
|
|
8379
|
+
accountId: rehearsalAccount,
|
|
8380
|
+
partition: rehearsalRegion.startsWith('us-gov-') ? 'aws-us-gov' : 'aws',
|
|
8381
|
+
region: rehearsalRegion,
|
|
8382
|
+
stage: rehearsalStage,
|
|
8383
|
+
}).deploymentRoleArn;
|
|
8384
|
+
rehearsal = reconcileRouterWafBlockingRehearsal({
|
|
8385
|
+
evidence: routerWafLiveEvidence,
|
|
8386
|
+
expected: {
|
|
8387
|
+
accountId: rehearsalAccount,
|
|
8388
|
+
deploymentRoleArn: rehearsalRoleArn,
|
|
8389
|
+
region: rehearsalRegion,
|
|
8390
|
+
stage: rehearsalStage,
|
|
8391
|
+
wafContractDigest: routerWafContractDigest(normalizedRouterWafPolicy),
|
|
8392
|
+
workspace: '${name}',
|
|
8393
|
+
},
|
|
8394
|
+
policy: normalizedRouterWafPolicy,
|
|
8395
|
+
receipt: routerWafBlockingRehearsal,
|
|
8396
|
+
});
|
|
8397
|
+
}
|
|
8305
8398
|
const wafPlan = createRouterWafStagePlan({
|
|
8306
8399
|
policy: normalizedRouterWafPolicy,
|
|
8307
|
-
rehearsal
|
|
8308
|
-
? reconcileRouterWafBlockingRehearsal({
|
|
8309
|
-
evidence: routerWafLiveEvidence,
|
|
8310
|
-
expected: {
|
|
8311
|
-
accountId: rehearsalAccount,
|
|
8312
|
-
deploymentRoleArn: rehearsalRoleArn,
|
|
8313
|
-
region: rehearsalRegion,
|
|
8314
|
-
stage: rehearsalStage,
|
|
8315
|
-
wafContractDigest: routerWafContractDigest(normalizedRouterWafPolicy),
|
|
8316
|
-
workspace: '${name}',
|
|
8317
|
-
},
|
|
8318
|
-
policy: normalizedRouterWafPolicy,
|
|
8319
|
-
receipt: routerWafBlockingRehearsal,
|
|
8320
|
-
})
|
|
8321
|
-
: null,
|
|
8400
|
+
rehearsal,
|
|
8322
8401
|
stage: $app.stage,
|
|
8323
8402
|
});
|
|
8324
8403
|
const deploymentAccount = process.env.AWS_EXPECTED_ACCOUNT_ID?.trim() ?? '';
|
|
@@ -8753,7 +8832,7 @@ ${foundationPlan.resources.postgres
|
|
|
8753
8832
|
{ dependsOn: [alertTopicPolicy] },
|
|
8754
8833
|
)
|
|
8755
8834
|
: undefined;
|
|
8756
|
-
const dashboard = new aws.cloudwatch.Dashboard('FoundationDashboard', {
|
|
8835
|
+
const dashboard = observability.dashboards === 'none' ? undefined : new aws.cloudwatch.Dashboard('FoundationDashboard', {
|
|
8757
8836
|
dashboardName: 'ebk-' + $app.stage + '-foundation',
|
|
8758
8837
|
dashboardBody: databaseInstanceId.apply((identifier: string) => JSON.stringify({
|
|
8759
8838
|
widgets: [
|
|
@@ -8824,12 +8903,18 @@ ${foundationPlan.resources.postgres
|
|
|
8824
8903
|
treatMissingData: 'notBreaching',
|
|
8825
8904
|
},
|
|
8826
8905
|
);`
|
|
8827
|
-
: ` const dashboard = new aws.cloudwatch.Dashboard('FoundationDashboard', {
|
|
8906
|
+
: ` const dashboard = observability.dashboards === 'none' ? undefined : new aws.cloudwatch.Dashboard('FoundationDashboard', {
|
|
8828
8907
|
dashboardName: 'ebk-' + $app.stage + '-foundation',
|
|
8829
|
-
dashboardBody: JSON.stringify({ widgets: [{
|
|
8830
|
-
type: '
|
|
8831
|
-
properties: {
|
|
8832
|
-
|
|
8908
|
+
dashboardBody: router.distributionID.apply((distributionId: string) => JSON.stringify({ widgets: [{
|
|
8909
|
+
type: 'metric', x: 0, y: 0, width: 24, height: 6,
|
|
8910
|
+
properties: {
|
|
8911
|
+
title: 'Router requests and errors', region: 'us-east-1', period: 300,
|
|
8912
|
+
metrics: [
|
|
8913
|
+
['AWS/CloudFront', 'Requests', 'DistributionId', distributionId, 'Region', 'Global', { stat: 'Sum' }],
|
|
8914
|
+
['AWS/CloudFront', '5xxErrorRate', 'DistributionId', distributionId, 'Region', 'Global', { stat: 'Average', yAxis: 'right' }],
|
|
8915
|
+
],
|
|
8916
|
+
},
|
|
8917
|
+
}] })),
|
|
8833
8918
|
});`}
|
|
8834
8919
|
|
|
8835
8920
|
if (new Set(['development', 'staging', 'production']).has($app.stage)) {
|
|
@@ -8879,7 +8964,7 @@ ${foundationPlan.resources.containerCompute ? ' clusterId: cluster.id,' : ''}
|
|
|
8879
8964
|
contractVersion: '${foundationPlan.descriptor.contractVersion}',
|
|
8880
8965
|
costAnomalySubscriptionArn: accountCostAnomalySubscription?.arn,
|
|
8881
8966
|
${foundationPlan.resources.postgres ? ' databaseCapacityAlarmName: databaseCapacityAlarm.name,' : ''}
|
|
8882
|
-
dashboardName: dashboard
|
|
8967
|
+
dashboardName: dashboard?.dashboardName,
|
|
8883
8968
|
${foundationPlan.resources.postgres
|
|
8884
8969
|
? ` databaseClusterId: database.id,
|
|
8885
8970
|
databaseEventSubscriptionId: databaseEvents?.id,`
|