@geminixiang/mikan 1.0.0-beta.77 → 1.0.0-beta.78
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/CHANGELOG.md +19 -0
- package/dist/adapters/web/login/oauth.d.ts.map +1 -1
- package/dist/adapters/web/login/oauth.js +3 -2
- package/dist/adapters/web/login/oauth.js.map +1 -1
- package/dist/adapters/web/login/portal.js +3 -2
- package/dist/adapters/web/login/portal.js.map +1 -1
- package/dist/cli/boot.d.ts.map +1 -1
- package/dist/cli/boot.js +3 -1
- package/dist/cli/boot.js.map +1 -1
- package/dist/cli/sandbox.d.ts +3 -0
- package/dist/cli/sandbox.d.ts.map +1 -0
- package/dist/cli/sandbox.js +79 -0
- package/dist/cli/sandbox.js.map +1 -0
- package/dist/cli/types.d.ts +2 -1
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli/types.js.map +1 -1
- package/dist/harness/index.d.ts +4 -0
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +4 -0
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/mcp-result.d.ts +20 -0
- package/dist/harness/mcp-result.d.ts.map +1 -0
- package/dist/harness/mcp-result.js +171 -0
- package/dist/harness/mcp-result.js.map +1 -0
- package/dist/harness/mcp.d.ts.map +1 -1
- package/dist/harness/mcp.js +7 -32
- package/dist/harness/mcp.js.map +1 -1
- package/dist/harness/presenter.d.ts +1 -0
- package/dist/harness/presenter.d.ts.map +1 -1
- package/dist/harness/presenter.js +1 -1
- package/dist/harness/presenter.js.map +1 -1
- package/dist/harness/prompt.js +1 -1
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +8 -3
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/tools/pi-tools.d.ts +1 -0
- package/dist/harness/tools/pi-tools.d.ts.map +1 -1
- package/dist/harness/tools/pi-tools.js +1 -1
- package/dist/harness/tools/pi-tools.js.map +1 -1
- package/dist/harness/types.d.ts +1 -1
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/main.js +7 -5
- package/dist/main.js.map +1 -1
- package/dist/memory-capture/index.d.ts +16 -0
- package/dist/memory-capture/index.d.ts.map +1 -0
- package/dist/memory-capture/index.js +194 -0
- package/dist/memory-capture/index.js.map +1 -0
- package/dist/memory-capture/types.d.ts +27 -0
- package/dist/memory-capture/types.d.ts.map +1 -0
- package/dist/memory-capture/types.js.map +1 -0
- package/dist/observability/types.d.ts +1 -1
- package/dist/observability/types.d.ts.map +1 -1
- package/dist/observability/types.js.map +1 -1
- package/dist/office/index.d.ts.map +1 -1
- package/dist/office/index.js +2 -1
- package/dist/office/index.js.map +1 -1
- package/dist/office/projection.d.ts.map +1 -1
- package/dist/office/projection.js +5 -4
- package/dist/office/projection.js.map +1 -1
- package/dist/runtime/conversation-runtime.d.ts.map +1 -1
- package/dist/runtime/conversation-runtime.js +16 -59
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +2 -1
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sandbox/cloudflare.d.ts.map +1 -1
- package/dist/sandbox/cloudflare.js +2 -1
- package/dist/sandbox/cloudflare.js.map +1 -1
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +21 -14
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +2 -1
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/layout.d.ts +7 -0
- package/dist/sandbox/layout.d.ts.map +1 -0
- package/dist/sandbox/layout.js +13 -0
- package/dist/sandbox/layout.js.map +1 -0
- package/dist/sandbox/provisioner.d.ts +24 -4
- package/dist/sandbox/provisioner.d.ts.map +1 -1
- package/dist/sandbox/provisioner.js +210 -20
- package/dist/sandbox/provisioner.js.map +1 -1
- package/dist/sessions/session-store.d.ts +1 -1
- package/dist/sessions/session-store.d.ts.map +1 -1
- package/dist/sessions/store.d.ts +0 -1
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +0 -31
- package/dist/sessions/store.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vault/index.d.ts.map +1 -1
- package/dist/vault/index.js +7 -6
- package/dist/vault/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/dream/index.d.ts +0 -20
- package/dist/dream/index.d.ts.map +0 -1
- package/dist/dream/index.js +0 -262
- package/dist/dream/index.js.map +0 -1
- package/dist/dream/types.d.ts +0 -30
- package/dist/dream/types.d.ts.map +0 -1
- package/dist/dream/types.js.map +0 -1
- /package/dist/{dream → memory-capture}/types.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,25 @@ any release.
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [1.0.0-beta.78]
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Capture durable knowledge after each settled human run: Jev gates the exchange, and the conversation's model adds or updates stamped lines under `## Captured knowledge` in the conversation `MEMORY.md`; configured secrets are redacted from captured entries (ADR 0011).
|
|
17
|
+
- Give each new managed image container a per-office home volume (`mikan-home-<key>`) at `/root`. A stopped container whose image or mounts are stale is recreated from the current image with the same volume, so `/root` survives image upgrades; running containers are never interrupted (ADR 0009).
|
|
18
|
+
- Add `mikan sandbox status|diff|migrate` to inspect managed containers and move legacy containers onto a home volume with the daemon stopped.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- Bound MCP tool results like `bash`: JSON is re-serialized compactly, oversized results become a structural digest (keys, counts, and pagination kept) within Pi's 50KB/2000-line limit, and the full result is spilled to `.mikan/mcp-output/` in the runtime workspace. `structuredContent` is used when `content` is empty, binary resources are no longer inlined, error text is bounded, and MCP results pass through secret redaction.
|
|
23
|
+
- Shared top-level channel sessions no longer rotate every two weeks; they stay current until `/new`, and Pi's automatic compaction bounds the model context (ADR 0010).
|
|
24
|
+
- The sandbox image installs its runtime outside `/root` and is published only with mikan releases.
|
|
25
|
+
- Document the Vault as the store for development credentials that sandbox programs read directly; OpenConnector is the path for third-party service access (ADR 0013).
|
|
26
|
+
|
|
27
|
+
### Removed
|
|
28
|
+
|
|
29
|
+
- Remove scheduled Dream memory maintenance. Conversation `MEMORY.md` is written only by the agent and by post-run memory capture; existing `dream.json` checkpoints are no longer read (ADR 0012).
|
|
30
|
+
|
|
12
31
|
## [1.0.0-beta.77]
|
|
13
32
|
|
|
14
33
|
### Added
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../../src/adapters/web/login/oauth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../../src/adapters/web/login/oauth.ts"],"names":[],"mappings":"AAKA,YAAY,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAoO/C,wBAAgB,gBAAgB,IAAI,YAAY,EAAE,CA4BjD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAM3E"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readEnv } from "../../../env-manifest.js";
|
|
2
2
|
import { isRecord, parseJsonValue } from "../../../file-guards.js";
|
|
3
3
|
import * as log from "../../../log.js";
|
|
4
|
+
import { guestHomePath } from "../../../sandbox/layout.js";
|
|
4
5
|
const DEFAULT_GOOGLE_WORKSPACE_CLI_SCOPES = [
|
|
5
6
|
"https://www.googleapis.com/auth/drive",
|
|
6
7
|
"https://mail.google.com/",
|
|
@@ -53,7 +54,7 @@ function getBuiltinOAuthServices() {
|
|
|
53
54
|
fileOutput: {
|
|
54
55
|
type: "authorized_user",
|
|
55
56
|
relativePath: "gws.json",
|
|
56
|
-
targetPath: "
|
|
57
|
+
targetPath: guestHomePath(".config/gws/credentials.json"),
|
|
57
58
|
},
|
|
58
59
|
},
|
|
59
60
|
{
|
|
@@ -73,7 +74,7 @@ function getBuiltinOAuthServices() {
|
|
|
73
74
|
fileOutput: {
|
|
74
75
|
type: "authorized_user",
|
|
75
76
|
relativePath: "gcloud-adc.json",
|
|
76
|
-
targetPath: "
|
|
77
|
+
targetPath: guestHomePath(".config/gcloud/application_default_credentials.json"),
|
|
77
78
|
envKey: "GOOGLE_APPLICATION_CREDENTIALS",
|
|
78
79
|
additionalEnvKeys: ["CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE"],
|
|
79
80
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../../src/adapters/web/login/oauth.ts"],"names":[],"mappings":"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","sourcesContent":["import { readEnv } from \"../../../env-manifest.js\";\nimport { isRecord, parseJsonValue } from \"../../../file-guards.js\";\nimport * as log from \"../../../log.js\";\n\nexport type { LoginCredentialKind, OAuthService } from \"./types.js\";\nimport type { OAuthService } from \"./types.js\";\n\nconst DEFAULT_GOOGLE_WORKSPACE_CLI_SCOPES = [\n \"https://www.googleapis.com/auth/drive\",\n \"https://mail.google.com/\",\n \"https://www.googleapis.com/auth/calendar\",\n \"https://www.googleapis.com/auth/spreadsheets\",\n \"https://www.googleapis.com/auth/documents\",\n \"https://www.googleapis.com/auth/chat.messages.create\",\n];\n\nconst DEFAULT_GOOGLE_CLOUD_SDK_SCOPES = [\n \"openid\",\n \"https://www.googleapis.com/auth/userinfo.email\",\n \"https://www.googleapis.com/auth/cloud-platform\",\n];\n\nconst DEFAULT_GITHUB_OAUTH_SCOPES = [\"repo\", \"read:user\", \"user:email\", \"read:org\", \"gist\"];\n\nfunction resolveScopesFromEnv(envKey: string, fallback: string[]): string[] {\n const raw = readEnv(envKey);\n if (!raw) return fallback;\n\n const scopes = raw.split(/[\\s,]+/).filter(Boolean);\n\n return scopes.length > 0 ? scopes : fallback;\n}\n\nfunction getBuiltinOAuthServices(): OAuthService[] {\n return [\n {\n id: \"github\",\n label: \"GitHub\",\n aliases: [\"github\", \"github_oauth\", \"gh_oauth\"],\n authorizationUrl: \"https://github.com/login/oauth/authorize\",\n tokenUrl: \"https://github.com/login/oauth/access_token\",\n scopes: resolveScopesFromEnv(\"GITHUB_OAUTH_SCOPES\", DEFAULT_GITHUB_OAUTH_SCOPES),\n clientIdEnvKey: \"GITHUB_OAUTH_CLIENT_ID\",\n clientSecretEnvKey: \"GITHUB_OAUTH_CLIENT_SECRET\",\n accessTokenEnvKeys: [\"GITHUB_OAUTH_ACCESS_TOKEN\", \"GH_TOKEN\"],\n refreshTokenEnvKey: \"GITHUB_OAUTH_REFRESH_TOKEN\",\n },\n {\n id: \"google_workspace_cli\",\n label: \"Google Workspace CLI\",\n aliases: [\"google_workspace_cli\", \"gws\", \"googleworkspace\", \"google-workspace-cli\"],\n authorizationUrl: \"https://accounts.google.com/o/oauth2/v2/auth\",\n tokenUrl: \"https://oauth2.googleapis.com/token\",\n scopes: resolveScopesFromEnv(\n \"GOOGLE_WORKSPACE_CLI_OAUTH_SCOPES\",\n DEFAULT_GOOGLE_WORKSPACE_CLI_SCOPES,\n ),\n clientIdEnvKey: \"GOOGLE_WORKSPACE_CLI_CLIENT_ID\",\n clientSecretEnvKey: \"GOOGLE_WORKSPACE_CLI_CLIENT_SECRET\",\n authorizationParams: {\n access_type: \"offline\",\n include_granted_scopes: \"true\",\n prompt: \"consent\",\n },\n fileOutput: {\n type: \"authorized_user\",\n relativePath: \"gws.json\",\n targetPath: \"/root/.config/gws/credentials.json\",\n },\n },\n {\n id: \"google_cloud_sdk\",\n label: \"Google Cloud SDK (gcloud)\",\n aliases: [\"google_cloud_sdk\", \"gcloud\", \"google-cloud-sdk\", \"google_cloud\", \"gcp\"],\n authorizationUrl: \"https://accounts.google.com/o/oauth2/v2/auth\",\n tokenUrl: \"https://oauth2.googleapis.com/token\",\n scopes: resolveScopesFromEnv(\n \"GOOGLE_CLOUD_SDK_OAUTH_SCOPES\",\n DEFAULT_GOOGLE_CLOUD_SDK_SCOPES,\n ),\n clientIdEnvKey: \"GOOGLE_CLOUD_SDK_CLIENT_ID\",\n clientSecretEnvKey: \"GOOGLE_CLOUD_SDK_CLIENT_SECRET\",\n authorizationParams: {\n access_type: \"offline\",\n include_granted_scopes: \"true\",\n prompt: \"consent\",\n },\n fileOutput: {\n type: \"authorized_user\",\n relativePath: \"gcloud-adc.json\",\n targetPath: \"/root/.config/gcloud/application_default_credentials.json\",\n envKey: \"GOOGLE_APPLICATION_CREDENTIALS\",\n additionalEnvKeys: [\"CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE\"],\n },\n },\n ];\n}\n\nfunction trimmedString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value.trim() : undefined;\n}\n\nfunction parseAccessTokenEnvKeys(\n value: Record<string, unknown>,\n index: number,\n id: string,\n): string[] | undefined | null {\n const keys = [trimmedString(value.accessTokenEnvKey)];\n for (const field of [\"additionalAccessTokenEnvKeys\", \"accessTokenEnvKeys\"] as const) {\n const parsed = parseStringArray(value[field], field, index, id);\n if (parsed === null) return null;\n keys.push(...(parsed ?? []).map((key) => key.trim()));\n }\n const unique = [...new Set(keys.filter((key): key is string => !!key))];\n return unique.length > 0 ? unique : undefined;\n}\n\nfunction parseFileOutput(\n value: unknown,\n index: number,\n id: string,\n): OAuthService[\"fileOutput\"] | null {\n if (!isRecord(value)) return undefined;\n const additionalEnvKeys = parseStringArray(\n value.additionalEnvKeys,\n \"fileOutput.additionalEnvKeys\",\n index,\n id,\n );\n if (additionalEnvKeys === null) return null;\n const relativePath = trimmedString(value.relativePath);\n if (trimmedString(value.type) !== \"authorized_user\" || !relativePath) return undefined;\n return {\n type: \"authorized_user\",\n relativePath,\n targetPath: trimmedString(value.targetPath),\n envKey: trimmedString(value.envKey),\n additionalEnvKeys,\n };\n}\n\nfunction parseOAuthService(value: unknown, index: number): OAuthService | null {\n if (!isRecord(value)) {\n log.logWarning(`Skipping OAUTH_SERVICES_JSON[${index}]: expected an object`);\n return null;\n }\n\n const id = trimmedString(value.id) ?? \"\";\n const label = trimmedString(value.label) ?? \"\";\n const authorizationUrl = trimmedString(value.authorizationUrl) ?? \"\";\n const tokenUrl = trimmedString(value.tokenUrl) ?? \"\";\n const clientIdEnvKey = trimmedString(value.clientIdEnvKey) ?? \"\";\n const clientSecretEnvKey = trimmedString(value.clientSecretEnvKey) ?? \"\";\n const missing = [\n [\"id\", id],\n [\"label\", label],\n [\"authorizationUrl\", authorizationUrl],\n [\"tokenUrl\", tokenUrl],\n [\"clientIdEnvKey\", clientIdEnvKey],\n [\"clientSecretEnvKey\", clientSecretEnvKey],\n ]\n .filter((entry) => !entry[1])\n .map((entry) => entry[0]);\n\n if (missing.length > 0) {\n const labelForLog = id ? ` (${id})` : \"\";\n log.logWarning(\n `Skipping OAUTH_SERVICES_JSON[${index}]${labelForLog}: missing ${missing.join(\", \")}`,\n );\n return null;\n }\n\n const aliases = parseStringArray(value.aliases, \"aliases\", index, id);\n if (aliases === null) return null;\n const scopes = parseStringArray(value.scopes, \"scopes\", index, id);\n if (scopes === null) return null;\n const authorizationParams = parseStringRecord(\n value.authorizationParams,\n \"authorizationParams\",\n index,\n id,\n );\n if (authorizationParams === null) return null;\n\n const accessTokenEnvKeys = parseAccessTokenEnvKeys(value, index, id);\n if (accessTokenEnvKeys === null) return null;\n const fileOutput = parseFileOutput(value.fileOutput, index, id);\n if (fileOutput === null) return null;\n\n return {\n id: id.toLowerCase(),\n label,\n aliases: aliases?.map((v) => v.toLowerCase()) ?? [id.toLowerCase()],\n authorizationUrl,\n tokenUrl,\n scopes: scopes ?? [],\n clientIdEnvKey,\n clientSecretEnvKey,\n accessTokenEnvKeys,\n refreshTokenEnvKey: trimmedString(value.refreshTokenEnvKey),\n authorizationParams: authorizationParams ?? undefined,\n fileOutput,\n };\n}\n\nfunction parseStringArray(\n value: unknown,\n field: string,\n index: number,\n id: string,\n): string[] | undefined | null {\n if (value === undefined) return undefined;\n if (!Array.isArray(value) || value.some((entry) => typeof entry !== \"string\")) {\n log.logWarning(`Skipping OAUTH_SERVICES_JSON[${index}] (${id}): ${field} must be strings`);\n return null;\n }\n return value;\n}\n\nfunction parseStringRecord(\n value: unknown,\n field: string,\n index: number,\n id: string,\n): Record<string, string> | undefined | null {\n if (value === undefined) return undefined;\n if (!isRecord(value) || Object.values(value).some((entry) => typeof entry !== \"string\")) {\n log.logWarning(`Skipping OAUTH_SERVICES_JSON[${index}] (${id}): ${field} must be strings`);\n return null;\n }\n return value as Record<string, string>;\n}\n\nexport function getOAuthServices(): OAuthService[] {\n const raw = readEnv(\"OAUTH_SERVICES_JSON\");\n const builtins = getBuiltinOAuthServices();\n if (!raw) return builtins;\n\n let parsed: unknown[];\n try {\n parsed = parseJsonValue(raw, Array.isArray, (detail) =>\n detail === \"unexpected JSON shape\"\n ? \"expected a JSON array of OAuth service definitions\"\n : detail,\n );\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n log.logWarning(\n detail === \"expected a JSON array of OAuth service definitions\"\n ? \"Ignoring OAUTH_SERVICES_JSON: expected a JSON array of OAuth service definitions\"\n : \"Ignoring OAUTH_SERVICES_JSON: invalid JSON\",\n detail,\n );\n return builtins;\n }\n\n const custom = parsed\n .map((serviceValue, index) => parseOAuthService(serviceValue, index))\n .filter((service): service is OAuthService => service !== null);\n const byId = new Map([...builtins, ...custom].map((service) => [service.id, service]));\n return [...byId.values()];\n}\n\nexport function resolveOAuthService(input: string): OAuthService | undefined {\n const normalized = input.trim().toLowerCase();\n if (!normalized) return undefined;\n return getOAuthServices().find(\n (service) => service.id === normalized || service.aliases.includes(normalized),\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../../src/adapters/web/login/oauth.ts"],"names":[],"mappings":"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","sourcesContent":["import { readEnv } from \"../../../env-manifest.js\";\nimport { isRecord, parseJsonValue } from \"../../../file-guards.js\";\nimport * as log from \"../../../log.js\";\nimport { guestHomePath } from \"../../../sandbox/layout.js\";\n\nexport type { LoginCredentialKind, OAuthService } from \"./types.js\";\nimport type { OAuthService } from \"./types.js\";\n\nconst DEFAULT_GOOGLE_WORKSPACE_CLI_SCOPES = [\n \"https://www.googleapis.com/auth/drive\",\n \"https://mail.google.com/\",\n \"https://www.googleapis.com/auth/calendar\",\n \"https://www.googleapis.com/auth/spreadsheets\",\n \"https://www.googleapis.com/auth/documents\",\n \"https://www.googleapis.com/auth/chat.messages.create\",\n];\n\nconst DEFAULT_GOOGLE_CLOUD_SDK_SCOPES = [\n \"openid\",\n \"https://www.googleapis.com/auth/userinfo.email\",\n \"https://www.googleapis.com/auth/cloud-platform\",\n];\n\nconst DEFAULT_GITHUB_OAUTH_SCOPES = [\"repo\", \"read:user\", \"user:email\", \"read:org\", \"gist\"];\n\nfunction resolveScopesFromEnv(envKey: string, fallback: string[]): string[] {\n const raw = readEnv(envKey);\n if (!raw) return fallback;\n\n const scopes = raw.split(/[\\s,]+/).filter(Boolean);\n\n return scopes.length > 0 ? scopes : fallback;\n}\n\nfunction getBuiltinOAuthServices(): OAuthService[] {\n return [\n {\n id: \"github\",\n label: \"GitHub\",\n aliases: [\"github\", \"github_oauth\", \"gh_oauth\"],\n authorizationUrl: \"https://github.com/login/oauth/authorize\",\n tokenUrl: \"https://github.com/login/oauth/access_token\",\n scopes: resolveScopesFromEnv(\"GITHUB_OAUTH_SCOPES\", DEFAULT_GITHUB_OAUTH_SCOPES),\n clientIdEnvKey: \"GITHUB_OAUTH_CLIENT_ID\",\n clientSecretEnvKey: \"GITHUB_OAUTH_CLIENT_SECRET\",\n accessTokenEnvKeys: [\"GITHUB_OAUTH_ACCESS_TOKEN\", \"GH_TOKEN\"],\n refreshTokenEnvKey: \"GITHUB_OAUTH_REFRESH_TOKEN\",\n },\n {\n id: \"google_workspace_cli\",\n label: \"Google Workspace CLI\",\n aliases: [\"google_workspace_cli\", \"gws\", \"googleworkspace\", \"google-workspace-cli\"],\n authorizationUrl: \"https://accounts.google.com/o/oauth2/v2/auth\",\n tokenUrl: \"https://oauth2.googleapis.com/token\",\n scopes: resolveScopesFromEnv(\n \"GOOGLE_WORKSPACE_CLI_OAUTH_SCOPES\",\n DEFAULT_GOOGLE_WORKSPACE_CLI_SCOPES,\n ),\n clientIdEnvKey: \"GOOGLE_WORKSPACE_CLI_CLIENT_ID\",\n clientSecretEnvKey: \"GOOGLE_WORKSPACE_CLI_CLIENT_SECRET\",\n authorizationParams: {\n access_type: \"offline\",\n include_granted_scopes: \"true\",\n prompt: \"consent\",\n },\n fileOutput: {\n type: \"authorized_user\",\n relativePath: \"gws.json\",\n targetPath: guestHomePath(\".config/gws/credentials.json\"),\n },\n },\n {\n id: \"google_cloud_sdk\",\n label: \"Google Cloud SDK (gcloud)\",\n aliases: [\"google_cloud_sdk\", \"gcloud\", \"google-cloud-sdk\", \"google_cloud\", \"gcp\"],\n authorizationUrl: \"https://accounts.google.com/o/oauth2/v2/auth\",\n tokenUrl: \"https://oauth2.googleapis.com/token\",\n scopes: resolveScopesFromEnv(\n \"GOOGLE_CLOUD_SDK_OAUTH_SCOPES\",\n DEFAULT_GOOGLE_CLOUD_SDK_SCOPES,\n ),\n clientIdEnvKey: \"GOOGLE_CLOUD_SDK_CLIENT_ID\",\n clientSecretEnvKey: \"GOOGLE_CLOUD_SDK_CLIENT_SECRET\",\n authorizationParams: {\n access_type: \"offline\",\n include_granted_scopes: \"true\",\n prompt: \"consent\",\n },\n fileOutput: {\n type: \"authorized_user\",\n relativePath: \"gcloud-adc.json\",\n targetPath: guestHomePath(\".config/gcloud/application_default_credentials.json\"),\n envKey: \"GOOGLE_APPLICATION_CREDENTIALS\",\n additionalEnvKeys: [\"CLOUDSDK_AUTH_CREDENTIAL_FILE_OVERRIDE\"],\n },\n },\n ];\n}\n\nfunction trimmedString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value.trim() : undefined;\n}\n\nfunction parseAccessTokenEnvKeys(\n value: Record<string, unknown>,\n index: number,\n id: string,\n): string[] | undefined | null {\n const keys = [trimmedString(value.accessTokenEnvKey)];\n for (const field of [\"additionalAccessTokenEnvKeys\", \"accessTokenEnvKeys\"] as const) {\n const parsed = parseStringArray(value[field], field, index, id);\n if (parsed === null) return null;\n keys.push(...(parsed ?? []).map((key) => key.trim()));\n }\n const unique = [...new Set(keys.filter((key): key is string => !!key))];\n return unique.length > 0 ? unique : undefined;\n}\n\nfunction parseFileOutput(\n value: unknown,\n index: number,\n id: string,\n): OAuthService[\"fileOutput\"] | null {\n if (!isRecord(value)) return undefined;\n const additionalEnvKeys = parseStringArray(\n value.additionalEnvKeys,\n \"fileOutput.additionalEnvKeys\",\n index,\n id,\n );\n if (additionalEnvKeys === null) return null;\n const relativePath = trimmedString(value.relativePath);\n if (trimmedString(value.type) !== \"authorized_user\" || !relativePath) return undefined;\n return {\n type: \"authorized_user\",\n relativePath,\n targetPath: trimmedString(value.targetPath),\n envKey: trimmedString(value.envKey),\n additionalEnvKeys,\n };\n}\n\nfunction parseOAuthService(value: unknown, index: number): OAuthService | null {\n if (!isRecord(value)) {\n log.logWarning(`Skipping OAUTH_SERVICES_JSON[${index}]: expected an object`);\n return null;\n }\n\n const id = trimmedString(value.id) ?? \"\";\n const label = trimmedString(value.label) ?? \"\";\n const authorizationUrl = trimmedString(value.authorizationUrl) ?? \"\";\n const tokenUrl = trimmedString(value.tokenUrl) ?? \"\";\n const clientIdEnvKey = trimmedString(value.clientIdEnvKey) ?? \"\";\n const clientSecretEnvKey = trimmedString(value.clientSecretEnvKey) ?? \"\";\n const missing = [\n [\"id\", id],\n [\"label\", label],\n [\"authorizationUrl\", authorizationUrl],\n [\"tokenUrl\", tokenUrl],\n [\"clientIdEnvKey\", clientIdEnvKey],\n [\"clientSecretEnvKey\", clientSecretEnvKey],\n ]\n .filter((entry) => !entry[1])\n .map((entry) => entry[0]);\n\n if (missing.length > 0) {\n const labelForLog = id ? ` (${id})` : \"\";\n log.logWarning(\n `Skipping OAUTH_SERVICES_JSON[${index}]${labelForLog}: missing ${missing.join(\", \")}`,\n );\n return null;\n }\n\n const aliases = parseStringArray(value.aliases, \"aliases\", index, id);\n if (aliases === null) return null;\n const scopes = parseStringArray(value.scopes, \"scopes\", index, id);\n if (scopes === null) return null;\n const authorizationParams = parseStringRecord(\n value.authorizationParams,\n \"authorizationParams\",\n index,\n id,\n );\n if (authorizationParams === null) return null;\n\n const accessTokenEnvKeys = parseAccessTokenEnvKeys(value, index, id);\n if (accessTokenEnvKeys === null) return null;\n const fileOutput = parseFileOutput(value.fileOutput, index, id);\n if (fileOutput === null) return null;\n\n return {\n id: id.toLowerCase(),\n label,\n aliases: aliases?.map((v) => v.toLowerCase()) ?? [id.toLowerCase()],\n authorizationUrl,\n tokenUrl,\n scopes: scopes ?? [],\n clientIdEnvKey,\n clientSecretEnvKey,\n accessTokenEnvKeys,\n refreshTokenEnvKey: trimmedString(value.refreshTokenEnvKey),\n authorizationParams: authorizationParams ?? undefined,\n fileOutput,\n };\n}\n\nfunction parseStringArray(\n value: unknown,\n field: string,\n index: number,\n id: string,\n): string[] | undefined | null {\n if (value === undefined) return undefined;\n if (!Array.isArray(value) || value.some((entry) => typeof entry !== \"string\")) {\n log.logWarning(`Skipping OAUTH_SERVICES_JSON[${index}] (${id}): ${field} must be strings`);\n return null;\n }\n return value;\n}\n\nfunction parseStringRecord(\n value: unknown,\n field: string,\n index: number,\n id: string,\n): Record<string, string> | undefined | null {\n if (value === undefined) return undefined;\n if (!isRecord(value) || Object.values(value).some((entry) => typeof entry !== \"string\")) {\n log.logWarning(`Skipping OAUTH_SERVICES_JSON[${index}] (${id}): ${field} must be strings`);\n return null;\n }\n return value as Record<string, string>;\n}\n\nexport function getOAuthServices(): OAuthService[] {\n const raw = readEnv(\"OAUTH_SERVICES_JSON\");\n const builtins = getBuiltinOAuthServices();\n if (!raw) return builtins;\n\n let parsed: unknown[];\n try {\n parsed = parseJsonValue(raw, Array.isArray, (detail) =>\n detail === \"unexpected JSON shape\"\n ? \"expected a JSON array of OAuth service definitions\"\n : detail,\n );\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n log.logWarning(\n detail === \"expected a JSON array of OAuth service definitions\"\n ? \"Ignoring OAUTH_SERVICES_JSON: expected a JSON array of OAuth service definitions\"\n : \"Ignoring OAUTH_SERVICES_JSON: invalid JSON\",\n detail,\n );\n return builtins;\n }\n\n const custom = parsed\n .map((serviceValue, index) => parseOAuthService(serviceValue, index))\n .filter((service): service is OAuthService => service !== null);\n const byId = new Map([...builtins, ...custom].map((service) => [service.id, service]));\n return [...byId.values()];\n}\n\nexport function resolveOAuthService(input: string): OAuthService | undefined {\n const normalized = input.trim().toLowerCase();\n if (!normalized) return undefined;\n return getOAuthServices().find(\n (service) => service.id === normalized || service.aliases.includes(normalized),\n );\n}\n"]}
|
|
@@ -1032,8 +1032,9 @@ async function handleLinkComplete(data, linkTokenStore, vaultManager, notify, re
|
|
|
1032
1032
|
try {
|
|
1033
1033
|
vaultManager.upsertEnv(linkToken.vaultId, updates);
|
|
1034
1034
|
if (sentryCliConfig) {
|
|
1035
|
-
|
|
1036
|
-
|
|
1035
|
+
const target = defaultVaultTargetPath(".sentryclirc");
|
|
1036
|
+
vaultManager.upsertFile(linkToken.vaultId, ".sentryclirc", sentryCliConfig, target);
|
|
1037
|
+
fileTargets.push(target);
|
|
1037
1038
|
}
|
|
1038
1039
|
}
|
|
1039
1040
|
catch (persistError) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portal.js","sourceRoot":"","sources":["../../../../src/adapters/web/login/portal.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes } from \"node:crypto\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { escapeHtml, readJsonBody, renderPortalShell, requestBaseUrl } from \"../portal-shell.js\";\nimport { resolveLinkBaseUrl } from \"../../../env-manifest.js\";\nimport { readEnv } from \"../../../env-manifest.js\";\nimport type { PlatformName } from \"../../index.js\";\nimport { InMemoryTokenStore } from \"../token-store.js\";\nimport type { LinkToken } from \"./types.js\";\nexport type { LinkToken } from \"./types.js\";\nimport {\n getOAuthServices,\n resolveOAuthService,\n type LoginCredentialKind,\n type OAuthService,\n} from \"./oauth.js\";\nimport * as log from \"../../../log.js\";\nimport { reportUserFacingError } from \"../../../observability/index.js\";\nimport { PRODUCT_NAME } from \"../../messages.js\";\nimport { defaultVaultTargetPath, type VaultManager } from \"../../../vault/index.js\";\n\nexport type { NotifyFn } from \"./types.js\";\n\nconst TTL_MS = 15 * 60 * 1000;\n\nexport class InMemoryLinkTokenStore extends InMemoryTokenStore<LinkToken> {\n create(\n platform: PlatformName,\n platformUserId: string,\n conversationId: string,\n vaultId: string,\n providerId: string,\n ): LinkToken {\n this.deleteWhere(\n (token) => token.platform === platform && token.platformUserId === platformUserId,\n );\n return this.createRecord(TTL_MS, {\n platform,\n platformUserId,\n vaultId,\n providerId,\n conversationId,\n });\n }\n}\nimport type { NotifyFn } from \"./types.js\";\n\ninterface LinkCompleteBody {\n token: string;\n mode?: LoginCredentialKind;\n envKey?: string;\n credential?: string;\n env?: Record<string, string>;\n}\n\ninterface OAuthStartBody {\n token: string;\n serviceId: string;\n}\n\ninterface PendingOAuthState {\n linkToken: string;\n serviceId: string;\n codeVerifier: string;\n expiresAt: number;\n}\n\ninterface SecretPresetField {\n envKey: string;\n envKeys?: string[];\n label: string;\n type: \"text\" | \"password\";\n placeholder: string;\n helpText: string;\n optional?: boolean;\n pattern?: string;\n patternMessage?: string;\n}\n\ninterface SecretPreset {\n id: string;\n label: string;\n description: string;\n note?: string;\n fields: SecretPresetField[];\n}\n\nconst OAUTH_STATE_TTL_MS = 10 * 60 * 1000;\nconst DEFAULT_SECRET_CONFIG_ID = \"manual\";\nconst SECRET_PRESETS: SecretPreset[] = [\n {\n id: \"cloudflare_wrangler\",\n label: \"Cloudflare / Wrangler\",\n description:\n \"Store a Cloudflare API token and account ID for Wrangler, Workers, Pages, D1, and KV.\",\n note: \"Create a scoped API Token from Cloudflare Dashboard → My Profile → API Tokens. Do not use the Global API Key.\",\n fields: [\n {\n envKey: \"CLOUDFLARE_API_TOKEN\",\n label: \"Cloudflare API Token\",\n type: \"password\",\n placeholder: \"cfut_...\",\n helpText: \"Recommended for Wrangler, CI, and sandbox use.\",\n },\n {\n envKey: \"CLOUDFLARE_ACCOUNT_ID\",\n label: \"Cloudflare Account ID\",\n type: \"text\",\n placeholder: \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n helpText: \"Find this via wrangler whoami or in the Cloudflare dashboard account page.\",\n pattern: \"^[A-Fa-f0-9]{32}$\",\n patternMessage: \"Account ID must be a 32-character hexadecimal string.\",\n },\n ],\n },\n {\n id: \"openai\",\n label: \"OpenAI\",\n description: \"Store an OpenAI API key for tools and SDKs that use OPENAI_API_KEY.\",\n note: \"Create a standard API key from the OpenAI dashboard. Paste the key exactly as issued.\",\n fields: [\n {\n envKey: \"OPENAI_API_KEY\",\n label: \"OpenAI API Key\",\n type: \"password\",\n placeholder: \"sk-...\",\n helpText: \"Used by the OpenAI SDK, CLI wrappers, and many coding tools.\",\n },\n ],\n },\n {\n id: \"anthropic\",\n label: \"Anthropic\",\n description: \"Store an Anthropic API key for Claude and tools that use ANTHROPIC_API_KEY.\",\n note: \"Create this key from the Anthropic Console. Use a workspace-scoped key when possible.\",\n fields: [\n {\n envKey: \"ANTHROPIC_API_KEY\",\n label: \"Anthropic API Key\",\n type: \"password\",\n placeholder: \"sk-ant-...\",\n helpText: \"Used by Claude integrations and Anthropic-compatible tooling.\",\n },\n ],\n },\n {\n id: \"gemini\",\n label: \"Gemini\",\n description:\n \"Store one Google AI Studio key and expose it as both GEMINI_API_KEY and GOOGLE_API_KEY.\",\n note: \"Create a Gemini / Google AI Studio API key, then paste it once here for compatibility with both env names.\",\n fields: [\n {\n envKey: \"GEMINI_API_KEY\",\n envKeys: [\"GEMINI_API_KEY\", \"GOOGLE_API_KEY\"],\n label: \"Gemini API Key\",\n type: \"password\",\n placeholder: \"AIza...\",\n helpText: \"One value will be written to both GEMINI_API_KEY and GOOGLE_API_KEY.\",\n },\n ],\n },\n {\n id: \"openrouter\",\n label: \"OpenRouter\",\n description: \"Store an OpenRouter API key for tools that route models through OpenRouter.\",\n note: \"Create a key from the OpenRouter dashboard and paste it here.\",\n fields: [\n {\n envKey: \"OPENROUTER_API_KEY\",\n label: \"OpenRouter API Key\",\n type: \"password\",\n placeholder: \"sk-or-v1-...\",\n helpText: \"Used by OpenRouter SDKs and compatible model gateways.\",\n },\n ],\n },\n {\n id: \"github_pat\",\n label: \"GitHub PAT\",\n description:\n \"Store one GitHub personal access token and expose it as both GH_TOKEN and GITHUB_TOKEN.\",\n note: \"Create a fine-grained or classic personal access token from GitHub Settings → Developer settings.\",\n fields: [\n {\n envKey: \"GH_TOKEN\",\n envKeys: [\"GH_TOKEN\", \"GITHUB_TOKEN\"],\n label: \"GitHub Personal Access Token\",\n type: \"password\",\n placeholder: \"github_pat_...\",\n helpText: \"One value will be written to both GH_TOKEN and GITHUB_TOKEN.\",\n },\n ],\n },\n {\n id: \"vercel\",\n label: \"Vercel\",\n description: \"Store a Vercel token plus optional org and project IDs for deployment tooling.\",\n note: \"Create a token from the Vercel dashboard. Org ID and Project ID are optional but useful for scripted deploys.\",\n fields: [\n {\n envKey: \"VERCEL_TOKEN\",\n label: \"Vercel Token\",\n type: \"password\",\n placeholder: \"vercel_...\",\n helpText: \"Required for Vercel CLI and API access.\",\n },\n {\n envKey: \"VERCEL_ORG_ID\",\n label: \"Vercel Org ID\",\n type: \"text\",\n placeholder: \"team_...\",\n helpText: \"Optional. Set this when you want to target a specific team or account.\",\n optional: true,\n },\n {\n envKey: \"VERCEL_PROJECT_ID\",\n label: \"Vercel Project ID\",\n type: \"text\",\n placeholder: \"prj_...\",\n helpText: \"Optional. Set this when deploy scripts need a fixed project reference.\",\n optional: true,\n },\n ],\n },\n {\n id: \"sentry\",\n label: \"Sentry\",\n description:\n \"Store a Sentry auth token plus optional org/project, and mount ~/.sentryclirc for sentry-cli.\",\n note: \"Create an auth token from Sentry Settings → Account → API → Auth Tokens. Saving this preset also writes /root/.sentryclirc for sentry-cli.\",\n fields: [\n {\n envKey: \"SENTRY_AUTH_TOKEN\",\n label: \"Sentry Auth Token\",\n type: \"password\",\n placeholder: \"sntrys_...\",\n helpText:\n \"Required for Sentry CLI, releases, and sourcemap uploads. Also written to /root/.sentryclirc.\",\n },\n {\n envKey: \"SENTRY_ORG\",\n label: \"Sentry Org Slug\",\n type: \"text\",\n placeholder: \"my-org\",\n helpText: \"Optional. Helpful for Sentry CLI commands and CI automation.\",\n optional: true,\n },\n {\n envKey: \"SENTRY_PROJECT\",\n label: \"Sentry Project Slug\",\n type: \"text\",\n placeholder: \"my-project\",\n helpText: \"Optional. Helpful for release and sourcemap commands.\",\n optional: true,\n },\n ],\n },\n];\n\nexport function createLoginRequestHandler(\n linkTokenStore: InMemoryLinkTokenStore,\n vaultManager: VaultManager,\n notify: NotifyFn,\n): (req: IncomingMessage, res: ServerResponse, url: URL) => boolean {\n const oauthStates = new Map<string, PendingOAuthState>();\n\n return (req, res, url) => {\n if (req.method === \"GET\" && url.pathname === \"/link\") {\n const rawToken = url.searchParams.get(\"token\") ?? \"\";\n const linkToken = linkTokenStore.peek(rawToken);\n\n if (!linkToken) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n renderErrorPage(\n \"This link is invalid or has expired. Ask the bot for a new /login link.\",\n ),\n );\n return true;\n }\n\n const oauthServiceHint = linkToken.providerId\n ? resolveOAuthService(linkToken.providerId)\n : undefined;\n const oauthServices = getOAuthServices();\n const defaultMode: LoginCredentialKind = oauthServiceHint ? \"oauth\" : \"api_key\";\n const existingSecrets = describeVaultSecrets(vaultManager, linkToken.vaultId);\n\n res.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n renderCredentialPage({\n token: rawToken,\n title: oauthServiceHint ? `${oauthServiceHint.label} OAuth` : \"Store Secret\",\n defaultMode,\n initialEnvKey: \"\",\n secretLabel: \"Secret value\",\n placeholder: \"sk-...\",\n helpText: oauthServiceHint\n ? `Authorize ${oauthServiceHint.label} and store tokens in your vault.`\n : \"Set any environment variable key/value pair in your vault.\",\n oauthServices,\n oauthServiceIdHint: oauthServiceHint?.id,\n existingSecrets,\n }),\n );\n return true;\n }\n\n if (req.method === \"POST\" && url.pathname === \"/api/link/complete\") {\n if (!enforceCsrf(req, res)) return true;\n void readJsonBody(req, res, 16 * 1024).then((body) => {\n if (body === null) return;\n return handleLinkComplete(\n body as Partial<LinkCompleteBody>,\n linkTokenStore,\n vaultManager,\n notify,\n res,\n );\n });\n return true;\n }\n\n if (req.method === \"POST\" && url.pathname === \"/api/oauth/start\") {\n if (!enforceCsrf(req, res)) return true;\n void readJsonBody(req, res, 16 * 1024).then((body) => {\n if (body === null) return;\n return handleOAuthStart(\n body as Partial<OAuthStartBody>,\n req,\n linkTokenStore,\n oauthStates,\n res,\n );\n });\n return true;\n }\n\n if (req.method === \"GET\" && url.pathname === \"/oauth/callback\") {\n void handleOAuthCallback({\n url,\n req,\n linkTokenStore,\n vaultManager,\n notify,\n oauthStates,\n res,\n }).catch((err: Error) => {\n log.logWarning(\"OAuth callback failed\", err.message);\n reportUserFacingError(err, {\n domain: \"login\",\n surface: \"oauth\",\n operation: \"oauth_callback\",\n severity: \"error\",\n context: { route: \"/oauth/callback\" },\n });\n res.writeHead(500, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(\"OAuth callback failed. Please retry /login.\"));\n });\n return true;\n }\n\n return false;\n };\n}\n\nfunction enforceCsrf(req: IncomingMessage, res: ServerResponse): boolean {\n const contentType = (req.headers[\"content-type\"] as string | undefined)\n ?.split(\";\")[0]\n ?.trim()\n .toLowerCase();\n if (contentType !== \"application/json\") {\n res.writeHead(415, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Content-Type must be application/json\" }));\n return false;\n }\n\n const configured = resolveLinkBaseUrl();\n if (!configured) {\n return true;\n }\n\n let configuredOrigin: string;\n try {\n configuredOrigin = new URL(configured).origin;\n } catch {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Server misconfiguration\" }));\n return false;\n }\n\n if (requestOrigin(req) !== configuredOrigin) {\n res.writeHead(403, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Cross-origin request rejected\" }));\n return false;\n }\n\n return true;\n}\n\nfunction requestOrigin(req: IncomingMessage): string | undefined {\n const origin = (req.headers.origin as string | undefined)?.trim();\n if (origin && origin !== \"null\") return origin;\n\n const referer = (req.headers.referer as string | undefined)?.trim();\n if (!referer) return undefined;\n try {\n return new URL(referer).origin;\n } catch {\n return undefined;\n }\n}\n\nconst esc = escapeHtml;\n\nconst loginViewStyles = `\n\n\n p { margin: 0; color: var(--muted); font-size: 0.92rem; line-height: 1.55; }\n\n .stack > * + * { margin-top: 14px; }\n\n label {\n display: block;\n margin-bottom: 6px;\n font-size: 0.86rem;\n font-weight: 600;\n color: var(--text);\n }\n\n input, select {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--border);\n border-radius: 10px;\n background: #fff;\n color: var(--text);\n font: inherit;\n }\n\n input:focus-visible,\n select:focus-visible {\n outline: 2px solid var(--text);\n outline-offset: 1px;\n }\n\n .primary-button {\n width: 100%;\n padding: 12px 18px;\n border: none;\n border-radius: 12px;\n background: var(--text);\n color: #fff;\n cursor: pointer;\n font: 500 0.95rem/1.2 'DM Sans', sans-serif;\n transition: opacity 120ms;\n }\n\n .primary-button:hover:not(:disabled) { opacity: 0.85; }\n .primary-button:disabled { opacity: 0.5; cursor: default; }\n\n .service-logo {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n border-radius: 10px;\n flex: 0 0 36px;\n background: #1c1e21;\n color: #fff;\n }\n\n .service-logo svg {\n display: block;\n width: 20px;\n height: 20px;\n }\n\n .service-logo-text {\n font-size: 11px;\n font-weight: 800;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n }\n\n .service-logo.cloudflare {\n background: linear-gradient(180deg, #ffb66d 0%, #f48120 100%);\n }\n\n .service-logo.openai {\n background: linear-gradient(180deg, #3e4045 0%, #111315 100%);\n }\n\n .service-logo.anthropic {\n background: linear-gradient(180deg, #d6b48c 0%, #9a6d3a 100%);\n }\n\n .service-logo.gemini {\n background: linear-gradient(180deg, #8ab4ff 0%, #5b6cff 100%);\n }\n\n .service-logo.openrouter {\n background: linear-gradient(180deg, #8c8cff 0%, #4f46e5 100%);\n }\n\n .service-logo.github {\n background: linear-gradient(180deg, #4a4f57 0%, #1b1f23 100%);\n }\n\n .service-logo.vercel {\n background: linear-gradient(180deg, #4a4f57 0%, #000 100%);\n }\n\n .service-logo.sentry {\n background: linear-gradient(180deg, #7c5cff 0%, #3f2e8c 100%);\n }\n\n .service-logo.manual {\n background: linear-gradient(180deg, #43474d 0%, #1c1e21 100%);\n }\n\n .provider-card > * + * {\n margin-top: 14px;\n }\n\n .provider-header {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .provider-title {\n flex: 1;\n margin: 0;\n font-size: 1rem;\n font-weight: 650;\n line-height: 1.3;\n }\n\n .provider-field label {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n }\n\n .help {\n position: relative;\n display: inline-flex;\n align-items: center;\n }\n\n .help-trigger {\n width: 18px;\n height: 18px;\n padding: 0;\n border: 1px solid var(--border);\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.9);\n color: var(--muted);\n font-size: 11px;\n font-weight: 700;\n line-height: 1;\n cursor: pointer;\n }\n\n .help-trigger:hover {\n color: var(--text);\n border-color: var(--text);\n }\n\n .help-content {\n display: none;\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n z-index: 10;\n width: max-content;\n max-width: 280px;\n padding: 10px 12px;\n border: 1px solid var(--border);\n border-radius: 10px;\n background: #fff;\n color: var(--text);\n font-size: 0.85rem;\n font-weight: 400;\n line-height: 1.45;\n box-shadow: 0 8px 24px rgba(28, 30, 33, 0.12);\n white-space: normal;\n }\n\n .help-trigger[aria-expanded=\"true\"] + .help-content {\n display: block;\n }\n\n .help-trigger[aria-expanded=\"true\"] {\n color: var(--text);\n border-color: var(--text);\n }\n\n .mode {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n margin-top: 22px;\n }\n\n .mode label {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n padding: 10px 12px;\n border: 1px solid var(--border);\n border-radius: 999px;\n background: rgba(255, 255, 255, 0.85);\n font-weight: 500;\n }\n\n .mode input {\n width: auto;\n margin: 0;\n }\n\n .panel {\n display: none;\n }\n\n .panel.active {\n display: block;\n }\n\n #api-panel.active {\n display: grid;\n gap: 16px;\n }\n\n .panel-note {\n margin-top: 10px;\n font-size: 0.92rem;\n }\n\n .result,\n .status {\n margin-top: 20px;\n padding: 14px 16px;\n border-radius: 14px;\n font-size: 0.95rem;\n }\n\n .result {\n display: none;\n }\n\n .result.ok,\n .status.ok {\n background: var(--ok-bg);\n color: var(--ok-text);\n }\n\n .result.err,\n .status.err {\n background: var(--err-bg);\n color: var(--err-text);\n }\n\n .secrets-summary {\n margin-top: 18px;\n padding: 14px 16px;\n border: 1px solid var(--border);\n border-radius: 14px;\n background: rgba(255, 255, 255, 0.72);\n }\n\n .secrets-summary h2 {\n margin: 0 0 8px;\n font-size: 0.98rem;\n }\n\n .secrets-summary p {\n font-size: 0.92rem;\n }\n\n .secrets-summary ul {\n margin: 10px 0 0;\n padding-left: 18px;\n color: var(--text);\n }\n\n .secrets-summary li + li {\n margin-top: 6px;\n }\n\n .close-note {\n margin-top: 14px;\n font-size: 0.92rem;\n }\n\n @media (max-width: 640px) {\n .mode label { flex: 1; justify-content: center; }\n input, select { padding: 12px; }\n .primary-button { padding: 14px 18px; }\n .help-content { max-width: min(260px, calc(100vw - 40px)); }\n .provider-header .help-content { left: auto; right: 0; }\n }\n`;\n\nfunction renderHtmlDocument(title: string, shellContent: string): string {\n return renderPortalShell({\n activeView: \"vault\",\n pageTitle: \"Vault\",\n body: shellContent,\n extraStyles: loginViewStyles,\n });\n}\n\nfunction renderStatusPage(\n title: string,\n message: string,\n tone: \"ok\" | \"err\",\n options?: { closeNote?: boolean },\n): string {\n const closeNote = options?.closeNote ? '<p class=\"close-note\">You can close this tab.</p>' : \"\";\n return renderHtmlDocument(\n title,\n `<section class=\"card\"><div class=\"stack\">\n <p class=\"eyebrow\">${PRODUCT_NAME}</p>\n <h1 class=\"page-title\">${esc(title)}</h1>\n <div class=\"status ${tone}\">${esc(message)}</div>\n ${closeNote}\n </div></section>`,\n );\n}\n\ninterface ExistingSecretsSummary {\n envKeys: string[];\n mountTargets: string[];\n}\n\nfunction describeVaultSecrets(vaultManager: VaultManager, vaultId: string): ExistingSecretsSummary {\n const vault = vaultManager.resolve(vaultId);\n if (!vault) {\n return { envKeys: [], mountTargets: [] };\n }\n\n return {\n envKeys: Object.keys(vault.env).toSorted((left, right) => left.localeCompare(right)),\n mountTargets: [...new Set(vault.mounts.map((mount) => mount.target))].toSorted((left, right) =>\n left.localeCompare(right),\n ),\n };\n}\n\nfunction renderSecretsSummary(summary: ExistingSecretsSummary): string {\n if (summary.envKeys.length === 0 && summary.mountTargets.length === 0) {\n return `\n <section class=\"secrets-summary\">\n <h2>Currently stored</h2>\n <p>No secrets are stored in this vault yet.</p>\n </section>`;\n }\n\n const envItems = summary.envKeys.map((envKey) => `<li><code>${esc(envKey)}</code></li>`).join(\"\");\n const mountItems = summary.mountTargets\n .map((target) => `<li><code>${esc(target)}</code></li>`)\n .join(\"\");\n\n return `\n <section class=\"secrets-summary\">\n <h2>Currently stored</h2>\n <p>Only secret names and mounted paths are shown here. Secret values are never displayed.</p>\n ${summary.envKeys.length > 0 ? `<p><strong>Environment keys</strong></p><ul>${envItems}</ul>` : \"\"}\n ${summary.mountTargets.length > 0 ? `<p><strong>Mounted secret files</strong></p><ul>${mountItems}</ul>` : \"\"}\n </section>`;\n}\n\nfunction renderServiceLogo(kind: string): string {\n if (kind === \"cloudflare_wrangler\") {\n return `<span class=\"service-logo cloudflare\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\">\n <path d=\"M8.5 17.5h8.2a2.9 2.9 0 0 0 .4-5.78A4.45 4.45 0 0 0 8.9 10.4a3.7 3.7 0 0 0-.4 7.1Z\" fill=\"white\" fill-opacity=\"0.98\"/>\n <path d=\"M6.6 17.5h5.1a2.3 2.3 0 0 0 0-4.6 3.1 3.1 0 0 0-3-2.2 3.23 3.23 0 0 0-3.18 3.64A2.67 2.67 0 0 0 6.6 17.5Z\" fill=\"white\"/>\n </svg>\n </span>`;\n }\n\n const textLogos: Record<string, { className: string; text: string }> = {\n openai: { className: \"openai\", text: \"OA\" },\n anthropic: { className: \"anthropic\", text: \"AI\" },\n gemini: { className: \"gemini\", text: \"G\" },\n openrouter: { className: \"openrouter\", text: \"OR\" },\n github_pat: { className: \"github\", text: \"GH\" },\n vercel: { className: \"vercel\", text: \"V\" },\n sentry: { className: \"sentry\", text: \"S\" },\n manual: { className: \"manual\", text: \">_\" },\n };\n const logo = textLogos[kind] ?? textLogos.manual ?? { className: \"manual\", text: \">_\" };\n return `<span class=\"service-logo ${logo.className}\" aria-hidden=\"true\"><span class=\"service-logo-text\">${logo.text}</span></span>`;\n}\n\nfunction resolveFieldEnvKeys(field: SecretPresetField): string[] {\n return field.envKeys && field.envKeys.length > 0 ? field.envKeys : [field.envKey];\n}\n\nfunction renderStoredEnvKeysInline(field: SecretPresetField): string {\n return resolveFieldEnvKeys(field)\n .map((envKey) => `<code>${esc(envKey)}</code>`)\n .join(\", \");\n}\n\nfunction renderHelpIcon(html: string): string {\n return `<span class=\"help\">\n <button type=\"button\" class=\"help-trigger\" aria-label=\"More info\" aria-expanded=\"false\">?</button>\n <span class=\"help-content\" role=\"tooltip\">${html}</span>\n </span>`;\n}\n\nfunction renderPresetProviderCard(preset: SecretPreset): string {\n const headerHelp = preset.note ? renderHelpIcon(esc(preset.note)) : \"\";\n const fields = preset.fields\n .map((field) => {\n const storedKeys = renderStoredEnvKeysInline(field);\n const helpText = `${esc(field.helpText)} Stored as ${storedKeys}.${field.optional ? \" Optional.\" : \"\"}`;\n return `<div class=\"provider-field\">\n <label for=\"preset-${esc(preset.id)}-${esc(field.envKey)}\">\n ${esc(field.label)}\n ${renderHelpIcon(helpText)}\n </label>\n <input\n id=\"preset-${esc(preset.id)}-${esc(field.envKey)}\"\n type=\"${field.type}\"\n autocomplete=\"off\"\n placeholder=\"${esc(field.placeholder)}\"\n data-env-key=\"${esc(field.envKey)}\"\n data-env-keys=\"${esc(resolveFieldEnvKeys(field).join(\",\"))}\"\n data-field-label=\"${esc(field.label)}\"\n ${field.optional ? 'data-optional=\"true\"' : \"\"}\n ${field.pattern ? `data-pattern=\"${esc(field.pattern)}\"` : \"\"}\n ${field.patternMessage ? `data-pattern-message=\"${esc(field.patternMessage)}\"` : \"\"}\n >\n </div>`;\n })\n .join(\"\\n\");\n\n return `<section class=\"card provider-card\" data-provider-kind=\"preset\" data-provider-id=\"${esc(preset.id)}\">\n <div class=\"provider-header\">\n ${renderServiceLogo(preset.id)}\n <h2 class=\"provider-title\">${esc(preset.label)}</h2>\n ${headerHelp}\n </div>\n ${fields}\n </section>`;\n}\n\nfunction renderManualProviderCard(\n initialEnvKey: string,\n secretLabel: string,\n placeholder: string,\n): string {\n const headerHelp = renderHelpIcon(\n esc(\n \"Set any environment variable key/value pair manually. Use this when no provider preset fits.\",\n ),\n );\n return `<section class=\"card provider-card\" data-provider-kind=\"manual\" data-provider-id=\"${esc(DEFAULT_SECRET_CONFIG_ID)}\">\n <div class=\"provider-header\">\n ${renderServiceLogo(\"manual\")}\n <h2 class=\"provider-title\">Manual entry</h2>\n ${headerHelp}\n </div>\n <div class=\"provider-field\">\n <label for=\"envKey\">Environment key</label>\n <input id=\"envKey\" type=\"text\" name=\"envKey\" placeholder=\"OPENAI_API_KEY\" value=\"${esc(initialEnvKey)}\" autocomplete=\"off\">\n </div>\n <div class=\"provider-field\">\n <label for=\"credential\">${esc(secretLabel)}</label>\n <input id=\"credential\" type=\"password\" name=\"credential\" placeholder=\"${esc(placeholder)}\" autocomplete=\"off\">\n </div>\n </section>`;\n}\n\nconst CREDENTIAL_PAGE_TOKEN = \"__MIKAN_LOGIN_TOKEN__\";\nconst CREDENTIAL_PAGE_SCRIPT = ` <script>\n const envKeyPattern = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n function selectedMode() {\n return document.querySelector('input[name=\"mode\"]:checked').value;\n }\n\n function showResult(message, ok) {\n const result = document.getElementById('result');\n result.style.display = 'block';\n result.className = ok ? 'result ok' : 'result err';\n result.textContent = message;\n }\n\n function resetContinueButton() {\n const btn = document.getElementById('btn');\n btn.disabled = false;\n btn.textContent = 'Continue';\n }\n\n function syncPanels() {\n const mode = selectedMode();\n document.getElementById('api-panel').classList.toggle('active', mode === 'api_key');\n document.getElementById('oauth-panel').classList.toggle('active', mode === 'oauth');\n }\n\n function collectManualCard(card) {\n const envKey = card.querySelector('#envKey').value.trim();\n const credential = card.querySelector('#credential').value.trim();\n if (!envKey && !credential) return { skip: true };\n if (!envKeyPattern.test(envKey)) return { error: 'Manual entry: please enter a valid environment key.' };\n if (!credential) return { error: 'Manual entry: please enter a secret value.' };\n return { env: { [envKey]: credential } };\n }\n\n function collectPresetCard(card) {\n const inputs = card.querySelectorAll('input[data-env-key]');\n const filled = Array.from(inputs).some((input) => input.value.trim() !== '');\n if (!filled) return { skip: true };\n\n const env = {};\n for (const input of inputs) {\n const value = input.value.trim();\n const label = input.dataset.fieldLabel || input.dataset.envKey || 'a value';\n const optional = input.dataset.optional === 'true';\n if (!value) {\n if (optional) continue;\n return { error: 'Please enter ' + label + '.' };\n }\n if (input.dataset.pattern && !(new RegExp(input.dataset.pattern).test(value))) {\n return { error: input.dataset.patternMessage || ('Invalid ' + label + '.') };\n }\n const envKeys = (input.dataset.envKeys || input.dataset.envKey || '')\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean);\n for (const envKey of envKeys) {\n env[envKey] = value;\n }\n }\n return { env };\n }\n\n function collectApiEnv() {\n const env = {};\n let any = false;\n for (const card of document.querySelectorAll('.provider-card')) {\n const result = card.dataset.providerKind === 'manual'\n ? collectManualCard(card)\n : collectPresetCard(card);\n if (result.skip) continue;\n if (result.error) return { error: result.error };\n Object.assign(env, result.env);\n any = true;\n }\n if (!any) return { error: 'Fill in at least one provider before continuing.' };\n return { env };\n }\n\n async function startOAuthFlow() {\n const serviceId = document.getElementById('oauthService').value;\n const r = await fetch('/api/oauth/start', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token: '__MIKAN_LOGIN_TOKEN__', serviceId }),\n });\n const data = await r.json();\n if (!r.ok) {\n showResult('Error: ' + (data.error ?? r.status), false);\n resetContinueButton();\n return;\n }\n window.location.href = data.redirectUrl;\n }\n\n async function saveApiSecrets() {\n const payload = collectApiEnv();\n if (payload.error) {\n showResult(payload.error, false);\n resetContinueButton();\n return;\n }\n\n const r = await fetch('/api/link/complete', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token: '__MIKAN_LOGIN_TOKEN__', mode: 'api_key', env: payload.env }),\n });\n const data = await r.json();\n if (r.ok) {\n showResult(data.message ?? 'Credential stored. You can close this tab.', true);\n document.getElementById('btn').style.display = 'none';\n for (const input of document.querySelectorAll('input,select,button')) input.disabled = true;\n } else {\n showResult('Error: ' + (data.error ?? r.status), false);\n resetContinueButton();\n }\n }\n\n let openHelp = null;\n function closeOpenHelp() {\n if (openHelp) {\n openHelp.setAttribute('aria-expanded', 'false');\n openHelp = null;\n }\n }\n\n for (const trigger of document.querySelectorAll('.help-trigger')) {\n trigger.addEventListener('click', (event) => {\n event.stopPropagation();\n const wasOpen = trigger.getAttribute('aria-expanded') === 'true';\n closeOpenHelp();\n if (!wasOpen) {\n trigger.setAttribute('aria-expanded', 'true');\n openHelp = trigger;\n }\n });\n }\n\n document.addEventListener('click', closeOpenHelp);\n document.addEventListener('keydown', (event) => {\n if (event.key === 'Escape') closeOpenHelp();\n });\n\n for (const radio of document.querySelectorAll('input[name=\"mode\"]')) {\n radio.addEventListener('change', syncPanels);\n }\n\n syncPanels();\n\n async function connect() {\n const btn = document.getElementById('btn');\n const mode = selectedMode();\n btn.disabled = true;\n btn.textContent = mode === 'oauth' ? 'Redirecting…' : 'Saving…';\n\n try {\n if (mode === 'oauth') {\n await startOAuthFlow();\n return;\n }\n await saveApiSecrets();\n } catch (err) {\n showResult('Network error: ' + (err?.message ?? err), false);\n resetContinueButton();\n }\n }\n </script>`;\n\nfunction renderCredentialPageScript(token: string): string {\n return CREDENTIAL_PAGE_SCRIPT.replaceAll(CREDENTIAL_PAGE_TOKEN, () => esc(token));\n}\n\ninterface CredentialPageOptions {\n token: string;\n title: string;\n defaultMode: LoginCredentialKind;\n initialEnvKey: string;\n secretLabel: string;\n placeholder: string;\n helpText: string;\n oauthServices: OAuthService[];\n oauthServiceIdHint: string | undefined;\n existingSecrets: ExistingSecretsSummary;\n}\n\nfunction renderCredentialPage(options: CredentialPageOptions): string {\n const {\n token,\n title,\n defaultMode,\n initialEnvKey,\n secretLabel,\n placeholder,\n helpText,\n oauthServices,\n oauthServiceIdHint,\n existingSecrets,\n } = options;\n const oauthOptions = oauthServices\n .map((service) => {\n const selected = service.id === oauthServiceIdHint ? ' selected=\"selected\"' : \"\";\n return `<option value=\"${esc(service.id)}\"${selected}>${esc(service.label)}</option>`;\n })\n .join(\"\\n\");\n const presetCards = SECRET_PRESETS.map(renderPresetProviderCard).join(\"\\n\");\n\n return renderHtmlDocument(\n \"Login\",\n `<section class=\"card stack\">\n <p class=\"eyebrow\">${PRODUCT_NAME}</p>\n <h1 class=\"page-title\">${esc(title)}</h1>\n <p>Your personal sandbox is already provisioned automatically.</p>\n <p>${esc(helpText)}</p>\n ${renderSecretsSummary(existingSecrets)}\n <div class=\"mode\">\n <label><input type=\"radio\" name=\"mode\" value=\"api_key\" ${defaultMode === \"api_key\" ? \"checked\" : \"\"}> Secrets / API tokens</label>\n <label><input type=\"radio\" name=\"mode\" value=\"oauth\" ${defaultMode === \"oauth\" ? \"checked\" : \"\"}> OAuth login</label>\n </div>\n</section>\n\n<div id=\"api-panel\" class=\"panel\">\n ${presetCards}\n ${renderManualProviderCard(initialEnvKey, secretLabel, placeholder)}\n</div>\n\n<div id=\"oauth-panel\" class=\"panel card stack\">\n <label for=\"oauthService\">OAuth service</label>\n <select id=\"oauthService\" name=\"oauthService\">${oauthOptions}</select>\n <p class=\"panel-note\">You'll be redirected to the selected service's authorization page.</p>\n</div>\n\n<div>\n <button id=\"btn\" class=\"primary-button\" onclick=\"connect()\">Continue</button>\n <div id=\"result\" class=\"result\" aria-live=\"polite\"></div>\n</div>\n${renderCredentialPageScript(token)}`,\n );\n}\n\nfunction renderErrorPage(message: string): string {\n return renderStatusPage(\"Login Error\", message, \"err\");\n}\n\nfunction renderSuccessPage(message: string): string {\n return renderStatusPage(\"Connected\", message, \"ok\", { closeNote: true });\n}\n\nfunction isValidEnvKey(value: string): boolean {\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(value);\n}\n\nfunction extractEnvUpdates(data: Partial<LinkCompleteBody>): {\n updates?: Record<string, string>;\n error?: string;\n} {\n if (data.env && typeof data.env === \"object\" && !Array.isArray(data.env)) {\n const rawEntries = Object.entries(data.env);\n if (rawEntries.length === 0) return { error: \"Missing required field: env\" };\n\n const updates: Record<string, string> = {};\n for (const [rawKey, rawValue] of rawEntries) {\n const envKey = rawKey.trim();\n const credential = typeof rawValue === \"string\" ? rawValue.trim() : \"\";\n if (!isValidEnvKey(envKey)) return { error: `Invalid envKey format: ${rawKey}` };\n if (!credential) return { error: `Missing value for envKey: ${envKey}` };\n updates[envKey] = credential;\n }\n\n return { updates };\n }\n\n const envKey = data.envKey?.trim() ?? \"\";\n const credential = data.credential?.trim() ?? \"\";\n if (!isValidEnvKey(envKey)) return { error: \"Invalid envKey format\" };\n if (!credential) return { error: \"Missing required field: credential\" };\n return { updates: { [envKey]: credential } };\n}\n\nfunction renderStoredEnvMessage(envKeys: string[], fileTargets: string[] = []): string {\n const fileSuffix = fileTargets.length > 0 ? ` Mounted file(s): ${fileTargets.join(\", \")}.` : \"\";\n if (envKeys.length === 1) {\n return `${envKeys[0]} stored successfully in vault.${fileSuffix}`;\n }\n\n return `${envKeys.length} secrets stored successfully in vault: ${envKeys.join(\", \")}.${fileSuffix}`;\n}\n\nfunction renderSentryCliConfig(updates: Record<string, string>): string | undefined {\n const token = updates.SENTRY_AUTH_TOKEN?.trim();\n if (!token) return undefined;\n\n const lines = [\"[auth]\", `token=${token}`, \"\"];\n const defaults: string[] = [];\n const org = updates.SENTRY_ORG?.trim();\n const project = updates.SENTRY_PROJECT?.trim();\n if (org) defaults.push(`org = ${org}`);\n if (project) defaults.push(`project = ${project}`);\n if (defaults.length > 0) {\n lines.push(\"[defaults]\", ...defaults, \"\");\n }\n return lines.join(\"\\n\");\n}\n\nasync function handleLinkComplete(\n data: Partial<LinkCompleteBody>,\n linkTokenStore: InMemoryLinkTokenStore,\n vaultManager: VaultManager,\n notify: NotifyFn,\n res: ServerResponse,\n): Promise<void> {\n if (!data.token) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Missing required field: token\" }));\n return;\n }\n\n const { updates, error } = extractEnvUpdates(data);\n if (!updates || error) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: error ?? \"Invalid env payload\" }));\n return;\n }\n\n const envKeys = Object.keys(updates).toSorted((left, right) => left.localeCompare(right));\n\n const linkToken = linkTokenStore.consume(data.token);\n if (!linkToken) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Invalid or expired token\" }));\n return;\n }\n\n const fileTargets: string[] = [];\n const sentryCliConfig = renderSentryCliConfig(updates);\n\n try {\n vaultManager.upsertEnv(linkToken.vaultId, updates);\n if (sentryCliConfig) {\n vaultManager.upsertFile(\n linkToken.vaultId,\n \".sentryclirc\",\n sentryCliConfig,\n \"/root/.sentryclirc\",\n );\n fileTargets.push(\"/root/.sentryclirc\");\n }\n } catch (persistError) {\n log.logWarning(\n `Failed to persist [${envKeys.join(\", \")}] for ${linkToken.platform}/${linkToken.platformUserId}`,\n persistError instanceof Error ? persistError.message : String(persistError),\n );\n reportUserFacingError(persistError, {\n domain: \"login\",\n surface: \"credential_login\",\n operation: \"vault_persist\",\n severity: \"error\",\n platform: linkToken.platform,\n context: {\n conversationId: linkToken.conversationId,\n vaultId: linkToken.vaultId,\n credentialMode: data.mode ?? \"manual\",\n envKeyCount: envKeys.length,\n fileTargetCount: fileTargets.length,\n },\n });\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n error:\n \"Failed to store credential on server. Please fix the server issue and run /login again.\",\n }),\n );\n return;\n }\n\n log.logInfo(\n `Stored [${envKeys.join(\", \")}] for ${linkToken.platform}/${linkToken.platformUserId} in vault:${linkToken.vaultId}`,\n );\n\n const message = renderStoredEnvMessage(envKeys, fileTargets);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: true, message }));\n\n notify(\n linkToken.platform,\n linkToken.conversationId,\n `${message} Vault: \\`${linkToken.vaultId}\\`.`,\n ).catch((err: Error) => {\n log.logWarning(\"Failed to notify user after credential login\", err.message);\n reportUserFacingError(err, {\n domain: \"login\",\n surface: \"credential_login\",\n operation: \"notify_user\",\n severity: \"warning\",\n platform: linkToken.platform,\n context: {\n conversationId: linkToken.conversationId,\n vaultId: linkToken.vaultId,\n credentialMode: data.mode ?? \"manual\",\n envKeyCount: envKeys.length,\n fileTargetCount: fileTargets.length,\n },\n });\n });\n}\n\nasync function handleOAuthStart(\n data: Partial<OAuthStartBody>,\n req: IncomingMessage,\n linkTokenStore: InMemoryLinkTokenStore,\n oauthStates: Map<string, PendingOAuthState>,\n res: ServerResponse,\n): Promise<void> {\n if (!data.token || !data.serviceId) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Missing required fields: token/serviceId\" }));\n return;\n }\n\n const linkToken = linkTokenStore.peek(data.token);\n if (!linkToken) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Invalid or expired token\" }));\n return;\n }\n\n const service = resolveOAuthService(data.serviceId);\n if (!service) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: `Unsupported OAuth service: ${data.serviceId}` }));\n return;\n }\n\n const clientId = readEnv(service.clientIdEnvKey);\n const clientSecret = readEnv(service.clientSecretEnvKey);\n if (!clientId || !clientSecret) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n error:\n `OAuth service ${service.label} is not configured. ` +\n `Missing ${service.clientIdEnvKey}/${service.clientSecretEnvKey}.`,\n }),\n );\n return;\n }\n\n const state = randomBytes(16).toString(\"hex\");\n const codeVerifier = randomBytes(32).toString(\"base64url\");\n oauthStates.set(state, {\n linkToken: data.token,\n serviceId: service.id,\n codeVerifier,\n expiresAt: Date.now() + OAUTH_STATE_TTL_MS,\n });\n\n for (const [k, v] of oauthStates) {\n if (Date.now() > v.expiresAt) oauthStates.delete(k);\n }\n\n const redirectUri = `${requestBaseUrl(req)}/oauth/callback`;\n const authorizeUrl = new URL(service.authorizationUrl);\n authorizeUrl.searchParams.set(\"response_type\", \"code\");\n authorizeUrl.searchParams.set(\"client_id\", clientId);\n authorizeUrl.searchParams.set(\"redirect_uri\", redirectUri);\n authorizeUrl.searchParams.set(\"state\", state);\n if (service.scopes.length > 0) {\n authorizeUrl.searchParams.set(\"scope\", service.scopes.join(\" \"));\n }\n for (const [key, value] of Object.entries(service.authorizationParams ?? {})) {\n authorizeUrl.searchParams.set(key, value);\n }\n\n const codeChallenge = createHash(\"sha256\").update(codeVerifier).digest(\"base64url\");\n authorizeUrl.searchParams.set(\"code_challenge\", codeChallenge);\n authorizeUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: true, redirectUrl: authorizeUrl.toString() }));\n}\n\ninterface OAuthCallbackOptions {\n url: URL;\n req: IncomingMessage;\n linkTokenStore: InMemoryLinkTokenStore;\n vaultManager: VaultManager;\n notify: NotifyFn;\n oauthStates: Map<string, PendingOAuthState>;\n res: ServerResponse;\n}\n\ninterface ResolvedOAuthCallback {\n code: string;\n codeVerifier: string;\n service: OAuthService;\n clientId: string;\n clientSecret: string;\n linkToken: LinkToken;\n}\n\nfunction resolveOAuthCallback(options: OAuthCallbackOptions): ResolvedOAuthCallback | undefined {\n const { url, oauthStates, linkTokenStore, res } = options;\n const state = url.searchParams.get(\"state\") ?? \"\";\n const code = url.searchParams.get(\"code\") ?? \"\";\n const oauthError = url.searchParams.get(\"error\");\n\n const pending = oauthStates.get(state);\n if (pending) oauthStates.delete(state);\n\n if (oauthError) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(`OAuth authorization failed: ${oauthError}`));\n return undefined;\n }\n if (!pending || Date.now() > pending.expiresAt) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(\"OAuth state is invalid or expired. Please run /login again.\"));\n return undefined;\n }\n if (!code) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(\"Missing OAuth authorization code.\"));\n return undefined;\n }\n\n const service = resolveOAuthService(pending.serviceId);\n if (!service) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(\"Unsupported OAuth service.\"));\n return undefined;\n }\n const clientId = readEnv(service.clientIdEnvKey);\n const clientSecret = readEnv(service.clientSecretEnvKey);\n if (!clientId || !clientSecret) {\n res.writeHead(500, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(\"OAuth service is not configured on server.\"));\n return undefined;\n }\n\n const linkToken = linkTokenStore.consume(pending.linkToken);\n if (!linkToken) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(\"Login link is invalid or expired. Please run /login again.\"));\n return undefined;\n }\n return { code, codeVerifier: pending.codeVerifier, service, clientId, clientSecret, linkToken };\n}\n\ninterface StoreOAuthCredentialsOptions {\n tokenResponse: Record<string, string>;\n service: OAuthService;\n clientId: string;\n clientSecret: string;\n linkToken: LinkToken;\n vaultManager: VaultManager;\n res: ServerResponse;\n}\n\nfunction storeOAuthCredentials(options: StoreOAuthCredentialsOptions): string[] | undefined {\n const { tokenResponse, service, clientId, clientSecret, linkToken, vaultManager, res } = options;\n const accessToken = tokenResponse.access_token?.trim();\n const refreshToken = tokenResponse.refresh_token?.trim();\n if (!accessToken) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(\"OAuth token exchange did not return an access_token.\"));\n return undefined;\n }\n\n const updates: Record<string, string> = {};\n for (const key of service.accessTokenEnvKeys ?? []) updates[key] = accessToken;\n if (refreshToken && service.refreshTokenEnvKey)\n updates[service.refreshTokenEnvKey] = refreshToken;\n\n const fileOutput = service.fileOutput;\n let mountedPath: string | undefined;\n if (fileOutput?.type === \"authorized_user\") {\n if (!refreshToken) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n renderErrorPage(\n \"OAuth token exchange did not return a refresh_token. \" +\n \"Retry after revoking prior consent or ensure prompt=consent is applied.\",\n ),\n );\n return undefined;\n }\n mountedPath = fileOutput.targetPath ?? defaultVaultTargetPath(fileOutput.relativePath);\n if (fileOutput.envKey) updates[fileOutput.envKey] = mountedPath;\n for (const key of fileOutput.additionalEnvKeys ?? []) updates[key] = mountedPath;\n }\n\n const storedTargets: string[] = [];\n try {\n if (Object.keys(updates).length > 0) {\n vaultManager.upsertEnv(linkToken.vaultId, updates);\n storedTargets.push(...Object.keys(updates).toSorted());\n }\n if (fileOutput?.type === \"authorized_user\" && refreshToken) {\n vaultManager.upsertFile(\n linkToken.vaultId,\n fileOutput.relativePath,\n renderAuthorizedUserCredential(clientId, clientSecret, refreshToken),\n fileOutput.targetPath,\n );\n if (mountedPath) storedTargets.push(mountedPath);\n }\n } catch (persistError) {\n log.logWarning(\n `Failed to persist OAuth credentials for ${linkToken.platform}/${linkToken.platformUserId}`,\n persistError instanceof Error ? persistError.message : String(persistError),\n );\n reportUserFacingError(persistError, {\n domain: \"login\",\n surface: \"oauth\",\n operation: \"vault_persist\",\n severity: \"error\",\n platform: linkToken.platform,\n context: {\n conversationId: linkToken.conversationId,\n vaultId: linkToken.vaultId,\n serviceId: service.id,\n credentialMode: \"oauth\",\n storedTargetCount: storedTargets.length,\n },\n });\n res.writeHead(500, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n renderErrorPage(\n \"OAuth tokens were received but could not be stored on the server. Fix the server issue and run /login again.\",\n ),\n );\n return undefined;\n }\n return storedTargets;\n}\n\nasync function handleOAuthCallback(options: OAuthCallbackOptions): Promise<void> {\n const resolved = resolveOAuthCallback(options);\n if (!resolved) return;\n const { service, code, clientId, clientSecret, codeVerifier, linkToken } = resolved;\n const redirectUri = `${requestBaseUrl(options.req)}/oauth/callback`;\n const tokenResponse = await exchangeOAuthCode({\n service,\n code,\n clientId,\n clientSecret,\n redirectUri,\n codeVerifier,\n });\n const storedTargets = storeOAuthCredentials({\n tokenResponse,\n service,\n clientId,\n clientSecret,\n linkToken,\n vaultManager: options.vaultManager,\n res: options.res,\n });\n if (!storedTargets) return;\n\n log.logInfo(\n `Stored [${storedTargets.join(\", \")}] for ${linkToken.platform}/${linkToken.platformUserId} in vault:${linkToken.vaultId}`,\n );\n options\n .notify(\n linkToken.platform,\n linkToken.conversationId,\n `${service.label} OAuth stored (${storedTargets.join(\", \")}) in vault \\`${linkToken.vaultId}\\`.`,\n )\n .catch((err: Error) => {\n log.logWarning(\"Failed to notify user after OAuth login\", err.message);\n reportUserFacingError(err, {\n domain: \"login\",\n surface: \"oauth\",\n operation: \"notify_user\",\n severity: \"warning\",\n platform: linkToken.platform,\n context: {\n conversationId: linkToken.conversationId,\n vaultId: linkToken.vaultId,\n serviceId: service.id,\n credentialMode: \"oauth\",\n storedTargetCount: storedTargets.length,\n },\n });\n });\n\n options.res.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" });\n options.res.end(renderSuccessPage(`${service.label} OAuth connected successfully.`));\n}\n\ninterface ExchangeOAuthCodeOptions {\n service: OAuthService;\n code: string;\n clientId: string;\n clientSecret: string;\n redirectUri: string;\n codeVerifier: string;\n}\n\nasync function exchangeOAuthCode(\n options: ExchangeOAuthCodeOptions,\n): Promise<Record<string, string>> {\n const { service, code, clientId, clientSecret, redirectUri, codeVerifier } = options;\n const params = new URLSearchParams();\n params.set(\"grant_type\", \"authorization_code\");\n params.set(\"code\", code);\n params.set(\"client_id\", clientId);\n params.set(\"client_secret\", clientSecret);\n params.set(\"redirect_uri\", redirectUri);\n params.set(\"code_verifier\", codeVerifier);\n\n const response = await fetch(service.tokenUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n Accept: \"application/json\",\n },\n body: params.toString(),\n });\n\n const text = await response.text();\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n let parsed: Record<string, string> = {};\n\n if (contentType.includes(\"application/json\")) {\n parsed = JSON.parse(text) as Record<string, string>;\n } else {\n const form = new URLSearchParams(text);\n parsed = Object.fromEntries(form.entries());\n }\n\n if (!response.ok) {\n const message = parsed.error_description ?? parsed.error ?? `${response.status}`;\n throw new Error(`OAuth token exchange failed for ${service.id}: ${message}`);\n }\n\n return parsed;\n}\n\nfunction renderAuthorizedUserCredential(\n clientId: string,\n clientSecret: string,\n refreshToken: string,\n): string {\n return (\n JSON.stringify(\n {\n client_id: clientId,\n client_secret: clientSecret,\n refresh_token: refreshToken,\n type: \"authorized_user\",\n },\n null,\n 2,\n ) + \"\\n\"\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"portal.js","sourceRoot":"","sources":["../../../../src/adapters/web/login/portal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACjG,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAEnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAGvD,OAAO,EACL,gBAAgB,EAChB,mBAAmB,GAGpB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,GAAG,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAqB,MAAM,yBAAyB,CAAC;AAIpF,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAE9B,MAAM,OAAO,sBAAuB,SAAQ,kBAA6B;IACvE,MAAM,CACJ,QAAsB,EACtB,cAAsB,EACtB,cAAsB,EACtB,OAAe,EACf,UAAkB;QAElB,IAAI,CAAC,WAAW,CACd,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,cAAc,KAAK,cAAc,CAClF,CAAC;QACF,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;YAC/B,QAAQ;YACR,cAAc;YACd,OAAO;YACP,UAAU;YACV,cAAc;SACf,CAAC,CAAC;IACL,CAAC;CACF;AA2CD,MAAM,kBAAkB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAC1C,MAAM,wBAAwB,GAAG,QAAQ,CAAC;AAC1C,MAAM,cAAc,GAAmB;IACrC;QACE,EAAE,EAAE,qBAAqB;QACzB,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EACT,uFAAuF;QACzF,IAAI,EAAE,+GAA+G;QACrH,MAAM,EAAE;YACN;gBACE,MAAM,EAAE,sBAAsB;gBAC9B,KAAK,EAAE,sBAAsB;gBAC7B,IAAI,EAAE,UAAU;gBAChB,WAAW,EAAE,UAAU;gBACvB,QAAQ,EAAE,gDAAgD;aAC3D;YACD;gBACE,MAAM,EAAE,uBAAuB;gBAC/B,KAAK,EAAE,uBAAuB;gBAC9B,IAAI,EAAE,MAAM;gBACZ,WAAW,EAAE,kCAAkC;gBAC/C,QAAQ,EAAE,4EAA4E;gBACtF,OAAO,EAAE,mBAAmB;gBAC5B,cAAc,EAAE,uDAAuD;aACxE;SACF;KACF;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,qEAAqE;QAClF,IAAI,EAAE,uFAAuF;QAC7F,MAAM,EAAE;YACN;gBACE,MAAM,EAAE,gBAAgB;gBACxB,KAAK,EAAE,gBAAgB;gBACvB,IAAI,EAAE,UAAU;gBAChB,WAAW,EAAE,QAAQ;gBACrB,QAAQ,EAAE,8DAA8D;aACzE;SACF;KACF;IACD;QACE,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,WAAW;QAClB,WAAW,EAAE,6EAA6E;QAC1F,IAAI,EAAE,uFAAuF;QAC7F,MAAM,EAAE;YACN;gBACE,MAAM,EAAE,mBAAmB;gBAC3B,KAAK,EAAE,mBAAmB;gBAC1B,IAAI,EAAE,UAAU;gBAChB,WAAW,EAAE,YAAY;gBACzB,QAAQ,EAAE,+DAA+D;aAC1E;SACF;KACF;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,QAAQ;QACf,WAAW,EACT,yFAAyF;QAC3F,IAAI,EAAE,4GAA4G;QAClH,MAAM,EAAE;YACN;gBACE,MAAM,EAAE,gBAAgB;gBACxB,OAAO,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;gBAC7C,KAAK,EAAE,gBAAgB;gBACvB,IAAI,EAAE,UAAU;gBAChB,WAAW,EAAE,SAAS;gBACtB,QAAQ,EAAE,sEAAsE;aACjF;SACF;KACF;IACD;QACE,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,6EAA6E;QAC1F,IAAI,EAAE,+DAA+D;QACrE,MAAM,EAAE;YACN;gBACE,MAAM,EAAE,oBAAoB;gBAC5B,KAAK,EAAE,oBAAoB;gBAC3B,IAAI,EAAE,UAAU;gBAChB,WAAW,EAAE,cAAc;gBAC3B,QAAQ,EAAE,wDAAwD;aACnE;SACF;KACF;IACD;QACE,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,YAAY;QACnB,WAAW,EACT,yFAAyF;QAC3F,IAAI,EAAE,mGAAmG;QACzG,MAAM,EAAE;YACN;gBACE,MAAM,EAAE,UAAU;gBAClB,OAAO,EAAE,CAAC,UAAU,EAAE,cAAc,CAAC;gBACrC,KAAK,EAAE,8BAA8B;gBACrC,IAAI,EAAE,UAAU;gBAChB,WAAW,EAAE,gBAAgB;gBAC7B,QAAQ,EAAE,8DAA8D;aACzE;SACF;KACF;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,gFAAgF;QAC7F,IAAI,EAAE,+GAA+G;QACrH,MAAM,EAAE;YACN;gBACE,MAAM,EAAE,cAAc;gBACtB,KAAK,EAAE,cAAc;gBACrB,IAAI,EAAE,UAAU;gBAChB,WAAW,EAAE,YAAY;gBACzB,QAAQ,EAAE,yCAAyC;aACpD;YACD;gBACE,MAAM,EAAE,eAAe;gBACvB,KAAK,EAAE,eAAe;gBACtB,IAAI,EAAE,MAAM;gBACZ,WAAW,EAAE,UAAU;gBACvB,QAAQ,EAAE,wEAAwE;gBAClF,QAAQ,EAAE,IAAI;aACf;YACD;gBACE,MAAM,EAAE,mBAAmB;gBAC3B,KAAK,EAAE,mBAAmB;gBAC1B,IAAI,EAAE,MAAM;gBACZ,WAAW,EAAE,SAAS;gBACtB,QAAQ,EAAE,wEAAwE;gBAClF,QAAQ,EAAE,IAAI;aACf;SACF;KACF;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,QAAQ;QACf,WAAW,EACT,+FAA+F;QACjG,IAAI,EAAE,4IAA4I;QAClJ,MAAM,EAAE;YACN;gBACE,MAAM,EAAE,mBAAmB;gBAC3B,KAAK,EAAE,mBAAmB;gBAC1B,IAAI,EAAE,UAAU;gBAChB,WAAW,EAAE,YAAY;gBACzB,QAAQ,EACN,+FAA+F;aAClG;YACD;gBACE,MAAM,EAAE,YAAY;gBACpB,KAAK,EAAE,iBAAiB;gBACxB,IAAI,EAAE,MAAM;gBACZ,WAAW,EAAE,QAAQ;gBACrB,QAAQ,EAAE,8DAA8D;gBACxE,QAAQ,EAAE,IAAI;aACf;YACD;gBACE,MAAM,EAAE,gBAAgB;gBACxB,KAAK,EAAE,qBAAqB;gBAC5B,IAAI,EAAE,MAAM;gBACZ,WAAW,EAAE,YAAY;gBACzB,QAAQ,EAAE,uDAAuD;gBACjE,QAAQ,EAAE,IAAI;aACf;SACF;KACF;CACF,CAAC;AAEF,MAAM,UAAU,yBAAyB,CACvC,cAAsC,EACtC,YAA0B,EAC1B,MAAgB;IAEhB,MAAM,WAAW,GAAG,IAAI,GAAG,EAA6B,CAAC;IAEzD,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QACvB,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACrD,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACrD,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAEhD,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;gBACnE,GAAG,CAAC,GAAG,CACL,eAAe,CACb,yEAAyE,CAC1E,CACF,CAAC;gBACF,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,gBAAgB,GAAG,SAAS,CAAC,UAAU;gBAC3C,CAAC,CAAC,mBAAmB,CAAC,SAAS,CAAC,UAAU,CAAC;gBAC3C,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;YACzC,MAAM,WAAW,GAAwB,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;YAChF,MAAM,eAAe,GAAG,oBAAoB,CAAC,YAAY,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;YAE9E,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;YACnE,GAAG,CAAC,GAAG,CACL,oBAAoB,CAAC;gBACnB,KAAK,EAAE,QAAQ;gBACf,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc;gBAC5E,WAAW;gBACX,aAAa,EAAE,EAAE;gBACjB,WAAW,EAAE,cAAc;gBAC3B,WAAW,EAAE,QAAQ;gBACrB,QAAQ,EAAE,gBAAgB;oBACxB,CAAC,CAAC,aAAa,gBAAgB,CAAC,KAAK,kCAAkC;oBACvE,CAAC,CAAC,4DAA4D;gBAChE,aAAa;gBACb,kBAAkB,EAAE,gBAAgB,EAAE,EAAE;gBACxC,eAAe;aAChB,CAAC,CACH,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,QAAQ,KAAK,oBAAoB,EAAE,CAAC;YACnE,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;YACxC,KAAK,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;gBACnD,IAAI,IAAI,KAAK,IAAI;oBAAE,OAAO;gBAC1B,OAAO,kBAAkB,CACvB,IAAiC,EACjC,cAAc,EACd,YAAY,EACZ,MAAM,EACN,GAAG,CACJ,CAAC;YACJ,CAAC,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,QAAQ,KAAK,kBAAkB,EAAE,CAAC;YACjE,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;YACxC,KAAK,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;gBACnD,IAAI,IAAI,KAAK,IAAI;oBAAE,OAAO;gBAC1B,OAAO,gBAAgB,CACrB,IAA+B,EAC/B,GAAG,EACH,cAAc,EACd,WAAW,EACX,GAAG,CACJ,CAAC;YACJ,CAAC,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,GAAG,CAAC,QAAQ,KAAK,iBAAiB,EAAE,CAAC;YAC/D,KAAK,mBAAmB,CAAC;gBACvB,GAAG;gBACH,GAAG;gBACH,cAAc;gBACd,YAAY;gBACZ,MAAM;gBACN,WAAW;gBACX,GAAG;aACJ,CAAC,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;gBACtB,GAAG,CAAC,UAAU,CAAC,uBAAuB,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;gBACrD,qBAAqB,CAAC,GAAG,EAAE;oBACzB,MAAM,EAAE,OAAO;oBACf,OAAO,EAAE,OAAO;oBAChB,SAAS,EAAE,gBAAgB;oBAC3B,QAAQ,EAAE,OAAO;oBACjB,OAAO,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE;iBACtC,CAAC,CAAC;gBACH,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;gBACnE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,6CAA6C,CAAC,CAAC,CAAC;YAC1E,CAAC,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,GAAoB,EAAE,GAAmB;IAC5D,MAAM,WAAW,GAAI,GAAG,CAAC,OAAO,CAAC,cAAc,CAAwB;QACrE,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACf,EAAE,IAAI,EAAE;SACP,WAAW,EAAE,CAAC;IACjB,IAAI,WAAW,KAAK,kBAAkB,EAAE,CAAC;QACvC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,uCAAuC,EAAE,CAAC,CAAC,CAAC;QAC5E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,UAAU,GAAG,kBAAkB,EAAE,CAAC;IACxC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,gBAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,gBAAgB,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAC,CAAC;QAC9D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,aAAa,CAAC,GAAG,CAAC,KAAK,gBAAgB,EAAE,CAAC;QAC5C,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC,CAAC,CAAC;QACpE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,GAAoB;IACzC,MAAM,MAAM,GAAI,GAAG,CAAC,OAAO,CAAC,MAA6B,EAAE,IAAI,EAAE,CAAC;IAClE,IAAI,MAAM,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC;IAE/C,MAAM,OAAO,GAAI,GAAG,CAAC,OAAO,CAAC,OAA8B,EAAE,IAAI,EAAE,CAAC;IACpE,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,GAAG,GAAG,UAAU,CAAC;AAEvB,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkSvB,CAAC;AAEF,SAAS,kBAAkB,CAAC,KAAa,EAAE,YAAoB;IAC7D,OAAO,iBAAiB,CAAC;QACvB,UAAU,EAAE,OAAO;QACnB,SAAS,EAAE,OAAO;QAClB,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,eAAe;KAC7B,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CACvB,KAAa,EACb,OAAe,EACf,IAAkB,EAClB,OAAiC;IAEjC,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,mDAAmD,CAAC,CAAC,CAAC,EAAE,CAAC;IAChG,OAAO,kBAAkB,CACvB,KAAK,EACL;2BACuB,YAAY;+BACR,GAAG,CAAC,KAAK,CAAC;2BACd,IAAI,KAAK,GAAG,CAAC,OAAO,CAAC;QACxC,SAAS;qBACI,CAClB,CAAC;AACJ,CAAC;AAOD,SAAS,oBAAoB,CAAC,YAA0B,EAAE,OAAe;IACvE,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC3C,CAAC;IAED,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACpF,YAAY,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAC7F,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAC1B;KACF,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,OAA+B;IAC3D,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtE,OAAO;;;;aAIE,CAAC;IACZ,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClG,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY;SACpC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC;SACvD,IAAI,CAAC,EAAE,CAAC,CAAC;IAEZ,OAAO;;;;MAIH,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,+CAA+C,QAAQ,OAAO,CAAC,CAAC,CAAC,EAAE;MAChG,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,mDAAmD,UAAU,OAAO,CAAC,CAAC,CAAC,EAAE;aACpG,CAAC;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,IAAI,IAAI,KAAK,qBAAqB,EAAE,CAAC;QACnC,OAAO;;;;;YAKC,CAAC;IACX,CAAC;IAED,MAAM,SAAS,GAAwD;QACrE,MAAM,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE;QAC3C,SAAS,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE;QACjD,MAAM,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE;QAC1C,UAAU,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE;QACnD,UAAU,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE;QAC/C,MAAM,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE;QAC1C,MAAM,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE;QAC1C,MAAM,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE;KAC5C,CAAC;IACF,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,MAAM,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACxF,OAAO,6BAA6B,IAAI,CAAC,SAAS,wDAAwD,IAAI,CAAC,IAAI,gBAAgB,CAAC;AACtI,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAwB;IACnD,OAAO,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACpF,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAwB;IACzD,OAAO,mBAAmB,CAAC,KAAK,CAAC;SAC9B,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC;SAC9C,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,SAAS,cAAc,CAAC,IAAY;IAClC,OAAO;;gDAEuC,IAAI;UAC1C,CAAC;AACX,CAAC;AAED,SAAS,wBAAwB,CAAC,MAAoB;IACpD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM;SACzB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,MAAM,UAAU,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,cAAc,UAAU,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACxG,OAAO;6BACgB,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;YACpD,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;YAChB,cAAc,CAAC,QAAQ,CAAC;;;uBAGb,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;kBACxC,KAAK,CAAC,IAAI;;yBAEH,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC;0BACrB,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;2BAChB,GAAG,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;8BACtC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;YAClC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE;YAC5C,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,iBAAiB,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YAC3D,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,yBAAyB,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;;aAEhF,CAAC;IACV,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,qFAAqF,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;;QAEpG,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;mCACD,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;QAC5C,UAAU;;MAEZ,MAAM;aACC,CAAC;AACd,CAAC;AAED,SAAS,wBAAwB,CAC/B,aAAqB,EACrB,WAAmB,EACnB,WAAmB;IAEnB,MAAM,UAAU,GAAG,cAAc,CAC/B,GAAG,CACD,8FAA8F,CAC/F,CACF,CAAC;IACF,OAAO,qFAAqF,GAAG,CAAC,wBAAwB,CAAC;;QAEnH,iBAAiB,CAAC,QAAQ,CAAC;;QAE3B,UAAU;;;;yFAIuE,GAAG,CAAC,aAAa,CAAC;;;gCAG3E,GAAG,CAAC,WAAW,CAAC;8EAC8B,GAAG,CAAC,WAAW,CAAC;;aAEjF,CAAC;AACd,CAAC;AAED,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AACtD,MAAM,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAuKnB,CAAC;AAEb,SAAS,0BAA0B,CAAC,KAAa;IAC/C,OAAO,sBAAsB,CAAC,UAAU,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AACpF,CAAC;AAeD,SAAS,oBAAoB,CAAC,OAA8B;IAC1D,MAAM,EACJ,KAAK,EACL,KAAK,EACL,WAAW,EACX,aAAa,EACb,WAAW,EACX,WAAW,EACX,QAAQ,EACR,aAAa,EACb,kBAAkB,EAClB,eAAe,GAChB,GAAG,OAAO,CAAC;IACZ,MAAM,YAAY,GAAG,aAAa;SAC/B,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QACf,MAAM,QAAQ,GAAG,OAAO,CAAC,EAAE,KAAK,kBAAkB,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;QACjF,OAAO,kBAAkB,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC;IACxF,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,MAAM,WAAW,GAAG,cAAc,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE5E,OAAO,kBAAkB,CACvB,OAAO,EACP;uBACmB,YAAY;2BACR,GAAG,CAAC,KAAK,CAAC;;OAE9B,GAAG,CAAC,QAAQ,CAAC;IAChB,oBAAoB,CAAC,eAAe,CAAC;;6DAEoB,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;2DAC5C,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;;;;;IAK/F,WAAW;IACX,wBAAwB,CAAC,aAAa,EAAE,WAAW,EAAE,WAAW,CAAC;;;;;kDAKnB,YAAY;;;;;;;;EAQ5D,0BAA0B,CAAC,KAAK,CAAC,EAAE,CAClC,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,OAAe;IACtC,OAAO,gBAAgB,CAAC,aAAa,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe;IACxC,OAAO,gBAAgB,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,iBAAiB,CAAC,IAA+B;IAIxD,IAAI,IAAI,CAAC,GAAG,IAAI,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACzE,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5C,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,6BAA6B,EAAE,CAAC;QAE7E,MAAM,OAAO,GAA2B,EAAE,CAAC;QAC3C,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,UAAU,EAAE,CAAC;YAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YAC7B,MAAM,UAAU,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;gBAAE,OAAO,EAAE,KAAK,EAAE,0BAA0B,MAAM,EAAE,EAAE,CAAC;YACjF,IAAI,CAAC,UAAU;gBAAE,OAAO,EAAE,KAAK,EAAE,6BAA6B,MAAM,EAAE,EAAE,CAAC;YACzE,OAAO,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC;QAC/B,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,CAAC;IACrB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACjD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;IACtE,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAC;IACxE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,sBAAsB,CAAC,OAAiB,EAAE,WAAW,GAAa,EAAE;IAC3E,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,qBAAqB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAChG,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,iCAAiC,UAAU,EAAE,CAAC;IACpE,CAAC;IAED,OAAO,GAAG,OAAO,CAAC,MAAM,0CAA0C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,UAAU,EAAE,CAAC;AACvG,CAAC;AAED,SAAS,qBAAqB,CAAC,OAA+B;IAC5D,MAAM,KAAK,GAAG,OAAO,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC;IAChD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAE7B,MAAM,KAAK,GAAG,CAAC,QAAQ,EAAE,SAAS,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC;IAC/C,IAAI,GAAG;QAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC;IACvC,IAAI,OAAO;QAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,OAAO,EAAE,CAAC,CAAC;IACnD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,IAA+B,EAC/B,cAAsC,EACtC,YAA0B,EAC1B,MAAgB,EAChB,GAAmB;IAEnB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC,CAAC,CAAC;QACpE,OAAO;IACT,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACnD,IAAI,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC;QACtB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,IAAI,qBAAqB,EAAE,CAAC,CAAC,CAAC;QACnE,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;IAE1F,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IAED,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,MAAM,eAAe,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAEvD,IAAI,CAAC;QACH,YAAY,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACnD,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,MAAM,GAAG,sBAAsB,CAAC,cAAc,CAAC,CAAC;YACtD,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;YACpF,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAAC,OAAO,YAAY,EAAE,CAAC;QACtB,GAAG,CAAC,UAAU,CACZ,sBAAsB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,QAAQ,IAAI,SAAS,CAAC,cAAc,EAAE,EACjG,YAAY,YAAY,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAC5E,CAAC;QACF,qBAAqB,CAAC,YAAY,EAAE;YAClC,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,kBAAkB;YAC3B,SAAS,EAAE,eAAe;YAC1B,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,OAAO,EAAE;gBACP,cAAc,EAAE,SAAS,CAAC,cAAc;gBACxC,OAAO,EAAE,SAAS,CAAC,OAAO;gBAC1B,cAAc,EAAE,IAAI,CAAC,IAAI,IAAI,QAAQ;gBACrC,WAAW,EAAE,OAAO,CAAC,MAAM;gBAC3B,eAAe,EAAE,WAAW,CAAC,MAAM;aACpC;SACF,CAAC,CAAC;QACH,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,SAAS,CAAC;YACb,KAAK,EACH,yFAAyF;SAC5F,CAAC,CACH,CAAC;QACF,OAAO;IACT,CAAC;IAED,GAAG,CAAC,OAAO,CACT,WAAW,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,QAAQ,IAAI,SAAS,CAAC,cAAc,aAAa,SAAS,CAAC,OAAO,EAAE,CACrH,CAAC;IAEF,MAAM,OAAO,GAAG,sBAAsB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAC7D,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAE/C,MAAM,CACJ,SAAS,CAAC,QAAQ,EAClB,SAAS,CAAC,cAAc,EACxB,GAAG,OAAO,aAAa,SAAS,CAAC,OAAO,KAAK,CAC9C,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;QACrB,GAAG,CAAC,UAAU,CAAC,8CAA8C,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5E,qBAAqB,CAAC,GAAG,EAAE;YACzB,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,kBAAkB;YAC3B,SAAS,EAAE,aAAa;YACxB,QAAQ,EAAE,SAAS;YACnB,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,OAAO,EAAE;gBACP,cAAc,EAAE,SAAS,CAAC,cAAc;gBACxC,OAAO,EAAE,SAAS,CAAC,OAAO;gBAC1B,cAAc,EAAE,IAAI,CAAC,IAAI,IAAI,QAAQ;gBACrC,WAAW,EAAE,OAAO,CAAC,MAAM;gBAC3B,eAAe,EAAE,WAAW,CAAC,MAAM;aACpC;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,IAA6B,EAC7B,GAAoB,EACpB,cAAsC,EACtC,WAA2C,EAC3C,GAAmB;IAEnB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QACnC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,0CAA0C,EAAE,CAAC,CAAC,CAAC;QAC/E,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACpD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,8BAA8B,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;QACnF,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACjD,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACzD,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;QAC/B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,SAAS,CAAC;YACb,KAAK,EACH,iBAAiB,OAAO,CAAC,KAAK,sBAAsB;gBACpD,WAAW,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,kBAAkB,GAAG;SACrE,CAAC,CACH,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,YAAY,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC3D,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE;QACrB,SAAS,EAAE,IAAI,CAAC,KAAK;QACrB,SAAS,EAAE,OAAO,CAAC,EAAE;QACrB,YAAY;QACZ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,kBAAkB;KAC3C,CAAC,CAAC;IAEH,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,SAAS;YAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,WAAW,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC5D,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvD,YAAY,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IACvD,YAAY,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IACrD,YAAY,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;IAC3D,YAAY,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC9C,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,YAAY,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACnE,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,IAAI,EAAE,CAAC,EAAE,CAAC;QAC7E,YAAY,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,aAAa,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACpF,YAAY,CAAC,YAAY,CAAC,GAAG,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;IAC/D,YAAY,CAAC,YAAY,CAAC,GAAG,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC;IAE/D,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;AAC9E,CAAC;AAqBD,SAAS,oBAAoB,CAAC,OAA6B;IACzD,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IAC1D,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAClD,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAChD,MAAM,UAAU,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAEjD,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,OAAO;QAAE,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEvC,IAAI,UAAU,EAAE,CAAC;QACf,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;QACnE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,+BAA+B,UAAU,EAAE,CAAC,CAAC,CAAC;QACtE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;QAC/C,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;QACnE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,6DAA6D,CAAC,CAAC,CAAC;QACxF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;QACnE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,mCAAmC,CAAC,CAAC,CAAC;QAC9D,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACvD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;QACnE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,4BAA4B,CAAC,CAAC,CAAC;QACvD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACjD,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACzD,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;QAC/B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;QACnE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,4CAA4C,CAAC,CAAC,CAAC;QACvE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;QACnE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,4DAA4D,CAAC,CAAC,CAAC;QACvF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;AAClG,CAAC;AAYD,SAAS,qBAAqB,CAAC,OAAqC;IAClE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IACjG,MAAM,WAAW,GAAG,aAAa,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC;IACvD,MAAM,YAAY,GAAG,aAAa,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC;IACzD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;QACnE,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,sDAAsD,CAAC,CAAC,CAAC;QACjF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,kBAAkB,IAAI,EAAE;QAAE,OAAO,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC;IAC/E,IAAI,YAAY,IAAI,OAAO,CAAC,kBAAkB;QAC5C,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,GAAG,YAAY,CAAC;IAErD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IACtC,IAAI,WAA+B,CAAC;IACpC,IAAI,UAAU,EAAE,IAAI,KAAK,iBAAiB,EAAE,CAAC;QAC3C,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;YACnE,GAAG,CAAC,GAAG,CACL,eAAe,CACb,uDAAuD;gBACrD,yEAAyE,CAC5E,CACF,CAAC;YACF,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,WAAW,GAAG,UAAU,CAAC,UAAU,IAAI,sBAAsB,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;QACvF,IAAI,UAAU,CAAC,MAAM;YAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC;QAChE,KAAK,MAAM,GAAG,IAAI,UAAU,CAAC,iBAAiB,IAAI,EAAE;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC;IACnF,CAAC;IAED,MAAM,aAAa,GAAa,EAAE,CAAC;IACnC,IAAI,CAAC;QACH,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpC,YAAY,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACnD,aAAa,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,UAAU,EAAE,IAAI,KAAK,iBAAiB,IAAI,YAAY,EAAE,CAAC;YAC3D,YAAY,CAAC,UAAU,CACrB,SAAS,CAAC,OAAO,EACjB,UAAU,CAAC,YAAY,EACvB,8BAA8B,CAAC,QAAQ,EAAE,YAAY,EAAE,YAAY,CAAC,EACpE,UAAU,CAAC,UAAU,CACtB,CAAC;YACF,IAAI,WAAW;gBAAE,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAAC,OAAO,YAAY,EAAE,CAAC;QACtB,GAAG,CAAC,UAAU,CACZ,2CAA2C,SAAS,CAAC,QAAQ,IAAI,SAAS,CAAC,cAAc,EAAE,EAC3F,YAAY,YAAY,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAC5E,CAAC;QACF,qBAAqB,CAAC,YAAY,EAAE;YAClC,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,OAAO;YAChB,SAAS,EAAE,eAAe;YAC1B,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,OAAO,EAAE;gBACP,cAAc,EAAE,SAAS,CAAC,cAAc;gBACxC,OAAO,EAAE,SAAS,CAAC,OAAO;gBAC1B,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,cAAc,EAAE,OAAO;gBACvB,iBAAiB,EAAE,aAAa,CAAC,MAAM;aACxC;SACF,CAAC,CAAC;QACH,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;QACnE,GAAG,CAAC,GAAG,CACL,eAAe,CACb,8GAA8G,CAC/G,CACF,CAAC;QACF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,OAA6B;IAC9D,MAAM,QAAQ,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC;IACpF,MAAM,WAAW,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IACpE,MAAM,aAAa,GAAG,MAAM,iBAAiB,CAAC;QAC5C,OAAO;QACP,IAAI;QACJ,QAAQ;QACR,YAAY;QACZ,WAAW;QACX,YAAY;KACb,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,qBAAqB,CAAC;QAC1C,aAAa;QACb,OAAO;QACP,QAAQ;QACR,YAAY;QACZ,SAAS;QACT,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC,CAAC;IACH,IAAI,CAAC,aAAa;QAAE,OAAO;IAE3B,GAAG,CAAC,OAAO,CACT,WAAW,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,QAAQ,IAAI,SAAS,CAAC,cAAc,aAAa,SAAS,CAAC,OAAO,EAAE,CAC3H,CAAC;IACF,OAAO;SACJ,MAAM,CACL,SAAS,CAAC,QAAQ,EAClB,SAAS,CAAC,cAAc,EACxB,GAAG,OAAO,CAAC,KAAK,kBAAkB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,SAAS,CAAC,OAAO,KAAK,CACjG;SACA,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;QACpB,GAAG,CAAC,UAAU,CAAC,yCAAyC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QACvE,qBAAqB,CAAC,GAAG,EAAE;YACzB,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,OAAO;YAChB,SAAS,EAAE,aAAa;YACxB,QAAQ,EAAE,SAAS;YACnB,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,OAAO,EAAE;gBACP,cAAc,EAAE,SAAS,CAAC,cAAc;gBACxC,OAAO,EAAE,SAAS,CAAC,OAAO;gBAC1B,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,cAAc,EAAE,OAAO;gBACvB,iBAAiB,EAAE,aAAa,CAAC,MAAM;aACxC;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEL,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,KAAK,gCAAgC,CAAC,CAAC,CAAC;AACvF,CAAC;AAWD,KAAK,UAAU,iBAAiB,CAC9B,OAAiC;IAEjC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;IACrF,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAAC;IAC/C,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzB,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAClC,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;IAC1C,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;IACxC,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;IAE1C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE;QAC7C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,mCAAmC;YACnD,MAAM,EAAE,kBAAkB;SAC3B;QACD,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE;KACxB,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IAC/D,IAAI,MAAM,GAA2B,EAAE,CAAC;IAExC,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC7C,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA2B,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,CAAC,iBAAiB,IAAI,MAAM,CAAC,KAAK,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;QACjF,MAAM,IAAI,KAAK,CAAC,mCAAmC,OAAO,CAAC,EAAE,KAAK,OAAO,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,8BAA8B,CACrC,QAAgB,EAChB,YAAoB,EACpB,YAAoB;IAEpB,OAAO,CACL,IAAI,CAAC,SAAS,CACZ;QACE,SAAS,EAAE,QAAQ;QACnB,aAAa,EAAE,YAAY;QAC3B,aAAa,EAAE,YAAY;QAC3B,IAAI,EAAE,iBAAiB;KACxB,EACD,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,CACT,CAAC;AACJ,CAAC","sourcesContent":["import { createHash, randomBytes } from \"node:crypto\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { escapeHtml, readJsonBody, renderPortalShell, requestBaseUrl } from \"../portal-shell.js\";\nimport { resolveLinkBaseUrl } from \"../../../env-manifest.js\";\nimport { readEnv } from \"../../../env-manifest.js\";\nimport type { PlatformName } from \"../../index.js\";\nimport { InMemoryTokenStore } from \"../token-store.js\";\nimport type { LinkToken } from \"./types.js\";\nexport type { LinkToken } from \"./types.js\";\nimport {\n getOAuthServices,\n resolveOAuthService,\n type LoginCredentialKind,\n type OAuthService,\n} from \"./oauth.js\";\nimport * as log from \"../../../log.js\";\nimport { reportUserFacingError } from \"../../../observability/index.js\";\nimport { PRODUCT_NAME } from \"../../messages.js\";\nimport { defaultVaultTargetPath, type VaultManager } from \"../../../vault/index.js\";\n\nexport type { NotifyFn } from \"./types.js\";\n\nconst TTL_MS = 15 * 60 * 1000;\n\nexport class InMemoryLinkTokenStore extends InMemoryTokenStore<LinkToken> {\n create(\n platform: PlatformName,\n platformUserId: string,\n conversationId: string,\n vaultId: string,\n providerId: string,\n ): LinkToken {\n this.deleteWhere(\n (token) => token.platform === platform && token.platformUserId === platformUserId,\n );\n return this.createRecord(TTL_MS, {\n platform,\n platformUserId,\n vaultId,\n providerId,\n conversationId,\n });\n }\n}\nimport type { NotifyFn } from \"./types.js\";\n\ninterface LinkCompleteBody {\n token: string;\n mode?: LoginCredentialKind;\n envKey?: string;\n credential?: string;\n env?: Record<string, string>;\n}\n\ninterface OAuthStartBody {\n token: string;\n serviceId: string;\n}\n\ninterface PendingOAuthState {\n linkToken: string;\n serviceId: string;\n codeVerifier: string;\n expiresAt: number;\n}\n\ninterface SecretPresetField {\n envKey: string;\n envKeys?: string[];\n label: string;\n type: \"text\" | \"password\";\n placeholder: string;\n helpText: string;\n optional?: boolean;\n pattern?: string;\n patternMessage?: string;\n}\n\ninterface SecretPreset {\n id: string;\n label: string;\n description: string;\n note?: string;\n fields: SecretPresetField[];\n}\n\nconst OAUTH_STATE_TTL_MS = 10 * 60 * 1000;\nconst DEFAULT_SECRET_CONFIG_ID = \"manual\";\nconst SECRET_PRESETS: SecretPreset[] = [\n {\n id: \"cloudflare_wrangler\",\n label: \"Cloudflare / Wrangler\",\n description:\n \"Store a Cloudflare API token and account ID for Wrangler, Workers, Pages, D1, and KV.\",\n note: \"Create a scoped API Token from Cloudflare Dashboard → My Profile → API Tokens. Do not use the Global API Key.\",\n fields: [\n {\n envKey: \"CLOUDFLARE_API_TOKEN\",\n label: \"Cloudflare API Token\",\n type: \"password\",\n placeholder: \"cfut_...\",\n helpText: \"Recommended for Wrangler, CI, and sandbox use.\",\n },\n {\n envKey: \"CLOUDFLARE_ACCOUNT_ID\",\n label: \"Cloudflare Account ID\",\n type: \"text\",\n placeholder: \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n helpText: \"Find this via wrangler whoami or in the Cloudflare dashboard account page.\",\n pattern: \"^[A-Fa-f0-9]{32}$\",\n patternMessage: \"Account ID must be a 32-character hexadecimal string.\",\n },\n ],\n },\n {\n id: \"openai\",\n label: \"OpenAI\",\n description: \"Store an OpenAI API key for tools and SDKs that use OPENAI_API_KEY.\",\n note: \"Create a standard API key from the OpenAI dashboard. Paste the key exactly as issued.\",\n fields: [\n {\n envKey: \"OPENAI_API_KEY\",\n label: \"OpenAI API Key\",\n type: \"password\",\n placeholder: \"sk-...\",\n helpText: \"Used by the OpenAI SDK, CLI wrappers, and many coding tools.\",\n },\n ],\n },\n {\n id: \"anthropic\",\n label: \"Anthropic\",\n description: \"Store an Anthropic API key for Claude and tools that use ANTHROPIC_API_KEY.\",\n note: \"Create this key from the Anthropic Console. Use a workspace-scoped key when possible.\",\n fields: [\n {\n envKey: \"ANTHROPIC_API_KEY\",\n label: \"Anthropic API Key\",\n type: \"password\",\n placeholder: \"sk-ant-...\",\n helpText: \"Used by Claude integrations and Anthropic-compatible tooling.\",\n },\n ],\n },\n {\n id: \"gemini\",\n label: \"Gemini\",\n description:\n \"Store one Google AI Studio key and expose it as both GEMINI_API_KEY and GOOGLE_API_KEY.\",\n note: \"Create a Gemini / Google AI Studio API key, then paste it once here for compatibility with both env names.\",\n fields: [\n {\n envKey: \"GEMINI_API_KEY\",\n envKeys: [\"GEMINI_API_KEY\", \"GOOGLE_API_KEY\"],\n label: \"Gemini API Key\",\n type: \"password\",\n placeholder: \"AIza...\",\n helpText: \"One value will be written to both GEMINI_API_KEY and GOOGLE_API_KEY.\",\n },\n ],\n },\n {\n id: \"openrouter\",\n label: \"OpenRouter\",\n description: \"Store an OpenRouter API key for tools that route models through OpenRouter.\",\n note: \"Create a key from the OpenRouter dashboard and paste it here.\",\n fields: [\n {\n envKey: \"OPENROUTER_API_KEY\",\n label: \"OpenRouter API Key\",\n type: \"password\",\n placeholder: \"sk-or-v1-...\",\n helpText: \"Used by OpenRouter SDKs and compatible model gateways.\",\n },\n ],\n },\n {\n id: \"github_pat\",\n label: \"GitHub PAT\",\n description:\n \"Store one GitHub personal access token and expose it as both GH_TOKEN and GITHUB_TOKEN.\",\n note: \"Create a fine-grained or classic personal access token from GitHub Settings → Developer settings.\",\n fields: [\n {\n envKey: \"GH_TOKEN\",\n envKeys: [\"GH_TOKEN\", \"GITHUB_TOKEN\"],\n label: \"GitHub Personal Access Token\",\n type: \"password\",\n placeholder: \"github_pat_...\",\n helpText: \"One value will be written to both GH_TOKEN and GITHUB_TOKEN.\",\n },\n ],\n },\n {\n id: \"vercel\",\n label: \"Vercel\",\n description: \"Store a Vercel token plus optional org and project IDs for deployment tooling.\",\n note: \"Create a token from the Vercel dashboard. Org ID and Project ID are optional but useful for scripted deploys.\",\n fields: [\n {\n envKey: \"VERCEL_TOKEN\",\n label: \"Vercel Token\",\n type: \"password\",\n placeholder: \"vercel_...\",\n helpText: \"Required for Vercel CLI and API access.\",\n },\n {\n envKey: \"VERCEL_ORG_ID\",\n label: \"Vercel Org ID\",\n type: \"text\",\n placeholder: \"team_...\",\n helpText: \"Optional. Set this when you want to target a specific team or account.\",\n optional: true,\n },\n {\n envKey: \"VERCEL_PROJECT_ID\",\n label: \"Vercel Project ID\",\n type: \"text\",\n placeholder: \"prj_...\",\n helpText: \"Optional. Set this when deploy scripts need a fixed project reference.\",\n optional: true,\n },\n ],\n },\n {\n id: \"sentry\",\n label: \"Sentry\",\n description:\n \"Store a Sentry auth token plus optional org/project, and mount ~/.sentryclirc for sentry-cli.\",\n note: \"Create an auth token from Sentry Settings → Account → API → Auth Tokens. Saving this preset also writes /root/.sentryclirc for sentry-cli.\",\n fields: [\n {\n envKey: \"SENTRY_AUTH_TOKEN\",\n label: \"Sentry Auth Token\",\n type: \"password\",\n placeholder: \"sntrys_...\",\n helpText:\n \"Required for Sentry CLI, releases, and sourcemap uploads. Also written to /root/.sentryclirc.\",\n },\n {\n envKey: \"SENTRY_ORG\",\n label: \"Sentry Org Slug\",\n type: \"text\",\n placeholder: \"my-org\",\n helpText: \"Optional. Helpful for Sentry CLI commands and CI automation.\",\n optional: true,\n },\n {\n envKey: \"SENTRY_PROJECT\",\n label: \"Sentry Project Slug\",\n type: \"text\",\n placeholder: \"my-project\",\n helpText: \"Optional. Helpful for release and sourcemap commands.\",\n optional: true,\n },\n ],\n },\n];\n\nexport function createLoginRequestHandler(\n linkTokenStore: InMemoryLinkTokenStore,\n vaultManager: VaultManager,\n notify: NotifyFn,\n): (req: IncomingMessage, res: ServerResponse, url: URL) => boolean {\n const oauthStates = new Map<string, PendingOAuthState>();\n\n return (req, res, url) => {\n if (req.method === \"GET\" && url.pathname === \"/link\") {\n const rawToken = url.searchParams.get(\"token\") ?? \"\";\n const linkToken = linkTokenStore.peek(rawToken);\n\n if (!linkToken) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n renderErrorPage(\n \"This link is invalid or has expired. Ask the bot for a new /login link.\",\n ),\n );\n return true;\n }\n\n const oauthServiceHint = linkToken.providerId\n ? resolveOAuthService(linkToken.providerId)\n : undefined;\n const oauthServices = getOAuthServices();\n const defaultMode: LoginCredentialKind = oauthServiceHint ? \"oauth\" : \"api_key\";\n const existingSecrets = describeVaultSecrets(vaultManager, linkToken.vaultId);\n\n res.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n renderCredentialPage({\n token: rawToken,\n title: oauthServiceHint ? `${oauthServiceHint.label} OAuth` : \"Store Secret\",\n defaultMode,\n initialEnvKey: \"\",\n secretLabel: \"Secret value\",\n placeholder: \"sk-...\",\n helpText: oauthServiceHint\n ? `Authorize ${oauthServiceHint.label} and store tokens in your vault.`\n : \"Set any environment variable key/value pair in your vault.\",\n oauthServices,\n oauthServiceIdHint: oauthServiceHint?.id,\n existingSecrets,\n }),\n );\n return true;\n }\n\n if (req.method === \"POST\" && url.pathname === \"/api/link/complete\") {\n if (!enforceCsrf(req, res)) return true;\n void readJsonBody(req, res, 16 * 1024).then((body) => {\n if (body === null) return;\n return handleLinkComplete(\n body as Partial<LinkCompleteBody>,\n linkTokenStore,\n vaultManager,\n notify,\n res,\n );\n });\n return true;\n }\n\n if (req.method === \"POST\" && url.pathname === \"/api/oauth/start\") {\n if (!enforceCsrf(req, res)) return true;\n void readJsonBody(req, res, 16 * 1024).then((body) => {\n if (body === null) return;\n return handleOAuthStart(\n body as Partial<OAuthStartBody>,\n req,\n linkTokenStore,\n oauthStates,\n res,\n );\n });\n return true;\n }\n\n if (req.method === \"GET\" && url.pathname === \"/oauth/callback\") {\n void handleOAuthCallback({\n url,\n req,\n linkTokenStore,\n vaultManager,\n notify,\n oauthStates,\n res,\n }).catch((err: Error) => {\n log.logWarning(\"OAuth callback failed\", err.message);\n reportUserFacingError(err, {\n domain: \"login\",\n surface: \"oauth\",\n operation: \"oauth_callback\",\n severity: \"error\",\n context: { route: \"/oauth/callback\" },\n });\n res.writeHead(500, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(\"OAuth callback failed. Please retry /login.\"));\n });\n return true;\n }\n\n return false;\n };\n}\n\nfunction enforceCsrf(req: IncomingMessage, res: ServerResponse): boolean {\n const contentType = (req.headers[\"content-type\"] as string | undefined)\n ?.split(\";\")[0]\n ?.trim()\n .toLowerCase();\n if (contentType !== \"application/json\") {\n res.writeHead(415, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Content-Type must be application/json\" }));\n return false;\n }\n\n const configured = resolveLinkBaseUrl();\n if (!configured) {\n return true;\n }\n\n let configuredOrigin: string;\n try {\n configuredOrigin = new URL(configured).origin;\n } catch {\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Server misconfiguration\" }));\n return false;\n }\n\n if (requestOrigin(req) !== configuredOrigin) {\n res.writeHead(403, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Cross-origin request rejected\" }));\n return false;\n }\n\n return true;\n}\n\nfunction requestOrigin(req: IncomingMessage): string | undefined {\n const origin = (req.headers.origin as string | undefined)?.trim();\n if (origin && origin !== \"null\") return origin;\n\n const referer = (req.headers.referer as string | undefined)?.trim();\n if (!referer) return undefined;\n try {\n return new URL(referer).origin;\n } catch {\n return undefined;\n }\n}\n\nconst esc = escapeHtml;\n\nconst loginViewStyles = `\n\n\n p { margin: 0; color: var(--muted); font-size: 0.92rem; line-height: 1.55; }\n\n .stack > * + * { margin-top: 14px; }\n\n label {\n display: block;\n margin-bottom: 6px;\n font-size: 0.86rem;\n font-weight: 600;\n color: var(--text);\n }\n\n input, select {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid var(--border);\n border-radius: 10px;\n background: #fff;\n color: var(--text);\n font: inherit;\n }\n\n input:focus-visible,\n select:focus-visible {\n outline: 2px solid var(--text);\n outline-offset: 1px;\n }\n\n .primary-button {\n width: 100%;\n padding: 12px 18px;\n border: none;\n border-radius: 12px;\n background: var(--text);\n color: #fff;\n cursor: pointer;\n font: 500 0.95rem/1.2 'DM Sans', sans-serif;\n transition: opacity 120ms;\n }\n\n .primary-button:hover:not(:disabled) { opacity: 0.85; }\n .primary-button:disabled { opacity: 0.5; cursor: default; }\n\n .service-logo {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n border-radius: 10px;\n flex: 0 0 36px;\n background: #1c1e21;\n color: #fff;\n }\n\n .service-logo svg {\n display: block;\n width: 20px;\n height: 20px;\n }\n\n .service-logo-text {\n font-size: 11px;\n font-weight: 800;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n }\n\n .service-logo.cloudflare {\n background: linear-gradient(180deg, #ffb66d 0%, #f48120 100%);\n }\n\n .service-logo.openai {\n background: linear-gradient(180deg, #3e4045 0%, #111315 100%);\n }\n\n .service-logo.anthropic {\n background: linear-gradient(180deg, #d6b48c 0%, #9a6d3a 100%);\n }\n\n .service-logo.gemini {\n background: linear-gradient(180deg, #8ab4ff 0%, #5b6cff 100%);\n }\n\n .service-logo.openrouter {\n background: linear-gradient(180deg, #8c8cff 0%, #4f46e5 100%);\n }\n\n .service-logo.github {\n background: linear-gradient(180deg, #4a4f57 0%, #1b1f23 100%);\n }\n\n .service-logo.vercel {\n background: linear-gradient(180deg, #4a4f57 0%, #000 100%);\n }\n\n .service-logo.sentry {\n background: linear-gradient(180deg, #7c5cff 0%, #3f2e8c 100%);\n }\n\n .service-logo.manual {\n background: linear-gradient(180deg, #43474d 0%, #1c1e21 100%);\n }\n\n .provider-card > * + * {\n margin-top: 14px;\n }\n\n .provider-header {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .provider-title {\n flex: 1;\n margin: 0;\n font-size: 1rem;\n font-weight: 650;\n line-height: 1.3;\n }\n\n .provider-field label {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n }\n\n .help {\n position: relative;\n display: inline-flex;\n align-items: center;\n }\n\n .help-trigger {\n width: 18px;\n height: 18px;\n padding: 0;\n border: 1px solid var(--border);\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.9);\n color: var(--muted);\n font-size: 11px;\n font-weight: 700;\n line-height: 1;\n cursor: pointer;\n }\n\n .help-trigger:hover {\n color: var(--text);\n border-color: var(--text);\n }\n\n .help-content {\n display: none;\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n z-index: 10;\n width: max-content;\n max-width: 280px;\n padding: 10px 12px;\n border: 1px solid var(--border);\n border-radius: 10px;\n background: #fff;\n color: var(--text);\n font-size: 0.85rem;\n font-weight: 400;\n line-height: 1.45;\n box-shadow: 0 8px 24px rgba(28, 30, 33, 0.12);\n white-space: normal;\n }\n\n .help-trigger[aria-expanded=\"true\"] + .help-content {\n display: block;\n }\n\n .help-trigger[aria-expanded=\"true\"] {\n color: var(--text);\n border-color: var(--text);\n }\n\n .mode {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n margin-top: 22px;\n }\n\n .mode label {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin: 0;\n padding: 10px 12px;\n border: 1px solid var(--border);\n border-radius: 999px;\n background: rgba(255, 255, 255, 0.85);\n font-weight: 500;\n }\n\n .mode input {\n width: auto;\n margin: 0;\n }\n\n .panel {\n display: none;\n }\n\n .panel.active {\n display: block;\n }\n\n #api-panel.active {\n display: grid;\n gap: 16px;\n }\n\n .panel-note {\n margin-top: 10px;\n font-size: 0.92rem;\n }\n\n .result,\n .status {\n margin-top: 20px;\n padding: 14px 16px;\n border-radius: 14px;\n font-size: 0.95rem;\n }\n\n .result {\n display: none;\n }\n\n .result.ok,\n .status.ok {\n background: var(--ok-bg);\n color: var(--ok-text);\n }\n\n .result.err,\n .status.err {\n background: var(--err-bg);\n color: var(--err-text);\n }\n\n .secrets-summary {\n margin-top: 18px;\n padding: 14px 16px;\n border: 1px solid var(--border);\n border-radius: 14px;\n background: rgba(255, 255, 255, 0.72);\n }\n\n .secrets-summary h2 {\n margin: 0 0 8px;\n font-size: 0.98rem;\n }\n\n .secrets-summary p {\n font-size: 0.92rem;\n }\n\n .secrets-summary ul {\n margin: 10px 0 0;\n padding-left: 18px;\n color: var(--text);\n }\n\n .secrets-summary li + li {\n margin-top: 6px;\n }\n\n .close-note {\n margin-top: 14px;\n font-size: 0.92rem;\n }\n\n @media (max-width: 640px) {\n .mode label { flex: 1; justify-content: center; }\n input, select { padding: 12px; }\n .primary-button { padding: 14px 18px; }\n .help-content { max-width: min(260px, calc(100vw - 40px)); }\n .provider-header .help-content { left: auto; right: 0; }\n }\n`;\n\nfunction renderHtmlDocument(title: string, shellContent: string): string {\n return renderPortalShell({\n activeView: \"vault\",\n pageTitle: \"Vault\",\n body: shellContent,\n extraStyles: loginViewStyles,\n });\n}\n\nfunction renderStatusPage(\n title: string,\n message: string,\n tone: \"ok\" | \"err\",\n options?: { closeNote?: boolean },\n): string {\n const closeNote = options?.closeNote ? '<p class=\"close-note\">You can close this tab.</p>' : \"\";\n return renderHtmlDocument(\n title,\n `<section class=\"card\"><div class=\"stack\">\n <p class=\"eyebrow\">${PRODUCT_NAME}</p>\n <h1 class=\"page-title\">${esc(title)}</h1>\n <div class=\"status ${tone}\">${esc(message)}</div>\n ${closeNote}\n </div></section>`,\n );\n}\n\ninterface ExistingSecretsSummary {\n envKeys: string[];\n mountTargets: string[];\n}\n\nfunction describeVaultSecrets(vaultManager: VaultManager, vaultId: string): ExistingSecretsSummary {\n const vault = vaultManager.resolve(vaultId);\n if (!vault) {\n return { envKeys: [], mountTargets: [] };\n }\n\n return {\n envKeys: Object.keys(vault.env).toSorted((left, right) => left.localeCompare(right)),\n mountTargets: [...new Set(vault.mounts.map((mount) => mount.target))].toSorted((left, right) =>\n left.localeCompare(right),\n ),\n };\n}\n\nfunction renderSecretsSummary(summary: ExistingSecretsSummary): string {\n if (summary.envKeys.length === 0 && summary.mountTargets.length === 0) {\n return `\n <section class=\"secrets-summary\">\n <h2>Currently stored</h2>\n <p>No secrets are stored in this vault yet.</p>\n </section>`;\n }\n\n const envItems = summary.envKeys.map((envKey) => `<li><code>${esc(envKey)}</code></li>`).join(\"\");\n const mountItems = summary.mountTargets\n .map((target) => `<li><code>${esc(target)}</code></li>`)\n .join(\"\");\n\n return `\n <section class=\"secrets-summary\">\n <h2>Currently stored</h2>\n <p>Only secret names and mounted paths are shown here. Secret values are never displayed.</p>\n ${summary.envKeys.length > 0 ? `<p><strong>Environment keys</strong></p><ul>${envItems}</ul>` : \"\"}\n ${summary.mountTargets.length > 0 ? `<p><strong>Mounted secret files</strong></p><ul>${mountItems}</ul>` : \"\"}\n </section>`;\n}\n\nfunction renderServiceLogo(kind: string): string {\n if (kind === \"cloudflare_wrangler\") {\n return `<span class=\"service-logo cloudflare\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\">\n <path d=\"M8.5 17.5h8.2a2.9 2.9 0 0 0 .4-5.78A4.45 4.45 0 0 0 8.9 10.4a3.7 3.7 0 0 0-.4 7.1Z\" fill=\"white\" fill-opacity=\"0.98\"/>\n <path d=\"M6.6 17.5h5.1a2.3 2.3 0 0 0 0-4.6 3.1 3.1 0 0 0-3-2.2 3.23 3.23 0 0 0-3.18 3.64A2.67 2.67 0 0 0 6.6 17.5Z\" fill=\"white\"/>\n </svg>\n </span>`;\n }\n\n const textLogos: Record<string, { className: string; text: string }> = {\n openai: { className: \"openai\", text: \"OA\" },\n anthropic: { className: \"anthropic\", text: \"AI\" },\n gemini: { className: \"gemini\", text: \"G\" },\n openrouter: { className: \"openrouter\", text: \"OR\" },\n github_pat: { className: \"github\", text: \"GH\" },\n vercel: { className: \"vercel\", text: \"V\" },\n sentry: { className: \"sentry\", text: \"S\" },\n manual: { className: \"manual\", text: \">_\" },\n };\n const logo = textLogos[kind] ?? textLogos.manual ?? { className: \"manual\", text: \">_\" };\n return `<span class=\"service-logo ${logo.className}\" aria-hidden=\"true\"><span class=\"service-logo-text\">${logo.text}</span></span>`;\n}\n\nfunction resolveFieldEnvKeys(field: SecretPresetField): string[] {\n return field.envKeys && field.envKeys.length > 0 ? field.envKeys : [field.envKey];\n}\n\nfunction renderStoredEnvKeysInline(field: SecretPresetField): string {\n return resolveFieldEnvKeys(field)\n .map((envKey) => `<code>${esc(envKey)}</code>`)\n .join(\", \");\n}\n\nfunction renderHelpIcon(html: string): string {\n return `<span class=\"help\">\n <button type=\"button\" class=\"help-trigger\" aria-label=\"More info\" aria-expanded=\"false\">?</button>\n <span class=\"help-content\" role=\"tooltip\">${html}</span>\n </span>`;\n}\n\nfunction renderPresetProviderCard(preset: SecretPreset): string {\n const headerHelp = preset.note ? renderHelpIcon(esc(preset.note)) : \"\";\n const fields = preset.fields\n .map((field) => {\n const storedKeys = renderStoredEnvKeysInline(field);\n const helpText = `${esc(field.helpText)} Stored as ${storedKeys}.${field.optional ? \" Optional.\" : \"\"}`;\n return `<div class=\"provider-field\">\n <label for=\"preset-${esc(preset.id)}-${esc(field.envKey)}\">\n ${esc(field.label)}\n ${renderHelpIcon(helpText)}\n </label>\n <input\n id=\"preset-${esc(preset.id)}-${esc(field.envKey)}\"\n type=\"${field.type}\"\n autocomplete=\"off\"\n placeholder=\"${esc(field.placeholder)}\"\n data-env-key=\"${esc(field.envKey)}\"\n data-env-keys=\"${esc(resolveFieldEnvKeys(field).join(\",\"))}\"\n data-field-label=\"${esc(field.label)}\"\n ${field.optional ? 'data-optional=\"true\"' : \"\"}\n ${field.pattern ? `data-pattern=\"${esc(field.pattern)}\"` : \"\"}\n ${field.patternMessage ? `data-pattern-message=\"${esc(field.patternMessage)}\"` : \"\"}\n >\n </div>`;\n })\n .join(\"\\n\");\n\n return `<section class=\"card provider-card\" data-provider-kind=\"preset\" data-provider-id=\"${esc(preset.id)}\">\n <div class=\"provider-header\">\n ${renderServiceLogo(preset.id)}\n <h2 class=\"provider-title\">${esc(preset.label)}</h2>\n ${headerHelp}\n </div>\n ${fields}\n </section>`;\n}\n\nfunction renderManualProviderCard(\n initialEnvKey: string,\n secretLabel: string,\n placeholder: string,\n): string {\n const headerHelp = renderHelpIcon(\n esc(\n \"Set any environment variable key/value pair manually. Use this when no provider preset fits.\",\n ),\n );\n return `<section class=\"card provider-card\" data-provider-kind=\"manual\" data-provider-id=\"${esc(DEFAULT_SECRET_CONFIG_ID)}\">\n <div class=\"provider-header\">\n ${renderServiceLogo(\"manual\")}\n <h2 class=\"provider-title\">Manual entry</h2>\n ${headerHelp}\n </div>\n <div class=\"provider-field\">\n <label for=\"envKey\">Environment key</label>\n <input id=\"envKey\" type=\"text\" name=\"envKey\" placeholder=\"OPENAI_API_KEY\" value=\"${esc(initialEnvKey)}\" autocomplete=\"off\">\n </div>\n <div class=\"provider-field\">\n <label for=\"credential\">${esc(secretLabel)}</label>\n <input id=\"credential\" type=\"password\" name=\"credential\" placeholder=\"${esc(placeholder)}\" autocomplete=\"off\">\n </div>\n </section>`;\n}\n\nconst CREDENTIAL_PAGE_TOKEN = \"__MIKAN_LOGIN_TOKEN__\";\nconst CREDENTIAL_PAGE_SCRIPT = ` <script>\n const envKeyPattern = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n function selectedMode() {\n return document.querySelector('input[name=\"mode\"]:checked').value;\n }\n\n function showResult(message, ok) {\n const result = document.getElementById('result');\n result.style.display = 'block';\n result.className = ok ? 'result ok' : 'result err';\n result.textContent = message;\n }\n\n function resetContinueButton() {\n const btn = document.getElementById('btn');\n btn.disabled = false;\n btn.textContent = 'Continue';\n }\n\n function syncPanels() {\n const mode = selectedMode();\n document.getElementById('api-panel').classList.toggle('active', mode === 'api_key');\n document.getElementById('oauth-panel').classList.toggle('active', mode === 'oauth');\n }\n\n function collectManualCard(card) {\n const envKey = card.querySelector('#envKey').value.trim();\n const credential = card.querySelector('#credential').value.trim();\n if (!envKey && !credential) return { skip: true };\n if (!envKeyPattern.test(envKey)) return { error: 'Manual entry: please enter a valid environment key.' };\n if (!credential) return { error: 'Manual entry: please enter a secret value.' };\n return { env: { [envKey]: credential } };\n }\n\n function collectPresetCard(card) {\n const inputs = card.querySelectorAll('input[data-env-key]');\n const filled = Array.from(inputs).some((input) => input.value.trim() !== '');\n if (!filled) return { skip: true };\n\n const env = {};\n for (const input of inputs) {\n const value = input.value.trim();\n const label = input.dataset.fieldLabel || input.dataset.envKey || 'a value';\n const optional = input.dataset.optional === 'true';\n if (!value) {\n if (optional) continue;\n return { error: 'Please enter ' + label + '.' };\n }\n if (input.dataset.pattern && !(new RegExp(input.dataset.pattern).test(value))) {\n return { error: input.dataset.patternMessage || ('Invalid ' + label + '.') };\n }\n const envKeys = (input.dataset.envKeys || input.dataset.envKey || '')\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean);\n for (const envKey of envKeys) {\n env[envKey] = value;\n }\n }\n return { env };\n }\n\n function collectApiEnv() {\n const env = {};\n let any = false;\n for (const card of document.querySelectorAll('.provider-card')) {\n const result = card.dataset.providerKind === 'manual'\n ? collectManualCard(card)\n : collectPresetCard(card);\n if (result.skip) continue;\n if (result.error) return { error: result.error };\n Object.assign(env, result.env);\n any = true;\n }\n if (!any) return { error: 'Fill in at least one provider before continuing.' };\n return { env };\n }\n\n async function startOAuthFlow() {\n const serviceId = document.getElementById('oauthService').value;\n const r = await fetch('/api/oauth/start', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token: '__MIKAN_LOGIN_TOKEN__', serviceId }),\n });\n const data = await r.json();\n if (!r.ok) {\n showResult('Error: ' + (data.error ?? r.status), false);\n resetContinueButton();\n return;\n }\n window.location.href = data.redirectUrl;\n }\n\n async function saveApiSecrets() {\n const payload = collectApiEnv();\n if (payload.error) {\n showResult(payload.error, false);\n resetContinueButton();\n return;\n }\n\n const r = await fetch('/api/link/complete', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token: '__MIKAN_LOGIN_TOKEN__', mode: 'api_key', env: payload.env }),\n });\n const data = await r.json();\n if (r.ok) {\n showResult(data.message ?? 'Credential stored. You can close this tab.', true);\n document.getElementById('btn').style.display = 'none';\n for (const input of document.querySelectorAll('input,select,button')) input.disabled = true;\n } else {\n showResult('Error: ' + (data.error ?? r.status), false);\n resetContinueButton();\n }\n }\n\n let openHelp = null;\n function closeOpenHelp() {\n if (openHelp) {\n openHelp.setAttribute('aria-expanded', 'false');\n openHelp = null;\n }\n }\n\n for (const trigger of document.querySelectorAll('.help-trigger')) {\n trigger.addEventListener('click', (event) => {\n event.stopPropagation();\n const wasOpen = trigger.getAttribute('aria-expanded') === 'true';\n closeOpenHelp();\n if (!wasOpen) {\n trigger.setAttribute('aria-expanded', 'true');\n openHelp = trigger;\n }\n });\n }\n\n document.addEventListener('click', closeOpenHelp);\n document.addEventListener('keydown', (event) => {\n if (event.key === 'Escape') closeOpenHelp();\n });\n\n for (const radio of document.querySelectorAll('input[name=\"mode\"]')) {\n radio.addEventListener('change', syncPanels);\n }\n\n syncPanels();\n\n async function connect() {\n const btn = document.getElementById('btn');\n const mode = selectedMode();\n btn.disabled = true;\n btn.textContent = mode === 'oauth' ? 'Redirecting…' : 'Saving…';\n\n try {\n if (mode === 'oauth') {\n await startOAuthFlow();\n return;\n }\n await saveApiSecrets();\n } catch (err) {\n showResult('Network error: ' + (err?.message ?? err), false);\n resetContinueButton();\n }\n }\n </script>`;\n\nfunction renderCredentialPageScript(token: string): string {\n return CREDENTIAL_PAGE_SCRIPT.replaceAll(CREDENTIAL_PAGE_TOKEN, () => esc(token));\n}\n\ninterface CredentialPageOptions {\n token: string;\n title: string;\n defaultMode: LoginCredentialKind;\n initialEnvKey: string;\n secretLabel: string;\n placeholder: string;\n helpText: string;\n oauthServices: OAuthService[];\n oauthServiceIdHint: string | undefined;\n existingSecrets: ExistingSecretsSummary;\n}\n\nfunction renderCredentialPage(options: CredentialPageOptions): string {\n const {\n token,\n title,\n defaultMode,\n initialEnvKey,\n secretLabel,\n placeholder,\n helpText,\n oauthServices,\n oauthServiceIdHint,\n existingSecrets,\n } = options;\n const oauthOptions = oauthServices\n .map((service) => {\n const selected = service.id === oauthServiceIdHint ? ' selected=\"selected\"' : \"\";\n return `<option value=\"${esc(service.id)}\"${selected}>${esc(service.label)}</option>`;\n })\n .join(\"\\n\");\n const presetCards = SECRET_PRESETS.map(renderPresetProviderCard).join(\"\\n\");\n\n return renderHtmlDocument(\n \"Login\",\n `<section class=\"card stack\">\n <p class=\"eyebrow\">${PRODUCT_NAME}</p>\n <h1 class=\"page-title\">${esc(title)}</h1>\n <p>Your personal sandbox is already provisioned automatically.</p>\n <p>${esc(helpText)}</p>\n ${renderSecretsSummary(existingSecrets)}\n <div class=\"mode\">\n <label><input type=\"radio\" name=\"mode\" value=\"api_key\" ${defaultMode === \"api_key\" ? \"checked\" : \"\"}> Secrets / API tokens</label>\n <label><input type=\"radio\" name=\"mode\" value=\"oauth\" ${defaultMode === \"oauth\" ? \"checked\" : \"\"}> OAuth login</label>\n </div>\n</section>\n\n<div id=\"api-panel\" class=\"panel\">\n ${presetCards}\n ${renderManualProviderCard(initialEnvKey, secretLabel, placeholder)}\n</div>\n\n<div id=\"oauth-panel\" class=\"panel card stack\">\n <label for=\"oauthService\">OAuth service</label>\n <select id=\"oauthService\" name=\"oauthService\">${oauthOptions}</select>\n <p class=\"panel-note\">You'll be redirected to the selected service's authorization page.</p>\n</div>\n\n<div>\n <button id=\"btn\" class=\"primary-button\" onclick=\"connect()\">Continue</button>\n <div id=\"result\" class=\"result\" aria-live=\"polite\"></div>\n</div>\n${renderCredentialPageScript(token)}`,\n );\n}\n\nfunction renderErrorPage(message: string): string {\n return renderStatusPage(\"Login Error\", message, \"err\");\n}\n\nfunction renderSuccessPage(message: string): string {\n return renderStatusPage(\"Connected\", message, \"ok\", { closeNote: true });\n}\n\nfunction isValidEnvKey(value: string): boolean {\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(value);\n}\n\nfunction extractEnvUpdates(data: Partial<LinkCompleteBody>): {\n updates?: Record<string, string>;\n error?: string;\n} {\n if (data.env && typeof data.env === \"object\" && !Array.isArray(data.env)) {\n const rawEntries = Object.entries(data.env);\n if (rawEntries.length === 0) return { error: \"Missing required field: env\" };\n\n const updates: Record<string, string> = {};\n for (const [rawKey, rawValue] of rawEntries) {\n const envKey = rawKey.trim();\n const credential = typeof rawValue === \"string\" ? rawValue.trim() : \"\";\n if (!isValidEnvKey(envKey)) return { error: `Invalid envKey format: ${rawKey}` };\n if (!credential) return { error: `Missing value for envKey: ${envKey}` };\n updates[envKey] = credential;\n }\n\n return { updates };\n }\n\n const envKey = data.envKey?.trim() ?? \"\";\n const credential = data.credential?.trim() ?? \"\";\n if (!isValidEnvKey(envKey)) return { error: \"Invalid envKey format\" };\n if (!credential) return { error: \"Missing required field: credential\" };\n return { updates: { [envKey]: credential } };\n}\n\nfunction renderStoredEnvMessage(envKeys: string[], fileTargets: string[] = []): string {\n const fileSuffix = fileTargets.length > 0 ? ` Mounted file(s): ${fileTargets.join(\", \")}.` : \"\";\n if (envKeys.length === 1) {\n return `${envKeys[0]} stored successfully in vault.${fileSuffix}`;\n }\n\n return `${envKeys.length} secrets stored successfully in vault: ${envKeys.join(\", \")}.${fileSuffix}`;\n}\n\nfunction renderSentryCliConfig(updates: Record<string, string>): string | undefined {\n const token = updates.SENTRY_AUTH_TOKEN?.trim();\n if (!token) return undefined;\n\n const lines = [\"[auth]\", `token=${token}`, \"\"];\n const defaults: string[] = [];\n const org = updates.SENTRY_ORG?.trim();\n const project = updates.SENTRY_PROJECT?.trim();\n if (org) defaults.push(`org = ${org}`);\n if (project) defaults.push(`project = ${project}`);\n if (defaults.length > 0) {\n lines.push(\"[defaults]\", ...defaults, \"\");\n }\n return lines.join(\"\\n\");\n}\n\nasync function handleLinkComplete(\n data: Partial<LinkCompleteBody>,\n linkTokenStore: InMemoryLinkTokenStore,\n vaultManager: VaultManager,\n notify: NotifyFn,\n res: ServerResponse,\n): Promise<void> {\n if (!data.token) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Missing required field: token\" }));\n return;\n }\n\n const { updates, error } = extractEnvUpdates(data);\n if (!updates || error) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: error ?? \"Invalid env payload\" }));\n return;\n }\n\n const envKeys = Object.keys(updates).toSorted((left, right) => left.localeCompare(right));\n\n const linkToken = linkTokenStore.consume(data.token);\n if (!linkToken) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Invalid or expired token\" }));\n return;\n }\n\n const fileTargets: string[] = [];\n const sentryCliConfig = renderSentryCliConfig(updates);\n\n try {\n vaultManager.upsertEnv(linkToken.vaultId, updates);\n if (sentryCliConfig) {\n const target = defaultVaultTargetPath(\".sentryclirc\");\n vaultManager.upsertFile(linkToken.vaultId, \".sentryclirc\", sentryCliConfig, target);\n fileTargets.push(target);\n }\n } catch (persistError) {\n log.logWarning(\n `Failed to persist [${envKeys.join(\", \")}] for ${linkToken.platform}/${linkToken.platformUserId}`,\n persistError instanceof Error ? persistError.message : String(persistError),\n );\n reportUserFacingError(persistError, {\n domain: \"login\",\n surface: \"credential_login\",\n operation: \"vault_persist\",\n severity: \"error\",\n platform: linkToken.platform,\n context: {\n conversationId: linkToken.conversationId,\n vaultId: linkToken.vaultId,\n credentialMode: data.mode ?? \"manual\",\n envKeyCount: envKeys.length,\n fileTargetCount: fileTargets.length,\n },\n });\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n error:\n \"Failed to store credential on server. Please fix the server issue and run /login again.\",\n }),\n );\n return;\n }\n\n log.logInfo(\n `Stored [${envKeys.join(\", \")}] for ${linkToken.platform}/${linkToken.platformUserId} in vault:${linkToken.vaultId}`,\n );\n\n const message = renderStoredEnvMessage(envKeys, fileTargets);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: true, message }));\n\n notify(\n linkToken.platform,\n linkToken.conversationId,\n `${message} Vault: \\`${linkToken.vaultId}\\`.`,\n ).catch((err: Error) => {\n log.logWarning(\"Failed to notify user after credential login\", err.message);\n reportUserFacingError(err, {\n domain: \"login\",\n surface: \"credential_login\",\n operation: \"notify_user\",\n severity: \"warning\",\n platform: linkToken.platform,\n context: {\n conversationId: linkToken.conversationId,\n vaultId: linkToken.vaultId,\n credentialMode: data.mode ?? \"manual\",\n envKeyCount: envKeys.length,\n fileTargetCount: fileTargets.length,\n },\n });\n });\n}\n\nasync function handleOAuthStart(\n data: Partial<OAuthStartBody>,\n req: IncomingMessage,\n linkTokenStore: InMemoryLinkTokenStore,\n oauthStates: Map<string, PendingOAuthState>,\n res: ServerResponse,\n): Promise<void> {\n if (!data.token || !data.serviceId) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Missing required fields: token/serviceId\" }));\n return;\n }\n\n const linkToken = linkTokenStore.peek(data.token);\n if (!linkToken) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Invalid or expired token\" }));\n return;\n }\n\n const service = resolveOAuthService(data.serviceId);\n if (!service) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: `Unsupported OAuth service: ${data.serviceId}` }));\n return;\n }\n\n const clientId = readEnv(service.clientIdEnvKey);\n const clientSecret = readEnv(service.clientSecretEnvKey);\n if (!clientId || !clientSecret) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n error:\n `OAuth service ${service.label} is not configured. ` +\n `Missing ${service.clientIdEnvKey}/${service.clientSecretEnvKey}.`,\n }),\n );\n return;\n }\n\n const state = randomBytes(16).toString(\"hex\");\n const codeVerifier = randomBytes(32).toString(\"base64url\");\n oauthStates.set(state, {\n linkToken: data.token,\n serviceId: service.id,\n codeVerifier,\n expiresAt: Date.now() + OAUTH_STATE_TTL_MS,\n });\n\n for (const [k, v] of oauthStates) {\n if (Date.now() > v.expiresAt) oauthStates.delete(k);\n }\n\n const redirectUri = `${requestBaseUrl(req)}/oauth/callback`;\n const authorizeUrl = new URL(service.authorizationUrl);\n authorizeUrl.searchParams.set(\"response_type\", \"code\");\n authorizeUrl.searchParams.set(\"client_id\", clientId);\n authorizeUrl.searchParams.set(\"redirect_uri\", redirectUri);\n authorizeUrl.searchParams.set(\"state\", state);\n if (service.scopes.length > 0) {\n authorizeUrl.searchParams.set(\"scope\", service.scopes.join(\" \"));\n }\n for (const [key, value] of Object.entries(service.authorizationParams ?? {})) {\n authorizeUrl.searchParams.set(key, value);\n }\n\n const codeChallenge = createHash(\"sha256\").update(codeVerifier).digest(\"base64url\");\n authorizeUrl.searchParams.set(\"code_challenge\", codeChallenge);\n authorizeUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ ok: true, redirectUrl: authorizeUrl.toString() }));\n}\n\ninterface OAuthCallbackOptions {\n url: URL;\n req: IncomingMessage;\n linkTokenStore: InMemoryLinkTokenStore;\n vaultManager: VaultManager;\n notify: NotifyFn;\n oauthStates: Map<string, PendingOAuthState>;\n res: ServerResponse;\n}\n\ninterface ResolvedOAuthCallback {\n code: string;\n codeVerifier: string;\n service: OAuthService;\n clientId: string;\n clientSecret: string;\n linkToken: LinkToken;\n}\n\nfunction resolveOAuthCallback(options: OAuthCallbackOptions): ResolvedOAuthCallback | undefined {\n const { url, oauthStates, linkTokenStore, res } = options;\n const state = url.searchParams.get(\"state\") ?? \"\";\n const code = url.searchParams.get(\"code\") ?? \"\";\n const oauthError = url.searchParams.get(\"error\");\n\n const pending = oauthStates.get(state);\n if (pending) oauthStates.delete(state);\n\n if (oauthError) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(`OAuth authorization failed: ${oauthError}`));\n return undefined;\n }\n if (!pending || Date.now() > pending.expiresAt) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(\"OAuth state is invalid or expired. Please run /login again.\"));\n return undefined;\n }\n if (!code) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(\"Missing OAuth authorization code.\"));\n return undefined;\n }\n\n const service = resolveOAuthService(pending.serviceId);\n if (!service) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(\"Unsupported OAuth service.\"));\n return undefined;\n }\n const clientId = readEnv(service.clientIdEnvKey);\n const clientSecret = readEnv(service.clientSecretEnvKey);\n if (!clientId || !clientSecret) {\n res.writeHead(500, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(\"OAuth service is not configured on server.\"));\n return undefined;\n }\n\n const linkToken = linkTokenStore.consume(pending.linkToken);\n if (!linkToken) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(\"Login link is invalid or expired. Please run /login again.\"));\n return undefined;\n }\n return { code, codeVerifier: pending.codeVerifier, service, clientId, clientSecret, linkToken };\n}\n\ninterface StoreOAuthCredentialsOptions {\n tokenResponse: Record<string, string>;\n service: OAuthService;\n clientId: string;\n clientSecret: string;\n linkToken: LinkToken;\n vaultManager: VaultManager;\n res: ServerResponse;\n}\n\nfunction storeOAuthCredentials(options: StoreOAuthCredentialsOptions): string[] | undefined {\n const { tokenResponse, service, clientId, clientSecret, linkToken, vaultManager, res } = options;\n const accessToken = tokenResponse.access_token?.trim();\n const refreshToken = tokenResponse.refresh_token?.trim();\n if (!accessToken) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(renderErrorPage(\"OAuth token exchange did not return an access_token.\"));\n return undefined;\n }\n\n const updates: Record<string, string> = {};\n for (const key of service.accessTokenEnvKeys ?? []) updates[key] = accessToken;\n if (refreshToken && service.refreshTokenEnvKey)\n updates[service.refreshTokenEnvKey] = refreshToken;\n\n const fileOutput = service.fileOutput;\n let mountedPath: string | undefined;\n if (fileOutput?.type === \"authorized_user\") {\n if (!refreshToken) {\n res.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n renderErrorPage(\n \"OAuth token exchange did not return a refresh_token. \" +\n \"Retry after revoking prior consent or ensure prompt=consent is applied.\",\n ),\n );\n return undefined;\n }\n mountedPath = fileOutput.targetPath ?? defaultVaultTargetPath(fileOutput.relativePath);\n if (fileOutput.envKey) updates[fileOutput.envKey] = mountedPath;\n for (const key of fileOutput.additionalEnvKeys ?? []) updates[key] = mountedPath;\n }\n\n const storedTargets: string[] = [];\n try {\n if (Object.keys(updates).length > 0) {\n vaultManager.upsertEnv(linkToken.vaultId, updates);\n storedTargets.push(...Object.keys(updates).toSorted());\n }\n if (fileOutput?.type === \"authorized_user\" && refreshToken) {\n vaultManager.upsertFile(\n linkToken.vaultId,\n fileOutput.relativePath,\n renderAuthorizedUserCredential(clientId, clientSecret, refreshToken),\n fileOutput.targetPath,\n );\n if (mountedPath) storedTargets.push(mountedPath);\n }\n } catch (persistError) {\n log.logWarning(\n `Failed to persist OAuth credentials for ${linkToken.platform}/${linkToken.platformUserId}`,\n persistError instanceof Error ? persistError.message : String(persistError),\n );\n reportUserFacingError(persistError, {\n domain: \"login\",\n surface: \"oauth\",\n operation: \"vault_persist\",\n severity: \"error\",\n platform: linkToken.platform,\n context: {\n conversationId: linkToken.conversationId,\n vaultId: linkToken.vaultId,\n serviceId: service.id,\n credentialMode: \"oauth\",\n storedTargetCount: storedTargets.length,\n },\n });\n res.writeHead(500, { \"Content-Type\": \"text/html; charset=utf-8\" });\n res.end(\n renderErrorPage(\n \"OAuth tokens were received but could not be stored on the server. Fix the server issue and run /login again.\",\n ),\n );\n return undefined;\n }\n return storedTargets;\n}\n\nasync function handleOAuthCallback(options: OAuthCallbackOptions): Promise<void> {\n const resolved = resolveOAuthCallback(options);\n if (!resolved) return;\n const { service, code, clientId, clientSecret, codeVerifier, linkToken } = resolved;\n const redirectUri = `${requestBaseUrl(options.req)}/oauth/callback`;\n const tokenResponse = await exchangeOAuthCode({\n service,\n code,\n clientId,\n clientSecret,\n redirectUri,\n codeVerifier,\n });\n const storedTargets = storeOAuthCredentials({\n tokenResponse,\n service,\n clientId,\n clientSecret,\n linkToken,\n vaultManager: options.vaultManager,\n res: options.res,\n });\n if (!storedTargets) return;\n\n log.logInfo(\n `Stored [${storedTargets.join(\", \")}] for ${linkToken.platform}/${linkToken.platformUserId} in vault:${linkToken.vaultId}`,\n );\n options\n .notify(\n linkToken.platform,\n linkToken.conversationId,\n `${service.label} OAuth stored (${storedTargets.join(\", \")}) in vault \\`${linkToken.vaultId}\\`.`,\n )\n .catch((err: Error) => {\n log.logWarning(\"Failed to notify user after OAuth login\", err.message);\n reportUserFacingError(err, {\n domain: \"login\",\n surface: \"oauth\",\n operation: \"notify_user\",\n severity: \"warning\",\n platform: linkToken.platform,\n context: {\n conversationId: linkToken.conversationId,\n vaultId: linkToken.vaultId,\n serviceId: service.id,\n credentialMode: \"oauth\",\n storedTargetCount: storedTargets.length,\n },\n });\n });\n\n options.res.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" });\n options.res.end(renderSuccessPage(`${service.label} OAuth connected successfully.`));\n}\n\ninterface ExchangeOAuthCodeOptions {\n service: OAuthService;\n code: string;\n clientId: string;\n clientSecret: string;\n redirectUri: string;\n codeVerifier: string;\n}\n\nasync function exchangeOAuthCode(\n options: ExchangeOAuthCodeOptions,\n): Promise<Record<string, string>> {\n const { service, code, clientId, clientSecret, redirectUri, codeVerifier } = options;\n const params = new URLSearchParams();\n params.set(\"grant_type\", \"authorization_code\");\n params.set(\"code\", code);\n params.set(\"client_id\", clientId);\n params.set(\"client_secret\", clientSecret);\n params.set(\"redirect_uri\", redirectUri);\n params.set(\"code_verifier\", codeVerifier);\n\n const response = await fetch(service.tokenUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n Accept: \"application/json\",\n },\n body: params.toString(),\n });\n\n const text = await response.text();\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n let parsed: Record<string, string> = {};\n\n if (contentType.includes(\"application/json\")) {\n parsed = JSON.parse(text) as Record<string, string>;\n } else {\n const form = new URLSearchParams(text);\n parsed = Object.fromEntries(form.entries());\n }\n\n if (!response.ok) {\n const message = parsed.error_description ?? parsed.error ?? `${response.status}`;\n throw new Error(`OAuth token exchange failed for ${service.id}: ${message}`);\n }\n\n return parsed;\n}\n\nfunction renderAuthorizedUserCredential(\n clientId: string,\n clientSecret: string,\n refreshToken: string,\n): string {\n return (\n JSON.stringify(\n {\n client_id: clientId,\n client_secret: clientSecret,\n refresh_token: refreshToken,\n type: \"authorized_user\",\n },\n null,\n 2,\n ) + \"\\n\"\n );\n}\n"]}
|
package/dist/cli/boot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boot.d.ts","sourceRoot":"","sources":["../../src/cli/boot.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA+B3C,wBAAgB,WAAW,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,QAAQ,CAoB5E;
|
|
1
|
+
{"version":3,"file":"boot.d.ts","sourceRoot":"","sources":["../../src/cli/boot.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA+B3C,wBAAgB,WAAW,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,QAAQ,CAoB5E;AA0BD,wBAAgB,QAAQ,IAAI,MAAM,CAejC"}
|