@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
@@ -0,0 +1,5 @@
1
+ rules:
2
+ unpinned-uses:
3
+ config:
4
+ policies:
5
+ '*': hash-pin
@@ -1,17 +1,18 @@
1
- allowed_words = ["nginx"]
1
+ allowed_words = ["nginx", "NGINX"]
2
+
2
3
  [configuration]
4
+ description = "nginx files: gixy finds security mistakes, and the server parser checks the rest in a container."
3
5
  title = "nginx"
4
- description = "nginx configuration: gixy for the security mistakes, and the server's own parser in a container for the rest."
5
6
 
6
7
  [files]
7
8
  paths = ["**/nginx.conf", "**/nginx/**/*.conf"]
8
9
 
9
10
  [[tool]]
11
+ builds = ["macos", "linux"]
12
+ mise = "pipx:gixy-ng"
10
13
  name = "gixy"
11
- version = "0.2.53"
12
14
  pypi = "gixy-ng"
13
- mise = "pipx:gixy-ng"
14
- builds = ["macos", "linux"]
15
+ version = "0.2.53"
15
16
  version_pattern = "(\\d+\\.\\d+\\.\\d+)"
16
17
 
17
18
  [[tool]]
@@ -24,28 +25,27 @@ system = true
24
25
  [[tool_file]]
25
26
  target = ".gspot/config/gixy.cfg"
26
27
  tool = "gixy"
27
- rule_keys = ["skips"]
28
28
 
29
29
  [[check]]
30
- name = "gixy"
31
- example = "A location matching `/proxy/(.*)` with `proxy_pass http://$1` lets the request choose the destination and reports `ssrf`. Remove the request-controlled proxy destination and use the intended fixed upstream, or remove the proxy operation when the endpoint only needs to return a response."
32
- level = "recommended"
33
- stage = "commit"
34
30
  command = ["gixy", "--config", "{tool_file:gixy}", "--format", "json", "{file}"]
31
+ example = "A location for `/proxy/(.*)` with `proxy_pass http://$1` sends requests to any host and reports `ssrf`. Point `proxy_pass` at a fixed upstream instead."
32
+ help = "Change the block the way the rule page says. Turn one rule off with `gspot ignore nginx/gixy --rule <name> --reason \"<why>\"`."
33
+ level = "recommended"
34
+ name = "gixy"
35
35
  output = { format = "json", fields = { file = "path", line = "line", rule = "plugin", message = "summary" } }
36
- summary = "Reads every nginx file for the mistakes that open a server: request forgery, path traversal through alias, header injection, a disclosed version."
36
+ stage = "commit"
37
+ summary = "Checks every nginx file for mistakes that expose a server: request forgery, path traversal through alias, header injection, and a disclosed version."
37
38
  why = "These mistakes parse, serve traffic, and look like any other location block until somebody uses them."
38
- help = "Change the block the way the rule's page says. Turn one rule off with gspot ignore nginx/gixy --rule `<name>` --reason \"`<why>`\"."
39
39
 
40
40
  [[check]]
41
- name = "config-test"
42
- example = "The line `invalid_directive on;` fails the native configuration test with `nginx -t`. Remove the unknown directive or replace it with the intended supported directive, such as `listen 443 ssl;` in the configured TLS server. Rerun with the configured deployment image available."
41
+ example = "The line `invalid_directive on;` fails `nginx -t`. Remove it, or replace it with a known directive such as `listen 443 ssl;`."
42
+ files = { filenames = ["nginx.conf"] }
43
+ help = "Fix the line nginx names. Set `tools.nginx.image` to the one your deployment runs."
43
44
  level = "recommended"
44
- stage = "push"
45
- runs = "scope"
45
+ name = "config-test"
46
46
  needs = ["docker"]
47
+ runs = "scope"
48
+ stage = "push"
49
+ summary = "Runs `nginx -t` on each main file inside the image, with a throwaway certificate and resolved upstream names. Records every file that nginx parsed."
47
50
  tool = "docker"
48
- files = { filenames = ["nginx.conf"] }
49
- summary = "Validates each main configuration inside the nginx image and records the files nginx parsed. It mounts a throwaway certificate and resolves upstream names."
50
- why = "Only nginx knows whether nginx accepts the file, and the other place to learn it is the restart in production."
51
- help = "Read the line nginx names. Set tools.nginx.image to the image the deployment runs."
51
+ why = "Only nginx itself can confirm that a file parses; otherwise the first test comes at the restart in production."
@@ -1,4 +1,6 @@
1
- # `nginx`
1
+ # NGINX
2
+
3
+ Read this rule when you change NGINX configuration.
2
4
 
3
5
  ## Edge responsibilities
4
6
 
@@ -24,7 +26,7 @@
24
26
  - Use immutable caching only for content-addressed assets. Give mutable resources a cache
25
27
  lifetime and revalidation policy consistent with their update process.
26
28
  - Keep configuration in the repository, lint it before commit, and reload it through the
27
- deployment flow, never edited on the host.
29
+ deployment flow; never edit it on the host.
28
30
 
29
31
  ## Images
30
32
 
@@ -34,5 +36,4 @@
34
36
 
35
37
  See [nginx TLS configuration](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_stapling)
36
38
  for stapling requirements. Certificate authorities can
37
- [retire OCSP](https://letsencrypt.org/2024/12/05/ending-ocsp); verify issuer support
38
- before enabling stapling.
39
+ [retire OCSP](https://letsencrypt.org/2024/12/05/ending-ocsp).
@@ -1,15 +1,15 @@
1
1
  [configuration]
2
+ description = "A committed OpenAPI document: Spectral lints it, and its generator command leaves it unchanged."
2
3
  title = "OpenAPI"
3
- description = "A committed OpenAPI document: Spectral lints it, and the command that writes it must not change it."
4
4
 
5
5
  [detect]
6
6
  filenames = ["openapi.yaml", "openapi.yml", "openapi.json", "swagger.json", "swagger.yaml"]
7
7
 
8
8
  [[tool]]
9
+ mise = "npm:@stoplight/spectral-cli"
9
10
  name = "spectral"
10
- version = "6.15.0"
11
11
  npm = "@stoplight/spectral-cli"
12
- mise = "npm:@stoplight/spectral-cli"
12
+ version = "6.15.0"
13
13
 
14
14
  # Spectral's Ajv plugins must use the same ajv package as Spectral, so the tool project installs one shared ajv.
15
15
 
@@ -21,30 +21,30 @@ target = ".gspot/config/spectral.yaml"
21
21
  tool = "spectral"
22
22
 
23
23
  [[check]]
24
- name = "spectral"
25
- example = "An OpenAPI document whose operation references an undefined schema reports a validation finding. Define the schema or correct the reference in the source that produces the document, then regenerate it."
24
+ command = ["spectral", "lint", "--ruleset", "{tool_file:spectral}", "--format", "text", "{setting:openapi.document}"]
25
+ cwd = "root"
26
+ example = "An operation that references an undefined schema reports a finding. Define the schema or fix the reference in the source, then generate the document again."
27
+ files = { extensions = [".yaml", ".yml", ".json"] }
28
+ help = "Change the document the way the rule says, or the code that writes it."
26
29
  level = "recommended"
27
- stage = "commit"
30
+ name = "spectral"
31
+ output = { format = "regex", pattern = '^(?<file>.+):(?<line>\d+):(?<column>\d+) (?:error|warning) (?<rule>\S+) "(?<message>.*)"$' }
28
32
  runs = "scope"
33
+ stage = "commit"
34
+ summary = "Lints the file in `openapi.document` with the Spectral OpenAPI rules."
29
35
  tool = "spectral"
30
- cwd = "root"
31
- command = ["spectral", "lint", "--ruleset", "{tool_file:spectral}", "--format", "text", "{setting:openapi.document}"]
32
36
  when = { setting = "openapi.document" }
33
- output = { format = "regex", pattern = '^(?<file>.+):(?<line>\d+):(?<column>\d+) (?:error|warning) (?<rule>\S+) "(?<message>.*)"$' }
34
- files = { extensions = [".yaml", ".yml", ".json"] }
35
- summary = "Lints the OpenAPI document named in openapi.document with the Spectral OpenAPI rules."
36
- why = "Clients are written from this document, so an operation with no id or an undefined response becomes somebody's broken client."
37
- help = "Change the document the way the rule says, or the code that writes it."
37
+ why = "Teams generate clients from this document, so an operation with no ID or an undefined response breaks them."
38
38
 
39
39
  [[check]]
40
- name = "stale-document"
41
40
  command = ["{setting:openapi.generate_command}"]
42
- when = { setting = "openapi.generate_command" }
43
- generated_paths = [{ path = "{setting:openapi.document}" }]
44
- example = "A committed OpenAPI document that differs from the configured generator output reports drift. Run the declared generator, inspect the changed document, and retain the corrected output before rerunning."
41
+ example = "A committed document that differs from the generator output reports drift. Run the generator, review the change, and commit it."
42
+ generator_outputs = [{ path = "{setting:openapi.document}" }]
43
+ help = "Run the command and commit the document it writes."
45
44
  level = "recommended"
46
- stage = "push"
45
+ name = "stale-document"
47
46
  runs = "scope"
48
- summary = "Runs the command in openapi.generate_command and fails when it changes the document."
47
+ stage = "push"
48
+ summary = "Runs `openapi.generate_command` and fails when the document changes."
49
+ when = { setting = "openapi.generate_command" }
49
50
  why = "A committed document that lags the routes describes a service that does not exist."
50
- help = "Run the command and commit the document it writes."
@@ -1,5 +1,7 @@
1
1
  # OpenAPI
2
2
 
3
+ Read this rule when you change an OpenAPI document or its contract tests.
4
+
3
5
  ## Public contracts
4
6
 
5
7
  When the project publishes OpenAPI, its document describes the runtime API.
@@ -35,5 +37,5 @@ When you write contract tests:
35
37
  - Test the public response. Assert its status and content type.
36
38
  - Keep generated schemas and their inputs synchronized through the existing generator.
37
39
 
38
- An assertion that checks only selected response fields does not prove that the whole response
40
+ An assertion that checks only some fields does not prove that the whole response
39
41
  satisfies its schema. Use the project's schema validator for that claim.
@@ -1,8 +1,9 @@
1
1
  allowed_words = ["Xcode"]
2
+
2
3
  [configuration]
3
- title = "Xcode"
4
+ description = "An Xcode project: property lists that parse, build settings files, and complete string catalogs. Asset catalogs hold their images, sources belong to a target, and entitlements stay on a list."
4
5
  suggests = ["swift"]
5
- description = "An Xcode project: property lists that parse, build settings files, and complete string catalogs. Asset catalogs hold their images, test targets sit in a plan, sources belong to a target, and entitlements stay on a list."
6
+ title = "Xcode"
6
7
 
7
8
  [detect]
8
9
  paths = ["**/*.xcodeproj/project.pbxproj"]
@@ -13,119 +14,98 @@ extensions = [".plist", ".entitlements", ".xcconfig", ".xcstrings", ".storyboard
13
14
  paths = ["**/project.pbxproj", "**/*.xcscheme", "**/*.xctestplan", "**/*.xcassets/**/Contents.json"]
14
15
 
15
16
  [[tool]]
16
- name = "plutil"
17
- install_hint = "install Xcode from the App Store"
18
- system = true
19
17
  builds = ["macos"]
20
18
  crash_pattern = "couldn['’]t be opened"
19
+ install_hint = "install Xcode from the App Store"
20
+ name = "plutil"
21
+ system = true
21
22
 
22
23
  [[check]]
23
- name = "plutil"
24
- example = "A plist containing an unclosed dictionary fails native validation. Close the dictionary and plist elements, then rerun with plutil available on a declared platform."
25
- level = "recommended"
26
- stage = "commit"
27
24
  command = ["plutil", "-lint", "{files}"]
25
+ example = "A plist with an unclosed dictionary fails plutil. Close the dictionary element."
28
26
  files = { extensions = [".plist", ".entitlements"] }
27
+ help = "Fix the element plutil names."
28
+ level = "recommended"
29
+ name = "plutil"
29
30
  output = { format = "regex", pattern = "^(?<file>[^:]+): (?<message>(?!OK$).+)$" }
31
+ stage = "commit"
30
32
  summary = "Parses every property list and entitlements file with plutil."
31
33
  why = "A broken plist fails the build or, worse, ships an app whose settings silently fell back to defaults."
32
- help = "Fix the element plutil names."
33
34
 
34
35
  [[check]]
35
- name = "xcconfig"
36
36
  example = "A non-comment line `PRODUCT_NAME App` in an `.xcconfig` file lacks an assignment operator. Change it to `PRODUCT_NAME = App`."
37
- level = "recommended"
38
- stage = "commit"
39
- runs = "scope"
40
37
  files = { extensions = [".xcconfig"] }
41
- summary = "Checks that every line of a build settings file is a setting, an include, or a comment."
42
- why = "Xcode ignores a line it cannot read, so a typo turns a setting off without a word."
43
38
  help = "Write the line as a name, an equals sign, and a value."
39
+ level = "recommended"
40
+ name = "xcconfig"
41
+ runs = "scope"
42
+ stage = "commit"
43
+ summary = "Checks that each line of an `.xcconfig` file holds a setting, an include, or a comment."
44
+ why = "Xcode silently skips a line it cannot parse, so a typo turns a setting off."
44
45
 
45
46
  [[check]]
46
- name = "xcstrings"
47
- example = "A string catalog entry with one translated locale and an absent required locale reports the missing translation. Add that locale and its translation, or explicitly mark the string as not translated when that is the intended catalog state."
47
+ example = "A catalog string that lacks a required locale reports a finding. Add the translation, or mark the string as not translated."
48
+ files = { extensions = [".xcstrings"] }
49
+ help = "Add the translation, or mark the string as not translated in the catalog."
48
50
  level = "recommended"
49
- stage = "commit"
51
+ name = "xcstrings"
50
52
  runs = "scope"
51
- files = { extensions = [".xcstrings"] }
52
- summary = "Checks that every string catalog parses, and that every string has a translation for every locale the catalog uses."
53
+ stage = "commit"
54
+ summary = "Checks that each string catalog parses and translates every string into all its locales."
53
55
  why = "A string with no translation shows its source language in the middle of a translated screen."
54
- help = "Add the translation, or mark the string as not translated in the catalog."
55
56
 
56
57
  [[check]]
57
- name = "assets"
58
- example = "A `Contents.json` image entry naming `icon.png` reports a missing asset when that file does not exist. Add the intended image beside the manifest or remove the obsolete entry."
58
+ example = "A `Contents.json` that names a missing `icon.png` reports a finding. Add the image beside it, or remove the reference."
59
+ files = { paths = ["**/*.xcassets/**"], extensions = [".swift"] }
60
+ help = "Add the image or delete the asset."
59
61
  level = "recommended"
60
- stage = "commit"
62
+ name = "assets"
61
63
  runs = "scope"
62
- files = { paths = ["**/*.xcassets/**"], extensions = [".swift"] }
63
- summary = "Checks that every asset Contents.json parses and that every image set holds the images it names."
64
+ stage = "commit"
65
+ summary = "Checks that each asset `Contents.json` parses, and that its image set holds each file it names."
64
66
  why = "An image set with no image draws nothing at run time."
65
- help = "Add the image or delete the asset."
66
67
 
67
68
  [[check]]
68
- name = "unused-assets"
69
- example = "An asset set named only in an Xcode build setting counts as used. An asset that no source or build setting names reports an unused-asset finding."
70
- level = "all"
71
- stage = "commit"
72
- runs = "scope"
69
+ example = "An asset set that no source file or build setting names reports `unused-asset`. Delete it, or reference it where the app loads it."
73
70
  files = { paths = ["**/*.xcassets/**"], extensions = [".swift", ".storyboard", ".xib", ".plist", ".pbxproj", ".xcconfig"] }
74
- summary = "At level all, finds asset sets that no source or Xcode build setting names."
75
- why = "An asset nobody names ships in the app for nothing."
76
- help = "Delete the asset or name it where it is used. For an accepted asset selected at runtime, run gspot ignore xcode/unused-assets --rule unused-asset --paths `<glob>` --reason \"`<why>`\"."
77
-
78
- [[check]]
79
- name = "test-plans"
80
- example = "A test target absent from the test plan used by its scheme reports missing coverage by the plan. Add that target to the plan and point the scheme at the plan."
71
+ help = "Delete the asset, or name it in the code that loads it. For an asset that the app picks at run time, run `gspot ignore xcode/unused-assets --rule unused-asset --paths <glob> --reason \"<why>\"`."
81
72
  level = "all"
82
- stage = "commit"
73
+ name = "unused-assets"
83
74
  runs = "scope"
84
- summary = "Checks that every shared scheme that runs tests names a test plan, and that every test target is in a plan."
85
- why = "A test target outside every plan never runs in CI, and its tests rot while they look present."
86
- help = "Add the target to a test plan, and point the scheme at the plan."
75
+ stage = "commit"
76
+ summary = "Finds asset sets that no source or Xcode build setting names, at level all."
77
+ why = "An asset nobody names ships in the app for nothing."
87
78
 
88
79
  [[check]]
89
- name = "files-without-target"
90
- example = "A Swift source file under the project that belongs to no target reports an orphan source. Add the file to its intended target or delete the unused source. Remove project references to files that no longer exist."
80
+ example = "A Swift file in no target reports a finding. Add the file to a target, or delete it."
81
+ files = { extensions = [".swift"], paths = ["**/project.pbxproj"] }
82
+ help = "Add the file to a target, or delete it."
91
83
  level = "recommended"
92
- stage = "commit"
84
+ name = "files-without-target"
93
85
  runs = "scope"
94
- files = { extensions = [".swift"], paths = ["**/project.pbxproj"] }
95
- summary = "Compares the Swift files in the tree with the files the project names: a file in no target, and a target file that is gone."
96
- why = "A Swift file in no target is never compiled, so it breaks without anyone seeing it."
97
- help = "Add the file to a target or delete it, and remove the reference to a file that is gone."
98
-
99
- [[check]]
100
- name = "symlinks"
101
- when = { git = true }
102
- example = "A source directory represented by a symlink reports a project symlink finding. Replace the link with the intended repository-owned directory and update project references."
103
- level = "all"
104
86
  stage = "commit"
105
- runs = "scope"
106
- summary = "Reports every tracked symlink beside or under an Xcode project, with where it points."
107
- why = "Xcode, git, and each lint tool follow a symlink their own way, so one file is checked twice or never."
108
- help = "Replace the symlink with the folder it points at, or ignore the path with a reason."
87
+ summary = "Finds the Swift files in the tree that no target of the project names."
88
+ why = "Xcode never compiles a Swift file that belongs to no target, so it breaks unnoticed."
109
89
 
110
90
  [[check]]
111
- name = "entitlements"
112
- example = "An entitlement enabled in an `.entitlements` file but absent from `xcode.allowed_entitlements` reports a settings finding. Remove an unnecessary entitlement, or explicitly allow the required entitlement in settings."
113
- level = "recommended"
114
- when = { setting = "xcode.allowed_entitlements" }
115
- stage = "commit"
116
- runs = "scope"
91
+ example = "An `.entitlements` key missing from `xcode.allowed_entitlements` reports a finding. Remove it, or add it to that list."
117
92
  files = { extensions = [".entitlements"] }
118
- summary = "Checks that every entitlement is on xcode.allowed_entitlements, when the settings hold that list."
119
- why = "An entitlement is a capability the system grants the app, and a new one deserves a review of its own."
120
93
  help = "Remove the entitlement, or add it to xcode.allowed_entitlements."
94
+ level = "recommended"
95
+ name = "entitlements"
96
+ runs = "scope"
97
+ stage = "commit"
98
+ summary = "Checks each entitlement against `xcode.allowed_entitlements`, when the settings hold that list."
99
+ when = { setting = "xcode.allowed_entitlements" }
100
+ why = "Each entitlement grants the app a system capability, so a new one needs its own review."
121
101
 
122
102
  [[check]]
123
- name = "app-transport-security"
124
- example = "An Info.plist enabling `NSAllowsArbitraryLoads` disables transport protection broadly and reports a finding. Remove that key. If one host requires an exception, declare only the host-specific exception."
103
+ example = "An Info.plist with `NSAllowsArbitraryLoads` reports a finding. Remove the key, and add an exception only for a host that needs one."
104
+ files = { extensions = [".plist"] }
105
+ help = "Remove the key, and add an exception for the one host that needs it."
125
106
  level = "recommended"
126
- stage = "commit"
107
+ name = "app-transport-security"
127
108
  runs = "scope"
128
- files = { extensions = [".plist"] }
109
+ stage = "commit"
129
110
  summary = "Refuses a property list that allows arbitrary loads, which turns transport security off for every host."
130
- why = "With arbitrary loads the app speaks plain HTTP to anyone, and one forgotten debug setting ships it."
131
- help = "Remove the key, and add an exception for the one host that needs it."
111
+ why = "Arbitrary loads let the app send plain HTTP to any host, and one forgotten debug setting ships that."
@@ -1,8 +1,10 @@
1
1
  # Xcode
2
2
 
3
+ Read this rule when you change Xcode project settings, schemes, or build phases.
4
+
3
5
  ## Project settings
4
6
 
5
- - `SWIFT_STRICT_CONCURRENCY = complete`. Set the upcoming-feature flags the project adopts in
7
+ - `SWIFT_STRICT_CONCURRENCY = complete`. Set adopted upcoming-feature flags in
6
8
  the project, not per file.
7
9
  - Share schemes needed by collaborators and CI. Keep personal scheme state out of the repository.
8
10
  - Set deployment targets deliberately for each supported product. Verify compatibility
@@ -22,7 +24,7 @@
22
24
  - Run-script phases declare their interpreter and pass the checks for that language.
23
25
  - Every run-script phase declares its input and output files so the build system can skip it.
24
26
  - No network access or code generation without declared outputs.
25
- - The linter and the formatter run before commit, not as build phases that fail the build twice.
27
+ - The linter and the formatter run before commit, not as phases that fail the build twice.
26
28
 
27
29
  ## Project organization
28
30
 
@@ -30,5 +32,5 @@
30
32
 
31
33
  Keep shared build settings in the project or `.xcconfig` file. A target overrides only
32
34
  what differs. Preserve the project's chosen modules and packages; do not introduce
33
- a package only to enforce a directory layout. Keep substantial build-script logic in a
35
+ one only to enforce a folder layout. Keep substantial build-script logic in a
34
36
  repository file its language tools can check.