@empire-builder-kit/nx 1.0.0-rc.40 → 1.0.0-rc.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -10
- package/package.json +3 -3
- package/src/blueprints/external-sandbox.d.ts +1 -1
- package/src/cli/deploy-runtime.d.ts +25 -1
- package/src/cli/deploy-runtime.js +120 -4
- package/src/cli/dev-command.d.ts +2 -0
- package/src/cli/dev-command.js +8 -0
- package/src/cli/main.js +20 -6
- package/src/cli/personal-secret-runtime.d.ts +12 -0
- package/src/cli/personal-secret-runtime.js +18 -3
- package/src/cli/secret-terminal.js +1 -1
- package/src/container-images.d.ts +1 -1
- package/src/container-images.js +1 -1
- package/src/developer-agent/operation-registry.d.ts +10 -0
- package/src/developer-agent/operation-registry.js +60 -13
- package/src/developer-agent/planning.d.ts +8 -1
- package/src/developer-agent/planning.js +23 -3
- package/src/executors/local-deploy/local-approval.js +1 -1
- package/src/executors/sst-lifecycle/governed-native-operation.js +3 -2
- package/src/executors/sst-lifecycle/run-sst-command.d.ts +6 -0
- package/src/executors/sst-lifecycle/run-sst-command.js +3 -33
- package/src/foundation/cost-estimate.d.ts +170 -0
- package/src/foundation/cost-estimate.js +683 -0
- package/src/generators/preset/tool-versions.d.ts +0 -2
- package/src/generators/preset/tool-versions.js +1 -3
- package/src/generators/preset/workspace-files-adopter-skills.js +39 -18
- package/src/generators/preset/workspace-files-developer-agent.js +83 -27
- package/src/generators/preset/workspace-files-shared-operation-claims.d.ts +10 -0
- package/src/generators/preset/workspace-files-shared-operation-claims.js +59 -0
- package/src/generators/preset/workspace-files-stage-authority.js +13 -2
- package/src/generators/preset/workspace-files-thin-deploy.d.ts +10 -0
- package/src/generators/preset/workspace-files-thin-deploy.js +54 -20
- package/src/generators/preset/workspace-files-thin-docs.js +32 -14
- package/src/generators/preset/workspace-files.js +28 -8
- package/src/generators/slice/built-in-plan-api-contract-files.js +7 -4
- package/src/generators/slice/built-in-plan-authorization-files.js +10 -5
- package/src/generators/slice/built-in-plan-authorization-infrastructure-files.js +933 -249
- package/src/generators/slice/built-in-plan-data-files.js +17 -8
- package/src/generators/slice/built-in-plan-database-retirement-rehearsal-files.js +5 -1
- package/src/generators/slice/built-in-plan-frontend-files.js +7 -0
- package/src/generators/slice/built-in-plan-infrastructure-files.js +0 -1
- package/src/generators/slice/built-in-plan-infrastructure-safety-files.js +8 -3
- package/src/generators/slice/built-in-plan-metadata-files.js +2 -1
- package/src/generators/slice/built-in-plan-reliability-files.js +4 -1
- package/src/generators/slice/built-in-plan-shared.d.ts +2 -2
- package/src/generators/slice/built-in-plan-shared.js +2 -2
- package/src/generators/slice/built-in-plan-testing-persistence-event-files.d.ts +7 -0
- package/src/generators/slice/built-in-plan-testing-persistence-event-files.js +487 -0
- package/src/generators/slice/built-in-plan-testing-persistence-files.js +2 -0
- package/src/generators/slice/built-in-plan.js +3 -1
- package/src/generators/workload/frozen-container.d.ts +1 -1
- package/src/git-policy/github-bootstrap.d.ts +9 -0
- package/src/git-policy/github-bootstrap.js +16 -2
- package/src/local-dev/fleet-inventory.js +18 -10
- package/src/local-dev/fleet-launcher.js +2 -2
- package/src/secrets/personal-command.d.ts +18 -2
- package/src/secrets/personal-command.js +66 -12
- package/src/secrets/verification.js +6 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DeveloperAgentOperationRegistryError = void 0;
|
|
3
|
+
exports.ROUTER_WAF_REHEARSAL_OWNER_RATIONALE = exports.GRAPH_INTERACTIVE_RATIONALE = exports.FORMAT_WRITE_OWNER_RATIONALE = exports.WORKLOAD_DEV_OWNER_RATIONALE = exports.DOCKER_BUILD_OWNER_RATIONALE = exports.DEPLOY_LOCAL_OWNER_RATIONALE = exports.DeveloperAgentOperationRegistryError = void 0;
|
|
4
4
|
exports.joinDeveloperAgentAuthorityClasses = joinDeveloperAgentAuthorityClasses;
|
|
5
5
|
exports.createDeveloperAgentOperationRegistry = createDeveloperAgentOperationRegistry;
|
|
6
6
|
exports.requireDeveloperAgentOperation = requireDeveloperAgentOperation;
|
|
@@ -37,7 +37,16 @@ const PROTECTED_CANONICAL_STAGES = [
|
|
|
37
37
|
'production',
|
|
38
38
|
];
|
|
39
39
|
const PROTECTED_WORKFLOW_ONLY_RATIONALE = 'This exact target is reserved for a protected workflow that supplies reviewed authority and retained evidence; Developer-Agent planning must use that owning workflow.';
|
|
40
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Non-plannable local targets name their real owner. Each string states only
|
|
42
|
+
* behaviour that exists: none of them promises a Developer-Agent plan entry.
|
|
43
|
+
*/
|
|
44
|
+
exports.DEPLOY_LOCAL_OWNER_RATIONALE = 'Development deployment is owned by ebk deploy development [slice]: run that command directly with the saved development --profile and the policy-derived --expectedRoleArn. This root target is its Nx implementation, not a separate entry point.';
|
|
45
|
+
exports.DOCKER_BUILD_OWNER_RATIONALE = 'Local workload image builds use the host Docker daemon outside any bounded owner. Verify workload source with its build, test and typecheck targets; ebk deploy development <slice> builds the deployable image.';
|
|
46
|
+
exports.WORKLOAD_DEV_OWNER_RATIONALE = 'A hot workload process started outside the ebk dev Fleet has no owned port, lifecycle or cleanup. Verify Service and Job source with its test, typecheck and build targets and exercise it through ebk deploy development <slice>.';
|
|
47
|
+
exports.FORMAT_WRITE_OWNER_RATIONALE = 'Formatting rewrites source files only: run pnpm nx format:write directly as part of a source edit, then rerun the required verification.';
|
|
48
|
+
exports.GRAPH_INTERACTIVE_RATIONALE = 'nx graph starts an interactive browser server and is not a bounded operation; use ebk agent context for the read-only project inventory.';
|
|
49
|
+
exports.ROUTER_WAF_REHEARSAL_OWNER_RATIONALE = 'The Router WAF rehearsal requires an exact --probeUrl that planning cannot derive: run it directly through its Nx target with that option after a development deployment.';
|
|
41
50
|
function policyLifecycleActionForTarget(targetName) {
|
|
42
51
|
if (exact('deploy', 'deploy-infrastructure', 'deploy-local', 'deployment-plan', 'foundation-ready')(targetName)) {
|
|
43
52
|
return 'deploy';
|
|
@@ -402,19 +411,19 @@ const TARGET_SIGNATURES = [
|
|
|
402
411
|
const kind = plural === 'services' ? 'service' : 'job';
|
|
403
412
|
return (`docker build -f packages/${slice}/${plural}/${workload}/Dockerfile ` +
|
|
404
413
|
`-t ${slice}-${kind}-${workload}:local ../../../..`);
|
|
405
|
-
}, { nonPlannableRationale:
|
|
414
|
+
}, { nonPlannableRationale: exports.DOCKER_BUILD_OWNER_RATIONALE }),
|
|
406
415
|
runScriptSignature('dev', (input) => input.project.root.includes('/services/')
|
|
407
416
|
? 'node --experimental-strip-types src/main.ts'
|
|
408
417
|
: input.project.root.includes('/jobs/')
|
|
409
418
|
? 'node --experimental-strip-types src/run.ts'
|
|
410
|
-
: undefined, { nonPlannableRationale:
|
|
419
|
+
: undefined, { nonPlannableRationale: exports.WORKLOAD_DEV_OWNER_RATIONALE }),
|
|
411
420
|
runScriptSignature('format', (input) => input.project.tags.includes('scope:workspace')
|
|
412
421
|
? 'nx format:write'
|
|
413
|
-
: undefined, { nonPlannableRationale:
|
|
422
|
+
: undefined, { nonPlannableRationale: exports.FORMAT_WRITE_OWNER_RATIONALE }),
|
|
414
423
|
runScriptSignature('format:check', (input) => input.project.tags.includes('scope:workspace')
|
|
415
424
|
? 'nx format:check --all'
|
|
416
425
|
: undefined),
|
|
417
|
-
runScriptSignature('graph', (input) => input.project.tags.includes('scope:workspace') ? 'nx graph' : undefined, { nonPlannableRationale:
|
|
426
|
+
runScriptSignature('graph', (input) => input.project.tags.includes('scope:workspace') ? 'nx graph' : undefined, { nonPlannableRationale: exports.GRAPH_INTERACTIVE_RATIONALE }),
|
|
418
427
|
runScriptSignature('health', (input) => input.project.tags.includes('scope:workspace')
|
|
419
428
|
? `nx run ${input.project.name}:workspace-health`
|
|
420
429
|
: undefined),
|
|
@@ -441,7 +450,7 @@ const TARGET_SIGNATURES = [
|
|
|
441
450
|
? 'pnpm run lint && pnpm run typecheck && pnpm test && pnpm run build'
|
|
442
451
|
: undefined),
|
|
443
452
|
executorSignature('deployment-plan', '@empire-builder-kit/nx:deployment-plan', exactOptions(() => ({ action: 'deploy', stage: 'staging' }))),
|
|
444
|
-
executorSignature('deploy-local', '@empire-builder-kit/nx:local-deploy', exactOptions(() => ({ stage: 'development' })), ['workspace-health'], { nonPlannableRationale:
|
|
453
|
+
executorSignature('deploy-local', '@empire-builder-kit/nx:local-deploy', exactOptions(() => ({ stage: 'development' })), ['workspace-health'], { nonPlannableRationale: exports.DEPLOY_LOCAL_OWNER_RATIONALE }),
|
|
445
454
|
executorSignature('dev', '@empire-builder-kit/nx:fleet', exactOptions(() => ({})), undefined, {
|
|
446
455
|
continuous: true,
|
|
447
456
|
}),
|
|
@@ -528,7 +537,7 @@ const TARGET_SIGNATURES = [
|
|
|
528
537
|
'capabilities,contract,deployIfMissing,foundationProject,stage', [{ params: 'ignore', projects: ['foundation'], target: 'verify' }]),
|
|
529
538
|
executorSignature('profile-preflight', '@empire-builder-kit/nx:foundation-profile-preflight', exactOptions(() => ({ stage: 'development' }))),
|
|
530
539
|
executorSignature('remove-preflight', '@empire-builder-kit/nx:foundation-remove-preflight', exactOptions(() => ({ stage: 'development' }))),
|
|
531
|
-
executorSignature('router-waf-rehearsal', '@empire-builder-kit/nx:router-waf-rehearsal', exactOptions(() => ({})), undefined, { nonPlannableRationale:
|
|
540
|
+
executorSignature('router-waf-rehearsal', '@empire-builder-kit/nx:router-waf-rehearsal', exactOptions(() => ({})), undefined, { nonPlannableRationale: exports.ROUTER_WAF_REHEARSAL_OWNER_RATIONALE }),
|
|
532
541
|
];
|
|
533
542
|
/**
|
|
534
543
|
* Rules are deliberately ordered from highest/conservative authority to
|
|
@@ -574,6 +583,8 @@ const TARGET_RULES = [
|
|
|
574
583
|
!suffix('-report', '-status')(targetName)),
|
|
575
584
|
requiredVerification: ['verify', 'protected-proof'],
|
|
576
585
|
},
|
|
586
|
+
// These two apply shared GitHub repository or AWS secret-container state
|
|
587
|
+
// outside the personal development stage, so they keep an approval point.
|
|
577
588
|
{
|
|
578
589
|
approvalRequired: true,
|
|
579
590
|
authority: 'protected-propose',
|
|
@@ -589,12 +600,33 @@ const TARGET_RULES = [
|
|
|
589
600
|
'docs/developer-agent.md',
|
|
590
601
|
],
|
|
591
602
|
evidenceClasses: ['protected-promotion-proof'],
|
|
592
|
-
matches:
|
|
603
|
+
matches: exact('github-bootstrap', 'secret-initialize'),
|
|
604
|
+
requiredVerification: ['source', 'protected-proof'],
|
|
605
|
+
},
|
|
606
|
+
// Report-first plans, collectors and deployed verification read and
|
|
607
|
+
// propose only; staging and production reach stays bounded by the
|
|
608
|
+
// deployment role, not by a plan-time approval point.
|
|
609
|
+
{
|
|
610
|
+
approvalRequired: false,
|
|
611
|
+
authority: 'protected-propose',
|
|
612
|
+
contractClasses: [
|
|
613
|
+
'configuration',
|
|
614
|
+
'infrastructure',
|
|
615
|
+
'reliability',
|
|
616
|
+
'performance',
|
|
617
|
+
],
|
|
618
|
+
documentationPaths: [
|
|
619
|
+
'AGENTS.md',
|
|
620
|
+
'docs/git-workflow.md',
|
|
621
|
+
'docs/developer-agent.md',
|
|
622
|
+
],
|
|
623
|
+
evidenceClasses: ['protected-promotion-proof'],
|
|
624
|
+
matches: (targetName) => exact('deployment-plan', 'infrastructure-plan', 'infrastructure-drift', 'ecr-inspector-collect', 'performance-cost-collect', 'reliability-deployed-verify', 'reliability-diagnostic', 'reliability-exercise-collect', 'secret-metadata', 'smoke-deployed', 'stage-authority-render')(targetName),
|
|
593
625
|
requiredVerification: ['source', 'protected-proof'],
|
|
594
626
|
},
|
|
595
627
|
{
|
|
596
628
|
applicableStages: ['development'],
|
|
597
|
-
approvalRequired:
|
|
629
|
+
approvalRequired: false,
|
|
598
630
|
authority: 'development-mutate',
|
|
599
631
|
contractClasses: ['database'],
|
|
600
632
|
documentationPaths: ['AGENTS.md', 'docs/developer-agent.md'],
|
|
@@ -602,13 +634,25 @@ const TARGET_RULES = [
|
|
|
602
634
|
matches: exact('test-integration', 'verify-local-browser'),
|
|
603
635
|
requiredVerification: ['local-integration'],
|
|
604
636
|
},
|
|
637
|
+
// dev-setup can reach host trust-store installation and privileged port
|
|
638
|
+
// forwarding (--trust, --portless): an OS-level consent boundary.
|
|
605
639
|
{
|
|
606
640
|
approvalRequired: true,
|
|
607
641
|
authority: 'development-mutate',
|
|
608
642
|
contractClasses: ['database', 'infrastructure'],
|
|
609
643
|
documentationPaths: ['AGENTS.md', 'docs/developer-agent.md'],
|
|
610
644
|
evidenceClasses: ['local-integration'],
|
|
611
|
-
matches: exact('dev
|
|
645
|
+
matches: exact('dev-setup'),
|
|
646
|
+
requiredVerification: ['local-integration'],
|
|
647
|
+
},
|
|
648
|
+
// Personal development-stage work under the human's own bounded identity.
|
|
649
|
+
{
|
|
650
|
+
approvalRequired: false,
|
|
651
|
+
authority: 'development-mutate',
|
|
652
|
+
contractClasses: ['database', 'infrastructure'],
|
|
653
|
+
documentationPaths: ['AGENTS.md', 'docs/developer-agent.md'],
|
|
654
|
+
evidenceClasses: ['local-integration'],
|
|
655
|
+
matches: exact('dev', 'dev-cleanup', 'dev-task-cleanup', 'db-local-down', 'db-local-migrate', 'db-local-up', 'secret-personal-down'),
|
|
612
656
|
requiredVerification: ['local-integration'],
|
|
613
657
|
},
|
|
614
658
|
{
|
|
@@ -673,7 +717,7 @@ function localDevOperations(projects, externalOwnedProjectNames, developmentClos
|
|
|
673
717
|
});
|
|
674
718
|
const lifecycle = (command, slice) => ({
|
|
675
719
|
applicableStages: ['development'],
|
|
676
|
-
approvalRequired:
|
|
720
|
+
approvalRequired: false,
|
|
677
721
|
authority: 'development-mutate',
|
|
678
722
|
command: {
|
|
679
723
|
args: ['dev', command, slice, '--no-wait', '--json'],
|
|
@@ -1007,7 +1051,10 @@ function operationForTarget(input, forwardedStage, reviewedExternal = false) {
|
|
|
1007
1051
|
: ALL_CANONICAL_STAGES;
|
|
1008
1052
|
return {
|
|
1009
1053
|
applicableStages,
|
|
1010
|
-
|
|
1054
|
+
// Development needs no lifecycle acknowledgement (the governed executors
|
|
1055
|
+
// prompt only for staging and production); protected stages never reach
|
|
1056
|
+
// this branch and keep the rule's approval.
|
|
1057
|
+
approvalRequired: developmentLifecycle ? false : rule.approvalRequired,
|
|
1011
1058
|
authority,
|
|
1012
1059
|
...(authority === 'protected-mutate' || authority === 'destructive'
|
|
1013
1060
|
? {}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DeveloperAgentContext, type DeveloperAgentGeneratorInput, type DeveloperAgentGeneratorPreview, type DeveloperAgentPlan } from './model.js';
|
|
1
|
+
import { type DeveloperAgentAuthorityClass, type DeveloperAgentContext, type DeveloperAgentGeneratorInput, type DeveloperAgentGeneratorPreview, type DeveloperAgentPlan } from './model.js';
|
|
2
2
|
import { type DeveloperAgentOperationRegistry } from './operation-registry.js';
|
|
3
3
|
export interface DeveloperAgentPlanRequest {
|
|
4
4
|
acceptanceCriteriaReference: string;
|
|
@@ -15,4 +15,11 @@ export declare class DeveloperAgentPlanInputError extends Error {
|
|
|
15
15
|
readonly classification: "invalid-input";
|
|
16
16
|
constructor(message: string);
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Names the gate an approval point actually stands for. Development-stage
|
|
20
|
+
* work through the bounded owners carries no approval point at all; the
|
|
21
|
+
* remaining points are protected authority, destructive recovery, an explicit
|
|
22
|
+
* shared-state apply, or host-level consent (dev-setup trust and ports).
|
|
23
|
+
*/
|
|
24
|
+
export declare function approvalPointDescription(authority: DeveloperAgentAuthorityClass): string;
|
|
18
25
|
export declare function planDeveloperAgentWork(context: DeveloperAgentContext, registry: DeveloperAgentOperationRegistry, request: DeveloperAgentPlanRequest, options?: DeveloperAgentPlanOptions): DeveloperAgentPlan;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DeveloperAgentPlanInputError = void 0;
|
|
4
|
+
exports.approvalPointDescription = approvalPointDescription;
|
|
4
5
|
exports.planDeveloperAgentWork = planDeveloperAgentWork;
|
|
5
6
|
const model_js_1 = require("./model.js");
|
|
6
7
|
const index_js_1 = require("../testing-evidence/index.js");
|
|
@@ -222,6 +223,27 @@ function policyBlockers(context, operation) {
|
|
|
222
223
|
}
|
|
223
224
|
return blockers;
|
|
224
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* Names the gate an approval point actually stands for. Development-stage
|
|
228
|
+
* work through the bounded owners carries no approval point at all; the
|
|
229
|
+
* remaining points are protected authority, destructive recovery, an explicit
|
|
230
|
+
* shared-state apply, or host-level consent (dev-setup trust and ports).
|
|
231
|
+
*/
|
|
232
|
+
function approvalPointDescription(authority) {
|
|
233
|
+
switch (authority) {
|
|
234
|
+
case 'protected-mutate':
|
|
235
|
+
return 'Matching GitHub environment and OIDC authority';
|
|
236
|
+
case 'destructive':
|
|
237
|
+
return 'Explicit human approval of the exact target and retained recovery proof';
|
|
238
|
+
case 'protected-propose':
|
|
239
|
+
return 'Human approval before the owning tool applies shared GitHub or AWS state with --apply';
|
|
240
|
+
case 'development-mutate':
|
|
241
|
+
return 'Human consent to host trust-store or privileged port-forwarding changes; the human answers any OS credential prompt';
|
|
242
|
+
case 'local-source':
|
|
243
|
+
case 'read-only':
|
|
244
|
+
return 'Explicit human approval before invoking the owning tool';
|
|
245
|
+
}
|
|
246
|
+
}
|
|
225
247
|
function nextAction(operation, blockers) {
|
|
226
248
|
if (blockers.length > 0) {
|
|
227
249
|
return {
|
|
@@ -381,9 +403,7 @@ function planDeveloperAgentWork(context, registry, request, options = {}) {
|
|
|
381
403
|
? [
|
|
382
404
|
{
|
|
383
405
|
authority: operation.authority,
|
|
384
|
-
description: operation.authority
|
|
385
|
-
? 'Matching GitHub environment and OIDC authority'
|
|
386
|
-
: 'Explicit owning-tool approval',
|
|
406
|
+
description: approvalPointDescription(operation.authority),
|
|
387
407
|
},
|
|
388
408
|
]
|
|
389
409
|
: [],
|
|
@@ -5,7 +5,7 @@ exports.createTtyLocalMutationApprover = createTtyLocalMutationApprover;
|
|
|
5
5
|
const promises_1 = require("node:readline/promises");
|
|
6
6
|
class LocalMutationApprovalUnavailableError extends Error {
|
|
7
7
|
constructor() {
|
|
8
|
-
super('Local protected-stage mutation requires an interactive TTY
|
|
8
|
+
super('Local protected-stage mutation requires a human at an interactive TTY to type the exact acknowledgement challenge. Development needs no acknowledgement. An agent without a terminal should hand the human the exact command to run in their own terminal, or propose the change through the protected GitHub workflow.');
|
|
9
9
|
this.name = 'LocalMutationApprovalUnavailableError';
|
|
10
10
|
}
|
|
11
11
|
}
|
|
@@ -30,6 +30,7 @@ function readSource(root) {
|
|
|
30
30
|
workingTreeDigest: identity.digest,
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
+
const LOCAL_PROTECTED_LIFECYCLE_TTY_MESSAGE = 'Local protected-stage lifecycle mutation requires a human at an interactive TTY to type the exact acknowledgement challenge. Development needs no acknowledgement. An agent without a terminal should hand the human the exact command to run in their own terminal, or propose the change through the protected GitHub workflow.';
|
|
33
34
|
/** Active operator acknowledgement, not an independent-review claim. */
|
|
34
35
|
function createTtyGovernedNativeOperationApprover(terminal = {
|
|
35
36
|
input: process.stdin,
|
|
@@ -37,7 +38,7 @@ function createTtyGovernedNativeOperationApprover(terminal = {
|
|
|
37
38
|
}) {
|
|
38
39
|
return async ({ challenge }) => {
|
|
39
40
|
if (!terminal.input.isTTY || !terminal.output.isTTY) {
|
|
40
|
-
throw new Error(
|
|
41
|
+
throw new Error(LOCAL_PROTECTED_LIFECYCLE_TTY_MESSAGE);
|
|
41
42
|
}
|
|
42
43
|
const prompt = (0, promises_1.createInterface)({
|
|
43
44
|
input: terminal.input,
|
|
@@ -48,7 +49,7 @@ function createTtyGovernedNativeOperationApprover(terminal = {
|
|
|
48
49
|
return ((await prompt.question(`Type ${challenge} to continue: `)) === challenge);
|
|
49
50
|
}
|
|
50
51
|
catch {
|
|
51
|
-
throw new Error(
|
|
52
|
+
throw new Error(LOCAL_PROTECTED_LIFECYCLE_TTY_MESSAGE);
|
|
52
53
|
}
|
|
53
54
|
finally {
|
|
54
55
|
prompt.close();
|
|
@@ -68,6 +68,12 @@ export declare function runGovernedChildProcess(input: {
|
|
|
68
68
|
environment: NodeJS.ProcessEnv;
|
|
69
69
|
executable: string;
|
|
70
70
|
spawnChild?: typeof spawn;
|
|
71
|
+
/**
|
|
72
|
+
* Defaults to inheriting all three streams. A structured caller may route
|
|
73
|
+
* the child's stdout to the parent's stderr (`['inherit', 2, 'inherit']`)
|
|
74
|
+
* so its own stdout carries only the structured result.
|
|
75
|
+
*/
|
|
76
|
+
stdio?: 'inherit' | readonly ['inherit', 2, 'inherit'];
|
|
71
77
|
}): Promise<GovernedChildProcessResult>;
|
|
72
78
|
export declare function createSstChildEnvironment(ambient: NodeJS.ProcessEnv, invocation: SstCommandInvocation['environment']): NodeJS.ProcessEnv;
|
|
73
79
|
export declare function assertSafeSstForwardedArguments(args: readonly string[]): void;
|
|
@@ -241,7 +241,9 @@ function runGovernedChildProcess(input) {
|
|
|
241
241
|
detached: process.platform !== 'win32',
|
|
242
242
|
env: environment,
|
|
243
243
|
shell: false,
|
|
244
|
-
stdio: 'inherit'
|
|
244
|
+
stdio: input.stdio === undefined || input.stdio === 'inherit'
|
|
245
|
+
? 'inherit'
|
|
246
|
+
: ['inherit', 2, 'inherit'],
|
|
245
247
|
});
|
|
246
248
|
let finishing = false;
|
|
247
249
|
let settled = false;
|
|
@@ -760,38 +762,6 @@ function buildSstCommandInvocation(command, options, context, environment = proc
|
|
|
760
762
|
};
|
|
761
763
|
}
|
|
762
764
|
async function runSstLifecyclePreflights(command, options, context, invocation, dependencies = {}, environment = process.env) {
|
|
763
|
-
// Standard Slices contain a Python infrastructure provisioner even when
|
|
764
|
-
// their application handlers are TypeScript. Fail before SST can partially
|
|
765
|
-
// create resources; recovery operations must remain available without build
|
|
766
|
-
// tooling. This is a local prerequisite, not a provider-plan gate.
|
|
767
|
-
if ((command === 'dev' || command === 'deploy') &&
|
|
768
|
-
(0, node_fs_1.existsSync)((0, node_path_1.join)(invocation.cwd, 'pyproject.toml'))) {
|
|
769
|
-
const manifest = (0, node_fs_1.lstatSync)((0, node_path_1.join)(invocation.cwd, 'pyproject.toml'));
|
|
770
|
-
if (!manifest.isFile() || manifest.isSymbolicLink()) {
|
|
771
|
-
throw new Error('Python tooling manifest must be a regular project file.');
|
|
772
|
-
}
|
|
773
|
-
const childEnvironment = {};
|
|
774
|
-
for (const key of ['PATH', 'Path', 'PATHEXT', 'SystemRoot', 'SYSTEMROOT']) {
|
|
775
|
-
if (environment[key] !== undefined)
|
|
776
|
-
childEnvironment[key] = environment[key];
|
|
777
|
-
}
|
|
778
|
-
const result = (0, node_child_process_1.spawnSync)('uv', ['--version'], {
|
|
779
|
-
cwd: invocation.cwd,
|
|
780
|
-
env: childEnvironment,
|
|
781
|
-
encoding: 'utf8',
|
|
782
|
-
timeout: 5_000,
|
|
783
|
-
maxBuffer: 4_096,
|
|
784
|
-
windowsHide: true,
|
|
785
|
-
shell: false,
|
|
786
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
787
|
-
});
|
|
788
|
-
if (result.error ||
|
|
789
|
-
result.status !== 0 ||
|
|
790
|
-
!/^uv \d+\.\d+\.\d+\b/.test(result.stdout ?? '')) {
|
|
791
|
-
// Do not surface arbitrary tool stderr or inherited credential material.
|
|
792
|
-
throw new Error(`Python tooling for ${context.projectName ?? 'the selected project'} requires uv on PATH. Install the workspace-documented uv version and retry the same EBK command. No SST child started.`);
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
765
|
const stage = command === 'dev' ||
|
|
796
766
|
(command === 'remove' && invocation.environment.EBK_NX_TASK_CLEANUP) ||
|
|
797
767
|
(command === 'unlock' && invocation.environment.EBK_NX_TASK_UNLOCK)
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { type DeploymentProfile } from '../repository-policy/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Dated AWS list-price snapshot for the generated cost estimate.
|
|
4
|
+
*
|
|
5
|
+
* Every price is copied from the public AWS Price List bulk API
|
|
6
|
+
* (https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/index.json),
|
|
7
|
+
* OnDemand terms, without rounding. `usd` is the published price per AWS
|
|
8
|
+
* `unit`; `per` only scales the displayed unit (for example per million
|
|
9
|
+
* requests). Refresh the whole snapshot together, change `capturedOn`, and
|
|
10
|
+
* re-render docs/foundation.md; never compute a date at generation time.
|
|
11
|
+
*/
|
|
12
|
+
export interface ListPriceSource {
|
|
13
|
+
/** Price List offer code. */
|
|
14
|
+
offer: string;
|
|
15
|
+
/** Version segment of the offer file URL. */
|
|
16
|
+
version: string;
|
|
17
|
+
/** Offer file region segment: us-east-1, or aws-other for global rates. */
|
|
18
|
+
file: 'aws-other' | 'us-east-1';
|
|
19
|
+
sku: string;
|
|
20
|
+
rateCode: string;
|
|
21
|
+
usageType: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ListUnitPrice {
|
|
24
|
+
/** Exact published USD price per AWS unit. */
|
|
25
|
+
usd: string;
|
|
26
|
+
/** Display multiplier (a power of ten) applied to `usd`. */
|
|
27
|
+
per: number;
|
|
28
|
+
/** Display unit for `per` AWS units, e.g. "million requests". */
|
|
29
|
+
unit: string;
|
|
30
|
+
source: ListPriceSource;
|
|
31
|
+
}
|
|
32
|
+
export declare const FOUNDATION_LIST_PRICE_SNAPSHOT: {
|
|
33
|
+
readonly capturedOn: "2026-10-02";
|
|
34
|
+
readonly currency: "USD";
|
|
35
|
+
readonly hoursPerMonth: 730;
|
|
36
|
+
readonly offerFileUrlTemplate: "https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/<offer>/<version>/<file>/index.json";
|
|
37
|
+
readonly region: {
|
|
38
|
+
readonly code: "us-east-1";
|
|
39
|
+
readonly name: "US East (N. Virginia)";
|
|
40
|
+
};
|
|
41
|
+
readonly prices: {
|
|
42
|
+
readonly apiGatewayHttpRequests: ListUnitPrice;
|
|
43
|
+
readonly appConfigConfigurationRequests: ListUnitPrice;
|
|
44
|
+
readonly appConfigConfigurationsReceived: ListUnitPrice;
|
|
45
|
+
readonly auroraPostgresBackup: ListUnitPrice;
|
|
46
|
+
readonly auroraPostgresIo: ListUnitPrice;
|
|
47
|
+
readonly auroraPostgresServerlessV2Acu: ListUnitPrice;
|
|
48
|
+
readonly auroraPostgresStorage: ListUnitPrice;
|
|
49
|
+
readonly cloudFrontDataTransferOut: ListUnitPrice;
|
|
50
|
+
readonly cloudFrontHttpsRequests: ListUnitPrice;
|
|
51
|
+
readonly cloudWatchAlarmMetric: ListUnitPrice;
|
|
52
|
+
readonly cloudWatchCustomMetric: ListUnitPrice;
|
|
53
|
+
readonly cloudWatchDashboard: ListUnitPrice;
|
|
54
|
+
readonly cloudWatchLogsDataProtection: ListUnitPrice;
|
|
55
|
+
readonly cloudWatchLogsIngest: ListUnitPrice;
|
|
56
|
+
readonly cloudWatchLogsStorage: ListUnitPrice;
|
|
57
|
+
readonly cognitoEssentialsMau: ListUnitPrice;
|
|
58
|
+
readonly cognitoLiteMau: ListUnitPrice;
|
|
59
|
+
readonly cognitoMachineAppClient: ListUnitPrice;
|
|
60
|
+
readonly cognitoMachineTokenRequest: ListUnitPrice;
|
|
61
|
+
readonly dynamoDbPitrStorage: ListUnitPrice;
|
|
62
|
+
readonly dynamoDbReadRequestUnits: ListUnitPrice;
|
|
63
|
+
readonly dynamoDbStorage: ListUnitPrice;
|
|
64
|
+
readonly dynamoDbWriteRequestUnits: ListUnitPrice;
|
|
65
|
+
readonly ec2T4gNano: ListUnitPrice;
|
|
66
|
+
readonly eventBridgeArchiveProcessed: ListUnitPrice;
|
|
67
|
+
readonly eventBridgeArchiveStorage: ListUnitPrice;
|
|
68
|
+
readonly eventBridgeCustomEvents: ListUnitPrice;
|
|
69
|
+
readonly fargateMemoryGbHour: ListUnitPrice;
|
|
70
|
+
readonly fargateVcpuHour: ListUnitPrice;
|
|
71
|
+
readonly kmsKey: ListUnitPrice;
|
|
72
|
+
readonly kmsRequests: ListUnitPrice;
|
|
73
|
+
readonly lambdaComputeX86: ListUnitPrice;
|
|
74
|
+
readonly lambdaRequests: ListUnitPrice;
|
|
75
|
+
readonly natGatewayData: ListUnitPrice;
|
|
76
|
+
readonly natGatewayHour: ListUnitPrice;
|
|
77
|
+
readonly publicIpv4InUse: ListUnitPrice;
|
|
78
|
+
readonly route53HostedZone: ListUnitPrice;
|
|
79
|
+
readonly s3StandardStorage: ListUnitPrice;
|
|
80
|
+
readonly secretsManagerApi: ListUnitPrice;
|
|
81
|
+
readonly secretsManagerSecret: ListUnitPrice;
|
|
82
|
+
readonly snsRequests: ListUnitPrice;
|
|
83
|
+
readonly sqsFifoRequests: ListUnitPrice;
|
|
84
|
+
readonly sqsStandardRequests: ListUnitPrice;
|
|
85
|
+
readonly stepFunctionsStandardTransitions: ListUnitPrice;
|
|
86
|
+
readonly wafRequests: ListUnitPrice;
|
|
87
|
+
readonly wafRule: ListUnitPrice;
|
|
88
|
+
readonly wafWebAcl: ListUnitPrice;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
export type ListPriceKey = keyof typeof FOUNDATION_LIST_PRICE_SNAPSHOT.prices;
|
|
92
|
+
/**
|
|
93
|
+
* Generated Foundation quantities that are literals in the Foundation template
|
|
94
|
+
* or inside SST 4.17.1 components rather than in a framework contract. The
|
|
95
|
+
* cost-estimate count-drift spec executes the generated Foundation and fails
|
|
96
|
+
* when any of these differ from what the generator constructs.
|
|
97
|
+
*/
|
|
98
|
+
export declare const FOUNDATION_COST_INVENTORY: {
|
|
99
|
+
/** One CloudFront Router Web ACL per stage. */
|
|
100
|
+
readonly wafWebAcls: 1;
|
|
101
|
+
/** One Foundation CloudWatch dashboard per stage. */
|
|
102
|
+
readonly dashboards: 1;
|
|
103
|
+
/** Declared network: `az: 2`, one Elastic IP and one NAT unit per public subnet. */
|
|
104
|
+
readonly availabilityZones: 2;
|
|
105
|
+
/** SST Vpc Cloud Map private DNS namespace (a Route 53 private hosted zone). */
|
|
106
|
+
readonly privateHostedZones: 1;
|
|
107
|
+
/** Declared nonproduction NAT mode; production uses its capacity contract. */
|
|
108
|
+
readonly nonproductionNat: "ec2";
|
|
109
|
+
/** SST Aurora master credential secret. */
|
|
110
|
+
readonly auroraMasterSecrets: 1;
|
|
111
|
+
/** Declared SQL Foundation alarm metrics (Aurora capacity alarm). */
|
|
112
|
+
readonly sqlAlarmMetrics: 1;
|
|
113
|
+
/** Declared nonproduction Aurora scaling. */
|
|
114
|
+
readonly nonproductionAurora: {
|
|
115
|
+
readonly development: {
|
|
116
|
+
readonly max: "2 ACU";
|
|
117
|
+
readonly min: "0 ACU";
|
|
118
|
+
readonly pauseAfter: "5 minutes";
|
|
119
|
+
};
|
|
120
|
+
readonly staging: {
|
|
121
|
+
readonly max: "4 ACU";
|
|
122
|
+
readonly min: "0 ACU";
|
|
123
|
+
readonly pauseAfter: "5 minutes";
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
/** Seeded Router WAF access: nonproduction allowlist, production public. */
|
|
127
|
+
readonly routerWafAccess: {
|
|
128
|
+
readonly development: "allowlist";
|
|
129
|
+
readonly staging: "allowlist";
|
|
130
|
+
readonly production: "public";
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
export interface StandardSliceCostInventory {
|
|
134
|
+
alarms: number;
|
|
135
|
+
alarmMetrics: number;
|
|
136
|
+
dataProtectedLogGroups: number;
|
|
137
|
+
kmsKeys: number;
|
|
138
|
+
/** Secrets Manager secrets created by Slice infrastructure. */
|
|
139
|
+
secrets: number;
|
|
140
|
+
machineClients: number;
|
|
141
|
+
dashboards: number;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Per-stage fixed inventory of one default Standard Slice (no async adapters,
|
|
145
|
+
* performance load off). The count-drift spec renders and executes the
|
|
146
|
+
* generated Slice infrastructure and fails when these differ.
|
|
147
|
+
*/
|
|
148
|
+
export declare const STANDARD_SLICE_COST_INVENTORY: Readonly<{
|
|
149
|
+
sqlFree: StandardSliceCostInventory;
|
|
150
|
+
sqlDeclared: StandardSliceCostInventory;
|
|
151
|
+
personalStage: StandardSliceCostInventory;
|
|
152
|
+
}>;
|
|
153
|
+
export declare const FOUNDATION_COST_ESTIMATE_BEGIN_MARKER = "<!-- ebk:foundation-cost-estimate:begin -->";
|
|
154
|
+
export declare const FOUNDATION_COST_ESTIMATE_END_MARKER = "<!-- ebk:foundation-cost-estimate:end -->";
|
|
155
|
+
/** The exact label every rendered estimate carries. */
|
|
156
|
+
export declare function foundationCostEstimateLabel(): string;
|
|
157
|
+
/** Nonproduction Aurora scaling as costs.md prose, e.g. "0–4 ACUs, pause after 5 idle minutes". */
|
|
158
|
+
export declare function nonproductionAuroraScalingLabel(stage: 'development' | 'staging'): string;
|
|
159
|
+
export interface FoundationCostEstimateOptions {
|
|
160
|
+
deploymentProfile: DeploymentProfile;
|
|
161
|
+
/** Markdown level of the estimate's top heading (2 for costs.md, 3 for docs). */
|
|
162
|
+
headingLevel: 2 | 3;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Pure, deterministic Markdown renderer for the dated list-price estimate.
|
|
166
|
+
* Quantities derive from the Foundation capability plan, the deployment
|
|
167
|
+
* profile's active stages, the production capacity contracts and the
|
|
168
|
+
* drift-checked inventories above. No clock, network or environment input.
|
|
169
|
+
*/
|
|
170
|
+
export declare function renderFoundationCostEstimate(options: FoundationCostEstimateOptions): string;
|