@opvs-ai/cli 0.16.0 → 0.20.1

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 (60) hide show
  1. package/README.md +88 -8
  2. package/dist/.build-stamp.json +5 -5
  3. package/dist/commands/agent.js +6 -5
  4. package/dist/commands/agent.js.map +1 -1
  5. package/dist/commands/auth.js +246 -76
  6. package/dist/commands/auth.js.map +1 -1
  7. package/dist/commands/board-links.js +5 -2
  8. package/dist/commands/board-links.js.map +1 -1
  9. package/dist/commands/boards.js +26 -16
  10. package/dist/commands/boards.js.map +1 -1
  11. package/dist/commands/code.d.ts +23 -0
  12. package/dist/commands/code.js +90 -0
  13. package/dist/commands/code.js.map +1 -0
  14. package/dist/commands/columns.d.ts +1 -0
  15. package/dist/commands/columns.js +53 -4
  16. package/dist/commands/columns.js.map +1 -1
  17. package/dist/commands/config.js +5 -2
  18. package/dist/commands/config.js.map +1 -1
  19. package/dist/commands/docs.js +17 -8
  20. package/dist/commands/docs.js.map +1 -1
  21. package/dist/commands/employees.js +4 -2
  22. package/dist/commands/employees.js.map +1 -1
  23. package/dist/commands/files.js +5 -2
  24. package/dist/commands/files.js.map +1 -1
  25. package/dist/commands/links.js +9 -4
  26. package/dist/commands/links.js.map +1 -1
  27. package/dist/commands/mail.js +5 -2
  28. package/dist/commands/mail.js.map +1 -1
  29. package/dist/commands/markers.js +18 -5
  30. package/dist/commands/markers.js.map +1 -1
  31. package/dist/commands/members.js +4 -1
  32. package/dist/commands/members.js.map +1 -1
  33. package/dist/commands/projects.js +57 -12
  34. package/dist/commands/projects.js.map +1 -1
  35. package/dist/commands/scheduled-runs.d.ts +26 -0
  36. package/dist/commands/scheduled-runs.js +182 -0
  37. package/dist/commands/scheduled-runs.js.map +1 -0
  38. package/dist/commands/stages.js +5 -2
  39. package/dist/commands/stages.js.map +1 -1
  40. package/dist/commands/tasks.js +8 -5
  41. package/dist/commands/tasks.js.map +1 -1
  42. package/dist/commands/tools.js +34 -5
  43. package/dist/commands/tools.js.map +1 -1
  44. package/dist/commands/workspace.js +5 -2
  45. package/dist/commands/workspace.js.map +1 -1
  46. package/dist/index.js +4 -0
  47. package/dist/index.js.map +1 -1
  48. package/dist/lib/auth-poll.d.ts +25 -3
  49. package/dist/lib/auth-poll.js +39 -6
  50. package/dist/lib/auth-poll.js.map +1 -1
  51. package/dist/lib/confirm.d.ts +14 -0
  52. package/dist/lib/confirm.js +17 -0
  53. package/dist/lib/confirm.js.map +1 -1
  54. package/dist/lib/health.d.ts +131 -1
  55. package/dist/lib/health.js +192 -3
  56. package/dist/lib/health.js.map +1 -1
  57. package/dist/lib/pending-auth.d.ts +41 -0
  58. package/dist/lib/pending-auth.js +69 -0
  59. package/dist/lib/pending-auth.js.map +1 -0
  60. package/package.json +2 -2
package/README.md CHANGED
@@ -41,13 +41,23 @@ Agent runs: opvs auth request -w <workspace> -e <admin-email>
41
41
  --> Approval email sent to admin
42
42
  --> CLI polls for approval every 3s
43
43
 
44
- Admin clicks: [Approve] button in email
44
+ Admin clicks: [Approve] button in email (the link works for 60 minutes)
45
45
  --> Token generated and delivered to CLI
46
46
  --> Saved to ~/.opvs/config.json
47
47
  ```
48
48
 
49
49
  No passwords, no copy-pasting tokens. The human stays in control.
50
50
 
51
+ The CLI waits 5 minutes for the approval (`--wait <minutes>` to change it). If the admin
52
+ approves later, the request is still open — collect the token with:
53
+
54
+ ```bash
55
+ opvs auth resume
56
+ ```
57
+
58
+ Exit codes for `auth request` and `auth resume`: `0` approved · `1` denied, expired or
59
+ failed · `2` not approved yet (run `opvs auth resume`).
60
+
51
61
  ## Multi-Workspace Support
52
62
 
53
63
  The CLI supports multiple workspaces (brands) with kubectl-style context switching. Each workspace has its own token, brand, and API URL.
@@ -70,7 +80,7 @@ opvs -w my-company boards list
70
80
  opvs workspace current
71
81
 
72
82
  # Remove a workspace
73
- opvs workspace remove old-brand
83
+ opvs workspace remove old-brand --yes
74
84
  ```
75
85
 
76
86
  ### Config File
@@ -125,12 +135,37 @@ opvs boards set-routing ASP --harness codex # Board routing defaults ('
125
135
  opvs boards projects ASP # Projects claiming the board (none|resolved|ambiguous)
126
136
  opvs boards add-to-project ASP <project-uuid> # Additive
127
137
  opvs boards move-to-project ASP <project-uuid> --yes # REMOVES it from every other project — previews first
128
- opvs boards health ASP --profile factory # Unsupplied thresholds print NOT CHECKED
138
+ opvs boards health ASP --profile factory # EXITS 2 on not_healthy — see below
139
+ opvs boards health ASP --format json | jq .verdict # the report VERBATIM
129
140
  opvs boards apply-preset ASP factory-full # DRY RUN by default; --yes applies
130
141
  opvs boards apply-preset ASP factory-full --yes --json | jq .applied # ONE JSON document: the applied plan
131
142
  opvs boards update ASP --archived true # Hidden from `boards list`; cards stay CLAIMABLE
132
143
  ```
133
144
 
145
+ #### Gating a script on board / project health
146
+
147
+ `boards health` and `projects health` are the same report the dashboard shows, and they set an
148
+ exit code so a shell can gate on them:
149
+
150
+ | Exit | Verdict | Means |
151
+ |-----:|---------|-------|
152
+ | `0` | `healthy` | every check ran, none failed |
153
+ | `0` | `incomplete` | **you supplied no threshold**, so some check made no finding. A fact about your REQUEST, not about the board — pass `--require-complete` to make it exit 2 |
154
+ | `2` | `not_healthy` | at least one check FAILED |
155
+ | `1` | — | transport, auth, a bad ref, or a verdict the CLI could not read |
156
+
157
+ ```bash
158
+ # A planner gate. `2` stops the run; `1` means the check itself could not be made.
159
+ opvs boards health "$BOARD" --profile planner-orchestration || exit $?
160
+ ```
161
+
162
+ 🔑 **`1` and `2` are deliberately different.** `2` is "the board failed"; `1` is "I could not
163
+ ask". A gate that treated them alike would pass an expired token off as a healthy board.
164
+
165
+ On `not_healthy` only the FAIL rows print — `--all-checks` brings the rest back. `--format json`
166
+ is the server's report verbatim (for `jq`); `--format md|yaml` is the server's own rendering, and
167
+ the exit code is still the verdict's.
168
+
134
169
  > ⚠️ **A factory board claims NOTHING until it is in exactly ONE active project.** Every claim on a
135
170
  > factory board in no project (`none`) or in two or more (`ambiguous`) returns
136
171
  > `{task_id: null, reason: "board_project_unresolved"}` — the columns can be perfectly wired and the
@@ -138,13 +173,35 @@ opvs boards update ASP --archived true # Hidden from `boards list`
138
173
  > `add-to-project`, `move-to-project`, `apply-preset`, `projects add-board | remove-board | archive`
139
174
  > all check afterwards and warn on stderr when a factory board is left unresolved.
140
175
 
176
+ > **Destructive commands ask first (ASP-144).** Every command that deletes, revokes, cancels or
177
+ > uninstalls something asks `[y/N]` at a terminal, and **off a terminal (an agent loop, CI, a pipe)
178
+ > it refuses and exits 1 unless you pass `--yes` / `-y`**. Examples here carry `--yes` because
179
+ > that is how an agent runs them. Not gated, because a sibling command undoes them and nothing is
180
+ > deleted: `projects archive` (`--undo`), `projects remove-board` (`add-board`), `mail daemon uninstall`
181
+ > (`mail daemon start`). `tests/commands/destructive-gate-asp144.test.ts` walks the built command tree
182
+ > and fails on a new destructive-named command without `--yes`.
183
+
184
+ ### Scheduled runs
185
+
186
+ ```bash
187
+ opvs scheduled-runs list [--project <uuid>] [--board <uuid>] [--state scheduled|fired|failed|cancelled|all] [--limit 100]
188
+ opvs scheduled-runs get <id> # state, fired_at, last_error
189
+ opvs scheduled-runs create --project <uuid> --run-at 2026-09-17T08:00:00Z [--board <uuid>] [--params '{"note":"nightly"}']
190
+ opvs scheduled-runs cancel <id> --yes # only a run that has not fired
191
+ ```
192
+ > Scheduling costs nothing. At `--run-at` (the scanner sweeps about once a minute) the project, or one
193
+ > board, is **armed** exactly as ▶ Play arms it (`ProjectRunService.arm`): the factory starts claiming its
194
+ > cards, those builds spend, and it stays armed until paused or stopped. `create` and `cancel` are brand
195
+ > admin only (403). `--run-at` must carry a zone (`Z` or `+02:00`); ids are full UUIDs. Cancel never disarms
196
+ > a run that already fired — it returns the row unchanged, and the CLI says so.
197
+
141
198
  ### Members
142
199
 
143
200
  ```bash
144
201
  opvs members list <boardId>
145
202
  opvs members add <boardId> --user <uuid> # or --agent <uuid>; a member of YOUR brand
146
203
  opvs members invite <boardId> --email x@y.com --role commenter # outside your brand → a guest of this board
147
- opvs members remove <boardId> <uuid> --type agent # --type defaults to user
204
+ opvs members remove <boardId> <uuid> --type agent --yes # --type defaults to user
148
205
  ```
149
206
 
150
207
  > `--role` (viewer | commenter | editor) caps an **external guest** only; a member of your own brand
@@ -167,7 +224,7 @@ opvs columns update <columnId> --wip-limit none # 'none' clears;
167
224
 
168
225
  ```bash
169
226
  opvs projects set-routing <project-uuid> --model claude-opus-5
170
- opvs projects health <project-uuid> --profile planner-orchestration
227
+ opvs projects health <project-uuid> --profile planner-orchestration # EXITS 2 on not_healthy
171
228
  opvs projects bundle set <project-uuid> --command ship --command-body ship=./ship.md # a body map REPLACES
172
229
  ```
173
230
 
@@ -209,6 +266,28 @@ opvs docs update <project> <slug> -f content.md
209
266
  opvs docs search "query" # Search docs
210
267
  ```
211
268
 
269
+ ### Code index
270
+
271
+ ```bash
272
+ # "Does this already exist?" — ask BEFORE writing it.
273
+ opvs code context "resolve_brand" --project <project-id>
274
+ opvs code context "resolveBrand" --project <id> --kind function --limit 5
275
+ opvs code summary --project <project-id> # Repo orientation: languages, entry points, top files
276
+ ```
277
+
278
+ Two answers you must not conflate: `indexed: false` means *there was nothing to
279
+ search* (no index for this project, or it is not yours), while `verdict: none`
280
+ means *we searched and found nothing*. Only the second is evidence of absence.
281
+ A capped result set says so — read `truncated`, and read
282
+ `freshness.index_truncated` separately: that one means the index is partial.
283
+ `freshness.scan_truncated` says the SCAN stopped early, so parts of the repo were
284
+ never read at all; `freshness.symbols_dropped_at_ingest` counts symbols the API
285
+ could not store, from files that were read.
286
+
287
+ Needs the `code:read` scope, which is in the default ceiling. There is no
288
+ `opvs code index` command on purpose — writing an index is `code:write`, which
289
+ a worker PAT does not carry, and the ingest caller is the sidecar on the desk.
290
+
212
291
  ### Session
213
292
 
214
293
  ```bash
@@ -231,8 +310,9 @@ opvs init # Print CLAUDE.md snippet
231
310
 
232
311
  ```bash
233
312
  opvs auth request -w <slug> -e <email> # Request token
313
+ opvs auth resume # Collect a token approved after the wait
234
314
  opvs auth status # Current auth info
235
- opvs auth revoke # Revoke token
315
+ opvs auth revoke --yes # Revoke token
236
316
  opvs auth list # List agent tokens (admin)
237
317
  ```
238
318
 
@@ -252,7 +332,7 @@ opvs tools help @opvs-ai/agentboard --section methods # Just the methods
252
332
  opvs tools list # Installed packages on this brand
253
333
  opvs tools install @opvs-ai/agentboard \
254
334
  --grants '{"vendor.opvs-ai.agentboard.read":true}' # Install with entitlements
255
- opvs tools uninstall @opvs-ai/agentboard # Soft-uninstall
335
+ opvs tools uninstall @opvs-ai/agentboard --yes # Soft-uninstall
256
336
 
257
337
  # Invoke
258
338
  opvs tools call @opvs-ai/agentboard list_tasks \
@@ -270,7 +350,7 @@ gateway plugin `skill_pin` tool is the canonical surface.
270
350
  opvs workspace list # List all workspaces
271
351
  opvs workspace use <slug> # Switch current workspace
272
352
  opvs workspace current # Show current workspace details
273
- opvs workspace remove <slug> # Remove a saved workspace
353
+ opvs workspace remove <slug> --yes # Remove a saved workspace
274
354
  ```
275
355
 
276
356
  ## YAML Output
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "stamp_version": 1,
3
3
  "package": "@opvs-ai/cli",
4
- "version": "0.16.0",
5
- "source_digest": "4d5002b9cebabfe3ca99d102e5d83e94161b9464cfefccf1c77f2da8f8aa8b43",
6
- "source_files": 41,
7
- "built_at": "2026-09-16T09:59:57.093Z",
8
- "node": "v22.22.0"
4
+ "version": "0.20.1",
5
+ "source_digest": "5f2aeb431e9a054d49cf81631229a8b256b90a0120ea1b37ce860dfccf7302ca",
6
+ "source_files": 44,
7
+ "built_at": "2026-09-28T13:58:06.956Z",
8
+ "node": "v22.23.2"
9
9
  }
@@ -71,7 +71,7 @@ export function registerAgentCommands(program) {
71
71
  agent
72
72
  .command("batch-create")
73
73
  .description("Create multiple tasks at once from a JSON file")
74
- .requiredOption("--file <path>", "JSON file with array of task objects (board_id, title, description, priority)")
74
+ .requiredOption("--file <path>", "JSON file with an array of task objects: board_id and title required; column_id, description, priority, agent_instructions optional")
75
75
  .action(async (opts) => {
76
76
  const wsSlug = program.opts().workspace;
77
77
  try {
@@ -173,14 +173,15 @@ export function registerAgentCommands(program) {
173
173
  .command("mention <taskId>")
174
174
  .description("@mention an agent on a task (triggers agent to respond)")
175
175
  .requiredOption("--agent <slug>", "Agent slug to mention")
176
- .option("--message <text>", "Message for the agent")
176
+ // Required: the gateway answers `400 agent_slug and message are required`
177
+ // without one, so an optional flag only moved the failure to the server
178
+ // (ASP-271).
179
+ .requiredOption("--message <text>", "Message for the agent")
177
180
  .action(async (taskId, opts) => {
178
181
  const wsSlug = program.opts().workspace;
179
182
  try {
180
183
  const client = createClient(wsSlug);
181
- const body = { agent_slug: opts.agent };
182
- if (opts.message)
183
- body.message = opts.message;
184
+ const body = { agent_slug: opts.agent, message: opts.message };
184
185
  const res = await client.post(`/api/v1/board/tasks/${taskId}/agent-mention`, body);
185
186
  const data = await res.json();
186
187
  printJson(data);
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"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"}
@@ -2,21 +2,205 @@
2
2
  * opvs auth — AI-native token provisioning + management
3
3
  */
4
4
  import { getEffectiveConfig, saveWorkspace, setCurrentWorkspace, loadRawConfig, apiUnauthPost, createClient, DEFAULT_WORKSPACE, } from "@opvs-ai/core";
5
+ /**
6
+ * Point `current_workspace` at `fallback` ONLY if the pointer is currently
7
+ * empty or dangling.
8
+ *
9
+ * `auth request` used to call `setCurrentWorkspace(workspaces[0].brand_slug)`
10
+ * unconditionally, so re-authing to refresh an expiring token silently moved
11
+ * the CLI to whichever brand the server happened to list first. Everything
12
+ * after that ran against the wrong brand while still looking right: the very
13
+ * next command reported `skill '@opvs-ai/agentmemory' is not installed on
14
+ * this brand`, which is true of the brand it had been moved to and false of
15
+ * the one the operator thought they were on. Reported by @di-atomic
16
+ * 2026-09-21.
17
+ *
18
+ * The workspace pointer is sticky state. `opvs workspace use <slug>` is what
19
+ * changes it; re-authenticating is not. (`saveWorkspace` already has exactly
20
+ * these semantics — it sets current only when none is set. This makes the
21
+ * explicit call agree with it instead of overriding it.)
22
+ *
23
+ * Returns the slug that is current afterwards, so the caller can print it —
24
+ * a workspace pointer you cannot see is how this went unnoticed.
25
+ */
26
+ function ensureCurrentWorkspace(fallback) {
27
+ const cfg = loadRawConfig();
28
+ const existing = cfg.current_workspace;
29
+ if (existing && cfg.workspaces[existing])
30
+ return existing;
31
+ setCurrentWorkspace(fallback);
32
+ return fallback;
33
+ }
5
34
  import { buildFingerprint } from "../lib/fingerprint.js";
6
35
  import { pollForApproval } from "../lib/auth-poll.js";
36
+ import { clearPendingAuth, loadPendingAuth, savePendingAuth, } from "../lib/pending-auth.js";
7
37
  import { printJson } from "../lib/format.js";
38
+ import { confirmOrExit, YES_HELP } from "../lib/confirm.js";
39
+ const WAIT_HELP = "Minutes to wait here for the approval before handing off to `opvs auth resume` " +
40
+ "(default: 5). The request itself stays approvable on the server for longer.";
41
+ /**
42
+ * `--wait <minutes>` → milliseconds. `undefined` when the flag is absent (the poll
43
+ * loop's own default applies); `null` when it is not a positive number.
44
+ */
45
+ function parseWaitMinutes(value) {
46
+ if (value === undefined)
47
+ return undefined;
48
+ const minutes = Number(value);
49
+ if (!Number.isFinite(minutes) || minutes <= 0)
50
+ return null;
51
+ return Math.round(minutes * 60_000);
52
+ }
53
+ /**
54
+ * Save the request for `opvs auth resume` BEFORE the first poll, so a process
55
+ * killed mid-wait (an agent's tool-call timeout) still leaves it collectable.
56
+ * A failure to save must not cost the login itself — it only loses the resume.
57
+ */
58
+ function rememberPending(fields) {
59
+ const pending = { ...fields, created_at: new Date().toISOString() };
60
+ try {
61
+ savePendingAuth(pending);
62
+ }
63
+ catch (err) {
64
+ const msg = err instanceof Error ? err.message : String(err);
65
+ process.stderr.write(`Warning: could not save this request for \`opvs auth resume\` (${msg}). ` +
66
+ "If the wait below ends before it is approved, request access again.\n");
67
+ }
68
+ return pending;
69
+ }
70
+ function forgetPending() {
71
+ try {
72
+ clearPendingAuth();
73
+ }
74
+ catch {
75
+ /* nothing to clean up is not an error */
76
+ }
77
+ }
78
+ function handoffMessage(pending, now = Date.now()) {
79
+ const who = pending.owner_email ? `The approval email went to ${pending.owner_email}. ` : "";
80
+ const expiry = new Date(pending.expires_at).getTime();
81
+ if (Number.isFinite(expiry) && expiry > now) {
82
+ const minutes = Math.max(1, Math.ceil((expiry - now) / 60_000));
83
+ return (`Not approved yet. The request stays open for about ${minutes} more minute${minutes === 1 ? "" : "s"} ` +
84
+ `(until ${pending.expires_at}).\n${who}Once it has been approved, run:\n opvs auth resume`);
85
+ }
86
+ return `Not approved yet. ${who}If it is approved in time, run:\n opvs auth resume`;
87
+ }
88
+ /**
89
+ * Turn a poll result into saved credentials and a message — shared by
90
+ * `auth request` and `auth resume`, so a late approval ends exactly like a
91
+ * prompt one. The saved request is dropped on every final answer and kept only
92
+ * while the server may still approve it.
93
+ */
94
+ function settleApproval(result, pending) {
95
+ const baseUrl = pending.api_url;
96
+ const wsSlug = pending.workspace_slug;
97
+ if (result.status === "active" && wsSlug && result.token) {
98
+ saveWorkspace(wsSlug, {
99
+ api_url: baseUrl,
100
+ token: result.token,
101
+ brand_id: result.brand_id ?? null,
102
+ brand_name: result.brand_name ?? "",
103
+ });
104
+ forgetPending();
105
+ const current = ensureCurrentWorkspace(wsSlug);
106
+ console.log(`\nAuthenticated! Token saved to workspace "${wsSlug}".`);
107
+ console.log(`Brand: ${result.brand_name} (ID: ${result.brand_id})`);
108
+ console.log(`Scopes: ${result.scopes?.join(", ")}`);
109
+ console.log(current === wsSlug
110
+ ? `Current workspace: ${current}`
111
+ : `Current workspace: ${current} (unchanged — "opvs workspace use ${wsSlug}" to switch)`);
112
+ return;
113
+ }
114
+ if (result.status === "active" && !wsSlug && result.workspaces?.length) {
115
+ // Save each workspace
116
+ for (const ws of result.workspaces) {
117
+ saveWorkspace(ws.brand_slug, {
118
+ api_url: baseUrl,
119
+ token: ws.token,
120
+ brand_id: ws.brand_id,
121
+ brand_name: ws.brand_name,
122
+ });
123
+ }
124
+ forgetPending();
125
+ // Keep whatever workspace was already current — re-authing is not
126
+ // a request to switch brands. Falls back to the first only when
127
+ // there is no usable pointer yet (first auth on this machine).
128
+ const current = ensureCurrentWorkspace(result.workspaces[0].brand_slug);
129
+ const slugs = result.workspaces.map((ws) => ws.brand_slug).join(", ");
130
+ console.log(`\nAuthenticated! ${result.workspaces.length} workspace${result.workspaces.length !== 1 ? "s" : ""} configured: ${slugs}`);
131
+ for (const ws of result.workspaces) {
132
+ // Print the granted scopes per workspace — each token is clamped to its
133
+ // own workspace's policy, so they are not necessarily what was asked for
134
+ // and are not necessarily the same across workspaces.
135
+ const granted = ws.scopes?.length ? ws.scopes.join(", ") : "(none)";
136
+ const marker = ws.brand_slug === current ? " [current]" : "";
137
+ console.log(` ${ws.brand_slug}: ${ws.brand_name} (ID: ${ws.brand_id})${marker}`);
138
+ console.log(` scopes: ${granted}`);
139
+ }
140
+ console.log(`\nCurrent workspace: ${current} — unchanged by this command. ` +
141
+ `Switch with "opvs workspace use <slug>".`);
142
+ return;
143
+ }
144
+ if (result.status === "active" && !wsSlug && result.token) {
145
+ // Fallback: server returned single-brand format
146
+ const slug = pending.brands?.[0]?.brand_slug || "default";
147
+ saveWorkspace(slug, {
148
+ api_url: baseUrl,
149
+ token: result.token,
150
+ brand_id: result.brand_id ?? null,
151
+ brand_name: result.brand_name ?? "",
152
+ });
153
+ forgetPending();
154
+ const currentFb = ensureCurrentWorkspace(slug);
155
+ console.log(`\nAuthenticated! Token saved to workspace "${slug}".`);
156
+ console.log(`Current workspace: ${currentFb}`);
157
+ return;
158
+ }
159
+ if (result.status === "denied") {
160
+ forgetPending();
161
+ console.error("\nAccess denied by the workspace admin. Check with them before requesting again.");
162
+ process.exit(1);
163
+ return;
164
+ }
165
+ if (result.status === "expired") {
166
+ forgetPending();
167
+ console.error("\nRequest expired before it was approved, so nothing was granted.\n" +
168
+ "Run `opvs auth request` again, and approve the newest email.");
169
+ process.exit(1);
170
+ return;
171
+ }
172
+ if (result.status === "invalid") {
173
+ forgetPending();
174
+ console.error("\nThe server no longer recognises this request. Run `opvs auth request` to start a new one.");
175
+ process.exit(1);
176
+ return;
177
+ }
178
+ // Not decided yet — or approved, but the token has not arrived yet. Either
179
+ // way the request can still be collected; keep it, and say how.
180
+ console.error(`\n${handoffMessage(pending)}`);
181
+ process.exit(2);
182
+ }
8
183
  export function registerAuthCommands(program) {
9
184
  const auth = program.command("auth").description("Token authentication");
10
185
  auth
11
186
  .command("request")
12
- .description("Request a PAT token (sends approval email to admin)")
187
+ .description("Request a PAT token (sends an approval email to the workspace admin). Waits here for the approval, " +
188
+ "then hands off — the request stays approvable on the server for longer, and `opvs auth resume` " +
189
+ "collects the token. Exit codes: 0 approved · 1 denied, expired or failed · 2 not approved yet.")
13
190
  .requiredOption("-e, --email <email>", "Admin email (who approves)")
14
191
  .option("-p, --project <name>", "Project name (shown in approval email)")
15
192
  .option("-s, --scopes <scopes>", "Comma-separated scopes to request (default: the workspace's standard agent scopes)")
16
193
  .option("-t, --ttl <hours>", "Token TTL in hours (omit for no expiry)")
17
194
  .option("--api-url <url>", "API base URL (overrides config)")
195
+ .option("--wait <minutes>", WAIT_HELP)
18
196
  .action(async (opts) => {
19
197
  const wsSlug = program.opts().workspace;
198
+ const waitMs = parseWaitMinutes(opts.wait);
199
+ if (waitMs === null) {
200
+ console.error("Error: --wait takes a number of minutes greater than 0");
201
+ process.exit(1);
202
+ return;
203
+ }
20
204
  const config = loadRawConfig();
21
205
  const fingerprint = buildFingerprint();
22
206
  // No client-side default. This used to be hard-coded to "board:read,board:write",
@@ -47,31 +231,17 @@ export function registerAuthCommands(program) {
47
231
  const { request_id, poll_token, expires_at } = data;
48
232
  console.log(`Request ID: ${request_id}`);
49
233
  console.log(`Expires: ${expires_at}`);
50
- const result = await pollForApproval(baseUrl, request_id, poll_token);
51
- if (result.status === "active" && result.token) {
52
- saveWorkspace(wsSlug, {
53
- api_url: baseUrl,
54
- token: result.token,
55
- brand_id: result.brand_id ?? null,
56
- brand_name: result.brand_name ?? "",
57
- });
58
- setCurrentWorkspace(wsSlug);
59
- console.log(`\nAuthenticated! Token saved to workspace "${wsSlug}".`);
60
- console.log(`Brand: ${result.brand_name} (ID: ${result.brand_id})`);
61
- console.log(`Scopes: ${result.scopes?.join(", ")}`);
62
- }
63
- else if (result.status === "denied") {
64
- console.error("\nAccess denied by workspace owner.");
65
- process.exit(1);
66
- }
67
- else if (result.status === "expired") {
68
- console.error("\nRequest expired. Try again.");
69
- process.exit(1);
70
- }
71
- else {
72
- console.error("\nRequest timed out. The owner may not have seen the email.");
73
- process.exit(1);
74
- }
234
+ const pending = rememberPending({
235
+ request_id,
236
+ poll_token,
237
+ api_url: baseUrl,
238
+ expires_at,
239
+ owner_email: opts.email,
240
+ workspace_slug: wsSlug,
241
+ brands: [],
242
+ });
243
+ const result = await pollForApproval(baseUrl, request_id, poll_token, waitMs, expires_at);
244
+ settleApproval(result, pending);
75
245
  }
76
246
  catch (err) {
77
247
  const e = err;
@@ -96,54 +266,17 @@ export function registerAuthCommands(program) {
96
266
  console.log(`Found ${brandCount} workspace${brandCount !== 1 ? "s" : ""}. Approval email sent to ${opts.email}`);
97
267
  console.log(`Request ID: ${request_id}`);
98
268
  console.log(`Expires: ${expires_at}`);
99
- const result = await pollForApproval(baseUrl, request_id, poll_token);
100
- if (result.status === "active" && result.workspaces?.length) {
101
- // Save each workspace
102
- for (const ws of result.workspaces) {
103
- saveWorkspace(ws.brand_slug, {
104
- api_url: baseUrl,
105
- token: ws.token,
106
- brand_id: ws.brand_id,
107
- brand_name: ws.brand_name,
108
- });
109
- }
110
- // Set the first workspace as current
111
- setCurrentWorkspace(result.workspaces[0].brand_slug);
112
- const slugs = result.workspaces.map((ws) => ws.brand_slug).join(", ");
113
- console.log(`\nAuthenticated! ${result.workspaces.length} workspace${result.workspaces.length !== 1 ? "s" : ""} configured: ${slugs}`);
114
- for (const ws of result.workspaces) {
115
- // Print the granted scopes per workspace — each token is clamped to its
116
- // own workspace's policy, so they are not necessarily what was asked for
117
- // and are not necessarily the same across workspaces.
118
- const granted = ws.scopes?.length ? ws.scopes.join(", ") : "(none)";
119
- console.log(` ${ws.brand_slug}: ${ws.brand_name} (ID: ${ws.brand_id})`);
120
- console.log(` scopes: ${granted}`);
121
- }
122
- }
123
- else if (result.status === "active" && result.token) {
124
- // Fallback: server returned single-brand format
125
- const slug = brands?.[0]?.brand_slug || "default";
126
- saveWorkspace(slug, {
127
- api_url: baseUrl,
128
- token: result.token,
129
- brand_id: result.brand_id ?? null,
130
- brand_name: result.brand_name ?? "",
131
- });
132
- setCurrentWorkspace(slug);
133
- console.log(`\nAuthenticated! Token saved to workspace "${slug}".`);
134
- }
135
- else if (result.status === "denied") {
136
- console.error("\nAccess denied by admin.");
137
- process.exit(1);
138
- }
139
- else if (result.status === "expired") {
140
- console.error("\nRequest expired. Try again.");
141
- process.exit(1);
142
- }
143
- else {
144
- console.error("\nRequest timed out. The admin may not have seen the email.");
145
- process.exit(1);
146
- }
269
+ const pending = rememberPending({
270
+ request_id,
271
+ poll_token,
272
+ api_url: baseUrl,
273
+ expires_at,
274
+ owner_email: opts.email,
275
+ workspace_slug: null,
276
+ brands: brands ?? [],
277
+ });
278
+ const result = await pollForApproval(baseUrl, request_id, poll_token, waitMs, expires_at);
279
+ settleApproval(result, pending);
147
280
  }
148
281
  catch (err) {
149
282
  const e = err;
@@ -152,6 +285,30 @@ export function registerAuthCommands(program) {
152
285
  }
153
286
  }
154
287
  });
288
+ auth
289
+ .command("resume")
290
+ .description("Collect the token for the last `auth request` on this machine — for an approval that came after " +
291
+ "it stopped waiting. Same exit codes as `auth request`.")
292
+ .option("--wait <minutes>", WAIT_HELP)
293
+ .action(async (opts) => {
294
+ const waitMs = parseWaitMinutes(opts.wait);
295
+ if (waitMs === null) {
296
+ console.error("Error: --wait takes a number of minutes greater than 0");
297
+ process.exit(1);
298
+ return;
299
+ }
300
+ const pending = loadPendingAuth();
301
+ if (!pending) {
302
+ console.error("No pending access request on this machine. Run `opvs auth request` to start one.");
303
+ process.exit(1);
304
+ return;
305
+ }
306
+ console.log(`Resuming request ${pending.request_id}` +
307
+ (pending.owner_email ? ` (approval email: ${pending.owner_email})` : "") +
308
+ ".");
309
+ const result = await pollForApproval(pending.api_url, pending.request_id, pending.poll_token, waitMs, pending.expires_at);
310
+ settleApproval(result, pending);
311
+ });
155
312
  auth
156
313
  .command("status")
157
314
  .description("Show current authentication status")
@@ -181,9 +338,22 @@ export function registerAuthCommands(program) {
181
338
  });
182
339
  auth
183
340
  .command("revoke")
184
- .description("Revoke the token for the current workspace")
185
- .action(async () => {
341
+ .description("Revoke the token for the current workspace, on the server and on this machine. Asks first; needs --yes off a terminal.")
342
+ .option("-y, --yes", YES_HELP)
343
+ .action(async (opts) => {
186
344
  const wsSlug = program.opts().workspace;
345
+ // Ask OUTSIDE the try below: its catch clears the local token, so a
346
+ // refusal raised inside it would be handled as a failed revoke.
347
+ let hasToken = false;
348
+ try {
349
+ hasToken = Boolean(getEffectiveConfig(wsSlug).token);
350
+ }
351
+ catch {
352
+ /* the try below reports a config error */
353
+ }
354
+ if (hasToken) {
355
+ await confirmOrExit("Revoke this workspace's token?", opts.yes, "It stops working at once, and getting another needs a new `opvs auth request` and an approval");
356
+ }
187
357
  try {
188
358
  const cfg = getEffectiveConfig(wsSlug);
189
359
  if (!cfg.token) {