@datarails-ai/dr-cli 1.6.130 → 1.6.131

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "cliVersion": "1.6.130",
3
+ "cliVersion": "1.6.131",
4
4
  "_contract": "Resolve a command path through `aliases` (canonical prefix + alias segment -> canonical path) before any lookup. A path listed in `pendingCommands`, or whose first segment is a key of `pending`, is UNDECIDED, not unrestricted: fail closed or skip it, and never read a path's absence from `commands` as 'no requirement'. An entry carrying `denied` is UNAVAILABLE to any AGENT-SCOPED credential — one whose `scopes` claim carries at least one `resource:action` entry; a claim that is absent, empty, capability-only or wholly unparseable is UNRESTRICTED, and this mark does not apply to it — whatever else that entry says: it is not a ceiling and it is not always-available, its `denied.reason` says why and `denied.until` names the ticket that lifts it, and the absence of `requires` on it must NEVER be read as 'no requirement'. Only an entry in `commands` with an empty `requires` means always-available.",
5
5
  "commands": {
6
6
  "login": {
@@ -1435,6 +1435,22 @@
1435
1435
  }
1436
1436
  ]
1437
1437
  },
1438
+ "error-enrichments types list": {
1439
+ "requires": [
1440
+ {
1441
+ "resource": "integrations",
1442
+ "action": "read"
1443
+ }
1444
+ ]
1445
+ },
1446
+ "error-enrichments types create": {
1447
+ "requires": [
1448
+ {
1449
+ "resource": "integrations",
1450
+ "action": "write"
1451
+ }
1452
+ ]
1453
+ },
1438
1454
  "skill list": {
1439
1455
  "requires": []
1440
1456
  },
@@ -1851,6 +1867,22 @@
1851
1867
  }
1852
1868
  ]
1853
1869
  },
1870
+ "integrations netsuite readiness": {
1871
+ "requires": [
1872
+ {
1873
+ "resource": "integrations",
1874
+ "action": "write"
1875
+ }
1876
+ ]
1877
+ },
1878
+ "integrations netsuite saved-search-sql": {
1879
+ "requires": [
1880
+ {
1881
+ "resource": "integrations",
1882
+ "action": "read"
1883
+ }
1884
+ ]
1885
+ },
1854
1886
  "connectors publish": {
1855
1887
  "denied": {
1856
1888
  "reason": "The connectors control plane runs no dr-auth-sdk guard and checks no scope, so the `integrations` ceiling this command declares would be enforced by nobody. Closed to scoped credentials until that control plane adopts the SDK.",
@@ -2339,6 +2371,30 @@
2339
2371
  }
2340
2372
  ]
2341
2373
  },
