Skip to content

feat(ui): expose custom registry force sync#2869

Open
daryllimyt wants to merge 2 commits into
mainfrom
codex/add-force-sync-option-for-custom-registry
Open

feat(ui): expose custom registry force sync#2869
daryllimyt wants to merge 2 commits into
mainfrom
codex/add-force-sync-option-for-custom-registry

Conversation

@daryllimyt

@daryllimyt daryllimyt commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Motivation

  • The custom registry UI lacked a way to trigger a "force" repository sync, which is needed to delete an existing synced version and re-pull actions from the remote repository.
  • Exposing force sync in the UI keeps admin workflows consistent with the underlying API which supports a force flag for repository syncs.

Description

  • Added a "Force sync from remote" item to the custom registry Manage menu and a new force-sync dialog state in frontend/src/components/registry/workspace-actions-controls.tsx.
  • Extended the SyncRepositoryDialog component to accept a force prop, render force-specific title/warning copy, and adjust the action label accordingly in frontend/src/components/registry/dialogs/repository-sync-dialog.tsx.
  • When performing the sync the dialog now passes the force value in the request body to the repository sync API (requestBody: { force }).
  • Updated dialog opening logic so selecting the new menu item opens the sync dialog in force mode and reuses existing dialog UI/UX.

Testing

  • Ran pnpm -C frontend run typecheck and it completed successfully.
  • Ran pnpm -C frontend exec biome check src/components/registry/dialogs/repository-sync-dialog.tsx src/components/registry/workspace-actions-controls.tsx and there were no reported issues.
  • Ran git diff --check to validate whitespace/patch issues and it returned no problems.

Codex Task


Summary by cubic

Adds a “Force sync from remote” option for custom registries and wires the dialog to send the force flag. Force sync is gated by org:registry:delete and is enforced server-side.

  • New Features

    • Added “Force sync from remote” in the Manage menu (visible only with org:registry:update and org:registry:delete).
    • SyncRepositoryDialog accepts force, updates title/warning and action label, and sends requestBody: { force }; selecting the new item opens the dialog in force mode.
  • Bug Fixes

    • API now requires org:registry:delete when force is true and rejects requests missing it; the UI hides force sync without this scope.

Written for commit a4d7f66. Summary will update on new commits.

Review in cubic

@daryllimyt daryllimyt marked this pull request as ready for review June 17, 2026 21:16
@daryllimyt

Copy link
Copy Markdown
Contributor Author

@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review

@daryllimyt I have started the AI code review. It will take a few minutes to complete.

@daryllimyt

Copy link
Copy Markdown
Contributor Author

@codex review

@zeropath-ai

zeropath-ai Bot commented Jun 17, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to a4d7f66.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► frontend/src/components/registry/dialogs/repository-sync-dialog.tsx
    Add force sync functionality to repository sync dialog
► frontend/src/components/registry/workspace-actions-controls.tsx
    Add "Force sync from remote" option to the actions menu
► tests/unit/test_registry_repositories_service.py
    Add test for force sync repository scope check
► tracecat/registry/repositories/service.py
    Implement force sync logic in the sync_repository method

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: d45c6496ca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@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.

1 issue found across 2 files

Confidence score: 3/5

  • In frontend/src/components/registry/workspace-actions-controls.tsx, force sync (which can delete an existing synced version) shares the same org:registry:update permission as regular sync, so users with routine update access may be able to perform a destructive action unintentionally or beyond intended privilege. Before merging, gate force sync behind a dedicated stricter RBAC scope (or equivalent explicit authorization check) and verify who currently holds that permission.

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread frontend/src/components/registry/workspace-actions-controls.tsx

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a4d7f667ef

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +130 to +133
raise ScopeDeniedError(
required_scopes=["org:registry:delete"],
missing_scopes=["org:registry:delete"],
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Let scope denials propagate as 403

When a caller has org:registry:update but not org:registry:delete and sends force: true, this new check raises ScopeDeniedError from inside sync_registry_repository's try block. That route only re-raises EntitlementRequired/HTTPException before its broad except Exception, so the intended authorization failure is converted into a 500 "Unexpected error" instead of the app-level 403 scope-denied response. Re-raise or catch ScopeDeniedError in the route so missing delete scope is reported correctly.

Useful? React with 👍 / 👎.

@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.

1 issue found across 3 files (changes from recent commits).

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="tracecat/registry/repositories/service.py">

<violation number="1" location="tracecat/registry/repositories/service.py:130">
P2: `ScopeDeniedError` raised here will be caught by the route handler's broad `except Exception` block in `router.py`, which converts it into a generic 500 response instead of the intended 403 scope-denied response. The route only re-raises `EntitlementRequired`/`RegistryNotFound`/`HTTPException` before its catch-all. Either add `ScopeDeniedError` to the route's explicit exception handling, or let it propagate by adding it to the re-raise conditions.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

if force and not has_scope(
self.role.scopes or frozenset(), "org:registry:delete"
):
raise ScopeDeniedError(

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: ScopeDeniedError raised here will be caught by the route handler's broad except Exception block in router.py, which converts it into a generic 500 response instead of the intended 403 scope-denied response. The route only re-raises EntitlementRequired/RegistryNotFound/HTTPException before its catch-all. Either add ScopeDeniedError to the route's explicit exception handling, or let it propagate by adding it to the re-raise conditions.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tracecat/registry/repositories/service.py, line 130:

<comment>`ScopeDeniedError` raised here will be caught by the route handler's broad `except Exception` block in `router.py`, which converts it into a generic 500 response instead of the intended 403 scope-denied response. The route only re-raises `EntitlementRequired`/`RegistryNotFound`/`HTTPException` before its catch-all. Either add `ScopeDeniedError` to the route's explicit exception handling, or let it propagate by adding it to the re-raise conditions.</comment>

<file context>
@@ -122,15 +122,23 @@ async def sync_repository(
+        if force and not has_scope(
+            self.role.scopes or frozenset(), "org:registry:delete"
+        ):
+            raise ScopeDeniedError(
+                required_scopes=["org:registry:delete"],
+                missing_scopes=["org:registry:delete"],
</file context>

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant