Skip to content

feat(policy): capability field + opt-in fail-closed exposure (audit #31, P2)#33

Merged
hyperpolymath merged 1 commit into
mainfrom
audit/policy-schema-capability
Jun 2, 2026
Merged

feat(policy): capability field + opt-in fail-closed exposure (audit #31, P2)#33
hyperpolymath merged 1 commit into
mainfrom
audit/policy-schema-capability

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

Audit issue: #31 (priority 2 — policy schema is allowlist-shaped but shallow).

Two structural weaknesses in the policy DSL, fixed without breaking
back-compat:

  1. No first-class capability label. Today the only capability binding
    is via the implicit trust-level total order in SafeTrust. Adds an
    optional capability field at the route level and propagates it onto
    PolicyCompiler.CompiledRule so downstream consumers (audit log,
    future chimichanga-style attenuation, the new EgressPolicy seam in
    feat(egress): draft EgressPolicy schema + decide/3 (audit #31, P1) #32) can read it.

  2. parse_exposure is unconditionally fail-open. Documented as
    intentional but combined with the Map.get(route, \"exposure\", \"public\")
    compiler default this means a typoed or omitted exposure silently makes
    the route public. Adds an opt-in :exposure_fail_closed = true flag
    that flips unknown values to :internal (most restrictive level).
    Default remains fail-open for back-compat; this is opt-in for
    environments where confidentiality is weighted above availability
    (e.g., neurophone egress).

Diff: 4 files, +173 / -5 LoC (under the 300-LoC PR ceiling).

Test plan

  • mix test test/policy_capability_test.exs
  • mix test — confirm no existing tests broke (capability defaults to
    nil so all existing CompiledRule callers continue to work)
  • Confirm parse_exposure(\"typo\") returns :public by default and
    :internal when :exposure_fail_closed is set
  • Status: DRAFT — please do not auto-merge. Owner review only.

Echo-types audit

record-as-not-relevant. Capability label is a passive string in v1; it
does not interact with echo types. Re-check when chimichanga attenuation
attaches to it.

Refs: #31, related to #32

… (audit #31, P2)

Two structural weaknesses in the policy schema, fixed without breaking
back-compat:

1. NO FIRST-CLASS CAPABILITY LABEL.
   Adds an optional `capability` field at the route level. When set, it
   propagates onto `PolicyCompiler.CompiledRule` so downstream consumers
   (audit log, future chimichanga attenuation, the new EgressPolicy seam
   in audit/egress-mode-scaffold) can read it. Validator rejects empty
   strings and non-strings; nil/omitted is back-compat.

2. parse_exposure WAS UNCONDITIONALLY FAIL-OPEN.
   Existing behaviour: `parse_exposure("typo") -> :public`. Documented as
   intentional but combined with the `Map.get(route, "exposure", "public")`
   compiler default this means an omitted-or-typoed exposure silently
   makes the route public. Adds an opt-in
   `:exposure_fail_closed = true` flag that flips unknown values to
   `:internal` (most restrictive). Default remains fail-open for
   back-compat; this is opt-in for environments where confidentiality is
   weighted above availability (e.g., neurophone egress).

Test coverage:
* PolicyValidator: capability accept (non-empty, omitted) / reject (empty, non-string)
* PolicyCompiler: capability propagation onto CompiledRule
* SafeTrust: default-fail-open, opt-in-fail-closed, known-values-unchanged

Refs: #31 (self-audit, priority 2)
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

🔍 Hypatia Security Scan

Findings: 65 issues detected

Severity Count
🔴 Critical 6
🟠 High 17
🟡 Medium 42

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Issue in boj-build.yml",
    "type": "missing_timeout_minutes",
    "file": "boj-build.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in casket-pages.yml",
    "type": "missing_timeout_minutes",
    "file": "casket-pages.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in casket-pages.yml",
    "type": "missing_timeout_minutes",
    "file": "casket-pages.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in codeql.yml",
    "type": "missing_timeout_minutes",
    "file": "codeql.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in governance.yml",
    "type": "missing_timeout_minutes",
    "file": "governance.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath hyperpolymath marked this pull request as ready for review June 2, 2026 10:17
@hyperpolymath hyperpolymath merged commit e64a3aa into main Jun 2, 2026
18 checks passed
@hyperpolymath hyperpolymath deleted the audit/policy-schema-capability branch June 2, 2026 10:18
hyperpolymath added a commit that referenced this pull request Jun 2, 2026
…audit #31, P3) (#34)

Pure documentation — no code change. Adds docs/CAPABILITY-INTEGRATION.md
describing the contract surfaces by which the gateway connects (or, in
v0.x, *will connect*) to:

* the estate capability model (chimichanga capability attenuation,
  boj-server cartridges already partially wired via
  PolicyLoader.load_from_boj_catalog/1)
* service discovery via groove-protocol

Documented as a CONTRACT, not a feature list, because:
1. The cross-repo contracts are still stabilising
2. The compiler-side schema change is in flight in #33
3. The egress mode in #32 is the more urgent consumer

Also extends PROOFS_NEEDED.md with the two open obligations and a fresh
echo-types record-as-not-relevant audit per estate convention.

Refs: #31 (self-audit, priority 3), related to #32, #33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant