@gspothq/cli 0.1.1 → 0.2.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 (205) hide show
  1. package/README.md +58 -11
  2. package/configurations/database/postgres/manifest.toml +51 -57
  3. package/configurations/database/postgres/rules/POSTGRES.md +14 -13
  4. package/configurations/framework/astro/manifest.toml +33 -35
  5. package/configurations/framework/astro/rules/ASTRO.md +2 -2
  6. package/configurations/framework/expo/manifest.toml +19 -19
  7. package/configurations/framework/express/manifest.toml +10 -4
  8. package/configurations/framework/express/rules/EXPRESS.md +9 -7
  9. package/configurations/framework/fastapi/manifest.toml +9 -3
  10. package/configurations/framework/fastapi/rules/FASTAPI.md +19 -18
  11. package/configurations/framework/nestjs/manifest.toml +12 -12
  12. package/configurations/framework/nestjs/rules/NESTJS.md +9 -9
  13. package/configurations/framework/nextjs/manifest.toml +39 -79
  14. package/configurations/framework/nextjs/rules/NEXTJS.md +9 -7
  15. package/configurations/framework/nextjs/tool-files/semgrep/nextjs.yml +35 -0
  16. package/configurations/framework/react/manifest.toml +33 -43
  17. package/configurations/framework/react/rules/REACT.md +14 -20
  18. package/configurations/framework/react-dom/manifest.toml +6 -6
  19. package/configurations/framework/react-native/manifest.toml +11 -11
  20. package/configurations/framework/react-native/rules/REACT-NATIVE.md +3 -5
  21. package/configurations/framework/site/manifest.toml +57 -110
  22. package/configurations/framework/site/rules/SITE.md +1 -1
  23. package/configurations/framework/svelte/manifest.toml +29 -31
  24. package/configurations/framework/svelte/rules/SVELTE.md +6 -6
  25. package/configurations/framework/vue/manifest.toml +37 -37
  26. package/configurations/framework/vue/rules/VUE.md +6 -6
  27. package/configurations/general/commits/manifest.toml +20 -84
  28. package/configurations/general/commits/rules/GIT.md +24 -13
  29. package/configurations/general/coverage/manifest.toml +1 -1
  30. package/configurations/general/dependencies/manifest.toml +47 -107
  31. package/configurations/general/dependencies/rules/DEPENDENCIES.md +13 -7
  32. package/configurations/general/docs/manifest.toml +28 -43
  33. package/configurations/general/docs/rules/DOCS.md +16 -9
  34. package/configurations/general/duplication/manifest.toml +12 -14
  35. package/configurations/general/engineering/manifest.toml +6 -2
  36. package/configurations/general/engineering/rules/agent/PLANNING.md +9 -6
  37. package/configurations/general/engineering/rules/agent/SUPPRESSIONS.md +20 -11
  38. package/configurations/general/engineering/rules/agent/TASKS.md +6 -2
  39. package/configurations/general/engineering/rules/agent/WORKING.md +34 -29
  40. package/configurations/general/engineering/rules/code/ACCESSIBILITY.md +9 -7
  41. package/configurations/general/engineering/rules/code/CLI.md +12 -9
  42. package/configurations/general/engineering/rules/code/COMMENTS.md +11 -1
  43. package/configurations/general/engineering/rules/code/CONFIGURATION.md +2 -0
  44. package/configurations/general/engineering/rules/code/ERRORS.md +5 -3
  45. package/configurations/general/engineering/rules/code/HTTP.md +9 -10
  46. package/configurations/general/engineering/rules/code/LOGGING.md +10 -9
  47. package/configurations/general/engineering/rules/code/TESTING.md +18 -11
  48. package/configurations/general/files/manifest.toml +45 -73
  49. package/configurations/general/files/rules/YAML.md +20 -10
  50. package/configurations/general/format/manifest.toml +53 -106
  51. package/configurations/general/gspot/manifest.toml +19 -39
  52. package/configurations/general/gspot/rules/GENERATED.md +14 -4
  53. package/configurations/general/licenses/manifest.toml +12 -14
  54. package/configurations/general/naming/defaults.json +14 -13
  55. package/configurations/general/naming/manifest.toml +17 -17
  56. package/configurations/general/naming/rules/NAMING.md +87 -67
  57. package/configurations/general/prose/manifest.toml +166 -25
  58. package/configurations/general/prose/rules/WRITING.md +6 -2
  59. package/configurations/general/repository/manifest.toml +12 -12
  60. package/configurations/general/secrets/manifest.toml +52 -73
  61. package/configurations/general/secrets/rules/SECRETS.md +3 -1
  62. package/configurations/general/security/manifest.toml +29 -52
  63. package/configurations/general/security/rules/SECURITY.md +8 -6
  64. package/configurations/general/spelling/manifest.toml +15 -25
  65. package/configurations/general/structure/manifest.toml +31 -31
  66. package/configurations/infrastructure/ansible/manifest.toml +15 -15
  67. package/configurations/infrastructure/docker/manifest.toml +55 -67
  68. package/configurations/infrastructure/docker/rules/DOCKER.md +15 -13
  69. package/configurations/infrastructure/github-actions/manifest.toml +21 -41
  70. package/configurations/infrastructure/github-actions/rules/GITHUB-ACTIONS.md +16 -12
  71. package/configurations/infrastructure/github-actions/tool-files/zizmor.yml +5 -0
  72. package/configurations/infrastructure/nginx/manifest.toml +20 -20
  73. package/configurations/infrastructure/nginx/rules/NGINX.md +5 -4
  74. package/configurations/infrastructure/openapi/manifest.toml +20 -20
  75. package/configurations/infrastructure/openapi/rules/OPENAPI.md +3 -1
  76. package/configurations/infrastructure/xcode/manifest.toml +55 -75
  77. package/configurations/infrastructure/xcode/rules/XCODE.md +5 -3
  78. package/configurations/language/bash/manifest.toml +89 -170
  79. package/configurations/language/bash/rules/BASH.md +79 -17
  80. package/configurations/language/bash/rules/LANGUAGE.md +30 -26
  81. package/configurations/language/bash/rules/OPERATIONS.md +10 -8
  82. package/configurations/language/bash/rules/SAFETY.md +39 -35
  83. package/configurations/language/css/manifest.toml +22 -61
  84. package/configurations/language/css/rules/CSS.md +21 -2
  85. package/configurations/language/css/rules/TAILWIND.md +7 -5
  86. package/configurations/language/html/manifest.toml +16 -35
  87. package/configurations/language/html/rules/HTML.md +23 -5
  88. package/configurations/language/javascript/eslint-runtime-names.json +66 -61
  89. package/configurations/language/javascript/eslint-runtime.mjs +118 -0
  90. package/configurations/language/javascript/manifest.toml +135 -207
  91. package/configurations/language/javascript/rules/BUN.md +2 -2
  92. package/configurations/language/javascript/rules/COMPONENTS.md +4 -4
  93. package/configurations/language/javascript/rules/DENO.md +1 -1
  94. package/configurations/language/javascript/rules/JAVASCRIPT.md +30 -17
  95. package/configurations/language/javascript/rules/NODE.md +2 -2
  96. package/configurations/language/javascript/rules/PLAYWRIGHT.md +10 -9
  97. package/configurations/language/markdown/manifest.toml +20 -51
  98. package/configurations/language/python/manifest.toml +231 -342
  99. package/configurations/language/python/rules/DESIGN.md +40 -33
  100. package/configurations/language/python/rules/FLOW.md +8 -6
  101. package/configurations/language/python/rules/PACKAGING.md +14 -7
  102. package/configurations/language/python/rules/PYTHON.md +83 -33
  103. package/configurations/language/python/rules/TYPING.md +25 -23
  104. package/configurations/language/sql/manifest.toml +19 -37
  105. package/configurations/language/sql/rules/SQL.md +90 -2
  106. package/configurations/language/swift/manifest.toml +67 -78
  107. package/configurations/language/swift/rules/SWIFT.md +138 -40
  108. package/configurations/language/swift/rules/SWIFTUI.md +11 -9
  109. package/configurations/language/swift/rules/UIKIT.md +21 -19
  110. package/configurations/language/typescript/manifest.toml +34 -34
  111. package/configurations/language/typescript/rules/TYPESCRIPT.md +62 -10
  112. package/configurations/library/drizzle/manifest.toml +25 -38
  113. package/configurations/library/drizzle/rules/DRIZZLE.md +4 -2
  114. package/configurations/library/react-hook-form/manifest.toml +4 -4
  115. package/configurations/library/react-hook-form/rules/REACT-HOOK-FORM.md +15 -13
  116. package/configurations/library/tanstack-query/manifest.toml +6 -6
  117. package/configurations/library/tanstack-query/rules/TANSTACK-QUERY.md +5 -3
  118. package/configurations/library/testing-library/manifest.toml +6 -6
  119. package/configurations/library/translations/manifest.toml +22 -22
  120. package/configurations/library/translations/rules/NEXT-INTL.md +6 -8
  121. package/configurations/library/translations/rules/TRANSLATIONS.md +22 -23
  122. package/configurations/library/trpc/manifest.toml +3 -3
  123. package/configurations/library/trpc/rules/TRPC.md +8 -6
  124. package/configurations/library/zod/manifest.toml +6 -6
  125. package/configurations/library/zod/rules/ZOD.md +4 -2
  126. package/configurations/library/zustand/manifest.toml +4 -4
  127. package/configurations/library/zustand/rules/ZUSTAND.md +16 -14
  128. package/configurations/platform/cloudflare/manifest.toml +28 -47
  129. package/configurations/platform/cloudflare/rules/CLOUDFLARE.md +11 -6
  130. package/configurations/platform/supabase/manifest.toml +48 -61
  131. package/configurations/platform/supabase/rules/SUPABASE.md +27 -28
  132. package/configurations/testing/jest/manifest.toml +21 -22
  133. package/configurations/testing/pytest/manifest.toml +28 -28
  134. package/configurations/testing/swift-tests/manifest.toml +18 -29
  135. package/configurations/testing/swift-tests/rules/SWIFT-TESTS.md +7 -5
  136. package/configurations/testing/vitest/manifest.toml +32 -32
  137. package/configurations/testing/vitest/rules/VITEST.md +3 -1
  138. package/dist/gspot.js +22297 -24707
  139. package/dist/{linkinator-program.js → linkinator-process.js} +5 -7
  140. package/dist/{purgecss-program.js → purgecss-process.js} +12 -12
  141. package/package.json +7 -9
  142. package/configurations/infrastructure/github-actions/zizmor.yml +0 -3
  143. package/configurations/language/bash/rules/NAMING.md +0 -62
  144. package/configurations/language/css/rules/NAMING.md +0 -17
  145. package/configurations/language/html/rules/NAMING.md +0 -16
  146. package/configurations/language/javascript/rules/NAMING.md +0 -31
  147. package/configurations/language/markdown/markdownlint-cli2.mjs +0 -19
  148. package/configurations/language/python/rules/NAMING.md +0 -53
  149. package/configurations/language/sql/rules/NAMING.md +0 -90
  150. package/configurations/language/swift/rules/NAMING.md +0 -88
  151. package/configurations/language/typescript/rules/NAMING.md +0 -73
  152. package/configurations/library/swift-snapshot-testing/manifest.toml +0 -32
  153. package/dist/THIRD-PARTY-NOTICES.md +0 -25
  154. package/dist/eslint-rule-levels.json +0 -10
  155. package/dist/tool-versions.json +0 -3
  156. package/gspot.schema.json +0 -45991
  157. /package/{dist/LICENSE.md → LICENSE.md} +0 -0
  158. /package/configurations/framework/express/{semgrep → tool-files/semgrep}/express.yml +0 -0
  159. /package/configurations/framework/fastapi/{semgrep → tool-files/semgrep}/fastapi.yml +0 -0
  160. /package/configurations/general/dependencies/{syncpack.json → tool-files/syncpack.json} +0 -0
  161. /package/configurations/general/prose/{vale → tool-files/vale}/styles/LICENSES.md +0 -0
  162. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/ampm.yml +0 -0
  163. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/conscious-language.yml +0 -0
  164. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/contractions.yml +0 -0
  165. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/currency.yml +0 -0
  166. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/dashes.yml +0 -0
  167. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/date-ordinals.yml +0 -0
  168. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/dates.yml +0 -0
  169. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/file-paths.yml +0 -0
  170. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/future.yml +0 -0
  171. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/hedging.yml +0 -0
  172. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/history.yml +0 -0
  173. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/idioms.yml +0 -0
  174. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/interface-verbs.yml +0 -0
  175. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/jargon.yml +0 -0
  176. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/leading-conjunctions.yml +0 -0
  177. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/link-text.yml +0 -0
  178. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/locations.yml +0 -0
  179. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/marketing.yml +0 -0
  180. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/merge-conflict-markers.yml +0 -0
  181. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/militaristic-language.yml +0 -0
  182. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/modals.yml +0 -0
  183. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/numbered-units.yml +0 -0
  184. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/obvious-fields.yml +0 -0
  185. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/ordinal-adverbs.yml +0 -0
  186. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/percentage-numbers.yml +0 -0
  187. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/placeholders.yml +0 -0
  188. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/product-centric-writing.yml +0 -0
  189. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/punctuated-headings.yml +0 -0
  190. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/self-reference.yml +0 -0
  191. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/session-identifiers.yml +0 -0
  192. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/since.yml +0 -0
  193. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/straight-quotes.yml +0 -0
  194. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/suspended-hyphens.yml +0 -0
  195. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/symbols.yml +0 -0
  196. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/time-ranges.yml +0 -0
  197. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/url-prepositions.yml +0 -0
  198. /package/configurations/general/prose/{vale → tool-files/vale}/styles/gspot/version-range.yml +0 -0
  199. /package/configurations/general/secrets/{gitleaks.toml → tool-files/gitleaks.toml} +0 -0
  200. /package/configurations/infrastructure/docker/{trivyignore → tool-files/trivyignore} +0 -0
  201. /package/configurations/language/bash/{semgrep → tool-files/semgrep}/bash.yml +0 -0
  202. /package/configurations/language/javascript/{semgrep → tool-files/semgrep}/javascript.yml +0 -0
  203. /package/configurations/language/swift/{semgrep → tool-files/semgrep}/swift.yml +0 -0
  204. /package/configurations/platform/cloudflare/{semgrep → tool-files/semgrep}/cloudflare.yml +0 -0
  205. /package/configurations/platform/supabase/{semgrep → tool-files/semgrep}/supabase.yml +0 -0
