phase: 148_pdf_pages_in_sources
**Phase 148 — final verification pass: complete, 100% green.**
- **Verified (tasks 01–04 already implemented):** page render/persist at index (`_persist_page_copies`, fail-soft, stale-replace, qualifier-loss, prune hook via `_delete_page_copies`); public `GET /api/documents/{id}/pages/{n}` (uuid4-credential, 404-all-non-servable, `image/png` + cache header); `DocContent.page_urls` additive-omitted; shared `renderDocument` strip (lazy imgs, "Page N" captions, text + Summary suppressed, onerror note, createElement-only); migration 0026; `pdf_page_dir` setting; `.env.example` entry
- **Completion criteria:** (1) pictorial + fallback classes get `p{N}.png` + `page_count`, text-heavy gets neither — pinned, pass; (2) unchanged re-sync renders zero (fast path) — pass; (3) changed re-index replaces copies, qualifier-loss/prune delete — pass; (4) route 404 matrix + payload key absent-never-null — pass; (5) modal AND /document.html strip with suppression, text-heavy byte-identical — E2E pass; (6) see below; (7) no completed-phase drift — full suite green
- **Tests:** `uv run pytest --cov=app --cov-report=term-missing` → **3461 passed, 0 failed**, `app/` coverage **99%** (>90%); `uv run pytest tests/e2e/test_pdf_pages_in_sources.py -v --no-cov` → **4 passed** in isolation; `uv run ruff check .` clean; `uv run pyright` → 0 errors, 0 warnings
- **Documentation:** README had **1 pre-existing inconsistency** — the Production Deployment section's standalone `podman run` example (and compose note) omitted the **required** `BOR_ADMIN_PASSWORD`/`BOR_SESSION_SECRET` (the fail-loud boot gate the README's own Admin section documents — the container would refuse to start); fixed with the two `-e` flags + a note for the compose path. All else verified consistent: 70/70 `.env.example` vars documented, all defaults match `config.py`, pages table matches routes, Containerfile/esbuild/uid-10001/healthcheck/entrypoint claims accurate, QA commands match pytest config. **AGENTS.md: verified consistent — no changes needed**
- **Notable:** repo uses `Containerfile` (Podman) — README's `podman build` example is valid as-is; no live infrastructure touched
- **Next pending phase:** `149_sync_progress_box`
This commit is contained in:
@@ -4778,13 +4778,56 @@ a.answer-image:hover { text-decoration: underline; } /* flat — the caption und
|
||||
}
|
||||
/* The onerror fallback (the route's 404 — the row exists but the
|
||||
copy was lost): a muted note in the card's place-of-image; the
|
||||
description below still renders, so the doc stays readable. */
|
||||
description below still renders, so the doc stays readable. Phase
|
||||
148 (task 03) reuses THIS class for the page strip's lost-page
|
||||
note (the same muted styling — no new pattern). */
|
||||
.doc-image-unavailable {
|
||||
margin: 1.25rem 1rem;
|
||||
color: var(--ink-soft); /* 5.1:1 on --surface (AA) */
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* Page strip (phase 148, task 03): the viewer's rendered-page strip
|
||||
for a page-qualifying PDF — the payload's page_urls (task 02's
|
||||
exact 1-based route list) replaces the text content AND the
|
||||
.doc-summary panel (the owner's contract: the per-page
|
||||
descriptions stay in the DB for Q&A, just not shown to the user).
|
||||
The core renders it into the SAME #doc-content slot the .doc-raw /
|
||||
.doc-md paths use — no new column — inside the existing doc
|
||||
content column: --chat-column (72rem — the .container width, the
|
||||
.doc-md / .doc-image language) at every viewport. A vertical stack
|
||||
(one page per row — the natural reading order for instruction
|
||||
manuals); each figure carries the page PNG on the non-clashing
|
||||
--surface with the line border + radius (the .doc-image figure
|
||||
precedent — a page PNG must sit on a surface in both themes) and a
|
||||
centered muted "Page N" caption. Static content — no animation
|
||||
(nothing for prefers-reduced-motion to still); the lazy imgs + alt
|
||||
text (WCAG) carry the accessibility. Phase-08 tokens only (no new
|
||||
hue — the monochrome invariant). */
|
||||
.doc-pages {
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
max-width: var(--chat-column);
|
||||
margin-inline: auto;
|
||||
}
|
||||
.doc-page { margin: 0; }
|
||||
.doc-page img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius);
|
||||
background: var(--surface);
|
||||
}
|
||||
.doc-page-num {
|
||||
font-size: 0.78rem;
|
||||
color: var(--ink-soft); /* 8.2:1 on --surface, ~9.7:1 on --bg (AA in both themes) */
|
||||
text-align: center;
|
||||
padding: 0.35rem 0 0;
|
||||
}
|
||||
|
||||
/* Designed not-found state (no emoji — plain SVG mark, phase 08 rule). */
|
||||
.doc-not-found {
|
||||
width: 100%;
|
||||
|
||||
Reference in New Issue
Block a user