@gspothq/cli 0.0.0-stage → 0.1.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 (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,40 @@
1
+ [configuration]
2
+ title = "Translations"
3
+ requires = ["javascript"]
4
+ description = "Translated interfaces: no literal text in components, and message files that parse and stay complete in every locale."
5
+
6
+ [detect]
7
+ dependencies = ["next-intl", "react-i18next", "i18next", "react-intl", "@lingui/core"]
8
+
9
+ [[tool]]
10
+ name = "eslint-plugin-i18next"
11
+ rule_prefix = "i18next"
12
+ kind = "library"
13
+ version = "6.1.5"
14
+ npm = "eslint-plugin-i18next"
15
+
16
+ [[check]]
17
+ name = "messages"
18
+ example = "If the base locale defines `welcome` but another required locale does not, the check reports the missing key. Add the translated message with matching interpolation arguments."
19
+ level = "recommended"
20
+ stage = "push"
21
+ runs = "scope"
22
+ summary = "Checks next-intl JSON/ICU message files under translations.messages_folder: each message parses, none is empty, no key holds a dot, and every locale holds every key of the base."
23
+ why = "This check compares every locale with the base locale, so missing keys and different interpolation arguments are found across files."
24
+ help = "Correct the message, or add the missing key to the locale."
25
+
26
+ [check.when]
27
+ dependencies = ["next-intl"]
28
+ setting = "translations.messages_folder"
29
+
30
+ [rules."NEXT-INTL.md"]
31
+ dependencies = ["next-intl"]
32
+
33
+ [eslint]
34
+ all_level_rules = ["i18next/no-literal-string"]
35
+
36
+ [[tool_file]]
37
+ target = ".gspot/config/eslint.config.mjs"
38
+ tool = "eslint"
39
+ fragment = true
40
+ required_tools = ["eslint-plugin-i18next"]
@@ -0,0 +1,33 @@
1
+ # next-intl
2
+
3
+ Rules for `next-intl` in a Next.js App Router application. The locale, catalog, and right-to-left (RTL) rules that
4
+ hold for any framework appear in the shared translation rules; these add what the library dictates.
5
+
6
+ ## Configuration
7
+
8
+ - One request configuration module owns locale resolution, message loading, time zone, and the
9
+ `now` reference. It validates the candidate locale against the supported list before building a
10
+ catalog import path. Nothing else resolves a locale.
11
+ - Define routing in one module: locales, default locale, prefix strategy, and pathnames
12
+ that both the proxy and the navigation helpers import.
13
+ - Use the library's navigation helpers such as `Link`, `redirect`, `usePathname`, `useRouter` for every
14
+ internal link so locale prefixes and alternate metadata stay correct. Never `next/link` directly
15
+ in a localized route.
16
+
17
+ ## Server and client boundaries
18
+
19
+ - Use `getTranslations` in async Server Components. Non-async components can use
20
+ `useTranslations`; the library selects its server or client implementation from the render context.
21
+ - Keep `now` and `timeZone` identical between the server render and the first browser render so
22
+ formatted dates and relative times hydrate without mismatch.
23
+ - Generate `alternates` and `canonical` metadata from the routing definition. Do not hand-write
24
+ locale URLs in metadata.
25
+
26
+ ## Messages
27
+
28
+ - Handle missing messages through `onError` and choose the visible error text through
29
+ `getMessageFallback`. The default reports an error and returns a key-based fallback.
30
+ Configure client callbacks in a Client Component because functions cannot cross the server boundary.
31
+
32
+ See [request configuration](https://next-intl.dev/docs/usage/configuration) and
33
+ [Server and Client Components](https://next-intl.dev/docs/environments/server-client-components).
@@ -0,0 +1,102 @@
1
+ # Translations
2
+
3
+ Internationalization, or i18n, lets an application support different languages and regional formats.
4
+ A locale names the language and formatting conventions, message catalogs hold the translated text,
5
+ and International Components for Unicode (ICU) MessageFormat adds placeholders, plurals, and selection to messages.
6
+
7
+ ## Locales and routing
8
+
9
+ - Define the supported locales, the default locale, and locale selection in one place, with Best Current Practice (BCP) 47
10
+ tags such as `en-GB`.
11
+ - Check a locale from a URL, cookie, or header against the supported list before loading messages,
12
+ and build catalog import paths from checked values only. Unsupported input gets the documented
13
+ default or not-found behavior, not a failed dynamic import.
14
+ - Choose the routing deliberately. A public site with locale-prefixed URLs needs locale-aware links,
15
+ redirects, canonical URLs, alternate-language metadata, and sitemap entries. An application
16
+ without indexed locale URLs can select the language by cookie or saved preference.
17
+ - Define the precedence among the URL, the saved preference, the negotiated header, and the
18
+ default, without redirect loops.
19
+ - A request-local i18n configuration owns resolution, and request handling and displayed content
20
+ use the same locale. Never keep a user's locale in mutable server module state, and partition
21
+ localized data in server, browser, and content delivery network (CDN) caches.
22
+
23
+ ## Messages and catalogs
24
+
25
+ Keys name stable product concepts, so a reader finds the owning feature. Never build a key from an
26
+ arbitrary server string, a display name, or an English source sentence.
27
+
28
+ - Group related messages under one namespace per feature. Share a message only when its meaning
29
+ and grammatical role match everywhere.
30
+ - Translators get complete sentences or clauses. Never concatenate translated fragments or
31
+ pluralize by appending an English suffix; use ICU arguments, plurals, selects, and rich text
32
+ through the library's rendering API.
33
+ - Placeholder names belong to the message contract, so a change to one updates every caller and
34
+ catalog together.
35
+ - Rich tags stay stable and map to trusted components. Never accept executable markup from a
36
+ translator or a provider response.
37
+ - Translate safe validation and error codes where the application presents them. A raw schema exception, SQL
38
+ message, or provider error does not supply a translation key.
39
+ - User-generated content, proper names, identifiers, and developer logs supply interpolation data,
40
+ not message keys, and stay untranslated.
41
+
42
+ Translate every application-authored string the application displays to the user. That covers headings, buttons,
43
+ placeholders, toasts, validation errors, accessible names, image alternatives, navigation,
44
+ metadata, list status controls, and the empty, error, and loading states.
45
+
46
+ Plural categories can differ by locale while every locale takes the same input value. Configure
47
+ the catalog loader for the application's format and namespace layout.
48
+
49
+ Translations land in the same change as their call sites; an incomplete locale leaves the
50
+ supported list instead. Checks validate catalog structure. List the locales and screens for the
51
+ user to check for linguistic accuracy, dynamic keys, and untranslated UI text. Missing
52
+ show keys during development, and make a production fallback intentional and observable, never
53
+ a silent `catch` that hides a missing catalog.
54
+
55
+ ## Rendering and formatting
56
+
57
+ - Use the framework's established i18n library. Translate on the server where rendering happens
58
+ there, and give each client provider the scoped messages its interactive children need, never
59
+ every locale or the whole catalog.
60
+ - Format numbers, currencies, dates, relative times, and time zones through locale-aware APIs.
61
+ Never infer currency or time zone from language alone.
62
+ - Use an explicit product time-zone policy. Define when relative timestamps refresh.
63
+ - Localized public routes get localized metadata, and each alternate link points to the matching
64
+ resource in that locale, including a resource missing in some languages. Never generate an
65
+ alternate URL that redirects forever or describes missing content.
66
+
67
+ ## Changing the language
68
+
69
+ 1. Keep the current resource, relevant search parameters, and hash where the routing supports them.
70
+ 2. Persist the preference through the validated write owner when the product promises persistence.
71
+ 3. Navigate through the locale-aware routing, so server-rendered content, client labels, and
72
+ metadata agree.
73
+ 4.
74
+
75
+ Refresh locale-dependent query keys and results instead of keeping translated data under an
76
+ identity without the locale. 5. Keep focus and scroll position sensible. 6. Report a failed preference write; never show a completed selection that reverts on refresh.
77
+
78
+ A language menu names each language with a clear label, commonly its native name, not a flag.
79
+ Treat region and currency as separate choices when the product offers them.
80
+
81
+ ## Right-to-left layout
82
+
83
+ Set the document's `lang` and `dir` for the selected locale. List supported right-to-left (RTL)
84
+ locales and affected screens for the user to check. Use logical spacing and alignment properties, and mirror an icon or image only when
85
+ its meaning requires it. Focus order and horizontal scrolling follow the direction, and record data
86
+ never reverses to display RTL text. Include identifiers and URLs inside translated sentences in that list because their directions mix.
87
+
88
+ ## Verification
89
+
90
+ List the default locale, another supported locale, and affected screens for the user to check.
91
+ Include long translations, other writing systems, plural cases, rich text, form errors, locale
92
+ selection after refresh, localized navigation, and screen-reader labels. A new RTL locale adds its
93
+ layout and mixed-direction text to that list.
94
+
95
+ ## References
96
+
97
+ Use documentation matching the installed release and enabled features.
98
+
99
+ | Topic | Primary source |
100
+ | -------------------- | --------------------------------------------------------------------------------------- |
101
+ | ICU MessageFormat | [ICU MessageFormat](https://unicode-org.github.io/icu/userguide/format_parse/messages/) |
102
+ | BCP 47 language tags | [Request for Comments (RFC) 5646](https://www.rfc-editor.org/rfc/rfc5646) |
@@ -0,0 +1,14 @@
1
+ allowed_words = ["tRPC"]
2
+
3
+ [configuration]
4
+ title = "tRPC"
5
+ requires = ["javascript"]
6
+ description = "tRPC routers: every procedure validates its input, and client code imports the declared server module as a type only. Name your server module `server` in `[[architecture.module]]`."
7
+
8
+ [detect]
9
+ dependencies = ["@trpc/server"]
10
+
11
+ [[eslint.selectors]]
12
+ selector = "CallExpression[callee.property.name=/^(query|mutation|subscription)$/]:not(:has(CallExpression[callee.property.name='input']))"
13
+ message = "Give the procedure an input schema before its resolver, even when the input is nothing."
14
+ role = "routers"
@@ -0,0 +1,43 @@
1
+ # tRPC
2
+
3
+ Use the client integration the project has. Do not mix the classic and TanStack-native clients.
4
+ Check the installed release before using a version-specific API.
5
+
6
+ ## Request ownership
7
+
8
+ Create context from verified identity for each request. Context creation can run during prefetching,
9
+ so it performs no writes. Each operation in a batch authorizes itself; a batch does not create a transaction.
10
+ Authentication proves identity, and resource authorization proves access to the named resource.
11
+ Neither a valid input nor a procedure named public proves permission.
12
+
13
+ Direct callers receive verified context explicitly. Never store a session in a process-wide
14
+ variable or cast a direct caller into an HTTP request. Procedures that share logic call the same
15
+ authorized domain operation rather than calling each other.
16
+
17
+ See [authorization](https://trpc.io/docs/server/authorization)
18
+ and [server callers](https://trpc.io/docs/server/server-side-calls).
19
+
20
+ ## Client state and transport
21
+
22
+ Use generated query options and keys. A mutation key identifies a write, not the queries to
23
+ invalidate. Server rendering and browser consumption use the same QueryClient and serialization
24
+ contract; private results stay out of dehydration. A rendered server total and client-query rows
25
+ need one data owner or coordinated refresh.
26
+
27
+ Cookie-setting operations use a transport that can finish headers before streaming. Configure
28
+ serialization at both ends and preserve transformer metadata. Bound batch sizes and expensive
29
+ work. One layer owns retries, and retries of a write require an idempotency contract.
30
+
31
+ See [TanStack integration](https://trpc.io/docs/client/tanstack-react-query/setup)
32
+ and [links](https://trpc.io/docs/client/links).
33
+
34
+ ## Cancellation and events
35
+
36
+ Forward cancellation to the work owner and release listeners and streams. A disconnected client
37
+ does not prove that a write failed; recover its state by operation identity before retrying.
38
+ Late responses must not update another resource or session.
39
+
40
+ Subscriptions reauthorize after identity changes. Resumable events use stable identifiers,
41
+ deduplicate replay, and restore a fresh snapshot when retention has expired.
42
+
43
+ See [subscriptions](https://trpc.io/docs/server/subscriptions).
@@ -0,0 +1,25 @@
1
+ allowed_words = ["Zod"]
2
+
3
+ [configuration]
4
+ title = "Zod"
5
+ requires = ["javascript"]
6
+ description = "Zod schemas: ESLint rules reject unsafe schema APIs and recommend replacements for deprecated APIs."
7
+
8
+ [detect]
9
+ dependencies = ["zod"]
10
+
11
+ [[tool]]
12
+ name = "eslint-plugin-zod"
13
+ rule_prefix = "zod"
14
+ kind = "library"
15
+ version = "4.12.0"
16
+ npm = "eslint-plugin-zod"
17
+
18
+ [eslint]
19
+ all_level_rules = ["zod/no-any-schema", "zod/no-native-enum", "zod/prefer-meta-last", "zod/prefer-strict-object"]
20
+
21
+ [[tool_file]]
22
+ target = ".gspot/config/eslint.config.mjs"
23
+ tool = "eslint"
24
+ fragment = true
25
+ required_tools = ["eslint-plugin-zod"]
@@ -0,0 +1,44 @@
1
+ # Zod
2
+
3
+ Check the installed release and its consumers before choosing an API. Put a runtime schema with
4
+ the feature that owns the contract. Infer input and output types from it rather than keeping a
5
+ second handwritten contract.
6
+
7
+ ## Validate boundaries
8
+
9
+ Parse values at the boundary that receives them and pass the parsed result inward. Static types,
10
+ a constructed validator, and successful client validation do not validate a server request.
11
+ An invalid provider response shows an integration failure, not invalid user input. A valid identifier
12
+ proves no access.
13
+
14
+ Choose thrown or returned validation issues to match the boundary. Async checks need async parsing;
15
+ a safe parse does not catch exceptions thrown by custom code or transport decoding. Keep resource
16
+ limits on collections and nesting. Preserve original bytes when signatures depend on them.
17
+
18
+ See [parsing and inferred types](https://zod.dev/basics).
19
+
20
+ ## Patches and normalization
21
+
22
+ Derive a patch from fields the caller may edit, not the whole persistence row. Keep omission,
23
+ undefined, null, and empty input distinct. Defaults do not silently turn absence into a write.
24
+ Normalize only where the contract permits it; never trim signed values, passwords, or exact-byte
25
+ identifiers. Coercion must not turn an empty required number into zero.
26
+
27
+ Select response fields before returning them. A loose object schema does not protect private data.
28
+ Pass request-specific state to validation. Do not capture it in a process-wide schema.
29
+
30
+ See [schema APIs](https://zod.dev/api).
31
+
32
+ ## Errors and published contracts
33
+
34
+ Return safe field paths and stable codes. Keep private values out of issues and error messages;
35
+ do not enable raw input reporting for private payloads. Translate at the request or presentation
36
+ boundary without mutating global locale state for one request.
37
+
38
+ A JSON Schema projection cannot represent every runtime contract. Keep runtime validation and
39
+ verify the exported dialect against meaningful examples. Use an explicit transport schema for
40
+ non-JSON values instead of allowing every value in the projection. Regenerate consumers when the
41
+ contract changes, and check omitted fields, defaults, patches, and date handling after an upgrade.
42
+
43
+ See [error customization](https://zod.dev/error-customization)
44
+ and [JSON Schema](https://zod.dev/json-schema).
@@ -0,0 +1,18 @@
1
+ allowed_words = ["Zustand"]
2
+
3
+ [configuration]
4
+ title = "Zustand"
5
+ requires = ["javascript"]
6
+ description = "Zustand stores: a store is created in a store file, and a component reads it through a selector."
7
+
8
+ [detect]
9
+ dependencies = ["zustand"]
10
+
11
+ [[eslint.selectors]]
12
+ selector = "CallExpression[callee.name=/^use[A-Z]\\w*Store$/][arguments.length=0]"
13
+ message = "Pass a selector to the store hook, so the component renders when its slice changes and at no other time."
14
+
15
+ [[tool_file]]
16
+ target = ".gspot/config/eslint.config.mjs"
17
+ tool = "eslint"
18
+ fragment = true
@@ -0,0 +1,106 @@
1
+ # Zustand
2
+
3
+ Zustand holds client state that several components share when local or form state cannot serve them.
4
+ Fetched server data stays in the query cache.
5
+
6
+ ## Scope and initialize the store
7
+
8
+ - Create a store through a factory, with `createStore` from `zustand/vanilla` when a context
9
+ provider owns the instance. Report an explicit error for a missing required provider.
10
+ - The provider keeps one instance for its mounted lifetime and exposes it through React context.
11
+ Consumers call `useStore(store, selector)`. In a Next.js App Router project, declare this provider as a
12
+ Client Component.
13
+ - In a server-rendered app, create request-dependent stores per request. Never share a store
14
+ initialized with one user's identity across requests.
15
+ - An action called outside React uses the intended store instance, passed in, never a hidden
16
+ global store that bypasses request or provider scope.
17
+ - In a server-rendered app, the provider takes an initial snapshot that matches the first browser
18
+ render. Browser storage, random values, and current timestamps stay out of that snapshot.
19
+ - In a Next.js App Router project, Server Components read authorized server data rather than using
20
+ the client store to pass data between requests.
21
+ - Place the provider where the state lives: a shared layout keeps state across navigation, and a
22
+ page or keyed resource provider resets it.
23
+ - New initialization props do not reinitialize an existing store. Define a reconciliation action or
24
+ remount at a changed resource boundary, keeping drafts when the interaction needs them.
25
+
26
+ ## Select narrowly and keep results stable
27
+
28
+ - Components select the specific values and actions they read. A large layout or every list row
29
+ never subscribes to the whole store through an unselected hook.
30
+ - Select a primitive, stored entity, or stable action directly when the consumer needs only that value.
31
+ A selector that returns a tuple, array, or object of several values uses `useShallow` from a
32
+ supported entry point such as `zustand/react/shallow`.
33
+ - In Zustand 5, a selector that allocates a new result on every read can cause an update loop.
34
+ Fallback arrays, objects, and functions stay stable too, and an absent action never becomes a
35
+ fresh empty callback.
36
+ - Custom equality goes through `zustand/traditional` and its peer dependency; the standard `create`
37
+ takes no equality argument.
38
+ - Subscribe rows by entity ID. The list owner subscribes to ordering and paging instead of every
39
+ record's content.
40
+ - Derive values through selectors or computations over authoritative state, never synchronized counts,
41
+ array copies, or flags that disagree after a deletion, rollback, or reset.
42
+ - `getState()` reads an imperative snapshot without a subscription, so rendered values come from
43
+ selectors. Release manual subscriptions with their owning component or service.
44
+
45
+ ## Update without losing fields
46
+
47
+ - Use a functional `set` when the result depends on current state. Zustand merges the returned
48
+ object at the top level only, so a nested change copies each changed ancestor and keeps unchanged
49
+ siblings and references.
50
+ - Shallow comparison does not inspect nested values: replace a changed object, Map, Set, or array instead of mutating
51
+ it. Copy an edited record inside a Map too, because a new Map holding the same mutated record
52
+ leaves entity selectors on the old reference.
53
+ - Type an empty collection where the code builds it, such as `new Map<string, Entity>()`, without an
54
+ assertion. New stores and resets create fresh collections.
55
+ - Use `replace: true` only for a complete replacement that keeps the store's shape, actions
56
+ included. A reset changes the domain state and leaves a usable store.
57
+ - A store that already uses Immer changes only the provided draft. It configures Map and Set
58
+ support where the installed Immer requires it and keeps non-draftable external objects out of
59
+ drafts.
60
+ - One store uses one update method, and an immutable-update library joins only when it saves real
61
+ complexity.
62
+
63
+ ## Actions and slices
64
+
65
+ - Actions carry domain meaning, such as adding a record, switching a resource, or applying a
66
+ confirmed save. They live beside their state and keep its validation and related field changes.
67
+ - Changes that form one invariant go in one `set` call. Two actions in sequence make two store
68
+ transitions, and React render batching does not merge them.
69
+ - Slices organize one cohesive store, with one owner for each field and action, so spreading slices
70
+ cannot silently overwrite names. Middleware wraps the completed store, not each slice, and slice
71
+ creator types stay compatible with it.
72
+ - Asynchronous actions keep request identity and cancellation explicit. A delayed action never
73
+ updates the next resource after the reader moves on.
74
+
75
+ ## Persisted state
76
+
77
+ - `persist` takes a unique storage name and a `partialize` allowlist of durable fields. Actions,
78
+ request flags, live handles, access tokens, and credentials stay out.
79
+ - Maps, Sets, and other values that JSON loses get explicit serialization.
80
+ - Persist the current shape. When it changes, reset disposable cached state instead of migrating old
81
+ shapes, and move required user-authored records to the current shape. Missing, malformed, or
82
+ unavailable storage yields the initial state.
83
+ - In a server-rendered app, browser restoration stays apart from the first snapshot. Use
84
+ `skipHydration` and an explicit `rehydrate()` when automatic restoration changes it.
85
+ - Track hydration through the supported callbacks or subscriptions, not one read of
86
+ `hasHydrated()`, and release the listeners when their owner unmounts.
87
+ - Sign-out and identity or tenant changes reset live private state and clear or partition its
88
+ persisted copy. Clearing storage alone leaves the in-memory store unchanged.
89
+ - A pending restoration never reapplies the previous identity's data.
90
+
91
+ ## Verification
92
+
93
+ Check independent provider instances, nested updates, resets, and malformed stored state. A delayed
94
+ update must not change another resource or restore a previous identity's private state.
95
+
96
+ ## References
97
+
98
+ | Topic | Primary source |
99
+ | ----------------- | -------------------------------------------------------------------------------------------------- |
100
+ | Next.js setup | [Next.js guide](https://zustand.docs.pmnd.rs/learn/guides/nextjs) |
101
+ | Immutable updates | [Immutable state](https://zustand.docs.pmnd.rs/learn/guides/immutable-state-and-merging) |
102
+ | Maps and Sets | [Maps and Sets](https://zustand.docs.pmnd.rs/learn/guides/maps-and-sets-usage) |
103
+ | Immer | [Immer middleware](https://zustand.docs.pmnd.rs/reference/integrations/immer-middleware) |
104
+ | Slices | [Slices pattern](https://zustand.docs.pmnd.rs/learn/guides/slices-pattern) |
105
+ | Zustand 5 | [Migrating to v5](https://zustand.docs.pmnd.rs/reference/migrations/migrating-to-v5) |
106
+ | Persistence | [Persisting store data](https://zustand.docs.pmnd.rs/reference/integrations/persisting-store-data) |
@@ -0,0 +1,94 @@
1
+ allowed_words = ["Cloudflare"]
2
+ generated = ["worker-configuration.d.ts"]
3
+
4
+ [configuration]
5
+ title = "Cloudflare"
6
+ requires = ["javascript"]
7
+ suggests = []
8
+ description = "Cloudflare Pages and Workers: a wrangler configuration that parses and pins its date, headers and redirects files Cloudflare can read, fresh binding types, and the Semgrep rules for workers."
9
+
10
+ [detect]
11
+ filenames = ["wrangler.toml", "wrangler.json", "wrangler.jsonc", "_worker.js"]
12
+ paths = ["**/functions/_middleware.{js,ts}"]
13
+ dependencies = ["wrangler", "@opennextjs/cloudflare"]
14
+
15
+ [files]
16
+ extensions = [".d.ts"]
17
+ filenames = ["wrangler.toml", "wrangler.json", "wrangler.jsonc", "_headers", "_redirects"]
18
+
19
+ [[tool]]
20
+ name = "wrangler"
21
+ install_hint = "Run: npm install --save-dev wrangler"
22
+ system = true
23
+ version_command = ["--version"]
24
+ min_version = "3.78.3"
25
+ npm = "wrangler"
26
+
27
+ [[tool]]
28
+ name = "v8r"
29
+
30
+ [[tool_file]]
31
+ source = "semgrep/cloudflare.yml"
32
+ target = ".gspot/config/semgrep/cloudflare.yml"
33
+ tool = "semgrep"
34
+ rule_keys = ["rules"]
35
+ per_scope = true
36
+ when = { configuration = "security" }
37
+ level = "all"
38
+
39
+ [[check]]
40
+ name = "wrangler"
41
+ tool = ["wrangler", "v8r"]
42
+ command = ["v8r", "--schema", "{wrangler_schema}", "--ignore-errors", "--output-format", "text", "{files}"]
43
+ output = { format = "regex", pattern = "^(?<file>[^#\\s]+)#(?<message>.+)$" }
44
+ files = { filenames = ["wrangler.toml", "wrangler.json", "wrangler.jsonc"] }
45
+ example = "A Wrangler configuration without `compatibility_date` reports the missing date. Add a reviewed date in `YYYY-MM-DD` form, such as `2025-01-31`, and test the Worker against that runtime behavior."
46
+ level = "recommended"
47
+ stage = "commit"
48
+ runs = "scope"
49
+ summary = "Checks that every wrangler configuration parses, names the worker, and pins a compatibility date."
50
+ why = "Without a pinned date the runtime changes behavior under a deployed worker."
51
+ help = "Add the name and a compatibility_date in the form 2025-01-31."
52
+
53
+ [[check]]
54
+ name = "headers"
55
+ example = "An indented `X-Frame-Options: DENY` line before any path in `_headers` reports that the header sits under no path. Put the intended path, such as `/*`, on the preceding unindented line."
56
+ level = "recommended"
57
+ stage = "commit"
58
+ runs = "scope"
59
+ summary = "Checks that the headers file is blocks of a path line and indented header lines."
60
+ why = "Cloudflare skips a line it cannot read, so a typo silently drops a security header."
61
+ help = "Write each block as a path, then indented lines of a name, a colon, and a value."
62
+
63
+ [[check]]
64
+ name = "redirects"
65
+ example = "The `_redirects` line `/old /new 999` reports an unsupported redirect status. For an intended permanent redirect, change it to `/old /new 301`."
66
+ level = "recommended"
67
+ stage = "commit"
68
+ runs = "scope"
69
+ summary = "Checks each redirect source, destination, and optional status: 200, 301, 302, 303, 307, or 308, without a force suffix."
70
+ why = "A redirect Cloudflare cannot read is dropped, and the old address starts to answer 404."
71
+ help = "Write the rule as source, destination, status."
72
+
73
+ [[check]]
74
+ name = "stale-types"
75
+ command = ["wrangler", "types", "{file}", "--env-interface", "{setting:cloudflare.types_interface}"]
76
+ generated_paths = [{ pattern = "**/{setting:cloudflare.types_file}" }]
77
+ example = "A generated Worker environment type file that differs from `wrangler types` output reports drift. Regenerate it using the configured Wrangler project, inspect the changes, and rerun."
78
+ level = "recommended"
79
+ stage = "push"
80
+ runs = "scope"
81
+ tool = "wrangler"
82
+ summary = "Checks that a tracked environment types file matches what wrangler writes."
83
+ why = "Stale binding types let code compile against a binding the configuration dropped."
84
+ help = "Run wrangler types and commit the file."
85
+
86
+ [[check]]
87
+ name = "security-headers"
88
+ example = "A configured response-header block without a required security header reports the missing header. Add that header to every governed path block using the value required by settings."
89
+ level = "recommended"
90
+ stage = "commit"
91
+ runs = "scope"
92
+ summary = "Checks that the headers file sets the content type, referrer, and framing headers for every path."
93
+ why = "A site of files has no server code, so the headers file is the only place these protections can live."
94
+ help = "Add the header to the block for every path."
@@ -0,0 +1,23 @@
1
+ # Workers
2
+
3
+ Rules that hold because the code runs on a V8 isolate runtime such as Cloudflare Workers.
4
+
5
+ ## Global variables
6
+
7
+ - Web APIs such as `Request`, `Response`, `fetch`, `URL`, `crypto`, and `caches` work in this runtime.
8
+ - Node API availability depends on the compatibility date and flags. Check the configured
9
+ runtime before using `node:` imports or `process.env`.
10
+ - Bindings can come from handler arguments, supported entrypoint properties, or `env` imported
11
+ from `cloudflare:workers`. Build a client from `env` inside the request.
12
+ - Module-scope binding access does not permit request-only I/O outside a request context.
13
+
14
+ ## Lifetime
15
+
16
+ - The runtime can reuse or discard isolates. Module state provides neither durable storage nor a safe place
17
+ for request-specific user data.
18
+ - Share immutable configuration. Keep mutable request state isolated and persist durable
19
+ state through the application's storage contract.
20
+ - Use `ctx.waitUntil()` for work after the response. Use a Queue or Workflow for work that must finish.
21
+
22
+ See the Cloudflare [Node process support](https://developers.cloudflare.com/workers/runtime-apis/nodejs/process/)
23
+ and [binding access](https://developers.cloudflare.com/workers/runtime-apis/bindings/).
@@ -0,0 +1,12 @@
1
+ rules:
2
+ - id: gspot.cloudflare.no-wildcard-cors-origin
3
+ pattern-either:
4
+ - pattern: '"Access-Control-Allow-Origin": "*"'
5
+ - pattern: "'Access-Control-Allow-Origin': '*'"
6
+ - pattern: $HEADERS.set("Access-Control-Allow-Origin", "*")
7
+ - pattern: $HEADERS.append("Access-Control-Allow-Origin", "*")
8
+ message: Cloudflare middleware must not send wildcard CORS origins.
9
+ languages:
10
+ - javascript
11
+ - typescript
12
+ severity: ERROR