Changelog
Set-once contact email
PATCH /v1/club/contacts/{id}accepts an optionalemail, settable once on a contact that has none; once present it cannot be changed or cleared. Previously the route accepted noemailat all.- Sending the address the contact already has is accepted as a no-op, so a read-modify-write client can echo it back.
- A different address on a contact that already has one answers
400 invalid_requestwithdetails: [{ field: "email", code: "already set" }]; an address another person on the platform already uses answers the same withcode: "already in use"; an explicitnullis malformed. POST /v1/club/contactsnow answers a duplicate email with400 invalid_requestnaming the field instead of500 internal_error:already in this clubfor the main email, andhouseholdMembers[i].draft.emailfor a household draft, withduplicate in requestwhen the call repeats an address.PATCH /v1/federation/people/{contactId}is unchanged: a federation registration requires an email, which cannot be corrected afterwards.
API reference request samples
- Request samples now show the signing headers honestly:
X-Sx-Key-Idis the one security scheme, andX-Sx-Timestamp,X-Sx-NonceandX-Sx-Signatureare required header parameters on every operation, with descriptions and examples. Previously all four headers showed the same placeholder secret. - OpenAPI gains
servers(partner-api.sportsx.aiandpartner-dev-api.sportsx.fun); write operations carry anIdempotency-Keyexample and contact create/update fields carry examples. - Documentation and contract-check changes only; API behaviour is unchanged.
Club OWNER-only scope grants
- Replaced the P0 “unsupported for every issuer” decision for
club.compliance.read_files,club.safety.read_sensitive,club.coaches.read,club.coaches.write, andclub.federations.readwith an exact-current-club OWNER-only grant rule. - Kept permission wildcard and role evidence separate: ADMIN, custom wildcard holders and owners of other clubs cannot grant these scopes.
- Applied one server-owned grant ceiling to the scope catalog, credential creation and scope update. Existing keys retain explicit scopes only; strict reduction remains available and rotation does not expand them.
P5 contract publication
- Published signed-only authentication; removed obsolete Bearer and runtime mock-demo guidance.
- Frozen the current inventory at 96 explicit controller operations: public
GET /healthplus 95 signed/v1operations on 85 path templates. - Added equal-route bilingual OpenAPI, source-ledger drift checks, missing-translation and missing-spec failures, and bilingual docs build gates.
- Documented workspace Redis limits, fail-closed idempotency, five signing webhook events, canonical reconciliation and current provisioning/worker limitations.
P6 standalone Partner worker
- Added explicit
PARTNER_ROLE=api|workerstartup with backward-compatibleapidefault and fail-fast unknown roles. - Moved webhook queue consumption and recovery out of every Academy mode into the health-only worker; retained the shared producer in Partner API and Academy.
- Added independent API/worker Kubernetes Deployments from the same bundle. Only the API has a Service/public route.
- Added isolated Postgres/Redis runtime checks for role routes, queue registry identity, consumer ownership and shutdown.