Skip to content

feat(git): PAT-free clone of public github: templates (trinity-enterprise#123)#1757

Open
vybe wants to merge 1 commit into
devfrom
feature/ent123-pat-free-clone
Open

feat(git): PAT-free clone of public github: templates (trinity-enterprise#123)#1757
vybe wants to merge 1 commit into
devfrom
feature/ent123-pat-free-clone

Conversation

@vybe

@vybe vybe commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Creating an agent from a public github:owner/repo template now succeeds with no GitHub PAT anywhere — anonymous, read-only, source-mode clone. Gating prerequisite for the fresh-install fleet-provisioning epic (abilityai/trinity-enterprise#122 → first-run manifest seed ent#124, UI manifest install ent#126).
  • Visibility is validated over the git transport (credential-less git ls-remote probe — same transport as the real clone, immune to the anonymous REST 60/hr cap): definitive miss → combined named 400 "not found or private — add a GitHub token"; transient → fail-closed 502 (monitoring is default-off, a fail-open would ship a silently empty agent).
  • Every push surface fails honestly for a tokenless agent: backend sync/reset return a named no_write_credentials 409 (baked env or per-agent PAT row — covers the bug: per-agent GitHub PAT (#347) never propagates to an existing container — git remote keeps an empty password, all pushes fail #1264 live-injection window), the container's push remote is blackholed with a self-describing URL, and the MCP git_sync hint stops suggesting chat_with_agent (chat can't fix missing credentials).
  • Closes a second silent-empty-agent route while at it: the bug(recovery): soft-delete recovery dead-ends — recover tells you to start, but start 404s when the container is gone #1559 rebuild-recovery seam (_apply_persisted_auth_env) gated github env on pat AND repo — now repo-only, PAT-conditional, with source-mode/branch re-derivation.

Changes

  • src/backend/services/agent_service/crud.py — tokenless gate (""None normalization, source-mode-only 400 incl. explicit None), owner/repo charset guard, tokenless ls-remote validation branch, repo-only env assembly (token vars + GIT_SYNC_AUTO require a PAT)
  • src/backend/services/agent_service/lifecycle.py — rebuild-seam gate flip
  • src/backend/services/git_service.pyprobe_anonymous_repo_access, _agent_has_write_credentials + guards; src/backend/routers/git.py — reset 409 mapping
  • docker/base-image/startup.sh — repo-only clone gate, conditional CLONE_URL, GIT_TERMINAL_PROMPT=0, push blackhole, workspace-.env PAT fallback, private-repo failure cause
  • src/mcp-server/src/tools/git.tsno_write_credentials hint suppression
  • Docs: requirements/github.md §11.11, architecture.md, github-sync.md + mcp-git-tools.md flows, learnings.md

⚠️ Deploy note

Base-image rebuild is a hard ordering requirement. An un-rebuilt image still has the old GITHUB_PAT-gated clone block — tokenless creation on it yields an empty agent with no failure marker. ./scripts/deploy/build-base-image.sh before (or with) backend rollout.

Test Plan

  • New: pytest tests/unit/test_ent123_tokenless_clone.py -v — 50 tests (gate, charset guard, probe outcomes, env assembly, rebuild seam, stderr classification, write-credential guard, startup.sh static)
  • Pinned regressions green (130): test_1484_create_agent_characterization · test_1439_clone_status_health · test_1574_gh_token_wiring · test_ent162_per_user_github_pat · test_1264_per_agent_pat_propagation · test_fork_to_own
  • /verify-local (base-image build + real agent boot) recommended before release — the anonymous in-image clone is the one path unit tests can't prove

Refs abilityai/trinity-enterprise#123 (cross-repo — closed manually at release)

🤖 Generated with Claude Code

…rce-mode agents (trinity-enterprise#123)

Creating an agent from a public github:owner/repo now works with no GitHub
token anywhere: anonymous read-only source-mode clone. Gating prerequisite
for the ent#122 fresh-install fleet provisioning epic (first-run manifest
seed ent#124, UI manifest install ent#126).

Backend:
- crud.py: _gate_tokenless_request ("" -> None normalization; tokenless is
  source-mode-only — falsy check catches explicit None; fork passthrough);
  owner/repo charset guard before startup.sh's eval-built clone command;
  _validate_github_access tokenless branch probes over the git transport
  (probe_anonymous_repo_access ls-remote — immune to the anon REST 60/hr
  cap; definitive miss -> combined "not found or private" 400; transient ->
  fail-closed 502) + anonymous source-branch check; _apply_github_env gates
  on repo only (token vars + GIT_SYNC_AUTO require a PAT).
- lifecycle.py: _apply_persisted_auth_env rebuild seam gates on repo, not
  PAT — a tokenless agent rebuilt after container loss still clones
  (closes another silent-empty-agent route, #843/#1439 class); source-mode
  rows re-derive GIT_SOURCE_MODE/BRANCH.
- git_service.py: probe_anonymous_repo_access; sync_to_github and
  reset_to_main_preserve_state pre-check write credentials (baked env OR
  per-agent PAT row — never global; covers the #1264 live-injection
  window) -> named no_write_credentials 409 instead of a cryptic auth
  failure. routers/git.py maps it into the reset 409 set.
- mcp-server git.ts: no_write_credentials suppresses the chat_with_agent
  hint (a chat turn cannot fix missing credentials).

Base image (rebuild required — release-note ordering requirement):
- startup.sh clone gate is repo-only; CLONE_URL embeds oauth2 only when a
  PAT exists (mirrors the fork-to-own UPSTREAM_URL); GIT_TERMINAL_PROMPT=0
  fail-fast; tokenless push remote blackholed (self-describing URL) so any
  in-container push fails legibly; workspace-.env PAT fallback protects a
  live-injected token across ops-path raw restarts; private-repo cause
  added to clone-failure text.

Tests: tests/unit/test_ent123_tokenless_clone.py (50) + 130 pinned
regression tests green (1484/1439/1574/ent162/1264/fork_to_own).
Docs: requirements github.md §11.11, architecture.md, github-sync.md +
mcp-git-tools.md flows, learnings.md.

Refs abilityai/trinity-enterprise#123

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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