-- ============ MCP Tokens ============ CREATE TABLE mcp_tokens ( id UUID PRIMARY KEY, token_hash BYTEA UNIQUE NOT NULL, -- SHA-256(opaque token) user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, name TEXT NOT NULL, issuer TEXT NOT NULL, scope JSONB NOT NULL DEFAULT '{}'::jsonb, -- {"tools": [...] | null, "project_ids": [...] | null} acp_session_id UUID REFERENCES acp_sessions(id) ON DELETE CASCADE, -- 仅 issuer='system' 填 expires_at TIMESTAMPTZ, -- NULL = 永不过期 last_used_at TIMESTAMPTZ, revoked_at TIMESTAMPTZ, created_by UUID NOT NULL REFERENCES users(id), created_at TIMESTAMPTZ NOT NULL DEFAULT now(), CONSTRAINT mcp_tokens_issuer_check CHECK (issuer IN ('system','admin')), CONSTRAINT mcp_tokens_system_session_required CHECK ((issuer='system' AND acp_session_id IS NOT NULL) OR (issuer='admin' AND acp_session_id IS NULL)) ); CREATE INDEX idx_mcp_tokens_user_active ON mcp_tokens(user_id) WHERE revoked_at IS NULL; CREATE INDEX idx_mcp_tokens_session ON mcp_tokens(acp_session_id) WHERE acp_session_id IS NOT NULL; CREATE INDEX idx_mcp_tokens_expires ON mcp_tokens(expires_at) WHERE revoked_at IS NULL;