cdk-preflight 0.0.97 → 0.0.99

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.
@@ -24,8 +24,10 @@ cdk-preflight のルール追加パイプライン。AGENTS.md の設計原則
24
24
  - ヘルパーは `_pf_<短縮名>_` プレフィックスで一意に
25
25
  - `walk` ビルトインは無い。`to_number`/`object.get`/`flatten_list`/`resolve` で明示的に書く
26
26
  - fail テンプレートはこのルール**だけ**に違反、pass テンプレートは完全クリーン
27
- 4. **ローカルゲート**: まず `npx ts-node --transpile-only --project test/tsconfig.json scripts/rule-check.ts check <service|rule-id>...` を回す。`rules/` を直接読んで 1 エンジンに全ルールを載せ、fail が自分のルールで鳴るか / pass が全ルール無音か / どちらも組み込みエンジンに止められないかを返す(`bundle-rules` も meta.yaml の evidence も要らないので、実機ゲート前の直しはここで回す。80 本で数秒)。全部 `ok` になってから `npx projen bundle-rules && npx jest test/rules.test.ts test/structure.test.ts`。**jest は `-t` で対象を絞る**。フルスイートは PR 直前の 1 回だけでよく、実測では 401 回中 73 回がフル実行で合計 5.8 時間を溶かしている。
27
+ - **数値・長さ・個数の制約は境界ちょうどで書く**。fail は「違反する値のうち限界に最も近いもの」、pass は「限界そのもの」— 20 文字下限なら fail=19 文字 / pass=20 文字であって、fail=5 文字 / pass=26 文字ではない。緩いペアはルールの向きしか証明しない(`count(v) < 20` は fail が 5 文字なら定数が `< 10` でも鳴り、pass が 26 文字なら `< 25` でも黙る)ので、定数も比較演算子も固定できないし、実機ゲートの証拠も弱くなる(19 文字が CREATE に失敗して初めて下限 20 が実証される)。ルールが両端を見ているレンジは fail に両端を置く(fail の判定は「自分のルールの診断が 1 件以上」なので、違反リソースを 2 つ並べてよい)。エンジンのスキーマが既に持っている側の端は入れない — ルールもそこは見ていない(原則 1)し、重複ガードが赤くなる。順序の無い制約(プロパティ欠落、enum の値違い、リソース間の不整合)には境界が無いので対象外
28
+ 4. **ローカルゲート**: まず `npx ts-node --transpile-only --project test/tsconfig.json scripts/rule-check.ts check <service|rule-id>...` を回す。`rules/` を直接読んで 1 エンジンに全ルールを載せ、fail が自分のルールで鳴るか / pass が全ルール無音か / どちらも組み込みエンジンに止められないかを返す(`bundle-rules` も meta.yaml の evidence も要らないので、実機ゲート前の直しはここで回す。80 本で数秒)。全部 `ok` になってから `npx projen bundle-rules && npx jest test/rules.test.ts test/structure.test.ts`。`structure.test.ts` は手順 3 の境界値を機械で見る(rego のしきい値ごとに fail へ「限界に最も近い違反値」、pass へ「限界そのもの」が現れるか)。しきい値の検出が意味を持たないルールだけ `rules/_boundary-exceptions.txt` に理由付きで逃がす。**jest は `-t` で対象を絞る**。フルスイートは PR 直前の 1 回だけでよく、実測では 401 回中 73 回がフル実行で合計 5.8 時間を溶かしている。
28
29
  5. **実機再現ゲート**: `bash bench/verify-rule.sh <rule-id>`(要 AWS 認証)。観測したエラーメッセージと日付を `meta.yaml#repro.evidence` に記録。
30
+ - **evidence には実際にデプロイした値を書く**(`bench 2026-09-13 us-east-1: 19-char Value -> "...at least 20 characters" (ROLLBACK_COMPLETE); pass 20-char -> CREATE_COMPLETE`)。境界ちょうどのフィクスチャと組で、限界の位置そのものが meta.yaml から読める
29
31
  - fail テンプレートがデプロイに**成功**したら、それはドキュメント側の誤り(BROKEN-EXPECTATION)。ルールを削除し、証拠を issue に残して終了する。CloudFront では明文化された制約 9 件中 3 件がこれだった(2026-09-02)
