A community based topic aggregation platform built on atproto
at main 77 lines 4.2 kB view raw
1-- +goose Up 2-- Add API key authentication and OAuth credential storage for aggregators 3-- This enables aggregators to authenticate using API keys backed by OAuth sessions 4 5-- ============================================================================ 6-- Add API key columns to aggregators table 7-- ============================================================================ 8ALTER TABLE aggregators 9 -- API key identification (prefix for log correlation, hash for auth) 10 ADD COLUMN api_key_prefix VARCHAR(12), 11 ADD COLUMN api_key_hash VARCHAR(64) UNIQUE, 12 13 -- OAuth credentials (encrypted at application layer before storage) 14 -- SECURITY: These columns contain sensitive OAuth tokens 15 ADD COLUMN oauth_access_token TEXT, 16 ADD COLUMN oauth_refresh_token TEXT, 17 ADD COLUMN oauth_token_expires_at TIMESTAMPTZ, 18 19 -- OAuth session metadata for token refresh 20 ADD COLUMN oauth_pds_url TEXT, 21 ADD COLUMN oauth_auth_server_iss TEXT, 22 ADD COLUMN oauth_auth_server_token_endpoint TEXT, 23 24 -- DPoP keys and nonces for token refresh (multibase encoded) 25 -- SECURITY: Contains private key material 26 ADD COLUMN oauth_dpop_private_key_multibase TEXT, 27 ADD COLUMN oauth_dpop_authserver_nonce TEXT, 28 ADD COLUMN oauth_dpop_pds_nonce TEXT, 29 30 -- API key lifecycle timestamps 31 ADD COLUMN api_key_created_at TIMESTAMPTZ, 32 ADD COLUMN api_key_revoked_at TIMESTAMPTZ, 33 ADD COLUMN api_key_last_used_at TIMESTAMPTZ; 34 35-- Index for API key lookup during authentication 36-- Partial index excludes NULL values since not all aggregators have API keys 37CREATE INDEX idx_aggregators_api_key_hash 38 ON aggregators(api_key_hash) 39 WHERE api_key_hash IS NOT NULL; 40 41-- ============================================================================ 42-- Security comments on sensitive columns 43-- ============================================================================ 44COMMENT ON COLUMN aggregators.api_key_prefix IS 'First 12 characters of API key for identification in logs (not secret)'; 45COMMENT ON COLUMN aggregators.api_key_hash IS 'SHA-256 hash of full API key for authentication lookup'; 46COMMENT ON COLUMN aggregators.oauth_access_token IS 'SENSITIVE: Encrypted OAuth access token for PDS operations'; 47COMMENT ON COLUMN aggregators.oauth_refresh_token IS 'SENSITIVE: Encrypted OAuth refresh token for session renewal'; 48COMMENT ON COLUMN aggregators.oauth_token_expires_at IS 'When the OAuth access token expires (triggers refresh)'; 49COMMENT ON COLUMN aggregators.oauth_pds_url IS 'PDS URL for this aggregators OAuth session'; 50COMMENT ON COLUMN aggregators.oauth_auth_server_iss IS 'OAuth authorization server issuer URL'; 51COMMENT ON COLUMN aggregators.oauth_auth_server_token_endpoint IS 'OAuth token refresh endpoint URL'; 52COMMENT ON COLUMN aggregators.oauth_dpop_private_key_multibase IS 'SENSITIVE: DPoP private key in multibase format for token refresh'; 53COMMENT ON COLUMN aggregators.oauth_dpop_authserver_nonce IS 'Latest DPoP nonce from authorization server'; 54COMMENT ON COLUMN aggregators.oauth_dpop_pds_nonce IS 'Latest DPoP nonce from PDS'; 55COMMENT ON COLUMN aggregators.api_key_created_at IS 'When the API key was generated'; 56COMMENT ON COLUMN aggregators.api_key_revoked_at IS 'When the API key was revoked (NULL = active)'; 57COMMENT ON COLUMN aggregators.api_key_last_used_at IS 'Last successful authentication using this API key'; 58 59-- +goose Down 60-- Remove API key columns from aggregators table 61DROP INDEX IF EXISTS idx_aggregators_api_key_hash; 62 63ALTER TABLE aggregators 64 DROP COLUMN IF EXISTS api_key_prefix, 65 DROP COLUMN IF EXISTS api_key_hash, 66 DROP COLUMN IF EXISTS oauth_access_token, 67 DROP COLUMN IF EXISTS oauth_refresh_token, 68 DROP COLUMN IF EXISTS oauth_token_expires_at, 69 DROP COLUMN IF EXISTS oauth_pds_url, 70 DROP COLUMN IF EXISTS oauth_auth_server_iss, 71 DROP COLUMN IF EXISTS oauth_auth_server_token_endpoint, 72 DROP COLUMN IF EXISTS oauth_dpop_private_key_multibase, 73 DROP COLUMN IF EXISTS oauth_dpop_authserver_nonce, 74 DROP COLUMN IF EXISTS oauth_dpop_pds_nonce, 75 DROP COLUMN IF EXISTS api_key_created_at, 76 DROP COLUMN IF EXISTS api_key_revoked_at, 77 DROP COLUMN IF EXISTS api_key_last_used_at;