-
v7.2.0
Stablereleased this
2026-07-17 16:37:36 +00:00 | 100 commits to main since this releaseTea Leaves v7.2.0 — Reliability, Data Integrity & Docs
Released 2026-07-17
The Medium/Low remainder of the 2026-07-15 codebase audit — the things that rot quietly rather than break loudly — plus two bonus features and a long-standing CI flake finally root-caused. All 13 milestone issues, no breaking changes. Migrations
044–046(additive;046renames one column).🛡️ Data integrity
- Deleting a user no longer strips attachments off the entries it preserves (#98).
media.user_idwas stillON DELETE CASCADEwhileentries.user_idisSET NULL— so a departed collaborator's media was hard-deleted (and files orphaned on disk) even on entries the schema intends to keep. Migration044makes itSET NULL;entry_idremains the lifecycle anchor. - Soft-deleted content no longer leaks (#93, #94). The legacy motif share query served trashed motifs and entries; export leaked trashed rows across four queries (including one that embedded a trashed entry's content via a connection to a live one). CSV export cells starting
= + - @are now neutralised against spreadsheet formula injection. - Federation optimistic-lock TOCTOU (#96). The lock read happened on the pool before the write transaction, so a concurrent local edit could be silently clobbered by a stale remote update. Now
SELECT … FOR UPDATEinside the transaction; regression-tested with a real concurrent-edit race. - Media access is project-scoped, not uploader-scoped (#135). Every media route keyed off
media.user_id, so a collaborator's uploads were invisible to the project owner today, and (post-#98) a deleted uploader's preserved media was unreachable. Reads now scope to the entry's project; delete is stricter (uploader or project owner only). Multi-user tested.
⚙️ Reliability & ops
/healthprobes its dependencies (#97). It returnedokthe moment the event loop was alive; now it runsSELECT 1+ RedisPING(each bounded) and returns 503 when either is down. Added a containerHEALTHCHECKand gatedapponservice_healthy. (Note: Docker Compose doesn't restart on healthcheck failure — that's tracked in #137 → monitoring.)- CI builds the production images (#103) and asserts the migrations copy landed — a Dockerfile/peer-dep regression can no longer ship unverified.
- Bounded Redis job retention (#100), top-level crash handlers (#101), a project-scoped entry-list index (#95), and the AP signature freshness window widened 30 s → 5 min (#102) so clock-skewed federated peers stop being rejected as invalid.
✨ Features
- Semantic dedup Pass 2 is real (#99). It was documented as active but never existed — the duplicate-review queue could never fill. Now cosine similarity over
text_embeddingflags near-duplicate imports, with imports embedding inline (one AI call per post) and a dedicatedimport.dedupThreshold(default 0.95) so a themed archive doesn't flag itself. - Real perceptual image dedup (#136).
media.phashheld a SHA-256 of the bytes (matches only byte-identical files) under a misleading name. Renamed tocontent_sha256; added a 64-bit dHash so re-encoded/resized copies are caught. Threshold set from measurement — re-encodes 0–7 bits apart, distinct images ≥24, default 10 in the gap.
📚 Docs
- README documents v6.2 and v7 (#104) — it trailed the code by a major version; the federation trust model is now written down for a new operator. Categories/Insights added; two further stale claims fixed.
🧪 Internal
API suite grew to 268 tests (from 232). And the
API — typecheck & testsCI flake is root-caused and fixed: with no AI configured the app defaults to ollama atlocalhost:11434, so every entry-write test fired a fire-and-forget embedding fetch that piled up inside CI's Docker-in-Docker and starved the pg pool, pushinganalytics.test.tspast its 15 s timeout.test/setup.tsnow takes the suite off the network for AI. It was never the runner.Upgrading: migrations
044–046apply on boot; no config changes.046renamesmedia.phash→media.content_sha256and addsmedia.dhash.Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Deleting a user no longer strips attachments off the entries it preserves (#98).