flecto 1.0.0 → 1.0.1

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.
Files changed (4) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +133 -161
  3. package/index.js +2 -2
  4. package/package.json +6 -5
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Siddharth Mehta
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Siddharth Mehta
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Flecto
2
2
 
3
- A semantic file watcher that detects *meaningful* changes in structured config files and reports them in plain Englishnot raw line diffs.
3
+ **Flecto watches your config files and tells you exactly what changedin plain English.**
4
+
5
+ No more staring at raw line diffs. When your `.env`, `YAML`, `JSON`, or `TOML` file changes, Flecto shows you what actually happened:
4
6
 
5
7
  ```
6
8
  [10:42:31] config/prod.yaml — 3 changes
@@ -9,9 +11,11 @@ A semantic file watcher that detects *meaningful* changes in structured config f
9
11
  - deprecated.old_key
10
12
  ```
11
13
 
12
- Supports **JSON**, **YAML**, **TOML**, and **ENV** files.
14
+ ---
15
+
16
+ ## Why Flecto?
13
17
 
14
- Recruiter-focused overview: see `README_RECRUITERS.md`.
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.
15
19
 
16
20
  ---
17
21
 
@@ -21,22 +25,13 @@ Recruiter-focused overview: see `README_RECRUITERS.md`.
21
25
  npm install -g flecto
22
26
  ```
23
27
 
24
- Or from source:
25
-
26
- ```bash
27
- git clone https://github.com/siddharrth2005/sentinel.git
28
- cd sentinel
29
- npm install
30
- npm install -g .
31
- ```
32
-
33
- After install, `flecto` is available globally.
28
+ After that, `flecto` is available globally from anywhere.
34
29
 
35
30
  ---
36
31
 
37
- ## Usage
32
+ ## Quick Start
38
33
 
39
- ### Watch a file
34
+ Watch any config file:
40
35
 
41
36
  ```bash
42
37
  flecto watch config/prod.yaml
@@ -45,49 +40,54 @@ flecto watch settings.json
45
40
  flecto watch pyproject.toml
46
41
  ```
47
42
 
48
- ### Watch multiple files/globs
43
+ That's it. Flecto starts watching and prints a clear summary every time something changes.
44
+
45
+ ---
46
+
47
+ ## Common Use Cases
48
+
49
+ ### Watch multiple files at once
49
50
 
50
51
  ```bash
51
52
  flecto watch "config/**/*.yaml" ".env"
52
53
  ```
53
54
 
54
- ### Watch with verbose output
55
+ ### See detailed before/after values
55
56
 
56
57
  ```bash
57
58
  flecto watch config/prod.yaml --mode verbose
58
59
  ```
59
60
 
60
- Verbose mode shows before/after values on separate lines and adds a blank line between change events.
61
-
62
- ### Ignore specific key paths
61
+ ### Ignore noisy keys (like timestamps)
63
62
 
64
63
  ```bash
65
64
  flecto watch config/prod.yaml --ignore "updated_at,meta.timestamp"
66
65
  ```
67
66
 
68
- Comma-separated paths. Supports:
69
- - exact path ignore: `meta.timestamp`
70
- - subtree ignore: `meta` (ignores `meta.*` and `meta[0].*`)
71
- - wildcard segment: `servers[*].meta.timestamp`
72
- - key anywhere: `**.updated_at`
67
+ You can ignore exact keys, entire subtrees, wildcards, or keys anywhere in the file:
73
68
 
74
- ### Run a shell command on every change
69
+ | Pattern | What it ignores |
70
+ |---|---|
71
+ | `meta.timestamp` | That exact key |
72
+ | `meta` | Everything under `meta.*` |
73
+ | `servers[*].meta.timestamp` | That key inside any array item |
74
+ | `**.updated_at` | Any key named `updated_at`, anywhere |
75
+
76
+ ### Run a command when something changes
75
77
 
76
78
  ```bash
