Skip to content

docs(openapi): document the 503 five more routes already answer - #1163

Merged
rmyndharis merged 1 commit into
mainfrom
docs/document-remaining-503-capable-routes
Aug 9, 2026
Merged

docs(openapi): document the 503 five more routes already answer#1163
rmyndharis merged 1 commit into
mainfrom
docs/document-remaining-503-capable-routes

Conversation

@rmyndharis

Copy link
Copy Markdown
Owner

What

Five routes answer 503 today and published only their success statuses. This adds the missing @ApiResponse declarations and regenerates the snapshot. No runtime behaviour changes — every 503 here was already reachable.

Route Declared before Answers 503 since
POST /sessions/{id}/groups/{groupId}/participants 200 0.14.5
DELETE /sessions/{id}/groups/{groupId}/participants 200 0.14.5
POST /sessions/{id}/groups/{groupId}/participants/promote 200 0.14.5
POST /sessions/{id}/groups/{groupId}/participants/demote 200 0.14.5
GET /sessions/{id}/labels/{labelId}/chats 200,400,501 0.14.0

CHANGELOG [0.14.5] already states the participant writes "now answer 503", so the changelog was right and the contract was the part left behind.

Why the previous pass missed them

#1149 derived its set from delegate methods containing a bounded call. These five fail that derivation in two different ways, which is worth recording so the next sweep does not repeat it:

The participant writes hide the bounded call one level down. addParticipants, removeParticipants, promoteParticipants and demoteParticipants each contain a single forwarding call and nothing else; the deadline lives inside the private runParticipantsUpdate they all delegate to. A derivation matching "method containing a bounded call" sees four methods containing none.

The label read has no request budget at all. Its 503 comes from an EngineTransportError thrown directly on the whatsapp-web.js side when the page connection dies mid-read. A sweep anchored on the deadline helper cannot see it by construction. It has been undocumented for five releases, with whatsapp-web-js.adapter.spec.ts asserting the behaviour that whole time.

Why the two descriptions differ

The participant 503 is the one status that separates "WhatsApp never answered" from the per-participant refusals a 200 already reports inside results — an unanswered query yields [], which the empty-results guard would otherwise turn into a 403, selling a dead transport as a permissions problem. All four share one constant so the four cannot drift apart.

The label route has no deadline, so reusing the request-budget sentence there would have documented a mechanism that route does not have. It gets wording about the page connection instead.

Test

The structural invariant in openapi-contract.spec.ts is keyed off the response schema rather than a list of paths, so a fifth participant route inherits it rather than slipping past the way these four did. It was checked in both directions: dropping the 503 from one route fails it, and renaming the schema fails the non-empty guard rather than passing vacuously.

Deliberately unchanged

Creating a group, creating a channel and the media send path stay unbounded and undeclared, for the reason CHANGELOG [0.14.5] gives — they are non-idempotent and the Go SDK retries POST on 503, so declaring it there would break the interlock.

Out of scope, noted for follow-up

  • The four participant routes can also answer 403 (EngineRefusedError, on a total refusal or an empty result) and do not declare it.
  • GET /labels/{labelId}/chats can answer 404 (LabelNotFoundError, unknown label) and does not declare it.
  • The MCP tool surface reaches the same service methods over HTTP but carries no @ApiResponse surface at all.
  • openapi.json is copied into the docs repository; that snapshot needs refreshing, and the API-conventions and troubleshooting pages can now claim the 503 for these routes.

Verification

openapi:check, lint, format:check, tsc --noEmit, build, dashboard build all exit 0; npm test passes 5119 tests across 300 suites. openapi.json was regenerated with npm run openapi:export, never edited by hand.

Refs #1149

The four group participant writes and the label chat read answer 503 today but
published only their success statuses, so a client generated from the contract
had no branch for a failure the gateway was already returning.

Both are blind spots of the derivation that documented the other thirty rather
than new behaviour, and they fail it in different ways:

  - The participant writes delegate to a PRIVATE helper. addParticipants,
    removeParticipants, promoteParticipants and demoteParticipants each contain
    a single forwarding call; the bounded call lives one level deeper, inside
    runParticipantsUpdate. A derivation matching "delegate method containing a
    bounded call" sees four methods containing none. Bounded since 0.14.5.

  - The label chat read has no request budget at all. Its 503 comes from a
    direct EngineTransportError on the whatsapp-web.js side, thrown when the
    page connection dies mid-read, so a sweep anchored on the deadline helper
    cannot see it. It has answered 503 since 0.14.0 - five releases undocumented,
    with an adapter spec asserting it that whole time.

The wording differs accordingly. The participant 503 is the one status that
separates "WhatsApp never answered" from the per-participant refusals a 200
reports inside `results`, and it is shared by all four through one constant.
Reusing the request-budget sentence on the label route would have documented a
deadline that route does not have.

A structural test keys the invariant off the response schema rather than a list
of paths, so a fifth participant route inherits it instead of slipping past the
same way these four did. It fails if the 503 is dropped, and its non-empty guard
fails if the schema is renamed out from under the selector.

Deliberately unchanged: creating a group, creating a channel and the media send
path stay unbounded and undeclared, for the reason CHANGELOG [0.14.5] gives -
they are non-idempotent and the Go SDK retries POST on 503.

No runtime behaviour changes; every 503 here was already reachable.
@rmyndharis
rmyndharis merged commit 4d7fc44 into main Aug 9, 2026
16 checks passed
@rmyndharis
rmyndharis deleted the docs/document-remaining-503-capable-routes branch August 9, 2026 00:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant