@odla-ai/cli 0.16.7 → 0.17.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/index.d.cts CHANGED
@@ -235,7 +235,7 @@ declare function adminAi(options: AdminAiOptions): Promise<void>;
235
235
  declare const CAPABILITIES: {
236
236
  readonly cli: readonly ["start an email-bound device request without accepting a password or user session token", "register the app and enable configured services per environment", "issue, persist, and explicitly rotate configured service credentials", "add or remove app co-owners, each of whom self-provisions their own credentials for the shared db without any secret handoff", "write local Worker values and push deployed Worker secrets through Wrangler stdin", "store tenant-vault secrets (including the Clerk webhook secret and reserved Clerk secret key) write-only from stdin or an env var", "compose declared app-capability schema/rules, create guarded seeds when absent, and configure platform AI, auth, and deployment links", "apply Google Calendar booking config, then drive state-bound consent, status, discovery, and disconnect flows (bookings run live through the platform proxy)", "validate integration contracts offline and smoke-test a provisioned db environment plus anonymous capability routes", "run app-attributed hosted security discovery and independent validation without provider keys", "connect/revoke source-read-only GitHub sources and drive commit-pinned hosted security jobs without PATs or provider keys", "let admins manage system AI policy and credentials, inspect attributed usage, and read immutable admin changes through separate short-lived capability-only approvals"];
237
237
  readonly agent: readonly ["install and import the selected odla SDKs", "wrap the Worker with withObservability and choose useful telemetry", "install capability packages, mount their runtime routes, and make application-specific schema, rules, auth, UI, and migration decisions", "wire @odla-ai/calendar into trusted Worker code and keep the app admin key out of browsers"];
238
- readonly human: readonly ["provide the existing odla account email, then sign in and explicitly review/approve the exact device code", "review mirrored calendar/attendee disclosure and complete the server-issued Google consent flow", "consent to production changes with --yes", "request destructive credential rotation explicitly", "review application semantics, security findings, releases, and merges", "approve redacted-source disclosure before hosted security reasoning", "approve GitHub App repository access separately from redacted-snippet disclosure"];
238
+ readonly human: readonly ["provide the existing odla account email, then sign in and explicitly review/approve the exact device code", "review mirrored calendar/attendee disclosure and complete the server-issued Google consent flow", "consent to changes against an app's live database with --yes", "request destructive credential rotation explicitly", "review application semantics, security findings, releases, and merges", "approve redacted-source disclosure before hosted security reasoning", "approve GitHub App repository access separately from redacted-snippet disclosure"];
239
239
  readonly studio: readonly ["view telemetry and environment state", "let signed-in users inventory/revoke their own agent grants and admins audit/global-revoke them", "review calendar connection, granted read scope, selected calendars, and sync health without exposing provider tokens", "perform manual credential recovery — for the primary owner or any co-owner — when the CLI's local shown-once copy is unavailable", "configure system AI purposes and view app/environment/run-attributed usage", "connect/revoke GitHub security sources and inspect ref-to-SHA jobs, routes, retention, coverage, and normalized reports"];
240
240
  };
241
241
  type Output = Pick<typeof console, "log">;
