Skip to content

[REMOTE-1370] Phase 2b: driver credential writes and refresh loop#10153

Open
jasonkeung wants to merge 4 commits intomasterfrom
jason/remote-1370-phase2-impl
Open

[REMOTE-1370] Phase 2b: driver credential writes and refresh loop#10153
jasonkeung wants to merge 4 commits intomasterfrom
jason/remote-1370-phase2-impl

Conversation

@jasonkeung
Copy link
Copy Markdown
Contributor

@jasonkeung jasonkeung commented May 5, 2026

Description

Second half of Phase 2 of REMOTE-1370. Depends on: #10152.

Adds the actual credential management logic in the driver — startup writes, git config, and periodic refresh.

Changes:

  • New `driver/git_credentials.rs` with:
    • Atomic writes to `/.git-credentials` and `/.config/gh/hosts.yaml`
    • One-time git config setup (`credential.helper store`, SSH→HTTPS `url.insteadOf`)
    • Git user identity configuration from server-returned username/email
    • `refresh_loop()`: infinite async future that re-fetches and overwrites credentials every ~50 minutes
  • `fetch_secrets_and_attachments` calls `taskGitCredentials` as a 5th parallel fetch alongside the existing four (managed secrets, task attachments, task metadata, handoff snapshot); writes credential files and git config on completion
  • `run_internal` races harness execution against the refresh loop via `futures::select!` for both Oz and ThirdParty harness paths; the refresh future is dropped when the harness completes

Why 50 minutes: GitHub tokens expire after 1 hour. The server's `OAuthConnectionTokenSource` already refreshes with a 55-minute lead time, so each call returns a fresh token.

This PR should not merge until Phase 1 (warp-server) is deployed and stable, and #10152 is merged first.

Linked Issue

Linear: REMOTE-1370

Testing

  • All existing tests pass (`cargo nextest run --no-fail-fast -p warp`)
  • `cargo fmt` and `cargo clippy` clean

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

Conversation: https://staging.warp.dev/conversation/e16dc3e2-8e2f-4499-8c9b-59b200e17c50

Co-Authored-By: Oz oz-agent@warp.dev

jasonkeung and others added 2 commits May 5, 2026 11:56
- Add taskGitCredentials types to schema.graphql (verified against staging)
  and add to clientQueries allowlist in client-schema.ts
- Add task_git_credentials.rs GraphQL query file (cynic) following the
  task_secrets pattern
- Add GitCredential struct and get_task_git_credentials to AIClient
  trait with a ServerApi implementation

Co-Authored-By: Oz <oz-agent@warp.dev>
- Add driver/git_credentials.rs: atomic writes to ~/.git-credentials
  and ~/.config/gh/hosts.yaml, one-time git config setup (credential.helper
  store, url.insteadOf), git identity configuration, and refresh_loop()
  which re-fetches credentials every 50 minutes
- Extend fetch_secrets_and_attachments to call taskGitCredentials in
  parallel at startup; writes credential files and git config
- Add futures::select! refresh loop in run_internal, racing the harness
  execution against the infinite refresh loop for both Oz and ThirdParty
  harnesses

Co-Authored-By: Oz <oz-agent@warp.dev>
@jasonkeung
Copy link
Copy Markdown
Contributor Author

/oz-review

@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 5, 2026

@jasonkeung

I'm re-reviewing this pull request in response to a review request.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR adds cloud-agent git/gh credential file management, git config setup, and a periodic refresh loop around Oz and third-party harness execution.

Concerns

  • The credential file writes create token-bearing files with default process umask permissions instead of forcing owner-only permissions.
  • The second url.https://github.com/.insteadOf write overwrites the first rewrite, so one advertised SSH URL form will not be configured.

Security

  • GitHub tokens are written to plaintext credential files; those files must be created with restrictive permissions before merge.

Verdict

Found: 0 critical, 2 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread app/src/ai/agent_sdk/driver/git_credentials.rs Outdated
Comment thread app/src/ai/agent_sdk/driver/git_credentials.rs Outdated
- Write ~/.git-credentials and ~/.config/gh/hosts.yaml temp files with
  0600 permissions (mode + set_permissions) matching the existing pattern
  in write_codex_auth_json, preventing other users from reading tokens
