phase: 101_tokens_page_overhaul
All gates verified green — no defects found, nothing to fix. Final report:
## Phase 101 — final verification pass (all tasks already complete; verified, not re-implemented)
**Verified against the working tree** (task files 01–04 present in `complete/`):
- Active/revoked table split (Status column gone, section hidden while 0 revoked, per-table search with query state surviving re-renders) in `frontend/index.html` + `tokens.js`
- `generateToken()` refuses blank/whitespace names (`Give the token a name first.`, no request); `|| "token"` fallback deleted
- Atomic rotation: `regenerate_token` service + `POST /api/tokens/{id}/regenerate` (201 new-plaintext-once / 404 / 409 / router-wide 403) + `TokenListItem.revoked_at` (D5)
- Regenerate two-step confirm UI + CSS (`.token-regenerate`, neutral hover, no new hue); A4 pins intact
**Test / lint / coverage results:**
- `uv run pytest` → **2065 passed**
- `uv run pytest --cov=app --cov-report=term-missing` → **TOTAL 99%** (>90% ✓)
- `uv run ruff check . && uv run pyright` → clean (0 errors)
- `uv run pytest tests/e2e/test_tokens_page.py -v --no-cov` → **4 passed** (isolation, DB up)
- Regression, each in isolation: `test_api_tokens.py` **9 passed**, `test_admin_auth.py` **6 passed**, `test_shared_header.py` **6 passed**, `test_theme_semantic_completion.py` **8 passed** (its revoked-pill pin was correctly re-scoped to the revoked table in this phase)
**Completion criteria:** 1 ✓ split+search (E2E 1–2) · 2 ✓ required name (E2E 3 + source pin) · 3 ✓ rotation end-to-end, old token refused at gate (E2E 4 + API 404/409 pinned) · 4 ✓ A4 holds (list carries no plaintext/hashes) · 5 ✓ suite/coverage/lint green · 6 ✓ E2E + regressions green in isolation · 7 commit left to the harness per executor rules (all changes uncommitted in the working tree)
**Deviations:** none. Next pending phase: `98_sync_summary_visibility`.
This commit is contained in:
@@ -3167,14 +3167,66 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
|
||||
}
|
||||
.token-revoke:hover:not(:disabled) { background: var(--err-bg); color: var(--err-ink); border-color: var(--err-line); }
|
||||
.token-revoke:disabled { opacity: 0.5; cursor: wait; }
|
||||
/* Empty-state row: the muted centered message at full table width
|
||||
(the .history-empty-row language, inline in the table). */
|
||||
/* Regenerate (phase 101 task 03, D2): the .token-revoke's structural
|
||||
twin — the SAME size / border / radius / focus, the transparent
|
||||
fill + ink-soft text — but the NEUTRAL action's hover
|
||||
(brand-soft / brand-ink), NOT the revoke's error hover: a
|
||||
rotation is a hand-out of a successor, not a deletion (no new
|
||||
hue — the phase-92 monochrome invariant). The confirm pair
|
||||
reuses the .history-confirm-* classes unchanged (the pair CSS
|
||||
above). :disabled mirrors the revoke button's rule (the
|
||||
in-flight state, while the rotation POST is out). */
|
||||
.token-regenerate {
|
||||
min-height: 44px;
|
||||
padding: 0.35rem 0.7rem;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-sm);
|
||||
background: transparent;
|
||||
color: var(--ink-soft);
|
||||
font: inherit;
|
||||
font-weight: 600;
|
||||
font-size: 0.82rem;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
.token-regenerate:hover:not(:disabled) { background: var(--brand-soft); color: var(--brand-ink); }
|
||||
.token-regenerate:disabled { opacity: 0.5; cursor: wait; }
|
||||
/* Empty-state + search no-match rows (phase 101): the muted centered
|
||||
message at full table width (the .history-empty-row language,
|
||||
inline in the table) — CLASS-based, so both the active table's
|
||||
#tokens-empty-row / #tokens-no-match-row and the revoked table's
|
||||
#tokens-revoked-no-match-row share it. */
|
||||
.tokens-empty-row td {
|
||||
padding: 2.25rem 1rem;
|
||||
text-align: center;
|
||||
color: var(--ink-soft);
|
||||
font-style: italic;
|
||||
}
|
||||
/* Phase 101 (task 02, D4): the per-table live label search — the
|
||||
house input surface (the #token-label / archive-upload input
|
||||
family: --line hairline, --surface fill, ink text — AA pairs, no
|
||||
new hue), full width, the ≥44px target, the global :focus-visible
|
||||
ring (no custom focus rule — the house pattern). */
|
||||
.token-search {
|
||||
width: 100%;
|
||||
min-height: 44px;
|
||||
padding: 0.55rem 0.8rem;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--surface);
|
||||
color: var(--ink);
|
||||
font: inherit;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
/* The revoked section's sub-heading (phase 101 D1): the phase-97
|
||||
.kb-level h2 voice — mono, 1rem, brand-ink (the path voice, AA on
|
||||
the page background). */
|
||||
.tokens-revoked-heading {
|
||||
margin: 1.5rem 0 0.5rem;
|
||||
font-family: var(--mono);
|
||||
font-size: 1rem;
|
||||
color: var(--brand-ink);
|
||||
}
|
||||
|
||||
/* ---------- Theme view (phase 91, tasks 04 + 05) ----------
|
||||
The shell's seventh view (#view-theme): the admin palette + branding
|
||||
|
||||
Reference in New Issue
Block a user