@friggframework/devtools 2.0.0-next.1 → 2.0.0-next.100

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 (235) hide show
  1. package/frigg-cli/README.md +1289 -0
  2. package/frigg-cli/__tests__/unit/commands/build.test.js +279 -0
  3. package/frigg-cli/__tests__/unit/commands/db-setup.test.js +649 -0
  4. package/frigg-cli/__tests__/unit/commands/deploy.test.js +320 -0
  5. package/frigg-cli/__tests__/unit/commands/doctor.test.js +309 -0
  6. package/frigg-cli/__tests__/unit/commands/install.test.js +400 -0
  7. package/frigg-cli/__tests__/unit/commands/ui.test.js +346 -0
  8. package/frigg-cli/__tests__/unit/dependencies.test.js +74 -0
  9. package/frigg-cli/__tests__/unit/utils/database-validator.test.js +397 -0
  10. package/frigg-cli/__tests__/unit/utils/error-messages.test.js +345 -0
  11. package/frigg-cli/__tests__/unit/version-detection.test.js +171 -0
  12. package/frigg-cli/__tests__/utils/mock-factory.js +270 -0
  13. package/frigg-cli/__tests__/utils/prisma-mock.js +194 -0
  14. package/frigg-cli/__tests__/utils/test-fixtures.js +463 -0
  15. package/frigg-cli/__tests__/utils/test-setup.js +287 -0
  16. package/frigg-cli/auth-command/CLAUDE.md +293 -0
  17. package/frigg-cli/auth-command/README.md +450 -0
  18. package/frigg-cli/auth-command/api-key-flow.js +153 -0
  19. package/frigg-cli/auth-command/auth-tester.js +344 -0
  20. package/frigg-cli/auth-command/credential-storage.js +182 -0
  21. package/frigg-cli/auth-command/index.js +256 -0
  22. package/frigg-cli/auth-command/json-schema-form.js +67 -0
  23. package/frigg-cli/auth-command/module-loader.js +172 -0
  24. package/frigg-cli/auth-command/oauth-callback-server.js +431 -0
  25. package/frigg-cli/auth-command/oauth-flow.js +195 -0
  26. package/frigg-cli/auth-command/utils/browser.js +30 -0
  27. package/frigg-cli/build-command/index.js +66 -0
  28. package/frigg-cli/db-setup-command/index.js +246 -0
  29. package/frigg-cli/deploy-command/SPEC-DEPLOY-DRY-RUN.md +981 -0
  30. package/frigg-cli/deploy-command/index.js +305 -0
  31. package/frigg-cli/doctor-command/index.js +335 -0
  32. package/frigg-cli/generate-command/__tests__/generate-command.test.js +301 -0
  33. package/frigg-cli/generate-command/azure-generator.js +43 -0
  34. package/frigg-cli/generate-command/gcp-generator.js +47 -0
  35. package/frigg-cli/generate-command/index.js +332 -0
  36. package/frigg-cli/generate-command/terraform-generator.js +555 -0
  37. package/frigg-cli/generate-iam-command.js +118 -0
  38. package/frigg-cli/index.js +189 -1
  39. package/frigg-cli/index.test.js +1 -4
  40. package/frigg-cli/init-command/backend-first-handler.js +756 -0
  41. package/frigg-cli/init-command/index.js +93 -0
  42. package/frigg-cli/init-command/template-handler.js +143 -0
  43. package/frigg-cli/install-command/index.js +1 -4
  44. package/frigg-cli/jest.config.js +124 -0
  45. package/frigg-cli/package.json +63 -0
  46. package/frigg-cli/repair-command/index.js +564 -0
  47. package/frigg-cli/start-command/index.js +125 -6
  48. package/frigg-cli/start-command/start-command.test.js +297 -0
  49. package/frigg-cli/test/init-command.test.js +180 -0
  50. package/frigg-cli/test/npm-registry.test.js +319 -0
  51. package/frigg-cli/ui-command/index.js +154 -0
  52. package/frigg-cli/utils/app-resolver.js +319 -0
  53. package/frigg-cli/utils/backend-path.js +16 -17
  54. package/frigg-cli/utils/database-validator.js +167 -0
  55. package/frigg-cli/utils/error-messages.js +329 -0
  56. package/frigg-cli/utils/npm-registry.js +167 -0
  57. package/frigg-cli/utils/process-manager.js +199 -0
  58. package/frigg-cli/utils/repo-detection.js +405 -0
  59. package/index.js +4 -2
  60. package/infrastructure/ARCHITECTURE.md +487 -0
  61. package/infrastructure/CLAUDE.md +481 -0
  62. package/infrastructure/HEALTH.md +468 -0
  63. package/infrastructure/README.md +522 -0
  64. package/infrastructure/__tests__/fixtures/mock-aws-resources.js +391 -0
  65. package/infrastructure/__tests__/helpers/test-utils.js +277 -0
  66. package/infrastructure/__tests__/postgres-config.test.js +914 -0
  67. package/infrastructure/__tests__/template-generation.test.js +687 -0
  68. package/infrastructure/create-frigg-infrastructure.js +147 -0
  69. package/infrastructure/docs/POSTGRES-CONFIGURATION.md +630 -0
  70. package/infrastructure/docs/PRE-DEPLOYMENT-HEALTH-CHECK-SPEC.md +1317 -0
  71. package/infrastructure/docs/WEBSOCKET-CONFIGURATION.md +105 -0
  72. package/infrastructure/docs/deployment-instructions.md +268 -0
  73. package/infrastructure/docs/generate-iam-command.md +278 -0
  74. package/infrastructure/docs/iam-policy-templates.md +193 -0
  75. package/infrastructure/domains/admin-scripts/admin-script-builder.js +330 -0
  76. package/infrastructure/domains/admin-scripts/admin-script-builder.test.js +628 -0
  77. package/infrastructure/domains/admin-scripts/index.js +5 -0
  78. package/infrastructure/domains/database/aurora-builder.js +857 -0
  79. package/infrastructure/domains/database/aurora-builder.test.js +960 -0
  80. package/infrastructure/domains/database/aurora-discovery.js +87 -0
  81. package/infrastructure/domains/database/aurora-discovery.test.js +188 -0
  82. package/infrastructure/domains/database/aurora-resolver.js +210 -0
  83. package/infrastructure/domains/database/aurora-resolver.test.js +347 -0
  84. package/infrastructure/domains/database/migration-builder.js +715 -0
  85. package/infrastructure/domains/database/migration-builder.test.js +322 -0
  86. package/infrastructure/domains/database/migration-resolver.js +163 -0
  87. package/infrastructure/domains/database/migration-resolver.test.js +337 -0
  88. package/infrastructure/domains/health/application/ports/IPropertyReconciler.js +164 -0
  89. package/infrastructure/domains/health/application/ports/IResourceDetector.js +129 -0
  90. package/infrastructure/domains/health/application/ports/IResourceImporter.js +142 -0
  91. package/infrastructure/domains/health/application/ports/IStackRepository.js +131 -0
  92. package/infrastructure/domains/health/application/ports/index.js +26 -0
  93. package/infrastructure/domains/health/application/use-cases/__tests__/execute-resource-import-use-case.test.js +679 -0
  94. package/infrastructure/domains/health/application/use-cases/__tests__/mismatch-analyzer-method-name.test.js +167 -0
  95. package/infrastructure/domains/health/application/use-cases/__tests__/repair-via-import-use-case.test.js +1130 -0
  96. package/infrastructure/domains/health/application/use-cases/execute-resource-import-use-case.js +221 -0
  97. package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.js +152 -0
  98. package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.test.js +343 -0
  99. package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.js +535 -0
  100. package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.test.js +376 -0
  101. package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.js +213 -0
  102. package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.test.js +441 -0
  103. package/infrastructure/domains/health/docs/ACME-DEV-DRIFT-ANALYSIS.md +267 -0
  104. package/infrastructure/domains/health/docs/BUILD-VS-DEPLOYED-TEMPLATE-ANALYSIS.md +324 -0
  105. package/infrastructure/domains/health/docs/ORPHAN-DETECTION-ANALYSIS.md +386 -0
  106. package/infrastructure/domains/health/docs/SPEC-CLEANUP-COMMAND.md +1419 -0
  107. package/infrastructure/domains/health/docs/TDD-IMPLEMENTATION-SUMMARY.md +391 -0
  108. package/infrastructure/domains/health/docs/TEMPLATE-COMPARISON-IMPLEMENTATION.md +551 -0
  109. package/infrastructure/domains/health/domain/entities/issue.js +299 -0
  110. package/infrastructure/domains/health/domain/entities/issue.test.js +528 -0
  111. package/infrastructure/domains/health/domain/entities/property-mismatch.js +108 -0
  112. package/infrastructure/domains/health/domain/entities/property-mismatch.test.js +275 -0
  113. package/infrastructure/domains/health/domain/entities/resource.js +159 -0
  114. package/infrastructure/domains/health/domain/entities/resource.test.js +432 -0
  115. package/infrastructure/domains/health/domain/entities/stack-health-report.js +306 -0
  116. package/infrastructure/domains/health/domain/entities/stack-health-report.test.js +601 -0
  117. package/infrastructure/domains/health/domain/services/__tests__/health-score-percentage-based.test.js +380 -0
  118. package/infrastructure/domains/health/domain/services/__tests__/import-progress-monitor.test.js +971 -0
  119. package/infrastructure/domains/health/domain/services/__tests__/import-template-generator.test.js +1150 -0
  120. package/infrastructure/domains/health/domain/services/__tests__/logical-id-mapper.test.js +672 -0
  121. package/infrastructure/domains/health/domain/services/__tests__/template-parser.test.js +496 -0
  122. package/infrastructure/domains/health/domain/services/__tests__/update-progress-monitor.test.js +419 -0
  123. package/infrastructure/domains/health/domain/services/health-score-calculator.js +248 -0
  124. package/infrastructure/domains/health/domain/services/health-score-calculator.test.js +504 -0
  125. package/infrastructure/domains/health/domain/services/import-progress-monitor.js +195 -0
  126. package/infrastructure/domains/health/domain/services/import-template-generator.js +435 -0
  127. package/infrastructure/domains/health/domain/services/logical-id-mapper.js +345 -0
  128. package/infrastructure/domains/health/domain/services/mismatch-analyzer.js +234 -0
  129. package/infrastructure/domains/health/domain/services/mismatch-analyzer.test.js +431 -0
  130. package/infrastructure/domains/health/domain/services/property-mutability-config.js +382 -0
  131. package/infrastructure/domains/health/domain/services/template-parser.js +245 -0
  132. package/infrastructure/domains/health/domain/services/update-progress-monitor.js +192 -0
  133. package/infrastructure/domains/health/domain/value-objects/health-score.js +138 -0
  134. package/infrastructure/domains/health/domain/value-objects/health-score.test.js +267 -0
  135. package/infrastructure/domains/health/domain/value-objects/property-mutability.js +161 -0
  136. package/infrastructure/domains/health/domain/value-objects/property-mutability.test.js +198 -0
  137. package/infrastructure/domains/health/domain/value-objects/resource-state.js +167 -0
  138. package/infrastructure/domains/health/domain/value-objects/resource-state.test.js +196 -0
  139. package/infrastructure/domains/health/domain/value-objects/stack-identifier.js +192 -0
  140. package/infrastructure/domains/health/domain/value-objects/stack-identifier.test.js +262 -0
  141. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-cfn-tagged.test.js +312 -0
  142. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-multi-stack.test.js +367 -0
  143. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-relationship-analysis.test.js +432 -0
  144. package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.js +784 -0
  145. package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.test.js +1133 -0
  146. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.js +565 -0
  147. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.test.js +554 -0
  148. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.js +318 -0
  149. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.test.js +398 -0
  150. package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.js +777 -0
  151. package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.test.js +580 -0
  152. package/infrastructure/domains/integration/integration-builder.js +596 -0
  153. package/infrastructure/domains/integration/integration-builder.test.js +939 -0
  154. package/infrastructure/domains/integration/integration-resolver.js +170 -0
  155. package/infrastructure/domains/integration/integration-resolver.test.js +369 -0
  156. package/infrastructure/domains/integration/websocket-builder.js +69 -0
  157. package/infrastructure/domains/integration/websocket-builder.test.js +195 -0
  158. package/infrastructure/domains/networking/vpc-builder.js +2051 -0
  159. package/infrastructure/domains/networking/vpc-builder.test.js +1960 -0
  160. package/infrastructure/domains/networking/vpc-discovery.js +177 -0
  161. package/infrastructure/domains/networking/vpc-discovery.test.js +350 -0
  162. package/infrastructure/domains/networking/vpc-resolver.js +505 -0
  163. package/infrastructure/domains/networking/vpc-resolver.test.js +801 -0
  164. package/infrastructure/domains/parameters/ssm-builder.js +79 -0
  165. package/infrastructure/domains/parameters/ssm-builder.test.js +189 -0
  166. package/infrastructure/domains/parameters/ssm-discovery.js +84 -0
  167. package/infrastructure/domains/parameters/ssm-discovery.test.js +210 -0
  168. package/infrastructure/domains/scheduler/scheduler-builder.js +211 -0
  169. package/infrastructure/domains/security/iam-generator.js +816 -0
  170. package/infrastructure/domains/security/iam-generator.test.js +204 -0
  171. package/infrastructure/domains/security/kms-builder.js +415 -0
  172. package/infrastructure/domains/security/kms-builder.test.js +392 -0
  173. package/infrastructure/domains/security/kms-discovery.js +80 -0
  174. package/infrastructure/domains/security/kms-discovery.test.js +177 -0
  175. package/infrastructure/domains/security/kms-resolver.js +96 -0
  176. package/infrastructure/domains/security/kms-resolver.test.js +216 -0
  177. package/infrastructure/domains/security/templates/frigg-deployment-iam-stack.yaml +401 -0
  178. package/infrastructure/domains/security/templates/iam-policy-basic.json +218 -0
  179. package/infrastructure/domains/security/templates/iam-policy-full.json +288 -0
  180. package/infrastructure/domains/shared/base-builder.js +112 -0
  181. package/infrastructure/domains/shared/base-resolver.js +186 -0
  182. package/infrastructure/domains/shared/base-resolver.test.js +305 -0
  183. package/infrastructure/domains/shared/builder-orchestrator.js +212 -0
  184. package/infrastructure/domains/shared/builder-orchestrator.test.js +213 -0
  185. package/infrastructure/domains/shared/cloudformation-discovery-v2.js +334 -0
  186. package/infrastructure/domains/shared/cloudformation-discovery.js +681 -0
  187. package/infrastructure/domains/shared/cloudformation-discovery.test.js +1320 -0
  188. package/infrastructure/domains/shared/environment-builder.js +119 -0
  189. package/infrastructure/domains/shared/environment-builder.test.js +247 -0
  190. package/infrastructure/domains/shared/providers/aws-provider-adapter.js +579 -0
  191. package/infrastructure/domains/shared/providers/aws-provider-adapter.test.js +416 -0
  192. package/infrastructure/domains/shared/providers/azure-provider-adapter.stub.js +93 -0
  193. package/infrastructure/domains/shared/providers/cloud-provider-adapter.js +136 -0
  194. package/infrastructure/domains/shared/providers/gcp-provider-adapter.stub.js +82 -0
  195. package/infrastructure/domains/shared/providers/provider-factory.js +108 -0
  196. package/infrastructure/domains/shared/providers/provider-factory.test.js +170 -0
  197. package/infrastructure/domains/shared/resource-discovery.enhanced.test.js +306 -0
  198. package/infrastructure/domains/shared/resource-discovery.js +256 -0
  199. package/infrastructure/domains/shared/resource-discovery.test.js +757 -0
  200. package/infrastructure/domains/shared/types/app-definition.js +225 -0
  201. package/infrastructure/domains/shared/types/discovery-result.js +106 -0
  202. package/infrastructure/domains/shared/types/discovery-result.test.js +258 -0
  203. package/infrastructure/domains/shared/types/index.js +46 -0
  204. package/infrastructure/domains/shared/types/resource-ownership.js +108 -0
  205. package/infrastructure/domains/shared/types/resource-ownership.test.js +101 -0
  206. package/infrastructure/domains/shared/utilities/base-definition-factory.js +418 -0
  207. package/infrastructure/domains/shared/utilities/base-definition-factory.js.bak +338 -0
  208. package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +291 -0
  209. package/infrastructure/domains/shared/utilities/handler-path-resolver.js +134 -0
  210. package/infrastructure/domains/shared/utilities/handler-path-resolver.test.js +268 -0
  211. package/infrastructure/domains/shared/utilities/prisma-layer-manager.js +159 -0
  212. package/infrastructure/domains/shared/utilities/prisma-layer-manager.test.js +444 -0
  213. package/infrastructure/domains/shared/validation/env-validator.js +78 -0
  214. package/infrastructure/domains/shared/validation/env-validator.test.js +173 -0
  215. package/infrastructure/domains/shared/validation/plugin-validator.js +187 -0
  216. package/infrastructure/domains/shared/validation/plugin-validator.test.js +323 -0
  217. package/infrastructure/esbuild.config.js +53 -0
  218. package/infrastructure/index.js +4 -0
  219. package/infrastructure/infrastructure-composer.js +121 -0
  220. package/infrastructure/infrastructure-composer.test.js +1896 -0
  221. package/infrastructure/integration.test.js +383 -0
  222. package/infrastructure/scripts/build-prisma-layer.js +701 -0
  223. package/infrastructure/scripts/build-prisma-layer.test.js +170 -0
  224. package/infrastructure/scripts/build-time-discovery.js +238 -0
  225. package/infrastructure/scripts/build-time-discovery.test.js +379 -0
  226. package/infrastructure/scripts/run-discovery.js +110 -0
  227. package/infrastructure/scripts/verify-prisma-layer.js +72 -0
  228. package/management-ui/README.md +203 -0
  229. package/package.json +53 -11
  230. package/test/index.js +2 -4
  231. package/test/mock-api.js +1 -3
  232. package/test/mock-integration.js +4 -14
  233. package/.eslintrc.json +0 -3
  234. package/CHANGELOG.md +0 -132
  235. package/test/auther-definition-tester.js +0 -125
