cdk-preflight 0.0.23 → 0.0.25
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/.jsii +3 -3
- package/AGENTS.md +2 -0
- package/README.md +22 -0
- package/docs/rules.md +14 -0
- package/lib/index.js +1 -1
- package/lib/rules.generated.js +157 -2
- package/package.json +1 -1
package/.jsii
CHANGED
|
@@ -9414,7 +9414,7 @@
|
|
|
9414
9414
|
},
|
|
9415
9415
|
"name": "cdk-preflight",
|
|
9416
9416
|
"readme": {
|
|
9417
|
-
"markdown": "# cdk-preflight\n\n**Catch deploy-time CloudFormation failures at `cdk synth` time.**\n\nSome CloudFormation constraints are not expressed in resource provider schemas — they live only in documentation, in service API validation, or across multiple properties. Templates that violate them pass `cdk synth`, pass CloudFormation pre-deployment validation, and then fail minutes into a deployment, burning a rollback cycle.\n\ncdk-preflight is a curated [Rego rule pack](docs/rules.md) for exactly those constraints, evaluated with the CloudFormation validation engine that ships inside `aws-cdk-lib` (>= 2.267.0). By default a violation **fails `cdk synth`** — a template that is known to fail at deploy time never leaves your machine.\n\nEvery bundled rule is backed by a `fail`/`pass` template pair, and the failure has been reproduced against real AWS (or is explicitly marked `doc-only`). Rules that the built-in validation engine already covers are deliberately **not** duplicated — a test suite enforces this.\n\n## Quick start\n\n```bash\nnpm i -D cdk-preflight\nnpx cdk-preflight init # inserts Preflight.apply(app) into your CDK app\n```\n\nor add one line yourself:\n\n```ts\nimport { Preflight } from 'cdk-preflight';\n\nconst app = new App();\nPreflight.apply(app);\n```\n\nOn violation, `cdk synth` fails with one error per finding, including the construct trace:\n\n```text\nERROR idle_timeout.timeout_seconds is 5000 but must be between 1 and 4000 seconds (cdk-preflight)\n MyStack/Alb/Resource (Alb16C2F182) aws-cdk-lib.aws_elasticloadbalancingv2.CfnLoadBalancer\n\nSynthesis finished with errors\n```\n\n## Observe-only mode\n\nTo roll the rules out gradually, start with `enforce: false`: findings then surface as synth **warnings** through the CDK built-in validator, with construct traces and per-finding acknowledgement:\n\n```ts\nPreflight.apply(app, { enforce: false });\n```\n\n```text\nWARNING idle_timeout.timeout_seconds is 5000 but must be between 1 and 4000 seconds (CloudFormation Validate)\n MyStack/Alb (Alb) aws-cdk-lib.aws_elasticloadbalancingv2.CfnLoadBalancer\n Acknowledge with 'CloudFormation-Validate::pf-elbv2-lb-idle-timeout-range'\n```\n\n| Option | Default | Effect |\n|---|---|---|\n| `enforce` | `true` | Violations of bundled rules fail synthesis; set to `false` to only warn |\n| `strict` | `false` | With `enforce`: also fail on error-class findings (`ERROR`/`FATAL`, e.g. `F3034`) of the built-in validation engine itself, which the CDK currently downgrades to warnings |\n| `exclude` | `[]` | Rule ids to disable |\n| `includeUpstreamPending` | `true` | Include rules already proposed to the upstream engine but not yet merged |\n\nTo opt out of a single rule, pass its id in `exclude`. In observe-only mode, individual findings can also be suppressed with the CDK acknowledge mechanism shown in the warning text.\n\n## Bundled rules\n\nSee [docs/rules.md](docs/rules.md) for the generated rule table. Highlights:\n\n- **ELBv2**: `idle_timeout` / `deregistration_delay` / `slow_start` attribute ranges (stringly-typed Key/Value attributes are invisible to schema validation)\n- **IAM**: managed (6,144 chars) and inline (role/group/user) policy document size limits\n- **CloudFront**: `MinTTL <= DefaultTTL <= MaxTTL` ordering, ACM certificates must live in `us-east-1`\n- **Step Functions**: `Next`/`Default`/`Choices` must reference defined states (a dangling `StartAt` is already caught by the engine's built-in `E3601`)\n- **EC2**: security group TCP/UDP port ranges and `FromPort <= ToPort`\n\n## For AI agents\n\nTo add cdk-preflight to a CDK app:\n\n1. `npm i -D cdk-preflight`\n2. `npx cdk-preflight init` (finds the entry point via `cdk.json` and inserts `Preflight.apply(app)`; use `--dry-run` to preview)\n3. Run `cdk synth`. Violations fail the synth with a validation report; each finding carries a rule id, the actual value, and a suggested fix\n4. To fix a finding, prefer correcting the resource. To opt out instead: `exclude: ['<rule-id>']` disables one rule, `enforce: false` switches to warn-only reporting\n\nThe machine-readable findings are written to `cdk.out/validation-report.json` when synthesizing with `-c @aws-cdk/core:validationReportJson=true`.\n\n## How it works\n\n`Preflight.apply()` evaluates the rules with the [cloudformation-validate](https://github.com/aws-cloudformation/cloudformation-validate) Rust/WASM engine that ships inside `aws-cdk-lib` — no extra binaries, no network access at synth time. In the default enforce mode the engine is invoked through a dedicated CDK validation plugin so that violations fail synthesis; with `enforce: false` the rules are instead injected into the CDK built-in `CloudFormationValidatePlugin` and reported as warnings.\n\nConstraints that *can* be expressed in schemas or generic engine rules are contributed upstream instead of living here; each rule's `meta.yaml` tracks its upstream status, and rules retire once the engine covers them.\n\n## Requirements\n\n- `aws-cdk-lib` >= 2.267.0 (the first release that bundles the built-in CloudFormation validator)\n\n## Contributing\n\nRule authoring, the verification gates (including real-deploy reproduction), and the test layout are documented in [AGENTS.md](AGENTS.md) — written for AI coding agents and humans alike.\n\n## License\n\nApache-2.0\n"
|
|
9417
|
+
"markdown": "# cdk-preflight\n\n**Catch deploy-time CloudFormation failures at `cdk synth` time.**\n\nSome CloudFormation constraints are not expressed in resource provider schemas — they live only in documentation, in service API validation, or across multiple properties. Templates that violate them pass `cdk synth`, pass CloudFormation pre-deployment validation, and then fail minutes into a deployment, burning a rollback cycle.\n\ncdk-preflight is a curated [Rego rule pack](docs/rules.md) for exactly those constraints, evaluated with the CloudFormation validation engine that ships inside `aws-cdk-lib` (>= 2.267.0). By default a violation **fails `cdk synth`** — a template that is known to fail at deploy time never leaves your machine.\n\nEvery bundled rule is backed by a `fail`/`pass` template pair, and the failure has been reproduced against real AWS (or is explicitly marked `doc-only`). Rules that the built-in validation engine already covers are deliberately **not** duplicated — a test suite enforces this.\n\n## Quick start\n\n```bash\nnpm i -D cdk-preflight\nnpx cdk-preflight init # inserts Preflight.apply(app) into your CDK app\n```\n\nor add one line yourself:\n\n```ts\nimport { Preflight } from 'cdk-preflight';\n\nconst app = new App();\nPreflight.apply(app);\n```\n\nOn violation, `cdk synth` fails with one error per finding, including the construct trace:\n\n```text\nERROR idle_timeout.timeout_seconds is 5000 but must be between 1 and 4000 seconds (cdk-preflight)\n MyStack/Alb/Resource (Alb16C2F182) aws-cdk-lib.aws_elasticloadbalancingv2.CfnLoadBalancer\n\nSynthesis finished with errors\n```\n\n## Observe-only mode\n\nTo roll the rules out gradually, start with `enforce: false`: findings then surface as synth **warnings** through the CDK built-in validator, with construct traces and per-finding acknowledgement:\n\n```ts\nPreflight.apply(app, { enforce: false });\n```\n\n```text\nWARNING idle_timeout.timeout_seconds is 5000 but must be between 1 and 4000 seconds (CloudFormation Validate)\n MyStack/Alb (Alb) aws-cdk-lib.aws_elasticloadbalancingv2.CfnLoadBalancer\n Acknowledge with 'CloudFormation-Validate::pf-elbv2-lb-idle-timeout-range'\n```\n\n| Option | Default | Effect |\n|---|---|---|\n| `enforce` | `true` | Violations of bundled rules fail synthesis; set to `false` to only warn |\n| `strict` | `false` | With `enforce`: also fail on error-class findings (`ERROR`/`FATAL`, e.g. `F3034`) of the built-in validation engine itself, which the CDK currently downgrades to warnings |\n| `exclude` | `[]` | Rule ids to disable |\n| `includeUpstreamPending` | `true` | Include rules already proposed to the upstream engine but not yet merged |\n\nTo opt out of a single rule, pass its id in `exclude`. In observe-only mode, individual findings can also be suppressed with the CDK acknowledge mechanism shown in the warning text.\n\n## Bundled rules\n\nSee [docs/rules.md](docs/rules.md) for the generated rule table. Highlights:\n\n- **ELBv2**: `idle_timeout` / `deregistration_delay` / `slow_start` attribute ranges (stringly-typed Key/Value attributes are invisible to schema validation)\n- **IAM**: managed (6,144 chars) and inline (role/group/user) policy document size limits\n- **CloudFront**: `MinTTL <= DefaultTTL <= MaxTTL` ordering, ACM certificates must live in `us-east-1`\n- **Step Functions**: `Next`/`Default`/`Choices` must reference defined states (a dangling `StartAt` is already caught by the engine's built-in `E3601`)\n- **EC2**: security group TCP/UDP port ranges and `FromPort <= ToPort`\n\n## For AI agents\n\nTo add cdk-preflight to a CDK app:\n\n1. `npm i -D cdk-preflight`\n2. `npx cdk-preflight init` (finds the entry point via `cdk.json` and inserts `Preflight.apply(app)`; use `--dry-run` to preview)\n3. Run `cdk synth`. Violations fail the synth with a validation report; each finding carries a rule id, the actual value, and a suggested fix\n4. To fix a finding, prefer correcting the resource. To opt out instead: `exclude: ['<rule-id>']` disables one rule, `enforce: false` switches to warn-only reporting\n\nThe machine-readable findings are written to `cdk.out/validation-report.json` when synthesizing with `-c @aws-cdk/core:validationReportJson=true`.\n\n### Report missed deploy errors\n\ncdk-preflight only knows the failure modes it has benched. When a deploy fails on a constraint the pack should have caught, that report is how new rules get added — but at that moment cdk-preflight is out of the loop (it passed the synth), so the instruction has to already sit in your agent's context. Paste this into your repository's `AGENTS.md` (or `CLAUDE.md`):\n\n```markdown\n## cdk-preflight: report missed deploy errors\n\nIf `cdk deploy` fails even though `cdk synth` (with cdk-preflight enabled) passed,\nand the failure is a service-side validation rejection — CREATE_FAILED/UPDATE_FAILED\nwith a 400-class message such as \"Invalid request provided: ...\" — cdk-preflight is\nmissing a rule. Report it:\n\n1. Qualify first. NOT reportable: AccessDenied / permissions, service quotas,\n throttling, name conflicts with existing resources, stabilization timeouts.\n2. Redact account-specific data (account IDs -> 123456789012, real ARNs/domains\n -> placeholders).\n3. Search existing issues: https://github.com/badmintoncryer/cdk-preflight/issues\n4. With your user's approval, open a \"Missed deploy error\" issue with the verbatim\n error message, the resource type, a minimal template snippet, and your\n aws-cdk-lib / cdk-preflight versions.\n```\n\n## How it works\n\n`Preflight.apply()` evaluates the rules with the [cloudformation-validate](https://github.com/aws-cloudformation/cloudformation-validate) Rust/WASM engine that ships inside `aws-cdk-lib` — no extra binaries, no network access at synth time. In the default enforce mode the engine is invoked through a dedicated CDK validation plugin so that violations fail synthesis; with `enforce: false` the rules are instead injected into the CDK built-in `CloudFormationValidatePlugin` and reported as warnings.\n\nConstraints that *can* be expressed in schemas or generic engine rules are contributed upstream instead of living here; each rule's `meta.yaml` tracks its upstream status, and rules retire once the engine covers them.\n\n## Requirements\n\n- `aws-cdk-lib` >= 2.267.0 (the first release that bundles the built-in CloudFormation validator)\n\n## Contributing\n\nRule authoring, the verification gates (including real-deploy reproduction), and the test layout are documented in [AGENTS.md](AGENTS.md) — written for AI coding agents and humans alike.\n\n## License\n\nApache-2.0\n"
|
|
9418
9418
|
},
|
|
9419
9419
|
"repository": {
|
|
9420
9420
|
"type": "git",
|
|
@@ -9598,6 +9598,6 @@
|
|
|
9598
9598
|
"symbolId": "src/index:PreflightOptions"
|
|
9599
9599
|
}
|
|
9600
9600
|
},
|
|
9601
|
-
"version": "0.0.
|
|
9602
|
-
"fingerprint": "
|
|
9601
|
+
"version": "0.0.25",
|
|
9602
|
+
"fingerprint": "c+pg2nGhkrPvXDoLEwgEYyVevXiGTWv17L4vLavSHKQ="
|
|
9603
9603
|
}
|
package/AGENTS.md
CHANGED
|
@@ -109,3 +109,5 @@ bench/ # real-deploy verification (needs an AWS account; no
|
|
|
109
109
|
- The CDK renders `Acknowledge with 'cdk-preflight::<rule-id>'` under enforce-mode errors, but `Validations.acknowledge()` currently suppresses only annotation warnings (`validations.ts`: "Currently only annotation warnings can be suppressed") — the hint is inert for policy violations. The working opt-outs in enforce mode are `exclude` and `enforce: false`; do not document the acknowledge mechanism for enforce mode.
|
|
110
110
|
- **`net.cidr_*` builtins do not exist** in the engine's Rego build ("could not find func", measured 2026-09-03 on `net.cidr_contains` / `net.cidr_intersects` / `net.cidr_is_valid`). CIDR math must be hand-rolled: `split`, `to_number`, a 33-entry power-of-two table, and `floor` (which does exist). The gap matters less than it looks: the engine already ships cross-resource CIDR checks — subnet-not-within-VPC is `E3059` and sibling-subnet overlap is `E3060` (both fire on `Ref`-wired resources in one template).
|
|
111
111
|
- The engine validates instance/node types **against the deploy region** when one is supplied via `validateDetailed(tpl, { pseudoParameterOverrides: { region } })` — `E3628` ('trn1.32xlarge' is not valid for region 'ap-northeast-1'), measured 2026-09-03. Without a region it validates against the union of all regions and emits `I9003`. The enforce plugin passes the region whenever the app's env is concrete, so region-availability rules for instance types belong to the engine, not this pack.
|
|
112
|
+
- **`json.unmarshal` and `json.is_valid` exist** (measured 2026-09-03, 1.7.0-beta). Opaque JSON-in-a-string properties (CloudWatch `DashboardBody`) can be parsed and validated structurally in Rego — this is the lens-2 workhorse. Reference implementations: `pf-cloudwatch-dashboard-*`.
|
|
113
|
+
- **Probing the raw engine with custom rules**: the rule set must be named `violation` (`data.<pkg>.violation` is looked up; a `diagnostics` set fails with "not a valid rule path"), and hand-built diagnostic objects need lowercase severities (`error`, not `ERROR`/`CUSTOM` — those are display labels added by the wrapper). Pack rules never see this because `make_diag_full` handles the shape.
|
package/README.md
CHANGED
|
@@ -77,6 +77,28 @@ To add cdk-preflight to a CDK app:
|
|
|
77
77
|
|
|
78
78
|
The machine-readable findings are written to `cdk.out/validation-report.json` when synthesizing with `-c @aws-cdk/core:validationReportJson=true`.
|
|
79
79
|
|
|
80
|
+
### Report missed deploy errors
|
|
81
|
+
|
|
82
|
+
cdk-preflight only knows the failure modes it has benched. When a deploy fails on a constraint the pack should have caught, that report is how new rules get added — but at that moment cdk-preflight is out of the loop (it passed the synth), so the instruction has to already sit in your agent's context. Paste this into your repository's `AGENTS.md` (or `CLAUDE.md`):
|
|
83
|
+
|
|
84
|
+
```markdown
|
|
85
|
+
## cdk-preflight: report missed deploy errors
|
|
86
|
+
|
|
87
|
+
If `cdk deploy` fails even though `cdk synth` (with cdk-preflight enabled) passed,
|
|
88
|
+
and the failure is a service-side validation rejection — CREATE_FAILED/UPDATE_FAILED
|
|
89
|
+
with a 400-class message such as "Invalid request provided: ..." — cdk-preflight is
|
|
90
|
+
missing a rule. Report it:
|
|
91
|
+
|
|
92
|
+
1. Qualify first. NOT reportable: AccessDenied / permissions, service quotas,
|
|
93
|
+
throttling, name conflicts with existing resources, stabilization timeouts.
|
|
94
|
+
2. Redact account-specific data (account IDs -> 123456789012, real ARNs/domains
|
|
95
|
+
-> placeholders).
|
|
96
|
+
3. Search existing issues: https://github.com/badmintoncryer/cdk-preflight/issues
|
|
97
|
+
4. With your user's approval, open a "Missed deploy error" issue with the verbatim
|
|
98
|
+
error message, the resource type, a minimal template snippet, and your
|
|
99
|
+
aws-cdk-lib / cdk-preflight versions.
|
|
100
|
+
```
|
|
101
|
+
|
|
80
102
|
## How it works
|
|
81
103
|
|
|
82
104
|
`Preflight.apply()` evaluates the rules with the [cloudformation-validate](https://github.com/aws-cloudformation/cloudformation-validate) Rust/WASM engine that ships inside `aws-cdk-lib` — no extra binaries, no network access at synth time. In the default enforce mode the engine is invoked through a dedicated CDK validation plugin so that violations fail synthesis; with `enforce: false` the rules are instead injected into the CDK built-in `CloudFormationValidatePlugin` and reported as warnings.
|
package/docs/rules.md
CHANGED
|
@@ -52,10 +52,16 @@
|
|
|
52
52
|
| `pf-cloudwatch-alarm-period` | AWS::CloudWatch::Alarm | Period must be 10, 20, 30 or a multiple of 60 | none |
|
|
53
53
|
| `pf-cloudwatch-alarm-threshold` | AWS::CloudWatch::Alarm | Standard operators need Threshold, range operators need ThresholdMetricId | none |
|
|
54
54
|
| `pf-cloudwatch-composite-alarm-rule-syntax` | AWS::CloudWatch::CompositeAlarm | An AlarmRule must start with a valid expression token | none |
|
|
55
|
+
| `pf-cloudwatch-dashboard-body-json` | AWS::CloudWatch::Dashboard | DashboardBody must be valid JSON | none |
|
|
56
|
+
| `pf-cloudwatch-dashboard-name` | AWS::CloudWatch::Dashboard | Dashboard names allow only alphanumerics, dash and underscore | none |
|
|
57
|
+
| `pf-cloudwatch-dashboard-widget-fields` | AWS::CloudWatch::Dashboard | Every dashboard widget requires type and properties | none |
|
|
58
|
+
| `pf-cloudwatch-dashboard-widget-position` | AWS::CloudWatch::Dashboard | Dashboard widget x tops out at 23 and width at 24 | none |
|
|
59
|
+
| `pf-cloudwatch-dashboard-widgets` | AWS::CloudWatch::Dashboard | DashboardBody requires a widgets array | none |
|
|
55
60
|
| `pf-cloudwatch-datapoints-evaluation` | AWS::CloudWatch::Alarm | DatapointsToAlarm must not exceed EvaluationPeriods | none |
|
|
56
61
|
| `pf-cloudwatch-extended-statistic` | AWS::CloudWatch::Alarm | A percentile statistic cannot exceed p100 | none |
|
|
57
62
|
| `pf-cloudwatch-metric-query-exclusive` | AWS::CloudWatch::Alarm | Expression and MetricStat are mutually exclusive per query | none |
|
|
58
63
|
| `pf-cloudwatch-metric-query-returndata` | AWS::CloudWatch::Alarm | Exactly one metric query must return data | none |
|
|
64
|
+
| `pf-cloudwatch-threshold-metric-id` | AWS::CloudWatch::Alarm | ThresholdMetricId must match a metric query that returns data | none |
|
|
59
65
|
| `pf-cognito-alias-username-exclusive` | AWS::Cognito::UserPool | AliasAttributes and UsernameAttributes are mutually exclusive | none |
|
|
60
66
|
| `pf-cognito-client-credentials-exclusive` | AWS::Cognito::UserPoolClient | client_credentials cannot combine with code or implicit | none |
|
|
61
67
|
| `pf-cognito-client-credentials-secret` | AWS::Cognito::UserPoolClient | client_credentials needs a client secret | none |
|
|
@@ -106,6 +112,14 @@
|
|
|
106
112
|
| `pf-ecs-essential-container` | AWS::ECS::TaskDefinition | At least one container must be essential | none |
|
|
107
113
|
| `pf-ecs-fargate-network-mode` | AWS::ECS::TaskDefinition | Fargate task definitions require NetworkMode 'awsvpc' | none |
|
|
108
114
|
| `pf-ecs-fargate-task-cpu-memory` | AWS::ECS::TaskDefinition | FARGATE compatibility requires task-level Cpu and Memory | none |
|
|
115
|
+
| `pf-ecs-service-codedeploy-lb` | AWS::ECS::Service | CODE_DEPLOY deployment controller requires a load balancer | none |
|
|
116
|
+
| `pf-ecs-service-daemon-desired-count` | AWS::ECS::Service | DAEMON scheduling strategy does not accept DesiredCount | none |
|
|
117
|
+
| `pf-ecs-service-deployment-percent` | AWS::ECS::Service | DeploymentConfiguration percent bounds (min <= 100, max >= 100) | none |
|
|
118
|
+
| `pf-ecs-service-fargate-placement` | AWS::ECS::Service | Placement constraints and strategies are not supported on FARGATE | none |
|
|
119
|
+
| `pf-ecs-service-launch-type-capacity-provider` | AWS::ECS::Service | LaunchType and CapacityProviderStrategy are mutually exclusive | none |
|
|
120
|
+
| `pf-ecs-service-lb-target-exclusive` | AWS::ECS::Service | A load balancer entry takes either TargetGroupArn or LoadBalancerName, not both | none |
|
|
121
|
+
| `pf-ecs-service-network-config-mode` | AWS::ECS::Service<br>AWS::ECS::TaskDefinition | NetworkConfiguration requires an awsvpc task definition | none |
|
|
122
|
+
| `pf-ecs-service-platform-version-ec2` | AWS::ECS::Service | PlatformVersion is not allowed with the EC2 launch type | none |
|
|
109
123
|
| `pf-elbv2-alb-subnet-count` | AWS::ElasticLoadBalancingV2::LoadBalancer | Application load balancers need at least two subnets | none |
|
|
110
124
|
| `pf-elbv2-app-cookie-name` | AWS::ElasticLoadBalancingV2::TargetGroup | app_cookie stickiness requires a cookie name | none |
|
|
111
125
|
| `pf-elbv2-hc-timeout-interval` | AWS::ElasticLoadBalancingV2::TargetGroup | Health check timeout must be strictly smaller than the interval | none |
|
package/lib/index.js
CHANGED
|
@@ -17,7 +17,7 @@ const rules_generated_1 = require("./rules.generated");
|
|
|
17
17
|
* Preflight.apply(app);
|
|
18
18
|
*/
|
|
19
19
|
class Preflight {
|
|
20
|
-
static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-preflight.Preflight", version: "0.0.
|
|
20
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-preflight.Preflight", version: "0.0.25" };
|
|
21
21
|
/**
|
|
22
22
|
* Register the cdk-preflight rules on an App or Stage.
|
|
23
23
|
*/
|