feat: Workbench policy enforcement - #4055
Conversation
Soffi AI SummaryThis PR introduces a full Workbench Policy Enforcement feature in the security section of the Console frontend. The motivation is to give operators a way to define, manage, and attach security policies to workbenches and stacks — enforcing governance rules on AI agent sessions and infrastructure runs. Key changes:
Updated: 2026-08-27 11:20 UTC |
|
plural review this |
| def evaluate_policy(%{policy_id: id, input: input, policy: source}, _) | ||
| when is_binary(source) do | ||
| with %{type: type} <- Policy.get_policy(id) do | ||
| Policy.evaluate_custom_policy(type, source, input) | ||
| else | ||
| _ -> {:error, "not found"} | ||
| end | ||
| end |
There was a problem hiding this comment.
Reviewed current head 06964013. Previous feedback is addressed: custom evaluation is split and validated/capped, attachment counts are batched, the binding index exists, picker pagination/selected injection works, the Resource header is present, and Gatekeeper reset clears filters. I found the following remaining authorization/data-integrity and pagination/layout issues that need resolution.
Validation performed: git diff --check 83b5411504b6821ab50c002b65e288687393e6ef...06964013b6385bf12795336a428b44cd545a121a passed; no application tests/builds/generators were run during this static review.
There was a problem hiding this comment.
update_policy/3 authorizes the persisted policy before applying caller-controlled attributes, but Policy.changeset/2 permits project_id (and type) changes. A writer of a policy in project A can therefore transfer it to project B without authorization on B; changing type can also leave existing workbench/stack/binding associations incompatible. Authorize the requested post-update ownership/resource (or explicitly authorize both old and destination projects), and reject or safely reconcile type changes when dependent attachments exist. Add a regression test for an inaccessible destination project.
There was a problem hiding this comment.
Remaining findings (supplement to current review)
- B — attachment-rule update authorization:
update_binding_policy/3must authorize both caller-suppliedpolicy_idandbind_policy_id(and their post-update relationship), not only the persisted rule. Reject inaccessible replacements; add tests showing a user cannot re-point either field to a policy outside their access. - C — binding-rule type integrity: On create and update, require the target
policy_idtype to match the rule target (workbench/stack) and requirebind_policy_idto be a binding/evaluator policy. Enforce this server-side and add valid/invalid type-combination tests for both mutations. - D — stable attachment cursors: Order Relay attachment rows by a deterministic unique composite key (for example timestamp plus resource type and ID) before cursor pagination, including timestamp ties. Add pagination tests with equal timestamps proving pages have no duplicate or skipped attachments.
|
plural review this |
There was a problem hiding this comment.
Reviewed current head 080bf760. The earlier simulator validation/size-cap, binding provenance/counts, picker pagination, and policy-update ownership/type fixes are present. Two blocking issues remain:
- Custom-source simulation bypasses resource authorization.
- Policy create/detail and attachment-rule routes bypass the Security layout, so the Security navigation disappears.
Please add regression coverage for both fixes. I did not run the test suite in this review environment.
There was a problem hiding this comment.
Thanks for addressing the earlier validation, binding provenance/count, selector pagination, and immutable project/type concerns. I still found three authorization/routing issues that need correction before merge:
- Custom policy simulation does not authorize the selected policy against
current_user. - Binding-policy updates do not authorize or type-check replacement policy IDs.
- Policy detail/evaluation/attachment routes remain outside the Security layout.
|
plural review this |
Test Plan
Test environment: https://console.your-env.onplural.sh/
Checklist
Plural Flow: console