Skip to content

feat: Add organization and workspace API key management#2347

Merged
daryllimyt merged 76 commits intomainfrom
feat/api-keys
Apr 23, 2026
Merged

feat: Add organization and workspace API key management#2347
daryllimyt merged 76 commits intomainfrom
feat/api-keys

Conversation

@daryllimyt
Copy link
Copy Markdown
Contributor

@daryllimyt daryllimyt commented Mar 12, 2026

Checklist

  • Read CONTRIBUTING.md.
  • PR title is short and non-generic (see previously merged PRs for examples).
  • PR only implements a single feature or fixes a single bug.
  • Tests passing (uv run pytest tests)?
  • Lint / pre-commits passing (pre-commit run --all-files)?

Description

This PR adds organization-level and workspace-level API key management.

Backend changes add managed API key models, migration, auth credential handling, routes, scopes, and audit metadata so API keys can be issued, updated, revoked, and authenticated with the correct org/workspace context.

Frontend changes add API key settings pages and management flows for organization and workspace contexts. The workspace API key page was aligned to the same collection-page structure used by workflows and case management, and the edit dialog now uses the RBAC scope-selection UI pattern.

Validation run for this branch:

  • uv run pytest tests/unit/api/test_api_api_keys.py tests/unit/test_auth_api_keys.py tests/unit/test_auth_credentials_api_keys.py tests/unit/test_role_headers.py
  • uv run ruff check .
  • uv run basedpyright tracecat/api_keys tracecat/auth/api_keys.py tracecat/auth/credentials.py tracecat/auth/dependencies.py tracecat/auth/types.py tracecat/authz/scopes.py tracecat/authz/seeding.py tracecat/db/models.py tracecat/db/tenant_rls.py tracecat/api/app.py tracecat/workspaces/router.py tracecat/agent/router.py tracecat/audit/enums.py tracecat/audit/logger.py tracecat/audit/service.py tracecat/audit/types.py alembic/versions/548aa7691799_add_api_key_tables.py tests/unit/api/conftest.py tests/unit/api/test_api_api_keys.py tests/unit/test_auth_api_keys.py tests/unit/test_auth_credentials_api_keys.py tests/unit/test_role_headers.py
  • pnpm -C frontend run typecheck

Related Issues

None.

Screenshots / Recordings

Not included. The workspace API keys page and edit dialog intentionally match the existing workflows, case management, and RBAC permission-selection UI patterns.

Steps to QA

  1. Open organization settings and navigate to API keys.
  2. Create, edit, and revoke an organization API key and confirm the list updates correctly.
  3. Open a workspace and navigate to API keys.
  4. Verify the page layout matches the workflows and case management collection pages, including the create action in the header bar.
  5. Edit a workspace API key and verify the permissions UI matches the RBAC scope selector and the modal body scrolls correctly.
  6. Run the validation commands listed above.

Summary by cubic

Adds organization- and workspace‑scoped service accounts with managed API keys so machines can call actor‑safe routes under RBAC. Includes pages to issue, rotate, and revoke keys, plus tighter auth via x-tracecat-api-key.

  • New Features

    • Backend: Service accounts and managed API keys (tc_org_sk_… / tc_ws_sk_…) with CRUD, issue/rotate/revoke, cursor pagination, and audit on service account and API key resources; org/workspace routers added; organization domains gain verification fields.
    • Auth: WorkspaceActorRole / OrgActorRole for API‑key auth on actor‑safe org/workspace routes; managed key parsing/verification and header x-tracecat-api-key; workspace listing uses list_accessible_workspaces.
    • UI: Organization → Service accounts and Workspace → Service accounts pages with shared scope selector; sidebars and default workspace routing include Service accounts; settings modal nav gating improved.
  • Bug Fixes and Refactors

    • Scopes: Enforce workflow:read for graph reads and workflow:update for graph mutations; extend guards across cases, integrations, editor, workflows, executions, schedules, and tags; tighten case tag routes to case:read / case:update; guard org entitlement reads by scope; keep org deletion/settings/agent, GitHub manifest, draft execution, webhook API‑key revocation, webhook secret reads, and workflow detail user‑only; allow org members to list workspaces.
    • Service accounts/keys: Resolve service‑account actor labels in audit; audit keys by key id; serialize API key issuance; fix reverse pagination flags and use filtered totals; translate list errors; allow clearing descriptions; cascade org deletion to keys; block service accounts from owning/updating/deleting user comments; stabilize Role/RoleACL header handling and effective scope computation; return 403 for workspace search auth errors; guard workspace Service accounts route and landing redirect behind scope checks.

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

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

