cdk-preflight 0.0.123 → 0.0.125

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 CHANGED
@@ -9416,7 +9416,7 @@
9416
9416
  },
9417
9417
  "name": "cdk-preflight",
9418
9418
  "readme": {
9419
- "markdown": "<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/badmintoncryer/cdk-preflight/main/assets/logo.png\" alt=\"cdk-preflight\" width=\"104\" height=\"104\">\n</p>\n\n<h1 align=\"center\">cdk-preflight</h1>\n\n<p align=\"center\">\n <strong>Catch deploy-time CloudFormation failures at <code>cdk synth</code> time.</strong>\n</p>\n\n<p align=\"center\">\n <a href=\"https://github.com/badmintoncryer/cdk-preflight/actions/workflows/monthly-verify.yml\"><img src=\"https://github.com/badmintoncryer/cdk-preflight/actions/workflows/monthly-verify.yml/badge.svg\" alt=\"monthly real-deploy verification\"></a>\n <a href=\"https://www.npmjs.com/package/cdk-preflight\"><img src=\"https://img.shields.io/npm/v/cdk-preflight.svg\" alt=\"npm version\"></a>\n <a href=\"https://www.npmjs.com/package/cdk-preflight\"><img src=\"https://img.shields.io/npm/dt/cdk-preflight.svg\" alt=\"npm total downloads\"></a>\n <a href=\"docs/rules.md\"><img src=\"https://img.shields.io/badge/rules-2266-blue\" alt=\"2266 bundled rules\"></a>\n</p>\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\nThe pack aims at **every deploy-time failure that no existing CDK mechanism already catches** — nothing narrower. Every bundled rule is backed by a `fail`/`pass` template pair, and the failure has been reproduced against real AWS. The handful of rules that could not be reproduced are marked `doc-only` and report as **warnings**: they show up in the validation report but never fail synth. Rules that the built-in validation engine already covers are deliberately **not** duplicated — a test suite enforces this.\n\n> **Requires `aws-cdk-lib` >= 2.267.0** (released 2026-08-27) — the first release that bundles\n> the CloudFormation validation engine. On older versions the rules cannot run at all.\n\n## Quick start\n\n```bash\nnpm i -D cdk-preflight\nnpx cdkpf init # inserts Preflight.apply(app) into your CDK app\n # (`npx cdkpf init` is the same command, shorter)\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## What it catches\n\nFour ordinary-looking snippets. All of them pass `cdk synth` and CloudFormation\npre-deployment validation, and all of them fail minutes into a deployment:\n\n```ts\n// 1) pf-iam-inline-policy-size — enumerate buckets, grant each one, blow past 10,240 chars\n// \"Maximum policy size of 10240 bytes exceeded for role IngestRole\"\n// (via role.addToPolicy the CDK auto-splits into managed policies instead,\n// and you hit the 6,144-char limit as pf-iam-managed-policy-size)\nnew iam.Policy(this, 'IngestPolicy', {\n roles: [role],\n statements: [new iam.PolicyStatement({\n actions: ['s3:GetObject', 's3:ListBucket'],\n resources: Array.from({ length: 200 },\n (_, i) => `arn:aws:s3:::data-lake-landing-zone-${i}/year=*/month=*/*`),\n })],\n});\n\n// 2) pf-lambda-env-size — a config blob in the environment, over the 4KB total\n// \"Lambda was unable to configure your environment variables because the\n// environment variables you have provided exceeded the 4KB limit\"\nnew lambda.Function(this, 'Fn', {\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'index.handler',\n code: lambda.Code.fromInline('exports.handler = async () => {};'),\n environment: { FEATURE_FLAGS: JSON.stringify(bigFeatureFlagMap) },\n});\n\n// 3) pf-sfn-asl-missing-state (+ pf-sfn-asl-unreachable-state) — a typo in a state name\n// \"Invalid State Machine Definition: 'MISSING_TRANSITION_TARGET: ...'\"\nnew sfn.StateMachine(this, 'Pipeline', {\n definitionBody: sfn.DefinitionBody.fromString(JSON.stringify({\n StartAt: 'Validate',\n States: {\n Validate: { Type: 'Pass', Next: 'Transform' },\n Trasform: { Type: 'Pass', End: true }, // typo: Transform\n },\n })),\n});\n\n// 4) pf-logs-filter-pattern-bracket — a filter pattern opened with '[' and never closed\n// \"If a filter pattern starts with '[' it must end with ']'\"\nnew logs.MetricFilter(this, 'ErrorFilter', {\n logGroup,\n metricNamespace: 'Pipeline',\n metricName: 'Errors',\n filterPattern: logs.FilterPattern.literal('[time, level=ERROR, msg'),\n});\n```\n\nNone of these are type errors, so the L2 constructs accept them; none of them are\nexpressible in a resource schema, so CloudFormation accepts the template. With\n`Preflight.apply(app)` in place they fail `cdk synth` instead.\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> **Known limitation with stages.** The AWS CDK CLI drops validation findings for stacks nested in a `Stage`\n> before printing them, so in observe-only mode those findings appear **only** in `cdk.out/validation-report.json`\n> and never on the console. Enforce mode is not affected: cdk-preflight reports such findings itself and fails\n> synthesis. This is a CLI-side bug (present since aws-cdk 2.1128.1), not a rule evaluation problem.\n\n> **If the rules cannot run, the build stops.** When the evaluation engine fails on a template (a rule pack that\n> does not compile, an engine bug), enforce mode reports it as a violation named `pf-engine-error` and fails\n> synthesis for that stack instead of passing green with no rule having run. The other stacks keep their rules.\n> `pf-engine-error` is not a bundled rule and cannot be `exclude`d; `enforce: false` unblocks the build if you\n> need one.\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 everywhere, pass its id in `exclude`. To suppress a\nsingle *finding* on one construct, acknowledge it — this works in both modes, the\nid prefix just differs (`cdk-preflight::` when enforcing, `CloudFormation-Validate::`\nin observe-only, as printed in the warning text):\n\n```ts\ncdk.Validations.of(errorFilter).acknowledge({\n id: 'cdk-preflight::pf-logs-filter-pattern-bracket',\n reason: 'log group is written by a legacy producer; pattern is fixed upstream',\n});\n```\n\n## Bundled rules\n\nSee [docs/rules.md](docs/rules.md) for the generated rule table.\n\n<!-- supported-resources:start -->\n<details>\n<summary><b>290 resource types across 44 services</b> — click to expand</summary>\n\nResource names are relative to `AWS::<Service>::`; the number in parentheses is how many rules target that type.\n\n| Service | Resource types |\n|---|---|\n| **(any resource type)** | `*` (2) |\n| **ApiGateway** | `ApiKey` (1), `Authorizer` (5), `Deployment` (1), `DocumentationPart` (1), `DomainName` (4), `GatewayResponse` (1), `Method` (12), `Model` (3), `Resource` (1), `RestApi` (4), `Stage` (9), `UsagePlan` (5), `VpcLink` (1) |\n| **ApiGatewayV2** | `Api` (5), `Authorizer` (11), `DomainName` (3), `Integration` (15), `IntegrationResponse` (1), `Model` (2), `Route` (6), `RouteResponse` (2), `Stage` (4), `VpcLink` (1) |\n| **AppSync** | `Api` (7), `ApiCache` (4), `ApiKey` (2), `ChannelNamespace` (5), `DataSource` (15), `DomainName` (1), `FunctionConfiguration` (24), `GraphQLApi` (16), `GraphQLSchema` (12), `Resolver` (32), `SourceApiAssociation` (3) |\n| **Athena** | `DataCatalog` (6), `WorkGroup` (8) |\n| **AutoScaling** | `AutoScalingGroup` (38), `LifecycleHook` (8), `ScalingPolicy` (41), `ScheduledAction` (13), `WarmPool` (4) |\n| **Batch** | `ComputeEnvironment` (40), `ConsumableResource` (2), `JobDefinition` (109), `JobQueue` (18), `SchedulingPolicy` (8), `ServiceEnvironment` (6) |\n| **Bedrock** | `ApplicationInferenceProfile` (2), `AutomatedReasoningPolicy` (3), `Blueprint` (3), `DataAutomationProject` (8), `DataSource` (12), `Flow` (14), `Guardrail` (19), `IntelligentPromptRouter` (5), `KnowledgeBase` (18), `Prompt` (4) |\n| **BedrockAgentCore** | `ApiKeyCredentialProvider` (1), `BrowserCustom` (1), `CodeInterpreterCustom` (1), `ConfigurationBundle` (3), `Dataset` (3), `Evaluator` (4), `Gateway` (5), `GatewayRule` (3), `GatewayTarget` (9), `Harness` (2), `HarnessEndpoint` (2), `Memory` (6), `OAuth2CredentialProvider` (3), `OnlineEvaluationConfig` (3), `PaymentCredentialProvider` (1), `PaymentManager` (1), `Policy` (3), `ResourcePolicy` (1), `Runtime` (8), `RuntimeEndpoint` (1) |\n| **CloudFront** | `AnycastIpList` (1), `CachePolicy` (7), `ContinuousDeploymentPolicy` (5), `Distribution` (55), `Function` (4), `KeyGroup` (1), `KeyValueStore` (2), `OriginRequestPolicy` (5), `PublicKey` (1), `RealtimeLogConfig` (3), `ResponseHeadersPolicy` (8), `VpcOrigin` (3) |\n| **CloudWatch** | `Alarm` (21), `AnomalyDetector` (6), `CompositeAlarm` (6), `Dashboard` (14), `InsightRule` (7), `MetricStream` (6) |\n| **Cognito** | `IdentityPool` (3), `IdentityPoolRoleAttachment` (7), `LogDeliveryConfiguration` (3), `ManagedLoginBranding` (2), `UserPool` (52), `UserPoolClient` (21), `UserPoolDomain` (7), `UserPoolGroup` (1), `UserPoolIdentityProvider` (11), `UserPoolResourceServer` (4), `UserPoolRiskConfigurationAttachment` (6), `UserPoolUICustomizationAttachment` (2) |\n| **DynamoDB** | `GlobalTable` (26), `Table` (28) |\n| **EC2** | `ClientVpnAuthorizationRule` (1), `ClientVpnEndpoint` (6), `DHCPOptions` (2), `EIPAssociation` (1), `FlowLog` (4), `Instance` (10), `KeyPair` (1), `LaunchTemplate` (5), `NatGateway` (2), `NetworkAclEntry` (1), `NetworkInterface` (2), `PlacementGroup` (3), `PrefixList` (3), `Route` (1), `SecurityGroup` (6), `SecurityGroupEgress` (5), `SecurityGroupIngress` (5), `Subnet` (6), `TrafficMirrorTarget` (1), `TransitGateway` (2), `TransitGatewayRoute` (1), `Volume` (6), `VPC` (2), `VPCCidrBlock` (1), `VPCEndpoint` (4), `VPCGatewayAttachment` (1), `VPNConnection` (5) |\n| **ECR** | `PullThroughCacheRule` (3), `RegistryScanningConfiguration` (1), `ReplicationConfiguration` (1), `Repository` (7), `RepositoryCreationTemplate` (8), `SigningConfiguration` (1) |\n| **ECS** | `CapacityProvider` (3), `Cluster` (5), `Service` (37), `TaskDefinition` (64), `TaskSet` (2) |\n| **EFS** | `AccessPoint` (1), `FileSystem` (7), `MountTarget` (4) |\n| **ElastiCache** | `CacheCluster` (9), `ReplicationGroup` (14), `User` (2), `UserGroup` (1) |\n| **ElasticLoadBalancingV2** | `Listener` (57), `ListenerCertificate` (2), `ListenerRule` (37), `LoadBalancer` (37), `TargetGroup` (58), `TrustStore` (1), `TrustStoreRevocation` (1) |\n| **Events** | `ApiDestination` (1), `Archive` (5), `Connection` (1), `Endpoint` (2), `EventBus` (2), `Rule` (23) |\n| **EventSchemas** | `Discoverer` (1), `Registry` (1), `RegistryPolicy` (1), `Schema` (1) |\n| **Glue** | `Classifier` (6), `Connection` (5), `Crawler` (11), `CustomEntityType` (1), `Database` (1), `DataQualityRuleset` (1), `Job` (15), `MLTransform` (4), `Partition` (1), `Schema` (3), `SecurityConfiguration` (1), `Table` (1), `Trigger` (10), `UserDefinedFunction` (2), `Workflow` (1) |\n| **IAM** | `Group` (23), `GroupPolicy` (1), `InstanceProfile` (2), `ManagedPolicy` (31), `OIDCProvider` (2), `Policy` (29), `Role` (40), `RolePolicy` (1), `ServiceLinkedRole` (1), `User` (24), `UserPolicy` (1) |\n| **Kinesis** | `ResourcePolicy` (4), `Stream` (5), `StreamConsumer` (2) |\n| **KinesisAnalyticsV2** | `Application` (20), `ApplicationCloudWatchLoggingOption` (1), `ApplicationOutput` (1), `ApplicationReferenceDataSource` (1) |\n| **KinesisFirehose** | `DeliveryStream` (68) |\n| **KMS** | `Alias` (2), `Key` (12), `ReplicaKey` (4) |\n| **Lambda** | `Alias` (7), `CodeSigningConfig` (1), `EventInvokeConfig` (5), `EventSourceMapping` (54), `Function` (46), `LayerVersion` (8), `LayerVersionPermission` (3), `Permission` (8), `Url` (8), `Version` (1) |\n| **Logs** | `AccountPolicy` (6), `DeliveryDestination` (3), `Destination` (1), `LogAnomalyDetector` (2), `LogGroup` (10), `MetricFilter` (7), `QueryDefinition` (1), `ResourcePolicy` (1), `SubscriptionFilter` (6), `Transformer` (3) |\n| **MemoryDB** | `Cluster` (8), `User` (1) |\n| **Pipes** | `Pipe` (9) |\n| **RDS** | `DBCluster` (19), `DBInstance` (33), `DBParameterGroup` (2), `DBProxy` (4), `DBProxyTargetGroup` (2), `DBShardGroup` (1), `DBSubnetGroup` (3), `EventSubscription` (3), `OptionGroup` (1) |\n| **Route53** | `CidrCollection` (11), `DNSSEC` (3), `HealthCheck` (30), `HostedZone` (14), `KeySigningKey` (9), `RecordSet` (75), `RecordSetGroup` (76) |\n| **Route53Profiles** | `ProfileAssociation` (1), `ProfileResourceAssociation` (6) |\n| **Route53Resolver** | `FirewallDomainList` (3), `FirewallRuleGroup` (18), `FirewallRuleGroupAssociation` (4), `ResolverDNSSECConfig` (1), `ResolverEndpoint` (18), `ResolverQueryLoggingConfig` (1), `ResolverQueryLoggingConfigAssociation` (1), `ResolverRule` (15), `ResolverRuleAssociation` (1) |\n| **S3** | `AccessPoint` (1), `Bucket` (54), `BucketPolicy` (4), `StorageLens` (5), `StorageLensGroup` (3) |\n| **S3Express** | `AccessPoint` (3), `DirectoryBucket` (11) |\n| **Scheduler** | `Schedule` (10), `ScheduleGroup` (1) |\n| **SecretsManager** | `RotationSchedule` (4), `Secret` (5), `SecretTargetAttachment` (1) |\n| **SNS** | `Subscription` (9), `Topic` (12), `TopicPolicy` (1) |\n| **SQS** | `Queue` (9), `QueuePolicy` (1) |\n| **SSM** | `Association` (3), `Document` (3), `MaintenanceWindow` (2), `MaintenanceWindowTarget` (1), `MaintenanceWindowTask` (1), `Parameter` (5) |\n| **StepFunctions** | `Activity` (3), `StateMachine` (26) |\n| **WAFv2** | `IPSet` (3), `LoggingConfiguration` (3), `RegexPatternSet` (3), `RuleGroup` (18), `WebACL` (23), `WebACLAssociation` (2) |\n\n</details>\n<!-- supported-resources:end -->\n\nHighlights:\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` — or the shorter alias `npx cdkpf 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## Scope and rule lifecycle\n\nA constraint belongs in the pack when violating it makes a real deployment fail *and* no layer that sees the same synthesized template already blocks it. There is no further \"is this worth a rule\" question — if the gap is real, it gets a rule.\n\nCDK L2 construct validation is deliberately **not** one of those layers. `CfnXxx` usage, escape hatches, `addPropertyOverride`, `cloudformation-include` and migrated templates all bypass L2, so an L2 guard covering the same mistake neither disqualifies a rule nor retires one.\n\nThat makes growth the normal state, and it has a consequence worth knowing before you upgrade: **new rules land in minor releases, so a minor upgrade can newly fail a `cdk synth` that passed yesterday.** That is intended, not a regression. If you need a frozen rule set, pin the version; to drop a single rule, `exclude: ['<rule-id>']`; to see everything without failing the build, `enforce: false`.\n\nRules move the other way too. Once the validation engine bundled in `aws-cdk-lib` (or CloudFormation's own pre-deploy validation) starts blocking a constraint, the rule is deleted rather than kept as a duplicate — staying on an older `aws-cdk-lib` and an older cdk-preflight keeps the old behavior.\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 also make good upstream PRs to that engine, but nothing here waits on one — the upstream release cycle is deliberately slower than this pack's. Each rule's `meta.yaml` tracks its upstream status so that retirement stays bookkeeping.\n\n## Requirements\n\n- `aws-cdk-lib` >= 2.267.0, released 2026-08-27 (the first release that bundles the built-in CloudFormation validator). This is a recent release — an existing CDK app may need an upgrade before cdk-preflight can run.\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"
9419
+ "markdown": "<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/badmintoncryer/cdk-preflight/main/assets/logo.png\" alt=\"cdk-preflight\" width=\"104\" height=\"104\">\n</p>\n\n<h1 align=\"center\">cdk-preflight</h1>\n\n<p align=\"center\">\n <strong>Catch deploy-time CloudFormation failures at <code>cdk synth</code> time.</strong>\n</p>\n\n<p align=\"center\">\n <a href=\"https://github.com/badmintoncryer/cdk-preflight/actions/workflows/monthly-verify.yml\"><img src=\"https://github.com/badmintoncryer/cdk-preflight/actions/workflows/monthly-verify.yml/badge.svg\" alt=\"monthly real-deploy verification\"></a>\n <a href=\"https://www.npmjs.com/package/cdk-preflight\"><img src=\"https://img.shields.io/npm/v/cdk-preflight.svg\" alt=\"npm version\"></a>\n <a href=\"https://www.npmjs.com/package/cdk-preflight\"><img src=\"https://img.shields.io/npm/dt/cdk-preflight.svg\" alt=\"npm total downloads\"></a>\n <a href=\"docs/rules.md\"><img src=\"https://img.shields.io/badge/rules-2437-blue\" alt=\"2437 bundled rules\"></a>\n</p>\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\nThe pack aims at **every deploy-time failure that no existing CDK mechanism already catches** — nothing narrower. Every bundled rule is backed by a `fail`/`pass` template pair, and the failure has been reproduced against real AWS. The handful of rules that could not be reproduced are marked `doc-only` and report as **warnings**: they show up in the validation report but never fail synth. Rules that the built-in validation engine already covers are deliberately **not** duplicated — a test suite enforces this.\n\n> **Requires `aws-cdk-lib` >= 2.267.0** (released 2026-08-27) — the first release that bundles\n> the CloudFormation validation engine. On older versions the rules cannot run at all.\n\n## Quick start\n\n```bash\nnpm i -D cdk-preflight\nnpx cdkpf init # inserts Preflight.apply(app) into your CDK app\n # (`npx cdkpf init` is the same command, shorter)\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## What it catches\n\nFour ordinary-looking snippets. All of them pass `cdk synth` and CloudFormation\npre-deployment validation, and all of them fail minutes into a deployment:\n\n```ts\n// 1) pf-iam-inline-policy-size — enumerate buckets, grant each one, blow past 10,240 chars\n// \"Maximum policy size of 10240 bytes exceeded for role IngestRole\"\n// (via role.addToPolicy the CDK auto-splits into managed policies instead,\n// and you hit the 6,144-char limit as pf-iam-managed-policy-size)\nnew iam.Policy(this, 'IngestPolicy', {\n roles: [role],\n statements: [new iam.PolicyStatement({\n actions: ['s3:GetObject', 's3:ListBucket'],\n resources: Array.from({ length: 200 },\n (_, i) => `arn:aws:s3:::data-lake-landing-zone-${i}/year=*/month=*/*`),\n })],\n});\n\n// 2) pf-lambda-env-size — a config blob in the environment, over the 4KB total\n// \"Lambda was unable to configure your environment variables because the\n// environment variables you have provided exceeded the 4KB limit\"\nnew lambda.Function(this, 'Fn', {\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'index.handler',\n code: lambda.Code.fromInline('exports.handler = async () => {};'),\n environment: { FEATURE_FLAGS: JSON.stringify(bigFeatureFlagMap) },\n});\n\n// 3) pf-sfn-asl-missing-state (+ pf-sfn-asl-unreachable-state) — a typo in a state name\n// \"Invalid State Machine Definition: 'MISSING_TRANSITION_TARGET: ...'\"\nnew sfn.StateMachine(this, 'Pipeline', {\n definitionBody: sfn.DefinitionBody.fromString(JSON.stringify({\n StartAt: 'Validate',\n States: {\n Validate: { Type: 'Pass', Next: 'Transform' },\n Trasform: { Type: 'Pass', End: true }, // typo: Transform\n },\n })),\n});\n\n// 4) pf-logs-filter-pattern-bracket — a filter pattern opened with '[' and never closed\n// \"If a filter pattern starts with '[' it must end with ']'\"\nnew logs.MetricFilter(this, 'ErrorFilter', {\n logGroup,\n metricNamespace: 'Pipeline',\n metricName: 'Errors',\n filterPattern: logs.FilterPattern.literal('[time, level=ERROR, msg'),\n});\n```\n\nNone of these are type errors, so the L2 constructs accept them; none of them are\nexpressible in a resource schema, so CloudFormation accepts the template. With\n`Preflight.apply(app)` in place they fail `cdk synth` instead.\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> **Known limitation with stages.** The AWS CDK CLI drops validation findings for stacks nested in a `Stage`\n> before printing them, so in observe-only mode those findings appear **only** in `cdk.out/validation-report.json`\n> and never on the console. Enforce mode is not affected: cdk-preflight reports such findings itself and fails\n> synthesis. This is a CLI-side bug (present since aws-cdk 2.1128.1), not a rule evaluation problem.\n\n> **If the rules cannot run, the build stops.** When the evaluation engine fails on a template (a rule pack that\n> does not compile, an engine bug), enforce mode reports it as a violation named `pf-engine-error` and fails\n> synthesis for that stack instead of passing green with no rule having run. The other stacks keep their rules.\n> `pf-engine-error` is not a bundled rule and cannot be `exclude`d; `enforce: false` unblocks the build if you\n> need one.\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 everywhere, pass its id in `exclude`. To suppress a\nsingle *finding* on one construct, acknowledge it — this works in both modes, the\nid prefix just differs (`cdk-preflight::` when enforcing, `CloudFormation-Validate::`\nin observe-only, as printed in the warning text):\n\n```ts\ncdk.Validations.of(errorFilter).acknowledge({\n id: 'cdk-preflight::pf-logs-filter-pattern-bracket',\n reason: 'log group is written by a legacy producer; pattern is fixed upstream',\n});\n```\n\n## Bundled rules\n\nSee [docs/rules.md](docs/rules.md) for the generated rule table.\n\n<!-- supported-resources:start -->\n<details>\n<summary><b>306 resource types across 49 services</b> — click to expand</summary>\n\nResource names are relative to `AWS::<Service>::`; the number in parentheses is how many rules target that type.\n\n| Service | Resource types |\n|---|---|\n| **(any resource type)** | `*` (2) |\n| **ApiGateway** | `ApiKey` (1), `Authorizer` (5), `Deployment` (1), `DocumentationPart` (1), `DomainName` (4), `GatewayResponse` (1), `Method` (12), `Model` (3), `Resource` (1), `RestApi` (4), `Stage` (9), `UsagePlan` (5), `VpcLink` (1) |\n| **ApiGatewayV2** | `Api` (5), `Authorizer` (11), `DomainName` (3), `Integration` (15), `IntegrationResponse` (1), `Model` (2), `Route` (6), `RouteResponse` (2), `Stage` (4), `VpcLink` (1) |\n| **AppSync** | `Api` (7), `ApiCache` (4), `ApiKey` (2), `ChannelNamespace` (5), `DataSource` (15), `DomainName` (1), `FunctionConfiguration` (24), `GraphQLApi` (16), `GraphQLSchema` (12), `Resolver` (32), `SourceApiAssociation` (3) |\n| **Athena** | `DataCatalog` (6), `WorkGroup` (8) |\n| **AutoScaling** | `AutoScalingGroup` (38), `LifecycleHook` (8), `ScalingPolicy` (41), `ScheduledAction` (13), `WarmPool` (4) |\n| **Batch** | `ComputeEnvironment` (40), `ConsumableResource` (2), `JobDefinition` (109), `JobQueue` (18), `SchedulingPolicy` (8), `ServiceEnvironment` (6) |\n| **Bedrock** | `ApplicationInferenceProfile` (2), `AutomatedReasoningPolicy` (3), `Blueprint` (3), `DataAutomationProject` (8), `DataSource` (12), `Flow` (14), `Guardrail` (19), `IntelligentPromptRouter` (5), `KnowledgeBase` (18), `Prompt` (4) |\n| **BedrockAgentCore** | `ApiKeyCredentialProvider` (1), `BrowserCustom` (1), `CodeInterpreterCustom` (1), `ConfigurationBundle` (3), `Dataset` (3), `Evaluator` (4), `Gateway` (5), `GatewayRule` (3), `GatewayTarget` (9), `Harness` (2), `HarnessEndpoint` (2), `Memory` (6), `OAuth2CredentialProvider` (3), `OnlineEvaluationConfig` (3), `PaymentCredentialProvider` (1), `PaymentManager` (1), `Policy` (3), `ResourcePolicy` (1), `Runtime` (8), `RuntimeEndpoint` (1) |\n| **CloudFront** | `AnycastIpList` (1), `CachePolicy` (7), `ContinuousDeploymentPolicy` (5), `Distribution` (55), `Function` (4), `KeyGroup` (1), `KeyValueStore` (2), `OriginRequestPolicy` (5), `PublicKey` (1), `RealtimeLogConfig` (3), `ResponseHeadersPolicy` (8), `VpcOrigin` (3) |\n| **CloudWatch** | `Alarm` (21), `AnomalyDetector` (6), `CompositeAlarm` (6), `Dashboard` (14), `InsightRule` (7), `MetricStream` (6) |\n| **CodeBuild** | `Project` (37), `ReportGroup` (2), `SourceCredential` (4) |\n| **CodeCommit** | `Repository` (11) |\n| **CodeDeploy** | `Application` (7), `DeploymentConfig` (12), `DeploymentGroup` (23) |\n| **CodePipeline** | `CustomActionType` (3), `Pipeline` (25), `Webhook` (2) |\n| **Cognito** | `IdentityPool` (3), `IdentityPoolRoleAttachment` (7), `LogDeliveryConfiguration` (3), `ManagedLoginBranding` (2), `UserPool` (52), `UserPoolClient` (21), `UserPoolDomain` (7), `UserPoolGroup` (1), `UserPoolIdentityProvider` (11), `UserPoolResourceServer` (4), `UserPoolRiskConfigurationAttachment` (6), `UserPoolUICustomizationAttachment` (2) |\n| **DynamoDB** | `GlobalTable` (26), `Table` (28) |\n| **EC2** | `ClientVpnAuthorizationRule` (1), `ClientVpnEndpoint` (6), `DHCPOptions` (2), `EIPAssociation` (1), `FlowLog` (4), `Instance` (10), `KeyPair` (1), `LaunchTemplate` (5), `NatGateway` (2), `NetworkAclEntry` (1), `NetworkInterface` (2), `PlacementGroup` (3), `PrefixList` (3), `Route` (1), `SecurityGroup` (6), `SecurityGroupEgress` (5), `SecurityGroupIngress` (5), `Subnet` (6), `TrafficMirrorTarget` (1), `TransitGateway` (2), `TransitGatewayRoute` (1), `Volume` (6), `VPC` (2), `VPCCidrBlock` (1), `VPCEndpoint` (4), `VPCGatewayAttachment` (1), `VPNConnection` (5) |\n| **ECR** | `PullThroughCacheRule` (3), `RegistryScanningConfiguration` (1), `ReplicationConfiguration` (1), `Repository` (7), `RepositoryCreationTemplate` (8), `SigningConfiguration` (1) |\n| **ECS** | `CapacityProvider` (3), `Cluster` (5), `Service` (37), `TaskDefinition` (64), `TaskSet` (2) |\n| **EFS** | `AccessPoint` (1), `FileSystem` (7), `MountTarget` (4) |\n| **ElastiCache** | `CacheCluster` (9), `ReplicationGroup` (14), `User` (2), `UserGroup` (1) |\n| **ElasticLoadBalancingV2** | `Listener` (57), `ListenerCertificate` (2), `ListenerRule` (37), `LoadBalancer` (37), `TargetGroup` (58), `TrustStore` (1), `TrustStoreRevocation` (1) |\n| **Events** | `ApiDestination` (1), `Archive` (5), `Connection` (1), `Endpoint` (2), `EventBus` (2), `Rule` (23) |\n| **EventSchemas** | `Discoverer` (1), `Registry` (1), `RegistryPolicy` (1), `Schema` (1) |\n| **Glue** | `Classifier` (6), `Connection` (5), `Crawler` (11), `CustomEntityType` (1), `Database` (1), `DataQualityRuleset` (1), `Job` (15), `MLTransform` (4), `Partition` (1), `Schema` (3), `SecurityConfiguration` (1), `Table` (1), `Trigger` (10), `UserDefinedFunction` (2), `Workflow` (1) |\n| **IAM** | `Group` (23), `GroupPolicy` (1), `InstanceProfile` (2), `ManagedPolicy` (31), `OIDCProvider` (2), `Policy` (29), `Role` (40), `RolePolicy` (1), `ServiceLinkedRole` (1), `User` (24), `UserPolicy` (1) |\n| **Kinesis** | `ResourcePolicy` (4), `Stream` (5), `StreamConsumer` (2) |\n| **KinesisAnalyticsV2** | `Application` (20), `ApplicationCloudWatchLoggingOption` (1), `ApplicationOutput` (1), `ApplicationReferenceDataSource` (1) |\n| **KinesisFirehose** | `DeliveryStream` (68) |\n| **KMS** | `Alias` (2), `Key` (12), `ReplicaKey` (4) |\n| **Lambda** | `Alias` (7), `CodeSigningConfig` (1), `EventInvokeConfig` (5), `EventSourceMapping` (54), `Function` (46), `LayerVersion` (8), `LayerVersionPermission` (3), `Permission` (8), `Url` (8), `Version` (1) |\n| **Logs** | `AccountPolicy` (6), `DeliveryDestination` (3), `Destination` (1), `LogAnomalyDetector` (2), `LogGroup` (10), `MetricFilter` (7), `QueryDefinition` (1), `ResourcePolicy` (1), `SubscriptionFilter` (6), `Transformer` (3) |\n| **MemoryDB** | `Cluster` (8), `User` (1) |\n| **MSK** | `BatchScramSecret` (2), `Cluster` (31), `ClusterPolicy` (1), `Configuration` (4), `Replicator` (10), `ServerlessCluster` (4) |\n| **Pipes** | `Pipe` (9) |\n| **RDS** | `DBCluster` (19), `DBInstance` (33), `DBParameterGroup` (2), `DBProxy` (4), `DBProxyTargetGroup` (2), `DBShardGroup` (1), `DBSubnetGroup` (3), `EventSubscription` (3), `OptionGroup` (1) |\n| **Route53** | `CidrCollection` (11), `DNSSEC` (3), `HealthCheck` (30), `HostedZone` (14), `KeySigningKey` (9), `RecordSet` (75), `RecordSetGroup` (76) |\n| **Route53Profiles** | `ProfileAssociation` (1), `ProfileResourceAssociation` (6) |\n| **Route53Resolver** | `FirewallDomainList` (3), `FirewallRuleGroup` (18), `FirewallRuleGroupAssociation` (4), `ResolverDNSSECConfig` (1), `ResolverEndpoint` (18), `ResolverQueryLoggingConfig` (1), `ResolverQueryLoggingConfigAssociation` (1), `ResolverRule` (15), `ResolverRuleAssociation` (1) |\n| **S3** | `AccessPoint` (1), `Bucket` (54), `BucketPolicy` (4), `StorageLens` (5), `StorageLensGroup` (3) |\n| **S3Express** | `AccessPoint` (3), `DirectoryBucket` (11) |\n| **Scheduler** | `Schedule` (10), `ScheduleGroup` (1) |\n| **SecretsManager** | `RotationSchedule` (4), `Secret` (5), `SecretTargetAttachment` (1) |\n| **SNS** | `Subscription` (9), `Topic` (12), `TopicPolicy` (1) |\n| **SQS** | `Queue` (9), `QueuePolicy` (1) |\n| **SSM** | `Association` (3), `Document` (3), `MaintenanceWindow` (2), `MaintenanceWindowTarget` (1), `MaintenanceWindowTask` (1), `Parameter` (5) |\n| **StepFunctions** | `Activity` (3), `StateMachine` (26) |\n| **WAFv2** | `IPSet` (3), `LoggingConfiguration` (3), `RegexPatternSet` (3), `RuleGroup` (18), `WebACL` (23), `WebACLAssociation` (2) |\n\n</details>\n<!-- supported-resources:end -->\n\nHighlights:\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` — or the shorter alias `npx cdkpf 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## Scope and rule lifecycle\n\nA constraint belongs in the pack when violating it makes a real deployment fail *and* no layer that sees the same synthesized template already blocks it. There is no further \"is this worth a rule\" question — if the gap is real, it gets a rule.\n\nCDK L2 construct validation is deliberately **not** one of those layers. `CfnXxx` usage, escape hatches, `addPropertyOverride`, `cloudformation-include` and migrated templates all bypass L2, so an L2 guard covering the same mistake neither disqualifies a rule nor retires one.\n\nThat makes growth the normal state, and it has a consequence worth knowing before you upgrade: **new rules land in minor releases, so a minor upgrade can newly fail a `cdk synth` that passed yesterday.** That is intended, not a regression. If you need a frozen rule set, pin the version; to drop a single rule, `exclude: ['<rule-id>']`; to see everything without failing the build, `enforce: false`.\n\nRules move the other way too. Once the validation engine bundled in `aws-cdk-lib` (or CloudFormation's own pre-deploy validation) starts blocking a constraint, the rule is deleted rather than kept as a duplicate — staying on an older `aws-cdk-lib` and an older cdk-preflight keeps the old behavior.\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 also make good upstream PRs to that engine, but nothing here waits on one — the upstream release cycle is deliberately slower than this pack's. Each rule's `meta.yaml` tracks its upstream status so that retirement stays bookkeeping.\n\n## Requirements\n\n- `aws-cdk-lib` >= 2.267.0, released 2026-08-27 (the first release that bundles the built-in CloudFormation validator). This is a recent release — an existing CDK app may need an upgrade before cdk-preflight can run.\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"
9420
9420
  },
