Skip to content

Releases

v1.1.0

Choose a tag to compare

@github-actions github-actions released this 10 Nov 13:42
Immutable release. Only release title and notes can be modified.
6247883

seampact 1.1.0

seampact 1.1.0 adds two server targets, API Platform and Next.js, an axios client, and app input rules on the Node and PHP servers. Every package, in every ecosystem, moves to 1.1.0. Your contracts need no change.

New targets

  • A new seampact/api-platform target generates API Platform 5 resources, operations and processors for a contract, served through the Symfony boundary. Every reply goes through the boundary, and the exceptions of API Platform's security map to the api's errors. See the API Platform guide.
  • The API Platform target writes JSON-LD items and Hydra collections with the @id of each resource, and @seampact/pack-api-platform answers a failed validation with API Platform's 422 violations body.
  • A new @seampact/codegen-nextjs target generates a route handler per api for a Next.js 16 catch-all route file, with the contract's access, validation and reply checks around your handlers. See the Next.js guide.
  • A new @seampact/codegen-axios target generates the typed client over your own axios instance, and the React, Vue and Angular targets run over it unchanged. See the axios client.
  • Both server targets pass the shared http suite in CI, Next.js on a real next build and next start app, and the compatibility matrix lists them as tested.

App input rules

Your own checks now run after the contract's checks, written in your validator library, and a failure answers the contract's schema-invalid error with app.<name> issues (ADR 0028):

  • Express, Fastify and Hono take typed inputRules beside hooks, with zod, yup or Ajv rules; Next.js takes them in routeHandler, as Hono does.
  • NestJS and AdonisJS take them in forRoot and registerRoutes, with class-validator, VineJS, zod or yup rules.
  • Laravel takes rules in Laravel's validation syntax, and Symfony takes Symfony constraints.
  • The shared http suite has an input-rules case; the servers without input rules yet skip it by name.

Python, Spring Boot and API Platform get input rules in 1.2.0. Until then, API Platform refuses a tagged input rules service at cache:warmup with input.rules.unsupported.

Examples

Three runnable apps, each generated from one contract and kept green by CI: NestJS and React, Laravel and Vue, and a full-stack Next.js app.

Registry pages

  • Every published package's npm, Packagist and PyPI page opens with a one-sentence description, keywords, an install line and a link to its guide; Maven Central and the Gradle Plugin Portal get the same descriptions and tags.
  • The Gradle Plugin Portal approved io.github.jubasse.seampact: Gradle builds load the plugin from the portal.
  • The npm packages are published through npm trusted publishing, with no token.

v1.0.1

Choose a tag to compare

@github-actions github-actions released this 08 Nov 13:29
Immutable release. Only release title and notes can be modified.
dfdf88d

seampact 1.0.1

seampact 1.0.1 is a patch release: server fixes, clearer generate errors, better docs and agent skills. Every package, in every ecosystem, moves to 1.0.1. Nothing in your contract changes.

Upgrade note

Python, Laravel and Symfony servers now compute the ETag and idempotency digests of a body holding an integer past 2^53 as the other targets do, so the same body gets the same digest on every server. After the upgrade, a retry of such a request stored by 1.0.0 no longer matches its record and is served as a new request.

Server fixes

  • AdonisJS servers answer a request body in an unknown content coding with 415 and a corrupt or cut gzip body with 400, where they answered 500 before.
  • AdonisJS 6 servers answer a compressed request body with 415, or 413 when it is over the route limit once inflated, where they answered 400 before.
  • Fastify servers that register @fastify/compress now accept gzip request bodies and answer an unknown content coding with 415, a body over the limit once inflated with 413 and a corrupt gzip body with 400, where they refused, failed or hung before.
  • The PHP boundary now reads a gzip request body of several members whole, and refuses as invalid the bytes after a gzip or deflate stream that do not start another gzip member.
  • The PHP boundary now refuses a gzip or deflate request body cut before its end as invalid, instead of reading it as a shorter body.
  • The framework-route allow-list on FastAPI, DRF and Ninja now matches the Node rule: a single * no longer admits a catch-all route, ** matches zero segments, and empty segments are ignored.

Clearer errors

  • A generate refusal now names its contract file and line, gives a fix of its own (starting with "Ask the user first:" when it changes the API) and ends with the URL of its troubleshooting row.
  • The Spring Boot, PHP and Python generators no longer tell you to update to a release that does not exist when they refuse a form: the fix says to ask the user before removing the operation, or to remove a waiting artefact switch from the entry, and links the troubleshooting page.

Docs and agents

  • The docs are rewritten for every stack, with a new types and validation section.
  • The FastAPI, DRF and Ninja guides now show how to write a paged list handler.
  • Coding agents get small, focused docs files and seampact skills: npx skills add jubasse/seampact (AI agents).

Registry pages

  • The Maven Central POMs and the Gradle Plugin Portal page link to the docs site, the Spring Boot ones to the Spring Boot guide.
  • The Packagist pages link to the docs site, the source and the issues, the Laravel and Symfony ones to their own guide.
  • The PyPI pages link to the docs site, the source and the issues, the FastAPI, DRF and Ninja ones to their own guide.

v1.0.0

Choose a tag to compare

@github-actions github-actions released this 08 Nov 07:23
Immutable release. Only release title and notes can be modified.
4c15f81

seampact 1.0.0

seampact 1.0.0 is the first release. You write one contract in YAML. seampact generates the server boundary, the client and the OpenAPI document from it, and checks in CI that nothing drifted.

Every package, in every ecosystem, has the same version. Install shows how to get each one.

Where to get it

Registry What you get Status
npm the CLI, the generators, the runtime and the packs live, 2026-11-07
Maven Central the Spring Boot runtime, the hooks, the Maven plugin and the compiler live, 2026-11-07
Gradle Plugin Portal the Gradle plugin io.github.jubasse.seampact pending review, 2026-11-07
Packagist seampact/laravel, seampact/symfony and their libraries live, 2026-11-07
PyPI seampact-fastapi, seampact-drf, seampact-ninja and their libraries live, 2026-11-07
GitHub releases the compiler binary for five systems, with SHA256SUMS live, 2026-11-07

The Gradle Plugin Portal reviews each new plugin by hand, which takes a few days. Until it approves, the Maven plugin works at once, and Gradle builds can load the plugin from Maven Central: see the Spring Boot guide.

On release day, pnpm can answer "no matching version" for @seampact/*. Its minimumReleaseAge setting holds back a package published in the last day. Wait, or add minimumReleaseAgeExclude: ["@seampact/*"] to pnpm-workspace.yaml: see Install.

What 1.0 ships

Servers:

Clients and validators:

  • A typed fetch client, React hooks (TanStack Query, SWR or RTK Query) and TypeScript types.
  • Validators with zod, yup or class-validator.

Everything else:

  • The OpenAPI 3.1 document of each api.
  • seampact diff classifies a change as additive or breaking, and seampact check fails CI on drift.
  • Access rights, signed webhooks, idempotency keys, paging and conditional requests.
  • The standalone compiler binary: compile, lint, diff, explain and bundle without Node.js.

Known limits

A form that 1.0 does not support is refused by name when you run seampact generate. The message says which form and where. Nothing is generated silently wrong. Generate errors explains most of them. Where a line says "remove the operation", list the other operations in the entry's operations filter and write that one by hand.

Every server (the Node servers, Spring Boot, Laravel, Symfony, FastAPI, DRF and Ninja):

  • A principal with variants (viewer_or_device), a principal requirement and a principal binding are refused. Declare one principal kind per route and check the principal in your handler.
  • A signature scheme that your application verifies is refused. Verify the signature in your own middleware and leave it out of the contract.
  • An API key in the query string and HTTP Basic are refused. Send the key in a header, or use a bearer token.
  • A scope that your application resolves (resolver) is refused. Declare the scope from the path (path.projectId) or the subdomain.
  • An identity header written on a response (also by the fetch client), such as the rights-version header (identity.response.header.unsupported), is refused. Remove it from the identity's headers, or declare a deadline, trace or actor header in: request.
  • accessHooks: false (native access) is refused. Keep the hooks and read the framework's own auth in the authenticate hook.
  • A sort key restricted by a right (sortable: [{ key, right }], or a key of a field with restrictedTo) is refused. Leave the key out of sortable.
  • A page or an item that writes the $collection, $resource or item id slots (JSON:API, HAL, JSON-LD) is refused. Use a page style without them.

Every server and the fetch client:

  • Form, multipart and file download bodies are refused. Remove the operation.
  • A redirect response is refused. Remove the operation.
  • A response header that the route writes itself is refused. Remove the operation.
  • A tagged union (oneOf with a discriminator) is refused, and by zod too. Remove the operation.
  • A degradable operation is refused. Remove the operation.
  • A query list in brackets form (tag[]=a) is refused. Set conventions.query.lists to repeat or comma.
  • A deprecated operation is refused by the fetch client only. Remove the operation from the client entry.

Node servers:

  • Optional authentication is refused. Spring Boot, Laravel, Symfony, FastAPI, DRF and Ninja generate it.
  • Absolute URLs in responses are refused. Use relative URLs; Spring Boot, Laravel, Symfony, FastAPI, DRF and Ninja write absolute ones from a configured public origin.
  • The split sort style is refused. Use signed, pair or keyed.
  • An input field right below the top level of the input (/details/budget) is refused. Put the field at the top level of the input, or check the right in your handler.
  • idempotency.enforce: none is refused. Keep boundary. Spring Boot, Laravel, Symfony, FastAPI, DRF and Ninja generate it, but the 1.0 test suite does not cover it there yet.

PHP and Python servers (Laravel, Symfony, FastAPI, DRF, Ninja):

  • The complete page fact of a changes-since paging style is refused. Use another paging style on these servers.

Spring Boot, Laravel and NestJS:

  • The suffixes option and per-operation handlers (perOperation) are refused. Use the default names and the default perResource handlers.
  • A custom metadata on a right is refused on NestJS and Laravel. Leave it out of the right.
  • The codeName option is refused on NestJS. Spring Boot and Laravel support it.

Clients and validators:

  • An open enum with a fallback is refused in the types the fetch client is generated beside. Declare a closed enum.
  • An error format that writes its code only inside a text template is refused for the fetch client. Put the code in a field of its own.
  • The ignore and keep policies for unknown keys of an operation input are refused with the zod, yup and class-validator validators. Keep the default, which refuses unknown keys.

Known differences between servers. A portable client avoids them:

  • A comma list sent as an empty value (sort=) is an empty list on the Node servers and one empty item on Spring Boot and PHP.
  • A comma key sent twice (sort=a&sort=-b) answers 400 on the Node servers. Spring Boot and PHP join both values.
  • limit=1e3 is read as 1000 on Node. Spring Boot, Laravel, Symfony and FastAPI answer 400.

Not in 1.0:

  • API Platform comes after 1.0. Use Symfony with its own controllers, as the Symfony guide shows.
  • The CASL (NestJS) and spatie (Laravel) adapters come in 1.1. Until then, write the rights in your own guard or policy.
  • Test helpers, dev docs served by the server, and a ready-made idempotency store are not generated on the Node, Java, PHP and Python servers. The idempotency store is an interface you implement; the Node servers have an in-memory one.
  • Express, Fastify, Hono and FastAPI generate no native access export, and Express, Fastify and Hono map no framework security refusals: your own middleware owns them.
  • The Angular service does not set HttpClient's XSRF header. Call withXsrfConfiguration with the contract's CSRF header name, as the Angular guide says.
  • The fetch client does not retry by the nature of an error code. It retries a rejected request, never a declared error.
  • The binary and the plugins download over HTTPS only and read no proxy variable. Behind a proxy, put the binary on a mirror and set its URL and hash, or point to a local file.
  • macOS binaries carry an ad hoc signature, not an Apple one. If macOS blocks the file, allow it in System Settings.