Failsafe write guards for AI-driven abilities#18
Merged
Conversation
Member
Author
|
Companion (assistant side, consumes the |
…abilities The Gravity Forms abilities (forms-*, feeds-*) call GFAPI directly with permission_callback => __return_true and no internal check, so any chat user (edit_posts) could edit/delete forms and feeds — breaking integrations — or read submissions (PII). CapabilityPolicy requires manage_options for them via wp_register_ability_args. Deliberately narrow: other write abilities already enforce caps internally or via their REST controller, and reads are intentionally public, so they're left untouched. Filterable via gds-mcp/ability_capability. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…onfirmation forms-update fully replaces the fields array; dropping a field or changing its type orphans that field's submitted entries, with no revisions to recover. updateForm() now diffs old vs new fields and, when the form has entries, refuses removals/type-changes unless confirm_destructive is set. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
content-delete no longer exposes force=true. Content is always trashed (recoverable); types without trash support fall back to a permanent delete since they have no recoverable option. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
translations-link overwrites Polylang's translation group and can strip a post from its current group, silently orphaning previously-linked posts with no revisions. It now refuses relinks that change a post's language or drop existing siblings unless confirm_destructive is set. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
938a7a9 to
e7ebb1e
Compare
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Failsafes that make AI-assistant-driven writes safe to run in production, focused on operations that have no undo (Gravity Forms fields, taxonomy terms, Polylang translation links). Companion to generoi/gds-assistant#25.
Least-privilege capability for Gravity Forms
Most write abilities already enforce capabilities (internally, returning
forbidden, or via their REST controller), and reads are intentionally public. The exception is the Gravity Forms abilities (forms-*,feeds-*): they call GFAPI directly withpermission_callback => '__return_true'and no internal check, so any chat user (edit_posts) could edit/delete forms and feeds — breaking ActiveCampaign/webhook integrations — or read submissions (PII).CapabilityPolicyrequiresmanage_optionsfor them at registration viawp_register_ability_args, only replacing the permissive default (never loosening a real check). Deliberately narrow; filterable viagds-mcp/ability_capability.Destructive-write guards (data layer)
forms-update— refuses to remove a field or change its type when the form has entries (orphans submissions, no revisions) unlessconfirm_destructiveis set.translations-link— refuses relinks that change a post's language or orphan existing translation siblings unlessconfirm_destructive.force=truepermanent delete removed. Always trashes (recoverable); types without trash support fall back to permanent delete.confirm_destructiveis injected by gds-assistant only after a human approves in chat, so the guards also protect non-chat callers.Tests
CapabilityPolicyTest(new), extendedGravityFormsAbilityTestandLinkTranslationsAbilityTest, updatedContentAbilityTest/WorkflowTestfor trash-only delete.🤖 Generated with Claude Code