Skip to content

fix(runner): keep warm sessions alive with managed GitHub access - #13815

Merged
cryppadotta merged 2 commits into
masterfrom
codex/github-credential-reuse-repro-20260922
Sep 22, 2026
Merged

cryppadotta merged 2 commits into
masterfrom
codex/github-credential-reuse-repro-20260922

Conversation

@cryppadotta

@cryppadotta cryppadotta commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Thinking Path

  • Paperclip manages AI agents and their work.
  • The native Runner keeps a live provider process between task turns.
  • Managed GitHub access used a token tied to one run.
  • A new run forced Paperclip to replace that process to replace its token.
  • This PR gives the session a stable credential transport and binds each operation to the active run.
  • The agent can keep its process while Paperclip checks current identity and grants.

Linked Issues or Issue Description

Follow-up to #13738. Related credential-rotation work: #11770 and #8208 use process replacement for other adapter credentials; this change applies to managed GitHub access in the native Runner.

What happened?

A configured GitHub connection forced a warm native provider process to close at each new run. The saved conversation survived, but the live process did not.

Expected behavior

Keep the warm provider process. Resolve GitHub access for the current run when each command starts. Deny access while idle or after the run ends.

Steps to reproduce

  1. Configure managed GitHub access for a native Runner agent with a warm session.
  2. Complete a turn, then send another message to the same task.
  3. Observe the provider process close with the reason warm native session configuration changed.

Paperclip version or commit

Reproduced on master 8326e33ad. Rebased onto e3d8fb087 before submission.

Deployment mode

Local and remote native execution, including the sandbox callback bridge.

What Changed

  • Move configured native GitHub transport and launcher ownership from the run to the provider session.
  • Bind the broker only after the executor acquires session ownership. Clear that binding when the run exits.
  • Keep the shared live-run, identity, grant, and trust-policy checks for each credential request.
  • Reject wrong scopes, idle requests, and credential responses that arrive after their run binding changes.
  • Retire transport and launcher files with the provider session. Keep anonymous commands available if bridge startup fails.
  • Add red/green executor tests, real subprocess and callback-bridge tests, and database checks. Update the runtime documentation.

Verification

  • Before the fix, both new local and remote warm-session reuse tests failed.
  • After the fix, 435 targeted tests passed across the executor, broker, launcher, token, and database suites.
  • A real long-lived test process kept the same PID and original environment across two runs, including through the production callback bridge on local test processes.
  • Server typecheck and TypeScript compilation passed.
  • Full workspace typecheck and build passed. Server typecheck passed again after the review fix.
  • The fallback-logging regression failed before the fix; all 9 broker tests pass afterward.
  • The exact chat sidebar browser scenario passed locally. The initial CI timeout showed failed Vite module downloads; all eight browser shards pass on the latest commit.
  • All 53 latest-head checks passed, including the full CI test matrix and security checks (two unrelated conditional checks skipped).
  • The duplicate full local test run was stopped after CI passed; it is not claimed as a completed local pass. Targeted local tests, workspace typecheck/build, and the browser scenario passed.
  • Greptile reviewed the latest commit at 5/5 with no unresolved findings.
  • No fresh paid provider or Daytona campaign has run for this change.

Risks

  • The broker now lives as long as the provider session. Tests cover idle denial, late cleanup, late responses, shutdown, and failed startup.
  • Its in-memory authority does not survive a controller restart. Existing checkpoint and process-recovery rules still apply.
  • Raw GitHub credentials remain confined to individual command processes. The session transport token cannot select a different task, agent, company, or run.
  • No database migration or public API change.

Model Used

OpenAI Codex, GPT-6, with reasoning, terminal tools, and code execution. The exact serving model ID and context-window size are not exposed in this session.

