@aws/nx-plugin 1.0.0-rc.5 → 1.0.0-rc.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1198) hide show
  1. package/LICENSE-THIRD-PARTY +5300 -5843
  2. package/README.md +7 -7
  3. package/generators.json +120 -8
  4. package/migrations.json +21 -0
  5. package/package.json +39 -20
  6. package/src/agentcore-gateway/attach-upstream.d.ts +33 -0
  7. package/src/agentcore-gateway/attach-upstream.js +38 -0
  8. package/src/agentcore-gateway/attach-upstream.js.map +1 -0
  9. package/src/agentcore-gateway/files/cedar/policies/README.md +61 -0
  10. package/src/agentcore-gateway/files/cedar/policies/permit-all.cedar +26 -0
  11. package/src/agentcore-gateway/files/project/local-dev.ts.template +134 -0
  12. package/src/agentcore-gateway/gateway-connection/generator.d.ts +21 -0
  13. package/src/agentcore-gateway/gateway-connection/generator.js +101 -0
  14. package/src/agentcore-gateway/gateway-connection/generator.js.map +1 -0
  15. package/src/agentcore-gateway/gateway-connection/schema.d.js +6 -0
  16. package/src/agentcore-gateway/gateway-connection/schema.d.js.map +1 -0
  17. package/src/agentcore-gateway/gateway-connection/schema.d.ts +13 -0
  18. package/src/agentcore-gateway/gateway-connection/schema.json +31 -0
  19. package/src/agentcore-gateway/generator.d.ts +25 -0
  20. package/src/agentcore-gateway/generator.js +166 -0
  21. package/src/agentcore-gateway/generator.js.map +1 -0
  22. package/src/agentcore-gateway/mcp-connection/generator.d.ts +19 -0
  23. package/src/agentcore-gateway/mcp-connection/generator.js +59 -0
  24. package/src/agentcore-gateway/mcp-connection/generator.js.map +1 -0
  25. package/src/agentcore-gateway/mcp-connection/schema.d.js +6 -0
  26. package/src/agentcore-gateway/mcp-connection/schema.d.js.map +1 -0
  27. package/src/agentcore-gateway/mcp-connection/schema.d.ts +13 -0
  28. package/src/agentcore-gateway/mcp-connection/schema.json +31 -0
  29. package/src/agentcore-gateway/schema.d.js +6 -0
  30. package/src/agentcore-gateway/schema.d.js.map +1 -0
  31. package/src/agentcore-gateway/schema.d.ts +17 -0
  32. package/src/agentcore-gateway/schema.json +71 -0
  33. package/src/connection/{agent-serve-local.d.ts → agent-local-dev.d.ts} +7 -7
  34. package/src/connection/agent-local-dev.js +42 -0
  35. package/src/connection/agent-local-dev.js.map +1 -0
  36. package/src/connection/agent-runtime-config.d.ts +1 -1
  37. package/src/connection/agent-runtime-config.js +9 -14
  38. package/src/connection/agent-runtime-config.js.map +1 -1
  39. package/src/connection/generator.d.ts +7 -14
  40. package/src/connection/generator.js +167 -194
  41. package/src/connection/generator.js.map +1 -1
  42. package/src/connection/local-dev.d.ts +15 -0
  43. package/src/connection/local-dev.js +37 -0
  44. package/src/connection/local-dev.js.map +1 -0
  45. package/src/connection/schema.d.js +6 -0
  46. package/src/connection/schema.d.js.map +1 -0
  47. package/src/connection/schema.d.ts +1 -0
  48. package/src/connection/schema.json +5 -0
  49. package/src/connection/supported-connections.d.ts +107 -0
  50. package/src/connection/supported-connections.js +151 -0
  51. package/src/connection/supported-connections.js.map +1 -0
  52. package/src/index.js +2 -5
  53. package/src/index.js.map +1 -1
  54. package/src/infra/app/__snapshots__/generator.spec.ts.snap +106 -100
  55. package/src/infra/app/files/app/src/main.ts.template +1 -1
  56. package/src/infra/app/files/app/src/stages/application-stage.ts.template +1 -1
  57. package/src/infra/app/generator.d.ts +3 -3
  58. package/src/infra/app/generator.js +146 -123
  59. package/src/infra/app/generator.js.map +1 -1
  60. package/src/infra/app/schema.d.js +6 -0
  61. package/src/infra/app/schema.d.js.map +1 -0
  62. package/src/infra/app/schema.d.ts +1 -1
  63. package/src/infra/app/schema.json +5 -0
  64. package/src/init/generator.d.ts +18 -0
  65. package/src/init/generator.js +35 -0
  66. package/src/init/generator.js.map +1 -0
  67. package/src/init/schema.d.js +6 -0
  68. package/src/init/schema.d.js.map +1 -0
  69. package/src/init/schema.d.ts +16 -0
  70. package/src/init/schema.json +35 -0
  71. package/src/license/config-types.d.ts +2 -2
  72. package/src/license/config-types.js +8 -2
  73. package/src/license/config-types.js.map +1 -1
  74. package/src/license/config.d.ts +4 -4
  75. package/src/license/config.js +267 -242
  76. package/src/license/config.js.map +1 -1
  77. package/src/license/dependency-check/check.d.ts +6 -2
  78. package/src/license/dependency-check/check.js +51 -46
  79. package/src/license/dependency-check/check.js.map +1 -1
  80. package/src/license/dependency-check/collectors/collector.js +41 -71
  81. package/src/license/dependency-check/collectors/collector.js.map +1 -1
  82. package/src/license/dependency-check/collectors/npm-collector.js +34 -41
  83. package/src/license/dependency-check/collectors/npm-collector.js.map +1 -1
  84. package/src/license/dependency-check/collectors/python-collector.d.ts +4 -0
  85. package/src/license/dependency-check/collectors/python-collector.js +55 -62
  86. package/src/license/dependency-check/collectors/python-collector.js.map +1 -1
  87. package/src/license/dependency-check/evaluator.d.ts +1 -1
  88. package/src/license/dependency-check/evaluator.js +40 -68
  89. package/src/license/dependency-check/evaluator.js.map +1 -1
  90. package/src/license/dependency-check/executor.d.ts +1 -1
  91. package/src/license/dependency-check/executor.js +30 -22
  92. package/src/license/dependency-check/executor.js.map +1 -1
  93. package/src/license/dependency-check/pre-approved.js +949 -336
  94. package/src/license/dependency-check/pre-approved.js.map +1 -1
  95. package/src/license/dependency-check/types.js +2 -3
  96. package/src/license/dependency-check/types.js.map +1 -1
  97. package/src/license/generator.d.ts +3 -3
  98. package/src/license/generator.js +65 -68
  99. package/src/license/generator.js.map +1 -1
  100. package/src/license/index.d.ts +2 -2
  101. package/src/license/index.js +3 -9
  102. package/src/license/index.js.map +1 -1
  103. package/src/license/known-exceptions.d.ts +2 -2
  104. package/src/license/known-exceptions.js +19 -13
  105. package/src/license/known-exceptions.js.map +1 -1
  106. package/src/license/schema.d.js +6 -0
  107. package/src/license/schema.d.js.map +1 -0
  108. package/src/license/schema.d.ts +2 -0
  109. package/src/license/schema.json +5 -0
  110. package/src/license/sync/generator.d.ts +2 -2
  111. package/src/license/sync/generator.js +94 -119
  112. package/src/license/sync/generator.js.map +1 -1
  113. package/src/license/sync/project-file-sync.d.ts +2 -2
  114. package/src/license/sync/project-file-sync.js +28 -35
  115. package/src/license/sync/project-file-sync.js.map +1 -1
  116. package/src/mcp-server/dev-server.d.ts +1 -0
  117. package/src/mcp-server/dev-server.js +18 -0
  118. package/src/mcp-server/dev-server.js.map +1 -0
  119. package/src/mcp-server/generator-info.d.ts +5 -1
  120. package/src/mcp-server/generator-info.js +149 -165
  121. package/src/mcp-server/generator-info.js.map +1 -1
  122. package/src/mcp-server/guide-pipeline.d.ts +1 -1
  123. package/src/mcp-server/guide-pipeline.js +199 -206
  124. package/src/mcp-server/guide-pipeline.js.map +1 -1
  125. package/src/mcp-server/guide-render.js +10 -25
  126. package/src/mcp-server/guide-render.js.map +1 -1
  127. package/src/mcp-server/index.js +6 -10
  128. package/src/mcp-server/index.js.map +1 -1
  129. package/src/mcp-server/mdx-ast.js +42 -56
  130. package/src/mcp-server/mdx-ast.js.map +1 -1
  131. package/src/mcp-server/option-filter.js +33 -47
  132. package/src/mcp-server/option-filter.js.map +1 -1
  133. package/src/mcp-server/schema-registry.d.ts +9 -3
  134. package/src/mcp-server/schema-registry.js +41 -38
  135. package/src/mcp-server/schema-registry.js.map +1 -1
  136. package/src/mcp-server/schema.d.ts +1 -1
  137. package/src/mcp-server/schema.js +9 -7
  138. package/src/mcp-server/schema.js.map +1 -1
  139. package/src/mcp-server/server.js +24 -24
  140. package/src/mcp-server/server.js.map +1 -1
  141. package/src/mcp-server/tools/add-to-existing-project.d.ts +12 -0
  142. package/src/mcp-server/tools/add-to-existing-project.js +36 -0
  143. package/src/mcp-server/tools/add-to-existing-project.js.map +1 -0
  144. package/src/mcp-server/tools/create-workspace-command.d.ts +1 -1
  145. package/src/mcp-server/tools/create-workspace-command.js +23 -24
  146. package/src/mcp-server/tools/create-workspace-command.js.map +1 -1
  147. package/src/mcp-server/tools/general-guidance.d.ts +3 -3
  148. package/src/mcp-server/tools/general-guidance.js +53 -31
  149. package/src/mcp-server/tools/general-guidance.js.map +1 -1
  150. package/src/mcp-server/tools/generator-guide.d.ts +2 -2
  151. package/src/mcp-server/tools/generator-guide.js +29 -37
  152. package/src/mcp-server/tools/generator-guide.js.map +1 -1
  153. package/src/mcp-server/tools/list-generators.d.ts +2 -2
  154. package/src/mcp-server/tools/list-generators.js +19 -25
  155. package/src/mcp-server/tools/list-generators.js.map +1 -1
  156. package/src/mcp-server/tools/upgrade-workspace.d.ts +11 -0
  157. package/src/mcp-server/tools/upgrade-workspace.js +32 -0
  158. package/src/mcp-server/tools/upgrade-workspace.js.map +1 -0
  159. package/src/migrations/latest/modernize-function-props-cast/migration.d.ts +6 -0
  160. package/src/migrations/latest/modernize-function-props-cast/migration.js +66 -0
  161. package/src/migrations/latest/modernize-function-props-cast/migration.js.map +1 -0
  162. package/src/migrations/latest/restrict-cors-to-custom-domains/migration.d.ts +6 -0
  163. package/src/migrations/latest/restrict-cors-to-custom-domains/migration.js +110 -0
  164. package/src/migrations/latest/restrict-cors-to-custom-domains/migration.js.map +1 -0
  165. package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.d.ts +6 -0
  166. package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.js +129 -0
  167. package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.js.map +1 -0
  168. package/src/open-api/ts-client/__snapshots__/generator.additional-properties.spec.ts.snap +147 -33
  169. package/src/open-api/ts-client/__snapshots__/generator.arrays.spec.ts.snap +308 -75
  170. package/src/open-api/ts-client/__snapshots__/generator.complex-types.spec.ts.snap +298 -74
  171. package/src/open-api/ts-client/__snapshots__/generator.composite-types.spec.ts.snap +748 -103
  172. package/src/open-api/ts-client/__snapshots__/generator.content-type.spec.ts.snap +230 -37
  173. package/src/open-api/ts-client/__snapshots__/generator.duplicate-types.spec.ts.snap +249 -52
  174. package/src/open-api/ts-client/__snapshots__/generator.edge-cases.spec.ts.snap +5535 -0
  175. package/src/open-api/ts-client/__snapshots__/generator.fast-api-gaps.spec.ts.snap +736 -0
  176. package/src/open-api/ts-client/__snapshots__/generator.fast-api.spec.ts.snap +305 -71
  177. package/src/open-api/ts-client/__snapshots__/generator.multipart.spec.ts.snap +298 -0
  178. package/src/open-api/ts-client/__snapshots__/generator.primitive-types.spec.ts.snap +353 -82
  179. package/src/open-api/ts-client/__snapshots__/generator.request.spec.ts.snap +176 -55
  180. package/src/open-api/ts-client/__snapshots__/generator.reserved-keywords.spec.ts.snap +101 -25
  181. package/src/open-api/ts-client/__snapshots__/generator.response.spec.ts.snap +147 -33
  182. package/src/open-api/ts-client/__snapshots__/generator.spec-compliance.spec.ts.snap +1883 -0
  183. package/src/open-api/ts-client/__snapshots__/generator.streaming.spec.ts.snap +392 -88
  184. package/src/open-api/ts-client/__snapshots__/generator.tags.spec.ts.snap +200 -48
  185. package/src/open-api/ts-client/files/client.gen.ts.template +358 -24
  186. package/src/open-api/ts-client/files/types.gen.ts.template +6 -4
  187. package/src/open-api/ts-client/generator.d.ts +3 -3
  188. package/src/open-api/ts-client/generator.js +41 -26
  189. package/src/open-api/ts-client/generator.js.map +1 -1
  190. package/src/open-api/ts-client/schema.d.js +6 -0
  191. package/src/open-api/ts-client/schema.d.js.map +1 -0
  192. package/src/open-api/ts-hooks/files/options-proxy.gen.ts.template +7 -2
  193. package/src/open-api/ts-hooks/generator.d.ts +3 -3
  194. package/src/open-api/ts-hooks/generator.js +17 -21
  195. package/src/open-api/ts-hooks/generator.js.map +1 -1
  196. package/src/open-api/ts-hooks/generator.spec.tsx +84 -14
  197. package/src/open-api/ts-hooks/schema.d.js +6 -0
  198. package/src/open-api/ts-hooks/schema.d.js.map +1 -0
  199. package/src/open-api/ts-metadata/generator.d.ts +3 -3
  200. package/src/open-api/ts-metadata/generator.js +12 -20
  201. package/src/open-api/ts-metadata/generator.js.map +1 -1
  202. package/src/open-api/ts-metadata/schema.d.js +6 -0
  203. package/src/open-api/ts-metadata/schema.d.js.map +1 -0
  204. package/src/open-api/utils/codegen-data/languages.d.ts +3 -5
  205. package/src/open-api/utils/codegen-data/languages.js +59 -66
  206. package/src/open-api/utils/codegen-data/languages.js.map +1 -1
  207. package/src/open-api/utils/codegen-data/types.d.ts +255 -10
  208. package/src/open-api/utils/codegen-data/types.js +54 -30
  209. package/src/open-api/utils/codegen-data/types.js.map +1 -1
  210. package/src/open-api/utils/codegen-data.d.ts +8 -4
  211. package/src/open-api/utils/codegen-data.js +494 -674
  212. package/src/open-api/utils/codegen-data.js.map +1 -1
  213. package/src/open-api/utils/normalise.d.ts +5 -1
  214. package/src/open-api/utils/normalise.js +437 -246
  215. package/src/open-api/utils/normalise.js.map +1 -1
  216. package/src/open-api/utils/parse.d.ts +2 -2
  217. package/src/open-api/utils/parse.js +11 -13
  218. package/src/open-api/utils/parse.js.map +1 -1
  219. package/src/open-api/utils/parser.d.ts +55 -0
  220. package/src/open-api/utils/parser.js +787 -0
  221. package/src/open-api/utils/parser.js.map +1 -0
  222. package/src/open-api/utils/refs.d.ts +1 -1
  223. package/src/open-api/utils/refs.js +12 -22
  224. package/src/open-api/utils/refs.js.map +1 -1
  225. package/src/open-api/utils/types.d.ts +18 -0
  226. package/src/open-api/utils/types.js +5 -2
  227. package/src/open-api/utils/types.js.map +1 -1
  228. package/src/preset/__snapshots__/generator.spec.ts.snap +149 -28
  229. package/src/preset/generator.d.ts +4 -4
  230. package/src/preset/generator.js +66 -147
  231. package/src/preset/generator.js.map +1 -1
  232. package/src/preset/schema.d.js +6 -0
  233. package/src/preset/schema.d.js.map +1 -0
  234. package/src/preset/schema.d.ts +6 -2
  235. package/src/preset/schema.json +16 -5
  236. package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +321 -0
  237. package/src/py/agent/__snapshots__/generator.frameworks.spec.ts.snap +734 -0
  238. package/src/py/agent/__snapshots__/{generator.spec.ts.snap → generator.protocols.spec.ts.snap} +182 -314
  239. package/src/py/agent/a2a-connection/__snapshots__/generator.spec.ts.snap +189 -0
  240. package/src/py/agent/a2a-connection/files/agent-connection/app/__targetAgentSnakeCase___client_strands.py.template +30 -0
  241. package/src/py/agent/a2a-connection/files/langchain/agent-connection/app/__targetAgentSnakeCase___client_langchain.py.template +28 -0
  242. package/src/py/agent/a2a-connection/generator.d.ts +3 -3
  243. package/src/py/agent/a2a-connection/generator.js +113 -85
  244. package/src/py/agent/a2a-connection/generator.js.map +1 -1
  245. package/src/py/agent/a2a-connection/schema.d.js +8 -0
  246. package/src/py/agent/a2a-connection/schema.d.js.map +1 -0
  247. package/src/py/agent/a2a-connection/schema.d.ts +1 -0
  248. package/src/py/agent/a2a-connection/schema.json +5 -0
  249. package/src/py/agent/files/a2a-langchain/main.py.template +89 -0
  250. package/src/py/agent/files/ag-ui-langchain/main.py.template +83 -0
  251. package/src/py/agent/files/common/agent.py.template +2 -0
  252. package/src/py/agent/files/common-langchain/agent.py.template +30 -0
  253. package/src/py/agent/files/deploy/Dockerfile.template +1 -1
  254. package/src/py/agent/files/http/init.py.template +7 -25
  255. package/src/py/agent/files/http/main.py.template +3 -4
  256. package/src/py/agent/files/http-langchain/main.py.template +84 -0
  257. package/src/py/agent/gateway-connection/__snapshots__/generator.spec.ts.snap +184 -0
  258. package/src/py/agent/gateway-connection/files/agent-connection/app/__gatewaySnakeCase___client_strands.py.template +35 -0
  259. package/src/py/agent/gateway-connection/files/langchain/agent-connection/app/__gatewaySnakeCase___client_langchain.py.template +34 -0
  260. package/src/py/agent/gateway-connection/generator.d.ts +10 -0
  261. package/src/py/agent/gateway-connection/generator.js +119 -0
  262. package/src/py/agent/gateway-connection/generator.js.map +1 -0
  263. package/src/py/agent/gateway-connection/schema.d.js +6 -0
  264. package/src/py/agent/gateway-connection/schema.d.js.map +1 -0
  265. package/src/py/agent/gateway-connection/schema.d.ts +13 -0
  266. package/src/py/agent/gateway-connection/schema.json +31 -0
  267. package/src/py/agent/generator.d.ts +3 -3
  268. package/src/py/agent/generator.js +290 -183
  269. package/src/py/agent/generator.js.map +1 -1
  270. package/src/py/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +153 -89
  271. package/src/py/agent/mcp-connection/files/agent-connection/app/__mcpServerSnakeCase___client_strands.py.template +30 -0
  272. package/src/py/agent/mcp-connection/files/langchain/agent-connection/app/__mcpServerSnakeCase___client_langchain.py.template +30 -0
  273. package/src/py/agent/mcp-connection/generator.d.ts +3 -3
  274. package/src/py/agent/mcp-connection/generator.js +65 -126
  275. package/src/py/agent/mcp-connection/generator.js.map +1 -1
  276. package/src/py/agent/mcp-connection/schema.d.js +8 -0
  277. package/src/py/agent/mcp-connection/schema.d.js.map +1 -0
  278. package/src/py/agent/mcp-connection/schema.d.ts +1 -0
  279. package/src/py/agent/mcp-connection/schema.json +5 -0
  280. package/src/py/agent/react-connection/__snapshots__/generator.spec.ts.snap +11 -19
  281. package/src/py/agent/react-connection/generator.d.ts +4 -4
  282. package/src/py/agent/react-connection/generator.js +55 -59
  283. package/src/py/agent/react-connection/generator.js.map +1 -1
  284. package/src/py/agent/react-connection/{serve-local.d.ts → local-dev.d.ts} +6 -6
  285. package/src/py/agent/react-connection/local-dev.js +36 -0
  286. package/src/py/agent/react-connection/local-dev.js.map +1 -0
  287. package/src/py/agent/react-connection/schema.d.js +8 -0
  288. package/src/py/agent/react-connection/schema.d.js.map +1 -0
  289. package/src/py/agent/react-connection/schema.d.ts +1 -0
  290. package/src/py/agent/react-connection/schema.json +5 -0
  291. package/src/py/agent/schema.d.js +6 -0
  292. package/src/py/agent/schema.d.js.map +1 -0
  293. package/src/py/agent/schema.d.ts +2 -1
  294. package/src/py/agent/schema.json +6 -1
  295. package/src/py/api/generator.d.ts +3 -3
  296. package/src/py/api/generator.js +12 -11
  297. package/src/py/api/generator.js.map +1 -1
  298. package/src/py/api/schema.d.js +6 -0
  299. package/src/py/api/schema.d.js.map +1 -0
  300. package/src/py/api/schema.d.ts +1 -0
  301. package/src/py/api/schema.json +5 -0
  302. package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +1522 -0
  303. package/src/py/dynamodb/agent-connection/__snapshots__/generator.spec.ts.snap +45 -0
  304. package/src/py/dynamodb/agent-connection/generator.d.ts +10 -0
  305. package/src/py/dynamodb/agent-connection/generator.js +39 -0
  306. package/src/py/dynamodb/agent-connection/generator.js.map +1 -0
  307. package/src/py/dynamodb/agent-connection/schema.d.js +8 -0
  308. package/src/py/dynamodb/agent-connection/schema.d.js.map +1 -0
  309. package/src/py/dynamodb/agent-connection/schema.d.ts +15 -0
  310. package/src/py/dynamodb/agent-connection/schema.json +27 -0
  311. package/src/py/dynamodb/fast-api-connection/__snapshots__/generator.spec.ts.snap +23 -0
  312. package/src/py/dynamodb/fast-api-connection/generator.d.ts +10 -0
  313. package/src/py/dynamodb/fast-api-connection/generator.js +37 -0
  314. package/src/py/dynamodb/fast-api-connection/generator.js.map +1 -0
  315. package/src/py/dynamodb/fast-api-connection/schema.d.js +8 -0
  316. package/src/py/dynamodb/fast-api-connection/schema.d.js.map +1 -0
  317. package/src/py/dynamodb/fast-api-connection/schema.d.ts +13 -0
  318. package/src/py/dynamodb/fast-api-connection/schema.json +23 -0
  319. package/src/py/dynamodb/files/__name__/__init__.py.template +6 -0
  320. package/src/py/dynamodb/files/__name__/client.py.template +39 -0
  321. package/src/py/dynamodb/files/__name__/entities/__init__.py.template +4 -0
  322. package/src/py/dynamodb/files/__name__/entities/base.py.template +63 -0
  323. package/src/py/dynamodb/files/__name__/entities/example.py.template +64 -0
  324. package/src/py/dynamodb/files/config.json.template +24 -0
  325. package/src/py/dynamodb/generator.d.ts +10 -0
  326. package/src/py/dynamodb/generator.js +110 -0
  327. package/src/py/dynamodb/generator.js.map +1 -0
  328. package/src/py/dynamodb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +45 -0
  329. package/src/py/dynamodb/mcp-server-connection/generator.d.ts +10 -0
  330. package/src/py/dynamodb/mcp-server-connection/generator.js +39 -0
  331. package/src/py/dynamodb/mcp-server-connection/generator.js.map +1 -0
  332. package/src/py/dynamodb/mcp-server-connection/schema.d.js +8 -0
  333. package/src/py/dynamodb/mcp-server-connection/schema.d.js.map +1 -0
  334. package/src/py/dynamodb/mcp-server-connection/schema.d.ts +15 -0
  335. package/src/py/dynamodb/mcp-server-connection/schema.json +27 -0
  336. package/src/py/dynamodb/schema.d.js +6 -0
  337. package/src/py/dynamodb/schema.d.js.map +1 -0
  338. package/src/py/dynamodb/schema.d.ts +16 -0
  339. package/src/py/dynamodb/schema.json +75 -0
  340. package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +238 -4694
  341. package/src/py/fast-api/__snapshots__/generator.terraform.spec.ts.snap +5409 -0
  342. package/src/py/fast-api/files/app/__name__/init.py.template +5 -22
  343. package/src/py/fast-api/files/app/__name__/main.py.template +4 -1
  344. package/src/py/fast-api/generator.d.ts +3 -3
  345. package/src/py/fast-api/generator.js +90 -87
  346. package/src/py/fast-api/generator.js.map +1 -1
  347. package/src/py/fast-api/react/__snapshots__/generator.spec.ts.snap +4 -3
  348. package/src/py/fast-api/react/generator.d.ts +4 -4
  349. package/src/py/fast-api/react/generator.js +25 -25
  350. package/src/py/fast-api/react/generator.js.map +1 -1
  351. package/src/py/fast-api/react/open-api.d.ts +1 -1
  352. package/src/py/fast-api/react/open-api.js +31 -29
  353. package/src/py/fast-api/react/open-api.js.map +1 -1
  354. package/src/py/fast-api/react/schema.d.js +6 -0
  355. package/src/py/fast-api/react/schema.d.js.map +1 -0
  356. package/src/py/fast-api/react/schema.d.ts +1 -0
  357. package/src/py/fast-api/react/schema.json +5 -0
  358. package/src/py/fast-api/schema.d.js +6 -0
  359. package/src/py/fast-api/schema.d.js.map +1 -0
  360. package/src/py/fast-api/schema.d.ts +1 -0
  361. package/src/py/fast-api/schema.json +5 -0
  362. package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +4 -4
  363. package/src/py/lambda-function/generator.d.ts +3 -3
  364. package/src/py/lambda-function/generator.js +60 -59
  365. package/src/py/lambda-function/generator.js.map +1 -1
  366. package/src/py/lambda-function/schema.d.js +6 -0
  367. package/src/py/lambda-function/schema.d.js.map +1 -0
  368. package/src/py/lambda-function/schema.d.ts +1 -0
  369. package/src/py/lambda-function/schema.json +5 -0
  370. package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +209 -19
  371. package/src/py/mcp-server/files/deploy/Dockerfile.template +1 -1
  372. package/src/py/mcp-server/generator.d.ts +3 -3
  373. package/src/py/mcp-server/generator.js +163 -127
  374. package/src/py/mcp-server/generator.js.map +1 -1
  375. package/src/py/mcp-server/schema.d.js +6 -0
  376. package/src/py/mcp-server/schema.d.js.map +1 -0
  377. package/src/py/mcp-server/schema.d.ts +1 -0
  378. package/src/py/mcp-server/schema.json +5 -0
  379. package/src/py/project/generator.d.ts +17 -4
  380. package/src/py/project/generator.js +229 -130
  381. package/src/py/project/generator.js.map +1 -1
  382. package/src/py/project/schema.d.js +6 -0
  383. package/src/py/project/schema.d.js.map +1 -0
  384. package/src/py/project/schema.d.ts +1 -0
  385. package/src/py/project/schema.json +5 -0
  386. package/src/py/rdb/__snapshots__/generator.spec.ts.snap +2070 -0
  387. package/src/py/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +104 -0
  388. package/src/py/rdb/agent-connection/generator.d.ts +10 -0
  389. package/src/py/rdb/agent-connection/generator.js +46 -0
  390. package/src/py/rdb/agent-connection/generator.js.map +1 -0
  391. package/src/py/rdb/agent-connection/schema.d.js +8 -0
  392. package/src/py/rdb/agent-connection/schema.d.js.map +1 -0
  393. package/src/py/rdb/agent-connection/schema.d.ts +15 -0
  394. package/src/py/rdb/agent-connection/schema.json +27 -0
  395. package/src/py/rdb/fast-api-connection/__snapshots__/generator.spec.ts.snap +44 -0
  396. package/src/py/rdb/fast-api-connection/files/__apiModuleName__/dependencies/__rdbNameSnake__.py.template +14 -0
  397. package/src/py/rdb/fast-api-connection/generator.d.ts +10 -0
  398. package/src/py/rdb/fast-api-connection/generator.js +54 -0
  399. package/src/py/rdb/fast-api-connection/generator.js.map +1 -0
  400. package/src/py/rdb/fast-api-connection/schema.d.js +8 -0
  401. package/src/py/rdb/fast-api-connection/schema.d.js.map +1 -0
  402. package/src/py/rdb/fast-api-connection/schema.d.ts +13 -0
  403. package/src/py/rdb/fast-api-connection/schema.json +23 -0
  404. package/src/py/rdb/files/Dockerfile.create-db-user.template +14 -0
  405. package/src/py/rdb/files/Dockerfile.migration.template +14 -0
  406. package/src/py/rdb/files/__name__/__init__.py.template +3 -0
  407. package/src/py/rdb/files/__name__/connection.py.template +55 -0
  408. package/src/py/rdb/files/__name__/create_db_user_handler.py.template +97 -0
  409. package/src/py/rdb/files/__name__/migration_handler.py.template +36 -0
  410. package/src/py/rdb/files/__name__/models/__init__.py.template +3 -0
  411. package/src/py/rdb/files/__name__/models/example.py.template +8 -0
  412. package/src/py/rdb/files/__name__/utils.py.template +104 -0
  413. package/src/py/rdb/files/alembic.ini.template +38 -0
  414. package/src/py/rdb/files/config.json.template +14 -0
  415. package/src/py/rdb/files/migrations/env.py.template +80 -0
  416. package/src/py/rdb/files/migrations/script.py.mako.template +28 -0
  417. package/src/py/rdb/generator.d.ts +6 -0
  418. package/src/py/rdb/generator.js +280 -0
  419. package/src/py/rdb/generator.js.map +1 -0
  420. package/src/py/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +101 -0
  421. package/src/py/rdb/mcp-server-connection/generator.d.ts +10 -0
  422. package/src/py/rdb/mcp-server-connection/generator.js +46 -0
  423. package/src/py/rdb/mcp-server-connection/generator.js.map +1 -0
  424. package/src/py/rdb/mcp-server-connection/schema.d.js +8 -0
  425. package/src/py/rdb/mcp-server-connection/schema.d.js.map +1 -0
  426. package/src/py/rdb/mcp-server-connection/schema.d.ts +15 -0
  427. package/src/py/rdb/mcp-server-connection/schema.json +27 -0
  428. package/src/py/rdb/schema.d.js +6 -0
  429. package/src/py/rdb/schema.d.js.map +1 -0
  430. package/src/py/rdb/schema.d.ts +16 -0
  431. package/src/py/rdb/schema.json +77 -0
  432. package/src/py/rdb/utils.d.ts +6 -0
  433. package/src/py/rdb/utils.js +16 -0
  434. package/src/py/rdb/utils.js.map +1 -0
  435. package/src/sdk/agentcore-gateway.d.ts +6 -0
  436. package/src/sdk/agentcore-gateway.js +7 -0
  437. package/src/sdk/agentcore-gateway.js.map +1 -0
  438. package/src/sdk/connection.d.ts +6 -0
  439. package/src/sdk/connection.js +6 -0
  440. package/src/sdk/connection.js.map +1 -0
  441. package/src/sdk/license.d.ts +8 -0
  442. package/src/sdk/license.js +7 -0
  443. package/src/sdk/license.js.map +1 -0
  444. package/src/sdk/open-api.d.ts +10 -0
  445. package/src/sdk/open-api.js +8 -0
  446. package/src/sdk/open-api.js.map +1 -0
  447. package/src/sdk/py.d.ts +16 -0
  448. package/src/sdk/py.js +11 -0
  449. package/src/sdk/py.js.map +1 -0
  450. package/src/sdk/terraform.d.ts +6 -0
  451. package/src/sdk/terraform.js +7 -0
  452. package/src/sdk/terraform.js.map +1 -0
  453. package/src/sdk/ts.d.ts +37 -0
  454. package/src/sdk/ts.js +39 -0
  455. package/src/sdk/ts.js.map +1 -0
  456. package/{sdk → src/sdk}/utils/ast.d.ts +1 -2
  457. package/src/sdk/utils/ast.js +6 -0
  458. package/src/sdk/utils/ast.js.map +1 -0
  459. package/{sdk → src/sdk}/utils/format.d.ts +1 -1
  460. package/src/sdk/utils/format.js +6 -0
  461. package/src/sdk/utils/format.js.map +1 -0
  462. package/{sdk → src/sdk}/utils/test.d.ts +1 -1
  463. package/src/sdk/utils/test.js +6 -0
  464. package/src/sdk/utils/test.js.map +1 -0
  465. package/src/smithy/project/__snapshots__/generator.spec.ts.snap +19 -24
  466. package/src/smithy/project/files/build.Dockerfile.template +1 -4
  467. package/src/smithy/project/files/src/operations/echo.smithy.template +1 -0
  468. package/src/smithy/project/generator.d.ts +3 -3
  469. package/src/smithy/project/generator.js +64 -57
  470. package/src/smithy/project/generator.js.map +1 -1
  471. package/src/smithy/project/schema.d.js +6 -0
  472. package/src/smithy/project/schema.d.js.map +1 -0
  473. package/src/smithy/project/schema.d.ts +1 -0
  474. package/src/smithy/project/schema.json +5 -0
  475. package/src/smithy/react-connection/__snapshots__/generator.spec.ts.snap +1 -1
  476. package/src/smithy/react-connection/generator.d.ts +3 -3
  477. package/src/smithy/react-connection/generator.js +39 -47
  478. package/src/smithy/react-connection/generator.js.map +1 -1
  479. package/src/smithy/react-connection/schema.d.js +6 -0
  480. package/src/smithy/react-connection/schema.d.js.map +1 -0
  481. package/src/smithy/react-connection/schema.d.ts +1 -0
  482. package/src/smithy/react-connection/schema.json +5 -0
  483. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +850 -136
  484. package/src/smithy/ts/api/files/handler.ts.template +2 -2
  485. package/src/smithy/ts/api/files/local-server.ts.template +2 -2
  486. package/src/smithy/ts/api/files/operations/echo.ts.template +2 -2
  487. package/src/smithy/ts/api/files/service.ts.template +3 -3
  488. package/src/smithy/ts/api/generator.d.ts +3 -3
  489. package/src/smithy/ts/api/generator.js +131 -105
  490. package/src/smithy/ts/api/generator.js.map +1 -1
  491. package/src/smithy/ts/api/schema.d.js +6 -0
  492. package/src/smithy/ts/api/schema.d.js.map +1 -0
  493. package/src/smithy/ts/api/schema.d.ts +1 -0
  494. package/src/smithy/ts/api/schema.json +5 -0
  495. package/src/terraform/project/files/application/scripts/bootstrap.ts.template +40 -1
  496. package/src/terraform/project/files/application/src/main.tf.template +6 -1
  497. package/src/terraform/project/files/application/src/providers.tf.template +1 -1
  498. package/src/terraform/project/generator.d.ts +3 -3
  499. package/src/terraform/project/generator.js +159 -104
  500. package/src/terraform/project/generator.js.map +1 -1
  501. package/src/terraform/project/schema.d.js +9 -0
  502. package/src/terraform/project/schema.d.js.map +1 -0
  503. package/src/terraform/project/schema.d.ts +1 -0
  504. package/src/terraform/project/schema.json +5 -0
  505. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +1180 -185
  506. package/src/trpc/backend/files/src/client/index.ts.template +1 -1
  507. package/src/trpc/backend/files/src/handler.ts.template +1 -1
  508. package/src/trpc/backend/files/src/index.ts.template +5 -5
  509. package/src/trpc/backend/files/src/init.ts.template +1 -1
  510. package/src/trpc/backend/files/src/local-server.ts.template +1 -1
  511. package/src/trpc/backend/files/src/middleware/index.ts.template +7 -7
  512. package/src/trpc/backend/files/src/procedures/echo.ts.template +3 -3
  513. package/src/trpc/backend/files/src/router.ts.template +2 -2
  514. package/src/trpc/backend/files/src/schema/echo.ts.template +2 -2
  515. package/src/trpc/backend/files/src/schema/index.ts.template +1 -1
  516. package/src/trpc/backend/generator.d.ts +4 -4
  517. package/src/trpc/backend/generator.js +100 -84
  518. package/src/trpc/backend/generator.js.map +1 -1
  519. package/src/trpc/backend/schema.d.js +6 -0
  520. package/src/trpc/backend/schema.d.js.map +1 -0
  521. package/src/trpc/backend/schema.d.ts +3 -2
  522. package/src/trpc/backend/schema.json +5 -0
  523. package/src/trpc/react/__snapshots__/generator.spec.ts.snap +4 -4
  524. package/src/trpc/react/files/src/components/__apiNameClassName__ClientProvider.tsx.template +3 -3
  525. package/src/trpc/react/generator.d.ts +4 -4
  526. package/src/trpc/react/generator.js +64 -59
  527. package/src/trpc/react/generator.js.map +1 -1
  528. package/src/trpc/react/schema.d.js +6 -0
  529. package/src/trpc/react/schema.d.js.map +1 -0
  530. package/src/trpc/react/schema.d.ts +1 -0
  531. package/src/trpc/react/schema.json +5 -0
  532. package/src/ts/agent/__snapshots__/generator.spec.ts.snap +792 -23
  533. package/src/ts/agent/a2a-connection/__snapshots__/generator.spec.ts.snap +257 -0
  534. package/src/ts/agent/a2a-connection/files/agent-connection/app/__targetAgentKebabCase__-client-strands.ts.template +23 -0
  535. package/src/ts/agent/a2a-connection/generator.d.ts +3 -3
  536. package/src/ts/agent/a2a-connection/generator.js +65 -55
  537. package/src/ts/agent/a2a-connection/generator.js.map +1 -1
  538. package/src/ts/agent/a2a-connection/schema.d.js +8 -0
  539. package/src/ts/agent/a2a-connection/schema.d.js.map +1 -0
  540. package/src/ts/agent/a2a-connection/schema.d.ts +1 -0
  541. package/src/ts/agent/a2a-connection/schema.json +5 -0
  542. package/src/ts/agent/files/a2a/index.ts.template +1 -1
  543. package/src/ts/agent/files/ag-ui/index.ts.template +26 -10
  544. package/src/ts/agent/files/common/agent.ts.template +7 -2
  545. package/src/ts/agent/files/deploy/Dockerfile.template +13 -2
  546. package/src/ts/agent/files/http/client.ts.template +2 -2
  547. package/src/ts/agent/files/http/index.ts.template +2 -2
  548. package/src/ts/agent/files/http/router.ts.template +5 -5
  549. package/src/ts/agent/gateway-connection/__snapshots__/generator.spec.ts.snap +221 -0
  550. package/src/ts/agent/gateway-connection/files/agent-connection/app/__gatewayKebabCase__-client-strands.ts.template +30 -0
  551. package/src/ts/agent/gateway-connection/generator.d.ts +10 -0
  552. package/src/ts/agent/gateway-connection/generator.js +117 -0
  553. package/src/ts/agent/gateway-connection/generator.js.map +1 -0
  554. package/src/ts/agent/gateway-connection/schema.d.js +6 -0
  555. package/src/ts/agent/gateway-connection/schema.d.js.map +1 -0
  556. package/src/ts/agent/gateway-connection/schema.d.ts +13 -0
  557. package/src/ts/agent/gateway-connection/schema.json +31 -0
  558. package/src/ts/agent/generator.d.ts +3 -3
  559. package/src/ts/agent/generator.js +213 -145
  560. package/src/ts/agent/generator.js.map +1 -1
  561. package/src/ts/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +193 -111
  562. package/src/ts/agent/mcp-connection/files/agent-connection/app/__mcpServerKebabCase__-client-strands.ts.template +22 -0
  563. package/src/ts/agent/mcp-connection/generator.d.ts +3 -3
  564. package/src/ts/agent/mcp-connection/generator.js +56 -60
  565. package/src/ts/agent/mcp-connection/generator.js.map +1 -1
  566. package/src/ts/agent/mcp-connection/schema.d.js +8 -0
  567. package/src/ts/agent/mcp-connection/schema.d.js.map +1 -0
  568. package/src/ts/agent/mcp-connection/schema.d.ts +1 -0
  569. package/src/ts/agent/mcp-connection/schema.json +5 -0
  570. package/src/ts/agent/react-connection/generator.d.ts +4 -4
  571. package/src/ts/agent/react-connection/generator.js +88 -91
  572. package/src/ts/agent/react-connection/generator.js.map +1 -1
  573. package/src/ts/agent/react-connection/local-dev.d.ts +13 -0
  574. package/src/ts/agent/react-connection/local-dev.js +17 -0
  575. package/src/ts/agent/react-connection/local-dev.js.map +1 -0
  576. package/src/ts/agent/react-connection/schema.d.js +8 -0
  577. package/src/ts/agent/react-connection/schema.d.js.map +1 -0
  578. package/src/ts/agent/react-connection/schema.d.ts +1 -0
  579. package/src/ts/agent/react-connection/schema.json +5 -0
  580. package/src/ts/agent/schema.d.js +6 -0
  581. package/src/ts/agent/schema.d.js.map +1 -0
  582. package/src/ts/agent/schema.d.ts +1 -0
  583. package/src/ts/agent/schema.json +5 -0
  584. package/src/ts/api/generator.d.ts +3 -3
  585. package/src/ts/api/generator.js +16 -16
  586. package/src/ts/api/generator.js.map +1 -1
  587. package/src/ts/api/schema.d.js +6 -0
  588. package/src/ts/api/schema.d.js.map +1 -0
  589. package/src/ts/api/schema.d.ts +3 -1
  590. package/src/ts/api/schema.json +5 -0
  591. package/src/ts/astro-docs/__snapshots__/generator.spec.ts.snap +15 -16
  592. package/src/ts/astro-docs/files/translation/scripts/translate.ts.template +3 -2
  593. package/src/ts/astro-docs/generator.d.ts +3 -3
  594. package/src/ts/astro-docs/generator.js +80 -54
  595. package/src/ts/astro-docs/generator.js.map +1 -1
  596. package/src/ts/astro-docs/schema.d.js +6 -0
  597. package/src/ts/astro-docs/schema.d.js.map +1 -0
  598. package/src/ts/astro-docs/schema.d.ts +2 -2
  599. package/src/ts/astro-docs/schema.json +3 -3
  600. package/src/ts/dcr-proxy/__snapshots__/generator.spec.ts.snap +982 -0
  601. package/src/ts/dcr-proxy/generator.d.ts +10 -0
  602. package/src/ts/dcr-proxy/generator.js +98 -0
  603. package/src/ts/dcr-proxy/generator.js.map +1 -0
  604. package/src/ts/dcr-proxy/schema.d.js +6 -0
  605. package/src/ts/dcr-proxy/schema.d.js.map +1 -0
  606. package/src/ts/dcr-proxy/schema.d.ts +13 -0
  607. package/src/ts/dcr-proxy/schema.json +44 -0
  608. package/src/ts/docs/generator.d.ts +3 -3
  609. package/src/ts/docs/generator.js +10 -10
  610. package/src/ts/docs/generator.js.map +1 -1
  611. package/src/ts/docs/schema.d.js +6 -0
  612. package/src/ts/docs/schema.d.js.map +1 -0
  613. package/src/ts/docs/schema.d.ts +1 -4
  614. package/src/ts/docs/schema.json +3 -3
  615. package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +402 -518
  616. package/src/ts/dynamodb/agent-connection/__snapshots__/generator.spec.ts.snap +5 -5
  617. package/src/ts/dynamodb/agent-connection/generator.d.ts +3 -3
  618. package/src/ts/dynamodb/agent-connection/generator.js +21 -23
  619. package/src/ts/dynamodb/agent-connection/generator.js.map +1 -1
  620. package/src/ts/dynamodb/agent-connection/schema.d.js +8 -0
  621. package/src/ts/dynamodb/agent-connection/schema.d.js.map +1 -0
  622. package/src/ts/dynamodb/agent-connection/schema.d.ts +1 -0
  623. package/src/ts/dynamodb/agent-connection/schema.json +5 -0
  624. package/src/ts/dynamodb/files/config.json.template +24 -0
  625. package/src/ts/dynamodb/files/src/client.ts.template +30 -11
  626. package/src/ts/dynamodb/files/src/entities/example.ts.template +1 -1
  627. package/src/ts/dynamodb/files/src/entities/index.ts.template +1 -1
  628. package/src/ts/dynamodb/files/src/index.ts.template +2 -11
  629. package/src/ts/dynamodb/generator.d.ts +3 -3
  630. package/src/ts/dynamodb/generator.js +76 -63
  631. package/src/ts/dynamodb/generator.js.map +1 -1
  632. package/src/ts/dynamodb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +5 -5
  633. package/src/ts/dynamodb/mcp-server-connection/generator.d.ts +3 -3
  634. package/src/ts/dynamodb/mcp-server-connection/generator.js +21 -23
  635. package/src/ts/dynamodb/mcp-server-connection/generator.js.map +1 -1
  636. package/src/ts/dynamodb/mcp-server-connection/schema.d.js +8 -0
  637. package/src/ts/dynamodb/mcp-server-connection/schema.d.js.map +1 -0
  638. package/src/ts/dynamodb/mcp-server-connection/schema.d.ts +1 -0
  639. package/src/ts/dynamodb/mcp-server-connection/schema.json +5 -0
  640. package/src/ts/dynamodb/schema.d.js +6 -0
  641. package/src/ts/dynamodb/schema.d.js.map +1 -0
  642. package/src/ts/dynamodb/schema.d.ts +2 -0
  643. package/src/ts/dynamodb/schema.json +25 -2
  644. package/src/ts/dynamodb/smithy-connection/__snapshots__/generator.spec.ts.snap +3 -3
  645. package/src/ts/dynamodb/smithy-connection/generator.d.ts +3 -3
  646. package/src/ts/dynamodb/smithy-connection/generator.js +20 -22
  647. package/src/ts/dynamodb/smithy-connection/generator.js.map +1 -1
  648. package/src/ts/dynamodb/smithy-connection/schema.d.js +8 -0
  649. package/src/ts/dynamodb/smithy-connection/schema.d.js.map +1 -0
  650. package/src/ts/dynamodb/smithy-connection/schema.d.ts +1 -0
  651. package/src/ts/dynamodb/smithy-connection/schema.json +5 -0
  652. package/src/ts/dynamodb/trpc-connection/__snapshots__/generator.spec.ts.snap +3 -3
  653. package/src/ts/dynamodb/trpc-connection/generator.d.ts +3 -3
  654. package/src/ts/dynamodb/trpc-connection/generator.js +20 -22
  655. package/src/ts/dynamodb/trpc-connection/generator.js.map +1 -1
  656. package/src/ts/dynamodb/trpc-connection/schema.d.js +8 -0
  657. package/src/ts/dynamodb/trpc-connection/schema.d.js.map +1 -0
  658. package/src/ts/dynamodb/trpc-connection/schema.d.ts +1 -0
  659. package/src/ts/dynamodb/trpc-connection/schema.json +5 -0
  660. package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +8 -6
  661. package/src/ts/lambda-function/files/handler/__lambdaFunctionKebabCase__.ts.template +2 -1
  662. package/src/ts/lambda-function/generator.d.ts +3 -3
  663. package/src/ts/lambda-function/generator.js +60 -56
  664. package/src/ts/lambda-function/generator.js.map +1 -1
  665. package/src/ts/lambda-function/io.js +83 -52
  666. package/src/ts/lambda-function/io.js.map +1 -1
  667. package/src/ts/lambda-function/schema.d.js +6 -0
  668. package/src/ts/lambda-function/schema.d.js.map +1 -0
  669. package/src/ts/lambda-function/schema.d.ts +1 -0
  670. package/src/ts/lambda-function/schema.json +5 -0
  671. package/src/ts/lib/__snapshots__/generator.spec.ts.snap +98 -93
  672. package/src/ts/lib/__snapshots__/vitest.spec.ts.snap +24 -0
  673. package/src/ts/lib/biome.d.ts +7 -0
  674. package/src/ts/lib/biome.js +91 -0
  675. package/src/ts/lib/biome.js.map +1 -0
  676. package/src/ts/lib/generator.d.ts +3 -3
  677. package/src/ts/lib/generator.js +107 -108
  678. package/src/ts/lib/generator.js.map +1 -1
  679. package/src/ts/lib/grit/vitest-pass-with-no-tests.grit +1 -4
  680. package/src/ts/lib/schema.d.js +6 -0
  681. package/src/ts/lib/schema.d.js.map +1 -0
  682. package/src/ts/lib/schema.d.ts +1 -1
  683. package/src/ts/lib/schema.json +5 -0
  684. package/src/ts/lib/ts-project-utils.d.ts +12 -2
  685. package/src/ts/lib/ts-project-utils.js +95 -71
  686. package/src/ts/lib/ts-project-utils.js.map +1 -1
  687. package/src/ts/lib/types.d.ts +6 -0
  688. package/src/ts/lib/types.js +5 -2
  689. package/src/ts/lib/types.js.map +1 -1
  690. package/src/ts/lib/vitest.d.ts +2 -2
  691. package/src/ts/lib/vitest.js +30 -26
  692. package/src/ts/lib/vitest.js.map +1 -1
  693. package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +209 -42
  694. package/src/ts/mcp-server/files/Dockerfile.template +13 -2
  695. package/src/ts/mcp-server/generator.d.ts +3 -3
  696. package/src/ts/mcp-server/generator.js +183 -140
  697. package/src/ts/mcp-server/generator.js.map +1 -1
  698. package/src/ts/mcp-server/schema.d.js +6 -0
  699. package/src/ts/mcp-server/schema.d.js.map +1 -0
  700. package/src/ts/mcp-server/schema.d.ts +1 -0
  701. package/src/ts/mcp-server/schema.json +5 -0
  702. package/src/ts/nx-generator/__snapshots__/generator.spec.ts.snap +46 -26
  703. package/src/ts/nx-generator/files/common/schema.d.ts.template +1 -0
  704. package/src/ts/nx-generator/files/common/schema.json.template +5 -0
  705. package/src/ts/nx-generator/files/local/generator.ts.template +3 -3
  706. package/src/ts/nx-generator/files/nx-plugin-for-aws/generator/generator.ts.template +6 -7
  707. package/src/ts/nx-generator/generator.d.ts +2 -2
  708. package/src/ts/nx-generator/generator.js +118 -73
  709. package/src/ts/nx-generator/generator.js.map +1 -1
  710. package/src/ts/nx-generator/schema.d.js +6 -0
  711. package/src/ts/nx-generator/schema.d.js.map +1 -0
  712. package/src/ts/nx-generator/schema.d.ts +1 -0
  713. package/src/ts/nx-generator/schema.json +5 -0
  714. package/src/ts/nx-migration/files/migration.spec.ts.template +26 -0
  715. package/src/ts/nx-migration/files/migration.ts.template +61 -0
  716. package/src/ts/nx-migration/files/prompt.md.template +46 -0
  717. package/src/ts/nx-migration/generator.d.ts +24 -0
  718. package/src/ts/nx-migration/generator.js +122 -0
  719. package/src/ts/nx-migration/generator.js.map +1 -0
  720. package/src/ts/nx-migration/schema.d.js +6 -0
  721. package/src/ts/nx-migration/schema.d.js.map +1 -0
  722. package/src/ts/nx-migration/schema.d.ts +13 -0
  723. package/src/ts/nx-migration/schema.json +63 -0
  724. package/src/ts/nx-plugin/__snapshots__/generator.spec.ts.snap +36 -25
  725. package/src/ts/nx-plugin/files/mcp-server/resources/GENERAL_GUIDANCE.md.template +5 -6
  726. package/src/ts/nx-plugin/files/mcp-server/server.ts.template +5 -5
  727. package/src/ts/nx-plugin/files/mcp-server/tools/create-workspace-command.ts.template +2 -2
  728. package/src/ts/nx-plugin/files/mcp-server/tools/general-guidance.ts.template +1 -1
  729. package/src/ts/nx-plugin/files/mcp-server/tools/generator-guide.ts.template +2 -2
  730. package/src/ts/nx-plugin/files/mcp-server/tools/list-generators.ts.template +2 -2
  731. package/src/ts/nx-plugin/files/mcp-server/utils.ts.template +4 -4
  732. package/src/ts/nx-plugin/generator.d.ts +3 -3
  733. package/src/ts/nx-plugin/generator.js +61 -50
  734. package/src/ts/nx-plugin/generator.js.map +1 -1
  735. package/src/ts/nx-plugin/schema.d.js +9 -0
  736. package/src/ts/nx-plugin/schema.d.js.map +1 -0
  737. package/src/ts/nx-plugin/schema.json +5 -0
  738. package/src/ts/nx-plugin/utils.d.ts +21 -1
  739. package/src/ts/nx-plugin/utils.js +60 -51
  740. package/src/ts/nx-plugin/utils.js.map +1 -1
  741. package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +551 -642
  742. package/src/ts/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +6 -6
  743. package/src/ts/rdb/agent-connection/generator.d.ts +3 -3
  744. package/src/ts/rdb/agent-connection/generator.js +37 -39
  745. package/src/ts/rdb/agent-connection/generator.js.map +1 -1
  746. package/src/ts/rdb/agent-connection/schema.d.js +8 -0
  747. package/src/ts/rdb/agent-connection/schema.d.js.map +1 -0
  748. package/src/ts/rdb/agent-connection/schema.d.ts +1 -0
  749. package/src/ts/rdb/agent-connection/schema.json +5 -0
  750. package/src/ts/rdb/files/Dockerfile.template +19 -1
  751. package/src/ts/rdb/files/config.json.template +14 -0
  752. package/src/ts/rdb/files/prisma.config.ts.template +6 -5
  753. package/src/ts/rdb/files/src/create-db-user-handler.ts.template +9 -11
  754. package/src/ts/rdb/files/src/index.ts.template +1 -2
  755. package/src/ts/rdb/files/src/migration-handler.ts.template +5 -30
  756. package/src/ts/rdb/files/src/prisma.ts.template +33 -25
  757. package/src/ts/rdb/files/src/utils.ts.template +3 -0
  758. package/src/ts/rdb/generator.d.ts +3 -7
  759. package/src/ts/rdb/generator.js +177 -131
  760. package/src/ts/rdb/generator.js.map +1 -1
  761. package/src/ts/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +6 -6
  762. package/src/ts/rdb/mcp-server-connection/generator.d.ts +3 -3
  763. package/src/ts/rdb/mcp-server-connection/generator.js +35 -37
  764. package/src/ts/rdb/mcp-server-connection/generator.js.map +1 -1
  765. package/src/ts/rdb/mcp-server-connection/schema.d.js +8 -0
  766. package/src/ts/rdb/mcp-server-connection/schema.d.js.map +1 -0
  767. package/src/ts/rdb/mcp-server-connection/schema.d.ts +1 -0
  768. package/src/ts/rdb/mcp-server-connection/schema.json +5 -0
  769. package/src/ts/rdb/schema.d.js +6 -0
  770. package/src/ts/rdb/schema.d.js.map +1 -0
  771. package/src/ts/rdb/schema.d.ts +1 -0
  772. package/src/ts/rdb/schema.json +6 -1
  773. package/src/ts/rdb/smithy-connection/__snapshots__/generator.spec.ts.snap +3 -3
  774. package/src/ts/rdb/smithy-connection/generator.d.ts +3 -3
  775. package/src/ts/rdb/smithy-connection/generator.js +45 -43
  776. package/src/ts/rdb/smithy-connection/generator.js.map +1 -1
  777. package/src/ts/rdb/smithy-connection/schema.d.js +8 -0
  778. package/src/ts/rdb/smithy-connection/schema.d.js.map +1 -0
  779. package/src/ts/rdb/smithy-connection/schema.d.ts +1 -0
  780. package/src/ts/rdb/smithy-connection/schema.json +5 -0
  781. package/src/ts/rdb/trpc-connection/__snapshots__/generator.spec.ts.snap +3 -3
  782. package/src/ts/rdb/trpc-connection/generator.d.ts +3 -3
  783. package/src/ts/rdb/trpc-connection/generator.js +35 -31
  784. package/src/ts/rdb/trpc-connection/generator.js.map +1 -1
  785. package/src/ts/rdb/trpc-connection/schema.d.js +8 -0
  786. package/src/ts/rdb/trpc-connection/schema.d.js.map +1 -0
  787. package/src/ts/rdb/trpc-connection/schema.d.ts +1 -0
  788. package/src/ts/rdb/trpc-connection/schema.json +5 -0
  789. package/src/ts/rdb/utils.d.ts +1 -1
  790. package/src/ts/rdb/utils.js +9 -11
  791. package/src/ts/rdb/utils.js.map +1 -1
  792. package/src/ts/react-website/agui/files/common/src/hooks/useAgui__agentNameClassName__.tsx.template +1 -16
  793. package/src/ts/react-website/agui/generator.d.ts +1 -1
  794. package/src/ts/react-website/agui/generator.js +70 -62
  795. package/src/ts/react-website/agui/generator.js.map +1 -1
  796. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +1387 -813
  797. package/src/ts/react-website/app/generator.d.ts +4 -4
  798. package/src/ts/react-website/app/generator.js +241 -196
  799. package/src/ts/react-website/app/generator.js.map +1 -1
  800. package/src/ts/react-website/app/schema.d.js +6 -0
  801. package/src/ts/react-website/app/schema.d.js.map +1 -0
  802. package/src/ts/react-website/app/schema.d.ts +1 -1
  803. package/src/ts/react-website/app/schema.json +11 -6
  804. package/src/ts/react-website/cognito-auth/__snapshots__/generator.spec.ts.snap +139 -26
  805. package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +48 -12
  806. package/src/ts/react-website/cognito-auth/__snapshots__/generator.ux-provider.spec.ts.snap +0 -20
  807. package/src/ts/react-website/cognito-auth/files/app/components/CognitoAuth/index.tsx.template +2 -2
  808. package/src/ts/react-website/cognito-auth/generator.d.ts +4 -4
  809. package/src/ts/react-website/cognito-auth/generator.js +65 -63
  810. package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
  811. package/src/ts/react-website/cognito-auth/grit/cloudscape-auth-menu.grit +8 -6
  812. package/src/ts/react-website/cognito-auth/grit/cognito-auth-wrapper.grit +1 -1
  813. package/src/ts/react-website/cognito-auth/grit/none-auth-menu.grit +1 -0
  814. package/src/ts/react-website/cognito-auth/grit/shadcn-auth-menu.grit +3 -1
  815. package/src/ts/react-website/cognito-auth/grit/shadcn-state-declarations.grit +3 -1
  816. package/src/ts/react-website/cognito-auth/schema.d.js +6 -0
  817. package/src/ts/react-website/cognito-auth/schema.d.js.map +1 -0
  818. package/src/ts/react-website/cognito-auth/schema.d.ts +1 -0
  819. package/src/ts/react-website/cognito-auth/schema.json +5 -0
  820. package/src/ts/react-website/cognito-auth/utils.d.ts +1 -1
  821. package/src/ts/react-website/cognito-auth/utils.js +34 -32
  822. package/src/ts/react-website/cognito-auth/utils.js.map +1 -1
  823. package/src/ts/react-website/runtime-config/__snapshots__/generator.spec.ts.snap +2 -2
  824. package/src/ts/react-website/runtime-config/files/app/components/RuntimeConfig/index.tsx.template +2 -2
  825. package/src/ts/react-website/runtime-config/generator.d.ts +3 -3
  826. package/src/ts/react-website/runtime-config/generator.js +29 -31
  827. package/src/ts/react-website/runtime-config/generator.js.map +1 -1
  828. package/src/ts/react-website/runtime-config/schema.d.js +6 -0
  829. package/src/ts/react-website/runtime-config/schema.d.js.map +1 -0
  830. package/src/ts/react-website/runtime-config/schema.d.ts +1 -0
  831. package/src/ts/react-website/runtime-config/schema.json +5 -0
  832. package/src/ts/sync/generator.d.ts +3 -3
  833. package/src/ts/sync/generator.js +137 -60
  834. package/src/ts/sync/generator.js.map +1 -1
  835. package/src/ts/website/app/generator.d.ts +3 -3
  836. package/src/ts/website/app/generator.js +10 -10
  837. package/src/ts/website/app/generator.js.map +1 -1
  838. package/src/ts/website/app/schema.d.js +6 -0
  839. package/src/ts/website/app/schema.d.js.map +1 -0
  840. package/src/ts/website/app/schema.d.ts +1 -1
  841. package/src/ts/website/app/schema.json +11 -6
  842. package/src/ts/website/auth/generator.d.ts +4 -4
  843. package/src/ts/website/auth/generator.js +11 -10
  844. package/src/ts/website/auth/generator.js.map +1 -1
  845. package/src/ts/website/auth/schema.d.js +6 -0
  846. package/src/ts/website/auth/schema.d.js.map +1 -0
  847. package/src/ts/website/auth/schema.d.ts +1 -0
  848. package/src/ts/website/auth/schema.json +5 -0
  849. package/src/utils/__snapshots__/shared-constructs.spec.ts.snap +21 -0
  850. package/src/utils/agent-chat/agent-chat.d.ts +31 -0
  851. package/src/utils/agent-chat/agent-chat.js +31 -0
  852. package/src/utils/agent-chat/agent-chat.js.map +1 -0
  853. package/src/utils/agent-chat/files/a2a/chat.ts.template +33 -0
  854. package/src/utils/agent-chat/files/ag-ui/chat.ts.template +17 -0
  855. package/src/utils/agent-chat/files/common/agentcore.ts.template +81 -0
  856. package/src/utils/agent-chat/files/http-py/chat.ts.template +43 -0
  857. package/src/utils/agent-chat/files/http-ts/chat.ts.template +54 -0
  858. package/src/utils/agent-connection/agent-connection.d.ts +117 -25
  859. package/src/utils/agent-connection/agent-connection.js +467 -103
  860. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  861. package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client-config.ts.template +93 -0
  862. package/src/utils/agent-connection/files/core-auth/agentcore-endpoints.ts.template +37 -0
  863. package/src/utils/agent-connection/files/core-auth/agentcore-fetch.ts.template +54 -0
  864. package/src/utils/agent-connection/files/core-gateway/agentcore-gateway-mcp-transport.ts.template +41 -0
  865. package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-transport.ts.template +70 -0
  866. package/src/utils/agent-connection/files/core-runtime-config/runtime-config.ts.template +22 -32
  867. package/src/utils/agent-connection/files/core-shared/agentcore-transport.ts.template +39 -0
  868. package/src/utils/agent-connection/files/core-strands/a2a/agentcore-a2a-client-strands.ts.template +61 -0
  869. package/src/utils/agent-connection/files/core-strands/base/model-errors-strands.ts.template +36 -0
  870. package/src/utils/agent-connection/files/core-strands/base/tool-errors-strands.ts.template +22 -0
  871. package/src/utils/agent-connection/files/{core-runtime-config/with-session-id.ts.template → core-strands/base/with-session-id-strands.ts.template} +1 -1
  872. package/src/utils/agent-connection/files/core-strands/gateway/agentcore-gateway-mcp-client-strands.ts.template +26 -0
  873. package/src/utils/agent-connection/files/core-strands/mcp/agentcore-mcp-client-strands.ts.template +27 -0
  874. package/src/utils/agent-connection/files/py-core-a2a/agentcore_a2a_client_config.py.template +43 -0
  875. package/src/utils/agent-connection/files/py-core-auth/agentcore_endpoints.py.template +47 -0
  876. package/src/utils/agent-connection/files/py-core-auth/auth/session.py.template +51 -0
  877. package/src/utils/agent-connection/files/py-core-gateway/agentcore_gateway_mcp_transport.py.template +28 -0
  878. package/src/utils/agent-connection/files/py-core-langchain/a2a/agentcore_a2a_client_langchain.py.template +99 -0
  879. package/src/utils/agent-connection/files/py-core-langchain/gateway/agentcore_gateway_mcp_client_langchain.py.template +57 -0
  880. package/src/utils/agent-connection/files/py-core-langchain/mcp/agentcore_mcp_client_langchain.py.template +64 -0
  881. package/src/utils/agent-connection/files/py-core-mcp/agentcore_mcp_transport.py.template +34 -0
  882. package/src/utils/agent-connection/files/py-core-runtime-config/runtime_config.py.template +5 -18
  883. package/src/utils/agent-connection/files/py-core-shared/agentcore_transport.py.template +40 -0
  884. package/src/utils/agent-connection/files/py-core-strands/a2a/agentcore_a2a_client_strands.py.template +66 -0
  885. package/src/utils/agent-connection/files/py-core-strands/base/model_errors_strands.py.template +40 -0
  886. package/src/utils/agent-connection/files/py-core-strands/gateway/agentcore_gateway_mcp_client_strands.py.template +22 -0
  887. package/src/utils/agent-connection/files/py-core-strands/mcp/agentcore_mcp_client_strands.py.template +30 -0
  888. package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +12 -3
  889. package/src/utils/agent-core-constructs/agent-core-constructs.js +104 -38
  890. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  891. package/src/utils/agent-core-constructs/files/cdk/app/agent-core/__nameKebabCase__/__nameKebabCase__.ts.template +31 -4
  892. package/src/utils/agent-core-constructs/files/cdk/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.ts.template +85 -0
  893. package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/agentcore-gateway.ts.template +497 -0
  894. package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/readiness-probe/index.js.template +55 -0
  895. package/src/utils/agent-core-constructs/files/terraform/app/agent-core/__nameKebabCase__/__nameKebabCase__.tf.template +32 -0
  896. package/src/utils/agent-core-constructs/files/terraform/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.tf.template +488 -0
  897. package/src/utils/agent-core-constructs/files/terraform/app/agentcore-gateway/__nameKebabCase__/render-cedar.cjs.template +13 -0
  898. package/src/utils/agent-core-constructs/files/terraform/core/agent-core/runtime.tf.template +151 -13
  899. package/src/utils/agent-core-constructs/files/terraform/core/agentcore-gateway/gateway.tf.template +14 -0
  900. package/src/utils/api-constructs/api-constructs.d.ts +2 -2
  901. package/src/utils/api-constructs/api-constructs.js +50 -31
  902. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  903. package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +20 -15
  904. package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +24 -16
  905. package/src/utils/api-constructs/files/cdk/core/api/http/http-api.ts.template +26 -9
  906. package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account/index.js.template +70 -0
  907. package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account.ts.template +82 -0
  908. package/src/utils/api-constructs/files/cdk/core/api/rest/rest-api.ts.template +54 -18
  909. package/src/utils/api-constructs/files/cdk/core/api/trpc/trpc-utils.ts.template +1 -1
  910. package/src/utils/api-constructs/files/cdk/core/api/utils/utils.ts.template +61 -7
  911. package/src/utils/api-constructs/files/terraform/app/apis/http/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +101 -12
  912. package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +194 -8
  913. package/src/utils/api-constructs/files/terraform/core/api/http/http-api/http-api.tf.template +1 -1
  914. package/src/utils/api-constructs/files/terraform/core/api/rest/api-gateway-account/api-gateway-account.tf.template +83 -0
  915. package/src/utils/api-constructs/files/terraform/core/api/rest/rest-api/rest-api.tf.template +5 -11
  916. package/src/utils/api-constructs/open-api-metadata.d.ts +2 -2
  917. package/src/utils/api-constructs/open-api-metadata.js +22 -22
  918. package/src/utils/api-constructs/open-api-metadata.js.map +1 -1
  919. package/src/utils/ast/website.d.ts +5 -1
  920. package/src/utils/ast/website.js +18 -20
  921. package/src/utils/ast/website.js.map +1 -1
  922. package/src/utils/ast.d.ts +5 -1
  923. package/src/utils/ast.js +107 -89
  924. package/src/utils/ast.js.map +1 -1
  925. package/src/utils/base-tsconfig.d.ts +30 -0
  926. package/src/utils/base-tsconfig.js +32 -0
  927. package/src/utils/base-tsconfig.js.map +1 -0
  928. package/src/utils/bundle/bundle.d.ts +1 -1
  929. package/src/utils/bundle/bundle.js +51 -47
  930. package/src/utils/bundle/bundle.js.map +1 -1
  931. package/src/utils/commands.d.ts +15 -5
  932. package/src/utils/commands.js +87 -28
  933. package/src/utils/commands.js.map +1 -1
  934. package/src/utils/config/index.d.ts +21 -5
  935. package/src/utils/config/index.js +5 -4
  936. package/src/utils/config/index.js.map +1 -1
  937. package/src/utils/config/utils.d.ts +5 -4
  938. package/src/utils/config/utils.js +50 -59
  939. package/src/utils/config/utils.js.map +1 -1
  940. package/src/utils/connection/open-api/files/components/__apiNameClassName__Provider.tsx.template +1 -1
  941. package/src/utils/connection/open-api/react.d.ts +6 -6
  942. package/src/utils/connection/open-api/react.js +82 -77
  943. package/src/utils/connection/open-api/react.js.map +1 -1
  944. package/src/utils/containers.d.ts +1 -1
  945. package/src/utils/containers.js +22 -23
  946. package/src/utils/containers.js.map +1 -1
  947. package/src/utils/dcr-proxy-constructs/dcr-proxy-constructs.d.ts +38 -0
  948. package/src/utils/dcr-proxy-constructs/dcr-proxy-constructs.js +93 -0
  949. package/src/utils/dcr-proxy-constructs/dcr-proxy-constructs.js.map +1 -0
  950. package/src/utils/dcr-proxy-constructs/files/cdk/app/dcr-proxies/__nameKebabCase__/__nameKebabCase__.ts.template +227 -0
  951. package/src/utils/dcr-proxy-constructs/files/project/src/handlers/authorization-server-metadata.ts.template +39 -0
  952. package/src/utils/dcr-proxy-constructs/files/project/src/handlers/authorize.ts.template +26 -0
  953. package/src/utils/dcr-proxy-constructs/files/project/src/handlers/mcp-proxy.ts.template +89 -0
  954. package/src/utils/dcr-proxy-constructs/files/project/src/handlers/protected-resource-metadata.ts.template +13 -0
  955. package/src/utils/dcr-proxy-constructs/files/project/src/handlers/register.ts.template +70 -0
  956. package/src/utils/dcr-proxy-constructs/files/project/src/handlers/token.ts.template +75 -0
  957. package/src/utils/dcr-proxy-constructs/files/terraform/app/dcr-proxies/__nameKebabCase__/__nameKebabCase__.tf.template +410 -0
  958. package/src/utils/dependencies.d.ts +18 -0
  959. package/src/utils/dependencies.js +206 -0
  960. package/src/utils/dependencies.js.map +1 -0
  961. package/src/utils/docker.d.ts +53 -0
  962. package/src/utils/docker.js +92 -0
  963. package/src/utils/docker.js.map +1 -0
  964. package/src/utils/dynamodb-constructs/dynamodb-constructs.d.ts +3 -3
  965. package/src/utils/dynamodb-constructs/dynamodb-constructs.js +39 -41
  966. package/src/utils/dynamodb-constructs/dynamodb-constructs.js.map +1 -1
  967. package/src/utils/dynamodb-constructs/files/cdk/app/dynamodb/__nameKebabCase__.ts.template +18 -5
  968. package/src/utils/dynamodb-constructs/files/cdk/core/dynamodb.ts.template +1 -1
  969. package/src/utils/dynamodb-constructs/files/terraform/app/dynamodb/__nameKebabCase__/__nameKebabCase__.tf.template +24 -17
  970. package/src/utils/dynamodb-constructs/files/terraform/core/dynamodb/dynamodb.tf.template +1 -1
  971. package/src/utils/files/common/constructs/src/core/cloudfront.ts.template +14 -0
  972. package/src/utils/files/common/constructs/src/core/index.ts.template +5 -4
  973. package/src/utils/files/common/constructs/src/index.ts.template +2 -2
  974. package/src/utils/files/common/infra-config/src/index.ts.template +3 -3
  975. package/src/utils/files/common/infra-config/src/resolve-stage.ts.template +2 -2
  976. package/src/utils/files/common/infra-config/src/stages.config.ts.template +1 -1
  977. package/src/{ts/dynamodb/files/scripts → utils/files/common/scripts/src/dynamodb}/create-local-table.ts.template +65 -31
  978. package/src/utils/files/common/scripts/src/dynamodb/pull-image.ts.template +13 -0
  979. package/src/utils/files/common/scripts/src/dynamodb/start-container.ts.template +104 -0
  980. package/src/utils/files/common/scripts/src/infra/infra-deploy.ts.template +2 -0
  981. package/src/utils/files/common/scripts/src/infra/infra-destroy.ts.template +2 -0
  982. package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/cdk-command.ts.template +6 -3
  983. package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/run.ts.template +3 -3
  984. package/src/utils/files/common/scripts/src/rdb/mysql/wait-for-mysql-db.ts.template +32 -0
  985. package/src/utils/files/common/scripts/src/rdb/postgres/wait-for-postgres-db.ts.template +32 -0
  986. package/src/utils/files/common/scripts/src/rdb/shared/pull-image.ts.template +16 -0
  987. package/src/utils/files/common/scripts/src/rdb/shared/start-container.ts.template +115 -0
  988. package/src/utils/files/common/shadcn/readme/README.md.template +3 -3
  989. package/src/utils/files/common/shadcn/src/index.ts.template +2 -2
  990. package/src/utils/files/shadcn/components.json.template +1 -1
  991. package/src/utils/files/terraform/src/core/asset-bucket/asset-bucket.tf.template +63 -72
  992. package/src/utils/files/terraform/src/core/runtime-config/appconfig/appconfig.tf.template +1 -1
  993. package/src/utils/files/terraform/src/core/runtime-config/appconfig-deployment/appconfig-deployment.tf.template +12 -6
  994. package/src/utils/files/terraform/src/core/runtime-config/entry/entry.tf.template +1 -1
  995. package/src/utils/files/terraform/src/core/runtime-config/read/read.tf.template +9 -4
  996. package/src/utils/files/website/hooks/sigv4/useSigV4.tsx.template +1 -1
  997. package/src/utils/format.d.ts +70 -2
  998. package/src/utils/format.js +326 -108
  999. package/src/utils/format.js.map +1 -1
  1000. package/src/utils/fs.d.ts +1 -1
  1001. package/src/utils/fs.js +14 -13
  1002. package/src/utils/fs.js.map +1 -1
  1003. package/src/utils/function-constructs/files/cdk/app/lambda-functions/__nameKebabCase__.ts.template +1 -1
  1004. package/src/utils/function-constructs/files/terraform/app/lambda-functions/__nameKebabCase__/__nameKebabCase__.tf.template +2 -2
  1005. package/src/utils/function-constructs/function-constructs.d.ts +2 -2
  1006. package/src/utils/function-constructs/function-constructs.js +22 -25
  1007. package/src/utils/function-constructs/function-constructs.js.map +1 -1
  1008. package/src/utils/generators.d.ts +4 -0
  1009. package/src/utils/generators.js +18 -20
  1010. package/src/utils/generators.js.map +1 -1
  1011. package/src/utils/git.d.ts +1 -1
  1012. package/src/utils/git.js +19 -34
  1013. package/src/utils/git.js.map +1 -1
  1014. package/src/utils/iac-providers.js +5 -5
  1015. package/src/utils/iac-providers.js.map +1 -1
  1016. package/src/utils/iac.d.ts +1 -1
  1017. package/src/utils/iac.js +12 -14
  1018. package/src/utils/iac.js.map +1 -1
  1019. package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +131 -24
  1020. package/src/utils/identity-constructs/files/terraform/core/user-identity/add-callback-url/add-callback-url.tf.template +28 -9
  1021. package/src/utils/identity-constructs/files/terraform/core/user-identity/identity/identity.tf.template +106 -6
  1022. package/src/utils/identity-constructs/files/terraform/core/user-identity/main.tf.template +7 -0
  1023. package/src/utils/identity-constructs/identity-constructs.d.ts +2 -2
  1024. package/src/utils/identity-constructs/identity-constructs.js +42 -31
  1025. package/src/utils/identity-constructs/identity-constructs.js.map +1 -1
  1026. package/src/utils/init.d.ts +59 -0
  1027. package/src/utils/init.js +282 -0
  1028. package/src/utils/init.js.map +1 -0
  1029. package/src/utils/install.d.ts +32 -0
  1030. package/src/utils/install.js +58 -0
  1031. package/src/utils/install.js.map +1 -0
  1032. package/src/utils/js.d.ts +4 -0
  1033. package/src/utils/js.js +27 -20
  1034. package/src/utils/js.js.map +1 -1
  1035. package/src/utils/mcp.d.ts +10 -1
  1036. package/src/utils/mcp.js +42 -41
  1037. package/src/utils/mcp.js.map +1 -1
  1038. package/src/utils/metrics.d.ts +9 -3
  1039. package/src/utils/metrics.js +61 -46
  1040. package/src/utils/metrics.js.map +1 -1
  1041. package/src/utils/migration-versions.d.ts +95 -0
  1042. package/src/utils/migration-versions.js +128 -0
  1043. package/src/utils/migration-versions.js.map +1 -0
  1044. package/src/utils/mock-project-graph.js +8 -12
  1045. package/src/utils/mock-project-graph.js.map +1 -1
  1046. package/src/utils/module-format.d.ts +25 -0
  1047. package/src/utils/module-format.js +45 -0
  1048. package/src/utils/module-format.js.map +1 -0
  1049. package/src/utils/names.d.ts +22 -0
  1050. package/src/utils/names.js +44 -48
  1051. package/src/utils/names.js.map +1 -1
  1052. package/src/utils/npm-scope.d.ts +1 -5
  1053. package/src/utils/npm-scope.js +7 -20
  1054. package/src/utils/npm-scope.js.map +1 -1
  1055. package/src/utils/nx.d.ts +57 -4
  1056. package/src/utils/nx.js +192 -75
  1057. package/src/utils/nx.js.map +1 -1
  1058. package/src/utils/nxlv-python.d.ts +1 -1
  1059. package/src/utils/nxlv-python.js +27 -15
  1060. package/src/utils/nxlv-python.js.map +1 -1
  1061. package/src/utils/object.js +5 -11
  1062. package/src/utils/object.js.map +1 -1
  1063. package/src/utils/paths.d.ts +1 -1
  1064. package/src/utils/paths.js +11 -15
  1065. package/src/utils/paths.js.map +1 -1
  1066. package/src/utils/pkg-manager.js +4 -9
  1067. package/src/utils/pkg-manager.js.map +1 -1
  1068. package/src/utils/pnpm-workspace.d.ts +1 -12
  1069. package/src/utils/pnpm-workspace.js +16 -43
  1070. package/src/utils/pnpm-workspace.js.map +1 -1
  1071. package/src/utils/port.d.ts +29 -7
  1072. package/src/utils/port.js +67 -28
  1073. package/src/utils/port.js.map +1 -1
  1074. package/src/utils/project-package-json.d.ts +39 -0
  1075. package/src/utils/project-package-json.js +119 -0
  1076. package/src/utils/project-package-json.js.map +1 -0
  1077. package/src/utils/py.d.ts +16 -3
  1078. package/src/utils/py.js +72 -47
  1079. package/src/utils/py.js.map +1 -1
  1080. package/src/utils/rdb-constructs/files/cdk/app/dbs/__nameKebabCase__.ts.template +72 -18
  1081. package/src/utils/rdb-constructs/files/cdk/core/rdb/aurora.ts.template +112 -88
  1082. package/src/utils/rdb-constructs/files/terraform/app/dbs/__nameKebabCase__/__nameKebabCase__.tf.template +127 -53
  1083. package/src/utils/rdb-constructs/files/terraform/core/rdb/aurora/aurora.tf.template +60 -53
  1084. package/src/utils/rdb-constructs/rdb-constructs.d.ts +15 -4
  1085. package/src/utils/rdb-constructs/rdb-constructs.js +38 -41
  1086. package/src/utils/rdb-constructs/rdb-constructs.js.map +1 -1
  1087. package/src/utils/ruff.d.ts +59 -0
  1088. package/src/utils/ruff.js +140 -0
  1089. package/src/utils/ruff.js.map +1 -0
  1090. package/src/utils/shared-constructs-constants.d.ts +1 -0
  1091. package/src/utils/shared-constructs-constants.js +16 -15
  1092. package/src/utils/shared-constructs-constants.js.map +1 -1
  1093. package/src/utils/shared-constructs.d.ts +2 -2
  1094. package/src/utils/shared-constructs.js +61 -67
  1095. package/src/utils/shared-constructs.js.map +1 -1
  1096. package/src/utils/shared-dynamodb-scripts.d.ts +11 -0
  1097. package/src/utils/shared-dynamodb-scripts.js +27 -0
  1098. package/src/utils/shared-dynamodb-scripts.js.map +1 -0
  1099. package/src/utils/shared-infra-config.d.ts +1 -1
  1100. package/src/utils/shared-infra-config.js +31 -30
  1101. package/src/utils/shared-infra-config.js.map +1 -1
  1102. package/src/utils/shared-infra-scripts.d.ts +11 -0
  1103. package/src/utils/shared-infra-scripts.js +43 -0
  1104. package/src/utils/shared-infra-scripts.js.map +1 -0
  1105. package/src/utils/shared-rdb-scripts.d.ts +16 -0
  1106. package/src/utils/shared-rdb-scripts.js +45 -0
  1107. package/src/utils/shared-rdb-scripts.js.map +1 -0
  1108. package/src/utils/shared-scripts.d.ts +2 -5
  1109. package/src/utils/shared-scripts.js +12 -38
  1110. package/src/utils/shared-scripts.js.map +1 -1
  1111. package/src/utils/shared-shadcn.d.ts +1 -1
  1112. package/src/utils/shared-shadcn.js +69 -72
  1113. package/src/utils/shared-shadcn.js.map +1 -1
  1114. package/src/utils/test-git.d.ts +39 -0
  1115. package/src/utils/test-git.js +117 -0
  1116. package/src/utils/test-git.js.map +1 -0
  1117. package/src/utils/test.d.ts +15 -1
  1118. package/src/utils/test.js +46 -23
  1119. package/src/utils/test.js.map +1 -1
  1120. package/src/utils/toml.d.ts +6 -1
  1121. package/src/utils/toml.js +20 -14
  1122. package/src/utils/toml.js.map +1 -1
  1123. package/src/utils/versions.d.ts +161 -99
  1124. package/src/utils/versions.js +177 -116
  1125. package/src/utils/versions.js.map +1 -1
  1126. package/src/utils/website-constructs/files/cdk/app/static-websites/__websiteNameKebabCase__.ts.template +2 -2
  1127. package/src/utils/website-constructs/files/cdk/core/static-website.ts.template +203 -41
  1128. package/src/utils/website-constructs/files/terraform/app/static-websites/__websiteNameKebabCase__/__websiteNameKebabCase__.tf.template +1 -1
  1129. package/src/utils/website-constructs/files/terraform/core/static-website/static-website.tf.template +145 -93
  1130. package/src/utils/website-constructs/website-constructs.d.ts +2 -2
  1131. package/src/utils/website-constructs/website-constructs.js +38 -30
  1132. package/src/utils/website-constructs/website-constructs.js.map +1 -1
  1133. package/bin/aws-nx-mcp.d.ts +0 -2
  1134. package/bin/aws-nx-mcp.js +0 -17
  1135. package/bin/aws-nx-mcp.js.map +0 -1
  1136. package/sdk/connection.d.ts +0 -6
  1137. package/sdk/connection.js +0 -10
  1138. package/sdk/connection.js.map +0 -1
  1139. package/sdk/license.d.ts +0 -8
  1140. package/sdk/license.js +0 -13
  1141. package/sdk/license.js.map +0 -1
  1142. package/sdk/open-api.d.ts +0 -10
  1143. package/sdk/open-api.js +0 -15
  1144. package/sdk/open-api.js.map +0 -1
  1145. package/sdk/py.d.ts +0 -14
  1146. package/sdk/py.js +0 -18
  1147. package/sdk/py.js.map +0 -1
  1148. package/sdk/terraform.d.ts +0 -6
  1149. package/sdk/terraform.js +0 -11
  1150. package/sdk/terraform.js.map +0 -1
  1151. package/sdk/ts.d.ts +0 -29
  1152. package/sdk/ts.js +0 -47
  1153. package/sdk/ts.js.map +0 -1
  1154. package/sdk/utils/ast.js +0 -12
  1155. package/sdk/utils/ast.js.map +0 -1
  1156. package/sdk/utils/format.js +0 -10
  1157. package/sdk/utils/format.js.map +0 -1
  1158. package/sdk/utils/test.js +0 -10
  1159. package/sdk/utils/test.js.map +0 -1
  1160. package/src/connection/agent-serve-local.js +0 -48
  1161. package/src/connection/agent-serve-local.js.map +0 -1
  1162. package/src/connection/serve-local.d.ts +0 -15
  1163. package/src/connection/serve-local.js +0 -41
  1164. package/src/connection/serve-local.js.map +0 -1
  1165. package/src/py/agent/a2a-connection/files/agent-connection/app/__targetAgentSnakeCase___client.py.template +0 -22
  1166. package/src/py/agent/mcp-connection/files/agent-connection/app/__mcpServerSnakeCase___client.py.template +0 -22
  1167. package/src/py/agent/react-connection/serve-local.js +0 -30
  1168. package/src/py/agent/react-connection/serve-local.js.map +0 -1
  1169. package/src/py/agent/scripts/http/chat.ts.template +0 -38
  1170. package/src/ts/agent/a2a-connection/files/agent-connection/app/__targetAgentKebabCase__-client.ts.template +0 -19
  1171. package/src/ts/agent/mcp-connection/files/agent-connection/app/__mcpServerKebabCase__-client.ts.template +0 -19
  1172. package/src/ts/agent/react-connection/serve-local.d.ts +0 -13
  1173. package/src/ts/agent/react-connection/serve-local.js +0 -19
  1174. package/src/ts/agent/react-connection/serve-local.js.map +0 -1
  1175. package/src/ts/agent/scripts/http/chat.ts.template +0 -35
  1176. package/src/ts/dynamodb/files/scripts/pull-image.ts.template +0 -15
  1177. package/src/ts/dynamodb/files/scripts/start-container.ts.template +0 -81
  1178. package/src/ts/dynamodb/files/src/constants.ts.template +0 -9
  1179. package/src/ts/dynamodb/files/src/gsi.ts.template +0 -14
  1180. package/src/ts/lib/eslint.d.ts +0 -14
  1181. package/src/ts/lib/eslint.js +0 -90
  1182. package/src/ts/lib/eslint.js.map +0 -1
  1183. package/src/ts/lib/grit/eslint-dependency-checks-warn.grit +0 -1
  1184. package/src/ts/rdb/files/scripts/pull-image.ts.template +0 -15
  1185. package/src/ts/rdb/files/scripts/start-container.ts.template +0 -84
  1186. package/src/ts/rdb/files/scripts/wait-for-db.ts.template +0 -55
  1187. package/src/ts/rdb/files/src/constants.ts.template +0 -8
  1188. package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client.ts.template +0 -123
  1189. package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-client.ts.template +0 -128
  1190. package/src/utils/agent-connection/files/py-core-a2a/agentcore_a2a_client.py.template +0 -120
  1191. package/src/utils/agent-connection/files/py-core-mcp/agentcore_mcp_client.py.template +0 -89
  1192. package/src/utils/files/common/scripts/src/infra-deploy.ts.template +0 -2
  1193. package/src/utils/files/common/scripts/src/infra-destroy.ts.template +0 -2
  1194. package/src/utils/files/terraform/scripts/reset-runtime-config.ts.template +0 -25
  1195. /package/src/utils/agent-connection/files/{py-core-runtime-config/with_session_id.py.template → py-core-strands/base/with_session_id_strands.py.template} +0 -0
  1196. /package/src/utils/files/common/scripts/src/{index.ts.template → infra/index.ts.template} +0 -0
  1197. /package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/credentials.ts.template +0 -0
  1198. /package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/stage-parser.ts.template +0 -0
