@odla-ai/cli 0.13.1 → 0.14.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/README.md +20 -0
- package/dist/bin.cjs +3478 -703
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-I7XDJZB6.js → chunk-AN6KZMR5.js} +3563 -784
- package/dist/chunk-AN6KZMR5.js.map +1 -0
- package/dist/index.cjs +3486 -703
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +100 -22
- package/dist/index.d.ts +100 -22
- package/dist/index.js +9 -1
- package/package.json +3 -2
- package/skills/odla/SKILL.md +4 -0
- package/skills/odla/references/co-owners.md +61 -0
- package/dist/chunk-I7XDJZB6.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -2,6 +2,99 @@ import { SecurityReport, PlatformSecurityRun } from '@odla-ai/security';
|
|
|
2
2
|
import { HostedSecurityJob, GitHubConnectionStatus, GitHubSecuritySource, HostedSecurityIntentResponse, HostedSecurityPlan, HostedSecurityReport, HostedSecurityJobStatus } from '@odla-ai/security/hosted';
|
|
3
3
|
export { GitHubConnectionAttempt, GitHubConnectionStatus, GitHubSecuritySource, HostedSecurityCounts, HostedSecurityCoverage, HostedSecurityIntent, HostedSecurityIntentResponse, HostedSecurityJob, HostedSecurityJobStatus, HostedSecurityPlan, HostedSecurityPlanRoute, HostedSecurityReport, HostedSecurityReportFinding, HostedSecurityRoute } from '@odla-ai/security/hosted';
|
|
4
4
|
|
|
5
|
+
/** One exact platform scope obtainable through the admin device flow. */
|
|
6
|
+
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:code:host:connect" | "platform:security:self";
|
|
7
|
+
/** Inputs for obtaining one short-lived, exact-scope platform device grant. */
|
|
8
|
+
interface ScopedPlatformTokenOptions {
|
|
9
|
+
platform: string;
|
|
10
|
+
scope: ScopedPlatformScope;
|
|
11
|
+
/** Existing odla account email used only when a fresh handshake is required. */
|
|
12
|
+
email?: string;
|
|
13
|
+
open?: boolean;
|
|
14
|
+
fetch?: typeof fetch;
|
|
15
|
+
stdout?: Pick<typeof console, "log">;
|
|
16
|
+
openApprovalUrl?: (url: string) => Promise<void>;
|
|
17
|
+
tokenFile?: string;
|
|
18
|
+
/** Keep the shown-once grant only in memory. */
|
|
19
|
+
cache?: boolean;
|
|
20
|
+
/** Human-visible purpose recorded on the exact handshake. */
|
|
21
|
+
label?: string;
|
|
22
|
+
}
|
|
23
|
+
/** Obtain/cache one exact platform scope without granting ambient admin. */
|
|
24
|
+
declare function getScopedPlatformToken(options: ScopedPlatformTokenOptions): Promise<string>;
|
|
25
|
+
|
|
26
|
+
/** Immutable, release-owned Pi adapter. No registry credential enters it. */
|
|
27
|
+
declare const CODE_PI_IMAGE = "ghcr.io/cory/odla-pi-agent@sha256:713db58428bc05cb486167c5747de8fd826669c9b283ff78e0139ac194c3d058";
|
|
28
|
+
/** Supported local isolation engines for an odla Code host runtime. */
|
|
29
|
+
type CodeContainerEngine = "container" | "podman" | "docker";
|
|
30
|
+
/** Immutable CaMeL-registered build recipe available to an agent container. */
|
|
31
|
+
interface CodeBuildRule {
|
|
32
|
+
id: string;
|
|
33
|
+
image: string;
|
|
34
|
+
command: readonly string[];
|
|
35
|
+
timeoutMs: number;
|
|
36
|
+
maxOutputBytes: number;
|
|
37
|
+
cpus?: number;
|
|
38
|
+
memory?: string;
|
|
39
|
+
pids?: number;
|
|
40
|
+
tmpfsBytes?: number;
|
|
41
|
+
}
|
|
42
|
+
/** Bounded host facts reported on each outbound Code control-plane heartbeat. */
|
|
43
|
+
interface CodeHostCapabilities {
|
|
44
|
+
protocolVersion: 1;
|
|
45
|
+
platform: "macos" | "linux";
|
|
46
|
+
arch: string;
|
|
47
|
+
engines: CodeContainerEngine[];
|
|
48
|
+
cpuCount: number;
|
|
49
|
+
memoryBytes: number;
|
|
50
|
+
}
|
|
51
|
+
/** Initial CaMeL-registered clean-build rule. App-specific recipes can replace
|
|
52
|
+
* this only after their own owner-visible registration flow exists. */
|
|
53
|
+
declare const CODE_BUILD_RECIPES: readonly CodeBuildRule[];
|
|
54
|
+
type Output$1 = Pick<typeof console, "log" | "error">;
|
|
55
|
+
/** Inputs for enrolling the current checkout and running its foreground Pi host. */
|
|
56
|
+
interface CodeConnectOptions {
|
|
57
|
+
configPath: string;
|
|
58
|
+
/** Repository root. Defaults to the current directory. */
|
|
59
|
+
cwd?: string;
|
|
60
|
+
env?: string;
|
|
61
|
+
email?: string;
|
|
62
|
+
open?: boolean;
|
|
63
|
+
name?: string;
|
|
64
|
+
slots?: number;
|
|
65
|
+
engine?: CodeContainerEngine | "auto";
|
|
66
|
+
heartbeatMs?: number;
|
|
67
|
+
/** Enroll and prove one heartbeat without waiting for sessions. */
|
|
68
|
+
once?: boolean;
|
|
69
|
+
fetch?: typeof fetch;
|
|
70
|
+
stdout?: Output$1;
|
|
71
|
+
openApprovalUrl?: (url: string) => Promise<void>;
|
|
72
|
+
signal?: AbortSignal;
|
|
73
|
+
/** Test/embedding boundaries. */
|
|
74
|
+
getToken?: typeof getScopedPlatformToken;
|
|
75
|
+
selectEngine?: (requested: CodeContainerEngine | "auto") => Promise<CodeContainerEngine>;
|
|
76
|
+
runRuntime?: (input: CodeRuntimeInput) => Promise<void>;
|
|
77
|
+
readGitOrigin?: (cwd: string) => Promise<string>;
|
|
78
|
+
}
|
|
79
|
+
/** Authority and runtime boundaries used after a Code host enrollment succeeds. */
|
|
80
|
+
interface CodeRuntimeInput {
|
|
81
|
+
endpoint: string;
|
|
82
|
+
token: string;
|
|
83
|
+
engine: CodeContainerEngine;
|
|
84
|
+
capabilities: CodeHostCapabilities;
|
|
85
|
+
heartbeatMs: number;
|
|
86
|
+
once: boolean;
|
|
87
|
+
signal?: AbortSignal;
|
|
88
|
+
stdout: Output$1;
|
|
89
|
+
fetch?: typeof fetch;
|
|
90
|
+
}
|
|
91
|
+
/** Enroll this machine from an odla project and keep the embedded Pi runtime
|
|
92
|
+
* online. Both the approval grant and host credential hashes are stored in
|
|
93
|
+
* odla-ai/db; plaintext host authority exists only in this running process. */
|
|
94
|
+
declare function codeConnect(options: CodeConnectOptions): Promise<void>;
|
|
95
|
+
/** Run outbound presence and fenced Pi commands without opening a listener. */
|
|
96
|
+
declare function runCodeRuntime(input: CodeRuntimeInput): Promise<void>;
|
|
97
|
+
|
|
5
98
|
/** Map a CLI failure to its process exit code: 75 (EX_TEMPFAIL) marks a
|
|
6
99
|
* handshake that is still awaiting human approval — the pending state is
|
|
7
100
|
* persisted and rerunning the same command resumes it — everything else is 1. */
|
|
@@ -14,6 +107,7 @@ interface CliDependencies {
|
|
|
14
107
|
readGitOrigin?: (cwd: string) => Promise<string>;
|
|
15
108
|
confirm?: (message: string) => Promise<boolean>;
|
|
16
109
|
stdout?: Pick<typeof console, "log" | "error">;
|
|
110
|
+
codeConnect?: (options: CodeConnectOptions) => Promise<void>;
|
|
17
111
|
}
|
|
18
112
|
/**
|
|
19
113
|
* Parse CLI arguments and dispatch the matching odla command.
|
|
@@ -28,23 +122,6 @@ interface CliDependencies {
|
|
|
28
122
|
*/
|
|
29
123
|
declare function runCli(argv?: string[], dependencies?: CliDependencies): Promise<void>;
|
|
30
124
|
|
|
31
|
-
/** One exact platform scope obtainable through the admin device flow. */
|
|
32
|
-
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";
|
|
33
|
-
/** Inputs for obtaining one short-lived, exact-scope platform device grant. */
|
|
34
|
-
interface ScopedPlatformTokenOptions {
|
|
35
|
-
platform: string;
|
|
36
|
-
scope: ScopedPlatformScope;
|
|
37
|
-
/** Existing odla account email used only when a fresh handshake is required. */
|
|
38
|
-
email?: string;
|
|
39
|
-
open?: boolean;
|
|
40
|
-
fetch?: typeof fetch;
|
|
41
|
-
stdout?: Pick<typeof console, "log">;
|
|
42
|
-
openApprovalUrl?: (url: string) => Promise<void>;
|
|
43
|
-
tokenFile?: string;
|
|
44
|
-
}
|
|
45
|
-
/** Obtain/cache one exact platform scope without granting ambient admin. */
|
|
46
|
-
declare function getScopedPlatformToken(options: ScopedPlatformTokenOptions): Promise<string>;
|
|
47
|
-
|
|
48
125
|
/** Hosted platform purposes whose provider, model, and budgets an admin may route. */
|
|
49
126
|
declare const SYSTEM_AI_PURPOSES: readonly ["o11y.triage", "security.discovery", "security.validation"];
|
|
50
127
|
/** One catalog-validated, platform-funded System AI purpose. */
|
|
@@ -99,10 +176,10 @@ declare function adminAi(options: AdminAiOptions): Promise<void>;
|
|
|
99
176
|
/** Stable, machine-readable division of work between the CLI, coding agent,
|
|
100
177
|
* human operator, and Studio. Printed by `odla-ai capabilities --json`. */
|
|
101
178
|
declare const CAPABILITIES: {
|
|
102
|
-
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", "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"];
|
|
179
|
+
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"];
|
|
103
180
|
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"];
|
|
104
181
|
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"];
|
|
105
|
-
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"];
|
|
182
|
+
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"];
|
|
106
183
|
};
|
|
107
184
|
type Output = Pick<typeof console, "log">;
|
|
108
185
|
/** Print the stable responsibility boundary for humans or agent tooling. */
|
|
@@ -671,8 +748,9 @@ interface HostedSecurityRequestOptions {
|
|
|
671
748
|
interface ConnectGitHubSecuritySourceOptions extends HostedSecurityRequestOptions {
|
|
672
749
|
appId: string;
|
|
673
750
|
env: string;
|
|
674
|
-
/**
|
|
675
|
-
|
|
751
|
+
/** Optional owner/name cross-check. The server always scans the app's one
|
|
752
|
+
* Studio-connected repository; a mismatch fails the connect. */
|
|
753
|
+
repository?: string;
|
|
676
754
|
/** false prints but does not launch the install URL. Defaults to true. */
|
|
677
755
|
open?: boolean;
|
|
678
756
|
openInstallUrl?: (url: string) => Promise<void>;
|
|
@@ -855,4 +933,4 @@ declare function installSkill(options?: SkillInstallOptions): SkillInstallResult
|
|
|
855
933
|
*/
|
|
856
934
|
declare function smoke(options: SmokeOptions): Promise<void>;
|
|
857
935
|
|
|
858
|
-
export { AGENT_HARNESSES, type AdminAiOptions, type AgentHarness, type AgentHarnessSelector, type AvailableGoogleCalendar, CAPABILITIES, type CalendarConfig, type CalendarConnectionState, type CalendarLifecycleOptions, type CalendarServiceConfig, type CalendarStatus, type CliDependencies, type ConnectGitHubSecuritySourceOptions, type DisconnectGitHubSecuritySourceOptions, type FollowHostedSecurityJobOptions, GOOGLE_CALENDAR_EVENTS_SCOPE, type GetHostedSecurityIntentOptions, type GetHostedSecurityJobOptions, type GoogleCalendarConfig, type HarnessInstallResult, type HostedSecurityProfile, type HostedSecurityResult, type HostedSecurityTokenRequest, type IntegrationProbe, type IntegrationSeed, type ListGitHubSecuritySourcesOptions, type ListHostedSecurityJobsOptions, type LoadedProjectConfig, type LocalCredentials, type OdlaIntegration, type OdlaProjectConfig, type ProvisionOptions, type ProvisionPlan, type RunHostedSecurityOptions, SYSTEM_AI_PURPOSES, type ScopedPlatformTokenOptions, type SecretsPushOptions, type SecretsSetOptions, type SkillInstallOptions, type SkillInstallResult, type SmokeOptions, type StartHostedSecurityJobOptions, type SystemAiPurpose, adminAi, calendarBookingPageUrl, calendarCalendars, calendarConnect, calendarDisconnect, calendarServiceConfig, calendarStatus, connectGitHubSecuritySource, disconnectGitHubSecuritySource, doctor, exitCodeFor, followHostedSecurityJob, getHostedSecurityIntent, getHostedSecurityJob, getHostedSecurityPlan, getHostedSecurityReport, getScopedPlatformToken, inferGitHubRepository, initProject, installSkill, isTerminalHostedSecurityStatus, listGitHubSecuritySources, listHostedSecurityJobs, printCapabilities, provision, redactSecrets, repositoryFromGitRemote, runCli, runHostedSecurity, secretsPush, secretsSet, secretsSetClerkKey, smoke, startHostedSecurityJob };
|
|
936
|
+
export { AGENT_HARNESSES, type AdminAiOptions, type AgentHarness, type AgentHarnessSelector, type AvailableGoogleCalendar, CAPABILITIES, CODE_BUILD_RECIPES, CODE_PI_IMAGE, type CalendarConfig, type CalendarConnectionState, type CalendarLifecycleOptions, type CalendarServiceConfig, type CalendarStatus, type CliDependencies, type CodeBuildRule, type CodeConnectOptions, type CodeContainerEngine, type CodeHostCapabilities, type CodeRuntimeInput, type ConnectGitHubSecuritySourceOptions, type DisconnectGitHubSecuritySourceOptions, type FollowHostedSecurityJobOptions, GOOGLE_CALENDAR_EVENTS_SCOPE, type GetHostedSecurityIntentOptions, type GetHostedSecurityJobOptions, type GoogleCalendarConfig, type HarnessInstallResult, type HostedSecurityProfile, type HostedSecurityResult, type HostedSecurityTokenRequest, type IntegrationProbe, type IntegrationSeed, type ListGitHubSecuritySourcesOptions, type ListHostedSecurityJobsOptions, type LoadedProjectConfig, type LocalCredentials, type OdlaIntegration, type OdlaProjectConfig, type ProvisionOptions, type ProvisionPlan, type RunHostedSecurityOptions, SYSTEM_AI_PURPOSES, type ScopedPlatformTokenOptions, type SecretsPushOptions, type SecretsSetOptions, type SkillInstallOptions, type SkillInstallResult, type SmokeOptions, type StartHostedSecurityJobOptions, type SystemAiPurpose, adminAi, calendarBookingPageUrl, calendarCalendars, calendarConnect, calendarDisconnect, calendarServiceConfig, calendarStatus, codeConnect, connectGitHubSecuritySource, disconnectGitHubSecuritySource, doctor, exitCodeFor, followHostedSecurityJob, getHostedSecurityIntent, getHostedSecurityJob, getHostedSecurityPlan, getHostedSecurityReport, getScopedPlatformToken, inferGitHubRepository, initProject, installSkill, isTerminalHostedSecurityStatus, listGitHubSecuritySources, listHostedSecurityJobs, printCapabilities, provision, redactSecrets, repositoryFromGitRemote, runCli, runCodeRuntime, runHostedSecurity, secretsPush, secretsSet, secretsSetClerkKey, smoke, startHostedSecurityJob };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,99 @@ import { SecurityReport, PlatformSecurityRun } from '@odla-ai/security';
|
|
|
2
2
|
import { HostedSecurityJob, GitHubConnectionStatus, GitHubSecuritySource, HostedSecurityIntentResponse, HostedSecurityPlan, HostedSecurityReport, HostedSecurityJobStatus } from '@odla-ai/security/hosted';
|
|
3
3
|
export { GitHubConnectionAttempt, GitHubConnectionStatus, GitHubSecuritySource, HostedSecurityCounts, HostedSecurityCoverage, HostedSecurityIntent, HostedSecurityIntentResponse, HostedSecurityJob, HostedSecurityJobStatus, HostedSecurityPlan, HostedSecurityPlanRoute, HostedSecurityReport, HostedSecurityReportFinding, HostedSecurityRoute } from '@odla-ai/security/hosted';
|
|
4
4
|
|
|
5
|
+
/** One exact platform scope obtainable through the admin device flow. */
|
|
6
|
+
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:code:host:connect" | "platform:security:self";
|
|
7
|
+
/** Inputs for obtaining one short-lived, exact-scope platform device grant. */
|
|
8
|
+
interface ScopedPlatformTokenOptions {
|
|
9
|
+
platform: string;
|
|
10
|
+
scope: ScopedPlatformScope;
|
|
11
|
+
/** Existing odla account email used only when a fresh handshake is required. */
|
|
12
|
+
email?: string;
|
|
13
|
+
open?: boolean;
|
|
14
|
+
fetch?: typeof fetch;
|
|
15
|
+
stdout?: Pick<typeof console, "log">;
|
|
16
|
+
openApprovalUrl?: (url: string) => Promise<void>;
|
|
17
|
+
tokenFile?: string;
|
|
18
|
+
/** Keep the shown-once grant only in memory. */
|
|
19
|
+
cache?: boolean;
|
|
20
|
+
/** Human-visible purpose recorded on the exact handshake. */
|
|
21
|
+
label?: string;
|
|
22
|
+
}
|
|
23
|
+
/** Obtain/cache one exact platform scope without granting ambient admin. */
|
|
24
|
+
declare function getScopedPlatformToken(options: ScopedPlatformTokenOptions): Promise<string>;
|
|
25
|
+
|
|
26
|
+
/** Immutable, release-owned Pi adapter. No registry credential enters it. */
|
|
27
|
+
declare const CODE_PI_IMAGE = "ghcr.io/cory/odla-pi-agent@sha256:713db58428bc05cb486167c5747de8fd826669c9b283ff78e0139ac194c3d058";
|
|
28
|
+
/** Supported local isolation engines for an odla Code host runtime. */
|
|
29
|
+
type CodeContainerEngine = "container" | "podman" | "docker";
|
|
30
|
+
/** Immutable CaMeL-registered build recipe available to an agent container. */
|
|
31
|
+
interface CodeBuildRule {
|
|
32
|
+
id: string;
|
|
33
|
+
image: string;
|
|
34
|
+
command: readonly string[];
|
|
35
|
+
timeoutMs: number;
|
|
36
|
+
maxOutputBytes: number;
|
|
37
|
+
cpus?: number;
|
|
38
|
+
memory?: string;
|
|
39
|
+
pids?: number;
|
|
40
|
+
tmpfsBytes?: number;
|
|
41
|
+
}
|
|
42
|
+
/** Bounded host facts reported on each outbound Code control-plane heartbeat. */
|
|
43
|
+
interface CodeHostCapabilities {
|
|
44
|
+
protocolVersion: 1;
|
|
45
|
+
platform: "macos" | "linux";
|
|
46
|
+
arch: string;
|
|
47
|
+
engines: CodeContainerEngine[];
|
|
48
|
+
cpuCount: number;
|
|
49
|
+
memoryBytes: number;
|
|
50
|
+
}
|
|
51
|
+
/** Initial CaMeL-registered clean-build rule. App-specific recipes can replace
|
|
52
|
+
* this only after their own owner-visible registration flow exists. */
|
|
53
|
+
declare const CODE_BUILD_RECIPES: readonly CodeBuildRule[];
|
|
54
|
+
type Output$1 = Pick<typeof console, "log" | "error">;
|
|
55
|
+
/** Inputs for enrolling the current checkout and running its foreground Pi host. */
|
|
56
|
+
interface CodeConnectOptions {
|
|
57
|
+
configPath: string;
|
|
58
|
+
/** Repository root. Defaults to the current directory. */
|
|
59
|
+
cwd?: string;
|
|
60
|
+
env?: string;
|
|
61
|
+
email?: string;
|
|
62
|
+
open?: boolean;
|
|
63
|
+
name?: string;
|
|
64
|
+
slots?: number;
|
|
65
|
+
engine?: CodeContainerEngine | "auto";
|
|
66
|
+
heartbeatMs?: number;
|
|
67
|
+
/** Enroll and prove one heartbeat without waiting for sessions. */
|
|
68
|
+
once?: boolean;
|
|
69
|
+
fetch?: typeof fetch;
|
|
70
|
+
stdout?: Output$1;
|
|
71
|
+
openApprovalUrl?: (url: string) => Promise<void>;
|
|
72
|
+
signal?: AbortSignal;
|
|
73
|
+
/** Test/embedding boundaries. */
|
|
74
|
+
getToken?: typeof getScopedPlatformToken;
|
|
75
|
+
selectEngine?: (requested: CodeContainerEngine | "auto") => Promise<CodeContainerEngine>;
|
|
76
|
+
runRuntime?: (input: CodeRuntimeInput) => Promise<void>;
|
|
77
|
+
readGitOrigin?: (cwd: string) => Promise<string>;
|
|
78
|
+
}
|
|
79
|
+
/** Authority and runtime boundaries used after a Code host enrollment succeeds. */
|
|
80
|
+
interface CodeRuntimeInput {
|
|
81
|
+
endpoint: string;
|
|
82
|
+
token: string;
|
|
83
|
+
engine: CodeContainerEngine;
|
|
84
|
+
capabilities: CodeHostCapabilities;
|
|
85
|
+
heartbeatMs: number;
|
|
86
|
+
once: boolean;
|
|
87
|
+
signal?: AbortSignal;
|
|
88
|
+
stdout: Output$1;
|
|
89
|
+
fetch?: typeof fetch;
|
|
90
|
+
}
|
|
91
|
+
/** Enroll this machine from an odla project and keep the embedded Pi runtime
|
|
92
|
+
* online. Both the approval grant and host credential hashes are stored in
|
|
93
|
+
* odla-ai/db; plaintext host authority exists only in this running process. */
|
|
94
|
+
declare function codeConnect(options: CodeConnectOptions): Promise<void>;
|
|
95
|
+
/** Run outbound presence and fenced Pi commands without opening a listener. */
|
|
96
|
+
declare function runCodeRuntime(input: CodeRuntimeInput): Promise<void>;
|
|
97
|
+
|
|
5
98
|
/** Map a CLI failure to its process exit code: 75 (EX_TEMPFAIL) marks a
|
|
6
99
|
* handshake that is still awaiting human approval — the pending state is
|
|
7
100
|
* persisted and rerunning the same command resumes it — everything else is 1. */
|
|
@@ -14,6 +107,7 @@ interface CliDependencies {
|
|
|
14
107
|
readGitOrigin?: (cwd: string) => Promise<string>;
|
|
15
108
|
confirm?: (message: string) => Promise<boolean>;
|
|
16
109
|
stdout?: Pick<typeof console, "log" | "error">;
|
|
110
|
+
codeConnect?: (options: CodeConnectOptions) => Promise<void>;
|
|
17
111
|
}
|
|
18
112
|
/**
|
|
19
113
|
* Parse CLI arguments and dispatch the matching odla command.
|
|
@@ -28,23 +122,6 @@ interface CliDependencies {
|
|
|
28
122
|
*/
|
|
29
123
|
declare function runCli(argv?: string[], dependencies?: CliDependencies): Promise<void>;
|
|
30
124
|
|
|
31
|
-
/** One exact platform scope obtainable through the admin device flow. */
|
|
32
|
-
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";
|
|
33
|
-
/** Inputs for obtaining one short-lived, exact-scope platform device grant. */
|
|
34
|
-
interface ScopedPlatformTokenOptions {
|
|
35
|
-
platform: string;
|
|
36
|
-
scope: ScopedPlatformScope;
|
|
37
|
-
/** Existing odla account email used only when a fresh handshake is required. */
|
|
38
|
-
email?: string;
|
|
39
|
-
open?: boolean;
|
|
40
|
-
fetch?: typeof fetch;
|
|
41
|
-
stdout?: Pick<typeof console, "log">;
|
|
42
|
-
openApprovalUrl?: (url: string) => Promise<void>;
|
|
43
|
-
tokenFile?: string;
|
|
44
|
-
}
|
|
45
|
-
/** Obtain/cache one exact platform scope without granting ambient admin. */
|
|
46
|
-
declare function getScopedPlatformToken(options: ScopedPlatformTokenOptions): Promise<string>;
|
|
47
|
-
|
|
48
125
|
/** Hosted platform purposes whose provider, model, and budgets an admin may route. */
|
|
49
126
|
declare const SYSTEM_AI_PURPOSES: readonly ["o11y.triage", "security.discovery", "security.validation"];
|
|
50
127
|
/** One catalog-validated, platform-funded System AI purpose. */
|
|
@@ -99,10 +176,10 @@ declare function adminAi(options: AdminAiOptions): Promise<void>;
|
|
|
99
176
|
/** Stable, machine-readable division of work between the CLI, coding agent,
|
|
100
177
|
* human operator, and Studio. Printed by `odla-ai capabilities --json`. */
|
|
101
178
|
declare const CAPABILITIES: {
|
|
102
|
-
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", "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"];
|
|
179
|
+
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"];
|
|
103
180
|
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"];
|
|
104
181
|
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"];
|
|
105
|
-
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"];
|
|
182
|
+
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"];
|
|
106
183
|
};
|
|
107
184
|
type Output = Pick<typeof console, "log">;
|
|
108
185
|
/** Print the stable responsibility boundary for humans or agent tooling. */
|
|
@@ -671,8 +748,9 @@ interface HostedSecurityRequestOptions {
|
|
|
671
748
|
interface ConnectGitHubSecuritySourceOptions extends HostedSecurityRequestOptions {
|
|
672
749
|
appId: string;
|
|
673
750
|
env: string;
|
|
674
|
-
/**
|
|
675
|
-
|
|
751
|
+
/** Optional owner/name cross-check. The server always scans the app's one
|
|
752
|
+
* Studio-connected repository; a mismatch fails the connect. */
|
|
753
|
+
repository?: string;
|
|
676
754
|
/** false prints but does not launch the install URL. Defaults to true. */
|
|
677
755
|
open?: boolean;
|
|
678
756
|
openInstallUrl?: (url: string) => Promise<void>;
|
|
@@ -855,4 +933,4 @@ declare function installSkill(options?: SkillInstallOptions): SkillInstallResult
|
|
|
855
933
|
*/
|
|
856
934
|
declare function smoke(options: SmokeOptions): Promise<void>;
|
|
857
935
|
|
|
858
|
-
export { AGENT_HARNESSES, type AdminAiOptions, type AgentHarness, type AgentHarnessSelector, type AvailableGoogleCalendar, CAPABILITIES, type CalendarConfig, type CalendarConnectionState, type CalendarLifecycleOptions, type CalendarServiceConfig, type CalendarStatus, type CliDependencies, type ConnectGitHubSecuritySourceOptions, type DisconnectGitHubSecuritySourceOptions, type FollowHostedSecurityJobOptions, GOOGLE_CALENDAR_EVENTS_SCOPE, type GetHostedSecurityIntentOptions, type GetHostedSecurityJobOptions, type GoogleCalendarConfig, type HarnessInstallResult, type HostedSecurityProfile, type HostedSecurityResult, type HostedSecurityTokenRequest, type IntegrationProbe, type IntegrationSeed, type ListGitHubSecuritySourcesOptions, type ListHostedSecurityJobsOptions, type LoadedProjectConfig, type LocalCredentials, type OdlaIntegration, type OdlaProjectConfig, type ProvisionOptions, type ProvisionPlan, type RunHostedSecurityOptions, SYSTEM_AI_PURPOSES, type ScopedPlatformTokenOptions, type SecretsPushOptions, type SecretsSetOptions, type SkillInstallOptions, type SkillInstallResult, type SmokeOptions, type StartHostedSecurityJobOptions, type SystemAiPurpose, adminAi, calendarBookingPageUrl, calendarCalendars, calendarConnect, calendarDisconnect, calendarServiceConfig, calendarStatus, connectGitHubSecuritySource, disconnectGitHubSecuritySource, doctor, exitCodeFor, followHostedSecurityJob, getHostedSecurityIntent, getHostedSecurityJob, getHostedSecurityPlan, getHostedSecurityReport, getScopedPlatformToken, inferGitHubRepository, initProject, installSkill, isTerminalHostedSecurityStatus, listGitHubSecuritySources, listHostedSecurityJobs, printCapabilities, provision, redactSecrets, repositoryFromGitRemote, runCli, runHostedSecurity, secretsPush, secretsSet, secretsSetClerkKey, smoke, startHostedSecurityJob };
|
|
936
|
+
export { AGENT_HARNESSES, type AdminAiOptions, type AgentHarness, type AgentHarnessSelector, type AvailableGoogleCalendar, CAPABILITIES, CODE_BUILD_RECIPES, CODE_PI_IMAGE, type CalendarConfig, type CalendarConnectionState, type CalendarLifecycleOptions, type CalendarServiceConfig, type CalendarStatus, type CliDependencies, type CodeBuildRule, type CodeConnectOptions, type CodeContainerEngine, type CodeHostCapabilities, type CodeRuntimeInput, type ConnectGitHubSecuritySourceOptions, type DisconnectGitHubSecuritySourceOptions, type FollowHostedSecurityJobOptions, GOOGLE_CALENDAR_EVENTS_SCOPE, type GetHostedSecurityIntentOptions, type GetHostedSecurityJobOptions, type GoogleCalendarConfig, type HarnessInstallResult, type HostedSecurityProfile, type HostedSecurityResult, type HostedSecurityTokenRequest, type IntegrationProbe, type IntegrationSeed, type ListGitHubSecuritySourcesOptions, type ListHostedSecurityJobsOptions, type LoadedProjectConfig, type LocalCredentials, type OdlaIntegration, type OdlaProjectConfig, type ProvisionOptions, type ProvisionPlan, type RunHostedSecurityOptions, SYSTEM_AI_PURPOSES, type ScopedPlatformTokenOptions, type SecretsPushOptions, type SecretsSetOptions, type SkillInstallOptions, type SkillInstallResult, type SmokeOptions, type StartHostedSecurityJobOptions, type SystemAiPurpose, adminAi, calendarBookingPageUrl, calendarCalendars, calendarConnect, calendarDisconnect, calendarServiceConfig, calendarStatus, codeConnect, connectGitHubSecuritySource, disconnectGitHubSecuritySource, doctor, exitCodeFor, followHostedSecurityJob, getHostedSecurityIntent, getHostedSecurityJob, getHostedSecurityPlan, getHostedSecurityReport, getScopedPlatformToken, inferGitHubRepository, initProject, installSkill, isTerminalHostedSecurityStatus, listGitHubSecuritySources, listHostedSecurityJobs, printCapabilities, provision, redactSecrets, repositoryFromGitRemote, runCli, runCodeRuntime, runHostedSecurity, secretsPush, secretsSet, secretsSetClerkKey, smoke, startHostedSecurityJob };
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import {
|
|
3
3
|
AGENT_HARNESSES,
|
|
4
4
|
CAPABILITIES,
|
|
5
|
+
CODE_BUILD_RECIPES,
|
|
6
|
+
CODE_PI_IMAGE,
|
|
5
7
|
GOOGLE_CALENDAR_EVENTS_SCOPE,
|
|
6
8
|
SYSTEM_AI_PURPOSES,
|
|
7
9
|
adminAi,
|
|
@@ -11,6 +13,7 @@ import {
|
|
|
11
13
|
calendarDisconnect,
|
|
12
14
|
calendarServiceConfig,
|
|
13
15
|
calendarStatus,
|
|
16
|
+
codeConnect,
|
|
14
17
|
connectGitHubSecuritySource,
|
|
15
18
|
disconnectGitHubSecuritySource,
|
|
16
19
|
doctor,
|
|
@@ -32,16 +35,19 @@ import {
|
|
|
32
35
|
redactSecrets,
|
|
33
36
|
repositoryFromGitRemote,
|
|
34
37
|
runCli,
|
|
38
|
+
runCodeRuntime,
|
|
35
39
|
runHostedSecurity,
|
|
36
40
|
secretsPush,
|
|
37
41
|
secretsSet,
|
|
38
42
|
secretsSetClerkKey,
|
|
39
43
|
smoke,
|
|
40
44
|
startHostedSecurityJob
|
|
41
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-AN6KZMR5.js";
|
|
42
46
|
export {
|
|
43
47
|
AGENT_HARNESSES,
|
|
44
48
|
CAPABILITIES,
|
|
49
|
+
CODE_BUILD_RECIPES,
|
|
50
|
+
CODE_PI_IMAGE,
|
|
45
51
|
GOOGLE_CALENDAR_EVENTS_SCOPE,
|
|
46
52
|
SYSTEM_AI_PURPOSES,
|
|
47
53
|
adminAi,
|
|
@@ -51,6 +57,7 @@ export {
|
|
|
51
57
|
calendarDisconnect,
|
|
52
58
|
calendarServiceConfig,
|
|
53
59
|
calendarStatus,
|
|
60
|
+
codeConnect,
|
|
54
61
|
connectGitHubSecuritySource,
|
|
55
62
|
disconnectGitHubSecuritySource,
|
|
56
63
|
doctor,
|
|
@@ -72,6 +79,7 @@ export {
|
|
|
72
79
|
redactSecrets,
|
|
73
80
|
repositoryFromGitRemote,
|
|
74
81
|
runCli,
|
|
82
|
+
runCodeRuntime,
|
|
75
83
|
runHostedSecurity,
|
|
76
84
|
secretsPush,
|
|
77
85
|
secretsSet,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@odla-ai/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.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",
|
|
@@ -59,10 +59,11 @@
|
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"@odla-ai/ai": "^0.5.0",
|
|
61
61
|
"@odla-ai/apps": "^0.8.1",
|
|
62
|
-
"@odla-ai/db": "
|
|
62
|
+
"@odla-ai/db": ">=0.6.4",
|
|
63
63
|
"@odla-ai/security": "^0.3.1"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
+
"@odla-ai/harness": "*",
|
|
66
67
|
"@types/node": "^22.10.0",
|
|
67
68
|
"tsup": "^8.5.1",
|
|
68
69
|
"typescript": "^6.0.3",
|
package/skills/odla/SKILL.md
CHANGED
|
@@ -9,6 +9,7 @@ description: >
|
|
|
9
9
|
runbookOrder:
|
|
10
10
|
- references/build.md
|
|
11
11
|
- references/sdks.md
|
|
12
|
+
- references/co-owners.md
|
|
12
13
|
---
|
|
13
14
|
|
|
14
15
|
# odla
|
|
@@ -160,3 +161,6 @@ code, paste a publishable key, run a command) — and wait for a nod.
|
|
|
160
161
|
exported TypeScript declarations/JSDoc (resolve entry points through its
|
|
161
162
|
`package.json` `exports`). Rendered references are also public at
|
|
162
163
|
`https://odla.ai/docs/packages/<pkg>`.
|
|
164
|
+
- `references/co-owners.md` — sharing one app's db and tooling across a team:
|
|
165
|
+
`app owners add/list/remove`, and how each co-owner self-provisions their own
|
|
166
|
+
credentials (dev and the shared prod database) without any secret handoff.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Co-owners — sharing one app's db and tooling
|
|
2
|
+
|
|
3
|
+
An odla app can have more than one owner. The creator is the **primary owner**;
|
|
4
|
+
everyone else is a **co-owner** with the *same* full access. This is how a team
|
|
5
|
+
shares one database — dev and prod — with each person holding their own
|
|
6
|
+
revocable credentials. No secret is ever copied between people.
|
|
7
|
+
|
|
8
|
+
## The rule that makes this safe
|
|
9
|
+
|
|
10
|
+
Each owner mints their **own** `ODLA_API_KEY`. You never send someone a
|
|
11
|
+
`.dev.vars`, a `.odla/credentials.local.json`, or a key over chat. The registry
|
|
12
|
+
records who co-owns an app; the db honors any co-owner when they provision.
|
|
13
|
+
|
|
14
|
+
## Onboarding a co-owner
|
|
15
|
+
|
|
16
|
+
1. **The primary owner adds them** (they must already be a signed-up odla
|
|
17
|
+
member — an admin invites them first if not):
|
|
18
|
+
|
|
19
|
+
```cmd
|
|
20
|
+
npx @odla-ai/cli app owners add teammate@example.com
|
|
21
|
+
npx @odla-ai/cli app owners list
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
(`npx @odla-ai/cli app owners remove teammate@example.com` revokes it. The
|
|
25
|
+
primary owner can't be removed. Studio's app **Settings** does the same.)
|
|
26
|
+
|
|
27
|
+
2. **The co-owner provisions as themselves.** They clone the repo (which carries
|
|
28
|
+
`odla.config.mjs` but not the gitignored credentials) and run provision with
|
|
29
|
+
their *own* account email — the device grant is approved by them, not the
|
|
30
|
+
primary owner:
|
|
31
|
+
|
|
32
|
+
```cmd
|
|
33
|
+
npx @odla-ai/cli provision --email teammate@example.com --write-dev-vars --push-secrets
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
provision verifies the existing app (it does not re-create it), mints the
|
|
37
|
+
co-owner's own db/o11y credentials for the shared tenant, writes their local
|
|
38
|
+
`.dev.vars`, and transfers secrets to their Worker. They can now
|
|
39
|
+
`npm run dev` and, at the production checkpoint, deploy.
|
|
40
|
+
|
|
41
|
+
## Production is one shared database
|
|
42
|
+
|
|
43
|
+
Every environment's tenant is the same across all owners (prod's tenant is the
|
|
44
|
+
bare app id; `dev` is `<appId>--dev`). So multiple co-owners deploying to
|
|
45
|
+
**production** all read and write the **same** prod database — each with their
|
|
46
|
+
own key. Treat first-prod provision/deploy as the usual human checkpoint
|
|
47
|
+
(`provision --dry-run` review, then `provision --yes --push-secrets`), and never
|
|
48
|
+
rotate another owner's credentials on their behalf.
|
|
49
|
+
|
|
50
|
+
## If provision says "you are not an owner"
|
|
51
|
+
|
|
52
|
+
provision checks tenant admin access up front and aborts **before** anything is
|
|
53
|
+
minted or written — no credential lands on disk, in the vault, or in a Worker.
|
|
54
|
+
It means the registry doesn't list you as an owner yet: ask an existing owner
|
|
55
|
+
to run `npx @odla-ai/cli app owners add <your-email>`, then re-run provision.
|
|
56
|
+
|
|
57
|
+
## If a co-owner loses their local key
|
|
58
|
+
|
|
59
|
+
Keys are shown once and stored hashed — there is no reveal. Re-mint instead:
|
|
60
|
+
re-run `provision` (or Studio's **mint API key**). Both work for any owner now,
|
|
61
|
+
not just the creator.
|