9421
9421
  "repository": {
9422
9422
  "type": "git",
@@ -9600,6 +9600,6 @@
9600
9600
  "symbolId": "src/index:PreflightOptions"
9601
9601
  }
9602
9602
  },
9603
- "version": "0.0.123",
9604
- "fingerprint": "q7JqluQCgeetrFQZTveDBhqCd2H8hEjrkqKO8u2hN+c="
9603
+ "version": "0.0.125",
9604
+ "fingerprint": "IQd2mv0HVKxTOWXN+Kq+4JQP8i6FDiTpzRaW05EHlIE="
9605
9605
  }
package/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
  <a href="https://github.com/badmintoncryer/cdk-preflight/actions/workflows/monthly-verify.yml"><img src="https://github.com/badmintoncryer/cdk-preflight/actions/workflows/monthly-verify.yml/badge.svg" alt="monthly real-deploy verification"></a>
13
13
  <a href="https://www.npmjs.com/package/cdk-preflight"><img src="https://img.shields.io/npm/v/cdk-preflight.svg" alt="npm version"></a>
14
14
  <a href="https://www.npmjs.com/package/cdk-preflight"><img src="https://img.shields.io/npm/dt/cdk-preflight.svg" alt="npm total downloads"></a>
15
- <a href="docs/rules.md"><img src="https://img.shields.io/badge/rules-2266-blue" alt="2266 bundled rules"></a>
15
+ <a href="docs/rules.md"><img src="https://img.shields.io/badge/rules-2437-blue" alt="2437 bundled rules"></a>
16
16
  </p>
17
17
 
18
18
  Some 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.
@@ -155,7 +155,7 @@ See [docs/rules.md](docs/rules.md) for the generated rule table.
155
155
 
156
156
  <!-- supported-resources:start -->
157
157
  <details>
158
- <summary><b>290 resource types across 44 services</b> — click to expand</summary>
158
+ <summary><b>306 resource types across 49 services</b> — click to expand</summary>
159
159
 
160
160
  Resource names are relative to `AWS::<Service>::`; the number in parentheses is how many rules target that type.
161
161
 
@@ -172,6 +172,10 @@ Resource names are relative to `AWS::<Service>::`; the number in parentheses is
172
172
  | **BedrockAgentCore** | `ApiKeyCredentialProvider` (1), `BrowserCustom` (1), `CodeInterpreterCustom` (1), `ConfigurationBundle` (3), `Dataset` (3), `Evaluator` (4), `Gateway` (5), `GatewayRule` (3), `GatewayTarget` (9), `Harness` (2), `HarnessEndpoint` (2), `Memory` (6), `OAuth2CredentialProvider` (3), `OnlineEvaluationConfig` (3), `PaymentCredentialProvider` (1), `PaymentManager` (1), `Policy` (3), `ResourcePolicy` (1), `Runtime` (8), `RuntimeEndpoint` (1) |
