⚠️ BREAKING CHANGE — operator action required before upgrade
Legacy pre-F032 DCR OAuth client rows (Claude.ai / ChatGPT / Cursor / Cline connections made before 0.1.6) are auto-purged during the upgrade migration. Any live AI-host session bound to a legacy DCR row will disconnect on the next request; affected users must re-run the OAuth authorize flow from their AI host to reconnect. All post-F032 DCR registrations are per-server and unaffected.
Consider before upgrading:
- Snapshot
wp_acrossai_mcp_oauth_{clients,tokens,auth_codes}in case rollback is needed - Notify users with active AI-host connections that they will need to re-authorize once after upgrade
What ships
F032 core — SECURITY FIX
Closes a cross-server privilege-escalation gap where an admin on Server A's Connectors tab could revoke or delete Server B's OAuth clients and tokens by modifying the client_id in the outbound REST body.
- Adds
server_id BIGINT UNSIGNED NOT NULLfirst-class column to 3 OAuth tables (oauth_clients,oauth_tokens,oauth_auth_codes) via D28 3-part BerlinDB$upgradescontract - Replaces
UNIQUE(client_id)with compositeUNIQUE(client_id, server_id)onoauth_clients— same DCR connector can now be registered on multiple servers as independent rows - Every mutating REST endpoint requires + validates
server_idin the body → mismatch returns403 acrossai_mcp_oauth_cross_serverAND fires 4-argdo_action( 'acrossai_mcp_oauth_cross_server_attempted', $client_id, $server_id_requested, $user_id, $timestamp )(owning server_id INTENTIONALLY omitted per SEC-032-001) - DCR endpoint: RFC 8707
resourceorigin verification againsthome_url()+ 503 race guard against pre-migration deploy window - Legacy DCR rows auto-purged during upgrade with orphan-server guard (SEC-032-003) — aggregate
acrossai_mcp_oauth_legacy_dcr_purgedaction fires once per run UserLifecycle::on_user_deletedstays site-wide per FR-042 (regression-tested)
F032 extended scope
- New BerlinDB module
wp_acrossai_mcp_connector_approved_users— promotes admin-approval state from serialized wp_options to first-class relational table withUNIQUE(server_id, connector_slug, user_id)presence constraint - New "Approved Users" admin panel between Connections and Settings when
require_admin_approval = true— Pending + Approved sections with Approve/Deny/Revoke actions - New revoke-approval → token-revoke cascade wired via
acrossai_mcp_connector_user_approval_revokedaction +acrossai_mcp_connector_revoke_tokens_on_approval_revokedopt-out filter - New "Revoke from all servers" nuclear button — deliberate D31 carve-out with mutually-exclusive observability action so forensic streams stay clean
- New annotated token counts in Connections panel:
"2 (1 access · 1 refresh)"replaces opaque totals - New AC connection-time gate at OAuth authorize + CLI device-grant + Application Password generation via shared
AcrossAI_MCP_Access_Control::user_has_server_access()helper — closes UX gap where denied users saw "connected" then silent 403 on every tool call - Enriched 403 at AC tool-call boundary now includes
server_slug+user_rolesfor operator debugging - FR-051 admin bypass: users with
manage_optionsbypassrequire_admin_approvalpending queue + auto-added to approved list withapproved_by = self - SEC-L1 remediation: distinct
acrossai_mcp_connector_admin_self_bypassedobservability action differentiates self-service bypass rows from explicit-reviewer approval rows
Governance
- 2 security-review passes (plan v1 HIGH → v2 INFORMATIONAL after 4 SEC remediations) + tasks review (MODERATE) + staged security review (INFORMATIONAL with SEC-L1 remediated inline)
- Architecture review MEDIUM V1 refactor + HIGH V2 DoD gates — V1 fixed via
enumerate_connector_clients()helper extraction - All F021 governance gates pass (T118b/c/d layering, T119 crypto column widths, T120 raw-secret generation)
- PHPCS strict + PHPStan L8 clean on all F032-touched files
- All 8 required CI checks green on merge (WPCS, PHPStan, PHPUnit pure + integration, ESLint, PHP 8.1+ compat, Package Hierarchy, F021 grep gates)
Durable memory codified
- D31 / DEC-F032-OAUTH-SERVER-ID-FIRST-CLASS
- D32 / DEC-CONNECTOR-APPROVAL-REVOKE-CASCADE
- D33 / DEC-OAUTH-AUTHORIZE-AC-GATE
- D34 / DEC-CROSS-SERVER-NUCLEAR-REVOKE-CARVE-OUT
- B37 / B-CROSS-SERVER-BYPASS-VIA-CLIENT-ID-ONLY (grep-gate)
- B38 / B-ADMIN-SELF-APPROVAL-AUDIT-TRAIL-AMBIGUITY (grep-gate)
- B39 / B-DYNAMIC-IN-CLAUSE-TRIGGERS-PHPCS-FALSE-POSITIVE (grep-gate)
Ships unconditionally per Q2 clarification
No feature flag. Rollback is via composer package downgrade if operationally required.