feat: phases 77–80 — navbar view refresh, static background, API tokens, history suggestion chips
Single consolidated commit for four completed, validated phases (77, 78, 79, 80). The pipeline run left all work uncommitted because the harness commits only with PHASE_COMMIT=1 while child executors are forbidden from committing; the phases themselves all passed validation and moved to .agents/phases/complete/. Phase 77 — navbar view refresh - router.js dispatches bor:view-refresh on re-show / active re-click / popstate (gated on wasMounted; first show and boot exempt) - History / RAG / Sources / Tuning re-fetch on refresh (admin branch); Chat deliberately excluded (stream survival) - History "Refresh" button (admin-only, in-flight disable + status line) - New story suite tests/e2e/test_navbar_refresh.py (7 tests) Phase 78 — static background - Removed the animated glow layers; static 44px grid over the flat --bg canvas; default and reduced-motion renders byte-identical - Updated background/theme E2E suites; removed bg-glow test pins Phase 79 — API tokens - api_tokens model + migration 0012; hash-only token service - Admin tokens API + Tokens admin view; POST /api/token-auth; live-revoking require_user on chat / suggestions / document content - Frontend token gate with localStorage cache; anonymous E2E suites migrated to token login - New story suite tests/e2e/test_api_tokens.py (9 tests) Phase 80 — history suggestion chips - last_questions() endpoint with SEED fallback; startNewChat() refetch - Seed-semantics docs (config.py, .env.example, README) - Integration state matrix + E2E suite rewritten to the 4 chip states Also included: phase-76 report artifacts and the repo restore-test-db skill (previously untracked), scripts/* ruff fixes from phase 77. Final gate state (phase 80 final pass, covers everything above): - uv run pytest --cov=app → 1637 passed, 0 failed, app/ coverage 99% - uv run ruff check . && uv run pyright → clean, 0 errors - Per-phase story E2E suites green in isolation
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
Everything is green. This was a verification pass only — no code changes were needed. Final report:
|
||||
|
||||
**Phase 79 (API tokens) — final verification pass**
|
||||
- Verified tasks 01–08 already complete in `complete/79_api_tokens/`; confirmed implementation matches the locked design (A3–A5): `api_tokens` model + migration `0012`, hash-only token service, admin tokens router, `POST /api/token-auth` + 3-role whoami, live-revoking `require_user` on chat/suggestions/document-content, frontend gate + localStorage cache, Tokens admin view.
|
||||
- Test results:
|
||||
- `uv run pytest tests/e2e/test_api_tokens.py -v --no-cov` → **9 passed** (all owner-sentence clauses pinned: anon lockout, shared open, UI generate, token-user chat+doc, reload cache, admin walls 403, sign-out clears key, revocation refusal, no-enumeration error)
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → **1639 passed, 0 failed, coverage 99%** (>90% floor)
|
||||
- `uv run ruff check . && uv run pyright` → **clean (0 errors)**
|
||||
- E2E spot-checks green: `test_admin_auth`, `test_share_chat` (anonymous), `test_chat_rag`, `test_nav_switch_keeps_stream`, `test_smoke` + all 10 token-migrated chat suites
|
||||
- Completion criteria: all met — story suite green in isolation; token-user E2E chat + cited doc / anon 401 + gate / shared open / admin surfaces 403 (asserted in the passing suite); cache-survives-reload, sign-out clears, revocation refused on next request + fresh login; full suite + coverage + lint green.
|
||||
- Notable: commit + phase-dir move are the harness's (per this pass's rules); README "API tokens" section verified present; `.env.example` correctly untouched. No defects found.
|
||||
- Next pending phase: **80_history_suggestion_chips**.
|
||||
@@ -0,0 +1,81 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 22%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 30%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 53%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 61%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 70%]
|
||||
........................................................................ [ 75%]
|
||||
........................................................................ [ 79%]
|
||||
........................................................................ [ 84%]
|
||||
........................................................................ [ 88%]
|
||||
........................................................................ [ 92%]
|
||||
........................................................................ [ 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 40 0 100%
|
||||
app/api/chat.py 178 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 0 100%
|
||||
app/api/git_sources.py 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 11 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/api/tokens.py 28 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 108 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/core/tokens.py 33 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 62 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 0 100%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 180 3 98%
|
||||
app/rag/llm.py 216 0 100%
|
||||
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 231 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3136 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
@@ -0,0 +1,13 @@
|
||||
All green. Task 01 is complete.
|
||||
|
||||
**Report**
|
||||
|
||||
- `app/models.py`: `ApiToken` model after `SavedChat` — `id` UUID PK (uuid4 default), `label` String(120) NOT NULL (display-only), `token_hash` String(64) NOT NULL unique (sha256 of the full `bor_…` token), `created_at` server-default now(), `last_used_at`/`revoked_at` TIMESTAMPTZ NULL; docstring documents the hashed-credential trust model; module docstring gains the `api_tokens` bullet.
|
||||
- `alembic/versions/0012_api_tokens.py` (revision `0012` → `0011`): `op.create_table` + explicit unique `op.create_index("ix_api_tokens_token_hash", …)` (the 0009/0011 shape); downgrade drops index then table.
|
||||
- `tests/unit/test_api_tokens_model.py` (new, schema-level per house precedent): table name, column set/nullability/widths, `token_hash` unique, `label` not unique — 4 tests.
|
||||
- `tests/integration/test_migration_0012.py` (new, mirrors `test_migration_0011.py`): upgrade column contract, lifecycle round-trip, duplicate-hash rejection + repeated-label OK, downgrade/round-trip — 5 tests.
|
||||
- Migration: `uv run alembic upgrade head` → 0012 applied; `downgrade -1` + `upgrade head` round-trips cleanly; dev DB at `0012 (head)` so tasks 02/03 pick the table up.
|
||||
- Full suite: `uv run pytest --cov=app --cov-report=term` → **1570 passed**, coverage **99%** (>90%; `app/models.py` 100%).
|
||||
- Lint/types: `uv run ruff check .` → All checks passed; `uv run pyright` → 0 errors.
|
||||
- Deviation (minor): model column uses `unique=True` alone (all four house precedents — `doc_drafts.token`, `saved_chats.share_token`, etc.) rather than `unique=True, index=True`; the unique index requirement is met by the migration's explicit `op.create_index(..., unique=True)`, exactly the 0009 shape the task pointed at.
|
||||
- Next pending task: `.agents/phases/todo/79_api_tokens/02_token_admin_api.md` (token service + admin create/list/revoke).
|
||||
@@ -0,0 +1,78 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 22%]
|
||||
........................................................................ [ 27%]
|
||||
........................................................................ [ 32%]
|
||||
........................................................................ [ 36%]
|
||||
........................................................................ [ 41%]
|
||||
........................................................................ [ 45%]
|
||||
........................................................................ [ 50%]
|
||||
........................................................................ [ 55%]
|
||||
........................................................................ [ 59%]
|
||||
........................................................................ [ 64%]
|
||||
........................................................................ [ 68%]
|
||||
........................................................................ [ 73%]
|
||||
........................................................................ [ 77%]
|
||||
........................................................................ [ 82%]
|
||||
........................................................................ [ 87%]
|
||||
........................................................................ [ 91%]
|
||||
........................................................................ [ 96%]
|
||||
.......................................................... [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 22 0 100%
|
||||
app/api/chat.py 177 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 0 100%
|
||||
app/api/git_sources.py 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 8 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/config.py 140 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 20 0 100%
|
||||
app/core/caching.py 108 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 60 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 0 100%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 180 3 98%
|
||||
app/rag/llm.py 216 0 100%
|
||||
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 210 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3005 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
@@ -0,0 +1,15 @@
|
||||
Task 02 complete — all gates green.
|
||||
|
||||
**Implemented**
|
||||
- `app/core/tokens.py` — `generate_token` / `hash_token` (sha256 of FULL string) / `create_token` / `find_active_by_token` (hash → unique-index hit → `revoked_at IS NULL`, generic miss) / `mark_used` / `revoke` (stamp-once, False only for missing id); hash-lookup-vs-constant-time-contrast documented; house flush-not-commit split
|
||||
- `app/schemas.py` — `TokenCreateRequest` (strip-then 1–120, 422 fail-loud), `TokenCreated` (only schema carrying plaintext), `TokenListItem` / `TokenList` (secret-free by construction), `TokenAuthRequest` (deliberately no min-length → task-03 401 contract)
|
||||
- `app/api/tokens.py` — router-wide `require_admin`; `POST /tokens` → 201 (plaintext once), `GET /tokens` newest-first (`created_at desc, id desc`), `POST /tokens/{id}/revoke` → 204 idempotent / 404 `token not found`; registered in `app/main.py` before the static mount
|
||||
- `tests/unit/test_tokens.py` (11) + `tests/integration/test_tokens_api.py` (7): shape, hash, round-trip, all miss paths, revoke idempotency + `last_used_at` preservation, anonymous 403s, plaintext/hash never in list, duplicate labels, 422s, 404, ordering
|
||||
|
||||
**Results**
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → 1588 passed; TOTAL 99% (`core/tokens.py` 100%, `api/tokens.py` 100%)
|
||||
- `uv run ruff check .` → clean (fixed `datetime.UTC` alias + import sort); `uv run pyright` → 0 errors
|
||||
|
||||
**Decisions** — service flushes, endpoint commits (sources_meta house pattern); used `datetime.UTC` per ruff (identical to spec's `timezone.utc`).
|
||||
|
||||
**Next pending task:** `03_token_auth_enforcement.md`
|
||||
@@ -0,0 +1,81 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 22%]
|
||||
........................................................................ [ 27%]
|
||||
........................................................................ [ 31%]
|
||||
........................................................................ [ 36%]
|
||||
........................................................................ [ 40%]
|
||||
........................................................................ [ 45%]
|
||||
........................................................................ [ 49%]
|
||||
........................................................................ [ 54%]
|
||||
........................................................................ [ 58%]
|
||||
........................................................................ [ 63%]
|
||||
........................................................................ [ 68%]
|
||||
........................................................................ [ 72%]
|
||||
........................................................................ [ 77%]
|
||||
........................................................................ [ 81%]
|
||||
........................................................................ [ 86%]
|
||||
........................................................................ [ 90%]
|
||||
........................................................................ [ 95%]
|
||||
........................................................................ [ 99%]
|
||||
.... [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 22 0 100%
|
||||
app/api/chat.py 177 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 0 100%
|
||||
app/api/git_sources.py 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 8 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/api/tokens.py 28 0 100%
|
||||
app/config.py 140 0 100%
|
||||
app/core/__init__.py 0 0 100%
|
||||
app/core/auth.py 20 0 100%
|
||||
app/core/caching.py 108 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/core/tokens.py 33 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 62 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 0 100%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 180 3 98%
|
||||
app/rag/llm.py 216 0 100%
|
||||
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 231 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3089 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
@@ -0,0 +1,15 @@
|
||||
All green. Task 03 complete.
|
||||
|
||||
**Implemented**
|
||||
- `app/core/auth.py`: `USER_SESSION_KEY`/`USER_TOKEN_ID_KEY` + `require_user` — admin always passes (no DB touch); token session live-checks the `api_tokens` row per request (PK lookup = revocation check); dead session (revoked/missing/corrupt id) → both user keys popped + 401 `authentication required`; anonymous → same 401
|
||||
- `app/api/auth.py`: public `POST /api/token-auth` (valid → `mark_used`+commit+`user`/`user_token_id` session keys → 204; malformed/unknown/revoked/empty → ONE generic 401 `invalid token`); `whoami` now reports `admin`|`user`|`anonymous` (admin wins on coexistence); `WhoamiResponse.role` comment updated; logout unchanged (wipes both roles)
|
||||
- Enforcement: `_user: None = Depends(require_user)` on `POST /api/chat`, `GET /api/suggestions` (+ `db` dep), `GET /api/documents/content` (docstring: phase-16 soft rule SUPERSEDED); fixed stale "viewer/chat public" docstrings in `docs.py`, `steering.py`, `models.py`, `tokens.py`
|
||||
- Tests: `require_user` matrix + 3-role whoami in `tests/unit/test_auth.py`; `test_auth_api.py` rewritten pins (token-auth flows, mid-session revocation → chat 401 + whoami anonymous + fresh login refused, token-user surface matrix incl. 403s on all admin surfaces); admin sign-in wired into `test_api.py`, `test_chat_api.py`, `test_kb_overview_api.py`, `test_document_content.py`, `test_document_viewer.py`, `test_chat_gate.py`, `test_chat_cancel.py` (raw ASGI scope carries a signed admin cookie)
|
||||
|
||||
**Results**
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → 1605 passed; TOTAL coverage **99%** (>90% bar; all modified files 100%)
|
||||
- `uv run ruff check .` → All checks passed; `uv run pyright` → 0 errors
|
||||
|
||||
**Decisions**: `last_used_at` stamped only on `token-auth` (per task-03 spec — the only request presenting the token; the gate re-sends it per page load); prior tasks' docstrings aligned accordingly. E2E suites (10 anonymous chat suites, `test_admin_auth.py`) intentionally untouched — that's task 04.
|
||||
|
||||
**Next pending task**: `.agents/phases/todo/79_api_tokens/04_migrate_anonymous_e2e.md`
|
||||
@@ -0,0 +1,81 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 22%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 31%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 40%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 49%]
|
||||
........................................................................ [ 53%]
|
||||
........................................................................ [ 58%]
|
||||
........................................................................ [ 62%]
|
||||
........................................................................ [ 67%]
|
||||
........................................................................ [ 71%]
|
||||
........................................................................ [ 76%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 85%]
|
||||
........................................................................ [ 89%]
|
||||
........................................................................ [ 94%]
|
||||
........................................................................ [ 98%]
|
||||
..................... [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 40 0 100%
|
||||
app/api/chat.py 178 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 0 100%
|
||||
app/api/git_sources.py 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 11 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/api/tokens.py 28 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 108 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/core/tokens.py 33 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 62 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 0 100%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 180 3 98%
|
||||
app/rag/llm.py 216 0 100%
|
||||
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 231 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3136 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
@@ -0,0 +1,17 @@
|
||||
All gates pass. Final state verified:
|
||||
|
||||
**Task 04 report — E2E suites meet the new auth contract**
|
||||
|
||||
**Implemented**
|
||||
- `auth_helpers.py`: added `login_with_token` (+ `WRONG_TOKEN` sentinel, wrong/revoked branch via `#auth-gate-error` role=alert) for task 07; made `login()` idempotent — an already-signed-in context boot-redirects past the form (login.js whoami), which was breaking double sign-in.
|
||||
- Signed in the 10 named chat suites **plus ~40 more** the audit widened (viewer/suggestion/upload/sync suites) — page `login()` or httpx client login; shared-chat + deliberate anonymous-surface suites untouched.
|
||||
- `test_admin_auth.py`: anonymous pins moved to the gated contract (401 `{"detail":"authentication required"}` on `/api/chat` + `/api/documents/content`, whoami anonymous, viewer not-found card); password flow unchanged.
|
||||
- **Defects fixed**: (a) app bug — `sources.js` `loadDocs` race (boot re-attach + boot load interleave → 2× catalog rows, 108-row table) got a monotonic seq guard; (b) test-infra bug — 8 module-scoped `app_server` overrides collided with the session app on port 8123 in combined runs (silently driving the wrong server) → dedicated ports 8124–8134; (c) sync suites' TRUNCATE now clears `git_sources` (shared-DB hygiene); (d) anonymous viewer-content asserts made role-conditional (not-found card = anonymous settled state); (e) anonymous chip/contrast tests sign in (suggestions gated).
|
||||
|
||||
**Gates**
|
||||
- `uv run pytest tests/e2e -v --no-cov` → **308 passed, 0 failed** (single session; baseline was 174 failed)
|
||||
- `uv run pytest tests/e2e/test_share_chat.py test_smoke.py test_nav_switch_keeps_stream.py test_archive_upload_sources.py test_admin_auth.py --no-cov` (isolation spot-check) → 22 passed
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → **1605 passed, app/ 99%**
|
||||
- `uv run ruff check . && uv run pyright` → clean
|
||||
|
||||
**Decisions**: port fix + loadDocs guard are test-infra/app defects (no story semantics changed), required to make the combined inventory green — the full inventory had never been run as one session before. Not committed (per instructions). Next pending: **05_frontend_token_gate**.
|
||||
@@ -0,0 +1,81 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 22%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 31%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 40%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 49%]
|
||||
........................................................................ [ 53%]
|
||||
........................................................................ [ 58%]
|
||||
........................................................................ [ 62%]
|
||||
........................................................................ [ 67%]
|
||||
........................................................................ [ 71%]
|
||||
........................................................................ [ 76%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 85%]
|
||||
........................................................................ [ 89%]
|
||||
........................................................................ [ 94%]
|
||||
........................................................................ [ 98%]
|
||||
..................... [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 40 0 100%
|
||||
app/api/chat.py 178 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 0 100%
|
||||
app/api/git_sources.py 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 11 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/api/tokens.py 28 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 108 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/core/tokens.py 33 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 62 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 0 100%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 180 3 98%
|
||||
app/rag/llm.py 216 0 100%
|
||||
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 231 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3136 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
@@ -0,0 +1,16 @@
|
||||
All work is complete and verified. Final report:
|
||||
|
||||
**Implemented** — In-app token gate + browser caching (phase 79 task 05):
|
||||
- `frontend/assets/token-gate.js` (new): mounts `#auth-gate` (shell) / `#doc-auth-gate` (viewer). Silent re-auth of cached `bor.token` via `POST /api/token-auth` runs **before** the whoami check (no gate flash, race-free vs header boot); dead/revoked cached tokens are dropped. Anonymous → gate revealed, `#main` made `inert`, focus lands on the token input. Success → cache token, invalidate whoami cache, unlock **without reload**, re-boot header, fire `onAuthed`.
|
||||
- `header.js`: Sign in/out pair keys off `authenticated` (a token user sees Sign out; sign-out clears `bor.token` too); admin-only nav links + steering panel still key off `role === "admin"`.
|
||||
- Gate markup/CSS in `index.html` + `document.html`; `Containerfile` esbuild line; unit pins `tests/unit/test_token_gate.py` (+ updated header/chat-UI pins); migrated 10 anonymous E2E suites to the gate contract.
|
||||
|
||||
**Test/lint/coverage**
|
||||
- `uv run pytest --cov=app` → **1622 passed**, TOTAL coverage **99%** (gate >90%)
|
||||
- `uv run ruff check .` → clean; `uv run pyright` → 0 errors
|
||||
- E2E full inventory run: 4 anonymous-flow failures found → fixed → green; gate-related batch re-ran **61 passed**
|
||||
- Real-server manual pass (9 flows: anonymous, wrong token, right token no-reload, cached reload, viewer, sign-out, revoked-login, revoked-cached, anonymous viewer) — all green
|
||||
|
||||
**Decisions** — Gate locks the whole `#main` (all views, incl. tuning/sources), not just chat; header stays interactive (admin form login remains the second entry). Token `user` = authenticated for the sign-in pair but gets the anonymous UI surface (no admin links, no steering panel). `test_global_tuning`'s 403-form contract now runs as a non-admin token user (the anonymous path is unreachable by design); `test_responsive_polish` checks the gate's focus contract anonymous + original AC3 contract signed-in. No git ops; no `.agents/` files touched; throwaway debug scripts removed.
|
||||
|
||||
**Next task** — `.agents/phases/todo/79_api_tokens/06_tokens_admin_view.md`
|
||||
@@ -0,0 +1,81 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 22%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 31%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 53%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 62%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 71%]
|
||||
........................................................................ [ 75%]
|
||||
........................................................................ [ 79%]
|
||||
........................................................................ [ 84%]
|
||||
........................................................................ [ 88%]
|
||||
........................................................................ [ 93%]
|
||||
........................................................................ [ 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 40 0 100%
|
||||
app/api/chat.py 178 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 0 100%
|
||||
app/api/git_sources.py 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 11 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/api/tokens.py 28 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 108 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/core/tokens.py 33 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 62 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 0 100%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 180 3 98%
|
||||
app/rag/llm.py 216 0 100%
|
||||
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 231 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3136 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
@@ -0,0 +1,18 @@
|
||||
Everything is green and the tree contains only expected changes (plus the phase's earlier uncommitted tasks 01–05, which the harness commits atomically).
|
||||
|
||||
## Report — Task 06: admin Tokens view (generate · list · revoke)
|
||||
|
||||
**Implemented**
|
||||
- `#view-tokens` section in the shell (`index.html`): page-head, `#tokens-gate` (history-gate pattern, `?next=/tokens.html`), `#tokens-status` live region, create row (label + Generate, ship-hidden), `#token-once` block (mono read-only field + Copy, ship-hidden), full-width table Label | Created | Last used | Status (Active em-dash / rose Revoked pill, cell aria-labels) | Actions (visually-hidden header), hidden empty row
|
||||
- `frontend/assets/tokens.js`: `mount(root)` with admin gate (anonymous: gate in, controls out, **no** `/api/tokens` fetch), re-entrant `loadTokens()` (replaces rows, hides+wipes the once-block), generate (blank label → `"token"`, "Generating…" lifecycle, plaintext revealed only after the re-render load — never stored client-side), copy (clipboard + inline select-fallback, own ~10-line copy), inline two-step Revoke (`history-confirm-*`, row re-renders Revoked), `bor:view-refresh` listener armed in admin branch, all cells textContent (zero innerHTML)
|
||||
- Router entries (`VIEW`/`VIEW_PATH`/`VIEW_MODULES`/`TITLES`/`DESCRIPTIONS`, replaceAll brand contract), `header.js` reveals `#nav-tokens` for admin
|
||||
- `/tokens.html` in `app/main.py` `_shell_routes` + `caching.py` `HTML_PAGES`; styles.css Tokens section (history-table/brand-pill/stale-pill language, focus-visible, AA pairs) + ≤640px stacking
|
||||
- Tests: `test_frontend_router.py` view-map/module/title pins extended + 2 new tokens contract tests; `test_api.py` (3 lists), `test_caching_revalidation.py` `SHELL_BACKED_PAGES`, `test_caching.py` `HTML_PAGES`; `test_nav_rename_sources.py` `NAV_TAIL` gains "Tokens"
|
||||
- **Deviation (required):** `#nav-tokens` also ships on `document.html`/`login.html`/`shared.html` (task named only `index.html`) — the phase-34 one-bar contract and `test_nav_consistency.py`'s cross-page inventory parity (History precedent, 4 pages) make the shell-only link a real failure; null-safe header.js is unaffected
|
||||
|
||||
**Results**
|
||||
- `uv run pytest --cov=app --cov-report=term-missing` → exit 0, TOTAL 99% (>90%; `main.py`/`caching.py`/`tokens.py` all 100%)
|
||||
- `uv run ruff check . && uv run pyright` → clean
|
||||
- E2E (isolated): temp manual pass (anon gate/no-fetch; admin generate→once+copy→revoke two-step→Revoked; re-show hides once-block; revoked token refused; active token unlocks; user gets gate) + `test_cache_busting`, `test_asset_cache_revalidation`, `test_nav_switch_keeps_stream`, `test_nav_consistency`, `test_admin_auth`, `test_nav_rename_sources`, `test_header_consistency`, `test_mobile_hamburger_nav`, `test_shared_header`, `test_navbar_refresh`, `test_tuning_nav_link`, `test_sticky_navbar`, `test_smoke`, `test_document_viewer`, `test_global_tuning`, `test_git_sources_admin`, `test_kb_overview`, `test_chat_history`, `test_history_copy`, `test_share_chat`, `test_stale_saved_chats` — all green (temp file deleted)
|
||||
|
||||
**Next pending task:** `07_e2e_story_suite.md`
|
||||
@@ -0,0 +1,81 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 22%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 30%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 53%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 61%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 70%]
|
||||
........................................................................ [ 75%]
|
||||
........................................................................ [ 79%]
|
||||
........................................................................ [ 84%]
|
||||
........................................................................ [ 88%]
|
||||
........................................................................ [ 92%]
|
||||
........................................................................ [ 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 40 0 100%
|
||||
app/api/chat.py 178 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 0 100%
|
||||
app/api/git_sources.py 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 11 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/api/tokens.py 28 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 108 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/core/tokens.py 33 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 62 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 0 100%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 180 3 98%
|
||||
app/rag/llm.py 216 0 100%
|
||||
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 231 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3136 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
@@ -0,0 +1,17 @@
|
||||
All gates green. Task complete.
|
||||
|
||||
**Report — Phase 79, task 07 (story E2E suite)**
|
||||
|
||||
- Implemented `tests/e2e/test_api_tokens.py` (new, 9 tests) pinning every clause of TODO.md L5 in a real browser:
|
||||
- anonymous lockout: `#auth-gate` visible, `#main` inert, composer unreachable via inverted tab walk; chat/suggestions/document-content 401 from empty cookies
|
||||
- shared chats stay open: admin creates+shares via API; fresh context renders `/shared/<token>` with zero gate markup
|
||||
- admin UI generate: `#token-once-value` matches `bor_[0-9a-f]{32}`, Active row in table, once-block wiped on re-show (router re-show refresh)
|
||||
- token flow: real-gate login (task-04 helper) → grounded mock-LLM turn → cited chip opens same-page `#doc-modal`; all 5 admin nav links absent, Sign out visible, whoami role `user`
|
||||
- caching: `localStorage["bor.token"]` survives reload with silent re-auth (no gate, no re-entry)
|
||||
- admin-only walls 403 on tokens/chats/docs/steering/git-sources; sign out clears session + cached token
|
||||
- revocation: UI two-step; chain pinned in the holder's own browser cookies — whoami still `user` (lazy) → next gated 401 clears the session → whoami anonymous; fresh login refused at the gate
|
||||
- wrong token: role=alert stays, malformed and well-formed-unknown 401 bodies byte-equal (no enumeration)
|
||||
- Results: `uv run pytest tests/e2e/test_api_tokens.py -v --no-cov` → **9 passed** (isolation); spot-check `test_admin_auth.py` + `test_share_chat.py` → 10 passed; `uv run pytest --cov=app` → green, `app/` coverage **99%** (>90%); `uv run ruff check .` clean; `uv run pyright` 0 errors
|
||||
- Notable: no app defects found — tasks 01–06 hold. One harness quirk worked around: httpx's cookie jar ignores the expired `Set-Cookie` the 401 sends, so the revocation chain is driven through the user context's real browser fetch (also matches the task's "context cookies" wording; app contract itself verified via TestClient)
|
||||
- DB hygiene: autouse fixture deletes only `e2e-`-labeled token rows (never TRUNCATE — shared dev DB); shared-chat row cleaned in `finally`
|
||||
- Next pending task: `08_regression_sweep_commit.md` (full pipeline + README auth section + atomic commit)
|
||||
@@ -0,0 +1,81 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 22%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 30%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 53%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 61%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 70%]
|
||||
........................................................................ [ 75%]
|
||||
........................................................................ [ 79%]
|
||||
........................................................................ [ 84%]
|
||||
........................................................................ [ 88%]
|
||||
........................................................................ [ 92%]
|
||||
........................................................................ [ 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 40 0 100%
|
||||
app/api/chat.py 178 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 0 100%
|
||||
app/api/git_sources.py 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 11 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/api/tokens.py 28 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 108 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/core/tokens.py 33 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 62 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 0 100%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 180 3 98%
|
||||
app/rag/llm.py 216 0 100%
|
||||
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 231 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3136 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
@@ -0,0 +1,13 @@
|
||||
All green. Final report:
|
||||
|
||||
**Phase 79, Task 08 — Regression sweep (commit owned by harness per pipeline rules)**
|
||||
|
||||
- Full suite: `uv run pytest --cov=app --cov-report=term` → **1627 passed, 99% coverage** (>90%; token deltas at 100%)
|
||||
- `uv run ruff check . && uv run pyright` → clean (0 errors)
|
||||
- E2E spot-checks, each in isolation: `test_api_tokens.py` 9✓, `test_admin_auth.py` 6✓, `test_share_chat.py` 4✓ (anonymous), `test_chat_rag.py` 3✓, `test_nav_switch_keeps_stream.py` 4✓, `test_smoke.py` 3✓
|
||||
- Real-browser + real-LLM verification (3 fresh windows, live server on :8085): admin generated a token in the Tokens view (plaintext shown once, gone after reload); private window passed the gate, chatted, opened a cited doc, **reloaded without re-entry** (cached token); anonymous window met the gate yet opened a shared chat; admin revoked → user's next question 401'd live and a fresh login got the generic invalid-token error; token user 403'd on `/api/docs`, `/api/chats`
|
||||
- README: new **API tokens** subsection under Admin & sign-in (generate/use/scope/revoke) + fixed two stale "viewer stays public" statements and the whoami/who-can-do-what tables
|
||||
- `.env.example` unchanged — no new settings added (verified); dev-DB verification artifacts cleaned (tokens + 2 test chats removed)
|
||||
- No defects found in prior tasks; no code changes needed
|
||||
- Per harness rules: no `git add`/`commit`, phase dir left in `todo/` for the harness
|
||||
- Next pending: phase 80 (`.agents/phases/todo/80_*/`), which builds on the now-gated `/api/suggestions`
|
||||
@@ -0,0 +1,81 @@
|
||||
........................................................................ [ 4%]
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 13%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 22%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 30%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 39%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 48%]
|
||||
........................................................................ [ 53%]
|
||||
........................................................................ [ 57%]
|
||||
........................................................................ [ 61%]
|
||||
........................................................................ [ 66%]
|
||||
........................................................................ [ 70%]
|
||||
........................................................................ [ 75%]
|
||||
........................................................................ [ 79%]
|
||||
........................................................................ [ 84%]
|
||||
........................................................................ [ 88%]
|
||||
........................................................................ [ 92%]
|
||||
........................................................................ [ 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 40 0 100%
|
||||
app/api/chat.py 178 0 100%
|
||||
app/api/chats.py 110 0 100%
|
||||
app/api/config.py 7 0 100%
|
||||
app/api/doc_drafts.py 93 0 100%
|
||||
app/api/docs.py 50 0 100%
|
||||
app/api/git_sources.py 212 0 100%
|
||||
app/api/health.py 10 0 100%
|
||||
app/api/steering.py 42 0 100%
|
||||
app/api/suggestions.py 11 0 100%
|
||||
app/api/sync.py 101 0 100%
|
||||
app/api/tokens.py 28 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 108 0 100%
|
||||
app/core/debugging.py 29 2 93%
|
||||
app/core/docs_push.py 39 0 100%
|
||||
app/core/logging.py 13 0 100%
|
||||
app/core/tokens.py 33 0 100%
|
||||
app/db.py 21 0 100%
|
||||
app/main.py 62 0 100%
|
||||
app/models.py 94 0 100%
|
||||
app/rag/__init__.py 0 0 100%
|
||||
app/rag/agent.py 222 0 100%
|
||||
app/rag/archive_upload.py 128 0 100%
|
||||
app/rag/chunker.py 206 4 98%
|
||||
app/rag/git_sources.py 14 0 100%
|
||||
app/rag/importer.py 180 3 98%
|
||||
app/rag/llm.py 216 0 100%
|
||||
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 231 0 100%
|
||||
-----------------------------------------------
|
||||
TOTAL 3136 12 99%
|
||||
coverage gate: app/ 99% (>90%) OK
|
||||
All checks passed!
|
||||
0 errors, 0 warnings, 0 informations
|
||||
validation OK
|
||||
Reference in New Issue
Block a user