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.
|
||||
@@ -136,6 +136,12 @@ Protocol interfaces are provided for:
|
||||
These are contracts for future implementations. They are intentionally light
|
||||
and do not force the current CLI through a persistent backend.
|
||||
|
||||
WP-0009 adds the first concrete `AccessPolicyGateway` implementation:
|
||||
`LocalLabelPolicyGateway`. It supports labels, trust zones, path rules, enforce
|
||||
and audit modes, denied-result diagnostics, redaction, and explainable decisions.
|
||||
Relationship and rule-policy systems remain adapter protocols rather than core
|
||||
dependencies.
|
||||
|
||||
## CLI
|
||||
|
||||
Read-only inspection commands:
|
||||
@@ -145,6 +151,7 @@ mkt backend list --path examples/backends
|
||||
mkt backend inspect local-sqlite-cache --path examples/backends --require snapshots --require provenance
|
||||
mkt backend snapshot-id docs/content-references.md
|
||||
mkt backend refresh-plan docs --state examples/backend-state/snapshot-state.yaml
|
||||
mkt policy check public-agent query private/doc.md --policy examples/policy/local-label-policy.yaml --path private/doc.md
|
||||
```
|
||||
|
||||
The existing `mkt cache status` remains the lightweight file-manifest change
|
||||
|
||||
@@ -36,6 +36,7 @@ framework organizes how Markitect itself exposes and composes capabilities.
|
||||
| `validator` | schema, contract, section assertion | document/context in, diagnostics out |
|
||||
| `runtime` | context loader, form state, dynamic rules | document/contract/context in, diagnostics and state out |
|
||||
| `assessment-runner` | provider-neutral rubric execution | assessment request in, normalized result out |
|
||||
| `policy-gateway` | local label gateway, future external auth adapters | subject/action/object in, decision or filtered results out |
|
||||
| `template-engine` | deterministic templates | template/data in, Markdown out |
|
||||
| `generation-adapter` | provider-neutral assisted generation | request in, generated candidate out |
|
||||
| `cli-group` | cache, backend, ref, class | command descriptors or registration hook |
|
||||
|
||||
@@ -36,12 +36,14 @@ Query indexed snapshots:
|
||||
```text
|
||||
mkt cache query 'sections[heading=Decision]' --root .
|
||||
mkt cache query '$.headings[*].text' --engine jsonpath --root .
|
||||
mkt cache query 'sections[heading=Decision]' --policy examples/policy/local-label-policy.yaml --subject public-agent
|
||||
```
|
||||
|
||||
Search indexed section/block text:
|
||||
|
||||
```text
|
||||
mkt search SQLite --root .
|
||||
mkt search SQLite --policy examples/policy/local-label-policy.yaml --subject public-agent
|
||||
```
|
||||
|
||||
Inspect a parsed AST without using the cache:
|
||||
@@ -90,8 +92,19 @@ This is enough to recover the useful markitect-main idea of keeping parsed
|
||||
structure available for faster and richer query backends, while keeping the
|
||||
normal CLI usable without a cache.
|
||||
|
||||
## Policy-Aware Retrieval
|
||||
|
||||
`mkt cache query` and `mkt search` can run with a local label policy before
|
||||
results leave the local backend boundary. When `--policy` is supplied, Markitect
|
||||
extracts labels and trust zones from document frontmatter and applies any path
|
||||
rules in the policy file. JSON/YAML output includes policy decisions and
|
||||
diagnostics.
|
||||
|
||||
See `docs/access-control-policy-gateway.md` for the policy vocabulary and
|
||||
adapter boundaries.
|
||||
|
||||
## Future Work
|
||||
|
||||
Follow-on backend work can now focus on richer dependency extraction from
|
||||
references, transclusion, and literate chunks; access-controlled query gateways;
|
||||
and larger-scale memory/context packages.
|
||||
references, transclusion, and literate chunks; persistent decision logs; and
|
||||
larger-scale memory/context packages.
|
||||
|
||||
@@ -37,7 +37,7 @@ and descriptions mirror the operational view.
|
||||
| `MKTT-WP-0013` | complete | done | `MKTT-WP-0003`, `MKTT-WP-0004`, `MKTT-WP-0006`, `MKTT-WP-0007`, `MKTT-WP-0010` | Internal extension framework is complete: characterization tests, canonical processing model, descriptors, registries, lifecycle callbacks, query-engine registry, built-in extension catalog, CLI command specs, and authoring guide. |
|
||||
| `MKTT-WP-0005` | complete | done | `MKTT-WP-0003`, `MKTT-WP-0004` | Runtime context, form state, dynamic rules, workflow integration, and provider-neutral assessment boundary are complete. |
|
||||
| `MKTT-WP-0011` | complete | done | `MKTT-WP-0003`; task-level triggers: `MKTT-WP-0010-T001`, `MKTT-WP-0010-T005` | Markdown dataflow workflow layer is complete: workflow standard, source collectors, binding model, deterministic steps, assisted boundary, safe outputs, CLI, docs, and examples. |
|
||||
| `MKTT-WP-0009` | P2 | todo | `MKTT-WP-0006` | Establish access-control gateway before security-sensitive cache/context use. |
|
||||
| `MKTT-WP-0009` | complete | done | `MKTT-WP-0006` | Access-controlled knowledge gateway is complete: local labels, trust zones, path rules, policy-aware cache query/search, decisions, diagnostics, and external adapter boundaries. |
|
||||
| `MKTT-WP-0012` | P3 | todo | `MKTT-WP-0004`, `MKTT-WP-0010`, `MKTT-WP-0011` | Future Quarkdown-inspired document function layer: reusable Markdown-native function calls over processors, references, contracts, workflows, and later assisted steps. |
|
||||
| `MKTT-WP-0008` | P3 | todo | `MKTT-WP-0006`, `MKTT-WP-0007`, `MKTT-WP-0009` | Agent working-memory cache after backend and policy floor are available. |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user