flecto 2.0.0 → 2.1.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,103 @@
1
+ # Changelog
2
+
3
+ All notable changes to Flecto will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog], and this project adheres to
6
+ [Semantic Versioning].
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [2.1.0] - 2026-07-24
11
+
12
+ ### Added
13
+
14
+ - Default-on array identity matching with auto-detect of unique `id`, then
15
+ `name`. Escape hatch: `--no-array-id` or `"arrayId": false` in `.flectorc`.
16
+ Custom keys still work via `--array-id-key`. ([#6])
17
+ - `flecto history` for local snapshot drift baselines (`--limit`). ([#7])
18
+ - Richer declarative policy predicates: `beforeEquals`, `beforeIn` / `afterIn`,
19
+ `beforeTruthy` / `afterTruthy`, `afterMatches`, `numericDelta`,
20
+ `match.pathEquals` / `match.pathPrefix`, and `allOf` / `anyOf`. ([#34])
21
+ - Built-in `compose` and `node-runtime` policy packs. ([#8])
22
+ - JSON Schema + load-time validation for policy packs
23
+ (`schemas/flecto-policy-pack-2.0.json`). ([#36])
24
+ - `flecto policies list` (+ `--json`) for pack discovery. ([#37])
25
+ - `flecto policies test <fixtureDir>` fixture harness for packs/plugins. ([#38])
26
+ - Per-profile `severityRemap` to raise, lower, or silence pack rules without
27
+ forking. ([#39])
28
+ - Reusable GitHub Action wrapper for `flecto ci`
29
+ (`.github/actions/flecto-ci`). ([#9])
30
+ - Policy pack + plugin authoring guides, cookbook, and examples. ([#32], [#35])
31
+ - `CHANGELOG.md` with v2.1 migration notes. ([#33])
32
+
33
+ ### Changed
34
+
35
+ - Node.js requirement raised to **>=20.19.0** (matches chokidar 5). CI matrix
36
+ is 20/22/24; publish uses Node 22. ([#22], [#27])
37
+ - `flecto ci` and `flecto watch --snapshot` fail closed when every target is
38
+ missing or unsupported. Pass `--allow-empty` to permit an empty run.
39
+ ([#20], [#29], [#40])
40
+ - Only options explicitly set on the CLI override `.flectorc` profiles
41
+ (Commander defaults no longer wipe profile settings). ([#19], [#31])
42
+ - Watch mode fails closed on policy pack/plugin load or evaluation errors,
43
+ independent of `--on-alert-failure`. ([#25])
44
+ - Secret masking recursively redacts nested secret values when enabled. ([#24])
45
+ - Dangerous-toggle rules treat stringy truthy values (`true` / `1` / `yes`) as
46
+ enabled, so `.env` / INI configs are covered. ([#23])
47
+
48
+ ### Fixed
49
+
50
+ - `arrayIgnoreOrder` no longer false-positives on object key order or throws on
51
+ non-JSON values such as `undefined`. ([#21])
52
+ - `fireAlerts` preserves its `{ ok }` result and surfaces queue errors; watch
53
+ consumes rejected alert handlers safely. ([#26])
54
+ - GitHub annotation output escapes `%`, newlines, commas, and colons per
55
+ workflow-command rules. ([#28])
56
+ - Removed leftover `.sentinel-snapshots/` gitignore entry. ([#30])
57
+
58
+ ### Migration notes
59
+
60
+ - **Array identity is on by default.** Diff paths may change from index-based
61
+ (`services[0].…`) to identity-based (`services["api"].…`). Review snapshots,
62
+ CI baselines, and any automation that consumes diff paths before upgrading.
63
+ - To keep 2.0-style index-based array diffs: `--no-array-id` or
64
+ `"arrayId": false` in `.flectorc`.
65
+ - **Node 18 is no longer supported.** Use Node.js 20.19.0 or newer.
66
+ - Recursive masking only affects output when secret masking is enabled, but
67
+ nested secret values previously visible in terminal/webhook payloads are now
68
+ redacted.
69
+ - `.flectorc` profile settings (for example `mode`, `failOn`, `format`) now
70
+ apply when you omit the corresponding CLI flags.
71
+ - Misconfigured policy packs/plugins cause `watch` to exit non-zero instead of
72
+ continuing with no policies.
73
+
74
+ [Unreleased]: https://github.com/myselfsiddharth/Flecto/compare/v2.1.0...HEAD
75
+ [2.1.0]: https://github.com/myselfsiddharth/Flecto/compare/v2.0.0...v2.1.0
76
+ [#6]: https://github.com/myselfsiddharth/Flecto/issues/6
77
+ [#7]: https://github.com/myselfsiddharth/Flecto/issues/7
78
+ [#8]: https://github.com/myselfsiddharth/Flecto/issues/8
79
+ [#9]: https://github.com/myselfsiddharth/Flecto/issues/9
80
+ [#19]: https://github.com/myselfsiddharth/Flecto/issues/19
81
+ [#20]: https://github.com/myselfsiddharth/Flecto/issues/20
82
+ [#21]: https://github.com/myselfsiddharth/Flecto/issues/21
83
+ [#22]: https://github.com/myselfsiddharth/Flecto/issues/22
84
+ [#23]: https://github.com/myselfsiddharth/Flecto/issues/23
85
+ [#24]: https://github.com/myselfsiddharth/Flecto/issues/24
86
+ [#25]: https://github.com/myselfsiddharth/Flecto/issues/25
87
+ [#26]: https://github.com/myselfsiddharth/Flecto/issues/26
88
+ [#27]: https://github.com/myselfsiddharth/Flecto/issues/27
89
+ [#28]: https://github.com/myselfsiddharth/Flecto/issues/28
90
+ [#29]: https://github.com/myselfsiddharth/Flecto/issues/29
91
+ [#30]: https://github.com/myselfsiddharth/Flecto/issues/30
92
+ [#31]: https://github.com/myselfsiddharth/Flecto/issues/31
93
+ [#32]: https://github.com/myselfsiddharth/Flecto/issues/32
94
+ [#33]: https://github.com/myselfsiddharth/Flecto/issues/33
95
+ [#34]: https://github.com/myselfsiddharth/Flecto/issues/34
96
+ [#35]: https://github.com/myselfsiddharth/Flecto/issues/35
97
+ [#36]: https://github.com/myselfsiddharth/Flecto/issues/36
98
+ [#37]: https://github.com/myselfsiddharth/Flecto/issues/37
99
+ [#38]: https://github.com/myselfsiddharth/Flecto/issues/38
100
+ [#39]: https://github.com/myselfsiddharth/Flecto/issues/39
101
+ [#40]: https://github.com/myselfsiddharth/Flecto/pull/40
102
+ [Keep a Changelog]: https://keepachangelog.com/en/1.1.0/
103
+ [Semantic Versioning]: https://semver.org/spec/v2.0.0.html
package/README.md CHANGED
@@ -1,21 +1,56 @@
1
- # Flecto
1
+ <p align="center">
2
+ <img src="docs/assets/flecto-hero.png" alt="Flecto — semantic config watcher" width="920"/>
3
+ </p>
2
4
 
3
- **Flecto watches your config files and tells you exactly what changed — in plain English.**
5
+ <h1 align="center">Flecto</h1>
4
6
 
5
- No more staring at raw line diffs. When your `.env`, `YAML`, `JSON`, `TOML`, or `INI` file changes, Flecto shows you what actually happened:
7
+ <p align="center">
8
+ <strong>Config changes, in plain English — with risk flags built in.</strong><br/>
9
+ Watch · Diff · Policy · CI · Webhooks
10
+ </p>
6
11
 
7
- ```
8
- [10:42:31] config/prod.yaml 3 changes
9
- ~ database.pool_size: 5 → 20
10
- + feature_flags.dark_mode: true
11
- - deprecated.old_key
12
- ```
12
+ <p align="center">
13
+ <a href="https://www.npmjs.com/package/flecto"><img alt="npm" src="https://img.shields.io/npm/v/flecto?style=flat-square&color=34d399&labelColor=0b1220"/></a>
14
+ <a href="https://github.com/myselfsiddharth/Flecto/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/myselfsiddharth/Flecto/ci.yml?branch=main&style=flat-square&label=CI&labelColor=0b1220"/></a>
15
+ <a href="LICENSE"><img alt="MIT" src="https://img.shields.io/badge/license-MIT-8fa3bf?style=flat-square&labelColor=0b1220"/></a>
16
+ <a href="https://github.com/myselfsiddharth/Flecto/stargazers"><img alt="Stars" src="https://img.shields.io/github/stars/myselfsiddharth/Flecto?style=flat-square&color=fbbf24&labelColor=0b1220"/></a>
17
+ </p>
18
+
19
+ <p align="center">
20
+ <a href="https://github.com/myselfsiddharth/Flecto/stargazers">⭐ Star this repo</a> if Flecto saves you from a noisy config diff — it helps others find the project.
21
+ </p>
22
+
23
+ <p align="center">
24
+ <img src="docs/assets/flecto-demo.png" alt="Flecto watch demo in the terminal" width="920"/>
25
+ </p>
26
+
27
+ <p align="center">
28
+ <img src="docs/assets/demo-watch.svg" alt="Animated Flecto watch output" width="920"/>
29
+ </p>
13
30
 
14
31
  ---
15
32
 
16
- ## Why Flecto?
33
+ ## Why teams use Flecto
34
+
35
+ Line diffs lie about config. Formatting churn, key reorders, and “small” YAML edits hide the changes that actually matter in production.
36
+
37
+ **Flecto** turns structured config into semantic events:
17
38
 
18
- Standard file watchers tell you *a file changed*. Flecto tells you *what* changed and *why it might matter* — flagging secrets, dangerous toggles, and risky config jumps automatically.
39
+ - What changed (`pool_size: 5 20`)
40
+ - What was added or removed
41
+ - What looks risky (secrets, dangerous toggles, pool jumps)
42
+ - What to do next (CI gate, webhook, shell command)
43
+
44
+ See the [changelog and migration notes](CHANGELOG.md) for release history and
45
+ upcoming v2.1 behavior changes.
46
+
47
+ > Diff tools compare trees. **Flecto watches, scores risk, and alerts.**
48
+
49
+ | Without Flecto | With Flecto |
50
+ |---|---|
51
+ | `+ 40 lines of YAML noise` | `~ database.pool_size: 5 → 20` |
52
+ | Hope someone notices `debug: true` | Policy finding → CI fails |
53
+ | “Something in `.env` changed” | Exact keys + optional secret masking |
19
54
 
20
55
  ---
21
56
 
@@ -25,47 +60,61 @@ Standard file watchers tell you *a file changed*. Flecto tells you *what* change
25
60
  npm install -g flecto
26
61
  ```
27
62
 
28
- After that, `flecto` is available globally from anywhere.
63
+ Requires Node.js 20.19.0 or later.
29
64
 
30
- ---
65
+ ```bash
66
+ flecto --version
67
+ flecto doctor
68
+ ```
31
69
 
32
- ## Quick Start
70
+ ---
33
71
 
34
- Watch any config file:
72
+ ## Quick start
35
73
 
36
74
  ```bash
37
75
  flecto watch config/prod.yaml
38
76
  flecto watch .env
39
77
  flecto watch settings.json
40
78
  flecto watch pyproject.toml
79
+ flecto watch app.ini
41
80
  ```
42
81
 
43
- That's it. Flecto starts watching and prints a clear summary every time something changes.
82
+ Thats it Flecto prints a clear summary on every meaningful change.
83
+
84
+ ---
85
+
86
+ ## Features at a glance
87
+
88
+ - **Semantic diffs** for JSON, YAML, TOML, INI, and dotenv (`.env`, `.env.*`, `*.env`)
89
+ - **Live watch** with optional command + webhook delivery
90
+ - **Policy packs** (`default`, `strict-prod`, `compose`, `node-runtime`) + custom `policies/*.json` + local ESM plugins
91
+ - **CI mode** with JSON / NDJSON / GitHub annotations and fail rules
92
+ - **Snapshots & diffs** for deploy scripts and pre-commit hooks
93
+ - **Profiles** via `--profile` or `FLECTO_PROFILE`
94
+ - **Default array identity** (`id` / `name`, or `--array-id-key`) and secret masking
44
95
 
45
96
  ---
46
97
 
47
- ## Common Use Cases
98
+ ## Common use cases
48
99
 
49
- ### Watch multiple files at once
100
+ ### Watch multiple files
50
101
 
51
102
  ```bash
52
103
  flecto watch "config/**/*.yaml" ".env"
53
104
  ```
54
105
 
55
- ### See detailed before/after values
106
+ ### Verbose before/after
56
107
 
57
108
  ```bash
58
109
  flecto watch config/prod.yaml --mode verbose
59
110
  ```
60
111
 
61
- ### Ignore noisy keys (like timestamps)
112
+ ### Ignore noisy keys
62
113
 
63
114
  ```bash
64
115
  flecto watch config/prod.yaml --ignore "updated_at,meta.timestamp"
65
116
  ```
66
117
 
67
- You can ignore exact keys, entire subtrees, wildcards, or keys anywhere in the file:
68
-
69
118
  | Pattern | What it ignores |
70
119
  |---|---|
71
120
  | `meta.timestamp` | That exact key |
@@ -73,21 +122,15 @@ You can ignore exact keys, entire subtrees, wildcards, or keys anywhere in the f
73
122
  | `servers[*].meta.timestamp` | That key inside any array item |
74
123
  | `**.updated_at` | Any key named `updated_at`, anywhere |
75
124
 
76
- ### Run a command when something changes
125
+ ### Run a command on change
77
126
 
78
127
  ```bash
79
128
  flecto watch .env --command "docker-compose restart app"
80
129
  ```
81
130
 
82
- Flecto passes the changes as JSON to your command via the `FLECTO_CHANGES` environment variable.
83
-
84
- ### Send changes to a webhook
85
-
86
- ```bash
87
- flecto watch config/prod.yaml --webhook https://hooks.example.com/notify
88
- ```
131
+ Changes are passed as JSON via `FLECTO_CHANGES` (large payloads may use `FLECTO_CHANGES_FILE`).
89
132
 
90
- Add auth headers if needed:
133
+ ### Webhooks
91
134
 
92
135
  ```bash
93
136
  flecto watch config/prod.yaml \
@@ -95,7 +138,7 @@ flecto watch config/prod.yaml \
95
138
  --webhook-header "Authorization: Bearer TOKEN"
96
139
  ```
97
140
 
98
- Each webhook payload includes a full event envelope:
141
+ Envelope shape (`schema_version: "2.0"`):
99
142
 
100
143
  ```json
101
144
  {
@@ -119,7 +162,7 @@ Each webhook payload includes a full event envelope:
119
162
  }
120
163
  ```
121
164
 
122
- Envelope JSON Schema: [`schemas/flecto-envelope-2.0.json`](schemas/flecto-envelope-2.0.json).
165
+ JSON Schema: [`schemas/flecto-envelope-2.0.json`](schemas/flecto-envelope-2.0.json).
123
166
 
124
167
  ### Policy packs and profiles
125
168
 
@@ -127,8 +170,6 @@ Envelope JSON Schema: [`schemas/flecto-envelope-2.0.json`](schemas/flecto-envelo
127
170
  flecto ci config/prod.yaml --profile prod --snapshot-ref HEAD~1
128
171
  ```
129
172
 
130
- `.flectorc.json` example:
131
-
132
173
  ```json
133
174
  {
134
175
  "defaults": {
@@ -138,29 +179,104 @@ flecto ci config/prod.yaml --profile prod --snapshot-ref HEAD~1
138
179
  "profiles": {
139
180
  "prod": {
140
181
  "policies": ["default", "strict-prod"],
182
+ "severityRemap": { "pool-size-jump": "error" },
141
183
  "maskSecrets": true
142
184
  }
143
185
  }
144
186
  }
145
187
  ```
146
188
 
147
- Profile selection: `--profile` > `FLECTO_PROFILE` > defaults. Custom packs live in `policies/<id>.json`. Local ESM plugins export `evaluate(changes, ctx)`.
189
+ Profile selection: `--profile` > `FLECTO_PROFILE` > defaults.
190
+ Custom packs: `policies/<id>.json`. Plugins: local ESM exporting `evaluate(changes, ctx)`.
148
191
 
149
- ### Opt-in array identity matching
192
+ #### Declarative rule predicates
193
+
194
+ Rules combine their top-level predicates with AND. In addition to `when`, regex
195
+ `match.path`, `afterEquals`, and `numericJump`, packs can use:
196
+
197
+ - `beforeEquals`, `afterIn`, and `beforeIn` for exact values or allowed value lists.
198
+ - `beforeTruthy: true` and `afterTruthy: true` to require a truthy before/after value.
199
+ - `afterMatches` to require a string after value that matches a regular expression.
200
+ - `numericDelta: { "min": 10 }` to match an absolute numeric change of at least 10.
201
+ - `match.pathEquals` and `match.pathPrefix` for exact or prefix path matching without regex.
202
+ - `allOf` and `anyOf` arrays of simple match clauses. Every `allOf` clause and at least
203
+ one `anyOf` clause must match. Clauses support the same value, truthiness, numeric, and
204
+ `match` predicates, but cannot nest composition.
205
+
206
+ ```json
207
+ {
208
+ "id": "risky-feature-enable",
209
+ "severity": "error",
210
+ "allOf": [
211
+ { "match": { "pathPrefix": "features." } },
212
+ { "afterTruthy": true }
213
+ ],
214
+ "anyOf": [
215
+ { "afterEquals": true },
216
+ { "afterIn": ["unsafe", "disabled"] }
217
+ ]
218
+ }
219
+ ```
220
+
221
+ Pack loading fails closed for unknown rule or `match` fields, invalid regexes, and invalid
222
+ predicate shapes, so misspelled predicates cannot silently disable a rule.
223
+
224
+ Use `severityRemap` in defaults or a profile to change pack rule severities without forking a pack:
225
+
226
+ ```json
227
+ {
228
+ "profiles": {
229
+ "dev": {
230
+ "severityRemap": { "pool-size-jump": "off" }
231
+ },
232
+ "prod": {
233
+ "severityRemap": { "pool-size-jump": "error" }
234
+ }
235
+ }
236
+ }
237
+ ```
238
+
239
+ Each key is a rule id and each value must be `info`, `warn`, `error`, or `off`. The remap applies after all configured built-in and local packs load, before findings and CI `--fail-on` checks. When multiple packs provide the same rule id, the remap applies to every matching pack rule. Plugin findings are unchanged. Unknown rule ids print a warning instead of being ignored silently.
240
+
241
+ Authoring guides: [policy packs](docs/policy-packs.md) · [plugins](docs/plugins.md) · [plugin cookbook](docs/plugin-cookbook.md).
242
+
243
+ ### Discover policy packs
150
244
 
151
245
  ```bash
152
- flecto watch config/services.yaml --array-id-key id
246
+ flecto policies list
247
+ flecto policies list --json
153
248
  ```
154
249
 
155
- Without the flag, arrays still diff by index (1.x behavior).
250
+ The command lists every bundled and local pack that resolves from the current
251
+ working directory, including its source path and rule count. For a given pack
252
+ id, Flecto resolves local files before bundled packs in this order:
253
+ `policies/<id>.json`, `policies/<id>.yaml`, `policies/<id>.yml`, then the
254
+ built-in pack. A local pack with the same id overrides its built-in counterpart.
156
255
 
157
- ### Migrating from envelope 1.1
256
+ ### Array identity matching
158
257
 
159
- - `schema_version` is now `"2.0"`
160
- - Envelope type name is `FlectoEnvelope` (was `SentinelEnvelope` in docs/types only)
161
- - New `policies` array on change envelopes
162
- - Webhook headers are unchanged (`X-Flecto-*`)
163
- ### Use both command and webhook together
258
+ ```bash
259
+ flecto watch config/services.yaml
260
+ ```
261
+
262
+ Arrays of objects automatically match by a shared, unique `id` key, falling back
263
+ to `name` when `id` is unavailable. This avoids false changes when named items
264
+ are reordered. Use a custom identity field when needed:
265
+
266
+ ```bash
267
+ flecto watch config/services.yaml --array-id-key serviceKey
268
+ ```
269
+
270
+ To restore index-based diffs for every array, pass `--no-array-id`:
271
+
272
+ ```bash
273
+ flecto watch config/services.yaml --no-array-id
274
+ ```
275
+
276
+ In `.flectorc`, set `"arrayId": false` in `defaults` or a profile for the same
277
+ escape hatch.
278
+
279
+ ### Command + webhook together
164
280
 
165
281
  ```bash
166
282
  flecto watch .env \
@@ -179,37 +295,26 @@ flecto watch config/prod.yaml \
179
295
 
180
296
  | Flag | Options | What it does |
181
297
  |---|---|---|
182
- | `--delivery-mode` | `best-effort` (default), `at-least-once` | Whether to persist and retry failed webhook events |
183
- | `--on-alert-failure` | `warn`, `exit`, `retry` | What happens if a command or webhook fails |
298
+ | `--delivery-mode` | `best-effort` (default), `at-least-once` | Persist and retry failed webhook events |
299
+ | `--on-alert-failure` | `warn`, `exit`, `retry` | Behavior when command/webhook fails |
184
300
 
185
301
  ---
186
302
 
187
- ## Snapshots & Diffs
188
-
189
- Save a baseline snapshot of your file:
303
+ ## Snapshots & diffs
190
304
 
191
305
  ```bash
192
306
  flecto watch config/prod.yaml --snapshot
193
- # Saved to .flecto-snapshots/<id>.json
194
- ```
195
-
196
- Then compare the current file against it anytime:
197
-
198
- ```bash
199
307
  flecto watch config/prod.yaml --diff
308
+ flecto history config/prod.yaml --limit 10
200
309
  ```
201
310
 
202
- Exit codes:
203
- - `0` — no changes (file is clean)
204
- - `1` — changes detected
311
+ Exit codes: `0` clean · `1` changes detected.
205
312
 
206
- This is useful in deployment scripts and pre-commit hooks.
313
+ `flecto history` stays local: it lists recent snapshots from `.flecto-snapshots/` with their timestamps and semantic change counts from the previous snapshot. Counts use the same ignore paths, array identity, and order settings as `flecto watch --diff` (CLI flags or `.flectorc`). Omit files to view all saved snapshot history.
207
314
 
208
315
  ---
209
316
 
210
- ## CI Mode
211
-
212
- Catch risky config changes before they ship:
317
+ ## CI mode
213
318
 
214
319
  ```bash
215
320
  flecto ci "config/**/*.yaml" \
@@ -218,49 +323,84 @@ flecto ci "config/**/*.yaml" \
218
323
  --fail-on "changed,policy,error"
219
324
  ```
220
325
 
221
- **Output formats:** `json`, `ndjson`, `github-annotations`
326
+ **Formats:** `json`, `ndjson`, `github-annotations`
327
+ **Fail triggers:** `changed`, `added`, `removed`, `policy`, `error`, `warn`
328
+ Unresolved `--snapshot-ref` fails closed (no silent empty baseline).
329
+ If every target is missing or unsupported, `flecto ci` and `flecto watch --snapshot` exit non-zero (pass `--allow-empty` to opt out).
222
330
 
223
- **Fail triggers:** `changed`, `added`, `removed`, `policy`, `error`, `warn`
331
+ ### GitHub Action
332
+
333
+ Use the [Flecto CI Action](.github/actions/flecto-ci/action.yml) to run `flecto ci` in a workflow with GitHub annotations enabled by default. A complete local-action workflow is available at [`examples/github-action/flecto-ci.yml`](examples/github-action/flecto-ci.yml).
334
+
335
+ ```yaml
336
+ permissions:
337
+ contents: read
338
+
339
+ steps:
340
+ - uses: actions/checkout@v7
341
+ with:
342
+ fetch-depth: 2
343
+ - uses: myselfsiddharth/Flecto/.github/actions/flecto-ci@main
344
+ with:
345
+ targets: config/**/*.{yaml,yml,json,toml,ini}
346
+ snapshot-ref: HEAD~1
347
+ ```
348
+
349
+ `contents: read` is required by `actions/checkout`. The Action emits workflow-command annotations and needs no write permissions. Keep `fetch-depth: 2` (or use `fetch-depth: 0`) when using the default `HEAD~1` baseline.
350
+
351
+ | Input | Default | Description |
352
+ |---|---|---|
353
+ | `targets` | `config/**/*.{yaml,yml,json,toml,ini}` | Whitespace-separated paths or glob patterns to check |
354
+ | `fail-on` | `policy,error` | Comma-separated events that fail the job |
355
+ | `policies` | _(empty)_ | Comma-separated policy pack IDs; omit to use `.flectorc` / Flecto defaults |
356
+ | `profile` | _(empty)_ | Optional `.flectorc` profile |
357
+ | `format` | `github-annotations` | Flecto output format |
358
+ | `snapshot-ref` | `HEAD~1` | Git ref or snapshot file used as the baseline |
359
+ | `node-version` | `20` | Node.js version used to run Flecto |
360
+
361
+ The Action runs `npx --yes flecto@2 ci`: the major version is pinned so compatible Flecto updates are received. For fully reproducible builds, pin the Action reference to a commit SHA and replace `@2` in a forked Action with an exact published Flecto version.
224
362
 
225
363
  ---
226
364
 
227
- ## Built-in Policy Checks
365
+ ## Built-in policy checks
228
366
 
229
- Flecto automatically flags changes that look risky:
367
+ Built-in pack ids:
230
368
 
231
- - 🔑 **Secrets touched** keys named `secret`, `token`, `password`, `api_key`, etc.
232
- - ⚠️ **Dangerous toggles** `debug: true`, `disable_tls`, `skip_tls_verify`, `allow_insecure`
233
- - 📈 **Large pool size jumps** `pool_size` doubled or more
369
+ - `default`secrets, dangerous toggles, and pool-size jumps.
370
+ - `strict-prod` stricter severities and matching for production use.
371
+ - `compose` privileged services, host networking, Docker socket mounts, and sensitive host-directory bind mounts.
372
+ - `node-runtime` — removed Node.js engine requirements, TLS verification bypasses, and enabled Node debugging or inspector options.
234
373
 
235
- Policy violations can fail your CI pipeline with `--fail-on policy`.
374
+ Fail CI with `--fail-on policy`.
236
375
 
237
376
  ---
238
377
 
239
- ## Tuning for Network Drives or Odd Editors
378
+ ## Migrating from envelope 1.1
379
+
380
+ - `schema_version` is now `"2.0"`
381
+ - Type name is `FlectoEnvelope` (docs/types)
382
+ - New `policies` array on change envelopes
383
+ - Webhook headers unchanged (`X-Flecto-*`)
384
+
385
+ ---
240
386
 
241
- Some editors write files via a temp file swap, which can confuse standard watchers. Enable polling mode:
387
+ ## Tuning for network drives / odd editors
242
388
 
243
389
  ```bash
244
390
  flecto watch config/prod.yaml --polling --interval 500
245
391
  ```
246
392
 
247
- Default polling interval is `100ms`. Polling is off by default.
393
+ Polling is off by default (interval default `100ms` when enabled).
248
394
 
249
395
  ---
250
396
 
251
- ## Config File (.flectorc)
252
-
253
- Set your defaults once so you don't have to repeat flags every time.
254
-
255
- Generate a starter config:
397
+ ## Config file (`.flectorc`)
256
398
 
257
399
  ```bash
258
400
  flecto init
259
401
  ```
260
402
 
261
- Flecto looks for `.flectorc`, `.flectorc.json`, `.flectorc.yaml`, or `.flectorc.yml`.
262
-
263
- Example:
403
+ Looks for `.flectorc`, `.flectorc.json`, `.flectorc.yaml`, or `.flectorc.yml`.
264
404
 
265
405
  ```json
266
406
  {
@@ -269,35 +409,35 @@ Example:
269
409
  "interval": 100,
270
410
  "ignore": ["**.updated_at"],
271
411
  "deliveryMode": "best-effort",
272
- "onAlertFailure": "warn"
412
+ "onAlertFailure": "warn",
413
+ "policies": ["default"],
414
+ "arrayId": true
273
415
  },
274
416
  "profiles": {
275
417
  "dev": { "mode": "verbose" },
276
- "ci": { "failOn": "policy,error" }
418
+ "ci": { "failOn": "policy,error" },
419
+ "prod": {
420
+ "policies": ["default", "strict-prod"],
421
+ "severityRemap": { "pool-size-jump": "error" },
422
+ "maskSecrets": true
423
+ }
277
424
  },
278
- "files": ["config/**/*.yaml", ".env"],
425
+ "files": ["config/**/*.{yaml,yml,json,toml,ini}", ".env", ".env.*", "*.env"],
279
426
  "exclude": ["**/node_modules/**"]
280
427
  }
281
428
  ```
282
429
 
283
- Use a named profile:
284
-
285
430
  ```bash
286
431
  flecto watch --profile dev
287
432
  flecto ci --profile ci
288
- ```
289
-
290
- CLI flags always override profile/default values.
291
-
292
- Verify your setup:
293
-
294
- ```bash
295
433
  flecto doctor
296
434
  ```
297
435
 
436
+ CLI flags override profile/default values.
437
+
298
438
  ---
299
439
 
300
- ## Output Format Reference
440
+ ## Output format reference
301
441
 
302
442
  ### Compact (default)
303
443
 
@@ -315,47 +455,45 @@ flecto doctor
315
455
  ~ path
316
456
  before: old_value
317
457
  after: new_value
318
- + path: value
319
- (key added)
320
458
  ```
321
459
 
322
460
  ---
323
461
 
324
- ## Error Handling
325
-
326
- Flecto is designed to keep running even when things go wrong:
462
+ ## Error handling
327
463
 
328
464
  | Situation | Behavior |
329
465
  |---|---|
330
- | File not found | Error message + exit 1 |
331
- | Unsupported file format | Lists supported extensions + exit 1 |
332
- | File has a parse error | Warning shown, last valid state kept, watching continues |
333
- | Command fails | Warning shown, watcher continues |
334
- | Webhook fails | Warning shown, watcher continues |
335
- | Ctrl+C | Clean shutdown message |
466
+ | File not found | Error + exit 1 |
467
+ | Unsupported format | Lists supported extensions + exit 1 |
468
+ | Parse error while watching | Warning, last valid state kept |
469
+ | Command / webhook fails | Warning (unless `--on-alert-failure exit`) |
470
+ | Ctrl+C | Clean shutdown |
336
471
 
337
472
  ---
338
473
 
339
- ## Running Tests
474
+ ## How it works
340
475
 
341
- ```bash
342
- npm test
343
- # or directly:
344
- node --test test/*.test.js
345
- ```
476
+ 1. **Parser** — format by extension / dotenv naming → structured values
477
+ 2. **Watcher** — [chokidar](https://github.com/paulmillr/chokidar) + debounce
478
+ 3. **Differ** — semantic tree diff (objects, arrays, ignore rules, automatic array ids)
479
+ 4. **Policy engine** — packs + plugins → severity findings
480
+ 5. **Envelope** — versioned automation payload (`2.0`)
481
+ 6. **Alerter** — command and/or webhook with retry modes
482
+
483
+ ---
484
+
485
+ ## Contributing
486
+
487
+ Flecto is open source. See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, PR rules, and review expectations.
488
+ Please read the [Code of Conduct](CODE_OF_CONDUCT.md) and [Security policy](SECURITY.md).
346
489
 
347
- Tests cover the differ, watcher behavior, webhook delivery, policy logic, and CI command behavior.
490
+ Roadmap lives in [GitHub milestones](https://github.com/myselfsiddharth/Flecto/milestones).
348
491
 
349
492
  ---
350
493
 
351
- ## How It Works
494
+ ## Star the project
352
495
 
353
- 1. **Parser** detects the file format by extension and parses it into structured JS values.
354
- 2. **Watcher** — uses [chokidar](https://github.com/paulmillr/chokidar) with debouncing so rapid saves don't flood you with events.
355
- 3. **Differ** — computes a semantic diff (not a line diff), supporting objects, arrays, scalars, and ignore rules.
356
- 4. **Policy engine** — inspects the changes for patterns that look risky and adds severity findings.
357
- 5. **Envelope** — wraps each batch of changes in a versioned event schema ready for automation.
358
- 6. **Alerter** — delivers events via command execution and/or webhook, with configurable retry logic.
496
+ If Flecto helps your team catch a risky config change **[star the repo](https://github.com/myselfsiddharth/Flecto)** so more people can find it.
359
497
 
360
498
  ---
361
499