Repository navigation
docs(release): record the changes since rc.5 and correct the incident guidance - #883
Merged
Merged
Conversation
… guidance CHANGELOG [Unreleased] gains the ten PRs merged after v0.8.0-rc.5 (#870 to #879; #874 is CI-only and is not listed). Upgrade notes lead: the 0065 migration signs everyone out, cookie logout requires the CSRF token, and the audit export refuses an unknown parameter. Each entry was checked against the merged code: the 0065 migration body, the binder's sid check and EvaluateBearerBinding, the logout CSRF branch, the LockWaitBound, OperationDeadline and RollbackCleanupLimit constants, and the auth.login.failure and admin.user.enabled declarations in audit/events.yaml. Known limitations name CP bugs/OW-072 and OW-062. QUICKSTART's incident step said active sessions end "via logout" and told operators to rotate passwords. Logout ends one login, and a user's own password change signs out nothing else (OW-072). It now names disable and the administrator reset, which end every interactive credential since #875 and #876. SECURITY_INCIDENT said an access token is ended only by rotating the signing key. Since #876 it names its session and is refused once that session is revoked, so revoking the rows ends it with no restart. Key rotation is kept, scoped to a key that may itself be exposed.
Three defects in SECURITY_INCIDENT, all present in v0.8.0-rc.5 (CP
bugs/OW-082), kept in their own commit so they can be dropped
independently.
- "There is no is_active flag; disabling an account means
soft-deleting it." POST /api/v1/users/{id}:disable has existed since
#601 and, since #875, ends every interactive credential. The section
now leads with disable, which :enable reverses, and keeps delete and
the SQL fallback with what each does and does not do.
- The delete was said to be audited as account.user.deleted, which is
the host-side /etc/passwd event. DeleteUserByID emits
admin.user.deleted.
- Recovery verification step 3, headed "No live sessions for disabled
accounts", checked only deleted_at. It now checks disabled_at too.
remyluslosius
force-pushed
the
docs/v0-8-0-changelog-and-incident-guidance
branch
from
September 27, 2026 01:23
bc34d1a to
13ccc3b
Compare
remyluslosius
deleted the
docs/v0-8-0-changelog-and-incident-guidance
branch
September 27, 2026 01:35
remyluslosius
added a commit
that referenced
this pull request
Sep 28, 2026
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.
remyluslosius
added a commit
that referenced
this pull request
Sep 28, 2026
* feat(kensa): integrate Kensa v0.10.0 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). * fix(packaging): refuse a Kensa corpus beside an older engine 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. * fix(kensa): flag variables the operator must decide and keep NIST lift 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). * test(packaging): verify the engine pairing against the resolvers in Go 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. * feat(frameworks): name every framework with Kensa's label (D-2 S-7) 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. * fix(packaging): never unpack a Kensa corpus beside an older engine 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. * chore(secrets): refresh baseline line numbers after rebasing onto main detect-secrets rescan after the rebase moved flagged lines. No finding was added or removed; only line numbers changed. * test(packaging): run the pairing scenarios with scriptlets and check 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. * docs(packaging): scope the corpus check to OpenWatch-built packages and 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. * docs(changelog): keep [Unreleased] to the standard categories 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.
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.
Documentation for everything merged after v0.8.0-rc.5, plus one pre-existing runbook defect in a separate commit.
Commit 1: release notes and incident guidance for #870 to #879
[Unreleased]covers the ten PRs since rc.5 (ci(go): run internal/server in its own test invocation, alone #874 is CI-only and not listed). It has upgrade notes, Security, Changed, Fixed and Known limitations sections. Each entry was checked against merged code: the 0065 migration body, the bindersidcheck andEvaluateBearerBinding, the logout CSRF branch, theLockWaitBound/OperationDeadline/RollbackCleanupLimitconstants, and theauth.login.failureandadmin.user.enableddeclarations inaudit/events.yaml.bugs/OW-072). It now names disable and the administrator reset.Commit 2: CP
bugs/OW-082(droppable)All three defects are present in rc.5. This is proposed under the interruption rule's operator-text clause and can be dropped without affecting commit 1.
:disablehas existed since feat(remediation): free-core execution engine (Fix + rollback, kensa v0.5.1) #601 and ends every interactive credential.account.user.deleted, the host/etc/passwdevent. The real code isadmin.user.deleted.deleted_at.Merge-order note
#880, #881 and #882 each add an entry to
CHANGELOG.md[Unreleased], and #881 edits the API-token row of the same SECURITY_INCIDENT table. Whichever merges second rebases. The conflicts are textual; no entry contradicts another.Verification
check-doc-style.pyclean on all three files; pre-commit clean (the.secrets.baselinechange is the hook's line-number refresh).