feat(kensa): integrate Kensa v0.10.0 - #882
Merged
Merged
Conversation
Pins github.com/Hanalyx/kensa v0.10.0 (only kensa moved in go.sum). The engine constant, system-kensa-executor 2.10.0 (context, C-13) and the third-party notices follow. Corpus: 769 to 779 rules, two new framework keys, nist_800_171 and cmmc_l2, 324 rules each, measured through pkg/kensa.RuleFrameworkRefs. The backend family labels and the host-detail lens chips name them "NIST 800-171" and "CMMC Level 2"; the chip transform would have rendered "CMMC L 2" (frontend-host-compliance-tab 1.7.0, AC-12). The README, the scanning guide framework table and the distribution matrix are re-derived from v0.10.0. Variables: v0.10.0 ships eight corpus-used variables with an empty default. The catalog test bounded the list at a constant 29; it now derives the bound from BuiltInVars and checks membership. api-system-scan-config 1.5.0 adds AC-11: a list override reaches the rule's set_compare parameters verbatim on reload, and removing it restores the default. configure_me stays limited to the three placeholders (C-07); extending it is a decision, not part of this change. The scanning guide gains a Scan variables section naming the eight, the list syntax and the fact that values are not type checked. Mutation checks, each red then restored by inverse edit with the hash verified: reload without overrides (AC-11), a wrong CMMC backend label (system-compliance-lens AC-02), a missing CMMC chip label (AC-12). Findings filed, not fixed here: CP bugs/OW-080 (override values are stored and applied without a type check; the Kensa checker is internal, features/KN-OW-022) and bugs/OW-081 (the rc.5 engine cannot load the 0.10.0 corpus and the packages do not forbid that pairing; a decision is needed before this merges).
CP bugs/OW-081. Kensa v0.9.0 cannot load the v0.10.0 corpus: LoadRules fails on the first variable it does not know, serve starts anyway, and every scan fails. kensa-rules takes its version from go.mod and openwatch required it unversioned, so a rules-only upgrade onto rc.5 or earlier produced exactly that pairing. The openwatch RPM and DEB now provide openwatch-kensa-engine at the Kensa version they link, and kensa-rules requires openwatch-kensa-engine at least its own version. Both come from one helper, packaging/common/kensa-version.sh, which the corpus stager also uses, so the two values cannot drift. No floor is written by hand: a fixed "openwatch >= rc.6" would have made the pair built on main uninstallable together until the version bump. An older corpus under a newer engine loads, so an openwatch-only upgrade stays allowed. The spec default 0.0.0 satisfies no corpus, so a build that forgets the define fails at install rather than shipping an unguarded pair. Contract: release-upgrade 1.1.0, C-06, AC-08 (built artifacts carry the provide and the requirement at the go.mod version, read from go.mod independently of the helper) and AC-09 (container behavior on RPM and DEB). package-smoke gains a kensa-rules-compat job that runs AC-09 against v0.7.1, the previous GA. Measured locally against the published v0.8.0-rc.5 packages and this tree built as rc.6, Rocky 9 and Ubuntu 24.04: - dnf, rpm -U and apt refuse kensa-rules 0.10.0 alone; the installed corpus stays 0.9.0; - openwatch-only upgrade, coordinated upgrade and fresh install succeed; - the new corpus refuses a downgrade of openwatch to rc.5; - 1:0.8.0~rc.5 < ~rc.6 < ~rc.10 < 1:0.8.0 and 0.9.0 < 0.10.0 in both formats. Mutations, each red then restored with the hash checked: kensa-rules without the floor (AC-09, both formats), openwatch without the provide (AC-09, both formats), and the DEB provide left at 0.0.0 (AC-08). Residual, measured and documented, not covered: a bare dpkg -i of the rules package unpacks it and leaves it unconfigured (the files are replaced), and rpm --nodeps bypasses the check. The documented paths use dnf and apt. The upgrade runbook and the CHANGELOG say so.
…t to 800-53 configure_me (api-system-scan-config C-07, amended in 1.5.0, which is unpublished). It marked the three placeholder defaults only. It now marks every variable whose built-in value cannot be right for a real site: the three placeholders and every corpus-used variable Kensa ships with an empty default. For v0.10.0 that is eleven, named in C-07 and pinned in the test: the three plus authorized_listening_ports, authorized_local_accounts, authorized_network_protocols, authorized_privileged_users, authorized_service_accounts, authorized_services, flaw_remediation_max_days and suid_sgid_baseline. The other 32 carry a benchmark value or a generic list valid as shipped. C-07 says configure_me marks a decision to make and does not classify a scan result, which needs KN-OW-021. The card's count no longer calls every flagged value a placeholder; the OpenAPI description follows and the generated code is refreshed. The catalog test (AC-08) now checks contents: the entry set, each default and each rule-id list against values built in the test from the two library tables, two fixed points, and the ConfigureMe set against the named inventory. Mutations, each red then restored with the hash checked: flag placeholders only; trim whitespace from defaults, which changes only banner_text. Remediation projected lift (api-remediation 1.8.0, C-07, AC-18). The nist bucket matched every key starting "nist", so v0.10.0's nist_800_171 joined it: 19 rules carry 800-171 and not 800-53, so they would be quoted a NIST gain, and the denominator would count both frameworks. The bucket is now the 800-53 family, in both the class match and the SQL denominator. AC-18 discriminates each half, and a mutation of each half turns it red (25 instead of 33.33; a lift quoted for an 800-171-only rule).
…o CI Go CI failed its specter sync gate on 3a243ae: release-upgrade AC-09 skipped there, because its only test drove containers, which only package-smoke provides. A skipped criterion is uncovered. AC-09 now asks the resolvers directly, with no root, container or network: rpm --test against a scratch rpmdb, and apt-get -s against a fixture dpkg status, using the real packages the tree builds. The older openwatch is a payload-free fixture at 1:0.7.1 that provides no engine. It must sort below the tree's own build (packaging/version.env's rc), which the first draft of this test got wrong: with the fixture at rc.5 the resolvers saw the same version already installed and tested nothing. A base fixture supplies every other requirement of the packages under test, derived from their own Requires and Depends. Scenarios in both formats: rules-only upgrade refused naming openwatch-kensa-engine; openwatch-only, coordinated and fresh install accepted; downgrade to the fixture refused; version ordering. Mutations, each red then restored with the hash checked: kensa-rules without the floor (rules-only and downgrade accepted, both formats) and openwatch without the provide (coordinated and fresh refused, both formats). The container test stays, without a criterion of its own, and package-smoke's kensa-rules-compat job runs it by its new name. AC-09's text now says how it is verified.
Founder decision 2026-09-26: S-7 is in v0.8. OpenWatch held three label
sources that disagreed (internal/framework's map, the Compliance tab's
id transform, and the report's first-token collapse), and the rule
library and scan detail grouped every nist* key as one "NIST" tone. So
an 800-53 report and an 800-171 report carried the same "NIST" on their
cover, OSCAL title and file name.
One source now: internal/kensa.FrameworkLabel wraps
pkg/kensa.FrameworkFromID. An id Kensa does not know is returned as it
is; OpenWatch derives no label.
- framework.Label (family labels) and the report scope label use it.
- The API carries it: label on GET /hosts/{id}/compliance/frameworks
and GET /reports/frameworks, framework_labels on GET /rules and GET
/scans/{id}. Additive fields; generated code refreshed.
- The UI renders them: lens chips and panels, the report picker, and
the rule library and scan detail tags (title and accessible name).
The rule library filter offers one option per framework, by label.
Signed artifacts: the attestation content still carries the exact key.
The scope label is computed at generation and stored, and every face
reads the stored value, so a report generated before this change keeps
its label, its JSON face still hashes to content_sha256 and its
signature verifies (api-reports AC-27).
Contracts: system-compliance-lens 1.7.0 C-08, AC-02 amended, AC-14;
api-reports 1.19.0 AC-07 and AC-09 amended, AC-27;
frontend-host-compliance-tab 1.7.0 AC-12 rewritten (unpublished, so in
place); frontend-reports 1.14.0 AC-09; frontend-rules-library 1.1.0
AC-05; frontend-scan-detail 1.2.0 AC-09.
Mutations, each red then restored with the hash checked. The first
backend round failed to build, because removing the only kensa call left
an unused import, so it proved nothing; each was re-run in a form that
compiles:
- Label upper-casing the id (AC-02);
- the scope label's first-token collapse (AC-07, AC-27);
- the host label set to the raw id (AC-14);
- scan detail labels emptied (AC-14);
- the chip rendering framework_id (AC-02);
- the rule filter ignoring labels (AC-05);
- tags ignoring labels (AC-05).
Visible changes: "CIS RHEL 9" reads "CIS (RHEL 9)", "PCI DSS 4" reads
"PCI DSS 4.0". Kensa formats only RHEL versions, so Ubuntu benchmarks
read "CIS (ubuntu22)"; requested from Kensa as CP features/KN-OW-023
rather than patched locally.
CP bugs/OW-081, design completed on founder authorization 2026-09-26. The earlier change guaranteed only that the resolver refuses. dpkg unpacks a package with an unmet Depends before failing, so a bare `dpkg -i` of kensa-rules 0.10.0 beside rc.5 replaced the corpus and left the package unconfigured, with every scan failing. That is an ordinary install path, not a bypass. Four DEB mechanisms were measured against the same scenarios before one was chosen: - Depends only: rules-only dpkg -i replaced the corpus. - Breaks on openwatch older than rc.6: refused dpkg -i, but made the tree's own pair uninstallable, because main builds as the published rc.5 version. - Pre-Depends: deadlocked with openwatch's own Depends, so even coordinated and fresh installs failed. - A preinst guard (chosen): refused rules-only dpkg -i and apt with every corpus file byte-identical, and accepted the apt coordinated upgrade, dpkg -i with openwatch listed first, fresh installs and main's own pair. Its one cost is dpkg -i with the rules listed first: refused, leaving openwatch upgraded beside the old corpus, which is a working pair, with a message naming the fix. packaging/kensa-rules/preinst.in reads openwatch's Status-Status and Provides through dpkg-query, so a held or half-installed openwatch is still checked, and compares with dpkg --compare-versions. RPM needed nothing more: dnf and rpm -U refuse before touching files. Measured, both formats: rolling openwatch back alone is refused; rolling both packages back in one command succeeds. The upgrade runbook now says so, with the recovery for a corpus forced on with --nodeps or --force-depends (plain apt refuses from that broken state; dpkg -i then dpkg --configure -a works). Contract: release-upgrade C-06 reworded as the boundary tested today, not a promise about future engines, and AC-10 added. AC-10 runs the preinst from the built package against a stub dpkg-query in Go CI. The container test gains the dpkg -i, rollback and file-digest checks, and passes on Ubuntu 24.04 and Rocky 9. Mutations, each red then restored with the hash checked: no preinst in the package; the guard checking only "installed"; ge weakened to gt.
detect-secrets rescan after the rebase moved flagged lines. No finding was added or removed; only line numbers changed.
…state and corpus separately The container test ran RPM transactions with tsflags=noscripts and checked only the recorded kensa-rules version plus a corpus digest. It did not cover a joint rpm -Uvh, dnf upgrade, or single-package upgrades in both orders. - RPM transactions now run their scriptlets. The openwatch upgrade scriptlet skips its migration when no database answers, so a container is enough. - New scenarios: dnf upgrade of both packages, a joint rpm -Uvh, and single-package upgrades in both orders through the package manager (and rpm -U on RPM). - After every step, package-manager state and corpus contents are checked as separate facts: each package's recorded version and a clean dpkg --audit or rpm -V, and a digest of /usr/share/kensa/rules compared with the payload of the kensa-rules package that should be installed. Removing the DEB preinst makes the refused dpkg -i step fail all three checks: version, dpkg --audit and corpus digest.
…nd disclose the Kensa package The CHANGELOG, the upgrade runbook and release-upgrade C-06 said a newer corpus is refused beside an older openwatch on every ordinary install path. That holds for the kensa-rules package OpenWatch builds. Kensa publishes a package with the same name and install path that declares no engine requirement, and openwatch's dependency on the name accepts it. The text described a protection that does not cover that package. - release-upgrade C-06 (1.1.0, not yet published) now scopes the MUST to the OpenWatch-built package and states the Kensa package as disclosed, not prevented (CP bugs/OW-081, criterion 3b). - The upgrade runbook gains "What this check does not cover": the Kensa package, hosts on rc.5 or earlier, how to tell the two packages apart, and how to restore OpenWatch's. Updating the rules now means both packages from one OpenWatch release. - The CHANGELOG qualifies the refusal and adds a known limitation. - The installation guide no longer says the rules update without an OpenWatch release, which the engine requirement made untrue. The secrets baseline moves only line numbers; no finding was added or removed.
remyluslosius
force-pushed
the
feat/kensa-v0.10.0
branch
from
September 28, 2026 00:42
5ba3480 to
82809ee
Compare
release-changelog C-02 and AC-02 allow only Added, Changed, Deprecated, Removed, Fixed and Security as category headings. #883 added "Upgrade notes" and "Known limitations" headings to [Unreleased], and main fails TestChangelog_UnreleasedCategoriesAreStandard. Go CI did not catch it: #883 changed only documentation, so the quality gate skipped every Go test. Both blocks move, unchanged in content, into the section's lead-in as labeled paragraphs, the form the candidate sections already use for text before their first category. No entry is dropped.
This was referenced Sep 28, 2026
remyluslosius
added a commit
that referenced
this pull request
Sep 28, 2026
…pts (#885) CP bugs/OW-081, the #882 acceptance list. The container test switched its RPM transactions from tsflags=noscripts to scriptlets, which dropped the noscripts case instead of adding scriptlets beside it. A pass with scriptlets is not evidence that the refusals hold on dependency resolution alone. The container test takes a mode: scripts (the default, unchanged) or noscripts (RPM only). In noscripts mode every dnf transaction carries --setopt=tsflags=noscripts and every rpm -U and rpm -Uvh carries --noscripts. All scenarios and both separate checks, package-manager state and corpus digest, run as before. The scriptlet check is inverted: it asserts no identity keys were provisioned, which proves the mode took effect. package-smoke gains a third job, "kensa-rules compat rockylinux:9 noscripts"; the two existing job names are unchanged. Local run against main's packages from ab68f30 and the v0.7.1 GA: noscripts 39 of 39, scripts 39 of 39, the only difference the inverted scriptlet check. A copy with the noscripts flags removed failed on that check alone.
remyluslosius
added a commit
that referenced
this pull request
Sep 28, 2026
Stage 1 for the sixth 0.8.0 candidate, from main fc1117d. VERSION is 0.8.0-rc.6 in packaging/version.env, the README phrase and the newest CHANGELOG heading; CODENAME stays Eyrie. The hygiene test binds the three. The changelog section records rc.5 on facts: built, every machine gate passed, assets published as a pre-release, no human verdict recorded for its fleet checks, documentation review or release-captain signature, tag and assets preserved. Since rc.5: #870 to #881, #883 and #882. The [Unreleased] notes move into the rc.6 section unchanged. Known limitations gain the two the readiness record lists as shipping with v0.8: drift does not distinguish a corpus change from a host change (D-2 S-3, accepted 2026-09-26), and scan variable values are not type checked (OW-080). Next unused candidate number verified: no v0.8.0-rc.6 tag on the remote or locally, and no release or draft of that name. No tag, publication or attestation.
remyluslosius
added a commit
that referenced
this pull request
Sep 28, 2026
Stage 1 for the sixth 0.8.0 candidate, from main fc1117d. VERSION is 0.8.0-rc.6 in packaging/version.env, the README phrase and the newest CHANGELOG heading; CODENAME stays Eyrie. The hygiene test binds the three. The changelog section records rc.5 on facts: built, every machine gate passed, assets published as a pre-release, no human verdict recorded for its fleet checks, documentation review or release-captain signature, tag and assets preserved. Since rc.5: #870 to #881, #883 and #882. The [Unreleased] notes move into the rc.6 section unchanged. Known limitations gain the two the readiness record lists as shipping with v0.8: drift does not distinguish a corpus change from a host change (D-2 S-3, accepted 2026-09-26), and scan variable values are not type checked (OW-080). Next unused candidate number verified: no v0.8.0-rc.6 tag on the remote or locally, and no release or draft of that name. No tag, publication or attestation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Integrates Kensa v0.10.0 and completes D-2 S-7, per CP
projects/openwatch/V0_8_0_READINESS. Rebased ontomain25b1794fon 2026-09-27. Awaiting one founder merge decision. The earlier blockers are settled: S-3 is accepted as a v0.8 limitation (2026-09-26), and the long-term packaging design is the joint embedding decision (2026-09-27, CPfeatures/KN-OW-024), which does not approve this PR by itself.Commits
9cfa51b3Kensa v0.10.0.nist_800_171andcmmc_l2.api-system-scan-configAC-11).1278018fEngine and corpus pairing (OW-081).openwatchprovidesopenwatch-kensa-engine;kensa-rulesrequires at least its own version.d635a119configure_meand NIST lift.nistprojection counts 800-53 only (api-remediationAC-18).b7454d4bAC-09 in Go CI. The pairing is checked against the resolvers (rpm --test,apt-get -s).d9d2efd7D-2 S-7.FrameworkFromIDthroughinternal/kensa.api-reportsAC-27).system-compliance-lens1.7.0 C-08, AC-14.8c51e98aDEBpreinst.preinstrefuses before any file is replaced, so a baredpkg -ino longer leaves a newer corpus on disk.release-upgradeC-06 is the boundary tested today; AC-10 added.40ce447fSecrets baseline. Line numbers only, after the rebase.1af21ea8Packaging tests completed.tsflags=noscripts).dnf upgradeof both packages, a jointrpm -Uvh, and single-package upgrades in both orders.82809ee8Protection scoped to what it covers.kensa-rules, and disclose that Kensa's package of the same name is not checked.6c3cb5cfCHANGELOG categories.[Unreleased], whichrelease-changelogC-02 and AC-02 forbid.mainfails that test; its Go CI skipped the Go suite because docs(release): record the changes since rc.5 and correct the incident guidance #883 was docs-only (CPbugs/OW-086).Visible changes
features/KN-OW-023).kensa-rules, a rules-only upgrade onto an olderopenwatchis refused with nothing changed, on dnf,rpm -U, apt anddpkg -i.What the packaging does and does not protect
kensa-rules0.10.0 besideopenwatchv0.7.1 or rc.5rpm -U, apt anddpkg -ikensa-rulesbesideopenwatchrc.5 or earlierkensa-rulesbeside this buildREADME.mddiffers); engine 0.10.0 loads all 779. A future Kensa corpus is not checkedpkg/kensa.LoadRulesrpm --nodeps,dpkg --force-*The Kensa-published rows are disclosed, not prevented: C-06, the CHANGELOG known limitations and the upgrade runbook state them (CP
bugs/OW-081, criterion 3b). The long-term fix is the accepted embedding direction, planned for v0.9 and not in this PR.S-3 measurement (summary)
Evidence at
6c3cb5cf6c3cb5cf: 25 checks pass, 6 skipped (triage and labeling automation only). Go CI 36363780217, CodeQL 36363780238, Package smoke 36363780199.kensa-rules compatin package-smoke, against the published v0.7.1 packages, scriptlets on: RPM 41 checks passed (job 108746415473), DEB 37 (job 108746415464). Covers the refused rules-only upgrade (dnf,rpm -U, apt,dpkg -i), openwatch-only, coordinated,dnf upgrade, jointrpm -Uvh, single-package upgrades in both orders, fresh install, refused downgrade and joint rollback. After every step, package-manager state (recorded version,dpkg --auditorrpm -V) and corpus contents (digest against the expected package payload) are checked separately.preinstfails the refuseddpkg -istep on all three checks: version,dpkg --audit, corpus digest.82809ee8: Go CI 36363190972 failed only onTestChangelog_UnreleasedCategoriesAreStandard(AC-02), fixed in6c3cb5cf. Kept here as the record.internal/serverat the Makefile's 10-minute limit (CI allows 1800 s, CPbugs/OW-066); hosted phase 2 passed.pkg/kensa.LoadRules, as in the table above.