@odla-ai/cli 0.5.0 → 0.7.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/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # @odla-ai/cli — LLM context
2
2
 
3
- > Agent-operable CLI for provisioning odla apps, services, credentials, Worker secrets, and local runtime files.
3
+ > Agent-operable CLI for odla provisioning, scoped System AI administration, hosted security runs, Worker secrets, and smoke checks.
4
4
 
5
5
  > ⚠️ **Early access — pre-1.0.** Agents work from bounded runbooks; humans
6
6
  > approve credentials, production changes, releases, and merges. APIs and exact
@@ -9,9 +9,11 @@
9
9
 
10
10
  Project-neutral provisioning CLI for odla apps. It creates and validates an
11
11
  `odla.config.mjs`, then uses that config to register an app, enable services,
12
- push odla-db schema/rules, configure platform AI, configure Clerk auth, record
12
+ push odla-db schema/rules, configure per-app BYOK AI, configure Clerk auth, record
13
13
  deployment links, provision o11y ingest credentials, and transfer local or
14
- deployed Worker secrets without printing them.
14
+ deployed Worker secrets without printing them. It also gives platform admins a
15
+ scoped System AI control surface and gives app owners a provider-key-free
16
+ hosted security command.
15
17
 
16
18
  It does not know about any specific app. App identity, environments, services,
17
19
  schema, rules, auth, AI provider, and links all come from config.
@@ -29,8 +31,8 @@ For a project you keep working in, install it as a dev dependency so the
29
31
  shorter `npx odla-ai` form works and the version is pinned by your lockfile:
30
32
 
31
33
  ```bash
32
- npm view @odla-ai/cli@0.5.0 version
33
- npm i -D --save-exact @odla-ai/cli@0.5.0
34
+ npm view @odla-ai/cli@0.7.0 version
35
+ npm i -D --save-exact @odla-ai/cli@0.7.0
34
36
  ```
35
37
 
36
38
  ## Prerequisites
@@ -59,6 +61,14 @@ npx odla-ai provision --dry-run
59
61
  npx odla-ai provision --write-dev-vars --push-secrets
60
62
  npx odla-ai smoke --env dev
61
63
  npx odla-ai secrets push --env dev
64
+ npx odla-ai security run . --env dev --ack-redacted-source
65
+ npx odla-ai admin ai show
66
+ npx odla-ai admin ai models
67
+ npx odla-ai admin ai set security --discovery-provider anthropic --discovery-model claude-opus-4-8 --validation-provider openai --validation-model gpt-5.5 --enabled
68
+ npx odla-ai admin ai credentials
69
+ npx odla-ai admin ai credential set anthropic --from-env ANTHROPIC_API_KEY
70
+ npx odla-ai admin ai usage --app-id my-app --env prod --limit 50
71
+ npx odla-ai admin ai audit --limit 25
62
72
  npx odla-ai skill install
63
73
  npx odla-ai version