package/dist/index.d.ts CHANGED
@@ -235,7 +235,7 @@ declare function adminAi(options: AdminAiOptions): Promise<void>;
235
235
  declare const CAPABILITIES: {
236
236
  readonly cli: readonly ["start an email-bound device request without accepting a password or user session token", "register the app and enable configured services per environment", "issue, persist, and explicitly rotate configured service credentials", "add or remove app co-owners, each of whom self-provisions their own credentials for the shared db without any secret handoff", "write local Worker values and push deployed Worker secrets through Wrangler stdin", "store tenant-vault secrets (including the Clerk webhook secret and reserved Clerk secret key) write-only from stdin or an env var", "compose declared app-capability schema/rules, create guarded seeds when absent, and configure platform AI, auth, and deployment links", "apply Google Calendar booking config, then drive state-bound consent, status, discovery, and disconnect flows (bookings run live through the platform proxy)", "validate integration contracts offline and smoke-test a provisioned db environment plus anonymous capability routes", "run app-attributed hosted security discovery and independent validation without provider keys", "connect/revoke source-read-only GitHub sources and drive commit-pinned hosted security jobs without PATs or provider keys", "let admins manage system AI policy and credentials, inspect attributed usage, and read immutable admin changes through separate short-lived capability-only approvals"];
237
237
  readonly agent: readonly ["install and import the selected odla SDKs", "wrap the Worker with withObservability and choose useful telemetry", "install capability packages, mount their runtime routes, and make application-specific schema, rules, auth, UI, and migration decisions", "wire @odla-ai/calendar into trusted Worker code and keep the app admin key out of browsers"];
238
- readonly human: readonly ["provide the existing odla account email, then sign in and explicitly review/approve the exact device code", "review mirrored calendar/attendee disclosure and complete the server-issued Google consent flow", "consent to production changes with --yes", "request destructive credential rotation explicitly", "review application semantics, security findings, releases, and merges", "approve redacted-source disclosure before hosted security reasoning", "approve GitHub App repository access separately from redacted-snippet disclosure"];
238
+ readonly human: readonly ["provide the existing odla account email, then sign in and explicitly review/approve the exact device code", "review mirrored calendar/attendee disclosure and complete the server-issued Google consent flow", "consent to changes against an app's live database with --yes", "request destructive credential rotation explicitly", "review application semantics, security findings, releases, and merges", "approve redacted-source disclosure before hosted security reasoning", "approve GitHub App repository access separately from redacted-snippet disclosure"];
239
239
  readonly studio: readonly ["view telemetry and environment state", "let signed-in users inventory/revoke their own agent grants and admins audit/global-revoke them", "review calendar connection, granted read scope, selected calendars, and sync health without exposing provider tokens", "perform manual credential recovery — for the primary owner or any co-owner — when the CLI's local shown-once copy is unavailable", "configure system AI purposes and view app/environment/run-attributed usage", "connect/revoke GitHub security sources and inspect ref-to-SHA jobs, routes, retention, coverage, and normalized reports"];
240
240
  };
241
241
  type Output = Pick<typeof console, "log">;
package/dist/index.js CHANGED
@@ -43,7 +43,7 @@ import {
43
43
  secretsSetClerkKey,
44
44
  smoke,
45
45
  startHostedSecurityJob
46
- } from "./chunk-X3HUN6S3.js";
46
+ } from "./chunk-2UKO2NED.js";
47
47
  export {
48
48
  AGENT_HARNESSES,
49
49
  CAPABILITIES,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@odla-ai/cli",
3
- "version": "0.16.7",
3
+ "version": "0.17.0",
4
4
  "description": "Agent-operable CLI for odla provisioning, calendar consent and sync lifecycle, System AI administration, Worker secrets, security jobs, and smoke checks.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://odla.ai/docs/packages/cli",
@@ -57,10 +57,10 @@
57
57
  "prepublishOnly": "npm run build"
58
58
  },
59
59
  "dependencies": {
60
- "@odla-ai/ai": ">=0.5.0 <0.7.0",
61
- "@odla-ai/apps": "^0.8.1",
60
+ "@odla-ai/ai": ">=0.5.0 <1.0.0",
61
+ "@odla-ai/apps": ">=0.8.1 <1.0.0",
62
62
  "@odla-ai/db": ">=0.6.4",
63
- "@odla-ai/security": "^0.3.1"
63
+ "@odla-ai/security": ">=0.3.1 <1.0.0"
64
64
  },