- Add run_git_config_add (--add flag) so multi-value insteadOf entries
  coexist instead of the second overwriting the first
- Derive SSH→HTTPS URL rewrites from credential hosts rather than
  hardcoding github.com, using --add for both scp-style and ssh:// forms
  per host

Co-Authored-By: Oz <oz-agent@warp.dev>
@jasonkeung
Copy link
Copy Markdown
Contributor Author

/oz-review

@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 5, 2026

@jasonkeung

I'm re-reviewing this pull request in response to a review request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR adds driver-side GitHub credential setup for cloud agent sandboxes, including initial credential file writes, git/gh configuration, and a periodic refresh loop that is raced against Oz and third-party harness execution.

Concerns

  • No blocking code or security concerns found in the annotated diff.
  • The PR description states this should not merge until Phase 1 is deployed and #10152 is merged; keep that release dependency enforced outside this code review.

Verdict

Found: 0 critical, 0 important, 0 suggestions

Approve

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

@jasonkeung jasonkeung marked this pull request as ready for review May 5, 2026 18:50
@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 5, 2026

@jasonkeung

I'm starting a first review of this pull request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR adds cloud-agent GitHub credential file setup, git/gh configuration, and a periodic refresh loop for long-running harnesses.

Concerns

  • Empty credential responses are treated as no-ops, which can leave previously written GitHub credentials on disk in reused or revoked-auth scenarios.
  • Refresh failures sleep for another full refresh interval before retrying, so a single transient failure around the 50-minute refresh point can leave agents with expired credentials until the next 50-minute tick.

Security

  • Stale credential files should be cleared when the server returns no credentials; otherwise previous task credentials can remain available in the sandbox.

Verdict

Found: 0 critical, 2 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

log::info!("Git credentials configured from taskGitCredentials");
}
}
Ok(_) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] [SECURITY] Treating an empty authoritative response as a no-op leaves any existing ~/.git-credentials/hosts.yaml from a previous run in place; clear the credential files instead so reused sandboxes cannot retain stale repo access.

Ok(creds) => creds,
Err(e) => {
log::warn!("Failed to refresh git credentials: {e:#}");
continue;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] On this continue the loop sleeps another full 50 minutes, so one transient refresh failure at the 50-minute mark can leave credentials expired until the next retry; use a short backoff within the remaining validity window.

jasonkeung added a commit that referenced this pull request May 5, 2026
#10152)

## Description

First half of Phase 2 of REMOTE-1370. Adds the GraphQL plumbing for
\`taskGitCredentials\` so the driver can call it in the next PR.

**Changes:**
- Add \`taskGitCredentials\` types to \`schema.graphql\` and add to the
\`clientQueries\` allowlist in \`client-schema.ts\`
- New \`task_git_credentials.rs\` cynic query file, following the
\`task_secrets\` pattern
- Add \`GitCredential\` struct and \`get_task_git_credentials\` to
\`AIClient\` trait + \`ServerApi\` implementation

No behaviour change — nothing calls \`get_task_git_credentials\` yet;
that's in the follow-on PR.

**schema.graphql approach:** \`yarn generate -p staging\` was run to
verify the new types, but the output was not committed wholesale because
the current staging server also has other unrelated schema changes
(removed \`freeAvailableModels\`, new \`VOYAGE_4_512\` EmbeddingConfig
variant, etc.) that are out of scope and would break existing Rust
bindings. Instead, only the \`taskGitCredentials\` types were
cherry-picked — the field names, nullability, and doc comments were
verified to be identical to what the server generates.

Warp-server staging is deployed with the new query.

Followed by: #10153.

## Linked Issue

Linear: REMOTE-1370

## Testing

- \`cargo build -p warp\` clean
- \`cargo fmt\` and \`cargo clippy\` clean

## Agent Mode
- [x] Warp Agent Mode - This PR was created via Warp's AI Agent Mode

Conversation:
https://staging.warp.dev/conversation/e16dc3e2-8e2f-4499-8c9b-59b200e17c50

Co-Authored-By: Oz <oz-agent@warp.dev>

---------

Co-authored-by: Oz <oz-agent@warp.dev>
Co-authored-by: oz-for-oss[bot] <277970191+oz-for-oss[bot]@users.noreply.github.com>
Base automatically changed from jason/remote-1370-phase2-infra to master May 5, 2026 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant