WS8 PR C: firm API keys, admin area, member roles
What
- Firm-level (shared) provider API keys managed by admins, layered into
key resolution as user > firm > env. Orgless/unmigrated deployments are
unchanged.
- New /admin area (routes/admin.ts) behind requireAuth + requireAdmin:
GET/PUT firm-keys, GET members, PATCH member role (MFA-gated mutations).
- Admin "Firm settings" screen: members (role badges, promote/demote with
confirm + MFA), firm API keys (per-provider rows), read-only Policies
preview. Sidebar gains a "Firm admin" group, visible only to admins.
Why
- First user-visible firm-administration surface for the pilot, building on
the PR A (#34) organisation foundation. Lets a firm provision one shared
set of provider keys for all members while a member's own key still wins.
How
- Shared AES-256-GCM crypto extracted to lib/apiKeyCrypto.ts (scheme
unchanged); userApiKeys.ts keeps thin wrappers. Firm-key CRUD in
organisationApiKeys.ts. Member listing + setMemberRole (org-scoped writes,
last-admin guard) in organisations.ts. No migration - organisation_api_keys
already exists from PR A.
- account/api-keys surfaces the new "firm" source ("Provided by your firm").
Tested
- Backend: tsc clean; vitest 199/199 (rewrote userApiKeys precedence matrix;
new organisationApiKeys, organisationMembers, routes/admin tests covering
authz 403, last-admin 409, cross-firm scoping 404).
- Frontend: tsc clean; eslint src 34 errors/77 warnings - identical to main
baseline (changed files add zero).
- evals:smoke from the main checkout: 4/4 pass.
- Independent code review: no blockers.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| Repository | Sloth-ninja/JessicaOSS |
|---|---|
| Author | sloth-ninja <ezanahaddis@gmail.com> |
| Authored | |
| Parents | d52ffc01 |
| Stats | 16 files changed , +2011 , -102 |
| Part of | WS8 PR C: firm API keys, admin area, member roles |
Capture this commit into my fork
Download a Markdown prompt that tells Claude how to port this
exact commit into your working tree. Run it via
claude -p < capture-commit-9fba26ab.md
from inside the repo you want the change in.