Skip to content

v0.8.40: browser agent improvements, permission requests - #7876

Open
waleedlatif1 wants to merge 8 commits into
mainfrom
staging
Open

waleedlatif1 wants to merge 8 commits into
mainfrom
staging

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

icecrasher321 and others added 6 commits September 15, 2026 17:25
…7868)

* chore(db): drop retired usage columns and compatibility scaffolding

* fix(db): forward force flags for local and dev schema pushes
…ty (#7872)

* fix(browser): preserve click targets and bound screenshot capture

* fix(browser): preserve observations and support native form controls

* fix(browser): share snapshot text budget with inline fragments
* feat(access-requests): request and review permission access

* fix(access-requests): reuse resource states and harden review lifecycle

* fix(access-requests): recheck rollout and retain public models
* fix(workspace): hydrate access policy before rendering chat

* fix(workspace): update layout test setup for access prefetch
@waleedlatif1
waleedlatif1 requested a review from a team as a code owner September 16, 2026 06:09
@vercel

vercel Bot commented Sep 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
docs Skipped Skipped Sep 16, 2026 4:26pm UTC

Request Review

@github-actions github-actions Bot added the requires-mothership-merge Has a companion PR on the mothership/copilot side — merge in lockstep label Sep 16, 2026
@github-actions

Copy link
Copy Markdown

⚠️ Cross-repo companion check

One or more companion PRs aren't merged into main yet (aggregated across the feature PRs in this release). Merging this without them will leave copilot and sim out of sync — merge them in lockstep.

  • ⚠️ simstudioai/mothership#502 — merged into staging (this PR targets main) — fix(browser): align structured input and multiple selection contracts

@greptile-apps

greptile-apps Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

The PR should not merge until a timed-out native screenshot capture has a recovery path that does not permanently disable screenshots for the affected tab.

Findings

  1. P1 Stalled capture blocks retries

Summary

This release introduces organization-governed permission access requests, contracts retired database columns, improves desktop browser automation, hydrates workspace policy earlier, and updates sidebar/menu behavior.

  • Adds request discovery, submission, cancellation, administrator preview and resolution, notification, audit, and organization-settings flows.
  • Adds the permission-access-request schema and removes retired usage/file-size compatibility columns and scripts.
  • Improves browser snapshots, native structured controls, multi-select handling, click reliability, and cancellation.
  • Exposes restricted workspace features as requestable states while preserving existing behavior when requests are disabled.
  • Refines sidebar row actions, menus, and workspace policy hydration.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Member[Workspace member] --> Discovery[Discover restricted capability]
  Discovery --> Request[Create access request]
  Request --> DB[(Permission access request)]
  DB --> Outbox[Notification outbox]
  Outbox --> Admin[Organization administrator]
  Admin --> Preview[Recompute policy preview and impact]
  Preview --> Decision{Decision}
  Decision -->|Decline| History[Record final decision and audit]
  Decision -->|Apply| Lock[Acquire organization and policy locks]
  Lock --> Recheck[Reauthorize and verify fingerprint]
  Recheck --> Policy[Update permission group or member limit]
  Policy --> History
  History --> Requester[Notify requester]
Loading

Reviews (1) · Last reviewed commit: "fix(workspace): hydrate access policy be..."

Comment on lines +480 to +485
const capture = (async () => {
try {
return await contents.capturePage(undefined, { stayHidden: true })
} finally {
pendingScreenshotCaptures.delete(contents)
}

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.

P1 Stalled capture blocks retries

When capturePage exceeds the five-second timeout, the caller fails but the native promise remains pending and keeps this tab in pendingScreenshotCaptures. If the native operation never settles, every later screenshot on the tab is rejected as already pending, permanently disabling screenshots until the tab is replaced. The affected tab needs a recovery or retirement path after timeout.

Knowledge Base Used:

@cubic-dev-ai cubic-dev-ai 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.

6 issues found across 222 files

Confidence score: 2/5

  • apps/desktop/src/main/browser-agent/cdp.ts can leave pendingScreenshotCaptures populated indefinitely when the five-second timeout rejects before the native capturePage promise settles, causing stale state or resource growth; ensure timeout handling performs independent cleanup or cancellation.
  • apps/sim/lib/permission-access-requests/policy.ts and apps/sim/lib/permission-groups/application/read-user-config.ts can expose requestable or blocking access-control UI for targets that deployment enforcement excludes or when self-hosted Access Control is disabled, creating user-facing policy inconsistencies; resolve both paths through the shared deployment regime and environment allowlist.
  • apps/sim/lib/api/contracts/access-requests.ts accepts arbitrary strings in enum-backed policy snapshots, weakening contract validation and allowing malformed changes through; validate before and after with the canonical read schema.
  • apps/sim/components/access-requests/my-access-requests.tsx hides allowed and unavailable catalog entries by filtering to requestable, while apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/toolbar/toolbar.tsx opens a new request flow for already-pending integration requests; preserve all discovery states and route pending rows to the existing request.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/sim/lib/permission-access-requests/policy.ts">

<violation number="1" location="apps/sim/lib/permission-access-requests/policy.ts:58">
P2: When a deployment-wide integration allowlist excludes a catalog target, this raw group config can mark it allowed or requestable even though enforcement rejects it. Merge the environment allowlist into the resolved group before evaluating targets and building deltas.</violation>
</file>

<file name="apps/sim/lib/api/contracts/access-requests.ts">

<violation number="1" location="apps/sim/lib/api/contracts/access-requests.ts:214">
P2: Policy-change snapshots accept arbitrary strings for enum-backed permission fields because this contract reuses one generic list schema for every `configKey`. Validate `before` and `after` with the canonical read schema for the selected permission field before exposing or persisting previews and history.</violation>
</file>

<file name="apps/sim/components/access-requests/my-access-requests.tsx">

<violation number="1" location="apps/sim/components/access-requests/my-access-requests.tsx:50">
P2: When Browse access loads, `state: 'requestable'` filters out every allowed and unavailable entry, making the corresponding rendering branches unreachable. Remove this filter so the catalog displays all discovery states.</violation>
</file>

<file name="apps/sim/lib/permission-groups/application/read-user-config.ts">

<violation number="1" location="apps/sim/lib/permission-groups/application/read-user-config.ts:32">
P2: When self-hosted Access Control is disabled, this still resolves an entitled organization’s group and can block the UI despite server enforcement being inactive. Gate resolution through the shared deployment-regime check before returning the group config.</violation>
</file>

<file name="apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/toolbar/toolbar.tsx">

<violation number="1" location="apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/toolbar/toolbar.tsx:533">
P2: When an integration request is already pending, clicking its restricted toolbar row opens the creation modal instead of the existing request. Discover integration targets and route `pendingRequestId` to the workspace access-requests page; only open the creation modal when no pending request exists.</violation>
</file>

<file name="apps/desktop/src/main/browser-agent/cdp.ts">

<violation number="1" location="apps/desktop/src/main/browser-agent/cdp.ts:482">
P1: When the five-second timer wins, `captureViewportImage` rejects while the `capturePage` promise continues running; its `finally` is the only cleanup for `pendingScreenshotCaptures`. If the native promise never settles, later screenshots remain rejected forever. Retire or recreate the tab, or otherwise clear the guard through a timeout recovery path before returning the timeout error.</violation>
</file>

Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.
Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread packages/db/scripts/push.ts
})
const capture = (async () => {
try {
return await contents.capturePage(undefined, { stayHidden: true })

@cubic-dev-ai cubic-dev-ai Bot Sep 16, 2026

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.

P1: When the five-second timer wins, captureViewportImage rejects while the capturePage promise continues running; its finally is the only cleanup for pendingScreenshotCaptures. If the native promise never settles, later screenshots remain rejected forever. Retire or recreate the tab, or otherwise clear the guard through a timeout recovery path before returning the timeout error.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/main/browser-agent/cdp.ts, line 482:

<comment>When the five-second timer wins, `captureViewportImage` rejects while the `capturePage` promise continues running; its `finally` is the only cleanup for `pendingScreenshotCaptures`. If the native promise never settles, later screenshots remain rejected forever. Retire or recreate the tab, or otherwise clear the guard through a timeout recovery path before returning the timeout error.</comment>

<file context>
@@ -456,8 +452,48 @@ function sameScreenshotViewport(
+    })
+    const capture = (async () => {
+      try {
+        return await contents.capturePage(undefined, { stayHidden: true })
+      } finally {
+        pendingScreenshotCaptures.delete(contents)
</file context>
Fix with cubic

(isHosted
? await isOrganizationOnEnterprisePlan(context.organizationId, 'return-false', executor)
: isAccessControlEnabled)
const group = !entitled

@cubic-dev-ai cubic-dev-ai Bot Sep 16, 2026

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.

P2: When a deployment-wide integration allowlist excludes a catalog target, this raw group config can mark it allowed or requestable even though enforcement rejects it. Merge the environment allowlist into the resolved group before evaluating targets and building deltas.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/sim/lib/permission-access-requests/policy.ts, line 58:

<comment>When a deployment-wide integration allowlist excludes a catalog target, this raw group config can mark it allowed or requestable even though enforcement rejects it. Merge the environment allowlist into the resolved group before evaluating targets and building deltas.</comment>

<file context>
@@ -0,0 +1,122 @@
+    (isHosted
+      ? await isOrganizationOnEnterprisePlan(context.organizationId, 'return-false', executor)
+      : isAccessControlEnabled)
+  const group = !entitled
+    ? null
+    : context.workspaceId
</file context>
Fix with cubic

export type AccessRequestResponse = z.output<typeof accessRequestResponseSchema>

export const accessRequestPolicyValueSchema = storedAccessRequestPolicyValueSchema
export const accessRequestPolicyChangeSchema = storedAccessRequestPolicyChangeSchema

@cubic-dev-ai cubic-dev-ai Bot Sep 16, 2026

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.

P2: Policy-change snapshots accept arbitrary strings for enum-backed permission fields because this contract reuses one generic list schema for every configKey. Validate before and after with the canonical read schema for the selected permission field before exposing or persisting previews and history.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/sim/lib/api/contracts/access-requests.ts, line 214:

<comment>Policy-change snapshots accept arbitrary strings for enum-backed permission fields because this contract reuses one generic list schema for every `configKey`. Validate `before` and `after` with the canonical read schema for the selected permission field before exposing or persisting previews and history.</comment>

<file context>
@@ -0,0 +1,312 @@
+export type AccessRequestResponse = z.output<typeof accessRequestResponseSchema>
+
+export const accessRequestPolicyValueSchema = storedAccessRequestPolicyValueSchema
+export const accessRequestPolicyChangeSchema = storedAccessRequestPolicyChangeSchema
+export type AccessRequestPolicyChange = z.output<typeof accessRequestPolicyChangeSchema>
+export const accessRequestDecisionSchema = storedAccessRequestDecisionSchema
</file context>
Fix with cubic

{
...scope,
search: debouncedSearch,
state: 'requestable',

@cubic-dev-ai cubic-dev-ai Bot Sep 16, 2026

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.

P2: When Browse access loads, state: 'requestable' filters out every allowed and unavailable entry, making the corresponding rendering branches unreachable. Remove this filter so the catalog displays all discovery states.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/sim/components/access-requests/my-access-requests.tsx, line 50:

<comment>When Browse access loads, `state: 'requestable'` filters out every allowed and unavailable entry, making the corresponding rendering branches unreachable. Remove this filter so the catalog displays all discovery states.</comment>

<file context>
@@ -0,0 +1,204 @@
+    {
+      ...scope,
+      search: debouncedSearch,
+      state: 'requestable',
+      limit: ACCESS_REQUEST_PAGE_SIZE,
+      offset,
</file context>
Fix with cubic

isOrganizationOnEnterprisePlan(organizationId, 'throw'),
])
: [false, false]
const resolved =

@cubic-dev-ai cubic-dev-ai Bot Sep 16, 2026

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.

P2: When self-hosted Access Control is disabled, this still resolves an entitled organization’s group and can block the UI despite server enforcement being inactive. Gate resolution through the shared deployment-regime check before returning the group config.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/sim/lib/permission-groups/application/read-user-config.ts, line 32:

<comment>When self-hosted Access Control is disabled, this still resolves an entitled organization’s group and can block the UI despite server enforcement being inactive. Gate resolution through the shared deployment-regime check before returning the group config.</comment>

<file context>
@@ -0,0 +1,46 @@
+          isOrganizationOnEnterprisePlan(organizationId, 'throw'),
+        ])
+      : [false, false]
+    const resolved =
+      organizationId && entitled
+        ? await resolveWorkspaceGroup(principal.userId, organizationId, context.workspaceId)
</file context>
Fix with cubic

.sort((a, b) => a.name.localeCompare(b.name))
}, [customBlocksData, currentWorkflowId, fallbackIconUrl])

const handleRequestItemClick = useCallback(

@cubic-dev-ai cubic-dev-ai Bot Sep 16, 2026

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.

P2: When an integration request is already pending, clicking its restricted toolbar row opens the creation modal instead of the existing request. Discover integration targets and route pendingRequestId to the workspace access-requests page; only open the creation modal when no pending request exists.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/toolbar/toolbar.tsx, line 533:

<comment>When an integration request is already pending, clicking its restricted toolbar row opens the creation modal instead of the existing request. Discover integration targets and route `pendingRequestId` to the workspace access-requests page; only open the creation modal when no pending request exists.</comment>

<file context>
@@ -502,6 +530,13 @@ export const Toolbar = memo(
         .sort((a, b) => a.name.localeCompare(b.name))
     }, [customBlocksData, currentWorkflowId, fallbackIconUrl])
 
+    const handleRequestItemClick = useCallback(
+      (type: string) => {
+        if (accessRequestsEnabled) setRequestedBlockType(type)
</file context>
Fix with cubic

Comment thread .github/CONTRIBUTING.md Outdated
… Difference? (#7878)

* feat(library): AI Personal Assistant vs. AI Agent Builder: What's the Difference?

* Pi Babysit: address PR #7878 feedback

---------

Co-authored-by: Sim Pi Agent <pi@sim.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

requires-mothership-merge Has a companion PR on the mothership/copilot side — merge in lockstep

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants