@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 +43 -10
- package/dist/scopes-map.json +1 -1
- package/dist/skills/dr-cli/reference/admin.md +9 -0
- package/package.json +2 -2
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.
|
|
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.
|
|
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-
|
|
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
|
-
|
|
7263
|
-
|
|
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 () =>
|
|
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
|
-
|
|
7302
|
-
|
|
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 = [];
|
package/dist/scopes-map.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
|
-
"cliVersion": "1.6.
|
|
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.
|
|
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.
|
|
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",
|