@@ -1,9 +1,10 @@
1
1
  allowed_words = ["Supabase"]
2
+
2
3
  [configuration]
3
- title = "Supabase"
4
+ description = "A Supabase project: edge functions under Deno. Every storage bucket has a policy, and privileged keys stay in their allowed files."
4
5
  requires = ["postgres", "javascript"]
5
6
  suggests = ["typescript"]
6
- description = "A Supabase project: a project file that parses, edge functions under Deno, and migrations named as the CLI names them. Every storage bucket has a policy, and privileged keys stay in their allowed files."
7
+ title = "Supabase"
7
8
 
8
9
  [detect]
9
10
  paths = ["**/supabase/config.toml"]
@@ -12,101 +13,87 @@ project_files = ["supabase/config.toml"]
12
13
  [files]
13
14
  paths = ["supabase/config.toml", "supabase/functions/**", "supabase/seed.sql"]
14
15
 
16
+ [defaults]
17
+ "postgres.client_schemas" = ["public"]
18
+ "tools.squawk.assume_in_transaction" = true
19
+
15
20
  [[tool]]
16
- name = "deno"
17
- version = "2.6.6"
18
- min_version = "2.0.0"
19
- mise = "deno"
20
21
  brew = "deno"
21
22
  github = { name = "denoland/deno", version = "v2.6.6" }
