generated from coulomb/repo-seed
Access controlled knowledge gateway functionality
This commit is contained in:
173
docs/access-control-policy-gateway.md
Normal file
173
docs/access-control-policy-gateway.md
Normal file
@@ -0,0 +1,173 @@
|
||||
# Access-Controlled Knowledge Gateway
|
||||
|
||||
Date: 2026-05-04
|
||||
|
||||
## Purpose
|
||||
|
||||
The policy gateway adds an explicit boundary before cached query, search, and
|
||||
future context-package results leave a backend. It starts with a local label
|
||||
policy and keeps room for more rigid authorization systems later.
|
||||
|
||||
This layer does not make Markitect a full identity platform. Core Markitect
|
||||
answers a narrower question:
|
||||
|
||||
```text
|
||||
subject + action + object + context -> policy decision
|
||||
```
|
||||
|
||||
Backend and workflow code can then filter, redact, log, and explain results
|
||||
using the same decision envelope.
|
||||
|
||||
## Access-Control Ladder
|
||||
|
||||
The intended progression is:
|
||||
|
||||
| Level | Mode | Purpose |
|
||||
| --- | --- | --- |
|
||||
| 1 | Labels and trust zones | Local labs, prototypes, and agent context safety. |
|
||||
| 2 | Path/file ACLs | Repository-local restrictions and team boundaries. |
|
||||
| 3 | Relationship policies | Zanzibar/OpenFGA/SpiceDB-style subject-object relations. |
|
||||
| 4 | Attribute/rule policies | OPA/Rego, Cedar, and policy-as-data engines. |
|
||||
| 5 | External policy services | Organization identity, audit, and authorization systems. |
|
||||
|
||||
WP-0009 implements levels 1 and 2 directly and defines adapter boundaries for
|
||||
levels 3 and 4.
|
||||
|
||||
## Local Label Policy
|
||||
|
||||
Local policy files are YAML:
|
||||
|
||||
```yaml
|
||||
id: local-label-policy
|
||||
mode: enforce
|
||||
default_labels: [public]
|
||||
default_subject: public-agent
|
||||
subjects:
|
||||
public-agent:
|
||||
allowed_labels: [public]
|
||||
trust_zones: [public]
|
||||
internal-agent:
|
||||
allowed_labels: [public, internal]
|
||||
trust_zones: [public, internal]
|
||||
path_rules:
|
||||
- id: private-path
|
||||
pattern: private/**
|
||||
labels: [internal]
|
||||
trust_zone: internal
|
||||
```
|
||||
|
||||
Policy modes:
|
||||
|
||||
- `off`: allow every result and emit allow decisions.
|
||||
- `audit`: keep results but mark decisions that would have been denied.
|
||||
- `enforce`: deny or redact results before they leave the boundary.
|
||||
|
||||
Denied behavior:
|
||||
|
||||
- `on_denied: drop` removes denied results. This is the default.
|
||||
- `on_denied: redact` keeps the envelope but replaces text and value.
|
||||
|
||||
Object labels can come from document frontmatter, policy metadata, or path
|
||||
rules. Supported frontmatter shapes:
|
||||
|
||||
```yaml
|
||||
---
|
||||
labels: [internal]
|
||||
policy:
|
||||
labels: [internal]
|
||||
trust_zone: internal
|
||||
---
|
||||
```
|
||||
|
||||
Path rules augment frontmatter labels. This lets a repository declare that
|
||||
everything under `private/**` is internal even if an individual document forgets
|
||||
its frontmatter label.
|
||||
|
||||
## CLI
|
||||
|
||||
Check one decision:
|
||||
|
||||
```text
|
||||
mkt policy check public-agent query private/doc.md \
|
||||
--policy examples/policy/local-label-policy.yaml \
|
||||
--path private/doc.md
|
||||
```
|
||||
|
||||
Filter local FTS search results:
|
||||
|
||||
```text
|
||||
mkt search Knowledge \
|
||||
--policy examples/policy/local-label-policy.yaml \
|
||||
--subject public-agent
|
||||
```
|
||||
|
||||
Filter indexed query results:
|
||||
|
||||
```text
|
||||
mkt cache query 'sections[heading=Decision]' \
|
||||
--policy examples/policy/local-label-policy.yaml \
|
||||
--subject public-agent
|
||||
```
|
||||
|
||||
JSON and YAML outputs include:
|
||||
|
||||
- `policy`: mode, subject, action, allowed, denied, redacted, audit counts
|
||||
- `policy_decisions`: per-result decisions with stable ids and reasons
|
||||
- `diagnostics`: denied/redacted result diagnostics
|
||||
|
||||
Text output shows a compact policy summary before the filtered matches.
|
||||
|
||||
## Decision Logs
|
||||
|
||||
Every local decision contains:
|
||||
|
||||
- stable `decision_id`
|
||||
- subject
|
||||
- action
|
||||
- object id
|
||||
- effect: `allow`, `deny`, `redact`, or `audit_denied`
|
||||
- reason
|
||||
- mode
|
||||
- rule id
|
||||
- labels
|
||||
- trust zone
|
||||
- metadata, including object path and policy id
|
||||
|
||||
`LocalLabelPolicyGateway.explain_decision(decision_id)` returns a decision made
|
||||
by the current gateway instance. Persistent decision logs are intentionally left
|
||||
to future backend storage.
|
||||
|
||||
## Adapter Boundaries
|
||||
|
||||
Relationship policies use `RelationshipPolicyAdapter`:
|
||||
|
||||
```text
|
||||
RelationshipPolicyRequest(subject, relation, object_id, namespace, context)
|
||||
-> PolicyDecision
|
||||
```
|
||||
|
||||
This is the attachment point for Zanzibar/OpenFGA/SpiceDB-style systems.
|
||||
|
||||
Rule policies use `RulePolicyAdapter`:
|
||||
|
||||
```text
|
||||
RulePolicyRequest(subject, action, object, context, policy_id)
|
||||
-> PolicyDecision
|
||||
```
|
||||
|
||||
This is the attachment point for OPA/Rego, Cedar, or other
|
||||
attribute/rule-based systems.
|
||||
|
||||
Adapters must return the same `PolicyDecision` shape as the local label
|
||||
gateway. That keeps query filtering, diagnostics, provenance, and future
|
||||
context-package filtering independent from the concrete policy engine.
|
||||
|
||||
## Extension Fit
|
||||
|
||||
The local gateway is registered as `policy.local-label`. It is an internal
|
||||
extension with no network dependency. Backends and workflows can request the
|
||||
`policy` or `policy_filter` capability without importing an external service.
|
||||
|
||||
The design intentionally stays close to Markdown: labels can live in document
|
||||
frontmatter, path rules live in YAML, and external authorization languages are
|
||||
extensions rather than replacements for the core contract.
|
||||
Reference in New Issue
Block a user