30
32
  - **予想と違う理由**で失敗した場合(他アカウントの ARN、ドメイン所有権の検証など)は証拠にならない。サービスエラーが対象の制約そのものを名指しするまでテンプレートを作り直すか、除去できない交絡は `evidence` に明記する
31
33
  - `doc-only` は「再現に安価に作れないリソース(検証済み ACM 証明書、所有ドメイン等)が要る」場合に限る最終手段であって、まだ試していない制約への近道ではない。詳細は AGENTS.md の "A doc sentence is a hypothesis, not evidence" に従う
@@ -84,6 +84,7 @@ EOL ランタイム、廃止インスタンスタイプ、リージョン非対
84
84
  ```
85
85
  出力は 1 件 1 行(`BLOCK <file> <ruleId>/<severity>` か `clean <file>`)。
86
86
  `ERROR` / `FATAL`(`source` が `SCHEMA` か `CFN_LINT`)が出たら**その候補は捨てる**。`WARN` クラスだけ、あるいは `INFO` だけならグレーゾーンなので、上流に severity の issue を出す候補として記録し、つなぎで実装するなら `upstream: pending-engine` を付ける
87
+ - **探りのテンプレートも境界値で打つ**。重複ガードの判定は値ごとなので、限界から遠い値で探ると「エンジンが持っている定数がサービスより緩い」ケースを取り違える:スキーマの下限が 10 でサービスの下限が 20 なら、5 文字の探りは `BLOCK` されて候補ごと捨ててしまうが、19 文字の探りは `clean` で戻り、10〜19 という本物の隙間が候補として残る。実装フェーズでそのまま fail テンプレートになる値でもある(pass 側と合わせた規定は `add-preflight-rule` の手順 3)
87
88
  - **CLI のサービスモデルが API より古いことがある**(2026-09-05、`aws wafv2` は `Monetize` と `PreParseTextTransformations` を知らず ParamValidation で落ちた)。CLI が拒否するフィールドだけスタックを立てる。名前が scope / region 単位で一意なサービス(WAFv2)は、並列 bench のフィクスチャ名にルール ID を混ぜる
88
89
  - **`--cli-input-json` の blob は base64**(`SearchString` を平文で書くとクライアント側で "Invalid base64" になり、サーバに届かないまま全滅する)
89
90
  - **サービス API を直接叩けるものは先に叩く**(2026-09-05、KMS / Secrets Manager / SSM で実測)。CFN ハンドラが CreateKey / CreateAlias / ReplicateKey / GetRandomPassword / RotateSecret / PutParameter / CreateDocument / CreateMaintenanceWindow / CreateAssociation をそのまま呼ぶサービスでは、API の拒否=スタックイベントの文面で、失敗した呼び出しは何も作らないのでタダ。ハンドラ独自の検査(`SecretString` と `GenerateSecretString` の排他、`HostedRotationLambda` の transform 要否など)だけスタックを立てる
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-2089-blue\" alt=\"2089 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. 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` — 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-2198-blue\" alt=\"2198 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. 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` — 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.97",
9604
- "fingerprint": "+v5mhLKKJVAdhtpH9zG7zDXlBQAY46YwsZQU8sY9i28="
9603
+ "version": "0.0.99",
9604
+ "fingerprint": "z77LFWfrrJjWcqV745dEnEt3Xe3FOTc4/MlDXRNBILU="
9605
9605
  }
package/AGENTS.md CHANGED
@@ -16,6 +16,8 @@ Growth is the normal state. The upstream engine ships slowly and carefully by de
16
16
 
17
17
  1. **No duplication of the engine.** If the bundled engine already reports a constraint as ERROR/FATAL (schema check or built-in rule), we must not re-implement it. `test/rules.test.ts` enforces this mechanically ("does not duplicate a built-in blocker"). If that test fails for a new rule, the rule is unnecessary — delete it and record why in the PR.
