Skip to content

fix(runnerhub): scope Runner-originated binding calls to the session's tenant (RIG-4146) - #1463

Merged
trunk-io[bot] merged 1 commit into
mainfrom
compass-server/rig-4146-runner-tenant-scope
Oct 2, 2026
Merged

trunk-io[bot] merged 1 commit into
mainfrom
compass-server/rig-4146-runner-tenant-scope

Conversation

@rigel-mintaka

@rigel-mintaka rigel-mintaka commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

This PR is part of a stack containing 4 PRs:

  1. main
  2. "fix(runnerhub): scope Runner-originated binding calls to the session's tenant (RIG-4146)" (this PR)
  3. feat(server): archive the transcript tail when a session ends without Stop (RIG-4135) #1464
  4. fix(delivery): wake owed agents when a Runner attaches (RIG-4166) #1465
  5. fix(server): run a delivery-loop wake under the agent's tenant (RIG-4167) #1466

Fixes RIG-4146 (Matt's ruling: option 2).

Problem

Runners are shared across tenants, so the Runner door context has no tenant. Binding reads and deletes on deliverAck, forgeNotificationAck and dropLostSession therefore ran under the bootstrap tenant. For an agent in another tenant, a cold binding read failed closed (no ack, no wake), and the durable delete matched nothing.

Change

  • store.SessionBindingTenant(session, runner) is a read under the system role. It is filtered on both session and runner. It returns ErrConflict when two tenants bind the same session on one runner, so it never picks a tenant arbitrarily.
  • Hub.runnerSessionCtx resolves that tenant and returns WithTenant(ctx). A miss or a store fault keeps today's context, which still fails closed. A conflict refuses the call.
  • deliverAck, forgeNotificationAck and dropLostSession run under the scoped context.

Tests

  • TestDropLostSessionScopesToTheSessionTenant (runnerhub pgtest): a tenant-B session read cold is released durably and woken. With runnerSessionCtx disabled it fails: "lost = [], want [...]: the tenant-B session was not resolved".
  • TestSessionBindingTenantResolvesAcrossTenantsUnderSystemRole (store pgtest) covers the found, foreign-runner and conflict cases.
  • The runnerhub, store, server and delivery suites pass (unit and pgtest, -race). sqlc drift is clean. Lint reports 0 issues in the touched packages.

Known follow-ups (low)

  • Every ack now does one system-role read, even when the binding is cached. A later change can keep the tenant in the hub's binding cache.
  • The other Runner paths (RelayCommsCall, lifecycle, board, forge relays, frame publish, and the re-enroll reap) are still unscoped. They fail closed for non-bootstrap tenants.

…s tenant (RIG-4146)

Runners are shared across tenants, so the Runner door carries no tenant and
binding reads/deletes on deliverAck, forgeNotificationAck and dropLostSession
ran under the bootstrap tenant. Resolve the session's tenant under the system
role (SessionBindingTenant), then act under WithTenant. A session bound in two
tenants on one runner is refused.

Co-authored-by: Matt Wilkinson <matt@rigel.build>
@trunk-io

trunk-io Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

😎 This pull request was merged.

@linear-code

linear-code Bot commented Oct 2, 2026

Copy link
Copy Markdown

RIG-4146

@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown

Compass engineering docs preview: https://compass-server-rig-4146-runn.compass-eng-docs.pages.dev

Deployed from compass-server/rig-4146-runner-tenant-scope at d4d5590.

@trunk-io
trunk-io Bot merged commit e25b064 into main Oct 2, 2026
17 checks passed
@trunk-io
trunk-io Bot deleted the compass-server/rig-4146-runner-tenant-scope branch October 2, 2026 03:46
@trunk-io

trunk-io Bot commented Oct 2, 2026

Copy link
Copy Markdown

This pull request was merged into main as part of stacked PR 1466.

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.

2 participants