Repository navigation
Backend asks blocking iOS parity — A8, A9, A11, A12 (+ A10 docs) #66
Description
Part of #44 · Backend changes needed in ~/Codez/interlinedlist (the Next.js app). No iOS work
here beyond consuming them; each item names what it unblocks.
A8 — GET /api/user/{username}/messages ignores Bearer 🔴 one-line fix, no client work
The route resolves the viewer with session-only getCurrentUser(), so a Bearer client is
anonymous on a profile wall. Live-proved: the response is byte-identical with and without a
valid token.
Consequences on iOS:
dugByMeis alwaysfalseon a profile wall, so a post's dig state flips between the feed and
the same post on the author's profile.- The mutual-block filter never applies to the wall endpoint.
Ask: switch to getCurrentUserOrSyncToken.
A11 — no collaborator-scoped document listing 🔴 blocks a shipped web feature on iOS
The web lists documents shared with you (app/documents/layout.tsx → getSharedDocuments(user.id)
→ components/documents/SharedDocumentsList.tsx), but the data is server-rendered — there is no
API route, so no mobile client can reproduce it. Lists already have GET /api/lists/watching;
documents have nothing.
Ask: add GET /api/documents/shared-with-me (or GET /api/documents?scope=shared) returning the
existing getSharedDocuments() shape — { id, title, role, updatedAt, isPublic, owner } —
authorized with getCurrentUserOrSyncToken.
A9 — inbound email-invite acceptance is session-only 🟠
GET/POST /api/lists/invite/{token} and /api/documents/invite/{token} use getCurrentUser. iOS can
send invites (ShareInvitesSheet) but an invited iOS user cannot accept in-app — the deep link
has to bounce out to the web and back.
Ask: accept Bearer on both.
A12 — undocumented surfaces 🟡
No /help/api/* page exists for: /api/lists/watching, /api/lists/{id}/contributors,
/api/dm/conversations, /api/limits, /api/messages/{id}/reply-counts,
/api/organizations/{id}/users.
Ask: document them. reply-counts especially — its name reads like in-app reply counts, but it
returns cross-post reply counts from Bluesky/Mastodon/LinkedIn/X; that misreading already made it
into our own planning docs.
A10 residual — AI docs still describe BYO-key 🟡 docs only
/help/ai and /help/api/ai-integration still say the user brings their own provider key. The
product shipped as a subscriber entitlement on the app's server-side key
(lib/ai/resolve-provider.ts; live /api/ai/status returns providers:["anthropic"] for an account
with no keys). iOS #43 was built against the deployed behaviour, not the docs.
Ask: update both pages, and drop hasOpenaiApiKey / hasAnthropicApiKey / hasGeminiApiKey from
GET /api/user if they are now vestigial.
Checklist
- A8 — Bearer on the profile-wall messages route ✅ verified done 2026-09-15
- A11 — documents shared-with-me route ❌ still missing (blocks W5: "Shared with me" documents (needs a backend route — A11) #54)
- A9 — Bearer on invite acceptance (lists + documents) ✅ verified done 2026-09-15
- A12 —
/help/api/*pages for the six undocumented routes - A10 — correct the AI docs; remove the vestigial key flags
Activity
docs: mark G15/G16/G18 shipped and point open work at epic #44
Adron commentedon Sep 15, 2026
Status re-verified against the backend working tree — 2026-09-15
app/api/user/[username]/messages/route.ts:3,23now imports and callsgetCurrentUserOrSyncToken.app/api/lists/invite/[token]/route.ts:3,52,83andapp/api/documents/invite/[token]/route.ts:3,52,83usegetCurrentUserOrSyncToken.shared-with-meroute exists;app/api/documents/sharedisshared/[token](share-link resolution), andapp/api/documents/route.tshas noscopehandling.getSharedDocumentsis still only called fromapp/documents/layout.tsx:22. This continues to block #54./help/api/*docs for six routesConsequence for iOS
dugByMeflip between the feed and a profile wall should be gone — worth aconfirmation pass on iOS, but no client change is required.
worth a follow-up issue to wire invite acceptance into the deep-link path rather than bouncing to
the web.
New backend ask discovered since this issue was filed
PATCH /api/messages/{id}is thereschedule route; iOS
EditMessageViewcannot work against it.POST /api/user/change-email/requestaccepts apasswordand never verifies it.Adron commentedon Sep 16, 2026
Remaining asks are backend-repo work — here is exactly what's needed for each
A8 and A9 are done (verified 2026-09-15). The three that remain all land in
~/Codez/interlinedlist, not here, so I'm leaving them rather than opening cross-repo PRs. What eachone needs to be actionable:
A11 —
GET /api/documents/shared-with-me🔴 highest value, blocks #54Everything needed already exists server-side; this is plumbing, not design.
getSharedDocuments(userId)(lib/documents/queries.ts:142) returns the exact shape, andapp/documents/layout.tsx:22already calls it — it just has no HTTP surface.app/api/documents/shared-with-me/route.ts(or?scope=sharedon the existingdocuments route — either is fine, the first is less likely to disturb the root-only listing).
getCurrentUserOrSyncToken, so Bearer clients work. This is the whole point of the ask.{ id, title, role, updatedAt, isPublic, owner }— whatevergetSharedDocumentsalready emits, unchanged.
GET /api/lists/watching) — does itpage? If yes, match it; if no, don't invent a different convention.
The iOS side is written up in #54 and can start the day this lands.
A12 —
/help/api/*pages for six routes 🟡/api/lists/watching,/api/lists/{id}/contributors,/api/dm/conversations,/api/limits,/api/messages/{id}/reply-counts,/api/organizations/{id}/users.reply-countsis the one that actually matters: the name reads like in-app reply counts, but itreturns cross-post reply counts from Bluesky/Mastodon/LinkedIn/X. That misreading already made it
into our own planning docs (
work-consolidation.mdrecorded it as a feed perf item) and cost are-scope. Worth a sentence on the page saying what it is not.
Since #86 (
dmConversations) and #84 (reply-counts) now have real iOS consumers, the request/responseshapes in those PRs can be lifted straight into the docs.
A10 — AI docs still describe BYO-key 🟡 docs only
/help/aiand/help/api/ai-integrationstill say the user brings their own provider key. Itshipped as a subscriber entitlement on the app's server-side key (
lib/ai/resolve-provider.ts).hasOpenaiApiKey/hasAnthropicApiKey/hasGeminiApiKeystill returned byGET /api/user? They are not inuserSelect(lib/auth/user-select.ts) — that file says thekey columns were deliberately removed after issues #199/#206/#207. So the ask to "drop them from
GET /api/user" appears already done; only the prose is stale. Worth confirming and strikingthat half of A10.
Suggested split
A11 is the only one gating iOS work. If it's useful I can draft the route in the backend repo as a
separate PR — say the word and tell me the pagination answer above. A12 and A10 are documentation and
don't block anything.