mirror of
https://github.com/Such-Software/smirk-backend-core.git
synced 2026-10-17 07:21:32 +02:00
The admin authorization data model. The server stores only public keys; an admin is authorized by presence in admin_keys, and each row carries an HMAC (ADMIN_KEY_INTEGRITY_SECRET, separate from DATABASE_URL) over id|pubkey|scope|created_at|activated_at|revoked_at. Because the MAC covers the revocation/activation state, a DB-write attacker who clears revoked_at (un-revoke) or revives a key produces a mismatch the guard rejects — the MAC proves a pubkey is *currently* authorized, not merely once. - migration 20260625000002: admin_keys (partial unique index = one active row per pubkey; soft revoke keeps history) + admin_sessions (separate table/secret from user sessions; cascade-on-key-delete). - core::crypto::admin_mac: compute/verify over a JSON-canonical field set, timestamps as microsecond epochs; constant-time compare; KATs bind revoked/activated state. - db::admin_keys: create / get_active (re-verifies MAC, fail-closed + logs tamper) / list / count_live / activate / revoke. Every covered-field write recomputes the MAC centrally; timestamps truncated to microseconds so the signed value round-trips; revoke/activate are FOR UPDATE transactions. - 5 L1 tests incl. the load-bearing raw-SQL un-revoke -> MAC mismatch -> rejected.