Files
sxchnge/docs/api-versions.md
T

92 lines
4.9 KiB
Markdown

# Installing product HTTP API versions
The product executable selects supported implementations in
`backend/product/app/profile/runtime.go`. Each entry maps a version name to an
`api.Installer`; v1 composes the existing authentication and second-factor
contracts. Adding an implementation requires a package and a registry entry,
without changing runtime installation code.
Select installations in the product YAML:
```yaml
api:
versions:
- version: v1
path: /api/v1
# Existing middleware, storage and notification configuration follows.
```
Only v1 ships today. Once a v2 implementation is registered, a second entry with
`version: v2` and `path: /api/v2` serves both versions in the same process. Each
version can be selected once. Unknown/unavailable versions, duplicate versions,
overlapping mounts, noncanonical paths and mounts occupying operational endpoints
fail startup. Paths must be absolute, non-root, without trailing slashes, URL
escapes, queries, fragments or router pattern syntax. Mounts use ASCII letters,
digits, slashes, hyphens, underscores, periods and tildes.
Omitting `versions` retains compatibility: v1 mounts at the path in the environment
variable named by `api.middleware.api_endpoint_env` (normally
`SXCHNGE_API_ENDPOINT=/api/v1`). An explicit `versions: []` installs no application
routes; process infrastructure and operational endpoints remain available.
The endpoint environment variable continues to locate the process health and
metrics compatibility endpoints, including when explicit application mounts are
used. With `/api/v1`, these are `/api/v1/health`, `/api/v1/metrics` and `/metrics`.
Keep this value unchanged when adding a version. Health is outside application
middleware; the existing HTTP collector excludes operational traffic. These
operational endpoints are reserved and are never version-owned contracts.
## Ownership and lifecycle
Runtime bootstrap opens shared stores once and injects those stores into the
customer service, auth flow and second-factor service. Notification connections
are opened once. Every installer receives the same typed dependencies and its
own router, validated mount, URL provider and logger. Installers register routes
relative to their mount and do not open or close process resources.
Auth v1 handlers, request DTOs and response mappers live under
`backend/product/auth/http/v1`; factor transport lives under
`backend/product/twofactor/http/v1`. Models, services and storage remain in their
owning features. A future version owns its wire contract and reuses domain
services, so changing its DTOs does not silently change v1. The generic runtime
and HTTP middleware do not import concrete API versions.
All version routers are built before any application router is attached. An
installer error aborts startup, preserves the cause and closes shared resources.
Bootstrap must either return a cleanup callback for resources it opened or close
them itself before returning an error; it must not do both. The built-in bootstrap
cleans its partial initialization internally. Runtime invokes an acquired cleanup
callback once, including on installation failure or repeated/concurrent shutdown.
The server retains ownership of the shared database factory.
The removed generic service registry and untyped runtime component lookup have no
product consumers. The typed dependencies and installer registry replace them.
This changes internal Go composition APIs; public v1 JSON and HTTP paths remain
compatible. No database migration is required.
## Cookies and links
Runtime binds browser cookie scope to the installed mount using request context.
Set and clear operations use the same `<mount>/accounts` path. The existing v1
path remains `/api/v1/accounts`; `/api/v2` would use `/api/v2/accounts`. Cookie
name, host-only policy, Secure, HttpOnly and SameSite settings are unchanged.
Changing an existing mount requires clients to authenticate at the new path;
cookies at the old path do not migrate automatically. Versions share domain
session state, so account-wide revocation continues to apply across versions.
`API_ENDPOINT` no longer overrides cookies globally. Direct standalone handler
calls retain their request-path fallback; installed APIs always use explicit
scope. Installers generate API links through `scope.URLs`, which combines the
configured origin and that installation's mount. The origin must use HTTP or
HTTPS with a hostname and optional port. Configured notification activation URLs
remain frontend links and are not rewritten as API links.
## Validation
Runtime tests exercise independently behaving versions, shared dependency identity,
disabled routes, invalid mounts, scoped links, cookie set/delete behavior, failed
installation cleanup and repeated shutdown. The existing Mongo-backed startup
test covers the default v1 installation on an empty database. Existing auth and
factor tests moved with their transports and retain their contract assertions.
Run `make test` and `make lint-backend` from the repository root.