@gspothq/cli 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/README.md +18 -2
  2. package/configurations/database/postgres/manifest.toml +114 -0
  3. package/configurations/database/postgres/rules/POSTGRES.md +78 -0
  4. package/configurations/framework/astro/eslint-presets.json +138 -0
  5. package/configurations/framework/astro/manifest.toml +95 -0
  6. package/configurations/framework/astro/rules/ASTRO.md +39 -0
  7. package/configurations/framework/expo/manifest.toml +43 -0
  8. package/configurations/framework/express/manifest.toml +17 -0
  9. package/configurations/framework/express/rules/EXPRESS.md +73 -0
  10. package/configurations/framework/express/semgrep/express.yml +71 -0
  11. package/configurations/framework/fastapi/manifest.toml +11 -0
  12. package/configurations/framework/fastapi/rules/FASTAPI.md +100 -0
  13. package/configurations/framework/fastapi/semgrep/fastapi.yml +44 -0
  14. package/configurations/framework/nestjs/eslint-presets.json +62 -0
  15. package/configurations/framework/nestjs/manifest.toml +52 -0
  16. package/configurations/framework/nestjs/rules/NESTJS.md +44 -0
  17. package/configurations/framework/nextjs/eslint-presets.json +73 -0
  18. package/configurations/framework/nextjs/manifest.toml +119 -0
  19. package/configurations/framework/nextjs/rules/NEXTJS.md +43 -0
  20. package/configurations/framework/react/eslint-presets.json +77 -0
  21. package/configurations/framework/react/manifest.toml +93 -0
  22. package/configurations/framework/react/rules/REACT.md +108 -0
  23. package/configurations/framework/react-dom/eslint-presets.json +110 -0
  24. package/configurations/framework/react-dom/manifest.toml +24 -0
  25. package/configurations/framework/react-native/manifest.toml +46 -0
  26. package/configurations/framework/react-native/rules/REACT-NATIVE.md +51 -0
  27. package/configurations/framework/site/manifest.toml +170 -0
  28. package/configurations/framework/site/rules/SITE.md +20 -0
  29. package/configurations/framework/svelte/eslint-presets.json +67 -0
  30. package/configurations/framework/svelte/manifest.toml +83 -0
  31. package/configurations/framework/svelte/rules/SVELTE.md +48 -0
  32. package/configurations/framework/vue/eslint-presets.json +180 -0
  33. package/configurations/framework/vue/manifest.toml +83 -0
  34. package/configurations/framework/vue/rules/VUE.md +41 -0
  35. package/configurations/general/commits/manifest.toml +111 -0
  36. package/configurations/general/commits/rules/GIT.md +31 -0
  37. package/configurations/general/coverage/manifest.toml +3 -0
  38. package/configurations/general/dependencies/manifest.toml +159 -0
  39. package/configurations/general/dependencies/rules/DEPENDENCIES.md +30 -0
  40. package/configurations/general/dependencies/syncpack.json +15 -0
  41. package/configurations/general/docs/manifest.toml +79 -0
  42. package/configurations/general/docs/rules/DOCS.md +86 -0
  43. package/configurations/general/duplication/manifest.toml +32 -0
  44. package/configurations/general/engineering/manifest.toml +8 -0
  45. package/configurations/general/engineering/rules/agent/PLANNING.md +42 -0
  46. package/configurations/general/engineering/rules/agent/SUPPRESSIONS.md +16 -0
  47. package/configurations/general/engineering/rules/agent/TALKING.md +3 -0
  48. package/configurations/general/engineering/rules/agent/TASKS.md +19 -0
  49. package/configurations/general/engineering/rules/agent/WORKING.md +83 -0
  50. package/configurations/general/engineering/rules/code/ACCESSIBILITY.md +32 -0
  51. package/configurations/general/engineering/rules/code/CLI.md +37 -0
  52. package/configurations/general/engineering/rules/code/COMMENTS.md +38 -0
  53. package/configurations/general/engineering/rules/code/CONFIGURATION.md +25 -0
  54. package/configurations/general/engineering/rules/code/ERRORS.md +49 -0
  55. package/configurations/general/engineering/rules/code/HTTP.md +46 -0
  56. package/configurations/general/engineering/rules/code/LOGGING.md +55 -0
  57. package/configurations/general/engineering/rules/code/TESTING.md +58 -0
  58. package/configurations/general/files/manifest.toml +141 -0
  59. package/configurations/general/files/rules/YAML.md +19 -0
  60. package/configurations/general/format/manifest.toml +152 -0
  61. package/configurations/general/gspot/manifest.toml +65 -0
  62. package/configurations/general/gspot/rules/GENERATED.md +10 -0
  63. package/configurations/general/licenses/manifest.toml +33 -0
  64. package/configurations/general/naming/defaults.json +423 -0
  65. package/configurations/general/naming/manifest.toml +35 -0
  66. package/configurations/general/naming/rules/NAMING.md +179 -0
  67. package/configurations/general/prose/manifest.toml +86 -0
  68. package/configurations/general/prose/rules/WRITING.md +31 -0
  69. package/configurations/general/prose/vale/styles/LICENSES.md +55 -0
  70. package/configurations/general/prose/vale/styles/gspot/ampm.yml +8 -0
  71. package/configurations/general/prose/vale/styles/gspot/conscious-language.yml +16 -0
  72. package/configurations/general/prose/vale/styles/gspot/contractions.yml +43 -0
  73. package/configurations/general/prose/vale/styles/gspot/currency.yml +8 -0
  74. package/configurations/general/prose/vale/styles/gspot/dashes.yml +8 -0
  75. package/configurations/general/prose/vale/styles/gspot/date-ordinals.yml +41 -0
  76. package/configurations/general/prose/vale/styles/gspot/dates.yml +7 -0
  77. package/configurations/general/prose/vale/styles/gspot/file-paths.yml +7 -0
  78. package/configurations/general/prose/vale/styles/gspot/future.yml +17 -0
  79. package/configurations/general/prose/vale/styles/gspot/hedging.yml +22 -0
  80. package/configurations/general/prose/vale/styles/gspot/history.yml +16 -0
  81. package/configurations/general/prose/vale/styles/gspot/idioms.yml +21 -0
  82. package/configurations/general/prose/vale/styles/gspot/interface-verbs.yml +11 -0
  83. package/configurations/general/prose/vale/styles/gspot/jargon.yml +11 -0
  84. package/configurations/general/prose/vale/styles/gspot/leading-conjunctions.yml +12 -0
  85. package/configurations/general/prose/vale/styles/gspot/link-text.yml +8 -0
  86. package/configurations/general/prose/vale/styles/gspot/locations.yml +14 -0
  87. package/configurations/general/prose/vale/styles/gspot/marketing.yml +26 -0
  88. package/configurations/general/prose/vale/styles/gspot/merge-conflict-markers.yml +13 -0
  89. package/configurations/general/prose/vale/styles/gspot/militaristic-language.yml +22 -0
  90. package/configurations/general/prose/vale/styles/gspot/modals.yml +9 -0
  91. package/configurations/general/prose/vale/styles/gspot/numbered-units.yml +18 -0
  92. package/configurations/general/prose/vale/styles/gspot/obvious-fields.yml +14 -0
  93. package/configurations/general/prose/vale/styles/gspot/ordinal-adverbs.yml +15 -0
  94. package/configurations/general/prose/vale/styles/gspot/percentage-numbers.yml +8 -0
  95. package/configurations/general/prose/vale/styles/gspot/placeholders.yml +7 -0
  96. package/configurations/general/prose/vale/styles/gspot/product-centric-writing.yml +8 -0
  97. package/configurations/general/prose/vale/styles/gspot/punctuated-headings.yml +11 -0
  98. package/configurations/general/prose/vale/styles/gspot/self-reference.yml +15 -0
  99. package/configurations/general/prose/vale/styles/gspot/session-identifiers.yml +11 -0
  100. package/configurations/general/prose/vale/styles/gspot/since.yml +6 -0
  101. package/configurations/general/prose/vale/styles/gspot/straight-quotes.yml +11 -0
  102. package/configurations/general/prose/vale/styles/gspot/suspended-hyphens.yml +8 -0
  103. package/configurations/general/prose/vale/styles/gspot/symbols.yml +8 -0
  104. package/configurations/general/prose/vale/styles/gspot/time-ranges.yml +14 -0
  105. package/configurations/general/prose/vale/styles/gspot/url-prepositions.yml +10 -0
  106. package/configurations/general/prose/vale/styles/gspot/version-range.yml +8 -0
  107. package/configurations/general/repository/manifest.toml +24 -0
  108. package/configurations/general/secrets/gitleaks.toml +2 -0
  109. package/configurations/general/secrets/manifest.toml +125 -0
  110. package/configurations/general/secrets/rules/SECRETS.md +13 -0
  111. package/configurations/general/security/manifest.toml +77 -0
  112. package/configurations/general/security/rules/SECURITY.md +55 -0
  113. package/configurations/general/spelling/manifest.toml +46 -0
  114. package/configurations/general/structure/manifest.toml +70 -0
  115. package/configurations/infrastructure/ansible/manifest.toml +33 -0
  116. package/configurations/infrastructure/docker/manifest.toml +127 -0
  117. package/configurations/infrastructure/docker/rules/DOCKER.md +135 -0
  118. package/configurations/infrastructure/docker/trivyignore +2 -0
  119. package/configurations/infrastructure/github-actions/manifest.toml +76 -0
  120. package/configurations/infrastructure/github-actions/rules/GITHUB-ACTIONS.md +43 -0
  121. package/configurations/infrastructure/github-actions/zizmor.yml +3 -0
  122. package/configurations/infrastructure/nginx/manifest.toml +51 -0
  123. package/configurations/infrastructure/nginx/rules/NGINX.md +38 -0
  124. package/configurations/infrastructure/openapi/manifest.toml +50 -0
  125. package/configurations/infrastructure/openapi/rules/OPENAPI.md +39 -0
  126. package/configurations/infrastructure/xcode/manifest.toml +131 -0
  127. package/configurations/infrastructure/xcode/rules/XCODE.md +34 -0
  128. package/configurations/language/bash/manifest.toml +261 -0
  129. package/configurations/language/bash/rules/BASH.md +106 -0
  130. package/configurations/language/bash/rules/LANGUAGE.md +213 -0
  131. package/configurations/language/bash/rules/NAMING.md +62 -0
  132. package/configurations/language/bash/rules/OPERATIONS.md +77 -0
  133. package/configurations/language/bash/rules/SAFETY.md +222 -0
  134. package/configurations/language/bash/semgrep/bash.yml +30 -0
  135. package/configurations/language/css/manifest.toml +98 -0
  136. package/configurations/language/css/rules/CSS.md +28 -0
  137. package/configurations/language/css/rules/NAMING.md +17 -0
  138. package/configurations/language/css/rules/TAILWIND.md +26 -0
  139. package/configurations/language/css/stylelint-rule-names.json +89 -0
  140. package/configurations/language/html/manifest.toml +59 -0
  141. package/configurations/language/html/rules/HTML.md +27 -0
  142. package/configurations/language/html/rules/NAMING.md +16 -0
  143. package/configurations/language/javascript/eslint-presets.json +997 -0
  144. package/configurations/language/javascript/eslint-rule-names.json +299 -0
  145. package/configurations/language/javascript/eslint-runtime-names.json +61 -0
  146. package/configurations/language/javascript/manifest.toml +393 -0
  147. package/configurations/language/javascript/rules/BUN.md +13 -0
  148. package/configurations/language/javascript/rules/COMPONENTS.md +18 -0
  149. package/configurations/language/javascript/rules/DENO.md +15 -0
  150. package/configurations/language/javascript/rules/JAVASCRIPT.md +60 -0
  151. package/configurations/language/javascript/rules/NAMING.md +31 -0
  152. package/configurations/language/javascript/rules/NODE.md +21 -0
  153. package/configurations/language/javascript/rules/PLAYWRIGHT.md +34 -0
  154. package/configurations/language/javascript/semgrep/javascript.yml +84 -0
  155. package/configurations/language/markdown/manifest.toml +85 -0
  156. package/configurations/language/markdown/markdownlint-cli2.mjs +19 -0
  157. package/configurations/language/python/manifest.toml +621 -0
  158. package/configurations/language/python/rules/DESIGN.md +136 -0
  159. package/configurations/language/python/rules/FLOW.md +124 -0
  160. package/configurations/language/python/rules/NAMING.md +53 -0
  161. package/configurations/language/python/rules/PACKAGING.md +49 -0
  162. package/configurations/language/python/rules/PYTHON.md +136 -0
  163. package/configurations/language/python/rules/TYPING.md +132 -0
  164. package/configurations/language/sql/manifest.toml +68 -0
  165. package/configurations/language/sql/rules/NAMING.md +90 -0
  166. package/configurations/language/sql/rules/SQL.md +9 -0
  167. package/configurations/language/swift/manifest.toml +164 -0
  168. package/configurations/language/swift/rules/NAMING.md +88 -0
  169. package/configurations/language/swift/rules/SWIFT.md +134 -0
  170. package/configurations/language/swift/rules/SWIFTUI.md +61 -0
  171. package/configurations/language/swift/rules/UIKIT.md +99 -0
  172. package/configurations/language/swift/semgrep/swift.yml +126 -0
  173. package/configurations/language/typescript/eslint-presets.json +215 -0
  174. package/configurations/language/typescript/manifest.toml +72 -0
  175. package/configurations/language/typescript/rules/NAMING.md +73 -0
  176. package/configurations/language/typescript/rules/TYPESCRIPT.md +79 -0
  177. package/configurations/library/drizzle/manifest.toml +68 -0
  178. package/configurations/library/drizzle/rules/DRIZZLE.md +44 -0
  179. package/configurations/library/react-hook-form/manifest.toml +15 -0
  180. package/configurations/library/react-hook-form/rules/REACT-HOOK-FORM.md +48 -0
  181. package/configurations/library/swift-snapshot-testing/manifest.toml +32 -0
  182. package/configurations/library/tanstack-query/eslint-presets.json +21 -0
  183. package/configurations/library/tanstack-query/manifest.toml +26 -0
  184. package/configurations/library/tanstack-query/rules/TANSTACK-QUERY.md +41 -0
  185. package/configurations/library/testing-library/eslint-presets.json +191 -0
  186. package/configurations/library/testing-library/manifest.toml +47 -0
  187. package/configurations/library/translations/manifest.toml +40 -0
  188. package/configurations/library/translations/rules/NEXT-INTL.md +33 -0
  189. package/configurations/library/translations/rules/TRANSLATIONS.md +102 -0
  190. package/configurations/library/trpc/manifest.toml +14 -0
  191. package/configurations/library/trpc/rules/TRPC.md +43 -0
  192. package/configurations/library/zod/manifest.toml +25 -0
  193. package/configurations/library/zod/rules/ZOD.md +44 -0
  194. package/configurations/library/zustand/manifest.toml +18 -0
  195. package/configurations/library/zustand/rules/ZUSTAND.md +106 -0
  196. package/configurations/platform/cloudflare/manifest.toml +94 -0
  197. package/configurations/platform/cloudflare/rules/CLOUDFLARE.md +23 -0
  198. package/configurations/platform/cloudflare/semgrep/cloudflare.yml +12 -0
  199. package/configurations/platform/supabase/manifest.toml +112 -0
  200. package/configurations/platform/supabase/rules/SUPABASE.md +129 -0
  201. package/configurations/platform/supabase/semgrep/supabase.yml +60 -0
  202. package/configurations/testing/jest/manifest.toml +54 -0
  203. package/configurations/testing/pytest/manifest.toml +53 -0
  204. package/configurations/testing/swift-tests/manifest.toml +52 -0
  205. package/configurations/testing/swift-tests/rules/SWIFT-TESTS.md +79 -0
  206. package/configurations/testing/vitest/eslint-presets.json +22 -0
  207. package/configurations/testing/vitest/manifest.toml +69 -0
  208. package/configurations/testing/vitest/rules/VITEST.md +18 -0
  209. package/dist/LICENSE.md +201 -0
  210. package/dist/THIRD-PARTY-NOTICES.md +25 -0
  211. package/dist/eslint-rule-levels.json +10 -0
  212. package/dist/gspot.js +30740 -0
  213. package/dist/linkinator-program.js +65 -0
  214. package/dist/purgecss-program.js +51 -0
  215. package/dist/tool-versions.json +3 -0
  216. package/grammars/bash.wasm +0 -0
  217. package/grammars/css.wasm +0 -0
  218. package/grammars/html.wasm +0 -0
  219. package/grammars/javascript.wasm +0 -0
  220. package/grammars/licenses/tree-sitter-bash.txt +21 -0
  221. package/grammars/licenses/tree-sitter-css.txt +21 -0
  222. package/grammars/licenses/tree-sitter-html.txt +21 -0
  223. package/grammars/licenses/tree-sitter-javascript.txt +21 -0
  224. package/grammars/licenses/tree-sitter-python.txt +21 -0
  225. package/grammars/licenses/tree-sitter-swift.txt +21 -0
  226. package/grammars/licenses/tree-sitter-typescript.txt +21 -0
  227. package/grammars/python.wasm +0 -0
  228. package/grammars/swift.wasm +0 -0
  229. package/grammars/tsx.wasm +0 -0
  230. package/grammars/typescript.wasm +0 -0
  231. package/gspot.schema.json +45991 -0
  232. package/package.json +93 -5
@@ -0,0 +1,68 @@
1
+ allowed_words = ["SQL"]
2
+ [configuration]
3
+ title = "SQL"
4
+ suggests = []
5
+ description = "SQLFluff checks layout and style in the project dialect. At all, SQL checks line comments, file length, and PostgreSQL function structure."
6
+
7
+ [files]
8
+ extensions = [".sql", ".pgsql", ".psql"]
9
+
10
+ [[tool]]
11
+ name = "sqlfluff"
12
+ crash_pattern = '^Traceback \(most recent call last\):$'
13
+ suppression = { marker = "\\bnoqa\\b", reason = "--[^\\n]*?-- ?(?<reason>\\S.*)" }
14
+ version = "4.3.0"
15
+ min_version = "3.0.0"
16
+ pypi = "sqlfluff"
17
+ mise = "pipx:sqlfluff"
18
+ brew = "sqlfluff"
19
+ [[tool.replace]]
20
+ file = ".sqlfluff"
21
+ shared = false
22
+
23
+ [[tool.replace]]
24
+ file = ".sqlfluffignore"
25
+ shared = false
26
+
27
+ [[tool.replace]]
28
+ file = "pyproject.toml"
29
+ table = "tool.sqlfluff"
30
+ shared = true
31
+
32
+ [[tool.replace]]
33
+ file = "setup.cfg"
34
+ table = "sqlfluff"
35
+ shared = true
36
+
37
+ [[tool.replace]]
38
+ file = "tox.ini"
39
+ table = "sqlfluff"
40
+ shared = true
41
+
42
+ [[tool_file]]
43
+ target = ".gspot/config/sqlfluff.cfg"
44
+ tool = "sqlfluff"
45
+ per_scope = true
46
+ rule_keys = ["sqlfluff.exclude_rules", "sqlfluff:rules"]
47
+
48
+ [[check]]
49
+ name = "sqlfluff"
50
+ example = "The query `select id from user_accounts;` reports CP01 under the configured uppercase keyword policy. Format it as `SELECT id FROM user_accounts;` and rerun using the project dialect."
51
+ level = "recommended"
52
+ stage = "commit"
53
+ command = ["sqlfluff", "lint", "--config", "{tool_file:sqlfluff}", "--ignore-local-config", "--disable-progress-bar", "--format", "json", "{files}"]
54
+ exit_codes = [1]
55
+ fix = ["sqlfluff", "fix", "--config", "{tool_file:sqlfluff}", "--ignore-local-config", "--disable-progress-bar", "{files}"]
56
+ output = { format = "json", children = "violations", fields = { file = "filepath", line = "start_line_no", column = "start_line_pos", rule = "code", message = "description" } }
57
+ summary = "Lints every SQL file for layout, capitalization, aliasing, and ambiguous references, in the dialect the database configuration names."
58
+ why = "SQL that reads one way in every file lets a reviewer look at what the statement does."
59
+ help = "Run gspot check --fix. Turn one rule off with gspot ignore sql/sqlfluff --rule `<code>` --reason \"`<why>`\"."
60
+
61
+ [[check]]
62
+ name = "functions"
63
+ example = "A SQL function that only forwards one expression reports a trivial-function finding. Inline unnecessary calls and delete the function. If an external API requires the signature, record that with `gspot ignore` and a reason."
64
+ level = "all"
65
+ stage = "commit"
66
+ summary = "For the postgres dialect, reports trivial SQL and PL/pgSQL functions and excessive declared input parameters."
67
+ why = "Unnecessary functions add indirection; excessive parameters obscure responsibilities."
68
+ help = "Inline unnecessary functions. If a required API needs one, run `gspot ignore sql/functions --paths <file> --reason <why>`. Reduce parameters or configure limits.sql.function_parameters."
@@ -0,0 +1,90 @@
1
+ # SQL Naming
2
+
3
+ SQL names define durable infrastructure interfaces. Rename them only
4
+ through migrations and contract-aware code changes.
5
+
6
+ ## SQL case rules
7
+
8
+ <!-- level: all -->
9
+
10
+ - SQL schemas, tables, columns, functions, function parameters, indexes,
11
+ triggers, constraints, and policies use `lower_snake_case`.
12
+ - Fully qualify grants and function signatures when names have more than one possible meaning.
13
+ - Do not use quoted sentence-style identifiers for local policy names.
14
+ - Do not use pluralization or prefixes inconsistently inside one schema.
15
+
16
+ | Avoid | Prefer | Meaning |
17
+ | ---------------------------- | -------------------------------- | ---------------------------------- |
18
+ | `public.OrderItems` | `public.order_items` | An order-item table. |
19
+ | `users_can_view_order_items` | `users_can_view_own_order_items` | A policy restricted to owned rows. |
20
+
21
+ The policy name must describe its actual predicate. A name that says "own"
22
+ does not establish ownership checks or enable Row Level Security.
23
+
24
+ ## Migration filenames
25
+
26
+ <!-- level: all -->
27
+
28
+ Follow the migration tool's file names. Name each migration for its durable database change.
29
+
30
+ ## SQL tables and columns
31
+
32
+ <!-- level: all -->
33
+
34
+ - Table names identify the domain set stored by the relation.
35
+ - Column names identify the value, not the application layer that reads it.
36
+ - Foreign-key columns use the referenced concept plus `_id`.
37
+ - Timestamp columns use stable event names such as `created_at`,
38
+ `updated_at`, `deleted_at`, or a concrete domain event time.
39
+ - Boolean columns use concise positive assertion names without an `is_`
40
+ prefix.
41
+ - Avoid generic columns that hide meaning.
42
+
43
+ | Avoid | Prefer | Meaning |
44
+ | --------- | --------------------------- | ------------------------- |
45
+ | `data` | `message_delivery_attempts` | Delivery attempt table. |
46
+ | `payload` | `provider_response` | Response payload column. |
47
+ | `flag` | `retryable` | Retry eligibility column. |
48
+ | `date` | `attempted_at` | Attempt timestamp column. |
49
+
50
+ ## SQL functions and parameters
51
+
52
+ <!-- level: all -->
53
+
54
+ - SQL function names use verb phrases or domain operation names. These verbs govern function
55
+ names, not migration filenames.
56
+
57
+ - Retrieval functions use `get_` regardless of whether they return one row,
58
+ an optional row, a collection, or a paginated collection. Do not use
59
+ `read_`, `find_`, `fetch_`, `load_`, or `list_` as retrieval synonyms.
60
+ - Data-access mutation functions use `set_`, `insert_`, `update_`, or
61
+ `delete_` according to the operation they perform. Do not use `create_`,
62
+ `add_`, `save_`, `write_`, `put_`, `upsert_`, or `remove_` as synonyms.
63
+ - Function parameters use `lower_snake_case`.
64
+ - Parameter names never collide with table column names.
65
+ - `SECURITY DEFINER` functions must have names that make the privileged action
66
+ clear.
67
+ - Do not name functions like arbitrary script tasks.
68
+
69
+ Use `archive_expired_orders` for a transactional operation that archives
70
+ expired orders. Name its user argument `target_user_id` when `user_id` already names
71
+ already a column in the affected tables. A generic `run` name hides the
72
+ operation, and an unqualified `id` can obscure column ownership.
73
+
74
+ ## Indexes, constraints, triggers, and policies
75
+
76
+ <!-- level: all -->
77
+
78
+ - Name constraints and scope them to their table or concept.
79
+ - Name indexes by table plus indexed columns or purpose.
80
+ - Name triggers by event and action.
81
+ - Name policies by actor plus allowed action.
82
+ - Keep names stable because they appear in migrations, errors, grants, and
83
+ database inspection output.
84
+
85
+ | Avoid | Prefer | Meaning |
86
+ | --------------- | --------------------------------- | ------------------------------------ |
87
+ | `idx1` | `messages_user_id_created_at_idx` | Index on user and creation time. |
88
+ | `check_status` | `messages_status_not_empty_check` | Nonempty status constraint. |
89
+ | `trigger1` | `messages_set_updated_at` | Update timestamp trigger. |
90
+ | `select_policy` | `users_can_view_own_messages` | Policy restricted to owned messages. |
@@ -0,0 +1,9 @@
1
+ # SQL
2
+
3
+ ## SQL style
4
+
5
+ - Fully qualify cross-schema references.
6
+ - Prefer explicit column lists for every `INSERT` and every grant of write
7
+ privileges.
8
+ - Keep table constraints close to the table definition unless the migration must add them
9
+ later for dependency reasons.
@@ -0,0 +1,164 @@
1
+ allowed_words = ["Swift", "SwiftLint", "SwiftFormat", "Periphery"]
2
+
3
+ ignored_folders = [".build", "DerivedData", "Pods"]
4
+
5
+ [configuration]
6
+ title = "Swift"
7
+ suggests = []
8
+ description = "Swift sources: SwiftLint with stable rules selected by level and analyzer rules, SwiftFormat, a build, and Periphery for dead code."
9
+
10
+ [detect]
11
+ extensions = [".swift"]
12
+ project_files = ["Package.swift"]
13
+
14
+ [files]
15
+ extensions = [".swift"]
16
+ filenames = ["Package.swift", "Package.resolved"]
17
+
18
+ [[tool]]
19
+ name = "swiftlint"
20
+ rule_url = "https://realm.github.io/SwiftLint/{rule}.html"
21
+ suppression = { marker = "\\bswiftlint:disable\\b", reason = " - (?<reason>\\S.*)" }
22
+ builds = ["macos", "linux"]
23
+ version = "0.63.2"
24
+ min_version = "0.57.0"
25
+ mise = "swiftlint"
26
+ brew = "swiftlint"
27
+ github = { name = "realm/SwiftLint", version = "0.63.2" }
28
+ version_command = ["version"]
29
+ [[tool.replace]]
30
+ file = ".swiftlint.yml"
31
+ shared = false
32
+
33
+ [[tool.replace]]
34
+ file = ".swiftlint.yaml"
35
+ shared = false
36
+
37
+ [[tool]]
38
+ name = "swiftformat"
39
+ suppression = { marker = "\\bswiftformat:disable\\b", reason = " - (?<reason>\\S.*)" }
40
+ builds = ["macos", "linux"]
41
+ version = "0.61.1"
42
+ min_version = "0.54.0"
43
+ # The GitHub release ships an app bundle beside the executable, which mise skips.
44
+ mise = { name = "swiftformat", version = "0.61.1", options = { no_app = true, rename_exe = "swiftformat" } }
45
+ brew = "swiftformat"
46
+ github = { name = "nicklockwood/SwiftFormat", version = "0.61.1" }
47
+ [[tool.replace]]
48
+ file = ".swiftformat"
49
+ shared = false
50
+
51
+ [[tool]]
52
+ name = "periphery"
53
+ suppression = { marker = "\\bperiphery:ignore\\b", reason = " - (?<reason>\\S.*)" }
54
+ builds = ["macos"]
55
+ version = "3.6.0"
56
+ min_version = "3.0.0"
57
+ mise = "periphery"
58
+ brew = "periphery"
59
+ github = { name = "peripheryapp/periphery", version = "3.6.0" }
60
+ version_command = ["version"]
61
+ [[tool.replace]]
62
+ file = ".periphery.yml"
63
+ shared = false
64
+
65
+ [[tool.replace]]
66
+ file = ".periphery.yaml"
67
+ shared = false
68
+
69
+ [[tool]]
70
+ name = "swift"
71
+ system = true
72
+
73
+ [[tool]]
74
+ name = "xcodebuild"
75
+ install_hint = "install Xcode from the App Store"
76
+ system = true
77
+
78
+ [[tool_file]]
79
+ target = ".gspot/config/swiftlint.yml"
80
+ tool = "swiftlint"
81
+ rule_keys = ["opt_in_rules", "analyzer_rules", "disabled_rules"]
82
+ per_scope = true
83
+ pointer = { path = ".swiftlint.yml", body = "parent_config: {target_json}\n" }
84
+
85
+ [[tool_file]]
86
+ target = ".gspot/config/swiftformat"
87
+ tool = "swiftformat"
88
+ rule_keys = ["enable", "disable"]
89
+ per_scope = true
90
+
91
+ [[tool_file]]
92
+ target = ".gspot/config/periphery.yml"
93
+ tool = "periphery"
94
+ per_scope = true
95
+
96
+ [[check]]
97
+ name = "swiftlint"
98
+ example = "The forced cast `value as! NSString` reports `force_cast`. Use a conditional cast and handle the failed conversion, or change the input contract so no cast is required."
99
+ level = "recommended"
100
+ stage = "commit"
101
+ tool = "swiftlint"
102
+ command = ["swiftlint", "lint", "--strict", "--quiet", "--no-cache", "--reporter", "json", "{files}"]
103
+ fix = ["swiftlint", "lint", "--fix", "--quiet", "--no-cache", "{files}"]
104
+ cwd = "scope"
105
+ files = { extensions = [".swift"] }
106
+ output = { format = "json", fields = { file = "file", line = "line", column = "character", rule = "rule_id", message = "reason" } }
107
+ summary = "Lints Swift files with the scoped and nested SwiftLint configurations, treating warnings as errors."
108
+ why = "Forced casts and tries can crash, and a strong delegate can retain its owner. Find these before committing."
109
+ help = "Run gspot check --fix for the rules that fix themselves. Turn one rule off with gspot ignore swift/swiftlint --rule `<id>` --reason \"`<why>`\"."
110
+
111
+ [[check]]
112
+ name = "swiftformat"
113
+ example = "A declaration beginning `func greeting` reports `consecutiveSpaces`. Run the configured formatter to obtain `func greeting`, inspect the diff, and rerun."
114
+ level = "recommended"
115
+ stage = "commit"
116
+ command = ["swiftformat", "--lint", "--config", "{tool_file:swiftformat}", "{files}"]
117
+ exit_codes = [1]
118
+ fix = ["swiftformat", "--quiet", "--config", "{tool_file:swiftformat}", "{files}"]
119
+ files = { extensions = [".swift"] }
120
+ output = { format = "regex", pattern = "^(?<file>.+?):(?<line>\\d+):(?<column>\\d+): (?:error|warning): \\((?<rule>\\w+)\\) (?<message>.*)$" }
121
+ summary = "Checks the layout of every Swift file against the shipped SwiftFormat rules."
122
+ why = "One layout everywhere keeps a diff about the change and not about where a brace went."
123
+ help = "Run gspot check --fix."
124
+
125
+ [[check]]
126
+ name = "build"
127
+ example = "A Swift assignment of a string to an `Int` variable fails compilation. Correct the value or declared type and rerun with the required compiler and project settings available."
128
+ level = "recommended"
129
+ stage = "push"
130
+ runs = "scope"
131
+ needs = ["build"]
132
+ operating_systems = ["macos", "linux"]
133
+ summary = "Builds the package or Xcode scheme incrementally to report compiler errors."
134
+ why = "Swift has no type check without a build, so the build is the type check."
135
+ help = "Fix the first compiler error; later ones are often the same mistake."
136
+
137
+ [[check]]
138
+ name = "swiftlint-analyze"
139
+ example = "An import unused by the compiled Swift sources reports an analyzer finding. Remove the import and rerun the build-backed analysis. A missing build log does not establish a clean result."
140
+ level = "recommended"
141
+ stage = "manual"
142
+ runs = "scope"
143
+ needs = ["build"]
144
+ operating_systems = ["macos"]
145
+ tool = "swiftlint"
146
+ summary = "Runs the SwiftLint analyzer rules over the compiler log of the build: unused imports and captured variables."
147
+ why = "These rules need the compiler's view of the code, which a file-by-file lint does not have."
148
+ help = "Remove what the rule names. Keep an import the analyzer misjudges under tools.swiftlint.always_keep_imports."
149
+
150
+ [[check]]
151
+ name = "periphery"
152
+ example = "A declaration with no references in the selected compiled project reports unused code. Delete the unused declaration and rebuild before rerunning. Runtime-only references require a specific documented exception."
153
+ level = "recommended"
154
+ stage = "push"
155
+ runs = "scope"
156
+ needs = ["build"]
157
+ tool = "periphery"
158
+ summary = "Scans the built project for declarations nothing uses."
159
+ why = "Dead code is read, maintained, and migrated by people who cannot tell it is dead."
160
+ help = "Delete the declaration, or mark it with a periphery:ignore comment that says who uses it."
161
+
162
+ [rules]
163
+ "SWIFTUI.md" = { tags = ["swift-import:SwiftUI"] }
164
+ "UIKIT.md" = { tags = ["swift-import:UIKit"] }
@@ -0,0 +1,88 @@
1
+ # Swift Naming
2
+
3
+ Swift naming follows the Apple API Design Guidelines and optimizes for call-site clarity.
4
+
5
+ ## Case, scope, and files
6
+
7
+ <!-- level: all -->
8
+
9
+ Preserve external names and domain notation that the team uses. Express privacy through access
10
+ modifiers, not an underscore.
11
+
12
+ Express a structural relationship through nesting rather than a longer
13
+ top-level name: `Parser.Error`, not `ParseError`. A static property does not repeat its
14
+ declaring type: `UIColor.primary`, not `UIColor.primaryColor`. Use `shared` and `default`
15
+ only when they describe the role. Use an empty enum as a namespace only for tightly related
16
+ constants or functions never instantiated.
17
+
18
+ ## Roles
19
+
20
+ <!-- level: all -->
21
+
22
+ A suffix says what a type owns and means one thing across the whole codebase. If `Repository`
23
+ owns domain-facing data access in one feature, it does not own HTTP mechanics in another.
24
+ Which suffixes a project uses depends on the pattern it picked, but these framework words have
25
+ one meaning:
26
+
27
+ | Role word | Use when |
28
+ | ---------------- | -------------------------------------------------------------------------------------- |
29
+ | `View` | SwiftUI view or UIKit view type that presents UI. |
30
+ | `ViewController` | UIKit screen controller. |
31
+ | `ViewModel` | Presentation state and user intent owner for one screen, flow, or cohesive surface. |
32
+ | `ViewState` | Value describing screen presentation state. |
33
+ | `ViewAction` | Typed user or lifecycle intent emitted by a view. |
34
+ | `Coordinator` | Navigation or flow state owner. |
35
+ | `Router` | Route mutation or destination-selection boundary, narrower than a coordinator. |
36
+ | `DataSource` | UIKit list adapter that feeds rows and sections. |
37
+ | `CellModel` | Values a reusable cell renders: strings, image references, state, and lightweight IDs. |
38
+
39
+ Repository protocols speak domain language and return domain results through domain
40
+ operations such as `TemplateRepository.getTemplate`; an implementation may name its technology
41
+ such as `HTTPTemplateRepository` when that distinguishes real implementations. Client types own
42
+ external API or SDK mechanics such as `TemplateAPIClient`. Coordinators own route state, destination
43
+ construction, stack mutations, and presentation flow such as `TemplateCoordinator.showEditTemplate`.
44
+ Keep route enums within their feature and name them for the flow. Give them stable domain identifiers
45
+ such as `TemplateDestination.editTemplate`. Never give them view models, views, repository implementations, SDK
46
+ clients, database records, or DTOs.
47
+
48
+ ## Methods, labels, and delegates
49
+
50
+ <!-- level: all -->
51
+
52
+ When the project uses view models, name a direct UI event for the event
53
+ such as `submitButtonTapped()`, `cameraPermissionDenied()`, `selectedItemChanged(to:)`. Name domain work
54
+ with a domain verb such as `enqueueFileUpload(_:)`, `refreshOrderHistory(for:)`,
55
+ `validateEmailAddress(_:)`; `handle`, `process`, and `didTap` name neither. Reserve `handle...` for
56
+ reserved for literal UIKit target-action and notification handlers marked `@objc`.
57
+
58
+ Names form grammatical English at the call site: omit the first label when the base
59
+ name and argument form a phrase and included when it clarifies a weak type. Initializer
60
+ arguments that set stored properties use the property names with explicit `self.`, and
61
+ factories use `make...` such as `makeTemplateView(for:)`. Nonmutating methods without side effects
62
+ read as noun phrases, and mutating methods read as imperatives. Pairs follow `sort`/`sorted`,
63
+ `append`/`appending`, `formUnion`/`union`.
64
+
65
+ A delegate method passes the source object first and unlabeled, and never trims its signature because
66
+ one caller currently owns it. Name a source-only `Void` event with the source type plus a tense
67
+ phrase: `draftStore(_:didDeleteDraft:)`. A source-only `Bool` answer uses `can`, `is`, or
68
+ another predicate, never `should` or `may`: `draftStoreCanDeleteDraft`. Name a source-only value with a
69
+ noun phrase with a natural preposition: `numberOfSections(in:)`. Extra arguments make the
70
+ second label describe the event or requested value:
71
+ `messageListDataSource(_:heightForMessageAt:)`.
72
+
73
+ ## Protocols and identifiers
74
+
75
+ <!-- level: all -->
76
+
77
+ A protocol carries no `I` prefix and no `Protocol` suffix. Name a domain role with a noun such as `TemplateRepository`. Name a capability for its behavior, often with `-ing`,
78
+ such as `ProgressReporting`, `ThemeColorProviding`, or `LoginCoordinating`. Avoid an automatic `-able`
79
+ name that describes no clear capability. `Provider`, `Repository`, `Client`, and
80
+ `Coordinating` appear only when the protocol serves that role, and no protocol exists per ViewModel or use
81
+ case merely to enable mocks.
82
+
83
+ Presentation identifiers provide stable interfaces for UI identity, diffable data sources,
84
+ navigation, persistence, and tests, named for what they identify rather than the framework
85
+ that consumes them. Snapshot items use stable presentation or domain IDs, never DTO identity,
86
+ array offsets, or index paths. `id` suffices when the enclosing type supplies the context
87
+ such as `MessageRow.id`; a role-qualified name such as `selectedMessageID` or `conversationID`
88
+ serves a scope with several identifiers.
@@ -0,0 +1,134 @@
1
+ # Swift
2
+
3
+ Swift source follows the Apple API Design Guidelines and the local formatting and lint
4
+ configuration. SwiftFormat owns layout. Treat warnings as errors in the build settings.
5
+
6
+ ## Files and style
7
+
8
+ Every file imports exactly the top-level modules it uses, as whole modules unless a single
9
+ declaration avoids a known conflict. Group imports by compiler condition, with
10
+ `@testable import` after regular imports in tests. `// MARK: - Section` marks meaningful groups in larger files,
11
+ and a file comment appears only when the file groups several abstractions and the grouping
12
+ needs explanation. Type inference covers a right-hand side with a clear type; an explicit annotation
13
+ covers empty collections, `nil` initial values, weak type information, and public API
14
+ clarity. Enum raw values that map to an external wire or persistence contract need documentation;
15
+ an explicit case list replaces `default` where a future case must force review. Attributes
16
+ with parameters go on their own line when they hurt readability inline.
17
+
18
+ ### File organization
19
+
20
+ <!-- level: all -->
21
+
22
+ One primary top-level type per file, with small private helpers allowed beside it. Keep overloads adjacent. Organize extensions rather than scattering them across files. Group SwiftUI
23
+ dynamic properties by property-wrapper type.
24
+
25
+ Good:
26
+
27
+ ```swift
28
+ private func sumPositive(_ values: [Int]) -> Int {
29
+ var total = 0
30
+ for value in values where value > 0 {
31
+ total += value
32
+ }
33
+ return total
34
+ }
35
+
36
+ /// Compare the sums of positive values in two collections.
37
+ public func comparePositiveTotals(_ left: [Int], _ right: [Int]) -> Int {
38
+ sumPositive(left) - sumPositive(right)
39
+ }
40
+ ```
41
+
42
+ ## Practices
43
+
44
+ Use `let` by default and `var` for required mutation. Class-constrained protocols use
45
+ `AnyObject`. Prefer shorthand types such as `[Element]`, `[Key: Value]`, or `Wrapped?`, and use `Void` for function
46
+ types. Optionals express valid absence rather than sentinel values, compared to
47
+ `nil` when only presence matters and bound when the code uses the value, chained for one-off access.
48
+
49
+ Typed errors distinguish several meaningful failure states. A force unwrap or cast needs a
50
+ proven invariant. At level `all`, use `// swiftlint:disable:next force_unwrapping` with the
51
+ invariant as the reason for an unavoidable unwrap. Avoid global mutable state, with `static let` or computed `static var` over stored
52
+ mutable statics.
53
+
54
+ `guard` handles early exits, `for ... where` a loop guarded by one condition,
55
+ `for` over `forEach` for control flow or async work, and `map`, `compactMap`, and
56
+ `filter` express side-effect-free transformation. Pattern bindings put `let` on each element
57
+ where that avoids ambiguity. Use weak capture only when a callback must not extend the captured
58
+ object's lifetime. Otherwise, capture the immutable values the callback needs. `#fileID` serves production diagnostics; `#filePath`
59
+ only tests and tooling. Overload operators only with their standard meaning, and a
60
+ custom operator exists only as standard domain notation.
61
+
62
+ ### API and ownership conventions
63
+
64
+ <!-- level: all -->
65
+
66
+ Structs keep synthesized
67
+ memberwise initializers where sufficient, value types hold data without identity, and classes
68
+ serve identity, reference semantics, lifecycle, observable state, or framework requirements.
69
+ An implicitly unwrapped optional appears only for Apple lifecycle cases such as `@IBOutlet`,
70
+ Objective-C nullability gaps, and test data.
71
+
72
+ Declare top-level access to match the public contract. An extension carries no blanket access
73
+ modifier. Types nest when they only make sense in the parent's context, and a caseless enum
74
+ groups truly related statics. Methods and properties beat free functions unless the function
75
+ follows the standard library and stays symmetric.
76
+ Logging goes through the project logging system, and
77
+ images and colors come from named assets or explicit constructors.
78
+
79
+ ## Networking
80
+
81
+ URLs come from `URLComponents` or a typed endpoint value, never concatenated query strings,
82
+ and a production `URL(string:)!` documents its invariant. Inject base URLs and credentials
83
+ at composition. Use `Encodable` types for request bodies with an explicit method and
84
+ content type, never `[String: Any]`. `URLSession` succeeds for non-2xx responses.
85
+ Validate `HTTPURLResponse` status explicitly. Treat a non-HTTP response as a transport
86
+ failure.
87
+
88
+ Responses decode into DTOs mapped into domain values at the boundary. Validate required fields and
89
+ external enum values there. Do not invent a fallback ID, date, or case.
90
+ Clients expose typed errors distinguishing encoding, decoding, transport, invalid response,
91
+ invalid status, and cancellation, which stays distinguishable when navigation supersedes a
92
+ task. When you write tests, inject the transport and cover request construction, status validation,
93
+ decoding failure, cancellation, and mapping without a live service.
94
+
95
+ ### Networking ownership
96
+
97
+ <!-- level: all -->
98
+
99
+ A network client owns base URL, path construction, query items, method, headers, body
100
+ encoding, transport calls, status validation, and decoding. Views and view models never build
101
+ a `URLRequest`, call `URLSession`, decode a DTO, or inspect a status. Prefer Foundation `URLSession`
102
+ with async/await rather than a third-party networking framework.
103
+
104
+ ## Documentation comments
105
+
106
+ `///` documents a declaration before its attributes and modifiers. Swift markup uses
107
+ `- Parameter name:`, `- Parameters:`, `- Returns`, and `- Throws`. Backticks name parameters
108
+ and types. `// MARK:`, implementation notes, and tool directives use ordinary `//` comments.
109
+
110
+ ## Concurrency and errors
111
+
112
+ Structured `async`/`await` with `async throws` APIs replaces callback pyramids and unmanaged
113
+ task trees. UI state mutates on the main actor. When the project uses view models, keep them
114
+ `@MainActor`.
115
+
116
+ Expensive work moves into use cases, repositories, actors, or background tasks. `Task` creation stays
117
+ in the modules that need them: view models, coordinators, or views through `.task`, never in an initializer, always
118
+ with an owner and a cancellation strategy. Store handles when a disappearing view, a
119
+ retry, or a newer request must cancel older work. Check cancellation in long loops and
120
+ before publishing stale results.
121
+
122
+ Shared mutable state sits behind actors, main-actor
123
+ isolation, or explicit synchronization, with actor isolation preferred over
124
+ `DispatchQueue.main.async`. The compiler verifies `Sendable` designs; a module without
125
+ concurrency annotations gets `@preconcurrency import`, and `@unchecked Sendable` or
126
+ `nonisolated(unsafe)` appears only with a documented local invariant and no safer design.
127
+ Inject clocks and scheduling interfaces where time affects logic or tests.
128
+
129
+ Typed errors serve callers with different recovery paths, and untyped `Error` only generic
130
+ boundaries where cases add nothing. Technical errors become user-facing messages at the presentation
131
+ boundary. Failed operations throw, and UI loading and error display use explicit state enums.
132
+ Reserve `fatalError` for an unrecoverable programmer error with a documented invariant,
133
+ `assertionFailure` for an unexpected but recoverable state, and `precondition` for an invariant
134
+ that continuing requires.
@@ -0,0 +1,61 @@
1
+ # SwiftUI
2
+
3
+ ## Architecture
4
+
5
+ <!-- level: all -->
6
+
7
+ This rule picks no presentation pattern, such as Model-View-ViewModel (MVVM) or The Composable Architecture (TCA); a project that wants one writes it
8
+ down.
9
+
10
+ ## SwiftUI views
11
+
12
+ - Keep view-local state in the view when its lifetime matches the view's identity.
13
+ Use `@State`, `@FocusState`, `@GestureState`, and bindings according to their
14
+ ownership and read contracts.
15
+ - Keep view-owned state properties private. Inject values owned by a parent
16
+ through the appropriate input or binding.
17
+ - Preserve read and actor isolation when state changes.
18
+ - Do not store derived state in `@State` when source state provides enough data to compute it.
19
+ - Avoid heavy computation in `body`; SwiftUI can evaluate it repeatedly.
20
+ - Preserve cancellation and stale-result handling for lifecycle work started with
21
+ `.task`, `.onAppear`, or refresh actions.
22
+
23
+ ### View organization
24
+
25
+ <!-- level: all -->
26
+
27
+ - Views render state and forward user intent to the project's operation or state owner.
28
+ - Keep business workflows, network calls, database calls, and concrete infrastructure
29
+ construction in their existing owners.
30
+ - Do not add explicit `@ViewBuilder` to `body`; the compiler provides it.
31
+ - Use `@ViewBuilder` for helper properties or functions that need conditional view branches.
32
+ - Omit `else { EmptyView() }` when the missing branch already produces no content.
33
+ - Extract subviews by visual responsibility, not to reduce line count.
34
+ - Give reusable views explicit inputs instead of hidden dependencies on broad environment objects.
35
+ - Keep short display formatting local. Put reusable or domain-sensitive formatting
36
+ with the behavior that owns it.
37
+
38
+ ## State ownership
39
+
40
+ <!-- level: all -->
41
+
42
+ Keep screen and flow state in the project's selected state owner. Use a shared owner
43
+ when multiple screens need the same state. A store owns cohesive feature or domain
44
+ state; app-wide state belongs in app composition only for global state, such as
45
+ session, theme, or connectivity.
46
+
47
+ Prefer an enum for mutually exclusive loading states instead of parallel booleans.
48
+ Keep transient UI state out of the domain model.
49
+
50
+ ## Shared state correctness
51
+
52
+ Use a single source of truth or an explicit refresh strategy when multiple views
53
+ consume the same domain state. Do not assume that creating a second observable
54
+ object keeps it synchronized with the first. Preserve the intended object's lifetime
55
+ across view reconstruction and identity changes.
56
+
57
+ ## Accessibility
58
+
59
+ - Interactive controls get traits, states, and hints when the visible label does not provide enough information.
60
+ - `.accessibilityHidden(true)` hides only decorative or duplicate content.
61
+ - Ask the user to check navigation, modal presentation, focus, and custom controls with VoiceOver.