77
79
  flecto watch .env --command "docker-compose restart app"
78
80
  ```
79
81
 
80
- Changes are passed to the command as JSON in the `FLECTO_CHANGES` environment variable, and the watched file path in `FLECTO_FILE`.
81
-
82
- If the change payload is too large for env vars, Flecto writes it to `FLECTO_CHANGES_FILE` and sets `FLECTO_CHANGES` to `[]`.
82
+ Flecto passes the changes as JSON to your command via the `FLECTO_CHANGES` environment variable.
83
83
 
84
- ### POST changes to a webhook
84
+ ### Send changes to a webhook
85
85
 
86
86
  ```bash
87
87
  flecto watch config/prod.yaml --webhook https://hooks.example.com/notify
88
88
  ```
89
89
 
90
- Add custom headers (repeatable):
90
+ Add auth headers if needed:
91
91
 
92
92
  ```bash
93
93
  flecto watch config/prod.yaml \
@@ -95,24 +95,13 @@ flecto watch config/prod.yaml \
95
95
  --webhook-header "Authorization: Bearer TOKEN"
96
96
  ```
97
97
 
98
- Flecto webhook payloads include an event envelope with:
99
- - `schema_version`
100
- - `event_id`
101
- - `batch_id`
102
- - `event_type` (`changes` or `lifecycle`)
103
- - `source`
104
- - `emitted_at`
105
- - `file`
106
- - `changes`
107
-
108
- Payload shape:
98
+ Each webhook payload includes a full event envelope:
99
+
109
100
  ```json
