You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/implementation/auth.md
+21-1Lines changed: 21 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -65,6 +65,22 @@ Each credential is a separate keychain entry using service name `"githits"`:
65
65
66
66
The `v1:` prefix allows future key format changes without collisions.
67
67
68
+
#### Windows chunked storage
69
+
70
+
Windows Credential Manager limits credential blobs to `CRED_MAX_CREDENTIAL_BLOB_SIZE` (2560 **bytes**). The `@napi-rs/keyring` binding encodes passwords as UTF-16 (2 bytes per character), so the effective character limit is 1280. Since JSON-serialized token data (especially JWT access tokens) can exceed this, the CLI wraps the `KeyringService` with a `ChunkingKeyringService` decorator on Windows (`process.platform === "win32"`). This decorator is not applied on macOS or Linux, which have no practical per-entry size limits.
71
+
72
+
When a value exceeds `WINDOWS_MAX_ENTRY_SIZE` (1200 characters — a conservative threshold providing 80-char margin from the 1280 limit), the decorator splits it across multiple keyring entries. The chunk size is configurable via the `ChunkingKeyringService` constructor, so the same decorator can be reused if other platforms have different limits:
|`<original-key>:chunk:<writeId>:0`| First chunk of the JSON value |
78
+
|`<original-key>:chunk:<writeId>:N`| Nth chunk of the JSON value |
79
+
80
+
Each write uses a unique `writeId` to namespace chunk keys. This ensures atomicity: new chunks are written before the sentinel is updated, so a crash at any point leaves valid data. Old chunks are cleaned up after the sentinel is committed.
81
+
82
+
Values under 1200 characters are stored directly with no sentinel, maintaining full backward compatibility with pre-chunking CLI versions. If a user downgrades the CLI after tokens were stored as chunks, the old CLI reads the sentinel as raw text, fails JSON parsing (via `parseJsonOrNull`), and prompts re-login. The same applies to chunked client registrations, which would trigger re-registration. Both are acceptable graceful degradation.
83
+
68
84
The `getStorageLocation()` method returns a platform-specific label: "macOS Keychain (githits)" on macOS, "Windows Credential Manager (githits)" on Windows, and "System keychain (githits)" on Linux.
69
85
70
86
### File storage (fallback)
@@ -93,7 +109,9 @@ Keychain write must succeed before the file entry is deleted. Tokens and client
@@ -129,6 +147,7 @@ The `hasValidToken` flag is checked by `requireAuth()` in `src/commands/mcp.ts`
129
147
-**Token refresh fails silently** — By design. The container clears stale auth and `hasValidToken` becomes false, prompting re-login.
130
148
-**Clearing auth** — Run `githits logout` to remove stored tokens and client registration for the current environment.
131
149
-**Keychain unavailable warning** — If the system keychain is not accessible (headless Linux, CI), the CLI falls back to file storage in `~/.githits/` and prints a warning to stderr.
150
+
-**Windows "password encoded as UTF-16 is longer than platform limit"** — The Windows Credential Manager limits credential blobs to 2560 bytes (`CRED_MAX_CREDENTIAL_BLOB_SIZE`). Since passwords are stored as UTF-16 (2 bytes per char), the effective limit is 1280 characters. The `ChunkingKeyringService` decorator handles this automatically by splitting large values across multiple entries. If this error occurs on an older CLI version, upgrade to get chunked storage support.
132
151
133
152
## Key Reference Files
134
153
@@ -142,6 +161,7 @@ The `hasValidToken` flag is checked by `requireAuth()` in `src/commands/mcp.ts`
0 commit comments