@vibe-commit/capture 0.4.5 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +57 -1
  2. package/dist/atomic_write.d.ts +14 -0
  3. package/dist/atomic_write.js +33 -0
  4. package/dist/atomic_write.js.map +1 -0
  5. package/dist/commands/auth.d.ts +26 -2
  6. package/dist/commands/auth.js +68 -13
  7. package/dist/commands/auth.js.map +1 -1
  8. package/dist/commands/browser_credential.d.ts +39 -12
  9. package/dist/commands/browser_credential.js +84 -11
  10. package/dist/commands/browser_credential.js.map +1 -1
  11. package/dist/commands/connect.d.ts +6 -2
  12. package/dist/commands/connect.js +140 -42
  13. package/dist/commands/connect.js.map +1 -1
  14. package/dist/commands/credential_problem.d.ts +43 -0
  15. package/dist/commands/credential_problem.js +81 -0
  16. package/dist/commands/credential_problem.js.map +1 -0
  17. package/dist/commands/device_credential.d.ts +47 -0
  18. package/dist/commands/device_credential.js +275 -0
  19. package/dist/commands/device_credential.js.map +1 -0
  20. package/dist/commands/finish_mint.d.ts +73 -0
  21. package/dist/commands/finish_mint.js +140 -0
  22. package/dist/commands/finish_mint.js.map +1 -0
  23. package/dist/commands/probe.d.ts +14 -0
  24. package/dist/commands/probe.js +29 -0
  25. package/dist/commands/probe.js.map +1 -0
  26. package/dist/commands/status.js +36 -52
  27. package/dist/commands/status.js.map +1 -1
  28. package/dist/copy/index.d.ts +1 -1
  29. package/dist/copy/index.js +1 -1
  30. package/dist/copy/index.js.map +1 -1
  31. package/dist/copy/strings.d.ts +183 -4
  32. package/dist/copy/strings.js +192 -6
  33. package/dist/copy/strings.js.map +1 -1
  34. package/dist/credential.d.ts +25 -0
  35. package/dist/credential.js +41 -3
  36. package/dist/credential.js.map +1 -1
  37. package/dist/credential_meta.d.ts +66 -0
  38. package/dist/credential_meta.js +164 -0
  39. package/dist/credential_meta.js.map +1 -0
  40. package/dist/device_mode.d.ts +18 -0
  41. package/dist/device_mode.js +28 -0
  42. package/dist/device_mode.js.map +1 -0
  43. package/dist/hooks/entry.d.ts +5 -0
  44. package/dist/hooks/entry.js +40 -5
  45. package/dist/hooks/entry.js.map +1 -1
  46. package/dist/index.js +33 -2
  47. package/dist/index.js.map +1 -1
  48. package/dist/install.d.ts +37 -0
  49. package/dist/install.js +29 -2
  50. package/dist/install.js.map +1 -1
  51. package/dist/oauth/device.d.ts +129 -0
  52. package/dist/oauth/device.js +194 -0
  53. package/dist/oauth/device.js.map +1 -0
  54. package/dist/oauth/discovery.d.ts +5 -0
  55. package/dist/oauth/discovery.js +6 -0
  56. package/dist/oauth/discovery.js.map +1 -1
  57. package/dist/oauth/mint.d.ts +18 -5
  58. package/dist/oauth/mint.js +18 -5
  59. package/dist/oauth/mint.js.map +1 -1
  60. package/dist/oauth/retire.d.ts +64 -0
  61. package/dist/oauth/retire.js +106 -0
  62. package/dist/oauth/retire.js.map +1 -0
  63. package/dist/oauth/signin.d.ts +12 -0
  64. package/dist/oauth/signin.js +5 -1
  65. package/dist/oauth/signin.js.map +1 -1
  66. package/dist/oauth/token.d.ts +1 -0
  67. package/dist/oauth/token.js +5 -0
  68. package/dist/oauth/token.js.map +1 -1
  69. package/dist/oauth/whoami.d.ts +55 -0
  70. package/dist/oauth/whoami.js +77 -0
  71. package/dist/oauth/whoami.js.map +1 -0
  72. package/dist/paths.d.ts +19 -0
  73. package/dist/paths.js +25 -0
  74. package/dist/paths.js.map +1 -1
  75. package/dist/post.d.ts +39 -4
  76. package/dist/post.js +103 -16
  77. package/dist/post.js.map +1 -1
  78. package/dist/state.d.ts +11 -0
  79. package/dist/state.js +33 -0
  80. package/dist/state.js.map +1 -1
  81. package/dist/system_message.d.ts +21 -2
  82. package/dist/system_message.js +37 -7
  83. package/dist/system_message.js.map +1 -1
  84. package/dist/term.d.ts +6 -0
  85. package/dist/term.js +15 -0
  86. package/dist/term.js.map +1 -1
  87. package/dist/update_nudge.d.ts +31 -0
  88. package/dist/update_nudge.js +127 -0
  89. package/dist/update_nudge.js.map +1 -0
  90. package/dist/version.d.ts +1 -1
  91. package/dist/version.js +1 -1
  92. package/package.json +3 -3
package/README.md CHANGED
@@ -25,13 +25,33 @@ the approved direction points at `Vibe-Commit/claude-plugin`, which vendors the
25
25
 
26
26
  | Command | What it does |
27
27
  |---|---|
28
- | `vibecommit connect` | Connect this repo and capture the current session. |
28
+ | `vibecommit connect` | Connect this repo and capture the current session. On a machine with no credential it signs you in through the browser first. |
29
+ | `vibecommit auth` | Replace this machine's credential: sign in through the browser, or `--paste` one you made in Settings. Run it again whenever `status` or a hook says the credential is no longer accepted. Inside a git repo it then goes on to `connect` that repo; outside one it only saves the credential. |
29
30
  | `vibecommit status` | Show whether capture is on for this repo and when it last succeeded. |
30
31
  | `vibecommit off` | Stop capturing for this repo. |
31
32
  | `vibecommit why <file>:<line>` | Show the conversation turns recorded against the commit that last changed this line. |
32
33
  | `vibecommit report --since <when>` | Summarise capture coverage over a time window. |
33
34
  | `vibecommit finalize --session <id>` \| `--latest` | Close a finished session's last turn so commits made in it can be recorded. |
34
35
 
36
+ ### Keeping a machine connected
37
+
38
+ `vibecommit connect` asks the server whether this machine's credential is still accepted **before** it sends
39
+ anything. If it is not, `connect` says so, prints the command that fixes it last, and exits `3`; it does not print
40
+ "Connected". Turns held while the credential was rejected upload once you reconnect. If the server cannot be
41
+ reached, `connect` finishes as it always did and adds one line saying it could not confirm the credential.
42
+
43
+ The fix is `vibecommit auth` (for the Claude Code plugin, which puts nothing on your `PATH`, the line names
44
+ `node <path> auth`). Running it again on a machine that already has a credential **retires the credential it replaces**,
45
+ so Settings shows one row per machine, but only when both are in the same workspace. If the browser lands you in a
46
+ different workspace, `auth` shows the account and workspace and asks first, defaulting to no; answering no changes
47
+ nothing on this machine. A credential set through `VIBECOMMIT_TOKEN` is never replaced or retired by `auth`.
48
+
49
+ `vibecommit status` shows when a credential is being rejected (`status --json` carries it as `credential_stopped`,
50
+ which is `null` when nothing is stopped).
51
+
52
+ After a successful `status`, `connect` or `auth`, on a terminal, a final line tells you when a newer version is on
53
+ npm. It never appears in a hook, under `--json`, or after an error. Set `VIBECOMMIT_NO_UPDATE_CHECK=1` to turn it off.
54
+
35
55
  ### One-shot runs: `vibecommit finalize`
36
56
 
37
57
  A turn is recorded only once a following prompt opens the next one, so the **last turn of a
@@ -114,6 +134,42 @@ accepts a third `match_kind`,
114
134
  witnessing it directly — rendered with its own basis sentence, never folded into the unqualified `exact`
115
135
  copy.
116
136
 
137
+ 0.5.0 makes connecting a machine something you can check and undo. `vibecommit connect` and `vibecommit auth` ask
138
+ the server who a stored credential belongs to before sending anything: a credential the server no longer accepts
139
+ is named as the fault and nothing is sent, and an unreachable server keeps today's behaviour with one muted line.
140
+ Signing in again over a credential on this machine asks a question when the workspace would change — or when the
141
+ new credential cannot be confirmed while the old one could — showing the new workspace beside the one it
142
+ replaces; answering *no* revokes the credential it just created, and says so if it could not. Signing in again
143
+ as the same workspace saves without asking. Saving a replacement also retires the credential it replaces, but
144
+ only for a credential stored in a file, only within the same workspace, and best effort: what was and was not
145
+ retired is printed. `vibecommit status` (and `status --json`, as `credential_stopped`) say when the server no
146
+ longer accepts a machine's credential and capture has stopped sending for it.
147
+ `vibecommit connect --device` (also `auth --device`) signs a machine in without a browser on it. It is chosen
148
+ automatically over SSH, on Linux with no display, or when the browser cannot be opened. It prints a code and
149
+ `https://www.vibecommit.ai/device`; you approve there on any device that has a browser; the machine then shows
150
+ the account and workspace that approved and asks `[y/N]`, and nothing is saved until you answer `y`. Approving
151
+ with a code needs the account setting *Allow approving machines with a code*, which is per account and off by
152
+ default; with it off, the approval page says so and the code simply stays valid for its five minutes. The server
153
+ sets a credential's end date and moves it forward while the machine keeps capturing; a credential idle for 90
154
+ days ends. The hook records the end date in the credential's metadata file (never in `credentials.json`);
155
+ within 14 days of it the hook says so once a day, naming the command that renews it, and `vibecommit status` turns
156
+ to a warning. On a terminal, a successful `connect` also mentions on its last line when a newer version exists.
157
+ It needs a server that has the matching routes (the workspace question and the device sign-in), which the
158
+ production server has.
159
+
160
+ 0.6.0 makes `auth` and `connect` one motion, and changes four contracts you may be scripting around.
161
+ `vibecommit auth` inside a git repository now continues into `connect` after it saves the credential, so it may
162
+ ask `connect`'s consent question; outside a repository, with `--stdin`, or with no terminal, it only saves the
163
+ credential, exactly as before, and a refused replacement (`declined`) still exits 1 without connecting. The chained
164
+ `connect` never opens a second sign-in. `vibecommit connect` in a repository where Claude Code has not run yet now
165
+ installs the git and agent hooks and exits 0 (it used to exit 1 and install neither); its "no Claude Code session"
166
+ warning is on stdout, and a `vibecommit` command on PATH that is not this one still exits 1. An organisation that
167
+ has not approved capture yet now gets its hooks installed too: the "capture is armed" screen was previously
168
+ printed without them. The ending reports hook setup first, then prints "Connected." and, when the server's reply
169
+ names the recorded session, a link to that session's page (`/app/conversations/<id>`), falling back to the
170
+ captures list; the PATH check and the unconfirmed-credential note follow it. Only `connect` reads that part of the
171
+ server's reply; the hooks never read a successful response body.
172
+
117
173
  ## Status
118
174
 
119
175
  **Implemented**, not a scaffold. All six commands above have real bodies — OAuth sign-in
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Write a file so that no reader ever sees half of it — temp file in the SAME
3
+ * directory, then `rename`.
4
+ *
5
+ * `rename(2)` within one filesystem replaces the destination in one step, so a
6
+ * hook that reads `credentials.json` while `auth` is saving gets the old file or
7
+ * the new one and never a torn one (`FC5`). The temp file is created `wx` at the
8
+ * final mode, so the bytes are never readable by group or other even briefly,
9
+ * and the `chmod` after is the same belt `saveCredential` has always worn
10
+ * (`writeFileSync`'s `mode` is masked by the umask).
11
+ *
12
+ * A failure removes the temp file and rethrows: the destination is untouched.
13
+ */
14
+ export declare function writeFileAtomic(path: string, data: string, mode: number): void;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Write a file so that no reader ever sees half of it — temp file in the SAME
3
+ * directory, then `rename`.
4
+ *
5
+ * `rename(2)` within one filesystem replaces the destination in one step, so a
6
+ * hook that reads `credentials.json` while `auth` is saving gets the old file or
7
+ * the new one and never a torn one (`FC5`). The temp file is created `wx` at the
8
+ * final mode, so the bytes are never readable by group or other even briefly,
9
+ * and the `chmod` after is the same belt `saveCredential` has always worn
10
+ * (`writeFileSync`'s `mode` is masked by the umask).
11
+ *
12
+ * A failure removes the temp file and rethrows: the destination is untouched.
13
+ */
14
+ import { randomBytes } from "node:crypto";
15
+ import { chmodSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
16
+ export function writeFileAtomic(path, data, mode) {
17
+ const tmp = `${path}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
18
+ try {
19
+ writeFileSync(tmp, data, { mode, flag: "wx" });
20
+ chmodSync(tmp, mode);
21
+ renameSync(tmp, path);
22
+ }
23
+ catch (error) {
24
+ try {
25
+ unlinkSync(tmp);
26
+ }
27
+ catch {
28
+ /* nothing to clean up */
29
+ }
30
+ throw error;
31
+ }
32
+ }
33
+ //# sourceMappingURL=atomic_write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomic_write.js","sourceRoot":"","sources":["../src/atomic_write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE3E,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,IAAY,EAAE,IAAY;IACtE,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3E,IAAI,CAAC;QACH,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACrB,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC;YACH,UAAU,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;QAC3B,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -52,11 +52,29 @@
52
52
  * ⚠ So there is no path on which `CR-226` makes the pre-existing flow worse:
53
53
  * every failure lands on the prompt that was the whole verb before it.
54
54
  *
55
+ * ## ⭐ Inside a git work tree, a save CONTINUES INTO `connect` (0.6.0, `CR-236`)
56
+ *
57
+ * `/install` and this verb's own ending used to make a new user run two commands back to back — `auth`,
58
+ * then `connect` — for what is one intent. So on a TERMINAL, inside any git work tree
59
+ * (`resolveProjectKeys(cwd) !== null`, the precondition `connect` checks for itself), a SAVED credential
60
+ * goes straight on into `connect`, which asks its own consent question first, and `auth` returns
61
+ * `connect`'s exit code. The gate (`shouldConnect`) is checked on BOTH save paths — the browser's `saved`
62
+ * result and the TTY paste.
63
+ *
64
+ * ⛔ Never on `--stdin` or a non-TTY: CI must keep exit 0 and never meet a consent refusal. Never on
65
+ * `declined`, an empty paste or a wrong-class paste: nothing was saved. Outside a repo the output and
66
+ * the exit are byte-identical to before — that is the escape hatch for a renewal that should not touch
67
+ * the repo you are standing in.
68
+ *
69
+ * ⛔ **NEVER A SECOND SIGN-IN.** `src/index.ts` hands the chained `connect` NO `browser`, so an `absent`
70
+ * credential falls to its warning and never to a mint; this verb just saved one, so it is not absent.
71
+ * `test/auth-connect-chain.test.ts` brace-matches the inner call to keep it so.
72
+ *
55
73
  * @provenance vibecommit-mcp src/transport/server.ts — POST /oauth/ingest-credential is the mint route, verified
56
74
  * @provenance vibecommit-web app/api/ingest-credentials/route.ts — the dashboard producer the paste path still serves, verified
57
75
  */
58
76
  import type { CommandContext } from "./context.js";
59
- import type { BrowserCredential, Retry } from "./browser_credential.js";
77
+ import type { BrowserCredential, BrowserOptions, Retry } from "./browser_credential.js";
60
78
  export interface AuthDeps {
61
79
  /**
62
80
  * Read the secret from a terminal WITHOUT ECHOING IT. Injected for the same
@@ -76,6 +94,12 @@ export interface AuthDeps {
76
94
  * so a test that forgot to stub it cannot reach a server or open a browser.
77
95
  * `src/index.ts` passes the real one.
78
96
  */
79
- readonly browser?: (ctx: CommandContext, retry: Retry) => Promise<BrowserCredential>;
97
+ readonly browser?: (ctx: CommandContext, retry: Retry, options?: BrowserOptions) => Promise<BrowserCredential>;
98
+ /**
99
+ * The chain into `connect` — `CR-236`. Injected like `browser`, for the same reason: left out, this verb
100
+ * behaves exactly as it did before the chain, so a suite that forgot to stub it cannot reach a network.
101
+ * `src/index.ts` passes one that carries NO `browser` (never a second sign-in).
102
+ */
103
+ readonly connect?: (ctx: CommandContext) => Promise<number>;
80
104
  }
81
105
  export declare function auth(ctx: CommandContext, argv: readonly string[], deps?: AuthDeps): Promise<number>;
@@ -52,14 +52,34 @@
52
52
  * ⚠ So there is no path on which `CR-226` makes the pre-existing flow worse:
53
53
  * every failure lands on the prompt that was the whole verb before it.
54
54
  *
55
+ * ## ⭐ Inside a git work tree, a save CONTINUES INTO `connect` (0.6.0, `CR-236`)
56
+ *
57
+ * `/install` and this verb's own ending used to make a new user run two commands back to back — `auth`,
58
+ * then `connect` — for what is one intent. So on a TERMINAL, inside any git work tree
59
+ * (`resolveProjectKeys(cwd) !== null`, the precondition `connect` checks for itself), a SAVED credential
60
+ * goes straight on into `connect`, which asks its own consent question first, and `auth` returns
61
+ * `connect`'s exit code. The gate (`shouldConnect`) is checked on BOTH save paths — the browser's `saved`
62
+ * result and the TTY paste.
63
+ *
64
+ * ⛔ Never on `--stdin` or a non-TTY: CI must keep exit 0 and never meet a consent refusal. Never on
65
+ * `declined`, an empty paste or a wrong-class paste: nothing was saved. Outside a repo the output and
66
+ * the exit are byte-identical to before — that is the escape hatch for a renewal that should not touch
67
+ * the repo you are standing in.
68
+ *
69
+ * ⛔ **NEVER A SECOND SIGN-IN.** `src/index.ts` hands the chained `connect` NO `browser`, so an `absent`
70
+ * credential falls to its warning and never to a mint; this verb just saved one, so it is not absent.
71
+ * `test/auth-connect-chain.test.ts` brace-matches the inner call to keep it so.
72
+ *
55
73
  * @provenance vibecommit-mcp src/transport/server.ts — POST /oauth/ingest-credential is the mint route, verified
56
74
  * @provenance vibecommit-web app/api/ingest-credentials/route.ts — the dashboard producer the paste path still serves, verified
57
75
  */
58
- import { AUTH, HELP, URLS } from "../copy/index.js";
76
+ import { AUTH, COMMANDS, DEVICE, HELP, URLS } from "../copy/index.js";
77
+ import { authCommandFor } from "../install.js";
59
78
  import { writeLines } from "./context.js";
60
79
  import { EXIT } from "../exit.js";
61
80
  import { INGEST_TOKEN_PREFIX, IngestCredential, saveCredential } from "../credential.js";
62
81
  import { credentialsPath } from "../paths.js";
82
+ import { resolveProjectKeys } from "../project.js";
63
83
  import { paint, renderErrorBlock, tildePath, wrap } from "../term.js";
64
84
  /**
65
85
  * `--stdin` forces the pipe even on a terminal — the CI shape, where a job may
@@ -68,6 +88,8 @@ import { paint, renderErrorBlock, tildePath, wrap } from "../term.js";
68
88
  const STDIN_FLAG = "--stdin";
69
89
  /** `CR-226`. Skip the browser and go straight to the prompt. */
70
90
  const PASTE_FLAG = "--paste";
91
+ /** `CR-234d`. Sign in by CODE, approved on another device — TTY only. */
92
+ const DEVICE_FLAG = "--device";
71
93
  export async function auth(ctx, argv, deps = {}) {
72
94
  // ⛔ THE ARGV REFUSAL COMES FIRST, before stdin is read, resumed or opened.
73
95
  // Anything else would mean the secret in `argv` had already been accepted by
@@ -92,11 +114,33 @@ export async function auth(ctx, argv, deps = {}) {
92
114
  return EXIT.ok;
93
115
  }
94
116
  const piped = argv.includes(STDIN_FLAG) || !ctx.stdinIsTty;
117
+ // `CR-234d`: `--device` is TTY only (the approval is a person's) and is the opposite of `--paste`.
118
+ if (argv.includes(DEVICE_FLAG) && (piped || argv.includes(PASTE_FLAG))) {
119
+ writeLines(ctx.stderr, renderErrorBlock(piped
120
+ ? {
121
+ kind: "bad",
122
+ what: DEVICE.needsTerminalWhat,
123
+ why: [DEVICE.needsTerminalWhy],
124
+ fixLabel: DEVICE.needsTerminalFix,
125
+ fixes: [DEVICE.needsTerminalCommand(authCommandFor(ctx.env, ctx.selfPath))],
126
+ }
127
+ : {
128
+ kind: "bad",
129
+ what: DEVICE.conflictWhat,
130
+ why: [DEVICE.conflictWhy],
131
+ fixLabel: DEVICE.conflictFix,
132
+ fixes: [COMMANDS.auth, `${COMMANDS.auth} ${PASTE_FLAG}`],
133
+ }, ctx.colour));
134
+ return EXIT.usage;
135
+ }
95
136
  // ── `CR-226`: the browser, first, on a terminal only. ──────────────────────
96
137
  if (!piped && !argv.includes(PASTE_FLAG) && deps.browser !== undefined) {
97
- const minted = await deps.browser(ctx, "auth");
138
+ const minted = await deps.browser(ctx, "auth", { device: argv.includes(DEVICE_FLAG) });
98
139
  if (minted.kind === "saved")
99
- return saved(ctx);
140
+ return await saved(ctx, deps, piped, minted.notes);
141
+ // The user said NO at the replace confirmation: not a failure of the browser, so no paste prompt.
142
+ if (minted.kind === "declined")
143
+ return EXIT.failure;
100
144
  // The reason is already on stderr. The documented fallback is the paste
101
145
  // this verb has always had, with the page that mints one named first.
102
146
  writeLines(ctx.stdout, [
@@ -139,17 +183,28 @@ export async function auth(ctx, argv, deps = {}) {
139
183
  return EXIT.failure;
140
184
  }
141
185
  saveCredential(ctx.home, new IngestCredential(secret, "file"));
142
- return saved(ctx);
186
+ return await saved(ctx, deps, piped);
143
187
  }
144
- /** The one confirmation, whichever path wrote the file. */
145
- function saved(ctx) {
146
- writeLines(ctx.stdout, renderErrorBlock({
147
- kind: "ok",
148
- what: AUTH.savedWhat,
149
- why: [AUTH.savedWhy(tildePath(credentialsPath(ctx.home), ctx.home))],
150
- fixLabel: AUTH.nextLabel,
151
- fixes: [AUTH.nextCommand],
152
- }, ctx.colour));
188
+ /**
189
+ * The one confirmation, whichever path wrote the file — and the chain's single gate.
190
+ *
191
+ * `shouldConnect` is read here, AFTER a save and nowhere else, so `declined`, empty and wrong-class input
192
+ * (which return before this) can never chain. When it holds, the "Next, connect a repository" fix line is
193
+ * dropped — `connect`'s own output follows — and `connect`'s exit code is returned. When it does not, the
194
+ * block and the exit are exactly what they were.
195
+ */
196
+ async function saved(ctx, deps, piped, notes = []) {
197
+ const shouldConnect = !piped && deps.connect !== undefined && resolveProjectKeys(ctx.cwd) !== null;
198
+ writeLines(ctx.stdout, [
199
+ ...renderErrorBlock({
200
+ kind: "ok",
201
+ what: AUTH.savedWhat,
202
+ why: [AUTH.savedWhy(tildePath(credentialsPath(ctx.home), ctx.home)), ...notes],
203
+ ...(shouldConnect ? {} : { fixLabel: AUTH.nextLabel, fixes: [AUTH.nextCommand] }),
204
+ }, ctx.colour),
205
+ ]);
206
+ if (shouldConnect && deps.connect !== undefined)
207
+ return await deps.connect(ctx);
153
208
  return EXIT.ok;
154
209
  }
155
210
  //# sourceMappingURL=auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
@@ -27,8 +27,9 @@
27
27
  * nothing to use — `connect` gates on `absent`, and `auth` is the verb a user
28
28
  * types precisely to replace what is there.
29
29
  */
30
- import { type IngestCredential } from "../credential.js";
31
30
  import { type CommandContext } from "./context.js";
31
+ import { type BrowserCredential } from "./finish_mint.js";
32
+ export { finishMint, type BrowserCredential, type FinishMintInput, type Prior } from "./finish_mint.js";
32
33
  /**
33
34
  * The network and the browser, injectable. Defaults are the real ones; a test
34
35
  * supplies a `fetch` aimed at a stand-in server and an `openBrowser` that follows
@@ -39,6 +40,27 @@ export interface BrowserDeps {
39
40
  readonly openBrowser?: (url: string) => boolean;
40
41
  /** The machine's name, for the credential's label. */
41
42
  readonly hostname?: () => string;
43
+ /** How long the browser round trip may take. Tests only: the real default is `SIGNIN_DEADLINE_MS`. */
44
+ readonly deadlineMs?: number;
45
+ /** `process.platform`, for the headless check. Tests only. */
46
+ readonly platform?: NodeJS.Platform;
47
+ /** The device flow's wait between polls. Tests only: the real one is a timer. */
48
+ readonly sleep?: (ms: number) => Promise<void>;
49
+ /** The device flow's Ctrl+C. Tests only: the real one listens for SIGINT. */
50
+ readonly interrupt?: () => {
51
+ readonly promise: Promise<void>;
52
+ readonly dispose: () => void;
53
+ };
54
+ }
55
+ /**
56
+ * What the caller asked of the browser beat beyond the default (`CR-234d`).
57
+ *
58
+ * `device: true` is `--device`: sign in by CODE even where a browser would open. Absent, the beat still
59
+ * chooses the device flow by itself on an SSH session or a Linux box with no display (`headlessReason`),
60
+ * and falls back to it when the browser cannot be opened.
61
+ */
62
+ export interface BrowserOptions {
63
+ readonly device?: boolean;
42
64
  }
43
65
  /**
44
66
  * Which verb a failed step tells the user to run again.
@@ -60,7 +82,22 @@ export interface SignInBeatOptions extends BrowserDeps {
60
82
  * working one.
61
83
  */
62
84
  readonly replace?: boolean;
85
+ /**
86
+ * `G8a`. A session file that LOADS is not a session that WORKS: before saying "already signed in",
87
+ * ask the server to renew it. Only a refused refresh (`expired`) falls through to a fresh sign-in;
88
+ * a busy lock, an unreachable server or a malformed answer proves nothing, and says "already".
89
+ */
90
+ readonly verify?: boolean;
91
+ /** Ask the authorize page to bind this org (re-auth, plan item 2(a), brief A1). */
92
+ readonly orgId?: string;
93
+ /**
94
+ * `CR-234d`. If the browser cannot be opened, return `NO_BROWSER` instead of printing the URL and waiting
95
+ * for a callback nobody can make. Only `browserCredential` sets this, and only it handles the result.
96
+ */
97
+ readonly fallbackToDevice?: boolean;
63
98
  }
99
+ /** `signInBeat`'s sentinel for "no browser, go to the device flow". Never an exit code a verb returns. */
100
+ export declare const NO_BROWSER = -1;
64
101
  /**
65
102
  * The browser sign-in beat — `CR-084d`.
66
103
  *
@@ -69,16 +106,6 @@ export interface SignInBeatOptions extends BrowserDeps {
69
106
  * says so; it never replaces a working session.
70
107
  */
71
108
  export declare function signInBeat(ctx: CommandContext, options: SignInBeatOptions): Promise<number>;
72
- export type BrowserCredential =
73
- /** Minted AND written to `credentials.json`. The caller confirms it on screen. */
74
- {
75
- readonly kind: "saved";
76
- readonly credential: IngestCredential;
77
- }
78
- /** Nothing was written. The reason is already on stderr; the caller offers the paste. */
79
- | {
80
- readonly kind: "failed";
81
- };
82
109
  /**
83
110
  * Sign in if needed, mint this machine's credential, save it — `CR-226`.
84
111
  *
@@ -86,4 +113,4 @@ export type BrowserCredential =
86
113
  * because what comes next differs by caller (`auth` ends, `connect` goes on to
87
114
  * capture) and a confirmation here would be a second one.
88
115
  */
89
- export declare function browserCredential(ctx: CommandContext, retry: Retry, deps?: BrowserDeps): Promise<BrowserCredential>;
116
+ export declare function browserCredential(ctx: CommandContext, retry: Retry, deps?: BrowserDeps, options?: BrowserOptions): Promise<BrowserCredential>;
@@ -28,15 +28,25 @@
28
28
  * types precisely to replace what is there.
29
29
  */
30
30
  import { hostname as osHostname } from "node:os";
31
+ import { headlessReason } from "../device_mode.js";
32
+ import { resolveOnPath } from "../install.js";
31
33
  import { AUTH, COMMANDS, SIGNIN } from "../copy/index.js";
32
- import { saveCredential } from "../credential.js";
34
+ import { loadCredential } from "../credential.js";
33
35
  import { EXIT } from "../exit.js";
34
36
  import { mcpUrl } from "../oauth/discovery.js";
35
37
  import { machineLabel } from "../oauth/mint.js";
36
38
  import { loadSession } from "../oauth/session.js";
37
- import { HTTP_TIMEOUT_MS, mintWithSession, openBrowser as platformOpenBrowser, signIn, } from "../oauth/signin.js";
39
+ import { authorizedAccessToken, HTTP_TIMEOUT_MS, mintWithSession, openBrowser as platformOpenBrowser, signIn, } from "../oauth/signin.js";
38
40
  import { paint, renderErrorBlock, wrap } from "../term.js";
39
41
  import { writeLines } from "./context.js";
42
+ import { deviceCredential } from "./device_credential.js";
43
+ import { finishMint } from "./finish_mint.js";
44
+ import { probeCredential } from "./probe.js";
45
+ // `finishMint` and its types moved to `finish_mint.ts` (`CR-234d`) so the device flow can share them without
46
+ // a cycle. Re-exported here because this is where every caller and test has always found them.
47
+ export { finishMint } from "./finish_mint.js";
48
+ /** `signInBeat`'s sentinel for "no browser, go to the device flow". Never an exit code a verb returns. */
49
+ export const NO_BROWSER = -1;
40
50
  /**
41
51
  * The browser sign-in beat — `CR-084d`.
42
52
  *
@@ -46,8 +56,18 @@ import { writeLines } from "./context.js";
46
56
  */
47
57
  export async function signInBeat(ctx, options) {
48
58
  if (options.replace !== true && loadSession(ctx.home).kind === "ok") {
49
- writeLines(ctx.stdout, wrap(SIGNIN.alreadySignedIn, 2));
50
- return EXIT.ok;
59
+ const live = options.verify === true
60
+ ? await authorizedAccessToken({
61
+ home: ctx.home,
62
+ fetch: options.fetch ?? fetch,
63
+ nowMs: () => ctx.now().getTime(),
64
+ })
65
+ : null;
66
+ if (live === null || live.kind !== "expired") {
67
+ writeLines(ctx.stdout, wrap(SIGNIN.alreadySignedIn, 2));
68
+ return EXIT.ok;
69
+ }
70
+ // The refresh grant was refused: the session is over. Sign in again below.
51
71
  }
52
72
  const endpoint = mcpUrl(ctx.env);
53
73
  if (endpoint === null) {
@@ -60,6 +80,9 @@ export async function signInBeat(ctx, options) {
60
80
  fetch: options.fetch ?? fetch,
61
81
  nowMs: () => ctx.now().getTime(),
62
82
  openBrowser: options.openBrowser ?? platformOpenBrowser,
83
+ ...(options.orgId === undefined ? {} : { orgId: options.orgId }),
84
+ ...(options.deadlineMs === undefined ? {} : { deadlineMs: options.deadlineMs }),
85
+ ...(options.fallbackToDevice === true ? { fallbackOnNoBrowser: true } : {}),
63
86
  onAuthorizeUrl: (url, opened) => {
64
87
  writeLines(ctx.stdout, [
65
88
  "",
@@ -77,6 +100,8 @@ export async function signInBeat(ctx, options) {
77
100
  writeLines(ctx.stdout, ["", ...wrap(SIGNIN.done, 2)]);
78
101
  return EXIT.ok;
79
102
  }
103
+ if (outcome.kind === "no-browser")
104
+ return NO_BROWSER;
80
105
  writeLines(ctx.stderr, ["", ...signInFailure(ctx, options.retry, outcome)]);
81
106
  return EXIT.failure;
82
107
  }
@@ -117,7 +142,7 @@ function signInError(ctx, retry, what, why, fixLabel = SIGNIN.noServerFix) {
117
142
  * because what comes next differs by caller (`auth` ends, `connect` goes on to
118
143
  * capture) and a confirmation here would be a second one.
119
144
  */
120
- export async function browserCredential(ctx, retry, deps = {}) {
145
+ export async function browserCredential(ctx, retry, deps = {}, options = {}) {
121
146
  // Resolved ONCE and handed to both halves, so the session and the credential
122
147
  // cannot come from two different servers.
123
148
  const endpoint = mcpUrl(ctx.env);
@@ -125,11 +150,45 @@ export async function browserCredential(ctx, retry, deps = {}) {
125
150
  writeLines(ctx.stderr, signInError(ctx, retry, SIGNIN.noServerWhat, SIGNIN.noServerRefusedWhy));
126
151
  return { kind: "failed" };
127
152
  }
128
- if ((await signInBeat(ctx, { ...deps, retry })) !== EXIT.ok)
153
+ const fetchImpl = deps.fetch ?? fetch;
154
+ // ⛔ THE CREDENTIAL THIS RE-AUTH REPLACES, and only from the FILE (plan item 2). `VIBECOMMIT_TOKEN`
155
+ // wins `loadCredential`, so an exported variable makes `source` "env" and `prior` null: an
156
+ // environment credential is the CI path (D56) and is never probed, bound or retired from here.
157
+ const loaded = loadCredential({ env: ctx.env, home: ctx.home });
158
+ const prior = loaded.kind === "ok" && loaded.credential.source === "file"
159
+ ? {
160
+ credential: loaded.credential,
161
+ // Not recorded: it is about to be replaced, and its facts must not outlive it.
162
+ who: await probeCredential(ctx, loaded.credential, fetchImpl, { record: false }),
163
+ }
164
+ : null;
165
+ // ⛔ DEVICE MODE (`CR-234d`, plan item 7). By request (`--device`), or because this machine has no browser
166
+ // of its own: an SSH session, or a Linux box with no display. The loopback sign-in would open a browser
167
+ // nobody can see and wait out its deadline, so the machine asks for a code instead. The prefilled link is
168
+ // opened only where a browser plausibly exists — `--device` on a desktop — never on a headless box.
169
+ const headless = headlessReason(ctx.env, deps.platform ?? process.platform);
170
+ if (options.device === true || headless !== null) {
171
+ return await deviceCredential(ctx, { endpoint, prior, openLink: headless === null }, deps);
172
+ }
173
+ const signedIn = await signInBeat(ctx, {
174
+ ...deps,
175
+ retry,
176
+ // 2(a): ask the authorize page to bind the org the old credential belongs to. Only on a 200 —
177
+ // an org the server would not vouch for is not worth asking for.
178
+ ...(prior?.who.kind === "ok" ? { orgId: prior.who.orgId } : {}),
179
+ // A browser that cannot be opened is a headless machine the check above did not recognise: go to
180
+ // the device flow rather than print a URL and wait for a callback nobody can make.
181
+ fallbackToDevice: true,
182
+ openBrowser: deps.openBrowser ?? ((url) => canOpenBrowser(ctx.env, deps.platform ?? process.platform) && platformOpenBrowser(url)),
183
+ });
184
+ if (signedIn === NO_BROWSER) {
185
+ return await deviceCredential(ctx, { endpoint, prior, openLink: false }, deps);
186
+ }
187
+ if (signedIn !== EXIT.ok) {
129
188
  return { kind: "failed" };
189
+ }
130
190
  const label = machineLabel((deps.hostname ?? osHostname)());
131
191
  writeLines(ctx.stdout, ["", ...wrap(AUTH.minting(label), 2)]);
132
- const fetchImpl = deps.fetch ?? fetch;
133
192
  const mint = () => mintWithSession(endpoint, label, {
134
193
  home: ctx.home,
135
194
  fetch: fetchImpl,
@@ -151,14 +210,28 @@ export async function browserCredential(ctx, retry, deps = {}) {
151
210
  outcome = await mint();
152
211
  }
153
212
  if (outcome.kind === "ok") {
154
- // Through the CR-216 writer, so the 0700/0600 double-chmod and the
155
- // wrong-class refusal apply exactly as they do to a pasted credential.
156
- saveCredential(ctx.home, outcome.credential);
157
- return { kind: "saved", credential: outcome.credential };
213
+ return await finishMint(ctx, {
214
+ minted: outcome.credential,
215
+ facts: outcome.facts,
216
+ prior,
217
+ endpoint,
218
+ fetch: fetchImpl,
219
+ // The block guards a re-auth that lands in a DIFFERENT workspace. The device flow passes
220
+ // "always" — there the approver is not the person at this terminal.
221
+ confirm: "on-replace",
222
+ });
158
223
  }
159
224
  writeLines(ctx.stderr, ["", ...renderErrorBlock({ kind: "bad", what: AUTH.mintFailedWhat, why: [mintWhy(outcome)] }, ctx.colour)]);
160
225
  return { kind: "failed" };
161
226
  }
227
+ /**
228
+ * Is there anything on this machine that could open a URL? `openBrowser` reports `true` once `spawn` returns,
229
+ * and a missing `xdg-open` only surfaces later as an asynchronous error — so on Linux the answer is checked
230
+ * up front. macOS and Windows ship `open` and `start`.
231
+ */
232
+ function canOpenBrowser(env, platform) {
233
+ return platform !== "linux" || resolveOnPath(env, "xdg-open") !== null;
234
+ }
162
235
  /** One `why` per way the mint can fail. No status codes on screen (§13.6). */
163
236
  function mintWhy(outcome) {
164
237
  switch (outcome.kind) {
@@ -1 +1 @@
1
- {"version":3,"file":"browser_credential.js","sourceRoot":"","sources":["../../src/commands/browser_credential.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browser_credential.js","sourceRoot":"","sources":["../../src/commands/browser_credential.ts"],"names":[],"mappings":"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"}
@@ -27,7 +27,7 @@
27
27
  * @provenance vibecommit-mcp src/transport/server.ts — POST /oauth/ingest-credential now mints one, verified
28
28
  */
29
29
  import { type CommandContext } from "./context.js";
30
- import { type BrowserCredential, type Retry } from "./browser_credential.js";
30
+ import { type BrowserCredential, type BrowserOptions, type Retry } from "./browser_credential.js";
31
31
  /**
32
32
  * What `connect` was asked to do beyond the default.
33
33
  *
@@ -37,6 +37,8 @@ import { type BrowserCredential, type Retry } from "./browser_credential.js";
37
37
  export interface ConnectOptions {
38
38
  /** `--sign-in`. Off by default — see the module note for why. */
39
39
  readonly signIn?: boolean;
40
+ /** `CR-234d`: `--device`. Obtain a missing credential by CODE, approved on another device. TTY only. */
41
+ readonly device?: boolean;
40
42
  /** `TODOS[184]`: `--help`/`-h`. `connect` has no `argv` param, so this is computed at the call site. */
41
43
  readonly help?: boolean;
42
44
  }
@@ -50,6 +52,8 @@ export interface ConnectOptions {
50
52
  * caught where it matters.
51
53
  */
52
54
  export interface ConnectDeps {
53
- readonly browser?: (ctx: CommandContext, retry: Retry) => Promise<BrowserCredential>;
55
+ readonly browser?: (ctx: CommandContext, retry: Retry, options?: BrowserOptions) => Promise<BrowserCredential>;
56
+ /** The network for the credential probe. Left out, the real `fetch` — the stand-in server is a URL. */
57
+ readonly fetch?: typeof fetch;
54
58
  }
55
59
  export declare function connect(ctx: CommandContext, options?: ConnectOptions, deps?: ConnectDeps): Promise<number>;