@@ -0,0 +1,193 @@
1
+ # Frigg IAM Policy Templates
2
+
3
+ This directory contains IAM policy templates for deploying Frigg applications with the appropriate permissions.
4
+
5
+ ## Quick Start
6
+
7
+ For immediate deployment, you have two ready-to-use IAM policy options:
8
+
9
+ ### Option 1: Basic Policy (Recommended for getting started)
10
+ ```bash
11
+ # Use the basic policy for core Frigg functionality
12
+ aws iam put-user-policy \
13
+ --user-name frigg-deployment-user \
14
+ --policy-name FriggBasicDeploymentPolicy \
15
+ --policy-document file://domains/security/templates/iam-policy-basic.json
16
+ ```
17
+
18
+ **Includes permissions for:**
19
+ - ✅ AWS Discovery (finding your VPC, subnets, security groups)
20
+ - ✅ CloudFormation stacks (deploy/update Frigg applications)
21
+ - ✅ Lambda functions (create and manage serverless functions)
22
+ - ✅ Lambda EventSourceMappings (connect Lambda to SQS, SNS, Kinesis)
23
+ - ✅ API Gateway (HTTP endpoints for your integrations)
24
+ - ✅ SQS/SNS (message queues and notifications)
25
+ - ✅ S3 (deployment artifacts, including bucket tagging)
26
+ - ✅ CloudWatch/Logs (monitoring and logging)
27
+ - ✅ IAM roles (Lambda execution roles)
28
+
29
+ ### Option 2: Full Policy (All features enabled)
30
+ ```bash
31
+ # Use the full policy for advanced Frigg features
32
+ aws iam put-user-policy \
33
+ --user-name frigg-deployment-user \
34
+ --policy-name FriggFullDeploymentPolicy \
35
+ --policy-document file://domains/security/templates/iam-policy-full.json
36
+ ```
37
+
38
+ **Includes everything from Basic Policy PLUS:**
39
+ - ✅ **VPC Management** - Create route tables, NAT gateways, VPC endpoints
40
+ - ✅ **KMS Encryption** - Field-level encryption for sensitive data
41
+ - ✅ **SSM Parameter Store** - Secure configuration management
42
+
43
+ ## When to Use Which Policy
44
+
45
+ ### Use Basic Policy When:
46
+ - Getting started with Frigg
47
+ - Building simple integrations without VPC requirements
48
+ - You want minimal AWS permissions
49
+ - You're not handling sensitive data requiring encryption
50
+
51
+ ### Use Full Policy When:
52
+ - You need VPC isolation for security/compliance
53
+ - You're handling sensitive data requiring KMS encryption
54
+ - You want to use SSM Parameter Store for configuration
55
+ - You're deploying production applications
56
+
57
+ ## Current Issue Resolution
58
+
59
+ **If you're seeing the error:** `User is not authorized to perform: ec2:CreateRouteTable`
60
+
61
+ This means your current deployment user doesn't have VPC permissions. You have two options:
62
+
63
+ ### Quick Fix: Apply Full Policy
64
+ ```bash
65
+ aws iam put-user-policy \
66
+ --user-name frigg-deployment-user \
67
+ --policy-name FriggFullDeploymentPolicy \
68
+ --policy-document file://domains/security/templates/iam-policy-full.json
69
+ ```
70
+
71
+ ### Alternative: Update CloudFormation Stack
72
+ If you deployed using the CloudFormation template, update it with VPC support:
73
+ ```bash
74
+ aws cloudformation update-stack \
75
+ --stack-name frigg-deployment-iam \
76
+ --template-body file://domains/security/templates/frigg-deployment-iam-stack.yaml \
77
+ --parameters ParameterKey=EnableVPCSupport,ParameterValue=true \
78
+ --capabilities CAPABILITY_IAM
79
+ ```
80
+
81
+ ## Using the IAM Generator
82
+
83
+ For custom policy generation based on your app definition:
84
+
85
+ ```javascript
86
+ const { generateIAMPolicy, generateIAMCloudFormation, getFeatureSummary } = require('./iam-generator');
87
+
88
+ // Generate basic JSON policy
89
+ const basicPolicy = generateIAMPolicy('basic');
90
+
91
+ // Generate full JSON policy
92
+ const fullPolicy = generateIAMPolicy('full');
93
+
94
+ // Generate CloudFormation template with auto-detected features
95
+ const summary = getFeatureSummary(appDefinition);
96
+ const template = generateIAMCloudFormation({
97
+ appName: summary.appName,
98
+ features: summary.features,
99
+ userPrefix: 'frigg-deployment-user',
100
+ stackName: 'frigg-deployment-iam'
101
+ });
102
+
103
+ // Or manually specify features
104
+ const customTemplate = generateIAMCloudFormation({
105
+ appName: 'my-app',
106
+ features: {
107
+ vpc: true,
108
+ kms: true,
109
+ ssm: true,
110
+ websockets: false
111
+ },
112
+ userPrefix: 'my-deployment-user',
113
+ stackName: 'my-deployment-stack'
114
+ });
115
+ ```
116
+
117
+ ### Feature Detection
118
+
119
+ Use `getFeatureSummary(appDefinition)` to automatically detect features from your app definition:
120
+
121
+ ```javascript
122
+ const summary = getFeatureSummary(appDefinition);
123
+ // Returns: { appName, features: { core, vpc, kms, ssm, websockets }, integrationCount }
124
+ ```
125
+
126
+ ## Security Best Practices
127
+
128
+ ### Resource Scoping
129
+ Both policies are scoped to resources containing "frigg" in their names:
130
+ - ✅ `my-frigg-app-prod` (will work)
131
+ - ❌ `my-integration-app` (won't work - missing "frigg")
132
+
133
+ ### Account-Specific Resources
134
+ Replace `*` with your AWS account ID for tighter security:
135
+ ```json
136
+ {
137
+ "Resource": [
138
+ "arn:aws:lambda:us-east-1:123456789012:function:*frigg*"
139
+ ]
140
+ }
141
+ ```
142
+
143
+ ### Environment-Specific Policies
144
+ Consider separate policies for different environments:
145
+ - `frigg-dev-policy` (full permissions for development)
146
+ - `frigg-prod-policy` (restricted permissions for production)
147
+
148
+ ## Troubleshooting
149
+
150
+ ### Common Permission Errors
151
+
152
+ 1. **"ec2:CreateRouteTable" error** → Use Full Policy
153
+ 2. **"kms:GenerateDataKey" error** → Enable KMS in your policy
154
+ 3. **"ssm:GetParameter" error** → Enable SSM in your policy
155
+ 4. **Lambda VPC errors** → Ensure VPC permissions are enabled
156
+ 5. **"lambda:DeleteEventSourceMapping" error** → Update to latest policy (includes EventSourceMapping permissions)
157
+ 6. **"ec2:DeleteVpcEndpoints" error** → Update IAM policy to use `ec2:DeleteVpcEndpoints` (plural) instead of `ec2:DeleteVpcEndpoint`
158
+ 7. **"s3:PutBucketTagging" error** → Update to latest policy (includes S3 bucket tagging permissions)
159
+
160
+ ### Validation
161
+ Test your policy by deploying a simple Frigg app:
162
+ ```bash
163
+ npx create-frigg-app test-deployment
164
+ cd test-deployment
165
+ frigg deploy
166
+ ```
167
+
168
+ ### Policy Comparison
169
+
170
+ | Feature | Basic Policy | Full Policy | CloudFormation Template |
171
+ |---------|--------------|-------------|-------------------------|
172
+ | Core Deployment | ✅ | ✅ | ✅ |
173
+ | VPC Management | ❌ | ✅ | ✅ (conditional) |
174
+ | KMS Encryption | ❌ | ✅ | ✅ (conditional) |
175
+ | SSM Parameters | ❌ | ✅ | ✅ (conditional) |
176
+ | Format | JSON | JSON | YAML with parameters |
177
+ | Use Case | Getting started | Production ready | Infrastructure as Code |
178
+
179
+ ## Files in this Directory
180
+
181
+ - `../domains/security/templates/iam-policy-basic.json` - Core Frigg permissions only (JSON format)
182
+ - `../domains/security/templates/iam-policy-full.json` - All features enabled (JSON format)
183
+ - `../domains/security/templates/frigg-deployment-iam-stack.yaml` - CloudFormation template with conditional parameters
184
+ - `../domains/security/iam-generator.js` - Programmatic policy generation with basic/full/auto modes
185
+ - This file (`iam-policy-templates.md`) - Quick start guide and usage examples
186
+
187
+ ## Support
188
+
189
+ If you encounter permission issues:
190
+ 1. Check the error message for the specific missing permission
191
+ 2. Verify your resource names contain "frigg"
192
+ 3. Consider upgrading from Basic to Full policy
193
+ 4. Review the AWS-IAM-CREDENTIAL-NEEDS.md for detailed explanations
@@ -0,0 +1,330 @@
1
+ /**
2
+ * Admin Script Builder
3
+ *
4
+ * Domain Layer - Hexagonal Architecture
5
+ *
6
+ * Responsible for:
7
+ * - Creating SQS queue for admin script execution
8
+ * - Creating Lambda function for script execution (worker)
9
+ * - Creating Lambda function for admin API routes (router)
10
+ * - Creating EventBridge Scheduler resources (Phase 2)
11
+ * - Creating IAM roles for scheduler to invoke Lambda
12
+ * - Granting the router/executor Lambdas IAM permission to send to the queue
13
+ * and (when scheduling is enabled) manage EventBridge schedules
14
+ */
15
+
16
+ const { InfrastructureBuilder, ValidationResult } = require('../shared/base-builder');
17
+
18
+ class AdminScriptBuilder extends InfrastructureBuilder {
19
+ constructor() {
20
+ super();
21
+ this.name = 'AdminScriptBuilder';
22
+ }
23
+
24
+ shouldExecute(appDefinition) {
25
+ return Array.isArray(appDefinition.adminScripts) && appDefinition.adminScripts.length > 0;
26
+ }
27
+
28
+ getDependencies() {
29
+ return []; // Can run independently
30
+ }
31
+
32
+ validate(appDefinition) {
33
+ const result = new ValidationResult();
34
+
35
+ if (!appDefinition.adminScripts) {
36
+ return result; // Not an error, just no scripts
37
+ }
38
+
39
+ if (!Array.isArray(appDefinition.adminScripts)) {
40
+ result.addError('adminScripts must be an array');
41
+ return result;
42
+ }
43
+
44
+ // Validate each script
45
+ appDefinition.adminScripts.forEach((script, index) => {
46
+ if (!script?.Definition?.name) {
47
+ result.addError(`Admin script at index ${index} is missing Definition or name`);
48
+ }
49
+ });
50
+
51
+ return result;
52
+ }
53
+
54
+ async build(appDefinition, discoveredResources) {
55
+ console.log(`\n[${this.name}] Configuring admin scripts...`);
56
+ console.log(` Processing ${appDefinition.adminScripts.length} scripts...`);
57
+
58
+ const usePrismaLayer = appDefinition.usePrismaLambdaLayer !== false;
59
+ const adminConfig = appDefinition.admin || {};
60
+
61
+ const result = {
62
+ functions: {},
63
+ resources: {},
64
+ environment: {},
65
+ custom: {},
66
+ iamStatements: [],
67
+ };
68
+
69
+ // Create admin script queue
70
+ this.createAdminScriptQueue(result);
71
+
72
+ // Create Lambda function for script execution
73
+ this.createScriptExecutorFunction(appDefinition, result, usePrismaLayer);
74
+
75
+ // Create API routes for script management
76
+ this.createAdminScriptRoutes(appDefinition, result, usePrismaLayer);
77
+
78
+ // Phase 2: Create EventBridge Scheduler resources
79
+ if (adminConfig.enableScheduling) {
80
+ this.createSchedulerResources(appDefinition, result);
81
+ }
82
+
83
+ // Log registered scripts
84
+ appDefinition.adminScripts.forEach(script => {
85
+ const name = script.Definition?.name || 'unknown';
86
+ console.log(` ✓ Registered: ${name}`);
87
+ });
88
+
89
+ console.log(`[${this.name}] ✅ Admin script configuration completed`);
90
+ return result;
91
+ }
92
+
93
+ createAdminScriptQueue(result) {
94
+ result.resources.AdminScriptQueue = {
95
+ Type: 'AWS::SQS::Queue',
96
+ Properties: {
97
+ QueueName: '${self:service}-${self:provider.stage}-AdminScriptQueue',
98
+ MessageRetentionPeriod: 86400, // 1 day
99
+ VisibilityTimeout: 900, // 15 minutes (Lambda max)
100
+ RedrivePolicy: {
101
+ maxReceiveCount: 3,
102
+ deadLetterTargetArn: {
103
+ 'Fn::GetAtt': ['InternalErrorQueue', 'Arn'],
104
+ },
105
+ },
106
+ },
107
+ };
108
+
109
+ result.environment.ADMIN_SCRIPT_QUEUE_URL = { Ref: 'AdminScriptQueue' };
110
+
111
+ // The router enqueues async executions and scripts enqueue continuations
112
+ // via queueScript()/queueScriptBatch(). The base role's wildcard does not
113
+ // cover this queue's name, so grant SendMessage explicitly.
114
+ result.iamStatements.push({
115
+ Effect: 'Allow',
116
+ Action: [
117
+ 'sqs:SendMessage',
118
+ 'sqs:SendMessageBatch',
119
+ 'sqs:GetQueueUrl',
120
+ 'sqs:GetQueueAttributes',
121
+ ],
122
+ Resource: { 'Fn::GetAtt': ['AdminScriptQueue', 'Arn'] },
123
+ });
124
+
125
+ console.log(' ✓ Created AdminScriptQueue');
126
+ }
127
+
128
+ createScriptExecutorFunction(appDefinition, result, usePrismaLayer) {
129
+ result.functions.adminScriptExecutor = {
130
+ handler: 'node_modules/@friggframework/admin-scripts/src/infrastructure/script-executor-handler.handler',
131
+ skipEsbuild: true,
132
+ package: this.skipEsbuildPackageConfig(appDefinition, usePrismaLayer),
133
+ ...(usePrismaLayer && { layers: [{ Ref: 'PrismaLambdaLayer' }] }),
134
+ timeout: 900, // 15 minutes max
135
+ memorySize: 1024,
136
+ events: [
137
+ {
138
+ sqs: {
139
+ arn: { 'Fn::GetAtt': ['AdminScriptQueue', 'Arn'] },
140
+ batchSize: 1,
141
+ },
142
+ },
143
+ ],
144
+ };
145
+ console.log(' ✓ Created adminScriptExecutor function');
146
+ }
147
+
148
+ createAdminScriptRoutes(appDefinition, result, usePrismaLayer) {
149
+ result.functions.adminScriptRouter = {
150
+ handler: 'node_modules/@friggframework/admin-scripts/src/infrastructure/admin-script-router.handler',
151
+ skipEsbuild: true,
152
+ package: this.skipEsbuildPackageConfig(appDefinition, usePrismaLayer),
153
+ ...(usePrismaLayer && { layers: [{ Ref: 'PrismaLambdaLayer' }] }),
154
+ timeout: 30,
155
+ events: [
156
+ // List scripts
157
+ { httpApi: { path: '/admin/scripts', method: 'GET' } },
158
+ // Get script details
159
+ { httpApi: { path: '/admin/scripts/{scriptName}', method: 'GET' } },
160
+ // Execute script (sync or async)
161
+ { httpApi: { path: '/admin/scripts/{scriptName}', method: 'POST' } },
162
+ // Validate script input (dry-run preview)
163
+ { httpApi: { path: '/admin/scripts/{scriptName}/validate', method: 'POST' } },
164
+ // List executions for a script
165
+ { httpApi: { path: '/admin/scripts/{scriptName}/executions', method: 'GET' } },
166
+ // Get a single execution
167
+ {
168
+ httpApi: {
169
+ path: '/admin/scripts/{scriptName}/executions/{executionId}',
170
+ method: 'GET',
171
+ },
172
+ },
173
+ // Schedule management (Phase 2)
174
+ { httpApi: { path: '/admin/scripts/{scriptName}/schedule', method: 'GET' } },
175
+ { httpApi: { path: '/admin/scripts/{scriptName}/schedule', method: 'PUT' } },
176
+ { httpApi: { path: '/admin/scripts/{scriptName}/schedule', method: 'DELETE' } },
177
+ ],
178
+ };
179
+ console.log(' ✓ Created adminScriptRouter function');
180
+ }
181
+
182
+ // Without this, the skipEsbuild functions package the whole node_modules
183
+ // closure (aws-sdk, Prisma, dev deps) and blow past Lambda's 250 MB limit.
184
+ // Mirrors the exclusions the framework's other node_modules handlers use.
185
+ skipEsbuildPackageConfig(appDefinition, usePrismaLayer) {
186
+ const tlsCAFile = appDefinition?.database?.documentDB?.tlsCAFile;
187
+ return {
188
+ include: [
189
+ // Handlers connect to the DB, so ship the DocumentDB CA cert.
190
+ ...(tlsCAFile ? [tlsCAFile.replace(/^\.\//, '')] : []),
191
+ ],
192
+ exclude: [
193
+ 'node_modules/aws-sdk/**',
194
+ 'node_modules/@aws-sdk/**',
195
+ ...(usePrismaLayer
196
+ ? [
197
+ 'node_modules/@prisma/**',
198
+ 'node_modules/.prisma/**',
199
+ 'node_modules/prisma/**',
200
+ 'node_modules/@friggframework/core/generated/**',
201
+ ]
202
+ : []),
203
+ 'node_modules/**/node_modules/**',
204
+ 'node_modules/@friggframework/test/**',
205
+ 'node_modules/@friggframework/eslint-config/**',
206
+ 'node_modules/@friggframework/prettier-config/**',
207
+ 'node_modules/jest/**',
208
+ 'node_modules/prettier/**',
209
+ 'node_modules/eslint/**',
210
+ 'node_modules/esbuild/**',
211
+ 'node_modules/@esbuild/**',
212
+ 'node_modules/typescript/**',
213
+ 'node_modules/webpack/**',
214
+ 'node_modules/osls/**',
215
+ 'node_modules/serverless-esbuild/**',
216
+ 'node_modules/serverless-jetpack/**',
217
+ 'node_modules/serverless-offline/**',
218
+ 'node_modules/serverless-offline-sqs/**',
219
+ 'node_modules/serverless-dotenv-plugin/**',
220
+ 'node_modules/serverless-kms-grants/**',
221
+ // Never deploy secrets or the lockfile.
222
+ '.env',
223
+ '.env.*',
224
+ '**/.env',
225
+ '**/.env.*',
226
+ '.frigg-credentials.json',
227
+ 'package-lock.json',
228
+ 'test/**',
229
+ 'layers/**',
230
+ 'coverage/**',
231
+ '**/*.test.js',
232
+ '**/*.spec.js',
233
+ ],
234
+ };
235
+ }
236
+
237
+ createSchedulerResources(appDefinition, result) {
238
+ // Constructed ARN, not Fn::GetAtt: a GetAtt edge to the executor closes a
239
+ // CloudFormation circular dependency via the shared Lambda execution role.
240
+ const executorArn = {
241
+ 'Fn::Sub':
242
+ 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${self:service}-${self:provider.stage}-adminScriptExecutor',
243
+ };
244
+
245
+ // Create IAM role for EventBridge Scheduler
246
+ result.resources.AdminScriptSchedulerRole = {
247
+ Type: 'AWS::IAM::Role',
248
+ Properties: {
249
+ RoleName: '${self:service}-${self:provider.stage}-admin-script-scheduler',
250
+ AssumeRolePolicyDocument: {
251
+ Version: '2012-10-17',
252
+ Statement: [{
253
+ Effect: 'Allow',
254
+ Principal: { Service: 'scheduler.amazonaws.com' },
255
+ Action: 'sts:AssumeRole',
256
+ }],
257
+ },
258
+ Policies: [{
259
+ PolicyName: 'InvokeLambda',
260
+ PolicyDocument: {
261
+ Version: '2012-10-17',
262
+ Statement: [{
263
+ Effect: 'Allow',
264
+ Action: 'lambda:InvokeFunction',
265
+ Resource: executorArn,
266
+ }],
267
+ },
268
+ }],
269
+ },
270
+ };
271
+
272
+ // Create schedule group
273
+ result.resources.AdminScriptScheduleGroup = {
274
+ Type: 'AWS::Scheduler::ScheduleGroup',
275
+ Properties: {
276
+ Name: '${self:service}-${self:provider.stage}-admin-scripts',
277
+ },
278
+ };
279
+
280
+ // Router-scoped, not shared provider env. Two reasons: broadcasting the
281
+ // resource references to every function creates CloudFormation circular
282
+ // deps; and SCHEDULER_PROVIDER='aws' is only valid for the admin-script
283
+ // adapter (the router's sole consumer) — core's scheduler factory, used
284
+ // by integration Lambdas, rejects 'aws', so it must not leak app-wide.
285
+ result.functions.adminScriptRouter.environment = {
286
+ ...(result.functions.adminScriptRouter.environment || {}),
287
+ SCHEDULER_PROVIDER: 'aws',
288
+ SCHEDULER_ROLE_ARN: {
289
+ 'Fn::GetAtt': ['AdminScriptSchedulerRole', 'Arn'],
290
+ },
291
+ ADMIN_SCRIPT_SCHEDULE_GROUP: { Ref: 'AdminScriptScheduleGroup' },
292
+ ADMIN_SCRIPT_EXECUTOR_LAMBDA_ARN: executorArn,
293
+ };
294
+
295
+ // The router manages schedules through the AWS scheduler adapter, so it
296
+ // needs scheduler:* on this group plus iam:PassRole for the role it hands
297
+ // to EventBridge. (UpdateSchedule covers the upsert conflict path.)
298
+ result.iamStatements.push(
299
+ {
300
+ Effect: 'Allow',
301
+ Action: [
302
+ 'scheduler:CreateSchedule',
303
+ 'scheduler:UpdateSchedule',
304
+ 'scheduler:DeleteSchedule',
305
+ 'scheduler:GetSchedule',
306
+ ],
307
+ Resource: {
308
+ 'Fn::Sub': [
309
+ 'arn:aws:scheduler:${AWS::Region}:${AWS::AccountId}:schedule/${GroupName}/*',
310
+ { GroupName: { Ref: 'AdminScriptScheduleGroup' } },
311
+ ],
312
+ },
313
+ },
314
+ {
315
+ Effect: 'Allow',
316
+ Action: ['iam:PassRole'],
317
+ Resource: { 'Fn::GetAtt': ['AdminScriptSchedulerRole', 'Arn'] },
318
+ Condition: {
319
+ StringEquals: {
320
+ 'iam:PassedToService': 'scheduler.amazonaws.com',
321
+ },
322
+ },
323
+ }
324
+ );
325
+
326
+ console.log(' ✓ Created EventBridge Scheduler resources');
327
+ }
328
+ }
329
+
330
+ module.exports = { AdminScriptBuilder };