Skip to content

feat(tasks): rebind sandbox GitHub identity and git author to the actor - #70024

Closed
VojtechBartos wants to merge 1 commit into
vojtab/slack-app-per-message-identityfrom
vojtab/slack-app-per-message-github-identity
Closed

feat(tasks): rebind sandbox GitHub identity and git author to the actor#70024
VojtechBartos wants to merge 1 commit into
vojtab/slack-app-per-message-identityfrom
vojtab/slack-app-per-message-github-identity

Conversation

@VojtechBartos

Copy link
Copy Markdown
Member

Problem

Stacked on #69618 (which rebinds the PostHog MCP identity per message). Commits and PRs from the agent sandbox are still authored by whoever created the task, even when a teammate is the one driving the turn — their work lands under someone else's name.

Changes

Extends the per-message rebind to GitHub: when the acting user has a personal GitHub install covering the task's repository, the live sandbox's git remote token, GITHUB_TOKEN/GH_TOKEN, and GIT_AUTHOR_*/GIT_COMMITTER_* are swapped via the agentsh env file — which the exec wrapper re-sources per command, so the change reaches the agent's later git/gh calls (including gh pr create) with no sandbox restart. The facade's rebind_sandbox_identity_for_user gains the GitHub half; the Slack layer is untouched.

Guardrails, since two background systems re-apply GitHub credentials and would otherwise fight a swap:

  • The credential refresh loop resolves the swapped integration instead of the task creator's, and token-rotation propagation skips sandboxes whose identity was swapped away — neither silently reverts a swap.
  • A github_user identity mark lets same-actor messages skip integration resolution entirely (a DB query and, on a stale repo cache, a paginated GitHub API sync per message otherwise), and it survives swaps — including switching back to the creator.
  • Sandbox liveness is checked before the token-rotation lock, so a dead sandbox never triggers a mint-and-revoke.
  • Only user-authored, non-caller-token runs are ever swapped; actors without a covering install keep the previous identity (their message still goes through — they simply keep authoring as before).

How did you test this code?

Automated only; manual multiplayer verification planned with the queue-workflow dev rollout.

  • Six tests in test_sandbox_credentials.py, each pinning a distinct regression: the swap applies token + git author through the shared apply helper in one env write and records both identity marks; actors without a covering install, bot-authored runs, and same-identity messages are skipped; switching back to the creator re-applies their identity; and the creator fast path skips integration resolution on never-swapped runs.
  • Full tasks process_task + slack_app forwarding suites green on this branch and on the base branch independently.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Docs update

N/A, internal credential mechanics behind the queue-workflow flag.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Authored with Claude Code; split out of a combined MCP+GitHub identity PR so this tasks-owned half reviews independently. Decisions: identity marks live in the tasks cache alongside the MCP one (durable TaskRun.state storage is a named follow-up, as is including swapped-to sandboxes in rotation propagation); the swap reuses apply_github_credentials_to_sandbox via a new extra_env parameter so there is one definition of where a sandbox reads GitHub tokens from; the agentsh env-file mechanism was verified to re-source per command, so no sandbox-side changes were needed.

@VojtechBartos VojtechBartos self-assigned this Jul 10, 2026
@trunk-io

trunk-io Bot commented Jul 10, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic BadgeStatic Badge

View Full Report ↗︎Docs

Extends the per-message identity rebind: when the acting user has a
personal GitHub install covering the task's repository, swap the git
remote token, GITHUB_TOKEN/GH_TOKEN, and GIT_AUTHOR_*/GIT_COMMITTER_*
in the live sandbox via the agentsh env file (re-sourced per command,
so no restart), making this turn's commits and PRs theirs. Actors
without a covering install keep the previous identity; bot-authored
and caller-token runs are never swapped.

The github/github_user identity marks make the credential refresh loop
resolve the swapped integration instead of the task creator's, keep
token-rotation propagation from reverting a swap, and let same-actor
messages skip integration resolution entirely. Sandbox liveness is
checked before the rotation lock so a dead sandbox never triggers a
token mint-and-revoke.
@VojtechBartos
VojtechBartos force-pushed the vojtab/slack-app-per-message-github-identity branch from 86e4de7 to cb3ffdd Compare July 13, 2026 11:16
@github-actions

Copy link
Copy Markdown
Contributor

🤖 CI report

ℹ️ ClickHouse migration SQL — 1 migration(s)

ClickHouse migration SQL per cloud environment

  • unset
    • all
      DROP TABLE IF EXISTS property_values_mv
      CREATE MATERIALIZED VIEW IF NOT EXISTS property_values_mv
      TO property_values
      AS SELECT
          team_id,
          property_type,
          property_key,
          property_value,
          property_count,
          coalesce(_timestamp, now()) as last_seen
      FROM posthog_test.kafka_property_values
  • US, EU
    • aux
      DROP TABLE IF EXISTS property_values_mv
      CREATE MATERIALIZED VIEW IF NOT EXISTS property_values_mv
      TO property_values
      AS SELECT
          team_id,
          property_type,
          property_key,
          property_value,
          property_count,
          coalesce(_timestamp, now()) as last_seen
      FROM posthog_test.kafka_property_values
  • DEV
    • data
      DROP TABLE IF EXISTS property_values_mv
      CREATE MATERIALIZED VIEW IF NOT EXISTS property_values_mv
      TO property_values
      AS SELECT
          team_id,
          property_type,
          property_key,
          property_value,
          property_count,
          coalesce(_timestamp, now()) as last_seen
      FROM posthog_test.kafka_property_values

@VojtechBartos

Copy link
Copy Markdown
Member Author

Closing to rebuild on master's run-state actor design (#66212). The replacement follows #70454's transition-gate pattern so MCP and GitHub identity switch in the same place.

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