Renames src/fabledassistant -> src/scribe and all imports, plus the
default DB name and DB user/password (fabled -> scribe) in config +
compose. 952 refs / 154 files. Reverses the old 'internal name stays
fabledassistant' convention.
Code-only: live databases are still physically named 'fabledassistant'.
Deployed environments must set POSTGRES_DB / POSTGRES_USER (or rename the
DB) since the defaults now resolve to 'scribe'. Repo (FabledScribe), git
host (fabledsword), MCP (fabled-git) and the image name (fabledscribe)
are intentionally unchanged.
ruff check src/ clean locally; CI (typecheck + pytest) is the gate.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CI fix for aef5009: test_resolve_bearer_none_for_invalid referenced
resolve_bearer but the import lived inside an earlier test only. Hoist it
to the module import. Production code unaffected (1 failed / 284 passed).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
Thin parser over the existing api_keys lookup. Strips the Bearer
prefix, validates the token via services/api_keys.lookup_key (which
already filters revoked keys and updates last_used_at), and returns
the user_id for the in-flight MCP request.
Tests follow the existing mock-async_session pattern in
test_api_keys.py rather than introducing a real DB fixture.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>