@gspothq/cli 0.0.0-stage → 0.1.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 (232) hide show
  1. package/README.md +18 -2
  2. package/configurations/database/postgres/manifest.toml +114 -0
  3. package/configurations/database/postgres/rules/POSTGRES.md +78 -0
  4. package/configurations/framework/astro/eslint-presets.json +138 -0
  5. package/configurations/framework/astro/manifest.toml +95 -0
  6. package/configurations/framework/astro/rules/ASTRO.md +39 -0
  7. package/configurations/framework/expo/manifest.toml +43 -0
  8. package/configurations/framework/express/manifest.toml +17 -0
  9. package/configurations/framework/express/rules/EXPRESS.md +73 -0
  10. package/configurations/framework/express/semgrep/express.yml +71 -0
  11. package/configurations/framework/fastapi/manifest.toml +11 -0
  12. package/configurations/framework/fastapi/rules/FASTAPI.md +100 -0
  13. package/configurations/framework/fastapi/semgrep/fastapi.yml +44 -0
  14. package/configurations/framework/nestjs/eslint-presets.json +62 -0
  15. package/configurations/framework/nestjs/manifest.toml +52 -0
  16. package/configurations/framework/nestjs/rules/NESTJS.md +44 -0
  17. package/configurations/framework/nextjs/eslint-presets.json +73 -0
  18. package/configurations/framework/nextjs/manifest.toml +119 -0
  19. package/configurations/framework/nextjs/rules/NEXTJS.md +43 -0
  20. package/configurations/framework/react/eslint-presets.json +77 -0
  21. package/configurations/framework/react/manifest.toml +93 -0
  22. package/configurations/framework/react/rules/REACT.md +108 -0
  23. package/configurations/framework/react-dom/eslint-presets.json +110 -0
  24. package/configurations/framework/react-dom/manifest.toml +24 -0
  25. package/configurations/framework/react-native/manifest.toml +46 -0
  26. package/configurations/framework/react-native/rules/REACT-NATIVE.md +51 -0
  27. package/configurations/framework/site/manifest.toml +170 -0
  28. package/configurations/framework/site/rules/SITE.md +20 -0
  29. package/configurations/framework/svelte/eslint-presets.json +67 -0
  30. package/configurations/framework/svelte/manifest.toml +83 -0
  31. package/configurations/framework/svelte/rules/SVELTE.md +48 -0
  32. package/configurations/framework/vue/eslint-presets.json +180 -0
  33. package/configurations/framework/vue/manifest.toml +83 -0
  34. package/configurations/framework/vue/rules/VUE.md +41 -0
  35. package/configurations/general/commits/manifest.toml +111 -0
  36. package/configurations/general/commits/rules/GIT.md +31 -0
  37. package/configurations/general/coverage/manifest.toml +3 -0
  38. package/configurations/general/dependencies/manifest.toml +159 -0
  39. package/configurations/general/dependencies/rules/DEPENDENCIES.md +30 -0
  40. package/configurations/general/dependencies/syncpack.json +15 -0
  41. package/configurations/general/docs/manifest.toml +79 -0
  42. package/configurations/general/docs/rules/DOCS.md +86 -0
  43. package/configurations/general/duplication/manifest.toml +32 -0
  44. package/configurations/general/engineering/manifest.toml +8 -0
  45. package/configurations/general/engineering/rules/agent/PLANNING.md +42 -0
  46. package/configurations/general/engineering/rules/agent/SUPPRESSIONS.md +16 -0
  47. package/configurations/general/engineering/rules/agent/TALKING.md +3 -0
  48. package/configurations/general/engineering/rules/agent/TASKS.md +19 -0
  49. package/configurations/general/engineering/rules/agent/WORKING.md +83 -0
  50. package/configurations/general/engineering/rules/code/ACCESSIBILITY.md +32 -0
  51. package/configurations/general/engineering/rules/code/CLI.md +37 -0
  52. package/configurations/general/engineering/rules/code/COMMENTS.md +38 -0
  53. package/configurations/general/engineering/rules/code/CONFIGURATION.md +25 -0
  54. package/configurations/general/engineering/rules/code/ERRORS.md +49 -0
  55. package/configurations/general/engineering/rules/code/HTTP.md +46 -0
  56. package/configurations/general/engineering/rules/code/LOGGING.md +55 -0
  57. package/configurations/general/engineering/rules/code/TESTING.md +58 -0
  58. package/configurations/general/files/manifest.toml +141 -0
  59. package/configurations/general/files/rules/YAML.md +19 -0
  60. package/configurations/general/format/manifest.toml +152 -0
  61. package/configurations/general/gspot/manifest.toml +65 -0
  62. package/configurations/general/gspot/rules/GENERATED.md +10 -0
  63. package/configurations/general/licenses/manifest.toml +33 -0
  64. package/configurations/general/naming/defaults.json +423 -0
  65. package/configurations/general/naming/manifest.toml +35 -0
  66. package/configurations/general/naming/rules/NAMING.md +179 -0
  67. package/configurations/general/prose/manifest.toml +86 -0
  68. package/configurations/general/prose/rules/WRITING.md +31 -0
  69. package/configurations/general/prose/vale/styles/LICENSES.md +55 -0
  70. package/configurations/general/prose/vale/styles/gspot/ampm.yml +8 -0
  71. package/configurations/general/prose/vale/styles/gspot/conscious-language.yml +16 -0
  72. package/configurations/general/prose/vale/styles/gspot/contractions.yml +43 -0
  73. package/configurations/general/prose/vale/styles/gspot/currency.yml +8 -0
  74. package/configurations/general/prose/vale/styles/gspot/dashes.yml +8 -0
  75. package/configurations/general/prose/vale/styles/gspot/date-ordinals.yml +41 -0
  76. package/configurations/general/prose/vale/styles/gspot/dates.yml +7 -0
  77. package/configurations/general/prose/vale/styles/gspot/file-paths.yml +7 -0
  78. package/configurations/general/prose/vale/styles/gspot/future.yml +17 -0
  79. package/configurations/general/prose/vale/styles/gspot/hedging.yml +22 -0
  80. package/configurations/general/prose/vale/styles/gspot/history.yml +16 -0
  81. package/configurations/general/prose/vale/styles/gspot/idioms.yml +21 -0
  82. package/configurations/general/prose/vale/styles/gspot/interface-verbs.yml +11 -0
  83. package/configurations/general/prose/vale/styles/gspot/jargon.yml +11 -0
  84. package/configurations/general/prose/vale/styles/gspot/leading-conjunctions.yml +12 -0
  85. package/configurations/general/prose/vale/styles/gspot/link-text.yml +8 -0
  86. package/configurations/general/prose/vale/styles/gspot/locations.yml +14 -0
  87. package/configurations/general/prose/vale/styles/gspot/marketing.yml +26 -0
  88. package/configurations/general/prose/vale/styles/gspot/merge-conflict-markers.yml +13 -0
  89. package/configurations/general/prose/vale/styles/gspot/militaristic-language.yml +22 -0
  90. package/configurations/general/prose/vale/styles/gspot/modals.yml +9 -0
  91. package/configurations/general/prose/vale/styles/gspot/numbered-units.yml +18 -0
  92. package/configurations/general/prose/vale/styles/gspot/obvious-fields.yml +14 -0
  93. package/configurations/general/prose/vale/styles/gspot/ordinal-adverbs.yml +15 -0
  94. package/configurations/general/prose/vale/styles/gspot/percentage-numbers.yml +8 -0
  95. package/configurations/general/prose/vale/styles/gspot/placeholders.yml +7 -0
  96. package/configurations/general/prose/vale/styles/gspot/product-centric-writing.yml +8 -0
  97. package/configurations/general/prose/vale/styles/gspot/punctuated-headings.yml +11 -0
  98. package/configurations/general/prose/vale/styles/gspot/self-reference.yml +15 -0
  99. package/configurations/general/prose/vale/styles/gspot/session-identifiers.yml +11 -0
  100. package/configurations/general/prose/vale/styles/gspot/since.yml +6 -0
  101. package/configurations/general/prose/vale/styles/gspot/straight-quotes.yml +11 -0
  102. package/configurations/general/prose/vale/styles/gspot/suspended-hyphens.yml +8 -0
  103. package/configurations/general/prose/vale/styles/gspot/symbols.yml +8 -0
  104. package/configurations/general/prose/vale/styles/gspot/time-ranges.yml +14 -0
  105. package/configurations/general/prose/vale/styles/gspot/url-prepositions.yml +10 -0
  106. package/configurations/general/prose/vale/styles/gspot/version-range.yml +8 -0
  107. package/configurations/general/repository/manifest.toml +24 -0
  108. package/configurations/general/secrets/gitleaks.toml +2 -0
  109. package/configurations/general/secrets/manifest.toml +125 -0
  110. package/configurations/general/secrets/rules/SECRETS.md +13 -0
  111. package/configurations/general/security/manifest.toml +77 -0
  112. package/configurations/general/security/rules/SECURITY.md +55 -0
  113. package/configurations/general/spelling/manifest.toml +46 -0
  114. package/configurations/general/structure/manifest.toml +70 -0
  115. package/configurations/infrastructure/ansible/manifest.toml +33 -0
  116. package/configurations/infrastructure/docker/manifest.toml +127 -0
  117. package/configurations/infrastructure/docker/rules/DOCKER.md +135 -0
  118. package/configurations/infrastructure/docker/trivyignore +2 -0
  119. package/configurations/infrastructure/github-actions/manifest.toml +76 -0
  120. package/configurations/infrastructure/github-actions/rules/GITHUB-ACTIONS.md +43 -0
  121. package/configurations/infrastructure/github-actions/zizmor.yml +3 -0
  122. package/configurations/infrastructure/nginx/manifest.toml +51 -0
  123. package/configurations/infrastructure/nginx/rules/NGINX.md +38 -0
  124. package/configurations/infrastructure/openapi/manifest.toml +50 -0
  125. package/configurations/infrastructure/openapi/rules/OPENAPI.md +39 -0
  126. package/configurations/infrastructure/xcode/manifest.toml +131 -0
  127. package/configurations/infrastructure/xcode/rules/XCODE.md +34 -0
  128. package/configurations/language/bash/manifest.toml +261 -0
  129. package/configurations/language/bash/rules/BASH.md +106 -0
  130. package/configurations/language/bash/rules/LANGUAGE.md +213 -0
  131. package/configurations/language/bash/rules/NAMING.md +62 -0
  132. package/configurations/language/bash/rules/OPERATIONS.md +77 -0
  133. package/configurations/language/bash/rules/SAFETY.md +222 -0
  134. package/configurations/language/bash/semgrep/bash.yml +30 -0
  135. package/configurations/language/css/manifest.toml +98 -0
  136. package/configurations/language/css/rules/CSS.md +28 -0
  137. package/configurations/language/css/rules/NAMING.md +17 -0
  138. package/configurations/language/css/rules/TAILWIND.md +26 -0
  139. package/configurations/language/css/stylelint-rule-names.json +89 -0
  140. package/configurations/language/html/manifest.toml +59 -0
  141. package/configurations/language/html/rules/HTML.md +27 -0
  142. package/configurations/language/html/rules/NAMING.md +16 -0
  143. package/configurations/language/javascript/eslint-presets.json +997 -0
  144. package/configurations/language/javascript/eslint-rule-names.json +299 -0
  145. package/configurations/language/javascript/eslint-runtime-names.json +61 -0
  146. package/configurations/language/javascript/manifest.toml +393 -0
  147. package/configurations/language/javascript/rules/BUN.md +13 -0
  148. package/configurations/language/javascript/rules/COMPONENTS.md +18 -0
  149. package/configurations/language/javascript/rules/DENO.md +15 -0
  150. package/configurations/language/javascript/rules/JAVASCRIPT.md +60 -0
  151. package/configurations/language/javascript/rules/NAMING.md +31 -0
  152. package/configurations/language/javascript/rules/NODE.md +21 -0
  153. package/configurations/language/javascript/rules/PLAYWRIGHT.md +34 -0
  154. package/configurations/language/javascript/semgrep/javascript.yml +84 -0
  155. package/configurations/language/markdown/manifest.toml +85 -0
  156. package/configurations/language/markdown/markdownlint-cli2.mjs +19 -0
  157. package/configurations/language/python/manifest.toml +621 -0
  158. package/configurations/language/python/rules/DESIGN.md +136 -0
  159. package/configurations/language/python/rules/FLOW.md +124 -0
  160. package/configurations/language/python/rules/NAMING.md +53 -0
  161. package/configurations/language/python/rules/PACKAGING.md +49 -0
  162. package/configurations/language/python/rules/PYTHON.md +136 -0
  163. package/configurations/language/python/rules/TYPING.md +132 -0
  164. package/configurations/language/sql/manifest.toml +68 -0
  165. package/configurations/language/sql/rules/NAMING.md +90 -0
  166. package/configurations/language/sql/rules/SQL.md +9 -0
  167. package/configurations/language/swift/manifest.toml +164 -0
  168. package/configurations/language/swift/rules/NAMING.md +88 -0
  169. package/configurations/language/swift/rules/SWIFT.md +134 -0
  170. package/configurations/language/swift/rules/SWIFTUI.md +61 -0
  171. package/configurations/language/swift/rules/UIKIT.md +99 -0
  172. package/configurations/language/swift/semgrep/swift.yml +126 -0
  173. package/configurations/language/typescript/eslint-presets.json +215 -0
  174. package/configurations/language/typescript/manifest.toml +72 -0
  175. package/configurations/language/typescript/rules/NAMING.md +73 -0
  176. package/configurations/language/typescript/rules/TYPESCRIPT.md +79 -0
  177. package/configurations/library/drizzle/manifest.toml +68 -0
  178. package/configurations/library/drizzle/rules/DRIZZLE.md +44 -0
  179. package/configurations/library/react-hook-form/manifest.toml +15 -0
  180. package/configurations/library/react-hook-form/rules/REACT-HOOK-FORM.md +48 -0
  181. package/configurations/library/swift-snapshot-testing/manifest.toml +32 -0
  182. package/configurations/library/tanstack-query/eslint-presets.json +21 -0
  183. package/configurations/library/tanstack-query/manifest.toml +26 -0
  184. package/configurations/library/tanstack-query/rules/TANSTACK-QUERY.md +41 -0
  185. package/configurations/library/testing-library/eslint-presets.json +191 -0
  186. package/configurations/library/testing-library/manifest.toml +47 -0
  187. package/configurations/library/translations/manifest.toml +40 -0
  188. package/configurations/library/translations/rules/NEXT-INTL.md +33 -0
  189. package/configurations/library/translations/rules/TRANSLATIONS.md +102 -0
  190. package/configurations/library/trpc/manifest.toml +14 -0
  191. package/configurations/library/trpc/rules/TRPC.md +43 -0
  192. package/configurations/library/zod/manifest.toml +25 -0
  193. package/configurations/library/zod/rules/ZOD.md +44 -0
  194. package/configurations/library/zustand/manifest.toml +18 -0
  195. package/configurations/library/zustand/rules/ZUSTAND.md +106 -0
  196. package/configurations/platform/cloudflare/manifest.toml +94 -0
  197. package/configurations/platform/cloudflare/rules/CLOUDFLARE.md +23 -0
  198. package/configurations/platform/cloudflare/semgrep/cloudflare.yml +12 -0
  199. package/configurations/platform/supabase/manifest.toml +112 -0
  200. package/configurations/platform/supabase/rules/SUPABASE.md +129 -0
  201. package/configurations/platform/supabase/semgrep/supabase.yml +60 -0
  202. package/configurations/testing/jest/manifest.toml +54 -0
  203. package/configurations/testing/pytest/manifest.toml +53 -0
  204. package/configurations/testing/swift-tests/manifest.toml +52 -0
  205. package/configurations/testing/swift-tests/rules/SWIFT-TESTS.md +79 -0
  206. package/configurations/testing/vitest/eslint-presets.json +22 -0
  207. package/configurations/testing/vitest/manifest.toml +69 -0
  208. package/configurations/testing/vitest/rules/VITEST.md +18 -0
  209. package/dist/LICENSE.md +201 -0
  210. package/dist/THIRD-PARTY-NOTICES.md +25 -0
  211. package/dist/eslint-rule-levels.json +10 -0
  212. package/dist/gspot.js +30740 -0
  213. package/dist/linkinator-program.js +65 -0
  214. package/dist/purgecss-program.js +51 -0
  215. package/dist/tool-versions.json +3 -0
  216. package/grammars/bash.wasm +0 -0
  217. package/grammars/css.wasm +0 -0
  218. package/grammars/html.wasm +0 -0
  219. package/grammars/javascript.wasm +0 -0
  220. package/grammars/licenses/tree-sitter-bash.txt +21 -0
  221. package/grammars/licenses/tree-sitter-css.txt +21 -0
  222. package/grammars/licenses/tree-sitter-html.txt +21 -0
  223. package/grammars/licenses/tree-sitter-javascript.txt +21 -0
  224. package/grammars/licenses/tree-sitter-python.txt +21 -0
  225. package/grammars/licenses/tree-sitter-swift.txt +21 -0
  226. package/grammars/licenses/tree-sitter-typescript.txt +21 -0
  227. package/grammars/python.wasm +0 -0
  228. package/grammars/swift.wasm +0 -0
  229. package/grammars/tsx.wasm +0 -0
  230. package/grammars/typescript.wasm +0 -0
  231. package/gspot.schema.json +45991 -0
  232. package/package.json +93 -5
@@ -0,0 +1,71 @@
1
+ rules:
2
+ - id: gspot.express.raw-query-interpolation
3
+ patterns:
4
+ - pattern: $DB.$METHOD(`...${req.$SOURCE.$FIELD}...`, ...)
5
+ - metavariable-regex:
6
+ metavariable: $METHOD
7
+ regex: ^(query|execute|raw|\$queryRawUnsafe)$
8
+ - metavariable-regex:
9
+ metavariable: $SOURCE
10
+ regex: ^(body|query|params)$
11
+ message: 'SQL injection risk: request data is interpolated into a database call.
12
+ Use parameterised queries or an ORM.'
13
+ languages:
14
+ - typescript
15
+ - javascript
16
+ severity: ERROR
17
+ metadata:
18
+ cwe:
19
+ - CWE-89
20
+ category: security
21
+ - id: gspot.express.unvalidated-redirect
22
+ patterns:
23
+ - pattern-either:
24
+ - pattern: res.redirect(req.body.$VALUE)
25
+ - pattern: res.redirect(req.query.$VALUE)
26
+ - pattern: res.redirect(req.params.$VALUE)
27
+ message: 'Open redirect: request data is passed directly to res.redirect().
28
+ Validate against an allowlist of URLs.'
29
+ languages:
30
+ - typescript
31
+ - javascript
32
+ severity: ERROR
33
+ metadata:
34
+ cwe:
35
+ - CWE-601
36
+ category: security
37
+ - id: gspot.express.res-send-raw-input
38
+ patterns:
39
+ - pattern-either:
40
+ - pattern: res.send(req.$SOURCE.$FIELD)
41
+ - pattern: res.send(`...${req.$SOURCE.$FIELD}...`)
42
+ - metavariable-regex:
43
+ metavariable: $SOURCE
44
+ regex: ^(body|query|params)$
45
+ message: 'Reflected XSS risk: request data is sent as text or HTML. Escape HTML
46
+ output or use res.json() to send JSON.'
47
+ languages:
48
+ - typescript
49
+ - javascript
50
+ severity: ERROR
51
+ metadata:
52
+ cwe:
53
+ - CWE-79
54
+ category: security
55
+ - id: gspot.express.no-stack-trace-in-response
56
+ patterns:
57
+ - pattern-either:
58
+ - pattern: 'res.send({..., stack: $ERR.stack, ...})'
59
+ - pattern: 'res.json({..., stack: $ERR.stack, ...})'
60
+ - pattern: 'res.status(...).send({..., stack: $ERR.stack, ...})'
61
+ - pattern: 'res.status(...).json({..., stack: $ERR.stack, ...})'
62
+ message: Stack traces in API responses leak internal implementation details. Log
63
+ the stack server-side and return a generic error message.
64
+ languages:
65
+ - typescript
66
+ - javascript
67
+ severity: ERROR
68
+ metadata:
69
+ cwe:
70
+ - CWE-209
71
+ category: security
@@ -0,0 +1,11 @@
1
+ [configuration]
2
+ title = "FastAPI"
3
+ requires = ["python"]
4
+ suggests = ["openapi"]
5
+ description = "Checks FastAPI route declarations with Ruff. Adds Semgrep request-handling rules when security is selected and suggests the OpenAPI configuration."
6
+
7
+ [detect]
8
+ dependencies = ["fastapi"]
9
+
10
+ [ruff_rules]
11
+ recommended = ["FAST001", "FAST002", "FAST003"]
@@ -0,0 +1,100 @@
1
+ # FastAPI
2
+
3
+ Structure, parameters, schemas, responses, errors, and the runtime of a Python project on FastAPI
4
+ and Pydantic v2.
5
+
6
+ ## Structure
7
+
8
+ <!-- level: all -->
9
+
10
+ Path operations adapt HTTP input to application calls and results to HTTP output; business logic
11
+ lives outside them. One main module creates the `FastAPI` object and wires routers, global
12
+ dependencies, middleware, exception handlers, and startup. Routers group related operations under
13
+ a prefix that does not end in `/`, and imports use their domain, `items.router` and `users.router`.
14
+ Database, SDK, and service clients stay out of import-time work, and nothing patches `sys.path`.
15
+
16
+ ```python
17
+ """Expose a fixed catalog with validated identifiers and public responses."""
18
+
19
+ from typing import Annotated
20
+
21
+ from fastapi import Path, FastAPI, APIRouter, HTTPException, status
22
+ from pydantic import BaseModel
23
+
24
+
25
+ class Item(BaseModel):
26
+ """Public catalog item."""
27
+
28
+ name: str
29
+
30
+
31
+ CATALOG = (Item(name="Notebook"), Item(name="Pencil"))
32
+ router = APIRouter(prefix="/items", tags=["items"])
33
+
34
+
35
+ @router.get("/{item_id}")
36
+ def get_item(item_id: Annotated[int, Path(ge=0)]) -> Item:
37
+ """Return one catalog item or a public not-found response."""
38
+ if item_id >= len(CATALOG):
39
+ raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Item not found")
40
+ return CATALOG[item_id]
41
+
42
+
43
+ app = FastAPI(openapi_url=None, docs_url=None, redoc_url=None)
44
+ app.include_router(router)
45
+ ```
46
+
47
+ ## Parameters
48
+
49
+ `Annotated[..., Query(...)]`, `Path`, `Body`, `Header`, `Cookie`, `Form`, `File`, or `Depends`;
50
+ a plain scalar supplies a query parameter. A parameter without a default requires a value, even when it
51
+ accepts `None`. Constraints such as `max_length` or `ge` belong at the boundary when the public interface requires them. Use a dependency for a check that needs a database or authorization state, not
52
+ a validator. Declare fixed routes such as `/users/me` before `/users/{user_id}`, and group
53
+ pagination or filter parameters into a query model with `extra="forbid"`.
54
+
55
+ Forms need `python-multipart`, and one operation never mixes JSON body fields with form fields
56
+ or files. Uploads arrive as `UploadFile`, bounded in count and size; `bytes` holds only small
57
+ values. Never use a filename as a filesystem path, a content type never proves safety, and never log uploaded
58
+ contents.
59
+
60
+ ## Schemas and responses
61
+
62
+ Pydantic models define the schemas where data enters or leaves. Use separate classes for create, read, and update shapes when
63
+ their fields differ. Never return an input with passwords or tokens as the response. Known JSON
64
+ shapes use nested models with typed containers. Use `UUID` for identifiers, timezone-aware instants across a
65
+ boundary, and `Decimal` for money. A partial update reads
66
+ `model_dump(exclude_unset=True)`, merges with the stored value, and validates the complete model,
67
+ because `model_copy(update=...)` validates nothing.
68
+
69
+ The return type defines the public schema; `response_model` serves a returned object of another
70
+ shape. A dedicated output model filters fields, never `response_model_exclude`, which still
71
+ documents the full model. A response validation failure shows a server bug. Fix the data or
72
+ the schema.
73
+
74
+ ## Status codes and errors
75
+
76
+ Non-default success codes go in the decorator with `fastapi.status` constants: 201 for creation,
77
+ 202 for accepted work, and 204 for a deliberate empty body. Raise `HTTPException` rather than returning it. Its `detail` supplies a public error message. Existence and
78
+ authorization checks answer alike, so responses do not reveal a private resource. Global exception
79
+ handlers return the standard error shape and never echo a validation error's body.
80
+
81
+ ## Runtime
82
+
83
+ - Declare a path operation or dependency `async def` when it awaits async libraries and `def` when it
84
+ calls blocking code; a blocking call inside `async def` stalls the event loop. Run CPU-heavy work in a worker process, not in `async def`.
85
+ - Dependencies carry request-scoped concerns: authentication, sessions, pagination, and
86
+ reusable validation. A `yield` dependency owns one resource, cleans up in `finally`, and
87
+ re-raises what it catches.
88
+ - Authentication that appears in OpenAPI uses the security utilities. A JSON Web Token (JWT) verifier allows an
89
+ explicit algorithm list and requires `exp` and `sub`.
90
+ - `BackgroundTasks` runs small follow-up work after the response; durable or heavy work goes to
91
+ a queue. Middleware holds cross-cutting HTTP behavior only, and the last middleware added runs
92
+ outermost.
93
+ - Turn OpenAPI and the interactive docs off unless a typed setting turns them on, and the schema
94
+ exposes no internal or admin routes.
95
+
96
+ ## Testing
97
+
98
+ Tests cover the HTTP contract through the test client: status codes, bodies, headers, and
99
+ authentication. Replace external systems with dependency overrides at the application
100
+ boundary. Tests cover the application rather than FastAPI's routing implementation.
@@ -0,0 +1,44 @@
1
+ rules:
2
+ - id: gspot.fastapi.cors-wildcard-with-credentials
3
+ patterns:
4
+ - pattern: $APP.add_middleware(CORSMiddleware, ..., allow_origins=["*"], ...,
5
+ allow_credentials=True, ...)
6
+ message: Every origin is allowed together with credentials, so any site reads an
7
+ authenticated response. List the origins.
8
+ languages:
9
+ - python
10
+ severity: ERROR
11
+ metadata:
12
+ cwe:
13
+ - CWE-942
14
+ category: security
15
+ - id: gspot.fastapi.debug-enabled
16
+ pattern: FastAPI(..., debug=True, ...)
17
+ message: Debug mode returns tracebacks to the client. Read the flag from
18
+ configuration, off by default.
19
+ languages:
20
+ - python
21
+ severity: ERROR
22
+ metadata:
23
+ cwe:
24
+ - CWE-489
25
+ category: security
26
+ - id: gspot.fastapi.exception-text-in-response
27
+ patterns:
28
+ - pattern-either:
29
+ - pattern: HTTPException(..., detail=str($ERROR), ...)
30
+ - pattern: HTTPException(..., detail=f"...{$ERROR}...", ...)
31
+ - pattern-inside: |-
32
+ try:
33
+ ...
34
+ except $TYPE as $ERROR:
35
+ ...
36
+ message: The text of an internal exception goes to the client. Log it, and
37
+ return a stable message.
38
+ languages:
39
+ - python
40
+ severity: ERROR
41
+ metadata:
42
+ cwe:
43
+ - CWE-209
44
+ category: security
@@ -0,0 +1,62 @@
1
+ {
2
+ "recommended": {
3
+ "package": "@darraghor/eslint-plugin-nestjs-typed",
4
+ "version": "7.5.5",
5
+ "source": "configs.flatRecommended",
6
+ "blocks": [
7
+ { "parser": true },
8
+ {
9
+ "parser": false,
10
+ "rules": {
11
+ "@darraghor/nestjs-typed/provided-injected-should-match-factory-parameters": "error",
12
+ "@darraghor/nestjs-typed/injectable-should-be-provided": [
13
+ "error",
14
+ { "src": ["src/**/*.ts"], "filterFromPaths": ["node_modules", ".test.", ".spec."] }
15
+ ],
16
+ "@darraghor/nestjs-typed/api-property-matches-property-optionality": "error",
17
+ "@darraghor/nestjs-typed/api-method-should-specify-api-response": "error",
18
+ "@darraghor/nestjs-typed/controllers-should-supply-api-tags": "error",
19
+ "@darraghor/nestjs-typed/api-enum-property-best-practices": "error",
20
+ "@darraghor/nestjs-typed/api-property-returning-array-should-set-array": "error",
21
+ "@darraghor/nestjs-typed/validation-pipe-should-use-forbid-unknown": "error",
22
+ "@darraghor/nestjs-typed/param-decorator-name-matches-route-param": "error",
23
+ "@darraghor/nestjs-typed/validated-non-primitive-property-needs-type-decorator": "error",
24
+ "@darraghor/nestjs-typed/validate-nested-of-array-should-set-each": "error",
25
+ "@darraghor/nestjs-typed/all-properties-are-whitelisted": "error",
26
+ "@darraghor/nestjs-typed/all-properties-have-explicit-defined": "error",
27
+ "@darraghor/nestjs-typed/api-methods-should-be-guarded": "off",
28
+ "@darraghor/nestjs-typed/api-method-should-specify-api-operation": "off",
29
+ "@darraghor/nestjs-typed/sort-module-metadata-arrays": "off",
30
+ "@darraghor/nestjs-typed/no-duplicate-decorators": "error",
31
+ "@darraghor/nestjs-typed/use-injectable-provided-token": "error",
32
+ "@darraghor/nestjs-typed/api-property-should-have-api-extra-models": "error",
33
+ "@darraghor/nestjs-typed/api-operation-summary-description-capitalized": "error",
34
+ "@darraghor/nestjs-typed/use-dependency-injection": "off",
35
+ "@darraghor/nestjs-typed/use-correct-endpoint-naming-convention": "off",
36
+ "@darraghor/nestjs-typed/forward-ref-injection-should-use-wrapper-type": "error",
37
+ "@darraghor/nestjs-typed/swagger-file-upload-should-be-documented": "error",
38
+ "@darraghor/nestjs-typed/uploaded-file-should-be-validated": "error"
39
+ }
40
+ }
41
+ ]
42
+ },
43
+ "noSwagger": {
44
+ "package": "@darraghor/eslint-plugin-nestjs-typed",
45
+ "version": "7.5.5",
46
+ "source": "configs.flatNoSwagger",
47
+ "blocks": [
48
+ {
49
+ "parser": false,
50
+ "rules": {
51
+ "@darraghor/nestjs-typed/api-property-matches-property-optionality": "off",
52
+ "@darraghor/nestjs-typed/api-method-should-specify-api-response": "off",
53
+ "@darraghor/nestjs-typed/api-method-should-specify-api-operation": "off",
54
+ "@darraghor/nestjs-typed/controllers-should-supply-api-tags": "off",
55
+ "@darraghor/nestjs-typed/api-enum-property-best-practices": "off",
56
+ "@darraghor/nestjs-typed/api-property-returning-array-should-set-array": "off",
57
+ "@darraghor/nestjs-typed/swagger-file-upload-should-be-documented": "off"
58
+ }
59
+ }
60
+ ]
61
+ }
62
+ }
@@ -0,0 +1,52 @@
1
+ [prefix_collisions]
2
+ kinds = ["controller", "service", "module", "guard", "pipe", "filter", "interceptor", "middleware", "decorator", "gateway", "resolver", "repository", "entity", "dto", "strategy", "provider"]
3
+
4
+ [configuration]
5
+ title = "NestJS"
6
+ requires = ["typescript"]
7
+ suggests = []
8
+ description = "A NestJS service: the compiler options decorators need, the NestJS plugin rules for providers, routes, and DTOs, and no circular modules."
9
+
10
+ [detect]
11
+ dependencies = ["@nestjs/core"]
12
+ filenames = ["nest-cli.json"]
13
+
14
+ [files]
15
+ filenames = ["nest-cli.json"]
16
+
17
+ [[tool]]
18
+ name = "@darraghor/eslint-plugin-nestjs-typed"
19
+ rule_prefix = "@darraghor/nestjs-typed"
20
+ kind = "library"
21
+ version = "7.5.5"
22
+ npm = "@darraghor/eslint-plugin-nestjs-typed"
23
+
24
+ [eslint]
25
+ all_level_rules = ["@darraghor/nestjs-typed/api-operation-summary-description-capitalized"]
26
+
27
+ [eslint.presets.recommended]
28
+ package = "@darraghor/eslint-plugin-nestjs-typed"
29
+ source = "configs.flatRecommended"
30
+
31
+ [eslint.presets.noSwagger]
32
+ package = "@darraghor/eslint-plugin-nestjs-typed"
33
+ source = "configs.flatNoSwagger"
34
+
35
+ [[eslint.rules_off]]
36
+ rules = ["gspot/no-trivial-files", "gspot/no-trivial-functions"]
37
+ files = ["**/*.module.ts"]
38
+ reason = "A Nest module is an empty decorated class that registers providers and controllers, which is the shape Nest asks for."
39
+
40
+ [[eslint.selectors]]
41
+ selector = "CallExpression[callee.name='forwardRef']"
42
+ message = "forwardRef papers over two modules that import each other. Move what both need into a third module."
43
+
44
+ [[eslint.selectors]]
45
+ selector = "Decorator[expression.callee.name=/^(Res|Response)$/]:not(:has(Property[key.name='passthrough'][value.value=true]))"
46
+ message = "Taking the response object turns off interceptors and the return value. Return the value, or pass { passthrough: true }."
47
+
48
+ [[tool_file]]
49
+ target = ".gspot/config/eslint.config.mjs"
50
+ tool = "eslint"
51
+ fragment = true
52
+ required_tools = ["@darraghor/eslint-plugin-nestjs-typed"]
@@ -0,0 +1,44 @@
1
+ # NestJS
2
+
3
+ These rules cover NestJS modules, controllers, providers, validation, configuration, and tests.
4
+
5
+ ## Request handling
6
+
7
+ - Return the documented HTTP status. Do not report a failed operation as a successful response.
8
+ - Validate body, query, and route parameters before using them. Configure `ValidationPipe`
9
+ transformation and unknown-field handling for the declared input contract.
10
+ - Do not expose password hashes, tokens, or internal fields in responses.
11
+
12
+ ## Providers and lifecycle
13
+
14
+ - Register each provider with its intended owner. Repeated registration can create distinct instances.
15
+ - Request-scoped dependencies propagate request scope to their consumers. Check lifetime and
16
+ resource costs before selecting that scope.
17
+ - Close connections and timers through the application lifecycle, such as `OnModuleDestroy`.
18
+
19
+ ## Configuration and security
20
+
21
+ - Fail startup when required configuration has missing or malformed values.
22
+ - Use guards for route authorization. Enforce additional permissions at each protected operation
23
+ when one request performs several operations or the service has non-HTTP callers.
24
+ - Guards run before pipes. Do not assume guard inputs have passed DTO transformation or validation.
25
+ - Set request-size limits, security headers, and rate limits for the exposed application.
26
+
27
+ ## Feature organization
28
+
29
+ <!-- level: all -->
30
+
31
+ - Give each feature one module and export only providers consumed by other features.
32
+ - Inject dependencies through constructors instead of constructing them inside consumers.
33
+ - Define the versioning contract before publishing a public API.
34
+ - Keep request DTOs distinct from persistence entities and map between them explicitly.
35
+
36
+ ## Tests
37
+
38
+ - Use `Test.createTestingModule` and `overrideProvider` to isolate service dependencies.
39
+ - Exercise HTTP behavior with the real pipes, guards, and filters.
40
+ - Do not mock the class under test or assert on private methods.
41
+ - Close test applications in teardown.
42
+
43
+ See Nest's [response handling](https://docs.nestjs.com/controllers) and
44
+ [authorization guidance](https://docs.nestjs.com/security/authorization).
@@ -0,0 +1,73 @@
1
+ {
2
+ "recommended": {
3
+ "package": "@next/eslint-plugin-next",
4
+ "version": "16.3.8",
5
+ "source": "configs.core-web-vitals",
6
+ "blocks": [
7
+ {
8
+ "parser": false,
9
+ "rules": {
10
+ "@next/next/google-font-display": "warn",
11
+ "@next/next/google-font-preconnect": "warn",
12
+ "@next/next/next-script-for-ga": "warn",
13
+ "@next/next/no-async-client-component": "warn",
14
+ "@next/next/no-before-interactive-script-outside-document": "warn",
15
+ "@next/next/no-css-tags": "warn",
16
+ "@next/next/no-head-element": "warn",
17
+ "@next/next/no-html-link-for-pages": "error",
18
+ "@next/next/no-img-element": "warn",
19
+ "@next/next/no-location-assign-relative-destination": "warn",
20
+ "@next/next/no-page-custom-font": "warn",
21
+ "@next/next/no-styled-jsx-in-document": "warn",
22
+ "@next/next/no-sync-scripts": "error",
23
+ "@next/next/no-title-in-document-head": "warn",
24
+ "@next/next/no-typos": "warn",
25
+ "@next/next/no-unwanted-polyfillio": "warn",
26
+ "@next/next/inline-script-id": "error",
27
+ "@next/next/no-assign-module-variable": "error",
28
+ "@next/next/no-document-import-in-page": "error",
29
+ "@next/next/no-duplicate-head": "error",
30
+ "@next/next/no-head-import-in-document": "error",
31
+ "@next/next/no-script-component-in-head": "error"
32
+ }
33
+ }
34
+ ]
35
+ },
36
+ "refresh": {
37
+ "package": "eslint-plugin-react-refresh",
38
+ "version": "0.5.7",
39
+ "source": "configs.next",
40
+ "blocks": [
41
+ {
42
+ "parser": false,
43
+ "rules": {
44
+ "react-refresh/only-export-components": [
45
+ "error",
46
+ {
47
+ "allowExportNames": [
48
+ "experimental_ppr",
49
+ "dynamic",
50
+ "dynamicParams",
51
+ "revalidate",
52
+ "fetchCache",
53
+ "runtime",
54
+ "preferredRegion",
55
+ "maxDuration",
56
+ "metadata",
57
+ "generateMetadata",
58
+ "viewport",
59
+ "generateViewport",
60
+ "generateImageMetadata",
61
+ "generateSitemaps",
62
+ "generateStaticParams",
63
+ "instant",
64
+ "contentType",
65
+ "size"
66
+ ]
67
+ }
68
+ ]
69
+ }
70
+ }
71
+ ]
72
+ }
73
+ }
@@ -0,0 +1,119 @@
1
+ route_files = ["page", "layout", "template", "default", "loading", "error", "not-found", "global-error", "route", "middleware", "proxy"]
2
+ allowed_words = ["Next.js"]
3
+ generated = ["next-env.d.ts"]
4
+
5
+ [[naming.override]]
6
+ paths = ["**/app/**", "**/pages/**"]
7
+ categories = ["files"]
8
+ allowed_names = ["instrumentation", "sitemap", "robots", "manifest", "opengraph-image", "icon", "apple-icon", "_app", "_document", "_error", "404", "500"]
9
+ reason = "Next.js names these files."
10
+
11
+ [[naming.override]]
12
+ paths = ["**"]
13
+ languages = ["typescript", "javascript"]
14
+ categories = ["functions", "methods", "variables"]
15
+ allowed_names = ["getStaticProps", "getServerSideProps", "generateMetadata", "generateStaticParams", "generateViewport"]
16
+ reason = "Next.js discovers these data and metadata exports by name."
17
+
18
+ [configuration]
19
+ title = "Next.js"
20
+ requires = ["typescript", "react", "react-dom"]
21
+ suggests = ["css"]
22
+ description = "A Next.js app: the framework and hooks rules of ESLint, and server code marked as server only. Route segments serve one thing, and the configuration turns no build check off."
23
+
24
+ [detect]
25
+ dependencies = ["next"]
26
+
27
+ [files]
28
+ paths = ["**/next.config.js", "**/next.config.mjs", "**/next.config.ts"]
29
+
30
+ [[tool]]
31
+ name = "next"
32
+ system = true
33
+ min_version = "15.5.0"
34
+ version_command = ["--version"]
35
+
36
+ [[tool]]
37
+ name = "@next/eslint-plugin-next"
38
+ rule_prefix = "@next/next"
39
+ kind = "library"
40
+ version = "16.3.8"
41
+ npm = "@next/eslint-plugin-next"
42
+
43
+ [[check]]
44
+ name = "tsc"
45
+ tool = "next"
46
+ example = "The TypeScript declaration `const count: number = \"one\";` reports an incompatible assignment. Correct it to `const count: number = 1;` when the contract requires a number."
47
+ level = "recommended"
48
+ stage = "push"
49
+ runs = "scope"
50
+ instead_of = "typescript/tsc"
51
+ summary = "Has Next.js write its types, then type-checks the app with the strict compiler options."
52
+ why = "A fresh clone holds no next-env.d.ts and no route types, so a plain tsc run fails on imports the framework resolves."
53
+ help = "Read the first error tsc prints and fix that file; later errors are often the same mistake."
54
+
55
+ [[check]]
56
+ name = "build"
57
+ tool = "next"
58
+ example = "A Next.js page importing a nonexistent component fails the project build. Restore the component or correct the import path and rerun the configured build."
59
+ level = "all"
60
+ stage = "push"
61
+ runs = "scope"
62
+ needs = ["build"]
63
+ summary = "Builds the app with next build at all when its scope contains an app or pages tree."
64
+ why = "Some mistakes show only at build time: a server import in a client file, or a page that cannot be prerendered."
65
+ help = "Run next build and read the first error it prints."
66
+
67
+ [check.files]
68
+ paths = ["**/app/**", "**/pages/**"]
69
+
70
+ [[check]]
71
+ name = "route-segments"
72
+ example = "A Next.js segment containing both `page.tsx` and `route.ts` reports conflicting route ownership. Move the route handler into a separate segment, such as `api`, and update its callers."
73
+ level = "recommended"
74
+ stage = "commit"
75
+ runs = "once"
76
+ summary = "Checks that no route segment holds both a page and a route handler."
77
+ why = "This commit check finds route conflicts before next build and also runs at recommended, where the build check does not."
78
+ help = "Move the route handler into a segment of its own, such as an api folder."
79
+
80
+ [[check]]
81
+ name = "next-config"
82
+ example = "Setting `typescript.ignoreBuildErrors` to `true` in Next.js configuration reports a disabled type gate. Remove the switch and correct the type errors before building."
83
+ level = "recommended"
84
+ stage = "commit"
85
+ runs = "once"
86
+ summary = "Checks that the framework configuration turns no build check off and puts no secret into the client environment."
87
+ why = "A build that ignores lint and type errors ships them, and a key under env is readable by every visitor."
88
+ help = "Remove the switch, and read the secret on the server."
89
+
90
+ [[check]]
91
+ name = "version-pairs"
92
+ example = "Different installed versions of `next` and its lint package report an alignment finding. Install the same version of both and update the lockfile with the package manager."
93
+ level = "recommended"
94
+ stage = "commit"
95
+ runs = "once"
96
+ summary = "Checks that Next.js and its lint packages use the same installed version."
97
+ why = "A lint package a version behind flags what the framework allows and allows what it removed."
98
+ help = "Move both packages to the same version."
99
+
100
+ [eslint]
101
+ all_level_rules = ["@next/next/next-script-for-ga", "@next/next/no-html-link-for-pages", "@next/next/no-img-element", "@next/next/no-page-custom-font"]
102
+
103
+ [eslint.presets.recommended]
104
+ package = "@next/eslint-plugin-next"
105
+ source = "configs.core-web-vitals"
106
+
107
+ [eslint.presets.refresh]
108
+ package = "eslint-plugin-react-refresh"
109
+ source = "configs.next"
110
+
111
+ [[eslint.rules_off]]
112
+ rules = ["gspot/no-trivial-files"]
113
+ reason = "Next.js discovers route files by name, so each file can hold one export in its own folder."
114
+
115
+ [[tool_file]]
116
+ target = ".gspot/config/eslint.config.mjs"
117
+ tool = "eslint"
118
+ fragment = true
119
+ required_tools = ["@next/eslint-plugin-next"]
@@ -0,0 +1,43 @@
1
+ # Next.js
2
+
3
+ Preserve the project's router, installed Next.js and React versions, runtime, and deployment
4
+ adapter. App Router guidance applies only to App Router routes.
5
+
6
+ ## Server and client ownership
7
+
8
+ Keep privileged operations and credentials on the server. Send only authorized fields to the
9
+ browser. That includes query hydration and Server Component props. A hidden control, type, or filename
10
+ does not control access. A client entry includes its imports in the client graph; keep it small
11
+ and compose server-rendered children into it.
12
+
13
+ Validate and authorize every mutation at its server entry. Routes, actions, and RPC procedures
14
+ share the same domain operation. Initial server reads do not HTTP-fetch the application's own
15
+ Route Handler. Rendering, `GET` requests, and prefetching perform no writes.
16
+
17
+ See [Server and Client Components](https://nextjs.org/docs/app/getting-started/server-and-client-components).
18
+
19
+ ## Loading and failures
20
+
21
+ Put a loading boundary around the section that waits. Keep useful content mounted during refresh,
22
+ and reset pending state when the selected resource changes. Start independent work early without
23
+ moving protected reads before authorization.
24
+
25
+ Decide status, headers, cookies, redirects, and not-found behavior before streaming commits the
26
+ response. Preserve framework control-flow exceptions. Check direct load, client navigation,
27
+ refresh, Back, and failed prefetch; those paths need not share the same state.
28
+
29
+ See [streaming](https://nextjs.org/docs/app/guides/streaming).
30
+
31
+ ## Cache contracts
32
+
33
+ Check whether the project enables Cache Components before choosing APIs. Above a cached operation,
34
+ state who may read it, its key, lifetime, and invalidation path. Include identity, tenant, locale,
35
+ filters, and permissions where they affect results; session tokens stay out of keys.
36
+
37
+ Default private data to uncached until an isolation design exists. Never let a cached decision
38
+ retain revoked access. Clear private browser caches on logout. Invalidate after the write commits
39
+ and before a terminating redirect; a failed refresh must not retry the committed write.
40
+ Next.js and a client query cache need separate reconciliation.
41
+
42
+ See [caching](https://nextjs.org/docs/app/getting-started/caching)
43
+ and [revalidation](https://nextjs.org/docs/app/getting-started/revalidating).