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
Copy file name to clipboardExpand all lines: .agents/skills/debug-openshell-cluster/SKILL.md
+26Lines changed: 26 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -106,6 +106,30 @@ The middleware service must start before the gateway and be reachable from both
106
106
107
107
At request time, distinguish an explicit `middleware_denied` result from `middleware_failed`. A denial is always enforced. A failure follows the policy-local `on_error`: `fail_closed` blocks the request, while `fail_open` bypasses only that stage and emits a detection finding. If a running supervisor cannot install a new registry, it preserves its last-known-good generation and emits a configuration failure event.
108
108
109
+
For network policy validation failures, first distinguish a gateway mutation
110
+
rejection from a supervisor runtime rejection. Direct policy updates,
111
+
incremental merges and approvals, provider attachments, and provider-profile
112
+
fanout are validated against the complete effective policy before persistence
113
+
when the gateway knows the affected sandbox scope. A `FAILED_PRECONDITION`
114
+
ambiguity response means no invalid revision or partial fanout was stored.
115
+
Supervisor validation remains defense in depth for startup, races, and policy
116
+
sources outside those mutation paths.
117
+
118
+
Runtime rejection behavior is configured only in `gateway.toml`:
119
+
120
+
```toml
121
+
[openshell.gateway]
122
+
policy_validation_failure_mode = "fail_closed"
123
+
```
124
+
125
+
The default `fail_closed` mode deactivates the previous generation, closes
126
+
pinned relays, and quarantines new egress until a valid generation loads.
127
+
`retain_last_valid` explicitly keeps the previous valid policy active; without
128
+
one it still fails closed. Restart the gateway after changing this field.
129
+
Inspect sandbox OCSF configuration and finding events for the validation
130
+
rationale, configured and effective modes, active generation, and the explicit
131
+
`previous_policy_active` state.
132
+
109
133
### Step 4: Check Docker-Backed Gateways
110
134
111
135
```bash
@@ -400,6 +424,8 @@ openshell logs <sandbox-name>
400
424
| Provider profiles disappear after enabling an interceptor catalog |`provider_profile_sources` selected only an authoritative interceptor or returned invalid/duplicate IDs | Inspect source list and interceptor `Describe`/catalog logs; include `builtin` and `user` when intended |
401
425
| Gateway fails after registering supervisor middleware | Service unavailable, invalid manifest, duplicate binding, reserved name, or invalid body/timeout limit | Middleware service and gateway logs; `[[openshell.supervisor.middleware]]`; `Describe` response |
402
426
| Policy update rejects `network_middlewares`| Unknown middleware name, implementation-owned config invalid, duplicate order, broad/invalid host selector, or fail-closed coverage of `tls: skip`| Policy error, gateway logs, middleware `ValidateConfig`, selector and order fields |
427
+
| Policy mutation returns `FAILED_PRECONDITION` for endpoint ambiguity | Equally specific effective endpoint selectors disagree on connection or request-processing metadata | CLI error, base and provider-composed policy, affected profile attachments; confirm no new revision was stored |
428
+
| Supervisor enters policy quarantine | A runtime candidate failed validation while `policy_validation_failure_mode = "fail_closed"`| Sandbox OCSF config/finding events, validation rationale, active generation, `previous_policy_active`|
403
429
| HTTP request returns `middleware_failed` or `middleware_denied`| Selected stage failed or explicitly denied the admitted request | Sandbox OCSF logs; policy-local middleware config; service availability; `on_error`|
404
430
| Custom compute driver is unavailable | Driver process/socket missing, inaccessible, or configured with a reserved/mismatched name | Socket ownership/mode, driver service logs, gateway `GetCapabilities` logs |
405
431
| Image pull failure | Gateway or sandbox image cannot be pulled | Runtime events and image pull credentials |
Remember: `*` does not cross `/` boundaries. Use `**` for recursive matching across path segments.
240
+
Path matching uses the runtime `glob` engine. Both `*` and `**` may cross `/`
241
+
boundaries; `?` matches one character, and bracket classes such as `[0-9]` and
242
+
`[!0]` are supported. Prefer segment-shaped patterns such as
243
+
`/repos/*/issues` for readability, but do not rely on `*` to stop at `/`.
241
244
242
245
### Building the Explicit Rules List
243
246
@@ -439,7 +442,7 @@ The policy needs to go somewhere. Determine which mode applies:
439
442
440
443
2.**Check for conflicts**:
441
444
- Does a policy with the same key already exist? If so, ask the user whether to **replace** it, **merge** new endpoints/binaries into it, or use a different key.
442
-
- Does an existing policy already cover the same host:port? Warn the user — overlapping endpoint coverage across policies causes OPA evaluation errors (complete rule conflict).
445
+
- Does an existing endpoint selector overlap the new selector? Compatible overlaps are allowed and can intentionally aggregate allow and deny rules. Reject or revise equally specific overlaps that disagree on connection or request-processing metadata, including TLS, destination constraints, protocol/parser behavior, enforcement, or credential handling. A more-specific path selector may override broader request-processing metadata.
443
446
444
447
3.**Apply the change**:
445
448
-**Adding a new policy**: Insert the new policy block under `network_policies`, maintaining the file's existing indentation and style.
Copy file name to clipboardExpand all lines: docs/reference/gateway-config.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -175,7 +175,7 @@ phases = ["validate"]
175
175
176
176
Local Docker, Podman, and VM gateways can also set `[openshell.gateway.mtls_auth] enabled = true` to authenticate CLI callers from verified client certificates. Kubernetes deployments must leave this unset and use OIDC or a trusted access proxy; the Helm chart does not render this table.
177
177
178
-
`[openshell.gateway] policy_validation_failure_mode` controls what sandbox supervisors do when a complete candidate policy fails validation. The default, `fail_closed`, deactivates the previous network policy, closes relays pinned to it, and denies new egress until a valid generation loads. `retain_last_valid` leaves the previous valid generation active. Both modes reject the candidate atomically; startup always fails closed when no previous valid generation exists. Changing the value requires restarting the gateway so it can reload `gateway.toml` and distribute the new posture to sandbox supervisors.
178
+
`[openshell.gateway] policy_validation_failure_mode` controls what sandbox supervisors do when a complete candidate policy fails runtime validation. The default, `fail_closed`, deactivates the previous network policy, closes relays pinned to it, and denies new egress until a valid generation loads. `retain_last_valid` leaves the previous valid generation active. Both modes reject the candidate atomically; startup always fails closed when no previous valid generation exists. Gateway mutation paths that can preflight a known effective scope reject invalid candidates before persistence and leave the active policy unchanged regardless of this setting. Changing the value requires restarting the gateway so it can reload `gateway.toml` and distribute the new posture to sandbox supervisors.
179
179
180
180
`[openshell.gateway.gateway_jwt] ttl_secs` controls gateway-minted sandbox JWT lifetime. When omitted, it defaults to `0`: the token `exp` claim and `expires_at_ms` response field become `0`, and the sandbox JWT does not expire. Use that default only for local single-player Docker, Podman, or VM gateways. Kubernetes and other shared deployments should set a positive TTL; Helm renders `3600` seconds by default, and the gateway logs a warning when a Kubernetes gateway uses `0`.
| `path` | string | Yes | URL path glob. `*` and `**` match zero or more characters and may cross `/`; `?` matches one character; bracket classes such as `[0-9]` and `[!0]` are supported. |
220
220
| `query` | map | No | Query parameter matchers keyed by decoded param name. Matcher value can be a glob string (`tag: "foo-*"`) or an object with `any` (`tag: { any: ["foo-*", "bar-*"] }`). |
Copy file name to clipboardExpand all lines: docs/sandboxes/policies.mdx
+20-5Lines changed: 20 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -205,7 +205,21 @@ The following steps outline the hot-reload policy update workflow.
205
205
206
206
OpenShell validates a complete candidate policy before activating any part of it. Endpoints may overlap when their connection and request-processing metadata agree. For example, two `api.example.com:443` REST entries can contribute different allow and deny rules when they use the same TLS, destination, credential, parser, and enforcement settings. A plain L4 endpoint may overlap an L7 endpoint because it authorizes the destination without contributing request-processing metadata. A more-specific path endpoint may override request-processing metadata from a broader endpoint, such as a `/graphql` GraphQL endpoint alongside a general REST endpoint for the same host. OpenShell rejects the candidate when overlapping exact or wildcard host selectors can both contribute equally specific endpoint configuration and disagree on those fields.
207
207
208
-
The gateway's `policy_validation_failure_mode` configuration determines what happens after rejection. Set it under `[openshell.gateway]` in `gateway.toml`. Its default is `fail_closed`:
208
+
When the gateway knows the affected sandbox scope, it validates the complete
209
+
effective candidate before persistence. This covers direct policy replacement,
210
+
incremental merges and proposal approvals, provider attachment, and
211
+
provider-profile updates that fan out to attached sandboxes. An ambiguity
212
+
failure returns `FAILED_PRECONDITION`; OpenShell stores no invalid policy
213
+
revision and does not partially apply a profile update. Supervisor validation
214
+
remains a defense-in-depth boundary for startup, concurrent changes, and policy
215
+
sources outside those mutation paths.
216
+
217
+
A gateway preflight rejection leaves the currently active policy unchanged
218
+
regardless of failure mode because the candidate is never persisted or
219
+
distributed. If a candidate reaches a supervisor and fails runtime validation,
220
+
the gateway's `policy_validation_failure_mode` configuration determines the
221
+
supervisor posture. Set it under `[openshell.gateway]` in `gateway.toml`. Its
222
+
default is `fail_closed`:
209
223
210
224
```toml
211
225
[openshell.gateway]
@@ -354,13 +368,14 @@ means:
354
368
- match the endpoint `api.github.com:443`.
355
369
- match HTTP method `POST`.
356
370
- match paths like `/repos/acme/issues`.
357
-
- do not match deeper paths like `/repos/acme/project/issues/123` because `*` matches one path segment.
371
+
- also match deeper paths when the surrounding literals align, because `*` may include `/`.
358
372
359
373
Path globs follow the same semantics as YAML allow and deny rules:
360
374
361
-
- `*`matches one path segment.
362
-
- `**`matches any number of segments.
363
-
- `/repos/*/issues`matches one repository owner or name segment in the middle.
375
+
- `*`and `**` match zero or more characters and may cross `/` boundaries.
376
+
- `?`matches exactly one character.
377
+
- bracket classes such as `[0-9]` and negated classes such as `[!0]` are supported.
378
+
- `/repos/*/issues`matches any intervening text, including multiple path segments.
364
379
- `/repos/**`matches everything under `/repos/`.
365
380
366
381
The rule-level commands only modify method and path constraints. They do not change binaries, hostnames, ports, protocol settings, or WebSocket message payload matching.
0 commit comments