@@ -17,13 +17,25 @@ exists x:
1717
1818Rust normalizes schema-level OpenShell policy semantics, such as access presets
1919and unsupported field detection. Z3 owns the action variables (` binary ` , ` host ` ,
20- ` port ` , ` protocol ` , ` method ` , and ` path ` ) and checks whether any symbolic action
21- is allowed by the candidate but not by the maximum. Host, path, and binary globs
20+ ` port ` , ` layer ` , ` method ` , and ` path ` ) and checks whether any symbolic action is
21+ allowed by the candidate but not by the maximum. Host, path, and binary globs
2222compile to Z3 regular-expression constraints. If the solver finds such an ` x ` ,
2323the candidate exceeds the maximum. If no such ` x ` exists, the candidate is within
2424the modeled maximum. If either policy uses a surface the spike does not model
2525yet, the check fails closed as ` Unsupported ` .
2626
27+ The first modeled action layers are:
28+
29+ ``` text
30+ L4: binary, host, port
31+ REST: binary, host, port, method, path
32+ WebSocket: binary, host, port, method, path
33+ ```
34+
35+ An L4 endpoint is broader than inspected protocols: it covers raw L4, REST, and
36+ WebSocket actions on the same binary/host/port. REST and WebSocket endpoints
37+ cover only their own inspected action layer.
38+
2739## Demo 1: Narrow Candidate Within Maximum
2840
2941Maximum:
@@ -155,11 +167,66 @@ port: 443 -> [443, 8443]
155167
156168Why: each change creates at least one action that the maximum does not allow.
157169
158- L4-only endpoints are not modeled in this spike. They fail closed as
159- ` Unsupported ` rather than being compared against the REST-only symbolic action
160- domain.
170+ ## Demo 5: L4, REST, And WebSocket Layering
171+
172+ An L4 maximum covers a narrower REST candidate on the same binary/host/port:
173+
174+ ``` yaml
175+ maximum :
176+ endpoints :
177+ - host : api.github.com
178+ port : 443
179+
180+ candidate :
181+ endpoints :
182+ - host : api.github.com
183+ port : 443
184+ protocol : rest
185+ enforcement : enforce
186+ access : read-write
187+ ` ` `
188+
189+ Result:
190+
191+ ` ` ` text
192+ WithinMax
193+ ```
194+
195+ A REST maximum does not cover a raw L4 candidate:
161196
162- ## Demo 5: Unsupported Surfaces Fail Closed
197+ ``` text
198+ ExceedsMax {
199+ protocol: "l4",
200+ host: "api.github.com",
201+ port: 443,
202+ ...
203+ }
204+ ```
205+
206+ Why: raw L4 egress is broader and less inspected than an enforced REST or
207+ WebSocket surface.
208+
209+ WebSocket endpoints are modeled as their own inspected layer with ` GET ` and
210+ ` WEBSOCKET_TEXT ` actions. ` read-only ` WebSocket access covers the opening
211+ ` GET ` , not text send authority. Credential rewrite flags fail closed until the
212+ prover has an explicit authority check for introducing credential injection.
213+
214+ ## Demo 6: Credentialed L4 Is A Separate High-Risk Check
215+
216+ The spike also includes a separate check for uninspected credentialed L4 reach:
217+
218+ ``` text
219+ exists x:
220+ policy_allows(x)
221+ AND x.layer = L4
222+ AND credential_target_matches(x.host)
223+ ```
224+
225+ This is intentionally separate from maximum containment. It lets product policy
226+ decide whether credentialed L4 should be explicitly allowed, auto-denied, or
227+ sent to human review without changing the meaning of the signed maximum.
228+
229+ ## Demo 7: Unsupported Surfaces Fail Closed
163230
164231Maximum:
165232
@@ -189,7 +256,7 @@ GraphQL operation and field constraints
189256MCP tool/resource constraints
190257CIDR-only allowed_ips
191258endpoint path scoping
192- L4-only endpoints
259+ credential rewrite flags
193260```
194261
195262## Narrowness Companion
@@ -227,9 +294,11 @@ exact new grant: +1
227294single path wildcard: +2
228295host/binary wildcard: +3
229296recursive glob (**): +6
297+ L7-to-L4 broadening: +8
230298```
231299
232- A conservative budget can allow one exact grant and reject recursive globs:
300+ A conservative budget can allow one exact grant, including an exact L4
301+ host/port grant, while rejecting recursive globs and L7-to-L4 broadening:
233302
234303``` rust
235304NarrownessBudget {
@@ -239,7 +308,12 @@ NarrownessBudget {
239308}
240309```
241310
242- ## Demo 6: One Exact Path Fits A Narrow Budget
311+ Credentialed raw L4 is handled by the separate credentialed-L4 check above. A
312+ production auto-approval gate can combine that result with this budget, for
313+ example by assigning a high score or requiring human review when raw L4 reaches
314+ a credential target.
315+
316+ ## Demo 8: One Exact Path Fits A Narrow Budget
243317
244318Current:
245319
@@ -280,7 +354,59 @@ WithinBudget {
280354Why: the candidate adds one exact modeled grant. The grant allows both ` GET ` and
281355runtime-implied ` HEAD ` , but the budget counts the source grant once.
282356
283- ## Demo 7: Lazy Recursive Path Exceeds A Narrow Budget
357+ ## Demo 9: Exact L4 Versus L7-To-L4 Broadening
358+
359+ An exact L4 grant to a new normal host is still one exact grant:
360+
361+ ``` yaml
362+ candidate :
363+ endpoints :
364+ - host : files.pythonhosted.org
365+ port : 443
366+ ` ` `
367+
368+ Result:
369+
370+ ` ` ` text
371+ WithinBudget {
372+ total_score : 1,
373+ reasons : [NewGrant]
374+ }
375+ ```
376+
377+ If the current policy already has inspected REST/WebSocket access for the same
378+ authority and the candidate asks for raw L4, the same exact host/port becomes a
379+ larger jump:
380+
381+ ``` yaml
382+ current :
383+ endpoints :
384+ - host : api.github.com
385+ port : 443
386+ protocol : rest
387+ enforcement : enforce
388+ access : full
389+
390+ candidate :
391+ endpoints :
392+ - host : api.github.com
393+ port : 443
394+ ` ` `
395+
396+ Result:
397+
398+ ` ` ` text
399+ ExceedsBudget {
400+ total_score : 9,
401+ reasons : [NewGrant, L7ToL4Broadening]
402+ }
403+ ```
404+
405+ Why: the candidate is not just adding a host. It is replacing inspected
406+ method/path reasoning with raw host/port authority for a service the current
407+ policy already modeled at L7.
408+
409+ ## Demo 10: Lazy Recursive Path Exceeds A Narrow Budget
284410
285411Current:
286412
@@ -330,29 +456,22 @@ it.
330456mise exec -- cargo test -p openshell-prover
331457```
332458
333- Maximal-policy tests include :
459+ Coverage includes :
334460
335461``` text
336- envelope::tests::exact_rest_rule_is_within_maximum
337- envelope::tests::broader_rest_path_exceeds_maximum
338- envelope::tests::method_escalation_exceeds_maximum
339- envelope::tests::host_wildcard_broadening_exceeds_maximum
340- envelope::tests::binary_wildcard_broadening_exceeds_maximum
341- envelope::tests::port_broadening_exceeds_maximum
342- envelope::tests::l4_candidate_exceeds_l7_maximum
343- envelope::tests::maximum_wildcards_cover_exact_candidate
344- envelope::tests::deny_rules_are_unsupported_until_modeled
345- envelope::tests::query_graphql_cidr_and_mcp_surfaces_are_unsupported
346- envelope::tests::narrowness_allows_one_exact_path_delta_within_budget
347- envelope::tests::narrowness_allows_one_exact_method_delta_within_budget
348- envelope::tests::narrowness_rejects_multiple_exact_grants_over_budget
349- envelope::tests::narrowness_rejects_recursive_path_glob_as_too_broad
462+ REST method/path/host/binary/port containment
463+ L4 versus REST/WebSocket layer containment
464+ WebSocket text-send and read-only behavior
465+ credentialed raw L4 detection
466+ fail-closed unsupported deny/query/GraphQL/MCP/CIDR/rewrite surfaces
467+ exact, wildcard, recursive-glob, L4, and WebSocket narrowness deltas
468+ representative provider-shaped accept/reject cases
350469```
351470
352471## Readout
353472
354- This validates the product shape for REST/path/binary/host/port maximum-policy
355- envelopes and narrowness budgets with symbolic Z3 counterexample queries. Deny
356- rules, MCP, GraphQL, query constraints, CIDR, and L4-only endpoints can land as
357- follow-on modeled surfaces once the containment and delta mechanics are proven
358- useful.
473+ This validates the product shape for L4, REST, and WebSocket maximum-policy
474+ envelopes, narrowness budgets, and uninspected credentialed L4 detection with
475+ symbolic Z3 counterexample queries. Deny rules, MCP, GraphQL, query constraints,
476+ and CIDR can land as follow-on modeled surfaces once the containment and delta
477+ mechanics are proven useful.
0 commit comments