Slice 6: notifications per §15

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ben Stull
2026-05-24 23:09:04 -07:00
parent 1b0968a9a2
commit f67d0aa0db
21 changed files with 3588 additions and 168 deletions
+29
View File
@@ -901,6 +901,35 @@ def make_router(
)
return {"ok": True, "message_id": message_id}
@router.post("/api/rfcs/{slug}/branches/{branch}/chat-seen")
async def advance_chat_seen(slug: str, branch: str, body: dict, request: Request) -> dict[str, Any]:
"""§15.7 chat-seen cursor advance.
Body: `{"last_seen_message_id": <int>}`. Upserts branch_chat_seen
and runs the §15.7 reconciler — every unread notification scoped
to this (slug, branch) on or before the new cursor is marked read.
"""
viewer = auth.require_user(request)
_require_rfc_with_repo(slug)
if not _can_read_branch(slug, branch, viewer):
raise HTTPException(403, "Branch is private")
last_seen = int(body.get("last_seen_message_id") or 0) or None
db.conn().execute(
"""
INSERT INTO branch_chat_seen (user_id, rfc_slug, branch_name, last_seen_message_id, seen_at)
VALUES (?, ?, ?, ?, datetime('now'))
ON CONFLICT(user_id, rfc_slug, branch_name) DO UPDATE SET
last_seen_message_id = excluded.last_seen_message_id,
seen_at = excluded.seen_at
""",
(viewer.user_id, slug, branch, last_seen),
)
from . import notify
reconciled = notify.reconcile_seen_advance(
user_id=viewer.user_id, rfc_slug=slug, branch_name=branch,
)
return {"ok": True, "reconciled": reconciled}
@router.post("/api/rfcs/{slug}/branches/{branch}/threads/{thread_id}/resolve")
async def resolve_thread(slug: str, branch: str, thread_id: int, request: Request) -> dict[str, Any]:
viewer = auth.require_contributor(request)