@empire-builder-kit/nx 1.0.0-rc.40 → 1.0.0-rc.41

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.
Files changed (56) hide show
  1. package/README.md +26 -10
  2. package/package.json +3 -3
  3. package/src/blueprints/external-sandbox.d.ts +1 -1
  4. package/src/cli/deploy-runtime.d.ts +25 -1
  5. package/src/cli/deploy-runtime.js +120 -4
  6. package/src/cli/dev-command.d.ts +2 -0
  7. package/src/cli/dev-command.js +8 -0
  8. package/src/cli/main.js +20 -6
  9. package/src/cli/personal-secret-runtime.d.ts +12 -0
  10. package/src/cli/personal-secret-runtime.js +18 -3
  11. package/src/cli/secret-terminal.js +1 -1
  12. package/src/container-images.d.ts +1 -1
  13. package/src/container-images.js +1 -1
  14. package/src/developer-agent/operation-registry.d.ts +10 -0
  15. package/src/developer-agent/operation-registry.js +60 -13
  16. package/src/developer-agent/planning.d.ts +8 -1
  17. package/src/developer-agent/planning.js +23 -3
  18. package/src/executors/local-deploy/local-approval.js +1 -1
  19. package/src/executors/sst-lifecycle/governed-native-operation.js +3 -2
  20. package/src/executors/sst-lifecycle/run-sst-command.d.ts +6 -0
  21. package/src/executors/sst-lifecycle/run-sst-command.js +3 -33
  22. package/src/foundation/cost-estimate.d.ts +170 -0
  23. package/src/foundation/cost-estimate.js +683 -0
  24. package/src/generators/preset/tool-versions.d.ts +0 -2
  25. package/src/generators/preset/tool-versions.js +1 -3
  26. package/src/generators/preset/workspace-files-adopter-skills.js +39 -18
  27. package/src/generators/preset/workspace-files-developer-agent.js +83 -27
  28. package/src/generators/preset/workspace-files-shared-operation-claims.d.ts +10 -0
  29. package/src/generators/preset/workspace-files-shared-operation-claims.js +59 -0
  30. package/src/generators/preset/workspace-files-stage-authority.js +13 -2
  31. package/src/generators/preset/workspace-files-thin-deploy.d.ts +10 -0
  32. package/src/generators/preset/workspace-files-thin-deploy.js +54 -20
  33. package/src/generators/preset/workspace-files-thin-docs.js +32 -14
  34. package/src/generators/preset/workspace-files.js +28 -8
  35. package/src/generators/slice/built-in-plan-api-contract-files.js +7 -4
  36. package/src/generators/slice/built-in-plan-authorization-files.js +10 -5
  37. package/src/generators/slice/built-in-plan-authorization-infrastructure-files.js +933 -249
  38. package/src/generators/slice/built-in-plan-data-files.js +17 -8
  39. package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.js +5 -1
  40. package/src/generators/slice/built-in-plan-frontend-files.js +7 -0
  41. package/src/generators/slice/built-in-plan-infrastructure-files.js +0 -1
  42. package/src/generators/slice/built-in-plan-infrastructure-safety-files.js +8 -3
  43. package/src/generators/slice/built-in-plan-metadata-files.js +2 -1
  44. package/src/generators/slice/built-in-plan-reliability-files.js +4 -1
  45. package/src/generators/slice/built-in-plan-testing-persistence-event-files.d.ts +7 -0
  46. package/src/generators/slice/built-in-plan-testing-persistence-event-files.js +487 -0
  47. package/src/generators/slice/built-in-plan-testing-persistence-files.js +2 -0
  48. package/src/generators/slice/built-in-plan.js +3 -1
  49. package/src/generators/workload/frozen-container.d.ts +1 -1
  50. package/src/git-policy/github-bootstrap.d.ts +9 -0
  51. package/src/git-policy/github-bootstrap.js +16 -2
  52. package/src/local-dev/fleet-inventory.js +18 -10
  53. package/src/local-dev/fleet-launcher.js +2 -2
  54. package/src/secrets/personal-command.d.ts +18 -2
  55. package/src/secrets/personal-command.js +66 -12
  56. package/src/secrets/verification.js +6 -1
@@ -8,8 +8,6 @@ export declare const WORKSPACE_SST_VERSION: "4.17.1";
8
8
  export declare const WORKSPACE_NODE_VERSION: "22.23.1";
9
9
  export declare const WORKSPACE_PNPM_VERSION: "11.20.0";
10
10
  export declare const WORKSPACE_VITEST_VERSION: "4.1.4";
11
- /** Python packaging runtime required by the pinned SST-generated workloads. */
12
- export declare const WORKSPACE_UV_VERSION: "0.11.28";
13
11
  export declare const WORKSPACE_PNPM_SHA512: "9a6f330a95b66446ea088faf1521405a8a01f07fde7124cc9958dfed52d4bb436737e65b08f85f37b46fcba375092558ac51262b816844b22f63406ed166bfee";
14
12
  export declare const WORKSPACE_PNPM_DESCRIPTOR: "pnpm@11.20.0+sha512.9a6f330a95b66446ea088faf1521405a8a01f07fde7124cc9958dfed52d4bb436737e65b08f85f37b46fcba375092558ac51262b816844b22f63406ed166bfee";
