Skip to content

Add fixed-route single instance response shaping - #163

Merged
eviltester merged 1 commit into
masterfrom
codex/single-instance-response-shape-162
Aug 23, 2026
Merged

Add fixed-route single instance response shaping#163
eviltester merged 1 commit into
masterfrom
codex/single-instance-response-shape-162

Conversation

@eviltester

Copy link
Copy Markdown
Owner

Summary

  • Add route-level response shape metadata with ResponseShape and respondWithSingleInstance() for fixed-resource routes.
  • Shape successful fixed-route responses before route response policies so hooks and header policies see the intended single instance.
  • Document shaped fixed routes as single-instance OpenAPI responses and keep legacy collection behavior unchanged unless the route opts in.

Verification

  • mvn -pl thingifier verify
  • Full pre-commit reactor verification passed across all 14 modules
  • Installed thingifier-1.5.6-SNAPSHOT to local Maven for API Challenges

Closes #162

Copilot AI lite review requested due to automatic review settings August 23, 2026 15:45
@eviltester
eviltester merged commit 2668129 into master Aug 23, 2026
4 checks passed
@eviltester
eviltester deleted the codex/single-instance-response-shape-162 branch August 23, 2026 15:48

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c922764e0e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +118 to +120
if (!rule.hasFixedIdentifierMapping()) {
return ApiResponse.error(
500,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle generated instance routes before rejecting the shape

When respondWithSingleInstance() is placed on a normal generated instance rule—the added ThingifierApiSpecTest does this for /api/todos/{id}—a successful request returns 500 solely because the rule has no fixed mapping, even when response.hasReturnedInstance() is already true. This turns an otherwise valid generated GET into a server error; accept an already-satisfied singleton response before enforcing fixed-route conversion, or reject this configuration during specification setup.

Useful? React with 👍 / 👎.

Comment on lines +106 to +107
case COLLECTION:
return collectionResponse(rule, publicPath, response);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Document collection-shaped fixed responses as collections

When a fixed route uses ResponseShape.COLLECTION, this branch makes the runtime response a collection, but OpenAPI generation never consumes RoutingDefinition.responseShape(): ThingifierApiSpec.applyFixedRoutePayloads() still registers the singular entity payload for successful fixed routes, and Swaggerizer derives its schema from that payload name. Generated clients therefore expect an object while the server returns the collection wrapper, so the documented payload/schema also needs to honor this shape.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Response shaping currently turns non-fixed routes with a shape override into 500 errors, which makes the new API unsafe to use outside fixed-identifier routes.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR introduces an explicit, route-level “response shape” contract (ResponseShape) so fixed-identifier routes can opt into returning a single entity instance (and be documented as such), with shaping applied before route response policies/hooks.

Changes:

  • Added ResponseShape and route-level configuration on ThingifierApiRouteRule (responseShape(...), respondWithSingleInstance()) and copied this metadata into generated RoutingDefinitions.
  • Implemented response shaping in RouteApiResponsePolicyApplier so successful fixed-route responses can be coerced into single-instance (or collection) form before success policies and hooks run.
  • Added tests covering route metadata propagation, fixed-route runtime behavior (legacy override, hooks, HEAD header policies), and OpenAPI schema expectations.
File summaries
File Description
thingifier/src/test/java/uk/co/compendiumdev/thingifier/api/spec/ThingifierApiSpecTest.java Adds tests that response-shape overrides are recorded on route rules and copied into generated route definitions.
thingifier/src/test/java/uk/co/compendiumdev/thingifier/api/spec/ThingifierApiFixedRouteTest.java Adds fixed-route runtime and OpenAPI tests for single-instance shaping, legacy behavior preservation, hooks, HEAD ordering, and ENSURE_EXISTS behavior.
thingifier/src/test/java/uk/co/compendiumdev/thingifier/api/response/RouteApiResponsePolicyTest.java Adds tests for multiple-instance rejection under SINGLE_INSTANCE and explicit COLLECTION wrapping behavior.
thingifier/src/main/java/uk/co/compendiumdev/thingifier/api/spec/ThingifierApiRouteRule.java Adds route-level response shape configuration, getters, and propagation into routing definitions.
thingifier/src/main/java/uk/co/compendiumdev/thingifier/api/spec/ResponseShape.java Introduces the ResponseShape enum (DEFAULT, SINGLE_INSTANCE, COLLECTION).
thingifier/src/main/java/uk/co/compendiumdev/thingifier/api/docgen/RoutingDefinition.java Stores response-shape metadata for documentation generation.
thingifier/src/main/java/uk/co/compendiumdev/thingifier/adapter/http/apihandlers/RouteApiResponsePolicyApplier.java Applies response-shape transformation before response policies and view/body handling.
Review details
  • Files reviewed: 7/7 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +95 to +101
if (!rule.hasResponseShapeOverride()
|| response.isErrorResponse()
|| response.hasABodyOverride()
|| response.getStatusCode() < 200
|| response.getStatusCode() >= 300) {
return response;
}
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.

Route-level single-instance response shape for fixed routes

2 participants