-- Users CREATE TABLE IF NOT EXISTS users ( public_key TEXT PRIMARY KEY, inviter TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Challenges (login nonces) CREATE TABLE IF NOT EXISTS challenges ( nonce TEXT PRIMARY KEY, public_key TEXT NOT NULL, expires_at TIMESTAMPTZ NOT NULL, used BOOLEAN NOT NULL DEFAULT FALSE ); -- Sessions CREATE TABLE IF NOT EXISTS sessions ( token TEXT PRIMARY KEY, public_key TEXT NOT NULL, expires_at TIMESTAMPTZ NOT NULL ); -- Invitations CREATE TABLE IF NOT EXISTS invitations ( jti TEXT PRIMARY KEY, inviter_public_key TEXT NOT NULL, invitee_public_key TEXT, expires_at TIMESTAMPTZ NOT NULL, max_uses INT NOT NULL, used_count INT NOT NULL DEFAULT 0 ); -- Collections CREATE TABLE IF NOT EXISTS collections ( id TEXT PRIMARY KEY, owner_key TEXT NOT NULL, name TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Features (geometry and properties as JSONB) CREATE TABLE IF NOT EXISTS features ( id TEXT PRIMARY KEY, collection_id TEXT NOT NULL REFERENCES collections(id) ON DELETE CASCADE, owner_key TEXT NOT NULL, type TEXT NOT NULL DEFAULT 'Feature', geometry JSONB NOT NULL, properties JSONB, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_collections_owner ON collections(owner_key); CREATE INDEX IF NOT EXISTS idx_features_collection ON features(collection_id); CREATE INDEX IF NOT EXISTS idx_features_owner ON features(owner_key); CREATE INDEX IF NOT EXISTS idx_challenges_expires ON challenges(expires_at); CREATE INDEX IF NOT EXISTS idx_sessions_expires ON sessions(expires_at);