cdk-insights 1.41.0 → 1.41.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entry.js +5 -5
- package/dist/index.js +31 -31
- package/package.json +1 -1
package/dist/entry.js
CHANGED
|
@@ -158,7 +158,7 @@ ${e}`;return s(n,{})},dJ=t=>e=>{if(fT(e)){let n=e.stdout?.toString()||"",r=e.std
|
|
|
158
158
|
`):[],s=[];for(let n of e){let r=n.trim();if(!r||SJ(r))continue;let o=r.replace(/^at\s+(?:.*?\s+)?/,"").match(bJ);if(!o)continue;let[,a,,c,u]=o;gJ(a)||s.push({filePath:a.startsWith("/")?a:`./${a}`,line:Number(c),column:Number(u),kind:"unknown"})}return s},Ub=t=>{if(t.length===0)return t;let e=t.findIndex(n=>/\.tsx?$/.test(n.filePath));if(e<=0)return t;let[s]=t.splice(e,1);return[s,...t]},vJ=t=>{if(t.type===FT){let e=t.data,s=Ub(jb(e?.stackTrace));return s.length===0?null:s.map((n,r)=>({...n,kind:r===0?"property":n.kind,...r===0&&e.propertyName?{propertyName:e.propertyName}:{}}))}if(TT.includes(t.type)){let e=Ub(jb(t.data));return e.length===0?null:e.map((s,n)=>({...s,kind:n===0?"creation":s.kind}))}return null},PT=t=>{if(t.length===0)return null;let[e]=t;return{filePath:e.filePath,line:e.line,column:e.column,frames:t}},IT=(t,e)=>PT(Ub(jb(t))),Qf=(t,e,s=process.cwd())=>{try{if(t&&typeof t=="object"&&"artifacts"in t){let c=t,u=e,l={};for(let f of Object.values(c.artifacts??{}))if(f.metadata)for(let[m,g]of Object.entries(f.metadata))l[m]=g;let d=Object.entries(l).filter(([,f])=>f.some(m=>m.type==="aws:cdk:logicalId"&&m.data===u));for(let[f,m]of d){let g=m.find(C=>C.type==="aws:cdk:info"&&typeof C.data=="string"&&C.data.startsWith("cdk-insights::")&&!C.data.startsWith("cdk-insights::nagFinding::"));if(g)try{let C=JSON.parse(g.data.replace("cdk-insights::",""));if(C.sourceLocation)return{filePath:C.sourceLocation.filePath,line:C.sourceLocation.line||1,column:C.sourceLocation.column||1,constructPath:f,stackName:f.split("/")[0]||"",logicalId:u,confidence:"high"}}catch{}let h=[...m.filter(C=>C.type===FT),...m.filter(C=>TT.includes(C.type))];for(let C of h){let A=vJ(C),w=A?PT(A):null;if(!w?.filePath)continue;let N=Cs.resolve(s,w.filePath);if(ks.existsSync(N))return{...w,line:w.line??1,column:w.column??1,constructPath:f,stackName:f.split("/")[0]||"",logicalId:u,confidence:"high"}}let b=m.find(C=>C.type==="aws:cdk:logicalId"&&C.data===u)?.trace;if(b){let C=IT(b,f);if(C?.filePath){let A=Cs.resolve(s,C.filePath);if(ks.existsSync(A))return{...C,line:C.line??1,column:C.column??1,constructPath:f,stackName:f.split("/")[0]||"",logicalId:u,confidence:"high"}}}}for(let[f]of d){let m=RT(f,s);if(m)return{...m,line:m.line??1,column:m.column??1,constructPath:f,stackName:f.split("/")[0]||"",logicalId:u,confidence:"medium"}}let p=d[0]?.[0]||u;return kT(p,u,s)}let r=t,i=e,o=IT(r,i);if(o?.filePath){let c=Cs.resolve(s,o.filePath);if(ks.existsSync(c))return{...o,line:o.line??1,column:o.column??1,constructPath:i,confidence:"high"}}let a=RT(i,s);return a?{...a,line:a.line??1,column:a.column??1,constructPath:i,confidence:"medium"}:kT(i,i,s)}catch{return{filePath:e,line:1,column:1,constructPath:e,confidence:"low"}}},kT=(t,e,s)=>{let n=t.split("/").pop()||"",r=t.split("/")[0]||"",i=xJ(s);for(let o of i)try{let a=Gb(o);if(!a)continue;let c=a.split(`
|
|
159
159
|
`);for(let u=0;u<c.length;u++){let l=c[u];if(l.includes("new")&&l.includes("this")&&(l.includes(n)||l.includes(r)))return{filePath:Cs.relative(s,o),line:u+1,column:l.indexOf("new")+1,constructPath:t,stackName:r,logicalId:e,confidence:"low"}}}catch{}return null}});var Ec,Kb,Rc,Xf=D(()=>{"use strict";Ec=oe(require("node:fs")),Kb=oe(require("node:path")),Rc=t=>{let e=Kb.join(t,"manifest.json");if(!Ec.existsSync(e))return{};let s;try{s=JSON.parse(Ec.readFileSync(e,"utf-8"))}catch{return{}}if(!s.artifacts)return s;for(let n of Object.values(s.artifacts)){let r=n?.additionalMetadataFile;if(!r||n.metadata)continue;let i=Kb.join(t,r);if(Ec.existsSync(i))try{let o=JSON.parse(Ec.readFileSync(i,"utf-8"));o&&typeof o=="object"&&(n.metadata=o)}catch{}}return s}});var CJ,DJ,AJ,wJ,LT,OT=D(()=>{"use strict";wT();qb();Xf();CJ=t=>{let e=t.split(".");return e[e.length-1]||t},DJ=t=>{if(!t||t.length===0)return;let e=t.filter(r=>!r.isCustom).map(r=>CJ(r.fqn)),s=t.filter(r=>r.isCustom).length,n=[];return e.length>0&&n.push(`\`${e.join("`, `")}\``),s>0&&n.push(s===1?"a user-defined mixin (opaque to cdk-insights)":`${s} user-defined mixins (opaque to cdk-insights)`),`Note: CDK Mixin(s) applied to this resource \u2014 ${n.join(" and ")}. If your remediation conflicts with a mixin, the mixin will re-apply at synth; update the mixin definition or its \`Mixins.of(scope)\` selector instead of (or in addition to) the resource props.`},AJ=(t,e)=>e?t?`${t}
|
|
160
160
|
|
|
161
|
-
${e}`:e:t,wJ=(t,e)=>t?!!(e?.startsWith("AWS::CDK::")||e?.startsWith("Cfn")||t.endsWith("/Resource")||t==="Resource"||t.includes("Asset")||t.includes("CustomResource")):!1,LT=(t,e,s,n,r)=>{let i=Rc("cdk.out");return Object.entries(t).reduce((o,[a,c])=>{let u=Object.keys(e).find(z=>e[z]===a)??c.cdkPath,l=s[a]?.__constructType??n.Resources?.[a]?.Type??"",d=r[a]?.githubUrl,p=r[a]?.docUrl,f=r[a]?.constructName,m=r[a]?.constructLevel,g=r[a]?.fqn,h=wJ(u,l),y=s[a]?.displayName,b=y??s[a]?.__friendlyName??u.split("/").pop()??a,C=y??u??c.locationHint,A=Qf(i,a),w=c.appliedMixins??s[a]?.__appliedMixins,N=DJ(w),L=[...c.sources?.cdkInsights?.issues??[],...c.sources?.cdkNag?.issues??[]].map(z=>({...z,recommendation:AT(AJ(z.recommendation,N),m),locationHint:C,githubUrl:d,docUrl:p,constructName:f,...m?{constructLevel:m}:{},...g?{fqn:g}:{},...A?.filePath&&{sourceLocation:{filePath:A.filePath,line:A.line||1,column:A.column||1,confidence:A.confidence||"low",...A.frames&&A.frames.length>0?{frames:A.frames}:{}}},stackName:A?.stackName,stackId:A?.stackName,timestamp:new Date().toISOString()})),R=L.filter(z=>z.foundBy!=="cdkNag"),H=L.filter(z=>z.foundBy==="cdkNag"),B=s[a],S=c.parentPath||B?.__parentPath,U=c.childCount??B?.__childCount,k=c.tags||B?.__tags,K=c.sourceLocation||B?.__sourceLocation,x=c.constructHierarchy||B?.__constructHierarchy,v=c.serviceCategory||B?.__serviceCategory,Y=c.dependencies||B?.__dependencies,J=c.sensitiveProperties||B?.__sensitiveProperties,X=c.usesDefaults??B?.__usesDefaults,re=c.l2ConstructType||B?.__l2ConstructType,pe=c.l2ConstructId||B?.__l2ConstructId,Ae=c.createdBy||B?.__createdBy,we=c.rootSourceLocation||B?.__rootSourceLocation,ue=c.searchHint||B?.__searchHint,Re=K?{filePath:K.filePath,line:K.line,column:K.column,endLine:K.endLine,endColumn:K.endColumn,confidence:K.confidence||"high",method:K.method,enclosingScope:K.enclosingScope,codeSnippet:K.codeSnippet}:A?.filePath?{filePath:A.filePath,line:A.line||1,column:A.column||1,confidence:A.confidence||"low"}:void 0;return o[a]={...c,resourceId:a,displayName:y,cdkPath:u,friendlyName:b,locationHint:C,constructName:f,githubUrl:d,docUrl:p,isGenerated:h,type:l,constructType:l,parentPath:S,childCount:U,tags:k,sourceLocation:Re,constructHierarchy:x,logicalId:a,serviceCategory:v,dependencies:Y,sensitiveProperties:J,usesDefaults:X,l2ConstructType:re,l2ConstructId:pe,createdBy:Ae,rootSourceLocation:we,searchHint:ue,appliedMixins:w,sources:{cdkInsights:{issues:R},cdkNag:{issues:H}}},o},{})}});var EJ,il,MT,BT,RJ,ol,al,Vb,NT,Zb=D(()=>{"use strict";EJ=new Set(["AwsSolutions-IAM4","AwsSolutions-IAM5","AwsSolutions-S1","AwsSolutions-S2","AwsSolutions-S3","AwsSolutions-S10","AwsSolutions-RDS2","AwsSolutions-RDS6","AwsSolutions-RDS10","AwsSolutions-EC23","AwsSolutions-EC26","AwsSolutions-ECS4","AwsSolutions-COG2","AwsSolutions-COG3","AwsSolutions-ELB2","AwsSolutions-KMS5","AwsSolutions-L1","AwsSolutions-SMG4","AwsSolutions-DDB3","AwsSolutions-CB4"]),il={AwsSolutions:"https://github.com/cdklabs/cdk-nag/blob/main/RULES.md#awssolutions-rules","HIPAA.Security":"https://github.com/cdklabs/cdk-nag/blob/main/RULES.md#hipaasecurity-rules","NIST.800.53.R4":"https://github.com/cdklabs/cdk-nag/blob/main/RULES.md#nist-80053-rules","NIST.800.53.R5":"https://github.com/cdklabs/cdk-nag/blob/main/RULES.md#nist-80053-rules","PCI.DSS.321":"https://github.com/cdklabs/cdk-nag/blob/main/RULES.md#pcidss-rules"},MT={IAM:"Security",S:"Security",EC:"Security",VPC:"Security",KMS:"Security",SMG:"Security",COG:"Security",CFR:"Security",ELB:"Security",RDS:"Security",DDB:"Security",SQS:"Security",SNS:"Security",L:"Security",ECS:"Security",EKS:"Security",CB:"Security",ATH:"Security",OS:"Security",RS:"Security",TS:"Security",QL:"Security",APS:"Security",DOC:"Security",EFS:"Security",GL:"Security",KDF:"Security",KDS:"Security",LEX:"Security",MSK:"Security",N:"Security",QS:"Security",EMR:"Security",AS:"Reliability",AEC:"Reliability",KDA:"Reliability",CW:"Operational Excellence",CT:"Operational Excellence",SF:"Operational Excellence",EB:"Operational Excellence",ASC:"Operational Excellence",MS:"Operational Excellence",EVB:"Operational Excellence",C91:"Security"},BT=t=>t.match(/^((?:AwsSolutions|HIPAA\.Security|NIST\.800\.53\.R[45]|PCI\.DSS\.321)-[A-Z0-9]+)/i)?.[1],RJ=t=>t.match(/-([A-Z]+)\d*$/i)?.[1]?.toUpperCase(),ol=(t,e)=>{if(e&&EJ.has(e))return"CRITICAL";switch(t){case"aws:cdk:error":return"HIGH";case"aws:cdk:warning":return"MEDIUM";case"aws:cdk:info":return"LOW";default:return"HIGH"}},al=t=>{if(!t)return"Security";let e=RJ(t);return e&&MT[e]?MT[e]:"Security"},Vb=t=>{if(t){if(t.startsWith("AwsSolutions-"))return il.AwsSolutions;if(t.startsWith("HIPAA.Security-"))return il["HIPAA.Security"];if(t.startsWith("NIST.800.53.R4-"))return il["NIST.800.53.R4"];if(t.startsWith("NIST.800.53.R5-"))return il["NIST.800.53.R5"];if(t.startsWith("PCI.DSS.321-"))return il["PCI.DSS.321"]}},NT=t=>t.startsWith("AwsSolutions-")||t.startsWith("HIPAA.Security-")||t.startsWith("NIST.800.53.R")||t.startsWith("PCI.DSS.321-")});var $T,WT=D(()=>{"use strict";Zb();$T=(t,e)=>{let s=/\[([^\]]*)\]\s*\[([^\]]*)\]\s*\[([^\]]*)\]/g,n=[],r=s.exec(t);for(;r!==null;){let i=r[1]??"",o=r[2],a=r[3];if(o&&a){let c=e[i]??i;n.push({resourceId:c,issue:a,severity:ol("inline",o),wafPillar:al(o),foundBy:"cdkNag",constructPath:i,ruleId:o})}r=s.exec(t)}return n}});var em,jT,UT,HT=D(()=>{"use strict";em=oe(require("node:fs")),jT=oe(require("node:path")),UT=(t=process.cwd())=>{let e=jT.join(t,"cdk.json");if(!em.existsSync(e))return{context:{},found:!1};let s;try{s=em.readFileSync(e,"utf-8")}catch{return{context:{},found:!1}}let n;try{n=JSON.parse(s)}catch{return{context:{},found:!1,source:e}}return n&&typeof n=="object"&&!Array.isArray(n)&&"context"in n&&typeof n.context=="object"&&n.context!==null&&!Array.isArray(n.context)?{context:n.context,found:!0,source:e}:{context:{},found:!0,source:e}}});var GT,zT=D(()=>{"use strict";GT=(t,e)=>e?Object.entries(t).reduce((s,[n,r])=>(s[n]={...r,__description:r.__description||e[n]},s),{}):{...t}});var IJ,kJ,qT,KT=D(()=>{"use strict";IJ="aws:cdk:analytics:mixin",kJ="*",qT=t=>{let e=new Set,s=[];for(let n of t){if(n.type!==IJ||!n.data||typeof n.data!="object"||Array.isArray(n.data))continue;let r=n.data.mixin;typeof r!="string"||r.length===0||e.has(r)||(e.add(r),s.push({fqn:r,isCustom:r===kJ}))}return s}});var cl,_J,Yb,VT,FJ,ZT,TJ,PJ,YT,JT=D(()=>{"use strict";Zb();dt();KT();cl="cdk-insights::",_J="aws:cdk:acknowledged-rules",Yb="cdk-insights::nagFinding::",VT=t=>t.startsWith(cl)&&!t.startsWith(Yb),FJ=t=>t.startsWith(Yb),ZT="2.2.0",TJ=(t,e)=>{let s=t.split(".").map(Number),n=e.split(".").map(Number);for(let r=0;r<Math.max(s.length,n.length);r++){let i=s[r]||0,o=n[r]||0;if(i!==o)return i-o}return 0},PJ=(t,e)=>{if(!t){Me.debug("Legacy cdk-insights metadata found (no version field)",{constructPath:e});return}TJ(t,ZT)<0&&Me.debug(`Metadata version ${t} is older than expected ${ZT}`,{constructPath:e,hint:"Consider re-running cdk synth with the latest cdk-insights aspect"})},YT=(t,e,s,n,r)=>{try{let i=t.artifacts??{},a=(i[n]||i[`${n}.template.json`])?.metadata??{},c={...e},u={...s},l=[];for(let[p,{githubUrl:f,docUrl:m}]of Object.entries(r))if(f||m){let g=u[p]||{};u[p]={...g,...f&&{__github:f},...m&&{__docs:m}}}for(let[p,f]of Object.entries(a)){for(let C of f)if(C.type===_J&&!(!C.data||typeof C.data!="object"))for(let[A,w]of Object.entries(C.data)){if(!A.startsWith(cl))continue;let N=A.slice(cl.length);if(!N)continue;let L=typeof w=="string"?w:"";l.push({constructPath:p,ruleId:N,reason:L})}let m=f.find(C=>C.type==="aws:cdk:logicalId"&&typeof C.data=="string");if(!m)continue;let g=m.data,h=p.startsWith("/")?p.slice(1):p;c[h]=g;let y=qT(f);y.length>0&&(u[g]={...u[g],__appliedMixins:y});let b=f.find(C=>C.type==="aws:cdk:info"&&typeof C.data=="string"&&VT(C.data));if(b)try{let C=JSON.parse(b.data.slice(cl.length)),{friendlyName:A,constructType:w,description:N,stackId:L,sourceLocation:R,parentPath:H,childCount:B,tags:S,version:U,logicalId:k,constructHierarchy:K,serviceCategory:x,dependencies:v,sensitiveProperties:Y,usesDefaults:J,l2ConstructType:X,l2ConstructId:re,createdBy:pe,rootSourceLocation:Ae,searchHint:we}=C;PJ(U,p);let ue={...u[g]};A&&(ue.__friendlyName=A),w&&(ue.__constructType=w),N&&(ue.__description=N),L&&(ue.__stackId=n),R&&(ue.__sourceLocation=R),H&&(ue.__parentPath=H),B!==void 0&&(ue.__childCount=B),S&&Object.keys(S).length>0&&(ue.__tags=S),U&&(ue.__metadataVersion=U),k&&(ue.__logicalId=k),K?.length>0&&(ue.__constructHierarchy=K),x&&(ue.__serviceCategory=x),v?.length>0&&(ue.__dependencies=v),Y?.length>0&&(ue.__sensitiveProperties=Y),J!==void 0&&(ue.__usesDefaults=J),X&&(ue.__l2ConstructType=X),re&&(ue.__l2ConstructId=re),pe&&(ue.__createdBy=pe),Ae&&(ue.__rootSourceLocation=Ae),we&&(ue.__searchHint=we),u[g]=ue}catch(C){Me.warn(`Failed to parse cdk-insights metadata for ${p}:`,{error:C})}}let d={};for(let[p,f]of Object.entries(a)){let m=f.find(N=>N.type==="aws:cdk:logicalId"&&typeof N.data=="string");if(!m)continue;let g=m.data,h=[],y=f.find(N=>N.type==="aws:cdk:info"&&typeof N.data=="string"&&VT(N.data));if(y)try{let N=JSON.parse(y.data.slice(cl.length));Array.isArray(N.issues)&&(h=N.issues.map(L=>({resourceId:L.resourceId,issue:L.issue,recommendation:L.recommendation,severity:L.severity,wafPillar:L.wafPillar,foundBy:"cdkInsights",constructPath:p,stackId:u[g]?.__stackId,constructType:u[g]?.__constructType,githubUrl:s[g]?.__github,docUrl:s[g]?.__docs})))}catch(N){Me.warn(`Failed to parse cdk-insights metadata for ${p}:`,{error:N})}let b=f.filter(N=>(N.type==="aws:cdk:error"||N.type==="aws:cdk:warning")&&typeof N.data=="string"&&NT(N.data)).map(N=>{let L=N.data,R=BT(L),H=ol(N.type,R);return{resourceId:g,issue:L,recommendation:void 0,severity:H,wafPillar:al(R),foundBy:"cdkNag",constructPath:p,ruleId:R,stackId:u[g]?.__stackId,constructType:u[g]?.__constructType,githubUrl:s[g]?.__github,docUrl:Vb(R)||s[g]?.__docs}}),C=[];for(let N of f)if(N.type==="aws:cdk:info"&&typeof N.data=="string"&&FJ(N.data))try{let L=JSON.parse(N.data.slice(Yb.length)),R=L.level==="Error"?"aws:cdk:error":"aws:cdk:warning",H=ol(R,L.ruleId);C.push({resourceId:g,issue:`${L.ruleId}${L.findingId?`[${L.findingId}]`:""}: ${L.ruleInfo}`,recommendation:L.ruleExplanation,severity:H,wafPillar:al(L.ruleId),foundBy:"cdkNag",constructPath:p,ruleId:L.ruleId,stackId:u[g]?.__stackId,constructType:u[g]?.__constructType,githubUrl:s[g]?.__github,docUrl:Vb(L.ruleId)||s[g]?.__docs})}catch(L){Me.warn(`Failed to parse cdk-insights nag finding for ${p}:`,{error:L})}let A=[...b,...C],w=u[g];d[g]={resourceId:g,friendlyName:w?.__friendlyName||g,cdkPath:p,locationHint:p,type:s[g]?.Type,isGenerated:!1,constructType:w?.__constructType,parentPath:w?.__parentPath,childCount:w?.__childCount,tags:w?.__tags,sourceLocation:w?.__sourceLocation,logicalId:g,constructHierarchy:w?.__constructHierarchy,serviceCategory:w?.__serviceCategory,dependencies:w?.__dependencies,sensitiveProperties:w?.__sensitiveProperties,usesDefaults:w?.__usesDefaults,l2ConstructType:w?.__l2ConstructType,l2ConstructId:w?.__l2ConstructId,createdBy:w?.__createdBy,rootSourceLocation:w?.__rootSourceLocation,searchHint:w?.__searchHint,appliedMixins:w?.__appliedMixins,sources:{cdkInsights:{issues:h},cdkNag:{issues:A}}}}if(Object.keys(d).length===0)for(let p of Object.keys(u))d[p]={resourceId:p,friendlyName:p,cdkPath:p,isGenerated:!1,sources:{cdkInsights:{issues:[]},cdkNag:{issues:[]}}};return{pathToLogicalId:c,unifiedResourceMap:u,resourceIdMetadata:r,recommendationMap:d,acknowledgements:l}}catch(i){return Me.error("\u26A0\uFE0F Failed to parse manifest.json for logical ID mappings:",{error:i}),Me.warn("Unknown error in parseManifestMetadata",{error:i}),{pathToLogicalId:e,unifiedResourceMap:s,resourceIdMetadata:r,recommendationMap:{},acknowledgements:[]}}}});function LJ(t){let e=tm.join(t,"manifest.json");if(!Kr.existsSync(e))return{};let s=JSON.parse(Kr.readFileSync(e,"utf8")),n={};for(let r of Object.values(s.artifacts)){if(r.type!=="cdk:asset-manifest")continue;let i=r.properties.file,o=tm.join(t,i);if(!Kr.existsSync(o))continue;let a=JSON.parse(Kr.readFileSync(o,"utf8"));for(let[c,u]of Object.entries(a.files||{}))n[c]=u.displayName}return n}function QT(t){let e={},s={},n={},r={},i=LJ(t),o=Kr.readdirSync(t).filter(a=>a.endsWith(".template.json"));for(let a of o){let c=a.replace(/\.template\.json$/,""),u=JSON.parse(Kr.readFileSync(tm.join(t,a),"utf8"));e[c]=u;for(let[l,d]of Object.entries(u.Resources||{})){if(new Set(["CDKMetadata","BootstrapVersion","CheckBootstrapVersion"]).has(l)||d.Type?.startsWith("AWS::CDK::")||d.Type==="AWS::SSM::Parameter")continue;let f={...d,displayName:l},m=f.Metadata??{};typeof m["aws:cdk:path"]=="string"&&(s[m["aws:cdk:path"]]=l);let g=m["aws:asset:path"],h=typeof g=="string"?g.replace(/^asset\./,""):void 0;if(h&&i[h])f.displayName=i[h];else if(typeof m["aws:cdk:path"]=="string"){let y=m["aws:cdk:path"].split("/"),b=y[y.length-1],C=b==="Resource"&&y.length>1?y[y.length-2]:b;f.displayName=C}n[l]=f,r[l]=f.displayName??l}}return{stacks:e,pathToLogicalId:s,unifiedResourceMap:n,displayNameMap:r,assetSourcePaths:Object.fromEntries(Object.entries(n).filter(([,a])=>a.Metadata?.["aws:asset:path"]).map(([a,c])=>[a,c.Metadata["aws:asset:path"]]))}}var Kr,tm,XT=D(()=>{"use strict";Kr=oe(require("node:fs")),tm=oe(require("node:path"))});var OJ,MJ,BJ,NJ,$J,eP,tP=D(()=>{"use strict";OJ=["cdk-nag","cdk-monitoring-constructs","cdk-watchful","@cdk-cosmos/","@aws-cdk-containers/","@aws-prototyping-sdk/"],MJ=t=>t.startsWith("aws-cdk-lib.aws_")||t.startsWith("aws-cdk-lib.core.")||t.startsWith("aws-cdk-lib/aws-")||/^@aws-cdk\/aws[-_]/.test(t)||/^@aws-cdk\/core/.test(t),BJ=t=>t.startsWith("@aws-solutions-constructs/"),NJ=t=>OJ.some(e=>t.startsWith(e)||t.startsWith(`${e}.`)),$J=t=>{let e=t.split(".");return e[e.length-1]??""},eP=t=>!t||typeof t!="string"?"unknown":$J(t).startsWith("Cfn")?"L1":BJ(t)?"L3-aws-solutions":NJ(t)?"L3-third-party":MJ(t)?"L2":"L3-custom"});var sP,nP=D(()=>{"use strict";sP=t=>{let e="https://github.com/aws/aws-cdk/blob/main/packages",s="https://docs.aws.amazon.com/cdk/api/v2/docs",n=t.split(".");if(n.length<3)return{githubUrl:null,docUrl:null,constructName:null};let[,r,...i]=n,o=`${e}/aws-cdk-lib/${r}/lib/${i.join("/")}.ts`,a=`${s}/${t}.html`;return{githubUrl:o,docUrl:a,constructName:i[0]}}});var sm,rP,iP=D(()=>{"use strict";sm=oe(require("node:fs"));tP();nP();rP=(t,e)=>{let s=`${t}/tree.json`;if(!sm.existsSync(s))return{pathToLogicalId:e,resourceIdMetadata:{}};let n=JSON.parse(sm.readFileSync(s,"utf-8")),i=(n.tree?.children?Object.values(n.tree.children):[n]).map(d=>({node:d,parentPath:""})),o=[];for(;i.length;){let d=i.pop();if(!d)continue;let{node:p,parentPath:f}=d,m=f?`${f}/${p.id}`:p.id,g=m.replace(/^\/+/,""),h=e[g],y=p.constructInfo?.fqn,b=p.attributes?.["aws:cdk:cloudformation:props"],C=b&&typeof b.description=="string"?b.description:void 0;if(o.push({logicalId:h,path:m,fqn:y,description:C}),p.children)for(let A of Object.values(p.children))i.push({node:A,parentPath:m})}let a={},c={},u={},l=d=>(c[d]||(c[d]={githubUrl:"",docUrl:"",constructName:"",constructLevel:"unknown"}),c[d]);for(let{logicalId:d,path:p,fqn:f,description:m}of o)if(d){if(a[p]=d,f){let g=l(d);g.fqn=f,g.constructLevel=eP(f);let{githubUrl:h,docUrl:y,constructName:b}=sP(f);h&&(g.githubUrl=h),y&&(g.docUrl=y,b&&(g.constructName=b))}m&&(u[d]=m)}return{pathToLogicalId:{...e,...a},resourceIdMetadata:c,autoGeneratedDescriptions:u}}});var oP,aP,cP,WJ,Ic,Vr,jJ,UJ,HJ,GJ,uP,Jb=D(()=>{"use strict";oP=oe(require("node:fs")),aP=oe(require("node:path")),cP="cdk-insights",WJ="policy-validation-report.json",Ic=t=>typeof t=="object"&&t!==null&&!Array.isArray(t),Vr=t=>typeof t=="string"?t:void 0,jJ=t=>{if(!Ic(t))return;let e={};for(let[s,n]of Object.entries(t))typeof n=="string"&&(e[s]=n);return Object.keys(e).length>0?e:void 0},UJ=t=>{if(!Ic(t))return;let e=t.locations,s=Array.isArray(e)?e.filter(o=>typeof o=="string"):[],n=Vr(t.resourceLogicalId),r=Vr(t.constructPath),i=Vr(t.templatePath);if(!(!n&&!r))return{...n?{resourceLogicalId:n}:{},...r?{constructPath:r}:{},...i?{templatePath:i}:{},locations:s}},HJ=(t,e)=>{if(!Ic(e))return[];let s=Vr(e.ruleName),n=Vr(e.description);if(!s||!n)return[];let r=Array.isArray(e.violatingConstructs)?e.violatingConstructs:null,i=Array.isArray(e.violatingResources)?e.violatingResources:null,o=r??i??[],a=Vr(e.severity),c=Vr(e.fix),u=jJ(e.ruleMetadata),l=[];for(let d of o){let p=UJ(d);p&&l.push({pluginName:t,ruleName:s,description:n,...a?{severity:a}:{},...c?{fix:c}:{},...u?{ruleMetadata:u}:{},resource:p})}return l},GJ=t=>{if(!Ic(t))return[];let e=Ic(t.summary)?t.summary:void 0,s=Vr(e?.pluginName)??Vr(t.pluginName)??"unknown",n=t.violations;return Array.isArray(n)?n.flatMap(r=>HJ(s,r)):[]},uP=(t={})=>{let e=t.cdkOutDir??"cdk.out",s=t.filename??WJ,n=t.warn??(c=>console.warn(c)),r=aP.join(e,s),i;try{i=oP.readFileSync(r,"utf-8")}catch(c){return c?.code==="ENOENT"?[]:(n(`cdk-insights: could not read ${r}: ${c.message}`),[])}let o;try{o=JSON.parse(i)}catch(c){return n(`cdk-insights: ${r} is not valid JSON: ${c.message}`),[]}if(!Ic(o))return[];let a=o.pluginReports;return Array.isArray(a)?a.flatMap(GJ):[]}});var nm,rm,Qb=D(()=>{"use strict";rl();OT();WT();HT();Xf();zT();JT();XT();iP();Jb();$b();nm="cdk.out",rm=t=>{let e=yT({stackName:t,extractInlineNagFindings:$T}),s=Rc(nm),{context:n}=UT(),{stacks:r,pathToLogicalId:i,unifiedResourceMap:o,assetSourcePaths:a}=QT(nm),{pathToLogicalId:c,resourceIdMetadata:u,autoGeneratedDescriptions:l}=rP(nm,i),d={...i,...c},p=GT(o,l),f=t?r[t]?{[t]:r[t]}:{}:r,m={},g=Object.fromEntries(Object.entries(f).map(([C,A])=>{let{recommendationMap:w,unifiedResourceMap:N,acknowledgements:L}=YT(s,d,p,C,u);m[C]=L;let R={...p,...N};for(let[S,U]of Object.entries(A.Resources??{})){let k=R[S]?.__appliedMixins;k&&k.length>0&&(U.__appliedMixins=k)}let H=Object.fromEntries(Object.keys(A.Resources??{}).map(S=>[S,w[S]??{resourceId:S,friendlyName:d[S]??S,cdkPath:S,isGenerated:!1,sources:{cdkInsights:{issues:[]},cdkNag:{issues:[]}}}])),B=LT(H,d,R,A,u);return[C,B]})),{version:h,supportsBoxTraces:y}=qr(),b=uP({cdkOutDir:nm});return{stacks:f,inlineFindings:e,pathToLogicalId:d,recommendationMapPerStack:g,assetSourcePaths:a,acknowledgementsPerStack:m,cdkVersion:h,supportsBoxTraces:y,cdkContext:n,resourceIdMetadata:u,validationReportFindings:b}}});var kc,zJ,qJ,ta,im,lP=D(()=>{"use strict";kc=(t,e)=>{let s=[];if(t==null)return s;if(typeof t=="string"){let n=t.matchAll(/\$\{([^.}]+)(?:\.[^}]+)?\}/g);for(let r of n){let i=r[1];e.has(i)&&s.push(i)}return s}if(Array.isArray(t)){for(let n of t)s.push(...kc(n,e));return s}if(typeof t=="object"){let n=t;if("Ref"in n&&typeof n.Ref=="string"&&e.has(n.Ref)&&s.push(n.Ref),"Fn::GetAtt"in n){let r=n["Fn::GetAtt"];if(Array.isArray(r)&&typeof r[0]=="string")e.has(r[0])&&s.push(r[0]);else if(typeof r=="string"){let i=r.split(".")[0];e.has(i)&&s.push(i)}}if("Fn::Sub"in n){let r=n["Fn::Sub"];Array.isArray(r)?(s.push(...kc(r[0],e)),r[1]&&typeof r[1]=="object"&&s.push(...kc(r[1],e))):s.push(...kc(r,e))}for(let[r,i]of Object.entries(n))["Ref","Fn::GetAtt","Fn::Sub"].includes(r)||s.push(...kc(i,e))}return s},zJ=t=>t.DependsOn?Array.isArray(t.DependsOn)?t.DependsOn:[t.DependsOn]:[],qJ=(t,e)=>{if(e.length===0)return;let s=new Set(e.map(i=>i.type.split("::")[2]||i.type)),n=Array.from(s).slice(0,3),r=t.split("::")[2]||t;if(t.includes("SecurityGroup"))return`Security group attached to: ${n.join(", ")}`;if(t.includes("IAM::Role"))return`IAM role assumed by: ${n.join(", ")}`;if(t.includes("VPC")||t.includes("Subnet"))return`Network hosting: ${n.join(", ")}`;if(t.includes("KMS::Key"))return`Encryption key used by: ${n.join(", ")}`;if(t.includes("S3::Bucket")){if(n.some(i=>i.includes("Lambda")))return"S3 bucket accessed by Lambda functions";if(n.some(i=>i.includes("CloudFront")))return"S3 bucket serving as CloudFront origin"}if(t.includes("DynamoDB::Table")&&n.some(i=>i.includes("Lambda")))return"DynamoDB table accessed by Lambda functions";if(e.length>0)return`Referenced by ${e.length} resource${e.length>1?"s":""}: ${n.join(", ")}`},ta=t=>{let e=new Set(Object.keys(t)),s={};for(let n of e)s[n]={dependencies:[],dependents:[]};for(let[n,r]of Object.entries(t)){let i=zJ(r),o=kc(r.Properties,e),a=[...new Set([...i,...o])];s[n].dependencies=a;for(let c of a)s[c]&&s[c].dependents.push(n)}for(let[n,r]of Object.entries(t)){let i=s[n],o=i.dependents.map(a=>({id:a,type:t[a]?.Type||"Unknown"}));i.usageDescription=qJ(r.Type,o)}return s},im=(t,e,s)=>{let n=e[t];if(!n)return{dependencies:[],dependents:[]};let r=n.dependencies.map(o=>{let a=s[o]?.Type?.split("::")[2]||o;return`${o} (${a})`}),i=n.dependents.map(o=>{let a=s[o]?.Type?.split("::")[2]||o;return`${o} (${a})`});return{dependencies:r,dependents:i,usageDescription:n.usageDescription}}});var om=D(()=>{"use strict";lP()});var KJ,VJ,ZJ,am,Xb=D(()=>{"use strict";om();KJ=(t,e,s)=>{let n={},r=new Set(["AWS::RDS::DBInstance","AWS::RDS::DBCluster","AWS::ElastiCache::CacheCluster","AWS::ElastiCache::ReplicationGroup","AWS::Redshift::Cluster","AWS::OpenSearchService::Domain","AWS::Elasticsearch::Domain","AWS::ECS::Service"]),i=new Set(Object.entries(t).filter(([,o])=>r.has(o.Type)).map(([o])=>o));for(let[o,a]of Object.entries(t)){if(a.Type!=="AWS::Lambda::Function")continue;let c=a.Properties||{},u=!!(c.VpcConfig&&(c.VpcConfig.SubnetIds||c.VpcConfig.SecurityGroupIds)),l=e[o];if(!l)continue;if(l.dependencies.some(p=>i.has(p))&&!u){n[o]||(n[o]={issues:[]});let p=l.dependencies.filter(f=>i.has(f));n[o].issues.push(s(o,`Lambda function references VPC resources (${p.join(", ")}) but is not VPC-enabled`,"Configure VpcConfig with appropriate SubnetIds and SecurityGroupIds to allow the Lambda function to connect to VPC resources. Without VPC configuration, the function cannot reach private resources like RDS databases.","HIGH","Reliability",a.Metadata?.["aws:cdk:path"]||o,"cdkInsights"))}}return n},VJ=(t,e)=>{let s={},n=new Map;for(let[r,i]of Object.entries(t)){if(i.Type!=="AWS::S3::Bucket")continue;let o=i.Properties||{},a=!!(o.BucketEncryption||o.ServerSideEncryptionConfiguration);n.set(r,a)}for(let[r,i]of Object.entries(t)){if(i.Type!=="AWS::S3::Bucket")continue;let a=(i.Properties||{}).ReplicationConfiguration;if(!a)continue;let c=n.get(r),u=a.Rules;if(!(!u||!Array.isArray(u)))for(let l of u){if(l.Status!=="Enabled")continue;let d=l.Destination;if(!d||!d.Bucket)continue;let f=d.EncryptionConfiguration;c&&!f&&(s[r]||(s[r]={issues:[]}),s[r].issues.push(e(r,"S3 replication configured without encryption configuration for replicated objects","Specify EncryptionConfiguration in the replication rule to ensure replicated objects maintain encryption. Use ReplicaKmsKeyID to specify the KMS key for encrypting replicated objects in the destination bucket.","MEDIUM","Security",i.Metadata?.["aws:cdk:path"]||r,"cdkInsights")))}}return s},ZJ=(t,e,s)=>{let n={},r=new Set([80,443,8080,8443]);for(let[i,o]of Object.entries(t)){if(o.Type!=="AWS::EC2::SecurityGroup")continue;let c=(o.Properties||{}).SecurityGroupIngress||[],u=e[i];if(!(u&&u.dependents.length>0))continue;let d=[];for(let p of c){let f=p.CidrIp,m=p.CidrIpv6,g=p.FromPort,h=p.ToPort;if(!(f==="0.0.0.0/0"||m==="::/0")||g===void 0)continue;let b=h!==void 0&&h!==g,C=!r.has(g);(b||C)&&d.push(g)}if(d.length>0){n[i]||(n[i]={issues:[]});let p=u.dependents.map(f=>t[f]?.Type?.split("::")[2]||"Unknown").join(", ");n[i].issues.push(s(i,`Security group used by ${p} has public access on non-standard ports: ${d.join(", ")}`,"Restrict ingress rules to specific CIDR blocks or reference other security groups instead of allowing 0.0.0.0/0 on non-standard ports. Consider using a bastion host or VPN for administrative access.","HIGH","Security",o.Metadata?.["aws:cdk:path"]||i,"cdkInsights"))}}return n},am=(t,e)=>{let s=t.Resources||{},n=ta(s),r={},i=[KJ(s,n,e),VJ(s,e),ZJ(s,n,e)];for(let o of i)for(let[a,c]of Object.entries(o))r[a]||(r[a]={issues:[]}),r[a].issues.push(...c.issues);return r}});var YJ,JJ,QJ,XJ,eQ,cm,eS=D(()=>{"use strict";om();YJ=t=>{let e=[],s=Object.values(t).map(R=>R.Type),n={};for(let R of s)n[R]=(n[R]||0)+1;let r=s.some(R=>R==="AWS::Lambda::Function"),i=s.some(R=>R==="AWS::ApiGateway::RestApi"||R==="AWS::ApiGatewayV2::Api"),o=s.some(R=>R==="AWS::DynamoDB::Table"),a=s.some(R=>R==="AWS::S3::Bucket");r&&(o||a)&&!s.some(R=>R.includes("ECS")||R.includes("EC2::Instance"))&&e.push("serverless");let c=s.some(R=>R==="AWS::ECS::Service"||R==="AWS::ECS::TaskDefinition"||R==="AWS::ECS::Cluster"),u=s.some(R=>R.startsWith("AWS::EKS::"));(c||u)&&e.push("container-based");let l=s.some(R=>R.startsWith("AWS::Events::")),d=s.some(R=>R==="AWS::SNS::Topic"),p=s.some(R=>R==="AWS::SQS::Queue"),f=s.some(R=>R.startsWith("AWS::Kinesis::")),m=s.some(R=>R.startsWith("AWS::StepFunctions::"));(l||d||p||f||m)&&r&&e.push("event-driven"),i&&e.push("api-gateway");let g=s.some(R=>R.startsWith("AWS::Glue::")),h=s.some(R=>R.startsWith("AWS::Athena::")),y=s.some(R=>R.startsWith("AWS::EMR::"));(f||g||h||y)&&e.push("data-processing");let b=s.some(R=>R==="AWS::CloudFront::Distribution");a&&b&&!r&&!c&&e.push("static-website");let C=n["AWS::Lambda::Function"]||0,A=n["AWS::ECS::Service"]||0;(C>=3||A>=2)&&e.push("microservices");let w=s.some(R=>R==="AWS::EC2::Instance"),N=s.some(R=>R==="AWS::RDS::DBInstance"||R==="AWS::RDS::DBCluster"),L=s.some(R=>R==="AWS::ElasticLoadBalancingV2::LoadBalancer");return w&&(N||L)&&e.push("traditional"),e},JJ=(t,e)=>{let s={},n=Object.values(t).map(l=>l.Type),r=n.some(l=>l==="AWS::CloudWatch::Alarm"),i=n.some(l=>l==="AWS::Lambda::Function"),o=n.some(l=>l==="AWS::ECS::Service"),a=n.some(l=>l==="AWS::RDS::DBInstance"||l==="AWS::RDS::DBCluster");(i||o||a)&&!r&&(s["Stack Architecture"]={issues:[e("Stack Architecture","No CloudWatch Alarms defined for critical resources","Add CloudWatch Alarms to monitor key metrics like Lambda errors, ECS task failures, or RDS connections. Consider using CDK's built-in alarm methods or aws-cdk-lib/aws-cloudwatch.","MEDIUM","Operational Excellence","Stack Architecture","cdkInsights")]});let c=n.some(l=>l==="AWS::XRay::Group"||l==="AWS::XRay::SamplingRule");return n.filter(l=>l==="AWS::Lambda::Function").length>=3&&!c&&(s["Stack Architecture"]||(s["Stack Architecture"]={issues:[]}),s["Stack Architecture"].issues.push(e("Stack Architecture","Multiple Lambda functions without X-Ray tracing configuration","Enable X-Ray tracing for your Lambda functions to gain visibility into distributed request flows and identify performance bottlenecks. Set tracing: lambda.Tracing.ACTIVE on your functions.","LOW","Operational Excellence","Stack Architecture","cdkInsights"))),s},QJ=(t,e)=>{let s={},n=Object.values(t).map(p=>p.Type),r=n.some(p=>p==="AWS::ApiGateway::RestApi"||p==="AWS::ApiGatewayV2::Api"),i=n.some(p=>p==="AWS::ElasticLoadBalancingV2::LoadBalancer"),o=n.some(p=>p==="AWS::CloudFront::Distribution"),a=n.some(p=>p==="AWS::WAFv2::WebACL"||p==="AWS::WAF::WebACL");(r||i||o)&&!a&&(s["Stack Architecture"]||(s["Stack Architecture"]={issues:[]}),s["Stack Architecture"].issues.push(e("Stack Architecture","Public-facing resources without WAF protection","Consider adding AWS WAF to protect your API Gateway, ALB, or CloudFront distribution from common web exploits. WAF can help prevent SQL injection, XSS, and rate-limit malicious traffic.","MEDIUM","Security","Stack Architecture","cdkInsights")));let c=n.some(p=>p==="AWS::SecretsManager::Secret"),u=n.some(p=>p==="AWS::SSM::Parameter"),l=n.some(p=>p==="AWS::RDS::DBInstance"||p==="AWS::RDS::DBCluster"),d=!1;for(let[p,f]of Object.entries(t))if(f.Type==="AWS::Lambda::Function"){let m=f.Properties?.Environment?.Variables;if(m){let g=["PASSWORD","SECRET","API_KEY","TOKEN","CREDENTIAL"];for(let h of Object.keys(m))if(g.some(y=>h.toUpperCase().includes(y))){let y=m[h];if(typeof y=="string"&&!y.startsWith("{{")){d=!0;break}}}}return l&&!c&&!u&&(s["Stack Architecture"]||(s["Stack Architecture"]={issues:[]}),s["Stack Architecture"].issues.push(e("Stack Architecture","RDS database without Secrets Manager for credential rotation","Use AWS Secrets Manager to store and automatically rotate database credentials. This improves security by eliminating hardcoded passwords and enabling automatic credential rotation.","HIGH","Security","Stack Architecture","cdkInsights"))),s},XJ=(t,e)=>{let s={},n=Object.values(t).filter(u=>u.Type==="AWS::EC2::NatGateway").length;n>=3&&(s["Stack Architecture"]||(s["Stack Architecture"]={issues:[]}),s["Stack Architecture"].issues.push(e("Stack Architecture",`${n} NAT Gateways detected - potential cost optimization`,"Multiple NAT Gateways can be expensive ($32/month each + data processing). Consider if all are necessary, or explore alternatives like NAT instances for dev environments, or VPC endpoints for AWS services.","MEDIUM","Cost Optimization","Stack Architecture","cdkInsights")));let r=n>0,i=Object.values(t).some(u=>u.Type==="AWS::EC2::VPCEndpoint"),o=Object.values(t).some(u=>{if(u.Type!=="AWS::Lambda::Function")return!1;let l=u.Properties?.VpcConfig;return l?.SubnetIds||l?.SecurityGroupIds}),a=Object.values(t).some(u=>u.Type==="AWS::S3::Bucket"),c=Object.values(t).some(u=>u.Type==="AWS::DynamoDB::Table");return o&&r&&!i&&(a||c)&&(s["Stack Architecture"]||(s["Stack Architecture"]={issues:[]}),s["Stack Architecture"].issues.push(e("Stack Architecture","VPC Lambda functions accessing AWS services through NAT Gateway","Consider using VPC Endpoints (Gateway endpoints for S3/DynamoDB are free) instead of routing AWS service traffic through NAT Gateway. This reduces costs and improves latency.","LOW","Cost Optimization","Stack Architecture","cdkInsights"))),s},eQ=(t,e,s)=>{let n={};for(let[r,i]of Object.entries(e)){let o=t[r];if(!o)continue;let a=i.dependents.length;if(a>=5){let c=o.Type.split("::")[2]||o.Type;n["Stack Architecture"]||(n["Stack Architecture"]={issues:[]}),n["Stack Architecture"].issues.push(s("Stack Architecture",`${c} (${r}) is a potential single point of failure with ${a} dependent resources`,"Consider adding redundancy or failover mechanisms for this critical resource. For databases, consider Multi-AZ. For queues, consider dead-letter queues. For Lambda, ensure proper error handling.","MEDIUM","Reliability","Stack Architecture","cdkInsights"))}}for(let[r,i]of Object.entries(t)){if(i.Type!=="AWS::DynamoDB::Table")continue;if(i.Properties?.PointInTimeRecoverySpecification?.PointInTimeRecoveryEnabled!==!0){let a=e[r];a&&a.dependents.length>=3&&(n["Stack Architecture"]||(n["Stack Architecture"]={issues:[]}),n["Stack Architecture"].issues.push(s("Stack Architecture",`Critical DynamoDB table ${r} has ${a.dependents.length} dependents but no point-in-time recovery`,"Enable Point-in-Time Recovery (PITR) for critical DynamoDB tables used by multiple resources. This provides continuous backups with 35-day retention.","HIGH","Reliability","Stack Architecture","cdkInsights")))}}return n},cm=(t,e)=>{let s=t.Resources||{};if(Object.keys(s).length<3)return{};let r=ta(s),i=YJ(s),o={},a=[JJ(s,e),QJ(s,e),XJ(s,e),eQ(s,r,e)];for(let c of a)for(let[u,l]of Object.entries(c))o[u]||(o[u]={issues:[]}),o[u].issues.push(...l.issues);return o}});function dP(){let t;try{t=require.resolve("@aws-solutions-constructs/core/package.json")}catch{return[]}let e=(0,ul.dirname)((0,ul.dirname)(t));return(0,um.readdirSync)(e).filter(s=>s!=="core"&&s.startsWith("aws-")&&(0,um.statSync)((0,ul.join)(e,s)).isDirectory())}var um,ul,pP=D(()=>{"use strict";um=require("node:fs"),ul=require("node:path")});var fP,mP=D(()=>{"use strict";fP={"aws-apigateway-dynamodb":{className:"ApiGatewayToDynamoDB",packageName:"aws-apigateway-dynamodb",friendlyName:"Api Gateway To Dynamo DB",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-apigateway-dynamodb/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-apigateway-dynamodb",requiredResourceTypes:["AWS::DynamoDB::Table","AWS::Logs::LogGroup","AWS::ApiGateway::RestApi","AWS::ApiGateway::Deployment","AWS::ApiGateway::Stage","AWS::ApiGateway::Resource","AWS::ApiGateway::Method","AWS::ApiGateway::UsagePlan","AWS::IAM::Role","AWS::ApiGateway::Account","AWS::IAM::Policy"]},"aws-apigateway-kinesisstreams":{className:"ApiGatewayToKinesisStreams",packageName:"aws-apigateway-kinesisstreams",friendlyName:"Api Gateway To Kinesis Streams",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-apigateway-kinesisstreams/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-apigateway-kinesisstreams",requiredResourceTypes:["AWS::Logs::LogGroup","AWS::ApiGateway::RestApi","AWS::ApiGateway::Deployment","AWS::ApiGateway::Stage","AWS::ApiGateway::Resource","AWS::ApiGateway::Method","AWS::ApiGateway::UsagePlan","AWS::ApiGateway::RequestValidator","AWS::ApiGateway::Model","AWS::IAM::Role","AWS::ApiGateway::Account","AWS::IAM::Policy","AWS::CloudWatch::Alarm","AWS::Kinesis::Stream"]},"aws-apigateway-lambda":{className:"ApiGatewayToLambda",packageName:"aws-apigateway-lambda",friendlyName:"Api Gateway To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-apigateway-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-apigateway-lambda",requiredResourceTypes:["AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function","AWS::Logs::LogGroup","AWS::ApiGateway::RestApi","AWS::ApiGateway::Deployment","AWS::ApiGateway::Stage","AWS::ApiGateway::Resource","AWS::Lambda::Permission","AWS::ApiGateway::Method","AWS::ApiGateway::UsagePlan","AWS::ApiGateway::Account"]},"aws-apigateway-sqs":{className:"ApiGatewayToSqs",packageName:"aws-apigateway-sqs",friendlyName:"Api Gateway To Sqs",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-apigateway-sqs/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-apigateway-sqs",requiredResourceTypes:["AWS::SQS::Queue","AWS::SQS::QueuePolicy","AWS::Logs::LogGroup","AWS::ApiGateway::RestApi","AWS::ApiGateway::Deployment","AWS::ApiGateway::Stage","AWS::ApiGateway::Method","AWS::ApiGateway::UsagePlan","AWS::IAM::Role","AWS::ApiGateway::Account","AWS::IAM::Policy"]},"aws-apigatewayv2websocket-sqs":{className:"ApiGatewayV2WebSocketToSqs",packageName:"aws-apigatewayv2websocket-sqs",friendlyName:"Api Gateway V2 Web Socket To Sqs",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-apigatewayv2websocket-sqs/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-apigatewayv2websocket-sqs",requiredResourceTypes:["AWS::SQS::Queue","AWS::SQS::QueuePolicy","AWS::IAM::Role","AWS::IAM::Policy","AWS::ApiGatewayV2::Api","AWS::ApiGatewayV2::Integration","AWS::ApiGatewayV2::Route","AWS::ApiGatewayV2::Stage","AWS::Logs::LogGroup"]},"aws-cloudfront-apigateway-lambda":{className:"CloudFrontToApiGatewayToLambda",packageName:"aws-cloudfront-apigateway-lambda",friendlyName:"Cloud Front To Api Gateway To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-cloudfront-apigateway-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-cloudfront-apigateway-lambda",requiredResourceTypes:["AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function","AWS::Logs::LogGroup","AWS::ApiGateway::RestApi","AWS::ApiGateway::Deployment","AWS::ApiGateway::Stage","AWS::ApiGateway::Resource","AWS::Lambda::Permission","AWS::ApiGateway::Method","AWS::ApiGateway::UsagePlan","AWS::ApiGateway::Account","AWS::CloudFront::Function","AWS::S3::Bucket","AWS::S3::BucketPolicy","AWS::CloudFront::Distribution"]},"aws-cloudfront-mediastore":{className:"CloudFrontToMediaStore",packageName:"aws-cloudfront-mediastore",friendlyName:"Cloud Front To Media Store",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-cloudfront-mediastore/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-cloudfront-mediastore",requiredResourceTypes:["AWS::CloudFront::CloudFrontOriginAccessIdentity","AWS::MediaStore::Container","AWS::S3::Bucket","AWS::S3::BucketPolicy","AWS::CloudFront::OriginRequestPolicy","AWS::CloudFront::Function","AWS::CloudFront::Distribution"]},"aws-cloudfront-oai-s3":{className:"CloudFrontToOaiToS3",packageName:"aws-cloudfront-oai-s3",friendlyName:"Cloud Front To Oai To S3",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-cloudfront-oai-s3/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-cloudfront-oai-s3",requiredResourceTypes:["AWS::S3::Bucket","AWS::S3::BucketPolicy","AWS::CloudFront::Function","AWS::CloudFront::CloudFrontOriginAccessIdentity","AWS::CloudFront::Distribution"]},"aws-cloudfront-s3":{className:"CloudFrontToS3",packageName:"aws-cloudfront-s3",friendlyName:"Cloud Front To S3",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-cloudfront-s3/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-cloudfront-s3",requiredResourceTypes:["AWS::S3::Bucket","AWS::S3::BucketPolicy","AWS::CloudFront::Function","AWS::CloudFront::OriginAccessControl","AWS::CloudFront::Distribution"]},"aws-cognito-apigateway-lambda":{className:"CognitoToApiGatewayToLambda",packageName:"aws-cognito-apigateway-lambda",friendlyName:"Cognito To Api Gateway To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-cognito-apigateway-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-cognito-apigateway-lambda",requiredResourceTypes:["AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function","AWS::Logs::LogGroup","AWS::ApiGateway::RestApi","AWS::ApiGateway::Deployment","AWS::ApiGateway::Stage","AWS::ApiGateway::Resource","AWS::Lambda::Permission","AWS::ApiGateway::Method","AWS::ApiGateway::UsagePlan","AWS::ApiGateway::Account","AWS::Cognito::UserPool","AWS::Cognito::UserPoolClient","AWS::ApiGateway::Authorizer"]},"aws-dynamodbstreams-lambda":{className:"DynamoDBStreamsToLambda",packageName:"aws-dynamodbstreams-lambda",friendlyName:"Dynamo DBStreams To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-dynamodbstreams-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-dynamodbstreams-lambda",requiredResourceTypes:["AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function","AWS::Lambda::EventSourceMapping","AWS::DynamoDB::Table","AWS::SQS::Queue","AWS::SQS::QueuePolicy"]},"aws-kinesisfirehose-s3":{className:"KinesisFirehoseToS3",packageName:"aws-kinesisfirehose-s3",friendlyName:"Kinesis Firehose To S3",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-kinesisfirehose-s3/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-kinesisfirehose-s3",requiredResourceTypes:["AWS::S3::Bucket","AWS::S3::BucketPolicy","AWS::Logs::LogGroup","AWS::Logs::LogStream","AWS::IAM::Role","AWS::IAM::Policy","AWS::KinesisFirehose::DeliveryStream"]},"aws-kinesisstreams-kinesisfirehose-s3":{className:"KinesisStreamsToKinesisFirehoseToS3",packageName:"aws-kinesisstreams-kinesisfirehose-s3",friendlyName:"Kinesis Streams To Kinesis Firehose To S3",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-kinesisstreams-kinesisfirehose-s3/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-kinesisstreams-kinesisfirehose-s3",requiredResourceTypes:["AWS::Kinesis::Stream","AWS::S3::Bucket","AWS::S3::BucketPolicy","AWS::Logs::LogGroup","AWS::Logs::LogStream","AWS::IAM::Role","AWS::IAM::Policy","AWS::KinesisFirehose::DeliveryStream","AWS::CloudWatch::Alarm"]},"aws-s3-lambda":{className:"S3ToLambda",packageName:"aws-s3-lambda",friendlyName:"S3 To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-s3-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-s3-lambda",requiredResourceTypes:["AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function","AWS::S3::Bucket","AWS::S3::BucketPolicy","Custom::S3BucketNotifications","AWS::Lambda::Permission"]},"aws-s3-sns":{className:"S3ToSns",packageName:"aws-s3-sns",friendlyName:"S3 To Sns",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-s3-sns/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-s3-sns",requiredResourceTypes:["AWS::S3::Bucket","AWS::S3::BucketPolicy","Custom::S3BucketNotifications","AWS::KMS::Key","AWS::SNS::Topic","AWS::SNS::TopicPolicy","AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function"]},"aws-s3-sqs":{className:"S3ToSqs",packageName:"aws-s3-sqs",friendlyName:"S3 To Sqs",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-s3-sqs/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-s3-sqs",requiredResourceTypes:["AWS::S3::Bucket","AWS::S3::BucketPolicy","Custom::S3BucketNotifications","AWS::SQS::Queue","AWS::SQS::QueuePolicy","AWS::KMS::Key","AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function"]},"aws-sns-lambda":{className:"SnsToLambda",packageName:"aws-sns-lambda",friendlyName:"Sns To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-sns-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-sns-lambda",requiredResourceTypes:["AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function","AWS::Lambda::Permission","AWS::SNS::Subscription","AWS::SNS::Topic","AWS::SNS::TopicPolicy"]},"aws-sns-sqs":{className:"SnsToSqs",packageName:"aws-sns-sqs",friendlyName:"Sns To Sqs",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-sns-sqs/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-sns-sqs",requiredResourceTypes:["AWS::SNS::Topic","AWS::SNS::TopicPolicy","AWS::SQS::Queue","AWS::SQS::QueuePolicy","AWS::SNS::Subscription","AWS::KMS::Key"]},"aws-eventbridge-kinesisstreams":{className:"EventbridgeToKinesisStreams",packageName:"aws-eventbridge-kinesisstreams",friendlyName:"EventBridge To Kinesis Streams",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-eventbridge-kinesisstreams/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-eventbridge-kinesisstreams",requiredResourceTypes:["AWS::Events::Rule","AWS::Kinesis::Stream"]},"aws-eventbridge-sns":{className:"EventbridgeToSns",packageName:"aws-eventbridge-sns",friendlyName:"EventBridge To SNS",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-eventbridge-sns/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-eventbridge-sns",requiredResourceTypes:["AWS::Events::Rule","AWS::SNS::Topic"]},"aws-eventbridge-sqs":{className:"EventbridgeToSqs",packageName:"aws-eventbridge-sqs",friendlyName:"EventBridge To SQS",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-eventbridge-sqs/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-eventbridge-sqs",requiredResourceTypes:["AWS::Events::Rule","AWS::SQS::Queue"]},"aws-eventbridge-stepfunctions":{className:"EventbridgeToStepfunctions",packageName:"aws-eventbridge-stepfunctions",friendlyName:"EventBridge To StepFunctions",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-eventbridge-stepfunctions/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-eventbridge-stepfunctions",requiredResourceTypes:["AWS::Events::Rule","AWS::StepFunctions::StateMachine"]},"aws-alb-fargate":{className:"AlbToFargate",packageName:"aws-alb-fargate",friendlyName:"ALB To Fargate",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-alb-fargate/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-alb-fargate",requiredResourceTypes:["AWS::ElasticLoadBalancingV2::LoadBalancer","AWS::ElasticLoadBalancingV2::Listener","AWS::ECS::Cluster","AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::IAM::Role","AWS::Logs::LogGroup"]},"aws-alb-lambda":{className:"AlbToLambda",packageName:"aws-alb-lambda",friendlyName:"ALB To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-alb-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-alb-lambda",requiredResourceTypes:["AWS::ElasticLoadBalancingV2::LoadBalancer","AWS::ElasticLoadBalancingV2::Listener","AWS::Lambda::Function","AWS::IAM::Role","AWS::Logs::LogGroup"]},"aws-apigateway-iot":{className:"ApiGatewayToIot",packageName:"aws-apigateway-iot",friendlyName:"API Gateway To IoT",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-apigateway-iot/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-apigateway-iot",requiredResourceTypes:["AWS::ApiGateway::RestApi","AWS::ApiGateway::Resource","AWS::ApiGateway::Method","AWS::IoT::TopicRule"]},"aws-apigateway-sagemakerendpoint":{className:"ApiGatewayToSagemakerendpoint",packageName:"aws-apigateway-sagemakerendpoint",friendlyName:"API Gateway To SageMaker Endpoint",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-apigateway-sagemakerendpoint/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-apigateway-sagemakerendpoint",requiredResourceTypes:["AWS::ApiGateway::RestApi","AWS::ApiGateway::Integration","AWS::SageMaker::Endpoint"]},"aws-cloudfront-apigateway":{className:"CloudFrontToApiGateway",packageName:"aws-cloudfront-apigateway",friendlyName:"CloudFront To API Gateway",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-cloudfront-apigateway/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-cloudfront-apigateway",requiredResourceTypes:["AWS::CloudFront::Distribution","AWS::ApiGateway::RestApi","AWS::ApiGateway::Method"]},"aws-dynamodbstreams-lambda-elasticsearch-kibana":{className:"DynamoDBStreamsToLambdaElasticsearchKibana",packageName:"aws-dynamodbstreams-lambda-elasticsearch-kibana",friendlyName:"DynamoDB Streams To Lambda Elasticsearch Kibana",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-dynamodbstreams-lambda-elasticsearch-kibana/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-dynamodbstreams-lambda-elasticsearch-kibana",requiredResourceTypes:["AWS::DynamoDB::Stream","AWS::Lambda::Function","AWS::Elasticsearch::Domain","AWS::IAM::Role","AWS::Logs::LogGroup"]},"aws-dynamodbstreams-pipes-stepfunctions":{className:"DynamoDBStreamsToPipesStepfunctions",packageName:"aws-dynamodbstreams-pipes-stepfunctions",friendlyName:"DynamoDB Streams To Pipes StepFunctions",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-dynamodbstreams-pipes-stepfunctions/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-dynamodbstreams-pipes-stepfunctions",requiredResourceTypes:["AWS::DynamoDB::Stream","AWS::StepFunctions::StateMachine"]},"aws-eventbridge-kinesisfirehose-s3":{className:"EventbridgeToKinesisfirehoseToS3",packageName:"aws-eventbridge-kinesisfirehose-s3",friendlyName:"EventBridge To Kinesis Firehose To S3",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-eventbridge-kinesisfirehose-s3/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-eventbridge-kinesisfirehose-s3",requiredResourceTypes:["AWS::Events::Rule","AWS::KinesisFirehose::DeliveryStream","AWS::S3::Bucket"]},"aws-eventbridge-lambda":{className:"EventbridgeToLambda",packageName:"aws-eventbridge-lambda",friendlyName:"EventBridge To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-eventbridge-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-eventbridge-lambda",requiredResourceTypes:["AWS::Events::Rule","AWS::Lambda::Function","AWS::IAM::Role"]},"aws-fargate-dynamodb":{className:"FargateToDynamodb",packageName:"aws-fargate-dynamodb",friendlyName:"Fargate To DynamoDB",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-dynamodb/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-dynamodb",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::DynamoDB::Table"]},"aws-fargate-eventbridge":{className:"FargateToEventbridge",packageName:"aws-fargate-eventbridge",friendlyName:"Fargate To EventBridge",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-eventbridge/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-eventbridge",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::Events::Rule"]},"aws-fargate-kinesisfirehose":{className:"FargateToKinesisfirehose",packageName:"aws-fargate-kinesisfirehose",friendlyName:"Fargate To Kinesis Firehose",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-kinesisfirehose/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-kinesisfirehose",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::KinesisFirehose::DeliveryStream"]},"aws-fargate-kinesisstreams":{className:"FargateToKinesisstreams",packageName:"aws-fargate-kinesisstreams",friendlyName:"Fargate To Kinesis Streams",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-kinesisstreams/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-kinesisstreams",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::Kinesis::Stream"]},"aws-fargate-opensearch":{className:"FargateToOpensearch",packageName:"aws-fargate-opensearch",friendlyName:"Fargate To OpenSearch",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-opensearch/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-opensearch",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::OpenSearch::Domain"]},"aws-fargate-s3":{className:"FargateToS3",packageName:"aws-fargate-s3",friendlyName:"Fargate To S3",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-s3/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-s3",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::S3::Bucket"]},"aws-fargate-secretsmanager":{className:"FargateToSecretsmanager",packageName:"aws-fargate-secretsmanager",friendlyName:"Fargate To SecretsManager",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-secretsmanager/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-secretsmanager",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::SecretsManager::Secret"]},"aws-fargate-sns":{className:"FargateToSns",packageName:"aws-fargate-sns",friendlyName:"Fargate To SNS",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-sns/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-sns",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::SNS::Topic"]},"aws-fargate-sqs":{className:"FargateToSqs",packageName:"aws-fargate-sqs",friendlyName:"Fargate To SQS",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-sqs/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-sqs",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::SQS::Queue"]},"aws-fargate-ssmstringparameter":{className:"FargateToSsmstringparameter",packageName:"aws-fargate-ssmstringparameter",friendlyName:"Fargate To SSM String Parameter",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-ssmstringparameter/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-ssmstringparameter",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::SSM::StringParameter"]},"aws-fargate-stepfunctions":{className:"FargateToStepfunctions",packageName:"aws-fargate-stepfunctions",friendlyName:"Fargate To StepFunctions",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-stepfunctions/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-stepfunctions",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::StepFunctions::StateMachine"]},"aws-iot-kinesisfirehose-s3":{className:"IotToKinesisfirehoseToS3",packageName:"aws-iot-kinesisfirehose-s3",friendlyName:"IoT To Kinesis Firehose To S3",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-iot-kinesisfirehose-s3/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-iot-kinesisfirehose-s3",requiredResourceTypes:["AWS::IoT::TopicRule","AWS::KinesisFirehose::DeliveryStream","AWS::S3::Bucket"]},"aws-iot-kinesisstreams":{className:"IotToKinesisstreams",packageName:"aws-iot-kinesisstreams",friendlyName:"IoT To Kinesis Streams",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-iot-kinesisstreams/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-iot-kinesisstreams",requiredResourceTypes:["AWS::IoT::TopicRule","AWS::Kinesis::Stream"]},"aws-iot-lambda":{className:"IotToLambda",packageName:"aws-iot-lambda",friendlyName:"IoT To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-iot-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-iot-lambda",requiredResourceTypes:["AWS::IoT::TopicRule","AWS::Lambda::Function","AWS::IAM::Role"]}}});var hP,gP=D(()=>{"use strict";mP();hP=async t=>{let e={};for(let s of t)try{let n=await import(`@aws-solutions-constructs/${s}`),r=Object.keys(n).find(u=>/^[A-Z][a-zA-Z0-9]*To[A-Z][a-zA-Z0-9]*$/.test(u));if(!r)continue;let i=`https://docs.aws.amazon.com/solutions/latest/${s}/`,o=`https://github.com/awslabs/aws-solutions-constructs/tree/main/${s}`,c=fP[s]?.requiredResourceTypes||[];e[s]={className:r,packageName:s,friendlyName:r.replace(/([a-z0-9])([A-Z])/g,"$1 $2").trim(),documentationUrl:i,githubUrl:o,requiredResourceTypes:c}}catch{}return e}});var j,me=D(()=>{"use strict";j=(t,e)=>t.Metadata?.["aws:cdk:path"]??e});var yP,W,$,ee,T,xP,fe=D(()=>{"use strict";yP={LOW:0,MEDIUM:1,HIGH:2,CRITICAL:3},W=(t,e)=>t?.resourceIdMetadata?.[e]?.constructLevel,$=t=>t==="L3-aws-solutions"||t==="L3-third-party",ee=t=>{let e=yP[t]??0;return e<=0?"LOW":Object.entries(yP).find(([,s])=>s===e-1)?.[0]},T=(t,e,s)=>{if(!$(e))return t;let n=s?` Look for a \`${s}\` argument on the construct.`:"";return`${t} This resource is owned by an L3 pattern \u2014 fix via the pattern's props${n} rather than escape-hatching the underlying CFN resource.`},xP=(t,e)=>{let s=t?.cdkContext?.[e];return s===!0||s==="true"}});var bP,SP=D(()=>{"use strict";me();fe();bP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::CertificateManager::Certificate")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[];return i.Properties?.ValidationMethod==="EMAIL"&&l.push(e(r,"ACM certificate uses email validation instead of DNS validation.",T("Use DNS validation for automated certificate renewal. Email validation requires manual intervention for renewals.",o),c("LOW"),"Operational Excellence",u,"cdkInsights")),i.Properties?.CertificateTransparencyLoggingPreference==="DISABLED"&&l.push(e(r,"ACM certificate has certificate transparency logging disabled.",T("Enable certificate transparency logging for security monitoring and to detect misissued certificates.",o),c("LOW"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var vP,CP=D(()=>{"use strict";me();fe();vP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::ApiGateway::RestApi"&&!i.Properties?.EndpointConfiguration?.Types?.includes("PRIVATE")){let o=W(s,r),a=$(o);n[r]={issues:[e(r,"API Gateway is publicly accessible.",T("If this API is intentionally public, ignore this finding (or suppress it via .cdk-insights.json). For internal APIs, use PRIVATE endpoints to restrict access.",o,"endpointConfiguration / endpointTypes"),a?"LOW":"MEDIUM","Security",j(i,r),"cdkInsights")]}}return n},{})});var tQ,DP,AP=D(()=>{"use strict";me();fe();tQ=t=>typeof t=="string"&&t.toUpperCase()==="OPTIONS",DP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{let o=i.Type==="AWS::ApiGateway::Method",a=i.Type==="AWS::ApiGatewayV2::Route";if(!o&&!a)return n;let c=i.Properties??{},u=c.AuthorizationType;if(o&&tQ(c.HttpMethod)||!(u===void 0||u==="NONE"))return n;let d=j(i,r),p=W(s,r),f=$(p),m=o?"API Gateway Method has no authorization (AuthorizationType is NONE).":"API Gateway v2 Route has no authorization (AuthorizationType is NONE).";return n[r]={issues:[e(r,m,T("Set AuthorizationType to AWS_IAM, COGNITO_USER_POOLS, CUSTOM (REST), or JWT (HTTP API). Public-by-default endpoints expose backend Lambdas to anyone on the internet without authentication. If the route is intentionally public (e.g. a webhook receiver), prefer api-key + WAF rate limiting.",p,"methodOptions.authorizationType"),f?"MEDIUM":"HIGH","Security",d,"cdkInsights")]},n},{})});var wP,EP=D(()=>{"use strict";me();fe();wP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::AppSync::GraphQLApi")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[],d=i.Properties?.AuthenticationType;d==="API_KEY"&&l.push(e(r,"AppSync API uses API key authentication.",T("Consider using AWS_IAM, AMAZON_COGNITO_USER_POOLS, or OPENID_CONNECT for production workloads. API keys are best for development or public read-only access.",o),c("MEDIUM"),"Security",u,"cdkInsights"));let p=i.Properties?.AdditionalAuthenticationProviders;return d!=="AWS_IAM"&&(!p||p.length===0)&&l.push(e(r,"AppSync API does not have multiple authentication providers configured.",T("Consider adding AdditionalAuthenticationProviders for flexibility in authenticating different client types.",o),c("LOW"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var RP,IP=D(()=>{"use strict";me();fe();RP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::AppSync::GraphQLApi")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[],d=i.Properties?.LogConfig;return d?d.FieldLogLevel==="NONE"&&l.push(e(r,"AppSync API has field-level logging disabled.",T("Set FieldLogLevel to ERROR or ALL to capture GraphQL resolver execution details.",o),c("LOW"),"Operational Excellence",u,"cdkInsights")):l.push(e(r,"AppSync API does not have logging configured.",T("Enable LogConfig to capture request/response logs in CloudWatch for debugging and monitoring.",o),c("MEDIUM"),"Operational Excellence",u,"cdkInsights")),i.Properties?.XrayEnabled!==!0&&l.push(e(r,"AppSync API does not have X-Ray tracing enabled.",T("Enable XrayEnabled for distributed tracing and performance analysis.",o),c("LOW"),"Operational Excellence",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var kP,_P=D(()=>{"use strict";me();fe();kP=(t,e,s)=>{let n=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::AppSync::GraphQLApi"),r=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::WAFv2::WebACLAssociation"),i=new Set(r.map(([,o])=>{let a=o.Properties?.ResourceArn;return typeof a=="string"?a:a?.["Fn::GetAtt"]?.[0]?a["Fn::GetAtt"][0]:null}).filter(Boolean));return n.reduce((o,[a,c])=>{let u=j(c,a);if(!i.has(a)){let d=W(s,a),p=$(d),f=m=>p?ee(m):m;o[a]={issues:[e(a,"AppSync API does not have AWS WAF protection.",T("Associate a WAF WebACL to protect against common web exploits and control access to the API.",d),f("MEDIUM"),"Security",u,"cdkInsights")]}}return o},{})}});var FP,TP=D(()=>{"use strict";me();fe();FP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Backup::BackupPlan")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[],p=i.Properties?.BackupPlan?.BackupPlanRule||[];for(let f of p){(f.CopyActions||[]).length===0&&l.push(e(r,`Backup rule "${f.RuleName||"unnamed"}" does not have cross-region copy configured.`,T("Add CopyActions to replicate backups to another region for disaster recovery.",o),c("LOW"),"Reliability",u,"cdkInsights"));let g=f.Lifecycle;!g?.DeleteAfterDays&&!g?.MoveToColdStorageAfterDays&&l.push(e(r,`Backup rule "${f.RuleName||"unnamed"}" has no lifecycle configuration.`,T("Set DeleteAfterDays or MoveToColdStorageAfterDays to manage backup retention and costs.",o),c("LOW"),"Cost Optimization",u,"cdkInsights"))}return l.length>0&&(n[r]={issues:l}),n},{})});var PP,LP=D(()=>{"use strict";me();fe();PP=(t,e,s)=>{let n=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::Backup::BackupVault"),r=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::Backup::BackupVaultLock"),i=new Set(r.map(([,o])=>{let a=o.Properties?.BackupVaultName;return typeof a=="string"?a:typeof a=="object"&&a?.Ref?a.Ref:null}).filter(Boolean));return n.reduce((o,[a,c])=>{let u=W(s,a),l=$(u),d=b=>l?ee(b):b,p=j(c,a),f=[];c.Properties?.EncryptionKeyArn||f.push(e(a,"Backup vault uses default AWS-managed encryption key.",T("Specify a customer-managed KMS key using EncryptionKeyArn for additional control over encryption.",u),d("LOW"),"Security",p,"cdkInsights"));let g=c.Properties?.BackupVaultName,h=typeof g=="string"?g:typeof g=="object"?g?.Ref:void 0;return i.has(a)||h&&i.has(h)||f.push(e(a,"Backup vault does not have a vault lock configured.",T("Add a BackupVaultLock to enforce retention policies and prevent backup deletion for compliance requirements.",u),d("LOW"),"Security",p,"cdkInsights")),f.length>0&&(o[a]={issues:f}),o},{})}});var OP,MP=D(()=>{"use strict";me();fe();OP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::CloudFront::Distribution")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r);return i.Properties?.DistributionConfig?.DefaultCacheBehavior?.ViewerProtocolPolicy==="allow-all"&&(n[r]={issues:[e(r,"CloudFront distribution allows HTTP traffic (ViewerProtocolPolicy is allow-all).",T('Set ViewerProtocolPolicy to "https-only" or "redirect-to-https" to enforce HTTPS and protect data in transit.',o),c("HIGH"),"Security",u,"cdkInsights")]}),n},{})});var BP,NP=D(()=>{"use strict";me();fe();BP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::CloudFront::Distribution")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r);return i.Properties?.DistributionConfig?.Logging?.Bucket||(n[r]={issues:[e(r,"CloudFront distribution does not have access logging enabled.",T("Enable access logging to an S3 bucket to track viewer requests for security analysis, auditing, and troubleshooting.",o),c("MEDIUM"),"Security",u,"cdkInsights")]}),n},{})});var sQ,$P,WP=D(()=>{"use strict";me();fe();sQ=["SSLv3","TLSv1","TLSv1_2016","TLSv1.1_2016"],$P=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::CloudFront::Distribution")return n;let o=j(i,r),c=i.Properties?.DistributionConfig?.ViewerCertificate,u=c?.MinimumProtocolVersion;if(c?.CloudFrontDefaultCertificate)return n;let l=W(s,r),d=$(l),p=f=>d?ee(f):f;return u&&sQ.includes(u)&&(n[r]={issues:[e(r,`CloudFront distribution uses outdated TLS version (${u}).`,T("Use TLSv1.2_2021 or later for improved security. Older TLS versions have known vulnerabilities.",l),p("MEDIUM"),"Security",o,"cdkInsights")]}),n},{})});var jP,UP=D(()=>{"use strict";me();fe();jP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::CloudFront::Distribution")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);return i.Properties?.DistributionConfig?.WebACLId||(n[r]={issues:[e(r,"CloudFront distribution has no WAF WebACL associated.",T("Associate a WAF WebACL to protect against common web exploits, SQL injection, XSS, and DDoS attacks.",o),c("MEDIUM"),"Security",u,"cdkInsights")]}),n},{})});var HP,GP=D(()=>{"use strict";HP=(t,e)=>Object.entries(t.Resources||{}).some(([,n])=>n.Type==="AWS::CloudTrail::Trail")?{}:{Global:{issues:[e("Global","No CloudTrail Trail defined in this stack.","CloudTrail is most commonly configured at the AWS account or organization level (one Trail covers every stack). If account-level CloudTrail is already in place, suppress this rule. If not, add a CloudTrail Trail at the account level \u2014 defining one per stack is rarely the right shape.","LOW","Security","Global","cdkInsights")]}}});var zP,qP=D(()=>{"use strict";me();fe();zP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::CloudWatch::Alarm")return n;let o=W(s,r),a=$(o),c=g=>a?ee(g):g,u=j(i,r),l=[],d=i.Properties?.AlarmActions,p=i.Properties?.OKActions,f=i.Properties?.InsufficientDataActions;return(!d||d.length===0)&&l.push(e(r,"CloudWatch Alarm has no alarm actions configured.",T("Add AlarmActions (SNS topic, Lambda, etc.) to receive notifications when the alarm state changes to ALARM.",o),c("MEDIUM"),"Operational Excellence",u,"cdkInsights")),i.Properties?.TreatMissingData||l.push(e(r,"CloudWatch Alarm does not specify how to treat missing data.",T("Set TreatMissingData to define alarm behavior when data points are missing (missing, ignore, breaching, or notBreaching).",o),c("LOW"),"Operational Excellence",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var KP,VP=D(()=>{"use strict";me();fe();KP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Logs::LogGroup")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);return i.Properties?.KmsKeyId||(n[r]={issues:[e(r,"CloudWatch Log Group is not encrypted with a customer-managed KMS key.",T("Enable KMS encryption using KmsKeyId to protect sensitive log data at rest with customer-managed keys.",o),c("LOW"),"Security",u,"cdkInsights")]}),n},{})});var nQ,rQ,ZP,YP=D(()=>{"use strict";me();fe();nQ="@aws-cdk/aws-lambda:logRetentionDefaultsTo30Days",rQ=t=>/\/LogRetention[0-9A-Fa-f]*$/.test(t)||/LogRetention[0-9A-Fa-f]+$/.test(t),ZP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Logs::LogGroup")return n;let o=j(i,r),a=i.Properties?.RetentionInDays,c=W(s,r),u=$(c);return a!==void 0||xP(s,nQ)&&rQ(o||r)||(n[r]={issues:[e(r,"CloudWatch Log Group has no retention period set (logs retained indefinitely).",T("Set RetentionInDays to control storage costs. Consider 30-90 days for operational logs, longer for compliance requirements.",c,"logGroupProps.retention"),u?"LOW":"MEDIUM","Cost Optimization",o,"cdkInsights")]}),n},{})});var JP,QP=D(()=>{"use strict";me();fe();JP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Cognito::UserPool")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r),l=i.Properties?.MfaConfiguration;return(!l||l==="OFF")&&(n[r]={issues:[e(r,"Cognito User Pool has MFA disabled.",T("Enable MFA (OPTIONAL or ON) to add an extra layer of security for user authentication.",o),c("MEDIUM"),"Security",u,"cdkInsights")]}),n},{})});var XP,eL=D(()=>{"use strict";me();fe();XP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Cognito::UserPool")return n;let o=[],a=j(i,r),c=i.Properties?.PasswordPolicy,u=W(s,r),l=$(u),d=p=>l?ee(p):p;if(!c)o.push(e(r,"Cognito User Pool has no password policy configured.",T("Configure a strong password policy with minimum length, uppercase, lowercase, numbers, and symbols requirements.",u,"passwordPolicy"),d("HIGH"),"Security",a,"cdkInsights"));else{let p=c.MinimumLength||8;p<12&&o.push(e(r,`Cognito password policy has minimum length of ${p} characters.`,T("Set MinimumLength to at least 12 characters for stronger security against brute-force attacks.",u,"passwordPolicy.minLength"),d("MEDIUM"),"Security",a,"cdkInsights")),c.RequireSymbols===!1&&o.push(e(r,"Cognito password policy does not require symbols.",T("Enable RequireSymbols for stronger password complexity requirements.",u,"passwordPolicy.requireSymbols"),d("LOW"),"Security",a,"cdkInsights"))}return o.length>0&&(n[r]={issues:o}),n},{})});var tL,sL=D(()=>{"use strict";me();fe();tL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Cognito::UserPool")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r),l=i.Properties?.UserPoolAddOns?.AdvancedSecurityMode;return(!l||l==="OFF")&&(n[r]={issues:[e(r,"Cognito User Pool does not have advanced security features enabled.",T("Enable UserPoolAddOns with AdvancedSecurityMode set to AUDIT or ENFORCED to detect compromised credentials and block suspicious sign-ins.",o),c("LOW"),"Security",u,"cdkInsights")]}),n},{})});var nL,rL=D(()=>{"use strict";me();fe();nL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::DynamoDB::Table"||i.Properties?.SSESpecification?.SSEEnabled===!0)return n;let a=j(i,r),c=W(s,r),u=$(c);return n[r]={issues:[e(r,"DynamoDB Table is not configured with KMS encryption.",T("Set SSESpecification.SSEEnabled to true and provide a customer-managed KMSMasterKeyId. Without SSESpecification, DynamoDB encrypts with an AWS-owned key \u2014 adequate for general use but not for HIPAA / PCI-DSS workloads that require customer-controlled key rotation and audit.",c,"tableProps.encryption"),u?"LOW":"MEDIUM","Security",a,"cdkInsights")]},n},{})});var iL,oL=D(()=>{"use strict";me();fe();iL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::DynamoDB::Table"||i.Properties?.PointInTimeRecoverySpecification?.PointInTimeRecoveryEnabled===!0)return n;let a=j(i,r),c=W(s,r),u=$(c);return n[r]={issues:[e(r,"DynamoDB Table does not have Point-in-Time Recovery enabled.",T("Set PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled to true to enable continuous backups for the last 35 days. Required by HIPAA and SOC2 for data resilience.",c,"tableProps.pointInTimeRecoverySpecification"),u?"LOW":"MEDIUM","Reliability",a,"cdkInsights")]},n},{})});var aL,cL=D(()=>{"use strict";me();fe();aL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::DynamoDB::Table")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=i.Properties?.BillingMode,l=j(i,r);return(!u||u==="PROVISIONED")&&(n[r]={issues:[e(r,"DynamoDB table uses provisioned capacity without on-demand billing.",T("Consider using BillingMode: PAY_PER_REQUEST for automatic scaling and cost optimization, especially for unpredictable workloads. For predictable workloads, configure Application Auto Scaling.",o),c("MEDIUM"),"Cost Optimization",l,"cdkInsights")]}),n},{})});var uL,lL=D(()=>{"use strict";me();fe();uL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::DynamoDB::Table"&&!i.Properties?.StreamSpecification){let o=W(s,r),a=$(o),c=u=>a?ee(u):u;n[r]={issues:[e(r,"DynamoDB table does not have streams enabled.",T("Consider enabling DynamoDB Streams to capture item-level changes for analytics, auditing, event-driven architectures, and cross-region replication.",o),c("LOW"),"Operational Excellence",j(i,r),"cdkInsights")]}}return n},{})});var dL,pL=D(()=>{"use strict";me();fe();dL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EC2::Volume")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=[],l=j(i,r),d=i.Properties??{};return d.Encrypted!==!0&&u.push(e(r,"EBS Volume is not encrypted.",T("Enable encryption on EBS volumes to protect data at rest. Use the Encrypted property and optionally specify a KmsKeyId.",o),c("HIGH"),"Security",l,"cdkInsights")),d.VolumeType==="gp2"&&u.push(e(r,"EBS Volume uses gp2 storage type.",T("Consider migrating to gp3 for up to 20% cost savings with better baseline performance (3,000 IOPS and 125 MB/s throughput).",o),c("LOW"),"Cost Optimization",l,"cdkInsights")),u.length>0&&(n[r]={issues:u}),n},{})});var fL,mL=D(()=>{"use strict";me();fe();fL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EFS::FileSystem"||i.Properties?.Encrypted===!0)return n;let a=j(i,r),c=W(s,r),u=$(c);return n[r]={issues:[e(r,"EFS FileSystem is not encrypted at rest.",T("Set Encrypted to true and provide KmsKeyId for a customer-managed key. Encryption can only be enabled at filesystem creation; existing unencrypted filesystems require data migration to a new encrypted filesystem.",c,"fileSystemProps.encrypted"),u?"MEDIUM":"HIGH","Security",a,"cdkInsights")]},n},{})});var hL,gL,yL=D(()=>{"use strict";me();fe();hL=t=>Array.isArray(t)&&t.length>0,gL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::AutoScaling::AutoScalingGroup")return n;let o=i.Properties??{};if(!(hL(o.LoadBalancerNames)||hL(o.TargetGroupARNs))||o.HealthCheckType==="ELB")return n;let u=j(i,r),l=W(s,r),d=$(l);return n[r]={issues:[e(r,"AutoScalingGroup attached to a load balancer is not using ELB health checks.",T("Set HealthCheckType to ELB so unhealthy instances detected by the load balancer are recycled. EC2 health checks (the default) only catch instance-level failures, missing app-level outages the LB would otherwise detect.",l,"asgProps.healthCheckType"),d?"LOW":"MEDIUM","Reliability",u,"cdkInsights")]},n},{})});var xL,bL=D(()=>{"use strict";me();fe();xL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::AutoScaling::LaunchConfiguration"||i.Properties?.AssociatePublicIpAddress!==!0)return n;let o=j(i,r),a=W(s,r),c=$(a);return n[r]={issues:[e(r,"AutoScaling LaunchConfiguration sets AssociatePublicIpAddress=true.",T("Set AssociatePublicIpAddress to false. Instances launched from this configuration will get a public IP and be reachable from the internet directly; prefer placing them in private subnets behind an ALB / NLB.",a,"launchConfigProps.associatePublicIpAddress"),c?"MEDIUM":"HIGH","Security",o,"cdkInsights")]},n},{})});var SL,vL=D(()=>{"use strict";me();fe();SL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::EC2::Instance"&&i.Properties?.InstanceType?.toString().startsWith("t2")){let o=W(s,r),a=$(o),c=u=>a?ee(u):u;n[r]={issues:[e(r,"EC2 instance is using an older t2 instance. Consider upgrading to t3 for better performance and cost savings.",T("Upgrade to a t3 instance for improved performance, lower latency, and better cost efficiency.",o),c("MEDIUM"),"Cost Optimization",j(i,r),"cdkInsights")]}}return n},{})});var CL,DL=D(()=>{"use strict";me();fe();CL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::EC2::NatGateway"){let o=W(s,r),a=$(o),c=u=>a?ee(u):u;n[r]={issues:[e(r,"NAT Gateway detected. NAT Gateways incur hourly charges (~$0.045/hr) plus data processing fees (~$0.045/GB).",T("Consider alternatives like NAT instances for lower traffic, VPC endpoints for AWS services, or IPv6 egress-only internet gateways to reduce costs.",o),c("LOW"),"Cost Optimization",j(i,r),"cdkInsights")]}}return n},{})});var AL,wL=D(()=>{"use strict";me();fe();AL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EC2::Instance")return n;let o=i.Properties?.NetworkInterfaces;if(!Array.isArray(o)||o.length===0||!o.some(d=>d&&d.AssociatePublicIpAddress===!0))return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,"EC2 Instance has a network interface with public IP association (AssociatePublicIpAddress=true).",T("Set AssociatePublicIpAddress to false on the NetworkInterface, or remove the property and rely on subnet defaults. A public IP on the instance ENI makes it directly internet-reachable; prefer a NAT/ALB for outbound and inbound traffic.",u,"instanceProps.associatePublicIpAddress"),l?"MEDIUM":"HIGH","Security",c,"cdkInsights")]},n},{})});var iQ,oQ,aQ,EL,RL=D(()=>{"use strict";me();fe();iQ=[22,3389,3306,5432,1433,27017,6379],oQ=t=>t.CidrIp==="0.0.0.0/0"||t.CidrIpv6==="::/0",aQ=(t,e,s)=>e===void 0||s===void 0?!1:t>=e&&t<=s,EL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EC2::SecurityGroup")return n;let o=W(s,r),a=$(o),c=h=>a?ee(h):h,u=[],l=j(i,r),d=i.Properties?.SecurityGroupIngress||[],p=i.Properties?.SecurityGroupEgress||[],f=d.some(h=>h.CidrIp==="0.0.0.0/0"),m=d.some(h=>h.CidrIpv6==="::/0");f&&u.push(e(r,"Security Group allows unrestricted IPv4 ingress (0.0.0.0/0).",T("Restrict security group rules to specific IPs and ports.",o),c("HIGH"),"Security",l,"cdkInsights")),m&&u.push(e(r,"Security Group allows unrestricted IPv6 ingress (::/0).",T("Restrict security group rules to specific IPs and ports.",o),c("HIGH"),"Security",l,"cdkInsights"));for(let h of d)if(oQ(h)){for(let y of iQ)if(aQ(y,h.FromPort,h.ToPort)){u.push(e(r,`Security Group exposes port ${y} to the internet.`,T("Restrict access to management and database ports. Use bastion hosts, VPN, or AWS Systems Manager Session Manager instead.",o),c("CRITICAL"),"Security",l,"cdkInsights"));break}}return p.some(h=>h.CidrIp==="0.0.0.0/0")&&u.push(e(r,"Security Group allows unrestricted egress to 0.0.0.0/0.",T("Consider restricting egress rules to specific destinations for defense in depth.",o),c("LOW"),"Security",l,"cdkInsights")),d.length===0&&p.length===0&&u.push(e(r,"Security Group has no ingress or egress rules defined.",T("Review if this security group is in use. Empty security groups may indicate orphaned resources or misconfiguration.",o),c("LOW"),"Operational Excellence",l,"cdkInsights")),u.length>0&&(n[r]={issues:u}),n},{})});var IL,kL=D(()=>{"use strict";me();fe();IL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EC2::Subnet"||i.Properties?.MapPublicIpOnLaunch!==!0)return n;let o=j(i,r),a=W(s,r),c=$(a);return n[r]={issues:[e(r,"EC2 Subnet auto-assigns public IPs to launched instances (MapPublicIpOnLaunch=true).",T("Set MapPublicIpOnLaunch to false unless this is intentionally a public subnet. Instances should opt into a public IP at the ENI level rather than inheriting it from subnet defaults \u2014 keeps the blast radius small if a private workload accidentally lands here.",a,"subnetProps.mapPublicIpOnLaunch"),c?"LOW":"MEDIUM","Security",o,"cdkInsights")]},n},{})});var _L,FL=D(()=>{"use strict";me();fe();_L=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ECR::Repository")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);return i.Properties?.ImageTagMutability!=="IMMUTABLE"&&(n[r]={issues:[e(r,"ECR repository allows mutable image tags.",T("Set ImageTagMutability to IMMUTABLE to prevent image tags from being overwritten, ensuring deployment consistency.",o),c("MEDIUM"),"Security",u,"cdkInsights")]}),n},{})});var TL,PL=D(()=>{"use strict";me();fe();TL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ECR::Repository")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);return i.Properties?.LifecyclePolicy?.LifecyclePolicyText||(n[r]={issues:[e(r,"ECR repository does not have a lifecycle policy configured.",T("Add a lifecycle policy to automatically clean up old or untagged images and reduce storage costs.",o),c("MEDIUM"),"Cost Optimization",u,"cdkInsights")]}),n},{})});var LL,OL=D(()=>{"use strict";me();fe();LL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ECR::Repository")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[];return i.Properties?.ImageScanningConfiguration?.ScanOnPush!==!0&&l.push(e(r,"ECR repository does not have image scanning on push enabled.",T("Enable ScanOnPush in ImageScanningConfiguration to automatically scan images for vulnerabilities when pushed.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var ML,BL=D(()=>{"use strict";me();fe();ML=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ECS::TaskDefinition")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=[],l=j(i,r),d=i.Properties?.ContainerDefinitions||[];for(let p of d)p.LogConfiguration?.LogDriver||u.push(e(r,`ECS container "${p.Name||"unnamed"}" has no logging configuration.`,T("Configure LogConfiguration with awslogs driver to send container logs to CloudWatch for monitoring and debugging.",o),c("MEDIUM"),"Operational Excellence",l,"cdkInsights"));return u.length>0&&(n[r]={issues:u}),n},{})});var NL,$L=D(()=>{"use strict";me();fe();NL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ECS::Service")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=i.Properties?.ServiceConnectConfiguration;if(!u||u.Enabled!==!0||u.LogConfiguration?.LogDriver)return n;let d=j(i,r);return n[r]={issues:[e(r,"ECS Service Connect is enabled without an access log configuration.",T("Configure ServiceConnectConfiguration.LogConfiguration with a LogDriver (e.g. awslogs) to capture inter-service traffic metadata for audit, debugging, and incident response.",o),c("MEDIUM"),"Security",d,"cdkInsights")]},n},{})});var WL,jL=D(()=>{"use strict";me();fe();WL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ECS::TaskDefinition")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=[],l=j(i,r),d=i.Properties?.ContainerDefinitions||[];for(let p of d){let f=p.Memory||p.MemoryReservation,m=p.Cpu;!f&&!m&&u.push(e(r,`ECS container "${p.Name||"unnamed"}" has no CPU or memory limits defined.`,T("Define CPU and Memory limits to prevent runaway containers and ensure predictable resource allocation.",o),c("LOW"),"Reliability",l,"cdkInsights"))}return u.length>0&&(n[r]={issues:u}),n},{})});var cQ,UL,HL=D(()=>{"use strict";me();fe();cQ=/(^|_)(secret|password|passwd|pwd|credential|private_key|api_key|api_secret|auth_token|access_key|access_secret|bearer_token|jwt_secret|encryption_key|signing_key)(_|$)/i,UL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ECS::TaskDefinition")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=[],l=j(i,r),d=i.Properties?.ContainerDefinitions||[];for(let p of d){let f=p.Environment||[];for(let m of f)cQ.test(m.Name||"")&&u.push(e(r,`ECS task definition has sensitive environment variable "${m.Name}" in plaintext.`,T('Use AWS Secrets Manager or SSM Parameter Store with the "secrets" property instead of plaintext environment variables.',o),c("HIGH"),"Security",l,"cdkInsights"))}return u.length>0&&(n[r]={issues:u}),n},{})});var GL,zL=D(()=>{"use strict";me();fe();GL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EKS::Cluster")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[];return i.Properties?.EncryptionConfig?.some(f=>f.Resources?.includes("secrets"))||l.push(e(r,"EKS cluster does not have Kubernetes secrets encryption enabled.",T("Configure EncryptionConfig with a KMS key to encrypt secrets stored in etcd.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var qL,KL=D(()=>{"use strict";me();fe();qL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EKS::Cluster")return n;let o=W(s,r),a=$(o),c=h=>a?ee(h):h,u=j(i,r),l=[],p=i.Properties?.Logging?.ClusterLogging?.EnabledTypes||[],f=p.map(h=>h.Type).filter(h=>!!h),g=["api","audit","authenticator","controllerManager","scheduler"].filter(h=>!f.includes(h));return g.length>0&&l.push(e(r,`EKS cluster is missing control plane logging for: ${g.join(", ")}.`,T("Enable all control plane log types (api, audit, authenticator, controllerManager, scheduler) for comprehensive cluster monitoring.",o),c("MEDIUM"),"Operational Excellence",u,"cdkInsights")),p.length===0?(n[r]={issues:[e(r,"EKS cluster does not have any control plane logging enabled.",T("Enable control plane logging to CloudWatch for audit trails and troubleshooting Kubernetes API issues.",o),c("MEDIUM"),"Security",u,"cdkInsights")]},n):(l.length>0&&(n[r]={issues:l}),n)},{})});var VL,ZL=D(()=>{"use strict";me();fe();VL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EKS::Cluster")return n;let o=W(s,r),a=$(o),c=g=>a?ee(g):g,u=j(i,r),l=[],d=i.Properties?.ResourcesVpcConfig,p=d?.EndpointPublicAccess,f=d?.EndpointPrivateAccess,m=d?.PublicAccessCidrs;return p===!0&&f!==!0&&l.push(e(r,"EKS cluster has only public endpoint access enabled.",T("Enable EndpointPrivateAccess to allow communication between nodes and the API server within the VPC.",o),c("MEDIUM"),"Security",u,"cdkInsights")),p===!0&&(!m||m.length===0||m.includes("0.0.0.0/0"))&&l.push(e(r,"EKS cluster public endpoint is accessible from the internet (0.0.0.0/0).",T("Restrict PublicAccessCidrs to specific IP ranges that need to access the Kubernetes API.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var YL,JL=D(()=>{"use strict";me();fe();YL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ElasticLoadBalancingV2::LoadBalancer")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r);return(i.Properties?.LoadBalancerAttributes||[]).some(p=>p.Key==="deletion_protection.enabled"&&p.Value==="true")||(n[r]={issues:[e(r,"Load Balancer does not have deletion protection enabled.",T("Enable deletion protection to prevent accidental deletion of the load balancer in production environments.",o),c("MEDIUM"),"Reliability",u,"cdkInsights")]}),n},{})});var QL,XL=D(()=>{"use strict";me();fe();QL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ElasticLoadBalancingV2::Listener")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=i.Properties?.Protocol,d=i.Properties?.Port;return l==="HTTP"&&d!==80?n[r]={issues:[e(r,`Load Balancer listener uses HTTP protocol on port ${d}.`,T("Use HTTPS protocol with a valid SSL certificate to encrypt traffic in transit.",o),c("HIGH"),"Security",u,"cdkInsights")]}:l==="HTTP"&&d===80&&((i.Properties?.DefaultActions||[]).some(m=>m.Type==="redirect"&&m.RedirectConfig?.Protocol==="HTTPS")||(n[r]={issues:[e(r,"Load Balancer HTTP listener on port 80 does not redirect to HTTPS.",T("Configure the HTTP listener to redirect to HTTPS to ensure encrypted traffic.",o),c("MEDIUM"),"Security",u,"cdkInsights")]})),n},{})});var e6,t6=D(()=>{"use strict";me();fe();e6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ElasticLoadBalancingV2::LoadBalancer")return n;let o=j(i,r);if(!(i.Properties?.LoadBalancerAttributes||[]).some(u=>u.Key==="access_logs.s3.enabled"&&u.Value==="true")){let u=W(s,r),l=$(u),d=p=>l?ee(p):p;n[r]={issues:[e(r,"Load Balancer does not have access logging enabled.",T("Enable access logging to S3 for security analysis, auditing, and troubleshooting of traffic patterns.",u,"accessLogs / logAccessLogs"),d("MEDIUM"),"Security",o,"cdkInsights")]}}return n},{})});var uQ,s6,n6=D(()=>{"use strict";me();fe();uQ=["ELBSecurityPolicy-2016-08","ELBSecurityPolicy-TLS-1-0-2015-04","ELBSecurityPolicy-TLS-1-1-2017-01","ELBSecurityPolicy-2015-05"],s6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ElasticLoadBalancingV2::Listener")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=i.Properties?.Protocol,d=i.Properties?.SslPolicy;return l!=="HTTPS"&&l!=="TLS"||d&&uQ.includes(d)&&(n[r]={issues:[e(r,`Load Balancer listener uses outdated security policy (${d}).`,T("Use ELBSecurityPolicy-TLS13-1-2-2021-06 or later for TLS 1.3 support, or at minimum ELBSecurityPolicy-TLS-1-2-2017-01 for TLS 1.2.",o),c("MEDIUM"),"Security",u,"cdkInsights")]}),n},{})});var r6,i6=D(()=>{"use strict";me();fe();r6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ElastiCache::ReplicationGroup")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[],d=i.Properties?.AuthToken,p=i.Properties?.TransitEncryptionEnabled;return!d&&p===!0&&l.push(e(r,"ElastiCache Redis cluster has transit encryption but no AUTH token configured.",T("Set AuthToken to require authentication for Redis connections, providing an additional security layer.",o),c("MEDIUM"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var o6,a6=D(()=>{"use strict";me();fe();o6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ElastiCache::ReplicationGroup"&&i.Type!=="AWS::ElastiCache::CacheCluster")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[];return i.Properties?.AtRestEncryptionEnabled!==!0&&l.push(e(r,"ElastiCache cluster does not have encryption at rest enabled.",T("Enable AtRestEncryptionEnabled to protect cached data at rest using AWS-managed or customer-managed keys.",o),c("HIGH"),"Security",u,"cdkInsights")),i.Properties?.TransitEncryptionEnabled!==!0&&l.push(e(r,"ElastiCache cluster does not have encryption in transit enabled.",T("Enable TransitEncryptionEnabled to protect data during transfer between clients and the cache.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var c6,u6=D(()=>{"use strict";me();fe();c6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ElastiCache::ReplicationGroup")return n;let o=W(s,r),a=$(o),c=g=>a?ee(g):g,u=j(i,r),l=[],d=i.Properties?.AutomaticFailoverEnabled,p=i.Properties?.NumNodeGroups||1,f=i.Properties?.ReplicasPerNodeGroup||0;return d!==!0&&(p>1||f>0)&&l.push(e(r,"ElastiCache replication group has replicas but automatic failover is not enabled.",T("Enable AutomaticFailoverEnabled to automatically promote a replica to primary if the primary node fails.",o),c("MEDIUM"),"Reliability",u,"cdkInsights")),i.Properties?.MultiAZEnabled!==!0&&d===!0&&l.push(e(r,"ElastiCache replication group has automatic failover but Multi-AZ is not enabled.",T("Enable MultiAZEnabled to distribute nodes across availability zones for higher availability.",o),c("MEDIUM"),"Reliability",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var l6,d6=D(()=>{"use strict";me();fe();l6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Events::Rule")return n;let o=j(i,r),a=W(s,r),c=$(a),u=d=>c?ee(d):d,l=[];return i.Properties?.State!=="ENABLED"&&l.push(e(r,"EventBridge rule is disabled or not explicitly enabled.",T("Ensure the EventBridge rule State is set to ENABLED to trigger events as expected.",a,"enabled / state"),u("MEDIUM"),"Operational Excellence",o,"cdkInsights")),(!i.Properties?.Targets||Array.isArray(i.Properties.Targets)&&i.Properties.Targets.length===0)&&l.push(e(r,"EventBridge rule has no targets configured. Events matching this rule will be silently dropped.",T("Add at least one target (Lambda, SQS, SNS, Step Functions, etc.) to process matched events. Without targets, the rule matches events but takes no action.",a,"targets"),u("HIGH"),"Reliability",o,"cdkInsights")),l.length>0&&(n[r]={issues:[...n[r]?.issues||[],...l]}),n},{})});var lQ,dQ,p6,f6=D(()=>{"use strict";me();fe();lQ=t=>{if(t==="*")return!0;if(t&&typeof t=="object"){let e=t.AWS;if(e==="*"||Array.isArray(e)&&e.includes("*"))return!0}return!1},dQ=t=>t.Condition!==void 0&&t.Condition!==null&&typeof t.Condition=="object"&&Object.keys(t.Condition).length>0,p6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Events::EventBusPolicy")return n;let o=i.Properties??{},a=[];o.Principal!==void 0&&a.push({Effect:"Allow",Principal:o.Principal,Condition:o.Condition});let c=o.Statement;if(c&&(Array.isArray(c.Statement)?a.push(...c.Statement):a.push(c)),a.filter(f=>(f.Effect===void 0||f.Effect==="Allow")&&lQ(f.Principal)&&!dQ(f)).length===0)return n;let l=j(i,r),d=W(s,r),p=$(d);return n[r]={issues:[e(r,"EventBridge EventBusPolicy grants access to wildcard Principal without a Condition.",T("Replace wildcard Principal with a specific AWS account / org ID, or add a Condition (e.g. aws:PrincipalOrgID) to scope cross-account access. Wildcard principals on an event bus mean any AWS account can publish events to your bus.",d,"eventBusPolicyProps.statement"),p?"HIGH":"CRITICAL","Security",l,"cdkInsights")]},n},{})});var m6,h6=D(()=>{"use strict";me();fe();m6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Glue::Connection")return n;let o=W(s,r),a=$(o),c=m=>a?ee(m):m,u=j(i,r),l=[],d=i.Properties?.ConnectionInput,p=d?.ConnectionType,f=d?.PhysicalConnectionRequirements;if(p==="JDBC"){f?.SubnetId||l.push(e(r,"Glue JDBC connection does not specify a VPC subnet.",T("Configure PhysicalConnectionRequirements with SubnetId and SecurityGroupIdList for network isolation.",o),c("MEDIUM"),"Security",u,"cdkInsights"));let g=d?.ConnectionProperties?.JDBC_CONNECTION_URL||"";typeof g=="string"&&!g.includes("ssl=true")&&!g.includes("useSSL=true")&&l.push(e(r,"Glue JDBC connection URL may not enforce SSL.",T("Ensure the JDBC connection URL includes SSL parameters to encrypt data in transit.",o),c("LOW"),"Security",u,"cdkInsights"))}return l.length>0&&(n[r]={issues:l}),n},{})});var g6,y6=D(()=>{"use strict";me();fe();g6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Glue::Job")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=[];return i.Properties?.SecurityConfiguration||l.push(e(r,"Glue job does not have a security configuration specified.",T("Create and attach a SecurityConfiguration to enable encryption for job bookmarks, S3 data, and CloudWatch logs.",o),c("MEDIUM"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var x6,b6,pQ,S6,v6=D(()=>{"use strict";me();fe();x6=/^\d{12}$/,b6=/arn:aws:iam::(\d{12}):root/,pQ=t=>{if(!t)return[];if(typeof t=="string"){if(x6.test(t))return[t];let e=t.match(b6);return e?[e[1]]:[]}return typeof t=="object"&&t.AWS?(Array.isArray(t.AWS)?t.AWS:[t.AWS]).flatMap(s=>{if(x6.test(s))return[s];let n=s.match(b6);return n?[n[1]]:[]}):[]},S6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::IAM::Role")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=[],l=j(i,r),d=i.Properties?.AssumeRolePolicyDocument;if(d?.Statement){for(let p of d.Statement)if(p.Effect==="Allow"){let f=pQ(p.Principal);for(let m of f)u.push(e(r,`IAM Role allows cross-account trust from account ${m}.`,T("Verify this cross-account trust relationship is intentional and the external account is trusted. Consider adding conditions to restrict access.",o),c("MEDIUM"),"Security",l,"cdkInsights"))}}return u.length>0&&(n[r]={issues:u}),n},{})});var C6,D6=D(()=>{"use strict";fe();C6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::IAM::Policy"&&i.Type!=="AWS::IAM::Role")return n;let o=i.Properties?.Policies,a=[];if(Array.isArray(o))for(let f of o)f?.PolicyDocument&&a.push(f.PolicyDocument);let c=i.Properties?.PolicyDocument;c&&a.push(c);let u=W(s,r),l=$(u),d=f=>l?ee(f):f,p=[];for(let f of a){if(!f?.Statement)continue;let m=f.Statement;for(let g of m)if(g.Effect==="Allow"){let h=g.Action,y=g.Resource,b=h==="*"||Array.isArray(h)&&h.includes("*"),C=y==="*"||Array.isArray(y)&&y.includes("*");b&&C?p.push(e(r,"IAM policy allows all actions (*) on all resources (*). This grants administrative access.",T("Restrict both actions and resources to follow the principle of least privilege.",u,"rolePolicy / inlinePolicies"),d("CRITICAL"),"Security",r,"cdkInsights")):b?p.push(e(r,"IAM policy allows all actions (*). This is overly permissive.",T("Specify only the required actions instead of using wildcards.",u,"rolePolicy / inlinePolicies"),d("CRITICAL"),"Security",r,"cdkInsights")):C&&p.push(e(r,"IAM policy allows actions on all resources (*). This is overly permissive.",T("Restrict resources to specific ARNs instead of using wildcards.",u,"rolePolicy / inlinePolicies"),d("HIGH"),"Security",r,"cdkInsights"))}}return p.length>0&&(n[r]={issues:p}),n},{})});var fQ,mQ,A6,w6=D(()=>{"use strict";me();fe();fQ=[/\/ServiceRole\/Resource$/,/\/Role\/Resource$/,/\/InstanceRole\/Resource$/,/CustomResourceProvider\/Role$/],mQ=t=>fQ.some(e=>e.test(t)),A6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::IAM::Role")return n;let o=W(s,r),a=$(o),c=l=>a?ee(l):l,u=j(i,r);return mQ(u)||i.Properties?.PermissionsBoundary||(n[r]={issues:[e(r,"IAM Role has no permission boundary configured.",T("Consider using permission boundaries to limit the maximum permissions for delegated access and prevent privilege escalation.",o),c("LOW"),"Security",u,"cdkInsights")]}),n},{})});var E6,R6,I6=D(()=>{"use strict";me();fe();E6=t=>Array.isArray(t)&&t.length>0,R6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::IAM::User")return n;let o=i.Properties??{},a=E6(o.Policies),c=E6(o.ManagedPolicyArns);if(!a&&!c)return n;let u=j(i,r),l=W(s,r),d=$(l),p=[];return a&&p.push(e(r,"IAM User has inline policies attached.",T("Move policies to an IAM Group and add the user to the group, or attach via a Role assumed by the user. CIS AWS Foundations 1.15 requires users to inherit permissions through groups.",l,"userProps.attachInlinePolicy"),d?"LOW":"MEDIUM","Security",u,"cdkInsights")),c&&p.push(e(r,"IAM User has managed policies attached directly.",T("Attach managed policies to an IAM Group and add the user to that group. Direct attachment violates CIS AWS Foundations 1.15 (users must inherit permissions through groups).",l,"userProps.managedPolicies"),d?"LOW":"MEDIUM","Security",u,"cdkInsights")),n[r]={issues:p},n},{})});var k6,_6=D(()=>{"use strict";me();fe();k6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Kinesis::Stream")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=[],d=i.Properties?.StreamEncryption;return(!d?.EncryptionType||d.EncryptionType==="NONE")&&l.push(e(r,"Kinesis Data Stream does not have server-side encryption enabled.",T("Enable StreamEncryption with EncryptionType KMS to protect data at rest.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var F6,T6=D(()=>{"use strict";me();fe();F6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Kinesis::Stream")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[];i.Properties?.RetentionPeriodHours===24&&l.push(e(r,"Kinesis Data Stream uses minimum retention period (24 hours).",T("Consider increasing RetentionPeriodHours for applications that need to replay or reprocess data during failures.",o),c("LOW"),"Reliability",u,"cdkInsights"));let p=i.Properties?.StreamModeDetails?.StreamMode;return l.length>0&&(n[r]={issues:l}),n},{})});var hQ,P6,L6=D(()=>{"use strict";me();fe();hQ=t=>typeof t=="string"?t==="*":typeof t=="object"?Object.values(t).some(e=>Array.isArray(e)?e.includes("*"):e==="*"):!1,P6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if((i.Type==="AWS::KMS::Key"&&Array.isArray(i.Properties?.KeyPolicy?.Statement)?i.Properties.KeyPolicy.Statement:[]).some(c=>hQ(c.Principal))){let c=W(s,r),u=$(c);n[r]={issues:[e(r,"KMS key has a public policy.",T("Restrict the KMS key policy to specific IAM roles or users to prevent unauthorized access.",c,"keyPolicy / admins / encryptionKey"),u?"HIGH":"CRITICAL","Security",j(i,r),"cdkInsights")]}}return n},{})});var gQ,yQ,xQ,bQ,SQ,O6,vQ,CQ,DQ,AQ,wQ,M6,B6=D(()=>{"use strict";me();fe();gQ=new Set(["*","kms:*","kms:PutKeyPolicy"]),yQ=new Set(["*","kms:*","kms:PutKeyPolicy"]),xQ=new Set(["aws:PrincipalArn","aws:PrincipalAccount","aws:PrincipalIsAWSService"]),bQ=new Set(["StringNotEquals","StringNotLike","ArnNotLike","ArnNotEquals"]),SQ=t=>{if(t==="*")return!0;if(t&&typeof t=="object"&&!Array.isArray(t)){let e=t,s=e.AWS;if(s==="*"||Array.isArray(s)&&s.includes("*")||e.Service==="*")return!0}return!1},O6=t=>typeof t=="string"?[t]:Array.isArray(t)?t.filter(e=>typeof e=="string"):[],vQ=t=>O6(t).find(e=>gQ.has(e)),CQ=t=>{if(!t||typeof t!="object")return!1;for(let[e,s]of Object.entries(t)){if(!s||typeof s!="object")continue;let n=Object.keys(s);if(n.includes("aws:PrincipalIsAWSService"))return!0;if(bQ.has(e)){for(let r of n)if(xQ.has(r))return!0}}return!1},DQ=t=>{if(!t||typeof t!="object"||Array.isArray(t))return!1;let e=t.AWS;return(Array.isArray(e)?e:[e]).some(n=>{if(n==="*")return!1;if(typeof n=="string")return/:root$/.test(n);if(n&&typeof n=="object"){let r=JSON.stringify(n);return r.includes("AWS::AccountId")&&r.includes("root")}return!1})},AQ=t=>t.Effect!=="Allow"||t.NotPrincipal!==void 0||!DQ(t.Principal)?!1:O6(t.Action).some(s=>yQ.has(s)),wQ=t=>{if(t.Effect!=="Deny"||t.NotPrincipal!==void 0||!SQ(t.Principal))return;let e=vQ(t.Action);if(e&&!CQ(t.Condition))return e},M6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::KMS::Key")return n;let o=i.Properties?.KeyPolicy?.Statement;if(!Array.isArray(o)||o.some(AQ))return n;let a=o.map(wQ).find(d=>d!==void 0);if(!a)return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,`Key policy contains a Deny statement on ${a} with Principal: '*' and no carveout for the account root or admin role. This locks the account out of the KMS key \u2014 recovery requires breaking glass on the account root credentials AND scheduling a 7-30 day key deletion (which does not actually let you recover the key, just remove it). Effectively unrecoverable for any data the key has encrypted; AWS Support typically declines to intervene.`,T("Keep the auto-injected root Allow statement (CDK's defaultKeyPolicy) intact, or add an explicit Allow on Principal: { AWS: 'arn:aws:iam::<account>:root' } for Action: kms:*. Alternatively, add a NotPrincipal exemption or a Condition with StringNotEquals on aws:PrincipalArn to exempt your admin role(s).",u,"keyPolicy.statements"),l?"HIGH":"CRITICAL","Security",c,"cdkInsights")]},n},{})});var N6,$6=D(()=>{"use strict";me();fe();N6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Lambda::Function")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);return i.Properties?.ReservedConcurrentExecutions===void 0&&(n[r]={issues:[e(r,"Lambda function has no reserved concurrency configured.",T("Consider setting ReservedConcurrentExecutions to prevent the function from consuming all available account concurrency and to control scaling behavior.",o),c("LOW"),"Reliability",u,"cdkInsights")]}),n},{})});var EQ,RQ,tS,IQ,W6,j6=D(()=>{"use strict";me();fe();EQ=new Set(["events.amazonaws.com","sns.amazonaws.com","s3.amazonaws.com","ses.amazonaws.com","codecommit.amazonaws.com","codepipeline.amazonaws.com","config.amazonaws.com","cloudwatch.amazonaws.com","iot.amazonaws.com","logs.amazonaws.com","pipes.amazonaws.com","scheduler.amazonaws.com","cognito-idp.amazonaws.com"]),RQ=new Set(["apigateway.amazonaws.com","elasticloadbalancing.amazonaws.com","lambda.amazonaws.com"]),tS=t=>{if(typeof t=="string")return t;if(typeof t=="object"&&t!==null){let e=t;if(typeof e.Ref=="string")return e.Ref;let s=e["Fn::GetAtt"];if(Array.isArray(s)&&typeof s[0]=="string")return s[0]}return null},IQ=t=>{let e=new Map,s=(n,r)=>{e.has(n)||e.set(n,new Set),e.get(n)?.add(r)};for(let n of Object.values(t))if(n.Type==="AWS::Lambda::Permission"){let r=tS(n.Properties?.FunctionName),i=n.Properties?.Principal;if(!r||typeof i!="string")continue;EQ.has(i)?s(r,"async"):RQ.has(i)&&s(r,"sync")}else if(n.Type==="AWS::Lambda::EventSourceMapping"){let r=tS(n.Properties?.FunctionName);r&&s(r,"event-source")}else if(n.Type==="AWS::Lambda::EventInvokeConfig"){let r=tS(n.Properties?.FunctionName);r&&s(r,"async")}return e},W6=(t,e,s)=>{let n=t.Resources||{},r=IQ(n);return Object.entries(n).reduce((i,[o,a])=>{if(a.Type!=="AWS::Lambda::Function"||a.Properties?.DeadLetterConfig?.TargetArn)return i;let c=j(a,o),u=W(s,o),l=$(u),d=r.get(o)??new Set(["unknown"]),p=d.has("async"),f=d.has("sync"),m=d.has("event-source");return f&&!p&&!m?i:m&&!p?(i[o]={issues:[e(o,"Lambda function consumes an event source mapping without a failure destination.",T("For SQS/Kinesis/DynamoDB Streams, configure an OnFailure destination on the EventSourceMapping (DestinationConfig.OnFailure) \u2014 function-level DeadLetterConfig is for async invocations and does not apply to poll-based event sources.",u,"onFailure / deadLetterQueue (on EventSourceMapping)"),l?"LOW":"MEDIUM","Reliability",c,"cdkInsights")]},i):p?(i[o]={issues:[e(o,"Lambda function has no Dead Letter Queue configured for async invocations.",T("Configure a Dead Letter Queue (SQS or SNS) via DeadLetterConfig to capture failed async invocations for debugging, monitoring, and retry processing.",u,"deadLetterQueueEnabled / deadLetterQueue"),l?"LOW":"MEDIUM","Reliability",c,"cdkInsights")]},i):(i[o]={issues:[e(o,"Lambda function has no Dead Letter Queue configured (invocation mode could not be inferred).",T("No invocation source was detected in this template. If the function is invoked async (EventBridge, SNS, S3, etc.), configure DeadLetterConfig to capture failures. If it is invoked sync (API Gateway, ALB, direct invoke), DLQ does not apply and this finding can be suppressed.",u,"deadLetterQueueEnabled / deadLetterQueue"),"LOW","Reliability",c,"cdkInsights")]},i)},{})}});var kQ,U6,H6=D(()=>{"use strict";me();fe();kQ=/\b(secret|password|passwd|pwd|credential|private_key|api_key|api_secret|auth_token|access_key|access_secret|bearer_token|jwt_secret|encryption_key|signing_key)\b/i,U6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::Lambda::Function"){let o=W(s,r),a=$(o),c=l=>a?ee(l):l,u=Object.entries(i.Properties?.Environment?.Variables||{}).filter(([l])=>kQ.test(l)).map(([l])=>e(r,`Lambda function contains sensitive environment variable: ${l}.`,T("Store sensitive environment variables in AWS Secrets Manager or SSM Parameter Store instead of plaintext environment variables.",o),c("HIGH"),"Security",j(i,r),"cdkInsights"));u.length>0&&(n[r]={issues:u})}return n},{})});var G6,z6=D(()=>{"use strict";me();fe();G6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::Lambda::Function"){let o=W(s,r),a=$(o),c=l=>a?ee(l):l,u=i.Properties?.MemorySize;typeof u=="number"&&u>1024&&(n[r]={issues:[e(r,"Lambda function has high memory allocation.",T("Consider reducing memory for cost savings.",o),c("MEDIUM"),"Cost Optimization",j(i,r),"cdkInsights")]})}return n},{})});var _Q,FQ,TQ,q6,K6,V6,Z6=D(()=>{"use strict";me();fe();_Q=t=>typeof t=="string"&&/^\d{12}$/.test(t),FQ=t=>{if(!t||typeof t!="object")return!1;let e=t.Ref;return typeof e=="string"&&e.endsWith("AccountId")},TQ=t=>t==="*"||t===void 0,q6=t=>typeof t=="string"&&t.endsWith(".amazonaws.com"),K6=t=>t?!!(t.SourceArn||t.SourceAccount||t.PrincipalOrgID||t.OrganizationId):!1,V6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{let o=i.Type==="AWS::Lambda::Permission",a=i.Type==="AWS::Lambda::LayerVersionPermission";if(!o&&!a)return n;let c=i.Properties??{},u=c.Principal,l=[],d=j(i,r),p=W(s,r),f=$(p);return TQ(u)?l.push(e(r,`${i.Type} grants public access via wildcard Principal.`,T("Set Principal to a specific AWS account ID, an AWS service principal with SourceArn/SourceAccount, or an OrganizationId. Wildcard principals make the function/layer reachable from any AWS account.",p,"permissionProps.principal"),f?"HIGH":"CRITICAL","Security",d,"cdkInsights")):o&&q6(u)&&!K6(c)?l.push(e(r,"Lambda::Permission grants a service principal access without SourceArn / SourceAccount / PrincipalOrgID.",T("Constrain the service principal: set SourceArn to the specific resource that may invoke the function, or SourceAccount to your AWS account ID. Without one of these, any account using that AWS service can invoke this function (confused-deputy risk).",p,"permissionProps.sourceArn"),f?"MEDIUM":"HIGH","Security",d,"cdkInsights")):o&&!_Q(u)&&!FQ(u)&&!q6(u)&&!K6(c)&&l.push(e(r,"Lambda::Permission has an unrecognised Principal shape with no source restriction.",T("Confirm the Principal resolves to an account ID, an org ID, or an AWS service plus a SourceArn/SourceAccount. Wildcards or unrestricted patterns expose the function publicly.",p,"permissionProps.principal"),f?"LOW":"MEDIUM","Security",d,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var PQ,Y6,J6=D(()=>{"use strict";me();fe();PQ={nodejs:"nodejs22.x","nodejs4.3":"nodejs22.x","nodejs4.3-edge":"nodejs22.x","nodejs6.10":"nodejs22.x","nodejs8.10":"nodejs22.x","nodejs10.x":"nodejs22.x","nodejs12.x":"nodejs22.x","nodejs14.x":"nodejs22.x","nodejs16.x":"nodejs22.x","nodejs18.x":"nodejs22.x","python2.7":"python3.13","python3.6":"python3.13","python3.7":"python3.13","python3.8":"python3.13","python3.9":"python3.13",java8:"java21","java8.al2":"java21",java11:"java21","dotnetcore1.0":"dotnet8","dotnetcore2.0":"dotnet8","dotnetcore2.1":"dotnet8","dotnetcore3.1":"dotnet8","dotnet5.0":"dotnet8",dotnet6:"dotnet8","ruby2.5":"ruby3.3","ruby2.7":"ruby3.3","go1.x":"provided.al2023"},Y6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Lambda::Function")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=i.Properties?.Runtime;if(typeof u!="string")return n;let l=PQ[u];return l&&(n[r]={issues:[e(r,`Lambda function uses deprecated runtime "${u}". This runtime has reached or is approaching end-of-life and will no longer receive security patches.`,T(`Upgrade to "${l}" for continued security patches, performance improvements, and long-term support.`,o),c("HIGH"),"Security",j(i,r),"cdkInsights")]}),n},{})});var Q6,X6=D(()=>{"use strict";me();fe();Q6=(t,e,s)=>Object.values(t.Resources||{}).some(r=>r.Type==="AWS::EC2::NatGateway")?Object.entries(t.Resources||{}).reduce((r,[i,o])=>{if(o.Type!=="AWS::Lambda::Function")return r;let a=W(s,i),c=$(a),u=p=>c?ee(p):p,l=j(o,i),d=o.Properties?.VpcConfig;return d?.SubnetIds&&d.SubnetIds.length>0&&(r[i]={issues:[e(i,"Lambda function in VPC with NAT Gateway detected. NAT Gateway costs can accumulate quickly.",T("Evaluate if VPC attachment is necessary. Consider using VPC endpoints for AWS services to reduce NAT costs. NAT Gateway charges ~$0.045/hr plus $0.045/GB processed.",a),u("MEDIUM"),"Cost Optimization",l,"cdkInsights")]}),r},{}):{}});var eO,tO=D(()=>{"use strict";me();fe();eO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::MSK::Cluster")return n;let o=W(s,r),a=$(o),c=g=>a?ee(g):g,u=j(i,r),l=[],d=i.Properties?.ClientAuthentication,p=(d?.Tls?.CertificateAuthorityArnList?.length??0)>0,f=d?.Sasl?.Scram?.Enabled===!0||d?.Sasl?.Iam?.Enabled===!0,m=d?.Unauthenticated?.Enabled===!0;return!p&&!f&&l.push(e(r,"MSK cluster does not have client authentication configured.",T("Enable SASL/SCRAM, IAM authentication, or mutual TLS for client authentication.",o),c("HIGH"),"Security",u,"cdkInsights")),m&&l.push(e(r,"MSK cluster allows unauthenticated access.",T("Disable unauthenticated access and require client authentication for all connections.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var sO,nO=D(()=>{"use strict";me();fe();sO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::MSK::Cluster")return n;let o=W(s,r),a=$(o),c=m=>a?ee(m):m,u=j(i,r),l=[],d=i.Properties?.EncryptionInfo;d?.EncryptionAtRest?.DataVolumeKMSKeyId||l.push(e(r,"MSK cluster does not use a customer-managed KMS key for encryption at rest.",T("Specify DataVolumeKMSKeyId in EncryptionAtRest for additional control over data encryption.",o),c("LOW"),"Security",u,"cdkInsights"));let f=d?.EncryptionInTransit;return f?.ClientBroker!=="TLS"&&l.push(e(r,"MSK cluster does not enforce TLS encryption for client-broker communication.",T("Set ClientBroker to TLS in EncryptionInTransit to encrypt data between clients and brokers.",o),c("HIGH"),"Security",u,"cdkInsights")),f?.InCluster!==!0&&l.push(e(r,"MSK cluster does not have encryption enabled for inter-broker communication.",T("Set InCluster to true in EncryptionInTransit to encrypt data between brokers.",o),c("MEDIUM"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var rO,iO=D(()=>{"use strict";me();fe();rO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::MSK::Cluster")return n;let o=W(s,r),a=$(o),c=h=>a?ee(h):h,u=j(i,r),l=[],p=i.Properties?.LoggingInfo?.BrokerLogs,f=p?.CloudWatchLogs?.Enabled===!0,m=p?.Firehose?.Enabled===!0,g=p?.S3?.Enabled===!0;return!f&&!m&&!g&&l.push(e(r,"MSK cluster does not have broker logging configured.",T("Enable broker logs to CloudWatch, Firehose, or S3 for monitoring and troubleshooting Kafka operations.",o),c("MEDIUM"),"Operational Excellence",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var oO,aO=D(()=>{"use strict";me();fe();oO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::OpenSearchService::Domain"&&i.Type!=="AWS::Elasticsearch::Domain")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[];i.Properties?.AdvancedSecurityOptions?.Enabled!==!0&&l.push(e(r,"OpenSearch domain does not have fine-grained access control enabled.",T("Enable AdvancedSecurityOptions to use IAM or internal user database for document-level and field-level security.",o),c("MEDIUM"),"Security",u,"cdkInsights"));let p=i.Properties?.VPCOptions;return(!p?.SubnetIds||p.SubnetIds.length===0)&&l.push(e(r,"OpenSearch domain is not deployed within a VPC.",T("Configure VPCOptions with subnet IDs to deploy the domain within a VPC for network isolation.",o),c("MEDIUM"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var cO,uO=D(()=>{"use strict";me();fe();cO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::OpenSearchService::Domain"&&i.Type!=="AWS::Elasticsearch::Domain")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[];return i.Properties?.EncryptionAtRestOptions?.Enabled!==!0&&l.push(e(r,"OpenSearch domain does not have encryption at rest enabled.",T("Enable EncryptionAtRestOptions to protect indexed data at rest using AWS KMS.",o),c("HIGH"),"Security",u,"cdkInsights")),i.Properties?.NodeToNodeEncryptionOptions?.Enabled!==!0&&l.push(e(r,"OpenSearch domain does not have node-to-node encryption enabled.",T("Enable NodeToNodeEncryptionOptions to encrypt data in transit between nodes within the cluster.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var lO,dO=D(()=>{"use strict";me();fe();lO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::OpenSearchService::Domain"&&i.Type!=="AWS::Elasticsearch::Domain")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=[],d=i.Properties?.LogPublishingOptions;return d?.AUDIT_LOGS?.Enabled||l.push(e(r,"OpenSearch domain does not have audit logging enabled.",T("Enable AUDIT_LOGS in LogPublishingOptions to track user activity for security and compliance monitoring.",o),c("LOW"),"Security",u,"cdkInsights")),d?.ES_APPLICATION_LOGS?.Enabled||l.push(e(r,"OpenSearch domain does not have application logging enabled.",T("Enable ES_APPLICATION_LOGS in LogPublishingOptions to capture error logs for troubleshooting.",o),c("LOW"),"Operational Excellence",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var pO,fO=D(()=>{"use strict";me();fe();pO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::RDS::DBInstance")return n;let o=j(i,r),a=i.Properties?.BackupRetentionPeriod,c=W(s,r),u=$(c),l=d=>u?ee(d):d;return a===0?n[r]={issues:[e(r,"RDS instance has automated backups disabled (BackupRetentionPeriod is 0).",T("Enable automated backups with at least 7 days retention for production databases to enable point-in-time recovery.",c,"backupRetention"),l("HIGH"),"Reliability",o,"cdkInsights")]}:a!==void 0&&a<7&&(n[r]={issues:[e(r,`RDS backup retention period is only ${a} day(s).`,T("Consider increasing backup retention to at least 7 days for production databases.",c,"backupRetention"),l("MEDIUM"),"Reliability",o,"cdkInsights")]}),n},{})});var mO,hO=D(()=>{"use strict";me();fe();mO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::RDS::DBInstance")return n;let o=W(s,r),a=$(o),c=l=>a?ee(l):l,u=j(i,r);return i.Properties?.DeletionProtection!==!0&&(n[r]={issues:[e(r,"RDS instance does not have deletion protection enabled.",T("Enable DeletionProtection to prevent accidental database deletion.",o),c("MEDIUM"),"Reliability",u,"cdkInsights")]}),n},{})});var gO,yO=D(()=>{"use strict";me();fe();gO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::RDS::DBInstance"&&i.Properties?.StorageEncrypted!==!0){let o=W(s,r),a=$(o);n[r]={issues:[e(r,"RDS instance is not encrypted.",T("Enable encryption to protect data at rest and meet compliance standards.",o,"storageEncrypted / storageEncryptionKey"),a?"HIGH":"CRITICAL","Security",j(i,r),"cdkInsights")]}}return n},{})});var LQ,xO,bO=D(()=>{"use strict";me();fe();LQ=new Set(["AWS::RDS::DBInstance","AWS::RDS::DBCluster"]),xO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(!LQ.has(i.Type))return n;let o=i.Properties?.EnableCloudwatchLogsExports;if(Array.isArray(o)&&o.length>0)return n;let a=j(i,r),c=W(s,r),u=$(c);return n[r]={issues:[e(r,"RDS database does not export logs to CloudWatch.",T("Set EnableCloudwatchLogsExports to the relevant log types for the engine (e.g. ['error','general','slowquery'] for MySQL, ['postgresql'] for PostgreSQL, ['audit','error','general','slowquery'] for MariaDB).",c,"databaseProps.cloudwatchLogsExports"),u?"LOW":"MEDIUM","Security",a,"cdkInsights")]},n},{})});var OQ,SO,vO=D(()=>{"use strict";me();fe();OQ=new Set([1,5,10,15,30,60]),SO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::RDS::DBInstance")return n;let o=i.Properties?.MonitoringInterval,a=typeof o=="number"?o:typeof o=="string"?Number.parseInt(o,10):void 0;if(typeof a=="number"&&OQ.has(a))return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,"RDS Instance does not have enhanced monitoring enabled.",T("Set MonitoringInterval to 1, 5, 10, 15, 30, or 60 (seconds) and provide MonitoringRoleArn so RDS can publish OS-level metrics to CloudWatch Logs.",u,"databaseProps.monitoringInterval"),l?"LOW":"MEDIUM","Operational Excellence",c,"cdkInsights")]},n},{})});var CO,DO=D(()=>{"use strict";me();fe();CO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::RDS::DBInstance")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=i.Properties??{},l=u.MultiAZ===!0,d=u.StorageType==="gp2",p=typeof u.StorageType>"u";return l&&(d||p)&&(n[r]={issues:[e(r,d?"RDS instance is using Multi-AZ with gp2 storage. Consider gp3 for lower costs.":"RDS instance is using Multi-AZ without explicitly setting a storage type. gp3 may offer better performance and cost savings.",T("Switch to gp3 storage for RDS to reduce costs and improve performance.",o),c("MEDIUM"),"Cost Optimization",j(i,r),"cdkInsights")]}),n},{})});var AO,wO=D(()=>{"use strict";me();fe();AO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::RDS::DBInstance")return n;let o=W(s,r),a=$(o),c=l=>a?ee(l):l,u=j(i,r);return i.Properties?.PubliclyAccessible===!0&&(n[r]={issues:[e(r,"RDS instance is publicly accessible from the internet.",T("Set PubliclyAccessible to false and access the database through private subnets, bastion hosts, or VPN. If public access is intentional (e.g. a dev or staging database with restricted security groups), suppress this rule for the resource.",o),c("HIGH"),"Security",u,"cdkInsights")]}),n},{})});var EO,RO=D(()=>{"use strict";me();fe();EO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Redshift::Cluster")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=[];return i.Properties?.Encrypted!==!0&&l.push(e(r,"Redshift cluster does not have encryption at rest enabled.",T("Set Encrypted to true and specify a KmsKeyId to protect data at rest.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var IO,kO=D(()=>{"use strict";me();fe();IO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Redshift::Cluster")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);return i.Properties?.LoggingProperties?.BucketName||(n[r]={issues:[e(r,"Redshift cluster does not have audit logging enabled.",T("Configure LoggingProperties with an S3 bucket to capture connection logs, user activity, and query activity.",o),c("MEDIUM"),"Security",u,"cdkInsights")]}),n},{})});var _O,FO=D(()=>{"use strict";me();fe();_O=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Redshift::Cluster")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);return i.Properties?.PubliclyAccessible===!0&&(n[r]={issues:[e(r,"Redshift cluster is publicly accessible.",T("Set PubliclyAccessible to false and use VPC endpoints or bastion hosts for secure access. If public access is intentional (e.g. analytics tooling or customer-facing dashboards) ensure security groups restrict the source CIDRs and suppress this rule for the resource.",o),c("HIGH"),"Security",u,"cdkInsights")]}),n},{})});var TO,PO=D(()=>{"use strict";me();fe();TO=(t,e,s)=>{let n=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::Route53::HostedZone"),r=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::Route53::DNSSEC"),i=new Set(r.map(([,o])=>{let a=o.Properties?.HostedZoneId;return typeof a=="string"?a:a?.Ref?a.Ref:null}).filter(Boolean));return n.reduce((o,[a,c])=>{if(c.Properties?.HostedZoneConfig?.Comment?.includes("private"))return o;let u=j(c,a);if(!i.has(a)){let d=W(s,a),p=$(d),f=m=>p?ee(m):m;o[a]={issues:[e(a,"Route53 Hosted Zone does not have DNSSEC signing enabled.",T("Enable DNSSEC to protect against DNS spoofing and cache poisoning attacks by cryptographically signing DNS records.",d),f("LOW"),"Security",u,"cdkInsights")]}}return o},{})}});var LO,OO=D(()=>{"use strict";me();fe();LO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Route53::HealthCheck")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=[],d=i.Properties?.HealthCheckConfig;return d?.Type==="HTTP"&&l.push(e(r,"Route53 Health Check uses HTTP instead of HTTPS.",T("Use HTTPS for health checks to ensure the endpoint supports secure connections and to validate SSL certificates.",o),c("LOW"),"Security",u,"cdkInsights")),d?.RequestInterval===30&&l.push(e(r,"Route53 Health Check uses standard (30 second) request interval.",T("Consider using fast interval (10 seconds) for critical endpoints to detect failures more quickly.",o),c("LOW"),"Reliability",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var MO,BO=D(()=>{"use strict";me();fe();MO=(t,e,s)=>{let n=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::Route53::HostedZone"),r=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::Route53::QueryLoggingConfig"),i=new Set(r.map(([,o])=>{let a=o.Properties?.HostedZoneId;return typeof a=="string"?a:a?.Ref?a.Ref:null}).filter(Boolean));return n.reduce((o,[a,c])=>{let u=j(c,a);if(!i.has(a)){let d=W(s,a),p=$(d),f=m=>p?ee(m):m;o[a]={issues:[e(a,"Route53 Hosted Zone does not have query logging enabled.",T("Enable query logging to CloudWatch Logs for DNS query analysis, troubleshooting, and security monitoring.",d),f("LOW"),"Security",u,"cdkInsights")]}}return o},{})}});var NO,$O=D(()=>{"use strict";me();fe();NO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::S3::Bucket")return n;let o=[],a=i.Properties??{},c=j(i,r),u=W(s,r),l=$(u);a.BucketEncryption||o.push(e(r,"S3 Bucket lacks encryption.",T("Enable encryption at rest for better security.",u,"bucketProps.encryption"),l?"MEDIUM":"HIGH","Security",c,"cdkInsights"));let d=a?.PublicAccessBlockConfiguration;return d?(d.BlockPublicAcls===!1&&o.push(e(r,"S3 Bucket allows public ACLs (BlockPublicAcls is false).","Set BlockPublicAcls to true to prevent public ACLs from being applied.","CRITICAL","Security",c,"cdkInsights")),d.BlockPublicPolicy===!1&&o.push(e(r,"S3 Bucket allows public bucket policies (BlockPublicPolicy is false).","Set BlockPublicPolicy to true to prevent public bucket policies.","CRITICAL","Security",c,"cdkInsights")),d.IgnorePublicAcls===!1&&o.push(e(r,"S3 Bucket does not ignore public ACLs (IgnorePublicAcls is false).","Set IgnorePublicAcls to true to ignore any public ACLs on the bucket.","HIGH","Security",c,"cdkInsights")),d.RestrictPublicBuckets===!1&&o.push(e(r,"S3 Bucket does not restrict public bucket access (RestrictPublicBuckets is false).","Set RestrictPublicBuckets to true to restrict access to the bucket to only authorized users.","HIGH","Security",c,"cdkInsights"))):o.push(e(r,"S3 Bucket has no PublicAccessBlockConfiguration defined.","Configure PublicAccessBlockConfiguration with BlockPublicAcls, BlockPublicPolicy, IgnorePublicAcls, and RestrictPublicBuckets all set to true.","HIGH","Security",c,"cdkInsights")),a.VersioningConfiguration||o.push(e(r,"S3 Bucket has no versioning enabled.","Enable versioning to protect against accidental deletions.","MEDIUM","Operational Excellence",c,"cdkInsights")),o.length>0&&(n[r]={issues:o}),n},{})});var MQ,BQ,NQ,$Q,WQ,jQ,UQ,HQ,GQ,zQ,qQ,WO,jO=D(()=>{"use strict";me();fe();MQ=new Set(["*","s3:*","s3:DeleteBucket","s3:DeleteBucketPolicy","s3:PutBucketPolicy"]),BQ=new Set(["aws:PrincipalArn","aws:PrincipalAccount","aws:PrincipalIsAWSService"]),NQ=new Set(["StringNotEquals","StringNotLike","ArnNotLike","ArnNotEquals"]),$Q=t=>{if(t==="*")return!0;if(t&&typeof t=="object"&&!Array.isArray(t)){let e=t,s=e.AWS;if(s==="*"||Array.isArray(s)&&s.includes("*")||e.Service==="*")return!0}return!1},WQ=t=>typeof t=="string"?[t]:Array.isArray(t)?t.filter(e=>typeof e=="string"):[],jQ=t=>WQ(t).find(e=>MQ.has(e)),UQ=t=>t===!1||t==="false"||t==="False",HQ=t=>{if(t==null)return!0;let e=Array.isArray(t)?t:[t];if(e.length===0)return!0;for(let s of e){if(typeof s!="string"||s==="*")return!0;let n=s.split(":::")[1];if(n===void 0||!n.includes("/"))return!0}return!1},GQ=t=>{let e=t.Condition;if(!e||typeof e!="object")return!1;let s=e.Bool??e.BoolIfExists;return s?UQ(s["aws:SecureTransport"]):!1},zQ=t=>{if(!t||typeof t!="object")return!1;for(let[e,s]of Object.entries(t)){if(!s||typeof s!="object")continue;let n=Object.keys(s);if(n.includes("aws:PrincipalIsAWSService"))return!0;if(NQ.has(e)){for(let r of n)if(BQ.has(r))return!0}}return!1},qQ=t=>{if(t.Effect!=="Deny"||t.NotPrincipal!==void 0||!$Q(t.Principal))return;let e=jQ(t.Action);if(e&&!GQ(t)&&!zQ(t.Condition)&&HQ(t.Resource))return e},WO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::S3::BucketPolicy")return n;let o=i.Properties?.PolicyDocument?.Statement;if(!Array.isArray(o))return n;let a=o.map(qQ).find(d=>d!==void 0);if(!a)return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,`Bucket policy contains a Deny statement on ${a} with Principal: '*' and no carveout for the account root or admin role. This will lock the account out of the bucket \u2014 recovery requires breaking glass on the account root credentials to remove the bucket policy. AWS Support will typically not intervene for this scenario.`,T("Add a NotPrincipal exemption for the account root (e.g. arn:aws:iam::<account>:root) or use a Condition with StringNotEquals on aws:PrincipalArn to exempt your admin role(s). If the Deny is intended for transport security, scope it with aws:SecureTransport rather than a blanket Deny on Principal: '*'.",u,"bucketPolicyProps.statements"),l?"HIGH":"CRITICAL","Security",c,"cdkInsights")]},n},{})});var KQ,VQ,UO,HO=D(()=>{"use strict";me();fe();KQ=t=>t===!1||t==="false"||t==="False",VQ=t=>{if(t.Effect!=="Deny")return!1;let e=t.Condition;if(!e||typeof e!="object")return!1;let s=e.Bool??e.BoolIfExists;return s?KQ(s["aws:SecureTransport"]):!1},UO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::S3::BucketPolicy")return n;let o=i.Properties?.PolicyDocument?.Statement;if(Array.isArray(o)&&o.some(VQ))return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,"S3 BucketPolicy does not deny non-SSL/TLS requests.",T("Add a Deny statement with Condition.Bool['aws:SecureTransport']=false to enforce TLS for all S3 access. CIS AWS Foundations 2.1.1 and PCI-DSS require encrypted-in-transit requests.",u,"bucketPolicyProps.statements"),l?"MEDIUM":"HIGH","Security",c,"cdkInsights")]},n},{})});var GO,zO=D(()=>{"use strict";me();fe();GO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::S3::Bucket")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r);return(i.Properties?.LifecycleConfiguration?.Rules||[]).length===0&&(n[r]={issues:[e(r,"S3 bucket has no lifecycle policy configured.",T("Configure lifecycle rules to automatically transition objects to cheaper storage classes (e.g., Glacier) or delete old versions to optimize storage costs.",o),c("MEDIUM"),"Cost Optimization",u,"cdkInsights")]}),n},{})});var qO,KO=D(()=>{"use strict";me();fe();qO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::S3::Bucket"||(i.Properties??{}).LoggingConfiguration?.DestinationBucketName)return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,"S3 Bucket has no access logging configured.",T("Set LoggingConfiguration.DestinationBucketName to capture object-level access logs in a separate bucket. Required by CIS AWS Foundations 2.1.2 and useful for incident forensics.",u,"bucketProps.serverAccessLogsBucket"),l?"LOW":"MEDIUM","Security",c,"cdkInsights")]},n},{})});var ZQ,VO,ZO=D(()=>{"use strict";me();fe();ZQ=/\b(prod|production|critical|backup|dr|disaster|recovery|primary)\b/i,VO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::S3::Bucket")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=i.Properties?.BucketName||r,d=i.Properties?.ReplicationConfiguration;return ZQ.test(l)&&!d?.Rules?.length&&(n[r]={issues:[e(r,"Critical S3 bucket does not have cross-region replication configured.",T("Consider enabling cross-region replication for disaster recovery and data durability on production/critical buckets.",o),c("LOW"),"Reliability",u,"cdkInsights")]}),n},{})});var YO,JO=D(()=>{"use strict";me();fe();YO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::S3::Bucket"&&!i.Properties?.IntelligentTieringConfigurations){let o=W(s,r),a=$(o),c=u=>a?ee(u):u;n[r]={issues:[e(r,"S3 Bucket does not use Intelligent-Tiering. Consider enabling it for cost optimization.",T("Enable Intelligent-Tiering for automatic cost optimization of infrequently accessed objects.",o),c("LOW"),"Cost Optimization",j(i,r),"cdkInsights")]}}return n},{})});var QO,XO=D(()=>{"use strict";me();fe();QO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{let o=i.Properties??{};if(i.Type==="AWS::SecretsManager::Secret"&&o.PublicPolicy){let a=W(s,r),c=$(a),u=l=>c?ee(l):l;n[r]={issues:[e(r,"Secret is publicly accessible.",T("Restrict secret access using IAM policies to ensure only authorized entities can retrieve it.",a),u("CRITICAL"),"Security",j(i,r),"cdkInsights")]}}return n},{})});var e3,t3=D(()=>{"use strict";me();fe();e3=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::SNS::Topic"&&!i.Properties?.KmsMasterKeyId){let o=W(s,r),a=$(o),c=u=>a?ee(u):u;n[r]={issues:[e(r,"SNS topic is not encrypted.",T("Enable AWS KMS encryption for SNS to protect sensitive messages in transit and at rest.",o),c("HIGH"),"Security",j(i,r),"cdkInsights")]}}return n},{})});var YQ,JQ,QQ,XQ,eX,tX,sX,nX,s3,n3=D(()=>{"use strict";me();fe();YQ=new Set(["*","sns:*","sns:DeleteTopic","sns:RemovePermission"]),JQ=new Set(["aws:PrincipalArn","aws:PrincipalAccount","aws:PrincipalIsAWSService"]),QQ=new Set(["StringNotEquals","StringNotLike","ArnNotLike","ArnNotEquals"]),XQ=t=>{if(t==="*")return!0;if(t&&typeof t=="object"&&!Array.isArray(t)){let e=t,s=e.AWS;if(s==="*"||Array.isArray(s)&&s.includes("*")||e.Service==="*")return!0}return!1},eX=t=>typeof t=="string"?[t]:Array.isArray(t)?t.filter(e=>typeof e=="string"):[],tX=t=>eX(t).find(e=>YQ.has(e)),sX=t=>{if(!t||typeof t!="object")return!1;for(let[e,s]of Object.entries(t)){if(!s||typeof s!="object")continue;let n=Object.keys(s);if(n.includes("aws:PrincipalIsAWSService"))return!0;if(QQ.has(e)){for(let r of n)if(JQ.has(r))return!0}}return!1},nX=t=>{if(t.Effect!=="Deny"||t.NotPrincipal!==void 0||!XQ(t.Principal))return;let e=tX(t.Action);if(e&&!sX(t.Condition))return e},s3=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::SNS::TopicPolicy")return n;let o=i.Properties?.PolicyDocument?.Statement;if(!Array.isArray(o))return n;let a=o.map(nX).find(d=>d!==void 0);if(!a)return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,`Topic policy contains a Deny statement on ${a} with Principal: '*' and no carveout for the account root or admin role. This locks the account out of the topic \u2014 recovery requires breaking glass on the account root credentials to remove the topic policy, or delete-and-recreate the topic if no subscribers depend on its ARN. In fan-out architectures that's often a multi-stack rebuild.`,T("Add a NotPrincipal exemption for the account root (e.g. arn:aws:iam::<account>:root) or use a Condition with StringNotEquals on aws:PrincipalArn to exempt your admin role(s). If the Deny is intended to scope to AWS services, use aws:PrincipalIsAWSService rather than a blanket Deny on Principal: '*'.",u,"topicPolicyProps.statements"),l?"HIGH":"CRITICAL","Security",c,"cdkInsights")]},n},{})});var r3,i3=D(()=>{"use strict";me();fe();r3=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::SQS::Queue"&&!i.Properties?.KmsMasterKeyId){let o=W(s,r),a=$(o),c=u=>a?ee(u):u;n[r]={issues:[e(r,"SQS queue is not encrypted.",T("Enable AWS KMS encryption for SQS to protect message data in transit and at rest.",o),c("HIGH"),"Security",j(i,r),"cdkInsights")]}}return n},{})});var rX,iX,oX,aX,cX,uX,lX,dX,o3,a3=D(()=>{"use strict";me();fe();rX=new Set(["*","sqs:*","sqs:DeleteQueue","sqs:RemovePermission"]),iX=new Set(["aws:PrincipalArn","aws:PrincipalAccount","aws:PrincipalIsAWSService"]),oX=new Set(["StringNotEquals","StringNotLike","ArnNotLike","ArnNotEquals"]),aX=t=>{if(t==="*")return!0;if(t&&typeof t=="object"&&!Array.isArray(t)){let e=t,s=e.AWS;if(s==="*"||Array.isArray(s)&&s.includes("*")||e.Service==="*")return!0}return!1},cX=t=>typeof t=="string"?[t]:Array.isArray(t)?t.filter(e=>typeof e=="string"):[],uX=t=>cX(t).find(e=>rX.has(e)),lX=t=>{if(!t||typeof t!="object")return!1;for(let[e,s]of Object.entries(t)){if(!s||typeof s!="object")continue;let n=Object.keys(s);if(n.includes("aws:PrincipalIsAWSService"))return!0;if(oX.has(e)){for(let r of n)if(iX.has(r))return!0}}return!1},dX=t=>{if(t.Effect!=="Deny"||t.NotPrincipal!==void 0||!aX(t.Principal))return;let e=uX(t.Action);if(e&&!lX(t.Condition))return e},o3=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::SQS::QueuePolicy")return n;let o=i.Properties?.PolicyDocument?.Statement;if(!Array.isArray(o))return n;let a=o.map(dX).find(d=>d!==void 0);if(!a)return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,`Queue policy contains a Deny statement on ${a} with Principal: '*' and no carveout for the account root or admin role. This locks the account out of the queue \u2014 recovery requires breaking glass on the account root credentials to remove the queue policy, or delete-and-recreate the queue if nothing else depends on its ARN. In event-driven systems that's often a multi-stack rebuild.`,T("Add a NotPrincipal exemption for the account root (e.g. arn:aws:iam::<account>:root) or use a Condition with StringNotEquals on aws:PrincipalArn to exempt your admin role(s). If the Deny is intended to scope to AWS services, use aws:PrincipalIsAWSService rather than a blanket Deny on Principal: '*'.",u,"queuePolicyProps.statements"),l?"HIGH":"CRITICAL","Security",c,"cdkInsights")]},n},{})});var c3,u3=D(()=>{"use strict";me();fe();c3=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::StepFunctions::StateMachine"&&i.Properties?.LoggingConfiguration===void 0){let o=W(s,r),a=$(o),c=u=>a?ee(u):u;n[r]={issues:[e(r,"Step Function lacks logging configuration.",T("Enable logging for the Step Function using AWS CloudWatch to improve monitoring and debugging.",o),c("HIGH"),"Security",j(i,r),"cdkInsights")]}}return n},{})});var l3,d3=D(()=>{"use strict";me();fe();l3=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EC2::SecurityGroup")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);if(i.Properties?.GroupName==="default"){let d=i.Properties?.SecurityGroupIngress||[],p=i.Properties?.SecurityGroupEgress||[];(d.length>0||p.length>0)&&(n[r]={issues:[e(r,"VPC default security group has rules configured.",T("Remove all rules from the default security group and use custom security groups instead. Default groups cannot be deleted but should have no rules.",o),c("MEDIUM"),"Security",u,"cdkInsights")]})}return n},{})});var p3,f3=D(()=>{"use strict";me();fe();p3=(t,e,s)=>{let n=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::EC2::VPC"),r=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::EC2::FlowLog"),i=new Set(r.filter(([,o])=>o.Properties?.ResourceType==="VPC").map(([,o])=>{let a=o.Properties?.ResourceId;return typeof a=="string"?a:a?.Ref?a.Ref:null}).filter(Boolean));return n.reduce((o,[a,c])=>{let u=j(c,a);if(!i.has(a)){let d=W(s,a),p=$(d),f=m=>p?ee(m):m;o[a]={issues:[e(a,"VPC does not have flow logs enabled.",T("Enable VPC Flow Logs to capture network traffic information for security analysis and troubleshooting.",d),f("MEDIUM"),"Security",u,"cdkInsights")]}}return o},{})}});var m3,h3=D(()=>{"use strict";me();fe();m3=(t,e,s)=>{let n=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::WAFv2::WebACL"),r=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::WAFv2::LoggingConfiguration"),i=new Set(r.map(([,o])=>{let a=o.Properties?.ResourceArn;return typeof a=="string"?a:a?.Ref?a.Ref:a?.["Fn::GetAtt"]?.[0]?a["Fn::GetAtt"][0]:null}).filter(Boolean));return n.reduce((o,[a,c])=>{let u=j(c,a);if(!(i.has(a)||r.some(([,d])=>{let p=d.Properties?.ResourceArn;return typeof p=="object"&&(p?.Ref===a||p?.["Fn::GetAtt"]?.[0]===a)}))){let d=W(s,a),p=$(d),f=m=>p?ee(m):m;o[a]={issues:[e(a,"WAF WebACL does not have logging configured.",T("Enable WAF logging to capture detailed information about web requests for security analysis and compliance.",d),f("MEDIUM"),"Security",u,"cdkInsights")]}}return o},{})}});var g3,y3=D(()=>{"use strict";me();fe();g3=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::WAFv2::WebACL")return n;let o=W(s,r),a=$(o),c=m=>a?ee(m):m,u=j(i,r),l=[],d=i.Properties?.DefaultAction;d?.Allow&&!d?.Block&&l.push(e(r,"WAF WebACL has default action set to Allow, which permits all traffic not matching rules.",T("Consider setting the default action to Block and explicitly allowing known-good traffic patterns for defense-in-depth.",o),c("MEDIUM"),"Security",u,"cdkInsights")),i.Properties?.VisibilityConfig?.CloudWatchMetricsEnabled||l.push(e(r,"WAF WebACL does not have CloudWatch metrics enabled.",T("Enable CloudWatchMetricsEnabled in VisibilityConfig to monitor WAF activity and detect potential attacks.",o),c("MEDIUM"),"Security",u,"cdkInsights"));let f=i.Properties?.Rules;return(!f||f.length===0)&&l.push(e(r,"WAF WebACL has no rules defined.",T("Add WAF rules to protect against common web exploits like SQL injection, XSS, and bot traffic.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var pX,x3,b3,S3,fX,lm,ll,mX,v3,C3,D3=D(()=>{"use strict";pX=t=>Object.values(t.Resources||{}).some(e=>e.Type==="Custom::S3BucketNotifications"),x3=t=>Object.values(t.Resources||{}).some(e=>e.Type==="AWS::Lambda::EventSourceMapping"),b3=t=>Object.values(t.Resources||{}).some(e=>e.Type==="AWS::Events::Rule"),S3=(t,e)=>Object.values(t.Resources||{}).some(s=>s.Type!=="AWS::ElasticLoadBalancingV2::Listener"?!1:(s.Properties?.DefaultActions||s.Properties?.Actions)?.some(r=>r.TargetGroupArn?.startsWith(e))),fX=t=>Object.values(t.Resources||{}).some(e=>e.Type==="AWS::Lambda::Permission"&&e.Properties?.Principal==="apigateway.amazonaws.com"),lm=(t,e)=>Object.values(t.Resources||{}).some(s=>s.Type==="AWS::ApiGateway::Integration"&&typeof s.Properties?.Uri=="string"&&s.Properties.Uri.includes(e)),ll=(t,e)=>Object.values(t.Resources||{}).some(s=>s.Type==="AWS::IoT::TopicRule"&&s.Properties?.TopicRulePayload?.actions?.some(n=>Object.hasOwn(n,e))),mX=t=>Object.values(t.Resources||{}).some(e=>e.Type==="AWS::ECS::Service"),v3=(t,e)=>Object.values(t.Resources||{}).some(s=>s.Type==="AWS::SNS::Subscription"&&s.Properties?.Protocol===e),C3=(t,e)=>{let s=[],n={},r={};for(let[o,a]of Object.entries(e)){let c=a.requiredResourceTypes||[];if(c.length!==0){r[o]=c.length;for(let u of c)n[u]||(n[u]=[]),n[u].push(o)}}let i={};for(let o of Object.values(t.Resources||{})){let a=o.Type,c=n[a];if(c){for(let u of c)if(i[u]=(i[u]||0)+1,i[u]===r[u]){let l=e[u],d=!0;switch(u){case"aws-s3-lambda":d=pX(t)||x3(t);break;case"aws-dynamodbstreams-lambda":d=x3(t);break;case"aws-eventbridge-lambda":d=b3(t);break;case"aws-alb-fargate":d=S3(t,"arn:aws:ecs:");break;case"aws-alb-lambda":d=S3(t,"arn:aws:lambda:");break;case"aws-apigateway-lambda":d=fX(t);break;case"aws-apigateway-sqs":d=lm(t,"sqs");break;case"aws-apigateway-dynamodb":d=lm(t,"dynamodb");break;case"aws-apigateway-kinesisstreams":d=lm(t,"kinesis");break;case"aws-apigateway-sagemakerendpoint":d=lm(t,"sagemaker");break;case"aws-iot-lambda":d=ll(t,"lambda");break;case"aws-iot-kinesisstreams":d=ll(t,"kinesis");break;case"aws-iot-kinesisfirehose-s3":d=ll(t,"firehose");break;case"aws-iot-sqs":d=ll(t,"sqs");break;case"aws-iot-s3":d=ll(t,"s3");break;case"aws-sns-lambda":d=v3(t,"lambda");break;case"aws-sns-sqs":d=v3(t,"sqs");break;case"aws-fargate-dynamodb":case"aws-fargate-eventbridge":case"aws-fargate-kinesisfirehose":case"aws-fargate-kinesisstreams":case"aws-fargate-opensearch":case"aws-fargate-s3":case"aws-fargate-secretsmanager":case"aws-fargate-sns":case"aws-fargate-sqs":case"aws-fargate-ssmstringparameter":case"aws-fargate-stepfunctions":d=mX(t);break;case"aws-eventbridge-kinesisfirehose-s3":case"aws-eventbridge-kinesisstreams":case"aws-eventbridge-sns":case"aws-eventbridge-sqs":case"aws-eventbridge-stepfunctions":d=b3(t);break}if(!d)continue;s.push({resourceId:l.className,issue:`Possible Pattern detected: ${l.friendlyName}`,recommendation:`Consider using the AWS Solutions Construct \`${l.className}\` from \`@aws-solutions-constructs/${u}\`.`,severity:"LOW",wafPillar:"Operational Excellence",docUrl:l.documentationUrl,githubUrl:l.githubUrl,constructPath:l.className,foundBy:"cdkInsights"}),delete r[u]}}}return s}});var A3,w3=D(()=>{"use strict";SP();CP();AP();EP();IP();_P();TP();LP();MP();NP();WP();UP();GP();qP();VP();YP();QP();eL();sL();Xb();rL();oL();cL();lL();pL();mL();yL();bL();vL();DL();wL();RL();kL();FL();PL();OL();BL();$L();jL();HL();zL();KL();ZL();JL();XL();t6();n6();i6();a6();u6();d6();f6();h6();y6();v6();D6();w6();I6();_6();T6();L6();B6();$6();j6();H6();z6();Z6();J6();X6();tO();nO();iO();aO();uO();dO();fO();hO();yO();bO();vO();DO();wO();RO();kO();FO();PO();OO();BO();$O();jO();HO();zO();KO();ZO();JO();XO();t3();n3();i3();a3();eS();u3();d3();f3();h3();y3();D3();A3=()=>({iamPolicies:C6,iamPermissionBoundary:A6,iamCrossAccountTrust:S6,iamUserPolicies:R6,s3Buckets:NO,s3BucketLogging:qO,s3BucketPolicySsl:UO,s3BucketPolicySelfLockout:WO,s3IntelligentTiering:YO,s3LifecyclePolicy:GO,s3Replication:VO,securityGroups:EL,ec2InstanceType:SL,ec2PublicIp:AL,ec2SubnetAutoPublicIp:IL,natGatewayUsage:CL,ebsVolumes:dL,lambdaEnvironmentVariables:U6,lambdaMemory:G6,lambdaReservedConcurrency:N6,lambdaDeadLetterQueue:W6,lambdaRuntime:Y6,lambdaVpcNatWarning:Q6,lambdaPermission:V6,rdsEncryption:gO,rdsMultiAZ:CO,rdsPublicAccess:AO,rdsBackupRetention:pO,rdsDeletionProtection:mO,rdsLogging:xO,rdsEnhancedMonitoring:SO,dynamoDBAutoScaling:aL,dynamoDBStreams:uL,dynamoDBPitr:iL,dynamoDBEncryption:nL,cloudFrontHttpsOnly:OP,cloudFrontWafAssociation:jP,cloudFrontLogging:BP,cloudFrontTls:$P,elbDeletionProtection:YL,elbLogging:e6,elbHttpsListeners:QL,elbSecurityPolicy:s6,ecsSecrets:UL,ecsLogging:ML,ecsServiceConnectLogs:NL,ecsResources:WL,cognitoPasswordPolicy:XP,cognitoMfa:JP,cognitoAdvancedSecurity:tL,wafWebAcl:g3,wafLogging:m3,cloudWatchLogRetention:ZP,cloudWatchEncryption:KP,cloudWatchAlarms:zP,route53Dnssec:TO,route53HealthChecks:LO,route53QueryLogging:MO,elastiCacheEncryption:o6,elastiCacheAuth:r6,elastiCacheFailover:c6,ecrScanning:LL,ecrLifecycle:TL,ecrImmutableTags:_L,openSearchEncryption:cO,openSearchAccessControl:oO,openSearchLogging:lO,acmValidation:bP,backupPlans:FP,backupVault:PP,vpcFlowLogs:p3,vpcDefaultSecurityGroup:l3,kinesisEncryption:k6,kinesisRetention:F6,appSyncAuth:wP,appSyncLogging:RP,appSyncWaf:kP,eksPublicEndpoint:VL,eksEncryption:GL,eksLogging:qL,redshiftEncryption:EO,redshiftPublicAccess:_O,redshiftLogging:IO,mskEncryption:sO,mskAuth:eO,mskLogging:rO,glueEncryption:g6,glueConnections:m6,efsEncryption:fL,autoScalingGroupHealthCheck:gL,autoScalingLaunchConfigPublicIp:xL,apiGateway:vP,apiGatewayMethodAuth:DP,secretsManager:QO,cloudTrailLogging:HP,eventBridgeRules:l6,eventBusPolicy:p6,kmsKeys:P6,kmsKeyPolicySelfLockout:M6,sns:e3,snsTopicPolicySelfLockout:s3,sqs:r3,sqsQueuePolicySelfLockout:o3,stepFunctions:c3,crossResourceRelationships:am,stackArchitecture:cm,solutionsPatterns:C3})});var dl,E3,sS=D(()=>{"use strict";dl=(t={})=>{let{ttl:e=3e5,maxSize:s=1e3}=t,n=new Map,r=new Set,i=[],o=Date.now(),a=6e4,c=f=>Date.now()-f.timestamp>f.ttl,u=f=>{r.delete(f)},l=()=>{let f=0;for(let m=0;m<i.length;m++)r.has(i[m])&&(i[f++]=i[m]);i.length=f},d=()=>{let f=Date.now();if(f-o<a)return;o=f;let m=[];for(let[g,h]of n.entries())c(h)&&m.push(g);for(let g of m)n.delete(g),u(g);m.length>0&&l()},p=()=>{for(;n.size>=s&&i.length>0;){let f=i.shift();f&&r.has(f)&&(n.delete(f),r.delete(f))}};return{get(f){let m=n.get(f);if(m){if(c(m)){n.delete(f),u(f);return}return m.value}},set(f,m,g){n.size>=s*.9&&d(),p(),r.has(f)&&u(f),n.set(f,{value:m,timestamp:Date.now(),ttl:g??e}),r.add(f),i.push(f)},clear(){n.clear(),r.clear(),i.length=0},size(){return n.size},has(f){let m=n.get(f);return m?c(m)?(n.delete(f),u(f),!1):!0:!1}}},E3=(t,e={})=>{let s=dl(e);return(...n)=>{let r;try{r=JSON.stringify(n)}catch{return t(...n)}let i=s.get(r);if(i!==void 0)return i;let o=t(...n);return s.set(r,o),o}}});function pl(t,e){let s=e.split("."),n=t;for(let r of s){if(n==null||typeof n!="object")return;n=n[r]}return n}function nS(t,e){switch(t.type){case"property_exists":{let s=pl(e,t.path),n=s!=null;return t.negate?!n:n}case"property_equals":{let s=pl(e,t.path),n=JSON.stringify(s)===JSON.stringify(t.value);return t.negate?!n:n}case"property_matches":{let s=pl(e,t.path);if(typeof s!="string")return!!t.negate;let n=new RegExp(t.pattern).test(s);return t.negate?!n:n}case"property_gt":{let s=pl(e,t.path);return typeof s!="number"?!1:s>t.value}case"property_lt":{let s=pl(e,t.path);return typeof s!="number"?!1:s<t.value}case"and":return t.conditions.every(s=>nS(s,e));case"or":return t.conditions.some(s=>nS(s,e));default:return!1}}function R3(t,e,s){if(e.length===0)return{};let n={};for(let[r,i]of Object.entries(t.Resources||{}))for(let o of e)if(o.resourceTypes.some(c=>c.endsWith("*")?i.Type.startsWith(c.slice(0,-1)):i.Type===c))try{if(nS(o.condition,i)){let u=s(r,`[${o.ruleId}] ${o.description}`,o.recommendation,o.severity,o.wafPillar,"","cdkInsights");u.ruleId=o.ruleId,n[r]||(n[r]={issues:[]}),n[r].issues.push(u)}}catch(c){et.warn(`Error evaluating custom rule '${o.ruleId}' on resource '${r}'`,{error:c instanceof Error?c.message:String(c)})}return n}var I3=D(()=>{"use strict";dt()});var fl,dm=D(()=>{"use strict";fl={"iam-policies-overly-permissive":{ruleId:"iam-policies-overly-permissive",checkKey:"iamPolicies",name:"IAM Overly Permissive Policies",description:"Detects IAM policies with overly permissive actions like * wildcards.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Review IAM policies for overly broad permissions","Replace wildcard (*) actions with specific actions","Use IAM Access Analyzer to identify unused permissions"],resourceTypes:["AWS::IAM::Policy","AWS::IAM::Role","AWS::IAM::ManagedPolicy"]},"iam-permission-boundary-missing":{ruleId:"iam-permission-boundary-missing",checkKey:"iamPermissionBoundary",name:"IAM Permission Boundary Missing",description:"Detects IAM roles without permission boundaries.",severity:"LOW",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html",complianceFrameworks:["SOC2","CIS","NIST"],remediationSteps:["Create a permission boundary policy","Attach the permission boundary to IAM roles"],resourceTypes:["AWS::IAM::Role"]},"iam-cross-account-trust":{ruleId:"iam-cross-account-trust",checkKey:"iamCrossAccountTrust",name:"IAM Cross-Account Trust",description:"Detects IAM roles with cross-account trust relationships.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_aws-accounts.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Verify cross-account trust is intentional","Add conditions to restrict access (e.g., external ID)","Document the business justification"],resourceTypes:["AWS::IAM::Role"]},"iam-user-direct-policies":{ruleId:"iam-user-direct-policies",checkKey:"iamUserPolicies",name:"IAM User Direct Policies",description:"Detects IAM Users with policies attached directly (inline Policies or ManagedPolicyArns). CIS AWS Foundations 1.15 requires users to inherit permissions through groups.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#use-groups-for-permissions",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Create an IAM Group with the required policies","Add the user to the group instead of attaching policies directly","Remove Policies and ManagedPolicyArns from AWS::IAM::User resources"],resourceTypes:["AWS::IAM::User"]},"s3-bucket-public-access":{ruleId:"s3-bucket-public-access",checkKey:"s3Buckets",name:"S3 Bucket Public Access",description:"Detects S3 buckets with public access enabled.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-block-public-access.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Enable S3 Block Public Access settings","Review bucket policies for public access","Use VPC endpoints for private access"],resourceTypes:["AWS::S3::Bucket"]},"s3-intelligent-tiering":{ruleId:"s3-intelligent-tiering",checkKey:"s3IntelligentTiering",name:"S3 Intelligent Tiering",description:"Recommends S3 Intelligent Tiering for cost optimization.",severity:"LOW",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/intelligent-tiering.html",remediationSteps:["Enable S3 Intelligent-Tiering for buckets with varying access patterns","Configure archive access tiers for infrequently accessed data"],resourceTypes:["AWS::S3::Bucket"]},"s3-lifecycle-policy-missing":{ruleId:"s3-lifecycle-policy-missing",checkKey:"s3LifecyclePolicy",name:"S3 Lifecycle Policy Missing",description:"Detects S3 buckets without lifecycle policies.",severity:"MEDIUM",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html",remediationSteps:["Create lifecycle rules to transition objects to cheaper storage classes","Set expiration rules for temporary data","Use lifecycle rules to delete incomplete multipart uploads"],resourceTypes:["AWS::S3::Bucket"]},"s3-replication-missing":{ruleId:"s3-replication-missing",checkKey:"s3Replication",name:"S3 Replication Missing",description:"Detects critical S3 buckets without cross-region replication.",severity:"LOW",wafPillar:"Reliability",complianceFrameworks:["SOC2","HIPAA","NIST"],awsDocUrl:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/replication.html",remediationSteps:["Enable cross-region replication for disaster recovery","Configure replication rules for critical data"],resourceTypes:["AWS::S3::Bucket"]},"s3-bucket-access-logging-disabled":{ruleId:"s3-bucket-access-logging-disabled",checkKey:"s3BucketLogging",name:"S3 Bucket Access Logging Disabled",description:"Detects S3 buckets without server access logging configured. Required by CIS AWS Foundations 2.1.2 and useful for incident forensics.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/ServerLogs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Set LoggingConfiguration.DestinationBucketName on the bucket to capture access logs","Use a separate bucket for logs to avoid recursive logging","Configure a lifecycle rule on the log bucket to manage storage costs"],resourceTypes:["AWS::S3::Bucket"]},"s3-bucket-policy-non-ssl":{ruleId:"s3-bucket-policy-non-ssl",checkKey:"s3BucketPolicySsl",name:"S3 BucketPolicy Permits Non-SSL Requests",description:"Detects AWS::S3::BucketPolicy resources that lack a Deny statement enforcing aws:SecureTransport. Without this, the bucket accepts plain HTTP requests in addition to HTTPS.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/security-best-practices.html#enforce-tls",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Add a Deny statement with Action s3:* and Condition Bool aws:SecureTransport=false","Apply the Deny to both the bucket ARN and the bucket-objects ARN (arn/* )","Use BoolIfExists if the policy already accepts unsigned requests via specific clauses"],resourceTypes:["AWS::S3::BucketPolicy"]},"s3-bucket-policy-self-lockout":{ruleId:"s3-bucket-policy-self-lockout",checkKey:"s3BucketPolicySelfLockout",name:"S3 BucketPolicy Self-Lockout",description:"Detects AWS::S3::BucketPolicy resources containing a Deny statement on s3:DeleteBucket, s3:*, or * with a broad Principal and no NotPrincipal or aws:PrincipalArn carveout for the account root or admin role. Such a policy locks the account out of its own bucket \u2014 recovery requires breaking glass on the account root credentials, since AWS Support typically declines to intervene where customers have a self-service path via root.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-policy-language-overview.html",complianceFrameworks:["SOC2","NIST"],remediationSteps:["Add a NotPrincipal exemption for the account root (arn:aws:iam::<account>:root) or admin role(s)","Or use a Condition with StringNotEquals on aws:PrincipalArn to exempt admin role ARNs","If the Deny is intended for transport security, scope it with aws:SecureTransport rather than a blanket Deny on Principal: '*'"],resourceTypes:["AWS::S3::BucketPolicy"]},"lambda-env-sensitive-data":{ruleId:"lambda-env-sensitive-data",checkKey:"lambdaEnvironmentVariables",name:"Lambda Sensitive Environment Variables",description:"Detects Lambda functions with sensitive data in environment variables.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Move sensitive data to AWS Secrets Manager","Use SSM Parameter Store with SecureString","Enable Lambda environment variable encryption"],resourceTypes:["AWS::Lambda::Function"]},"lambda-memory-optimization":{ruleId:"lambda-memory-optimization",checkKey:"lambdaMemory",name:"Lambda Memory Optimization",description:"Detects Lambda functions with suboptimal memory configuration.",severity:"LOW",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/lambda/latest/dg/configuration-function-common.html#configuration-memory-console",remediationSteps:["Use AWS Lambda Power Tuning to find optimal memory","Consider cost vs performance tradeoffs"],resourceTypes:["AWS::Lambda::Function"]},"lambda-reserved-concurrency-missing":{ruleId:"lambda-reserved-concurrency-missing",checkKey:"lambdaReservedConcurrency",name:"Lambda Reserved Concurrency Missing",description:"Detects Lambda functions without reserved concurrency.",severity:"LOW",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html",remediationSteps:["Set reserved concurrency for critical functions","Use provisioned concurrency for latency-sensitive workloads"],resourceTypes:["AWS::Lambda::Function"]},"lambda-dlq-missing":{ruleId:"lambda-dlq-missing",checkKey:"lambdaDeadLetterQueue",name:"Lambda Dead Letter Queue Missing",description:"Detects Lambda functions without dead letter queue configuration.",severity:"MEDIUM",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html#invocation-dlq",remediationSteps:["Configure a dead letter queue (SQS or SNS)","Set up monitoring for DLQ messages","Implement retry logic for failed invocations"],resourceTypes:["AWS::Lambda::Function"]},"lambda-vpc-nat-cost":{ruleId:"lambda-vpc-nat-cost",checkKey:"lambdaVpcNatWarning",name:"Lambda VPC NAT Gateway Cost Warning",description:"Warns about potential NAT Gateway costs for VPC-attached Lambda functions.",severity:"MEDIUM",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/lambda/latest/dg/configuration-vpc.html",remediationSteps:["Use VPC endpoints instead of NAT Gateway where possible","Consider if VPC attachment is necessary","Monitor NAT Gateway data processing costs"],resourceTypes:["AWS::Lambda::Function"]},"lambda-permission-public":{ruleId:"lambda-permission-public",checkKey:"lambdaPermission",name:"Lambda Permission Permits Public Access",description:"Detects AWS::Lambda::Permission and AWS::Lambda::LayerVersionPermission resources that grant invoke / use rights with a wildcard Principal, or grant a service principal without a SourceArn / SourceAccount / PrincipalOrgID restriction (confused-deputy risk).",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Replace wildcard Principal with a specific 12-digit AWS account ID or {Ref: AWS::AccountId}","For service principals, set SourceArn to the specific resource that may invoke the function","For S3 service principal, set SourceAccount to your AWS account ID","For LayerVersionPermission, prefer OrganizationId over wildcard Principal"],resourceTypes:["AWS::Lambda::Permission","AWS::Lambda::LayerVersionPermission"]},"dynamodb-autoscaling-missing":{ruleId:"dynamodb-autoscaling-missing",checkKey:"dynamoDBAutoScaling",name:"DynamoDB Auto Scaling Missing",description:"Detects DynamoDB tables without auto-scaling enabled.",severity:"MEDIUM",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AutoScaling.html",remediationSteps:["Enable DynamoDB auto-scaling or use on-demand capacity","Set appropriate minimum and maximum capacity units"],resourceTypes:["AWS::DynamoDB::Table"]},"dynamodb-streams-disabled":{ruleId:"dynamodb-streams-disabled",checkKey:"dynamoDBStreams",name:"DynamoDB Streams Disabled",description:"Detects DynamoDB tables without streams enabled.",severity:"LOW",wafPillar:"Operational Excellence",awsDocUrl:"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.html",remediationSteps:["Enable DynamoDB Streams for change data capture","Consider point-in-time recovery for data protection"],resourceTypes:["AWS::DynamoDB::Table"]},"dynamodb-encryption-aws-owned-key":{ruleId:"dynamodb-encryption-aws-owned-key",checkKey:"dynamoDBEncryption",name:"DynamoDB Table Uses AWS-Owned Encryption Key",description:"Detects AWS::DynamoDB::Table resources without SSESpecification.SSEEnabled=true. DynamoDB always encrypts at rest, but the default AWS-owned key cannot be inspected, audited, or rotated by the customer \u2014 inadequate for HIPAA / PCI-DSS / FedRAMP workloads.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/encryption.howitworks.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set SSESpecification.SSEEnabled to true on the table","Provide SSESpecification.KMSMasterKeyId pointing at a customer-managed KMS key","Verify the KMS key has rotation enabled (kms-key-rotation-disabled covers this)"],resourceTypes:["AWS::DynamoDB::Table"]},"dynamodb-pitr-disabled":{ruleId:"dynamodb-pitr-disabled",checkKey:"dynamoDBPitr",name:"DynamoDB Point-in-Time Recovery Disabled",description:"Detects DynamoDB tables without Point-in-Time Recovery enabled. PITR provides continuous backups for the last 35 days and is required for SOC2 / HIPAA data resilience.",severity:"MEDIUM",wafPillar:"Reliability",complianceFrameworks:["SOC2","HIPAA","NIST"],awsDocUrl:"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery.html",remediationSteps:["Set PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled to true on the table","Verify the AWS region supports PITR for your table type (Provisioned / On-Demand)"],resourceTypes:["AWS::DynamoDB::Table"]},"rds-encryption-disabled":{ruleId:"rds-encryption-disabled",checkKey:"rdsEncryption",name:"RDS Encryption Disabled",description:"Detects RDS instances without encryption at rest.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.Encryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Enable encryption for new RDS instances","For existing instances, create encrypted snapshot and restore"],resourceTypes:["AWS::RDS::DBInstance","AWS::RDS::DBCluster"]},"rds-multi-az-disabled":{ruleId:"rds-multi-az-disabled",checkKey:"rdsMultiAZ",name:"RDS Multi-AZ Disabled",description:"Detects RDS instances without Multi-AZ deployment.",severity:"MEDIUM",wafPillar:"Reliability",complianceFrameworks:["SOC2","HIPAA","NIST"],awsDocUrl:"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.html",remediationSteps:["Enable Multi-AZ for production databases","Consider Aurora for automatic multi-AZ"],resourceTypes:["AWS::RDS::DBInstance"]},"rds-publicly-accessible":{ruleId:"rds-publicly-accessible",checkKey:"rdsPublicAccess",name:"RDS Publicly Accessible",description:"Detects RDS instances that are publicly accessible.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_VPC.WorkingWithRDSInstanceinaVPC.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Set PubliclyAccessible to false","Use VPC security groups to control access","Access databases through bastion hosts or VPN"],resourceTypes:["AWS::RDS::DBInstance"]},"rds-backup-retention-low":{ruleId:"rds-backup-retention-low",checkKey:"rdsBackupRetention",name:"RDS Backup Retention Low",description:"Detects RDS instances with insufficient backup retention.",severity:"MEDIUM",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithAutomatedBackups.html",complianceFrameworks:["SOC2","HIPAA","NIST"],remediationSteps:["Set backup retention period to at least 7 days","Consider longer retention for compliance requirements","Enable cross-region backup replication"],resourceTypes:["AWS::RDS::DBInstance","AWS::RDS::DBCluster"]},"rds-deletion-protection-disabled":{ruleId:"rds-deletion-protection-disabled",checkKey:"rdsDeletionProtection",name:"RDS Deletion Protection Disabled",description:"Detects RDS instances without deletion protection.",severity:"MEDIUM",wafPillar:"Reliability",complianceFrameworks:["SOC2","HIPAA","NIST"],awsDocUrl:"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_DeleteInstance.html",remediationSteps:["Enable deletion protection for production databases","Use CloudFormation DeletionPolicy: Retain"],resourceTypes:["AWS::RDS::DBInstance","AWS::RDS::DBCluster"]},"rds-logging-disabled":{ruleId:"rds-logging-disabled",checkKey:"rdsLogging",name:"RDS Logging Disabled",description:"Detects RDS DBInstance and DBCluster resources without EnableCloudwatchLogsExports configured. Engine logs (error, slow query, audit) are not exported to CloudWatch for retention or analysis.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set EnableCloudwatchLogsExports to the engine's relevant log types (e.g. ['error','slowquery'] for MySQL, ['postgresql'] for PostgreSQL)","Configure a CloudWatch Logs retention policy on the resulting log group","For Aurora, enable both DBCluster and per-instance log exports"],resourceTypes:["AWS::RDS::DBInstance","AWS::RDS::DBCluster"]},"rds-enhanced-monitoring-disabled":{ruleId:"rds-enhanced-monitoring-disabled",checkKey:"rdsEnhancedMonitoring",name:"RDS Enhanced Monitoring Disabled",description:"Detects RDS instances without enhanced monitoring (MonitoringInterval missing or set to 0). OS-level metrics are not published to CloudWatch Logs.",severity:"MEDIUM",wafPillar:"Operational Excellence",awsDocUrl:"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Monitoring.OS.html",remediationSteps:["Set MonitoringInterval to one of 1, 5, 10, 15, 30, or 60 (seconds)","Provide MonitoringRoleArn pointing at an IAM role with AmazonRDSEnhancedMonitoringRole attached"],resourceTypes:["AWS::RDS::DBInstance"]},"ec2-instance-type-outdated":{ruleId:"ec2-instance-type-outdated",checkKey:"ec2InstanceType",name:"EC2 Instance Type Outdated",description:"Detects EC2 instances using older generation instance types.",severity:"LOW",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html",remediationSteps:["Upgrade to current generation instance types","Use AWS Compute Optimizer for recommendations"],resourceTypes:["AWS::EC2::Instance"]},"nat-gateway-usage":{ruleId:"nat-gateway-usage",checkKey:"natGatewayUsage",name:"NAT Gateway Usage",description:"Identifies NAT Gateway usage for cost awareness.",severity:"LOW",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html",remediationSteps:["Consider VPC endpoints to reduce NAT Gateway traffic","Use NAT instances for lower traffic volumes"],resourceTypes:["AWS::EC2::NatGateway"]},"security-group-unrestricted-ingress":{ruleId:"security-group-unrestricted-ingress",checkKey:"securityGroups",name:"Security Group Unrestricted Ingress",description:"Detects security groups with unrestricted ingress (0.0.0.0/0).",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Restrict ingress to specific IP ranges","Use security group references for internal traffic","Implement least privilege network access"],resourceTypes:["AWS::EC2::SecurityGroup"]},"ebs-volume-unencrypted":{ruleId:"ebs-volume-unencrypted",checkKey:"ebsVolumes",name:"EBS Volume Unencrypted",description:"Detects EBS volumes without encryption.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Enable EBS encryption by default in account settings","Use KMS customer managed keys for additional control"],resourceTypes:["AWS::EC2::Volume"]},"ec2-subnet-auto-public-ip":{ruleId:"ec2-subnet-auto-public-ip",checkKey:"ec2SubnetAutoPublicIp",name:"EC2 Subnet Auto-Assigns Public IPs",description:"Detects AWS::EC2::Subnet resources with MapPublicIpOnLaunch=true. Instances launched into the subnet inherit a public IP by default, which makes them internet-reachable without an explicit opt-in at the ENI level.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/vpc/latest/userguide/vpc-ip-addressing.html#subnet-public-ip",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set MapPublicIpOnLaunch to false unless this is intentionally a public subnet","Have instances opt into a public IP via the ENI configuration when needed","Use VPC endpoints / NAT for outbound access from private subnets"],resourceTypes:["AWS::EC2::Subnet"]},"ec2-instance-public-ip":{ruleId:"ec2-instance-public-ip",checkKey:"ec2PublicIp",name:"EC2 Instance Public IP",description:"Detects EC2 instances whose NetworkInterfaces specify AssociatePublicIpAddress=true, exposing the instance directly to the internet.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-instance-addressing.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Set AssociatePublicIpAddress to false on the NetworkInterface","Place the instance in a private subnet and use a NAT Gateway / VPC endpoint for outbound","Use an ALB / NLB in a public subnet to front the workload instead"],resourceTypes:["AWS::EC2::Instance"]},"cloudfront-https-only":{ruleId:"cloudfront-https-only",checkKey:"cloudFrontHttpsOnly",name:"CloudFront HTTPS Only",description:"Detects CloudFront distributions allowing HTTP traffic.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-https.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set ViewerProtocolPolicy to https-only or redirect-to-https","Configure custom SSL certificate"],resourceTypes:["AWS::CloudFront::Distribution"]},"cloudfront-waf-missing":{ruleId:"cloudfront-waf-missing",checkKey:"cloudFrontWafAssociation",name:"CloudFront WAF Missing",description:"Detects CloudFront distributions without WAF association.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-awswaf.html",complianceFrameworks:["SOC2","PCI-DSS","NIST"],remediationSteps:["Associate AWS WAF web ACL with CloudFront distribution","Configure WAF rules for common attack patterns"],resourceTypes:["AWS::CloudFront::Distribution"]},"cloudfront-logging-disabled":{ruleId:"cloudfront-logging-disabled",checkKey:"cloudFrontLogging",name:"CloudFront Logging Disabled",description:"Detects CloudFront distributions without access logging.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable standard logging to S3","Consider real-time logs for detailed analysis"],resourceTypes:["AWS::CloudFront::Distribution"]},"cloudfront-tls-outdated":{ruleId:"cloudfront-tls-outdated",checkKey:"cloudFrontTls",name:"CloudFront TLS Outdated",description:"Detects CloudFront distributions using outdated TLS versions.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/secure-connections-supported-viewer-protocols-ciphers.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set MinimumProtocolVersion to TLSv1.2_2021 or higher","Use a custom SSL certificate"],resourceTypes:["AWS::CloudFront::Distribution"]},"elb-deletion-protection-disabled":{ruleId:"elb-deletion-protection-disabled",checkKey:"elbDeletionProtection",name:"ELB Deletion Protection Disabled",description:"Detects load balancers without deletion protection.",severity:"MEDIUM",wafPillar:"Reliability",complianceFrameworks:["SOC2","HIPAA","NIST"],awsDocUrl:"https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#deletion-protection",remediationSteps:["Enable deletion protection for production load balancers","Use CloudFormation DeletionPolicy: Retain"],resourceTypes:["AWS::ElasticLoadBalancingV2::LoadBalancer"]},"elb-logging-disabled":{ruleId:"elb-logging-disabled",checkKey:"elbLogging",name:"ELB Logging Disabled",description:"Detects load balancers without access logging.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable access logging to S3","Configure log retention policy"],resourceTypes:["AWS::ElasticLoadBalancingV2::LoadBalancer"]},"elb-https-listeners-missing":{ruleId:"elb-https-listeners-missing",checkKey:"elbHttpsListeners",name:"ELB HTTPS Listeners Missing",description:"Detects load balancers with HTTP listeners not redirecting to HTTPS.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Add HTTPS listener with valid SSL certificate","Configure HTTP to HTTPS redirect"],resourceTypes:["AWS::ElasticLoadBalancingV2::Listener"]},"elb-security-policy-outdated":{ruleId:"elb-security-policy-outdated",checkKey:"elbSecurityPolicy",name:"ELB Security Policy Outdated",description:"Detects load balancers using outdated TLS security policies.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Update to ELBSecurityPolicy-TLS13-1-2-2021-06 or newer","Remove support for deprecated protocols"],resourceTypes:["AWS::ElasticLoadBalancingV2::Listener"]},"ecs-secrets-plaintext":{ruleId:"ecs-secrets-plaintext",checkKey:"ecsSecrets",name:"ECS Secrets in Plaintext",description:"Detects ECS task definitions with sensitive data in plaintext environment variables.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Use secrets property with Secrets Manager ARN","Use SSM Parameter Store SecureString"],resourceTypes:["AWS::ECS::TaskDefinition"]},"ecs-logging-disabled":{ruleId:"ecs-logging-disabled",checkKey:"ecsLogging",name:"ECS Logging Disabled",description:"Detects ECS task definitions without logging configured.",severity:"MEDIUM",wafPillar:"Operational Excellence",awsDocUrl:"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using_awslogs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Configure awslogs log driver","Set up CloudWatch log groups with retention"],resourceTypes:["AWS::ECS::TaskDefinition"]},"ecs-service-connect-access-logs-missing":{ruleId:"ecs-service-connect-access-logs-missing",checkKey:"ecsServiceConnectLogs",name:"ECS Service Connect Access Logs Missing",description:"Detects ECS services with Service Connect enabled but no access log configuration, leaving inter-service traffic unaudited.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-connect-logging.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set ServiceConnectConfiguration.LogConfiguration with a LogDriver such as awslogs","Send Service Connect logs to a CloudWatch log group with a retention policy","Confirm log group encryption is configured for sensitive workloads"],resourceTypes:["AWS::ECS::Service"]},"ecs-resources-missing":{ruleId:"ecs-resources-missing",checkKey:"ecsResources",name:"ECS Resource Limits Missing",description:"Detects ECS task definitions without CPU/memory limits.",severity:"LOW",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_size",remediationSteps:["Set CPU and memory at task level for Fargate","Set container-level memory limits for EC2"],resourceTypes:["AWS::ECS::TaskDefinition"]},"cognito-password-policy-weak":{ruleId:"cognito-password-policy-weak",checkKey:"cognitoPasswordPolicy",name:"Cognito Password Policy Weak",description:"Detects Cognito user pools with weak password policies.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-policies.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set minimum password length to at least 12 characters","Require uppercase, lowercase, numbers, and symbols"],resourceTypes:["AWS::Cognito::UserPool"]},"cognito-mfa-disabled":{ruleId:"cognito-mfa-disabled",checkKey:"cognitoMfa",name:"Cognito MFA Disabled",description:"Detects Cognito user pools without MFA enabled.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-mfa.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable MFA (OPTIONAL or ON)","Configure SMS or TOTP as MFA method"],resourceTypes:["AWS::Cognito::UserPool"]},"cognito-advanced-security-disabled":{ruleId:"cognito-advanced-security-disabled",checkKey:"cognitoAdvancedSecurity",name:"Cognito Advanced Security Disabled",description:"Detects Cognito user pools without advanced security features.",severity:"LOW",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-settings-advanced-security.html",complianceFrameworks:["SOC2","NIST"],remediationSteps:["Enable advanced security mode (AUDIT or ENFORCED)","Configure risk-based adaptive authentication"],resourceTypes:["AWS::Cognito::UserPool"]},"api-gateway-method-auth-missing":{ruleId:"api-gateway-method-auth-missing",checkKey:"apiGatewayMethodAuth",name:"API Gateway Method Has No Authorization",description:"Detects AWS::ApiGateway::Method and AWS::ApiGatewayV2::Route resources where AuthorizationType is missing or NONE (excluding OPTIONS preflight). Public-by-default endpoints expose backend Lambdas to anyone on the internet.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/apigateway/latest/developerguide/permissions.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set AuthorizationType to AWS_IAM, COGNITO_USER_POOLS, or CUSTOM (REST APIs)","Use JWT or AWS_IAM AuthorizationType for HTTP APIs (v2)","If the route is intentionally public (e.g. webhook receiver), prefer api-key + WAF rate limiting and suppress this rule explicitly"],resourceTypes:["AWS::ApiGateway::Method","AWS::ApiGatewayV2::Route"]},"api-gateway-logging-disabled":{ruleId:"api-gateway-logging-disabled",checkKey:"apiGateway",name:"API Gateway Logging Disabled",description:"Detects API Gateway stages without logging enabled.",severity:"MEDIUM",wafPillar:"Operational Excellence",awsDocUrl:"https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-logging.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable CloudWatch logging for API stages","Configure access logging for request/response details"],resourceTypes:["AWS::ApiGateway::Stage","AWS::ApiGatewayV2::Stage"]},"secrets-manager-rotation-disabled":{ruleId:"secrets-manager-rotation-disabled",checkKey:"secretsManager",name:"Secrets Manager Rotation Disabled",description:"Detects secrets without automatic rotation configured.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable automatic rotation","Set rotation schedule (e.g., every 30 days)"],resourceTypes:["AWS::SecretsManager::Secret"]},"cloudtrail-logging-disabled":{ruleId:"cloudtrail-logging-disabled",checkKey:"cloudTrailLogging",name:"CloudTrail Logging Disabled",description:"Detects CloudTrail trails with logging disabled.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-getting-started.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Ensure IsLogging is enabled","Configure multi-region trails","Enable log file validation"],resourceTypes:["AWS::CloudTrail::Trail"]},"eventbridge-bus-policy-wildcard-principal":{ruleId:"eventbridge-bus-policy-wildcard-principal",checkKey:"eventBusPolicy",name:"EventBridge Bus Policy Allows Wildcard Principal",description:"Detects AWS::Events::EventBusPolicy with an Allow statement targeting Principal=* (or AWS=*) without a Condition restricting access. Without the condition, any AWS account can publish events to the bus.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-bus-perms.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Replace wildcard Principal with specific 12-digit AWS account IDs","Or scope the policy with a Condition such as aws:PrincipalOrgID","Verify the StatementId is descriptive \u2014 easier to audit later"],resourceTypes:["AWS::Events::EventBusPolicy"]},"eventbridge-dlq-missing":{ruleId:"eventbridge-dlq-missing",checkKey:"eventBridgeRules",name:"EventBridge DLQ Missing",description:"Detects EventBridge rules without dead letter queue.",severity:"LOW",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-rule-dlq.html",remediationSteps:["Configure dead letter queue for failed event delivery","Set up monitoring for DLQ messages"],resourceTypes:["AWS::Events::Rule"]},"kms-key-rotation-disabled":{ruleId:"kms-key-rotation-disabled",checkKey:"kmsKeys",name:"KMS Key Rotation Disabled",description:"Detects KMS keys without automatic rotation.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Enable automatic key rotation","Key rotation occurs annually"],resourceTypes:["AWS::KMS::Key"]},"kms-key-policy-self-lockout":{ruleId:"kms-key-policy-self-lockout",checkKey:"kmsKeyPolicySelfLockout",name:"KMS Key Policy Self-Lockout",description:"Detects AWS::KMS::Key resources whose KeyPolicy contains a Deny statement on kms:*, kms:PutKeyPolicy, or * with a broad Principal and no carveout for the account root or admin role. Such a policy locks the account out of its own key \u2014 recovery requires breaking glass on the account root credentials AND scheduling a 7-30 day key deletion (which does not actually let you recover the key, just remove it). Effectively unrecoverable for any data the key has encrypted; AWS Support typically declines to intervene where customers have a self-service path via root.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html",complianceFrameworks:["SOC2","NIST"],remediationSteps:["Keep the auto-injected root Allow statement (CDK's defaultKeyPolicy) intact, or add an explicit Allow on Principal: { AWS: 'arn:aws:iam::<account>:root' } for Action: kms:*","Or add a NotPrincipal exemption for the account root or admin role(s)","Or use a Condition with StringNotEquals on aws:PrincipalArn to exempt admin role ARNs"],resourceTypes:["AWS::KMS::Key"]},"sns-encryption-disabled":{ruleId:"sns-encryption-disabled",checkKey:"sns",name:"SNS Encryption Disabled",description:"Detects SNS topics without encryption.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/sns/latest/dg/sns-server-side-encryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable server-side encryption with KMS","Use customer managed keys for additional control"],resourceTypes:["AWS::SNS::Topic"]},"sqs-encryption-disabled":{ruleId:"sqs-encryption-disabled",checkKey:"sqs",name:"SQS Encryption Disabled",description:"Detects SQS queues without encryption.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-server-side-encryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable server-side encryption with KMS","Use SQS-managed keys (SSE-SQS) or customer managed keys"],resourceTypes:["AWS::SQS::Queue"]},"sqs-queue-policy-self-lockout":{ruleId:"sqs-queue-policy-self-lockout",checkKey:"sqsQueuePolicySelfLockout",name:"SQS QueuePolicy Self-Lockout",description:"Detects AWS::SQS::QueuePolicy resources containing a Deny statement on sqs:DeleteQueue, sqs:RemovePermission, sqs:*, or * with a broad Principal and no NotPrincipal or aws:PrincipalArn carveout for the account root or admin role. Such a policy locks the account out of its own queue \u2014 recovery requires breaking glass on the account root credentials to remove the queue policy, or delete-and-recreate the queue if nothing else depends on its ARN. In event-driven systems that is often a multi-stack rebuild.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-access-policy-language-basic-structure.html",complianceFrameworks:["SOC2","NIST"],remediationSteps:["Add a NotPrincipal exemption for the account root (arn:aws:iam::<account>:root) or admin role(s)","Or use a Condition with StringNotEquals on aws:PrincipalArn to exempt admin role ARNs","If the Deny is intended to scope to AWS services, use aws:PrincipalIsAWSService rather than a blanket Deny on Principal: '*'"],resourceTypes:["AWS::SQS::QueuePolicy"]},"sns-topic-policy-self-lockout":{ruleId:"sns-topic-policy-self-lockout",checkKey:"snsTopicPolicySelfLockout",name:"SNS TopicPolicy Self-Lockout",description:"Detects AWS::SNS::TopicPolicy resources containing a Deny statement on sns:DeleteTopic, sns:RemovePermission, sns:*, or * with a broad Principal and no NotPrincipal or aws:PrincipalArn carveout for the account root or admin role. Such a policy locks the account out of its own topic \u2014 recovery requires breaking glass on the account root credentials to remove the topic policy, or delete-and-recreate the topic if no subscribers depend on its ARN. In fan-out architectures that is often a multi-stack rebuild.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/sns/latest/dg/sns-access-policy-language-key-concepts.html",complianceFrameworks:["SOC2","NIST"],remediationSteps:["Add a NotPrincipal exemption for the account root (arn:aws:iam::<account>:root) or admin role(s)","Or use a Condition with StringNotEquals on aws:PrincipalArn to exempt admin role ARNs","If the Deny is intended to scope to AWS services, use aws:PrincipalIsAWSService rather than a blanket Deny on Principal: '*'"],resourceTypes:["AWS::SNS::TopicPolicy"]},"stepfunctions-logging-disabled":{ruleId:"stepfunctions-logging-disabled",checkKey:"stepFunctions",name:"Step Functions Logging Disabled",description:"Detects Step Functions state machines without logging.",severity:"MEDIUM",wafPillar:"Operational Excellence",awsDocUrl:"https://docs.aws.amazon.com/step-functions/latest/dg/cw-logs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable CloudWatch Logs for state machine execution","Set appropriate log level (ALL, ERROR, FATAL, OFF)"],resourceTypes:["AWS::StepFunctions::StateMachine"]},"acm-certificate-email-validation":{ruleId:"acm-certificate-email-validation",checkKey:"acmValidation",name:"ACM Certificate Validation Hardening",description:"Detects ACM certificates using email validation or with certificate transparency logging disabled.",severity:"LOW",wafPillar:"Security",complianceFrameworks:["SOC2","NIST"],awsDocUrl:"https://docs.aws.amazon.com/acm/latest/userguide/dns-validation.html",remediationSteps:["Use DNS validation for automated certificate renewal","Enable certificate transparency logging to detect misissuance"],resourceTypes:["AWS::CertificateManager::Certificate"]},"appsync-api-key-auth":{ruleId:"appsync-api-key-auth",checkKey:"appSyncAuth",name:"AppSync API Key Authentication",description:"Detects AppSync APIs using API key authentication or lacking additional authentication providers.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Use AWS_IAM, Cognito User Pools, or OIDC for production workloads","Configure AdditionalAuthenticationProviders for client flexibility"],resourceTypes:["AWS::AppSync::GraphQLApi"]},"appsync-logging-disabled":{ruleId:"appsync-logging-disabled",checkKey:"appSyncLogging",name:"AppSync Logging Disabled",description:"Detects AppSync APIs without logging, field-level logging, or X-Ray tracing.",severity:"MEDIUM",wafPillar:"Operational Excellence",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],awsDocUrl:"https://docs.aws.amazon.com/appsync/latest/devguide/monitoring.html",remediationSteps:["Configure LogConfig to capture request/response logs in CloudWatch","Set FieldLogLevel to ERROR or ALL for resolver execution detail","Enable XrayEnabled for distributed tracing"],resourceTypes:["AWS::AppSync::GraphQLApi"]},"appsync-waf-missing":{ruleId:"appsync-waf-missing",checkKey:"appSyncWaf",name:"AppSync WAF Missing",description:"Detects AppSync APIs without an associated AWS WAF WebACL.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/appsync/latest/devguide/WAF-Integration.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Associate a WAFv2 WebACL with the AppSync API","Define rules to protect against common web exploits"],resourceTypes:["AWS::AppSync::GraphQLApi","AWS::WAFv2::WebACLAssociation"]},"backup-plan-misconfigured":{ruleId:"backup-plan-misconfigured",checkKey:"backupPlans",name:"Backup Plan Misconfigured",description:"Detects Backup plan rules without cross-region copy or lifecycle configuration.",severity:"LOW",wafPillar:"Reliability",complianceFrameworks:["SOC2","HIPAA","NIST"],awsDocUrl:"https://docs.aws.amazon.com/aws-backup/latest/devguide/about-backup-plans.html",remediationSteps:["Add CopyActions to replicate backups cross-region for DR","Set DeleteAfterDays / MoveToColdStorageAfterDays to manage retention and cost"],resourceTypes:["AWS::Backup::BackupPlan"]},"backup-vault-hardening":{ruleId:"backup-vault-hardening",checkKey:"backupVault",name:"Backup Vault Hardening",description:"Detects Backup vaults using AWS-managed keys or without a vault lock for compliance.",severity:"LOW",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/aws-backup/latest/devguide/vaultlock.html",complianceFrameworks:["SOC2","HIPAA","NIST"],remediationSteps:["Specify a customer-managed KMS key via EncryptionKeyArn","Add a BackupVaultLock to enforce retention and prevent deletion"],resourceTypes:["AWS::Backup::BackupVault","AWS::Backup::BackupVaultLock"]},"cloudwatch-alarm-actions-missing":{ruleId:"cloudwatch-alarm-actions-missing",checkKey:"cloudWatchAlarms",name:"CloudWatch Alarm Actions Missing",description:"Detects CloudWatch Alarms without alarm actions or missing-data handling.",severity:"MEDIUM",wafPillar:"Operational Excellence",awsDocUrl:"https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html",remediationSteps:["Add AlarmActions (SNS, Lambda, SSM) for state-change notifications","Set TreatMissingData to define behaviour for missing data points"],resourceTypes:["AWS::CloudWatch::Alarm"]},"cloudwatch-logs-encryption-disabled":{ruleId:"cloudwatch-logs-encryption-disabled",checkKey:"cloudWatchEncryption",name:"CloudWatch Logs Encryption Disabled",description:"Detects CloudWatch Log Groups not encrypted with a customer-managed KMS key.",severity:"LOW",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/encrypt-log-data-kms.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set KmsKeyId on the LogGroup to encrypt with a customer-managed key"],resourceTypes:["AWS::Logs::LogGroup"]},"cloudwatch-logs-retention-missing":{ruleId:"cloudwatch-logs-retention-missing",checkKey:"cloudWatchLogRetention",name:"CloudWatch Logs Retention Missing",description:"Detects CloudWatch Log Groups without an explicit retention period (logs retained indefinitely).",severity:"MEDIUM",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html",remediationSteps:["Set RetentionInDays to control storage cost (30\u201390 days for ops, longer for compliance)"],resourceTypes:["AWS::Logs::LogGroup"]},"ecr-mutable-tags":{ruleId:"ecr-mutable-tags",checkKey:"ecrImmutableTags",name:"ECR Mutable Image Tags",description:"Detects ECR repositories that allow image tags to be overwritten.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-tag-mutability.html",complianceFrameworks:["SOC2","PCI-DSS","NIST"],remediationSteps:["Set ImageTagMutability to IMMUTABLE"],resourceTypes:["AWS::ECR::Repository"]},"ecr-lifecycle-policy-missing":{ruleId:"ecr-lifecycle-policy-missing",checkKey:"ecrLifecycle",name:"ECR Lifecycle Policy Missing",description:"Detects ECR repositories without a lifecycle policy to clean up old images.",severity:"MEDIUM",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/AmazonECR/latest/userguide/LifecyclePolicies.html",remediationSteps:["Define a LifecyclePolicy to expire untagged or excess image versions"],resourceTypes:["AWS::ECR::Repository"]},"ecr-scan-on-push-disabled":{ruleId:"ecr-scan-on-push-disabled",checkKey:"ecrScanning",name:"ECR Scan-on-Push Disabled",description:"Detects ECR repositories without image vulnerability scanning on push.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable ScanOnPush in ImageScanningConfiguration","Or use enhanced scanning at the registry level"],resourceTypes:["AWS::ECR::Repository"]},"eks-secrets-encryption-disabled":{ruleId:"eks-secrets-encryption-disabled",checkKey:"eksEncryption",name:"EKS Secrets Encryption Disabled",description:"Detects EKS clusters without envelope encryption for Kubernetes secrets in etcd.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/eks/latest/userguide/enable-kms.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:['Configure EncryptionConfig with a KMS key referencing resources: ["secrets"]'],resourceTypes:["AWS::EKS::Cluster"]},"eks-control-plane-logging-disabled":{ruleId:"eks-control-plane-logging-disabled",checkKey:"eksLogging",name:"EKS Control Plane Logging Disabled",description:"Detects EKS clusters with no control plane log types enabled.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable api, audit, authenticator, controllerManager, and scheduler logs"],resourceTypes:["AWS::EKS::Cluster"]},"eks-public-endpoint-unrestricted":{ruleId:"eks-public-endpoint-unrestricted",checkKey:"eksPublicEndpoint",name:"EKS Public Endpoint Unrestricted",description:"Detects EKS clusters with the API endpoint reachable from 0.0.0.0/0 or only via the public network.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable EndpointPrivateAccess for in-VPC node communication","Restrict PublicAccessCidrs to known administrative IP ranges"],resourceTypes:["AWS::EKS::Cluster"]},"elasticache-auth-token-missing":{ruleId:"elasticache-auth-token-missing",checkKey:"elastiCacheAuth",name:"ElastiCache AUTH Token Missing",description:"Detects Redis replication groups with transit encryption but no AUTH token configured.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/auth.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set AuthToken to require Redis client authentication"],resourceTypes:["AWS::ElastiCache::ReplicationGroup"]},"elasticache-encryption-disabled":{ruleId:"elasticache-encryption-disabled",checkKey:"elastiCacheEncryption",name:"ElastiCache Encryption Disabled",description:"Detects ElastiCache clusters without at-rest or in-transit encryption.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/at-rest-encryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set AtRestEncryptionEnabled: true","Set TransitEncryptionEnabled: true"],resourceTypes:["AWS::ElastiCache::ReplicationGroup","AWS::ElastiCache::CacheCluster"]},"elasticache-failover-disabled":{ruleId:"elasticache-failover-disabled",checkKey:"elastiCacheFailover",name:"ElastiCache Automatic Failover Disabled",description:"Detects ElastiCache replication groups without automatic failover or Multi-AZ.",severity:"MEDIUM",wafPillar:"Reliability",complianceFrameworks:["SOC2","HIPAA"],awsDocUrl:"https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/AutoFailover.html",remediationSteps:["Enable AutomaticFailoverEnabled","Enable MultiAZEnabled to span availability zones"],resourceTypes:["AWS::ElastiCache::ReplicationGroup"]},"glue-connection-network-isolation":{ruleId:"glue-connection-network-isolation",checkKey:"glueConnections",name:"Glue Connection Network Isolation",description:"Detects Glue JDBC connections without VPC subnet placement or SSL enforcement.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/glue/latest/dg/setup-vpc-for-glue-access.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set PhysicalConnectionRequirements with SubnetId and SecurityGroupIdList","Include SSL parameters in the JDBC connection URL"],resourceTypes:["AWS::Glue::Connection"]},"glue-job-encryption-missing":{ruleId:"glue-job-encryption-missing",checkKey:"glueEncryption",name:"Glue Job Encryption Missing",description:"Detects Glue jobs without an attached SecurityConfiguration for encrypting bookmarks, S3 data, and CloudWatch logs.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/glue/latest/dg/encryption-security-configuration.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Create a SecurityConfiguration enabling KMS encryption for all targets","Reference it via the job's SecurityConfiguration property"],resourceTypes:["AWS::Glue::Job"]},"kinesis-encryption-disabled":{ruleId:"kinesis-encryption-disabled",checkKey:"kinesisEncryption",name:"Kinesis Encryption Disabled",description:"Detects Kinesis Data Streams without server-side KMS encryption.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/streams/latest/dev/server-side-encryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set StreamEncryption with EncryptionType: KMS and a KeyId"],resourceTypes:["AWS::Kinesis::Stream"]},"kinesis-retention-minimum":{ruleId:"kinesis-retention-minimum",checkKey:"kinesisRetention",name:"Kinesis Minimum Retention",description:"Detects Kinesis Data Streams using the default 24-hour retention period.",severity:"LOW",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/streams/latest/dev/kinesis-extended-retention.html",remediationSteps:["Increase RetentionPeriodHours to support replay/reprocessing during incidents"],resourceTypes:["AWS::Kinesis::Stream"]},"lambda-runtime-deprecated":{ruleId:"lambda-runtime-deprecated",checkKey:"lambdaRuntime",name:"Lambda Deprecated Runtime",description:"Detects Lambda functions using runtimes that have reached or are approaching end-of-life.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html",complianceFrameworks:["SOC2","PCI-DSS","NIST"],remediationSteps:["Upgrade to a currently supported runtime","Track AWS Lambda runtime deprecation announcements"],resourceTypes:["AWS::Lambda::Function"]},"msk-client-authentication-missing":{ruleId:"msk-client-authentication-missing",checkKey:"mskAuth",name:"MSK Client Authentication Missing",description:"Detects MSK clusters without client authentication or that allow unauthenticated access.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/msk/latest/developerguide/kafka_apis_iam.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable SASL/SCRAM, IAM auth, or mTLS in ClientAuthentication","Disable Unauthenticated access"],resourceTypes:["AWS::MSK::Cluster"]},"msk-encryption-weak":{ruleId:"msk-encryption-weak",checkKey:"mskEncryption",name:"MSK Encryption Weak",description:"Detects MSK clusters without TLS for client-broker traffic, without inter-broker encryption, or using AWS-managed keys for at-rest encryption.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/msk/latest/developerguide/msk-encryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set ClientBroker to TLS in EncryptionInTransit","Set InCluster to true in EncryptionInTransit","Specify DataVolumeKMSKeyId for at-rest encryption"],resourceTypes:["AWS::MSK::Cluster"]},"msk-broker-logging-disabled":{ruleId:"msk-broker-logging-disabled",checkKey:"mskLogging",name:"MSK Broker Logging Disabled",description:"Detects MSK clusters without broker logs configured.",severity:"MEDIUM",wafPillar:"Operational Excellence",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],awsDocUrl:"https://docs.aws.amazon.com/msk/latest/developerguide/msk-logging.html",remediationSteps:["Enable broker logs to CloudWatch Logs, Firehose, or S3"],resourceTypes:["AWS::MSK::Cluster"]},"opensearch-access-control-weak":{ruleId:"opensearch-access-control-weak",checkKey:"openSearchAccessControl",name:"OpenSearch Access Control Weak",description:"Detects OpenSearch domains without fine-grained access control or VPC placement.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/opensearch-service/latest/developerguide/fgac.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable AdvancedSecurityOptions","Configure VPCOptions to deploy the domain inside a VPC"],resourceTypes:["AWS::OpenSearchService::Domain","AWS::Elasticsearch::Domain"]},"opensearch-encryption-disabled":{ruleId:"opensearch-encryption-disabled",checkKey:"openSearchEncryption",name:"OpenSearch Encryption Disabled",description:"Detects OpenSearch domains without at-rest encryption or node-to-node encryption.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/opensearch-service/latest/developerguide/encryption-at-rest.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable EncryptionAtRestOptions with a KMS key","Enable NodeToNodeEncryptionOptions"],resourceTypes:["AWS::OpenSearchService::Domain","AWS::Elasticsearch::Domain"]},"opensearch-logging-disabled":{ruleId:"opensearch-logging-disabled",checkKey:"openSearchLogging",name:"OpenSearch Logging Disabled",description:"Detects OpenSearch domains without audit logs or application logs published to CloudWatch.",severity:"LOW",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/opensearch-service/latest/developerguide/audit-logs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable AUDIT_LOGS in LogPublishingOptions","Enable ES_APPLICATION_LOGS in LogPublishingOptions"],resourceTypes:["AWS::OpenSearchService::Domain","AWS::Elasticsearch::Domain"]},"redshift-encryption-disabled":{ruleId:"redshift-encryption-disabled",checkKey:"redshiftEncryption",name:"Redshift Encryption Disabled",description:"Detects Redshift clusters without at-rest encryption.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-db-encryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set Encrypted: true and specify a KmsKeyId"],resourceTypes:["AWS::Redshift::Cluster"]},"redshift-audit-logging-disabled":{ruleId:"redshift-audit-logging-disabled",checkKey:"redshiftLogging",name:"Redshift Audit Logging Disabled",description:"Detects Redshift clusters without audit logging to S3 (connection, user, query activity).",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set LoggingProperties with a target S3 bucket and key prefix"],resourceTypes:["AWS::Redshift::Cluster"]},"redshift-publicly-accessible":{ruleId:"redshift-publicly-accessible",checkKey:"redshiftPublicAccess",name:"Redshift Publicly Accessible",description:"Detects Redshift clusters reachable from the public internet.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/redshift/latest/mgmt/managing-clusters-vpc.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Set PubliclyAccessible: false","Use VPC endpoints, bastion hosts, or VPN for access"],resourceTypes:["AWS::Redshift::Cluster"]},"route53-dnssec-disabled":{ruleId:"route53-dnssec-disabled",checkKey:"route53Dnssec",name:"Route 53 DNSSEC Disabled",description:"Detects Route 53 hosted zones without DNSSEC signing enabled.",severity:"LOW",wafPillar:"Security",complianceFrameworks:["SOC2","NIST"],awsDocUrl:"https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-configuring-dnssec.html",remediationSteps:["Create an AWS::Route53::DNSSEC resource for the hosted zone","Configure a key-signing key (KSK)"],resourceTypes:["AWS::Route53::HostedZone","AWS::Route53::DNSSEC"]},"route53-health-check-suboptimal":{ruleId:"route53-health-check-suboptimal",checkKey:"route53HealthChecks",name:"Route 53 Health Check Suboptimal",description:"Detects Route 53 health checks using HTTP instead of HTTPS or the standard request interval.",severity:"LOW",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-failover.html",remediationSteps:["Use HTTPS to validate certificate and endpoint security","Use a 10-second request interval for critical endpoints"],resourceTypes:["AWS::Route53::HealthCheck"]},"route53-query-logging-disabled":{ruleId:"route53-query-logging-disabled",checkKey:"route53QueryLogging",name:"Route 53 Query Logging Disabled",description:"Detects Route 53 hosted zones without query logging.",severity:"LOW",wafPillar:"Security",complianceFrameworks:["SOC2","HIPAA","NIST"],awsDocUrl:"https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/query-logs.html",remediationSteps:["Create an AWS::Route53::QueryLoggingConfig pointing to a CloudWatch Logs group"],resourceTypes:["AWS::Route53::HostedZone","AWS::Route53::QueryLoggingConfig"]},"vpc-default-security-group-rules-present":{ruleId:"vpc-default-security-group-rules-present",checkKey:"vpcDefaultSecurityGroup",name:"VPC Default Security Group Has Rules",description:"Detects default VPC security groups with ingress or egress rules; defaults should be empty.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/vpc/latest/userguide/default-security-group.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Remove all rules from the default security group","Use purpose-built security groups instead"],resourceTypes:["AWS::EC2::SecurityGroup"]},"vpc-flow-logs-missing":{ruleId:"vpc-flow-logs-missing",checkKey:"vpcFlowLogs",name:"VPC Flow Logs Missing",description:"Detects VPCs without flow logs configured.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Create an AWS::EC2::FlowLog resource targeting the VPC","Send logs to CloudWatch Logs or S3"],resourceTypes:["AWS::EC2::VPC","AWS::EC2::FlowLog"]},"waf-logging-disabled":{ruleId:"waf-logging-disabled",checkKey:"wafLogging",name:"WAF Logging Disabled",description:"Detects WAFv2 WebACLs without logging configuration for analysed requests.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/waf/latest/developerguide/logging.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Create an AWS::WAFv2::LoggingConfiguration for the WebACL"],resourceTypes:["AWS::WAFv2::WebACL","AWS::WAFv2::LoggingConfiguration"]},"autoscaling-group-no-elb-healthcheck":{ruleId:"autoscaling-group-no-elb-healthcheck",checkKey:"autoScalingGroupHealthCheck",name:"AutoScaling Group Not Using ELB Health Checks",description:"Detects AWS::AutoScaling::AutoScalingGroup resources attached to a load balancer (LoadBalancerNames or TargetGroupARNs) but using EC2 health checks. EC2 health checks miss app-level outages the load balancer would otherwise detect.",severity:"MEDIUM",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/autoscaling/ec2/userguide/healthcheck.html",remediationSteps:["Set HealthCheckType to ELB on the AutoScalingGroup","Set HealthCheckGracePeriod to give instances time to bootstrap before the LB starts probing","Verify the ALB / NLB target group has appropriate health-check thresholds"],resourceTypes:["AWS::AutoScaling::AutoScalingGroup"]},"autoscaling-launch-config-public-ip":{ruleId:"autoscaling-launch-config-public-ip",checkKey:"autoScalingLaunchConfigPublicIp",name:"AutoScaling LaunchConfiguration Assigns Public IP",description:"Detects AWS::AutoScaling::LaunchConfiguration with AssociatePublicIpAddress=true. Instances launched from this configuration get a public IP and are internet-reachable directly.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/autoscaling/ec2/userguide/AutoScalingGroupExamples.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set AssociatePublicIpAddress to false on the LaunchConfiguration","Place instances in private subnets behind an ALB / NLB","Use a NAT Gateway / VPC endpoints for outbound traffic","Migrate to AWS::EC2::LaunchTemplate (LaunchConfiguration is deprecated)"],resourceTypes:["AWS::AutoScaling::LaunchConfiguration"]},"efs-encryption-disabled":{ruleId:"efs-encryption-disabled",checkKey:"efsEncryption",name:"EFS Encryption Disabled",description:"Detects AWS::EFS::FileSystem resources without Encrypted=true. The CFN default is unencrypted (unlike the EFS console default), and encryption can only be enabled at filesystem creation.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/efs/latest/ug/encryption-at-rest.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set Encrypted to true on the AWS::EFS::FileSystem resource","Provide KmsKeyId pointing at a customer-managed KMS key for additional control","For existing unencrypted filesystems, migrate data to a new encrypted filesystem"],resourceTypes:["AWS::EFS::FileSystem"]},"waf-webacl-misconfigured":{ruleId:"waf-webacl-misconfigured",checkKey:"wafWebAcl",name:"WAF WebACL Misconfigured",description:"Detects WAFv2 WebACLs with no rules, default Allow action, or CloudWatch metrics disabled.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/waf/latest/developerguide/web-acl.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Add WAF rules covering the OWASP Top 10 baseline","Set DefaultAction to Block for defence-in-depth","Enable CloudWatchMetricsEnabled in VisibilityConfig"],resourceTypes:["AWS::WAFv2::WebACL"]},"cross-resource-misconfiguration":{ruleId:"cross-resource-misconfiguration",checkKey:"crossResourceRelationships",name:"Cross-Resource Misconfiguration",description:"Detects misconfigurations only visible across multiple resources: Lambda functions referencing VPC-only resources without VpcConfig, S3 replication without encryption configuration, and security groups exposing non-standard ports to the public when used by sensitive services.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/welcome.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Configure VpcConfig on Lambda functions that reach VPC-only resources (RDS, ElastiCache, Redshift, OpenSearch, ECS Service)","Specify EncryptionConfiguration on S3 replication rules so replicated objects retain encryption at the destination","Restrict 0.0.0.0/0 ingress on non-standard ports for security groups attached to sensitive services"],resourceTypes:["AWS::Lambda::Function","AWS::S3::Bucket","AWS::EC2::SecurityGroup","AWS::RDS::DBInstance","AWS::ElastiCache::CacheCluster","AWS::Redshift::Cluster","AWS::OpenSearchService::Domain","AWS::Elasticsearch::Domain","AWS::ECS::Service"]},"stack-architecture-recommendations":{ruleId:"stack-architecture-recommendations",checkKey:"stackArchitecture",name:"Stack Architecture Recommendations",description:"Detects architectural omissions across the stack: missing CloudWatch Alarms on critical resources, Lambda functions without X-Ray tracing, public-facing resources without WAF, RDS databases without Secrets Manager rotation, and excessive NAT Gateway usage.",severity:"MEDIUM",wafPillar:"Operational Excellence",awsDocUrl:"https://docs.aws.amazon.com/wellarchitected/latest/framework/welcome.html",remediationSteps:["Add CloudWatch Alarms on key metrics (Lambda errors, ECS task failures, RDS connections)","Enable X-Ray tracing on Lambda functions for distributed-request visibility","Associate AWS WAF with public-facing API Gateway, ALB, or CloudFront distributions","Use Secrets Manager with automatic rotation for RDS database credentials","Audit NAT Gateway count and consider VPC endpoints or NAT instances for cost reduction"],resourceTypes:["AWS::Lambda::Function","AWS::ApiGateway::RestApi","AWS::ApiGatewayV2::Api","AWS::ElasticLoadBalancingV2::LoadBalancer","AWS::CloudFront::Distribution","AWS::RDS::DBInstance","AWS::EC2::NatGateway","AWS::CloudWatch::Alarm"]}}});var hX,gX,IEe,yX,xX,bX,SX,rS,vX,iS=D(()=>{"use strict";w3();sS();Qa();I3();dm();dt();hX=(()=>{let t=new Map;for(let e of Object.values(fl))e.checkKey&&e.ruleId&&t.set(e.checkKey,e.ruleId);return t})(),gX={IAM:["AWS::IAM::"],S3:["AWS::S3::"],Lambda:["AWS::Lambda::"],DynamoDB:["AWS::DynamoDB::"],RDS:["AWS::RDS::"],EC2:["AWS::EC2::"],SNS:["AWS::SNS::"],SQS:["AWS::SQS::"],StepFunctions:["AWS::StepFunctions::"],CloudTrail:["AWS::CloudTrail::"],ApiGateway:["AWS::ApiGateway::","AWS::ApiGatewayV2::"],SecretsManager:["AWS::SecretsManager::"],KMS:["AWS::KMS::"],EventBridge:["AWS::Events::"],CloudFront:["AWS::CloudFront::"],ELB:["AWS::ElasticLoadBalancing::","AWS::ElasticLoadBalancingV2::"],ECS:["AWS::ECS::"],Cognito:["AWS::Cognito::"],WAF:["AWS::WAFv2::","AWS::WAF::"],CloudWatch:["AWS::CloudWatch::","AWS::Logs::"],Route53:["AWS::Route53::"],ElastiCache:["AWS::ElastiCache::"],ECR:["AWS::ECR::"],OpenSearch:["AWS::OpenSearchService::","AWS::Elasticsearch::"],ACM:["AWS::CertificateManager::"],Backup:["AWS::Backup::"],VPC:["AWS::EC2::VPC","AWS::EC2::FlowLog","AWS::EC2::SecurityGroup"],Kinesis:["AWS::Kinesis::"],AppSync:["AWS::AppSync::"],EKS:["AWS::EKS::"],Redshift:["AWS::Redshift::"],MSK:["AWS::MSK::"],Glue:["AWS::Glue::"],EFS:["AWS::EFS::"],AutoScaling:["AWS::AutoScaling::"]},IEe=dl({ttl:3e5,maxSize:100}),yX=E3(A3,{ttl:6e5,maxSize:10}),xX=t=>{if(t.includes("All services")||t.length===0)return s=>!s.Type.startsWith("AWS::CDK::");let e=[];for(let s of t){if(s==="All services")continue;let n=gX[s];n&&e.push(...n)}return e.length===0?s=>!s.Type.startsWith("AWS::CDK::"):s=>!s.Type.startsWith("AWS::CDK::")&&e.some(n=>s.Type.startsWith(n))},bX=t=>{let e=new Map,s={CRITICAL:4,HIGH:3,MEDIUM:2,LOW:1};for(let n of t){let r=n.issue,i=e.get(r);i?s[n.severity]>s[i.severity]&&e.set(r,n):e.set(r,n)}return Array.from(e.values())},SX=(t,e,s,n)=>{let r={CRITICAL:0,HIGH:0,MEDIUM:0,LOW:0},i={},o=0;for(let a of Object.values(t))for(let c of a.issues){o++,r[c.severity]++;let u=c.ruleId?Tu(c.ruleId)??"Other":"Other";i[u]=(i[u]||0)+1}return{totalResources:e,analyzedResources:Object.keys(t).length,totalFindings:o,findingsBySeverity:r,findingsByService:i,analysisTimeMs:Date.now()-n,servicesAnalyzed:s}},rS=(t,e,s=[],n={},r=[],i)=>vX(t,e,{selectedServices:s,solutionsRegistry:n,deduplicateFindings:!0,includeStatistics:!1,customRules:r,ruleContext:i}).findings,vX=(t,e,s={})=>{let n=Date.now(),{selectedServices:r=[],solutionsRegistry:i={},deduplicateFindings:o=!0,customRules:a=[],ruleContext:c}=s,u=yX(),l=new Set(["solutionsPatterns","stackArchitecture","crossResourceRelationships"]),d=Object.keys(u).filter(w=>!l.has(w)),{services:p}=Hp(r),f=hk(p,d),m={},g=xX(p),h=Object.keys(t.Resources||{}).length,y=Object.entries(t.Resources||{}).filter(([,w])=>g(w)).reduce((w,[N,L])=>(w[N]=L,w),{}),b=[];for(let w of f)try{let N=u[w];if(typeof N!="function"){let H=Tu(w)??w;et.warn(`\u26A0\uFE0F Service check function for ${H} (${w}) is not available`);continue}let L=N({Resources:y},e,c);b.push(w);let R=hX.get(w);for(let[H,B]of Object.entries(L)){if(m[H]||(m[H]={issues:[]}),R)for(let S of B.issues)S.ruleId||(S.ruleId=R);m[H].issues.push(...B.issues)}}catch(N){let L=Tu(w)??w;et.warn(`\u26A0\uFE0F Error in ${L} analysis (${w})`,{error:N instanceof Error?N.message:String(N)})}if(Object.keys(i).length>0)try{let w=u.solutionsPatterns({Resources:y},i);for(let N of w){let L=N.resourceId;m[L]||(m[L]={issues:[]}),m[L].issues.push(N)}}catch(w){et.warn("\u26A0\uFE0F Error in solutions pattern analysis",{error:w instanceof Error?w.message:String(w)})}if(a.length>0)try{let w=R3(t,a,e);for(let[N,L]of Object.entries(w))m[N]||(m[N]={issues:[]}),m[N].issues.push(...L.issues);et.info(`Custom rules evaluated: ${a.length} rule(s)`)}catch(w){et.warn("\u26A0\uFE0F Error evaluating custom rules",{error:w instanceof Error?w.message:String(w)})}if(o)for(let w of Object.keys(m))m[w].issues=bX(m[w].issues);Object.keys(m).length===0&&et.info(`\x1B[32m\u2705 No security or cost issues detected!\x1B[0m
|
|
161
|
+
${e}`:e:t,wJ=(t,e)=>t?!!(e?.startsWith("AWS::CDK::")||e?.startsWith("Cfn")||t.endsWith("/Resource")||t==="Resource"||t.includes("Asset")||t.includes("CustomResource")):!1,LT=(t,e,s,n,r)=>{let i=Rc("cdk.out");return Object.entries(t).reduce((o,[a,c])=>{let u=Object.keys(e).find(z=>e[z]===a)??c.cdkPath,l=s[a]?.__constructType??n.Resources?.[a]?.Type??"",d=r[a]?.githubUrl,p=r[a]?.docUrl,f=r[a]?.constructName,m=r[a]?.constructLevel,g=r[a]?.fqn,h=wJ(u,l),y=s[a]?.displayName,b=y??s[a]?.__friendlyName??u.split("/").pop()??a,C=y??u??c.locationHint,A=Qf(i,a),w=c.appliedMixins??s[a]?.__appliedMixins,N=DJ(w),L=[...c.sources?.cdkInsights?.issues??[],...c.sources?.cdkNag?.issues??[]].map(z=>({...z,recommendation:AT(AJ(z.recommendation,N),m),locationHint:C,githubUrl:d,docUrl:p,constructName:f,...m?{constructLevel:m}:{},...g?{fqn:g}:{},...A?.filePath&&{sourceLocation:{filePath:A.filePath,line:A.line||1,column:A.column||1,confidence:A.confidence||"low",...A.frames&&A.frames.length>0?{frames:A.frames}:{}}},stackName:A?.stackName,stackId:A?.stackName,timestamp:new Date().toISOString()})),R=L.filter(z=>z.foundBy!=="cdkNag"),H=L.filter(z=>z.foundBy==="cdkNag"),B=s[a],S=c.parentPath||B?.__parentPath,U=c.childCount??B?.__childCount,k=c.tags||B?.__tags,K=c.sourceLocation||B?.__sourceLocation,x=c.constructHierarchy||B?.__constructHierarchy,v=c.serviceCategory||B?.__serviceCategory,Y=c.dependencies||B?.__dependencies,J=c.sensitiveProperties||B?.__sensitiveProperties,X=c.usesDefaults??B?.__usesDefaults,re=c.l2ConstructType||B?.__l2ConstructType,pe=c.l2ConstructId||B?.__l2ConstructId,Ae=c.createdBy||B?.__createdBy,we=c.rootSourceLocation||B?.__rootSourceLocation,ue=c.searchHint||B?.__searchHint,Re=K?{filePath:K.filePath,line:K.line,column:K.column,endLine:K.endLine,endColumn:K.endColumn,confidence:K.confidence||"high",method:K.method,enclosingScope:K.enclosingScope,codeSnippet:K.codeSnippet}:A?.filePath?{filePath:A.filePath,line:A.line||1,column:A.column||1,confidence:A.confidence||"low"}:void 0;return o[a]={...c,resourceId:a,displayName:y,cdkPath:u,friendlyName:b,locationHint:C,constructName:f,githubUrl:d,docUrl:p,isGenerated:h,type:l,constructType:l,parentPath:S,childCount:U,tags:k,sourceLocation:Re,constructHierarchy:x,logicalId:a,serviceCategory:v,dependencies:Y,sensitiveProperties:J,usesDefaults:X,l2ConstructType:re,l2ConstructId:pe,createdBy:Ae,rootSourceLocation:we,searchHint:ue,appliedMixins:w,sources:{cdkInsights:{issues:R},cdkNag:{issues:H}}},o},{})}});var EJ,il,MT,BT,RJ,ol,al,Vb,NT,Zb=D(()=>{"use strict";EJ=new Set(["AwsSolutions-IAM4","AwsSolutions-IAM5","AwsSolutions-S1","AwsSolutions-S2","AwsSolutions-S3","AwsSolutions-S10","AwsSolutions-RDS2","AwsSolutions-RDS6","AwsSolutions-RDS10","AwsSolutions-EC23","AwsSolutions-EC26","AwsSolutions-ECS4","AwsSolutions-COG2","AwsSolutions-COG3","AwsSolutions-ELB2","AwsSolutions-KMS5","AwsSolutions-L1","AwsSolutions-SMG4","AwsSolutions-DDB3","AwsSolutions-CB4"]),il={AwsSolutions:"https://github.com/cdklabs/cdk-nag/blob/main/RULES.md#awssolutions-rules","HIPAA.Security":"https://github.com/cdklabs/cdk-nag/blob/main/RULES.md#hipaasecurity-rules","NIST.800.53.R4":"https://github.com/cdklabs/cdk-nag/blob/main/RULES.md#nist-80053-rules","NIST.800.53.R5":"https://github.com/cdklabs/cdk-nag/blob/main/RULES.md#nist-80053-rules","PCI.DSS.321":"https://github.com/cdklabs/cdk-nag/blob/main/RULES.md#pcidss-rules"},MT={IAM:"Security",S:"Security",EC:"Security",VPC:"Security",KMS:"Security",SMG:"Security",COG:"Security",CFR:"Security",ELB:"Security",RDS:"Security",DDB:"Security",SQS:"Security",SNS:"Security",L:"Security",ECS:"Security",EKS:"Security",CB:"Security",ATH:"Security",OS:"Security",RS:"Security",TS:"Security",QL:"Security",APS:"Security",DOC:"Security",EFS:"Security",GL:"Security",KDF:"Security",KDS:"Security",LEX:"Security",MSK:"Security",N:"Security",QS:"Security",EMR:"Security",AS:"Reliability",AEC:"Reliability",KDA:"Reliability",CW:"Operational Excellence",CT:"Operational Excellence",SF:"Operational Excellence",EB:"Operational Excellence",ASC:"Operational Excellence",MS:"Operational Excellence",EVB:"Operational Excellence",C91:"Security"},BT=t=>t.match(/^((?:AwsSolutions|HIPAA\.Security|NIST\.800\.53\.R[45]|PCI\.DSS\.321)-[A-Z0-9]+)/i)?.[1],RJ=t=>t.match(/-([A-Z]+)\d*$/i)?.[1]?.toUpperCase(),ol=(t,e)=>{if(e&&EJ.has(e))return"CRITICAL";switch(t){case"aws:cdk:error":return"HIGH";case"aws:cdk:warning":return"MEDIUM";case"aws:cdk:info":return"LOW";default:return"HIGH"}},al=t=>{if(!t)return"Security";let e=RJ(t);return e&&MT[e]?MT[e]:"Security"},Vb=t=>{if(t){if(t.startsWith("AwsSolutions-"))return il.AwsSolutions;if(t.startsWith("HIPAA.Security-"))return il["HIPAA.Security"];if(t.startsWith("NIST.800.53.R4-"))return il["NIST.800.53.R4"];if(t.startsWith("NIST.800.53.R5-"))return il["NIST.800.53.R5"];if(t.startsWith("PCI.DSS.321-"))return il["PCI.DSS.321"]}},NT=t=>t.startsWith("AwsSolutions-")||t.startsWith("HIPAA.Security-")||t.startsWith("NIST.800.53.R")||t.startsWith("PCI.DSS.321-")});var $T,WT=D(()=>{"use strict";Zb();$T=(t,e)=>{let s=/\[([^\]]*)\]\s*\[([^\]]*)\]\s*\[([^\]]*)\]/g,n=[],r=s.exec(t);for(;r!==null;){let i=r[1]??"",o=r[2],a=r[3];if(o&&a){let c=e[i]??i;n.push({resourceId:c,issue:a,severity:ol("inline",o),wafPillar:al(o),foundBy:"cdkNag",constructPath:i,ruleId:o})}r=s.exec(t)}return n}});var em,jT,UT,HT=D(()=>{"use strict";em=oe(require("node:fs")),jT=oe(require("node:path")),UT=(t=process.cwd())=>{let e=jT.join(t,"cdk.json");if(!em.existsSync(e))return{context:{},found:!1};let s;try{s=em.readFileSync(e,"utf-8")}catch{return{context:{},found:!1}}let n;try{n=JSON.parse(s)}catch{return{context:{},found:!1,source:e}}return n&&typeof n=="object"&&!Array.isArray(n)&&"context"in n&&typeof n.context=="object"&&n.context!==null&&!Array.isArray(n.context)?{context:n.context,found:!0,source:e}:{context:{},found:!0,source:e}}});var GT,zT=D(()=>{"use strict";GT=(t,e)=>e?Object.entries(t).reduce((s,[n,r])=>(s[n]={...r,__description:r.__description||e[n]},s),{}):{...t}});var IJ,kJ,qT,KT=D(()=>{"use strict";IJ="aws:cdk:analytics:mixin",kJ="*",qT=t=>{let e=new Set,s=[];for(let n of t){if(n.type!==IJ||!n.data||typeof n.data!="object"||Array.isArray(n.data))continue;let r=n.data.mixin;typeof r!="string"||r.length===0||e.has(r)||(e.add(r),s.push({fqn:r,isCustom:r===kJ}))}return s}});var cl,_J,Yb,VT,FJ,ZT,TJ,PJ,YT,JT=D(()=>{"use strict";Zb();dt();KT();cl="cdk-insights::",_J="aws:cdk:acknowledged-rules",Yb="cdk-insights::nagFinding::",VT=t=>t.startsWith(cl)&&!t.startsWith(Yb),FJ=t=>t.startsWith(Yb),ZT="2.2.0",TJ=(t,e)=>{let s=t.split(".").map(Number),n=e.split(".").map(Number);for(let r=0;r<Math.max(s.length,n.length);r++){let i=s[r]||0,o=n[r]||0;if(i!==o)return i-o}return 0},PJ=(t,e)=>{if(!t){Me.debug("Legacy cdk-insights metadata found (no version field)",{constructPath:e});return}TJ(t,ZT)<0&&Me.debug(`Metadata version ${t} is older than expected ${ZT}`,{constructPath:e,hint:"Consider re-running cdk synth with the latest cdk-insights aspect"})},YT=(t,e,s,n,r)=>{try{let i=t.artifacts??{},a=(i[n]||i[`${n}.template.json`])?.metadata??{},c={...e},u={...s},l=[];for(let[p,{githubUrl:f,docUrl:m}]of Object.entries(r))if(f||m){let g=u[p]||{};u[p]={...g,...f&&{__github:f},...m&&{__docs:m}}}for(let[p,f]of Object.entries(a)){for(let C of f)if(C.type===_J&&!(!C.data||typeof C.data!="object"))for(let[A,w]of Object.entries(C.data)){if(!A.startsWith(cl))continue;let N=A.slice(cl.length);if(!N)continue;let L=typeof w=="string"?w:"";l.push({constructPath:p,ruleId:N,reason:L})}let m=f.find(C=>C.type==="aws:cdk:logicalId"&&typeof C.data=="string");if(!m)continue;let g=m.data,h=p.startsWith("/")?p.slice(1):p;c[h]=g;let y=qT(f);y.length>0&&(u[g]={...u[g],__appliedMixins:y});let b=f.find(C=>C.type==="aws:cdk:info"&&typeof C.data=="string"&&VT(C.data));if(b)try{let C=JSON.parse(b.data.slice(cl.length)),{friendlyName:A,constructType:w,description:N,stackId:L,sourceLocation:R,parentPath:H,childCount:B,tags:S,version:U,logicalId:k,constructHierarchy:K,serviceCategory:x,dependencies:v,sensitiveProperties:Y,usesDefaults:J,l2ConstructType:X,l2ConstructId:re,createdBy:pe,rootSourceLocation:Ae,searchHint:we}=C;PJ(U,p);let ue={...u[g]};A&&(ue.__friendlyName=A),w&&(ue.__constructType=w),N&&(ue.__description=N),L&&(ue.__stackId=n),R&&(ue.__sourceLocation=R),H&&(ue.__parentPath=H),B!==void 0&&(ue.__childCount=B),S&&Object.keys(S).length>0&&(ue.__tags=S),U&&(ue.__metadataVersion=U),k&&(ue.__logicalId=k),K?.length>0&&(ue.__constructHierarchy=K),x&&(ue.__serviceCategory=x),v?.length>0&&(ue.__dependencies=v),Y?.length>0&&(ue.__sensitiveProperties=Y),J!==void 0&&(ue.__usesDefaults=J),X&&(ue.__l2ConstructType=X),re&&(ue.__l2ConstructId=re),pe&&(ue.__createdBy=pe),Ae&&(ue.__rootSourceLocation=Ae),we&&(ue.__searchHint=we),u[g]=ue}catch(C){Me.warn(`Failed to parse cdk-insights metadata for ${p}:`,{error:C})}}let d={};for(let[p,f]of Object.entries(a)){let m=f.find(N=>N.type==="aws:cdk:logicalId"&&typeof N.data=="string");if(!m)continue;let g=m.data,h=[],y=f.find(N=>N.type==="aws:cdk:info"&&typeof N.data=="string"&&VT(N.data));if(y)try{let N=JSON.parse(y.data.slice(cl.length));Array.isArray(N.issues)&&(h=N.issues.map(L=>({resourceId:L.resourceId,issue:L.issue,recommendation:L.recommendation,severity:L.severity,wafPillar:L.wafPillar,foundBy:"cdkInsights",constructPath:p,stackId:u[g]?.__stackId,constructType:u[g]?.__constructType,githubUrl:s[g]?.__github,docUrl:s[g]?.__docs})))}catch(N){Me.warn(`Failed to parse cdk-insights metadata for ${p}:`,{error:N})}let b=f.filter(N=>(N.type==="aws:cdk:error"||N.type==="aws:cdk:warning")&&typeof N.data=="string"&&NT(N.data)).map(N=>{let L=N.data,R=BT(L),H=ol(N.type,R);return{resourceId:g,issue:L,recommendation:void 0,severity:H,wafPillar:al(R),foundBy:"cdkNag",constructPath:p,ruleId:R,stackId:u[g]?.__stackId,constructType:u[g]?.__constructType,githubUrl:s[g]?.__github,docUrl:Vb(R)||s[g]?.__docs}}),C=[];for(let N of f)if(N.type==="aws:cdk:info"&&typeof N.data=="string"&&FJ(N.data))try{let L=JSON.parse(N.data.slice(Yb.length)),R=L.level==="Error"?"aws:cdk:error":"aws:cdk:warning",H=ol(R,L.ruleId);C.push({resourceId:g,issue:`${L.ruleId}${L.findingId?`[${L.findingId}]`:""}: ${L.ruleInfo}`,recommendation:L.ruleExplanation,severity:H,wafPillar:al(L.ruleId),foundBy:"cdkNag",constructPath:p,ruleId:L.ruleId,stackId:u[g]?.__stackId,constructType:u[g]?.__constructType,githubUrl:s[g]?.__github,docUrl:Vb(L.ruleId)||s[g]?.__docs})}catch(L){Me.warn(`Failed to parse cdk-insights nag finding for ${p}:`,{error:L})}let A=[...b,...C],w=u[g];d[g]={resourceId:g,friendlyName:w?.__friendlyName||g,cdkPath:p,locationHint:p,type:s[g]?.Type,isGenerated:!1,constructType:w?.__constructType,parentPath:w?.__parentPath,childCount:w?.__childCount,tags:w?.__tags,sourceLocation:w?.__sourceLocation,logicalId:g,constructHierarchy:w?.__constructHierarchy,serviceCategory:w?.__serviceCategory,dependencies:w?.__dependencies,sensitiveProperties:w?.__sensitiveProperties,usesDefaults:w?.__usesDefaults,l2ConstructType:w?.__l2ConstructType,l2ConstructId:w?.__l2ConstructId,createdBy:w?.__createdBy,rootSourceLocation:w?.__rootSourceLocation,searchHint:w?.__searchHint,appliedMixins:w?.__appliedMixins,sources:{cdkInsights:{issues:h},cdkNag:{issues:A}}}}if(Object.keys(d).length===0)for(let p of Object.keys(u))d[p]={resourceId:p,friendlyName:p,cdkPath:p,isGenerated:!1,sources:{cdkInsights:{issues:[]},cdkNag:{issues:[]}}};return{pathToLogicalId:c,unifiedResourceMap:u,resourceIdMetadata:r,recommendationMap:d,acknowledgements:l}}catch(i){return Me.error("\u26A0\uFE0F Failed to parse manifest.json for logical ID mappings:",{error:i}),Me.warn("Unknown error in parseManifestMetadata",{error:i}),{pathToLogicalId:e,unifiedResourceMap:s,resourceIdMetadata:r,recommendationMap:{},acknowledgements:[]}}}});function LJ(t){let e=tm.join(t,"manifest.json");if(!Kr.existsSync(e))return{};let s=JSON.parse(Kr.readFileSync(e,"utf8")),n={};for(let r of Object.values(s.artifacts)){if(r.type!=="cdk:asset-manifest")continue;let i=r.properties.file,o=tm.join(t,i);if(!Kr.existsSync(o))continue;let a=JSON.parse(Kr.readFileSync(o,"utf8"));for(let[c,u]of Object.entries(a.files||{}))n[c]=u.displayName}return n}function QT(t){let e={},s={},n={},r={},i=LJ(t),o=Kr.readdirSync(t).filter(a=>a.endsWith(".template.json"));for(let a of o){let c=a.replace(/\.template\.json$/,""),u=JSON.parse(Kr.readFileSync(tm.join(t,a),"utf8"));e[c]=u;for(let[l,d]of Object.entries(u.Resources||{})){if(new Set(["CDKMetadata","BootstrapVersion","CheckBootstrapVersion"]).has(l)||d.Type?.startsWith("AWS::CDK::")||d.Type==="AWS::SSM::Parameter")continue;let f={...d,displayName:l},m=f.Metadata??{};typeof m["aws:cdk:path"]=="string"&&(s[m["aws:cdk:path"]]=l);let g=m["aws:asset:path"],h=typeof g=="string"?g.replace(/^asset\./,""):void 0;if(h&&i[h])f.displayName=i[h];else if(typeof m["aws:cdk:path"]=="string"){let y=m["aws:cdk:path"].split("/"),b=y[y.length-1],C=b==="Resource"&&y.length>1?y[y.length-2]:b;f.displayName=C}n[l]=f,r[l]=f.displayName??l}}return{stacks:e,pathToLogicalId:s,unifiedResourceMap:n,displayNameMap:r,assetSourcePaths:Object.fromEntries(Object.entries(n).filter(([,a])=>a.Metadata?.["aws:asset:path"]).map(([a,c])=>[a,c.Metadata["aws:asset:path"]]))}}var Kr,tm,XT=D(()=>{"use strict";Kr=oe(require("node:fs")),tm=oe(require("node:path"))});var OJ,MJ,BJ,NJ,$J,eP,tP=D(()=>{"use strict";OJ=["cdk-nag","cdk-monitoring-constructs","cdk-watchful","@cdk-cosmos/","@aws-cdk-containers/","@aws-prototyping-sdk/"],MJ=t=>t.startsWith("aws-cdk-lib.aws_")||t.startsWith("aws-cdk-lib.core.")||t.startsWith("aws-cdk-lib/aws-")||/^@aws-cdk\/aws[-_]/.test(t)||/^@aws-cdk\/core/.test(t),BJ=t=>t.startsWith("@aws-solutions-constructs/"),NJ=t=>OJ.some(e=>t.startsWith(e)||t.startsWith(`${e}.`)),$J=t=>{let e=t.split(".");return e[e.length-1]??""},eP=t=>!t||typeof t!="string"?"unknown":$J(t).startsWith("Cfn")?"L1":BJ(t)?"L3-aws-solutions":NJ(t)?"L3-third-party":MJ(t)?"L2":"L3-custom"});var sP,nP=D(()=>{"use strict";sP=t=>{let e="https://github.com/aws/aws-cdk/blob/main/packages",s="https://docs.aws.amazon.com/cdk/api/v2/docs",n=t.split(".");if(n.length<3)return{githubUrl:null,docUrl:null,constructName:null};let[,r,...i]=n,o=`${e}/aws-cdk-lib/${r}/lib/${i.join("/")}.ts`,a=`${s}/${t}.html`;return{githubUrl:o,docUrl:a,constructName:i[0]}}});var sm,rP,iP=D(()=>{"use strict";sm=oe(require("node:fs"));tP();nP();rP=(t,e)=>{let s=`${t}/tree.json`;if(!sm.existsSync(s))return{pathToLogicalId:e,resourceIdMetadata:{}};let n=JSON.parse(sm.readFileSync(s,"utf-8")),i=(n.tree?.children?Object.values(n.tree.children):[n]).map(d=>({node:d,parentPath:""})),o=[];for(;i.length;){let d=i.pop();if(!d)continue;let{node:p,parentPath:f}=d,m=f?`${f}/${p.id}`:p.id,g=m.replace(/^\/+/,""),h=e[g],y=p.constructInfo?.fqn,b=p.attributes?.["aws:cdk:cloudformation:props"],C=b&&typeof b.description=="string"?b.description:void 0;if(o.push({logicalId:h,path:m,fqn:y,description:C}),p.children)for(let A of Object.values(p.children))i.push({node:A,parentPath:m})}let a={},c={},u={},l=d=>(c[d]||(c[d]={githubUrl:"",docUrl:"",constructName:"",constructLevel:"unknown"}),c[d]);for(let{logicalId:d,path:p,fqn:f,description:m}of o)if(d){if(a[p]=d,f){let g=l(d);g.fqn=f,g.constructLevel=eP(f);let{githubUrl:h,docUrl:y,constructName:b}=sP(f);h&&(g.githubUrl=h),y&&(g.docUrl=y,b&&(g.constructName=b))}m&&(u[d]=m)}return{pathToLogicalId:{...e,...a},resourceIdMetadata:c,autoGeneratedDescriptions:u}}});var oP,aP,cP,WJ,Ic,Vr,jJ,UJ,HJ,GJ,uP,Jb=D(()=>{"use strict";oP=oe(require("node:fs")),aP=oe(require("node:path")),cP="cdk-insights",WJ="policy-validation-report.json",Ic=t=>typeof t=="object"&&t!==null&&!Array.isArray(t),Vr=t=>typeof t=="string"?t:void 0,jJ=t=>{if(!Ic(t))return;let e={};for(let[s,n]of Object.entries(t))typeof n=="string"&&(e[s]=n);return Object.keys(e).length>0?e:void 0},UJ=t=>{if(!Ic(t))return;let e=t.locations,s=Array.isArray(e)?e.filter(o=>typeof o=="string"):[],n=Vr(t.resourceLogicalId),r=Vr(t.constructPath),i=Vr(t.templatePath);if(!(!n&&!r))return{...n?{resourceLogicalId:n}:{},...r?{constructPath:r}:{},...i?{templatePath:i}:{},locations:s}},HJ=(t,e)=>{if(!Ic(e))return[];let s=Vr(e.ruleName),n=Vr(e.description);if(!s||!n)return[];let r=Array.isArray(e.violatingConstructs)?e.violatingConstructs:null,i=Array.isArray(e.violatingResources)?e.violatingResources:null,o=r??i??[],a=Vr(e.severity),c=Vr(e.fix),u=jJ(e.ruleMetadata),l=[];for(let d of o){let p=UJ(d);p&&l.push({pluginName:t,ruleName:s,description:n,...a?{severity:a}:{},...c?{fix:c}:{},...u?{ruleMetadata:u}:{},resource:p})}return l},GJ=t=>{if(!Ic(t))return[];let e=Ic(t.summary)?t.summary:void 0,s=Vr(e?.pluginName)??Vr(t.pluginName)??"unknown",n=t.violations;return Array.isArray(n)?n.flatMap(r=>HJ(s,r)):[]},uP=(t={})=>{let e=t.cdkOutDir??"cdk.out",s=t.filename??WJ,n=t.warn??(c=>console.warn(c)),r=aP.join(e,s),i;try{i=oP.readFileSync(r,"utf-8")}catch(c){return c?.code==="ENOENT"?[]:(n(`cdk-insights: could not read ${r}: ${c.message}`),[])}let o;try{o=JSON.parse(i)}catch(c){return n(`cdk-insights: ${r} is not valid JSON: ${c.message}`),[]}if(!Ic(o))return[];let a=o.pluginReports;return Array.isArray(a)?a.flatMap(GJ):[]}});var nm,rm,Qb=D(()=>{"use strict";rl();OT();WT();HT();Xf();zT();JT();XT();iP();Jb();$b();nm="cdk.out",rm=t=>{let e=yT({stackName:t,extractInlineNagFindings:$T}),s=Rc(nm),{context:n}=UT(),{stacks:r,pathToLogicalId:i,unifiedResourceMap:o,assetSourcePaths:a}=QT(nm),{pathToLogicalId:c,resourceIdMetadata:u,autoGeneratedDescriptions:l}=rP(nm,i),d={...i,...c},p=GT(o,l),f=t?r[t]?{[t]:r[t]}:{}:r,m={},g=Object.fromEntries(Object.entries(f).map(([C,A])=>{let{recommendationMap:w,unifiedResourceMap:N,acknowledgements:L}=YT(s,d,p,C,u);m[C]=L;let R={...p,...N};for(let[S,U]of Object.entries(A.Resources??{})){let k=R[S]?.__appliedMixins;k&&k.length>0&&(U.__appliedMixins=k)}let H=Object.fromEntries(Object.keys(A.Resources??{}).map(S=>[S,w[S]??{resourceId:S,friendlyName:d[S]??S,cdkPath:S,isGenerated:!1,sources:{cdkInsights:{issues:[]},cdkNag:{issues:[]}}}])),B=LT(H,d,R,A,u);return[C,B]})),{version:h,supportsBoxTraces:y}=qr(),b=uP({cdkOutDir:nm});return{stacks:f,inlineFindings:e,pathToLogicalId:d,recommendationMapPerStack:g,assetSourcePaths:a,acknowledgementsPerStack:m,cdkVersion:h,supportsBoxTraces:y,cdkContext:n,resourceIdMetadata:u,validationReportFindings:b}}});var kc,zJ,qJ,ta,im,lP=D(()=>{"use strict";kc=(t,e)=>{let s=[];if(t==null)return s;if(typeof t=="string"){let n=t.matchAll(/\$\{([^.}]+)(?:\.[^}]+)?\}/g);for(let r of n){let i=r[1];e.has(i)&&s.push(i)}return s}if(Array.isArray(t)){for(let n of t)s.push(...kc(n,e));return s}if(typeof t=="object"){let n=t;if("Ref"in n&&typeof n.Ref=="string"&&e.has(n.Ref)&&s.push(n.Ref),"Fn::GetAtt"in n){let r=n["Fn::GetAtt"];if(Array.isArray(r)&&typeof r[0]=="string")e.has(r[0])&&s.push(r[0]);else if(typeof r=="string"){let i=r.split(".")[0];e.has(i)&&s.push(i)}}if("Fn::Sub"in n){let r=n["Fn::Sub"];Array.isArray(r)?(s.push(...kc(r[0],e)),r[1]&&typeof r[1]=="object"&&s.push(...kc(r[1],e))):s.push(...kc(r,e))}for(let[r,i]of Object.entries(n))["Ref","Fn::GetAtt","Fn::Sub"].includes(r)||s.push(...kc(i,e))}return s},zJ=t=>t.DependsOn?Array.isArray(t.DependsOn)?t.DependsOn:[t.DependsOn]:[],qJ=(t,e)=>{if(e.length===0)return;let s=new Set(e.map(i=>i.type.split("::")[2]||i.type)),n=Array.from(s).slice(0,3),r=t.split("::")[2]||t;if(t.includes("SecurityGroup"))return`Security group attached to: ${n.join(", ")}`;if(t.includes("IAM::Role"))return`IAM role assumed by: ${n.join(", ")}`;if(t.includes("VPC")||t.includes("Subnet"))return`Network hosting: ${n.join(", ")}`;if(t.includes("KMS::Key"))return`Encryption key used by: ${n.join(", ")}`;if(t.includes("S3::Bucket")){if(n.some(i=>i.includes("Lambda")))return"S3 bucket accessed by Lambda functions";if(n.some(i=>i.includes("CloudFront")))return"S3 bucket serving as CloudFront origin"}if(t.includes("DynamoDB::Table")&&n.some(i=>i.includes("Lambda")))return"DynamoDB table accessed by Lambda functions";if(e.length>0)return`Referenced by ${e.length} resource${e.length>1?"s":""}: ${n.join(", ")}`},ta=t=>{let e=new Set(Object.keys(t)),s={};for(let n of e)s[n]={dependencies:[],dependents:[]};for(let[n,r]of Object.entries(t)){let i=zJ(r),o=kc(r.Properties,e),a=[...new Set([...i,...o])];s[n].dependencies=a;for(let c of a)s[c]&&s[c].dependents.push(n)}for(let[n,r]of Object.entries(t)){let i=s[n],o=i.dependents.map(a=>({id:a,type:t[a]?.Type||"Unknown"}));i.usageDescription=qJ(r.Type,o)}return s},im=(t,e,s)=>{let n=e[t];if(!n)return{dependencies:[],dependents:[]};let r=n.dependencies.map(o=>{let a=s[o]?.Type?.split("::")[2]||o;return`${o} (${a})`}),i=n.dependents.map(o=>{let a=s[o]?.Type?.split("::")[2]||o;return`${o} (${a})`});return{dependencies:r,dependents:i,usageDescription:n.usageDescription}}});var om=D(()=>{"use strict";lP()});var KJ,VJ,ZJ,am,Xb=D(()=>{"use strict";om();KJ=(t,e,s)=>{let n={},r=new Set(["AWS::RDS::DBInstance","AWS::RDS::DBCluster","AWS::ElastiCache::CacheCluster","AWS::ElastiCache::ReplicationGroup","AWS::Redshift::Cluster","AWS::OpenSearchService::Domain","AWS::Elasticsearch::Domain","AWS::ECS::Service"]),i=new Set(Object.entries(t).filter(([,o])=>r.has(o.Type)).map(([o])=>o));for(let[o,a]of Object.entries(t)){if(a.Type!=="AWS::Lambda::Function")continue;let c=a.Properties||{},u=!!(c.VpcConfig&&(c.VpcConfig.SubnetIds||c.VpcConfig.SecurityGroupIds)),l=e[o];if(!l)continue;if(l.dependencies.some(p=>i.has(p))&&!u){n[o]||(n[o]={issues:[]});let p=l.dependencies.filter(f=>i.has(f));n[o].issues.push(s(o,`Lambda function references VPC resources (${p.join(", ")}) but is not VPC-enabled`,"Configure VpcConfig with appropriate SubnetIds and SecurityGroupIds to allow the Lambda function to connect to VPC resources. Without VPC configuration, the function cannot reach private resources like RDS databases.","HIGH","Reliability",a.Metadata?.["aws:cdk:path"]||o,"cdkInsights"))}}return n},VJ=(t,e)=>{let s={},n=new Map;for(let[r,i]of Object.entries(t)){if(i.Type!=="AWS::S3::Bucket")continue;let o=i.Properties||{},a=!!(o.BucketEncryption||o.ServerSideEncryptionConfiguration);n.set(r,a)}for(let[r,i]of Object.entries(t)){if(i.Type!=="AWS::S3::Bucket")continue;let a=(i.Properties||{}).ReplicationConfiguration;if(!a)continue;let c=n.get(r),u=a.Rules;if(!(!u||!Array.isArray(u)))for(let l of u){if(l.Status!=="Enabled")continue;let d=l.Destination;if(!d||!d.Bucket)continue;let f=d.EncryptionConfiguration;c&&!f&&(s[r]||(s[r]={issues:[]}),s[r].issues.push(e(r,"S3 replication configured without encryption configuration for replicated objects","Specify EncryptionConfiguration in the replication rule to ensure replicated objects maintain encryption. Use ReplicaKmsKeyID to specify the KMS key for encrypting replicated objects in the destination bucket.","MEDIUM","Security",i.Metadata?.["aws:cdk:path"]||r,"cdkInsights")))}}return s},ZJ=(t,e,s)=>{let n={},r=new Set([80,443,8080,8443]);for(let[i,o]of Object.entries(t)){if(o.Type!=="AWS::EC2::SecurityGroup")continue;let c=(o.Properties||{}).SecurityGroupIngress||[],u=e[i];if(!(u&&u.dependents.length>0))continue;let d=[];for(let p of c){let f=p.CidrIp,m=p.CidrIpv6,g=p.FromPort,h=p.ToPort;if(!(f==="0.0.0.0/0"||m==="::/0")||g===void 0)continue;let b=h!==void 0&&h!==g,C=!r.has(g);(b||C)&&d.push(g)}if(d.length>0){n[i]||(n[i]={issues:[]});let p=u.dependents.map(f=>t[f]?.Type?.split("::")[2]||"Unknown").join(", ");n[i].issues.push(s(i,`Security group used by ${p} has public access on non-standard ports: ${d.join(", ")}`,"Restrict ingress rules to specific CIDR blocks or reference other security groups instead of allowing 0.0.0.0/0 on non-standard ports. Consider using a bastion host or VPN for administrative access.","HIGH","Security",o.Metadata?.["aws:cdk:path"]||i,"cdkInsights"))}}return n},am=(t,e)=>{let s=t.Resources||{},n=ta(s),r={},i=[KJ(s,n,e),VJ(s,e),ZJ(s,n,e)];for(let o of i)for(let[a,c]of Object.entries(o))r[a]||(r[a]={issues:[]}),r[a].issues.push(...c.issues);return r}});var YJ,JJ,QJ,XJ,eQ,cm,eS=D(()=>{"use strict";om();YJ=t=>{let e=[],s=Object.values(t).map(R=>R.Type),n={};for(let R of s)n[R]=(n[R]||0)+1;let r=s.some(R=>R==="AWS::Lambda::Function"),i=s.some(R=>R==="AWS::ApiGateway::RestApi"||R==="AWS::ApiGatewayV2::Api"),o=s.some(R=>R==="AWS::DynamoDB::Table"),a=s.some(R=>R==="AWS::S3::Bucket");r&&(o||a)&&!s.some(R=>R.includes("ECS")||R.includes("EC2::Instance"))&&e.push("serverless");let c=s.some(R=>R==="AWS::ECS::Service"||R==="AWS::ECS::TaskDefinition"||R==="AWS::ECS::Cluster"),u=s.some(R=>R.startsWith("AWS::EKS::"));(c||u)&&e.push("container-based");let l=s.some(R=>R.startsWith("AWS::Events::")),d=s.some(R=>R==="AWS::SNS::Topic"),p=s.some(R=>R==="AWS::SQS::Queue"),f=s.some(R=>R.startsWith("AWS::Kinesis::")),m=s.some(R=>R.startsWith("AWS::StepFunctions::"));(l||d||p||f||m)&&r&&e.push("event-driven"),i&&e.push("api-gateway");let g=s.some(R=>R.startsWith("AWS::Glue::")),h=s.some(R=>R.startsWith("AWS::Athena::")),y=s.some(R=>R.startsWith("AWS::EMR::"));(f||g||h||y)&&e.push("data-processing");let b=s.some(R=>R==="AWS::CloudFront::Distribution");a&&b&&!r&&!c&&e.push("static-website");let C=n["AWS::Lambda::Function"]||0,A=n["AWS::ECS::Service"]||0;(C>=3||A>=2)&&e.push("microservices");let w=s.some(R=>R==="AWS::EC2::Instance"),N=s.some(R=>R==="AWS::RDS::DBInstance"||R==="AWS::RDS::DBCluster"),L=s.some(R=>R==="AWS::ElasticLoadBalancingV2::LoadBalancer");return w&&(N||L)&&e.push("traditional"),e},JJ=(t,e)=>{let s={},n=Object.values(t).map(l=>l.Type),r=n.some(l=>l==="AWS::CloudWatch::Alarm"),i=n.some(l=>l==="AWS::Lambda::Function"),o=n.some(l=>l==="AWS::ECS::Service"),a=n.some(l=>l==="AWS::RDS::DBInstance"||l==="AWS::RDS::DBCluster");(i||o||a)&&!r&&(s["Stack Architecture"]={issues:[e("Stack Architecture","No CloudWatch Alarms defined for critical resources","Add CloudWatch Alarms to monitor key metrics like Lambda errors, ECS task failures, or RDS connections. Consider using CDK's built-in alarm methods or aws-cdk-lib/aws-cloudwatch.","MEDIUM","Operational Excellence","Stack Architecture","cdkInsights")]});let c=n.some(l=>l==="AWS::XRay::Group"||l==="AWS::XRay::SamplingRule");return n.filter(l=>l==="AWS::Lambda::Function").length>=3&&!c&&(s["Stack Architecture"]||(s["Stack Architecture"]={issues:[]}),s["Stack Architecture"].issues.push(e("Stack Architecture","Multiple Lambda functions without X-Ray tracing configuration","Enable X-Ray tracing for your Lambda functions to gain visibility into distributed request flows and identify performance bottlenecks. Set tracing: lambda.Tracing.ACTIVE on your functions.","LOW","Operational Excellence","Stack Architecture","cdkInsights"))),s},QJ=(t,e)=>{let s={},n=Object.values(t).map(p=>p.Type),r=n.some(p=>p==="AWS::ApiGateway::RestApi"||p==="AWS::ApiGatewayV2::Api"),i=n.some(p=>p==="AWS::ElasticLoadBalancingV2::LoadBalancer"),o=n.some(p=>p==="AWS::CloudFront::Distribution"),a=n.some(p=>p==="AWS::WAFv2::WebACL"||p==="AWS::WAF::WebACL");(r||i||o)&&!a&&(s["Stack Architecture"]||(s["Stack Architecture"]={issues:[]}),s["Stack Architecture"].issues.push(e("Stack Architecture","Public-facing resources without WAF protection","Consider adding AWS WAF to protect your API Gateway, ALB, or CloudFront distribution from common web exploits. WAF can help prevent SQL injection, XSS, and rate-limit malicious traffic.","MEDIUM","Security","Stack Architecture","cdkInsights")));let c=n.some(p=>p==="AWS::SecretsManager::Secret"),u=n.some(p=>p==="AWS::SSM::Parameter"),l=n.some(p=>p==="AWS::RDS::DBInstance"||p==="AWS::RDS::DBCluster"),d=!1;for(let[p,f]of Object.entries(t))if(f.Type==="AWS::Lambda::Function"){let m=f.Properties?.Environment?.Variables;if(m){let g=["PASSWORD","SECRET","API_KEY","TOKEN","CREDENTIAL"];for(let h of Object.keys(m))if(g.some(y=>h.toUpperCase().includes(y))){let y=m[h];if(typeof y=="string"&&!y.startsWith("{{")){d=!0;break}}}}return l&&!c&&!u&&(s["Stack Architecture"]||(s["Stack Architecture"]={issues:[]}),s["Stack Architecture"].issues.push(e("Stack Architecture","RDS database without Secrets Manager for credential rotation","Use AWS Secrets Manager to store and automatically rotate database credentials. This improves security by eliminating hardcoded passwords and enabling automatic credential rotation.","HIGH","Security","Stack Architecture","cdkInsights"))),s},XJ=(t,e)=>{let s={},n=Object.values(t).filter(u=>u.Type==="AWS::EC2::NatGateway").length;n>=3&&(s["Stack Architecture"]||(s["Stack Architecture"]={issues:[]}),s["Stack Architecture"].issues.push(e("Stack Architecture",`${n} NAT Gateways detected - potential cost optimization`,"Multiple NAT Gateways can be expensive ($32/month each + data processing). Consider if all are necessary, or explore alternatives like NAT instances for dev environments, or VPC endpoints for AWS services.","MEDIUM","Cost Optimization","Stack Architecture","cdkInsights")));let r=n>0,i=Object.values(t).some(u=>u.Type==="AWS::EC2::VPCEndpoint"),o=Object.values(t).some(u=>{if(u.Type!=="AWS::Lambda::Function")return!1;let l=u.Properties?.VpcConfig;return l?.SubnetIds||l?.SecurityGroupIds}),a=Object.values(t).some(u=>u.Type==="AWS::S3::Bucket"),c=Object.values(t).some(u=>u.Type==="AWS::DynamoDB::Table");return o&&r&&!i&&(a||c)&&(s["Stack Architecture"]||(s["Stack Architecture"]={issues:[]}),s["Stack Architecture"].issues.push(e("Stack Architecture","VPC Lambda functions accessing AWS services through NAT Gateway","Consider using VPC Endpoints (Gateway endpoints for S3/DynamoDB are free) instead of routing AWS service traffic through NAT Gateway. This reduces costs and improves latency.","LOW","Cost Optimization","Stack Architecture","cdkInsights"))),s},eQ=(t,e,s)=>{let n={};for(let[r,i]of Object.entries(e)){let o=t[r];if(!o)continue;let a=i.dependents.length;if(a>=5){let c=o.Type.split("::")[2]||o.Type;n["Stack Architecture"]||(n["Stack Architecture"]={issues:[]}),n["Stack Architecture"].issues.push(s("Stack Architecture",`${c} (${r}) is a potential single point of failure with ${a} dependent resources`,"Consider adding redundancy or failover mechanisms for this critical resource. For databases, consider Multi-AZ. For queues, consider dead-letter queues. For Lambda, ensure proper error handling.","MEDIUM","Reliability","Stack Architecture","cdkInsights"))}}for(let[r,i]of Object.entries(t)){if(i.Type!=="AWS::DynamoDB::Table")continue;if(i.Properties?.PointInTimeRecoverySpecification?.PointInTimeRecoveryEnabled!==!0){let a=e[r];a&&a.dependents.length>=3&&(n["Stack Architecture"]||(n["Stack Architecture"]={issues:[]}),n["Stack Architecture"].issues.push(s("Stack Architecture",`Critical DynamoDB table ${r} has ${a.dependents.length} dependents but no point-in-time recovery`,"Enable Point-in-Time Recovery (PITR) for critical DynamoDB tables used by multiple resources. This provides continuous backups with 35-day retention.","HIGH","Reliability","Stack Architecture","cdkInsights")))}}return n},cm=(t,e)=>{let s=t.Resources||{};if(Object.keys(s).length<3)return{};let r=ta(s),i=YJ(s),o={},a=[JJ(s,e),QJ(s,e),XJ(s,e),eQ(s,r,e)];for(let c of a)for(let[u,l]of Object.entries(c))o[u]||(o[u]={issues:[]}),o[u].issues.push(...l.issues);return o}});function dP(){let t;try{t=require.resolve("@aws-solutions-constructs/core/package.json")}catch{return[]}let e=(0,ul.dirname)((0,ul.dirname)(t));return(0,um.readdirSync)(e).filter(s=>s!=="core"&&s.startsWith("aws-")&&(0,um.statSync)((0,ul.join)(e,s)).isDirectory())}var um,ul,pP=D(()=>{"use strict";um=require("node:fs"),ul=require("node:path")});var fP,mP=D(()=>{"use strict";fP={"aws-apigateway-dynamodb":{className:"ApiGatewayToDynamoDB",packageName:"aws-apigateway-dynamodb",friendlyName:"Api Gateway To Dynamo DB",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-apigateway-dynamodb/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-apigateway-dynamodb",requiredResourceTypes:["AWS::DynamoDB::Table","AWS::Logs::LogGroup","AWS::ApiGateway::RestApi","AWS::ApiGateway::Deployment","AWS::ApiGateway::Stage","AWS::ApiGateway::Resource","AWS::ApiGateway::Method","AWS::ApiGateway::UsagePlan","AWS::IAM::Role","AWS::ApiGateway::Account","AWS::IAM::Policy"]},"aws-apigateway-kinesisstreams":{className:"ApiGatewayToKinesisStreams",packageName:"aws-apigateway-kinesisstreams",friendlyName:"Api Gateway To Kinesis Streams",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-apigateway-kinesisstreams/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-apigateway-kinesisstreams",requiredResourceTypes:["AWS::Logs::LogGroup","AWS::ApiGateway::RestApi","AWS::ApiGateway::Deployment","AWS::ApiGateway::Stage","AWS::ApiGateway::Resource","AWS::ApiGateway::Method","AWS::ApiGateway::UsagePlan","AWS::ApiGateway::RequestValidator","AWS::ApiGateway::Model","AWS::IAM::Role","AWS::ApiGateway::Account","AWS::IAM::Policy","AWS::CloudWatch::Alarm","AWS::Kinesis::Stream"]},"aws-apigateway-lambda":{className:"ApiGatewayToLambda",packageName:"aws-apigateway-lambda",friendlyName:"Api Gateway To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-apigateway-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-apigateway-lambda",requiredResourceTypes:["AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function","AWS::Logs::LogGroup","AWS::ApiGateway::RestApi","AWS::ApiGateway::Deployment","AWS::ApiGateway::Stage","AWS::ApiGateway::Resource","AWS::Lambda::Permission","AWS::ApiGateway::Method","AWS::ApiGateway::UsagePlan","AWS::ApiGateway::Account"]},"aws-apigateway-sqs":{className:"ApiGatewayToSqs",packageName:"aws-apigateway-sqs",friendlyName:"Api Gateway To Sqs",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-apigateway-sqs/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-apigateway-sqs",requiredResourceTypes:["AWS::SQS::Queue","AWS::SQS::QueuePolicy","AWS::Logs::LogGroup","AWS::ApiGateway::RestApi","AWS::ApiGateway::Deployment","AWS::ApiGateway::Stage","AWS::ApiGateway::Method","AWS::ApiGateway::UsagePlan","AWS::IAM::Role","AWS::ApiGateway::Account","AWS::IAM::Policy"]},"aws-apigatewayv2websocket-sqs":{className:"ApiGatewayV2WebSocketToSqs",packageName:"aws-apigatewayv2websocket-sqs",friendlyName:"Api Gateway V2 Web Socket To Sqs",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-apigatewayv2websocket-sqs/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-apigatewayv2websocket-sqs",requiredResourceTypes:["AWS::SQS::Queue","AWS::SQS::QueuePolicy","AWS::IAM::Role","AWS::IAM::Policy","AWS::ApiGatewayV2::Api","AWS::ApiGatewayV2::Integration","AWS::ApiGatewayV2::Route","AWS::ApiGatewayV2::Stage","AWS::Logs::LogGroup"]},"aws-cloudfront-apigateway-lambda":{className:"CloudFrontToApiGatewayToLambda",packageName:"aws-cloudfront-apigateway-lambda",friendlyName:"Cloud Front To Api Gateway To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-cloudfront-apigateway-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-cloudfront-apigateway-lambda",requiredResourceTypes:["AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function","AWS::Logs::LogGroup","AWS::ApiGateway::RestApi","AWS::ApiGateway::Deployment","AWS::ApiGateway::Stage","AWS::ApiGateway::Resource","AWS::Lambda::Permission","AWS::ApiGateway::Method","AWS::ApiGateway::UsagePlan","AWS::ApiGateway::Account","AWS::CloudFront::Function","AWS::S3::Bucket","AWS::S3::BucketPolicy","AWS::CloudFront::Distribution"]},"aws-cloudfront-mediastore":{className:"CloudFrontToMediaStore",packageName:"aws-cloudfront-mediastore",friendlyName:"Cloud Front To Media Store",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-cloudfront-mediastore/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-cloudfront-mediastore",requiredResourceTypes:["AWS::CloudFront::CloudFrontOriginAccessIdentity","AWS::MediaStore::Container","AWS::S3::Bucket","AWS::S3::BucketPolicy","AWS::CloudFront::OriginRequestPolicy","AWS::CloudFront::Function","AWS::CloudFront::Distribution"]},"aws-cloudfront-oai-s3":{className:"CloudFrontToOaiToS3",packageName:"aws-cloudfront-oai-s3",friendlyName:"Cloud Front To Oai To S3",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-cloudfront-oai-s3/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-cloudfront-oai-s3",requiredResourceTypes:["AWS::S3::Bucket","AWS::S3::BucketPolicy","AWS::CloudFront::Function","AWS::CloudFront::CloudFrontOriginAccessIdentity","AWS::CloudFront::Distribution"]},"aws-cloudfront-s3":{className:"CloudFrontToS3",packageName:"aws-cloudfront-s3",friendlyName:"Cloud Front To S3",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-cloudfront-s3/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-cloudfront-s3",requiredResourceTypes:["AWS::S3::Bucket","AWS::S3::BucketPolicy","AWS::CloudFront::Function","AWS::CloudFront::OriginAccessControl","AWS::CloudFront::Distribution"]},"aws-cognito-apigateway-lambda":{className:"CognitoToApiGatewayToLambda",packageName:"aws-cognito-apigateway-lambda",friendlyName:"Cognito To Api Gateway To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-cognito-apigateway-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-cognito-apigateway-lambda",requiredResourceTypes:["AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function","AWS::Logs::LogGroup","AWS::ApiGateway::RestApi","AWS::ApiGateway::Deployment","AWS::ApiGateway::Stage","AWS::ApiGateway::Resource","AWS::Lambda::Permission","AWS::ApiGateway::Method","AWS::ApiGateway::UsagePlan","AWS::ApiGateway::Account","AWS::Cognito::UserPool","AWS::Cognito::UserPoolClient","AWS::ApiGateway::Authorizer"]},"aws-dynamodbstreams-lambda":{className:"DynamoDBStreamsToLambda",packageName:"aws-dynamodbstreams-lambda",friendlyName:"Dynamo DBStreams To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-dynamodbstreams-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-dynamodbstreams-lambda",requiredResourceTypes:["AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function","AWS::Lambda::EventSourceMapping","AWS::DynamoDB::Table","AWS::SQS::Queue","AWS::SQS::QueuePolicy"]},"aws-kinesisfirehose-s3":{className:"KinesisFirehoseToS3",packageName:"aws-kinesisfirehose-s3",friendlyName:"Kinesis Firehose To S3",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-kinesisfirehose-s3/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-kinesisfirehose-s3",requiredResourceTypes:["AWS::S3::Bucket","AWS::S3::BucketPolicy","AWS::Logs::LogGroup","AWS::Logs::LogStream","AWS::IAM::Role","AWS::IAM::Policy","AWS::KinesisFirehose::DeliveryStream"]},"aws-kinesisstreams-kinesisfirehose-s3":{className:"KinesisStreamsToKinesisFirehoseToS3",packageName:"aws-kinesisstreams-kinesisfirehose-s3",friendlyName:"Kinesis Streams To Kinesis Firehose To S3",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-kinesisstreams-kinesisfirehose-s3/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-kinesisstreams-kinesisfirehose-s3",requiredResourceTypes:["AWS::Kinesis::Stream","AWS::S3::Bucket","AWS::S3::BucketPolicy","AWS::Logs::LogGroup","AWS::Logs::LogStream","AWS::IAM::Role","AWS::IAM::Policy","AWS::KinesisFirehose::DeliveryStream","AWS::CloudWatch::Alarm"]},"aws-s3-lambda":{className:"S3ToLambda",packageName:"aws-s3-lambda",friendlyName:"S3 To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-s3-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-s3-lambda",requiredResourceTypes:["AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function","AWS::S3::Bucket","AWS::S3::BucketPolicy","Custom::S3BucketNotifications","AWS::Lambda::Permission"]},"aws-s3-sns":{className:"S3ToSns",packageName:"aws-s3-sns",friendlyName:"S3 To Sns",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-s3-sns/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-s3-sns",requiredResourceTypes:["AWS::S3::Bucket","AWS::S3::BucketPolicy","Custom::S3BucketNotifications","AWS::KMS::Key","AWS::SNS::Topic","AWS::SNS::TopicPolicy","AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function"]},"aws-s3-sqs":{className:"S3ToSqs",packageName:"aws-s3-sqs",friendlyName:"S3 To Sqs",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-s3-sqs/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-s3-sqs",requiredResourceTypes:["AWS::S3::Bucket","AWS::S3::BucketPolicy","Custom::S3BucketNotifications","AWS::SQS::Queue","AWS::SQS::QueuePolicy","AWS::KMS::Key","AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function"]},"aws-sns-lambda":{className:"SnsToLambda",packageName:"aws-sns-lambda",friendlyName:"Sns To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-sns-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-sns-lambda",requiredResourceTypes:["AWS::IAM::Role","AWS::IAM::Policy","AWS::Lambda::Function","AWS::Lambda::Permission","AWS::SNS::Subscription","AWS::SNS::Topic","AWS::SNS::TopicPolicy"]},"aws-sns-sqs":{className:"SnsToSqs",packageName:"aws-sns-sqs",friendlyName:"Sns To Sqs",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-sns-sqs/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-sns-sqs",requiredResourceTypes:["AWS::SNS::Topic","AWS::SNS::TopicPolicy","AWS::SQS::Queue","AWS::SQS::QueuePolicy","AWS::SNS::Subscription","AWS::KMS::Key"]},"aws-eventbridge-kinesisstreams":{className:"EventbridgeToKinesisStreams",packageName:"aws-eventbridge-kinesisstreams",friendlyName:"EventBridge To Kinesis Streams",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-eventbridge-kinesisstreams/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-eventbridge-kinesisstreams",requiredResourceTypes:["AWS::Events::Rule","AWS::Kinesis::Stream"]},"aws-eventbridge-sns":{className:"EventbridgeToSns",packageName:"aws-eventbridge-sns",friendlyName:"EventBridge To SNS",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-eventbridge-sns/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-eventbridge-sns",requiredResourceTypes:["AWS::Events::Rule","AWS::SNS::Topic"]},"aws-eventbridge-sqs":{className:"EventbridgeToSqs",packageName:"aws-eventbridge-sqs",friendlyName:"EventBridge To SQS",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-eventbridge-sqs/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-eventbridge-sqs",requiredResourceTypes:["AWS::Events::Rule","AWS::SQS::Queue"]},"aws-eventbridge-stepfunctions":{className:"EventbridgeToStepfunctions",packageName:"aws-eventbridge-stepfunctions",friendlyName:"EventBridge To StepFunctions",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-eventbridge-stepfunctions/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-eventbridge-stepfunctions",requiredResourceTypes:["AWS::Events::Rule","AWS::StepFunctions::StateMachine"]},"aws-alb-fargate":{className:"AlbToFargate",packageName:"aws-alb-fargate",friendlyName:"ALB To Fargate",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-alb-fargate/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-alb-fargate",requiredResourceTypes:["AWS::ElasticLoadBalancingV2::LoadBalancer","AWS::ElasticLoadBalancingV2::Listener","AWS::ECS::Cluster","AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::IAM::Role","AWS::Logs::LogGroup"]},"aws-alb-lambda":{className:"AlbToLambda",packageName:"aws-alb-lambda",friendlyName:"ALB To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-alb-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-alb-lambda",requiredResourceTypes:["AWS::ElasticLoadBalancingV2::LoadBalancer","AWS::ElasticLoadBalancingV2::Listener","AWS::Lambda::Function","AWS::IAM::Role","AWS::Logs::LogGroup"]},"aws-apigateway-iot":{className:"ApiGatewayToIot",packageName:"aws-apigateway-iot",friendlyName:"API Gateway To IoT",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-apigateway-iot/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-apigateway-iot",requiredResourceTypes:["AWS::ApiGateway::RestApi","AWS::ApiGateway::Resource","AWS::ApiGateway::Method","AWS::IoT::TopicRule"]},"aws-apigateway-sagemakerendpoint":{className:"ApiGatewayToSagemakerendpoint",packageName:"aws-apigateway-sagemakerendpoint",friendlyName:"API Gateway To SageMaker Endpoint",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-apigateway-sagemakerendpoint/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-apigateway-sagemakerendpoint",requiredResourceTypes:["AWS::ApiGateway::RestApi","AWS::ApiGateway::Integration","AWS::SageMaker::Endpoint"]},"aws-cloudfront-apigateway":{className:"CloudFrontToApiGateway",packageName:"aws-cloudfront-apigateway",friendlyName:"CloudFront To API Gateway",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-cloudfront-apigateway/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-cloudfront-apigateway",requiredResourceTypes:["AWS::CloudFront::Distribution","AWS::ApiGateway::RestApi","AWS::ApiGateway::Method"]},"aws-dynamodbstreams-lambda-elasticsearch-kibana":{className:"DynamoDBStreamsToLambdaElasticsearchKibana",packageName:"aws-dynamodbstreams-lambda-elasticsearch-kibana",friendlyName:"DynamoDB Streams To Lambda Elasticsearch Kibana",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-dynamodbstreams-lambda-elasticsearch-kibana/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-dynamodbstreams-lambda-elasticsearch-kibana",requiredResourceTypes:["AWS::DynamoDB::Stream","AWS::Lambda::Function","AWS::Elasticsearch::Domain","AWS::IAM::Role","AWS::Logs::LogGroup"]},"aws-dynamodbstreams-pipes-stepfunctions":{className:"DynamoDBStreamsToPipesStepfunctions",packageName:"aws-dynamodbstreams-pipes-stepfunctions",friendlyName:"DynamoDB Streams To Pipes StepFunctions",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-dynamodbstreams-pipes-stepfunctions/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-dynamodbstreams-pipes-stepfunctions",requiredResourceTypes:["AWS::DynamoDB::Stream","AWS::StepFunctions::StateMachine"]},"aws-eventbridge-kinesisfirehose-s3":{className:"EventbridgeToKinesisfirehoseToS3",packageName:"aws-eventbridge-kinesisfirehose-s3",friendlyName:"EventBridge To Kinesis Firehose To S3",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-eventbridge-kinesisfirehose-s3/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-eventbridge-kinesisfirehose-s3",requiredResourceTypes:["AWS::Events::Rule","AWS::KinesisFirehose::DeliveryStream","AWS::S3::Bucket"]},"aws-eventbridge-lambda":{className:"EventbridgeToLambda",packageName:"aws-eventbridge-lambda",friendlyName:"EventBridge To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-eventbridge-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-eventbridge-lambda",requiredResourceTypes:["AWS::Events::Rule","AWS::Lambda::Function","AWS::IAM::Role"]},"aws-fargate-dynamodb":{className:"FargateToDynamodb",packageName:"aws-fargate-dynamodb",friendlyName:"Fargate To DynamoDB",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-dynamodb/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-dynamodb",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::DynamoDB::Table"]},"aws-fargate-eventbridge":{className:"FargateToEventbridge",packageName:"aws-fargate-eventbridge",friendlyName:"Fargate To EventBridge",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-eventbridge/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-eventbridge",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::Events::Rule"]},"aws-fargate-kinesisfirehose":{className:"FargateToKinesisfirehose",packageName:"aws-fargate-kinesisfirehose",friendlyName:"Fargate To Kinesis Firehose",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-kinesisfirehose/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-kinesisfirehose",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::KinesisFirehose::DeliveryStream"]},"aws-fargate-kinesisstreams":{className:"FargateToKinesisstreams",packageName:"aws-fargate-kinesisstreams",friendlyName:"Fargate To Kinesis Streams",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-kinesisstreams/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-kinesisstreams",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::Kinesis::Stream"]},"aws-fargate-opensearch":{className:"FargateToOpensearch",packageName:"aws-fargate-opensearch",friendlyName:"Fargate To OpenSearch",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-opensearch/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-opensearch",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::OpenSearch::Domain"]},"aws-fargate-s3":{className:"FargateToS3",packageName:"aws-fargate-s3",friendlyName:"Fargate To S3",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-s3/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-s3",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::S3::Bucket"]},"aws-fargate-secretsmanager":{className:"FargateToSecretsmanager",packageName:"aws-fargate-secretsmanager",friendlyName:"Fargate To SecretsManager",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-secretsmanager/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-secretsmanager",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::SecretsManager::Secret"]},"aws-fargate-sns":{className:"FargateToSns",packageName:"aws-fargate-sns",friendlyName:"Fargate To SNS",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-sns/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-sns",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::SNS::Topic"]},"aws-fargate-sqs":{className:"FargateToSqs",packageName:"aws-fargate-sqs",friendlyName:"Fargate To SQS",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-sqs/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-sqs",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::SQS::Queue"]},"aws-fargate-ssmstringparameter":{className:"FargateToSsmstringparameter",packageName:"aws-fargate-ssmstringparameter",friendlyName:"Fargate To SSM String Parameter",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-ssmstringparameter/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-ssmstringparameter",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::SSM::StringParameter"]},"aws-fargate-stepfunctions":{className:"FargateToStepfunctions",packageName:"aws-fargate-stepfunctions",friendlyName:"Fargate To StepFunctions",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-fargate-stepfunctions/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-fargate-stepfunctions",requiredResourceTypes:["AWS::ECS::TaskDefinition","AWS::ECS::Service","AWS::StepFunctions::StateMachine"]},"aws-iot-kinesisfirehose-s3":{className:"IotToKinesisfirehoseToS3",packageName:"aws-iot-kinesisfirehose-s3",friendlyName:"IoT To Kinesis Firehose To S3",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-iot-kinesisfirehose-s3/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-iot-kinesisfirehose-s3",requiredResourceTypes:["AWS::IoT::TopicRule","AWS::KinesisFirehose::DeliveryStream","AWS::S3::Bucket"]},"aws-iot-kinesisstreams":{className:"IotToKinesisstreams",packageName:"aws-iot-kinesisstreams",friendlyName:"IoT To Kinesis Streams",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-iot-kinesisstreams/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-iot-kinesisstreams",requiredResourceTypes:["AWS::IoT::TopicRule","AWS::Kinesis::Stream"]},"aws-iot-lambda":{className:"IotToLambda",packageName:"aws-iot-lambda",friendlyName:"IoT To Lambda",documentationUrl:"https://docs.aws.amazon.com/solutions/latest/aws-iot-lambda/",githubUrl:"https://github.com/awslabs/aws-solutions-constructs/tree/main/aws-iot-lambda",requiredResourceTypes:["AWS::IoT::TopicRule","AWS::Lambda::Function","AWS::IAM::Role"]}}});var hP,gP=D(()=>{"use strict";mP();hP=async t=>{let e={};for(let s of t)try{let n=await import(`@aws-solutions-constructs/${s}`),r=Object.keys(n).find(u=>/^[A-Z][a-zA-Z0-9]*To[A-Z][a-zA-Z0-9]*$/.test(u));if(!r)continue;let i=`https://docs.aws.amazon.com/solutions/latest/${s}/`,o=`https://github.com/awslabs/aws-solutions-constructs/tree/main/${s}`,c=fP[s]?.requiredResourceTypes||[];e[s]={className:r,packageName:s,friendlyName:r.replace(/([a-z0-9])([A-Z])/g,"$1 $2").trim(),documentationUrl:i,githubUrl:o,requiredResourceTypes:c}}catch{}return e}});var j,me=D(()=>{"use strict";j=(t,e)=>t.Metadata?.["aws:cdk:path"]??e});var yP,W,$,ee,T,xP,fe=D(()=>{"use strict";yP={LOW:0,MEDIUM:1,HIGH:2,CRITICAL:3},W=(t,e)=>t?.resourceIdMetadata?.[e]?.constructLevel,$=t=>t==="L3-aws-solutions"||t==="L3-third-party",ee=t=>{let e=yP[t]??0;return e<=0?"LOW":Object.entries(yP).find(([,s])=>s===e-1)?.[0]},T=(t,e,s)=>{if(!$(e))return t;let n=s?` Look for a \`${s}\` argument on the construct.`:"";return`${t} This resource is owned by an L3 pattern \u2014 fix via the pattern's props${n} rather than escape-hatching the underlying CFN resource.`},xP=(t,e)=>{let s=t?.cdkContext?.[e];return s===!0||s==="true"}});var bP,SP=D(()=>{"use strict";me();fe();bP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::CertificateManager::Certificate")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[];return i.Properties?.ValidationMethod==="EMAIL"&&l.push(e(r,"ACM certificate uses email validation instead of DNS validation.",T("Use DNS validation for automated certificate renewal. Email validation requires manual intervention for renewals.",o),c("LOW"),"Operational Excellence",u,"cdkInsights")),i.Properties?.CertificateTransparencyLoggingPreference==="DISABLED"&&l.push(e(r,"ACM certificate has certificate transparency logging disabled.",T("Enable certificate transparency logging for security monitoring and to detect misissued certificates.",o),c("LOW"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var vP,CP=D(()=>{"use strict";me();fe();vP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::ApiGateway::RestApi"&&!i.Properties?.EndpointConfiguration?.Types?.includes("PRIVATE")){let o=W(s,r),a=$(o);n[r]={issues:[e(r,"API Gateway is publicly accessible.",T("If this API is intentionally public, ignore this finding (or suppress it via .cdk-insights.json). For internal APIs, use PRIVATE endpoints to restrict access.",o,"endpointConfiguration / endpointTypes"),a?"LOW":"MEDIUM","Security",j(i,r),"cdkInsights")]}}return n},{})});var tQ,DP,AP=D(()=>{"use strict";me();fe();tQ=t=>typeof t=="string"&&t.toUpperCase()==="OPTIONS",DP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{let o=i.Type==="AWS::ApiGateway::Method",a=i.Type==="AWS::ApiGatewayV2::Route";if(!o&&!a)return n;let c=i.Properties??{},u=c.AuthorizationType;if(o&&tQ(c.HttpMethod)||!(u===void 0||u==="NONE"))return n;let d=j(i,r),p=W(s,r),f=$(p),m=o?"API Gateway Method has no authorization (AuthorizationType is NONE).":"API Gateway v2 Route has no authorization (AuthorizationType is NONE).";return n[r]={issues:[e(r,m,T("Set AuthorizationType to AWS_IAM, COGNITO_USER_POOLS, CUSTOM (REST), or JWT (HTTP API). Public-by-default endpoints expose backend Lambdas to anyone on the internet without authentication. If the route is intentionally public (e.g. a webhook receiver), prefer api-key + WAF rate limiting.",p,"methodOptions.authorizationType"),f?"MEDIUM":"HIGH","Security",d,"cdkInsights")]},n},{})});var wP,EP=D(()=>{"use strict";me();fe();wP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::AppSync::GraphQLApi")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[],d=i.Properties?.AuthenticationType;d==="API_KEY"&&l.push(e(r,"AppSync API uses API key authentication.",T("Consider using AWS_IAM, AMAZON_COGNITO_USER_POOLS, or OPENID_CONNECT for production workloads. API keys are best for development or public read-only access.",o),c("MEDIUM"),"Security",u,"cdkInsights"));let p=i.Properties?.AdditionalAuthenticationProviders;return d!=="AWS_IAM"&&(!p||p.length===0)&&l.push(e(r,"AppSync API does not have multiple authentication providers configured.",T("Consider adding AdditionalAuthenticationProviders for flexibility in authenticating different client types.",o),c("LOW"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var RP,IP=D(()=>{"use strict";me();fe();RP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::AppSync::GraphQLApi")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[],d=i.Properties?.LogConfig;return d?d.FieldLogLevel==="NONE"&&l.push(e(r,"AppSync API has field-level logging disabled.",T("Set FieldLogLevel to ERROR or ALL to capture GraphQL resolver execution details.",o),c("LOW"),"Operational Excellence",u,"cdkInsights")):l.push(e(r,"AppSync API does not have logging configured.",T("Enable LogConfig to capture request/response logs in CloudWatch for debugging and monitoring.",o),c("MEDIUM"),"Operational Excellence",u,"cdkInsights")),i.Properties?.XrayEnabled!==!0&&l.push(e(r,"AppSync API does not have X-Ray tracing enabled.",T("Enable XrayEnabled for distributed tracing and performance analysis.",o),c("LOW"),"Operational Excellence",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var kP,_P=D(()=>{"use strict";me();fe();kP=(t,e,s)=>{let n=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::AppSync::GraphQLApi"),r=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::WAFv2::WebACLAssociation"),i=new Set(r.map(([,o])=>{let a=o.Properties?.ResourceArn;return typeof a=="string"?a:a?.["Fn::GetAtt"]?.[0]?a["Fn::GetAtt"][0]:null}).filter(Boolean));return n.reduce((o,[a,c])=>{let u=j(c,a);if(!i.has(a)){let d=W(s,a),p=$(d),f=m=>p?ee(m):m;o[a]={issues:[e(a,"AppSync API does not have AWS WAF protection.",T("Associate a WAF WebACL to protect against common web exploits and control access to the API.",d),f("MEDIUM"),"Security",u,"cdkInsights")]}}return o},{})}});var FP,TP=D(()=>{"use strict";me();fe();FP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Backup::BackupPlan")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[],p=i.Properties?.BackupPlan?.BackupPlanRule||[];for(let f of p){(f.CopyActions||[]).length===0&&l.push(e(r,`Backup rule "${f.RuleName||"unnamed"}" does not have cross-region copy configured.`,T("Add CopyActions to replicate backups to another region for disaster recovery.",o),c("LOW"),"Reliability",u,"cdkInsights"));let g=f.Lifecycle;!g?.DeleteAfterDays&&!g?.MoveToColdStorageAfterDays&&l.push(e(r,`Backup rule "${f.RuleName||"unnamed"}" has no lifecycle configuration.`,T("Set DeleteAfterDays or MoveToColdStorageAfterDays to manage backup retention and costs.",o),c("LOW"),"Cost Optimization",u,"cdkInsights"))}return l.length>0&&(n[r]={issues:l}),n},{})});var PP,LP=D(()=>{"use strict";me();fe();PP=(t,e,s)=>{let n=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::Backup::BackupVault"),r=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::Backup::BackupVaultLock"),i=new Set(r.map(([,o])=>{let a=o.Properties?.BackupVaultName;return typeof a=="string"?a:typeof a=="object"&&a?.Ref?a.Ref:null}).filter(Boolean));return n.reduce((o,[a,c])=>{let u=W(s,a),l=$(u),d=b=>l?ee(b):b,p=j(c,a),f=[];c.Properties?.EncryptionKeyArn||f.push(e(a,"Backup vault uses default AWS-managed encryption key.",T("Specify a customer-managed KMS key using EncryptionKeyArn for additional control over encryption.",u),d("LOW"),"Security",p,"cdkInsights"));let g=c.Properties?.BackupVaultName,h=typeof g=="string"?g:typeof g=="object"?g?.Ref:void 0;return i.has(a)||h&&i.has(h)||f.push(e(a,"Backup vault does not have a vault lock configured.",T("Add a BackupVaultLock to enforce retention policies and prevent backup deletion for compliance requirements.",u),d("LOW"),"Security",p,"cdkInsights")),f.length>0&&(o[a]={issues:f}),o},{})}});var OP,MP=D(()=>{"use strict";me();fe();OP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::CloudFront::Distribution")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r);return i.Properties?.DistributionConfig?.DefaultCacheBehavior?.ViewerProtocolPolicy==="allow-all"&&(n[r]={issues:[e(r,"CloudFront distribution allows HTTP traffic (ViewerProtocolPolicy is allow-all).",T('Set ViewerProtocolPolicy to "https-only" or "redirect-to-https" to enforce HTTPS and protect data in transit.',o),c("HIGH"),"Security",u,"cdkInsights")]}),n},{})});var BP,NP=D(()=>{"use strict";me();fe();BP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::CloudFront::Distribution")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r);return i.Properties?.DistributionConfig?.Logging?.Bucket||(n[r]={issues:[e(r,"CloudFront distribution does not have access logging enabled.",T("Enable access logging to an S3 bucket to track viewer requests for security analysis, auditing, and troubleshooting.",o),c("MEDIUM"),"Security",u,"cdkInsights")]}),n},{})});var sQ,$P,WP=D(()=>{"use strict";me();fe();sQ=["SSLv3","TLSv1","TLSv1_2016","TLSv1.1_2016"],$P=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::CloudFront::Distribution")return n;let o=j(i,r),c=i.Properties?.DistributionConfig?.ViewerCertificate,u=c?.MinimumProtocolVersion;if(c?.CloudFrontDefaultCertificate)return n;let l=W(s,r),d=$(l),p=f=>d?ee(f):f;return u&&sQ.includes(u)&&(n[r]={issues:[e(r,`CloudFront distribution uses outdated TLS version (${u}).`,T("Use TLSv1.2_2021 or later for improved security. Older TLS versions have known vulnerabilities.",l),p("MEDIUM"),"Security",o,"cdkInsights")]}),n},{})});var jP,UP=D(()=>{"use strict";me();fe();jP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::CloudFront::Distribution")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);return i.Properties?.DistributionConfig?.WebACLId||(n[r]={issues:[e(r,"CloudFront distribution has no WAF WebACL associated.",T("Associate a WAF WebACL to protect against common web exploits, SQL injection, XSS, and DDoS attacks.",o),c("MEDIUM"),"Security",u,"cdkInsights")]}),n},{})});var HP,GP=D(()=>{"use strict";HP=(t,e)=>Object.entries(t.Resources||{}).some(([,n])=>n.Type==="AWS::CloudTrail::Trail")?{}:{Global:{issues:[e("Global","No CloudTrail Trail defined in this stack.","CloudTrail is most commonly configured at the AWS account or organization level (one Trail covers every stack). If account-level CloudTrail is already in place, suppress this rule. If not, add a CloudTrail Trail at the account level \u2014 defining one per stack is rarely the right shape.","LOW","Security","Global","cdkInsights")]}}});var zP,qP=D(()=>{"use strict";me();fe();zP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::CloudWatch::Alarm")return n;let o=W(s,r),a=$(o),c=g=>a?ee(g):g,u=j(i,r),l=[],d=i.Properties?.AlarmActions,p=i.Properties?.OKActions,f=i.Properties?.InsufficientDataActions;return(!d||d.length===0)&&l.push(e(r,"CloudWatch Alarm has no alarm actions configured.",T("Add AlarmActions (SNS topic, Lambda, etc.) to receive notifications when the alarm state changes to ALARM.",o),c("MEDIUM"),"Operational Excellence",u,"cdkInsights")),i.Properties?.TreatMissingData||l.push(e(r,"CloudWatch Alarm does not specify how to treat missing data.",T("Set TreatMissingData to define alarm behavior when data points are missing (missing, ignore, breaching, or notBreaching).",o),c("LOW"),"Operational Excellence",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var KP,VP=D(()=>{"use strict";me();fe();KP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Logs::LogGroup")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);return i.Properties?.KmsKeyId||(n[r]={issues:[e(r,"CloudWatch Log Group is not encrypted with a customer-managed KMS key.",T("Enable KMS encryption using KmsKeyId to protect sensitive log data at rest with customer-managed keys.",o),c("LOW"),"Security",u,"cdkInsights")]}),n},{})});var nQ,rQ,ZP,YP=D(()=>{"use strict";me();fe();nQ="@aws-cdk/aws-lambda:logRetentionDefaultsTo30Days",rQ=t=>/\/LogRetention[0-9A-Fa-f]*$/.test(t)||/LogRetention[0-9A-Fa-f]+$/.test(t),ZP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Logs::LogGroup")return n;let o=j(i,r),a=i.Properties?.RetentionInDays,c=W(s,r),u=$(c);return a!==void 0||xP(s,nQ)&&rQ(o||r)||(n[r]={issues:[e(r,"CloudWatch Log Group has no retention period set (logs retained indefinitely).",T("Set RetentionInDays to control storage costs. Consider 30-90 days for operational logs, longer for compliance requirements.",c,"logGroupProps.retention"),u?"LOW":"MEDIUM","Cost Optimization",o,"cdkInsights")]}),n},{})});var JP,QP=D(()=>{"use strict";me();fe();JP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Cognito::UserPool")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r),l=i.Properties?.MfaConfiguration;return(!l||l==="OFF")&&(n[r]={issues:[e(r,"Cognito User Pool has MFA disabled.",T("Enable MFA (OPTIONAL or ON) to add an extra layer of security for user authentication.",o),c("MEDIUM"),"Security",u,"cdkInsights")]}),n},{})});var XP,eL=D(()=>{"use strict";me();fe();XP=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Cognito::UserPool")return n;let o=[],a=j(i,r),c=i.Properties?.PasswordPolicy,u=W(s,r),l=$(u),d=p=>l?ee(p):p;if(!c)o.push(e(r,"Cognito User Pool has no password policy configured.",T("Configure a strong password policy with minimum length, uppercase, lowercase, numbers, and symbols requirements.",u,"passwordPolicy"),d("HIGH"),"Security",a,"cdkInsights"));else{let p=c.MinimumLength||8;p<12&&o.push(e(r,`Cognito password policy has minimum length of ${p} characters.`,T("Set MinimumLength to at least 12 characters for stronger security against brute-force attacks.",u,"passwordPolicy.minLength"),d("MEDIUM"),"Security",a,"cdkInsights")),c.RequireSymbols===!1&&o.push(e(r,"Cognito password policy does not require symbols.",T("Enable RequireSymbols for stronger password complexity requirements.",u,"passwordPolicy.requireSymbols"),d("LOW"),"Security",a,"cdkInsights"))}return o.length>0&&(n[r]={issues:o}),n},{})});var tL,sL=D(()=>{"use strict";me();fe();tL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Cognito::UserPool")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r),l=i.Properties?.UserPoolAddOns?.AdvancedSecurityMode;return(!l||l==="OFF")&&(n[r]={issues:[e(r,"Cognito User Pool does not have advanced security features enabled.",T("Enable UserPoolAddOns with AdvancedSecurityMode set to AUDIT or ENFORCED to detect compromised credentials and block suspicious sign-ins.",o),c("LOW"),"Security",u,"cdkInsights")]}),n},{})});var nL,rL=D(()=>{"use strict";me();fe();nL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::DynamoDB::Table"||i.Properties?.SSESpecification?.SSEEnabled===!0)return n;let a=j(i,r),c=W(s,r),u=$(c);return n[r]={issues:[e(r,"DynamoDB Table is not configured with KMS encryption.",T("Set SSESpecification.SSEEnabled to true and provide a customer-managed KMSMasterKeyId. Without SSESpecification, DynamoDB encrypts with an AWS-owned key \u2014 adequate for general use but not for HIPAA / PCI-DSS workloads that require customer-controlled key rotation and audit.",c,"tableProps.encryption"),u?"LOW":"MEDIUM","Security",a,"cdkInsights")]},n},{})});var iL,oL=D(()=>{"use strict";me();fe();iL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::DynamoDB::Table"||i.Properties?.PointInTimeRecoverySpecification?.PointInTimeRecoveryEnabled===!0)return n;let a=j(i,r),c=W(s,r),u=$(c);return n[r]={issues:[e(r,"DynamoDB Table does not have Point-in-Time Recovery enabled.",T("Set PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled to true to enable continuous backups for the last 35 days. Required by HIPAA and SOC2 for data resilience.",c,"tableProps.pointInTimeRecoverySpecification"),u?"LOW":"MEDIUM","Reliability",a,"cdkInsights")]},n},{})});var aL,cL=D(()=>{"use strict";me();fe();aL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::DynamoDB::Table")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=i.Properties?.BillingMode,l=j(i,r);return(!u||u==="PROVISIONED")&&(n[r]={issues:[e(r,"DynamoDB table uses provisioned capacity without on-demand billing.",T("Consider using BillingMode: PAY_PER_REQUEST for automatic scaling and cost optimization, especially for unpredictable workloads. For predictable workloads, configure Application Auto Scaling.",o),c("MEDIUM"),"Cost Optimization",l,"cdkInsights")]}),n},{})});var uL,lL=D(()=>{"use strict";me();fe();uL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::DynamoDB::Table"&&!i.Properties?.StreamSpecification){let o=W(s,r),a=$(o),c=u=>a?ee(u):u;n[r]={issues:[e(r,"DynamoDB table does not have streams enabled.",T("Consider enabling DynamoDB Streams to capture item-level changes for analytics, auditing, event-driven architectures, and cross-region replication.",o),c("LOW"),"Operational Excellence",j(i,r),"cdkInsights")]}}return n},{})});var dL,pL=D(()=>{"use strict";me();fe();dL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EC2::Volume")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=[],l=j(i,r),d=i.Properties??{};return d.Encrypted!==!0&&u.push(e(r,"EBS Volume is not encrypted.",T("Enable encryption on EBS volumes to protect data at rest. Use the Encrypted property and optionally specify a KmsKeyId.",o),c("HIGH"),"Security",l,"cdkInsights")),d.VolumeType==="gp2"&&u.push(e(r,"EBS Volume uses gp2 storage type.",T("Consider migrating to gp3 for up to 20% cost savings with better baseline performance (3,000 IOPS and 125 MB/s throughput).",o),c("LOW"),"Cost Optimization",l,"cdkInsights")),u.length>0&&(n[r]={issues:u}),n},{})});var fL,mL=D(()=>{"use strict";me();fe();fL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EFS::FileSystem"||i.Properties?.Encrypted===!0)return n;let a=j(i,r),c=W(s,r),u=$(c);return n[r]={issues:[e(r,"EFS FileSystem is not encrypted at rest.",T("Set Encrypted to true and provide KmsKeyId for a customer-managed key. Encryption can only be enabled at filesystem creation; existing unencrypted filesystems require data migration to a new encrypted filesystem.",c,"fileSystemProps.encrypted"),u?"MEDIUM":"HIGH","Security",a,"cdkInsights")]},n},{})});var hL,gL,yL=D(()=>{"use strict";me();fe();hL=t=>Array.isArray(t)&&t.length>0,gL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::AutoScaling::AutoScalingGroup")return n;let o=i.Properties??{};if(!(hL(o.LoadBalancerNames)||hL(o.TargetGroupARNs))||o.HealthCheckType==="ELB")return n;let u=j(i,r),l=W(s,r),d=$(l);return n[r]={issues:[e(r,"AutoScalingGroup attached to a load balancer is not using ELB health checks.",T("Set HealthCheckType to ELB so unhealthy instances detected by the load balancer are recycled. EC2 health checks (the default) only catch instance-level failures, missing app-level outages the LB would otherwise detect.",l,"asgProps.healthCheckType"),d?"LOW":"MEDIUM","Reliability",u,"cdkInsights")]},n},{})});var xL,bL=D(()=>{"use strict";me();fe();xL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::AutoScaling::LaunchConfiguration"||i.Properties?.AssociatePublicIpAddress!==!0)return n;let o=j(i,r),a=W(s,r),c=$(a);return n[r]={issues:[e(r,"AutoScaling LaunchConfiguration sets AssociatePublicIpAddress=true.",T("Set AssociatePublicIpAddress to false. Instances launched from this configuration will get a public IP and be reachable from the internet directly; prefer placing them in private subnets behind an ALB / NLB.",a,"launchConfigProps.associatePublicIpAddress"),c?"MEDIUM":"HIGH","Security",o,"cdkInsights")]},n},{})});var SL,vL=D(()=>{"use strict";me();fe();SL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::EC2::Instance"&&i.Properties?.InstanceType?.toString().startsWith("t2")){let o=W(s,r),a=$(o),c=u=>a?ee(u):u;n[r]={issues:[e(r,"EC2 instance is using an older t2 instance. Consider upgrading to t3 for better performance and cost savings.",T("Upgrade to a t3 instance for improved performance, lower latency, and better cost efficiency.",o),c("MEDIUM"),"Cost Optimization",j(i,r),"cdkInsights")]}}return n},{})});var CL,DL=D(()=>{"use strict";me();fe();CL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::EC2::NatGateway"){let o=W(s,r),a=$(o),c=u=>a?ee(u):u;n[r]={issues:[e(r,"NAT Gateway detected. NAT Gateways incur hourly charges (~$0.045/hr) plus data processing fees (~$0.045/GB).",T("Consider alternatives like NAT instances for lower traffic, VPC endpoints for AWS services, or IPv6 egress-only internet gateways to reduce costs.",o),c("LOW"),"Cost Optimization",j(i,r),"cdkInsights")]}}return n},{})});var AL,wL=D(()=>{"use strict";me();fe();AL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EC2::Instance")return n;let o=i.Properties?.NetworkInterfaces;if(!Array.isArray(o)||o.length===0||!o.some(d=>d&&d.AssociatePublicIpAddress===!0))return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,"EC2 Instance has a network interface with public IP association (AssociatePublicIpAddress=true).",T("Set AssociatePublicIpAddress to false on the NetworkInterface, or remove the property and rely on subnet defaults. A public IP on the instance ENI makes it directly internet-reachable; prefer a NAT/ALB for outbound and inbound traffic.",u,"instanceProps.associatePublicIpAddress"),l?"MEDIUM":"HIGH","Security",c,"cdkInsights")]},n},{})});var iQ,oQ,aQ,EL,RL=D(()=>{"use strict";me();fe();iQ=[22,3389,3306,5432,1433,27017,6379],oQ=t=>t.CidrIp==="0.0.0.0/0"||t.CidrIpv6==="::/0",aQ=(t,e,s)=>e===void 0||s===void 0?!1:t>=e&&t<=s,EL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EC2::SecurityGroup")return n;let o=W(s,r),a=$(o),c=h=>a?ee(h):h,u=[],l=j(i,r),d=i.Properties?.SecurityGroupIngress||[],p=i.Properties?.SecurityGroupEgress||[],f=d.some(h=>h.CidrIp==="0.0.0.0/0"),m=d.some(h=>h.CidrIpv6==="::/0");f&&u.push(e(r,"Security Group allows unrestricted IPv4 ingress (0.0.0.0/0).",T("Restrict security group rules to specific IPs and ports.",o),c("HIGH"),"Security",l,"cdkInsights")),m&&u.push(e(r,"Security Group allows unrestricted IPv6 ingress (::/0).",T("Restrict security group rules to specific IPs and ports.",o),c("HIGH"),"Security",l,"cdkInsights"));for(let h of d)if(oQ(h)){for(let y of iQ)if(aQ(y,h.FromPort,h.ToPort)){u.push(e(r,`Security Group exposes port ${y} to the internet.`,T("Restrict access to management and database ports. Use bastion hosts, VPN, or AWS Systems Manager Session Manager instead.",o),c("CRITICAL"),"Security",l,"cdkInsights"));break}}return p.some(h=>h.CidrIp==="0.0.0.0/0")&&u.push(e(r,"Security Group allows unrestricted egress to 0.0.0.0/0.",T("Consider restricting egress rules to specific destinations for defense in depth.",o),c("LOW"),"Security",l,"cdkInsights")),d.length===0&&p.length===0&&u.push(e(r,"Security Group has no ingress or egress rules defined.",T("Review if this security group is in use. Empty security groups may indicate orphaned resources or misconfiguration.",o),c("LOW"),"Operational Excellence",l,"cdkInsights")),u.length>0&&(n[r]={issues:u}),n},{})});var IL,kL=D(()=>{"use strict";me();fe();IL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EC2::Subnet"||i.Properties?.MapPublicIpOnLaunch!==!0)return n;let o=j(i,r),a=W(s,r),c=$(a);return n[r]={issues:[e(r,"EC2 Subnet auto-assigns public IPs to launched instances (MapPublicIpOnLaunch=true).",T("Set MapPublicIpOnLaunch to false unless this is intentionally a public subnet. Instances should opt into a public IP at the ENI level rather than inheriting it from subnet defaults \u2014 keeps the blast radius small if a private workload accidentally lands here.",a,"subnetProps.mapPublicIpOnLaunch"),c?"LOW":"MEDIUM","Security",o,"cdkInsights")]},n},{})});var _L,FL=D(()=>{"use strict";me();fe();_L=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ECR::Repository")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);return i.Properties?.ImageTagMutability!=="IMMUTABLE"&&(n[r]={issues:[e(r,"ECR repository allows mutable image tags.",T("Set ImageTagMutability to IMMUTABLE to prevent image tags from being overwritten, ensuring deployment consistency.",o),c("MEDIUM"),"Security",u,"cdkInsights")]}),n},{})});var TL,PL=D(()=>{"use strict";me();fe();TL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ECR::Repository")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);return i.Properties?.LifecyclePolicy?.LifecyclePolicyText||(n[r]={issues:[e(r,"ECR repository does not have a lifecycle policy configured.",T("Add a lifecycle policy to automatically clean up old or untagged images and reduce storage costs.",o),c("MEDIUM"),"Cost Optimization",u,"cdkInsights")]}),n},{})});var LL,OL=D(()=>{"use strict";me();fe();LL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ECR::Repository")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[];return i.Properties?.ImageScanningConfiguration?.ScanOnPush!==!0&&l.push(e(r,"ECR repository does not have image scanning on push enabled.",T("Enable ScanOnPush in ImageScanningConfiguration to automatically scan images for vulnerabilities when pushed.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var ML,BL=D(()=>{"use strict";me();fe();ML=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ECS::TaskDefinition")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=[],l=j(i,r),d=i.Properties?.ContainerDefinitions||[];for(let p of d)p.LogConfiguration?.LogDriver||u.push(e(r,`ECS container "${p.Name||"unnamed"}" has no logging configuration.`,T("Configure LogConfiguration with awslogs driver to send container logs to CloudWatch for monitoring and debugging.",o),c("MEDIUM"),"Operational Excellence",l,"cdkInsights"));return u.length>0&&(n[r]={issues:u}),n},{})});var NL,$L=D(()=>{"use strict";me();fe();NL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ECS::Service")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=i.Properties?.ServiceConnectConfiguration;if(!u||u.Enabled!==!0||u.LogConfiguration?.LogDriver)return n;let d=j(i,r);return n[r]={issues:[e(r,"ECS Service Connect is enabled without an access log configuration.",T("Configure ServiceConnectConfiguration.LogConfiguration with a LogDriver (e.g. awslogs) to capture inter-service traffic metadata for audit, debugging, and incident response.",o),c("MEDIUM"),"Security",d,"cdkInsights")]},n},{})});var WL,jL=D(()=>{"use strict";me();fe();WL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ECS::TaskDefinition")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=[],l=j(i,r),d=i.Properties?.ContainerDefinitions||[];for(let p of d){let f=p.Memory||p.MemoryReservation,m=p.Cpu;!f&&!m&&u.push(e(r,`ECS container "${p.Name||"unnamed"}" has no CPU or memory limits defined.`,T("Define CPU and Memory limits to prevent runaway containers and ensure predictable resource allocation.",o),c("LOW"),"Reliability",l,"cdkInsights"))}return u.length>0&&(n[r]={issues:u}),n},{})});var cQ,UL,HL=D(()=>{"use strict";me();fe();cQ=/(^|_)(secret|password|passwd|pwd|credential|private_key|api_key|api_secret|auth_token|access_key|access_secret|bearer_token|jwt_secret|encryption_key|signing_key)(_|$)/i,UL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ECS::TaskDefinition")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=[],l=j(i,r),d=i.Properties?.ContainerDefinitions||[];for(let p of d){let f=p.Environment||[];for(let m of f)cQ.test(m.Name||"")&&u.push(e(r,`ECS task definition has sensitive environment variable "${m.Name}" in plaintext.`,T('Use AWS Secrets Manager or SSM Parameter Store with the "secrets" property instead of plaintext environment variables.',o),c("HIGH"),"Security",l,"cdkInsights"))}return u.length>0&&(n[r]={issues:u}),n},{})});var GL,zL=D(()=>{"use strict";me();fe();GL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EKS::Cluster")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[];return i.Properties?.EncryptionConfig?.some(f=>f.Resources?.includes("secrets"))||l.push(e(r,"EKS cluster does not have Kubernetes secrets encryption enabled.",T("Configure EncryptionConfig with a KMS key to encrypt secrets stored in etcd.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var qL,KL=D(()=>{"use strict";me();fe();qL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EKS::Cluster")return n;let o=W(s,r),a=$(o),c=h=>a?ee(h):h,u=j(i,r),l=[],p=i.Properties?.Logging?.ClusterLogging?.EnabledTypes||[],f=p.map(h=>h.Type).filter(h=>!!h),g=["api","audit","authenticator","controllerManager","scheduler"].filter(h=>!f.includes(h));return g.length>0&&l.push(e(r,`EKS cluster is missing control plane logging for: ${g.join(", ")}.`,T("Enable all control plane log types (api, audit, authenticator, controllerManager, scheduler) for comprehensive cluster monitoring.",o),c("MEDIUM"),"Operational Excellence",u,"cdkInsights")),p.length===0?(n[r]={issues:[e(r,"EKS cluster does not have any control plane logging enabled.",T("Enable control plane logging to CloudWatch for audit trails and troubleshooting Kubernetes API issues.",o),c("MEDIUM"),"Security",u,"cdkInsights")]},n):(l.length>0&&(n[r]={issues:l}),n)},{})});var VL,ZL=D(()=>{"use strict";me();fe();VL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EKS::Cluster")return n;let o=W(s,r),a=$(o),c=g=>a?ee(g):g,u=j(i,r),l=[],d=i.Properties?.ResourcesVpcConfig,p=d?.EndpointPublicAccess,f=d?.EndpointPrivateAccess,m=d?.PublicAccessCidrs;return p===!0&&f!==!0&&l.push(e(r,"EKS cluster has only public endpoint access enabled.",T("Enable EndpointPrivateAccess to allow communication between nodes and the API server within the VPC.",o),c("MEDIUM"),"Security",u,"cdkInsights")),p===!0&&(!m||m.length===0||m.includes("0.0.0.0/0"))&&l.push(e(r,"EKS cluster public endpoint is accessible from the internet (0.0.0.0/0).",T("Restrict PublicAccessCidrs to specific IP ranges that need to access the Kubernetes API.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var YL,JL=D(()=>{"use strict";me();fe();YL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ElasticLoadBalancingV2::LoadBalancer")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r);return(i.Properties?.LoadBalancerAttributes||[]).some(p=>p.Key==="deletion_protection.enabled"&&p.Value==="true")||(n[r]={issues:[e(r,"Load Balancer does not have deletion protection enabled.",T("Enable deletion protection to prevent accidental deletion of the load balancer in production environments.",o),c("MEDIUM"),"Reliability",u,"cdkInsights")]}),n},{})});var QL,XL=D(()=>{"use strict";me();fe();QL=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ElasticLoadBalancingV2::Listener")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=i.Properties?.Protocol,d=i.Properties?.Port;return l==="HTTP"&&d!==80?n[r]={issues:[e(r,`Load Balancer listener uses HTTP protocol on port ${d}.`,T("Use HTTPS protocol with a valid SSL certificate to encrypt traffic in transit.",o),c("HIGH"),"Security",u,"cdkInsights")]}:l==="HTTP"&&d===80&&((i.Properties?.DefaultActions||[]).some(m=>m.Type==="redirect"&&m.RedirectConfig?.Protocol==="HTTPS")||(n[r]={issues:[e(r,"Load Balancer HTTP listener on port 80 does not redirect to HTTPS.",T("Configure the HTTP listener to redirect to HTTPS to ensure encrypted traffic.",o),c("MEDIUM"),"Security",u,"cdkInsights")]})),n},{})});var e6,t6=D(()=>{"use strict";me();fe();e6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ElasticLoadBalancingV2::LoadBalancer")return n;let o=j(i,r);if(!(i.Properties?.LoadBalancerAttributes||[]).some(u=>u.Key==="access_logs.s3.enabled"&&u.Value==="true")){let u=W(s,r),l=$(u),d=p=>l?ee(p):p;n[r]={issues:[e(r,"Load Balancer does not have access logging enabled.",T("Enable access logging to S3 for security analysis, auditing, and troubleshooting of traffic patterns.",u,"accessLogs / logAccessLogs"),d("MEDIUM"),"Security",o,"cdkInsights")]}}return n},{})});var uQ,s6,n6=D(()=>{"use strict";me();fe();uQ=["ELBSecurityPolicy-2016-08","ELBSecurityPolicy-TLS-1-0-2015-04","ELBSecurityPolicy-TLS-1-1-2017-01","ELBSecurityPolicy-2015-05"],s6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ElasticLoadBalancingV2::Listener")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=i.Properties?.Protocol,d=i.Properties?.SslPolicy;return l!=="HTTPS"&&l!=="TLS"||d&&uQ.includes(d)&&(n[r]={issues:[e(r,`Load Balancer listener uses outdated security policy (${d}).`,T("Use ELBSecurityPolicy-TLS13-1-2-2021-06 or later for TLS 1.3 support, or at minimum ELBSecurityPolicy-TLS-1-2-2017-01 for TLS 1.2.",o),c("MEDIUM"),"Security",u,"cdkInsights")]}),n},{})});var r6,i6=D(()=>{"use strict";me();fe();r6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ElastiCache::ReplicationGroup")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[],d=i.Properties?.AuthToken,p=i.Properties?.TransitEncryptionEnabled;return!d&&p===!0&&l.push(e(r,"ElastiCache Redis cluster has transit encryption but no AUTH token configured.",T("Set AuthToken to require authentication for Redis connections, providing an additional security layer.",o),c("MEDIUM"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var o6,a6=D(()=>{"use strict";me();fe();o6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ElastiCache::ReplicationGroup"&&i.Type!=="AWS::ElastiCache::CacheCluster")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[];return i.Properties?.AtRestEncryptionEnabled!==!0&&l.push(e(r,"ElastiCache cluster does not have encryption at rest enabled.",T("Enable AtRestEncryptionEnabled to protect cached data at rest using AWS-managed or customer-managed keys.",o),c("HIGH"),"Security",u,"cdkInsights")),i.Properties?.TransitEncryptionEnabled!==!0&&l.push(e(r,"ElastiCache cluster does not have encryption in transit enabled.",T("Enable TransitEncryptionEnabled to protect data during transfer between clients and the cache.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var c6,u6=D(()=>{"use strict";me();fe();c6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::ElastiCache::ReplicationGroup")return n;let o=W(s,r),a=$(o),c=g=>a?ee(g):g,u=j(i,r),l=[],d=i.Properties?.AutomaticFailoverEnabled,p=i.Properties?.NumNodeGroups||1,f=i.Properties?.ReplicasPerNodeGroup||0;return d!==!0&&(p>1||f>0)&&l.push(e(r,"ElastiCache replication group has replicas but automatic failover is not enabled.",T("Enable AutomaticFailoverEnabled to automatically promote a replica to primary if the primary node fails.",o),c("MEDIUM"),"Reliability",u,"cdkInsights")),i.Properties?.MultiAZEnabled!==!0&&d===!0&&l.push(e(r,"ElastiCache replication group has automatic failover but Multi-AZ is not enabled.",T("Enable MultiAZEnabled to distribute nodes across availability zones for higher availability.",o),c("MEDIUM"),"Reliability",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var l6,d6=D(()=>{"use strict";me();fe();l6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Events::Rule")return n;let o=j(i,r),a=W(s,r),c=$(a),u=d=>c?ee(d):d,l=[];return i.Properties?.State!=="ENABLED"&&l.push(e(r,"EventBridge rule is disabled or not explicitly enabled.",T("Ensure the EventBridge rule State is set to ENABLED to trigger events as expected.",a,"enabled / state"),u("MEDIUM"),"Operational Excellence",o,"cdkInsights")),(!i.Properties?.Targets||Array.isArray(i.Properties.Targets)&&i.Properties.Targets.length===0)&&l.push(e(r,"EventBridge rule has no targets configured. Events matching this rule will be silently dropped.",T("Add at least one target (Lambda, SQS, SNS, Step Functions, etc.) to process matched events. Without targets, the rule matches events but takes no action.",a,"targets"),u("HIGH"),"Reliability",o,"cdkInsights")),l.length>0&&(n[r]={issues:[...n[r]?.issues||[],...l]}),n},{})});var lQ,dQ,p6,f6=D(()=>{"use strict";me();fe();lQ=t=>{if(t==="*")return!0;if(t&&typeof t=="object"){let e=t.AWS;if(e==="*"||Array.isArray(e)&&e.includes("*"))return!0}return!1},dQ=t=>t.Condition!==void 0&&t.Condition!==null&&typeof t.Condition=="object"&&Object.keys(t.Condition).length>0,p6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Events::EventBusPolicy")return n;let o=i.Properties??{},a=[];o.Principal!==void 0&&a.push({Effect:"Allow",Principal:o.Principal,Condition:o.Condition});let c=o.Statement;if(c&&(Array.isArray(c.Statement)?a.push(...c.Statement):a.push(c)),a.filter(f=>(f.Effect===void 0||f.Effect==="Allow")&&lQ(f.Principal)&&!dQ(f)).length===0)return n;let l=j(i,r),d=W(s,r),p=$(d);return n[r]={issues:[e(r,"EventBridge EventBusPolicy grants access to wildcard Principal without a Condition.",T("Replace wildcard Principal with a specific AWS account / org ID, or add a Condition (e.g. aws:PrincipalOrgID) to scope cross-account access. Wildcard principals on an event bus mean any AWS account can publish events to your bus.",d,"eventBusPolicyProps.statement"),p?"HIGH":"CRITICAL","Security",l,"cdkInsights")]},n},{})});var m6,h6=D(()=>{"use strict";me();fe();m6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Glue::Connection")return n;let o=W(s,r),a=$(o),c=m=>a?ee(m):m,u=j(i,r),l=[],d=i.Properties?.ConnectionInput,p=d?.ConnectionType,f=d?.PhysicalConnectionRequirements;if(p==="JDBC"){f?.SubnetId||l.push(e(r,"Glue JDBC connection does not specify a VPC subnet.",T("Configure PhysicalConnectionRequirements with SubnetId and SecurityGroupIdList for network isolation.",o),c("MEDIUM"),"Security",u,"cdkInsights"));let g=d?.ConnectionProperties?.JDBC_CONNECTION_URL||"";typeof g=="string"&&!g.includes("ssl=true")&&!g.includes("useSSL=true")&&l.push(e(r,"Glue JDBC connection URL may not enforce SSL.",T("Ensure the JDBC connection URL includes SSL parameters to encrypt data in transit.",o),c("LOW"),"Security",u,"cdkInsights"))}return l.length>0&&(n[r]={issues:l}),n},{})});var g6,y6=D(()=>{"use strict";me();fe();g6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Glue::Job")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=[];return i.Properties?.SecurityConfiguration||l.push(e(r,"Glue job does not have a security configuration specified.",T("Create and attach a SecurityConfiguration to enable encryption for job bookmarks, S3 data, and CloudWatch logs.",o),c("MEDIUM"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var x6,b6,pQ,S6,v6=D(()=>{"use strict";me();fe();x6=/^\d{12}$/,b6=/arn:aws:iam::(\d{12}):root/,pQ=t=>{if(!t)return[];if(typeof t=="string"){if(x6.test(t))return[t];let e=t.match(b6);return e?[e[1]]:[]}return typeof t=="object"&&t.AWS?(Array.isArray(t.AWS)?t.AWS:[t.AWS]).flatMap(s=>{if(x6.test(s))return[s];let n=s.match(b6);return n?[n[1]]:[]}):[]},S6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::IAM::Role")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=[],l=j(i,r),d=i.Properties?.AssumeRolePolicyDocument;if(d?.Statement){for(let p of d.Statement)if(p.Effect==="Allow"){let f=pQ(p.Principal);for(let m of f)u.push(e(r,`IAM Role allows cross-account trust from account ${m}.`,T("Verify this cross-account trust relationship is intentional and the external account is trusted. Consider adding conditions to restrict access.",o),c("MEDIUM"),"Security",l,"cdkInsights"))}}return u.length>0&&(n[r]={issues:u}),n},{})});var C6,D6=D(()=>{"use strict";fe();C6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::IAM::Policy"&&i.Type!=="AWS::IAM::Role")return n;let o=i.Properties?.Policies,a=[];if(Array.isArray(o))for(let f of o)f?.PolicyDocument&&a.push(f.PolicyDocument);let c=i.Properties?.PolicyDocument;c&&a.push(c);let u=W(s,r),l=$(u),d=f=>l?ee(f):f,p=[];for(let f of a){if(!f?.Statement)continue;let m=f.Statement;for(let g of m)if(g.Effect==="Allow"){let h=g.Action,y=g.Resource,b=h==="*"||Array.isArray(h)&&h.includes("*"),C=y==="*"||Array.isArray(y)&&y.includes("*");b&&C?p.push(e(r,"IAM policy allows all actions (*) on all resources (*). This grants administrative access.",T("Restrict both actions and resources to follow the principle of least privilege.",u,"rolePolicy / inlinePolicies"),d("CRITICAL"),"Security",r,"cdkInsights")):b?p.push(e(r,"IAM policy allows all actions (*). This is overly permissive.",T("Specify only the required actions instead of using wildcards.",u,"rolePolicy / inlinePolicies"),d("CRITICAL"),"Security",r,"cdkInsights")):C&&p.push(e(r,"IAM policy allows actions on all resources (*). This is overly permissive.",T("Restrict resources to specific ARNs instead of using wildcards.",u,"rolePolicy / inlinePolicies"),d("HIGH"),"Security",r,"cdkInsights"))}}return p.length>0&&(n[r]={issues:p}),n},{})});var fQ,mQ,A6,w6=D(()=>{"use strict";me();fe();fQ=[/\/ServiceRole\/Resource$/,/\/Role\/Resource$/,/\/InstanceRole\/Resource$/,/CustomResourceProvider\/Role$/],mQ=t=>fQ.some(e=>e.test(t)),A6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::IAM::Role")return n;let o=W(s,r),a=$(o),c=l=>a?ee(l):l,u=j(i,r);return mQ(u)||i.Properties?.PermissionsBoundary||(n[r]={issues:[e(r,"IAM Role has no permission boundary configured.",T("Consider using permission boundaries to limit the maximum permissions for delegated access and prevent privilege escalation.",o),c("LOW"),"Security",u,"cdkInsights")]}),n},{})});var E6,R6,I6=D(()=>{"use strict";me();fe();E6=t=>Array.isArray(t)&&t.length>0,R6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::IAM::User")return n;let o=i.Properties??{},a=E6(o.Policies),c=E6(o.ManagedPolicyArns);if(!a&&!c)return n;let u=j(i,r),l=W(s,r),d=$(l),p=[];return a&&p.push(e(r,"IAM User has inline policies attached.",T("Move policies to an IAM Group and add the user to the group, or attach via a Role assumed by the user. CIS AWS Foundations 1.15 requires users to inherit permissions through groups.",l,"userProps.attachInlinePolicy"),d?"LOW":"MEDIUM","Security",u,"cdkInsights")),c&&p.push(e(r,"IAM User has managed policies attached directly.",T("Attach managed policies to an IAM Group and add the user to that group. Direct attachment violates CIS AWS Foundations 1.15 (users must inherit permissions through groups).",l,"userProps.managedPolicies"),d?"LOW":"MEDIUM","Security",u,"cdkInsights")),n[r]={issues:p},n},{})});var k6,_6=D(()=>{"use strict";me();fe();k6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Kinesis::Stream")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=[],d=i.Properties?.StreamEncryption;return(!d?.EncryptionType||d.EncryptionType==="NONE")&&l.push(e(r,"Kinesis Data Stream does not have server-side encryption enabled.",T("Enable StreamEncryption with EncryptionType KMS to protect data at rest.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var F6,T6=D(()=>{"use strict";me();fe();F6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Kinesis::Stream")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[];i.Properties?.RetentionPeriodHours===24&&l.push(e(r,"Kinesis Data Stream uses minimum retention period (24 hours).",T("Consider increasing RetentionPeriodHours for applications that need to replay or reprocess data during failures.",o),c("LOW"),"Reliability",u,"cdkInsights"));let p=i.Properties?.StreamModeDetails?.StreamMode;return l.length>0&&(n[r]={issues:l}),n},{})});var hQ,P6,L6=D(()=>{"use strict";me();fe();hQ=t=>typeof t=="string"?t==="*":typeof t=="object"?Object.values(t).some(e=>Array.isArray(e)?e.includes("*"):e==="*"):!1,P6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if((i.Type==="AWS::KMS::Key"&&Array.isArray(i.Properties?.KeyPolicy?.Statement)?i.Properties.KeyPolicy.Statement:[]).some(c=>hQ(c.Principal))){let c=W(s,r),u=$(c);n[r]={issues:[e(r,"KMS key has a public policy.",T("Restrict the KMS key policy to specific IAM roles or users to prevent unauthorized access.",c,"keyPolicy / admins / encryptionKey"),u?"HIGH":"CRITICAL","Security",j(i,r),"cdkInsights")]}}return n},{})});var gQ,yQ,xQ,bQ,SQ,O6,vQ,CQ,DQ,AQ,wQ,M6,B6=D(()=>{"use strict";me();fe();gQ=new Set(["*","kms:*","kms:PutKeyPolicy"]),yQ=new Set(["*","kms:*","kms:PutKeyPolicy"]),xQ=new Set(["aws:PrincipalArn","aws:PrincipalAccount","aws:PrincipalIsAWSService"]),bQ=new Set(["StringNotEquals","StringNotLike","ArnNotLike","ArnNotEquals"]),SQ=t=>{if(t==="*")return!0;if(t&&typeof t=="object"&&!Array.isArray(t)){let e=t,s=e.AWS;if(s==="*"||Array.isArray(s)&&s.includes("*")||e.Service==="*")return!0}return!1},O6=t=>typeof t=="string"?[t]:Array.isArray(t)?t.filter(e=>typeof e=="string"):[],vQ=t=>O6(t).find(e=>gQ.has(e)),CQ=t=>{if(!t||typeof t!="object")return!1;for(let[e,s]of Object.entries(t)){if(!s||typeof s!="object")continue;let n=Object.keys(s);if(n.includes("aws:PrincipalIsAWSService"))return!0;if(bQ.has(e)){for(let r of n)if(xQ.has(r))return!0}}return!1},DQ=t=>{if(!t||typeof t!="object"||Array.isArray(t))return!1;let e=t.AWS;return(Array.isArray(e)?e:[e]).some(n=>{if(n==="*")return!1;if(typeof n=="string")return/:root$/.test(n);if(n&&typeof n=="object"){let r=JSON.stringify(n);return r.includes("AWS::AccountId")&&r.includes("root")}return!1})},AQ=t=>t.Effect!=="Allow"||t.NotPrincipal!==void 0||!DQ(t.Principal)?!1:O6(t.Action).some(s=>yQ.has(s)),wQ=t=>{if(t.Effect!=="Deny"||t.NotPrincipal!==void 0||!SQ(t.Principal))return;let e=vQ(t.Action);if(e&&!CQ(t.Condition))return e},M6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::KMS::Key")return n;let o=i.Properties?.KeyPolicy?.Statement;if(!Array.isArray(o)||o.some(AQ))return n;let a=o.map(wQ).find(d=>d!==void 0);if(!a)return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,`Key policy contains a Deny statement on ${a} with Principal: '*' and no carveout for the account root or admin role. This locks the account out of the KMS key \u2014 recovery requires breaking glass on the account root credentials AND scheduling a 7-30 day key deletion (which does not actually let you recover the key, just remove it). Effectively unrecoverable for any data the key has encrypted; AWS Support typically declines to intervene.`,T("Keep the auto-injected root Allow statement (CDK's defaultKeyPolicy) intact, or add an explicit Allow on Principal: { AWS: 'arn:aws:iam::<account>:root' } for Action: kms:*. Alternatively, add a NotPrincipal exemption or a Condition with StringNotEquals on aws:PrincipalArn to exempt your admin role(s).",u,"keyPolicy.statements"),l?"HIGH":"CRITICAL","Security",c,"cdkInsights")]},n},{})});var N6,$6=D(()=>{"use strict";me();fe();N6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Lambda::Function")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);return i.Properties?.ReservedConcurrentExecutions===void 0&&(n[r]={issues:[e(r,"Lambda function has no reserved concurrency configured.",T("Consider setting ReservedConcurrentExecutions to prevent the function from consuming all available account concurrency and to control scaling behavior.",o),c("LOW"),"Reliability",u,"cdkInsights")]}),n},{})});var EQ,RQ,tS,IQ,W6,j6=D(()=>{"use strict";me();fe();EQ=new Set(["events.amazonaws.com","sns.amazonaws.com","s3.amazonaws.com","ses.amazonaws.com","codecommit.amazonaws.com","codepipeline.amazonaws.com","config.amazonaws.com","cloudwatch.amazonaws.com","iot.amazonaws.com","logs.amazonaws.com","pipes.amazonaws.com","scheduler.amazonaws.com","cognito-idp.amazonaws.com"]),RQ=new Set(["apigateway.amazonaws.com","elasticloadbalancing.amazonaws.com","lambda.amazonaws.com"]),tS=t=>{if(typeof t=="string")return t;if(typeof t=="object"&&t!==null){let e=t;if(typeof e.Ref=="string")return e.Ref;let s=e["Fn::GetAtt"];if(Array.isArray(s)&&typeof s[0]=="string")return s[0]}return null},IQ=t=>{let e=new Map,s=(n,r)=>{e.has(n)||e.set(n,new Set),e.get(n)?.add(r)};for(let n of Object.values(t))if(n.Type==="AWS::Lambda::Permission"){let r=tS(n.Properties?.FunctionName),i=n.Properties?.Principal;if(!r||typeof i!="string")continue;EQ.has(i)?s(r,"async"):RQ.has(i)&&s(r,"sync")}else if(n.Type==="AWS::Lambda::EventSourceMapping"){let r=tS(n.Properties?.FunctionName);r&&s(r,"event-source")}else if(n.Type==="AWS::Lambda::EventInvokeConfig"){let r=tS(n.Properties?.FunctionName);r&&s(r,"async")}return e},W6=(t,e,s)=>{let n=t.Resources||{},r=IQ(n);return Object.entries(n).reduce((i,[o,a])=>{if(a.Type!=="AWS::Lambda::Function"||a.Properties?.DeadLetterConfig?.TargetArn)return i;let c=j(a,o),u=W(s,o),l=$(u),d=r.get(o)??new Set(["unknown"]),p=d.has("async"),f=d.has("sync"),m=d.has("event-source");return f&&!p&&!m?i:m&&!p?(i[o]={issues:[e(o,"Lambda function consumes an event source mapping without a failure destination.",T("For SQS/Kinesis/DynamoDB Streams, configure an OnFailure destination on the EventSourceMapping (DestinationConfig.OnFailure) \u2014 function-level DeadLetterConfig is for async invocations and does not apply to poll-based event sources.",u,"onFailure / deadLetterQueue (on EventSourceMapping)"),l?"LOW":"MEDIUM","Reliability",c,"cdkInsights")]},i):p?(i[o]={issues:[e(o,"Lambda function has no Dead Letter Queue configured for async invocations.",T("Configure a Dead Letter Queue (SQS or SNS) via DeadLetterConfig to capture failed async invocations for debugging, monitoring, and retry processing.",u,"deadLetterQueueEnabled / deadLetterQueue"),l?"LOW":"MEDIUM","Reliability",c,"cdkInsights")]},i):(i[o]={issues:[e(o,"Lambda function has no Dead Letter Queue configured (invocation mode could not be inferred).",T("No invocation source was detected in this template. If the function is invoked async (EventBridge, SNS, S3, etc.), configure DeadLetterConfig to capture failures. If it is invoked sync (API Gateway, ALB, direct invoke), DLQ does not apply and this finding can be suppressed.",u,"deadLetterQueueEnabled / deadLetterQueue"),"LOW","Reliability",c,"cdkInsights")]},i)},{})}});var kQ,U6,H6=D(()=>{"use strict";me();fe();kQ=/\b(secret|password|passwd|pwd|credential|private_key|api_key|api_secret|auth_token|access_key|access_secret|bearer_token|jwt_secret|encryption_key|signing_key)\b/i,U6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::Lambda::Function"){let o=W(s,r),a=$(o),c=l=>a?ee(l):l,u=Object.entries(i.Properties?.Environment?.Variables||{}).filter(([l])=>kQ.test(l)).map(([l])=>e(r,`Lambda function contains sensitive environment variable: ${l}.`,T("Store sensitive environment variables in AWS Secrets Manager or SSM Parameter Store instead of plaintext environment variables.",o),c("HIGH"),"Security",j(i,r),"cdkInsights"));u.length>0&&(n[r]={issues:u})}return n},{})});var G6,z6=D(()=>{"use strict";me();fe();G6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::Lambda::Function"){let o=W(s,r),a=$(o),c=l=>a?ee(l):l,u=i.Properties?.MemorySize;typeof u=="number"&&u>1024&&(n[r]={issues:[e(r,"Lambda function has high memory allocation.",T("Consider reducing memory for cost savings.",o),c("MEDIUM"),"Cost Optimization",j(i,r),"cdkInsights")]})}return n},{})});var _Q,FQ,TQ,q6,K6,V6,Z6=D(()=>{"use strict";me();fe();_Q=t=>typeof t=="string"&&/^\d{12}$/.test(t),FQ=t=>{if(!t||typeof t!="object")return!1;let e=t.Ref;return typeof e=="string"&&e.endsWith("AccountId")},TQ=t=>t==="*"||t===void 0,q6=t=>typeof t=="string"&&t.endsWith(".amazonaws.com"),K6=t=>t?!!(t.SourceArn||t.SourceAccount||t.PrincipalOrgID||t.OrganizationId):!1,V6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{let o=i.Type==="AWS::Lambda::Permission",a=i.Type==="AWS::Lambda::LayerVersionPermission";if(!o&&!a)return n;let c=i.Properties??{},u=c.Principal,l=[],d=j(i,r),p=W(s,r),f=$(p);return TQ(u)?l.push(e(r,`${i.Type} grants public access via wildcard Principal.`,T("Set Principal to a specific AWS account ID, an AWS service principal with SourceArn/SourceAccount, or an OrganizationId. Wildcard principals make the function/layer reachable from any AWS account.",p,"permissionProps.principal"),f?"HIGH":"CRITICAL","Security",d,"cdkInsights")):o&&q6(u)&&!K6(c)?l.push(e(r,"Lambda::Permission grants a service principal access without SourceArn / SourceAccount / PrincipalOrgID.",T("Constrain the service principal: set SourceArn to the specific resource that may invoke the function, or SourceAccount to your AWS account ID. Without one of these, any account using that AWS service can invoke this function (confused-deputy risk).",p,"permissionProps.sourceArn"),f?"MEDIUM":"HIGH","Security",d,"cdkInsights")):o&&!_Q(u)&&!FQ(u)&&!q6(u)&&!K6(c)&&l.push(e(r,"Lambda::Permission has an unrecognised Principal shape with no source restriction.",T("Confirm the Principal resolves to an account ID, an org ID, or an AWS service plus a SourceArn/SourceAccount. Wildcards or unrestricted patterns expose the function publicly.",p,"permissionProps.principal"),f?"LOW":"MEDIUM","Security",d,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var PQ,Y6,J6=D(()=>{"use strict";me();fe();PQ={nodejs:"nodejs22.x","nodejs4.3":"nodejs22.x","nodejs4.3-edge":"nodejs22.x","nodejs6.10":"nodejs22.x","nodejs8.10":"nodejs22.x","nodejs10.x":"nodejs22.x","nodejs12.x":"nodejs22.x","nodejs14.x":"nodejs22.x","nodejs16.x":"nodejs22.x","nodejs18.x":"nodejs22.x","python2.7":"python3.13","python3.6":"python3.13","python3.7":"python3.13","python3.8":"python3.13","python3.9":"python3.13",java8:"java21","java8.al2":"java21",java11:"java21","dotnetcore1.0":"dotnet8","dotnetcore2.0":"dotnet8","dotnetcore2.1":"dotnet8","dotnetcore3.1":"dotnet8","dotnet5.0":"dotnet8",dotnet6:"dotnet8","ruby2.5":"ruby3.3","ruby2.7":"ruby3.3","go1.x":"provided.al2023"},Y6=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Lambda::Function")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=i.Properties?.Runtime;if(typeof u!="string")return n;let l=PQ[u];return l&&(n[r]={issues:[e(r,`Lambda function uses deprecated runtime "${u}". This runtime has reached or is approaching end-of-life and will no longer receive security patches.`,T(`Upgrade to "${l}" for continued security patches, performance improvements, and long-term support.`,o),c("HIGH"),"Security",j(i,r),"cdkInsights")]}),n},{})});var Q6,X6=D(()=>{"use strict";me();fe();Q6=(t,e,s)=>Object.values(t.Resources||{}).some(r=>r.Type==="AWS::EC2::NatGateway")?Object.entries(t.Resources||{}).reduce((r,[i,o])=>{if(o.Type!=="AWS::Lambda::Function")return r;let a=W(s,i),c=$(a),u=p=>c?ee(p):p,l=j(o,i),d=o.Properties?.VpcConfig;return d?.SubnetIds&&d.SubnetIds.length>0&&(r[i]={issues:[e(i,"Lambda function in VPC with NAT Gateway detected. NAT Gateway costs can accumulate quickly.",T("Evaluate if VPC attachment is necessary. Consider using VPC endpoints for AWS services to reduce NAT costs. NAT Gateway charges ~$0.045/hr plus $0.045/GB processed.",a),u("MEDIUM"),"Cost Optimization",l,"cdkInsights")]}),r},{}):{}});var eO,tO=D(()=>{"use strict";me();fe();eO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::MSK::Cluster")return n;let o=W(s,r),a=$(o),c=g=>a?ee(g):g,u=j(i,r),l=[],d=i.Properties?.ClientAuthentication,p=(d?.Tls?.CertificateAuthorityArnList?.length??0)>0,f=d?.Sasl?.Scram?.Enabled===!0||d?.Sasl?.Iam?.Enabled===!0,m=d?.Unauthenticated?.Enabled===!0;return!p&&!f&&l.push(e(r,"MSK cluster does not have client authentication configured.",T("Enable SASL/SCRAM, IAM authentication, or mutual TLS for client authentication.",o),c("HIGH"),"Security",u,"cdkInsights")),m&&l.push(e(r,"MSK cluster allows unauthenticated access.",T("Disable unauthenticated access and require client authentication for all connections.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var sO,nO=D(()=>{"use strict";me();fe();sO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::MSK::Cluster")return n;let o=W(s,r),a=$(o),c=m=>a?ee(m):m,u=j(i,r),l=[],d=i.Properties?.EncryptionInfo;d?.EncryptionAtRest?.DataVolumeKMSKeyId||l.push(e(r,"MSK cluster does not use a customer-managed KMS key for encryption at rest.",T("Specify DataVolumeKMSKeyId in EncryptionAtRest for additional control over data encryption.",o),c("LOW"),"Security",u,"cdkInsights"));let f=d?.EncryptionInTransit;return f?.ClientBroker!=="TLS"&&l.push(e(r,"MSK cluster does not enforce TLS encryption for client-broker communication.",T("Set ClientBroker to TLS in EncryptionInTransit to encrypt data between clients and brokers.",o),c("HIGH"),"Security",u,"cdkInsights")),f?.InCluster!==!0&&l.push(e(r,"MSK cluster does not have encryption enabled for inter-broker communication.",T("Set InCluster to true in EncryptionInTransit to encrypt data between brokers.",o),c("MEDIUM"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var rO,iO=D(()=>{"use strict";me();fe();rO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::MSK::Cluster")return n;let o=W(s,r),a=$(o),c=h=>a?ee(h):h,u=j(i,r),l=[],p=i.Properties?.LoggingInfo?.BrokerLogs,f=p?.CloudWatchLogs?.Enabled===!0,m=p?.Firehose?.Enabled===!0,g=p?.S3?.Enabled===!0;return!f&&!m&&!g&&l.push(e(r,"MSK cluster does not have broker logging configured.",T("Enable broker logs to CloudWatch, Firehose, or S3 for monitoring and troubleshooting Kafka operations.",o),c("MEDIUM"),"Operational Excellence",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var oO,aO=D(()=>{"use strict";me();fe();oO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::OpenSearchService::Domain"&&i.Type!=="AWS::Elasticsearch::Domain")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[];i.Properties?.AdvancedSecurityOptions?.Enabled!==!0&&l.push(e(r,"OpenSearch domain does not have fine-grained access control enabled.",T("Enable AdvancedSecurityOptions to use IAM or internal user database for document-level and field-level security.",o),c("MEDIUM"),"Security",u,"cdkInsights"));let p=i.Properties?.VPCOptions;return(!p?.SubnetIds||p.SubnetIds.length===0)&&l.push(e(r,"OpenSearch domain is not deployed within a VPC.",T("Configure VPCOptions with subnet IDs to deploy the domain within a VPC for network isolation.",o),c("MEDIUM"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var cO,uO=D(()=>{"use strict";me();fe();cO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::OpenSearchService::Domain"&&i.Type!=="AWS::Elasticsearch::Domain")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=j(i,r),l=[];return i.Properties?.EncryptionAtRestOptions?.Enabled!==!0&&l.push(e(r,"OpenSearch domain does not have encryption at rest enabled.",T("Enable EncryptionAtRestOptions to protect indexed data at rest using AWS KMS.",o),c("HIGH"),"Security",u,"cdkInsights")),i.Properties?.NodeToNodeEncryptionOptions?.Enabled!==!0&&l.push(e(r,"OpenSearch domain does not have node-to-node encryption enabled.",T("Enable NodeToNodeEncryptionOptions to encrypt data in transit between nodes within the cluster.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var lO,dO=D(()=>{"use strict";me();fe();lO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::OpenSearchService::Domain"&&i.Type!=="AWS::Elasticsearch::Domain")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=[],d=i.Properties?.LogPublishingOptions;return d?.AUDIT_LOGS?.Enabled||l.push(e(r,"OpenSearch domain does not have audit logging enabled.",T("Enable AUDIT_LOGS in LogPublishingOptions to track user activity for security and compliance monitoring.",o),c("LOW"),"Security",u,"cdkInsights")),d?.ES_APPLICATION_LOGS?.Enabled||l.push(e(r,"OpenSearch domain does not have application logging enabled.",T("Enable ES_APPLICATION_LOGS in LogPublishingOptions to capture error logs for troubleshooting.",o),c("LOW"),"Operational Excellence",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var pO,fO=D(()=>{"use strict";me();fe();pO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::RDS::DBInstance")return n;let o=j(i,r),a=i.Properties?.BackupRetentionPeriod,c=W(s,r),u=$(c),l=d=>u?ee(d):d;return a===0?n[r]={issues:[e(r,"RDS instance has automated backups disabled (BackupRetentionPeriod is 0).",T("Enable automated backups with at least 7 days retention for production databases to enable point-in-time recovery.",c,"backupRetention"),l("HIGH"),"Reliability",o,"cdkInsights")]}:a!==void 0&&a<7&&(n[r]={issues:[e(r,`RDS backup retention period is only ${a} day(s).`,T("Consider increasing backup retention to at least 7 days for production databases.",c,"backupRetention"),l("MEDIUM"),"Reliability",o,"cdkInsights")]}),n},{})});var mO,hO=D(()=>{"use strict";me();fe();mO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::RDS::DBInstance")return n;let o=W(s,r),a=$(o),c=l=>a?ee(l):l,u=j(i,r);return i.Properties?.DeletionProtection!==!0&&(n[r]={issues:[e(r,"RDS instance does not have deletion protection enabled.",T("Enable DeletionProtection to prevent accidental database deletion.",o),c("MEDIUM"),"Reliability",u,"cdkInsights")]}),n},{})});var gO,yO=D(()=>{"use strict";me();fe();gO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::RDS::DBInstance"&&i.Properties?.StorageEncrypted!==!0){let o=W(s,r),a=$(o);n[r]={issues:[e(r,"RDS instance is not encrypted.",T("Enable encryption to protect data at rest and meet compliance standards.",o,"storageEncrypted / storageEncryptionKey"),a?"HIGH":"CRITICAL","Security",j(i,r),"cdkInsights")]}}return n},{})});var LQ,xO,bO=D(()=>{"use strict";me();fe();LQ=new Set(["AWS::RDS::DBInstance","AWS::RDS::DBCluster"]),xO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(!LQ.has(i.Type))return n;let o=i.Properties?.EnableCloudwatchLogsExports;if(Array.isArray(o)&&o.length>0)return n;let a=j(i,r),c=W(s,r),u=$(c);return n[r]={issues:[e(r,"RDS database does not export logs to CloudWatch.",T("Set EnableCloudwatchLogsExports to the relevant log types for the engine (e.g. ['error','general','slowquery'] for MySQL, ['postgresql'] for PostgreSQL, ['audit','error','general','slowquery'] for MariaDB).",c,"databaseProps.cloudwatchLogsExports"),u?"LOW":"MEDIUM","Security",a,"cdkInsights")]},n},{})});var OQ,SO,vO=D(()=>{"use strict";me();fe();OQ=new Set([1,5,10,15,30,60]),SO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::RDS::DBInstance")return n;let o=i.Properties?.MonitoringInterval,a=typeof o=="number"?o:typeof o=="string"?Number.parseInt(o,10):void 0;if(typeof a=="number"&&OQ.has(a))return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,"RDS Instance does not have enhanced monitoring enabled.",T("Set MonitoringInterval to 1, 5, 10, 15, 30, or 60 (seconds) and provide MonitoringRoleArn so RDS can publish OS-level metrics to CloudWatch Logs.",u,"databaseProps.monitoringInterval"),l?"LOW":"MEDIUM","Operational Excellence",c,"cdkInsights")]},n},{})});var CO,DO=D(()=>{"use strict";me();fe();CO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::RDS::DBInstance")return n;let o=W(s,r),a=$(o),c=f=>a?ee(f):f,u=i.Properties??{},l=u.MultiAZ===!0,d=u.StorageType==="gp2",p=typeof u.StorageType>"u";return l&&(d||p)&&(n[r]={issues:[e(r,d?"RDS instance is using Multi-AZ with gp2 storage. Consider gp3 for lower costs.":"RDS instance is using Multi-AZ without explicitly setting a storage type. gp3 may offer better performance and cost savings.",T("Switch to gp3 storage for RDS to reduce costs and improve performance.",o),c("MEDIUM"),"Cost Optimization",j(i,r),"cdkInsights")]}),n},{})});var AO,wO=D(()=>{"use strict";me();fe();AO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::RDS::DBInstance")return n;let o=W(s,r),a=$(o),c=l=>a?ee(l):l,u=j(i,r);return i.Properties?.PubliclyAccessible===!0&&(n[r]={issues:[e(r,"RDS instance is publicly accessible from the internet.",T("Set PubliclyAccessible to false and access the database through private subnets, bastion hosts, or VPN. If public access is intentional (e.g. a dev or staging database with restricted security groups), suppress this rule for the resource.",o),c("HIGH"),"Security",u,"cdkInsights")]}),n},{})});var EO,RO=D(()=>{"use strict";me();fe();EO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Redshift::Cluster")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=[];return i.Properties?.Encrypted!==!0&&l.push(e(r,"Redshift cluster does not have encryption at rest enabled.",T("Set Encrypted to true and specify a KmsKeyId to protect data at rest.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var IO,kO=D(()=>{"use strict";me();fe();IO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Redshift::Cluster")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);return i.Properties?.LoggingProperties?.BucketName||(n[r]={issues:[e(r,"Redshift cluster does not have audit logging enabled.",T("Configure LoggingProperties with an S3 bucket to capture connection logs, user activity, and query activity.",o),c("MEDIUM"),"Security",u,"cdkInsights")]}),n},{})});var _O,FO=D(()=>{"use strict";me();fe();_O=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Redshift::Cluster")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);return i.Properties?.PubliclyAccessible===!0&&(n[r]={issues:[e(r,"Redshift cluster is publicly accessible.",T("Set PubliclyAccessible to false and use VPC endpoints or bastion hosts for secure access. If public access is intentional (e.g. analytics tooling or customer-facing dashboards) ensure security groups restrict the source CIDRs and suppress this rule for the resource.",o),c("HIGH"),"Security",u,"cdkInsights")]}),n},{})});var TO,PO=D(()=>{"use strict";me();fe();TO=(t,e,s)=>{let n=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::Route53::HostedZone"),r=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::Route53::DNSSEC"),i=new Set(r.map(([,o])=>{let a=o.Properties?.HostedZoneId;return typeof a=="string"?a:a?.Ref?a.Ref:null}).filter(Boolean));return n.reduce((o,[a,c])=>{if(c.Properties?.HostedZoneConfig?.Comment?.includes("private"))return o;let u=j(c,a);if(!i.has(a)){let d=W(s,a),p=$(d),f=m=>p?ee(m):m;o[a]={issues:[e(a,"Route53 Hosted Zone does not have DNSSEC signing enabled.",T("Enable DNSSEC to protect against DNS spoofing and cache poisoning attacks by cryptographically signing DNS records.",d),f("LOW"),"Security",u,"cdkInsights")]}}return o},{})}});var LO,OO=D(()=>{"use strict";me();fe();LO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::Route53::HealthCheck")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=[],d=i.Properties?.HealthCheckConfig;return d?.Type==="HTTP"&&l.push(e(r,"Route53 Health Check uses HTTP instead of HTTPS.",T("Use HTTPS for health checks to ensure the endpoint supports secure connections and to validate SSL certificates.",o),c("LOW"),"Security",u,"cdkInsights")),d?.RequestInterval===30&&l.push(e(r,"Route53 Health Check uses standard (30 second) request interval.",T("Consider using fast interval (10 seconds) for critical endpoints to detect failures more quickly.",o),c("LOW"),"Reliability",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var MO,BO=D(()=>{"use strict";me();fe();MO=(t,e,s)=>{let n=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::Route53::HostedZone"),r=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::Route53::QueryLoggingConfig"),i=new Set(r.map(([,o])=>{let a=o.Properties?.HostedZoneId;return typeof a=="string"?a:a?.Ref?a.Ref:null}).filter(Boolean));return n.reduce((o,[a,c])=>{let u=j(c,a);if(!i.has(a)){let d=W(s,a),p=$(d),f=m=>p?ee(m):m;o[a]={issues:[e(a,"Route53 Hosted Zone does not have query logging enabled.",T("Enable query logging to CloudWatch Logs for DNS query analysis, troubleshooting, and security monitoring.",d),f("LOW"),"Security",u,"cdkInsights")]}}return o},{})}});var NO,$O=D(()=>{"use strict";me();fe();NO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::S3::Bucket")return n;let o=[],a=i.Properties??{},c=j(i,r),u=W(s,r),l=$(u);a.BucketEncryption||o.push(e(r,"S3 Bucket lacks encryption.",T("Enable encryption at rest for better security.",u,"bucketProps.encryption"),l?"MEDIUM":"HIGH","Security",c,"cdkInsights"));let d=a?.PublicAccessBlockConfiguration;return d?(d.BlockPublicAcls===!1&&o.push(e(r,"S3 Bucket allows public ACLs (BlockPublicAcls is false).","Set BlockPublicAcls to true to prevent public ACLs from being applied.","CRITICAL","Security",c,"cdkInsights")),d.BlockPublicPolicy===!1&&o.push(e(r,"S3 Bucket allows public bucket policies (BlockPublicPolicy is false).","Set BlockPublicPolicy to true to prevent public bucket policies.","CRITICAL","Security",c,"cdkInsights")),d.IgnorePublicAcls===!1&&o.push(e(r,"S3 Bucket does not ignore public ACLs (IgnorePublicAcls is false).","Set IgnorePublicAcls to true to ignore any public ACLs on the bucket.","HIGH","Security",c,"cdkInsights")),d.RestrictPublicBuckets===!1&&o.push(e(r,"S3 Bucket does not restrict public bucket access (RestrictPublicBuckets is false).","Set RestrictPublicBuckets to true to restrict access to the bucket to only authorized users.","HIGH","Security",c,"cdkInsights"))):o.push(e(r,"S3 Bucket has no PublicAccessBlockConfiguration defined.","Configure PublicAccessBlockConfiguration with BlockPublicAcls, BlockPublicPolicy, IgnorePublicAcls, and RestrictPublicBuckets all set to true.","HIGH","Security",c,"cdkInsights")),a.VersioningConfiguration||o.push(e(r,"S3 Bucket has no versioning enabled.","Enable versioning to protect against accidental deletions.","MEDIUM","Operational Excellence",c,"cdkInsights")),o.length>0&&(n[r]={issues:o}),n},{})});var MQ,BQ,NQ,$Q,WQ,jQ,UQ,HQ,GQ,zQ,qQ,WO,jO=D(()=>{"use strict";me();fe();MQ=new Set(["*","s3:*","s3:DeleteBucket","s3:DeleteBucketPolicy","s3:PutBucketPolicy"]),BQ=new Set(["aws:PrincipalArn","aws:PrincipalAccount","aws:PrincipalIsAWSService"]),NQ=new Set(["StringNotEquals","StringNotLike","ArnNotLike","ArnNotEquals"]),$Q=t=>{if(t==="*")return!0;if(t&&typeof t=="object"&&!Array.isArray(t)){let e=t,s=e.AWS;if(s==="*"||Array.isArray(s)&&s.includes("*")||e.Service==="*")return!0}return!1},WQ=t=>typeof t=="string"?[t]:Array.isArray(t)?t.filter(e=>typeof e=="string"):[],jQ=t=>WQ(t).find(e=>MQ.has(e)),UQ=t=>t===!1||t==="false"||t==="False",HQ=t=>{if(t==null)return!0;let e=Array.isArray(t)?t:[t];if(e.length===0)return!0;for(let s of e){if(typeof s!="string"||s==="*")return!0;let n=s.split(":::")[1];if(n===void 0||!n.includes("/"))return!0}return!1},GQ=t=>{let e=t.Condition;if(!e||typeof e!="object")return!1;let s=e.Bool??e.BoolIfExists;return s?UQ(s["aws:SecureTransport"]):!1},zQ=t=>{if(!t||typeof t!="object")return!1;for(let[e,s]of Object.entries(t)){if(!s||typeof s!="object")continue;let n=Object.keys(s);if(n.includes("aws:PrincipalIsAWSService"))return!0;if(NQ.has(e)){for(let r of n)if(BQ.has(r))return!0}}return!1},qQ=t=>{if(t.Effect!=="Deny"||t.NotPrincipal!==void 0||!$Q(t.Principal))return;let e=jQ(t.Action);if(e&&!GQ(t)&&!zQ(t.Condition)&&HQ(t.Resource))return e},WO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::S3::BucketPolicy")return n;let o=i.Properties?.PolicyDocument?.Statement;if(!Array.isArray(o))return n;let a=o.map(qQ).find(d=>d!==void 0);if(!a)return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,`Bucket policy contains a Deny statement on ${a} with Principal: '*' and no carveout for the account root or admin role. This will lock the account out of the bucket \u2014 recovery requires breaking glass on the account root credentials to remove the bucket policy. AWS Support will typically not intervene for this scenario.`,T("Add a NotPrincipal exemption for the account root (e.g. arn:aws:iam::<account>:root) or use a Condition with StringNotEquals on aws:PrincipalArn to exempt your admin role(s). If the Deny is intended for transport security, scope it with aws:SecureTransport rather than a blanket Deny on Principal: '*'.",u,"bucketPolicyProps.statements"),l?"HIGH":"CRITICAL","Security",c,"cdkInsights")]},n},{})});var KQ,VQ,UO,HO=D(()=>{"use strict";me();fe();KQ=t=>t===!1||t==="false"||t==="False",VQ=t=>{if(t.Effect!=="Deny")return!1;let e=t.Condition;if(!e||typeof e!="object")return!1;let s=e.Bool??e.BoolIfExists;return s?KQ(s["aws:SecureTransport"]):!1},UO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::S3::BucketPolicy")return n;let o=i.Properties?.PolicyDocument?.Statement;if(Array.isArray(o)&&o.some(VQ))return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,"S3 BucketPolicy does not deny non-SSL/TLS requests.",T("Add a Deny statement with Condition.Bool['aws:SecureTransport']=false to enforce TLS for all S3 access. CIS AWS Foundations 2.1.1 and PCI-DSS require encrypted-in-transit requests.",u,"bucketPolicyProps.statements"),l?"MEDIUM":"HIGH","Security",c,"cdkInsights")]},n},{})});var GO,zO=D(()=>{"use strict";me();fe();GO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::S3::Bucket")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r);return(i.Properties?.LifecycleConfiguration?.Rules||[]).length===0&&(n[r]={issues:[e(r,"S3 bucket has no lifecycle policy configured.",T("Configure lifecycle rules to automatically transition objects to cheaper storage classes (e.g., Glacier) or delete old versions to optimize storage costs.",o),c("MEDIUM"),"Cost Optimization",u,"cdkInsights")]}),n},{})});var qO,KO=D(()=>{"use strict";me();fe();qO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::S3::Bucket"||(i.Properties??{}).LoggingConfiguration?.DestinationBucketName)return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,"S3 Bucket has no access logging configured.",T("Set LoggingConfiguration.DestinationBucketName to capture object-level access logs in a separate bucket. Required by CIS AWS Foundations 2.1.2 and useful for incident forensics.",u,"bucketProps.serverAccessLogsBucket"),l?"LOW":"MEDIUM","Security",c,"cdkInsights")]},n},{})});var ZQ,VO,ZO=D(()=>{"use strict";me();fe();ZQ=/\b(prod|production|critical|backup|dr|disaster|recovery|primary)\b/i,VO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::S3::Bucket")return n;let o=W(s,r),a=$(o),c=p=>a?ee(p):p,u=j(i,r),l=i.Properties?.BucketName||r,d=i.Properties?.ReplicationConfiguration;return ZQ.test(l)&&!d?.Rules?.length&&(n[r]={issues:[e(r,"Critical S3 bucket does not have cross-region replication configured.",T("Consider enabling cross-region replication for disaster recovery and data durability on production/critical buckets.",o),c("LOW"),"Reliability",u,"cdkInsights")]}),n},{})});var YO,JO=D(()=>{"use strict";me();fe();YO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::S3::Bucket"&&!i.Properties?.IntelligentTieringConfigurations){let o=W(s,r),a=$(o),c=u=>a?ee(u):u;n[r]={issues:[e(r,"S3 Bucket does not use Intelligent-Tiering. Consider enabling it for cost optimization.",T("Enable Intelligent-Tiering for automatic cost optimization of infrequently accessed objects.",o),c("LOW"),"Cost Optimization",j(i,r),"cdkInsights")]}}return n},{})});var QO,XO=D(()=>{"use strict";me();fe();QO=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{let o=i.Properties??{};if(i.Type==="AWS::SecretsManager::Secret"&&o.PublicPolicy){let a=W(s,r),c=$(a),u=l=>c?ee(l):l;n[r]={issues:[e(r,"Secret is publicly accessible.",T("Restrict secret access using IAM policies to ensure only authorized entities can retrieve it.",a),u("CRITICAL"),"Security",j(i,r),"cdkInsights")]}}return n},{})});var e3,t3=D(()=>{"use strict";me();fe();e3=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::SNS::Topic"&&!i.Properties?.KmsMasterKeyId){let o=W(s,r),a=$(o),c=u=>a?ee(u):u;n[r]={issues:[e(r,"SNS topic is not encrypted.",T("Enable AWS KMS encryption for SNS to protect sensitive messages in transit and at rest.",o),c("HIGH"),"Security",j(i,r),"cdkInsights")]}}return n},{})});var YQ,JQ,QQ,XQ,eX,tX,sX,nX,s3,n3=D(()=>{"use strict";me();fe();YQ=new Set(["*","sns:*","sns:DeleteTopic","sns:RemovePermission"]),JQ=new Set(["aws:PrincipalArn","aws:PrincipalAccount","aws:PrincipalIsAWSService"]),QQ=new Set(["StringNotEquals","StringNotLike","ArnNotLike","ArnNotEquals"]),XQ=t=>{if(t==="*")return!0;if(t&&typeof t=="object"&&!Array.isArray(t)){let e=t,s=e.AWS;if(s==="*"||Array.isArray(s)&&s.includes("*")||e.Service==="*")return!0}return!1},eX=t=>typeof t=="string"?[t]:Array.isArray(t)?t.filter(e=>typeof e=="string"):[],tX=t=>eX(t).find(e=>YQ.has(e)),sX=t=>{if(!t||typeof t!="object")return!1;for(let[e,s]of Object.entries(t)){if(!s||typeof s!="object")continue;let n=Object.keys(s);if(n.includes("aws:PrincipalIsAWSService"))return!0;if(QQ.has(e)){for(let r of n)if(JQ.has(r))return!0}}return!1},nX=t=>{if(t.Effect!=="Deny"||t.NotPrincipal!==void 0||!XQ(t.Principal))return;let e=tX(t.Action);if(e&&!sX(t.Condition))return e},s3=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::SNS::TopicPolicy")return n;let o=i.Properties?.PolicyDocument?.Statement;if(!Array.isArray(o))return n;let a=o.map(nX).find(d=>d!==void 0);if(!a)return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,`Topic policy contains a Deny statement on ${a} with Principal: '*' and no carveout for the account root or admin role. This locks the account out of the topic \u2014 recovery requires breaking glass on the account root credentials to remove the topic policy, or delete-and-recreate the topic if no subscribers depend on its ARN. In fan-out architectures that's often a multi-stack rebuild.`,T("Add a NotPrincipal exemption for the account root (e.g. arn:aws:iam::<account>:root) or use a Condition with StringNotEquals on aws:PrincipalArn to exempt your admin role(s). If the Deny is intended to scope to AWS services, use aws:PrincipalIsAWSService rather than a blanket Deny on Principal: '*'.",u,"topicPolicyProps.statements"),l?"HIGH":"CRITICAL","Security",c,"cdkInsights")]},n},{})});var r3,i3=D(()=>{"use strict";me();fe();r3=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{let o=!!i.Properties?.KmsMasterKeyId,a=i.Properties?.SqsManagedSseEnabled===!0;if(i.Type==="AWS::SQS::Queue"&&!o&&!a){let c=W(s,r),u=$(c),l=d=>u?ee(d):d;n[r]={issues:[e(r,"SQS queue is not encrypted.",T("Enable AWS KMS encryption for SQS to protect message data in transit and at rest.",c),l("HIGH"),"Security",j(i,r),"cdkInsights")]}}return n},{})});var rX,iX,oX,aX,cX,uX,lX,dX,o3,a3=D(()=>{"use strict";me();fe();rX=new Set(["*","sqs:*","sqs:DeleteQueue","sqs:RemovePermission"]),iX=new Set(["aws:PrincipalArn","aws:PrincipalAccount","aws:PrincipalIsAWSService"]),oX=new Set(["StringNotEquals","StringNotLike","ArnNotLike","ArnNotEquals"]),aX=t=>{if(t==="*")return!0;if(t&&typeof t=="object"&&!Array.isArray(t)){let e=t,s=e.AWS;if(s==="*"||Array.isArray(s)&&s.includes("*")||e.Service==="*")return!0}return!1},cX=t=>typeof t=="string"?[t]:Array.isArray(t)?t.filter(e=>typeof e=="string"):[],uX=t=>cX(t).find(e=>rX.has(e)),lX=t=>{if(!t||typeof t!="object")return!1;for(let[e,s]of Object.entries(t)){if(!s||typeof s!="object")continue;let n=Object.keys(s);if(n.includes("aws:PrincipalIsAWSService"))return!0;if(oX.has(e)){for(let r of n)if(iX.has(r))return!0}}return!1},dX=t=>{if(t.Effect!=="Deny"||t.NotPrincipal!==void 0||!aX(t.Principal))return;let e=uX(t.Action);if(e&&!lX(t.Condition))return e},o3=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::SQS::QueuePolicy")return n;let o=i.Properties?.PolicyDocument?.Statement;if(!Array.isArray(o))return n;let a=o.map(dX).find(d=>d!==void 0);if(!a)return n;let c=j(i,r),u=W(s,r),l=$(u);return n[r]={issues:[e(r,`Queue policy contains a Deny statement on ${a} with Principal: '*' and no carveout for the account root or admin role. This locks the account out of the queue \u2014 recovery requires breaking glass on the account root credentials to remove the queue policy, or delete-and-recreate the queue if nothing else depends on its ARN. In event-driven systems that's often a multi-stack rebuild.`,T("Add a NotPrincipal exemption for the account root (e.g. arn:aws:iam::<account>:root) or use a Condition with StringNotEquals on aws:PrincipalArn to exempt your admin role(s). If the Deny is intended to scope to AWS services, use aws:PrincipalIsAWSService rather than a blanket Deny on Principal: '*'.",u,"queuePolicyProps.statements"),l?"HIGH":"CRITICAL","Security",c,"cdkInsights")]},n},{})});var c3,u3=D(()=>{"use strict";me();fe();c3=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type==="AWS::StepFunctions::StateMachine"&&i.Properties?.LoggingConfiguration===void 0){let o=W(s,r),a=$(o),c=u=>a?ee(u):u;n[r]={issues:[e(r,"Step Function lacks logging configuration.",T("Enable logging for the Step Function using AWS CloudWatch to improve monitoring and debugging.",o),c("HIGH"),"Security",j(i,r),"cdkInsights")]}}return n},{})});var l3,d3=D(()=>{"use strict";me();fe();l3=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::EC2::SecurityGroup")return n;let o=W(s,r),a=$(o),c=d=>a?ee(d):d,u=j(i,r);if(i.Properties?.GroupName==="default"){let d=i.Properties?.SecurityGroupIngress||[],p=i.Properties?.SecurityGroupEgress||[];(d.length>0||p.length>0)&&(n[r]={issues:[e(r,"VPC default security group has rules configured.",T("Remove all rules from the default security group and use custom security groups instead. Default groups cannot be deleted but should have no rules.",o),c("MEDIUM"),"Security",u,"cdkInsights")]})}return n},{})});var p3,f3=D(()=>{"use strict";me();fe();p3=(t,e,s)=>{let n=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::EC2::VPC"),r=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::EC2::FlowLog"),i=new Set(r.filter(([,o])=>o.Properties?.ResourceType==="VPC").map(([,o])=>{let a=o.Properties?.ResourceId;return typeof a=="string"?a:a?.Ref?a.Ref:null}).filter(Boolean));return n.reduce((o,[a,c])=>{let u=j(c,a);if(!i.has(a)){let d=W(s,a),p=$(d),f=m=>p?ee(m):m;o[a]={issues:[e(a,"VPC does not have flow logs enabled.",T("Enable VPC Flow Logs to capture network traffic information for security analysis and troubleshooting.",d),f("MEDIUM"),"Security",u,"cdkInsights")]}}return o},{})}});var m3,h3=D(()=>{"use strict";me();fe();m3=(t,e,s)=>{let n=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::WAFv2::WebACL"),r=Object.entries(t.Resources||{}).filter(([,o])=>o.Type==="AWS::WAFv2::LoggingConfiguration"),i=new Set(r.map(([,o])=>{let a=o.Properties?.ResourceArn;return typeof a=="string"?a:a?.Ref?a.Ref:a?.["Fn::GetAtt"]?.[0]?a["Fn::GetAtt"][0]:null}).filter(Boolean));return n.reduce((o,[a,c])=>{let u=j(c,a);if(!(i.has(a)||r.some(([,d])=>{let p=d.Properties?.ResourceArn;return typeof p=="object"&&(p?.Ref===a||p?.["Fn::GetAtt"]?.[0]===a)}))){let d=W(s,a),p=$(d),f=m=>p?ee(m):m;o[a]={issues:[e(a,"WAF WebACL does not have logging configured.",T("Enable WAF logging to capture detailed information about web requests for security analysis and compliance.",d),f("MEDIUM"),"Security",u,"cdkInsights")]}}return o},{})}});var g3,y3=D(()=>{"use strict";me();fe();g3=(t,e,s)=>Object.entries(t.Resources||{}).reduce((n,[r,i])=>{if(i.Type!=="AWS::WAFv2::WebACL")return n;let o=W(s,r),a=$(o),c=m=>a?ee(m):m,u=j(i,r),l=[],d=i.Properties?.DefaultAction;d?.Allow&&!d?.Block&&l.push(e(r,"WAF WebACL has default action set to Allow, which permits all traffic not matching rules.",T("Consider setting the default action to Block and explicitly allowing known-good traffic patterns for defense-in-depth.",o),c("MEDIUM"),"Security",u,"cdkInsights")),i.Properties?.VisibilityConfig?.CloudWatchMetricsEnabled||l.push(e(r,"WAF WebACL does not have CloudWatch metrics enabled.",T("Enable CloudWatchMetricsEnabled in VisibilityConfig to monitor WAF activity and detect potential attacks.",o),c("MEDIUM"),"Security",u,"cdkInsights"));let f=i.Properties?.Rules;return(!f||f.length===0)&&l.push(e(r,"WAF WebACL has no rules defined.",T("Add WAF rules to protect against common web exploits like SQL injection, XSS, and bot traffic.",o),c("HIGH"),"Security",u,"cdkInsights")),l.length>0&&(n[r]={issues:l}),n},{})});var pX,x3,b3,S3,fX,lm,ll,mX,v3,C3,D3=D(()=>{"use strict";pX=t=>Object.values(t.Resources||{}).some(e=>e.Type==="Custom::S3BucketNotifications"),x3=t=>Object.values(t.Resources||{}).some(e=>e.Type==="AWS::Lambda::EventSourceMapping"),b3=t=>Object.values(t.Resources||{}).some(e=>e.Type==="AWS::Events::Rule"),S3=(t,e)=>Object.values(t.Resources||{}).some(s=>s.Type!=="AWS::ElasticLoadBalancingV2::Listener"?!1:(s.Properties?.DefaultActions||s.Properties?.Actions)?.some(r=>r.TargetGroupArn?.startsWith(e))),fX=t=>Object.values(t.Resources||{}).some(e=>e.Type==="AWS::Lambda::Permission"&&e.Properties?.Principal==="apigateway.amazonaws.com"),lm=(t,e)=>Object.values(t.Resources||{}).some(s=>s.Type==="AWS::ApiGateway::Integration"&&typeof s.Properties?.Uri=="string"&&s.Properties.Uri.includes(e)),ll=(t,e)=>Object.values(t.Resources||{}).some(s=>s.Type==="AWS::IoT::TopicRule"&&s.Properties?.TopicRulePayload?.actions?.some(n=>Object.hasOwn(n,e))),mX=t=>Object.values(t.Resources||{}).some(e=>e.Type==="AWS::ECS::Service"),v3=(t,e)=>Object.values(t.Resources||{}).some(s=>s.Type==="AWS::SNS::Subscription"&&s.Properties?.Protocol===e),C3=(t,e)=>{let s=[],n={},r={};for(let[o,a]of Object.entries(e)){let c=a.requiredResourceTypes||[];if(c.length!==0){r[o]=c.length;for(let u of c)n[u]||(n[u]=[]),n[u].push(o)}}let i={};for(let o of Object.values(t.Resources||{})){let a=o.Type,c=n[a];if(c){for(let u of c)if(i[u]=(i[u]||0)+1,i[u]===r[u]){let l=e[u],d=!0;switch(u){case"aws-s3-lambda":d=pX(t)||x3(t);break;case"aws-dynamodbstreams-lambda":d=x3(t);break;case"aws-eventbridge-lambda":d=b3(t);break;case"aws-alb-fargate":d=S3(t,"arn:aws:ecs:");break;case"aws-alb-lambda":d=S3(t,"arn:aws:lambda:");break;case"aws-apigateway-lambda":d=fX(t);break;case"aws-apigateway-sqs":d=lm(t,"sqs");break;case"aws-apigateway-dynamodb":d=lm(t,"dynamodb");break;case"aws-apigateway-kinesisstreams":d=lm(t,"kinesis");break;case"aws-apigateway-sagemakerendpoint":d=lm(t,"sagemaker");break;case"aws-iot-lambda":d=ll(t,"lambda");break;case"aws-iot-kinesisstreams":d=ll(t,"kinesis");break;case"aws-iot-kinesisfirehose-s3":d=ll(t,"firehose");break;case"aws-iot-sqs":d=ll(t,"sqs");break;case"aws-iot-s3":d=ll(t,"s3");break;case"aws-sns-lambda":d=v3(t,"lambda");break;case"aws-sns-sqs":d=v3(t,"sqs");break;case"aws-fargate-dynamodb":case"aws-fargate-eventbridge":case"aws-fargate-kinesisfirehose":case"aws-fargate-kinesisstreams":case"aws-fargate-opensearch":case"aws-fargate-s3":case"aws-fargate-secretsmanager":case"aws-fargate-sns":case"aws-fargate-sqs":case"aws-fargate-ssmstringparameter":case"aws-fargate-stepfunctions":d=mX(t);break;case"aws-eventbridge-kinesisfirehose-s3":case"aws-eventbridge-kinesisstreams":case"aws-eventbridge-sns":case"aws-eventbridge-sqs":case"aws-eventbridge-stepfunctions":d=b3(t);break}if(!d)continue;s.push({resourceId:l.className,issue:`Possible Pattern detected: ${l.friendlyName}`,recommendation:`Consider using the AWS Solutions Construct \`${l.className}\` from \`@aws-solutions-constructs/${u}\`.`,severity:"LOW",wafPillar:"Operational Excellence",docUrl:l.documentationUrl,githubUrl:l.githubUrl,constructPath:l.className,foundBy:"cdkInsights"}),delete r[u]}}}return s}});var A3,w3=D(()=>{"use strict";SP();CP();AP();EP();IP();_P();TP();LP();MP();NP();WP();UP();GP();qP();VP();YP();QP();eL();sL();Xb();rL();oL();cL();lL();pL();mL();yL();bL();vL();DL();wL();RL();kL();FL();PL();OL();BL();$L();jL();HL();zL();KL();ZL();JL();XL();t6();n6();i6();a6();u6();d6();f6();h6();y6();v6();D6();w6();I6();_6();T6();L6();B6();$6();j6();H6();z6();Z6();J6();X6();tO();nO();iO();aO();uO();dO();fO();hO();yO();bO();vO();DO();wO();RO();kO();FO();PO();OO();BO();$O();jO();HO();zO();KO();ZO();JO();XO();t3();n3();i3();a3();eS();u3();d3();f3();h3();y3();D3();A3=()=>({iamPolicies:C6,iamPermissionBoundary:A6,iamCrossAccountTrust:S6,iamUserPolicies:R6,s3Buckets:NO,s3BucketLogging:qO,s3BucketPolicySsl:UO,s3BucketPolicySelfLockout:WO,s3IntelligentTiering:YO,s3LifecyclePolicy:GO,s3Replication:VO,securityGroups:EL,ec2InstanceType:SL,ec2PublicIp:AL,ec2SubnetAutoPublicIp:IL,natGatewayUsage:CL,ebsVolumes:dL,lambdaEnvironmentVariables:U6,lambdaMemory:G6,lambdaReservedConcurrency:N6,lambdaDeadLetterQueue:W6,lambdaRuntime:Y6,lambdaVpcNatWarning:Q6,lambdaPermission:V6,rdsEncryption:gO,rdsMultiAZ:CO,rdsPublicAccess:AO,rdsBackupRetention:pO,rdsDeletionProtection:mO,rdsLogging:xO,rdsEnhancedMonitoring:SO,dynamoDBAutoScaling:aL,dynamoDBStreams:uL,dynamoDBPitr:iL,dynamoDBEncryption:nL,cloudFrontHttpsOnly:OP,cloudFrontWafAssociation:jP,cloudFrontLogging:BP,cloudFrontTls:$P,elbDeletionProtection:YL,elbLogging:e6,elbHttpsListeners:QL,elbSecurityPolicy:s6,ecsSecrets:UL,ecsLogging:ML,ecsServiceConnectLogs:NL,ecsResources:WL,cognitoPasswordPolicy:XP,cognitoMfa:JP,cognitoAdvancedSecurity:tL,wafWebAcl:g3,wafLogging:m3,cloudWatchLogRetention:ZP,cloudWatchEncryption:KP,cloudWatchAlarms:zP,route53Dnssec:TO,route53HealthChecks:LO,route53QueryLogging:MO,elastiCacheEncryption:o6,elastiCacheAuth:r6,elastiCacheFailover:c6,ecrScanning:LL,ecrLifecycle:TL,ecrImmutableTags:_L,openSearchEncryption:cO,openSearchAccessControl:oO,openSearchLogging:lO,acmValidation:bP,backupPlans:FP,backupVault:PP,vpcFlowLogs:p3,vpcDefaultSecurityGroup:l3,kinesisEncryption:k6,kinesisRetention:F6,appSyncAuth:wP,appSyncLogging:RP,appSyncWaf:kP,eksPublicEndpoint:VL,eksEncryption:GL,eksLogging:qL,redshiftEncryption:EO,redshiftPublicAccess:_O,redshiftLogging:IO,mskEncryption:sO,mskAuth:eO,mskLogging:rO,glueEncryption:g6,glueConnections:m6,efsEncryption:fL,autoScalingGroupHealthCheck:gL,autoScalingLaunchConfigPublicIp:xL,apiGateway:vP,apiGatewayMethodAuth:DP,secretsManager:QO,cloudTrailLogging:HP,eventBridgeRules:l6,eventBusPolicy:p6,kmsKeys:P6,kmsKeyPolicySelfLockout:M6,sns:e3,snsTopicPolicySelfLockout:s3,sqs:r3,sqsQueuePolicySelfLockout:o3,stepFunctions:c3,crossResourceRelationships:am,stackArchitecture:cm,solutionsPatterns:C3})});var dl,E3,sS=D(()=>{"use strict";dl=(t={})=>{let{ttl:e=3e5,maxSize:s=1e3}=t,n=new Map,r=new Set,i=[],o=Date.now(),a=6e4,c=f=>Date.now()-f.timestamp>f.ttl,u=f=>{r.delete(f)},l=()=>{let f=0;for(let m=0;m<i.length;m++)r.has(i[m])&&(i[f++]=i[m]);i.length=f},d=()=>{let f=Date.now();if(f-o<a)return;o=f;let m=[];for(let[g,h]of n.entries())c(h)&&m.push(g);for(let g of m)n.delete(g),u(g);m.length>0&&l()},p=()=>{for(;n.size>=s&&i.length>0;){let f=i.shift();f&&r.has(f)&&(n.delete(f),r.delete(f))}};return{get(f){let m=n.get(f);if(m){if(c(m)){n.delete(f),u(f);return}return m.value}},set(f,m,g){n.size>=s*.9&&d(),p(),r.has(f)&&u(f),n.set(f,{value:m,timestamp:Date.now(),ttl:g??e}),r.add(f),i.push(f)},clear(){n.clear(),r.clear(),i.length=0},size(){return n.size},has(f){let m=n.get(f);return m?c(m)?(n.delete(f),u(f),!1):!0:!1}}},E3=(t,e={})=>{let s=dl(e);return(...n)=>{let r;try{r=JSON.stringify(n)}catch{return t(...n)}let i=s.get(r);if(i!==void 0)return i;let o=t(...n);return s.set(r,o),o}}});function pl(t,e){let s=e.split("."),n=t;for(let r of s){if(n==null||typeof n!="object")return;n=n[r]}return n}function nS(t,e){switch(t.type){case"property_exists":{let s=pl(e,t.path),n=s!=null;return t.negate?!n:n}case"property_equals":{let s=pl(e,t.path),n=JSON.stringify(s)===JSON.stringify(t.value);return t.negate?!n:n}case"property_matches":{let s=pl(e,t.path);if(typeof s!="string")return!!t.negate;let n=new RegExp(t.pattern).test(s);return t.negate?!n:n}case"property_gt":{let s=pl(e,t.path);return typeof s!="number"?!1:s>t.value}case"property_lt":{let s=pl(e,t.path);return typeof s!="number"?!1:s<t.value}case"and":return t.conditions.every(s=>nS(s,e));case"or":return t.conditions.some(s=>nS(s,e));default:return!1}}function R3(t,e,s){if(e.length===0)return{};let n={};for(let[r,i]of Object.entries(t.Resources||{}))for(let o of e)if(o.resourceTypes.some(c=>c.endsWith("*")?i.Type.startsWith(c.slice(0,-1)):i.Type===c))try{if(nS(o.condition,i)){let u=s(r,`[${o.ruleId}] ${o.description}`,o.recommendation,o.severity,o.wafPillar,"","cdkInsights");u.ruleId=o.ruleId,n[r]||(n[r]={issues:[]}),n[r].issues.push(u)}}catch(c){et.warn(`Error evaluating custom rule '${o.ruleId}' on resource '${r}'`,{error:c instanceof Error?c.message:String(c)})}return n}var I3=D(()=>{"use strict";dt()});var fl,dm=D(()=>{"use strict";fl={"iam-policies-overly-permissive":{ruleId:"iam-policies-overly-permissive",checkKey:"iamPolicies",name:"IAM Overly Permissive Policies",description:"Detects IAM policies with overly permissive actions like * wildcards.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Review IAM policies for overly broad permissions","Replace wildcard (*) actions with specific actions","Use IAM Access Analyzer to identify unused permissions"],resourceTypes:["AWS::IAM::Policy","AWS::IAM::Role","AWS::IAM::ManagedPolicy"]},"iam-permission-boundary-missing":{ruleId:"iam-permission-boundary-missing",checkKey:"iamPermissionBoundary",name:"IAM Permission Boundary Missing",description:"Detects IAM roles without permission boundaries.",severity:"LOW",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html",complianceFrameworks:["SOC2","CIS","NIST"],remediationSteps:["Create a permission boundary policy","Attach the permission boundary to IAM roles"],resourceTypes:["AWS::IAM::Role"]},"iam-cross-account-trust":{ruleId:"iam-cross-account-trust",checkKey:"iamCrossAccountTrust",name:"IAM Cross-Account Trust",description:"Detects IAM roles with cross-account trust relationships.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_aws-accounts.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Verify cross-account trust is intentional","Add conditions to restrict access (e.g., external ID)","Document the business justification"],resourceTypes:["AWS::IAM::Role"]},"iam-user-direct-policies":{ruleId:"iam-user-direct-policies",checkKey:"iamUserPolicies",name:"IAM User Direct Policies",description:"Detects IAM Users with policies attached directly (inline Policies or ManagedPolicyArns). CIS AWS Foundations 1.15 requires users to inherit permissions through groups.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#use-groups-for-permissions",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Create an IAM Group with the required policies","Add the user to the group instead of attaching policies directly","Remove Policies and ManagedPolicyArns from AWS::IAM::User resources"],resourceTypes:["AWS::IAM::User"]},"s3-bucket-public-access":{ruleId:"s3-bucket-public-access",checkKey:"s3Buckets",name:"S3 Bucket Public Access",description:"Detects S3 buckets with public access enabled.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-block-public-access.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Enable S3 Block Public Access settings","Review bucket policies for public access","Use VPC endpoints for private access"],resourceTypes:["AWS::S3::Bucket"]},"s3-intelligent-tiering":{ruleId:"s3-intelligent-tiering",checkKey:"s3IntelligentTiering",name:"S3 Intelligent Tiering",description:"Recommends S3 Intelligent Tiering for cost optimization.",severity:"LOW",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/intelligent-tiering.html",remediationSteps:["Enable S3 Intelligent-Tiering for buckets with varying access patterns","Configure archive access tiers for infrequently accessed data"],resourceTypes:["AWS::S3::Bucket"]},"s3-lifecycle-policy-missing":{ruleId:"s3-lifecycle-policy-missing",checkKey:"s3LifecyclePolicy",name:"S3 Lifecycle Policy Missing",description:"Detects S3 buckets without lifecycle policies.",severity:"MEDIUM",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html",remediationSteps:["Create lifecycle rules to transition objects to cheaper storage classes","Set expiration rules for temporary data","Use lifecycle rules to delete incomplete multipart uploads"],resourceTypes:["AWS::S3::Bucket"]},"s3-replication-missing":{ruleId:"s3-replication-missing",checkKey:"s3Replication",name:"S3 Replication Missing",description:"Detects critical S3 buckets without cross-region replication.",severity:"LOW",wafPillar:"Reliability",complianceFrameworks:["SOC2","HIPAA","NIST"],awsDocUrl:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/replication.html",remediationSteps:["Enable cross-region replication for disaster recovery","Configure replication rules for critical data"],resourceTypes:["AWS::S3::Bucket"]},"s3-bucket-access-logging-disabled":{ruleId:"s3-bucket-access-logging-disabled",checkKey:"s3BucketLogging",name:"S3 Bucket Access Logging Disabled",description:"Detects S3 buckets without server access logging configured. Required by CIS AWS Foundations 2.1.2 and useful for incident forensics.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/ServerLogs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Set LoggingConfiguration.DestinationBucketName on the bucket to capture access logs","Use a separate bucket for logs to avoid recursive logging","Configure a lifecycle rule on the log bucket to manage storage costs"],resourceTypes:["AWS::S3::Bucket"]},"s3-bucket-policy-non-ssl":{ruleId:"s3-bucket-policy-non-ssl",checkKey:"s3BucketPolicySsl",name:"S3 BucketPolicy Permits Non-SSL Requests",description:"Detects AWS::S3::BucketPolicy resources that lack a Deny statement enforcing aws:SecureTransport. Without this, the bucket accepts plain HTTP requests in addition to HTTPS.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/security-best-practices.html#enforce-tls",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Add a Deny statement with Action s3:* and Condition Bool aws:SecureTransport=false","Apply the Deny to both the bucket ARN and the bucket-objects ARN (arn/* )","Use BoolIfExists if the policy already accepts unsigned requests via specific clauses"],resourceTypes:["AWS::S3::BucketPolicy"]},"s3-bucket-policy-self-lockout":{ruleId:"s3-bucket-policy-self-lockout",checkKey:"s3BucketPolicySelfLockout",name:"S3 BucketPolicy Self-Lockout",description:"Detects AWS::S3::BucketPolicy resources containing a Deny statement on s3:DeleteBucket, s3:*, or * with a broad Principal and no NotPrincipal or aws:PrincipalArn carveout for the account root or admin role. Such a policy locks the account out of its own bucket \u2014 recovery requires breaking glass on the account root credentials, since AWS Support typically declines to intervene where customers have a self-service path via root.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-policy-language-overview.html",complianceFrameworks:["SOC2","NIST"],remediationSteps:["Add a NotPrincipal exemption for the account root (arn:aws:iam::<account>:root) or admin role(s)","Or use a Condition with StringNotEquals on aws:PrincipalArn to exempt admin role ARNs","If the Deny is intended for transport security, scope it with aws:SecureTransport rather than a blanket Deny on Principal: '*'"],resourceTypes:["AWS::S3::BucketPolicy"]},"lambda-env-sensitive-data":{ruleId:"lambda-env-sensitive-data",checkKey:"lambdaEnvironmentVariables",name:"Lambda Sensitive Environment Variables",description:"Detects Lambda functions with sensitive data in environment variables.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Move sensitive data to AWS Secrets Manager","Use SSM Parameter Store with SecureString","Enable Lambda environment variable encryption"],resourceTypes:["AWS::Lambda::Function"]},"lambda-memory-optimization":{ruleId:"lambda-memory-optimization",checkKey:"lambdaMemory",name:"Lambda Memory Optimization",description:"Detects Lambda functions with suboptimal memory configuration.",severity:"LOW",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/lambda/latest/dg/configuration-function-common.html#configuration-memory-console",remediationSteps:["Use AWS Lambda Power Tuning to find optimal memory","Consider cost vs performance tradeoffs"],resourceTypes:["AWS::Lambda::Function"]},"lambda-reserved-concurrency-missing":{ruleId:"lambda-reserved-concurrency-missing",checkKey:"lambdaReservedConcurrency",name:"Lambda Reserved Concurrency Missing",description:"Detects Lambda functions without reserved concurrency.",severity:"LOW",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html",remediationSteps:["Set reserved concurrency for critical functions","Use provisioned concurrency for latency-sensitive workloads"],resourceTypes:["AWS::Lambda::Function"]},"lambda-dlq-missing":{ruleId:"lambda-dlq-missing",checkKey:"lambdaDeadLetterQueue",name:"Lambda Dead Letter Queue Missing",description:"Detects Lambda functions without dead letter queue configuration.",severity:"MEDIUM",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html#invocation-dlq",remediationSteps:["Configure a dead letter queue (SQS or SNS)","Set up monitoring for DLQ messages","Implement retry logic for failed invocations"],resourceTypes:["AWS::Lambda::Function"]},"lambda-vpc-nat-cost":{ruleId:"lambda-vpc-nat-cost",checkKey:"lambdaVpcNatWarning",name:"Lambda VPC NAT Gateway Cost Warning",description:"Warns about potential NAT Gateway costs for VPC-attached Lambda functions.",severity:"MEDIUM",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/lambda/latest/dg/configuration-vpc.html",remediationSteps:["Use VPC endpoints instead of NAT Gateway where possible","Consider if VPC attachment is necessary","Monitor NAT Gateway data processing costs"],resourceTypes:["AWS::Lambda::Function"]},"lambda-permission-public":{ruleId:"lambda-permission-public",checkKey:"lambdaPermission",name:"Lambda Permission Permits Public Access",description:"Detects AWS::Lambda::Permission and AWS::Lambda::LayerVersionPermission resources that grant invoke / use rights with a wildcard Principal, or grant a service principal without a SourceArn / SourceAccount / PrincipalOrgID restriction (confused-deputy risk).",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Replace wildcard Principal with a specific 12-digit AWS account ID or {Ref: AWS::AccountId}","For service principals, set SourceArn to the specific resource that may invoke the function","For S3 service principal, set SourceAccount to your AWS account ID","For LayerVersionPermission, prefer OrganizationId over wildcard Principal"],resourceTypes:["AWS::Lambda::Permission","AWS::Lambda::LayerVersionPermission"]},"dynamodb-autoscaling-missing":{ruleId:"dynamodb-autoscaling-missing",checkKey:"dynamoDBAutoScaling",name:"DynamoDB Auto Scaling Missing",description:"Detects DynamoDB tables without auto-scaling enabled.",severity:"MEDIUM",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AutoScaling.html",remediationSteps:["Enable DynamoDB auto-scaling or use on-demand capacity","Set appropriate minimum and maximum capacity units"],resourceTypes:["AWS::DynamoDB::Table"]},"dynamodb-streams-disabled":{ruleId:"dynamodb-streams-disabled",checkKey:"dynamoDBStreams",name:"DynamoDB Streams Disabled",description:"Detects DynamoDB tables without streams enabled.",severity:"LOW",wafPillar:"Operational Excellence",awsDocUrl:"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.html",remediationSteps:["Enable DynamoDB Streams for change data capture","Consider point-in-time recovery for data protection"],resourceTypes:["AWS::DynamoDB::Table"]},"dynamodb-encryption-aws-owned-key":{ruleId:"dynamodb-encryption-aws-owned-key",checkKey:"dynamoDBEncryption",name:"DynamoDB Table Uses AWS-Owned Encryption Key",description:"Detects AWS::DynamoDB::Table resources without SSESpecification.SSEEnabled=true. DynamoDB always encrypts at rest, but the default AWS-owned key cannot be inspected, audited, or rotated by the customer \u2014 inadequate for HIPAA / PCI-DSS / FedRAMP workloads.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/encryption.howitworks.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set SSESpecification.SSEEnabled to true on the table","Provide SSESpecification.KMSMasterKeyId pointing at a customer-managed KMS key","Verify the KMS key has rotation enabled (kms-key-rotation-disabled covers this)"],resourceTypes:["AWS::DynamoDB::Table"]},"dynamodb-pitr-disabled":{ruleId:"dynamodb-pitr-disabled",checkKey:"dynamoDBPitr",name:"DynamoDB Point-in-Time Recovery Disabled",description:"Detects DynamoDB tables without Point-in-Time Recovery enabled. PITR provides continuous backups for the last 35 days and is required for SOC2 / HIPAA data resilience.",severity:"MEDIUM",wafPillar:"Reliability",complianceFrameworks:["SOC2","HIPAA","NIST"],awsDocUrl:"https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery.html",remediationSteps:["Set PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled to true on the table","Verify the AWS region supports PITR for your table type (Provisioned / On-Demand)"],resourceTypes:["AWS::DynamoDB::Table"]},"rds-encryption-disabled":{ruleId:"rds-encryption-disabled",checkKey:"rdsEncryption",name:"RDS Encryption Disabled",description:"Detects RDS instances without encryption at rest.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.Encryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Enable encryption for new RDS instances","For existing instances, create encrypted snapshot and restore"],resourceTypes:["AWS::RDS::DBInstance","AWS::RDS::DBCluster"]},"rds-multi-az-disabled":{ruleId:"rds-multi-az-disabled",checkKey:"rdsMultiAZ",name:"RDS Multi-AZ Disabled",description:"Detects RDS instances without Multi-AZ deployment.",severity:"MEDIUM",wafPillar:"Reliability",complianceFrameworks:["SOC2","HIPAA","NIST"],awsDocUrl:"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.html",remediationSteps:["Enable Multi-AZ for production databases","Consider Aurora for automatic multi-AZ"],resourceTypes:["AWS::RDS::DBInstance"]},"rds-publicly-accessible":{ruleId:"rds-publicly-accessible",checkKey:"rdsPublicAccess",name:"RDS Publicly Accessible",description:"Detects RDS instances that are publicly accessible.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_VPC.WorkingWithRDSInstanceinaVPC.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Set PubliclyAccessible to false","Use VPC security groups to control access","Access databases through bastion hosts or VPN"],resourceTypes:["AWS::RDS::DBInstance"]},"rds-backup-retention-low":{ruleId:"rds-backup-retention-low",checkKey:"rdsBackupRetention",name:"RDS Backup Retention Low",description:"Detects RDS instances with insufficient backup retention.",severity:"MEDIUM",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithAutomatedBackups.html",complianceFrameworks:["SOC2","HIPAA","NIST"],remediationSteps:["Set backup retention period to at least 7 days","Consider longer retention for compliance requirements","Enable cross-region backup replication"],resourceTypes:["AWS::RDS::DBInstance","AWS::RDS::DBCluster"]},"rds-deletion-protection-disabled":{ruleId:"rds-deletion-protection-disabled",checkKey:"rdsDeletionProtection",name:"RDS Deletion Protection Disabled",description:"Detects RDS instances without deletion protection.",severity:"MEDIUM",wafPillar:"Reliability",complianceFrameworks:["SOC2","HIPAA","NIST"],awsDocUrl:"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_DeleteInstance.html",remediationSteps:["Enable deletion protection for production databases","Use CloudFormation DeletionPolicy: Retain"],resourceTypes:["AWS::RDS::DBInstance","AWS::RDS::DBCluster"]},"rds-logging-disabled":{ruleId:"rds-logging-disabled",checkKey:"rdsLogging",name:"RDS Logging Disabled",description:"Detects RDS DBInstance and DBCluster resources without EnableCloudwatchLogsExports configured. Engine logs (error, slow query, audit) are not exported to CloudWatch for retention or analysis.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_LogAccess.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set EnableCloudwatchLogsExports to the engine's relevant log types (e.g. ['error','slowquery'] for MySQL, ['postgresql'] for PostgreSQL)","Configure a CloudWatch Logs retention policy on the resulting log group","For Aurora, enable both DBCluster and per-instance log exports"],resourceTypes:["AWS::RDS::DBInstance","AWS::RDS::DBCluster"]},"rds-enhanced-monitoring-disabled":{ruleId:"rds-enhanced-monitoring-disabled",checkKey:"rdsEnhancedMonitoring",name:"RDS Enhanced Monitoring Disabled",description:"Detects RDS instances without enhanced monitoring (MonitoringInterval missing or set to 0). OS-level metrics are not published to CloudWatch Logs.",severity:"MEDIUM",wafPillar:"Operational Excellence",awsDocUrl:"https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Monitoring.OS.html",remediationSteps:["Set MonitoringInterval to one of 1, 5, 10, 15, 30, or 60 (seconds)","Provide MonitoringRoleArn pointing at an IAM role with AmazonRDSEnhancedMonitoringRole attached"],resourceTypes:["AWS::RDS::DBInstance"]},"ec2-instance-type-outdated":{ruleId:"ec2-instance-type-outdated",checkKey:"ec2InstanceType",name:"EC2 Instance Type Outdated",description:"Detects EC2 instances using older generation instance types.",severity:"LOW",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html",remediationSteps:["Upgrade to current generation instance types","Use AWS Compute Optimizer for recommendations"],resourceTypes:["AWS::EC2::Instance"]},"nat-gateway-usage":{ruleId:"nat-gateway-usage",checkKey:"natGatewayUsage",name:"NAT Gateway Usage",description:"Identifies NAT Gateway usage for cost awareness.",severity:"LOW",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html",remediationSteps:["Consider VPC endpoints to reduce NAT Gateway traffic","Use NAT instances for lower traffic volumes"],resourceTypes:["AWS::EC2::NatGateway"]},"security-group-unrestricted-ingress":{ruleId:"security-group-unrestricted-ingress",checkKey:"securityGroups",name:"Security Group Unrestricted Ingress",description:"Detects security groups with unrestricted ingress (0.0.0.0/0).",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Restrict ingress to specific IP ranges","Use security group references for internal traffic","Implement least privilege network access"],resourceTypes:["AWS::EC2::SecurityGroup"]},"ebs-volume-unencrypted":{ruleId:"ebs-volume-unencrypted",checkKey:"ebsVolumes",name:"EBS Volume Unencrypted",description:"Detects EBS volumes without encryption.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Enable EBS encryption by default in account settings","Use KMS customer managed keys for additional control"],resourceTypes:["AWS::EC2::Volume"]},"ec2-subnet-auto-public-ip":{ruleId:"ec2-subnet-auto-public-ip",checkKey:"ec2SubnetAutoPublicIp",name:"EC2 Subnet Auto-Assigns Public IPs",description:"Detects AWS::EC2::Subnet resources with MapPublicIpOnLaunch=true. Instances launched into the subnet inherit a public IP by default, which makes them internet-reachable without an explicit opt-in at the ENI level.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/vpc/latest/userguide/vpc-ip-addressing.html#subnet-public-ip",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set MapPublicIpOnLaunch to false unless this is intentionally a public subnet","Have instances opt into a public IP via the ENI configuration when needed","Use VPC endpoints / NAT for outbound access from private subnets"],resourceTypes:["AWS::EC2::Subnet"]},"ec2-instance-public-ip":{ruleId:"ec2-instance-public-ip",checkKey:"ec2PublicIp",name:"EC2 Instance Public IP",description:"Detects EC2 instances whose NetworkInterfaces specify AssociatePublicIpAddress=true, exposing the instance directly to the internet.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-instance-addressing.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Set AssociatePublicIpAddress to false on the NetworkInterface","Place the instance in a private subnet and use a NAT Gateway / VPC endpoint for outbound","Use an ALB / NLB in a public subnet to front the workload instead"],resourceTypes:["AWS::EC2::Instance"]},"cloudfront-https-only":{ruleId:"cloudfront-https-only",checkKey:"cloudFrontHttpsOnly",name:"CloudFront HTTPS Only",description:"Detects CloudFront distributions allowing HTTP traffic.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-https.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set ViewerProtocolPolicy to https-only or redirect-to-https","Configure custom SSL certificate"],resourceTypes:["AWS::CloudFront::Distribution"]},"cloudfront-waf-missing":{ruleId:"cloudfront-waf-missing",checkKey:"cloudFrontWafAssociation",name:"CloudFront WAF Missing",description:"Detects CloudFront distributions without WAF association.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-awswaf.html",complianceFrameworks:["SOC2","PCI-DSS","NIST"],remediationSteps:["Associate AWS WAF web ACL with CloudFront distribution","Configure WAF rules for common attack patterns"],resourceTypes:["AWS::CloudFront::Distribution"]},"cloudfront-logging-disabled":{ruleId:"cloudfront-logging-disabled",checkKey:"cloudFrontLogging",name:"CloudFront Logging Disabled",description:"Detects CloudFront distributions without access logging.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable standard logging to S3","Consider real-time logs for detailed analysis"],resourceTypes:["AWS::CloudFront::Distribution"]},"cloudfront-tls-outdated":{ruleId:"cloudfront-tls-outdated",checkKey:"cloudFrontTls",name:"CloudFront TLS Outdated",description:"Detects CloudFront distributions using outdated TLS versions.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/secure-connections-supported-viewer-protocols-ciphers.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set MinimumProtocolVersion to TLSv1.2_2021 or higher","Use a custom SSL certificate"],resourceTypes:["AWS::CloudFront::Distribution"]},"elb-deletion-protection-disabled":{ruleId:"elb-deletion-protection-disabled",checkKey:"elbDeletionProtection",name:"ELB Deletion Protection Disabled",description:"Detects load balancers without deletion protection.",severity:"MEDIUM",wafPillar:"Reliability",complianceFrameworks:["SOC2","HIPAA","NIST"],awsDocUrl:"https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#deletion-protection",remediationSteps:["Enable deletion protection for production load balancers","Use CloudFormation DeletionPolicy: Retain"],resourceTypes:["AWS::ElasticLoadBalancingV2::LoadBalancer"]},"elb-logging-disabled":{ruleId:"elb-logging-disabled",checkKey:"elbLogging",name:"ELB Logging Disabled",description:"Detects load balancers without access logging.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable access logging to S3","Configure log retention policy"],resourceTypes:["AWS::ElasticLoadBalancingV2::LoadBalancer"]},"elb-https-listeners-missing":{ruleId:"elb-https-listeners-missing",checkKey:"elbHttpsListeners",name:"ELB HTTPS Listeners Missing",description:"Detects load balancers with HTTP listeners not redirecting to HTTPS.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Add HTTPS listener with valid SSL certificate","Configure HTTP to HTTPS redirect"],resourceTypes:["AWS::ElasticLoadBalancingV2::Listener"]},"elb-security-policy-outdated":{ruleId:"elb-security-policy-outdated",checkKey:"elbSecurityPolicy",name:"ELB Security Policy Outdated",description:"Detects load balancers using outdated TLS security policies.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Update to ELBSecurityPolicy-TLS13-1-2-2021-06 or newer","Remove support for deprecated protocols"],resourceTypes:["AWS::ElasticLoadBalancingV2::Listener"]},"ecs-secrets-plaintext":{ruleId:"ecs-secrets-plaintext",checkKey:"ecsSecrets",name:"ECS Secrets in Plaintext",description:"Detects ECS task definitions with sensitive data in plaintext environment variables.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Use secrets property with Secrets Manager ARN","Use SSM Parameter Store SecureString"],resourceTypes:["AWS::ECS::TaskDefinition"]},"ecs-logging-disabled":{ruleId:"ecs-logging-disabled",checkKey:"ecsLogging",name:"ECS Logging Disabled",description:"Detects ECS task definitions without logging configured.",severity:"MEDIUM",wafPillar:"Operational Excellence",awsDocUrl:"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using_awslogs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Configure awslogs log driver","Set up CloudWatch log groups with retention"],resourceTypes:["AWS::ECS::TaskDefinition"]},"ecs-service-connect-access-logs-missing":{ruleId:"ecs-service-connect-access-logs-missing",checkKey:"ecsServiceConnectLogs",name:"ECS Service Connect Access Logs Missing",description:"Detects ECS services with Service Connect enabled but no access log configuration, leaving inter-service traffic unaudited.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-connect-logging.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set ServiceConnectConfiguration.LogConfiguration with a LogDriver such as awslogs","Send Service Connect logs to a CloudWatch log group with a retention policy","Confirm log group encryption is configured for sensitive workloads"],resourceTypes:["AWS::ECS::Service"]},"ecs-resources-missing":{ruleId:"ecs-resources-missing",checkKey:"ecsResources",name:"ECS Resource Limits Missing",description:"Detects ECS task definitions without CPU/memory limits.",severity:"LOW",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#task_size",remediationSteps:["Set CPU and memory at task level for Fargate","Set container-level memory limits for EC2"],resourceTypes:["AWS::ECS::TaskDefinition"]},"cognito-password-policy-weak":{ruleId:"cognito-password-policy-weak",checkKey:"cognitoPasswordPolicy",name:"Cognito Password Policy Weak",description:"Detects Cognito user pools with weak password policies.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-policies.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set minimum password length to at least 12 characters","Require uppercase, lowercase, numbers, and symbols"],resourceTypes:["AWS::Cognito::UserPool"]},"cognito-mfa-disabled":{ruleId:"cognito-mfa-disabled",checkKey:"cognitoMfa",name:"Cognito MFA Disabled",description:"Detects Cognito user pools without MFA enabled.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-mfa.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable MFA (OPTIONAL or ON)","Configure SMS or TOTP as MFA method"],resourceTypes:["AWS::Cognito::UserPool"]},"cognito-advanced-security-disabled":{ruleId:"cognito-advanced-security-disabled",checkKey:"cognitoAdvancedSecurity",name:"Cognito Advanced Security Disabled",description:"Detects Cognito user pools without advanced security features.",severity:"LOW",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-settings-advanced-security.html",complianceFrameworks:["SOC2","NIST"],remediationSteps:["Enable advanced security mode (AUDIT or ENFORCED)","Configure risk-based adaptive authentication"],resourceTypes:["AWS::Cognito::UserPool"]},"api-gateway-method-auth-missing":{ruleId:"api-gateway-method-auth-missing",checkKey:"apiGatewayMethodAuth",name:"API Gateway Method Has No Authorization",description:"Detects AWS::ApiGateway::Method and AWS::ApiGatewayV2::Route resources where AuthorizationType is missing or NONE (excluding OPTIONS preflight). Public-by-default endpoints expose backend Lambdas to anyone on the internet.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/apigateway/latest/developerguide/permissions.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set AuthorizationType to AWS_IAM, COGNITO_USER_POOLS, or CUSTOM (REST APIs)","Use JWT or AWS_IAM AuthorizationType for HTTP APIs (v2)","If the route is intentionally public (e.g. webhook receiver), prefer api-key + WAF rate limiting and suppress this rule explicitly"],resourceTypes:["AWS::ApiGateway::Method","AWS::ApiGatewayV2::Route"]},"api-gateway-logging-disabled":{ruleId:"api-gateway-logging-disabled",checkKey:"apiGateway",name:"API Gateway Logging Disabled",description:"Detects API Gateway stages without logging enabled.",severity:"MEDIUM",wafPillar:"Operational Excellence",awsDocUrl:"https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-logging.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable CloudWatch logging for API stages","Configure access logging for request/response details"],resourceTypes:["AWS::ApiGateway::Stage","AWS::ApiGatewayV2::Stage"]},"secrets-manager-rotation-disabled":{ruleId:"secrets-manager-rotation-disabled",checkKey:"secretsManager",name:"Secrets Manager Rotation Disabled",description:"Detects secrets without automatic rotation configured.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable automatic rotation","Set rotation schedule (e.g., every 30 days)"],resourceTypes:["AWS::SecretsManager::Secret"]},"cloudtrail-logging-disabled":{ruleId:"cloudtrail-logging-disabled",checkKey:"cloudTrailLogging",name:"CloudTrail Logging Disabled",description:"Detects CloudTrail trails with logging disabled.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-getting-started.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Ensure IsLogging is enabled","Configure multi-region trails","Enable log file validation"],resourceTypes:["AWS::CloudTrail::Trail"]},"eventbridge-bus-policy-wildcard-principal":{ruleId:"eventbridge-bus-policy-wildcard-principal",checkKey:"eventBusPolicy",name:"EventBridge Bus Policy Allows Wildcard Principal",description:"Detects AWS::Events::EventBusPolicy with an Allow statement targeting Principal=* (or AWS=*) without a Condition restricting access. Without the condition, any AWS account can publish events to the bus.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-bus-perms.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Replace wildcard Principal with specific 12-digit AWS account IDs","Or scope the policy with a Condition such as aws:PrincipalOrgID","Verify the StatementId is descriptive \u2014 easier to audit later"],resourceTypes:["AWS::Events::EventBusPolicy"]},"eventbridge-dlq-missing":{ruleId:"eventbridge-dlq-missing",checkKey:"eventBridgeRules",name:"EventBridge DLQ Missing",description:"Detects EventBridge rules without dead letter queue.",severity:"LOW",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-rule-dlq.html",remediationSteps:["Configure dead letter queue for failed event delivery","Set up monitoring for DLQ messages"],resourceTypes:["AWS::Events::Rule"]},"kms-key-rotation-disabled":{ruleId:"kms-key-rotation-disabled",checkKey:"kmsKeys",name:"KMS Key Rotation Disabled",description:"Detects KMS keys without automatic rotation.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Enable automatic key rotation","Key rotation occurs annually"],resourceTypes:["AWS::KMS::Key"]},"kms-key-policy-self-lockout":{ruleId:"kms-key-policy-self-lockout",checkKey:"kmsKeyPolicySelfLockout",name:"KMS Key Policy Self-Lockout",description:"Detects AWS::KMS::Key resources whose KeyPolicy contains a Deny statement on kms:*, kms:PutKeyPolicy, or * with a broad Principal and no carveout for the account root or admin role. Such a policy locks the account out of its own key \u2014 recovery requires breaking glass on the account root credentials AND scheduling a 7-30 day key deletion (which does not actually let you recover the key, just remove it). Effectively unrecoverable for any data the key has encrypted; AWS Support typically declines to intervene where customers have a self-service path via root.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html",complianceFrameworks:["SOC2","NIST"],remediationSteps:["Keep the auto-injected root Allow statement (CDK's defaultKeyPolicy) intact, or add an explicit Allow on Principal: { AWS: 'arn:aws:iam::<account>:root' } for Action: kms:*","Or add a NotPrincipal exemption for the account root or admin role(s)","Or use a Condition with StringNotEquals on aws:PrincipalArn to exempt admin role ARNs"],resourceTypes:["AWS::KMS::Key"]},"sns-encryption-disabled":{ruleId:"sns-encryption-disabled",checkKey:"sns",name:"SNS Encryption Disabled",description:"Detects SNS topics without encryption.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/sns/latest/dg/sns-server-side-encryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable server-side encryption with KMS","Use customer managed keys for additional control"],resourceTypes:["AWS::SNS::Topic"]},"sqs-encryption-disabled":{ruleId:"sqs-encryption-disabled",checkKey:"sqs",name:"SQS Encryption Disabled",description:"Detects SQS queues without encryption.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-server-side-encryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable server-side encryption with KMS","Use SQS-managed keys (SSE-SQS) or customer managed keys"],resourceTypes:["AWS::SQS::Queue"]},"sqs-queue-policy-self-lockout":{ruleId:"sqs-queue-policy-self-lockout",checkKey:"sqsQueuePolicySelfLockout",name:"SQS QueuePolicy Self-Lockout",description:"Detects AWS::SQS::QueuePolicy resources containing a Deny statement on sqs:DeleteQueue, sqs:RemovePermission, sqs:*, or * with a broad Principal and no NotPrincipal or aws:PrincipalArn carveout for the account root or admin role. Such a policy locks the account out of its own queue \u2014 recovery requires breaking glass on the account root credentials to remove the queue policy, or delete-and-recreate the queue if nothing else depends on its ARN. In event-driven systems that is often a multi-stack rebuild.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-access-policy-language-basic-structure.html",complianceFrameworks:["SOC2","NIST"],remediationSteps:["Add a NotPrincipal exemption for the account root (arn:aws:iam::<account>:root) or admin role(s)","Or use a Condition with StringNotEquals on aws:PrincipalArn to exempt admin role ARNs","If the Deny is intended to scope to AWS services, use aws:PrincipalIsAWSService rather than a blanket Deny on Principal: '*'"],resourceTypes:["AWS::SQS::QueuePolicy"]},"sns-topic-policy-self-lockout":{ruleId:"sns-topic-policy-self-lockout",checkKey:"snsTopicPolicySelfLockout",name:"SNS TopicPolicy Self-Lockout",description:"Detects AWS::SNS::TopicPolicy resources containing a Deny statement on sns:DeleteTopic, sns:RemovePermission, sns:*, or * with a broad Principal and no NotPrincipal or aws:PrincipalArn carveout for the account root or admin role. Such a policy locks the account out of its own topic \u2014 recovery requires breaking glass on the account root credentials to remove the topic policy, or delete-and-recreate the topic if no subscribers depend on its ARN. In fan-out architectures that is often a multi-stack rebuild.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/sns/latest/dg/sns-access-policy-language-key-concepts.html",complianceFrameworks:["SOC2","NIST"],remediationSteps:["Add a NotPrincipal exemption for the account root (arn:aws:iam::<account>:root) or admin role(s)","Or use a Condition with StringNotEquals on aws:PrincipalArn to exempt admin role ARNs","If the Deny is intended to scope to AWS services, use aws:PrincipalIsAWSService rather than a blanket Deny on Principal: '*'"],resourceTypes:["AWS::SNS::TopicPolicy"]},"stepfunctions-logging-disabled":{ruleId:"stepfunctions-logging-disabled",checkKey:"stepFunctions",name:"Step Functions Logging Disabled",description:"Detects Step Functions state machines without logging.",severity:"MEDIUM",wafPillar:"Operational Excellence",awsDocUrl:"https://docs.aws.amazon.com/step-functions/latest/dg/cw-logs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable CloudWatch Logs for state machine execution","Set appropriate log level (ALL, ERROR, FATAL, OFF)"],resourceTypes:["AWS::StepFunctions::StateMachine"]},"acm-certificate-email-validation":{ruleId:"acm-certificate-email-validation",checkKey:"acmValidation",name:"ACM Certificate Validation Hardening",description:"Detects ACM certificates using email validation or with certificate transparency logging disabled.",severity:"LOW",wafPillar:"Security",complianceFrameworks:["SOC2","NIST"],awsDocUrl:"https://docs.aws.amazon.com/acm/latest/userguide/dns-validation.html",remediationSteps:["Use DNS validation for automated certificate renewal","Enable certificate transparency logging to detect misissuance"],resourceTypes:["AWS::CertificateManager::Certificate"]},"appsync-api-key-auth":{ruleId:"appsync-api-key-auth",checkKey:"appSyncAuth",name:"AppSync API Key Authentication",description:"Detects AppSync APIs using API key authentication or lacking additional authentication providers.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/appsync/latest/devguide/security-authz.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Use AWS_IAM, Cognito User Pools, or OIDC for production workloads","Configure AdditionalAuthenticationProviders for client flexibility"],resourceTypes:["AWS::AppSync::GraphQLApi"]},"appsync-logging-disabled":{ruleId:"appsync-logging-disabled",checkKey:"appSyncLogging",name:"AppSync Logging Disabled",description:"Detects AppSync APIs without logging, field-level logging, or X-Ray tracing.",severity:"MEDIUM",wafPillar:"Operational Excellence",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],awsDocUrl:"https://docs.aws.amazon.com/appsync/latest/devguide/monitoring.html",remediationSteps:["Configure LogConfig to capture request/response logs in CloudWatch","Set FieldLogLevel to ERROR or ALL for resolver execution detail","Enable XrayEnabled for distributed tracing"],resourceTypes:["AWS::AppSync::GraphQLApi"]},"appsync-waf-missing":{ruleId:"appsync-waf-missing",checkKey:"appSyncWaf",name:"AppSync WAF Missing",description:"Detects AppSync APIs without an associated AWS WAF WebACL.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/appsync/latest/devguide/WAF-Integration.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Associate a WAFv2 WebACL with the AppSync API","Define rules to protect against common web exploits"],resourceTypes:["AWS::AppSync::GraphQLApi","AWS::WAFv2::WebACLAssociation"]},"backup-plan-misconfigured":{ruleId:"backup-plan-misconfigured",checkKey:"backupPlans",name:"Backup Plan Misconfigured",description:"Detects Backup plan rules without cross-region copy or lifecycle configuration.",severity:"LOW",wafPillar:"Reliability",complianceFrameworks:["SOC2","HIPAA","NIST"],awsDocUrl:"https://docs.aws.amazon.com/aws-backup/latest/devguide/about-backup-plans.html",remediationSteps:["Add CopyActions to replicate backups cross-region for DR","Set DeleteAfterDays / MoveToColdStorageAfterDays to manage retention and cost"],resourceTypes:["AWS::Backup::BackupPlan"]},"backup-vault-hardening":{ruleId:"backup-vault-hardening",checkKey:"backupVault",name:"Backup Vault Hardening",description:"Detects Backup vaults using AWS-managed keys or without a vault lock for compliance.",severity:"LOW",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/aws-backup/latest/devguide/vaultlock.html",complianceFrameworks:["SOC2","HIPAA","NIST"],remediationSteps:["Specify a customer-managed KMS key via EncryptionKeyArn","Add a BackupVaultLock to enforce retention and prevent deletion"],resourceTypes:["AWS::Backup::BackupVault","AWS::Backup::BackupVaultLock"]},"cloudwatch-alarm-actions-missing":{ruleId:"cloudwatch-alarm-actions-missing",checkKey:"cloudWatchAlarms",name:"CloudWatch Alarm Actions Missing",description:"Detects CloudWatch Alarms without alarm actions or missing-data handling.",severity:"MEDIUM",wafPillar:"Operational Excellence",awsDocUrl:"https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html",remediationSteps:["Add AlarmActions (SNS, Lambda, SSM) for state-change notifications","Set TreatMissingData to define behaviour for missing data points"],resourceTypes:["AWS::CloudWatch::Alarm"]},"cloudwatch-logs-encryption-disabled":{ruleId:"cloudwatch-logs-encryption-disabled",checkKey:"cloudWatchEncryption",name:"CloudWatch Logs Encryption Disabled",description:"Detects CloudWatch Log Groups not encrypted with a customer-managed KMS key.",severity:"LOW",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/encrypt-log-data-kms.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set KmsKeyId on the LogGroup to encrypt with a customer-managed key"],resourceTypes:["AWS::Logs::LogGroup"]},"cloudwatch-logs-retention-missing":{ruleId:"cloudwatch-logs-retention-missing",checkKey:"cloudWatchLogRetention",name:"CloudWatch Logs Retention Missing",description:"Detects CloudWatch Log Groups without an explicit retention period (logs retained indefinitely).",severity:"MEDIUM",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html",remediationSteps:["Set RetentionInDays to control storage cost (30\u201390 days for ops, longer for compliance)"],resourceTypes:["AWS::Logs::LogGroup"]},"ecr-mutable-tags":{ruleId:"ecr-mutable-tags",checkKey:"ecrImmutableTags",name:"ECR Mutable Image Tags",description:"Detects ECR repositories that allow image tags to be overwritten.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-tag-mutability.html",complianceFrameworks:["SOC2","PCI-DSS","NIST"],remediationSteps:["Set ImageTagMutability to IMMUTABLE"],resourceTypes:["AWS::ECR::Repository"]},"ecr-lifecycle-policy-missing":{ruleId:"ecr-lifecycle-policy-missing",checkKey:"ecrLifecycle",name:"ECR Lifecycle Policy Missing",description:"Detects ECR repositories without a lifecycle policy to clean up old images.",severity:"MEDIUM",wafPillar:"Cost Optimization",awsDocUrl:"https://docs.aws.amazon.com/AmazonECR/latest/userguide/LifecyclePolicies.html",remediationSteps:["Define a LifecyclePolicy to expire untagged or excess image versions"],resourceTypes:["AWS::ECR::Repository"]},"ecr-scan-on-push-disabled":{ruleId:"ecr-scan-on-push-disabled",checkKey:"ecrScanning",name:"ECR Scan-on-Push Disabled",description:"Detects ECR repositories without image vulnerability scanning on push.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable ScanOnPush in ImageScanningConfiguration","Or use enhanced scanning at the registry level"],resourceTypes:["AWS::ECR::Repository"]},"eks-secrets-encryption-disabled":{ruleId:"eks-secrets-encryption-disabled",checkKey:"eksEncryption",name:"EKS Secrets Encryption Disabled",description:"Detects EKS clusters without envelope encryption for Kubernetes secrets in etcd.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/eks/latest/userguide/enable-kms.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:['Configure EncryptionConfig with a KMS key referencing resources: ["secrets"]'],resourceTypes:["AWS::EKS::Cluster"]},"eks-control-plane-logging-disabled":{ruleId:"eks-control-plane-logging-disabled",checkKey:"eksLogging",name:"EKS Control Plane Logging Disabled",description:"Detects EKS clusters with no control plane log types enabled.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable api, audit, authenticator, controllerManager, and scheduler logs"],resourceTypes:["AWS::EKS::Cluster"]},"eks-public-endpoint-unrestricted":{ruleId:"eks-public-endpoint-unrestricted",checkKey:"eksPublicEndpoint",name:"EKS Public Endpoint Unrestricted",description:"Detects EKS clusters with the API endpoint reachable from 0.0.0.0/0 or only via the public network.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable EndpointPrivateAccess for in-VPC node communication","Restrict PublicAccessCidrs to known administrative IP ranges"],resourceTypes:["AWS::EKS::Cluster"]},"elasticache-auth-token-missing":{ruleId:"elasticache-auth-token-missing",checkKey:"elastiCacheAuth",name:"ElastiCache AUTH Token Missing",description:"Detects Redis replication groups with transit encryption but no AUTH token configured.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/auth.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set AuthToken to require Redis client authentication"],resourceTypes:["AWS::ElastiCache::ReplicationGroup"]},"elasticache-encryption-disabled":{ruleId:"elasticache-encryption-disabled",checkKey:"elastiCacheEncryption",name:"ElastiCache Encryption Disabled",description:"Detects ElastiCache clusters without at-rest or in-transit encryption.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/at-rest-encryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set AtRestEncryptionEnabled: true","Set TransitEncryptionEnabled: true"],resourceTypes:["AWS::ElastiCache::ReplicationGroup","AWS::ElastiCache::CacheCluster"]},"elasticache-failover-disabled":{ruleId:"elasticache-failover-disabled",checkKey:"elastiCacheFailover",name:"ElastiCache Automatic Failover Disabled",description:"Detects ElastiCache replication groups without automatic failover or Multi-AZ.",severity:"MEDIUM",wafPillar:"Reliability",complianceFrameworks:["SOC2","HIPAA"],awsDocUrl:"https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/AutoFailover.html",remediationSteps:["Enable AutomaticFailoverEnabled","Enable MultiAZEnabled to span availability zones"],resourceTypes:["AWS::ElastiCache::ReplicationGroup"]},"glue-connection-network-isolation":{ruleId:"glue-connection-network-isolation",checkKey:"glueConnections",name:"Glue Connection Network Isolation",description:"Detects Glue JDBC connections without VPC subnet placement or SSL enforcement.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/glue/latest/dg/setup-vpc-for-glue-access.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set PhysicalConnectionRequirements with SubnetId and SecurityGroupIdList","Include SSL parameters in the JDBC connection URL"],resourceTypes:["AWS::Glue::Connection"]},"glue-job-encryption-missing":{ruleId:"glue-job-encryption-missing",checkKey:"glueEncryption",name:"Glue Job Encryption Missing",description:"Detects Glue jobs without an attached SecurityConfiguration for encrypting bookmarks, S3 data, and CloudWatch logs.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/glue/latest/dg/encryption-security-configuration.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Create a SecurityConfiguration enabling KMS encryption for all targets","Reference it via the job's SecurityConfiguration property"],resourceTypes:["AWS::Glue::Job"]},"kinesis-encryption-disabled":{ruleId:"kinesis-encryption-disabled",checkKey:"kinesisEncryption",name:"Kinesis Encryption Disabled",description:"Detects Kinesis Data Streams without server-side KMS encryption.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/streams/latest/dev/server-side-encryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set StreamEncryption with EncryptionType: KMS and a KeyId"],resourceTypes:["AWS::Kinesis::Stream"]},"kinesis-retention-minimum":{ruleId:"kinesis-retention-minimum",checkKey:"kinesisRetention",name:"Kinesis Minimum Retention",description:"Detects Kinesis Data Streams using the default 24-hour retention period.",severity:"LOW",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/streams/latest/dev/kinesis-extended-retention.html",remediationSteps:["Increase RetentionPeriodHours to support replay/reprocessing during incidents"],resourceTypes:["AWS::Kinesis::Stream"]},"lambda-runtime-deprecated":{ruleId:"lambda-runtime-deprecated",checkKey:"lambdaRuntime",name:"Lambda Deprecated Runtime",description:"Detects Lambda functions using runtimes that have reached or are approaching end-of-life.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html",complianceFrameworks:["SOC2","PCI-DSS","NIST"],remediationSteps:["Upgrade to a currently supported runtime","Track AWS Lambda runtime deprecation announcements"],resourceTypes:["AWS::Lambda::Function"]},"msk-client-authentication-missing":{ruleId:"msk-client-authentication-missing",checkKey:"mskAuth",name:"MSK Client Authentication Missing",description:"Detects MSK clusters without client authentication or that allow unauthenticated access.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/msk/latest/developerguide/kafka_apis_iam.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable SASL/SCRAM, IAM auth, or mTLS in ClientAuthentication","Disable Unauthenticated access"],resourceTypes:["AWS::MSK::Cluster"]},"msk-encryption-weak":{ruleId:"msk-encryption-weak",checkKey:"mskEncryption",name:"MSK Encryption Weak",description:"Detects MSK clusters without TLS for client-broker traffic, without inter-broker encryption, or using AWS-managed keys for at-rest encryption.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/msk/latest/developerguide/msk-encryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set ClientBroker to TLS in EncryptionInTransit","Set InCluster to true in EncryptionInTransit","Specify DataVolumeKMSKeyId for at-rest encryption"],resourceTypes:["AWS::MSK::Cluster"]},"msk-broker-logging-disabled":{ruleId:"msk-broker-logging-disabled",checkKey:"mskLogging",name:"MSK Broker Logging Disabled",description:"Detects MSK clusters without broker logs configured.",severity:"MEDIUM",wafPillar:"Operational Excellence",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],awsDocUrl:"https://docs.aws.amazon.com/msk/latest/developerguide/msk-logging.html",remediationSteps:["Enable broker logs to CloudWatch Logs, Firehose, or S3"],resourceTypes:["AWS::MSK::Cluster"]},"opensearch-access-control-weak":{ruleId:"opensearch-access-control-weak",checkKey:"openSearchAccessControl",name:"OpenSearch Access Control Weak",description:"Detects OpenSearch domains without fine-grained access control or VPC placement.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/opensearch-service/latest/developerguide/fgac.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable AdvancedSecurityOptions","Configure VPCOptions to deploy the domain inside a VPC"],resourceTypes:["AWS::OpenSearchService::Domain","AWS::Elasticsearch::Domain"]},"opensearch-encryption-disabled":{ruleId:"opensearch-encryption-disabled",checkKey:"openSearchEncryption",name:"OpenSearch Encryption Disabled",description:"Detects OpenSearch domains without at-rest encryption or node-to-node encryption.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/opensearch-service/latest/developerguide/encryption-at-rest.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable EncryptionAtRestOptions with a KMS key","Enable NodeToNodeEncryptionOptions"],resourceTypes:["AWS::OpenSearchService::Domain","AWS::Elasticsearch::Domain"]},"opensearch-logging-disabled":{ruleId:"opensearch-logging-disabled",checkKey:"openSearchLogging",name:"OpenSearch Logging Disabled",description:"Detects OpenSearch domains without audit logs or application logs published to CloudWatch.",severity:"LOW",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/opensearch-service/latest/developerguide/audit-logs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Enable AUDIT_LOGS in LogPublishingOptions","Enable ES_APPLICATION_LOGS in LogPublishingOptions"],resourceTypes:["AWS::OpenSearchService::Domain","AWS::Elasticsearch::Domain"]},"redshift-encryption-disabled":{ruleId:"redshift-encryption-disabled",checkKey:"redshiftEncryption",name:"Redshift Encryption Disabled",description:"Detects Redshift clusters without at-rest encryption.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-db-encryption.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set Encrypted: true and specify a KmsKeyId"],resourceTypes:["AWS::Redshift::Cluster"]},"redshift-audit-logging-disabled":{ruleId:"redshift-audit-logging-disabled",checkKey:"redshiftLogging",name:"Redshift Audit Logging Disabled",description:"Detects Redshift clusters without audit logging to S3 (connection, user, query activity).",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set LoggingProperties with a target S3 bucket and key prefix"],resourceTypes:["AWS::Redshift::Cluster"]},"redshift-publicly-accessible":{ruleId:"redshift-publicly-accessible",checkKey:"redshiftPublicAccess",name:"Redshift Publicly Accessible",description:"Detects Redshift clusters reachable from the public internet.",severity:"CRITICAL",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/redshift/latest/mgmt/managing-clusters-vpc.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Set PubliclyAccessible: false","Use VPC endpoints, bastion hosts, or VPN for access"],resourceTypes:["AWS::Redshift::Cluster"]},"route53-dnssec-disabled":{ruleId:"route53-dnssec-disabled",checkKey:"route53Dnssec",name:"Route 53 DNSSEC Disabled",description:"Detects Route 53 hosted zones without DNSSEC signing enabled.",severity:"LOW",wafPillar:"Security",complianceFrameworks:["SOC2","NIST"],awsDocUrl:"https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-configuring-dnssec.html",remediationSteps:["Create an AWS::Route53::DNSSEC resource for the hosted zone","Configure a key-signing key (KSK)"],resourceTypes:["AWS::Route53::HostedZone","AWS::Route53::DNSSEC"]},"route53-health-check-suboptimal":{ruleId:"route53-health-check-suboptimal",checkKey:"route53HealthChecks",name:"Route 53 Health Check Suboptimal",description:"Detects Route 53 health checks using HTTP instead of HTTPS or the standard request interval.",severity:"LOW",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-failover.html",remediationSteps:["Use HTTPS to validate certificate and endpoint security","Use a 10-second request interval for critical endpoints"],resourceTypes:["AWS::Route53::HealthCheck"]},"route53-query-logging-disabled":{ruleId:"route53-query-logging-disabled",checkKey:"route53QueryLogging",name:"Route 53 Query Logging Disabled",description:"Detects Route 53 hosted zones without query logging.",severity:"LOW",wafPillar:"Security",complianceFrameworks:["SOC2","HIPAA","NIST"],awsDocUrl:"https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/query-logs.html",remediationSteps:["Create an AWS::Route53::QueryLoggingConfig pointing to a CloudWatch Logs group"],resourceTypes:["AWS::Route53::HostedZone","AWS::Route53::QueryLoggingConfig"]},"vpc-default-security-group-rules-present":{ruleId:"vpc-default-security-group-rules-present",checkKey:"vpcDefaultSecurityGroup",name:"VPC Default Security Group Has Rules",description:"Detects default VPC security groups with ingress or egress rules; defaults should be empty.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/vpc/latest/userguide/default-security-group.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Remove all rules from the default security group","Use purpose-built security groups instead"],resourceTypes:["AWS::EC2::SecurityGroup"]},"vpc-flow-logs-missing":{ruleId:"vpc-flow-logs-missing",checkKey:"vpcFlowLogs",name:"VPC Flow Logs Missing",description:"Detects VPCs without flow logs configured.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","CIS","NIST"],remediationSteps:["Create an AWS::EC2::FlowLog resource targeting the VPC","Send logs to CloudWatch Logs or S3"],resourceTypes:["AWS::EC2::VPC","AWS::EC2::FlowLog"]},"waf-logging-disabled":{ruleId:"waf-logging-disabled",checkKey:"wafLogging",name:"WAF Logging Disabled",description:"Detects WAFv2 WebACLs without logging configuration for analysed requests.",severity:"MEDIUM",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/waf/latest/developerguide/logging.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Create an AWS::WAFv2::LoggingConfiguration for the WebACL"],resourceTypes:["AWS::WAFv2::WebACL","AWS::WAFv2::LoggingConfiguration"]},"autoscaling-group-no-elb-healthcheck":{ruleId:"autoscaling-group-no-elb-healthcheck",checkKey:"autoScalingGroupHealthCheck",name:"AutoScaling Group Not Using ELB Health Checks",description:"Detects AWS::AutoScaling::AutoScalingGroup resources attached to a load balancer (LoadBalancerNames or TargetGroupARNs) but using EC2 health checks. EC2 health checks miss app-level outages the load balancer would otherwise detect.",severity:"MEDIUM",wafPillar:"Reliability",awsDocUrl:"https://docs.aws.amazon.com/autoscaling/ec2/userguide/healthcheck.html",remediationSteps:["Set HealthCheckType to ELB on the AutoScalingGroup","Set HealthCheckGracePeriod to give instances time to bootstrap before the LB starts probing","Verify the ALB / NLB target group has appropriate health-check thresholds"],resourceTypes:["AWS::AutoScaling::AutoScalingGroup"]},"autoscaling-launch-config-public-ip":{ruleId:"autoscaling-launch-config-public-ip",checkKey:"autoScalingLaunchConfigPublicIp",name:"AutoScaling LaunchConfiguration Assigns Public IP",description:"Detects AWS::AutoScaling::LaunchConfiguration with AssociatePublicIpAddress=true. Instances launched from this configuration get a public IP and are internet-reachable directly.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/autoscaling/ec2/userguide/AutoScalingGroupExamples.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set AssociatePublicIpAddress to false on the LaunchConfiguration","Place instances in private subnets behind an ALB / NLB","Use a NAT Gateway / VPC endpoints for outbound traffic","Migrate to AWS::EC2::LaunchTemplate (LaunchConfiguration is deprecated)"],resourceTypes:["AWS::AutoScaling::LaunchConfiguration"]},"efs-encryption-disabled":{ruleId:"efs-encryption-disabled",checkKey:"efsEncryption",name:"EFS Encryption Disabled",description:"Detects AWS::EFS::FileSystem resources without Encrypted=true. The CFN default is unencrypted (unlike the EFS console default), and encryption can only be enabled at filesystem creation.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/efs/latest/ug/encryption-at-rest.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Set Encrypted to true on the AWS::EFS::FileSystem resource","Provide KmsKeyId pointing at a customer-managed KMS key for additional control","For existing unencrypted filesystems, migrate data to a new encrypted filesystem"],resourceTypes:["AWS::EFS::FileSystem"]},"waf-webacl-misconfigured":{ruleId:"waf-webacl-misconfigured",checkKey:"wafWebAcl",name:"WAF WebACL Misconfigured",description:"Detects WAFv2 WebACLs with no rules, default Allow action, or CloudWatch metrics disabled.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/waf/latest/developerguide/web-acl.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Add WAF rules covering the OWASP Top 10 baseline","Set DefaultAction to Block for defence-in-depth","Enable CloudWatchMetricsEnabled in VisibilityConfig"],resourceTypes:["AWS::WAFv2::WebACL"]},"cross-resource-misconfiguration":{ruleId:"cross-resource-misconfiguration",checkKey:"crossResourceRelationships",name:"Cross-Resource Misconfiguration",description:"Detects misconfigurations only visible across multiple resources: Lambda functions referencing VPC-only resources without VpcConfig, S3 replication without encryption configuration, and security groups exposing non-standard ports to the public when used by sensitive services.",severity:"HIGH",wafPillar:"Security",awsDocUrl:"https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/welcome.html",complianceFrameworks:["SOC2","HIPAA","PCI-DSS","NIST"],remediationSteps:["Configure VpcConfig on Lambda functions that reach VPC-only resources (RDS, ElastiCache, Redshift, OpenSearch, ECS Service)","Specify EncryptionConfiguration on S3 replication rules so replicated objects retain encryption at the destination","Restrict 0.0.0.0/0 ingress on non-standard ports for security groups attached to sensitive services"],resourceTypes:["AWS::Lambda::Function","AWS::S3::Bucket","AWS::EC2::SecurityGroup","AWS::RDS::DBInstance","AWS::ElastiCache::CacheCluster","AWS::Redshift::Cluster","AWS::OpenSearchService::Domain","AWS::Elasticsearch::Domain","AWS::ECS::Service"]},"stack-architecture-recommendations":{ruleId:"stack-architecture-recommendations",checkKey:"stackArchitecture",name:"Stack Architecture Recommendations",description:"Detects architectural omissions across the stack: missing CloudWatch Alarms on critical resources, Lambda functions without X-Ray tracing, public-facing resources without WAF, RDS databases without Secrets Manager rotation, and excessive NAT Gateway usage.",severity:"MEDIUM",wafPillar:"Operational Excellence",awsDocUrl:"https://docs.aws.amazon.com/wellarchitected/latest/framework/welcome.html",remediationSteps:["Add CloudWatch Alarms on key metrics (Lambda errors, ECS task failures, RDS connections)","Enable X-Ray tracing on Lambda functions for distributed-request visibility","Associate AWS WAF with public-facing API Gateway, ALB, or CloudFront distributions","Use Secrets Manager with automatic rotation for RDS database credentials","Audit NAT Gateway count and consider VPC endpoints or NAT instances for cost reduction"],resourceTypes:["AWS::Lambda::Function","AWS::ApiGateway::RestApi","AWS::ApiGatewayV2::Api","AWS::ElasticLoadBalancingV2::LoadBalancer","AWS::CloudFront::Distribution","AWS::RDS::DBInstance","AWS::EC2::NatGateway","AWS::CloudWatch::Alarm"]}}});var hX,gX,IEe,yX,xX,bX,SX,rS,vX,iS=D(()=>{"use strict";w3();sS();Qa();I3();dm();dt();hX=(()=>{let t=new Map;for(let e of Object.values(fl))e.checkKey&&e.ruleId&&t.set(e.checkKey,e.ruleId);return t})(),gX={IAM:["AWS::IAM::"],S3:["AWS::S3::"],Lambda:["AWS::Lambda::"],DynamoDB:["AWS::DynamoDB::"],RDS:["AWS::RDS::"],EC2:["AWS::EC2::"],SNS:["AWS::SNS::"],SQS:["AWS::SQS::"],StepFunctions:["AWS::StepFunctions::"],CloudTrail:["AWS::CloudTrail::"],ApiGateway:["AWS::ApiGateway::","AWS::ApiGatewayV2::"],SecretsManager:["AWS::SecretsManager::"],KMS:["AWS::KMS::"],EventBridge:["AWS::Events::"],CloudFront:["AWS::CloudFront::"],ELB:["AWS::ElasticLoadBalancing::","AWS::ElasticLoadBalancingV2::"],ECS:["AWS::ECS::"],Cognito:["AWS::Cognito::"],WAF:["AWS::WAFv2::","AWS::WAF::"],CloudWatch:["AWS::CloudWatch::","AWS::Logs::"],Route53:["AWS::Route53::"],ElastiCache:["AWS::ElastiCache::"],ECR:["AWS::ECR::"],OpenSearch:["AWS::OpenSearchService::","AWS::Elasticsearch::"],ACM:["AWS::CertificateManager::"],Backup:["AWS::Backup::"],VPC:["AWS::EC2::VPC","AWS::EC2::FlowLog","AWS::EC2::SecurityGroup"],Kinesis:["AWS::Kinesis::"],AppSync:["AWS::AppSync::"],EKS:["AWS::EKS::"],Redshift:["AWS::Redshift::"],MSK:["AWS::MSK::"],Glue:["AWS::Glue::"],EFS:["AWS::EFS::"],AutoScaling:["AWS::AutoScaling::"]},IEe=dl({ttl:3e5,maxSize:100}),yX=E3(A3,{ttl:6e5,maxSize:10}),xX=t=>{if(t.includes("All services")||t.length===0)return s=>!s.Type.startsWith("AWS::CDK::");let e=[];for(let s of t){if(s==="All services")continue;let n=gX[s];n&&e.push(...n)}return e.length===0?s=>!s.Type.startsWith("AWS::CDK::"):s=>!s.Type.startsWith("AWS::CDK::")&&e.some(n=>s.Type.startsWith(n))},bX=t=>{let e=new Map,s={CRITICAL:4,HIGH:3,MEDIUM:2,LOW:1};for(let n of t){let r=n.issue,i=e.get(r);i?s[n.severity]>s[i.severity]&&e.set(r,n):e.set(r,n)}return Array.from(e.values())},SX=(t,e,s,n)=>{let r={CRITICAL:0,HIGH:0,MEDIUM:0,LOW:0},i={},o=0;for(let a of Object.values(t))for(let c of a.issues){o++,r[c.severity]++;let u=c.ruleId?Tu(c.ruleId)??"Other":"Other";i[u]=(i[u]||0)+1}return{totalResources:e,analyzedResources:Object.keys(t).length,totalFindings:o,findingsBySeverity:r,findingsByService:i,analysisTimeMs:Date.now()-n,servicesAnalyzed:s}},rS=(t,e,s=[],n={},r=[],i)=>vX(t,e,{selectedServices:s,solutionsRegistry:n,deduplicateFindings:!0,includeStatistics:!1,customRules:r,ruleContext:i}).findings,vX=(t,e,s={})=>{let n=Date.now(),{selectedServices:r=[],solutionsRegistry:i={},deduplicateFindings:o=!0,customRules:a=[],ruleContext:c}=s,u=yX(),l=new Set(["solutionsPatterns","stackArchitecture","crossResourceRelationships"]),d=Object.keys(u).filter(w=>!l.has(w)),{services:p}=Hp(r),f=hk(p,d),m={},g=xX(p),h=Object.keys(t.Resources||{}).length,y=Object.entries(t.Resources||{}).filter(([,w])=>g(w)).reduce((w,[N,L])=>(w[N]=L,w),{}),b=[];for(let w of f)try{let N=u[w];if(typeof N!="function"){let H=Tu(w)??w;et.warn(`\u26A0\uFE0F Service check function for ${H} (${w}) is not available`);continue}let L=N({Resources:y},e,c);b.push(w);let R=hX.get(w);for(let[H,B]of Object.entries(L)){if(m[H]||(m[H]={issues:[]}),R)for(let S of B.issues)S.ruleId||(S.ruleId=R);m[H].issues.push(...B.issues)}}catch(N){let L=Tu(w)??w;et.warn(`\u26A0\uFE0F Error in ${L} analysis (${w})`,{error:N instanceof Error?N.message:String(N)})}if(Object.keys(i).length>0)try{let w=u.solutionsPatterns({Resources:y},i);for(let N of w){let L=N.resourceId;m[L]||(m[L]={issues:[]}),m[L].issues.push(N)}}catch(w){et.warn("\u26A0\uFE0F Error in solutions pattern analysis",{error:w instanceof Error?w.message:String(w)})}if(a.length>0)try{let w=R3(t,a,e);for(let[N,L]of Object.entries(w))m[N]||(m[N]={issues:[]}),m[N].issues.push(...L.issues);et.info(`Custom rules evaluated: ${a.length} rule(s)`)}catch(w){et.warn("\u26A0\uFE0F Error evaluating custom rules",{error:w instanceof Error?w.message:String(w)})}if(o)for(let w of Object.keys(m))m[w].issues=bX(m[w].issues);Object.keys(m).length===0&&et.info(`\x1B[32m\u2705 No security or cost issues detected!\x1B[0m
|
|
162
162
|
`);let C=[...new Set(b.map(w=>Tu(w)).filter(w=>w!==void 0))],A=SX(m,h,C,n);return{findings:m,statistics:A}}});var oS,CX,pm,aS=D(()=>{"use strict";oS=t=>typeof t=="object"&&t!==null&&!Array.isArray(t),CX=t=>{if(!oS(t))return null;let e=t["Fn::GetStackOutput"];if(!oS(e))return null;let s=e.StackName,n=e.OutputName;if(typeof s!="string"||typeof n!="string")return null;let r=typeof e.Region=="string"?e.Region:void 0;return{stackName:s,outputName:n,region:r}},pm=t=>{let e=[],s=n=>{let r=CX(n);if(r){e.push(r);return}if(Array.isArray(n)){for(let i of n)s(i);return}if(oS(n))for(let i of Object.values(n))s(i)};return s(t),e}});var DX,k3,_3=D(()=>{"use strict";DX=(t,e)=>{if(t===e)return 0;if(t.length===0)return e.length;if(e.length===0)return t.length;let s=Array.from({length:e.length+1},(r,i)=>i),n=new Array(e.length+1).fill(0);for(let r=1;r<=t.length;r++){n[0]=r;for(let i=1;i<=e.length;i++){let o=t.charCodeAt(r-1)===e.charCodeAt(i-1)?0:1;n[i]=Math.min(n[i-1]+1,s[i]+1,s[i-1]+o)}[s,n]=[n,s]}return s[e.length]},k3=(t,e,s=3)=>{let n=null,r=s+1;for(let i of e){let o=DX(t,i);o<r&&(r=o,n=i)}return n}});var F3,T3=D(()=>{"use strict";aS();_3();F3=(t,e,s)=>{let n={};if(!s)return n;let{outputsByStack:r}=s,i=t.Resources||{};for(let[o,a]of Object.entries(i)){let c=pm(a);if(c.length!==0)for(let u of c){let l=r.get(u.stackName);if(!l||l.has(u.outputName))continue;let d=a.Metadata?.["aws:cdk:path"]||o,p=u.region?` (region: ${u.region})`:"",f=k3(u.outputName,l),m=f&&f!==u.outputName?` Did you mean "${f}"?`:"";n[o]||(n[o]={issues:[]}),n[o].issues.push(e(o,`Fn::GetStackOutput references output "${u.outputName}" on stack "${u.stackName}"${p}, but no such output is declared by that stack in this CDK app.${m} Deploy will fail at resolution time with Outputs.NoSuchOutput.`,f?`Verify the output logical ID matches what the producer stack declares. The closest declared output on "${u.stackName}" is "${f}" \u2014 if that is the intended target, fix the reference. If the producer is deployed outside this app, this finding is a false positive and can be ignored.`:`Verify the output logical ID matches what the producer stack declares. If the producer is in this app, check its CfnOutput logical IDs against "${u.outputName}". If the producer is deployed outside this app, this finding is a false positive and can be ignored.`,"CRITICAL","Reliability",d,"cdkInsights"))}}return n}});var $s,P3,fm,Xn,st,Ke,_i,cs=D(()=>{"use strict";$s=t=>t?JSON.stringify(t).length:0,P3=t=>{if(!t||typeof t!="object")return 0;let s=t.Statement;return Array.isArray(s)?s.length:s&&typeof s=="object"?1:0},fm=(t,e)=>{if(!t)return null;if(typeof t=="string"&&e.has(t))return t;if(typeof t!="object")return null;let s=t;if("Ref"in s&&typeof s.Ref=="string"&&e.has(s.Ref))return s.Ref;if("Fn::GetAtt"in s){let n=s["Fn::GetAtt"];if(Array.isArray(n)&&typeof n[0]=="string"&&e.has(n[0]))return n[0];if(typeof n=="string"){let r=n.split(".")[0];if(e.has(r))return r}}return null},Xn=t=>{if(!t||typeof t!="object")return[];let s=t.Statement;return Array.isArray(s)?s:s&&typeof s=="object"?[s]:[]},st=(t,e)=>e<=0?0:t/e,Ke=t=>t<1024?`${t} bytes`:`${(t/1024).toFixed(1)}KB`,_i=t=>{let s=(t.Properties||{}).Policies;return Array.isArray(s)?s.map(n=>({name:n.PolicyName||"unnamed",document:n.PolicyDocument})):[]}});var Ge,L3,O3,M3,Kt=D(()=>{"use strict";cs();Ge=(t,e)=>Object.entries(t).filter(([,s])=>s.Type===e),L3=t=>{let e=new Set(Object.keys(t)),s=new Map;for(let[n,r]of Object.entries(t)){if(r.Type!=="AWS::Events::Rule")continue;let o=(r.Properties||{}).Targets;if(Array.isArray(o))for(let a of o){let c=a.DeadLetterConfig;if(!c?.Arn)continue;let u=fm(c.Arn,e);if(!u)continue;let l=s.get(u)||[];l.push(n),s.set(u,l)}}return s},O3=t=>{let e=new Map;for(let[s,n]of Object.entries(t)){if(n.Type!=="AWS::Events::Rule")continue;let r=n.Properties||{},i="default";typeof r.EventBusName=="string"?i=r.EventBusName:r.EventBusName&&typeof r.EventBusName=="object"&&(i=JSON.stringify(r.EventBusName));let o=e.get(i)||[];o.push(s),e.set(i,o)}return e},M3=(t,e,s)=>{let n=new Set(Object.keys(s)),r=e.Properties||{},i=r.SecurityGroupIngress||[],o=r.SecurityGroupEgress||[],a=Array.isArray(i)?i.length:0,c=Array.isArray(o)?o.length:0;for(let[,u]of Object.entries(s))u.Type==="AWS::EC2::SecurityGroupIngress"&&fm(u.Properties?.GroupId,n)===t&&a++,u.Type==="AWS::EC2::SecurityGroupEgress"&&fm(u.Properties?.GroupId,n)===t&&c++;return{inbound:a,outbound:c}}});var B3,N3,$3=D(()=>{"use strict";cs();Kt();B3=t=>{let e=t.Effect||"Allow",s=Array.isArray(t.Action)?[...t.Action].sort():typeof t.Action=="string"?[t.Action]:[],n=Array.isArray(t.Resource)?[...t.Resource].sort():typeof t.Resource=="string"?[t.Resource]:[];return`${e}|${s.join(",")}|${n.join(",")}`},N3=(t,e)=>{let s={},n=t.Resources||{},r=Ge(n,"AWS::IAM::Role"),i=Ge(n,"AWS::IAM::Policy");for(let[o,a]of r){let c=a.Metadata?.["aws:cdk:path"]||o,u=[],l=_i(a);for(let f of l){if(!f.document)continue;let m=Xn(f.document);for(let g of m)u.push({key:B3(g),source:`inline policy "${f.name}"`})}for(let[,f]of i){let m=f.Properties||{},g=m.Roles;if(!Array.isArray(g)||!g.some(A=>typeof A=="string"?A===o:A&&typeof A=="object"?A.Ref===o:!1))continue;let y=m.PolicyDocument;if(!y)continue;let b=Xn(y),C=m.PolicyName||"unnamed";for(let A of b)u.push({key:B3(A),source:`attached policy "${C}"`})}let d=new Map;for(let{key:f,source:m}of u){let g=d.get(f)||[];g.push(m),d.set(f,g)}let p=0;for(let[,f]of d)f.length>1&&(p+=f.length-1);p>0&&(s[o]||(s[o]={issues:[]}),s[o].issues.push(e(o,`IAM role has ${p} duplicate policy statement(s) across its inline and attached policies. Duplicate statements increase policy size without adding permissions.`,"Consolidate duplicate statements into a single policy. Review inline policies and attached AWS::IAM::Policy resources for overlapping Effect + Action + Resource combinations.","LOW","Security",c,"cdkInsights")))}return s}});var AX,W3,j3=D(()=>{"use strict";Kt();AX=t=>{for(let[,e]of Object.entries(t)){let s=e.Metadata?.["aws:cdk:path"];if(s&&/prod/i.test(s))return!0;if(e.Metadata){for(let n of Object.values(e.Metadata))if(typeof n=="string"&&/prod/i.test(n))return!0}}return!1},W3=(t,e)=>{let s={},n=t.Resources||{},r=AX(n),i=[...Ge(n,"AWS::DynamoDB::Table"),...Ge(n,"AWS::DynamoDB::GlobalTable")];for(let[o,a]of i)if(!((a.Properties||{}).PointInTimeRecoverySpecification?.PointInTimeRecoveryEnabled===!0)){let d=a.Metadata?.["aws:cdk:path"]||o,p=r?"HIGH":"MEDIUM",f=r?" This appears to be a production stack, making data recovery capabilities especially important.":"";s[o]||(s[o]={issues:[]}),s[o].issues.push(e(o,`DynamoDB table does not have Point-in-Time Recovery (PITR) enabled.${f} Without PITR, accidental data deletions or corruption cannot be recovered.`,"Enable PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled on this table to allow restoration to any point within the last 35 days.",p,"Reliability",d,"cdkInsights"))}return s}});var U3,H3=D(()=>{"use strict";Kt();U3=(t,e)=>{let s={},n=t.Resources||{},r=Ge(n,"AWS::Events::Rule");for(let[i,o]of r){let c=(o.Properties||{}).Targets;if(!Array.isArray(c))continue;let u=o.Metadata?.["aws:cdk:path"]||i,l=[];for(let d=0;d<c.length;d++)c[d].DeadLetterConfig||l.push(d);l.length>0&&(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`EventBridge rule has ${l.length} target(s) without a DeadLetterConfig. Failed invocations will be silently dropped after exhausting retries.`,"Configure a DeadLetterConfig with an SQS queue on each target to capture failed invocations for debugging and reprocessing.","MEDIUM","Reliability",u,"cdkInsights")))}return s}});var G3,z3=D(()=>{"use strict";Kt();G3=(t,e)=>{let s={},n=t.Resources||{},r=Ge(n,"AWS::Lambda::Function"),i=Ge(n,"AWS::Logs::LogGroup"),o=new Set;for(let[,a]of i){let c=a.Properties?.LogGroupName;typeof c=="string"&&o.add(c)}for(let[a,c]of r){let l=(c.Properties||{}).FunctionName;if(typeof l!="string")continue;let d=`/aws/lambda/${l}`;if(!o.has(d)){let p=c.Metadata?.["aws:cdk:path"]||a;s[a]||(s[a]={issues:[]}),s[a].issues.push(e(a,`Lambda function "${l}" does not have an explicit AWS::Logs::LogGroup resource. CloudWatch will auto-create a log group with no retention policy, leading to indefinite log retention and increased costs.`,"Define an explicit AWS::Logs::LogGroup with a RetentionInDays property for this Lambda function to control log retention and avoid unbounded storage costs.","LOW","Operational Excellence",p,"cdkInsights"))}}return s}});var wX,q3,K3=D(()=>{"use strict";aS();wX=new Set(["Custom::CrossRegionExportWriter","Custom::CrossRegionExportReader"]),q3=(t,e)=>{let s={},n=t.Resources||{},r=[];for(let[o,a]of Object.entries(n))wX.has(a.Type)&&r.push(o);if(r.length===0||!Object.values(n).some(o=>pm(o).length>0))return s;for(let o of r){let a=n[o],c=a.Metadata?.["aws:cdk:path"]||o;s[o]||(s[o]={issues:[]}),s[o].issues.push(e(o,`Stack contains both a legacy ${a.Type} (from the pre-2.253.0 \`crossRegionReferences\` SSM mechanism) and one or more \`Fn::GetStackOutput\` calls (the new cross-region path). Partial migrations leak SSM parameters and can fail subsequent deploys with \`ParameterAlreadyExists\` (see aws/aws-cdk#37845).`,"Finish the migration in one of two orderings: (1) deploy the new `Fn::GetStackOutput`-based code first, drift-check, then remove the old code paths in a follow-up deploy; or (2) revert to the old mechanism if your CDK toolchain is not consistently on 2.253.0+. Do not leave both forms coexisting across deploys.","HIGH","Reliability",c,"cdkInsights"))}return s}});var V3,Z3=D(()=>{"use strict";Kt();V3=(t,e)=>{let s={},n=t.Resources||{},r=L3(n);for(let[i,o]of r){let a=o.length;if(a<=10)continue;let u=n[i]?.Metadata?.["aws:cdk:path"]||i,l=a>15?"HIGH":"MEDIUM",d=a>15?`SQS queue is used as a shared DLQ by ${a} EventBridge rules. This many targets will cause CDK to auto-generate excessive per-target SQS policy statements, risking policy size limit breaches.`:`SQS queue is used as a shared DLQ by ${a} EventBridge rules. As more rules are added, CDK will auto-generate per-target SQS policy statements that may exceed the policy size limit.`;s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,d,"Use dedicated DLQs per rule group, or create a single consolidated SQS policy using Queue.fromQueueArn() to prevent CDK from auto-generating per-target policy statements.",l,"Reliability",u,"cdkInsights"))}return s}});var _c,ml,EX,RX,IX,kX,_X,Y3,J3,Q3=D(()=>{"use strict";_c=oe(require("node:fs")),ml=oe(require("node:path")),EX=["bin","lib","src"],RX=/["']?crossRegionReferences["']?\s*:\s*true/,IX=new Set([".ts",".tsx",".js",".jsx",".mts",".cts"]),kX=new Set(["node_modules","dist","build",".git","cdk.out",".cdk.staging","coverage",".next",".turbo"]),_X=t=>{try{let s=_c.readFileSync(t,"utf-8").split(`
|
|
163
163
|
`);for(let n=0;n<s.length;n++){let r=RX.exec(s[n]);if(r)return{filePath:t,line:n+1,excerpt:r[0]}}}catch{}return null},Y3=t=>{let e;try{e=_c.readdirSync(t,{withFileTypes:!0})}catch{return null}for(let s of e){if(s.name.startsWith(".")||kX.has(s.name))continue;let n=ml.join(t,s.name);if(s.isDirectory()){let r=Y3(n);if(r)return r}else if(s.isFile()){let r=ml.extname(s.name);if(!IX.has(r))continue;let i=_X(n);if(i)return i}}return null},J3=(t,e=EX)=>{for(let s of e){let n=ml.join(t,s);if(!_c.existsSync(n))continue;let r=Y3(n);if(r)return r}return null}});var cS,X3,eM,tM=D(()=>{"use strict";rl();Q3();cS="2.253.0",X3=!1,eM=(t,e)=>{if(X3)return{};let{version:s}=qr();if(!s)return{};if(ea(s,cS)<0)return{};let n=J3(process.cwd());if(!n)return{};X3=!0;let r=n.filePath.startsWith(process.cwd())?n.filePath.slice(process.cwd().length+1):n.filePath;return{Global:{issues:[e("Global",`Stack prop \`crossRegionReferences: true\` is set in \`${r}:${n.line}\` but your aws-cdk-lib is ${s} (>= ${cS}). This flag is a no-op on this version \u2014 CDK now takes the \`Fn::GetStackOutput\` path unconditionally for cross-region references (aws/aws-cdk#37724) and the legacy SSM-custom-resource path it used to enable has been removed.`,`Remove the \`crossRegionReferences: true\` Stack prop. Cross-region references work out of the box on aws-cdk-lib >= ${cS}. If you have legacy \`Custom::CrossRegionExportWriter\` / \`Reader\` resources in deployed stacks, see TL-XRES-007 for the migration ordering.`,"LOW","Operational Excellence","Global","cdkInsights")]}}}});var sM,nM=D(()=>{"use strict";sM=(t,e)=>{let s={},n=t.Resources||{},r=new Set,i,o,a=0;for(let[u,l]of Object.entries(n))(l.__appliedMixins??[]).some(f=>f.isCustom)&&(r.add(l.Type),a++,i||(i=u,o=l.Metadata?.["aws:cdk:path"]||u));if(r.size<3||!i)return s;let c=Array.from(r).sort().join(", ");return s[i]={issues:[]},s[i].issues.push(e(i,`A user-defined CDK Mixin appears on ${a} resources across ${r.size} distinct CFN types in this stack (${c}). This is the template-visible signature of \`.with(customMixin)\` recursing through every descendant via \`target.node.findAll()\` \u2014 likely because the custom mixin's \`supports()\` filter accepts every construct.`,"Verify your custom mixin's `supports()` method narrows correctly to the intended resource type(s). If the broad application is intentional, you can suppress this finding via `Validations.of(scope).acknowledge({ id: 'cdk-insights::TL-MIXIN-002', reason: '...' })`.","LOW","Operational Excellence",o??i,"cdkInsights")),s}});var rM,iM=D(()=>{"use strict";rM=[{fqn:"aws-cdk-lib.aws_s3.mixins.BucketVersioning",cfnResourceType:"AWS::S3::Bucket",displayName:"BucketVersioning"},{fqn:"aws-cdk-lib.aws_s3.mixins.BucketEncryption",cfnResourceType:"AWS::S3::Bucket",displayName:"BucketEncryption"},{fqn:"aws-cdk-lib.aws_s3.mixins.BucketBlockPublicAccess",cfnResourceType:"AWS::S3::Bucket",displayName:"BucketBlockPublicAccess"}]});var oM,aM=D(()=>{"use strict";Kt();iM();oM=(t,e)=>{let s={},n=t.Resources||{};for(let r of rM){let i=Ge(n,r.cfnResourceType);if(i.length<2)continue;let o=[],a=[];for(let[c,u]of i)(u.__appliedMixins??[]).some(p=>p.fqn===r.fqn)?o.push(c):a.push([c,u]);if(!(o.length===0||a.length===0))for(let[c,u]of a){let l=u.Metadata?.["aws:cdk:path"]||c;s[c]||(s[c]={issues:[]}),s[c].issues.push(e(c,`CDK Mixin \`${r.displayName}\` is applied to ${o.length}/${i.length} ${r.cfnResourceType} resources in this stack but missing from this one. This is the signature of \`Mixins.of(scope).apply(...)\` silently skipping resources outside the selector.`,`Either apply \`${r.displayName}\` to this resource explicitly via \`.with()\`, or switch the stack-wide application to \`Mixins.of(scope).requireAll().apply(new ${r.displayName}())\` so synth fails when the mixin can't be applied to a selected construct.`,"LOW","Security",l,"cdkInsights"))}}return s}});var FX,TX,PX,cM,uM=D(()=>{"use strict";cs();Kt();FX=new Set(["aws:SourceArn","aws:SourceAccount","aws:PrincipalOrgID","aws:SourceVpce"]),TX=t=>{if(t==="*")return!0;if(t&&typeof t=="object"&&!Array.isArray(t)){let e=t,s=e.AWS;if(s==="*"||Array.isArray(s)&&s.includes("*")||e.Service==="*")return!0}return!1},PX=t=>{if(!t||typeof t!="object")return!1;let e=t;for(let s of Object.values(e))if(s&&typeof s=="object"){let n=s;for(let r of Object.keys(n))if(FX.has(r))return!0}return!1},cM=(t,e)=>{let s={},n=t.Resources||{},r=[];for(let[i,o]of Ge(n,"AWS::SQS::QueuePolicy")){let a=o.Metadata?.["aws:cdk:path"]||i;r.push([i,o.Properties?.PolicyDocument,a])}for(let[i,o]of Ge(n,"AWS::SNS::TopicPolicy")){let a=o.Metadata?.["aws:cdk:path"]||i;r.push([i,o.Properties?.PolicyDocument,a])}for(let[i,o]of Ge(n,"AWS::S3::BucketPolicy")){let a=o.Metadata?.["aws:cdk:path"]||i;r.push([i,o.Properties?.PolicyDocument,a])}for(let[i,o]of Ge(n,"AWS::KMS::Key")){let a=o.Metadata?.["aws:cdk:path"]||i;r.push([i,o.Properties?.KeyPolicy,a])}for(let[i,o,a]of r){if(!o)continue;let c=Xn(o);for(let u of c){if((u.Effect||"Allow")!=="Allow"||!TX(u.Principal))continue;let d=u.Condition,p=d!=null;p&&PX(d)||(p?(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,'Resource policy has a statement with Principal: "*" and a Condition that does not use a strongly restrictive key (aws:SourceArn, aws:SourceAccount, aws:PrincipalOrgID, or aws:SourceVpce). The current condition may not sufficiently limit access.',"Replace or supplement the existing Condition with aws:SourceArn, aws:SourceAccount, aws:PrincipalOrgID, or aws:SourceVpce to ensure only trusted sources can access this resource.","MEDIUM","Security",a,"cdkInsights"))):(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,'Resource policy has a statement with Principal: "*" and no Condition. This allows any AWS account or anonymous user to invoke the allowed actions.',"Add a restrictive Condition using aws:SourceArn, aws:SourceAccount, aws:PrincipalOrgID, or aws:SourceVpce to limit access to trusted sources.","HIGH","Security",a,"cdkInsights"))))}}return s}});var LX,OX,lM,dM=D(()=>{"use strict";cs();Kt();LX=[{pattern:/^arn:aws[a-z-]*:iam::aws:policy\/service-role\/AWSLambdaBasicExecutionRole$/,name:"AWSLambdaBasicExecutionRole",actions:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"]},{pattern:/^arn:aws[a-z-]*:iam::aws:policy\/service-role\/AWSLambdaVPCAccessExecutionRole$/,name:"AWSLambdaVPCAccessExecutionRole",actions:["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents","ec2:CreateNetworkInterface","ec2:DescribeNetworkInterfaces","ec2:DeleteNetworkInterface"]},{pattern:/^arn:aws[a-z-]*:iam::aws:policy\/AmazonDynamoDBReadOnlyAccess$/,name:"AmazonDynamoDBReadOnlyAccess",actions:["dynamodb:BatchGetItem","dynamodb:GetItem","dynamodb:Query","dynamodb:Scan","dynamodb:DescribeTable","dynamodb:DescribeReservedCapacity","dynamodb:DescribeReservedCapacityOfferings","dynamodb:ListTables","dynamodb:DescribeStream","dynamodb:ListStreams"]},{pattern:/^arn:aws[a-z-]*:iam::aws:policy\/AmazonDynamoDBFullAccess$/,name:"AmazonDynamoDBFullAccess",actions:["dynamodb:*"]},{pattern:/^arn:aws[a-z-]*:iam::aws:policy\/AmazonS3ReadOnlyAccess$/,name:"AmazonS3ReadOnlyAccess",actions:["s3:Get*","s3:List*"]},{pattern:/^arn:aws[a-z-]*:iam::aws:policy\/AmazonS3FullAccess$/,name:"AmazonS3FullAccess",actions:["s3:*"]},{pattern:/^arn:aws[a-z-]*:iam::aws:policy\/AmazonSQSFullAccess$/,name:"AmazonSQSFullAccess",actions:["sqs:*"]},{pattern:/^arn:aws[a-z-]*:iam::aws:policy\/AmazonSNSFullAccess$/,name:"AmazonSNSFullAccess",actions:["sns:*"]},{pattern:/^arn:aws[a-z-]*:iam::aws:policy\/CloudWatchFullAccess$/,name:"CloudWatchFullAccess",actions:["cloudwatch:*","logs:*"]},{pattern:/^arn:aws[a-z-]*:iam::aws:policy\/AWSStepFunctionsFullAccess$/,name:"AWSStepFunctionsFullAccess",actions:["states:*"]}],OX=(t,e)=>{if(t===e)return!0;let s=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${s}$`,"i").test(t)},lM=(t,e)=>{let s={},n=t.Resources||{},r=Ge(n,"AWS::IAM::Role");for(let[i,o]of r){let c=(o.Properties||{}).ManagedPolicyArns;if(!Array.isArray(c)||c.length===0)continue;let u=[];for(let m of c)if(typeof m=="string"){for(let g of LX)if(g.pattern.test(m))for(let h of g.actions)u.push({action:h,policyName:g.name})}if(u.length===0)continue;let l=_i(o),d=[];for(let m of l){if(!m.document)continue;let g=Xn(m.document);for(let h of g){if((h.Effect||"Allow")!=="Allow")continue;let b=Array.isArray(h.Action)?h.Action:typeof h.Action=="string"?[h.Action]:[];for(let C of b)for(let A of u)if(OX(C,A.action)){d.push({action:C,policyName:A.policyName,inlinePolicy:m.name});break}}}if(d.length===0)continue;let p=o.Metadata?.["aws:cdk:path"]||i,f=[...new Set(d.map(m=>m.policyName))];s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`IAM role has ${d.length} inline action(s) that overlap with permissions already granted by managed policy(ies): ${f.join(", ")}. Redundant inline statements increase policy size without adding permissions.`,"Remove redundant inline policy statements that are already covered by attached managed policies. Review the managed policy permissions before adding inline actions.","LOW","Security",p,"cdkInsights"))}return s}});var MX,BX,NX,$X,pM,fM=D(()=>{"use strict";cs();Kt();MX="cloudformation:DescribeStacks",BX=(t,e)=>typeof t=="string"?t===e||t==="*":Array.isArray(t)?t.some(s=>typeof s=="string"&&(s===e||s==="*")):!1,NX=t=>!!(t==="*"||Array.isArray(t)&&t.includes("*")),$X=t=>{let e=t.Properties?.Policies;return Array.isArray(e)?e.map(s=>s&&typeof s=="object"?s.PolicyDocument:void 0).filter(s=>s!==void 0):[]},pM=(t,e)=>{let s={},n=t.Resources||{},r=[];for(let[i,o]of Ge(n,"AWS::IAM::Policy")){let a=o.Metadata?.["aws:cdk:path"]||i,c=o.Properties?.PolicyDocument;c&&r.push([i,c,a])}for(let[i,o]of Ge(n,"AWS::IAM::ManagedPolicy")){let a=o.Metadata?.["aws:cdk:path"]||i,c=o.Properties?.PolicyDocument;c&&r.push([i,c,a])}for(let[i,o]of Ge(n,"AWS::IAM::Role")){let a=o.Metadata?.["aws:cdk:path"]||i;for(let c of $X(o))r.push([i,c,a])}for(let[i,o,a]of r)for(let c of Xn(o))(c.Effect||"Allow")==="Allow"&&BX(c.Action,MX)&&NX(c.Resource)&&(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,'IAM policy grants `cloudformation:DescribeStacks` with `Resource: "*"`. This is the permission CDK 2.253.0\'s auto-generated cross-account `Fn::GetStackOutput` flow grants \u2014 but CDK scopes it to a specific producer stack ARN. A wildcard here lets the holder enumerate every stack in the account, including ones the consumer never references.','Replace `Resource: "*"` with the specific producer stack ARN, e.g. `arn:aws:cloudformation:<region>:<account>:stack/<producer-stack-name>/*`. If you are not using `Fn::GetStackOutput` and this permission is for something else, scope it to the stacks the role actually needs to describe.',"MEDIUM","Security",a,"cdkInsights")));return s}});var WX,jX,mM,hM=D(()=>{"use strict";cs();Kt();WX=t=>{let e=t.Effect||"Allow",s=JSON.stringify(t.Principal||"*"),n=JSON.stringify(t.Condition||null);return`${e}|${s}|${n}`},jX=t=>{let e=t.Action;return Array.isArray(e)?e:typeof e=="string"?[e]:[]},mM=(t,e)=>{let s={},n=t.Resources||{},r=[...Ge(n,"AWS::SQS::QueuePolicy"),...Ge(n,"AWS::SNS::TopicPolicy")];for(let[i,o]of r){let c=(o.Properties||{}).PolicyDocument;if(!c)continue;let u=Xn(c);if(u.length<=2)continue;let l=o.Metadata?.["aws:cdk:path"]||i,d=new Map;for(let h=0;h<u.length;h++){let y=WX(u[h]),b=jX(u[h]),C=d.get(y)||[];C.push({actions:b,index:h}),d.set(y,C)}let p=0;for(let[,h]of d)h.length>1&&(p+=h.length-1);if(p<=0||p<2)continue;let f=u.length,g=p/f>.5?"MEDIUM":"LOW";s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`Policy has ${f} statements, of which ${p} could be consolidated. Multiple statements share the same Effect, Principal, and Condition but differ only in Action values.`,"Consolidate statements that share the same Effect, Principal, and Condition into a single statement with an Action array. This reduces policy size and improves readability.",g,"Reliability",l,"cdkInsights"))}return s}});var gM,yM=D(()=>{"use strict";gM={"2.251.0":[{resourceType:"AWS::ElasticLoadBalancing::LoadBalancer",removedAttributes:["SourceSecurityGroup"],removedTypes:["PolicyItem","SourceSecurityGroup"],releaseUrl:"https://github.com/aws/aws-cdk/releases/tag/v2.251.0",notes:"Verified 2026-05-03 against release v2.251.0 (commit 9e6c2ef). Classic ELB v1 only. The removed names are GetAtt return attribute and authoring-time jsii types \u2014 synthesized CFN property shape is unchanged, and no CFN property additions affect covered resource types."}]}});var UX,HX,xM,bM,SM,vM=D(()=>{"use strict";yM();rl();dm();UX=(t,e)=>{let s=[];for(let[n,r]of Object.entries(e))if(!(ea(n,t)>0))for(let i of r)s.push({...i,introducedIn:n});return s},HX=(t,e)=>Object.values(e).filter(s=>s.resourceTypes.includes(t)).map(s=>s.ruleId),xM=(t,e,s,n="regression",r=gM,i=fl)=>{let o={};if(!s)return o;let a=UX(s,r);if(a.length===0)return o;let c=new Map;for(let[u,l]of Object.entries(t.Resources??{})){let d=c.get(l.Type)??[];d.push(u),c.set(l.Type,d)}for(let u of a){let l=c.get(u.resourceType);if(!l||l.length===0)continue;let d=HX(u.resourceType,i);if(d.length!==0)if(n==="regression"){let p=u.removedProperties??[],f=u.renamedProperties??[];if(p.length===0&&f.length===0)continue;let m=[...p.map(g=>`removed property "${g}"`),...f.map(g=>`renamed "${g.from}" \u2192 "${g.to}"`)].join(", ");for(let g of l)o[g]||(o[g]={issues:[]}),o[g].issues.push(e(g,`aws-cdk-lib v${u.introducedIn} regenerated the L1 schema for ${u.resourceType} (${m}). Existing cdk-insights rule(s) [${d.join(", ")}] may have silently lost coverage.`,`Verify rule coverage against the current schema. Release notes: ${u.releaseUrl}`,"LOW","Operational Excellence",g,"cdkInsights"))}else{let p=u.addedProperties??[];if(p.length===0)continue;let f=p.map(m=>`"${m}"`).join(", ");for(let m of l)o[m]||(o[m]={issues:[]}),o[m].issues.push(e(m,`aws-cdk-lib v${u.introducedIn} added new propert${p.length===1?"y":"ies"} ${f} to ${u.resourceType}. Existing cdk-insights rule(s) [${d.join(", ")}] don't evaluate ${p.length===1?"it":"them"} \u2014 consider whether a rule should.`,`Review the new propert${p.length===1?"y":"ies"} for security, cost, or compliance implications. Release notes: ${u.releaseUrl}`,"LOW","Operational Excellence",m,"cdkInsights"))}}return o},bM=(t,e)=>{let{version:s}=qr();return xM(t,e,s,"regression")},SM=(t,e)=>{let{version:s}=qr();return xM(t,e,s,"coverage-gap")}});var xe,wt,Ws=D(()=>{"use strict";xe={SQS_POLICY_MAX_BYTES:8192,SQS_POLICY_MAX_STATEMENTS:20,IAM_INLINE_POLICY_MAX_BYTES:2048,IAM_MANAGED_POLICY_MAX_BYTES:6144,IAM_ROLE_AGGREGATE_INLINE_MAX_BYTES:10240,LAMBDA_ENV_MAX_BYTES:4096,LAMBDA_MAX_LAYERS:5,S3_BUCKET_POLICY_MAX_BYTES:20480,SNS_TOPIC_POLICY_MAX_BYTES:30720,EVENTBRIDGE_RULES_PER_BUS_DEFAULT:300,CFN_MAX_RESOURCES:500,CFN_TEMPLATE_MAX_BYTES_DIRECT:51200,CFN_TEMPLATE_MAX_BYTES_S3:460800,SECURITY_GROUP_MAX_INBOUND_RULES:60,SECURITY_GROUP_MAX_OUTBOUND_RULES:60},wt=.8});var CM,DM=D(()=>{"use strict";cs();Ws();CM=(t,e)=>{let s={},n=Object.keys(t.Resources||{}).length,r="__TEMPLATE_LEVEL__";return n>=xe.CFN_MAX_RESOURCES?(s[r]||(s[r]={issues:[]}),s[r].issues.push(e(r,`CloudFormation template contains ${n} resources, reaching or exceeding the ${xe.CFN_MAX_RESOURCES}-resource limit. Deployment will fail.`,"Split the stack into multiple nested stacks or separate stacks to stay within the CloudFormation resource limit.","CRITICAL","Reliability","__TEMPLATE_LEVEL__","cdkInsights"))):st(n,xe.CFN_MAX_RESOURCES)>=wt&&(s[r]||(s[r]={issues:[]}),s[r].issues.push(e(r,`CloudFormation template contains ${n} resources (${Math.round(st(n,xe.CFN_MAX_RESOURCES)*100)}% of the ${xe.CFN_MAX_RESOURCES}-resource limit).`,"Consider splitting the stack into multiple nested stacks or separate stacks before this limit is reached.","HIGH","Reliability","__TEMPLATE_LEVEL__","cdkInsights"))),s}});var AM,wM=D(()=>{"use strict";cs();Ws();AM=(t,e)=>{let s={},n=JSON.stringify(t).length,r="__TEMPLATE_LEVEL__";return n>=xe.CFN_TEMPLATE_MAX_BYTES_S3?(s[r]||(s[r]={issues:[]}),s[r].issues.push(e(r,`CloudFormation template is ${Ke(n)}, exceeding the ${Ke(xe.CFN_TEMPLATE_MAX_BYTES_S3)} S3 upload limit. Deployment will fail regardless of deployment method.`,"Split the stack into multiple nested stacks or separate stacks to reduce template size.","CRITICAL","Reliability","__TEMPLATE_LEVEL__","cdkInsights"))):st(n,xe.CFN_TEMPLATE_MAX_BYTES_S3)>=wt&&(s[r]||(s[r]={issues:[]}),s[r].issues.push(e(r,`CloudFormation template is ${Ke(n)} (${Math.round(st(n,xe.CFN_TEMPLATE_MAX_BYTES_S3)*100)}% of the ${Ke(xe.CFN_TEMPLATE_MAX_BYTES_S3)} S3 upload limit).`,"Consider splitting the stack into multiple nested stacks or separate stacks before this limit is reached.","MEDIUM","Reliability","__TEMPLATE_LEVEL__","cdkInsights"))),n>=xe.CFN_TEMPLATE_MAX_BYTES_DIRECT?(s[r]||(s[r]={issues:[]}),s[r].issues.push(e(r,`CloudFormation template is ${Ke(n)}, exceeding the ${Ke(xe.CFN_TEMPLATE_MAX_BYTES_DIRECT)} direct upload limit.`,"CDK uploads templates via S3 by default so this is informational. If deploying outside CDK with `aws cloudformation create-stack --template-body=...`, switch to `--template-url` or use S3.","LOW","Reliability","__TEMPLATE_LEVEL__","cdkInsights"))):st(n,xe.CFN_TEMPLATE_MAX_BYTES_DIRECT)>=wt&&(s[r]||(s[r]={issues:[]}),s[r].issues.push(e(r,`CloudFormation template is ${Ke(n)} (${Math.round(st(n,xe.CFN_TEMPLATE_MAX_BYTES_DIRECT)*100)}% of the ${Ke(xe.CFN_TEMPLATE_MAX_BYTES_DIRECT)} direct upload limit).`,"CDK uploads templates via S3 by default so this is informational. The S3-upload limit (450KB) is the one that actually applies to CDK deployments.","LOW","Reliability","__TEMPLATE_LEVEL__","cdkInsights"))),s}});var EM,RM=D(()=>{"use strict";cs();Kt();Ws();EM=(t,e)=>{let s={},n=t.Resources||{},r=O3(n);for(let[i,o]of r){let a=o.length,c=o[0],l=n[c]?.Metadata?.["aws:cdk:path"]||c;a>=xe.EVENTBRIDGE_RULES_PER_BUS_DEFAULT?(s[c]||(s[c]={issues:[]}),s[c].issues.push(e(c,`EventBridge bus "${i}" has ${a} rules, reaching or exceeding the ${xe.EVENTBRIDGE_RULES_PER_BUS_DEFAULT}-rule default limit. Deployment may fail.`,"Request a service quota increase for EventBridge rules per bus, or split rules across multiple event buses.","HIGH","Reliability",l,"cdkInsights"))):st(a,xe.EVENTBRIDGE_RULES_PER_BUS_DEFAULT)>=wt&&(s[c]||(s[c]={issues:[]}),s[c].issues.push(e(c,`EventBridge bus "${i}" has ${a} rules (${Math.round(st(a,xe.EVENTBRIDGE_RULES_PER_BUS_DEFAULT)*100)}% of the ${xe.EVENTBRIDGE_RULES_PER_BUS_DEFAULT}-rule default limit).`,"Consider requesting a service quota increase or splitting rules across multiple event buses before this limit is reached.","MEDIUM","Reliability",l,"cdkInsights")))}return s}});var IM,kM=D(()=>{"use strict";cs();Kt();Ws();IM=(t,e)=>{let s={},n=t.Resources||{},r=Ge(n,"AWS::IAM::Role"),i=Ge(n,"AWS::IAM::User");for(let[o,a]of[...r,...i]){let c=a.Metadata?.["aws:cdk:path"]||o,u=_i(a);for(let l of u){if(!l.document)continue;let d=$s(l.document);d>=xe.IAM_INLINE_POLICY_MAX_BYTES?(s[o]||(s[o]={issues:[]}),s[o].issues.push(e(o,`Inline policy "${l.name}" is ${Ke(d)}, exceeding the ${Ke(xe.IAM_INLINE_POLICY_MAX_BYTES)} limit. Deployment will fail.`,"Convert this inline policy to a managed policy, or reduce the number of statements and actions. Use wildcard patterns where appropriate to consolidate permissions.","CRITICAL","Reliability",c,"cdkInsights"))):st(d,xe.IAM_INLINE_POLICY_MAX_BYTES)>=wt&&(s[o]||(s[o]={issues:[]}),s[o].issues.push(e(o,`Inline policy "${l.name}" is ${Ke(d)} (${Math.round(st(d,xe.IAM_INLINE_POLICY_MAX_BYTES)*100)}% of the ${Ke(xe.IAM_INLINE_POLICY_MAX_BYTES)} limit). Adding more permissions may cause deployment failure.`,"Consider converting this inline policy to a managed policy before the limit is reached.","HIGH","Reliability",c,"cdkInsights")))}}return s}});var _M,FM=D(()=>{"use strict";cs();Kt();Ws();_M=(t,e)=>{let s={},n=t.Resources||{},r=Ge(n,"AWS::IAM::ManagedPolicy");for(let[i,o]of r){let c=(o.Properties||{}).PolicyDocument;if(!c)continue;let u=$s(c),l=o.Metadata?.["aws:cdk:path"]||i;u>=xe.IAM_MANAGED_POLICY_MAX_BYTES?(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`Managed policy is ${Ke(u)}, exceeding the ${Ke(xe.IAM_MANAGED_POLICY_MAX_BYTES)} limit. Deployment will fail.`,"Split this managed policy into multiple smaller policies, or consolidate statements using wildcard patterns to reduce size.","CRITICAL","Reliability",l,"cdkInsights"))):st(u,xe.IAM_MANAGED_POLICY_MAX_BYTES)>=wt&&(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`Managed policy is ${Ke(u)} (${Math.round(st(u,xe.IAM_MANAGED_POLICY_MAX_BYTES)*100)}% of the ${Ke(xe.IAM_MANAGED_POLICY_MAX_BYTES)} limit). Adding more permissions may cause deployment failure.`,"Consider splitting this managed policy into multiple policies before the limit is reached.","HIGH","Reliability",l,"cdkInsights")))}return s}});var TM,PM=D(()=>{"use strict";cs();Kt();Ws();TM=(t,e)=>{let s={},n=t.Resources||{},r=Ge(n,"AWS::IAM::Role");for(let[i,o]of r){let a=o.Metadata?.["aws:cdk:path"]||i,c=_i(o),u=0;for(let l of c)l.document&&(u+=$s(l.document));u!==0&&(u>=xe.IAM_ROLE_AGGREGATE_INLINE_MAX_BYTES?(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`Aggregate inline policy size is ${Ke(u)} across ${c.length} policies, exceeding the ${Ke(xe.IAM_ROLE_AGGREGATE_INLINE_MAX_BYTES)} limit. Deployment will fail.`,"Convert some inline policies to managed policies to reduce the aggregate inline size. Consider consolidating overlapping permissions across policies.","CRITICAL","Reliability",a,"cdkInsights"))):st(u,xe.IAM_ROLE_AGGREGATE_INLINE_MAX_BYTES)>=wt&&(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`Aggregate inline policy size is ${Ke(u)} across ${c.length} policies (${Math.round(st(u,xe.IAM_ROLE_AGGREGATE_INLINE_MAX_BYTES)*100)}% of the ${Ke(xe.IAM_ROLE_AGGREGATE_INLINE_MAX_BYTES)} limit). Adding more inline policies may cause deployment failure.`,"Consider converting some inline policies to managed policies before the aggregate limit is reached.","HIGH","Reliability",a,"cdkInsights"))))}return s}});var LM,OM=D(()=>{"use strict";cs();Kt();Ws();LM=(t,e)=>{let s={},n=t.Resources||{},r=Ge(n,"AWS::Lambda::Function");for(let[i,o]of r){let c=(o.Properties||{}).Environment;if(!c?.Variables)continue;let u=$s(c.Variables),l=o.Metadata?.["aws:cdk:path"]||i;u>=xe.LAMBDA_ENV_MAX_BYTES?(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`Lambda environment variables are ${Ke(u)}, exceeding the ${Ke(xe.LAMBDA_ENV_MAX_BYTES)} limit. Deployment will fail.`,"Move large configuration values to SSM Parameter Store or Secrets Manager. Use a single JSON-encoded parameter instead of many individual environment variables.","CRITICAL","Reliability",l,"cdkInsights"))):st(u,xe.LAMBDA_ENV_MAX_BYTES)>=wt&&(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`Lambda environment variables are ${Ke(u)} (${Math.round(st(u,xe.LAMBDA_ENV_MAX_BYTES)*100)}% of the ${Ke(xe.LAMBDA_ENV_MAX_BYTES)} limit). Adding more variables may cause deployment failure.`,"Consider moving some configuration values to SSM Parameter Store or Secrets Manager before the limit is reached.","HIGH","Reliability",l,"cdkInsights")))}return s}});var MM,BM=D(()=>{"use strict";Kt();Ws();MM=(t,e)=>{let s={},n=t.Resources||{},r=Ge(n,"AWS::Lambda::Function");for(let[i,o]of r){let c=(o.Properties||{}).Layers;if(!Array.isArray(c))continue;let u=c.length,l=o.Metadata?.["aws:cdk:path"]||i;u>xe.LAMBDA_MAX_LAYERS?(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`Lambda function has ${u} layers, exceeding the maximum of ${xe.LAMBDA_MAX_LAYERS} layers. Deployment will fail.`,"Consolidate layers by combining related dependencies into a single layer, or move some dependencies into the deployment package itself.","CRITICAL","Reliability",l,"cdkInsights"))):u===xe.LAMBDA_MAX_LAYERS&&(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`Lambda function has ${u} of ${xe.LAMBDA_MAX_LAYERS} maximum layers. There is no headroom to add additional layers.`,"Consider consolidating layers by combining related dependencies into a single layer to free up a layer slot for future needs.","HIGH","Reliability",l,"cdkInsights")))}return s}});var NM,$M=D(()=>{"use strict";cs();Kt();Ws();NM=(t,e)=>{let s={},n=t.Resources||{},r=Ge(n,"AWS::S3::BucketPolicy");for(let[i,o]of r){let c=(o.Properties||{}).PolicyDocument;if(!c)continue;let u=$s(c),l=o.Metadata?.["aws:cdk:path"]||i;u>=xe.S3_BUCKET_POLICY_MAX_BYTES?(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`S3 bucket policy is ${Ke(u)}, exceeding the ${Ke(xe.S3_BUCKET_POLICY_MAX_BYTES)} limit. Deployment will fail.`,"Consolidate policy statements or split resources across multiple buckets to reduce policy size.","CRITICAL","Reliability",l,"cdkInsights"))):st(u,xe.S3_BUCKET_POLICY_MAX_BYTES)>=wt&&(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`S3 bucket policy is ${Ke(u)} (${Math.round(st(u,xe.S3_BUCKET_POLICY_MAX_BYTES)*100)}% of the ${Ke(xe.S3_BUCKET_POLICY_MAX_BYTES)} limit). Adding more statements may cause deployment failure.`,"Consider consolidating policy statements or splitting resources across multiple buckets before this limit is reached.","HIGH","Reliability",l,"cdkInsights")))}return s}});var WM,jM=D(()=>{"use strict";cs();Kt();Ws();WM=(t,e)=>{let s={},n=t.Resources||{},r=Ge(n,"AWS::EC2::SecurityGroup");for(let[i,o]of r){let{inbound:a,outbound:c}=M3(i,o,n),u=o.Metadata?.["aws:cdk:path"]||i;a>=xe.SECURITY_GROUP_MAX_INBOUND_RULES?(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`Security group has ${a} inbound rules, reaching or exceeding the ${xe.SECURITY_GROUP_MAX_INBOUND_RULES}-rule limit. Deployment will fail.`,"Consolidate rules using CIDR ranges or prefix lists, or split workloads across multiple security groups.","CRITICAL","Reliability",u,"cdkInsights"))):st(a,xe.SECURITY_GROUP_MAX_INBOUND_RULES)>=wt&&(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`Security group has ${a} inbound rules (${Math.round(st(a,xe.SECURITY_GROUP_MAX_INBOUND_RULES)*100)}% of the ${xe.SECURITY_GROUP_MAX_INBOUND_RULES}-rule limit).`,"Consider consolidating rules using CIDR ranges or prefix lists before this limit is reached.","HIGH","Reliability",u,"cdkInsights"))),c>=xe.SECURITY_GROUP_MAX_OUTBOUND_RULES?(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`Security group has ${c} outbound rules, reaching or exceeding the ${xe.SECURITY_GROUP_MAX_OUTBOUND_RULES}-rule limit. Deployment will fail.`,"Consolidate rules using CIDR ranges or prefix lists, or split workloads across multiple security groups.","CRITICAL","Reliability",u,"cdkInsights"))):st(c,xe.SECURITY_GROUP_MAX_OUTBOUND_RULES)>=wt&&(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`Security group has ${c} outbound rules (${Math.round(st(c,xe.SECURITY_GROUP_MAX_OUTBOUND_RULES)*100)}% of the ${xe.SECURITY_GROUP_MAX_OUTBOUND_RULES}-rule limit).`,"Consider consolidating rules using CIDR ranges or prefix lists before this limit is reached.","HIGH","Reliability",u,"cdkInsights")))}return s}});var UM,HM=D(()=>{"use strict";cs();Kt();Ws();UM=(t,e)=>{let s={},n=t.Resources||{},r=Ge(n,"AWS::SNS::TopicPolicy");for(let[i,o]of r){let c=(o.Properties||{}).PolicyDocument;if(!c)continue;let u=$s(c),l=o.Metadata?.["aws:cdk:path"]||i;u>=xe.SNS_TOPIC_POLICY_MAX_BYTES?(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`SNS topic policy is ${Ke(u)}, exceeding the ${Ke(xe.SNS_TOPIC_POLICY_MAX_BYTES)} limit. Deployment will fail.`,"Consolidate policy statements or split subscriptions across multiple topics to reduce policy size.","CRITICAL","Reliability",l,"cdkInsights"))):st(u,xe.SNS_TOPIC_POLICY_MAX_BYTES)>=wt&&(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`SNS topic policy is ${Ke(u)} (${Math.round(st(u,xe.SNS_TOPIC_POLICY_MAX_BYTES)*100)}% of the ${Ke(xe.SNS_TOPIC_POLICY_MAX_BYTES)} limit). Adding more statements may cause deployment failure.`,"Consider consolidating policy statements or splitting subscriptions across multiple topics before this limit is reached.","HIGH","Reliability",l,"cdkInsights")))}return s}});var GM,zM=D(()=>{"use strict";cs();Kt();Ws();GM=(t,e)=>{let s={},n=t.Resources||{},r=Ge(n,"AWS::SQS::QueuePolicy");for(let[i,o]of r){let c=(o.Properties||{}).PolicyDocument;if(!c)continue;let u=$s(c),l=P3(c),d=o.Metadata?.["aws:cdk:path"]||i;u>=xe.SQS_POLICY_MAX_BYTES?(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`SQS queue policy is ${Ke(u)}, exceeding the ${Ke(xe.SQS_POLICY_MAX_BYTES)} limit. Deployment will fail.`,"Consolidate policy statements into a single statement with broader conditions, or split targets across multiple queues. If using a shared DLQ with EventBridge targets, use Queue.fromQueueArn() to prevent CDK from auto-generating per-target statements.","CRITICAL","Reliability",d,"cdkInsights"))):st(u,xe.SQS_POLICY_MAX_BYTES)>=wt&&(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`SQS queue policy is ${Ke(u)} (${Math.round(st(u,xe.SQS_POLICY_MAX_BYTES)*100)}% of the ${Ke(xe.SQS_POLICY_MAX_BYTES)} limit). Adding more targets may cause deployment failure.`,"Consider consolidating policy statements or splitting targets across multiple queues before this limit is reached.","HIGH","Reliability",d,"cdkInsights"))),l>=xe.SQS_POLICY_MAX_STATEMENTS?(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`SQS queue policy has ${l} statements, reaching or exceeding the ${xe.SQS_POLICY_MAX_STATEMENTS}-statement limit.`,"Consolidate statements using wildcard conditions or array-valued Action/Resource fields instead of one statement per target.","CRITICAL","Reliability",d,"cdkInsights"))):st(l,xe.SQS_POLICY_MAX_STATEMENTS)>=wt&&(s[i]||(s[i]={issues:[]}),s[i].issues.push(e(i,`SQS queue policy has ${l} of ${xe.SQS_POLICY_MAX_STATEMENTS} maximum statements (${Math.round(st(l,xe.SQS_POLICY_MAX_STATEMENTS)*100)}%).`,"Consider consolidating policy statements before this limit is reached.","HIGH","Reliability",d,"cdkInsights")))}return s}});var GX,uS,qM=D(()=>{"use strict";T3();$3();j3();H3();z3();K3();Z3();tM();nM();aM();uM();dM();fM();hM();vM();DM();wM();RM();kM();FM();PM();OM();BM();$M();jM();HM();zM();GX=[{ruleId:"TL-LIMIT-001",title:"SQS Queue Policy Size Limit",category:"serviceLimits",defaultSeverity:"CRITICAL",wafPillar:"Reliability",check:GM,description:"SQS queue policies must be under 8KB / 20 statements. Commonly exceeded when CDK auto-generates per-target policy statements for shared DLQs."},{ruleId:"TL-LIMIT-002",title:"IAM Inline Policy Size Limit",category:"serviceLimits",defaultSeverity:"CRITICAL",wafPillar:"Reliability",check:IM,description:"Each IAM inline policy must be under 2,048 bytes when URL-encoded."},{ruleId:"TL-LIMIT-003",title:"IAM Managed Policy Size Limit",category:"serviceLimits",defaultSeverity:"CRITICAL",wafPillar:"Reliability",check:_M,description:"IAM managed policies must be under 6,144 bytes."},{ruleId:"TL-LIMIT-004",title:"IAM Role Aggregate Inline Policy Size",category:"serviceLimits",defaultSeverity:"CRITICAL",wafPillar:"Reliability",check:TM,description:"Total size of all inline policies on a single IAM role must be under 10,240 bytes."},{ruleId:"TL-LIMIT-005",title:"Lambda Environment Variables Size Limit",category:"serviceLimits",defaultSeverity:"CRITICAL",wafPillar:"Reliability",check:LM,description:"Lambda environment variables must total under 4KB including keys and values."},{ruleId:"TL-LIMIT-006",title:"Lambda Layers Limit",category:"serviceLimits",defaultSeverity:"CRITICAL",wafPillar:"Reliability",check:MM,description:"Lambda functions can have a maximum of 5 layers."},{ruleId:"TL-LIMIT-007",title:"S3 Bucket Policy Size Limit",category:"serviceLimits",defaultSeverity:"CRITICAL",wafPillar:"Reliability",check:NM,description:"S3 bucket policies must be under 20KB."},{ruleId:"TL-LIMIT-008",title:"SNS Topic Policy Size Limit",category:"serviceLimits",defaultSeverity:"CRITICAL",wafPillar:"Reliability",check:UM,description:"SNS topic policies must be under 30KB."},{ruleId:"TL-LIMIT-009",title:"EventBridge Rules Per Bus Limit",category:"serviceLimits",defaultSeverity:"HIGH",wafPillar:"Reliability",check:EM,description:"Default quota is 300 EventBridge rules per event bus."},{ruleId:"TL-LIMIT-010",title:"CloudFormation Stack Resource Count",category:"serviceLimits",defaultSeverity:"CRITICAL",wafPillar:"Reliability",check:CM,description:"CloudFormation stacks have a hard limit of 500 resources."},{ruleId:"TL-LIMIT-011",title:"CloudFormation Template Size",category:"serviceLimits",defaultSeverity:"CRITICAL",wafPillar:"Reliability",check:AM,description:"CloudFormation templates have a 51KB limit (direct) or 460KB limit (S3)."},{ruleId:"TL-LIMIT-012",title:"Security Group Rules Limit",category:"serviceLimits",defaultSeverity:"CRITICAL",wafPillar:"Reliability",check:WM,description:"Security groups have a default limit of 60 inbound and 60 outbound rules."},{ruleId:"TL-XRES-001",title:"Shared DLQ with Too Many EventBridge Targets",category:"crossResourceAntiPatterns",defaultSeverity:"HIGH",wafPillar:"Reliability",check:V3,description:"CDK generates one SQS policy statement per EventBridge target. Too many targets sharing a DLQ causes the policy to exceed the 8KB limit."},{ruleId:"TL-XRES-002",title:"EventBridge Targets Without DLQ",category:"crossResourceAntiPatterns",defaultSeverity:"MEDIUM",wafPillar:"Reliability",check:U3,description:"EventBridge rule targets should have a Dead Letter Queue for failed event delivery."},{ruleId:"TL-XRES-003",title:"Lambda Without Explicit Log Group",category:"crossResourceAntiPatterns",defaultSeverity:"LOW",wafPillar:"Operational Excellence",check:G3,description:"Lambda functions without explicit CloudWatch Log Groups use auto-created groups with infinite retention."},{ruleId:"TL-XRES-004",title:"DynamoDB Without Point-in-Time Recovery",category:"crossResourceAntiPatterns",defaultSeverity:"MEDIUM",wafPillar:"Reliability",check:W3,description:"DynamoDB tables should have PITR enabled, especially in production stacks."},{ruleId:"TL-XRES-005",title:"Duplicate IAM Policy Statements",category:"crossResourceAntiPatterns",defaultSeverity:"LOW",wafPillar:"Security",check:N3,description:"Duplicate policy statements across a role waste policy size budget and may indicate copy-paste errors."},{ruleId:"TL-XRES-006",title:"Dangling Fn::GetStackOutput Reference",category:"crossResourceAntiPatterns",defaultSeverity:"CRITICAL",wafPillar:"Reliability",check:F3,description:"Fn::GetStackOutput (CDK >= 2.253.0) references a stack or output that does not exist in any sibling stack in the same CDK app. Deploy will fail at resolution time with Outputs.NoSuchOutput."},{ruleId:"TL-XRES-007",title:"Mixed Cross-Region Reference Migration State",category:"crossResourceAntiPatterns",defaultSeverity:"HIGH",wafPillar:"Reliability",check:q3,description:"Stack contains both the legacy SSM-custom-resource cross-region reference path (Custom::CrossRegionExportWriter / Reader) and the new Fn::GetStackOutput intrinsic. Partial migrations leak SSM parameters and can fail subsequent deploys with ParameterAlreadyExists (aws/aws-cdk#37845)."},{ruleId:"TL-XRES-008",title:"Stale crossRegionReferences Stack Prop",category:"crossResourceAntiPatterns",defaultSeverity:"LOW",wafPillar:"Operational Excellence",check:eM,description:"Stack prop `crossRegionReferences: true` is set in user source but aws-cdk-lib is >= 2.253.0, where the flag is a no-op \u2014 CDK takes the Fn::GetStackOutput path unconditionally. Advisory; remove the prop to reduce surprise on future readers."},{ruleId:"TL-POL-001",title:"Redundant SQS/SNS Policy Statements",category:"policyAnalysis",defaultSeverity:"MEDIUM",wafPillar:"Reliability",check:mM,description:"Policy statements that could be consolidated to reduce policy size."},{ruleId:"TL-POL-002",title:"IAM Overlapping Managed and Inline Policies",category:"policyAnalysis",defaultSeverity:"LOW",wafPillar:"Security",check:lM,description:"Inline policy statements that duplicate permissions from attached managed policies."},{ruleId:"TL-POL-003",title:"Overly Broad Resource Policy Principals",category:"policyAnalysis",defaultSeverity:"HIGH",wafPillar:"Security",check:cM,description:"Resource policies with wildcard (*) principals without restrictive conditions."},{ruleId:"TL-POL-004",title:"Over-Scoped cloudformation:DescribeStacks Permission",category:"policyAnalysis",defaultSeverity:"MEDIUM",wafPillar:"Security",check:pM,description:`IAM policy grants cloudformation:DescribeStacks with Resource: "*". CDK 2.253.0's auto-generated cross-account Fn::GetStackOutput flow scopes this permission to the specific producer stack ARN \u2014 a wildcard here is escape-hatch over-privilege and grants enumeration of every stack in the account.`},{ruleId:"TL-DRIFT-001",title:"CDK L1 Schema Drift",category:"schemaDrift",defaultSeverity:"LOW",wafPillar:"Operational Excellence",check:bM,description:"Detects when the user's aws-cdk-lib version regenerated an L1 CloudFormation resource schema in a way that may silently invalidate cdk-insights rule coverage."},{ruleId:"TL-DRIFT-002",title:"CDK L1 Schema Coverage Gap",category:"schemaDrift",defaultSeverity:"LOW",wafPillar:"Operational Excellence",check:SM,description:"Surfaces newly-added L1 CloudFormation properties on resource types already covered by cdk-insights rules. Hint that a new rule may be worth opening; not a regression."},{ruleId:"TL-MIXIN-001",title:"Compliance-Critical Mixin Applied Without Stack Coverage",category:"crossResourceAntiPatterns",defaultSeverity:"LOW",wafPillar:"Security",check:oM,description:"A compliance-critical CDK Mixin (e.g., BucketEncryption, BucketVersioning) is applied to some but not all resources of its target type in the stack \u2014 the template-visible signature of `Mixins.of(scope).apply(...)` silently skipping resources. Recommends `requireAll()` enforcement."},{ruleId:"TL-MIXIN-002",title:"Custom Mixin Applied Across Many Resource Types",category:"crossResourceAntiPatterns",defaultSeverity:"LOW",wafPillar:"Operational Excellence",check:sM,description:"A user-defined CDK Mixin appears on resources spanning 3+ distinct CFN types in the same stack \u2014 the template-visible signature of `.with(customMixin)` recursing through descendants because the mixin's `supports()` filter accepts every construct. Verify the supports() narrows to the intended resource type."}],uS=(t,e,s,n)=>{let r={};for(let i of GX)if(!(s&&s.length>0&&!s.some(a=>i.ruleId.toLowerCase().includes(a.toLowerCase())||i.category.toLowerCase().includes(a.toLowerCase())||i.title.toLowerCase().includes(a.toLowerCase()))))try{let o=i.check(t,e,n);for(let[a,c]of Object.entries(o)){r[a]||(r[a]={issues:[]});for(let u of c.issues)u.ruleId=i.ruleId;r[a].issues.push(...c.issues)}}catch{}return r}});var KM=D(()=>{"use strict";qM();Ws()});var hl,gl,lS=D(()=>{"use strict";hl={DEFAULT_MAX_CONCURRENT:5,DEFAULT_RETRY_ATTEMPTS:3,DEFAULT_RETRY_DELAY_MS:1e3,DEFAULT_TIMEOUT_MS:60*1e3},gl={WARNING_PERCENTAGE:.8,HARD_STOP_PERCENTAGE:.9,DEFAULT_FREE_AI_INSIGHTS:500,DEFAULT_PRO_AI_INSIGHTS:5e3,DEFAULT_TEAM_AI_INSIGHTS_PER_SEAT:1e4}});var sa,mm=D(()=>{"use strict";sa="3"});var xm,Qt,Tc,Fc,zX,qX,VM,hm,YM,ZM,Fi,gm,KX,VX,ZX,YX,JX,QX,dS,pS,ym,JM=D(()=>{"use strict";xm=oe(require("node:crypto")),Qt=oe(require("node:fs")),Tc=oe(require("node:path"));mp();dt();mm();dy();Fc=Tc.join(process.env.HOME||process.env.USERPROFILE||"",".cdk-insights","cache","analysis-cache.json"),zX=()=>{let t=Tc.dirname(Fc);Qt.existsSync(t)||Qt.mkdirSync(t,{recursive:!0})},qX=()=>{if(Pa())return new Map;try{if(Qt.existsSync(Fc)){let t=JSON.parse(Qt.readFileSync(Fc,"utf-8")),e=new Map,s=Date.now();for(let[n,r]of t.entries||[])s-r.timestamp>r.ttl||r.schemaVersion===sa&&e.set(n,r);return e}}catch(t){xn.warn("Could not load cache from disk",{error:t instanceof Error?t.message:String(t)})}return new Map},VM=t=>{if(!Pa())try{zX();let e={entries:Array.from(t.entries()),timestamp:Date.now(),version:"1.0"};Qt.writeFileSync(Fc,JSON.stringify(e,null,2),"utf-8")}catch(e){xn.warn("Could not save cache to disk",{error:e instanceof Error?e.message:String(e)})}},hm=new Map,YM=()=>Tc.join(process.env.HOME||process.env.USERPROFILE||"",".cdk-insights","cache","file-hashes.json"),ZM=5e3,Fi=null,gm=!1,KX=()=>{if(Fi!==null)return Fi;let t=YM();try{if(Qt.existsSync(t)){let e=Qt.readFileSync(t,"utf-8"),s=JSON.parse(e);if(s&&s.version===1&&s.entries)return Fi=s,Fi}}catch{}return Fi={version:1,entries:{}},Fi},VX=()=>{if(!gm||Fi===null)return;let t=YM();try{let e=Fi,s=Object.keys(e.entries);if(s.length>ZM){let r=s.map(o=>[o,e.entries[o].lastAccessedAt]).sort((o,a)=>o[1]-a[1]),i=s.length-ZM;for(let o=0;o<i;o++)delete e.entries[r[o][0]]}let n=Tc.dirname(t);Qt.existsSync(n)||Qt.mkdirSync(n,{recursive:!0}),Qt.writeFileSync(t,JSON.stringify(e),"utf-8"),gm=!1}catch{}};process.on("exit",VX);ZX=t=>{let e=hm.get(t);if(e!==void 0)return e;try{let s=Qt.statSync(t),n=s.mtime.getTime(),r=s.size,i=KX(),o=i.entries[t];if(o&&o.mtime===n&&o.size===r){o.lastAccessedAt=Date.now(),gm=!0;let l={filePath:t,lastModified:n,hash:o.hash};return hm.set(t,l),l}let a=Qt.readFileSync(t,"utf-8"),c=xm.createHash("sha256").update(a).digest("hex"),u={filePath:t,lastModified:n,hash:c};return hm.set(t,u),i.entries[t]={size:r,mtime:n,hash:c,lastAccessedAt:Date.now()},gm=!0,u}catch{return hm.set(t,null),null}},YX=t=>{let e={};for(let s of t){let n=ZX(s);n&&(e[s]=n)}return e},JX=(t,e)=>t?xm.createHash("sha256").update(`${t}:${e||""}`).digest("hex").slice(0,16):"no-auth",QX=t=>xm.createHash("sha256").update(JSON.stringify(t)).digest("hex"),dS=(t,e,s,n,r=[])=>{let i=JX(s,n),o=QX(e),a=YX(r);return{resourceId:t,authContext:i,resourceHash:o,fileHashes:a,schemaVersion:sa}},pS=t=>{let e=Object.entries(t.fileHashes).sort(([s],[n])=>s.localeCompare(n)).map(([s,n])=>`${s}:${n.hash}`).join("|");return`v${t.schemaVersion}:${t.resourceId}:${t.authContext}:${t.resourceHash}:${e}`},ym=class{cache;ttl;maxSize;disabled=!1;constructor(e={}){this.ttl=e.ttl||6*60*60*1e3,this.maxSize=e.maxSize||1e3,this.disabled=e.disabled||!1,this.disabled?this.cache=new Map:this.cache=qX()}setDisabled(e){this.disabled=e,e&&this.cache.clear()}get(e){if(this.disabled){Up();return}let s=this.cache.get(e);if(!s){Up();return}if(Date.now()-s.timestamp>s.ttl){this.cache.delete(e),Up();return}return pk(),s.value}set(e,s,n,r){this.disabled||(this.cache.size>=this.maxSize&&this.evictOldest(),this.cache.set(e,{value:s,timestamp:Date.now(),ttl:r??this.ttl,fileHashes:n.fileHashes,authContext:n.authContext,resourceHash:n.resourceHash,schemaVersion:n.schemaVersion}),fk(),this.cache.size%10===0&&VM(this.cache))}has(e){return this.cache.has(e)}clear(){if(this.cache.clear(),!Pa())try{Qt.existsSync(Fc)&&Qt.unlinkSync(Fc)}catch(e){xn.warn("Could not clear disk cache",{error:e instanceof Error?e.message:String(e)})}}saveToDisk(){VM(this.cache)}size(){return this.cache.size}evictOldest(){let e,s=Date.now();for(let[n,r]of Array.from(this.cache.entries()))r.timestamp<s&&(s=r.timestamp,e=n);e&&this.cache.delete(e)}getStats(){return{size:this.cache.size,maxSize:this.maxSize,hitRate:0,totalHits:0,totalMisses:0}}getAllCachedResults(){return new Map(this.cache)}getCachedResultsForResources(e){let s=new Map;for(let[n,r]of Array.from(this.cache.entries())){let i=n.split(":")[0];e.includes(i)&&Date.now()-r.timestamp<=r.ttl&&s.set(i,r.value)}return s}hasCachedResult(e){for(let s of Array.from(this.cache.keys()))if(s.split(":")[0]===e)return!0;return!1}}});var XX,eee,e8,tee,QM,see,nee,XM,fS,mS,na,bm,yl=D(()=>{"use strict";XX=new Set(["the","a","an","is","are","was","were","be","been","has","have","had","do","does","did","will","would","could","should","may","might","must","shall","can","this","that","these","those","it","its","to","for","of","in","on","at","by","with","from","or","and","not","no","but","if","then","else","when","where","resource","configuration","setting","configured","property","properties","which","lead","leads","leading","means","using","use","used","ensure","consider","also","such","most","more","any","all","some","other","each","every","necessary","unnecessary","recommended","default","specific","current","potential","possible","workloads","workload"]),eee=[["lacks","missing","without","absent","none","defined"],["encryption","encrypted","encrypt"],["configured","configuration","config","settings","setting"],["enabled","enable","active","activated"],["disabled","disable","inactive"],["public","publicly","open"],["access","accessible","accessibility"],["transit","transfer","transmission"],["rest","stored","storage"],["logging","logs","logged","log"],["dlq","dead","letter","queue"],["monitor","monitoring","observability"],["alarm","alarms","alert","alerts"],["unrestricted","permissive","overly"],["egress","outbound"],["ingress","inbound"],["recovery","backup","restore"],["pitr","point"],["function","functions"],["cluster","clusters"],["instance","instances"],["bucket","buckets"],["table","tables"],["domain","domains"],["node","nodes"],["policy","policies"],["rule","rules"],["subnet","subnets"],["high","higher","excessive","elevated"],["allocation","allocated","allocate"],["provisioned","provision"],["scaling","autoscaling","auto"],["restrict","restricted","restriction"],["expose","exposed","exposing","exposure"],["allow","allows","allowing"],["prevent","prevents","preventing"],["memory","ram","2gb","1gb"]],e8=new Map;for(let t of eee){let e=t[0];for(let s of t)e8.set(s,e)}tee=t=>e8.get(t)||t,QM=t=>{if(!t)return new Set;let e=t.toLowerCase().replace(/[^\w\s]/g," ").replace(/\s+/g," ").trim().split(" ").filter(s=>s.length>2&&!XX.has(s)).map(tee);return new Set(e)},see=(t,e)=>{if(t.size===0&&e.size===0)return 1;if(t.size===0||e.size===0)return 0;let s=[...t].filter(r=>e.has(r)).length,n=new Set([...t,...e]).size;return n>0?s/n:0},nee=.4,XM=3,fS=(t,e)=>{let s=QM(t.issue),n=QM(e.issue);return s.size<XM||n.size<XM?!1:see(s,n)>=nee},mS=t=>`${t.issue}::${t.severity}::${t.wafPillar}`,na=t=>{let{existing:e,incoming:s}=t,n=new Set(e.map(mS)),r=[];for(let i of s){let o=mS(i);n.has(o)||e.some(u=>fS(i,u))||r.some(u=>fS(i,u))||(n.add(o),r.push(i))}return r},bm=(t,e)=>{let s=new Set,n=[];for(let r of t){let i=mS(r);s.has(i)||n.some(a=>fS(r,a))||(s.add(i),n.push(r))}return n}});var t8,Pc,s8=D(()=>{"use strict";t8=oe(require("node:crypto")),Pc=(t,e)=>{let s=`${t}:${e}`;return t8.createHash("sha256").update(s).digest("hex").slice(0,32)}});var n8,r8,hS=D(()=>{"use strict";dt();n8=t=>e=>{let s={},n={};return Object.entries(e).forEach(([r,i])=>{let o=t(i);s[o]=r,n[o]=i}),{redactedResources:n,mapping:s}},r8=(t,e,s={})=>{let n=[];return t.forEach(r=>{let i=r.resourceId,o=s[i];if(!o&&i.includes("/")){let c=i.split("/"),u=c[c.length-2],l=Object.entries(e).find(([d,p])=>p.startsWith(u));l&&(o=l[1])}if(!o)return;let a=Object.entries(e).find(([,c])=>c===o)?.[0];if(!a){Me.warn(`\u26A0\uFE0F Unable to find redacted ID for logical resource: ${o}`);return}n.push({...r,resourceId:a})}),n}});function gS(t,e,{ignoreNonConfigurable:s=!1}={}){let{name:n}=t;for(let r of Reflect.ownKeys(e))ree(t,e,r,s);return oee(t,e),lee(t,e,n),t}var ree,iee,oee,aee,cee,uee,lee,i8=D(()=>{ree=(t,e,s,n)=>{if(s==="length"||s==="prototype"||s==="arguments"||s==="caller")return;let r=Object.getOwnPropertyDescriptor(t,s),i=Object.getOwnPropertyDescriptor(e,s);!iee(r,i)&&n||Object.defineProperty(t,s,i)},iee=function(t,e){return t===void 0||t.configurable||t.writable===e.writable&&t.enumerable===e.enumerable&&t.configurable===e.configurable&&(t.writable||t.value===e.value)},oee=(t,e)=>{let s=Object.getPrototypeOf(e);s!==Object.getPrototypeOf(t)&&Object.setPrototypeOf(t,s)},aee=(t,e)=>`/* Wrapped ${t}*/
|
|
164
164
|
${e}`,cee=Object.getOwnPropertyDescriptor(Function.prototype,"toString"),uee=Object.getOwnPropertyDescriptor(Function.prototype.toString,"name"),lee=(t,e,s)=>{let n=s===""?"":`with ${s.trim()}() `,r=aee.bind(null,n,e.toString());Object.defineProperty(r,"name",uee);let{writable:i,enumerable:o,configurable:a}=cee;Object.defineProperty(t,"toString",{value:r,writable:i,enumerable:o,configurable:a})}});var Sm,o8,a8,c8=D(()=>{i8();Sm=new WeakMap,o8=(t,e={})=>{if(typeof t!="function")throw new TypeError("Expected a function");let s,n=0,r=t.displayName||t.name||"<anonymous>",i=function(...o){if(Sm.set(i,++n),n===1)s=t.apply(this,o),t=void 0;else if(e.throw===!0)throw new Error(`Function \`${r}\` can only be called once`);return s};return gS(i,t),Sm.set(i,n),i};o8.callCount=t=>{if(!Sm.has(t))throw new Error(`The given function \`${t.name}\` is not wrapped by the \`onetime\` package`);return Sm.get(t)};a8=o8});var xl,u8,dee,l8,d8=D(()=>{xl=oe(require("node:process"),1);c8();Ny();u8=xl.default.stderr.isTTY?xl.default.stderr:xl.default.stdout.isTTY?xl.default.stdout:void 0,dee=u8?a8(()=>{lf(()=>{u8.write("\x1B[?25h")},{alwaysLast:!0})}):()=>{},l8=dee});var yS,vm,Lc,xS,p8=D(()=>{yS=oe(require("node:process"),1);d8();vm=!1,Lc={};Lc.show=(t=yS.default.stderr)=>{t.isTTY&&(vm=!1,t.write("\x1B[?25h"))};Lc.hide=(t=yS.default.stderr)=>{t.isTTY&&(l8(),vm=!0,t.write("\x1B[?25l"))};Lc.toggle=(t,e)=>{t!==void 0&&(vm=t),vm?Lc.show(e):Lc.hide(e)};xS=Lc});var f8=M((pke,pee)=>{pee.exports={dots:{interval:80,frames:["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"]},dots2:{interval:80,frames:["\u28FE","\u28FD","\u28FB","\u28BF","\u287F","\u28DF","\u28EF","\u28F7"]},dots3:{interval:80,frames:["\u280B","\u2819","\u281A","\u281E","\u2816","\u2826","\u2834","\u2832","\u2833","\u2813"]},dots4:{interval:80,frames:["\u2804","\u2806","\u2807","\u280B","\u2819","\u2838","\u2830","\u2820","\u2830","\u2838","\u2819","\u280B","\u2807","\u2806"]},dots5:{interval:80,frames:["\u280B","\u2819","\u281A","\u2812","\u2802","\u2802","\u2812","\u2832","\u2834","\u2826","\u2816","\u2812","\u2810","\u2810","\u2812","\u2813","\u280B"]},dots6:{interval:80,frames:["\u2801","\u2809","\u2819","\u281A","\u2812","\u2802","\u2802","\u2812","\u2832","\u2834","\u2824","\u2804","\u2804","\u2824","\u2834","\u2832","\u2812","\u2802","\u2802","\u2812","\u281A","\u2819","\u2809","\u2801"]},dots7:{interval:80,frames:["\u2808","\u2809","\u280B","\u2813","\u2812","\u2810","\u2810","\u2812","\u2816","\u2826","\u2824","\u2820","\u2820","\u2824","\u2826","\u2816","\u2812","\u2810","\u2810","\u2812","\u2813","\u280B","\u2809","\u2808"]},dots8:{interval:80,frames:["\u2801","\u2801","\u2809","\u2819","\u281A","\u2812","\u2802","\u2802","\u2812","\u2832","\u2834","\u2824","\u2804","\u2804","\u2824","\u2820","\u2820","\u2824","\u2826","\u2816","\u2812","\u2810","\u2810","\u2812","\u2813","\u280B","\u2809","\u2808","\u2808"]},dots9:{interval:80,frames:["\u28B9","\u28BA","\u28BC","\u28F8","\u28C7","\u2867","\u2857","\u284F"]},dots10:{interval:80,frames:["\u2884","\u2882","\u2881","\u2841","\u2848","\u2850","\u2860"]},dots11:{interval:100,frames:["\u2801","\u2802","\u2804","\u2840","\u2880","\u2820","\u2810","\u2808"]},dots12:{interval:80,frames:["\u2880\u2800","\u2840\u2800","\u2804\u2800","\u2882\u2800","\u2842\u2800","\u2805\u2800","\u2883\u2800","\u2843\u2800","\u280D\u2800","\u288B\u2800","\u284B\u2800","\u280D\u2801","\u288B\u2801","\u284B\u2801","\u280D\u2809","\u280B\u2809","\u280B\u2809","\u2809\u2819","\u2809\u2819","\u2809\u2829","\u2808\u2899","\u2808\u2859","\u2888\u2829","\u2840\u2899","\u2804\u2859","\u2882\u2829","\u2842\u2898","\u2805\u2858","\u2883\u2828","\u2843\u2890","\u280D\u2850","\u288B\u2820","\u284B\u2880","\u280D\u2841","\u288B\u2801","\u284B\u2801","\u280D\u2809","\u280B\u2809","\u280B\u2809","\u2809\u2819","\u2809\u2819","\u2809\u2829","\u2808\u2899","\u2808\u2859","\u2808\u2829","\u2800\u2899","\u2800\u2859","\u2800\u2829","\u2800\u2898","\u2800\u2858","\u2800\u2828","\u2800\u2890","\u2800\u2850","\u2800\u2820","\u2800\u2880","\u2800\u2840"]},dots13:{interval:80,frames:["\u28FC","\u28F9","\u28BB","\u283F","\u285F","\u28CF","\u28E7","\u28F6"]},dots8Bit:{interval:80,frames:["\u2800","\u2801","\u2802","\u2803","\u2804","\u2805","\u2806","\u2807","\u2840","\u2841","\u2842","\u2843","\u2844","\u2845","\u2846","\u2847","\u2808","\u2809","\u280A","\u280B","\u280C","\u280D","\u280E","\u280F","\u2848","\u2849","\u284A","\u284B","\u284C","\u284D","\u284E","\u284F","\u2810","\u2811","\u2812","\u2813","\u2814","\u2815","\u2816","\u2817","\u2850","\u2851","\u2852","\u2853","\u2854","\u2855","\u2856","\u2857","\u2818","\u2819","\u281A","\u281B","\u281C","\u281D","\u281E","\u281F","\u2858","\u2859","\u285A","\u285B","\u285C","\u285D","\u285E","\u285F","\u2820","\u2821","\u2822","\u2823","\u2824","\u2825","\u2826","\u2827","\u2860","\u2861","\u2862","\u2863","\u2864","\u2865","\u2866","\u2867","\u2828","\u2829","\u282A","\u282B","\u282C","\u282D","\u282E","\u282F","\u2868","\u2869","\u286A","\u286B","\u286C","\u286D","\u286E","\u286F","\u2830","\u2831","\u2832","\u2833","\u2834","\u2835","\u2836","\u2837","\u2870","\u2871","\u2872","\u2873","\u2874","\u2875","\u2876","\u2877","\u2838","\u2839","\u283A","\u283B","\u283C","\u283D","\u283E","\u283F","\u2878","\u2879","\u287A","\u287B","\u287C","\u287D","\u287E","\u287F","\u2880","\u2881","\u2882","\u2883","\u2884","\u2885","\u2886","\u2887","\u28C0","\u28C1","\u28C2","\u28C3","\u28C4","\u28C5","\u28C6","\u28C7","\u2888","\u2889","\u288A","\u288B","\u288C","\u288D","\u288E","\u288F","\u28C8","\u28C9","\u28CA","\u28CB","\u28CC","\u28CD","\u28CE","\u28CF","\u2890","\u2891","\u2892","\u2893","\u2894","\u2895","\u2896","\u2897","\u28D0","\u28D1","\u28D2","\u28D3","\u28D4","\u28D5","\u28D6","\u28D7","\u2898","\u2899","\u289A","\u289B","\u289C","\u289D","\u289E","\u289F","\u28D8","\u28D9","\u28DA","\u28DB","\u28DC","\u28DD","\u28DE","\u28DF","\u28A0","\u28A1","\u28A2","\u28A3","\u28A4","\u28A5","\u28A6","\u28A7","\u28E0","\u28E1","\u28E2","\u28E3","\u28E4","\u28E5","\u28E6","\u28E7","\u28A8","\u28A9","\u28AA","\u28AB","\u28AC","\u28AD","\u28AE","\u28AF","\u28E8","\u28E9","\u28EA","\u28EB","\u28EC","\u28ED","\u28EE","\u28EF","\u28B0","\u28B1","\u28B2","\u28B3","\u28B4","\u28B5","\u28B6","\u28B7","\u28F0","\u28F1","\u28F2","\u28F3","\u28F4","\u28F5","\u28F6","\u28F7","\u28B8","\u28B9","\u28BA","\u28BB","\u28BC","\u28BD","\u28BE","\u28BF","\u28F8","\u28F9","\u28FA","\u28FB","\u28FC","\u28FD","\u28FE","\u28FF"]},sand:{interval:80,frames:["\u2801","\u2802","\u2804","\u2840","\u2848","\u2850","\u2860","\u28C0","\u28C1","\u28C2","\u28C4","\u28CC","\u28D4","\u28E4","\u28E5","\u28E6","\u28EE","\u28F6","\u28F7","\u28FF","\u287F","\u283F","\u289F","\u281F","\u285B","\u281B","\u282B","\u288B","\u280B","\u280D","\u2849","\u2809","\u2811","\u2821","\u2881"]},line:{interval:130,frames:["-","\\","|","/"]},line2:{interval:100,frames:["\u2802","-","\u2013","\u2014","\u2013","-"]},pipe:{interval:100,frames:["\u2524","\u2518","\u2534","\u2514","\u251C","\u250C","\u252C","\u2510"]},simpleDots:{interval:400,frames:[". ",".. ","..."," "]},simpleDotsScrolling:{interval:200,frames:[". ",".. ","..."," .."," ."," "]},star:{interval:70,frames:["\u2736","\u2738","\u2739","\u273A","\u2739","\u2737"]},star2:{interval:80,frames:["+","x","*"]},flip:{interval:70,frames:["_","_","_","-","`","`","'","\xB4","-","_","_","_"]},hamburger:{interval:100,frames:["\u2631","\u2632","\u2634"]},growVertical:{interval:120,frames:["\u2581","\u2583","\u2584","\u2585","\u2586","\u2587","\u2586","\u2585","\u2584","\u2583"]},growHorizontal:{interval:120,frames:["\u258F","\u258E","\u258D","\u258C","\u258B","\u258A","\u2589","\u258A","\u258B","\u258C","\u258D","\u258E"]},balloon:{interval:140,frames:[" ",".","o","O","@","*"," "]},balloon2:{interval:120,frames:[".","o","O","\xB0","O","o","."]},noise:{interval:100,frames:["\u2593","\u2592","\u2591"]},bounce:{interval:120,frames:["\u2801","\u2802","\u2804","\u2802"]},boxBounce:{interval:120,frames:["\u2596","\u2598","\u259D","\u2597"]},boxBounce2:{interval:100,frames:["\u258C","\u2580","\u2590","\u2584"]},triangle:{interval:50,frames:["\u25E2","\u25E3","\u25E4","\u25E5"]},binary:{interval:80,frames:["010010","001100","100101","111010","111101","010111","101011","111000","110011","110101"]},arc:{interval:100,frames:["\u25DC","\u25E0","\u25DD","\u25DE","\u25E1","\u25DF"]},circle:{interval:120,frames:["\u25E1","\u2299","\u25E0"]},squareCorners:{interval:180,frames:["\u25F0","\u25F3","\u25F2","\u25F1"]},circleQuarters:{interval:120,frames:["\u25F4","\u25F7","\u25F6","\u25F5"]},circleHalves:{interval:50,frames:["\u25D0","\u25D3","\u25D1","\u25D2"]},squish:{interval:100,frames:["\u256B","\u256A"]},toggle:{interval:250,frames:["\u22B6","\u22B7"]},toggle2:{interval:80,frames:["\u25AB","\u25AA"]},toggle3:{interval:120,frames:["\u25A1","\u25A0"]},toggle4:{interval:100,frames:["\u25A0","\u25A1","\u25AA","\u25AB"]},toggle5:{interval:100,frames:["\u25AE","\u25AF"]},toggle6:{interval:300,frames:["\u101D","\u1040"]},toggle7:{interval:80,frames:["\u29BE","\u29BF"]},toggle8:{interval:100,frames:["\u25CD","\u25CC"]},toggle9:{interval:100,frames:["\u25C9","\u25CE"]},toggle10:{interval:100,frames:["\u3282","\u3280","\u3281"]},toggle11:{interval:50,frames:["\u29C7","\u29C6"]},toggle12:{interval:120,frames:["\u2617","\u2616"]},toggle13:{interval:80,frames:["=","*","-"]},arrow:{interval:100,frames:["\u2190","\u2196","\u2191","\u2197","\u2192","\u2198","\u2193","\u2199"]},arrow2:{interval:80,frames:["\u2B06\uFE0F ","\u2197\uFE0F ","\u27A1\uFE0F ","\u2198\uFE0F ","\u2B07\uFE0F ","\u2199\uFE0F ","\u2B05\uFE0F ","\u2196\uFE0F "]},arrow3:{interval:120,frames:["\u25B9\u25B9\u25B9\u25B9\u25B9","\u25B8\u25B9\u25B9\u25B9\u25B9","\u25B9\u25B8\u25B9\u25B9\u25B9","\u25B9\u25B9\u25B8\u25B9\u25B9","\u25B9\u25B9\u25B9\u25B8\u25B9","\u25B9\u25B9\u25B9\u25B9\u25B8"]},bouncingBar:{interval:80,frames:["[ ]","[= ]","[== ]","[=== ]","[====]","[ ===]","[ ==]","[ =]","[ ]","[ =]","[ ==]","[ ===]","[====]","[=== ]","[== ]","[= ]"]},bouncingBall:{interval:80,frames:["( \u25CF )","( \u25CF )","( \u25CF )","( \u25CF )","( \u25CF)","( \u25CF )","( \u25CF )","( \u25CF )","( \u25CF )","(\u25CF )"]},smiley:{interval:200,frames:["\u{1F604} ","\u{1F61D} "]},monkey:{interval:300,frames:["\u{1F648} ","\u{1F648} ","\u{1F649} ","\u{1F64A} "]},hearts:{interval:100,frames:["\u{1F49B} ","\u{1F499} ","\u{1F49C} ","\u{1F49A} ","\u2764\uFE0F "]},clock:{interval:100,frames:["\u{1F55B} ","\u{1F550} ","\u{1F551} ","\u{1F552} ","\u{1F553} ","\u{1F554} ","\u{1F555} ","\u{1F556} ","\u{1F557} ","\u{1F558} ","\u{1F559} ","\u{1F55A} "]},earth:{interval:180,frames:["\u{1F30D} ","\u{1F30E} ","\u{1F30F} "]},material:{interval:17,frames:["\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581","\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581","\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581","\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581","\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581","\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581","\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581","\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581","\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581","\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581","\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581","\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588","\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588","\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588","\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588","\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588","\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588","\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588","\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588","\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581","\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581\u2581","\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581","\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581\u2581","\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581\u2581","\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581","\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2588","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581","\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581\u2581"]},moon:{interval:80,frames:["\u{1F311} ","\u{1F312} ","\u{1F313} ","\u{1F314} ","\u{1F315} ","\u{1F316} ","\u{1F317} ","\u{1F318} "]},runner:{interval:140,frames:["\u{1F6B6} ","\u{1F3C3} "]},pong:{interval:80,frames:["\u2590\u2802 \u258C","\u2590\u2808 \u258C","\u2590 \u2802 \u258C","\u2590 \u2820 \u258C","\u2590 \u2840 \u258C","\u2590 \u2820 \u258C","\u2590 \u2802 \u258C","\u2590 \u2808 \u258C","\u2590 \u2802 \u258C","\u2590 \u2820 \u258C","\u2590 \u2840 \u258C","\u2590 \u2820 \u258C","\u2590 \u2802 \u258C","\u2590 \u2808 \u258C","\u2590 \u2802\u258C","\u2590 \u2820\u258C","\u2590 \u2840\u258C","\u2590 \u2820 \u258C","\u2590 \u2802 \u258C","\u2590 \u2808 \u258C","\u2590 \u2802 \u258C","\u2590 \u2820 \u258C","\u2590 \u2840 \u258C","\u2590 \u2820 \u258C","\u2590 \u2802 \u258C","\u2590 \u2808 \u258C","\u2590 \u2802 \u258C","\u2590 \u2820 \u258C","\u2590 \u2840 \u258C","\u2590\u2820 \u258C"]},shark:{interval:120,frames:["\u2590|\\____________\u258C","\u2590_|\\___________\u258C","\u2590__|\\__________\u258C","\u2590___|\\_________\u258C","\u2590____|\\________\u258C","\u2590_____|\\_______\u258C","\u2590______|\\______\u258C","\u2590_______|\\_____\u258C","\u2590________|\\____\u258C","\u2590_________|\\___\u258C","\u2590__________|\\__\u258C","\u2590___________|\\_\u258C","\u2590____________|\\\u258C","\u2590____________/|\u258C","\u2590___________/|_\u258C","\u2590__________/|__\u258C","\u2590_________/|___\u258C","\u2590________/|____\u258C","\u2590_______/|_____\u258C","\u2590______/|______\u258C","\u2590_____/|_______\u258C","\u2590____/|________\u258C","\u2590___/|_________\u258C","\u2590__/|__________\u258C","\u2590_/|___________\u258C","\u2590/|____________\u258C"]},dqpb:{interval:100,frames:["d","q","p","b"]},weather:{interval:100,frames:["\u2600\uFE0F ","\u2600\uFE0F ","\u2600\uFE0F ","\u{1F324} ","\u26C5\uFE0F ","\u{1F325} ","\u2601\uFE0F ","\u{1F327} ","\u{1F328} ","\u{1F327} ","\u{1F328} ","\u{1F327} ","\u{1F328} ","\u26C8 ","\u{1F328} ","\u{1F327} ","\u{1F328} ","\u2601\uFE0F ","\u{1F325} ","\u26C5\uFE0F ","\u{1F324} ","\u2600\uFE0F ","\u2600\uFE0F "]},christmas:{interval:400,frames:["\u{1F332}","\u{1F384}"]},grenade:{interval:80,frames:["\u060C ","\u2032 "," \xB4 "," \u203E "," \u2E0C"," \u2E0A"," |"," \u204E"," \u2055"," \u0DF4 "," \u2053"," "," "," "]},point:{interval:125,frames:["\u2219\u2219\u2219","\u25CF\u2219\u2219","\u2219\u25CF\u2219","\u2219\u2219\u25CF","\u2219\u2219\u2219"]},layer:{interval:150,frames:["-","=","\u2261"]},betaWave:{interval:80,frames:["\u03C1\u03B2\u03B2\u03B2\u03B2\u03B2\u03B2","\u03B2\u03C1\u03B2\u03B2\u03B2\u03B2\u03B2","\u03B2\u03B2\u03C1\u03B2\u03B2\u03B2\u03B2","\u03B2\u03B2\u03B2\u03C1\u03B2\u03B2\u03B2","\u03B2\u03B2\u03B2\u03B2\u03C1\u03B2\u03B2","\u03B2\u03B2\u03B2\u03B2\u03B2\u03C1\u03B2","\u03B2\u03B2\u03B2\u03B2\u03B2\u03B2\u03C1"]},fingerDance:{interval:160,frames:["\u{1F918} ","\u{1F91F} ","\u{1F596} ","\u270B ","\u{1F91A} ","\u{1F446} "]},fistBump:{interval:80,frames:["\u{1F91C}\u3000\u3000\u3000\u3000\u{1F91B} ","\u{1F91C}\u3000\u3000\u3000\u3000\u{1F91B} ","\u{1F91C}\u3000\u3000\u3000\u3000\u{1F91B} ","\u3000\u{1F91C}\u3000\u3000\u{1F91B}\u3000 ","\u3000\u3000\u{1F91C}\u{1F91B}\u3000\u3000 ","\u3000\u{1F91C}\u2728\u{1F91B}\u3000\u3000 ","\u{1F91C}\u3000\u2728\u3000\u{1F91B}\u3000 "]},soccerHeader:{interval:80,frames:[" \u{1F9D1}\u26BD\uFE0F \u{1F9D1} ","\u{1F9D1} \u26BD\uFE0F \u{1F9D1} ","\u{1F9D1} \u26BD\uFE0F \u{1F9D1} ","\u{1F9D1} \u26BD\uFE0F \u{1F9D1} ","\u{1F9D1} \u26BD\uFE0F \u{1F9D1} ","\u{1F9D1} \u26BD\uFE0F \u{1F9D1} ","\u{1F9D1} \u26BD\uFE0F\u{1F9D1} ","\u{1F9D1} \u26BD\uFE0F \u{1F9D1} ","\u{1F9D1} \u26BD\uFE0F \u{1F9D1} ","\u{1F9D1} \u26BD\uFE0F \u{1F9D1} ","\u{1F9D1} \u26BD\uFE0F \u{1F9D1} ","\u{1F9D1} \u26BD\uFE0F \u{1F9D1} "]},mindblown:{interval:160,frames:["\u{1F610} ","\u{1F610} ","\u{1F62E} ","\u{1F62E} ","\u{1F626} ","\u{1F626} ","\u{1F627} ","\u{1F627} ","\u{1F92F} ","\u{1F4A5} ","\u2728 ","\u3000 ","\u3000 ","\u3000 "]},speaker:{interval:160,frames:["\u{1F508} ","\u{1F509} ","\u{1F50A} ","\u{1F509} "]},orangePulse:{interval:100,frames:["\u{1F538} ","\u{1F536} ","\u{1F7E0} ","\u{1F7E0} ","\u{1F536} "]},bluePulse:{interval:100,frames:["\u{1F539} ","\u{1F537} ","\u{1F535} ","\u{1F535} ","\u{1F537} "]},orangeBluePulse:{interval:100,frames:["\u{1F538} ","\u{1F536} ","\u{1F7E0} ","\u{1F7E0} ","\u{1F536} ","\u{1F539} ","\u{1F537} ","\u{1F535} ","\u{1F535} ","\u{1F537} "]},timeTravel:{interval:100,frames:["\u{1F55B} ","\u{1F55A} ","\u{1F559} ","\u{1F558} ","\u{1F557} ","\u{1F556} ","\u{1F555} ","\u{1F554} ","\u{1F553} ","\u{1F552} ","\u{1F551} ","\u{1F550} "]},aesthetic:{interval:80,frames:["\u25B0\u25B1\u25B1\u25B1\u25B1\u25B1\u25B1","\u25B0\u25B0\u25B1\u25B1\u25B1\u25B1\u25B1","\u25B0\u25B0\u25B0\u25B1\u25B1\u25B1\u25B1","\u25B0\u25B0\u25B0\u25B0\u25B1\u25B1\u25B1","\u25B0\u25B0\u25B0\u25B0\u25B0\u25B1\u25B1","\u25B0\u25B0\u25B0\u25B0\u25B0\u25B0\u25B1","\u25B0\u25B0\u25B0\u25B0\u25B0\u25B0\u25B0","\u25B0\u25B1\u25B1\u25B1\u25B1\u25B1\u25B1"]},dwarfFortress:{interval:80,frames:[" \u2588\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 ","\u263A\u2588\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 ","\u263A\u2588\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 ","\u263A\u2593\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 ","\u263A\u2593\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 ","\u263A\u2592\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 ","\u263A\u2592\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 ","\u263A\u2591\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 ","\u263A\u2591\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 ","\u263A \u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2593\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2593\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2592\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2592\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2591\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2591\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A \u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2593\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2593\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2592\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2592\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2591\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2591\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A \u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2588\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2593\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2593\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2592\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2592\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2591\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2591\u2588\u2588\xA3\xA3\xA3 "," \u263A \u2588\u2588\xA3\xA3\xA3 "," \u263A\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2588\u2588\xA3\xA3\xA3 "," \u263A\u2593\u2588\xA3\xA3\xA3 "," \u263A\u2593\u2588\xA3\xA3\xA3 "," \u263A\u2592\u2588\xA3\xA3\xA3 "," \u263A\u2592\u2588\xA3\xA3\xA3 "," \u263A\u2591\u2588\xA3\xA3\xA3 "," \u263A\u2591\u2588\xA3\xA3\xA3 "," \u263A \u2588\xA3\xA3\xA3 "," \u263A\u2588\xA3\xA3\xA3 "," \u263A\u2588\xA3\xA3\xA3 "," \u263A\u2593\xA3\xA3\xA3 "," \u263A\u2593\xA3\xA3\xA3 "," \u263A\u2592\xA3\xA3\xA3 "," \u263A\u2592\xA3\xA3\xA3 "," \u263A\u2591\xA3\xA3\xA3 "," \u263A\u2591\xA3\xA3\xA3 "," \u263A \xA3\xA3\xA3 "," \u263A\xA3\xA3\xA3 "," \u263A\xA3\xA3\xA3 "," \u263A\u2593\xA3\xA3 "," \u263A\u2593\xA3\xA3 "," \u263A\u2592\xA3\xA3 "," \u263A\u2592\xA3\xA3 "," \u263A\u2591\xA3\xA3 "," \u263A\u2591\xA3\xA3 "," \u263A \xA3\xA3 "," \u263A\xA3\xA3 "," \u263A\xA3\xA3 "," \u263A\u2593\xA3 "," \u263A\u2593\xA3 "," \u263A\u2592\xA3 "," \u263A\u2592\xA3 "," \u263A\u2591\xA3 "," \u263A\u2591\xA3 "," \u263A \xA3 "," \u263A\xA3 "," \u263A\xA3 "," \u263A\u2593 "," \u263A\u2593 "," \u263A\u2592 "," \u263A\u2592 "," \u263A\u2591 "," \u263A\u2591 "," \u263A "," \u263A &"," \u263A \u263C&"," \u263A \u263C &"," \u263A\u263C &"," \u263A\u263C & "," \u203C & "," \u263A & "," \u203C & "," \u263A & "," \u203C & "," \u263A & ","\u203C & "," & "," & "," & \u2591 "," & \u2592 "," & \u2593 "," & \xA3 "," & \u2591\xA3 "," & \u2592\xA3 "," & \u2593\xA3 "," & \xA3\xA3 "," & \u2591\xA3\xA3 "," & \u2592\xA3\xA3 ","& \u2593\xA3\xA3 ","& \xA3\xA3\xA3 "," \u2591\xA3\xA3\xA3 "," \u2592\xA3\xA3\xA3 "," \u2593\xA3\xA3\xA3 "," \u2588\xA3\xA3\xA3 "," \u2591\u2588\xA3\xA3\xA3 "," \u2592\u2588\xA3\xA3\xA3 "," \u2593\u2588\xA3\xA3\xA3 "," \u2588\u2588\xA3\xA3\xA3 "," \u2591\u2588\u2588\xA3\xA3\xA3 "," \u2592\u2588\u2588\xA3\xA3\xA3 "," \u2593\u2588\u2588\xA3\xA3\xA3 "," \u2588\u2588\u2588\xA3\xA3\xA3 "," \u2591\u2588\u2588\u2588\xA3\xA3\xA3 "," \u2592\u2588\u2588\u2588\xA3\xA3\xA3 "," \u2593\u2588\u2588\u2588\xA3\xA3\xA3 "," \u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u2591\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u2592\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u2593\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u2591\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u2592\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u2593\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u2588\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "," \u2588\u2588\u2588\u2588\u2588\u2588\xA3\xA3\xA3 "]}}});var bS=M((fke,h8)=>{"use strict";var Cm=Object.assign({},f8()),m8=Object.keys(Cm);Object.defineProperty(Cm,"random",{get(){let t=Math.floor(Math.random()*m8.length),e=m8[t];return Cm[e]}});h8.exports=Cm});function SS(){return Tn.default.platform!=="win32"?Tn.default.env.TERM!=="linux":!!Tn.default.env.CI||!!Tn.default.env.WT_SESSION||!!Tn.default.env.TERMINUS_SUBLIME||Tn.default.env.ConEmuTask==="{cmd::Cmder}"||Tn.default.env.TERM_PROGRAM==="Terminus-Sublime"||Tn.default.env.TERM_PROGRAM==="vscode"||Tn.default.env.TERM==="xterm-256color"||Tn.default.env.TERM==="alacritty"||Tn.default.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}var Tn,g8=D(()=>{Tn=oe(require("node:process"),1)});var fee,mee,hee,bl,y8=D(()=>{sl();g8();fee={info:Xe.blue("\u2139"),success:Xe.green("\u2714"),warning:Xe.yellow("\u26A0"),error:Xe.red("\u2716")},mee={info:Xe.blue("i"),success:Xe.green("\u221A"),warning:Xe.yellow("\u203C"),error:Xe.red("\xD7")},hee=SS()?fee:mee,bl=hee});function vS({onlyFirst:t=!1}={}){let s=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))","(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|");return new RegExp(s,t?void 0:"g")}var x8=D(()=>{});function Sl(t){if(typeof t!="string")throw new TypeError(`Expected a \`string\`, got \`${typeof t}\``);return t.replace(gee,"")}var gee,CS=D(()=>{x8();gee=vS()});function b8(t){return t===161||t===164||t===167||t===168||t===170||t===173||t===174||t>=176&&t<=180||t>=182&&t<=186||t>=188&&t<=191||t===198||t===208||t===215||t===216||t>=222&&t<=225||t===230||t>=232&&t<=234||t===236||t===237||t===240||t===242||t===243||t>=247&&t<=250||t===252||t===254||t===257||t===273||t===275||t===283||t===294||t===295||t===299||t>=305&&t<=307||t===312||t>=319&&t<=322||t===324||t>=328&&t<=331||t===333||t===338||t===339||t===358||t===359||t===363||t===462||t===464||t===466||t===468||t===470||t===472||t===474||t===476||t===593||t===609||t===708||t===711||t>=713&&t<=715||t===717||t===720||t>=728&&t<=731||t===733||t===735||t>=768&&t<=879||t>=913&&t<=929||t>=931&&t<=937||t>=945&&t<=961||t>=963&&t<=969||t===1025||t>=1040&&t<=1103||t===1105||t===8208||t>=8211&&t<=8214||t===8216||t===8217||t===8220||t===8221||t>=8224&&t<=8226||t>=8228&&t<=8231||t===8240||t===8242||t===8243||t===8245||t===8251||t===8254||t===8308||t===8319||t>=8321&&t<=8324||t===8364||t===8451||t===8453||t===8457||t===8467||t===8470||t===8481||t===8482||t===8486||t===8491||t===8531||t===8532||t>=8539&&t<=8542||t>=8544&&t<=8555||t>=8560&&t<=8569||t===8585||t>=8592&&t<=8601||t===8632||t===8633||t===8658||t===8660||t===8679||t===8704||t===8706||t===8707||t===8711||t===8712||t===8715||t===8719||t===8721||t===8725||t===8730||t>=8733&&t<=8736||t===8739||t===8741||t>=8743&&t<=8748||t===8750||t>=8756&&t<=8759||t===8764||t===8765||t===8776||t===8780||t===8786||t===8800||t===8801||t>=8804&&t<=8807||t===8810||t===8811||t===8814||t===8815||t===8834||t===8835||t===8838||t===8839||t===8853||t===8857||t===8869||t===8895||t===8978||t>=9312&&t<=9449||t>=9451&&t<=9547||t>=9552&&t<=9587||t>=9600&&t<=9615||t>=9618&&t<=9621||t===9632||t===9633||t>=9635&&t<=9641||t===9650||t===9651||t===9654||t===9655||t===9660||t===9661||t===9664||t===9665||t>=9670&&t<=9672||t===9675||t>=9678&&t<=9681||t>=9698&&t<=9701||t===9711||t===9733||t===9734||t===9737||t===9742||t===9743||t===9756||t===9758||t===9792||t===9794||t===9824||t===9825||t>=9827&&t<=9829||t>=9831&&t<=9834||t===9836||t===9837||t===9839||t===9886||t===9887||t===9919||t>=9926&&t<=9933||t>=9935&&t<=9939||t>=9941&&t<=9953||t===9955||t===9960||t===9961||t>=9963&&t<=9969||t===9972||t>=9974&&t<=9977||t===9979||t===9980||t===9982||t===9983||t===10045||t>=10102&&t<=10111||t>=11094&&t<=11097||t>=12872&&t<=12879||t>=57344&&t<=63743||t>=65024&&t<=65039||t===65533||t>=127232&&t<=127242||t>=127248&&t<=127277||t>=127280&&t<=127337||t>=127344&&t<=127373||t===127375||t===127376||t>=127387&&t<=127404||t>=917760&&t<=917999||t>=983040&&t<=1048573||t>=1048576&&t<=1114109}function S8(t){return t===12288||t>=65281&&t<=65376||t>=65504&&t<=65510}function v8(t){return t>=4352&&t<=4447||t===8986||t===8987||t===9001||t===9002||t>=9193&&t<=9196||t===9200||t===9203||t===9725||t===9726||t===9748||t===9749||t>=9776&&t<=9783||t>=9800&&t<=9811||t===9855||t>=9866&&t<=9871||t===9875||t===9889||t===9898||t===9899||t===9917||t===9918||t===9924||t===9925||t===9934||t===9940||t===9962||t===9970||t===9971||t===9973||t===9978||t===9981||t===9989||t===9994||t===9995||t===10024||t===10060||t===10062||t>=10067&&t<=10069||t===10071||t>=10133&&t<=10135||t===10160||t===10175||t===11035||t===11036||t===11088||t===11093||t>=11904&&t<=11929||t>=11931&&t<=12019||t>=12032&&t<=12245||t>=12272&&t<=12287||t>=12289&&t<=12350||t>=12353&&t<=12438||t>=12441&&t<=12543||t>=12549&&t<=12591||t>=12593&&t<=12686||t>=12688&&t<=12773||t>=12783&&t<=12830||t>=12832&&t<=12871||t>=12880&&t<=42124||t>=42128&&t<=42182||t>=43360&&t<=43388||t>=44032&&t<=55203||t>=63744&&t<=64255||t>=65040&&t<=65049||t>=65072&&t<=65106||t>=65108&&t<=65126||t>=65128&&t<=65131||t>=94176&&t<=94180||t===94192||t===94193||t>=94208&&t<=100343||t>=100352&&t<=101589||t>=101631&&t<=101640||t>=110576&&t<=110579||t>=110581&&t<=110587||t===110589||t===110590||t>=110592&&t<=110882||t===110898||t>=110928&&t<=110930||t===110933||t>=110948&&t<=110951||t>=110960&&t<=111355||t>=119552&&t<=119638||t>=119648&&t<=119670||t===126980||t===127183||t===127374||t>=127377&&t<=127386||t>=127488&&t<=127490||t>=127504&&t<=127547||t>=127552&&t<=127560||t===127568||t===127569||t>=127584&&t<=127589||t>=127744&&t<=127776||t>=127789&&t<=127797||t>=127799&&t<=127868||t>=127870&&t<=127891||t>=127904&&t<=127946||t>=127951&&t<=127955||t>=127968&&t<=127984||t===127988||t>=127992&&t<=128062||t===128064||t>=128066&&t<=128252||t>=128255&&t<=128317||t>=128331&&t<=128334||t>=128336&&t<=128359||t===128378||t===128405||t===128406||t===128420||t>=128507&&t<=128591||t>=128640&&t<=128709||t===128716||t>=128720&&t<=128722||t>=128725&&t<=128727||t>=128732&&t<=128735||t===128747||t===128748||t>=128756&&t<=128764||t>=128992&&t<=129003||t===129008||t>=129292&&t<=129338||t>=129340&&t<=129349||t>=129351&&t<=129535||t>=129648&&t<=129660||t>=129664&&t<=129673||t>=129679&&t<=129734||t>=129742&&t<=129756||t>=129759&&t<=129769||t>=129776&&t<=129784||t>=131072&&t<=196605||t>=196608&&t<=262141}var C8=D(()=>{});function yee(t){if(!Number.isSafeInteger(t))throw new TypeError(`Expected a code point, got \`${typeof t}\`.`)}function D8(t,{ambiguousAsWide:e=!1}={}){return yee(t),S8(t)||v8(t)||e&&b8(t)?2:1}var A8=D(()=>{C8()});var E8=M((wke,w8)=>{w8.exports=()=>/[#*0-9]\uFE0F?\u20E3|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26AA\u26B0\u26B1\u26BD\u26BE\u26C4\u26C8\u26CF\u26D1\u26E9\u26F0-\u26F5\u26F7\u26F8\u26FA\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B55\u3030\u303D\u3297\u3299]\uFE0F?|[\u261D\u270C\u270D](?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?|[\u270A\u270B](?:\uD83C[\uDFFB-\uDFFF])?|[\u23E9-\u23EC\u23F0\u23F3\u25FD\u2693\u26A1\u26AB\u26C5\u26CE\u26D4\u26EA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2795-\u2797\u27B0\u27BF\u2B50]|\u26D3\uFE0F?(?:\u200D\uD83D\uDCA5)?|\u26F9(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?(?:\u200D[\u2640\u2642]\uFE0F?)?|\u2764\uFE0F?(?:\u200D(?:\uD83D\uDD25|\uD83E\uDE79))?|\uD83C(?:[\uDC04\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]\uFE0F?|[\uDF85\uDFC2\uDFC7](?:\uD83C[\uDFFB-\uDFFF])?|[\uDFC4\uDFCA](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDFCB\uDFCC](?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF43\uDF45-\uDF4A\uDF4C-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uDDE6\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF]|\uDDE7\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF]|\uDDE8\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF7\uDDFA-\uDDFF]|\uDDE9\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF]|\uDDEA\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA]|\uDDEB\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7]|\uDDEC\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE]|\uDDED\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA]|\uDDEE\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9]|\uDDEF\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5]|\uDDF0\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF]|\uDDF1\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE]|\uDDF2\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF]|\uDDF3\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF]|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE]|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC]|\uDDF8\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF]|\uDDF9\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF]|\uDDFA\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF]|\uDDFB\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA]|\uDDFC\uD83C[\uDDEB\uDDF8]|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C[\uDDEA\uDDF9]|\uDDFF\uD83C[\uDDE6\uDDF2\uDDFC]|\uDF44(?:\u200D\uD83D\uDFEB)?|\uDF4B(?:\u200D\uD83D\uDFE9)?|\uDFC3(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDFF3\uFE0F?(?:\u200D(?:\u26A7\uFE0F?|\uD83C\uDF08))?|\uDFF4(?:\u200D\u2620\uFE0F?|\uDB40\uDC67\uDB40\uDC62\uDB40(?:\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDC73\uDB40\uDC63\uDB40\uDC74|\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F)?)|\uD83D(?:[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3]\uFE0F?|[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC](?:\uD83C[\uDFFB-\uDFFF])?|[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4\uDEB5](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD74\uDD90](?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?|[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC25\uDC27-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE41\uDE43\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEDC-\uDEDF\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB\uDFF0]|\uDC08(?:\u200D\u2B1B)?|\uDC15(?:\u200D\uD83E\uDDBA)?|\uDC26(?:\u200D(?:\u2B1B|\uD83D\uDD25))?|\uDC3B(?:\u200D\u2744\uFE0F?)?|\uDC41\uFE0F?(?:\u200D\uD83D\uDDE8\uFE0F?)?|\uDC68(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDC68\uDC69]\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE])))?))?|\uDC69(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?[\uDC68\uDC69]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?))|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFE])))?))?|\uDC6F(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDD75(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDE2E(?:\u200D\uD83D\uDCA8)?|\uDE35(?:\u200D\uD83D\uDCAB)?|\uDE36(?:\u200D\uD83C\uDF2B\uFE0F?)?|\uDE42(?:\u200D[\u2194\u2195]\uFE0F?)?|\uDEB6(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?)|\uD83E(?:[\uDD0C\uDD0F\uDD18-\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5\uDEC3-\uDEC5\uDEF0\uDEF2-\uDEF8](?:\uD83C[\uDFFB-\uDFFF])?|[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD\uDDCF\uDDD4\uDDD6-\uDDDD](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDDDE\uDDDF](?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD0D\uDD0E\uDD10-\uDD17\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCC\uDDD0\uDDE0-\uDDFF\uDE70-\uDE7C\uDE80-\uDE89\uDE8F-\uDEC2\uDEC6\uDECE-\uDEDC\uDEDF-\uDEE9]|\uDD3C(?:\u200D[\u2640\u2642]\uFE0F?|\uD83C[\uDFFB-\uDFFF])?|\uDDCE(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDDD1(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1|\uDDD1\u200D\uD83E\uDDD2(?:\u200D\uD83E\uDDD2)?|\uDDD2(?:\u200D\uD83E\uDDD2)?))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFC-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFD-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?))?|\uDEF1(?:\uD83C(?:\uDFFB(?:\u200D\uD83E\uDEF2\uD83C[\uDFFC-\uDFFF])?|\uDFFC(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFD-\uDFFF])?|\uDFFD(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])?|\uDFFE(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFD\uDFFF])?|\uDFFF(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFE])?))?)/g});function DS(t,e={}){if(typeof t!="string"||t.length===0)return 0;let{ambiguousIsNarrow:s=!0,countAnsiEscapeCodes:n=!1}=e;if(n||(t=Sl(t)),t.length===0)return 0;let r=0,i={ambiguousAsWide:!s};for(let{segment:o}of xee.segment(t)){let a=o.codePointAt(0);if(!(a<=31||a>=127&&a<=159)&&!(a>=8203&&a<=8207||a===65279)&&!(a>=768&&a<=879||a>=6832&&a<=6911||a>=7616&&a<=7679||a>=8400&&a<=8447||a>=65056&&a<=65071)&&!(a>=55296&&a<=57343)&&!(a>=65024&&a<=65039)&&!bee.test(o)){if((0,R8.default)().test(o)){r+=2;continue}r+=D8(a,i)}}return r}var R8,xee,bee,I8=D(()=>{CS();A8();R8=oe(E8(),1),xee=new Intl.Segmenter,bee=new RegExp("^\\p{Default_Ignorable_Code_Point}$","u")});function AS({stream:t=process.stdout}={}){return!!(t&&t.isTTY&&process.env.TERM!=="dumb"&&!("CI"in process.env))}var k8=D(()=>{});function ES(){let{env:t}=wS.default,{TERM:e,TERM_PROGRAM:s}=t;return wS.default.platform!=="win32"?e!=="linux":!!t.WT_SESSION||!!t.TERMINUS_SUBLIME||t.ConEmuTask==="{cmd::Cmder}"||s==="Terminus-Sublime"||s==="vscode"||e==="xterm-256color"||e==="alacritty"||e==="rxvt-unicode"||e==="rxvt-unicode-256color"||t.TERMINAL_EMULATOR==="JetBrains-JediTerm"}var wS,_8=D(()=>{wS=oe(require("node:process"),1)});var er,See,RS,vee,IS,F8=D(()=>{er=oe(require("node:process"),1),See=3,RS=class{#n=0;start(){this.#n++,this.#n===1&&this.#s()}stop(){if(this.#n<=0)throw new Error("`stop` called more times than `start`");this.#n--,this.#n===0&&this.#e()}#s(){er.default.platform==="win32"||!er.default.stdin.isTTY||(er.default.stdin.setRawMode(!0),er.default.stdin.on("data",this.#i),er.default.stdin.resume())}#e(){er.default.stdin.isTTY&&(er.default.stdin.off("data",this.#i),er.default.stdin.pause(),er.default.stdin.setRawMode(!1))}#i(e){e[0]===See&&er.default.emit("SIGINT")}},vee=new RS,IS=vee});function Dm(t){return new kS(t)}var vl,Cl,Cee,kS,T8=D(()=>{vl=oe(require("node:process"),1);sl();p8();Cl=oe(bS(),1);y8();CS();I8();k8();_8();F8();Cee=oe(bS(),1),kS=class{#n=0;#s=!1;#e=0;#i=-1;#p=0;#t;#o;#r;#f;#h;#u;#l;#d;#g;#a;#c;color;constructor(e){typeof e=="string"&&(e={text:e}),this.#t={color:"cyan",stream:vl.default.stderr,discardStdin:!0,hideCursor:!0,...e},this.color=this.#t.color,this.spinner=this.#t.spinner,this.#h=this.#t.interval,this.#r=this.#t.stream,this.#u=typeof this.#t.isEnabled=="boolean"?this.#t.isEnabled:AS({stream:this.#r}),this.#l=typeof this.#t.isSilent=="boolean"?this.#t.isSilent:!1,this.text=this.#t.text,this.prefixText=this.#t.prefixText,this.suffixText=this.#t.suffixText,this.indent=this.#t.indent,vl.default.env.NODE_ENV==="test"&&(this._stream=this.#r,this._isEnabled=this.#u,Object.defineProperty(this,"_linesToClear",{get(){return this.#n},set(s){this.#n=s}}),Object.defineProperty(this,"_frameIndex",{get(){return this.#i}}),Object.defineProperty(this,"_lineCount",{get(){return this.#e}}))}get indent(){return this.#d}set indent(e=0){if(!(e>=0&&Number.isInteger(e)))throw new Error("The `indent` option must be an integer from 0 and up");this.#d=e,this.#m()}get interval(){return this.#h??this.#o.interval??100}get spinner(){return this.#o}set spinner(e){if(this.#i=-1,this.#h=void 0,typeof e=="object"){if(e.frames===void 0)throw new Error("The given spinner must have a `frames` property");this.#o=e}else if(!ES())this.#o=Cl.default.line;else if(e===void 0)this.#o=Cl.default.dots;else if(e!=="default"&&Cl.default[e])this.#o=Cl.default[e];else throw new Error(`There is no built-in spinner named '${e}'. See https://github.com/sindresorhus/cli-spinners/blob/main/spinners.json for a full list.`)}get text(){return this.#g}set text(e=""){this.#g=e,this.#m()}get prefixText(){return this.#a}set prefixText(e=""){this.#a=e,this.#m()}get suffixText(){return this.#c}set suffixText(e=""){this.#c=e,this.#m()}get isSpinning(){return this.#f!==void 0}#y(e=this.#a,s=" "){return typeof e=="string"&&e!==""?e+s:typeof e=="function"?e()+s:""}#x(e=this.#c,s=" "){return typeof e=="string"&&e!==""?s+e:typeof e=="function"?s+e():""}#m(){let e=this.#r.columns??80,s=this.#y(this.#a,"-"),n=this.#x(this.#c,"-"),r=" ".repeat(this.#d)+s+"--"+this.#g+"--"+n;this.#e=0;for(let i of Sl(r).split(`
|
|
@@ -174,7 +174,7 @@ ${gt.primary.bold(`${Xt.rocket} ${s}`)}`),console.log(`${gt.comment("\u2500".rep
|
|
|
174
174
|
${gt.primary.bold(`${Xt.chart} Analysis Complete!`)}`),console.log(gt.comment("\u2500".repeat(50))),console.log(gt.success(`\u2705 Completed: ${n}`)),i>0&&console.log(gt.error(`\u274C Failed: ${i}`)),o>0&&console.log(gt.warning(`\u23F0 Timed out: ${o}`)),console.log(gt.comment(`\u23F1\uFE0F Total time: ${y}s`))}}}createSpinner(e){let s=Dm({text:e,color:"blue",spinner:"dots"}).start();return{stop:n=>{n?s.succeed(n):s.stop()},fail:n=>{s.fail(n||"Failed")},warn:n=>{s.warn(n||"Warning")},info:n=>{s.info(n||"Info")}}}showSummary(e){console.log(`
|
|
175
175
|
${gt.primary.bold(`${Xt.chart} Analysis Summary`)}`),console.log(gt.comment("\u2500".repeat(40))),console.log(gt.text(`Completed ${e.length} step${e.length===1?"":"s"} successfully!`))}header(e){console.log(`
|
|
176
176
|
${gt.primary.bold(`${Xt.rocket} ${e}`)}`),console.log(`${gt.comment("\u2500".repeat(60))}
|
|
177
|
-
`)}section(e,s=Xt.info){console.log(gt.primary.bold(`${s} ${e}`))}success(e,s=Xt.success){console.log(gt.success(`${s} ${e}`))}info(e,s=Xt.info){console.log(gt.info(`${s} ${e}`))}warning(e,s=Xt.warning){console.log(gt.warning(`${s} ${e}`))}error(e,s=Xt.error){console.log(gt.error(`${s} ${e}`))}comment(e,s=""){console.log(gt.comment(`${s} ${e}`))}phase1(e){console.log(gt.info(`${Xt.phase1} Phase 1: ${e}`))}phase2(e){console.log(gt.primary(`${Xt.phase2} Phase 2: ${e}`))}phase3(e){console.log(gt.secondary(`${Xt.phase3} Phase 3: ${e}`))}severityBadge(e){switch(e.toUpperCase()){case"CRITICAL":return gt.severity.critical.bold(`${Xt.critical} CRITICAL`);case"HIGH":return gt.severity.high.bold(`${Xt.high} HIGH`);case"MEDIUM":return gt.severity.medium.bold(`${Xt.medium} MEDIUM`);case"LOW":return gt.severity.low.bold(`${Xt.low} LOW`);default:return gt.comment(e)}}divider(){console.log(gt.comment("\u2500".repeat(60)))}newline(){console.log("")}clearLine(){process.stdout.write(`\r${" ".repeat(process.stdout.columns)}\r`)}},Am=_S.getInstance()});var P8,L8=D(()=>{"use strict";P8=t=>t&&(t.Name||t.ResourceName||t.FunctionName)||"Unnamed"});var TS,O8,PS,M8=D(()=>{"use strict";dt();TS=null,O8=t=>{TS=t},PS=()=>{if(TS&&!process.env.CI)try{TS.saveToDisk(),ie.info("\u{1F4BE} Cache saved to disk on exit")}catch(t){ie.warn("\u26A0\uFE0F Could not save cache on exit",{error:t instanceof Error?t.message:String(t)})}};process.on("exit",PS);process.on("SIGINT",()=>{PS(),process.exit(0)});process.on("SIGTERM",()=>{PS(),process.exit(0)})});var Dee,Aee,wm,wee,Eee,Ree,Iee,B8,N8=D(()=>{"use strict";lS();JM();sS();yl();om();s8();hS();FS();dt();Qn();L8();M8();Dee={maxConcurrent:hl.DEFAULT_MAX_CONCURRENT,retryAttempts:hl.DEFAULT_RETRY_ATTEMPTS,retryDelay:hl.DEFAULT_RETRY_DELAY_MS,timeoutMs:hl.DEFAULT_TIMEOUT_MS},Aee=t=>{if(!(t instanceof Error))return!1;let e=t.message??"";return e.startsWith("Polling timed out")||e==="Analysis timeout"||e.toLowerCase().includes("timeout")},wm=(t,e)=>{let s=t.match(/^(.+?)(\s\([^)]+\))?$/);if(!s)return t;let[,n,r=""]=s;return`${Pc(e,n)}${r}`},wee=t=>{let e=dl({ttl:6e4,maxSize:1e3});return({analysisError:s,redactedId:n})=>{let r=s instanceof Error?s.message:"unknown",i=`${n}:${r}`,o=e.get(i)||0;return Aee(s)?{status:"timeout",redactedId:n}:(e.set(i,o+1),o>t.retryAttempts?{status:"skipped",redactedId:n}:{status:"fail",redactedId:n,error:s})}},Eee=({analyzeResource:t,redactionMapping:e,aggregatedResult:s,errorHandler:n,config:r,authToken:i,fingerprint:o,stackName:a,analysisCache:c,originalResources:u,relationships:l,aiModelId:d})=>async({redactedId:p,redactedResources:f,findingsByResource:m,progressTracker:g})=>{let h=m.get(p)||[],y=f[p];if(!y)return{status:"skipped",redactedId:p};let C=dS(p,y,i,o,[]),A=pS(C),w=e[p];if(!w)return{status:"skipped",redactedId:p};let N=w,L=()=>(s[N]||(s[N]={issues:[]}),s[N]),R=c.get(A);if(R){let k=(R.issues||[]).map(x=>({...x,resource:N,resourceId:N})),K=L();return K.issues.push(...na({existing:K.issues,incoming:k})),K.resourceName=R.resourceName,{status:"success",redactedId:p,resourceKey:N,remappedIssues:k,resourceName:R.resourceName}}let H=Pc(a,w),B=Pc("cdk-insights-stack",a),S=im(w,l,u),U={dependencies:S.dependencies.map(k=>wm(k,a)),dependents:S.dependents.map(k=>wm(k,a)),usageDescription:S.usageDescription};for(let k=1;k<=r.retryAttempts;k++)try{let K=await Promise.race([t(B,H,y,y.Type,i,o,h,g,U,d),new Promise((Y,J)=>setTimeout(()=>J(new Error("Analysis timeout")),r.timeoutMs))]);K.resourceId=N;let x=(K.issues||[]).map(Y=>({...Y,resource:N,resourceId:N})),v=L();return v.issues.push(...na({existing:v.issues,incoming:x})),v.resourceName=K.resourceName,c.set(A,K,C),{status:"success",redactedId:p,resourceKey:N,remappedIssues:x,resourceName:K.resourceName}}catch(K){if(k===r.retryAttempts)return n({analysisError:K,redactedId:p});await new Promise(x=>setTimeout(x,r.retryDelay*2**(k-1)))}return{status:"fail",redactedId:p,error:new Error("Max retries exceeded")}},Ree=async(t,e,s)=>{let n=Math.max(1,Math.floor(e)),r=0,i=Array.from({length:Math.min(n,t.length)}).map(async()=>{for(;r<t.length;){let o=r;r+=1;let a=t[o];await s(a)}});await Promise.allSettled(i)},Iee=10,B8=({analyzeResource:t,analyzeResourcesBatch:e,redactResources:s,config:n=Dee})=>async({stackName:r,resources:i,authToken:o,existingFindingsMap:a,pathToLogicalId:c,fingerprint:u,noCache:l=!1,cacheConfig:d,aiModelId:p,aiBatchSize:f})=>{let m={},g=[],h={startTime:Date.now(),processedCount:0,successCount:0,failureCount:0,timeoutCount:0},{redactedResources:y,mapping:b}=s(i),C=r8(a,b,c),A=new Map;for(let X of C){let re=A.get(X.resourceId);re?re.push(X):A.set(X.resourceId,[X])}let w=Object.keys(y),N=w.length,L=ta(i),R=new ym({ttl:d?.ttl||6*60*60*1e3,maxSize:d?.maxSize||5e3,disabled:l||!d?.enabled});O8(R);let H=wee(n),B=Eee({analyzeResource:t,redactionMapping:b,aggregatedResult:m,errorHandler:H,config:n,authToken:o,fingerprint:u,stackName:r,analysisCache:R,originalResources:i,relationships:L,aiModelId:p}),S=Am.createSingleLineProgressTracker(N,"Analyzing resources with AI"),U=Math.min(Math.max(1,Math.floor(f??1)),Iee);if(U>1&&!!e&&e){ie.debug("Batched analysis enabled",{batchSize:U,totalResources:N});let X=Pc("cdk-insights-stack",r),re=pe=>{let Ae=im(pe,L,i);return{dependencies:Ae.dependencies.map(we=>wm(we,r)),dependents:Ae.dependents.map(we=>wm(we,r)),usageDescription:Ae.usageDescription}};for(let pe=0;pe<w.length;pe+=U){let Ae=w.slice(pe,pe+U),we=async()=>{for(let z of Ae){let ae=await B({redactedId:z,redactedResources:y,findingsByResource:A,progressTracker:S});switch(h.processedCount++,ae.status){case"success":h.successCount++;break;case"timeout":h.timeoutCount++,g.push({redactedId:z,resourceData:y[z],resourceType:y[z].Type,existingFindings:A.get(z)||[]});break;case"fail":case"skipped":h.failureCount++;break}}},ue=new Map,Re=[];for(let z of Ae){let ae=y[z],q=b[z];if(!ae||!q){h.processedCount++,h.failureCount++;continue}let _=dS(z,ae,o,u,[]),le=pS(_),F=R.get(le);if(F){let ye=(F.issues||[]).map(I=>({...I,resource:q,resourceId:q}));m[q]||(m[q]={issues:[]});let Se=m[q];Se.issues.push(...na({existing:Se.issues,incoming:ye})),Se.resourceName=F.resourceName,h.processedCount++,h.successCount++;continue}let te=Pc(r,q);ue.set(te,{redactedId:z,originalResourceId:q,cacheKey:le,cacheComponents:_}),Re.push({stableResourceId:te,resourceData:ae,resourceType:ae.Type,context:re(q),existingFindings:A.get(z)||[]})}if(Re.length!==0)try{let z=await Promise.race([e(X,Re,o,u,p),new Promise((ae,q)=>setTimeout(()=>q(new Error("Analysis timeout")),n.timeoutMs))]);for(let[ae,q]of ue){let _=z.get(ae);if(h.processedCount++,!_){ie.warn(`Batched response missing entry for resource ${q.originalResourceId}`,{stableResourceId:ae,redactedId:q.redactedId}),h.failureCount++;continue}let le=(_.issues||[]).map(te=>({...te,resource:q.originalResourceId,resourceId:q.originalResourceId}));m[q.originalResourceId]||(m[q.originalResourceId]={issues:[]});let F=m[q.originalResourceId];F.issues.push(...na({existing:F.issues,incoming:le})),F.resourceName=_.resourceName,R.set(q.cacheKey,{resourceId:q.originalResourceId,issues:_.issues||[],resourceName:_.resourceName},q.cacheComponents),h.successCount++}}catch(z){ie.warn("Batched analysis call failed \u2014 falling back to per-resource for this chunk",{error:z instanceof Error?z.message:String(z),chunkSize:Ae.length}),await we()}}}else await Ree(w,n.maxConcurrent,async X=>{ie.debug(`Starting analysis for resource ${X}`,{redactedId:X,maxConcurrent:n.maxConcurrent});let re=await B({redactedId:X,redactedResources:y,findingsByResource:A,progressTracker:S});switch(h.processedCount++,ie.debug(`Resource ${X} analysis result: ${re.status}`,{redactedId:X,status:re.status,hasProgressTracker:!!S}),re.status){case"success":h.successCount++,ie.debug(`Resource ${X} completed successfully`,{redactedId:X,resourceKey:re.resourceKey});break;case"timeout":h.timeoutCount++,ie.warn(`Resource ${X} timed out`,{redactedId:X}),g.push({redactedId:X,resourceData:y[X],resourceType:y[X].Type,existingFindings:A.get(X)||[]});break;case"fail":case"skipped":h.failureCount++,ie.warn(`Resource ${X} failed or was skipped`,{redactedId:X,status:re.status});break}});let K=Date.now()-h.startTime,x=S.getStats();if(ie.debug("Analysis completed with progress tracker stats",{progressTrackerStats:x,performanceMetrics:h,totalTime:K,totalResources:N,maxConcurrent:n.maxConcurrent}),P.analysisComplete(K,h.successCount,h.failureCount,h.timeoutCount),h.failureCount>0||h.timeoutCount>0){P.newline(),P.info("\u{1F4CA} Performance Analysis:");let X=h.successCount>0?Math.round(K/1e3/h.successCount):0;P.comment(` \u23F1\uFE0F Average completion time: ${X}s`),P.comment(` \u{1F4CA} Success rate: ${(h.successCount/N*100).toFixed(1)}%`)}if(g.length>0){P.newline(),P.warning("\u23F0 Timed Out Resources:"),P.comment(` \u{1F4CB} Total timed out: ${g.length}`);for(let X of g){if(P.comment(` \u274C ${X.resourceType}: ${X.redactedId}`),X.resourceData?.Properties){let pe=X.resourceData.Properties,Ae=P8(pe);P.comment(` \u{1F4DD} Name: ${Ae}`)}X.existingFindings.length>0&&P.comment(` \u{1F50D} Existing findings: ${X.existingFindings.length}`),X.resourceData?.Metadata&&P.comment(" \u{1F4CD} Has metadata: Yes"),["AWS::CloudFormation::Stack","AWS::Serverless::Application","AWS::ECS::Service"].includes(X.resourceType)&&P.comment(" \u26A0\uFE0F Complex resource type - may require extended analysis time")}P.newline(),P.info("\u{1F4A1} Tip: Some resources are taking longer to analyze than expected."),P.comment(" This is normal for complex resources. The analysis will continue with the remaining resources."),P.warning(`Retrying ${g.length} resource${g.length===1?"":"s"} that need a little more time...`)}let v=new Set(Object.keys(m)),Y=new Set(Object.values(b)),J=Array.from(Y).filter(X=>!v.has(X)||!m[X]?.issues?.length);if(J.length>0){let X=R.getCachedResultsForResources(J),re=0;for(let[pe,Ae]of Array.from(X.entries())){if(m[pe]?.issues?.length>0)continue;let we=(Ae.issues||[]).map(ue=>({...ue,resource:pe,resourceId:pe}));we.length>0&&(m[pe]||(m[pe]={issues:[]}),m[pe].issues.push(...we),m[pe].resourceName=Ae.resourceName,re+=we.length)}re>0}return m}});var W8,kee,$8,_ee,Fee,LS,Oc,Mc,j8,U8,Tee,Pee,Lee,Bc,Em=D(()=>{"use strict";W8="1.41.0",kee={Security:"https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/",Reliability:"https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/","Performance Efficiency":"https://docs.aws.amazon.com/wellarchitected/latest/performance-efficiency-pillar/","Cost Optimization":"https://docs.aws.amazon.com/wellarchitected/latest/cost-optimization-pillar/","Operational Excellence":"https://docs.aws.amazon.com/wellarchitected/latest/operational-excellence-pillar/",Sustainability:"https://docs.aws.amazon.com/wellarchitected/latest/sustainability-pillar/"},$8=t=>t.toLowerCase().replace(/[^\w\s-]/g,"").trim().replace(/\s+/g,"-").replace(/-+/g,"-"),_ee=(t,e)=>{let s=0;if(s+=2e3,e){let n=Object.values(t).filter(r=>{let i=r.sources.cdkInsights?.issues??[],o=r.sources.cdkNag?.issues??[];return i.length>0||o.length>0});s+=n.length*100}for(let[,n]of Object.entries(t)){let r=n.sources.cdkInsights?.issues??[],i=n.sources.cdkNag?.issues??[];for(let o of[...r,...i])s+=o.issue.length,s+=o.recommendation?.length||0,s+=o.codeSnippet?.length||0,s+=500}return s},Fee=t=>t?t.split(`
|
|
177
|
+
`)}section(e,s=Xt.info){console.log(gt.primary.bold(`${s} ${e}`))}success(e,s=Xt.success){console.log(gt.success(`${s} ${e}`))}info(e,s=Xt.info){console.log(gt.info(`${s} ${e}`))}warning(e,s=Xt.warning){console.log(gt.warning(`${s} ${e}`))}error(e,s=Xt.error){console.log(gt.error(`${s} ${e}`))}comment(e,s=""){console.log(gt.comment(`${s} ${e}`))}phase1(e){console.log(gt.info(`${Xt.phase1} Phase 1: ${e}`))}phase2(e){console.log(gt.primary(`${Xt.phase2} Phase 2: ${e}`))}phase3(e){console.log(gt.secondary(`${Xt.phase3} Phase 3: ${e}`))}severityBadge(e){switch(e.toUpperCase()){case"CRITICAL":return gt.severity.critical.bold(`${Xt.critical} CRITICAL`);case"HIGH":return gt.severity.high.bold(`${Xt.high} HIGH`);case"MEDIUM":return gt.severity.medium.bold(`${Xt.medium} MEDIUM`);case"LOW":return gt.severity.low.bold(`${Xt.low} LOW`);default:return gt.comment(e)}}divider(){console.log(gt.comment("\u2500".repeat(60)))}newline(){console.log("")}clearLine(){process.stdout.write(`\r${" ".repeat(process.stdout.columns)}\r`)}},Am=_S.getInstance()});var P8,L8=D(()=>{"use strict";P8=t=>t&&(t.Name||t.ResourceName||t.FunctionName)||"Unnamed"});var TS,O8,PS,M8=D(()=>{"use strict";dt();TS=null,O8=t=>{TS=t},PS=()=>{if(TS&&!process.env.CI)try{TS.saveToDisk(),ie.info("\u{1F4BE} Cache saved to disk on exit")}catch(t){ie.warn("\u26A0\uFE0F Could not save cache on exit",{error:t instanceof Error?t.message:String(t)})}};process.on("exit",PS);process.on("SIGINT",()=>{PS(),process.exit(0)});process.on("SIGTERM",()=>{PS(),process.exit(0)})});var Dee,Aee,wm,wee,Eee,Ree,Iee,B8,N8=D(()=>{"use strict";lS();JM();sS();yl();om();s8();hS();FS();dt();Qn();L8();M8();Dee={maxConcurrent:hl.DEFAULT_MAX_CONCURRENT,retryAttempts:hl.DEFAULT_RETRY_ATTEMPTS,retryDelay:hl.DEFAULT_RETRY_DELAY_MS,timeoutMs:hl.DEFAULT_TIMEOUT_MS},Aee=t=>{if(!(t instanceof Error))return!1;let e=t.message??"";return e.startsWith("Polling timed out")||e==="Analysis timeout"||e.toLowerCase().includes("timeout")},wm=(t,e)=>{let s=t.match(/^(.+?)(\s\([^)]+\))?$/);if(!s)return t;let[,n,r=""]=s;return`${Pc(e,n)}${r}`},wee=t=>{let e=dl({ttl:6e4,maxSize:1e3});return({analysisError:s,redactedId:n})=>{let r=s instanceof Error?s.message:"unknown",i=`${n}:${r}`,o=e.get(i)||0;return Aee(s)?{status:"timeout",redactedId:n}:(e.set(i,o+1),o>t.retryAttempts?{status:"skipped",redactedId:n}:{status:"fail",redactedId:n,error:s})}},Eee=({analyzeResource:t,redactionMapping:e,aggregatedResult:s,errorHandler:n,config:r,authToken:i,fingerprint:o,stackName:a,analysisCache:c,originalResources:u,relationships:l,aiModelId:d})=>async({redactedId:p,redactedResources:f,findingsByResource:m,progressTracker:g})=>{let h=m.get(p)||[],y=f[p];if(!y)return{status:"skipped",redactedId:p};let C=dS(p,y,i,o,[]),A=pS(C),w=e[p];if(!w)return{status:"skipped",redactedId:p};let N=w,L=()=>(s[N]||(s[N]={issues:[]}),s[N]),R=c.get(A);if(R){let k=(R.issues||[]).map(x=>({...x,resource:N,resourceId:N})),K=L();return K.issues.push(...na({existing:K.issues,incoming:k})),K.resourceName=R.resourceName,{status:"success",redactedId:p,resourceKey:N,remappedIssues:k,resourceName:R.resourceName}}let H=Pc(a,w),B=Pc("cdk-insights-stack",a),S=im(w,l,u),U={dependencies:S.dependencies.map(k=>wm(k,a)),dependents:S.dependents.map(k=>wm(k,a)),usageDescription:S.usageDescription};for(let k=1;k<=r.retryAttempts;k++)try{let K=await Promise.race([t(B,H,y,y.Type,i,o,h,g,U,d),new Promise((Y,J)=>setTimeout(()=>J(new Error("Analysis timeout")),r.timeoutMs))]);K.resourceId=N;let x=(K.issues||[]).map(Y=>({...Y,resource:N,resourceId:N})),v=L();return v.issues.push(...na({existing:v.issues,incoming:x})),v.resourceName=K.resourceName,c.set(A,K,C),{status:"success",redactedId:p,resourceKey:N,remappedIssues:x,resourceName:K.resourceName}}catch(K){if(k===r.retryAttempts)return n({analysisError:K,redactedId:p});await new Promise(x=>setTimeout(x,r.retryDelay*2**(k-1)))}return{status:"fail",redactedId:p,error:new Error("Max retries exceeded")}},Ree=async(t,e,s)=>{let n=Math.max(1,Math.floor(e)),r=0,i=Array.from({length:Math.min(n,t.length)}).map(async()=>{for(;r<t.length;){let o=r;r+=1;let a=t[o];await s(a)}});await Promise.allSettled(i)},Iee=10,B8=({analyzeResource:t,analyzeResourcesBatch:e,redactResources:s,config:n=Dee})=>async({stackName:r,resources:i,authToken:o,existingFindingsMap:a,pathToLogicalId:c,fingerprint:u,noCache:l=!1,cacheConfig:d,aiModelId:p,aiBatchSize:f})=>{let m={},g=[],h={startTime:Date.now(),processedCount:0,successCount:0,failureCount:0,timeoutCount:0},{redactedResources:y,mapping:b}=s(i),C=r8(a,b,c),A=new Map;for(let X of C){let re=A.get(X.resourceId);re?re.push(X):A.set(X.resourceId,[X])}let w=Object.keys(y),N=w.length,L=ta(i),R=new ym({ttl:d?.ttl||6*60*60*1e3,maxSize:d?.maxSize||5e3,disabled:l||!d?.enabled});O8(R);let H=wee(n),B=Eee({analyzeResource:t,redactionMapping:b,aggregatedResult:m,errorHandler:H,config:n,authToken:o,fingerprint:u,stackName:r,analysisCache:R,originalResources:i,relationships:L,aiModelId:p}),S=Am.createSingleLineProgressTracker(N,"Analyzing resources with AI"),U=Math.min(Math.max(1,Math.floor(f??1)),Iee);if(U>1&&!!e&&e){ie.debug("Batched analysis enabled",{batchSize:U,totalResources:N});let X=Pc("cdk-insights-stack",r),re=pe=>{let Ae=im(pe,L,i);return{dependencies:Ae.dependencies.map(we=>wm(we,r)),dependents:Ae.dependents.map(we=>wm(we,r)),usageDescription:Ae.usageDescription}};for(let pe=0;pe<w.length;pe+=U){let Ae=w.slice(pe,pe+U),we=async()=>{for(let z of Ae){let ae=await B({redactedId:z,redactedResources:y,findingsByResource:A,progressTracker:S});switch(h.processedCount++,ae.status){case"success":h.successCount++;break;case"timeout":h.timeoutCount++,g.push({redactedId:z,resourceData:y[z],resourceType:y[z].Type,existingFindings:A.get(z)||[]});break;case"fail":case"skipped":h.failureCount++;break}}},ue=new Map,Re=[];for(let z of Ae){let ae=y[z],q=b[z];if(!ae||!q){h.processedCount++,h.failureCount++;continue}let _=dS(z,ae,o,u,[]),le=pS(_),F=R.get(le);if(F){let ye=(F.issues||[]).map(I=>({...I,resource:q,resourceId:q}));m[q]||(m[q]={issues:[]});let Se=m[q];Se.issues.push(...na({existing:Se.issues,incoming:ye})),Se.resourceName=F.resourceName,h.processedCount++,h.successCount++;continue}let te=Pc(r,q);ue.set(te,{redactedId:z,originalResourceId:q,cacheKey:le,cacheComponents:_}),Re.push({stableResourceId:te,resourceData:ae,resourceType:ae.Type,context:re(q),existingFindings:A.get(z)||[]})}if(Re.length!==0)try{let z=await Promise.race([e(X,Re,o,u,p),new Promise((ae,q)=>setTimeout(()=>q(new Error("Analysis timeout")),n.timeoutMs))]);for(let[ae,q]of ue){let _=z.get(ae);if(h.processedCount++,!_){ie.warn(`Batched response missing entry for resource ${q.originalResourceId}`,{stableResourceId:ae,redactedId:q.redactedId}),h.failureCount++;continue}let le=(_.issues||[]).map(te=>({...te,resource:q.originalResourceId,resourceId:q.originalResourceId}));m[q.originalResourceId]||(m[q.originalResourceId]={issues:[]});let F=m[q.originalResourceId];F.issues.push(...na({existing:F.issues,incoming:le})),F.resourceName=_.resourceName,R.set(q.cacheKey,{resourceId:q.originalResourceId,issues:_.issues||[],resourceName:_.resourceName},q.cacheComponents),h.successCount++}}catch(z){ie.warn("Batched analysis call failed \u2014 falling back to per-resource for this chunk",{error:z instanceof Error?z.message:String(z),chunkSize:Ae.length}),await we()}}}else await Ree(w,n.maxConcurrent,async X=>{ie.debug(`Starting analysis for resource ${X}`,{redactedId:X,maxConcurrent:n.maxConcurrent});let re=await B({redactedId:X,redactedResources:y,findingsByResource:A,progressTracker:S});switch(h.processedCount++,ie.debug(`Resource ${X} analysis result: ${re.status}`,{redactedId:X,status:re.status,hasProgressTracker:!!S}),re.status){case"success":h.successCount++,ie.debug(`Resource ${X} completed successfully`,{redactedId:X,resourceKey:re.resourceKey});break;case"timeout":h.timeoutCount++,ie.warn(`Resource ${X} timed out`,{redactedId:X}),g.push({redactedId:X,resourceData:y[X],resourceType:y[X].Type,existingFindings:A.get(X)||[]});break;case"fail":case"skipped":h.failureCount++,ie.warn(`Resource ${X} failed or was skipped`,{redactedId:X,status:re.status});break}});let K=Date.now()-h.startTime,x=S.getStats();if(ie.debug("Analysis completed with progress tracker stats",{progressTrackerStats:x,performanceMetrics:h,totalTime:K,totalResources:N,maxConcurrent:n.maxConcurrent}),P.analysisComplete(K,h.successCount,h.failureCount,h.timeoutCount),h.failureCount>0||h.timeoutCount>0){P.newline(),P.info("\u{1F4CA} Performance Analysis:");let X=h.successCount>0?Math.round(K/1e3/h.successCount):0;P.comment(` \u23F1\uFE0F Average completion time: ${X}s`),P.comment(` \u{1F4CA} Success rate: ${(h.successCount/N*100).toFixed(1)}%`)}if(g.length>0){P.newline(),P.warning("\u23F0 Timed Out Resources:"),P.comment(` \u{1F4CB} Total timed out: ${g.length}`);for(let X of g){if(P.comment(` \u274C ${X.resourceType}: ${X.redactedId}`),X.resourceData?.Properties){let pe=X.resourceData.Properties,Ae=P8(pe);P.comment(` \u{1F4DD} Name: ${Ae}`)}X.existingFindings.length>0&&P.comment(` \u{1F50D} Existing findings: ${X.existingFindings.length}`),X.resourceData?.Metadata&&P.comment(" \u{1F4CD} Has metadata: Yes"),["AWS::CloudFormation::Stack","AWS::Serverless::Application","AWS::ECS::Service"].includes(X.resourceType)&&P.comment(" \u26A0\uFE0F Complex resource type - may require extended analysis time")}P.newline(),P.info("\u{1F4A1} Tip: Some resources are taking longer to analyze than expected."),P.comment(" This is normal for complex resources. The analysis will continue with the remaining resources."),P.warning(`Retrying ${g.length} resource${g.length===1?"":"s"} that need a little more time...`)}let v=new Set(Object.keys(m)),Y=new Set(Object.values(b)),J=Array.from(Y).filter(X=>!v.has(X)||!m[X]?.issues?.length);if(J.length>0){let X=R.getCachedResultsForResources(J),re=0;for(let[pe,Ae]of Array.from(X.entries())){if(m[pe]?.issues?.length>0)continue;let we=(Ae.issues||[]).map(ue=>({...ue,resource:pe,resourceId:pe}));we.length>0&&(m[pe]||(m[pe]={issues:[]}),m[pe].issues.push(...we),m[pe].resourceName=Ae.resourceName,re+=we.length)}re>0}return m}});var W8,kee,$8,_ee,Fee,LS,Oc,Mc,j8,U8,Tee,Pee,Lee,Bc,Em=D(()=>{"use strict";W8="1.41.1",kee={Security:"https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/",Reliability:"https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/","Performance Efficiency":"https://docs.aws.amazon.com/wellarchitected/latest/performance-efficiency-pillar/","Cost Optimization":"https://docs.aws.amazon.com/wellarchitected/latest/cost-optimization-pillar/","Operational Excellence":"https://docs.aws.amazon.com/wellarchitected/latest/operational-excellence-pillar/",Sustainability:"https://docs.aws.amazon.com/wellarchitected/latest/sustainability-pillar/"},$8=t=>t.toLowerCase().replace(/[^\w\s-]/g,"").trim().replace(/\s+/g,"-").replace(/-+/g,"-"),_ee=(t,e)=>{let s=0;if(s+=2e3,e){let n=Object.values(t).filter(r=>{let i=r.sources.cdkInsights?.issues??[],o=r.sources.cdkNag?.issues??[];return i.length>0||o.length>0});s+=n.length*100}for(let[,n]of Object.entries(t)){let r=n.sources.cdkInsights?.issues??[],i=n.sources.cdkNag?.issues??[];for(let o of[...r,...i])s+=o.issue.length,s+=o.recommendation?.length||0,s+=o.codeSnippet?.length||0,s+=500}return s},Fee=t=>t?t.split(`
|
|
178
178
|
`).map(e=>e.trim()).filter(Boolean).join(`
|
|
179
179
|
`):"",LS=t=>{let e=`- **Issue:** ${t.issue}`;return t.recommendation&&(e+=`
|
|
180
180
|
- **Recommendation:** ${Fee(t.recommendation)}`),t.context&&(t.context.property&&(e+=`
|
|
@@ -296,7 +296,7 @@ ${o}`)}});var Z8,Y8,J8=D(()=>{"use strict";Z8=require("node:child_process"),Y8=(
|
|
|
296
296
|
`)}catch(a){console.error("Failed to write GitHub outputs:",a)}}});var km,f4,m4=D(()=>{"use strict";dt();km=t=>{switch(t.toUpperCase()){case"CRITICAL":return"\u{1F534}";case"HIGH":return"\u{1F7E0}";case"MEDIUM":return"\u{1F7E1}";case"LOW":return"\u{1F7E2}";default:return"\u26AA"}},f4=(t,e)=>{Me.info(`
|
|
297
297
|
\u{1F4DD} Analysis Summary for stack: ${t}`),Me.info(`Total Resources Scanned: ${e.totalResources}`),Me.info(`Resources with Issues: ${e.resourcesWithIssues} (${e.percentWithIssues}%)`),Me.info(`Total Issues Found: ${e.totalIssues}
|
|
298
298
|
`),Me.info("Severity Breakdown:"),Me.info(` ${km("CRITICAL")} Critical: ${e.severityCounts.CRITICAL}`),Me.info(` ${km("HIGH")} High: ${e.severityCounts.HIGH}`),Me.info(` ${km("MEDIUM")} Medium: ${e.severityCounts.MEDIUM}`),Me.info(` ${km("LOW")} Low: ${e.severityCounts.LOW}
|
|
299
|
-
`),Me.info("WAF Pillar Impact:");for(let[s,n]of Object.entries(e.wafIssues))Me.info(` ${s}: ${n}`);Me.info(""),Me.info("Top Priorities:"),e.severityCounts.CRITICAL>0&&Me.info(" \u{1F534} Address Critical issues immediately (highest risk)"),e.severityCounts.HIGH>0&&Me.info(" \u{1F7E0} Then handle High-severity issues"),e.severityCounts.MEDIUM>0&&Me.info(" \u{1F7E1} Schedule Medium-severity tasks soon"),e.severityCounts.LOW>0&&Me.info(" \u{1F7E2} Plan Low-severity enhancements at your convenience"),Me.info("")}});var Xee,ete,tte,h4,El,US=D(()=>{"use strict";Xee=u0(),ete=t=>{switch(t){case"CRITICAL":return"\u{1F534}";case"HIGH":return"\u{1F536}";case"MEDIUM":return"\u{1F7E1}";case"LOW":return"\u{1F7E2}";default:return"\u26AA"}},tte=(t,e)=>{let s=t.sourceLocation||e?.sourceLocation;if(s){let{filePath:n,line:r,column:i,confidence:o}=s,a=o==="high"?"\u{1F3AF}":o==="medium"?"\u{1F4CD}":"\u2753",c=n.length>40?`...${n.slice(-37)}`:n;return`${a} ${c}:${r}:${i}`}if(e?.rootSourceLocation){let{filePath:n,line:r,column:i}=e.rootSourceLocation;return`\u{1F517} ${n.length>40?`...${n.slice(-37)}`:n}:${r}:${i}`}return e?.createdBy?`\u{1F517} ${e.createdBy.length>28?`${e.createdBy.slice(0,25)}...`:e.createdBy}`:""},h4={CRITICAL:4,HIGH:3,MEDIUM:2,LOW:1},El=t=>{let e=new Xee({head:["Resource","Stack","Severity","Service","Issue","Location"],colWidths:[20,15,10,15,40,30],wordWrap:!0}),s=[];for(let[,n]of Object.entries(t)){let r=[...n.sources?.cdkInsights?.issues??[],...n.sources?.cdkNag?.issues??[]];for(let i of r){let o=i.constructType||n.constructType||n.type||"Unknown",a=tte(i,n);s.push({issue:i,group:n,service:o,sourceLocation:a})}}s.sort((n,r)=>{let i=h4[n.issue.severity]||0;return(h4[r.issue.severity]||0)-i});for(let{issue:n,group:r,service:i,sourceLocation:o}of s)e.push([r.friendlyName||r.resourceId,n.stackName||"Unknown",`${ete(n.severity)} ${n.severity}`,i,n.issue,o||n.locationHint||""]);console.log(e.toString())}});var Rl=M((B_e,ste)=>{ste.exports={name:"cdk-insights",version:"1.41.0",description:"AWS CDK security and cost analysis CLI. Free static scans via npm \u2014 no account needed. Sign up free to add AI-powered insights.",main:"dist/index.js",types:"dist/index.d.ts",bin:{"cdk-insights":"dist/entry.js"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js",require:"./dist/index.js"}},files:["dist/**/*","README.md","LICENSE"],scripts:{test:"vitest --run",lint:"biome lint src/",typecheck:"tsc --noEmit",format:"biome format --write src/",check:"biome check src/","check:schema-sync":"ts-node scripts/check-schema-sync.ts",build:"ts-node scripts/build.ts","build:dev":"CDK_INSIGHTS_ENVIRONMENT=dev CDK_INSIGHTS_API_URL=https://s2zhmjbwlj.execute-api.eu-west-2.amazonaws.com/v1 ts-node scripts/build.ts",start:"node dist/index.js",dev:"ts-node src/index.ts",prepare:"husky install && npm run build","start:dev":"CDK_ENV=local ts-node src/index.ts","ai-run":"ts-node src/index.ts",unlink:"npm unlink -g cdk-insights",link:"npm link","prepare:test":"npm run unlink && npm run build && npm run link","prepare:dev":"npm run unlink && npm run build:dev && npm run link","deploy:dev":"STAGE=dev cdk deploy","destroy:dev":"STAGE=dev cdk destroy","release:patch":"bumper release patch","release:minor":"bumper release minor","release:major":"bumper release major","release:dry-run":"bumper release patch --dry-run","changelog:preview":"bumper preview","changelog:generate":"bumper generate","validate:commits":"bumper validate","release:check":"npm run validate:commits && npm run test && npm run build","release:full":"npm run release:check && npm run changelog:generate","setup:bumper":"bumper setup","publish:beta":"npm run build && npm publish --tag beta && npm dist-tag add cdk-insights@$npm_package_version latest","publish:alpha":"npm run build && npm publish --tag alpha","publish:canary":"npm run build && npm publish --tag canary","publish:latest":"npm run build && npm publish --tag latest","version:beta":"npm version prerelease --preid=beta","version:alpha":"npm version prerelease --preid=alpha","version:rc":"npm version prerelease --preid=rc","cdk-insights":"node scripts/cdk-insights-wrapper.js",scan:"node scripts/cdk-insights-wrapper.js scan","scan:all":"node scripts/cdk-insights-wrapper.js scan --all","scan:json":"node scripts/cdk-insights-wrapper.js scan --format json","scan:markdown":"node scripts/cdk-insights-wrapper.js scan --format markdown","scan:summary":"node scripts/cdk-insights-wrapper.js scan --format summary","scan:with-issues":"node scripts/cdk-insights-wrapper.js scan --withIssue","cache:clear":"node scripts/cdk-insights-wrapper.js cache clear","cache:status":"node scripts/cdk-insights-wrapper.js cache status","demo:progress":"ts-node src/examples/progress-demo.ts","demo:single-line":"ts-node src/examples/single-line-progress-demo.ts","test:line-clearing":"ts-node src/examples/line-clearing-test.ts"},publishConfig:{access:"public"},keywords:["aws","cdk","cloudformation","analysis","security","cost-optimization","static-analysis","devops","infrastructure","aws-cdk","cloud-security","compliance"],author:"Lee Priest <lee@cdkinsights.dev>",license:"BUSL-1.1",homepage:"https://github.com/instancelabs/cdk-insights",bugs:"https://github.com/instancelabs/cdk-insights/issues",repository:{type:"git",url:"git+https://github.com/instancelabs/cdk-insights.git"},dependencies:{"@inquirer/prompts":"^7.4.1","@middy/core":"^6.1.6","@types/glob":"^8.1.0",axios:"^1.8.4",chalk:"^5.4.1",chokidar:"^3.6.0","cli-progress":"^3.12.0","cli-table3":"^0.6.5",dotenv:"^16.5.0",envolution:"^1.4.1",glob:"^11.0.3",ora:"^8.2.0",strogger:"^2.0.3",yargs:"^17.7.2",zod:"^3.23.8"},devDependencies:{"@aws-sdk/client-dynamodb":"^3.788.0","@biomejs/biome":"^2.0.6","@commitlint/cli":"^19.8.1","@commitlint/config-conventional":"^19.8.1","@types/cli-progress":"^3.11.6","@types/jsonwebtoken":"^9.0.9","@types/node":"^22.14.1","@types/yargs":"^17.0.33","aws-cdk":"^2.1010.0","bumper-cli":"^1.6.0",esbuild:"^0.25.2",husky:"^8.0.3","ts-node":"^10.9.2",typescript:"^5.8.3",vitest:"^3.1.1"},peerDependencies:{"@aws-solutions-constructs/aws-apigateway-lambda":"^2.0.0","@aws-solutions-constructs/aws-lambda-stepfunctions":"^2.0.0","@aws-solutions-constructs/aws-s3-lambda":"^2.0.0","aws-cdk-lib":"^2.190.0","cdk-nag":"^2.35.73",constructs:"^10.4.2"},peerDependenciesMeta:{"@aws-solutions-constructs/aws-apigateway-lambda":{optional:!0},"@aws-solutions-constructs/aws-lambda-stepfunctions":{optional:!0},"@aws-solutions-constructs/aws-s3-lambda":{optional:!0}}}});var y4,nte,g4,rte,x4,b4=D(()=>{"use strict";y4=oe(require("node:fs"));dt();yl();({version:nte}=Rl()),g4={CRITICAL:0,HIGH:1,MEDIUM:2,LOW:3},rte=(t,e,s)=>{let n=Object.entries(s).map(([r,i])=>{let o=[...i.sources?.cdkInsights?.issues??[],...i.sources?.cdkNag?.issues??[]].slice().sort((c,u)=>g4[c.severity]-g4[u.severity]),a=bm(o,i.cdkPath);return{resourceId:i.resourceId,logicalId:i.logicalId,cdkName:i.friendlyName,resourceName:i.resourceName,cdkPath:i.cdkPath,githubUrl:i.githubUrl,docUrl:i.docUrl,constructType:i.constructType,parentPath:i.parentPath,childCount:i.childCount,tags:i.tags,sourceLocation:i.sourceLocation,constructHierarchy:i.constructHierarchy,serviceCategory:i.serviceCategory,dependencies:i.dependencies,sensitiveProperties:i.sensitiveProperties,usesDefaults:i.usesDefaults,l2ConstructType:i.l2ConstructType,l2ConstructId:i.l2ConstructId,createdBy:i.createdBy,rootSourceLocation:i.rootSourceLocation,searchHint:i.searchHint,issues:a.map(c=>({issue:c.issue,recommendation:c.recommendation,severity:c.severity,wafPillar:c.wafPillar,codeSnippet:c.codeSnippet,locationHint:c.locationHint,foundBy:c.foundBy,sourceLocation:c.sourceLocation,stackName:c.stackName}))}});return{stackName:t,generatedAt:new Date().toISOString(),version:nte,summary:e,recommendations:n}},x4=(t,e,s)=>{let n=rte(t,e,s),r=`${t}_analysis_report.json`;try{y4.writeFileSync(r,JSON.stringify(n,null,2),"utf-8"),Me.info(`\u{1F4C4} JSON report written to ${r}`)}catch(i){let o=i instanceof Error?i.message:String(i);throw Me.error(`\u274C Failed to write JSON report to ${r}: ${o}`),new Error(`Failed to write analysis report: ${o}`)}return n}});var ite,ote,S4,_m,ate,HS=D(()=>{"use strict";({version:ite}=Rl()),ote=t=>{switch(t){case"CRITICAL":case"HIGH":return"error";case"MEDIUM":return"warning";default:return"note"}},S4=t=>{switch(t){case"CRITICAL":return 9;case"HIGH":return 7;case"MEDIUM":return 4;case"LOW":return 2;default:return 1}},_m=(t,e)=>{let s=[],n=[],r=new Set;for(let[i,o]of Object.entries(e)){let a=[...o.sources?.cdkInsights?.issues||[],...o.sources?.cdkNag?.issues||[]];for(let c of a){let u=ate(c);r.has(u)||(r.add(u),s.push({id:u,name:c.issue.slice(0,100),shortDescription:{text:c.issue},fullDescription:c.recommendation?{text:c.recommendation}:void 0,helpUri:c.docUrl||c.githubUrl,properties:{"security-severity":S4(c.severity).toString(),tags:[c.wafPillar,c.severity,c.foundBy].filter(Boolean)}}));let d=(c.sourceLocation?.frames?.slice(1)??[]).map(p=>({physicalLocation:{artifactLocation:{uri:p.filePath,uriBaseId:"%SRCROOT%"},region:{startLine:p.line,startColumn:p.column}},message:{text:p.kind==="property"&&p.propertyName?`Property set: ${p.propertyName}`:p.kind==="creation"?"Construct created here":"Related call site"}}));n.push({ruleId:u,level:ote(c.severity),message:{text:c.recommendation||c.issue},locations:[{physicalLocation:{artifactLocation:{uri:c.sourceLocation?.filePath||`cdk.out/${t}.template.json`,uriBaseId:"%SRCROOT%"},region:c.sourceLocation?{startLine:c.sourceLocation.line,startColumn:c.sourceLocation.column}:void 0}}],...d.length>0?{relatedLocations:d}:{},properties:{"security-severity":S4(c.severity).toString(),wafPillar:c.wafPillar,recommendation:c.recommendation}})}}return{$schema:"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",version:"2.1.0",runs:[{tool:{driver:{name:"cdk-insights",version:ite,informationUri:"https://cdkinsights.dev",rules:s}},results:n}]}},ate=t=>{let e=t.issue.toLowerCase().replace(/[^a-z0-9]+/g,"-").slice(0,50);return`CDK-${t.severity}-${e}`}});var GS,v4,C4=D(()=>{"use strict";GS=oe(require("node:fs"));dt();Em();m4();US();b4();HS();jS();v4=(t,e,s,n,r)=>{switch(Me.info(`Generating output in format: ${t}`),t){case"markdown":{let i=Bc(e,s,r,n),o=`${e}_analysis_report.md`;try{GS.writeFileSync(o,i),Me.info(`\u{1F4C4} Saved Markdown report to ${o}`)}catch(a){let c=a instanceof Error?a.message:String(a);throw Me.error(`\u274C Failed to write Markdown report to ${o}: ${c}`),new Error(`Failed to write Markdown report: ${c}`)}break}case"table":{El(s);break}case"json":{let i=x4(e,r,s);process.stdout.write(`${JSON.stringify(i,null,2)}
|
|
299
|
+
`),Me.info("WAF Pillar Impact:");for(let[s,n]of Object.entries(e.wafIssues))Me.info(` ${s}: ${n}`);Me.info(""),Me.info("Top Priorities:"),e.severityCounts.CRITICAL>0&&Me.info(" \u{1F534} Address Critical issues immediately (highest risk)"),e.severityCounts.HIGH>0&&Me.info(" \u{1F7E0} Then handle High-severity issues"),e.severityCounts.MEDIUM>0&&Me.info(" \u{1F7E1} Schedule Medium-severity tasks soon"),e.severityCounts.LOW>0&&Me.info(" \u{1F7E2} Plan Low-severity enhancements at your convenience"),Me.info("")}});var Xee,ete,tte,h4,El,US=D(()=>{"use strict";Xee=u0(),ete=t=>{switch(t){case"CRITICAL":return"\u{1F534}";case"HIGH":return"\u{1F536}";case"MEDIUM":return"\u{1F7E1}";case"LOW":return"\u{1F7E2}";default:return"\u26AA"}},tte=(t,e)=>{let s=t.sourceLocation||e?.sourceLocation;if(s){let{filePath:n,line:r,column:i,confidence:o}=s,a=o==="high"?"\u{1F3AF}":o==="medium"?"\u{1F4CD}":"\u2753",c=n.length>40?`...${n.slice(-37)}`:n;return`${a} ${c}:${r}:${i}`}if(e?.rootSourceLocation){let{filePath:n,line:r,column:i}=e.rootSourceLocation;return`\u{1F517} ${n.length>40?`...${n.slice(-37)}`:n}:${r}:${i}`}return e?.createdBy?`\u{1F517} ${e.createdBy.length>28?`${e.createdBy.slice(0,25)}...`:e.createdBy}`:""},h4={CRITICAL:4,HIGH:3,MEDIUM:2,LOW:1},El=t=>{let e=new Xee({head:["Resource","Stack","Severity","Service","Issue","Location"],colWidths:[20,15,10,15,40,30],wordWrap:!0}),s=[];for(let[,n]of Object.entries(t)){let r=[...n.sources?.cdkInsights?.issues??[],...n.sources?.cdkNag?.issues??[]];for(let i of r){let o=i.constructType||n.constructType||n.type||"Unknown",a=tte(i,n);s.push({issue:i,group:n,service:o,sourceLocation:a})}}s.sort((n,r)=>{let i=h4[n.issue.severity]||0;return(h4[r.issue.severity]||0)-i});for(let{issue:n,group:r,service:i,sourceLocation:o}of s)e.push([r.friendlyName||r.resourceId,n.stackName||"Unknown",`${ete(n.severity)} ${n.severity}`,i,n.issue,o||n.locationHint||""]);console.log(e.toString())}});var Rl=M((B_e,ste)=>{ste.exports={name:"cdk-insights",version:"1.41.1",description:"AWS CDK security and cost analysis CLI. Free static scans via npm \u2014 no account needed. Sign up free to add AI-powered insights.",main:"dist/index.js",types:"dist/index.d.ts",bin:{"cdk-insights":"dist/entry.js"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js",require:"./dist/index.js"}},files:["dist/**/*","README.md","LICENSE"],scripts:{test:"vitest --run",lint:"biome lint src/",typecheck:"tsc --noEmit",format:"biome format --write src/",check:"biome check src/","check:schema-sync":"ts-node scripts/check-schema-sync.ts",build:"ts-node scripts/build.ts","build:dev":"CDK_INSIGHTS_ENVIRONMENT=dev CDK_INSIGHTS_API_URL=https://s2zhmjbwlj.execute-api.eu-west-2.amazonaws.com/v1 ts-node scripts/build.ts",start:"node dist/index.js",dev:"ts-node src/index.ts",prepare:"husky install && npm run build","start:dev":"CDK_ENV=local ts-node src/index.ts","ai-run":"ts-node src/index.ts",unlink:"npm unlink -g cdk-insights",link:"npm link","prepare:test":"npm run unlink && npm run build && npm run link","prepare:dev":"npm run unlink && npm run build:dev && npm run link","deploy:dev":"STAGE=dev cdk deploy","destroy:dev":"STAGE=dev cdk destroy","release:patch":"bumper release patch","release:minor":"bumper release minor","release:major":"bumper release major","release:dry-run":"bumper release patch --dry-run","changelog:preview":"bumper preview","changelog:generate":"bumper generate","validate:commits":"bumper validate","release:check":"npm run validate:commits && npm run test && npm run build","release:full":"npm run release:check && npm run changelog:generate","setup:bumper":"bumper setup","publish:beta":"npm run build && npm publish --tag beta && npm dist-tag add cdk-insights@$npm_package_version latest","publish:alpha":"npm run build && npm publish --tag alpha","publish:canary":"npm run build && npm publish --tag canary","publish:latest":"npm run build && npm publish --tag latest","version:beta":"npm version prerelease --preid=beta","version:alpha":"npm version prerelease --preid=alpha","version:rc":"npm version prerelease --preid=rc","cdk-insights":"node scripts/cdk-insights-wrapper.js",scan:"node scripts/cdk-insights-wrapper.js scan","scan:all":"node scripts/cdk-insights-wrapper.js scan --all","scan:json":"node scripts/cdk-insights-wrapper.js scan --format json","scan:markdown":"node scripts/cdk-insights-wrapper.js scan --format markdown","scan:summary":"node scripts/cdk-insights-wrapper.js scan --format summary","scan:with-issues":"node scripts/cdk-insights-wrapper.js scan --withIssue","cache:clear":"node scripts/cdk-insights-wrapper.js cache clear","cache:status":"node scripts/cdk-insights-wrapper.js cache status","demo:progress":"ts-node src/examples/progress-demo.ts","demo:single-line":"ts-node src/examples/single-line-progress-demo.ts","test:line-clearing":"ts-node src/examples/line-clearing-test.ts"},publishConfig:{access:"public"},keywords:["aws","cdk","cloudformation","analysis","security","cost-optimization","static-analysis","devops","infrastructure","aws-cdk","cloud-security","compliance"],author:"Lee Priest <lee@cdkinsights.dev>",license:"BUSL-1.1",homepage:"https://github.com/instancelabs/cdk-insights",bugs:"https://github.com/instancelabs/cdk-insights/issues",repository:{type:"git",url:"git+https://github.com/instancelabs/cdk-insights.git"},dependencies:{"@inquirer/prompts":"^7.4.1","@middy/core":"^6.1.6","@types/glob":"^8.1.0",axios:"^1.8.4",chalk:"^5.4.1",chokidar:"^3.6.0","cli-progress":"^3.12.0","cli-table3":"^0.6.5",dotenv:"^16.5.0",envolution:"^1.4.1",glob:"^11.0.3",ora:"^8.2.0",strogger:"^2.0.3",yargs:"^17.7.2",zod:"^3.23.8"},devDependencies:{"@aws-sdk/client-dynamodb":"^3.788.0","@biomejs/biome":"^2.0.6","@commitlint/cli":"^19.8.1","@commitlint/config-conventional":"^19.8.1","@types/cli-progress":"^3.11.6","@types/jsonwebtoken":"^9.0.9","@types/node":"^22.14.1","@types/yargs":"^17.0.33","aws-cdk":"^2.1010.0","bumper-cli":"^1.6.0",esbuild:"^0.25.2",husky:"^8.0.3","ts-node":"^10.9.2",typescript:"^5.8.3",vitest:"^3.1.1"},peerDependencies:{"@aws-solutions-constructs/aws-apigateway-lambda":"^2.0.0","@aws-solutions-constructs/aws-lambda-stepfunctions":"^2.0.0","@aws-solutions-constructs/aws-s3-lambda":"^2.0.0","aws-cdk-lib":"^2.190.0","cdk-nag":"^2.35.73",constructs:"^10.4.2"},peerDependenciesMeta:{"@aws-solutions-constructs/aws-apigateway-lambda":{optional:!0},"@aws-solutions-constructs/aws-lambda-stepfunctions":{optional:!0},"@aws-solutions-constructs/aws-s3-lambda":{optional:!0}}}});var y4,nte,g4,rte,x4,b4=D(()=>{"use strict";y4=oe(require("node:fs"));dt();yl();({version:nte}=Rl()),g4={CRITICAL:0,HIGH:1,MEDIUM:2,LOW:3},rte=(t,e,s)=>{let n=Object.entries(s).map(([r,i])=>{let o=[...i.sources?.cdkInsights?.issues??[],...i.sources?.cdkNag?.issues??[]].slice().sort((c,u)=>g4[c.severity]-g4[u.severity]),a=bm(o,i.cdkPath);return{resourceId:i.resourceId,logicalId:i.logicalId,cdkName:i.friendlyName,resourceName:i.resourceName,cdkPath:i.cdkPath,githubUrl:i.githubUrl,docUrl:i.docUrl,constructType:i.constructType,parentPath:i.parentPath,childCount:i.childCount,tags:i.tags,sourceLocation:i.sourceLocation,constructHierarchy:i.constructHierarchy,serviceCategory:i.serviceCategory,dependencies:i.dependencies,sensitiveProperties:i.sensitiveProperties,usesDefaults:i.usesDefaults,l2ConstructType:i.l2ConstructType,l2ConstructId:i.l2ConstructId,createdBy:i.createdBy,rootSourceLocation:i.rootSourceLocation,searchHint:i.searchHint,issues:a.map(c=>({issue:c.issue,recommendation:c.recommendation,severity:c.severity,wafPillar:c.wafPillar,codeSnippet:c.codeSnippet,locationHint:c.locationHint,foundBy:c.foundBy,sourceLocation:c.sourceLocation,stackName:c.stackName}))}});return{stackName:t,generatedAt:new Date().toISOString(),version:nte,summary:e,recommendations:n}},x4=(t,e,s)=>{let n=rte(t,e,s),r=`${t}_analysis_report.json`;try{y4.writeFileSync(r,JSON.stringify(n,null,2),"utf-8"),Me.info(`\u{1F4C4} JSON report written to ${r}`)}catch(i){let o=i instanceof Error?i.message:String(i);throw Me.error(`\u274C Failed to write JSON report to ${r}: ${o}`),new Error(`Failed to write analysis report: ${o}`)}return n}});var ite,ote,S4,_m,ate,HS=D(()=>{"use strict";({version:ite}=Rl()),ote=t=>{switch(t){case"CRITICAL":case"HIGH":return"error";case"MEDIUM":return"warning";default:return"note"}},S4=t=>{switch(t){case"CRITICAL":return 9;case"HIGH":return 7;case"MEDIUM":return 4;case"LOW":return 2;default:return 1}},_m=(t,e)=>{let s=[],n=[],r=new Set;for(let[i,o]of Object.entries(e)){let a=[...o.sources?.cdkInsights?.issues||[],...o.sources?.cdkNag?.issues||[]];for(let c of a){let u=ate(c);r.has(u)||(r.add(u),s.push({id:u,name:c.issue.slice(0,100),shortDescription:{text:c.issue},fullDescription:c.recommendation?{text:c.recommendation}:void 0,helpUri:c.docUrl||c.githubUrl,properties:{"security-severity":S4(c.severity).toString(),tags:[c.wafPillar,c.severity,c.foundBy].filter(Boolean)}}));let d=(c.sourceLocation?.frames?.slice(1)??[]).map(p=>({physicalLocation:{artifactLocation:{uri:p.filePath,uriBaseId:"%SRCROOT%"},region:{startLine:p.line,startColumn:p.column}},message:{text:p.kind==="property"&&p.propertyName?`Property set: ${p.propertyName}`:p.kind==="creation"?"Construct created here":"Related call site"}}));n.push({ruleId:u,level:ote(c.severity),message:{text:c.recommendation||c.issue},locations:[{physicalLocation:{artifactLocation:{uri:c.sourceLocation?.filePath||`cdk.out/${t}.template.json`,uriBaseId:"%SRCROOT%"},region:c.sourceLocation?{startLine:c.sourceLocation.line,startColumn:c.sourceLocation.column}:void 0}}],...d.length>0?{relatedLocations:d}:{},properties:{"security-severity":S4(c.severity).toString(),wafPillar:c.wafPillar,recommendation:c.recommendation}})}}return{$schema:"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",version:"2.1.0",runs:[{tool:{driver:{name:"cdk-insights",version:ite,informationUri:"https://cdkinsights.dev",rules:s}},results:n}]}},ate=t=>{let e=t.issue.toLowerCase().replace(/[^a-z0-9]+/g,"-").slice(0,50);return`CDK-${t.severity}-${e}`}});var GS,v4,C4=D(()=>{"use strict";GS=oe(require("node:fs"));dt();Em();m4();US();b4();HS();jS();v4=(t,e,s,n,r)=>{switch(Me.info(`Generating output in format: ${t}`),t){case"markdown":{let i=Bc(e,s,r,n),o=`${e}_analysis_report.md`;try{GS.writeFileSync(o,i),Me.info(`\u{1F4C4} Saved Markdown report to ${o}`)}catch(a){let c=a instanceof Error?a.message:String(a);throw Me.error(`\u274C Failed to write Markdown report to ${o}: ${c}`),new Error(`Failed to write Markdown report: ${c}`)}break}case"table":{El(s);break}case"json":{let i=x4(e,r,s);process.stdout.write(`${JSON.stringify(i,null,2)}
|
|
300
300
|
`);break}case"sarif":{let i=_m(e,s),o=`${e}_analysis_report.sarif`;try{GS.writeFileSync(o,JSON.stringify(i,null,2)),Me.info(`\u{1F4C4} SARIF report written to: ${o}`),console.log(JSON.stringify(i,null,2))}catch(a){let c=a instanceof Error?a.message:String(a);throw Me.error(`\u274C Failed to write SARIF report to ${o}: ${c}`),new Error(`Failed to write SARIF report: ${c}`)}break}case"github-actions":{Im(e,s,r.severityCounts,r.totalResources);break}default:f4(e,r);break}}});var Fm,D4=D(()=>{"use strict";Fm=(t,e,s,n)=>{let r=0,i=0,o={CRITICAL:0,HIGH:0,MEDIUM:0,LOW:0},a={"Operational Excellence":0,Security:0,"Cost Optimization":0,Reliability:0,"Performance Efficiency":0,Sustainability:0};for(let l in t){let d=[...t[l].sources.cdkInsights?.issues??[],...t[l].sources.cdkNag?.issues??[]],p=!s||s.has(l);d.length>0&&p&&i++,r+=d.length;for(let f of d)o[f.severity]+=1,a[f.wafPillar]+=1}let c=e,u=c>0?Number.parseFloat((i/c*100).toFixed(1)):0;return{totalResources:c,resourcesWithIssues:i,percentWithIssues:u,totalIssues:r,severityCounts:o,wafIssues:a,generatedBy:"cdk-insights",generatedAt:new Date().toISOString(),...n?{aiSkippedReason:n}:{}}}});var A4,w4,E4=D(()=>{"use strict";A4=oe(require("node:crypto")),w4=t=>A4.createHash("sha256").update(JSON.stringify(t)).digest("hex")});var Tm,cte,ute,zS,qS=D(()=>{"use strict";Tm=(t,e)=>e.endsWith("*")?t.startsWith(e.slice(0,-1)):t===e,cte=(t,e)=>{if(!t)return!1;let s=t.startsWith("/")?t.slice(1):t,n=e.startsWith("/")?e.slice(1):e;return n?s===n||s.startsWith(`${n}/`):!0},ute=(t,e,s)=>!t.ruleId||s.length===0||e.length===0?!1:s.some(n=>n.ruleId===t.ruleId&&e.some(r=>cte(r,n.constructPath))),zS=(t,e,s)=>{let{ignoreRules:n=[],ignorePaths:r=[],acknowledgements:i=[]}=s;return n.length===0&&r.length===0&&i.length===0?!1:r.some(a=>e.some(c=>Tm(c,a)))||t.ruleId&&n.some(c=>Tm(t.ruleId,c))?!0:ute(t,e,i)}});var lte,dte,pte,fte,R4,I4=D(()=>{"use strict";lte=[/depends\s*on.*(?:not\s*(?:be\s*)?available|may\s*not\s*exist|circular)/i,/dependson.*relationship/i,/resource.*depends.*another.*resource/i,/dependency.*(?:not\s*)?(?:be\s*)?ready/i,/lacks?\s*(?:meaningful\s*)?tags?(?:\s*for)?/i,/missing.*tags?.*(?:metadata|identification)/i,/no\s*tags?\s*(?:defined|configured|specified)/i,/does\s*not\s*have\s*any\s*tags/i,/tags?.*(?:auditing|cost\s*allocation|management)/i,/\[redacted\].*(?:incomplete|invalid|malformed|missing)/i,/incomplete.*\[redacted\]/i,/placeholder.*value/i,/missing.*closing.*brace/i,/replac(?:e|ing).*\[redacted\]/i,/\[redacted\].*(?:should|could|must)\s*be/i,/trust.*policy.*any.*service.*\[redacted\]/i,/any.*service.*within.*account.*\[redacted\]/i,/cdk.*metadata.*exposed/i,/metadata.*cdk.*path/i,/nat\s*gateway.*(?:move|associated).*(?:private\s*subnet|public\s*subnet.*risk)/i,/move.*nat\s*gateway.*private/i,/eip.*not\s*associated.*(?:instance|resource)/i,/elastic\s*ip.*not.*(?:associated|utilized|being\s*used)/i,/userdata\s*(?:script\s*)?is\s*empty/i,/empty.*userdata/i,/routetable.*(?:tags?|metadata)/i,/iam.*(?:policy|role).*(?:grants?|has).*(?:sts:assumerole|administratoraccess).*(?:overly\s*)?permissive/i,/inline\s*policy\s*grants?\s*unrestricted\s*access\s*to\s*all/i,/subnet.*mappubliciponlaunch.*(?:true|set)/i,/mappubliciponlaunch.*(?:expose|public\s*ip|internet)/i,/instances.*launched.*subnet.*public\s*ip/i],dte=[/tags?/i,/naming\s*convention/i,/resource\s*name.*not.*descriptive/i,/lacks?\s*description/i,/missing\s*description/i,/default\s*iam\s*role.*(?:broad|permissive)/i,/security\s*group.*(?:all\s*outbound|all\s*egress|unrestricted\s*egress)/i,/allows?\s*all\s*outbound\s*traffic/i],pte=t=>lte.some(e=>e.test(t)),fte=t=>dte.some(e=>e.test(t)),R4=(t,e=!1)=>t.filter(s=>{let n=s.issue||"";return!(pte(n)||e&&fte(n))})});var k4,_4=D(()=>{"use strict";dt();yl();I4();k4=({staticRecommendations:t,aiRecommendations:e,recommendationMap:s,ruleFilter:n,filterIssuesByRule:r,_displayNameMap:i={}})=>{let o={...s};for(let[d,{issues:p}]of Object.entries(t))o[d]&&(o[d].sources||(o[d].sources={cdkInsights:{issues:[]},cdkNag:{issues:[]}}),o[d].sources.cdkInsights||(o[d].sources.cdkInsights={issues:[]}),o[d].sources.cdkInsights.issues.push(...p));let a=0,c=0,u=0,l=0;for(let[d,p]of Object.entries(e)){if(!p||!Array.isArray(p.issues)){Me.warn(`\u26A0\uFE0F No AI issues for resource '${d}', skipping.`);continue}let f=d;if(!o[f]){Me.warn(`\u26A0\uFE0F AI recommendations for unknown resource '${f}', skipping enrichment.`);continue}let m=o[f],g=n.length>0?r(p.issues,n):p.issues,y=R4(g,m.isGenerated).map(C=>{switch(C.severity||(Me.debug(`AI recommendation missing severity for resource '${f}', defaulting to MEDIUM`),C.severity="MEDIUM"),C.severity.toUpperCase()==="CRITICAL"&&(Me.debug(`Capping AI finding from CRITICAL \u2192 HIGH for resource '${f}' (AI findings are advisory)`),C.severity="HIGH"),C.severity.toUpperCase()){case"CRITICAL":a++;break;case"HIGH":c++;break;case"MEDIUM":u++;break;case"LOW":l++;break;default:Me.warn(`\u26A0\uFE0F Unknown severity '${C.severity}' for resource '${f}', defaulting to MEDIUM`),C.severity="MEDIUM",u++;break}return{resourceName:C.resourceName||m.resourceName,resourceId:f,friendlyName:m.friendlyName,displayName:m.displayName,locationHint:C.locationHint||m.locationHint,constructPath:m.cdkPath,githubUrl:m.githubUrl,docUrl:m.docUrl,issue:C.issue||"AI analysis issue",recommendation:C.recommendation||"No specific recommendation provided",severity:C.severity,wafPillar:(()=>{if(C.wafPillar)switch(C.wafPillar.toLowerCase().trim()){case"security":return"Security";case"operational excellence":return"Operational Excellence";case"cost optimization":return"Cost Optimization";case"reliability":return"Reliability";case"performance efficiency":return"Performance Efficiency";case"sustainability":return"Sustainability";default:return"Security"}return"Security"})(),codeSnippet:C.codeSnippet||"",foundBy:C.foundBy??"cdkInsights"}}),b=bm(y,m.cdkPath);m.sources||(m.sources={cdkInsights:{issues:[]},cdkNag:{issues:[]}}),m.sources.cdkInsights||(m.sources.cdkInsights={issues:[]}),m.sources.cdkInsights.issues.push(...b)}return{updatedMap:o,criticalCount:a,highCount:c,mediumCount:u,lowCount:l}}});var Pm,KS,mte,hte,VS=D(()=>{"use strict";Pm=t=>{if(!t||t.length===0)return 0;let e=t.length,s=new Map;for(let r of t)s.set(r,(s.get(r)||0)+1);let n=0;for(let r of s.values()){let i=r/e;n-=i*Math.log2(i)}return n},KS=(t,e=!1)=>{if(t.length<16||mte(t)||Pm(t)<(e?4:4.5))return!1;let r=/[A-Z]/.test(t),i=/[a-z]/.test(t),o=/[0-9]/.test(t),a=/[^A-Za-z0-9]/.test(t),c=[r,i,o,a].filter(Boolean).length;return e?c>=1:c>=2},mte=t=>{if(/^https?:\/\//i.test(t)||/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(t)||/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(t)||/^arn:aws[a-z-]*:[a-z0-9-]+:[a-z0-9-]*:\d*:/.test(t)||/^(\/|\.\/|\.\.\/|[A-Za-z]:\\)/.test(t)||/^s3:\/\/[a-z0-9.-]+\//.test(t)||/^[A-Za-z][A-Za-z0-9]*(DefaultPolicy|DefaultRole|ServiceRole|EventsRole|ExecutionRole|LogRetention|LambdaFunction|Handler|Function|Role|Policy)[A-F0-9]{8,}$/.test(t)||/^sha256:[a-f0-9]{64}$/.test(t)||/^[a-f0-9]{40}$/.test(t)||/^Z[A-Z0-9]{14,22}$/.test(t)||/^[a-z]{2}-[a-z]+-\d_[A-Za-z0-9]{9,}$/.test(t)||/^(vpc|subnet|sg|igw|nat|rtb|acl|eni|i|ami|vol|snap|eipalloc)-[a-f0-9]{8,17}$/.test(t)||/^E[A-Z0-9]{13}$/.test(t))return!0;if(/^[A-Za-z0-9+/]{4,}={0,2}$/.test(t)){let e=new Set(t).size;if(t.length>50&&e<10)return!0}return!!hte(t)},hte=t=>{let e=t.length;for(let s=1;s<=e/2;s++)if(t.slice(0,s).repeat(Math.ceil(e/s)).slice(0,e)===t)return!0;return!1}});var ZS,YS,gte,yte,xte,bte,F4,T4,JS,QS,XS,ev,Lm,tv,sv=D(()=>{"use strict";ZS=[/api[_-]?key/i,/secret[_-]?key/i,/^password$/i,/^passwd$/i,/credential/i,/private[_-]?key/i,/access[_-]?key/i,/auth[_-]?token/i,/bearer[_-]?token/i,/refresh[_-]?token/i,/client[_-]?secret/i,/app[_-]?secret/i,/secret[_-]?value/i,/aws[_-]?secret/i,/aws[_-]?access[_-]?key/i,/aws[_-]?session[_-]?token/i,/db[_-]?password/i,/database[_-]?password/i,/master[_-]?password/i,/master[_-]?user[_-]?password/i,/admin[_-]?password/i,/root[_-]?password/i,/connection[_-]?string/i,/stripe[_-]?key/i,/stripe[_-]?secret/i,/github[_-]?token/i,/gitlab[_-]?token/i,/slack[_-]?token/i,/slack[_-]?webhook/i,/discord[_-]?token/i,/twilio[_-]?token/i,/sendgrid[_-]?key/i,/mailgun[_-]?key/i,/datadog[_-]?key/i,/new[_-]?relic[_-]?key/i,/sentry[_-]?dsn/i,/webhook[_-]?secret/i,/signing[_-]?key/i,/signing[_-]?secret/i,/encryption[_-]?key/i,/jwt[_-]?secret/i,/hmac[_-]?key/i,/ssh[_-]?key/i,/ssh[_-]?private/i,/pem[_-]?key/i,/rsa[_-]?key/i],YS=[/^A[BGIK-Z][A-Z]{2}[0-9A-Z]{16}$/,/^[A-Za-z0-9/+=]{40}$/,/-----BEGIN (RSA |EC |DSA |OPENSSH |ENCRYPTED )?PRIVATE KEY-----/,/-----BEGIN PGP PRIVATE KEY BLOCK-----/,/^eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/,/^gh[pousr]_[A-Za-z0-9]{36,}$/,/^[srp]k_(live|test)_[A-Za-z0-9]{24,}$/,/^xox[bpas]-[A-Za-z0-9-]+$/,/^SK[a-f0-9]{32}$/i,/^SG\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/],gte=[/\{\{resolve:secretsmanager:/,/{{resolve:secretsmanager:/,/\{\{resolve:ssm:/,/{{resolve:ssm:/,/\{\{resolve:ssm-secure:/,/{{resolve:ssm-secure:/,/^\/[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(\/[a-zA-Z0-9_.-]+)+$/,/!Ref\s+\w+/,/!GetAtt\s+[\w.]+/,/!Sub\s+/,/\$\{[\w:.]+\}/,/\$\{Token\[/,/\[\[token:/i,/\${Token\[TOKEN\.\d+\]\}/,/^arn:aws[a-z-]*:[a-z0-9-]+:[a-z0-9-]*:\d*:/],yte=[/^<[^>]+>$/,/^CHANGE[_-]?ME$/i,/^REPLACE[_-]?ME$/i,/^TODO$/i,/^TODO:/i,/^FIXME$/i,/^XXX$/i,/^YOUR[_-]/i,/^INSERT[_-]/i,/^ENTER[_-]/i,/^\*+$/,/^x+$/i,/^\s*$/,/^default$/i,/^example$/i,/^sample$/i,/^test$/i,/^demo$/i,/^dummy$/i,/^fake$/i,/^mock$/i,/^placeholder$/i],xte=[/^Description$/i,/^AlarmDescription$/i,/^Comment$/i,/^Label$/i,/^Summary$/i,/^DisplayName$/i,/^Name$/i,/^PolicyName$/i,/^RoleName$/i,/^FunctionName$/i,/^QueueName$/i,/^TopicName$/i,/^BucketName$/i,/^TableName$/i,/^StreamName$/i,/^LogGroupName$/i,/^ParameterName$/i,/^SecretName$/i,/^StateMachineName$/i,/^RuleName$/i,/^AliasName$/i,/^StackName$/i,/^GroupName$/i,/^UserName$/i,/^PolicyDocument$/i,/^ClientId$/i,/^UserPoolClientId$/i,/^UserPoolId$/i,/^IdentityPoolId$/i,/^DistributionId$/i,/^HostedZoneId$/i,/^CertificateArn$/i,/^TopicArn$/i,/^QueueArn$/i,/^FunctionArn$/i,/^Arn$/i,/^EventPattern$/i,/^Definition$/i,/^DefinitionString$/i,/^Template$/i,/^TemplateURL$/i,/^TemplateBody$/i,/^EventSourceName$/i,/^PartnerEventSource$/i],bte=[/(?:^|\.)Targets\[\d+\]\.Input$/,/(?:^|\.)Create$/,/(?:^|\.)Update$/,/(?:^|\.)Delete$/,/(?:^|\.)DefinitionString$/,/(?:^|\.)Code\.ZipFile$/,/(?:^|\.)Statement\[\d+\]\.Resource$/,/(?:^|\.)Statement\[\d+\]\.Resource\[\d+\]$/,/(?:^|\.)Statement\[\d+\]\.Sid$/],F4=t=>xte.some(e=>e.test(t)),T4=t=>bte.some(e=>e.test(t)),JS=t=>ZS.some(e=>e.test(t)),QS=t=>YS.some(e=>e.test(t)),XS=t=>gte.some(e=>e.test(t)),ev=t=>yte.some(e=>e.test(t)),Lm=t=>{if(typeof t!="object"||t===null)return!1;let e=["Ref","Fn::GetAtt","Fn::Sub","Fn::Join","Fn::ImportValue","Fn::If","Fn::Select","Fn::Split","Fn::Base64","Fn::Cidr","Fn::FindInMap","Fn::GetAZs","Fn::Transform"],s=Object.keys(t);return s.length===1&&e.includes(s[0])},tv=t=>{let e=[{patterns:[/api[_-]?key/i,/access[_-]?key/i],category:"api_key"},{patterns:[/password/i,/passwd/i],category:"password"},{patterns:[/private[_-]?key/i,/ssh[_-]?key/i,/pem[_-]?key/i,/rsa[_-]?key/i],category:"private_key"},{patterns:[/aws[_-]?secret/i,/aws[_-]?access/i],category:"aws_credentials"},{patterns:[/token/i,/bearer/i],category:"token"},{patterns:[/secret/i,/credential/i],category:"secret"},{patterns:[/connection[_-]?string/i,/database/i,/db[_-]/i],category:"database"},{patterns:[/webhook/i,/signing/i,/encryption/i,/hmac/i,/jwt/i],category:"encryption_key"}];for(let{patterns:s,category:n}of e)if(s.some(r=>r.test(t)))return n;return"secret"}});var Il,kl,nv=D(()=>{"use strict";Il=t=>{let e={api_key:`Use AWS Secrets Manager to store API keys securely:
|
|
301
301
|
|
|
302
302
|
// CDK TypeScript example:
|
|
@@ -458,7 +458,7 @@ See: https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html`},kl
|
|
|
458
458
|
`,CHAR_NO_BREAK_SPACE:"\xA0",CHAR_PERCENT:"%",CHAR_PLUS:"+",CHAR_QUESTION_MARK:"?",CHAR_RIGHT_ANGLE_BRACKET:">",CHAR_RIGHT_CURLY_BRACE:"}",CHAR_RIGHT_SQUARE_BRACKET:"]",CHAR_SEMICOLON:";",CHAR_SINGLE_QUOTE:"'",CHAR_SPACE:" ",CHAR_TAB:" ",CHAR_UNDERSCORE:"_",CHAR_VERTICAL_LINE:"|",CHAR_ZERO_WIDTH_NOBREAK_SPACE:"\uFEFF"}});var l5=M((TTe,u5)=>{"use strict";var wre=ih(),{MAX_LENGTH:o5,CHAR_BACKSLASH:Kv,CHAR_BACKTICK:Ere,CHAR_COMMA:Rre,CHAR_DOT:Ire,CHAR_LEFT_PARENTHESES:kre,CHAR_RIGHT_PARENTHESES:_re,CHAR_LEFT_CURLY_BRACE:Fre,CHAR_RIGHT_CURLY_BRACE:Tre,CHAR_LEFT_SQUARE_BRACKET:a5,CHAR_RIGHT_SQUARE_BRACKET:c5,CHAR_DOUBLE_QUOTE:Pre,CHAR_SINGLE_QUOTE:Lre,CHAR_NO_BREAK_SPACE:Ore,CHAR_ZERO_WIDTH_NOBREAK_SPACE:Mre}=i5(),Bre=(t,e={})=>{if(typeof t!="string")throw new TypeError("Expected a string");let s=e||{},n=typeof s.maxLength=="number"?Math.min(o5,s.maxLength):o5;if(t.length>n)throw new SyntaxError(`Input length (${t.length}), exceeds max characters (${n})`);let r={type:"root",input:t,nodes:[]},i=[r],o=r,a=r,c=0,u=t.length,l=0,d=0,p,f=()=>t[l++],m=g=>{if(g.type==="text"&&a.type==="dot"&&(a.type="text"),a&&a.type==="text"&&g.type==="text"){a.value+=g.value;return}return o.nodes.push(g),g.parent=o,g.prev=a,a=g,g};for(m({type:"bos"});l<u;)if(o=i[i.length-1],p=f(),!(p===Mre||p===Ore)){if(p===Kv){m({type:"text",value:(e.keepEscaping?p:"")+f()});continue}if(p===c5){m({type:"text",value:"\\"+p});continue}if(p===a5){c++;let g;for(;l<u&&(g=f());){if(p+=g,g===a5){c++;continue}if(g===Kv){p+=f();continue}if(g===c5&&(c--,c===0))break}m({type:"text",value:p});continue}if(p===kre){o=m({type:"paren",nodes:[]}),i.push(o),m({type:"text",value:p});continue}if(p===_re){if(o.type!=="paren"){m({type:"text",value:p});continue}o=i.pop(),m({type:"text",value:p}),o=i[i.length-1];continue}if(p===Pre||p===Lre||p===Ere){let g=p,h;for(e.keepQuotes!==!0&&(p="");l<u&&(h=f());){if(h===Kv){p+=h+f();continue}if(h===g){e.keepQuotes===!0&&(p+=h);break}p+=h}m({type:"text",value:p});continue}if(p===Fre){d++;let h={type:"brace",open:!0,close:!1,dollar:a.value&&a.value.slice(-1)==="$"||o.dollar===!0,depth:d,commas:0,ranges:0,nodes:[]};o=m(h),i.push(o),m({type:"open",value:p});continue}if(p===Tre){if(o.type!=="brace"){m({type:"text",value:p});continue}let g="close";o=i.pop(),o.close=!0,m({type:g,value:p}),d--,o=i[i.length-1];continue}if(p===Rre&&d>0){if(o.ranges>0){o.ranges=0;let g=o.nodes.shift();o.nodes=[g,{type:"text",value:wre(o)}]}m({type:"comma",value:p}),o.commas++;continue}if(p===Ire&&d>0&&o.commas===0){let g=o.nodes;if(d===0||g.length===0){m({type:"text",value:p});continue}if(a.type==="dot"){if(o.range=[],a.value+=p,a.type="range",o.nodes.length!==3&&o.nodes.length!==5){o.invalid=!0,o.ranges=0,a.type="text";continue}o.ranges++,o.args=[];continue}if(a.type==="range"){g.pop();let h=g[g.length-1];h.value+=a.value+p,a=h,o.ranges--;continue}m({type:"dot",value:p});continue}m({type:"text",value:p})}do if(o=i.pop(),o.type!=="root"){o.nodes.forEach(y=>{y.nodes||(y.type==="open"&&(y.isOpen=!0),y.type==="close"&&(y.isClose=!0),y.nodes||(y.type="text"),y.invalid=!0)});let g=i[i.length-1],h=g.nodes.indexOf(o);g.nodes.splice(h,1,...o.nodes)}while(i.length>0);return m({type:"eos"}),r};u5.exports=Bre});var f5=M((PTe,p5)=>{"use strict";var d5=ih(),Nre=e5(),$re=n5(),Wre=l5(),tn=(t,e={})=>{let s=[];if(Array.isArray(t))for(let n of t){let r=tn.create(n,e);Array.isArray(r)?s.push(...r):s.push(r)}else s=[].concat(tn.create(t,e));return e&&e.expand===!0&&e.nodupes===!0&&(s=[...new Set(s)]),s};tn.parse=(t,e={})=>Wre(t,e);tn.stringify=(t,e={})=>d5(typeof t=="string"?tn.parse(t,e):t,e);tn.compile=(t,e={})=>(typeof t=="string"&&(t=tn.parse(t,e)),Nre(t,e));tn.expand=(t,e={})=>{typeof t=="string"&&(t=tn.parse(t,e));let s=$re(t,e);return e.noempty===!0&&(s=s.filter(Boolean)),e.nodupes===!0&&(s=[...new Set(s)]),s};tn.create=(t,e={})=>t===""||t.length<3?[t]:e.expand!==!0?tn.compile(t,e):tn.expand(t,e);p5.exports=tn});var m5=M((LTe,jre)=>{jre.exports=["3dm","3ds","3g2","3gp","7z","a","aac","adp","afdesign","afphoto","afpub","ai","aif","aiff","alz","ape","apk","appimage","ar","arj","asf","au","avi","bak","baml","bh","bin","bk","bmp","btif","bz2","bzip2","cab","caf","cgm","class","cmx","cpio","cr2","cur","dat","dcm","deb","dex","djvu","dll","dmg","dng","doc","docm","docx","dot","dotm","dra","DS_Store","dsk","dts","dtshd","dvb","dwg","dxf","ecelp4800","ecelp7470","ecelp9600","egg","eol","eot","epub","exe","f4v","fbs","fh","fla","flac","flatpak","fli","flv","fpx","fst","fvt","g3","gh","gif","graffle","gz","gzip","h261","h263","h264","icns","ico","ief","img","ipa","iso","jar","jpeg","jpg","jpgv","jpm","jxr","key","ktx","lha","lib","lvp","lz","lzh","lzma","lzo","m3u","m4a","m4v","mar","mdi","mht","mid","midi","mj2","mka","mkv","mmr","mng","mobi","mov","movie","mp3","mp4","mp4a","mpeg","mpg","mpga","mxu","nef","npx","numbers","nupkg","o","odp","ods","odt","oga","ogg","ogv","otf","ott","pages","pbm","pcx","pdb","pdf","pea","pgm","pic","png","pnm","pot","potm","potx","ppa","ppam","ppm","pps","ppsm","ppsx","ppt","pptm","pptx","psd","pya","pyc","pyo","pyv","qt","rar","ras","raw","resources","rgb","rip","rlc","rmf","rmvb","rpm","rtf","rz","s3m","s7z","scpt","sgi","shar","snap","sil","sketch","slk","smv","snk","so","stl","suo","sub","swf","tar","tbz","tbz2","tga","tgz","thmx","tif","tiff","tlz","ttc","ttf","txz","udf","uvh","uvi","uvm","uvp","uvs","uvu","viv","vob","war","wav","wax","wbmp","wdp","weba","webm","webp","whl","wim","wm","wma","wmv","wmx","woff","woff2","wrm","wvx","xbm","xif","xla","xlam","xls","xlsb","xlsm","xlsx","xlt","xltm","xltx","xm","xmind","xpi","xpm","xwd","xz","z","zip","zipx"]});var g5=M((OTe,h5)=>{h5.exports=m5()});var x5=M((MTe,y5)=>{"use strict";var Ure=require("path"),Hre=g5(),Gre=new Set(Hre);y5.exports=t=>Gre.has(Ure.extname(t).slice(1).toLowerCase())});var ch=M(Be=>{"use strict";var{sep:zre}=require("path"),{platform:Vv}=process,qre=require("os");Be.EV_ALL="all";Be.EV_READY="ready";Be.EV_ADD="add";Be.EV_CHANGE="change";Be.EV_ADD_DIR="addDir";Be.EV_UNLINK="unlink";Be.EV_UNLINK_DIR="unlinkDir";Be.EV_RAW="raw";Be.EV_ERROR="error";Be.STR_DATA="data";Be.STR_END="end";Be.STR_CLOSE="close";Be.FSEVENT_CREATED="created";Be.FSEVENT_MODIFIED="modified";Be.FSEVENT_DELETED="deleted";Be.FSEVENT_MOVED="moved";Be.FSEVENT_CLONED="cloned";Be.FSEVENT_UNKNOWN="unknown";Be.FSEVENT_FLAG_MUST_SCAN_SUBDIRS=1;Be.FSEVENT_TYPE_FILE="file";Be.FSEVENT_TYPE_DIRECTORY="directory";Be.FSEVENT_TYPE_SYMLINK="symlink";Be.KEY_LISTENERS="listeners";Be.KEY_ERR="errHandlers";Be.KEY_RAW="rawEmitters";Be.HANDLER_KEYS=[Be.KEY_LISTENERS,Be.KEY_ERR,Be.KEY_RAW];Be.DOT_SLASH=`.${zre}`;Be.BACK_SLASH_RE=/\\/g;Be.DOUBLE_SLASH_RE=/\/\//;Be.SLASH_OR_BACK_SLASH_RE=/[/\\]/;Be.DOT_RE=/\..*\.(sw[px])$|~$|\.subl.*\.tmp/;Be.REPLACER_RE=/^\.[/\\]/;Be.SLASH="/";Be.SLASH_SLASH="//";Be.BRACE_START="{";Be.BANG="!";Be.ONE_DOT=".";Be.TWO_DOTS="..";Be.STAR="*";Be.GLOBSTAR="**";Be.ROOT_GLOBSTAR="/**/*";Be.SLASH_GLOBSTAR="/**";Be.DIR_SUFFIX="Dir";Be.ANYMATCH_OPTS={dot:!0};Be.STRING_TYPE="string";Be.FUNCTION_TYPE="function";Be.EMPTY_STR="";Be.EMPTY_FN=()=>{};Be.IDENTITY_FN=t=>t;Be.isWindows=Vv==="win32";Be.isMacos=Vv==="darwin";Be.isLinux=Vv==="linux";Be.isIBMi=qre.type()==="OS400"});var A5=M((NTe,D5)=>{"use strict";var Qr=require("fs"),ls=require("path"),{promisify:Ql}=require("util"),Kre=x5(),{isWindows:Vre,isLinux:Zre,EMPTY_FN:Yre,EMPTY_STR:Jre,KEY_LISTENERS:Uc,KEY_ERR:Zv,KEY_RAW:Zl,HANDLER_KEYS:Qre,EV_CHANGE:lh,EV_ADD:uh,EV_ADD_DIR:Xre,EV_ERROR:S5,STR_DATA:eie,STR_END:tie,BRACE_START:sie,STAR:nie}=ch(),rie="watch",iie=Ql(Qr.open),v5=Ql(Qr.stat),oie=Ql(Qr.lstat),aie=Ql(Qr.close),Yv=Ql(Qr.realpath),cie={lstat:oie,stat:v5},Qv=(t,e)=>{t instanceof Set?t.forEach(e):e(t)},Yl=(t,e,s)=>{let n=t[e];n instanceof Set||(t[e]=n=new Set([n])),n.add(s)},uie=t=>e=>{let s=t[e];s instanceof Set?s.clear():delete t[e]},Jl=(t,e,s)=>{let n=t[e];n instanceof Set?n.delete(s):n===s&&delete t[e]},C5=t=>t instanceof Set?t.size===0:!t,dh=new Map;function b5(t,e,s,n,r){let i=(o,a)=>{s(t),r(o,a,{watchedPath:t}),a&&t!==a&&ph(ls.resolve(t,a),Uc,ls.join(t,a))};try{return Qr.watch(t,e,i)}catch(o){n(o)}}var ph=(t,e,s,n,r)=>{let i=dh.get(t);i&&Qv(i[e],o=>{o(s,n,r)})},lie=(t,e,s,n)=>{let{listener:r,errHandler:i,rawEmitter:o}=n,a=dh.get(e),c;if(!s.persistent)return c=b5(t,s,r,i,o),c.close.bind(c);if(a)Yl(a,Uc,r),Yl(a,Zv,i),Yl(a,Zl,o);else{if(c=b5(t,s,ph.bind(null,e,Uc),i,ph.bind(null,e,Zl)),!c)return;c.on(S5,async u=>{let l=ph.bind(null,e,Zv);if(a.watcherUnusable=!0,Vre&&u.code==="EPERM")try{let d=await iie(t,"r");await aie(d),l(u)}catch{}else l(u)}),a={listeners:r,errHandlers:i,rawEmitters:o,watcher:c},dh.set(e,a)}return()=>{Jl(a,Uc,r),Jl(a,Zv,i),Jl(a,Zl,o),C5(a.listeners)&&(a.watcher.close(),dh.delete(e),Qre.forEach(uie(a)),a.watcher=void 0,Object.freeze(a))}},Jv=new Map,die=(t,e,s,n)=>{let{listener:r,rawEmitter:i}=n,o=Jv.get(e),a=new Set,c=new Set,u=o&&o.options;return u&&(u.persistent<s.persistent||u.interval>s.interval)&&(a=o.listeners,c=o.rawEmitters,Qr.unwatchFile(e),o=void 0),o?(Yl(o,Uc,r),Yl(o,Zl,i)):(o={listeners:r,rawEmitters:i,options:s,watcher:Qr.watchFile(e,s,(l,d)=>{Qv(o.rawEmitters,f=>{f(lh,e,{curr:l,prev:d})});let p=l.mtimeMs;(l.size!==d.size||p>d.mtimeMs||p===0)&&Qv(o.listeners,f=>f(t,l))})},Jv.set(e,o)),()=>{Jl(o,Uc,r),Jl(o,Zl,i),C5(o.listeners)&&(Jv.delete(e),Qr.unwatchFile(e),o.options=o.watcher=void 0,Object.freeze(o))}},Xv=class{constructor(e){this.fsw=e,this._boundHandleError=s=>e._handleError(s)}_watchWithNodeFs(e,s){let n=this.fsw.options,r=ls.dirname(e),i=ls.basename(e);this.fsw._getWatchedDir(r).add(i);let a=ls.resolve(e),c={persistent:n.persistent};s||(s=Yre);let u;return n.usePolling?(c.interval=n.enableBinaryInterval&&Kre(i)?n.binaryInterval:n.interval,u=die(e,a,c,{listener:s,rawEmitter:this.fsw._emitRaw})):u=lie(e,a,c,{listener:s,errHandler:this._boundHandleError,rawEmitter:this.fsw._emitRaw}),u}_handleFile(e,s,n){if(this.fsw.closed)return;let r=ls.dirname(e),i=ls.basename(e),o=this.fsw._getWatchedDir(r),a=s;if(o.has(i))return;let c=async(l,d)=>{if(this.fsw._throttle(rie,e,5)){if(!d||d.mtimeMs===0)try{let p=await v5(e);if(this.fsw.closed)return;let f=p.atimeMs,m=p.mtimeMs;(!f||f<=m||m!==a.mtimeMs)&&this.fsw._emit(lh,e,p),Zre&&a.ino!==p.ino?(this.fsw._closeFile(l),a=p,this.fsw._addPathCloser(l,this._watchWithNodeFs(e,c))):a=p}catch{this.fsw._remove(r,i)}else if(o.has(i)){let p=d.atimeMs,f=d.mtimeMs;(!p||p<=f||f!==a.mtimeMs)&&this.fsw._emit(lh,e,d),a=d}}},u=this._watchWithNodeFs(e,c);if(!(n&&this.fsw.options.ignoreInitial)&&this.fsw._isntIgnored(e)){if(!this.fsw._throttle(uh,e,0))return;this.fsw._emit(uh,e,s)}return u}async _handleSymlink(e,s,n,r){if(this.fsw.closed)return;let i=e.fullPath,o=this.fsw._getWatchedDir(s);if(!this.fsw.options.followSymlinks){this.fsw._incrReadyCount();let a;try{a=await Yv(n)}catch{return this.fsw._emitReady(),!0}return this.fsw.closed?void 0:(o.has(r)?this.fsw._symlinkPaths.get(i)!==a&&(this.fsw._symlinkPaths.set(i,a),this.fsw._emit(lh,n,e.stats)):(o.add(r),this.fsw._symlinkPaths.set(i,a),this.fsw._emit(uh,n,e.stats)),this.fsw._emitReady(),!0)}if(this.fsw._symlinkPaths.has(i))return!0;this.fsw._symlinkPaths.set(i,!0)}_handleRead(e,s,n,r,i,o,a){if(e=ls.join(e,Jre),!n.hasGlob&&(a=this.fsw._throttle("readdir",e,1e3),!a))return;let c=this.fsw._getWatchedDir(n.path),u=new Set,l=this.fsw._readdirp(e,{fileFilter:d=>n.filterPath(d),directoryFilter:d=>n.filterDir(d),depth:0}).on(eie,async d=>{if(this.fsw.closed){l=void 0;return}let p=d.path,f=ls.join(e,p);if(u.add(p),!(d.stats.isSymbolicLink()&&await this._handleSymlink(d,e,f,p))){if(this.fsw.closed){l=void 0;return}(p===r||!r&&!c.has(p))&&(this.fsw._incrReadyCount(),f=ls.join(i,ls.relative(i,f)),this._addToNodeFs(f,s,n,o+1))}}).on(S5,this._boundHandleError);return new Promise(d=>l.once(tie,()=>{if(this.fsw.closed){l=void 0;return}let p=a?a.clear():!1;d(),c.getChildren().filter(f=>f!==e&&!u.has(f)&&(!n.hasGlob||n.filterPath({fullPath:ls.resolve(e,f)}))).forEach(f=>{this.fsw._remove(e,f)}),l=void 0,p&&this._handleRead(e,!1,n,r,i,o,a)}))}async _handleDir(e,s,n,r,i,o,a){let c=this.fsw._getWatchedDir(ls.dirname(e)),u=c.has(ls.basename(e));!(n&&this.fsw.options.ignoreInitial)&&!i&&!u&&(!o.hasGlob||o.globFilter(e))&&this.fsw._emit(Xre,e,s),c.add(ls.basename(e)),this.fsw._getWatchedDir(e);let l,d,p=this.fsw.options.depth;if((p==null||r<=p)&&!this.fsw._symlinkPaths.has(a)){if(!i&&(await this._handleRead(e,n,o,i,e,r,l),this.fsw.closed))return;d=this._watchWithNodeFs(e,(f,m)=>{m&&m.mtimeMs===0||this._handleRead(f,!1,o,i,e,r,l)})}return d}async _addToNodeFs(e,s,n,r,i){let o=this.fsw._emitReady;if(this.fsw._isIgnored(e)||this.fsw.closed)return o(),!1;let a=this.fsw._getWatchHelpers(e,r);!a.hasGlob&&n&&(a.hasGlob=n.hasGlob,a.globFilter=n.globFilter,a.filterPath=c=>n.filterPath(c),a.filterDir=c=>n.filterDir(c));try{let c=await cie[a.statMethod](a.watchPath);if(this.fsw.closed)return;if(this.fsw._isIgnored(a.watchPath,c))return o(),!1;let u=this.fsw.options.followSymlinks&&!e.includes(nie)&&!e.includes(sie),l;if(c.isDirectory()){let d=ls.resolve(e),p=u?await Yv(e):e;if(this.fsw.closed||(l=await this._handleDir(a.watchPath,c,s,r,i,a,p),this.fsw.closed))return;d!==p&&p!==void 0&&this.fsw._symlinkPaths.set(d,p)}else if(c.isSymbolicLink()){let d=u?await Yv(e):e;if(this.fsw.closed)return;let p=ls.dirname(a.watchPath);if(this.fsw._getWatchedDir(p).add(a.watchPath),this.fsw._emit(uh,a.watchPath,c),l=await this._handleDir(p,c,s,r,e,a,d),this.fsw.closed)return;d!==void 0&&this.fsw._symlinkPaths.set(ls.resolve(e),d)}else l=this._handleFile(a.watchPath,c,s);return o(),this.fsw._addPathCloser(e,l),!1}catch(c){if(this.fsw._handleError(c))return o(),e}}};D5.exports=Xv});var F5=M(($Te,aC)=>{"use strict";var iC=require("fs"),ds=require("path"),{promisify:oC}=require("util"),Hc;try{Hc=require("fsevents")}catch(t){process.env.CHOKIDAR_PRINT_FSEVENTS_REQUIRE_ERROR&&console.error(t)}if(Hc){let t=process.version.match(/v(\d+)\.(\d+)/);if(t&&t[1]&&t[2]){let e=Number.parseInt(t[1],10),s=Number.parseInt(t[2],10);e===8&&s<16&&(Hc=void 0)}}var{EV_ADD:eC,EV_CHANGE:pie,EV_ADD_DIR:w5,EV_UNLINK:fh,EV_ERROR:fie,STR_DATA:mie,STR_END:hie,FSEVENT_CREATED:gie,FSEVENT_MODIFIED:yie,FSEVENT_DELETED:xie,FSEVENT_MOVED:bie,FSEVENT_UNKNOWN:Sie,FSEVENT_FLAG_MUST_SCAN_SUBDIRS:vie,FSEVENT_TYPE_FILE:Cie,FSEVENT_TYPE_DIRECTORY:Xl,FSEVENT_TYPE_SYMLINK:_5,ROOT_GLOBSTAR:E5,DIR_SUFFIX:Die,DOT_SLASH:R5,FUNCTION_TYPE:tC,EMPTY_FN:Aie,IDENTITY_FN:wie}=ch(),Eie=t=>isNaN(t)?{}:{depth:t},nC=oC(iC.stat),Rie=oC(iC.lstat),I5=oC(iC.realpath),Iie={stat:nC,lstat:Rie},aa=new Map,kie=10,_ie=new Set([69888,70400,71424,72704,73472,131328,131840,262912]),Fie=(t,e)=>({stop:Hc.watch(t,e)});function Tie(t,e,s,n){let r=ds.extname(e)?ds.dirname(e):e,i=ds.dirname(r),o=aa.get(r);Pie(i)&&(r=i);let a=ds.resolve(t),c=a!==e,u=(d,p,f)=>{c&&(d=d.replace(e,a)),(d===a||!d.indexOf(a+ds.sep))&&s(d,p,f)},l=!1;for(let d of aa.keys())if(e.indexOf(ds.resolve(d)+ds.sep)===0){r=d,o=aa.get(r),l=!0;break}return o||l?o.listeners.add(u):(o={listeners:new Set([u]),rawEmitter:n,watcher:Fie(r,(d,p)=>{if(!o.listeners.size||p&vie)return;let f=Hc.getInfo(d,p);o.listeners.forEach(m=>{m(d,p,f)}),o.rawEmitter(f.event,d,f)})},aa.set(r,o)),()=>{let d=o.listeners;if(d.delete(u),!d.size&&(aa.delete(r),o.watcher))return o.watcher.stop().then(()=>{o.rawEmitter=o.watcher=void 0,Object.freeze(o)})}}var Pie=t=>{let e=0;for(let s of aa.keys())if(s.indexOf(t)===0&&(e++,e>=kie))return!0;return!1},Lie=()=>Hc&&aa.size<128,sC=(t,e)=>{let s=0;for(;!t.indexOf(e)&&(t=ds.dirname(t))!==e;)s++;return s},k5=(t,e)=>t.type===Xl&&e.isDirectory()||t.type===_5&&e.isSymbolicLink()||t.type===Cie&&e.isFile(),rC=class{constructor(e){this.fsw=e}checkIgnored(e,s){let n=this.fsw._ignoredPaths;if(this.fsw._isIgnored(e,s))return n.add(e),s&&s.isDirectory()&&n.add(e+E5),!0;n.delete(e),n.delete(e+E5)}addOrChange(e,s,n,r,i,o,a,c){let u=i.has(o)?pie:eC;this.handleEvent(u,e,s,n,r,i,o,a,c)}async checkExists(e,s,n,r,i,o,a,c){try{let u=await nC(e);if(this.fsw.closed)return;k5(a,u)?this.addOrChange(e,s,n,r,i,o,a,c):this.handleEvent(fh,e,s,n,r,i,o,a,c)}catch(u){u.code==="EACCES"?this.addOrChange(e,s,n,r,i,o,a,c):this.handleEvent(fh,e,s,n,r,i,o,a,c)}}handleEvent(e,s,n,r,i,o,a,c,u){if(!(this.fsw.closed||this.checkIgnored(s)))if(e===fh){let l=c.type===Xl;(l||o.has(a))&&this.fsw._remove(i,a,l)}else{if(e===eC){if(c.type===Xl&&this.fsw._getWatchedDir(s),c.type===_5&&u.followSymlinks){let d=u.depth===void 0?void 0:sC(n,r)+1;return this._addToFsEvents(s,!1,!0,d)}this.fsw._getWatchedDir(i).add(a)}let l=c.type===Xl?e+Die:e;this.fsw._emit(l,s),l===w5&&this._addToFsEvents(s,!1,!0)}}_watchWithFsEvents(e,s,n,r){if(this.fsw.closed||this.fsw._isIgnored(e))return;let i=this.fsw.options,a=Tie(e,s,async(c,u,l)=>{if(this.fsw.closed||i.depth!==void 0&&sC(c,s)>i.depth)return;let d=n(ds.join(e,ds.relative(e,c)));if(r&&!r(d))return;let p=ds.dirname(d),f=ds.basename(d),m=this.fsw._getWatchedDir(l.type===Xl?d:p);if(_ie.has(u)||l.event===Sie)if(typeof i.ignored===tC){let g;try{g=await nC(d)}catch{}if(this.fsw.closed||this.checkIgnored(d,g))return;k5(l,g)?this.addOrChange(d,c,s,p,m,f,l,i):this.handleEvent(fh,d,c,s,p,m,f,l,i)}else this.checkExists(d,c,s,p,m,f,l,i);else switch(l.event){case gie:case yie:return this.addOrChange(d,c,s,p,m,f,l,i);case xie:case bie:return this.checkExists(d,c,s,p,m,f,l,i)}},this.fsw._emitRaw);return this.fsw._emitReady(),a}async _handleFsEventsSymlink(e,s,n,r){if(!(this.fsw.closed||this.fsw._symlinkPaths.has(s))){this.fsw._symlinkPaths.set(s,!0),this.fsw._incrReadyCount();try{let i=await I5(e);if(this.fsw.closed)return;if(this.fsw._isIgnored(i))return this.fsw._emitReady();this.fsw._incrReadyCount(),this._addToFsEvents(i||e,o=>{let a=e;return i&&i!==R5?a=o.replace(i,e):o!==R5&&(a=ds.join(e,o)),n(a)},!1,r)}catch(i){if(this.fsw._handleError(i))return this.fsw._emitReady()}}}emitAdd(e,s,n,r,i){let o=n(e),a=s.isDirectory(),c=this.fsw._getWatchedDir(ds.dirname(o)),u=ds.basename(o);a&&this.fsw._getWatchedDir(o),!c.has(u)&&(c.add(u),(!r.ignoreInitial||i===!0)&&this.fsw._emit(a?w5:eC,o,s))}initWatch(e,s,n,r){if(this.fsw.closed)return;let i=this._watchWithFsEvents(n.watchPath,ds.resolve(e||n.watchPath),r,n.globFilter);this.fsw._addPathCloser(s,i)}async _addToFsEvents(e,s,n,r){if(this.fsw.closed)return;let i=this.fsw.options,o=typeof s===tC?s:wie,a=this.fsw._getWatchHelpers(e);try{let c=await Iie[a.statMethod](a.watchPath);if(this.fsw.closed)return;if(this.fsw._isIgnored(a.watchPath,c))throw null;if(c.isDirectory()){if(a.globFilter||this.emitAdd(o(e),c,o,i,n),r&&r>i.depth)return;this.fsw._readdirp(a.watchPath,{fileFilter:u=>a.filterPath(u),directoryFilter:u=>a.filterDir(u),...Eie(i.depth-(r||0))}).on(mie,u=>{if(this.fsw.closed||u.stats.isDirectory()&&!a.filterPath(u))return;let l=ds.join(a.watchPath,u.path),{fullPath:d}=u;if(a.followSymlinks&&u.stats.isSymbolicLink()){let p=i.depth===void 0?void 0:sC(l,ds.resolve(a.watchPath))+1;this._handleFsEventsSymlink(l,d,o,p)}else this.emitAdd(l,u.stats,o,i,n)}).on(fie,Aie).on(hie,()=>{this.fsw._emitReady()})}else this.emitAdd(a.watchPath,c,o,i,n),this.fsw._emitReady()}catch(c){(!c||this.fsw._handleError(c))&&(this.fsw._emitReady(),this.fsw._emitReady())}if(i.persistent&&n!==!0)if(typeof s===tC)this.initWatch(void 0,e,a,o);else{let c;try{c=await I5(a.watchPath)}catch{}this.initWatch(c,e,a,o)}}};aC.exports=rC;aC.exports.canUse=Lie});var U5=M(CC=>{"use strict";var{EventEmitter:Oie}=require("events"),SC=require("fs"),bt=require("path"),{promisify:N5}=require("util"),Mie=YB(),fC=wN().default,Bie=FN(),cC=jv(),Nie=f5(),$ie=$v(),Wie=A5(),T5=F5(),{EV_ALL:uC,EV_READY:jie,EV_ADD:mh,EV_CHANGE:ed,EV_UNLINK:P5,EV_ADD_DIR:Uie,EV_UNLINK_DIR:Hie,EV_RAW:Gie,EV_ERROR:lC,STR_CLOSE:zie,STR_END:qie,BACK_SLASH_RE:Kie,DOUBLE_SLASH_RE:L5,SLASH_OR_BACK_SLASH_RE:Vie,DOT_RE:Zie,REPLACER_RE:Yie,SLASH:dC,SLASH_SLASH:Jie,BRACE_START:Qie,BANG:mC,ONE_DOT:$5,TWO_DOTS:Xie,GLOBSTAR:eoe,SLASH_GLOBSTAR:pC,ANYMATCH_OPTS:hC,STRING_TYPE:vC,FUNCTION_TYPE:toe,EMPTY_STR:gC,EMPTY_FN:soe,isWindows:noe,isMacos:roe,isIBMi:ioe}=ch(),ooe=N5(SC.stat),aoe=N5(SC.readdir),yC=(t=[])=>Array.isArray(t)?t:[t],W5=(t,e=[])=>(t.forEach(s=>{Array.isArray(s)?W5(s,e):e.push(s)}),e),O5=t=>{let e=W5(yC(t));if(!e.every(s=>typeof s===vC))throw new TypeError(`Non-string provided as watch path: ${e}`);return e.map(j5)},M5=t=>{let e=t.replace(Kie,dC),s=!1;for(e.startsWith(Jie)&&(s=!0);e.match(L5);)e=e.replace(L5,dC);return s&&(e=dC+e),e},j5=t=>M5(bt.normalize(M5(t))),B5=(t=gC)=>e=>typeof e!==vC?e:j5(bt.isAbsolute(e)?e:bt.join(t,e)),coe=(t,e)=>bt.isAbsolute(t)?t:t.startsWith(mC)?mC+bt.join(e,t.slice(1)):bt.join(e,t),sr=(t,e)=>t[e]===void 0,xC=class{constructor(e,s){this.path=e,this._removeWatcher=s,this.items=new Set}add(e){let{items:s}=this;s&&e!==$5&&e!==Xie&&s.add(e)}async remove(e){let{items:s}=this;if(!s||(s.delete(e),s.size>0))return;let n=this.path;try{await aoe(n)}catch{this._removeWatcher&&this._removeWatcher(bt.dirname(n),bt.basename(n))}}has(e){let{items:s}=this;if(s)return s.has(e)}getChildren(){let{items:e}=this;if(e)return[...e.values()]}dispose(){this.items.clear(),delete this.path,delete this._removeWatcher,delete this.items,Object.freeze(this)}},uoe="stat",loe="lstat",bC=class{constructor(e,s,n,r){this.fsw=r,this.path=e=e.replace(Yie,gC),this.watchPath=s,this.fullWatchPath=bt.resolve(s),this.hasGlob=s!==e,e===gC&&(this.hasGlob=!1),this.globSymlink=this.hasGlob&&n?void 0:!1,this.globFilter=this.hasGlob?fC(e,void 0,hC):!1,this.dirParts=this.getDirParts(e),this.dirParts.forEach(i=>{i.length>1&&i.pop()}),this.followSymlinks=n,this.statMethod=n?uoe:loe}checkGlobSymlink(e){return this.globSymlink===void 0&&(this.globSymlink=e.fullParentDir===this.fullWatchPath?!1:{realPath:e.fullParentDir,linkPath:this.fullWatchPath}),this.globSymlink?e.fullPath.replace(this.globSymlink.realPath,this.globSymlink.linkPath):e.fullPath}entryPath(e){return bt.join(this.watchPath,bt.relative(this.watchPath,this.checkGlobSymlink(e)))}filterPath(e){let{stats:s}=e;if(s&&s.isSymbolicLink())return this.filterDir(e);let n=this.entryPath(e);return(this.hasGlob&&typeof this.globFilter===toe?this.globFilter(n):!0)&&this.fsw._isntIgnored(n,s)&&this.fsw._hasReadPermissions(s)}getDirParts(e){if(!this.hasGlob)return[];let s=[];return(e.includes(Qie)?Nie.expand(e):[e]).forEach(r=>{s.push(bt.relative(this.watchPath,r).split(Vie))}),s}filterDir(e){if(this.hasGlob){let s=this.getDirParts(this.checkGlobSymlink(e)),n=!1;this.unmatchedGlob=!this.dirParts.some(r=>r.every((i,o)=>(i===eoe&&(n=!0),n||!s[0][o]||fC(i,s[0][o],hC))))}return!this.unmatchedGlob&&this.fsw._isntIgnored(this.entryPath(e),e.stats)}},hh=class extends Oie{constructor(e){super();let s={};e&&Object.assign(s,e),this._watched=new Map,this._closers=new Map,this._ignoredPaths=new Set,this._throttled=new Map,this._symlinkPaths=new Map,this._streams=new Set,this.closed=!1,sr(s,"persistent")&&(s.persistent=!0),sr(s,"ignoreInitial")&&(s.ignoreInitial=!1),sr(s,"ignorePermissionErrors")&&(s.ignorePermissionErrors=!1),sr(s,"interval")&&(s.interval=100),sr(s,"binaryInterval")&&(s.binaryInterval=300),sr(s,"disableGlobbing")&&(s.disableGlobbing=!1),s.enableBinaryInterval=s.binaryInterval!==s.interval,sr(s,"useFsEvents")&&(s.useFsEvents=!s.usePolling),T5.canUse()||(s.useFsEvents=!1),sr(s,"usePolling")&&!s.useFsEvents&&(s.usePolling=roe),ioe&&(s.usePolling=!0);let r=process.env.CHOKIDAR_USEPOLLING;if(r!==void 0){let c=r.toLowerCase();c==="false"||c==="0"?s.usePolling=!1:c==="true"||c==="1"?s.usePolling=!0:s.usePolling=!!c}let i=process.env.CHOKIDAR_INTERVAL;i&&(s.interval=Number.parseInt(i,10)),sr(s,"atomic")&&(s.atomic=!s.usePolling&&!s.useFsEvents),s.atomic&&(this._pendingUnlinks=new Map),sr(s,"followSymlinks")&&(s.followSymlinks=!0),sr(s,"awaitWriteFinish")&&(s.awaitWriteFinish=!1),s.awaitWriteFinish===!0&&(s.awaitWriteFinish={});let o=s.awaitWriteFinish;o&&(o.stabilityThreshold||(o.stabilityThreshold=2e3),o.pollInterval||(o.pollInterval=100),this._pendingWrites=new Map),s.ignored&&(s.ignored=yC(s.ignored));let a=0;this._emitReady=()=>{a++,a>=this._readyCount&&(this._emitReady=soe,this._readyEmitted=!0,process.nextTick(()=>this.emit(jie)))},this._emitRaw=(...c)=>this.emit(Gie,...c),this._readyEmitted=!1,this.options=s,s.useFsEvents?this._fsEventsHandler=new T5(this):this._nodeFsHandler=new Wie(this),Object.freeze(s)}add(e,s,n){let{cwd:r,disableGlobbing:i}=this.options;this.closed=!1;let o=O5(e);return r&&(o=o.map(a=>{let c=coe(a,r);return i||!cC(a)?c:$ie(c)})),o=o.filter(a=>a.startsWith(mC)?(this._ignoredPaths.add(a.slice(1)),!1):(this._ignoredPaths.delete(a),this._ignoredPaths.delete(a+pC),this._userIgnored=void 0,!0)),this.options.useFsEvents&&this._fsEventsHandler?(this._readyCount||(this._readyCount=o.length),this.options.persistent&&(this._readyCount+=o.length),o.forEach(a=>this._fsEventsHandler._addToFsEvents(a))):(this._readyCount||(this._readyCount=0),this._readyCount+=o.length,Promise.all(o.map(async a=>{let c=await this._nodeFsHandler._addToNodeFs(a,!n,0,0,s);return c&&this._emitReady(),c})).then(a=>{this.closed||a.filter(c=>c).forEach(c=>{this.add(bt.dirname(c),bt.basename(s||c))})})),this}unwatch(e){if(this.closed)return this;let s=O5(e),{cwd:n}=this.options;return s.forEach(r=>{!bt.isAbsolute(r)&&!this._closers.has(r)&&(n&&(r=bt.join(n,r)),r=bt.resolve(r)),this._closePath(r),this._ignoredPaths.add(r),this._watched.has(r)&&this._ignoredPaths.add(r+pC),this._userIgnored=void 0}),this}close(){if(this.closed)return this._closePromise;this.closed=!0,this.removeAllListeners();let e=[];return this._closers.forEach(s=>s.forEach(n=>{let r=n();r instanceof Promise&&e.push(r)})),this._streams.forEach(s=>s.destroy()),this._userIgnored=void 0,this._readyCount=0,this._readyEmitted=!1,this._watched.forEach(s=>s.dispose()),["closers","watched","streams","symlinkPaths","throttled"].forEach(s=>{this[`_${s}`].clear()}),this._closePromise=e.length?Promise.all(e).then(()=>{}):Promise.resolve(),this._closePromise}getWatched(){let e={};return this._watched.forEach((s,n)=>{let r=this.options.cwd?bt.relative(this.options.cwd,n):n;e[r||$5]=s.getChildren().sort()}),e}emitWithAll(e,s){this.emit(...s),e!==lC&&this.emit(uC,...s)}async _emit(e,s,n,r,i){if(this.closed)return;let o=this.options;noe&&(s=bt.normalize(s)),o.cwd&&(s=bt.relative(o.cwd,s));let a=[e,s];i!==void 0?a.push(n,r,i):r!==void 0?a.push(n,r):n!==void 0&&a.push(n);let c=o.awaitWriteFinish,u;if(c&&(u=this._pendingWrites.get(s)))return u.lastChange=new Date,this;if(o.atomic){if(e===P5)return this._pendingUnlinks.set(s,a),setTimeout(()=>{this._pendingUnlinks.forEach((l,d)=>{this.emit(...l),this.emit(uC,...l),this._pendingUnlinks.delete(d)})},typeof o.atomic=="number"?o.atomic:100),this;e===mh&&this._pendingUnlinks.has(s)&&(e=a[0]=ed,this._pendingUnlinks.delete(s))}if(c&&(e===mh||e===ed)&&this._readyEmitted){let l=(d,p)=>{d?(e=a[0]=lC,a[1]=d,this.emitWithAll(e,a)):p&&(a.length>2?a[2]=p:a.push(p),this.emitWithAll(e,a))};return this._awaitWriteFinish(s,c.stabilityThreshold,e,l),this}if(e===ed&&!this._throttle(ed,s,50))return this;if(o.alwaysStat&&n===void 0&&(e===mh||e===Uie||e===ed)){let l=o.cwd?bt.join(o.cwd,s):s,d;try{d=await ooe(l)}catch{}if(!d||this.closed)return;a.push(d)}return this.emitWithAll(e,a),this}_handleError(e){let s=e&&e.code;return e&&s!=="ENOENT"&&s!=="ENOTDIR"&&(!this.options.ignorePermissionErrors||s!=="EPERM"&&s!=="EACCES")&&this.emit(lC,e),e||this.closed}_throttle(e,s,n){this._throttled.has(e)||this._throttled.set(e,new Map);let r=this._throttled.get(e),i=r.get(s);if(i)return i.count++,!1;let o,a=()=>{let u=r.get(s),l=u?u.count:0;return r.delete(s),clearTimeout(o),u&&clearTimeout(u.timeoutObject),l};o=setTimeout(a,n);let c={timeoutObject:o,clear:a,count:0};return r.set(s,c),c}_incrReadyCount(){return this._readyCount++}_awaitWriteFinish(e,s,n,r){let i,o=e;this.options.cwd&&!bt.isAbsolute(e)&&(o=bt.join(this.options.cwd,e));let a=new Date,c=u=>{SC.stat(o,(l,d)=>{if(l||!this._pendingWrites.has(e)){l&&l.code!=="ENOENT"&&r(l);return}let p=Number(new Date);u&&d.size!==u.size&&(this._pendingWrites.get(e).lastChange=p);let f=this._pendingWrites.get(e);p-f.lastChange>=s?(this._pendingWrites.delete(e),r(void 0,d)):i=setTimeout(c,this.options.awaitWriteFinish.pollInterval,d)})};this._pendingWrites.has(e)||(this._pendingWrites.set(e,{lastChange:a,cancelWait:()=>(this._pendingWrites.delete(e),clearTimeout(i),n)}),i=setTimeout(c,this.options.awaitWriteFinish.pollInterval))}_getGlobIgnored(){return[...this._ignoredPaths.values()]}_isIgnored(e,s){if(this.options.atomic&&Zie.test(e))return!0;if(!this._userIgnored){let{cwd:n}=this.options,r=this.options.ignored,i=r&&r.map(B5(n)),o=yC(i).filter(c=>typeof c===vC&&!cC(c)).map(c=>c+pC),a=this._getGlobIgnored().map(B5(n)).concat(i,o);this._userIgnored=fC(a,void 0,hC)}return this._userIgnored([e,s])}_isntIgnored(e,s){return!this._isIgnored(e,s)}_getWatchHelpers(e,s){let n=s||this.options.disableGlobbing||!cC(e)?e:Bie(e),r=this.options.followSymlinks;return new bC(e,n,r,this)}_getWatchedDir(e){this._boundRemove||(this._boundRemove=this._remove.bind(this));let s=bt.resolve(e);return this._watched.has(s)||this._watched.set(s,new xC(s,this._boundRemove)),this._watched.get(s)}_hasReadPermissions(e){if(this.options.ignorePermissionErrors)return!0;let n=(e&&Number.parseInt(e.mode,10))&511;return!!(4&Number.parseInt(n.toString(8)[0],10))}_remove(e,s,n){let r=bt.join(e,s),i=bt.resolve(r);if(n=n??(this._watched.has(r)||this._watched.has(i)),!this._throttle("remove",r,100))return;!n&&!this.options.useFsEvents&&this._watched.size===1&&this.add(e,s,!0),this._getWatchedDir(r).getChildren().forEach(p=>this._remove(r,p));let c=this._getWatchedDir(e),u=c.has(s);c.remove(s),this._symlinkPaths.has(i)&&this._symlinkPaths.delete(i);let l=r;if(this.options.cwd&&(l=bt.relative(this.options.cwd,r)),this.options.awaitWriteFinish&&this._pendingWrites.has(l)&&this._pendingWrites.get(l).cancelWait()===mh)return;this._watched.delete(r),this._watched.delete(i);let d=n?Hie:P5;u&&!this._isIgnored(r)&&this._emit(d,r),this.options.useFsEvents||this._closePath(r)}_closePath(e){this._closeFile(e);let s=bt.dirname(e);this._getWatchedDir(s).remove(bt.basename(e))}_closeFile(e){let s=this._closers.get(e);s&&(s.forEach(n=>n()),this._closers.delete(e))}_addPathCloser(e,s){if(!s)return;let n=this._closers.get(e);n||(n=[],this._closers.set(e,n)),n.push(s)}_readdirp(e,s){if(this.closed)return;let n={type:uC,alwaysStat:!0,lstat:!0,...s},r=Mie(e,n);return this._streams.add(r),r.once(zie,()=>{r=void 0}),r.once(qie,()=>{r&&(this._streams.delete(r),r=void 0)}),r}};CC.FSWatcher=hh;var doe=(t,e)=>{let s=new hh(e);return s.add(t),s};CC.watch=doe});var G5,Sr,poe,foe,H5,moe,z5,q5=D(()=>{"use strict";G5=oe(require("node:fs")),Sr=oe(require("node:path")),poe=["**/.*","**/.*/**","**/node_modules/**"],foe="cdk.out",H5=t=>t===void 0?[]:Array.isArray(t)?t:[t],moe=t=>{try{let e=G5.readFileSync(t,"utf-8");return JSON.parse(e)??{}}catch{return{}}},z5=(t=process.cwd())=>{let e=t,s=moe(Sr.join(e,"cdk.json")),n=H5(s.watch?.include),r=H5(s.watch?.exclude),i=s.output??foe,o=n.length>0?n:[e],a=[...r,...poe],c=Sr.relative(e,Sr.resolve(e,i));return c.length>0&&!c.startsWith(`..${Sr.sep}`)&&!Sr.isAbsolute(c)&&a.push(`${c}/**`),{include:o,exclude:a,rootDir:e}}});var Z5,Y5,hoe,J5,Q5,goe,yoe,xoe,K5,V5,boe,Soe,X5,e$=D(()=>{"use strict";NS();Qn();Z5={critical:0,high:0,medium:0,low:0,total:0},Y5={counts:{...Z5},byFingerprint:new Map},hoe={CRITICAL:"critical",HIGH:"high",MEDIUM:"medium",LOW:"low"},J5=t=>{let e={counts:{...Z5},byFingerprint:new Map};if(!t)return e;for(let s of Object.values(t)){let n=[...s.sources?.cdkInsights?.issues??[],...s.sources?.cdkNag?.issues??[]];for(let r of n){let i=r.stackName??"_",o=wl(i,s,r);if(e.byFingerprint.has(o))continue;e.byFingerprint.set(o,{issue:r,group:s,stackName:i}),e.counts.total+=1;let a=hoe[r.severity];a&&(e.counts[a]+=1)}}return e},Q5=(t,e)=>{let s=[],n=[];for(let[o,a]of e.byFingerprint)t.byFingerprint.has(o)||s.push({fingerprint:o,...a});for(let[o,a]of t.byFingerprint)e.byFingerprint.has(o)||n.push({fingerprint:o,...a});let r={CRITICAL:0,HIGH:1,MEDIUM:2,LOW:3},i=(o,a)=>{let c=r[o.issue.severity]-r[a.issue.severity];return c!==0?c:o.fingerprint.localeCompare(a.fingerprint)};return s.sort(i),n.sort(i),{added:s,removed:n}},goe=t=>t==="CRITICAL"?de.severity.critical:t==="HIGH"?de.severity.high:t==="MEDIUM"?de.severity.medium:de.severity.low,yoe=(t,e=70)=>{let s=t.replace(/\s+/g," ").trim();return s.length>e?`${s.slice(0,e-1)}\u2026`:s},xoe=t=>{let e=t.stackName!=="_"?t.stackName:"",s=t.group.cdkPath||t.group.friendlyName||t.group.resourceId||"?";return e&&!s.startsWith(`${e}/`)&&!s.includes("/")?`${e}/${s}`:s},K5=(t,e)=>{let n=goe(e.issue.severity)(e.issue.severity.padEnd(8)),r=de.text(xoe(e)),i=de.comment(yoe(e.issue.issue));return` ${t==="+"?de.error("+"):de.success("-")} ${n} ${r} ${i}`},V5=8,boe=t=>t.toTimeString().slice(0,8),Soe=t=>t<1e3?`${t}ms`:`${(t/1e3).toFixed(1)}s`,X5=({state:t,diff:e,trigger:s,elapsedMs:n,timestamp:r,isFirstRun:i,watchPathCount:o})=>{let a=[],c=de.comment("\u2500".repeat(72));a.push(c);let u=[de.primary("\u{1F440} CDK Insights \xB7 watch"),de.comment(boe(r)),de.comment(Soe(n)),de.text(`triggered: ${de.accent(s)}`)].join(de.comment(" \xB7 "));a.push(` ${u}`),a.push("");let{counts:l}=t,d=[`${de.severity.critical(`${_t.critical} CRITICAL`)} ${de.text(String(l.critical).padStart(3))}`,`${de.severity.high(`${_t.high} HIGH`)} ${de.text(String(l.high).padStart(3))}`,`${de.severity.medium(`${_t.medium} MEDIUM`)} ${de.text(String(l.medium).padStart(3))}`,`${de.severity.low(`${_t.low} LOW`)} ${de.text(String(l.low).padStart(3))}`].join(de.comment(" "));if(a.push(` ${d} ${de.comment("\xB7")} ${de.text(`total ${l.total}`)}`),a.push(""),i)a.push(de.comment(" Initial scan complete."));else if(e&&(e.added.length>0||e.removed.length>0)){a.push(de.text(` ${de.error(`+${e.added.length}`)} new \xB7 ${de.success(`-${e.removed.length}`)} resolved since last save:`));let f=e.added.slice(0,V5);for(let g of f)a.push(K5("+",g));e.added.length>f.length&&a.push(de.comment(` \u2026and ${e.added.length-f.length} more added`));let m=e.removed.slice(0,V5);for(let g of m)a.push(K5("-",g));e.removed.length>m.length&&a.push(de.comment(` \u2026and ${e.removed.length-m.length} more resolved`))}else a.push(de.comment(" No changes since last save."));a.push("");let p=[de.comment(`Watching ${o} pattern(s) \xB7 Ctrl+C to exit \xB7 --output table for full report`)].join("");return a.push(` ${p}`),a.push(c),a.join(`
|
|
459
459
|
`)}});var r$={};Ch(r$,{runWatchLoop:()=>Doe});var t$,s$,voe,n$,Coe,Doe,i$=D(()=>{"use strict";t$=oe(require("node:path")),s$=oe(U5());q5();Qn();e$();AC();voe=300,n$=t=>t.output!=="table"&&t.format!=="table",Coe=t=>{let e=n$(t);return{...t,local:!0,github:!1,withIssue:!1,prComment:!1,writeBaseline:!1,diff:!1,failOnCritical:!1,output:e?"summary":"table",format:e?"summary":"table"}},Doe=async t=>{let e=Coe(t.config),s=n$(t.config),{include:n,exclude:r,rootDir:i}=z5(),o=null,a=!1,c=!1,u=Y5,l=!0,d=async f=>{if(a){c=!0;return}a=!0;let m=Date.now();P.info(`\u{1F504} ${f}`);try{let g=await DC(e,t.fingerprint,t.authToken,t.licenseInfo,t.usageData,t.project,t.licenseKey,!0,void 0,void 0,void 0,s);if(s){let h=J5(g?.recommendationMaps),y=l?void 0:Q5(u,h),b=X5({state:h,diff:y,trigger:f,elapsedMs:Date.now()-m,timestamp:new Date,isFirstRun:l,watchPathCount:n.length});console.clear(),console.log(b),u=h,l=!1}else P.success(`\u2713 Done at ${new Date().toLocaleTimeString()}`)}catch(g){let h=g instanceof Error?g.message:String(g);P.error(`Run failed \u2014 keeping last good results. ${h.split(`
|
|
460
460
|
`)[0]}`)}finally{a=!1,c&&(c=!1,d("queued change(s)"))}};P.info(`\u{1F440} Watch mode \u2014 watching ${n.length} include pattern(s) under ${i}`),P.comment(" AI analysis disabled in watch mode. Press Ctrl+C to exit.");let p=s$.default.watch(n,{cwd:i,ignored:r,ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}});await d("initial scan"),p.on("all",(f,m)=>{o&&clearTimeout(o),o=setTimeout(()=>{let g=t$.relative(i,m)||m;d(`${f} ${g}`)},voe)}),p.on("error",f=>{P.error(`Watcher error: ${f instanceof Error?f.message:String(f)}`)}),await new Promise(f=>{let m=()=>{P.info(`
|
|
461
|
-
\u{1F44B} Stopping watcher.`),p.close().then(()=>f())};process.once("SIGINT",m),process.once("SIGTERM",m)})}});async function woe(t,e){let s=t.all?"All stacks":t.stackName||"All stacks",n=await Ii({message:"Which stack would you like to analyze?",default:s,choices:e.map(c=>({name:c,value:c}))}),r=t.output||t.format||"table",i=await Ii({message:"Choose output format:",choices:[{name:"\u{1F4CA} Table (default) - Human-readable table with colors",value:"table"},{name:"\u{1F4C4} Markdown - GitHub-compatible markdown report",value:"markdown"},{name:"\u{1F527} JSON - Structured data for CI/CD integration",value:"json"},{name:"\u{1F4CB} Summary - Brief overview with counts",value:"summary"}],default:r}),o=t.services&&t.services.length>0?t.services:["All services"],a=await qy({message:"Which AWS services would you like to analyze? (Use <space> to toggle, <enter> to confirm)",choices:[{name:"\u{1F50D} All services (recommended)",value:"All services",checked:o.includes("All services")},{name:"\u{1F510} IAM - Identity and Access Management",value:"IAM",checked:o.includes("IAM")},{name:"\u{1F4E6} S3 - Simple Storage Service",value:"S3",checked:o.includes("S3")},{name:"\u26A1 Lambda - Serverless Functions",value:"Lambda",checked:o.includes("Lambda")},{name:"\u{1F5C4}\uFE0F DynamoDB - NoSQL Database",value:"DynamoDB",checked:o.includes("DynamoDB")},{name:"\u{1F5C4}\uFE0F RDS - Relational Database",value:"RDS",checked:o.includes("RDS")},{name:"\u{1F5A5}\uFE0F EC2 - Virtual Machines",value:"EC2",checked:o.includes("EC2")},{name:"\u{1F4E2} SNS - Simple Notification Service",value:"SNS",checked:o.includes("SNS")},{name:"\u{1F4E8} SQS - Simple Queue Service",value:"SQS",checked:o.includes("SQS")},{name:"\u{1F504} Step Functions - Workflow Orchestration",value:"StepFunctions",checked:o.includes("StepFunctions")},{name:"\u{1F4DD} CloudTrail - API Logging",value:"CloudTrail",checked:o.includes("CloudTrail")},{name:"\u{1F310} API Gateway - REST APIs",value:"ApiGateway",checked:o.includes("ApiGateway")},{name:"\u{1F511} Secrets Manager - Secret Management",value:"SecretsManager",checked:o.includes("SecretsManager")},{name:"\u{1F510} KMS - Key Management",value:"KMS",checked:o.includes("KMS")},{name:"\u{1F4E1} EventBridge - Event Routing",value:"EventBridge",checked:o.includes("EventBridge")},{name:"\u{1F310} CloudFront - Content Delivery Network",value:"CloudFront",checked:o.includes("CloudFront")},{name:"\u2696\uFE0F ELB - Elastic Load Balancing",value:"ELB",checked:o.includes("ELB")},{name:"\u{1F433} ECS - Elastic Container Service",value:"ECS",checked:o.includes("ECS")},{name:"\u{1F464} Cognito - User Authentication",value:"Cognito",checked:o.includes("Cognito")},{name:"\u{1F6E1}\uFE0F WAF - Web Application Firewall",value:"WAF",checked:o.includes("WAF")},{name:"\u{1F4CA} CloudWatch - Monitoring & Logging",value:"CloudWatch",checked:o.includes("CloudWatch")},{name:"\u{1F30D} Route53 - DNS Management",value:"Route53",checked:o.includes("Route53")},{name:"\u26A1 ElastiCache - In-Memory Caching",value:"ElastiCache",checked:o.includes("ElastiCache")},{name:"\u{1F4E6} ECR - Container Registry",value:"ECR",checked:o.includes("ECR")},{name:"\u{1F50E} OpenSearch - Search & Analytics",value:"OpenSearch",checked:o.includes("OpenSearch")},{name:"\u{1F50F} ACM - Certificate Manager",value:"ACM",checked:o.includes("ACM")},{name:"\u{1F4BE} Backup - Backup Management",value:"Backup",checked:o.includes("Backup")},{name:"\u{1F517} VPC - Virtual Private Cloud",value:"VPC",checked:o.includes("VPC")},{name:"\u{1F30A} Kinesis - Real-time Streaming",value:"Kinesis",checked:o.includes("Kinesis")},{name:"\u{1F4F1} AppSync - GraphQL APIs",value:"AppSync",checked:o.includes("AppSync")},{name:"\u2638\uFE0F EKS - Kubernetes Service",value:"EKS",checked:o.includes("EKS")},{name:"\u{1F4C8} Redshift - Data Warehouse",value:"Redshift",checked:o.includes("Redshift")},{name:"\u{1F4EC} MSK - Managed Kafka",value:"MSK",checked:o.includes("MSK")},{name:"\u{1F9EA} Glue - ETL & Data Catalog",value:"Glue",checked:o.includes("Glue")}]});return{stackName:n,output:i,services:a}}async function DC(t,e,s,n,r,i,o,a,c,u,l,d){let{stackName:p,output:f,services:m,withIssue:g,ruleFilter:h,failOnCritical:y}=t,b=p==="All stacks"?void 0:p,{stacks:C,inlineFindings:A,pathToLogicalId:w,recommendationMapPerStack:N,assetSourcePaths:L,acknowledgementsPerStack:R,cdkVersion:H,supportsBoxTraces:B,cdkContext:S,resourceIdMetadata:U,validationReportFindings:k}=rm(b),K=Object.keys(C).length;P.success(`Synthesis complete. Found ${K} stack${K===1?"":"s"} to analyze.`),H&&!B&&P.info(`Detected aws-cdk-lib ${H}. Upgrade to >= 2.252.0 for per-property source locations on deferred values.`);let x=Object.values(C).reduce((q,_)=>{let le=Object.entries(_.Resources||{}).filter(([,F])=>!F.Type.startsWith("AWS::CDK::"));return q+le.length},0);x>0?P.info(`\u{1F50D} Preparing to analyze ${x} total resources across ${K} stacks...`):P.warning("No user resources found in stacks. Make sure your CDK app is properly configured.");let v=null,Y=!!s;if(a&&(Y=!1,P.info("\u{1F3E0} Running in local mode - static analysis only")),o&&!a){P.info("\u{1F50D} Checking license quota...");let q=n.licenseType==="FREE"||n.status==="TRIAL",_=n.totalResourcesAnalyzed||0,le=n.trialUsageLimit||n.maxUsage||200,F=Number.isNaN(_)?0:_,te=Number.isNaN(le)?200:le;if(q&&F>=te)Y=!1,v={canProceed:!0,canRunStaticAnalysis:!0,canRunAIAnalysis:!1,quota:{currentResourcesAnalyzed:F,maxResources:te,remainingResources:Math.max(0,te-F),isTrial:!0,trialExpired:!1},reason:`Trial AI credit allowance exceeded (${F}/${te} used)`,upgradePath:"https://cdkinsights.dev/pricing"},P.warning("\u26A0\uFE0F Trial AI credit allowance exceeded \u2014 falling back to static scans only"),P.comment(" Upgrade to Pro for 5,000 AI credits per month");else if(v=await sB({licenseKey:o,requestedResources:x,allowOveruse:t.allowOveruse,usageData:r,licenseInfo:n}),Y=!!s&&(v?.canRunAIAnalysis??!0),v?.quota?.isTrial){let ye=v.quota.currentResourcesAnalyzed,Se=v.quota.maxResources;ye>=Se&&(v={...v,canProceed:!0,canRunStaticAnalysis:!0,canRunAIAnalysis:!1,reason:`Trial AI credit allowance exceeded (${ye}/${Se} used) \u2014 falling back to static scans only`},Y=!1)}v?.quota?.isTrial&&P.displayTrialStatus({currentResourcesAnalyzed:v.quota.currentResourcesAnalyzed,maxResources:v.quota.maxResources,remainingResources:v.quota.remainingResources,isTrial:v.quota.isTrial,trialExpired:v.quota.trialExpired,trialStart:n.trialStart,trialEnd:n.trialEnd,tier:n.tier}),!Y&&v?.quota?P.displayQuotaWarning({currentResourcesAnalyzed:v.quota.currentResourcesAnalyzed,maxResources:v.quota.maxResources,requestedResources:x,remainingResources:v.quota.remainingResources,isTrial:v.quota.isTrial}):Y&&o&&P.success("AI analysis enabled - you'll receive comprehensive recommendations")}let J=Hp(t.services),X=J.services;J.removedAllServices?ie.debug(`Services normalization: removed "All services", using: ${X.join(", ")}`):J.defaultedToAll&&ie.debug('Services normalization: defaulting to "All services"');let re=c||{},pe=t.warnSensitive||re.warnOnly||!1,Ae=(()=>{let q=S?.["cdkInsights:aiModel"];return typeof q=="string"?q:void 0})(),we=fB({flag:t.model,cdkContext:Ae,userConfig:typeof t.ai?.model=="string"?t.ai?.model:void 0,tier:n?.tier});we.downgradedFromTierGate?P.warning(`\u26A0\uFE0F Requested AI model "${we.requestedAlias}" is not available on your tier \u2014 using "${we.alias}" instead.`):we.source!=="tierDefault"&&P.comment(`\u{1F916} AI model: ${we.alias} (from ${we.source})`);let ue=t.ai?.batchSize,Re=typeof ue=="number"&&Number.isFinite(ue)?Math.max(1,Math.floor(ue)):void 0;Re&&Re>1&&P.comment(`\u{1F9FA} AI batching: ${Re} resources per call`);let z={stacks:C,inlineFindings:A,validationReportFindings:k,pathToLogicalId:w,recommendationMapPerStack:N,assetSourcePaths:L,acknowledgementsPerStack:R,output:c$(t),services:X,withIssue:t.withIssue,ruleFilter:t.ruleFilter||[],ignoreRules:t.ignoreRules||[],ignorePaths:t.ignorePaths||[],failOnCritical:t.failOnCritical,authToken:s,fingerprint:e,tier:n?.tier,quotaValidation:v||null,noCache:t.noCache||!1,cache:{enabled:t.cache?.enabled??!0,ttl:t.cache?.ttl??3e5,maxSize:t.cache?.maxSize??5e3},allowOveruse:t.allowOveruse||!1,warnSensitive:pe,sensitiveDataDetection:{disabled:re.enabled===!1,ignoreProperties:re.ignoreProperties||[],allowPatterns:re.allowPatterns||[],strictMode:re.strictMode||!1},cdkContext:S,resourceIdMetadata:U,aiModelId:we.bedrockModelId,aiBatchSize:Re,forceLocal:a,baselineExclude:u,collectFingerprints:l,skipRendering:d};return{...await Um(z),totalResources:x}}var o$,a$,Aoe,c$,u$,AC=D(()=>{"use strict";o$=oe(require("node:fs")),a$=oe(require("node:path"));mb();rr();pp();uF();xb();pF();vF();$b();Qa();vT();Qb();uv();tB();Xa();gy();mp();nB();vb();dt();oB();uB();mv();Qn();mB();yB();$l();Aoe=()=>{let t=a$.resolve(process.cwd(),"cdk.out");return o$.existsSync(t)},c$=t=>t.summaryOnly?"summary":t.format==="json"||t.output==="json"?"json":t.format==="markdown"||t.output==="markdown"?"markdown":t.format==="summary"||t.output==="summary"?"summary":t.format==="sarif"||t.output==="sarif"?"sarif":t.format==="github-actions"||t.output==="github-actions"?"github-actions":"table";u$={command:"scan [stackName]",describe:"Scan CDK stacks for best practices and security issues",builder:t=>t.positional("stackName",{type:"string",describe:"Name of the stack to analyze"}).option("ci",{type:"boolean",default:!1}).option("withIssue",{type:"boolean",description:"Create GitHub issues from findings?"}).option("output",{alias:"o",type:"string",choices:["json","table","markdown","summary","sarif","github-actions"]}).option("all",{type:"boolean",description:"Analyze all CDK stacks,",default:!1}).option("services",{type:"array",string:!0,description:"Only run checks for these services (e.g. IAM, S3, Lambda)"}).option("format",{type:"string",choices:["json","table","markdown","summary","sarif","github-actions"],describe:"Alias for --output (preferred)"}).option("yes",{type:"boolean",description:"Skip prompts and use saved/default values,",default:!1,alias:"y"}).option("reset",{type:"boolean",description:"Clear saved config and start fresh"}).option("redact",{type:"boolean",description:"Redact sensitive resource names in output",default:!1}).option("summaryOnly",{type:"boolean",description:"Only show summary in console output",default:!1}).option("synth",{type:"boolean",description:"Run cdk synth before analysis",default:!1}).option("watch",{type:"boolean",description:"Watch CDK files and re-run static analysis on save. AI, baseline writes, GitHub issues, PR comments and scan history are disabled in watch mode. Reuses cdk.json `watch.include` / `watch.exclude` (same as `cdk watch`).",default:!1}).option("failOnCritical",{type:"boolean",description:"Exit with code 1 if critical issues are found (defaults to true)",default:!0}).option("ruleFilter",{type:"array",string:!0,describe:"Filter findings to only include matching rule IDs or categories (e.g. AwsSolutions-IAM4, Security)"}).option("github",{describe:"Create GitHub issues for findings,",type:"boolean",default:!1}).option("noCache",{describe:"Disable cache and force fresh analysis",type:"boolean",default:!1}).option("allowOveruse",{describe:"Allow AI analysis even when exceeding paid allowance (extra usage will be charged)",type:"boolean",default:!1}).option("local",{describe:"Run static analysis only (skip AI analysis even with a valid license)",type:"boolean",default:!1}).option("warnSensitive",{describe:"Treat sensitive data as warning instead of critical (will not fail CI)",type:"boolean",default:!1}).option("prComment",{describe:"Post analysis summary as a PR comment (GitHub Actions only)",type:"boolean",default:!1}).option("model",{describe:"AI model alias for analysis (nova-lite, mistral-14b, haiku-4-5, sonnet-4-6). Overrides cdk.json and user config. Tier-gated.",type:"string"}).option("diff",{describe:"Only show findings new since the saved baseline (.cdk-insights-baseline.json). Existing findings still appear in summaries but never fail CI.",type:"boolean",default:!1}).option("writeBaseline",{describe:"Write the current findings to .cdk-insights-baseline.json (or --baseline path) and exit 0 regardless of severity. Skips findings rendering.",type:"boolean",default:!1}).option("baseline",{describe:"Path to the baseline file. Defaults to .cdk-insights-baseline.json in cwd. Used by both --diff and --writeBaseline.",type:"string"}),handler:async t=>{try{let e=t.output||t.format;if((e==="json"||e==="sarif")&&(process.env.CDK_INSIGHTS_QUIET_STDOUT="1"),t.reset){Km(),ie.info("\u{1F5D1}\uFE0F Cleared saved CLI preferences.");return}let s=Xu(),n=s.fingerprint,r=s.project;(!n||n.length===0)&&(P.error("Failed to generate system fingerprint for authentication."),P.comment(" This may indicate a permissions issue with reading system information."),process.exit(1));let i=process.env.CDK_INSIGHTS_LICENSE_KEY,o,a,c;if(i){let k=await Sk(i,n,r);k?(o=k.token,a=k.usageData,c=k.licenseInfo||await Gm(i,o),k.fingerprint?n=k.fingerprint:n=Xu(o).fingerprint):(P.warning("\u26A0\uFE0F License validation failed. Running in free tier mode."),P.comment(" Check your license key and internet connection."),c=await Gm(i,void 0))}else c=await Gm(void 0,void 0);let u=`${c?.tier??"free"} tier`;P.info(`\u{1F50D} CDK Insights (${u})`),c.tier==="free"&&!i&&(P.comment("\u{1F4A1} Upgrade to Pro for AI-powered recommendations and GitHub integration"),P.comment(" Visit: https://cdkinsights.dev"));let l=tr(),d=gB(l,t),p=d.ci||fp();if(p&&!d.ci){let k=YR();P.info(`Detected CI environment${k?`: ${k}`:""}`)}let f=!p&&JR();if(p&&!d.stackName&&!d.all&&(d.all=!0),p&&!d.output&&(d.output="json"),d.watch){(d.writeBaseline||d.diff)&&(P.error("--watch cannot be combined with --writeBaseline or --diff."),P.comment(" Run those modes one-shot, then start `cdk-insights scan --watch` for the live loop."),process.exit(2));let k=["json","sarif","github-actions","markdown"],K=typeof t.output=="string"?t.output:void 0,x=typeof t.format=="string"?t.format:void 0,v=K??x;v&&k.includes(v)?(P.warning(`--watch ignores --output ${v}; using compact summary output.`),d.output="summary",d.format="summary"):v==="table"?(d.output="table",d.format="table"):(d.output="summary",d.format="summary"),d.local=!0,d.failOnCritical=!1,!d.stackName&&!d.all&&(d.stackName="All stacks");let{runWatchLoop:Y}=await Promise.resolve().then(()=>(i$(),r$));await Y({config:d,fingerprint:n,authToken:o,licenseInfo:c,usageData:a,project:r,licenseKey:i});return}Aoe()||(P.info("\u26A1 No cdk.out directory found. Running cdk synth..."),xT()||(P.error("Failed to synthesize CDK stacks."),P.comment(" Make sure your CDK app compiles correctly."),process.exit(1)));let m=dF();m.length===0&&(P.error("No CDK stacks found in cdk.out directory."),P.comment(' Make sure you have run "cdk synth" and that your CDK app defines at least one stack.'),P.comment(" If cdk.out exists, check that it contains valid CloudFormation templates."),process.exit(1));let g=["All stacks",...m],h=d;if((t.github||h.withIssue)&&(Ir.isFeatureEnabled("githubIntegration",c.tier)?P.success("\u{1F517} GitHub integration enabled"):(P.error("GitHub integration is not available for your current tier"),P.comment(dp("githubIntegration",c.tier,"GitHub integration")),process.exit(1))),f&&!d.yes){let k=await woe(d,g);h={...d,...k}}h.all&&(h.stackName="All stacks"),h.stackName||(h.stackName="All stacks"),f&&h.output||(h.output=c$(h)),h.format=h.output,(h.output==="json"||h.output==="sarif")&&(process.env.CDK_INSIGHTS_QUIET_STDOUT="1"),f&&h.output==="markdown"&&h.withIssue===void 0?h.withIssue=await bc({message:"Create GitHub issues from findings? (only available with markdown output)",default:!1}):h.withIssue===void 0&&(h.withIssue=!1),h.output==="table"&&(h.withIssue=!1);let y,b=0;if(h.diff)try{let k=gb(h.baseline);k?(y=new Set(k.fingerprints),b=k.fingerprints.length,P.info(`\u{1F4D0} Diff against baseline (${k.fingerprints.length} known findings; ${k.generatedAt}).`)):P.warning("No baseline file found. Run `cdk-insights scan --writeBaseline` to create one. Showing all findings.")}catch(k){P.error(k instanceof Error?k.message:"Failed to load baseline file."),process.exit(2)}let C=h.writeBaseline?new Set:void 0,A=h.writeBaseline===!0,w=cB(),N=new Date,L=await DC(h,n,o,c,a,r,i,h.local,l.sensitiveDataDetection,y,C,A),R=l.telemetry?.enabled===!0&&!!i;if(h.diff&&y){let k=0,K=[];for(let x of Object.values(L.recommendationMaps||{})){if(!x?.sources)continue;let v=[...x.sources.cdkInsights?.issues??[],...x.sources.cdkNag?.issues??[]];k+=v.length,K.push(...v)}if(P.info(`\u{1F4D0} Diff result: ${k} new finding${k===1?"":"s"} (${b} existing, suppressed).`),R){let x=(()=>{try{return gb(h.baseline)}catch{return null}})();Pl({enabled:!0,licenseKey:i,authToken:o,tier:c?.tier,event:{type:"diff_run",newFindings:k,existingSuppressed:b,newSeverities:fv(K),baselineGeneratedAt:x?.generatedAt,failedOnCritical:!!L.hasCriticalIssues}})}}if(h.writeBaseline&&C){let k="1.41.0",{path:K,count:x}=cF([...C],{cliVersion:k,overridePath:h.baseline});if(P.success(`\u{1F4CC} Wrote baseline of ${x} finding${x===1?"":"s"} to ${K}.`),P.comment(" On the next run, pass --diff to see only new findings since this point."),R){let v=[],Y={},J=new Set;for(let X of Object.values(L.recommendationMaps||{})){if(!X?.sources)continue;let re=[...X.sources.cdkInsights?.issues??[],...X.sources.cdkNag?.issues??[]];v.push(...re);for(let Ae of re){let we=Ae.ruleId,ue=/^([A-Za-z][A-Za-z0-9-]+):\s/.exec(Ae.issue??""),Re=we||ue?.[1]||"unknown";Y[Re]=(Y[Re]??0)+1}let pe=X.type;pe?.startsWith("AWS::")&&J.add(pe.split("::")[1])}Pl({enabled:!0,licenseKey:i,authToken:o,tier:c?.tier,event:{type:"baseline_written",totalFindings:x,severityCounts:fv(v),ruleHistogram:Y,uniqueServices:J.size}})}return}let H=[],B=L.recommendationMaps||{},S=new Set;for(let[k,K]of Object.entries(B)){let x=K,v=k.includes(":")?k.substring(k.indexOf(":")+1):k,Y=k.includes(":")?k.substring(0,k.indexOf(":")):"";Y&&S.add(Y);let J=[...x.sources.cdkInsights?.issues??[],...x.sources.cdkNag?.issues??[],...x.sources.validationReport?.issues??[]];for(let X of J)H.push({resourceId:v,issue:X.issue,recommendation:X.recommendation,severity:X.severity,wafPillar:X.wafPillar||"Security",foundBy:X.foundBy||"cdkInsights",validationPluginName:X.validationPluginName,seenInSynth:X.seenInSynth,constructPath:X.constructPath,codeSnippet:X.codeSnippet,sourceLocation:X.sourceLocation,ruleId:X.ruleId,context:X.context,constructType:X.constructType||x.constructType})}if(h.prComment)if(Gf()){P.info("Posting analysis summary to PR...");let k=[...S],K={stackNames:k.length>0?k:[h.stackName||"Unknown"],resourceCount:L.totalResources,issues:H,reportUrl:void 0,aiEnabled:!h.local&&!!i,tier:c?.tier||"free"},x=await Cb({data:K,updateExisting:!0});x.success?P.success("PR comment posted successfully"):P.warning(`Failed to post PR comment: ${x.error}`)}else P.warning("PR comment requested but not in GitHub Actions PR context. Skipping."),P.comment(" PR comments require: GitHub Actions + pull_request event + GITHUB_TOKEN permissions");if(P.success(`Analysis complete! ${h.withIssue?"GitHub issues have been created for the findings.":"Review the findings above."}`),l.scanHistory?.enabled===!0&&i&&o&&!h.writeBaseline){let k="1.41.0",K=new Date,x=!h.local&&!!i,v=iB({scanId:w,cliVersion:k,recommendationMaps:L.recommendationMaps||{},scannedResourceIds:L.scannedResourceIds??new Set,scanStartedAt:N,scanCompletedAt:K,aiAnalysis:{ran:x}});P.info("\u{1F4E4} Uploading scan to CDK Insights...");let Y=await aB({enabled:!0,licenseKey:i,authToken:o,tier:c?.tier,report:v});if(!Y.skipped)if(Y.success)P.success(`Uploaded as scan ${Y.scanId}`),Y.viewUrl&&P.comment(` View: ${Y.viewUrl}`),Y.retentionDays&&P.comment(` Retained for ${Y.retentionDays} day${Y.retentionDays===1?"":"s"} \u2014 adjust in scanHistory settings.`),P.comment(" You opted in via .cdk-insights.json. To opt out, set scanHistory.enabled = false.");else{let J=Y.serverMessage??Y.reason??"unknown";P.warning(`Could not upload scan to CDK Insights (${J}). Run continues normally.`)}}if(l.feedback!==!1&&f&&o&&H.length>0)try{let k=await Ii({message:"Was this analysis helpful?",choices:[{name:"Yes, helpful!",value:"helpful"},{name:"Actionable - I'll fix these",value:"actionable"},{name:"Not helpful",value:"not_helpful"},{name:"Inaccurate findings",value:"inaccurate"},{name:"Skip",value:"skip"}],default:"skip"});if(k!=="skip"){let K=Kn(),v=ST({apiClient:{post:async(J,X)=>{let{data:re}=await Rt.post(`${K}${J}`,X,{headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json","x-cdk-insights-fingerprint":n,"x-cdk-insights-client":"cli"},timeout:1e4});return re}}}),Y={};for(let[J,X]of Object.entries(L.recommendationMaps||{})){let re=X,pe=J.includes(":")?J.substring(J.indexOf(":")+1):J;re.type&&(Y[pe]=re.type)}if(k==="helpful")v.markReportAsHelpful(H,Y).catch(()=>{}),P.comment(" Thanks for your feedback!");else{let J=H.map(X=>({issue:X,rating:k,resourceType:Y[X.resourceId]}));v.submitBatchFeedback(J).catch(()=>{}),P.comment(" Thanks for your feedback!")}}}catch{}else f||P.comment(" Have feedback? Let us know: https://cdkinsights.dev/feedback?source=cli");L.hasCriticalIssues&&(L.hasSensitiveData&&!h.warnSensitive?(P.error("Sensitive data detected. Exiting with code 1."),P.comment(" Use --warn-sensitive to continue without failing, or fix the issues.")):P.error("Critical issues found. Exiting with code 1."),await new Promise(k=>{process.stdout.write("")?k():process.stdout.once("drain",k)}),process.exit(1))}catch(e){let{message:s}=e;P.error(`An error occurred during analysis: ${s||e}`),process.exit(1)}}}});var Gc,v$,S$,Hoe,C$,D$=D(()=>{"use strict";Gc=oe(require("node:fs")),v$=oe(require("node:path")),S$="@aws-cdk/core:stackTrace",Hoe=t=>{let e;try{e=JSON.parse(t)}catch{return{status:"invalid-json"}}if(e===null||typeof e!="object"||Array.isArray(e))return{status:"invalid-json"};let s=e,n=s.context,r=n&&typeof n=="object"&&!Array.isArray(n)?{...n}:{};if(r[S$]===!0)return{status:"already-set",updated:t};r[S$]=!0;let i={...s,context:r},o=t.endsWith(`
|
|
461
|
+
\u{1F44B} Stopping watcher.`),p.close().then(()=>f())};process.once("SIGINT",m),process.once("SIGTERM",m)})}});async function woe(t,e){let s=t.all?"All stacks":t.stackName||"All stacks",n=await Ii({message:"Which stack would you like to analyze?",default:s,choices:e.map(c=>({name:c,value:c}))}),r=t.output||t.format||"table",i=await Ii({message:"Choose output format:",choices:[{name:"\u{1F4CA} Table (default) - Human-readable table with colors",value:"table"},{name:"\u{1F4C4} Markdown - GitHub-compatible markdown report",value:"markdown"},{name:"\u{1F527} JSON - Structured data for CI/CD integration",value:"json"},{name:"\u{1F4CB} Summary - Brief overview with counts",value:"summary"}],default:r}),o=t.services&&t.services.length>0?t.services:["All services"],a=await qy({message:"Which AWS services would you like to analyze? (Use <space> to toggle, <enter> to confirm)",choices:[{name:"\u{1F50D} All services (recommended)",value:"All services",checked:o.includes("All services")},{name:"\u{1F510} IAM - Identity and Access Management",value:"IAM",checked:o.includes("IAM")},{name:"\u{1F4E6} S3 - Simple Storage Service",value:"S3",checked:o.includes("S3")},{name:"\u26A1 Lambda - Serverless Functions",value:"Lambda",checked:o.includes("Lambda")},{name:"\u{1F5C4}\uFE0F DynamoDB - NoSQL Database",value:"DynamoDB",checked:o.includes("DynamoDB")},{name:"\u{1F5C4}\uFE0F RDS - Relational Database",value:"RDS",checked:o.includes("RDS")},{name:"\u{1F5A5}\uFE0F EC2 - Virtual Machines",value:"EC2",checked:o.includes("EC2")},{name:"\u{1F4E2} SNS - Simple Notification Service",value:"SNS",checked:o.includes("SNS")},{name:"\u{1F4E8} SQS - Simple Queue Service",value:"SQS",checked:o.includes("SQS")},{name:"\u{1F504} Step Functions - Workflow Orchestration",value:"StepFunctions",checked:o.includes("StepFunctions")},{name:"\u{1F4DD} CloudTrail - API Logging",value:"CloudTrail",checked:o.includes("CloudTrail")},{name:"\u{1F310} API Gateway - REST APIs",value:"ApiGateway",checked:o.includes("ApiGateway")},{name:"\u{1F511} Secrets Manager - Secret Management",value:"SecretsManager",checked:o.includes("SecretsManager")},{name:"\u{1F510} KMS - Key Management",value:"KMS",checked:o.includes("KMS")},{name:"\u{1F4E1} EventBridge - Event Routing",value:"EventBridge",checked:o.includes("EventBridge")},{name:"\u{1F310} CloudFront - Content Delivery Network",value:"CloudFront",checked:o.includes("CloudFront")},{name:"\u2696\uFE0F ELB - Elastic Load Balancing",value:"ELB",checked:o.includes("ELB")},{name:"\u{1F433} ECS - Elastic Container Service",value:"ECS",checked:o.includes("ECS")},{name:"\u{1F464} Cognito - User Authentication",value:"Cognito",checked:o.includes("Cognito")},{name:"\u{1F6E1}\uFE0F WAF - Web Application Firewall",value:"WAF",checked:o.includes("WAF")},{name:"\u{1F4CA} CloudWatch - Monitoring & Logging",value:"CloudWatch",checked:o.includes("CloudWatch")},{name:"\u{1F30D} Route53 - DNS Management",value:"Route53",checked:o.includes("Route53")},{name:"\u26A1 ElastiCache - In-Memory Caching",value:"ElastiCache",checked:o.includes("ElastiCache")},{name:"\u{1F4E6} ECR - Container Registry",value:"ECR",checked:o.includes("ECR")},{name:"\u{1F50E} OpenSearch - Search & Analytics",value:"OpenSearch",checked:o.includes("OpenSearch")},{name:"\u{1F50F} ACM - Certificate Manager",value:"ACM",checked:o.includes("ACM")},{name:"\u{1F4BE} Backup - Backup Management",value:"Backup",checked:o.includes("Backup")},{name:"\u{1F517} VPC - Virtual Private Cloud",value:"VPC",checked:o.includes("VPC")},{name:"\u{1F30A} Kinesis - Real-time Streaming",value:"Kinesis",checked:o.includes("Kinesis")},{name:"\u{1F4F1} AppSync - GraphQL APIs",value:"AppSync",checked:o.includes("AppSync")},{name:"\u2638\uFE0F EKS - Kubernetes Service",value:"EKS",checked:o.includes("EKS")},{name:"\u{1F4C8} Redshift - Data Warehouse",value:"Redshift",checked:o.includes("Redshift")},{name:"\u{1F4EC} MSK - Managed Kafka",value:"MSK",checked:o.includes("MSK")},{name:"\u{1F9EA} Glue - ETL & Data Catalog",value:"Glue",checked:o.includes("Glue")}]});return{stackName:n,output:i,services:a}}async function DC(t,e,s,n,r,i,o,a,c,u,l,d){let{stackName:p,output:f,services:m,withIssue:g,ruleFilter:h,failOnCritical:y}=t,b=p==="All stacks"?void 0:p,{stacks:C,inlineFindings:A,pathToLogicalId:w,recommendationMapPerStack:N,assetSourcePaths:L,acknowledgementsPerStack:R,cdkVersion:H,supportsBoxTraces:B,cdkContext:S,resourceIdMetadata:U,validationReportFindings:k}=rm(b),K=Object.keys(C).length;P.success(`Synthesis complete. Found ${K} stack${K===1?"":"s"} to analyze.`),H&&!B&&P.info(`Detected aws-cdk-lib ${H}. Upgrade to >= 2.252.0 for per-property source locations on deferred values.`);let x=Object.values(C).reduce((q,_)=>{let le=Object.entries(_.Resources||{}).filter(([,F])=>!F.Type.startsWith("AWS::CDK::"));return q+le.length},0);x>0?P.info(`\u{1F50D} Preparing to analyze ${x} total resources across ${K} stacks...`):P.warning("No user resources found in stacks. Make sure your CDK app is properly configured.");let v=null,Y=!!s;if(a&&(Y=!1,P.info("\u{1F3E0} Running in local mode - static analysis only")),o&&!a){P.info("\u{1F50D} Checking license quota...");let q=n.licenseType==="FREE"||n.status==="TRIAL",_=n.totalResourcesAnalyzed||0,le=n.trialUsageLimit||n.maxUsage||200,F=Number.isNaN(_)?0:_,te=Number.isNaN(le)?200:le;if(q&&F>=te)Y=!1,v={canProceed:!0,canRunStaticAnalysis:!0,canRunAIAnalysis:!1,quota:{currentResourcesAnalyzed:F,maxResources:te,remainingResources:Math.max(0,te-F),isTrial:!0,trialExpired:!1},reason:`Trial AI credit allowance exceeded (${F}/${te} used)`,upgradePath:"https://cdkinsights.dev/pricing"},P.warning("\u26A0\uFE0F Trial AI credit allowance exceeded \u2014 falling back to static scans only"),P.comment(" Upgrade to Pro for 5,000 AI credits per month");else if(v=await sB({licenseKey:o,requestedResources:x,allowOveruse:t.allowOveruse,usageData:r,licenseInfo:n}),Y=!!s&&(v?.canRunAIAnalysis??!0),v?.quota?.isTrial){let ye=v.quota.currentResourcesAnalyzed,Se=v.quota.maxResources;ye>=Se&&(v={...v,canProceed:!0,canRunStaticAnalysis:!0,canRunAIAnalysis:!1,reason:`Trial AI credit allowance exceeded (${ye}/${Se} used) \u2014 falling back to static scans only`},Y=!1)}v?.quota?.isTrial&&P.displayTrialStatus({currentResourcesAnalyzed:v.quota.currentResourcesAnalyzed,maxResources:v.quota.maxResources,remainingResources:v.quota.remainingResources,isTrial:v.quota.isTrial,trialExpired:v.quota.trialExpired,trialStart:n.trialStart,trialEnd:n.trialEnd,tier:n.tier}),!Y&&v?.quota?P.displayQuotaWarning({currentResourcesAnalyzed:v.quota.currentResourcesAnalyzed,maxResources:v.quota.maxResources,requestedResources:x,remainingResources:v.quota.remainingResources,isTrial:v.quota.isTrial}):Y&&o&&P.success("AI analysis enabled - you'll receive comprehensive recommendations")}let J=Hp(t.services),X=J.services;J.removedAllServices?ie.debug(`Services normalization: removed "All services", using: ${X.join(", ")}`):J.defaultedToAll&&ie.debug('Services normalization: defaulting to "All services"');let re=c||{},pe=t.warnSensitive||re.warnOnly||!1,Ae=(()=>{let q=S?.["cdkInsights:aiModel"];return typeof q=="string"?q:void 0})(),we=fB({flag:t.model,cdkContext:Ae,userConfig:typeof t.ai?.model=="string"?t.ai?.model:void 0,tier:n?.tier});we.downgradedFromTierGate?P.warning(`\u26A0\uFE0F Requested AI model "${we.requestedAlias}" is not available on your tier \u2014 using "${we.alias}" instead.`):we.source!=="tierDefault"&&P.comment(`\u{1F916} AI model: ${we.alias} (from ${we.source})`);let ue=t.ai?.batchSize,Re=typeof ue=="number"&&Number.isFinite(ue)?Math.max(1,Math.floor(ue)):void 0;Re&&Re>1&&P.comment(`\u{1F9FA} AI batching: ${Re} resources per call`);let z={stacks:C,inlineFindings:A,validationReportFindings:k,pathToLogicalId:w,recommendationMapPerStack:N,assetSourcePaths:L,acknowledgementsPerStack:R,output:c$(t),services:X,withIssue:t.withIssue,ruleFilter:t.ruleFilter||[],ignoreRules:t.ignoreRules||[],ignorePaths:t.ignorePaths||[],failOnCritical:t.failOnCritical,authToken:s,fingerprint:e,tier:n?.tier,quotaValidation:v||null,noCache:t.noCache||!1,cache:{enabled:t.cache?.enabled??!0,ttl:t.cache?.ttl??3e5,maxSize:t.cache?.maxSize??5e3},allowOveruse:t.allowOveruse||!1,warnSensitive:pe,sensitiveDataDetection:{disabled:re.enabled===!1,ignoreProperties:re.ignoreProperties||[],allowPatterns:re.allowPatterns||[],strictMode:re.strictMode||!1},cdkContext:S,resourceIdMetadata:U,aiModelId:we.bedrockModelId,aiBatchSize:Re,forceLocal:a,baselineExclude:u,collectFingerprints:l,skipRendering:d};return{...await Um(z),totalResources:x}}var o$,a$,Aoe,c$,u$,AC=D(()=>{"use strict";o$=oe(require("node:fs")),a$=oe(require("node:path"));mb();rr();pp();uF();xb();pF();vF();$b();Qa();vT();Qb();uv();tB();Xa();gy();mp();nB();vb();dt();oB();uB();mv();Qn();mB();yB();$l();Aoe=()=>{let t=a$.resolve(process.cwd(),"cdk.out");return o$.existsSync(t)},c$=t=>t.summaryOnly?"summary":t.format==="json"||t.output==="json"?"json":t.format==="markdown"||t.output==="markdown"?"markdown":t.format==="summary"||t.output==="summary"?"summary":t.format==="sarif"||t.output==="sarif"?"sarif":t.format==="github-actions"||t.output==="github-actions"?"github-actions":"table";u$={command:"scan [stackName]",describe:"Scan CDK stacks for best practices and security issues",builder:t=>t.positional("stackName",{type:"string",describe:"Name of the stack to analyze"}).option("ci",{type:"boolean",default:!1}).option("withIssue",{type:"boolean",description:"Create GitHub issues from findings?"}).option("output",{alias:"o",type:"string",choices:["json","table","markdown","summary","sarif","github-actions"]}).option("all",{type:"boolean",description:"Analyze all CDK stacks,",default:!1}).option("services",{type:"array",string:!0,description:"Only run checks for these services (e.g. IAM, S3, Lambda)"}).option("format",{type:"string",choices:["json","table","markdown","summary","sarif","github-actions"],describe:"Alias for --output (preferred)"}).option("yes",{type:"boolean",description:"Skip prompts and use saved/default values,",default:!1,alias:"y"}).option("reset",{type:"boolean",description:"Clear saved config and start fresh"}).option("redact",{type:"boolean",description:"Redact sensitive resource names in output",default:!1}).option("summaryOnly",{type:"boolean",description:"Only show summary in console output",default:!1}).option("synth",{type:"boolean",description:"Run cdk synth before analysis",default:!1}).option("watch",{type:"boolean",description:"Watch CDK files and re-run static analysis on save. AI, baseline writes, GitHub issues, PR comments and scan history are disabled in watch mode. Reuses cdk.json `watch.include` / `watch.exclude` (same as `cdk watch`).",default:!1}).option("failOnCritical",{type:"boolean",description:"Exit with code 1 if critical issues are found (defaults to true)",default:!0}).option("ruleFilter",{type:"array",string:!0,describe:"Filter findings to only include matching rule IDs or categories (e.g. AwsSolutions-IAM4, Security)"}).option("github",{describe:"Create GitHub issues for findings,",type:"boolean",default:!1}).option("noCache",{describe:"Disable cache and force fresh analysis",type:"boolean",default:!1}).option("allowOveruse",{describe:"Allow AI analysis even when exceeding paid allowance (extra usage will be charged)",type:"boolean",default:!1}).option("local",{describe:"Run static analysis only (skip AI analysis even with a valid license)",type:"boolean",default:!1}).option("warnSensitive",{describe:"Treat sensitive data as warning instead of critical (will not fail CI)",type:"boolean",default:!1}).option("prComment",{describe:"Post analysis summary as a PR comment (GitHub Actions only)",type:"boolean",default:!1}).option("model",{describe:"AI model alias for analysis (nova-lite, mistral-14b, haiku-4-5, sonnet-4-6). Overrides cdk.json and user config. Tier-gated.",type:"string"}).option("diff",{describe:"Only show findings new since the saved baseline (.cdk-insights-baseline.json). Existing findings still appear in summaries but never fail CI.",type:"boolean",default:!1}).option("writeBaseline",{describe:"Write the current findings to .cdk-insights-baseline.json (or --baseline path) and exit 0 regardless of severity. Skips findings rendering.",type:"boolean",default:!1}).option("baseline",{describe:"Path to the baseline file. Defaults to .cdk-insights-baseline.json in cwd. Used by both --diff and --writeBaseline.",type:"string"}),handler:async t=>{try{let e=t.output||t.format;if((e==="json"||e==="sarif")&&(process.env.CDK_INSIGHTS_QUIET_STDOUT="1"),t.reset){Km(),ie.info("\u{1F5D1}\uFE0F Cleared saved CLI preferences.");return}let s=Xu(),n=s.fingerprint,r=s.project;(!n||n.length===0)&&(P.error("Failed to generate system fingerprint for authentication."),P.comment(" This may indicate a permissions issue with reading system information."),process.exit(1));let i=process.env.CDK_INSIGHTS_LICENSE_KEY,o,a,c;if(i){let k=await Sk(i,n,r);k?(o=k.token,a=k.usageData,c=k.licenseInfo||await Gm(i,o),k.fingerprint?n=k.fingerprint:n=Xu(o).fingerprint):(P.warning("\u26A0\uFE0F License validation failed. Running in free tier mode."),P.comment(" Check your license key and internet connection."),c=await Gm(i,void 0))}else c=await Gm(void 0,void 0);let u=`${c?.tier??"free"} tier`;P.info(`\u{1F50D} CDK Insights (${u})`),c.tier==="free"&&!i&&(P.comment("\u{1F4A1} Upgrade to Pro for AI-powered recommendations and GitHub integration"),P.comment(" Visit: https://cdkinsights.dev"));let l=tr(),d=gB(l,t),p=d.ci||fp();if(p&&!d.ci){let k=YR();P.info(`Detected CI environment${k?`: ${k}`:""}`)}let f=!p&&JR();if(p&&!d.stackName&&!d.all&&(d.all=!0),p&&!d.output&&(d.output="json"),d.watch){(d.writeBaseline||d.diff)&&(P.error("--watch cannot be combined with --writeBaseline or --diff."),P.comment(" Run those modes one-shot, then start `cdk-insights scan --watch` for the live loop."),process.exit(2));let k=["json","sarif","github-actions","markdown"],K=typeof t.output=="string"?t.output:void 0,x=typeof t.format=="string"?t.format:void 0,v=K??x;v&&k.includes(v)?(P.warning(`--watch ignores --output ${v}; using compact summary output.`),d.output="summary",d.format="summary"):v==="table"?(d.output="table",d.format="table"):(d.output="summary",d.format="summary"),d.local=!0,d.failOnCritical=!1,!d.stackName&&!d.all&&(d.stackName="All stacks");let{runWatchLoop:Y}=await Promise.resolve().then(()=>(i$(),r$));await Y({config:d,fingerprint:n,authToken:o,licenseInfo:c,usageData:a,project:r,licenseKey:i});return}Aoe()||(P.info("\u26A1 No cdk.out directory found. Running cdk synth..."),xT()||(P.error("Failed to synthesize CDK stacks."),P.comment(" Make sure your CDK app compiles correctly."),process.exit(1)));let m=dF();m.length===0&&(P.error("No CDK stacks found in cdk.out directory."),P.comment(' Make sure you have run "cdk synth" and that your CDK app defines at least one stack.'),P.comment(" If cdk.out exists, check that it contains valid CloudFormation templates."),process.exit(1));let g=["All stacks",...m],h=d;if((t.github||h.withIssue)&&(Ir.isFeatureEnabled("githubIntegration",c.tier)?P.success("\u{1F517} GitHub integration enabled"):(P.error("GitHub integration is not available for your current tier"),P.comment(dp("githubIntegration",c.tier,"GitHub integration")),process.exit(1))),f&&!d.yes){let k=await woe(d,g);h={...d,...k}}h.all&&(h.stackName="All stacks"),h.stackName||(h.stackName="All stacks"),f&&h.output||(h.output=c$(h)),h.format=h.output,(h.output==="json"||h.output==="sarif")&&(process.env.CDK_INSIGHTS_QUIET_STDOUT="1"),f&&h.output==="markdown"&&h.withIssue===void 0?h.withIssue=await bc({message:"Create GitHub issues from findings? (only available with markdown output)",default:!1}):h.withIssue===void 0&&(h.withIssue=!1),h.output==="table"&&(h.withIssue=!1);let y,b=0;if(h.diff)try{let k=gb(h.baseline);k?(y=new Set(k.fingerprints),b=k.fingerprints.length,P.info(`\u{1F4D0} Diff against baseline (${k.fingerprints.length} known findings; ${k.generatedAt}).`)):P.warning("No baseline file found. Run `cdk-insights scan --writeBaseline` to create one. Showing all findings.")}catch(k){P.error(k instanceof Error?k.message:"Failed to load baseline file."),process.exit(2)}let C=h.writeBaseline?new Set:void 0,A=h.writeBaseline===!0,w=cB(),N=new Date,L=await DC(h,n,o,c,a,r,i,h.local,l.sensitiveDataDetection,y,C,A),R=l.telemetry?.enabled===!0&&!!i;if(h.diff&&y){let k=0,K=[];for(let x of Object.values(L.recommendationMaps||{})){if(!x?.sources)continue;let v=[...x.sources.cdkInsights?.issues??[],...x.sources.cdkNag?.issues??[]];k+=v.length,K.push(...v)}if(P.info(`\u{1F4D0} Diff result: ${k} new finding${k===1?"":"s"} (${b} existing, suppressed).`),R){let x=(()=>{try{return gb(h.baseline)}catch{return null}})();Pl({enabled:!0,licenseKey:i,authToken:o,tier:c?.tier,event:{type:"diff_run",newFindings:k,existingSuppressed:b,newSeverities:fv(K),baselineGeneratedAt:x?.generatedAt,failedOnCritical:!!L.hasCriticalIssues}})}}if(h.writeBaseline&&C){let k="1.41.1",{path:K,count:x}=cF([...C],{cliVersion:k,overridePath:h.baseline});if(P.success(`\u{1F4CC} Wrote baseline of ${x} finding${x===1?"":"s"} to ${K}.`),P.comment(" On the next run, pass --diff to see only new findings since this point."),R){let v=[],Y={},J=new Set;for(let X of Object.values(L.recommendationMaps||{})){if(!X?.sources)continue;let re=[...X.sources.cdkInsights?.issues??[],...X.sources.cdkNag?.issues??[]];v.push(...re);for(let Ae of re){let we=Ae.ruleId,ue=/^([A-Za-z][A-Za-z0-9-]+):\s/.exec(Ae.issue??""),Re=we||ue?.[1]||"unknown";Y[Re]=(Y[Re]??0)+1}let pe=X.type;pe?.startsWith("AWS::")&&J.add(pe.split("::")[1])}Pl({enabled:!0,licenseKey:i,authToken:o,tier:c?.tier,event:{type:"baseline_written",totalFindings:x,severityCounts:fv(v),ruleHistogram:Y,uniqueServices:J.size}})}return}let H=[],B=L.recommendationMaps||{},S=new Set;for(let[k,K]of Object.entries(B)){let x=K,v=k.includes(":")?k.substring(k.indexOf(":")+1):k,Y=k.includes(":")?k.substring(0,k.indexOf(":")):"";Y&&S.add(Y);let J=[...x.sources.cdkInsights?.issues??[],...x.sources.cdkNag?.issues??[],...x.sources.validationReport?.issues??[]];for(let X of J)H.push({resourceId:v,issue:X.issue,recommendation:X.recommendation,severity:X.severity,wafPillar:X.wafPillar||"Security",foundBy:X.foundBy||"cdkInsights",validationPluginName:X.validationPluginName,seenInSynth:X.seenInSynth,constructPath:X.constructPath,codeSnippet:X.codeSnippet,sourceLocation:X.sourceLocation,ruleId:X.ruleId,context:X.context,constructType:X.constructType||x.constructType})}if(h.prComment)if(Gf()){P.info("Posting analysis summary to PR...");let k=[...S],K={stackNames:k.length>0?k:[h.stackName||"Unknown"],resourceCount:L.totalResources,issues:H,reportUrl:void 0,aiEnabled:!h.local&&!!i,tier:c?.tier||"free"},x=await Cb({data:K,updateExisting:!0});x.success?P.success("PR comment posted successfully"):P.warning(`Failed to post PR comment: ${x.error}`)}else P.warning("PR comment requested but not in GitHub Actions PR context. Skipping."),P.comment(" PR comments require: GitHub Actions + pull_request event + GITHUB_TOKEN permissions");if(P.success(`Analysis complete! ${h.withIssue?"GitHub issues have been created for the findings.":"Review the findings above."}`),l.scanHistory?.enabled===!0&&i&&o&&!h.writeBaseline){let k="1.41.1",K=new Date,x=!h.local&&!!i,v=iB({scanId:w,cliVersion:k,recommendationMaps:L.recommendationMaps||{},scannedResourceIds:L.scannedResourceIds??new Set,scanStartedAt:N,scanCompletedAt:K,aiAnalysis:{ran:x}});P.info("\u{1F4E4} Uploading scan to CDK Insights...");let Y=await aB({enabled:!0,licenseKey:i,authToken:o,tier:c?.tier,report:v});if(!Y.skipped)if(Y.success)P.success(`Uploaded as scan ${Y.scanId}`),Y.viewUrl&&P.comment(` View: ${Y.viewUrl}`),Y.retentionDays&&P.comment(` Retained for ${Y.retentionDays} day${Y.retentionDays===1?"":"s"} \u2014 adjust in scanHistory settings.`),P.comment(" You opted in via .cdk-insights.json. To opt out, set scanHistory.enabled = false.");else{let J=Y.serverMessage??Y.reason??"unknown";P.warning(`Could not upload scan to CDK Insights (${J}). Run continues normally.`)}}if(l.feedback!==!1&&f&&o&&H.length>0)try{let k=await Ii({message:"Was this analysis helpful?",choices:[{name:"Yes, helpful!",value:"helpful"},{name:"Actionable - I'll fix these",value:"actionable"},{name:"Not helpful",value:"not_helpful"},{name:"Inaccurate findings",value:"inaccurate"},{name:"Skip",value:"skip"}],default:"skip"});if(k!=="skip"){let K=Kn(),v=ST({apiClient:{post:async(J,X)=>{let{data:re}=await Rt.post(`${K}${J}`,X,{headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json","x-cdk-insights-fingerprint":n,"x-cdk-insights-client":"cli"},timeout:1e4});return re}}}),Y={};for(let[J,X]of Object.entries(L.recommendationMaps||{})){let re=X,pe=J.includes(":")?J.substring(J.indexOf(":")+1):J;re.type&&(Y[pe]=re.type)}if(k==="helpful")v.markReportAsHelpful(H,Y).catch(()=>{}),P.comment(" Thanks for your feedback!");else{let J=H.map(X=>({issue:X,rating:k,resourceType:Y[X.resourceId]}));v.submitBatchFeedback(J).catch(()=>{}),P.comment(" Thanks for your feedback!")}}}catch{}else f||P.comment(" Have feedback? Let us know: https://cdkinsights.dev/feedback?source=cli");L.hasCriticalIssues&&(L.hasSensitiveData&&!h.warnSensitive?(P.error("Sensitive data detected. Exiting with code 1."),P.comment(" Use --warn-sensitive to continue without failing, or fix the issues.")):P.error("Critical issues found. Exiting with code 1."),await new Promise(k=>{process.stdout.write("")?k():process.stdout.once("drain",k)}),process.exit(1))}catch(e){let{message:s}=e;P.error(`An error occurred during analysis: ${s||e}`),process.exit(1)}}}});var Gc,v$,S$,Hoe,C$,D$=D(()=>{"use strict";Gc=oe(require("node:fs")),v$=oe(require("node:path")),S$="@aws-cdk/core:stackTrace",Hoe=t=>{let e;try{e=JSON.parse(t)}catch{return{status:"invalid-json"}}if(e===null||typeof e!="object"||Array.isArray(e))return{status:"invalid-json"};let s=e,n=s.context,r=n&&typeof n=="object"&&!Array.isArray(n)?{...n}:{};if(r[S$]===!0)return{status:"already-set",updated:t};r[S$]=!0;let i={...s,context:r},o=t.endsWith(`
|
|
462
462
|
`)?`
|
|
463
463
|
`:"";return{status:"added",updated:`${JSON.stringify(i,null,2)}${o}`}},C$=t=>{let e=v$.join(t,"cdk.json");if(!Gc.existsSync(e))return{status:"missing",cdkJsonPath:e};let s=Gc.readFileSync(e,"utf-8"),n=Hoe(s);return n.status==="invalid-json"?{status:"invalid-json",cdkJsonPath:e}:n.status==="already-set"?{status:"already-set",cdkJsonPath:e}:(Gc.writeFileSync(e,n.updated,"utf-8"),{status:"added",cdkJsonPath:e})}});var F$=oe(wh()),Sh=require("node:child_process"),T$=oe(require("node:path")),P$=require("node:util");rr();var L$=oe(u0());var Qd=require("assert");var aH={right:pH,center:fH},cH=0,zd=1,uH=2,qd=3,l0=class{constructor(e){var s;this.width=e.width,this.wrap=(s=e.wrap)!==null&&s!==void 0?s:!0,this.rows=[]}span(...e){let s=this.div(...e);s.span=!0}resetOutput(){this.rows=[]}div(...e){if(e.length===0&&this.div(""),this.wrap&&this.shouldApplyLayoutDSL(...e)&&typeof e[0]=="string")return this.applyLayoutDSL(e[0]);let s=e.map(n=>typeof n=="string"?this.colFromString(n):n);return this.rows.push(s),s}shouldApplyLayoutDSL(...e){return e.length===1&&typeof e[0]=="string"&&/[\t\n]/.test(e[0])}applyLayoutDSL(e){let s=e.split(`
|
|
464
464
|
`).map(r=>r.split(" ")),n=0;return s.forEach(r=>{r.length>1&&Ks.stringWidth(r[0])>n&&(n=Math.min(Math.floor(this.width*.5),Ks.stringWidth(r[0])))}),s.forEach(r=>{this.div(...r.map((i,o)=>({text:i.trim(),padding:this.measurePadding(i),width:o===0&&r.length>1?n:void 0})))}),this.rows[this.rows.length-1]}colFromString(e){return{text:e,padding:this.measurePadding(e)}}measurePadding(e){let s=Ks.stripAnsi(e);return[0,s.match(/\s*$/)[0].length,0,s.match(/^\s*/)[0].length]}toString(){let e=[];return this.rows.forEach(s=>{this.rowToString(s,e)}),e.filter(s=>!s.hidden).map(s=>s.text).join(`
|
|
@@ -582,7 +582,7 @@ ${t.body.join(`
|
|
|
582
582
|
\u2705 Configuration saved successfully!`),console.log(`
|
|
583
583
|
\u{1F4CB} Your current configuration:`),console.log(JSON.stringify(t,null,2))}finally{s.close()}},Zoe=()=>{let t=tr();console.log("\u{1F4CB} Current Configuration:"),console.log(JSON.stringify(t,null,2))},Yoe=t=>{let{key:e,value:s}=t;if(t.help){nd(e);return}s||(console.log(`
|
|
584
584
|
\u274C No value provided for ${e}`),nd(e),process.exit(1));let n=tr(),r;try{e==="services"||e==="ruleFilter"?r=s.split(",").map(o=>o.trim()):e==="cache"?r=JSON.parse(s):s.toLowerCase()==="true"||s.toLowerCase()==="false"?r=s.toLowerCase()==="true":Number.isNaN(Number(s))?r=s:r=Number(s)}catch{ie.error(`\u274C Invalid value for ${e}: ${s}`),nd(e),process.exit(1)}let i=IC[e];i&&(i.type==="boolean"&&typeof r!="boolean"&&(ie.error(`\u274C ${e} must be a boolean (true/false)`),nd(e),process.exit(1)),i.type==="array"&&!Array.isArray(r)&&(ie.error(`\u274C ${e} must be a comma-separated list`),nd(e),process.exit(1))),n[e]=r,Nl(n),ie.info(`\u2714\uFE0F ${e} = ${JSON.stringify(r)}`)},Joe=t=>{let{key:e}=t,s=tr();if(s[e]===void 0){ie.warn(`\u26A0\uFE0F ${e} not set`);return}delete s[e],Nl(s),ie.info(`\u2714\uFE0F Removed ${e}`)},O$=new Set(["vi","vim","nvim","nano","emacs","code","subl","atom","gedit","kate","notepad","notepad++","micro","helix","pico"]),Qoe=t=>{let e=t.split("/").pop()||t;return O$.has(e.toLowerCase())},Xoe=()=>{let t=Zp.get("EDITOR")||"vi";Qoe(t)||(ie.error(`\u274C Unsupported editor: ${t}. Allowed editors: ${Array.from(O$).join(", ")}`),process.exit(1));let e=(0,Sh.spawnSync)(t,[Koe],{stdio:"inherit"});e.error&&(ie.error("\u274C Editor error",{error:e.error.message}),process.exit(1)),ie.info("\u2714\uFE0F Config saved")},kC=t=>t.teamId||process.env.CDK_INSIGHTS_TEAM_ID||void 0,_C=()=>{let t=Zp.get("CDK_INSIGHTS_LICENSE_KEY");if(!t)throw new Error("CDK_INSIGHTS_LICENSE_KEY environment variable is required for team config operations");return{"Content-Type":"application/json","x-api-key":t}},FC=()=>Zp.get("CDK_INSIGHTS_API_URL")||"https://api.cdkinsights.dev",eae=async t=>{let e=kC(t);e||(console.error("\u274C Team ID required. Use --team-id or set CDK_INSIGHTS_TEAM_ID env var."),process.exit(1));try{console.log("\u{1F4E5} Fetching team configurations...");let n=(await Rt.get(`${FC()}/v1/teams/${e}/configs`,{headers:_C()})).data;n.success||(console.error(`\u274C ${n.error||n.message}`),process.exit(1));let i=n.configurations?.find(u=>u.isDefault);if(!i){console.log('\u2139\uFE0F No default team configuration found. Use "config team-configs" to list available configs.');return}let o=Bl(i.configData),c={...tr(),...o};Nl(c),console.log(`\u2705 Pulled team config "${i.configName}" (v${i.version}) to .cdk-insights.json`)}catch(s){console.error(`\u274C Failed to pull config: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}},tae=async t=>{let e=kC(t);e||(console.error("\u274C Team ID required. Use --team-id or set CDK_INSIGHTS_TEAM_ID env var."),process.exit(1));try{let s=tr(),n=t.name||"CLI Config",r=t.description||"";console.log(`\u{1F4E4} Pushing local config as "${n}"...`);let o=(await Rt.post(`${FC()}/v1/teams/${e}/configs`,{configName:n,configDescription:r,configData:s},{headers:_C()})).data;o.success||(console.error(`\u274C ${o.error||o.message}`),process.exit(1));let a=o.configuration;console.log(`\u2705 Config pushed as "${a?.configName}" (v${a?.version})`)}catch(s){console.error(`\u274C Failed to push config: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}},sae=async t=>{let e=kC(t);e||(console.error("\u274C Team ID required. Use --team-id or set CDK_INSIGHTS_TEAM_ID env var."),process.exit(1));try{console.log(`\u{1F4CB} Listing team configurations...
|
|
585
|
-
`);let n=(await Rt.get(`${FC()}/v1/teams/${e}/configs`,{headers:_C()})).data;n.success||(console.error(`\u274C ${n.error||n.message}`),process.exit(1));let r=n.configurations;if(!r||r.length===0){console.log(' No configurations found. Use "config push" to share your config with the team.');return}for(let i of r){let o=i.updatedAt?new Date(i.updatedAt*1e3).toISOString().replace("T"," ").split(".")[0]:"-",a=i.isDefault?" [DEFAULT]":"";console.log(` ${i.configName||"Unnamed"}${a} (v${i.version||1})`),i.configDescription&&console.log(` ${i.configDescription}`),console.log(` Updated: ${o}`),console.log("")}}catch(s){console.error(`\u274C Failed to list configs: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}},nae=async t=>{let{path:e}=t,s=(0,P$.promisify)(Sh.exec),n=e||process.cwd();ie.info(`\u{1F6E0}\uFE0F Running 'cdk synth' in ${n}...`);try{let{stderr:r}=await s("cdk synth",{cwd:n,env:{...process.env,CDK_DEBUG:"true"}});r&&ie.error(r)}catch(r){ie.error("\u274C Failed to synthesize stacks",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}},rae=()=>{ie.info("\u{1F5D1}\uFE0F Clearing caches..."),lk(),vk();let t=ly();ie.info(`\u{1F4C1} Cache directory: ${t.cacheDir}`),ie.info(`\u{1F4CA} Cache status: ${t.cacheFileExists?"Files found":"No persistent cache files"}`)},iae=()=>{ie.info("\u{1F4CA} Cache Status:");let t=ly();if(ie.info(`\u{1F4C1} Cache directory: ${t.cacheDir}`),ie.info(`\u{1F4C2} Directory exists: ${t.cacheDirExists?"Yes":"No"}`),ie.info(`\u{1F4C4} Cache file exists: ${t.cacheFileExists?"Yes":"No"}`),t.cacheSize!==void 0){let e=(t.cacheSize/1024).toFixed(2);ie.info(`\u{1F4CF} Cache file size: ${e} KB`)}ie.info(`\u2699\uFE0F Cache enabled: ${dk()?"Yes":"No"}`),ie.info("\u2139\uFE0F Note: Current cache is in-memory and clears on process restart")},oae=()=>{let t=new L$.default({head:["Command/Option","Description"],colWidths:[30,80]});return t.push(["COMMANDS",""],["scan [stackName]","Scan CDK stacks for best practices and security issues"],["fix","Apply mechanical fixes for findings whose remediation is unambiguous (defaults to dry-run; pass --apply)"],["init","Add cdk-insights npm scripts to your package.json"],["config <action>","Manage project-level configuration"],["synth","Run `cdk synth` automatically before analysis"],["hook","Install Git pre-commit hook for CDK Insights"],["reset","Clear saved prompt answers and CLI preferences"],["clear-cache","Clear the analysis cache"],["cache-status","Show cache status and statistics"],["setup","Interactive setup: install the CDK Insights aspect, Validations plugin, or AwsSolutionsChecks"],["",""]),t.push(["SCAN OPTIONS",""],["--output, -o","Output format: json, table, markdown, summary, sarif, github-actions"],["--format","Alias for --output"],["--all, -a","Analyze all available stacks"],["--services","Comma-separated list of AWS services to analyze"],["--with-issue","Create GitHub issues for findings (markdown output only)"],["--github","Alias for --with-issue"],["--redact","Redact sensitive resource names in output"],["--summaryOnly","Only show summary in console"],["--synth","Run `cdk synth` before analysis"],["--ci","Run in CI mode (no prompts)"],["--yes, -y","Skip prompts and use saved/default values"],["--reset","Clear saved config and start fresh"],["--failOnCritical","Exit with code 1 if critical issues found"],["--ruleFilter","Filter findings by rule IDs or categories"],["--noCache","Disable cache and force fresh analysis"],["--allow-overuse","Allow AI analysis even when exceeding paid allowance (extra usage charged)"],["--local","Run static analysis only (skip AI even with valid license)"],["--warn-sensitive","Treat sensitive data as warning (does not fail CI)"],["--prComment","Post analysis summary as a PR comment (GitHub Actions only)"],["--model","AI model alias (nova-lite, mistral-14b, haiku-4-5, sonnet-4-6). Tier-gated."],["--diff","Filter findings to only those new since the saved baseline (.cdk-insights-baseline.json)"],["--writeBaseline","Save current findings as the baseline; suppresses fail-on-critical and skips rendering"],["--baseline","Override path to the baseline file"],["",""]),t.push(["FIX OPTIONS",""],["--rule","Only fix findings for this rule ID (e.g. AwsSolutions-S10). Without this flag, fixes every supported rule."],["--dry-run","Preview changes without writing files. Default behaviour; pass --apply to disable."],["--apply","Write fixes to disk. Implies --dry-run=false."],["",""]),t.push(["CONFIG SUBCOMMANDS",""],["config list","Show current configuration"],["config set <key> <value>","Set a configuration key"],["config unset <key>","Remove a configuration key"],["config edit","Open config file in your editor"],["config setup","Interactive setup to configure CDK Insights"],["",""]),t.push(["GLOBAL OPTIONS",""],["--help, -h","Show help information"],["--version, -v","Show version information"]),t.toString()},aae={command:"config <action> [key] [value]",describe:"Manage project-level configuration",builder:t=>t.command({command:"list",describe:"Show current configuration",handler:Zoe}).command({command:"set <key> <value>",describe:"Set a configuration key",builder:e=>e.positional("key",{type:"string",choices:["stackName","output","services","redact","withIssue","summaryOnly","synth","ruleFilter","failOnCritical","noCache","allowOveruse","local","cache","sensitiveDataDetection"],describe:"Configuration field to set"}).positional("value",{type:"string",describe:"Value to set (use --help for field-specific help)"}).option("help",{type:"boolean",describe:"Show detailed help for the specified field"}),handler:Yoe}).command({command:"unset <key>",describe:"Remove a configuration key",builder:e=>e.positional("key",{type:"string",choices:["stackName","output","services","redact","withIssue","summaryOnly","synth","ruleFilter","failOnCritical","noCache","allowOveruse","local","cache","sensitiveDataDetection"],describe:"Configuration field to remove"}),handler:Joe}).command({command:"edit",describe:"Open config file in your editor",handler:Xoe}).command({command:"setup",describe:"Interactive setup to configure CDK Insights",handler:Voe}).command({command:"pull",describe:"Pull the team default configuration to local .cdk-insights.json",builder:e=>e.option("team-id",{type:"string",describe:"Team/subscription ID (uses CDK_INSIGHTS_TEAM_ID env var if not set)"}),handler:eae}).command({command:"push",describe:"Push local .cdk-insights.json as a team configuration",builder:e=>e.option("team-id",{type:"string",describe:"Team/subscription ID (uses CDK_INSIGHTS_TEAM_ID env var if not set)"}).option("name",{type:"string",describe:"Configuration name",default:"CLI Config"}).option("description",{type:"string",describe:"Configuration description",default:""}),handler:tae}).command({command:"team-configs",describe:"List available team configurations",builder:e=>e.option("team-id",{type:"string",describe:"Team/subscription ID (uses CDK_INSIGHTS_TEAM_ID env var if not set)"}),handler:sae}).demandCommand(1).help(),handler:()=>{}},cae=()=>{ZR(x0(process.argv)).scriptName("cdk-insights").version("1.41.
|
|
585
|
+
`);let n=(await Rt.get(`${FC()}/v1/teams/${e}/configs`,{headers:_C()})).data;n.success||(console.error(`\u274C ${n.error||n.message}`),process.exit(1));let r=n.configurations;if(!r||r.length===0){console.log(' No configurations found. Use "config push" to share your config with the team.');return}for(let i of r){let o=i.updatedAt?new Date(i.updatedAt*1e3).toISOString().replace("T"," ").split(".")[0]:"-",a=i.isDefault?" [DEFAULT]":"";console.log(` ${i.configName||"Unnamed"}${a} (v${i.version||1})`),i.configDescription&&console.log(` ${i.configDescription}`),console.log(` Updated: ${o}`),console.log("")}}catch(s){console.error(`\u274C Failed to list configs: ${s instanceof Error?s.message:String(s)}`),process.exit(1)}},nae=async t=>{let{path:e}=t,s=(0,P$.promisify)(Sh.exec),n=e||process.cwd();ie.info(`\u{1F6E0}\uFE0F Running 'cdk synth' in ${n}...`);try{let{stderr:r}=await s("cdk synth",{cwd:n,env:{...process.env,CDK_DEBUG:"true"}});r&&ie.error(r)}catch(r){ie.error("\u274C Failed to synthesize stacks",{error:r instanceof Error?r.message:String(r)}),process.exit(1)}},rae=()=>{ie.info("\u{1F5D1}\uFE0F Clearing caches..."),lk(),vk();let t=ly();ie.info(`\u{1F4C1} Cache directory: ${t.cacheDir}`),ie.info(`\u{1F4CA} Cache status: ${t.cacheFileExists?"Files found":"No persistent cache files"}`)},iae=()=>{ie.info("\u{1F4CA} Cache Status:");let t=ly();if(ie.info(`\u{1F4C1} Cache directory: ${t.cacheDir}`),ie.info(`\u{1F4C2} Directory exists: ${t.cacheDirExists?"Yes":"No"}`),ie.info(`\u{1F4C4} Cache file exists: ${t.cacheFileExists?"Yes":"No"}`),t.cacheSize!==void 0){let e=(t.cacheSize/1024).toFixed(2);ie.info(`\u{1F4CF} Cache file size: ${e} KB`)}ie.info(`\u2699\uFE0F Cache enabled: ${dk()?"Yes":"No"}`),ie.info("\u2139\uFE0F Note: Current cache is in-memory and clears on process restart")},oae=()=>{let t=new L$.default({head:["Command/Option","Description"],colWidths:[30,80]});return t.push(["COMMANDS",""],["scan [stackName]","Scan CDK stacks for best practices and security issues"],["fix","Apply mechanical fixes for findings whose remediation is unambiguous (defaults to dry-run; pass --apply)"],["init","Add cdk-insights npm scripts to your package.json"],["config <action>","Manage project-level configuration"],["synth","Run `cdk synth` automatically before analysis"],["hook","Install Git pre-commit hook for CDK Insights"],["reset","Clear saved prompt answers and CLI preferences"],["clear-cache","Clear the analysis cache"],["cache-status","Show cache status and statistics"],["setup","Interactive setup: install the CDK Insights aspect, Validations plugin, or AwsSolutionsChecks"],["",""]),t.push(["SCAN OPTIONS",""],["--output, -o","Output format: json, table, markdown, summary, sarif, github-actions"],["--format","Alias for --output"],["--all, -a","Analyze all available stacks"],["--services","Comma-separated list of AWS services to analyze"],["--with-issue","Create GitHub issues for findings (markdown output only)"],["--github","Alias for --with-issue"],["--redact","Redact sensitive resource names in output"],["--summaryOnly","Only show summary in console"],["--synth","Run `cdk synth` before analysis"],["--ci","Run in CI mode (no prompts)"],["--yes, -y","Skip prompts and use saved/default values"],["--reset","Clear saved config and start fresh"],["--failOnCritical","Exit with code 1 if critical issues found"],["--ruleFilter","Filter findings by rule IDs or categories"],["--noCache","Disable cache and force fresh analysis"],["--allow-overuse","Allow AI analysis even when exceeding paid allowance (extra usage charged)"],["--local","Run static analysis only (skip AI even with valid license)"],["--warn-sensitive","Treat sensitive data as warning (does not fail CI)"],["--prComment","Post analysis summary as a PR comment (GitHub Actions only)"],["--model","AI model alias (nova-lite, mistral-14b, haiku-4-5, sonnet-4-6). Tier-gated."],["--diff","Filter findings to only those new since the saved baseline (.cdk-insights-baseline.json)"],["--writeBaseline","Save current findings as the baseline; suppresses fail-on-critical and skips rendering"],["--baseline","Override path to the baseline file"],["",""]),t.push(["FIX OPTIONS",""],["--rule","Only fix findings for this rule ID (e.g. AwsSolutions-S10). Without this flag, fixes every supported rule."],["--dry-run","Preview changes without writing files. Default behaviour; pass --apply to disable."],["--apply","Write fixes to disk. Implies --dry-run=false."],["",""]),t.push(["CONFIG SUBCOMMANDS",""],["config list","Show current configuration"],["config set <key> <value>","Set a configuration key"],["config unset <key>","Remove a configuration key"],["config edit","Open config file in your editor"],["config setup","Interactive setup to configure CDK Insights"],["",""]),t.push(["GLOBAL OPTIONS",""],["--help, -h","Show help information"],["--version, -v","Show version information"]),t.toString()},aae={command:"config <action> [key] [value]",describe:"Manage project-level configuration",builder:t=>t.command({command:"list",describe:"Show current configuration",handler:Zoe}).command({command:"set <key> <value>",describe:"Set a configuration key",builder:e=>e.positional("key",{type:"string",choices:["stackName","output","services","redact","withIssue","summaryOnly","synth","ruleFilter","failOnCritical","noCache","allowOveruse","local","cache","sensitiveDataDetection"],describe:"Configuration field to set"}).positional("value",{type:"string",describe:"Value to set (use --help for field-specific help)"}).option("help",{type:"boolean",describe:"Show detailed help for the specified field"}),handler:Yoe}).command({command:"unset <key>",describe:"Remove a configuration key",builder:e=>e.positional("key",{type:"string",choices:["stackName","output","services","redact","withIssue","summaryOnly","synth","ruleFilter","failOnCritical","noCache","allowOveruse","local","cache","sensitiveDataDetection"],describe:"Configuration field to remove"}),handler:Joe}).command({command:"edit",describe:"Open config file in your editor",handler:Xoe}).command({command:"setup",describe:"Interactive setup to configure CDK Insights",handler:Voe}).command({command:"pull",describe:"Pull the team default configuration to local .cdk-insights.json",builder:e=>e.option("team-id",{type:"string",describe:"Team/subscription ID (uses CDK_INSIGHTS_TEAM_ID env var if not set)"}),handler:eae}).command({command:"push",describe:"Push local .cdk-insights.json as a team configuration",builder:e=>e.option("team-id",{type:"string",describe:"Team/subscription ID (uses CDK_INSIGHTS_TEAM_ID env var if not set)"}).option("name",{type:"string",describe:"Configuration name",default:"CLI Config"}).option("description",{type:"string",describe:"Configuration description",default:""}),handler:tae}).command({command:"team-configs",describe:"List available team configurations",builder:e=>e.option("team-id",{type:"string",describe:"Team/subscription ID (uses CDK_INSIGHTS_TEAM_ID env var if not set)"}),handler:sae}).demandCommand(1).help(),handler:()=>{}},cae=()=>{ZR(x0(process.argv)).scriptName("cdk-insights").version("1.41.1").usage("Usage: $0 <command> [options]").command(u$).command(d$).command(x$).command(b$).command(k$).command(_$).command(aae).command("hook","Install Git pre-commit hook for CDK Insights",()=>{},()=>p$()).command("synth","Run `cdk synth` automatically before analysis",t=>t.option("path",{type:"string",describe:"Path to the CDK project (defaults to current directory)"}),nae).command("clear-cache","Clear the analysis cache",()=>{},rae).command("cache-status","Show the current cache status",()=>{},iae).demandCommand(1,"Please specify a command.").strict().help().wrap(null).epilog(oae()).parse()};cae();
|
|
586
586
|
/*! Bundled license information:
|
|
587
587
|
|
|
588
588
|
mime-db/index.js:
|