skill development and ADR sessions
All checks were successful
Build, test and publish / verify (push) Successful in 7m44s
All checks were successful
Build, test and publish / verify (push) Successful in 7m44s
This commit is contained in:
176
adr/refined/ADR2_http-api-contracts-and-tooling.md
Normal file
176
adr/refined/ADR2_http-api-contracts-and-tooling.md
Normal file
@@ -0,0 +1,176 @@
|
||||
**ID:** ADR2 \
|
||||
**Title:** HTTP API contracts and tooling \
|
||||
**Supersedes:** - \
|
||||
**Status:** REFINED \
|
||||
**Expiration Date:** Six months after approval; record the calendar date upon manual approval.
|
||||
|
||||
## Context
|
||||
|
||||
Agile Dancers currently uses REST without an explicit architectural decision.
|
||||
The landscape needs agreed defaults for communication across system boundaries,
|
||||
contract documentation, client generation, compatibility, and error handling.
|
||||
|
||||
Interactions include frontend access, requests between business systems,
|
||||
delegation of long-running calculations to workers, change notifications, and
|
||||
external consumers. Most clients and servers are developed by the same maintainer.
|
||||
Consumers must nevertheless be able to upgrade independently. The independently
|
||||
deployable systems proposed in ADR1 are relevant context; ADR1 remains REFINED
|
||||
and is not approved through this decision.
|
||||
|
||||
The current frontend uses Angular, but future clients may use other frameworks
|
||||
or languages. Contracts and tooling should support that flexibility.
|
||||
|
||||
For now, interactions use a defined alternative path when another system is
|
||||
offline. Durable queued delivery is not a current requirement. More specialized
|
||||
communication mechanisms may become appropriate for particular interactions.
|
||||
|
||||
## Decisions
|
||||
|
||||
### Scope and communication style
|
||||
|
||||
Use HTTP APIs with JSON payloads as the default across system boundaries.
|
||||
Use resource-oriented endpoints where natural and action-oriented endpoints
|
||||
where they express business intent more clearly. Do not force business actions
|
||||
into CRUD operations. For example:
|
||||
|
||||
```text
|
||||
GET /api/v1/schedules/{id}
|
||||
POST /api/v1/schedules/{id}/calculate
|
||||
```
|
||||
|
||||
Action endpoints still follow HTTP method and status semantics. For long-running
|
||||
work, use an explicit job or operation resource with a status endpoint when the
|
||||
caller needs to track progress. A notification can initially use a direct HTTP
|
||||
request with documented failure behavior; this does not promise durable delivery.
|
||||
|
||||
These are landscape defaults. Document justified exceptions alongside the
|
||||
relevant interface, including the reason and the alternative contract and failure
|
||||
behavior. This ADR does not mandate GraphQL, RPC, or messaging infrastructure.
|
||||
|
||||
### Contracts and documentation
|
||||
|
||||
Describe HTTP APIs using OpenAPI. Normally generate the description from server
|
||||
code, adding explicit descriptions and annotations where needed. Review the
|
||||
resulting contract as a public interface; generation alone does not ensure
|
||||
completeness or backward compatibility.
|
||||
|
||||
Use self-hosted Scalar API Reference as the default interactive documentation UI.
|
||||
Keep the OpenAPI document independently available so consumers and tooling do not
|
||||
depend on the UI. Publish a contract artifact for each supported major version.
|
||||
|
||||
Choose an OpenAPI specification version supported by the server tooling, Scalar,
|
||||
and the selected client generators. Do not automatically adopt the latest version
|
||||
without checking that compatibility.
|
||||
|
||||
### Client generation
|
||||
|
||||
Generate client transport code and contract types from OpenAPI by default, using
|
||||
OpenAPI Generator. Select the generator appropriate to the consuming technology;
|
||||
use `typescript-angular` for Angular clients. This choice does not require future
|
||||
frontends to use Angular.
|
||||
|
||||
Pin generator versions and configuration for reproducible generation. Generate
|
||||
against a selected contract artifact rather than requiring a running server during
|
||||
the client build. Keep generated code separate from handwritten application logic
|
||||
and do not manually edit generated files. Generated static types do not by
|
||||
themselves provide runtime response validation.
|
||||
|
||||
### Versioning and compatibility
|
||||
|
||||
Put the major contract version in the URL, such as `/api/v1/schedules`.
|
||||
Keep backward-compatible changes within that major version. Introduce a new
|
||||
major version for breaking changes. Software release and generated client package
|
||||
versions may advance independently of the major contract version.
|
||||
|
||||
Allow consumers to upgrade independently. Normally support one contract version;
|
||||
during transitions, aim to support two. This is a guideline rather than a hard
|
||||
cap: additional versions may coexist when justified. Document supported versions,
|
||||
deprecation, and the transition plan, coordinating retirement with affected
|
||||
consumers. Check compatibility before releasing contract changes.
|
||||
|
||||
### Errors and offline behavior
|
||||
|
||||
Standardize API error bodies on RFC 9457 Problem Details using
|
||||
`application/problem+json` and appropriate HTTP status codes. Use stable problem
|
||||
`type` identifiers for programmatic handling and readable explanations for humans.
|
||||
Clients must not depend on parsing human-readable messages. Document expected
|
||||
errors in OpenAPI, including validation details where applicable. Do not expose
|
||||
internal exception details or sensitive information in error responses.
|
||||
|
||||
Define timeouts and the offline alternative path for each interaction. A network
|
||||
failure may produce no HTTP response, so consumers must handle that separately
|
||||
from a Problem Details response. Avoid automatic retries of actions unless
|
||||
repeating them is safe. Do not assume durable delivery or eventual replay.
|
||||
|
||||
### Adoption and review
|
||||
|
||||
Adopt incrementally for new interfaces and interfaces being substantially changed.
|
||||
Migrate existing interfaces through planned work while preserving compatibility
|
||||
for existing consumers. No immediate landscape-wide rewrite is required.
|
||||
|
||||
Review six months after approval, or earlier if integration needs expose
|
||||
limitations. The review date triggers reevaluation rather than automatic expiry.
|
||||
|
||||
## Options considered
|
||||
|
||||
### Communication approach
|
||||
|
||||
| Option | Pros | Cons | Outcome |
|
||||
| --- | --- | --- | --- |
|
||||
| Resource-oriented HTTP/JSON with action endpoints | Readable resources and business actions; supports different client technologies; retains HTTP semantics. | Requires consistent endpoint conventions and explicit handling of long-running work and failures. | Chosen as the default. |
|
||||
| GraphQL | Flexible data selection; typed schema; supports different consumer views of related data. | Adds query authorization and performance concerns; requires additional conventions for work delegation and notifications. | Not chosen: current needs and common client/server ownership do not justify the added complexity. |
|
||||
| RPC, including JSON-RPC and gRPC | Explicit operation contracts; JSON-RPC is lightweight; gRPC supports strongly typed generated clients. | Operation-oriented contracts require careful evolution; gRPC adds browser integration requirements. | Not chosen as the default: resource-oriented HTTP with optional actions better matches the desired interface flexibility. RPC remains a possible justified exception. |
|
||||
|
||||
### Contract description and authoring
|
||||
|
||||
| Option | Pros | Cons | Outcome |
|
||||
| --- | --- | --- | --- |
|
||||
| OpenAPI, normally generated from server code | Language-independent HTTP contracts; supports documentation and client generation; avoids separately maintaining a design language. | Needs annotations, review, and compatibility checks; generated output can be incomplete. | Chosen. |
|
||||
| TypeSpec generating OpenAPI | Dedicated contract authoring language; can generate descriptions and other artifacts. | Adds a language and compiler to maintain. | Not chosen: no current benefit sufficient to justify the additional tooling. |
|
||||
| RAML | API description language with reusable modeling constructs. | Its specification repository is archived, creating a maintenance concern for a new standard. | Not chosen. |
|
||||
|
||||
### Interactive documentation
|
||||
|
||||
| Option | Pros | Cons | Outcome |
|
||||
| --- | --- | --- | --- |
|
||||
| Scalar API Reference | Readable interactive documentation; integrated request testing; self-hosting and configuration options. | Requires integration and maintenance alongside the server framework. | Chosen: readability and testability are the primary purposes of the UI. |
|
||||
| Swagger UI | Interactive requests and authentication support; direct integration with Quarkus OpenAPI tooling. | Its expandable operation layout is less aligned with the preferred reading experience. | Not chosen as the landscape default. |
|
||||
|
||||
### Client generation
|
||||
|
||||
| Option | Pros | Cons | Outcome |
|
||||
| --- | --- | --- | --- |
|
||||
| OpenAPI Generator | Supports Angular and other client technologies in one tool family; configurable generation. | Generator-specific options and upgrades need management. | Chosen to support future technology changes. |
|
||||
| ng-openapi-gen | Angular-focused generation; npm-based tooling. | Other client technologies require another generator. | Not chosen as the landscape default. |
|
||||
| Handwritten clients | Direct control over client code and application integration. | Duplicates contract types and request details; increases drift risk. | Not chosen as the default. |
|
||||
|
||||
## Consequences
|
||||
|
||||
- Apply the defaults to new and substantially changed interfaces. Plan migration
|
||||
of existing interfaces incrementally, preserving consumer compatibility.
|
||||
- Generate and publish versioned OpenAPI artifacts. Add Scalar to provide
|
||||
interactive documentation and request testing for supported contracts.
|
||||
- Establish pinned OpenAPI Generator configurations for client technologies,
|
||||
initially Angular. Keep generated code separate from application logic.
|
||||
- Add contract validation and compatibility checks to release workflows. Verify
|
||||
generated clients against the actual contract before adopting generator upgrades.
|
||||
- Introduce URL major versions and coordinate deprecation with consumers. Normally
|
||||
maintain one version and temporarily two, documenting justified deviations.
|
||||
- Align API error responses with Problem Details and document expected failures.
|
||||
Define timeout and offline behavior per interaction, including safe retry rules.
|
||||
- Record justified exceptions alongside their interfaces rather than imposing an
|
||||
unsuitable communication mechanism on every interaction.
|
||||
- Record the calendar review date upon manual approval. REFINED captures the
|
||||
agreed proposal; approval remains a separate manual step.
|
||||
|
||||
### References
|
||||
|
||||
- [OpenAPI specification](https://spec.openapis.org/oas/)
|
||||
- [Scalar API Reference configuration](https://scalar.com/products/api-references/configuration)
|
||||
- [OpenAPI Generator: TypeScript Angular](https://openapi-generator.tech/docs/generators/typescript-angular/)
|
||||
- [RFC 9457: Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc9457.html)
|
||||
- [Swagger UI configuration](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/)
|
||||
- [TypeSpec overview](https://learn.microsoft.com/en-us/azure/developer/typespec/overview/)
|
||||
- [RAML specification repository](https://github.com/raml-org/raml-spec)
|
||||
- [JSON-RPC specification](https://www.jsonrpc.org/specification)
|
||||
- [ng-openapi-gen](https://github.com/cyclosproject/ng-openapi-gen)
|
||||
Reference in New Issue
Block a user