@odla-ai/cli 0.2.1 → 0.4.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 +123 -58
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-5J4LKP37.js → chunk-UWT7C6VT.js} +124 -59
- package/dist/chunk-UWT7C6VT.js.map +1 -0
- package/dist/index.cjs +123 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +1 -1
- package/llms.txt +10 -1
- package/package.json +1 -1
- package/skills/odla/SKILL.md +76 -0
- package/skills/odla/references/build.md +58 -0
- package/skills/odla/references/sdks.md +64 -0
- package/skills/odla-migrate/references/phase-3-auth.md +7 -2
- package/skills/odla-migrate/references/secrets-map.md +6 -4
- package/dist/chunk-5J4LKP37.js.map +0 -1
|
@@ -6,6 +6,7 @@ var REPLACEMENTS = [
|
|
|
6
6
|
[/\bsk_(live|test)_[A-Za-z0-9]+/g, "sk_$1_[redacted]"],
|
|
7
7
|
[/\bsk-[A-Za-z0-9._-]+/g, "sk-[redacted]"],
|
|
8
8
|
[/\bwhsec_[A-Za-z0-9+/=]+/g, "whsec_[redacted]"],
|
|
9
|
+
[/\bo11y_[A-Za-z0-9]+/g, "o11y_[redacted]"],
|
|
9
10
|
[/\b(ghp|gho|github_pat)_[A-Za-z0-9_]+/g, "$1_[redacted]"],
|
|
10
11
|
[/\bAKIA[A-Z0-9]{12,}/g, "AKIA[redacted]"]
|
|
11
12
|
];
|
|
@@ -260,7 +261,7 @@ function wranglerWarnings(rootDir) {
|
|
|
260
261
|
const vars = block.vars;
|
|
261
262
|
if (vars && typeof vars === "object") {
|
|
262
263
|
for (const [name, value] of Object.entries(vars)) {
|
|
263
|
-
if (name === "ODLA_API_KEY" || typeof value === "string" && looksSecret(value)) {
|
|
264
|
+
if (name === "ODLA_API_KEY" || name === "ODLA_O11Y_TOKEN" || typeof value === "string" && looksSecret(value)) {
|
|
264
265
|
warnings.push(`wrangler ${label}vars.${name} looks like a secret \u2014 use "odla-ai secrets push" / wrangler secret put, never vars`);
|
|
265
266
|
}
|
|
266
267
|
}
|
|
@@ -280,54 +281,6 @@ function readPackageJson(rootDir) {
|
|
|
280
281
|
}
|
|
281
282
|
}
|
|
282
283
|
|
|
283
|
-
// src/doctor.ts
|
|
284
|
-
async function doctor(options) {
|
|
285
|
-
const out = options.stdout ?? console;
|
|
286
|
-
const cfg = await loadProjectConfig(options.configPath);
|
|
287
|
-
const plan = buildPlan(cfg);
|
|
288
|
-
const schema = await resolveDataExport(cfg, cfg.db?.schema, ["schema", "SCHEMA"]);
|
|
289
|
-
const configuredRules = await resolveDataExport(cfg, cfg.db?.rules, ["rules", "RULES"]);
|
|
290
|
-
const rules = configuredRules ?? (schema && cfg.db?.defaultRules !== false ? rulesFromSchema(schema) : void 0);
|
|
291
|
-
const entities = serializedEntities(schema);
|
|
292
|
-
out.log(`config: ${cfg.configPath}`);
|
|
293
|
-
out.log(`app: ${plan.appName} (${plan.appId})`);
|
|
294
|
-
out.log(`envs: ${plan.envs.join(", ")}`);
|
|
295
|
-
out.log(`svc: ${plan.services.join(", ")}`);
|
|
296
|
-
out.log(`schema: ${schema ? `${entities.length} entities` : "none"}`);
|
|
297
|
-
out.log(`rules: ${rules ? `${Object.keys(rules).length} namespaces` : "none"}`);
|
|
298
|
-
out.log(`ai: ${cfg.ai?.provider ?? "not configured"}`);
|
|
299
|
-
const warnings = [];
|
|
300
|
-
if (schema && entities.length === 0) warnings.push("schema has no entities");
|
|
301
|
-
if (rules) {
|
|
302
|
-
for (const ns of Object.keys(rules)) {
|
|
303
|
-
if (entities.length > 0 && !entities.includes(ns)) warnings.push(`rules include "${ns}" but schema has no matching entity`);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
if (cfg.services.includes("ai") && !cfg.ai?.provider) warnings.push("ai service is enabled but ai.provider is not set");
|
|
307
|
-
if (cfg.auth?.clerk) {
|
|
308
|
-
for (const [env, value] of Object.entries(cfg.auth.clerk)) {
|
|
309
|
-
if (typeof value === "string" && value.startsWith("$") && !process.env[value.slice(1)]) {
|
|
310
|
-
warnings.push(`auth.clerk.${env} references unset env var ${value}`);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
if (cfg.ai?.keyEnv && !process.env[cfg.ai.keyEnv]) warnings.push(`${cfg.ai.keyEnv} is not set; provision will skip provider key storage`);
|
|
315
|
-
warnings.push(...lintRules(rules, entities, cfg.db?.publicRead ?? []));
|
|
316
|
-
warnings.push(...trackedSecretFiles(cfg.rootDir));
|
|
317
|
-
warnings.push(...wranglerWarnings(cfg.rootDir));
|
|
318
|
-
if (warnings.length) {
|
|
319
|
-
out.log("");
|
|
320
|
-
out.log("warnings:");
|
|
321
|
-
for (const warning of warnings) out.log(` - ${warning}`);
|
|
322
|
-
} else {
|
|
323
|
-
out.log("ok");
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
// src/init.ts
|
|
328
|
-
import { existsSync as existsSync5, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
329
|
-
import { dirname as dirname3, resolve as resolve4 } from "path";
|
|
330
|
-
|
|
331
284
|
// src/local.ts
|
|
332
285
|
import { chmodSync, existsSync as existsSync4, mkdirSync, readFileSync as readFileSync4, writeFileSync } from "fs";
|
|
333
286
|
import { dirname as dirname2, relative, resolve as resolve3 } from "path";
|
|
@@ -363,7 +316,8 @@ function mergeCredential(current, update) {
|
|
|
363
316
|
next.envs[update.env] = {
|
|
364
317
|
...next.envs[update.env] ?? {},
|
|
365
318
|
tenantId: update.tenantId,
|
|
366
|
-
...update.dbKey ? { dbKey: update.dbKey } : {}
|
|
319
|
+
...update.dbKey ? { dbKey: update.dbKey } : {},
|
|
320
|
+
...update.o11yToken ? { o11yToken: update.o11yToken } : {}
|
|
367
321
|
};
|
|
368
322
|
return next;
|
|
369
323
|
}
|
|
@@ -376,7 +330,7 @@ function ensureGitignore(rootDir) {
|
|
|
376
330
|
writeFileSync(path, `${existing}${prefix}${missing.join("\n")}
|
|
377
331
|
`);
|
|
378
332
|
}
|
|
379
|
-
function writeDevVars(path, credentials, env) {
|
|
333
|
+
function writeDevVars(path, credentials, env, o11y) {
|
|
380
334
|
const entry = credentials.envs[env];
|
|
381
335
|
if (!entry?.dbKey) throw new Error(`no db key for env "${env}" in ${path}`);
|
|
382
336
|
const lines = [
|
|
@@ -387,6 +341,11 @@ function writeDevVars(path, credentials, env) {
|
|
|
387
341
|
`ODLA_TENANT="${entry.tenantId}"`,
|
|
388
342
|
`ODLA_API_KEY="${entry.dbKey}"`
|
|
389
343
|
];
|
|
344
|
+
if (o11y) {
|
|
345
|
+
lines.push(`ODLA_O11Y_ENDPOINT="${o11y.endpoint}"`, `ODLA_O11Y_SERVICE="${o11y.service}"`);
|
|
346
|
+
if (o11y.version) lines.push(`ODLA_O11Y_VERSION="${o11y.version}"`);
|
|
347
|
+
if (entry.o11yToken) lines.push(`ODLA_O11Y_TOKEN="${entry.o11yToken}"`);
|
|
348
|
+
}
|
|
390
349
|
mkdirSync(dirname2(path), { recursive: true });
|
|
391
350
|
writeFileSync(path, `${lines.join("\n")}
|
|
392
351
|
`);
|
|
@@ -397,7 +356,61 @@ function displayPath(path, rootDir = process.cwd()) {
|
|
|
397
356
|
return rel && !rel.startsWith("..") ? rel : path;
|
|
398
357
|
}
|
|
399
358
|
|
|
359
|
+
// src/doctor.ts
|
|
360
|
+
async function doctor(options) {
|
|
361
|
+
const out = options.stdout ?? console;
|
|
362
|
+
const cfg = await loadProjectConfig(options.configPath);
|
|
363
|
+
const plan = buildPlan(cfg);
|
|
364
|
+
const schema = await resolveDataExport(cfg, cfg.db?.schema, ["schema", "SCHEMA"]);
|
|
365
|
+
const configuredRules = await resolveDataExport(cfg, cfg.db?.rules, ["rules", "RULES"]);
|
|
366
|
+
const rules = configuredRules ?? (schema && cfg.db?.defaultRules !== false ? rulesFromSchema(schema) : void 0);
|
|
367
|
+
const entities = serializedEntities(schema);
|
|
368
|
+
out.log(`config: ${cfg.configPath}`);
|
|
369
|
+
out.log(`app: ${plan.appName} (${plan.appId})`);
|
|
370
|
+
out.log(`envs: ${plan.envs.join(", ")}`);
|
|
371
|
+
out.log(`svc: ${plan.services.join(", ")}`);
|
|
372
|
+
out.log(`schema: ${schema ? `${entities.length} entities` : "none"}`);
|
|
373
|
+
out.log(`rules: ${rules ? `${Object.keys(rules).length} namespaces` : "none"}`);
|
|
374
|
+
out.log(`ai: ${cfg.ai?.provider ?? "not configured"}`);
|
|
375
|
+
const warnings = [];
|
|
376
|
+
if (schema && entities.length === 0) warnings.push("schema has no entities");
|
|
377
|
+
if (rules) {
|
|
378
|
+
for (const ns of Object.keys(rules)) {
|
|
379
|
+
if (entities.length > 0 && !entities.includes(ns)) warnings.push(`rules include "${ns}" but schema has no matching entity`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
if (cfg.services.includes("ai") && !cfg.ai?.provider) warnings.push("ai service is enabled but ai.provider is not set");
|
|
383
|
+
if (cfg.auth?.clerk) {
|
|
384
|
+
for (const [env, value] of Object.entries(cfg.auth.clerk)) {
|
|
385
|
+
if (typeof value === "string" && value.startsWith("$") && !process.env[value.slice(1)]) {
|
|
386
|
+
warnings.push(`auth.clerk.${env} references unset env var ${value}`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
if (cfg.ai?.keyEnv && !process.env[cfg.ai.keyEnv]) warnings.push(`${cfg.ai.keyEnv} is not set; provision will skip provider key storage`);
|
|
391
|
+
if (cfg.services.includes("o11y")) {
|
|
392
|
+
const credentials = readCredentials(cfg.local.credentialsFile);
|
|
393
|
+
for (const env of cfg.envs) {
|
|
394
|
+
if (!credentials?.envs[env]?.o11yToken) {
|
|
395
|
+
warnings.push(`o11y is enabled but env "${env}" has no ingest token \u2014 run "odla-ai provision" to mint one`);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
warnings.push(...lintRules(rules, entities, cfg.db?.publicRead ?? []));
|
|
400
|
+
warnings.push(...trackedSecretFiles(cfg.rootDir));
|
|
401
|
+
warnings.push(...wranglerWarnings(cfg.rootDir));
|
|
402
|
+
if (warnings.length) {
|
|
403
|
+
out.log("");
|
|
404
|
+
out.log("warnings:");
|
|
405
|
+
for (const warning of warnings) out.log(` - ${warning}`);
|
|
406
|
+
} else {
|
|
407
|
+
out.log("ok");
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
400
411
|
// src/init.ts
|
|
412
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
413
|
+
import { dirname as dirname3, resolve as resolve4 } from "path";
|
|
401
414
|
function initProject(options) {
|
|
402
415
|
const out = options.stdout ?? console;
|
|
403
416
|
const rootDir = resolve4(options.rootDir ?? process.cwd());
|
|
@@ -454,6 +467,12 @@ function configTemplate(input) {
|
|
|
454
467
|
// prod: "$CLERK_PUBLISHABLE_KEY",
|
|
455
468
|
},
|
|
456
469
|
},
|
|
470
|
+
// Add "o11y" to services to enable observability; provision then mints the
|
|
471
|
+
// ingest token and scaffolds the ODLA_O11Y_* vars into .dev.vars.
|
|
472
|
+
// o11y: {
|
|
473
|
+
// service: "${input.appId}", // defaults to the app id
|
|
474
|
+
// // endpoint: "https://o11y.odla.ai",
|
|
475
|
+
// },
|
|
457
476
|
links: {
|
|
458
477
|
// dev: "https://dev.example.com",
|
|
459
478
|
// prod: "https://example.com",
|
|
@@ -654,6 +673,15 @@ async function provision(options) {
|
|
|
654
673
|
dbKey = await mintDbKey({ cfg, tenantId, env, token, auth, fetch: doFetch });
|
|
655
674
|
out.log(`${env}: minted db key for ${tenantId}`);
|
|
656
675
|
}
|
|
676
|
+
let o11yToken = cfg.services.includes("o11y") && !options.rotateKeys ? credentials?.envs[env]?.o11yToken : void 0;
|
|
677
|
+
if (cfg.services.includes("o11y")) {
|
|
678
|
+
if (o11yToken) {
|
|
679
|
+
out.log(`${env}: reusing local o11y ingest token`);
|
|
680
|
+
} else {
|
|
681
|
+
o11yToken = await mintO11yToken(cfg, env, token, doFetch);
|
|
682
|
+
out.log(`${env}: minted o11y ingest token`);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
657
685
|
if (schema) {
|
|
658
686
|
await postJson(doFetch, `${cfg.dbEndpoint}/app/${encodeURIComponent(tenantId)}/schema`, dbKey, { schema });
|
|
659
687
|
out.log(`${env}: schema pushed`);
|
|
@@ -678,7 +706,8 @@ async function provision(options) {
|
|
|
678
706
|
dbEndpoint: cfg.dbEndpoint,
|
|
679
707
|
env,
|
|
680
708
|
tenantId,
|
|
681
|
-
dbKey
|
|
709
|
+
dbKey,
|
|
710
|
+
...o11yToken ? { o11yToken } : {}
|
|
682
711
|
});
|
|
683
712
|
}
|
|
684
713
|
if (cfg.local.gitignore) ensureGitignore(cfg.rootDir);
|
|
@@ -689,10 +718,18 @@ async function provision(options) {
|
|
|
689
718
|
const devVarsTarget = resolveWriteDevVarsTarget(cfg, options.writeDevVars);
|
|
690
719
|
if (devVarsTarget && credentials) {
|
|
691
720
|
const env = cfg.envs.includes("dev") ? "dev" : cfg.envs[0] ?? "prod";
|
|
692
|
-
writeDevVars(devVarsTarget, credentials, env);
|
|
721
|
+
writeDevVars(devVarsTarget, credentials, env, o11yDevVars(cfg));
|
|
693
722
|
out.log(`dev vars: wrote ${displayPath(devVarsTarget, cfg.rootDir)} for ${env}`);
|
|
694
723
|
}
|
|
695
724
|
}
|
|
725
|
+
function o11yDevVars(cfg) {
|
|
726
|
+
if (!cfg.services.includes("o11y")) return void 0;
|
|
727
|
+
return {
|
|
728
|
+
endpoint: cfg.o11y?.endpoint ?? "https://o11y.odla.ai",
|
|
729
|
+
service: cfg.o11y?.service ?? cfg.app.id,
|
|
730
|
+
...cfg.o11y?.version ? { version: cfg.o11y.version } : {}
|
|
731
|
+
};
|
|
732
|
+
}
|
|
696
733
|
async function readRegistryApp(cfg, token, doFetch) {
|
|
697
734
|
const res = await doFetch(`${cfg.platformUrl}/registry/apps/${encodeURIComponent(cfg.app.id)}`, {
|
|
698
735
|
headers: { authorization: `Bearer ${token}` }
|
|
@@ -729,6 +766,16 @@ async function mintDbKey(opts) {
|
|
|
729
766
|
if (!body.key) throw new Error(`db key mint (${opts.tenantId}) returned no key`);
|
|
730
767
|
return body.key;
|
|
731
768
|
}
|
|
769
|
+
async function mintO11yToken(cfg, env, token, doFetch) {
|
|
770
|
+
const res = await doFetch(
|
|
771
|
+
`${cfg.platformUrl}/o11y/${encodeURIComponent(cfg.app.id)}/token?env=${encodeURIComponent(env)}`,
|
|
772
|
+
{ method: "POST", headers: { authorization: `Bearer ${token}` } }
|
|
773
|
+
);
|
|
774
|
+
if (!res.ok) throw new Error(`o11y token mint (${env}) failed: ${res.status} ${await safeText(res)}`);
|
|
775
|
+
const body = await res.json();
|
|
776
|
+
if (!body.token) throw new Error(`o11y token mint (${env}) returned no token`);
|
|
777
|
+
return body.token;
|
|
778
|
+
}
|
|
732
779
|
async function postJson(doFetch, url, bearer, body) {
|
|
733
780
|
const res = await doFetch(url, {
|
|
734
781
|
method: "POST",
|
|
@@ -791,19 +838,24 @@ async function secretsPush(options) {
|
|
|
791
838
|
}
|
|
792
839
|
const wranglerEnv = PROD_ENV_NAMES.has(env) ? void 0 : env;
|
|
793
840
|
const target = wranglerEnv ? `wrangler env "${wranglerEnv}"` : "the top-level (prod) wrangler env";
|
|
841
|
+
const secrets = [{ name: "ODLA_API_KEY", value: dbKey }];
|
|
842
|
+
const o11yToken = credentials.envs[env]?.o11yToken;
|
|
843
|
+
if (o11yToken) secrets.push({ name: "ODLA_O11Y_TOKEN", value: o11yToken });
|
|
794
844
|
if (options.dryRun) {
|
|
795
|
-
out.log(`dry run: would push
|
|
845
|
+
for (const s of secrets) out.log(`dry run: would push ${s.name} (${redactSecrets(s.value)}) to ${target}`);
|
|
796
846
|
return;
|
|
797
847
|
}
|
|
798
848
|
const run = options.runner ?? defaultRunner;
|
|
799
849
|
if (!await wranglerLoggedIn(run, cfg.rootDir)) {
|
|
800
850
|
throw new Error(`wrangler is not logged in \u2014 run "wrangler login" (a browser step for the human)`);
|
|
801
851
|
}
|
|
802
|
-
const
|
|
803
|
-
|
|
804
|
-
|
|
852
|
+
for (const s of secrets) {
|
|
853
|
+
const result = await wranglerPutSecret(run, { name: s.name, value: s.value, env: wranglerEnv, cwd: cfg.rootDir });
|
|
854
|
+
if (result.code !== 0) {
|
|
855
|
+
throw new Error(`wrangler secret put ${s.name} failed (exit ${result.code}): ${redactSecrets(`${result.stderr || result.stdout}`.trim())}`);
|
|
856
|
+
}
|
|
857
|
+
out.log(`${s.name} pushed to ${target} (value read from ${credentialsPath}, never echoed)`);
|
|
805
858
|
}
|
|
806
|
-
out.log(`ODLA_API_KEY pushed to ${target} (value read from ${credentialsPath}, never echoed)`);
|
|
807
859
|
}
|
|
808
860
|
|
|
809
861
|
// src/skill.ts
|
|
@@ -998,6 +1050,17 @@ async function runCli(argv = process.argv.slice(2)) {
|
|
|
998
1050
|
});
|
|
999
1051
|
return;
|
|
1000
1052
|
}
|
|
1053
|
+
if (command === "setup") {
|
|
1054
|
+
installSkill({
|
|
1055
|
+
dir: stringOpt(parsed.options.dir),
|
|
1056
|
+
global: parsed.options.global === true,
|
|
1057
|
+
force: parsed.options.force === true
|
|
1058
|
+
});
|
|
1059
|
+
console.log(
|
|
1060
|
+
"\nSkills installed. Point your coding agent at this repo \u2014 the `odla` skill orients it\n(build a new app, or migrate an existing site) and drives `odla-ai init` / `provision`."
|
|
1061
|
+
);
|
|
1062
|
+
return;
|
|
1063
|
+
}
|
|
1001
1064
|
if (command === "skill") {
|
|
1002
1065
|
const sub = parsed.positionals[1];
|
|
1003
1066
|
if (sub !== "install") throw new Error(`unknown skill subcommand "${sub ?? ""}". Try "odla-ai skill install".`);
|
|
@@ -1084,6 +1147,7 @@ function printHelp() {
|
|
|
1084
1147
|
console.log(`odla-ai
|
|
1085
1148
|
|
|
1086
1149
|
Usage:
|
|
1150
|
+
odla-ai setup [--dir <project>] [--global] [--force]
|
|
1087
1151
|
odla-ai init --app-id <id> --name <name> [--services db,ai] [--env dev --env prod]
|
|
1088
1152
|
odla-ai doctor [--config odla.config.mjs]
|
|
1089
1153
|
odla-ai provision [--config odla.config.mjs] [--dry-run] [--open|--no-open] [--rotate-keys] [--write-dev-vars[=path]]
|
|
@@ -1093,6 +1157,7 @@ Usage:
|
|
|
1093
1157
|
odla-ai version
|
|
1094
1158
|
|
|
1095
1159
|
Commands:
|
|
1160
|
+
setup Install the odla skills so a coding agent can drive the rest.
|
|
1096
1161
|
init Create a generic odla.config.mjs plus starter schema/rules files.
|
|
1097
1162
|
doctor Validate and summarize the project config without network calls.
|
|
1098
1163
|
provision Register the app, enable services, push schema/rules, configure AI/auth.
|
|
@@ -1119,4 +1184,4 @@ export {
|
|
|
1119
1184
|
smoke,
|
|
1120
1185
|
runCli
|
|
1121
1186
|
};
|
|
1122
|
-
//# sourceMappingURL=chunk-
|
|
1187
|
+
//# sourceMappingURL=chunk-UWT7C6VT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/redact.ts","../src/config.ts","../src/doctor-checks.ts","../src/wrangler.ts","../src/local.ts","../src/doctor.ts","../src/init.ts","../src/provision.ts","../src/token.ts","../src/open.ts","../src/secrets.ts","../src/skill.ts","../src/smoke.ts","../src/cli.ts"],"sourcesContent":["/**\n * Secret redaction shared by every command's output path and by doctor's\n * \"does this value look like a secret\" checks. Clerk publishable keys\n * (pk_test_/pk_live_) are public by design and are deliberately not matched.\n */\nconst REPLACEMENTS: Array<[RegExp, string]> = [\n [/odla_(sk|dev)_[A-Za-z0-9._-]+/g, \"odla_$1_[redacted]\"],\n [/\\bsk_(live|test)_[A-Za-z0-9]+/g, \"sk_$1_[redacted]\"],\n [/\\bsk-[A-Za-z0-9._-]+/g, \"sk-[redacted]\"],\n [/\\bwhsec_[A-Za-z0-9+/=]+/g, \"whsec_[redacted]\"],\n [/\\bo11y_[A-Za-z0-9]+/g, \"o11y_[redacted]\"],\n [/\\b(ghp|gho|github_pat)_[A-Za-z0-9_]+/g, \"$1_[redacted]\"],\n [/\\bAKIA[A-Z0-9]{12,}/g, \"AKIA[redacted]\"],\n];\n\nexport function redactSecrets(value: string): string {\n let result = value;\n for (const [pattern, replacement] of REPLACEMENTS) result = result.replace(pattern, replacement);\n return result;\n}\n\n/** True when a value matches any known secret shape (used for detection, never display). */\nexport function looksSecret(value: string): boolean {\n return redactSecrets(value) !== value || value.includes(\"-----BEGIN\");\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { AppRules, LoadedProjectConfig, OdlaProjectConfig, ProvisionPlan } from \"./types\";\n\nconst DEFAULT_PLATFORM = \"https://odla.ai\";\nconst DEFAULT_ENVS = [\"prod\", \"dev\"];\nconst DEFAULT_SERVICES = [\"db\", \"ai\"];\n\nexport async function loadProjectConfig(configPath = \"odla.config.mjs\"): Promise<LoadedProjectConfig> {\n const resolved = resolve(configPath);\n if (!existsSync(resolved)) {\n throw new Error(`config not found: ${configPath}. Run \"odla-ai init\" first or pass --config.`);\n }\n\n const raw = await loadConfigModule(resolved);\n const rootDir = dirname(resolved);\n validateRawConfig(raw, resolved);\n\n const platformUrl = trimSlash(process.env.ODLA_PLATFORM_URL || raw.platformUrl || DEFAULT_PLATFORM);\n const dbEndpoint = trimSlash(process.env.ODLA_DB_ENDPOINT || raw.dbEndpoint || platformUrl);\n const envs = unique(raw.envs?.length ? raw.envs : DEFAULT_ENVS);\n const services = unique(raw.services?.length ? raw.services : DEFAULT_SERVICES);\n const local = {\n tokenFile: resolve(rootDir, raw.local?.tokenFile ?? \".odla/dev-token.json\"),\n credentialsFile: resolve(rootDir, raw.local?.credentialsFile ?? \".odla/credentials.local.json\"),\n devVarsFile: resolve(rootDir, raw.local?.devVarsFile ?? \".dev.vars\"),\n gitignore: raw.local?.gitignore ?? true,\n };\n\n return {\n ...raw,\n configPath: resolved,\n rootDir,\n platformUrl,\n dbEndpoint,\n envs,\n services,\n local,\n };\n}\n\nexport async function resolveDataExport<T>(\n cfg: LoadedProjectConfig,\n value: unknown,\n names: string[],\n): Promise<T | undefined> {\n if (value === undefined || value === null || value === false) return undefined;\n if (typeof value !== \"string\") return value as T;\n\n const target = isAbsolute(value) ? value : resolve(cfg.rootDir, value);\n if (target.endsWith(\".json\")) {\n return JSON.parse(readFileSync(target, \"utf8\")) as T;\n }\n const mod = (await import(pathToFileURL(target).href)) as Record<string, unknown>;\n for (const name of names) {\n if (mod[name] !== undefined) return mod[name] as T;\n }\n if (mod.default !== undefined) return mod.default as T;\n throw new Error(`${value} did not export ${names.join(\", \")} or default`);\n}\n\nexport function buildPlan(cfg: LoadedProjectConfig): ProvisionPlan {\n return {\n appId: cfg.app.id,\n appName: cfg.app.name,\n platformUrl: cfg.platformUrl,\n dbEndpoint: cfg.dbEndpoint,\n envs: cfg.envs,\n services: cfg.services,\n hasSchema: !!cfg.db?.schema,\n hasRules: !!cfg.db?.rules || (!!cfg.db?.schema && cfg.db.defaultRules !== false),\n aiProvider: cfg.ai?.provider,\n };\n}\n\nexport function rulesFromSchema(schema: unknown): AppRules {\n const entities = serializedEntities(schema);\n return Object.fromEntries(\n entities.map((name) => [name, { view: \"false\", create: \"false\", update: \"false\", delete: \"false\" }]),\n );\n}\n\nexport function serializedEntities(schema: unknown): string[] {\n if (!schema || typeof schema !== \"object\") return [];\n const entities = (schema as { entities?: unknown }).entities;\n if (!entities || typeof entities !== \"object\" || Array.isArray(entities)) return [];\n return Object.keys(entities);\n}\n\nexport function envValue(value: string | undefined): string | undefined {\n if (!value) return undefined;\n if (value.startsWith(\"$\")) return process.env[value.slice(1)];\n return value;\n}\n\nfunction validateRawConfig(raw: unknown, path: string): asserts raw is OdlaProjectConfig {\n if (!raw || typeof raw !== \"object\") throw new Error(`${path} must export an object`);\n const cfg = raw as OdlaProjectConfig;\n if (!cfg.app || typeof cfg.app !== \"object\") throw new Error(`${path}: missing app object`);\n if (!validId(cfg.app.id)) throw new Error(`${path}: app.id must be lowercase letters, numbers, and hyphens`);\n if (!cfg.app.name || typeof cfg.app.name !== \"string\") throw new Error(`${path}: app.name is required`);\n if (cfg.envs?.some((env) => !validId(env))) throw new Error(`${path}: env names must be lowercase letters, numbers, and hyphens`);\n}\n\nfunction validId(value: unknown): value is string {\n return typeof value === \"string\" && /^[a-z0-9][a-z0-9-]*$/.test(value);\n}\n\nasync function loadConfigModule(path: string): Promise<OdlaProjectConfig> {\n if (path.endsWith(\".json\")) return JSON.parse(readFileSync(path, \"utf8\")) as OdlaProjectConfig;\n const mod = (await import(`${pathToFileURL(path).href}?t=${Date.now()}`)) as {\n default?: OdlaProjectConfig | (() => OdlaProjectConfig | Promise<OdlaProjectConfig>);\n config?: OdlaProjectConfig;\n };\n const value = mod.default ?? mod.config;\n if (typeof value === \"function\") return await value();\n return value as OdlaProjectConfig;\n}\n\nfunction trimSlash(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n\nfunction unique(values: string[]): string[] {\n return [...new Set(values.filter(Boolean))];\n}\n","import { execFileSync } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { looksSecret } from \"./redact\";\nimport { findWranglerConfig, readWranglerConfig } from \"./wrangler\";\nimport type { AppRules } from \"./types\";\n\n/**\n * Rules lint: a literal \"true\" grants the action to every client. `view` may\n * be deliberate for public content — allowlist those namespaces via\n * `db.publicRead`; writes are never safely \"true\".\n */\nexport function lintRules(rules: AppRules | undefined, entities: string[], publicRead: string[]): string[] {\n const warnings: string[] = [];\n if (!rules) return warnings;\n for (const [ns, actions] of Object.entries(rules)) {\n for (const [action, expr] of Object.entries(actions)) {\n if (typeof expr !== \"string\" || expr.trim() !== \"true\") continue;\n if (action === \"view\" && publicRead.includes(ns)) continue;\n warnings.push(\n action === \"view\"\n ? `rules.${ns}.view is \"true\" — public read; add \"${ns}\" to db.publicRead if intended`\n : `rules.${ns}.${action} is \"true\" — any client can ${action} ${ns} rows`,\n );\n }\n }\n for (const entity of entities) {\n if (!(entity in rules)) warnings.push(`schema entity \"${entity}\" has no rules entry (all client access denied)`);\n }\n return warnings;\n}\n\nexport type ExecLike = (cmd: string, args: string[], cwd: string) => string;\n\nconst defaultExec: ExecLike = (cmd, args, cwd) => execFileSync(cmd, args, { cwd, encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", \"ignore\"] });\n\n/** Credential files that must never be committed. Silent when git is absent. */\nexport function trackedSecretFiles(rootDir: string, exec: ExecLike = defaultExec): string[] {\n let output: string;\n try {\n output = exec(\"git\", [\"ls-files\", \"--\", \".dev.vars\", \".odla\"], rootDir);\n } catch {\n return [];\n }\n return output\n .split(/\\r?\\n/)\n .filter(Boolean)\n .map((path) => `${path} is tracked by git — run \"git rm --cached ${path}\" and commit; it belongs in .gitignore`);\n}\n\n/** Wrangler config sanity: the assets-dir footgun, secret-looking vars. */\nexport function wranglerWarnings(rootDir: string): string[] {\n const configPath = findWranglerConfig(rootDir);\n if (!configPath) return [];\n const config = readWranglerConfig(configPath);\n if (!config) return [];\n\n const warnings: string[] = [];\n const blocks: Array<{ label: string; block: Record<string, unknown> }> = [{ label: \"\", block: config }];\n const envs = config.env;\n if (envs && typeof envs === \"object\") {\n for (const [name, block] of Object.entries(envs as Record<string, unknown>)) {\n if (block && typeof block === \"object\") blocks.push({ label: `env.${name}.`, block: block as Record<string, unknown> });\n }\n }\n\n for (const { label, block } of blocks) {\n const assets = block.assets as { directory?: string } | undefined;\n if (assets?.directory) {\n const dir = resolve(rootDir, assets.directory);\n if (dir === resolve(rootDir)) {\n warnings.push(`${label}assets.directory is the project root — point it at a dedicated build dir (wrangler dev fails with \"spawn EBADF\")`);\n } else if (existsSync(join(dir, \"node_modules\"))) {\n warnings.push(`${label}assets.directory contains node_modules — wrangler dev's watcher will exhaust file descriptors`);\n }\n }\n const vars = block.vars;\n if (vars && typeof vars === \"object\") {\n for (const [name, value] of Object.entries(vars as Record<string, unknown>)) {\n if (name === \"ODLA_API_KEY\" || name === \"ODLA_O11Y_TOKEN\" || (typeof value === \"string\" && looksSecret(value))) {\n warnings.push(`wrangler ${label}vars.${name} looks like a secret — use \"odla-ai secrets push\" / wrangler secret put, never vars`);\n }\n }\n }\n }\n\n const pkg = readPackageJson(rootDir);\n if (pkg && typeof pkg.scripts === \"object\" && pkg.scripts && \"deploy\" in (pkg.scripts as Record<string, unknown>)) {\n warnings.push(`package.json has a script named \"deploy\" — CI may auto-deploy it; rename to deploy:app`);\n }\n return warnings;\n}\n\nfunction readPackageJson(rootDir: string): Record<string, unknown> | null {\n try {\n return JSON.parse(readFileSync(join(rootDir, \"package.json\"), \"utf8\")) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport interface RunResult {\n code: number;\n stdout: string;\n stderr: string;\n}\n\n/** Subprocess seam: injectable in tests, `defaultRunner` in production. */\nexport type CommandRunner = (cmd: string, args: string[], opts?: { input?: string; cwd?: string }) => Promise<RunResult>;\n\nexport const defaultRunner: CommandRunner = (cmd, args, opts) =>\n new Promise((resolvePromise, reject) => {\n const child = spawn(cmd, args, { cwd: opts?.cwd, stdio: [\"pipe\", \"pipe\", \"pipe\"] });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (chunk: Buffer) => (stdout += chunk.toString()));\n child.stderr.on(\"data\", (chunk: Buffer) => (stderr += chunk.toString()));\n child.on(\"error\", reject);\n child.on(\"close\", (code) => resolvePromise({ code: code ?? 1, stdout, stderr }));\n child.stdin.end(opts?.input ?? \"\");\n });\n\nconst WRANGLER_CONFIG_FILES = [\"wrangler.jsonc\", \"wrangler.json\", \"wrangler.toml\"];\n\nexport function findWranglerConfig(rootDir: string): string | null {\n for (const name of WRANGLER_CONFIG_FILES) {\n const path = join(rootDir, name);\n if (existsSync(path)) return path;\n }\n return null;\n}\n\n/** Parses wrangler.json/jsonc. Returns null for .toml (unparsed) or invalid JSON. */\nexport function readWranglerConfig(path: string): Record<string, unknown> | null {\n if (path.endsWith(\".toml\")) return null;\n try {\n return JSON.parse(stripJsonComments(readFileSync(path, \"utf8\"))) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\n/** Removes // and both-slash block comments without touching string contents. */\nexport function stripJsonComments(text: string): string {\n let result = \"\";\n let inString = false;\n for (let i = 0; i < text.length; i++) {\n const ch = text[i]!;\n if (inString) {\n result += ch;\n if (ch === \"\\\\\") {\n result += text[i + 1] ?? \"\";\n i++;\n } else if (ch === '\"') {\n inString = false;\n }\n continue;\n }\n if (ch === '\"') {\n inString = true;\n result += ch;\n continue;\n }\n if (ch === \"/\" && text[i + 1] === \"/\") {\n while (i < text.length && text[i] !== \"\\n\") i++;\n result += \"\\n\";\n continue;\n }\n if (ch === \"/\" && text[i + 1] === \"*\") {\n i += 2;\n while (i < text.length && !(text[i] === \"*\" && text[i + 1] === \"/\")) i++;\n i++;\n continue;\n }\n result += ch;\n }\n return result;\n}\n\nexport async function wranglerLoggedIn(run: CommandRunner, cwd: string): Promise<boolean> {\n try {\n const result = await run(\"npx\", [\"wrangler\", \"whoami\"], { cwd });\n return result.code === 0 && !/not authenticated/i.test(`${result.stdout}${result.stderr}`);\n } catch {\n return false;\n }\n}\n\n/** Pipes the value via stdin — it never appears on argv or in process listings. */\nexport function wranglerPutSecret(\n run: CommandRunner,\n opts: { name: string; value: string; env?: string; cwd: string },\n): Promise<RunResult> {\n const args = [\"wrangler\", \"secret\", \"put\", opts.name, ...(opts.env ? [\"--env\", opts.env] : [])];\n return run(\"npx\", args, { input: opts.value, cwd: opts.cwd });\n}\n","import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, relative, resolve } from \"node:path\";\nimport type { LocalCredentials } from \"./types\";\n\nconst GITIGNORE_LINES = [\".odla/*.local.json\", \".odla/dev-token.json\", \".dev.vars\"];\n\nexport function readJsonFile<T>(path: string): T | null {\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as T;\n } catch {\n return null;\n }\n}\n\nexport function writePrivateJson(path: string, value: unknown): void {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, `${JSON.stringify(value, null, 2)}\\n`);\n chmodSync(path, 0o600);\n}\n\nexport function readCredentials(path: string): LocalCredentials | null {\n return readJsonFile<LocalCredentials>(path);\n}\n\nexport function mergeCredential(\n current: LocalCredentials | null,\n update: { appId: string; platformUrl: string; dbEndpoint: string; env: string; tenantId: string; dbKey?: string; o11yToken?: string },\n): LocalCredentials {\n const next: LocalCredentials = current ?? {\n appId: update.appId,\n platformUrl: update.platformUrl,\n dbEndpoint: update.dbEndpoint,\n updatedAt: new Date(0).toISOString(),\n envs: {},\n };\n next.appId = update.appId;\n next.platformUrl = update.platformUrl;\n next.dbEndpoint = update.dbEndpoint;\n next.updatedAt = new Date().toISOString();\n next.envs[update.env] = {\n ...(next.envs[update.env] ?? {}),\n tenantId: update.tenantId,\n ...(update.dbKey ? { dbKey: update.dbKey } : {}),\n ...(update.o11yToken ? { o11yToken: update.o11yToken } : {}),\n };\n return next;\n}\n\nexport function ensureGitignore(rootDir: string): void {\n const path = resolve(rootDir, \".gitignore\");\n const existing = existsSync(path) ? readFileSync(path, \"utf8\") : \"\";\n const missing = GITIGNORE_LINES.filter((line) => !existing.split(/\\r?\\n/).includes(line));\n if (missing.length === 0) return;\n const prefix = existing && !existing.endsWith(\"\\n\") ? \"\\n\" : \"\";\n writeFileSync(path, `${existing}${prefix}${missing.join(\"\\n\")}\\n`);\n}\n\nexport interface O11yDevVars {\n endpoint: string;\n service: string;\n version?: string;\n}\n\nexport function writeDevVars(path: string, credentials: LocalCredentials, env: string, o11y?: O11yDevVars): void {\n const entry = credentials.envs[env];\n if (!entry?.dbKey) throw new Error(`no db key for env \"${env}\" in ${path}`);\n const lines = [\n `ODLA_PLATFORM=\"${credentials.platformUrl}\"`,\n `ODLA_ENDPOINT=\"${credentials.dbEndpoint}\"`,\n `ODLA_APP_ID=\"${credentials.appId}\"`,\n `ODLA_ENV=\"${env}\"`,\n `ODLA_TENANT=\"${entry.tenantId}\"`,\n `ODLA_API_KEY=\"${entry.dbKey}\"`,\n ];\n if (o11y) {\n lines.push(`ODLA_O11Y_ENDPOINT=\"${o11y.endpoint}\"`, `ODLA_O11Y_SERVICE=\"${o11y.service}\"`);\n if (o11y.version) lines.push(`ODLA_O11Y_VERSION=\"${o11y.version}\"`);\n // The ingest token is a secret; .dev.vars is gitignored (holds ODLA_API_KEY too).\n if (entry.o11yToken) lines.push(`ODLA_O11Y_TOKEN=\"${entry.o11yToken}\"`);\n }\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, `${lines.join(\"\\n\")}\\n`);\n chmodSync(path, 0o600);\n}\n\nexport function displayPath(path: string, rootDir = process.cwd()): string {\n const rel = relative(rootDir, path);\n return rel && !rel.startsWith(\"..\") ? rel : path;\n}\n","import { buildPlan, loadProjectConfig, resolveDataExport, rulesFromSchema, serializedEntities } from \"./config\";\nimport { lintRules, trackedSecretFiles, wranglerWarnings } from \"./doctor-checks\";\nimport { readCredentials } from \"./local\";\nimport type { AppRules } from \"./types\";\n\nexport interface DoctorOptions {\n configPath: string;\n stdout?: Pick<typeof console, \"log\" | \"error\">;\n}\n\nexport async function doctor(options: DoctorOptions): Promise<void> {\n const out = options.stdout ?? console;\n const cfg = await loadProjectConfig(options.configPath);\n const plan = buildPlan(cfg);\n const schema = await resolveDataExport<unknown>(cfg, cfg.db?.schema, [\"schema\", \"SCHEMA\"]);\n const configuredRules = await resolveDataExport<AppRules>(cfg, cfg.db?.rules, [\"rules\", \"RULES\"]);\n const rules = configuredRules ?? (schema && cfg.db?.defaultRules !== false ? rulesFromSchema(schema) : undefined);\n const entities = serializedEntities(schema);\n\n out.log(`config: ${cfg.configPath}`);\n out.log(`app: ${plan.appName} (${plan.appId})`);\n out.log(`envs: ${plan.envs.join(\", \")}`);\n out.log(`svc: ${plan.services.join(\", \")}`);\n out.log(`schema: ${schema ? `${entities.length} entities` : \"none\"}`);\n out.log(`rules: ${rules ? `${Object.keys(rules).length} namespaces` : \"none\"}`);\n out.log(`ai: ${cfg.ai?.provider ?? \"not configured\"}`);\n\n const warnings: string[] = [];\n if (schema && entities.length === 0) warnings.push(\"schema has no entities\");\n if (rules) {\n for (const ns of Object.keys(rules)) {\n if (entities.length > 0 && !entities.includes(ns)) warnings.push(`rules include \"${ns}\" but schema has no matching entity`);\n }\n }\n if (cfg.services.includes(\"ai\") && !cfg.ai?.provider) warnings.push(\"ai service is enabled but ai.provider is not set\");\n if (cfg.auth?.clerk) {\n for (const [env, value] of Object.entries(cfg.auth.clerk)) {\n if (typeof value === \"string\" && value.startsWith(\"$\") && !process.env[value.slice(1)]) {\n warnings.push(`auth.clerk.${env} references unset env var ${value}`);\n }\n }\n }\n if (cfg.ai?.keyEnv && !process.env[cfg.ai.keyEnv]) warnings.push(`${cfg.ai.keyEnv} is not set; provision will skip provider key storage`);\n if (cfg.services.includes(\"o11y\")) {\n // o11y enabled but no ingest token = telemetry silently rejected. Provision mints one.\n const credentials = readCredentials(cfg.local.credentialsFile);\n for (const env of cfg.envs) {\n if (!credentials?.envs[env]?.o11yToken) {\n warnings.push(`o11y is enabled but env \"${env}\" has no ingest token — run \"odla-ai provision\" to mint one`);\n }\n }\n }\n warnings.push(...lintRules(rules, entities, cfg.db?.publicRead ?? []));\n warnings.push(...trackedSecretFiles(cfg.rootDir));\n warnings.push(...wranglerWarnings(cfg.rootDir));\n\n if (warnings.length) {\n out.log(\"\");\n out.log(\"warnings:\");\n for (const warning of warnings) out.log(` - ${warning}`);\n } else {\n out.log(\"ok\");\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { ensureGitignore } from \"./local\";\n\nexport interface InitOptions {\n rootDir?: string;\n configPath?: string;\n appId: string;\n name: string;\n envs?: string[];\n services?: string[];\n aiProvider?: string;\n force?: boolean;\n stdout?: Pick<typeof console, \"log\" | \"error\">;\n}\n\nexport function initProject(options: InitOptions): void {\n const out = options.stdout ?? console;\n const rootDir = resolve(options.rootDir ?? process.cwd());\n const configPath = resolve(rootDir, options.configPath ?? \"odla.config.mjs\");\n if (existsSync(configPath) && !options.force) {\n throw new Error(`${configPath} already exists. Pass --force to overwrite.`);\n }\n if (!/^[a-z0-9][a-z0-9-]*$/.test(options.appId)) {\n throw new Error(\"--app-id must be lowercase letters, numbers, and hyphens\");\n }\n const envs = options.envs?.length ? options.envs : [\"prod\", \"dev\"];\n const services = options.services?.length ? options.services : [\"db\", \"ai\"];\n const aiProvider = options.aiProvider ?? \"anthropic\";\n\n mkdirSync(dirname(configPath), { recursive: true });\n mkdirSync(resolve(rootDir, \"src/odla\"), { recursive: true });\n mkdirSync(resolve(rootDir, \".odla\"), { recursive: true });\n\n writeFileSync(configPath, configTemplate({ appId: options.appId, name: options.name, envs, services, aiProvider }));\n writeIfMissing(resolve(rootDir, \"src/odla/schema.mjs\"), schemaTemplate());\n writeIfMissing(resolve(rootDir, \"src/odla/rules.mjs\"), rulesTemplate());\n ensureGitignore(rootDir);\n\n out.log(`created ${relativeDisplay(configPath, rootDir)}`);\n out.log(\"created src/odla/schema.mjs and src/odla/rules.mjs\");\n out.log(\"updated .gitignore for local odla credentials\");\n}\n\nfunction writeIfMissing(path: string, text: string): void {\n if (existsSync(path)) return;\n writeFileSync(path, text);\n}\n\nfunction configTemplate(input: { appId: string; name: string; envs: string[]; services: string[]; aiProvider: string }): string {\n return `export default {\n platformUrl: process.env.ODLA_PLATFORM_URL ?? \"https://odla.ai\",\n dbEndpoint: process.env.ODLA_ENDPOINT ?? process.env.ODLA_DB_ENDPOINT ?? \"https://db.odla.ai\",\n app: {\n id: \"${input.appId}\",\n name: \"${input.name.replace(/\"/g, '\\\\\"')}\",\n },\n envs: ${JSON.stringify(input.envs)},\n services: ${JSON.stringify(input.services)},\n db: {\n schema: \"./src/odla/schema.mjs\",\n rules: \"./src/odla/rules.mjs\",\n // When rules is omitted, the CLI generates deny-all rules from schema.\n defaultRules: \"deny\",\n },\n ai: {\n provider: process.env.ODLA_AI_PROVIDER ?? \"${input.aiProvider}\",\n // Optional: set this env var while running provision to store the provider\n // key in the platform vault for each tenant.\n keyEnv: \"${defaultKeyEnv(input.aiProvider)}\",\n },\n auth: {\n clerk: {\n // dev: \"$CLERK_PUBLISHABLE_KEY\",\n // prod: \"$CLERK_PUBLISHABLE_KEY\",\n },\n },\n // Add \"o11y\" to services to enable observability; provision then mints the\n // ingest token and scaffolds the ODLA_O11Y_* vars into .dev.vars.\n // o11y: {\n // service: \"${input.appId}\", // defaults to the app id\n // // endpoint: \"https://o11y.odla.ai\",\n // },\n links: {\n // dev: \"https://dev.example.com\",\n // prod: \"https://example.com\",\n },\n local: {\n tokenFile: \".odla/dev-token.json\",\n credentialsFile: \".odla/credentials.local.json\",\n devVarsFile: \".dev.vars\",\n },\n};\n`;\n}\n\nfunction schemaTemplate(): string {\n return `// Replace this starter schema with your app's odla-db schema.\n// Knowledge-graph projects can export @odla-ai/kg's toSerializedSchema(ontology).\nexport const schema = {\n entities: {\n notes: {\n attrs: {\n id: { type: \"string\", unique: true, indexed: true, optional: false },\n text: { type: \"string\", unique: false, indexed: false, optional: false },\n createdAt: { type: \"number\", unique: false, indexed: true, optional: false },\n },\n },\n },\n links: {},\n};\n`;\n}\n\nfunction rulesTemplate(): string {\n return `// odla-db is default-deny. The starter keeps runtime data backend-only.\nexport const rules = {\n notes: {\n view: \"false\",\n create: \"false\",\n update: \"false\",\n delete: \"false\",\n },\n};\n`;\n}\n\nfunction defaultKeyEnv(provider: string): string {\n if (provider === \"openai\") return \"OPENAI_API_KEY\";\n if (provider === \"google\") return \"GOOGLE_API_KEY\";\n return \"ANTHROPIC_API_KEY\";\n}\n\nfunction relativeDisplay(path: string, rootDir: string): string {\n return path.startsWith(rootDir) ? path.slice(rootDir.length + 1) : path;\n}\n","import { createAppsClient, tenantIdFor } from \"@odla-ai/apps\";\nimport { DEFAULT_SECRET_NAMES, putSecret } from \"@odla-ai/ai\";\nimport { dirname, resolve } from \"node:path\";\nimport process from \"node:process\";\nimport type { AppRules, LoadedProjectConfig, ProvisionOptions } from \"./types\";\nimport { buildPlan, envValue, loadProjectConfig, resolveDataExport, rulesFromSchema } from \"./config\";\nimport { getDeveloperToken } from \"./token\";\nimport { displayPath, ensureGitignore, mergeCredential, type O11yDevVars, readCredentials, writeDevVars, writePrivateJson } from \"./local\";\nimport { redactSecrets } from \"./redact\";\n\ntype FetchLike = typeof fetch;\n\nexport async function provision(options: ProvisionOptions): Promise<void> {\n const out = options.stdout ?? console;\n const cfg = await loadProjectConfig(options.configPath);\n const plan = buildPlan(cfg);\n\n out.log(`odla-ai: ${plan.appName} (${plan.appId})`);\n out.log(` platform: ${plan.platformUrl}`);\n out.log(` db: ${plan.dbEndpoint}`);\n out.log(` envs: ${plan.envs.join(\", \")}`);\n out.log(` services: ${plan.services.join(\", \")}`);\n\n const schema = await resolveDataExport<unknown>(cfg, cfg.db?.schema, [\"schema\", \"SCHEMA\"]);\n const configuredRules = await resolveDataExport<AppRules>(cfg, cfg.db?.rules, [\"rules\", \"RULES\"]);\n const rules = configuredRules ?? (schema && cfg.db?.defaultRules !== false ? rulesFromSchema(schema) : undefined);\n\n if (options.dryRun) {\n out.log(\"dry run: no network calls or file writes\");\n out.log(` schema: ${schema ? \"yes\" : \"no\"}`);\n out.log(` rules: ${rules ? Object.keys(rules).length : 0} namespaces`);\n out.log(` ai: ${cfg.ai?.provider ?? \"not configured\"}`);\n return;\n }\n\n const doFetch = options.fetch ?? fetch;\n const token = await getDeveloperToken(cfg, options, doFetch, out);\n const auth = { authorization: `Bearer ${token}`, \"content-type\": \"application/json\" };\n const apps = createAppsClient({ endpoint: cfg.platformUrl, token, fetcher: { fetch: doFetch } });\n\n const existing = await readRegistryApp(cfg, token, doFetch);\n if (existing) {\n out.log(`app: ${cfg.app.id} already exists`);\n } else {\n await apps.createApp({ name: cfg.app.name, appId: cfg.app.id });\n out.log(`app: created ${cfg.app.id}`);\n }\n\n for (const env of cfg.envs) {\n for (const service of cfg.services) {\n if (service === \"ai\") {\n if (cfg.ai?.provider) {\n await apps.setAi(cfg.app.id, env, { provider: cfg.ai.provider, ...(cfg.ai.model ? { model: cfg.ai.model } : {}) });\n out.log(`${env}: ai configured (${cfg.ai.provider}${cfg.ai.model ? `/${cfg.ai.model}` : \"\"})`);\n } else {\n await apps.setService(cfg.app.id, \"ai\", true, { env });\n out.log(`${env}: ai enabled`);\n }\n } else {\n await apps.setService(cfg.app.id, service, true, { env });\n out.log(`${env}: ${service} enabled`);\n }\n }\n\n const authConfig = normalizeClerkConfig(cfg.auth?.clerk?.[env]);\n if (authConfig?.publishableKey) {\n await apps.setAuth(cfg.app.id, env, authConfig);\n out.log(`${env}: auth configured (clerk ${authConfig.mode ?? \"client\"})`);\n }\n\n const link = cfg.links?.[env];\n if (link !== undefined) {\n await apps.setLink(cfg.app.id, env, link ?? null);\n out.log(`${env}: link ${link ? \"set\" : \"cleared\"}`);\n }\n }\n\n let credentials = readCredentials(cfg.local.credentialsFile);\n for (const env of cfg.envs) {\n const tenantId = tenantIdFor(cfg.app.id, env);\n let dbKey = !options.rotateKeys ? credentials?.envs[env]?.dbKey : undefined;\n if (dbKey) {\n out.log(`${env}: reusing local db key for ${tenantId}`);\n } else {\n dbKey = await mintDbKey({ cfg, tenantId, env, token, auth, fetch: doFetch });\n out.log(`${env}: minted db key for ${tenantId}`);\n }\n\n // o11y is useless with the service enabled but no ingest token, so mint one\n // here (reuse the local copy unless rotating) — same lifecycle as the db key.\n let o11yToken = cfg.services.includes(\"o11y\") && !options.rotateKeys ? credentials?.envs[env]?.o11yToken : undefined;\n if (cfg.services.includes(\"o11y\")) {\n if (o11yToken) {\n out.log(`${env}: reusing local o11y ingest token`);\n } else {\n o11yToken = await mintO11yToken(cfg, env, token, doFetch);\n out.log(`${env}: minted o11y ingest token`);\n }\n }\n\n if (schema) {\n await postJson(doFetch, `${cfg.dbEndpoint}/app/${encodeURIComponent(tenantId)}/schema`, dbKey, { schema });\n out.log(`${env}: schema pushed`);\n }\n if (rules) {\n await postJson(doFetch, `${cfg.dbEndpoint}/app/${encodeURIComponent(tenantId)}/admin/rules`, token, rules);\n out.log(`${env}: rules pushed (${Object.keys(rules).length} namespaces)`);\n }\n\n if (cfg.ai?.provider && cfg.ai.keyEnv) {\n const key = process.env[cfg.ai.keyEnv];\n if (key) {\n const secretName = cfg.ai.secretName ?? defaultSecretName(cfg.ai.provider);\n await putSecret({ endpoint: cfg.dbEndpoint, token, fetch: doFetch }, tenantId, secretName, key);\n out.log(`${env}: ${cfg.ai.provider} key stored in vault (${secretName})`);\n } else {\n out.log(`${env}: ${cfg.ai.keyEnv} not set; skipped provider key storage`);\n }\n }\n\n credentials = mergeCredential(credentials, {\n appId: cfg.app.id,\n platformUrl: cfg.platformUrl,\n dbEndpoint: cfg.dbEndpoint,\n env,\n tenantId,\n dbKey,\n ...(o11yToken ? { o11yToken } : {}),\n });\n }\n\n if (cfg.local.gitignore) ensureGitignore(cfg.rootDir);\n if (options.writeCredentials !== false && credentials) {\n writePrivateJson(cfg.local.credentialsFile, credentials);\n out.log(`credentials: wrote ${displayPath(cfg.local.credentialsFile, cfg.rootDir)} (0600, gitignored)`);\n }\n\n const devVarsTarget = resolveWriteDevVarsTarget(cfg, options.writeDevVars);\n if (devVarsTarget && credentials) {\n const env = cfg.envs.includes(\"dev\") ? \"dev\" : (cfg.envs[0] ?? \"prod\");\n writeDevVars(devVarsTarget, credentials, env, o11yDevVars(cfg));\n out.log(`dev vars: wrote ${displayPath(devVarsTarget, cfg.rootDir)} for ${env}`);\n }\n}\n\n/** Non-secret o11y vars to scaffold into .dev.vars when the service is enabled\n * (the ODLA_O11Y_TOKEN ingest secret is minted from the dashboard separately). */\nfunction o11yDevVars(cfg: LoadedProjectConfig): O11yDevVars | undefined {\n if (!cfg.services.includes(\"o11y\")) return undefined;\n return {\n endpoint: cfg.o11y?.endpoint ?? \"https://o11y.odla.ai\",\n service: cfg.o11y?.service ?? cfg.app.id,\n ...(cfg.o11y?.version ? { version: cfg.o11y.version } : {}),\n };\n}\n\nasync function readRegistryApp(cfg: LoadedProjectConfig, token: string, doFetch: FetchLike): Promise<unknown | null> {\n const res = await doFetch(`${cfg.platformUrl}/registry/apps/${encodeURIComponent(cfg.app.id)}`, {\n headers: { authorization: `Bearer ${token}` },\n });\n if (res.status === 404) return null;\n if (!res.ok) return null;\n const json = (await res.json()) as { app?: unknown };\n return json.app ?? null;\n}\n\nasync function mintDbKey(opts: {\n cfg: LoadedProjectConfig;\n tenantId: string;\n env: string;\n token: string;\n auth: Record<string, string>;\n fetch: FetchLike;\n}): Promise<string> {\n let res = await opts.fetch(`${opts.cfg.dbEndpoint}/admin/apps/${encodeURIComponent(opts.tenantId)}/keys`, {\n method: \"POST\",\n headers: opts.auth,\n body: \"{}\",\n });\n if (res.status === 404) {\n const created = await opts.fetch(`${opts.cfg.dbEndpoint}/admin/apps`, {\n method: \"POST\",\n headers: opts.auth,\n body: JSON.stringify({\n name: opts.env === \"prod\" ? opts.cfg.app.name : `${opts.cfg.app.name} (${opts.env})`,\n appId: opts.tenantId,\n }),\n });\n if (!created.ok) throw new Error(`db app create (${opts.tenantId}) failed: ${created.status} ${await safeText(created)}`);\n res = await opts.fetch(`${opts.cfg.dbEndpoint}/admin/apps/${encodeURIComponent(opts.tenantId)}/keys`, {\n method: \"POST\",\n headers: opts.auth,\n body: \"{}\",\n });\n }\n if (!res.ok) throw new Error(`db key mint (${opts.tenantId}) failed: ${res.status} ${await safeText(res)}`);\n const body = (await res.json()) as { key?: string };\n if (!body.key) throw new Error(`db key mint (${opts.tenantId}) returned no key`);\n return body.key;\n}\n\n/** Mint (rotate) the app/env's o11y ingest token via the registry proxy. The\n * developer token authorizes it — provision owns the app it created. */\nasync function mintO11yToken(cfg: LoadedProjectConfig, env: string, token: string, doFetch: FetchLike): Promise<string> {\n const res = await doFetch(\n `${cfg.platformUrl}/o11y/${encodeURIComponent(cfg.app.id)}/token?env=${encodeURIComponent(env)}`,\n { method: \"POST\", headers: { authorization: `Bearer ${token}` } },\n );\n if (!res.ok) throw new Error(`o11y token mint (${env}) failed: ${res.status} ${await safeText(res)}`);\n const body = (await res.json()) as { token?: string };\n if (!body.token) throw new Error(`o11y token mint (${env}) returned no token`);\n return body.token;\n}\n\nasync function postJson(doFetch: FetchLike, url: string, bearer: string, body: unknown): Promise<void> {\n const res = await doFetch(url, {\n method: \"POST\",\n headers: { authorization: `Bearer ${bearer}`, \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n if (!res.ok) throw new Error(`${new URL(url).pathname} failed: ${res.status} ${await safeText(res)}`);\n}\n\nfunction normalizeClerkConfig(value: unknown): { publishableKey: string; audience?: string; mode?: \"client\" | \"full\" } | null {\n if (!value) return null;\n if (typeof value === \"string\") {\n const publishableKey = envValue(value);\n return publishableKey ? { publishableKey } : null;\n }\n if (typeof value !== \"object\") return null;\n const cfg = value as { publishableKey?: string; audience?: string; mode?: \"client\" | \"full\" };\n const publishableKey = envValue(cfg.publishableKey);\n return publishableKey ? { publishableKey, ...(cfg.audience ? { audience: cfg.audience } : {}), ...(cfg.mode ? { mode: cfg.mode } : {}) } : null;\n}\n\nfunction defaultSecretName(provider: string): string {\n const names = DEFAULT_SECRET_NAMES as Record<string, string>;\n return names[provider] ?? `${provider}_api_key`;\n}\n\nfunction resolveWriteDevVarsTarget(cfg: LoadedProjectConfig, requested: string | boolean | undefined): string | null {\n if (!requested) return null;\n if (requested === true) return cfg.local.devVarsFile;\n return resolve(dirname(cfg.configPath), requested);\n}\n\nasync function safeText(res: Response): Promise<string> {\n try {\n return redactSecrets((await res.text()).slice(0, 500));\n } catch {\n return \"\";\n }\n}\n","import { requestToken } from \"@odla-ai/db\";\nimport process from \"node:process\";\nimport type { LoadedProjectConfig, ProvisionOptions } from \"./types\";\nimport { openUrl } from \"./open\";\nimport { displayPath, readJsonFile, writePrivateJson } from \"./local\";\n\ntype FetchLike = typeof fetch;\n\nexport async function getDeveloperToken(\n cfg: LoadedProjectConfig,\n options: ProvisionOptions,\n doFetch: FetchLike,\n out: Pick<typeof console, \"log\" | \"error\">,\n): Promise<string> {\n if (options.token) return options.token;\n if (process.env.ODLA_DEV_TOKEN) return process.env.ODLA_DEV_TOKEN;\n\n const cached = readJsonFile<{ token?: string; expiresAt?: number }>(cfg.local.tokenFile);\n if (cached?.token && (cached.expiresAt ?? 0) > Date.now() + 60_000) {\n out.log(`auth: using cached developer token (${displayPath(cfg.local.tokenFile, cfg.rootDir)})`);\n return cached.token;\n }\n\n const browser = approvalBrowser(options);\n const { token, expiresAt } = await requestToken({\n endpoint: cfg.platformUrl,\n label: `${cfg.app.id} provisioner`,\n fetch: doFetch,\n onCode: async ({ userCode, expiresIn }) => {\n const approvalUrl = handshakeUrl(cfg.platformUrl, userCode);\n out.log(\"\");\n out.log(`Approve code ${userCode} at ${approvalUrl} within ${Math.floor(expiresIn / 60)}m.`);\n if (browser.open) {\n try {\n await (options.openApprovalUrl ?? openUrl)(approvalUrl);\n out.log(`auth: opened browser for approval${browser.mode === \"auto\" ? \" (auto)\" : \"\"}`);\n } catch (err) {\n out.log(`auth: could not open browser (${err instanceof Error ? err.message : String(err)})`);\n }\n } else if (browser.reason) {\n out.log(`auth: browser launch skipped (${browser.reason})`);\n }\n out.log(\"\");\n },\n });\n writePrivateJson(cfg.local.tokenFile, { token, expiresAt });\n out.log(`auth: developer token cached (${displayPath(cfg.local.tokenFile, cfg.rootDir)})`);\n return token;\n}\n\nexport function approvalBrowser(options: ProvisionOptions): { open: boolean; mode?: \"auto\" | \"forced\"; reason?: string } {\n if (options.open === true) return { open: true, mode: \"forced\" };\n if (options.open === false) return { open: false, reason: \"disabled by --no-open\" };\n if (process.env.CI) return { open: false, reason: \"CI environment\" };\n\n const interactive = options.interactive ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);\n if (!interactive) return { open: false, reason: \"non-interactive shell; pass --open to force\" };\n return { open: true, mode: \"auto\" };\n}\n\nexport function handshakeUrl(platformUrl: string, userCode: string): string {\n const url = new URL(\"/handshakes\", platformUrl);\n url.searchParams.set(\"code\", userCode);\n return url.toString();\n}\n","import { spawn } from \"node:child_process\";\nimport process from \"node:process\";\n\nexport interface OpenUrlOptions {\n platform?: NodeJS.Platform;\n spawnImpl?: typeof spawn;\n}\n\nexport async function openUrl(url: string, options: OpenUrlOptions = {}): Promise<void> {\n const command = openerFor(options.platform ?? process.platform);\n const doSpawn = options.spawnImpl ?? spawn;\n await new Promise<void>((resolve, reject) => {\n const child = doSpawn(command.cmd, [...command.args, url], {\n stdio: \"ignore\",\n detached: true,\n });\n child.once(\"error\", reject);\n child.once(\"spawn\", () => {\n child.unref();\n resolve();\n });\n });\n}\n\nexport function openerFor(platform: NodeJS.Platform): { cmd: string; args: string[] } {\n if (platform === \"darwin\") return { cmd: \"open\", args: [] };\n if (platform === \"win32\") return { cmd: \"cmd\", args: [\"/c\", \"start\", \"\"] };\n return { cmd: \"xdg-open\", args: [] };\n}\n","import { loadProjectConfig } from \"./config\";\nimport { displayPath, readCredentials } from \"./local\";\nimport { redactSecrets } from \"./redact\";\nimport { defaultRunner, findWranglerConfig, wranglerLoggedIn, wranglerPutSecret } from \"./wrangler\";\nimport type { CommandRunner } from \"./wrangler\";\n\nexport interface SecretsPushOptions {\n configPath: string;\n env: string;\n dryRun?: boolean;\n /** Required to push to a prod-named env; the visible consent token in agent transcripts. */\n yes?: boolean;\n runner?: CommandRunner;\n stdout?: Pick<typeof console, \"log\" | \"error\">;\n}\n\nconst PROD_ENV_NAMES = new Set([\"prod\", \"production\"]);\n\n/**\n * Moves the env's odla-db key from `.odla/credentials.local.json` into the\n * Worker via `wrangler secret put ODLA_API_KEY`, piping the value over stdin\n * so it never appears on argv, in output, or in the conversation transcript.\n */\nexport async function secretsPush(options: SecretsPushOptions): Promise<void> {\n const out = options.stdout ?? console;\n const cfg = await loadProjectConfig(options.configPath);\n const env = options.env;\n\n if (!cfg.envs.includes(env)) {\n throw new Error(`env \"${env}\" is not in config envs (${cfg.envs.join(\", \")})`);\n }\n if (PROD_ENV_NAMES.has(env) && !options.yes) {\n throw new Error(`refusing to push a secret to \"${env}\" without --yes`);\n }\n\n const credentialsPath = displayPath(cfg.local.credentialsFile, cfg.rootDir);\n const credentials = readCredentials(cfg.local.credentialsFile);\n if (!credentials) throw new Error(`no credentials at ${credentialsPath} — run \"odla-ai provision\" first`);\n if (credentials.appId !== cfg.app.id) {\n throw new Error(`credentials at ${credentialsPath} are for \"${credentials.appId}\", not \"${cfg.app.id}\"`);\n }\n const dbKey = credentials.envs[env]?.dbKey;\n if (!dbKey) throw new Error(`no db key for env \"${env}\" in ${credentialsPath} — run \"odla-ai provision\" first`);\n\n const wranglerConfig = findWranglerConfig(cfg.rootDir);\n if (!wranglerConfig) {\n throw new Error(`no wrangler config found in ${cfg.rootDir} (wrangler.jsonc, wrangler.json, or wrangler.toml)`);\n }\n\n // Convention from the reference apps: the top-level wrangler config is prod;\n // every other env is a named `env.<name>` block.\n const wranglerEnv = PROD_ENV_NAMES.has(env) ? undefined : env;\n const target = wranglerEnv ? `wrangler env \"${wranglerEnv}\"` : \"the top-level (prod) wrangler env\";\n\n // Push the db key plus the o11y ingest token when the app minted one — both\n // are Worker secrets that live only in the 0600 credentials file until now.\n const secrets: Array<{ name: string; value: string }> = [{ name: \"ODLA_API_KEY\", value: dbKey }];\n const o11yToken = credentials.envs[env]?.o11yToken;\n if (o11yToken) secrets.push({ name: \"ODLA_O11Y_TOKEN\", value: o11yToken });\n\n if (options.dryRun) {\n for (const s of secrets) out.log(`dry run: would push ${s.name} (${redactSecrets(s.value)}) to ${target}`);\n return;\n }\n\n const run = options.runner ?? defaultRunner;\n if (!(await wranglerLoggedIn(run, cfg.rootDir))) {\n throw new Error(`wrangler is not logged in — run \"wrangler login\" (a browser step for the human)`);\n }\n\n for (const s of secrets) {\n const result = await wranglerPutSecret(run, { name: s.name, value: s.value, env: wranglerEnv, cwd: cfg.rootDir });\n if (result.code !== 0) {\n throw new Error(`wrangler secret put ${s.name} failed (exit ${result.code}): ${redactSecrets(`${result.stderr || result.stdout}`.trim())}`);\n }\n out.log(`${s.name} pushed to ${target} (value read from ${credentialsPath}, never echoed)`);\n }\n}\n","import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, relative, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport interface SkillInstallOptions {\n /** Project directory receiving `.claude/skills/`. Defaults to cwd. Ignored with `global`. */\n dir?: string;\n /** Install into `~/.claude/skills/` instead of the project. */\n global?: boolean;\n /** Overwrite locally modified skill files. */\n force?: boolean;\n /** Test/embedding override for the home directory. */\n homeDir?: string;\n /** Test/embedding override for the bundled skills directory. */\n sourceDir?: string;\n stdout?: Pick<typeof console, \"log\" | \"error\">;\n}\n\nexport interface SkillInstallResult {\n targetDir: string;\n written: string[];\n unchanged: string[];\n}\n\n/**\n * Copies the skills bundled with this package into `.claude/skills/` so the\n * user's agent picks them up. Idempotent: unchanged files are skipped, and a\n * locally modified file is never overwritten without `force`.\n */\nexport function installSkill(options: SkillInstallOptions = {}): SkillInstallResult {\n const out = options.stdout ?? console;\n const sourceDir = options.sourceDir ?? fileURLToPath(new URL(\"../skills\", import.meta.url));\n const targetDir = options.global\n ? join(options.homeDir ?? homedir(), \".claude\", \"skills\")\n : resolve(options.dir ?? process.cwd(), \".claude\", \"skills\");\n\n const files = listFiles(sourceDir);\n if (files.length === 0) throw new Error(`no bundled skills found at ${sourceDir}`);\n\n const written: string[] = [];\n const unchanged: string[] = [];\n const conflicts: string[] = [];\n for (const rel of files) {\n const target = join(targetDir, rel);\n const source = readFileSync(join(sourceDir, rel), \"utf8\");\n if (existsSync(target)) {\n const current = readFileSync(target, \"utf8\");\n if (current === source) {\n unchanged.push(rel);\n continue;\n }\n if (!options.force) {\n conflicts.push(rel);\n continue;\n }\n }\n written.push(rel);\n }\n\n if (conflicts.length > 0) {\n throw new Error(\n `skill files modified locally (re-run with --force to overwrite):\\n${conflicts.map((f) => ` - ${join(targetDir, f)}`).join(\"\\n\")}`,\n );\n }\n\n for (const rel of written) {\n const target = join(targetDir, rel);\n mkdirSync(join(target, \"..\"), { recursive: true });\n writeFileSync(target, readFileSync(join(sourceDir, rel), \"utf8\"));\n }\n\n const skills = [...new Set(files.map((f) => f.split(/[\\\\/]/)[0]))].sort();\n out.log(`skills: ${skills.join(\", \")}`);\n out.log(`installed ${written.length} file(s) to ${targetDir}${unchanged.length ? ` (${unchanged.length} unchanged)` : \"\"}`);\n return { targetDir, written, unchanged };\n}\n\nfunction listFiles(dir: string): string[] {\n if (!existsSync(dir)) return [];\n const results: string[] = [];\n const walk = (current: string): void => {\n for (const entry of readdirSync(current, { withFileTypes: true })) {\n const path = join(current, entry.name);\n if (entry.isDirectory()) walk(path);\n else results.push(relative(dir, path));\n }\n };\n walk(dir);\n return results.sort();\n}\n","import { loadProjectConfig, resolveDataExport, serializedEntities } from \"./config\";\nimport { displayPath, readCredentials } from \"./local\";\nimport type { SmokeOptions } from \"./types\";\n\ntype FetchLike = typeof fetch;\n\nexport async function smoke(options: SmokeOptions): Promise<void> {\n const out = options.stdout ?? console;\n const cfg = await loadProjectConfig(options.configPath);\n const env = options.env ?? (cfg.envs.includes(\"dev\") ? \"dev\" : (cfg.envs[0] ?? \"prod\"));\n if (!cfg.envs.includes(env)) throw new Error(`env \"${env}\" is not declared in ${displayPath(cfg.configPath, cfg.rootDir)}`);\n\n const credentials = readCredentials(cfg.local.credentialsFile);\n if (!credentials) {\n throw new Error(`local credentials missing: ${displayPath(cfg.local.credentialsFile, cfg.rootDir)}. Run \"odla-ai provision --write-dev-vars\".`);\n }\n if (credentials.appId !== cfg.app.id) {\n throw new Error(`local credentials are for app \"${credentials.appId}\", but config app is \"${cfg.app.id}\"`);\n }\n\n const entry = credentials.envs[env];\n if (!entry?.tenantId || !entry.dbKey) {\n throw new Error(`local credentials have no db key for env \"${env}\". Run \"odla-ai provision --write-dev-vars\".`);\n }\n\n const doFetch = options.fetch ?? fetch;\n out.log(`smoke: ${cfg.app.id}/${env}`);\n out.log(` tenant: ${entry.tenantId}`);\n\n const publicConfig = await getJson(doFetch, publicConfigUrl(cfg.platformUrl, cfg.app.id, env), undefined);\n out.log(` public-config: ok`);\n\n if (cfg.ai?.provider) {\n const provider = ((publicConfig as { ai?: { provider?: unknown } | null }).ai?.provider ?? null) as string | null;\n if (provider !== cfg.ai.provider) {\n throw new Error(`ai provider mismatch: expected \"${cfg.ai.provider}\", public-config has \"${provider ?? \"none\"}\"`);\n }\n out.log(` ai: ${provider}`);\n }\n\n const expectedSchema = await resolveDataExport<unknown>(cfg, cfg.db?.schema, [\"schema\", \"SCHEMA\"]);\n const expectedEntities = serializedEntities(expectedSchema);\n const liveSchemaPayload = await getJson(doFetch, `${cfg.dbEndpoint}/app/${encodeURIComponent(entry.tenantId)}/schema`, entry.dbKey);\n const liveSchema = (liveSchemaPayload as { schema?: unknown }).schema ?? liveSchemaPayload;\n const liveEntities = serializedEntities(liveSchema);\n if (expectedEntities.length) {\n const missing = expectedEntities.filter((entity) => !liveEntities.includes(entity));\n if (missing.length) throw new Error(`live schema is missing expected entities: ${missing.join(\", \")}`);\n }\n out.log(` schema: ${liveEntities.length} entities`);\n\n const aggregateEntity = expectedEntities[0] ?? liveEntities[0];\n if (aggregateEntity) {\n const aggregate = await postJson(doFetch, `${cfg.dbEndpoint}/app/${encodeURIComponent(entry.tenantId)}/aggregate`, entry.dbKey, {\n ns: aggregateEntity,\n aggregate: { count: true },\n });\n const count = (aggregate as { aggregate?: { count?: unknown } }).aggregate?.count;\n out.log(` aggregate: ${aggregateEntity}.count=${String(count ?? \"ok\")}`);\n } else {\n out.log(` aggregate: skipped (schema has no entities)`);\n }\n out.log(\"ok\");\n}\n\nasync function getJson(doFetch: FetchLike, url: string, bearer: string | undefined): Promise<unknown> {\n const res = await doFetch(url, {\n headers: bearer ? { authorization: `Bearer ${bearer}` } : undefined,\n });\n if (!res.ok) throw new Error(`${new URL(url).pathname} returned ${res.status}: ${await safeText(res)}`);\n return res.json();\n}\n\nasync function postJson(doFetch: FetchLike, url: string, bearer: string, body: unknown): Promise<unknown> {\n const res = await doFetch(url, {\n method: \"POST\",\n headers: { authorization: `Bearer ${bearer}`, \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n if (!res.ok) throw new Error(`${new URL(url).pathname} returned ${res.status}: ${await safeText(res)}`);\n return res.json();\n}\n\nfunction publicConfigUrl(platformUrl: string, appId: string, env: string): string {\n const url = new URL(`/registry/apps/${encodeURIComponent(appId)}/public-config`, platformUrl);\n url.searchParams.set(\"env\", env);\n return url.toString();\n}\n\nasync function safeText(res: Response): Promise<string> {\n try {\n return (await res.text()).slice(0, 500);\n } catch {\n return \"\";\n }\n}\n","import { readFileSync } from \"node:fs\";\nimport { doctor } from \"./doctor\";\nimport { initProject } from \"./init\";\nimport { provision } from \"./provision\";\nimport { secretsPush } from \"./secrets\";\nimport { installSkill } from \"./skill\";\nimport { smoke } from \"./smoke\";\nimport type { ProvisionOptions } from \"./types\";\n\nexport async function runCli(argv = process.argv.slice(2)): Promise<void> {\n const parsed = parseArgv(argv);\n const command = parsed.positionals[0] ?? \"help\";\n if (command === \"version\" || command === \"-v\" || parsed.options.version === true) {\n console.log(cliVersion());\n return;\n }\n\n if (command === \"help\" || command === \"--help\" || command === \"-h\") {\n printHelp();\n return;\n }\n\n if (command === \"init\") {\n initProject({\n appId: requiredString(parsed.options[\"app-id\"], \"--app-id\"),\n name: requiredString(parsed.options.name, \"--name\"),\n configPath: stringOpt(parsed.options.config),\n envs: listOpt(parsed.options.env),\n services: listOpt(parsed.options.services),\n aiProvider: stringOpt(parsed.options[\"ai-provider\"]),\n force: parsed.options.force === true,\n });\n return;\n }\n\n if (command === \"doctor\") {\n await doctor({ configPath: stringOpt(parsed.options.config) ?? \"odla.config.mjs\" });\n return;\n }\n\n if (command === \"provision\") {\n const writeDevVars = parsed.options[\"write-dev-vars\"];\n const opts: ProvisionOptions = {\n configPath: stringOpt(parsed.options.config) ?? \"odla.config.mjs\",\n dryRun: parsed.options[\"dry-run\"] === true,\n rotateKeys: parsed.options[\"rotate-keys\"] === true,\n writeCredentials: parsed.options[\"write-credentials\"] !== false,\n writeDevVars: typeof writeDevVars === \"string\" ? writeDevVars : writeDevVars === true,\n token: stringOpt(parsed.options.token),\n open: parsed.options.open === false ? false : parsed.options.open === true ? true : undefined,\n yes: parsed.options.yes === true,\n };\n await provision(opts);\n return;\n }\n\n if (command === \"smoke\") {\n await smoke({\n configPath: stringOpt(parsed.options.config) ?? \"odla.config.mjs\",\n env: stringOpt(parsed.options.env),\n });\n return;\n }\n\n if (command === \"setup\") {\n // The agent front door: install the bundled skills so a coding agent picks\n // up the `odla` skill and drives init/provision/build from here.\n installSkill({\n dir: stringOpt(parsed.options.dir),\n global: parsed.options.global === true,\n force: parsed.options.force === true,\n });\n console.log(\n \"\\nSkills installed. Point your coding agent at this repo — the `odla` skill orients it\\n\" +\n \"(build a new app, or migrate an existing site) and drives `odla-ai init` / `provision`.\",\n );\n return;\n }\n\n if (command === \"skill\") {\n const sub = parsed.positionals[1];\n if (sub !== \"install\") throw new Error(`unknown skill subcommand \"${sub ?? \"\"}\". Try \"odla-ai skill install\".`);\n installSkill({\n dir: stringOpt(parsed.options.dir),\n global: parsed.options.global === true,\n force: parsed.options.force === true,\n });\n return;\n }\n\n if (command === \"secrets\") {\n const sub = parsed.positionals[1];\n if (sub !== \"push\") throw new Error(`unknown secrets subcommand \"${sub ?? \"\"}\". Try \"odla-ai secrets push --env dev\".`);\n await secretsPush({\n configPath: stringOpt(parsed.options.config) ?? \"odla.config.mjs\",\n env: requiredString(parsed.options.env, \"--env\"),\n dryRun: parsed.options[\"dry-run\"] === true,\n yes: parsed.options.yes === true,\n });\n return;\n }\n\n throw new Error(`unknown command \"${command}\". Run \"odla-ai help\".`);\n}\n\ninterface ParsedArgv {\n positionals: string[];\n options: Record<string, string | boolean | string[]>;\n}\n\nfunction parseArgv(argv: string[]): ParsedArgv {\n const positionals: string[] = [];\n const options: Record<string, string | boolean | string[]> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]!;\n if (!arg.startsWith(\"--\")) {\n positionals.push(arg);\n continue;\n }\n const eq = arg.indexOf(\"=\");\n const rawName = arg.slice(2, eq === -1 ? undefined : eq);\n if (!rawName) continue;\n if (rawName.startsWith(\"no-\")) {\n options[rawName.slice(3)] = false;\n continue;\n }\n if (eq !== -1) {\n addOption(options, rawName, arg.slice(eq + 1));\n continue;\n }\n const value = argv[i + 1];\n if (value !== undefined && !value.startsWith(\"--\")) {\n i++;\n addOption(options, rawName, value);\n } else {\n addOption(options, rawName, true);\n }\n }\n return { positionals, options };\n}\n\nfunction addOption(options: Record<string, string | boolean | string[]>, name: string, value: string | boolean): void {\n const cur = options[name];\n if (cur === undefined) {\n options[name] = value;\n } else if (Array.isArray(cur)) {\n cur.push(String(value));\n } else {\n options[name] = [String(cur), String(value)];\n }\n}\n\nfunction requiredString(value: string | boolean | string[] | undefined, name: string): string {\n const s = stringOpt(value);\n if (!s) throw new Error(`${name} is required`);\n return s;\n}\n\nfunction stringOpt(value: string | boolean | string[] | undefined): string | undefined {\n if (typeof value === \"string\") return value;\n if (Array.isArray(value)) return value[value.length - 1];\n return undefined;\n}\n\nfunction listOpt(value: string | boolean | string[] | undefined): string[] | undefined {\n if (value === undefined || value === false || value === true) return undefined;\n const values = Array.isArray(value) ? value : [value];\n return values.flatMap((item) => item.split(\",\")).map((item) => item.trim()).filter(Boolean);\n}\n\nexport function cliVersion(): string {\n const pkg = JSON.parse(readFileSync(new URL(\"../package.json\", import.meta.url), \"utf8\")) as { version?: string };\n return pkg.version ?? \"unknown\";\n}\n\nfunction printHelp(): void {\n console.log(`odla-ai\n\nUsage:\n odla-ai setup [--dir <project>] [--global] [--force]\n odla-ai init --app-id <id> --name <name> [--services db,ai] [--env dev --env prod]\n odla-ai doctor [--config odla.config.mjs]\n odla-ai provision [--config odla.config.mjs] [--dry-run] [--open|--no-open] [--rotate-keys] [--write-dev-vars[=path]]\n odla-ai smoke [--config odla.config.mjs] [--env dev]\n odla-ai skill install [--dir <project>] [--global] [--force]\n odla-ai secrets push --env <env> [--config odla.config.mjs] [--dry-run] [--yes]\n odla-ai version\n\nCommands:\n setup Install the odla skills so a coding agent can drive the rest.\n init Create a generic odla.config.mjs plus starter schema/rules files.\n doctor Validate and summarize the project config without network calls.\n provision Register the app, enable services, push schema/rules, configure AI/auth.\n smoke Verify local credentials, public-config, live schema, and db aggregate.\n skill Install the bundled Claude Code skills into .claude/skills/.\n secrets Push the env's db key into the Worker via wrangler, stdin-piped.\n version Print the CLI version.\n\nSafety:\n Provision caches the approved developer token and local db keys under .odla/\n with mode 0600, and init adds those paths to .gitignore.\n Provision opens the approval page automatically in interactive terminals;\n use --open to force browser launch or --no-open to suppress it.\n`);\n}\n"],"mappings":"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","names":["existsSync","readFileSync","join","resolve","existsSync","readFileSync","resolve","existsSync","join","readFileSync","existsSync","readFileSync","dirname","resolve","existsSync","mkdirSync","writeFileSync","dirname","resolve","resolve","existsSync","mkdirSync","dirname","writeFileSync","dirname","resolve","process","process","spawn","process","resolve","process","process","publishableKey","resolve","dirname","existsSync","mkdirSync","readFileSync","writeFileSync","join","relative","resolve","postJson","safeText","readFileSync","writeDevVars","readFileSync"]}
|