65
65
  "devDependencies": {
66
66
  "@odla-ai/harness": "*",
@@ -41,11 +41,13 @@ State which path you're taking and what you'll build in one line; get a nod.
41
41
  A fresh odla device request also needs the existing account email via
42
42
  `--email` or `ODLA_USER_EMAIL`; email is a non-secret identifier. Never ask
43
43
  for an odla password, Clerk token, or browser session.
44
- 2. **Dev before prod.** Keep `envs: ["dev"]` and verify the tenant
45
- (`<appId>--dev`) before any write or deploy. Add `prod` only at the explicit
46
- production checkpoint. The first prod
47
- `provision --dry-run` review, `provision --yes --push-secrets`, and deploy
48
- are human checkpoints.
44
+ 2. **Sandbox before live.** Every app has two databases on production odla.ai:
45
+ a sandbox (env `dev`, tenant `<appId>--dev`) and a live one (env `prod`,
46
+ tenant `<appId>`). "prod" names the app's live DATABASE, never a different
47
+ odla there is only one odla.ai. Keep `envs: ["dev"]` and verify the tenant
48
+ before any write or deploy. Add `prod` only at the explicit go-live
49
+ checkpoint. That first live `provision --dry-run` review,
50
+ `provision --yes --push-secrets`, and deploy are human checkpoints.
49
51
  3. **Rules are default-deny.** A namespace with no rule is invisible; a write
50
52
  with no rule is rejected. Never widen a rule just to clear a 403 — edit
51
53
  `src/odla/rules.mjs` deliberately, and flag rule changes to the human.
@@ -155,6 +155,15 @@ injected isolated executor and never falls back to the host shell.
155
155
 
156
156
  ## Others
157
157
 
158
+ - **@odla-ai/chapter** — membership sites from one `defineChapter()` config:
159
+ generates the odla-db schema + deny-all rules + group seed + provisioning
160
+ integration, and ships the worker (join/apply, Stripe membership, Google
161
+ booking, member area, exactly-once lifecycle email, CRM projection) plus a UI
162
+ kit. Composable: `chapterWorker({ chapter, routes })` runs host routes before
163
+ the built-ins and shares its auth context, and `./ui/member` is react-only
164
+ (no Clerk SDK) while `./ui/admin` is the gated console. **If a migration target
165
+ is a membership site, start here instead of hand-authoring schema** — see
166
+ `odla-migrate/references/phase-2-chapter.md`.
158
167
  - **@odla-ai/ui** — design system: CSS tokens, five themes, component styles,
159
168
  chart helpers.
160
169
  - **@odla-ai/kg** — ontology-driven knowledge graph: source connectors, LLM
@@ -33,8 +33,10 @@ installed skill at `../odla/SKILL.md` instead.
33
33
 
34
34
  1. The old site (GitHub Pages) stays live and untouched until Phase 5
35
35
  sign-off. Before that, rollback is always "do nothing."
36
- 2. Dev only until Phase 5: `envs: ["dev"]` in odla.config.mjs; the dev
37
- tenant is `<appId>--dev`. Verify the tenant before any write or deploy.
36
+ 2. Sandbox database only until Phase 5: `envs: ["dev"]` in odla.config.mjs; the
37
+ sandbox tenant is `<appId>--dev`, and the app's live database (env `prod`)
38
+ is the bare `<appId>`. Both sit on production odla.ai. Verify the tenant
39
+ before any write or deploy.
38
40
  3. Never print, paste, or commit a secret. Never `cat` .dev.vars,
39
41
  .odla/credentials.local.json, or .odla/dev-token.json. Read
40
42
  references/secrets-map.md BEFORE any command that touches a credential.
@@ -0,0 +1,88 @@
1
+ # Phase 2 (chapter): membership sites start from `defineChapter()`
2
+
3
+ **Use this instead of hand-authoring `src/odla/schema.mjs` when the site is a
4
+ membership site** — applications/join, paid membership, booked intro calls, a
5
+ member area, an admin console, a people CRM. `@odla-ai/chapter` generates all of
6
+ that. A real conversion deleted ~2,500 lines: a 2,094-line worker became 6, and
7
+ four hand-maintained files (schema, rules, group seed, provisioner) became one
8
+ `defineChapter()` call.
9
+
10
+ If the app is NOT a membership site, stay on `phase-2-db.md`. If it is a
11
+ membership site with a few extra entities, use chapter for what it models and
12
+ hand-author only the namespaces it does not.
13
+
14
+ ## The sequence (do not reorder)
15
+
16
+ 1. **Write the config and assert parity BEFORE deleting anything.**
17
+ ```js
18
+ export const chapter = defineChapter({
19
+ id: "example-chapter", name: "Example", mode: "chapter",
20
+ prices: { standardCents: 90000 },
21
+ emails: { notificationEmail: "owner@example.com" },
22
+ });
23
+ ```
24
+ Then diff `chapter.schema` against the site's existing schema **in a test** and
25
+ require equality. That single assertion is what makes the deletion safe rather
26
+ than hopeful.
27
+ 2. **Freeze the old schema as a fixture, don't just delete it.** Move it to
28
+ `test/fixtures/legacy-schema.mjs` and keep asserting against it, so an upstream
29
+ default change fails a test instead of a live `provision`. It costs nothing and
30
+ is the only durable guard against drift in a generated schema.
31
+ 3. **Swap provisioning** — `createChapterIntegration(chapter)` in
32
+ `odla.config.mjs` `integrations: [...]`. Inert until the next provision run. It
33
+ supplies schema + rules + seeds, so the `db` block goes away entirely.
34
+ 4. **Then the worker**, keeping every bespoke route as a host route:
35
+ `chapterWorker({ chapter, routes })` runs host routes BEFORE the built-ins and
36
+ hands each the same context (`ctx.verifyUser`, `ctx.makeDb`, `ctx.roleFor`,
37
+ `ctx.isAdmin`), so you never verify a JWT twice. Do NOT hand routes over to
38
+ chapter in the same change as the framework swap.
39
+ 5. **Override rather than inherit wherever local behavior was a decision.**
40
+ 6. `npx @odla-ai/cli doctor` → `provision --dry-run` (show the human) → provision.
41
+
42
+ The same parity-before-deletion pattern works for UI: render the packaged
43
+ component beside yours, assert byte-identical markup, then delete yours and keep
44
+ the test as an integration guard — the CSS class contract is the site's, not the
45
+ package's.
46
+
47
+ ## Behavior deltas to audit
48
+
49
+ These bite silently; no smoke test catches them.
50
+
51
+ - **Per-field caps.** `application.defaultMaxLen` is 2000. A join form accepting a
52
+ 5000-char message starts rejecting input. Pass `maxLen` explicitly.
53
+ - **`services` default** is `["db","calendar","o11y"]`; `smoke` compares config
54
+ against the platform, so set it explicitly if you don't run the o11y collector.
55
+ - **Which email fires from which route.** `adminNotification` fires on
56
+ `POST /api/applications` by default; `prepEmail` from `/api/schedule/book`;
57
+ `paymentConfirmation` from the Stripe webhook. Set
58
+ `sends: { adminNotification: "payment" | "submit" | "never" }` if the site's
59
+ policy differs — and re-check this on every chapter upgrade, since wiring a
60
+ send changes outbound mail with no local diff.
61
+ - **Account creation model.** `account: "invite"` (default) mints a Clerk
62
+ invitation; `"create"` makes the account server-side; `"none"` skips. Swapping
63
+ in chapter's route while expecting server-side create loses it silently — the
64
+ applicant finds out when they cannot sign in.
65
+ - **CRM projection points.** chapter projects on application submit, not on
66
+ booking or webhook status change. Mirroring pipeline stage into the CRM means
67
+ keeping those routes.
68
+ - **Route names.** chapter serves `/api/config`, `/api/join-config`. Alias legacy
69
+ names in ~4 lines as host routes rather than rewriting pages.
70
+
71
+ ## Install notes
72
+
73
+ - **A worker-only adoption does not need `@odla-ai/auth-clerk`.** The worker
74
+ verifies Clerk JWTs with `jose` via `ctx.verifyUser`. Install auth-clerk only
75
+ for `@odla-ai/chapter/ui/admin` (the Clerk-gated console) or the themed sign-in
76
+ components; `@odla-ai/chapter/ui/member` needs nothing but react.
77
+ - **`--legacy-peer-deps` is a diagnostic, not a setting.** It suppresses exactly
78
+ the peer error that tells you a pair is unsupported. If an install errors, read
79
+ it. A site that left the flag on ran an unsupported ui/crm pair for a day with
80
+ no signal.
81
+
82
+ ## Verify the surface from the types
83
+
84
+ Docs lag at this release cadence. **Read `dist/*.d.ts` and grep the built bundle
85
+ for route strings; treat prose as intent.** When verifying live routes, note that
86
+ Clerk session tokens expire in ~60s — a script that mints a JWT then runs a batch
87
+ of curls must re-mint per batch (`clerk api /sessions`, then
88
+ `/sessions/<id>/tokens`).
@@ -27,7 +27,16 @@ opens the review page in interactive terminals; loading it alone is inert.
27
27
  re-project on read), lists need explicit `order`, uniques are
28
28
  single-attr (derive composite keys), ON CONFLICT maps to `mutationId`
29
29
  dedupe.
30
- 4. Write `src/odla/schema.mjs` for the app's entities. KEEP the
30
+ 4. **Membership site? Go to `phase-2-chapter.md` before writing any
31
+ schema.** If the app has applications/join, paid membership, booked
32
+ intro calls, a member area, an admin console or a people CRM, then
33
+ `defineChapter()` from `@odla-ai/chapter` GENERATES the schema, the
34
+ deny-all rules, the seed row and the provisioning integration. Hand-
35
+ authoring them here is exactly the work that package exists to delete
36
+ (a real conversion cut ~2,500 lines). Use chapter for what it models;
37
+ hand-author only the namespaces it does not.
38
+
39
+ Otherwise, write `src/odla/schema.mjs` for the app's entities. KEEP the
31
40
  generated deny-all `src/odla/rules.mjs`: the worker mediates all
32
41
  access with its app key (which bypasses rules); browsers get nothing
33
42
  directly. Loosening a rule is a human checkpoint.