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
fix(trust): enforce §3 invariant 3 — BoJ ignores X-Trust-Level from non-loopback (standards#98) (#106)
## Summary
Phase A contract §3 invariant 3 mandates: *"Any `X-Trust-Level`
arriving from any other source MUST be ignored and treated as
`untrusted`."*
`BojRest.TrustPolicy.satisfies?/3` previously accepted
`X-Trust-Level: authenticated|internal` from any caller — the third
clause matched regardless of `is_local`. A non-loopback caller reaching
BoJ's back-side bind (a §4 violation) could therefore claim any trust
class by setting a header. This is the **BoJ-side half of the §3
defence-in-depth pair**; the gateway-side strip + re-emit landed as
http-capability-gateway#11.
## The fix
One new clause between the existing `:public` and `:authenticated`
arms:
```elixir
def satisfies?(_required, _trust, false), do: false
```
Plus the surrounding bookkeeping:
- `trust_policy_test.exs` — 2 existing assertions inverted (they
codified the buggy behaviour) + 2 new tests explicitly pinning §3
- `router_test.exs` — 2 existing tests inverted (used to assert that
a non-loopback caller with `X-Trust-Level: authenticated|internal`
passed; now assert they get 403)
- `phase_c_seam_test.exs` — 5 `@tag skip:` annotations removed; module
moduledoc updated (was a "documented finding" module; now a live
enforcement test module)
- `docs/integration/http-capability-gateway-boj-contract.md` — new
"Implementation status (Phase C)" subsection naming the three
controls (gateway-side / BoJ-side / operational §4) and where each
landed
- `lib/boj_rest/trust_policy.ex` — moduledoc updated with a "Phase A §3
invariant 3" subsection explaining the new clause
## Test plan
- [x] `mix test test/{trust_policy,router,phase_c_seam}_test.exs` —
**64/64 green**
- [x] full `mix test` — 2 failures, both pre-existing baseline rot in
`catalog_test.exs:85` + `catalog_properties_test.exs:73` (cartridge
`auth.method` values), unrelated to this PR
- [ ] reviewer: confirm §3 enforcement is correct — non-loopback caller
cannot promote trust class via header
- [ ] reviewer: confirm the inversion of the 2 router-tests + 2
trust_policy_tests is the right call (they were testing the buggy
behaviour)
## Refs
Refs hyperpolymath/standards#98
Refs hyperpolymath/standards#91
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments