The Query Surface
Movement, auth, and real-time are the parts with moving pieces. But most of the API is quieter and more numerous: "give me the cameras I can see," "the images for this camera and time range," "my notifications." These read endpoints are the bulk of what the frontend calls, and they all share one shape.
The one idea to hold on to
Every read endpoint is a thin CQRS query: controller → MediatR query → Infrastructure repo, returning a frontend-shaped DTO — not a raw storage entity. The controller decides the shape and the caller's scope; the handler fetches and maps. Because the mapping happens here, the frontend never couples to Cosmos or SQL models — it depends on the API's DTOs, and the storage schema can change underneath without breaking the app.
The read domains, each a Queries folder in the Application layer (reach for the source for the
exact query list rather than a catalog here):
| Controller | Answers |
|---|---|
Cameras · CameraFilters | Which cameras this user can see, and how they're filtered/grouped |
Images · VideoLibrary | Frames and clips for a camera and time range |
Alerts · Notifications | Active alerts and the user's notifications |
ActivityLog | Recent movement/activity per camera |
AiDetection | Condor detections surfaced to the operator |
SharedViews · User · FeatureFlags | Saved map views, user preferences, and flag state |
"Which cameras" is a user-scoped question — the camera queries filter to what the caller is allowed to see (the RBAC allow-list from the shared data layer). Don't assume a camera id in a URL is automatically authorized just because the request has a valid token; the scoping is in the query, so a new read endpoint has to apply the same filter or it will over-share. When adding a query, copy a scoped sibling.
Wrapping up
The query surface is the API's calm majority: many thin CQRS reads (and some commands) that map shared storage into frontend-shaped DTOs, keeping the app decoupled from the schema — with per-query scoping as the thing you must not forget when extending it. Together with movement, auth, and real-time, that's the whole backend-for-frontend.
Back to the overview: The Frontend's Backend.