You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
`relay.audit.retention_local_only` fires when the audit sink is a local rotating `file` sink and `evidence.audit_offhost_shipping` is not declared: a local rotating file caps retention, and an attacker with host access can destroy the audit trail. `stdout` sinks are exempt (retention is the orchestrator's log pipeline's concern) and `syslog` sinks are exempt (forwarding is the syslog daemon's own surface).
1412
1413
1413
1414
`relay.audit.shipping_unverified` and `relay.audit.shipping_stale` read the ack cursor's observed health. `shipping_unverified` fires when any shipping target (`stdout`, `syslog`, or an attested local `file` sink) lacks `evidence.audit_ack_cursor_path`. It warns under `production` and refuses startup under `evidence_grade`, because a missing observation capability cannot heal at runtime. `shipping_stale` fires when a cursor is configured but is missing, unreadable, malformed, too old, too slow to read, or names a `last_acked_hash` other than the live keyed audit-chain tail. It fails readiness under `evidence_grade` and recovers when the trusted shipper advances a fresh cursor to the current tail. Neither hard gate is waivable. Runtime tail equality establishes that the claimed watermark belongs to this chain and the local backlog is zero; the unsigned local cursor is not cryptographic proof of remote receipt. Offline `doctor` cannot bind to a live chain and therefore reports a fresh cursor as `unverified`, never `ok`; an evidence-grade offline check consequently reports the hard shipping gate. The signed-bundle acceptance audit advances the tail before Relay serves requests, so the shipper must run independently of application readiness and acknowledge that boot record before `/ready` can return 200. Remediation: configure the cursor maintained by the off-host shipper, restore shipping, adjust `evidence.audit_ack_max_age_secs` if the cadence is legitimately slower, or repair a path or watermark mismatch. Removing the cursor does not satisfy `evidence_grade`.
1414
1415
1416
+
`relay.aggregates.privacy_budget_untracked` fires when a dataset classified `personal`, `confidential`, or `secret` has a dataset-level aggregate with `access.aggregate_only_execution: true`. Only dataset-level declarations count: they are the only ones the aggregate query routes serve, so table-level and entity-level declarations raise no finding. Aggregate routes apply per-result minimum cell-size suppression (`disclosure_control.min_cell_size`), but track no longitudinal query budget: `query_budget.tracked` is always false. This is a documented, accepted limitation, not a fixable misconfiguration, so it warns at every bound profile, including `evidence_grade`, rather than blocking startup or readiness. Leaving the finding active is a legitimate steady state that keeps the posture honest; a deployment waiver naming the finding records a dated operator acknowledgement instead, at the cost of re-issuing the waiver whenever it expires. See "Aggregates are not privacy-budgeted" in [Known limitations and non-guarantees](https://docs.registrystack.org/explanation/known-limitations/).
1417
+
1415
1418
The current deployment profile, its findings, and active waivers are reported under `deployment` in the operations posture (`GET /admin/v1/posture`).
1416
1419
1417
1420
### Boot-time visibility
1418
1421
1419
-
Reduced posture is loud at boot, not only visible on the posture surface. Every config load warns once per waiver-suppressed finding (`deployment.gate_waived`, with the finding id, reference, optional summary, and expiry), once per expired waiver (`deployment.waiver_expired`), and once when the profile is undeclared (`deployment.profile_undeclared`). The serve path additionally writes one operational audit record per waived gate at boot, once the audit pipeline exists: event `deployment.gate_waived` at audit path `/__events/deployment.gate_waived`, with `error_code` set to the gate id. That minimized audit record does not copy waiver metadata.
1422
+
Reduced posture is loud at boot, not only visible on the posture surface. Every config load warns once per waiver-suppressed finding (`deployment.gate_waived`, with the finding id, reference, optional summary, and expiry), once per expired waiver (`deployment.waiver_expired`), and once when the profile is undeclared (`deployment.profile_undeclared`). A sensitive dataset's aggregate-only-execution aggregate additionally warns once per config load with `deployment.privacy_budget_untracked`, naming the finding id; a waived occurrence is reported through the generic `deployment.gate_waived` line instead, not a duplicate line. The serve path additionally writes one operational audit record per waived gate at boot, once the audit pipeline exists: event `deployment.gate_waived` at audit path `/__events/deployment.gate_waived`, with `error_code` set to the gate id. That minimized audit record does not copy waiver metadata.
1420
1423
1421
1424
This boot-time audit write inherits `audit.write_policy` (see below). Under `fail_closed` (the default), a failed write aborts startup. Under `availability_first`, the failure is logged (`audit.operational_event_write_failed`) and startup continues, so the durable record is best-effort; the per-gate boot log warnings above remain the guaranteed floor.
1422
1425
@@ -1735,6 +1738,8 @@ aggregates:
1735
1738
1736
1739
Supported aggregate functions include the configured V1 set used by tests and examples, such as `count`, `sum`, and `avg`. The runtime config key remains `indicators` for compatibility; public aggregate APIs expose these configured series as measures. `temporal_field` is optional; when present, native aggregate `temporal.from` and `temporal.to` are translated into the declared range-capable allowed filter for that source-entity field. Dataset measure and dimension discovery is derived from these aggregate declarations, so keep ids stable and labels consumer-friendly. Keep disclosure thresholds explicit and reviewable.
1737
1740
1741
+
`disclosure_control`and `access.aggregate_only_execution` bound per-result minimum cell-size suppression on a single query; they do not track a longitudinal query budget across repeated aggregate queries. On a `personal`, `confidential`, or `secret` dataset, a dataset-level `aggregate_only_execution` aggregate raises the `relay.aggregates.privacy_budget_untracked` deployment finding described in the findings catalog under "Deployment profile" above; see "Aggregates are not privacy-budgeted" in [Known limitations and non-guarantees](https://docs.registrystack.org/explanation/known-limitations/) for the underlying limitation.
1742
+
1738
1743
### Spatial EDR aggregates
1739
1744
1740
1745
Spatial EDR exposure is opt-in. Requires `--features ogcapi-edr`.
Copy file name to clipboardExpand all lines: crates/registry-relay/openapi/registry-relay.openapi.json
+10-4Lines changed: 10 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -1184,7 +1184,7 @@
1184
1184
"type": "array"
1185
1185
},
1186
1186
"claim_names": {
1187
-
"description": "Names of all claims that may be returned by this profile.",
1187
+
"description": "Top-level names of all claims that may be returned by this profile. Every released value is a scalar (string, number, or boolean).",
1188
1188
"items": {
1189
1189
"type": "string"
1190
1190
},
@@ -1268,7 +1268,7 @@
1268
1268
"description": "Request body for resolving an attribute release profile against one subject.",
1269
1269
"properties": {
1270
1270
"claims": {
1271
-
"description": "Optional subset of claim names to return. Absent means the profile default set; an empty array is rejected (400); duplicate or over-bound arrays are rejected (400); any explicit subset must include every required claim; any unknown claim name is denied.",
1271
+
"description": "Optional subset of claim names to return. Entries are whole top-level claim names; there is no sub-selection inside a claim value. Absent means the profile default set; an empty array is rejected (400); duplicate or over-bound arrays are rejected (400); any explicit subset must include every required claim; any unknown claim name is denied.",
1272
1272
"items": {
1273
1273
"type": "string"
1274
1274
},
@@ -1314,8 +1314,14 @@
1314
1314
"description": "Resolved attribute release claim bundle. Contains only the approved, minimised claims for the matched subject. Never includes raw source rows, subject identifiers outside released claims, or private source internals.",
1315
1315
"properties": {
1316
1316
"claims": {
1317
-
"additionalProperties": true,
1318
-
"description": "Released claim bundle. Keys are claim names; values are the projected or computed claim values.",
1317
+
"additionalProperties": {
1318
+
"type": [
1319
+
"string",
1320
+
"number",
1321
+
"boolean"
1322
+
]
1323
+
},
1324
+
"description": "Released claim bundle. Keys are top-level claim names; values are scalar-only in v1 (string, number, or boolean). Structured object or array values are never released: a claim whose projected or computed value is not a scalar is treated as unavailable, so a required claim of that shape denies the release and an optional one is omitted. Claim selection is by top-level claim name only; there is no sub-selection inside a claim value.",
0 commit comments