@vibe-commit/capture 0.7.0 → 0.8.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 (85) hide show
  1. package/README.md +114 -7
  2. package/dist/account_not_here.d.ts +15 -0
  3. package/dist/account_not_here.js +25 -0
  4. package/dist/account_not_here.js.map +1 -0
  5. package/dist/commands/auth.d.ts +7 -0
  6. package/dist/commands/auth.js +21 -0
  7. package/dist/commands/auth.js.map +1 -1
  8. package/dist/commands/browser_credential.d.ts +4 -2
  9. package/dist/commands/browser_credential.js +5 -2
  10. package/dist/commands/browser_credential.js.map +1 -1
  11. package/dist/commands/connect.d.ts +9 -0
  12. package/dist/commands/connect.js +13 -8
  13. package/dist/commands/connect.js.map +1 -1
  14. package/dist/commands/connect_account.d.ts +135 -0
  15. package/dist/commands/connect_account.js +321 -0
  16. package/dist/commands/connect_account.js.map +1 -0
  17. package/dist/commands/connect_picker.js +160 -26
  18. package/dist/commands/connect_picker.js.map +1 -1
  19. package/dist/commands/device_credential.d.ts +3 -1
  20. package/dist/commands/device_credential.js +1 -0
  21. package/dist/commands/device_credential.js.map +1 -1
  22. package/dist/commands/finish_mint.d.ts +28 -0
  23. package/dist/commands/finish_mint.js +16 -4
  24. package/dist/commands/finish_mint.js.map +1 -1
  25. package/dist/commands/status.d.ts +19 -1
  26. package/dist/commands/status.js +123 -14
  27. package/dist/commands/status.js.map +1 -1
  28. package/dist/commands/status_machine.d.ts +12 -3
  29. package/dist/commands/status_machine.js +64 -3
  30. package/dist/commands/status_machine.js.map +1 -1
  31. package/dist/commands/sync_reason.d.ts +17 -0
  32. package/dist/commands/sync_reason.js +25 -0
  33. package/dist/commands/sync_reason.js.map +1 -0
  34. package/dist/consent.d.ts +109 -3
  35. package/dist/consent.js +210 -13
  36. package/dist/consent.js.map +1 -1
  37. package/dist/copy/strings.d.ts +122 -3
  38. package/dist/copy/strings.js +142 -3
  39. package/dist/copy/strings.js.map +1 -1
  40. package/dist/grants_sync.d.ts +165 -0
  41. package/dist/grants_sync.js +289 -0
  42. package/dist/grants_sync.js.map +1 -0
  43. package/dist/grants_verb.d.ts +70 -0
  44. package/dist/grants_verb.js +121 -0
  45. package/dist/grants_verb.js.map +1 -0
  46. package/dist/hooks/entry.js +8 -2
  47. package/dist/hooks/entry.js.map +1 -1
  48. package/dist/hooks/session_grants.d.ts +59 -0
  49. package/dist/hooks/session_grants.js +91 -0
  50. package/dist/hooks/session_grants.js.map +1 -0
  51. package/dist/hooks/session_start.d.ts +28 -7
  52. package/dist/hooks/session_start.js +55 -11
  53. package/dist/hooks/session_start.js.map +1 -1
  54. package/dist/index.js +22 -5
  55. package/dist/index.js.map +1 -1
  56. package/dist/oauth/retire.d.ts +10 -0
  57. package/dist/oauth/retire.js +13 -0
  58. package/dist/oauth/retire.js.map +1 -1
  59. package/dist/paths.d.ts +20 -0
  60. package/dist/paths.js +26 -0
  61. package/dist/paths.js.map +1 -1
  62. package/dist/pending_revoke.d.ts +117 -0
  63. package/dist/pending_revoke.js +233 -0
  64. package/dist/pending_revoke.js.map +1 -0
  65. package/dist/pending_revoke_file.d.ts +55 -0
  66. package/dist/pending_revoke_file.js +74 -0
  67. package/dist/pending_revoke_file.js.map +1 -0
  68. package/dist/picker.d.ts +30 -2
  69. package/dist/picker.js +55 -6
  70. package/dist/picker.js.map +1 -1
  71. package/dist/picker_checklist.d.ts +19 -3
  72. package/dist/picker_checklist.js +40 -4
  73. package/dist/picker_checklist.js.map +1 -1
  74. package/dist/policy.d.ts +16 -1
  75. package/dist/policy.js +21 -2
  76. package/dist/policy.js.map +1 -1
  77. package/dist/post.d.ts +41 -2
  78. package/dist/post.js +40 -12
  79. package/dist/post.js.map +1 -1
  80. package/dist/system_message.d.ts +25 -2
  81. package/dist/system_message.js +29 -5
  82. package/dist/system_message.js.map +1 -1
  83. package/dist/version.d.ts +1 -1
  84. package/dist/version.js +1 -1
  85. package/package.json +2 -2
@@ -0,0 +1,135 @@
1
+ /**
2
+ * What `connect` does with the account's grants (slice 2, S4 part 3): the changes it queues for the account, the turn-ons the
3
+ * account itself had turned off, the second question a joining machine is asked, and `g` — use the repositories the account
4
+ * already grants, on a machine with no credential.
5
+ *
6
+ * ```
7
+ * changeOps(change, covered) the account writes a picker change means, for the pending queue
8
+ * splitAccountExclusions(change, …) a repo the account turned off is a `turn on`, not an add
9
+ * joiningMachine(ctx, …) screen 2: "Your account also grants … Capture those here too?"
10
+ * mintForG(ctx, …) `g`: sign in (the credential held in MEMORY behind a write-ahead row), then read the account's grants
11
+ * commitG(ctx, g) the yes: credentials.json, then the row's deletion
12
+ * settleG(ctx, deps, g) the ONE finally: a run that did not commit revokes what `g` made and clears its row
13
+ * ```
14
+ *
15
+ * ⛔ LOADED LAZILY with `connect_picker.ts` (see its docblock): the picker path is a person at a terminal.
16
+ *
17
+ * ⛔ `g` IS THE ONE PLACE A CREDENTIAL IS MADE AHEAD OF CONSENT (exception 3), and it is kept honest by WRITE-AHEAD (`pending_revoke.ts`):
18
+ * the instant the server hands the token over a row for it is written, and the credential lives in memory — `credentials.json` does not
19
+ * exist before the person's yes. Whatever then ends the run short of the yes (a no, Ctrl+C, a kill, an unexpected throw) leaves a row the
20
+ * next verb revokes, never a live credential nothing remembers; the yes commits the grants, then `credentials.json`, then deletes the row.
21
+ * It is reached only from the picker's `g`, which is offered only where there is no credential and a browser to sign in with — so never
22
+ * from the `auth` chain (which has no browser, and always leaves a credential).
23
+ */
24
+ import { readAccountState } from "../consent.js";
25
+ import { saveCredential, type IngestCredential } from "../credential.js";
26
+ import { type AccountSnapshot, type SyncOp } from "../grants_sync.js";
27
+ import { type VerbSync, type VerbSyncDeps } from "../grants_verb.js";
28
+ import type { PickerChange } from "../picker.js";
29
+ import { type ConnectDeps, type ConnectOptions } from "./connect.js";
30
+ import { type CommandContext } from "./context.js";
31
+ /**
32
+ * The account writes a picker change means, in the order they should be queued. A re-include is `include` (the account's
33
+ * exclusion lifts) and, unless an owner grant already covers the repo, `grant` (it is named on this machine from now on) —
34
+ * exactly what `applyChange` does to `grants.json`. A removal is a `revoke`; a per-clone consent withdrawn is a `revoke` of its slug,
35
+ * because the first sync uploaded it as a grant.
36
+ */
37
+ export declare function changeOps(change: PickerChange, covered: (slug: string) => boolean): SyncOp[];
38
+ /**
39
+ * A repo the ACCOUNT has turned off (not only this machine) and the person picked as an ordinary add is a re-include: it moves
40
+ * to `turnOn`, so the grant block names it on its own `turn on` row, `(turned off on your account)`, and the yes lifts the
41
+ * exclusion for every machine. The user's yes wins, as slice 1's re-include rule has it. `accountOff` is every `turn on` slug the
42
+ * account turned off, the moved ones and the ones that were already turn-ons here.
43
+ */
44
+ export declare function splitAccountExclusions(change: PickerChange, accountExcluded: readonly string[]): {
45
+ readonly change: PickerChange;
46
+ readonly accountOff: ReadonlySet<string>;
47
+ };
48
+ /**
49
+ * Screen 2 — a machine joining an account by picking local repos (design slice 2, step 4). After the credential and the first
50
+ * sync, the account may grant more than was just picked: ask, naming them, before any is admitted on this machine. `y` names them
51
+ * here (and syncs, so the server learns this machine's set); `n` — and Ctrl+C, which here is a No that does not undo what was
52
+ * already chosen — leaves them on the account, listed by `status`.
53
+ *
54
+ * Returns the names now captured here, for the "Capture is on" block, and whether the question was cancelled with Ctrl+C: the run
55
+ * then finishes its non-interactive steps and asks nothing more (no backfill offer), VQ's ruling on #88.
56
+ */
57
+ export declare function joiningMachine(ctx: CommandContext, deps: VerbSyncDeps, answers: string,
58
+ /** The first-sync line was already printed in this run: the sync after "y" does not print it again. */
59
+ firstSyncSaid?: boolean): Promise<{
60
+ readonly names: readonly string[];
61
+ readonly cancelled: boolean;
62
+ readonly sync: VerbSync | null;
63
+ }>;
64
+ /**
65
+ * What `connect` says under "Capture is on" about the sync after its writes (VQ, on VT's question). Capture IS on whatever this
66
+ * says — the local grants admit the repo — so these are muted lines that tell the truth about the ACCOUNT, by what the sync answered:
67
+ * - synced: nothing;
68
+ * - a 400 (our own bug; the queue is kept and will be refused again): the status row's wording, "didn't accept · report this";
69
+ * - a 401 (the credential is no longer accepted): `ERRORS.authFatal` and the channel's `auth` command;
70
+ * - anything else (no answer, off-contract, over the caps, or no sync attempted): "hasn't been told yet; running `status` retries".
71
+ * Only `connect`, `status` and `off` sync, so the retry it names is `status`.
72
+ */
73
+ export declare function accountNoteLines(ctx: CommandContext, sync: VerbSync | null): string[];
74
+ /** What `g` found: the credential it made (in MEMORY ONLY), and the account's grants (`null`: they could not be read). */
75
+ export type GMint = {
76
+ readonly kind: "exit";
77
+ readonly code: number;
78
+ } | {
79
+ readonly kind: "minted";
80
+ readonly credential: IngestCredential;
81
+ readonly snapshot: AccountSnapshot | null;
82
+ readonly notes: readonly string[];
83
+ readonly origin: string;
84
+ };
85
+ /**
86
+ * `g`'s state across a `connectPicker` run, for the ONE `finally` that settles it (`settleG`). `credential` is the token `g` made;
87
+ * `committed` flips only once the credential is on disk behind a successful grant write; `end` says how a run that granted nothing
88
+ * ended, for the line the person reads.
89
+ */
90
+ export interface GState {
91
+ credential: IngestCredential | null;
92
+ /** What the GET learned: written to `grants-account.json` at the commit (after the yes), never before it. */
93
+ snapshot: AccountSnapshot | null;
94
+ /** The origin that minted the credential: where an in-memory revoke goes when its row is missing or the queue is refused. */
95
+ origin: string;
96
+ /** What the mint said to add to the "Saved" block (the environment-token shadow note). */
97
+ notes: readonly string[];
98
+ committed: boolean;
99
+ end: "declined" | "cancelled" | "lost" | "unrecorded" | "occupied" | null;
100
+ }
101
+ /**
102
+ * The yes, for a credential `g` is holding: the GRANTS are already written (the caller's `applyChange`); now `credentials.json`, THEN
103
+ * the row's deletion. `committed` flips as soon as the credential is on disk, so a failure of the deletion (or a kill between the two)
104
+ * never revokes what the person kept: the row's token IS the current credential, and the next verb's retry skips and drops it.
105
+ */
106
+ export declare function commitG(ctx: CommandContext, g: GState, save?: typeof saveCredential): "committed" | "lost" | "unrecorded" | "occupied";
107
+ /**
108
+ * `g`: sign in through `deps.browser` (the credential beat, behind its own gate: no credential, a terminal, a browser), then ONE
109
+ * `GET` of the account's grants — a pure read that marks nothing as synced.
110
+ *
111
+ * ⛔ **WRITE-AHEAD, AND NOTHING ON DISK.** The mint is asked to HOLD the credential (`hold`): the instant the server hands the token
112
+ * over, a row for it is written to `pending-revoke.json` (`addPendingRevoke`), and `credentials.json` is NOT written — the credential
113
+ * lives in memory until the person's yes, and the GET below uses it from there. If the row cannot be written (an insecure or unreadable
114
+ * file, the cap, a failed write) the credential is revoked in memory at once, nothing is kept, and `g` ends on the ordinary
115
+ * "Nothing was changed" path with a muted line that says what happened.
116
+ *
117
+ * What the GET learned is NOT written here: `commitG` writes it to `grants-account.json` after the yes, so a no or Ctrl+C leaves nothing
118
+ * about the account behind on a machine that keeps no credential — and after a yes, `account.excluded` denies an account-excluded repo
119
+ * under a newly granted owner.
120
+ */
121
+ export declare function mintForG(ctx: CommandContext, options: ConnectOptions, deps: ConnectDeps, account: VerbSyncDeps): Promise<GMint>;
122
+ /** The account's own list as a picker change: its owners, and its repos that no listed owner covers and that are not turned off. */
123
+ export declare function accountChange(snapshot: AccountSnapshot): PickerChange;
124
+ /**
125
+ * The ONE `finally` of `g` (VQ + VT, #88). A run that did not COMMIT the credential — a no, Ctrl+C (the first, a second, a
126
+ * SIGHUP: the row already exists, so a signal needs only to exit), an empty account, Enter, a removals-only yes, a failed write or an
127
+ * unexpected throw — makes one best-effort revoke within 3 s, to the origin the row recorded, and the row leaves on a 2xx, a 401 or a
128
+ * 404. Nothing was ever on disk, so there is no file to delete; the row is what stays if the revoke does not land.
129
+ *
130
+ * `end` says how a run that granted nothing ended: its line is printed here, and "the server will be told on the next vibecommit
131
+ * command that contacts the server" only when the row is still there to say it with. A throw prints nothing and rethrows.
132
+ */
133
+ export declare function settleG(ctx: CommandContext, deps: ConnectDeps, g: GState): Promise<void>;
134
+ /** The account state the last sync recorded, or `null` before a first sync. */
135
+ export declare function lastAccountState(home: string): ReturnType<typeof readAccountState>["account"];
@@ -0,0 +1,321 @@
1
+ /**
2
+ * What `connect` does with the account's grants (slice 2, S4 part 3): the changes it queues for the account, the turn-ons the
3
+ * account itself had turned off, the second question a joining machine is asked, and `g` — use the repositories the account
4
+ * already grants, on a machine with no credential.
5
+ *
6
+ * ```
7
+ * changeOps(change, covered) the account writes a picker change means, for the pending queue
8
+ * splitAccountExclusions(change, …) a repo the account turned off is a `turn on`, not an add
9
+ * joiningMachine(ctx, …) screen 2: "Your account also grants … Capture those here too?"
10
+ * mintForG(ctx, …) `g`: sign in (the credential held in MEMORY behind a write-ahead row), then read the account's grants
11
+ * commitG(ctx, g) the yes: credentials.json, then the row's deletion
12
+ * settleG(ctx, deps, g) the ONE finally: a run that did not commit revokes what `g` made and clears its row
13
+ * ```
14
+ *
15
+ * ⛔ LOADED LAZILY with `connect_picker.ts` (see its docblock): the picker path is a person at a terminal.
16
+ *
17
+ * ⛔ `g` IS THE ONE PLACE A CREDENTIAL IS MADE AHEAD OF CONSENT (exception 3), and it is kept honest by WRITE-AHEAD (`pending_revoke.ts`):
18
+ * the instant the server hands the token over a row for it is written, and the credential lives in memory — `credentials.json` does not
19
+ * exist before the person's yes. Whatever then ends the run short of the yes (a no, Ctrl+C, a kill, an unexpected throw) leaves a row the
20
+ * next verb revokes, never a live credential nothing remembers; the yes commits the grants, then `credentials.json`, then deletes the row.
21
+ * It is reached only from the picker's `g`, which is offered only where there is no credential and a browser to sign in with — so never
22
+ * from the `auth` chain (which has no browser, and always leaves a credential).
23
+ */
24
+ import { PICKER, REPLACE } from "../copy/index.js";
25
+ import { isAffirmative, normalizeOwner, normalizeSlug, ownerOfSlug, readAccountState, holdsAny, updateGrants, writeAccountState, } from "../consent.js";
26
+ import { existsSync } from "node:fs";
27
+ import { saveCredential } from "../credential.js";
28
+ import { stoppedSyncReason } from "./sync_reason.js";
29
+ import { EXIT } from "../exit.js";
30
+ import { fetchAccountGrants, GRANTS_VERB_BODY_BYTES } from "../grants_sync.js";
31
+ import { readAccountView, syncForVerb } from "../grants_verb.js";
32
+ import { authCommandFor, channelCommand, connectCommandFor } from "../install.js";
33
+ import { COMMANDS } from "../copy/index.js";
34
+ import { addPendingRevoke, holdsRow, removePendingRevoke, revokeHeld } from "../pending_revoke.js";
35
+ import { readPerClone } from "../machine_state.js";
36
+ import { credentialsPath } from "../paths.js";
37
+ import { ingestUrl } from "../post.js";
38
+ import { paint, renderErrorBlock, wrap } from "../term.js";
39
+ import { askOrCancel, savedBlock } from "./connect.js";
40
+ import { credentialProblemBlock } from "./credential_problem.js";
41
+ import { writeLines } from "./context.js";
42
+ /**
43
+ * The account writes a picker change means, in the order they should be queued. A re-include is `include` (the account's
44
+ * exclusion lifts) and, unless an owner grant already covers the repo, `grant` (it is named on this machine from now on) —
45
+ * exactly what `applyChange` does to `grants.json`. A removal is a `revoke`; a per-clone consent withdrawn is a `revoke` of its slug,
46
+ * because the first sync uploaded it as a grant.
47
+ */
48
+ export function changeOps(change, covered) {
49
+ const ops = [];
50
+ for (const value of change.stopOwners)
51
+ ops.push({ op: "revoke", kind: "owner", value });
52
+ for (const value of [...change.stopRepos, ...change.stopClones])
53
+ ops.push({ op: "revoke", kind: "repo", value });
54
+ for (const value of change.addOwners)
55
+ ops.push({ op: "grant", kind: "owner", value });
56
+ for (const value of change.addRepos)
57
+ ops.push({ op: "grant", kind: "repo", value });
58
+ for (const value of change.turnOn) {
59
+ ops.push({ op: "include", kind: "repo", value });
60
+ if (!covered(value))
61
+ ops.push({ op: "grant", kind: "repo", value });
62
+ }
63
+ return ops;
64
+ }
65
+ /**
66
+ * A repo the ACCOUNT has turned off (not only this machine) and the person picked as an ordinary add is a re-include: it moves
67
+ * to `turnOn`, so the grant block names it on its own `turn on` row, `(turned off on your account)`, and the yes lifts the
68
+ * exclusion for every machine. The user's yes wins, as slice 1's re-include rule has it. `accountOff` is every `turn on` slug the
69
+ * account turned off, the moved ones and the ones that were already turn-ons here.
70
+ */
71
+ export function splitAccountExclusions(change, accountExcluded) {
72
+ const off = new Set(accountExcluded.map(normalizeSlug));
73
+ const moved = change.addRepos.filter((slug) => off.has(slug));
74
+ const next = moved.length === 0
75
+ ? change
76
+ : { ...change, addRepos: change.addRepos.filter((slug) => !off.has(slug)), turnOn: [...change.turnOn, ...moved] };
77
+ return { change: next, accountOff: new Set(next.turnOn.filter((slug) => off.has(slug))) };
78
+ }
79
+ /**
80
+ * Screen 2 — a machine joining an account by picking local repos (design slice 2, step 4). After the credential and the first
81
+ * sync, the account may grant more than was just picked: ask, naming them, before any is admitted on this machine. `y` names them
82
+ * here (and syncs, so the server learns this machine's set); `n` — and Ctrl+C, which here is a No that does not undo what was
83
+ * already chosen — leaves them on the account, listed by `status`.
84
+ *
85
+ * Returns the names now captured here, for the "Capture is on" block, and whether the question was cancelled with Ctrl+C: the run
86
+ * then finishes its non-interactive steps and asks nothing more (no backfill offer), VQ's ruling on #88.
87
+ */
88
+ export async function joiningMachine(ctx, deps, answers,
89
+ /** The first-sync line was already printed in this run: the sync after "y" does not print it again. */
90
+ firstSyncSaid = false) {
91
+ const view = readAccountView(ctx.home, readPerClone(ctx.home).flatMap((clone) => (clone.slug === null ? [] : [clone.slug])), { kind: "skipped" });
92
+ const names = view === null ? [] : view.notHere;
93
+ if (names.length === 0)
94
+ return { names: [], cancelled: false, sync: null };
95
+ writeLines(ctx.stdout, [
96
+ "",
97
+ ...wrap(PICKER.joinAlso(names.join("\n")), 2),
98
+ ...(names.length > 3 ? names.map((name) => ` ${name}`) : []),
99
+ ]);
100
+ const answer = await askOrCancel(ctx, ` ${paint(ctx.colour, "text", PICKER.joinQuestion)} ${paint(ctx.colour, "muted", answers)} `);
101
+ if (answer === null || !isAffirmative(answer)) {
102
+ writeLines(ctx.stdout, ["", ...wrap(PICKER.joinDeclined(channelCommand(ctx.env, ctx.selfPath, COMMANDS.status)), 2)]);
103
+ return { names: [], cancelled: answer === null, sync: null };
104
+ }
105
+ const owners = names.filter((name) => name.endsWith("/")).map((name) => normalizeOwner(name.slice(0, -1)));
106
+ const repos = names.filter((name) => !name.endsWith("/")).map(normalizeSlug);
107
+ try {
108
+ updateGrants(ctx.home, (g) => {
109
+ const nextOwners = [...new Set([...g.owners, ...owners])];
110
+ return {
111
+ ...g,
112
+ owners: nextOwners,
113
+ repos: [...new Set([...g.repos, ...repos.filter((slug) => !nextOwners.includes(ownerOfSlug(slug)))])],
114
+ };
115
+ });
116
+ }
117
+ catch {
118
+ // `grants.json` became unreadable since the picker's own write: nothing was named, and the next `connect` says so.
119
+ return { names: [], cancelled: false, sync: null };
120
+ }
121
+ // The server's `named` set is what the dashboard's "confirmed on N of M machines" counts: tell it now.
122
+ const sync = await syncForVerb(ctx, false, deps, { quietFirst: firstSyncSaid });
123
+ return { names, cancelled: false, sync };
124
+ }
125
+ /**
126
+ * What `connect` says under "Capture is on" about the sync after its writes (VQ, on VT's question). Capture IS on whatever this
127
+ * says — the local grants admit the repo — so these are muted lines that tell the truth about the ACCOUNT, by what the sync answered:
128
+ * - synced: nothing;
129
+ * - a 400 (our own bug; the queue is kept and will be refused again): the status row's wording, "didn't accept · report this";
130
+ * - a 401 (the credential is no longer accepted): `ERRORS.authFatal` and the channel's `auth` command;
131
+ * - anything else (no answer, off-contract, over the caps, or no sync attempted): "hasn't been told yet; running `status` retries".
132
+ * Only `connect`, `status` and `off` sync, so the retry it names is `status`.
133
+ */
134
+ export function accountNoteLines(ctx, sync) {
135
+ if (sync === null)
136
+ return [];
137
+ if (sync.kind === "ran" && sync.result.kind === "synced")
138
+ return [];
139
+ if (sync.kind === "ran") {
140
+ // A 400 and a 401 have their own lines, shared with `off` (`sync_reason.ts`, hook-safe).
141
+ const reason = stoppedSyncReason(ctx, sync.result);
142
+ if (reason !== null)
143
+ return reason;
144
+ }
145
+ const status = channelCommand(ctx.env, ctx.selfPath, COMMANDS.status);
146
+ // F2 / R2-2: the held wording only when the hold applies to something — a synced machine with a queued grant the cached account does
147
+ // not already grant (`holdsAny`, the gate's own predicate). Otherwise nothing waits and the plain line is the true one.
148
+ const held = holdsAny(ctx.home);
149
+ return wrap(held ? PICKER.accountNotToldHeld(status) : PICKER.accountNotTold(status), 2).map((line) => paint(ctx.colour, "muted", line));
150
+ }
151
+ /**
152
+ * The yes, for a credential `g` is holding: the GRANTS are already written (the caller's `applyChange`); now `credentials.json`, THEN
153
+ * the row's deletion. `committed` flips as soon as the credential is on disk, so a failure of the deletion (or a kill between the two)
154
+ * never revokes what the person kept: the row's token IS the current credential, and the next verb's retry skips and drops it.
155
+ */
156
+ export function commitG(ctx, g, save = saveCredential) {
157
+ if (g.credential === null)
158
+ return "lost";
159
+ // ⛔ BEFORE ANYTHING IS WRITTEN: the row is `g`'s lease on the credential. If it is gone, another verb's retry settled it (revoked it)
160
+ // while the question was open, and a `credentials.json` written now would be a dead credential: refuse. A `credentials.json` that
161
+ // already exists is a concurrent mint: never overwritten. Either way nothing is saved, and the finally revokes the in-memory token.
162
+ const held = holdsRow(ctx.home, g.credential.expose());
163
+ if (held === "gone")
164
+ return "lost";
165
+ if (held === "unusable")
166
+ return "unrecorded";
167
+ if (existsSync(credentialsPath(ctx.home)))
168
+ return "occupied";
169
+ save(ctx.home, g.credential);
170
+ g.committed = true;
171
+ removePendingRevoke(ctx.home, g.credential.expose());
172
+ savedBlock(ctx, g.notes);
173
+ // The account's state, as a sync leaves it — written only now, after the yes, so a no or Ctrl+C leaves nothing about the account
174
+ // on a machine that keeps no credential. It makes `account.excluded` deny an account-excluded repo under a newly granted owner.
175
+ if (g.snapshot !== null) {
176
+ try {
177
+ writeAccountState(ctx.home, {
178
+ account: {
179
+ owners: g.snapshot.owners,
180
+ repos: g.snapshot.repos,
181
+ excluded: g.snapshot.excluded,
182
+ epoch: g.snapshot.epoch,
183
+ synced_at: ctx.now().toISOString(),
184
+ },
185
+ refused: [],
186
+ stale: false,
187
+ last_get_at: readAccountState(ctx.home).last_get_at,
188
+ });
189
+ }
190
+ catch {
191
+ // A cache of what the server said; the next sync writes it.
192
+ }
193
+ }
194
+ return "committed";
195
+ }
196
+ /**
197
+ * `g`: sign in through `deps.browser` (the credential beat, behind its own gate: no credential, a terminal, a browser), then ONE
198
+ * `GET` of the account's grants — a pure read that marks nothing as synced.
199
+ *
200
+ * ⛔ **WRITE-AHEAD, AND NOTHING ON DISK.** The mint is asked to HOLD the credential (`hold`): the instant the server hands the token
201
+ * over, a row for it is written to `pending-revoke.json` (`addPendingRevoke`), and `credentials.json` is NOT written — the credential
202
+ * lives in memory until the person's yes, and the GET below uses it from there. If the row cannot be written (an insecure or unreadable
203
+ * file, the cap, a failed write) the credential is revoked in memory at once, nothing is kept, and `g` ends on the ordinary
204
+ * "Nothing was changed" path with a muted line that says what happened.
205
+ *
206
+ * What the GET learned is NOT written here: `commitG` writes it to `grants-account.json` after the yes, so a no or Ctrl+C leaves nothing
207
+ * about the account behind on a machine that keeps no credential — and after a yes, `account.excluded` denies an account-excluded repo
208
+ * under a newly granted owner.
209
+ */
210
+ export async function mintForG(ctx, options, deps, account) {
211
+ if (deps.browser === undefined)
212
+ return { kind: "exit", code: EXIT.failure };
213
+ const refusal = { current: null };
214
+ const mintedAt = { origin: "" };
215
+ const hold = {
216
+ record: (credential, endpoint) => {
217
+ // The row carries `g`'s lease (this process, 30 minutes): another verb's retry leaves it alone while the question is open.
218
+ const added = addPendingRevoke(ctx.home, credential, endpoint, ctx.now(), { lease: true });
219
+ if (added.kind === "written")
220
+ mintedAt.origin = new URL(endpoint).origin;
221
+ if (added.kind !== "written")
222
+ refusal.current = added;
223
+ return added.kind === "written";
224
+ },
225
+ release: (credential) => removePendingRevoke(ctx.home, credential.expose()),
226
+ };
227
+ const minted = await deps.browser(ctx, "connect", { device: options.device === true, scope: "repos", hold });
228
+ if (minted.kind === "unrecorded") {
229
+ const read = refusal.current !== null && refusal.current.kind === "refused" ? refusal.current.read : null;
230
+ if (read !== null && read.kind === "insecure-file") {
231
+ writeLines(ctx.stderr, ["", ...renderErrorBlock(credentialProblemBlock(read, authCommandFor(ctx.env, ctx.selfPath)), ctx.colour)]);
232
+ }
233
+ else {
234
+ writeLines(ctx.stdout, ["", ...wrap(PICKER.gNotRecorded, 2).map((line) => paint(ctx.colour, "muted", line))]);
235
+ }
236
+ // ⛔ NEVER "Cancelled. Nothing was changed.": a credential WAS made. In memory it was revoked (`declinedRevoked`), or it could not be
237
+ // and may still be live (`declinedOrphan` says where to revoke it) — either way the line is the credential's, and the exit is 1.
238
+ writeLines(ctx.stdout, wrap(minted.revoked ? REPLACE.declinedRevoked : REPLACE.declinedOrphan, 2).map((line) => paint(ctx.colour, "muted", line)));
239
+ return { kind: "exit", code: EXIT.failure };
240
+ }
241
+ // A declined or failed sign-in has already said why on screen, and made no credential that the client has to remember.
242
+ if (minted.kind !== "held")
243
+ return { kind: "exit", code: EXIT.failure };
244
+ const url = ingestUrl(ctx.env);
245
+ const read = url === null
246
+ ? null
247
+ : await fetchAccountGrants(url, minted.credential, {
248
+ fetch: account.fetch,
249
+ ...(account.timeoutMs === undefined ? {} : { timeoutMs: account.timeoutMs }),
250
+ maxBodyBytes: GRANTS_VERB_BODY_BYTES,
251
+ });
252
+ const snapshot = read !== null && read.kind === "ok" ? read : null;
253
+ return { kind: "minted", credential: minted.credential, snapshot, notes: minted.notes ?? [], origin: mintedAt.origin };
254
+ }
255
+ /** The account's own list as a picker change: its owners, and its repos that no listed owner covers and that are not turned off. */
256
+ export function accountChange(snapshot) {
257
+ const owners = snapshot.owners.map(normalizeOwner);
258
+ const off = new Set(snapshot.excluded);
259
+ return {
260
+ addOwners: owners,
261
+ addRepos: snapshot.repos.map(normalizeSlug).filter((slug) => !off.has(slug) && !owners.includes(ownerOfSlug(slug))),
262
+ turnOn: [],
263
+ stopOwners: [],
264
+ stopRepos: [],
265
+ stopClones: [],
266
+ };
267
+ }
268
+ /**
269
+ * The ONE `finally` of `g` (VQ + VT, #88). A run that did not COMMIT the credential — a no, Ctrl+C (the first, a second, a
270
+ * SIGHUP: the row already exists, so a signal needs only to exit), an empty account, Enter, a removals-only yes, a failed write or an
271
+ * unexpected throw — makes one best-effort revoke within 3 s, to the origin the row recorded, and the row leaves on a 2xx, a 401 or a
272
+ * 404. Nothing was ever on disk, so there is no file to delete; the row is what stays if the revoke does not land.
273
+ *
274
+ * `end` says how a run that granted nothing ended: its line is printed here, and "the server will be told on the next vibecommit
275
+ * command that contacts the server" only when the row is still there to say it with. A throw prints nothing and rethrows.
276
+ */
277
+ export async function settleG(ctx, deps, g) {
278
+ if (g.credential === null || g.committed)
279
+ return;
280
+ const result = await revokeHeld(ctx.home, g.credential, g.origin, deps.fetch ?? globalThis.fetch);
281
+ // A queue file that is insecure is named, with its fix: until it is fixed no later verb can read the row.
282
+ if (result.insecure !== null) {
283
+ writeLines(ctx.stderr, ["", ...renderErrorBlock(credentialProblemBlock(result.insecure, authCommandFor(ctx.env, ctx.selfPath)), ctx.colour)]);
284
+ }
285
+ if (g.end === null)
286
+ return;
287
+ const cancelled = g.end === "cancelled";
288
+ // Exactly what happened: "revoked" only on an answer from the server; "removed here … will be told" only while a readable row is
289
+ // there to tell it with; and with no usable row and no answer the credential may be live, so it says where to remove it.
290
+ const connect = connectCommandFor(ctx.env, ctx.selfPath);
291
+ const fate = result.kind === "revoked" ? REPLACE.declinedRevoked : result.kind === "waiting" ? PICKER.gRemovedWillTell : REPLACE.declinedOrphan;
292
+ // `orphan` (no usable row, no answer) and `unrevocable` (a 404: the row ended, but nothing revoked it) both leave a credential that may
293
+ // be live: neither is ever called "revoked" ("0.8.0 truth fixes" F7).
294
+ const live = result.kind === "orphan" || result.kind === "unrevocable";
295
+ // ⛔ "Nothing is captured on this machine" is for a run that ended with no credential kept AND nothing granted. An occupied
296
+ // `credentials.json` means the grants are saved and a credential is on disk: capture IS on, so that case says what happened and
297
+ // then what became of the credential this run made, on its own line.
298
+ if (g.end === "occupied") {
299
+ writeLines(ctx.stdout, ["", ...wrap(PICKER.gOccupied(connect), 2), ...wrap(fate, 2)]);
300
+ return;
301
+ }
302
+ const line = g.end === "lost" && result.kind === "revoked"
303
+ ? PICKER.gRevokedElsewhere(connect)
304
+ : g.end === "unrecorded" && !live
305
+ ? PICKER.gRecordUnusable(connect)
306
+ : live
307
+ ? REPLACE.declinedOrphan
308
+ : cancelled
309
+ ? result.kind === "revoked"
310
+ ? PICKER.gCancelledRevoked
311
+ : PICKER.gCancelledRemoved
312
+ : result.kind === "revoked"
313
+ ? PICKER.gDeclinedRevoked
314
+ : PICKER.gDeclinedRemoved;
315
+ writeLines(ctx.stdout, cancelled ? ["", "", ...wrap(line, 2)] : ["", ...wrap(line, 2)]);
316
+ }
317
+ /** The account state the last sync recorded, or `null` before a first sync. */
318
+ export function lastAccountState(home) {
319
+ return readAccountState(home).account;
320
+ }
321
+ //# sourceMappingURL=connect_account.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect_account.js","sourceRoot":"","sources":["../../src/commands/connect_account.ts"],"names":[],"mappings":"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"}