@odla-ai/cli 0.4.0 → 0.5.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.
@@ -15,22 +15,23 @@ own terminal so you never see the value.
15
15
  via this session):
16
16
 
17
17
  export <PROVIDER>_API_KEY=... # their key
18
- npx odla-ai provision
18
+ npx @odla-ai/cli provision
19
19
 
20
20
  provision stores the key in the tenant vault and sets provider/model
21
21
  in the registry. Their shell forgets it when closed; wrangler and git
22
- never see it. If they use `! npx odla-ai provision` in-session, the
22
+ never see it. If they use `! npx @odla-ai/cli provision` in-session, the
23
23
  export must still happen in a terminal you don't read.
24
24
  3. `npm i @odla-ai/ai`. In the worker, use `initFromPlatform` — it reads
25
25
  provider/model from public-config (cached ~60s) and resolves the key
26
26
  from the vault at call time using only the app's db key. Provider and
27
- model are switchable in Studio with no redeploy. Reference:
28
- `examples/kg-demo` in the odla-ai monorepo.
27
+ model are switchable in Studio with no redeploy. Read
28
+ `node_modules/@odla-ai/ai/llms.txt` and the public platform manual for the
29
+ complete vault + public-config contract.
29
30
  4. Add one `/api/*` route that round-trips the model; deploy dev.
30
31
 
31
32
  ## Verification checklist
32
33
 
33
- - [ ] `npx odla-ai smoke --env dev` passes
34
+ - [ ] `npx @odla-ai/cli smoke --env dev` passes
34
35
  - [ ] The AI route returns a model response on the deployed dev worker
35
36
  - [ ] `wrangler.jsonc` `vars` contain NO provider key; `git grep` for the
36
37
  key's prefix finds nothing
@@ -5,25 +5,35 @@ worker, DNS cut over — with GitHub Pages kept live as the rollback for
5
5
  at least 72 hours.
6
6
 
7
7
  Human obligations: add the domain to Cloudflare; click through the DNS
8
- changes (you supply exact values); create the prod Clerk instance if
9
- the app uses login; final go/no-go at each step below.
8
+ changes (you supply exact values); if using login, **activate production
9
+ on the existing Clerk app** (`npx clerk deploy`) the same app's prod
10
+ instance, never a second Clerk app per env; final go/no-go at each step.
10
11
 
11
12
  ## Steps
12
13
 
13
14
  1. Update `odla.config.mjs`: add `"prod"` to `envs`; add
14
- `auth.clerk.prod` (`pk_live_…` from the prod Clerk instance) if using
15
- login; add `links: { prod: "https://<domain>" }` (the CNAME domain
16
- captured in Phase 0). If using AI, the human re-runs the Phase 4
17
- export + provision so the PROD tenant's vault gets the key.
18
- 2. `npx odla-ai provision --dry-run`, show the human, then
19
- `npx odla-ai provision` provisions the prod tenant (`<appId>`),
20
- idempotent for everything already done in dev.
21
- 3. Push the prod db key: `npx odla-ai secrets push --env prod --yes`
22
- (targets the top-level wrangler env; `--yes` is the explicit prod
23
- consent see references/secrets-map.md).
24
- 4. Build, then `npx wrangler deploy` (first prod deploy). Verify
15
+ `auth.clerk.prod` (`pk_live_…` from the app's **activated production
16
+ instance** one Clerk app, two instances, see below) if using login;
17
+ add `links: { prod: "https://<domain>" }` (the CNAME domain captured in
18
+ Phase 0). If using AI, the human re-runs the Phase 4 export + provision
19
+ so the PROD tenant's vault gets the key.
20
+ 2. `npx @odla-ai/cli provision --dry-run`, show the human, then
21
+ `npx @odla-ai/cli provision --yes --push-secrets` provisions the prod
22
+ tenant (`<appId>`) and transfers its configured db/o11y secrets through
23
+ Wrangler stdin. `--yes` is the explicit production consent; use standalone
24
+ `secrets push --env prod --yes` only to retry the transfer (see
25
+ references/secrets-map.md).
26
+ 3. Build, then run the passive pre-cutover security gate:
27
+ first require `npm view @odla-ai/security@0.1.0 version` to succeed. An
28
+ exact-version `E404` means the release is unavailable and blocks cutover;
29
+ it is not a clean scan and does not prove the package name is absent. Run
30
+ `npm i -D --save-exact @odla-ai/security@0.1.0` followed by
31
+ `npx odla-security scan . --profile odla --out .odla/security/pre-cutover --fail-on high --fail-on-candidates critical`.
32
+ Review `REPORT.md`; a candidate is a lead, not confirmation, and a baseline
33
+ requires a concrete reason, owner, and expiry.
34
+ 4. `npx wrangler deploy` (first prod deploy). Verify
25
35
  `/api/health` and the parity paths on the prod workers.dev URL.
