Commit bdcfb10
authored
feat(slice-bc): framework-at-query-time + runtime wiring specs (+code corrections) (#429)
Five new specs, two v2 amendments, two API addendums, and the matching
code corrections to make scheduler + kensa-executor materially
implement v2.0.0 in main. The runtime wiring itself (openwatch worker
subcommand, daemon orchestration, live Kensa binding) and findings UI
are spec'd but not implemented in this PR — those land in follow-up
PRs that take these specs as their contract.
Architectural correction
Kensa's API is Kensa.Scan(ctx, host, rules, opts...) — the caller
passes the rules; framework identity is per-rule metadata in
rule.References, not a scan input. OpenWatch's v1 spec wrongly
modeled scans as framework-scoped:
- scheduler.JobPayload carried a FrameworkID HMAC-bound field.
- executor.Run took a framework parameter.
- Fleet/host APIs had no framework slicing surface.
v2 corrects this: jobs are per-host (no framework), executor runs
the full applicable rule corpus, framework is a query-time
projection on host_rule_state.framework_refs JSONB.
New specs (3)
system-daemon-orchestration cmd/openwatch serve / migrate / worker
/ check-config boot+shutdown ordering;
13 ACs; EmitFunc DI invariant;
alertrouter MUST subscribe before bus
has publishers.
system-worker-subcommand SKIP-LOCKED claim, HMAC verify,
transient-vs-permanent retry policy,
advisory-lock per-host concurrency
guard, graceful drain on SIGTERM;
13 ACs; references system-job-queue
for retry/dead-letter semantics.
frontend-findings-ui First frontend spec; route /hosts/{id}
with three regions (identity+liveness,
compliance, recent transactions),
optional ?framework= URL param,
role-gated, axe-core clean; 15 ACs;
framework-of-implementation agnostic.
Spec amendments (2)
system-scheduler 1.0.0 -> 2.0.0
- C-11 HMAC inputs: (host_id, policy_version, enqueued_at).
- C-12 NEW: NewService has no defaultFramework param; JobPayload
has no FrameworkID field. Source-inspection enforces.
- AC-06 reworded; AC-16 NEW (source-inspection).
system-kensa-executor 1.0.0 -> 2.0.0
- C-12 Run signature: Run(ctx, hostID, policyVersion).
- C-13 Production scanFunc binds pkg/kensa.Default;
unwiredScanFunc remains test-only //nolint:unused.
- C-14 Result.Outcomes covers every rule Kensa returned;
RuleOutcome.FrameworkRefs flattened from rule References.
- AC-01 reworded; AC-06 drops framework_unsupported reason;
AC-17/18 NEW (source-inspection).
API spec addendums (2)
api-fleet-observability 1.0.0 -> 1.1.0
- C-07/08 NEW: optional ?framework= filter on every endpoint;
exact-key match on framework_refs JSONB; absent / empty value
is unfiltered (identical to v1.0.0).
- AC-14/15/16/17 NEW (framework filter); AC-18 = renumbered
v1.0.0 AC-14 (POST returns 405).
api-hosts 1.1.0 -> 1.2.0
- C-07/08 NEW: ?framework= filters compliance_summary; liveness
unaffected.
- AC-17/18 NEW (framework filter; CIS-only host returns zeros
when STIG requested).
Code corrections (signature changes, no behavior drift on
unfiltered paths)
internal/scheduler
- JobPayload drops FrameworkID; Encode layout updated.
v1 payloads now fail Verify (intended migration behavior —
pre-v2 queued jobs are dead-lettered).
- NewService drops defaultFramework parameter.
- Dispatch body map drops framework_id key.
- source_test.go NEW: AC-16 source-inspection.
internal/kensa
- Result drops FrameworkID (per-rule FrameworkRefs stays).
- ScanFunc, Run, emitStarted/Completed/Failure,
reportHostKeyUnknown/EvidenceOversize/KensaError all drop
framework param.
- unwiredScanFunc annotated //nolint:unused per AC-18 — the
production binding lands with the worker subcommand PR.
- source_test.go: AC-17/18 NEW (Run / ScanFunc signature
inspection).
internal/fleetrollup
- options.go NEW: WithFramework functional option.
- service.go: 4 methods now accept optional opts; SQL uses
"$N::text IS NULL OR framework_refs ? $N" for unbranched
filtering. Empty string -> NULL -> unfiltered.
api/openapi.yaml
- All 5 fleet endpoints + GET /hosts/{id} accept ?framework=.
- Re-ran make generate-api to refresh server.gen.go.
internal/server
- fleet_handlers.go: 4 handlers thread Framework param into
fleetrollup via frameworkOpts() helper.
- fleet_helpers.go: frameworkOpts() converts *string to
[]fleetrollup.Option.
- hosts_handlers.go: GetHostByID now takes
GetHostByIDParams; threads framework into
loadHostComplianceSummary.
- hosts_enrichment.go: loadHostComplianceSummary takes
framework; SQL filters via JSONB ?-operator.
Tests
All affected specs at 100% AC coverage:
api-fleet-observability 18/18 (was 14/14)
api-hosts 18/18 (was 16/16)
system-scheduler 16/16 (was 15/15)
system-kensa-executor 18/18 (was 16/16)
system-fleet-rollup 13/13 (unchanged — already 100%)
Existing test files updated for the new signatures; 4 new tests
added for fleet AC-14/15/16/17 + 2 for hosts AC-17/18.
Verification
go vet ./... clean
go test -race -count=1 PASS (full tree, with Postgres, 4 minutes)
specter parse PASS (44 specs total — 3 new)
specter check PASS
specter coverage all touched specs at 100%
Not in this PR (specs deliberately reference but implement nothing):
- openwatch worker subcommand binary
- Slice B package wiring into cmd/openwatch serve (scheduler tick,
liveness loop, alertrouter)
- Live Kensa binding (pkg/kensa.Default-backed ScanFunc)
- Frontend code (only the spec is in this PR)
Specs touched
system-scheduler v1.0.0 -> v2.0.0
system-kensa-executor v1.0.0 -> v2.0.0
api-fleet-observability v1.0.0 -> v1.1.0
api-hosts v1.1.0 -> v1.2.0
system-daemon-orchestration NEW
system-worker-subcommand NEW
frontend-findings-ui NEW1 parent dc8e42f commit bdcfb10
24 files changed
Lines changed: 1200 additions & 493 deletions
File tree
- app
- api
- internal
- fleetrollup
- kensa
- scheduler
- server
- api
- specs
- api
- system
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
690 | 690 | | |
691 | 691 | | |
692 | 692 | | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
693 | 697 | | |
694 | 698 | | |
695 | 699 | | |
| |||
797 | 801 | | |
798 | 802 | | |
799 | 803 | | |
800 | | - | |
| 804 | + | |
801 | 805 | | |
802 | 806 | | |
803 | 807 | | |
804 | 808 | | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
805 | 814 | | |
806 | 815 | | |
807 | 816 | | |
| |||
845 | 854 | | |
846 | 855 | | |
847 | 856 | | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
848 | 861 | | |
849 | 862 | | |
850 | 863 | | |
| |||
871 | 884 | | |
872 | 885 | | |
873 | 886 | | |
| 887 | + | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
874 | 891 | | |
875 | 892 | | |
876 | 893 | | |
| |||
897 | 914 | | |
898 | 915 | | |
899 | 916 | | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
900 | 921 | | |
901 | 922 | | |
902 | 923 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
32 | | - | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
33 | 41 | | |
34 | 42 | | |
35 | 43 | | |
36 | 44 | | |
37 | | - | |
| 45 | + | |
| 46 | + | |
38 | 47 | | |
39 | | - | |
| 48 | + | |
40 | 49 | | |
41 | 50 | | |
42 | 51 | | |
| |||
52 | 61 | | |
53 | 62 | | |
54 | 63 | | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
55 | 74 | | |
56 | 75 | | |
57 | 76 | | |
| |||
79 | 98 | | |
80 | 99 | | |
81 | 100 | | |
82 | | - | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
83 | 105 | | |
84 | 106 | | |
85 | 107 | | |
86 | 108 | | |
| 109 | + | |
87 | 110 | | |
88 | 111 | | |
89 | 112 | | |
90 | 113 | | |
| 114 | + | |
91 | 115 | | |
92 | 116 | | |
93 | 117 | | |
94 | | - | |
| 118 | + | |
95 | 119 | | |
96 | 120 | | |
97 | 121 | | |
| |||
113 | 137 | | |
114 | 138 | | |
115 | 139 | | |
116 | | - | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
117 | 144 | | |
118 | 145 | | |
119 | 146 | | |
120 | 147 | | |
| 148 | + | |
121 | 149 | | |
122 | 150 | | |
123 | 151 | | |
124 | 152 | | |
| 153 | + | |
125 | 154 | | |
126 | 155 | | |
127 | 156 | | |
128 | | - | |
| 157 | + | |
129 | 158 | | |
130 | 159 | | |
131 | 160 | | |
| |||
149 | 178 | | |
150 | 179 | | |
151 | 180 | | |
152 | | - | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
153 | 185 | | |
154 | 186 | | |
155 | 187 | | |
156 | 188 | | |
| 189 | + | |
157 | 190 | | |
158 | | - | |
159 | | - | |
| 191 | + | |
160 | 192 | | |
161 | 193 | | |
162 | 194 | | |
163 | 195 | | |
| 196 | + | |
164 | 197 | | |
165 | 198 | | |
166 | 199 | | |
167 | 200 | | |
168 | 201 | | |
169 | 202 | | |
170 | | - | |
| 203 | + | |
171 | 204 | | |
172 | 205 | | |
173 | 206 | | |
| |||
0 commit comments