Files
FabledScribe/tests
bvandeusen aef5009fc2
CI & Build / Python lint (push) Successful in 3s
CI & Build / Python tests (push) Failing after 24s
CI & Build / TypeScript typecheck (push) Successful in 42s
CI & Build / Build & push image (push) Has been skipped
fix(contract-drift): MCP read-only scope, shared-note writes, event TZ
Drift-audit Group 5 (high-severity contract drift):

- MCP read-only keys could call every write tool: the Bearer resolver
  discarded api_key.scope and dispatch had no gate. Add resolve_bearer()
  (returns user_id + scope) and a scope gate in the /mcp ASGI wrapper that
  buffers the JSON-RPC body and rejects tools/call for any tool outside a
  read all-list when scope=='read' (default-deny for unknown/new tools).
- Shared project notes/tasks panel was empty for non-owners: get_project_notes_route
  now queries notes/milestones with the project OWNER's uid (mirrors the
  already-fixed milestones route).
- Shared editors couldn't save/delete shared NOTES (tasks worked): the three
  notes write routes now resolve via get_note_for_user, gate on can_write_note,
  and write as the owner — matching the tasks routes.
- Event timezone drift: naive datetimes from the MCP date+time split are now
  localized to the user's tz at a single canonical service point (create_event
  /update_event), so MCP- and UI-created events agree. tz-aware inputs
  (REST/CalDAV) pass through untouched.
- create_note validates status/priority (TaskStatus/TaskPriority), closing the
  MCP create_task path that let out-of-enum values persist (no DB CHECK).

Tests cover resolve_bearer scope + the write-tool classifier.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 19:02:19 -04:00
..