Skip to content

fix(daemon): preserve tenant scope for queued drains#1834

Merged
mistercrunch merged 4 commits into
mainfrom
fix-1831-queued-prompt-drain
Jul 7, 2026
Merged

fix(daemon): preserve tenant scope for queued drains#1834
mistercrunch merged 4 commits into
mainfrom
fix-1831-queued-prompt-drain

Conversation

@richardfogaca

@richardfogaca richardfogaca commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Linked issue

Fixes #1831

Summary

  • Add a queue-specific tenant-scope helper for session queue draining.
  • Preserve tenant context when completion/idle hooks and queue retries trigger queued-task processing.
  • Preserve hidden session tenant metadata so completion hooks can safely recover the tenant from the already-returned patched session row.
  • Cover params-based, ALS-based, trusted-hint, static-tenant, and fail-closed required-tenant behavior with focused tests.

Why / context

Queued prompts could stay stuck after a running task completed because completion-time queue drains depended on deferred tenant-scoped work. If the deferred path had minimal params, the drain could skip instead of starting the next queued task. Sending another prompt kicked the enqueue path, which processed the older queued task and left the newest one stuck.

Implementation notes

  • deferWithSessionQueueTenantScope and runWithSessionQueueTenantScope resolve tenant context from params.tenant, current tenant ALS, trusted hidden tenant metadata from an already-returned session row, or configured static tenant mode.
  • SessionRepository attaches non-enumerable hidden tenant metadata to session DTOs and preserves it through update() return values; it is available in-process but not exposed through JSON serialization.
  • Required multi-tenant mode without tenant context still fails closed rather than running unscoped or attempting RLS-protected tenant discovery.
  • Session after-patch queue drain and queue retry paths pass scoped queue params into triggerQueueProcessing / processNextQueuedTask.
  • Queue locks, retry de-dupe, and oldest queued task ordering are preserved.

Validation / test plan

  • pnpm --filter @agor/daemon test -- src/utils/session-queue-tenant-scope.test.ts src/utils/tenant-db-scope.test.ts src/register-hooks.test.ts
  • pnpm --filter @agor/core test -- src/db/repositories/tasks.test.ts src/db/repositories/sessions.test.ts src/db/tenant-scope.test.ts
  • pnpm exec biome check apps/agor-daemon/src/utils/session-queue-tenant-scope.ts apps/agor-daemon/src/utils/session-queue-tenant-scope.test.ts apps/agor-daemon/src/register-hooks.ts apps/agor-daemon/src/register-hooks.test.ts apps/agor-daemon/src/register-routes.ts packages/core/src/db/repositories/sessions.ts packages/core/src/db/repositories/sessions.test.ts
  • git diff --check
  • pnpm check:multitenancy-boundaries remains red due existing baseline drift unrelated to this PR; touched-code classification is clean.
  • Live runtime queue-flow proof was not completed because the local branch environment did not expose app/health endpoints.

Screenshots / demos

Not applicable; backend queue-processing fix.

Risks / rollout / rollback

Risk is concentrated in queue-drain tenant scoping and hidden tenant metadata propagation on session DTOs. The change is fail-closed for required multi-tenant paths without tenant context and preserves existing queue lock/order semantics. Rollback by reverting this PR.

Out of scope / follow-ups

A broader queue refactor/reconciler would make queue draining convergent and reduce reliance on fire-and-forget triggers; that is intentionally separate from this focused regression fix.

@richardfogaca richardfogaca marked this pull request as ready for review July 7, 2026 16:18
Copilot AI review requested due to automatic review settings July 7, 2026 16:18

Copilot AI 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.

Pull request overview

This PR fixes a regression where queued prompts could stop draining after task completion by ensuring queue-drain work re-enters the correct tenant database scope even when invoked from completion/idle hooks, retries, or other minimal-params deferred paths.

Changes:

  • Introduces a queue-specific tenant scoping helper (runWithSessionQueueTenantScope / deferWithSessionQueueTenantScope) that can recover tenant context from params, ALS, trusted hidden tenant metadata, or static mode.
  • Preserves hidden (non-enumerable) tenant_id metadata on session DTOs across SessionRepository mapping and update() return values so completion hooks can safely recover tenant context without exposing it via JSON.
  • Updates queue drain triggers (sessions after.patch and queue retry paths) to pass tenant-scoped params, and adds focused tests for tenant resolution behavior and hidden tenant metadata.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/core/src/db/repositories/sessions.ts Attaches/preserves hidden tenant_id metadata on session DTOs (non-enumerable) for in-process tenant recovery.
packages/core/src/db/repositories/sessions.test.ts Adds mapping test coverage ensuring tenant_id is preserved in-process but not exposed via JSON/enumeration.
apps/agor-daemon/src/utils/session-queue-tenant-scope.ts Adds queue-specific tenant scope resolution + run/defer helpers for queue draining.
apps/agor-daemon/src/utils/session-queue-tenant-scope.test.ts Adds tests for params/ALS/hint/static/fail-closed tenant resolution for queue draining.
apps/agor-daemon/src/register-routes.ts Wraps queued-task processing + retry scheduling in session-queue tenant scoping.
apps/agor-daemon/src/register-hooks.ts Uses trusted hidden tenant_id from patched session DTO to scope after.patch queue drain.
apps/agor-daemon/src/register-hooks.test.ts Tests trusted hidden-tenant metadata reading without JSON exposure.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/agor-daemon/src/utils/session-queue-tenant-scope.ts
Comment thread apps/agor-daemon/src/utils/session-queue-tenant-scope.ts
Comment thread apps/agor-daemon/src/utils/session-queue-tenant-scope.ts Outdated
@richardfogaca richardfogaca added the ai-reviewed-gpt-5-5 Reviewed by GPT-5.5 AI reviewer label Jul 7, 2026
@mistercrunch mistercrunch merged commit 9f25ceb into main Jul 7, 2026
2 checks passed
@mistercrunch mistercrunch deleted the fix-1831-queued-prompt-drain branch July 7, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-reviewed-gpt-5-5 Reviewed by GPT-5.5 AI reviewer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Queued prompts never drain on task completion (regressed by tenant-scope refactor)

3 participants