@next-friday/create-app 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +94 -2
  3. package/dist/main.mjs +414 -0
  4. package/package.json +84 -3
  5. package/templates/base/.agents/hooks/agent-shell-gate.sh +355 -0
  6. package/templates/base/.agents/hooks/agent-suppression-gate.sh +45 -0
  7. package/templates/base/.agents/rules/automation-owned-checks.md +5 -0
  8. package/templates/base/.agents/rules/code-comments.md +3 -0
  9. package/templates/base/.agents/rules/current-state-authority.md +17 -0
  10. package/templates/base/.agents/rules/demand-driven-configuration.md +7 -0
  11. package/templates/base/.agents/rules/dependency-security.md +5 -0
  12. package/templates/base/.agents/rules/deterministic-testing.md +15 -0
  13. package/templates/base/.agents/rules/diagnostics-and-error-handling.md +7 -0
  14. package/templates/base/.agents/rules/git-workflow.md +10 -0
  15. package/templates/base/.agents/rules/no-suppression.md +7 -0
  16. package/templates/base/.agents/rules/script-driven-changes.md +7 -0
  17. package/templates/base/.agents/rules/single-author-style.md +7 -0
  18. package/templates/base/.claude/rules/agents-guide.md +1 -0
  19. package/templates/base/.claude/rules/automation-owned-checks.md +1 -0
  20. package/templates/base/.claude/rules/code-comments.md +1 -0
  21. package/templates/base/.claude/rules/current-state-authority.md +1 -0
  22. package/templates/base/.claude/rules/demand-driven-configuration.md +1 -0
  23. package/templates/base/.claude/rules/dependency-security.md +12 -0
  24. package/templates/base/.claude/rules/diagnostics-and-error-handling.md +1 -0
  25. package/templates/base/.claude/rules/git-workflow.md +1 -0
  26. package/templates/base/.claude/rules/no-suppression.md +1 -0
  27. package/templates/base/.claude/rules/script-driven-changes.md +1 -0
  28. package/templates/base/.claude/rules/single-author-style.md +1 -0
  29. package/templates/base/.claude/settings.json +61 -0
  30. package/templates/base/.commitlintrc.json +3 -0
  31. package/templates/base/.cursor/BUGBOT.md +17 -0
  32. package/templates/base/.cursor/hooks/agent-constitution-gate.sh +32 -0
  33. package/templates/base/.cursor/hooks.json +26 -0
  34. package/templates/base/.cursor/rules/automation-owned-checks.mdc +10 -0
  35. package/templates/base/.cursor/rules/code-comments.mdc +8 -0
  36. package/templates/base/.cursor/rules/current-state-authority.mdc +22 -0
  37. package/templates/base/.cursor/rules/demand-driven-configuration.mdc +12 -0
  38. package/templates/base/.cursor/rules/dependency-security.mdc +11 -0
  39. package/templates/base/.cursor/rules/diagnostics-and-error-handling.mdc +12 -0
  40. package/templates/base/.cursor/rules/git-workflow.mdc +15 -0
  41. package/templates/base/.cursor/rules/no-suppression.mdc +12 -0
  42. package/templates/base/.cursor/rules/script-driven-changes.mdc +12 -0
  43. package/templates/base/.cursor/rules/single-author-style.mdc +12 -0
  44. package/templates/base/.editorconfig +13 -0
  45. package/templates/base/.gitattributes +1 -0
  46. package/templates/base/.github/CODEOWNERS +2 -0
  47. package/templates/base/.github/ISSUE_TEMPLATE/config.yml +1 -0
  48. package/templates/base/.github/dependabot.yml +77 -0
  49. package/templates/base/.github/file-filters.yml +19 -0
  50. package/templates/base/.github/labeler.yml +25 -0
  51. package/templates/base/.github/requirements/diff-cover.txt +213 -0
  52. package/templates/base/.github/workflows/deploy.yml +124 -0
  53. package/templates/base/.github/workflows/osv-scanner.yml +34 -0
  54. package/templates/base/.github/workflows/pr-triage.yml +29 -0
  55. package/templates/base/.github/workflows/secret-scan.yml +50 -0
  56. package/templates/base/.github/workflows/validate-pr-title.yml +48 -0
  57. package/templates/base/.github/workflows/zizmor.yml +62 -0
  58. package/templates/base/.github/zizmor.yml +4 -0
  59. package/templates/base/.gitleaks.toml +14 -0
  60. package/templates/base/.husky/commit-msg +3 -0
  61. package/templates/base/.husky/pre-commit +17 -0
  62. package/templates/base/.husky/pre-merge-commit +7 -0
  63. package/templates/base/.husky/pre-push +15 -0
  64. package/templates/base/.nvmrc +1 -0
  65. package/templates/base/SECURITY.md +15 -0
  66. package/templates/base/knip.json +3 -0
  67. package/templates/base/pnpm-workspace.yaml +18 -0
  68. package/templates/base/railway.json +9 -0
  69. package/templates/base/scripts/check-agent-gates.ts +252 -0
  70. package/templates/base/scripts/sync-agent-rules.ts +121 -0
  71. package/templates/nestjs/.agents/rules/typescript-first.md +7 -0
  72. package/templates/nestjs/.agents/rules.json +41 -0
  73. package/templates/nestjs/.claude/rules/deterministic-testing.md +20 -0
  74. package/templates/nestjs/.claude/rules/typescript-first.md +13 -0
  75. package/templates/nestjs/.cursor/rules/deterministic-testing.mdc +21 -0
  76. package/templates/nestjs/.cursor/rules/typescript-first.mdc +13 -0
  77. package/templates/nestjs/.dependency-cruiser.json +28 -0
  78. package/templates/nestjs/.dockerignore +8 -0
  79. package/templates/nestjs/.env.example +1 -0
  80. package/templates/nestjs/.github/ISSUE_TEMPLATE/bug.yml +66 -0
  81. package/templates/nestjs/.github/ISSUE_TEMPLATE/feature.yml +50 -0
  82. package/templates/nestjs/.github/pull_request_template.md +25 -0
  83. package/templates/nestjs/.github/workflows/ci.yml +181 -0
  84. package/templates/nestjs/.github/workflows/sast.yml +45 -0
  85. package/templates/nestjs/.lintstagedrc.json +10 -0
  86. package/templates/nestjs/.prettierignore +2 -0
  87. package/templates/nestjs/.prettierrc.json +1 -0
  88. package/templates/nestjs/AGENTS.md +8 -0
  89. package/templates/nestjs/CONTRIBUTING.md +57 -0
  90. package/templates/nestjs/Dockerfile +27 -0
  91. package/templates/nestjs/README.md +78 -0
  92. package/templates/nestjs/_gitignore +47 -0
  93. package/templates/nestjs/eslint.config.ts +7 -0
  94. package/templates/nestjs/package.json +83 -0
  95. package/templates/nestjs/src/app.controller.test.ts +23 -0
  96. package/templates/nestjs/src/app.controller.ts +13 -0
  97. package/templates/nestjs/src/app.module.ts +12 -0
  98. package/templates/nestjs/src/app.service.ts +10 -0
  99. package/templates/nestjs/src/health/health.controller.test.ts +17 -0
  100. package/templates/nestjs/src/health/health.controller.ts +14 -0
  101. package/templates/nestjs/src/health/health.module.ts +10 -0
  102. package/templates/nestjs/src/main.ts +25 -0
  103. package/templates/nestjs/src/port.test.ts +29 -0
  104. package/templates/nestjs/src/port.ts +20 -0
  105. package/templates/nestjs/test/app.e2e.test.ts +40 -0
  106. package/templates/nestjs/tsconfig.build.json +9 -0
  107. package/templates/nestjs/tsconfig.json +20 -0
  108. package/templates/nestjs/vitest.config.ts +13 -0
  109. package/templates/nestjs/vitest.e2e.config.ts +8 -0
  110. package/templates/nextjs/.agents/rules/typescript-first.md +7 -0
  111. package/templates/nextjs/.agents/rules.json +41 -0
  112. package/templates/nextjs/.claude/rules/deterministic-testing.md +21 -0
  113. package/templates/nextjs/.claude/rules/typescript-first.md +15 -0
  114. package/templates/nextjs/.cursor/rules/deterministic-testing.mdc +21 -0
  115. package/templates/nextjs/.cursor/rules/typescript-first.mdc +13 -0
  116. package/templates/nextjs/.dependency-cruiser.json +34 -0
  117. package/templates/nextjs/.dockerignore +10 -0
  118. package/templates/nextjs/.env.example +1 -0
  119. package/templates/nextjs/.github/ISSUE_TEMPLATE/bug.yml +66 -0
  120. package/templates/nextjs/.github/ISSUE_TEMPLATE/feature.yml +50 -0
  121. package/templates/nextjs/.github/pull_request_template.md +25 -0
  122. package/templates/nextjs/.github/workflows/ci.yml +187 -0
  123. package/templates/nextjs/.github/workflows/sast.yml +46 -0
  124. package/templates/nextjs/.lintstagedrc.json +10 -0
  125. package/templates/nextjs/.prettierignore +2 -0
  126. package/templates/nextjs/AGENTS.md +18 -0
  127. package/templates/nextjs/CONTRIBUTING.md +57 -0
  128. package/templates/nextjs/Dockerfile +23 -0
  129. package/templates/nextjs/README.md +74 -0
  130. package/templates/nextjs/_gitignore +51 -0
  131. package/templates/nextjs/app/favicon.ico +0 -0
  132. package/templates/nextjs/app/globals.css +26 -0
  133. package/templates/nextjs/app/health/route.test.ts +20 -0
  134. package/templates/nextjs/app/health/route.ts +23 -0
  135. package/templates/nextjs/app/layout.tsx +29 -0
  136. package/templates/nextjs/app/page.test.ts +11 -0
  137. package/templates/nextjs/app/page.tsx +8 -0
  138. package/templates/nextjs/eslint.config.ts +32 -0
  139. package/templates/nextjs/knip.json +4 -0
  140. package/templates/nextjs/next.config.ts +35 -0
  141. package/templates/nextjs/package.json +78 -0
  142. package/templates/nextjs/playwright.config.ts +27 -0
  143. package/templates/nextjs/postcss.config.mjs +7 -0
  144. package/templates/nextjs/prettier.config.ts +11 -0
  145. package/templates/nextjs/test/home.e2e.test.ts +11 -0
  146. package/templates/nextjs/tsconfig.json +33 -0
  147. package/templates/nextjs/vitest.config.ts +12 -0
  148. package/templates/nodejs/.agents/rules/typescript-first.md +7 -0
  149. package/templates/nodejs/.agents/rules.json +41 -0
  150. package/templates/nodejs/.claude/rules/deterministic-testing.md +20 -0
  151. package/templates/nodejs/.claude/rules/typescript-first.md +13 -0
  152. package/templates/nodejs/.cursor/rules/deterministic-testing.mdc +21 -0
  153. package/templates/nodejs/.cursor/rules/typescript-first.mdc +13 -0
  154. package/templates/nodejs/.dependency-cruiser.json +28 -0
  155. package/templates/nodejs/.dockerignore +8 -0
  156. package/templates/nodejs/.env.example +1 -0
  157. package/templates/nodejs/.github/ISSUE_TEMPLATE/bug.yml +66 -0
  158. package/templates/nodejs/.github/ISSUE_TEMPLATE/feature.yml +50 -0
  159. package/templates/nodejs/.github/pull_request_template.md +25 -0
  160. package/templates/nodejs/.github/workflows/ci.yml +179 -0
  161. package/templates/nodejs/.github/workflows/sast.yml +45 -0
  162. package/templates/nodejs/.lintstagedrc.json +10 -0
  163. package/templates/nodejs/.prettierignore +2 -0
  164. package/templates/nodejs/.prettierrc.json +1 -0
  165. package/templates/nodejs/AGENTS.md +8 -0
  166. package/templates/nodejs/CONTRIBUTING.md +56 -0
  167. package/templates/nodejs/Dockerfile +27 -0
  168. package/templates/nodejs/README.md +74 -0
  169. package/templates/nodejs/_gitignore +47 -0
  170. package/templates/nodejs/eslint.config.ts +7 -0
  171. package/templates/nodejs/package.json +66 -0
  172. package/templates/nodejs/src/main.ts +22 -0
  173. package/templates/nodejs/src/port.test.ts +30 -0
  174. package/templates/nodejs/src/port.ts +20 -0
  175. package/templates/nodejs/src/server.test.ts +60 -0
  176. package/templates/nodejs/src/server.ts +37 -0
  177. package/templates/nodejs/tsconfig.build.json +9 -0
  178. package/templates/nodejs/tsconfig.json +19 -0
  179. package/templates/nodejs/vitest.config.ts +12 -0
  180. package/templates/payload/.agents/rules/typescript-first.md +7 -0
  181. package/templates/payload/.agents/rules.json +41 -0
  182. package/templates/payload/.claude/rules/deterministic-testing.md +21 -0
  183. package/templates/payload/.claude/rules/typescript-first.md +15 -0
  184. package/templates/payload/.cursor/rules/deterministic-testing.mdc +21 -0
  185. package/templates/payload/.cursor/rules/typescript-first.mdc +13 -0
  186. package/templates/payload/.dependency-cruiser.json +34 -0
  187. package/templates/payload/.dockerignore +9 -0
  188. package/templates/payload/.editorconfig-checker.json +3 -0
  189. package/templates/payload/.env.example +4 -0
  190. package/templates/payload/.github/ISSUE_TEMPLATE/bug.yml +66 -0
  191. package/templates/payload/.github/ISSUE_TEMPLATE/feature.yml +50 -0
  192. package/templates/payload/.github/pull_request_template.md +25 -0
  193. package/templates/payload/.github/workflows/ci.yml +204 -0
  194. package/templates/payload/.github/workflows/sast.yml +46 -0
  195. package/templates/payload/.lintstagedrc.json +10 -0
  196. package/templates/payload/.prettierignore +5 -0
  197. package/templates/payload/.prettierrc.json +1 -0
  198. package/templates/payload/AGENTS.md +19 -0
  199. package/templates/payload/CONTRIBUTING.md +58 -0
  200. package/templates/payload/Dockerfile +26 -0
  201. package/templates/payload/README.md +98 -0
  202. package/templates/payload/_gitignore +52 -0
  203. package/templates/payload/eslint.config.ts +35 -0
  204. package/templates/payload/next.config.ts +43 -0
  205. package/templates/payload/package.json +86 -0
  206. package/templates/payload/playwright.config.ts +27 -0
  207. package/templates/payload/src/app/(frontend)/layout.tsx +18 -0
  208. package/templates/payload/src/app/(frontend)/page.test.ts +14 -0
  209. package/templates/payload/src/app/(frontend)/page.tsx +14 -0
  210. package/templates/payload/src/app/(frontend)/styles.css +15 -0
  211. package/templates/payload/src/app/(payload)/admin/[[...segments]]/not-found.tsx +24 -0
  212. package/templates/payload/src/app/(payload)/admin/[[...segments]]/page.tsx +24 -0
  213. package/templates/payload/src/app/(payload)/admin/importMap.ts +6 -0
  214. package/templates/payload/src/app/(payload)/api/[...slug]/route.ts +19 -0
  215. package/templates/payload/src/app/(payload)/api/graphql/route.ts +8 -0
  216. package/templates/payload/src/app/(payload)/api/graphql-playground/route.ts +7 -0
  217. package/templates/payload/src/app/(payload)/custom.scss +0 -0
  218. package/templates/payload/src/app/(payload)/layout.tsx +31 -0
  219. package/templates/payload/src/app/health/route.test.ts +20 -0
  220. package/templates/payload/src/app/health/route.ts +23 -0
  221. package/templates/payload/src/collections/media.test.ts +27 -0
  222. package/templates/payload/src/collections/media.ts +18 -0
  223. package/templates/payload/src/collections/users.test.ts +10 -0
  224. package/templates/payload/src/collections/users.ts +10 -0
  225. package/templates/payload/src/environment.test.ts +32 -0
  226. package/templates/payload/src/environment.ts +14 -0
  227. package/templates/payload/src/migrations/20261030_005055_initial.json +969 -0
  228. package/templates/payload/src/migrations/20261030_005055_initial.ts +134 -0
  229. package/templates/payload/src/migrations/index.ts +9 -0
  230. package/templates/payload/src/payload-types.ts +339 -0
  231. package/templates/payload/src/payload.config.ts +47 -0
  232. package/templates/payload/test/home.e2e.test.ts +16 -0
  233. package/templates/payload/tsconfig.json +34 -0
  234. package/templates/payload/vitest.config.ts +19 -0