173
173
  | **CloudFront** | `AnycastIpList` (1), `CachePolicy` (7), `ContinuousDeploymentPolicy` (5), `Distribution` (55), `Function` (4), `KeyGroup` (1), `KeyValueStore` (2), `OriginRequestPolicy` (5), `PublicKey` (1), `RealtimeLogConfig` (3), `ResponseHeadersPolicy` (8), `VpcOrigin` (3) |
174
174
  | **CloudWatch** | `Alarm` (21), `AnomalyDetector` (6), `CompositeAlarm` (6), `Dashboard` (14), `InsightRule` (7), `MetricStream` (6) |
175
+ | **CodeBuild** | `Project` (37), `ReportGroup` (2), `SourceCredential` (4) |
176
+ | **CodeCommit** | `Repository` (11) |
177
+ | **CodeDeploy** | `Application` (7), `DeploymentConfig` (12), `DeploymentGroup` (23) |
178
+ | **CodePipeline** | `CustomActionType` (3), `Pipeline` (25), `Webhook` (2) |
175
179
  | **Cognito** | `IdentityPool` (3), `IdentityPoolRoleAttachment` (7), `LogDeliveryConfiguration` (3), `ManagedLoginBranding` (2), `UserPool` (52), `UserPoolClient` (21), `UserPoolDomain` (7), `UserPoolGroup` (1), `UserPoolIdentityProvider` (11), `UserPoolResourceServer` (4), `UserPoolRiskConfigurationAttachment` (6), `UserPoolUICustomizationAttachment` (2) |
