cloud-doctor 0.0.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/bin/cloud-doctor.js +13 -0
- package/dist/chunk-4PZ65VRA.js +586 -0
- package/dist/chunk-4PZ65VRA.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +612 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../core/src/constants.ts","../../core/src/calculate-score.ts","../../core/src/highlighter.ts","../../core/src/load-config.ts","../../core/src/plugin-registry.ts","../../core/src/scan-summary.ts","../../plugin-aws/src/plugin.ts","../../plugin-aws/src/discovery/list-profiles.ts","../../plugin-aws/src/discovery/validate.ts","../../plugin-aws/src/scan/run-rules.ts","../../plugins/src/index.ts","../../plugins/src/stubs.ts"],"sourcesContent":["export const PERFECT_SCORE = 100;\nexport const SCORE_GOOD_THRESHOLD = 75;\nexport const SCORE_OK_THRESHOLD = 50;\nexport const TOP_FIXES_DISPLAY_COUNT = 5;\n\nexport const ERROR_RULE_PENALTY = 1.5;\nexport const WARNING_RULE_PENALTY = 0.75;\n\nexport const DIAGNOSTIC_CATEGORY_BUCKETS = [\n \"Security\",\n \"Misconfiguration\",\n \"Observability\",\n \"Reliability\",\n \"Governance\",\n] as const;\n","import {\n ERROR_RULE_PENALTY,\n PERFECT_SCORE,\n SCORE_GOOD_THRESHOLD,\n SCORE_OK_THRESHOLD,\n WARNING_RULE_PENALTY,\n} from \"./constants.js\";\nimport type { Diagnostic, ScoreResult } from \"./types.js\";\n\nexport const getScoreLabel = (score: number): string => {\n if (score >= SCORE_GOOD_THRESHOLD) return \"Great\";\n if (score >= SCORE_OK_THRESHOLD) return \"Needs work\";\n return \"Critical\";\n};\n\nexport const calculateScore = (diagnostics: Diagnostic[]): ScoreResult => {\n if (diagnostics.length === 0) {\n return { score: PERFECT_SCORE, label: getScoreLabel(PERFECT_SCORE) };\n }\n\n const errorRules = new Set<string>();\n const warningRules = new Set<string>();\n\n for (const diagnostic of diagnostics) {\n const ruleKey = `${diagnostic.plugin}/${diagnostic.rule}`;\n if (diagnostic.severity === \"error\") {\n errorRules.add(ruleKey);\n } else {\n warningRules.add(ruleKey);\n }\n }\n\n const penalty = errorRules.size * ERROR_RULE_PENALTY + warningRules.size * WARNING_RULE_PENALTY;\n const score = Math.max(0, Math.round(PERFECT_SCORE - penalty));\n\n return { score, label: getScoreLabel(score) };\n};\n","import pc from \"picocolors\";\n\nexport const highlighter = {\n error: pc.red,\n warn: pc.yellow,\n info: pc.cyan,\n success: pc.green,\n dim: pc.dim,\n gray: pc.gray,\n bold: pc.bold,\n};\n\nexport const setColorEnabled = (enabled: boolean): void => {\n const colors = pc.createColors(enabled);\n highlighter.error = colors.red;\n highlighter.warn = colors.yellow;\n highlighter.info = colors.cyan;\n highlighter.success = colors.green;\n highlighter.dim = colors.dim;\n highlighter.gray = colors.gray;\n highlighter.bold = colors.bold;\n};\n","import { createJiti } from \"jiti\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { parseJSONC } from \"confbox\";\nimport type { CloudDoctorConfig } from \"./types.js\";\n\nconst CONFIG_FILENAMES = [\n \"doctor.config.ts\",\n \"doctor.config.mts\",\n \"doctor.config.js\",\n \"doctor.config.mjs\",\n \"doctor.config.json\",\n \"doctor.config.jsonc\",\n] as const;\n\nconst findConfigFile = (startDir: string): string | null => {\n let current = path.resolve(startDir);\n const root = path.parse(current).root;\n\n while (true) {\n for (const filename of CONFIG_FILENAMES) {\n const candidate = path.join(current, filename);\n if (fs.existsSync(candidate)) return candidate;\n }\n\n const packageJsonPath = path.join(current, \"package.json\");\n if (fs.existsSync(packageJsonPath)) {\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, \"utf8\")) as {\n cloudDoctor?: CloudDoctorConfig;\n };\n if (packageJson.cloudDoctor) {\n return packageJsonPath;\n }\n } catch {\n // ignore malformed package.json\n }\n }\n\n if (current === root) break;\n current = path.dirname(current);\n }\n\n return null;\n};\n\nconst loadConfigModule = async (configPath: string): Promise<CloudDoctorConfig> => {\n const ext = path.extname(configPath);\n\n if (ext === \".json\" || ext === \".jsonc\") {\n return parseJSONC(fs.readFileSync(configPath, \"utf8\")) as CloudDoctorConfig;\n }\n\n if (configPath.endsWith(\"package.json\")) {\n const packageJson = JSON.parse(fs.readFileSync(configPath, \"utf8\")) as {\n cloudDoctor?: CloudDoctorConfig;\n };\n return packageJson.cloudDoctor ?? {};\n }\n\n const jiti = createJiti(import.meta.url, { interopDefault: true });\n const loaded = await jiti.import(configPath);\n const config = (loaded as { default?: CloudDoctorConfig }).default ?? loaded;\n return config as CloudDoctorConfig;\n};\n\nexport const loadConfig = async (cwd = process.cwd()): Promise<CloudDoctorConfig> => {\n const configPath = findConfigFile(cwd);\n if (!configPath) return {};\n return loadConfigModule(configPath);\n};\n\nexport const defineConfig = (config: CloudDoctorConfig): CloudDoctorConfig => config;\n","import type { CloudDoctorPlugin, ProviderId } from \"./types.js\";\n\nexport class PluginRegistry {\n private readonly plugins = new Map<ProviderId, CloudDoctorPlugin>();\n\n register(plugin: CloudDoctorPlugin): void {\n this.plugins.set(plugin.id, plugin);\n }\n\n get(id: ProviderId): CloudDoctorPlugin | undefined {\n return this.plugins.get(id);\n }\n\n require(id: ProviderId): CloudDoctorPlugin {\n const plugin = this.plugins.get(id);\n if (!plugin) {\n throw new Error(`Unknown provider: ${id}`);\n }\n return plugin;\n }\n\n list(): CloudDoctorPlugin[] {\n return [...this.plugins.values()];\n }\n\n listAvailable(): CloudDoctorPlugin[] {\n return this.list().filter((plugin) => plugin.status !== \"coming-soon\");\n }\n}\n\nexport const createPluginRegistry = (): PluginRegistry => new PluginRegistry();\n","import {\n DIAGNOSTIC_CATEGORY_BUCKETS,\n TOP_FIXES_DISPLAY_COUNT,\n} from \"./constants.js\";\nimport { calculateScore, getScoreLabel } from \"./calculate-score.js\";\nimport type {\n Diagnostic,\n DiagnosticCategory,\n JsonReport,\n JsonReportError,\n ScanMeta,\n ScanResult,\n ScanSummary,\n} from \"./types.js\";\nimport type { ResolvedIdentity } from \"./types.js\";\nimport type { ProviderId } from \"./types.js\";\n\nexport const buildCategoryCounts = (\n diagnostics: Diagnostic[],\n): ScanSummary[\"categoryCounts\"] => {\n const counts: Partial<Record<DiagnosticCategory, { errors: number; warnings: number }>> = {};\n\n for (const diagnostic of diagnostics) {\n const bucket = counts[diagnostic.category] ?? { errors: 0, warnings: 0 };\n if (diagnostic.severity === \"error\") {\n bucket.errors += 1;\n } else {\n bucket.warnings += 1;\n }\n counts[diagnostic.category] = bucket;\n }\n\n return counts;\n};\n\nexport const buildScanSummary = (diagnostics: Diagnostic[]): ScanSummary => {\n const { score, label } = calculateScore(diagnostics);\n const errorCount = diagnostics.filter((d) => d.severity === \"error\").length;\n const warningCount = diagnostics.filter((d) => d.severity === \"warning\").length;\n\n return {\n score,\n label,\n errorCount,\n warningCount,\n categoryCounts: buildCategoryCounts(diagnostics),\n };\n};\n\nexport const computeProjectedScore = (\n diagnostics: Diagnostic[],\n topRuleCount = TOP_FIXES_DISPLAY_COUNT,\n): number | undefined => {\n const errorRuleKeys = new Set<string>();\n const orderedErrorRules: string[] = [];\n\n for (const diagnostic of diagnostics) {\n if (diagnostic.severity !== \"error\") continue;\n const ruleKey = `${diagnostic.plugin}/${diagnostic.rule}`;\n if (!errorRuleKeys.has(ruleKey)) {\n errorRuleKeys.add(ruleKey);\n orderedErrorRules.push(ruleKey);\n }\n }\n\n if (orderedErrorRules.length === 0) return undefined;\n\n const rulesToRemove = new Set(orderedErrorRules.slice(0, topRuleCount));\n const remaining = diagnostics.filter(\n (d) => !rulesToRemove.has(`${d.plugin}/${d.rule}`),\n );\n\n return calculateScore(remaining).score;\n};\n\nexport const buildJsonReport = (input: {\n provider: ProviderId;\n identity: ResolvedIdentity;\n diagnostics: Diagnostic[];\n meta: ScanMeta;\n}): JsonReport => {\n const summary = buildScanSummary(input.diagnostics);\n const projectedScore = computeProjectedScore(input.diagnostics);\n if (projectedScore !== undefined) {\n summary.projectedScore = projectedScore;\n }\n\n return {\n schemaVersion: 1,\n provider: input.provider,\n identity: input.identity,\n summary,\n diagnostics: input.diagnostics,\n meta: input.meta,\n };\n};\n\nexport const buildJsonReportError = (input: {\n error: unknown;\n elapsedMilliseconds: number;\n}): JsonReportError => ({\n schemaVersion: 1,\n error: input.error instanceof Error ? input.error.message : String(input.error),\n elapsedMilliseconds: input.elapsedMilliseconds,\n});\n\nexport const groupDiagnosticsByRule = (\n diagnostics: Diagnostic[],\n): Map<string, Diagnostic[]> => {\n const groups = new Map<string, Diagnostic[]>();\n for (const diagnostic of diagnostics) {\n const key = `${diagnostic.plugin}/${diagnostic.rule}`;\n const existing = groups.get(key) ?? [];\n existing.push(diagnostic);\n groups.set(key, existing);\n }\n return groups;\n};\n\nexport const getTopErrorRules = (\n diagnostics: Diagnostic[],\n limit = TOP_FIXES_DISPLAY_COUNT,\n): Array<{ ruleKey: string; diagnostics: Diagnostic[] }> => {\n const errorDiagnostics = diagnostics.filter((d) => d.severity === \"error\");\n const groups = groupDiagnosticsByRule(errorDiagnostics);\n return [...groups.entries()]\n .slice(0, limit)\n .map(([ruleKey, ruleDiagnostics]) => ({ ruleKey, diagnostics: ruleDiagnostics }));\n};\n\nexport const sortCategoriesForDisplay = (\n categories: Iterable<DiagnosticCategory>,\n): DiagnosticCategory[] => {\n const rank = new Map(DIAGNOSTIC_CATEGORY_BUCKETS.map((category, index) => [category, index]));\n return [...categories].sort((a, b) => {\n const rankA = rank.get(a);\n const rankB = rank.get(b);\n if (rankA !== undefined && rankB !== undefined) return rankA - rankB;\n if (rankA !== undefined) return -1;\n if (rankB !== undefined) return 1;\n return a.localeCompare(b);\n });\n};\n\nexport type { ScanResult };\n","import type {\n CloudDoctorPlugin,\n DiscoveryContext,\n IdentityInput,\n IdentitySummary,\n ResolvedIdentity,\n ScanConfig,\n ScanResult,\n} from \"@cloud-doctor/core\";\nimport { buildScanSummary } from \"@cloud-doctor/core\";\nimport {\n hasEnvironmentCredentials,\n hasWebIdentityCredentials,\n listAwsProfiles,\n resolveDefaultProfileName,\n} from \"./discovery/list-profiles.js\";\nimport {\n createCredentialProvider,\n profileToIdentityKind,\n SsoLoginRequiredError,\n validateAwsCredentials,\n} from \"./discovery/validate.js\";\nimport { runAwsRules } from \"./scan/run-rules.js\";\n\nconst formatProfileLabel = (profileName: string, region?: string): string => {\n const regionSuffix = region ? ` · ${region}` : \"\";\n return `${profileName}${regionSuffix}`;\n};\n\nconst buildProfileSummaries = async (): Promise<IdentitySummary[]> => {\n const profiles = await listAwsProfiles();\n const summaries: IdentitySummary[] = [];\n\n for (const profile of profiles) {\n if (profile.name === \"(environment)\") continue;\n\n summaries.push({\n id: profile.name,\n label: formatProfileLabel(profile.name, profile.region),\n kind: profileToIdentityKind(profile),\n profileName: profile.name,\n defaultRegion: profile.region,\n status: \"unknown\",\n hint:\n profile.kind === \"sso\"\n ? \"SSO profile — will validate on selection\"\n : profile.kind === \"assume-role\"\n ? `Assumes ${profile.roleArn ?? \"role\"}`\n : undefined,\n });\n }\n\n if (hasEnvironmentCredentials()) {\n summaries.unshift({\n id: \"__environment__\",\n label: \"(environment credentials)\",\n kind: \"environment\",\n status: \"unknown\",\n hint: \"AWS_ACCESS_KEY_ID is set\",\n });\n }\n\n if (hasWebIdentityCredentials()) {\n summaries.unshift({\n id: \"__web_identity__\",\n label: \"(web identity / OIDC)\",\n kind: \"web-identity\",\n status: \"unknown\",\n hint: process.env.AWS_ROLE_ARN,\n });\n }\n\n return summaries;\n};\n\nconst resolveProfileInput = (\n input: IdentityInput,\n configProfile?: string,\n): { profileName?: string; useEnvironment?: boolean } => {\n if (input.useEnvironment) return { useEnvironment: true };\n if (input.profile) return { profileName: input.profile };\n if (configProfile) return { profileName: configProfile };\n if (process.env.AWS_PROFILE) return { profileName: process.env.AWS_PROFILE };\n\n const envSelected = input.manualAccessKeyId ? undefined : hasEnvironmentCredentials();\n if (envSelected && !input.profile) return { useEnvironment: true };\n\n return {};\n};\n\nexport const awsPlugin: CloudDoctorPlugin = {\n id: \"aws\",\n displayName: \"AWS\",\n description: \"Amazon Web Services account\",\n status: \"stable\",\n\n async discoverIdentities(_ctx: DiscoveryContext): Promise<IdentitySummary[]> {\n return buildProfileSummaries();\n },\n\n async resolveIdentity(ctx: DiscoveryContext, input: IdentityInput): Promise<ResolvedIdentity> {\n const profiles = await listAwsProfiles();\n const resolution = resolveProfileInput(input, undefined);\n\n if (resolution.useEnvironment) {\n return {\n provider: \"aws\",\n id: \"__environment__\",\n label: \"(environment credentials)\",\n kind: \"environment\",\n region: input.region ?? process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION,\n };\n }\n\n if (input.manualAccessKeyId && input.manualSecretAccessKey) {\n return {\n provider: \"aws\",\n id: \"__manual__\",\n label: \"(manual credentials)\",\n kind: \"manual\",\n region: input.region,\n };\n }\n\n const profileName =\n resolution.profileName ?? resolveDefaultProfileName(profiles) ?? profiles[0]?.name;\n\n if (!profileName) {\n if (ctx.yes || ctx.json) {\n throw new Error(\n \"No AWS profiles found. Configure ~/.aws/config or pass --profile, set AWS_PROFILE, or use environment credentials.\",\n );\n }\n throw new Error(\"No AWS profiles found\");\n }\n\n const profile = profiles.find((entry) => entry.name === profileName);\n return {\n provider: \"aws\",\n id: profileName,\n label: formatProfileLabel(profileName, profile?.region ?? input.region),\n kind: profile ? profileToIdentityKind(profile) : \"profile\",\n profileName,\n region: input.region ?? profile?.region,\n };\n },\n\n async validateIdentity(identity: ResolvedIdentity): Promise<ResolvedIdentity> {\n if (identity.kind === \"manual\") {\n throw new Error(\"Manual credentials must be validated via validateAwsCredentials before scan.\");\n }\n\n return validateAwsCredentials({\n profileName: identity.profileName,\n region: identity.region,\n label: identity.label,\n kind: identity.kind,\n useEnvironment: identity.kind === \"environment\",\n });\n },\n\n async scan(identity: ResolvedIdentity, config: ScanConfig): Promise<ScanResult> {\n const start = performance.now();\n const diagnostics = await runAwsRules(identity, config);\n const summary = buildScanSummary(diagnostics);\n\n return {\n provider: \"aws\",\n identity,\n diagnostics,\n summary,\n meta: {\n durationMs: Math.round(performance.now() - start),\n regionsScanned: config.regions,\n },\n };\n },\n};\n\nexport { SsoLoginRequiredError, listAwsProfiles, validateAwsCredentials, createCredentialProvider };\n","import * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { loadSharedConfigFiles } from \"@smithy/shared-ini-file-loader\";\n\nexport interface AwsProfileRecord {\n name: string;\n region?: string;\n kind: \"static\" | \"sso\" | \"assume-role\" | \"web-identity\" | \"unknown\";\n ssoSessionName?: string;\n roleArn?: string;\n sourceProfile?: string;\n}\n\nconst profileNameFromSection = (sectionName: string): string | null => {\n if (sectionName === \"default\") return \"default\";\n if (sectionName.startsWith(\"profile \")) return sectionName.slice(\"profile \".length);\n // credentials file sections are bare profile names\n if (!sectionName.includes(\" \")) return sectionName;\n return null;\n};\n\nconst classifyProfile = (\n profileName: string,\n configSection: Record<string, string | undefined>,\n hasStaticCredentials: boolean,\n): AwsProfileRecord[\"kind\"] => {\n if (configSection[\"sso_start_url\"] || configSection[\"sso_session\"]) return \"sso\";\n if (configSection[\"role_arn\"]) return \"assume-role\";\n if (configSection[\"web_identity_token_file\"]) return \"web-identity\";\n if (hasStaticCredentials) return \"static\";\n if (profileName === \"default\" && hasStaticCredentials) return \"static\";\n return \"unknown\";\n};\n\nexport const getAwsConfigPaths = (): { configFile: string; credentialsFile: string } => {\n const home = os.homedir();\n return {\n configFile: process.env.AWS_CONFIG_FILE ?? path.join(home, \".aws\", \"config\"),\n credentialsFile: process.env.AWS_SHARED_CREDENTIALS_FILE ?? path.join(home, \".aws\", \"credentials\"),\n };\n};\n\nexport const listAwsProfiles = async (): Promise<AwsProfileRecord[]> => {\n const { configFile, credentialsFile } = getAwsConfigPaths();\n const { configFile: configSections, credentialsFile: credentialSections } =\n await loadSharedConfigFiles({\n configFilepath: configFile,\n filepath: credentialsFile,\n });\n\n const profileNames = new Set<string>();\n\n for (const sectionName of Object.keys(configSections)) {\n const profileName = profileNameFromSection(sectionName);\n if (profileName) profileNames.add(profileName);\n }\n\n for (const sectionName of Object.keys(credentialSections)) {\n const profileName = profileNameFromSection(sectionName);\n if (profileName) profileNames.add(profileName);\n }\n\n if (profileNames.size === 0 && process.env.AWS_ACCESS_KEY_ID) {\n return [\n {\n name: \"(environment)\",\n kind: \"unknown\",\n },\n ];\n }\n\n const profiles: AwsProfileRecord[] = [];\n\n for (const profileName of [...profileNames].sort((a, b) => {\n if (a === \"default\") return -1;\n if (b === \"default\") return 1;\n return a.localeCompare(b);\n })) {\n const configSection =\n configSections[`profile ${profileName}`] ??\n configSections[profileName] ??\n {};\n const credentialSection = credentialSections[profileName] ?? {};\n const hasStaticCredentials = Boolean(\n credentialSection.aws_access_key_id && credentialSection.aws_secret_access_key,\n );\n\n profiles.push({\n name: profileName,\n region: configSection.region,\n kind: classifyProfile(profileName, configSection, hasStaticCredentials),\n ssoSessionName: configSection.sso_session,\n roleArn: configSection.role_arn,\n sourceProfile: configSection.source_profile,\n });\n }\n\n return profiles;\n};\n\nexport const resolveDefaultProfileName = (profiles: AwsProfileRecord[]): string | undefined => {\n if (process.env.AWS_PROFILE) return process.env.AWS_PROFILE;\n if (profiles.some((profile) => profile.name === \"default\")) return \"default\";\n if (profiles.length === 1 && profiles[0]?.name !== \"(environment)\") {\n return profiles[0]?.name;\n }\n return undefined;\n};\n\nexport const hasEnvironmentCredentials = (): boolean =>\n Boolean(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY);\n\nexport const hasWebIdentityCredentials = (): boolean =>\n Boolean(process.env.AWS_WEB_IDENTITY_TOKEN_FILE && process.env.AWS_ROLE_ARN);\n","import { STSClient, GetCallerIdentityCommand } from \"@aws-sdk/client-sts\";\nimport { fromEnv, fromIni, fromInstanceMetadata, fromTokenFile } from \"@aws-sdk/credential-providers\";\nimport type { AwsCredentialIdentityProvider } from \"@smithy/types\";\nimport type { ResolvedIdentity, IdentityKind } from \"@cloud-doctor/core\";\nimport type { AwsProfileRecord } from \"./list-profiles.js\";\n\nexport interface CredentialResolutionInput {\n profileName?: string;\n region?: string;\n useEnvironment?: boolean;\n manualAccessKeyId?: string;\n manualSecretAccessKey?: string;\n manualSessionToken?: string;\n}\n\nconst kindFromProfile = (profile: AwsProfileRecord): IdentityKind => {\n switch (profile.kind) {\n case \"sso\":\n return \"sso\";\n case \"assume-role\":\n return \"assume-role\";\n case \"web-identity\":\n return \"web-identity\";\n case \"static\":\n return \"profile\";\n default:\n return \"profile\";\n }\n};\n\nexport const createCredentialProvider = (\n input: CredentialResolutionInput,\n): AwsCredentialIdentityProvider => {\n if (input.manualAccessKeyId && input.manualSecretAccessKey) {\n return async () => ({\n accessKeyId: input.manualAccessKeyId!,\n secretAccessKey: input.manualSecretAccessKey!,\n sessionToken: input.manualSessionToken,\n });\n }\n\n if (input.useEnvironment || (!input.profileName && process.env.AWS_ACCESS_KEY_ID)) {\n return fromEnv();\n }\n\n if (!input.profileName && process.env.AWS_WEB_IDENTITY_TOKEN_FILE) {\n return fromTokenFile({\n roleArn: process.env.AWS_ROLE_ARN,\n webIdentityTokenFile: process.env.AWS_WEB_IDENTITY_TOKEN_FILE,\n });\n }\n\n if (input.profileName) {\n return fromIni({ profile: input.profileName });\n }\n\n return async () => {\n try {\n return await fromEnv()();\n } catch {\n try {\n return await fromIni()();\n } catch {\n return fromInstanceMetadata()();\n }\n }\n };\n};\n\nexport const validateAwsCredentials = async (\n input: CredentialResolutionInput & { label: string; kind: IdentityKind },\n): Promise<ResolvedIdentity> => {\n const credentials = createCredentialProvider({\n profileName: input.profileName,\n region: input.region,\n useEnvironment: input.useEnvironment,\n manualAccessKeyId: input.manualAccessKeyId,\n manualSecretAccessKey: input.manualSecretAccessKey,\n manualSessionToken: input.manualSessionToken,\n });\n const client = new STSClient({\n credentials,\n region: input.region ?? process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? \"us-east-1\",\n });\n\n try {\n const response = await client.send(new GetCallerIdentityCommand({}));\n return {\n provider: \"aws\",\n id: response.Account ?? \"unknown\",\n label: input.label,\n kind: input.kind,\n profileName: input.profileName,\n region: input.region,\n accountId: response.Account,\n arn: response.Arn,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (message.includes(\"Token has expired\") || message.includes(\"sso\")) {\n throw new SsoLoginRequiredError(input.profileName ?? \"default\");\n }\n throw error;\n } finally {\n client.destroy();\n }\n};\n\nexport class SsoLoginRequiredError extends Error {\n readonly profileName: string;\n\n constructor(profileName: string) {\n super(`Profile \"${profileName}\" requires SSO login. Run: aws sso login --profile ${profileName}`);\n this.name = \"SsoLoginRequiredError\";\n this.profileName = profileName;\n }\n}\n\nexport const profileToIdentityKind = kindFromProfile;\n","import type { Diagnostic, ResolvedIdentity, ScanConfig } from \"@cloud-doctor/core\";\n\n/**\n * Placeholder scan — v1 scaffold returns zero findings until rules land.\n * Rules will register via defineRule + codegen in subsequent PRs.\n */\nexport const runAwsRules = async (\n identity: ResolvedIdentity,\n _config: ScanConfig,\n): Promise<Diagnostic[]> => {\n void identity;\n return [];\n};\n","import { createPluginRegistry, type PluginRegistry, type ProviderId } from \"@cloud-doctor/core\";\nimport { awsPlugin } from \"@cloud-doctor/plugin-aws\";\nimport { cloudflarePlugin, dbPlugin, gcloudPlugin, k8sPlugin } from \"./stubs.js\";\n\nlet cachedRegistry: PluginRegistry | null = null;\n\nexport const createDefaultRegistry = (): PluginRegistry => {\n const registry = createPluginRegistry();\n registry.register(awsPlugin);\n registry.register(gcloudPlugin);\n registry.register(k8sPlugin);\n registry.register(dbPlugin);\n registry.register(cloudflarePlugin);\n return registry;\n};\n\nexport const getDefaultRegistry = (): PluginRegistry => {\n if (!cachedRegistry) {\n cachedRegistry = createDefaultRegistry();\n }\n return cachedRegistry;\n};\n\nexport const PROVIDER_IDS: ProviderId[] = [\"aws\", \"gcloud\", \"k8s\", \"db\", \"cloudflare\"];\n\nexport const isProviderId = (value: string): value is ProviderId =>\n (PROVIDER_IDS as string[]).includes(value);\n","import type { CloudDoctorPlugin } from \"@cloud-doctor/core\";\n\nconst comingSoon = (\n id: CloudDoctorPlugin[\"id\"],\n displayName: string,\n description: string,\n): CloudDoctorPlugin => ({\n id,\n displayName,\n description,\n status: \"coming-soon\",\n async discoverIdentities() {\n return [];\n },\n async resolveIdentity() {\n throw new Error(`${displayName} support is coming soon. Use \"aws\" for now.`);\n },\n async validateIdentity(identity) {\n return identity;\n },\n async scan() {\n throw new Error(`${displayName} support is coming soon.`);\n },\n});\n\nexport const gcloudPlugin = comingSoon(\"gcloud\", \"GCloud\", \"Google Cloud project\");\nexport const k8sPlugin = comingSoon(\"k8s\", \"Kubernetes\", \"Cluster workloads\");\nexport const dbPlugin = comingSoon(\"db\", \"Database\", \"Postgres, MySQL, Redis, and more\");\nexport const cloudflarePlugin = comingSoon(\"cloudflare\", \"Cloudflare\", \"DNS, WAF, Workers\");\n"],"mappings":"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","names":["path"]}
|