Enterprise CORS allow-list
This document publishes the canonical set of browser origins that AseptSoft's single-page application (SPA) is served from. An AseptSoft API backend must permit these origins in its CORS configuration so the SPA can call it from a browser.
It is the single source of truth for that origin set. Managed AseptSoft backends consume it automatically (see Managed regions); self-hosting administrators are responsible for applying it to their own reverse-proxy or ingress (see Self-host configuration).
- Maintained at:
admin-docs/enterprise-cors-allowlist.mdin the AseptSoft repository — the authoritative source copy. - Intended publish location: https://docs.aseptsoft.ch/enterprise/cors-allowlist — the docs-site publishing pipeline is pending (tracked as a separate work item); until it lands, the repository copy above is authoritative.
- Current version:
2026q2.
Canonical allow-list (V1 — version 2026q2)
The V1 canonical origin set is:
https://app.aseptsoft.ch
https://app-ch.aseptsoft.ch
https://app-eu.aseptsoft.ch
https://app-us.aseptsoft.ch
https://app-ap.aseptsoft.ch
| Origin | Purpose |
|---|---|
https://app.aseptsoft.ch |
Shared SPA host — the canonical bookmark target. |
https://app-ch.aseptsoft.ch |
Switzerland-region SPA host alias. |
https://app-eu.aseptsoft.ch |
EU-region SPA host alias. |
https://app-us.aseptsoft.ch |
US-region SPA host alias (reserved; not yet deployed). |
https://app-ap.aseptsoft.ch |
APAC-region SPA host alias (reserved; not yet deployed). |
All five origins are published from V1 even though app-us and app-ap are not
deployed until customer demand triggers those regions. Publishing the full set
up-front means a region rollout never requires a synchronised allow-list bump on
already-deployed backends.
As a comma-separated value — the form the Cors__AllowedOrigins environment
variable expects:
https://app.aseptsoft.ch,https://app-ch.aseptsoft.ch,https://app-eu.aseptsoft.ch,https://app-us.aseptsoft.ch,https://app-ap.aseptsoft.ch
Applied CORS policy
An AseptSoft API serves these origins with the following CORS policy:
- Allowed origins: exactly the set above — never a
*wildcard. - Allowed methods: any method.
- Allowed headers: any header.
- Exposed headers:
ETag,Location(Access-Control-Expose-Headers) — the response headers browser JavaScript is permitted to read.ETagbacks conditional reads (If-None-Match→304) andLocationcarries the URL of a freshly created resource (201responses). These must be enumerated explicitly: anAccess-Control-Expose-Headers: *wildcard is treated as the literal header name*when credentials are allowed, so it would expose nothing. - Credentials: allowed (
Access-Control-Allow-Credentials: true) — the SPA sends a session bearer, so credentialed CORS is required. Credentialed CORS is incompatible with a*origin wildcard; this is why the allow-list is explicit. - Preflight cache:
Access-Control-Max-Age: 600(10 minutes) — caps preflight chatter on steady-state hot-path traffic.
A preflight OPTIONS request from an origin not on the list returns success
with no Access-Control-Allow-Origin header, so the browser blocks the call.
This is fail-closed: an unknown origin is rejected, never silently allowed.
Who needs this
Managed regions (automatic)
AseptSoft-managed backends — the Personal cloud regions and Enterprise-managed
deployments — consume this allow-list automatically. The set is the default
of the personalCorsOrigins[] Bicep parameter in infra/region/main.bicep,
which the per-region deployment flows into the API Container App as the
Cors__AllowedOrigins environment variable. No administrator action is required;
a deployment refresh propagates any future change.
Self-host backends
Self-hosting administrators own their CORS posture. AseptSoft does not — and cannot — configure CORS on a backend it does not operate. Read this document, then apply the allow-list to your reverse-proxy or ingress as shown in Self-host configuration.
Security caveats
- The allow-list is the SPA origin set, not an authorisation boundary. CORS governs which browser origins may issue cross-origin calls; it is not a substitute for authentication or authorisation. Every API route still enforces its own auth.
- Never widen to
*. A wildcard origin is incompatible with credentialed CORS and would expose the API to any website. Always configure the explicit set. - Self-host admins are accountable for their own posture. If you self-host and also serve the AseptSoft SPA from a custom origin, add only that origin — do not remove or weaken the canonical entries unless you have retired the corresponding host.
- Do not echo the request
Originheader unconditionally. Some proxy recipes reflect whateverOriginarrives; combined withAllow-Credentials: truethat is equivalent to a wildcard. Match against the fixed list instead. - Treat removals as breaking changes. Removing an origin breaks every browser still loading the SPA from it. Honour the deprecation window.
Lifecycle and versioning
This document is versioned with a version: <year>q<quarter> header (currently
2026q2). Each revision carries a change log row.
Quarterly bump cadence
The allow-list is reviewed and, if needed, bumped once per quarter, aligned with AseptSoft's other published-key and published-set rotation cadences. New origins are appended at a quarter boundary. A bump that only adds origins is backwards-compatible — existing backends keep working until they pick up the new set on their next deployment refresh.
Deprecation window
When an origin must be removed, it enters a 6-month deprecation window before deletion:
- The origin is annotated in the change log with a
removal-date: <year>q<quarter>at least two quarters in the future. - It remains in the allow-list — and remains served — for the whole window.
- At the stated
removal-datethe origin is removed in that quarter's version bump.
Six months gives enterprise administrators time to plan, audit, and migrate any bookmarks or embedded links before a removed origin stops working.
Self-host configuration
Apply the canonical allow-list to whichever layer terminates browser traffic for your backend.
AseptSoft API — environment variable
If you run the AseptSoft API container directly, set the allow-list as a comma-separated environment variable. The API's built-in CORS policy reads it:
Cors__AllowedOrigins=https://app.aseptsoft.ch,https://app-ch.aseptsoft.ch,https://app-eu.aseptsoft.ch,https://app-us.aseptsoft.ch,https://app-ap.aseptsoft.ch
Azure Container Apps ingress
When deploying the API as an Azure Container App, set the same environment
variable on the container (az containerapp shown; Bicep / Terraform equivalent):
az containerapp update \
--name <your-api-app> \
--resource-group <your-rg> \
--set-env-vars \
'Cors__AllowedOrigins=https://app.aseptsoft.ch,https://app-ch.aseptsoft.ch,https://app-eu.aseptsoft.ch,https://app-us.aseptsoft.ch,https://app-ap.aseptsoft.ch'
Container Apps ingress itself does not need a separate CORS rule — the API process applies the policy. If you additionally place a CORS rule on the ingress, keep it identical to this list.
nginx reverse proxy
If a reverse proxy terminates TLS in front of the API, match the request
Origin against the fixed set — never reflect it blindly:
map $http_origin $aseptsoft_cors_origin {
default "";
"https://app.aseptsoft.ch" $http_origin;
"https://app-ch.aseptsoft.ch" $http_origin;
"https://app-eu.aseptsoft.ch" $http_origin;
"https://app-us.aseptsoft.ch" $http_origin;
"https://app-ap.aseptsoft.ch" $http_origin;
}
server {
location / {
if ($aseptsoft_cors_origin) {
add_header Access-Control-Allow-Origin $aseptsoft_cors_origin always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "*" always;
add_header Access-Control-Expose-Headers "ETag, Location" always;
add_header Access-Control-Max-Age "600" always;
}
if ($request_method = OPTIONS) {
return 204;
}
proxy_pass http://aseptsoft-api;
}
}
The map block resolves to an empty string for any unlisted origin, so the
Access-Control-Allow-Origin header is omitted and the browser blocks the call.
Change log
| version | change | removal-date |
|---|---|---|
2026q2 |
Initial publication. V1 canonical set: app, app-ch, app-eu, app-us, app-ap. |
— |