@opensip-cli/checks-typescript 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 +12 -0
- package/dist/__tests__/all-checks-execute.test.d.ts.map +1 -0
- package/dist/__tests__/all-checks-execute.test.js +846 -0
- package/dist/__tests__/all-checks-execute.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-2.test.d.ts +9 -0
- package/dist/__tests__/behavior-fixtures-2.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-2.test.js +625 -0
- package/dist/__tests__/behavior-fixtures-2.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-3.test.d.ts +7 -0
- package/dist/__tests__/behavior-fixtures-3.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-3.test.js +658 -0
- package/dist/__tests__/behavior-fixtures-3.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-4.test.d.ts +8 -0
- package/dist/__tests__/behavior-fixtures-4.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-4.test.js +590 -0
- package/dist/__tests__/behavior-fixtures-4.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-5.test.d.ts +7 -0
- package/dist/__tests__/behavior-fixtures-5.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-5.test.js +548 -0
- package/dist/__tests__/behavior-fixtures-5.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-6.test.d.ts +18 -0
- package/dist/__tests__/behavior-fixtures-6.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-6.test.js +1700 -0
- package/dist/__tests__/behavior-fixtures-6.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures.test.d.ts +10 -0
- package/dist/__tests__/behavior-fixtures.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures.test.js +812 -0
- package/dist/__tests__/behavior-fixtures.test.js.map +1 -0
- package/dist/__tests__/branch-fixtures-2.test.d.ts +6 -0
- package/dist/__tests__/branch-fixtures-2.test.d.ts.map +1 -0
- package/dist/__tests__/branch-fixtures-2.test.js +1369 -0
- package/dist/__tests__/branch-fixtures-2.test.js.map +1 -0
- package/dist/__tests__/branch-fixtures-3.test.d.ts +7 -0
- package/dist/__tests__/branch-fixtures-3.test.d.ts.map +1 -0
- package/dist/__tests__/branch-fixtures-3.test.js +877 -0
- package/dist/__tests__/branch-fixtures-3.test.js.map +1 -0
- package/dist/__tests__/branch-fixtures.test.d.ts +6 -0
- package/dist/__tests__/branch-fixtures.test.d.ts.map +1 -0
- package/dist/__tests__/branch-fixtures.test.js +1072 -0
- package/dist/__tests__/branch-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 +39 -0
- package/dist/__tests__/checks.test.js.map +1 -0
- package/dist/__tests__/fixture-coverage.allowlist.d.ts +19 -0
- package/dist/__tests__/fixture-coverage.allowlist.d.ts.map +1 -0
- package/dist/__tests__/fixture-coverage.allowlist.js +27 -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__/no-bootstrap-tool-import.test.d.ts +2 -0
- package/dist/__tests__/no-bootstrap-tool-import.test.d.ts.map +1 -0
- package/dist/__tests__/no-bootstrap-tool-import.test.js +75 -0
- package/dist/__tests__/no-bootstrap-tool-import.test.js.map +1 -0
- package/dist/__tests__/phantom-dependency-detection.test.d.ts +12 -0
- package/dist/__tests__/phantom-dependency-detection.test.d.ts.map +1 -0
- package/dist/__tests__/phantom-dependency-detection.test.js +112 -0
- package/dist/__tests__/phantom-dependency-detection.test.js.map +1 -0
- package/dist/__tests__/typescript-frontend.test.d.ts +8 -0
- package/dist/__tests__/typescript-frontend.test.d.ts.map +1 -0
- package/dist/__tests__/typescript-frontend.test.js +57 -0
- package/dist/__tests__/typescript-frontend.test.js.map +1 -0
- package/dist/checks/architecture/circular-import-detection.d.ts +14 -0
- package/dist/checks/architecture/circular-import-detection.d.ts.map +1 -0
- package/dist/checks/architecture/circular-import-detection.js +55 -0
- package/dist/checks/architecture/circular-import-detection.js.map +1 -0
- package/dist/checks/architecture/contracts-schema-consistency.d.ts +11 -0
- package/dist/checks/architecture/contracts-schema-consistency.d.ts.map +1 -0
- package/dist/checks/architecture/contracts-schema-consistency.js +75 -0
- package/dist/checks/architecture/contracts-schema-consistency.js.map +1 -0
- package/dist/checks/architecture/drizzle-orm-migration-guardrails.d.ts +12 -0
- package/dist/checks/architecture/drizzle-orm-migration-guardrails.d.ts.map +1 -0
- package/dist/checks/architecture/drizzle-orm-migration-guardrails.js +92 -0
- package/dist/checks/architecture/drizzle-orm-migration-guardrails.js.map +1 -0
- package/dist/checks/architecture/index.d.ts +10 -0
- package/dist/checks/architecture/index.d.ts.map +1 -0
- package/dist/checks/architecture/index.js +10 -0
- package/dist/checks/architecture/index.js.map +1 -0
- package/dist/checks/architecture/missing-type-exports.d.ts +13 -0
- package/dist/checks/architecture/missing-type-exports.d.ts.map +1 -0
- package/dist/checks/architecture/missing-type-exports.js +245 -0
- package/dist/checks/architecture/missing-type-exports.js.map +1 -0
- package/dist/checks/architecture/module-coupling-fan-out.d.ts +20 -0
- package/dist/checks/architecture/module-coupling-fan-out.d.ts.map +1 -0
- package/dist/checks/architecture/module-coupling-fan-out.js +120 -0
- package/dist/checks/architecture/module-coupling-fan-out.js.map +1 -0
- package/dist/checks/architecture/no-bootstrap-tool-import.d.ts +38 -0
- package/dist/checks/architecture/no-bootstrap-tool-import.d.ts.map +1 -0
- package/dist/checks/architecture/no-bootstrap-tool-import.js +95 -0
- package/dist/checks/architecture/no-bootstrap-tool-import.js.map +1 -0
- package/dist/checks/architecture/package-json-exports-field.d.ts +10 -0
- package/dist/checks/architecture/package-json-exports-field.d.ts.map +1 -0
- package/dist/checks/architecture/package-json-exports-field.js +56 -0
- package/dist/checks/architecture/package-json-exports-field.js.map +1 -0
- package/dist/checks/architecture/phantom-dependency-detection.d.ts +22 -0
- package/dist/checks/architecture/phantom-dependency-detection.d.ts.map +1 -0
- package/dist/checks/architecture/phantom-dependency-detection.js +330 -0
- package/dist/checks/architecture/phantom-dependency-detection.js.map +1 -0
- package/dist/checks/architecture/tsconfig-extends-validation.d.ts +10 -0
- package/dist/checks/architecture/tsconfig-extends-validation.d.ts.map +1 -0
- package/dist/checks/architecture/tsconfig-extends-validation.js +78 -0
- package/dist/checks/architecture/tsconfig-extends-validation.js.map +1 -0
- package/dist/checks/index.d.ts +6 -0
- package/dist/checks/index.d.ts.map +1 -0
- package/dist/checks/index.js +6 -0
- package/dist/checks/index.js.map +1 -0
- package/dist/checks/quality/api/api-contract-validation.d.ts +15 -0
- package/dist/checks/quality/api/api-contract-validation.d.ts.map +1 -0
- package/dist/checks/quality/api/api-contract-validation.js +316 -0
- package/dist/checks/quality/api/api-contract-validation.js.map +1 -0
- package/dist/checks/quality/api/api-response-validation.d.ts +14 -0
- package/dist/checks/quality/api/api-response-validation.d.ts.map +1 -0
- package/dist/checks/quality/api/api-response-validation.js +209 -0
- package/dist/checks/quality/api/api-response-validation.js.map +1 -0
- package/dist/checks/quality/api/fastify-route-validation.d.ts +14 -0
- package/dist/checks/quality/api/fastify-route-validation.d.ts.map +1 -0
- package/dist/checks/quality/api/fastify-route-validation.js +298 -0
- package/dist/checks/quality/api/fastify-route-validation.js.map +1 -0
- package/dist/checks/quality/api/fastify-schema-coverage.d.ts +11 -0
- package/dist/checks/quality/api/fastify-schema-coverage.d.ts.map +1 -0
- package/dist/checks/quality/api/fastify-schema-coverage.js +261 -0
- package/dist/checks/quality/api/fastify-schema-coverage.js.map +1 -0
- package/dist/checks/quality/api/index.d.ts +5 -0
- package/dist/checks/quality/api/index.d.ts.map +1 -0
- package/dist/checks/quality/api/index.js +5 -0
- package/dist/checks/quality/api/index.js.map +1 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions.d.ts +32 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions.js +451 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions.js.map +1 -0
- package/dist/checks/quality/code-structure/index.d.ts +3 -0
- package/dist/checks/quality/code-structure/index.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/index.js +3 -0
- package/dist/checks/quality/code-structure/index.js.map +1 -0
- package/dist/checks/quality/code-structure/no-any-types.d.ts +13 -0
- package/dist/checks/quality/code-structure/no-any-types.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/no-any-types.js +116 -0
- package/dist/checks/quality/code-structure/no-any-types.js.map +1 -0
- package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.d.ts +15 -0
- package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.js +51 -0
- package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.js.map +1 -0
- package/dist/checks/quality/data-integrity/array-validation.d.ts +16 -0
- package/dist/checks/quality/data-integrity/array-validation.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/array-validation.js +508 -0
- package/dist/checks/quality/data-integrity/array-validation.js.map +1 -0
- package/dist/checks/quality/data-integrity/database-index-coverage.d.ts +14 -0
- package/dist/checks/quality/data-integrity/database-index-coverage.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/database-index-coverage.js +235 -0
- package/dist/checks/quality/data-integrity/database-index-coverage.js.map +1 -0
- package/dist/checks/quality/data-integrity/database-schema-validation.d.ts +16 -0
- package/dist/checks/quality/data-integrity/database-schema-validation.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/database-schema-validation.js +328 -0
- package/dist/checks/quality/data-integrity/database-schema-validation.js.map +1 -0
- package/dist/checks/quality/data-integrity/in-memory-repository-detection.d.ts +14 -0
- package/dist/checks/quality/data-integrity/in-memory-repository-detection.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/in-memory-repository-detection.js +157 -0
- package/dist/checks/quality/data-integrity/in-memory-repository-detection.js.map +1 -0
- package/dist/checks/quality/data-integrity/index.d.ts +8 -0
- package/dist/checks/quality/data-integrity/index.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/index.js +8 -0
- package/dist/checks/quality/data-integrity/index.js.map +1 -0
- package/dist/checks/quality/data-integrity/missing-input-validation.d.ts +12 -0
- package/dist/checks/quality/data-integrity/missing-input-validation.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/missing-input-validation.js +180 -0
- package/dist/checks/quality/data-integrity/missing-input-validation.js.map +1 -0
- package/dist/checks/quality/data-integrity/null-safety.d.ts +33 -0
- package/dist/checks/quality/data-integrity/null-safety.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/null-safety.js +766 -0
- package/dist/checks/quality/data-integrity/null-safety.js.map +1 -0
- package/dist/checks/quality/data-integrity/numeric-validation.d.ts +12 -0
- package/dist/checks/quality/data-integrity/numeric-validation.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/numeric-validation.js +409 -0
- package/dist/checks/quality/data-integrity/numeric-validation.js.map +1 -0
- package/dist/checks/quality/frontend/a11y-form-labels.d.ts +14 -0
- package/dist/checks/quality/frontend/a11y-form-labels.d.ts.map +1 -0
- package/dist/checks/quality/frontend/a11y-form-labels.js +93 -0
- package/dist/checks/quality/frontend/a11y-form-labels.js.map +1 -0
- package/dist/checks/quality/frontend/a11y-semantic-html.d.ts +14 -0
- package/dist/checks/quality/frontend/a11y-semantic-html.d.ts.map +1 -0
- package/dist/checks/quality/frontend/a11y-semantic-html.js +88 -0
- package/dist/checks/quality/frontend/a11y-semantic-html.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/test-only-frontend-modules.d.ts +13 -0
- package/dist/checks/quality/frontend/test-only-frontend-modules.d.ts.map +1 -0
- package/dist/checks/quality/frontend/test-only-frontend-modules.js +159 -0
- package/dist/checks/quality/frontend/test-only-frontend-modules.js.map +1 -0
- package/dist/checks/quality/incomplete-regex-escaping.d.ts +13 -0
- package/dist/checks/quality/incomplete-regex-escaping.d.ts.map +1 -0
- package/dist/checks/quality/incomplete-regex-escaping.js +207 -0
- package/dist/checks/quality/incomplete-regex-escaping.js.map +1 -0
- package/dist/checks/quality/index.d.ts +11 -0
- package/dist/checks/quality/index.d.ts.map +1 -0
- package/dist/checks/quality/index.js +11 -0
- package/dist/checks/quality/index.js.map +1 -0
- package/dist/checks/quality/linting/index.d.ts +2 -0
- package/dist/checks/quality/linting/index.d.ts.map +1 -0
- package/dist/checks/quality/linting/index.js +2 -0
- package/dist/checks/quality/linting/index.js.map +1 -0
- package/dist/checks/quality/linting/typescript-frontend.d.ts +25 -0
- package/dist/checks/quality/linting/typescript-frontend.d.ts.map +1 -0
- package/dist/checks/quality/linting/typescript-frontend.js +159 -0
- package/dist/checks/quality/linting/typescript-frontend.js.map +1 -0
- package/dist/checks/quality/observability/index.d.ts +5 -0
- package/dist/checks/quality/observability/index.d.ts.map +1 -0
- package/dist/checks/quality/observability/index.js +5 -0
- package/dist/checks/quality/observability/index.js.map +1 -0
- package/dist/checks/quality/observability/logger-event-name-format.d.ts +12 -0
- package/dist/checks/quality/observability/logger-event-name-format.d.ts.map +1 -0
- package/dist/checks/quality/observability/logger-event-name-format.js +124 -0
- package/dist/checks/quality/observability/logger-event-name-format.js.map +1 -0
- package/dist/checks/quality/observability/no-hardcoded-correlation-id.d.ts +5 -0
- package/dist/checks/quality/observability/no-hardcoded-correlation-id.d.ts.map +1 -0
- package/dist/checks/quality/observability/no-hardcoded-correlation-id.js +77 -0
- package/dist/checks/quality/observability/no-hardcoded-correlation-id.js.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/analyzer.test.d.ts +11 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/analyzer.test.d.ts.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/analyzer.test.js +107 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/analyzer.test.js.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/logger-detector.test.d.ts +12 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/logger-detector.test.d.ts.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/logger-detector.test.js +94 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/logger-detector.test.js.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/analyzer.d.ts +13 -0
- package/dist/checks/quality/observability/observability-coverage/analyzer.d.ts.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/analyzer.js +117 -0
- package/dist/checks/quality/observability/observability-coverage/analyzer.js.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/index.d.ts +4 -0
- package/dist/checks/quality/observability/observability-coverage/index.d.ts.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/index.js +4 -0
- package/dist/checks/quality/observability/observability-coverage/index.js.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/logger-detector.d.ts +29 -0
- package/dist/checks/quality/observability/observability-coverage/logger-detector.d.ts.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/logger-detector.js +111 -0
- package/dist/checks/quality/observability/observability-coverage/logger-detector.js.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/types.d.ts +64 -0
- package/dist/checks/quality/observability/observability-coverage/types.d.ts.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/types.js +6 -0
- package/dist/checks/quality/observability/observability-coverage/types.js.map +1 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.d.ts +22 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.d.ts.map +1 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.js +212 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.js.map +1 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.test.d.ts +11 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.test.d.ts.map +1 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.test.js +46 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.test.js.map +1 -0
- package/dist/checks/quality/patterns/__tests__/toctou-fp.test.d.ts +14 -0
- package/dist/checks/quality/patterns/__tests__/toctou-fp.test.d.ts.map +1 -0
- package/dist/checks/quality/patterns/__tests__/toctou-fp.test.js +61 -0
- package/dist/checks/quality/patterns/__tests__/toctou-fp.test.js.map +1 -0
- package/dist/checks/quality/patterns/async-waterfall-detection.d.ts +26 -0
- package/dist/checks/quality/patterns/async-waterfall-detection.d.ts.map +1 -0
- package/dist/checks/quality/patterns/async-waterfall-detection.js +410 -0
- package/dist/checks/quality/patterns/async-waterfall-detection.js.map +1 -0
- package/dist/checks/quality/patterns/dispose-pattern-completeness.d.ts +13 -0
- package/dist/checks/quality/patterns/dispose-pattern-completeness.d.ts.map +1 -0
- package/dist/checks/quality/patterns/dispose-pattern-completeness.js +220 -0
- package/dist/checks/quality/patterns/dispose-pattern-completeness.js.map +1 -0
- package/dist/checks/quality/patterns/error-handling-quality.d.ts +17 -0
- package/dist/checks/quality/patterns/error-handling-quality.d.ts.map +1 -0
- package/dist/checks/quality/patterns/error-handling-quality.js +335 -0
- package/dist/checks/quality/patterns/error-handling-quality.js.map +1 -0
- package/dist/checks/quality/patterns/index.d.ts +10 -0
- package/dist/checks/quality/patterns/index.d.ts.map +1 -0
- package/dist/checks/quality/patterns/index.js +10 -0
- package/dist/checks/quality/patterns/index.js.map +1 -0
- package/dist/checks/quality/patterns/lifecycle-cleanup-enforcement.d.ts +16 -0
- package/dist/checks/quality/patterns/lifecycle-cleanup-enforcement.d.ts.map +1 -0
- package/dist/checks/quality/patterns/lifecycle-cleanup-enforcement.js +205 -0
- package/dist/checks/quality/patterns/lifecycle-cleanup-enforcement.js.map +1 -0
- package/dist/checks/quality/patterns/result-pattern-consistency.d.ts +16 -0
- package/dist/checks/quality/patterns/result-pattern-consistency.d.ts.map +1 -0
- package/dist/checks/quality/patterns/result-pattern-consistency.js +328 -0
- package/dist/checks/quality/patterns/result-pattern-consistency.js.map +1 -0
- package/dist/checks/quality/patterns/silent-early-returns.d.ts +23 -0
- package/dist/checks/quality/patterns/silent-early-returns.d.ts.map +1 -0
- package/dist/checks/quality/patterns/silent-early-returns.js +266 -0
- package/dist/checks/quality/patterns/silent-early-returns.js.map +1 -0
- package/dist/checks/quality/patterns/stream-buffer-size-limits.d.ts +13 -0
- package/dist/checks/quality/patterns/stream-buffer-size-limits.d.ts.map +1 -0
- package/dist/checks/quality/patterns/stream-buffer-size-limits.js +163 -0
- package/dist/checks/quality/patterns/stream-buffer-size-limits.js.map +1 -0
- package/dist/checks/quality/patterns/throws-documentation.d.ts +23 -0
- package/dist/checks/quality/patterns/throws-documentation.d.ts.map +1 -0
- package/dist/checks/quality/patterns/throws-documentation.js +519 -0
- package/dist/checks/quality/patterns/throws-documentation.js.map +1 -0
- package/dist/checks/quality/patterns/toctou-race-condition.d.ts +48 -0
- package/dist/checks/quality/patterns/toctou-race-condition.d.ts.map +1 -0
- package/dist/checks/quality/patterns/toctou-race-condition.js +639 -0
- package/dist/checks/quality/patterns/toctou-race-condition.js.map +1 -0
- package/dist/checks/quality/stubbed-implementation-detection.d.ts +24 -0
- package/dist/checks/quality/stubbed-implementation-detection.d.ts.map +1 -0
- package/dist/checks/quality/stubbed-implementation-detection.js +355 -0
- package/dist/checks/quality/stubbed-implementation-detection.js.map +1 -0
- package/dist/checks/quality/unused-config-options.d.ts +12 -0
- package/dist/checks/quality/unused-config-options.d.ts.map +1 -0
- package/dist/checks/quality/unused-config-options.js +245 -0
- package/dist/checks/quality/unused-config-options.js.map +1 -0
- package/dist/checks/resilience/__tests__/callback-invocation-safe.test.d.ts +2 -0
- package/dist/checks/resilience/__tests__/callback-invocation-safe.test.d.ts.map +1 -0
- package/dist/checks/resilience/__tests__/callback-invocation-safe.test.js +79 -0
- package/dist/checks/resilience/__tests__/callback-invocation-safe.test.js.map +1 -0
- package/dist/checks/resilience/__tests__/context-leakage-fp.test.d.ts +12 -0
- package/dist/checks/resilience/__tests__/context-leakage-fp.test.d.ts.map +1 -0
- package/dist/checks/resilience/__tests__/context-leakage-fp.test.js +34 -0
- package/dist/checks/resilience/__tests__/context-leakage-fp.test.js.map +1 -0
- package/dist/checks/resilience/__tests__/context-mutation.test.d.ts +11 -0
- package/dist/checks/resilience/__tests__/context-mutation.test.d.ts.map +1 -0
- package/dist/checks/resilience/__tests__/context-mutation.test.js +54 -0
- package/dist/checks/resilience/__tests__/context-mutation.test.js.map +1 -0
- package/dist/checks/resilience/callback-invocation-safe.d.ts +34 -0
- package/dist/checks/resilience/callback-invocation-safe.d.ts.map +1 -0
- package/dist/checks/resilience/callback-invocation-safe.js +247 -0
- package/dist/checks/resilience/callback-invocation-safe.js.map +1 -0
- package/dist/checks/resilience/context-leakage.d.ts +25 -0
- package/dist/checks/resilience/context-leakage.d.ts.map +1 -0
- package/dist/checks/resilience/context-leakage.js +435 -0
- package/dist/checks/resilience/context-leakage.js.map +1 -0
- package/dist/checks/resilience/context-mutation.d.ts +21 -0
- package/dist/checks/resilience/context-mutation.d.ts.map +1 -0
- package/dist/checks/resilience/context-mutation.js +368 -0
- package/dist/checks/resilience/context-mutation.js.map +1 -0
- package/dist/checks/resilience/detached-promises.d.ts +40 -0
- package/dist/checks/resilience/detached-promises.d.ts.map +1 -0
- package/dist/checks/resilience/detached-promises.js +646 -0
- package/dist/checks/resilience/detached-promises.js.map +1 -0
- package/dist/checks/resilience/index.d.ts +7 -0
- package/dist/checks/resilience/index.d.ts.map +1 -0
- package/dist/checks/resilience/index.js +7 -0
- package/dist/checks/resilience/index.js.map +1 -0
- package/dist/checks/resilience/no-raw-fetch.d.ts +11 -0
- package/dist/checks/resilience/no-raw-fetch.d.ts.map +1 -0
- package/dist/checks/resilience/no-raw-fetch.js +110 -0
- package/dist/checks/resilience/no-raw-fetch.js.map +1 -0
- package/dist/checks/resilience/no-unbounded-concurrency.d.ts +11 -0
- package/dist/checks/resilience/no-unbounded-concurrency.d.ts.map +1 -0
- package/dist/checks/resilience/no-unbounded-concurrency.js +117 -0
- package/dist/checks/resilience/no-unbounded-concurrency.js.map +1 -0
- package/dist/checks/security/__tests__/sql-injection.test.d.ts +17 -0
- package/dist/checks/security/__tests__/sql-injection.test.d.ts.map +1 -0
- package/dist/checks/security/__tests__/sql-injection.test.js +97 -0
- package/dist/checks/security/__tests__/sql-injection.test.js.map +1 -0
- package/dist/checks/security/index.d.ts +4 -0
- package/dist/checks/security/index.d.ts.map +1 -0
- package/dist/checks/security/index.js +4 -0
- package/dist/checks/security/index.js.map +1 -0
- package/dist/checks/security/input-sanitization.d.ts +20 -0
- package/dist/checks/security/input-sanitization.d.ts.map +1 -0
- package/dist/checks/security/input-sanitization.js +255 -0
- package/dist/checks/security/input-sanitization.js.map +1 -0
- package/dist/checks/security/sql-injection.d.ts +24 -0
- package/dist/checks/security/sql-injection.d.ts.map +1 -0
- package/dist/checks/security/sql-injection.js +330 -0
- package/dist/checks/security/sql-injection.js.map +1 -0
- package/dist/checks/security/unsafe-secret-comparison.d.ts +17 -0
- package/dist/checks/security/unsafe-secret-comparison.d.ts.map +1 -0
- package/dist/checks/security/unsafe-secret-comparison.js +227 -0
- package/dist/checks/security/unsafe-secret-comparison.js.map +1 -0
- package/dist/checks/testing/index.d.ts +2 -0
- package/dist/checks/testing/index.d.ts.map +1 -0
- package/dist/checks/testing/index.js +2 -0
- package/dist/checks/testing/index.js.map +1 -0
- package/dist/checks/testing/mock-implementations-in-production.d.ts +12 -0
- package/dist/checks/testing/mock-implementations-in-production.d.ts.map +1 -0
- package/dist/checks/testing/mock-implementations-in-production.js +211 -0
- package/dist/checks/testing/mock-implementations-in-production.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 +18 -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 +39 -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 +13 -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 +14 -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 +55 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
// @fitness-ignore-file unused-config-options -- Config options reserved for future use or environment-specific
|
|
2
|
+
// @fitness-ignore-file context-mutation -- Local array/object mutations are safe within function scope; not shared context
|
|
3
|
+
// @fitness-ignore-file silent-early-returns -- Guard clauses in pattern matching function return false for non-matching patterns
|
|
4
|
+
/**
|
|
5
|
+
* @fileoverview Context mutation safety check — flags direct mutation of
|
|
6
|
+
* request/execution context objects, which causes side effects across
|
|
7
|
+
* middleware in concurrent server environments.
|
|
8
|
+
*/
|
|
9
|
+
import { logger } from '@opensip-cli/core';
|
|
10
|
+
import { defineCheck, isCommentLine } from '@opensip-cli/fitness';
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// CONTEXT MUTATION CHECK
|
|
13
|
+
// =============================================================================
|
|
14
|
+
/**
|
|
15
|
+
* Safe string patterns for checking context objects.
|
|
16
|
+
* Using string includes for safe, linear-time matching.
|
|
17
|
+
*/
|
|
18
|
+
const CONTEXT_STRING_PATTERNS = [
|
|
19
|
+
'request.context',
|
|
20
|
+
'request.ctx',
|
|
21
|
+
'req.context',
|
|
22
|
+
'req.ctx',
|
|
23
|
+
'ctx.',
|
|
24
|
+
'context.',
|
|
25
|
+
'RequestContext',
|
|
26
|
+
'ExecutionContext',
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Checks if content uses context patterns.
|
|
30
|
+
* @param content - The content to check
|
|
31
|
+
* @returns True if content contains context patterns
|
|
32
|
+
*/
|
|
33
|
+
function usesContextPattern(content) {
|
|
34
|
+
return CONTEXT_STRING_PATTERNS.some((pattern) => content.includes(pattern));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Detects local declarations of `ctx` or `context` as a function-scoped
|
|
38
|
+
* variable — `const ctx = {...}`, `const ctx: T = {...}`, `let ctx`,
|
|
39
|
+
* `var ctx`. When such a declaration exists in the file, every
|
|
40
|
+
* subsequent `ctx.X =` mutation is a local-object-construction
|
|
41
|
+
* pattern, NOT a mutation of a shared request context. Skipping those
|
|
42
|
+
* lines eliminates the canonical false-positive where a function
|
|
43
|
+
* builds a return object named `ctx` and the check flags it as
|
|
44
|
+
* request-context mutation.
|
|
45
|
+
*
|
|
46
|
+
* Whole-word matching prevents collisions with `myCtx`, `subContext`,
|
|
47
|
+
* etc. Returns the set of identifier names that are locally declared
|
|
48
|
+
* — callers consult it before flagging a mutation rooted at that
|
|
49
|
+
* identifier.
|
|
50
|
+
*/
|
|
51
|
+
const LOCAL_DECLARATION_PATTERNS = [
|
|
52
|
+
['ctx', /\b(?:const|let|var)\s+ctx\b(?!\s*\.)/],
|
|
53
|
+
['context', /\b(?:const|let|var)\s+context\b(?!\s*\.)/],
|
|
54
|
+
];
|
|
55
|
+
function findLocallyDeclaredNames(content) {
|
|
56
|
+
const declared = new Set();
|
|
57
|
+
for (const [name, pattern] of LOCAL_DECLARATION_PATTERNS) {
|
|
58
|
+
if (pattern.test(content))
|
|
59
|
+
declared.add(name);
|
|
60
|
+
}
|
|
61
|
+
return declared;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Finds the end index of a word (consecutive word characters) in a string.
|
|
65
|
+
* @param str - The string to search
|
|
66
|
+
* @returns The index after the last word character, or 0 if no word characters found
|
|
67
|
+
*/
|
|
68
|
+
function findWordEndIndex(str) {
|
|
69
|
+
logger.debug({
|
|
70
|
+
evt: 'fitness.checks.context_mutation.find_word_end_index',
|
|
71
|
+
msg: 'Finding end index of word characters in string',
|
|
72
|
+
});
|
|
73
|
+
let wordEnd = 0;
|
|
74
|
+
// eslint-disable-next-line unicorn/no-for-loop -- offset-bearing scan: returns the UTF-16 index after the last word char
|
|
75
|
+
for (let i = 0; i < str.length; i++) {
|
|
76
|
+
const char = str[i];
|
|
77
|
+
if (char === undefined || !/\w/.test(char)) {
|
|
78
|
+
return wordEnd;
|
|
79
|
+
}
|
|
80
|
+
wordEnd = i + 1;
|
|
81
|
+
}
|
|
82
|
+
return wordEnd;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Creates a safe mutation detector using string matching.
|
|
86
|
+
* Detects patterns like: ctx.property = or context.field =
|
|
87
|
+
* Does NOT match comparison operators (==, ===, !=, !==)
|
|
88
|
+
* @param prefix - The prefix to match (e.g., 'ctx.')
|
|
89
|
+
* @returns A detector that checks for assignment after prefix and word
|
|
90
|
+
*/
|
|
91
|
+
function createAssignmentDetector(prefix) {
|
|
92
|
+
return {
|
|
93
|
+
test: (line) => {
|
|
94
|
+
logger.debug({
|
|
95
|
+
evt: 'fitness.checks.context_mutation.assignment_detector_test',
|
|
96
|
+
msg: 'Testing line for context assignment mutation',
|
|
97
|
+
});
|
|
98
|
+
const idx = line.indexOf(prefix);
|
|
99
|
+
if (idx === -1)
|
|
100
|
+
return false;
|
|
101
|
+
// Find next non-word character after prefix
|
|
102
|
+
const afterPrefix = line.slice(Math.max(0, idx + prefix.length));
|
|
103
|
+
// Must have at least one word character
|
|
104
|
+
const wordEnd = findWordEndIndex(afterPrefix);
|
|
105
|
+
if (wordEnd === 0)
|
|
106
|
+
return false;
|
|
107
|
+
const afterWord = afterPrefix.slice(Math.max(0, wordEnd)).trimStart();
|
|
108
|
+
// Check for assignment (but NOT comparison operators)
|
|
109
|
+
if (!afterWord.startsWith('='))
|
|
110
|
+
return false;
|
|
111
|
+
// Exclude === and == (comparison) and !=, !==
|
|
112
|
+
const secondChar = afterWord.charAt(1);
|
|
113
|
+
if (secondChar === '=' || secondChar === '!')
|
|
114
|
+
return false;
|
|
115
|
+
return true;
|
|
116
|
+
},
|
|
117
|
+
patternName: `${prefix}*=`,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Creates a simple string contains detector.
|
|
122
|
+
* @param pattern - The string pattern to match
|
|
123
|
+
* @returns A detector that checks for pattern inclusion
|
|
124
|
+
*/
|
|
125
|
+
function createContainsDetector(pattern) {
|
|
126
|
+
return {
|
|
127
|
+
test: (line) => line.includes(pattern),
|
|
128
|
+
patternName: pattern,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Creates a detector for array mutation methods on context objects.
|
|
133
|
+
* Only matches patterns like ctx.array.push() or context.items.splice()
|
|
134
|
+
* Does NOT match local variables like myArray.push()
|
|
135
|
+
* @param method - The method name (e.g., 'push', 'splice')
|
|
136
|
+
* @returns A detector that checks for context-prefixed array mutations
|
|
137
|
+
*/
|
|
138
|
+
function createContextArrayMutationDetector(method) {
|
|
139
|
+
const contextPrefixes = [
|
|
140
|
+
'ctx.',
|
|
141
|
+
'context.',
|
|
142
|
+
'req.context.',
|
|
143
|
+
'request.context.',
|
|
144
|
+
'req.',
|
|
145
|
+
'request.',
|
|
146
|
+
];
|
|
147
|
+
return {
|
|
148
|
+
test: (line) => {
|
|
149
|
+
logger.debug({
|
|
150
|
+
evt: 'fitness.checks.context_mutation.array_mutation_detector_test',
|
|
151
|
+
msg: 'Testing line for context array mutation pattern',
|
|
152
|
+
});
|
|
153
|
+
// Must contain the method call
|
|
154
|
+
if (!line.includes(`.${method}(`))
|
|
155
|
+
return false;
|
|
156
|
+
// Check if it's prefixed by a context variable
|
|
157
|
+
for (const prefix of contextPrefixes) {
|
|
158
|
+
const prefixIdx = line.indexOf(prefix);
|
|
159
|
+
if (prefixIdx !== -1) {
|
|
160
|
+
// Check if the method call is after the context prefix
|
|
161
|
+
const methodIdx = line.indexOf(`.${method}(`, prefixIdx);
|
|
162
|
+
if (methodIdx > prefixIdx) {
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
},
|
|
169
|
+
patternName: `ctx/*.${method}()`,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Safe mutation detectors using string-based matching.
|
|
174
|
+
* Only flags mutations on actual context objects, not local variables.
|
|
175
|
+
*/
|
|
176
|
+
const MUTATION_DETECTORS = [
|
|
177
|
+
createAssignmentDetector('ctx.'),
|
|
178
|
+
createAssignmentDetector('context.'),
|
|
179
|
+
createAssignmentDetector('req.context.'),
|
|
180
|
+
createAssignmentDetector('request.context.'),
|
|
181
|
+
createContainsDetector('Object.assign(ctx'),
|
|
182
|
+
createContainsDetector('Object.assign( ctx'),
|
|
183
|
+
createContainsDetector('Object.assign(context'),
|
|
184
|
+
createContainsDetector('Object.assign( context'),
|
|
185
|
+
// Only flag array mutations when prefixed by context objects
|
|
186
|
+
createContextArrayMutationDetector('push'),
|
|
187
|
+
createContextArrayMutationDetector('splice'),
|
|
188
|
+
createContextArrayMutationDetector('pop'),
|
|
189
|
+
createContextArrayMutationDetector('shift'),
|
|
190
|
+
createContextArrayMutationDetector('unshift'),
|
|
191
|
+
createContainsDetector('delete ctx.'),
|
|
192
|
+
createContainsDetector('delete context.'),
|
|
193
|
+
];
|
|
194
|
+
/**
|
|
195
|
+
* Safe keywords (allowed mutations).
|
|
196
|
+
* These are common fields that are either:
|
|
197
|
+
* - Standard context setup fields that are expected to be set
|
|
198
|
+
* - Fields that indicate local object construction, not request context mutation
|
|
199
|
+
*/
|
|
200
|
+
const SAFE_KEYWORDS = [
|
|
201
|
+
'correlationId',
|
|
202
|
+
'requestId',
|
|
203
|
+
'traceId',
|
|
204
|
+
'spanId',
|
|
205
|
+
'logger',
|
|
206
|
+
'startTime',
|
|
207
|
+
// Common local context construction patterns
|
|
208
|
+
'userId', // User ID setup in local context objects
|
|
209
|
+
'timestamp', // Timestamp field in local context
|
|
210
|
+
'details', // Details field in error/result context
|
|
211
|
+
'metadata', // Metadata field in local context
|
|
212
|
+
'statusCode', // Status code in error context
|
|
213
|
+
'code', // Error code in error context
|
|
214
|
+
// Recovery/retry execution context fields
|
|
215
|
+
'fallbackAttempts', // Used in recovery/retry execution contexts
|
|
216
|
+
'lastError', // Used in retry execution contexts
|
|
217
|
+
'strategy', // Used in retry execution contexts
|
|
218
|
+
'retryAttempts', // Used in retry execution contexts
|
|
219
|
+
// Validation context fields
|
|
220
|
+
'schemaName', // Used in validation contexts
|
|
221
|
+
// Ticket/build context fields
|
|
222
|
+
'git', // Used in ticket/build context
|
|
223
|
+
'environment', // Used in ticket/build context
|
|
224
|
+
// Search relevance context fields
|
|
225
|
+
'userPreferences', // Used in search relevance context
|
|
226
|
+
'boosts', // Used in search relevance context
|
|
227
|
+
// Fitness check analysis context fields
|
|
228
|
+
'violations', // Used in fitness check analysis contexts
|
|
229
|
+
];
|
|
230
|
+
/**
|
|
231
|
+
* Safe context prefixes that indicate non-request context objects.
|
|
232
|
+
* These are local/scoped context objects, not shared request contexts.
|
|
233
|
+
*/
|
|
234
|
+
const SAFE_CONTEXT_PREFIXES = [
|
|
235
|
+
'entry.context', // Log entry context (per-entry metadata)
|
|
236
|
+
'logEntry.context', // Log entry context
|
|
237
|
+
'this.context', // Builder pattern on class instances
|
|
238
|
+
'result.context', // Result/response context
|
|
239
|
+
'error.context', // Error context builder
|
|
240
|
+
'config.context', // Configuration context
|
|
241
|
+
'options.context', // Options object context
|
|
242
|
+
'params.context', // Parameters context
|
|
243
|
+
'state.context', // Local state context
|
|
244
|
+
'item.context', // Item/element context
|
|
245
|
+
'record.context', // Record context
|
|
246
|
+
'event.context', // Event context
|
|
247
|
+
];
|
|
248
|
+
/**
|
|
249
|
+
* Checks if a line contains safe mutation patterns.
|
|
250
|
+
* @param line - The line to check
|
|
251
|
+
* @returns True if line contains safe patterns
|
|
252
|
+
*/
|
|
253
|
+
function isSafeMutation(line) {
|
|
254
|
+
logger.debug({
|
|
255
|
+
evt: 'fitness.checks.context_mutation.is_safe_mutation',
|
|
256
|
+
msg: 'Checking if line contains safe mutation patterns',
|
|
257
|
+
});
|
|
258
|
+
// Check for safe keywords
|
|
259
|
+
if (SAFE_KEYWORDS.some((keyword) => line.includes(keyword))) {
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
// Check for safe context prefixes (non-request context objects)
|
|
263
|
+
if (SAFE_CONTEXT_PREFIXES.some((prefix) => line.includes(prefix))) {
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Find a mutation detector that matches the line.
|
|
270
|
+
* @param line - The line to check.
|
|
271
|
+
* @returns The matching detector and whether it's a safe mutation, or null if no match.
|
|
272
|
+
*/
|
|
273
|
+
function findMutationMatch(line) {
|
|
274
|
+
for (const detector of MUTATION_DETECTORS) {
|
|
275
|
+
if (detector.test(line)) {
|
|
276
|
+
return { detector, isSafe: isSafeMutation(line) };
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Check if the mutation is defensive (inside a try block).
|
|
283
|
+
* @param lines - All lines of the file.
|
|
284
|
+
* @param index - Current line index.
|
|
285
|
+
* @returns True if the mutation is in a try block.
|
|
286
|
+
*/
|
|
287
|
+
function isDefensiveMutation(lines, index) {
|
|
288
|
+
if (!Array.isArray(lines)) {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
const contextBefore = lines.slice(Math.max(0, index - 5), index).join('\n');
|
|
292
|
+
return contextBefore.includes('try');
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Pure analysis function. Exported so unit tests can exercise the
|
|
296
|
+
* detection logic without standing up the full Check framework
|
|
297
|
+
* (defineCheck wraps `analyze` into an `execute` closure that requires
|
|
298
|
+
* an ExecutionContext to invoke).
|
|
299
|
+
*/
|
|
300
|
+
export function analyzeContextMutation(content, filePath) {
|
|
301
|
+
logger.debug({
|
|
302
|
+
evt: 'fitness.checks.context_mutation.context_mutation_check_analyze',
|
|
303
|
+
msg: 'Analyzing file for unsafe context mutations',
|
|
304
|
+
});
|
|
305
|
+
const violations = [];
|
|
306
|
+
if (!usesContextPattern(content))
|
|
307
|
+
return violations;
|
|
308
|
+
const locallyDeclared = findLocallyDeclaredNames(content);
|
|
309
|
+
const lines = content.split('\n');
|
|
310
|
+
for (let i = 0; i < lines.length; i++) {
|
|
311
|
+
const line = lines[i];
|
|
312
|
+
if (line === undefined || !line)
|
|
313
|
+
continue;
|
|
314
|
+
if (isCommentLine(line))
|
|
315
|
+
continue;
|
|
316
|
+
const match = findMutationMatch(line);
|
|
317
|
+
if (!match || match.isSafe)
|
|
318
|
+
continue;
|
|
319
|
+
const rootName = match.detector.patternName.split('.')[0];
|
|
320
|
+
if (locallyDeclared.has(rootName))
|
|
321
|
+
continue;
|
|
322
|
+
const isDefensive = isDefensiveMutation(lines, i);
|
|
323
|
+
const lineNumber = i + 1;
|
|
324
|
+
violations.push({
|
|
325
|
+
line: lineNumber,
|
|
326
|
+
column: 0,
|
|
327
|
+
message: 'Mutation of context object may cause side effects',
|
|
328
|
+
severity: isDefensive ? 'warning' : 'error',
|
|
329
|
+
suggestion: 'Create a new context object instead of mutating. Use spread operator: const newCtx = { ...ctx, property: newValue }; or Object.freeze() for immutability.',
|
|
330
|
+
match: match.detector.patternName,
|
|
331
|
+
type: 'context-mutation',
|
|
332
|
+
filePath,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
return violations;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Check: resilience/context-mutation
|
|
339
|
+
*
|
|
340
|
+
* Detects potentially unsafe mutations of request/execution context objects.
|
|
341
|
+
* Context should be immutable to prevent side effects across middleware.
|
|
342
|
+
*/
|
|
343
|
+
export const contextMutationCheck = defineCheck({
|
|
344
|
+
id: 'abed5b29-960b-486f-bb0d-5b9e1744241d',
|
|
345
|
+
slug: 'context-mutation',
|
|
346
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'frontend', 'cli'] },
|
|
347
|
+
contentFilter: 'strip-strings',
|
|
348
|
+
confidence: 'medium',
|
|
349
|
+
description: 'Detect unsafe mutations of request/execution context',
|
|
350
|
+
longDescription: `**Purpose:** Prevents direct mutation of request/execution context objects, which can cause side effects across middleware and handlers.
|
|
351
|
+
|
|
352
|
+
**Detects:**
|
|
353
|
+
- Assignment to context properties: \`ctx.prop =\`, \`context.prop =\`, \`req.context.prop =\`, \`request.context.prop =\` (excluding \`==\`/\`===\` comparisons)
|
|
354
|
+
- \`Object.assign(ctx, ...)\` and \`Object.assign(context, ...)\`
|
|
355
|
+
- Array mutation methods on context objects: \`.push()\`, \`.splice()\`, \`.pop()\`, \`.shift()\`, \`.unshift()\`
|
|
356
|
+
- \`delete ctx.\` / \`delete context.\` expressions
|
|
357
|
+
- Allows safe fields like \`correlationId\`, \`requestId\`, \`logger\`, and non-request context prefixes like \`error.context\`, \`this.context\`
|
|
358
|
+
|
|
359
|
+
**Why it matters:** Mutating shared request context causes unpredictable cross-request data leakage in concurrent server environments.
|
|
360
|
+
|
|
361
|
+
**Scope:** General best practice. Analyzes each file individually via string matching.`,
|
|
362
|
+
tags: ['resilience', 'context', 'immutability'],
|
|
363
|
+
fileTypes: ['ts'],
|
|
364
|
+
analyze(content, filePath) {
|
|
365
|
+
return analyzeContextMutation(content, filePath);
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
//# sourceMappingURL=context-mutation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-mutation.js","sourceRoot":"","sources":["../../../src/checks/resilience/context-mutation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Detached promise detection — flags un-awaited promise-returning
|
|
3
|
+
* calls inside async contexts.
|
|
4
|
+
*
|
|
5
|
+
* The defaults here cover **generic JS/TS sync APIs only** (Array, String,
|
|
6
|
+
* Object, Math, JSON, `console.*`, the Node `*Sync` family, timer
|
|
7
|
+
* scheduling, and EventEmitter). Framework-specific helpers (Fastify
|
|
8
|
+
* decorators, Pyroscope SDK, OTel propagation, DBOS `.init`, Vitest /
|
|
9
|
+
* Drizzle helpers, etc.) belong in a recipe's
|
|
10
|
+
* `checks.config['detached-promises']` block — see
|
|
11
|
+
* {@link DetachedPromisesConfig}. The check reads that block via
|
|
12
|
+
* `getCheckConfig` and merges it into the effective sync-call sets.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Recipe-config shape for the detached-promises check. Each field augments the
|
|
16
|
+
* built-in defaults; nothing here is required. Project-specific helper names
|
|
17
|
+
* (e.g. opensip's `attachDomainContext`, `sendError`) belong in a recipe's
|
|
18
|
+
* `checks.config['detached-promises']` block, not in built-in defaults.
|
|
19
|
+
*/
|
|
20
|
+
export interface DetachedPromisesConfig extends Record<string, unknown> {
|
|
21
|
+
/** Method/function names that are synchronous (no await needed). */
|
|
22
|
+
additionalSyncFunctions?: readonly string[];
|
|
23
|
+
/** Receiver identifiers (the part before the dot) that are synchronous. */
|
|
24
|
+
additionalSyncReceivers?: readonly string[];
|
|
25
|
+
/** Method-name prefixes that mark a call as synchronous (e.g. `'wire'`). */
|
|
26
|
+
additionalSyncPrefixes?: readonly string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Check: resilience/detached-promises
|
|
30
|
+
*
|
|
31
|
+
* Detects promises that are not awaited or handled.
|
|
32
|
+
* Missing await can cause silent failures.
|
|
33
|
+
*
|
|
34
|
+
* Uses AST analysis to:
|
|
35
|
+
* - Only flag calls inside async functions/methods
|
|
36
|
+
* - Skip known synchronous functions (logger.*, ensureCorrelationIdFor, etc.)
|
|
37
|
+
* - Skip fire-and-forget patterns (process.nextTick, setImmediate, etc.)
|
|
38
|
+
*/
|
|
39
|
+
export declare const detachedPromises: import("@opensip-cli/fitness").Check;
|
|
40
|
+
//# sourceMappingURL=detached-promises.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detached-promises.d.ts","sourceRoot":"","sources":["../../../src/checks/resilience/detached-promises.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AAMH;;;;;GAKG;AACH,MAAM,WAAW,sBAAuB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACrE,oEAAoE;IACpE,uBAAuB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,2EAA2E;IAC3E,uBAAuB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,4EAA4E;IAC5E,sBAAsB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAmoBD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,sCA0B3B,CAAC"}
|