Refs-only cards with on-demand content - phase 2 of the #189 track #323

Merged
robbertbos merged 1 commit from phase-2-refs-only into main 2026-08-16 12:45:01 +00:00
Owner

A card now stores references only: post_id, channel_id, channel_name, permalink, thread_root_id. Message, author, channel names and attachments come live from Mattermost through a new bulk pass-through (POST /api/mm/cards/content: posts + authors + channel/team names in one round trip per linked server, tombstones for posts Mattermost no longer returns). Nothing of the message rests in the database; what does rest stays encrypted (phase 1).

Backend: sync drops the edit-refresh path and the author lookup; revision 98aee9976b23 strips existing rows one-way (rollout note in the changelog); import of old bundles keeps only ref fields; the dev MM mock answers the three content reads so preview and e2e work.

Frontend: one chunked bulk content query per list with an in-memory-only cache (deliberately never localStorage), required content-prop down the row tree so vue-tsc catches a missing hookup, tombstone rows that keep status/planning/notes, a per-list retry notice on fetch failure, search and mention-prefetch reading from the content cache, and e2e specs stubbing the content endpoint keyed on source_id.

Measured against digilab before building: the on-demand model adds ~30-105 ms to a first list paint (ping p50 15 ms, two to three round trips).

Gates: 1990 backend tests at 100% coverage, 1206 vitest, vue-tsc + build, full e2e green (118 passed).

A card now stores references only: post_id, channel_id, channel_name, permalink, thread_root_id. Message, author, channel names and attachments come live from Mattermost through a new bulk pass-through (POST /api/mm/cards/content: posts + authors + channel/team names in one round trip per linked server, tombstones for posts Mattermost no longer returns). Nothing of the message rests in the database; what does rest stays encrypted (phase 1). Backend: sync drops the edit-refresh path and the author lookup; revision 98aee9976b23 strips existing rows one-way (rollout note in the changelog); import of old bundles keeps only ref fields; the dev MM mock answers the three content reads so preview and e2e work. Frontend: one chunked bulk content query per list with an in-memory-only cache (deliberately never localStorage), required content-prop down the row tree so vue-tsc catches a missing hookup, tombstone rows that keep status/planning/notes, a per-list retry notice on fetch failure, search and mention-prefetch reading from the content cache, and e2e specs stubbing the content endpoint keyed on source_id. Measured against digilab before building: the on-demand model adds ~30-105 ms to a first list paint (ping p50 15 ms, two to three round trips). Gates: 1990 backend tests at 100% coverage, 1206 vitest, vue-tsc + build, full e2e green (118 passed).
Cards store references only; content comes from Mattermost per request
All checks were successful
CI / release-scripts (pull_request) Successful in 6s
security-scan / SBOM (trivy) (pull_request) Successful in 10s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 15s
security-scan / JS SCA (npm audit) (pull_request) Successful in 17s
security-scan / Python SAST (bandit) (pull_request) Successful in 17s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 36s
test-build / build (frontend) (pull_request) Successful in 52s
CI / frontend-test (pull_request) Successful in 59s
test-build / build (backend) (pull_request) Successful in 1m7s
test-build / build (pull_request) Successful in 0s
CI / pre-commit (pull_request) Successful in 1m37s
CI / backend-test (pull_request) Successful in 2m40s
CI / e2e (pull_request) Successful in 4m4s
CI / release-scripts (push) Successful in 7s
security-scan / SBOM (trivy) (push) Successful in 11s
security-scan / Filesystem scan (trivy fs) (push) Successful in 14s
security-scan / JS SCA (npm audit) (push) Successful in 17s
security-scan / Python SAST (bandit) (push) Successful in 18s
security-scan / Python SCA (pip-audit) (push) Successful in 37s
publish-main / build (frontend) (push) Successful in 57s
CI / frontend-test (push) Successful in 1m1s
publish-main / build (backend) (push) Successful in 1m12s
publish-main / build (push) Successful in 0s
CI / pre-commit (push) Successful in 1m40s
CI / backend-test (push) Successful in 2m42s
CI / e2e (push) Successful in 4m6s
83996c0acc
cards.source_data shrinks to post_id, channel_id, channel_name, permalink
and thread_root_id. A new bulk pass-through, POST /api/mm/cards/content,
serves message, author, channel and attachment data live per page view
(posts, authors and channel names in one round trip per linked server), so
an edited post needs no resync and message content no longer rests in the
database at all. A post Mattermost no longer returns renders as a tombstone
that keeps status, planning and notes; a failed fetch shows one retry
notice per list.

Sync drops the edit-refresh path and the author lookup; the strip revision
(98aee9976b23) removes content from existing rows one-way. Import of old
bundles keeps only the ref fields. The frontend fetches content once per
list through a chunked bulk query with an in-memory (never persisted)
cache; search and mention-prefetch read from it.

Measured beforehand against digilab: the on-demand model adds ~30-105 ms
to a first list paint (ping p50 15 ms; two to three round trips).
robbertbos deleted branch phase-2-refs-only 2026-08-16 12:45:01 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
robbertbos/waggle!323
No description provided.