···161- [x] API endpoints (write path — proxy to user's PDS) — **DONE** (ATB-12):
162 - `POST /api/topics` — create `space.atbb.post` record with `forumRef` but no `reply` ref. Validates text (1-300 graphemes), writes to user's PDS via OAuth agent, returns {uri, cid, rkey} with 201 status. Fire-and-forget design (firehose indexes asynchronously). (`apps/appview/src/routes/topics.ts:13-119`)
163 - `POST /api/posts` — create `space.atbb.post` record with both `forumRef` and `reply` ref. Validates text, parses rootPostId/parentPostId, validates parent belongs to same thread, writes to user's PDS, returns {uri, cid, rkey}. (`apps/appview/src/routes/posts.ts:13-119`)
164- - Helper functions for validation: `validateGraphemeLength()` (1-300 graphemes using `@atproto/api` UnicodeString), `getForumByUri()`, `getPostsByIds()` (bulk lookup with Map), `validateReplyParent()` (thread boundary validation). (`apps/appview/src/routes/helpers.ts:65-190`)
165- - Tests: 7 integration tests for POST /api/topics, 6 integration tests for POST /api/posts, 16 unit tests for helpers. All 112 appview tests passing.
0166167#### Phase 2: Auth & Membership (Week 5–6)
168- [x] Implement AT Proto OAuth flow (user login via their PDS) — **Complete:** OAuth 2.1 implementation using `@atproto/oauth-client-node` library with PKCE flow, state validation, automatic token refresh, and DPoP. Supports any AT Protocol PDS (not limited to bsky.social). Routes in `apps/appview/src/routes/auth.ts` (ATB-14)
···161- [x] API endpoints (write path — proxy to user's PDS) — **DONE** (ATB-12):
162 - `POST /api/topics` — create `space.atbb.post` record with `forumRef` but no `reply` ref. Validates text (1-300 graphemes), writes to user's PDS via OAuth agent, returns {uri, cid, rkey} with 201 status. Fire-and-forget design (firehose indexes asynchronously). (`apps/appview/src/routes/topics.ts:13-119`)
163 - `POST /api/posts` — create `space.atbb.post` record with both `forumRef` and `reply` ref. Validates text, parses rootPostId/parentPostId, validates parent belongs to same thread, writes to user's PDS, returns {uri, cid, rkey}. (`apps/appview/src/routes/posts.ts:13-119`)
164+ - Helper functions for validation: `validatePostText()` (1-300 graphemes using `@atproto/api` UnicodeString, with type guard for non-string input), `getForumByUri()`, `getPostsByIds()` (bulk lookup with Map), `validateReplyParent()` (thread boundary validation). (`apps/appview/src/routes/helpers.ts:65-190`)
165+ - Error handling: Type guards prevent crashes, JSON parsing wrapped in try-catch (400 for malformed), catch blocks re-throw TypeError/ReferenceError (don't swallow programming bugs), network errors (503) vs server errors (500) properly classified. No silent data fabrication (returns null).
166+ - Tests: 16 integration tests for POST /api/topics (includes 5 PDS error scenarios), 14 integration tests for POST /api/posts (includes 5 PDS error scenarios), 16 unit tests for helpers. **134 total appview tests passing** (29 new tests for ATB-12). Three comprehensive review rounds completed.
167168#### Phase 2: Auth & Membership (Week 5–6)
169- [x] Implement AT Proto OAuth flow (user login via their PDS) — **Complete:** OAuth 2.1 implementation using `@atproto/oauth-client-node` library with PKCE flow, state validation, automatic token refresh, and DPoP. Supports any AT Protocol PDS (not limited to bsky.social). Routes in `apps/appview/src/routes/auth.ts` (ATB-14)