Skip to content

feat: add requester-approved delegation to registered runners - #37

Merged
cgaravitoq merged 4 commits into
stagingfrom
cgaravitoq/bd-a2-delegation-core
Oct 7, 2026
Merged

cgaravitoq merged 4 commits into
stagingfrom
cgaravitoq/bd-a2-delegation-core

Conversation

@cgaravitoq

@cgaravitoq cgaravitoq commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

An allowlisted Slack requester can delegate a bug thread to a registered runner after approving its button.
The worker captures the raw thread, binds decisions to the requester, and keeps a refused dispatch approved and queued until the runner returns.

Changes

  • Add opt-in delegation configuration, migration 0008, the runner/task API, and delegate_to_conductor for a bound channel thread or an admitted channel from an owner's DM.
  • Enable approval interactivity independently of MCP gates, list online and offline runners with distinct buttons, dispatch through waitUntil, and post Started only after the runner reports running.
  • Use state/runner compare-and-set transitions and recoverable claim tokens generated from 32 random bytes, retaining only SHA-256 hashes.
  • Scope task tokens to progress and replies in the approved thread, atomically settle a verbatim done receipt and task, and cancel task expiry on claim, cancellation or completion.
  • Schedule 24-hour proposal expiry on the conversation instance and postpone conversation destruction while a task alarm remains.

Verification

Verify: PASS at 084f2fec1e310416f60537adc0fbb5f842be3b8c with Bun 1.4.2, 358 tests passed and 0 failed.

  • bun install --frozen-lockfile
  • bun run format:check
  • bun run lint
  • bun run typecheck
  • bun test
  • bun run knip
  • bun run deploy:dry
  • bun audit --ignore=GHSA-vfj7-8cjw-p6xm (no vulnerabilities, one ignored advisory)
  • bun run verify

Coverage includes opt-in configuration/instructions, migration persistence, code-owned capture, requester decisions, queued and refused sends, instance expiry, approval/cancellation/expiry races, competing claims, holder recovery and token revocation, runner transitions, scoped progress/replies, verbatim completion, and a fetch double rejecting object receivers and redirect: "error" on injected and default global fetch paths.
Eleven temporary behavior removals each produced a regression failure and were restored; separate red/green cases cover retention preceding task expiry and long summaries with a 300-character title.
No dependency, lockfile, deployment configuration or CI changes.

CI: PASS at 084f2fec1e310416f60537adc0fbb5f842be3b8c, verify run completed successfully in 51 seconds with the workflow-pinned Bun 1.3.14.

Not covered

Live Slack, Access and a real runner (wave-end pass).

cgaravitoq added 4 commits October 7, 2026 14:57
Let allowlisted requesters hand a captured thread to a registered runner
without letting thread content or another user authorize the task.
Use state and runner compare-and-set transitions, recoverable hashed task
tokens, and per-instance expiry so dispatch failures stay queued and
progress stays scoped to the approved thread until completion.
…t task tokens

With delegation configured, POST /progress, GET /progress/replies and
GET /progress/channels answered 403 token_scope to any request whose
bearer was absent or unknown, where the base answered 401 unauthorized.
The contract reserves 403 token_scope for a live task token used outside
its own channel, thread and task; a bearer that is no task token, or a
revoked one, is no credential and stays 401, as on the /delegation routes.

Closes the review P1 on the unrequested change to the existing progress
refusal; the new assertions fail with 403 without this change.
Only an allowlisted Slack user may hand a thread to a runner, yet removing
the allowedUserIds condition in mountDelegationTool left every test green.
The operator config in the agent test now carries delegation and an
allowlist, and a DM from a user outside it must mount no tool.

Closes the review P1 at apps/slack-agent/src/agent.ts:137; the new test
fails with the condition removed.
Section 8 dispatches the approved task with the configured runner
headers, and without them the access gateway answers 403 in production,
yet dropping them from POST /tasks left every test green because only the
health probe asserted them.

Closes the review P1 at apps/slack-agent/test/delegation.test.ts:413; the
dispatch assertions fail with the headers removed from POST /tasks.
@cgaravitoq
cgaravitoq merged commit 9039b05 into staging Oct 7, 2026
2 checks passed
@cgaravitoq
cgaravitoq deleted the cgaravitoq/bd-a2-delegation-core branch October 7, 2026 13:13
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