Platform architectureread it before you trust it

There is no black box in here.

Twenty-two services behind a single gateway, one database per service, and an event mesh between them. Every boundary on this page is one your reviewer can inspect on your own hardware.

Verified, not certified — every claim below names the check that produces it.

CLIENTS KONG · :8000 · ONE DOOR 22 SERVICES · ONE DATABASE EACH APACHE PULSAR EVENT MESH Operator console Next.js · browser · WebSocket Aircraft & docks MQTT · MAVLink · SRT Authority & partners REST · federated USS X-USER-ID · X-TENANT-ID · X-ROLES STRIPPED AT THE DOOR BEARER TOKEN PASSED THROUGH VERIFIED INSIDE EACH SERVICE auth-iam verifies every token · derives tenant flight-ops operations · conformance monitoring deconfliction F3548-21 · DSS client remote-id F3411 · SP + DP roles geofence ED-269 zone lifecycle evidence hash-linked audit trail no cross-service database access EventEnvelope one contract · canonical topics Asynchronous only publish and subscribe · never a table read Dead-letter topic bounded retries · the envelope survives 20 app services + 2 headless workers · Python 3.12 · FastAPI · async SQLAlchemy · one Alembic history each
Identity is derived, never received Kong strips X-User-ID, X-Tenant-ID and X-Roles. Each service verifies the bearer token itself.
No shared database Each service owns its schema and migrations. Integration is events, not table reads.

The shape of the system

22 Services behind one gateway 20 app services · 2 headless workers
1:1 Service to database separate schema · separate migrations
0 Identity headers trusted stripped at the boundary, always
RLS Tenant isolation in Postgres enforced under a non-owner role
The boundary

One door — and it does not believe what you tell it.

Every client reaches the platform through Kong on port 8000. Kong strips the identity headers a client might set, and it does not verify the token either. That second part is deliberate: verification happens inside each service, against the token, on every request.

As sent by the client
POST /api/v1/operations
Host: utm.example.gov:8000
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6…
X-User-ID: 3f2a-9c11-… stripped
X-Tenant-ID: ministry-ops stripped
X-Roles: platform_admin stripped
As the service receives it
POST /api/v1/operations
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6…
— identity headers are gone before routing
Identity, after the service verifies the token
sub · 3f2a-9c11 tenant · corniche-air roles · operator

The header claimed platform_admin and a different tenant. The verified token says operator at corniche-air. The service uses the token, because the header never arrives.

Removed, not merely ignored

X-User-ID, X-Tenant-ID and X-Roles are stripped at the gateway, so no service can receive them from outside. There is no configuration in which a forged header becomes an identity — the header simply is not there.

The gateway is not the authority

Kong routes, rate-limits and terminates TLS. It does not decide who you are. A gateway that both routes and authenticates becomes a single point of failure and a single point of trust at the same time.

Each service verifies the token itself

HS256 and RS256 with JWKS, in one shared library rather than twenty-two implementations. User, tenant and roles are derived from verified claims — never from transport, never from a trusted-network assumption.

Default deny is the backstop

Shared middleware refuses an unauthenticated request on any route that has not explicitly opted out. A newly added route is closed until somebody deliberately opens it, which is the opposite of the usual accident.

One honest caveat. The Docker Compose stack also publishes each service on a direct host port for development smoke tests. Those ports bypass the gateway, and they must not be exposed in production — the deployment guide says so, the production preflight checks it, and we would rather you read it here than find it yourself.


Tenancy

Row-level security — and the condition under which it does nothing.

Every tenant-scoped table carries a PostgreSQL row-level security policy. That is the easy half. The half most vendors leave out of the datasheet is that RLS does not apply to the role that owns the table.

Isolation off the failure mode

Connected as the database owner

The owner bypasses every policy. A tenant-scoped query returns every tenant's rows and nothing anywhere warns you. This is documented PostgreSQL behaviour, not a defect in the platform — which is precisely why it has to be designed against rather than assumed away.

SELECT … FROM operations2 431 rows
tenants represented9
Isolation enforced the required configuration

Connected as the application role

A non-owner role, provisioned by make db-setup after the migrations run. Policies apply on every read and every write. Cross-tenant reads and writes are covered behaviourally, so the isolation is a tested property rather than a diagram.

SELECT … FROM operations287 rows
tenants represented1
So the runtime refuses to start in the wrong one.

In production, if the application user is not set to the non-owner role, the preflight fails and the stack does not come up. A misconfiguration becomes an outage you notice at deploy time instead of a data leak you notice later.

scripts/production_preflight.py

POSTGRES_APP_USER must be the app role · fails closed when ENV is production