176
180
  | **DynamoDB** | `GlobalTable` (26), `Table` (28) |
177
181
  | **EC2** | `ClientVpnAuthorizationRule` (1), `ClientVpnEndpoint` (6), `DHCPOptions` (2), `EIPAssociation` (1), `FlowLog` (4), `Instance` (10), `KeyPair` (1), `LaunchTemplate` (5), `NatGateway` (2), `NetworkAclEntry` (1), `NetworkInterface` (2), `PlacementGroup` (3), `PrefixList` (3), `Route` (1), `SecurityGroup` (6), `SecurityGroupEgress` (5), `SecurityGroupIngress` (5), `Subnet` (6), `TrafficMirrorTarget` (1), `TransitGateway` (2), `TransitGatewayRoute` (1), `Volume` (6), `VPC` (2), `VPCCidrBlock` (1), `VPCEndpoint` (4), `VPCGatewayAttachment` (1), `VPNConnection` (5) |
@@ -191,6 +195,7 @@ Resource names are relative to `AWS::<Service>::`; the number in parentheses is
191
195
  | **Lambda** | `Alias` (7), `CodeSigningConfig` (1), `EventInvokeConfig` (5), `EventSourceMapping` (54), `Function` (46), `LayerVersion` (8), `LayerVersionPermission` (3), `Permission` (8), `Url` (8), `Version` (1) |
192
196
  | **Logs** | `AccountPolicy` (6), `DeliveryDestination` (3), `Destination` (1), `LogAnomalyDetector` (2), `LogGroup` (10), `MetricFilter` (7), `QueryDefinition` (1), `ResourcePolicy` (1), `SubscriptionFilter` (6), `Transformer` (3) |
193
197
  | **MemoryDB** | `Cluster` (8), `User` (1) |
198
+ | **MSK** | `BatchScramSecret` (2), `Cluster` (31), `ClusterPolicy` (1), `Configuration` (4), `Replicator` (10), `ServerlessCluster` (4) |
194
199
  | **Pipes** | `Pipe` (9) |
195
200
  | **RDS** | `DBCluster` (19), `DBInstance` (33), `DBParameterGroup` (2), `DBProxy` (4), `DBProxyTargetGroup` (2), `DBShardGroup` (1), `DBSubnetGroup` (3), `EventSubscription` (3), `OptionGroup` (1) |
196
201
  | **Route53** | `CidrCollection` (11), `DNSSEC` (3), `HealthCheck` (30), `HostedZone` (14), `KeySigningKey` (9), `RecordSet` (75), `RecordSetGroup` (76) |
package/docs/rules.md CHANGED
@@ -794,6 +794,125 @@
794
794
  | `pf-cloudwatch-metric-stream-role-account` | AWS::CloudWatch::MetricStream | RoleArn must be in the stack's own account | ERROR | none |
795
795
  | `pf-cloudwatch-metricstat-stat-syntax` | AWS::CloudWatch::Alarm | MetricStat.Stat must be a CloudWatch statistic | ERROR | none |
796
796
  | `pf-cloudwatch-threshold-metric-id` | AWS::CloudWatch::Alarm | ThresholdMetricId must match a metric query that returns data | ERROR | none |
