Files
yidaima/RuoYi-Vue/docs/superpowers/plans/2026-07-11-plugin-separation-of-duties-approval.md

4.0 KiB

Plugin Separation-of-Duties Approval Implementation Plan

For agentic workers: Implement task-by-task with tests first. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Replace the execution operator's inline approval assertion with persistent, independently approved, expiring, revocable, single-use evidence.

Architecture: A Transition-scoped approval journal freezes requester roles and routing identity. Decisions and executions share one Transition-first lock order. Execution copies a complete audit snapshot, atomically consumes the approved row, and only then creates receipts and Outbox work.

Tech Stack: Java 8, Spring Boot 2.5, Spring Security, MyBatis, MySQL 5.7-compatible SQL, JUnit 4, Vue 2, Element UI.

Task 1: Policy And Identity

Files:

  • Modify: PluginExecutionProperties.java

  • Create: PluginApprovalPolicy.java

  • Modify: PluginExecutionRoutingPolicy.java

  • Test: approval and routing policy tests

  • Add bounded request and approved-evidence TTLs, separation switch, and role allowlists.

  • Canonicalize and freeze actor role snapshots.

  • Reject self-approval and disallowed roles.

  • Include all approval policy settings in routing identity.

  • Remove the direct execution-request approval shortcut.

Task 2: Persistent Lifecycle

Files:

  • Create: approval domain and request models

  • Modify: execution domain audit snapshot

  • Modify: PluginTransitionExecutionMapper.java and XML

  • Modify: Factory full and upgrade SQL scripts

  • Add PENDING, APPROVED, REVOKED, CONSUMED, and EXPIRED states.

  • Persist request, decision, revocation, consumption, and expiry evidence.

  • Add immutable requester/approver snapshots to execution rows.

  • Add guarded lifecycle updates and single-execution uniqueness.

  • Keep schema upgrades compatible with MySQL 5.7.

Task 3: Service And Concurrency

Files:

  • Modify: PluginTransitionExecutionService.java

  • Test: PluginTransitionExecutionServiceTest.java

  • Implement request, list, approve, and revoke operations under the Transition lock.

  • Bind approval to exact mode, Transition, routing, environment, and Executor.

  • Apply lazy request and evidence expiry.

  • Consume exactly one approved row before receipts and Outbox creation.

  • Expire sibling requests after consumption and reject post-consumption revocation.

  • Test expiry, self-approval, revocation, consumption races, and immutable audit snapshots.

Task 4: API And Permissions

Files:

  • Modify: FeaturePluginController.java

  • Modify: Registry and delivery status models

  • Modify: sql/plugin_registry_menu.sql

  • Test: FeaturePluginControllerTest.java

  • Add Transition approval request, list, approve, and revoke endpoints.

  • Pass authenticated role keys into the policy layer.

  • Separate execute/request permission from approve/revoke permission.

  • Expose non-secret policy status without target credentials.

  • Add a reflection contract test for permission separation.

Task 5: Dual-Person UI

Files:

  • Modify: ruoyi-ui/src/api/generator/plugin.js

  • Modify: Plugin and delivery verification views

  • Modify: ruoyi-ui/test/pluginRegistryView.test.mjs

  • Add approval lifecycle API functions.

  • Add a Transition approval table with request, approve, revoke, expiry, and audit details.

  • Select only matching approved evidence for real execution.

  • Preserve dry-run confirmation without approval evidence.

  • Show consumed requester/approver evidence in execution history.

Task 6: Documentation And Regression

Files:

  • Create: this implementation plan and the matching design document

  • Modify: AI Software Factory roadmap

  • Document identity, locks, expiry, revocation, consumption, and boundaries.

  • Run 162 focused Plugin tests.

  • Run 805 generator tests: 787 pass and the exact 18 known baseline failures remain.

  • Run 38 admin tests, four frontend static tests, and the production build.

  • Confirm the existing development endpoints return HTTP 200.