Nothing writes to your site until the exact change is approved.
Every mutating call previews itself first, binds the approval to that exact payload, and refuses to run if either one changes before execution.
Dry-run previews are common now. Exact-match approval still isn't.
Most AI tools ask permission somehow these days. Permission alone doesn't cover these three.
The agent itself
Misreads a value, targets the wrong post ID, or takes a bigger action than you asked for. Nothing separate checks the write before it lands on production.
The person prompting it
The person typing the prompt is usually also the person who'd approve it. Same set of eyes, twice.
A compromised session
A leaked token or hijacked session inherits everything the agent could already do. Nothing else stands in the way.
Named verbs are the front door. Raw code execution is a gated side exit.
Three tiers, ordered by how much damage a single call can do.
Scoped tokens
Every bearer token carries one scope — recon, mutate, or admin — each a strict superset of the one below. Call above your scope and you get a clean 403, never a partial write.
Named verbs
The agent's only normal vocabulary is a closed set of typed actions. Update this option, edit this post, bust this cache. Raw PHP execution still exists, but as a separately gated, admin-only, SSH-only tier. It's never the front door.
Dry-run by default
Every guarded verb defaults to apply=False. The response previews the exact before-and-after plus a change digest — nothing writes until that preview is approved.
An approval authorizes one exact digest. Nothing else.
Every packet binds site, target, verb, arguments, preview, and pre-change state into one hash. Change any of those and the approval stops matching. It can't be reused for a different value, a different target, or a site that's since drifted.
- Site, target resource, and verb name
- Exact normalized arguments (or their canonical hash)
- Risk classification, reason, and a human-readable summary
- Pre-change state hash / ETag
- Sanitized preview or diff
- Approver identity, decision, comment, and timestamp
# dry-run returns a SHA-256 digest over:
change_digest = sha256(
site, verb, target,
normalized_payload, current_etag
)
# execution refuses unless the live request
# still matches the approved digest exactly
wp_mutate_option(…, apply=True,
expected_etag="<etag from preview>")
→ refuses if payload or live state differs
→ PacketRequiredError if no approved packet exists
Three policy outcomes. Approval is a role your team assigns to someone else.
Low-risk, reversible actions go straight through. Nobody babysits every harmless read or trivial change — that's what keeps approval fatigue from setting in.
Risky writes route to a human first. The approver reviews the same preview the requester saw and signs off on that exact digest. Assign the role to someone else, and no one reviews their own work.
Some actions are refused outright by policy, regardless of who's asking or how they ask.
What actually happens when something tries to go wrong.
apply=True and no approved, open packet for that exact site, target, and payload raises PacketRequiredError. No write, no snapshot, nothing touched.etag back as expected_etag catches it. The write refuses instead of silently overwriting someone else's change.packet_close(durable_check_delay_seconds=…) re-reads the mutated value after a delay and flags it if a cache or plugin quietly reverted it. Verification happens twice — once at write time, once again after a delay.Roadmap: a tested, one-click rollback for plugin and theme updates is next. Today's snapshot-before-write covers option and post-meta changes.
Restraint is part of the trust model.
- "Unbreakable," "zero risk," or "AI can never damage your site." We don't say it. It isn't true of any system.
- No SOC 2, HIPAA, or similar compliance claim unless it's been independently verified.
- We don't call the audit ledger "immutable." That word gets earned once it's cryptographically tamper-evident and externally anchored.
- We call it a "snapshot" unless a tested, one-click restore actually exists. "Rollback" is reserved for that.
- We won't say "works with every plugin or page builder" until integration tests prove it, plugin by plugin.
- We won't say "never sends content to Cloud" — two of Cloud's three preview modes carry sanitized or encrypted content. See the exact boundary on the trust architecture page.
The guard stops accidents: a wrong target, a stale write, a tampered approval. It does not stop a fully-authorized caller with a valid admin-scoped token who chooses to misuse it. Read SECURITY.md for the full trust boundaries, known open risks, and how to report a vulnerability.
Walk through the guard on a real client site.
A 30-minute review: map how AI reaches production today, test one harmless dry run, and see the evidence trail.