controllers/common/errors.py is consumed by other controllers; keep it
untouched and declare the openapi-surface error as an OpenApiError
subclass. Wire output is identical.
Review follow-ups:
- finalize() now falls back to a minimal status-derived body instead of
letting a ValidationError escape the framework error handler when an
already-rewritten e.data carries malformed canonical details
- document that a pre-built e.response bypasses the body formatter
- note the promote-to-libs seam for transport-generic codes in the module
docstring
- CLI: skip the loc prefix when a server error detail has an empty loc
Replaces the _quota_error/.response hack in workspaces.py with two
throwable OpenApiError subclasses (MemberLimitExceeded,
MemberLicenseExceeded) so all 403 quota responses flow through
OpenApiErrorFormatter rather than bypassing it via the early-return
in external_api.py. Wire codes rename to member_limit_exceeded and
member_license_exceeded.