7 issues found across 41 files

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/auth/types.py">

<violation number="1" location="tracecat/auth/types.py:45">
P2: `api_key_kind` has exactly two valid values (`"organization"`, `"workspace"`) but is typed as bare `str | None`. Use `Literal["organization", "workspace"] | None` to catch invalid values at the type level.</violation>
</file>

<file name="frontend/src/app/organization/settings/workspaces/[workspaceId]/page.tsx">

<violation number="1" location="frontend/src/app/organization/settings/workspaces/[workspaceId]/page.tsx:55">
P2: Including `workspace:api_key:read` in this page-level allow condition grants access to full workspace settings UI, not just API key read functionality. Restrict this route to workspace/org update scopes (or split API key views to a separate route/component).</violation>
</file>

<file name="tracecat/api_keys/router.py">

<violation number="1" location="tracecat/api_keys/router.py:49">
P1: The fallback in `_translate_error` returns `str(exc)` for all unexpected exceptions, which can leak internal details (e.g., database constraint names, internal paths) to API clients. Return a generic message for the catch-all case and log the actual error server-side.

(Based on your team's feedback about error handling posture.) [FEEDBACK_USED]</violation>
</file>

<file name="tracecat/auth/credentials.py">

<violation number="1" location="tracecat/auth/credentials.py:133">
P2: Use `is not None` instead of truthiness when checking `role.scopes`. An empty `frozenset()` (resolved zero scopes) is falsy and would be discarded by `or`, collapsing it with `None` (unresolved). This matters for distinguishing "no scopes resolved" from "scopes not yet computed."

(Based on your team's feedback about checking `role.scopes is not None` instead of using truthiness.) [FEEDBACK_USED]</violation>
</file>

<file name="tracecat/api_keys/service.py">

<violation number="1" location="tracecat/api_keys/service.py:47">
P2: `TracecatAuthorizationError` is semantically wrong for an invalid cursor value. This is a validation error (bad input), not an authorization failure. Use `ValueError` so the router maps it to HTTP 400 instead of a 403.</violation>

<violation number="2" location="tracecat/api_keys/service.py:74">
P1: Reverse pagination returns wrong results because `ORDER BY` is always DESC. The existing workflow pagination pattern flips to ASC when `params.reverse` is True so that `LIMIT` picks the items closest to the cursor. Without this, the previous-page query returns items from the wrong end of the filtered set.</violation>
</file>

<file name="frontend/src/components/organization/api-keys-manager.tsx">

<violation number="1" location="frontend/src/components/organization/api-keys-manager.tsx:574">
P2: `AlertDialogAction` auto-closes the dialog on click, so the `disabled={revokePending}` guard and "Revoking..." loading text are never visible. Call `e.preventDefault()` to keep the dialog open while the async revoke runs; it will close when `handleRevoke` sets `revokeTarget` to `null`.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread tracecat/api_keys/router.py Outdated
Comment thread tracecat/api_keys/service.py Outdated
Comment thread tracecat/auth/types.py Outdated
Comment thread frontend/src/app/organization/settings/workspaces/[workspaceId]/page.tsx Outdated
Comment thread tracecat/auth/credentials.py
Comment thread tracecat/api_keys/service.py Outdated
Comment thread frontend/src/components/organization/api-keys-manager.tsx Outdated
Copy link
Copy Markdown

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

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

ℹ️ 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 thread tracecat/auth/dependencies.py Outdated
Comment thread tracecat/api_keys/service.py Outdated
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 10 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/api_keys/router.py">

<violation number="1" location="tracecat/api_keys/router.py:58">
P2: Use sanitized error logging instead of `logger.exception` on this public API error path to avoid recording full traceback details in production logs.

(Based on your team's feedback about sanitized logging on public API exception paths.) [FEEDBACK_USED]</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread tracecat/api_keys/router.py Outdated
Copy link
Copy Markdown

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

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: 2d501c3c88

ℹ️ 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 thread tracecat/api_keys/service.py Outdated
Comment thread tracecat/api_keys/service.py Outdated
@blacksmith-sh

This comment has been minimized.

Copy link
Copy Markdown

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

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: 918c8a9383

ℹ️ 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 thread alembic/versions/548aa7691799_add_api_key_tables.py
@daryllimyt daryllimyt changed the title Add organization and workspace API key management feat: Add organization and workspace API key management Mar 12, 2026
@blacksmith-sh

This comment has been minimized.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

10 issues found across 61 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="tests/unit/test_role_headers.py">

<violation number="1" location="tests/unit/test_role_headers.py:221">
P2: This unit test now triggers a real DB lookup because the mocked headers include a workspace ID but omit `x-tracecat-role-organization-id`. Add the org header (or monkeypatch `_get_workspace_org_id`) to keep the test isolated.</violation>
</file>

<file name="tracecat/audit/types.py">

<violation number="1" location="tracecat/audit/types.py:35">
P2: `service_account_api_key` audit events use the parent service-account ID as `resource_id`, so key rotation/revocation events cannot identify the actual API key record.</violation>
</file>

<file name="tracecat/workspaces/router.py">

<violation number="1" location="tracecat/workspaces/router.py:58">
P1: This scope decorator blocks regular workspace members from listing their own workspaces. `/workspaces` is an org-scoped request, so workspace-scoped `workspace:read` grants are not present during dependency resolution and the membership-based fallback never runs.</violation>
</file>

<file name="tracecat/workflow/store/router.py">

<violation number="1" location="tracecat/workflow/store/router.py:90">
P2: Allowing `WorkspaceActorRole` here makes workspace API keys hit a downstream `org:settings:read` check they can never satisfy, so these sync endpoints will still 403 for API-key callers.</violation>
</file>

<file name="frontend/src/components/organization/service-accounts-manager.tsx">

<violation number="1" location="frontend/src/components/organization/service-accounts-manager.tsx:200">
P2: `openCreateDialog` is missing from the `useEffect` dependency array. Because the function is recreated every render and isn't wrapped in `useCallback`, simply adding it to deps would re-fire the effect each render. Inline the calls or memoize the function to satisfy exhaustive-deps correctly.

(Based on your team's feedback about avoiding non-stable object references in useEffect deps.) [FEEDBACK_USED]</violation>
</file>

<file name="frontend/src/components/organization/org-settings-service-accounts.tsx">

<violation number="1" location="frontend/src/components/organization/org-settings-service-accounts.tsx:45">
P2: Gate organization service-account actions by org write scopes; the manager currently enables all mutating controls by default for read-only users.</violation>
</file>

<file name="tracecat/db/models.py">

<violation number="1" location="tracecat/db/models.py:973">
P3: Tautological check constraint: `organization_id` is `NOT NULL`, so `organization_id IS NOT NULL` is always true, making the entire constraint `workspace_id IS NULL OR TRUE` — always satisfied. If the intent is to enforce "workspace requires org", that's already guaranteed by the NOT NULL column. Consider removing the no-op constraint to avoid misleading future readers, or if the real intent was something else (e.g., workspace must belong to the same org), express that instead.</violation>
</file>

<file name="frontend/src/app/workspaces/[workspaceId]/service-accounts/page.tsx">

<violation number="1" location="frontend/src/app/workspaces/[workspaceId]/service-accounts/page.tsx:14">
P2: Wait for `useScopeCheck` to resolve before rendering this page. While it is still `undefined`, the child component mounts and issues workspace service-account queries before unauthorized users are sent to the 404.</violation>
</file>

<file name="tracecat/service_accounts/router.py">

<violation number="1" location="tracecat/service_accounts/router.py:213">
P1: All remaining mutation endpoints (disable, enable, regenerate-key, revoke-key) for both org and workspace routers are also missing `@require_scope` decorators. These should be gated behind appropriate scopes (e.g., `org:service_account:update` or a dedicated `org:service_account:manage` scope) consistent with the read-endpoint pattern.</violation>
</file>

<file name="tracecat/service_accounts/service.py">

<violation number="1" location="tracecat/service_accounts/service.py:61">
P2: `has_more` and `has_previous` must be swapped along with the cursors when `reverse=True`. Other pagination implementations in the codebase (`tables/service.py`, `cases/rows/service.py`) correctly swap both pairs. Without this, backward pagination returns incorrect `has_more`/`has_previous` flags to the client.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread tracecat/workspaces/router.py Outdated
Comment thread tracecat/service_accounts/router.py
Comment thread tests/unit/test_role_headers.py
Comment thread tracecat/audit/types.py
Comment thread tracecat/workflow/store/router.py
Comment thread frontend/src/components/organization/service-accounts-manager.tsx
Comment thread frontend/src/app/workspaces/[workspaceId]/service-accounts/page.tsx
Comment thread tracecat/service_accounts/service.py
Comment thread tracecat/db/models.py
Copy link
Copy Markdown

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

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

ℹ️ 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 thread tracecat/workspaces/router.py Outdated
Comment thread tracecat/agent/router.py Outdated
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

10 issues found across 28 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/cases/dropdowns/router.py">

<violation number="1" location="tracecat/cases/dropdowns/router.py:37">
P1: Switching these endpoints to `WorkspaceActorRole` opens part of the case API to API keys while the rest of case management is still user-only. That lets service accounts mutate/read case dropdown data through a narrower path that bypasses the existing actor restriction.</violation>
</file>

<file name="tracecat/cases/tag_definitions/router.py">

<violation number="1" location="tracecat/cases/tag_definitions/router.py:49">
P1: This delete route is authorized with `case:update`, which bypasses the existing `case:delete` privilege boundary for case resources.</violation>
</file>

<file name="tracecat/workflow/management/router.py">

<violation number="1" location="tracecat/workflow/management/router.py:214">
P2: Allowing `WorkspaceActorRole` here drops revocation attribution for service-account callers, because they always have `user_id=None` and this handler records `revoked_by` from `role.user_id`.</violation>
</file>

<file name="tracecat/workspaces/router.py">

<violation number="1" location="tracecat/workspaces/router.py:61">
P1: Keep `create_workspace` on a user-only org dependency. `OrgActorRole` admits API keys, so service-account credentials with `workspace:create` can now create new workspaces through this org-level route.</violation>
</file>

<file name="tracecat/settings/router.py">

<violation number="1" location="tracecat/settings/router.py:6">
P1: Switching these settings routes to `OrgActorRole` makes organization API keys eligible to read and mutate organization-wide settings, including SAML and audit configuration. Keep these endpoints user-only unless you explicitly want machine credentials to control auth and audit state.</violation>
</file>

<file name="tracecat/cases/durations/router.py">

<violation number="1" location="tracecat/cases/durations/router.py:38">
P1: This endpoint now grants write-capable sync behavior to callers with only `case:read`. Because `list_case_durations` commits `sync_case_durations(...)`, a read-scoped actor can still mutate case duration state.</violation>
</file>

<file name="tracecat/organization/router.py">

<violation number="1" location="tracecat/organization/router.py:72">
P0: Keep organization deletion user-only. Changing this dependency to `OrgActorRole` lets org API keys with `org:delete` remove the entire organization.</violation>
</file>

<file name="tracecat/workspaces/service.py">

<violation number="1" location="tracecat/workspaces/service.py:244">
P2: This authorization failure is unhandled on `/workspaces/search`, so the new `TracecatAuthorizationError` path becomes a 500 response instead of a forbidden result.

(Based on your team's feedback about centralizing translation of known authorization/domain errors into sanitized client responses.) [FEEDBACK_USED]</violation>
</file>

<file name="tracecat/workflow/executions/router.py">

<violation number="1" location="tracecat/workflow/executions/router.py:367">
P1: Keep the draft-execution route user-only; switching it to `WorkspaceActorRole` lets API keys run unpublished workflow graphs under the normal `workflow:execute` scope.</violation>
</file>

<file name="tracecat/vcs/router.py">

<violation number="1" location="tracecat/vcs/router.py:31">
P2: `/github/manifest` now allows API-key actors, but the follow-up `/github/install` callback is still user-only, so service accounts can start a manifest flow they cannot complete.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread tracecat/organization/router.py
Comment thread tracecat/cases/dropdowns/router.py
Comment thread tracecat/cases/tag_definitions/router.py Outdated
Comment thread tracecat/workspaces/router.py
Comment thread tracecat/settings/router.py Outdated
Comment thread tracecat/cases/durations/router.py
Comment thread tracecat/workflow/executions/router.py
Comment thread tracecat/workflow/management/router.py
Comment thread tracecat/workspaces/service.py
Comment thread tracecat/vcs/router.py Outdated
Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

💡 Codex Review

https://github.com/TracecatHQ/tracecat/blob/29e58442ca5ecc108b275ad1910942b55fef412a/tracecat/workspaces/router.py#L126
P2 Badge Handle authorization errors in workspace search route

Catch and translate TracecatAuthorizationError here the same way list_workspaces does. WorkspaceService.search_workspaces() raises this error for non-privileged service-account actors without a bound workspace (tracecat/workspaces/service.py), which is reachable when an organization-scoped API key has workspace:read (allowed by the route’s require_scope(..., require_all=False)) but not org:workspace:read; without a handler, that valid request path returns a 500 instead of a 403.

ℹ️ 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".

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

10 issues found across 132 files (changes from recent commits).

Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.

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="frontend/src/components/nav/builder-nav.tsx">

<violation number="1" location="frontend/src/components/nav/builder-nav.tsx:502">
P2: `Run` can submit the default `{}` payload before the persisted trigger payload has been restored, so the first execution after opening a workflow may run with the wrong inputs.</violation>
</file>

<file name="frontend/src/app/organization/page.tsx">

<violation number="1" location="frontend/src/app/organization/page.tsx:4">
P2: This redirect makes `/organization` land on an entitlement-locked page for orgs without `custom_registry`. Use an always-available organization settings route as the default landing page.</violation>
</file>

<file name="frontend/src/components/dashboard/workflows-dashboard.tsx">

<violation number="1" location="frontend/src/components/dashboard/workflows-dashboard.tsx:1020">
P2: A failure after `createWorkflow` leaves a partial duplicate behind while showing "Duplicate failed". Users can retry and accidentally create orphaned or half-tagged copies.</violation>
</file>

<file name="frontend/src/components/settings/profile-settings.tsx">

<violation number="1" location="frontend/src/components/settings/profile-settings.tsx:46">
P2: Wait for the profile update to succeed before clearing the local draft; otherwise failed saves silently discard the edited name.</violation>

<violation number="2" location="frontend/src/components/settings/profile-settings.tsx:55">
P2: Skip the Enter-to-blur behavior while IME composition is active, or name entry can be interrupted for composed languages.</violation>
</file>

<file name="frontend/src/providers/builder.tsx">

<violation number="1" location="frontend/src/providers/builder.tsx:309">
P2: Clearing the debounce on cleanup drops the latest trigger-payload edits if the user leaves the workflow within 250ms.</violation>
</file>

<file name="frontend/src/components/settings/workspace-general-settings.tsx">

<violation number="1" location="frontend/src/components/settings/workspace-general-settings.tsx:124">
P2: The delete confirmation text persists across close/reopen because the dialog stays mounted, which weakens the re-type safeguard for this destructive action.</violation>
</file>

<file name="frontend/src/components/agents/agents-table.tsx">

<violation number="1" location="frontend/src/components/agents/agents-table.tsx:409">
P2: Block duplicate requests globally; the current per-row guard allows concurrent duplications and races navigation.</violation>
</file>

<file name="frontend/src/components/settings/workspace-runtime-settings.tsx">

<violation number="1" location="frontend/src/components/settings/workspace-runtime-settings.tsx:68">
P2: Use nullish coalescing here; `|| undefined` drops a saved `0`, so the form cannot display or round-trip a valid persisted timeout value.</violation>

<violation number="2" location="frontend/src/components/settings/workspace-runtime-settings.tsx:109">
P2: This field defines a validation error message but never renders `FormMessage`, so invalid timeout values fail without any visible explanation.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread frontend/src/components/nav/builder-nav.tsx
Comment thread frontend/src/app/organization/page.tsx
Comment thread frontend/src/components/dashboard/workflows-dashboard.tsx
Comment thread frontend/src/components/settings/profile-settings.tsx
Comment thread frontend/src/components/settings/profile-settings.tsx
Comment thread frontend/src/providers/builder.tsx
Comment thread frontend/src/components/settings/workspace-general-settings.tsx
Comment thread frontend/src/components/agents/agents-table.tsx
Comment thread frontend/src/components/settings/workspace-runtime-settings.tsx
Comment thread frontend/src/components/settings/workspace-runtime-settings.tsx
Copy link
Copy Markdown

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

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: 6f2dd75753

ℹ️ 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 thread tracecat/workspaces/router.py Outdated
Comment thread tracecat/workspaces/router.py
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

3 issues found across 6 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/workspaces/router.py">

<violation number="1" location="tracecat/workspaces/router.py:58">
P1: Requiring only `org:read` here locks workspace-scoped API keys out of the workspace list/search endpoints; they only carry `workspace:read`.</violation>
</file>

<file name="tracecat/workflow/graph/router.py">

<violation number="1" location="tracecat/workflow/graph/router.py:27">
P1: Removing `@require_scope("workflow:read")` bypasses RBAC scope enforcement on the graph read endpoint. Every other workflow router endpoint retains its scope check. Any authenticated workspace actor—including service accounts that were intentionally granted only narrow scopes—can now read workflow graphs without `workflow:read` permission.</violation>

<violation number="2" location="tracecat/workflow/graph/router.py:49">
P0: Removing `@require_scope("workflow:update")` bypasses RBAC scope enforcement on the graph mutation endpoint. This allows any authenticated workspace actor—including service accounts without `workflow:update` permission—to modify workflow graphs via PATCH.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread tracecat/workflow/graph/router.py
Comment thread tracecat/workspaces/router.py
Comment thread tracecat/workflow/graph/router.py
Copy link
Copy Markdown

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

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: 25a2348c93

ℹ️ 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 thread tracecat/cases/dropdowns/router.py
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 21 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/workflow/management/router.py">

<violation number="1">
P1: Restricting only the revoke route leaves webhook API-key deletion callable by workspace API keys.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread tracecat/workflow/management/router.py
Copy link
Copy Markdown

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

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: 74bbaa3f8a

ℹ️ 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 thread tracecat/organization/router.py
@daryllimyt daryllimyt temporarily deployed to internal-registry-ci April 22, 2026 21:12 — with GitHub Actions Inactive
@daryllimyt daryllimyt had a problem deploying to internal-registry-ci April 22, 2026 21:12 — with GitHub Actions Failure
@blacksmith-sh

This comment has been minimized.

@daryllimyt daryllimyt temporarily deployed to internal-registry-ci April 22, 2026 21:26 — with GitHub Actions Inactive
@daryllimyt daryllimyt temporarily deployed to internal-registry-ci April 22, 2026 21:26 — with GitHub Actions Inactive
@daryllimyt daryllimyt temporarily deployed to internal-registry-ci April 22, 2026 21:34 — with GitHub Actions Inactive
@daryllimyt daryllimyt temporarily deployed to internal-registry-ci April 22, 2026 21:34 — with GitHub Actions Inactive
@daryllimyt daryllimyt temporarily deployed to internal-registry-ci April 22, 2026 21:37 — with GitHub Actions Inactive
@daryllimyt daryllimyt temporarily deployed to internal-registry-ci April 22, 2026 21:37 — with GitHub Actions Inactive
Copy link
Copy Markdown

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

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: 17e684507f

ℹ️ 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 thread tracecat/service_accounts/service.py
@daryllimyt daryllimyt temporarily deployed to internal-registry-ci April 22, 2026 21:59 — with GitHub Actions Inactive
@daryllimyt daryllimyt temporarily deployed to internal-registry-ci April 22, 2026 21:59 — with GitHub Actions Inactive
Copy link
Copy Markdown

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

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: 8c29dd889a

ℹ️ 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 thread tracecat/workflow/management/router.py Outdated
Comment thread tracecat/workspaces/router.py Outdated
@daryllimyt daryllimyt temporarily deployed to internal-registry-ci April 22, 2026 23:44 — with GitHub Actions Inactive
@daryllimyt daryllimyt temporarily deployed to internal-registry-ci April 22, 2026 23:44 — with GitHub Actions Inactive
Copy link
Copy Markdown

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

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: 58efb9c4b2

ℹ️ 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 thread frontend/src/app/workspaces/[workspaceId]/page.tsx Outdated
@daryllimyt daryllimyt temporarily deployed to internal-registry-ci April 23, 2026 01:02 — with GitHub Actions Inactive
@daryllimyt daryllimyt temporarily deployed to internal-registry-ci April 23, 2026 01:02 — with GitHub Actions Inactive
@daryllimyt daryllimyt merged commit 3783a03 into main Apr 23, 2026
18 checks passed
@daryllimyt daryllimyt deleted the feat/api-keys branch April 23, 2026 01:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant