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:
@@ -0,0 +1,20 @@
|
||||
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`.
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
........................................................................ [ 3%]
|
||||
........................................................................ [ 6%]
|
||||
........................................................................ [ 10%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 20%]
|
||||
........................................................................ [ 24%]
|
||||
........................................................................ [ 27%]
|
||||
........................................................................ [ 31%]
|
||||
........................................................................ [ 34%]
|
||||
........................................................................ [ 38%]
|
||||
........................................................................ [ 41%]
|
||||
........................................................................ [ 45%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 52%]
|
||||
........................................................................ [ 55%]
|
||||
........................................................................ [ 59%]
|
||||
........................................................................ [ 62%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 69%]
|
||||
........................................................................ [ 73%]
|
||||
........................................................................ [ 76%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 90%]
|
||||
........................................................................ [ 94%]
|
||||
........................................................................ [ 97%]
|
||||
................................................. [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
|
||||
|
||||
Name Stmts Miss Cover
|
||||
--------------------------------------------------
|
||||
app/__init__.py 1 0 100%
|
||||
app/api/__init__.py 0 0 100%
|
||||
app/api/auth.py 52 0 100%
|
||||
app/api/chat.py 181 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 13 0 100%
|
||||
app/api/doc_drafts.py 94 0 100%
|
||||
app/api/docs.py 127 1 99%
|
||||
app/api/git_sources.py 229 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 29 0 100%
|
||||
app/api/sync.py 115 0 100%
|
||||
app/api/tokens.py 40 0 100%
|
||||
app/api/ui_settings.py 55 0 100%
|
||||
app/config.py 140 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 45 0 100%
|
||||
app/core/caching.py 124 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/errors.py 5 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/core/rate_limit.py 44 0 100%
|
||||
app/core/security_headers.py 20 0 100%
|
||||
app/core/theming.py 38 0 100%
|
||||
app/core/tokens.py 44 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 66 0 100%
|
||||
app/models.py 125 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 316 1 99%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/folder_summaries.py 121 0 100%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 190 3 98%
|
||||
app/rag/llm.py 243 1 99%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 88 0 100%
|
||||
app/rag/retriever.py 150 3 98%
|
||||
app/rag/scaffolding.py 55 0 100%
|
||||
app/rag/source_removal.py 41 0 100%
|
||||
app/rag/sources_meta.py 16 0 100%
|
||||
app/rag/suggestions.py 27 0 100%
|
||||
app/rag/summarizer.py 24 0 100%
|
||||
app/schemas.py 307 0 100%
|
||||
--------------------------------------------------
|
||||
TOTAL 3848 15 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414).
|
||||
Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest`
|
||||
|
||||
validation OK
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
Task 01 complete — everything green.
|
||||
|
||||
**Implemented**
|
||||
- `app/core/tokens.py`: `TokenAlreadyRevoked` exception + `regenerate_token(db, token_id)` — atomic rotation (revoke-stamp + same-label successor create in one flush-only unit; caller owns the single commit), `None` for unknown id; module docstring carries the rotation/A4 contract.
|
||||
- `app/api/tokens.py`: `POST /api/tokens/{id}/regenerate` → 201 `TokenCreated` (new row's one plaintext moment), 404 `token not found`, 409 `token already revoked`; router-wide `require_admin` covers it; `list_tokens` now passes `revoked_at`.
|
||||
- `app/schemas.py`: `TokenListItem.revoked_at: datetime | None = None` (D5, wire-additive, docstring pinned).
|
||||
|
||||
**Tests**
|
||||
- Unit (`tests/unit/test_tokens.py`): rotation matrix — new row/same label/well-formed plaintext/hash round-trip, old row stamped, old plaintext dead, missing → `None`, revoked → raises, rollback undoes BOTH writes (service never commits).
|
||||
- Integration (`tests/integration/test_tokens_api.py`): 201 rotation (old row revoked w/ ISO `revoked_at`, new row active + newer `created_at` via deterministic gap, A4 list stays secret-free), 404, 409 (row untouched), 403 anonymous on all routes + 403 token-user; phase-79 list pins updated in place for the new field.
|
||||
|
||||
**Results**
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → 2060 passed, TOTAL 99% (>90%; tokens modules 100%)
|
||||
- `uv run ruff check .` → clean; `uv run pyright` → 0 errors
|
||||
- Regression: `tests/integration/test_auth_api.py` (17) and `uv run pytest tests/e2e/test_api_tokens.py --no-cov` (9) green in isolation
|
||||
|
||||
**Decisions**: none beyond spec; kept house conventions (service flushes/endpoint commits, one message per 404/409, docstring-carried contracts).
|
||||
|
||||
**Next pending task**: `.agents/phases/todo/101_tokens_page_overhaul/02_two_tables_search_required_name.md`
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
........................................................................ [ 3%]
|
||||
........................................................................ [ 6%]
|
||||
........................................................................ [ 10%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 20%]
|
||||
........................................................................ [ 24%]
|
||||
........................................................................ [ 27%]
|
||||
........................................................................ [ 31%]
|
||||
........................................................................ [ 34%]
|
||||
........................................................................ [ 38%]
|
||||
........................................................................ [ 41%]
|
||||
........................................................................ [ 45%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 52%]
|
||||
........................................................................ [ 55%]
|
||||
........................................................................ [ 59%]
|
||||
........................................................................ [ 62%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 69%]
|
||||
........................................................................ [ 73%]
|
||||
........................................................................ [ 76%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 90%]
|
||||
........................................................................ [ 94%]
|
||||
........................................................................ [ 97%]
|
||||
............................................ [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
|
||||
|
||||
Name Stmts Miss Cover
|
||||
--------------------------------------------------
|
||||
app/__init__.py 1 0 100%
|
||||
app/api/__init__.py 0 0 100%
|
||||
app/api/auth.py 52 0 100%
|
||||
app/api/chat.py 181 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 13 0 100%
|
||||
app/api/doc_drafts.py 94 0 100%
|
||||
app/api/docs.py 127 1 99%
|
||||
app/api/git_sources.py 229 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 29 0 100%
|
||||
app/api/sync.py 115 0 100%
|
||||
app/api/tokens.py 40 0 100%
|
||||
app/api/ui_settings.py 55 0 100%
|
||||
app/config.py 140 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 45 0 100%
|
||||
app/core/caching.py 124 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/errors.py 5 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/core/rate_limit.py 44 0 100%
|
||||
app/core/security_headers.py 20 0 100%
|
||||
app/core/theming.py 38 0 100%
|
||||
app/core/tokens.py 44 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 66 0 100%
|
||||
app/models.py 125 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 316 1 99%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/folder_summaries.py 121 0 100%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 190 3 98%
|
||||
app/rag/llm.py 243 1 99%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 88 0 100%
|
||||
app/rag/retriever.py 150 3 98%
|
||||
app/rag/scaffolding.py 55 0 100%
|
||||
app/rag/source_removal.py 41 0 100%
|
||||
app/rag/sources_meta.py 16 0 100%
|
||||
app/rag/suggestions.py 27 0 100%
|
||||
app/rag/summarizer.py 24 0 100%
|
||||
app/schemas.py 307 0 100%
|
||||
--------------------------------------------------
|
||||
TOTAL 3848 15 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414).
|
||||
Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest`
|
||||
|
||||
validation OK
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
All green. Task 02 is complete.
|
||||
|
||||
**Implemented (phase 101, task 02 — two tables, per-table search, required name):**
|
||||
- `frontend/index.html` `#view-tokens`: 4-column active table (Status `<th>` gone, empty row `colspan=4`), new ship-hidden `#tokens-no-match-row`, both `type=search` inputs (`#token-search-active/-revoked`, `.token-search`), and the new ship-hidden revoked section (heading + search + 4-column table with `Revoked` column) below the active wrap; create row now `aria-label="Token name"` / `e.g. alice — required`
|
||||
- `frontend/assets/tokens.js`: `loadTokens` splits by `tok.revoked` (server order kept), `setRevokedSectionVisible(n)` (heading+search+wrap shown iff ≥1 revoked), `applyFilter` (case-insensitive label substring, state rows excluded, no-match copy `No tokens match "<query>".`), persistent `activeQuery`/`revokedQuery` re-applied after every render, input listeners armed in the admin branch (no fetch), D3 required-name block (`Give the token a name first.` + re-focus, no request); `confirmRevoke` now relocates the row to the revoked table via the re-entrant load (its `revoked_at` cell needs the server stamp); `|| "token"` fallback deleted
|
||||
- `styles.css`: `.token-search` (house input surface, full-width, ≥44px), `.tokens-revoked-heading` (phase-97 mono voice); empty/no-match styling already class-based (no-op)
|
||||
- Source pins: 3 new tests in `tests/unit/test_frontend_router.py` (scaffold, JS split/search/name, CSS) — all pre-existing phase-79 pins still pass
|
||||
- Defect fixes (in place): `tests/e2e/test_api_tokens.py` revoked-row assertions moved to `#tokens-revoked-tbody` (per phase plan task 04 item 5); `test_theme_semantic_completion.py::test_revoked_pill_gray_labeled` → `test_revoked_table_state_labeled` (pill intentionally gone — D1)
|
||||
|
||||
**Gates:** `uv run pytest --cov=app` → 2063 passed, app 99% (>90%) · `ruff check .` clean · `pyright` 0/0/0 · E2E in isolation: `test_api_tokens.py` 9 ✓, `test_theme_semantic_completion.py` 8 ✓, `test_history_page_width`+`test_admin_auth`+`test_shared_header` 17 ✓ (34 combined); temp in-browser verification of search/re-show/revoke split passed (file deleted)
|
||||
|
||||
**Decisions:** state rows (empty + no-match) excluded from the filter per 00_phase "(no-match/empty rows excluded)"; no-match text quotes the original untrimmed query; no mobile CSS change needed (class-based).
|
||||
|
||||
**Next pending task:** `03_regenerate_ui.md` (Regenerate control + CSS + source pins)
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
........................................................................ [ 3%]
|
||||
........................................................................ [ 6%]
|
||||
........................................................................ [ 10%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 20%]
|
||||
........................................................................ [ 24%]
|
||||
........................................................................ [ 27%]
|
||||
........................................................................ [ 31%]
|
||||
........................................................................ [ 34%]
|
||||
........................................................................ [ 38%]
|
||||
........................................................................ [ 41%]
|
||||
........................................................................ [ 45%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 52%]
|
||||
........................................................................ [ 55%]
|
||||
........................................................................ [ 59%]
|
||||
........................................................................ [ 62%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 69%]
|
||||
........................................................................ [ 73%]
|
||||
........................................................................ [ 76%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 90%]
|
||||
........................................................................ [ 94%]
|
||||
........................................................................ [ 97%]
|
||||
............................................... [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
|
||||
|
||||
Name Stmts Miss Cover
|
||||
--------------------------------------------------
|
||||
app/__init__.py 1 0 100%
|
||||
app/api/__init__.py 0 0 100%
|
||||
app/api/auth.py 52 0 100%
|
||||
app/api/chat.py 181 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 13 0 100%
|
||||
app/api/doc_drafts.py 94 0 100%
|
||||
app/api/docs.py 127 1 99%
|
||||
app/api/git_sources.py 229 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 29 0 100%
|
||||
app/api/sync.py 115 0 100%
|
||||
app/api/tokens.py 40 0 100%
|
||||
app/api/ui_settings.py 55 0 100%
|
||||
app/config.py 140 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 45 0 100%
|
||||
app/core/caching.py 124 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/errors.py 5 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/core/rate_limit.py 44 0 100%
|
||||
app/core/security_headers.py 20 0 100%
|
||||
app/core/theming.py 38 0 100%
|
||||
app/core/tokens.py 44 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 66 0 100%
|
||||
app/models.py 125 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 316 1 99%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/folder_summaries.py 121 0 100%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 190 3 98%
|
||||
app/rag/llm.py 243 1 99%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 88 0 100%
|
||||
app/rag/retriever.py 150 3 98%
|
||||
app/rag/scaffolding.py 55 0 100%
|
||||
app/rag/source_removal.py 41 0 100%
|
||||
app/rag/sources_meta.py 16 0 100%
|
||||
app/rag/suggestions.py 27 0 100%
|
||||
app/rag/summarizer.py 24 0 100%
|
||||
app/schemas.py 307 0 100%
|
||||
--------------------------------------------------
|
||||
TOTAL 3848 15 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414).
|
||||
Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest`
|
||||
|
||||
validation OK
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
All green. Final report:
|
||||
|
||||
## Task 03 complete — Regenerate control (rotation UI)
|
||||
|
||||
**Implemented**
|
||||
- `frontend/assets/tokens.js`: `makeRegenerateControl` (structural mirror of the revoke control: `.token-regenerate` button, `aria-label: "Regenerate token: <label>"`, exact confirm text `Regenerate? The current token is revoked.`, focus-to-Yes, No/failure → `restoreRegenerate()` with focus restored) + `confirmRegenerate` (disabled-while-in-flight, `POST /api/tokens/<id>/regenerate` no body; 201 → `loadTokens()` FIRST → once-block value-only reveal → exact D2 announce line; 404 → `row.remove()` + re-fetch + house 404 line; 409 → re-fetch + same line; network/non-2xx → neutral two-line copy + restore)
|
||||
- Active Actions cell now `actionsTd.append(makeRegenerateControl, makeRevokeControl)` — Regenerate first, each control owns its OWN `.tokens-actions` wrapper span (independent confirm scopes)
|
||||
- Module docstring: rotation semantics + 404/409 copy sections
|
||||
- `frontend/assets/styles.css`: `.token-regenerate` — the `.token-revoke` twin (44px/`--line`/radius/transparent/`--ink-soft`) with the NEUTRAL hover (`--brand-soft`/`--brand-ink`, no err hue) + revoke-consistent `:disabled`; comment notes the phase-92 monochrome invariant
|
||||
- Source pins in `tests/unit/test_frontend_router.py` (the task-02 pin file): `test_tokens_js_regenerate_control` (button/aria/confirm text/focus/restore, POST path, pinned 201 sequence load→reveal→announce, 404/409 copy, retryable restore ×2, cell order, per-control wrappers) + `test_tokens_regenerate_css_pins`
|
||||
|
||||
**Gates**
|
||||
- `uv run pytest --cov=app --cov-report=term` → 2065 passed, exit 0, TOTAL **99%** (>90%)
|
||||
- `uv run ruff check .` → All checks passed; `uv run pyright` → 0 errors, 0 warnings
|
||||
- `node --check` (ESM) on tokens.js → OK; revoke control untouched (its pins green)
|
||||
|
||||
**Decisions**: 404 branch follows the task's pinned decision (`row.remove()` + re-fetch + the revoke control's existing 404 line, not a revoked re-render); no E2E file added (task 04 owns the browser proof); no git commit per harness rules.
|
||||
|
||||
**Next pending task**: `.agents/phases/todo/101_tokens_page_overhaul/04_e2e_tokens_page.md`
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
........................................................................ [ 3%]
|
||||
........................................................................ [ 6%]
|
||||
........................................................................ [ 10%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 20%]
|
||||
........................................................................ [ 24%]
|
||||
........................................................................ [ 27%]
|
||||
........................................................................ [ 31%]
|
||||
........................................................................ [ 34%]
|
||||
........................................................................ [ 38%]
|
||||
........................................................................ [ 41%]
|
||||
........................................................................ [ 45%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 52%]
|
||||
........................................................................ [ 55%]
|
||||
........................................................................ [ 59%]
|
||||
........................................................................ [ 62%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 69%]
|
||||
........................................................................ [ 73%]
|
||||
........................................................................ [ 76%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 90%]
|
||||
........................................................................ [ 94%]
|
||||
........................................................................ [ 97%]
|
||||
................................................. [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
|
||||
|
||||
Name Stmts Miss Cover
|
||||
--------------------------------------------------
|
||||
app/__init__.py 1 0 100%
|
||||
app/api/__init__.py 0 0 100%
|
||||
app/api/auth.py 52 0 100%
|
||||
app/api/chat.py 181 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 13 0 100%
|
||||
app/api/doc_drafts.py 94 0 100%
|
||||
app/api/docs.py 127 1 99%
|
||||
app/api/git_sources.py 229 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 29 0 100%
|
||||
app/api/sync.py 115 0 100%
|
||||
app/api/tokens.py 40 0 100%
|
||||
app/api/ui_settings.py 55 0 100%
|
||||
app/config.py 140 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 45 0 100%
|
||||
app/core/caching.py 124 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/errors.py 5 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/core/rate_limit.py 44 0 100%
|
||||
app/core/security_headers.py 20 0 100%
|
||||
app/core/theming.py 38 0 100%
|
||||
app/core/tokens.py 44 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 66 0 100%
|
||||
app/models.py 125 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 316 1 99%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/folder_summaries.py 121 0 100%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 190 3 98%
|
||||
app/rag/llm.py 243 1 99%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 88 0 100%
|
||||
app/rag/retriever.py 150 3 98%
|
||||
app/rag/scaffolding.py 55 0 100%
|
||||
app/rag/source_removal.py 41 0 100%
|
||||
app/rag/sources_meta.py 16 0 100%
|
||||
app/rag/suggestions.py 27 0 100%
|
||||
app/rag/summarizer.py 24 0 100%
|
||||
app/schemas.py 307 0 100%
|
||||
--------------------------------------------------
|
||||
TOTAL 3848 15 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414).
|
||||
Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest`
|
||||
|
||||
validation OK
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
All gates green. Report:
|
||||
|
||||
**Task 04 complete — `101_tokens_page_overhaul` E2E + regressions**
|
||||
|
||||
- Implemented `tests/e2e/test_tokens_page.py` (4 tests, all per spec): revoked tokens in their own table below (4-col active thead, hidden-while-empty section, Revoked date cell ≠ created, no actions), both tables searchable (no-match row copy, queries survive a Tuning-nav re-show), nameless/whitespace generation refused (live-region line, `page.request` GET proves no row), full Regenerate rotation (two-step confirm + focus, new `bor_…` plaintext in the once-block, D2 line, successor newer + original in revoked table, NEW token signs in via fresh context, ORIGINAL refused at the gate).
|
||||
- Verified `tests/e2e/test_api_tokens.py` was already updated in place (revoked-row pins relocated to `#tokens-revoked-tbody`; no stale Status/pill/colspan refs) — green; `test_theme_semantic_completion.py` re-scope (this phase's) also green.
|
||||
- E2E (isolated, `--no-cov`, DB up): `uv run pytest tests/e2e/test_tokens_page.py -v --no-cov` → **4 passed**; `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**.
|
||||
- Full gate: `uv run pytest --cov=app --cov-report=term-missing` → **2065 passed, app/ coverage 99%** (>90%); `uv run ruff check .` → clean; `uv run pyright` → 0 errors.
|
||||
- Notable: one test-side race fixed (read the once-block after the D2 live-region line — the 201 sequence's last step); date cells indexed via `tokens-date-cell` class (Created = nth(0)). No app-code defects found.
|
||||
- Per harness rules: no `git add`/`commit`, no phase-dir move — all changes left in the working tree.
|
||||
- Next pending task: none in `101_tokens_page_overhaul` (this was the last task); queue continues with `98_sync_summary_visibility` etc. in `todo/`.
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
........................................................................ [ 3%]
|
||||
........................................................................ [ 6%]
|
||||
........................................................................ [ 10%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 20%]
|
||||
........................................................................ [ 24%]
|
||||
........................................................................ [ 27%]
|
||||
........................................................................ [ 31%]
|
||||
........................................................................ [ 34%]
|
||||
........................................................................ [ 38%]
|
||||
........................................................................ [ 41%]
|
||||
........................................................................ [ 45%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 52%]
|
||||
........................................................................ [ 55%]
|
||||
........................................................................ [ 59%]
|
||||
........................................................................ [ 62%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 69%]
|
||||
........................................................................ [ 73%]
|
||||
........................................................................ [ 76%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 83%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 90%]
|
||||
........................................................................ [ 94%]
|
||||
........................................................................ [ 97%]
|
||||
................................................. [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib/python3.13/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/brain_of_reese/.venv/lib/python3.13/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.13.13-final-0 _______________
|
||||
|
||||
Name Stmts Miss Cover
|
||||
--------------------------------------------------
|
||||
app/__init__.py 1 0 100%
|
||||
app/api/__init__.py 0 0 100%
|
||||
app/api/auth.py 52 0 100%
|
||||
app/api/chat.py 181 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 13 0 100%
|
||||
app/api/doc_drafts.py 94 0 100%
|
||||
app/api/docs.py 127 1 99%
|
||||
app/api/git_sources.py 229 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 29 0 100%
|
||||
app/api/sync.py 115 0 100%
|
||||
app/api/tokens.py 40 0 100%
|
||||
app/api/ui_settings.py 55 0 100%
|
||||
app/config.py 140 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 45 0 100%
|
||||
app/core/caching.py 124 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/errors.py 5 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/core/rate_limit.py 44 0 100%
|
||||
app/core/security_headers.py 20 0 100%
|
||||
app/core/theming.py 38 0 100%
|
||||
app/core/tokens.py 44 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 66 0 100%
|
||||
app/models.py 125 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 316 1 99%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/folder_summaries.py 121 0 100%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 190 3 98%
|
||||
app/rag/llm.py 243 1 99%
|
||||
app/rag/overview.py 71 0 100%
|
||||
app/rag/prompts.py 88 0 100%
|
||||
app/rag/retriever.py 150 3 98%
|
||||
app/rag/scaffolding.py 55 0 100%
|
||||
app/rag/source_removal.py 41 0 100%
|
||||
app/rag/sources_meta.py 16 0 100%
|
||||
app/rag/suggestions.py 27 0 100%
|
||||
app/rag/summarizer.py 24 0 100%
|
||||
app/schemas.py 307 0 100%
|
||||
--------------------------------------------------
|
||||
TOTAL 3848 15 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
WARNING: there is a new pyright version available (v1.1.411 -> v1.1.414).
|
||||
Please install the new version or set PYRIGHT_PYTHON_FORCE_VERSION to `latest`
|
||||
|
||||
validation OK
|
||||
Reference in New Issue
Block a user