Repository navigation
feat(auth)!: log in to the Archgate platform and serve git credentials - #602
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Team Run ID: 📒 Files selected for processing (8)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📜 Recent review details⏰ Context from checks skipped due to timeout. (3)
🧰 Additional context used📓 Path-based instructions (35)This project uses Archgate — an AI governance framework based on Architecture Decision Records (ADRs).⚙️ CodeRabbit configuration file Files:
Every subcommand module under `src/commands//` — at any nesting depth — MUST have a corresponding heading in the top-level parent's reference page at `docs/src/content/docs/reference/cli/.mdx`.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-016-cli-subcommand-documentation-accuracy.md) Files:
Keep English content at the root and mirror every English MDX file in each locale directory (`pt-br` and `nb`) with the same relative path and filename; do not create orphan translations.📄 CodeRabbit inference engine (.archgate/adrs/GEN-002-docs-i18n.md) Files:
All platform detection in `src/` must go through `src/helpers/platform.ts` (`isWindows()`, `isMacOS()`, `isLinux()`, `isWSL()`, or `getPlatformInfo()`); direct `process.platform` access and duplicated detection logic are forbidden outside `...📄 CodeRabbit inference engine (.archgate/adrs/ARCH-009-platform-detection-helper.md) Files:
All commands that operate on `.archgate/` project resources must use the shared `findProjectRoot()` from `src/helpers/paths.ts`; direct `process.cwd()` project-root resolution is prohibited except in `init`.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-011-consistent-project-root-resolution.md) Files:
Each command module must export a `register*Command(program)` function; each non-`index.ts` command file must define exactly one command.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-001-command-structure.md) Files:
Every asynchronous command action must wrap its entire body—from the first statement through the last—in a try-catch boundary.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-012-command-error-boundaries.md) Files:
In Commander.js command files, options requiring type narrowing beyond plain strings MUST use `new Option()` from `@commander-js/extra-typings` and register it with `.addOption()` instead of `.option()`.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-008-typed-command-options.md) Files:
**Directory structure mirrors `src/`** — `src/engine/runner.ts` is tested by `tests/engine/runner.test.ts`, so tests are discoverable by convention.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-005-testing-standards.md) Files:
Use `test.each()` or `describe.each()` for the same assertion logic against multiple independent inputs.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-025-idiomatic-bun-test-parametrization-and-matchers.md) Files:
Use Bun's built-in test runner (`bun test`) for all tests.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-005-testing-standards.md) Files:
All environment variable access in `src/` MUST use `Bun.env` instead of `process.env`.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-014-prefer-bun-env.md) Files:
All subprocess execution in Archgate source files must use `Bun.spawn` with array-based arguments; do not use `Bun.$` or import `$` from `bun`.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-007-cross-platform-subprocess-execution.md) Files:
copilot-gated behavior must use `isCopilotAvailable()` (PATH check OR config dir exists), never `isCopilotCliAvailable()` alone.📄 CodeRabbit inference engine (CLAUDE.md) Files:
Every `inquirer.prompt(...)` call must be wrapped in `withPromptFix(() => ...)` imported from `src/helpers/prompt.ts`; keep the wrapper adjacent to the prompt invocation so automated checks can detect it.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-019-inquirer-prompt-fix.md) Files:
Every call to `Bun.Glob#scan()` (`glob.scan(...)`) in source must pass `{ dot: true }` in its options object, including scans whose patterns do not explicitly target dot-directories.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-020-glob-scan-include-dotfiles.md) Files:
Use `styleText(format, text)` from `node:util` for all colored CLI output; do not use raw ANSI escape codes or third-party color libraries such as chalk, kleur, or picocolors.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-003-output-formatting.md) Files:
Use exit codes 0 for success, 1 for expected failures, 2 for internal errors, and 130 for user cancellation; do not use other exit codes.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-002-error-handling.md) Files:
When implementing Windows-specific behavior, consider WSL; do not assume that `process.platform === "linux"` means a native Linux environment.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-009-platform-detection-helper.md) Files:
Markdown and MDX text content MUST NOT contain a backslash-escaped backtick.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-021-authored-text-integrity.md) Files:
Prefer Bun built-ins for file I/O, HTTP, globbing, testing, and subprocess execution; prefer `node:` built-in modules over npm alternatives when appropriate.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-006-dependency-policy.md) Files:
Zod schemas are the single source of truth.📄 CodeRabbit inference engine (CLAUDE.md) Files:
Brazilian Portuguese translations must use correct diacritical marks, including characters such as `ã`, `ç`, `é`, `í`, `ó`, `ú`, `â`, `ê`, `ô`, and `à`.📄 CodeRabbit inference engine (.archgate/adrs/GEN-002-docs-i18n.md) Files:
Norwegian translations must use Bokmål rather than Nynorsk, use informal `du`, and preserve correct characters such as `æ`, `ø`, and `å`.📄 CodeRabbit inference engine (.archgate/adrs/GEN-002-docs-i18n.md) Files:
Project-authored TypeScript comments must be concise, describe current behavior only, and never narrate history, relocations, refactors, or how the code came to be.📄 CodeRabbit inference engine (.archgate/adrs/GEN-004-concise-forward-only-code-comments.md) Files:
Use MDX format for all documentation content pages under `docs/src/content/docs/`.📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md) Files:
Top-level command modules must follow the `src/commands/.ts` or `src/commands//index.ts` convention.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-015-cli-command-documentation-coverage.md) Files:
The documentation site must be an Astro 5/Starlight project under `docs/`, separate from the CLI project with its own package manifest, TypeScript configuration, lockfile, and build pipeline.📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md) Files:
Invoke linting, formatting, and validation through package scripts (`bun run lint`, `bun run format`, `bun run format:check`, and `bun run validate`), rather than directly invoking tool binaries such as `bunx prettier`, `bunx oxfmt`, `npx e...📄 CodeRabbit inference engine (.archgate/adrs/GEN-003-tool-invocation-via-scripts.md) Files:
Use `_resetAllCaches()` from `src/helpers/platform.ts` to simulate different platforms in tests rather than mocking `process.platform` directly.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-009-platform-detection-helper.md) Files:
**Barrel files and re-exports are forbidden.**📄 CodeRabbit inference engine (.archgate/adrs/ARCH-004-no-barrel-files.md) Files:
Heavy runtime dependencies such as `inquirer`, `posthog-node`, and `@sentry/*` must be loaded with dynamic `import()` at their point of use, never through top-level static value imports.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-018-lazy-load-heavy-dependencies.md) Files:
In Bun TypeScript source files, use `await Bun.file(path).json()` to read JSON files instead of `JSON.parse(await Bun.file(path).text())` or `JSON.parse(fs.readFileSync(...))`.📄 CodeRabbit inference engine (.archgate/adrs/ARCH-010-prefer-bun-built-in-json-parsing.md) Files:
Do not include the docs build in the CLI `validate` pipeline; docs build failures must not block CLI development or CI.📄 CodeRabbit inference engine (.archgate/adrs/GEN-001-documentation-site.md) Files:
Every TypeScript source file in `src/` and `tests/` must begin with `// SPDX-License-Identifier: Apache-2.0` followed by `// Copyright 2026 Archgate`.📄 CodeRabbit inference engine (.archgate/adrs/LEGAL-001-spdx-license-headers.md) Files:
🧠 Learnings (2)📓 Common learnings📚 Learning: 2026-07-25T22:03:14.216ZApplied to files:
🪛 Betterleaks (1.8.1)docs/public/llms-full.txt[high] 2393-2393: Detected a potential hardcoded password literal, which may expose account credentials. (generic-password) [high] 4517-4517: Detected a potential hardcoded password literal, which may expose account credentials. (generic-password) 🔇 Additional comments (4)
📝 WalkthroughWalkthroughThe CLI replaces GitHub device-flow signup with Archgate OAuth 2.0 Device Authorization Grant authentication. It stores and renews token sets, registers a host-specific Merge Risk: 🟡 Moderate · up to Published privacy policies describe outdated authentication and identity-data handling. Correct the English, Norwegian, and Brazilian Portuguese policies before release. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This comment was marked as resolved.
This comment was marked as resolved.
Code Coverage
Full HTML report available in workflow artifacts. Per-directory breakdown
|
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as outdated.
This comment was marked as outdated.
`credential erase` cleared the whole token set. Git erases whenever the credentials it was handed are rejected, so a single 401 — an access token that slipped past the renewal skew, or a transient error from the plugins host — destroyed the refresh token too and cost the user a full device-flow login for a recoverable failure. Erase now expires the access token and keeps the refresh token, so the next lookup renews. `renew()` also ignored whether the rotated pair was persisted. The exchange invalidates the old refresh token, so a failed write left the stored one dead with nothing to replace it: the current request still succeeded and every later one failed with no explanation. The failure is now reported, on stderr so the credential protocol on stdout stays intact. Both reported by Cursor Bugbot. The credential-store suite passed 500 lines with the new cases, so the renewal ones move to their own file. Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
…vice-flow adapter The CLI now reaches the platform's sign-in service only through the PlatformAuth contract in platform-auth.ts; oauth-device-flow.ts is one implementation of it, configured with endpoints rather than knowing whose they are. No provider is named anywhere in the code. Behaviour-preserving tidy-ups on the way: one form-POST helper for the three token requests, one runner for git credential approve/reject, one launcher loop shared by the browser and clipboard helpers, and one sign-in tail shared by login and login refresh. Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
…idation - Token requests send redirect: "error" so a 307/308 cannot replay a device code or refresh token to another host. - git credential fill ignores stderr instead of leaving an unread pipe. - invalidateAccessToken reports whether the lapsed token set was stored. - Docs describe credential storage as depending on the configured git credential helper, chain the manual VS Code install on curl succeeding, and list archgate credential in the CLI index and sidebar. Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
The auth contract, credential store, helper config and credential command import PLUGINS_HOST from plugin-install.ts, which also derives its API and marketplace URLs from it. Sign-in no longer defines a host that belongs to the plugins service. Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
…e without git - credentialInput throws a UserError for a host, username or password holding a line break or NUL, so an ID-token claim cannot forge a second host= line. - git() in git-credential-config returns 1 when git cannot be started, so login warns and logout hints instead of failing with an internal error. - The device-code body is read through jsonBody, keeping a proxy's HTML page a user-facing error. - LoginFlowResult.githubUser is accountName; the value is whatever the platform reports. - The helper-config test proves the reset entry lands after a system-scope helper, not only that a global entry is replaced. - The privacy policy states what the CLI itself reads from the sign-in result. Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
While archgate is the helper for the plugins host, the lookup for that host reaches archgate itself rather than the OS store, so a legacy token filed there was never rejected and resurfaced after logout. Logout and refresh now remove the helper entry first; logout still clears when that removal fails. Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
The first access token is minted by the device-code exchange, which sent no resource indicator; only refreshed tokens carried the plugins audience. The exchange now repeats the resource (RFC 8707 §2.2). Test suites clean their temp directories through safeRmSync instead of a blanket catch. Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
Git started by an editor or a GUI client rarely inherits the shell PATH that holds archgate, and the reset entry leaves no other helper for the plugins host, so those clones got no credentials. The helper entry now names this executable by absolute path, quoted for the POSIX shell git runs it through, with backslashes turned into forward slashes for Git for Windows. Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
Renewal now tells three outcomes apart: a refused grant is a SessionExpiredError, which the credential store treats as signed out; an unreachable service or a non-grant failure is a plain UserError that propagates with its cause, so the user is neither told to sign in again nor shown an internal error. A repeat login with a stored platform session re-registers the git credential helper in case the first write failed. Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
…ithout a shell - saveTokenSet reads back the record for the account it wrote and accepts it only when the blob matches; a helper answering an older or another user's record no longer counts as persisted. - clearCredentials reports whether every record was removed; logout fails with a hint instead of reporting success over a leftover token. - A refused platform session ends the credential lookup; the legacy store is consulted only while no platform session is stored. - TLS failures during sign-in go through handleCommandError as a UserError. - Windows and WSL open URLs through rundll32 rather than cmd or PowerShell, which parse ? and & out of the verification URL. - Suites created by this change restore spies with mock.restore(). - Docs: storage wording depends on the configured helper everywhere, headless wording names native Linux, and the legacy-token behaviour is stated as it is. Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
…failures - requestDeviceCode reports an unreachable service as a UserError with its cause; pollForTokens retries after a transport failure until the code expires instead of aborting the sign-in. - clearCredentials counts a fill timeout as a host it could not clear, and login refresh stops on a failed clear instead of signing in over it. - The credential helper skips the git install check at startup: git started it, stdout is the protocol channel, and an installer must not run there. Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
The record is stored for the account "archgate" with the display name inside the JSON payload, validated by SessionSchema. Signing in as another user replaces the record instead of leaving the old one beside it, every read selects this record rather than whichever the helper answers first, and logout removes the record that is actually in use. With a constant account and a JSON payload nothing can carry a protocol line break, so the explicit guard is gone. Docs use sign-in wording for the beta notes and describe refresh the same way in every locale; suites restore spies with mock.restore(). Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
An empty username, name or email claim was accepted as the account name; the stored session requires a non-empty one, so the record was written and then dropped on the next read. Empty claims are now skipped like absent ones. Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
…late-landing winner - As git's credential helper the CLI skips telemetry and Sentry startup, the update notice and the exit flushes, so git is not held on the network; the answer ends with the protocol's blank-line terminator. - A renewal refused because a sibling process rotated the token re-reads the store a few times before giving up, since the winner writes its result only after its own exchange. Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
…ered While the helper still answers for the plugins host, clearing cannot see a legacy token behind it, so a failed unregister now halts refresh before anything is touched. Logout and refresh share the recovery hint. Also type the session-record test helpers with the schema-derived TokenSet, and say sign in rather than sign up on the installation page. Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com>
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
|
🧠 Learnings used✅ Action performedReview finished.
|
6b5aae7 to
39b00e4
Compare
# archgate ## [0.56.0](v0.55.0...v0.56.0) (2026-09-07) ### ⚠ BREAKING CHANGES * **auth:** `archgate login` authenticates against the Archgate platform via the OAuth device flow instead of GitHub's, so every user signs in again to obtain a platform session. - Signup no longer happens in the CLI. The email, editor and use-case prompts are gone; registration is whatever the Archgate platform's sign-in offers. - Credentials are stored as an access/refresh token set under `auth.archgate.dev`, not a single token under `plugins.archgate.dev`. - `archgate login` writes a `credential.https://plugins.archgate.dev.helper` entry to the user's global git config, and `archgate login logout` removes it. - `archgate credential` is a new command, invoked by git rather than by users. Tokens issued before this change keep working: they remain under `plugins.archgate.dev` and are still returned, so existing sessions are not invalidated until the user signs in again. --------- ### Features * **auth:** log in to the Archgate platform and serve git credentials ([#602](#602)) ([ec154b1](ec154b1)) ### Bug Fixes * **plugin-install:** keep Copilot CLI output out of error logs ([#598](#598)) ([2155ed7](2155ed7)), closes [#595](#595) --- This PR was generated with [simple-release](https://github.com/TrigenSoftware/simple-release). <details> <summary>📄 Cheatsheet</summary> <br> You can configure the bot's behavior through a pull request comment using the `!simple-release/set-options` command. ### Command Format ````md !simple-release/set-options ```json { "bump": {}, "publish": {} } ``` ```` ### Useful Parameters #### Bump | Parameter | Type | Description | |-----------|------|-------------| | `version` | `string` | Force set specific version | | `as` | `'major' \| 'minor' \| 'patch' \| 'prerelease'` | Release type | | `prerelease` | `string` | Pre-release identifier (e.g., "alpha", "beta") | | `firstRelease` | `boolean` | Whether this is the first release | | `skip` | `boolean` | Skip version bump | | `byProject` | `Record<string, object>` | Per-project bump options for monorepos | #### Publish | Parameter | Type | Description | |-----------|------|-------------| | `skip` | `boolean` | Skip publishing | | `access` | `'public' \| 'restricted'` | Package access level | | `tag` | `string` | Tag for npm publication | ### Usage Examples #### Force specific version ````md !simple-release/set-options ```json { "bump": { "version": "2.0.0" } } ``` ```` #### Force major bump ````md !simple-release/set-options ```json { "bump": { "as": "major" } } ``` ```` #### Create alpha pre-release ````md !simple-release/set-options ```json { "bump": { "prerelease": "alpha" } } ``` ```` #### Publish with specific access and tag ````md !simple-release/set-options ```json { "bump": { "prerelease": "beta" }, "publish": { "access": "public", "tag": "beta" } } ``` ```` ### Custom Changelog Preamble You can add custom markdown to the top of the changelog (right after the version header) using the `!simple-release/set-preamble` command. The markdown after the command line becomes the preamble. ```md !simple-release/set-preamble ## What's new? - The website was completely redesigned - The new API gives you awesome possibilities ``` In a monorepo, pass the full package name after the command to target a single package's changelog. Wrap the name in backticks so GitHub keeps it as text instead of a mention: ```md !simple-release/set-preamble `@your-org/core` ## Core changes - New plugin system ``` Use one comment per package, plus one without a name for the whole release. ### Access Restrictions The commands can only be used by users with permissions: - repository owner - organization member - collaborator ### Notes - The last comment with `!simple-release/set-options` command takes priority - The last `!simple-release/set-preamble` comment per package takes priority - JSON must be valid, otherwise the `set-options` command will be ignored - Parameters apply only to the current release execution - The commands can be updated by editing the comment or adding a new one </details> <!-- Please do not edit this comment. simple-release-pull-request: true simple-release-branch-from: release simple-release-branch-to: main --> Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
## Why #602 made `archgate login` write a `credential.https://plugins.archgate.dev.helper` entry so `git clone` of a plugin repository gets a fresh access token. `archgate doctor` only reported a `logged_in` boolean, so when a plugin clone prompted for a password there was nothing to tell the user which part of that chain was broken. ## What `doctor` now reports two more things under **Archgate**: - **Session** — `platform`, `legacy` (a token issued before platform sign-in, which the helper cannot serve), or `none`. - **Git helper** — the state of the helper entry, with the command that repairs it: | Label | Meaning | Hint | |---|---|---| | `OK` | entry names the running binary, reset entry precedes it, platform session stored | — | | `MISSING` | platform session stored, no entry | `archgate login` | | `not registered` | no entry, legacy or no session | `archgate login refresh` for legacy | | `STALE` | entry names another archgate binary (upgrade, reinstall elsewhere) | `archgate login` | | `SHARED` | reset entry missing or after archgate, so an inherited helper may answer first | `archgate login` | | `NO SESSION` | entry present, nothing stored for it to serve | `archgate login` | `--json` gains `archgate.session` and `archgate.credential_helper: { registered, current, resets_inherited }`. The read side (`inspectGitCredentialHelper`) lives beside `register`/`unregister` in `git-credential-config.ts` and reads every config scope in the order git consults them, since a system entry ahead of archgate answers first regardless of the global file. A git that cannot start reads as nothing registered. ## Deliberately not included A live `git credential fill` probe. From `doctor` it would spawn git → archgate → `resolveAccessToken`, which can refresh over the network, and it would run the helper recursively inside the command diagnosing it. The static read plus session kind covers every misconfiguration the helper code can produce; a live probe is `git clone` itself. ## Verified - `bun run validate` passes. - Fire-tested against isolated `GIT_CONFIG_GLOBAL` files: clean, stale path, missing reset, and `--json` shape, under a pseudo-TTY for the console rendering. - Docs updated in en, nb, pt-br; `llms-full.txt` regenerates from those. --------- Signed-off-by: Rhuan Barreto <rhuan.barreto@gmail.com> Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
# archgate ## [0.57.0](v0.56.0...v0.57.0) (2026-09-07) ### Features * **doctor:** diagnose the git credential helper entry ([#603](#603)) ([91d8a1d](91d8a1d)), references [#602](#602) ### Bug Fixes * **credential:** read git's request through the Node stdin stream ([#604](#604)) ([add40a5](add40a5)) --- This PR was generated with [simple-release](https://github.com/TrigenSoftware/simple-release). <details> <summary>📄 Cheatsheet</summary> <br> You can configure the bot's behavior through a pull request comment using the `!simple-release/set-options` command. ### Command Format ````md !simple-release/set-options ```json { "bump": {}, "publish": {} } ``` ```` ### Useful Parameters #### Bump | Parameter | Type | Description | |-----------|------|-------------| | `version` | `string` | Force set specific version | | `as` | `'major' \| 'minor' \| 'patch' \| 'prerelease'` | Release type | | `prerelease` | `string` | Pre-release identifier (e.g., "alpha", "beta") | | `firstRelease` | `boolean` | Whether this is the first release | | `skip` | `boolean` | Skip version bump | | `byProject` | `Record<string, object>` | Per-project bump options for monorepos | #### Publish | Parameter | Type | Description | |-----------|------|-------------| | `skip` | `boolean` | Skip publishing | | `access` | `'public' \| 'restricted'` | Package access level | | `tag` | `string` | Tag for npm publication | ### Usage Examples #### Force specific version ````md !simple-release/set-options ```json { "bump": { "version": "2.0.0" } } ``` ```` #### Force major bump ````md !simple-release/set-options ```json { "bump": { "as": "major" } } ``` ```` #### Create alpha pre-release ````md !simple-release/set-options ```json { "bump": { "prerelease": "alpha" } } ``` ```` #### Publish with specific access and tag ````md !simple-release/set-options ```json { "bump": { "prerelease": "beta" }, "publish": { "access": "public", "tag": "beta" } } ``` ```` ### Custom Changelog Preamble You can add custom markdown to the top of the changelog (right after the version header) using the `!simple-release/set-preamble` command. The markdown after the command line becomes the preamble. ```md !simple-release/set-preamble ## What's new? - The website was completely redesigned - The new API gives you awesome possibilities ``` In a monorepo, pass the full package name after the command to target a single package's changelog. Wrap the name in backticks so GitHub keeps it as text instead of a mention: ```md !simple-release/set-preamble `@your-org/core` ## Core changes - New plugin system ``` Use one comment per package, plus one without a name for the whole release. ### Access Restrictions The commands can only be used by users with permissions: - repository owner - organization member - collaborator ### Notes - The last comment with `!simple-release/set-options` command takes priority - The last `!simple-release/set-preamble` comment per package takes priority - JSON must be valid, otherwise the `set-options` command will be ignored - Parameters apply only to the current release execution - The commands can be updated by editing the comment or adding a new one </details> <!-- Please do not edit this comment. simple-release-pull-request: true simple-release-branch-from: release simple-release-branch-to: main --> Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
archgate loginnow runs an OAuth 2.0 Device Authorization Grant (RFC 8628) against the Archgate platform instead of GitHub, and stores the resulting access and refresh tokens rather than a single long-lived plugin token.Why a credential helper
Access tokens are short-lived, and the old storage model cannot carry that. Plugin repositories are cloned over HTTPS, and git reads the stored credential itself — the CLI is not in that request path. A token written once into the credential manager would stop working within the hour.
archgate credentialcloses the gap as a git credential helper: git asks it on each request, and it answers with a cached access token, renewing from the refresh token only once the cached one has lapsed. This is the same shape asgh auth git-credentialfor github.com, including the config idiom:The empty entry resets helpers inherited from a wider config scope so archgate is the only one consulted for that host alone; every other remote keeps whatever helper it already had.
archgate login logoutremoves both entries.Two details worth reviewing closely
Tokens are filed under
auth.archgate.dev, not the plugins host. The store reaches the keychain throughgit credential, so keeping tokens under the host archgate is the helper for would make every read re-enter this process. Storing them elsewhere is what avoids the recursion.Bun.spawnsnapshots the environment at startup. A laterBun.envassignment does not reach the child, sogit()passesenvexplicitly. Without it the helper tests silently wrote to the developer's real~/.gitconfigwhile appearing to pass — the config assertions were reading back the same polluted file. I hit exactly that and had to clean my own global config.Migration
Tokens issued before this change stay filed under the plugins host and are still returned unchanged, so existing sessions keep working until the user signs in again.
Removed
The GitHub device flow, the token claim call and the signup prompts are gone along with their tests — identity and registration now belong to the Archgate platform.
SIGNUP_EDITORSwent with them.Not addressed here
Any account that can sign in to the Archgate platform now obtains plugin access. The signup step previously gated that. If the beta allowlist is still wanted, it needs an explicit check on the server rather than in the CLI — that is a backend change, not a CLI one, so it is deliberately out of scope for this PR. Flagging it because it is a policy change, not just a refactor.
Validation
bun run validatepasses end to end: lint, typecheck, format:check, 2600 tests,archgate check43/43, knip, build check.New tests cover the device flow (polling,
slow_down, denial, expiry, refresh rotation, expiry skew), the credential protocol parser and formatter — including that a value containing a newline is dropped rather than allowed to forge protocol lines — the helper's silence for hosts that are not ours, and the git config registration including the reset entry and idempotency across repeated logins.BREAKING CHANGE:
archgate loginauthenticates against the Archgate platformvia the OAuth device flow instead of GitHub's, so every user signs in again
to obtain a platform session.
are gone; registration is whatever the Archgate platform's sign-in offers.
auth.archgate.dev, not a single token underplugins.archgate.dev.archgate loginwrites acredential.https://plugins.archgate.dev.helperentry to the user's global git config, and
archgate login logoutremoves it.archgate credentialis a new command, invoked by git rather than by users.Tokens issued before this change keep working: they remain under
plugins.archgate.devand are still returned, so existing sessions are notinvalidated until the user signs in again.