2374
+ "filebox custom-reports list": {
2375
+ "requires": [
2376
+ {
2377
+ "resource": "fileboxes",
2378
+ "action": "read"
2379
+ }
2380
+ ]
2381
+ },
2382
+ "filebox custom-reports create": {
2383
+ "requires": [
2384
+ {
2385
+ "resource": "fileboxes",
2386
+ "action": "write"
2387
+ }
2388
+ ]
2389
+ },
2390
+ "filebox custom-reports apply": {
2391
+ "requires": [
2392
+ {
2393
+ "resource": "fileboxes",
2394
+ "action": "write"
2395
+ }
2396
+ ]
2397
+ },
2342
2398
  "widgets list": {
2343
2399
  "requires": [
2344
2400
  {
@@ -295,6 +295,7 @@ area's gotchas.
295
295
  and its dependent objects into other organizations (two-step confirm).
296
296
  Destinations must come from `organizations push-targets`.
297
297
  - `filebox data-query get|set|set-sync-interval|clear|sync` (alias `dq`)
298
+ - `filebox custom-reports list|create|apply` — SuiteQL custom reports of the filebox's NetSuite connection; `create --name <n> --query-file <path>` and `apply <filebox_id> <report_id>` replace the filebox's query (two-step confirm)
298
299
  - `filebox validation-rules options|set`
299
300
  - `filebox kind-explain <id…> [--history] [--as-of DATE] [--json]` / `filebox kind-summary [--json]` —
300
301
  why a filebox has its type and whether it still matches its connections, and
@@ -323,14 +324,16 @@ area's gotchas.
323
324
  - `integrations share users|groups`
324
325
  - `integrations it list|get|add|update|delete|resync` (IT-admin file-sync; redacts secrets by default)
325
326
  - `integrations sftp create|provision` — self-serve SFTP fileboxes: `create --name <n>` makes a filebox and its SFTP folder `/<name>_<id>` in one step; `provision <filebox_id>` does it for an existing filebox
327
+ - `integrations netsuite readiness|saved-search-sql` — NetSuite 3.0 -> SuiteQL migration: `readiness <id> [--dry-run]` probes the bundle and, on CONFIRMED, stamps `bundle_version` 3 (two-step confirm); `saved-search-sql <id> --saved-search <ssid> [--out <file>]` prints a saved search's SQL and its library match
326
328
  - `entities list|qbd-availability|netsuite-connections|rename|rename-group|delete|mark-completed` (alias `companies`)
327
329
  - `entities create qbo|xero|qbd|netsuite` (connected accounting systems)
328
- - `error-enrichments list|stats|get|create|update|delete|test-regex|export|import` — the
330
+ - `error-enrichments list|stats|get|create|update|delete|test-regex|export|import|types list|types create` — the
329
331
  regex→readable-message rules shown when a sync fails. `get`/`update`/`delete` take
330
332
  one **or more** ids (`update` applies the same patch to each); `create` and
331
333
  `update` also accept an **array** `--payload-file` (rule objects for `create`,
332
334
  `{id, ...fields}` patches for `update`) for batch writes. Rules are **per server**;
333
- `list`/`stats` take `--all-servers`, writes take one `--server`. `import` is
335
+ `list`/`stats` take `--all-servers`, writes take one `--server`. A rule's `classification`
336
+ is a server-managed type name: `types list` shows them, `types create --name` adds one. `import` is
334
337
  wipe-and-replace and zeroes hits/feedback counters — it is not the reconcile
335
338
  tool: fleet changes are batch `create`/`update`, and `import` runs only when the
336
339
  user names it and confirms the analytics loss and id reassignment. Start at the
@@ -640,10 +643,11 @@ network traffic or hand-edits JSON. Full recipes in the relevant reference file.
640
643
  an unvalidated escape hatch that forwards straight to the server; a
641
644
  malformed value 500s with no error body. To know when it finished, add
642
645
  `--wait` — never poll `status` or the version count: an unchanged result
643
- writes no new version and still reads `SYNCED`. Never backfill
644
- **balances** from an aggregator (Plaid, Quiltt, Salt Edge, Flinks): it
645
- returns today's balance for every `--date`, so each period gets an
646
- identical copy. Backfill transactions only; sync balances for the current
646
+ writes no new version and still reads `SYNCED`, and a period is reported
647
+ `empty` (exit 0) only when the server logged an empty response for it.
648
+ Never backfill **balances** from an aggregator (Plaid, Quiltt, Salt Edge,
649
+ Flinks): it returns today's balance for every `--date`, so each period gets
650
+ an identical copy. Backfill transactions only; sync balances for the current
647
651
  period and let the nightly schedule build the history. See
648
652
  reference/filebox-documents.md.
649
653
  - **"User has no table permissions" is almost always a misread.** To see which
@@ -428,16 +428,26 @@ set-version-include` (below).
428
428
  `--wait` snapshots each `--date` period's versions before triggering, then
429
429
  polls until every period either gained a new version (**new version**) or
430
430
  had its latest version re-confirmed — the server bumps that version's
431
- `last_sync` instead of writing one (**unchanged**). It exits non-zero when
432
- the data-query goes to `ERROR` (with the server's `last_sync_error`) or on
431
+ `last_sync` instead of writing one (**unchanged**). A sync that returns
432
+ **no rows** writes no version and re-confirms none; `--wait` reports such a
433
+ period as **empty** (exit 0) only when the server has logged its
434
+ empty-response event ("Sync completed successfully, but no new data was
435
+ retrieved … for <period>.") after the trigger, by the server's own clock
436
+ (the sync response's `Date` header), naming that period. An empty response
437
+ that another sync of the same period logs after the trigger (a scheduled
438
+ run, another user) also counts. The data-query's status is never taken as
439
+ proof: a period that failed can read `SYNCED` once a later period runs.
440
+ Without that event (events unreadable, which warns once on stderr; no
441
+ `Date` header; or a new version that matches no period) the period stays
442
+ unfinished and the wait times out. It exits non-zero when the data-query
443
+ goes to `ERROR` (with the server's `last_sync_error`) or on
433
444
  `--timeout <seconds>` (default 1800). `--json` prints one object:
434
- `{outcome, periods: [{period, result: new_version|no_change|pending,
445
+ `{outcome, periods: [{period, result: new_version|no_change|empty|pending,
435
446
  version_id, version}], unmatched_new_versions, error, waited_seconds,
436
- warnings}` — `warnings` repeats any pre-sync `warning:` lines (empty when none).
437
- Without `--date`, it waits for the first period to finish. It cannot be
438
- combined with `--tag`. One blind spot: a sync that returns **no rows**
439
- writes no version and re-confirms none, so it ends in a timeout whose
440
- message says so — check `dr filebox data-query get <fb_id>`.
447
+ warnings}` (`version_id`/`version` are `null` for `empty`; `warnings`
448
+ repeats any pre-sync `warning:` lines, empty when none). Without `--date`,
449
+ it waits for the first period to finish. It cannot be combined with
450
+ `--tag`. On a timeout, check `dr filebox data-query get <fb_id>`.
441
451
  - `filebox data-query set-sync-interval <fb_id> --cron "<expr>"` — change how
442
452
  often the data-query polls (Workato-backed **and** connector-platform /
443
453
  `DatarailsConnector` fileboxes both use this cron). **Use this for sync
@@ -468,6 +478,17 @@ set-version-include` (below).
468
478
  (If you hand-build a `data-query set --payload-file` body instead, you must
469
479
  include a non-empty `sync_offset_array` yourself — that path does no
470
480
  defaulting.)
481
+ - `filebox custom-reports list|create|apply <fb_id>` — the SuiteQL custom reports of
482
+ the filebox's NetSuite connection: named queries shared by its fileboxes, unique by
483
+ name per connection. `list` shows id, name and how many fileboxes use each.
484
+ `create <fb_id> --name <n> --query-file <path>` creates a report from the SQL in the
485
+ file and links the filebox to it; `apply <fb_id> <report_id>` links the filebox to an
486
+ existing one. Both replace the filebox's query and are two-step (Tier B); the plan
487
+ shows the filebox name and its current query (objectType, library key or custom,
488
+ length). The
489
+ filebox's data query must already be SuiteQL (400 otherwise); 409 on `create` means
490
+ the name is taken (by a report or a library entry). Names and SQL are decoded in all
491
+ output, `--json` included.
471
492
  - `filebox set-auto-calc-frequency <doc_id> --cron "<expr>" [--enable]` —
472
493
  two-step. Controls Datarails **auto-calculate** scheduling, a **different**
473
494
  feature from the Workato sync cron. `--enable` bootstraps auto-calc if it's
@@ -100,6 +100,42 @@ container, and files dropped there land in the filebox.
100
100
  - Do not copy SFTP settings from another filebox with `filebox data-query set`. That
101
101
  links the filebox but creates no folder, so the client has nowhere to drop files.
102
102
 
103
+ ## NetSuite 3.0 -> SuiteQL migration (`integrations netsuite`)
104
+
105
+ Helpers for converting a NetSuite 3.0 connection's fileboxes to SuiteQL in place. `<id>`
106
+ is the NetSuite connection (data integration) id, not a filebox id.
107
+
108
+ - `integrations netsuite readiness <id> --dry-run` makes one live SuiteQL call and prints
109
+ the outcome: `CONFIRMED`, `PENDING` (the bundle role or permission is not added yet),
110
+ `NOT_CONNECTED` (no credentials), `SKIPPED_FLAG_OFF` (the org lacks
111
+ `netsuite_suiteql`) or `ERROR`, with the detail and the connection's current
112
+ `bundle_version`. Nothing is written, and no confirmation is needed.
113
+ - Without `--dry-run` it is a write: a `CONFIRMED` probe stamps `bundle_version` 3 (the 3.0
114
+ bundle) on the connection config. Two-step confirm (Tier B): the first run prints the
115
+ connection and a token; re-run with `--confirm-token <tok>`. Any other outcome stamps
116
+ nothing: the outcome is printed, then the command exits non-zero with
117
+ `readiness probe did not confirm (<OUTCOME>): <detail>; nothing was stamped`. A
118
+ `--dry-run` exits 0 for every outcome.
119
+ - `integrations netsuite saved-search-sql <id> --saved-search <ssid>` (read-only;
120
+ `<ssid>` is a numeric internal id, negative for NetSuite's standard searches, or a
121
+ `customsearch*` script id; anything else is refused before the call) prints
122
+ the saved search's name, the SuiteQL library entry it matches (`source_query_key`, or
123
+ `none — custom report`), and the bundle's SQL translation, decoded. `--out <file>` also
124
+ writes the decoded SQL to a file, owner-only (0600), overwriting a regular file and
125
+ refusing a symlink or a hard-linked file; feed it to
126
+ `filebox custom-reports create --query-file <file>` when there is no library match. If
127
+ the file cannot be written, the SQL is printed to stdout and the command exits
128
+ non-zero.
129
+ - `--json` prints the response body (decoded) on both.
130
+ - Errors print `<op> refused (409): <server detail>`. The server's 409 causes:
131
+ `Connection is SuiteQL-native or has no NetSuite 3.0 filebox` and
132
+ `connection account id is not a valid NetSuite account id` (both verbs), and
133
+ `connection has no credentials: <fields>` (`saved-search-sql` only; `readiness` reports
134
+ missing credentials as the `NOT_CONNECTED` outcome). 404 means the id is not a
135
+ NetSuite connection this account can see. 502 on `saved-search-sql` means the bundle
136
+ call failed, or the translated SQL is over the 100,000-character custom-report cap;
137
+ the detail says which.
138
+
103
139
  ## Entities — company data sources (`entities`, alias `companies`)
104
140
 
105
141
  The connected accounting systems (QuickBooks Online/Desktop, Xero, NetSuite) —
@@ -37,8 +37,16 @@ dr error-enrichments test-regex --server S --pattern RE (--sample S... | --sampl
37
37
  dr error-enrichments export [--server S | --all-servers | --servers A,B] [--include-test]
38
38
  [--out PATH] # PATH is a DIRECTORY when sweeping
39
39
  dr error-enrichments import --server S --file backup.csv # DESTRUCTIVE — see safety-backup.md
40
+ dr error-enrichments types list [--server S | --all-servers | --servers A,B] [--include-test] [--json]
41
+ dr error-enrichments types create --server S --name N [--description D] # add a classification type
40
42
  ```
41
43
 
44
+ `classification` is a server-managed **type name**, not a fixed list: read
45
+ `types list` for what a server accepts (a rule write with an unknown name is a
46
+ 400), and `types create` to add one. `--classification` filters on reads are
47
+ checked against the targeted server's live types, so a misspelling errors
48
+ instead of returning an empty list.
49
+
42
50
  An array `--payload-file` on `create` / `update` takes neither positional ids nor
43
51
  field flags — array mode carries every field inside each entry, and the command
44
52
  rejects the combination rather than guessing which one wins.
@@ -72,8 +72,9 @@ to spread to the fleet.
72
72
  message. The server shifts the sibling rows to make room — pass the rank you
73
73
  want and never renumber siblings by hand.
74
74
 
75
- 7. **Set `classification`** (`DataSource` | `Filebox` | `Unclassified`) and
76
- decide `approved`. Create as a draft (`--approved false`) only when the
75
+ 7. **Set `classification`** to a managed type (`dr error-enrichments types list
76
+ --server <S>`; omitted means `Unclassified`) and decide `approved`. Create as
77
+ a draft (`--approved false`) only when the
77
78
  pattern still needs field validation, and say out loud what that costs: a
78
79
  draft steals the hit from any lower-ranked approved rule and shows the user
79
80
  nothing, so a draft left in place is an active user-facing gap, not a
@@ -94,7 +94,10 @@ JSON
94
94
  dr error-enrichments update --payload-file /tmp/uk-patches.json --server UK
95
95
  ```
96
96
 
97
- For rules missing on the target — an array of full rule objects:
97
+ For rules missing on the target — an array of full rule objects. Classification
98
+ types are per server: run `dr error-enrichments types list --all-servers` first and
99
+ `types create` any name the target lacks, or every rule using it fails with a 400.
100
+ The `classification` below is illustrative:
98
101
 
99
102
  ```bash
100
103
  cat > /tmp/uk-new.json <<'JSON'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datarails-ai/dr-cli",
3
- "version": "1.6.130",
3
+ "version": "1.6.131",
4
4
  "description": "Datarails CLI",
5
5
  "type": "module",
6
6
  "engines": {
@@ -17,7 +17,7 @@
17
17
  "access": "public"
18
18
  },
19
19
  "dependencies": {
20
- "@datarails-ai/dr-appspace-cli": "0.12.8",
20
+ "@datarails-ai/dr-appspace-cli": "0.12.9",
21
21
  "@modelcontextprotocol/sdk": "^1.29.0",
22
22
  "@napi-rs/keyring": "^1.3.0",
23
23
  "commander": "^12.1.0",