@@ -0,0 +1,124 @@
1
+ name: Deploy
2
+ run-name: Deploy ${{ inputs.commit_sha }} to ${{ inputs.environment }}
3
+
4
+ on:
5
+ workflow_call:
6
+ inputs:
7
+ environment:
8
+ required: true
9
+ type: string
10
+ commit_sha:
11
+ required: true
12
+ type: string
13
+ workflow_dispatch:
14
+ inputs:
15
+ environment:
16
+ description: Railway environment to promote to
17
+ required: true
18
+ type: choice
19
+ options:
20
+ - uat
21
+ - prod
22
+ commit_sha:
23
+ description: Full commit SHA on main that passed CI
24
+ required: true
25
+ type: string
26
+
27
+ permissions: {}
28
+
29
+ concurrency:
30
+ group: deploy-${{ inputs.environment }}
31
+ cancel-in-progress: false
32
+
33
+ jobs:
34
+ verify:
35
+ name: Verify the requested commit
36
+ runs-on: ubuntu-latest
37
+ timeout-minutes: 5
38
+ permissions:
39
+ contents: read
40
+ actions: read # Needed to find the CI and deploy runs of the requested commit.
41
+ env:
42
+ COMMIT_SHA: ${{ inputs.commit_sha }}
43
+ TARGET: ${{ inputs.environment }}
44
+ steps:
45
+ - name: Checkout the requested revision
46
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
47
+ with:
48
+ ref: ${{ inputs.commit_sha }}
49
+ fetch-depth: 0
50
+ persist-credentials: false
51
+ - name: Require the commit on main with passing CI and a deployment to the previous environment
52
+ if: github.event_name == 'workflow_dispatch'
53
+ env:
54
+ GH_TOKEN: ${{ github.token }}
55
+ REPOSITORY: ${{ github.repository }}
56
+ run: |
57
+ [[ "$COMMIT_SHA" =~ ^[0-9a-f]{40}$ ]] || { echo "::error::Expected a full lowercase commit SHA"; exit 1; }
58
+ git merge-base --is-ancestor "$COMMIT_SHA" origin/main || { echo "::error::$COMMIT_SHA is not on main"; exit 1; }
59
+ ci_run="$(gh api "repos/$REPOSITORY/actions/workflows/ci.yml/runs?head_sha=$COMMIT_SHA&event=push&branch=main&status=success" --jq '.workflow_runs[0].id // empty')"
60
+ [[ -n "$ci_run" ]] || { echo "::error::No successful CI run on main for $COMMIT_SHA"; exit 1; }
61
+ case "$TARGET" in
62
+ uat)
63
+ previous=dev
64
+ deployed="$(gh api "repos/$REPOSITORY/actions/runs/$ci_run/jobs" --jq '[.jobs[] | select(.name == "Deploy to dev / Deploy to dev" and .conclusion == "success")] | length')"
65
+ ;;
66
+ prod)
67
+ previous=uat
68
+ export EXPECTED_TITLE="Deploy $COMMIT_SHA to uat"
69
+ deployed="$(gh api --paginate "repos/$REPOSITORY/actions/workflows/deploy.yml/runs?event=workflow_dispatch&status=success&per_page=100" --jq '.workflow_runs[] | select(.display_title == env.EXPECTED_TITLE) | .id' | wc -l)"
70
+ ;;
71
+ esac
72
+ [[ "$deployed" -gt 0 ]] || { echo "::error::$COMMIT_SHA has no successful $previous deployment; promote through $previous first"; exit 1; }
73
+
74
+ deploy:
75
+ name: Deploy to ${{ inputs.environment }}
76
+ needs: verify
77
+ runs-on: ubuntu-latest
78
+ timeout-minutes: 30
79
+ environment:
80
+ name: ${{ inputs.environment }}
81
+ url: ${{ vars.APP_URL }}
82
+ permissions:
83
+ contents: read
84
+ env:
85
+ APP_URL: ${{ vars.APP_URL }}
86
+ RAILWAY_CLI_SHA256: 2e682fd2ddf8d6fdf9e46d9d99d99646ff0022a6abb0c2bca93011348a269fb9
87
+ RAILWAY_CLI_VERSION: 5.71.0
88
+ RAILWAY_ENVIRONMENT: ${{ inputs.environment }}
89
+ RAILWAY_SERVICE: ${{ vars.RAILWAY_SERVICE }}
90
+ steps:
91
+ - name: Require environment settings
92
+ env:
93
+ RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
94
+ run: |
95
+ [[ -n "$RAILWAY_TOKEN" ]] || { echo "::error::Set the RAILWAY_TOKEN secret in the $RAILWAY_ENVIRONMENT environment"; exit 1; }
96
+ [[ -n "$RAILWAY_SERVICE" ]] || { echo "::error::Set the RAILWAY_SERVICE variable in the $RAILWAY_ENVIRONMENT environment"; exit 1; }
97
+ [[ "$APP_URL" == https://* ]] || { echo "::error::Set the APP_URL variable to an https URL in the $RAILWAY_ENVIRONMENT environment"; exit 1; }
98
+ - name: Checkout the requested revision
99
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
100
+ with:
101
+ ref: ${{ inputs.commit_sha }}
102
+ persist-credentials: false
103
+ - name: Install verified Railway CLI
104
+ run: |
105
+ archive="railway-v${RAILWAY_CLI_VERSION}-x86_64-unknown-linux-musl.tar.gz"
106
+ curl --silent --show-error --fail --location --retry 3 --output "$RUNNER_TEMP/$archive" \
107
+ "https://github.com/railwayapp/cli/releases/download/v${RAILWAY_CLI_VERSION}/${archive}"
108
+ echo "${RAILWAY_CLI_SHA256} $RUNNER_TEMP/$archive" | sha256sum --check --strict
109
+ tar --extract --gzip --file "$RUNNER_TEMP/$archive" --directory "$RUNNER_TEMP"
110
+ echo "$RUNNER_TEMP" >> "$GITHUB_PATH"
111
+ - name: Deploy
112
+ env:
113
+ RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
114
+ run: railway up --ci --service "$RAILWAY_SERVICE" --environment "$RAILWAY_ENVIRONMENT"
115
+ - name: Require a healthy deployment
116
+ run: |
117
+ for _ in $(seq 30); do
118
+ if curl --silent --fail --output /dev/null "$APP_URL/health"; then
119
+ exit 0
120
+ fi
121
+ sleep 10
122
+ done
123
+ echo "::error::$APP_URL/health did not respond"
124
+ exit 1
@@ -0,0 +1,34 @@
1
+ name: OSV-Scanner
2
+
3
+ on:
4
+ pull_request: {}
5
+ push:
6
+ branches:
7
+ - main
8
+ paths-ignore:
9
+ - "**/*.md"
10
+ - ".agents/**"
11
+ - ".claude/**"
12
+ - ".cursor/**"
13
+ schedule:
14
+ - cron: "37 2 * * 1"
15
+
16
+ permissions: {}
17
+
18
+ concurrency:
19
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
20
+ cancel-in-progress: true
21
+
22
+ jobs:
23
+ scan:
24
+ name: Scan
25
+ permissions:
26
+ actions: read # Needed by the reusable workflow to read workflow run metadata.
27
+ contents: read
28
+ security-events: write # Required by the reusable workflow's declared permissions; unused without SARIF upload.
29
+ uses: google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@b1d267aea5211fa648d9d442fa64b90dbdcbdd36 # v2.7.0
30
+ with:
31
+ upload-sarif: false
32
+ scan-args: |-
33
+ --lockfile=pnpm-lock.yaml
34
+ --lockfile=requirements.txt:.github/requirements/diff-cover.txt
@@ -0,0 +1,29 @@
1
+ name: PR Labeler
2
+
3
+ on:
4
+ pull_request_target:
5
+ types:
6
+ - opened
7
+ - reopened
8
+ - synchronize
9
+ - ready_for_review
10
+
11
+ permissions: {}
12
+
13
+ concurrency:
14
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
15
+ cancel-in-progress: true
16
+
17
+ jobs:
18
+ label:
19
+ name: Label
20
+ runs-on: ubuntu-latest
21
+ timeout-minutes: 10
22
+ permissions:
23
+ contents: read
24
+ pull-requests: write # Needed by actions/labeler to update pull request labels.
25
+ steps:
26
+ - name: Label pull request
27
+ uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0
28
+ with:
29
+ sync-labels: true
@@ -0,0 +1,50 @@
1
+ name: Secret Scan
2
+
3
+ on:
4
+ pull_request: {}
5
+ push:
6
+ branches:
7
+ - main
8
+
9
+ permissions: {}
10
+
11
+ concurrency:
12
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ scan:
17
+ name: TruffleHog and Gitleaks (secrets and PAN)
18
+ runs-on: ubuntu-latest
19
+ timeout-minutes: 10
20
+ permissions:
21
+ contents: read
22
+ env:
23
+ GITLEAKS_VERSION: 8.30.1
24
+ PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
25
+ PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
26
+ GITLEAKS_SHA256: 551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb
27
+ steps:
28
+ - name: Checkout repository
29
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
30
+ with:
31
+ fetch-depth: 0
32
+ persist-credentials: false
33
+ - name: Scan commits for secrets
34
+ uses: trufflesecurity/trufflehog@e76dff8a7e57d6df0c60ad8cbf5d5cba505a8fc9 # v3.99.2
35
+ with:
36
+ extra_args: --results=verified,unknown
37
+ - name: Install verified gitleaks
38
+ run: |
39
+ archive="gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
40
+ curl --silent --show-error --fail --location --output "$archive" \
41
+ "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/${archive}"
42
+ echo "${GITLEAKS_SHA256} ${archive}" | sha256sum --check --strict
43
+ tar --extract --gzip --file "$archive" gitleaks
44
+ - name: Scan history with repository rules
45
+ run: |
46
+ log_opts=()
47
+ if [[ -n "$PR_BASE_SHA" ]]; then
48
+ log_opts=(--log-opts="${PR_BASE_SHA}..${PR_HEAD_SHA}")
49
+ fi
50
+ ./gitleaks git --redact --config .gitleaks.toml --no-banner "${log_opts[@]}" .
@@ -0,0 +1,48 @@
1
+ name: Validate Pull Request Titles
2
+
3
+ on:
4
+ pull_request:
5
+ types:
6
+ - opened
7
+ - edited
8
+ - reopened
9
+ - synchronize
10
+
11
+ permissions:
12
+ pull-requests: read # Needed to read the pull request title for semantic validation.
13
+
14
+ concurrency:
15
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
16
+ cancel-in-progress: true
17
+
18
+ jobs:
19
+ validate-title:
20
+ name: Validate pull request title
21
+ if: github.event.pull_request.user.login != 'dependabot[bot]'
22
+ runs-on: ubuntu-latest
23
+ timeout-minutes: 10
24
+ steps:
25
+ - name: Validate pull request title
26
+ uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
27
+ env:
28
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29
+ with:
30
+ types: |
31
+ build
32
+ chore
33
+ ci
34
+ docs
35
+ feat
36
+ fix
37
+ perf
38
+ refactor
39
+ revert
40
+ style
41
+ test
42
+ requireScope: true
43
+ disallowScopes: |
44
+ .*[A-Z].*
45
+ subjectPattern: ^.{1,50}$
46
+ subjectPatternError: >-
47
+ The subject "{subject}" in pull request title "{title}" must be between
48
+ 1 and 50 characters.
@@ -0,0 +1,62 @@
1
+ name: Workflow Lint
2
+
3
+ on:
4
+ workflow_dispatch: {}
5
+ pull_request:
6
+ paths:
7
+ - ".github/**"
8
+ push:
9
+ branches:
10
+ - main
11
+ paths:
12
+ - ".github/**"
13
+
14
+ permissions: {}
15
+
16
+ concurrency:
17
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
18
+ cancel-in-progress: true
19
+
20
+ jobs:
21
+ zizmor:
22
+ name: Zizmor
23
+ runs-on: ubuntu-latest
24
+ timeout-minutes: 10
25
+ permissions:
26
+ contents: read
27
+ steps:
28
+ - name: Checkout repository
29
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
30
+ with:
31
+ persist-credentials: false
32
+ - name: Analyze GitHub Actions security
33
+ uses: zizmorcore/zizmor-action@85b2b9fb8e3325e7a23d7d0a9d7ba5ae0f999e3e # v0.7.1
34
+ with:
35
+ inputs: .github
36
+ version: 1.30.1
37
+ persona: pedantic
38
+ advanced-security: false
39
+
40
+ actionlint:
41
+ name: Actionlint
42
+ runs-on: ubuntu-latest
43
+ timeout-minutes: 10
44
+ permissions:
45
+ contents: read
46
+ env:
47
+ ACTIONLINT_VERSION: 1.7.12
48
+ ACTIONLINT_SHA256: 8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8
49
+ steps:
50
+ - name: Checkout repository
51
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
52
+ with:
53
+ persist-credentials: false
54
+ - name: Install verified actionlint
55
+ run: |
56
+ archive="actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
57
+ curl --silent --show-error --fail --location --output "$archive" \
58
+ "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/${archive}"
59
+ echo "${ACTIONLINT_SHA256} ${archive}" | sha256sum --check --strict
60
+ tar --extract --gzip --file "$archive" actionlint
61
+ - name: Lint workflows
62
+ run: ./actionlint -color
@@ -0,0 +1,4 @@
1
+ # Owner: @your-org/your-team. Reason: Semgrep rejects the `$/` self-repository syntax, so local actions use `./`. Expires: 2027-04-29.
2
+ rules:
3
+ self-repository:
4
+ disable: true
@@ -0,0 +1,14 @@
1
+ [extend]
2
+ useDefault = true
3
+
4
+ [[rules]]
5
+ id = "primary-account-number"
6
+ description = "Payment card PAN (Visa, Mastercard, Amex, Discover, JCB)"
7
+ regex = '''\b(?:4\d{12}(?:\d{3})?|5[1-5]\d{14}|2(?:2[2-9]\d|[3-6]\d{2}|7[01]\d|720)\d{12}|3[47]\d{13}|6(?:011|5\d{2})\d{12}|35(?:2[89]|[3-8]\d)\d{12})\b'''
8
+ keywords = ["2", "3", "4", "5", "6"]
9
+
10
+ [[rules.allowlists]]
11
+ description = "Published processor test PANs"
12
+ regexes = [
13
+ '''\b(?:4111111111111111|4242424242424242|4000056655665556|5555555555554444|5105105105105100|2223003122003222|378282246310005|371449635398431|6011111111111117|3530111333300000)\b''',
14
+ ]
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env sh
2
+
3
+ pnpm exec commitlint --edit "$1"
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env sh
2
+ set -e
3
+
4
+ # The first commit of a new repository creates main, so it is the only commit allowed there.
5
+ if [ "$(git branch --show-current)" = main ] && git rev-parse --quiet --verify HEAD > /dev/null; then
6
+ echo "pre-commit: do not commit on main. Create a branch: git switch --create <type>/<short-description>" >&2
7
+ exit 1
8
+ fi
9
+
10
+ command -v gitleaks > /dev/null 2>&1 || {
11
+ echo "pre-commit: gitleaks is required. Install it (see CONTRIBUTING.md), then commit again." >&2
12
+ exit 1
13
+ }
14
+
15
+ gitleaks git --pre-commit --redact --staged --no-banner --config .gitleaks.toml
16
+ pnpm rules:check
17
+ pnpm exec lint-staged
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env sh
2
+ set -e
3
+
4
+ if [ "$(git branch --show-current)" = main ]; then
5
+ echo "pre-merge-commit: do not merge into main locally. Merge through a pull request." >&2
6
+ exit 1
7
+ fi
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env sh
2
+ set -e
3
+
4
+ # The first push of a new repository creates main on the remote, so it is the only push allowed there.
5
+ while read -r _ _ remote_ref remote_oid; do
6
+ if [ "$remote_ref" = refs/heads/main ] && [ -n "$(printf '%s' "$remote_oid" | tr -d 0)" ]; then
7
+ echo "pre-push: do not push to main. Push your branch and open a pull request." >&2
8
+ exit 1
9
+ fi
10
+ done
11
+
12
+ pnpm check || {
13
+ echo "pre-push: pnpm check failed. Fix the failures above, commit, then push again." >&2
14
+ exit 1
15
+ }
@@ -0,0 +1 @@
1
+ 24.22.1
@@ -0,0 +1,15 @@
1
+ # Security Policy
2
+
3
+ ## Supported versions
4
+
5
+ Only the latest commit on the `main` branch receives security fixes.
6
+
7
+ ## Reporting a vulnerability
8
+
9
+ Report vulnerabilities privately through **Security → Report a vulnerability** in this repository. Describe the issue, the affected files or versions, and steps to reproduce it.
10
+
11
+ Do not open a public issue, pull request, or discussion for a vulnerability.
12
+
13
+ ## What to expect
14
+
15
+ A maintainer acknowledges the report, confirms or rejects the finding, and coordinates a fix and disclosure date with you.
@@ -0,0 +1,3 @@
1
+ {
2
+ "$schema": "https://unpkg.com/knip@6/schema.json"
3
+ }
@@ -0,0 +1,18 @@
1
+ engineStrict: true
2
+ savePrefix: ""
3
+ allowBuilds:
4
+ esbuild: true
5
+ unrs-resolver: true
6
+ overrides:
7
+ "katex@<0.18.2": ^0.18.2
8
+ "fast-uri@<3.1.9": ^3.1.9
9
+ "dompurify@<3.4.17": ^3.4.17
10
+ "esbuild@<0.27.0": ^0.28.2
11
+ "graphql-scalars@<2.0.1": ^2.0.1
12
+ "happy-dom@<21.0.4": ^21.0.4
13
+ minimumReleaseAgeExclude:
14
+ - "@next-friday/commitlint-config-friday@4.0.0"
15
+ - "@next-friday/eslint-config-friday@5.0.0"
16
+ - "@next-friday/eslint-config-friday@5.1.0"
17
+ - "@next-friday/prettier-config-friday@4.0.0"
18
+ - "@next-friday/eslint-plugin-friday@1.1.3"
@@ -0,0 +1,9 @@
1
+ {
2
+ "$schema": "https://railway.com/railway.schema.json",
3
+ "build": {
4
+ "builder": "DOCKERFILE"
5
+ },
6
+ "deploy": {
7
+ "healthcheckPath": "/health"
8
+ }
9
+ }