Skip to content

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. /providers and /models are the deployment catalogue and every mutation requires deployment scope; /provider-overrides and /model-overrides are what one scope changes about a catalogue entry, bounded by assertWithinScope.
  • Identity is per-scope memberships, not a flat role list, and authority is bounded by how the session authenticated. RoleScope is system, organization or department; tenant-admin was renamed in place to deployment-admin so 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 grant super-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/logout redirects 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, a migrate CLI 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, with chat() and listModels()) over the OpenAI-compatible surface.
  • gatewyse CLI: health, models, chat against 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_URI is 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_tokens form, which returned 400).
  • SSO google / microsoft / okta presets 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.providerIds and scopes.modelIds on 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, dead PermissionAction LIST and MANAGE members, and the duplicate AuditLog schema (unified onto the immutable, hash-chained one).