@standards-kit/conform 0.1.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.
Files changed (71) hide show
  1. package/dist/artifactregistry-QQWBMEQN.js +38 -0
  2. package/dist/artifactregistry-QQWBMEQN.js.map +1 -0
  3. package/dist/chunk-J5S6GRGW.js +314 -0
  4. package/dist/chunk-J5S6GRGW.js.map +1 -0
  5. package/dist/chunk-KHO6NIAI.js +1367 -0
  6. package/dist/chunk-KHO6NIAI.js.map +1 -0
  7. package/dist/chunk-M7G73Q6P.js +662 -0
  8. package/dist/chunk-M7G73Q6P.js.map +1 -0
  9. package/dist/chunk-P7TIZJ4C.js +85 -0
  10. package/dist/chunk-P7TIZJ4C.js.map +1 -0
  11. package/dist/chunk-RXA4FO7L.js +279 -0
  12. package/dist/chunk-RXA4FO7L.js.map +1 -0
  13. package/dist/cli.js +7432 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/cloudrun-O36R23SH.js +31 -0
  16. package/dist/cloudrun-O36R23SH.js.map +1 -0
  17. package/dist/cloudwatch-KSZ4A256.js +56 -0
  18. package/dist/cloudwatch-KSZ4A256.js.map +1 -0
  19. package/dist/dynamodb-5KVESCVJ.js +51 -0
  20. package/dist/dynamodb-5KVESCVJ.js.map +1 -0
  21. package/dist/ec2-HKPE6GZV.js +151 -0
  22. package/dist/ec2-HKPE6GZV.js.map +1 -0
  23. package/dist/ecs-OS3NJZTA.js +141 -0
  24. package/dist/ecs-OS3NJZTA.js.map +1 -0
  25. package/dist/elasticache-7TCRHYYM.js +151 -0
  26. package/dist/elasticache-7TCRHYYM.js.map +1 -0
  27. package/dist/elb-PEDLXW5R.js +151 -0
  28. package/dist/elb-PEDLXW5R.js.map +1 -0
  29. package/dist/generate-D4MFMOHP.js +28 -0
  30. package/dist/generate-D4MFMOHP.js.map +1 -0
  31. package/dist/iam-7H5HFWVQ.js +96 -0
  32. package/dist/iam-7H5HFWVQ.js.map +1 -0
  33. package/dist/iam-DJI64AGK.js +39 -0
  34. package/dist/iam-DJI64AGK.js.map +1 -0
  35. package/dist/index.js +7980 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/infra-UXM5XQX3.js +566 -0
  38. package/dist/infra-UXM5XQX3.js.map +1 -0
  39. package/dist/lambda-NFB5UILT.js +60 -0
  40. package/dist/lambda-NFB5UILT.js.map +1 -0
  41. package/dist/manifest-7AIL2FK2.js +23 -0
  42. package/dist/manifest-7AIL2FK2.js.map +1 -0
  43. package/dist/mcp-O5O7XVFG.js +204 -0
  44. package/dist/mcp-O5O7XVFG.js.map +1 -0
  45. package/dist/rds-KLG5O5SI.js +151 -0
  46. package/dist/rds-KLG5O5SI.js.map +1 -0
  47. package/dist/registry-V65CC7IN.js +15 -0
  48. package/dist/registry-V65CC7IN.js.map +1 -0
  49. package/dist/s3-2DH7PRVR.js +49 -0
  50. package/dist/s3-2DH7PRVR.js.map +1 -0
  51. package/dist/scan-EELS42BP.js +593 -0
  52. package/dist/scan-EELS42BP.js.map +1 -0
  53. package/dist/secretmanager-RDL62EFW.js +31 -0
  54. package/dist/secretmanager-RDL62EFW.js.map +1 -0
  55. package/dist/secretsmanager-MOOIHLAO.js +50 -0
  56. package/dist/secretsmanager-MOOIHLAO.js.map +1 -0
  57. package/dist/sns-Y36LVTWA.js +50 -0
  58. package/dist/sns-Y36LVTWA.js.map +1 -0
  59. package/dist/sqs-RRS3GRHK.js +61 -0
  60. package/dist/sqs-RRS3GRHK.js.map +1 -0
  61. package/dist/src-KZRTG3EU.js +45 -0
  62. package/dist/src-KZRTG3EU.js.map +1 -0
  63. package/dist/standards-RXK5G4IG.js +37 -0
  64. package/dist/standards-RXK5G4IG.js.map +1 -0
  65. package/dist/sync-RLYBGYNY.js +877 -0
  66. package/dist/sync-RLYBGYNY.js.map +1 -0
  67. package/dist/validate-AABLVQJS.js +327 -0
  68. package/dist/validate-AABLVQJS.js.map +1 -0
  69. package/dist/validator-6PL5I5EC.js +156 -0
  70. package/dist/validator-6PL5I5EC.js.map +1 -0
  71. package/package.json +91 -0
