acl: Phase 1 direct grants + deny-overrides, 24 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 56s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 56s
Datalog ACL layer (schema/facts/engine/api) over lib/datalog/. Direct grant permits unless explicit deny names same (S,A,R) — deny-overrides via stratified negation. Conformance wrapper + scoreboard. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ and federation extension. Reuses `lib/datalog/` evaluator and term model where p
|
||||
|
||||
## Status (rolling)
|
||||
|
||||
`bash lib/acl/conformance.sh` → **0/0** (not yet started)
|
||||
`bash lib/acl/conformance.sh` → **24/24** (Phase 1 complete)
|
||||
|
||||
## Ground rules
|
||||
|
||||
@@ -57,15 +57,15 @@ lib/acl/facts.sx — builds Datalog query
|
||||
|
||||
## Phase 1 — Direct grants
|
||||
|
||||
- [ ] `lib/acl/schema.sx` — sorts: subject {user, group, role, service}, action,
|
||||
- [x] `lib/acl/schema.sx` — sorts: subject {user, group, role, service}, action,
|
||||
resource {page, post, thread, peer}
|
||||
- [ ] `lib/acl/facts.sx` — `actor`, `resource`, `grant`, `deny` predicates as Datalog
|
||||
- [x] `lib/acl/facts.sx` — `actor`, `resource`, `grant`, `deny` predicates as Datalog
|
||||
EDB
|
||||
- [ ] `lib/acl/engine.sx` — `(permit? subj act res db)` reduces to Datalog query
|
||||
- [ ] `lib/acl/api.sx` — public `(acl/permit? ...)` taking implicit current db
|
||||
- [ ] `lib/acl/tests/direct.sx` — 15+ cases: direct grant, missing grant, explicit deny
|
||||
- [ ] `lib/acl/scoreboard.{json,md}` baseline
|
||||
- [ ] `lib/acl/conformance.sh` runs the suite
|
||||
- [x] `lib/acl/engine.sx` — `(permit? subj act res db)` reduces to Datalog query
|
||||
- [x] `lib/acl/api.sx` — public `(acl/permit? ...)` taking implicit current db
|
||||
- [x] `lib/acl/tests/direct.sx` — 15+ cases: direct grant, missing grant, explicit deny
|
||||
- [x] `lib/acl/scoreboard.{json,md}` baseline
|
||||
- [x] `lib/acl/conformance.sh` runs the suite
|
||||
|
||||
## Phase 2 — Inheritance
|
||||
|
||||
@@ -95,7 +95,34 @@ lib/acl/facts.sx — builds Datalog query
|
||||
|
||||
## Progress log
|
||||
|
||||
(loop fills this in)
|
||||
- **Phase 1 complete (24/24).** ACL is a thin layer over `lib/datalog/`:
|
||||
- `schema.sx` — sorts (subject/resource kinds, well-known actions) + EDB
|
||||
predicate arity table + `acl-fact-valid?` validator. Schema is data, since
|
||||
Datalog is untyped.
|
||||
- `facts.sx` — `acl-actor`/`acl-resource-fact`/`acl-grant`/`acl-deny`
|
||||
constructors returning Datalog fact tuples.
|
||||
- `engine.sx` — owns the ruleset `acl-phase1-rules` and reduces decisions to
|
||||
`dl-query`. `acl-build-db` = `dl-program-data facts rules`; `acl-permit?` =
|
||||
non-empty `(permit S A R)` query.
|
||||
- `api.sx` — `acl/load!` rebuilds an implicit current db; `acl/permit?` queries
|
||||
it. (Slash-symbols like `acl/permit?` parse fine as single tokens.)
|
||||
- **deny-overrides** encoded as `permit(S,A,R) :- grant(S,A,R), not deny(S,A,R)`.
|
||||
Stratifies cleanly because `deny` is EDB-only (no rule derives it). Verified:
|
||||
grant+deny on same (S,A,R) → denied.
|
||||
- Conformance: `conformance.conf` (datalog preloads + acl modules) + thin
|
||||
`conformance.sh` wrapper over `lib/guest/conformance.sh`. Scoreboard
|
||||
generated by the shared driver.
|
||||
- **Shared-plumbing note (for eventual `lib/guest/rules/`):** the
|
||||
`build-db = dl-program-data(facts, rules)` + `decide = non-empty ground query`
|
||||
shape is exactly what mod-sx (Prolog moderation) will also need. The reusable
|
||||
seam is engine.sx's two functions — facts→db and ground-query→bool — both
|
||||
pure pass-throughs to the rule engine. Not extracting yet (wait for mod-sx as
|
||||
second consumer per ground rules).
|
||||
- **Tooling note:** sx-tree path-based edit tools (`sx_replace_node`,
|
||||
`sx_read_subtree` with a path) ignored the path argument in this worktree
|
||||
(always resolved to index 0 / `[0,..]`). `sx_write_file`, `sx_validate`,
|
||||
`sx_find_all`, `sx_eval` all work; used full-file rewrites instead of path
|
||||
edits.
|
||||
|
||||
## Blockers
|
||||
|
||||
|
||||
Reference in New Issue
Block a user