POC Websocket types - #601
C0D3-M4513R wants to merge 20 commits into
Conversation
742b44e to
91b5283
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical and moderate schema issues remain in the WebSocket unions, discriminator modeling, and OpenAPI compatibility.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
This proof-of-concept adds OpenAPI schemas for WebSocket messages, notifications, and related payloads to support client deserialization.
Changes:
- Adds wrapper and non-wrapper WebSocket event schemas.
- Adds notification, content-refresh, user, friend, group, badge, and queue payload schemas.
- Registers the schemas in the components index.
File summaries
| File | Review status |
|---|---|
openapi/components/schemas/WebsocketWrapperUserUpdate.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperUserLocation.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperUserBadgeUnassigned.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperUserBadgeAssigned.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperResponseNotification.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperNotificationV2Update.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperNotificationV2Delete.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperNotificationV2.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperNotification.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperInstanceQueueReady.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperInstanceQueueJoined.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperGroupRoleUpdated.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperGroupMemberUpdated.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperGroupLeft.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperGroupJoined.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperFriendUpdate.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperFriendOnline.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperFriendOffline.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperFriendLocation.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperFriendDelete.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperFriendAdd.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperFriendActive.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketWrapperContentRefresh.yaml |
Moderate finding recorded |
openapi/components/schemas/WebsocketUserUpdate.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketUserLocation.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketUserBadgeUnassigned.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketUserBadgeAssigned.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketSeeNotification.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketResponseNotification.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketNotificationV2Update.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketNotificationV2Delete.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketNotificationV2.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketNotification.yaml |
Critical and moderate findings recorded |
openapi/components/schemas/WebsocketMessage.yaml |
Critical and nit findings recorded |
openapi/components/schemas/WebsocketInstanceQueueReady.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketInstanceQueueJoined.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketHideNotification.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketGroupRoleUpdated.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketGroupMemberUpdated.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketGroupLeft.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketGroupJoined.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketFriendUpdate.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketFriendOnline.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketFriendOffline.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketFriendLocation.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketFriendDelete.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketFriendAdd.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketFriendActive.yaml |
Reviewed; no final finding recorded |
openapi/components/schemas/WebsocketContentRefresh.yaml |
Nit recorded |
openapi/components/schemas/WebsocketClearNotification.yaml |
Critical finding recorded |
openapi/components/schemas/_index.yaml |
Nit recorded |
Review details
Suppressed comments (7)
openapi/components/schemas/WebsocketMessage.yaml:15
- These alternatives include
WebsocketWrapperNotification.yamland other wrapper files that are currently empty in this checkout. AddingWebsocketMessageto_index.yamlmakes the bundler resolve those references; empty targets are not usable Schema Objects (or become unconstrained branches), so the bundle will fail or the union will be ambiguous. Define each wrapper before referencing it, or remove unimplemented variants.
when: jsonschema
then:
contentSchema:
oneOf:
- $ref: ./WebsocketNotification.yaml
openapi/components/schemas/WebsocketMessage.yaml:14
- This publishes a 27-variant websocket union without a websocket workflow or capture in
test/arazzo.yaml. Per the repository's evidence rule, an uncaptured property, type, or variant is a missing test rather than a schema fact; add workflows that record these frames before indexing the union, otherwise generated clients will be constrained by guessed variants.
x-if:
when: jsonschema
then:
contentSchema:
oneOf:
openapi/components/schemas/WebsocketMessage.yaml:41
- This discriminator maps on
type, butWebsocketSeeNotification,WebsocketResponseNotification, andWebsocketClearNotificationdo not define that property. These branches therefore cannot be selected by the discriminator even after the conditional is placed at the intended schema level; add the actual wrapper type to each variant or map only schemas that carry it.
- $ref: ./WebsocketGroupJoined.yaml
- $ref: ./WebsocketGroupLeft.yaml
- $ref: ./WebsocketGroupMemberUpdated.yaml
- $ref: ./WebsocketGroupRoleUpdated.yaml
discriminator:
openapi/components/schemas/WebsocketMessage.yaml:13
WebsocketSeeNotification.yamlandWebsocketResponseNotification.yamlcurrently define the same three required string properties. Any content object matching one therefore matches both branches, so thisoneOfcannot distinguish the two message types. Add an evidence-backed schema distinction or discriminate at the enclosing message instead.
then:
contentSchema:
openapi/components/schemas/WebsocketMessage.yaml:14
- Even after fixing the indentation, these branches are
WebsocketWrapper...objects; for example,WebsocketWrapperContentRefreshalready requires its owntypeandcontent. Placing that union under the outer message'scontentmodels an extra nested wrapper, so make the message itself the union (or make the branches content-only) and discriminate at the field that actually carries the event type.
x-if:
when: jsonschema
then:
contentSchema:
oneOf:
openapi/components/schemas/WebsocketNotification.yaml:12
- The websocket detail union omits
NotificationEmpty, even though the existingSentNotificationunion models{}with that schema andNotificationTypeincludes types such asfriendRequestandmessagethat do not have a listed detail shape. Those valid empty-detail cases are left without a branch. Add the existing empty-detail schema and make the other branches mutually exclusive, or explicitly constrain this websocket model to the covered notification types.
oneOf:
openapi/components/schemas/_index.yaml:14
- These newly published WebSocket schemas add properties, required entries, enum values, and examples without any Arazzo workflow/capture covering WebSocket frames. Add workflows that capture the relevant message states before publishing these branches; otherwise the schema is inferred rather than evidence-backed.
WebsocketMessage:
$ref: ./WebsocketMessage.yaml
WebsocketNotification:
$ref: ./WebsocketNotification.yaml
- Files reviewed: 7/28 changed files
- Comments generated: 5
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| oneOf: | ||
| - $ref: ./NotificationDetailBoop.yaml | ||
| - $ref: ./NotificationDetailInvite.yaml | ||
| - $ref: ./NotificationDetailInviteResponse.yaml | ||
| - $ref: ./NotificationDetailRequestInvite.yaml |
| discriminator: | ||
| propertyName: type | ||
| mapping: | ||
| boop: ./NotificationDetailBoop.yaml | ||
| invite: ./NotificationDetailInvite.yaml |
09c9cf1 to
5b4cd87
Compare
5b4cd87 to
87e2c20
Compare
commit: |
80b23d2 to
051f92a
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical schema, discriminator, compatibility, and component-preservation issues block approval.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (4)
openapi/components/schemas/Notification.yaml:31
- These discriminator keys do not match the repository's
NotificationTypevalues (inviteResponse,requestInvite,requestInviteResponse,votetokickinNotificationType.yaml:4-11); the mapping uses hyphenated spellings instead. Even after fixing the discriminator placement, those notification variants will not resolve to a branch. Use the actual enum values as mapping keys.
invite-response: ./NotificationDetailInviteResponse.yaml
request-invite: ./NotificationDetailRequestInvite.yaml
request-invite-response: ./NotificationDetailRequestInviteResponse.yaml
vote-to-kick: ./NotificationDetailVoteToKick.yaml
openapi/components/schemas/WebsocketMessage.yaml:7
- No Arazzo workflow or captured response accompanies these new WebSocket branches, while this repository derives schema properties, enum values, and required entries from traffic. As written, this publishes guessed shapes (the TODOs in the new schemas reinforce that); add capture-backed workflow coverage and derive the union from it before adding these schemas.
oneOf:
- $ref: ./WebsocketMessageNormal.yaml
- $ref: ./WebsocketMessageDoubleJson.yaml
openapi/components/schemas/WebsocketNotification.yaml:19
- These
oneOfbranches are not mutually exclusive: the issue's invite payload hasworldIdandworldNamebut notype, andNotificationDetailBoophas no required properties, so it also accepts that object. TheoneOftherefore matches both Boop and Invite and rejects the notification instead of fixing deserialization. Make the branches mutually exclusive using capture-backed requirements, or use a non-oneOfrepresentation if the wire payload has no discriminator.
oneOf:
- $ref: ./NotificationDetailBoop.yaml
- $ref: ./NotificationDetailInvite.yaml
- $ref: ./NotificationDetailInviteResponse.yaml
- $ref: ./NotificationDetailRequestInvite.yaml
- $ref: ./NotificationDetailRequestInviteResponse.yaml
- $ref: ./NotificationDetailVoteToKick.yaml
discriminator:
openapi/components/schemas/WebsocketNotification.yaml:27
- These discriminator keys do not match the repository's
NotificationTypevalues (inviteResponse,requestInvite,requestInviteResponse,votetokickinNotificationType.yaml:4-11); the mapping uses hyphenated spellings instead. Even after fixing the discriminator placement, those notification variants will not resolve to a branch. Use the actual enum values as mapping keys.
invite-response: ./NotificationDetailInviteResponse.yaml
request-invite: ./NotificationDetailRequestInvite.yaml
request-invite-response: ./NotificationDetailRequestInviteResponse.yaml
vote-to-kick: ./NotificationDetailVoteToKick.yaml
- Files reviewed: 33/33 changed files
- Comments generated: 19
- Review effort level: Lite
| discriminator: | ||
| propertyName: type | ||
| mapping: | ||
| boop: ./NotificationDetailBoop.yaml | ||
| invite: ./NotificationDetailInvite.yaml |
| - notification | ||
| - response-notification | ||
| - notification-v2 | ||
| - notification-v2-update | ||
| - notification-v2-delete |
|
This approach does not work for actually deserializing the double-json encoded json, sadly. Also the discriminator mappings do not work (at least in rust). If possible I'd like someone more skilled at Openapi spec to look at this. |
Closes: #598
Please note: This bumps the Openapi Spec version to 3.1, which causes some issues with some language generators!