@datarails-ai/dr-cli 1.6.114 → 1.6.116

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/dist/cli.js CHANGED
@@ -8,7 +8,7 @@ import { fileURLToPath as fileURLToPath3 } from "url";
8
8
  // package.json
9
9
  var package_default = {
10
10
  name: "@datarails-ai/dr-cli",
11
- version: "1.6.114",
11
+ version: "1.6.116",
12
12
  description: "Datarails CLI",
13
13
  type: "module",
14
14
  engines: {
@@ -69,7 +69,7 @@ var package_default = {
69
69
  };
70
70
 
71
71
  // src/buildInfo.ts
72
- var BUILD_TIME = "2026-10-09T16:30:45.883Z";
72
+ var BUILD_TIME = "2026-10-12T07:26:22.083Z";
73
73
  function formatBuildTime(iso) {
74
74
  if (iso === "") return "";
75
75
  const d = new Date(iso);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "cliVersion": "1.6.114",
3
+ "cliVersion": "1.6.116",
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": {
@@ -547,6 +547,9 @@ operator JWT: `dr connectors query repoint <queryId> --artifact-version vN --ser
547
547
  VPN's TLS-inspection cert isn't trusted by Node: set `NODE_EXTRA_CA_CERTS` to the gateway CA (do NOT
548
548
  port-forward as a workaround, and never `NODE_TLS_REJECT_UNAUTHORIZED=0`). `dr filebox`/`dr integrations`
549
549
  working while `dr connectors` fails is expected — those hit the public monolith, not the internal CP.
550
+ Repoint, create and delete are scoped to the caller's org, so an operator login (not `login-as`) gets
551
+ `403`. A repoint to an artifact of a **different flavor** must pass `--runtime-flavor <new flavor>` in
552
+ the same command, or it gets `422`.
550
553
 
551
554
  ## 3. Datasource + filebox (monolith, via dr-cli)
552
555
 
@@ -763,8 +766,22 @@ dr connectors connector create --secret-ref <datasource_id> --json $ACC # ad
763
766
  # key — no uuid->id resolver on the monolith). It's the same <filebox_id> used in steps 3a/5.
764
767
  dr connectors query create --connector-id <id> --filebox-uuid <uuid> --filebox-id <filebox_id> \
765
768
  --artifact-name "<vendor>__<dq>" --artifact-version "<ver>" \
766
- --runtime-flavor base --query-config '{"base_url":"https://api.vendor.com","max_mb":30}' --json $ACC
769
+ --runtime-flavor <flavor> --query-config '{"base_url":"https://api.vendor.com","max_mb":30}' --json $ACC
767
770
  ```
771
+ **`--runtime-flavor` must be the artifact's flavor**: the `RUNTIME_FLAVOR` constant in the
772
+ connector's `connection.py` (`base`, `bigquery`, `redshift`, `ibmiodbc`, `sftp`, …). It picks the runner queue
773
+ the jobs go to. Always pass it, even for `base`. The flag defaults to `base`, and the control-plane
774
+ rejects a mismatch with `422 runtime_flavor must be the pinned artifact's (<flavor>)`. Before that
775
+ check existed, a non-base connector bound without the flag silently ran on the base runner,
776
+ which does not have the flavor's packages.
777
+
778
+ The control-plane also checks two more things on `query create`:
779
+ - **Org:** the caller's JWT org must be the connector's org (`403`). This is why `$ACC` must be the
780
+ `dr login-as` customer identity.
781
+ - **Filebox:** it asks the monolith, with the caller's token, whether the caller can see the filebox.
782
+ `403` means the caller can't see it, `422` means `--filebox-id` and `--filebox-uuid` name different
783
+ fileboxes, and `503` means the monolith couldn't answer.
784
+
768
785
  Both need `NODE_EXTRA_CA_CERTS` (VPN CA) like every `dr connectors` call. Verify with
769
786
  `dr connectors binding get <filebox_uuid> --json $ACC` (secret_ref + artifact + query_config resolve).
770
787
  The connector's `req.config` = `public_config` ∪ `query_config` ∪ the data-query's sync_query (its
@@ -871,7 +888,10 @@ unmerged connector has no version to ingest, bind, or run.
871
888
  | `dr filebox data-query get`/`versions --json` shows `&#x27;` (or `&quot;`) in config strings | The monolith serializer HTML-escapes string values on **read**; the DB stores raw quotes. | Cosmetic/display only — placeholder rendering still works. Don't "fix" the stored value; if you need the true string, HTML-unescape the output. |
872
889
  | New artifact code doesn't run even after publish | The runtime resolves the **active-version pointer** (`connector`+`org`), not your latest publish. | `dr connectors publish <dq.py>` then `dr connectors promote <name> --artifact-version vN` (both need `NODE_EXTRA_CA_CERTS`). Confirm: in-cluster `GET /internal/connectors/<name>/active?org_id=<org>`. |
873
890
  | `dr filebox get` never shows the filebox `uuid` | Not exposed by that command. | Read `filebox_uuid` from the `sync.requested` event (`datarails-connect-inngest`), or capture it from `dr filebox create --json`. |
874
- | Creating a binding via `curl localhost:8000/connectors` (or `/connector-queries`) → `401` / SPA HTML | Those POSTs are **authenticated** now; the port-forward serves the SPA. There is no unauthenticated create path. | Use the dr-cli (carries the JWT): `dr connectors connector create --secret-ref <ds>` then `dr connectors query create --connector-id <id> --filebox-uuid <uuid> --artifact-name … --artifact-version … --query-config '{…}'`. See step 4. |
891
+ | Creating a binding via `curl localhost:8000/connectors` (or `/connector-queries`) → `401` / SPA HTML | Those POSTs are **authenticated** now; the port-forward serves the SPA. There is no unauthenticated create path. | Use the dr-cli (carries the JWT): `dr connectors connector create --secret-ref <ds>` then `dr connectors query create --connector-id <id> --filebox-uuid <uuid> --filebox-id <filebox_id> --artifact-name … --artifact-version … --runtime-flavor <flavor> --query-config '{…}'`. See step 4. |
892
+ | `query create` / `query repoint` → `422 runtime_flavor must be the pinned artifact's (<flavor>)` | `--runtime-flavor` was left at its `base` default for a non-base artifact. Or a repoint moved to an artifact of another flavor without changing the binding's flavor. | Pass `--runtime-flavor` = the connector's `RUNTIME_FLAVOR`, in the same command as the artifact change. |
893
+ | `query create` / `query repoint` / `query delete` → `403`, and the control-plane logs `cross_org_denied` | The CLI identity is the operator (`@datarails.com`), whose JWT org is not the connector's org. These routes are org-scoped. | `dr login-as <customer-user-email> --server <X>` and use that `--account` (see *Identity*). |
894
+ | `query create`, or a repoint that changes the filebox → `403 the filebox is not one the caller can see`, `422 … name different fileboxes`, or `503 the monolith could not confirm the filebox` | The control-plane checks with the monolith, using the caller's token, that the caller can see the filebox. `403`: wrong org or wrong id. `422`: `--filebox-id` and `--filebox-uuid` come from two different fileboxes. `503`: the monolith was unreachable. | Use the `uuid` and numeric id from the same `dr filebox create --json` output, under the customer identity. On `503`, retry. |
875
895
  | Connector's own `log.info(...)` lines never appear in the runner logs / Groundcover (but `dr.runner` INFO does) | The hook runs in a **sandbox whose root logger has no handler**, so bare `logging` is dropped (only WARNING+ via lastResort, and even that may not surface). | Use `kit.logging.get_logger("<vendor>__<dq>")`: a stdout handler with a `[<vendor>__<dq>]` prefix, so lines are greppable in the shared `connectors-runner` pod. Never hand-roll a `StreamHandler` helper. Log auth (never the secret), the window, per-page progress, row count. |
876
896
  | A credential reaches Groundcover through a log line that logs no secret | The connector logged the raw `base_url`. It is **operator-supplied binding config**, so it can carry `user:pass@` userinfo or a credential in the query string — and the runner log is a shared multi-tenant stream. 24 connectors in dr-connectors currently do this (harmless for the keyless public sources, not for the credentialed ones). | Log only the hostname: `urlsplit(base_url).hostname` drops userinfo, port, path and query, which is all a log line needs to identify the environment. `samples/sample_streaming_fanout/` and the databricks connections model this. `kit.http.client`'s retry and error lines already name only `METHOD scheme://host[:port]/path`, and `kit.redact.safe_snippet` redacts credential-shaped vendor text. |
877
897
  | `get_query_class` receives `None` / multi-dataset connector raises "unknown objectType" / wrong dataset runs | `objectType` was placed at the data-query **config top level** instead of **inside `config.query`**. The runtime reads `dq["query"].get("objectType")` with **no top-level fallback**, so it comes through as `None`. | Put `objectType` inside the Sync-query, which is JSON **text**: `config.query = '{"objectType":"<dataset>"}'` (drop any top-level `objectType`). `dr connectors dev-fetch` warns when it's missing. Single-dataset connectors survive via their default; multi-dataset ones fail. |
@@ -62,8 +62,9 @@ per server can be logged in at once.
62
62
  credential file when one is in use (see below).
63
63
  - `dr login --api-key --server US` — save a user-bound **API key** instead of a
64
64
  browser session. The key is read from a hidden prompt, or from stdin when
65
- piped (`printf '%s\n' "$KEY" | dr login --api-key -s us`; piped, `-s` is
66
- required unless a credential file already names the server; don't run the
65
+ piped (`printf '%s\n' "$KEY" | dr login --api-key -s <KEY>`, with the server
66
+ the key was issued on; piped, `-s` is required unless a credential file
67
+ already names the server, and a different `-s` is refused; don't run the
67
68
  piped form under shell tracing or command logging). Never pass the key as an
68
69
  argument or paste it into chat. `dr` exchanges it for a JWT itself, so no
69
70
  re-login is ever needed while the key is live — and `login --api-key` does that
@@ -108,7 +109,9 @@ exchange response does not carry it and `login --api-key` does not set it, so
108
109
  update it in the file alongside the key, or the warning keeps naming the old
109
110
  one.
110
111
 
111
- `--server <KEY>` is **required on every command that hits an API**. Valid keys:
112
+ `--server <KEY>` is **required on every command that hits an API — unless a
113
+ credential file is in use**, which already names the server: omit it then (a
114
+ different key is refused as not matching the credentials). Valid keys:
112
115
  `US`, `US2`, `UK`, `CA`, `EU`, `STUDIO`, `DEV`, `DEV-1`, `TEST`, `TEST-1`, `TEST-2`, `TEST-3`, `TEST-4`, `TEST-5`, `TEST-6`, `TEST-7`, `DEMO` (case-insensitive).
113
116
 
114
117
  You can also pass a full **`https://<host>.datarails.com` URL** instead of a
@@ -15,7 +15,7 @@ key attributes, and emits a short-lived confirmation token. Re-run with
15
15
  file between plan and confirm invalidates the token.
16
16
  - The printed confirm command echoes the plan invocation's `--account`, so on
17
17
  a keychain holding several identities for the server it can be pasted
18
- verbatim — no need to re-add the flag by hand (gap #41).
18
+ verbatim — no need to re-add the flag by hand.
19
19
 
20
20
  Gated commands include: `dashboards delete`, `datamappers delete`,
21
21
  `dynamic-ranges delete`, `extables delete`, `functions delete`, `lut delete`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datarails-ai/dr-cli",
3
- "version": "1.6.114",
3
+ "version": "1.6.116",
4
4
  "description": "Datarails CLI",
5
5
  "type": "module",
6
6
  "engines": {