Skip to content

feat: Workbench policy enforcement - #4055

Draft
maciaszczykm wants to merge 68 commits into
masterfrom
marcin/prod-5159-workbench-policy-enforcement
Draft

feat: Workbench policy enforcement#4055
maciaszczykm wants to merge 68 commits into
masterfrom
marcin/prod-5159-workbench-policy-enforcement

Conversation

@maciaszczykm

Copy link
Copy Markdown
Member

Test Plan

Test environment: https://console.your-env.onplural.sh/

Checklist

  • I have added a meaningful title and summary to convey the impact of this PR to a user.
  • If required, I have updated the Plural documentation accordingly.
  • I have added tests to cover my changes.
  • I have deployed the agent to a test environment and verified that it works as expected (required only when changing agent code).

Plural Flow: console

@linear

linear Bot commented Aug 25, 2026

Copy link
Copy Markdown

PROD-5159

@maciaszczykm maciaszczykm added the enhancement New feature or request label Aug 25, 2026
@soffi-ai

soffi-ai Bot commented Aug 25, 2026

Copy link
Copy Markdown
Soffi AI Summary

This 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:

  • Policies section rebuilt: The existing monolithic Policies.tsx is refactored into a tabbed layout (PoliciesTabLayout) with dedicated sub-views: a policies list, an attachment rules table, and an evaluations tab.
  • Attachment Rules: New CRUD flows for "binding policies" (attachment rules) that associate a security policy with workbenches or stacks via type, regex matching, and bindings. Includes create/edit forms, a table view, and a delete confirmation flow.
  • Policy Create/Edit: A new PolicyCreateOrEdit form allows authoring policies including identity fields and Rego rule definitions.
  • Bindings modal: A CreateBindingModal enables attaching identity bindings (users/groups) to a policy directly from the wizard.
  • Rego syntax highlighting: A new Monaco editor language registration (registerRegoLanguage.ts) adds syntax highlighting for OPA Rego policy files, with corresponding light and dark editor theme tokens.
  • Gatekeeper renamed and restructured: The existing OPA/Gatekeeper constraint views are moved under a dedicated gatekeeper/ subdirectory and a new Gatekeeper.tsx + GatekeeperTable.tsx + GatekeeperColumns.tsx replace the previously flat structure, separating Gatekeeper constraints from the new custom policies concept.
  • Match count display: Policies now show a match/attachment count chip in the table.
  • Navigation and routing: New absolute/relative route constants are added for all new views, and breadcrumbs are wired up throughout.

Updated: 2026-08-27 11:20 UTC

Deploy in Soffi

@maciaszczykm
maciaszczykm requested a review from a team August 25, 2026 13:13
Comment thread lib/console/deployments/policy.ex Outdated
@maciaszczykm
maciaszczykm requested review from michaeljguarino and a balanced review from Copilot August 27, 2026 10:41
@maciaszczykm

Copy link
Copy Markdown
Member Author

@greptileai

@maciaszczykm

Copy link
Copy Markdown
Member Author

plural review this

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 56 out of 60 changed files in this pull request and generated 4 comments.

Comment on lines +92 to +99
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
Comment thread assets/src/components/security/policies/policy/PolicyDefinition.tsx Outdated
Comment thread assets/src/components/security/policies/policy/policyEval.ts
Comment thread lib/console/schema/binding_policy.ex Outdated

@plural-copilot plural-copilot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread assets/src/routes/securityRoutes.tsx

@plural-copilot plural-copilot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@plural-copilot plural-copilot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remaining findings (supplement to current review)

  • B — attachment-rule update authorization: update_binding_policy/3 must authorize both caller-supplied policy_id and bind_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_id type to match the rule target (workbench/stack) and require bind_policy_id to 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.

@maciaszczykm

Copy link
Copy Markdown
Member Author

plural review this

@plural-copilot plural-copilot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. Custom-source simulation bypasses resource authorization.
  2. 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.

Comment thread lib/console/graphql/resolvers/deployments/policy.ex
Comment thread assets/src/routes/securityRoutes.tsx

@plural-copilot plural-copilot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. Custom policy simulation does not authorize the selected policy against current_user.
  2. Binding-policy updates do not authorize or type-check replacement policy IDs.
  3. Policy detail/evaluation/attachment routes remain outside the Security layout.

@maciaszczykm

Copy link
Copy Markdown
Member Author

plural review this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants