@odla-ai/cli 0.27.12 → 0.27.13
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/README.md +7 -1
- package/dist/bin.cjs +42 -18
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-ECRBOR66.js → chunk-3YSCRXPF.js} +44 -20
- package/dist/chunk-3YSCRXPF.js.map +1 -0
- package/dist/index.cjs +42 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/skills/odla/references/build.md +8 -0
- package/dist/chunk-ECRBOR66.js.map +0 -1
package/dist/bin.js
CHANGED
|
@@ -292,23 +292,30 @@ function handshakeWaitMs(waitSeconds, interactive = process4.stdout.isTTY === tr
|
|
|
292
292
|
|
|
293
293
|
// src/token.ts
|
|
294
294
|
async function getDeveloperToken(cfg, options, doFetch, out, grantRequest = {}) {
|
|
295
|
-
if (options.token) return options.token;
|
|
296
295
|
const audience = platformAudience(cfg.platformUrl);
|
|
297
|
-
if (process5.env.ODLA_DEV_TOKEN) {
|
|
298
|
-
const declared = process5.env.ODLA_DEV_TOKEN_AUDIENCE;
|
|
299
|
-
if (declared) {
|
|
300
|
-
if (platformAudience(declared) !== audience) throw new Error("ODLA_DEV_TOKEN_AUDIENCE does not match the configured platform");
|
|
301
|
-
} else if (audience !== "https://odla.ai") {
|
|
302
|
-
throw new Error("ODLA_DEV_TOKEN_AUDIENCE is required for a non-default platform");
|
|
303
|
-
}
|
|
304
|
-
return process5.env.ODLA_DEV_TOKEN;
|
|
305
|
-
}
|
|
306
296
|
const optionalProjectCapabilities = grantRequest.optionalProjectCapabilities ?? [];
|
|
307
297
|
const grantIntent = { projectIds: [cfg.app.id], optionalProjectCapabilities };
|
|
308
298
|
const cached = readJsonFile(cfg.local.tokenFile);
|
|
309
|
-
if (
|
|
310
|
-
|
|
311
|
-
|
|
299
|
+
if (!grantRequest.forceReview) {
|
|
300
|
+
if (options.token) return options.token;
|
|
301
|
+
if (process5.env.ODLA_DEV_TOKEN) {
|
|
302
|
+
const declared = process5.env.ODLA_DEV_TOKEN_AUDIENCE;
|
|
303
|
+
if (declared) {
|
|
304
|
+
if (platformAudience(declared) !== audience) throw new Error("ODLA_DEV_TOKEN_AUDIENCE does not match the configured platform");
|
|
305
|
+
} else if (audience !== "https://odla.ai") {
|
|
306
|
+
throw new Error("ODLA_DEV_TOKEN_AUDIENCE is required for a non-default platform");
|
|
307
|
+
}
|
|
308
|
+
return process5.env.ODLA_DEV_TOKEN;
|
|
309
|
+
}
|
|
310
|
+
if (cached?.token && cached.platform === audience && (cached.expiresAt ?? 0) > Date.now() + 6e4 && cachedGrantCovers(cached, grantIntent)) {
|
|
311
|
+
out.error(`auth: using cached developer token (${displayPath(cfg.local.tokenFile, cfg.rootDir)})`);
|
|
312
|
+
return cached.token;
|
|
313
|
+
}
|
|
314
|
+
} else {
|
|
315
|
+
if (options.token) {
|
|
316
|
+
throw new Error("--request-grant cannot be combined with --token; remove --token so the approved replacement credential can be collected and cached");
|
|
317
|
+
}
|
|
318
|
+
out.error(`auth: requesting fresh owner review for app.manage on exact project "${cfg.app.id}"`);
|
|
312
319
|
}
|
|
313
320
|
const ctx = {
|
|
314
321
|
cfg,
|
|
@@ -1810,11 +1817,11 @@ async function assertTenantAdminAccess(doFetch, cfg, env, token) {
|
|
|
1810
1817
|
}
|
|
1811
1818
|
if (code === "provision_approval_required") {
|
|
1812
1819
|
throw new Error(
|
|
1813
|
-
`${env}: the agent credential does not carry the owner-reviewed app.manage grant required to provision "${cfg.app.id}" (tenant ${tenantId}). The human owner id on the token is accountability, not agent authority.
|
|
1820
|
+
`${env}: the agent credential does not carry the owner-reviewed app.manage grant required to provision "${cfg.app.id}" (tenant ${tenantId}). The human owner id on the token is accountability, not agent authority. Run "odla-ai provision --request-grant --email <odla-account>" to open one fresh exact-project owner review; do not change app ownership unless the human account itself is not an owner`
|
|
1814
1821
|
);
|
|
1815
1822
|
}
|
|
1816
1823
|
throw new Error(
|
|
1817
|
-
`${env}: this credential lacks live app.manage authority for "${cfg.app.id}" (tenant ${tenantId}) \u2014 nothing was minted or written;
|
|
1824
|
+
`${env}: this credential lacks live app.manage authority for "${cfg.app.id}" (tenant ${tenantId}) \u2014 nothing was minted or written; run "odla-ai provision --request-grant --email <odla-account>" to open a fresh owner review. If the human account is not an owner, an existing owner must add it in signed-in Studio; an agent token cannot repair ownership`
|
|
1818
1825
|
);
|
|
1819
1826
|
}
|
|
1820
1827
|
throw new Error(`${env}: tenant access preflight (${tenantId}) failed: ${res.status} ${await safeText4(res)}`);
|
|
@@ -7241,7 +7248,7 @@ function record6(value2) {
|
|
|
7241
7248
|
}
|
|
7242
7249
|
|
|
7243
7250
|
// src/provision.ts
|
|
7244
|
-
import { createAppsClient as createAppsClient3, orderAppServices as orderAppServices3, tenantIdFor as tenantIdFor4 } from "@odla-ai/apps";
|
|
7251
|
+
import { AppsError as AppsError2, createAppsClient as createAppsClient3, orderAppServices as orderAppServices3, tenantIdFor as tenantIdFor4 } from "@odla-ai/apps";
|
|
7245
7252
|
import { putSecret as putSecret2 } from "@odla-ai/ai";
|
|
7246
7253
|
import process9 from "process";
|
|
7247
7254
|
|
|
@@ -7462,14 +7469,25 @@ async function provision(options) {
|
|
|
7462
7469
|
}
|
|
7463
7470
|
const doFetch = options.fetch ?? fetch;
|
|
7464
7471
|
const token = await getDeveloperToken(cfg, options, doFetch, out, {
|
|
7465
|
-
optionalProjectCapabilities: ["app.manage"]
|
|
7472
|
+
optionalProjectCapabilities: ["app.manage"],
|
|
7473
|
+
forceReview: options.requestGrant
|
|
7466
7474
|
});
|
|
7467
7475
|
const apps = createAppsClient3({ endpoint: cfg.platformUrl, token, fetcher: { fetch: doFetch } });
|
|
7468
7476
|
const existing = await apps.resolveApp(cfg.app.id);
|
|
7469
7477
|
if (existing) {
|
|
7470
7478
|
out.log(`app: ${cfg.app.id} already exists`);
|
|
7471
7479
|
} else {
|
|
7472
|
-
|
|
7480
|
+
try {
|
|
7481
|
+
await apps.createApp({ name: cfg.app.name, appId: cfg.app.id });
|
|
7482
|
+
} catch (error) {
|
|
7483
|
+
if (error instanceof AppsError2 && error.status === 403) {
|
|
7484
|
+
throw new Error(
|
|
7485
|
+
`app "${cfg.app.id}" does not exist, and this authenticated agent credential has no owner-reviewed app.manage bootstrap grant for that exact id. Run "odla-ai provision --request-grant --email <odla-account>" to open the review URL and continue; developer ownership alone is not agent authority`,
|
|
7486
|
+
{ cause: error }
|
|
7487
|
+
);
|
|
7488
|
+
}
|
|
7489
|
+
throw error;
|
|
7490
|
+
}
|
|
7473
7491
|
out.log(`app: created ${cfg.app.id}`);
|
|
7474
7492
|
}
|
|
7475
7493
|
for (const env of cfg.envs) {
|
|
@@ -9360,7 +9378,7 @@ Usage:
|
|
|
9360
9378
|
odla-ai security report <job-id> [--json]
|
|
9361
9379
|
odla-ai security run [target] --ack-redacted-source [--env dev] [--profile odla] [--fail-on high]
|
|
9362
9380
|
odla-ai security run [target] --self --ack-redacted-source
|
|
9363
|
-
odla-ai provision [--config odla.config.mjs] [--email <odla-account>] [--wait <seconds>] [--dry-run] [--push-secrets] [--rotate-o11y-token] [--write-dev-vars[=path]] [--yes]
|
|
9381
|
+
odla-ai provision [--config odla.config.mjs] [--email <odla-account>] [--request-grant] [--wait <seconds>] [--dry-run] [--push-secrets] [--rotate-o11y-token] [--write-dev-vars[=path]] [--yes]
|
|
9364
9382
|
odla-ai smoke [--config odla.config.mjs] [--env dev] [--email <odla-account>] [--no-open]
|
|
9365
9383
|
odla-ai skill install [--dir <project>] [--agent <name>] [--global] [--force]
|
|
9366
9384
|
odla-ai secrets push --env <env> [--config odla.config.mjs] [--dry-run] [--yes]
|
|
@@ -9495,6 +9513,10 @@ Safety:
|
|
|
9495
9513
|
The email is a non-secret identity hint: never provide a password or session
|
|
9496
9514
|
token. The matching account must already exist, be signed in, explicitly
|
|
9497
9515
|
review the exact code, and finish any current request before claiming another.
|
|
9516
|
+
If provision reports that the current agent principal has no live app.manage
|
|
9517
|
+
grant, run it once with --request-grant. That flag ignores ODLA_DEV_TOKEN and
|
|
9518
|
+
the local cache, prints and opens a fresh exact-project owner-review URL, then
|
|
9519
|
+
continues provisioning with the approved replacement credential.
|
|
9498
9520
|
Run Code from a GitHub checkout already connected to an app in Studio; an
|
|
9499
9521
|
odla.config.mjs may select the app explicitly but is not required. Code host
|
|
9500
9522
|
approval and credential hashes live in odla-ai/db. The host
|
|
@@ -12796,6 +12818,7 @@ async function provisionCommand(parsed, dependencies) {
|
|
|
12796
12818
|
"write-credentials",
|
|
12797
12819
|
"write-dev-vars",
|
|
12798
12820
|
"token",
|
|
12821
|
+
"request-grant",
|
|
12799
12822
|
"email",
|
|
12800
12823
|
"open",
|
|
12801
12824
|
"wait",
|
|
@@ -12811,6 +12834,7 @@ async function provisionCommand(parsed, dependencies) {
|
|
|
12811
12834
|
writeCredentials: parsed.options["write-credentials"] !== false,
|
|
12812
12835
|
writeDevVars: typeof writeDevVars2 === "string" ? writeDevVars2 : writeDevVars2 === true,
|
|
12813
12836
|
token: stringOpt(parsed.options.token),
|
|
12837
|
+
requestGrant: parsed.options["request-grant"] === true,
|
|
12814
12838
|
email: stringOpt(parsed.options.email),
|
|
12815
12839
|
open: parsed.options.open === false ? false : parsed.options.open === true ? true : void 0,
|
|
12816
12840
|
wait: numberOpt(parsed.options.wait, "--wait"),
|
|
@@ -12906,4 +12930,4 @@ export {
|
|
|
12906
12930
|
exitCodeFor,
|
|
12907
12931
|
runCli
|
|
12908
12932
|
};
|
|
12909
|
-
//# sourceMappingURL=chunk-
|
|
12933
|
+
//# sourceMappingURL=chunk-3YSCRXPF.js.map
|