@odla-ai/cli 0.36.1 → 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 +43 -5
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-4QJ5NS64.js → chunk-OWTIDSL5.js} +36 -6
- package/dist/chunk-OWTIDSL5.js.map +1 -0
- package/dist/{cli-BFGY7F6X.js → cli-QR44X5IB.js} +2 -2
- package/dist/index.cjs +35 -5
- 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-4QJ5NS64.js.map +0 -1
- /package/dist/{cli-BFGY7F6X.js.map → cli-QR44X5IB.js.map} +0 -0
package/dist/bin.cjs
CHANGED
|
@@ -838,6 +838,7 @@ var init_admin_ai_auth = __esm({
|
|
|
838
838
|
"app:config:write": "apply or inspect one revision-bound configuration operation for an app you own",
|
|
839
839
|
"platform:runbook:write": "read and edit all of odla's operational runbooks, including admin-visible content",
|
|
840
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",
|
|
841
842
|
"platform:ai:policy:write": "change System AI model routing",
|
|
842
843
|
"platform:ai:policy:read": "read System AI model routing",
|
|
843
844
|
"platform:ai:credential:write": "replace a stored AI provider key",
|
|
@@ -11184,7 +11185,7 @@ Usage:
|
|
|
11184
11185
|
odla-ai security run [target] --ack-redacted-source [--env dev] [--profile odla] [--fail-on high]
|
|
11185
11186
|
odla-ai security run [target] --self --ack-redacted-source
|
|
11186
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]
|
|
11187
|
-
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]
|
|
11188
11189
|
odla-ai device list [--email <odla-account>] [--json]
|
|
11189
11190
|
odla-ai device revoke <device-id> [--email <odla-account>] [--json]
|
|
11190
11191
|
odla-ai credentials list [--config odla.config.mjs] [--env dev] [--all] [--json]
|
|
@@ -14546,6 +14547,31 @@ var init_advisory_output = __esm({
|
|
|
14546
14547
|
}
|
|
14547
14548
|
});
|
|
14548
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
|
+
|
|
14549
14575
|
// src/device-command.ts
|
|
14550
14576
|
async function deviceCommand(parsed, deps) {
|
|
14551
14577
|
const action2 = parsed.positionals[1] ?? "";
|
|
@@ -14562,7 +14588,17 @@ async function enroll(parsed, deps, cfg, doFetch, out, json) {
|
|
|
14562
14588
|
const name = stringOpt(parsed.options.name) ?? defaultDeviceName();
|
|
14563
14589
|
const apps = (stringOpt(parsed.options.app) ?? cfg.app.id).split(",").map((id2) => id2.trim()).filter(Boolean);
|
|
14564
14590
|
if (apps.length === 0) throw new Error("device enroll needs --app <id>[,<id>\u2026]");
|
|
14565
|
-
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
|
+
);
|
|
14566
14602
|
const response2 = await doFetch(`${cfg.platformUrl}/registry/devices`, {
|
|
14567
14603
|
method: "POST",
|
|
14568
14604
|
headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
|
|
@@ -14570,7 +14606,8 @@ async function enroll(parsed, deps, cfg, doFetch, out, json) {
|
|
|
14570
14606
|
name,
|
|
14571
14607
|
platform: import_node_process15.default.platform,
|
|
14572
14608
|
appIds: apps,
|
|
14573
|
-
...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 }
|
|
14574
14611
|
})
|
|
14575
14612
|
});
|
|
14576
14613
|
const body = await response2.json().catch(() => ({}));
|
|
@@ -14623,12 +14660,12 @@ async function revoke(parsed, deps, cfg, doFetch, out, json) {
|
|
|
14623
14660
|
out.error(`device: revoked ${deviceId}; every credential it minted is revoked with it`);
|
|
14624
14661
|
if (json) out.log(JSON.stringify({ deviceId, revoked: true }, null, 2));
|
|
14625
14662
|
}
|
|
14626
|
-
async function scopedToken2(parsed, deps, cfg, doFetch, out, label) {
|
|
14663
|
+
async function scopedToken2(parsed, deps, cfg, doFetch, out, label, scope = "app:device:enroll") {
|
|
14627
14664
|
const { credentials } = await resolveOperatorContext(parsed, { allowMissingConfig: true });
|
|
14628
14665
|
const scopedTokenFile = credentials.scopedTokenFile;
|
|
14629
14666
|
return getScopedPlatformToken({
|
|
14630
14667
|
platform: cfg.platformUrl,
|
|
14631
|
-
scope
|
|
14668
|
+
scope,
|
|
14632
14669
|
email: stringOpt(parsed.options.email),
|
|
14633
14670
|
label,
|
|
14634
14671
|
fetch: doFetch,
|
|
@@ -14648,6 +14685,7 @@ var init_device_command = __esm({
|
|
|
14648
14685
|
"src/device-command.ts"() {
|
|
14649
14686
|
"use strict";
|
|
14650
14687
|
init_cjs_shims();
|
|
14688
|
+
init_device_ttl();
|
|
14651
14689
|
import_node_fs20 = require("fs");
|
|
14652
14690
|
import_node_path18 = require("path");
|
|
14653
14691
|
import_node_process15 = __toESM(require("process"), 1);
|