18
18
  2. **Every rule ships with proof.** `templates/fail.template.json` must violate exactly this rule; `templates/pass.template.json` must be clean. `meta.yaml#repro` records how the deploy-time failure was verified (`real-deploy` / `research-case` / `doc-only` — the last one requires an explanation in `evidence`).
19
+
20
+ **Both fixtures sit on the boundary.** For an ordered constraint (a number, a length, a count) the fail template carries the *tightest violating* value and the pass template the *exact limit* — a 20-character minimum gets a 19-character fail and a 20-character pass, not 5 and 26. A slack pair proves only the direction of the rule: `count(v) < 20` still fires on a 5-character fail template when the constant is wrong (`< 10`), and a 26-character pass template stays silent even at `< 25`, so neither the constant nor the comparison operator is pinned by the fixtures. It also weakens the real-deploy gate, which is the only thing that establishes where AWS's limit actually is — a 19-character key that fails CREATE proves the documented 20, a 5-character one proves "somewhere above 5". A range the rule checks at both ends gets a resource at each end (the fixture assertion is "at least one diagnostic for this rule", so several violating resources in one fail template are fine, and a branch a single fixture cannot reach gets a targeted case in `test/rules.test.ts`). An end the engine's schema already enforces stays out of the fail template — the rule does not check it (principle 1) and the duplication guard would flag it. Constraints with no ordering — a missing property, a wrong enum member, a cross-resource mismatch — have no boundary to sit on. The evidence line records the values that were actually deployed, so it pins the boundary too: `bench 2026-09-13 us-east-1: 19-char Value -> "API Key value should be at least 20 characters" (ROLLBACK_COMPLETE); pass 20-char -> CREATE_COMPLETE`.
19
21
  3. **Upstream contribution is welcome, never a gate.** Constraints expressible in schemas or generic engine rules make good PRs to [cloudformation-validate](https://github.com/aws-cloudformation/cloudformation-validate) (open an issue first) — but a rule ships here first and never waits on one. Track status in `meta.yaml#upstream` (`none` / `pending-engine` / `engine-pr` / `retired`); the field exists so that retirement is bookkeeping rather than archaeology.
20
22
  4. **Tests are the contract.** Never merge with a red test; never weaken an assertion to make it pass. New behavior needs a new test first.
21
23
  5. **The boundary is the engine, not the CDK L2 layer.** Rules validate synthesized templates, so an L2 construct that validates (or structurally prevents) the same mistake does not make a rule redundant — L1 usage, escape hatches, `addPropertyOverride`, and externally generated templates all bypass L2. Overlapping an L2 guard is fine and expected; overlapping the bundled engine is forbidden (principle 1). L2 coverage is not a retirement trigger either — deleting a rule because an L2 construct checks it would strip the coverage from exactly the users this pack exists for. Only a layer that sees the same synthesized template retires a rule: the bundled engine, or CloudFormation's server-side validation. Noting an L2 overlap in the PR is useful context, not something to justify. See "Where this pack sits among validation layers" below.
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-2089-blue" alt="2089 bundled rules"></a>
15
+ <a href="docs/rules.md"><img src="https://img.shields.io/badge/rules-2198-blue" alt="2198 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.
package/docs/rules.md CHANGED
@@ -103,6 +103,115 @@
103
103
  | `pf-apigwv2-websocket-no-cors` | AWS::ApiGatewayV2::Api | WebSocket APIs take no CORS configuration | ERROR | none |
104
104
  | `pf-apigwv2-websocket-payload-version` | AWS::ApiGatewayV2::Integration | WebSocket AWS_PROXY integrations reject payload format 2.0 | ERROR | none |
105
105
  | `pf-apigwv2-websocket-route-selection` | AWS::ApiGatewayV2::Api | WebSocket APIs need RouteSelectionExpression | ERROR | none |
106
+ | `pf-appsync-api-additional-auth-duplicate-primary` | AWS::AppSync::GraphQLApi | An additional authentication provider may not repeat another mode | ERROR | none |
107
+ | `pf-appsync-api-cognito-requires-userpool-config` | AWS::AppSync::GraphQLApi | AMAZON_COGNITO_USER_POOLS authentication needs UserPoolConfig | ERROR | none |
108
+ | `pf-appsync-api-enhanced-metrics-values` | AWS::AppSync::GraphQLApi | DataSourceLevelMetricsBehavior takes one of two values | ERROR | pending-engine |
109
+ | `pf-appsync-api-env-var-count-max` | AWS::AppSync::GraphQLApi | An API carries at most 50 environment variables | ERROR | none |
110
+ | `pf-appsync-api-env-var-key-max-length` | AWS::AppSync::GraphQLApi | Environment variable keys are at most 64 characters | ERROR | none |
111
+ | `pf-appsync-api-env-var-key-min-length` | AWS::AppSync::GraphQLApi | Environment variable keys are at least 2 characters | ERROR | none |
112
+ | `pf-appsync-api-env-var-value-max-length` | AWS::AppSync::GraphQLApi | Environment variable values are at most 512 characters | ERROR | none |
113
+ | `pf-appsync-api-introspection-config-value` | AWS::AppSync::GraphQLApi | IntrospectionConfig takes one of ENABLED / DISABLED | ERROR | pending-engine |
114
+ | `pf-appsync-api-key-expires-max` | AWS::AppSync::ApiKey | An API key expires at most 365 days out | ERROR | none |
115
+ | `pf-appsync-api-key-expires-past` | AWS::AppSync::ApiKey | An API key expiry is an absolute Unix timestamp in seconds | ERROR | none |
116
+ | `pf-appsync-api-lambda-auth-requires-config` | AWS::AppSync::GraphQLApi | AWS_LAMBDA authentication needs LambdaAuthorizerConfig | ERROR | none |
117
+ | `pf-appsync-api-merged-requires-execution-role` | AWS::AppSync::GraphQLApi | A MERGED API needs MergedApiExecutionRoleArn | ERROR | none |
118
+ | `pf-appsync-api-oidc-issuer-scheme` | AWS::AppSync::GraphQLApi | The OIDC issuer is an https URL | ERROR | none |
119
+ | `pf-appsync-api-oidc-requires-openid-config` | AWS::AppSync::GraphQLApi | OPENID_CONNECT authentication needs OpenIDConnectConfig | ERROR | none |
120
+ | `pf-appsync-api-single-lambda-authorizer` | AWS::AppSync::GraphQLApi | An API can have only one Lambda authorizer | ERROR | none |
121
+ | `pf-appsync-api-type-value` | AWS::AppSync::GraphQLApi | ApiType takes one of GRAPHQL / MERGED | ERROR | pending-engine |
122
+ | `pf-appsync-api-userpool-default-action-with-additional` | AWS::AppSync::GraphQLApi | DefaultAction must be ALLOW when additional providers are configured | ERROR | none |
123
+ | `pf-appsync-api-visibility-value` | AWS::AppSync::GraphQLApi | Visibility takes one of GLOBAL / PRIVATE | ERROR | pending-engine |
124
+ | `pf-appsync-cache-behavior-value` | AWS::AppSync::ApiCache | ApiCachingBehavior takes one of FULL_REQUEST_CACHING / PER_RESOLVER_CACHING / OPERATION_LEVEL_CACHING | ERROR | none |
125
+ | `pf-appsync-cache-health-metrics-value` | AWS::AppSync::ApiCache | HealthMetricsConfig takes one of ENABLED / DISABLED | ERROR | none |
126
+ | `pf-appsync-cache-ttl-range` | AWS::AppSync::ApiCache | ApiCache TTL is between 1 and 3600 seconds | ERROR | none |
127
+ | `pf-appsync-cache-type-deprecated-instance` | AWS::AppSync::ApiCache | The T2 and R4 cache instance types are retired | ERROR | none |
128
+ | `pf-appsync-code-no-async` | AWS::AppSync::FunctionConfiguration<br>AWS::AppSync::Resolver | APPSYNC_JS does not support async functions | ERROR | none |
129
+ | `pf-appsync-code-no-class` | AWS::AppSync::FunctionConfiguration<br>AWS::AppSync::Resolver | APPSYNC_JS does not support class declarations | ERROR | none |
130
+ | `pf-appsync-code-no-continue` | AWS::AppSync::FunctionConfiguration<br>AWS::AppSync::Resolver | APPSYNC_JS does not support continue statements | ERROR | none |
131
+ | `pf-appsync-code-no-generator` | AWS::AppSync::FunctionConfiguration<br>AWS::AppSync::Resolver | APPSYNC_JS does not support generator functions | ERROR | none |
132
+ | `pf-appsync-code-no-increment-operator` | AWS::AppSync::FunctionConfiguration<br>AWS::AppSync::Resolver | APPSYNC_JS does not support ++ and -- | ERROR | none |
133
+ | `pf-appsync-code-no-instanceof` | AWS::AppSync::FunctionConfiguration<br>AWS::AppSync::Resolver | APPSYNC_JS does not support the instanceof operator | ERROR | none |
134
+ | `pf-appsync-code-no-promise` | AWS::AppSync::FunctionConfiguration<br>AWS::AppSync::Resolver | APPSYNC_JS does not support Promise | ERROR | none |
135
+ | `pf-appsync-code-no-regex-literal` | AWS::AppSync::FunctionConfiguration<br>AWS::AppSync::Resolver | APPSYNC_JS does not support regular expression literals | ERROR | none |
136
+ | `pf-appsync-code-no-this` | AWS::AppSync::FunctionConfiguration<br>AWS::AppSync::Resolver | APPSYNC_JS does not support this expressions | ERROR | none |
137
+ | `pf-appsync-code-no-try` | AWS::AppSync::FunctionConfiguration<br>AWS::AppSync::Resolver | APPSYNC_JS does not support try statements | ERROR | none |
138
+ | `pf-appsync-code-no-while` | AWS::AppSync::FunctionConfiguration<br>AWS::AppSync::Resolver | APPSYNC_JS does not support while loops | ERROR | none |
139
+ | `pf-appsync-code-request-response-exports-required` | AWS::AppSync::FunctionConfiguration<br>AWS::AppSync::Resolver | An APPSYNC_JS handler exports request and response | ERROR | none |
140
+ | `pf-appsync-domain-cert-region` | AWS::AppSync::DomainName | The custom domain certificate lives in us-east-1 | ERROR | none |
141
+ | `pf-appsync-ds-config-matches-type` | AWS::AppSync::DataSource | Only the configuration block matching Type may be set | ERROR | none |
142
+ | `pf-appsync-ds-delta-sync-requires-versioned` | AWS::AppSync::DataSource | DeltaSyncConfig needs a versioned table | ERROR | none |
143
+ | `pf-appsync-ds-dynamodb-region-mismatch` | AWS::AppSync::DataSource | DynamoDBConfig.AwsRegion must be a region name | ERROR | none |
144
+ | `pf-appsync-ds-dynamodb-requires-config` | AWS::AppSync::DataSource | A AMAZON_DYNAMODB data source needs DynamoDBConfig | ERROR | none |
145
+ | `pf-appsync-ds-eventbridge-requires-config` | AWS::AppSync::DataSource | A AMAZON_EVENTBRIDGE data source needs EventBridgeConfig | ERROR | none |
146
+ | `pf-appsync-ds-http-auth-type-value` | AWS::AppSync::DataSource | AuthorizationType takes AWS_IAM | ERROR | pending-engine |
147
+ | `pf-appsync-ds-http-endpoint-scheme` | AWS::AppSync::DataSource | An HTTP endpoint is an http or https URL | ERROR | none |
148
+ | `pf-appsync-ds-http-requires-config` | AWS::AppSync::DataSource | A HTTP data source needs HttpConfig | ERROR | none |
149
+ | `pf-appsync-ds-lambda-requires-config` | AWS::AppSync::DataSource | A AWS_LAMBDA data source needs LambdaConfig | ERROR | none |
150
+ | `pf-appsync-ds-lambda-requires-service-role` | AWS::AppSync::DataSource | A data source that reaches another service needs ServiceRoleArn | ERROR | none |
151
+ | `pf-appsync-ds-metrics-config-value` | AWS::AppSync::DataSource | MetricsConfig takes ENABLED / DISABLED | ERROR | pending-engine |
152
+ | `pf-appsync-ds-none-forbids-config` | AWS::AppSync::DataSource | A NONE data source takes no configuration block | ERROR | none |
153
+ | `pf-appsync-ds-opensearch-requires-config` | AWS::AppSync::DataSource | A AMAZON_OPENSEARCH_SERVICE data source needs OpenSearchServiceConfig | ERROR | none |
154
+ | `pf-appsync-ds-rds-requires-config` | AWS::AppSync::DataSource | A RELATIONAL_DATABASE data source needs RelationalDatabaseConfig | ERROR | none |
155
+ | `pf-appsync-ds-rds-source-type-value` | AWS::AppSync::DataSource | RelationalDatabaseSourceType takes RDS_HTTP_ENDPOINT | ERROR | pending-engine |
156
+ | `pf-appsync-ev-auth-provider-cognito-requires-config` | AWS::AppSync::Api | An AMAZON_COGNITO_USER_POOLS auth provider needs CognitoConfig | ERROR | none |
157
+ | `pf-appsync-ev-auth-provider-duplicate-type` | AWS::AppSync::Api | Each auth type appears once in AuthProviders | ERROR | none |
158
+ | `pf-appsync-ev-auth-provider-lambda-requires-config` | AWS::AppSync::Api | An AWS_LAMBDA auth provider needs LambdaAuthorizerConfig | ERROR | none |
159
+ | `pf-appsync-ev-auth-provider-oidc-requires-config` | AWS::AppSync::Api | An OPENID_CONNECT auth provider needs OpenIDConnectConfig | ERROR | none |
160
+ | `pf-appsync-ev-connection-auth-mode-in-providers` | AWS::AppSync::Api | ConnectionAuthModes may only use configured auth providers | ERROR | none |
161
+ | `pf-appsync-ev-publish-auth-mode-in-providers` | AWS::AppSync::Api | DefaultPublishAuthModes may only use configured auth providers | ERROR | none |
162
+ | `pf-appsync-ev-subscribe-auth-mode-in-providers` | AWS::AppSync::Api | DefaultSubscribeAuthModes may only use configured auth providers | ERROR | none |
163
+ | `pf-appsync-fn-code-and-mapping-template-exclusive` | AWS::AppSync::FunctionConfiguration | Code and mapping templates are exclusive | ERROR | none |
164
+ | `pf-appsync-fn-code-and-s3-location-exclusive` | AWS::AppSync::FunctionConfiguration | Code and CodeS3Location are exclusive | ERROR | none |
165
+ | `pf-appsync-fn-code-requires-runtime` | AWS::AppSync::FunctionConfiguration | Code needs a Runtime | ERROR | none |
166
+ | `pf-appsync-fn-data-source-exists` | AWS::AppSync::FunctionConfiguration | DataSourceName names a data source on the same API | ERROR | none |
167
+ | `pf-appsync-fn-function-version-value` | AWS::AppSync::FunctionConfiguration | FunctionVersion is 2018-05-29 | ERROR | none |
168
+ | `pf-appsync-fn-max-batch-size-requires-lambda-ds` | AWS::AppSync::FunctionConfiguration | MaxBatchSize only applies to a Lambda data source | ERROR | none |
169
+ | `pf-appsync-fn-runtime-name-value` | AWS::AppSync::FunctionConfiguration | Runtime.Name takes APPSYNC_JS | ERROR | pending-engine |
170
+ | `pf-appsync-fn-runtime-requires-code` | AWS::AppSync::FunctionConfiguration | A Runtime needs Code | ERROR | none |
171
+ | `pf-appsync-fn-runtime-version-value` | AWS::AppSync::FunctionConfiguration | The APPSYNC_JS runtime version is 1.0.0 | ERROR | none |
172
+ | `pf-appsync-fn-sync-conflict-detection-none-with-handler` | AWS::AppSync::FunctionConfiguration | ConflictDetection NONE takes no ConflictHandler | ERROR | none |
173
+ | `pf-appsync-fn-sync-conflict-handler-lambda-requires-config` | AWS::AppSync::FunctionConfiguration | A LAMBDA conflict handler needs LambdaConflictHandlerConfig | ERROR | none |
174
+ | `pf-appsync-fn-vtl-requires-function-version` | AWS::AppSync::FunctionConfiguration | A VTL function needs FunctionVersion | ERROR | none |
175
+ | `pf-appsync-ns-auth-mode-in-api-providers` | AWS::AppSync::ChannelNamespace | A namespace may only use auth modes its API configures | ERROR | none |
176
+ | `pf-appsync-ns-code-handlers-s3-exclusive` | AWS::AppSync::ChannelNamespace | CodeHandlers and CodeS3Location are exclusive | ERROR | none |
177
+ | `pf-appsync-ns-handler-code-requires-code-handlers` | AWS::AppSync::ChannelNamespace | A CODE handler needs handler code | ERROR | none |
178
+ | `pf-appsync-ns-handler-lambda-requires-config` | AWS::AppSync::ChannelNamespace | A DIRECT handler needs LambdaConfig | ERROR | none |
179
+ | `pf-appsync-ns-integration-data-source-exists` | AWS::AppSync::ChannelNamespace | A handler integration names a data source on the same API | ERROR | none |
180
+ | `pf-appsync-res-caching-ttl-range` | AWS::AppSync::Resolver | CachingConfig.Ttl is between 1 and 3600 seconds | ERROR | none |
181
+ | `pf-appsync-res-code-and-mapping-template-exclusive` | AWS::AppSync::Resolver | Code and mapping templates are exclusive | ERROR | none |
182
+ | `pf-appsync-res-code-and-s3-location-exclusive` | AWS::AppSync::Resolver | Code and CodeS3Location are exclusive | ERROR | none |
183
+ | `pf-appsync-res-code-requires-runtime` | AWS::AppSync::Resolver | Code needs a Runtime | ERROR | none |
184
+ | `pf-appsync-res-data-source-exists` | AWS::AppSync::Resolver | DataSourceName names a data source on the same API | ERROR | none |
185
+ | `pf-appsync-res-field-in-schema` | AWS::AppSync::Resolver | FieldName must exist on the type | ERROR | none |
186
+ | `pf-appsync-res-kind-value` | AWS::AppSync::Resolver | Kind takes UNIT / PIPELINE | ERROR | pending-engine |
187
+ | `pf-appsync-res-max-batch-size-requires-lambda-ds` | AWS::AppSync::Resolver | MaxBatchSize only applies to a Lambda data source | ERROR | none |
188
+ | `pf-appsync-res-metrics-config-value` | AWS::AppSync::Resolver | MetricsConfig takes ENABLED / DISABLED | ERROR | pending-engine |
189
+ | `pf-appsync-res-pipeline-forbids-data-source` | AWS::AppSync::Resolver | A PIPELINE resolver takes no DataSourceName | ERROR | none |
190
+ | `pf-appsync-res-pipeline-functions-max` | AWS::AppSync::Resolver | A pipeline runs at most 10 functions | ERROR | none |
191
+ | `pf-appsync-res-pipeline-requires-functions` | AWS::AppSync::Resolver | A PIPELINE resolver needs PipelineConfig.Functions | ERROR | none |
192
+ | `pf-appsync-res-runtime-name-value` | AWS::AppSync::Resolver | Runtime.Name takes APPSYNC_JS | ERROR | pending-engine |
193
+ | `pf-appsync-res-runtime-requires-code` | AWS::AppSync::Resolver | A Runtime needs Code | ERROR | none |
194
+ | `pf-appsync-res-runtime-version-value` | AWS::AppSync::Resolver | The APPSYNC_JS runtime version is 1.0.0 | ERROR | none |
195
+ | `pf-appsync-res-sync-conflict-detection-none-with-handler` | AWS::AppSync::Resolver | ConflictDetection NONE takes no ConflictHandler | ERROR | none |
196
+ | `pf-appsync-res-sync-conflict-handler-lambda-requires-config` | AWS::AppSync::Resolver | A LAMBDA conflict handler needs LambdaConflictHandlerConfig | ERROR | none |
197
+ | `pf-appsync-res-type-field-in-schema` | AWS::AppSync::Resolver | TypeName must exist in the schema | ERROR | none |
198
+ | `pf-appsync-res-unit-forbids-pipeline-config` | AWS::AppSync::Resolver | A UNIT resolver takes no PipelineConfig | ERROR | none |
199
+ | `pf-appsync-res-unit-requires-data-source` | AWS::AppSync::Resolver | A UNIT resolver needs DataSourceName | ERROR | none |
200
+ | `pf-appsync-schema-definition-or-s3-required` | AWS::AppSync::GraphQLSchema | A schema needs Definition or DefinitionS3Location | ERROR | none |
201
+ | `pf-appsync-schema-definition-s3-exclusive` | AWS::AppSync::GraphQLSchema | Definition and DefinitionS3Location are exclusive | ERROR | none |
202
+ | `pf-appsync-schema-duplicate-field` | AWS::AppSync::GraphQLSchema | A field name may only appear once per type | ERROR | none |
203
+ | `pf-appsync-schema-duplicate-schema-keyword` | AWS::AppSync::GraphQLSchema | A schema declares the schema block once | ERROR | none |
204
+ | `pf-appsync-schema-duplicate-type` | AWS::AppSync::GraphQLSchema | A type may only be declared once | ERROR | none |
205
+ | `pf-appsync-schema-input-type-as-output` | AWS::AppSync::GraphQLSchema | An input type cannot be a field type | ERROR | none |
206
+ | `pf-appsync-schema-interface-not-implemented` | AWS::AppSync::GraphQLSchema | A type must declare every field of the interfaces it implements | ERROR | none |
207
+ | `pf-appsync-schema-object-as-argument` | AWS::AppSync::GraphQLSchema | An argument type must be an input type | ERROR | none |
208
+ | `pf-appsync-schema-requires-query-root` | AWS::AppSync::GraphQLSchema | A schema needs a query root type | ERROR | none |
209
+ | `pf-appsync-schema-root-type-missing` | AWS::AppSync::GraphQLSchema | The schema block may only name declared types | ERROR | none |
210
+ | `pf-appsync-schema-undefined-type-reference` | AWS::AppSync::GraphQLSchema | Every field type must be declared in the schema | ERROR | none |
211
+ | `pf-appsync-schema-unknown-scalar` | AWS::AppSync::GraphQLSchema | Only AppSync's own AWS scalars exist | ERROR | none |
212
+ | `pf-appsync-source-api-merge-type-value` | AWS::AppSync::SourceApiAssociation | MergeType is AUTO_MERGE or MANUAL_MERGE | ERROR | pending-engine |
213
+ | `pf-appsync-source-api-merged-not-source` | AWS::AppSync::SourceApiAssociation | A merged API cannot be a source API | ERROR | none |
214
+ | `pf-appsync-source-api-not-merged-target` | AWS::AppSync::SourceApiAssociation | The association target must be a MERGED API | ERROR | none |
106
215
  | `pf-asg-az-xor-azid` | AWS::AutoScaling::AutoScalingGroup | A group names zones by name or by id, not both | ERROR | none |
107
216
  | `pf-asg-capacity-reservation-none-target-exclusive` | AWS::AutoScaling::AutoScalingGroup | A capacity reservation target needs the capacity-reservations-only preference | ERROR | none |
108
217
  | `pf-asg-cooldown-non-negative` | AWS::AutoScaling::AutoScalingGroup | Cooldown cannot be negative | 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.97" };
20
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-preflight.Preflight", version: "0.0.99" };
21
21
  /**
22
22
  * Register the cdk-preflight rules on an App or Stage.
23
23
  */