forgedev 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/package.json +1 -1
  2. package/src/chainproof-bridge.js +9 -2
  3. package/src/ci-mode.js +3 -4
  4. package/src/composer.js +228 -242
  5. package/src/doctor-checks-chainproof.js +14 -11
  6. package/src/doctor-checks.js +3 -19
  7. package/src/index.js +6 -34
  8. package/src/recommender.js +319 -319
  9. package/src/uat-generator.js +105 -93
  10. package/src/utils.js +245 -214
  11. package/templates/auth/jwt-custom/backend/app/api/auth.py.template +39 -45
  12. package/templates/auth/jwt-custom/backend/app/core/security.py.template +44 -37
  13. package/templates/backend/express/package.json.template +35 -33
  14. package/templates/backend/express/src/lib/prisma.ts.template +32 -0
  15. package/templates/backend/express/src/routes/health.ts.template +35 -27
  16. package/templates/backend/fastapi/backend/app/main.py.template +67 -60
  17. package/templates/backend/fastapi/backend/requirements.txt.template +18 -16
  18. package/templates/backend/hono/package.json.template +33 -31
  19. package/templates/backend/hono/src/lib/prisma.ts.template +32 -0
  20. package/templates/backend/hono/src/routes/health.ts.template +38 -27
  21. package/templates/base/.gitignore.template +32 -32
  22. package/templates/claude-code/commands/workflows.md +52 -52
  23. package/templates/database/prisma-postgres/prisma/schema.prisma.template +19 -18
  24. package/templates/database/sqlalchemy-postgres/backend/alembic/env.py.template +39 -40
  25. package/templates/database/sqlalchemy-postgres/backend/alembic.ini.template +38 -36
  26. package/templates/database/sqlalchemy-postgres/backend/app/db/session.py.template +50 -48
  27. package/templates/frontend/nextjs/package.json.template +45 -43
  28. package/templates/frontend/remix/package.json.template +41 -39
  29. package/templates/infra/docker/.dockerignore.template +16 -0
  30. package/templates/infra/docker-compose/docker-compose.yml.template +22 -19
  31. package/templates/infra/github-actions/.github/workflows/ci.yml.template +61 -52
  32. package/templates/infra/k8s/k8s/deployment.yml.template +70 -70
  33. package/templates/infra/k8s/k8s/hpa.yml.template +24 -24
  34. package/templates/infra/k8s/k8s/ingress.yml.template +26 -26
  35. package/templates/infra/k8s/k8s/kustomization.yml.template +13 -13
  36. package/templates/infra/k8s/k8s/namespace.yml.template +4 -4
  37. package/templates/infra/k8s/k8s/networkpolicy.yml.template +41 -41
  38. package/templates/infra/k8s/k8s/secrets.yml.template +10 -10
  39. package/templates/infra/k8s/k8s/service.yml.template +15 -15
  40. package/templates/testing/load/k6/README.md.template +48 -48
  41. package/templates/testing/load/k6/load-test.js.template +57 -57
