Context
backend/src/auth/apiKey.ts stores apiKey as single global API_KEY env var and checks req.headers['x-api-key'] === API_KEY without tenant scoping.
Why this is a gap
Compromised key works for all tenants and cannot be rotated per tenant without downtime; also no expiry or last-used tracking for audit.
Acceptance Criteria
Context
backend/src/auth/apiKey.tsstoresapiKeyas single globalAPI_KEYenv var and checksreq.headers['x-api-key'] === API_KEYwithout tenant scoping.Why this is a gap
Compromised key works for all tenants and cannot be rotated per tenant without downtime; also no expiry or last-used tracking for audit.
Acceptance Criteria
apiKeypertenantIdinapiKeytable withhashedKey,scopes[],expiresAt,lastUsedAttenantIdfrom path/query and validatesscopesincludes required scope for routeAPI_KEY_EXPIREDorSCOPE_INSUFFICIENTwithWWW-Authenticateheader