23
+ min_version = "2.0.0"
24
+ mise = "deno"
25
+ name = "deno"
22
26
  scoop = "deno"
27
+ version = "2.6.6"
23
28
 
24
29
  [[tool]]
25
- name = "supabase"
26
- system = true
27
- version_command = ["--version"]
30
+ brew = "supabase/tap/supabase"
28
31
  min_version = "2.0.0"
29
32
  mise = "supabase"
30
- brew = "supabase/tap/supabase"
33
+ name = "supabase"
31
34
  npm = "supabase"
32
35
  scoop = "supabase"
36
+ system = true
37
+ version_command = ["--version"]
33
38
 
34
- [[check]]
35
- name = "project-file"
36
- example = "A function entry in `supabase/config.toml` naming a function absent from the repository reports a stale function configuration. Restore the function source or remove its obsolete configuration table."
37
- level = "recommended"
38
- stage = "commit"
39
- runs = "scope"
40
- summary = "Checks that the project file parses, and that every function it configures has a folder with an index file."
41
- why = "The CLI reads this file at every deploy, and a function it configures with no code fails there."
42
- help = "Correct the file at the place the message names, or remove the table of a function the repository does not hold."
39
+ [[tool_file]]
40
+ per_scope = true
41
+ target = ".gspot/config/semgrep/supabase.yml"
42
+ tool = "semgrep"
43
+ when = { configuration = "security" }
43
44
 
44
45
  [[check]]
45
- name = "migration-names"
46
- example = "A Supabase migration named `add_users.sql` lacks the required timestamp prefix. Create it with `supabase migration new add_users`, then move the intended SQL into the generated migration file."
46
+ example = "A storage bucket with no policy on `storage.objects` reports a finding. Add a migration that defines access for that bucket."
47
+ help = "Add a policy on storage.objects for the bucket in a migration."
47
48
  level = "recommended"
48
- stage = "commit"
49
- runs = "scope"
50
- summary = "Checks that every migration is named fourteen digits, an underscore, and snake case words."
51
- why = "The CLI orders and records migrations by this name, and it skips a file it cannot read a version from."
52
- help = "Create the migration with supabase migration new `<name>`, which writes the name."
53
-
54
- [[check]]
55
49
  name = "storage-policies"
56
- example = "A declared storage bucket with no matching policy on `storage.objects` reports missing access policy. Add a migration defining the intended access policy for that bucket and rerun."
57
- level = "recommended"
58
- stage = "commit"
59
50
  runs = "scope"
51
+ stage = "commit"
60
52
  summary = "Checks that every storage bucket in the project file has a policy on storage.objects that names it."
61
- why = "A bucket with no policy is closed to everyone or, when it is public, open to everyone, and neither is a decision anybody wrote down."
62
- help = "Add a policy on storage.objects for the bucket in a migration."
53
+ why = "A bucket with no policy stays closed to every user, or open to anyone when public, and nobody recorded that choice."
63
54
 
64
55
  [[check]]
65
- name = "service-role-key"
66
- example = "A client source reading a Supabase secret or service-role key reports an administrative-key boundary finding. Move privileged operations and the key read to a server-only path, exposing only the required server operation to the client."
56
+ example = "Client code that reads a Supabase service-role key reports a finding. Move the key and the privileged work into an edge function."
57
+ help = "Move code to edge functions or tests, or run `gspot ignore supabase/service-role-key` with a reason."
67
58
  level = "recommended"
68
- stage = "commit"
59
+ name = "service-role-key"
69
60
  runs = "scope"
70
- summary = "Checks that secret and service role keys are named only in edge functions and test files."
61
+ stage = "commit"
62
+ summary = "Checks that only edge functions and test files name a secret or service role key."
71
63
  why = "Secret and service role keys bypass row level security, so a client bundle that holds either exposes privileged database access."
72
- help = "Move code to edge functions or tests, or run gspot ignore supabase/service-role-key with a reason."
73
64
 
74
65
  [[check]]
75
- name = "deno-lint"
76
- example = "An Edge Function declaring `var greeting = \"hello\";` reports `no-var`. Use `const greeting = \"hello\";` when the value does not change, then rerun with the pinned Deno tool available."
66
+ example = "An Edge Function declaring `var greeting = \"hello\";` reports `no-var`. Use `const greeting = \"hello\";` instead."
67
+ help = "Change the code the way the rule says; `deno lint --rules` explains each one."
77
68
  level = "recommended"
78
- stage = "commit"
69
+ name = "deno-lint"
79
70
  runs = "scope"
71
+ stage = "commit"
72
+ summary = "Runs `deno lint` over every edge function with its own deno.json."
80
73
  tool = "deno"
81
- summary = "Runs deno lint over every edge function, with the function's own deno.json."
82
- why = "Edge functions run under Deno, and its linter knows the runtime the Node rules do not."
83
- help = "Change the code the way the rule says; deno lint --rules explains each one."
74
+ why = "Edge functions run under Deno, and its linter covers runtime APIs that the Node rules miss."
84
75
 
85
76
  [[check]]
86
- name = "deno-check"
87
- example = "An Edge Function assigning a string to a number-typed variable reports a Deno type error. Correct the value or type to match the intended contract, then rerun."
77
+ example = "An edge function that assigns a string to a number variable reports a type error. Correct the value or the type."
78
+ help = "Fix the first error Deno prints; later ones often come from the same mistake."
88
79
  level = "recommended"
89
- stage = "push"
80
+ name = "deno-check"
90
81
  runs = "scope"
82
+ stage = "push"
83
+ summary = "Runs `deno check` on the entry file of every edge function."
91
84
  tool = "deno"
92
- summary = "Type checks the entry file of every edge function with deno check."
93
- why = "The project compiler does not resolve the import map of a function, so only Deno sees its types."
94
- help = "Fix the first error Deno prints; later ones are often the same mistake."
85
+ why = "The project compiler cannot resolve the import map of a function, so only Deno can check its types."
95
86
 
96
87
  [[check]]
97
- name = "stale-types"
98
88
  command = ["supabase", "gen", "types", "typescript", "--local", "{each:--schema:supabase.schemas}"]
99
- generated_paths = [{ stdout = "{setting:supabase.types_file}" }]
100
- example = "A database types file that differs from the configured local Supabase schema reports drift. With the local database ready, regenerate using `supabase gen types typescript --local`, write the output to the configured file, and rerun."
89
+ example = "A types file that differs from the local Supabase schema reports drift. With the local database running, write the output of `supabase gen types typescript --local` to that file."
90
+ generator_outputs = [{ stdout = "{setting:supabase.types_file}" }]
91
+ help = "Run `supabase gen types typescript --local` and write the output to the file."
101
92
  level = "recommended"
102
- stage = "push"
93
+ name = "stale-types"
94
+ needs = ["docker"]
103
95
  runs = "scope"
96
+ stage = "push"
97
+ summary = "Compares `supabase.types_file` with the output the Supabase CLI writes from the local database."
104
98
  tool = "supabase"
105
- needs = ["docker"]
106
- summary = "Compares supabase.types_file with the types the CLI writes from the local database."
107
99
  why = "Stale types let code compile against a column the database dropped."
108
- help = "Run supabase gen types typescript --local and write the output to the file."
109
-
110
- [defaults]
111
- "postgres.client_schemas" = ["public"]
112
- "tools.squawk.assume_in_transaction" = true
@@ -1,7 +1,8 @@
1
1
  # Supabase
2
2
 
3
- Layout, database access, storage, Edge Functions, configuration, and secrets of a Supabase
4
- project, on top of the Postgres rules. Supabase uses the API roles `anon`, `authenticated`, and
3
+ Read this rule when you change Supabase migrations, storage, Edge Functions, or `config.toml`.
4
+
5
+ Follow the Postgres rules too. Supabase uses the API roles `anon`, `authenticated`, and
5
6
  `service_role`.
6
7
 
7
8
  ## Layout and migrations
@@ -11,13 +12,12 @@ project, on top of the Postgres rules. Supabase uses the API roles `anon`, `auth
11
12
 
12
13
  ## Database access
13
14
 
14
- - `[api].schemas` in `config.toml` lists the schemas the Data API exposes. Treat those schemas as
15
+ - `[api].schemas` in `config.toml` lists the schemas the Data API exposes. Treat them as
15
16
  externally reachable.
16
- - row level security (RLS) with no policy denies access through the API roles. Use that choice for tables that clients
17
- must not read.
17
+ - A table with row level security (RLS) on and no policy denies access to the API roles. Use that choice for tables
18
+ that clients must not read.
18
19
  - Roles Supabase creates for auth, cron, or storage stay scoped to the functions and schemas they need.
19
- - Each policy chooses `TO anon`, `TO authenticated`, or `TO service_role` deliberately. The service
20
- role never stands in for precise grants or hides a missing policy.
20
+ - Name the Supabase roles in `TO`: `anon`, `authenticated`, or `service_role`.
21
21
  - A table can skip the foreign key to `auth.users` so its history survives account deletion.
22
22
  - Keep `[api].max_rows` conservative to bound accidental or malicious payloads.
23
23
 
@@ -25,17 +25,16 @@ project, on top of the Postgres rules. Supabase uses the API roles `anon`, `auth
25
25
 
26
26
  Choose the Supabase connection mode for the workload.
27
27
 
28
- | Workload | Connection choice |
29
- | ----------------------------------------------- | --------------------------------------------------------------------- |
30
- | Short-lived serverless application requests | Transaction pooler, with a compatible driver |
31
- | Persistent server with direct network access | Direct connection with a bounded application pool |
32
- | Persistent server on an IPv4-only network | Session pooler when the direct endpoint is unavailable |
33
- | Migrations, dumps, or session-dependent tooling | Direct connection; use a supported session alternative when necessary |
34
-
35
- A separate migration credential holds schema privileges. The application role holds only what
36
- runtime needs
37
- See [connection modes](https://supabase.com/docs/guides/database/connecting-to-postgres). Postgres.js
38
- uses the transaction pooler's supported configuration.
28
+ | Workload | Connection choice |
29
+ | --------------------------------------------- | --------------------------------------------------------------------- |
30
+ | Short-lived serverless application requests | Transaction pooler, with a compatible driver |
31
+ | Persistent server with direct network access | Direct connection with a bounded application pool |
32
+ | Persistent server on an IPv4-only network | Session pooler when the server cannot reach the direct endpoint |
33
+ | Migrations, dumps, or session-dependent tools | Direct connection; use a supported session alternative when necessary |
34
+
35
+ A separate migration credential holds schema privileges. The application role holds only the privileges it needs at runtime.
36
+ See [connection modes](https://supabase.com/docs/guides/database/connecting-to-postgres).
37
+
39
38
  Set explicit connection, idle, and query timeouts. Budget connections across instances and
40
39
  workers. With Postgres.js through transaction pooling, set `prepare: false` and confirm the setting
41
40
  after a driver or pooler change.
@@ -46,16 +45,16 @@ maps the identity to a fixed set of allowed roles, then opens a transaction on a
46
45
  connection. Use parameterized transaction-local `set_config` for claims and fixed trusted SQL for
47
46
  the role. Every protected query uses that transaction. Commit or rollback ends its context.
48
47
 
49
- When Drizzle generates migrations that the Supabase CLI applies, keep the CLI's migration format
48
+ When Drizzle generates migrations that the Supabase CLI applies, keep the CLI migration format
50
49
  and one authoritative applied-history ledger. Declare provider-managed schemas and roles as
51
- existing. Check replay through the chosen runner. See
50
+ existing. Check replay with the project migration tool. See
52
51
  [migration history](https://supabase.com/docs/guides/local-development/database-migrations) and
53
52
  [verified claims](https://supabase.com/docs/reference/javascript/auth-getclaims).
54
53
 
55
54
  ## Storage
56
55
 
57
56
  - Define buckets in migrations and mirror them in `config.toml`. A change to `public`,
58
- `file_size_limit`, or `allowed_mime_types` updates both in the same change.
57
+ `file_size_limit`, or `allowed_mime_types` updates both at once.
59
58
  - Bucket restrictions enforce file size and MIME type, not only application validation.
60
59
  - RLS policies on `storage.objects` and `storage.buckets` control access. The service controls metadata in the `storage` schema: migrations add only policies, indexes for RLS or validation, triggers,
61
60
  and bucket configuration. Object rows change only through the Storage API.
@@ -79,15 +78,15 @@ existing. Check replay through the chosen runner. See
79
78
 
80
79
  ## Edge functions
81
80
 
82
- - Each deployable function lives under `functions/<function-name>/` in the CLI's functions root,
83
- with a `[functions.<name>]` entry whose `entrypoint` starts from the configuration file directory.
81
+ - Each deployable function lives under `functions/<function-name>/` in the CLI functions root,
82
+ with a `[functions.<name>]` table whose `entrypoint` path starts from the folder of `config.toml`.
84
83
  Shared code lives in `functions/_shared/`, which Supabase never deploys.
85
84
  - Name a function folder in kebab-case for its callable operation, not its technology:
86
- `submit-order`, never `SubmitOrder` or `provider_handler`. The folder, configuration entry, and
87
- deployed name match.
85
+ `submit-order`, never `SubmitOrder` or `provider_handler`. The folder, the `config.toml` table, and
86
+ the deployed name match.
88
87
  - Edge Functions run on Deno, and the Deno rules hold.
89
88
  - Keep `verify_jwt = true` for user-authenticated functions. Set it to `false` only when the function
90
- exposes only public, harmless behavior, verifies a provider webhook signature, checks a service secret, or takes
89
+ exposes nothing but public, harmless behavior, verifies a provider webhook signature, checks a service secret, or takes
91
90
  a Vault secret from cron.
92
91
  - A publishable or secret API key differs from a user JSON Web Token (JWT). Never send that key as
93
92
  `Authorization: Bearer <key>`. Forward the caller's `Authorization` header to the Supabase
@@ -99,7 +98,7 @@ existing. Check replay through the chosen runner. See
99
98
  in `functions/_shared/`.
100
99
  - Functions have runtime, CPU, memory, bundle-size, and log-rate limits, so long CPU-heavy work
101
100
  runs elsewhere. Raw Supabase errors that expose credentials stay out of logs.
102
- - When you write tests, cover function logic in unit tests. Integration tests against a local
101
+ - When you write tests, cover function logic at the unit level. Integration tests against a local
103
102
  database and function server cover the client, auth, RLS, and the invocation path.
104
103
 
105
104
  ## Configuration and secrets
@@ -108,7 +107,7 @@ existing. Check replay through the chosen runner. See
108
107
 
109
108
  Ask the user before changing signup, anonymous sign-in, providers, hooks, JWT expiry, or password policy.
110
109
  Also ask before weakening auth settings, row-level security, grants, or `verify_jwt`.
111
- Proceed when the task already authorizes the change. Write the reason in the commit when the user authorizes a commit.
110
+ Proceed when the task already authorizes the change. When the user authorizes a commit, write the reason in it.
112
111
 
113
112
  - Service keys, Edge secrets, Vault values, database URLs, and provider API keys stay backend-only.
114
113
  They never appear in app code, checked-in files, logs, migration comments, tests, or test data.
@@ -1,7 +1,7 @@
1
1
  [configuration]
2
- title = "Jest"
2
+ description = "Jest lint rules and coverage floors for the repository test suites."
3
3
  requires = ["javascript", "coverage"]
4
- description = "Jest test rules and coverage floors for repository-owned test suites."
4
+ title = "Jest"
5
5
 
6
6
  [detect]
7
7
  dependencies = ["jest"]
@@ -15,27 +15,35 @@ name = "jest"
15
15
  system = true
16
16
 
17
17
  [[tool]]
18
+ kind = "library"
18
19
  name = "eslint-plugin-jest"
20
+ npm = "eslint-plugin-jest"
19
21
  rule_prefix = "jest"
20
- kind = "library"
21
22
  version = "29.16.6"
22
- npm = "eslint-plugin-jest"
23
+
24
+ [eslint]
25
+ all_level_rules = ["jest/prefer-strict-equal"]
26
+
27
+ [[tool_file]]
28
+ fragment = true
29
+ required_tools = ["eslint-plugin-jest"]
30
+ target = ".gspot/config/eslint.config.mjs"
31
+ tool = "eslint"
23
32
 
24
33
  [[check]]
25
- name = "coverage"
34
+ command = ["jest", "--ci", "--rootDir={root}/{scope}", "--coverage", "--coverageReporters=text-summary", "--coverageThreshold={\"global\":{\"lines\":{setting:coverage.lines},\"branches\":{setting:coverage.branches},\"functions\":{setting:coverage.functions},\"statements\":{setting:coverage.statements}}}"]
35
+ crash_pattern = "^No tests found|^ ● Test suite failed to run"
36
+ cwd = "scope"
26
37
  example = "Jest reports `coverage threshold for lines (90%) not met: 85%`. Add tests for the lines its report marks uncovered."
38
+ exit_codes = [1]
39
+ help = "Correct failed tests and cover the reported branches, functions, lines, and statements."
27
40
  level = "recommended"
28
- stage = "push"
41
+ name = "coverage"
29
42
  runs = "scope"
30
- cwd = "scope"
43
+ stage = "push"
44
+ summary = "Runs Jest and checks all four coverage floors."
31
45
  tool = "jest"
32
- command = ["jest", "--ci", "--rootDir={root}/{scope}", "--coverage", "--coverageReporters=text-summary", "--coverageThreshold={\"global\":{\"lines\":{setting:coverage.lines},\"branches\":{setting:coverage.branches},\"functions\":{setting:coverage.functions},\"statements\":{setting:coverage.statements}}}"]
33
- run_in_copy = true
34
- exit_codes = [1]
35
- crash_pattern = "^No tests found|^ ● Test suite failed to run"
36
- summary = "Runs Jest in a disposable source copy and checks all four coverage floors."
37
46
  why = "A coverage floor keeps new code from arriving untested."
38
- help = "Correct failed tests and cover the reported branches, functions, lines, and statements."
39
47
 
40
48
  [check.files]
41
49
  extensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]
@@ -43,12 +51,3 @@ extensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]
43
51
  [check.output]
44
52
  format = "regex"
45
53
  pattern = "^Jest: \"global\" (?<message>coverage threshold for .+ not met: .+)$"
46
-
47
- [eslint]
48
- all_level_rules = ["jest/prefer-strict-equal"]
49
-
50
- [[tool_file]]
51
- target = ".gspot/config/eslint.config.mjs"
52
- tool = "eslint"
53
- fragment = true
54
- required_tools = ["eslint-plugin-jest"]
@@ -1,53 +1,53 @@
1
1
  [configuration]
2
- title = "pytest"
2
+ description = "pytest suites: Ruff style rules for tests, test-name prefixes, and a coverage floor at push."
3
3
  requires = ["python", "coverage"]
4
- description = "pytest suites: Ruff pytest style rules over the tests, pytest test-name prefixes, and a coverage floor at push."
4
+ title = "pytest"
5
5
 
6
6
  [detect]
7
7
  dependencies = ["pytest"]
8
8
  filenames = ["conftest.py", "pytest.ini"]
9
9
 
10
+ [[naming.override]]
11
+ categories = ["functions", "methods"]
12
+ ignored_prefix = "^test_"
13
+ languages = ["python"]
14
+ paths = ["**/test_*.py", "**/*_test.py", "**/tests/**/*.py", "**/conftest.py"]
15
+ reason = "The test runner finds a test by this prefix."
16
+
10
17
  [[tool]]
11
- name = "pytest"
12
18
  install_hint = "Run: python -m pip install pytest"
13
- system = true
14
- suppression = { marker = "\\bpragma: ?no cover\\b", reason = "#[^#]*# ?(?<reason>\\S.*)" }
15
19
  min_version = "7.0.0"
20
+ name = "pytest"
16
21
  pypi = "pytest"
22
+ suppression = { marker = "\\bpragma: ?no cover\\b", reason = "#[^#]*# ?(?<reason>\\S.*)" }
23
+ system = true
17
24
  version_pattern = "(\\d+\\.\\d+\\.\\d+)"
18
25
 
19
26
  [[tool]]
20
- name = "pytest-cov"
21
27
  install_hint = "Install pytest-cov in the Python environment used by pytest."
22
28
  kind = "library"
23
- system = true
29
+ name = "pytest-cov"
24
30
  pypi = "pytest-cov"
31
+ system = true
25
32
  version_command = ["pytest", "--version", "--version"]
26
33
  version_pattern = "pytest-cov-(\\d+(?:\\.\\d+)+)"
27
34
 
35
+ [ruff]
36
+ all = ["PT001", "PT002", "PT003", "PT006", "PT007", "PT018", "PT019", "PT022", "PT023", "PT026"]
37
+ recommended = ["PT008", "PT009", "PT010", "PT011", "PT012", "PT013", "PT014", "PT015", "PT016", "PT017", "PT020", "PT021", "PT024", "PT025", "PT027", "PT028", "PT030", "PT031"]
38
+
28
39
  [[check]]
29
- name = "coverage"
30
- tool = ["pytest", "pytest-cov"]
31
- example = "pytest-cov reports `FAIL Required test coverage of 90% not reached. Total coverage: 85%`. Add a Python test for the uncovered behavior."
32
- level = "recommended"
33
- stage = "push"
34
- runs = "scope"
35
- cwd = "scope"
36
40
  command = ["pytest", "-q", "--strict-markers", "--strict-config", "--cov", "--cov-fail-under={setting:coverage.lines}", "--no-header", "-p", "no:cacheprovider"]
41
+ cwd = "scope"
42
+ example = "pytest-cov reports `FAIL Required test coverage of 90% not reached. Total coverage: 85%`. Add a Python test for the uncovered behavior."
37
43
  exit_codes = [1]
38
44
  files = { extensions = [".py"] }
45
+ help = "Fix the failed test, or cover the lines the report marks. Lower `coverage.lines` only with a reason."
46
+ level = "recommended"
47
+ name = "coverage"
39
48
  output = { format = "regex", pattern = "^(?<message>(?:FAIL Required test coverage|FAILED |ERROR ).*)$" }
40
- summary = "Runs the test suite with coverage, and fails when a test fails or the covered share falls under the floor."
41
- why = "Python coverage reveals branches and lines the test suite does not exercise before a push."
42
- help = "Fix the failing test, or add tests for the code the report shows uncovered. Lower coverage.lines with a reason."
43
-
44
- [ruff_rules]
45
- recommended = ["PT008", "PT009", "PT010", "PT011", "PT012", "PT013", "PT014", "PT015", "PT016", "PT017", "PT020", "PT021", "PT024", "PT025", "PT027", "PT028", "PT030", "PT031"]
46
- all = ["PT001", "PT002", "PT003", "PT006", "PT007", "PT018", "PT019", "PT022", "PT023", "PT026"]
47
-
48
- [[naming.override]]
49
- paths = ["**/test_*.py", "**/*_test.py", "**/tests/**/*.py", "**/conftest.py"]
50
- languages = ["python"]
51
- categories = ["functions", "methods"]
52
- ignored_prefix = "^test_"
53
- reason = "The test runner finds a test by this prefix."
49
+ runs = "scope"
50
+ stage = "push"
51
+ summary = "Runs pytest with coverage, and fails on a broken test or a covered share under the floor."
52
+ tool = ["pytest", "pytest-cov"]
53
+ why = "Coverage shows the Python branches and lines that no test runs, before a push."
@@ -1,52 +1,41 @@
1
1
  [configuration]
2
- title = "Swift Tests"
2
+ description = "Swift test files under XCTest and Swift Testing. A disabled test says why, and coverage holds a floor."
3
3
  requires = ["swift", "coverage"]
4
- description = "Swift test files under XCTest and Swift Testing. A disabled test says why, no test sleeps, and coverage holds a floor."
4
+ title = "Swift Tests"
5
5
 
6
6
  [detect]
7
- tags = ["swift-test", "swift-test-target"]
8
7
  paths = ["**/*.xctestplan"]
8
+ tags = ["swift-test", "swift-test-target"]
9
9
 
10
10
  [files]
11
- paths = ["**/*Tests/**/*.swift"]
12
11
  filenames = ["*.xctestplan"]
12
+ paths = ["**/*Tests/**/*.swift"]
13
13
 
14
14
  [[tool_file]]
15
+ per_scope = true
16
+ pointer = { path = ".swiftlint.yml", folders = ["**/*Tests"], body = "parent_config: {target_json}\ndisabled_rules:\n - force_unwrapping\n - missing_docs\n - no_magic_numbers\n" }
15
17
  target = ".gspot/config/swiftlint.yml"
16
18
  tool = "swiftlint"
17
- per_scope = true
18
- fragment = true
19
- pointer = { path = ".swiftlint.yml", directories = ["**/*Tests"], body = "parent_config: {target_json}\ndisabled_rules:\n - force_unwrapping\n - missing_docs\n - no_magic_numbers\n" }
20
19
 
21
20
  [[check]]
22
- name = "skip-reasons"
23
- example = "In a Swift test, `throw XCTSkip()` reports a missing reason. Restore the test, or supply a nonempty reason such as `throw XCTSkip(\"Requires the hardware test device\")`. The check requires a reason; it does not validate when the test will be enabled."
21
+ example = "`throw XCTSkip()` in a Swift test reports a missing reason. Restore the test, or give a reason such as `throw XCTSkip(\"Requires the hardware test device\")`."
22
+ files = { tags = ["swift-test"] }
23
+ help = "Write why the test stays off and what turns it on again, or delete it."
24
24
  level = "recommended"
25
+ name = "skip-reasons"
25
26
  stage = "commit"
26
- files = { tags = ["swift-test"] }
27
27
  summary = "Checks that skip calls and disabled traits name a nonempty reason, and unavailable tests carry an explanation."
28
- why = "A test turned off with no reason stays off, because nobody knows when it is safe to turn on."
29
- help = "Say why the test is off and what turns it back on, or delete the test."
30
-
31
- [[check]]
32
- name = "sleep"
33
- example = "A test using a fixed sleep to wait for asynchronous work reports a timing finding. Wait for the actual completion expectation or poll the required condition with a bounded timeout."
34
- level = "all"
35
- stage = "commit"
36
- files = { tags = ["swift-test"] }
37
- summary = "Refuses sleep calls in test files."
38
- why = "A sleep makes a test slow when it passes and flaky when the machine is slower than the number."
39
- help = "Wait on an expectation or a confirmation, or poll a condition with a timeout."
28
+ why = "A skipped test with no reason stays off, because nobody can tell when to restore it."
40
29
 
41
30
  [[check]]
42
- name = "coverage"
43
31
  example = "A Swift target reports 85% line coverage against a 90% floor. Add a test that exercises its uncovered lines, then rerun the target."
32
+ files = { extensions = [".swift"] }
33
+ help = "Add tests for the target, or lower its floor with a reason."
44
34
  level = "recommended"
45
- stage = "push"
46
- runs = "scope"
35
+ name = "coverage"
47
36
  needs = ["build"]
48
37
  operating_systems = ["macos", "linux"]
49
- files = { extensions = [".swift"] }
50
- summary = "Measures Xcode projects and Swift packages, holding each source target against coverage.lines and its coverage.override floor."
51
- why = "A target-specific coverage floor exposes Swift code that its test target has not exercised."
52
- help = "Add tests for the target, or lower its floor with a reason."
38
+ runs = "scope"
39
+ stage = "push"
40
+ summary = "Measures each source target in Xcode projects and Swift packages against `coverage.lines` and its `coverage.swift_target` floor."
41
+ why = "A floor for each target exposes Swift code that no test runs."
@@ -1,6 +1,8 @@
1
1
  # Swift Tests
2
2
 
3
- When you write tests, these rules cover XCTest, Swift Testing, and snapshot tests.
3
+ Read this rule when you write or change a Swift test.
4
+
5
+ These rules cover XCTest, Swift Testing, and snapshot tests.
4
6
 
5
7
  ## What to test
6
8
 
@@ -11,7 +13,7 @@ When you write tests, these rules cover XCTest, Swift Testing, and snapshot test
11
13
  - When the project uses view models, assert state transitions and what the application shows to the user, never private method calls.
12
14
  - Test invalid payload mapping and validate external data when it enters the program.
13
15
  - Test cancellation and stale results for asynchronous operations.
14
- - Do not mock SwiftUI or test its framework behavior.
16
+ - Do not mock SwiftUI.
15
17
  - Do not test trivial getters, setters, or framework behavior.
16
18
  - Do not add a protocol only to make a mock when the code already accepts the network or database client as an argument.
17
19
 
@@ -31,7 +33,7 @@ When you write tests, these rules cover XCTest, Swift Testing, and snapshot test
31
33
 
32
34
  - Test data shows the behavior under test.
33
35
  - Prefer private builders or stubs with sensible defaults when model construction hides the point of the test.
34
- - Keep test builders beside the tests that use them, unless many test files share them on purpose.
36
+ - Keep builders beside the tests that use them, unless many test files share them on purpose.
35
37
  - Decode JSON test data only when the test covers decoding, mapping, or the format of an external payload.
36
38
  - Do not add a production default to make a test shorter.
37
39
  - Prefer stable identifiers, dates, clocks, and ordering.
@@ -48,7 +50,7 @@ private extension Message {
48
50
  }
49
51
  ```
50
52
 
51
- Test builders belong in test code. A test setup API never becomes a second model layer.
53
+ A test setup API never becomes a second model layer.
52
54
 
53
55
  ## Style
54
56
 
@@ -57,7 +59,7 @@ Test builders belong in test code. A test setup API never becomes a second model
57
59
  - In XCTest, prefer throwing test methods with `try XCTUnwrap`.
58
60
  - In Swift Testing, prefer `try #require`.
59
61
  - Avoid `guard` in a test when an assertion helper states the failure directly.
60
- - Make test helpers and test data private unless several tests need them.
62
+ - Make helpers and test data private unless several tests need them.
61
63
 
62
64
  ## Disabled tests
63
65