Skip to content

feat(admin): user search by email/ID, remove table border#3646

Merged
waleedlatif1 merged 6 commits intomainfrom
waleedlatif1/hangzhou-v2
Mar 18, 2026
Merged

feat(admin): user search by email/ID, remove table border#3646
waleedlatif1 merged 6 commits intomainfrom
waleedlatif1/hangzhou-v2

Conversation

@waleedlatif1
Copy link
Collaborator

@waleedlatif1 waleedlatif1 commented Mar 18, 2026

Summary

  • Search: Replaces the Load Users button with a live search input. Email search uses listUsers with a contains operator; pasting a UUID switches to admin.getUser for exact ID lookup. Pagination resets on each new search.
  • Border fix: Removes the outer border-[var(--border-secondary)] on the user table container, which was rendering white in dark mode.

Test plan

  • Search by partial email returns matching users
  • Paste a full user UUID returns exactly that user
  • No white border around the user table in dark mode
  • Pagination still works across email search results

Sg312 and others added 5 commits March 17, 2026 16:19
* feat(csp): allow chat UI to be embedded in iframes

Mirror the existing form embed CSP pattern for chat pages: add
getChatEmbedCSPPolicy() with frame-ancestors *, configure /chat/:path*
headers in next.config.ts without X-Frame-Options, and early-return in
proxy.ts so chat routes skip the strict runtime CSP.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(csp): extract shared getEmbedCSPPolicy helper

Deduplicate getChatEmbedCSPPolicy and getFormEmbedCSPPolicy into a
shared private helper to prevent future divergence.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(logs): persist execution diagnostics markers

Store last-started and last-completed block markers with finalization metadata so later read surfaces can explain how a run ended without reconstructing executor state.

* fix(executor): preserve durable diagnostics ordering

Await only the persistence needed to keep diagnostics durable before terminal completion while keeping callback failures from changing execution behavior.

* fix(logs): preserve fallback diagnostics semantics

Keep successful fallback output and accumulated cost intact while tightening progress-write draining and deduplicating trace span counting for diagnostics helpers.

* fix(api): restore async execute route test mock

Add the missing AuthType export to the hybrid auth mock so the async execution route test exercises the 202 queueing path instead of crashing with a 500 in CI.

* fix(executor): align async block error handling

* fix(logs): tighten marker ordering scope

Allow same-millisecond marker writes to replace prior markers and drop the unused diagnostics read helper so this PR stays focused on persistence rather than unread foundation code.

* fix(logs): remove unused finalization type guard

Drop the unused  helper so this PR only ships the persistence-side status types it actually uses.

* fix(executor): await subflow diagnostics callbacks

Ensure empty-subflow and subflow-error lifecycle callbacks participate in progress-write draining before terminal finalization while still swallowing callback failures.

---------

Co-authored-by: test <test@example.com>
Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>
- Replace Load Users button with a live search input; query fires on any input
- Email search uses listUsers with contains operator
- User ID search (UUID format) uses admin.getUser directly for exact lookup
- Remove outer border on user table that rendered white in dark mode
- Reset pagination to page 0 on new search

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@cursor
Copy link

cursor bot commented Mar 18, 2026

You have used all Bugbot PR reviews included in your free trial for your GitHub account on this workspace.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

@vercel
Copy link

vercel bot commented Mar 18, 2026

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Mar 18, 2026 0:46am

Request Review

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 18, 2026

Greptile Summary

This PR ships two user-visible features (admin user search by email/UUID and a dark-mode border fix) alongside a substantial batch of infrastructure improvements across the executor, logging session, and CSP layers.

Admin search (primary feature)

  • admin.tsx replaces the "Load Users" toggle with a committed-search UX: the live input updates searchInput, but only Enter/button press commits to searchQuery, which drives the query's enabled flag and controls table visibility. Pagination resets correctly on every new search.
  • admin-users.ts routes UUID-shaped queries through admin.getUser (exact ID lookup) and all other non-empty strings through listUsers with a contains operator on the email field. The shared mapUser helper removes the duplicated field mapping.

Block lifecycle persistence (logging-session.ts, execution-core.ts)

  • Every onBlockStart / onBlockComplete now writes a monotonic lastStartedBlock / lastCompletedBlock marker directly to execution_data using conditional jsonb_set SQL (only advances when the new timestamp is ≥ the stored one).
  • A pendingProgressWrites Set<Promise<void>> tracks in-flight DB writes; drainPendingProgressWrites loops until the set is empty, so terminal completion always awaits all side-effect writes before finalizing.
  • wrappedOnBlockStart (mirroring the existing wrappedOnBlockComplete) awaits persistence synchronously while firing the user-supplied streaming callback fire-and-forget — consistent with the existing design for onBlockComplete.
  • All execution paths (completed, force_failed, cancelled, paused, fallback_completed) now record a finalizationPath discriminant plus optional completionFailure string for diagnostics.

Executor async propagation (block-executor.ts, loop.ts, parallel.ts, node.ts, subflow-utils.ts)

  • Lifecycle callbacks (onBlockStart, onBlockComplete) are now await-ed throughout the executor tree; each call site is wrapped in try/catch so a failing callback cannot abort execution.

Other fixes

  • workspace-file-manager.ts: trackChatUpload now tries an UPDATE first to link an existing file record to the chat before falling back to INSERT, preventing duplicate rows.
  • hooks/queries/workflows.ts: isPlaceholderData is added to effect deps and gates completeMetadataLoad so placeholder data is never surfaced as real results.
  • next.config.ts / proxy.ts: Chat embed pages (/chat/:path*) get their own permissive CSP block; the runtime CSP injection in the proxy is removed for chat routes; the fallback exclusion regex is corrected from (?!chat$) (only excluded bare /chat) to (?!chat) (correctly excludes all /chat/* paths).

Confidence Score: 5/5

  • This PR is safe to merge — all changes are well-tested, error paths are properly guarded, and the executor async refactor follows consistent patterns throughout.
  • All significant logic is covered by new or updated unit tests (parallel.test.ts, logging-session.test.ts, execution-core.test.ts, logger.test.ts). The async propagation across the executor is mechanical and consistent; error swallowing is deliberate (warns rather than throws). The admin search UX is straightforward and correct. No SQL injection risks (Drizzle's sql template properly parameterises all interpolated values). No breaking API changes — all new fields in ExecutionLoggerService are optional.
  • No files require special attention.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/settings/components/admin/admin.tsx Replaces the "Load Users" button with a live search input (email and UUID). State management is clean: searchInput tracks the field value, searchQuery is committed on Enter/button, pagination resets on each new search, and the table is hidden until a non-empty search query is active.
apps/sim/hooks/queries/admin-users.ts Refactors from enabled-boolean to searchQuery-string API. UUID detection with a standard regex routes to admin.getUser (exact lookup); all other non-empty queries use listUsers with a contains operator. mapUser helper correctly de-duplicates field mapping.
apps/sim/executor/execution/block-executor.ts Makes callOnBlockStart, callOnBlockComplete, and handleBlockError async; wraps each lifecycle callback invocation in try/catch so a failing callback cannot crash the executor. Clean, targeted change.
apps/sim/lib/logs/execution/logging-session.ts Large refactor adding per-block persistence (lastStartedBlock / lastCompletedBlock) written with monotonic SQL guards, a pendingProgressWrites Set for back-pressure, drainPendingProgressWrites that loops until the set is empty, and completeExecutionWithFinalization that centralises all finalization paths. Logic is well-structured and thoroughly tested.
apps/sim/lib/workflows/executor/execution-core.ts Introduces wrappedOnBlockStart mirroring the existing wrappedOnBlockComplete — persistence is awaited, while the user-supplied callback is fire-and-forget with .catch() suppression. The inner-try/outer-finally restructure in finalizeExecutionOutcome ensures clearExecutionCancellation always runs even when finalization throws.
apps/sim/lib/uploads/contexts/workspace/workspace-file-manager.ts Fixes a duplicate-record bug in trackChatUpload by attempting a targeted UPDATE first (keyed on s3Key + workspaceId, excluding soft-deleted rows) and only inserting a new row when no existing record is found.
apps/sim/next.config.ts Adds a dedicated /chat/:path* header block with permissive CSP and COEP/COOP, and fixes the fallback exclusion regex from (?!chat$) (only excluded the bare /chat path) to (?!chat) (correctly excludes all /chat/* paths from the generic rule).

Sequence Diagram

sequenceDiagram
    participant Executor as BlockExecutor
    participant WBS as wrappedOnBlockStart
    participant LS as LoggingSession
    participant DB as Database
    participant UCB as UserCallback (onBlockStart)

    Executor->>WBS: callOnBlockStart(blockId, blockName, blockType, order)
    WBS->>LS: onBlockStart(blockId, blockName, blockType, now())
    LS->>LS: trackProgressWrite(persistLastStartedBlock())
    LS->>DB: UPDATE workflow_execution_logs SET execution_data -> lastStartedBlock WHERE startedAt <= now()
    DB-->>LS: ok
    LS-->>WBS: resolved
    WBS-->>UCB: void callback(...).catch(warn) [fire-and-forget]
    WBS-->>Executor: resolved (persistence guaranteed)

    Note over Executor: Block executes…

    Executor->>WBS: callOnBlockComplete(blockId, name, type, output)
    WBS->>LS: onBlockComplete(blockId, name, type, output)
    LS->>LS: trackProgressWrite(persistLastCompletedBlock())
    LS->>DB: UPDATE workflow_execution_logs SET execution_data -> lastCompletedBlock WHERE endedAt <= output.endedAt
    DB-->>LS: ok
    LS->>LS: (if cost > 0) void trackProgressWrite(flushAccumulatedCost())
    LS-->>WBS: resolved
    WBS-->>UCB: void onBlockComplete(...).catch(warn) [fire-and-forget]
    WBS-->>Executor: resolved

    Note over Executor: Terminal finalization…

    Executor->>LS: safeComplete / safeCompleteWithError / etc.
    LS->>LS: drainPendingProgressWrites() [awaits all in-flight DB writes]
    LS->>DB: completeWorkflowExecution (with finalizationPath, lastStartedBlock, lastCompletedBlock)
    DB-->>LS: ok
    LS-->>Executor: done
Loading

Last reviewed commit: "fix(admin): replace ..."

- Split searchInput (controlled input) from searchQuery (committed value)
  so the hook only fires on Search click or Enter, not every keystroke
- Gate table render on searchQuery.length > 0 to prevent stale results
  showing after input is cleared

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@waleedlatif1
Copy link
Collaborator Author

Addressed all three comments:

Excessive API requests (P1) — Replaced live search with an explicit Search button + Enter key support. searchInput tracks the controlled input value; searchQuery only updates on submit. The hook only fires when a search is committed, eliminating per-keystroke requests entirely.

Stale results on clear (P1) — Gated the table render on searchQuery.length > 0 && usersData. Clearing the input and searching again (or just clearing) will hide the table, so stale results from the previous search never persist visually.

onBlockComplete fire-and-forget (P2) — Out of scope for this PR; that change is in execution-core.ts and unrelated to the admin UI work here.

@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1 waleedlatif1 merged commit 0fbf31b into main Mar 18, 2026
15 checks passed
@waleedlatif1 waleedlatif1 deleted the waleedlatif1/hangzhou-v2 branch March 18, 2026 01:00
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.

3 participants