Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/agent-memory/archgate-developer/MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Skipping steps 2 or 3 is a workflow violation. The user should NEVER have to inv
- **`CHANGELOG.md` is auto-generated — exclude from Prettier** — `CHANGELOG.md` is written by `TrigenSoftware/simple-release-action` during the release PR workflow. It is committed directly and never formatted by Prettier. It MUST be in `.prettierignore`; otherwise `bun run format:check` (part of `bun run validate`) will fail on the release PR. Do not attempt to run prettier on it post-commit.
- **`mock.module("node:fetch", ...)` does NOT intercept `globalThis.fetch` in Bun** — Bun's runtime fetch is `globalThis.fetch`, not the `node:fetch` module. Using `mock.module` silently fails; the real network is hit. Always mock fetch by assigning `globalThis.fetch = mockFn as unknown as typeof fetch` directly, and restore via `mock.restore()` in `afterEach`. TypeScript type cast: `as never` is insufficient for the `typeof fetch` type (which includes `preconnect`) — always use `as unknown as typeof fetch`. Also captured in ARCH-005 Don'ts.
- **Git credential tests need system-level isolation on Windows** — Overriding `Bun.env.HOME` is NOT sufficient to isolate `git credential fill/approve` calls in tests. Windows Credential Manager is a system-level API, not file-based. Tests MUST set `Bun.env.GIT_CONFIG_NOSYSTEM = "1"` and `Bun.env.GIT_CONFIG_GLOBAL = <path-to-empty-file>` to prevent git from reading the real credential helper config. Without this, tests on machines with stored credentials will pick up real tokens.
- **GCM prompt suppression requires 5 env vars** — `GIT_TERMINAL_PROMPT=0` alone does NOT prevent Git Credential Manager (GCM) from showing GUI prompts on Windows or askpass prompts on Linux. The full set for `gitCredentialEnv()` in `src/helpers/credential-store.ts` is: `GIT_TERMINAL_PROMPT=0`, `GCM_INTERACTIVE=never`, `GCM_GUI_PROMPT=false`, `GIT_ASKPASS=""`, `SSH_ASKPASS=""`. Omitting any one can trigger unexpected prompts in editor/MCP contexts where the CLI runs as a subprocess.
- **Module-level `{ ...Bun.env }` captures env at import time** — Spreading `Bun.env` into a module-level constant freezes the env snapshot. Tests that override `Bun.env.HOME` after import won't affect the constant. Fix: use a function that returns `{ ...Bun.env, ... }` on each call so it picks up test-time overrides. Applied in `src/helpers/credential-store.ts`.

## Validation Pipeline
Expand Down
5 changes: 3 additions & 2 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"attribution": { "commit": "", "pr": "" },
"permissions": {
"allow": [
"Bash(oxfmt *)",
Expand All @@ -18,7 +19,6 @@
"Grep"
]
},
"attribution": { "commit": "", "pr": "" },
"hooks": {
"PreToolUse": [
{
Expand All @@ -44,5 +44,6 @@
]
}
]
}
},
"enabledPlugins": { "sentry@claude-plugins-official": true }
}
22 changes: 20 additions & 2 deletions src/helpers/credential-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,27 @@ import { internalPath } from "./paths";
const CREDENTIAL_HOST = "plugins.archgate.dev";
const CREDENTIAL_TIMEOUT_MS = 3_000;

/** Build env for git credential commands at call time (not import time). */
/**
* Build env for git credential commands at call time (not import time).
*
* Suppresses ALL interactive prompts — terminal, GUI, and askpass — across
* platforms and Git Credential Manager (GCM) versions:
*
* - GIT_TERMINAL_PROMPT=0 — git's own terminal prompt
* - GCM_INTERACTIVE=never — GCM interactive mode (terminal + GUI)
* - GCM_GUI_PROMPT=false — GCM GUI-only prompt (Windows toast/dialog)
* - GIT_ASKPASS="" — external askpass program
* - SSH_ASKPASS="" — SSH askpass fallback (some helpers reuse it)
*/
function gitCredentialEnv(): Record<string, string | undefined> {
return { ...Bun.env, GIT_TERMINAL_PROMPT: "0", GCM_INTERACTIVE: "never" };
return {
...Bun.env,
GIT_TERMINAL_PROMPT: "0",
GCM_INTERACTIVE: "never",
GCM_GUI_PROMPT: "false",
GIT_ASKPASS: "",
SSH_ASKPASS: "",
};
}

export interface StoredCredentials {
Expand Down
Loading