Changelog¶
All notable changes to this project will be documented here.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[0.1.5]¶
Added¶
- Rewrote README and docs homepage to focus on runtime API behavior control without redeploying.
[0.1.4]¶
Added¶
- Google Search Console verification for docs site.
[0.1.3]¶
Added¶
- New tutorial sections: Route Control, Rollouts, Webhooks, Audit Log, and Custom Responses.
Removed¶
- Removed reference to token bucket algorithm, will add real implementation in coming release.
0.1.0¶
Changed¶
api-shieldis deprecated.waygateis the new package name. All future releases will be published underwaygateon PyPI. Replacepip install api-shieldwithpip install waygate(oruv add waygate). The import root changes fromshieldtowaygateand the CLI command fromshieldtowaygate.
[0.8.0]¶
Fixed¶
- Unprotected routes table not updating after adding a policy: routes stayed visible in the "Unprotected Routes" section after a rate limit was set because the filter compared
METHOD:/pathdisplay values against path-only strings stripped of the method prefix; comparison now uses the full composite key correctly. - Invalid rate limit strings accepted silently: submitting a malformed limit (e.g.
2/minutesedrr) was stored and caused a 500 on every request; the engine now validates the limit string before persisting and the dashboard modal surfaces an inline error with the correct format hint.
Added¶
-
Feature flags (
waygate[flags]): a full feature flag system built on the OpenFeature standard, supporting boolean, string, integer, float, and JSON flag types with multi-condition targeting rules, reusable user segments (explicit included/excluded lists plus attribute-based rules), percentage rollouts, prerequisite flags, individual user targeting, and a live SSE evaluation stream. Flags and segments are manageable from the admin dashboard (/waygate/flags,/waygate/segments) and the CLI (waygate flags *,waygate segments *) — including a newwaygate segments add-rulecommand and an "Add Rule" panel in the Edit Segment modal that lets operators add attribute-based targeting rules without touching code or the REST API directly. -
WAYGATE_SERVICEenv var fallback on all--serviceCLI options:waygate status,waygate enable,waygate disable,waygate maintenance, andwaygate scheduleall readWAYGATE_SERVICEautomatically — set it once withexport WAYGATE_SERVICE=payments-serviceand every command scopes itself to that service without repeating--service. An explicit--serviceflag always wins. waygate current-servicecommand: shows the active service context from theWAYGATE_SERVICEenvironment variable, or a hint to set it when the variable is absent.waygate servicescommand: lists all distinct service names registered with the Waygate Server, so you can discover which services are connected before switching context.- Dashboard "Unprotected Routes" section: the Rate Limits page now surfaces all routes that have no rate limit policy, with an "Add Limit" button per row that opens a modal to configure method, limit, algorithm, and key strategy in-place — no CLI required.
- Route existence validation in
set_rate_limit_policy(): attempting to add a rate limit policy for a route that does not exist now raisesRouteNotFoundExceptionimmediately; the REST API returns404and the CLI prints a clear error, preventing phantom policies from accumulating. WaygateSDK.rate_limit_backendparameter: pass aRedisBackendinstance to share rate limit counters across all replicas of a service connected to the same Waygate Server; without it each replica enforces limits independently.- Rate limit policy SSE propagation to SDK clients: policies set or deleted via the CLI or dashboard are now broadcast over the Waygate Server's SSE stream as typed
rl_policyenvelopes and applied to every connected SDK client in real time — no restart required. WaygateSDKauto-login (username/passwordparams): pass credentials directly toWaygateSDKinstead of a pre-issued token; on startup the SDK callsPOST /api/auth/loginwithplatform="sdk"and caches the resulting long-lived token for the life of the process — no manual token management required.- Separate SDK token lifetime (
sdk_token_expiry):WaygateServerandWaygateAdminnow acceptsdk_token_expiry(default 1 year) independently fromtoken_expiry(default 24 h for dashboard / CLI users), so service apps can run indefinitely without re-authentication while human sessions remain short-lived. platformfield onPOST /api/auth/login: the login endpoint now accepts"cli"(default) or"sdk"in the request body;"sdk"tokens usesdk_token_expiryand are intended for machine-to-machine service authentication.
0.7.0¶
Added¶
engine.sync— synchronous proxy for sync route handlers and background threads: every async engine method (enable,disable,set_maintenance,schedule_maintenance,set_env_only,enable_global_maintenance,disable_global_maintenance,set_rate_limit_policy,delete_rate_limit_policy,reset_rate_limit,get_state,list_states,get_audit_log) is now mirrored onengine.syncusinganyio.from_thread.run(), the same mechanism the waygate decorators use internally. Useengine.sync.*from plaindefFastAPI handlers (which FastAPI runs in a worker thread automatically) and background threads — no event-loop wiring required.- Env-gate management from dashboard and CLI: routes can now have their environment gate set or cleared at runtime — without redeployment — via the dashboard "Env Gate" button (opens an inline modal) and the new
waygate env set/waygate env clearCLI commands. - Global rate limit (
engine.set_global_rate_limit): a single rate limit policy applied across all routes with higher precedence than per-route limits — checked first, so a request blocked globally never touches a per-route counter. Supports all key strategies, burst allowance, and per-route exemptions (exempt_routes). Configurable from the dashboard Rate Limits page and the newwaygate grlCLI command group (get,set,delete,reset,enable,disable). - Global rate limit pause / resume (
engine.disable_global_rate_limit/engine.enable_global_rate_limit): suspend enforcement without removing the policy, then resume it later. Per-route policies are always unaffected.
Documentation¶
- Updated docs and README framework support section; added Adapters overview page.
0.6.0¶
Fixed¶
- OpenAPI schema stale across Gunicorn workers (
RedisBackend): route filtering in/docs//redocwas inconsistent and the global maintenance banner never appeared after changes made by another worker. The_run_global_config_listenertask was invalidating the in-process config cache but not bumping_schema_version, so the OpenAPI schema cache on receiving workers never expired. A newwaygate-route-state-listenerbackground task now bumps_schema_versionon every remote route state change too, ensuring all workers rebuild their schema on the next/openapi.jsonrequest. RedisBackendcrashes with "attached to a different loop" / "Event loop is closed" after worker restart:ConnectionPoolwas created once at__init__time and shared for the process lifetime; after a gunicorn worker recycle oruvicorn --reload, all Redis calls failed because the pool's internal futures were bound to the replaced event loop. Fixed by replacing the single shared pool with a per-event-loop pool dict (dict[id(loop), (weakref.ref(loop), pool)]): pools are now created lazily on first use within each event loop and dead entries are pruned automatically when the loop is GC'd.
0.5.0¶
Fixed¶
- Rate limit policies not synced across workers (
RedisBackend): updating a policy via the admin API or CLI only updated the in-process dict of the worker that handled the request. Other workers continued enforcing the old (decorator-declared) limit until restart. Fixed by adding awaygate:rl-policy-changeRedis pub/sub channel, everysetanddeletenow broadcasts the change to all instances, which apply it to their local_rate_limit_policiesdict immediately via a new background listener task (waygate-rl-policy-listener), mirroring the existingwaygate:global_invalidatepattern. - Rate limit policies reverted to decorator defaults on restart (
WaygateRouter):register_waygate_routes()calledrestore_rate_limit_policies()(viaregister_batch) before re-registering decorator-declared policies, so persisted admin/CLI updates were immediately overwritten on every app startup. Fixed by registering decorator policies first and runningrestore_rate_limit_policies()last, consistent with the order already used byscan_routes(). RedisRateLimitStorage.reset()blocked the event loop: the underlyinglimitslibrary exposes a synchronous Redis client; calling.scan()and.delete()directly insideasync def reset()stalled the event loop during every admin reset and routeenable()call. Fixed by offloading the SCAN + DELETE loop toasyncio.to_thread().enable()reset rate limit counters with seven sequential calls: afor _method in (…)loop called_rate_limiter.reset()once per HTTP method. Replaced with a singlereset_all_for_path()call (method=None), which is the existing one-shot API onWaygateRateLimiter.
0.4.0¶
Added¶
- Mobile & tablet responsive dashboard: all four tables (Routes, Audit, Rate Limits, Blocked) transform into stacked cards on screens narrower than 640 px using a CSS-only card layout with
data-labelattributes. Action buttons collapse to icon-only on small screens. - Back-to-top button: fixed button appears at the bottom-right after scrolling 200 px; hidden at the top.
- Success toast notifications: 2.5 s toast appears after any mutating action (enable, disable, maintenance, schedule, rate limit edit/reset/delete).
Changed¶
- CLI table pagination:
waygate status,waygate log,waygate rl list, andwaygate rl hitsnow support--pageand--per-page(default 20) instead of a flat--limit; a footer shows the current slice and the next/prev page flag to run. Thewaygate logstatus column now combines old and new state into a singleold > newcell and shows a coloured label for rate limit audit actions. Thewaygate rl hitstable drops theKeyandMethodcolumns in favour of a singlePathcolumn showingMETHOD /route. @env_onlynow returns 403 with JSON: env-gated routes blocked by the wrong environment return403 ENV_GATEDwithcurrent_env,allowed_envs, andpathinstead of a silent empty 404.- Tailwind CSS v3 → v4: replaced
tailwind.config.jswith a CSS-first config ininput.css(@import "tailwindcss",@source,@theme). Dashboard CSS is pre-built and committed; no Node.js required at install time. - No CDN dependency:
waygate.min.cssis now served as a local static file instead of the Tailwind CDN script, eliminating the production warning and removing the runtime network dependency.
0.3.0¶
Added¶
- Rate limiting (
@rate_limit): per-IP, per-user, per-API-key, and global counters with fixed/sliding/moving window algorithms. Supports burst allowance, tiered limits ({"free": "10/min", "pro": "100/min"}), exempt IPs/roles, and customon_missing_keybehaviour. Works as both a decorator and aDepends()dependency. Responses includeX-RateLimit-Limit/Remaining/ResetandRetry-Afterheaders. Requireswaygate[rate-limit]. - Rate limit custom responses:
response=on@rate_limitandresponses["rate_limited"]onWaygateMiddlewarefor replacing the default 429 JSON body with any StarletteResponse. - Rate limit dashboard:
/waygate/rate-limitstab showing registered policies with reset/edit/delete actions;/waygate/blockedpage for the blocked requests log. Policies can also be managed via thewaygate rlCLI commands (list,set,reset,delete,hits). - Rate limit audit log: policy changes (
set,update,reset,delete) are recorded in the audit log alongside route state changes, with coloured action badges in the dashboard. - Rate limit storage:
MemoryRateLimitStorage,FileRateLimitStorage(in-memory counters with periodic disk snapshot), andRedisRateLimitStorage(atomic Redis counters, multi-worker safe). Storage is auto-selected based on the main backend. - Custom responses for lifecycle decorators:
response=on@maintenance,@disabled, and@env_only;responses=dict onWaygateMiddlewarefor"maintenance","disabled", and"env_gated"states. @deprecatedasDepends(): injectsDeprecation,Sunset, andLinkheaders directly without requiring middleware.- Webhook deduplication:
RedisBackendusesSET NX EXto ensure only one instance fires webhooks per event in multi-instance deployments. Fails open on Redis error. - Distributed global maintenance:
RedisBackendpublishes towaygate:global_invalidateon everyset_global_config()call so all instances drop their cached config immediately. - Distributed Deployments guide (
docs/guides/distributed.md): backend capability matrix, global maintenance cache invalidation, scheduler behaviour, webhook dedup, and production checklist.
Changed¶
- Default
WAYGATE_ENVchanged from"production"to"dev". SetWAYGATE_ENV=productionexplicitly in production deployments. @deprecatedand all blocking decorators now supportDepends()in addition to the decorator form.
0.2.0 — Admin Redesign & Docs¶
Added¶
Admin & Dashboard¶
WaygateAdmin: unified admin interface combining the HTMX dashboard UI and the REST API under a single mount point- REST API under
/api/for programmatic route management (enable, disable, maintenance, schedule, audit, global maintenance) - Token-based authentication with HMAC-SHA256 signing
- Support for single user, multiple users, and custom
WaygateAuthBackendauth backends - Automatic token invalidation when credentials change (auth fingerprint mixed into signing key)
HttpOnlysession cookies for dashboard browser sessions- HTMX dashboard with SSE live updates, audit log table, and login page
- Platform field in audit log entries (
"cli"/"dashboard")
CLI¶
waygateCLI redesigned as a thin HTTP client over theWaygateAdminREST APIwaygate login/waygate logout,waygate status,waygate enable,waygate disable,waygate maintenance,waygate schedule,waygate logwaygate globalsubcommands: enable, disable, status, exempt-add, exempt-removewaygate config set-urlandwaygate config show- Cross-platform config file at
~/.waygate/config.json - Server URL auto-discovery via
WAYGATE_SERVER_URLenv var,.waygatefile, or config file
Documentation¶
- MkDocs Material documentation site with full tutorial, reference, guides, and adapter sections
Changed¶
- CLI no longer accesses the backend directly; all operations go through the REST API
- Custom auth header changed from
Authorization: BearertoX-Waygate-Token WaygateDashboardretained for backward compatibility;WaygateAdminis now the recommended entry point
0.1.0 — Initial Release¶
Added¶
Core¶
RouteStatus,MaintenanceWindow,RouteState,AuditEntryPydantic v2 modelsWaygateException,MaintenanceException,EnvGatedException,RouteDisabledExceptionWaygateBackendABC with full contractMemoryBackend: in-process dict withasyncio.QueuesubscribeFileBackend: JSON file viaaiofileswithasyncio.LockRedisBackend:redis-pyasync with pub/sub for live dashboard updates in multi-instance deploymentsWaygateEngine:check,register,enable,disable,set_maintenance,set_env_only,get_state,list_states,get_audit_log- Fail-open guarantee: backend errors are logged; requests pass through
MaintenanceScheduler:asyncio.Task-based scheduler that auto-activates and auto-deactivates maintenance windows- Webhook support:
add_webhook()andSlackWebhookFormatter
FastAPI adapter¶
@maintenance,@disabled,@env_only,@force_active,@deprecateddecoratorsWaygateRouter: drop-inAPIRouterreplacement with startup registration hookWaygateMiddleware: ASGI middleware with structured JSON error responses andRetry-Afterheader@deprecated: injectsDeprecation,Sunset, andLinkresponse headersapply_waygate_to_openapi: runtime OpenAPI schema filteringsetup_waygate_docs: enhanced/docsand/redocwith maintenance banners- Global maintenance mode:
enable_global_maintenance,disable_global_maintenance,get_global_maintenance
Dashboard (original)¶
- HTMX dashboard with SSE live updates and HTTP basic auth via
WaygateDashboard - Route list with status badges, enable/maintenance/disable actions per route
- Audit log table
CLI (original)¶
waygateCLI with direct backend accesswaygate status,waygate enable,waygate disable,waygate maintenance,waygate schedule,waygate log