Skip to content

Hygiene session 0: DELETE returns 204 (breaking) + origin-strategy Hydra cleanups - #1236

Draft
tomcrane wants to merge 10 commits into
developfrom
hygiene/session-0
Draft

Hygiene session 0: DELETE returns 204 (breaking) + origin-strategy Hydra cleanups#1236
tomcrane wants to merge 10 commits into
developfrom
hygiene/session-0

Conversation

@tomcrane

@tomcrane tomcrane commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

What does this change?

Applies the API-convention rulings made in the DLCS docs/API hygiene sprint's cross-cutting session (session 0, 2026-08-06, ruled in-room by the PO + engineering). One commit per ruling; commits accumulate as the session proceeds. Draft until the session closes. Companion docs PR: dlcs/public-docs#9.

Warning

Breaking changes — please carry these into the release notes:

  1. POST /customers/{id}/deleteImages — was 200 OK + { "message": "images deleted" }, now 204 No Content with empty body.
  2. DELETE /customers/{id}/resources/pdf/{queryName}?args=... — was 200 OK + { "success": true|false } (including failures reported as success: false inside a 200), now 204 No Content on success and a 500 Hydra Error when deletion fails.
  3. Three Customer wire keys are renamed by trimming a trailing space that has been in the serialised name: "administrator ""administrator", "created ""created", "acceptedAgreement ""acceptedAgreement". Any consumer that coded around the bug (requesting the spaced key) must switch; please check the portal before merging.
  4. Minor: PUT /customers/{id}/customHeaders/{headerId} on an existing header returned 201 Created (a handler bug, unchanged since 2023); it now returns 200 OK. 201 is still returned when a PUT creates.

Items 1, 2 and 4 are the ratified status-code conventions applied (refs #1050); item 3 closes the whitespace-property-name defect and adds a reflection guard test (DLCS.Hydra.Tests) so it cannot recur.

The ratified conventions, for context: every DELETE returns 204 No Content with an empty body (404/409/500 as Hydra Error); create-POSTs return 201 + Location (named action-POST exceptions: API-key creation, application setup — return 200); PUT upserts return 201 on create / 200 on replace, update-only PUTs annotate exactly what they do; every non-2xx response is a Hydra Error; error annotations always declare Type = typeof(Error); no Hydra property name carries whitespace.

Non-breaking commits (annotations / generated vocab / internal tidy-ups only):

  • XC-04DefaultDeliveryChannelsController create POST's catch-all returned a bare empty BadRequest(); now a Hydra Error 400. Internal tidy-up: TryValidateHydraDeliveryChannelPolicy returns null-when-valid instead of an Ok() sentinel.
  • XC-05 sweep — 24 bare error-status [ProducesResponseType] annotations across 9 controllers gain Type = typeof(Error), matching the actual HydraProblem bodies.
  • ACC-14 (via XC-02) — key-creation Hydra operation metadata claimed 201; the wire (sanctioned exception) returns 200; metadata now matches.
  • XC-03 — custom-header PUT annotates its 404 (update-only PUT annotates exactly what it does).
  • SPA-13 / SPA-19CustomerOriginStrategy no longer advertises a PATCH operation or a credentials PUT sub-resource that don't exist.
  • SPA-12 — origin-strategy Hydra attributes corrected to the documented contract (strategy settable; credentials write-only property; requiresCredentials read-only).

Integration tests updated for the changed status codes; API, API.Tests and DLCS.Hydra.Tests build clean; DLCS.Hydra.Tests pass (20/20) including the new guard test.

🤖 Generated with Claude Code

tomcrane and others added 5 commits August 5, 2026 11:59
Session-0 ruling (hygiene sprint, 2026-08-06): every DELETE returns 204
with an empty body on success. The two remaining Deliverator back-compat
endpoints migrate:

- POST /customers/{id}/deleteImages: was 200 + {message:"images deleted"},
  now 204
- DELETE /customers/{id}/resources/pdf/{queryName}: was 200 + {success:bool}
  (including success=false wrapped in a 200), now 204 on success and a
  500 Hydra Error when deletion fails

BREAKING: consumers reading those response bodies must stop.
Integration tests updated. Refs #1050.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Session-0 ruling (hygiene sprint, 2026-08-06). UpdateCustomHeaderHandler
returned WriteResult.Created after mutating an existing row, mapping to
201 Created + Location on every successful update since 2023. Now
WriteResult.Updated -> 200 OK, matching the controller annotation and
the upsert convention (201 create / 200 replace).

BREAKING (minor): PUT /customers/{id}/customHeaders/{headerId} on an
existing header now returns 200 instead of 201.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Session-0 ruling (hygiene sprint, 2026-08-06). DefineOperations
advertised PATCH but CustomerOriginStrategiesController implements only
GET/PUT/DELETE on {strategyId}; the docs table correctly omits PATCH.
Generated vocab/Hydra operations only - no wire behaviour change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Session-0 ruling (hygiene sprint, 2026-08-06). DefineOperations
advertised _:customer_originStrategy_credentials_upsert (PUT
vocab:Credentials -> 201) but no {strategyId}/credentials route exists
anywhere in the API - credentials are set via full-object PUT on the
strategy, as documented. Generated vocab only - no wire behaviour
change. The orphan sample demoing the phantom endpoint is deleted from
public-docs in the same session.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Session-0 ruling (hygiene sprint, 2026-08-06) - the docs tables are the
intended contract:

- CustomerOriginStrategy.strategy: ReadOnly true -> false (settable on
  POST/PUT; docs say readonly False)
- CustomerOriginStrategy.credentials: HydraLink -> RdfProperty with
  WriteOnly = true (a write-only secret modelled as a readable link was
  wrong; docs say writeonly True, and the API never renders it back)
- OriginStrategy.requiresCredentials: ReadOnly false -> true (docs say
  readonly True; the global strategy definitions are not writable)

Generated vocab/Hydra documentation only - no wire behaviour change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@tomcrane
tomcrane force-pushed the hygiene/session-0 branch from 2bf9b7c to 0ed301b Compare August 5, 2026 10:59
Session-0 ruling (hygiene sprint, 2026-08-06): create-POSTs return 201,
with exactly two named action-POST exceptions returning 200 - API-key
creation (the key/secret payload has no canonical URL) and application
setup. The controller returns 200; the Hydra operation metadata claimed
201. Metadata now matches the sanctioned wire behaviour. Generated
vocab only - no wire change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Session-0 ratification (2026-08-06): true-upsert PUTs annotate both
200 and 201; an update-only PUT annotates exactly what it does. PUT
/customHeaders/{id} 404s rather than creating, so its annotation set is
200/400/404 - the 404 was missing. Annotation only, no wire change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tomcrane and others added 3 commits August 5, 2026 12:15
Session-0 ratification (2026-08-06): every non-2xx carries a Hydra
Error via HydraProblem/HydraNotFound/ValidationFailed.

- DefaultDeliveryChannelsController create POST catch-all returned a
  bare empty BadRequest(); now a Hydra Error 400
- tidy-up: TryValidateHydraDeliveryChannelPolicy no longer returns an
  Ok() sentinel to mean valid - it returns null when valid, or the
  error result to relay. No wire change

The two ad-hoc 200-body shapes were removed by XC-01; the batch /test
endpoint's {success} body is ruled an acceptable, documented success
shape (docs change in public-docs hygiene/session-0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Session-0 ratification (2026-08-06), extending the rule PR #1234
started: every 4xx/5xx ProducesResponseType annotation declares
Type = typeof(Error), matching the HydraProblem bodies. 24 bare
error-status annotations across 9 controllers gain the type; three
controllers gain the Hydra.Model using. Annotations only - no wire
change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Session-0 ruling (2026-08-06). Customer serialised three wire keys with
a trailing space - "administrator ", "created ", "acceptedAgreement " -
forcing clients to request the exact spaced key. Names trimmed, and a
reflection guard test added (DLCS.Hydra.Tests) asserting no Hydra
JsonProperty name differs from its Trim(), so the defect class cannot
ship again.

BREAKING: any consumer coded around the bug (reading the spaced keys)
must switch to the clean names. The published docs already show the
clean names.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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