@odla-ai/cli 0.10.0 → 0.10.2

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
@@ -30,6 +30,8 @@ type ScopedPlatformScope = "platform:ai:policy:read" | "platform:ai:policy:write
30
30
  interface ScopedPlatformTokenOptions {
31
31
  platform: string;
32
32
  scope: ScopedPlatformScope;
33
+ /** Existing odla account email used only when a fresh handshake is required. */
34
+ email?: string;
33
35
  open?: boolean;
34
36
  fetch?: typeof fetch;
35
37
  stdout?: Pick<typeof console, "log">;
@@ -59,6 +61,8 @@ interface AdminAiOptions {
59
61
  maxCallsPerRun?: number;
60
62
  platform?: string;
61
63
  token?: string;
64
+ /** Existing odla account email used only when a fresh handshake is required. */
65
+ email?: string;
62
66
  json?: boolean;
63
67
  open?: boolean;
64
68
  fetch?: typeof fetch;
@@ -91,16 +95,17 @@ declare function adminAi(options: AdminAiOptions): Promise<void>;
91
95
  /** Stable, machine-readable division of work between the CLI, coding agent,
92
96
  * human operator, and Studio. Printed by `odla-ai capabilities --json`. */
93
97
  declare const CAPABILITIES: {
94
- readonly cli: readonly ["register the app and enable configured services per environment", "issue, persist, and explicitly rotate configured service credentials", "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", "push db schema/rules and configure platform AI, auth, and deployment links", "apply read-only Google calendar mirror and public booking-page config, then drive state-bound consent, status, discovery, resync, and disconnect flows", "validate config offline and smoke-test a provisioned db environment", "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"];
98
+ 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", "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", "push db schema/rules and configure platform AI, auth, and deployment links", "apply read-only Google calendar mirror and public booking-page config, then drive state-bound consent, status, discovery, resync, and disconnect flows", "validate config offline and smoke-test a provisioned db environment", "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"];
95
99
  readonly agent: readonly ["install and import the selected odla SDKs", "wrap the Worker with withObservability and choose useful telemetry", "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"];
96
- readonly human: readonly ["approve the odla device code and one-off third-party logins", "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"];
97
- readonly studio: readonly ["view telemetry and environment state", "review calendar connection, granted read scope, selected calendars, and sync health without exposing provider tokens", "perform manual credential recovery 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"];
100
+ 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"];
101
+ 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 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"];
98
102
  };
99
103
  type Output = Pick<typeof console, "log">;
100
104
  /** Print the stable responsibility boundary for humans or agent tooling. */
101
105
  declare function printCapabilities(json?: boolean, out?: Output): void;
102
106
 
103
107
  declare const CALENDAR_STATES: readonly ["not_connected", "authorizing", "needs_sync", "initial_sync", "healthy", "degraded", "disconnected", "failed"];
108
+ /** Connection lifecycle reported by the registry; mirrors the platform's calendar states. */
104
109
  type CalendarConnectionState = (typeof CALENDAR_STATES)[number];
105
110
  /** Owner-visible, secret-free calendar connection and sync health. */
106
111
  interface CalendarStatus {
@@ -136,10 +141,15 @@ interface AvailableGoogleCalendar {
136
141
  accessRole?: "freeBusyReader" | "reader" | "writer" | "owner";
137
142
  }
138
143
 
144
+ /** Shared inputs for the calendar lifecycle commands (status, connect,
145
+ * calendars, resync, disconnect): the project config path and env, plus
146
+ * injectable token, output, browser, clock, and polling hooks so agents and
147
+ * tests can drive the flow deterministically. */
139
148
  interface CalendarLifecycleOptions {
140
- configPath: string;
141
- env?: string;
142
- token?: string;
149
+ /** Path to the checked-in odla project config. */ configPath: string;
150
+ /** Configured environment; defaults to dev when present. */ env?: string;
151
+ /** Existing developer-token override. */ token?: string;
152
+ /** Existing odla account email used only for a fresh handshake. */ email?: string;
143
153
  open?: boolean;
144
154
  interactive?: boolean;
145
155
  yes?: boolean;
@@ -206,6 +216,8 @@ interface GoogleCalendarConfig {
206
216
  /** Store normalized attendee addresses, or only SHA-256 match keys. */
207
217
  attendeePolicy?: "full" | "hashed";
208
218
  }
219
+ /** The `calendar` block of `odla.config.mjs` — the Google read-mirror
220
+ * settings; valid only alongside the db service. */
209
221
  interface CalendarConfig {
210
222
  google: GoogleCalendarConfig;
211
223
  }
@@ -309,6 +321,8 @@ interface ProvisionOptions {
309
321
  writeCredentials?: boolean;
310
322
  writeDevVars?: string | boolean;
311
323
  token?: string;
324
+ /** Existing odla account email used only when a fresh device handshake is required. */
325
+ email?: string;
312
326
  /** true forces browser launch, false disables it, undefined auto-opens only for interactive terminals. */
313
327
  open?: boolean;
314
328
  /** Test/embedding override for terminal interactivity. Defaults to stdin/stdout TTY detection. */
@@ -344,6 +358,8 @@ interface SmokeOptions {
344
358
  env?: string;
345
359
  /** Developer-token override used only for owner-visible calendar health. */
346
360
  token?: string;
361
+ /** Existing odla account email used only when a fresh device handshake is required. */
362
+ email?: string;
347
363
  open?: boolean;
348
364
  interactive?: boolean;
349
365
  openApprovalUrl?: (url: string) => Promise<void>;
@@ -351,6 +367,7 @@ interface SmokeOptions {
351
367
  stdout?: Pick<typeof console, "log" | "error">;
352
368
  }
353
369
 
370
+ /** The only Google OAuth scope the platform ever requests: read-only calendar events. */
354
371
  declare const GOOGLE_CALENDAR_READ_SCOPE = "https://www.googleapis.com/auth/calendar.events.readonly";
355
372
  /** Resolve the checked-in calendar block into one controller-safe env payload. */
356
373
  declare function calendarServiceConfig(cfg: LoadedProjectConfig, env: string): CalendarServiceConfig;
@@ -434,14 +451,17 @@ declare function initProject(options: InitOptions): void;
434
451
  * (mode 0600, gitignored) and, when requested, `.dev.vars`.
435
452
  *
436
453
  * The developer token comes from (in order) `options.token`, `$ODLA_DEV_TOKEN`,
437
- * the cached `.odla` token, or a fresh device handshake — which prints a user
438
- * code + approval URL and, in interactive terminals, auto-opens the browser
454
+ * the cached `.odla` token, or a fresh email-bound device handshake — which
455
+ * prints a user code for the same signed-in account to review and, in
456
+ * interactive terminals, auto-opens the browser
439
457
  * (`open: true`/`false` forces/suppresses it). Network error bodies pass through
440
458
  * `redactSecrets` before display.
441
459
  *
442
460
  * @param options.dryRun Print the resolved plan and return before any network call/write.
443
461
  * @param options.rotateKeys Rotate db keys and o11y tokens.
444
462
  * @param options.rotateO11yToken Rotate only the o11y token.
463
+ * @param options.email Existing odla account email for a fresh handshake;
464
+ * this is an identity hint, never a password or session credential.
445
465
  * @param options.pushSecrets Preflight Wrangler, then push each env's configured
446
466
  * Worker secrets immediately after credential provisioning.
447
467
  * @param options.writeDevVars `true`/a path writes `.dev.vars`; `writeCredentials: false` skips the creds file.
@@ -499,6 +519,8 @@ interface SecretsSetOptions {
499
519
  yes?: boolean;
500
520
  /** Developer token override; defaults to $ODLA_DEV_TOKEN, the cached token, or a device handshake. */
501
521
  token?: string;
522
+ /** Existing odla account email used only when a fresh handshake is required. */
523
+ email?: string;
502
524
  open?: boolean;
503
525
  interactive?: boolean;
504
526
  openApprovalUrl?: (url: string) => Promise<void>;
package/dist/index.d.ts CHANGED
@@ -30,6 +30,8 @@ type ScopedPlatformScope = "platform:ai:policy:read" | "platform:ai:policy:write
30
30
  interface ScopedPlatformTokenOptions {
31
31
  platform: string;
32
32
  scope: ScopedPlatformScope;
33
+ /** Existing odla account email used only when a fresh handshake is required. */
34
+ email?: string;
33
35
  open?: boolean;
34
36
  fetch?: typeof fetch;
35
37
  stdout?: Pick<typeof console, "log">;
@@ -59,6 +61,8 @@ interface AdminAiOptions {
59
61
  maxCallsPerRun?: number;
60
62
  platform?: string;
61
63
  token?: string;
64
+ /** Existing odla account email used only when a fresh handshake is required. */
65
+ email?: string;
62
66
  json?: boolean;
63
67
  open?: boolean;
64
68
  fetch?: typeof fetch;
@@ -91,16 +95,17 @@ declare function adminAi(options: AdminAiOptions): Promise<void>;
91
95
  /** Stable, machine-readable division of work between the CLI, coding agent,
92
96
  * human operator, and Studio. Printed by `odla-ai capabilities --json`. */
93
97
  declare const CAPABILITIES: {
94
- readonly cli: readonly ["register the app and enable configured services per environment", "issue, persist, and explicitly rotate configured service credentials", "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", "push db schema/rules and configure platform AI, auth, and deployment links", "apply read-only Google calendar mirror and public booking-page config, then drive state-bound consent, status, discovery, resync, and disconnect flows", "validate config offline and smoke-test a provisioned db environment", "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"];
98
+ 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", "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", "push db schema/rules and configure platform AI, auth, and deployment links", "apply read-only Google calendar mirror and public booking-page config, then drive state-bound consent, status, discovery, resync, and disconnect flows", "validate config offline and smoke-test a provisioned db environment", "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"];
95
99
  readonly agent: readonly ["install and import the selected odla SDKs", "wrap the Worker with withObservability and choose useful telemetry", "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"];
96
- readonly human: readonly ["approve the odla device code and one-off third-party logins", "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"];
97
- readonly studio: readonly ["view telemetry and environment state", "review calendar connection, granted read scope, selected calendars, and sync health without exposing provider tokens", "perform manual credential recovery 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"];
100
+ 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"];
101
+ 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 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"];
98
102
  };
99
103
  type Output = Pick<typeof console, "log">;
100
104
  /** Print the stable responsibility boundary for humans or agent tooling. */
101
105
  declare function printCapabilities(json?: boolean, out?: Output): void;
102
106
 
103
107
  declare const CALENDAR_STATES: readonly ["not_connected", "authorizing", "needs_sync", "initial_sync", "healthy", "degraded", "disconnected", "failed"];
108
+ /** Connection lifecycle reported by the registry; mirrors the platform's calendar states. */
104
109
  type CalendarConnectionState = (typeof CALENDAR_STATES)[number];
105
110
  /** Owner-visible, secret-free calendar connection and sync health. */
106
111
  interface CalendarStatus {
@@ -136,10 +141,15 @@ interface AvailableGoogleCalendar {
136
141
  accessRole?: "freeBusyReader" | "reader" | "writer" | "owner";
137
142
  }
138
143
 
144
+ /** Shared inputs for the calendar lifecycle commands (status, connect,
145
+ * calendars, resync, disconnect): the project config path and env, plus
146
+ * injectable token, output, browser, clock, and polling hooks so agents and
147
+ * tests can drive the flow deterministically. */
139
148
  interface CalendarLifecycleOptions {
140
- configPath: string;
141
- env?: string;
142
- token?: string;
149
+ /** Path to the checked-in odla project config. */ configPath: string;
150
+ /** Configured environment; defaults to dev when present. */ env?: string;
151
+ /** Existing developer-token override. */ token?: string;
152
+ /** Existing odla account email used only for a fresh handshake. */ email?: string;
143
153
  open?: boolean;
144
154
  interactive?: boolean;
145
155
  yes?: boolean;
@@ -206,6 +216,8 @@ interface GoogleCalendarConfig {
206
216
  /** Store normalized attendee addresses, or only SHA-256 match keys. */
207
217
  attendeePolicy?: "full" | "hashed";
208
218
  }
219
+ /** The `calendar` block of `odla.config.mjs` — the Google read-mirror
220
+ * settings; valid only alongside the db service. */
209
221
  interface CalendarConfig {
210
222
  google: GoogleCalendarConfig;
211
223
  }
@@ -309,6 +321,8 @@ interface ProvisionOptions {
309
321
  writeCredentials?: boolean;
310
322
  writeDevVars?: string | boolean;
311
323
  token?: string;
324
+ /** Existing odla account email used only when a fresh device handshake is required. */
325
+ email?: string;
312
326
  /** true forces browser launch, false disables it, undefined auto-opens only for interactive terminals. */
313
327
  open?: boolean;
314
328
  /** Test/embedding override for terminal interactivity. Defaults to stdin/stdout TTY detection. */
@@ -344,6 +358,8 @@ interface SmokeOptions {
344
358
  env?: string;
345
359
  /** Developer-token override used only for owner-visible calendar health. */
346
360
  token?: string;
361
+ /** Existing odla account email used only when a fresh device handshake is required. */
362
+ email?: string;
347
363
  open?: boolean;
348
364
  interactive?: boolean;
349
365
  openApprovalUrl?: (url: string) => Promise<void>;
@@ -351,6 +367,7 @@ interface SmokeOptions {
351
367
  stdout?: Pick<typeof console, "log" | "error">;
352
368
  }
353
369
 
370
+ /** The only Google OAuth scope the platform ever requests: read-only calendar events. */
354
371
  declare const GOOGLE_CALENDAR_READ_SCOPE = "https://www.googleapis.com/auth/calendar.events.readonly";
355
372
  /** Resolve the checked-in calendar block into one controller-safe env payload. */
356
373
  declare function calendarServiceConfig(cfg: LoadedProjectConfig, env: string): CalendarServiceConfig;
@@ -434,14 +451,17 @@ declare function initProject(options: InitOptions): void;
434
451
  * (mode 0600, gitignored) and, when requested, `.dev.vars`.
435
452
  *
436
453
  * The developer token comes from (in order) `options.token`, `$ODLA_DEV_TOKEN`,
437
- * the cached `.odla` token, or a fresh device handshake — which prints a user
438
- * code + approval URL and, in interactive terminals, auto-opens the browser
454
+ * the cached `.odla` token, or a fresh email-bound device handshake — which
455
+ * prints a user code for the same signed-in account to review and, in
456
+ * interactive terminals, auto-opens the browser
439
457
  * (`open: true`/`false` forces/suppresses it). Network error bodies pass through
440
458
  * `redactSecrets` before display.
441
459
  *
442
460
  * @param options.dryRun Print the resolved plan and return before any network call/write.
443
461
  * @param options.rotateKeys Rotate db keys and o11y tokens.
444
462
  * @param options.rotateO11yToken Rotate only the o11y token.
463
+ * @param options.email Existing odla account email for a fresh handshake;
464
+ * this is an identity hint, never a password or session credential.
445
465
  * @param options.pushSecrets Preflight Wrangler, then push each env's configured
446
466
  * Worker secrets immediately after credential provisioning.
447
467
  * @param options.writeDevVars `true`/a path writes `.dev.vars`; `writeCredentials: false` skips the creds file.
@@ -499,6 +519,8 @@ interface SecretsSetOptions {
499
519
  yes?: boolean;
500
520
  /** Developer token override; defaults to $ODLA_DEV_TOKEN, the cached token, or a device handshake. */
501
521
  token?: string;
522
+ /** Existing odla account email used only when a fresh handshake is required. */
523
+ email?: string;
502
524
  open?: boolean;
503
525
  interactive?: boolean;
504
526
  openApprovalUrl?: (url: string) => Promise<void>;
package/dist/index.js CHANGED
@@ -38,7 +38,7 @@ import {
38
38
  secretsSetClerkKey,
39
39
  smoke,
40
40
  startHostedSecurityJob
41
- } from "./chunk-WDKBW4BE.js";
41
+ } from "./chunk-MWVKOIGR.js";
42
42
  export {
43
43
  AGENT_HARNESSES,
44
44
  CAPABILITIES,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@odla-ai/cli",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
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",
@@ -27,8 +27,7 @@
27
27
  "dist",
28
28
  "skills",
29
29
  "README.md",
30
- "REQUIREMENTS.md",
31
- "llms.txt"
30
+ "REQUIREMENTS.md"
32
31
  ],
33
32
  "sideEffects": false,
34
33
  "engines": {
@@ -55,14 +54,13 @@
55
54
  "typecheck": "tsc --noEmit",
56
55
  "test": "vitest run",
57
56
  "coverage": "vitest run --coverage",
58
- "gen:llms": "node ../../scripts/gen-llms.mjs",
59
- "prepublishOnly": "npm run build && npm run gen:llms"
57
+ "prepublishOnly": "npm run build"
60
58
  },
61
59
  "dependencies": {
62
- "@odla-ai/ai": "^0.3.3",
63
- "@odla-ai/apps": "^0.8.0",
64
- "@odla-ai/db": "^0.6.2",
65
- "@odla-ai/security": "^0.2.2"
60
+ "@odla-ai/ai": "^0.4.0",
61
+ "@odla-ai/apps": "^0.8.1",
62
+ "@odla-ai/db": "^0.6.4",
63
+ "@odla-ai/security": "^0.3.1"
66
64
  },
67
65
  "devDependencies": {
68
66
  "@types/node": "^22.10.0",
@@ -37,6 +37,9 @@ State which path you're taking and what you'll build in one line; get a nod.
37
37
  `.odla/credentials.local.json`, or `.odla/dev-token.json` — use `ls -l` to
38
38
  confirm they exist (and are `0600`). The only value a human ever pastes is a
39
39
  Clerk **publishable** key (`pk_…`) — public by design.
40
+ A fresh odla device request also needs the existing account email via
41
+ `--email` or `ODLA_USER_EMAIL`; email is a non-secret identifier. Never ask
42
+ for an odla password, Clerk token, or browser session.
40
43
  2. **Dev before prod.** Keep `envs: ["dev"]` and verify the tenant
41
44
  (`<appId>--dev`) before any write or deploy. Add `prod` only at the explicit
42
45
  production checkpoint. The first prod
@@ -66,8 +69,10 @@ guessing which platform/credential steps need manual work. Then:
66
69
  `withObservability`. The CLI will refuse secret delivery until the Wrangler
67
70
  target exists.
68
71
  3. **provision** ⏸ —
69
- `npx @odla-ai/cli provision --write-dev-vars --push-secrets`. A device code
70
- prints; the human approves it at https://odla.ai/studio. It creates the app,
72
+ `npx @odla-ai/cli provision --email <existing-odla-account>
73
+ --write-dev-vars --push-secrets`. A device code prints; that same account
74
+ signs in, reviews the exact code, and approves it at https://odla.ai/studio.
75
+ Opening the link alone is inert. It creates the app,
71
76
  enables services, issues or reuses configured credentials (db key + o11y
72
77
  ingest token when enabled), pushes schema + rules, writes `.dev.vars`, and
73
78
  transfers Worker secrets through Wrangler stdin. With calendar enabled it
@@ -119,5 +124,7 @@ code, paste a publishable key, run a command) — and wait for a nod.
119
124
  - `references/build.md` — the greenfield build, step by step, with the exact
120
125
  commands and what to verify at each one.
121
126
  - `references/sdks.md` — SDK cheat-sheet (what each does + minimal real usage).
122
- Every installed SDK also ships `node_modules/@odla-ai/<pkg>/llms.txt` read
123
- it for the full, current API.
127
+ For the full, version-matched API, read the installed package's README and
128
+ exported TypeScript declarations/JSDoc (resolve entry points through its
129
+ `package.json` `exports`). Rendered references are also public at
130
+ `https://odla.ai/docs/packages/<pkg>`.
@@ -30,18 +30,21 @@ deployed-secret transfer. With o11y, install `@odla-ai/o11y`, add
30
30
  `"nodejs_compat"` to `compatibility_flags`, and wrap the entrypoint with
31
31
  `withObservability`.
32
32
 
33
- Each installed package's `node_modules/@odla-ai/<pkg>/llms.txt` is the full API
34
- contract. The npm artifacts contain everything required for this flow; private
35
- service source or online documentation is not setup context.
33
+ Each installed package's README and exported TypeScript declarations/JSDoc are
34
+ the version-matched API contract; resolve public entry points through its
35
+ `package.json` `exports`. The npm artifacts contain everything required for
36
+ this flow; private service source or online documentation is not setup context.
36
37
 
37
38
  ## 3. Provision ⏸ device-code approval
38
39
 
39
40
  ```
40
- npx @odla-ai/cli provision --write-dev-vars --push-secrets
41
+ npx @odla-ai/cli provision --email <existing-odla-account> --write-dev-vars --push-secrets
41
42
  ```
42
43
 
43
- Prints a short device code and a link. The human opens https://odla.ai/studio, signs
44
- in, and approves the code no secret passes through the chat. Provision then:
44
+ The email is an account identifier, never a password or session credential.
45
+ Prints a short device code and a link. That same account opens the link, signs
46
+ in, explicitly reviews the exact code, and approves it — loading the URL alone
47
+ does not claim access, and no secret passes through the chat. Provision then:
45
48
  creates the app, enables its services, issues or reuses the db key (and the
46
49
  o11y ingest token when o11y is enabled), pushes schema + rules, writes
47
50
  `.dev.vars`, and transfers configured Worker secrets through Wrangler stdin.
@@ -85,12 +88,12 @@ code. Browser code uses db subscriptions under explicit rules or pure
85
88
  Install the passive harness and scan before any production secret or deploy:
86
89
 
87
90
  Before installing the exact release, first verify
88
- `npm view @odla-ai/security@0.2.2 version`. An exact-version `E404` means the
91
+ `npm view @odla-ai/security@0.3.1 version`. An exact-version `E404` means the
89
92
  release is unavailable and blocks this preflight; it is not a clean scan and
90
93
  does not prove the package name is absent.
91
94
 
92
95
  ```
93
- npm i -D --save-exact @odla-ai/security@0.2.2
96
+ npm i -D --save-exact @odla-ai/security@0.3.1
94
97
  npx odla-security scan . --profile odla --out .odla/security/pre-ship --fail-on high --fail-on-candidates critical
95
98
  ```
96
99
 
@@ -1,8 +1,9 @@
1
1
  # odla SDK cheat-sheet
2
2
 
3
- Install only what the app needs. Every package ships an `llms.txt` in
4
- `node_modules/@odla-ai/<pkg>/` with the full, current API read it. Minimal
5
- real usage below.
3
+ Install only what the app needs. Prefer the installed package's README and
4
+ exported TypeScript declarations/JSDoc over training memory; resolve public
5
+ entry points through its `package.json` `exports`. Rendered references are also
6
+ available at `https://odla.ai/docs/packages/<pkg>`. Minimal real usage follows.
6
7
 
7
8
  ## @odla-ai/db — realtime graph database
8
9
 
@@ -99,12 +100,12 @@ Run the passive CLI in local/CI development; do not import it into the running
99
100
  Worker:
100
101
 
101
102
  Before installing the exact release, require
102
- `npm view @odla-ai/security@0.2.2 version` to succeed before installing it. An
103
+ `npm view @odla-ai/security@0.3.1 version` to succeed before installing it. An
103
104
  exact-version `E404` means the release is unavailable, not that the preflight
104
105
  passed, and does not prove the package name is absent.
105
106
 
106
107
  ```
107
- npm i -D --save-exact @odla-ai/security@0.2.2
108
+ npm i -D --save-exact @odla-ai/security@0.3.1
108
109
  npx odla-security scan . --profile odla --out .odla/security/pre-ship --fail-on high --fail-on-candidates critical
109
110
  ```
110
111
 
@@ -38,6 +38,9 @@ installed skill at `../odla/SKILL.md` instead.
38
38
  3. Never print, paste, or commit a secret. Never `cat` .dev.vars,
39
39
  .odla/credentials.local.json, or .odla/dev-token.json. Read
40
40
  references/secrets-map.md BEFORE any command that touches a credential.
41
+ A fresh device request requires the existing odla account email via
42
+ `--email` or `ODLA_USER_EMAIL`; email is a non-secret identifier. Never ask
43
+ for an odla password, Clerk token, or browser session.
41
44
  4. Never `git add -A` without reading `git status` first.
42
45
  5. Never widen a db rule to silence a 403 — default-deny is the design.
43
46
  Any rules change is a human checkpoint.
@@ -118,5 +121,6 @@ On any failure, read references/troubleshooting.md before improvising.
118
121
  This installed skill and its `references/` directory are the complete migration
119
122
  runbook; do not fetch a website or private source repository to reconstruct it.
120
123
  Read only the current phase file as directed above. After `npm install`, prefer
121
- `node_modules/@odla-ai/*/llms.txt` over training memory for package APIs the
122
- installed artifact is the version this project actually uses.
124
+ each installed package's README and exported TypeScript declarations/JSDoc over
125
+ training memory; resolve entry points through its `package.json` `exports`.
126
+ Those artifacts describe the version this project actually uses.
@@ -4,14 +4,15 @@ Goal: the app registered on the platform, a dev odla-db tenant with
4
4
  schema + deny-all rules, the db key in the dev worker, and first
5
5
  `/api/*` routes live in dev.
6
6
 
7
- Human obligation: sign in at https://odla.ai/studio and approve the handshake
8
- code when the provision run prints it (it also opens the approval page
9
- in the browser in interactive terminals).
7
+ Human obligation: provide the existing odla account email (not a password or
8
+ session credential), sign in at https://odla.ai/studio, explicitly review the
9
+ exact handshake code, and approve it. The provision run prints the code and
10
+ opens the review page in interactive terminals; loading it alone is inert.
10
11
 
11
12
  ## Steps
12
13
 
13
- 1. Require `npm view @odla-ai/cli@0.10.0 version` to succeed, then run
14
- `npm i -D --save-exact @odla-ai/cli@0.10.0` and `npm i @odla-ai/db`.
14
+ 1. Require `npm view @odla-ai/cli@0.10.2 version` to succeed, then run
15
+ `npm i -D --save-exact @odla-ai/cli@0.10.2` and `npm i @odla-ai/db`.
15
16
  2. `npx @odla-ai/cli init --app-id <id> --name "<Name>" --env dev --services db`
16
17
  Review `odla.config.mjs`. Keep `envs: ["dev"]` — prod is Phase 5. Set
17
18
  `links.dev` to the URL the Phase 1 `wrangler deploy` **actually printed** —
@@ -21,7 +22,7 @@ in the browser in interactive terminals).
21
22
  public-config show where the app runs. (`links.prod` is set the same way at
22
23
  Phase 5, from the prod deploy's printed URL.)
23
24
  3. STOP before touching schema: read "Porting relational code" in
24
- `node_modules/@odla-ai/db/llms.txt`. The traps are silent: entity ids
25
+ `node_modules/@odla-ai/db/README.md`. The traps are silent: entity ids
25
26
  are not attrs (mirror an id attr), there is no NULL (omit on write,
26
27
  re-project on read), lists need explicit `order`, uniques are
27
28
  single-attr (derive composite keys), ON CONFLICT maps to `mutationId`
@@ -32,7 +33,8 @@ in the browser in interactive terminals).
32
33
  directly. Loosening a rule is a human checkpoint.
33
34
  5. `npx @odla-ai/cli doctor` until clean.
34
35
  6. `npx @odla-ai/cli provision --dry-run` — show the plan to the human.
35
- 7. `npx @odla-ai/cli provision --write-dev-vars --push-secrets` — handshake,
36
+ 7. `npx @odla-ai/cli provision --email <existing-odla-account>
37
+ --write-dev-vars --push-secrets` — handshake,
36
38
  app registration, dev db key, schema + rules push; writes
37
39
  `.odla/credentials.local.json` (0600) and `.dev.vars`, then pipes configured
38
40
  Worker secrets to Wrangler over stdin. Both local files are gitignored by
@@ -47,8 +49,9 @@ in the browser in interactive terminals).
47
49
  10. Add `/api/*` routes before the assets fall-through, using
48
50
  `init({ appId: env.ODLA_TENANT, adminToken: env.ODLA_API_KEY,
49
51
  endpoint: env.ODLA_ENDPOINT })` from `@odla-ai/db`. Read the installed
50
- package's `node_modules/@odla-ai/db/llms.txt` for query, transaction, and
51
- error contracts.
52
+ package's README and exported TypeScript declarations/JSDoc for query,
53
+ transaction, and error contracts. The rendered reference is at
54
+ `https://odla.ai/docs/packages/db` when online.
52
55
  11. `wrangler dev` + curl each route; then `npm run deploy:app:dev` and
53
56
  curl the workers.dev URL.
54
57
 
@@ -9,8 +9,8 @@ server-issued Google consent page. They never paste an OAuth code or token.
9
9
 
10
10
  1. Inventory the old behavior. Distinguish a public appointment-page link from
11
11
  actual event create/reschedule/cancel APIs. Do not promise more than exists.
12
- 2. Require `npm view @odla-ai/calendar@0.1.0 version` to succeed, then install
13
- `npm i --save-exact @odla-ai/calendar@0.1.0` as a runtime dependency. An
12
+ 2. Require `npm view @odla-ai/calendar@0.1.1 version` to succeed, then install
13
+ `npm i --save-exact @odla-ai/calendar@0.1.1` as a runtime dependency. An
14
14
  exact-version `E404` blocks this phase; do not substitute a git checkout or
15
15
  another version. Add `"calendar"` beside
16
16
  `"db"` in services and configure:
@@ -24,9 +24,10 @@ own terminal so you never see the value.
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. Read
28
- `node_modules/@odla-ai/ai/llms.txt` and the public platform manual for the
29
- complete vault + public-config contract.
27
+ model are switchable in Studio with no redeploy. Read the installed
28
+ `node_modules/@odla-ai/ai/README.md` and exported TypeScript
29
+ declarations/JSDoc for the version-matched API; the rendered reference at
30
+ `https://odla.ai/docs/packages/ai` covers the public platform composition.
30
31
  4. Add one `/api/*` route that round-trips the model; deploy dev.
31
32
 
32
33
  ## Verification checklist
@@ -24,10 +24,10 @@ instance, never a second Clerk app per env; final go/no-go at each step.
24
24
  `secrets push --env prod --yes` only to retry the transfer (see
25
25
  references/secrets-map.md).
26
26
  3. Build, then run the passive pre-cutover security gate:
27
- first require `npm view @odla-ai/security@0.2.2 version` to succeed. An
27
+ first require `npm view @odla-ai/security@0.3.1 version` to succeed. An
28
28
  exact-version `E404` means the release is unavailable and blocks cutover;
29
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.2.2` followed by
30
+ `npm i -D --save-exact @odla-ai/security@0.3.1` followed by
31
31
  `npx odla-security scan . --profile odla --out .odla/security/pre-cutover --fail-on high --fail-on-candidates critical`.
32
32
  Review `REPORT.md`; a candidate is a lead, not confirmation, and a baseline
33
33
  requires a concrete reason, owner, and expiry.
@@ -8,8 +8,9 @@
8
8
  | Clerk webhook secret (`whsec_…`) | tenant vault (`clerk_webhook_secret`) | only for auth mode "full"; piped with `secrets set clerk_webhook_secret --env <env> --stdin`, or entered in Studio; never wrangler, never chat |
9
9
  | Clerk secret key (`sk_test_`/`sk_live_`) | not needed for this journey | if a later feature needs user resolution/invites, pipe it with `secrets set-clerk-key --env <env>` (reserved `$clerk_secret`, write-only); never chat |
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_USER_EMAIL` / `--email` | process environment or one command invocation | non-secret identifier for the existing signed-in odla account allowed to review a fresh request; never substitute a password or session token |
11
12
  | `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
- | `odla_dev_…` (developer token) | `.odla/dev-token.json` (0600) | ~24h lifetime, provision-time only; never deployed |
13
+ | `odla_dev_…` (developer token) | `.odla/dev-token.json` (0600) | tracked/revocable, ~24h lifetime, provision-time only; never deployed; deleting this cache does not revoke a copied token |
13
14
  | scoped `odla_dev_…` (admin-approved platform capability) | `.odla/admin-token.local.json` (0600) | separate policy/credential/usage/self-audit scope, ~15m lifetime, denied on owner routes, never deployed |
14
15
  | `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 |
15
16
  | `ODLA_ENDPOINT` / `ODLA_TENANT` / `ODLA_PLATFORM` / `ODLA_APP_ID` / `ODLA_ENV` | wrangler `vars` | not secrets; keep them set in every env block |
@@ -30,7 +30,9 @@ prints what it verified against.
30
30
  Cause: the `odla_dev_…` token expired (~24h) or the handshake was never
31
31
  approved.
32
32
  Fix: re-run `npx @odla-ai/cli provision` — it starts a fresh handshake; the
33
- human approves the new code at the printed URL. Use `--no-open` in
33
+ matching existing account must be supplied with `--email` or
34
+ `ODLA_USER_EMAIL`, then signs in, reviews, and approves the exact code at the
35
+ printed URL. Never ask for a password or session token. Use `--no-open` in
34
36
  non-interactive shells if the browser launch misbehaves.
35
37
 
36
38
  ## `smoke` fails: missing credentials
@@ -78,6 +80,6 @@ the printed `secrets push --env ...` retry and do not rotate again.
78
80
  ## Something not covered here
79
81
 
80
82
  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.
83
+ and troubleshooting references; then the relevant installed package README and
84
+ exported TypeScript declarations/JSDoc. Do not improvise around a safety rule
85
+ to unblock yourself — surface the blocker to the human instead.
@@ -29,9 +29,13 @@ GET https://odla.ai/o11y/<appId>/<endpoint>?env=prod
29
29
  Authorization: Bearer <developer-token>
30
30
  ```
31
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
32
+ Get `<developer-token>` from `@odla-ai/cli` or the device handshake: start with
33
+ `POST https://odla.ai/handshake` and
34
+ `{"email":"<existing-odla-account>","label":"o11y debugger"}`, show the returned
35
+ verification URL, then poll `POST /handshake/poll`. Email is a non-secret
36
+ identifier; never ask for a password or session token. The matching account
37
+ must sign in and explicitly review and approve the exact code. `env` is `prod`
38
+ (default) or `dev`. If a read returns `{"error":"ae_not_configured"}` (501), the app's metrics
35
39
  reads aren't turned on yet — errors/traces still work; say so and fall back to them.
36
40
 
37
41
  ## Endpoints