26
- 5. `npx odla-ai smoke --env prod`.
36
+ 5. `npx @odla-ai/cli smoke --env prod`.
27
37
  6. Human: add the domain to Cloudflare, then attach it to the prod
28
38
  worker (Workers & Pages → the worker → Domains & Routes). Supply
29
39
  them the exact hostname values to enter.
@@ -37,9 +47,26 @@ the app uses login; final go/no-go at each step below.
37
47
  confirmation: disable GitHub Pages in the repo settings. KEEP the
38
48
  repo — it is still the source of the site.
39
49
 
50
+ ## Clerk in prod — one app, two instances
51
+
52
+ A Clerk **application** has a Development instance (used in dev) and a
53
+ Production instance. Production (`pk_live_…`) is **domain-coupled**:
54
+ `npx clerk deploy` walks the human through the production domain + DNS —
55
+ the same domain you're cutting over here — so activating it fits naturally
56
+ at Phase 5. **Do NOT create a second Clerk app per environment** — activate
57
+ production on the *existing* app. Then:
58
+
59
+ - Re-apply the instance config to the prod instance:
60
+ `npx clerk config patch --instance prod --file clerk-config.json`, and
61
+ re-add allowlist identifiers with `--app <id>` (see phase-3-auth.md).
62
+ - If mirroring users, add the `$users` webhook for the prod instance/tenant
63
+ (`https://db.odla.ai/webhooks/clerk/<appId>` + `whsec_` in the prod
64
+ tenant vault) — see phase-3b-user-sync.md.
65
+
40
66
  ## Verification checklist
41
67
 
42
- - [ ] `npx odla-ai smoke --env prod` passes
68
+ - [ ] `npx @odla-ai/cli smoke --env prod` passes
69
+ - [ ] Passive `odla-security` pre-cutover report reviewed; critical lead gate passes
43
70
  - [ ] Public domain serves from the worker (check the `x-odla-worker`
44
71
  header) on every parity path
45
72
  - [ ] Auth and AI routes verified from the public domain
@@ -49,5 +76,5 @@ Rollback: point DNS back at GitHub Pages (minutes). Nothing on the
49
76
  odla/Cloudflare side needs to be torn down to roll back.
50
77
 
51
78
  Done when: the 72-hour confirmation is done and MIGRATION.md is closed
