@opensip-cli/checks-universal 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +31 -0
- package/dist/__tests__/all-checks-execute.test.d.ts +17 -0
- package/dist/__tests__/all-checks-execute.test.d.ts.map +1 -0
- package/dist/__tests__/all-checks-execute.test.js +452 -0
- package/dist/__tests__/all-checks-execute.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-10.test.d.ts +8 -0
- package/dist/__tests__/behavior-fixtures-10.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-10.test.js +200 -0
- package/dist/__tests__/behavior-fixtures-10.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-11.test.d.ts +8 -0
- package/dist/__tests__/behavior-fixtures-11.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-11.test.js +120 -0
- package/dist/__tests__/behavior-fixtures-11.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-12.test.d.ts +8 -0
- package/dist/__tests__/behavior-fixtures-12.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-12.test.js +157 -0
- package/dist/__tests__/behavior-fixtures-12.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-2.test.d.ts +8 -0
- package/dist/__tests__/behavior-fixtures-2.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-2.test.js +785 -0
- package/dist/__tests__/behavior-fixtures-2.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-3.test.d.ts +6 -0
- package/dist/__tests__/behavior-fixtures-3.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-3.test.js +663 -0
- package/dist/__tests__/behavior-fixtures-3.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-4.test.d.ts +5 -0
- package/dist/__tests__/behavior-fixtures-4.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-4.test.js +612 -0
- package/dist/__tests__/behavior-fixtures-4.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-5.test.d.ts +5 -0
- package/dist/__tests__/behavior-fixtures-5.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-5.test.js +469 -0
- package/dist/__tests__/behavior-fixtures-5.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-6.test.d.ts +8 -0
- package/dist/__tests__/behavior-fixtures-6.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-6.test.js +591 -0
- package/dist/__tests__/behavior-fixtures-6.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-7.test.d.ts +5 -0
- package/dist/__tests__/behavior-fixtures-7.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-7.test.js +662 -0
- package/dist/__tests__/behavior-fixtures-7.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-8.test.d.ts +11 -0
- package/dist/__tests__/behavior-fixtures-8.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-8.test.js +634 -0
- package/dist/__tests__/behavior-fixtures-8.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-9.test.d.ts +11 -0
- package/dist/__tests__/behavior-fixtures-9.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-9.test.js +271 -0
- package/dist/__tests__/behavior-fixtures-9.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures.test.d.ts +14 -0
- package/dist/__tests__/behavior-fixtures.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures.test.js +1423 -0
- package/dist/__tests__/behavior-fixtures.test.js.map +1 -0
- package/dist/__tests__/checks.test.d.ts +2 -0
- package/dist/__tests__/checks.test.d.ts.map +1 -0
- package/dist/__tests__/checks.test.js +61 -0
- package/dist/__tests__/checks.test.js.map +1 -0
- package/dist/__tests__/env-var-validation.test.d.ts +14 -0
- package/dist/__tests__/env-var-validation.test.d.ts.map +1 -0
- package/dist/__tests__/env-var-validation.test.js +53 -0
- package/dist/__tests__/env-var-validation.test.js.map +1 -0
- package/dist/__tests__/file-length-limit.test.d.ts +2 -0
- package/dist/__tests__/file-length-limit.test.d.ts.map +1 -0
- package/dist/__tests__/file-length-limit.test.js +29 -0
- package/dist/__tests__/file-length-limit.test.js.map +1 -0
- package/dist/__tests__/fixture-coverage.allowlist.d.ts +18 -0
- package/dist/__tests__/fixture-coverage.allowlist.d.ts.map +1 -0
- package/dist/__tests__/fixture-coverage.allowlist.js +35 -0
- package/dist/__tests__/fixture-coverage.allowlist.js.map +1 -0
- package/dist/__tests__/fixture-coverage.test.d.ts +13 -0
- package/dist/__tests__/fixture-coverage.test.d.ts.map +1 -0
- package/dist/__tests__/fixture-coverage.test.js +57 -0
- package/dist/__tests__/fixture-coverage.test.js.map +1 -0
- package/dist/__tests__/iic.test.d.ts +15 -0
- package/dist/__tests__/iic.test.d.ts.map +1 -0
- package/dist/__tests__/iic.test.js +316 -0
- package/dist/__tests__/iic.test.js.map +1 -0
- package/dist/__tests__/no-skipped-tests.test.d.ts +14 -0
- package/dist/__tests__/no-skipped-tests.test.d.ts.map +1 -0
- package/dist/__tests__/no-skipped-tests.test.js +144 -0
- package/dist/__tests__/no-skipped-tests.test.js.map +1 -0
- package/dist/__tests__/no-todo-comments.test.d.ts +2 -0
- package/dist/__tests__/no-todo-comments.test.d.ts.map +1 -0
- package/dist/__tests__/no-todo-comments.test.js +31 -0
- package/dist/__tests__/no-todo-comments.test.js.map +1 -0
- package/dist/__tests__/no-unimplemented-markers.test.d.ts +2 -0
- package/dist/__tests__/no-unimplemented-markers.test.d.ts.map +1 -0
- package/dist/__tests__/no-unimplemented-markers.test.js +140 -0
- package/dist/__tests__/no-unimplemented-markers.test.js.map +1 -0
- package/dist/__tests__/public-api-jsdoc-scope.test.d.ts +10 -0
- package/dist/__tests__/public-api-jsdoc-scope.test.d.ts.map +1 -0
- package/dist/__tests__/public-api-jsdoc-scope.test.js +176 -0
- package/dist/__tests__/public-api-jsdoc-scope.test.js.map +1 -0
- package/dist/__tests__/resilience-fp.test.d.ts +14 -0
- package/dist/__tests__/resilience-fp.test.d.ts.map +1 -0
- package/dist/__tests__/resilience-fp.test.js +110 -0
- package/dist/__tests__/resilience-fp.test.js.map +1 -0
- package/dist/checks/architecture/__tests__/no-kebab-option-indexing.test.d.ts +2 -0
- package/dist/checks/architecture/__tests__/no-kebab-option-indexing.test.d.ts.map +1 -0
- package/dist/checks/architecture/__tests__/no-kebab-option-indexing.test.js +32 -0
- package/dist/checks/architecture/__tests__/no-kebab-option-indexing.test.js.map +1 -0
- package/dist/checks/architecture/__tests__/tool-has-manifest.test.d.ts +2 -0
- package/dist/checks/architecture/__tests__/tool-has-manifest.test.d.ts.map +1 -0
- package/dist/checks/architecture/__tests__/tool-has-manifest.test.js +152 -0
- package/dist/checks/architecture/__tests__/tool-has-manifest.test.js.map +1 -0
- package/dist/checks/architecture/__tests__/vitest-config-required-with-tests.test.d.ts +2 -0
- package/dist/checks/architecture/__tests__/vitest-config-required-with-tests.test.d.ts.map +1 -0
- package/dist/checks/architecture/__tests__/vitest-config-required-with-tests.test.js +129 -0
- package/dist/checks/architecture/__tests__/vitest-config-required-with-tests.test.js.map +1 -0
- package/dist/checks/architecture/_yaml-doc-bindings.d.ts +23 -0
- package/dist/checks/architecture/_yaml-doc-bindings.d.ts.map +1 -0
- package/dist/checks/architecture/_yaml-doc-bindings.js +29 -0
- package/dist/checks/architecture/_yaml-doc-bindings.js.map +1 -0
- package/dist/checks/architecture/dependencies/index.d.ts +2 -0
- package/dist/checks/architecture/dependencies/index.d.ts.map +1 -0
- package/dist/checks/architecture/dependencies/index.js +2 -0
- package/dist/checks/architecture/dependencies/index.js.map +1 -0
- package/dist/checks/architecture/dependencies/no-duplicate-packages.d.ts +11 -0
- package/dist/checks/architecture/dependencies/no-duplicate-packages.d.ts.map +1 -0
- package/dist/checks/architecture/dependencies/no-duplicate-packages.js +171 -0
- package/dist/checks/architecture/dependencies/no-duplicate-packages.js.map +1 -0
- package/dist/checks/architecture/docker-best-practices.d.ts +23 -0
- package/dist/checks/architecture/docker-best-practices.d.ts.map +1 -0
- package/dist/checks/architecture/docker-best-practices.js +427 -0
- package/dist/checks/architecture/docker-best-practices.js.map +1 -0
- package/dist/checks/architecture/docker-ignore-validation.d.ts +18 -0
- package/dist/checks/architecture/docker-ignore-validation.d.ts.map +1 -0
- package/dist/checks/architecture/docker-ignore-validation.js +117 -0
- package/dist/checks/architecture/docker-ignore-validation.js.map +1 -0
- package/dist/checks/architecture/docker-version-sync.d.ts +16 -0
- package/dist/checks/architecture/docker-version-sync.d.ts.map +1 -0
- package/dist/checks/architecture/docker-version-sync.js +193 -0
- package/dist/checks/architecture/docker-version-sync.js.map +1 -0
- package/dist/checks/architecture/env-var-validation.d.ts +14 -0
- package/dist/checks/architecture/env-var-validation.d.ts.map +1 -0
- package/dist/checks/architecture/env-var-validation.js +289 -0
- package/dist/checks/architecture/env-var-validation.js.map +1 -0
- package/dist/checks/architecture/heavy-import-detection.d.ts +11 -0
- package/dist/checks/architecture/heavy-import-detection.d.ts.map +1 -0
- package/dist/checks/architecture/heavy-import-detection.js +91 -0
- package/dist/checks/architecture/heavy-import-detection.js.map +1 -0
- package/dist/checks/architecture/index.d.ts +16 -0
- package/dist/checks/architecture/index.d.ts.map +1 -0
- package/dist/checks/architecture/index.js +16 -0
- package/dist/checks/architecture/index.js.map +1 -0
- package/dist/checks/architecture/modules/empty-package-detection.d.ts +11 -0
- package/dist/checks/architecture/modules/empty-package-detection.d.ts.map +1 -0
- package/dist/checks/architecture/modules/empty-package-detection.js +277 -0
- package/dist/checks/architecture/modules/empty-package-detection.js.map +1 -0
- package/dist/checks/architecture/modules/index.d.ts +3 -0
- package/dist/checks/architecture/modules/index.d.ts.map +1 -0
- package/dist/checks/architecture/modules/index.js +3 -0
- package/dist/checks/architecture/modules/index.js.map +1 -0
- package/dist/checks/architecture/modules/interface-implementation-consistency.d.ts +12 -0
- package/dist/checks/architecture/modules/interface-implementation-consistency.d.ts.map +1 -0
- package/dist/checks/architecture/modules/interface-implementation-consistency.js +555 -0
- package/dist/checks/architecture/modules/interface-implementation-consistency.js.map +1 -0
- package/dist/checks/architecture/no-custom-event-emitter.d.ts +11 -0
- package/dist/checks/architecture/no-custom-event-emitter.d.ts.map +1 -0
- package/dist/checks/architecture/no-custom-event-emitter.js +123 -0
- package/dist/checks/architecture/no-custom-event-emitter.js.map +1 -0
- package/dist/checks/architecture/no-kebab-option-indexing.d.ts +33 -0
- package/dist/checks/architecture/no-kebab-option-indexing.d.ts.map +1 -0
- package/dist/checks/architecture/no-kebab-option-indexing.js +81 -0
- package/dist/checks/architecture/no-kebab-option-indexing.js.map +1 -0
- package/dist/checks/architecture/node-version-consistency.d.ts +22 -0
- package/dist/checks/architecture/node-version-consistency.d.ts.map +1 -0
- package/dist/checks/architecture/node-version-consistency.js +225 -0
- package/dist/checks/architecture/node-version-consistency.js.map +1 -0
- package/dist/checks/architecture/project-readme-existence.d.ts +13 -0
- package/dist/checks/architecture/project-readme-existence.d.ts.map +1 -0
- package/dist/checks/architecture/project-readme-existence.js +55 -0
- package/dist/checks/architecture/project-readme-existence.js.map +1 -0
- package/dist/checks/architecture/stale-build-artifacts.d.ts +10 -0
- package/dist/checks/architecture/stale-build-artifacts.d.ts.map +1 -0
- package/dist/checks/architecture/stale-build-artifacts.js +55 -0
- package/dist/checks/architecture/stale-build-artifacts.js.map +1 -0
- package/dist/checks/architecture/tool-has-manifest.d.ts +27 -0
- package/dist/checks/architecture/tool-has-manifest.d.ts.map +1 -0
- package/dist/checks/architecture/tool-has-manifest.js +135 -0
- package/dist/checks/architecture/tool-has-manifest.js.map +1 -0
- package/dist/checks/architecture/vitest-config-extends-base.d.ts +15 -0
- package/dist/checks/architecture/vitest-config-extends-base.d.ts.map +1 -0
- package/dist/checks/architecture/vitest-config-extends-base.js +104 -0
- package/dist/checks/architecture/vitest-config-extends-base.js.map +1 -0
- package/dist/checks/architecture/vitest-config-required-with-tests.d.ts +49 -0
- package/dist/checks/architecture/vitest-config-required-with-tests.d.ts.map +1 -0
- package/dist/checks/architecture/vitest-config-required-with-tests.js +199 -0
- package/dist/checks/architecture/vitest-config-required-with-tests.js.map +1 -0
- package/dist/checks/documentation/_directives/eslint.d.ts +9 -0
- package/dist/checks/documentation/_directives/eslint.d.ts.map +1 -0
- package/dist/checks/documentation/_directives/eslint.js +168 -0
- package/dist/checks/documentation/_directives/eslint.js.map +1 -0
- package/dist/checks/documentation/_directives/fitness.d.ts +9 -0
- package/dist/checks/documentation/_directives/fitness.d.ts.map +1 -0
- package/dist/checks/documentation/_directives/fitness.js +64 -0
- package/dist/checks/documentation/_directives/fitness.js.map +1 -0
- package/dist/checks/documentation/_directives/graph.d.ts +10 -0
- package/dist/checks/documentation/_directives/graph.d.ts.map +1 -0
- package/dist/checks/documentation/_directives/graph.js +65 -0
- package/dist/checks/documentation/_directives/graph.js.map +1 -0
- package/dist/checks/documentation/_directives/graph.test.d.ts +2 -0
- package/dist/checks/documentation/_directives/graph.test.d.ts.map +1 -0
- package/dist/checks/documentation/_directives/graph.test.js +54 -0
- package/dist/checks/documentation/_directives/graph.test.js.map +1 -0
- package/dist/checks/documentation/_directives/semgrep.d.ts +8 -0
- package/dist/checks/documentation/_directives/semgrep.d.ts.map +1 -0
- package/dist/checks/documentation/_directives/semgrep.js +72 -0
- package/dist/checks/documentation/_directives/semgrep.js.map +1 -0
- package/dist/checks/documentation/_directives/types.d.ts +21 -0
- package/dist/checks/documentation/_directives/types.d.ts.map +1 -0
- package/dist/checks/documentation/_directives/types.js +9 -0
- package/dist/checks/documentation/_directives/types.js.map +1 -0
- package/dist/checks/documentation/_directives/typescript.d.ts +10 -0
- package/dist/checks/documentation/_directives/typescript.d.ts.map +1 -0
- package/dist/checks/documentation/_directives/typescript.js +54 -0
- package/dist/checks/documentation/_directives/typescript.js.map +1 -0
- package/dist/checks/documentation/_public-api-graph.d.ts +30 -0
- package/dist/checks/documentation/_public-api-graph.d.ts.map +1 -0
- package/dist/checks/documentation/_public-api-graph.js +304 -0
- package/dist/checks/documentation/_public-api-graph.js.map +1 -0
- package/dist/checks/documentation/directive-audit.d.ts +26 -0
- package/dist/checks/documentation/directive-audit.d.ts.map +1 -0
- package/dist/checks/documentation/directive-audit.js +144 -0
- package/dist/checks/documentation/directive-audit.js.map +1 -0
- package/dist/checks/documentation/index.d.ts +3 -0
- package/dist/checks/documentation/index.d.ts.map +1 -0
- package/dist/checks/documentation/index.js +3 -0
- package/dist/checks/documentation/index.js.map +1 -0
- package/dist/checks/documentation/public-api-jsdoc.d.ts +10 -0
- package/dist/checks/documentation/public-api-jsdoc.d.ts.map +1 -0
- package/dist/checks/documentation/public-api-jsdoc.js +131 -0
- package/dist/checks/documentation/public-api-jsdoc.js.map +1 -0
- package/dist/checks/file-length-limit.d.ts +16 -0
- package/dist/checks/file-length-limit.d.ts.map +1 -0
- package/dist/checks/file-length-limit.js +47 -0
- package/dist/checks/file-length-limit.js.map +1 -0
- package/dist/checks/index.d.ts +16 -0
- package/dist/checks/index.d.ts.map +1 -0
- package/dist/checks/index.js +16 -0
- package/dist/checks/index.js.map +1 -0
- package/dist/checks/no-todo-comments.d.ts +18 -0
- package/dist/checks/no-todo-comments.d.ts.map +1 -0
- package/dist/checks/no-todo-comments.js +79 -0
- package/dist/checks/no-todo-comments.js.map +1 -0
- package/dist/checks/no-unimplemented-markers.d.ts +24 -0
- package/dist/checks/no-unimplemented-markers.d.ts.map +1 -0
- package/dist/checks/no-unimplemented-markers.js +198 -0
- package/dist/checks/no-unimplemented-markers.js.map +1 -0
- package/dist/checks/quality/api/graphql-offset-pagination.d.ts +9 -0
- package/dist/checks/quality/api/graphql-offset-pagination.d.ts.map +1 -0
- package/dist/checks/quality/api/graphql-offset-pagination.js +63 -0
- package/dist/checks/quality/api/graphql-offset-pagination.js.map +1 -0
- package/dist/checks/quality/api/index.d.ts +3 -0
- package/dist/checks/quality/api/index.d.ts.map +1 -0
- package/dist/checks/quality/api/index.js +3 -0
- package/dist/checks/quality/api/index.js.map +1 -0
- package/dist/checks/quality/api/zod-openapi-sync.d.ts +13 -0
- package/dist/checks/quality/api/zod-openapi-sync.d.ts.map +1 -0
- package/dist/checks/quality/api/zod-openapi-sync.js +88 -0
- package/dist/checks/quality/api/zod-openapi-sync.js.map +1 -0
- package/dist/checks/quality/code-structure/dead-code.d.ts +12 -0
- package/dist/checks/quality/code-structure/dead-code.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/dead-code.js +238 -0
- package/dist/checks/quality/code-structure/dead-code.js.map +1 -0
- package/dist/checks/quality/code-structure/index.d.ts +5 -0
- package/dist/checks/quality/code-structure/index.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/index.js +5 -0
- package/dist/checks/quality/code-structure/index.js.map +1 -0
- package/dist/checks/quality/code-structure/no-ai-attribution.d.ts +25 -0
- package/dist/checks/quality/code-structure/no-ai-attribution.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/no-ai-attribution.js +76 -0
- package/dist/checks/quality/code-structure/no-ai-attribution.js.map +1 -0
- package/dist/checks/quality/code-structure/no-console-log.d.ts +17 -0
- package/dist/checks/quality/code-structure/no-console-log.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/no-console-log.js +106 -0
- package/dist/checks/quality/code-structure/no-console-log.js.map +1 -0
- package/dist/checks/quality/code-structure/no-process-artifacts.d.ts +25 -0
- package/dist/checks/quality/code-structure/no-process-artifacts.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/no-process-artifacts.js +104 -0
- package/dist/checks/quality/code-structure/no-process-artifacts.js.map +1 -0
- package/dist/checks/quality/dependency-version-consistency.d.ts +20 -0
- package/dist/checks/quality/dependency-version-consistency.d.ts.map +1 -0
- package/dist/checks/quality/dependency-version-consistency.js +266 -0
- package/dist/checks/quality/dependency-version-consistency.js.map +1 -0
- package/dist/checks/quality/fitness-ignore-hygiene.d.ts +10 -0
- package/dist/checks/quality/fitness-ignore-hygiene.d.ts.map +1 -0
- package/dist/checks/quality/fitness-ignore-hygiene.js +93 -0
- package/dist/checks/quality/fitness-ignore-hygiene.js.map +1 -0
- package/dist/checks/quality/frontend/expo-vector-icons.d.ts +13 -0
- package/dist/checks/quality/frontend/expo-vector-icons.d.ts.map +1 -0
- package/dist/checks/quality/frontend/expo-vector-icons.js +80 -0
- package/dist/checks/quality/frontend/expo-vector-icons.js.map +1 -0
- package/dist/checks/quality/frontend/image-optimization.d.ts +13 -0
- package/dist/checks/quality/frontend/image-optimization.d.ts.map +1 -0
- package/dist/checks/quality/frontend/image-optimization.js +166 -0
- package/dist/checks/quality/frontend/image-optimization.js.map +1 -0
- package/dist/checks/quality/frontend/index.d.ts +4 -0
- package/dist/checks/quality/frontend/index.d.ts.map +1 -0
- package/dist/checks/quality/frontend/index.js +4 -0
- package/dist/checks/quality/frontend/index.js.map +1 -0
- package/dist/checks/quality/frontend/navigation-typing.d.ts +12 -0
- package/dist/checks/quality/frontend/navigation-typing.d.ts.map +1 -0
- package/dist/checks/quality/frontend/navigation-typing.js +77 -0
- package/dist/checks/quality/frontend/navigation-typing.js.map +1 -0
- package/dist/checks/quality/graph-ignore-hygiene.d.ts +10 -0
- package/dist/checks/quality/graph-ignore-hygiene.d.ts.map +1 -0
- package/dist/checks/quality/graph-ignore-hygiene.js +95 -0
- package/dist/checks/quality/graph-ignore-hygiene.js.map +1 -0
- package/dist/checks/quality/graph-ignore-hygiene.test.d.ts +14 -0
- package/dist/checks/quality/graph-ignore-hygiene.test.d.ts.map +1 -0
- package/dist/checks/quality/graph-ignore-hygiene.test.js +58 -0
- package/dist/checks/quality/graph-ignore-hygiene.test.js.map +1 -0
- package/dist/checks/quality/index.d.ts +16 -0
- package/dist/checks/quality/index.d.ts.map +1 -0
- package/dist/checks/quality/index.js +16 -0
- package/dist/checks/quality/index.js.map +1 -0
- package/dist/checks/quality/linting/eslint-justifications.d.ts +12 -0
- package/dist/checks/quality/linting/eslint-justifications.d.ts.map +1 -0
- package/dist/checks/quality/linting/eslint-justifications.js +328 -0
- package/dist/checks/quality/linting/eslint-justifications.js.map +1 -0
- package/dist/checks/quality/linting/index.d.ts +4 -0
- package/dist/checks/quality/linting/index.d.ts.map +1 -0
- package/dist/checks/quality/linting/index.js +4 -0
- package/dist/checks/quality/linting/index.js.map +1 -0
- package/dist/checks/quality/linting/semgrep-justifications.d.ts +16 -0
- package/dist/checks/quality/linting/semgrep-justifications.d.ts.map +1 -0
- package/dist/checks/quality/linting/semgrep-justifications.js +229 -0
- package/dist/checks/quality/linting/semgrep-justifications.js.map +1 -0
- package/dist/checks/quality/linting/typescript-directive-hygiene.d.ts +12 -0
- package/dist/checks/quality/linting/typescript-directive-hygiene.d.ts.map +1 -0
- package/dist/checks/quality/linting/typescript-directive-hygiene.js +142 -0
- package/dist/checks/quality/linting/typescript-directive-hygiene.js.map +1 -0
- package/dist/checks/quality/no-compatibility-layer-names.d.ts +13 -0
- package/dist/checks/quality/no-compatibility-layer-names.d.ts.map +1 -0
- package/dist/checks/quality/no-compatibility-layer-names.js +100 -0
- package/dist/checks/quality/no-compatibility-layer-names.js.map +1 -0
- package/dist/checks/quality/no-deprecated-tags.d.ts +11 -0
- package/dist/checks/quality/no-deprecated-tags.d.ts.map +1 -0
- package/dist/checks/quality/no-deprecated-tags.js +76 -0
- package/dist/checks/quality/no-deprecated-tags.js.map +1 -0
- package/dist/checks/quality/no-markdown-references.d.ts +16 -0
- package/dist/checks/quality/no-markdown-references.d.ts.map +1 -0
- package/dist/checks/quality/no-markdown-references.js +145 -0
- package/dist/checks/quality/no-markdown-references.js.map +1 -0
- package/dist/checks/quality/no-raw-regex-on-code.d.ts +9 -0
- package/dist/checks/quality/no-raw-regex-on-code.d.ts.map +1 -0
- package/dist/checks/quality/no-raw-regex-on-code.js +61 -0
- package/dist/checks/quality/no-raw-regex-on-code.js.map +1 -0
- package/dist/checks/quality/no-temporary-workarounds.d.ts +11 -0
- package/dist/checks/quality/no-temporary-workarounds.d.ts.map +1 -0
- package/dist/checks/quality/no-temporary-workarounds.js +69 -0
- package/dist/checks/quality/no-temporary-workarounds.js.map +1 -0
- package/dist/checks/quality/no-window-alert.d.ts +19 -0
- package/dist/checks/quality/no-window-alert.d.ts.map +1 -0
- package/dist/checks/quality/no-window-alert.js +74 -0
- package/dist/checks/quality/no-window-alert.js.map +1 -0
- package/dist/checks/quality/observability/index.d.ts +2 -0
- package/dist/checks/quality/observability/index.d.ts.map +1 -0
- package/dist/checks/quality/observability/index.js +2 -0
- package/dist/checks/quality/observability/index.js.map +1 -0
- package/dist/checks/quality/observability/pino-serializer-coverage.d.ts +15 -0
- package/dist/checks/quality/observability/pino-serializer-coverage.d.ts.map +1 -0
- package/dist/checks/quality/observability/pino-serializer-coverage.js +209 -0
- package/dist/checks/quality/observability/pino-serializer-coverage.js.map +1 -0
- package/dist/checks/quality/patterns/async-state-pattern.d.ts +14 -0
- package/dist/checks/quality/patterns/async-state-pattern.d.ts.map +1 -0
- package/dist/checks/quality/patterns/async-state-pattern.js +80 -0
- package/dist/checks/quality/patterns/async-state-pattern.js.map +1 -0
- package/dist/checks/quality/patterns/index.d.ts +4 -0
- package/dist/checks/quality/patterns/index.d.ts.map +1 -0
- package/dist/checks/quality/patterns/index.js +4 -0
- package/dist/checks/quality/patterns/index.js.map +1 -0
- package/dist/checks/quality/patterns/no-non-null-assertions.d.ts +10 -0
- package/dist/checks/quality/patterns/no-non-null-assertions.d.ts.map +1 -0
- package/dist/checks/quality/patterns/no-non-null-assertions.js +97 -0
- package/dist/checks/quality/patterns/no-non-null-assertions.js.map +1 -0
- package/dist/checks/quality/patterns/performance-anti-patterns.d.ts +16 -0
- package/dist/checks/quality/patterns/performance-anti-patterns.d.ts.map +1 -0
- package/dist/checks/quality/patterns/performance-anti-patterns.js +239 -0
- package/dist/checks/quality/patterns/performance-anti-patterns.js.map +1 -0
- package/dist/checks/resilience/_helpers/config-validation.d.ts +27 -0
- package/dist/checks/resilience/_helpers/config-validation.d.ts.map +1 -0
- package/dist/checks/resilience/_helpers/config-validation.js +61 -0
- package/dist/checks/resilience/_helpers/config-validation.js.map +1 -0
- package/dist/checks/resilience/batch-operations.d.ts +22 -0
- package/dist/checks/resilience/batch-operations.d.ts.map +1 -0
- package/dist/checks/resilience/batch-operations.js +422 -0
- package/dist/checks/resilience/batch-operations.js.map +1 -0
- package/dist/checks/resilience/cache-ttl-validation.d.ts +13 -0
- package/dist/checks/resilience/cache-ttl-validation.d.ts.map +1 -0
- package/dist/checks/resilience/cache-ttl-validation.js +222 -0
- package/dist/checks/resilience/cache-ttl-validation.js.map +1 -0
- package/dist/checks/resilience/catch-clause-safety.d.ts +12 -0
- package/dist/checks/resilience/catch-clause-safety.d.ts.map +1 -0
- package/dist/checks/resilience/catch-clause-safety.js +110 -0
- package/dist/checks/resilience/catch-clause-safety.js.map +1 -0
- package/dist/checks/resilience/dangerous-config-defaults.d.ts +11 -0
- package/dist/checks/resilience/dangerous-config-defaults.d.ts.map +1 -0
- package/dist/checks/resilience/dangerous-config-defaults.js +304 -0
- package/dist/checks/resilience/dangerous-config-defaults.js.map +1 -0
- package/dist/checks/resilience/error-code-registration.d.ts +11 -0
- package/dist/checks/resilience/error-code-registration.d.ts.map +1 -0
- package/dist/checks/resilience/error-code-registration.js +88 -0
- package/dist/checks/resilience/error-code-registration.js.map +1 -0
- package/dist/checks/resilience/event-patterns.d.ts +21 -0
- package/dist/checks/resilience/event-patterns.d.ts.map +1 -0
- package/dist/checks/resilience/event-patterns.js +232 -0
- package/dist/checks/resilience/event-patterns.js.map +1 -0
- package/dist/checks/resilience/exit-code-correctness.d.ts +12 -0
- package/dist/checks/resilience/exit-code-correctness.d.ts.map +1 -0
- package/dist/checks/resilience/exit-code-correctness.js +107 -0
- package/dist/checks/resilience/exit-code-correctness.js.map +1 -0
- package/dist/checks/resilience/index.d.ts +18 -0
- package/dist/checks/resilience/index.d.ts.map +1 -0
- package/dist/checks/resilience/index.js +18 -0
- package/dist/checks/resilience/index.js.map +1 -0
- package/dist/checks/resilience/no-hardcoded-timeouts.d.ts +10 -0
- package/dist/checks/resilience/no-hardcoded-timeouts.d.ts.map +1 -0
- package/dist/checks/resilience/no-hardcoded-timeouts.js +291 -0
- package/dist/checks/resilience/no-hardcoded-timeouts.js.map +1 -0
- package/dist/checks/resilience/no-process-exit-in-finally.d.ts +11 -0
- package/dist/checks/resilience/no-process-exit-in-finally.d.ts.map +1 -0
- package/dist/checks/resilience/no-process-exit-in-finally.js +89 -0
- package/dist/checks/resilience/no-process-exit-in-finally.js.map +1 -0
- package/dist/checks/resilience/readline-cleanup.d.ts +11 -0
- package/dist/checks/resilience/readline-cleanup.d.ts.map +1 -0
- package/dist/checks/resilience/readline-cleanup.js +107 -0
- package/dist/checks/resilience/readline-cleanup.js.map +1 -0
- package/dist/checks/resilience/recovery-patterns.d.ts +25 -0
- package/dist/checks/resilience/recovery-patterns.d.ts.map +1 -0
- package/dist/checks/resilience/recovery-patterns.js +273 -0
- package/dist/checks/resilience/recovery-patterns.js.map +1 -0
- package/dist/checks/resilience/reentrancy-guard.d.ts +12 -0
- package/dist/checks/resilience/reentrancy-guard.d.ts.map +1 -0
- package/dist/checks/resilience/reentrancy-guard.js +86 -0
- package/dist/checks/resilience/reentrancy-guard.js.map +1 -0
- package/dist/checks/resilience/retry-config-validation.d.ts +13 -0
- package/dist/checks/resilience/retry-config-validation.d.ts.map +1 -0
- package/dist/checks/resilience/retry-config-validation.js +159 -0
- package/dist/checks/resilience/retry-config-validation.js.map +1 -0
- package/dist/checks/resilience/sentry/_helpers/sentry.d.ts +25 -0
- package/dist/checks/resilience/sentry/_helpers/sentry.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/_helpers/sentry.js +68 -0
- package/dist/checks/resilience/sentry/_helpers/sentry.js.map +1 -0
- package/dist/checks/resilience/sentry/index.d.ts +8 -0
- package/dist/checks/resilience/sentry/index.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/index.js +8 -0
- package/dist/checks/resilience/sentry/index.js.map +1 -0
- package/dist/checks/resilience/sentry/sentry-dsn-configured.d.ts +12 -0
- package/dist/checks/resilience/sentry/sentry-dsn-configured.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/sentry-dsn-configured.js +55 -0
- package/dist/checks/resilience/sentry/sentry-dsn-configured.js.map +1 -0
- package/dist/checks/resilience/sentry/sentry-environment-set.d.ts +12 -0
- package/dist/checks/resilience/sentry/sentry-environment-set.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/sentry-environment-set.js +51 -0
- package/dist/checks/resilience/sentry/sentry-environment-set.js.map +1 -0
- package/dist/checks/resilience/sentry/sentry-error-boundary.d.ts +12 -0
- package/dist/checks/resilience/sentry/sentry-error-boundary.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/sentry-error-boundary.js +75 -0
- package/dist/checks/resilience/sentry/sentry-error-boundary.js.map +1 -0
- package/dist/checks/resilience/sentry/sentry-pii-scrubbing.d.ts +13 -0
- package/dist/checks/resilience/sentry/sentry-pii-scrubbing.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/sentry-pii-scrubbing.js +125 -0
- package/dist/checks/resilience/sentry/sentry-pii-scrubbing.js.map +1 -0
- package/dist/checks/resilience/sentry/sentry-release-set.d.ts +12 -0
- package/dist/checks/resilience/sentry/sentry-release-set.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/sentry-release-set.js +51 -0
- package/dist/checks/resilience/sentry/sentry-release-set.js.map +1 -0
- package/dist/checks/resilience/sentry/sentry-sample-rate.d.ts +12 -0
- package/dist/checks/resilience/sentry/sentry-sample-rate.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/sentry-sample-rate.js +78 -0
- package/dist/checks/resilience/sentry/sentry-sample-rate.js.map +1 -0
- package/dist/checks/resilience/sentry/sentry-source-maps.d.ts +12 -0
- package/dist/checks/resilience/sentry/sentry-source-maps.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/sentry-source-maps.js +83 -0
- package/dist/checks/resilience/sentry/sentry-source-maps.js.map +1 -0
- package/dist/checks/resilience/service-patterns.d.ts +18 -0
- package/dist/checks/resilience/service-patterns.d.ts.map +1 -0
- package/dist/checks/resilience/service-patterns.js +230 -0
- package/dist/checks/resilience/service-patterns.js.map +1 -0
- package/dist/checks/resilience/timer-lifecycle.d.ts +10 -0
- package/dist/checks/resilience/timer-lifecycle.d.ts.map +1 -0
- package/dist/checks/resilience/timer-lifecycle.js +78 -0
- package/dist/checks/resilience/timer-lifecycle.js.map +1 -0
- package/dist/checks/resilience/transaction-patterns.d.ts +21 -0
- package/dist/checks/resilience/transaction-patterns.d.ts.map +1 -0
- package/dist/checks/resilience/transaction-patterns.js +258 -0
- package/dist/checks/resilience/transaction-patterns.js.map +1 -0
- package/dist/checks/security/__tests__/no-hardcoded-secrets.test.d.ts +9 -0
- package/dist/checks/security/__tests__/no-hardcoded-secrets.test.d.ts.map +1 -0
- package/dist/checks/security/__tests__/no-hardcoded-secrets.test.js +37 -0
- package/dist/checks/security/__tests__/no-hardcoded-secrets.test.js.map +1 -0
- package/dist/checks/security/__tests__/package-supply-chain-policy.test.d.ts +2 -0
- package/dist/checks/security/__tests__/package-supply-chain-policy.test.d.ts.map +1 -0
- package/dist/checks/security/__tests__/package-supply-chain-policy.test.js +128 -0
- package/dist/checks/security/__tests__/package-supply-chain-policy.test.js.map +1 -0
- package/dist/checks/security/api-key-rotation.d.ts +10 -0
- package/dist/checks/security/api-key-rotation.d.ts.map +1 -0
- package/dist/checks/security/api-key-rotation.js +186 -0
- package/dist/checks/security/api-key-rotation.js.map +1 -0
- package/dist/checks/security/auth-middleware-coverage.d.ts +11 -0
- package/dist/checks/security/auth-middleware-coverage.d.ts.map +1 -0
- package/dist/checks/security/auth-middleware-coverage.js +210 -0
- package/dist/checks/security/auth-middleware-coverage.js.map +1 -0
- package/dist/checks/security/auth-route-guard.d.ts +12 -0
- package/dist/checks/security/auth-route-guard.d.ts.map +1 -0
- package/dist/checks/security/auth-route-guard.js +70 -0
- package/dist/checks/security/auth-route-guard.js.map +1 -0
- package/dist/checks/security/cors-configuration.d.ts +11 -0
- package/dist/checks/security/cors-configuration.d.ts.map +1 -0
- package/dist/checks/security/cors-configuration.js +126 -0
- package/dist/checks/security/cors-configuration.js.map +1 -0
- package/dist/checks/security/csp-headers.d.ts +11 -0
- package/dist/checks/security/csp-headers.d.ts.map +1 -0
- package/dist/checks/security/csp-headers.js +192 -0
- package/dist/checks/security/csp-headers.js.map +1 -0
- package/dist/checks/security/dependency-vulnerability-audit.d.ts +15 -0
- package/dist/checks/security/dependency-vulnerability-audit.d.ts.map +1 -0
- package/dist/checks/security/dependency-vulnerability-audit.js +184 -0
- package/dist/checks/security/dependency-vulnerability-audit.js.map +1 -0
- package/dist/checks/security/env-secret-exposure.d.ts +11 -0
- package/dist/checks/security/env-secret-exposure.d.ts.map +1 -0
- package/dist/checks/security/env-secret-exposure.js +127 -0
- package/dist/checks/security/env-secret-exposure.js.map +1 -0
- package/dist/checks/security/hasura-production-config.d.ts +11 -0
- package/dist/checks/security/hasura-production-config.d.ts.map +1 -0
- package/dist/checks/security/hasura-production-config.js +122 -0
- package/dist/checks/security/hasura-production-config.js.map +1 -0
- package/dist/checks/security/index.d.ts +17 -0
- package/dist/checks/security/index.d.ts.map +1 -0
- package/dist/checks/security/index.js +17 -0
- package/dist/checks/security/index.js.map +1 -0
- package/dist/checks/security/jwt-validation.d.ts +11 -0
- package/dist/checks/security/jwt-validation.d.ts.map +1 -0
- package/dist/checks/security/jwt-validation.js +294 -0
- package/dist/checks/security/jwt-validation.js.map +1 -0
- package/dist/checks/security/no-eval.d.ts +16 -0
- package/dist/checks/security/no-eval.d.ts.map +1 -0
- package/dist/checks/security/no-eval.js +83 -0
- package/dist/checks/security/no-eval.js.map +1 -0
- package/dist/checks/security/no-hardcoded-secrets.d.ts +28 -0
- package/dist/checks/security/no-hardcoded-secrets.d.ts.map +1 -0
- package/dist/checks/security/no-hardcoded-secrets.js +209 -0
- package/dist/checks/security/no-hardcoded-secrets.js.map +1 -0
- package/dist/checks/security/package-supply-chain-policy.d.ts +12 -0
- package/dist/checks/security/package-supply-chain-policy.d.ts.map +1 -0
- package/dist/checks/security/package-supply-chain-policy.js +534 -0
- package/dist/checks/security/package-supply-chain-policy.js.map +1 -0
- package/dist/checks/security/rate-limit-coverage.d.ts +10 -0
- package/dist/checks/security/rate-limit-coverage.d.ts.map +1 -0
- package/dist/checks/security/rate-limit-coverage.js +143 -0
- package/dist/checks/security/rate-limit-coverage.js.map +1 -0
- package/dist/checks/security/semgrep-scan.d.ts +13 -0
- package/dist/checks/security/semgrep-scan.d.ts.map +1 -0
- package/dist/checks/security/semgrep-scan.js +86 -0
- package/dist/checks/security/semgrep-scan.js.map +1 -0
- package/dist/checks/security/use-centralized-crypto.d.ts +11 -0
- package/dist/checks/security/use-centralized-crypto.d.ts.map +1 -0
- package/dist/checks/security/use-centralized-crypto.js +129 -0
- package/dist/checks/security/use-centralized-crypto.js.map +1 -0
- package/dist/checks/security/webhook-signature-verification.d.ts +10 -0
- package/dist/checks/security/webhook-signature-verification.d.ts.map +1 -0
- package/dist/checks/security/webhook-signature-verification.js +183 -0
- package/dist/checks/security/webhook-signature-verification.js.map +1 -0
- package/dist/checks/testing/index.d.ts +6 -0
- package/dist/checks/testing/index.d.ts.map +1 -0
- package/dist/checks/testing/index.js +6 -0
- package/dist/checks/testing/index.js.map +1 -0
- package/dist/checks/testing/no-skipped-tests.d.ts +40 -0
- package/dist/checks/testing/no-skipped-tests.d.ts.map +1 -0
- package/dist/checks/testing/no-skipped-tests.js +174 -0
- package/dist/checks/testing/no-skipped-tests.js.map +1 -0
- package/dist/checks/testing/no-stub-tests.d.ts +11 -0
- package/dist/checks/testing/no-stub-tests.d.ts.map +1 -0
- package/dist/checks/testing/no-stub-tests.js +103 -0
- package/dist/checks/testing/no-stub-tests.js.map +1 -0
- package/dist/checks/testing/test-convention-consistency.d.ts +14 -0
- package/dist/checks/testing/test-convention-consistency.d.ts.map +1 -0
- package/dist/checks/testing/test-convention-consistency.js +93 -0
- package/dist/checks/testing/test-convention-consistency.js.map +1 -0
- package/dist/checks/testing/test-file-naming.d.ts +13 -0
- package/dist/checks/testing/test-file-naming.d.ts.map +1 -0
- package/dist/checks/testing/test-file-naming.js +218 -0
- package/dist/checks/testing/test-file-naming.js.map +1 -0
- package/dist/checks/testing/test-file-pairing.d.ts +13 -0
- package/dist/checks/testing/test-file-pairing.d.ts.map +1 -0
- package/dist/checks/testing/test-file-pairing.js +274 -0
- package/dist/checks/testing/test-file-pairing.js.map +1 -0
- package/dist/display/architecture.d.ts +9 -0
- package/dist/display/architecture.d.ts.map +1 -0
- package/dist/display/architecture.js +29 -0
- package/dist/display/architecture.js.map +1 -0
- package/dist/display/index.d.ts +20 -0
- package/dist/display/index.d.ts.map +1 -0
- package/dist/display/index.js +30 -0
- package/dist/display/index.js.map +1 -0
- package/dist/display/quality.d.ts +7 -0
- package/dist/display/quality.d.ts.map +1 -0
- package/dist/display/quality.js +34 -0
- package/dist/display/quality.js.map +1 -0
- package/dist/display/resilience.d.ts +7 -0
- package/dist/display/resilience.d.ts.map +1 -0
- package/dist/display/resilience.js +36 -0
- package/dist/display/resilience.js.map +1 -0
- package/dist/display/security-testing.d.ts +9 -0
- package/dist/display/security-testing.d.ts.map +1 -0
- package/dist/display/security-testing.js +31 -0
- package/dist/display/security-testing.js.map +1 -0
- package/dist/display/types.d.ts +6 -0
- package/dist/display/types.d.ts.map +1 -0
- package/dist/display/types.js +6 -0
- package/dist/display/types.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
// @fitness-ignore-file semgrep-justifications -- This check's own code references nosemgrep patterns for detection purposes
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Semgrep Justifications check
|
|
4
|
+
*
|
|
5
|
+
* Validates that all nosemgrep directives have proper justifications.
|
|
6
|
+
* Similar to eslint-justifications, this ensures suppression directives
|
|
7
|
+
* are documented with specific reasons.
|
|
8
|
+
*/
|
|
9
|
+
import { defineCheck } from '@opensip-cli/fitness';
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// CONSTANTS
|
|
12
|
+
// =============================================================================
|
|
13
|
+
const CHECK_SLUG = 'semgrep-justifications';
|
|
14
|
+
const CHECK_ID = 'f83332d7-b3f2-463c-be54-8689a0fac5e4';
|
|
15
|
+
const ISSUE_TYPE_MISSING_JUSTIFICATION = 'missing-justification';
|
|
16
|
+
const ISSUE_TYPE_GENERIC_JUSTIFICATION = 'generic-justification';
|
|
17
|
+
const ISSUE_TYPE_MISSING_RULE = 'missing-rule';
|
|
18
|
+
// Generic justification patterns - pre-compiled for safety
|
|
19
|
+
const GENERIC_JUSTIFICATIONS = [
|
|
20
|
+
/^todo$/i,
|
|
21
|
+
/^fix\s?(?:this|later|me)?$/i,
|
|
22
|
+
/^temporary$/i,
|
|
23
|
+
/^temp$/i,
|
|
24
|
+
/^wip$/i,
|
|
25
|
+
/^ignore$/i,
|
|
26
|
+
/^skip$/i,
|
|
27
|
+
/^disabled?$/i,
|
|
28
|
+
/^hack$/i,
|
|
29
|
+
/^workaround$/i,
|
|
30
|
+
/^needed$/i,
|
|
31
|
+
/^required$/i,
|
|
32
|
+
/^necessary$/i,
|
|
33
|
+
/^legacy$/i,
|
|
34
|
+
/^old\s?code$/i,
|
|
35
|
+
/^safe$/i,
|
|
36
|
+
/^ok$/i,
|
|
37
|
+
/^fine$/i,
|
|
38
|
+
/^false\s?positive$/i, // Too generic without explanation
|
|
39
|
+
];
|
|
40
|
+
const MIN_JUSTIFICATION_LENGTH = 10;
|
|
41
|
+
// =============================================================================
|
|
42
|
+
// ANALYSIS FUNCTIONS
|
|
43
|
+
// =============================================================================
|
|
44
|
+
/**
|
|
45
|
+
* Validates generic justification patterns
|
|
46
|
+
*/
|
|
47
|
+
function isGenericJustification(justification) {
|
|
48
|
+
const trimmed = justification.trim();
|
|
49
|
+
if (trimmed.length < MIN_JUSTIFICATION_LENGTH) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
return GENERIC_JUSTIFICATIONS.some((pattern) => pattern.test(trimmed));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Parse a nosemgrep directive line and extract rule ID and reason.
|
|
56
|
+
* Format: // nosemgrep: rule.id -- reason
|
|
57
|
+
* // nosemgrep: rule.id
|
|
58
|
+
* // nosemgrep -- reason (discouraged)
|
|
59
|
+
* // nosemgrep (discouraged)
|
|
60
|
+
*/
|
|
61
|
+
function parseNosemgrepLine(line) {
|
|
62
|
+
const commentIdx = line.indexOf('//');
|
|
63
|
+
if (commentIdx === -1) {
|
|
64
|
+
return { isDirective: false, ruleId: null, reason: null };
|
|
65
|
+
}
|
|
66
|
+
const afterComment = line.slice(commentIdx + 2).trim();
|
|
67
|
+
if (!afterComment.startsWith('nosemgrep')) {
|
|
68
|
+
return { isDirective: false, ruleId: null, reason: null };
|
|
69
|
+
}
|
|
70
|
+
const afterMarker = afterComment.slice('nosemgrep'.length);
|
|
71
|
+
// No rule ID and no reason: // nosemgrep
|
|
72
|
+
if (afterMarker.trim() === '') {
|
|
73
|
+
return { isDirective: true, ruleId: null, reason: null };
|
|
74
|
+
}
|
|
75
|
+
let ruleId = null;
|
|
76
|
+
let reason = null;
|
|
77
|
+
// Check for : separator (rule ID follows)
|
|
78
|
+
if (afterMarker.startsWith(':')) {
|
|
79
|
+
const afterColon = afterMarker.slice(1).trim();
|
|
80
|
+
// Check for -- separator (reason follows)
|
|
81
|
+
const reasonSeparator = afterColon.indexOf('--');
|
|
82
|
+
if (reasonSeparator === -1) {
|
|
83
|
+
ruleId = afterColon.trim() || null;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
ruleId = afterColon.slice(0, reasonSeparator).trim() || null;
|
|
87
|
+
reason = afterColon.slice(reasonSeparator + 2).trim() || null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else if (afterMarker.trim().startsWith('--')) {
|
|
91
|
+
// Just a reason, no rule ID: // nosemgrep -- reason
|
|
92
|
+
reason = afterMarker.trim().slice(2).trim() || null;
|
|
93
|
+
}
|
|
94
|
+
return { isDirective: true, ruleId, reason };
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Check a single line for nosemgrep suppression issues.
|
|
98
|
+
*/
|
|
99
|
+
function checkNosemgrepLine(line, lineNumber) {
|
|
100
|
+
const { isDirective, ruleId, reason } = parseNosemgrepLine(line);
|
|
101
|
+
if (!isDirective) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
// Case 1: Missing rule ID (blanket suppress)
|
|
105
|
+
if (!ruleId) {
|
|
106
|
+
return {
|
|
107
|
+
line: lineNumber,
|
|
108
|
+
type: ISSUE_TYPE_MISSING_RULE,
|
|
109
|
+
ruleId: null,
|
|
110
|
+
comment: line.trim(),
|
|
111
|
+
message: reason
|
|
112
|
+
? `Blanket nosemgrep without rule ID. Specify which rule: // nosemgrep: specific.rule.id -- ${reason}`
|
|
113
|
+
: 'Blanket nosemgrep without rule ID or justification. Add: // nosemgrep: specific.rule.id -- [reason why this is safe]',
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// Case 2: Missing justification
|
|
117
|
+
if (!reason) {
|
|
118
|
+
return {
|
|
119
|
+
line: lineNumber,
|
|
120
|
+
type: ISSUE_TYPE_MISSING_JUSTIFICATION,
|
|
121
|
+
ruleId,
|
|
122
|
+
comment: line.trim(),
|
|
123
|
+
message: `nosemgrep for '${ruleId}' missing justification. Add: // nosemgrep: ${ruleId} -- [specific reason why this is safe]`,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
// Case 3: Generic justification
|
|
127
|
+
if (isGenericJustification(reason)) {
|
|
128
|
+
return {
|
|
129
|
+
line: lineNumber,
|
|
130
|
+
type: ISSUE_TYPE_GENERIC_JUSTIFICATION,
|
|
131
|
+
ruleId,
|
|
132
|
+
comment: line.trim(),
|
|
133
|
+
message: `Generic justification for '${ruleId}': "${reason}". Replace with specific reason explaining why this code is safe (e.g., "Input validated by Zod schema" or "Internal CLI tool with trusted input only")`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// Valid justification
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Validates nosemgrep suppressions in file content.
|
|
141
|
+
*/
|
|
142
|
+
function validateNosemgrepSuppressions(content) {
|
|
143
|
+
const issues = [];
|
|
144
|
+
const lines = content.split('\n');
|
|
145
|
+
for (const [i, line] of lines.entries()) {
|
|
146
|
+
if (!line)
|
|
147
|
+
continue;
|
|
148
|
+
const issue = checkNosemgrepLine(line, i + 1);
|
|
149
|
+
if (issue) {
|
|
150
|
+
issues.push(issue);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return issues;
|
|
154
|
+
}
|
|
155
|
+
// =============================================================================
|
|
156
|
+
// HELPERS
|
|
157
|
+
// =============================================================================
|
|
158
|
+
function getSuggestionForIssueType(issueType) {
|
|
159
|
+
switch (issueType) {
|
|
160
|
+
case ISSUE_TYPE_MISSING_JUSTIFICATION: {
|
|
161
|
+
return 'Add a justification after -- explaining why this suppression is safe';
|
|
162
|
+
}
|
|
163
|
+
case ISSUE_TYPE_GENERIC_JUSTIFICATION: {
|
|
164
|
+
return 'Replace generic justification with a specific explanation of why this code is safe';
|
|
165
|
+
}
|
|
166
|
+
case ISSUE_TYPE_MISSING_RULE: {
|
|
167
|
+
return 'Specify the rule ID being suppressed: // nosemgrep: rule.id -- reason';
|
|
168
|
+
}
|
|
169
|
+
default: {
|
|
170
|
+
return 'Fix the nosemgrep directive format: // nosemgrep: rule.id -- reason';
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function getSeverityForIssueType(issueType) {
|
|
175
|
+
// Generic justifications are warnings, missing justifications/rules are errors
|
|
176
|
+
return issueType === ISSUE_TYPE_GENERIC_JUSTIFICATION ? 'warning' : 'error';
|
|
177
|
+
}
|
|
178
|
+
// =============================================================================
|
|
179
|
+
// CHECK DEFINITION
|
|
180
|
+
// =============================================================================
|
|
181
|
+
/**
|
|
182
|
+
* Check: quality/semgrep-justifications
|
|
183
|
+
*
|
|
184
|
+
* Ensures all nosemgrep suppressions have proper justifications.
|
|
185
|
+
* Missing justifications are errors; generic justifications are warnings.
|
|
186
|
+
* Blanket suppressions (without rule IDs) are errors.
|
|
187
|
+
*/
|
|
188
|
+
export const semgrepJustifications = defineCheck({
|
|
189
|
+
id: CHECK_ID,
|
|
190
|
+
slug: CHECK_SLUG,
|
|
191
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'frontend', 'cli'] },
|
|
192
|
+
contentFilter: 'raw',
|
|
193
|
+
confidence: 'medium',
|
|
194
|
+
description: 'Ensures all nosemgrep suppressions have proper justifications',
|
|
195
|
+
longDescription: `**Purpose:** Enforces that every \`nosemgrep\` directive includes a specific rule ID and a meaningful justification explaining why the suppression is safe.
|
|
196
|
+
|
|
197
|
+
**Detects:**
|
|
198
|
+
- Blanket \`nosemgrep\` directives without a rule ID (e.g., \`// nosemgrep\` instead of \`// nosemgrep: rule.id\`)
|
|
199
|
+
- Missing justifications (no \`--\` separator with reason after the rule ID)
|
|
200
|
+
- Generic justifications matching patterns like \`todo\`, \`fix later\`, \`temp\`, \`hack\`, \`safe\`, \`ok\`, \`false positive\`, etc. (18 patterns total)
|
|
201
|
+
- Justifications shorter than 10 characters
|
|
202
|
+
|
|
203
|
+
**Why it matters:** Semgrep suppressions hide security and correctness findings. Without specific justifications, it is impossible to audit whether suppressions are still valid or were added carelessly.
|
|
204
|
+
|
|
205
|
+
**Scope:** Analyzes each file individually. General best practice for security suppression documentation.`,
|
|
206
|
+
tags: ['compliance', 'documentation', 'security', 'quality'],
|
|
207
|
+
fileTypes: ['ts', 'tsx'],
|
|
208
|
+
analyze: (content, filePath) => {
|
|
209
|
+
const violations = [];
|
|
210
|
+
// Early exit optimization: skip files without any nosemgrep
|
|
211
|
+
if (!content.includes('nosemgrep')) {
|
|
212
|
+
return violations;
|
|
213
|
+
}
|
|
214
|
+
const issues = validateNosemgrepSuppressions(content);
|
|
215
|
+
for (const issue of issues) {
|
|
216
|
+
violations.push({
|
|
217
|
+
filePath,
|
|
218
|
+
line: issue.line,
|
|
219
|
+
message: issue.message,
|
|
220
|
+
severity: getSeverityForIssueType(issue.type),
|
|
221
|
+
suggestion: getSuggestionForIssueType(issue.type),
|
|
222
|
+
type: issue.type,
|
|
223
|
+
match: issue.comment,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
return violations;
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
//# sourceMappingURL=semgrep-justifications.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semgrep-justifications.js","sourceRoot":"","sources":["../../../../src/checks/quality/linting/semgrep-justifications.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TypeScript Directive Hygiene Check
|
|
3
|
+
*
|
|
4
|
+
* Validates TypeScript suppression directives (@ts-expect-error, @ts-ignore) have proper justifications.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Check: quality/typescript-directive-hygiene
|
|
8
|
+
*
|
|
9
|
+
* Ensures @ts-expect-error and @ts-ignore have proper justifications.
|
|
10
|
+
*/
|
|
11
|
+
export declare const typescriptDirectiveHygiene: import("@opensip-cli/fitness").Check;
|
|
12
|
+
//# sourceMappingURL=typescript-directive-hygiene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typescript-directive-hygiene.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/linting/typescript-directive-hygiene.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAsEH;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,sCA+ErC,CAAC"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TypeScript Directive Hygiene Check
|
|
3
|
+
*
|
|
4
|
+
* Validates TypeScript suppression directives (@ts-expect-error, @ts-ignore) have proper justifications.
|
|
5
|
+
*/
|
|
6
|
+
import { defineCheck, isTestFile } from '@opensip-cli/fitness';
|
|
7
|
+
/** Check ID constant to avoid duplicate string literals */
|
|
8
|
+
const CHECK_SLUG = 'typescript-directive-hygiene';
|
|
9
|
+
const CHECK_ID = 'e7007f81-f00c-4a2e-99a2-fc8a2193f658';
|
|
10
|
+
/**
|
|
11
|
+
* Regex to match TypeScript directive comments.
|
|
12
|
+
* Uses character class for whitespace to prevent ReDoS (no backtracking on \s*).
|
|
13
|
+
* Pattern: // followed by optional spaces/tabs, then directive, then rest of line
|
|
14
|
+
*/
|
|
15
|
+
const TS_DIRECTIVE_REGEX = /\/\/[ \t]*(@ts-expect-error|@ts-ignore)([^\n]*)$/;
|
|
16
|
+
const GENERIC_JUSTIFICATIONS = [
|
|
17
|
+
/^$/,
|
|
18
|
+
/^[ \t]*$/,
|
|
19
|
+
/^todo$/i,
|
|
20
|
+
/^fix[ \t]*(?:this|later|me)?$/i,
|
|
21
|
+
/^temporary$/i,
|
|
22
|
+
/^temp$/i,
|
|
23
|
+
/^wip$/i,
|
|
24
|
+
/^ignore$/i,
|
|
25
|
+
/^skip$/i,
|
|
26
|
+
/^hack$/i,
|
|
27
|
+
/^workaround$/i,
|
|
28
|
+
];
|
|
29
|
+
const MIN_JUSTIFICATION_LENGTH = 10;
|
|
30
|
+
/**
|
|
31
|
+
* Extract justification from the text after a TypeScript directive
|
|
32
|
+
*/
|
|
33
|
+
function extractJustification(afterDirective) {
|
|
34
|
+
const trimmed = afterDirective.trim();
|
|
35
|
+
// Check for -- separator (non-greedy, use string operations)
|
|
36
|
+
if (trimmed.startsWith('--')) {
|
|
37
|
+
const rest = trimmed.slice(2).trim();
|
|
38
|
+
return rest || null;
|
|
39
|
+
}
|
|
40
|
+
// Check for - separator (must have space after dash)
|
|
41
|
+
if (trimmed.startsWith('- ')) {
|
|
42
|
+
const rest = trimmed.slice(2).trim();
|
|
43
|
+
return rest || null;
|
|
44
|
+
}
|
|
45
|
+
// Check for : separator
|
|
46
|
+
if (trimmed.startsWith(':')) {
|
|
47
|
+
const rest = trimmed.slice(1).trim();
|
|
48
|
+
return rest || null;
|
|
49
|
+
}
|
|
50
|
+
// Accept substantial text without separator
|
|
51
|
+
if (trimmed.length >= MIN_JUSTIFICATION_LENGTH)
|
|
52
|
+
return trimmed;
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Check if a justification is too generic
|
|
57
|
+
*/
|
|
58
|
+
function isGeneric(justification) {
|
|
59
|
+
const trimmed = justification.trim();
|
|
60
|
+
if (trimmed.length < MIN_JUSTIFICATION_LENGTH)
|
|
61
|
+
return true;
|
|
62
|
+
return GENERIC_JUSTIFICATIONS.some((p) => p.test(trimmed));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check: quality/typescript-directive-hygiene
|
|
66
|
+
*
|
|
67
|
+
* Ensures @ts-expect-error and @ts-ignore have proper justifications.
|
|
68
|
+
*/
|
|
69
|
+
export const typescriptDirectiveHygiene = defineCheck({
|
|
70
|
+
id: CHECK_ID,
|
|
71
|
+
slug: CHECK_SLUG,
|
|
72
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'frontend', 'cli'] },
|
|
73
|
+
contentFilter: 'raw',
|
|
74
|
+
confidence: 'medium',
|
|
75
|
+
description: 'Ensures TypeScript directives have proper justifications',
|
|
76
|
+
longDescription: `**Purpose:** Enforces that every \`@ts-expect-error\` and \`@ts-ignore\` directive includes a meaningful justification and prefers \`@ts-expect-error\` over \`@ts-ignore\`.
|
|
77
|
+
|
|
78
|
+
**Detects:**
|
|
79
|
+
- Missing justifications on \`@ts-expect-error\` and \`@ts-ignore\` directives (no \`--\`, \`-\`, or \`:\` separator with reason)
|
|
80
|
+
- Generic justifications matching patterns like \`todo\`, \`fix later\`, \`temp\`, \`hack\`, \`workaround\`, etc., or text shorter than 10 characters
|
|
81
|
+
- Usage of \`@ts-ignore\` where \`@ts-expect-error\` should be used instead (warns about stale suppression risk)
|
|
82
|
+
|
|
83
|
+
**Why it matters:** Unjustified type suppressions hide real type errors and accumulate as technical debt. Using \`@ts-expect-error\` over \`@ts-ignore\` ensures suppressions are automatically flagged when the underlying issue is fixed.
|
|
84
|
+
|
|
85
|
+
**Scope:** Analyzes each file individually (excludes test files: \`**/__tests__/**\`, \`**/*.test.*\`, \`**/*.spec.*\`). General best practice.`,
|
|
86
|
+
tags: ['quality', 'code-quality', 'documentation'],
|
|
87
|
+
fileTypes: ['ts'],
|
|
88
|
+
analyze: (content, filePath) => {
|
|
89
|
+
const violations = [];
|
|
90
|
+
// Skip test files — directives inside test-fixture string literals are
|
|
91
|
+
// not source-level directives (the longDescription has always claimed this).
|
|
92
|
+
if (isTestFile(filePath))
|
|
93
|
+
return violations;
|
|
94
|
+
// Quick filter - skip files without directives
|
|
95
|
+
if (!content.includes('@ts-expect-error') && !content.includes('@ts-ignore')) {
|
|
96
|
+
return violations;
|
|
97
|
+
}
|
|
98
|
+
const lines = content.split('\n');
|
|
99
|
+
for (const [i, line_] of lines.entries()) {
|
|
100
|
+
const line = line_ ?? '';
|
|
101
|
+
const match = TS_DIRECTIVE_REGEX.exec(line);
|
|
102
|
+
if (!match)
|
|
103
|
+
continue;
|
|
104
|
+
const directive = match[1];
|
|
105
|
+
const afterDirective = match[2] ?? '';
|
|
106
|
+
const justification = extractJustification(afterDirective);
|
|
107
|
+
const lineNum = i + 1;
|
|
108
|
+
if (!justification) {
|
|
109
|
+
violations.push({
|
|
110
|
+
filePath,
|
|
111
|
+
line: lineNum,
|
|
112
|
+
message: `${directive} missing justification`,
|
|
113
|
+
severity: 'error',
|
|
114
|
+
suggestion: `Add a justification after the directive: ${directive} -- Reason why this suppression is needed`,
|
|
115
|
+
match: directive,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
else if (isGeneric(justification)) {
|
|
119
|
+
violations.push({
|
|
120
|
+
filePath,
|
|
121
|
+
line: lineNum,
|
|
122
|
+
message: `${directive} has generic justification: "${justification}"`,
|
|
123
|
+
severity: 'warning',
|
|
124
|
+
suggestion: `Replace generic justification with a specific explanation. Minimum ${MIN_JUSTIFICATION_LENGTH} characters describing WHY the suppression is needed`,
|
|
125
|
+
match: justification,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
else if (directive === '@ts-ignore') {
|
|
129
|
+
violations.push({
|
|
130
|
+
filePath,
|
|
131
|
+
line: lineNum,
|
|
132
|
+
message: `Use @ts-expect-error instead of @ts-ignore`,
|
|
133
|
+
severity: 'warning',
|
|
134
|
+
suggestion: 'Replace @ts-ignore with @ts-expect-error. The latter will error if the suppressed issue is fixed, preventing stale suppressions',
|
|
135
|
+
match: directive,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return violations;
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
//# sourceMappingURL=typescript-directive-hygiene.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typescript-directive-hygiene.js","sourceRoot":"","sources":["../../../../src/checks/quality/linting/typescript-directive-hygiene.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Detects compatibility-layer / legacy-wrapper /
|
|
3
|
+
* backward-compat declarations.
|
|
4
|
+
*
|
|
5
|
+
* Catches class/function/variable declarations whose names contain
|
|
6
|
+
* `CompatibilityLayer`, `LegacyWrapper`, or `BackwardCompat`. Refactor
|
|
7
|
+
* to the modern implementation directly; don't keep both paths alive
|
|
8
|
+
* behind a wrapper.
|
|
9
|
+
*
|
|
10
|
+
* Extracted from the former `no-legacy-code` umbrella in Phase C4.
|
|
11
|
+
*/
|
|
12
|
+
export declare const noCompatibilityLayerNames: import("@opensip-cli/fitness").Check;
|
|
13
|
+
//# sourceMappingURL=no-compatibility-layer-names.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-compatibility-layer-names.d.ts","sourceRoot":"","sources":["../../../src/checks/quality/no-compatibility-layer-names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAwDH,eAAO,MAAM,yBAAyB,sCAkDpC,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Detects compatibility-layer / legacy-wrapper /
|
|
3
|
+
* backward-compat declarations.
|
|
4
|
+
*
|
|
5
|
+
* Catches class/function/variable declarations whose names contain
|
|
6
|
+
* `CompatibilityLayer`, `LegacyWrapper`, or `BackwardCompat`. Refactor
|
|
7
|
+
* to the modern implementation directly; don't keep both paths alive
|
|
8
|
+
* behind a wrapper.
|
|
9
|
+
*
|
|
10
|
+
* Extracted from the former `no-legacy-code` umbrella in Phase C4.
|
|
11
|
+
*/
|
|
12
|
+
import { defineCheck } from '@opensip-cli/fitness';
|
|
13
|
+
const EXCLUDE_PATTERNS = [/fitness/, /test/, /spec/, /docs/, /reports/, /versioning/];
|
|
14
|
+
function shouldExcludeFile(relativePath) {
|
|
15
|
+
return EXCLUDE_PATTERNS.some((pattern) => pattern.test(relativePath));
|
|
16
|
+
}
|
|
17
|
+
const DECLARATION_KEYWORDS = ['class ', 'function ', 'const ', 'let ', 'var '];
|
|
18
|
+
const MATCHERS = [
|
|
19
|
+
{
|
|
20
|
+
needle: 'compatibilitylayer',
|
|
21
|
+
type: 'compatibility-layer',
|
|
22
|
+
message: 'Found compatibility layer class/function - refactor directly instead',
|
|
23
|
+
suggestion: 'Refactor to use the new implementation directly without a compatibility layer',
|
|
24
|
+
allowClass: true,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
needle: 'legacywrapper',
|
|
28
|
+
type: 'legacy-code-path',
|
|
29
|
+
message: 'Found legacy wrapper class/function - remove and update all dependent code',
|
|
30
|
+
suggestion: 'Remove the legacy wrapper and update all dependent code to use the modern implementation',
|
|
31
|
+
allowClass: true,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
needle: 'backwardcompat',
|
|
35
|
+
type: 'migration-utility',
|
|
36
|
+
message: 'Found backwards compatibility utility - not needed during pre-launch phase',
|
|
37
|
+
suggestion: 'Remove backwards compatibility utilities and use direct implementations',
|
|
38
|
+
allowClass: false,
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
function matchesDeclaration(line, matcher) {
|
|
42
|
+
const lower = line.toLowerCase();
|
|
43
|
+
if (!lower.includes(matcher.needle))
|
|
44
|
+
return false;
|
|
45
|
+
return DECLARATION_KEYWORDS.some((kw) => {
|
|
46
|
+
if (!matcher.allowClass && kw === 'class ')
|
|
47
|
+
return false;
|
|
48
|
+
return lower.includes(kw);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
export const noCompatibilityLayerNames = defineCheck({
|
|
52
|
+
id: 'e39edca8-ee4d-4de8-9a39-655f4d0eb86d',
|
|
53
|
+
slug: 'no-compatibility-layer-names',
|
|
54
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'frontend', 'cli'] },
|
|
55
|
+
contentFilter: 'raw',
|
|
56
|
+
confidence: 'medium',
|
|
57
|
+
description: 'Detects compatibility-layer, legacy-wrapper, and backward-compat declarations',
|
|
58
|
+
longDescription: `**Purpose:** Flags class/function/variable declarations whose names announce themselves as a compatibility layer. Once a refactor is done, the wrapper should be removed and call sites updated to the new implementation directly.
|
|
59
|
+
|
|
60
|
+
**Detects:**
|
|
61
|
+
- Declarations containing \`CompatibilityLayer\` (class/function/const/let/var)
|
|
62
|
+
- Declarations containing \`LegacyWrapper\` (class/function/const/let/var)
|
|
63
|
+
- Declarations containing \`BackwardCompat\` (function/const/let/var; \`class\` excluded — too rare to be reliable)
|
|
64
|
+
|
|
65
|
+
**Why it matters:** Wrapper names signal that two implementations are alive at once. Resolving the wrapper to a single direct implementation removes a source of drift.
|
|
66
|
+
|
|
67
|
+
**Scope:** General best practice. Analyzes each file individually; excludes test/docs/versioning paths.`,
|
|
68
|
+
tags: ['code-quality', 'compliance', 'quality'],
|
|
69
|
+
fileTypes: ['ts', 'tsx'],
|
|
70
|
+
analyze(content, filePath) {
|
|
71
|
+
if (shouldExcludeFile(filePath))
|
|
72
|
+
return [];
|
|
73
|
+
const lower = content.toLowerCase();
|
|
74
|
+
const hasAnyNeedle = MATCHERS.some((m) => lower.includes(m.needle));
|
|
75
|
+
if (!hasAnyNeedle)
|
|
76
|
+
return [];
|
|
77
|
+
const violations = [];
|
|
78
|
+
const lines = content.split('\n');
|
|
79
|
+
for (const [i, line] of lines.entries()) {
|
|
80
|
+
if (!line)
|
|
81
|
+
continue;
|
|
82
|
+
for (const matcher of MATCHERS) {
|
|
83
|
+
if (matchesDeclaration(line, matcher)) {
|
|
84
|
+
violations.push({
|
|
85
|
+
line: i + 1,
|
|
86
|
+
column: 0,
|
|
87
|
+
message: matcher.message,
|
|
88
|
+
severity: 'error',
|
|
89
|
+
type: matcher.type,
|
|
90
|
+
suggestion: matcher.suggestion,
|
|
91
|
+
match: line.trim(),
|
|
92
|
+
});
|
|
93
|
+
break; // one finding per line
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return violations;
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
//# sourceMappingURL=no-compatibility-layer-names.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-compatibility-layer-names.js","sourceRoot":"","sources":["../../../src/checks/quality/no-compatibility-layer-names.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Detects `@deprecated` JSDoc tags in production code.
|
|
3
|
+
*
|
|
4
|
+
* Once a symbol is marked deprecated, the deprecated implementation
|
|
5
|
+
* should be removed in the same PR — leaving it behind keeps two
|
|
6
|
+
* paths alive and accumulates tech debt.
|
|
7
|
+
*
|
|
8
|
+
* Extracted from the former `no-legacy-code` umbrella in Phase C4.
|
|
9
|
+
*/
|
|
10
|
+
export declare const noDeprecatedTags: import("@opensip-cli/fitness").Check;
|
|
11
|
+
//# sourceMappingURL=no-deprecated-tags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-deprecated-tags.d.ts","sourceRoot":"","sources":["../../../src/checks/quality/no-deprecated-tags.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA8BH,eAAO,MAAM,gBAAgB,sCA4C3B,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Detects `@deprecated` JSDoc tags in production code.
|
|
3
|
+
*
|
|
4
|
+
* Once a symbol is marked deprecated, the deprecated implementation
|
|
5
|
+
* should be removed in the same PR — leaving it behind keeps two
|
|
6
|
+
* paths alive and accumulates tech debt.
|
|
7
|
+
*
|
|
8
|
+
* Extracted from the former `no-legacy-code` umbrella in Phase C4.
|
|
9
|
+
*/
|
|
10
|
+
import { defineCheck } from '@opensip-cli/fitness';
|
|
11
|
+
const EXCLUDE_PATTERNS = [
|
|
12
|
+
/fitness/,
|
|
13
|
+
/test/,
|
|
14
|
+
/spec/,
|
|
15
|
+
/docs/,
|
|
16
|
+
/reports/,
|
|
17
|
+
// Schema-migration utilities legitimately mark superseded versions
|
|
18
|
+
/versioning/,
|
|
19
|
+
];
|
|
20
|
+
function shouldExcludeFile(relativePath) {
|
|
21
|
+
return EXCLUDE_PATTERNS.some((pattern) => pattern.test(relativePath));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Detects JSDoc `@deprecated` tag lines. Uses string operations to
|
|
25
|
+
* avoid regex complexity and ReDoS.
|
|
26
|
+
*/
|
|
27
|
+
function isDeprecatedJsdocLine(line) {
|
|
28
|
+
const trimmed = line.trim();
|
|
29
|
+
const normalized = trimmed.startsWith('*') ? trimmed.slice(1).trim() : trimmed;
|
|
30
|
+
// Defensive concatenation — avoids accidental self-detection in this file's source.
|
|
31
|
+
const marker = '@' + 'deprecated';
|
|
32
|
+
return normalized.toLowerCase().startsWith(marker);
|
|
33
|
+
}
|
|
34
|
+
export const noDeprecatedTags = defineCheck({
|
|
35
|
+
id: '3a27c17d-a926-46a8-864d-610de1a385eb',
|
|
36
|
+
slug: 'no-deprecated-tags',
|
|
37
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'frontend', 'cli'] },
|
|
38
|
+
contentFilter: 'raw',
|
|
39
|
+
confidence: 'medium',
|
|
40
|
+
description: 'Detects @deprecated JSDoc tags in production code',
|
|
41
|
+
longDescription: `**Purpose:** Surfaces \`@deprecated\` JSDoc tags so the deprecated implementation can be removed and call sites updated in the same PR.
|
|
42
|
+
|
|
43
|
+
**Detects:**
|
|
44
|
+
- JSDoc lines whose first non-asterisk word is \`@deprecated\` (case-insensitive)
|
|
45
|
+
|
|
46
|
+
**Why it matters:** Deprecation tags accumulate when the deprecated path stays alive. The fitness rule treats every tag as a follow-up to schedule, not a permanent annotation.
|
|
47
|
+
|
|
48
|
+
**Scope:** General best practice. Analyzes each file individually; excludes test/docs/versioning paths.`,
|
|
49
|
+
tags: ['code-quality', 'compliance', 'quality'],
|
|
50
|
+
fileTypes: ['ts', 'tsx'],
|
|
51
|
+
analyze(content, filePath) {
|
|
52
|
+
if (shouldExcludeFile(filePath))
|
|
53
|
+
return [];
|
|
54
|
+
if (!content.toLowerCase().includes('deprecated'))
|
|
55
|
+
return [];
|
|
56
|
+
const violations = [];
|
|
57
|
+
const lines = content.split('\n');
|
|
58
|
+
for (const [i, line] of lines.entries()) {
|
|
59
|
+
if (!line)
|
|
60
|
+
continue;
|
|
61
|
+
if (isDeprecatedJsdocLine(line)) {
|
|
62
|
+
violations.push({
|
|
63
|
+
line: i + 1,
|
|
64
|
+
column: 0,
|
|
65
|
+
message: 'Found @deprecated JSDoc tag - remove this deprecated code and update all callers in the same PR',
|
|
66
|
+
severity: 'error',
|
|
67
|
+
type: 'deprecated-tag',
|
|
68
|
+
suggestion: 'Remove the deprecated code entirely and update all call sites in the same PR',
|
|
69
|
+
match: line.trim(),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return violations;
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=no-deprecated-tags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-deprecated-tags.js","sourceRoot":"","sources":["../../../src/checks/quality/no-deprecated-tags.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAuB,MAAM,sBAAsB,CAAC;AAExE,MAAM,gBAAgB,GAAG;IACvB,SAAS;IACT,MAAM;IACN,MAAM;IACN,MAAM;IACN,SAAS;IACT,mEAAmE;IACnE,YAAY;CACb,CAAC;AAEF,SAAS,iBAAiB,CAAC,YAAoB;IAC7C,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;AACxE,CAAC;AAED;;;GAGG;AACH,SAAS,qBAAqB,CAAC,IAAY;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IAC/E,oFAAoF;IACpF,MAAM,MAAM,GAAG,GAAG,GAAG,YAAY,CAAC;IAClC,OAAO,UAAU,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC;IAC1C,EAAE,EAAE,sCAAsC;IAC1C,IAAI,EAAE,oBAAoB;IAC1B,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE;IAC9E,aAAa,EAAE,KAAK;IACpB,UAAU,EAAE,QAAQ;IACpB,WAAW,EAAE,mDAAmD;IAChE,eAAe,EAAE;;;;;;;wGAOqF;IACtG,IAAI,EAAE,CAAC,cAAc,EAAE,YAAY,EAAE,SAAS,CAAC;IAC/C,SAAS,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC;IAExB,OAAO,CAAC,OAAO,EAAE,QAAQ;QACvB,IAAI,iBAAiB,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,CAAC;QAC3C,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;YAAE,OAAO,EAAE,CAAC;QAE7D,MAAM,UAAU,GAAqB,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,KAAK,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YACxC,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,IAAI,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChC,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,CAAC,GAAG,CAAC;oBACX,MAAM,EAAE,CAAC;oBACT,OAAO,EACL,iGAAiG;oBACnG,QAAQ,EAAE,OAAO;oBACjB,IAAI,EAAE,gBAAgB;oBACtB,UAAU,EACR,8EAA8E;oBAChF,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE;iBACnB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Detect markdown file references in code comments
|
|
3
|
+
*
|
|
4
|
+
* File path references to markdown documents become stale when documents are
|
|
5
|
+
* moved, renamed, or deleted. Use stable identifiers instead.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Check: quality/no-markdown-references
|
|
9
|
+
*
|
|
10
|
+
* Detects markdown file path references in code comments. These references
|
|
11
|
+
* become stale when documents are moved, renamed, or deleted.
|
|
12
|
+
*
|
|
13
|
+
* Use stable identifiers instead of file paths to avoid stale references.
|
|
14
|
+
*/
|
|
15
|
+
export declare const noMarkdownReferences: import("@opensip-cli/fitness").Check;
|
|
16
|
+
//# sourceMappingURL=no-markdown-references.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-markdown-references.d.ts","sourceRoot":"","sources":["../../../src/checks/quality/no-markdown-references.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAwGH;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,sCA4C/B,CAAC"}
|