You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Implements the decision architecture so the docs match the code. An AgentWorkload action now passes through ordered layers, and every decision ends in a signed receipt.
Layers, in order: invariants (INV-01 to INV-06), policy packs, threshold, optional model, human approval. The first deny wins. Nothing can be loosened by a later layer.
Packages
pkg/invariants: hard rules that no pack, model or human can override.
pkg/rules: policy engine (OPA, Go 1.25 compatible), packs, threshold rules.
pkg/dataclass, pkg/decision: data classification, the layered decision flow, model shadow mode.
pkg/receipts, cmd/receipt-writer: hash-chained, Ed25519-signed receipts. Uses the public pkg/receiptspec from agentgate v0.1.4.
pkg/approval, pkg/dataset: human approve, reject and edit via annotation protocol and webhook stamping. Exports labeled examples.
pkg/tracing/decisiontrace: one trace span per layer.
tools/decision-train: offline trainer for the model layer.
Chart: global.receipts and decision-model values.
scripts/demo-claims.sh: runs every claim end to end on kind.
go test ./... passes except TestControllers in internal/controller. It needs envtest assets that this machine lacks and fails the same way on main.
make lint passes
OSS/private boundary guard and issue-first guard pass locally
No private-repo content leaked into OSS core
Commits are signed off (git commit -s), human-authored
Documentation updated
How to test
go build ./... && go vet ./... && make lint
go test ./pkg/... ./cmd/... ./tools/...
scripts/demo-claims.sh # needs kind, kubectl, helm, docker
demo-claims.sh prints a PASS line per claim: allow, deny by invariant, deny by pack, deny by threshold, require approval, model escalate, human approve, reject and edit.
Known gaps
Listed in BLOCKERS.md. They are documented, not hidden:
F7: dataset content is not bound to the original decision record.
F11: writer recovery trusts local files.
F12: deleted approval rows are not detected without a signed dataset manifest.
Runtime-adapter path runs no invariants, packs, receipts or approvals. Packs fail closed there.
Execution outcomes are not receipted. Only the pre-execution decision is.
Related issues
Relates to the decision architecture planning in agentgate. Companion docs PR: Clawdlinux/agentgate#35.
Split decision inputs by trust: declared, observed, agent-claimed.
Add pkg/dataclass deterministic detectors (email, phone, aadhaar,
pan, iban, card). Add pkg/decision/input, pkg/decision/observe, and
decision.Combine so claimed values can only tighten.
Add optional spec.declaredIntent to AgentWorkload. On the legacy
action path, undeclared data classes or destinations deny in strict
mode and escalate otherwise. Behaviour without declaredIntent is
unchanged.
Docs: docs/policy-input.md, sample manifest, ADR and README links.
Signed-off-by: Shreyansh Sancheti <007ssancheti@gmail.com>
Invariants INV-01..05 in pkg/invariants. INV-01 denies credential-shaped
values even without declaredIntent. New dataclass class: credential.
pkg/rules/engine embeds OPA v1.19.1 (last release on Go 1.25). Packs
dpdp-in@v0.1.0 and gdpr-eu@v0.1.0 ship via go:embed with Rego unit tests
run under go test. Packs only add deny or require_approval.
pkg/decision.Decide merges layers, strictest wins. Pack approval never
auto-allows. Opt in with spec.policyPacks. Unknown packs are rejected by
the webhook and fail closed in the controller. Packs on orchestrated
runtimes fail closed; invariants and packs run on the direct path only.
pkg/opa moved to pkg/rules/threshold. pkg/opa kept as deprecated aliases.
agentctl migrated to tablewriter v1, which OPA requires.
Signed-off-by: Shreyansh Sancheti <007ssancheti@gmail.com>
Status-only updates re-triggered Reconcile, which re-proposed and re-ran
the direct-path action in a tight loop (1638 receipts in one demo run).
Filter on generation, annotation, label, and deletion changes. Terminal
paths already return without requeue, so nothing relied on the echo.
MCP status, proposal, and execution values can hold personal data or
credentials. Log field counts only.
Signed-off-by: Shreyansh Sancheti <007ssancheti@gmail.com>
scripts/demo-claims.sh proves the decision-architecture claims with no
API keys. A deterministic mock MCP server plays the agent. Eight
scenarios print the exact command and a PASS or FAIL line, and the
script exits nonzero on any failure.
The repo Dockerfile cannot build while go.mod carries the local
receiptspec replace, so the demo builds linux binaries on the host and
packages them in a demo-only image loaded with kind load.
Signed-off-by: Shreyansh Sancheti <007ssancheti@gmail.com>
kindnet enforces NetworkPolicy. The chart's default-deny egress has no
rule for an MCP endpoint, so after the scenario 7 helm upgrade the new
operator pod could not reach the mock. Allow the kind pod CIDR on the
mock port only. Pass the kind context to every helm and kubectl call.
Signed-off-by: Shreyansh Sancheti <007ssancheti@gmail.com>
Document scripts/demo-claims.sh with its measured runtime, what it
proves, and what it does not. Update the audit row to describe opt-in
decision receipts on the direct path.
Signed-off-by: Shreyansh Sancheti <007ssancheti@gmail.com>
ADR Today vs target now lists the event filter, log redaction, the claims
demo, and what is not built. BLOCKERS gains the demo image detour and the
known gaps the demo exposed. CHANGELOG Unreleased summarizes the series.
values.yaml notes that the egress policy has no MCP endpoint rule.
Signed-off-by: Shreyansh Sancheti <007ssancheti@gmail.com>
Scans past depth, node, byte, or per-string limits used to drop the
rest silently. A credential past 64 KiB escaped INV-01, INV-03/04 and
packs. Scan now reports completeness and INV-06 denies incomplete
scans.
Signed-off-by: Shreyansh Sancheti <007ssancheti@gmail.com>
Redact credential and personal values from action-derived log fields and
status messages. Validate that a 64-byte Ed25519 key matches its seed in both
loaders. Fail receipt chain locking on non-unix builds. Allowlist fake
credential fixtures in the secret scanner. Correct INV-06, OPA, threat model
and stale replace notes in docs.
Signed-off-by: Shreyansh Sancheti <007ssancheti@gmail.com>
Redact sensitive action text before creating signed receipts
pkg/receipts/record.go:341
Action text is copied into the record and later into the signed receipt. A denied action can contain detected credentials or personal data. This contradicts the receipt privacy guarantee because INV-01 actions are still receipted. Redact or hash action-derived fields and threshold reasons before building the record.
Prevent broad egress policy overlap for the signing-key pod
charts/templates/_helpers.tpl:110
This label also matches the broad egress policy selector in charts/templates/networkpolicy.yaml:38-40. Kubernetes unions allowed egress across matching policies. The writer's separate egress: [] therefore does not isolate its signing-key pod from DNS and platform services. Exclude this component from the broad policy or avoid the matching label.
…t allowlist
The webhook rejects changes to declaredIntent, policyPacks, opaPolicy,
decisionModel and approvalCapture while an approval is pending. agentctl
dataset verify requires a pinned trust root, and decision eval counts data as
verified only with one. The secret scanner allows exact fixture values instead
of whole files.
Signed-off-by: Shreyansh Sancheti <007ssancheti@gmail.com>
This comment says v0.1.4 is untagged and the root Dockerfile cannot build. BLOCKERS.md:14-17 states v0.1.4 is pinned and that Dockerfile now builds. Update this explanation to avoid contradictory build guidance.
…ect required without enabled
The writer pods no longer carry part-of agentic-operator, which the broad
egress allow policy selects. NetworkPolicy rules add up, so the writer's own
deny could not revoke it. global.receipts.required=true now fails the render
unless enabled=true, so the operator cannot run with receipts silently off.
Signed-off-by: Shreyansh Sancheti <007ssancheti@gmail.com>
Redact JSON map keys with collision-safe placeholders
pkg/dataset/dataset.go:227
Redacted capture preserves map keys verbatim. An email or credential used as a JSON key is written raw to approvals.jsonl. Redact keys too, with a collision-safe placeholder scheme.
Align object-presence checks with IsZero behavior
docs/policy-input.md:31
This says object presence activates the checks, but Declared.IsZero skips them when every field is empty. Align this with the implemented and invariant-documented rule.
…whole tokens
The remote writer client treats the head as unknown from the POST until a
verified reply extends it, so a lost reply forces a resync instead of stacking
another receipt on a stale head. The secret scanner removes fixture values
only when they are whole tokens, so a longer token that starts with one still
fails.
Signed-off-by: Shreyansh Sancheti <007ssancheti@gmail.com>
Redact untrusted MCP action names in workload status
internal/controller/reservation.go:28
The reservation condition persists the untrusted MCP action name without redaction. Credential or personal data in the name will remain in workload status. Apply safeLogText here too.
Remove approved proposals to prevent duplicate action counting
pkg/decision/observe/observe.go:63
Approved actions remain in ProposedActions with Approved=false and are also appended to ExecutedActions. This counts one approved action twice and permanently increments prior_denied, skewing model features. Update or remove the matching proposal when approval succeeds.
Redact sensitive action fields before decision receipt creation
CHANGELOG.md:46
This privacy claim is false. Decision records store Action, Observed.Tool, and threshold reasons verbatim. An MCP action containing a credential is therefore persisted in signed JSONL, even when INV-01 denies it. Hash or redact these fields before receipt creation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Implements the decision architecture so the docs match the code. An AgentWorkload action now passes through ordered layers, and every decision ends in a signed receipt.
Layers, in order: invariants (INV-01 to INV-06), policy packs, threshold, optional model, human approval. The first deny wins. Nothing can be loosened by a later layer.
Packages
pkg/invariants: hard rules that no pack, model or human can override.pkg/rules: policy engine (OPA, Go 1.25 compatible), packs, threshold rules.pkg/dataclass,pkg/decision: data classification, the layered decision flow, model shadow mode.pkg/receipts,cmd/receipt-writer: hash-chained, Ed25519-signed receipts. Uses the publicpkg/receiptspecfrom agentgate v0.1.4.pkg/approval,pkg/dataset: human approve, reject and edit via annotation protocol and webhook stamping. Exports labeled examples.pkg/tracing/decisiontrace: one trace span per layer.tools/decision-train: offline trainer for the model layer.global.receiptsand decision-model values.scripts/demo-claims.sh: runs every claim end to end on kind.Docs
docs/architecture/decision-architecture.md(ADR),invariants.md,decision-model.md,docs/policy-input.md,policy-packs.md,receipts.md,approvals.md,TRACING.md,BLOCKERS.md,CHANGELOG.md.Type of change
Checklist
go build ./...passesgo vet ./...passesgo test ./...passes exceptTestControllersininternal/controller. It needs envtest assets that this machine lacks and fails the same way onmain.make lintpassesgit commit -s), human-authoredHow to test
demo-claims.shprints a PASS line per claim: allow, deny by invariant, deny by pack, deny by threshold, require approval, model escalate, human approve, reject and edit.Known gaps
Listed in
BLOCKERS.md. They are documented, not hidden:Related issues
Relates to the decision architecture planning in agentgate. Companion docs PR: Clawdlinux/agentgate#35.