@@ -281,7 +281,7 @@ import { EchoInputSchema, EchoOutputSchema } from '../schema/index.js';
281
281
  export const echo = publicProcedure
282
282
  .input(EchoInputSchema)
283
283
  .output(EchoOutputSchema)
284
- .query((opts) => ({ result: opts.input.message }));
284
+ .query((opts) => ({ message: opts.input.message }));
285
285
  "
286
286
  `;
287
287
 
@@ -303,13 +303,13 @@ exports[`trpc backend generator > should generate the project > apps/test-api/sr
303
303
  "import { z } from 'zod';
304
304
 
305
305
  export const EchoInputSchema = z.object({
306
- message: z.string(),
306
+ message: z.string().max(1024),
307
307
  });
308
308
 
309
309
  export type IEchoInput = z.TypeOf<typeof EchoInputSchema>;
310
310
 
311
311
  export const EchoOutputSchema = z.object({
312
- result: z.string(),
312
+ message: z.string().max(1024),
313
313
  });
314
314
 
315
315
  export type IEchoOutput = z.TypeOf<typeof EchoOutputSchema>;
@@ -380,9 +380,10 @@ import {
380
380
  IntegrationBuilder,
381
381
  RestApiIntegration,
382
382
  } from '../../core/api/utils.js';
383
+ import { findCloudFrontDomainNames } from '../../core/cloudfront.js';
383
384
  import { AddCorsPreflightAspect, RestApi } from '../../core/api/rest-api.js';
384
385
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
385
- import { AppRouter, appRouter } from ':proj/test-api';
386
+ import { AppRouter, appRouter } from '@proj/test-api';
386
387
 
387
388
  // String union type for all API operation names
388
389
  type Operations = Procedures<AppRouter>;
@@ -435,7 +436,7 @@ export class TestApi<
435
436
  return IntegrationBuilder.rest({
436
437
  pattern: 'isolated',
437
438
  operations: routerToOperations(appRouter),
438
- defaultIntegrationOptions: <FunctionProps>{
439
+ defaultIntegrationOptions: {
439
440
  runtime: Runtime.NODEJS_LATEST,
440
441
  handler: 'index.handler',
441
442
  code: Code.fromAsset(
@@ -448,7 +449,7 @@ export class TestApi<
448
449
  ),
449
450
  timeout: Duration.seconds(30),
450
451
  tracing: Tracing.ACTIVE,
451
- },
452
+ } as FunctionProps,
452
453
  buildDefaultIntegration: (op, props: FunctionProps) => {
453
454
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
454
455
  handler.addEnvironment(
@@ -478,6 +479,9 @@ export class TestApi<
478
479
  authorizer: new CognitoUserPoolsAuthorizer(scope, 'TestApiAuthorizer', {
479
480
  cognitoUserPools: [props.identity.userPool],
480
481
  }),
482
+ // Accept access tokens from both sign-in flows: 'openid' (Cognito hosted UI)
483
+ // and 'aws.cognito.signin.user.admin' (Cognito admin/SRP auth APIs).
484
+ authorizationScopes: ['openid', 'aws.cognito.signin.user.admin'],
481
485
  },
482
486
  deployOptions: {
483
487
  tracingEnabled: true,
@@ -504,7 +508,9 @@ export class TestApi<
504
508
  *
505
509
  * Configures the provided CloudFront distribution domains or origin strings
506
510
  * as the only permitted CORS origins in API Gateway preflight responses and the
507
- * AWS Lambda integrations.
511
+ * AWS Lambda integrations. Any custom domain names (aliases) configured on a
512
+ * CloudFront distribution are included automatically alongside its default
513
+ * \`*.cloudfront.net\` domain.
508
514
  *
509
515
  * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
510
516
  */
@@ -515,12 +521,14 @@ export class TestApi<
515
521
  | { cloudFrontDistribution: Distribution }
516
522
  )[]
517
523
  ) {
518
- const allowedOrigins = origins.map((origin) =>
524
+ const allowedOrigins = origins.flatMap((origin) =>
519
525
  typeof origin === 'string'
520
- ? origin
521
- : 'cloudFrontDistribution' in origin
522
- ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
523
- : \`https://\${origin.distributionDomainName}\`,
526
+ ? [origin]
527
+ : findCloudFrontDomainNames(
528
+ 'cloudFrontDistribution' in origin
529
+ ? origin.cloudFrontDistribution
530
+ : origin,
531
+ ).map((domain) => \`https://\${domain}\`),
524
532
  );
525
533
 
526
534
  this.allowedOrigins = allowedOrigins;
@@ -589,9 +597,10 @@ import {
589
597
  HttpApiIntegration,
590
598
  IntegrationBuilder,
591
599
  } from '../../core/api/utils.js';
600
+ import { findCloudFrontDomainNames } from '../../core/cloudfront.js';
592
601
  import { HttpApi } from '../../core/api/http-api.js';
593
602
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
594
- import { AppRouter, appRouter } from ':proj/test-api';
603
+ import { AppRouter, appRouter } from '@proj/test-api';
595
604
 
596
605
  // String union type for all API operation names
597
606
  type Operations = Procedures<AppRouter>;
@@ -637,7 +646,7 @@ export class TestApi<
637
646
  return IntegrationBuilder.http({
638
647
  pattern: 'isolated',
639
648
  operations: routerToOperations(appRouter),
640
- defaultIntegrationOptions: <FunctionProps>{
649
+ defaultIntegrationOptions: {
641
650
  runtime: Runtime.NODEJS_LATEST,
642
651
  handler: 'index.handler',
643
652
  code: Code.fromAsset(
@@ -650,7 +659,7 @@ export class TestApi<
650
659
  ),
651
660
  timeout: Duration.seconds(30),
652
661
  tracing: Tracing.ACTIVE,
653
- },
662
+ } as FunctionProps,
654
663
  buildDefaultIntegration: (op, props: FunctionProps) => {
655
664
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
656
665
  handler.addEnvironment(
@@ -706,6 +715,8 @@ export class TestApi<
706
715
  * as the only permitted CORS origins
707
716
  * in the API gateway. The CORS origins are not configured within the AWS Lambda
708
717
  * integrations since the associated header is controlled by API Gateway v2.
718
+ * Any custom domain names (aliases) configured on a CloudFront distribution are
719
+ * included automatically alongside its default \`*.cloudfront.net\` domain.
709
720
  *
710
721
  * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
711
722
  */
@@ -716,12 +727,14 @@ export class TestApi<
716
727
  | { cloudFrontDistribution: Distribution }
717
728
  )[]
718
729
  ) {
719
- const allowedOrigins = origins.map((origin) =>
730
+ const allowedOrigins = origins.flatMap((origin) =>
720
731
  typeof origin === 'string'
721
- ? origin
722
- : 'cloudFrontDistribution' in origin
723
- ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
724
- : \`https://\${origin.distributionDomainName}\`,
732
+ ? [origin]
733
+ : findCloudFrontDomainNames(
734
+ 'cloudFrontDistribution' in origin
735
+ ? origin.cloudFrontDistribution
736
+ : origin,
737
+ ).map((domain) => \`https://\${domain}\`),
725
738
  );
726
739
 
727
740
  const cfnApi = this.api.node.defaultChild;
@@ -801,9 +814,10 @@ import {
801
814
  IntegrationBuilder,
802
815
  RestApiIntegration,
803
816
  } from '../../core/api/utils.js';
817
+ import { findCloudFrontDomainNames } from '../../core/cloudfront.js';
804
818
  import { AddCorsPreflightAspect, RestApi } from '../../core/api/rest-api.js';
805
819
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
806
- import { AppRouter, appRouter } from ':proj/test-api';
820
+ import { AppRouter, appRouter } from '@proj/test-api';
807
821
 
808
822
  // String union type for all API operation names
809
823
  type Operations = Procedures<AppRouter>;
@@ -850,7 +864,7 @@ export class TestApi<
850
864
  return IntegrationBuilder.rest({
851
865
  pattern: 'isolated',
852
866
  operations: routerToOperations(appRouter),
853
- defaultIntegrationOptions: <FunctionProps>{
867
+ defaultIntegrationOptions: {
854
868
  runtime: Runtime.NODEJS_LATEST,
855
869
  handler: 'index.handler',
856
870
  code: Code.fromAsset(
@@ -863,7 +877,7 @@ export class TestApi<
863
877
  ),
864
878
  timeout: Duration.seconds(30),
865
879
  tracing: Tracing.ACTIVE,
866
- },
880
+ } as FunctionProps,
867
881
  buildDefaultIntegration: (op, props: FunctionProps) => {
868
882
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
869
883
  handler.addEnvironment(
@@ -938,7 +952,9 @@ export class TestApi<
938
952
  *
939
953
  * Configures the provided CloudFront distribution domains or origin strings
940
954
  * as the only permitted CORS origins in API Gateway preflight responses and the
941
- * AWS Lambda integrations.
955
+ * AWS Lambda integrations. Any custom domain names (aliases) configured on a
956
+ * CloudFront distribution are included automatically alongside its default
957
+ * \`*.cloudfront.net\` domain.
942
958
  *
943
959
  * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
944
960
  */
@@ -949,12 +965,14 @@ export class TestApi<
949
965
  | { cloudFrontDistribution: Distribution }
950
966
  )[]
951
967
  ) {
952
- const allowedOrigins = origins.map((origin) =>
968
+ const allowedOrigins = origins.flatMap((origin) =>
953
969
  typeof origin === 'string'
954
- ? origin
955
- : 'cloudFrontDistribution' in origin
956
- ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
957
- : \`https://\${origin.distributionDomainName}\`,
970
+ ? [origin]
971
+ : findCloudFrontDomainNames(
972
+ 'cloudFrontDistribution' in origin
973
+ ? origin.cloudFrontDistribution
974
+ : origin,
975
+ ).map((domain) => \`https://\${domain}\`),
958
976
  );
959
977
 
960
978
  this.allowedOrigins = allowedOrigins;
@@ -1021,9 +1039,10 @@ import {
1021
1039
  HttpApiIntegration,
1022
1040
  IntegrationBuilder,
1023
1041
  } from '../../core/api/utils.js';
1042
+ import { findCloudFrontDomainNames } from '../../core/cloudfront.js';
1024
1043
  import { HttpApi } from '../../core/api/http-api.js';
1025
1044
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
1026
- import { AppRouter, appRouter } from ':proj/test-api';
1045
+ import { AppRouter, appRouter } from '@proj/test-api';
1027
1046
 
1028
1047
  // String union type for all API operation names
1029
1048
  type Operations = Procedures<AppRouter>;
@@ -1062,7 +1081,7 @@ export class TestApi<
1062
1081
  return IntegrationBuilder.http({
1063
1082
  pattern: 'isolated',
1064
1083
  operations: routerToOperations(appRouter),
1065
- defaultIntegrationOptions: <FunctionProps>{
1084
+ defaultIntegrationOptions: {
1066
1085
  runtime: Runtime.NODEJS_LATEST,
1067
1086
  handler: 'index.handler',
1068
1087
  code: Code.fromAsset(
@@ -1075,7 +1094,7 @@ export class TestApi<
1075
1094
  ),
1076
1095
  timeout: Duration.seconds(30),
1077
1096
  tracing: Tracing.ACTIVE,
1078
- },
1097
+ } as FunctionProps,
1079
1098
  buildDefaultIntegration: (op, props: FunctionProps) => {
1080
1099
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
1081
1100
  handler.addEnvironment(
@@ -1150,6 +1169,8 @@ export class TestApi<
1150
1169
  * as the only permitted CORS origins
1151
1170
  * in the API gateway. The CORS origins are not configured within the AWS Lambda
1152
1171
  * integrations since the associated header is controlled by API Gateway v2.
1172
+ * Any custom domain names (aliases) configured on a CloudFront distribution are
1173
+ * included automatically alongside its default \`*.cloudfront.net\` domain.
1153
1174
  *
1154
1175
  * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
1155
1176
  */
@@ -1160,12 +1181,14 @@ export class TestApi<
1160
1181
  | { cloudFrontDistribution: Distribution }
1161
1182
  )[]
1162
1183
  ) {
1163
- const allowedOrigins = origins.map((origin) =>
1184
+ const allowedOrigins = origins.flatMap((origin) =>
1164
1185
  typeof origin === 'string'
1165
- ? origin
1166
- : 'cloudFrontDistribution' in origin
1167
- ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
1168
- : \`https://\${origin.distributionDomainName}\`,
1186
+ ? [origin]
1187
+ : findCloudFrontDomainNames(
1188
+ 'cloudFrontDistribution' in origin
1189
+ ? origin.cloudFrontDistribution
1190
+ : origin,
1191
+ ).map((domain) => \`https://\${domain}\`),
1169
1192
  );
1170
1193
 
1171
1194
  const cfnApi = this.api.node.defaultChild;
@@ -1199,15 +1222,18 @@ import {
1199
1222
  HttpApiIntegration,
1200
1223
  OperationDetails,
1201
1224
  } from './utils.js';
1202
- import { CfnOutput } from 'aws-cdk-lib';
1225
+ import { CfnOutput, Stack } from 'aws-cdk-lib';
1203
1226
  import {
1204
1227
  HttpApi as _HttpApi,
1205
1228
  HttpApiProps as _HttpApiProps,
1206
1229
  HttpMethod,
1207
1230
  HttpStage,
1208
1231
  LogGroupLogDestination,
1232
+ ThrottleSettings,
1209
1233
  } from 'aws-cdk-lib/aws-apigatewayv2';
1210
1234
  import { LogGroup } from 'aws-cdk-lib/aws-logs';
1235
+ import { Key } from 'aws-cdk-lib/aws-kms';
1236
+ import { ServicePrincipal } from 'aws-cdk-lib/aws-iam';
1211
1237
  import { suppressRules } from '../checkov.js';
1212
1238
 
1213
1239
  /**
@@ -1232,6 +1258,12 @@ export interface HttpApiProps<
1232
1258
  * Map of operation names to their API Gateway integrations
1233
1259
  */
1234
1260
  readonly integrations: TIntegrations;
1261
+ /**
1262
+ * Default throttling limits applied to the API's default stage.
1263
+ *
1264
+ * @default { rateLimit: 10000, burstLimit: 5000 }
1265
+ */
1266
+ readonly throttle?: ThrottleSettings;
1235
1267
  }
1236
1268
 
1237
1269
  /**
@@ -1265,6 +1297,7 @@ export class HttpApi<
1265
1297
  apiName,
1266
1298
  operations,
1267
1299
  integrations,
1300
+ throttle = { rateLimit: 10000, burstLimit: 5000 },
1268
1301
  ...props
1269
1302
  }: HttpApiProps<TIntegrations, TOperation>,
1270
1303
  ) {
@@ -1277,12 +1310,18 @@ export class HttpApi<
1277
1310
  ...props,
1278
1311
  });
1279
1312
 
1280
- const accessLogGroup = new LogGroup(this, 'AccessLogs');
1281
- suppressRules(
1282
- accessLogGroup,
1283
- ['CKV_AWS_158'],
1284
- 'Using default CloudWatch log encryption',
1313
+ // Customer-managed key for access log encryption at rest
1314
+ const logsKey = new Key(this, 'AccessLogsKey', {
1315
+ enableKeyRotation: true,
1316
+ });
1317
+ const stack = Stack.of(this);
1318
+ logsKey.grantEncryptDecrypt(
1319
+ new ServicePrincipal(\`logs.\${stack.region}.amazonaws.com\`),
1285
1320
  );
1321
+
1322
+ const accessLogGroup = new LogGroup(this, 'AccessLogs', {
1323
+ encryptionKey: logsKey,
1324
+ });
1286
1325
  suppressRules(
1287
1326
  accessLogGroup,
1288
1327
  ['CKV_AWS_66', 'CKV_AWS_338'],
@@ -1292,6 +1331,7 @@ export class HttpApi<
1292
1331
  this.defaultStage = new HttpStage(this, 'DefaultStage', {
1293
1332
  httpApi: this.api,
1294
1333
  autoDeploy: true,
1334
+ throttle,
1295
1335
  accessLogSettings: {
1296
1336
  destination: new LogGroupLogDestination(accessLogGroup),
1297
1337
  },
@@ -1371,9 +1411,10 @@ import {
1371
1411
  HttpApiIntegration,
1372
1412
  IntegrationBuilder,
1373
1413
  } from '../../core/api/utils.js';
1414
+ import { findCloudFrontDomainNames } from '../../core/cloudfront.js';
1374
1415
  import { HttpApi } from '../../core/api/http-api.js';
1375
1416
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
1376
- import { AppRouter, appRouter } from ':proj/test-api';
1417
+ import { AppRouter, appRouter } from '@proj/test-api';
1377
1418
 
1378
1419
  // String union type for all API operation names
1379
1420
  type Operations = Procedures<AppRouter>;
@@ -1412,7 +1453,7 @@ export class TestApi<
1412
1453
  return IntegrationBuilder.http({
1413
1454
  pattern: 'isolated',
1414
1455
  operations: routerToOperations(appRouter),
1415
- defaultIntegrationOptions: <FunctionProps>{
1456
+ defaultIntegrationOptions: {
1416
1457
  runtime: Runtime.NODEJS_LATEST,
1417
1458
  handler: 'index.handler',
1418
1459
  code: Code.fromAsset(
@@ -1425,7 +1466,7 @@ export class TestApi<
1425
1466
  ),
1426
1467
  timeout: Duration.seconds(30),
1427
1468
  tracing: Tracing.ACTIVE,
1428
- },
1469
+ } as FunctionProps,
1429
1470
  buildDefaultIntegration: (op, props: FunctionProps) => {
1430
1471
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
1431
1472
  handler.addEnvironment(
@@ -1475,6 +1516,8 @@ export class TestApi<
1475
1516
  * as the only permitted CORS origins
1476
1517
  * in the API gateway. The CORS origins are not configured within the AWS Lambda
1477
1518
  * integrations since the associated header is controlled by API Gateway v2.
1519
+ * Any custom domain names (aliases) configured on a CloudFront distribution are
1520
+ * included automatically alongside its default \`*.cloudfront.net\` domain.
1478
1521
  *
1479
1522
  * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
1480
1523
  */
@@ -1485,12 +1528,14 @@ export class TestApi<
1485
1528
  | { cloudFrontDistribution: Distribution }
1486
1529
  )[]
1487
1530
  ) {
1488
- const allowedOrigins = origins.map((origin) =>
1531
+ const allowedOrigins = origins.flatMap((origin) =>
1489
1532
  typeof origin === 'string'
1490
- ? origin
1491
- : 'cloudFrontDistribution' in origin
1492
- ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
1493
- : \`https://\${origin.distributionDomainName}\`,
1533
+ ? [origin]
1534
+ : findCloudFrontDomainNames(
1535
+ 'cloudFrontDistribution' in origin
1536
+ ? origin.cloudFrontDistribution
1537
+ : origin,
1538
+ ).map((domain) => \`https://\${domain}\`),
1494
1539
  );
1495
1540
 
1496
1541
  const cfnApi = this.api.node.defaultChild;
@@ -1751,6 +1796,8 @@ export type ApiIntegrations<TOperation extends string, TBaseIntegration> =
1751
1796
  * @template TDefaultIntegrationProps - Type for default integration properties
1752
1797
  * @template TDefaultIntegration - Type for default integration implementation
1753
1798
  * @template TPattern - The integration pattern ('shared' or 'isolated')
1799
+ * @template TOverridden - Union of operation names that have been overridden
1800
+ * @template TOperationOptioned - Union of operation names with per-operation options
1754
1801
  */
1755
1802
  export class IntegrationBuilder<
1756
1803
  TOperation extends string,
@@ -1759,6 +1806,8 @@ export class IntegrationBuilder<
1759
1806
  TDefaultIntegrationProps extends object,
1760
1807
  TDefaultIntegration extends TBaseIntegration,
1761
1808
  TPattern extends 'shared' | 'isolated',
1809
+ TOverridden extends string = never,
1810
+ TOperationOptioned extends string = never,
1762
1811
  > {
1763
1812
  /** Options for the integration builder */
1764
1813
  private options: IntegrationBuilderProps<
@@ -1771,6 +1820,11 @@ export class IntegrationBuilder<
1771
1820
  /** Map of operation names to their custom integrations */
1772
1821
  private integrations: Partial<TIntegrations> = {};
1773
1822
 
1823
+ /** Map of default integration keys to per-operation default option overrides */
1824
+ private perOperationOptions: Partial<
1825
+ Record<string, Partial<TDefaultIntegrationProps>>
1826
+ > = {};
1827
+
1774
1828
  /**
1775
1829
  * Create an Integration Builder for an HTTP API with a shared pattern
1776
1830
  */
@@ -1925,11 +1979,16 @@ export class IntegrationBuilder<
1925
1979
  /**
1926
1980
  * Overrides default integrations with custom implementations for specific operations.
1927
1981
  *
1982
+ * Operations which have per-operation options set via withOperationOptions cannot be
1983
+ * overridden, since these still use the default integration.
1984
+ *
1928
1985
  * @param overrides - Map of operation names to their custom integration implementations
1929
1986
  * @returns The builder instance with updated type information reflecting the overrides
1930
1987
  */
1931
1988
  public withOverrides<
1932
- TOverrideIntegrations extends Partial<Record<TOperation, TBaseIntegration>>,
1989
+ TOverrideIntegrations extends Partial<
1990
+ Record<Exclude<TOperation, TOperationOptioned>, TBaseIntegration>
1991
+ >,
1933
1992
  >(overrides: TOverrideIntegrations) {
1934
1993
  this.integrations = { ...this.integrations, ...overrides };
1935
1994
  // Re-type to include the overridden integration types.
@@ -1945,7 +2004,9 @@ export class IntegrationBuilder<
1945
2004
  MergedIntegrations,
1946
2005
  TDefaultIntegrationProps,
1947
2006
  TDefaultIntegration,
1948
- TPattern
2007
+ TPattern,
2008
+ TOverridden | Extract<keyof TOverrideIntegrations, string>,
2009
+ TOperationOptioned
1949
2010
  >;
1950
2011
  }
1951
2012
 
@@ -1964,6 +2025,43 @@ export class IntegrationBuilder<
1964
2025
  return this;
1965
2026
  }
1966
2027
 
2028
+ /**
2029
+ * Updates the default integration options for specific operations, without
2030
+ * affecting the others. The given options are merged with the defaults (and
2031
+ * any options set via withDefaultOptions) when building each default integration.
2032
+ *
2033
+ * Operations which have been replaced via withOverrides cannot be targeted, since
2034
+ * they no longer use the default integration.
2035
+ *
2036
+ * @param options - Map of operation names to partial default integration options
2037
+ * @returns The builder instance
2038
+ */
2039
+ public withOperationOptions<
2040
+ TOptions extends Partial<
2041
+ Record<
2042
+ Exclude<DefaultIntegrationKeys<TPattern, TOperation>, TOverridden>,
2043
+ Partial<TDefaultIntegrationProps>
2044
+ >
2045
+ >,
2046
+ >(options: TOptions) {
2047
+ Object.entries(options).forEach(([op, opOptions]) => {
2048
+ this.perOperationOptions[op] = {
2049
+ ...this.perOperationOptions[op],
2050
+ ...(opOptions as Partial<TDefaultIntegrationProps>),
2051
+ };
2052
+ });
2053
+ return this as unknown as IntegrationBuilder<
2054
+ TOperation,
2055
+ TBaseIntegration,
2056
+ TIntegrations,
2057
+ TDefaultIntegrationProps,
2058
+ TDefaultIntegration,
2059
+ TPattern,
2060
+ TOverridden,
2061
+ TOperationOptioned | Extract<keyof TOptions, string>
2062
+ >;
2063
+ }
2064
+
1967
2065
  /**
1968
2066
  * Builds and returns the complete set of integrations.
1969
2067
  *
@@ -1978,6 +2076,10 @@ export class IntegrationBuilder<
1978
2076
  */
1979
2077
  public build(): TIntegrations {
1980
2078
  const options = this.options;
2079
+ const buildOptionsFor = (op: string): TDefaultIntegrationProps => ({
2080
+ ...options.defaultIntegrationOptions,
2081
+ ...this.perOperationOptions[op],
2082
+ });
1981
2083
  return {
1982
2084
  ...Object.fromEntries(
1983
2085
  options.pattern === 'shared'
@@ -1986,7 +2088,7 @@ export class IntegrationBuilder<
1986
2088
  '$router',
1987
2089
  options.buildDefaultIntegration(
1988
2090
  '$router',
1989
- options.defaultIntegrationOptions,
2091
+ buildOptionsFor('$router'),
1990
2092
  ),
1991
2093
  ],
1992
2094
  ]
@@ -1997,10 +2099,7 @@ export class IntegrationBuilder<
1997
2099
  )
1998
2100
  .map((op) => [
1999
2101
  op,
2000
- options.buildDefaultIntegration(
2001
- op,
2002
- options.defaultIntegrationOptions,
2003
- ),
2102
+ options.buildDefaultIntegration(op, buildOptionsFor(op)),
2004
2103
  ]),
2005
2104
  ),
2006
2105
  ...this.integrations,
@@ -2013,21 +2112,27 @@ export class IntegrationBuilder<
2013
2112
  exports[`trpc backend generator > should set up shared constructs for rest > rest-api.ts 1`] = `
2014
2113
  "import { Construct, IConstruct } from 'constructs';
2015
2114
  import {
2115
+ AccessLogFormat,
2016
2116
  Cors,
2117
+ LogGroupLogDestination,
2017
2118
  Resource,
2018
2119
  RestApi as _RestApi,
2019
2120
  RestApiProps as _RestApiProps,
2020
2121
  IResource,
2021
2122
  Stage,
2123
+ ThrottleSettings,
2022
2124
  } from 'aws-cdk-lib/aws-apigateway';
2023
- import { IAspect, RemovalPolicy } from 'aws-cdk-lib';
2125
+ import { IAspect, Stack } from 'aws-cdk-lib';
2024
2126
  import {
2025
2127
  CfnLoggingConfiguration,
2026
2128
  CfnWebACL,
2027
2129
  CfnWebACLAssociation,
2028
2130
  } from 'aws-cdk-lib/aws-wafv2';
2029
2131
  import { LogGroup, RetentionDays } from 'aws-cdk-lib/aws-logs';
2132
+ import { Key } from 'aws-cdk-lib/aws-kms';
2133
+ import { ServicePrincipal } from 'aws-cdk-lib/aws-iam';
2030
2134
  import { RuntimeConfig } from '../runtime-config.js';
2135
+ import { ApiGatewayAccount } from './api-gateway-account.js';
2031
2136
  import {
2032
2137
  ApiIntegrations,
2033
2138
  OperationDetails,
@@ -2065,6 +2170,12 @@ export interface RestApiProps<
2065
2170
  * @default true
2066
2171
  */
2067
2172
  readonly enableWaf?: boolean;
2173
+ /**
2174
+ * Default throttling limits applied to all methods on the API's default stage.
2175
+ *
2176
+ * @default { rateLimit: 10000, burstLimit: 5000 }
2177
+ */
2178
+ readonly throttle?: ThrottleSettings;
2068
2179
  }
2069
2180
 
2070
2181
  /**
@@ -2099,14 +2210,49 @@ export class RestApi<
2099
2210
  operations,
2100
2211
  integrations,
2101
2212
  enableWaf = true,
2213
+ throttle = { rateLimit: 10000, burstLimit: 5000 },
2102
2214
  ...props
2103
2215
  }: RestApiProps<TIntegrations, TOperation>,
2104
2216
  ) {
2105
2217
  super(scope, id);
2106
2218
  this.integrations = integrations;
2107
2219
 
2220
+ // Account-level CloudWatch role required for REST API access logging
2221
+ const account = ApiGatewayAccount.ensure(this);
2222
+
2223
+ // KMS key for encrypting logs at rest, usable by CloudWatch Logs
2224
+ const logsKey = new Key(this, 'LogsKey', {
2225
+ enableKeyRotation: true,
2226
+ });
2227
+ logsKey.grantEncryptDecrypt(
2228
+ new ServicePrincipal(\`logs.\${Stack.of(this).region}.amazonaws.com\`),
2229
+ );
2230
+
2231
+ const accessLogs = new LogGroup(this, 'AccessLogs', {
2232
+ retention: RetentionDays.ONE_YEAR,
2233
+ encryptionKey: logsKey,
2234
+ });
2235
+
2108
2236
  // Create the API Gateway REST API
2109
- this.api = new _RestApi(this, 'Api', props);
2237
+ this.api = new _RestApi(this, 'Api', {
2238
+ ...props,
2239
+ deployOptions: {
2240
+ accessLogDestination: new LogGroupLogDestination(accessLogs),
2241
+ accessLogFormat: AccessLogFormat.jsonWithStandardFields(),
2242
+ ...props.deployOptions,
2243
+ methodOptions: {
2244
+ ...props.deployOptions?.methodOptions,
2245
+ // Default throttling applied to all resource paths and methods
2246
+ '/*/*': {
2247
+ throttlingRateLimit: throttle.rateLimit,
2248
+ throttlingBurstLimit: throttle.burstLimit,
2249
+ ...props.deployOptions?.methodOptions?.['/*/*'],
2250
+ },
2251
+ },
2252
+ },
2253
+ });
2254
+ // Ensure the account-level role is configured before the stage is created
2255
+ this.api.deploymentStage.node.addDependency(account.resource);
2110
2256
 