@@ -0,0 +1,60 @@
1
+ // src/infra/checkers/lambda.ts
2
+ import { GetFunctionCommand, LambdaClient } from "@aws-sdk/client-lambda";
3
+ var clientCache = /* @__PURE__ */ new Map();
4
+ function getClient(region) {
5
+ let client = clientCache.get(region);
6
+ if (!client) {
7
+ client = new LambdaClient({ region });
8
+ clientCache.set(region, client);
9
+ }
10
+ return client;
11
+ }
12
+ var LambdaChecker = {
13
+ async check(arn) {
14
+ const { resourceType, resourceId, region, raw } = arn;
15
+ if (resourceType !== "function") {
16
+ return {
17
+ arn: raw,
18
+ exists: false,
19
+ error: `Unsupported Lambda resource type: ${resourceType}`,
20
+ service: "lambda",
21
+ resourceType,
22
+ resourceId
23
+ };
24
+ }
25
+ const client = getClient(region);
26
+ try {
27
+ await client.send(new GetFunctionCommand({ FunctionName: resourceId }));
28
+ return {
29
+ arn: raw,
30
+ exists: true,
31
+ service: "lambda",
32
+ resourceType: "function",
33
+ resourceId
34
+ };
35
+ } catch (error) {
36
+ const err = error;
37
+ if (err.name === "ResourceNotFoundException") {
38
+ return {
39
+ arn: raw,
40
+ exists: false,
41
+ service: "lambda",
42
+ resourceType: "function",
43
+ resourceId
44
+ };
45
+ }
46
+ return {
47
+ arn: raw,
48
+ exists: false,
49
+ error: err.message || "Unknown error",
50
+ service: "lambda",
51
+ resourceType: "function",
52
+ resourceId
53
+ };
54
+ }
55
+ }
56
+ };
57
+ export {
58
+ LambdaChecker
59
+ };
60
+ //# sourceMappingURL=lambda-NFB5UILT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/infra/checkers/lambda.ts"],"sourcesContent":["/**\n * Lambda resource checker\n */\n\nimport { GetFunctionCommand, LambdaClient } from \"@aws-sdk/client-lambda\";\n\nimport type { ParsedArn, ResourceCheckResult } from \"../types.js\";\nimport type { ResourceChecker } from \"./types.js\";\n\n/**\n * Cache of Lambda clients by region\n */\nconst clientCache = new Map<string, LambdaClient>();\n\n/**\n * Get or create a Lambda client for a region\n */\nfunction getClient(region: string): LambdaClient {\n let client = clientCache.get(region);\n if (!client) {\n client = new LambdaClient({ region });\n clientCache.set(region, client);\n }\n return client;\n}\n\n/**\n * Lambda function checker\n */\nexport const LambdaChecker: ResourceChecker = {\n async check(arn: ParsedArn): Promise<ResourceCheckResult> {\n const { resourceType, resourceId, region, raw } = arn;\n\n // Only check functions (not layers for now)\n if (resourceType !== \"function\") {\n return {\n arn: raw,\n exists: false,\n error: `Unsupported Lambda resource type: ${resourceType}`,\n service: \"lambda\",\n resourceType,\n resourceId,\n };\n }\n\n const client = getClient(region);\n\n try {\n await client.send(new GetFunctionCommand({ FunctionName: resourceId }));\n return {\n arn: raw,\n exists: true,\n service: \"lambda\",\n resourceType: \"function\",\n resourceId,\n };\n } catch (error) {\n const err = error as Error & { name?: string };\n\n if (err.name === \"ResourceNotFoundException\") {\n return {\n arn: raw,\n exists: false,\n service: \"lambda\",\n resourceType: \"function\",\n resourceId,\n };\n }\n\n return {\n arn: raw,\n exists: false,\n error: err.message || \"Unknown error\",\n service: \"lambda\",\n resourceType: \"function\",\n resourceId,\n };\n }\n },\n};\n"],"mappings":";AAIA,SAAS,oBAAoB,oBAAoB;AAQjD,IAAM,cAAc,oBAAI,IAA0B;AAKlD,SAAS,UAAU,QAA8B;AAC/C,MAAI,SAAS,YAAY,IAAI,MAAM;AACnC,MAAI,CAAC,QAAQ;AACX,aAAS,IAAI,aAAa,EAAE,OAAO,CAAC;AACpC,gBAAY,IAAI,QAAQ,MAAM;AAAA,EAChC;AACA,SAAO;AACT;AAKO,IAAM,gBAAiC;AAAA,EAC5C,MAAM,MAAM,KAA8C;AACxD,UAAM,EAAE,cAAc,YAAY,QAAQ,IAAI,IAAI;AAGlD,QAAI,iBAAiB,YAAY;AAC/B,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,qCAAqC,YAAY;AAAA,QACxD,SAAS;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,UAAU,MAAM;AAE/B,QAAI;AACF,YAAM,OAAO,KAAK,IAAI,mBAAmB,EAAE,cAAc,WAAW,CAAC,CAAC;AACtE,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,cAAc;AAAA,QACd;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,YAAM,MAAM;AAEZ,UAAI,IAAI,SAAS,6BAA6B;AAC5C,eAAO;AAAA,UACL,KAAK;AAAA,UACL,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,cAAc;AAAA,UACd;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,IAAI,WAAW;AAAA,QACtB,SAAS;AAAA,QACT,cAAc;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,23 @@
1
+ import {
2
+ ManifestError,
3
+ detectAccountFromResource,
4
+ formatAccountKey,
5
+ getAllResources,
6
+ isLegacyManifest,
7
+ isMultiAccountManifest,
8
+ normalizeManifest,
9
+ parseAccountKey,
10
+ readManifest
11
+ } from "./chunk-M7G73Q6P.js";
12
+ export {
13
+ ManifestError,
14
+ detectAccountFromResource,
15
+ formatAccountKey,
16
+ getAllResources,
17
+ isLegacyManifest,
18
+ isMultiAccountManifest,
19
+ normalizeManifest,
20
+ parseAccountKey,
21
+ readManifest
22
+ };
23
+ //# sourceMappingURL=manifest-7AIL2FK2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,204 @@
1
+ import {
2
+ composeGuidelines,
3
+ fetchStandardsRepo,
4
+ fetchStandardsRepoFromSource,
5
+ getGuidelinesDir,
6
+ getRulesetsDir,
7
+ listRulesets,
8
+ loadAllGuidelines,
9
+ loadGuideline,
10
+ loadRuleset,
11
+ matchGuidelines,
12
+ toListItems
13
+ } from "./chunk-RXA4FO7L.js";
14
+ import "./chunk-P7TIZJ4C.js";
15
+ import {
16
+ loadConfigAsync
17
+ } from "./chunk-KHO6NIAI.js";
18
+
19
+ // src/mcp/server.ts
20
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
21
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
22
+
23
+ // src/mcp/tools/get-guideline.ts
24
+ import { z } from "zod";
25
+ var getGuidelineInputSchema = {
26
+ id: z.string().describe('Guideline ID (e.g., "auth", "database", "typescript")')
27
+ };
28
+ function createGetGuidelineHandler(source) {
29
+ return async (args) => {
30
+ const repoPath = source ? await fetchStandardsRepoFromSource(source) : await fetchStandardsRepo();
31
+ const guidelinesDir = getGuidelinesDir(repoPath);
32
+ const guideline = loadGuideline(guidelinesDir, args.id);
33
+ if (!guideline) {
34
+ return {
35
+ content: [
36
+ {
37
+ type: "text",
38
+ text: `Guideline not found: ${args.id}`
39
+ }
40
+ ],
41
+ isError: true
42
+ };
43
+ }
44
+ const header = `# ${guideline.title}
45
+
46
+ **Category:** ${guideline.category} | **Priority:** ${guideline.priority}
47
+ **Tags:** ${guideline.tags.join(", ")}
48
+
49
+ ---
50
+
51
+ `;
52
+ return {
53
+ content: [
54
+ {
55
+ type: "text",
56
+ text: header + guideline.content
57
+ }
58
+ ]
59
+ };
60
+ };
61
+ }
62
+
63
+ // src/mcp/tools/get-ruleset.ts
64
+ import { z as z2 } from "zod";
65
+ var getRulesetInputSchema = {
66
+ id: z2.string().describe('Ruleset ID (e.g., "typescript-production", "python-internal")')
67
+ };
68
+ function createGetRulesetHandler(source) {
69
+ return async (args) => {
70
+ const repoPath = source ? await fetchStandardsRepoFromSource(source) : await fetchStandardsRepo();
71
+ const rulesetsDir = getRulesetsDir(repoPath);
72
+ const ruleset = loadRuleset(rulesetsDir, args.id);
73
+ if (!ruleset) {
74
+ const available = listRulesets(rulesetsDir);
75
+ return {
76
+ content: [
77
+ {
78
+ type: "text",
79
+ text: `Ruleset not found: ${args.id}
80
+
81
+ Available rulesets:
82
+ ${available.map((r) => `- ${r}`).join("\n")}`
83
+ }
84
+ ],
85
+ isError: true
86
+ };
87
+ }
88
+ return {
89
+ content: [
90
+ {
91
+ type: "text",
92
+ text: `# Ruleset: ${ruleset.id}
93
+
94
+ \`\`\`toml
95
+ ${ruleset.content}
96
+ \`\`\``
97
+ }
98
+ ]
99
+ };
100
+ };
101
+ }
102
+
103
+ // src/mcp/tools/get-standards.ts
104
+ import { z as z3 } from "zod";
105
+ var getStandardsInputSchema = {
106
+ context: z3.string().describe(
107
+ 'Context string describing the task or technology stack (e.g., "python fastapi llm postgresql")'
108
+ ),
109
+ limit: z3.number().optional().describe("Maximum number of guidelines to return (default: 5)")
110
+ };
111
+ function createGetStandardsHandler(source) {
112
+ return async (args) => {
113
+ const repoPath = source ? await fetchStandardsRepoFromSource(source) : await fetchStandardsRepo();
114
+ const guidelinesDir = getGuidelinesDir(repoPath);
115
+ const guidelines = loadAllGuidelines(guidelinesDir);
116
+ const limit = args.limit ?? 5;
117
+ const matches = matchGuidelines(guidelines, args.context, limit);
118
+ const composed = composeGuidelines(matches);
119
+ const summary = matches.length > 0 ? `Found ${matches.length} matching guideline(s) for context: "${args.context}"
120
+
121
+ Matched guidelines (by relevance):
122
+ ${matches.map((m) => `- ${m.guideline.title} (score: ${m.score.toFixed(1)})`).join("\n")}
123
+
124
+ ---
125
+
126
+ ` : "";
127
+ return {
128
+ content: [
129
+ {
130
+ type: "text",
131
+ text: summary + composed
132
+ }
133
+ ]
134
+ };
135
+ };
136
+ }
137
+
138
+ // src/mcp/tools/list-guidelines.ts
139
+ import { z as z4 } from "zod";
140
+ var listGuidelinesInputSchema = {
141
+ category: z4.string().optional().describe("Optional category filter (e.g., 'security', 'infrastructure')")
142
+ };
143
+ function createListGuidelinesHandler(source) {
144
+ return async (args) => {
145
+ const repoPath = source ? await fetchStandardsRepoFromSource(source) : await fetchStandardsRepo();
146
+ const guidelinesDir = getGuidelinesDir(repoPath);
147
+ let guidelines = loadAllGuidelines(guidelinesDir);
148
+ if (args.category) {
149
+ const categoryLower = args.category.toLowerCase();
150
+ guidelines = guidelines.filter((g) => g.category.toLowerCase() === categoryLower);
151
+ }
152
+ const items = toListItems(guidelines);
153
+ return {
154
+ content: [
155
+ {
156
+ type: "text",
157
+ text: JSON.stringify(items, null, 2)
158
+ }
159
+ ]
160
+ };
161
+ };
162
+ }
163
+
164
+ // src/mcp/server.ts
165
+ function createServer(options = {}) {
166
+ const server = new McpServer({
167
+ name: "cm-standards",
168
+ version: "1.0.0"
169
+ });
170
+ const { standardsSource } = options;
171
+ server.registerTool("get_standards", {
172
+ description: "Get composed coding standards matching a context string. Use this to fetch relevant guidelines for a specific technology stack or task.",
173
+ inputSchema: getStandardsInputSchema
174
+ }, createGetStandardsHandler(standardsSource));
175
+ server.registerTool("list_guidelines", {
176
+ description: "List all available coding guidelines with optional category filter.",
177
+ inputSchema: listGuidelinesInputSchema
178
+ }, createListGuidelinesHandler(standardsSource));
179
+ server.registerTool("get_guideline", {
180
+ description: "Get a single coding guideline by its ID.",
181
+ inputSchema: getGuidelineInputSchema
182
+ }, createGetGuidelineHandler(standardsSource));
183
+ server.registerTool("get_ruleset", {
184
+ description: "Get a tool configuration ruleset by ID (e.g., typescript-production, python-internal).",
185
+ inputSchema: getRulesetInputSchema
186
+ }, createGetRulesetHandler(standardsSource));
187
+ return server;
188
+ }
189
+ async function startServer() {
190
+ let standardsSource;
191
+ try {
192
+ const { config } = await loadConfigAsync();
193
+ standardsSource = config.mcp?.standards?.source;
194
+ } catch {
195
+ }
196
+ const server = createServer({ standardsSource });
197
+ const transport = new StdioServerTransport();
198
+ await server.connect(transport);
199
+ }
200
+ export {
201
+ createServer,
202
+ startServer
203
+ };
204
+ //# sourceMappingURL=mcp-O5O7XVFG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mcp/server.ts","../src/mcp/tools/get-guideline.ts","../src/mcp/tools/get-ruleset.ts","../src/mcp/tools/get-standards.ts","../src/mcp/tools/list-guidelines.ts"],"sourcesContent":["/**\n * MCP Server for coding standards\n */\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\n\nimport { loadConfigAsync } from \"@standards-kit/core\";\nimport {\n createGetGuidelineHandler,\n getGuidelineInputSchema,\n createGetRulesetHandler,\n getRulesetInputSchema,\n createGetStandardsHandler,\n getStandardsInputSchema,\n createListGuidelinesHandler,\n listGuidelinesInputSchema,\n} from \"./tools/index.js\";\n\n/** Options for creating the MCP server */\nexport interface CreateServerOptions {\n /** Standards repository source (e.g., \"github:owner/repo\" or local path) */\n standardsSource?: string;\n}\n\n/**\n * Create and configure the MCP server with all tools registered.\n */\nexport function createServer(options: CreateServerOptions = {}): McpServer {\n const server = new McpServer({\n name: \"cm-standards\",\n version: \"1.0.0\",\n });\n\n const { standardsSource } = options;\n\n // Register get_standards tool - smart context matching\n server.registerTool(\"get_standards\", {\n description:\n \"Get composed coding standards matching a context string. Use this to fetch relevant guidelines for a specific technology stack or task.\",\n inputSchema: getStandardsInputSchema,\n }, createGetStandardsHandler(standardsSource));\n\n // Register list_guidelines tool\n server.registerTool(\"list_guidelines\", {\n description: \"List all available coding guidelines with optional category filter.\",\n inputSchema: listGuidelinesInputSchema,\n }, createListGuidelinesHandler(standardsSource));\n\n // Register get_guideline tool\n server.registerTool(\"get_guideline\", {\n description: \"Get a single coding guideline by its ID.\",\n inputSchema: getGuidelineInputSchema,\n }, createGetGuidelineHandler(standardsSource));\n\n // Register get_ruleset tool\n server.registerTool(\"get_ruleset\", {\n description:\n \"Get a tool configuration ruleset by ID (e.g., typescript-production, python-internal).\",\n inputSchema: getRulesetInputSchema,\n }, createGetRulesetHandler(standardsSource));\n\n return server;\n}\n\n/**\n * Start the MCP server with stdio transport.\n * Loads configuration from standards.toml to get the standards source.\n */\nexport async function startServer(): Promise<void> {\n let standardsSource: string | undefined;\n\n // Try to load config to get standards source\n try {\n const { config } = await loadConfigAsync();\n standardsSource = config.mcp?.standards?.source;\n } catch {\n // Config not found or invalid, use defaults\n }\n\n const server = createServer({ standardsSource });\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n","/**\n * MCP tool: get_guideline\n * Gets a single coding guideline by ID\n */\nimport { z } from \"zod\";\n\nimport {\n fetchStandardsRepo,\n fetchStandardsRepoFromSource,\n getGuidelinesDir,\n loadGuideline,\n} from \"../standards/index.js\";\n\n/** Input schema for get_guideline tool */\nexport const getGuidelineInputSchema = {\n id: z.string().describe('Guideline ID (e.g., \"auth\", \"database\", \"typescript\")'),\n};\n\n/** Handler result type - must have index signature for MCP SDK */\ninterface HandlerResult {\n [x: string]: unknown;\n content: { type: \"text\"; text: string }[];\n isError?: boolean;\n}\n\n/**\n * Create a get_guideline handler with optional custom source.\n * @param source - Optional standards source (e.g., \"github:owner/repo\" or local path)\n */\nexport function createGetGuidelineHandler(\n source?: string\n): (args: { id: string }) => Promise<HandlerResult> {\n return async (args) => {\n const repoPath = source\n ? await fetchStandardsRepoFromSource(source)\n : await fetchStandardsRepo();\n const guidelinesDir = getGuidelinesDir(repoPath);\n const guideline = loadGuideline(guidelinesDir, args.id);\n\n if (!guideline) {\n return {\n content: [\n {\n type: \"text\",\n text: `Guideline not found: ${args.id}`,\n },\n ],\n isError: true,\n };\n }\n\n // Return full markdown content with frontmatter info\n const header = `# ${guideline.title}\\n\\n**Category:** ${guideline.category} | **Priority:** ${guideline.priority}\\n**Tags:** ${guideline.tags.join(\", \")}\\n\\n---\\n\\n`;\n\n return {\n content: [\n {\n type: \"text\",\n text: header + guideline.content,\n },\n ],\n };\n };\n}\n","/**\n * MCP tool: get_ruleset\n * Gets a tool configuration ruleset by ID\n */\nimport { z } from \"zod\";\n\nimport {\n fetchStandardsRepo,\n fetchStandardsRepoFromSource,\n getRulesetsDir,\n loadRuleset,\n listRulesets,\n} from \"../standards/index.js\";\n\n/** Input schema for get_ruleset tool */\nexport const getRulesetInputSchema = {\n id: z.string().describe('Ruleset ID (e.g., \"typescript-production\", \"python-internal\")'),\n};\n\n/** Handler result type - must have index signature for MCP SDK */\ninterface HandlerResult {\n [x: string]: unknown;\n content: { type: \"text\"; text: string }[];\n isError?: boolean;\n}\n\n/**\n * Create a get_ruleset handler with optional custom source.\n * @param source - Optional standards source (e.g., \"github:owner/repo\" or local path)\n */\nexport function createGetRulesetHandler(\n source?: string\n): (args: { id: string }) => Promise<HandlerResult> {\n return async (args) => {\n const repoPath = source\n ? await fetchStandardsRepoFromSource(source)\n : await fetchStandardsRepo();\n const rulesetsDir = getRulesetsDir(repoPath);\n const ruleset = loadRuleset(rulesetsDir, args.id);\n\n if (!ruleset) {\n const available = listRulesets(rulesetsDir);\n return {\n content: [\n {\n type: \"text\",\n text: `Ruleset not found: ${args.id}\\n\\nAvailable rulesets:\\n${available.map((r) => `- ${r}`).join(\"\\n\")}`,\n },\n ],\n isError: true,\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: `# Ruleset: ${ruleset.id}\\n\\n\\`\\`\\`toml\\n${ruleset.content}\\n\\`\\`\\``,\n },\n ],\n };\n };\n}\n","/**\n * MCP tool: get_standards\n * Gets composed coding standards matching a context string\n */\nimport { z } from \"zod\";\n\nimport {\n fetchStandardsRepo,\n fetchStandardsRepoFromSource,\n getGuidelinesDir,\n loadAllGuidelines,\n matchGuidelines,\n composeGuidelines,\n} from \"../standards/index.js\";\n\n/** Input schema for get_standards tool */\nexport const getStandardsInputSchema = {\n context: z\n .string()\n .describe(\n 'Context string describing the task or technology stack (e.g., \"python fastapi llm postgresql\")'\n ),\n limit: z.number().optional().describe(\"Maximum number of guidelines to return (default: 5)\"),\n};\n\n/** Handler result type - must have index signature for MCP SDK */\ninterface HandlerResult {\n [x: string]: unknown;\n content: { type: \"text\"; text: string }[];\n}\n\n/**\n * Create a get_standards handler with optional custom source.\n * @param source - Optional standards source (e.g., \"github:owner/repo\" or local path)\n */\nexport function createGetStandardsHandler(\n source?: string\n): (args: { context: string; limit?: number }) => Promise<HandlerResult> {\n return async (args) => {\n const repoPath = source\n ? await fetchStandardsRepoFromSource(source)\n : await fetchStandardsRepo();\n const guidelinesDir = getGuidelinesDir(repoPath);\n const guidelines = loadAllGuidelines(guidelinesDir);\n\n const limit = args.limit ?? 5;\n const matches = matchGuidelines(guidelines, args.context, limit);\n\n const composed = composeGuidelines(matches);\n\n // Add summary header\n const summary =\n matches.length > 0\n ? `Found ${matches.length} matching guideline(s) for context: \"${args.context}\"\\n\\nMatched guidelines (by relevance):\\n${matches.map((m) => `- ${m.guideline.title} (score: ${m.score.toFixed(1)})`).join(\"\\n\")}\\n\\n---\\n\\n`\n : \"\";\n\n return {\n content: [\n {\n type: \"text\",\n text: summary + composed,\n },\n ],\n };\n };\n}\n","/**\n * MCP tool: list_guidelines\n * Lists all available coding guidelines with optional category filter\n */\nimport { z } from \"zod\";\n\nimport {\n fetchStandardsRepo,\n fetchStandardsRepoFromSource,\n getGuidelinesDir,\n loadAllGuidelines,\n toListItems,\n} from \"../standards/index.js\";\n\n/** Input schema for list_guidelines tool */\nexport const listGuidelinesInputSchema = {\n category: z.string().optional().describe(\"Optional category filter (e.g., 'security', 'infrastructure')\"),\n};\n\n/** Handler result type - must have index signature for MCP SDK */\ninterface HandlerResult {\n [x: string]: unknown;\n content: { type: \"text\"; text: string }[];\n}\n\n/**\n * Create a list_guidelines handler with optional custom source.\n * @param source - Optional standards source (e.g., \"github:owner/repo\" or local path)\n */\nexport function createListGuidelinesHandler(\n source?: string\n): (args: { category?: string }) => Promise<HandlerResult> {\n return async (args) => {\n const repoPath = source\n ? await fetchStandardsRepoFromSource(source)\n : await fetchStandardsRepo();\n const guidelinesDir = getGuidelinesDir(repoPath);\n let guidelines = loadAllGuidelines(guidelinesDir);\n\n // Filter by category if provided\n if (args.category) {\n const categoryLower = args.category.toLowerCase();\n guidelines = guidelines.filter((g) => g.category.toLowerCase() === categoryLower);\n }\n\n const items = toListItems(guidelines);\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(items, null, 2),\n },\n ],\n };\n };\n}\n"],"mappings":"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","names":["z","z","z","z","z","z"]}
@@ -0,0 +1,151 @@
1
+ // src/infra/checkers/rds.ts
2
+ import {
3
+ DescribeDBInstancesCommand,
4
+ DescribeDBClustersCommand,
5
+ DescribeDBSubnetGroupsCommand,
6
+ RDSClient
7
+ } from "@aws-sdk/client-rds";
8
+ var clientCache = /* @__PURE__ */ new Map();
9
+ function getClient(region) {
10
+ let client = clientCache.get(region);
11
+ if (!client) {
12
+ client = new RDSClient({ region });
13
+ clientCache.set(region, client);
14
+ }
15
+ return client;
16
+ }
17
+ async function checkDBInstance(client, arn) {
18
+ const { resourceId, raw } = arn;
19
+ try {
20
+ const response = await client.send(
21
+ new DescribeDBInstancesCommand({ DBInstanceIdentifier: resourceId })
22
+ );
23
+ const instance = response.DBInstances?.[0];
24
+ const exists = !!instance && instance.DBInstanceStatus !== "deleting";
25
+ return {
26
+ arn: raw,
27
+ exists,
28
+ service: "rds",
29
+ resourceType: "db",
30
+ resourceId
31
+ };
32
+ } catch (error) {
33
+ const err = error;
34
+ if (err.name === "DBInstanceNotFoundFault") {
35
+ return {
36
+ arn: raw,
37
+ exists: false,
38
+ service: "rds",
39
+ resourceType: "db",
40
+ resourceId
41
+ };
42
+ }
43
+ return {
44
+ arn: raw,
45
+ exists: false,
46
+ error: err.message || "Unknown error",
47
+ service: "rds",
48
+ resourceType: "db",
49
+ resourceId
50
+ };
51
+ }
52
+ }
53
+ async function checkDBCluster(client, arn) {
54
+ const { resourceId, raw } = arn;
55
+ try {
56
+ const response = await client.send(
57
+ new DescribeDBClustersCommand({ DBClusterIdentifier: resourceId })
58
+ );
59
+ const cluster = response.DBClusters?.[0];
60
+ const exists = !!cluster && cluster.Status !== "deleting";
61
+ return {
62
+ arn: raw,
63
+ exists,
64
+ service: "rds",
65
+ resourceType: "cluster",
66
+ resourceId
67
+ };
68
+ } catch (error) {
69
+ const err = error;
70
+ if (err.name === "DBClusterNotFoundFault") {
71
+ return {
72
+ arn: raw,
73
+ exists: false,
74
+ service: "rds",
75
+ resourceType: "cluster",
76
+ resourceId
77
+ };
78
+ }
79
+ return {
80
+ arn: raw,
81
+ exists: false,
82
+ error: err.message || "Unknown error",
83
+ service: "rds",
84
+ resourceType: "cluster",
85
+ resourceId
86
+ };
87
+ }
88
+ }
89
+ async function checkDBSubnetGroup(client, arn) {
90
+ const { resourceId, raw } = arn;
91
+ try {
92
+ const response = await client.send(
93
+ new DescribeDBSubnetGroupsCommand({ DBSubnetGroupName: resourceId })
94
+ );
95
+ const subnetGroup = response.DBSubnetGroups?.[0];
96
+ const exists = !!subnetGroup;
97
+ return {
98
+ arn: raw,
99
+ exists,
100
+ service: "rds",
101
+ resourceType: "subgrp",
102
+ resourceId
103
+ };
104
+ } catch (error) {
105
+ const err = error;
106
+ if (err.name === "DBSubnetGroupNotFoundFault") {
107
+ return {
108
+ arn: raw,
109
+ exists: false,
110
+ service: "rds",
111
+ resourceType: "subgrp",
112
+ resourceId
113
+ };
114
+ }
115
+ return {
116
+ arn: raw,
117
+ exists: false,
118
+ error: err.message || "Unknown error",
119
+ service: "rds",
120
+ resourceType: "subgrp",
121
+ resourceId
122
+ };
123
+ }
124
+ }
125
+ var RDSChecker = {
126
+ async check(arn) {
127
+ const { resourceType, resourceId, region, raw } = arn;
128
+ const client = getClient(region);
129
+ switch (resourceType) {
130
+ case "db":
131
+ return checkDBInstance(client, arn);
132
+ case "cluster":
133
+ return checkDBCluster(client, arn);
134
+ case "subgrp":
135
+ return checkDBSubnetGroup(client, arn);
136
+ default:
137
+ return {
138
+ arn: raw,
139
+ exists: false,
140
+ error: `Unsupported RDS resource type: ${resourceType}`,
141
+ service: "rds",
142
+ resourceType,
143
+ resourceId
144
+ };
145
+ }
146
+ }
147
+ };
148
+ export {
149
+ RDSChecker
150
+ };
151
+ //# sourceMappingURL=rds-KLG5O5SI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/infra/checkers/rds.ts"],"sourcesContent":["/**\n * RDS resource checker\n *\n * Supports:\n * - DB instances\n * - DB clusters (Aurora)\n * - DB subnet groups\n */\n\nimport {\n DescribeDBInstancesCommand,\n DescribeDBClustersCommand,\n DescribeDBSubnetGroupsCommand,\n RDSClient,\n} from \"@aws-sdk/client-rds\";\n\nimport type { ParsedArn, ResourceCheckResult } from \"../types.js\";\nimport type { ResourceChecker } from \"./types.js\";\n\n/**\n * Cache of RDS clients by region\n */\nconst clientCache = new Map<string, RDSClient>();\n\n/**\n * Get or create an RDS client for a region\n */\nfunction getClient(region: string): RDSClient {\n let client = clientCache.get(region);\n if (!client) {\n client = new RDSClient({ region });\n clientCache.set(region, client);\n }\n return client;\n}\n\n/**\n * Check if an RDS DB instance exists\n */\nasync function checkDBInstance(\n client: RDSClient,\n arn: ParsedArn\n): Promise<ResourceCheckResult> {\n const { resourceId, raw } = arn;\n\n try {\n const response = await client.send(\n new DescribeDBInstancesCommand({ DBInstanceIdentifier: resourceId })\n );\n\n const instance = response.DBInstances?.[0];\n const exists = !!instance && instance.DBInstanceStatus !== \"deleting\";\n\n return {\n arn: raw,\n exists,\n service: \"rds\",\n resourceType: \"db\",\n resourceId,\n };\n } catch (error) {\n const err = error as Error & { name?: string };\n\n if (err.name === \"DBInstanceNotFoundFault\") {\n return {\n arn: raw,\n exists: false,\n service: \"rds\",\n resourceType: \"db\",\n resourceId,\n };\n }\n\n return {\n arn: raw,\n exists: false,\n error: err.message || \"Unknown error\",\n service: \"rds\",\n resourceType: \"db\",\n resourceId,\n };\n }\n}\n\n/**\n * Check if an RDS DB cluster exists (Aurora)\n */\nasync function checkDBCluster(\n client: RDSClient,\n arn: ParsedArn\n): Promise<ResourceCheckResult> {\n const { resourceId, raw } = arn;\n\n try {\n const response = await client.send(\n new DescribeDBClustersCommand({ DBClusterIdentifier: resourceId })\n );\n\n const cluster = response.DBClusters?.[0];\n const exists = !!cluster && cluster.Status !== \"deleting\";\n\n return {\n arn: raw,\n exists,\n service: \"rds\",\n resourceType: \"cluster\",\n resourceId,\n };\n } catch (error) {\n const err = error as Error & { name?: string };\n\n if (err.name === \"DBClusterNotFoundFault\") {\n return {\n arn: raw,\n exists: false,\n service: \"rds\",\n resourceType: \"cluster\",\n resourceId,\n };\n }\n\n return {\n arn: raw,\n exists: false,\n error: err.message || \"Unknown error\",\n service: \"rds\",\n resourceType: \"cluster\",\n resourceId,\n };\n }\n}\n\n/**\n * Check if an RDS DB subnet group exists\n */\nasync function checkDBSubnetGroup(\n client: RDSClient,\n arn: ParsedArn\n): Promise<ResourceCheckResult> {\n const { resourceId, raw } = arn;\n\n try {\n const response = await client.send(\n new DescribeDBSubnetGroupsCommand({ DBSubnetGroupName: resourceId })\n );\n\n const subnetGroup = response.DBSubnetGroups?.[0];\n const exists = !!subnetGroup;\n\n return {\n arn: raw,\n exists,\n service: \"rds\",\n resourceType: \"subgrp\",\n resourceId,\n };\n } catch (error) {\n const err = error as Error & { name?: string };\n\n if (err.name === \"DBSubnetGroupNotFoundFault\") {\n return {\n arn: raw,\n exists: false,\n service: \"rds\",\n resourceType: \"subgrp\",\n resourceId,\n };\n }\n\n return {\n arn: raw,\n exists: false,\n error: err.message || \"Unknown error\",\n service: \"rds\",\n resourceType: \"subgrp\",\n resourceId,\n };\n }\n}\n\n/**\n * RDS resource checker\n */\nexport const RDSChecker: ResourceChecker = {\n async check(arn: ParsedArn): Promise<ResourceCheckResult> {\n const { resourceType, resourceId, region, raw } = arn;\n const client = getClient(region);\n\n switch (resourceType) {\n case \"db\":\n return checkDBInstance(client, arn);\n\n case \"cluster\":\n return checkDBCluster(client, arn);\n\n case \"subgrp\":\n return checkDBSubnetGroup(client, arn);\n\n default:\n return {\n arn: raw,\n exists: false,\n error: `Unsupported RDS resource type: ${resourceType}`,\n service: \"rds\",\n resourceType,\n resourceId,\n };\n }\n },\n};\n"],"mappings":";AASA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAQP,IAAM,cAAc,oBAAI,IAAuB;AAK/C,SAAS,UAAU,QAA2B;AAC5C,MAAI,SAAS,YAAY,IAAI,MAAM;AACnC,MAAI,CAAC,QAAQ;AACX,aAAS,IAAI,UAAU,EAAE,OAAO,CAAC;AACjC,gBAAY,IAAI,QAAQ,MAAM;AAAA,EAChC;AACA,SAAO;AACT;AAKA,eAAe,gBACb,QACA,KAC8B;AAC9B,QAAM,EAAE,YAAY,IAAI,IAAI;AAE5B,MAAI;AACF,UAAM,WAAW,MAAM,OAAO;AAAA,MAC5B,IAAI,2BAA2B,EAAE,sBAAsB,WAAW,CAAC;AAAA,IACrE;AAEA,UAAM,WAAW,SAAS,cAAc,CAAC;AACzC,UAAM,SAAS,CAAC,CAAC,YAAY,SAAS,qBAAqB;AAE3D,WAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,SAAS;AAAA,MACT,cAAc;AAAA,MACd;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,UAAM,MAAM;AAEZ,QAAI,IAAI,SAAS,2BAA2B;AAC1C,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,cAAc;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,OAAO,IAAI,WAAW;AAAA,MACtB,SAAS;AAAA,MACT,cAAc;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACF;AAKA,eAAe,eACb,QACA,KAC8B;AAC9B,QAAM,EAAE,YAAY,IAAI,IAAI;AAE5B,MAAI;AACF,UAAM,WAAW,MAAM,OAAO;AAAA,MAC5B,IAAI,0BAA0B,EAAE,qBAAqB,WAAW,CAAC;AAAA,IACnE;AAEA,UAAM,UAAU,SAAS,aAAa,CAAC;AACvC,UAAM,SAAS,CAAC,CAAC,WAAW,QAAQ,WAAW;AAE/C,WAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,SAAS;AAAA,MACT,cAAc;AAAA,MACd;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,UAAM,MAAM;AAEZ,QAAI,IAAI,SAAS,0BAA0B;AACzC,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,cAAc;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,OAAO,IAAI,WAAW;AAAA,MACtB,SAAS;AAAA,MACT,cAAc;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACF;AAKA,eAAe,mBACb,QACA,KAC8B;AAC9B,QAAM,EAAE,YAAY,IAAI,IAAI;AAE5B,MAAI;AACF,UAAM,WAAW,MAAM,OAAO;AAAA,MAC5B,IAAI,8BAA8B,EAAE,mBAAmB,WAAW,CAAC;AAAA,IACrE;AAEA,UAAM,cAAc,SAAS,iBAAiB,CAAC;AAC/C,UAAM,SAAS,CAAC,CAAC;AAEjB,WAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,SAAS;AAAA,MACT,cAAc;AAAA,MACd;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,UAAM,MAAM;AAEZ,QAAI,IAAI,SAAS,8BAA8B;AAC7C,aAAO;AAAA,QACL,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,cAAc;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,OAAO,IAAI,WAAW;AAAA,MACtB,SAAS;AAAA,MACT,cAAc;AAAA,MACd;AAAA,IACF;AAAA,EACF;AACF;AAKO,IAAM,aAA8B;AAAA,EACzC,MAAM,MAAM,KAA8C;AACxD,UAAM,EAAE,cAAc,YAAY,QAAQ,IAAI,IAAI;AAClD,UAAM,SAAS,UAAU,MAAM;AAE/B,YAAQ,cAAc;AAAA,MACpB,KAAK;AACH,eAAO,gBAAgB,QAAQ,GAAG;AAAA,MAEpC,KAAK;AACH,eAAO,eAAe,QAAQ,GAAG;AAAA,MAEnC,KAAK;AACH,eAAO,mBAAmB,QAAQ,GAAG;AAAA,MAEvC;AACE,eAAO;AAAA,UACL,KAAK;AAAA,UACL,QAAQ;AAAA,UACR,OAAO,kCAAkC,YAAY;AAAA,UACrD,SAAS;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,IACJ;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,15 @@
1
+ import {
2
+ fetchRegistry,
3
+ loadRuleset,
4
+ mergeConfigs,
5
+ parseRegistryUrl,
6
+ resolveExtends
7
+ } from "./chunk-KHO6NIAI.js";
8
+ export {
9
+ fetchRegistry,
10
+ loadRuleset,
11
+ mergeConfigs,
12
+ parseRegistryUrl,
13
+ resolveExtends
14
+ };
15
+ //# sourceMappingURL=registry-V65CC7IN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,49 @@
1
+ // src/infra/checkers/s3.ts
2
+ import { HeadBucketCommand, S3Client } from "@aws-sdk/client-s3";
3
+ var clientCache = /* @__PURE__ */ new Map();
4
+ function getClient(region) {
5
+ const effectiveRegion = region || "us-east-1";
6
+ let client = clientCache.get(effectiveRegion);
7
+ if (!client) {
8
+ client = new S3Client({
9
+ region: effectiveRegion,
10
+ followRegionRedirects: true
11
+ });
12
+ clientCache.set(effectiveRegion, client);
13
+ }
14
+ return client;
15
+ }
16
+ var S3Checker = {
17
+ async check(arn) {
18
+ const { resourceType, resourceId, raw } = arn;
19
+ if (resourceType === "object") {
20
+ const bucketName = resourceId.split("/")[0];
21
+ return checkBucket(bucketName, arn.region, raw);
22
+ }
23
+ return checkBucket(resourceId, arn.region, raw);
24
+ }
25
+ };
26
+ function bucketResult(arn, bucketName, exists, error) {
27
+ return { arn, exists, error, service: "s3", resourceType: "bucket", resourceId: bucketName };
28
+ }
29
+ function isBucketNotFound(err) {
30
+ const httpStatus = err.$metadata?.httpStatusCode;
31
+ return err.name === "NotFound" || err.name === "NoSuchBucket" || httpStatus === 404 || err.name === "Forbidden" || err.name === "AccessDenied" || httpStatus === 403;
32
+ }
33
+ async function checkBucket(bucketName, region, arn) {
34
+ const client = getClient(region);
35
+ try {
36
+ await client.send(new HeadBucketCommand({ Bucket: bucketName }));
37
+ return bucketResult(arn, bucketName, true);
38
+ } catch (error) {
39
+ const err = error;
40
+ if (isBucketNotFound(err)) {
41
+ return bucketResult(arn, bucketName, false);
42
+ }
43
+ return bucketResult(arn, bucketName, false, err.message || "Unknown error");
44
+ }
45
+ }
46
+ export {
47
+ S3Checker
48
+ };
49
+ //# sourceMappingURL=s3-2DH7PRVR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/infra/checkers/s3.ts"],"sourcesContent":["/**\n * S3 resource checker\n */\n\nimport { HeadBucketCommand, S3Client } from \"@aws-sdk/client-s3\";\n\nimport type { ParsedArn, ResourceCheckResult } from \"../types.js\";\nimport type { ResourceChecker } from \"./types.js\";\n\n/**\n * Cache of S3 clients by region\n */\nconst clientCache = new Map<string, S3Client>();\n\n/**\n * Get or create an S3 client for a region\n */\nfunction getClient(region: string): S3Client {\n // S3 is global, but we use us-east-1 for global operations\n const effectiveRegion = region || \"us-east-1\";\n\n let client = clientCache.get(effectiveRegion);\n if (!client) {\n client = new S3Client({\n region: effectiveRegion,\n followRegionRedirects: true,\n });\n clientCache.set(effectiveRegion, client);\n }\n return client;\n}\n\n/**\n * S3 bucket checker\n */\nexport const S3Checker: ResourceChecker = {\n async check(arn: ParsedArn): Promise<ResourceCheckResult> {\n const { resourceType, resourceId, raw } = arn;\n\n // Only check bucket existence (not individual objects)\n if (resourceType === \"object\") {\n // For objects, we'd need to check if the key exists, which is expensive\n // For now, we just check if the bucket exists\n const bucketName = resourceId.split(\"/\")[0];\n return checkBucket(bucketName, arn.region, raw);\n }\n\n return checkBucket(resourceId, arn.region, raw);\n },\n};\n\n/**\n * Create a bucket check result\n */\nfunction bucketResult(\n arn: string,\n bucketName: string,\n exists: boolean,\n error?: string\n): ResourceCheckResult {\n return { arn, exists, error, service: \"s3\", resourceType: \"bucket\", resourceId: bucketName };\n}\n\n/**\n * Check if error indicates bucket doesn't exist (404 or 403)\n */\nfunction isBucketNotFound(err: Error & { name?: string; $metadata?: { httpStatusCode?: number } }): boolean {\n const httpStatus = err.$metadata?.httpStatusCode;\n // 404 = not found, 403 = access denied (S3 returns 403 for non-existent buckets to prevent enumeration)\n return err.name === \"NotFound\" || err.name === \"NoSuchBucket\" || httpStatus === 404 ||\n err.name === \"Forbidden\" || err.name === \"AccessDenied\" || httpStatus === 403;\n}\n\n/**\n * Check if an S3 bucket exists\n */\nasync function checkBucket(bucketName: string, region: string, arn: string): Promise<ResourceCheckResult> {\n const client = getClient(region);\n\n try {\n await client.send(new HeadBucketCommand({ Bucket: bucketName }));\n return bucketResult(arn, bucketName, true);\n } catch (error) {\n const err = error as Error & { name?: string; $metadata?: { httpStatusCode?: number } };\n if (isBucketNotFound(err)) {\n return bucketResult(arn, bucketName, false);\n }\n return bucketResult(arn, bucketName, false, err.message || \"Unknown error\");\n }\n}\n"],"mappings":";AAIA,SAAS,mBAAmB,gBAAgB;AAQ5C,IAAM,cAAc,oBAAI,IAAsB;AAK9C,SAAS,UAAU,QAA0B;AAE3C,QAAM,kBAAkB,UAAU;AAElC,MAAI,SAAS,YAAY,IAAI,eAAe;AAC5C,MAAI,CAAC,QAAQ;AACX,aAAS,IAAI,SAAS;AAAA,MACpB,QAAQ;AAAA,MACR,uBAAuB;AAAA,IACzB,CAAC;AACD,gBAAY,IAAI,iBAAiB,MAAM;AAAA,EACzC;AACA,SAAO;AACT;AAKO,IAAM,YAA6B;AAAA,EACxC,MAAM,MAAM,KAA8C;AACxD,UAAM,EAAE,cAAc,YAAY,IAAI,IAAI;AAG1C,QAAI,iBAAiB,UAAU;AAG7B,YAAM,aAAa,WAAW,MAAM,GAAG,EAAE,CAAC;AAC1C,aAAO,YAAY,YAAY,IAAI,QAAQ,GAAG;AAAA,IAChD;AAEA,WAAO,YAAY,YAAY,IAAI,QAAQ,GAAG;AAAA,EAChD;AACF;AAKA,SAAS,aACP,KACA,YACA,QACA,OACqB;AACrB,SAAO,EAAE,KAAK,QAAQ,OAAO,SAAS,MAAM,cAAc,UAAU,YAAY,WAAW;AAC7F;AAKA,SAAS,iBAAiB,KAAkF;AAC1G,QAAM,aAAa,IAAI,WAAW;AAElC,SAAO,IAAI,SAAS,cAAc,IAAI,SAAS,kBAAkB,eAAe,OACzE,IAAI,SAAS,eAAe,IAAI,SAAS,kBAAkB,eAAe;AACnF;AAKA,eAAe,YAAY,YAAoB,QAAgB,KAA2C;AACxG,QAAM,SAAS,UAAU,MAAM;AAE/B,MAAI;AACF,UAAM,OAAO,KAAK,IAAI,kBAAkB,EAAE,QAAQ,WAAW,CAAC,CAAC;AAC/D,WAAO,aAAa,KAAK,YAAY,IAAI;AAAA,EAC3C,SAAS,OAAO;AACd,UAAM,MAAM;AACZ,QAAI,iBAAiB,GAAG,GAAG;AACzB,aAAO,aAAa,KAAK,YAAY,KAAK;AAAA,IAC5C;AACA,WAAO,aAAa,KAAK,YAAY,OAAO,IAAI,WAAW,eAAe;AAAA,EAC5E;AACF;","names":[]}