Skip to main content

Configuration

Everything the Settings screens write, they write through these routes. Zones and regions shape the ground; rules and doctrine decide what the system may do on it.

Zones​

A zone is a named, categorised, shaped area. Its category is what the system acts on: boundary is the geofence, keep_out is a solver hard constraint, jam and gps_denied degrade comms in simulation, free_fire is doctrine the rules read, isr_priority is a coverage objective, no_go and corridor steer navigation.

curl -X POST https://<your-backend-host>/api/zones \
-H "Content-Type: application/json" \
-d '{
"name": "tank farm keep-out",
"category": "keep_out",
"shape": { "shape": "circle", "center": [1.3521, 103.8198], "radius_m": 350 },
"band": { "ceiling_m": 120 }
}'
FieldRequiredTypeMeaning
nameyesstringShown on the map and in every rule firing that cites the zone.
categoryyesstringOne of the categories above.
shapeyesobjectTagged by shape: circle (center as [lat, lon], radius_m) or polygon (points, at least 3).
bandnoobjectVertical extent in metres above ground: floor_m, ceiling_m. Absent ends are open, so {} is every altitude.
region_idnostringScope to one region, or global when absent.
paramsnoobjectPer-category knobs: priority for ISR weight, strength for jam intensity.

GET /api/zones lists, PUT /api/zones/{id} replaces, DELETE /api/zones/{id} removes. Writes take effect in the running rules on the next tick; a keep-out drawn here is a keep-out the solver honours immediately. A 400 names the exact validation rule: empty name, non-positive radius, a polygon under three points, or an inverted altitude band.

Regions​

A region is a defended place: where the map centres and what a scenario runs over. GET/POST /api/regions, PUT/DELETE /api/regions/{id}, and PUT /api/workspace/default-region selects the one the console opens on. GET /api/meta returns the deployment's own description of itself: its regions and defaults in one response.

Sensors​

There is no sensor surface. A sensor is an asset: placed with POST /api/assets, listed with GET /api/assets?kind=sensor, and pointed with the same command call as everything else. See Assets & commands.

curl -X POST https://<your-backend-host>/api/assets/ast_c81b…/command \
-H "Content-Type: application/json" \
-d '{ "verb": "cue_sensor", "params": { "kind": "target", "track_id": "T-00492" } }'

curl -X POST https://<your-backend-host>/api/assets/ast_c81b…/command \
-H "Content-Type: application/json" \
-d '{ "verb": "cue_release", "params": { "kind": "none" } }'

GET /api/catalog/sensor-profiles lists the placeable profiles. A cue is a request: the sensor reports where it is actually looking, and the picture renders that report, not the request. Releasing is a verb rather than an absent parameter, because handing a latched mount back to arbitration is an act, and an act with no record of it cannot be arbitrated when two claims land on one camera.

Doctrine, rules and settings​

The decision loop runs the stored rule set, gated by the autonomy line and tuned by thresholds. Each has a small CRUD surface, and the whole of it exports as one document:

RoutesWhat they hold
GET/PUT/POST/PATCH/DELETE /api/rules, POST /api/rules/validate, GET /api/rules/libraryThe rule rows the loop runs, a validator for one row, and the shipped rule packs.
GET/PUT /api/thresholdsThe settings registry: every tunable key, its value, and where the value came from.
GET /api/decision-config, PUT /api/decision-config/autonomyThe engagement, identification, geography and alerting policies, and the one dial that moves the autonomy line.
GET/PUT /api/influenceOperator influence over the planner: pinned pairs and weights.
GET/PUT /api/planning-profilesThe profiles the planner authors one plan per pass for.
GET /api/strategiesThe compiled-in behaviour and solver strategy catalogues.
GET /api/doctrineEverything above, aggregated in one read.

The export is a versioned YAML document, and the import round-trips it:

curl https://<your-backend-host>/api/doctrine/export > doctrine.yaml
curl -X POST https://<your-backend-host>/api/doctrine/import \
-H "Content-Type: application/yaml" --data-binary @doctrine.yaml

That makes doctrine reviewable the way code is: exported, diffed, committed, and applied to another deployment. The same pattern covers the physical deployment: GET /api/settings/export returns every asset, link and sensor as one document, and POST /api/settings/import applies one (with "dry_run": true to see the report without writing).

curl https://<your-backend-host>/api/settings/export \
-H "X-Api-Key: $DOME_KEY" -H "X-Workspace-Id: $WORKSPACE" > site.json

curl -X POST https://<your-backend-host>/api/settings/import \
-H "Content-Type: application/json" \
-H "X-Api-Key: $DOME_KEY" -H "X-Workspace-Id: $WORKSPACE" \
-d "$(jq '. + {dry_run: true}' site.json)"

The document's own kind is AssetManifest, and stays that: it is a wire string, and files already committed carry it. The routes say what they do.

Secrets​

Credentials for integrations go into a write-only store: PUT /api/secrets/{name} stores a value, GET /api/secrets lists names and hints, DELETE removes one. There is deliberately no route that returns a value; a stored secret is referenced by name (secret://…) in integration config and resolved server-side. 503 means the store's encryption key is not configured on this deployment.