797
+ | `pf-codebuild-artifacts-encryption-disabled-s3-only` | AWS::CodeBuild::Project | Artifacts.EncryptionDisabled is only set for S3 artifacts | ERROR | none |
798
+ | `pf-codebuild-artifacts-no-artifacts-no-location` | AWS::CodeBuild::Project | NO_ARTIFACTS carries no Location | ERROR | none |
799
+ | `pf-codebuild-artifacts-s3-location-required` | AWS::CodeBuild::Project | S3 artifacts carry a Location | ERROR | none |
800
+ | `pf-codebuild-badge-not-supported-for-s3-source` | AWS::CodeBuild::Project | Build badges are not enabled on an S3 or source-less project | ERROR | none |
801
+ | `pf-codebuild-badge-not-with-codepipeline-source` | AWS::CodeBuild::Project | Build badges are not enabled on a CODEPIPELINE project | ERROR | none |
802
+ | `pf-codebuild-build-batch-timeout-range` | AWS::CodeBuild::Project | The batch build timeout stays between 5 and 2160 minutes | ERROR | none |
803
+ | `pf-codebuild-cache-docker-layer-linux-only` | AWS::CodeBuild::Project | PrivilegedMode is not set on a Windows environment | ERROR | none |
804
+ | `pf-codebuild-cache-local-requires-modes` | AWS::CodeBuild::Project | A LOCAL cache names its modes | ERROR | none |
805
+ | `pf-codebuild-cache-location-ignored-for-local` | AWS::CodeBuild::Project | LOCAL_SOURCE_CACHE goes with a project that has a source | ERROR | none |
806
+ | `pf-codebuild-cache-s3-requires-location` | AWS::CodeBuild::Project | An S3 cache names the bucket and prefix | ERROR | none |
807
+ | `pf-codebuild-compute-type-environment-type` | AWS::CodeBuild::Project | The Lambda compute types go with a Lambda environment type | ERROR | none |
808
+ | `pf-codebuild-concurrent-build-limit-range` | AWS::CodeBuild::Project | The per-project concurrent build limit is at least 1 | ERROR | none |
809
+ | `pf-codebuild-curated-image-requires-codebuild-credentials` | AWS::CodeBuild::Project | A CodeBuild curated image is pulled with CODEBUILD credentials | ERROR | none |
810
+ | `pf-codebuild-encryption-key-region` | AWS::CodeBuild::Project | The build output encryption key lives in the project's Region | ERROR | none |
811
+ | `pf-codebuild-environment-variable-name-reserved` | AWS::CodeBuild::Project | Environment variable names stay off the reserved CODEBUILD_ prefix | ERROR | none |
812
+ | `pf-codebuild-environment-variable-name-unique` | AWS::CodeBuild::Project | Environment variable names are unique within a project | ERROR | none |
813
+ | `pf-codebuild-file-system-identifier-charset` | AWS::CodeBuild::Project | A project that mounts a file system runs in privileged mode | ERROR | none |
814
+ | `pf-codebuild-file-system-location-format` | AWS::CodeBuild::Project | An EFS mount location names the file system and the directory | ERROR | none |
815
+ | `pf-codebuild-git-submodules-config-git-sources-only` | AWS::CodeBuild::Project | Git submodules are only configured on a git-backed source | ERROR | none |
816
+ | `pf-codebuild-lambda-compute-no-privileged-mode` | AWS::CodeBuild::Project | PrivilegedMode is not set on the Lambda compute mode | ERROR | none |
817
+ | `pf-codebuild-logs-s3-requires-location` | AWS::CodeBuild::Project | Enabled S3 build logs name the bucket and prefix | ERROR | none |
818
+ | `pf-codebuild-project-description-length` | AWS::CodeBuild::Project | The project description stays within 255 characters | ERROR | none |
819
+ | `pf-codebuild-project-name-length` | AWS::CodeBuild::Project | The project name stays within 150 characters | ERROR | none |
820
+ | `pf-codebuild-report-build-status-provider` | AWS::CodeBuild::Project | ReportBuildStatus is only set on a source provider that reports status | ERROR | none |
821
+ | `pf-codebuild-reportgroup-no-export-forbids-destination` | AWS::CodeBuild::ReportGroup | A NO_EXPORT report group carries no S3 destination | ERROR | none |
822
+ | `pf-codebuild-reportgroup-s3-export-requires-destination` | AWS::CodeBuild::ReportGroup | An S3 report group names its destination | ERROR | none |
823
+ | `pf-codebuild-secondary-artifact-identifier-unique` | AWS::CodeBuild::Project | Secondary artifact identifiers are unique within a project | ERROR | none |
824
+ | `pf-codebuild-secondary-artifacts-identifier-required` | AWS::CodeBuild::Project | Every secondary artifact carries an ArtifactIdentifier | ERROR | none |
825
+ | `pf-codebuild-secondary-artifacts-max-12` | AWS::CodeBuild::Project | A project declares at most 12 secondary artifacts | ERROR | none |
826
+ | `pf-codebuild-secondary-artifacts-no-codepipeline` | AWS::CodeBuild::Project | Secondary artifacts publish to S3 | ERROR | none |
827
+ | `pf-codebuild-secondary-source-identifier-unique` | AWS::CodeBuild::Project | Secondary source identifiers are unique within a project | ERROR | none |
828
+ | `pf-codebuild-secondary-sources-identifier-required` | AWS::CodeBuild::Project | Every secondary source carries a SourceIdentifier | ERROR | none |
829
+ | `pf-codebuild-secondary-sources-max-12` | AWS::CodeBuild::Project | A project declares at most 12 secondary sources | ERROR | none |
830
+ | `pf-codebuild-source-codepipeline-requires-artifacts-codepipeline` | AWS::CodeBuild::Project | The CODEPIPELINE source and artifact types are set together | ERROR | none |
831
+ | `pf-codebuild-source-location-required` | AWS::CodeBuild::Project | Every source that lives outside CodeBuild carries a Location | ERROR | none |
832
+ | `pf-codebuild-source-no-source-no-location` | AWS::CodeBuild::Project | A NO_SOURCE project carries no Source.Location | ERROR | none |
833
+ | `pf-codebuild-source-version-identifier-must-match-source` | AWS::CodeBuild::Project | Every SecondarySourceVersions entry names a declared secondary source | ERROR | none |
834
+ | `pf-codebuild-sourcecredential-basic-auth-bitbucket-only` | AWS::CodeBuild::SourceCredential | BASIC_AUTH source credentials are imported for Bitbucket only | ERROR | none |
835
+ | `pf-codebuild-sourcecredential-codeconnections-arn` | AWS::CodeBuild::SourceCredential | A CODECONNECTIONS credential carries a connection ARN as its Token | ERROR | none |
836
+ | `pf-codebuild-sourcecredential-oauth-not-supported` | AWS::CodeBuild::SourceCredential | OAUTH source credentials are not imported through CloudFormation | ERROR | none |
837
+ | `pf-codebuild-sourcecredential-one-per-server-type` | AWS::CodeBuild::SourceCredential | One source credential per server type per Region | ERROR | none |
838
+ | `pf-codebuild-vpc-security-groups-max-5` | AWS::CodeBuild::Project | VpcConfig names at most 5 security groups | ERROR | none |
839
+ | `pf-codebuild-vpc-subnets-max-16` | AWS::CodeBuild::Project | VpcConfig names at most 16 subnets | ERROR | none |
840
+ | `pf-codecommit-code-branch-name-valid` | AWS::CodeCommit::Repository | Code.BranchName must be a valid Git branch name | ERROR | none |
841
+ | `pf-codecommit-kms-key-region` | AWS::CodeCommit::Repository | KmsKeyId must name a KMS key in the repository's Region | ERROR | none |
842
+ | `pf-codecommit-trigger-branch-name-valid` | AWS::CodeCommit::Repository | Trigger branch names must be valid Git branch names | ERROR | none |
843
+ | `pf-codecommit-trigger-branches-max-10` | AWS::CodeCommit::Repository | A trigger may list at most 10 branches | ERROR | none |
844
+ | `pf-codecommit-trigger-custom-data-max-1000` | AWS::CodeCommit::Repository | Trigger CustomData is limited to 1000 characters | ERROR | none |
845
+ | `pf-codecommit-trigger-destination-region` | AWS::CodeCommit::Repository | A trigger's DestinationArn must be in the repository's Region | ERROR | none |
846
+ | `pf-codecommit-trigger-destination-service` | AWS::CodeCommit::Repository | A trigger's DestinationArn must be an SNS topic or a Lambda function | ERROR | none |
847
+ | `pf-codecommit-trigger-events-all-exclusive` | AWS::CodeCommit::Repository | The trigger event 'all' cannot be combined with another event | ERROR | none |
848
+ | `pf-codecommit-trigger-events-required` | AWS::CodeCommit::Repository | A trigger must specify at least one event | ERROR | none |
849
+ | `pf-codecommit-trigger-name-unique` | AWS::CodeCommit::Repository | Trigger names must be unique within a repository | ERROR | none |
850
+ | `pf-codecommit-triggers-max-10` | AWS::CodeCommit::Repository | A repository may declare at most 10 triggers | ERROR | none |
851
+ | `pf-codedeploy-app-compute-platform-value` | AWS::CodeDeploy::Application | Application ComputePlatform must be Server, Lambda, ECS or Kubernetes | ERROR | pending-engine |
852
+ | `pf-codedeploy-config-fleet-percent-range` | AWS::CodeDeploy::DeploymentConfig | MinimumHealthyHosts FLEET_PERCENT must be below 100 | ERROR | none |
853
+ | `pf-codedeploy-config-lambda-forbids-minimum-healthy-hosts` | AWS::CodeDeploy::DeploymentConfig | MinimumHealthyHosts is only valid on the Server compute platform | ERROR | none |
854
+ | `pf-codedeploy-config-lambda-requires-traffic-routing` | AWS::CodeDeploy::DeploymentConfig | A Lambda or ECS deployment configuration must set TrafficRoutingConfig | ERROR | none |
855
+ | `pf-codedeploy-config-name-reserved-prefix` | AWS::CodeDeploy::DeploymentConfig | A custom deployment configuration may not use the CodeDeployDefault. prefix | ERROR | none |
856
+ | `pf-codedeploy-config-server-forbids-traffic-routing` | AWS::CodeDeploy::DeploymentConfig | TrafficRoutingConfig is not valid on the Server compute platform | ERROR | none |
857
+ | `pf-codedeploy-config-server-requires-minimum-healthy-hosts` | AWS::CodeDeploy::DeploymentConfig | A Server deployment configuration must set MinimumHealthyHosts | ERROR | none |
858
+ | `pf-codedeploy-config-traffic-routing-block-matches-type` | AWS::CodeDeploy::DeploymentConfig | TrafficRoutingConfig must carry exactly the sub-block its Type names | ERROR | none |
859
+ | `pf-codedeploy-config-traffic-routing-percentage-range` | AWS::CodeDeploy::DeploymentConfig | Traffic routing percentage must be between 1 and 99 | ERROR | none |
860
+ | `pf-codedeploy-config-traffic-shift-interval-max` | AWS::CodeDeploy::DeploymentConfig | A traffic shift may not take more than 2880 minutes end to end | ERROR | none |
861
+ | `pf-codedeploy-config-zonal-minimum-healthy-per-zone-range` | AWS::CodeDeploy::DeploymentConfig | ZonalConfig MinimumHealthyHostsPerZone FLEET_PERCENT must be below 100 | ERROR | none |
862
+ | `pf-codedeploy-config-zonal-server-only` | AWS::CodeDeploy::DeploymentConfig | ZonalConfig is only supported on the Server compute platform | ERROR | none |
863
+ | `pf-codedeploy-dg-alarm-configuration-enabled-requires-alarms` | AWS::CodeDeploy::DeploymentGroup | An enabled AlarmConfiguration needs at least one alarm | ERROR | none |
864
+ | `pf-codedeploy-dg-autorollback-enabled-requires-events` | AWS::CodeDeploy::DeploymentGroup | An enabled AutoRollbackConfiguration needs at least one event | ERROR | none |
865
+ | `pf-codedeploy-dg-blue-green-config-required-members` | AWS::CodeDeploy::DeploymentGroup | BlueGreenDeploymentConfiguration must carry DeploymentReadyOption and TerminateBlueInstancesOnDeploymentSuccess | ERROR | none |
866
+ | `pf-codedeploy-dg-bluegreen-requires-traffic-control` | AWS::CodeDeploy::DeploymentGroup<br>AWS::CodeDeploy::Application | A BLUE_GREEN deployment style requires WITH_TRAFFIC_CONTROL | ERROR | none |
867
+ | `pf-codedeploy-dg-copy-asg-requires-asg` | AWS::CodeDeploy::DeploymentGroup | COPY_AUTO_SCALING_GROUP needs exactly one Auto Scaling group on the deployment group | ERROR | none |
868
+ | `pf-codedeploy-dg-deployment-config-platform-match` | AWS::CodeDeploy::DeploymentGroup<br>AWS::CodeDeploy::Application<br>AWS::CodeDeploy::DeploymentConfig | DeploymentConfigName must belong to the application's compute platform | ERROR | none |
869
+ | `pf-codedeploy-dg-deployment-ready-continue-no-wait-time` | AWS::CodeDeploy::DeploymentGroup | CONTINUE_DEPLOYMENT does not take a WaitTimeInMinutes | ERROR | none |
870
+ | `pf-codedeploy-dg-deployment-ready-stop-requires-wait-time` | AWS::CodeDeploy::DeploymentGroup | STOP_DEPLOYMENT needs a WaitTimeInMinutes above zero | ERROR | none |
871
+ | `pf-codedeploy-dg-ec2-filters-server-platform-only` | AWS::CodeDeploy::DeploymentGroup<br>AWS::CodeDeploy::Application | Instance tag filters are only valid on the Server compute platform | ERROR | none |
872
+ | `pf-codedeploy-dg-ec2-tag-filters-xor-tag-set` | AWS::CodeDeploy::DeploymentGroup | Ec2TagFilters and Ec2TagSet cannot both be specified | ERROR | none |
873
+ | `pf-codedeploy-dg-ecs-services-requires-ecs-platform` | AWS::CodeDeploy::DeploymentGroup<br>AWS::CodeDeploy::Application | ECSServices is only valid on the ECS compute platform | ERROR | none |
874
+ | `pf-codedeploy-dg-lambda-forbids-blue-green-config` | AWS::CodeDeploy::DeploymentGroup<br>AWS::CodeDeploy::Application | BlueGreenDeploymentConfiguration is not valid on the Lambda compute platform | ERROR | none |
875
+ | `pf-codedeploy-dg-lambda-requires-blue-green-traffic-control` | AWS::CodeDeploy::DeploymentGroup<br>AWS::CodeDeploy::Application | A Lambda deployment group must be BLUE_GREEN with WITH_TRAFFIC_CONTROL | ERROR | none |
876
+ | `pf-codedeploy-dg-onprem-tag-filters-xor-tag-set` | AWS::CodeDeploy::DeploymentGroup | OnPremisesInstanceTagFilters and OnPremisesTagSet cannot both be specified | ERROR | none |
877
+ | `pf-codedeploy-dg-revision-bundle-type-server` | AWS::CodeDeploy::DeploymentGroup | An EC2/On-Premises revision bundle is a tar, tgz or zip archive | ERROR | none |
878
+ | `pf-codedeploy-dg-revision-github-server-only` | AWS::CodeDeploy::DeploymentGroup | A GitHub revision can only be deployed on the EC2/On-Premises platform | ERROR | none |
879
+ | `pf-codedeploy-dg-tag-filter-type-value-consistency` | AWS::CodeDeploy::DeploymentGroup | A KEY_ONLY tag filter carries no Value and a VALUE_ONLY tag filter carries no Key | ERROR | none |
880
+ | `pf-codedeploy-dg-target-group-name-max-32` | AWS::CodeDeploy::DeploymentGroup | A TargetGroupInfo Name is a target group name of at most 32 characters, never an ARN | ERROR | none |
881
+ | `pf-codedeploy-dg-termination-wait-max` | AWS::CodeDeploy::DeploymentGroup | TerminationWaitTimeInMinutes may not exceed 2880 (two days) | ERROR | none |
882
+ | `pf-codedeploy-dg-traffic-control-requires-load-balancer` | AWS::CodeDeploy::DeploymentGroup | A Server deployment group routing traffic needs a load balancer or target group | ERROR | none |
883
+ | `pf-codedeploy-dg-trigger-name-and-target-unique` | AWS::CodeDeploy::DeploymentGroup | Trigger names and trigger target ARNs are each unique within a deployment group | ERROR | none |
884
+ | `pf-codedeploy-dg-trigger-target-region` | AWS::CodeDeploy::DeploymentGroup | A trigger's SNS topic must live in the deployment group's own Region | ERROR | none |
885
+ | `pf-codedeploy-dg-triggers-max-10` | AWS::CodeDeploy::DeploymentGroup | A deployment group may carry at most 10 notification triggers | ERROR | none |
886
+ | `pf-codepipeline-action-config-required-keys` | AWS::CodePipeline::Pipeline | An action's Configuration must carry the keys its provider requires | ERROR | none |
887
+ | `pf-codepipeline-action-type-id-combination` | AWS::CodePipeline::Pipeline | An action's Category, Owner and Provider must be a published combination | ERROR | none |
888
+ | `pf-codepipeline-artifact-name-charset` | AWS::CodePipeline::Pipeline | An artifact name is at most 100 characters of letters, digits, underscore and hyphen | ERROR | none |
889
+ | `pf-codepipeline-artifact-store-encryption-key-kms` | AWS::CodePipeline::Pipeline | An artifact store's EncryptionKey.Type must be the literal KMS | ERROR | pending-engine |
890
+ | `pf-codepipeline-artifact-stores-region-of-pipeline` | AWS::CodePipeline::Pipeline | The cross-region ArtifactStores list must include the pipeline's own region | ERROR | none |
891
+ | `pf-codepipeline-cat-artifact-min-le-max` | AWS::CodePipeline::CustomActionType | A custom action type's MinimumCount must not exceed its MaximumCount | ERROR | none |
892
+ | `pf-codepipeline-cat-queryable-max-1` | AWS::CodePipeline::CustomActionType | At most one configuration property of a custom action type may be Queryable | ERROR | none |
893
+ | `pf-codepipeline-cat-queryable-not-secret` | AWS::CodePipeline::CustomActionType | A Queryable configuration property must be Required and not Secret | ERROR | none |
894
+ | `pf-codepipeline-cross-region-action-needs-store` | AWS::CodePipeline::Pipeline | A cross-region action needs the plural ArtifactStores, not a single ArtifactStore | ERROR | none |
895
+ | `pf-codepipeline-first-stage-source-only` | AWS::CodePipeline::Pipeline | The first stage of a pipeline may contain source actions only | ERROR | none |
896
+ | `pf-codepipeline-non-source-stage-required` | AWS::CodePipeline::Pipeline | A pipeline needs at least one action whose category is not Source | ERROR | none |
897
+ | `pf-codepipeline-parallel-mode-no-rollback-condition` | AWS::CodePipeline::Pipeline | A PARALLEL pipeline cannot have a stage that exits failure with ROLLBACK | ERROR | none |
898
+ | `pf-codepipeline-run-order-range` | AWS::CodePipeline::Pipeline | An action's RunOrder must be between 1 and 999 | ERROR | none |
899
+ | `pf-codepipeline-source-action-first-stage-only` | AWS::CodePipeline::Pipeline | Source actions may appear in the first stage only | ERROR | none |
900
+ | `pf-codepipeline-stage-count-max` | AWS::CodePipeline::Pipeline | A pipeline may hold at most 50 stages | ERROR | none |
901
+ | `pf-codepipeline-stage-name-charset` | AWS::CodePipeline::Pipeline | A stage name is at most 100 characters of [A-Za-z0-9.@_-] | ERROR | none |
902
+ | `pf-codepipeline-stage-names-unique` | AWS::CodePipeline::Pipeline | Stage names must be unique within a pipeline | ERROR | none |
903
+ | `pf-codepipeline-stage-on-failure-result-xor-conditions` | AWS::CodePipeline::Pipeline | A stage's OnFailure takes either Result or Conditions, not both | ERROR | none |
904
+ | `pf-codepipeline-trigger-filter-patterns-max-8` | AWS::CodePipeline::Pipeline | A Git trigger filter accepts at most 8 include and 8 exclude patterns | ERROR | none |
905
+ | `pf-codepipeline-trigger-filters-max-3` | AWS::CodePipeline::Pipeline | A Git trigger accepts at most 3 push and 3 pull-request filters | ERROR | none |
906
+ | `pf-codepipeline-trigger-source-action-is-connection` | AWS::CodePipeline::Pipeline | A Git trigger must name a CodeStarSourceConnection source action of the pipeline | ERROR | none |
907
+ | `pf-codepipeline-v1-action-provider` | AWS::CodePipeline::Pipeline | The Commands, ECRBuildAndPublish and EKS action providers need a V2 pipeline | ERROR | none |
908
+ | `pf-codepipeline-v1-execution-mode` | AWS::CodePipeline::Pipeline | ExecutionMode QUEUED and PARALLEL need a V2 pipeline | ERROR | none |
909
+ | `pf-codepipeline-v1-stage-conditions` | AWS::CodePipeline::Pipeline | Stage conditions need a V2 pipeline | ERROR | none |
910
+ | `pf-codepipeline-v1-triggers` | AWS::CodePipeline::Pipeline | Git triggers need a V2 pipeline | ERROR | none |
911
+ | `pf-codepipeline-v1-variables` | AWS::CodePipeline::Pipeline | Pipeline-level variables need a V2 pipeline | ERROR | none |
912
+ | `pf-codepipeline-variable-names-unique` | AWS::CodePipeline::Pipeline | Pipeline-level variable names must be unique | ERROR | none |
913
+ | `pf-codepipeline-variables-max-50` | AWS::CodePipeline::Pipeline | A pipeline may declare at most 50 pipeline-level variables | ERROR | none |
914
+ | `pf-codepipeline-webhook-authentication-configuration` | AWS::CodePipeline::Webhook | AuthenticationConfiguration must carry exactly the property the Authentication mode takes | ERROR | none |
915
+ | `pf-codepipeline-webhook-filters-max-5` | AWS::CodePipeline::Webhook | A webhook may declare at most 5 filters | ERROR | none |
797
916
  | `pf-cognito-alias-username-exclusive` | AWS::Cognito::UserPool | AliasAttributes and UsernameAttributes are mutually exclusive | ERROR | none |
