feat(service,features): a workspace's issues are sealed for following over Neon Realtime
Draft
CH
10d ago+506+506+012345678901234567890123456789-5-5-0123456789
First of two PRs making the Issues list live over Neon Realtime, stacked on #3287.
What
issuesLiveStatement(userId, workspaceId)inissue-store.ts: the workspace's standing issues, the same columns, bound (500, as a subquery), and membership rule aslistIssues, aliased withliveSelectionand deterministic (nonow()). Order is the reader's.GET /api/live/issues?workspaceId=inlive-app.ts: seals that statement for the bearer's account;invalid-requestwithout a workspace,unavailablewhere Realtime is misconfigured or the seal is refused. Route file and rewrites added (functions:rewrites). The existing/api/issuesroute is unchanged.@luke/features/issue-live: the answer and rows schemas,issuesOfLiveRows(sorts as the held read does), andHostedIssueClient.listLive.
Tests
- PGlite parity in
issue-store.test.ts: the live rows, built byissuesOfLiveRows, deep-equallistIssuesfor a member (a teammate's issue, a changed one, an archived one left out), and are empty for an outsider. live-app.test.ts: sealed for the bearer and the workspace named; refused without a workspace; unavailable without Realtime.- New goldens in
hosted-wire-schemas.test.tsunderLUKE_UPDATE_FIXTURES=1:issue-live-issuesLiveAnswerSchema.jsonandissue-live-issuesLiveRowsSchema.json(new schemas only, no diffs to existing ones).
Checks run locally
lint, oxlint, knip, discarded-effect, repository checks (task names, rewrites), typecheck of database/features/service/web, and the features, issue-store, and live-app tests.
The host follow and the window push come in the next PR.
Made with Luke
After the restack
listLive names the account (?userId=), as #3287's live reads now do, and reads a 401 as LIVE_SIGNED_OUT. That is tested in issue-client.test.ts.