GET /openapi/v1/workspaces lists tenants the bearer's account is a
member of. GET /openapi/v1/workspaces/<id> returns one workspace
detail, member-gated (404 on non-member, never 403, so workspace IDs
don't leak across tenants).
Bearer-authed via @validate_bearer(accept=ACCEPT_USER_ANY). External
SSO bearers (no account_id) get an empty list / 404 — same posture as
GET /openapi/v1/account.
Cookie-authed /console/api/workspaces stays in console for the
dashboard SPA — different consumer, different auth model. No legacy
/v1/ remount this phase.
Plan: docs/superpowers/plans/2026-04-26-openapi-migration.md (in difyctl repo).