feat: MPS-24 — Checksums as a verifiable page report

Operator: the content page's Checksums panel should cover the whole
page (product/content file + thumbnail1 + title + description) so a
human or agent can re-hash what they see and confirm provenance.

- The async checksum infra is already generic: compute_checksums_async
  hashes ANY uploaded key incl. thumbnail1, recomputed on re-upload
  (no separate thumbnail auto-gen pipeline exists) — so the stored
  file + thumbnail checksums are already kept current.
- Product.content_checksums(): LIVE SHA-256+MD5 of title + description
  (computed on read, not stored) so it always matches the visible
  text — exactly what an agent/human re-hashes to verify.
- content.j2 Checksums <details> is now a 4-asset report table
  (Asset / Algorithm / Hash), SHA-256 + MD5 per asset.
- Tests: TestContentChecksums (3, no-DB). 1150 passed.
- Docs: mps-24.md Phase 2.8p.
This commit is contained in:
russell@unturf.com 2026-05-17 13:41:45 -04:00
parent 3467909b80
commit bc1c727a11
No known key found for this signature in database
4 changed files with 97 additions and 6 deletions

View file

@ -363,6 +363,24 @@ Tests (`test_functional.py::TestProductTagsSpa`):
Deferred (occasional click, not the hot path): AJAX-ifying the
"Suggest categories" link — still a full navigation by design.
**Phase 2.8p — Checksums as a verifiable page report** (shipped
2026-05-17): operator wants the content page's "Checksums" panel to
cover the whole page, not just the product file —
product/content file + thumbnail1 + title + description, so a human
or agent can re-hash what they see and confirm provenance. The async
checksum infra (`lib/checksums.py` / `compute_checksums_async`) is
already generic — the upload pipeline (`views/product.py:692`)
computes `checksums[file_key]` for ANY uploaded key incl.
`thumbnail1`, recomputed on re-upload (no separate thumbnail
auto-gen pipeline exists). Added `Product.content_checksums()`
**live** SHA-256+MD5 of `title`+`description` (computed on read, not
stored, so it always matches the visible text). `content.j2`
Checksums `<details>` is now a 4-asset report table (Asset /
Algorithm / Hash), SHA-256 + MD5 per asset. Tests:
`TestContentChecksums` (3, no-DB). Decisions: stored+recompute-on-
change for thumbnail (already satisfied by the generic upload path),
SHA-256 + MD5 both shown (match existing).
**Phase 2.8o — manual tags are ghost metadata: hide behind a flag**
(shipped 2026-05-17): operator direction — stop hand-attaching tags
("ghost metadata" invisible to humans/agents reading the page);