Skip to content

Add recipient routing (/routes) to the API spec and SDKs#263

Closed
etbyrd wants to merge 4 commits into
mainfrom
route-target-sdk
Closed

Add recipient routing (/routes) to the API spec and SDKs#263
etbyrd wants to merge 4 commits into
mainfrom
route-target-sdk

Conversation

@etbyrd

@etbyrd etbyrd commented Jun 25, 2026

Copy link
Copy Markdown
Member

What

Adds the recipient-routing API surface to the OpenAPI spec and regenerates the Node, Python, and Go SDKs (all bumped to 1.12.0).

New paths (Routes tag):

  • GET /routes, POST /routes, PATCH /routes/{id}, DELETE /routes/{id}
  • POST /routes/reorder, POST /routes/simulate

New schemas: MatchType, RecipientRoute, CreateRouteInput, UpdateRouteInput, ReorderRoutesInput, SimulateRouteInput, SimulateRouteResult, RouteEvaluation.

Endpoint schema gains kind, function_id, and is_route_target, matching the create/response contract.

POST /routes accepts either an existing endpoint_id or a function_id. With function_id, a dedicated route-target endpoint is minted for the function and bound to the route in one call (single-call per-address function routing).

Why

Recipient routing was reachable on the API but absent from the published spec, so the SDKs and CLI had no typed support for it. This documents the full surface and regenerates all SDKs from it.

Notes

  • The route schema is named RecipientRoute (not Route) because the Go generator reserves Route for its internal router type.
  • The CLI picks up the new operations from the regenerated manifest (a routes command group).

Test plan

  • make node-check: generated artifacts consistent; 692 tests pass.
  • make python-check: 322 tests pass.
  • make go-check: go vet and go test clean; generated client compiles.

etbyrd added 2 commits June 25, 2026 12:48
Documents the recipient-routing surface that was missing from the public spec:
- /routes GET/POST, /routes/{id} PATCH/DELETE, /routes/reorder, /routes/simulate
- Route, CreateRouteInput (endpoint_id OR function_id), UpdateRouteInput,
  ReorderRoutesInput, SimulateRouteInput, SimulateRouteResult schemas
- kind, function_id, is_route_target on Endpoint + CreateEndpointInput

Regenerated the Node SDK + CLI operation manifest from the spec.
…o 1.12.0

ogen reserves the type name Route for its generated router, so the schema is
named RecipientRoute to avoid a Go redeclaration. Regenerated the Node, Python,
and Go SDKs from the spec and bumped all four packages to 1.12.0.
@greptile-apps

greptile-apps Bot commented Jun 25, 2026

Copy link
Copy Markdown

Confidence Score: 5/5

Safe to merge — the change is a spec-to-SDK regeneration of an already-deployed API surface with no logic changes in non-generated code.

All changes are either generated from the OpenAPI spec or are version bumps. The spec additions are internally consistent, the router handles the static/parametric path ordering correctly, and the test suites (692 Node tests, 322 Python tests, Go vet+test) all pass. No hand-written logic was modified beyond the template version constants and README copy.

openapi/primitive-api.yaml — the RecipientRoute response schema declares only id as required, leaving match_type/pattern/endpoint_id optional even though the server always returns them; and SimulateRouteResult.matched_tier uses a plain string type rather than a $ref to MatchType (unlike RouteEvaluation.tier).

Important Files Changed

Filename Overview
openapi/primitive-api.yaml Adds /routes CRUD + reorder + simulate paths and all new schemas; matched_tier uses plain string
packages/api-core/src/api/types.gen.ts New RecipientRoute, CreateRouteInput, UpdateRouteInput, SimulateRouteResult, RouteEvaluation types generated correctly; SimulateRouteResult.matched_tier typed as string
packages/api-core/src/api/sdk.gen.ts All six route operations (listRoutes, createRoute, updateRoute, deleteRoute, reorderRoutes, simulateRoute) generated with correct URLs and HTTP methods
packages/api-core/src/api/index.ts All new route functions and types properly re-exported
sdk-go/api/oas_router_gen.go Router correctly checks literal /routes/reorder and /routes/simulate before the parametric /routes/{id} branch, preventing any path shadowing
sdk-python/src/primitive/api/models/simulate_route_result.py SimulateRouteResult model generated correctly; matched_tier typed as None
sdk-python/src/primitive/api/models/create_route_input.py CreateRouteInput attrs model with match_type/pattern required and endpoint_id/function_id as UUID
sdk-python/src/primitive/api/models/endpoint.py Endpoint model correctly extended with kind, function_id, and is_route_target optional fields
cli-node/src/oclif/function-templates.ts SDK_VERSION_RANGE and CLI_VERSION_RANGE bumped to ^1.12.0; function template README updated with recipient routing guidance

Reviews (3): Last reviewed commit: "Fix nullable-enum codegen for route simu..." | Re-trigger Greptile

Comment thread packages/api-core/src/api/types.gen.ts Outdated
Comment thread sdk-python/src/primitive/api/models/simulate_route_result_default_scope_type_1.py Outdated
Comment thread openapi/primitive-api.yaml
- Register a 'routes' oclif topic so the new Routes operations group has a
  description (the topic-per-tag test requires it).
- Bump SDK_VERSION_RANGE and CLI_VERSION_RANGE in the functions:init scaffold to
  ^1.12.0 to match the bumped package versions (lockstep test).
@etbyrd

etbyrd commented Jun 25, 2026

Copy link
Copy Markdown
Member Author

On CreateEndpointInput.url becoming optional: this is intentional and not a break for existing callers. A function endpoint (kind: function) has no URL, so url cannot be statically required on the shared create body. Existing http callers still pass url and still type-check; the relaxation only widens what compiles. The http requirement is enforced server-side (a kind: http create without url returns a 400), and the field description documents 'Required when kind is http'.

Expressing the conditional statically would need a oneOf discriminated on kind, which turns the input into a union and is handled inconsistently across the generators (the Go generator in particular). Given that, the optional field plus server validation is the pragmatic shape. Leaving as-is.

matched_tier and default_scope are modeled as plain nullable strings (the
existing EmailWebhookStatus convention) instead of a oneOf/null ref and an
enum-with-null. This regenerates matched_tier as string | null (was MatchType |
unknown, which TypeScript collapses to unknown) and stops the Python generator
emitting three duplicate default_scope enum classes.
@etbyrd

etbyrd commented Jun 26, 2026

Copy link
Copy Markdown
Member Author

Superseded. Recipient routing landed via #264 (already merged to main), which overlaps almost all of this PR and caused it to conflict. The one genuine gap #263 had over #264 was the endpoint route-target fields (kind / function_id / is_route_target), which I've split into a clean focused PR off current main: #267. Closing this to avoid the duplicate-conflict.

@etbyrd etbyrd closed this Jun 26, 2026
@etbyrd etbyrd deleted the route-target-sdk branch June 26, 2026 07:32
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