@datarails-ai/dr-cli 1.6.105 → 1.6.107

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.105",
3
+ "cliVersion": "1.6.107",
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": {
@@ -739,6 +739,26 @@
739
739
  }
740
740
  ]
741
741
  },
742
+ "functions data": {
743
+ "requires": [
744
+ {
745
+ "resource": "tables",
746
+ "action": "read"
747
+ }
748
+ ]
749
+ },
750
+ "functions drilldown": {
751
+ "requires": [
752
+ {
753
+ "resource": "tables",
754
+ "action": "read"
755
+ },
756
+ {
757
+ "resource": "dashboards",
758
+ "action": "read"
759
+ }
760
+ ]
761
+ },
742
762
  "functions delete": {
743
763
  "requires": [
744
764
  {
@@ -239,7 +239,11 @@ area's gotchas.
239
239
  - `metrics suggestions list|refresh` + `metrics dimensions suggestions list|refresh` — AI suggestion agents (list shows suggestions + `last_run` status; `refresh` triggers a run, `--wait [--timeout <s>]` polls to completion). Gated per-org by Unleash flags; a successful `metrics migrate` auto-triggers both agents, so a 409 from `refresh` right after usually means it's already running — check `list`.
240
240
  - `metrics suggestions profile` — read-only: profiles every table and returns, per table, the `reporting_axis` (WHICH date column a BASE metric should bucket by, with `chosen_by` naming the rule), `row_grain.reads_as` (`movements` -> time_aggregation SUM, `balances` -> EOP), candidate `measures`, `categoricals`, and the metrics already defined there. Use this BEFORE proposing any metric: `date_field` cannot be read off the payload (no field marks the reporting column) and guessing it produces a silently wrong number that passes validation. `reporting_axis: null` and `reads_as: "unknown"` are real answers - do not substitute a guess. All measure statistics are SAMPLED from storage-ordered windows and named `sampled_*`; there is deliberately no sum/avg. Needs no Unleash flag. ~30s and ~230 requests on a 43-table org.
241
241
  - `metrics dimensions suggestions profile` — read-only: profiles every table/field and returns scored candidate dimension groups (value-overlap grouping, existing-dimension dedupe, machine-readable rejection reasons) in ONE call. Use this instead of looping `templates distinct` per field when reasoning about what dimensions an org should have. Needs no Unleash flag. `--json` for the payload, `--out <file>` when only `summary`/`groups` matter, `--suppression <file>` when you already hold the existing-dimension and dismissed lists. Also emits `near_misses` — pairs just under the merge threshold, for you to judge rather than silently dropped.
242
- - `functions list|get|create|update|delete|set-filters` — a function's **definition** only.
242
+ - `functions list|get|create|update|delete|set-filters` — a function's **definition**.
243
+ - `functions data <id> --filter "F=V1,V2" --date "Reporting Date=2025-01-31" [--agg YTD]` — the
244
+ function's **live value**, computed by the same endpoint the Excel add-in uses for
245
+ `DR.GET`/`DR.YTD`; `functions drilldown <id> … [--out rows.csv]` — the rows behind it.
246
+ `create`/`update --date-field <Date field>` is required for YTD/QTD/MTD to work.
243
247
  - _`set-filters <id> --file <json> [--confirm]` is the **only** way to author a
244
248
  function's row-level filters (create/update don't touch them). FULL REPLACE —
245
249
  an empty array clears all; dimension `values` are a plain list, date filters
@@ -552,8 +556,9 @@ returns the source rows behind the number.
552
556
  counts — and a token; re-run with `--confirm-token` to fire it) → poll `scans
553
557
  status` again. This is a **full historical** rescan (every calc field × every
554
558
  version). To only pick up a datamapper change on the live template, prefer
555
- `datamappers update <id> --rescan latest` (latest version of the mapper's bound
556
- documents only) — far cheaper and lower-blast.
559
+ `datamappers update <id> --payload-file <p> --rescan latest` (latest version of
560
+ the mapper's bound documents only) — far cheaper and lower-blast. It publishes a
561
+ new mapper version, so the mapper gets a **new id**, which dr prints.
557
562
 
558
563
  **Build a `create` body from plain-English intent** (calc models, datamappers,
559
564
  metrics): you resolve names → integer IDs yourself against the tenant
@@ -67,12 +67,23 @@ value-inference behavior. `NAME` is the target **table field** name (the
67
67
  ## Update / preview / bind / delete
68
68
 
69
69
  - `datamappers update`, `datamappers delete` (two-step confirm).
70
- - `datamappers update --rescan latest` — after the PUT, dr watches the
71
- template's scan status for up to 30s, because servers without the DR-54200 fix
72
- save the config but ignore `rescan: "latest"`. If no new scan shows up, it
73
- prints a warning with a ready `datamappers bind <id> --doc … --rescan latest`
74
- command. Run `scans status <template_id>` first: the scan may only be queued,
75
- and `bind` on a queued scan starts a second one. Don't re-run `update`.
70
+ - `datamappers update <id> --payload-file <p>` publishes the payload as a **new
71
+ version** of the mapper, the same request the UI's "Publish and scan" sends
72
+ (`POST /api/templates/<tid>/mappers` with `datamapper_id` = the old id). The
73
+ server adds any new columns to the table, binds the new version to the old
74
+ one's documents, unbinds the old one, and rescans (`--rescan latest` by
75
+ default). The payload needs `config` and `sheet_name`; dr fills in `name`,
76
+ `ordinal`, the bound documents and the source version from the old mapper,
77
+ and any of those keys in the payload wins.
78
+ - **The mapper gets a new id.** dr prints it (`note: mapper <old> was published
79
+ as new version <new>`). Use the new id for the next update, and keep an
80
+ old→new log if anything outside the table refers to the mapper id.
81
+ `update` refuses an old id that is bound to no documents, and points at
82
+ `datamappers list --table <tid>` for the current one.
83
+ - A mapper made by an org import or template push has no source version on
84
+ record, and `update` stops with an error. Add `"document_version_id"` to the
85
+ payload: an ACTIVE version of one of its documents, with a `sheet_name` that
86
+ exists in it.
76
87
  - `datamappers preview --payload-file <p>` — renders mapper output for sample
77
88
  input ("what would this extract?") before saving.
78
89
  - `datamappers bind <mapper_id> --doc <id> [--rescan latest|all]` — change which
@@ -82,15 +93,15 @@ value-inference behavior. `NAME` is the target **table field** name (the
82
93
 
83
94
  `datamappers update <id> --payload-file <p> [--field NAME:TYPE ...]`. Repeatable;
84
95
  `TYPE` is `Text|Float|Date|Integer`. Each `--field` becomes a `fields_to_change`
85
- entry on the PUT body, telling the server to set that column's type **explicitly**
96
+ entry in the body, telling the server to set that column's type **explicitly**
86
97
  instead of inferring it — this is exactly what the web UI's "Publish and scan"
87
- does (same `PUT api/templates/mappers/<id>` endpoint; the only payload difference
88
- is `fields_to_change`).
98
+ does (same `POST api/templates/<tid>/mappers` endpoint; the only payload
99
+ difference is `fields_to_change`).
89
100
 
90
101
  **When you need it:** adding a calc column that multiplies/divides by a
91
102
  **LUT-injected column**. LUT columns land as **Text**; the server infers Text for
92
103
  them, so a formula like `[Posting Amount] * [Sign]` fails to materialise and the
93
- PUT returns a bare `HTTP 500` (`ETLError: … incorrect formula syntax`) — even
104
+ publish returns a bare `HTTP 500` (`ETLError: … incorrect formula syntax`) — even
94
105
  though the formula is valid. Fixing the LUT column's type up-front lets it
95
106
  materialise:
96
107
 
@@ -120,12 +131,12 @@ valid formula the ETL compiler can't resolve (unknown/wrong-cased function,
120
131
  unresolvable `[field]` reference, a string-constant that happens to be quoted)
121
132
  still returns a bare 500.
122
133
 
123
- After `create`, the CLI polls the template's `fields[]` for up to 30s for every
134
+ After `create` and `update`, the CLI polls the template's `fields[]` for up to 30s for every
124
135
  declared calc field to materialise, and warns (pointing at `mapper-recipes get`
125
136
  for working formulas) if any are missing — this catches the EOMONTH failure
126
137
  mode. Skipped when `--no-rescan` is set.
127
138
 
128
- On a PUT 500, the CLI writes a `dr-cli-error-<timestamp>.md` to the cwd capturing
139
+ On a create or update 500, the CLI writes a `dr-cli-error-<timestamp>.md` to the cwd capturing
129
140
  URL + status + request/response bodies; the path is named in the stderr error.
130
141
 
131
142
  Formula syntax:
@@ -12,7 +12,7 @@ Write:
12
12
 
13
13
  - `integrations add` (payload-file), `integrations sync`,
14
14
  `integrations test-connection`, `integrations update`,
15
- `integrations delete` (two-step confirm).
15
+ `integrations delete` (two-step confirm, Tier A, see below).
16
16
  - `integrations revoke <id>` (two-step confirm; Tier A on prod) — Disconnect a
17
17
  `DatarailsConnector` OAuth data source: `POST /api/v2/data_integrations/<id>/revoke`.
18
18
  The grant is cleared locally first (`oauth_tokens`/`oauth_pending` dropped,
@@ -23,6 +23,38 @@ Write:
23
23
  `revoked` may leave the grant live at the vendor. Legacy vendors are refused.
24
24
  - `integrations share users` / `integrations share groups`.
25
25
 
26
+ ### Deleting a data source (`integrations delete <id>`)
27
+
28
+ `DELETE /api/v3/data_integrations/<id>/`. It cannot be undone and **cascades to queries and
29
+ documents**. Typical use: removing a validation or staging datasource that holds live customer
30
+ credentials once its bindings are gone.
31
+
32
+ 1. **Plan:** run it without a token, as the identity that owns the data source (on a staging org,
33
+ the impersonated staging user, never the operator):
34
+ `dr integrations delete <id> --server <S> --account <user>`. It prints `name`, `type`, `status`,
35
+ `org` (name + id) and `shared` (user/group counts), plus the exact confirm command with a token
36
+ that expires in **10 minutes** and is bound to this id and verb. Check the org id and the name
37
+ before going on: the plan does **not** list the queries and documents the cascade will remove.
38
+ Make sure nothing you want to keep still points at this data source.
39
+ 2. **Relay and get a "yes"**: name, org and why it is being deleted.
40
+ 3. **Confirm:** re-run the printed command with `--confirm-token <tok>`. On a prod tenant (`US`,
41
+ `US2`, `UK`, `CA`, `EU`, `STUDIO`, `DEMO`) this is **Tier A**: the binary shows a fresh word in a
42
+ desktop dialog (or a TTY prompt) and a human must type it. With no interactive channel it exits
43
+ non-zero; hand the printed line to the user rather than retrying. Success prints
44
+ `Deleted integration <id> — "<name>".`
45
+ 4. **Verify:** `dr integrations get <id> --server <S> --account <user>` returns `HTTP 404`.
46
+
47
+ Notes:
48
+
49
+ - `dr connectors` `Connector` rows that reference the data source (`--secret-ref`) are **not**
50
+ deleted, and dr-cli has no connector delete. Delete the `dr connectors` bindings first
51
+ (`dr connectors query delete`), then record the orphaned connector id.
52
+ - A `403` (`delete refused: …`) means the identity can't delete it: switch to the owner's account,
53
+ not to the operator.
54
+ - Deleting a validation data source on the Workato-migration staging orgs left the staging fileboxes
55
+ in place (their data-query rows pointed at the data source). Check one with `dr filebox get` after
56
+ the delete if you need them as evidence.
57
+
26
58
  ## IT-admin file-sync (`integrations it`)
27
59
 
28
60
  File-sync connectors only — OneDrive / SharePoint / Egnyte. Output redacts
@@ -478,11 +478,10 @@ dr metrics dimensions suggestions profile -s DEV --account support@acme.com --js
478
478
  51-table org. Read `summary.empty_unverified` as "at least this many
479
479
  fields' emptiness is unproven", not as an exact census.
480
480
 
481
- ## Functions (DR.GET definitions)
481
+ ## Functions (DR.GET definitions and values)
482
482
 
483
483
  - `functions list`, `functions get <id>` — `get` returns the **definition**,
484
- **not** the live value. Live function values are computed in Excel via
485
- `DR.GET(...)` through the add-in and are not exposed by this CLI.
484
+ not the value (for the value see `functions data` below).
486
485
  - The core row is `id / name / agg / template / value_field`; below it `get`
487
486
  prints a **FILTERS** section (one row per persisted filter: `field`, `name`,
488
487
  `type`, `excluded`, `values`) and the **default agg date field** when set.
@@ -492,6 +491,18 @@ dr metrics dimensions suggestions profile -s DEV --account support@acme.com --js
492
491
  blob (owned by the add-in), shown verbatim as compact JSON — read it there
493
492
  rather than asking the customer to re-check the UI.
494
493
  - `functions create`, `functions update`, `functions delete` (two-step confirm).
494
+ - `--date-field <id|name>` (create and update) sets the function's **default
495
+ aggregation date field** (must be a Date field of the template) and sends the
496
+ platform's default per-period roll-up config (every period by month, `sum`,
497
+ end-of-period — what UI-created functions carry; a function needing MTD by
498
+ day must be adjusted in the UI). **Without it `DR.YTD`/`QTD`/`MTD`/…
499
+ do not work for the function anywhere** — `functions data --agg YTD` answers
500
+ HTTP 400 `{"DateAgg":[…]}` and the xlsx auto-calculate engine fails outright.
501
+ `create` without it prints a one-line warning on stderr. A later
502
+ `update`/`set-filters` full PUT keeps the date field (verified) — so
503
+ `update --template <id>` on a function that has one is **refused unless
504
+ `--date-field` is passed too** (the old field belongs to the old table, and
505
+ the server checks only its type).
495
506
  - `functions set-filters <id> --file <json> [--confirm]` — **the only way to
496
507
  author a function's filters** (`create`/`update` don't touch them). **FULL
497
508
  REPLACE**: the server deletes every existing filter and recreates from the
@@ -505,6 +516,65 @@ dr metrics dimensions suggestions profile -s DEV --account support@acme.com --js
505
516
  `--confirm`; internally a read-modify-write PUT that preserves the core fields
506
517
  and calculated-value links.
507
518
 
519
+ ### Live values: `functions data`
520
+
521
+ `functions data <id> [--filter "NAME=V1,V2"]… [--date "NAME=DATE[,DATE]"]… [--agg DEFAULT|YTD|YTG|QTD|QTG|MTD|MTG] [--json]`
522
+ evaluates the function through `PUT /api/functions/<id>/data/v2` — the endpoint
523
+ the Excel add-in calls for `DR.GET` (`--agg DEFAULT`) and `DR.YTD`/… — so the
524
+ number is the one Excel shows, with the function's own filters always applied
525
+ (a `--filter` can only narrow them, never override).
526
+
527
+ - Fields are named (or given by id) and resolved on the function's template;
528
+ the add-in's canonical field name goes on the wire. An unknown field fails
529
+ client-side with the list of valid fields.
530
+ - **Dates.** The endpoint wants **Excel serial numbers** (2025-01-31 = 45688);
531
+ epoch seconds and ISO strings are not rejected server-side, they silently
532
+ return nothing. The CLI converts: on a Date field (via `--date` or `--filter`)
533
+ pass `YYYY-MM-DD`, `M/D/YYYY`, an ISO datetime, a serial, or epoch seconds.
534
+ A bare month (`2025-06`) is **refused** — tables store a specific day
535
+ (usually month-END), so a month's 1st would match nothing (DEFAULT) or stop a
536
+ month short (YTD). Pass the stored day, e.g. `2025-06-30`.
537
+ - Several values on one field return **one row per value combination**; the
538
+ table shows each field's key (serials rendered back as dates) and `VALUE`
539
+ (rounded to 4 decimals for display; `--json` is the server body verbatim).
540
+ - No row at all prints `(no data: nothing matches these filters)` — a real
541
+ answer (unknown value, or the function's own filter excludes it), not an error.
542
+ - Errors: a per-query `error.msg` (e.g. "Field X is not related to function")
543
+ and any non-2xx exit non-zero; an HTTP 400 such as
544
+ `{"DateAgg":["Function N has no default aggregation date field"]}` is shown
545
+ verbatim with the `--date-field` fix. Under `--json` the body is printed first.
546
+
547
+ ### Rows behind a value: `functions drilldown`
548
+
549
+ `functions drilldown <id> [--filter …]… [--exclude …]… [--date …]… [--agg …] [--columns a,b] [--limit 20] [--out rows.csv] [--csv] [--json]`
550
+ calls `PUT /api/functions/<id>/drilldown/v4` with the same filters (as the
551
+ add-in's filter objects, field id + type resolved from the template).
552
+
553
+ - Prints `N rows × M columns`, the function's own aggregate over those rows
554
+ (`SUM(Amount) over these rows: …` — equals `functions data` with the same
555
+ filters), then the first `--limit` rows (0 = all) of the filtered fields and
556
+ the value field, or of `--columns`. Date columns arrive as epoch seconds and
557
+ are shown as dates.
558
+ - Above the server's inline cap (≈ tens of thousands of rows) the answer is
559
+ `too_large_data`. Without `--out` that is an error naming the size; narrow
560
+ with more `--filter`s or add `--out`. With `--out <file.csv>` the CLI takes
561
+ the add-in's **CSV export** path automatically (`export_to_csv` → cache-key
562
+ poll → report download, ~15 s for 25k rows × 215 columns, 20 MB); `--csv`
563
+ forces it. An inline answer with `--out` is written as CSV too (schema
564
+ columns, dates as `YYYY-MM-DD`). `--out` raises the command budget to 300 s
565
+ (`--timeout <s>` overrides).
566
+ - `--json` prints the inline body verbatim (rows plus a trailing
567
+ `{fields, empty_fields}` schema object); with `--out`, a JSON summary
568
+ (`source`, `rows`, `columns`, `aggregate`, `report_id`).
569
+ - **Credential scopes:** a scoped credential (API key) needs `tables:read`
570
+ **and `dashboards:read`** for `drilldown`. The CSV export path polls
571
+ `/api/cache/cache_keys_status` and downloads `/api/dashboards/report/<n>`,
572
+ both of which the server scopes to `dashboards`; without it the export fails
573
+ at the first status poll (error 40301) after the server has started the task.
574
+ The CLI declares `dashboards:read` for every drill-down, inline included,
575
+ because scopes are per command, not per flag. `functions data` needs
576
+ `tables:read` only.
577
+
508
578
  ## Customer-facing docs (KB)
509
579
 
510
580
  Help Center → the **"Semantic Layer"** category. Find current articles with `dr kb search "metric KPI"` (or
@@ -149,8 +149,9 @@ except on `update`, which resolves the range's own table automatically.
149
149
  the blast radius (document + version counts) and get a token, then re-run with
150
150
  `--confirm-token` — token-only, no word gate even on prod (a rescan re-derives
151
151
  data, it doesn't delete it). To pick up a datamapper change on the live template
152
- **without** touching history, use `datamappers update <id> --rescan latest`
153
- instead (re-extracts the latest version of the mapper's bound documents); a full rescan will re-run pre-existing
152
+ **without** touching history, use `datamappers update <id> --payload-file <p>
153
+ --rescan latest` instead (re-extracts the latest version of the mapper's bound
154
+ documents; it publishes a new mapper version, so the mapper gets a new id); a full rescan will re-run pre-existing
154
155
  calc fields against old rows, so a latent divide-by-null there fails the whole
155
156
  scan. Refuses `UsageStats` on every tenant (system data, not customer-owned).
156
157
  - `dataflow get` — the dependency graph: inputs → mappers → LUTs → table →
@@ -431,27 +431,20 @@ this path that advice does not hold.) The generator omits it.
431
431
  `document_version_id` is required and is **not** in `dr datamappers get` output —
432
432
  read it from the upload response or `dr filebox versions <filebox_id>`.
433
433
 
434
- ### Changing a mapper that already exists: remap, don't update
434
+ ### Changing a mapper that already exists: remap
435
435
 
436
436
  Widening an existing feed mapper, or adding reporting-amount columns to a business
437
- table's mappers, means editing mappers that already exist. `dr datamappers update` is
438
- the obvious tool, and on many orgs **it cannot work.** A mapper created by an org
439
- import or template push has no source version on record. `PUT
440
- /api/templates/mappers/<id>` reads the mapper's source file, and for such a mapper it
441
- fails with a bare HTTP 500. The server log shows `AttributeError: 'NoneType' object has
442
- no attribute 'get_document_data'`. No request body fixes it, because the endpoint never
443
- reads a version from the body.
437
+ table's mappers, means editing mappers that already exist. `dr datamappers update
438
+ <id> --payload-file <p>` does this as a remap: it publishes the edited config as a new
439
+ version of the mapper, the way the UI's "Publish and scan" does, and fills in `name`,
440
+ `ordinal`, the bound documents and the source version from the old mapper.
444
441
 
445
- Remap instead. `dr datamappers create from-file <table_id>` with the existing
446
- mapper's id replaces it in place and records a real source version:
442
+ A mapper created by an org import or template push has no source version on record,
443
+ and `update` stops with an error saying so. Put a version in the payload:
447
444
 
448
445
  ```json
449
446
  {
450
- "name": "<existing name>",
451
- "datamapper_id": <existing mapper id>,
452
- "ordinal": <existing ordinal>,
453
447
  "document_version_id": <an ACTIVE version of one of its documents>,
454
- "selected_document_ids": [<its mapped_documents_ids>],
455
448
  "sheet_name": "<a sheet that exists in THAT version>",
456
449
  "config": { ... the edited config ... }
457
450
  }
@@ -459,7 +452,8 @@ mapper's id replaces it in place and records a real source version:
459
452
 
460
453
  - **The mapper gets a new id.** The old id stays behind bound to no documents, and
461
454
  lookups, which live on the table, are unaffected. Keep an old→new id log for rollback.
462
- - **`ordinal` must be the existing one.** A lower one is refused as a duplicate mapper.
455
+ - **`ordinal` must be the existing one.** `update` sends it for you; a lower one in the
456
+ payload is refused as a duplicate mapper.
463
457
  - **`sheet_name` must exist in the version you pass**, and a mapper's
464
458
  `preview_sheet_name` is often stale. Check with `dr filebox sheets <version_id>`; when
465
459
  the preview sheet is gone and the version has one sheet, use that one.
@@ -754,7 +748,7 @@ the package layout reaches every producer.
754
748
  | `#NAME?` on the label cell | `TEXT()` wrapped around `DR.MONTH()` | Step 4 |
755
749
  | Self-rate is not exactly 1 | ratio not anchored to the target row | Step 4 |
756
750
  | Custom code rejected by the Tables dialog | never registered as an org currency | Step 1 |
757
- | `datamappers update` 500s on an unchanged config | mapper has no source version (org import) | remap, Step 6 |
751
+ | `datamappers update`: mapper has no source document version | mapper made by an org import | `document_version_id` in the payload, Step 6 |
758
752
  | Remap 500s: `Cannot read sheet with name …` | chosen version is in `ERROR` status | use the newest ACTIVE version, Step 6 |
759
753
  | New lookup columns empty on every target row | lookup built while the FX table was still scanning | rebuild the lookup, Step 7 |
760
754
  | Opening balances have no currency amounts | calc-model rows skip the mappers | **Step 7c** |
@@ -152,8 +152,11 @@ goes merge → new vN → §3 → `dr connectors query repoint` → re-sync. Cut
152
152
 
153
153
  The staging datasource holds **live customer credentials**, so remove it right away:
154
154
  1. `dr connectors query list` → `dr connectors query delete <queryId>` for each binding.
155
- 2. `dr integrations delete <ds>` (two-step confirm). dr-cli has no connector delete, so the orphaned
156
- `Connector` row points at a deleted datasource. Record its id.
155
+ 2. `dr integrations delete <ds> $STG` prints a plan and a confirm token. Re-run it with
156
+ `--confirm-token <tok>`. Prod is Tier A, so a human types the word shown in the desktop dialog; with
157
+ no interactive channel, hand the line to the user. Verify with `dr integrations get <ds> $STG` → 404.
158
+ dr-cli has no connector delete, so the orphaned `Connector` row points at a deleted datasource.
159
+ Record its id. (dr-cli skill, `reference/integrations.md`, "Deleting a data source".)
157
160
  3. Keep the staging fileboxes as evidence until cut-over + ticket close, then delete the `<Customer>` tree.
158
161
  4. Delete the local `wk/` and `st/` downloads: they are customer data. Keep only `report.md`.
159
162
  5. Record the report, what was deleted and what was kept in the migration ticket.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datarails-ai/dr-cli",
3
- "version": "1.6.105",
3
+ "version": "1.6.107",
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.11.2",
20
+ "@datarails-ai/dr-appspace-cli": "0.11.3",
21
21
  "@modelcontextprotocol/sdk": "^1.29.0",
22
22
  "@napi-rs/keyring": "^1.3.0",
23
23
  "commander": "^12.1.0",