@odla-ai/cli 0.27.12 → 0.27.14
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 +118 -19
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +76 -2
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-ECRBOR66.js → chunk-3SQ2XUBB.js} +49 -20
- package/dist/chunk-3SQ2XUBB.js.map +1 -0
- package/dist/index.cjs +45 -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/index.cjs
CHANGED
|
@@ -386,23 +386,30 @@ function handshakeWaitMs(waitSeconds, interactive = import_node_process3.default
|
|
|
386
386
|
|
|
387
387
|
// src/token.ts
|
|
388
388
|
async function getDeveloperToken(cfg, options, doFetch, out, grantRequest = {}) {
|
|
389
|
-
if (options.token) return options.token;
|
|
390
389
|
const audience = platformAudience(cfg.platformUrl);
|
|
391
|
-
if (import_node_process4.default.env.ODLA_DEV_TOKEN) {
|
|
392
|
-
const declared = import_node_process4.default.env.ODLA_DEV_TOKEN_AUDIENCE;
|
|
393
|
-
if (declared) {
|
|
394
|
-
if (platformAudience(declared) !== audience) throw new Error("ODLA_DEV_TOKEN_AUDIENCE does not match the configured platform");
|
|
395
|
-
} else if (audience !== "https://odla.ai") {
|
|
396
|
-
throw new Error("ODLA_DEV_TOKEN_AUDIENCE is required for a non-default platform");
|
|
397
|
-
}
|
|
398
|
-
return import_node_process4.default.env.ODLA_DEV_TOKEN;
|
|
399
|
-
}
|
|
400
390
|
const optionalProjectCapabilities = grantRequest.optionalProjectCapabilities ?? [];
|
|
401
391
|
const grantIntent = { projectIds: [cfg.app.id], optionalProjectCapabilities };
|
|
402
392
|
const cached = readJsonFile(cfg.local.tokenFile);
|
|
403
|
-
if (
|
|
404
|
-
|
|
405
|
-
|
|
393
|
+
if (!grantRequest.forceReview) {
|
|
394
|
+
if (options.token) return options.token;
|
|
395
|
+
if (import_node_process4.default.env.ODLA_DEV_TOKEN) {
|
|
396
|
+
const declared = import_node_process4.default.env.ODLA_DEV_TOKEN_AUDIENCE;
|
|
397
|
+
if (declared) {
|
|
398
|
+
if (platformAudience(declared) !== audience) throw new Error("ODLA_DEV_TOKEN_AUDIENCE does not match the configured platform");
|
|
399
|
+
} else if (audience !== "https://odla.ai") {
|
|
400
|
+
throw new Error("ODLA_DEV_TOKEN_AUDIENCE is required for a non-default platform");
|
|
401
|
+
}
|
|
402
|
+
return import_node_process4.default.env.ODLA_DEV_TOKEN;
|
|
403
|
+
}
|
|
404
|
+
if (cached?.token && cached.platform === audience && (cached.expiresAt ?? 0) > Date.now() + 6e4 && cachedGrantCovers(cached, grantIntent)) {
|
|
405
|
+
out.error(`auth: using cached developer token (${displayPath(cfg.local.tokenFile, cfg.rootDir)})`);
|
|
406
|
+
return cached.token;
|
|
407
|
+
}
|
|
408
|
+
} else {
|
|
409
|
+
if (options.token) {
|
|
410
|
+
throw new Error("--request-grant cannot be combined with --token; remove --token so the approved replacement credential can be collected and cached");
|
|
411
|
+
}
|
|
412
|
+
out.error(`auth: requesting fresh owner review for app.manage on exact project "${cfg.app.id}"`);
|
|
406
413
|
}
|
|
407
414
|
const ctx = {
|
|
408
415
|
cfg,
|
|
@@ -2899,11 +2906,11 @@ async function assertTenantAdminAccess(doFetch, cfg, env, token) {
|
|
|
2899
2906
|
}
|
|
2900
2907
|
if (code === "provision_approval_required") {
|
|
2901
2908
|
throw new Error(
|
|
2902
|
-
`${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.
|
|
2909
|
+
`${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`
|
|
2903
2910
|
);
|
|
2904
2911
|
}
|
|
2905
2912
|
throw new Error(
|
|
2906
|
-
`${env}: this credential lacks live app.manage authority for "${cfg.app.id}" (tenant ${tenantId}) \u2014 nothing was minted or written;
|
|
2913
|
+
`${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`
|
|
2907
2914
|
);
|
|
2908
2915
|
}
|
|
2909
2916
|
throw new Error(`${env}: tenant access preflight (${tenantId}) failed: ${res.status} ${await safeText4(res)}`);
|
|
@@ -8652,7 +8659,7 @@ Usage:
|
|
|
8652
8659
|
odla-ai security report <job-id> [--json]
|
|
8653
8660
|
odla-ai security run [target] --ack-redacted-source [--env dev] [--profile odla] [--fail-on high]
|
|
8654
8661
|
odla-ai security run [target] --self --ack-redacted-source
|
|
8655
|
-
odla-ai provision [--config odla.config.mjs] [--email <odla-account>] [--wait <seconds>] [--dry-run] [--push-secrets] [--rotate-o11y-token] [--write-dev-vars[=path]] [--yes]
|
|
8662
|
+
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]
|
|
8656
8663
|
odla-ai smoke [--config odla.config.mjs] [--env dev] [--email <odla-account>] [--no-open]
|
|
8657
8664
|
odla-ai skill install [--dir <project>] [--agent <name>] [--global] [--force]
|
|
8658
8665
|
odla-ai secrets push --env <env> [--config odla.config.mjs] [--dry-run] [--yes]
|
|
@@ -8787,6 +8794,13 @@ Safety:
|
|
|
8787
8794
|
The email is a non-secret identity hint: never provide a password or session
|
|
8788
8795
|
token. The matching account must already exist, be signed in, explicitly
|
|
8789
8796
|
review the exact code, and finish any current request before claiming another.
|
|
8797
|
+
If provision reports that the current agent principal has no live app.manage
|
|
8798
|
+
grant, run it once with --request-grant. That flag ignores ODLA_DEV_TOKEN and
|
|
8799
|
+
the local cache, prints and opens a fresh exact-project owner-review URL, then
|
|
8800
|
+
continues provisioning with the approved replacement credential.
|
|
8801
|
+
Before a non-dry-run provision, the executable checks npm's current CLI
|
|
8802
|
+
release. A confirmed stale client stops with a safe npx rerun command; a
|
|
8803
|
+
workspace-linked client also identifies the worktree that must be updated.
|
|
8790
8804
|
Run Code from a GitHub checkout already connected to an app in Studio; an
|
|
8791
8805
|
odla.config.mjs may select the app explicitly but is not required. Code host
|
|
8792
8806
|
approval and credential hashes live in odla-ai/db. The host
|
|
@@ -10752,14 +10766,25 @@ async function provision(options) {
|
|
|
10752
10766
|
}
|
|
10753
10767
|
const doFetch = options.fetch ?? fetch;
|
|
10754
10768
|
const token = await getDeveloperToken(cfg, options, doFetch, out, {
|
|
10755
|
-
optionalProjectCapabilities: ["app.manage"]
|
|
10769
|
+
optionalProjectCapabilities: ["app.manage"],
|
|
10770
|
+
forceReview: options.requestGrant
|
|
10756
10771
|
});
|
|
10757
10772
|
const apps = (0, import_apps12.createAppsClient)({ endpoint: cfg.platformUrl, token, fetcher: { fetch: doFetch } });
|
|
10758
10773
|
const existing = await apps.resolveApp(cfg.app.id);
|
|
10759
10774
|
if (existing) {
|
|
10760
10775
|
out.log(`app: ${cfg.app.id} already exists`);
|
|
10761
10776
|
} else {
|
|
10762
|
-
|
|
10777
|
+
try {
|
|
10778
|
+
await apps.createApp({ name: cfg.app.name, appId: cfg.app.id });
|
|
10779
|
+
} catch (error) {
|
|
10780
|
+
if (error instanceof import_apps12.AppsError && error.status === 403) {
|
|
10781
|
+
throw new Error(
|
|
10782
|
+
`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`,
|
|
10783
|
+
{ cause: error }
|
|
10784
|
+
);
|
|
10785
|
+
}
|
|
10786
|
+
throw error;
|
|
10787
|
+
}
|
|
10763
10788
|
out.log(`app: created ${cfg.app.id}`);
|
|
10764
10789
|
}
|
|
10765
10790
|
for (const env of cfg.envs) {
|
|
@@ -12878,6 +12903,7 @@ async function provisionCommand(parsed, dependencies) {
|
|
|
12878
12903
|
"write-credentials",
|
|
12879
12904
|
"write-dev-vars",
|
|
12880
12905
|
"token",
|
|
12906
|
+
"request-grant",
|
|
12881
12907
|
"email",
|
|
12882
12908
|
"open",
|
|
12883
12909
|
"wait",
|
|
@@ -12893,6 +12919,7 @@ async function provisionCommand(parsed, dependencies) {
|
|
|
12893
12919
|
writeCredentials: parsed.options["write-credentials"] !== false,
|
|
12894
12920
|
writeDevVars: typeof writeDevVars2 === "string" ? writeDevVars2 : writeDevVars2 === true,
|
|
12895
12921
|
token: stringOpt(parsed.options.token),
|
|
12922
|
+
requestGrant: parsed.options["request-grant"] === true,
|
|
12896
12923
|
email: stringOpt(parsed.options.email),
|
|
12897
12924
|
open: parsed.options.open === false ? false : parsed.options.open === true ? true : void 0,
|
|
12898
12925
|
wait: numberOpt(parsed.options.wait, "--wait"),
|