15
13
  /**
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WORKSPACE_SST_NPM_INTEGRITY = exports.WORKSPACE_PNPM_DESCRIPTOR = exports.WORKSPACE_PNPM_SHA512 = exports.WORKSPACE_UV_VERSION = exports.WORKSPACE_VITEST_VERSION = exports.WORKSPACE_PNPM_VERSION = exports.WORKSPACE_NODE_VERSION = exports.WORKSPACE_SST_VERSION = void 0;
3
+ exports.WORKSPACE_SST_NPM_INTEGRITY = exports.WORKSPACE_PNPM_DESCRIPTOR = exports.WORKSPACE_PNPM_SHA512 = exports.WORKSPACE_VITEST_VERSION = exports.WORKSPACE_PNPM_VERSION = exports.WORKSPACE_NODE_VERSION = exports.WORKSPACE_SST_VERSION = void 0;
4
4
  /**
5
5
  * Framework-required tool versions written into newly generated workspaces.
6
6
  *
@@ -11,8 +11,6 @@ exports.WORKSPACE_SST_VERSION = '4.17.1';
11
11
  exports.WORKSPACE_NODE_VERSION = '22.23.1';
12
12
  exports.WORKSPACE_PNPM_VERSION = '11.20.0';
13
13
  exports.WORKSPACE_VITEST_VERSION = '4.1.4';
14
- /** Python packaging runtime required by the pinned SST-generated workloads. */
15
- exports.WORKSPACE_UV_VERSION = '0.11.28';
16
14
  exports.WORKSPACE_PNPM_SHA512 = '9a6f330a95b66446ea088faf1521405a8a01f07fde7124cc9958dfed52d4bb436737e65b08f85f37b46fcba375092558ac51262b816844b22f63406ed166bfee';
17
15
  exports.WORKSPACE_PNPM_DESCRIPTOR = `pnpm@${exports.WORKSPACE_PNPM_VERSION}+sha512.${exports.WORKSPACE_PNPM_SHA512}`;
