Reshape the ai_sessions table (migration 003) and mapping/routes to the
full AISession contract: title, kind, notes, created_at, last_message_at;
drop legacy role/model/settings. toAISession now maps the new columns and
routes create/patch/messages handlers use the new shape.
- Fix PATCH /api/projects/:id/shares/:userId: query SELECT 1 instead of
SELECT id (project_shares has a composite PK, no id column)
- Add audit logging to existing share grant/revoke routes
- Add POST /api/projects/:id/transfer for ownership handoff
- Remove inline admin user/audit routes from routes.ts (now in admin.ts)
- Remove unused requireAdmin import and userPatch schema from routes.ts
Story whiteboard built on React Flow v11: free-form canvas of typed
nodes (character, world, chapter, note, image, group) with draggable
leads-to/contrasts/causes edges, cross-link selectors (chapter/entity),
linked-node badges, and an "Add beats to board" import from the plot.
Plot beats feature set:
- Status/locking (draft/revised/locked) with a progress bar
- Beat templates (three-act, save-the-cat, seven-point, custom)
- Timeline route with search/chapter/character filters
- Entity cross-links (entityIds) on beats and board nodes
- getBoard added to the StorageAdapter contract (local + server) and
REST endpoints; loadBoard now restores persisted board state
Storage & server:
- PlotBeat type (status, entityIds) across core types, Dexie schema,
and server mapping/routes/migration (002_plot_beats.sql)
- SQLite-safe column names (beat_order, entity_ids)
- Server seed data for plot beats
UI: accent Button variant, Badge variants, plot/timeline/whiteboard
stylesheets. Tests: templates module, plot-beat store round-trip,
board getBoard. typecheck, lint, test, and build all green.
The entry point defined and exported start() but never called it, so
running 'node --import tsx src/index.ts' imported the module and exited
0 without ever calling app.listen. Add a top-level start().catch() so the
server binds and logs its listen addresses.