Credential Management¶
VERGIL uses gh auth as the sole credential store and selects
credentials per-subprocess based on the operation being performed.
No global state changes, no ambient environment variables, no
custom keychain management.
For account creation and initial setup, see Account Setup. For the identity model that credentials serve, see Identity Architecture.
Token Strategy¶
Classic PATs¶
Both accounts use classic Personal Access Tokens. Fine-grained PATs were evaluated and abandoned:
- Fine-grained PATs are scoped to a single resource owner — a
token for
vergil-projectcannot accessdiogenes-project. Multi-org requires N×2 tokens. gh authstores one token per account per host. Multiple fine-grained PATs for the same account cannot coexist.- Fine-grained PATs cannot be created by outside collaborators scoped to an org. The agent account is an outside collaborator by design.
Classic PATs work across all repos the account has access to, regardless of org. One token per account covers everything.
Token Scopes¶
Human account:
| Scope | Purpose |
|---|---|
repo |
Full repository access |
admin:org |
Org settings, collaborator management |
workflow |
GitHub Actions |
read:org |
Org membership visibility |
Agent account:
| Scope | Purpose |
|---|---|
repo |
Full repository access |
read:org |
Org membership visibility |
The agent PAT intentionally excludes admin:org and workflow.
Token scope is not the primary security boundary — it is the
fourth layer of defense. See
Permission Model for the full
defense-in-depth architecture.
Credential Store¶
gh auth as the Single Source¶
Both accounts are logged into gh auth on the developer's
machine. No custom keychain entries, no platform-specific secure
store abstraction. Setup is a one-time operation per machine.
The login command is the same both times — what changes is which GitHub account is authenticated in your browser when you authorize the OAuth flow.
gh auth login has no -u flag
You cannot specify which account to log in as on the command line. The browser session determines which account gets logged in.
Step 1 — Log in the human account. Make sure you are signed into github.com as your personal account in the browser, then run:
Complete the OAuth authorization in the browser. gh adds your
human account to its credential store.
Step 2 — Log in the agent account. Switch your browser session
to the -vergil account (sign out and sign back in as
<username>-vergil), then run the same command again:
Complete the OAuth authorization. gh detects that this is a
different account and adds it alongside the first — it does not
replace it.
Step 3 — Restore the human account as the active default.
After both logins, switch back so your human account is active
for any raw gh commands:
Token Retrieval¶
The tooling retrieves tokens without changing global state:
This is a read operation. It does not change the active account and is safe to call from parallel processes.
Credential Selection¶
The Core Principle¶
The tool selects the credential, not the caller. There is no flag,
no env var, no override. The vrg-gh wrapper determines the
appropriate identity based on the command being executed. This is
a hard security boundary.
Default: Agent Account¶
All operations default to the agent account. Development operations — creating PRs, pushing branches, viewing status, creating issues — run under the agent identity.
Escalation to Human Account¶
Specific operations escalate to the human account when both the command and its context pass validation:
- Merge: Allowed under the human account only when the target
matches release workflow patterns (e.g.,
release/*branches merging tomain, back-merge frommaintodevelop). - Approval: Allowed under the human account only for release
PRs authored by
vergil-release[bot]. - Other admin operations: Denied entirely.
Escalation requires both a permitted command and a validated context. A merge request for a feature branch is denied even though merges are conditionally allowed.
No Human Detection¶
The tooling does not distinguish between a human caller and an
agent caller. It always operates in agent-restricted mode. If a
human runs vrg-gh pr merge on a feature branch, it is denied
the same way. The human's escape hatch is raw gh or the GitHub
UI.
GH_TOKEN Injection¶
Credential selection is per-subprocess via the GH_TOKEN
environment variable. The tooling never calls gh auth switch.
How It Works¶
_discover_accounts()parsesgh auth statusto find the-vergilaccount and derive the human account name._human_token()callsgh auth token -u <human>and caches the result for the process lifetime._gh_env()builds an environment dict withGH_TOKENset to the appropriate token.- Every
subprocess.runcall that invokesghreceives this environment dict via theenvparameter.
Parallel sessions are fully isolated. Each process resolves its own token independently. No shared state, no lock contention.
Graceful Degradation¶
If credential discovery fails (account not logged in, gh not
installed), _gh_env() returns None and the subprocess inherits
the parent environment. This allows the tooling to function in CI
environments where credentials are provided through other
mechanisms.
Account Discovery¶
The discovery algorithm is deliberately simple:
- Run
gh auth statusand parse all logged-in accounts. - Find the one account ending in
-vergil. - Derive the human account by stripping the suffix.
- If zero or more than one
-vergilaccount exists, fail with an explicit error.
Any number of other accounts can be present — -mimir, legacy
-agent, personal accounts — they are all ignored. Only the
-vergil suffix matters.
Failure Modes¶
- No
-vergilaccount: Explicit error naming the convention and suggestinggh auth login. - Multiple
-vergilaccounts: Explicit error listing the accounts found. - Required account not in
gh auth: Explicit error suggesting the missing login. - Never silent fallback: The tooling never substitutes one account for another. If the required credential is unavailable, the operation fails.
Security Model¶
The credential system does not depend on token scope as the primary enforcement mechanism. Defense in depth, in priority order:
- Account permissions — the agent account is an outside collaborator with Write access to specific repos. It cannot access repos it hasn't been invited to, regardless of token scope.
- Branch protection — rulesets prevent merging without review, prevent direct pushes to protected branches, require CI to pass.
vrg-ghwrapper — gates which operations the agent can attempt and which credential is used for each.- Token scope — the narrowest classic PAT scopes that support the required operations.
Multi-Org Support¶
A classic PAT works across all repos the account has access to, regardless of which org owns them. Adding a new org requires only inviting the agent account as an outside collaborator — no token changes, no credential reconfiguration.
Related¶
- Account Setup — creating accounts and
logging into
gh auth - Identity Architecture — the two-account model and naming conventions
- Permission Model — enforcement layers beyond credential selection
- Credential management design spec — full decision rationale and alternatives considered