@odla-ai/cli 0.36.0 → 0.37.0
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/bin.cjs +46 -7
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-DBZQIMES.js → chunk-OWTIDSL5.js} +39 -8
- package/dist/chunk-OWTIDSL5.js.map +1 -0
- package/dist/{cli-BN6WLH5O.js → cli-QR44X5IB.js} +2 -2
- package/dist/index.cjs +38 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-DBZQIMES.js.map +0 -1
- /package/dist/{cli-BN6WLH5O.js.map → cli-QR44X5IB.js.map} +0 -0
package/dist/bin.cjs
CHANGED
|
@@ -401,9 +401,10 @@ async function mintDeviceSession(platformUrl, credential2, doFetch) {
|
|
|
401
401
|
});
|
|
402
402
|
const body = await response2.json().catch(() => ({}));
|
|
403
403
|
if (!response2.ok || typeof body.token !== "string") {
|
|
404
|
-
const
|
|
404
|
+
const revocable = response2.status === 401 || response2.status === 403 || response2.status === 404;
|
|
405
|
+
const detail = body.error?.message ?? (response2.ok ? `registry returned ${response2.status} with no session token` : `registry returned ${response2.status}`);
|
|
405
406
|
throw new Error(
|
|
406
|
-
`device session failed: ${detail} (${response2.status}) \u2014 if this machine's enrollment was revoked or has expired, enroll it again in Studio
|
|
407
|
+
`device session failed: ${detail} (${response2.status})` + (revocable ? " \u2014 if this machine's enrollment was revoked or has expired, enroll it again in Studio" : "")
|
|
407
408
|
);
|
|
408
409
|
}
|
|
409
410
|
return { token: body.token, expiresAt: body.expiresAt ?? Date.now() };
|
|
@@ -837,6 +838,7 @@ var init_admin_ai_auth = __esm({
|
|
|
837
838
|
"app:config:write": "apply or inspect one revision-bound configuration operation for an app you own",
|
|
838
839
|
"platform:runbook:write": "read and edit all of odla's operational runbooks, including admin-visible content",
|
|
839
840
|
"app:device:enroll": "enrol this machine so it can mint its own short-lived credentials without asking you again",
|
|
841
|
+
"platform:device:enroll:extended": "enrol this machine with a credential that outlives the seven-day owner ceiling \u2014 a durable secret on a machine you are vouching for",
|
|
840
842
|
"platform:ai:policy:write": "change System AI model routing",
|
|
841
843
|
"platform:ai:policy:read": "read System AI model routing",
|
|
842
844
|
"platform:ai:credential:write": "replace a stored AI provider key",
|
|
@@ -11183,7 +11185,7 @@ Usage:
|
|
|
11183
11185
|
odla-ai security run [target] --ack-redacted-source [--env dev] [--profile odla] [--fail-on high]
|
|
11184
11186
|
odla-ai security run [target] --self --ack-redacted-source
|
|
11185
11187
|
odla-ai provision [--live] [--config odla.config.mjs] [--email <odla-account>] [--request-grant] [--no-open] [--wait <seconds>] [--dry-run] [--push-secrets] [--rotate-o11y-token] [--write-dev-vars[=path]] [--yes]
|
|
11186
|
-
odla-ai device enroll [--app <id>[,<id>...]] [--name <label>] [--capability <c>[,<c>...]] [--email <odla-account>] [--no-open] [--json]
|
|
11188
|
+
odla-ai device enroll [--app <id>[,<id>...]] [--name <label>] [--capability <c>[,<c>...]] [--device-ttl <30d|6w|2y|forever>] [--email <odla-account>] [--no-open] [--json]
|
|
11187
11189
|
odla-ai device list [--email <odla-account>] [--json]
|
|
11188
11190
|
odla-ai device revoke <device-id> [--email <odla-account>] [--json]
|
|
11189
11191
|
odla-ai credentials list [--config odla.config.mjs] [--env dev] [--all] [--json]
|
|
@@ -14545,6 +14547,31 @@ var init_advisory_output = __esm({
|
|
|
14545
14547
|
}
|
|
14546
14548
|
});
|
|
14547
14549
|
|
|
14550
|
+
// src/device-ttl.ts
|
|
14551
|
+
function parseDeviceTtl(raw) {
|
|
14552
|
+
if (raw === void 0 || raw === true) return void 0;
|
|
14553
|
+
const text3 = String(raw).trim().toLowerCase();
|
|
14554
|
+
if (!text3) return void 0;
|
|
14555
|
+
if (text3 === "forever" || text3 === "never") return 100 * 365 * DAY_MS;
|
|
14556
|
+
const match = /^(\d+)\s*([dwy])$/.exec(text3);
|
|
14557
|
+
if (!match) {
|
|
14558
|
+
throw new Error(
|
|
14559
|
+
`--device-ttl expects a duration like 30d, 6w, 2y, or "forever" (got "${raw}")`
|
|
14560
|
+
);
|
|
14561
|
+
}
|
|
14562
|
+
return Number(match[1]) * UNITS[match[2]];
|
|
14563
|
+
}
|
|
14564
|
+
var OWNER_DEVICE_TTL_MS, DAY_MS, UNITS;
|
|
14565
|
+
var init_device_ttl = __esm({
|
|
14566
|
+
"src/device-ttl.ts"() {
|
|
14567
|
+
"use strict";
|
|
14568
|
+
init_cjs_shims();
|
|
14569
|
+
OWNER_DEVICE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
14570
|
+
DAY_MS = 24 * 60 * 60 * 1e3;
|
|
14571
|
+
UNITS = { d: DAY_MS, w: 7 * DAY_MS, y: 365 * DAY_MS };
|
|
14572
|
+
}
|
|
14573
|
+
});
|
|
14574
|
+
|
|
14548
14575
|
// src/device-command.ts
|
|
14549
14576
|
async function deviceCommand(parsed, deps) {
|
|
14550
14577
|
const action2 = parsed.positionals[1] ?? "";
|
|
@@ -14561,7 +14588,17 @@ async function enroll(parsed, deps, cfg, doFetch, out, json) {
|
|
|
14561
14588
|
const name = stringOpt(parsed.options.name) ?? defaultDeviceName();
|
|
14562
14589
|
const apps = (stringOpt(parsed.options.app) ?? cfg.app.id).split(",").map((id2) => id2.trim()).filter(Boolean);
|
|
14563
14590
|
if (apps.length === 0) throw new Error("device enroll needs --app <id>[,<id>\u2026]");
|
|
14564
|
-
const
|
|
14591
|
+
const deviceTtlMs = parseDeviceTtl(parsed.options["device-ttl"]);
|
|
14592
|
+
const extended = deviceTtlMs !== void 0 && deviceTtlMs > OWNER_DEVICE_TTL_MS;
|
|
14593
|
+
const token = await scopedToken2(
|
|
14594
|
+
parsed,
|
|
14595
|
+
deps,
|
|
14596
|
+
cfg,
|
|
14597
|
+
doFetch,
|
|
14598
|
+
out,
|
|
14599
|
+
`odla CLI (enroll ${name})`,
|
|
14600
|
+
extended ? "platform:device:enroll:extended" : "app:device:enroll"
|
|
14601
|
+
);
|
|
14565
14602
|
const response2 = await doFetch(`${cfg.platformUrl}/registry/devices`, {
|
|
14566
14603
|
method: "POST",
|
|
14567
14604
|
headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
|
|
@@ -14569,7 +14606,8 @@ async function enroll(parsed, deps, cfg, doFetch, out, json) {
|
|
|
14569
14606
|
name,
|
|
14570
14607
|
platform: import_node_process15.default.platform,
|
|
14571
14608
|
appIds: apps,
|
|
14572
|
-
...parsed.options.capability ? { capabilities: String(parsed.options.capability).split(",").map((c) => c.trim()).filter(Boolean) } : {}
|
|
14609
|
+
...parsed.options.capability ? { capabilities: String(parsed.options.capability).split(",").map((c) => c.trim()).filter(Boolean) } : {},
|
|
14610
|
+
...deviceTtlMs === void 0 ? {} : { deviceTtlMs }
|
|
14573
14611
|
})
|
|
14574
14612
|
});
|
|
14575
14613
|
const body = await response2.json().catch(() => ({}));
|
|
@@ -14622,12 +14660,12 @@ async function revoke(parsed, deps, cfg, doFetch, out, json) {
|
|
|
14622
14660
|
out.error(`device: revoked ${deviceId}; every credential it minted is revoked with it`);
|
|
14623
14661
|
if (json) out.log(JSON.stringify({ deviceId, revoked: true }, null, 2));
|
|
14624
14662
|
}
|
|
14625
|
-
async function scopedToken2(parsed, deps, cfg, doFetch, out, label) {
|
|
14663
|
+
async function scopedToken2(parsed, deps, cfg, doFetch, out, label, scope = "app:device:enroll") {
|
|
14626
14664
|
const { credentials } = await resolveOperatorContext(parsed, { allowMissingConfig: true });
|
|
14627
14665
|
const scopedTokenFile = credentials.scopedTokenFile;
|
|
14628
14666
|
return getScopedPlatformToken({
|
|
14629
14667
|
platform: cfg.platformUrl,
|
|
14630
|
-
scope
|
|
14668
|
+
scope,
|
|
14631
14669
|
email: stringOpt(parsed.options.email),
|
|
14632
14670
|
label,
|
|
14633
14671
|
fetch: doFetch,
|
|
@@ -14647,6 +14685,7 @@ var init_device_command = __esm({
|
|
|
14647
14685
|
"src/device-command.ts"() {
|
|
14648
14686
|
"use strict";
|
|
14649
14687
|
init_cjs_shims();
|
|
14688
|
+
init_device_ttl();
|
|
14650
14689
|
import_node_fs20 = require("fs");
|
|
14651
14690
|
import_node_path18 = require("path");
|
|
14652
14691
|
import_node_process15 = __toESM(require("process"), 1);
|