@odla-ai/cli 0.16.7 → 0.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.cjs +346 -61
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-X3HUN6S3.js → chunk-2UKO2NED.js} +312 -20
- package/dist/chunk-2UKO2NED.js.map +1 -0
- package/dist/index.cjs +346 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +4 -4
- package/skills/odla/SKILL.md +7 -5
- package/skills/odla/references/sdks.md +9 -0
- package/skills/odla-migrate/SKILL.md +4 -2
- package/skills/odla-migrate/references/phase-2-chapter.md +90 -0
- package/skills/odla-migrate/references/phase-2-db.md +10 -1
- package/dist/chunk-X3HUN6S3.js.map +0 -1
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
|
|
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
|
|
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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@odla-ai/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.1",
|
|
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.
|
|
61
|
-
"@odla-ai/apps": "
|
|
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": "
|
|
63
|
+
"@odla-ai/security": ">=0.3.1 <1.0.0"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@odla-ai/harness": "*",
|
package/skills/odla/SKILL.md
CHANGED
|
@@ -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. **
|
|
45
|
-
(`<appId>--dev`)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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.
|
|
37
|
-
tenant is `<appId>--dev
|
|
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,90 @@
|
|
|
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` defaults to **`"none"`** (provisions
|
|
62
|
+
nothing) — the other models have an outbound side effect, so a site opts in.
|
|
63
|
+
`"create"` makes the account server-side; `"invite"` **emails a Clerk
|
|
64
|
+
invitation**. Swapping in chapter's route while expecting server-side create
|
|
65
|
+
loses it silently unless you set `account: "create"` — the applicant finds out
|
|
66
|
+
when they cannot sign in.
|
|
67
|
+
- **CRM projection points.** chapter projects on application submit, not on
|
|
68
|
+
booking or webhook status change. Mirroring pipeline stage into the CRM means
|
|
69
|
+
keeping those routes.
|
|
70
|
+
- **Route names.** chapter serves `/api/config`, `/api/join-config`. Alias legacy
|
|
71
|
+
names in ~4 lines as host routes rather than rewriting pages.
|
|
72
|
+
|
|
73
|
+
## Install notes
|
|
74
|
+
|
|
75
|
+
- **A worker-only adoption does not need `@odla-ai/auth-clerk`.** The worker
|
|
76
|
+
verifies Clerk JWTs with `jose` via `ctx.verifyUser`. Install auth-clerk only
|
|
77
|
+
for `@odla-ai/chapter/ui/admin` (the Clerk-gated console) or the themed sign-in
|
|
78
|
+
components; `@odla-ai/chapter/ui/member` needs nothing but react.
|
|
79
|
+
- **`--legacy-peer-deps` is a diagnostic, not a setting.** It suppresses exactly
|
|
80
|
+
the peer error that tells you a pair is unsupported. If an install errors, read
|
|
81
|
+
it. A site that left the flag on ran an unsupported ui/crm pair for a day with
|
|
82
|
+
no signal.
|
|
83
|
+
|
|
84
|
+
## Verify the surface from the types
|
|
85
|
+
|
|
86
|
+
Docs lag at this release cadence. **Read `dist/*.d.ts` and grep the built bundle
|
|
87
|
+
for route strings; treat prose as intent.** When verifying live routes, note that
|
|
88
|
+
Clerk session tokens expire in ~60s — a script that mints a JWT then runs a batch
|
|
89
|
+
of curls must re-mint per batch (`clerk api /sessions`, then
|
|
90
|
+
`/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.
|
|
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.
|