798
917
  | `pf-cognito-analytics-application-requires-role` | AWS::Cognito::UserPoolClient | Pinpoint ApplicationId needs a RoleArn | ERROR | none |
799
918
  | `pf-cognito-analytics-arn-region` | AWS::Cognito::UserPoolClient | The Pinpoint analytics app must be in the pool region | ERROR | none |
@@ -1784,6 +1903,58 @@
1784
1903
  | `pf-memorydb-snapshot-retention` | AWS::MemoryDB::Cluster | SnapshotRetentionLimit is 0-35 days | ERROR | none |
1785
1904
  | `pf-memorydb-snapshot-window` | AWS::MemoryDB::Cluster | SnapshotWindow must be hh24:mi-hh24:mi and must not overlap the maintenance window | ERROR | none |
1786
1905
  | `pf-memorydb-user-password` | AWS::MemoryDB::User | A password user needs passwords of 16-128 characters | ERROR | none |
1906
+ | `pf-msk-broker-count-multiple-of-az` | AWS::MSK::Cluster | The MSK broker count must be a multiple of the number of client subnets | ERROR | none |
1907
+ | `pf-msk-broker-logs-any-required` | AWS::MSK::Cluster | LoggingInfo.BrokerLogs must name at least one log destination | ERROR | none |
1908
+ | `pf-msk-broker-logs-cloudwatch-loggroup-required` | AWS::MSK::Cluster | Enabling CloudWatch Logs broker logs requires the LogGroup to be named | ERROR | none |
1909
+ | `pf-msk-broker-logs-firehose-stream-required` | AWS::MSK::Cluster | Enabling Kinesis Data Firehose broker logs requires the DeliveryStream to be named | ERROR | none |
1910
+ | `pf-msk-broker-logs-s3-bucket-required` | AWS::MSK::Cluster | Enabling Amazon S3 broker logs requires the Bucket to be named | ERROR | none |
1911
+ | `pf-msk-client-subnets-count` | AWS::MSK::Cluster | An MSK cluster needs exactly two or three client subnets | ERROR | none |
1912
+ | `pf-msk-client-subnets-distinct` | AWS::MSK::Cluster | MSK client subnets must all be different | ERROR | none |
1913
+ | `pf-msk-cluster-name-pattern` | AWS::MSK::Cluster | An MSK cluster name must be alphanumeric and may only contain hyphens after the first character | ERROR | none |
1914
+ | `pf-msk-clusterpolicy-resource-matches-cluster` | AWS::MSK::ClusterPolicy | A cluster policy's Resource must be the cluster the policy is attached to | ERROR | none |
1915
+ | `pf-msk-config-custom-advertised-listeners-format` | AWS::MSK::Configuration | custom.advertised.listeners must use the LISTENER_NAME://host:port+{broker_id} form | ERROR | none |
1916
+ | `pf-msk-config-kafka-versions-unknown` | AWS::MSK::Configuration | KafkaVersionsList must name Apache Kafka versions Amazon MSK knows | ERROR | none |
1917
+ | `pf-msk-config-name-pattern` | AWS::MSK::Configuration | An MSK configuration name must be alphanumeric and may only contain hyphens after the first character | ERROR | none |
1918
+ | `pf-msk-config-server-properties-allowed-keys` | AWS::MSK::Configuration | An MSK configuration may only set Amazon MSK's supported Apache Kafka properties | ERROR | none |
1919
+ | `pf-msk-express-kafka-version` | AWS::MSK::Cluster | Express brokers do not run every Apache Kafka version | ERROR | none |
1920
+ | `pf-msk-express-no-ebs-storage` | AWS::MSK::Cluster | An MSK cluster with Express brokers may not declare StorageInfo | ERROR | none |
1921
+ | `pf-msk-express-no-storage-mode` | AWS::MSK::Cluster | An MSK cluster with Express brokers may not declare StorageMode | ERROR | none |
1922
+ | `pf-msk-express-requires-three-subnets` | AWS::MSK::Cluster | An MSK cluster with Express brokers needs exactly three client subnets | ERROR | none |
1923
+ | `pf-msk-kafka-version-deprecated` | AWS::MSK::Cluster | A deprecated Apache Kafka version cannot be used for a new MSK cluster | ERROR | none |
1924
+ | `pf-msk-network-type-ipv4-at-create` | AWS::MSK::Cluster | A cluster is created IPv4-only | ERROR | none |
1925
+ | `pf-msk-open-monitoring-requires-exporter` | AWS::MSK::Cluster | Prometheus open monitoring needs an exporter | ERROR | none |
1926
+ | `pf-msk-provisioned-throughput-instance-type` | AWS::MSK::Cluster | Provisioned storage throughput needs kafka.m5.4xlarge / kafka.m7g.2xlarge or larger | ERROR | none |
1927
+ | `pf-msk-provisioned-throughput-max-per-instance` | AWS::MSK::Cluster | Provisioned storage throughput has a per-broker-size ceiling | ERROR | none |
1928
+ | `pf-msk-provisioned-throughput-min` | AWS::MSK::Cluster | Provisioned storage throughput starts at 250 MiB/s | ERROR | none |
1929
+ | `pf-msk-provisioned-throughput-volume-size` | AWS::MSK::Cluster | Provisioned storage throughput needs a volume of at least 10 GiB | ERROR | none |
1930
+ | `pf-msk-provisioned-throughput-without-enabled` | AWS::MSK::Cluster | VolumeThroughput only counts when ProvisionedThroughput is enabled | ERROR | none |
1931
+ | `pf-msk-public-access-not-at-create` | AWS::MSK::Cluster | Public access cannot be turned on while the cluster is created | ERROR | none |
1932
+ | `pf-msk-replicator-apache-kafka-cluster-requires-auth` | AWS::MSK::Replicator | An Apache Kafka cluster entry must declare ClientAuthentication | ERROR | none |
1933
+ | `pf-msk-replicator-arns-match-kafka-clusters` | AWS::MSK::Replicator | ReplicationInfoList ARNs must be the ones listed in KafkaClusters | ERROR | none |
1934
+ | `pf-msk-replicator-clusters-same-account` | AWS::MSK::Replicator | A replicator's source and target clusters must be in one account | ERROR | none |
1935
+ | `pf-msk-replicator-enhanced-sync-requires-identical` | AWS::MSK::Replicator | ENHANCED consumer-group offset sync needs IDENTICAL topic names | ERROR | none |
1936
+ | `pf-msk-replicator-kafka-cluster-exactly-one-kind` | AWS::MSK::Replicator | A KafkaClusters entry names either an MSK cluster or an Apache Kafka cluster | ERROR | none |
1937
+ | `pf-msk-replicator-service-role-account` | AWS::MSK::Replicator | The service execution role must live in the clusters' account | ERROR | none |
1938
+ | `pf-msk-replicator-source-arn-xor-id` | AWS::MSK::Replicator | A ReplicationInfo names the source cluster by ARN or by id, never both | ERROR | none |
1939
+ | `pf-msk-replicator-source-target-differ` | AWS::MSK::Replicator | A replicator's two KafkaClusters entries must be different clusters | ERROR | none |
1940
+ | `pf-msk-replicator-target-cluster-region` | AWS::MSK::Replicator | A replicator must be created in its target cluster's region | ERROR | none |
1941
+ | `pf-msk-replicator-vpc-config-only-for-msk-cluster` | AWS::MSK::Replicator | VpcConfig belongs to an MSK cluster entry, not an Apache Kafka one | ERROR | none |
1942
+ | `pf-msk-sasl-requires-in-cluster-encryption` | AWS::MSK::Cluster | Client authentication needs in-cluster encryption | ERROR | none |
1943
+ | `pf-msk-sasl-requires-tls-client-broker` | AWS::MSK::Cluster | Client authentication needs client-broker encryption | ERROR | none |
1944
+ | `pf-msk-scram-secret-account` | AWS::MSK::BatchScramSecret | SCRAM secrets must live in the same account as the MSK cluster | ERROR | none |
1945
+ | `pf-msk-scram-secret-list-unique` | AWS::MSK::BatchScramSecret | SecretArnList must not repeat a secret ARN | ERROR | none |
1946
+ | `pf-msk-serverless-name-pattern` | AWS::MSK::ServerlessCluster | A serverless MSK cluster name must be alphanumeric and may only contain hyphens after the first character | ERROR | none |
1947
+ | `pf-msk-serverless-sasl-iam-enabled` | AWS::MSK::ServerlessCluster | A serverless MSK cluster must keep SASL/IAM authentication enabled | ERROR | none |
1948
+ | `pf-msk-serverless-subnets-count` | AWS::MSK::ServerlessCluster | Each serverless MSK VPC configuration needs between 2 and 6 subnets | ERROR | none |
1949
+ | `pf-msk-serverless-vpc-configs-max` | AWS::MSK::ServerlessCluster | A serverless MSK cluster can span at most 5 VPCs | ERROR | none |
1950
+ | `pf-msk-t3-small-not-kraft` | AWS::MSK::Cluster | kafka.t3.small does not run KRaft metadata mode | ERROR | none |
1951
+ | `pf-msk-tiered-storage-instance-type` | AWS::MSK::Cluster | Tiered storage is not available on kafka.t3.small brokers | ERROR | none |
1952
+ | `pf-msk-tls-cert-authority-arn-format` | AWS::MSK::Cluster | CertificateAuthorityArnList holds AWS Private CA ARNs | ERROR | none |
1953
+ | `pf-msk-tls-enabled-requires-ca-list` | AWS::MSK::Cluster | A Tls block needs both Enabled and CertificateAuthorityArnList | ERROR | none |
1954
+ | `pf-msk-tls-plaintext-requires-unauthenticated` | AWS::MSK::Cluster | A TLS_PLAINTEXT listener has to enable unauthenticated traffic | ERROR | none |
1955
+ | `pf-msk-unauthenticated-only-requires-no-tls-only` | AWS::MSK::Cluster | A cluster has to accept some kind of client | ERROR | none |
1956
+ | `pf-msk-vpc-connectivity-auth-not-at-create` | AWS::MSK::Cluster | Multi-VPC connectivity auth schemes cannot be enabled at create time | ERROR | none |
1957
+ | `pf-msk-zookeeper-access-not-at-create` | AWS::MSK::Cluster | ZookeeperAccess cannot be set while the cluster is created | ERROR | none |
1787
1958
  | `pf-pipes-batch-size-target-limit` | AWS::Pipes::Pipe | Source BatchSize is capped by what the target accepts per call | ERROR | none |
1788
1959
  | `pf-pipes-cross-region` | AWS::Pipes::Pipe | A pipe's source and target must be in the pipe's Region | ERROR | none |
1789
1960
  | `pf-pipes-enrichment-type` | AWS::Pipes::Pipe | Pipe enrichment must be Lambda, Step Functions, API Gateway or an API destination | ERROR | 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.123" };
20
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-preflight.Preflight", version: "0.0.125" };
21
21
  /**
22
22
  * Register the cdk-preflight rules on an App or Stage.
23
23
  */