cdk-preflight 0.0.106 → 0.0.108
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/.claude/skills/add-preflight-rule/SKILL.md +5 -0
- package/.claude/skills/find-preflight-rules/SKILL.md +5 -0
- package/.claude/skills/run-preflight-issue/SKILL.md +133 -0
- package/.jsii +3 -3
- package/AGENTS.md +29 -0
- package/README.md +1 -1
- package/docs/rules.md +0 -2
- package/lib/index.js +1 -1
- package/lib/rules.generated.js +4 -26
- package/package.json +1 -1
|
@@ -35,6 +35,11 @@ cdk-preflight のルール追加パイプライン。AGENTS.md の設計原則
|
|
|
35
35
|
|
|
36
36
|
## セッションの切り方(コンテキスト予算)
|
|
37
37
|
|
|
38
|
+
**`run-preflight-issue`(オーケストレーター)経由で走っている場合、⑤⑥⑦ は 1 スライス = 1 サブエージェントが丸ごと持つ。**
|
|
39
|
+
`/clear` は要らず、スライスの切り方(20〜25 本・候補 id のプレフィックス境界・同一サービスは直列)と
|
|
40
|
+
push / PR の承認待ちはオーケストレーター側の責務。**自分がそのサブエージェントである場合、さらにエージェントを spawn せず、
|
|
41
|
+
実機で落ちたルールはその場で削って報告する。** このスキルを人間が直接使うときだけ、下の `/clear` 運用に従う。
|
|
42
|
+
|
|
38
43
|
API コストは **`往復回数 × 平均コンテキスト長`** でほぼ決まる(実測 2026-09-08、全 16 セッション集計: cache_read が入力の 98%、平均 258k tok/往復。平均 372k のセッションはルール 1 本 $5.2、213k で切ったセッションは $1.7)。**1 サービスぶんを 1 セッションで通さない**。`find-preflight-rules` から `candidates.json` を受け取り、下の境界で `/clear` して scratchpad の `<service>/` 配下のファイルだけを引き継ぐ:
|
|
39
44
|
|
|
40
45
|
| フェーズ | 入口 | 出口 |
|
|
@@ -93,6 +93,11 @@ EOL ランタイム、廃止インスタンスタイプ、リージョン非対
|
|
|
93
93
|
|
|
94
94
|
## セッションの切り方(コンテキスト予算)
|
|
95
95
|
|
|
96
|
+
**`run-preflight-issue`(オーケストレーター)経由で走っている場合、フェーズ境界 = サブエージェント境界なので `/clear` は要らない。**
|
|
97
|
+
オーケストレーターが成果物を読まないので親のコンテキストが伸びず、下の表の受け渡しはそのままサブエージェントへの
|
|
98
|
+
プロンプトとファイルで実現される。**自分がそのサブエージェントである場合、さらにエージェントを spawn しない。**
|
|
99
|
+
このスキルを人間が直接使うときだけ、下の `/clear` 運用に従う。
|
|
100
|
+
|
|
96
101
|
このパイプラインの API コストは **`往復回数 × 平均コンテキスト長`** でほぼ決まる。2026-09-08 に本プロジェクトの全トランスクリプトを集計した実測(16 セッション / 3,352 往復 / cache_read 850 Mtok / 概算 $1.9k):
|
|
97
102
|
|
|
98
103
|
- **cache_read が入力トークンの 98%**。**1 往復あたりの固定費がコンテキスト長に比例する**ので、長いセッションを続けること自体が課金される
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: run-preflight-issue
|
|
3
|
+
description: rule-discovery issue 1 本を 1 指示で完走させるオーケストレーター。棚卸し/API 一次選別/実装スライスをそれぞれ別のサブエージェントに投げ、報告と考慮事項を受け取って次のエージェントに渡し、進捗を台帳に書く。自分は成果物の中身を読まないのでコンテキストが膨らまない。issue 番号だけ渡して起動する。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# run-preflight-issue
|
|
7
|
+
|
|
8
|
+
`/run-preflight-issue <issue 番号 | next> [--from=A|B|C]`
|
|
9
|
+
|
|
10
|
+
rule-discovery issue 1 本(例 #64 Glue + Athena)を、**棚卸しから PR 承認待ちまで 1 指示で**通す。各フェーズは
|
|
11
|
+
`find-preflight-rules` / `add-preflight-rule` をそのまま読むサブエージェントが実行し、このスキルを走らせている
|
|
12
|
+
セッションは**オーケストレーター**として指示・検証・受け渡しだけを行う。
|
|
13
|
+
|
|
14
|
+
## 鉄則:オーケストレーターはファイルの中身を開かない
|
|
15
|
+
|
|
16
|
+
このやり方の価値は**コンテキストを汚さないこと**だけであって、それ以外の利点は無い。だから次を破ると全部無駄になる:
|
|
17
|
+
|
|
18
|
+
- **サブエージェントが作った成果物を `cat` / `Read` しない。** 許されるのは `wc -l`、`grep -c`、`ls`、`head -20 handoff.md` だけ
|
|
19
|
+
- GitHub への投稿は**本文を読まずに** `gh issue comment <n> --body-file <path>` で渡す(28KB のコメントでも 0 トークン)
|
|
20
|
+
- サブエージェントの報告テキストは context に入るので、**報告の書式を指定して短く保たせる**(下記「報告の型」)
|
|
21
|
+
- ドキュメント取得・テンプレート生成・ログ読みは全部サブエージェント側の仕事。オーケストレーターは 1 行も読まない
|
|
22
|
+
|
|
23
|
+
コストの実測(2026-09-08 集計)は `find-preflight-rules` の「セッションの切り方」にある。要点は
|
|
24
|
+
**cache_read が入力の 98%**、つまり長いコンテキストを抱えたまま往復を続けること自体が課金される、という点だけ。
|
|
25
|
+
サブエージェントは cold start なので、この固定費を親から切り離せる。
|
|
26
|
+
|
|
27
|
+
## 起動と再開
|
|
28
|
+
|
|
29
|
+
1. 引数が `next` なら #91(rule discovery queue)の未着手の先頭を拾う。issue 番号ならそれ。
|
|
30
|
+
2. 作業ディレクトリは `~/cdk-preflight-surveys/<service>-<issue>/`(例 `glue-athena-64/`)。無ければ作る。
|
|
31
|
+
3. **現在フェーズは `head -20 handoff.md` の台帳から判定する**(無ければ A から)。`--from` はその上書き。
|
|
32
|
+
4. issue に「着手します(日付)+スコープと進め方」のコメントを投稿する(キューの運用メモが着手記録を求めている)。
|
|
33
|
+
|
|
34
|
+
## 台帳(`handoff.md`)
|
|
35
|
+
|
|
36
|
+
`handoff.md` の**先頭**に必ずこの表を置く。**この表を書き換えるのはオーケストレーターだけ**で、サブエージェントは
|
|
37
|
+
自分のフェーズの節を下に追記するだけ。`/clear` されても落ちても、`head -20` だけで再開できるのが唯一の目的。
|
|
38
|
+
|
|
39
|
+
```markdown
|
|
40
|
+
| フェーズ | 状態 | エージェント | 成果物 | 人間待ち |
|
|
41
|
+
|---|---|---|---|---|
|
|
42
|
+
| A 棚卸し+重複ガード | done | ae888…(A) | candidates.json / guard-out.txt | - |
|
|
43
|
+
| B API 一次選別 | done | 3f12…(B) | api-triage.tsv / api-class.json | - |
|
|
44
|
+
| C1 実装(athena 15 本) | done | 9ab0…(C1) | rules/athena/*, branch feat/athena-rules | push/PR 承認 |
|
|
45
|
+
| C2 実装(glue job 系) | todo | - | - | - |
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
状態は `todo` / `running` / `done` / `blocked` の 4 つ。`blocked` には理由を 1 行で添える。
|
|
49
|
+
|
|
50
|
+
## フェーズとエージェントの割り当て
|
|
51
|
+
|
|
52
|
+
| エージェント | 読ませる手順書 | 入口 | 出口 |
|
|
53
|
+
|---|---|---|---|
|
|
54
|
+
| **A 調査** | `find-preflight-rules` 手順 1〜3 | サービス名 / issue 本文 | `inventory.md` / `candidates.json` / `guard-out.txt` / `issue-comment.md` |
|
|
55
|
+
| **B API 一次選別** | `find-preflight-rules` 手順 3 の「サービス API を直接叩けるものは先に叩く」 | `candidates.json` / `base.py` | `api-triage.tsv`(id / クラス / 判定 / 実機メッセージ / 制約 / レンズ)/ `api-class.json` / `issue-comment-api.md` |
|
|
56
|
+
| **C1..Cn 実装** | `add-preflight-rule` 手順 2〜6 | `api-triage.tsv` の該当スライス | `rules/<svc>/*` / `meta.yaml#repro` / ブランチ+コミット |
|
|
57
|
+
|
|
58
|
+
- **A を 1 個にまとめる**のは、棚卸し・仮説・ガードが同じドキュメント知識を共有するから。ここを割ると 2 個目が読み直す
|
|
59
|
+
- **B を必ず分ける**のは、AWS 認証と課金物という A とは別種の危険があるから。B の失敗は金を使う
|
|
60
|
+
- **C を割らない**(生成→ローカルゲート→実機ゲート→meta.yaml→コミットを 1 エージェントに持たせる)のは所有権の問題。
|
|
61
|
+
実機で落ちたルールはその場で削るのが正しく、⑥だけ別エージェントにすると⑤の成果物を他人が直す形になる
|
|
62
|
+
- **issue コメントの投稿はオーケストレーターがやる**(A と B の直後)。サブエージェントに `gh` を握らせない
|
|
63
|
+
|
|
64
|
+
## サブエージェントに渡すプロンプトの必須項目
|
|
65
|
+
|
|
66
|
+
毎回この 7 つを入れる。1 つでも抜くと今までに踏んだ穴を踏み直す:
|
|
67
|
+
|
|
68
|
+
1. **読ませるスキル名**を明示(「最初に `add-preflight-rule` スキルを Skill ツールで起動して従え」)。
|
|
69
|
+
同時に**起動してはいけないスキル**も書く(実装エージェントに `find-preflight-rules` を起動させない)
|
|
70
|
+
2. **入力ファイルの絶対パスと 1 行説明**。そして「**最初に `inventory.md` を読め**」。
|
|
71
|
+
ファイルに書いてあるだけでは読まれない
|
|
72
|
+
3. **前フェーズの「考慮事項」「申し送り」を逐語でコピー**する。台帳を参照させるのではなく、プロンプトに貼る
|
|
73
|
+
4. **課金物の禁止**: 禁止リソース型を名指しし、「**create API を呼ぶ前に落とす**」「pass フィクスチャを作らない
|
|
74
|
+
(`--fail-only`)」「既存の無料下敷きは消さない」。`絶対に課金パネルのリソースを作らない`はユーザーの明示指示
|
|
75
|
+
5. **git の縛り**: `main` に直接コミットしない / ブランチを切る / **push も `gh pr create` もしない** /
|
|
76
|
+
コミットメッセージに attribution 行を入れない
|
|
77
|
+
6. **報告の型**(下記)と「日本語で」
|
|
78
|
+
7. **迷ったら減らす方向に倒せ**。中途半端なルールを 1 本入れるより、確実な本数だけ入れて残りを報告させる
|
|
79
|
+
|
|
80
|
+
### 報告の型
|
|
81
|
+
|
|
82
|
+
サブエージェントの報告は親の context に入る。4 見出しだけを短く書かせ、詳細は `handoff.md` に追記させる:
|
|
83
|
+
|
|
84
|
+
- **結果**(本数・ブランチ名・テスト結果)
|
|
85
|
+
- **落としたものと理由**
|
|
86
|
+
- **考慮事項**(次のフェーズが知らないと踏む穴。オーケストレーターが次のプロンプトに逐語でコピーする)
|
|
87
|
+
- **人間の判断が必要**(ハード関門でなくてよい。台帳に溜める)
|
|
88
|
+
|
|
89
|
+
## 受け取ったら必ずやる検証
|
|
90
|
+
|
|
91
|
+
報告を信用しない。**安いものだけ自分で回す**(2026-09-13 実測: 報告の「エンジンは W3030 止まり」が誤りだった。
|
|
92
|
+
ただし親の前提の方が間違っていたので、食い違ったら両方を疑う):
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
ls rules/<svc> | wc -l # 本数が報告と一致するか
|
|
96
|
+
npx ts-node --transpile-only --project test/tsconfig.json scripts/rule-check.ts check <svc> # 0 NG か
|
|
97
|
+
grep -rl '<禁止リソース型>' rules/<svc> | wc -l # 課金物が 0 件か
|
|
98
|
+
git log --oneline -1 && git branch --show-current # コミットがあり main でないか
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
B の後は課金物の実在確認も回す(例 `aws athena list-capacity-reservations`)。**食い違ったら同じエージェントに
|
|
102
|
+
`SendMessage` で差し戻す** — コンテキストが残っているので cold start より圧倒的に安い。3 往復で直らなければ人間に上げる。
|
|
103
|
+
|
|
104
|
+
## スライスの切り方
|
|
105
|
+
|
|
106
|
+
- 1 スライス **20〜25 本**まで、**候補 id のプレフィックス境界**で割る(実測: Athena 15 本で 20 万トークン / 55 分)
|
|
107
|
+
- 同一サービスのスライスは**直列**。`rules/_lib/<svc>.rego` を 2 エージェントが同時に触ると必ず衝突する
|
|
108
|
+
- 別サービスなら並列可。そのときだけ Agent の `isolation: "worktree"` を使う
|
|
109
|
+
(`node_modules` と `bundle-rules` の初回セットアップが重いので、必要なときだけ)
|
|
110
|
+
- A の報告にスライス案があればそれを採用する(サービス構造を見ているのは A)
|
|
111
|
+
|
|
112
|
+
## 関門
|
|
113
|
+
|
|
114
|
+
**自動でやってよい**: issue コメントの投稿(着手・調査結果・API 結果)、実機再現ゲート(無料〜数円のスタックを多数作る)、
|
|
115
|
+
ブランチへのコミット。
|
|
116
|
+
|
|
117
|
+
**止まって人間に聞く**:
|
|
118
|
+
|
|
119
|
+
- `git push` と `gh pr create` — レビューは他人の時間を使う。ここで**台帳に溜めた「人間の判断が必要」も一緒に出す**
|
|
120
|
+
- 課金リソースが必要だと判明したとき(作らずに報告して止まる)
|
|
121
|
+
- `.claude/settings*.json` の permission を足したくなったとき(**自分で書き換えない**)
|
|
122
|
+
|
|
123
|
+
**絶対にしない**: 課金リソースの作成、issue の close、#91 のチェックボックス操作(PR マージが人間の手なので、
|
|
124
|
+
その先は全部人間の仕事)、既存の無料下敷き(`pfdb` / `pfwg` / `cdkpf-*-probe` ロールやバケット)の削除。
|
|
125
|
+
|
|
126
|
+
## やらないこと
|
|
127
|
+
|
|
128
|
+
- **成果物のレビュー**。読んだ時点でオーケストレーターのコンテキストが調査セッション 1 本ぶんに膨らむ。
|
|
129
|
+
品質はサブエージェント側の手順書(`add-preflight-rule` の境界値規定・実機ゲート)と上の機械的検証で担保する
|
|
130
|
+
- **フェーズごとにモデルを下げる**のは既定ではやらない。効いているのは「拒否メッセージ 97 本を 1 行ずつ読んで
|
|
131
|
+
候補の制約を名指ししているか判定する」「境界値の rego を詰める」という判断の質で、そこはケチらない。
|
|
132
|
+
実験するなら B から(`Agent` の `model` 引数)
|
|
133
|
+
- **人間の判断待ちで全体を止める**。ハード関門(push/PR・課金・permission)以外は台帳に溜めて先へ進む
|
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-2197-blue\" alt=\"2197 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-2195-blue\" alt=\"2195 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.
|
|
9604
|
-
"fingerprint": "
|
|
9603
|
+
"version": "0.0.108",
|
|
9604
|
+
"fingerprint": "jx+KXxLrGgCfxpeHg37Rbq+pvn7ZZCfWcLHRIh5VB2U="
|
|
9605
9605
|
}
|
package/AGENTS.md
CHANGED
|
@@ -22,6 +22,8 @@ Growth is the normal state. The upstream engine ships slowly and carefully by de
|
|
|
22
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.
|
|
23
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.
|
|
24
24
|
|
|
25
|
+
6. **The threshold is a hard limit, not an adjustable quota.** A rule may only assert a number that no account can change. If Service Quotas lists the limit as `Adjustable: true`, an account that has raised it deploys the template fine and the rule is simply wrong there — a false positive we cannot detect from the template, and the one kind of error that makes users switch the pack off. Check before writing the rule: `aws service-quotas list-service-quotas --service-code <code> --query 'Quotas[?Adjustable==`true`]'`. The bench account having the default value is not evidence of a hard limit; it is evidence of nothing. Limits that a quota increase cannot raise are fair game — say so in the rego comment, because the next reader will wonder.
|
|
26
|
+
|
|
25
27
|
## Where this pack sits among validation layers
|
|
26
28
|
|
|
27
29
|
Five other validation layers sit around a CDK app. Exactly one of them is a boundary for this pack, and the same one is the only trigger for retiring a rule; the relationships are:
|
|
@@ -102,6 +104,33 @@ test/ # 4 layers: rules / loader / structure / cli
|
|
|
102
104
|
bench/ # real-deploy verification (needs an AWS account; not part of CI)
|
|
103
105
|
```
|
|
104
106
|
|
|
107
|
+
## Working a discovery issue (the skills)
|
|
108
|
+
|
|
109
|
+
Three skills in `.claude/skills/` cover the work end to end. Pick the entry point by what you have:
|
|
110
|
+
|
|
111
|
+
| You have | Skill | What it does |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| An issue number from the queue (#91) | **`run-preflight-issue`** | Orchestrates the whole issue. Dispatches each phase to a separate subagent and never opens a deliverable itself |
|
|
114
|
+
| A service but no candidates yet | `find-preflight-rules` | Survey: inventory → 6 lenses → duplication guard → candidate checklist on the issue |
|
|
115
|
+
| One constraint, or a candidate list | `add-preflight-rule` | Implement: rule.rego + fixtures → local gate → real-deploy gate → `meta.yaml` → commit |
|
|
116
|
+
|
|
117
|
+
`/run-preflight-issue <issue number | next> [--from=A|B|C]` is the normal way in — `next` takes the first unstarted
|
|
118
|
+
item off #91, and the phase is otherwise read from the ledger at the top of `~/cdk-preflight-surveys/<svc>-<issue>/handoff.md`,
|
|
119
|
+
so a cleared or crashed session resumes from `head -20`. Phases map to agents as **A** survey + duplication guard,
|
|
120
|
+
**B** API-direct triage (kept separate: it needs AWS credentials and can spend money), **C1..Cn** one implementation
|
|
121
|
+
slice each (20–25 rules, split on candidate-id prefix, serial within a service so two agents never fight over
|
|
122
|
+
`rules/_lib/<service>.rego`).
|
|
123
|
+
|
|
124
|
+
Why the indirection: `cache_read` is 98% of input tokens, so a phase costs whatever parent context it drags along.
|
|
125
|
+
A cold subagent drops that fixed cost — and reading its output in the parent puts the cost straight back, which is why
|
|
126
|
+
the orchestrator is forbidden from opening deliverables (`wc -l`, `grep -c`, `gh issue comment --body-file`, nothing more).
|
|
127
|
+
It verifies each report with four cheap mechanical checks instead, and re-dispatches to the same agent when they disagree.
|
|
128
|
+
|
|
129
|
+
Human gates are explicit: posting issue comments and running the real-deploy gate are automatic; **`git push` and
|
|
130
|
+
`gh pr create` stop for approval** (soft judgement calls are batched and presented there); billable resources are refused
|
|
131
|
+
before the create call; and the orchestrator never edits permission settings, closes an issue, or ticks the queue.
|
|
132
|
+
If you are a subagent running one of these phases, do not spawn further agents.
|
|
133
|
+
|
|
105
134
|
## Adding a rule (the pipeline)
|
|
106
135
|
|
|
107
136
|
1. Identify a constraint that fails only at deploy time (doc page, API error message, war story).
|
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-
|
|
15
|
+
<a href="docs/rules.md"><img src="https://img.shields.io/badge/rules-2195-blue" alt="2195 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
|
@@ -903,7 +903,6 @@
|
|
|
903
903
|
| `pf-dynamodb-duplicate-attribute-definitions` | AWS::DynamoDB::Table | AttributeDefinitions must not define the same attribute twice | ERROR | none |
|
|
904
904
|
| `pf-dynamodb-duplicate-index-name` | AWS::DynamoDB::Table | Secondary index names must be unique | ERROR | none |
|
|
905
905
|
| `pf-dynamodb-global-table-attribute-definitions` | AWS::DynamoDB::GlobalTable | GlobalTable AttributeDefinitions must match the key schemas exactly | ERROR | none |
|
|
906
|
-
| `pf-dynamodb-global-table-gsi-count` | AWS::DynamoDB::GlobalTable | A global table can carry at most 20 global secondary indexes | ERROR | none |
|
|
907
906
|
| `pf-dynamodb-global-table-gsi-provisioned-write-settings` | AWS::DynamoDB::GlobalTable | Each GSI of a PROVISIONED GlobalTable needs WriteProvisionedThroughputSettings | ERROR | none |
|
|
908
907
|
| `pf-dynamodb-global-table-key-schema-shape` | AWS::DynamoDB::GlobalTable | GlobalTable KeySchema must be [HASH] or [HASH, RANGE] | ERROR | none |
|
|
909
908
|
| `pf-dynamodb-global-table-lsi-attribute-definitions` | AWS::DynamoDB::GlobalTable | GlobalTable LSI key attributes must be defined in AttributeDefinitions | ERROR | none |
|
|
@@ -929,7 +928,6 @@
|
|
|
929
928
|
| `pf-dynamodb-global-table-witness-requires-mrsc` | AWS::DynamoDB::GlobalTable | GlobalTableWitnesses only exists for MRSC global tables | ERROR | none |
|
|
930
929
|
| `pf-dynamodb-global-table-write-provisioned-with-ppr` | AWS::DynamoDB::GlobalTable | WriteProvisionedThroughputSettings cannot be used with PAY_PER_REQUEST | ERROR | none |
|
|
931
930
|
| `pf-dynamodb-gsi-billing-throughput` | AWS::DynamoDB::Table | GSI ProvisionedThroughput must match the table BillingMode | ERROR | none |
|
|
932
|
-
| `pf-dynamodb-gsi-count` | AWS::DynamoDB::Table | A table can carry at most 20 global secondary indexes | ERROR | none |
|
|
933
931
|
| `pf-dynamodb-gsi-projection-nonkey` | AWS::DynamoDB::Table | NonKeyAttributes goes with INCLUDE, and only with INCLUDE | ERROR | none |
|
|
934
932
|
| `pf-dynamodb-import-csv-delimiter` | AWS::DynamoDB::Table | A CSV import delimiter is a single character from , ; : | tab space | ERROR | none |
|
|
935
933
|
| `pf-dynamodb-import-format-options` | AWS::DynamoDB::Table | InputFormatOptions only applies to CSV imports | 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.
|
|
20
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-preflight.Preflight", version: "0.0.108" };
|
|
21
21
|
/**
|
|
22
22
|
* Register the cdk-preflight rules on an App or Stage.
|
|
23
23
|
*/
|