52
- out. Congratulate the human — and mention Studio (https://odla.ai) as
79
+ out. Congratulate the human — and mention Studio (https://odla.ai/studio) as
53
80
  where they watch their app from now on.
@@ -8,20 +8,26 @@
8
8
  | Clerk webhook secret (`whsec_…`) | tenant vault (`clerk_webhook_secret`) | only for auth mode "full"; entered in Studio, never wrangler, never chat |
9
9
  | Clerk secret key (`sk_test_`/`sk_live_`) | not used in this journey | never ask for it |
10
10
  | LLM provider key | tenant vault | env var in the HUMAN's shell for one provision run; never wrangler vars, never git, never chat |
11
- | `odla_sk_…` (tenant db key) | wrangler secret `ODLA_API_KEY` + `.odla/credentials.local.json` (0600) + `.dev.vars` | the only wrangler secret in this journey; move it only with the pipeline below |
11
+ | `odla_sk_…` (tenant db key) | wrangler secret `ODLA_API_KEY` + `.odla/credentials.local.json` (0600) + `.dev.vars` | present when db is enabled; move it only with the pipeline below |
12
12
  | `odla_dev_…` (developer token) | `.odla/dev-token.json` (0600) | ~24h lifetime, provision-time only; never deployed |
13
- | `o11y_…` (o11y ingest token) | wrangler secret `ODLA_O11Y_TOKEN` + `.odla/credentials.local.json` (0600) + `.dev.vars` | only if the app enables o11y; provision auto-mints it (dashboard can too); moved with the pipeline below alongside the db key; never a var, never chat |
14
- | `ODLA_ENDPOINT` / `ODLA_TENANT` / `ODLA_PLATFORM` / `ODLA_APP_ID` / `ODLA_ENV` / `ODLA_O11Y_ENDPOINT` / `ODLA_O11Y_SERVICE` | wrangler `vars` | not secrets; keep them set in every env block |
13
+ | `o11y_…` (o11y ingest token) | wrangler secret `ODLA_O11Y_TOKEN` + `.odla/credentials.local.json` (0600) + `.dev.vars` | only if the app enables o11y; provision issues/reuses it and moves it alongside the db key; never a var, never chat |
14
+ | `ODLA_ENDPOINT` / `ODLA_TENANT` / `ODLA_PLATFORM` / `ODLA_APP_ID` / `ODLA_ENV` | wrangler `vars` | not secrets; keep them set in every env block |
15
+ | `ODLA_O11Y_ENDPOINT` / `ODLA_O11Y_SERVICE` | `.dev.vars` from provision or optional wrangler `vars` overrides | not secrets; public ingest defaults to `https://o11y.odla.ai` and `ODLA_APP_ID` when the token is present |
15
16
 
16
17
  ## Moving the db key (+ o11y token) into the Worker (never through the transcript)
17
18
 
18
- Use the CLI — it reads the 0600 credentials file and pipes each value to
19
- wrangler over stdin, with preflights (`wrangler whoami`, config present)
20
- and redacted output. It pushes `ODLA_API_KEY` and, when the app enabled o11y,
21
- `ODLA_O11Y_TOKEN` too:
19
+ Normal provisioning owns the complete sequence issuance, mode-0600 local
20
+ storage, `.dev.vars`, and redacted Wrangler stdin transfer. It pushes
21
+ `ODLA_API_KEY` and, when the app enabled o11y, `ODLA_O11Y_TOKEN` too:
22
22
 
23
- npx odla-ai secrets push --env dev
24
- npx odla-ai secrets push --env prod --yes # Phase 5; --yes is the prod consent
23
+ npx @odla-ai/cli provision --write-dev-vars --push-secrets
24
+ npx @odla-ai/cli provision --yes --push-secrets # Phase 5; includes prod consent
25
+
26
+ Use the narrower command only to retry one environment's already-saved
27
+ credential transfer:
28
+
29
+ npx @odla-ai/cli secrets push --env dev
30
+ npx @odla-ai/cli secrets push --env prod --yes
25
31
 
26
32
  Manual fallback (identical mechanics, if the CLI is unavailable):
27
33
 
@@ -41,5 +47,9 @@ wrangler env is prod.)
41
47
  but verify.
42
48
  - If a secret value ever does land in the conversation or a committed
43
49
  file: tell the human immediately, treat it as burned, and rotate it
44
- (`provision --rotate-keys` for db keys with their explicit
45
- approval; provider dashboard for LLM/Clerk values).
50
+ (`provision --rotate-keys` for the broad credential set, or
51
+ `provision --rotate-o11y-token --push-secrets` for o11y only — with explicit
52
+ human approval; provider dashboard for LLM/Clerk values).
53
+ - Studio's o11y token control is manual recovery only. It invalidates the live
54
+ token immediately and does not update `.odla/credentials.local.json`; prefer
55
+ the CLI rotation above so the saved and deployed values move together.
@@ -22,14 +22,14 @@ Cause: tenant confusion — the code ran against `<appId>` (prod) instead
22
22
  of `<appId>--dev`, or vice versa. Typical trigger: `wrangler deploy`
23
23
  without `--env dev`, or `wrangler dev` picking up top-level vars.
24
24
  Fix: check `ODLA_TENANT`/`ODLA_ENV` in the relevant `wrangler.jsonc`
25
- env block and which deploy command ran. `npx odla-ai smoke --env dev`
25
+ env block and which deploy command ran. `npx @odla-ai/cli smoke --env dev`
26
26
  prints what it verified against.
27
27
 
28
28
  ## Provision fails with an auth/token error
29
29
 
30
30
  Cause: the `odla_dev_…` token expired (~24h) or the handshake was never
31
31
  approved.
32
- Fix: re-run `npx odla-ai provision` — it starts a fresh handshake; the
32
+ Fix: re-run `npx @odla-ai/cli provision` — it starts a fresh handshake; the
33
33
  human approves the new code at the printed URL. Use `--no-open` in
34
34
  non-interactive shells if the browser launch misbehaves.
35
35
 
@@ -37,16 +37,27 @@ non-interactive shells if the browser launch misbehaves.
37
37
 
38
38
  Cause: `.odla/credentials.local.json` absent, for a different app id,
39
39
  or lacking a db key for the requested env.
40
- Fix: run `npx odla-ai provision` for the configured envs first; confirm
40
+ Fix: run `npx @odla-ai/cli provision` for the configured envs first; confirm
41
41
  `envs` in odla.config.mjs includes the env you're smoking.
42
42
 
43
43
  ## `smoke` fails: schema mismatch
44
44
 
45
45
  Cause: local `src/odla/schema.mjs` changed since the last push.
46
- Fix: re-run `npx odla-ai provision` (schema re-push is the migration
46
+ Fix: re-run `npx @odla-ai/cli provision` (schema re-push is the migration
47
47
  mechanism; additive changes are safe on live tenants), then re-run
48
48
  smoke.
49
49
 
50
+ ## Provision reports an existing o11y token but no local credential
51
+
52
+ Cause: the shown-once token was issued elsewhere, or the local credentials file
53
+ was lost. Plain provision refuses to invalidate a deployed Worker just to
54
+ recover plaintext.
55
+ Fix: after explicit human approval, run
56
+ `npx @odla-ai/cli provision --rotate-o11y-token --push-secrets` (add `--yes`
57
+ when production is in the plan). This persists the replacement before moving it
58
+ to the Worker. Do not use the Studio button for routine recovery; it cannot sync
59
+ the repository's credential file.
60
+
50
61
  ## Clerk-verified requests return no email
51
62
 
52
63
  Cause: the Clerk session token doesn't include an email claim.
@@ -55,15 +66,18 @@ claim, then re-test. The worker only forwards what the JWT carries.
55
66
 
56
67
  ## Re-running provision — is it safe?
57
68
 
58
- Yes: re-runs are idempotent (existing app registration and db keys are
59
- reused; schema/rules re-push). The only destructive flag is
60
- `--rotate-keys`, which mints new db keys — deployed workers keep
61
- working only after you push the new key to them. Use it only on
62
- explicit human request (e.g. a burned key).
69
+ Yes: plain re-runs are idempotent (existing app registration and configured db
70
+ and o11y credentials are reused; schema/rules re-push). Destructive rotation is
71
+ always explicit: `--rotate-o11y-token` replaces only o11y, while
72
+ `--rotate-keys` is the broader credential rotation. Use either only on explicit
73
+ human request, and pair rotation with `--push-secrets` so the Worker receives
74
+ the replacement in the same run. This is not atomic: if the final Wrangler
75
+ transfer fails, the new value is already in the private credentials file. Run
76
+ the printed `secrets push --env ...` retry and do not rotate again.
63
77
 
64
78
  ## Something not covered here
65
79
 
66
- Check, in order: `npx odla-ai doctor` output; the field notes in
67
- https://odla.ai/llms.txt; the relevant
68
- `node_modules/@odla-ai/*/llms.txt`. Do not improvise around a safety
69
- rule to unblock yourself — surface the blocker to the human instead.
80
+ Check, in order: `npx @odla-ai/cli doctor` output; this skill's current phase
81
+ and troubleshooting references; then the relevant installed
82
+ `node_modules/@odla-ai/*/llms.txt`. Do not improvise around a safety rule to
83
+ unblock yourself — surface the blocker to the human instead.
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: odla-o11y-debug
3
+ description: >
4
+ Triage a production issue in an app instrumented with @odla-ai/o11y — find why
5
+ it's erroring, why latency or cost is spiking, and what's unusual about the bad
6
+ requests — by reading the odla-o11y API. Use when a deployed odla app is
7
+ misbehaving and you need to dig into its telemetry.
8
+ runbookOrder: []
9
+ ---
10
+
11
+ # odla-o11y-debug
12
+
13
+ You are debugging a **live odla app** through its observability data. The app is
14
+ instrumented with `@odla-ai/o11y`; its traces, errors, metrics, and LLM cost land
15
+ in the `odla-o11y` collector. This skill is the read side: how to pull the data
16
+ and reason from a symptom to a cause.
17
+
18
+ The core move is **cutting high-dimensional data to isolate the bad slice** — not
19
+ "is p95 high" but "*which* route / status / model / user is dragging it, and what
20
+ do those requests share."
21
+
22
+ ## Access
23
+
24
+ All reads go through the platform shell, operator-authed, so the collector's token
25
+ never leaves the server:
26
+
27
+ ```
28
+ GET https://odla.ai/o11y/<appId>/<endpoint>?env=prod
29
+ Authorization: Bearer <developer-token>
30
+ ```
31
+
32
+ Get `<developer-token>` from the device handshake (`POST https://odla.ai/handshake`
33
+ → approve in the Studio → `POST /handshake/poll`). `env` is `prod` (default) or
34
+ `dev`. If a read returns `{"error":"ae_not_configured"}` (501), the app's metrics
35
+ reads aren't turned on yet — errors/traces still work; say so and fall back to them.
36
+
37
+ ## Endpoints
38
+
39
+ | Endpoint | Answers |
40
+ | --- | --- |
41
+ | `GET /o11y/<app>/events` | recent activity feed (traces + errors), newest first |
42
+ | `GET /o11y/<app>/errors` | deduped error groups (type, code, route, count, last seen) |
43
+ | `GET /o11y/<app>/errors/<fingerprint>` | **one group + its message + STACK + span waterfall** |
44
+ | `GET /o11y/<app>/traces/<traceId>` | the merged span tree for a trace |
45
+ | `GET /o11y/<app>/metrics/red?minutes=60` | request/error/latency by route |
46
+ | `GET /o11y/<app>/metrics/timeseries?minutes=60` | RED over time (spot the spike) |
47
+ | `GET /o11y/<app>/explore?dimension=&metric=` | **RED grouped by ANY dimension** |
48
+ | `GET /o11y/<app>/llm/cost?minutes=1440` | spend by provider/model |
49
+ | `GET /o11y/<app>/llm/cost/timeseries` | spend over time |
50
+ | `GET /o11y/<app>/alerts` | configured triggers + firing history |
51
+
52
+ `explore` dimensions: `route`, `status`, `name`, `kind`, `http_status`,
53
+ `http_method`, `env`. `metric` (what to rank by): `p95_ms`, `avg_ms`, `requests`,
54
+ `errors`.
55
+
56
+ ## Triage loops
57
+
58
+ **An error is reported.** `GET /errors` → find the group by type/route/count →
59
+ `GET /errors/<fingerprint>`. The response `bundle` carries the **message and full
60
+ stack** (recovered from the logs signal — this is the whole point; older builds
61
+ dropped it). Read the stack, then read the `spans` waterfall to see which
62
+ downstream call (db, LLM, fetch) failed or was slow. Name the failing line.
63
+
64
+ **Latency or error rate is spiking ("why is p95 up?").** This is the exploration
65
+ loop:
66
+ 1. `GET /metrics/timeseries?minutes=<window>` — confirm the spike and its window.
67
+ 2. `GET /explore?dimension=route&metric=p95_ms` — which route owns the p95? Then
68
+ pivot the dimension: `status`, `http_status`, `http_method`, `env` — keep
69
+ slicing until one value dominates the metric.
70
+ 3. Pull a couple of the offending traces (`/events` filtered to that route, then
71
+ `/traces/<id>`) and read their spans + attributes. State **what the bad
72
+ requests share** (a route, a status code, a slow db/LLM span, a deploy env).
73
+
74
+ **Cost is climbing.** `GET /llm/cost/timeseries` (when) + `GET /llm/cost` (which
75
+ model). A single expensive model or a runaway call count is usually the story.
76
+
77
+ **"Is anything already watching this?"** `GET /alerts` — configured triggers and
78
+ their firing history (with per-channel delivery). If a spike had no trigger,
79
+ suggest one (metric + threshold + window).
80
+
81
+ ## Reasoning discipline
82
+
83
+ - **Lead with the stack.** For any error, quote `bundle.message` and the top of
84
+ `bundle.stack` before theorizing — it usually names the cause outright.
85
+ - **Isolate before explaining.** Don't explain an aggregate ("p95 is 800ms");
86
+ slice with `explore` until you have the specific cohort, then explain that.
87
+ - **Attribute, don't guess.** "These slow requests are all `http_status=503` on
88
+ `POST /pay`" beats "the payment service might be slow."
89
+ - **Weighted counts.** Metric aggregates are sampling-weighted (Analytics Engine
90
+ adaptively samples under load) — treat counts as estimates, ratios as sound.
91
+ - **Say what you couldn't see.** Arbitrary custom attributes live in the trace
92
+ payload, not the group-by dimensions; if the cohort is defined by a custom
93
+ field, note that you inferred it from individual traces, not an aggregate.
@@ -1 +0,0 @@
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"]}