@zivis/cli 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/app/index.d.ts +10 -0
- package/dist/commands/app/index.js +245 -0
- package/dist/commands/app/index.js.map +1 -0
- package/dist/commands/auth/index.d.ts +2 -0
- package/dist/commands/auth/index.js +41 -0
- package/dist/commands/auth/index.js.map +1 -0
- package/dist/commands/auth/login.d.ts +8 -0
- package/dist/commands/auth/login.js +65 -0
- package/dist/commands/auth/login.js.map +1 -0
- package/dist/commands/auth/logout.d.ts +5 -0
- package/dist/commands/auth/logout.js +14 -0
- package/dist/commands/auth/logout.js.map +1 -0
- package/dist/commands/auth/sessions.d.ts +4 -0
- package/dist/commands/auth/sessions.js +30 -0
- package/dist/commands/auth/sessions.js.map +1 -0
- package/dist/commands/auth/status.d.ts +4 -0
- package/dist/commands/auth/status.js +53 -0
- package/dist/commands/auth/status.js.map +1 -0
- package/dist/commands/credits/index.d.ts +2 -0
- package/dist/commands/credits/index.js +51 -0
- package/dist/commands/credits/index.js.map +1 -0
- package/dist/commands/mcp/index.d.ts +2 -0
- package/dist/commands/mcp/index.js +70 -0
- package/dist/commands/mcp/index.js.map +1 -0
- package/dist/commands/open/index.d.ts +10 -0
- package/dist/commands/open/index.js +57 -0
- package/dist/commands/open/index.js.map +1 -0
- package/dist/commands/scan/index.d.ts +2 -0
- package/dist/commands/scan/index.js +140 -0
- package/dist/commands/scan/index.js.map +1 -0
- package/dist/commands/target/index.d.ts +2 -0
- package/dist/commands/target/index.js +146 -0
- package/dist/commands/target/index.js.map +1 -0
- package/dist/commands/tm/index.d.ts +2 -0
- package/dist/commands/tm/index.js +266 -0
- package/dist/commands/tm/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/extractor/adapters/go/index.d.ts +7 -0
- package/dist/internal/extractor/adapters/go/index.js +71 -0
- package/dist/internal/extractor/adapters/go/index.js.map +1 -0
- package/dist/internal/extractor/adapters/go/manifest.d.ts +37 -0
- package/dist/internal/extractor/adapters/go/manifest.js +199 -0
- package/dist/internal/extractor/adapters/go/manifest.js.map +1 -0
- package/dist/internal/extractor/adapters/go/parser.d.ts +6 -0
- package/dist/internal/extractor/adapters/go/parser.js +23 -0
- package/dist/internal/extractor/adapters/go/parser.js.map +1 -0
- package/dist/internal/extractor/adapters/go/scanner.d.ts +39 -0
- package/dist/internal/extractor/adapters/go/scanner.js +216 -0
- package/dist/internal/extractor/adapters/go/scanner.js.map +1 -0
- package/dist/internal/extractor/adapters/python/index.d.ts +5 -0
- package/dist/internal/extractor/adapters/python/index.js +68 -0
- package/dist/internal/extractor/adapters/python/index.js.map +1 -0
- package/dist/internal/extractor/adapters/python/manifest.d.ts +25 -0
- package/dist/internal/extractor/adapters/python/manifest.js +236 -0
- package/dist/internal/extractor/adapters/python/manifest.js.map +1 -0
- package/dist/internal/extractor/adapters/python/parser.d.ts +5 -0
- package/dist/internal/extractor/adapters/python/parser.js +22 -0
- package/dist/internal/extractor/adapters/python/parser.js.map +1 -0
- package/dist/internal/extractor/adapters/python/scanner.d.ts +37 -0
- package/dist/internal/extractor/adapters/python/scanner.js +284 -0
- package/dist/internal/extractor/adapters/python/scanner.js.map +1 -0
- package/dist/internal/extractor/adapters/typescript/index.d.ts +9 -0
- package/dist/internal/extractor/adapters/typescript/index.js +84 -0
- package/dist/internal/extractor/adapters/typescript/index.js.map +1 -0
- package/dist/internal/extractor/adapters/typescript/manifest.d.ts +41 -0
- package/dist/internal/extractor/adapters/typescript/manifest.js +156 -0
- package/dist/internal/extractor/adapters/typescript/manifest.js.map +1 -0
- package/dist/internal/extractor/adapters/typescript/parser.d.ts +14 -0
- package/dist/internal/extractor/adapters/typescript/parser.js +33 -0
- package/dist/internal/extractor/adapters/typescript/parser.js.map +1 -0
- package/dist/internal/extractor/adapters/typescript/scanner.d.ts +43 -0
- package/dist/internal/extractor/adapters/typescript/scanner.js +188 -0
- package/dist/internal/extractor/adapters/typescript/scanner.js.map +1 -0
- package/dist/internal/extractor/index.d.ts +22 -0
- package/dist/internal/extractor/index.js +107 -0
- package/dist/internal/extractor/index.js.map +1 -0
- package/dist/internal/extractor/types.d.ts +124 -0
- package/dist/internal/extractor/types.js +28 -0
- package/dist/internal/extractor/types.js.map +1 -0
- package/dist/internal/extractor/walker.d.ts +32 -0
- package/dist/internal/extractor/walker.js +110 -0
- package/dist/internal/extractor/walker.js.map +1 -0
- package/dist/internal/ide-setup.d.ts +7 -0
- package/dist/internal/ide-setup.js +131 -0
- package/dist/internal/ide-setup.js.map +1 -0
- package/dist/internal/orgs.d.ts +8 -0
- package/dist/internal/orgs.js +31 -0
- package/dist/internal/orgs.js.map +1 -0
- package/dist/internal/project-binding.d.ts +11 -0
- package/dist/internal/project-binding.js +96 -0
- package/dist/internal/project-binding.js.map +1 -0
- package/dist/internal/target-auth/api-config.d.ts +37 -0
- package/dist/internal/target-auth/api-config.js +40 -0
- package/dist/internal/target-auth/api-config.js.map +1 -0
- package/dist/internal/target-auth/config.d.ts +20 -0
- package/dist/internal/target-auth/config.js +58 -0
- package/dist/internal/target-auth/config.js.map +1 -0
- package/dist/internal/target-auth/index.d.ts +30 -0
- package/dist/internal/target-auth/index.js +101 -0
- package/dist/internal/target-auth/index.js.map +1 -0
- package/dist/internal/target-auth/keychain.d.ts +23 -0
- package/dist/internal/target-auth/keychain.js +150 -0
- package/dist/internal/target-auth/keychain.js.map +1 -0
- package/dist/internal/target-auth/types.d.ts +51 -0
- package/dist/internal/target-auth/types.js +11 -0
- package/dist/internal/target-auth/types.js.map +1 -0
- package/dist/internal/target-auth/workos.d.ts +20 -0
- package/dist/internal/target-auth/workos.js +196 -0
- package/dist/internal/target-auth/workos.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as readline from "node:readline/promises";
|
|
4
|
+
import { decodeJwtPayload } from "@zivis-ai/mcp-security/auth/jwt";
|
|
5
|
+
import { detectProjectBinding } from "@zivis-ai/mcp-security/project-binding";
|
|
6
|
+
import { fetchUserOrgs } from "./orgs.js";
|
|
7
|
+
export async function ensureProjectBinding(opts) {
|
|
8
|
+
const { config, session, accessToken, cwd, autoBind, skipBind } = opts;
|
|
9
|
+
const claims = decodeJwtPayload(accessToken);
|
|
10
|
+
const jwtOrgId = claims?.org_id;
|
|
11
|
+
if (!jwtOrgId) {
|
|
12
|
+
console.log("");
|
|
13
|
+
console.log(" Note: JWT has no org_id — skipping project binding.");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const detected = detectProjectBinding(cwd);
|
|
17
|
+
if (detected?.binding.workosOrgId === jwtOrgId) {
|
|
18
|
+
console.log(`✓ Project binding verified: ${detected.filePath}`);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (detected?.binding.workosOrgId && detected.binding.workosOrgId !== jwtOrgId) {
|
|
22
|
+
console.error("");
|
|
23
|
+
console.error("[zivis] ERROR: Project binding org mismatches JWT org.");
|
|
24
|
+
console.error(`[zivis] Binding file: ${detected.filePath}`);
|
|
25
|
+
console.error(`[zivis] Binding org: ${detected.binding.workosOrgId}${detected.binding.orgName ? ` (${detected.binding.orgName})` : ""}`);
|
|
26
|
+
console.error(`[zivis] JWT org: ${jwtOrgId}`);
|
|
27
|
+
console.error("[zivis] This should not happen — investigate before proceeding.");
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
let orgInfo;
|
|
31
|
+
try {
|
|
32
|
+
const orgs = await fetchUserOrgs(config, accessToken);
|
|
33
|
+
orgInfo = orgs.find((o) => o.workosOrgId === jwtOrgId);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
console.log(` WARNING: Could not fetch org info: ${err instanceof Error ? err.message : err}`);
|
|
37
|
+
}
|
|
38
|
+
const orgName = orgInfo?.name || detected?.binding.orgName;
|
|
39
|
+
const zivisOrgId = orgInfo?.id || detected?.binding.orgId;
|
|
40
|
+
const orgLabel = orgName ? `${orgName} (${jwtOrgId})` : jwtOrgId;
|
|
41
|
+
if (detected && !detected.binding.workosOrgId) {
|
|
42
|
+
const upgraded = {
|
|
43
|
+
...detected.binding,
|
|
44
|
+
workosOrgId: jwtOrgId,
|
|
45
|
+
};
|
|
46
|
+
if (orgName)
|
|
47
|
+
upgraded.orgName = orgName;
|
|
48
|
+
if (zivisOrgId)
|
|
49
|
+
upgraded.orgId = zivisOrgId;
|
|
50
|
+
fs.writeFileSync(detected.filePath, JSON.stringify(upgraded, null, 2) + "\n");
|
|
51
|
+
console.log(`✓ Upgraded project binding with org: ${orgLabel}`);
|
|
52
|
+
console.log(` File: ${detected.filePath}`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const bindingPath = path.join(cwd, ".zivis", "project.json");
|
|
56
|
+
const interactive = process.stderr.isTTY && process.stdin.isTTY;
|
|
57
|
+
let shouldBind = autoBind;
|
|
58
|
+
if (!shouldBind && !skipBind && interactive) {
|
|
59
|
+
console.log("");
|
|
60
|
+
console.log("This directory has no .zivis/project.json binding.");
|
|
61
|
+
console.log(`Binding locks future MCP calls to org: ${orgLabel}`);
|
|
62
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
63
|
+
try {
|
|
64
|
+
const answer = (await rl.question("Create binding now? [Y/n] ")).trim().toLowerCase();
|
|
65
|
+
shouldBind = answer !== "n" && answer !== "no";
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
rl.close();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (!shouldBind) {
|
|
72
|
+
if (!skipBind) {
|
|
73
|
+
console.log("");
|
|
74
|
+
console.log(" WARNING: No project binding. MCP calls will not verify the org for this directory.");
|
|
75
|
+
console.log(" To bind later: zivis auth init");
|
|
76
|
+
}
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const binding = {
|
|
80
|
+
session,
|
|
81
|
+
workosOrgId: jwtOrgId,
|
|
82
|
+
};
|
|
83
|
+
if (orgName)
|
|
84
|
+
binding.orgName = orgName;
|
|
85
|
+
if (zivisOrgId)
|
|
86
|
+
binding.orgId = zivisOrgId;
|
|
87
|
+
const zivisDir = path.join(cwd, ".zivis");
|
|
88
|
+
if (!fs.existsSync(zivisDir)) {
|
|
89
|
+
fs.mkdirSync(zivisDir, { recursive: true });
|
|
90
|
+
}
|
|
91
|
+
fs.writeFileSync(bindingPath, JSON.stringify(binding, null, 2) + "\n");
|
|
92
|
+
console.log(`✓ Project bound to ${orgLabel}`);
|
|
93
|
+
console.log(` File: ${bindingPath}`);
|
|
94
|
+
console.log(" Commit this file so future sessions in this repo are org-locked.");
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=project-binding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-binding.js","sourceRoot":"","sources":["../../src/internal/project-binding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches an Application's auth config from the ZIVIS platform.
|
|
3
|
+
*
|
|
4
|
+
* Phase J.4: replaces the local `~/.config/zivis/target-configs/*.json`
|
|
5
|
+
* file the user previously had to write by hand. The Application's IdP
|
|
6
|
+
* discovery (clientId, domain, mode, scopes) lives on the Application
|
|
7
|
+
* record on the platform; the CLI calls this endpoint to learn how to
|
|
8
|
+
* PKCE-auth, then runs the flow locally and stores tokens in the user's
|
|
9
|
+
* keychain. Tokens never leave the user's machine unless the user
|
|
10
|
+
* explicitly ships them with a scenario-run trigger.
|
|
11
|
+
*/
|
|
12
|
+
import type { TargetAuthConfig, WorkosMode } from "./types.js";
|
|
13
|
+
interface AuthConfigResponse {
|
|
14
|
+
applicationId: string;
|
|
15
|
+
name: string;
|
|
16
|
+
type: string;
|
|
17
|
+
authType: string;
|
|
18
|
+
useEphemeralCreds: boolean;
|
|
19
|
+
oauth: {
|
|
20
|
+
provider: "workos";
|
|
21
|
+
clientId: string;
|
|
22
|
+
domain: string;
|
|
23
|
+
mode: WorkosMode;
|
|
24
|
+
scopes: string[];
|
|
25
|
+
} | null;
|
|
26
|
+
hint?: string;
|
|
27
|
+
error?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function fetchAuthConfig(applicationId: string, sessionName?: string): Promise<AuthConfigResponse>;
|
|
30
|
+
/**
|
|
31
|
+
* Adapt the platform's auth-config response into the local TargetAuthConfig
|
|
32
|
+
* shape that the existing PKCE flow consumes. Throws when the application
|
|
33
|
+
* isn't OAuth-PKCE-shaped (e.g., static_token, client_credentials) — the
|
|
34
|
+
* caller should give a useful error and direct the user elsewhere.
|
|
35
|
+
*/
|
|
36
|
+
export declare function adaptToWorkosConfig(resp: AuthConfigResponse): TargetAuthConfig;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches an Application's auth config from the ZIVIS platform.
|
|
3
|
+
*
|
|
4
|
+
* Phase J.4: replaces the local `~/.config/zivis/target-configs/*.json`
|
|
5
|
+
* file the user previously had to write by hand. The Application's IdP
|
|
6
|
+
* discovery (clientId, domain, mode, scopes) lives on the Application
|
|
7
|
+
* record on the platform; the CLI calls this endpoint to learn how to
|
|
8
|
+
* PKCE-auth, then runs the flow locally and stores tokens in the user's
|
|
9
|
+
* keychain. Tokens never leave the user's machine unless the user
|
|
10
|
+
* explicitly ships them with a scenario-run trigger.
|
|
11
|
+
*/
|
|
12
|
+
import { ApiClient } from "@zivis-ai/mcp-security/api-client";
|
|
13
|
+
import { DEFAULT_CONFIG } from "@zivis-ai/mcp-security/types";
|
|
14
|
+
export async function fetchAuthConfig(applicationId, sessionName) {
|
|
15
|
+
const config = sessionName
|
|
16
|
+
? { ...DEFAULT_CONFIG, session: sessionName }
|
|
17
|
+
: DEFAULT_CONFIG;
|
|
18
|
+
const client = new ApiClient(config);
|
|
19
|
+
return client.request("GET", `/api/applications/${encodeURIComponent(applicationId)}/auth-config`);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Adapt the platform's auth-config response into the local TargetAuthConfig
|
|
23
|
+
* shape that the existing PKCE flow consumes. Throws when the application
|
|
24
|
+
* isn't OAuth-PKCE-shaped (e.g., static_token, client_credentials) — the
|
|
25
|
+
* caller should give a useful error and direct the user elsewhere.
|
|
26
|
+
*/
|
|
27
|
+
export function adaptToWorkosConfig(resp) {
|
|
28
|
+
if (!resp.oauth) {
|
|
29
|
+
throw new Error(resp.hint || resp.error ||
|
|
30
|
+
`Application ${resp.applicationId} (${resp.authType}) is not configured for PKCE auth`);
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
type: "workos",
|
|
34
|
+
clientId: resp.oauth.clientId,
|
|
35
|
+
domain: resp.oauth.domain,
|
|
36
|
+
mode: resp.oauth.mode,
|
|
37
|
+
extraScopes: resp.oauth.scopes,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=api-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-config.js","sourceRoot":"","sources":["../../../src/internal/target-auth/api-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAoB9D,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,aAAqB,EACrB,WAAoB;IAEpB,MAAM,MAAM,GAAG,WAAW;QACxB,CAAC,CAAC,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE;QAC7C,CAAC,CAAC,cAAc,CAAC;IACnB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC,OAAO,CACnB,KAAK,EACL,qBAAqB,kBAAkB,CAAC,aAAa,CAAC,cAAc,CACrE,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAwB;IAC1D,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK;YACrB,eAAe,IAAI,CAAC,aAAa,KAAK,IAAI,CAAC,QAAQ,mCAAmC,CACzF,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ;QAC7B,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;QACzB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;QACrB,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;KAC/B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Target-auth config storage (local-only, v1).
|
|
3
|
+
*
|
|
4
|
+
* Per-target IdP config (domain, client_id, mode, callback port) lives under
|
|
5
|
+
* `~/.config/zivis/target-configs/<targetId>.json`. This is *config*, not
|
|
6
|
+
* credentials — safe to commit a sanitized version to your repo if you want
|
|
7
|
+
* teammates to share it.
|
|
8
|
+
*
|
|
9
|
+
* v2: ZIVIS will serve target-auth config from the API so any team member's
|
|
10
|
+
* CLI can discover it. For now, configure once locally with `zivis target
|
|
11
|
+
* configure` and check in the file if you want it shared.
|
|
12
|
+
*/
|
|
13
|
+
import type { TargetAuthConfig } from "./types.js";
|
|
14
|
+
export declare function loadTargetConfig(targetId: string): Promise<TargetAuthConfig | null>;
|
|
15
|
+
export declare function saveTargetConfig(targetId: string, cfg: TargetAuthConfig): Promise<string>;
|
|
16
|
+
export declare function listTargetConfigs(): Promise<Array<{
|
|
17
|
+
targetId: string;
|
|
18
|
+
type: string;
|
|
19
|
+
}>>;
|
|
20
|
+
export declare function getConfigPath(targetId: string): string;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Target-auth config storage (local-only, v1).
|
|
3
|
+
*
|
|
4
|
+
* Per-target IdP config (domain, client_id, mode, callback port) lives under
|
|
5
|
+
* `~/.config/zivis/target-configs/<targetId>.json`. This is *config*, not
|
|
6
|
+
* credentials — safe to commit a sanitized version to your repo if you want
|
|
7
|
+
* teammates to share it.
|
|
8
|
+
*
|
|
9
|
+
* v2: ZIVIS will serve target-auth config from the API so any team member's
|
|
10
|
+
* CLI can discover it. For now, configure once locally with `zivis target
|
|
11
|
+
* configure` and check in the file if you want it shared.
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from "node:fs/promises";
|
|
14
|
+
import * as path from "node:path";
|
|
15
|
+
import * as os from "node:os";
|
|
16
|
+
function configDir() {
|
|
17
|
+
return path.join(os.homedir(), ".config", "zivis", "target-configs");
|
|
18
|
+
}
|
|
19
|
+
function configPath(targetId) {
|
|
20
|
+
return path.join(configDir(), `${targetId}.json`);
|
|
21
|
+
}
|
|
22
|
+
export async function loadTargetConfig(targetId) {
|
|
23
|
+
try {
|
|
24
|
+
const raw = await fs.readFile(configPath(targetId), "utf8");
|
|
25
|
+
return JSON.parse(raw);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export async function saveTargetConfig(targetId, cfg) {
|
|
32
|
+
await fs.mkdir(configDir(), { recursive: true, mode: 0o700 });
|
|
33
|
+
const p = configPath(targetId);
|
|
34
|
+
await fs.writeFile(p, JSON.stringify(cfg, null, 2) + "\n", { mode: 0o600 });
|
|
35
|
+
return p;
|
|
36
|
+
}
|
|
37
|
+
export async function listTargetConfigs() {
|
|
38
|
+
try {
|
|
39
|
+
const entries = await fs.readdir(configDir());
|
|
40
|
+
const out = [];
|
|
41
|
+
for (const name of entries) {
|
|
42
|
+
if (!name.endsWith(".json"))
|
|
43
|
+
continue;
|
|
44
|
+
const targetId = name.slice(0, -".json".length);
|
|
45
|
+
const cfg = await loadTargetConfig(targetId);
|
|
46
|
+
if (cfg)
|
|
47
|
+
out.push({ targetId, type: cfg.type });
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export function getConfigPath(targetId) {
|
|
56
|
+
return configPath(targetId);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/internal/target-auth/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAG9B,SAAS,SAAS;IAChB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,UAAU,CAAC,QAAgB;IAClC,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,GAAG,QAAQ,OAAO,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IACrD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;QAC5D,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAqB,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,QAAgB,EAChB,GAAqB;IAErB,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9D,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC/B,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5E,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QAC9C,MAAM,GAAG,GAA8C,EAAE,CAAC;QAC1D,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,SAAS;YACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAChD,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAC7C,IAAI,GAAG;gBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Target-auth orchestrator: load config, run the right IdP flow, manage tokens.
|
|
3
|
+
*
|
|
4
|
+
* Public API:
|
|
5
|
+
* getValidTargetToken(targetId, persona) — returns access_token; refreshes if near expiry
|
|
6
|
+
* loginTarget(targetId, persona) — runs the appropriate IdP flow
|
|
7
|
+
* logoutTarget(targetId, persona) — clears stored tokens
|
|
8
|
+
*
|
|
9
|
+
* Designed so RT-runner-side ephemeral cred plumbing only sees a flat
|
|
10
|
+
* { accessToken, refreshToken?, expiresAt, idpType } bundle — no IdP
|
|
11
|
+
* specifics leak past this boundary.
|
|
12
|
+
*/
|
|
13
|
+
import type { EphemeralTargetCreds, TargetTokens } from "./types.js";
|
|
14
|
+
export declare function loginTarget(targetId: string, persona: string): Promise<TargetTokens>;
|
|
15
|
+
/**
|
|
16
|
+
* J.4 path: log in against an Application by id. Auth config comes from
|
|
17
|
+
* the platform (no local config file required). Tokens are stored under
|
|
18
|
+
* the existing keychain namespace using applicationId as the key — same
|
|
19
|
+
* keychain layout, no migration needed for already-stored tokens.
|
|
20
|
+
*/
|
|
21
|
+
export declare function loginApplication(applicationId: string, persona: string, sessionName?: string): Promise<TargetTokens>;
|
|
22
|
+
export declare function logoutTarget(targetId: string, persona: string): Promise<void>;
|
|
23
|
+
export declare function getValidTargetToken(targetId: string, persona: string): Promise<TargetTokens | null>;
|
|
24
|
+
export declare function getEphemeralCreds(targetId: string, persona: string): Promise<EphemeralTargetCreds | null>;
|
|
25
|
+
export declare function tokenInfo(targetId: string, persona: string): Promise<{
|
|
26
|
+
valid: boolean;
|
|
27
|
+
expiresAt: string | null;
|
|
28
|
+
secondsRemaining: number;
|
|
29
|
+
hasRefresh: boolean;
|
|
30
|
+
} | null>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Target-auth orchestrator: load config, run the right IdP flow, manage tokens.
|
|
3
|
+
*
|
|
4
|
+
* Public API:
|
|
5
|
+
* getValidTargetToken(targetId, persona) — returns access_token; refreshes if near expiry
|
|
6
|
+
* loginTarget(targetId, persona) — runs the appropriate IdP flow
|
|
7
|
+
* logoutTarget(targetId, persona) — clears stored tokens
|
|
8
|
+
*
|
|
9
|
+
* Designed so RT-runner-side ephemeral cred plumbing only sees a flat
|
|
10
|
+
* { accessToken, refreshToken?, expiresAt, idpType } bundle — no IdP
|
|
11
|
+
* specifics leak past this boundary.
|
|
12
|
+
*/
|
|
13
|
+
import { loadTargetConfig } from "./config.js";
|
|
14
|
+
import { loadTokens, storeTokens, deleteTokens } from "./keychain.js";
|
|
15
|
+
import { loginWorkos, refreshWorkos } from "./workos.js";
|
|
16
|
+
import { fetchAuthConfig, adaptToWorkosConfig } from "./api-config.js";
|
|
17
|
+
const REFRESH_BUFFER_MS = 5 * 60 * 1000;
|
|
18
|
+
export async function loginTarget(targetId, persona) {
|
|
19
|
+
const cfg = await mustLoadConfig(targetId);
|
|
20
|
+
const tokens = await runLogin(cfg, persona);
|
|
21
|
+
await storeTokens(targetId, persona, tokens);
|
|
22
|
+
return tokens;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* J.4 path: log in against an Application by id. Auth config comes from
|
|
26
|
+
* the platform (no local config file required). Tokens are stored under
|
|
27
|
+
* the existing keychain namespace using applicationId as the key — same
|
|
28
|
+
* keychain layout, no migration needed for already-stored tokens.
|
|
29
|
+
*/
|
|
30
|
+
export async function loginApplication(applicationId, persona, sessionName) {
|
|
31
|
+
const resp = await fetchAuthConfig(applicationId, sessionName);
|
|
32
|
+
const cfg = adaptToWorkosConfig(resp);
|
|
33
|
+
const tokens = await runLogin(cfg, persona);
|
|
34
|
+
await storeTokens(applicationId, persona, tokens);
|
|
35
|
+
return tokens;
|
|
36
|
+
}
|
|
37
|
+
export async function logoutTarget(targetId, persona) {
|
|
38
|
+
await deleteTokens(targetId, persona);
|
|
39
|
+
}
|
|
40
|
+
export async function getValidTargetToken(targetId, persona) {
|
|
41
|
+
const tokens = await loadTokens(targetId, persona);
|
|
42
|
+
if (!tokens)
|
|
43
|
+
return null;
|
|
44
|
+
if (tokens.expires_at > Date.now() + REFRESH_BUFFER_MS) {
|
|
45
|
+
return tokens;
|
|
46
|
+
}
|
|
47
|
+
if (!tokens.refresh_token)
|
|
48
|
+
return null;
|
|
49
|
+
const cfg = await mustLoadConfig(targetId);
|
|
50
|
+
const fresh = await runRefresh(cfg, tokens.refresh_token);
|
|
51
|
+
await storeTokens(targetId, persona, fresh);
|
|
52
|
+
return fresh;
|
|
53
|
+
}
|
|
54
|
+
export async function getEphemeralCreds(targetId, persona) {
|
|
55
|
+
const tokens = await getValidTargetToken(targetId, persona);
|
|
56
|
+
if (!tokens)
|
|
57
|
+
return null;
|
|
58
|
+
const cfg = await loadTargetConfig(targetId);
|
|
59
|
+
return {
|
|
60
|
+
idpType: (cfg?.type ?? "none"),
|
|
61
|
+
accessToken: tokens.access_token,
|
|
62
|
+
refreshToken: tokens.refresh_token,
|
|
63
|
+
expiresAt: tokens.expires_at,
|
|
64
|
+
persona,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export async function tokenInfo(targetId, persona) {
|
|
68
|
+
const tokens = await loadTokens(targetId, persona);
|
|
69
|
+
if (!tokens)
|
|
70
|
+
return null;
|
|
71
|
+
return {
|
|
72
|
+
valid: tokens.expires_at > Date.now() + REFRESH_BUFFER_MS,
|
|
73
|
+
expiresAt: new Date(tokens.expires_at).toISOString(),
|
|
74
|
+
secondsRemaining: Math.round((tokens.expires_at - Date.now()) / 1000),
|
|
75
|
+
hasRefresh: !!tokens.refresh_token,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async function mustLoadConfig(targetId) {
|
|
79
|
+
const cfg = await loadTargetConfig(targetId);
|
|
80
|
+
if (!cfg) {
|
|
81
|
+
throw new Error(`No auth config for target ${targetId}. Run: zivis target configure ${targetId} --type workos --client-id <id> --domain <host>`);
|
|
82
|
+
}
|
|
83
|
+
return cfg;
|
|
84
|
+
}
|
|
85
|
+
async function runLogin(cfg, persona) {
|
|
86
|
+
switch (cfg.type) {
|
|
87
|
+
case "workos":
|
|
88
|
+
return loginWorkos(cfg, persona);
|
|
89
|
+
default:
|
|
90
|
+
throw new Error(`Unsupported IdP type: ${cfg.type}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async function runRefresh(cfg, refreshToken) {
|
|
94
|
+
switch (cfg.type) {
|
|
95
|
+
case "workos":
|
|
96
|
+
return refreshWorkos(cfg, refreshToken);
|
|
97
|
+
default:
|
|
98
|
+
throw new Error(`Unsupported IdP type: ${cfg.type}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/internal/target-auth/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Target-auth keychain.
|
|
3
|
+
*
|
|
4
|
+
* Distinct namespace from the user's ZIVIS-platform tokens (handled by
|
|
5
|
+
* `zivis-mcp-security`'s keychain module). A user can be logged into
|
|
6
|
+
* ZIVIS itself AND to N customer-target IdPs simultaneously, each with
|
|
7
|
+
* multiple personas (admin, user_a, …) for permutation testing.
|
|
8
|
+
*
|
|
9
|
+
* Storage layout
|
|
10
|
+
* service: zivis.target.<targetId>.<persona>
|
|
11
|
+
* account: zivis-target
|
|
12
|
+
* value: JSON-serialised TargetTokens
|
|
13
|
+
*
|
|
14
|
+
* macOS-only for v1 (matches the engagement helper). Linux/Windows fall
|
|
15
|
+
* back to an encrypted file on disk; the underlying impl lives in
|
|
16
|
+
* `@zivis-ai/mcp-security/auth/keychain.ts` for the platform login — we
|
|
17
|
+
* deliberately don't share that module to keep the namespaces isolated.
|
|
18
|
+
*/
|
|
19
|
+
import type { TargetTokens } from "./types.js";
|
|
20
|
+
export declare function storeTokens(targetId: string, persona: string, tokens: TargetTokens): Promise<void>;
|
|
21
|
+
export declare function loadTokens(targetId: string, persona: string): Promise<TargetTokens | null>;
|
|
22
|
+
export declare function deleteTokens(targetId: string, persona: string): Promise<void>;
|
|
23
|
+
export declare function getStorageName(): string;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Target-auth keychain.
|
|
3
|
+
*
|
|
4
|
+
* Distinct namespace from the user's ZIVIS-platform tokens (handled by
|
|
5
|
+
* `zivis-mcp-security`'s keychain module). A user can be logged into
|
|
6
|
+
* ZIVIS itself AND to N customer-target IdPs simultaneously, each with
|
|
7
|
+
* multiple personas (admin, user_a, …) for permutation testing.
|
|
8
|
+
*
|
|
9
|
+
* Storage layout
|
|
10
|
+
* service: zivis.target.<targetId>.<persona>
|
|
11
|
+
* account: zivis-target
|
|
12
|
+
* value: JSON-serialised TargetTokens
|
|
13
|
+
*
|
|
14
|
+
* macOS-only for v1 (matches the engagement helper). Linux/Windows fall
|
|
15
|
+
* back to an encrypted file on disk; the underlying impl lives in
|
|
16
|
+
* `@zivis-ai/mcp-security/auth/keychain.ts` for the platform login — we
|
|
17
|
+
* deliberately don't share that module to keep the namespaces isolated.
|
|
18
|
+
*/
|
|
19
|
+
import { execFile } from "node:child_process";
|
|
20
|
+
import { promisify } from "node:util";
|
|
21
|
+
import * as fs from "node:fs/promises";
|
|
22
|
+
import * as path from "node:path";
|
|
23
|
+
import * as os from "node:os";
|
|
24
|
+
import * as crypto from "node:crypto";
|
|
25
|
+
const execFileAsync = promisify(execFile);
|
|
26
|
+
const SERVICE_PREFIX = "zivis.target";
|
|
27
|
+
const ACCOUNT = "zivis-target";
|
|
28
|
+
function svc(targetId, persona) {
|
|
29
|
+
return `${SERVICE_PREFIX}.${targetId}.${persona}`;
|
|
30
|
+
}
|
|
31
|
+
function fallbackPath(targetId, persona) {
|
|
32
|
+
const dir = path.join(os.homedir(), ".config", "zivis", "target-tokens");
|
|
33
|
+
return path.join(dir, `${targetId}.${persona}.enc`);
|
|
34
|
+
}
|
|
35
|
+
function fallbackKey() {
|
|
36
|
+
// Same scheme as the platform-side keychain fallback: derive from username.
|
|
37
|
+
return new Uint8Array(crypto.scryptSync(os.userInfo().username || "zivis", "zivis-target-salt", 32));
|
|
38
|
+
}
|
|
39
|
+
async function macStore(targetId, persona, value) {
|
|
40
|
+
try {
|
|
41
|
+
await execFileAsync("security", [
|
|
42
|
+
"delete-generic-password", "-a", ACCOUNT, "-s", svc(targetId, persona),
|
|
43
|
+
]);
|
|
44
|
+
}
|
|
45
|
+
catch { /* not present */ }
|
|
46
|
+
await execFileAsync("security", [
|
|
47
|
+
"add-generic-password", "-a", ACCOUNT, "-s", svc(targetId, persona), "-w", value,
|
|
48
|
+
]);
|
|
49
|
+
}
|
|
50
|
+
async function macRead(targetId, persona) {
|
|
51
|
+
try {
|
|
52
|
+
const { stdout } = await execFileAsync("security", [
|
|
53
|
+
"find-generic-password", "-a", ACCOUNT, "-s", svc(targetId, persona), "-w",
|
|
54
|
+
]);
|
|
55
|
+
return stdout.trim();
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async function macDelete(targetId, persona) {
|
|
62
|
+
try {
|
|
63
|
+
await execFileAsync("security", [
|
|
64
|
+
"delete-generic-password", "-a", ACCOUNT, "-s", svc(targetId, persona),
|
|
65
|
+
]);
|
|
66
|
+
}
|
|
67
|
+
catch { /* not present */ }
|
|
68
|
+
}
|
|
69
|
+
async function fileStore(targetId, persona, value) {
|
|
70
|
+
const p = fallbackPath(targetId, persona);
|
|
71
|
+
await fs.mkdir(path.dirname(p), { recursive: true, mode: 0o700 });
|
|
72
|
+
const iv = new Uint8Array(crypto.randomBytes(16));
|
|
73
|
+
const cipher = crypto.createCipheriv("aes-256-gcm", fallbackKey(), iv);
|
|
74
|
+
const encUpdate = new Uint8Array(cipher.update(value, "utf8"));
|
|
75
|
+
const encFinal = new Uint8Array(cipher.final());
|
|
76
|
+
const tag = new Uint8Array(cipher.getAuthTag());
|
|
77
|
+
const out = new Uint8Array(iv.length + tag.length + encUpdate.length + encFinal.length);
|
|
78
|
+
out.set(iv, 0);
|
|
79
|
+
out.set(tag, iv.length);
|
|
80
|
+
out.set(encUpdate, iv.length + tag.length);
|
|
81
|
+
out.set(encFinal, iv.length + tag.length + encUpdate.length);
|
|
82
|
+
await fs.writeFile(p, out, { mode: 0o600 });
|
|
83
|
+
}
|
|
84
|
+
async function fileRead(targetId, persona) {
|
|
85
|
+
try {
|
|
86
|
+
const p = fallbackPath(targetId, persona);
|
|
87
|
+
const buf = new Uint8Array(await fs.readFile(p));
|
|
88
|
+
const iv = buf.subarray(0, 16);
|
|
89
|
+
const tag = buf.subarray(16, 32);
|
|
90
|
+
const enc = buf.subarray(32);
|
|
91
|
+
const decipher = crypto.createDecipheriv("aes-256-gcm", fallbackKey(), iv);
|
|
92
|
+
decipher.setAuthTag(tag);
|
|
93
|
+
const decUpdate = new Uint8Array(decipher.update(enc));
|
|
94
|
+
const decFinal = new Uint8Array(decipher.final());
|
|
95
|
+
const dec = new Uint8Array(decUpdate.length + decFinal.length);
|
|
96
|
+
dec.set(decUpdate, 0);
|
|
97
|
+
dec.set(decFinal, decUpdate.length);
|
|
98
|
+
return Buffer.from(dec).toString("utf8");
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async function fileDelete(targetId, persona) {
|
|
105
|
+
try {
|
|
106
|
+
await fs.unlink(fallbackPath(targetId, persona));
|
|
107
|
+
}
|
|
108
|
+
catch { /* not present */ }
|
|
109
|
+
}
|
|
110
|
+
async function tryMac() {
|
|
111
|
+
if (process.platform !== "darwin")
|
|
112
|
+
return false;
|
|
113
|
+
try {
|
|
114
|
+
await execFileAsync("which", ["security"]);
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
export async function storeTokens(targetId, persona, tokens) {
|
|
122
|
+
const value = JSON.stringify(tokens);
|
|
123
|
+
if (await tryMac())
|
|
124
|
+
return macStore(targetId, persona, value);
|
|
125
|
+
return fileStore(targetId, persona, value);
|
|
126
|
+
}
|
|
127
|
+
export async function loadTokens(targetId, persona) {
|
|
128
|
+
const raw = (await tryMac())
|
|
129
|
+
? await macRead(targetId, persona)
|
|
130
|
+
: await fileRead(targetId, persona);
|
|
131
|
+
if (!raw)
|
|
132
|
+
return null;
|
|
133
|
+
try {
|
|
134
|
+
return JSON.parse(raw);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
export async function deleteTokens(targetId, persona) {
|
|
141
|
+
if (await tryMac())
|
|
142
|
+
return macDelete(targetId, persona);
|
|
143
|
+
return fileDelete(targetId, persona);
|
|
144
|
+
}
|
|
145
|
+
export function getStorageName() {
|
|
146
|
+
return process.platform === "darwin"
|
|
147
|
+
? "macOS Keychain"
|
|
148
|
+
: "encrypted file (~/.config/zivis/target-tokens)";
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=keychain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keychain.js","sourceRoot":"","sources":["../../../src/internal/target-auth/keychain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Target-auth: PKCE auth flows against the *customer's* identity provider.
|
|
3
|
+
*
|
|
4
|
+
* The user authenticates locally against the target system's IdP. Tokens
|
|
5
|
+
* stay in the user's OS keychain. When a scenario run is triggered, the
|
|
6
|
+
* CLI ships a short-lived access token (and optionally a refresh token)
|
|
7
|
+
* to the ZIVIS platform, which uses it for the duration of the run only.
|
|
8
|
+
* ZIVIS never persists target-system credentials.
|
|
9
|
+
*/
|
|
10
|
+
export type IdpType = "workos" | "auth0" | "apikey" | "none";
|
|
11
|
+
/** WorkOS path layout — three observed flavors. */
|
|
12
|
+
export type WorkosMode = "user_management" | "authkit" | "workos";
|
|
13
|
+
export interface WorkosConfig {
|
|
14
|
+
type: "workos";
|
|
15
|
+
/** WorkOS client_id (AuthKit application). */
|
|
16
|
+
clientId: string;
|
|
17
|
+
/**
|
|
18
|
+
* Auth host. e.g. `api.workos.com` (user_management/legacy) or
|
|
19
|
+
* `<custom>.authkit.app` (custom AuthKit domain).
|
|
20
|
+
*/
|
|
21
|
+
domain: string;
|
|
22
|
+
/** Path layout flavor. Defaults to `user_management`. */
|
|
23
|
+
mode?: WorkosMode;
|
|
24
|
+
/** localhost callback port for the PKCE redirect. Defaults to 5174. */
|
|
25
|
+
callbackPort?: number;
|
|
26
|
+
/** Extra OAuth scopes beyond `openid profile email offline_access`. */
|
|
27
|
+
extraScopes?: string[];
|
|
28
|
+
}
|
|
29
|
+
export type TargetAuthConfig = WorkosConfig;
|
|
30
|
+
export interface TargetTokens {
|
|
31
|
+
/** OAuth access token. */
|
|
32
|
+
access_token: string;
|
|
33
|
+
/** OAuth refresh token, if the IdP issued one. */
|
|
34
|
+
refresh_token?: string;
|
|
35
|
+
/** Unix-ms expiry, derived from JWT exp claim or `expires_in`. */
|
|
36
|
+
expires_at: number;
|
|
37
|
+
/** Optional id_token for client-side claim inspection. */
|
|
38
|
+
id_token?: string;
|
|
39
|
+
/** When this token bundle was obtained (unix-ms). */
|
|
40
|
+
obtained_at: number;
|
|
41
|
+
}
|
|
42
|
+
/** Bundle shipped to ZIVIS on `scenario run` — RT consumes ephemerally. */
|
|
43
|
+
export interface EphemeralTargetCreds {
|
|
44
|
+
idpType: IdpType;
|
|
45
|
+
accessToken: string;
|
|
46
|
+
refreshToken?: string;
|
|
47
|
+
/** Unix-ms expiry of the access token. */
|
|
48
|
+
expiresAt: number;
|
|
49
|
+
/** Echo of the persona, useful for audit logs. */
|
|
50
|
+
persona?: string;
|
|
51
|
+
}
|