Checklist

  • I have included a thinking path that traces from project context to this change
  • I have specified the model used (with version and capability details)
  • I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work
  • I have searched GitHub for duplicate or related PRs and linked them above
  • I have either (a) linked existing issues with Fixes: # / Closes # / Refs # OR (b) described the issue in-PR following the relevant issue template
  • I have not referenced internal/instance-local Paperclip issues or links (only public GitHub #NNN / github.com/paperclipai/paperclip URLs)
  • My branch name describes the change (e.g. docs/..., fix/...) and contains no internal Paperclip ticket id or instance-derived details
  • I have run tests locally and they pass
  • I have added or updated tests where applicable
  • I have updated relevant documentation to reflect my changes
  • I have considered and documented any risks above
  • All Paperclip CI gates are green
  • Greptile is 5/5 with no open P2s, recommendations, or follow-ups
  • I will address all Greptile and reviewer comments before requesting merge

Co-Authored-By: Paperclip <noreply@paperclip.ing>
@greptile-apps

greptile-apps Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with no outstanding correctness, security, or repository-rule findings.

Summary

This PR moves managed GitHub credential transport from run lifetime to native provider-session lifetime so warm provider processes can survive across runs while operation-time authorization remains bound to the active run.

  • Adds a session-owned, loopback-only credential broker with stable launcher transport and per-run activation.
  • Rechecks live-run identity, grants, and trust policy for each credential request and rejects idle or stale responses.
  • Retires broker and launcher resources with the warm session, while preserving anonymous commands when remote bridge startup fails.
  • Updates heartbeat integration, lifecycle documentation, and local/remote regression coverage.
  • The previous fallback-logging finding is fully fixed: failures from the optional log sink are now contained.

Reviews (2) · Last reviewed commit: "fix(runner): tolerate logging failure du..."

Comment thread server/src/services/native-runtime/native-github-access.ts Outdated
Co-Authored-By: Paperclip <noreply@paperclip.ing>
@cryppadotta
cryppadotta merged commit 3d78e3a into master Sep 22, 2026
56 checks passed
@cryppadotta
cryppadotta deleted the codex/github-credential-reuse-repro-20260922 branch September 22, 2026 18:07
cryppadotta added a commit that referenced this pull request Sep 22, 2026
…tools

* origin/master:
  refactor(server): remove retired operator UI snippet injection (#13789)
  fix(runner): keep warm sessions alive with managed GitHub access (#13815)
  fix: continue native agent chats after worker loss (#13813)
  fix: preserve chat message bindings in review recovery (#13818)
  chore(lockfile): refresh pnpm-lock.yaml (#13780)
  feat(ui): enable Grok in Cloud agent setup (#13791)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
cryppadotta added a commit that referenced this pull request Sep 22, 2026
…age (#13824)

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Runner E2E tests verify real tasks and retain evidence for failures.
> - Some exposure tests assumed that port 42000 was free.
> - A blank task page could also fail without enough browser startup
evidence.
> - This pull request tests occupied ports and task reloads, and records
private startup diagnostics.
> - These changes make test failures easier to reproduce and explain.

## Linked Issues or Issue Description

Refs #13815. Report publication already received its production fix in
#13750; this PR adds a regression check for that workflow.

**What happened?**

Three exposure tests assumed that the allocator would select port 42000.
The synthetic failure disappeared when another process occupied that
port. A prior Daytona run also retained an empty task page after
navigation, but its evidence did not record pending modules or
service-worker control.

**Expected behavior**

Exposure tests must exercise the intended failure on the actual assigned
port. Browser failure evidence must distinguish an empty root from
loaded content. A saved task must remain usable after navigation and
reload.

**Steps to reproduce**

Run the exposure regression with the base port pair marked unavailable.
Run the browser-support tests with an unresolved entry module. Open a
saved task under the service worker, navigate to the same URL, and
reload it.

**Paperclip version or commit**

Based on master at a68f3d8.

## What Changed

- Make synthetic exposure failures use the assigned port. Test both free
and occupied base pairs.
- Record document readiness, root children, service-worker control,
pending module paths, and recent module error or 304 statuses in private
runner evidence.
- Add browser tests for pending startup, failed module responses, and
diagnostic reset after navigation.
- Add a provider-free browser test for persisted task content and the
composer across three navigation/reload cycles.
- Guard trusted report-job lockfile resolution before frozen install and
AWS credential setup.
- Document the new evidence and test commands.

## Verification

- `pnpm test:e2e:runner:unit`: 443 tests passed.
- `pnpm test:e2e:runner:browser-support`: 10 tests passed.
- Exposure tests: 28 passed; 3 platform-specific skips.
- Harness typecheck, workspace typecheck, and full build passed.
- Task-reload browser test passed against a throwaway local instance. It
checks three navigation/reload cycles with a controlling service worker.
- All PR verification suites passed, including server, chat, workspace,
serialized server, Rust, runner, build, typecheck, and browser shards.
The existing sidebar navigation case showed an empty page on the first
CI attempt and passed on one retry.
- The monolithic local `pnpm test:run` was started, then stopped after
CI completed the equivalent suites. Additional local browser
reproduction attempts also hit embedded-Postgres startup failures; the
focused checks listed above completed successfully.
- Greptile: 5/5 on the current head, with no findings.

## Risks

This change affects tests and private test evidence. It does not change
production prompts or runtime behavior. Module paths omit queries; the
collector reads no response bodies or headers. The existing sanitizer
and publication allowlist still apply. A 304 response does not cause a
test failure.

The blank-page cause remains unconfirmed. The first CI attempt
reproduced it in an existing sidebar navigation case: the trace shows an
empty page after a service-worker-mediated 304 response for the large
editor module. The single retry passed. This PR adds coverage and
diagnostics; it does not claim to fix that intermittent symptom.

## Model Used

OpenAI Codex, GPT-6, with repository tools, code execution, and browser
tests. The exact deployed model variant and context-window size are not
exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
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