Phase 4: policy engine with deny-wins, default-deny evaluation

internal/policy/:
Priority-based policy engine per ARCHITECTURE.md §4. Stateless
Evaluate() sorts rules by priority, collects all matches, deny-wins
over allow, default-deny if no match. Rule matching: all populated
fields ANDed, empty fields are wildcards, repository glob via
path.Match. Built-in defaults: admin wildcard (all actions), human
user content access (pull/push/delete/catalog), version check
(always accessible). Engine wrapper with sync.RWMutex-protected
cache, SetRules merges with defaults, Reload loads from RuleStore.

internal/db/:
LoadEnabledPolicyRules() parses rule_json column from policy_rules
table into []policy.Rule, filtered by enabled=1, ordered by priority.

internal/server/:
RequirePolicy middleware extracts claims from context, repo from chi
URL param, evaluates policy, returns OCI DENIED (403) on deny with
optional audit callback.

69 tests passing across all packages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-19 15:05:28 -07:00
parent 3314b7a618
commit f5e67bd4aa
11 changed files with 1158 additions and 4 deletions

View File

@@ -13,7 +13,7 @@ design specification.
| 1 | Configuration & database | **Complete** |
| 2 | Blob storage layer | **Complete** |
| 3 | MCIAS authentication | **Complete** |
| 4 | Policy engine | Not started |
| 4 | Policy engine | **Complete** |
| 5 | OCI API — pull path | Not started |
| 6 | OCI API — push path | Not started |
| 7 | OCI API — delete path | Not started |