Why publish our own worst failure mode. Because a control you cannot inspect is a promise, not a control. If this page only said "multi-tenant with row-level security", you would have no way to tell whether the deployment in front of you actually enforces it. Now you know exactly which line to check.


Integration

Services do not read each other's databases.

One database per service, each with its own Alembic history. Services integrate by publishing onto an Apache Pulsar mesh under a shared EventEnvelope contract — never by reaching into another service's tables. It costs a little latency and buys the ability to change one service without a coordinated release of the other twenty-one.

flight-ops publishes operations.intent.v1 EventEnvelope · canonical topic deconfliction re-checks the volume evidence appends to the chain notifications tells the control room dead-letter topic bounded retries, then parked — replayable one publisher, any number of subscribers
One envelope

Every message carries event id, type, version, tenant and correlation id around its payload. A consumer can reject what it does not understand instead of guessing at it.

Canonical topics

Topic names come from a shared module, never a string literal in a handler. A typo becomes an import error at start-up rather than a subscription that is silently empty.

Failure is parked

Retries are bounded; what still fails lands on a dead-letter topic with the envelope intact, so it can be replayed once the consumer is fixed. Nothing is dropped quietly.

Migrations stay local

A schema change in one service cannot break another service's reads, because no other service reads it. That is the whole reason the databases are separate.


Deployment

Three modes. One codebase. The values file changes, not the platform.

An operator programme, a regulator and a national network run the same services with different surfaces enabled. There is no separate build, no "enterprise fork", and nothing you would have to migrate off if your remit grows.

Operator

Enterprise drone programmes
  • Plan → fly → prove, with SORA 2.5 and live conformance
  • Edge ingestion, video wall, fleet and crew management
  • Runs on your Kubernetes, or one Docker Compose host
PROFILE=operator

Authority

CAAs and ANSP innovation units
  • Approval workbench with jurisdiction rules and SLAs
  • ED-269 zone authoring and cross-operator supervision
  • Hash-linked audit trail with tenant-scoped export
PROFILE=authority

National

Country-scale programmes
  • DSS federation, Network Remote ID and CISP interfaces
  • Multi-authority delegation and cross-border workflows
  • Multi-region deployment with geo-replication values
PROFILE=national

Air-gapped is a first-class path, not a workaround.

The disconnected install is the same stack as the connected one. Images come from your private registry, licences are signed and verified locally, and nothing calls home to stay running — so a vendor outage cannot switch a control room off. What you give up is listed plainly in the air-gapped playbook, because there is a real list.

Container imagesPrivate registry mirror
Licence verificationSigned · offline · no phone-home
Map and terrain dataSeeded tiles, held locally
Local AI modelsWeights shipped in the bundle
UpdatesStaged bundles with rollback

Conformance

What is implemented, and how you check it yourself.

No independent conformance scheme for UTM platforms exists in most jurisdictions today. Be wary of anyone who implies otherwise. What we publish instead is the scope of each implementation, the maturity label it honestly carries, and the command that regenerates its evidence on your own stack.

Standards ledger — dated runs, or an explicit cadence. Never a vague claim.
Standard What is implemented How it is evidenced Status
ASTM F3548-21 Strategic deconfliction: operational-intent sharing, conflict detection and constraint awareness against a real DSS. InterUSS qualifier suites pass with zero findings above Low severity. make uss-qualifier · 2026-06-10 GA
ASTM F3411 v19 / v22a Network Remote ID in both the Service Provider and Display Provider roles, on one deployment. Verified by the same qualifier run against the reference DSS. make uss-qualifier · 2026-06-10 GA
JARUS SORA 2.5 Full ground and air-risk methodology with the complete SAIL table. The go/no-go it produces is advisory — a human still approves. Behaviourally pinned, not a lookup stub. SAIL matrix suite · every CI run Beta
EUROCAE ED-269 Geographical-zone lifecycle: authoring, versioning, activation windows and publication, validated against the ED-269 model. Schema contract tests; the official schema gate is a licensed capability. ED-269 schema suite · every CI run Beta
EU 2021/664 U-space Mandatory U-space service coverage across the platform capability set, including traffic information. Capability contract tests. Field experience is still narrow — hence the label. capability suite · every CI run Beta
ASTM F3548-21 ASTM F3411 JARUS SORA 2.5 EUROCAE ED-269 EU U-space Verified, not certified.

Day two

The part that decides whether it survives a year.

Anyone can demonstrate a platform on a good day. These are the properties your infrastructure team will ask about in the second meeting, and the reason they usually say yes.

Observability, in the chart

Prometheus, Grafana, Loki, Jaeger and SLO alerts ship inside the Helm chart rather than as a separate project you have to assemble. A correlation id issued at the gateway follows the request through every service log and every span.

/healthz liveness · /readyz readiness · uniform error envelope