2111
2257
  if (enableWaf) {
2112
2258
  this.webAcl = new CfnWebACL(this, 'WebAcl', {
@@ -2173,14 +2319,9 @@ export class RestApi<
2173
2319
  // \`aws-waf-logs-\` to satisfy the WAFv2 logging destination requirement.
2174
2320
  const wafLogGroup = new LogGroup(this, 'WebAclLogs', {
2175
2321
  logGroupName: \`aws-waf-logs-\${apiName}-\${this.node.addr.slice(-8)}\`,
2176
- retention: RetentionDays.ONE_MONTH,
2177
- removalPolicy: RemovalPolicy.DESTROY,
2322
+ retention: RetentionDays.ONE_YEAR,
2323
+ encryptionKey: logsKey,
2178
2324
  });
2179
- suppressRules(
2180
- wafLogGroup,
2181
- ['CKV_AWS_158'],
2182
- 'Using default CloudWatch log encryption for WAF logs',
2183
- );
2184
2325
 
2185
2326
  new CfnLoggingConfiguration(this, 'WebAclLoggingConfig', {
2186
2327
  resourceArn: this.webAcl.attrArn,
@@ -2194,12 +2335,6 @@ export class RestApi<
2194
2335
  'Caching not required for this use case',
2195
2336
  (c) => c instanceof Stage,
2196
2337
  );
2197
- suppressRules(
2198
- this.api,
2199
- ['CKV_AWS_76'],
2200
- 'API Gateway access logging disabled due to account-level CloudWatch Logs role ARN requirement',
2201
- (c) => c instanceof Stage,
2202
- );
2203
2338
 
2204
2339
  // Resolve the integration for a given operation.
2205
2340
  // If the operation has a dedicated integration, use it; otherwise fall back to $router.
@@ -2311,9 +2446,10 @@ import {
2311
2446
  IntegrationBuilder,
2312
2447
  RestApiIntegration,
2313
2448
  } from '../../core/api/utils.js';
2449
+ import { findCloudFrontDomainNames } from '../../core/cloudfront.js';
2314
2450
  import { AddCorsPreflightAspect, RestApi } from '../../core/api/rest-api.js';
2315
2451
  import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
2316
- import { AppRouter, appRouter } from ':proj/test-api';
2452
+ import { AppRouter, appRouter } from '@proj/test-api';
2317
2453
 
2318
2454
  // String union type for all API operation names
2319
2455
  type Operations = Procedures<AppRouter>;
@@ -2360,7 +2496,7 @@ export class TestApi<
2360
2496
  return IntegrationBuilder.rest({
2361
2497
  pattern: 'isolated',
2362
2498
  operations: routerToOperations(appRouter),
2363
- defaultIntegrationOptions: <FunctionProps>{
2499
+ defaultIntegrationOptions: {
2364
2500
  runtime: Runtime.NODEJS_LATEST,
2365
2501
  handler: 'index.handler',
2366
2502
  code: Code.fromAsset(
@@ -2373,7 +2509,7 @@ export class TestApi<
2373
2509
  ),
2374
2510
  timeout: Duration.seconds(30),
2375
2511
  tracing: Tracing.ACTIVE,
2376
- },
2512
+ } as FunctionProps,
2377
2513
  buildDefaultIntegration: (op, props: FunctionProps) => {
2378
2514
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
2379
2515
  handler.addEnvironment(
@@ -2426,7 +2562,9 @@ export class TestApi<
2426
2562
  *
2427
2563
  * Configures the provided CloudFront distribution domains or origin strings
2428
2564
  * as the only permitted CORS origins in API Gateway preflight responses and the
2429
- * AWS Lambda integrations.
2565
+ * AWS Lambda integrations. Any custom domain names (aliases) configured on a
2566
+ * CloudFront distribution are included automatically alongside its default
2567
+ * \`*.cloudfront.net\` domain.
2430
2568
  *
2431
2569
  * @param origins - The origin strings, CloudFront distributions, or objects containing a CloudFront distribution to grant CORS from
2432
2570
  */
@@ -2437,12 +2575,14 @@ export class TestApi<
2437
2575
  | { cloudFrontDistribution: Distribution }
2438
2576
  )[]
2439
2577
  ) {
2440
- const allowedOrigins = origins.map((origin) =>
2578
+ const allowedOrigins = origins.flatMap((origin) =>
2441
2579
  typeof origin === 'string'
2442
- ? origin
2443
- : 'cloudFrontDistribution' in origin
2444
- ? \`https://\${origin.cloudFrontDistribution.distributionDomainName}\`
2445
- : \`https://\${origin.distributionDomainName}\`,
2580
+ ? [origin]
2581
+ : findCloudFrontDomainNames(
2582
+ 'cloudFrontDistribution' in origin
2583
+ ? origin.cloudFrontDistribution
2584
+ : origin,
2585
+ ).map((domain) => \`https://\${domain}\`),
2446
2586
  );
2447
2587
 
2448
2588
  this.allowedOrigins = allowedOrigins;
@@ -2708,6 +2848,8 @@ export type ApiIntegrations<TOperation extends string, TBaseIntegration> =
2708
2848
  * @template TDefaultIntegrationProps - Type for default integration properties
2709
2849
  * @template TDefaultIntegration - Type for default integration implementation
2710
2850
  * @template TPattern - The integration pattern ('shared' or 'isolated')
2851
+ * @template TOverridden - Union of operation names that have been overridden
2852
+ * @template TOperationOptioned - Union of operation names with per-operation options
2711
2853
  */
2712
2854
  export class IntegrationBuilder<
2713
2855
  TOperation extends string,
@@ -2716,6 +2858,8 @@ export class IntegrationBuilder<
2716
2858
  TDefaultIntegrationProps extends object,
2717
2859
  TDefaultIntegration extends TBaseIntegration,
2718
2860
  TPattern extends 'shared' | 'isolated',
2861
+ TOverridden extends string = never,
2862
+ TOperationOptioned extends string = never,
2719
2863
  > {
2720
2864
  /** Options for the integration builder */
2721
2865
  private options: IntegrationBuilderProps<
@@ -2728,6 +2872,11 @@ export class IntegrationBuilder<
2728
2872
  /** Map of operation names to their custom integrations */
2729
2873
  private integrations: Partial<TIntegrations> = {};
2730
2874
 
2875
+ /** Map of default integration keys to per-operation default option overrides */
2876
+ private perOperationOptions: Partial<
2877
+ Record<string, Partial<TDefaultIntegrationProps>>
2878
+ > = {};
2879
+
2731
2880
  /**
2732
2881
  * Create an Integration Builder for an HTTP API with a shared pattern
2733
2882
  */
@@ -2882,11 +3031,16 @@ export class IntegrationBuilder<
2882
3031
  /**
2883
3032
  * Overrides default integrations with custom implementations for specific operations.
2884
3033
  *
3034
+ * Operations which have per-operation options set via withOperationOptions cannot be
3035
+ * overridden, since these still use the default integration.
3036
+ *
2885
3037
  * @param overrides - Map of operation names to their custom integration implementations
2886
3038
  * @returns The builder instance with updated type information reflecting the overrides
2887
3039
  */
2888
3040
  public withOverrides<
2889
- TOverrideIntegrations extends Partial<Record<TOperation, TBaseIntegration>>,
3041
+ TOverrideIntegrations extends Partial<
3042
+ Record<Exclude<TOperation, TOperationOptioned>, TBaseIntegration>
3043
+ >,
2890
3044
  >(overrides: TOverrideIntegrations) {
2891
3045
  this.integrations = { ...this.integrations, ...overrides };
2892
3046
  // Re-type to include the overridden integration types.
@@ -2902,7 +3056,9 @@ export class IntegrationBuilder<
2902
3056
  MergedIntegrations,
2903
3057
  TDefaultIntegrationProps,
2904
3058
  TDefaultIntegration,
2905
- TPattern
3059
+ TPattern,
3060
+ TOverridden | Extract<keyof TOverrideIntegrations, string>,
3061
+ TOperationOptioned
2906
3062
  >;
2907
3063
  }
2908
3064
 
@@ -2921,6 +3077,43 @@ export class IntegrationBuilder<
2921
3077
  return this;
2922
3078
  }
2923
3079
 
3080
+ /**
3081
+ * Updates the default integration options for specific operations, without
3082
+ * affecting the others. The given options are merged with the defaults (and
3083
+ * any options set via withDefaultOptions) when building each default integration.
3084
+ *
3085
+ * Operations which have been replaced via withOverrides cannot be targeted, since
3086
+ * they no longer use the default integration.
3087
+ *
3088
+ * @param options - Map of operation names to partial default integration options
3089
+ * @returns The builder instance
3090
+ */
3091
+ public withOperationOptions<
3092
+ TOptions extends Partial<
3093
+ Record<
3094
+ Exclude<DefaultIntegrationKeys<TPattern, TOperation>, TOverridden>,
3095
+ Partial<TDefaultIntegrationProps>
3096
+ >
3097
+ >,
3098
+ >(options: TOptions) {
3099
+ Object.entries(options).forEach(([op, opOptions]) => {
3100
+ this.perOperationOptions[op] = {
3101
+ ...this.perOperationOptions[op],
3102
+ ...(opOptions as Partial<TDefaultIntegrationProps>),
3103
+ };
3104
+ });
3105
+ return this as unknown as IntegrationBuilder<
3106
+ TOperation,
3107
+ TBaseIntegration,
3108
+ TIntegrations,
3109
+ TDefaultIntegrationProps,
3110
+ TDefaultIntegration,
3111
+ TPattern,
3112
+ TOverridden,
3113
+ TOperationOptioned | Extract<keyof TOptions, string>
3114
+ >;
3115
+ }
3116
+
2924
3117
  /**
2925
3118
  * Builds and returns the complete set of integrations.
2926
3119
  *
@@ -2935,6 +3128,10 @@ export class IntegrationBuilder<
2935
3128
  */
2936
3129
  public build(): TIntegrations {
2937
3130
  const options = this.options;
3131
+ const buildOptionsFor = (op: string): TDefaultIntegrationProps => ({
3132
+ ...options.defaultIntegrationOptions,
3133
+ ...this.perOperationOptions[op],
3134
+ });
2938
3135
  return {
2939
3136
  ...Object.fromEntries(
2940
3137
  options.pattern === 'shared'
@@ -2943,7 +3140,7 @@ export class IntegrationBuilder<
2943
3140
  '$router',
2944
3141
  options.buildDefaultIntegration(
2945
3142
  '$router',
2946
- options.defaultIntegrationOptions,
3143
+ buildOptionsFor('$router'),
2947
3144
  ),
2948
3145
  ],
2949
3146
  ]
@@ -2954,10 +3151,7 @@ export class IntegrationBuilder<
2954
3151
  )
2955
3152
  .map((op) => [
2956
3153
  op,
2957
- options.buildDefaultIntegration(
2958
- op,
2959
- options.defaultIntegrationOptions,
2960
- ),
3154
+ options.buildDefaultIntegration(op, buildOptionsFor(op)),
2961
3155
  ]),
2962
3156
  ),
2963
3157
  ...this.integrations,
@@ -2978,7 +3172,7 @@ terraform {
2978
3172
  required_providers {
2979
3173
  aws = {
2980
3174
  source = "hashicorp/aws"
2981
- version = "~> 6.0"
3175
+ version = "6.55.0"
2982
3176
  }
2983
3177
  }
2984
3178
  }
@@ -3225,7 +3419,7 @@ output "api_log_group_arn" {
3225
3419
  required_providers {
3226
3420
  aws = {
3227
3421
  source = "hashicorp/aws"
3228
- version = "~> 6.0"
3422
+ version = "6.55.0"
3229
3423
  }
3230
3424
  }
3231
3425
  }
@@ -3257,11 +3451,47 @@ variable "additional_iam_policy_statements" {
3257
3451
  default = []
3258
3452
  }
3259
3453
 
3454
+ variable "appconfig_application_id" {
3455
+ description = "ID of the shared runtime-config AppConfig application (from \`core/runtime-config/appconfig.application_id\`). When set, the Lambda functions receive \`RUNTIME_CONFIG_APP_ID\` and read access to the application."
3456
+ type = string
3457
+ default = null
3458
+ }
3459
+
3460
+ variable "appconfig_application_arn" {
3461
+ description = "ARN of the shared runtime-config AppConfig application (from \`core/runtime-config/appconfig.application_arn\`). Used to scope the IAM read permission granted to the Lambda functions."
3462
+ type = string
3463
+ default = null
3464
+ }
3465
+
3260
3466
  variable "asset_bucket_name" {
3261
3467
  description = "Name of the shared asset S3 bucket used to stage the Lambda deployment zip. Instantiate the \`core/asset-bucket\` module once per deployment and pass its \`bucket_name\` output here."
3262
3468
  type = string
3263
3469
  }
3264
3470
 
3471
+ # VPC Configuration (optional)
3472
+ variable "enable_vpc" {
3473
+ description = "Deploy the Lambda function into a VPC. Set alongside vpc_id/subnet_ids."
3474
+ type = bool
3475
+ default = false
3476
+ }
3477
+
3478
+ variable "vpc_id" {
3479
+ description = "VPC ID to deploy the Lambda function into. Required when enable_vpc is true."
3480
+ type = string
3481
+ default = null
3482
+
3483
+ validation {
3484
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
3485
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
3486
+ }
3487
+ }
3488
+
3489
+ variable "subnet_ids" {
3490
+ description = "Subnet IDs to deploy the Lambda function into. Required when enable_vpc is true."
3491
+ type = list(string)
3492
+ default = null
3493
+ }
3494
+
3265
3495
  # CORS Configuration (passed to core module)
3266
3496
  variable "cors_allow_credentials" {
3267
3497
  description = "Whether to allow credentials in CORS requests"
@@ -3293,12 +3523,6 @@ variable "cors_expose_headers" {
3293
3523
  default = []
3294
3524
  }
3295
3525
 
3296
- variable "cors_max_age" {
3297
- description = "Maximum age for CORS preflight requests in seconds"
3298
- type = number
3299
- default = 0
3300
- }
3301
-
3302
3526
  # Tags
3303
3527
  variable "tags" {
3304
3528
  description = "Tags to apply to all resources"
@@ -3349,16 +3573,37 @@ module "http_api" {
3349
3573
  cors_allow_methods = var.cors_allow_methods
3350
3574
  cors_allow_origins = var.cors_allow_origins
3351
3575
  cors_expose_headers = var.cors_expose_headers
3352
- cors_max_age = var.cors_max_age
3353
3576
 
3354
3577
  # Tags
3355
3578
  tags = var.tags
3356
3579
  }
3357
3580
 
3581
+ # Security group for the API Lambda function, used when deployed into a VPC
3582
+ resource "aws_security_group" "api_lambda" {
3583
+ count = var.enable_vpc ? 1 : 0
3584
+
3585
+ #checkov:skip=CKV2_AWS_5:Attached to api_lambda via vpc_config block; Checkov cannot resolve this reference
3586
+ name_prefix = "test-api-lambda-"
3587
+ description = "Security group for the TestApi API Lambda function"
3588
+ vpc_id = var.vpc_id
3589
+ tags = var.tags
3590
+ }
3591
+
3592
+ resource "aws_vpc_security_group_egress_rule" "api_lambda_https" {
3593
+ count = var.enable_vpc ? 1 : 0
3594
+
3595
+ security_group_id = aws_security_group.api_lambda[0].id
3596
+ cidr_ipv4 = "0.0.0.0/0"
3597
+ from_port = 443
3598
+ to_port = 443
3599
+ ip_protocol = "tcp"
3600
+ description = "Allow outbound HTTPS to AWS service endpoints"
3601
+ }
3602
+
3358
3603
  # Lambda function
3359
3604
  # This configures a single "router" lambda to serve all requests
3360
3605
  resource "aws_lambda_function" "api_lambda" {
3361
- #checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
3606
+ #checkov:skip=CKV_AWS_117:Lambda function is optionally deployed into a VPC via vpc_id/subnet_ids; not required for this use case
3362
3607
  #checkov:skip=CKV_AWS_116:Dead Letter Queue not required for this simple API use case
3363
3608
  #checkov:skip=CKV_AWS_272:Code signing not required for this use case
3364
3609
  #checkov:skip=CKV_AWS_115:Concurrent execution limit not required for this use case
@@ -3380,13 +3625,25 @@ resource "aws_lambda_function" "api_lambda" {
3380
3625
  mode = "Active"
3381
3626
  }
3382
3627
 
3628
+ dynamic "vpc_config" {
3629
+ for_each = var.enable_vpc ? [1] : []
3630
+ content {
3631
+ subnet_ids = var.subnet_ids
3632
+ security_group_ids = [aws_security_group.api_lambda[0].id]
3633
+ }
3634
+ }
3635
+
3383
3636
 
3384
3637
  environment {
3385
3638
  variables = merge({
3386
- }, var.env)
3639
+ }, var.appconfig_application_id != null ? {
3640
+ RUNTIME_CONFIG_APP_ID = var.appconfig_application_id
3641
+ } : {}, var.env)
3387
3642
  }
3388
3643
 
3389
3644
  tags = var.tags
3645
+
3646
+ depends_on = [aws_iam_role_policy_attachment.lambda_vpc_access]
3390
3647
  }
3391
3648
 
3392
3649
  # IAM role for Lambda execution
@@ -3421,18 +3678,39 @@ resource "aws_iam_role_policy_attachment" "lambda_xray_execution" {
3421
3678
  role = aws_iam_role.lambda_execution_role.name
3422
3679
  }
3423
3680
 
3681
+ # Attach VPC access policy to Lambda role when deployed into a VPC
3682
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
3683
+ count = var.enable_vpc ? 1 : 0
3684
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
3685
+ role = aws_iam_role.lambda_execution_role.name
3686
+ }
3687
+
3424
3688
  # Additional IAM policies for Lambda (if provided)
3425
3689
  resource "aws_iam_role_policy" "lambda_additional_policies" {
3426
- count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
3690
+ count = length(local.lambda_policy_statements) > 0 ? 1 : 0
3427
3691
  name = "TestApiHandler-additional-policies-\${random_string.suffix.result}"
3428
3692
  role = aws_iam_role.lambda_execution_role.id
3429
3693
 
3430
3694
  policy = jsonencode({
3431
3695
  Version = "2012-10-17"
3432
- Statement = var.additional_iam_policy_statements
3696
+ Statement = local.lambda_policy_statements
3433
3697
  })
3434
3698
  }
3435
3699
 
3700
+ locals {
3701
+ # Grant read access to the runtime-config AppConfig application when wired
3702
+ lambda_policy_statements = concat(var.appconfig_application_arn != null ? [
3703
+ {
3704
+ Effect = "Allow"
3705
+ Action = [
3706
+ "appconfig:StartConfigurationSession",
3707
+ "appconfig:GetLatestConfiguration"
3708
+ ]
3709
+ Resource = ["\${var.appconfig_application_arn}/*"]
3710
+ }
3711
+ ] : [], var.additional_iam_policy_statements)
3712
+ }
3713
+
3436
3714
  # CloudWatch Log Group for Lambda
3437
3715
  resource "aws_cloudwatch_log_group" "lambda_logs" {
3438
3716
  #checkov:skip=CKV_AWS_158:Using default CloudWatch log encryption
@@ -3591,6 +3869,11 @@ output "lambda_execution_role_name" {
3591
3869
  value = aws_iam_role.lambda_execution_role.name
3592
3870
  }
3593
3871
 
3872
+ output "security_group_id" {
3873
+ description = "Security group ID of the API Lambda function, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
3874
+ value = var.enable_vpc ? aws_security_group.api_lambda[0].id : null
3875
+ }
3876
+
3594
3877
  # Integration Outputs
3595
3878
  output "integration_id" {
3596
3879
  description = "ID of the Lambda integration"
@@ -3631,7 +3914,7 @@ terraform {
3631
3914
  required_providers {
3632
3915
  aws = {
3633
3916
  source = "hashicorp/aws"
3634
- version = "~> 6.0"
3917
+ version = "6.55.0"
3635
3918
  }
3636
3919
  }
3637
3920
  }
@@ -3878,7 +4161,7 @@ output "api_log_group_arn" {
3878
4161
  required_providers {
3879
4162
  aws = {
3880
4163
  source = "hashicorp/aws"
3881
- version = "~> 6.0"
4164
+ version = "6.55.0"
3882
4165
  }
3883
4166
  }
3884
4167
  }
@@ -3900,11 +4183,47 @@ variable "additional_iam_policy_statements" {
3900
4183
  default = []
3901
4184
  }
3902
4185
 
4186
+ variable "appconfig_application_id" {
4187
+ description = "ID of the shared runtime-config AppConfig application (from \`core/runtime-config/appconfig.application_id\`). When set, the Lambda functions receive \`RUNTIME_CONFIG_APP_ID\` and read access to the application."
4188
+ type = string
4189
+ default = null
4190
+ }
4191
+
4192
+ variable "appconfig_application_arn" {
4193
+ description = "ARN of the shared runtime-config AppConfig application (from \`core/runtime-config/appconfig.application_arn\`). Used to scope the IAM read permission granted to the Lambda functions."
4194
+ type = string
4195
+ default = null
4196
+ }
4197
+
3903
4198
  variable "asset_bucket_name" {
3904
4199
  description = "Name of the shared asset S3 bucket used to stage the Lambda deployment zip. Instantiate the \`core/asset-bucket\` module once per deployment and pass its \`bucket_name\` output here."
3905
4200
  type = string
3906
4201
  }
3907
4202
 
4203
+ # VPC Configuration (optional)
4204
+ variable "enable_vpc" {
4205
+ description = "Deploy the Lambda function into a VPC. Set alongside vpc_id/subnet_ids."
4206
+ type = bool
4207
+ default = false
4208
+ }
4209
+
4210
+ variable "vpc_id" {
4211
+ description = "VPC ID to deploy the Lambda function into. Required when enable_vpc is true."
4212
+ type = string
4213
+ default = null
4214
+
4215
+ validation {
4216
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
4217
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
4218
+ }
4219
+ }
4220
+
4221
+ variable "subnet_ids" {
4222
+ description = "Subnet IDs to deploy the Lambda function into. Required when enable_vpc is true."
4223
+ type = list(string)
4224
+ default = null
4225
+ }
4226
+
3908
4227
  # CORS Configuration (passed to core module)
3909
4228
  variable "cors_allow_credentials" {
3910
4229
  description = "Whether to allow credentials in CORS requests"
@@ -3936,12 +4255,6 @@ variable "cors_expose_headers" {
3936
4255
  default = []
3937
4256
  }
3938
4257
 
3939
- variable "cors_max_age" {
3940
- description = "Maximum age for CORS preflight requests in seconds"
3941
- type = number
3942
- default = 0
3943
- }
3944
-
3945
4258
  # Tags
3946
4259
  variable "tags" {
3947
4260
  description = "Tags to apply to all resources"
@@ -3992,16 +4305,37 @@ module "http_api" {
3992
4305
  cors_allow_methods = var.cors_allow_methods
3993
4306
  cors_allow_origins = var.cors_allow_origins
3994
4307
  cors_expose_headers = var.cors_expose_headers
3995
- cors_max_age = var.cors_max_age
3996
4308
 
3997
4309
  # Tags
3998
4310
  tags = var.tags
3999
4311
  }
4000
4312
 
4313
+ # Security group for the API Lambda function, used when deployed into a VPC
4314
+ resource "aws_security_group" "api_lambda" {
4315
+ count = var.enable_vpc ? 1 : 0
4316
+
4317
+ #checkov:skip=CKV2_AWS_5:Attached to api_lambda via vpc_config block; Checkov cannot resolve this reference
4318
+ name_prefix = "test-api-lambda-"
4319
+ description = "Security group for the TestApi API Lambda function"
4320
+ vpc_id = var.vpc_id
4321
+ tags = var.tags
4322
+ }
4323
+
4324
+ resource "aws_vpc_security_group_egress_rule" "api_lambda_https" {
4325
+ count = var.enable_vpc ? 1 : 0
4326
+
4327
+ security_group_id = aws_security_group.api_lambda[0].id
4328
+ cidr_ipv4 = "0.0.0.0/0"
4329
+ from_port = 443
4330
+ to_port = 443
4331
+ ip_protocol = "tcp"
4332
+ description = "Allow outbound HTTPS to AWS service endpoints"
4333
+ }
4334
+
4001
4335
  # Lambda function
4002
4336
  # This configures a single "router" lambda to serve all requests
4003
4337
  resource "aws_lambda_function" "api_lambda" {
4004
- #checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
4338
+ #checkov:skip=CKV_AWS_117:Lambda function is optionally deployed into a VPC via vpc_id/subnet_ids; not required for this use case
4005
4339
  #checkov:skip=CKV_AWS_116:Dead Letter Queue not required for this simple API use case
4006
4340
  #checkov:skip=CKV_AWS_272:Code signing not required for this use case
4007
4341
  #checkov:skip=CKV_AWS_115:Concurrent execution limit not required for this use case
@@ -4023,13 +4357,25 @@ resource "aws_lambda_function" "api_lambda" {
4023
4357
  mode = "Active"
4024
4358
  }
4025
4359
 
4360
+ dynamic "vpc_config" {
4361
+ for_each = var.enable_vpc ? [1] : []
4362
+ content {
4363
+ subnet_ids = var.subnet_ids
4364
+ security_group_ids = [aws_security_group.api_lambda[0].id]
4365
+ }
4366
+ }
4367
+
4026
4368
 
4027
4369
  environment {
4028
4370
  variables = merge({
4029
- }, var.env)
4371
+ }, var.appconfig_application_id != null ? {
4372
+ RUNTIME_CONFIG_APP_ID = var.appconfig_application_id
4373
+ } : {}, var.env)
4030
4374
  }
4031
4375
 
4032
4376
  tags = var.tags
4377
+
4378
+ depends_on = [aws_iam_role_policy_attachment.lambda_vpc_access]
4033
4379
  }
4034
4380
 
4035
4381
  # IAM role for Lambda execution
@@ -4064,18 +4410,39 @@ resource "aws_iam_role_policy_attachment" "lambda_xray_execution" {
4064
4410
  role = aws_iam_role.lambda_execution_role.name
4065
4411
  }
4066
4412
 
4413
+ # Attach VPC access policy to Lambda role when deployed into a VPC
4414
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
4415
+ count = var.enable_vpc ? 1 : 0
4416
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
4417
+ role = aws_iam_role.lambda_execution_role.name
4418
+ }
4419
+
4067
4420
  # Additional IAM policies for Lambda (if provided)
4068
4421
  resource "aws_iam_role_policy" "lambda_additional_policies" {
4069
- count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
4422
+ count = length(local.lambda_policy_statements) > 0 ? 1 : 0
4070
4423
  name = "TestApiHandler-additional-policies-\${random_string.suffix.result}"
4071
4424
  role = aws_iam_role.lambda_execution_role.id
4072
4425
 
4073
4426
  policy = jsonencode({
4074
4427
  Version = "2012-10-17"
4075
- Statement = var.additional_iam_policy_statements
4428
+ Statement = local.lambda_policy_statements
4076
4429
  })
4077
4430
  }
4078
4431
 
4432
+ locals {
4433
+ # Grant read access to the runtime-config AppConfig application when wired
4434
+ lambda_policy_statements = concat(var.appconfig_application_arn != null ? [
4435
+ {
4436
+ Effect = "Allow"
4437
+ Action = [
4438
+ "appconfig:StartConfigurationSession",
4439
+ "appconfig:GetLatestConfiguration"
4440
+ ]
4441
+ Resource = ["\${var.appconfig_application_arn}/*"]
4442
+ }
4443
+ ] : [], var.additional_iam_policy_statements)
4444
+ }
4445
+
4079
4446
  # CloudWatch Log Group for Lambda
4080
4447
  resource "aws_cloudwatch_log_group" "lambda_logs" {
4081
4448
  #checkov:skip=CKV_AWS_158:Using default CloudWatch log encryption
@@ -4316,6 +4683,11 @@ output "lambda_execution_role_name" {
4316
4683
  value = aws_iam_role.lambda_execution_role.name
4317
4684
  }
4318
4685
 
4686
+ output "security_group_id" {
4687
+ description = "Security group ID of the API Lambda function, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
4688
+ value = var.enable_vpc ? aws_security_group.api_lambda[0].id : null
4689
+ }
4690
+
4319
4691
  # Integration Outputs
4320
4692
  output "integration_id" {
4321
4693
  description = "ID of the Lambda integration"
@@ -4356,7 +4728,7 @@ terraform {
4356
4728
  required_providers {
4357
4729
  aws = {
4358
4730
  source = "hashicorp/aws"
4359
- version = "~> 6.0"
4731
+ version = "6.55.0"
4360
4732
  }
4361
4733
  }
4362
4734
  }
@@ -4603,7 +4975,7 @@ output "api_log_group_arn" {
4603
4975
  required_providers {
4604
4976
  aws = {
4605
4977
  source = "hashicorp/aws"
4606
- version = "~> 6.0"
4978
+ version = "6.55.0"
4607
4979
  }
4608
4980
  }
4609
4981
  }
@@ -4625,11 +4997,47 @@ variable "additional_iam_policy_statements" {
4625
4997
  default = []
4626
4998
  }
4627
4999
 
5000
+ variable "appconfig_application_id" {
5001
+ description = "ID of the shared runtime-config AppConfig application (from \`core/runtime-config/appconfig.application_id\`). When set, the Lambda functions receive \`RUNTIME_CONFIG_APP_ID\` and read access to the application."
5002
+ type = string
5003
+ default = null
5004
+ }
5005
+
5006
+ variable "appconfig_application_arn" {
5007
+ description = "ARN of the shared runtime-config AppConfig application (from \`core/runtime-config/appconfig.application_arn\`). Used to scope the IAM read permission granted to the Lambda functions."
5008
+ type = string
5009
+ default = null
5010
+ }
5011
+
4628
5012
  variable "asset_bucket_name" {
4629
5013
  description = "Name of the shared asset S3 bucket used to stage the Lambda deployment zip. Instantiate the \`core/asset-bucket\` module once per deployment and pass its \`bucket_name\` output here."
4630
5014
  type = string
4631
5015
  }
4632
5016
 
5017
+ # VPC Configuration (optional)
5018
+ variable "enable_vpc" {
5019
+ description = "Deploy the Lambda function into a VPC. Set alongside vpc_id/subnet_ids."
5020
+ type = bool
5021
+ default = false
5022
+ }
5023
+
5024
+ variable "vpc_id" {
5025
+ description = "VPC ID to deploy the Lambda function into. Required when enable_vpc is true."
5026
+ type = string
5027
+ default = null
5028
+
5029
+ validation {
5030
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
5031
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
5032
+ }
5033
+ }
5034
+
5035
+ variable "subnet_ids" {
5036
+ description = "Subnet IDs to deploy the Lambda function into. Required when enable_vpc is true."
5037
+ type = list(string)
5038
+ default = null
5039
+ }
5040
+
4633
5041
  # CORS Configuration (passed to core module)
4634
5042
  variable "cors_allow_credentials" {
4635
5043
  description = "Whether to allow credentials in CORS requests"
@@ -4661,12 +5069,6 @@ variable "cors_expose_headers" {
4661
5069
  default = []
4662
5070
  }
4663
5071
 
4664
- variable "cors_max_age" {
4665
- description = "Maximum age for CORS preflight requests in seconds"
4666
- type = number
4667
- default = 0
4668
- }
4669
-
4670
5072
  # Tags
4671
5073
  variable "tags" {
4672
5074
  description = "Tags to apply to all resources"
@@ -4717,16 +5119,37 @@ module "http_api" {
4717
5119
  cors_allow_methods = var.cors_allow_methods
4718
5120
  cors_allow_origins = var.cors_allow_origins
4719
5121
  cors_expose_headers = var.cors_expose_headers
4720
- cors_max_age = var.cors_max_age
4721
5122
 
4722
5123
  # Tags
4723
5124
  tags = var.tags
4724
5125
  }
4725
5126
 
5127
+ # Security group for the API Lambda function, used when deployed into a VPC
5128
+ resource "aws_security_group" "api_lambda" {
5129
+ count = var.enable_vpc ? 1 : 0
5130
+
5131
+ #checkov:skip=CKV2_AWS_5:Attached to api_lambda via vpc_config block; Checkov cannot resolve this reference
5132
+ name_prefix = "test-api-lambda-"
5133
+ description = "Security group for the TestApi API Lambda function"
5134
+ vpc_id = var.vpc_id
5135
+ tags = var.tags
5136
+ }
5137
+
5138
+ resource "aws_vpc_security_group_egress_rule" "api_lambda_https" {
5139
+ count = var.enable_vpc ? 1 : 0
5140
+
5141
+ security_group_id = aws_security_group.api_lambda[0].id
5142
+ cidr_ipv4 = "0.0.0.0/0"
5143
+ from_port = 443
5144
+ to_port = 443
5145
+ ip_protocol = "tcp"
5146
+ description = "Allow outbound HTTPS to AWS service endpoints"
5147
+ }
5148
+
4726
5149
  # Lambda function
4727
5150
  # This configures a single "router" lambda to serve all requests
4728
5151
  resource "aws_lambda_function" "api_lambda" {
4729
- #checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
5152
+ #checkov:skip=CKV_AWS_117:Lambda function is optionally deployed into a VPC via vpc_id/subnet_ids; not required for this use case
4730
5153
  #checkov:skip=CKV_AWS_116:Dead Letter Queue not required for this simple API use case
4731
5154
  #checkov:skip=CKV_AWS_272:Code signing not required for this use case
4732
5155
  #checkov:skip=CKV_AWS_115:Concurrent execution limit not required for this use case
@@ -4748,13 +5171,25 @@ resource "aws_lambda_function" "api_lambda" {
4748
5171
  mode = "Active"
4749
5172
  }
4750
5173
 
5174
+ dynamic "vpc_config" {
5175
+ for_each = var.enable_vpc ? [1] : []
5176
+ content {
5177
+ subnet_ids = var.subnet_ids
5178
+ security_group_ids = [aws_security_group.api_lambda[0].id]
5179
+ }
5180
+ }
5181
+
4751
5182
 
4752
5183
  environment {
4753
5184
  variables = merge({
4754
- }, var.env)
5185
+ }, var.appconfig_application_id != null ? {
5186
+ RUNTIME_CONFIG_APP_ID = var.appconfig_application_id
5187
+ } : {}, var.env)
4755
5188
  }
4756
5189
 
4757
5190
  tags = var.tags
5191
+
5192
+ depends_on = [aws_iam_role_policy_attachment.lambda_vpc_access]
4758
5193
  }
4759
5194
 
4760
5195
  # IAM role for Lambda execution
@@ -4789,18 +5224,39 @@ resource "aws_iam_role_policy_attachment" "lambda_xray_execution" {
4789
5224
  role = aws_iam_role.lambda_execution_role.name
4790
5225
  }
4791
5226
 
5227
+ # Attach VPC access policy to Lambda role when deployed into a VPC
5228
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
5229
+ count = var.enable_vpc ? 1 : 0
5230
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
5231
+ role = aws_iam_role.lambda_execution_role.name
5232
+ }
5233
+
4792
5234
  # Additional IAM policies for Lambda (if provided)
4793
5235
  resource "aws_iam_role_policy" "lambda_additional_policies" {
4794
- count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
5236
+ count = length(local.lambda_policy_statements) > 0 ? 1 : 0
4795
5237
  name = "TestApiHandler-additional-policies-\${random_string.suffix.result}"
4796
5238
  role = aws_iam_role.lambda_execution_role.id
4797
5239
 
4798
5240
  policy = jsonencode({
4799
5241
  Version = "2012-10-17"
4800
- Statement = var.additional_iam_policy_statements
5242
+ Statement = local.lambda_policy_statements
4801
5243
  })
4802
5244
  }
4803
5245
 
5246
+ locals {
5247
+ # Grant read access to the runtime-config AppConfig application when wired
5248
+ lambda_policy_statements = concat(var.appconfig_application_arn != null ? [
5249
+ {
5250
+ Effect = "Allow"
5251
+ Action = [
5252
+ "appconfig:StartConfigurationSession",
5253
+ "appconfig:GetLatestConfiguration"
5254
+ ]
5255
+ Resource = ["\${var.appconfig_application_arn}/*"]
5256
+ }
5257
+ ] : [], var.additional_iam_policy_statements)
5258
+ }
5259
+
4804
5260
  # CloudWatch Log Group for Lambda
4805
5261
  resource "aws_cloudwatch_log_group" "lambda_logs" {
4806
5262
  #checkov:skip=CKV_AWS_158:Using default CloudWatch log encryption
@@ -4946,6 +5402,11 @@ output "lambda_execution_role_name" {
4946
5402
  value = aws_iam_role.lambda_execution_role.name
4947
5403
  }
4948
5404
 
5405
+ output "security_group_id" {
5406
+ description = "Security group ID of the API Lambda function, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
5407
+ value = var.enable_vpc ? aws_security_group.api_lambda[0].id : null
5408
+ }
5409
+
4949
5410
  # Integration Outputs
4950
5411
  output "integration_id" {
4951
5412
  description = "ID of the Lambda integration"
@@ -4986,11 +5447,11 @@ terraform {
4986
5447
  required_providers {
4987
5448
  aws = {
4988
5449
  source = "hashicorp/aws"
4989
- version = "~> 6.33"
5450
+ version = "6.55.0"
4990
5451
  }
4991
5452
  random = {
4992
5453
  source = "hashicorp/random"
4993
- version = "~> 3.1"
5454
+ version = "3.9.0"
4994
5455
  }
4995
5456
  }
4996
5457
  }
@@ -5060,8 +5521,6 @@ data "aws_caller_identity" "current" {}
5060
5521
 
5061
5522
  # Resources
5062
5523
 
5063
- # Note: CloudWatch logging removed due to account-level CloudWatch Logs role ARN requirement
5064
-
5065
5524
  # REST API Gateway
5066
5525
  resource "aws_api_gateway_rest_api" "rest_api" {
5067
5526
  name = var.api_name
@@ -5078,10 +5537,8 @@ resource "aws_api_gateway_rest_api" "rest_api" {
5078
5537
  tags = var.tags
5079
5538
  }
5080
5539
 
5081
- # Note: Deployment and stage are created in the consuming module (e.g., foo-api.tf)
5082
- # after all methods and integrations are defined
5083
-
5084
- # Note: CloudWatch Log Group removed due to account-level CloudWatch Logs role ARN requirement
5540
+ # Note: Deployment, stage and access logging are created in the consuming module
5541
+ # (e.g., foo-api.tf) after all methods and integrations are defined
5085
5542
 
5086
5543
  # Gateway Response for CORS (4XX errors)
5087
5544
  resource "aws_api_gateway_gateway_response" "cors_4xx" {
@@ -5239,16 +5696,14 @@ output "waf_web_acl_arn" {
5239
5696
  value = var.enable_waf ? aws_wafv2_web_acl.api_waf[0].arn : null
5240
5697
  }
5241
5698
 
5242
- # Note: Stage and deployment outputs are provided by the consuming module
5243
-
5244
- # Note: CloudWatch log group outputs removed due to account-level CloudWatch Logs role ARN requirement",
5699
+ # Note: Stage, deployment and access log outputs are provided by the consuming module",
5245
5700
  "test-api.tf": "terraform {
5246
5701
  required_version = ">= 1.0"
5247
5702
 
5248
5703
  required_providers {
5249
5704
  aws = {
5250
5705
  source = "hashicorp/aws"
5251
- version = "~> 6.33"
5706
+ version = "6.55.0"
5252
5707
  }
5253
5708
  }
5254
5709
  }
@@ -5280,11 +5735,47 @@ variable "additional_iam_policy_statements" {
5280
5735
  default = []
5281
5736
  }
5282
5737
 
5738
+ variable "appconfig_application_id" {
5739
+ description = "ID of the shared runtime-config AppConfig application (from \`core/runtime-config/appconfig.application_id\`). When set, the Lambda functions receive \`RUNTIME_CONFIG_APP_ID\` and read access to the application."
5740
+ type = string
5741
+ default = null
5742
+ }
5743
+
5744
+ variable "appconfig_application_arn" {
5745
+ description = "ARN of the shared runtime-config AppConfig application (from \`core/runtime-config/appconfig.application_arn\`). Used to scope the IAM read permission granted to the Lambda functions."
5746
+ type = string
5747
+ default = null
5748
+ }
5749
+
5283
5750
  variable "asset_bucket_name" {
5284
5751
  description = "Name of the shared asset S3 bucket used to stage the Lambda deployment zip. Instantiate the \`core/asset-bucket\` module once per deployment and pass its \`bucket_name\` output here."
5285
5752
  type = string
5286
5753
  }
5287
5754
 
5755
+ # VPC Configuration (optional)
5756
+ variable "enable_vpc" {
5757
+ description = "Deploy the Lambda function into a VPC. Set alongside vpc_id/subnet_ids."
5758
+ type = bool
5759
+ default = false
5760
+ }
5761
+
5762
+ variable "vpc_id" {
5763
+ description = "VPC ID to deploy the Lambda function into. Required when enable_vpc is true."
5764
+ type = string
5765
+ default = null
5766
+
5767
+ validation {
5768
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
5769
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
5770
+ }
5771
+ }
5772
+
5773
+ variable "subnet_ids" {
5774
+ description = "Subnet IDs to deploy the Lambda function into. Required when enable_vpc is true."
5775
+ type = list(string)
5776
+ default = null
5777
+ }
5778
+
5288
5779
  # CORS Configuration (passed to core module)
5289
5780
 
5290
5781
  variable "cors_allow_headers" {
@@ -5347,6 +5838,11 @@ resource "aws_s3_object" "lambda_zip" {
5347
5838
  }
5348
5839
 
5349
5840
  # Use the core REST API module
5841
+ # Account-level CloudWatch role required for REST API access logging
5842
+ module "account" {
5843
+ source = "../../../core/api/api-gateway-account"
5844
+ }
5845
+
5350
5846
  module "rest_api" {
5351
5847
  source = "../../../core/api/rest-api"
5352
5848
 
@@ -5376,9 +5872,31 @@ resource "aws_wafv2_web_acl_association" "api_waf_association" {
5376
5872
  depends_on = [aws_api_gateway_stage.api_stage]
5377
5873
  }
5378
5874
 
5875
+ # Security group for the API Lambda function, used when deployed into a VPC
5876
+ resource "aws_security_group" "api_lambda" {
5877
+ count = var.enable_vpc ? 1 : 0
5878
+
5879
+ #checkov:skip=CKV2_AWS_5:Attached to api_lambda via vpc_config block; Checkov cannot resolve this reference
5880
+ name_prefix = "test-api-lambda-"
5881
+ description = "Security group for the TestApi API Lambda function"
5882
+ vpc_id = var.vpc_id
5883
+ tags = var.tags
5884
+ }
5885
+
5886
+ resource "aws_vpc_security_group_egress_rule" "api_lambda_https" {
5887
+ count = var.enable_vpc ? 1 : 0
5888
+
5889
+ security_group_id = aws_security_group.api_lambda[0].id
5890
+ cidr_ipv4 = "0.0.0.0/0"
5891
+ from_port = 443
5892
+ to_port = 443
5893
+ ip_protocol = "tcp"
5894
+ description = "Allow outbound HTTPS to AWS service endpoints"
5895
+ }
5896
+
5379
5897
  # Lambda function
5380
5898
  resource "aws_lambda_function" "api_lambda" {
5381
- #checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
5899
+ #checkov:skip=CKV_AWS_117:Lambda function is optionally deployed into a VPC via vpc_id/subnet_ids; not required for this use case
5382
5900
  #checkov:skip=CKV_AWS_116:Dead Letter Queue not required for this simple API use case
5383
5901
  #checkov:skip=CKV_AWS_272:Code signing not required for this use case
5384
5902
  #checkov:skip=CKV_AWS_115:Concurrent execution limit not required for this use case
@@ -5400,13 +5918,25 @@ resource "aws_lambda_function" "api_lambda" {
5400
5918
  mode = "Active"
5401
5919
  }
5402
5920
 
5921
+ dynamic "vpc_config" {
5922
+ for_each = var.enable_vpc ? [1] : []
5923
+ content {
5924
+ subnet_ids = var.subnet_ids
5925
+ security_group_ids = [aws_security_group.api_lambda[0].id]
5926
+ }
5927
+ }
5928
+
5403
5929
 
5404
5930
  environment {
5405
5931
  variables = merge({
5406
- }, var.env)
5932
+ }, var.appconfig_application_id != null ? {
5933
+ RUNTIME_CONFIG_APP_ID = var.appconfig_application_id
5934
+ } : {}, var.env)
5407
5935
  }
5408
5936
 
5409
5937
  tags = var.tags
5938
+
5939
+ depends_on = [aws_iam_role_policy_attachment.lambda_vpc_access]
5410
5940
  }
5411
5941
 
5412
5942
  # IAM role for Lambda execution
@@ -5441,18 +5971,39 @@ resource "aws_iam_role_policy_attachment" "lambda_xray_execution" {
5441
5971
  role = aws_iam_role.lambda_execution_role.name
5442
5972
  }
5443
5973
 
5974
+ # Attach VPC access policy to Lambda role when deployed into a VPC
5975
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
5976
+ count = var.enable_vpc ? 1 : 0
5977
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
5978
+ role = aws_iam_role.lambda_execution_role.name
5979
+ }
5980
+
5444
5981
  # Additional IAM policies for Lambda (if provided)
5445
5982
  resource "aws_iam_role_policy" "lambda_additional_policies" {
5446
- count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
5983
+ count = length(local.lambda_policy_statements) > 0 ? 1 : 0
5447
5984
  name = "TestApiHandler-additional-policies-\${random_string.suffix.result}"
5448
5985
  role = aws_iam_role.lambda_execution_role.id
5449
5986
 
5450
5987
  policy = jsonencode({
5451
5988
  Version = "2012-10-17"
5452
- Statement = var.additional_iam_policy_statements
5989
+ Statement = local.lambda_policy_statements
5453
5990
  })
5454
5991
  }
5455
5992
 
5993
+ locals {
5994
+ # Grant read access to the runtime-config AppConfig application when wired
5995
+ lambda_policy_statements = concat(var.appconfig_application_arn != null ? [
5996
+ {
5997
+ Effect = "Allow"
5998
+ Action = [
5999
+ "appconfig:StartConfigurationSession",
6000
+ "appconfig:GetLatestConfiguration"
6001
+ ]
6002
+ Resource = ["\${var.appconfig_application_arn}/*"]
6003
+ }
6004
+ ] : [], var.additional_iam_policy_statements)
6005
+ }
6006
+
5456
6007
  # CloudWatch Log Group for Lambda
5457
6008
  resource "aws_cloudwatch_log_group" "lambda_logs" {
5458
6009
  #checkov:skip=CKV_AWS_158:Using default CloudWatch log encryption
@@ -5502,6 +6053,9 @@ resource "aws_api_gateway_method" "proxy_method" {
5502
6053
 
5503
6054
  authorization = "COGNITO_USER_POOLS"
5504
6055
  authorizer_id = aws_api_gateway_authorizer.cognito_authorizer.id
6056
+ # Accept access tokens from both sign-in flows: 'openid' (Cognito hosted UI)
6057
+ # and 'aws.cognito.signin.user.admin' (Cognito admin/SRP auth APIs).
6058
+ authorization_scopes = ["openid", "aws.cognito.signin.user.admin"]
5505
6059
 
5506
6060
  request_parameters = {
5507
6061
  "method.request.path.proxy" = true
@@ -5588,11 +6142,63 @@ resource "aws_api_gateway_deployment" "api_deployment" {
5588
6142
  ]
5589
6143
  }
5590
6144
 
6145
+ # KMS key for encrypting access logs at rest
6146
+ resource "aws_kms_key" "access_logs" {
6147
+ description = "TestApi API access log encryption"
6148
+ deletion_window_in_days = 7
6149
+ enable_key_rotation = true
6150
+
6151
+ policy = jsonencode({
6152
+ Version = "2012-10-17"
6153
+ Statement = [
6154
+ {
6155
+ Sid = "Enable IAM User Permissions"
6156
+ Effect = "Allow"
6157
+ Principal = { AWS = "arn:aws:iam::\${data.aws_caller_identity.current.account_id}:root" }
6158
+ Action = "kms:*"
6159
+ Resource = "*"
6160
+ },
6161
+ {
6162
+ Sid = "Allow CloudWatch Logs"
6163
+ Effect = "Allow"
6164
+ Principal = { Service = "logs.\${data.aws_region.current.region}.amazonaws.com" }
6165
+ Action = [
6166
+ "kms:Encrypt",
6167
+ "kms:Decrypt",
6168
+ "kms:ReEncrypt*",
6169
+ "kms:GenerateDataKey*",
6170
+ "kms:DescribeKey"
6171
+ ]
6172
+ Resource = "*"
6173
+ Condition = {
6174
+ ArnEquals = {
6175
+ "kms:EncryptionContext:aws:logs:arn" = "arn:aws:logs:\${data.aws_region.current.region}:\${data.aws_caller_identity.current.account_id}:log-group:/aws/apigateway/test-api-\${random_string.suffix.result}/access"
6176
+ }
6177
+ }
6178
+ }
6179
+ ]
6180
+ })
6181
+
6182
+ tags = var.tags
6183
+ }
6184
+
6185
+ resource "aws_kms_alias" "access_logs" {
6186
+ name = "alias/test-api-\${random_string.suffix.result}-access-logs"
6187
+ target_key_id = aws_kms_key.access_logs.key_id
6188
+ }
6189
+
6190
+ # Access logs for the API Gateway stage
6191
+ resource "aws_cloudwatch_log_group" "access_logs" {
6192
+ name = "/aws/apigateway/test-api-\${random_string.suffix.result}/access"
6193
+ retention_in_days = 365
6194
+ kms_key_id = aws_kms_key.access_logs.arn
6195
+ tags = var.tags
6196
+ }
6197
+
5591
6198
  # API Gateway stage
5592
6199
  resource "aws_api_gateway_stage" "api_stage" {
5593
6200
  #checkov:skip=CKV_AWS_120:API Gateway caching not required for this use case
5594
- #checkov:skip=CKV_AWS_76:API Gateway access logging disabled due to account-level CloudWatch Logs role ARN requirement
5595
- #checkov:skip=CKV2_AWS_4:API Gateway logging level not applicable as access logging is disabled
6201
+ #checkov:skip=CKV2_AWS_4:Access logging is enabled below; verbose execution logging is intentionally not enabled
5596
6202
  #checkov:skip=CKV2_AWS_51:Client certificate authentication not required for this use case
5597
6203
  #checkov:skip=CKV2_AWS_77:WAFv2 Web ACL is attached via aws_wafv2_web_acl_association when var.enable_waf is true (default) and includes AWSManagedRulesKnownBadInputsRuleSet for Log4j protection; Checkov does not track the association across modules
5598
6204
  deployment_id = aws_api_gateway_deployment.api_deployment.id
@@ -5600,9 +6206,39 @@ resource "aws_api_gateway_stage" "api_stage" {
5600
6206
  stage_name = "prod"
5601
6207
  xray_tracing_enabled = true
5602
6208
 
6209
+ access_log_settings {
6210
+ destination_arn = aws_cloudwatch_log_group.access_logs.arn
6211
+ format = jsonencode({
6212
+ requestId = "$context.requestId"
6213
+ ip = "$context.identity.sourceIp"
6214
+ caller = "$context.identity.caller"
6215
+ user = "$context.identity.user"
6216
+ requestTime = "$context.requestTime"
6217
+ httpMethod = "$context.httpMethod"
6218
+ resourcePath = "$context.resourcePath"
6219
+ status = "$context.status"
6220
+ protocol = "$context.protocol"
6221
+ responseLength = "$context.responseLength"
6222
+ })
6223
+ }
6224
+
5603
6225
  tags = var.tags
5604
6226
 
5605
- depends_on = [aws_api_gateway_deployment.api_deployment]
6227
+ # Ensure the account-level role is configured before the stage is created
6228
+ depends_on = [aws_api_gateway_deployment.api_deployment, module.account]
6229
+ }
6230
+
6231
+ # Default throttling applied to all resource paths and methods
6232
+ resource "aws_api_gateway_method_settings" "throttling" {
6233
+ #checkov:skip=CKV_AWS_225:API Gateway caching not required for this use case
6234
+ rest_api_id = module.rest_api.api_id
6235
+ stage_name = aws_api_gateway_stage.api_stage.stage_name
6236
+ method_path = "*/*"
6237
+
6238
+ settings {
6239
+ throttling_rate_limit = 10000
6240
+ throttling_burst_limit = 5000
6241
+ }
5606
6242
  }
5607
6243
 
5608
6244
  # API Gateway Resource Policy
@@ -5741,6 +6377,11 @@ output "lambda_execution_role_name" {
5741
6377
  value = aws_iam_role.lambda_execution_role.name
5742
6378
  }
5743
6379
 
6380
+ output "security_group_id" {
6381
+ description = "Security group ID of the API Lambda function, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
6382
+ value = var.enable_vpc ? aws_security_group.api_lambda[0].id : null
6383
+ }
6384
+
5744
6385
  # Integration Outputs
5745
6386
  output "integration_id" {
5746
6387
  description = "ID of the Lambda integration"
@@ -5782,11 +6423,11 @@ terraform {
5782
6423
  required_providers {
5783
6424
  aws = {
5784
6425
  source = "hashicorp/aws"
5785
- version = "~> 6.33"
6426
+ version = "6.55.0"
5786
6427
  }
5787
6428
  random = {
5788
6429
  source = "hashicorp/random"
5789
- version = "~> 3.1"
6430
+ version = "3.9.0"
5790
6431
  }
5791
6432
  }
5792
6433
  }
@@ -5856,8 +6497,6 @@ data "aws_caller_identity" "current" {}
5856
6497
 
5857
6498
  # Resources
5858
6499
 
5859
- # Note: CloudWatch logging removed due to account-level CloudWatch Logs role ARN requirement
5860
-
5861
6500
  # REST API Gateway
5862
6501
  resource "aws_api_gateway_rest_api" "rest_api" {
5863
6502
  name = var.api_name
@@ -5874,10 +6513,8 @@ resource "aws_api_gateway_rest_api" "rest_api" {
5874
6513
  tags = var.tags
5875
6514
  }
5876
6515
 
5877
- # Note: Deployment and stage are created in the consuming module (e.g., foo-api.tf)
5878
- # after all methods and integrations are defined
5879
-
5880
- # Note: CloudWatch Log Group removed due to account-level CloudWatch Logs role ARN requirement
6516
+ # Note: Deployment, stage and access logging are created in the consuming module
6517
+ # (e.g., foo-api.tf) after all methods and integrations are defined
5881
6518
 
5882
6519
  # Gateway Response for CORS (4XX errors)
5883
6520
  resource "aws_api_gateway_gateway_response" "cors_4xx" {
@@ -6035,16 +6672,14 @@ output "waf_web_acl_arn" {
6035
6672
  value = var.enable_waf ? aws_wafv2_web_acl.api_waf[0].arn : null
6036
6673
  }
6037
6674
 
6038
- # Note: Stage and deployment outputs are provided by the consuming module
6039
-
6040
- # Note: CloudWatch log group outputs removed due to account-level CloudWatch Logs role ARN requirement",
6675
+ # Note: Stage, deployment and access log outputs are provided by the consuming module",
6041
6676
  "test-api.tf": "terraform {
6042
6677
  required_version = ">= 1.0"
6043
6678
 
6044
6679
  required_providers {
6045
6680
  aws = {
6046
6681
  source = "hashicorp/aws"
6047
- version = "~> 6.33"
6682
+ version = "6.55.0"
6048
6683
  }
6049
6684
  }
6050
6685
  }
@@ -6066,11 +6701,47 @@ variable "additional_iam_policy_statements" {
6066
6701
  default = []
6067
6702
  }
6068
6703
 
6704
+ variable "appconfig_application_id" {
6705
+ description = "ID of the shared runtime-config AppConfig application (from \`core/runtime-config/appconfig.application_id\`). When set, the Lambda functions receive \`RUNTIME_CONFIG_APP_ID\` and read access to the application."
6706
+ type = string
6707
+ default = null
6708
+ }
6709
+
6710
+ variable "appconfig_application_arn" {
6711
+ description = "ARN of the shared runtime-config AppConfig application (from \`core/runtime-config/appconfig.application_arn\`). Used to scope the IAM read permission granted to the Lambda functions."
6712
+ type = string
6713
+ default = null
6714
+ }
6715
+
6069
6716
  variable "asset_bucket_name" {
6070
6717
  description = "Name of the shared asset S3 bucket used to stage the Lambda deployment zip. Instantiate the \`core/asset-bucket\` module once per deployment and pass its \`bucket_name\` output here."
6071
6718
  type = string
6072
6719
  }
6073
6720
 
6721
+ # VPC Configuration (optional)
6722
+ variable "enable_vpc" {
6723
+ description = "Deploy the Lambda function into a VPC. Set alongside vpc_id/subnet_ids."
6724
+ type = bool
6725
+ default = false
6726
+ }
6727
+
6728
+ variable "vpc_id" {
6729
+ description = "VPC ID to deploy the Lambda function into. Required when enable_vpc is true."
6730
+ type = string
6731
+ default = null
6732
+
6733
+ validation {
6734
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
6735
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
6736
+ }
6737
+ }
6738
+
6739
+ variable "subnet_ids" {
6740
+ description = "Subnet IDs to deploy the Lambda function into. Required when enable_vpc is true."
6741
+ type = list(string)
6742
+ default = null
6743
+ }
6744
+
6074
6745
  # CORS Configuration (passed to core module)
6075
6746
 
6076
6747
  variable "cors_allow_headers" {
@@ -6133,6 +6804,11 @@ resource "aws_s3_object" "lambda_zip" {
6133
6804
  }
6134
6805
 
6135
6806
  # Use the core REST API module
6807
+ # Account-level CloudWatch role required for REST API access logging
6808
+ module "account" {
6809
+ source = "../../../core/api/api-gateway-account"
6810
+ }
6811
+
6136
6812
  module "rest_api" {
6137
6813
  source = "../../../core/api/rest-api"
6138
6814
 
@@ -6162,9 +6838,31 @@ resource "aws_wafv2_web_acl_association" "api_waf_association" {
6162
6838
  depends_on = [aws_api_gateway_stage.api_stage]
6163
6839
  }
6164
6840
 
6841
+ # Security group for the API Lambda function, used when deployed into a VPC
6842
+ resource "aws_security_group" "api_lambda" {
6843
+ count = var.enable_vpc ? 1 : 0
6844
+
6845
+ #checkov:skip=CKV2_AWS_5:Attached to api_lambda via vpc_config block; Checkov cannot resolve this reference
6846
+ name_prefix = "test-api-lambda-"
6847
+ description = "Security group for the TestApi API Lambda function"
6848
+ vpc_id = var.vpc_id
6849
+ tags = var.tags
6850
+ }
6851
+
6852
+ resource "aws_vpc_security_group_egress_rule" "api_lambda_https" {
6853
+ count = var.enable_vpc ? 1 : 0
6854
+
6855
+ security_group_id = aws_security_group.api_lambda[0].id
6856
+ cidr_ipv4 = "0.0.0.0/0"
6857
+ from_port = 443
6858
+ to_port = 443
6859
+ ip_protocol = "tcp"
6860
+ description = "Allow outbound HTTPS to AWS service endpoints"
6861
+ }
6862
+
6165
6863
  # Lambda function
6166
6864
  resource "aws_lambda_function" "api_lambda" {
6167
- #checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
6865
+ #checkov:skip=CKV_AWS_117:Lambda function is optionally deployed into a VPC via vpc_id/subnet_ids; not required for this use case
6168
6866
  #checkov:skip=CKV_AWS_116:Dead Letter Queue not required for this simple API use case
6169
6867
  #checkov:skip=CKV_AWS_272:Code signing not required for this use case
6170
6868
  #checkov:skip=CKV_AWS_115:Concurrent execution limit not required for this use case
@@ -6186,13 +6884,25 @@ resource "aws_lambda_function" "api_lambda" {
6186
6884
  mode = "Active"
6187
6885
  }
6188
6886
 
6887
+ dynamic "vpc_config" {
6888
+ for_each = var.enable_vpc ? [1] : []
6889
+ content {
6890
+ subnet_ids = var.subnet_ids
6891
+ security_group_ids = [aws_security_group.api_lambda[0].id]
6892
+ }
6893
+ }
6894
+
6189
6895
 
6190
6896
  environment {
6191
6897
  variables = merge({
6192
- }, var.env)
6898
+ }, var.appconfig_application_id != null ? {
6899
+ RUNTIME_CONFIG_APP_ID = var.appconfig_application_id
6900
+ } : {}, var.env)
6193
6901
  }
6194
6902
 
6195
6903
  tags = var.tags
6904
+
6905
+ depends_on = [aws_iam_role_policy_attachment.lambda_vpc_access]
6196
6906
  }
6197
6907
 
6198
6908
  # IAM role for Lambda execution
@@ -6227,18 +6937,39 @@ resource "aws_iam_role_policy_attachment" "lambda_xray_execution" {
6227
6937
  role = aws_iam_role.lambda_execution_role.name
6228
6938
  }
6229
6939
 
6940
+ # Attach VPC access policy to Lambda role when deployed into a VPC
6941
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
6942
+ count = var.enable_vpc ? 1 : 0
6943
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
6944
+ role = aws_iam_role.lambda_execution_role.name
6945
+ }
6946
+
6230
6947
  # Additional IAM policies for Lambda (if provided)
6231
6948
  resource "aws_iam_role_policy" "lambda_additional_policies" {
6232
- count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
6949
+ count = length(local.lambda_policy_statements) > 0 ? 1 : 0
6233
6950
  name = "TestApiHandler-additional-policies-\${random_string.suffix.result}"
6234
6951
  role = aws_iam_role.lambda_execution_role.id
6235
6952
 
6236
6953
  policy = jsonencode({
6237
6954
  Version = "2012-10-17"
6238
- Statement = var.additional_iam_policy_statements
6955
+ Statement = local.lambda_policy_statements
6239
6956
  })
6240
6957
  }
6241
6958
 
6959
+ locals {
6960
+ # Grant read access to the runtime-config AppConfig application when wired
6961
+ lambda_policy_statements = concat(var.appconfig_application_arn != null ? [
6962
+ {
6963
+ Effect = "Allow"
6964
+ Action = [
6965
+ "appconfig:StartConfigurationSession",
6966
+ "appconfig:GetLatestConfiguration"
6967
+ ]
6968
+ Resource = ["\${var.appconfig_application_arn}/*"]
6969
+ }
6970
+ ] : [], var.additional_iam_policy_statements)
6971
+ }
6972
+
6242
6973
  # CloudWatch Log Group for Lambda
6243
6974
  resource "aws_cloudwatch_log_group" "lambda_logs" {
6244
6975
  #checkov:skip=CKV_AWS_158:Using default CloudWatch log encryption
@@ -6365,11 +7096,63 @@ resource "aws_api_gateway_deployment" "api_deployment" {
6365
7096
  ]
6366
7097
  }
6367
7098
 
7099
+ # KMS key for encrypting access logs at rest
7100
+ resource "aws_kms_key" "access_logs" {
7101
+ description = "TestApi API access log encryption"
7102
+ deletion_window_in_days = 7
7103
+ enable_key_rotation = true
7104
+
7105
+ policy = jsonencode({
7106
+ Version = "2012-10-17"
7107
+ Statement = [
7108
+ {
7109
+ Sid = "Enable IAM User Permissions"
7110
+ Effect = "Allow"
7111
+ Principal = { AWS = "arn:aws:iam::\${data.aws_caller_identity.current.account_id}:root" }
7112
+ Action = "kms:*"
7113
+ Resource = "*"
7114
+ },
7115
+ {
7116
+ Sid = "Allow CloudWatch Logs"
7117
+ Effect = "Allow"
7118
+ Principal = { Service = "logs.\${data.aws_region.current.region}.amazonaws.com" }
7119
+ Action = [
7120
+ "kms:Encrypt",
7121
+ "kms:Decrypt",
7122
+ "kms:ReEncrypt*",
7123
+ "kms:GenerateDataKey*",
7124
+ "kms:DescribeKey"
7125
+ ]
7126
+ Resource = "*"
7127
+ Condition = {
7128
+ ArnEquals = {
7129
+ "kms:EncryptionContext:aws:logs:arn" = "arn:aws:logs:\${data.aws_region.current.region}:\${data.aws_caller_identity.current.account_id}:log-group:/aws/apigateway/test-api-\${random_string.suffix.result}/access"
7130
+ }
7131
+ }
7132
+ }
7133
+ ]
7134
+ })
7135
+
7136
+ tags = var.tags
7137
+ }
7138
+
7139
+ resource "aws_kms_alias" "access_logs" {
7140
+ name = "alias/test-api-\${random_string.suffix.result}-access-logs"
7141
+ target_key_id = aws_kms_key.access_logs.key_id
7142
+ }
7143
+
7144
+ # Access logs for the API Gateway stage
7145
+ resource "aws_cloudwatch_log_group" "access_logs" {
7146
+ name = "/aws/apigateway/test-api-\${random_string.suffix.result}/access"
7147
+ retention_in_days = 365
7148
+ kms_key_id = aws_kms_key.access_logs.arn
7149
+ tags = var.tags
7150
+ }
7151
+
6368
7152
  # API Gateway stage
6369
7153
  resource "aws_api_gateway_stage" "api_stage" {
6370
7154
  #checkov:skip=CKV_AWS_120:API Gateway caching not required for this use case
6371
- #checkov:skip=CKV_AWS_76:API Gateway access logging disabled due to account-level CloudWatch Logs role ARN requirement
6372
- #checkov:skip=CKV2_AWS_4:API Gateway logging level not applicable as access logging is disabled
7155
+ #checkov:skip=CKV2_AWS_4:Access logging is enabled below; verbose execution logging is intentionally not enabled
6373
7156
  #checkov:skip=CKV2_AWS_51:Client certificate authentication not required for this use case
6374
7157
  #checkov:skip=CKV2_AWS_77:WAFv2 Web ACL is attached via aws_wafv2_web_acl_association when var.enable_waf is true (default) and includes AWSManagedRulesKnownBadInputsRuleSet for Log4j protection; Checkov does not track the association across modules
6375
7158
  deployment_id = aws_api_gateway_deployment.api_deployment.id
@@ -6377,9 +7160,39 @@ resource "aws_api_gateway_stage" "api_stage" {
6377
7160
  stage_name = "prod"
6378
7161
  xray_tracing_enabled = true
6379
7162
 
7163
+ access_log_settings {
7164
+ destination_arn = aws_cloudwatch_log_group.access_logs.arn
7165
+ format = jsonencode({
7166
+ requestId = "$context.requestId"
7167
+ ip = "$context.identity.sourceIp"
7168
+ caller = "$context.identity.caller"
7169
+ user = "$context.identity.user"
7170
+ requestTime = "$context.requestTime"
7171
+ httpMethod = "$context.httpMethod"
7172
+ resourcePath = "$context.resourcePath"
7173
+ status = "$context.status"
7174
+ protocol = "$context.protocol"
7175
+ responseLength = "$context.responseLength"
7176
+ })
7177
+ }
7178
+
6380
7179
  tags = var.tags
6381
7180
 
6382
- depends_on = [aws_api_gateway_deployment.api_deployment]
7181
+ # Ensure the account-level role is configured before the stage is created
7182
+ depends_on = [aws_api_gateway_deployment.api_deployment, module.account]
7183
+ }
7184
+
7185
+ # Default throttling applied to all resource paths and methods
7186
+ resource "aws_api_gateway_method_settings" "throttling" {
7187
+ #checkov:skip=CKV_AWS_225:API Gateway caching not required for this use case
7188
+ rest_api_id = module.rest_api.api_id
7189
+ stage_name = aws_api_gateway_stage.api_stage.stage_name
7190
+ method_path = "*/*"
7191
+
7192
+ settings {
7193
+ throttling_rate_limit = 10000
7194
+ throttling_burst_limit = 5000
7195
+ }
6383
7196
  }
6384
7197
 
6385
7198
  # API Gateway Resource Policy
@@ -6529,6 +7342,11 @@ output "lambda_execution_role_name" {
6529
7342
  value = aws_iam_role.lambda_execution_role.name
6530
7343
  }
6531
7344
 
7345
+ output "security_group_id" {
7346
+ description = "Security group ID of the API Lambda function, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
7347
+ value = var.enable_vpc ? aws_security_group.api_lambda[0].id : null
7348
+ }
7349
+
6532
7350
  # Integration Outputs
6533
7351
  output "integration_id" {
6534
7352
  description = "ID of the Lambda integration"
@@ -6570,11 +7388,11 @@ terraform {
6570
7388
  required_providers {
6571
7389
  aws = {
6572
7390
  source = "hashicorp/aws"
6573
- version = "~> 6.33"
7391
+ version = "6.55.0"
6574
7392
  }
6575
7393
  random = {
6576
7394
  source = "hashicorp/random"
6577
- version = "~> 3.1"
7395
+ version = "3.9.0"
6578
7396
  }
6579
7397
  }
6580
7398
  }
@@ -6644,8 +7462,6 @@ data "aws_caller_identity" "current" {}
6644
7462
 
6645
7463
  # Resources
6646
7464
 
6647
- # Note: CloudWatch logging removed due to account-level CloudWatch Logs role ARN requirement
6648
-
6649
7465
  # REST API Gateway
6650
7466
  resource "aws_api_gateway_rest_api" "rest_api" {
6651
7467
  name = var.api_name
@@ -6662,10 +7478,8 @@ resource "aws_api_gateway_rest_api" "rest_api" {
6662
7478
  tags = var.tags
6663
7479
  }
6664
7480
 
6665
- # Note: Deployment and stage are created in the consuming module (e.g., foo-api.tf)
6666
- # after all methods and integrations are defined
6667
-
6668
- # Note: CloudWatch Log Group removed due to account-level CloudWatch Logs role ARN requirement
7481
+ # Note: Deployment, stage and access logging are created in the consuming module
7482
+ # (e.g., foo-api.tf) after all methods and integrations are defined
6669
7483
 
6670
7484
  # Gateway Response for CORS (4XX errors)
6671
7485
  resource "aws_api_gateway_gateway_response" "cors_4xx" {
@@ -6823,16 +7637,14 @@ output "waf_web_acl_arn" {
6823
7637
  value = var.enable_waf ? aws_wafv2_web_acl.api_waf[0].arn : null
6824
7638
  }
6825
7639
 
6826
- # Note: Stage and deployment outputs are provided by the consuming module
6827
-
6828
- # Note: CloudWatch log group outputs removed due to account-level CloudWatch Logs role ARN requirement",
7640
+ # Note: Stage, deployment and access log outputs are provided by the consuming module",
6829
7641
  "test-api.tf": "terraform {
6830
7642
  required_version = ">= 1.0"
6831
7643
 
6832
7644
  required_providers {
6833
7645
  aws = {
6834
7646
  source = "hashicorp/aws"
6835
- version = "~> 6.33"
7647
+ version = "6.55.0"
6836
7648
  }
6837
7649
  }
6838
7650
  }
@@ -6854,11 +7666,47 @@ variable "additional_iam_policy_statements" {
6854
7666
  default = []
6855
7667
  }
6856
7668
 
7669
+ variable "appconfig_application_id" {
7670
+ description = "ID of the shared runtime-config AppConfig application (from \`core/runtime-config/appconfig.application_id\`). When set, the Lambda functions receive \`RUNTIME_CONFIG_APP_ID\` and read access to the application."
7671
+ type = string
7672
+ default = null
7673
+ }
7674
+
7675
+ variable "appconfig_application_arn" {
7676
+ description = "ARN of the shared runtime-config AppConfig application (from \`core/runtime-config/appconfig.application_arn\`). Used to scope the IAM read permission granted to the Lambda functions."
7677
+ type = string
7678
+ default = null
7679
+ }
7680
+
6857
7681
  variable "asset_bucket_name" {
6858
7682
  description = "Name of the shared asset S3 bucket used to stage the Lambda deployment zip. Instantiate the \`core/asset-bucket\` module once per deployment and pass its \`bucket_name\` output here."
6859
7683
  type = string
6860
7684
  }
6861
7685
 
7686
+ # VPC Configuration (optional)
7687
+ variable "enable_vpc" {
7688
+ description = "Deploy the Lambda function into a VPC. Set alongside vpc_id/subnet_ids."
7689
+ type = bool
7690
+ default = false
7691
+ }
7692
+
7693
+ variable "vpc_id" {
7694
+ description = "VPC ID to deploy the Lambda function into. Required when enable_vpc is true."
7695
+ type = string
7696
+ default = null
7697
+
7698
+ validation {
7699
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
7700
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
7701
+ }
7702
+ }
7703
+
7704
+ variable "subnet_ids" {
7705
+ description = "Subnet IDs to deploy the Lambda function into. Required when enable_vpc is true."
7706
+ type = list(string)
7707
+ default = null
7708
+ }
7709
+
6862
7710
  # CORS Configuration (passed to core module)
6863
7711
 
6864
7712
  variable "cors_allow_headers" {
@@ -6921,6 +7769,11 @@ resource "aws_s3_object" "lambda_zip" {
6921
7769
  }
6922
7770
 
6923
7771
  # Use the core REST API module
7772
+ # Account-level CloudWatch role required for REST API access logging
7773
+ module "account" {
7774
+ source = "../../../core/api/api-gateway-account"
7775
+ }
7776
+
6924
7777
  module "rest_api" {
6925
7778
  source = "../../../core/api/rest-api"
6926
7779
 
@@ -6950,9 +7803,31 @@ resource "aws_wafv2_web_acl_association" "api_waf_association" {
6950
7803
  depends_on = [aws_api_gateway_stage.api_stage]
6951
7804
  }
6952
7805
 
7806
+ # Security group for the API Lambda function, used when deployed into a VPC
7807
+ resource "aws_security_group" "api_lambda" {
7808
+ count = var.enable_vpc ? 1 : 0
7809
+
7810
+ #checkov:skip=CKV2_AWS_5:Attached to api_lambda via vpc_config block; Checkov cannot resolve this reference
7811
+ name_prefix = "test-api-lambda-"
7812
+ description = "Security group for the TestApi API Lambda function"
7813
+ vpc_id = var.vpc_id
7814
+ tags = var.tags
7815
+ }
7816
+
7817
+ resource "aws_vpc_security_group_egress_rule" "api_lambda_https" {
7818
+ count = var.enable_vpc ? 1 : 0
7819
+
7820
+ security_group_id = aws_security_group.api_lambda[0].id
7821
+ cidr_ipv4 = "0.0.0.0/0"
7822
+ from_port = 443
7823
+ to_port = 443
7824
+ ip_protocol = "tcp"
7825
+ description = "Allow outbound HTTPS to AWS service endpoints"
7826
+ }
7827
+
6953
7828
  # Lambda function
6954
7829
  resource "aws_lambda_function" "api_lambda" {
6955
- #checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
7830
+ #checkov:skip=CKV_AWS_117:Lambda function is optionally deployed into a VPC via vpc_id/subnet_ids; not required for this use case
6956
7831
  #checkov:skip=CKV_AWS_116:Dead Letter Queue not required for this simple API use case
6957
7832
  #checkov:skip=CKV_AWS_272:Code signing not required for this use case
6958
7833
  #checkov:skip=CKV_AWS_115:Concurrent execution limit not required for this use case
@@ -6974,13 +7849,25 @@ resource "aws_lambda_function" "api_lambda" {
6974
7849
  mode = "Active"
6975
7850
  }
6976
7851
 
7852
+ dynamic "vpc_config" {
7853
+ for_each = var.enable_vpc ? [1] : []
7854
+ content {
7855
+ subnet_ids = var.subnet_ids
7856
+ security_group_ids = [aws_security_group.api_lambda[0].id]
7857
+ }
7858
+ }
7859
+
6977
7860
 
6978
7861
  environment {
6979
7862
  variables = merge({
6980
- }, var.env)
7863
+ }, var.appconfig_application_id != null ? {
7864
+ RUNTIME_CONFIG_APP_ID = var.appconfig_application_id
7865
+ } : {}, var.env)
6981
7866
  }
6982
7867
 
6983
7868
  tags = var.tags
7869
+
7870
+ depends_on = [aws_iam_role_policy_attachment.lambda_vpc_access]
6984
7871
  }
6985
7872
 
6986
7873
  # IAM role for Lambda execution
@@ -7015,18 +7902,39 @@ resource "aws_iam_role_policy_attachment" "lambda_xray_execution" {
7015
7902
  role = aws_iam_role.lambda_execution_role.name
7016
7903
  }
7017
7904
 
7905
+ # Attach VPC access policy to Lambda role when deployed into a VPC
7906
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
7907
+ count = var.enable_vpc ? 1 : 0
7908
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
7909
+ role = aws_iam_role.lambda_execution_role.name
7910
+ }
7911
+
7018
7912
  # Additional IAM policies for Lambda (if provided)
7019
7913
  resource "aws_iam_role_policy" "lambda_additional_policies" {
7020
- count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
7914
+ count = length(local.lambda_policy_statements) > 0 ? 1 : 0
7021
7915
  name = "TestApiHandler-additional-policies-\${random_string.suffix.result}"
7022
7916
  role = aws_iam_role.lambda_execution_role.id
7023
7917
 
7024
7918
  policy = jsonencode({
7025
7919
  Version = "2012-10-17"
7026
- Statement = var.additional_iam_policy_statements
7920
+ Statement = local.lambda_policy_statements
7027
7921
  })
7028
7922
  }
7029
7923
 
7924
+ locals {
7925
+ # Grant read access to the runtime-config AppConfig application when wired
7926
+ lambda_policy_statements = concat(var.appconfig_application_arn != null ? [
7927
+ {
7928
+ Effect = "Allow"
7929
+ Action = [
7930
+ "appconfig:StartConfigurationSession",
7931
+ "appconfig:GetLatestConfiguration"
7932
+ ]
7933
+ Resource = ["\${var.appconfig_application_arn}/*"]
7934
+ }
7935
+ ] : [], var.additional_iam_policy_statements)
7936
+ }
7937
+
7030
7938
  # CloudWatch Log Group for Lambda
7031
7939
  resource "aws_cloudwatch_log_group" "lambda_logs" {
7032
7940
  #checkov:skip=CKV_AWS_158:Using default CloudWatch log encryption
@@ -7247,11 +8155,63 @@ resource "aws_api_gateway_deployment" "api_deployment" {
7247
8155
  ]
7248
8156
  }
7249
8157
 
8158
+ # KMS key for encrypting access logs at rest
8159
+ resource "aws_kms_key" "access_logs" {
8160
+ description = "TestApi API access log encryption"
8161
+ deletion_window_in_days = 7
8162
+ enable_key_rotation = true
8163
+
8164
+ policy = jsonencode({
8165
+ Version = "2012-10-17"
8166
+ Statement = [
8167
+ {
8168
+ Sid = "Enable IAM User Permissions"
8169
+ Effect = "Allow"
8170
+ Principal = { AWS = "arn:aws:iam::\${data.aws_caller_identity.current.account_id}:root" }
8171
+ Action = "kms:*"
8172
+ Resource = "*"
8173
+ },
8174
+ {
8175
+ Sid = "Allow CloudWatch Logs"
8176
+ Effect = "Allow"
8177
+ Principal = { Service = "logs.\${data.aws_region.current.region}.amazonaws.com" }
8178
+ Action = [
8179
+ "kms:Encrypt",
8180
+ "kms:Decrypt",
8181
+ "kms:ReEncrypt*",
8182
+ "kms:GenerateDataKey*",
8183
+ "kms:DescribeKey"
8184
+ ]
8185
+ Resource = "*"
8186
+ Condition = {
8187
+ ArnEquals = {
8188
+ "kms:EncryptionContext:aws:logs:arn" = "arn:aws:logs:\${data.aws_region.current.region}:\${data.aws_caller_identity.current.account_id}:log-group:/aws/apigateway/test-api-\${random_string.suffix.result}/access"
8189
+ }
8190
+ }
8191
+ }
8192
+ ]
8193
+ })
8194
+
8195
+ tags = var.tags
8196
+ }
8197
+
8198
+ resource "aws_kms_alias" "access_logs" {
8199
+ name = "alias/test-api-\${random_string.suffix.result}-access-logs"
8200
+ target_key_id = aws_kms_key.access_logs.key_id
8201
+ }
8202
+
8203
+ # Access logs for the API Gateway stage
8204
+ resource "aws_cloudwatch_log_group" "access_logs" {
8205
+ name = "/aws/apigateway/test-api-\${random_string.suffix.result}/access"
8206
+ retention_in_days = 365
8207
+ kms_key_id = aws_kms_key.access_logs.arn
8208
+ tags = var.tags
8209
+ }
8210
+
7250
8211
  # API Gateway stage
7251
8212
  resource "aws_api_gateway_stage" "api_stage" {
7252
8213
  #checkov:skip=CKV_AWS_120:API Gateway caching not required for this use case
7253
- #checkov:skip=CKV_AWS_76:API Gateway access logging disabled due to account-level CloudWatch Logs role ARN requirement
7254
- #checkov:skip=CKV2_AWS_4:API Gateway logging level not applicable as access logging is disabled
8214
+ #checkov:skip=CKV2_AWS_4:Access logging is enabled below; verbose execution logging is intentionally not enabled
7255
8215
  #checkov:skip=CKV2_AWS_51:Client certificate authentication not required for this use case
7256
8216
  #checkov:skip=CKV2_AWS_77:WAFv2 Web ACL is attached via aws_wafv2_web_acl_association when var.enable_waf is true (default) and includes AWSManagedRulesKnownBadInputsRuleSet for Log4j protection; Checkov does not track the association across modules
7257
8217
  deployment_id = aws_api_gateway_deployment.api_deployment.id
@@ -7259,9 +8219,39 @@ resource "aws_api_gateway_stage" "api_stage" {
7259
8219
  stage_name = "prod"
7260
8220
  xray_tracing_enabled = true
7261
8221
 
8222
+ access_log_settings {
8223
+ destination_arn = aws_cloudwatch_log_group.access_logs.arn
8224
+ format = jsonencode({
8225
+ requestId = "$context.requestId"
8226
+ ip = "$context.identity.sourceIp"
8227
+ caller = "$context.identity.caller"
8228
+ user = "$context.identity.user"
8229
+ requestTime = "$context.requestTime"
8230
+ httpMethod = "$context.httpMethod"
8231
+ resourcePath = "$context.resourcePath"
8232
+ status = "$context.status"
8233
+ protocol = "$context.protocol"
8234
+ responseLength = "$context.responseLength"
8235
+ })
8236
+ }
8237
+
7262
8238
  tags = var.tags
7263
8239
 
7264
- depends_on = [aws_api_gateway_deployment.api_deployment]
8240
+ # Ensure the account-level role is configured before the stage is created
8241
+ depends_on = [aws_api_gateway_deployment.api_deployment, module.account]
8242
+ }
8243
+
8244
+ # Default throttling applied to all resource paths and methods
8245
+ resource "aws_api_gateway_method_settings" "throttling" {
8246
+ #checkov:skip=CKV_AWS_225:API Gateway caching not required for this use case
8247
+ rest_api_id = module.rest_api.api_id
8248
+ stage_name = aws_api_gateway_stage.api_stage.stage_name
8249
+ method_path = "*/*"
8250
+
8251
+ settings {
8252
+ throttling_rate_limit = 10000
8253
+ throttling_burst_limit = 5000
8254
+ }
7265
8255
  }
7266
8256
 
7267
8257
  # API Gateway Resource Policy
@@ -7400,6 +8390,11 @@ output "lambda_execution_role_name" {
7400
8390
  value = aws_iam_role.lambda_execution_role.name
7401
8391
  }
7402
8392
 
8393
+ output "security_group_id" {
8394
+ description = "Security group ID of the API Lambda function, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
8395
+ value = var.enable_vpc ? aws_security_group.api_lambda[0].id : null
8396
+ }
8397
+
7403
8398
  # Integration Outputs
7404
8399
  output "integration_id" {
7405
8400
  description = "ID of the Lambda integration"