@empire-builder-kit/nx 1.0.0-rc.31 → 1.0.0-rc.32
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 +7 -3
- package/src/aws/identity.js +1 -1
- package/src/aws/identity.js.map +1 -1
- package/src/aws-authority/stage-authority.d.ts +2 -0
- package/src/aws-authority/stage-authority.js +152 -20
- package/src/aws-authority/stage-authority.js.map +1 -1
- package/src/cli/main.d.ts +2 -0
- package/src/cli/main.js +11 -0
- package/src/cli/main.js.map +1 -1
- package/src/developer-agent/workspace-inspection.js +11 -2
- package/src/developer-agent/workspace-inspection.js.map +1 -1
- package/src/executors/github-bootstrap/github-bootstrap.d.ts +1 -0
- package/src/executors/github-bootstrap/github-bootstrap.js +1 -0
- package/src/executors/github-bootstrap/github-bootstrap.js.map +1 -1
- package/src/executors/github-bootstrap/schema.json +7 -1
- package/src/executors/infrastructure-plan/infrastructure-plan.d.ts +2 -0
- package/src/executors/infrastructure-plan/infrastructure-plan.js +18 -1
- package/src/executors/infrastructure-plan/infrastructure-plan.js.map +1 -1
- package/src/executors/local-deploy/local-deploy.d.ts +2 -0
- package/src/executors/local-deploy/local-deploy.js +17 -0
- package/src/executors/local-deploy/local-deploy.js.map +1 -1
- package/src/executors/router-waf-rehearsal/router-waf-rehearsal.d.ts +2 -0
- package/src/executors/router-waf-rehearsal/router-waf-rehearsal.js +2 -0
- package/src/executors/router-waf-rehearsal/router-waf-rehearsal.js.map +1 -1
- package/src/executors/secret-initialize/secret-initialize.d.ts +2 -0
- package/src/executors/secret-initialize/secret-initialize.js +14 -0
- package/src/executors/secret-initialize/secret-initialize.js.map +1 -1
- package/src/executors/secret-metadata/secret-metadata.d.ts +2 -0
- package/src/executors/secret-metadata/secret-metadata.js +14 -0
- package/src/executors/secret-metadata/secret-metadata.js.map +1 -1
- package/src/executors/sst-lifecycle/run-sst-command.d.ts +2 -0
- package/src/executors/sst-lifecycle/run-sst-command.js +17 -2
- package/src/executors/sst-lifecycle/run-sst-command.js.map +1 -1
- package/src/foundation/provision-logical-database.js +2 -0
- package/src/foundation/provision-logical-database.js.map +1 -1
- package/src/generators/preset/generator.js +6 -1
- package/src/generators/preset/generator.js.map +1 -1
- package/src/generators/preset/schema.d.ts +3 -0
- package/src/generators/preset/schema.json +5 -5
- package/src/generators/preset/workspace-files-performance-load.js +21 -12
- package/src/generators/preset/workspace-files-performance-load.js.map +1 -1
- package/src/generators/preset/workspace-files-stage-authority.d.ts +2 -0
- package/src/generators/preset/workspace-files-stage-authority.js +264 -60
- package/src/generators/preset/workspace-files-stage-authority.js.map +1 -1
- package/src/generators/preset/workspace-files-thin-deploy.d.ts +6 -1
- package/src/generators/preset/workspace-files-thin-deploy.js +102 -36
- package/src/generators/preset/workspace-files-thin-deploy.js.map +1 -1
- package/src/generators/preset/workspace-files-thin-docs.js +26 -10
- package/src/generators/preset/workspace-files-thin-docs.js.map +1 -1
- package/src/generators/preset/workspace-files.d.ts +1 -0
- package/src/generators/preset/workspace-files.js +111 -493
- package/src/generators/preset/workspace-files.js.map +1 -1
- package/src/generators/repository-policy/repository-policy.js +149 -19
- package/src/generators/repository-policy/repository-policy.js.map +1 -1
- package/src/generators/repository-policy/schema.d.ts +2 -0
- package/src/generators/repository-policy/schema.json +11 -1
- package/src/generators/repository-policy/tree-policy.d.ts +3 -0
- package/src/generators/repository-policy/tree-policy.js +25 -0
- package/src/generators/repository-policy/tree-policy.js.map +1 -0
- package/src/generators/slice/built-in-plan-async-work-files.js +41 -0
- package/src/generators/slice/built-in-plan-async-work-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-authorization-infrastructure-files.js +2 -0
- package/src/generators/slice/built-in-plan-authorization-infrastructure-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.js +19 -0
- package/src/generators/slice/built-in-plan-data-lifecycle-runtime-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-data-retention-launcher-files.js +21 -3
- package/src/generators/slice/built-in-plan-data-retention-launcher-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.js +20 -1
- package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-operations-files.js +22 -2
- package/src/generators/slice/built-in-plan-operations-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-performance-files.js +60 -0
- package/src/generators/slice/built-in-plan-performance-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-secret-runtime-files.js +13 -0
- package/src/generators/slice/built-in-plan-secret-runtime-files.js.map +1 -1
- package/src/generators/slice/built-in-plan-testing-files.js +20 -0
- package/src/generators/slice/built-in-plan-testing-files.js.map +1 -1
- package/src/generators/slice/slice.js +3 -3
- package/src/generators/slice/slice.js.map +1 -1
- package/src/generators/upgrade/upgrade.js +25 -28
- package/src/generators/upgrade/upgrade.js.map +1 -1
- package/src/generators/workload/performance-registration.js +4 -8
- package/src/generators/workload/performance-registration.js.map +1 -1
- package/src/git-policy/github-bootstrap.d.ts +10 -2
- package/src/git-policy/github-bootstrap.js +109 -13
- package/src/git-policy/github-bootstrap.js.map +1 -1
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -1
- package/src/local-dev/tls.js +5 -1
- package/src/local-dev/tls.js.map +1 -1
- package/src/repository-policy/policy.d.ts +16 -1
- package/src/repository-policy/policy.js +226 -12
- package/src/repository-policy/policy.js.map +1 -1
- package/src/schemas/repository-policy-v1.json +46 -2
- package/src/secrets/adapters.d.ts +2 -1
- package/src/secrets/adapters.js +12 -2
- package/src/secrets/adapters.js.map +1 -1
- package/src/supply-chain/generated-container-release-command.js +41 -18
- package/src/supply-chain/generated-container-release-command.js.map +1 -1
- package/src/workspace-deployment/identity.d.ts +3 -0
- package/src/workspace-deployment/identity.js +22 -0
- package/src/workspace-deployment/identity.js.map +1 -0
- package/src/workspace-deployment/index.d.ts +3 -0
- package/src/workspace-deployment/index.js +7 -0
- package/src/workspace-deployment/index.js.map +1 -0
- package/src/workspace-deployment/migration-evidence.d.ts +29 -0
- package/src/workspace-deployment/migration-evidence.js +83 -0
- package/src/workspace-deployment/migration-evidence.js.map +1 -0
- package/src/workspace-deployment/migration.d.ts +27 -0
- package/src/workspace-deployment/migration.js +109 -0
- package/src/workspace-deployment/migration.js.map +1 -0
- package/src/workspace-deployment/ownership.d.ts +81 -0
- package/src/workspace-deployment/ownership.js +381 -0
- package/src/workspace-deployment/ownership.js.map +1 -0
|
@@ -173,6 +173,49 @@ const TOOL_VERSIONS = {
|
|
|
173
173
|
function json(value) {
|
|
174
174
|
return `${JSON.stringify(value, null, 2)}\n`;
|
|
175
175
|
}
|
|
176
|
+
function indentWorkflowScript(source, spaces) {
|
|
177
|
+
const prefix = ' '.repeat(spaces);
|
|
178
|
+
return source
|
|
179
|
+
.trim()
|
|
180
|
+
.split('\n')
|
|
181
|
+
.map((line) => `${prefix}${line}`)
|
|
182
|
+
.join('\n');
|
|
183
|
+
}
|
|
184
|
+
function protectedSecretPolicyDerivationScript() {
|
|
185
|
+
return `node --input-type=module <<'NODE'
|
|
186
|
+
import { appendFileSync } from 'node:fs';
|
|
187
|
+
import {
|
|
188
|
+
configuredDeploymentAccountTopology,
|
|
189
|
+
configuredDeploymentRegion,
|
|
190
|
+
isActiveDeploymentStage,
|
|
191
|
+
readRepositoryOperatingPolicy,
|
|
192
|
+
} from '@empire-builder-kit/nx/repository-policy';
|
|
193
|
+
|
|
194
|
+
const output = process.env.GITHUB_OUTPUT?.trim() ?? '';
|
|
195
|
+
const renderedProfile = process.env.EBK_RENDERED_PROFILE?.trim() ?? '';
|
|
196
|
+
const stage = process.env.EBK_STAGE?.trim() ?? '';
|
|
197
|
+
if (!output) throw new Error('Secret workflow authority output is unavailable.');
|
|
198
|
+
const policy = readRepositoryOperatingPolicy(process.cwd());
|
|
199
|
+
if (policy.deploymentProfile !== renderedProfile) {
|
|
200
|
+
throw new Error('Generated and committed deployment profiles differ.');
|
|
201
|
+
}
|
|
202
|
+
if (!isActiveDeploymentStage(policy.deploymentProfile, stage)) {
|
|
203
|
+
throw new Error('Secret workflow stage is inactive for the committed deployment profile.');
|
|
204
|
+
}
|
|
205
|
+
const accounts = configuredDeploymentAccountTopology(
|
|
206
|
+
policy.deploymentProfile,
|
|
207
|
+
policy.deploymentAccounts,
|
|
208
|
+
);
|
|
209
|
+
const region = configuredDeploymentRegion(policy.deploymentRegion);
|
|
210
|
+
appendFileSync(output, [
|
|
211
|
+
'deployment_region=' + region,
|
|
212
|
+
'development_account_id=' + accounts.development,
|
|
213
|
+
'staging_account_id=' + (accounts.staging ?? ''),
|
|
214
|
+
'production_account_id=' + accounts.production,
|
|
215
|
+
'',
|
|
216
|
+
].join('\\n'));
|
|
217
|
+
NODE`;
|
|
218
|
+
}
|
|
176
219
|
function planApplicationBindingCheck() {
|
|
177
220
|
return ` node - <<'NODE'
|
|
178
221
|
const declared = JSON.parse(process.env.AWS_PLAN_SST_APPS_JSON ?? '');
|
|
@@ -1017,6 +1060,7 @@ const WORKSPACE_SEEDED_PATHS = new Set([
|
|
|
1017
1060
|
'docs/git-workflow.md',
|
|
1018
1061
|
'docs/repository-operating-policy.md',
|
|
1019
1062
|
'docs/stage-deployment-authority.md',
|
|
1063
|
+
'docs/workspace-deployment-ownership.md',
|
|
1020
1064
|
'docs/work-markers.md',
|
|
1021
1065
|
'ebk.repository-policy.json',
|
|
1022
1066
|
]);
|
|
@@ -1136,7 +1180,9 @@ function renderWorkspaceFiles(options) {
|
|
|
1136
1180
|
: protectedWorkflowStageChoices;
|
|
1137
1181
|
const rehearsalStage = (0, index_js_4.productionRehearsalStage)(deploymentProfile);
|
|
1138
1182
|
const protectedWorkflowStageBranchCases = `${rehearsalStage}:refs/heads/develop|production:refs/heads/main`;
|
|
1139
|
-
const
|
|
1183
|
+
const workspaceDeploymentId = options.workspaceDeploymentId ??
|
|
1184
|
+
`ebkws-${(0, index_js_1.hashGeneratedContent)(`workspace-deployment-id:${name}`).slice(0, 32)}`;
|
|
1185
|
+
const initialRepositoryPolicy = (0, index_js_4.createIncubationRepositoryPolicy)(deploymentProfile, workspaceDeploymentId);
|
|
1140
1186
|
initialRepositoryPolicy.deploymentAccounts = options.deploymentAccounts ?? {
|
|
1141
1187
|
development: null,
|
|
1142
1188
|
production: null,
|
|
@@ -7131,11 +7177,9 @@ jobs:
|
|
|
7131
7177
|
contents: read
|
|
7132
7178
|
id-token: write
|
|
7133
7179
|
env:
|
|
7134
|
-
AWS_DEPLOY_ROLE_ARN: \${{ secrets.AWS_DEPLOY_ROLE_ARN }}
|
|
7135
|
-
AWS_EXPECTED_ACCOUNT_ID: \${{ vars.AWS_EXPECTED_ACCOUNT_ID }}
|
|
7136
|
-
AWS_REGION: \${{ vars.AWS_REGION }}
|
|
7137
7180
|
EBK_ACTION: \${{ inputs.action }}
|
|
7138
7181
|
EBK_PROJECT: \${{ inputs.project }}
|
|
7182
|
+
EBK_RENDERED_PROFILE: ${deploymentProfile}
|
|
7139
7183
|
EBK_STAGE: \${{ inputs.stage }}
|
|
7140
7184
|
runs-on: ubuntu-latest
|
|
7141
7185
|
steps:
|
|
@@ -7150,13 +7194,6 @@ jobs:
|
|
|
7150
7194
|
case "$EBK_PROJECT" in
|
|
7151
7195
|
''|-*|*-|*[!a-z0-9-]*) echo 'Secret metadata project must be an exact normalized Slice name'; exit 1 ;;
|
|
7152
7196
|
esac
|
|
7153
|
-
test -n "$AWS_DEPLOY_ROLE_ARN" || { echo "$EBK_STAGE AWS_DEPLOY_ROLE_ARN is required"; exit 1; }
|
|
7154
|
-
test -n "$AWS_EXPECTED_ACCOUNT_ID" || { echo "$EBK_STAGE AWS_EXPECTED_ACCOUNT_ID is required"; exit 1; }
|
|
7155
|
-
test -n "$AWS_REGION" || { echo "$EBK_STAGE AWS_REGION is required"; exit 1; }
|
|
7156
|
-
case "$AWS_DEPLOY_ROLE_ARN" in
|
|
7157
|
-
arn:aws:iam::$AWS_EXPECTED_ACCOUNT_ID:role/*) ;;
|
|
7158
|
-
*) echo 'Secret metadata role does not belong to the expected account'; exit 1 ;;
|
|
7159
|
-
esac
|
|
7160
7197
|
- uses: ${checkoutAction}
|
|
7161
7198
|
with:
|
|
7162
7199
|
persist-credentials: false
|
|
@@ -7168,14 +7205,37 @@ jobs:
|
|
|
7168
7205
|
- run: pnpm install --frozen-lockfile --ignore-scripts --ignore-pnpmfile
|
|
7169
7206
|
- name: Verify managed workspace integrity before AWS authority
|
|
7170
7207
|
run: pnpm nx run ${name}:workspace-health
|
|
7208
|
+
- id: policy
|
|
7209
|
+
name: Derive committed secret metadata stage policy
|
|
7210
|
+
run: |
|
|
7211
|
+
${indentWorkflowScript(protectedSecretPolicyDerivationScript(), 10)}
|
|
7212
|
+
- id: authority
|
|
7213
|
+
name: Derive canonical committed stage authority
|
|
7214
|
+
env:
|
|
7215
|
+
EBK_DEVELOPMENT_ACCOUNT: \${{ steps.policy.outputs.development_account_id }}
|
|
7216
|
+
EBK_PRODUCTION_ACCOUNT: \${{ steps.policy.outputs.production_account_id }}
|
|
7217
|
+
EBK_REGION: \${{ steps.policy.outputs.deployment_region }}
|
|
7218
|
+
EBK_STAGING_ACCOUNT: \${{ steps.policy.outputs.staging_account_id }}
|
|
7219
|
+
run: |
|
|
7220
|
+
${indentWorkflowScript(`set -euo pipefail\n${(0, workspace_files_thin_deploy_js_1.canonicalStageAuthorityDerivationScript)()}`, 10)}
|
|
7171
7221
|
- uses: ${configureAwsAction}
|
|
7172
7222
|
with:
|
|
7173
|
-
|
|
7223
|
+
audience: \${{ steps.authority.outputs.audience }}
|
|
7224
|
+
role-to-assume: \${{ steps.authority.outputs.role_arn }}
|
|
7174
7225
|
role-session-name: ebk-secret-metadata-\${{ github.run_id }}-\${{ github.run_attempt }}
|
|
7175
|
-
aws-region: \${{
|
|
7176
|
-
- name: Verify
|
|
7177
|
-
|
|
7226
|
+
aws-region: \${{ steps.policy.outputs.deployment_region }}
|
|
7227
|
+
- name: Verify exact stage authority
|
|
7228
|
+
env:
|
|
7229
|
+
AWS_DEPLOY_ROLE_ARN: \${{ steps.authority.outputs.role_arn }}
|
|
7230
|
+
AWS_PARTITION: \${{ steps.authority.outputs.partition }}
|
|
7231
|
+
EBK_POLICY_ACCOUNT_ID: \${{ steps.authority.outputs.account_id }}
|
|
7232
|
+
run: |
|
|
7233
|
+
${indentWorkflowScript((0, workspace_files_thin_deploy_js_1.exactStageDeployerGuardScript)('Secret metadata', '$EBK_POLICY_ACCOUNT_ID'), 10)}
|
|
7178
7234
|
- name: Reconcile value-blind metadata
|
|
7235
|
+
env:
|
|
7236
|
+
AWS_DEPLOY_ROLE_ARN: \${{ steps.authority.outputs.role_arn }}
|
|
7237
|
+
AWS_EXPECTED_ACCOUNT_ID: \${{ steps.authority.outputs.account_id }}
|
|
7238
|
+
AWS_REGION: \${{ steps.policy.outputs.deployment_region }}
|
|
7179
7239
|
run: |
|
|
7180
7240
|
args=("--stage=$EBK_STAGE" "--region=$AWS_REGION")
|
|
7181
7241
|
if [ "$EBK_ACTION" = apply ]; then args+=("--apply"); fi
|
|
@@ -7220,12 +7280,10 @@ jobs:
|
|
|
7220
7280
|
contents: read
|
|
7221
7281
|
id-token: write
|
|
7222
7282
|
env:
|
|
7223
|
-
AWS_DEPLOY_ROLE_ARN: \${{ secrets.AWS_DEPLOY_ROLE_ARN }}
|
|
7224
|
-
AWS_EXPECTED_ACCOUNT_ID: \${{ vars.AWS_EXPECTED_ACCOUNT_ID }}
|
|
7225
|
-
AWS_REGION: \${{ vars.AWS_REGION }}
|
|
7226
7283
|
EBK_ACTION: \${{ inputs.action }}
|
|
7227
7284
|
EBK_LOGICAL_NAME: \${{ inputs.logical_name }}
|
|
7228
7285
|
EBK_PROJECT: \${{ inputs.project }}
|
|
7286
|
+
EBK_RENDERED_PROFILE: ${deploymentProfile}
|
|
7229
7287
|
EBK_STAGE: \${{ inputs.stage }}
|
|
7230
7288
|
runs-on: ubuntu-latest
|
|
7231
7289
|
steps:
|
|
@@ -7242,13 +7300,6 @@ jobs:
|
|
|
7242
7300
|
esac
|
|
7243
7301
|
[[ "$EBK_LOGICAL_NAME" =~ ^[A-Za-z][A-Za-z0-9]{0,63}$ ]] ||
|
|
7244
7302
|
{ echo 'Secret initialize logical name is invalid'; exit 1; }
|
|
7245
|
-
test -n "$AWS_DEPLOY_ROLE_ARN" || { echo "$EBK_STAGE AWS_DEPLOY_ROLE_ARN is required"; exit 1; }
|
|
7246
|
-
test -n "$AWS_EXPECTED_ACCOUNT_ID" || { echo "$EBK_STAGE AWS_EXPECTED_ACCOUNT_ID is required"; exit 1; }
|
|
7247
|
-
test -n "$AWS_REGION" || { echo "$EBK_STAGE AWS_REGION is required"; exit 1; }
|
|
7248
|
-
case "$AWS_DEPLOY_ROLE_ARN" in
|
|
7249
|
-
arn:aws:iam::$AWS_EXPECTED_ACCOUNT_ID:role/*) ;;
|
|
7250
|
-
*) echo 'Secret initialize role does not belong to the expected account'; exit 1 ;;
|
|
7251
|
-
esac
|
|
7252
7303
|
- uses: ${checkoutAction}
|
|
7253
7304
|
with:
|
|
7254
7305
|
persist-credentials: false
|
|
@@ -7260,14 +7311,37 @@ jobs:
|
|
|
7260
7311
|
- run: pnpm install --frozen-lockfile --ignore-scripts --ignore-pnpmfile
|
|
7261
7312
|
- name: Verify managed workspace integrity before AWS authority
|
|
7262
7313
|
run: pnpm nx run ${name}:workspace-health
|
|
7314
|
+
- id: policy
|
|
7315
|
+
name: Derive committed secret initialize stage policy
|
|
7316
|
+
run: |
|
|
7317
|
+
${indentWorkflowScript(protectedSecretPolicyDerivationScript(), 10)}
|
|
7318
|
+
- id: authority
|
|
7319
|
+
name: Derive canonical committed stage authority
|
|
7320
|
+
env:
|
|
7321
|
+
EBK_DEVELOPMENT_ACCOUNT: \${{ steps.policy.outputs.development_account_id }}
|
|
7322
|
+
EBK_PRODUCTION_ACCOUNT: \${{ steps.policy.outputs.production_account_id }}
|
|
7323
|
+
EBK_REGION: \${{ steps.policy.outputs.deployment_region }}
|
|
7324
|
+
EBK_STAGING_ACCOUNT: \${{ steps.policy.outputs.staging_account_id }}
|
|
7325
|
+
run: |
|
|
7326
|
+
${indentWorkflowScript(`set -euo pipefail\n${(0, workspace_files_thin_deploy_js_1.canonicalStageAuthorityDerivationScript)()}`, 10)}
|
|
7263
7327
|
- uses: ${configureAwsAction}
|
|
7264
7328
|
with:
|
|
7265
|
-
|
|
7329
|
+
audience: \${{ steps.authority.outputs.audience }}
|
|
7330
|
+
role-to-assume: \${{ steps.authority.outputs.role_arn }}
|
|
7266
7331
|
role-session-name: ebk-secret-initialize-\${{ github.run_id }}-\${{ github.run_attempt }}
|
|
7267
|
-
aws-region: \${{
|
|
7268
|
-
- name: Verify
|
|
7269
|
-
|
|
7332
|
+
aws-region: \${{ steps.policy.outputs.deployment_region }}
|
|
7333
|
+
- name: Verify exact stage authority
|
|
7334
|
+
env:
|
|
7335
|
+
AWS_DEPLOY_ROLE_ARN: \${{ steps.authority.outputs.role_arn }}
|
|
7336
|
+
AWS_PARTITION: \${{ steps.authority.outputs.partition }}
|
|
7337
|
+
EBK_POLICY_ACCOUNT_ID: \${{ steps.authority.outputs.account_id }}
|
|
7338
|
+
run: |
|
|
7339
|
+
${indentWorkflowScript((0, workspace_files_thin_deploy_js_1.exactStageDeployerGuardScript)('Secret initialize', '$EBK_POLICY_ACCOUNT_ID'), 10)}
|
|
7270
7340
|
- name: Initialize machine-generated secret value-blind
|
|
7341
|
+
env:
|
|
7342
|
+
AWS_DEPLOY_ROLE_ARN: \${{ steps.authority.outputs.role_arn }}
|
|
7343
|
+
AWS_EXPECTED_ACCOUNT_ID: \${{ steps.authority.outputs.account_id }}
|
|
7344
|
+
AWS_REGION: \${{ steps.policy.outputs.deployment_region }}
|
|
7271
7345
|
run: |
|
|
7272
7346
|
args=("--logicalName=$EBK_LOGICAL_NAME" "--stage=$EBK_STAGE" "--region=$AWS_REGION")
|
|
7273
7347
|
if [ "$EBK_ACTION" = apply ]; then args+=("--apply"); fi
|
|
@@ -7624,50 +7698,6 @@ export default tseslint.config(
|
|
|
7624
7698
|
rules: { 'no-console': 'error' },
|
|
7625
7699
|
},
|
|
7626
7700
|
);
|
|
7627
|
-
`,
|
|
7628
|
-
'README.md': `# ${name}
|
|
7629
|
-
|
|
7630
|
-
This workspace was created with Empire Builder Kit v1.
|
|
7631
|
-
|
|
7632
|
-
## Start here
|
|
7633
|
-
|
|
7634
|
-
1. Review \`docs/architecture.md\`.
|
|
7635
|
-
2. Review the generated Foundation before deploying it.
|
|
7636
|
-
3. Add product slices through the Empire Builder Kit Nx plugin.
|
|
7637
|
-
4. Review \`docs/repository-operating-policy.md\` and \`docs/git-workflow.md\` before enabling production.
|
|
7638
|
-
5. Read \`AGENTS.md\` and \`docs/work-markers.md\` before assigning generated customization work to agents.
|
|
7639
|
-
|
|
7640
|
-
For one-origin fleet development, initialize the workspace-pinned CLI once with
|
|
7641
|
-
\`ebk dev configure --profile=<bounded-development-profile>\`, inspect the certificate reported
|
|
7642
|
-
by \`ebk dev setup\`, and then explicitly approve \`ebk dev setup --trust\`. The supported v1
|
|
7643
|
-
origin uses the complete explicit-port HTTPS URL reported at startup; optional
|
|
7644
|
-
\`--portless\` setup is experimental. \`ebk dev doctor\` requires a real exact-host TLS
|
|
7645
|
-
handshake for trust and connectivity readiness, and reports portless access ready
|
|
7646
|
-
only after a live port-443 probe. Complete
|
|
7647
|
-
\`aws sso login --profile <bounded-development-profile>\`, then start selected Slices with
|
|
7648
|
-
\`ebk dev up billing accounts\`. The CLI derives the personal stage from the operating-system
|
|
7649
|
-
account, reads the saved profile and Region, propagates that AWS context to child Slices, and
|
|
7650
|
-
uses SST \`mono\` mode so agents and non-cursor-addressable terminals receive ordinary logs.
|
|
7651
|
-
Use \`ebk dev status\`, \`ebk dev logs\`, \`ebk dev tail\`, \`ebk dev restart\`,
|
|
7652
|
-
\`ebk dev down\`, and \`ebk dev doctor\` without supplying a stage. Setup, doctor, and the
|
|
7653
|
-
managed root Fleet target remain internal Nx-backed implementation surfaces; \`ebk dev\` is the
|
|
7654
|
-
framework-local development interface. For the development namespace, if the shell does not
|
|
7655
|
-
expose workspace binaries, \`pnpm exec ebk dev ...\` only locates the workspace-pinned binary;
|
|
7656
|
-
it is not another framework command surface. Protected Blueprint receipt review must instead
|
|
7657
|
-
use the direct installed \`.bin/ebk blueprint verification-review\` entry documented in
|
|
7658
|
-
\`docs/blueprints.md\`.
|
|
7659
|
-
|
|
7660
|
-
Workspace creation only writes source files. It does not create or change cloud resources.
|
|
7661
|
-
|
|
7662
|
-
New workspaces default to the one-account \`starter\` deployment profile. Configure the exact
|
|
7663
|
-
shared account and Region in \`ebk.repository-policy.json\`, authenticate through IAM Identity
|
|
7664
|
-
Center, add exact development and staging CIDRs to
|
|
7665
|
-
\`packages/foundation/security/router-waf.json\`, and use
|
|
7666
|
-
\`pnpm nx run ${name}:deploy-local -- --stage=development
|
|
7667
|
-
--profile=<profile> --expectedRoleArn=<role-arn>\`. Never invoke SST directly.
|
|
7668
|
-
For a brand-new stage with generated Product Slices, complete the documented workload-role
|
|
7669
|
-
Foundation publication and pass \`--phase=foundation-bootstrap\` once before publishing and
|
|
7670
|
-
deploying the complete stage.
|
|
7671
7701
|
`,
|
|
7672
7702
|
'docs/architecture.md': `# Workspace architecture
|
|
7673
7703
|
|
|
@@ -7690,286 +7720,6 @@ Every active canonical stage owns a separate Router/domain, Aurora cluster and m
|
|
|
7690
7720
|
Cognito user pool, event bus, secret namespace, IAM boundary, logs, queues, ECR namespace, and
|
|
7691
7721
|
stage-qualified SSM discovery contract. Discovery rejects a record for an inactive or different
|
|
7692
7722
|
canonical stage.
|
|
7693
|
-
`,
|
|
7694
|
-
'docs/git-workflow.md': `# Protected Git workflow
|
|
7695
|
-
|
|
7696
|
-
Ordinary work starts from \`develop\` and returns through a reviewed pull request to
|
|
7697
|
-
\`develop\`. A production promotion is exactly \`develop\` to \`main\`. After production,
|
|
7698
|
-
review and merge the managed \`main\` to \`develop\` sync-back pull request before ordinary
|
|
7699
|
-
work resumes.
|
|
7700
|
-
|
|
7701
|
-
Both protected branches require the stable \`policy\` and \`verify\` checks, one approving
|
|
7702
|
-
review including an approval from the committed catch-all CODEOWNER and someone other than the
|
|
7703
|
-
most recent pusher, dismissed stale reviews, resolved conversations, and merge commits. Replace
|
|
7704
|
-
the placeholder in \`.github/CODEOWNERS\` with a GitHub user or team that has repository access
|
|
7705
|
-
before bootstrap. An approval from \`github-actions[bot]\` cannot satisfy the independent
|
|
7706
|
-
code-owner gate; the Actions repository setting is needed to create the managed sync-back pull
|
|
7707
|
-
request, not to approve it.
|
|
7708
|
-
Direct updates, force pushes, deletion, squash merging, and rebase merging are prohibited.
|
|
7709
|
-
GitHub rulesets, environments, and AWS IAM are the authorization boundaries; local hooks are
|
|
7710
|
-
only defense in depth.
|
|
7711
|
-
|
|
7712
|
-
The rehearsal environment accepts only \`develop\`; \`production\` accepts only \`main\`.
|
|
7713
|
-
For \`starter\`, development is the rehearsal stage and GitHub deployment is optional for both
|
|
7714
|
-
development and production. For isolated profiles, staging is the rehearsal stage;
|
|
7715
|
-
\`production-isolated\` requires GitHub for production and \`fully-isolated\` requires GitHub
|
|
7716
|
-
for staging and production.
|
|
7717
|
-
The committed \`productionApproval.mode\` selects one of two production authorization
|
|
7718
|
-
contracts:
|
|
7719
|
-
|
|
7720
|
-
- \`promotion-pr\` is compatible with private repositories on GitHub Team. The required
|
|
7721
|
-
non-author CODEOWNER approval on the exact \`develop\` to \`main\` promotion pull request
|
|
7722
|
-
is the production authorization. Merging that pull request starts production deployment;
|
|
7723
|
-
there is no second EBK-managed environment approval or wait timer. The approver may also be
|
|
7724
|
-
the human whose merge triggers deployment. Roll back through a reviewed revert on the
|
|
7725
|
-
protected branches and let the resulting \`main\` push redeploy. A repository write actor who
|
|
7726
|
-
can run Actions may also manually dispatch \`deploy\`, \`refresh\`, or \`unlock\` against the
|
|
7727
|
-
already approved \`main\` tip without another human gate. That residual cannot introduce
|
|
7728
|
-
unreviewed source; production \`remove\` remains separately variable-gated. Restrict write and
|
|
7729
|
-
Actions access, audit dispatches, or select \`environment-reviewer\` when every production
|
|
7730
|
-
action needs separate approval.
|
|
7731
|
-
- \`environment-reviewer\` adds a separate production environment reviewer with self-review
|
|
7732
|
-
prevention. A private repository needs GitHub Enterprise capability for this mode. Bootstrap
|
|
7733
|
-
inspects that capability and fails closed on an unsupported plan; it never silently changes
|
|
7734
|
-
the committed mode.
|
|
7735
|
-
|
|
7736
|
-
Both modes retain required checks, a non-author CODEOWNER approval, no ruleset bypass, the
|
|
7737
|
-
literal production environment, and its branch-scoped credentials. The base \`staging\` and
|
|
7738
|
-
\`production\` environments own deployment and smoke authority plus their variables; isolated
|
|
7739
|
-
profiles also keep the staging-registry promotion pull role in production. Read-only container
|
|
7740
|
-
evidence uses only \`ecr-inspector-<stage>\`, which owns the exact evidence role and must trust
|
|
7741
|
-
that dedicated immutable repository/environment subject rather than the base stage subject.
|
|
7742
|
-
Starter promotion authenticates once to the shared account and copies the exact staging digest
|
|
7743
|
-
into a distinct production ECR repository. Dedicated
|
|
7744
|
-
\`infrastructure-plan-<stage>\` environments gate read-only role use. Separate
|
|
7745
|
-
\`async-recovery-<stage>\` and \`reliability-read-<stage>\` environments own only the role and
|
|
7746
|
-
variables required by that capability. Infrastructure-plan jobs use a repository-variable read-only role/input inventory;
|
|
7747
|
-
an independent clean audit job assumes that exact environment-subject role and verifies its
|
|
7748
|
-
trust and complete inline policy before any repository-backed plan job may assume it. Plan-role
|
|
7749
|
-
trust uses GitHub's immutable repository identity subject,
|
|
7750
|
-
\`repo:<owner>@<owner-id>/<repository>@<repository-id>:environment:<environment>\`.
|
|
7751
|
-
The audit derives it from the workflow's repository name, owner ID, repository ID, and literal
|
|
7752
|
-
environment and refuses missing IDs or the older mutable name-only subject. Update every
|
|
7753
|
-
adopter-owned AWS OIDC role trust to the immutable identity before protected use; never retain
|
|
7754
|
-
both forms. Every
|
|
7755
|
-
\`*-staging\` environment accepts only \`develop\`; every
|
|
7756
|
-
\`*-production\` environment accepts only \`main\`; reviewer, self-review, and wait protection
|
|
7757
|
-
matches the corresponding base stage. The credential-free \`npm-prerelease\` environment
|
|
7758
|
-
accepts only \`main\` and contains no secrets or variables. In Team-compatible
|
|
7759
|
-
\`promotion-pr\` mode, protected-main review plus the exact current-main tag binding is
|
|
7760
|
-
publication authorization, so it has no reviewer or wait rule. In
|
|
7761
|
-
\`environment-reviewer\` mode it mirrors production protection. Never add repository- or
|
|
7762
|
-
organization-visible fallbacks for protected values. Keep repository default workflow
|
|
7763
|
-
permissions read-only; generated jobs request only the additional permissions they need.
|
|
7764
|
-
|
|
7765
|
-
\`EBK_FLEET_ORIGIN\` is the sole protected deployment and smoke origin. Read-only plan jobs
|
|
7766
|
-
enter only their dedicated \`infrastructure-plan-<stage>\` environment; their stage-named
|
|
7767
|
-
repository variables \`EBK_STAGING_FLEET_ORIGIN\` and
|
|
7768
|
-
\`EBK_PRODUCTION_FLEET_ORIGIN\` remain plan inputs only. Before mutation, each
|
|
7769
|
-
base-environment-protected deployment requires
|
|
7770
|
-
its \`EBK_FLEET_ORIGIN\` to equal the origin retained by the plan.
|
|
7771
|
-
|
|
7772
|
-
\`AWS_ASYNC_RECOVERY_ROLE_ARN\` is a separate mutation role. Trust only this
|
|
7773
|
-
repository's exact \`async-recovery-<stage>\` GitHub OIDC subject and grant only
|
|
7774
|
-
the recovery operations/resources declared by generated capability adapters.
|
|
7775
|
-
|
|
7776
|
-
The preview-era performance aggregate, cost, and load workflow renderers remain available to
|
|
7777
|
-
framework maintainers, but RC.31 no longer emits their stale release-manifest-bound workflows
|
|
7778
|
-
or GitHub environments by default. Reintroducing them requires an explicit capability contract
|
|
7779
|
-
bound to the thin deployment receipt rather than the removed preview/replay lifecycle.
|
|
7780
|
-
|
|
7781
|
-
\`AWS_RELIABILITY_READ_ROLE_ARN\` is a separate read-only OIDC role. Trust only
|
|
7782
|
-
this repository's exact \`reliability-read-<stage>\` GitHub OIDC subject.
|
|
7783
|
-
Grant \`sts:GetCallerIdentity\`, \`cloudwatch:DescribeAlarms\`,
|
|
7784
|
-
\`cloudwatch:DescribeAlarmHistory\`, \`cloudwatch:GetMetricData\`,
|
|
7785
|
-
\`ecs:DescribeServices\`, and \`states:DescribeExecution\`. Scope ECS and Step
|
|
7786
|
-
Functions resources to the reviewed Slice services, state machines, and
|
|
7787
|
-
executions wherever IAM supports resource-level constraints. Do not grant log
|
|
7788
|
-
reads, deployment, CloudFormation, SST, or any AWS mutation.
|
|
7789
|
-
|
|
7790
|
-
The generated \`reliability-read.yml\` workflow selects the newest nonexpired
|
|
7791
|
-
binding artifact from a successful deployed-smoke run, reconciles it to the
|
|
7792
|
-
current successful protected deployment, and checks out that exact commit
|
|
7793
|
-
before assuming the role. Callers choose only a bounded operation and workload;
|
|
7794
|
-
they cannot supply the AWS account, Region, role, or binding path. The binding
|
|
7795
|
-
allowlists exact alarm names, API ID, ECS services, and Step Functions
|
|
7796
|
-
resources before the adapter makes a service call. Bootstrap verifies
|
|
7797
|
-
environment-only secret placement, not the role's hidden AWS trust or
|
|
7798
|
-
permission policy.
|
|
7799
|
-
|
|
7800
|
-
The async-recovery and reliability-read jobs have job-scoped \`id-token: write\`.
|
|
7801
|
-
They install the frozen dependency
|
|
7802
|
-
graph with lifecycle scripts and pnpm hooks disabled before assuming AWS
|
|
7803
|
-
authority. Immediately after the one pinned credential action, they blank the
|
|
7804
|
-
OIDC request URL and bearer for future steps and explicitly shadow both values
|
|
7805
|
-
empty on every later step. After bounded AWS use, they blank current AWS
|
|
7806
|
-
credential variables before evidence upload. This withholds credentials from
|
|
7807
|
-
later processes; it does not claim that GitHub revokes the job-level
|
|
7808
|
-
permission.
|
|
7809
|
-
|
|
7810
|
-
\`AWS_SMOKE_ROLE_ARN\` is separate from deployment authority. Trust only this
|
|
7811
|
-
repository's GitHub OIDC subject for the matching protected environment. Grant
|
|
7812
|
-
only run-scoped Cognito principal setup/cleanup on reviewed user-pool ARNs and
|
|
7813
|
-
\`logs:FilterLogEvents\` on exact
|
|
7814
|
-
\`/ebk/<stage>/<slice>/event-consumer\` log-group ARNs. Do not grant
|
|
7815
|
-
CloudFormation, SST mutation, broad Logs query, \`GetLogEvents\`,
|
|
7816
|
-
\`StartQuery\`, or \`logs:Unmask\`. Bootstrap verifies environment-only secret
|
|
7817
|
-
inventory but never creates or reads the secret, materializes the role, or
|
|
7818
|
-
attests its hidden policy.
|
|
7819
|
-
|
|
7820
|
-
Run the GitHub bootstrap in report mode first. Source upgrades never alter remote GitHub
|
|
7821
|
-
settings. Apply a reviewed report only after \`develop\` exists and the candidate's exact
|
|
7822
|
-
\`policy\` and \`verify\` check contexts have run.
|
|
7823
|
-
|
|
7824
|
-
Set \`GH_REPO=<owner>/<repository>\` and a suitable \`GH_TOKEN\`, then run
|
|
7825
|
-
\`pnpm nx run ${name}:github-bootstrap\`. Review the deterministic report before rerunning
|
|
7826
|
-
with \`--apply\`. The command never creates branches, credentials, secrets, or AWS resources.
|
|
7827
|
-
Supply \`--npmPrereleaseReviewerIds=<id,...>\` only in
|
|
7828
|
-
\`environment-reviewer\` mode when intentionally setting a distinct npm
|
|
7829
|
-
mutation reviewer set.
|
|
7830
|
-
Supply \`--productionReviewerIds=<id,...>\` only when committed policy selects
|
|
7831
|
-
\`environment-reviewer\`; it is rejected in \`promotion-pr\` mode.
|
|
7832
|
-
|
|
7833
|
-
Install the optional defense-in-depth pre-push hook explicitly with
|
|
7834
|
-
\`pnpm nx run ${name}:install-git-hooks\`. It refuses to overwrite an unrelated existing hook.
|
|
7835
|
-
|
|
7836
|
-
The sync-back workflow uses only \`GITHUB_TOKEN\` and never pushes or auto-merges. GitHub may
|
|
7837
|
-
place its pull-request workflows in an approval-required state. Approve them; if no run
|
|
7838
|
-
materializes, close and reopen the pull request as a human and then approve it.
|
|
7839
|
-
`,
|
|
7840
|
-
'docs/repository-operating-policy.md': `# Repository Operating Policy
|
|
7841
|
-
|
|
7842
|
-
\`ebk.repository-policy.json\` is the reviewed source of truth for deployment profile, exact
|
|
7843
|
-
stage account IDs, deployment Region, production access, production approval, per-Slice
|
|
7844
|
-
readiness, and the one shared production Foundation profile.
|
|
7845
|
-
New workspaces start with production disabled and explicit Team-compatible
|
|
7846
|
-
\`productionApproval.mode: "promotion-pr"\`. A missing approval mode or Slice entry fails
|
|
7847
|
-
closed; no GitHub capability is allowed to choose a mode implicitly.
|
|
7848
|
-
|
|
7849
|
-
Deployment profiles are proportional to operator maturity:
|
|
7850
|
-
|
|
7851
|
-
- \`starter\` (default) requires one shared account, permits local development and staging
|
|
7852
|
-
through the governed root Nx target, and reserves production for protected GitHub deployment;
|
|
7853
|
-
- \`production-isolated\` requires one development/staging account and a distinct production
|
|
7854
|
-
account; only production is GitHub-only; and
|
|
7855
|
-
- \`fully-isolated\` requires three distinct accounts; staging and production are GitHub-only.
|
|
7856
|
-
|
|
7857
|
-
Equal account IDs never imply shared stage resources. Router, Aurora, Cognito, events, secrets,
|
|
7858
|
-
IAM, logs, queues, resource names, and SSM discovery remain stage-specific. Existing prerelease
|
|
7859
|
-
repositories migrate explicitly to \`fully-isolated\`; upgrades never infer or weaken topology.
|
|
7860
|
-
That profile-only migration retains the former authority model but stays undeployable until exact
|
|
7861
|
-
development, staging, and production account IDs plus \`deploymentRegion\` are committed.
|
|
7862
|
-
|
|
7863
|
-
The named repository modes are source-writing presets, not runtime state. Report a change
|
|
7864
|
-
first and inspect the complete current/next policy:
|
|
7865
|
-
|
|
7866
|
-
\`\`\`bash
|
|
7867
|
-
pnpm nx g @empire-builder-kit/nx:repository-policy \\
|
|
7868
|
-
--deploymentProfile=starter --deploymentRegion=us-east-1 \\
|
|
7869
|
-
--developmentAccountId=111122223333 --stagingAccountId=111122223333 \\
|
|
7870
|
-
--productionAccountId=111122223333
|
|
7871
|
-
\`\`\`
|
|
7872
|
-
|
|
7873
|
-
Apply the reviewed source change separately with \`--apply\`. This command never contacts AWS
|
|
7874
|
-
or GitHub. Use \`--status=blocked|pilot|ready\` for explicit Slice transitions and
|
|
7875
|
-
\`--profile=cost-optimized|standard\` for an explicit shared Foundation decision.
|
|
7876
|
-
Use \`--productionApprovalMode=promotion-pr|environment-reviewer\` for an explicit approval
|
|
7877
|
-
transition. This changes committed policy only; a separate bootstrap report/apply reconciles
|
|
7878
|
-
remote GitHub settings.
|
|
7879
|
-
|
|
7880
|
-
After applying exact topology, authenticate with temporary federated credentials for development
|
|
7881
|
-
or staging and invoke
|
|
7882
|
-
\`pnpm nx run ${name}:deploy-local -- --stage=<stage> --profile=<profile>
|
|
7883
|
-
--expectedRoleArn=<role-arn>\`. Production runs only through the protected main-branch GitHub
|
|
7884
|
-
workflow. Each admitted local invocation plans the complete current stage, displays the stage
|
|
7885
|
-
summary and first material project, and requires a real TTY response of
|
|
7886
|
-
\`approve:<action>:<stage>:<project>:<current-plan-digest>\`. A human or authorized agent may type
|
|
7887
|
-
that acknowledgement; it is active operator control, not a claim of independent human review.
|
|
7888
|
-
The target creates one private ten-minute capability for that project, rechecks the exact source,
|
|
7889
|
-
artifacts, account, Region, role, stage, policy, state, and lock without a second provider preview,
|
|
7890
|
-
consumes the capability once, and removes it on every exit path. Unattended scripts cannot approve.
|
|
7891
|
-
Every material deploy or refresh mutates at most the first material project and ends with a
|
|
7892
|
-
controlled non-success \`replan-required\` handoff, including the last project in the ordered stage.
|
|
7893
|
-
Rerun the complete stage, review the new current summary, and repeat until one invocation proves
|
|
7894
|
-
every project is semantically converged. Only that convergence invocation succeeds. A preview is
|
|
7895
|
-
recent review and audit evidence; it is not represented as a cryptographically replayable Pulumi
|
|
7896
|
-
transaction. A complete, unlocked deploy plan containing only provider reads with no changed
|
|
7897
|
-
properties, replacement, failure, or unmatched risk finding is retained as observation evidence
|
|
7898
|
-
and counts as semantically converged. The standalone project planner may still return its
|
|
7899
|
-
conservative non-success for that drift observation; the root local transaction accepts only a
|
|
7900
|
-
freshly emitted exact provider-read-only record from that child. Repeated reads coalesce
|
|
7901
|
-
only when their logical ID and resource type match exactly. Any stale or ambiguous
|
|
7902
|
-
observation fails closed; a plan with desired changes remains material and requires review. One
|
|
7903
|
-
narrower case stays reviewable instead of becoming
|
|
7904
|
-
drift: when an upstream Foundation apply changes only both external framework-version tag
|
|
7905
|
-
projections (plus SST's already-bounded name hydration), the retained
|
|
7906
|
-
external identity must match one exact non-replacing provider read in the same ordinary plan.
|
|
7907
|
-
Missing read correlation, owned resources, other tag or property changes, incomplete tag pairs,
|
|
7908
|
-
and provider failures remain drift and fail closed. The local target requires the exact SST v5 account bootstrap normally
|
|
7909
|
-
created by the pinned \`ebk dev up\` path, then creates and attests only missing exact
|
|
7910
|
-
per-project/canonical-stage state passphrases before its formal read-only plans. This passphrase
|
|
7911
|
-
bootstrap is the only persistent pre-acknowledgement write; it creates no deployment authority
|
|
7912
|
-
and is reported in bounded local evidence. Clean immutable source, immediate per-project plans,
|
|
7913
|
-
migration and retention preflights, and secret-free result
|
|
7914
|
-
evidence remain mandatory. Direct SST is forbidden.
|
|
7915
|
-
|
|
7916
|
-
After an interrupted apply, use the same target with \`--action=refresh\` and the exact
|
|
7917
|
-
phase, stage, profile, and role. It retains the same plan-summary review boundary, admits only
|
|
7918
|
-
bounded drift-detected refresh evidence, and never turns refresh into an implicit deploy. When
|
|
7919
|
-
the interrupted write leaves a recorded provider output unusable by the ordinary desired preview,
|
|
7920
|
-
the plan stops without mutation. The non-writing refresh preview separates provider refresh
|
|
7921
|
-
records from its later desired preview and cannot replace failed ordinary desired authority;
|
|
7922
|
-
repair the recorded dependency or use the documented
|
|
7923
|
-
operator recovery path before planning again.
|
|
7924
|
-
|
|
7925
|
-
A stage-wide refresh still plans and authorizes every selected project. When one exact retained
|
|
7926
|
-
project plan proves an absent SST state that is unlocked, complete, empty, and drift-free, the
|
|
7927
|
-
root target records that project as a refresh no-op instead of invoking SST against a nonexistent
|
|
7928
|
-
stage. It also retains the pinned provider's exact SSM \`ebk:framework-version\` \`tagsAll\`
|
|
7929
|
-
normalization as a semantically inert observation after the same bounded shape
|
|
7930
|
-
repeats following refresh. Value changes, other tags, security findings, deletes, replacements,
|
|
7931
|
-
sensitive properties, and every other resource type remain material. Locked, incomplete, failed,
|
|
7932
|
-
or otherwise drifted plans are never skipped.
|
|
7933
|
-
|
|
7934
|
-
For a stage with no workload-role account baseline, publish the fixed Foundation-only candidate
|
|
7935
|
-
and invoke this root target with \`--phase=foundation-bootstrap\`. After Foundation outputs exist,
|
|
7936
|
-
publish the complete \`full-stage\` candidate and invoke the target without \`--phase\` (or with
|
|
7937
|
-
\`--phase=full-stage\`). The bootstrap phase selects exactly Foundation; it is not an arbitrary
|
|
7938
|
-
project filter.
|
|
7939
|
-
|
|
7940
|
-
Validation requires both an explicit production approval mode and an explicit Foundation
|
|
7941
|
-
profile. It does not infer omitted values. Use \`promotion-pr\` for a private GitHub Team
|
|
7942
|
-
repository. Use \`environment-reviewer\` only when the repository plan can enforce a separate
|
|
7943
|
-
environment reviewer.
|
|
7944
|
-
|
|
7945
|
-
- \`blocked\` prohibits production create, update, and migration.
|
|
7946
|
-
- \`pilot\` permits protected evidence gathering without claiming normal latency or maturity.
|
|
7947
|
-
- \`ready\` records an adopter decision after its evidence and review; it is not inferred.
|
|
7948
|
-
- removal and unlock remain explicit protected recovery paths so disabled policy cannot strand
|
|
7949
|
-
resources.
|
|
7950
|
-
|
|
7951
|
-
Protected production deploy and refresh validate the complete Foundation/Slice set before AWS
|
|
7952
|
-
access. The Foundation is always ordered first. The set is derived from committed policy and
|
|
7953
|
-
cannot be narrowed with an ad hoc project argument. The retained stage preview remains review
|
|
7954
|
-
evidence. Immediately before each project mutation the workflow computes one fresh plan against
|
|
7955
|
-
current state and applies it without a second redundant preview. Source, artifacts, configuration,
|
|
7956
|
-
policy, environment, and protected identities remain exact. Provider-only read/discard observations
|
|
7957
|
-
may appear or disappear, but any new delete, replacement, import, stateful or security change, IAM
|
|
7958
|
-
expansion, protection reduction, or unclassified resource stops for renewed approval. After an
|
|
7959
|
-
upstream mutation, every downstream project therefore receives a fresh independent risk decision.
|
|
7960
|
-
|
|
7961
|
-
\`standard\` keeps Aurora warm at 2–16 ACU. \`cost-optimized\` keeps a smaller
|
|
7962
|
-
0.5–4 ACU warm floor for starter production traffic. Both keep managed NAT,
|
|
7963
|
-
30-day backups, deletion protection, retained data, and the protected GitHub/OIDC/AWS path.
|
|
7964
|
-
Changing policy affects only later lifecycle requests; it never deploys or removes resources.
|
|
7965
|
-
Changing profile requires a separate reviewed Foundation deployment and retained operational
|
|
7966
|
-
evidence.
|
|
7967
|
-
|
|
7968
|
-
\`EBK_PRODUCTION_FOUNDATION_PROFILE\` is reserved managed executor input. The lifecycle
|
|
7969
|
-
executor derives it from validated committed policy immediately before SST and removes any
|
|
7970
|
-
ambient shell value. Do not set it as a local, repository, organization, or environment
|
|
7971
|
-
variable. Incubation keeps the last configured profile so protected remove and unlock can still
|
|
7972
|
-
render existing production resources; production deploy remains disabled.
|
|
7973
7723
|
`,
|
|
7974
7724
|
'docs/work-markers.md': `# Agent work markers
|
|
7975
7725
|
|
|
@@ -8244,29 +7994,6 @@ must be committed, reviewable, and auditable.
|
|
|
8244
7994
|
},
|
|
8245
7995
|
},
|
|
8246
7996
|
}),
|
|
8247
|
-
'packages/foundation/README.md': `# Standard Foundation
|
|
8248
|
-
|
|
8249
|
-
This project owns the workspace-wide AWS platform for each canonical \`development\`,
|
|
8250
|
-
\`staging\`, or \`production\` stage. It is a separate SST state boundary from product slices.
|
|
8251
|
-
Never deploy it at a framework-derived personal stage; that consumer maps to
|
|
8252
|
-
\`development\`.
|
|
8253
|
-
|
|
8254
|
-
It provides the v1 network, routing, container compute, Postgres, identity, events,
|
|
8255
|
-
observability, configuration, and deployment capabilities. Product slices consume its
|
|
8256
|
-
versioned contract; they do not import files from \`infra/\`.
|
|
8257
|
-
|
|
8258
|
-
Workspace creation does not deploy this project. Review \`docs/costs.md\`,
|
|
8259
|
-
\`docs/security.md\`, and \`docs/runbooks.md\` before the first deployment.
|
|
8260
|
-
|
|
8261
|
-
Set \`EBK_ROOT_DOMAIN\` before deploying when Route 53 in the target account owns a public
|
|
8262
|
-
domain. Without it, the shared Router uses its functional provider URL.
|
|
8263
|
-
|
|
8264
|
-
Before deploying development or staging, add at least one exact operator/probe CIDR to
|
|
8265
|
-
\`security/router-waf.json\`. Production is public by default behind the same managed and
|
|
8266
|
-
rate-limiting baseline; select its allowlist mode explicitly when required. Rehearse the
|
|
8267
|
-
resolved ${(0, index_js_4.productionRehearsalStage)(deploymentProfile)} stage with
|
|
8268
|
-
\`pnpm nx run foundation:router-waf-rehearsal -- --probeUrl=https://<router>/<slice>/api/health --profile=<temporary-profile>\`.
|
|
8269
|
-
`,
|
|
8270
7997
|
'packages/foundation/contracts/foundation.json': json({
|
|
8271
7998
|
contractVersion: '1.0.0',
|
|
8272
7999
|
capabilities: [
|
|
@@ -8328,7 +8055,6 @@ seeded decision record aligned with organization-specific budgets and alerts.
|
|
|
8328
8055
|
|
|
8329
8056
|
- Development uses EC2 NAT, a development bastion, and Aurora scale-to-zero.
|
|
8330
8057
|
${deploymentProfile === 'starter' ? '' : '- Staging uses EC2 NAT and Aurora scale-to-zero by default.\n'}- Production always uses managed NAT and retains protected data. Its explicit Repository
|
|
8331
|
-
- Production always uses managed NAT and retains protected data. Its explicit Repository
|
|
8332
8058
|
Operating Policy profile selects either the standard 2-ACU Aurora floor or the
|
|
8333
8059
|
cost-optimized 0.5-ACU warm floor.
|
|
8334
8060
|
- ECS, EventBridge, Cognito, SNS, SSM, and CloudWatch are primarily usage-priced; logs,
|
|
@@ -8336,102 +8062,6 @@ ${deploymentProfile === 'starter' ? '' : '- Staging uses EC2 NAT and Aurora scal
|
|
|
8336
8062
|
|
|
8337
8063
|
Run \`foundation:remove\` only for disposable stages. Production is retained and protected by
|
|
8338
8064
|
the SST configuration.
|
|
8339
|
-
`,
|
|
8340
|
-
'packages/foundation/docs/runbooks.md': `# Foundation runbooks
|
|
8341
|
-
|
|
8342
|
-
## Deployment
|
|
8343
|
-
|
|
8344
|
-
Use Nx for every supported lifecycle action:
|
|
8345
|
-
|
|
8346
|
-
- \`pnpm nx run foundation:deploy --stage=development\`
|
|
8347
|
-
- \`pnpm nx run foundation:refresh --stage=development\`
|
|
8348
|
-
- \`pnpm nx run foundation:unlock --stage=development\`
|
|
8349
|
-
- \`pnpm nx run foundation:remove --stage=development\`
|
|
8350
|
-
|
|
8351
|
-
Do not invoke SST lifecycle commands directly. The root \`deploy-local\` target is the governed
|
|
8352
|
-
local path for stages admitted by the committed deployment profile. Its fixed
|
|
8353
|
-
\`foundation-bootstrap\` phase is the only local partial-stage path and exists solely for the
|
|
8354
|
-
documented first workload-role publication; isolated protected stages remain on the trusted
|
|
8355
|
-
GitHub path.
|
|
8356
|
-
|
|
8357
|
-
Every local invocation plans the complete selected stage but mutates at most one material
|
|
8358
|
-
project. Type the exact current \`approve:<action>:<stage>:<project>:<plan-digest>\` challenge in a
|
|
8359
|
-
real TTY after reviewing the displayed summary. A human or authorized agent may operate that TTY;
|
|
8360
|
-
unattended input is refused. The acknowledgement creates one ten-minute, one-use, private
|
|
8361
|
-
capability bound to source, artifacts, policy, environment, credentials, and current state. A
|
|
8362
|
-
completed deploy or refresh returns the controlled non-success \`replan-required\`; rerun the
|
|
8363
|
-
complete stage, review the new current summary, and continue one project at a time. Only a
|
|
8364
|
-
semantically converged complete stage reports success. No upstream mutation can authorize a
|
|
8365
|
-
downstream project. A complete, unlocked deploy plan containing only provider reads with no
|
|
8366
|
-
changed properties, replacement, failure, or unmatched risk finding is retained as observation
|
|
8367
|
-
evidence and counts as semantically converged. The standalone project planner may still return
|
|
8368
|
-
its conservative non-success for that drift observation; the root local transaction accepts only
|
|
8369
|
-
a freshly emitted exact provider-read-only record from that child. Repeated reads coalesce
|
|
8370
|
-
only when their logical ID and resource type match exactly. Any stale or ambiguous
|
|
8371
|
-
observation fails closed; a plan with desired changes remains material and requires review. A
|
|
8372
|
-
material downstream plan may also retain an upstream Foundation framework-version tag advance as
|
|
8373
|
-
observation only when both external tag
|
|
8374
|
-
projections, the retained identity, optional bounded SST name hydration, and one non-replacing
|
|
8375
|
-
provider read correlate exactly. Every other external property or uncorroborated read remains
|
|
8376
|
-
drift and blocks before the TTY challenge.
|
|
8377
|
-
|
|
8378
|
-
For an interrupted local apply, run the same root target with \`--action=refresh\`, review its
|
|
8379
|
-
current provider-refresh evidence, and type the displayed TTY challenge. Before mutation the
|
|
8380
|
-
executor writes and verifies a private state recovery point plus a secret-free digest/version
|
|
8381
|
-
manifest. The refresh preview validates its provider and later desired-event partitions; any
|
|
8382
|
-
ordinary preview failure or malformed post-refresh desired event remains blocked. Provider-only
|
|
8383
|
-
observation noise is retained without claiming a replayable preview. Because refresh changes
|
|
8384
|
-
recorded state rather than cloud resources, provider-output security and protection findings
|
|
8385
|
-
remain explicit review requirements under the drift decision. Refresh never continues into deploy
|
|
8386
|
-
or claims desired-state convergence: run the governed deploy target afterward and resolve every
|
|
8387
|
-
remaining source-versus-state change. Exclude the \`.private.json\` recovery point from archives.
|
|
8388
|
-
|
|
8389
|
-
The root refresh target includes every selected project in its exact reviewed plan set. It skips
|
|
8390
|
-
the SST child only when that project's retained plan proves an absent, unlocked, complete, empty,
|
|
8391
|
-
and drift-free state, or when the only retained difference is the pinned provider's exact repeated
|
|
8392
|
-
SSM \`ebk:framework-version\` \`tagsAll\` normalization. It records the project as an explicit refresh no-op
|
|
8393
|
-
in either case while retaining the observation. Value changes, other tags, security findings,
|
|
8394
|
-
deletes, replacements, sensitive
|
|
8395
|
-
properties, and every other resource type remain material; every other plan must execute or fail
|
|
8396
|
-
closed.
|
|
8397
|
-
|
|
8398
|
-
## Router WAF
|
|
8399
|
-
|
|
8400
|
-
Each canonical stage owns one global-scope Web ACL attached to that stage's Foundation Router.
|
|
8401
|
-
The committed \`security/router-waf.json\` policy requires AWS Common Rule Set, Known Bad
|
|
8402
|
-
Inputs, Amazon IP Reputation, an IP rate limit, CloudWatch metrics, and sampled requests.
|
|
8403
|
-
Development and staging fail synthesis until their allowlists contain explicit CIDRs.
|
|
8404
|
-
Production is public by default and may be changed to an explicit allowlist.
|
|
8405
|
-
|
|
8406
|
-
For tuning, set a nonproduction stage to \`count\`, deploy and inspect sampled requests, then
|
|
8407
|
-
return staging to \`block\` and run the live allow/deny, managed-rule, rate-limit, metric, and
|
|
8408
|
-
sampled-request probes. Write their bounded, secret-free result to
|
|
8409
|
-
\`security/router-waf-live-evidence.json\`, then run
|
|
8410
|
-
\`pnpm nx run foundation:router-waf-rehearsal\`. The executor seals the exact policy digest
|
|
8411
|
-
into \`router-waf-blocking-rehearsal.json\`. Production synthesis rejects a missing, stale, or
|
|
8412
|
-
count-mode rehearsal. Full request logging is opt-in, blocked-only, retention-bounded, and
|
|
8413
|
-
redacts query strings plus credential-bearing headers.
|
|
8414
|
-
|
|
8415
|
-
Foundation stages are canonical. \`ebk dev\` derives a Product Slice personal
|
|
8416
|
-
stage from the operating-system account and maps that consumer to the
|
|
8417
|
-
development Foundation. Callers cannot select that stage. Slice preflight
|
|
8418
|
-
reports both identities, never deploys a personal Foundation, and full mapped
|
|
8419
|
-
personal-stage deploys fail closed.
|
|
8420
|
-
|
|
8421
|
-
## Database restore
|
|
8422
|
-
|
|
8423
|
-
Production Aurora retains 30 days of automated backups; non-production retains 7 days.
|
|
8424
|
-
Restore into a new cluster, validate application migrations and data integrity, then cut over
|
|
8425
|
-
consumers deliberately. Never expose the Foundation master credential to a product slice.
|
|
8426
|
-
|
|
8427
|
-
## Protected database migrations
|
|
8428
|
-
|
|
8429
|
-
Each database-backed Product Slice deploys a one-off Fargate migration task and
|
|
8430
|
-
Standard Step Functions workflow into the shared cluster. The existing
|
|
8431
|
-
environment-scoped \`AWS_DEPLOY_ROLE_ARN\` starts and observes that exact
|
|
8432
|
-
workflow; do not create a second migration OIDC role. GitHub has no direct SQL,
|
|
8433
|
-
database-secret-value, or \`rds-db:connect\` authority. The generated task role
|
|
8434
|
-
connects as the Slice's no-password IAM-authenticated migrator user.
|
|
8435
8065
|
`,
|
|
8436
8066
|
'packages/foundation/docs/security.md': `# Foundation security contract
|
|
8437
8067
|
|
|
@@ -9199,16 +8829,7 @@ export function app() {
|
|
|
9199
8829
|
version: '4.17.1',
|
|
9200
8830
|
},
|
|
9201
8831
|
policy: {
|
|
9202
|
-
adoptedImports: [
|
|
9203
|
-
{
|
|
9204
|
-
authority: 'workload-role-account-baseline',
|
|
9205
|
-
logicalId: 'FoundationVpcNatInstanceProfile',
|
|
9206
|
-
privateIdentifierTemplate: 'ebk-{stage}-foundation-nat-profile',
|
|
9207
|
-
recoveryRunbookRef: 'docs/workload-role-account-baseline.md',
|
|
9208
|
-
removalBehavior: 'retain',
|
|
9209
|
-
resourceType: 'aws:iam/instanceProfile:InstanceProfile',
|
|
9210
|
-
},
|
|
9211
|
-
],
|
|
8832
|
+
adoptedImports: [],
|
|
9212
8833
|
additiveLowRiskTypes: [
|
|
9213
8834
|
'aws:cloudwatch/dashboard:Dashboard',
|
|
9214
8835
|
'aws:cloudwatch/logGroup:LogGroup',
|
|
@@ -10528,7 +10149,7 @@ const decision = evaluateGitPolicy(request);
|
|
|
10528
10149
|
process.stdout.write(JSON.stringify(decision, null, 2) + '\\n');
|
|
10529
10150
|
if (!decision.allowed) process.exitCode = 1;
|
|
10530
10151
|
`,
|
|
10531
|
-
'tools/workspace-health.mjs': `import {
|
|
10152
|
+
'tools/workspace-health.mjs': `import { readRepositoryOperatingPolicy } from '@empire-builder-kit/nx/repository-policy';
|
|
10532
10153
|
import { assertWorkMarkerReport, formatWorkMarkerReport, scanWorkMarkers } from '@empire-builder-kit/nx/work-markers';
|
|
10533
10154
|
import { createHash } from 'node:crypto';
|
|
10534
10155
|
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
@@ -10591,13 +10212,7 @@ if (
|
|
|
10591
10212
|
validateOwnership('.', workspace, 'Workspace');
|
|
10592
10213
|
validateOwnership('packages/foundation', foundation, 'Foundation');
|
|
10593
10214
|
|
|
10594
|
-
|
|
10595
|
-
if (!policy.valid) {
|
|
10596
|
-
throw new Error(
|
|
10597
|
-
'Repository Operating Policy is invalid:\\n' +
|
|
10598
|
-
policy.issues.map(({ message, path }) => '- ' + path + ': ' + message).join('\\n'),
|
|
10599
|
-
);
|
|
10600
|
-
}
|
|
10215
|
+
readRepositoryOperatingPolicy(process.cwd());
|
|
10601
10216
|
|
|
10602
10217
|
for (const name of readdirSync('packages')) {
|
|
10603
10218
|
if (name === 'foundation') continue;
|
|
@@ -10615,7 +10230,11 @@ assertWorkMarkerReport(markerReport);
|
|
|
10615
10230
|
process.stdout.write('Empire Builder Kit workspace source health is green.\\n');
|
|
10616
10231
|
`,
|
|
10617
10232
|
};
|
|
10618
|
-
Object.assign(files, SUPPLY_CHAIN_WORKSPACE_FILE_PLAN.files, developerAgentFilePlan.files, (0, workspace_files_stage_authority_js_1.renderStageAuthorityWorkspaceFiles)({
|
|
10233
|
+
Object.assign(files, SUPPLY_CHAIN_WORKSPACE_FILE_PLAN.files, developerAgentFilePlan.files, (0, workspace_files_stage_authority_js_1.renderStageAuthorityWorkspaceFiles)({
|
|
10234
|
+
deploymentProfile,
|
|
10235
|
+
name,
|
|
10236
|
+
workspaceDeploymentId,
|
|
10237
|
+
}));
|
|
10619
10238
|
Object.assign(files, (0, workspace_files_ecr_inspector_js_1.renderThinEcrInspectorWorkflow)({
|
|
10620
10239
|
actionPins: {
|
|
10621
10240
|
checkout: checkoutAction,
|
|
@@ -10641,7 +10260,6 @@ process.stdout.write('Empire Builder Kit workspace source health is green.\\n');
|
|
|
10641
10260
|
name,
|
|
10642
10261
|
toolVersions: {
|
|
10643
10262
|
node: tool_versions_js_1.WORKSPACE_NODE_VERSION,
|
|
10644
|
-
pnpm: tool_versions_js_1.WORKSPACE_PNPM_VERSION,
|
|
10645
10263
|
sst: tool_versions_js_1.WORKSPACE_SST_VERSION,
|
|
10646
10264
|
},
|
|
10647
10265
|
}).files, (0, workspace_files_thin_docs_js_1.renderThinLifecycleDocumentation)({ deploymentProfile, name }));
|