110
101
  {
111
102
  "schema_version": "1.1",
112
103
  "event_id": "uuid",
113
- "batch_id": "uuid",
114
104
  "event_type": "changes",
115
- "source": "watch",
116
105
  "emitted_at": "2026-04-14T10:42:31.000Z",
117
106
  "file": "/absolute/path/to/config/prod.yaml",
118
107
  "changes": [
@@ -121,9 +110,7 @@ Payload shape:
121
110
  }
122
111
  ```
123
112
 
124
- ### Combine command + webhook
125
-
126
- Both can be active at the same time:
113
+ ### Use both command and webhook together
127
114
 
128
115
  ```bash
129
116
  flecto watch .env \
@@ -131,7 +118,7 @@ flecto watch .env \
131
118
  --webhook https://hooks.example.com/notify
132
119
  ```
133
120
 
134
- ### Delivery semantics and failure policy
121
+ ### Retry on failure
135
122
 
136
123
  ```bash
137
124
  flecto watch config/prod.yaml \
@@ -140,149 +127,89 @@ flecto watch config/prod.yaml \
140
127
  --on-alert-failure retry
141
128
  ```
142
129
 
143
- - `--delivery-mode best-effort` (default): no persistent retries
144
- - `--delivery-mode at-least-once`: failed webhook events are persisted and retried
145
- - `--on-alert-failure warn|exit|retry`: controls behavior when command/webhook fails
146
-
147
- ### Polling interval
148
-
149
- For network drives or editors that write via temp files, tune the polling interval:
150
-
151
- ```bash
152
- flecto watch config/prod.yaml --polling --interval 500
153
- ```
154
-
155
- Default polling interval is `100ms` (polling is **off** unless you pass `--polling`).
156
-
157
- ---
158
-
159
- ## CI mode
160
-
161
- Run semantic diffs in CI against snapshots or git refs:
162
-
163
- ```bash
164
- flecto ci "config/**/*.yaml" \
165
- --snapshot-ref HEAD~1 \
166
- --format github-annotations \
167
- --fail-on "changed,policy,error"
168
- ```
169
-
170
- `--format` supports:
171
- - `json`
172
- - `ndjson`
173
- - `github-annotations`
174
-
175
- `--fail-on` supports:
176
- - `changed`
177
- - `added`
178
- - `removed`
179
- - `policy`
180
- - `error`
181
- - `warn`
130
+ | Flag | Options | What it does |
131
+ |---|---|---|
132
+ | `--delivery-mode` | `best-effort` (default), `at-least-once` | Whether to persist and retry failed webhook events |
133
+ | `--on-alert-failure` | `warn`, `exit`, `retry` | What happens if a command or webhook fails |
182
134
 
183
135
  ---
184
136
 
185
- ## Snapshot & diff mode
137
+ ## Snapshots & Diffs
186
138
 
187
- ### Save a baseline snapshot
139
+ Save a baseline snapshot of your file:
188
140
 
189
141
  ```bash
190
142
  flecto watch config/prod.yaml --snapshot
191
- # .flecto-snapshots/<id>.json
143
+ # Saved to .flecto-snapshots/<id>.json
192
144
  ```
193
145
 
194
- ### Diff the current file against the saved snapshot
146
+ Then compare the current file against it anytime:
195
147
 
196
148
  ```bash
197
149
  flecto watch config/prod.yaml --diff
198
150
  ```
199
151
 
200
- Prints all changes since the snapshot was taken. Exits with:
201
- - **code 0** — file is clean (no changes)
202
- - **code 1** — changes detected (useful in CI pipelines)
152
+ Exit codes:
153
+ - `0`no changes (file is clean)
154
+ - `1` — changes detected
155
+
156
+ This is useful in deployment scripts and pre-commit hooks.
203
157
 
204
158
  ---
205
159
 
206
- ## Output format
160
+ ## CI Mode
207
161
 
208
- ### Compact (default)
162
+ Catch risky config changes before they ship:
209
163
 
210
- ```
211
- [HH:MM:SS] <filepath> N changes
212
- ~ <path>: <before> → <after>
213
- + <path>: <value>
214
- - <path>: <value>
164
+ ```bash
165
+ flecto ci "config/**/*.yaml" \
166
+ --snapshot-ref HEAD~1 \
167
+ --format github-annotations \
168
+ --fail-on "changed,policy,error"
215
169
  ```
216
170
 
217
- - `~` (yellow) value changed
218
- - `+` (green) — key added
219
- - `-` (red) — key removed
171
+ **Output formats:** `json`, `ndjson`, `github-annotations`
220
172
 
221
- ### Verbose (`--mode verbose`)
222
-
223
- ```
224
- [HH:MM:SS] <filepath> — N changes
225
- ~ <path>
226
- before: <value>
227
- after: <value>
228
- + <path>: <value>
229
- (key added)
230
-
231
- ```
173
+ **Fail triggers:** `changed`, `added`, `removed`, `policy`, `error`, `warn`
232
174
 
233
175
  ---
234
176
 
235
- ## Change event shape
177
+ ## Built-in Policy Checks
236
178
 
237
- Each semantic change is represented as:
179
+ Flecto automatically flags changes that look risky:
238
180
 
239
- ```ts
240
- {
241
- type: 'added' | 'removed' | 'changed',
242
- path: string, // dot-notation key path, e.g. "database.pool_size"
243
- before?: unknown, // previous value (absent for 'added')
244
- after?: unknown, // new value (absent for 'removed')
245
- note?: string, // optional note, e.g. "type changed from string to number"
246
- }
247
- ```
181
+ - 🔑 **Secrets touched** — keys named `secret`, `token`, `password`, `api_key`, etc.
182
+ - ⚠️ **Dangerous toggles** — `debug: true`, `disable_tls`, `skip_tls_verify`, `allow_insecure`
183
+ - 📈 **Large pool size jumps** — `pool_size` doubled or more
248
184
 
249
- Array items use index notation: `servers[1].port`.
185
+ Policy violations can fail your CI pipeline with `--fail-on policy`.
250
186
 
251
187
  ---
252
188
 
253
- ## Policy checks
254
-
255
- Built-in policy findings are evaluated from semantic changes:
256
- - secret-looking keys changed (`secret`, `token`, `password`, `api_key`, etc.)
257
- - dangerous toggles enabled (`debug`, `allow_insecure`, `disable_tls`, `skip_tls_verify`)
258
- - large `pool_size` jumps (>=2x)
189
+ ## Tuning for Network Drives or Odd Editors
259
190
 
260
- Policy findings can trigger CI failures with `--fail-on policy,error`.
191
+ Some editors write files via a temp file swap, which can confuse standard watchers. Enable polling mode:
261
192
 
262
- ---
193
+ ```bash
194
+ flecto watch config/prod.yaml --polling --interval 500
195
+ ```
263
196
 
264
- ## Error handling
265
-
266
- | Situation | Behavior |
267
- |---|---|
268
- | File not found | Error message + exit 1 |
269
- | Unsupported format | Lists supported extensions + exit 1 |
270
- | Parse error during watch | Warning shown, last valid state kept, watching continues |
271
- | Command failure | Warning shown, watcher continues |
272
- | Webhook failure | Warning shown, watcher continues |
273
- | Ctrl+C | Clean shutdown message |
197
+ Default polling interval is `100ms`. Polling is off by default.
274
198
 
275
199
  ---
276
200
 
277
- ## .flectorc configuration
201
+ ## Config File (.flectorc)
278
202
 
279
- Use `.flectorc`, `.flectorc.json`, `.flectorc.yaml`, or `.flectorc.yml`.
280
- Bootstrap one with:
203
+ Set your defaults once so you don't have to repeat flags every time.
204
+
205
+ Generate a starter config:
281
206
 
282
207
  ```bash
283
208
  flecto init
284
209
  ```
285
210
 
211
+ Flecto looks for `.flectorc`, `.flectorc.json`, `.flectorc.yaml`, or `.flectorc.yml`.
212
+
286
213
  Example:
287
214
 
288
215
  ```json
@@ -303,16 +230,16 @@ Example:
303
230
  }
304
231
  ```
305
232
 
306
- CLI flags take precedence over profile/default values.
307
-
308
- Use a profile with:
233
+ Use a named profile:
309
234
 
310
235
  ```bash
311
236
  flecto watch --profile dev
312
237
  flecto ci --profile ci
313
238
  ```
314
239
 
315
- Check setup with:
240
+ CLI flags always override profile/default values.
241
+
242
+ Verify your setup:
316
243
 
317
244
  ```bash
318
245
  flecto doctor
@@ -320,7 +247,46 @@ flecto doctor
320
247
 
321
248
  ---
322
249
 
323
- ## Running tests
250
+ ## Output Format Reference
251
+
252
+ ### Compact (default)
253
+
254
+ ```
255
+ [HH:MM:SS] <filepath> — N changes
256
+ ~ path: before → after (yellow — value changed)
257
+ + path: value (green — key added)
258
+ - path: value (red — key removed)
259
+ ```
260
+
261
+ ### Verbose (`--mode verbose`)
262
+
263
+ ```
264
+ [HH:MM:SS] <filepath> — N changes
265
+ ~ path
266
+ before: old_value
267
+ after: new_value
268
+ + path: value
269
+ (key added)
270
+ ```
271
+
272
+ ---
273
+
274
+ ## Error Handling
275
+
276
+ Flecto is designed to keep running even when things go wrong:
277
+
278
+ | Situation | Behavior |
279
+ |---|---|
280
+ | File not found | Error message + exit 1 |
281
+ | Unsupported file format | Lists supported extensions + exit 1 |
282
+ | File has a parse error | Warning shown, last valid state kept, watching continues |
283
+ | Command fails | Warning shown, watcher continues |
284
+ | Webhook fails | Warning shown, watcher continues |
285
+ | Ctrl+C | Clean shutdown message |
286
+
287
+ ---
288
+
289
+ ## Running Tests
324
290
 
325
291
  ```bash
326
292
  npm test
@@ -328,15 +294,21 @@ npm test
328
294
  node --test test/*.test.js
329
295
  ```
330
296
 
331
- Tests cover differ, watcher behavior, alert webhook delivery, policy logic, and CI command behavior.
297
+ Tests cover the differ, watcher behavior, webhook delivery, policy logic, and CI command behavior.
298
+
299
+ ---
300
+
301
+ ## How It Works
302
+
303
+ 1. **Parser** — detects the file format by extension and parses it into structured JS values.
304
+ 2. **Watcher** — uses [chokidar](https://github.com/paulmillr/chokidar) with debouncing so rapid saves don't flood you with events.
305
+ 3. **Differ** — computes a semantic diff (not a line diff), supporting objects, arrays, scalars, and ignore rules.
306
+ 4. **Policy engine** — inspects the changes for patterns that look risky and adds severity findings.
307
+ 5. **Envelope** — wraps each batch of changes in a versioned event schema ready for automation.
308
+ 6. **Alerter** — delivers events via command execution and/or webhook, with configurable retry logic.
332
309
 
333
310
  ---
334
311
 
335
- ## How it works
312
+ ## License
336
313
 
337
- 1. **Parser** detects format by file extension and parses the file into JS values.
338
- 2. **Watcher** — uses [chokidar](https://github.com/paulmillr/chokidar) with debouncing and lifecycle events.
339
- 3. **Differ** — computes semantic changes (supports object/array/scalar roots, ignore rules).
340
- 4. **Policy engine** — derives severity findings from change patterns.
341
- 5. **Envelope** — wraps change batches in a versioned automation event schema.
342
- 6. **Alerter** — runs commands and/or webhook delivery with configurable retry semantics.
314
+ MITsee [LICENSE](./LICENSE).
package/index.js CHANGED
@@ -4,7 +4,7 @@ import { program } from 'commander';
4
4
  import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
5
5
  import { resolve, relative } from 'path';
6
6
  import { createHash } from 'crypto';
7
- import { execSync } from 'child_process';
7
+ import { execFileSync } from 'child_process';
8
8
  import chalk from 'chalk';
9
9
 
10
10
  import { parseFile, isSupported, parseContent } from './src/parser.js';
@@ -104,7 +104,7 @@ function readSnapshotStateFromRef(filePath, snapshotRef) {
104
104
 
105
105
  // git ref mode: flecto ci file --snapshot-ref HEAD~1
106
106
  const rel = relative(process.cwd(), filePath).replaceAll('\\', '/');
107
- const raw = execSync(`git show ${snapshotRef}:${rel}`, { encoding: 'utf8' });
107
+ const raw = execFileSync('git', ['show', `${snapshotRef}:${rel}`], { encoding: 'utf8' });
108
108
  return parseContent(filePath, raw);
109
109
  }
110
110
 
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "flecto",
3
3
  "publishConfig": {
4
- "access": "public"
4
+ "access": "public",
5
+ "provenance": true
5
6
  },
6
- "version": "1.0.0",
7
+ "version": "1.0.1",
7
8
  "description": "Flecto — semantic config watcher that reports meaningful changes in plain English",
8
9
  "keywords": [
9
10
  "flecto",
@@ -14,13 +15,13 @@
14
15
  "devops",
15
16
  "ci"
16
17
  ],
17
- "homepage": "https://github.com/siddharrth2005/sentinel#readme",
18
+ "homepage": "https://github.com/myselfsiddharth/Flecto#readme",
18
19
  "bugs": {
19
- "url": "https://github.com/siddharrth2005/sentinel/issues"
20
+ "url": "https://github.com/myselfsiddharth/Flecto/issues"
20
21
  },
21
22
  "repository": {
22
23
  "type": "git",
23
- "url": "git+https://github.com/siddharrth2005/sentinel.git"
24
+ "url": "git+https://github.com/myselfsiddharth/Flecto.git"
24
25
  },
25
26
  "engines": {
26
27
  "node": ">=18"