Concepts
How intent plans, drift detection, and CSRG proofs work together
Concepts
ArmorCopilot enforces security at two layers: intent (what Copilot said it would do) and policy (what you said is allowed). Both must pass before a tool runs.
Intent Plans
Every Copilot session begins with a plan. The userPromptSubmitted hook injects a directive into Copilot's context telling it to call the register_intent_plan MCP tool as its first action.
A plan has this shape:
{
"goal": "Add a summary file for /etc",
"steps": [
{
"action": "write",
"description": "Create the summary file",
"metadata": { "inputs": { "file_path": "/tmp/etc-notes.md" } }
},
{
"action": "read",
"description": "Verify the file was written",
"metadata": { "inputs": { "file_path": "/tmp/etc-notes.md" } }
}
],
"session_id": "<copilot-session-uuid>"
}ArmorCopilot normalizes the plan, mints a signed intent JWT against the ArmorIQ backend (if connected), and writes a pending plan file at ~/.copilot/armorcopilot/pending-plan.<session_id>.json.
Per-session paths ensure concurrent Copilot windows don't clobber each other's plans.
Intent Drift
After the plan is registered, every preToolUse hook checks the tool name + arguments against the plan's declared steps.
- If the tool matches a declared step → allow
- If the tool isn't in the plan → block (intent drift)
- If the tool IS in the plan but policy denies it → block (policy wins)
Drift detection catches the case where Copilot says "I'll write the file then verify it" but then quietly tries shell to run rm -rf. Without drift detection, a policy that only blocked rm -rf would not catch the pattern. Drift makes any unplanned tool suspicious by default.
The whitelisted tools register_intent_plan, policy_read, policy_update, plus a small set of read-only coordination tools (read, grep, glob, todowrite, etc.) bypass the drift check. Network egress tools (webfetch, websearch) do not bypass. They go through full policy + intent enforcement.
Policy Rules
Policies are evaluated before intent. A denied tool stays denied even if it's in the plan.
Rules support:
- Tool-name match
- Argument-pattern match (substring or regex)
- Data-class match (PCI / PAYMENT / PHI / PII)
- Compound rules (path conditions, negation)
See Policy Rules for the full command surface + practical patterns.
CSRG Cryptographic Proofs
When backend-connected with crypto_policy_enabled=true, ArmorCopilot signs each step of the intent plan as it executes. The proof chain is bound to a Merkle root that's anchored on the ArmorIQ backend.
Benefits:
- Tamper detection. Any post-hoc modification of audit rows invalidates the chain.
- Step provenance. Each tool call is cryptographically tied to the plan that declared it.
- Compliance evidence. Exportable proof artifacts for SOC 2 / ISO 27001 audits.
CSRG is opt-in. Default is off (intent + policy alone work fine for most enforcement use cases).
Audit Pipeline
Every tool call (allowed OR denied) is enqueued to a local write-ahead log at ~/.copilot/armorcopilot/audit/. A background flusher inside the MCP server batches WAL entries and ships them to the ArmorIQ backend asynchronously.
| Property | Value |
|---|---|
| Durability | Disk-backed (WAL). Survives plugin restart. |
| Delivery | Async batched. Does not block the user-facing tool call. |
| Backpressure | Capped read window (4MiB per batch). Prevents OOM on backend outage. |
| Visibility | platform.armoriq.ai/products/armor-copilot |
If the ArmorIQ backend is unreachable, the WAL grows on disk and flushes when connectivity returns. The user-facing flow is never blocked.