The names were free-standing strings, so renaming a field on the response
schema would leave this list stale and quietly downgrade the error message to
the generic "unrecognized key". `satisfies` makes that a build failure.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Same change as the create body: the server-managed fields are no longer
advertised as writable in the generated spec, and the error map keeps the
specific message when one is sent.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The generated request spec listed `id`, `active`, `createdAt` and the other
server-managed fields as ordinary properties with empty schemas, because the
generator cannot express a "must be absent" check. Alongside
`additionalProperties: false`, the published contract positively invited callers
to send fields the server always rejects, and an SDK generated from it would
expose them as settable. The hand-written spec marked them `readOnly`.
They are now left out of the request shape, so the spec describes only what a
caller may send. The strict object rejects them as unrecognised keys, and an
error map keeps the specific message rather than letting a read-only field look
like a typo:
{ "id": "abc" } -> 'id' is a read-only field and cannot be set
{ "nam": "oops" } -> Unrecognized key(s) in object: 'nam'
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both comments described what the code does, which the code already showed. They
now record the reason a reviewer cannot see: Zod strips unknown keys where the
hand-written spec rejected them, and `/discover` can only read request bodies
out of that spec, which a decorator route has no entry in.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`workflowNodeGroup.yml` specified the structure: `id`, `name` and `nodeIds`
required, an optional `description` capped at 155 characters, and no other keys.
The DTO only checked that `nodeGroups` was an array, so four things the old API
rejected were being accepted:
nodeGroups: [{}] missing required fields
nodeGroups: [1, 2, 3] not objects
nodeGroups: [{ ...valid, bogus: 1 }] unknown key
nodeGroups: [{ ...valid, description: 156 }] over the length cap
Declared in the public DTO rather than reusing the internal
`workflowNodeGroupsSchema`, so a change to the internal request shape cannot
silently move the public contract.
The cap stays a literal 155 rather than `GROUP_DESCRIPTION_MAX_LENGTH` (145):
the engine truncates to that value instead of rejecting, so borrowing it would
start rejecting requests the old API accepted.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`UpdateWorkflowPublicDto` reuses the shared write shape from the create DTO, so
both bodies accept and reject the same fields; `projectId` is create-only and is
rejected here, matching the old `workflow.yml`.
`UpdateWorkflowQueryDto` carries `publishIfActive`, a documented query parameter
added in #35813. `WorkflowPublishBlockedErrorPublicDto` describes the 409 body.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Mirrors the hand-written `workflowCreate.yml` and `workflowSettings.yml` that
express-openapi-validator enforced, so the migrated endpoint accepts and rejects
exactly what it did before:
- unknown top-level keys are rejected, via a new optional `{ strict: true }` on
`Z.class` (default behaviour is unchanged for every other DTO)
- all 17 documented settings are typed, with their enums, and unknown settings
are rejected
- server-managed fields such as `id` and `active` are rejected with a read-only
error rather than silently ignored
- `binaryMode` and `credentialResolverId` are accepted, because the old spec
listed them; the controller strips them afterwards
`nodes`, `connections`, `staticData` and `pinData` stay shape-only checks. Their
contents are node-type specific and only the workflow engine can validate them,
which is also what the old spec did.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>