v9.0.0 — Social Monitoring & Quick Capture #139

Merged
claude-bot merged 8 commits from feat/v9-social-watch into main 2026-07-18 06:43:49 +00:00
Contributor

Milestone v9.0.0 — watch Bluesky/Mastodon accounts & tags and turn a matching post into an entry in one click.

Status: shipping v9.0.0 = P1 + #117 + P2 (Bluesky Jetstream). Account linking (P3) and Mastodon real-time are deferred to a dedicated spike (the issue's own recommendation — DPoP OAuth + browser flows can't be verified headlessly). The milestone's "done when" is P1 shipping; P2/P3 are upgrades. 334 tests pass (44 files), tsc clean, migration 052 applies, app build green. No new npm dependencies.

In this release

  • P1 (#22) — Public-data watch + one-click capture (polling MVP). (migration 052)
  • #117 — Worker-process split: BullMQ workers + streams can run in a dedicated worker container (safe-by-default; RUN_WORKERS_IN_API defaults on).
  • P2 (#23, partial) — Bluesky Jetstream real-time consumer (single shared WS, server-side DID filter, reconnect/backoff, cursor resume; gated by watch.streamingEnabled, off by default; health at /api/watch/stream-status).

Deferred to a follow-up spike

  • P2 (#23) — Mastodon real-time: needs an OAuth token (most instances no longer allow unauthenticated streaming) → lands with P3.
  • P3 (#24) — Account linking: Mastodon OAuth2 + Bluesky AT-Protocol OAuth (DPoP + hosted client metadata). Security-sensitive + browser/PDS flows requiring live verification.
  • Minor: a Watch-page stream-health chip (endpoint exists).

Closes #22.

🤖 Generated with Claude Code

Milestone [v9.0.0](https://git.rhoving.com/rbrooks/TeaLeaves/milestones) — watch Bluesky/Mastodon accounts & tags and turn a matching post into an entry in one click. **Status: shipping v9.0.0 = P1 + #117 + P2 (Bluesky Jetstream).** Account linking (P3) and Mastodon real-time are deferred to a dedicated spike (the issue's own recommendation — DPoP OAuth + browser flows can't be verified headlessly). The milestone's "done when" is P1 shipping; P2/P3 are upgrades. **334 tests pass** (44 files), tsc clean, migration 052 applies, app build green. No new npm dependencies. ### In this release - [x] **P1 (#22)** — Public-data watch + one-click capture (polling MVP). *(migration 052)* - [x] **#117** — Worker-process split: BullMQ workers + streams can run in a dedicated `worker` container (safe-by-default; `RUN_WORKERS_IN_API` defaults on). - [x] **P2 (#23, partial)** — Bluesky **Jetstream** real-time consumer (single shared WS, server-side DID filter, reconnect/backoff, cursor resume; gated by `watch.streamingEnabled`, off by default; health at `/api/watch/stream-status`). ### Deferred to a follow-up spike - [ ] **P2 (#23) — Mastodon real-time**: needs an OAuth token (most instances no longer allow unauthenticated streaming) → lands with P3. - [ ] **P3 (#24)** — Account linking: Mastodon OAuth2 + Bluesky AT-Protocol OAuth (DPoP + hosted client metadata). Security-sensitive + browser/PDS flows requiring live verification. - [ ] Minor: a Watch-page stream-health chip (endpoint exists). Closes #22. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(v9 p1): social watch backend — watches, poller, discovered posts, search
Some checks failed
CI / API — typecheck & tests (push) Has been cancelled
CI / App — typecheck, test & build (push) Has been cancelled
CI / Images — production build (push) Has been cancelled
d3631f8864
Migration 052: watches (project-scoped subscriptions) + discovered_posts
(review queue, deduped by source_id). Platform adapters (bluesky via public
AppView, mastodon via instance REST through the SSRF guard) behind a small
WatchAdapter interface. watchWorker: BullMQ repeatable poll (interval
watch.pollIntervalMinutes, default 10) enqueuing per-watch polls. Routes at
/api/watch: watches CRUD (instance_url SSRF-validated on create), discovered-
post queue + add/dismiss, and live direct search. addSocialPostAsEntry runs
checkDedup before insert (mirrors importWorker), surfacing an existing entry on
an exact source_id match rather than duplicating.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
test(v9 p1): watch endpoints — CRUD, SSRF guard, queue add/dismiss, dedup
Some checks failed
CI / Images — production build (push) Successful in 50s
CI / API — typecheck & tests (push) Has been cancelled
CI / App — typecheck, test & build (push) Has been cancelled
565eb20716
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(v9 p1): Watch frontend — nav item + page (Watches/Queue/Search)
Some checks failed
CI / API — typecheck & tests (push) Has been cancelled
CI / App — typecheck, test & build (push) Has been cancelled
CI / Images — production build (push) Has been cancelled
1f71c532fc
New top-level Watch nav (desktop + mobile overflow) with a pending-count badge.
WatchPage with three tabs: Watches (list/create/enable/delete, Mastodon caveat
inline), Queue (add-as-entry / dismiss with dedup messaging), Search (live
account/tag search → add to watchlist / add as entry). api client, plain-text
content, no new deps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs(v9): changelog for P1 (social watch + one-click capture)
Some checks failed
CI / Images — production build (push) Has been cancelled
CI / API — typecheck & tests (pull_request) Has been cancelled
CI / App — typecheck, test & build (pull_request) Has been cancelled
CI / Images — production build (pull_request) Has been cancelled
CI / API — typecheck & tests (push) Has been cancelled
CI / App — typecheck, test & build (push) Has been cancelled
7cc942c588
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(v9 #117): worker-process split — dedicated worker entrypoint
Some checks failed
CI / App — typecheck, test & build (push) Successful in 2m11s
CI / Images — production build (push) Successful in 2m10s
CI / Images — production build (pull_request) Successful in 14s
CI / App — typecheck, test & build (pull_request) Successful in 1m44s
CI / API — typecheck & tests (push) Successful in 4m32s
CI / API — typecheck & tests (pull_request) Has been cancelled
738b644cb2
Extract BullMQ worker startup into workers.ts (startWorkers) so it runs either
in the API process (RUN_WORKERS_IN_API=true, default — single-process deploys
unchanged) or a dedicated worker.ts process. index.ts starts them in-process
only when the flag is set; the API always owns migrations. deploy/compose.yaml
gains a `worker` service (same image, node dist/worker.js, depends_on api
healthy) with RUN_WORKERS_IN_API=false on the API — the P2-streaming prereq.
Safe-by-default: image auto-update never changes topology (Watchtower swaps
images, not compose); a host adopts the split by updating its compose. Documented
in deploy/README.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(v9 p2): Bluesky Jetstream real-time consumer (#23)
Some checks failed
CI / API — typecheck & tests (push) Has been cancelled
CI / App — typecheck, test & build (push) Has been cancelled
CI / Images — production build (push) Has been cancelled
CI / API — typecheck & tests (pull_request) Has been cancelled
CI / App — typecheck, test & build (pull_request) Has been cancelled
CI / Images — production build (pull_request) Has been cancelled
c8c5f93d57
A single shared Jetstream WebSocket per instance filters server-side by
wantedDids = every watched Bluesky account DID (resolved from handles),
wantedCollections=app.bsky.feed.post — genuinely real-time, cheap regardless of
watch count. Reconnect with backoff, cursor resume, dynamic DID-set refresh.
Runs in the worker set (#117); gated by watch.streamingEnabled (default off) and
additive to polling (global source_id UNIQUE dedupes). Cross-process health via
a Redis heartbeat, exposed at GET /api/watch/stream-status.

Scoping (honest platform reality): Mastodon real-time needs an auth token
(most instances no longer allow unauthenticated streaming), so it lands with P3
account linking; Mastodon + Bluesky tags stay on polling for P2. Extracted the
shared landDiscoveredPost helper. Pure event parser unit-tested.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs(v9): changelog for #117 (worker split) + P2 (Jetstream)
Some checks failed
CI / Images — production build (push) Successful in 35s
CI / App — typecheck, test & build (push) Successful in 1m39s
CI / API — typecheck & tests (push) Has been cancelled
CI / Images — production build (pull_request) Has been cancelled
CI / API — typecheck & tests (pull_request) Has been cancelled
CI / App — typecheck, test & build (pull_request) Has been cancelled
ccde10e22d
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chore(release): v9.0.0 — Social Monitoring & Quick Capture
All checks were successful
CI / App — typecheck, test & build (push) Successful in 2m29s
CI / App — typecheck, test & build (pull_request) Successful in 1m28s
CI / API — typecheck & tests (push) Successful in 4m26s
CI / Images — production build (push) Successful in 4m3s
CI / Images — production build (pull_request) Successful in 12s
CI / API — typecheck & tests (pull_request) Successful in 4m5s
980769d5d2
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
claude-bot deleted branch feat/v9-social-watch 2026-07-18 06:43:50 +00:00
Sign in to join this conversation.
No reviewers
No project
No assignees
2 participants
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
rbrooks/TeaLeaves!139
No description provided.