Observing policy and operational constraints
Two related concepts work together to decide whether a telescope is allowed to take an observation:
OperationalConstraintrecords define individual gates (weather must be acceptable, sun must be down, battery must be charged, storage must not be full, …). Each constraint has a current status snapshot.ObservingPolicyrecords bundle the constraints, batching rules, and other operational rules that a queue or grant should follow.
A given observation is eligible to run only when every constraint referenced by the applicable policy reports OK.
Operational constraints
Constraints are polymorphic — each kind has its own concrete class and its own logic for evaluating "OK now?" against current telemetry.
| Constraint type | What it gates on |
|---|---|
BatteryConstraint |
Battery state of charge on the SkyNode host |
StorageConstraint |
Free disk space on the SkyNode host |
SunAltitudeConstraint |
Sun's altitude relative to a configured threshold |
WeatherSensorConstraint |
Reading from a weather sensor (cloudiness, wind, rain, humidity, …) crossing a configured threshold |
MountSunSeparationConstraint |
Angular separation between the mount's current pointing and the sun |
Custom OperationalConstraint subclasses |
Future additions |
Constraints live at two scopes:
- Observatory-level — apply to every telescope at the observatory. Typical example: a single weather-sensor reading controlling go/no-go for all telescopes under one dome.
- Telescope-level — apply only to that telescope. Telescope-level layers on top of observatory-level; both must pass.
Each constraint has an OperationalConstraintStatusSnapshot that
SkyNode updates continuously. If a constraint is failing right now,
the status snapshot tells you exactly which threshold was crossed and
when.
Shutdown interlocks
A ShutdownInterlock is a stronger version of a constraint: when
fired, it forces an immediate safe-shutdown (close enclosure, park
mount) rather than simply blocking new observations. They exist for
events that mean "stop now, don't wait for the current task to
finish" — rain detected, dome jammed, hardware tripped.
Configure interlocks conservatively. The cost of an unnecessary shutdown is one missed night; the cost of a missed interlock can be much higher.
Observing policy
An ObservingPolicy wraps a set of operational constraints with the
operational rules that decide how observations on a given queue are
batched, retried, and scheduled. Queues reference a policy; policies
reference constraints.
This indirection lets you reuse the same policy across multiple queues (typical: all of a telescope's research queues share the research-tier policy; the maintenance queue gets its own permissive policy that ignores most constraints).
Editing policy in the web app
The owner-facing surface lives at
org-settings-observing-policy.tsx
in the React port. There you can:
- View current constraint statuses.
- Edit constraint thresholds.
- Add or remove constraints from a policy.
- Force-clear a constraint in case of a stuck sensor or known false positive (use sparingly).
The Angular site has the equivalent under
apps/website/src/app/features/entity/settings/observing-policy/.
In the API, policies are managed through the observing_policies
router; constraints and snapshots are managed through
operational_constraints and constraint_snapshots.
Reference
ObservingPolicy Schema
Properties
| Name | Type | Description |
|---|---|---|
| id | Integer |
No description |
| name | String(100) |
No description |
| description | String(Unbounded) (Optional) |
No description |
| allowed_data_policies | ARRAY |
No description |
| data_public_after | INTERVAL (Optional) |
No description |
| allowed_target_position_types | ARRAY (Optional) |
No description |
| allowed_coordinate_types | ARRAY (Optional) |
No description |
| allowed_catalog_object_types | ARRAY (Optional) |
No description |
| allow_hidden_observation | Boolean |
No description |
| allow_hidden_telemetry | Boolean |
No description |
| allowed_request_types | ARRAY |
No description |
| organization_id | Integer |
No description |
Relationships
| Relationship Name | Type |
|---|---|
| organization | Organization |
| observing_accounts | ObservingAccount |
| observing_queue_access_grants | ObservingQueueAccessGrant |
OperationalConstraint Schema (Abstract Base)
Properties
| Name | Type | Description |
|---|---|---|
| id | Integer |
The unique identifier for the constraint. |
| uid | UUID |
No description |
| constraint_type | Enum(weather_sensor, storage, battery, camera_temperature, sun_altitude, mount_sun_separation) |
No description |
| owner_id | Integer |
The organization or user which owns the constraint. |
| is_active | Boolean |
No description |
| min_value | Float (Optional) |
No description |
| max_value | Float (Optional) |
No description |
| stability_threshold | Integer |
Amount of time in seconds the constraint must be stable before it is considered valid |
| max_data_age | Integer |
How long in seconds the constraint can go without an update before it is considered invalid |
| last_modified | DateTime |
Timestamp of the most recent update to the constraint |
| is_deleted | Boolean |
Flag indicating whether the constraint has been deleted |
| observatory_id | Integer |
The observatory/site safety boundary for this constraint. |
| telescope_id | Integer (Optional) |
Optional telescope context for telescope-specific constraints. |
Relationships
| Relationship Name | Type |
|---|---|
| owner | Entity |
| observatory | Observatory |
| telescope | Telescope |
| actions | OperationalConstraintAction |
| states | OperationalConstraintStatusSnapshot |
Subclasses
| Name | constraint_type |
|---|---|
WeatherSensorConstraint |
weather_sensor |
StorageConstraint |
storage |
BatteryConstraint |
battery |
SunAltitudeConstraint |
sun_altitude |
MountSunSeparationConstraint |
mount_sun_separation |
OperationalConstraintStatusSnapshot Schema
Description: Timeseries of operational constraint evaluations.
Properties
| Name | Type | Description |
|---|---|---|
| constraint_id | Integer |
No description |
| timestamp | DateTime |
No description |
| data | JSONB |
No description |
Relationships
| Relationship Name | Type |
|---|---|
| constraint | OperationalConstraint |
ShutdownInterlock Schema
Properties
| Name | Type | Description |
|---|---|---|
| id | Integer |
No description |
| uid | UUID |
No description |
| owner_id | Integer |
No description |
| scope_type | Enum(telescope, observatory) |
No description |
| telescope_id | Integer (Optional) |
No description |
| observatory_id | Integer (Optional) |
No description |
| name | String(255) |
No description |
| reason | String(1024) (Optional) |
No description |
| is_enabled | Boolean |
No description |
| starts_at | DateTime (Optional) |
No description |
| expires_at | DateTime (Optional) |
No description |
| last_modified | DateTime |
No description |
| is_deleted | Boolean |
No description |
Relationships
| Relationship Name | Type |
|---|---|
| owner | Entity |
| telescope | Telescope |
| observatory | Observatory |