@datarails-ai/dr-cli 1.6.127 → 1.6.129

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.127",
11
+ version: "1.6.129",
12
12
  description: "Datarails CLI",
13
13
  type: "module",
14
14
  engines: {
@@ -40,7 +40,7 @@ var package_default = {
40
40
  postinstall: "node scripts/postinstall.mjs"
41
41
  },
42
42
  dependencies: {
43
- "@datarails-ai/dr-appspace-cli": "0.12.6",
43
+ "@datarails-ai/dr-appspace-cli": "0.12.7",
44
44
  "@modelcontextprotocol/sdk": "^1.29.0",
45
45
  "@napi-rs/keyring": "^1.3.0",
46
46
  commander: "^12.1.0",
@@ -69,7 +69,7 @@ var package_default = {
69
69
  };
70
70
 
71
71
  // src/buildInfo.ts
72
- var BUILD_TIME = "2026-10-12T20:54:31.824Z";
72
+ var BUILD_TIME = "2026-10-13T11:59:10.262Z";
73
73
  function formatBuildTime(iso) {
74
74
  if (iso === "") return "";
75
75
  const d = new Date(iso);
@@ -7259,9 +7259,12 @@ async function runFeaturesOrgsList(cfg) {
7259
7259
  if (cfg.orgId <= 0) {
7260
7260
  throw new Error("org id must be positive");
7261
7261
  }
7262
- const flags = await orgsList(cfg.client, cfg.orgId, {
7263
- signal: cfg.signal
7264
- });
7262
+ let flags;
7263
+ try {
7264
+ flags = await orgsList(cfg.client, cfg.orgId, { signal: cfg.signal });
7265
+ } catch (err) {
7266
+ throw orgFlagsError(err, cfg.client, cfg.orgId, false);
7267
+ }
7265
7268
  if (cfg.asJson) {
7266
7269
  writeJSONIndented(cfg.out, flags);
7267
7270
  return;
@@ -7296,11 +7299,22 @@ async function runFeaturesOrgsToggle(cfg) {
7296
7299
  token: cfg.token,
7297
7300
  server: cfg.serverFlag,
7298
7301
  confirmCmd: cfg.confirmCmd,
7299
- describe: async () => [`org: ${cfg.orgId}`, `flags: ${flagIds.join(", ")}`],
7302
+ describe: async () => {
7303
+ try {
7304
+ await orgsList(cfg.client, cfg.orgId, { signal: cfg.signal });
7305
+ } catch (err) {
7306
+ throw orgFlagsError(err, cfg.client, cfg.orgId, true);
7307
+ }
7308
+ return [`org: ${cfg.orgId}`, `flags: ${flagIds.join(", ")}`];
7309
+ },
7300
7310
  execute: async () => {
7301
- await orgsAddOrRemove(cfg.client, cfg.orgId, flagIds, cfg.verb, {
7302
- signal: cfg.signal
7303
- });
7311
+ try {
7312
+ await orgsAddOrRemove(cfg.client, cfg.orgId, flagIds, cfg.verb, {
7313
+ signal: cfg.signal
7314
+ });
7315
+ } catch (err) {
7316
+ throw orgFlagsError(err, cfg.client, cfg.orgId, true);
7317
+ }
7304
7318
  const act = cfg.verb === "addition" ? "enabled" : "disabled";
7305
7319
  const titled = act[0].toUpperCase() + act.slice(1);
7306
7320
  const noun = `flag${plural(flagIds.length)}`;
@@ -7309,6 +7323,25 @@ async function runFeaturesOrgsToggle(cfg) {
7309
7323
  }
7310
7324
  });
7311
7325
  }
7326
+ function orgFlagsError(err, client, orgId, write) {
7327
+ const nothingChanged = write ? ", so nothing changed" : "";
7328
+ if (isNotFoundError(err)) {
7329
+ return new Error(
7330
+ `org ${orgId} does not exist, or is not among the organizations ${client.email} can manage (404)${nothingChanged}.`
7331
+ );
7332
+ }
7333
+ if (!isForbiddenError(err)) return err;
7334
+ const head = `the platform refused access to the feature flags of org ${orgId} (403)${nothingChanged}. An org's feature flags are read and changed through the Datarails IT endpoints, which admit only an admin of the Datarails organization or a support user, checked on the account the CLI acts as. `;
7335
+ const session = client.session;
7336
+ if (isImpersonatedSession(session)) {
7337
+ return new Error(
7338
+ head + `This command acted as ${client.email}, impersonated by ${session.impersonatorEmail ?? ""}: the check applies to ${client.email}, not to you. Re-run it with --account ${session.impersonatorEmail ?? ""}.`
7339
+ );
7340
+ }
7341
+ return new Error(
7342
+ head + `${client.email} has neither role, or is blocked. Use the account you change flags with in the web IT console (\`dr whoami\` shows who you are), or ask for the support-user role.`
7343
+ );
7344
+ }
7312
7345
  function writeTable2(out, rows) {
7313
7346
  if (rows.length === 0) return;
7314
7347
  const widths = [];
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "cliVersion": "1.6.127",
3
+ "cliVersion": "1.6.129",
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": {
@@ -692,6 +692,15 @@ targets.
692
692
  (both two-step confirm-token flow — flipping flags changes customer-visible
693
693
  behavior).
694
694
 
695
+ **Run `features …` as the operator, never as a `login-as` identity.** Every
696
+ `features` command except `features list --enriched` admits only an admin of the
697
+ Datarails organization or a support user (`features groups …` only the admin),
698
+ and the server checks the account the command acts as. An impersonated customer
699
+ always gets 403, even when the operator can flip the flag in the web IT console.
700
+ Pass `--account <your own email>`. `features orgs add|remove` read the org's
701
+ flags at the plan step, so an identity that cannot write fails there, before a
702
+ confirm token is issued.
703
+
695
704
  **Know the flag name? Skip the listing entirely.** `--flag` accepts a flag **id
696
705
  or name** (repeatable), and the server resolves it — so to enable/disable a flag
697
706
  you already know, go straight to `features orgs add <org_id> --flag <name>`. Only
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datarails-ai/dr-cli",
3
- "version": "1.6.127",
3
+ "version": "1.6.129",
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.6",
20
+ "@datarails-ai/dr-appspace-cli": "0.12.7",
21
21
  "@modelcontextprotocol/sdk": "^1.29.0",
22
22
  "@napi-rs/keyring": "^1.3.0",
23
23
  "commander": "^12.1.0",