warrantkit 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentcontain/__init__.py +90 -0
- agentcontain/__main__.py +3 -0
- agentcontain/cli.py +154 -0
- agentcontain/demo.py +124 -0
- agentcontain/engine.py +525 -0
- agentcontain/events.py +54 -0
- agentcontain/evidence.py +398 -0
- agentcontain/external_evidence.py +91 -0
- agentcontain/fleet.py +163 -0
- agentcontain/fleet_status.py +85 -0
- agentcontain/fleet_status_history.py +69 -0
- agentcontain/identity.py +47 -0
- agentcontain/incident.py +98 -0
- agentcontain/ingest.py +36 -0
- agentcontain/operator.py +182 -0
- agentcontain/policy.py +38 -0
- agentcontain/policy_assignment.py +111 -0
- agentcontain/policy_distribution.py +81 -0
- agentcontain/policy_reconciliation.py +191 -0
- agentcontain/policy_rollout.py +111 -0
- agentcontain/state.py +116 -0
- agentcontain/store.py +49 -0
- warrantkit-0.1.0.dist-info/METADATA +394 -0
- warrantkit-0.1.0.dist-info/RECORD +28 -0
- warrantkit-0.1.0.dist-info/WHEEL +5 -0
- warrantkit-0.1.0.dist-info/entry_points.txt +3 -0
- warrantkit-0.1.0.dist-info/licenses/LICENSE +85 -0
- warrantkit-0.1.0.dist-info/top_level.txt +1 -0
agentcontain/__init__.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""WarrantKit platform primitives.
|
|
2
|
+
|
|
3
|
+
The platform layer defines policy, execution identity, lifecycle state, structured
|
|
4
|
+
events, and transport-neutral evidence around the AgentContainment engine.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .engine import (
|
|
8
|
+
Admission,
|
|
9
|
+
admit,
|
|
10
|
+
build_agentcontainment_engine,
|
|
11
|
+
containment_receipt,
|
|
12
|
+
detect,
|
|
13
|
+
evidence_envelope,
|
|
14
|
+
halt,
|
|
15
|
+
issue_recovery_authorization,
|
|
16
|
+
recover,
|
|
17
|
+
recontain,
|
|
18
|
+
verify,
|
|
19
|
+
)
|
|
20
|
+
from .events import Event, EventLog
|
|
21
|
+
from .evidence import EvidenceEnvelope, canonical_json
|
|
22
|
+
from .external_evidence import ExternalEvidenceReference
|
|
23
|
+
from .fleet import Agent, FleetRegistry, FleetScope, Organization, Project, Runtime
|
|
24
|
+
from .fleet_status import FleetPolicyStatus, fleet_policy_status
|
|
25
|
+
from .fleet_status_history import FleetPolicyStatusHistory, FleetPolicyStatusSnapshot
|
|
26
|
+
from .identity import ExecutionIdentity
|
|
27
|
+
from .incident import IncidentStatus, IncidentSummary
|
|
28
|
+
from .operator import EvidenceTimelineEvent, OperatorIncidentView
|
|
29
|
+
from .policy import Policy
|
|
30
|
+
from .policy_assignment import AssignmentState, PolicyAssignment, PolicyAssignmentRegistry
|
|
31
|
+
from .policy_reconciliation import (
|
|
32
|
+
RolloutReconciliation,
|
|
33
|
+
TargetReconciliation,
|
|
34
|
+
TargetReconciliationState,
|
|
35
|
+
reconcile_rollout,
|
|
36
|
+
)
|
|
37
|
+
from .policy_rollout import Rollout, RolloutState
|
|
38
|
+
from .policy_distribution import PolicyBundle, PolicyRegistry
|
|
39
|
+
from .state import LifecycleState, PlatformStateMachine
|
|
40
|
+
from .store import EvidenceStore, InMemoryEvidenceStore
|
|
41
|
+
|
|
42
|
+
__all__ = [
|
|
43
|
+
"Admission",
|
|
44
|
+
"Event",
|
|
45
|
+
"EventLog",
|
|
46
|
+
"EvidenceStore",
|
|
47
|
+
"InMemoryEvidenceStore",
|
|
48
|
+
"EvidenceEnvelope",
|
|
49
|
+
"ExternalEvidenceReference",
|
|
50
|
+
"Agent",
|
|
51
|
+
"FleetRegistry",
|
|
52
|
+
"FleetScope",
|
|
53
|
+
"Organization",
|
|
54
|
+
"Project",
|
|
55
|
+
"Runtime",
|
|
56
|
+
"FleetPolicyStatus",
|
|
57
|
+
"fleet_policy_status",
|
|
58
|
+
"FleetPolicyStatusHistory",
|
|
59
|
+
"FleetPolicyStatusSnapshot",
|
|
60
|
+
"ExecutionIdentity",
|
|
61
|
+
"IncidentStatus",
|
|
62
|
+
"IncidentSummary",
|
|
63
|
+
"EvidenceTimelineEvent",
|
|
64
|
+
"OperatorIncidentView",
|
|
65
|
+
"LifecycleState",
|
|
66
|
+
"PlatformStateMachine",
|
|
67
|
+
"Policy",
|
|
68
|
+
"AssignmentState",
|
|
69
|
+
"PolicyAssignment",
|
|
70
|
+
"PolicyAssignmentRegistry",
|
|
71
|
+
"TargetReconciliationState",
|
|
72
|
+
"TargetReconciliation",
|
|
73
|
+
"RolloutReconciliation",
|
|
74
|
+
"reconcile_rollout",
|
|
75
|
+
"Rollout",
|
|
76
|
+
"RolloutState",
|
|
77
|
+
"PolicyBundle",
|
|
78
|
+
"PolicyRegistry",
|
|
79
|
+
"admit",
|
|
80
|
+
"build_agentcontainment_engine",
|
|
81
|
+
"canonical_json",
|
|
82
|
+
"containment_receipt",
|
|
83
|
+
"detect",
|
|
84
|
+
"evidence_envelope",
|
|
85
|
+
"halt",
|
|
86
|
+
"issue_recovery_authorization",
|
|
87
|
+
"recover",
|
|
88
|
+
"recontain",
|
|
89
|
+
"verify",
|
|
90
|
+
]
|
agentcontain/__main__.py
ADDED
agentcontain/cli.py
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""Small operator-facing WarrantKit CLI."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from .engine import (
|
|
12
|
+
admit,
|
|
13
|
+
build_agentcontainment_engine,
|
|
14
|
+
containment_receipt,
|
|
15
|
+
contain,
|
|
16
|
+
evidence_envelope,
|
|
17
|
+
)
|
|
18
|
+
from .policy import Policy
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _policy_from_args(args: argparse.Namespace) -> Policy:
|
|
22
|
+
return Policy(policy_id=args.policy, capabilities=tuple(args.capability), allowed_egress=tuple(args.egress))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
26
|
+
parser = argparse.ArgumentParser(prog="warrantkit", description="WarrantKit runtime authorization, enforcement, and proof platform for autonomous AI agents.")
|
|
27
|
+
sub = parser.add_subparsers(dest="command", required=True)
|
|
28
|
+
inspect = sub.add_parser("inspect", help="inspect an evidence envelope as an operator incident")
|
|
29
|
+
inspect.add_argument("--evidence-file", required=True, help="JSON evidence envelope produced by WarrantKit")
|
|
30
|
+
inspect.add_argument("--json", action="store_true", help="emit the complete operator view as JSON")
|
|
31
|
+
demo = sub.add_parser("demo", help="run the no-root proof semantics demo")
|
|
32
|
+
run = sub.add_parser("run", help="admit an execution and optionally contain it")
|
|
33
|
+
run.add_argument("--policy", required=True, help="policy identifier")
|
|
34
|
+
run.add_argument("--agent-id", default="agent", help="agent identity")
|
|
35
|
+
run.add_argument("--capability", action="append", default=[], help="declared capability")
|
|
36
|
+
run.add_argument("--egress", action="append", default=[], help="allowed egress target")
|
|
37
|
+
run.add_argument("--cgroup-path", help="existing Linux cgroup-v2 path for this workload")
|
|
38
|
+
run.add_argument("--receipt-secret-file", help="read the HMAC receipt secret from a file instead of exposing it in argv")
|
|
39
|
+
run.add_argument("--receipt-secret-env", default="WARRANTKIT_RECEIPT_SECRET", help="environment variable containing the HMAC receipt secret")
|
|
40
|
+
run.add_argument("--evidence-output", help="write the complete evidence envelope to this JSON file")
|
|
41
|
+
run.add_argument("--contain", action="store_true", help="invoke external containment immediately after admission")
|
|
42
|
+
run.add_argument("--json", action="store_true", help="emit machine-readable execution state")
|
|
43
|
+
return parser
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def main(argv: list[str] | None = None) -> int:
|
|
47
|
+
args = build_parser().parse_args(argv)
|
|
48
|
+
if args.command == "inspect":
|
|
49
|
+
try:
|
|
50
|
+
from .evidence import EvidenceEnvelope
|
|
51
|
+
from .operator import OperatorIncidentView
|
|
52
|
+
envelope = EvidenceEnvelope.from_json(Path(args.evidence_file).read_text(encoding="utf-8"))
|
|
53
|
+
view = OperatorIncidentView.from_evidence(envelope)
|
|
54
|
+
if args.json:
|
|
55
|
+
print(json.dumps(view.to_dict(), sort_keys=True, indent=2))
|
|
56
|
+
else:
|
|
57
|
+
incident = view.incident
|
|
58
|
+
print(f"Incident {incident.incident_id}")
|
|
59
|
+
print(f" Agent: {view.agent.get('agent_id', 'unknown')}")
|
|
60
|
+
print(f" Policy: {view.policy.get('policy_id', 'unknown')}")
|
|
61
|
+
print(f" Event: {incident.trigger or 'none'}")
|
|
62
|
+
print(f" Status: {incident.status.value.upper()}")
|
|
63
|
+
print(f" Proof: {incident.proof_status}")
|
|
64
|
+
if view.receipt_id:
|
|
65
|
+
print(f" Receipt: {view.receipt_id}")
|
|
66
|
+
print(" Timeline:")
|
|
67
|
+
for event in view.timeline:
|
|
68
|
+
print(f" {event.sequence}. {event.name}")
|
|
69
|
+
return 0
|
|
70
|
+
except Exception as exc:
|
|
71
|
+
print(f"warrantkit: {exc}", file=sys.stderr)
|
|
72
|
+
return 1
|
|
73
|
+
if args.command == "demo":
|
|
74
|
+
from .demo import run_demo
|
|
75
|
+
return run_demo()
|
|
76
|
+
if args.command == "run":
|
|
77
|
+
policy = _policy_from_args(args)
|
|
78
|
+
try:
|
|
79
|
+
engine = build_agentcontainment_engine(args.agent_id, cgroup_path=args.cgroup_path)
|
|
80
|
+
admission = admit(policy, agent_id=args.agent_id, engine=engine)
|
|
81
|
+
report = contain(admission) if args.contain else None
|
|
82
|
+
|
|
83
|
+
receipt_secret = None
|
|
84
|
+
if args.receipt_secret_file:
|
|
85
|
+
receipt_secret = Path(args.receipt_secret_file).read_text(encoding="utf-8").rstrip("\r\n").encode("utf-8")
|
|
86
|
+
elif args.receipt_secret_env:
|
|
87
|
+
configured_secret = os.environ.get(args.receipt_secret_env)
|
|
88
|
+
if configured_secret:
|
|
89
|
+
receipt_secret = configured_secret.encode("utf-8")
|
|
90
|
+
elif args.receipt_secret_env == "WARRANTKIT_RECEIPT_SECRET":
|
|
91
|
+
legacy_secret = os.environ.get("AGENTCONTAIN_RECEIPT_SECRET")
|
|
92
|
+
if legacy_secret:
|
|
93
|
+
receipt_secret = legacy_secret.encode("utf-8")
|
|
94
|
+
|
|
95
|
+
receipt = (
|
|
96
|
+
containment_receipt(admission, receipt_secret)
|
|
97
|
+
if receipt_secret is not None and report is not None
|
|
98
|
+
else None
|
|
99
|
+
)
|
|
100
|
+
envelope = evidence_envelope(admission)
|
|
101
|
+
if receipt is not None:
|
|
102
|
+
envelope = envelope.with_receipt(receipt.to_dict())
|
|
103
|
+
|
|
104
|
+
payload = {
|
|
105
|
+
"execution_id": admission.identity.execution_id,
|
|
106
|
+
"agent_id": admission.identity.agent_id,
|
|
107
|
+
"policy_id": admission.identity.policy_id,
|
|
108
|
+
"policy_digest": admission.identity.policy_digest,
|
|
109
|
+
"epoch": admission.identity.epoch,
|
|
110
|
+
"state": admission.machine.state.value,
|
|
111
|
+
"events": [event.to_dict() for event in admission.machine.events.events],
|
|
112
|
+
}
|
|
113
|
+
if report is not None:
|
|
114
|
+
payload["containment"] = {
|
|
115
|
+
"complete": report.complete,
|
|
116
|
+
"certified": getattr(report, "certified", False),
|
|
117
|
+
"durable": getattr(report, "durable", False),
|
|
118
|
+
"external_verified": getattr(report, "external_verified", False),
|
|
119
|
+
"enforcement_latency_seconds": getattr(report, "enforcement_latency_seconds", None),
|
|
120
|
+
"failures": list(getattr(report, "failures", ())),
|
|
121
|
+
}
|
|
122
|
+
if receipt is not None:
|
|
123
|
+
payload["receipt"] = receipt.to_dict()
|
|
124
|
+
|
|
125
|
+
if args.evidence_output:
|
|
126
|
+
Path(args.evidence_output).write_text(
|
|
127
|
+
envelope.to_json() + "\n",
|
|
128
|
+
encoding="utf-8",
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
if args.json:
|
|
132
|
+
print(json.dumps(payload, sort_keys=True, indent=2))
|
|
133
|
+
else:
|
|
134
|
+
print(f"WarrantKit execution {payload['execution_id']}")
|
|
135
|
+
print(f" Agent: {payload['agent_id']}")
|
|
136
|
+
print(f" Policy: {payload['policy_id']}")
|
|
137
|
+
print(f" Epoch: {payload['epoch']}")
|
|
138
|
+
print(f" State: {payload['state'].upper()}")
|
|
139
|
+
for event in admission.machine.events.events:
|
|
140
|
+
print(f" Event: {event.name}")
|
|
141
|
+
if report is not None:
|
|
142
|
+
status = "VERIFIED" if report.certified and report.durable else "DEGRADED"
|
|
143
|
+
print(f" Containment: {status}")
|
|
144
|
+
if args.evidence_output:
|
|
145
|
+
print(f" Evidence: {args.evidence_output}")
|
|
146
|
+
return 0
|
|
147
|
+
except Exception as exc:
|
|
148
|
+
print(f"warrantkit: {exc}", file=sys.stderr)
|
|
149
|
+
return 1
|
|
150
|
+
return 2
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
if __name__ == "__main__":
|
|
154
|
+
raise SystemExit(main())
|
agentcontain/demo.py
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""No-privilege demonstration of WarrantKit lifecycle and proof semantics."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import hmac
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from .engine import admit, evidence_envelope
|
|
11
|
+
from .evidence import EvidenceEnvelope, canonical_json
|
|
12
|
+
from .operator import OperatorIncidentView
|
|
13
|
+
from .policy import Policy
|
|
14
|
+
|
|
15
|
+
_DEMO_KEY = b"warrantkit-demo-key-v1"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(frozen=True)
|
|
19
|
+
class DemoReport:
|
|
20
|
+
complete: bool = True
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class SimulatedEngine:
|
|
24
|
+
"""Demo-only engine. It does not enforce a kernel boundary."""
|
|
25
|
+
|
|
26
|
+
def contain(self) -> DemoReport:
|
|
27
|
+
return DemoReport()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _issue_receipt(evidence: EvidenceEnvelope) -> dict[str, Any]:
|
|
31
|
+
payload = {
|
|
32
|
+
"schema_version": 1,
|
|
33
|
+
"receipt_id": "demo-" + evidence.execution["execution_id"],
|
|
34
|
+
"execution_id": evidence.execution["execution_id"],
|
|
35
|
+
"agent_id": evidence.execution["agent_id"],
|
|
36
|
+
"epoch": evidence.execution["epoch"],
|
|
37
|
+
"containment": {
|
|
38
|
+
"requested": True,
|
|
39
|
+
"enforced": True,
|
|
40
|
+
"independently_verified": False,
|
|
41
|
+
"mode": "simulated",
|
|
42
|
+
},
|
|
43
|
+
"proof_status": "observed",
|
|
44
|
+
}
|
|
45
|
+
digest = hashlib.sha256(canonical_json(payload).encode("utf-8")).hexdigest()
|
|
46
|
+
signature = hmac.new(_DEMO_KEY, digest.encode("ascii"), hashlib.sha256).hexdigest()
|
|
47
|
+
return {"payload": payload, "digest": digest, "signature": signature}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _verify_receipt(receipt: dict[str, Any], evidence: EvidenceEnvelope) -> bool:
|
|
51
|
+
payload = receipt["payload"]
|
|
52
|
+
digest = hashlib.sha256(canonical_json(payload).encode("utf-8")).hexdigest()
|
|
53
|
+
signature = hmac.new(_DEMO_KEY, digest.encode("ascii"), hashlib.sha256).hexdigest()
|
|
54
|
+
return (
|
|
55
|
+
hmac.compare_digest(digest, receipt["digest"])
|
|
56
|
+
and hmac.compare_digest(signature, receipt["signature"])
|
|
57
|
+
and payload["execution_id"] == evidence.execution["execution_id"]
|
|
58
|
+
and payload["agent_id"] == evidence.execution["agent_id"]
|
|
59
|
+
and payload["epoch"] == evidence.execution["epoch"]
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def run_demo() -> int:
|
|
64
|
+
admission = admit(
|
|
65
|
+
Policy("demo", capabilities=("simulated-containment",)),
|
|
66
|
+
agent_id="demo-agent",
|
|
67
|
+
engine=SimulatedEngine(),
|
|
68
|
+
)
|
|
69
|
+
if not admission.engine.contain().complete:
|
|
70
|
+
raise RuntimeError("simulated containment failed")
|
|
71
|
+
|
|
72
|
+
admission.machine.contain()
|
|
73
|
+
admission.machine.detect({"reason": "demo_policy_violation"})
|
|
74
|
+
admission.machine.fence()
|
|
75
|
+
admission.machine.halt()
|
|
76
|
+
admission.machine.verify()
|
|
77
|
+
|
|
78
|
+
base = evidence_envelope(admission)
|
|
79
|
+
evidence = EvidenceEnvelope.from_execution(
|
|
80
|
+
execution=base.execution,
|
|
81
|
+
events=base.events,
|
|
82
|
+
enforcement={"complete": True, "mode": "simulated", "external_enforcement": False},
|
|
83
|
+
verification={"status": "observed", "method": "warrantkit-no-root-demo"},
|
|
84
|
+
proof={"simulated": True, "host_enforcement_verified": False},
|
|
85
|
+
provenance={"producer": "warrantkit-demo"},
|
|
86
|
+
)
|
|
87
|
+
receipt = _issue_receipt(evidence)
|
|
88
|
+
evidence = evidence.with_receipt(receipt)
|
|
89
|
+
evidence.validate()
|
|
90
|
+
|
|
91
|
+
if not _verify_receipt(receipt, evidence):
|
|
92
|
+
raise RuntimeError("demo receipt verification failed")
|
|
93
|
+
|
|
94
|
+
view = OperatorIncidentView.from_evidence(evidence)
|
|
95
|
+
incident = view.incident
|
|
96
|
+
|
|
97
|
+
print("WarrantKit — reference incident experience")
|
|
98
|
+
print("--------------------------------------------")
|
|
99
|
+
print(f"Execution: {admission.identity.execution_id}")
|
|
100
|
+
print(f"Agent: {view.agent['agent_id']}")
|
|
101
|
+
print(f"Policy: {view.policy['policy_id']}")
|
|
102
|
+
print(f"Policy digest: {view.policy['policy_digest']}")
|
|
103
|
+
print("Mode: SIMULATED (no kernel enforcement)")
|
|
104
|
+
print()
|
|
105
|
+
print("Incident")
|
|
106
|
+
print(f" Trigger: {incident.trigger or 'none'}")
|
|
107
|
+
print(f" Status: {incident.status.value.upper()}")
|
|
108
|
+
print(f" Proof: {incident.proof_status.upper()}")
|
|
109
|
+
print()
|
|
110
|
+
print("Lifecycle / evidence")
|
|
111
|
+
for event in view.timeline:
|
|
112
|
+
print(f" {event.sequence}. {event.name}")
|
|
113
|
+
print()
|
|
114
|
+
print("Proof")
|
|
115
|
+
print(" Evidence: OBSERVED")
|
|
116
|
+
print(" Verification: NOT CLAIMED (simulated)")
|
|
117
|
+
print(" Receipt: AUTHENTICATED")
|
|
118
|
+
print(f" Receipt ID: {view.receipt_id}")
|
|
119
|
+
print()
|
|
120
|
+
print("Verified ≠ claim is true")
|
|
121
|
+
print("This reference experience demonstrates the platform procedure,")
|
|
122
|
+
print("operator projection, and receipt integrity.")
|
|
123
|
+
print("It does not prove real host or kernel containment.")
|
|
124
|
+
return 0
|