octwin-cli 0.8.5 → 0.8.7

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 CHANGED
@@ -5,6 +5,68 @@ Format: [Keep a Changelog](https://keepachangelog.com/) — newest first, bucket
5
5
  **Added · Changed · Deprecated · Removed · Fixed · Security**. The platform-wide view lives in the
6
6
  repo root [`CHANGELOG.md`](../../CHANGELOG.md); this file is the CLI-only cut that ships with the package.
7
7
 
8
+ ## [0.8.7] - 2026-09-06
9
+
10
+ ### Added
11
+ - **`validate` now reads a map's KEYS, not only its values.** The declaration walker reported four
12
+ things — an unknown key, a missing `required` key, a wrong scalar type, a value outside a closed
13
+ `enum` — and every one of them is about a VALUE. But a map's keys carry meaning in several
14
+ declarations (`roles.yaml` grant resources and verbs, `xrm.yaml` entity names), and those keys had
15
+ no check at all. Rule 5 replays `propertyNames` — both the `enum` and the `pattern` form.
16
+
17
+ This is why publishing the RBAC vocabulary was worth doing. A pack author wrote `case:` where the
18
+ grant key is `record.case`, passed offline `validate` clean, and learned the truth one bad guess at
19
+ a time from `--remote` round-trips. They gave up on custom RBAC over it. The check now says
20
+ `not a valid key here — must be one of "record.case", …` before a deploy is attempted.
21
+
22
+ It stays inside the file's false-positive rule because it is a **faithful replay**: the same `enum`
23
+ membership and the same JS regex engine Zod itself runs, over a pattern the platform generated. A
24
+ pattern this engine cannot compile is treated like a combinator — walk away, do not guess.
25
+
26
+ Verified 2026-09-06 against the shipped binary: across all 23 marketplace packs rule 5 reports
27
+ **nothing**, with 10 of the 12 pulled declaration schemas carrying `propertyNames` (so the silence
28
+ is a result, not an unexercised branch). A deliberately broken key is caught on both branches — a
29
+ role named `Regional-Agent` against `^[a-z][a-z0-9_]*$`, and a grant key `case:` against an enum
30
+ vocabulary — each naming the file, the path and the rule it broke.
31
+
32
+ ### Fixed
33
+ - **`deploy` had stopped printing its seed counts entirely.** `printDeploySuccess` read
34
+ `r.summary.records` / `.updated` / `.images` / `.rules` / `.failed`, but the deploy route's
35
+ `summary` is a run-log **string** (`"clinic v1.2.0 — {…}"`), not an object. So every field was
36
+ `undefined`, `parts` stayed empty, and the `if (parts.length)` guard turned *"I am reading the
37
+ wrong field"* into *"there was nothing to say"* — the block printed nothing and looked like a
38
+ deploy that simply seeded no rows. The counts have been on `r.seeded`, keyed by seed kind, and
39
+ `printSeedCounts` already renders them (filtering zeros, which is what makes a partial seed
40
+ legible). The dead block is gone and `printSeedCounts` is called instead.
41
+
42
+ Same shape as the bug 0.8.6 fixed in `validate`: *no data* and *no problem* rendering identically.
43
+ Two independent places in this CLI reached it within one week.
44
+
45
+ ## [0.8.6] - 2026-09-04
46
+
47
+ ### Changed
48
+ - **`validate` can no longer print a `✓` for a check that did not run.** Each of the eight
49
+ checks now RETURNS an `Outcome` — `passed`, `findings`, or `not-run` — and a single printer
50
+ renders all of them, groups the skips by reason, and computes the exit code. Previously each
51
+ check printed its own `✓` inside the `if` that held its data, with a `skipped[]` array and a
52
+ `skipReasons` Map maintained alongside; it was correct because someone was careful, and the
53
+ next check added was one `if` away from lying again.
54
+
55
+ It had lied twice, in the same shape: the KB-dependent block once printed ONE `✓` above six
56
+ checks whose own `✓`s lived inside their `if`s (so a run with no pulled KB read as "one check,
57
+ passed", and an entire backlog batch reached production that way), and `yamlDocs()` once
58
+ dropped an unparseable file so `validate` printed all-green over a pack the platform's importer
59
+ then refused. **An unparseable file is not "no findings", it is "no idea", and those must never
60
+ print the same** — a check that returns nothing now cannot reach the `passed` branch at all.
61
+
62
+ Output is unchanged for a normal run. `passed` carries its own line, so the reserved-entity
63
+ check keeps the narrower wording it uses when the catalog rules are absent from an older pull.
64
+ `--require-kb` is now one line over the returned skip list.
65
+
66
+ Verified 2026-09-04: all 23 marketplace packs exit 0 with no findings; a pack with no pulled KB
67
+ prints zero `✓` for the six KB-dependent checks plus one grouped ⚠ naming all six, and
68
+ `--require-kb` exits 1; a duplicate YAML key still exits 1 naming the file.
69
+
8
70
  ## [0.8.5] - 2026-09-02
9
71
 
10
72
  ### Added