Backups you have actually restored

Scheduled backups are unremarkable; a restore nobody has rehearsed is a story you tell an inquiry. Restore drills run in CI, and CloudNativePG with point-in-time recovery is available on the high-availability path.

restore drill in CI · PITR on the HA path

Your identity provider, not ours

OIDC federation to the IdP you already run, with roles mapped by allowlist rather than by whatever a token happens to assert. There is no vendor-hosted account directory and no shadow set of users to deprovision separately.

OIDC SSO · allowlist role mapping

Licences that verify offline

Licences are signed and validated locally. The platform never calls a licence server to keep running, which is what makes air-gapped operation ordinary rather than exceptional — and what stops a vendor outage from becoming your outage.

signed offline licences · no phone-home
Capability catalogue

Everything it does, and how far along each part is.

Maturity is a column here, not a footnote. A feature page that renders 18 identical ticks converts better than this one and tells you less than nothing — you would learn what we chose to name, not what you can rely on next month.

What the labels mean

GA

Running in production, behaviourally tested, supported. Build on it.

Beta

Implemented and exercised; test coverage is structural rather than behavioural. Usable, worth verifying against your own case.

Preview

Partially implemented. Do not build a compliance argument on it.

Planned

Nothing is running behind it. Listed so you can plan, not so the page looks fuller.

Airspace and deconflictionThe standards path
Strategic deconfliction

ASTM F3548-21 operational intents checked against other intents, geozones and active NOTAMs, with the coverage of each check reported alongside the result.

GA
Remote ID traffic

ASTM F3411 network Remote ID and ADS-B In, with per-contact source and age. Broadcast RID needs a ground receiver that is not part of the platform.

GA
Geozone authoring and evaluation

ED-269 zones with geometry, vertical extent, recurring schedules and legal basis, enforced at planning time.

Beta
Federated USS peering

The DSS client exists, is independently qualified, and the integration points are built. No deployment ships federated with a peer, so deconfliction is scoped to one installation until you configure an endpoint.

Preview
Non-cooperative detection

The sensor registry and track ingest accept radar, RF, optical and acoustic sources, but no adapter ships to feed them. Aircraft that do not broadcast are not detected by any means.

Planned
OperationsThe day the operator actually has
Mission planning and approval

Route, volume and schedule, through a review workflow that records who approved what and against which assessment.

GA
Live map and telemetry

Positions over your own tile server, streamed over the gateway's websocket. No third-party basemap call is required.

GA
Fleet, sites and assets

Aircraft, docks, payloads and batteries, created by hand or synchronised from a vendor — with the provenance of each recorded rather than inferred.

GA
Drone-as-first-responder dispatch

Alert intake to launch proposal, with pre-flight rejections stated in plain terms rather than as error codes. Built and navigable; not yet validated against a live incident feed.

Beta
Per-asset health telemetry

Battery cycles, motor and link health per airframe. Vendor health snapshots exist for DJI fleets; there is no vendor-neutral per-asset health model yet.

Planned
Compliance and evidenceWhat survives an audit
Audit trail

Actor, tenant, correlation id and source service for every state change, consumed from the event mesh rather than written by the code that made the change.

GA
SORA 2.5 risk assessment

GRC and ARC with mitigations, SAIL derivation, the 24-objective matrix and the tactical mitigation check. Records what each objective requires; it does not attest that you met it.

Beta
Evidence archive

Flight records, video and decisions retrievable together against an incident rather than scattered across three systems.

Beta
PlatformWhat makes the rest defensible
Self-hosted, single host or Kubernetes

Compose for one machine, Helm for a cluster. No control plane we operate and no account we hold.

GA
Multi-tenancy with database-enforced isolation

PostgreSQL row-level security bound to a non-owner application role, so a query missing its tenant filter returns nothing.

GA
Single sign-on

OIDC against your identity provider, with role mapping by allowlist. SAML is not implemented, and an identity whose group matches no mapping receives the configured default role rather than no access.

Beta
Outbound event subscriptions

Signed webhooks with durable retries and encrypted secrets, for pushing events into your own systems.

Beta
AI detection and incident summarisation

Runs as a separate agent and is not part of the base install, and it ships disabled. On most deployments the AI screen’s primary state is "not installed", and it says so.

Preview
4 of the 18 rows above are Preview or Planned. Leaving them off would make this section shorter and the product look more finished. They are here because the alternative is a customer discovering the same 4 facts after signing — which costs everyone more than a slightly less impressive page does.

Give this page to your security reviewer.

The evaluation pack is the installer we ship to production, the architecture notes behind everything above, and the conformance suites you can re-run without asking us for permission.

No vendor account. No phone-home. Thirty days of the full tier on your own hardware.