Repository navigation
v0.4.0 — per-API-key capabilities
Headline: API keys can now be granted specific write capabilities (e.g. skills:write, recipes:write) without granting full admin powers. CI servers and teammates can publish skills/recipes without holding admin keys.
Server-side:
- New
api_keys.capabilitiesJSON column (migration 018) - New
store.APIKey.HasCapability()+store.SupportedCapabilitiescanonical list requireCapabilitymiddleware on skill upload + recipe POST/PATCH paths- 403 response now names the missing capability so CI operators know what to grant
- Admin keys retain all powers (additive model, capabilities are an opt-in extra)
Phase 2 of the design:
- POST /api/skills/{slug}/versions/{version} — was admin-only, now
skills:write - POST /api/recipes — now
recipes:write - PATCH /api/recipes/{slug} — now
recipes:write
Still admin-only (TODO in code):
- Skill version yank (DELETE) — needs uploaded_by_api_key_id ownership tracking
- Recipe DELETE — same
- Web UI for issuing capability-bearing keys (today: direct DB INSERT)
arc-sync unchanged from v0.3.2 — version stamp bumped to v0.4.0 for release-line consistency. Self-update on existing v0.3.x clients pulls v0.4.0 cleanly.
Compatibility: clients running on relay v0.3.x continue working. Migrating from v0.3.x → v0.4.0 is a no-op deploy (migration runs automatically).
Issuing a capability-bearing key (until UI ships):
-- Find the user the key should belong to
SELECT id, username FROM users WHERE username = 'ci-publisher';
-- Update an existing key, or create one via the existing UI then update
UPDATE api_keys SET capabilities = '["skills:write","recipes:write"]' WHERE id = '<key_id>';Test results: 805 passing in 30 packages.