Skip to content

Commit 14ba666

Browse files
docs(ci): warn future cosign-installer bumpers about --bundle requirement
QA-driven follow-up to 892cf3f. The §8 review surfaced a HIGH- severity foot-gun for any future contributor who bumps the cosign-installer pin past v3 + bumps `cosign-release` past v2.x: Per cosign-installer v4.0.0 release notes (2025-10-16): "In version v3+, using `cosign sign-blob` requires adding the `--bundle` flag which may require you to update your signing command." We currently pin `cosign-release: 'v2.4.1'`, so the `cosign sign- blob` calls in release.yml are fine TODAY. The trap is: 1. Future bumper raises cosign-installer@v3 → v4 (safe alone) 2. Same bumper raises cosign-release v2.4.1 → v3.x (BREAKS: sign-blob now requires --bundle) 3. Workflow either fails outright or — worse — silently emits signatures in a format `cosign verify-blob` rejects, a silent supply-chain regression Mitigation: warn in BOTH source-of-truth locations: - release.yml inline comment (line 35-44): "⚠ FUTURE BUMPER WARNING" block citing the cosign-installer v4.0.0 release notes + the conditional `--bundle` requirement - DECISION_LOG.md 2026-05-20 row maintenance rule: extends the existing rule with the same checklist item, keeps both sources in sync No behavioral change. Both files lint-clean against doc-drift.
1 parent dd48177 commit 14ba666

2 files changed

Lines changed: 11 additions & 1 deletion

File tree

.github/workflows/release.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ jobs:
3232
# critical and the 2026-05-13 §8 verification is keyed to its
3333
# behavior. v3→v4 would require re-doing the §8 dry-run on a
3434
# fresh throwaway tag, scheduled for a dedicated cycle.
35+
#
36+
# ⚠ FUTURE BUMPER WARNING (per cosign-installer v4.0.0 release
37+
# notes, 2025-10-16): cosign-installer@v4 supports BOTH Cosign
38+
# v2.x and Cosign v3+. The bump itself is safe AS LONG AS the
39+
# `cosign-release` field below stays on v2.x. If you ever bump
40+
# cosign-release to v3.x or later, the `cosign sign-blob` calls
41+
# below MUST add `--bundle` (in v3+ the sign-blob signature
42+
# format changed and the flag became required). Without it, the
43+
# workflow will fail or emit invalid signatures. See DECISION_LOG
44+
# 2026-05-20 row for the full bump-safety checklist.
3545
- uses: actions/checkout@v6
3646

3747
- name: Set up Python

