fix(ui): make toast notifications opaque instead of ~50% transparent - #484
Merged
Conversation
Contributor
schubydoo
enabled auto-merge (squash)
June 19, 2026 23:28
schubydoo
added a commit
that referenced
this pull request
Jun 20, 2026
## What Migrates clauster's release pipeline from **release-please** to **knope**, using a **changesets-only** model. This is the Phase-2 cutover from the proposal in `scratch/knope-migration-plan.md`, authorized to land now. Every user-facing change now ships a `.changeset/*.md` fragment that drives **both** the version bump and the changelog (`ignore_conventional_commits = true`), so release notes can carry the captured "why" instead of terse commit subjects. knope replaces **only** release-please's orchestration (version PR + changelog + draft-release creation) — the build / Sigstore-sign / `actions/attest` / publish supply chain and `release.yml` (PyPI + GHCR on the tag) are **unchanged**. ## How it works now - **`knope-prepare.yml`** (`push: main`) — when a `.changeset/*.md` is pending, knope bumps `pyproject.toml` + `src/clauster/__init__.py` + `CHANGELOG.md`, resyncs `uv.lock`, and opens/refreshes the `release` PR (`chore: prepare release X.Y.Z`). Gated on changeset *presence*, so a genuine knope failure fails the job **loudly** (no blanket `continue-on-error`); an ordinary push is a clean no-op. - **`knope-release.yml`** (the `release` PR merging) — builds the 5-target binaries, Sigstore-signs dists + binaries, attests SLSA provenance, runs a **fail-closed gate** (aborts unless the full signed set is present), then `knope release` natively does draft → upload assets → publish. The tag is created at publish and pushed as the clauster-ci App so it triggers `release.yml`. The immutability invariant (tag only at publish, assets attached to the draft first) is preserved. - **`changeset-check.yml`** — advisory, **non-blocking** nudge on `src/` PRs without a changeset (opt out with the `no-changelog` label). Triggered on `pull_request: closed` + `head_ref == 'release'` rather than a commit-message marker — the repo squash-merges and a squash subject is editable, so head_ref is the reliable signal. The release job checks out `merge_commit_sha` (the squash commit on main) so knope tags a commit that actually landed on main. ## Removed / updated - Deleted `release-please-config.json`, `.release-please-manifest.json`, `.github/workflows/release-please.yml`. - Refreshed `CONTRIBUTING.md` (the changeset workflow), the PR template, the `no-changelog` label, `.bestpractices.json`, and the now-stale `release-please` comments across the workflows/config. - Included a changeset for the pending toast-opacity fix ([#484](#484)) so knope's **first** release ships it as **0.12.1**. ## Validation - Reviewed adversarially by `clauster-ci-auditor` (twice — it caught a real silent-never-publish path in an earlier trigger design, now fixed): immutability / fail-closed gate, attest-before-sign ordering, App-token tag trigger, SHA-pinning, fork-safe advisory check, and prepare/release mutual-exclusion — all confirmed. - `knope prepare-release --dry-run` against this branch computes **0.12.1** with a correct `### Fixes` entry. - `yamllint` + `ruff` + `markdownlint` green (pre-commit). ## Maintainer notes (release-path — HOLD-for-maintainer) - **Cutover**: merging this opens knope's own `chore: prepare release 0.12.1` PR. The stale release-please PR [#486](#486) is superseded and being closed. - **First knope release** will pause at the `pypi` protected-environment approval (unchanged, in `release.yml`) — that's yours to approve. - The `RELEASE_PLEASE_APP_*` secret names are intentionally **kept** (renaming would require re-adding the repo secrets); the comments now explain they are the clauster-ci App credentials. - Local-only `.claude/rules/release-safety.md` still says "cut by release-please" — gitignored, not in this PR; update at your convenience. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Schuby <12485317+schubydoo@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
schubydoo
added a commit
that referenced
this pull request
Jun 20, 2026
## What Backfills `([#492])` into the `harden-untrusted-readers` changeset so 0.12.1's changelog entry is correctly linked — matching the toast entry's `([#484])`. The harden fix + its changeset both shipped in #492, but the changeset was authored without a link (the number didn't exist yet), so without this it would ship unlinked. Dry-run confirms both pending 0.12.1 entries now render with their links and no double-link. ##⚠️ Merge order - Merge this **before** [#491](#491) (the 0.12.1 release) so it lands in 0.12.1. - Then #491 (release), then [#493](#493) (the change_templates config — auto-links from 0.12.2 on, so no more manual backfills). Changeset-content only — no `src`, no new changeset needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Schuby <12485317+schubydoo@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
schubydoo
pushed a commit
that referenced
this pull request
Jun 20, 2026
Merging this PR tags and publishes **v0.12.1**. Generated by knope from the `.changeset/` fragments — don't edit it by hand; add or amend a changeset on the source PR instead. --- ## Fixes - Harden two untrusted-input readers against malformed input (both surfaced by new fuzz harnesses): the CSRF/CORS origin check no longer returns a 500 on an `Origin` header with an out-of-range or non-numeric port, and project discovery no longer crashes on a non-dict `~/.claude.json` — each now degrades safely ([#492](#492)). - Toast notifications now render fully opaque instead of ~50% transparent, so they stay readable over busy page content ([#484](#484)). Co-authored-by: clauster-ci[bot] <289303168+clauster-ci[bot]@users.noreply.github.com>
schubydoo
added a commit
that referenced
this pull request
Jun 20, 2026
## What Adds a `[release_notes] change_templates` config so knope **auto-appends the PR number** to every changelog entry, resolving `$pr_number` (knope 0.23.0+) to the PR that introduced each changeset. This closes the gap spotted on [#491](#491): without it, knope prints the changeset body verbatim, so an entry only had a PR link if the author *typed* one (the toast entry had `([#484])` only because it was added by hand; the harden-readers entry had none). Now: - **Authors write a plain summary** — no PR number (you don't have it at authoring time). - **knope appends `([#NNN])`** at release time, tracing the changeset's commit → PR. The ordered template chain handles every shape: a headed/complex changeset keeps its `### + body`, a one-liner renders as a bullet, and either drops the `(#NNN)` suffix when a change isn't yet traceable to a committed PR (e.g. a local `--dry-run`, where knope shows a `#1234` placeholder). ##⚠️ Best merged AFTER [#491](#491) (the 0.12.1 release) The **toast changeset is a backfill** — it was added in the cutover (#487) while its fix was #484 — so `$pr_number` resolves to the *cutover* PR, not the fix, and it would **double-link** with the manual `([#484])` still in its body. Merging this after 0.12.1 ships means: - 0.12.1 keeps the correct manual `([#484])` for the toast entry. - This template applies cleanly from **0.12.2** onward, where every changeset is authored in the same PR as its change, so `$pr_number` is always correct. If it lands first, the only effect is a one-time double-link on that single toast entry, which I'll clean up. ## Validation `knope prepare-release --dry-run` renders both pending 0.12.1 entries with the `([#…])` suffix correctly (the real numbers resolve in CI; the dry-run shows knope's `#1234` placeholder). Config + docs only — no `src`, so no changeset is needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Schuby <12485317+schubydoo@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: clauster-ci[bot] <289303168+clauster-ci[bot]@users.noreply.github.com>
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.
Reported: the toast/notification box is too transparent — dashboard content shows through it.
Root cause: toasts are Tabler
.alertcards (.toast-stack→.alert.alert-*). Tabler computes.alertbackground ascolor-mix(in srgb, var(--tblr-alert-bg), var(--tblr-bg-surface))where--tblr-alert-bgis itselfcolor-mix(… 10%, transparent)— so the fill lands ~50% opaque over the fixed-position toast and the page shows through.Fix: one CSS rule scoped to
.toast-stack .alertthat re-mixes the per-type tint (var(--tblr-alert-color)) into the solidvar(--tblr-bg-surface), so the toast is opaque while keeping its per-type colour. Theme-safe (both vars are theme-reactive).Reviewed by
clauster-frontend-reviewer: APPROVE — specificity(0,2,0)wins over Tabler.alert(0,1,0)without!important, scoped to only the toast region (no collateral on the ~15 other.alertuses), contrast-neutral (≤0.2 delta), holds in light + dark themes, zero XSS surface.