Blog · Engineering

Draft-first safety: how the plugin protects your site

Connecting an AI assistant to a live website should feel like handing a careful colleague a login — not like leaving a door open. LIYANS MCP’s safety model is not one feature; it is four habits the plugin never breaks, plus an authorisation rule that runs on every single call. This article walks through each, including the edge cases testing forced us to handle.

Habit 1: everything new is a draft

Pages and products are created with draft status, full stop. Publishing lives on separate, explicit tool paths that require both the publish scope and the WordPress publish capability. This is enforced, not conventional: during development we found that a post_status value passed inside tool arguments could slip past the default and publish directly. The argument is now stripped before any handler runs — the bug is recorded in the shipped changelog, because that is where bugs belong.

Habit 2: deletion means the Trash

The page-removal tool moves content to the WordPress Trash, from which it can be restored like anything you deleted by hand. There is no permanent-delete path for content anywhere in the plugin — not in a tool, not in a setting, not in the uninstaller. Uninstall removes only what the plugin itself wrote: its options, its log and snapshots tables, its cron event, its transients. Your content — including drafts the assistant built — is untouched. We verify this in integration testing: uninstall the plugin on a populated site and diff the content before and after.

Habit 3: snapshots before change

Any operation that rewrites an existing layout — a page update, an element append or remove, a rebuild inside a build session — first stores a snapshot of the previous element tree. liyans_restore_snapshot puts it back byte-for-byte. “Try a different hero section” becomes a reversible experiment instead of a commitment, and the assistant itself can undo its own last step when a verification check fails.

Habit 4: an audit log you own

Every tool call writes a row to a log table in your own database: when, which credential, which tool, success or failure. Retention is configurable, old rows are purged on a daily schedule, and the CSV export is hardened against spreadsheet formula injection — a detail that matters the day someone opens an export in Excel. Argument payloads are only written to the log if you deliberately enable content logging; by default the log keeps operational metadata.

The rule underneath: intersection, evaluated live

None of the habits matter if authorisation is sloppy, so the check is strict and live. A call is allowed only if the tool is inside the token’s scopes and the token’s owning WordPress account currently holds the tool’s required capability. Demote the account and its tokens weaken instantly. Read-scoped connections cannot see drafts, private posts, trashed items or store revenue — and verification tools apply the same unpublished-post guard as reading tools, so a read-only caller cannot even learn that a particular draft exists. That last leak — two verification tools skipping the guard — was found in our own audit and fixed in 1.2.0; the fix is described in the changelog, not hidden.

Safety, in the end, is what makes the connection usable at all. A tool you have to supervise nervously saves no time. One that drafts, trashes, snapshots and logs by default can simply be left on — which is when it starts paying for itself. In time, that is; it costs nothing in money.

← Back to the blog  ·  The full security model