Files
captoys/social-coop-checklist.md
T
dckcandClaude Opus 5.5 99ce5b6964 capsite: goal trees for a zotero cache and a social.coop cache
Both follow the diigo-cache pattern (webapp holds the credential,
read-only and minted narrow at the source; the cache serves a public
page). Zotero's versioned sync answers diigo's stale-head problem;
Mastodon's doesn't announce edits/deletes, so its tree carries that
as a design question.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-07 10:21:24 -05:00

5.4 KiB

social.coop cache goal tree

The same conventions as the diigo goal tree: each - [ ] is a goal, its indented children must pass first, working notes sit under each goal.

  • madmode's weekly roundup includes my social.coop activity (#23, PESOS): a cache of @dckc@social.coop — posts, boosts, and (with discretion) bookmarks and favourites; the access token stays inside webapp, so madmode holds no credential

    • 0. Decide the shape (user's call before code): - [ ] 0-i. New worker masto-cache/ beside diigo-cache/, or generalize diigo-cache? Recommendation: a new worker; extract shared pieces once two caches work. - [ ] 0-ii. Which feeds? Public posts and boosts need no credential (GET /api/v1/accounts/:id/statuses, or the ActivityPub outbox). Bookmarks, favourites, and followers-only posts need a token. Bookmarks are private by nature: publish them only behind an explicit opt-in (what counts as opting in is open). - [ ] 0-iii. Mastodon API or ActivityPub? The API is simpler and covers bookmarks/favourites; ActivityPub works against any server (portability if the account moves). Recommendation: the API now, keyed by the post's ActivityPub uri so a later move keeps ids stable.

    • 1. Credential discipline: a token from social.coop → Preferences → Development → New application, scopes read-only and narrow (read:statuses read:accounts read:bookmarks read:favourites, per 0-ii) — attenuation at the source. It rides as Authorization: Bearer, which webapp's mint form already blanks. Token → webapp DO storage only; ids → password manager. Revoking the app on social.coop is the kill switch.

    • 2. The cache (masto-cache/, the 1c pattern from diigo): - [ ] 2-i. Mint and wire against https://social.coop/api/; accounts/lookup?acct=dckc gives the account id. - [ ] 2-ii. Storage: one table per feed (statuses, bookmarks, favourites), keyed by uri, storing the status JSON and its edited_at. Durable state from day one: a SCHEMA_V1 step. - [ ] 2-iii. Fill: page backward with max_id (40 per page) following the Link header — bookmarks and favourites paginate only by Link (their cursors aren't status ids). Honor X-RateLimit-Remaining/-Reset (300 per 5 minutes is Mastodon's default). - [ ] 2-iv. Tests: pnpm lint && pnpm test, the real worker against a fake Mastodon, including Link pagination and a rate-limit response. - [ ] 2-v. Complete: a filled cache matches the account archive (Preferences → Import and export → Request your archive: outbox.json, likes.json, bookmarks.json), the analogue of diigo's scripts/compare-export.ts.

    • 3. Freshness: new posts are cheap (min_id = newest stored, page forward). Edits and deletions of older posts are not announced to an API poller; options: re-fetch the last N days on each refresh (the window a roundup cares about), or follow the streaming API. A test: a post added, one edited, and one deleted in the fake; the weekly window reflects all three. A cron alarm in the cache DO drives it.

    • 4. Read surfaces: /public/dckc with the date window and q filter of diigo's 1d (the same query module, if 0-i shares it), HTML and JSON; JSON shape pinned by a test. Serve only visibility: public posts (and opted-in bookmarks) there — followers-only and direct posts never reach a public page; a test says so.

    • 5. madmode's weekly page includes it: diigo's goal 4 (/bookmarks/2026-W41) grows a section from this cache, or becomes a combined /weekly/2026-W41. Same editorial question as there: raw list, or a draft the user edits.

    • 6. Deployed: after diigo's goal 5; rate-limit /public/*; mint against prod; fill.

    • 7. Token revocation: when social.coop rejects the token (401), refreshes fail; the public page keeps serving what's stored and says so. Re-mint is manual; same re-wire question as diigo's goal 6.

How to run

TBD with goal 2; it should mirror the diigo how-to-run.

Working rules

capsite AGENTS.md: dev servers are the user's job; durable state, loud about breaking changes; secrets discipline; generated config types.

Pointers