docs/DECISION_LOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ When making a tech choice with multiple valid options, record it here BEFORE dep
3434
| 2026-05-01 | **Kill `.btn-success` taxonomy too; collapse all green buttons to Splunk-bundled `.btn-primary` (build 635).** | (a) Keep `.btn-success` as a parallel rule with our own muted shade; (b) override Splunk's `.btn-primary` to our muted shade so all greens match; (c) migrate every `.btn-success` callsite to `.btn-primary` and delete the rule. | The build-634 desaturation pass kept `.btn-success` muted (`#388e3c`) while `.btn-primary` rendered Splunk's vivid `#1a8929`. User-facing result: "+ Add Row" / "+ Add Column" (btn-primary) and Save Changes / Approve (btn-success) had two slightly-different greens side-by-side on the same toolbar — visible inconsistency that the user flagged. (a) Maintaining a parallel rule has the same long-term liability as `.wl-btn` did (see 2026-05-01 prior entry). (b) Overriding Splunk's bundled `.btn-primary` is risky — it could affect Splunk-native UI elsewhere on the dashboard (Edit / Export / Cancel buttons in Splunk modals). (c) is the same playbook as the wl-btn migration: 5 callsites in 4 files, single-line search-and-replace per file, zero handler changes (handlers find by `#id`, not class). | Low — re-add the `.btn.btn-success` rule to `whitelist_manager.css` and revert the 5 callsite edits. The `.btn.btn-danger` and `.btn.btn-warning` muted rules (also build 634) are unaffected — those colours have no Splunk bundled equivalent so we keep owning them. **Maintenance rule (search-and-replace as a workflow)**: when removing a parallel CSS taxonomy, the operation is a class-rename via grep, NOT a refactor. The pattern: (1) `grep btn-success` for every callsite, (2) Edit each callsite's class string in place, (3) delete the now-orphan CSS rule, (4) verify no callsites remain. Components-based apps would centralize this in one template; vanilla-JS Splunk apps render HTML strings inline per module, so consistency relies on grep + discipline. When facing a similar audit (ANY parallel-CSS-system removal), reach for the search-and-replace workflow first; resist the urge to "abstract" or "centralize" because there is no shared template layer to put the abstraction in. |
3535
| 2026-04-29 | **Declare security-hardening track CLOSED at build 629 (round 9).** No further proactive hardening rounds. Future inbound work that does NOT match a re-opening signal (CVE, production incident, external audit finding, Q3 routine surfacing major-version compat work, or methodology shift to a fresh fuzz surface) is feature work, not hardening work. | (a) Continue with rounds 10+ at the same cadence; (b) move to a 6-month re-audit cycle with no per-round structure; (c) formal closure with explicit re-open criteria. | 9 rounds covered every reasonable security gap. Round 8 fuzz found 0 bugs; round 9 was pure housekeeping with no `app.conf [install] build` bump — the natural diminishing-returns signal. CI gates (4 Semgrep rules + doc-drift + quarterly pip-audit + unit tests on every PR), live FIM monitoring (15s + ~2s paths + dual-store baseline), recurring audits (Q3 2026 version-pinning routine), and Sigstore signing of releases now make the system self-sustaining without further rounds. Continuing past clear diminishing returns risks (a) hardening fatigue masking real signal, (b) churn-without-substance erosion of the changelog's signal-to-noise, (c) future contributors expecting a "round N" cadence and queuing low-value work to fit. Closing prevents this. | Low — any re-opening signal (CVE, incident, audit finding, methodology shift, major-version compat) immediately re-opens with a new round entry. Closing is a status declaration, not an architectural change. The closing summary at the top of `CHANGELOG.md` is the canonical artifact; future contributors read it before queuing security work. **Maintenance rule**: do NOT propose "round 10" by default. The next round must be triggered by an inbound signal, not by schedule. |
3636
| 2026-05-19 | **Fix `_execute_replay_revert_csv` by delegation to canonical `revert_csv_pipeline` (build 663)**, mirroring the pattern used by `create_rule`/`delete_rule`/`delete_csv` handlers. Add `"revert"` as an alias for `"revert_csv"` in `REPLAY_HANDLERS` so the dispatch table matches the handler's stored `action_type` literal. | (a) Delete `_execute_replay_revert_csv` and the dispatch entry entirely, since `wl_handler.py:6761` short-circuits revert approvals to `self._revert_csv` and the replay path is dead in production; (b) fix the in-function bugs in place (resolve path before calling `get_versions_dir`, pass `csv_path` not `csv_file` to `read_version_manifest`, read `version_filename` not `version_id`, fix the manifest iteration); (c) replace the whole body with a delegation to `revert_csv_pipeline`. | The replay function had three dormant bugs (no-arg `get_versions_dir()`, wrong-arg `read_version_manifest`, `version_id` vs `version_filename` field mismatch). (a) Removing the dispatch entry creates an architectural-contract trap: future contributors who consolidate approval paths will discover the replay layer is half-built and either silently broken or missing-by-design. (b) Fixing in place keeps a parallel implementation of revert logic that has to track every change to the direct-handler path (`wl_handler.py:_revert_csv` → `revert_csv_pipeline`); two sources of truth diverged exactly the way (b) would invite. (c) Delegation collapses both paths to the same pipeline call — replay becomes a thin wrapper over the same business logic, which is what the other approval handlers already do (`create_rule_pipeline`, `delete_rule_pipeline`, `delete_csv_pipeline`). Coverage rose 79% → 92% on `wl_replay.py` because the new body is small + fully reachable from tests. | Low — `git revert d267ea3`, re-introduces the broken body. The dispatch entry alias (`"revert" → _execute_replay_revert_csv`) is a separate concern and can stay if the underlying handler is removed — REPLAY_HANDLERS aliasing was added defensively to match future routing intent. **Maintenance rule**: when a replay handler exists for an `action_type`, it MUST delegate to the same canonical pipeline the direct-handler path uses. Do NOT reimplement the business logic in the replay layer — single source of truth keeps drift impossible. |
37-
| 2026-05-20 | **Partial Node-20 deprecation bump in `release.yml`** — bump `actions/checkout@v4 → @v6` and `actions/setup-python@v5 → @v6` to close §8 side-finding #1 from the 2026-05-13 Sigstore dry-run. Leave `sigstore/cosign-installer@v3` deliberately unbumped despite v4.1.2 being GA. The 13 other workflows (`a11y-audit.yml`, `appinspect.yml`, `appinspect-api.yml`, `ci.yml`, `codeql.yml`, `docs.yml`, `e2e-full.yml`, `e2e-smoke.yml`, `integration-tests.yml`, `pip-audit.yml`, `scorecard.yml`, `secret-scan.yml`, `semgrep.yml`, `validate-and-package.yml`, `zap-baseline.yml`) ALSO pin Node-20-era versions and need a separate sweep. | (a) Full project-wide sweep of all 14 workflows in one commit, including cosign-installer v3→v4; (b) bump everything except cosign-installer (signing-critical) in a single sweep; (c) **bump only the two actions §8 explicitly called out + only in release.yml**, defer rest to dedicated cycles. | (a) bundles a signing-critical action change (cosign-installer v3→v4) with routine Node-version bumps, invalidating the 2026-05-13 §8 verification in a non-atomic commit — if a verification step regresses, the cause could be the signing-installer OR any of the other bumps. Recovery requires bisecting across 14 files. (b) is the right scope long-term but is still a 13-workflow change that needs CI verification for each; doing it in this session would mean shipping ~14 untested workflow changes. (c) keeps the change surgical: 2-line edit, no Sigstore re-verification needed (the signing path is untouched), and the 2026-05-13 §8 dry-run remains the authoritative verification artifact. The 2026-09-16 GitHub deprecation deadline is ~4 months away — there's runway to do the full sweep in a dedicated cycle with per-workflow CI verification. The two flagged actions are the ones the §8 dry-run actually warned about, so the closure has a direct provenance link to the side-finding. | Low — `git revert` the bump commit reverts to v4/v5 pins; the 2026-09-16 deadline is the hard constraint, so revert is safe as long as the full sweep happens before then. **Maintenance rule**: bumping `cosign-installer@v3 → v4` MUST be done in a commit that also re-runs `docs/RELEASE_CHECKLIST.md` §8 on a fresh `v0.0.0-sigstore-test-N+1` tag. The §8 verification is keyed to the signing-installer version; changing it invalidates the static verification artifact. Maintain the same rule for any future signing-installer major bump. |
37+
| 2026-05-20 | **Partial Node-20 deprecation bump in `release.yml`** — bump `actions/checkout@v4 → @v6` and `actions/setup-python@v5 → @v6` to close §8 side-finding #1 from the 2026-05-13 Sigstore dry-run. Leave `sigstore/cosign-installer@v3` deliberately unbumped despite v4.1.2 being GA. The 13 other workflows (`a11y-audit.yml`, `appinspect.yml`, `appinspect-api.yml`, `ci.yml`, `codeql.yml`, `docs.yml`, `e2e-full.yml`, `e2e-smoke.yml`, `integration-tests.yml`, `pip-audit.yml`, `scorecard.yml`, `secret-scan.yml`, `semgrep.yml`, `validate-and-package.yml`, `zap-baseline.yml`) ALSO pin Node-20-era versions and need a separate sweep. | (a) Full project-wide sweep of all 14 workflows in one commit, including cosign-installer v3→v4; (b) bump everything except cosign-installer (signing-critical) in a single sweep; (c) **bump only the two actions §8 explicitly called out + only in release.yml**, defer rest to dedicated cycles. | (a) bundles a signing-critical action change (cosign-installer v3→v4) with routine Node-version bumps, invalidating the 2026-05-13 §8 verification in a non-atomic commit — if a verification step regresses, the cause could be the signing-installer OR any of the other bumps. Recovery requires bisecting across 14 files. (b) is the right scope long-term but is still a 13-workflow change that needs CI verification for each; doing it in this session would mean shipping ~14 untested workflow changes. (c) keeps the change surgical: 2-line edit, no Sigstore re-verification needed (the signing path is untouched), and the 2026-05-13 §8 dry-run remains the authoritative verification artifact. The 2026-09-16 GitHub deprecation deadline is ~4 months away — there's runway to do the full sweep in a dedicated cycle with per-workflow CI verification. The two flagged actions are the ones the §8 dry-run actually warned about, so the closure has a direct provenance link to the side-finding. | Low — `git revert` the bump commit reverts to v4/v5 pins; the 2026-09-16 deadline is the hard constraint, so revert is safe as long as the full sweep happens before then. **Maintenance rule (cosign-installer bumps)**: bumping `cosign-installer@v3 → v4` MUST be done in a commit that also re-runs `docs/RELEASE_CHECKLIST.md` §8 on a fresh `v0.0.0-sigstore-test-N+1` tag. The §8 verification is keyed to the signing-installer version; changing it invalidates the static verification artifact. Maintain the same rule for any future signing-installer major bump. **Additional checklist item (per cosign-installer v4.0.0 release notes, 2025-10-16):** cosign-installer v4 supports BOTH Cosign v2.x and v3+; the v3→v4 action bump itself is safe AS LONG AS the `cosign-release:` pin stays on v2.x. If you ALSO bump `cosign-release` to v3+ at the same time (or later), the `cosign sign-blob` calls in `release.yml` MUST add `--bundle` because the v3+ sign-blob signature format changed and the flag became required. Without it the workflow either fails outright or (worse) emits signatures in a format `cosign verify-blob` rejects — silent supply-chain regression. Documented in the release.yml inline comment AND here so both source-of-truth locations carry the warning. |
3838
| 2026-05-11 | **E2E tests CI-gated via TWO workflows.** `e2e-smoke.yml` runs ~3 non-destructive E2E flow tests on every PR (~5 min). `e2e-full.yml` runs the entire 20-test E2E suite (destructive + visual regression + concurrency + stress) on a nightly UTC schedule and via manual `workflow_dispatch`. Smoke selection: `test_trash_traversal.cjs` + `test_rate_limit_burst.cjs` + `test_control_panel_long_content.cjs` — all UI-driven, no destructive helpers, exercise the REST → frontend stack end-to-end. The destructive `WL_TEST_HARNESS=1` env var is set only inline per nightly step, never globally. | (a) Full CI on every PR (run all 22 on each PR); (b) tag-gated (PR label `e2e` to run any E2E); (c) manual `workflow_dispatch` only with no nightly; (d) status quo (E2E tests never run in CI, only ad-hoc on developer machines). | (a) is rejected because 20 tests × ~30-60s + Playwright + container setup = 30+ min added to every PR, multiplied across every contributor push. Rate-limit collisions in the integration suite (a documented Ring 3 finding) would be worse for E2E since the destructive E2E tests deplete shared counters faster than the integration suite. (b) shifts the gating decision to contributors who may forget the label — over time the signal degrades to "nobody runs E2E in CI". (c) is what (d) effectively becomes: opt-in tools get used heavily for a month then forgotten. (d) is the prior state — 20 tests with real bug-finding signal lived entirely outside CI, so PR-introduced regressions had to wait for a developer's manual run to surface. The chosen two-workflow shape preserves PR feedback latency (smoke <5 min) while ensuring the full suite runs at least daily; failures in the nightly run upload artifacts and surface in the GitHub Actions summary the next morning. Mirrors the standard test-pyramid principle: heavier tests run less frequently but never skip. | Low — to revert to "full E2E on every PR": change `schedule` and `workflow_dispatch` to `pull_request` in `e2e-full.yml` and delete `e2e-smoke.yml`. To revert to status quo: delete both workflow files. The two-workflow shape is intentional separation; merging them would re-introduce the latency cost (a) was rejected for. **Maintenance rule (adding a new E2E test)**: by default, NEW tests go to the nightly full workflow. Only promote to smoke after the test has been stable in nightly for ≥2 weeks AND a smoke slot opens up (we cap smoke at ~5 tests to keep PR latency <5 min). If you promote a test to smoke, document the choice in the workflow file's comments and remove an existing one if the cap is hit. |
3939

4040
**When a past decision is reversed**: add a NEW row with the new choice and a "Why reversed: see <YYYY-MM-DD> row" note. Do NOT delete or edit the old row — it is evidence for the next person who proposes the same losing option.

0 commit comments

Comments
 (0)