64
74
  ```
@@ -119,17 +129,56 @@ when provisioning has not written `.odla/credentials.local.json`.
119
129
 
120
130
  The bundled build/migration skills add a passive pre-ship gate with
121
131
  `@odla-ai/security`: after the exact-version availability check, run
122
- `npm i -D --save-exact @odla-ai/security@0.1.0`, then
132
+ `npm i -D --save-exact @odla-ai/security@0.2.0`, then
123
133
  `npx odla-security scan . --profile odla --out .odla/security/pre-ship --fail-on high --fail-on-candidates critical`.
124
- This is a separate binary, not a hidden `odla-ai` subcommand; it makes no model
125
- calls and does not execute target code.
134
+ The passive scan remains a separate binary: it makes no model calls and does
135
+ not execute target code. After explicit redacted-source approval,
136
+ `odla-ai security run . --env dev --ack-redacted-source` adds hosted discovery
137
+ and independent validation. The CLI obtains/reuses app-owner auth and the
138
+ platform supplies bounded role grants; it never requests provider keys.
139
+ The CLI schedules within those grants: recon consumes one discovery call,
140
+ first-pass hunts are capped before retries, and validation handles the
141
+ highest-risk candidates first. Used/skipped role calls appear in the summary
142
+ and report. Budget-limited coverage is explicitly incomplete and still fails
143
+ the default gate unless `--allow-incomplete` is supplied after review.
144
+ All hosted-security network calls target the configured odla platform origin.
145
+ The CLI transmits typed redacted security operations only and never contacts a
146
+ model-provider host; odla.ai owns the prompts/schemas, route, credential,
147
+ provider call, attribution, and receipt. Cached/environment tokens are bound to
148
+ their canonical platform audience and are rejected before disclosure on a
149
+ different origin. For a non-default platform, set the matching
150
+ `ODLA_DEV_TOKEN_AUDIENCE` with `ODLA_DEV_TOKEN`.
151
+ Early-access run ceilings are rolling; a `429` includes the platform's safe
152
+ retry hint, which the CLI surfaces without echoing arbitrary response text.
126
153
  Before installing the exact release, require
127
- `npm view @odla-ai/security@0.1.0 version` to succeed before installation. An
154
+ `npm view @odla-ai/security@0.2.0 version` to succeed before installation. An
128
155
  exact-version `E404` means the release is unavailable, not that the security
129
156
  preflight passed, and does not prove the package name is absent. odla's own
130
157
  engineering environment uses an equivalent internal gate; customer projects
131
158
  should use the published `odla-security` command above.
132
159
 
160
+ `admin ai show|models|set|credentials|credential set|usage|audit` manages platform-funded System
161
+ AI (`o11y.triage`, `security.discovery`, `security.validation`). It uses a
162
+ separate, mode-`0600` `.odla/admin-token.local.json` cache. Studio displays the
163
+ exact scope, only an admin can approve it, and it expires after ~15 minutes;
164
+ policy, credential, and usage capabilities are separate and cannot act as the
165
+ approver on ordinary app/db/o11y routes. `admin ai models` reads the server
166
+ catalog. `admin ai set security` updates discovery and independent validation
167
+ together with expected revisions; a concurrent edit returns 409 and reloads
168
+ instead of being overwritten. `admin ai usage` requests its own read-only
169
+ capability and lists metadata-only events and status aggregates; filter by
170
+ `--app-id`, `--env`, `--run-id`, and `--limit`, or emit `--json`. Prompts,
171
+ repository source, model output, reports, and provider credentials are never in
172
+ that response.
173
+ `admin ai audit` uses its own read capability for immutable, metadata-only
174
+ policy and credential change events with actor attribution; credential values
175
+ never enter that trail. Credential writes accept only
176
+ `--from-env <NAME>` or `--stdin` and never place the value in argv, output, or
177
+ the cache. System AI and each app's BYOK AI are separate vault/funding paths.
178
+ Admin bounds can only narrow hard ceilings of 64 calls per role/run and, for
179
+ each call, 512 KiB input and 32,768 output tokens. A non-default platform environment token
180
+ must declare the matching `ODLA_ADMIN_TOKEN_AUDIENCE`.
181
+
133
182
  `secrets push --env <env>` is the narrower recovery/retry command. It moves the
134
183
  configured env's odla-db key and/or o11y ingest token from
135
184
  `.odla/credentials.local.json` into the deployed Worker by piping each value
@@ -151,7 +200,8 @@ agent owns application semantics: installing `@odla-ai/o11y`, wrapping the
151
200
  Worker with `withObservability`, and choosing useful spans, metrics, errors, and
152
201
  LLM-usage records. The human owns the device approval, production consent, and
153
202
  explicit destructive rotation. Studio is where people view telemetry and
154
- perform manual recovery; its token control is not the normal setup path.
203
+ perform manual recovery, configure System AI, and inspect app/run-attributed
204
+ platform usage; its o11y token control is not the normal setup path.
155
205
  Run `npx odla-ai capabilities` for the human-readable contract or add `--json`
156
206
  when an agent or tool needs to branch on it without scraping prose.
157
207
 
@@ -230,9 +280,11 @@ If schema is present and rules are omitted, `defaultRules: "deny"` generates
230
280
  deny-all rules for every schema entity. That is the safe default for Workers
231
281
  that mediate reads and writes with an app key.
232
282
 
233
- ## API reference (generated from dist/index.d.ts, v0.5.0)
283
+ ## API reference (generated from dist/index.d.ts, v0.7.0)
234
284
 
235
285
  ```ts
286
+ import { SecurityReport, PlatformSecurityRun } from '@odla-ai/security';
287
+
236
288
  /**
237
289
  * Parse CLI arguments and dispatch to the matching command — the entry point
238
290
  * `bin.ts` invokes. `argv` defaults to `process.argv.slice(2)`; the first
@@ -243,7 +295,11 @@ that mediate reads and writes with an app key.
243
295
  * Recognized commands: `version`/`-v`/`--version` and `help`/`-h`/`--help` print
244
296
  * and return; `init` scaffolds a project (requires `--app-id` and `--name`);
245
297
  * `doctor` validates config offline; `capabilities` prints the responsibility
246
- * boundary; `provision` runs the full provision (including optional secret
298
+ * boundary; `admin ai` reads/updates purpose-specific platform AI policies,
299
+ * transfers write-only credentials, and reads metadata-only attributed usage
300
+ * through separate short-lived exact-scope device grants;
301
+ * `security run` performs an explicitly acknowledged, app-attributed hosted
302
+ * reasoning pass; `provision` runs the full provision (including optional secret
247
303
  * rotation, local vars, and deployed secret push); `smoke` checks a live env;
248
304
  * `setup` and `skill install` install the bundled offline runbooks for Claude
249
305
  * Code, Codex, Cursor, Copilot, Gemini, and `AGENTS.md`-aware agents; and
@@ -256,13 +312,77 @@ that mediate reads and writes with an app key.
256
312
  */
257
313
  declare function runCli(argv?: string[]): Promise<void>;
258
314
 
315
+ /** One exact platform scope obtainable through the admin device flow. */
316
+ type ScopedPlatformScope = "platform:ai:policy:read" | "platform:ai:policy:write" | "platform:ai:credential:read" | "platform:ai:credential:write" | "platform:ai:usage:read" | "platform:ai:audit:read" | "platform:security:self";
317
+ /** Inputs for obtaining one short-lived, exact-scope platform device grant. */
318
+ interface ScopedPlatformTokenOptions {
319
+ platform: string;
320
+ scope: ScopedPlatformScope;
321
+ open?: boolean;
322
+ fetch?: typeof fetch;
323
+ stdout?: Pick<typeof console, "log">;
324
+ openApprovalUrl?: (url: string) => Promise<void>;
325
+ tokenFile?: string;
326
+ }
327
+ /** Obtain/cache one exact platform scope without granting ambient admin. */
328
+ declare function getScopedPlatformToken(options: ScopedPlatformTokenOptions): Promise<string>;
329
+
330
+ /** Hosted platform purposes whose provider, model, and budgets an admin may route. */
331
+ declare const SYSTEM_AI_PURPOSES: readonly ["o11y.triage", "security.discovery", "security.validation"];
332
+ /** One catalog-validated, platform-funded System AI purpose. */
333
+ type SystemAiPurpose = (typeof SYSTEM_AI_PURPOSES)[number];
334
+
335
+ /** Inputs for one System AI policy/catalog read, policy update,
336
+ * credential-status read, write-only credential transfer, or metadata-only
337
+ * usage or admin-audit read. Provider values may come only from a named environment variable
338
+ * or stdin. */
339
+ interface AdminAiOptions {
340
+ action: "show" | "models" | "set" | "credentials" | "credential-set" | "usage" | "audit";
341
+ purpose?: string;
342
+ provider?: string;
343
+ model?: string;
344
+ enabled?: boolean;
345
+ maxInputBytes?: number;
346
+ maxOutputTokens?: number;
347
+ maxCallsPerRun?: number;
348
+ platform?: string;
349
+ token?: string;
350
+ json?: boolean;
351
+ open?: boolean;
352
+ fetch?: typeof fetch;
353
+ stdout?: Pick<typeof console, "log">;
354
+ openApprovalUrl?: (url: string) => Promise<void>;
355
+ credentialProvider?: string;
356
+ fromEnv?: string;
357
+ stdin?: boolean;
358
+ readStdin?: () => Promise<string>;
359
+ discoveryProvider?: string;
360
+ discoveryModel?: string;
361
+ validationProvider?: string;
362
+ validationModel?: string;
363
+ /** Optional metadata-only usage filters. */
364
+ appId?: string;
365
+ env?: string;
366
+ runId?: string;
367
+ limit?: number;
368
+ /** Separate short-lived admin-token cache; never reuses the app developer-token file. */
369
+ tokenFile?: string;
370
+ }
371
+ /** Read or update platform-funded AI routing and inspect attributed usage.
372
+ * Authentication is a short-lived,
373
+ * explicitly scoped device grant; ordinary app developer tokens never become
374
+ * platform admins. Credential writes accept values only from a named env var
375
+ * or stdin, transfer them once, and never place them in argv, output, or the
376
+ * scoped-token cache. */
377
+ declare function adminAi(options: AdminAiOptions): Promise<void>;
378
+
259
379
  /** Stable, machine-readable division of work between the CLI, coding agent,
260
380
  * human operator, and Studio. Printed by `odla-ai capabilities --json`. */
261
381
  declare const CAPABILITIES: {
262
- 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", "push db schema/rules and configure platform AI, auth, and deployment links", "validate config offline and smoke-test a provisioned db environment"];
382
+ 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", "push db schema/rules and configure platform AI, auth, and deployment links", "validate config offline and smoke-test a provisioned db environment", "run app-attributed hosted security discovery and independent validation without 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"];
263
383
  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"];
264
- readonly human: readonly ["approve the odla device code and one-off third-party logins", "consent to production changes with --yes", "request destructive credential rotation explicitly", "review application semantics, security findings, releases, and merges"];
265
- readonly studio: readonly ["view telemetry and environment state", "perform manual credential recovery when the CLI's local shown-once copy is unavailable"];
384
+ readonly human: readonly ["approve the odla device code and one-off third-party logins", "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"];
385
+ readonly studio: readonly ["view telemetry and environment state", "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"];
266
386
  };
267
387
  type Output = Pick<typeof console, "log">;
268
388
  /** Print the stable responsibility boundary for humans or agent tooling. */
@@ -535,6 +655,61 @@ interface SecretsPushOptions {
535
655
  */
536
656
  declare function secretsPush(options: SecretsPushOptions): Promise<void>;
537
657
 
658
+ /** Built-in security coverage profile selected for a hosted reasoning run. */
659
+ type HostedSecurityProfile = "odla" | "cloudflare-app" | "generic";
660
+ /** Exact attribution and authorization need supplied to a lazy token callback. */
661
+ interface HostedSecurityTokenRequest {
662
+ platform: string;
663
+ appId: string;
664
+ env: string;
665
+ selfAudit: boolean;
666
+ /** Self-audit asks the caller for an explicitly scoped platform credential. */
667
+ /** Ordinary app runs use owner authority and therefore request no platform scope. */
668
+ scope: "platform:security:self" | null;
669
+ }
670
+ /** Local snapshot/orchestration controls for an app-attributed hosted security
671
+ * run. The platform supplies model routes and provider credentials. */
672
+ interface RunHostedSecurityOptions {
673
+ /** Project config; loaded for customer-app runs and ignored for self-audit. */
674
+ configPath?: string;
675
+ /** Scan odla itself under the protected odla-ai/prod identity. */
676
+ selfAudit?: boolean;
677
+ /** Repository directory to snapshot. Defaults to the config root or cwd for self-audit. */
678
+ target?: string;
679
+ /** Private artifact directory. Defaults to `<target>/.odla/security/hosted`. */
680
+ out?: string;
681
+ /** Customer environment. Must be declared in config. Self-audit always uses prod. */
682
+ env?: string;
683
+ profile?: HostedSecurityProfile;
684
+ maxHuntTasks?: number;
685
+ /** Exact acknowledgement required before any source capture or network call. */
686
+ sourceDisclosureAck?: "redacted";
687
+ /** Optional client correlation id; the platform returns the authoritative run id. */
688
+ runId?: string;
689
+ /** Platform override. Customer runs otherwise use config.platformUrl. */
690
+ platform?: string;
691
+ /** Injected app credential; for self-audit this must be explicitly scoped by the caller. */
692
+ token?: string;
693
+ /** Lazy token acquisition. Receives the exact app/env and required scope. */
694
+ getToken?: (request: HostedSecurityTokenRequest) => string | Promise<string>;
695
+ fetch?: typeof fetch;
696
+ signal?: AbortSignal;
697
+ stdout?: Pick<typeof console, "log" | "error">;
698
+ }
699
+ /** Completed local report, public platform run metadata, and private artifact path. */
700
+ interface HostedSecurityResult {
701
+ report: SecurityReport;
702
+ run: Readonly<PlatformSecurityRun>;
703
+ output: string;
704
+ }
705
+ /**
706
+ * Run the hosted, redacted-source security harness for an odla app or odla's
707
+ * protected self-audit identity. Provider/model selection and provider secrets
708
+ * remain platform-owned; this function accepts only an app/scoped bearer and
709
+ * the opaque role grants remain inside @odla-ai/security's reasoner closures.
710
+ */
711
+ declare function runHostedSecurity(options: RunHostedSecurityOptions): Promise<HostedSecurityResult>;
712
+
538
713
  /** Agent harnesses with a first-class local adapter. */
539
714
  declare const AGENT_HARNESSES: readonly ["claude", "codex", "cursor", "copilot", "gemini", "agents"];
540
715
  /** A supported coding-agent harness. `agents` is the portable `AGENTS.md` adapter. */
@@ -614,5 +789,5 @@ declare function installSkill(options?: SkillInstallOptions): SkillInstallResult
614
789
  */
615
790
  declare function smoke(options: SmokeOptions): Promise<void>;
616
791
 
617
- export { AGENT_HARNESSES, type AgentHarness, type AgentHarnessSelector, CAPABILITIES, type HarnessInstallResult, type LoadedProjectConfig, type LocalCredentials, type OdlaProjectConfig, type ProvisionOptions, type ProvisionPlan, type SecretsPushOptions, type SkillInstallOptions, type SkillInstallResult, type SmokeOptions, doctor, initProject, installSkill, printCapabilities, provision, redactSecrets, runCli, secretsPush, smoke };
792
+ export { AGENT_HARNESSES, type AdminAiOptions, type AgentHarness, type AgentHarnessSelector, CAPABILITIES, type HarnessInstallResult, type HostedSecurityProfile, type HostedSecurityResult, type HostedSecurityTokenRequest, type LoadedProjectConfig, type LocalCredentials, type OdlaProjectConfig, type ProvisionOptions, type ProvisionPlan, type RunHostedSecurityOptions, SYSTEM_AI_PURPOSES, type ScopedPlatformTokenOptions, type SecretsPushOptions, type SkillInstallOptions, type SkillInstallResult, type SmokeOptions, type SystemAiPurpose, adminAi, doctor, getScopedPlatformToken, initProject, installSkill, printCapabilities, provision, redactSecrets, runCli, runHostedSecurity, secretsPush, smoke };
618
793
  ```
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@odla-ai/cli",
3
- "version": "0.5.0",
4
- "description": "Agent-operable CLI for provisioning odla apps, services, credentials, Worker secrets, and local runtime files.",
3
+ "version": "0.7.0",
4
+ "description": "Agent-operable CLI for odla provisioning, scoped System AI administration, hosted security runs, Worker secrets, and smoke checks.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://odla.ai/docs/packages/cli",
7
7
  "repository": {
@@ -59,9 +59,10 @@
59
59
  "prepublishOnly": "npm run build && npm run gen:llms"
60
60
  },
61
61
  "dependencies": {
62
- "@odla-ai/ai": "^0.3.0",
62
+ "@odla-ai/ai": "^0.3.2",
63
63
  "@odla-ai/apps": "^0.7.1",
64
- "@odla-ai/db": "^0.6.0"
64
+ "@odla-ai/db": "^0.6.2",
65
+ "@odla-ai/security": "^0.2.0"
65
66
  },
66
67
  "devDependencies": {
67
68
  "@types/node": "^22.10.0",
@@ -69,8 +69,12 @@ guessing which platform/credential steps need manual work. Then:
69
69
  ingest token when enabled), pushes schema + rules, writes `.dev.vars`, and
70
70
  transfers Worker secrets through Wrangler stdin.
71
71
  4. **run** — `npx wrangler dev` (auto-loads `.dev.vars`); verify locally.
72
- 5. **security** — run the passive `@odla-ai/security` odla profile;
73
- inspect every lead and keep critical candidate gating enabled.
72
+ 5. **security** — run the passive `@odla-ai/security` odla profile; inspect
73
+ every lead and keep critical candidate gating enabled. If the human approves
74
+ redacted source disclosure, follow with
75
+ `npx @odla-ai/cli security run . --env dev --ack-redacted-source` for
76
+ app-attributed discovery + independent validation. Never request provider
77
+ keys; the platform selects the routes and returns bounded role grants.
74
78
  6. **ship** ⏸ — after adding `prod`, run `npx @odla-ai/cli provision --dry-run`,
75
79
  show the human, then `npx @odla-ai/cli provision --yes --push-secrets` and
76
80
  `npx wrangler deploy`.
@@ -66,12 +66,12 @@ re-provision to push it, and retry.
66
66
  Install the passive harness and scan before any production secret or deploy:
67
67
 
68
68
  Before installing the exact release, first verify
69
- `npm view @odla-ai/security@0.1.0 version`. An exact-version `E404` means the
69
+ `npm view @odla-ai/security@0.2.0 version`. An exact-version `E404` means the
70
70
  release is unavailable and blocks this preflight; it is not a clean scan and
71
71
  does not prove the package name is absent.
72
72
 
73
73
  ```
74
- npm i -D --save-exact @odla-ai/security@0.1.0
74
+ npm i -D --save-exact @odla-ai/security@0.2.0
75
75
  npx odla-security scan . --profile odla --out .odla/security/pre-ship --fail-on high --fail-on-candidates critical
76
76
  ```
77
77
 
@@ -80,6 +80,19 @@ not execute target code. A `candidate` is a review lead, not a confirmed
80
80
  vulnerability; do not suppress one merely to clear the gate. Baseline entries
81
81
  need a fingerprint, concrete reason, owner, and expiry.
82
82
 
83
+ Optional hosted follow-up (human must explicitly approve redacted tracked-source
84
+ disclosure under the configured providers' retention/residency terms):
85
+
86
+ ```
87
+ npx @odla-ai/cli security run . --env dev --ack-redacted-source
88
+ ```
89
+
90
+ Do not ask for Anthropic/OpenAI/Google keys. The CLI obtains app-owner auth;
91
+ the platform fixes separate discovery/validation grants to the admin-configured
92
+ routes, attributes usage to this app/env/run, and retains no source or prompts
93
+ in its accounting ledger. If a rolling early-access ceiling returns `429`,
94
+ surface the CLI's safe retry hint and do not loop or manufacture a provider key.
95
+
83
96
  ## 6. Ship ⏸ human checkpoint
84
97
 
85
98
  Add `"prod"` to `envs`, provision again (prod tenant = the bare `appId`), then:
@@ -70,18 +70,21 @@ Run the passive CLI in local/CI development; do not import it into the running
70
70
  Worker:
71
71
 
72
72
  Before installing the exact release, require
73
- `npm view @odla-ai/security@0.1.0 version` to succeed before installing it. An
73
+ `npm view @odla-ai/security@0.2.0 version` to succeed before installing it. An
74
74
  exact-version `E404` means the release is unavailable, not that the preflight
75
75
  passed, and does not prove the package name is absent.
76
76
 
77
77
  ```
78
- npm i -D --save-exact @odla-ai/security@0.1.0
78
+ npm i -D --save-exact @odla-ai/security@0.2.0
79
79
  npx odla-security scan . --profile odla --out .odla/security/pre-ship --fail-on high --fail-on-candidates critical
80
80
  ```
81
81
 
82
- Deterministic rules emit leads. Autonomous recon/hunt/validation is an optional
83
- library flow with separate models, persistent state, and an explicitly injected
84
- isolated executor; it never falls back to the host shell.
82
+ Deterministic rules emit leads. After explicit redacted-source approval, run
83
+ `npx @odla-ai/cli security run . --env dev --ack-redacted-source` for hosted,
84
+ app-attributed discovery and independent validation. It obtains owner auth and
85
+ never asks for provider keys. The lower-level library flow remains available
86
+ for custom orchestrators; active reproduction still requires an explicitly
87
+ injected isolated executor and never falls back to the host shell.
85
88
 
86
89
  ## Others
87
90
 
@@ -10,8 +10,8 @@ in the browser in interactive terminals).
10
10
 
11
11
  ## Steps
12
12
 
13
- 1. Require `npm view @odla-ai/cli@0.5.0 version` to succeed, then run
14
- `npm i -D --save-exact @odla-ai/cli@0.5.0` and `npm i @odla-ai/db`.
13
+ 1. Require `npm view @odla-ai/cli@0.7.0 version` to succeed, then run
14
+ `npm i -D --save-exact @odla-ai/cli@0.7.0` and `npm i @odla-ai/db`.
15
15
  2. `npx @odla-ai/cli init --app-id <id> --name "<Name>" --env dev --services db`
16
16
  Review `odla.config.mjs`. Keep `envs: ["dev"]` — prod is Phase 5. Set
17
17
  `links.dev` to the URL the Phase 1 `wrangler deploy` **actually printed** —
@@ -24,13 +24,17 @@ 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.1.0 version` to succeed. An
27
+ first require `npm view @odla-ai/security@0.2.0 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.1.0` followed by
30
+ `npm i -D --save-exact @odla-ai/security@0.2.0` 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.
34
+ If the human explicitly approves redacted tracked-source disclosure, follow
35
+ with `npx @odla-ai/cli security run . --env prod --ack-redacted-source`.
36
+ The platform owns provider credentials and attributes the bounded,
37
+ independent-model run to this app; never request provider keys locally.
34
38
  4. `npx wrangler deploy` (first prod deploy). Verify
35
39
  `/api/health` and the parity paths on the prod workers.dev URL.
36
40
  5. `npx @odla-ai/cli smoke --env prod`.
@@ -10,10 +10,15 @@
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
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
+ | 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 |
13
14
  | `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
15
  | `ODLA_ENDPOINT` / `ODLA_TENANT` / `ODLA_PLATFORM` / `ODLA_APP_ID` / `ODLA_ENV` | wrangler `vars` | not secrets; keep them set in every env block |
15
16
  | `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 |
16
17
 
18
+ System AI provider credentials are platform-owned and never enter a customer
19
+ migration. `odla-ai security run` receives only app/run-bound role grants; do
20
+ not ask the human for Anthropic/OpenAI/Google keys for hosted security.
21
+
17
22
  ## Moving the db key (+ o11y token) into the Worker (never through the transcript)
18
23
 
19
24
  Normal provisioning owns the complete sequence — issuance, mode-0600 local