feat: API keys, per-tenant quotas, and per-key rate limits #137
No reviewers
Labels
No labels
area: api
area: auth
area: build
area: cache
area: ci
area: compare
area: model
area: provenance
area: rite
backport
blocked
breaking
confirmed
dependencies
duplicate
epic
invalid
needs-info
needs-triage
php
priority: high
priority: low
priority: medium
regression
type: chore
type: correction
type: docs
type: enhancement
type: feature
type: fix
type: perf
type: refactor
type: security
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Directorium/Api!137
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feature/21-api-keys-quotas"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Adds the metering layer (epic #21) behind a storage seam, disabled until a key store is configured — so the open service (and every existing test) is unchanged, and live MySQL wiring is a deploy step.
What's here
Auth\KeyStore(#22) — the one persistence seam, withInMemoryKeyStore(the tested double) andPdoKeyStore(MySQL,sql/schema.sql). Counters are aggregate — one upserted row per (tenant, month) and per (key, minute), never a row per request.Auth\KeyIssuer(#23) — issue / rotate / revoke. Onlysha256(secret)is stored; the plaintext is shown once.bin/api-key.phpis the maintainer CLI.Auth\AccessControl(#24/#25/#26) — authenticate viaAuthorization: BearerorX-API-Key, scope to the tenant, enforce the key's per-minute rate limit and the tenant's monthly quota, echoX-RateLimit-*.401 unauthenticated;429 rate_limited(withRetry-After) /429 quota_exceeded.GuardedHandlerwraps the calendar handlers; health + meta stay public.AccessControl(open by default viafromEnvironment()) and carries anApiException's headers onto the error response.Verification
composer checkgreen: phpcs, PHPStan[OK](52 source files), PHPUnit 88 tests / 303 assertions — covering the store, issue/rotate/revoke, 401 paths, valid-key grant + rate headers, and 429 rate/quota at both unit and kernel level.Scope notes
CI has no database, so the auth/quota/rate logic is proven against the in-memory store;
PdoKeyStoreis static-checked and integration-tested against a live MySQL at deploy (a maintainer step, alongside provisioningINTROIBO_DB_DSN). Admin rebuild/purge + AUP/terms endpoints are the next PR (epic #27).Refs #21 #22 #23 #24 #25 #26