Blame

836ff0 Claude (MCP) 2026-03-13 19:41:59
[mcp] Add P2-3 ACL enforcement summary
1
---
2
category: reference
3
tags:
4
- phase-2
5
- acl
6
- middleware
7
last_updated: 2026-03-13
8
---
9
10
# P2-3: ACL Enforcement Middleware
11
12
**Branch:** `feat/P2-3-acl-enforcement` (from `phase-2`)
13
**Status:** Complete — 21/21 tests passing
14
15
## Deliverables
16
17
### `app/auth/permissions.py`
18
- String constants: `READ`, `WRITE`, `UPLOAD`, `ADMIN`
19
- `ROLE_PERMISSIONS` dict mapping owner/editor/viewer to permission tuples
20
- `permissions_for_role(role)` — returns tuple or raises `ValueError`
21
- `format_permission_header(permissions)` — comma-separated string
22
23
### `app/auth/acl.py`
24
- `AclEnforcer` class with constructor injection (`acl_model`, `wiki_model`)
25
- `check_access(user_id, wiki_id)` — looks up ACL entry, returns `{role, permissions}` or raises `AuthError(403)`
26
- `check_public_access(wiki_id)` — parses `owner_id:wiki_slug`, checks `is_public` flag, returns READ or raises
27
- `check_bearer_token(token)` — delegates to `WikiModel.scan_by_token()`, returns editor-level permissions or raises `AuthError(401)`
28
29
### `app/auth/headers.py`
30
- `build_proxy_headers(email, name, permissions)` — returns dict with `x-otterwiki-name`, `x-otterwiki-email`, `x-otterwiki-permissions`
31
32
### `app/models/wiki.py` (modified)
33
- Added `scan_by_token(plaintext_token)` — scans all wikis with `mcp_token_hash`, checks each with `bcrypt.checkpw()`, handles pagination
34
- Added `bcrypt` and `Attr` imports
35
36
### `tests/test_acl.py`
37
- 21 tests using moto for DynamoDB mocking
38
- Covers: role mapping (4), format_permission_header (4), check_access (4), check_public_access (3), check_bearer_token (3), build_proxy_headers (3)
39
40
## Design Decisions
41
- Bearer token validation scans all wikis then bcrypt-checks each (bcrypt salts are non-deterministic)
42
- `wiki_id` format: `{owner_id}:{wiki_slug}` — parsed by `_parse_wiki_id()` helper
43
- Token-authenticated requests get editor-level permissions (READ, WRITE, UPLOAD)
44
- No new dependencies beyond `bcrypt` (already needed for token hashing)