You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
Copy file name to clipboardExpand all lines: docs/DECISION_LOG.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -34,7 +34,7 @@ When making a tech choice with multiple valid options, record it here BEFORE dep
34
34
| 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. |
35
35
| 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. |
36
36
| 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. |
38
38
| 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. |
39
39
40
40
**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