Skip to main content

The Control Plane

Everything so far runs on its own — orchestrations loop, timers fire, queues drain. But someone has to drive it: onboard a camera, change its rate, kick a stuck orchestration, manage who can see what. That's Alert.CA.Admin.API — an ASP.NET Core Web API (hosting the admin React SPA) that is the platform's control plane. The striking thing about it is what it doesn't do: it never calls the engine directly.

The one idea to hold on to​

The Admin API controls the engine indirectly, through shared state. To act on a camera it writes the intended state in Cosmos and lets the engine's change-feed trigger react; to observe a camera it reads the monitoring table. There is no RPC to the orchestrations.

"Kick this orchestration" is the cleanest example — it just bumps a timestamp:

// KickOrchestrationCommand
patchOperations.Add(PatchOperation.Set(nameof(AcquisitionDeviceEntity.LastUpdated), DateTimeOffset.UtcNow));
await _acquisitionDeviceRepository.PatchAsync(deviceId, patchOperations);

That Cosmos write is picked up by the engine's change-feed redeploy. And to show a camera's status, DurableEntityService reads GetLatestDurableEntityByDeviceId — the monitoring row — never the running entity. Write intent to Cosmos, read status from the mirror: that's the entire coupling between control plane and engine.

CQRS: thin controllers, handlers do the work​

The API is split into two projects on the CQRS pattern. Alert.CA.Admin.API holds thin controllers that translate HTTP into commands and queries; Alert.CA.Admin.API.Application holds the MediatR handlers that actually do the work:

Every request flows through a MediatR AuditBehavior pipeline, so administrative actions are audited by construction rather than by remembering to log each one.

Gotcha: control actions are eventually-applied, not immediate

Because the Admin API acts by writing Cosmos and letting the change feed react, a "kick" or a config change returns success once the write lands — not once the orchestration has redeployed. There's a small propagation delay, and if the device is inactive or in another environment the engine skips it entirely (per the redeploy gating). Success from the API means "intent recorded," not "engine already reconfigured."

Wrapping up​

The Admin API is a CQRS ASP.NET Core control plane that drives the platform entirely through shared state — writing intended config to Cosmos (where the change feed turns it into a redeploy) and reading status from the monitoring mirror — with Entra/API-key auth and an audit pipeline on every action. It's powerful precisely because it stays decoupled from the engine's runtime.

The rest of this section walks the control surface, starting with the one it exists for — driving the engine. Next: Controlling the Engine.