18
16
  /**
@@ -3,7 +3,6 @@ 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 tool_versions_js_1 = require("./tool-versions.js");
7
6
  exports.ADOPTER_SKILL_NAMES = [
8
7
  'ebk-orient-plan',
9
8
  'ebk-build-feature',
@@ -115,11 +114,21 @@ not done merely because its generated file exists or the page loads.
115
114
  description: 'Run EBK task-scoped hot development, fleet-origin browser checks and final deployed-development smoke; choose feature versus milestone verification accurately.',
116
115
  body: `# Develop and verify
117
116
 
118
- Inspect \`ebk dev doctor\` and \`ebk dev status\` with the approved account,
119
- Region and temporary credential context. Resolve readiness failures using the
120
- reported prerequisite; a doctor pass is not feature proof. Development accepts
121
- dirty source and does not require a production confirmation, release artifact
122
- or full workspace barrier.
117
+ Inspect \`ebk dev doctor\` and \`ebk dev status\` using the account and Region
118
+ fixed by committed repository policy and the profile saved by
119
+ \`ebk dev configure\`. If doctor reports an expired or missing SSO session, run
120
+ \`aws sso login --profile <profile>\`; the human approves the request in the
121
+ browser, so the session stays the human's own identity. In a hosted or
122
+ headless shell, add \`--use-device-code\` and the human approves the printed
123
+ code from their own browser. Confirm \`aws sts get-caller-identity\` reports
124
+ that identity, then continue. Never embed access keys, export, copy, or read
125
+ credentials from the SSO cache, or assume a separate or stronger principal.
126
+ Only an attended agent (local or hosted), one a human is actively directing,
127
+ uses that session; an unattended or background agent never receives a human
128
+ profile or SSO session. Resolve other readiness failures using the reported
129
+ prerequisite; a doctor pass is not feature proof.
130
+ Development accepts dirty source and does not require a production
131
+ confirmation, release artifact or full workspace barrier.
123
132
 
124
133
  If a container build stalls while Docker itself responds, run
125
134
  \`ebk dev doctor --refresh --json\` and inspect \`docker-credential-helpers\`.
@@ -148,12 +157,15 @@ Use affected unit/type/lint/ownership checks during edits. Require Docker for
148
157
  Slice integration tests (\`test-integration\`, part of \`verify\`), local container
149
158
  dependencies, or external Blueprint execution; require AWS
150
159
  credentials for actual task resources. Install browser binaries for browser
151
- proof. A Standard Slice includes a Python infrastructure provisioner even when
152
- its feature handlers use TypeScript: install uv ${tool_versions_js_1.WORKSPACE_UV_VERSION} (Python 3.12 or
153
- newer) on PATH before native development or deployment. Projects without Python and
154
- ordinary source-only feature checks do not require it. Tooling preflight is
155
- readiness, not browser or application proof; never infer that doctor alone has
156
- validated every build dependency.
160
+ proof. Tooling preflight is readiness, not browser or application proof; never
161
+ infer that doctor alone has validated every build dependency.
162
+
163
+ Measured 2026-09-28/29 on Linux during the rc.39 acceptance, a fresh two-Slice
164
+ \`ebk dev up\` took 334–442 s and \`ebk dev down\` 242–345 s. Those figures
165
+ include the Python provisioner build that rc.41 removes, so they may change.
166
+ \`ebk dev restart\` of retained resources took about 70–85 s including the
167
+ browser check. Prefer \`ebk dev restart\` while iterating and reserve
168
+ \`ebk dev down\` for the completion boundary.
157
169
 
158
170
  At the completion boundary, settle \`ebk dev down billing\`, then use
159
171
  \`ebk deploy development billing --profile=<approved-profile> --expectedRoleArn=<exact-role>\`.
@@ -177,12 +189,21 @@ mutation; source policy is authoritative if deliberately changed later.
177
189
 
178
190
  Use \`ebk deploy development\` for the complete active development stage, or
179
191
  \`ebk deploy development billing\` for Foundation plus one selected Slice.
180
- Pass the approved \`--profile\` and exact \`--expectedRoleArn\`; verify account,
181
- Region, stage and current caller. No direct SST or AWS application mutation.
182
-
183
- For an authorized local production deployment, retain clean source and the
184
- exact \`deploy:production:<account>:<region>:<source-commit>\` confirmation.
185
- An agent skill cannot authorize production or bypass a protected environment.
192
+ Pass the human's Identity Center \`--profile\` (typically the one saved by
193
+ \`ebk dev configure\`) and the exact stage deployment role from
194
+ \`docs/stage-deployment-authority.md\` as \`--expectedRoleArn\`; verify
195
+ account, Region, stage and current caller. Refresh an expired development
196
+ session as in the develop/verify skill. No direct SST or AWS application
197
+ mutation. A development deploy runs to completion with no prompt; add
198
+ \`--json\` for one bounded result on stdout after the run (the receipt this run
199
+ wrote and each project's outcome). Staging and production refuse \`--json\`.
200
+
201
+ A local staging or production deployment, where the profile admits one, is
202
+ human-operated: from clean source, a human at the terminal types the exact
203
+ acknowledgement (for production,
204
+ \`deploy:production:<account>:<region>:<source-commit>\`). Prepare the command,
205
+ the receipt review and the evidence for the human. An agent skill cannot
206
+ authorize production or bypass a protected environment.
186
207
  Refresh, unlock and remove are separate owning Nx targets: inspect their
187
208
  actual options and operation \`target:<project>:<target>\`; do not substitute
188
209
  deploy or raw provider commands. Remove dependent Slices before Foundation.
@@ -20,15 +20,33 @@ const HANDOFF_STATE_DESCRIPTIONS = {
20
20
  'failed-recovery-or-cleanup-required': 'Execution failed and named recovery or cleanup work is still required.',
21
21
  'proposal-or-research-only': 'The record contains no implementation or mutation claim.',
22
22
  };
23
+ /**
24
+ * One canonical secret hand-off for seeded agent guidance. `set` stays
25
+ * human-only (the CLI refuses agent and CI markers); `remove` carries no value
26
+ * and an agent may start it, with the human typing the hidden confirmation.
27
+ */
28
+ const HUMAN_SECRET_HANDOFF = `Human-supplied secret values are entered only by a human, in a terminal no agent spawned,
29
+ through \`ebk secret set <slice> <logical-name>\`; the command refuses agent and CI
30
+ environments, so the plaintext never crosses an agent-owned process. An agent prepares that
31
+ step: it names the exact Slice and logical name, tells the human the exact command to run,
32
+ and verifies afterwards with the value-blind status and verification targets.
33
+ \`ebk secret remove <slice> <logical-name>\` carries no value: an agent may start it, and the
34
+ human types the hidden confirmation in that interactive terminal. Agents and CI may use
35
+ value-blind metadata, status, verification, and the exact generated-secret initializer, which
36
+ accepts and returns no plaintext value.`;
23
37
  function deploymentAuthorityGuidance(deploymentProfile) {
24
38
  switch (deploymentProfile) {
25
39
  case 'starter':
26
40
  return `Development and production mutation may run locally only through the matching
27
41
  authenticated Nx lifecycle and committed Repository Operating Policy. GitHub deployment
28
- remains optional. Never invoke SST directly.`;
42
+ remains optional. A human operates the terminal for local production and types its exact
43
+ acknowledgement; an agent prepares the command, receipt review, and evidence.
44
+ Never invoke SST directly.`;
29
45
  case 'production-isolated':
30
46
  return `Development and staging mutation may run locally only through the matching
31
- authenticated Nx lifecycle and committed Repository Operating Policy. Production mutation
47
+ authenticated Nx lifecycle and committed Repository Operating Policy. A human operates the
48
+ terminal for local staging and types its exact acknowledgement; an agent prepares the
49
+ command, receipt review, and evidence. Production mutation
32
50
  belongs to the protected GitHub environment and OIDC workflow. Never invoke SST directly.`;
33
51
  case 'fully-isolated':
34
52
  return `Development mutation may run locally only through the matching authenticated Nx
@@ -45,11 +63,15 @@ not grant authority over another repository, account, environment, or worktree.
45
63
 
46
64
  Use \`ebk agent context\`, \`ebk agent plan\`, \`ebk agent upgrade-preview\`,
47
65
  \`ebk agent handoff\`, and \`ebk agent resume\`; add \`--json\` when a machine-readable
48
- result is required. Nx remains the graph and target authority: an agent plan is advisory, and
49
- work runs only through the authenticated owning target, typed Nx generator, bounded EBK
50
- development command, frozen package-manager command, or plan-derived adopter-owned
51
- source-edit scope. Protected and destructive operations expose identity and routing only,
52
- never local command arguments.
66
+ result is required. Nx remains the graph and target authority. An agent plan is advisory; it
67
+ is the route for typed generators, Upgrade preview and apply, and protected routing. Ordinary
68
+ edits to adopter-owned, seeded, and unrecorded files need no plan: make them directly on a
69
+ topic branch, bounded by \`.ebk/ownership.json\`, \`pnpm health\`, the verify barrier, and
70
+ pull-request review. Managed paths are never hand-edited. Other work runs through the
71
+ authenticated owning target, typed Nx generator, bounded EBK development command, or frozen
72
+ package-manager command.
73
+ Protected and destructive operations expose identity and routing only, never local command
74
+ arguments.
53
75
 
54
76
  External Blueprint receipt review is the one deliberate target exception. Run only
55
77
  \`ebk blueprint verification-review\` after the protected static approval; there is no Nx
@@ -81,18 +103,23 @@ that same generator with the exact scoped prefix
81
103
  the workspace's fail-closed dependency-state check: it lets Nx reach EBK's bound recovery
82
104
  callback, which owns the install. Never run \`pnpm install\` while the retained marker exists.
83
105
 
84
- Use one topic branch and linked worktree per independent change. Stop on stale base,
85
- overlapping paths or shared external state, ownership or generated drift, invalid policy,
86
- blocking markers, missing prerequisites, or unknown authority; never merge, rebase, discard,
87
- or overwrite another worktree automatically.
106
+ Use one topic branch and linked worktree per independent change. Stop on overlapping paths
107
+ or shared external state, ownership or generated drift, invalid policy, blocking markers,
108
+ missing prerequisites, or unknown authority. A stale base on your own topic branch is not a
109
+ stop: rebase or merge the base branch into your own branch, rerun affected verification, and
110
+ continue; where an operation itself binds an exact base (upgrade, formal handoff), refresh
111
+ the base first and then rerun that operation. Never merge, rebase, discard, or overwrite
112
+ another worktree or another actor's branch automatically. Before a shared operation (gateway
113
+ setup, package release, candidate adoption, database replacement, or development
114
+ deployment), follow the claim procedure in \`docs/shared-operation-claims.yaml\`.
88
115
 
89
- ${deploymentAuthorityGuidance(deploymentProfile)} Human-supplied secret values remain a
90
- human-only TTY ceremony. Agents may use value-blind metadata, status, verification, and the
91
- exact generated-secret initializer; the initializer accepts and returns no plaintext value.
116
+ ${deploymentAuthorityGuidance(deploymentProfile)}
117
+
118
+ ${HUMAN_SECRET_HANDOFF}
92
119
 
93
120
  Read \`docs/developer-agent.md\`, \`docs/developer-agent-handoff.template.json\`,
94
- \`docs/developer-agent-adapters.md\`, \`docs/git-workflow.md\`, and
95
- \`docs/work-markers.md\` before proceeding.
121
+ \`docs/developer-agent-adapters.md\`, \`docs/git-workflow.md\`,
122
+ \`docs/work-markers.md\`, and \`docs/shared-operation-claims.yaml\` before proceeding.
96
123
  `;
97
124
  }
98
125
  function renderHandoffStates() {
@@ -109,7 +136,9 @@ required. A skill, MCP client, IDE, or hosted agent service is optional.
109
136
 
110
137
  The numeric JSON schema in this runbook is framework-internal and may change before stable v1.
111
138
  Do not publish an adapter or treat it as an independent public API until the repository-native
112
- CLI and Nx contract complete their live pilots.
139
+ CLI and Nx contract complete their live pilots. A local, unpublished wrapper (skill, MCP tool,
140
+ or IDE command) that only invokes these same commands with \`--json\` is permitted under
141
+ \`docs/developer-agent-adapters.md\` and must stay removable without changing the workflow.
113
142
 
114
143
  ## Canonical loop
115
144
 
@@ -132,6 +161,10 @@ CLI and Nx contract complete their live pilots.
132
161
  the structured arguments reported by the plan;
133
162
  - execute authenticated read-only, local-source, or development Nx targets;
134
163
  - execute bounded \`ebk dev\` inspection or Slice lifecycle commands;
164
+ - run \`ebk deploy development [slice...]\` directly for a development deployment,
165
+ adding \`--json\` for one bounded result on stdout after the run (planning reports the
166
+ root \`deploy-local\` target as non-plannable and names this owner; staging and
167
+ production refuse \`--json\`);
135
168
  - execute the frozen package installation command;
136
169
  - make an ordinary source edit within inspected seeded/user-owned extension points
137
170
  (formal source-edit plans admit only adopter-owned paths); or
@@ -156,7 +189,11 @@ unsupported until their owning target, command, workflow, or runbook has an exac
156
189
  signature and proof contract. The stable Slice, Function, Service, Job, and Upgrade generators
157
190
  have closed typed inputs; arbitrary Blueprint references or inputs, dependency changes other
158
191
  than frozen installation, mutable development configuration, and secret set/remove remain
159
- outside \`ebk agent plan\`. Use their direct typed owner and never infer arguments.
192
+ outside \`ebk agent plan\` but are not forbidden: use their direct owner and never infer
193
+ arguments. Add or upgrade a dependency with \`pnpm add\` or \`pnpm up\` on the
194
+ adopter-owned entries of a projection-managed \`package.json\` (never a framework-managed
195
+ entry), then run the frozen installation and \`pnpm verify\`, which includes the
196
+ supply-chain checks, and let pull-request review cover the change.
160
197
 
161
198
  External Blueprint receipt creation is not an Nx target. After protected Git retains the exact
162
199
  static generated-content approval, invoke only \`ebk blueprint verification-review\`. The
@@ -188,9 +225,13 @@ project roots; the request cannot assert it. Cross-project selections, unknown o
188
225
  managed or seeded source-edit plan paths, raw commands, prompts, secret values, absolute paths,
189
226
  traversal, and symlink inputs are refused.
190
227
 
191
- That source-edit plan restriction does not make seeded feature code immutable.
192
- Edit seeded handlers, tests and feature registries through the ordinary documented
193
- feature workflow; managed mechanics always require their owning generator.
228
+ That source-edit plan restriction does not make seeded feature code immutable. A plan
229
+ refusal for a seeded path is not a prohibition: seeded files and files absent from the
230
+ ownership record may be edited directly on a topic branch, without a plan, bounded by
231
+ \`pnpm health\`, the verify barrier, and pull-request review. Edit seeded handlers, tests
232
+ and feature registries through the ordinary documented feature workflow; managed mechanics
233
+ always require their owning generator and are never hand-edited. Source-edit plans do not yet
234
+ admit seeded paths.
194
235
 
195
236
  Typed generator requests add one closed \`generatorInput\` object and cannot supply
196
237
  \`selectedFiles\`. New Slice planning accepts only \`{"generator":"slice","name":"billing"}\`
@@ -271,14 +312,29 @@ broaden an operation beyond the owning tool.
271
312
  Dirty source alone does not block ordinary feature generation, seeded/user-owned edits,
272
313
  affected verification or local development. Commit-bound plans, upgrades and formal
273
314
  handoffs still enforce their exact source requirements; protected authority is unchanged.
315
+ A stale base on your own topic branch is not a stop: rebase or merge the base branch into
316
+ your own branch, rerun affected verification, and continue. Never merge, rebase, discard,
317
+ or overwrite another worktree or another actor's branch.
274
318
 
275
319
  For every mutation, name the cleanup and recovery owner before execution.
276
- ${deploymentAuthorityGuidance(deploymentProfile)} Destructive work additionally requires an
277
- exact target, explicit approval, retained recovery proof, and completed cleanup.
278
-
279
- Human-supplied secret values are entered only through the human TTY ceremony. Agents and CI
280
- may use value-blind metadata, status, verification, and the exact generated-secret initializer;
281
- the initializer accepts and returns no plaintext value.
320
+ ${deploymentAuthorityGuidance(deploymentProfile)} Destructive work in a staging or production
321
+ stage additionally requires an exact target, the human-typed TTY acknowledgement or protected
322
+ GitHub environment approval that owns that stage, retained recovery proof, and completed
323
+ cleanup. Destructive work in the development stage (remove, unlock, migration, personal task
324
+ teardown) needs only the exact target and completed cleanup.
325
+
326
+ ${HUMAN_SECRET_HANDOFF}
327
+
328
+ ## Shared-operation claims
329
+
330
+ Gateway setup, package release, candidate adoption, database replacement, and development
331
+ deployment are shared operations that only one actor at a time may run. Before starting one,
332
+ follow the procedure in \`docs/shared-operation-claims.yaml\` and \`docs/work-markers.md\`:
333
+ read the current ledger, stop and report an open conflicting claim instead of running the
334
+ operation, otherwise record your claim, and delete it when the operation and its verification
335
+ are complete. Nothing enforces a claim; it is a convention built on work markers. Adding or
336
+ removing a claim changes the work-marker set, so \`ebk agent resume\` reports a retained
337
+ handoff as \`marker-blocked\`; record a fresh handoff after the claim changes.
282
338
 
283
339
  ## Handoff and resumption
284
340
 
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Seeded shared-operation claim ledger. A claim is an ordinary EBK work marker
3
+ * (`EBK-TODO` with a `PLAN:shared-operation/<operation>` reference), so the
4
+ * existing work-markers scanner validates and reports open claims; no new
5
+ * enforcement exists, and the generated text must not imply one.
6
+ */
7
+ export declare const SHARED_OPERATION_CLAIMS_PATH: "docs/shared-operation-claims.yaml";
8
+ export declare const SHARED_OPERATIONS: readonly ["gateway-setup", "package-release", "candidate-adoption", "database-replacement", "development-deployment"];
9
+ export declare const SHARED_OPERATION_CLAIM_PHASE: "shared-operation";
10
+ export declare function renderSharedOperationClaims(workspaceName: string): string;
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SHARED_OPERATION_CLAIM_PHASE = exports.SHARED_OPERATIONS = exports.SHARED_OPERATION_CLAIMS_PATH = void 0;
4
+ exports.renderSharedOperationClaims = renderSharedOperationClaims;
5
+ /**
6
+ * Seeded shared-operation claim ledger. A claim is an ordinary EBK work marker
7
+ * (`EBK-TODO` with a `PLAN:shared-operation/<operation>` reference), so the
8
+ * existing work-markers scanner validates and reports open claims; no new
9
+ * enforcement exists, and the generated text must not imply one.
10
+ */
11
+ exports.SHARED_OPERATION_CLAIMS_PATH = 'docs/shared-operation-claims.yaml';
12
+ exports.SHARED_OPERATIONS = [
13
+ 'gateway-setup',
14
+ 'package-release',
15
+ 'candidate-adoption',
16
+ 'database-replacement',
17
+ 'development-deployment',
18
+ ];
19
+ exports.SHARED_OPERATION_CLAIM_PHASE = 'shared-operation';
20
+ function renderSharedOperationClaims(workspaceName) {
21
+ return `# Shared-operation claim ledger
22
+ #
23
+ # Seeded by Empire Builder Kit; this repository owns the file after
24
+ # generation. It serializes shared operations that only one actor at a time
25
+ # may run: ${exports.SHARED_OPERATIONS.slice(0, -1).join(', ')}, and
26
+ # ${exports.SHARED_OPERATIONS.at(-1)}.
27
+ #
28
+ # Before starting one of them, an agent or a human:
29
+ #
30
+ # 1. reads the current copy of this file where the other actors record
31
+ # claims (for example the integration branch after a fetch) and looks for
32
+ # an open claim on the same operation;
33
+ # 2. if one exists, stops and reports the conflict instead of running the
34
+ # operation; the claim's owner or a human coordinator resolves it;
35
+ # 3. otherwise adds one claim line below and commits it where the other
36
+ # actors read this ledger before starting; and
37
+ # 4. deletes its own claim line once the operation and its verification are
38
+ # complete.
39
+ #
40
+ # A claim is one full-line EBK work marker: kind EBK-TODO, reference
41
+ # PLAN:${exports.SHARED_OPERATION_CLAIM_PHASE}/<operation>, where <operation> is one of
42
+ # the five names above, and a self-contained description naming the actor,
43
+ # the branch or worktree, the start time in UTC, and the exact target. Two
44
+ # open claims with the same reference conflict. For example (prose, not a
45
+ # claim):
46
+ #
47
+ # Example: EBK-TODO(PLAN:${exports.SHARED_OPERATION_CLAIM_PHASE}/development-deployment): <actor> on <branch> since <UTC time>; deploying billing to development.
48
+ #
49
+ # Run \`pnpm nx run ${workspaceName}:work-markers\` to list open claims with
50
+ # every other work marker and validate their syntax. Adding or removing a
51
+ # claim changes the marker set, so a retained Developer-Agent handoff
52
+ # reports the change on resume. Nothing enforces a claim: it is a
53
+ # convention the actors follow, and it is only as current as the copy they
54
+ # read.
55
+ #
56
+ # Open claims:
57
+ `;
58
+ }
59
+ //# sourceMappingURL=workspace-files-shared-operation-claims.js.map
@@ -26,7 +26,17 @@ pnpm nx run <workspace>:stage-authority-render -- \\
26
26
  \`\`\`
27
27
 
28
28
  Locally admitted stages require at least one reviewed
29
- \`--aws-principal-arn\`. Stages that require only protected GitHub deployment
29
+ \`--aws-principal-arn\`.
30
+
31
+ Rendering, reviewing, and read-only simulation of the emitted templates are
32
+ ordinary work an agent may do with the development profile. Applying the
33
+ owner-claim and authority stacks creates IAM roles and trust and therefore
34
+ requires an account-administrator credential that agents never hold: the agent
35
+ hands the exact rendered \`ownership-template.json\`, \`template.json\`, stack
36
+ names, and parameters to the account administrator, who applies them, and the
37
+ agent verifies afterwards with the read-only ownership doctor.
38
+
39
+ Stages that require only protected GitHub deployment
30
40
  require one exact \`--github-repository\` environment trust and reject local AWS
31
41
  principals. Production-isolated staging requires both the local principal and
32
42
  the protected GitHub environment trust: local staging remains supported, while
@@ -204,7 +214,8 @@ exclusive and retained. Two workspaces do not cohabit one tuple, and removing
204
214
  an application stack does not release the claim.
205
215
 
206
216
  Render stage authority with \`pnpm nx run ${options.name}:stage-authority-render --
207
- --stage=<stage> ...\`. Apply the emitted \`ownership-template.json\` as the exact
217
+ --stage=<stage> ...\`. An agent may render and review it; an account administrator
218
+ applies the stacks, because they create IAM roles and trust. Apply the emitted \`ownership-template.json\` as the exact
208
219
  claim stack in \`ownership-manifest.json\` before applying the authority template.
209
220
  CloudFormation's fixed-name SSM create is the atomic claim. The authority
210
221
  template accepts only that exact parameter path and fails its Rule before any
@@ -38,6 +38,16 @@ export interface ThinDeployWorkflowFilePlan {
38
38
  export declare function renderThinDeployVerifyCaller(profile: DeploymentProfile, deliveryLane?: 'protected-pair' | 'trunk', productionApprovalMode?: ThinDeployProductionApprovalMode): string;
39
39
  /** @internal Run exactly this generated script in the protected-runner fixture. */
40
40
  export declare function protectedBrowserInstallScript(): string;
41
+ /**
42
+ * @internal Run exactly this generated script in the protected-runner fixture.
43
+ *
44
+ * Reads the deploying stage's GitHub environment variables through request
45
+ * names and exports the canonical machine-credential variables only when they
46
+ * are set. An unset GitHub variable expands to '', which the generated Slice
47
+ * SST config would read as a generation rather than its blue-1 default, so the
48
+ * canonical names never reach the lifecycle when the request is empty.
49
+ */
50
+ export declare function machineCredentialRequestScript(): string;
41
51
  /** @internal Exported for executable source-contract tests. */
42
52
  export declare function exactStageDeployerGuardScript(operation: string, accountVariable: string): string;
43
53
  /** @internal Shared verbatim by every generated protected workflow. */
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EBK_RECORD_MAIN_TOKEN_SECRET = exports.THIN_DEPLOY_WORKFLOW_PATH = void 0;
4
4
  exports.renderThinDeployVerifyCaller = renderThinDeployVerifyCaller;
5
5
  exports.protectedBrowserInstallScript = protectedBrowserInstallScript;
6
+ exports.machineCredentialRequestScript = machineCredentialRequestScript;
6
7
  exports.exactStageDeployerGuardScript = exactStageDeployerGuardScript;
7
8
  exports.canonicalStageAuthorityDerivationScript = canonicalStageAuthorityDerivationScript;
8
9
  exports.exactStagingPromotionPullGuardScript = exactStagingPromotionPullGuardScript;
@@ -11,7 +12,6 @@ exports.restoredCandidateValidationScript = restoredCandidateValidationScript;
11
12
  exports.stagingPromotionSealScript = stagingPromotionSealScript;
12
13
  exports.postdeploySupplyChainBindingScript = postdeploySupplyChainBindingScript;
13
14
  exports.renderThinDeployWorkflowFilePlan = renderThinDeployWorkflowFilePlan;
14
- const tool_versions_js_1 = require("./tool-versions.js");
15
15
  exports.THIN_DEPLOY_WORKFLOW_PATH = '.github/workflows/deploy.yml';
16
16
  /** The production environment secret that lets record-main fast-forward main. */
17
17
  exports.EBK_RECORD_MAIN_TOKEN_SECRET = 'EBK_RECORD_MAIN_TOKEN';
@@ -133,6 +133,57 @@ for project in "\${projects[@]}"; do
133
133
  pnpm --dir "packages/$project" exec playwright install --with-deps chromium
134
134
  done`;
135
135
  }
136
+ /**
137
+ * @internal Run exactly this generated script in the protected-runner fixture.
138
+ *
139
+ * Reads the deploying stage's GitHub environment variables through request
140
+ * names and exports the canonical machine-credential variables only when they
141
+ * are set. An unset GitHub variable expands to '', which the generated Slice
142
+ * SST config would read as a generation rather than its blue-1 default, so the
143
+ * canonical names never reach the lifecycle when the request is empty.
144
+ */
145
+ function machineCredentialRequestScript() {
146
+ return `set -euo pipefail
147
+ generation="$EBK_REQUESTED_MACHINE_CREDENTIAL_GENERATION"
148
+ retire="$EBK_REQUESTED_MACHINE_RETIRE_PREVIOUS_GENERATION"
149
+ generation_pattern='^(blue|green)-[1-9][0-9]{0,11}$'
150
+ if [ -n "$generation" ] && ! [[ "$generation" =~ $generation_pattern ]]; then
151
+ echo 'EBK_MACHINE_CREDENTIAL_GENERATION must be blue-N or green-N, where N is 1 to 12 digits without a leading zero, or unset'
152
+ exit 1
153
+ fi
154
+ case "$retire" in
155
+ ''|false|true) ;;
156
+ *) echo 'EBK_MACHINE_RETIRE_PREVIOUS_GENERATION must be exactly true or false, or unset'; exit 1 ;;
157
+ esac
158
+ if [ "$retire" = true ]; then
159
+ [ -n "$generation" ] || {
160
+ echo 'Retiring the previous machine credential generation requires EBK_MACHINE_CREDENTIAL_GENERATION to name the current generation'
161
+ exit 1
162
+ }
163
+ if [ "$EBK_ACTION" = deploy ] && [ "$EBK_LIFECYCLE_SCOPE" != full ]; then
164
+ echo 'Retiring the previous machine credential generation requires a Deploy dispatch with lifecycle full; affected scope can skip the Slice'
165
+ exit 1
166
+ fi
167
+ fi
168
+ if [ -n "$generation" ]; then
169
+ echo "EBK_MACHINE_CREDENTIAL_GENERATION=$generation" >> "$GITHUB_ENV"
170
+ echo "Requested machine credential generation: $generation"
171
+ fi
172
+ if [ "$retire" = true ]; then
173
+ echo 'EBK_MACHINE_RETIRE_PREVIOUS_GENERATION=true' >> "$GITHUB_ENV"
174
+ echo 'Requested retirement of the previous machine credential generation'
175
+ fi`;
176
+ }
177
+ function machineCredentialRequestStep() {
178
+ return ` - name: Validate requested machine credential generation
179
+ env:
180
+ ACTIONS_ID_TOKEN_REQUEST_TOKEN: ''
181
+ ACTIONS_ID_TOKEN_REQUEST_URL: ''
182
+ EBK_REQUESTED_MACHINE_CREDENTIAL_GENERATION: \${{ vars.EBK_MACHINE_CREDENTIAL_GENERATION }}
183
+ EBK_REQUESTED_MACHINE_RETIRE_PREVIOUS_GENERATION: \${{ vars.EBK_MACHINE_RETIRE_PREVIOUS_GENERATION }}
184
+ run: |
185
+ ${indentedScript(machineCredentialRequestScript(), 10)}`;
186
+ }
136
187
  /** @internal Exported for executable source-contract tests. */
137
188
  function exactStageDeployerGuardScript(operation, accountVariable) {
138
189
  return `read -r caller_account caller_arn <<< "$(aws sts get-caller-identity --query '[Account,Arn]' --output text)"
@@ -1636,16 +1687,6 @@ ${indentedScript(restoredCandidateValidationScript(), 10)}
1636
1687
  ACTIONS_ID_TOKEN_REQUEST_TOKEN: ''
1637
1688
  ACTIONS_ID_TOKEN_REQUEST_URL: ''
1638
1689
  run: pnpm nx run ${name}:supply-chain-check-protected
1639
- - name: Install pinned uv for generated Python workloads
1640
- if: env.EBK_ACTION == 'deploy'
1641
- env:
1642
- ACTIONS_ID_TOKEN_REQUEST_TOKEN: ''
1643
- ACTIONS_ID_TOKEN_REQUEST_URL: ''
1644
- run: |
1645
- set -euo pipefail
1646
- python3 -m pip install --user --disable-pip-version-check 'uv==${tool_versions_js_1.WORKSPACE_UV_VERSION}'
1647
- echo "$HOME/.local/bin" >> "$GITHUB_PATH"
1648
- "$HOME/.local/bin/uv" --version
1649
1690
  - name: Install pinned Playwright Chromium for deployed smoke proofs
1650
1691
  if: env.EBK_ACTION == 'deploy' && needs.prepare.outputs.has_slices == 'true'
1651
1692
  env:
@@ -1653,6 +1694,7 @@ ${indentedScript(restoredCandidateValidationScript(), 10)}
1653
1694
  ACTIONS_ID_TOKEN_REQUEST_URL: ''
1654
1695
  run: |
1655
1696
  ${indentedScript(protectedBrowserInstallScript(), 10)}
1697
+ ${machineCredentialRequestStep()}
1656
1698
  - name: Revalidate exact protected branch tip before OIDC
1657
1699
  env:
1658
1700
  ACTIONS_ID_TOKEN_REQUEST_TOKEN: ''
@@ -2333,21 +2375,13 @@ ${indentedScript(restoredCandidateValidationScript(), 10)}
2333
2375
  ACTIONS_ID_TOKEN_REQUEST_TOKEN: ''
2334
2376
  ACTIONS_ID_TOKEN_REQUEST_URL: ''
2335
2377
  run: pnpm nx run ${name}:supply-chain-check-protected
2336
- - name: Install pinned uv for generated Python workloads
2337
- env:
2338
- ACTIONS_ID_TOKEN_REQUEST_TOKEN: ''
2339
- ACTIONS_ID_TOKEN_REQUEST_URL: ''
2340
- run: |
2341
- set -euo pipefail
2342
- python3 -m pip install --user --disable-pip-version-check 'uv==${tool_versions_js_1.WORKSPACE_UV_VERSION}'
2343
- echo "$HOME/.local/bin" >> "$GITHUB_PATH"
2344
- "$HOME/.local/bin/uv" --version
2345
2378
  - name: Install pinned Playwright Chromium for deployed smoke proofs
2346
2379
  env:
2347
2380
  ACTIONS_ID_TOKEN_REQUEST_TOKEN: ''
2348
2381
  ACTIONS_ID_TOKEN_REQUEST_URL: ''
2349
2382
  run: |
2350
2383
  ${indentedScript(protectedBrowserInstallScript(), 10)}
2384
+ ${machineCredentialRequestStep()}
2351
2385
  ${revalidateTip}
2352
2386
  - name: Assume the one stage deployment role
2353
2387
  uses: ${actionPins.configureAwsCredentials}
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.renderThinLifecycleDocumentation = renderThinLifecycleDocumentation;
4
4
  const index_js_1 = require("../../repository-policy/index.js");
5
- const tool_versions_js_1 = require("./tool-versions.js");
6
5
  function renderThinLifecycleDocumentation(options) {
7
6
  const stages = (0, index_js_1.activeDeploymentStages)(options.deploymentProfile);
8
7
  const stageList = stages.join(', ');
@@ -22,16 +21,19 @@ checks. Run \`pnpm verify\` at a milestone, not before each development edit.
22
21
  Configure the exact temporary AWS profile and stage deployment role described
23
22
  in \`docs/stage-deployment-authority.md\` before deploying development through
24
23
  \`ebk deploy development --profile=<profile> --expectedRoleArn=<role-arn>\`
25
- (the root \`deploy-local\` target). Do not invoke SST directly.
26
-
27
- Standard Slices include a Python infrastructure provisioner: install \`uv\`
28
- ${tool_versions_js_1.WORKSPACE_UV_VERSION} (Python 3.12 or newer) on PATH before \`ebk dev up\` or
29
- \`ebk deploy\`. Each Standard Slice stops before its SST child starts when
30
- \`uv --version\` fails; a full \`ebk deploy\` may already have deployed
31
- Foundation.
32
- Source-only feature checks do not require it. Slice \`verify\` runs
33
- \`test-integration\`, which needs a running Docker engine for DynamoDB Local (and
34
- PostgreSQL when SQL is declared).
24
+ (the root \`deploy-local\` target). The profile is the human's IAM Identity
25
+ Center profile, typically the one saved by \`ebk dev configure\`. When
26
+ \`ebk dev doctor\` reports the session expired or missing, an attended coding
27
+ agent (local or hosted) may run \`aws sso login --profile <profile>\`; the
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.
34
+
35
+ Slice \`verify\` runs \`test-integration\`, which needs a running Docker engine
36
+ for DynamoDB Local (and PostgreSQL when SQL is declared).
35
37
  `,
36
38
  'docs/git-workflow.md': `# Protected Git workflow
37
39
 
@@ -147,8 +149,13 @@ authority options, for focused deployment after Foundation. Other Slices are
147
149
  not redeployed; required peers must already exist. Omit Slice names for the
148
150
  complete stage. Explicit selection is local-only and its \`selectedSlices\`
149
151
  receipt is not full-stage acceptance or a protected affected-deployment baseline.
150
- \`ebk deploy --help\` lists options; it preserves native TTY/output and does not
151
- accept arbitrary Nx/SST flags or a noninteractive confirmation.
152
+ \`ebk deploy --help\` lists options. The command streams native output unchanged
153
+ and accepts no arbitrary Nx/SST flags; the written deployment receipt is the
154
+ structured result. Add \`--json\` to a development deploy to receive that receipt
155
+ and per-project status on stdout after the run (native output moves to stderr);
156
+ staging and production refuse \`--json\`. Development runs to completion with no
157
+ prompt; only local staging and starter production stop for the human-typed
158
+ acknowledgement described below.
152
159
 
153
160
  The root \`${options.name}:deploy-local\` target orders Foundation before every
154
161
  eligible Product Slice. Each project runs its public Nx \`deploy\` target, which
@@ -227,7 +234,9 @@ pinned SST owns native planning, state, locking, and deployment. Do not invoke
227
234
  SST directly.
228
235
 
229
236
  Before a nonproduction deployment, add the operator/probe CIDRs required by the
230
- stage's \`security/router-waf.json\` entry. Production remains public by default
237
+ stage's \`security/router-waf.json\` entry. This is an ordinary edit to a seeded
238
+ file; an agent may make it after confirming the current public IPv4 address of
239
+ the workstation or probe host with the human. Production remains public by default
231
240
  behind managed rules and rate limiting and requires its blocking rehearsal.
232
241
  The resolved ${rehearsalStage} stage is rehearsed with
233
242
  \`pnpm nx run foundation:router-waf-rehearsal -- --probeUrl=https://<router>/<slice>/api/health --profile=<temporary-profile>\`.
@@ -241,6 +250,15 @@ role. Development accepts a dirty tree and requires no acknowledgement:
241
250
 
242
251
  \`ebk deploy development --profile=<profile> --expectedRoleArn=<role-arn>\`
243
252
 
253
+ For development, when the session is expired or missing, an attended coding
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.
261
+
244
262
  Local staging, when active, requires a clean commit and an interactive
245
263
  \`approve:deploy:staging:<source-commit>\` response. Starter production requires
246
264
  a clean commit and one exact response entered at the real terminal prompt: