@go-labs-sg/bb 2.48.0 → 3.1.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.
- package/README.md +131 -15
- package/command-manifest.json +3149 -563
- package/command-reference.md +359 -31
- package/dist/index.js +2604 -753
- package/package.json +2 -2
- package/role-aware-agent-guide.md +7 -0
package/README.md
CHANGED
|
@@ -24,19 +24,115 @@ For AI agents using this CLI: do not execute mutations until the user explicitly
|
|
|
24
24
|
|
|
25
25
|
**Registry:** [`@go-labs-sg/bb`](https://www.npmjs.com/package/@go-labs-sg/bb)
|
|
26
26
|
|
|
27
|
+
## Supplier cursor pages and independent totals
|
|
28
|
+
|
|
29
|
+
`bb supplier list` (alias `list-suppliers`) returns rich `items` and `pageInfo` with opaque `nextCursor`, `previousCursor`, and directional availability. Use `--limit 1-100` (default 10), then pass a returned token unchanged with the same filters and sort. Previous navigation uses `--direction backward --cursor <previousCursor>`. Retired `--page`/`--perPage` flags are rejected; numbered/random-access pages are no longer supported.
|
|
30
|
+
|
|
31
|
+
`--sortBy` accepts `name`, `email`, `phone`, `gstRegistered`, `status`, `active`, `createdAt`, or `updatedAt`; `--sortDir` accepts `asc`/`desc`. Alternatively, `--sort '[{"id":"status","desc":false},{"id":"name","desc":false}]'` preserves multiple-column precedence. Do not combine both forms. Missing or changed live status-sort anchors produce a restart error, not an empty success.
|
|
32
|
+
|
|
33
|
+
`bb supplier count` (alias `count-suppliers`) calls `supplier.getSummary` independently: exact total, self-excluded GST/approval/active facets and the existing active-scoped tag facets. It accepts the same filters, not pagination or sort flags. Both commands default to active suppliers; use `--active false` for archived suppliers.
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
bb supplier list --limit 20 --name "ACME" --sortBy name --sortDir asc
|
|
37
|
+
bb supplier count --name "ACME"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Roll out the API and maintained CLI together: `suppliers`/`pageCount` and offset inputs are replaced by `items`/`pageInfo`. The separate supplier analytics endpoint is unchanged.
|
|
41
|
+
|
|
27
42
|
## Bill and claim list summaries
|
|
28
43
|
|
|
29
|
-
`bb bill list` / `bb claim list` (legacy `list-bills` / `list-claims`)
|
|
44
|
+
`bb bill list` / `bb claim list` (legacy `list-bills` / `list-claims`) read one bounded cursor page from summary-only `bill.getAll`: `--limit` (1–100, default 20), `--cursor` and `--direction forward|backward` return `{ items, pageInfo }`; follow `nextCursor`/`previousCursor` with the same filters and sort. `--page`, `--pageSize` and `--perPage` are rejected. Items carry summary fields, `isClaimable`, `lineItemCount` and `hasPendingApproval`. Totals, status facets (each ignoring its own status filter) and optional amount metrics come separately from `bb bill count` / `bb claim count` (`bill.getCounts`, `--includeMetrics true` for total/outstanding/pending-approval), which take filters only. Lists do not return attachment, detailed line-item or approval arrays, full supplier/budget/project/company records, or detail-only payment/integration/verification metadata.
|
|
30
45
|
|
|
31
46
|
**Breaking API migration:** `bill.getList` is removed completely, with no alias or fallback. Direct scripts reading the former rich `bill.getAll` response must adopt summaries and fetch selected bill/claim details with `bb get-bill-details <billId>`. Do not fetch details for every list row unless the task actually needs them. No rich-list flag or automatic detail expansion is added.
|
|
32
47
|
|
|
48
|
+
**Bill detail shape:** `bill.getById` / `bb get-bill-details` return only what the web bill pages read. Nested supplier, project, budget, people, attachments and approvals are narrowed to the displayed fields; supplier banking/provider data, contact people, catalogue descriptions and budget-item notes are not returned. Fetch line items, approvals, attachments or payment with `get-bill-line-items`, `get-bill-approvals`, `get-bill-attachments` or `get-bill-payment` only when a task needs them. Payment workflows (`update-bill-status --paymentProof`, `record-external-payment`) now read `bill.getPayment`.
|
|
49
|
+
|
|
50
|
+
**Quotation detail shape:** `quotation.getById` / `bb get-quotation` return only what the web quotation pages read: status, amounts, dates, project/company/budget/supplier names, people, line totals with budget-item name/description/quantity/cost, file roles and approvals. Signature placement metadata, raw supplier records and attachment audit fields are not returned. Use `get-quotation-line-items <quotationId>` (newest-first cursor pages, `--limit 1-100`, `--cursor`) for line-item supplier/budget/unit-price detail.
|
|
51
|
+
|
|
52
|
+
**Item detail shape:** `item.getItem` / `bb get-item` return the catalogue item's own fields (name, code, cost, rich-text description, GST flags, active/QuickBooks/availability state) with `supplier` narrowed to `{ id, name, gstRegistered, active, status }`, `itemCategory` to `{ id, name }` and attachments to `{ id, name, key, size }`. Full supplier and category records, plain-text `description`, `lowerCaseName` and the QuickBooks sync token are no longer included. `list-items` rows carry the list columns plus the same edit fields.
|
|
53
|
+
|
|
54
|
+
**Supplier detail shape:** `supplier.getSupplierById` / `bb get-supplier-details` keep every supplier field the detail page and pending-update diff compare (contact, banking, PayNow, payment/role/certification ids, address, pending update), with `createdBy` narrowed to `{ id, name, email, image, role }`, attachments to `{ id, name, key, size }`, payment method/role/certification/tags to `{ id, name }` and each catalogue item to `{ id, catalogueCode, name, cost, descriptionRichText, itemCategory { id, name }, _count }`. Approvals carry their ids, status, timestamps and approver/responder users, not budget/bill/quotation links. `lowerCaseName`, the QuickBooks id and sync token, and `createdById` are no longer included.
|
|
55
|
+
|
|
56
|
+
**Project detail shape:** `project.getProjectById` returns the project's own scheduling, ownership, Slack, Asana-task, QuickBooks and win fields plus the derived calendar, Asana and PM-membership fields, with `company { id, name }`, `asanaProject { gid, url }`, `insideSales`/`businessDevelopment`/`wonBy { id, name }`, `projectManager { id, name, email, bannedAt }` and `contactPerson { id, displayName, firstName, lastName }`. `project.getProjectDetailsById` / `bb get-project` returns the same project fields with only the derived Asana fields, `company { id, name }`, `asanaProject { gid, url }`, `wonBy { id, name }` and `contactPerson { id, displayName, firstName, lastName, email, mobile }`; it has no assignment relations, calendar or PM-membership fields. Both no longer include lost/override reasons, deal-automation and deal-lost bookkeeping columns, `winProofRequirement` or the payment-schedule lead days.
|
|
57
|
+
|
|
58
|
+
**Dashboard read shapes:** `get-dashboard`, `get-monthly-metrics` and `get-financial-overview` (and the web user dashboard) now read only the budget, item, discount and commission fields their totals use, and `get-estimate-performance` reads only budget status; their outputs are unchanged. The web-only `dashboard.getSupplierById` supplier read selects just the analytics card fields; its output is unchanged.
|
|
59
|
+
|
|
60
|
+
**Asana read shapes:** `asana.getAsanaTasks` returns the same sections and flattened task tree; its read now selects only the section and task fields it returns, not full task rows. The background Asana export reads only section and task titles and notes.
|
|
61
|
+
|
|
62
|
+
**Error-log read shapes:** `bb error recent list` / `bb get-recent-errors` items now carry only the table columns: `id, severity, status, message, errorName, errorType, component, route, action, createdAt` and `user { id, name, email }`. Stack, cause, request details, metadata, tags, AI summary and resolution moved to the new `bb error get <errorId>` / `bb get-error <errorId>` (`errorLog.getErrorById`), which no longer returns alert-group bookkeeping or the raw `userId`/`resolvedById` columns (use `user`/`resolvedByUser`).
|
|
63
|
+
|
|
64
|
+
**Company read shapes:** `company.getCompanyById` / `bb get-company` now return the company's own fields (`id, name, website, active, quickbooksId, createdById, createdAt, updatedAt`) without the embedded full `projects` array; use `bb list-projects --companyId <id>` for its projects. `bb list-companies` rows carry only `id, name, website, active, createdById, createdAt, updatedAt`, `createdBy { id, name, email, image }` and `_count`; use `bb get-company` for `quickbooksId`. Recent companies and the company QuickBooks sync status read only the fields they use; their outputs are unchanged.
|
|
65
|
+
|
|
66
|
+
**Customer-invoice readiness and quotation list loading:** `customerInvoice.getInvoiceReadiness`, `getInvoiceAmountPreview`, `getEligibleBudgets` and `getProjectInvoiceReadiness` read the budget through one selected shape (only the budget, project, contact, invoice-settings, discount and item fields the readiness and amount helpers use) with Prisma's default join instead of forced per-relation queries. The quotation list page and metrics reads also use the default join. Their outputs are unchanged.
|
|
67
|
+
|
|
68
|
+
**Bill item, quotation download and invoice-candidate reads:** `bill.getBudgetItemsForBill` / `getBudgetItemsForProject` rows now carry only the budget-item fields the bill, claim, quotation and line-item screens use: `item { id, catalogueCode }`, `supplier { id, name, gstRegistered, lowerCaseName }` (plus `address` on the project list for supplier verification), `itemCategory { id, name }`, and, on the project list only, `actualSpendings[] { id, amount, supplier }` (the bill list has no spendings). Neither is called by the CLI. `bb quotation pdf download` / `download-quotation-pdf` (`quotation.getSignedDownloadUrl`) returns `attachment { id, name, size, supplierQuotationFileRole }` with the signed `url`, without the internal storage key and row bookkeeping. `bb customer-invoice existing list` / `list-available-qbo-customer-invoices` (`customerInvoice.getExistingInvoiceCandidates`) reads only the budget state and project access fields; its output is unchanged.
|
|
69
|
+
|
|
70
|
+
**Project and item-category list read shapes:** `bb project list` / `bb list-projects` (`project.getAllProjects`) items keep every column the project table, cards and edit dialog use. They drop the deal-automation, calendar, Slack-message, win-override and lost-reason bookkeeping columns. Their relations narrow to `contactPerson { id, displayName, email }`, `company { id, name }`, `createdBy { id, name, email, image }` and `wonBy { id, name }`; `asanaProjectGid`/`asanaProjectUrl` are unchanged. Use `bb get-project <id>` for project details. `bb list-item-categories` rows carry `createdBy { id, name, email, image }` instead of the full user row.
|
|
71
|
+
|
|
72
|
+
**Customer invoice detail shape:** `customerInvoice.getInvoiceDetail` / `bb get-customer-invoice` return only what the web invoice page reads: batch status, totals, budget name, project permission ids, creator, approval approvers, operation/QuickBooks error state and per-invoice summaries (label, milestone, status, amounts, billing address, customer memo, email delivery). Invoice lines, history, QuickBooks ids/dates and full approval people are no longer included. Use `get-customer-invoice-invoices <batchId>`, `get-customer-invoice-lines <invoiceId>`, `get-customer-invoice-approvals <batchId>` and `get-customer-invoice-history <batchId>`; the last three are newest-first `{ items, pageInfo }` pages. `list-customer-invoices` rows likewise carry only the list columns (budget/project/company names, creator, invoice labels/doc numbers and amounts).
|
|
73
|
+
|
|
33
74
|
Coordinate the matching API/web deployment and CLI release/installations. MCP is deprecated and is not a rollout or acceptance gate. Published CLI builds still calling `getList` receive `NOT_FOUND` after API rollout, so a mixed-revision deployment is not compatible. Update those installations to the matching CLI release. Budget-list options are unchanged. This source change does not publish the CLI or deploy the API.
|
|
34
75
|
|
|
35
76
|
## Inventory list reads
|
|
36
77
|
|
|
37
|
-
`bb item list` / `bb list-items`
|
|
78
|
+
`bb item list` / `bb list-items` returns one cursor page of catalogue items, `{ items, pageInfo }`, newest first. Use `--limit` (1–100, default 20), `--cursor` and `--direction forward|backward`, keeping the same filters and sort; `--sortBy createdAt|updatedAt|name|cost|itemCategory|supplier` with `--sortDir asc|desc` picks the order. `--page` / `--perPage` are rejected. `bb item count` / `bb count-items` takes the same filters and returns `{ total, counts: { category, supplier } }`.
|
|
79
|
+
|
|
80
|
+
## Error-log pagination
|
|
81
|
+
|
|
82
|
+
`bb error recent list` / `bb get-recent-errors` now return a bounded `{ items, pageInfo }` without running an exact count. Use `--limit 1..100` (default 10), `--cursor '<returned token>'` and `--direction forward|backward`. Pass `nextCursor` forward or `previousCursor` backward, unchanged and with identical `--severity`, `--status` and `--timeFrame` filters. Omit the cursor to restart at the newest row. Legacy `--page` and `--perPage` are rejected rather than silently ignored.
|
|
83
|
+
|
|
84
|
+
`bb error recent count` / `bb count-errors` return independent `{ totalCount }` with the same filters. API/CLI/MCP default to `all_time`; the web retains its `last_30_days` default. MCP tools are `get_recent_errors`, `count_errors`, and independently scoped `get_error_metrics`. All require current administrator authorization.
|
|
85
|
+
|
|
86
|
+
This updates the existing error-list contract in place. Coordinate API, web, CLI and MCP rollout; old numbered-page clients must upgrade. Retain the existing chronological index: CockroachDB secondary indexes already append the primary key, so an additional `ErrorLog(createdAt, id)` index would duplicate its key ordering. Filter-specific indexes require representative plan/workload evidence before rollout. No database changes, deployment, CLI publication or measured RU savings are implied.
|
|
38
87
|
|
|
39
|
-
|
|
88
|
+
## Inbound source pagination
|
|
89
|
+
|
|
90
|
+
`bb inbound source list` / `bb list-inbound-sources` returns `{ sources, pageInfo }` without an exact count. Use `--limit 1..100` (default 25), `--cursor '<token>'`, and `--direction forward|backward`. Pass `nextCursor` forward or `previousCursor` backward without modifying it; omit the cursor to restart. Filters are `--search <name-or-form-id>`, `--processingEnabled true|false`, and `--processingMode ACTIVE|COLLECT_ONLY|SHADOW`.
|
|
91
|
+
|
|
92
|
+
`bb inbound source count` / `bb count-inbound-sources` returns independent `{ totalCount }` using the same filters, not pagination flags. Both commands remain Admin-only and Typeform-scoped. Legacy `--page`/`--perPage` and the numbered `pagination` envelope are removed; coordinate API/web and CLI upgrades. There is no silent offset fallback. Source order remains most recently updated first with an ID tie breaker; edits can move sources between live pages, so this is not a frozen export snapshot. No deployment, publication or measured RU savings are implied.
|
|
93
|
+
|
|
94
|
+
## Inbound submission pagination
|
|
95
|
+
|
|
96
|
+
`bb inbound submission list [--sourceId <id>] [--limit 25] [--cursor '<token>']`
|
|
97
|
+
(legacy `list-inbound-submissions`) now returns `{ submissions, hasMore, nextCursor }`.
|
|
98
|
+
Pass `nextCursor` back unchanged, with the same source filter, until it is `null`.
|
|
99
|
+
Omit the cursor to start again at the newest submissions. Limits are 1–100.
|
|
100
|
+
|
|
101
|
+
**Breaking pagination migration:** `--page` and `--perPage` are rejected; the
|
|
102
|
+
`pagination.totalCount`/`totalPages` envelope is removed. Request
|
|
103
|
+
`bb inbound submission count [--sourceId <id>]` (legacy `count-inbound-submissions`)
|
|
104
|
+
only when a total is needed. It returns `{ totalCount }`, independently of the list.
|
|
105
|
+
Both commands remain Admin-only. Cursor browsing is not a frozen export snapshot.
|
|
106
|
+
|
|
107
|
+
Deploy the API/web together before publishing the matching CLI. Older CLI clients
|
|
108
|
+
must upgrade before using this changed list; there is no silent offset fallback.
|
|
109
|
+
The web uses previous/next navigation and caches the separate total for reuse
|
|
110
|
+
(60-second freshness, not polling); Refresh rechecks the current page and total.
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
## Company list and count pagination
|
|
114
|
+
|
|
115
|
+
`bb company list` / `bb list-companies` now call `company.getCompanies` and return the complete `{ items, pageInfo }` response. Filters are `--name`, `--createdBy`, `--createdByIds <csv>`, and `--active true|false`. Sorting is `--sortBy name|createdAt` (project-count sorting was removed) and `--sortDir asc|desc`; defaults are `createdAt`, `desc`, and `--limit 20` (limit must be an integer from 1 through 100).
|
|
116
|
+
|
|
117
|
+
Cursors are opaque and scoped to the active account, filters, sort, and page width. Pass `pageInfo.nextCursor` unchanged with `--direction forward`, or `pageInfo.previousCursor` unchanged with `--direction backward`; backward requires `--cursor`. For example:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
bb company list --limit 20
|
|
121
|
+
bb company list --limit 20 --cursor '<nextCursor-from-the-previous-response>' --direction forward
|
|
122
|
+
bb company list --limit 20 --cursor '<previousCursor-from-the-previous-response>' --direction backward
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`bb company count` / `bb count-companies` call `company.getCompanyCounts` separately and return `{ totalCount, counts: { active: { true, false } } }`. Counts accept filters only; list pagination and sorting flags are rejected. Use count when a total is needed rather than walking every list page.
|
|
126
|
+
|
|
127
|
+
This is a breaking replacement for published company list clients that send `page`/`perPage` or expect a numbered-page response. Deploy the matching API before publishing the CLI, upgrade **all old published page clients**, and do not add an unbounded legacy shim or an all-pages loop. Canonical commands and legacy aliases remain available during the migration: `bb company list` / `bb list-companies`, and `bb company count` / `bb count-companies`.
|
|
128
|
+
|
|
129
|
+
## Project list and count pagination
|
|
130
|
+
|
|
131
|
+
`bb project list` / `bb list-projects` now call `project.getAllProjects` and return the complete `{ items, pageInfo }` response. Filters are `--companyId`, `--name`, legacy single-value `--status <status|ALL>`, optional `--statuses <csv>`, and `--active true|false`. Sorting is `--sortBy name|createdAt|status|companyName` and `--sortDir asc|desc`; defaults are `createdAt`, `desc`, and `--limit 20` (limit must be an integer from 1 through 100).
|
|
132
|
+
|
|
133
|
+
Cursors are opaque and scoped to the active account, filters, sort, and page width. Pass `pageInfo.nextCursor` unchanged with `--direction forward`, or `pageInfo.previousCursor` unchanged with `--direction backward`; backward requires `--cursor`. Legacy `--page` and `--perPage` are rejected rather than silently reinterpreted. For totals, use `bb project count` / `bb count-projects`, which call `project.getProjectCounts` independently and accept filters only; pagination and sorting flags are rejected. Counts return `{ totalCount, counts: { status, active: { true, false } } }`.
|
|
134
|
+
|
|
135
|
+
Deploy the matching API before publishing the CLI. Cursor browsing is not a frozen export snapshot; restart without the cursor when the API reports an expired or mismatched boundary.
|
|
40
136
|
|
|
41
137
|
## Company discovery and reuse
|
|
42
138
|
|
|
@@ -77,8 +173,14 @@ If `create-budget` reports an uncertain outcome (including Prisma P2028 or a net
|
|
|
77
173
|
|
|
78
174
|
A failed `create-supplier` request may likewise have committed. Inspect `bb list-suppliers --name <name>` and matching supplier details before retrying; names alone do not identify one attempt. If supplier creation succeeded but its separate approval request failed or returned no approval IDs, inspect that supplier's approvals by ID and retry only the approval step if needed. Do not create the supplier again. The CLI confirms the combined supplier-and-approval workflow before the first write.
|
|
79
175
|
|
|
176
|
+
`bb supplier create` (also `bb create-supplier`) cannot bypass supplier archive permissions. A matching archived name requires an Admin; normal users and Leads receive an authorization error before reactivation or replacement of the approved details. Permission flags do not grant a higher role. Ask an Admin to run `bb supplier reactivate --ids <supplierId>`, then use `bb supplier update` for edits under the normal review policy. Admin same-name recreation retains the existing approval status and creator; a rejected supplier still needs a separate Admin/Lead re-approval. Deploy this shared API guard before publishing the updated CLI help; older CLI versions also use the guarded mutation.
|
|
177
|
+
|
|
80
178
|
`create-budget-approval` and `create-estimate` accept `--companyPayload`, `--contactPayload`, and `--eventPayload` as JSON objects. The CLI rejects non-object JSON; the API validates required fields.
|
|
81
179
|
|
|
180
|
+
Budget approvals apply only to the current pending request: material edits and status changes supersede older pending requests. Refresh the budget and request approval again instead of retrying an old approval ID. `bb budget status update <id> APPROVED` requires a current Lead/Admin role; management permission, resource sharing and CLI permission flags do not grant approval authority. Existing Lead/Admin autoapproval remains available. If `bb quotation submit` or `bb quotation approve` conflicts after a concurrent ORIGINAL, amount or allocation change, refresh and review the current quotation before retrying. Both signing paths claim the captured revision and selection; a failed final approval claim rolls back the assigned decision, signed attachment and email/outbox writes. Deploy the shared API guards before publishing this CLI help. These fixes do not audit or repair historical decisions or signed documents.
|
|
181
|
+
|
|
182
|
+
`bb budget item supplier update --budgetItemId <id> --supplierId <id>` treats an eligible supplier/GST snapshot change as a material financial edit: it supersedes pending budget approvals and applies the standard budget/estimate reset policy. An identical supplier is a no-op. Refresh the budget and request approval again after an actual swap. Quotation signing also claims the exact selected allocation rows, so deleting an allocated budget item (including deletion during a budget restore) conflicts with an in-flight old submission or assigned final approval even if the parent quotation timestamp did not change. Existing capacity, bill-allocation deletion restrictions and attempt-specific cleanup are not bypassed.
|
|
183
|
+
|
|
82
184
|
`create-project` requires an existing Asana Deals lead task. In non-interactive runs pass `--asanaTaskId`; interactive runs can select a match with `--asanaSearch`. The Slack channel is resolved from the task unless all Slack channel flags are provided. For a new direct client, create the lead task in the website form first.
|
|
83
185
|
|
|
84
186
|
## Shared catalogue editing
|
|
@@ -137,8 +239,11 @@ bunx @go-labs-sg/bb <command>
|
|
|
137
239
|
Budget reads are active-only by default. The API enforces the historical-read permission; the CLI does not grant access based on the flag alone.
|
|
138
240
|
|
|
139
241
|
```bash
|
|
140
|
-
# Active budgets only (default)
|
|
242
|
+
# Active budgets only (default); one cursor page of { items, pageInfo }
|
|
141
243
|
bb list-budgets
|
|
244
|
+
bb list-budgets --limit 20 --cursor <nextCursor> --direction forward
|
|
245
|
+
# Totals plus status and active facets
|
|
246
|
+
bb count-budgets
|
|
142
247
|
bb get-budget <budget-id>
|
|
143
248
|
|
|
144
249
|
# Include inactive budgets; each form requires an ADMIN identity
|
|
@@ -149,6 +254,10 @@ bb get-budget-items <budget-id> --includeInactive
|
|
|
149
254
|
bb get-budget-details <budget-id> --includeInactive
|
|
150
255
|
```
|
|
151
256
|
|
|
257
|
+
`get-budget` and `get-budget-items` return every line item of the budget (`{ items, truncated, totals }`), not a page. `truncated` is true only past the 1,000-line safety cap. `totals` (item count, cost, total cost, total price, actual spending, pending approval) comes from `budget.getBudgetItemTotals`.
|
|
258
|
+
|
|
259
|
+
**Budget read shapes:** `get-budget` (`budget.getBudget`) now carries only the estimation grand total (`budgetEstimation.totals.grandTotal`); use `get-budget-details <budget-id>` (`budget.getBudgetDetail`) for the full estimation (plans, crew, validation, summary, assumptions, timeline, risks, recommendations). `get-budget-items` rows keep the editor fields (name, rich-text description/note, quantity, prices, flags, availability exception, bills, actual spending) with `supplier` narrowed to `{ id, name, gstRegistered, active, status }` and `itemCategory` to `{ id, name }`; plain-text `description`/`note`, timestamps and supplier contact/bank fields are no longer included.
|
|
260
|
+
|
|
152
261
|
`--active false` lists inactive budgets only. `--active all` lists active and inactive budgets. `--includeInactive` allows the three budget/detail/item commands to read inactive history. If the authenticated identity is not an Admin, the API rejects the historical request before reading budget data. For `get-budget`, the CLI requests the budget and its line items concurrently; each API read independently enforces the same active-only default and Admin-only historical opt-in.
|
|
153
262
|
|
|
154
263
|
## Secure credential storage
|
|
@@ -178,6 +287,13 @@ credentials through `Bun.secrets`. It never stores Google credentials. Use
|
|
|
178
287
|
`bb auth logout` to revoke the interactive session. For SSH or containers, pass
|
|
179
288
|
`--no-browser` and open the printed URL on another device.
|
|
180
289
|
|
|
290
|
+
The **CLI Sessions** screen uses the same self/admin list-and-revoke flow as the
|
|
291
|
+
other Go Labs apps. Its typed API is `cliAuth.list({ userId? })` and
|
|
292
|
+
`cliAuth.revoke({ sessionId, userId? })`: omitting `userId` targets the authenticated
|
|
293
|
+
user; targeting another user requires a Budget Builder admin. Revocation affects
|
|
294
|
+
only that device's CLI session and tokens, not automation API keys. Existing
|
|
295
|
+
`bb auth login`, `status`, `whoami`, and `logout` commands are unchanged.
|
|
296
|
+
|
|
181
297
|
Credentials use macOS Keychain, Windows Credential Manager, or Linux Secret Service, not plaintext files.
|
|
182
298
|
The per-user lock directory contains only random ownership markers used to serialize
|
|
183
299
|
login, refresh, and logout. macOS/Linux enforce owner-only POSIX permissions there;
|
|
@@ -296,7 +412,7 @@ Run `bb version` before agent-driven work to record the installed package versio
|
|
|
296
412
|
|
|
297
413
|
**Authoritative command list:** run `bb help` or inspect the generated `command-reference.md` / `command-manifest.json`. The catalog includes every canonical route, global option, and effect classification, but does not filter by the current `whoami` role. During the handler migration, command-specific arguments retain the compatibility dispatcher's validation and are explicitly marked `legacy-passthrough` in the manifest; use `bb help --legacy` for their detailed transition reference. Version 2 uses grouped, resource-first commands such as `bb budget list` and `bb bill attachment upload`. Flat commands such as `bb list-budgets` and their legacy `snake_case` aliases remain available during the v2 transition, with a deprecation notice and an equivalent grouped command in help. The CLI calls the shared tRPC API, including procedures also used by the web UI.
|
|
298
414
|
|
|
299
|
-
**Budget status automation:** Setting a budget to `ESTIMATE_ACCEPTED` requires a confirmed win-proof attachment. `--invoiceSettings '<json>'` remains available when the project needs saved delivery preferences, but invoice creation chooses its amount independently from those settings. If the parent project is `PITCH` or `LOST`, the API marks it `WON` automatically
|
|
415
|
+
**Budget status automation:** Setting a budget to `ESTIMATE_ACCEPTED` requires a confirmed win-proof attachment. `--invoiceSettings '<json>'` remains available when the project needs saved delivery preferences, but invoice creation chooses its amount independently from those settings. If the parent project is `PITCH` or `LOST`, the API marks it `WON` automatically, runs enabled Asana automation, and queues one project WON email to the BD, Inside Sales and PM with `ops@getout.sg` in CC (the same email is sent when `update-project-status` moves a `PITCH` or `LOST` project to `WON`). When rejecting the only accepted/closed budget on a commercial project, pass `--projectStatusOnCommercialRejection PITCH|LOST`.
|
|
300
416
|
|
|
301
417
|
### Typeform inbound administration
|
|
302
418
|
|
|
@@ -503,7 +619,7 @@ bb budget version list <budgetId> --all
|
|
|
503
619
|
|
|
504
620
|
The canonical backend procedure is `budgetVersion.getBudgetVersions`. It now accepts `{ budgetId, limit?, cursor? }` and returns `{ versions, nextCursor }`, with a default page size of 20 and maximum of 50. The former budgetId-only input remains valid, but returns the first page—not a complete-history array. **This response-shape and completeness change is breaking despite keeping the route name.** Older installed CLI builds and external scripts must consume `versions` and explicitly continue through `nextCursor`; otherwise they may fail or mistake partial history for a complete export. Deprecated MCP builds may also be incompatible, but they must not be updated or used as a rollout gate. Current CLI aliases `get-budget-versions` and `get_budget_versions` remain supported.
|
|
505
621
|
|
|
506
|
-
For direct tRPC clients, call `getBudgetVersions.query({ budgetId, limit: 20, cursor })`, consume `
|
|
622
|
+
For direct tRPC clients, call `getBudgetVersions.query({ budgetId, limit: 20, cursor })`, which returns `{ items, pageInfo: { hasNextPage, nextCursor } }` (list standardization); consume `items` and request the next page only when `pageInfo.nextCursor` is non-null. `cursor` is an opaque token bound to the budget and viewer role, not a version ID; a stale or mismatched token returns `BAD_REQUEST` and the export should restart. The CLI output keeps `{ versions, nextCursor }`. The intermediate `getBudgetVersionsPage` procedure is removed; migrate callers of that name to `getBudgetVersions` rather than retrying `NOT_FOUND`. A complete export must explicitly walk every page, abort on a failed page or repeated cursor, and emit success only after reaching the end; `bb budget version list <budgetId> --all` implements that traversal. Do not treat a first page as complete history. Cursors position by `createdAt` + `id`, so a deleted anchor version no longer breaks the next page; traversal is still not a snapshot, so versions written during an export may appear on later pages.
|
|
507
623
|
|
|
508
624
|
Coordinate the backend and maintained client rollout: publish/use this CLI only against a backend with the paginated `getBudgetVersions` contract; an older backend returns an array under that same name. MCP is deprecated and frozen, so do not update or publish it. Existing builds that call `getBudgetVersionsPage` must also migrate before that route is removed, including cached web bundles. The residual requester is not yet attributed: server timing logs prove route usage but do not identify its client or installed version. Reusing the route name bounds its history result; it does not prove complete-history consumers migrated, that a periodic schedule stopped, or that measured RU savings occurred. This source change does not publish clients, deploy the backend, delete audit snapshots or change indexes.
|
|
509
625
|
|
|
@@ -539,7 +655,7 @@ For `QBO_IMPORT` invoices, this existing command reads QBO and updates BB balanc
|
|
|
539
655
|
|
|
540
656
|
The Seatrium example must be previewed against live QBO again before an operator imports it. Previously observed invoice numbers and paid/open balances are not authorization or current-state evidence.
|
|
541
657
|
|
|
542
|
-
**Customer-invoice workflow parity:** `bb customer-invoice list` uses the same global/project
|
|
658
|
+
**Customer-invoice workflow parity:** `bb customer-invoice list` uses the same global/project cursor-page procedure as the web pages, and `bb customer-invoice count` returns the same totals, facets and metrics; omit filters for the global list or use `--projectId` for project scope. `bb customer-invoice send --payload '<json>'` uses the same protected email workflow as the web composer, sends to the payload's `to` address, saves that address as the project's configured billing email after a successful send, and marks the invoice `SENT`. `bb customer-invoice approve` and `bb customer-invoice reject` are Admin-only batch operations: callers select a batch ID, and the API resolves its internal pending Admin approval record. `bb customer-invoice sync` follows QuickBooks' paid state and zero balance, restoring `SENT` or `APPROVED` if that payment is reversed. Invoice approval refuses voided invoices and closes the estimate only when approved invoice coverage totals 100%; deletion, voiding, rejection, expiry, and QBO synchronization use the same estimate-reopening and live-payment guards as the web app. `bb customer-invoice void`, `delete` and `reject` print `{ batchId, batch, operation }`, where `batch` is the same shape as `get-customer-invoice` (or `null` once a delete completes); use `get-customer-invoice-invoices`, `-lines`, `-approvals` and `-history` for invoice lines, history and approval requester/responder.
|
|
543
659
|
|
|
544
660
|
For agent-driven invoice work, use this read-before-write sequence:
|
|
545
661
|
|
|
@@ -579,17 +695,17 @@ Admin/Lead users can run `bb supplier approve <supplierId>` to directly re-appro
|
|
|
579
695
|
|
|
580
696
|
| Area | Legacy handler labels (reference only; non-exhaustive) |
|
|
581
697
|
| --- | --- |
|
|
582
|
-
| **Budgets** | `list-budgets` (full payload by default; `--summary` or `--includeDetails false` for slim list), `get-budget`, `get-budget-items`, `get-budget-details`, `get-budget-categories
|
|
583
|
-
| **Bills / claims** | `list-bills` (`--isClaimable false` for bills, `--isClaimable true` for claims, omit for both), `list-claims` (claims only), `validate-bill-selection` (`--payload`, plus `--quotationIds q1,q2` or legacy `--quotationId q1`; validates the approved supplier and quotation coverage), `link-bill-quotations` (`<billId> --quotationIds q1,q2`; Admin source-link repair for eligible supplier bills), `stage-bill-attachment` (securely uploads invoice/payment-proof files before creation and returns attachment JSON; ownership and one-hour expiry are enforced by a server-side staged-upload record rather than encoded in the object key), `cleanup-staged-bill-attachments`, `create-bill` (`--payload`; set `isClaimable=false` for a bill and provide approved `quotationIds`, or use `--quotation-exempt` for an eligible server-validated exemption; set `isClaimable=true` for a claim without quotations; supplier bills require positive **before-GST** `extractedAmount` (full invoice subtotal) and `amount` (portion billed), with `amount <= extractedAmount`; line and quotation allocation amounts also exclude GST; an already-paid supplier bill sets `alreadyPaid=true` and requires `paymentReference` plus a staged PDF in `paymentProofAttachments`; admin creation automatically queues QBO finalization while other roles remain pending approval), `update-bill` (`--payload`), `update-bill-payment-evidence` (`--payload`; replaces the payment reference and payment-proof PDFs for an already-paid bill), `delete-bill`, `create-bill-approval` (also sends approval request emails), `update-bill-status` (`PAID` requires `--paymentReference`; pass `--paymentProof <receipt.pdf>` to stage and submit a PDF up to 20MB atomically, or omit it only when BB already has payment proof; moving to `PAID` runs the server's paid-bill notification workflow), `patch-bill-payment` (PAID bills: `--paymentTrackingUrl`, `--paymentReference`, `--quickbooksBillId`, `--paymentDate` ISO; clearing a paid bill's QuickBooks link is not allowed), `patch-bill-invoice-number`, `get-bill-attachments
|
|
584
|
-
| **Quotations** | `list-quotations` (
|
|
585
|
-
| **Customer invoices** | `check-customer-invoice-readiness`, `list-eligible-customer-invoice-budgets`, `preview-customer-invoice-amount`, `list-available-qbo-customer-invoices`, `list-customer-invoices` (global/project/budget filters
|
|
698
|
+
| **Budgets** | `list-budgets` (full payload by default; `--summary` or `--includeDetails false` for slim list), `get-budget`, `get-budget-items`, `get-budget-details`, `get-budget-categories` (forward cursor pages of active categories, name A–Z: `--q` / `--limit` / `--cursor`; returns `{ items, pageInfo }`), `get-budget-versions`, `rename-budget-version`, `restore-budget-version`, `update-budget-status` (`ESTIMATE_ACCEPTED` requires win proof, auto-marks `PITCH` or `LOST` projects `WON`, and auto-creates an Asana Event Ops section from Prompt 5 tasks when enabled; Prompt 5 skips quantity-zero items, combines matching non-GO-internal suppliers, keeps each GO internal item separate, removes generated work that repeats another line item or group, adds 5 mandatory supplier subtasks ending in "Get bill and upload to Budget Builder", and sets no subtask due dates; `--projectStatusOnCommercialRejection PITCH\|LOST` is required when rejecting the only accepted/closed budget on a commercial project), `mark-budget-won` (`<budgetId>` + proof file path; `PITCH` or `LOST` projects become `WON` automatically), `create-budget` / `update-budget` (`--payload`; cloned unavailable lines require `unavailableItemReviewAcknowledged: true`), `delete-budget`, `create-budget-approval` (also sends approval request emails), `create-estimate`, `send-estimate-to-contact-person` (same contact-person email workflow as web), `add-budget-items`, `update-budget-item`, `replace-budget-item`, `approve-unavailable-item-exception` (Lead/Admin), `remove-budget-item`, `reorder-budget-items`, `update-budget-item-supplier`, `mark-budget-items-not-utilized`, `restore-budget-item`, `create-placeholder-bill` (admin recovery), `create-budget-category`, `update-budget-category`, `delete-budget-category`, `update-budget-commission`, `delete-budget-commission`, `update-budget-discount`, `delete-budget-discount` (`--payload` where noted), `upload-budget-attachment` (`<budgetId>` + local file path; uses `attachment.requestBudgetAttachmentUpload` + PUT + `attachment.confirmBudgetAttachment`) |
|
|
699
|
+
| **Bills / claims** | `list-bills` (`--isClaimable false` for bills, `--isClaimable true` for claims, omit for both), `list-claims` (claims only), `validate-bill-selection` (`--payload`, plus `--quotationIds q1,q2` or legacy `--quotationId q1`; validates the approved supplier and quotation coverage), `link-bill-quotations` (`<billId> --quotationIds q1,q2`; Admin source-link repair for eligible supplier bills), `stage-bill-attachment` (securely uploads invoice/payment-proof files before creation and returns attachment JSON; ownership and one-hour expiry are enforced by a server-side staged-upload record rather than encoded in the object key), `cleanup-staged-bill-attachments`, `create-bill` (`--payload`; set `isClaimable=false` for a bill and provide approved `quotationIds`, or use `--quotation-exempt` for an eligible server-validated exemption; set `isClaimable=true` for a claim without quotations; supplier bills require positive **before-GST** `extractedAmount` (full invoice subtotal) and `amount` (portion billed), with `amount <= extractedAmount`; line and quotation allocation amounts also exclude GST; an already-paid supplier bill sets `alreadyPaid=true` and requires `paymentReference` plus a staged PDF in `paymentProofAttachments`; admin creation automatically queues QBO finalization while other roles remain pending approval), `update-bill` (`--payload`), `update-bill-payment-evidence` (`--payload`; replaces the payment reference and payment-proof PDFs for an already-paid bill), `delete-bill`, `create-bill-approval` (also sends approval request emails), `update-bill-status` (`PAID` requires `--paymentReference`; pass `--paymentProof <receipt.pdf>` to stage and submit a PDF up to 20MB atomically, or omit it only when BB already has payment proof; moving to `PAID` runs the server's paid-bill notification workflow), `patch-bill-payment` (PAID bills: `--paymentTrackingUrl`, `--paymentReference`, `--quickbooksBillId`, `--paymentDate` ISO; clearing a paid bill's QuickBooks link is not allowed), `patch-bill-invoice-number`, `get-bill-attachments` (newest-first cursor pages: `--limit` 1–50, `--cursor`; returns `{ items, pageInfo }`), `upload-bill-attachment` (`<billId>` + local path), `get-bill-details` (the web bill summary: status, amounts, people, payment, line totals), `get-bill-line-items` / `get-bill-approvals` (newest-first cursor pages: `--limit`, `--cursor`; `{ items, pageInfo }`), `get-bill-payment` (payment status, reference, date, tracking URL, QuickBooks link, external payment) |
|
|
700
|
+
| **Quotations** | `list-quotations` (project, budget, supplier, status, requester and text-search filters; newest-first cursor pages via `--limit` / `--cursor` / `--direction` returning `{ items, pageInfo }`; `--page` / `--perPage` / `--pageSize` are rejected), `count-quotations` (`quotation.getCounts`: filters only, returns `totalCount`, status facets that ignore their own status filter, and `--includeMetrics true` amount metrics), `get-quotation` (web quotation shape), `get-quotation-line-items` (`<quotationId>`; newest-first cursor pages, `--limit 1-100`, `--cursor`), `upload-quotation-attachment` (`<projectId>` + PDF/JPEG/PNG path up to 20MB; returns attachment JSON for payload use), `cleanup-staged-quotation-attachments`, `create-quotation` (`--payload` for `quotation.createDraft`; include `amountWithoutGst`, `gstAmount`, and `lineAmounts` entries `{ budgetItemId, amount }` for multiple selected items), `update-quotation` (`--payload`; updates a `DRAFT` or `REJECTED` quotation), `delete-quotation`, `submit-quotation`, `approve-quotation`, `reject-quotation`, `download-quotation-pdf` (`original`, `staff`, or `final`) |
|
|
701
|
+
| **Customer invoices** | `check-customer-invoice-readiness`, `list-eligible-customer-invoice-budgets`, `preview-customer-invoice-amount`, `list-available-qbo-customer-invoices`, `list-customer-invoices` (global/project/budget filters; cursor pages via `--limit` / `--cursor` / `--direction` returning `{ items, pageInfo }`, `--page` / `--perPage` rejected; `--sortBy totalInvoiceAmount` sorts provider-confirmed totals including GST, with unknown amounts last), `count-customer-invoices` (`customerInvoice.getCounts`: filters only; `totalCount`, lifecycle status facets that ignore their own status filter, and amount metrics), `get-customer-invoice` (web-shaped batch), `get-customer-invoice-invoices`, `get-customer-invoice-lines`, `get-customer-invoice-approvals`, `get-customer-invoice-history`, `get-customer-invoice-email-context`, `preview-qbo-customer-invoice`, `import-qbo-customer-invoice` (BB-only link with reviewed token), `create-customer-invoice`, `discard-customer-invoice`, `delete-customer-invoice`, `void-customer-invoice`, `approve-customer-invoice` (admin), `reject-customer-invoice` (admin), `send-customer-invoice-to-contact-person`, `download-customer-invoice-pdf` (non-admins cannot download while approval is pending), `sync-customer-invoice` |
|
|
586
702
|
| **Approvals** | `list-approvals` / `get-pending-approvals` (`--type budget\|supplier\|bill\|quotation\|customer_invoice\|all`), `approve-bill` / `reject-bill` (send reply email), `approve-budget` / `reject-budget` (send reply email), `approve-supplier` / `reject-supplier` (send reply email), `approve-quotation` / `reject-quotation`, `approve-customer-invoice` / `reject-customer-invoice` |
|
|
587
703
|
| **Companies & projects** | `list-companies`, `get-company`, `create-company`, `update-company` (`--payload`), `delete-company`, `list-projects`, `get-project` (its budget overview returns `totalRevenue`, calculated only from Estimate Accepted and Estimate Closed budgets), `get-project-hub-status`, `setup-project-hub`, `sync-project-hub-commercial-documents`, `create-project` (required: `--name`, `--companyId`, `--contactPersonId`, `--insideSalesId`, `--businessDevelopmentId`, `--venue`, `--startDate` as ISO datetime for project/window start; when `--asanaTaskId` is omitted, the CLI searches open Asana lead tasks in the Deals project, prompts for one of the top five matches, and resolves Slack channel fields from the selected deal card; optional `--asanaSearch`, `--pax`, `--endDate`, `--description`, `--projectManagerId`; always requests QBO project import like the web app), `update-project` (`--payload` with `dateRange.from` / `dateRange.to` for the project window; optional `projectManagerId` and `requestQboAccountantNotification` in JSON), `delete-project`, `check-project-reconciliation <id>` (runs the web app's live checks without changing status), `reconcile-project <id>` (reruns checks transactionally and marks an eligible project `RECONCILED`), `complete-project <id>` (reruns validation, marks a reconciled project `COMPLETED`, and queues QuickBooks placeholder cleanup), `import-qbo-project`, `update-project-status` (`<id>` `<status>`: `PITCH` \| `WON` \| `COMPLETED` \| `RECONCILED` \| `LOST`; close-out follows `WON` → `RECONCILED` → `COMPLETED`, and reconciliation requires every accepted/closed budget line to have an Approved/Paid bill or claim or be explicitly Not Utilized; marking `COMPLETED` queues deletion of every remaining project placeholder bill from QuickBooks; for `PITCH` → `WON` also pass a Budget Builder user `--projectManagerId` or `--projectManagerEmail`; when marking `WON` without an accepted/closed budget or proof, pass `--wonOverrideReason`) |
|
|
588
704
|
| **Contacts** | `list-contacts`, `create-contact-person` (`--payload`), `update-contact-person` (`--payload`) |
|
|
589
|
-
| **Suppliers & items** | `list-suppliers` (defaults to active suppliers, `--perPage 10`, sorted by `createdAt` desc; supports `--name`, `--sortBy` for scalar supplier fields, `--sortDir`, `--createdBy`, `--gstRegistered`, `--status`, `--supplierTags`, `--active false` for archived suppliers), `create-supplier` (`--payload`; when supplier status is `PENDING_APPROVAL`, also runs `supplier.createSupplierApproval` and `email.sendSupplierApprovalRequestEmail`), `update-supplier` (`--payload`; when supplier status is `PENDING_APPROVAL`, also runs `supplier.createSupplierApproval` and `email.sendSupplierApprovalRequestEmail`), `delete-suppliers` (`--ids` CSV; admin; archives/deactivates related items), `reactivate-suppliers` (`--ids` CSV; admin; reactivates related items), `create-certification` / `create-payment-method` / `create-supplier-role` / `create-supplier-tag` (`--name`), `get-supplier-details` (includes `supplierApprovalSummary` for pending approvers, superseded approvers, and the actual responder/respondedAt metadata), `get-supplier-analytics` (admin), `list-items` (`--includeQuickBooksDeactivationPending true` discovers interrupted QuickBooks deactivations for Admin retry), `create-item` (`--payload`), `update-item` (`--payload`), `archive-items` (`--ids` CSV, max 100; Budget Builder-only; open estimates retain unavailable snapshot lines for resolution), `delete-item` (admin; archives in Budget Builder and makes the item inactive in QuickBooks; blocked while an open estimate references it), `get-item`, `list-item-categories`, `create-item-category` / `update-item-category` / `delete-item-categories` (admin; `--ids` CSV for delete) |
|
|
590
|
-
| **Dashboard & users** | `whoami` (current authenticated identity and role), `list-users`, `create-user` (admin; provisions an API-only service identity with no Google sign-in; `--email`, optional `--name`, optional `--role` defaulting to `USER`), `create-api-key` (`--name`; defaults to the caller; admin-only `--userId` for another user; raw key shown once), `list-api-keys` (defaults to the caller; admin-only `--userId` for another user), `revoke-api-key` (key ID; admin-only `--userId` for another user), `get-user-performance`, `get-dashboard`, `get-monthly-metrics`, `get-system-overview`, `get-estimate-performance`, `get-financial-overview` (performance/dashboard commands are admin-only) |
|
|
591
|
-
| **Errors (admin)** | `get-recent-errors`, `get-error-metrics` |
|
|
592
|
-
| **Automation (admin)** | `list-integration-operations`, `retry-integration-operation` (Resend resolution requires `--confirmExternalStateReconciled true` plus `--outboundEmailResolution ACCEPTED\|NOT_ACCEPTED_RETRY`; include `--providerMessageId` when accepted) |
|
|
705
|
+
| **Suppliers & items** | `list-suppliers` (defaults to active suppliers, `--perPage 10`, sorted by `createdAt` desc; supports `--name`, `--sortBy` for scalar supplier fields, `--sortDir`, `--createdBy`, `--gstRegistered`, `--status`, `--supplierTags`, `--active false` for archived suppliers), `create-supplier` (`--payload`; when supplier status is `PENDING_APPROVAL`, also runs `supplier.createSupplierApproval` and `email.sendSupplierApprovalRequestEmail`), `update-supplier` (`--payload`; when supplier status is `PENDING_APPROVAL`, also runs `supplier.createSupplierApproval` and `email.sendSupplierApprovalRequestEmail`), `delete-suppliers` (`--ids` CSV; admin; archives/deactivates related items), `reactivate-suppliers` (`--ids` CSV; admin; reactivates related items), `create-certification` / `create-payment-method` / `create-supplier-role` / `create-supplier-tag` (`--name`), `get-supplier-details` (includes `supplierApprovalSummary` for pending approvers, superseded approvers, and the actual responder/respondedAt metadata), `get-supplier-analytics` (admin; cursor pages: `--limit` / `--cursor` / `--direction`, optional `--name`, `--status` CSV, `--gstRegistered true|false`, `--createdBy`, `--timeFrame` (with `--startDate`/`--endDate` for `CUSTOM` only), `--sortBy name|gstRegistered|status|phone|email|updatedAt|createdAt`, `--sortDir`; `--page` / `--perPage` rejected; invalid filters are rejected instead of silently widening results), `count-supplier-analytics` (admin; `{ totalCount }` for the same filters), `list-items` (`--includeQuickBooksDeactivationPending true` discovers interrupted QuickBooks deactivations for Admin retry), `create-item` (`--payload`), `update-item` (`--payload`), `archive-items` (`--ids` CSV, max 100; Budget Builder-only; open estimates retain unavailable snapshot lines for resolution), `delete-item` (admin; archives in Budget Builder and makes the item inactive in QuickBooks; blocked while an open estimate references it), `get-item`, `list-item-categories` (cursor pages of active categories: `--limit` / `--cursor` / `--direction`, optional `--name`, `--sortBy createdAt|name|itemCount|createdBy`, `--sortDir`; `--page` / `--perPage` rejected), `count-item-categories` (`{ totalCount }` for the same `--name`), `create-item-category` / `update-item-category` / `delete-item-categories` (admin; `--ids` CSV for delete) |
|
|
706
|
+
| **Dashboard & users** | `whoami` (current authenticated identity and role), `list-users` (forward cursor pages, name A–Z: `--limit` / `--cursor`, optional `--q` matching name or email; `--page` / `--perPage` rejected), `count-users` (`{ totalCount }` for the same `--q`), `create-user` (admin; provisions an API-only service identity with no Google sign-in; `--email`, optional `--name`, optional `--role` defaulting to `USER`), `create-api-key` (`--name`; defaults to the caller; admin-only `--userId` for another user; raw key shown once), `list-api-keys` (newest-first cursor pages: `--limit` 1–100, `--cursor`; returns `{ items, pageInfo }`; defaults to the caller; admin-only `--userId` for another user), `revoke-api-key` (key ID; admin-only `--userId` for another user), `get-user-performance`, `get-dashboard`, `get-monthly-metrics`, `get-system-overview`, `get-estimate-performance`, `get-financial-overview` (performance/dashboard commands are admin-only) |
|
|
707
|
+
| **Errors (admin)** | `get-recent-errors`, `get-error`, `get-error-metrics` |
|
|
708
|
+
| **Automation (admin)** | `list-integration-operations` (cursor pages, newest first: `--limit` / `--cursor` / `--direction` with `--search`, `--destination`, `--status`; `--page` / `--perPage` rejected), `count-integration-operations` (`{ filterOptions }` provider options only; no total, so the command does not scan the outbox; filter flags are accepted but ignored), `get-integration-operation <operationId>` (who queued the job, what it is for, saved progress, Retry state), `reconcile-resource-operation <operationId>`, `retry-integration-operation` (QuickBooks jobs with a saved attempt check QuickBooks first and never resend an applied change; Resend resolution requires `--confirmExternalStateReconciled true` plus `--outboundEmailResolution ACCEPTED\|NOT_ACCEPTED_RETRY`; include `--providerMessageId` when accepted) |
|
|
593
709
|
| **Historical / benchmarks** | `get-approved-budgets`, `get-budget-category-benchmarks`, `get-item-pricing-history`, `get-supplier-pricing-history` |
|
|
594
710
|
|
|
595
711
|
The CLI intentionally wraps low-level upload-request/confirm procedures into file-based commands and omits browser-only helpers such as navigation counts, combobox/facet data, recent-page bookkeeping, and live UI subscriptions. Operational workflows for bills, claims, quotations, customer invoices, project reconciliation/completion, and integration recovery are available directly.
|