Add actor-aware git identities with HTTPS credential override#6
Add actor-aware git identities with HTTPS credential override#6yashturkar wants to merge 5 commits into
Conversation
Separate USER (human) and AGENT (API) git identities so commits and pushes are attributed to the correct account. Each actor gets its own author/committer name+email, optional SSH command, and—new in this PR—an optional HTTPS token that overrides system credential helpers via git url.insteadOf rewriting. - Add GitActor type and propagate actor through all git_service calls - Add _actor_env() to inject per-actor GIT_AUTHOR_*, GIT_COMMITTER_*, GIT_SSH_COMMAND, and url.insteadOf env vars - Add GITHUB_AGENT_TOKEN for agent-specific PR creation - Route source=human writes with USER_ACTOR, source=api with AGENT_ACTOR - Update autosave worker to use USER_ACTOR for pull/commit/push - Add GIT_AGENT_HTTPS_TOKEN config for HTTPS push auth separation - Update tests for actor propagation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Flag that USER vs AGENT identity is currently caller-declared via the source query param and should be derived from authentication. Added to SECURITY.md, kb-server product spec, and tech-debt tracker. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The docs_lint script expects this directory to exist. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The generator used local time, causing date mismatches when CI runs in UTC. Switch to datetime.now(timezone.utc). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| GitActor = Literal["user", "agent"] | ||
| USER_ACTOR: GitActor = "user" | ||
| AGENT_ACTOR: GitActor = "agent" |
There was a problem hiding this comment.
This may be cleaner as an enum. The current pattern duplicates the allowed values by defining both a Literal alias and named constants. An enum would centralize the valid options in one place and make usage clearer.
| def push_branch( | ||
| branch: str, | ||
| remote: str | None = None, | ||
| retries: int = 2, | ||
| actor: GitActor | None = None, | ||
| ) -> None: |
There was a problem hiding this comment.
The general push also has branch and remote args. Why is this needed?
There was a problem hiding this comment.
Incase you don't wanna push to master/main ..?
There was a problem hiding this comment.
We haven't exposed that to the config though
There was a problem hiding this comment.
This relates to my other comment but it seems push is only called by autosave for user. We can just one with defaults to be main/master.
| def _token_for_actor(actor: GitActor = AGENT_ACTOR) -> str: | ||
| if actor == AGENT_ACTOR and settings.github_agent_token: | ||
| return settings.github_agent_token | ||
| return settings.github_token |
There was a problem hiding this comment.
Might be safer to explicitly check for if it also a user actor instead operating under the assumption of anything not agent is user. This might also be affected by moving to the enum
| remote: str | None = None, | ||
| branch: str | None = None, | ||
| retries: int = 2, | ||
| actor: GitActor | None = None, |
There was a problem hiding this comment.
We can also enforce constraints here. It seems only autosave uses this function to push user edits. We can only allow user edits here.
There was a problem hiding this comment.
Agreed, even better if we entirely yeet autosave and just keep vault-sync which uses the API
|
@copilot address @yashomdighe 's comments and update this PR with the fix |
|
@yashturkar I've opened a new pull request, #14, to work on those changes. Once the pull request is ready, I'll request review from you. |
Summary
GIT_AGENT_HTTPS_TOKENconfig that usesurl.insteadOfto override system credential helpers (osxkeychain, store) for agent pushesGITHUB_AGENT_TOKENfor agent-specific GitHub API calls (PR creation)GitActorthrough allgit_service,git_batcher,github_service,autosave, and route layerssourceparam) in SECURITY.md, product spec, and tech-debt trackerdocs/exec-plans/active/directory required by docs_lintTest plan
source=humanwrite commits tomainas USER identity and pushes with user credentialssource=apiwrite commits tokb-api/*branch as AGENT identity, pushes with agent token, creates PR as agentgit logshows distinct author/committer for each actordocs_lint.pypasses🤖 Generated with Claude Code - skipped over my docs and tests despite telling it, then switched to codex