Changelog
All notable changes to Gatewyse Enterprise are documented here. Format follows Keep a Changelog; this project uses semantic versioning once tagged.
1.0.0 — 2026-08-04
First tagged release. Nothing was published before it, so nothing here is a breaking change against a released baseline — the scope model below is simply what 1.0.0 is.
Scope model
- There is one tenant, created at boot and implicit in every request. The
organization is the first boundary that discriminates anything, cascading
organization to department. The admin and super-admin tenant APIs are gone;
the base policy the tenant exposed lives at
/api/admin/settings. - Providers and models cascade base to organization to department by sparse
patch.
/providersand/modelsare the deployment catalogue and every mutation requires deployment scope;/provider-overridesand/model-overridesare what one scope changes about a catalogue entry, bounded byassertWithinScope. - Identity is per-scope
memberships, not a flat role list, and authority is bounded by how the session authenticated.RoleScopeis system, organization or department;tenant-adminwas renamed in place todeployment-adminso existing assignments survive.
Added — Identity and access
- MFA enrollment:
POST /me/mfa/{setup,enable,disable,recovery-codes}on the existing TOTP verification (setup issues an otpauth URI plus one-time recovery codes; disable requires proof of possession). - SCIM 2.0 provisioning at
/scim/v2— Users (full lifecycle, soft-disable deprovision) and Groups to role membership, bearer auth, with an escalation guard so an IdP can never grantsuper-admin. - IdP group to role mapping on SSO login (
ssoConfig.groupRoleMappings); OIDC and SAML group claims are captured and roles re-synced on each login. - Refresh-token rotation reuse detection (a replayed rotated-out token revokes the whole session family) plus session listing, self-revoke and admin force-logout.
- SAML Single Logout (SP-initiated):
GET /api/auth/sso/saml/logoutredirects the authenticated user to their IdP’s SLO endpoint.
Added — Reliability and operations
- Provider circuit-breaker state is now shared across replicas via Redis (previously per-pod), fails open on Redis errors, single cross-pod half-open probe, per-provider thresholds.
- Budget-alert delivery (webhook, Slack, email) with atomic once-only dispatch; USD budgets now actually accrue (the deduction was 0).
- Backup restore (
POST /api/admin/backups/:id/restore) with sha256 archive verification before replay, plus RTO/RPO guidance. - Schema migration framework (
MigrationRunner,schema_migrations, amigrateCLI with up/down/status).
Added — Providers
- Novita, SiliconFlow, Nebius, Baseten, Hyperbolic, NVIDIA NIM (OpenAI-compatible) and Jina (embeddings and reranker); base URLs verified against vendor documentation. The provider catalogue is now 49 adapters.
Added — Developer experience
- Typed TypeScript SDK (
GatewyseClient, withchat()andlistModels()) over the OpenAI-compatible surface. gatewyseCLI:health,models,chatagainst a gateway.- Generated OpenAPI 3 spec served at
GET /openapi.json(built from the Zod schemas), importable into Swagger or Postman.
Added — Compliance and observability
- Prompt-cache read tokens are now priced at the discounted rate (10% default) end to end.
- Internal showback CSV export (
/api/admin/usage/breakdown?format=csv). - GDPR data-subject export (Article 15) and erasure (Article 17 — anonymize and scrub captured bodies, audit chain left intact).
- OpenTelemetry OTLP pipeline for traces, metrics and logs (previously
traces only), on both the server and the worker, which had no telemetry at
all; Winston logs are forwarded with trace context. Gated on
OTEL_EXPORTER_OTLP_ENDPOINT. - New Prometheus metrics:
aigw_guard_blocks_total,aigw_budget_blocks_total,aigw_cache_requests_total,aigw_auth_failures_total,aigw_rate_limit_rejections_total,aigw_stream_ttft_seconds,aigw_queue_depth. - Ships a Grafana dashboard, Prometheus alert rules and a scrape example.
- Pluggable
KeyProvider(a KMS/BYOK seam) behind encryption; the environment master key is the default, and a misconfigured provider fails loudly.
Changed
- Default
MONGODB_URIis single-node (no?replicaSet=rs0); production sets the URI explicitly. Ordinary operation uses no transactions or change streams. Encryption-key rotation is the one exception: it commits across collections in a single transaction and therefore requires a replica set, which every shipped Compose file provides. Against a standalone instance it refuses to start. - CI: the security audit no longer swallows failures, runs the admin Playwright e2e suite, collects coverage, and adds dependency review.
Fixed
- Anthropic adaptive-thinking request shape for Opus 4.8, Sonnet 5 and Fable 5
(was sending the manual
budget_tokensform, which returned 400). - SSO
google/microsoft/oktapresets are accepted at the callback; they were accepted at initiate and rejected at callback.
Security
- Encryption-key rotation covered the provider catalogue only. It now also re-encrypts organization and department credential overrides, MFA secrets and recovery codes, each under its own associated data, and commits them in one transaction. Previously a rotation plus key cutover left every uncovered secret permanently unreadable behind a success response.
- API-key IP allow-lists compared entries to the client address as strings, so a CIDR entry matched nothing and an IPv4-mapped address did not match its own IPv4 form. Real matching now, IPv4 and IPv6, failing closed on a malformed entry rather than skipping it.
- Audit entries were stamped with a seven-day expiry while everything else
described a year, and the stamp is immutable. Retention now defaults to 365
days and is set with
AUDIT_LOG_RETENTION_DAYS; a malformed value is refused rather than silently replaced. scopes.providerIdsandscopes.modelIdson API keys were stored and returned but never enforced. A non-empty value is now refused, so a confinement that does not exist cannot be configured. Use the deployment, organization or department allow-lists, which routing does enforce.
Removed
- Vestigial
stripeCustomerId, deadPermissionActionLIST and MANAGE members, and the duplicateAuditLogschema (unified onto the immutable, hash-chained one).