@@ -1,52 +1,61 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches: [main]
6
- pull_request:
7
- branches: [main]
8
-
9
- jobs:
10
- lint-and-test:
11
- runs-on: ubuntu-latest
12
-
13
- services:
14
- postgres:
15
- image: postgres:17-alpine
16
- env:
17
- POSTGRES_DB: {{PROJECT_NAME_SNAKE}}
18
- POSTGRES_USER: postgres
19
- POSTGRES_PASSWORD: postgres
20
- ports:
21
- - 5432:5432
22
- options: >-
23
- --health-cmd pg_isready
24
- --health-interval 10s
25
- --health-timeout 5s
26
- --health-retries 5
27
-
28
- steps:
29
- - uses: actions/checkout@v4
30
-
31
- - name: Setup Node.js
32
- uses: actions/setup-node@v4
33
- with:
34
- node-version: '22'
35
- cache: 'npm'
36
-
37
- - name: Install dependencies
38
- run: npm ci
39
-
40
- - name: Lint
41
- run: {{LINT_COMMAND}}
42
-
43
- - name: Type check
44
- run: {{TYPE_CHECK_COMMAND}}
45
-
46
- - name: Build
47
- run: {{BUILD_COMMAND}}
48
-
49
- - name: Test
50
- run: {{TEST_COMMAND}}
51
- env:
52
- DATABASE_URL: postgresql://postgres:postgres@localhost:5432/{{PROJECT_NAME_SNAKE}}
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint-and-test:
11
+ runs-on: ubuntu-latest
12
+
13
+ services:
14
+ postgres:
15
+ image: postgres:17-alpine
16
+ env:
17
+ POSTGRES_DB: {{PROJECT_NAME_SNAKE}}
18
+ POSTGRES_USER: postgres
19
+ POSTGRES_PASSWORD: postgres
20
+ ports:
21
+ - 5432:5432
22
+ options: >-
23
+ --health-cmd pg_isready
24
+ --health-interval 10s
25
+ --health-timeout 5s
26
+ --health-retries 5
27
+
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+
31
+ - name: Setup Node.js
32
+ uses: actions/setup-node@v4
33
+ with:
34
+ node-version: '22'
35
+ cache: 'npm'
36
+
37
+ - name: Install dependencies
38
+ run: npm ci
39
+
40
+ - name: Lint
41
+ run: {{LINT_COMMAND}}
42
+
43
+ - name: Type check
44
+ run: {{TYPE_CHECK_COMMAND}}
45
+
46
+ - name: Build
47
+ run: {{BUILD_COMMAND}}
48
+
49
+ - name: Test
50
+ run: {{TEST_COMMAND}}
51
+ env:
52
+ DATABASE_URL: postgresql://postgres:postgres@localhost:5432/{{PROJECT_NAME_SNAKE}}
53
+
54
+ - name: Security audit (npm)
55
+ run: npm audit --audit-level=high
56
+ continue-on-error: true
57
+
58
+ - name: Security audit (pip)
59
+ if: hashFiles('**/requirements.txt') != ''
60
+ run: pip install pip-audit && pip-audit -r requirements.txt
61
+ continue-on-error: true
@@ -1,70 +1,70 @@
1
- apiVersion: apps/v1
2
- kind: Deployment
3
- metadata:
4
- name: {{PROJECT_NAME}}
5
- labels:
6
- app: {{PROJECT_NAME}}
7
- spec:
8
- replicas: 2
9
- selector:
10
- matchLabels:
11
- app: {{PROJECT_NAME}}
12
- template:
13
- metadata:
14
- labels:
15
- app: {{PROJECT_NAME}}
16
- spec:
17
- automountServiceAccountToken: false
18
- securityContext:
19
- runAsNonRoot: true
20
- runAsUser: 1000
21
- fsGroup: 1000
22
- containers:
23
- - name: {{PROJECT_NAME}}
24
- image: {{PROJECT_NAME}}:{{IMAGE_TAG}} # Update to match your CI-built image tag
25
- imagePullPolicy: IfNotPresent
26
- ports:
27
- - containerPort: {{APP_PORT}}
28
- env:
29
- - name: PORT
30
- value: "{{APP_PORT}}"
31
- - name: DATABASE_URL
32
- valueFrom:
33
- secretKeyRef:
34
- name: {{PROJECT_NAME}}-secrets
35
- key: database-url
36
- securityContext:
37
- allowPrivilegeEscalation: false
38
- readOnlyRootFilesystem: true
39
- capabilities:
40
- drop: ["ALL"]
41
- volumeMounts:
42
- - name: tmp
43
- mountPath: /tmp
44
- livenessProbe:
45
- httpGet:
46
- path: /health
47
- port: {{APP_PORT}}
48
- initialDelaySeconds: 10
49
- periodSeconds: 15
50
- timeoutSeconds: 5
51
- failureThreshold: 3
52
- readinessProbe:
53
- httpGet:
54
- path: /healthz
55
- port: {{APP_PORT}}
56
- initialDelaySeconds: 5
57
- periodSeconds: 10
58
- timeoutSeconds: 5
59
- failureThreshold: 3
60
- resources:
61
- requests:
62
- cpu: 100m
63
- memory: 128Mi
64
- limits:
65
- cpu: 500m
66
- memory: 512Mi
67
- volumes:
68
- - name: tmp
69
- emptyDir: {}
70
- terminationGracePeriodSeconds: 30
1
+ apiVersion: apps/v1
2
+ kind: Deployment
3
+ metadata:
4
+ name: {{PROJECT_NAME}}
5
+ labels:
6
+ app: {{PROJECT_NAME}}
7
+ spec:
8
+ replicas: 2
9
+ selector:
10
+ matchLabels:
11
+ app: {{PROJECT_NAME}}
12
+ template:
13
+ metadata:
14
+ labels:
15
+ app: {{PROJECT_NAME}}
16
+ spec:
17
+ automountServiceAccountToken: false
18
+ securityContext:
19
+ runAsNonRoot: true
20
+ runAsUser: 1000
21
+ fsGroup: 1000
22
+ containers:
23
+ - name: {{PROJECT_NAME}}
24
+ image: {{PROJECT_NAME}}:{{IMAGE_TAG}} # Update to match your CI-built image tag
25
+ imagePullPolicy: IfNotPresent
26
+ ports:
27
+ - containerPort: {{APP_PORT}}
28
+ env:
29
+ - name: PORT
30
+ value: "{{APP_PORT}}"
31
+ - name: DATABASE_URL
32
+ valueFrom:
33
+ secretKeyRef:
34
+ name: {{PROJECT_NAME}}-secrets
35
+ key: database-url
36
+ securityContext:
37
+ allowPrivilegeEscalation: false
38
+ readOnlyRootFilesystem: true
39
+ capabilities:
40
+ drop: ["ALL"]
41
+ volumeMounts:
42
+ - name: tmp
43
+ mountPath: /tmp
44
+ livenessProbe:
45
+ httpGet:
46
+ path: /health
47
+ port: {{APP_PORT}}
48
+ initialDelaySeconds: 10
49
+ periodSeconds: 15
50
+ timeoutSeconds: 5
51
+ failureThreshold: 3
52
+ readinessProbe:
53
+ httpGet:
54
+ path: /healthz
55
+ port: {{APP_PORT}}
56
+ initialDelaySeconds: 5
57
+ periodSeconds: 10
58
+ timeoutSeconds: 5
59
+ failureThreshold: 3
60
+ resources:
61
+ requests:
62
+ cpu: 100m
63
+ memory: 128Mi
64
+ limits:
65
+ cpu: 500m
66
+ memory: 512Mi
67
+ volumes:
68
+ - name: tmp
69
+ emptyDir: {}
70
+ terminationGracePeriodSeconds: 30
@@ -1,24 +1,24 @@
1
- apiVersion: autoscaling/v2
2
- kind: HorizontalPodAutoscaler
3
- metadata:
4
- name: {{PROJECT_NAME}}
5
- spec:
6
- scaleTargetRef:
7
- apiVersion: apps/v1
8
- kind: Deployment
9
- name: {{PROJECT_NAME}}
10
- minReplicas: 2
11
- maxReplicas: 10
12
- metrics:
13
- - type: Resource
14
- resource:
15
- name: cpu
16
- target:
17
- type: Utilization
18
- averageUtilization: 70
19
- - type: Resource
20
- resource:
21
- name: memory
22
- target:
23
- type: Utilization
24
- averageUtilization: 80
1
+ apiVersion: autoscaling/v2
2
+ kind: HorizontalPodAutoscaler
3
+ metadata:
4
+ name: {{PROJECT_NAME}}
5
+ spec:
6
+ scaleTargetRef:
7
+ apiVersion: apps/v1
8
+ kind: Deployment
9
+ name: {{PROJECT_NAME}}
10
+ minReplicas: 2
11
+ maxReplicas: 10
12
+ metrics:
13
+ - type: Resource
14
+ resource:
15
+ name: cpu
16
+ target:
17
+ type: Utilization
18
+ averageUtilization: 70
19
+ - type: Resource
20
+ resource:
21
+ name: memory
22
+ target:
23
+ type: Utilization
24
+ averageUtilization: 80
@@ -1,26 +1,26 @@
1
- apiVersion: networking.k8s.io/v1
2
- kind: Ingress
3
- metadata:
4
- name: {{PROJECT_NAME}}
5
- annotations:
6
- nginx.ingress.kubernetes.io/ssl-redirect: "true"
7
- nginx.ingress.kubernetes.io/proxy-body-size: "10m"
8
- nginx.ingress.kubernetes.io/limit-rps: "10"
9
- nginx.ingress.kubernetes.io/limit-connections: "5"
10
- spec:
11
- ingressClassName: nginx
12
- rules:
13
- - host: {{PROJECT_NAME}}.example.com
14
- http:
15
- paths:
16
- - path: /
17
- pathType: Prefix
18
- backend:
19
- service:
20
- name: {{PROJECT_NAME}}
21
- port:
22
- number: 80
23
- tls:
24
- - hosts:
25
- - {{PROJECT_NAME}}.example.com
26
- secretName: {{PROJECT_NAME}}-tls
1
+ apiVersion: networking.k8s.io/v1
2
+ kind: Ingress
3
+ metadata:
4
+ name: {{PROJECT_NAME}}
5
+ annotations:
6
+ nginx.ingress.kubernetes.io/ssl-redirect: "true"
7
+ nginx.ingress.kubernetes.io/proxy-body-size: "10m"
8
+ nginx.ingress.kubernetes.io/limit-rps: "10"
9
+ nginx.ingress.kubernetes.io/limit-connections: "5"
10
+ spec:
11
+ ingressClassName: nginx
12
+ rules:
13
+ - host: {{PROJECT_NAME}}.example.com
14
+ http:
15
+ paths:
16
+ - path: /
17
+ pathType: Prefix
18
+ backend:
19
+ service:
20
+ name: {{PROJECT_NAME}}
21
+ port:
22
+ number: 80
23
+ tls:
24
+ - hosts:
25
+ - {{PROJECT_NAME}}.example.com
26
+ secretName: {{PROJECT_NAME}}-tls
@@ -1,13 +1,13 @@
1
- apiVersion: kustomize.config.k8s.io/v1beta1
2
- kind: Kustomization
3
-
4
- namespace: {{PROJECT_NAME}}
5
-
6
- resources:
7
- - namespace.yml
8
- - deployment.yml
9
- - service.yml
10
- - ingress.yml
11
- - secrets.yml
12
- - hpa.yml
13
- - networkpolicy.yml
1
+ apiVersion: kustomize.config.k8s.io/v1beta1
2
+ kind: Kustomization
3
+
4
+ namespace: {{PROJECT_NAME}}
5
+
6
+ resources:
7
+ - namespace.yml
8
+ - deployment.yml
9
+ - service.yml
10
+ - ingress.yml
11
+ - secrets.yml
12
+ - hpa.yml
13
+ - networkpolicy.yml
@@ -1,4 +1,4 @@
1
- apiVersion: v1
2
- kind: Namespace
3
- metadata:
4
- name: {{PROJECT_NAME}}
1
+ apiVersion: v1
2
+ kind: Namespace
3
+ metadata:
4
+ name: {{PROJECT_NAME}}
@@ -1,41 +1,41 @@
1
- apiVersion: networking.k8s.io/v1
2
- kind: NetworkPolicy
3
- metadata:
4
- name: {{PROJECT_NAME}}
5
- spec:
6
- podSelector:
7
- matchLabels:
8
- app: {{PROJECT_NAME}}
9
- policyTypes:
10
- - Ingress
11
- - Egress
12
- ingress:
13
- - from:
14
- - namespaceSelector:
15
- matchLabels:
16
- kubernetes.io/metadata.name: ingress-nginx
17
- ports:
18
- - port: {{APP_PORT}}
19
- egress:
20
- # Database
21
- - to:
22
- - podSelector:
23
- matchLabels:
24
- app: postgres
25
- ports:
26
- - port: 5432
27
- # DNS (UDP + TCP for large responses)
28
- - to:
29
- - namespaceSelector:
30
- matchLabels:
31
- kubernetes.io/metadata.name: kube-system
32
- ports:
33
- - port: 53
34
- protocol: UDP
35
- - port: 53
36
- protocol: TCP
37
- # Uncomment to allow outbound HTTPS (external APIs, OAuth, webhooks)
38
- # - to: []
39
- # ports:
40
- # - port: 443
41
- # protocol: TCP
1
+ apiVersion: networking.k8s.io/v1
2
+ kind: NetworkPolicy
3
+ metadata:
4
+ name: {{PROJECT_NAME}}
5
+ spec:
6
+ podSelector:
7
+ matchLabels:
8
+ app: {{PROJECT_NAME}}
9
+ policyTypes:
10
+ - Ingress
11
+ - Egress
12
+ ingress:
13
+ - from:
14
+ - namespaceSelector:
15
+ matchLabels:
16
+ kubernetes.io/metadata.name: ingress-nginx
17
+ ports:
18
+ - port: {{APP_PORT}}
19
+ egress:
20
+ # Database
21
+ - to:
22
+ - podSelector:
23
+ matchLabels:
24
+ app: postgres
25
+ ports:
26
+ - port: 5432
27
+ # DNS (UDP + TCP for large responses)
28
+ - to:
29
+ - namespaceSelector:
30
+ matchLabels:
31
+ kubernetes.io/metadata.name: kube-system
32
+ ports:
33
+ - port: 53
34
+ protocol: UDP
35
+ - port: 53
36
+ protocol: TCP
37
+ # Uncomment to allow outbound HTTPS (external APIs, OAuth, webhooks)
38
+ # - to: []
39
+ # ports:
40
+ # - port: 443
41
+ # protocol: TCP
@@ -1,10 +1,10 @@
1
- apiVersion: v1
2
- kind: Secret
3
- metadata:
4
- name: {{PROJECT_NAME}}-secrets
5
- type: Opaque
6
- stringData:
7
- # IMPORTANT: Replace these placeholder values before deploying.
8
- # In production, use sealed-secrets, external-secrets, or your cloud provider's secret manager.
9
- # Do NOT commit real credentials to version control.
10
- database-url: "postgresql://USER:CHANGE_ME_BEFORE_DEPLOY@postgres:5432/{{PROJECT_NAME_SNAKE}}"
1
+ apiVersion: v1
2
+ kind: Secret
3
+ metadata:
4
+ name: {{PROJECT_NAME}}-secrets
5
+ type: Opaque
6
+ stringData:
7
+ # IMPORTANT: Replace these placeholder values before deploying.
8
+ # In production, use sealed-secrets, external-secrets, or your cloud provider's secret manager.
9
+ # Do NOT commit real credentials to version control.
10
+ database-url: "postgresql://USER:CHANGE_ME_BEFORE_DEPLOY@postgres:5432/{{PROJECT_NAME_SNAKE}}?sslmode=require"
@@ -1,15 +1,15 @@
1
- apiVersion: v1
2
- kind: Service
3
- metadata:
4
- name: {{PROJECT_NAME}}
5
- labels:
6
- app: {{PROJECT_NAME}}
7
- spec:
8
- type: ClusterIP
9
- selector:
10
- app: {{PROJECT_NAME}}
11
- ports:
12
- - name: http
13
- port: 80
14
- targetPort: {{APP_PORT}}
15
- protocol: TCP
1
+ apiVersion: v1
2
+ kind: Service
3
+ metadata:
4
+ name: {{PROJECT_NAME}}
5
+ labels:
6
+ app: {{PROJECT_NAME}}
7
+ spec:
8
+ type: ClusterIP
9
+ selector:
10
+ app: {{PROJECT_NAME}}
11
+ ports:
12
+ - name: http
13
+ port: 80
14
+ targetPort: {{APP_PORT}}
15
+ protocol: TCP
@@ -1,48 +1,48 @@
1
- # Load Testing — {{PROJECT_NAME_PASCAL}}
2
-
3
- Uses [k6](https://k6.io/) for load testing.
4
-
5
- ## Setup
6
-
7
- ```bash
8
- # macOS
9
- brew install k6
10
-
11
- # Windows (scoop)
12
- scoop install k6
13
-
14
- # Docker (no install)
15
- docker run --rm -i grafana/k6 run - <load-test.js
16
- ```
17
-
18
- ## Run
19
-
20
- ```bash
21
- # Smoke test (quick, single request)
22
- k6 run --vus 1 --iterations 1 k6/load-test.js
23
-
24
- # Full load test against local server
25
- k6 run k6/load-test.js
26
-
27
- # Against staging
28
- k6 run -e BASE_URL=https://staging.example.com k6/load-test.js
29
- ```
30
-
31
- ## Thresholds
32
-
33
- | Metric | Threshold | Meaning |
34
- |--------|-----------|---------|
35
- | `http_req_duration p(95)` | < 500ms | 95th percentile response time |
36
- | `http_req_duration p(99)` | < 1.5s | 99th percentile response time |
37
- | `http_req_failed` | < 1% | Error rate |
38
- | `checks` | > 99% | Assertion pass rate |
39
-
40
- ## CI Integration
41
-
42
- Add to your CI pipeline after deployment:
43
-
44
- ```yaml
45
- - name: Load test
46
- run: |
47
- k6 run -e BASE_URL=${{ secrets.STAGING_URL }} k6/load-test.js
48
- ```
1
+ # Load Testing — {{PROJECT_NAME_PASCAL}}
2
+
3
+ Uses [k6](https://k6.io/) for load testing.
4
+
5
+ ## Setup
6
+
7
+ ```bash
8
+ # macOS
9
+ brew install k6
10
+
11
+ # Windows (scoop)
12
+ scoop install k6
13
+
14
+ # Docker (no install)
15
+ docker run --rm -i grafana/k6 run - <load-test.js
16
+ ```
17
+
18
+ ## Run
19
+
20
+ ```bash
21
+ # Smoke test (quick, single request)
22
+ k6 run --vus 1 --iterations 1 k6/load-test.js
23
+
24
+ # Full load test against local server
25
+ k6 run k6/load-test.js
26
+
27
+ # Against staging
28
+ k6 run -e BASE_URL=https://staging.example.com k6/load-test.js
29
+ ```
30
+
31
+ ## Thresholds
32
+
33
+ | Metric | Threshold | Meaning |
34
+ |--------|-----------|---------|
35
+ | `http_req_duration p(95)` | < 500ms | 95th percentile response time |
36
+ | `http_req_duration p(99)` | < 1.5s | 99th percentile response time |
37
+ | `http_req_failed` | < 1% | Error rate |
38
+ | `checks` | > 99% | Assertion pass rate |
39
+
40
+ ## CI Integration
41
+
42
+ Add to your CI pipeline after deployment:
43
+
44
+ ```yaml
45
+ - name: Load test
46
+ run: |
47
+ k6 run -e BASE_URL=${{ secrets.STAGING_URL }} k6/load-test.js
48
+ ```