@neurcode-ai/cli 0.9.64 → 0.9.65
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 +201 -0
- package/dist/commands/brain.d.ts.map +1 -1
- package/dist/commands/brain.js +273 -0
- package/dist/commands/brain.js.map +1 -1
- package/dist/commands/pilot-report.d.ts +9 -0
- package/dist/commands/pilot-report.d.ts.map +1 -0
- package/dist/commands/pilot-report.js +176 -0
- package/dist/commands/pilot-report.js.map +1 -0
- package/dist/commands/remediate-governance.d.ts +54 -0
- package/dist/commands/remediate-governance.d.ts.map +1 -0
- package/dist/commands/remediate-governance.js +375 -0
- package/dist/commands/remediate-governance.js.map +1 -0
- package/dist/commands/remediate.d.ts.map +1 -1
- package/dist/commands/remediate.js.map +1 -1
- package/dist/commands/replay.d.ts.map +1 -1
- package/dist/commands/replay.js +30 -0
- package/dist/commands/replay.js.map +1 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +307 -24
- package/dist/commands/verify.js.map +1 -1
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +1078 -0
- package/dist/daemon/server.js.map +1 -1
- package/dist/explainability/DeterminismClassifier.d.ts +34 -0
- package/dist/explainability/DeterminismClassifier.d.ts.map +1 -0
- package/dist/explainability/DeterminismClassifier.js +104 -0
- package/dist/explainability/DeterminismClassifier.js.map +1 -0
- package/dist/explainability/ViolationFormatter.d.ts +32 -0
- package/dist/explainability/ViolationFormatter.d.ts.map +1 -0
- package/dist/explainability/ViolationFormatter.js +252 -0
- package/dist/explainability/ViolationFormatter.js.map +1 -0
- package/dist/explainability/index.d.ts +15 -0
- package/dist/explainability/index.d.ts.map +1 -0
- package/dist/explainability/index.js +94 -0
- package/dist/explainability/index.js.map +1 -0
- package/dist/explainability/types.d.ts +37 -0
- package/dist/explainability/types.d.ts.map +1 -0
- package/dist/explainability/types.js +3 -0
- package/dist/explainability/types.js.map +1 -0
- package/dist/governance/canonical-pipeline.d.ts +38 -0
- package/dist/governance/canonical-pipeline.d.ts.map +1 -0
- package/dist/governance/canonical-pipeline.js +448 -0
- package/dist/governance/canonical-pipeline.js.map +1 -0
- package/dist/governance/structural-on-diff.d.ts +13 -0
- package/dist/governance/structural-on-diff.d.ts.map +1 -0
- package/dist/governance/structural-on-diff.js +35 -0
- package/dist/governance/structural-on-diff.js.map +1 -0
- package/dist/governance/structural-policy-merge.d.ts +14 -0
- package/dist/governance/structural-policy-merge.d.ts.map +1 -0
- package/dist/governance/structural-policy-merge.js +25 -0
- package/dist/governance/structural-policy-merge.js.map +1 -0
- package/dist/index.js +71 -0
- package/dist/index.js.map +1 -1
- package/dist/integrations/review-compression/index.d.ts +50 -0
- package/dist/integrations/review-compression/index.d.ts.map +1 -0
- package/dist/integrations/review-compression/index.js +158 -0
- package/dist/integrations/review-compression/index.js.map +1 -0
- package/dist/intent-engine/domain-taxonomy.d.ts +42 -0
- package/dist/intent-engine/domain-taxonomy.d.ts.map +1 -0
- package/dist/intent-engine/domain-taxonomy.js +534 -0
- package/dist/intent-engine/domain-taxonomy.js.map +1 -0
- package/dist/intent-engine/index.d.ts +1 -0
- package/dist/intent-engine/index.d.ts.map +1 -1
- package/dist/intent-engine/index.js +6 -1
- package/dist/intent-engine/index.js.map +1 -1
- package/dist/intent-engine/parser.d.ts.map +1 -1
- package/dist/intent-engine/parser.js +47 -0
- package/dist/intent-engine/parser.js.map +1 -1
- package/dist/intent-engine/semantic-expander.d.ts +104 -0
- package/dist/intent-engine/semantic-expander.d.ts.map +1 -0
- package/dist/intent-engine/semantic-expander.js +480 -0
- package/dist/intent-engine/semantic-expander.js.map +1 -0
- package/dist/patch-engine/patterns.d.ts.map +1 -1
- package/dist/patch-engine/patterns.js +8 -4
- package/dist/patch-engine/patterns.js.map +1 -1
- package/dist/semantic/index.d.ts +14 -0
- package/dist/semantic/index.d.ts.map +1 -0
- package/dist/semantic/index.js +30 -0
- package/dist/semantic/index.js.map +1 -0
- package/dist/semantic/tfidf-engine.d.ts +81 -0
- package/dist/semantic/tfidf-engine.d.ts.map +1 -0
- package/dist/semantic/tfidf-engine.js +278 -0
- package/dist/semantic/tfidf-engine.js.map +1 -0
- package/dist/semantic/vector-store.d.ts +108 -0
- package/dist/semantic/vector-store.d.ts.map +1 -0
- package/dist/semantic/vector-store.js +321 -0
- package/dist/semantic/vector-store.js.map +1 -0
- package/dist/structural-rules/context-severity.d.ts +46 -0
- package/dist/structural-rules/context-severity.d.ts.map +1 -0
- package/dist/structural-rules/context-severity.js +115 -0
- package/dist/structural-rules/context-severity.js.map +1 -0
- package/dist/structural-rules/distributed/DS001-saga-rollback-absence.d.ts +11 -0
- package/dist/structural-rules/distributed/DS001-saga-rollback-absence.d.ts.map +1 -0
- package/dist/structural-rules/distributed/DS001-saga-rollback-absence.js +212 -0
- package/dist/structural-rules/distributed/DS001-saga-rollback-absence.js.map +1 -0
- package/dist/structural-rules/distributed/DS002-missing-correlation-id.d.ts +11 -0
- package/dist/structural-rules/distributed/DS002-missing-correlation-id.d.ts.map +1 -0
- package/dist/structural-rules/distributed/DS002-missing-correlation-id.js +213 -0
- package/dist/structural-rules/distributed/DS002-missing-correlation-id.js.map +1 -0
- package/dist/structural-rules/distributed/index.d.ts +3 -0
- package/dist/structural-rules/distributed/index.d.ts.map +1 -0
- package/dist/structural-rules/distributed/index.js +8 -0
- package/dist/structural-rules/distributed/index.js.map +1 -0
- package/dist/structural-rules/engine.d.ts +25 -0
- package/dist/structural-rules/engine.d.ts.map +1 -0
- package/dist/structural-rules/engine.js +90 -0
- package/dist/structural-rules/engine.js.map +1 -0
- package/dist/structural-rules/index.d.ts +41 -0
- package/dist/structural-rules/index.d.ts.map +1 -0
- package/dist/structural-rules/index.js +141 -0
- package/dist/structural-rules/index.js.map +1 -0
- package/dist/structural-rules/python/PY001-asyncio-task-without-cancel.d.ts +11 -0
- package/dist/structural-rules/python/PY001-asyncio-task-without-cancel.d.ts.map +1 -0
- package/dist/structural-rules/python/PY001-asyncio-task-without-cancel.js +66 -0
- package/dist/structural-rules/python/PY001-asyncio-task-without-cancel.js.map +1 -0
- package/dist/structural-rules/python/PY002-unbounded-dict-singleton.d.ts +11 -0
- package/dist/structural-rules/python/PY002-unbounded-dict-singleton.d.ts.map +1 -0
- package/dist/structural-rules/python/PY002-unbounded-dict-singleton.js +135 -0
- package/dist/structural-rules/python/PY002-unbounded-dict-singleton.js.map +1 -0
- package/dist/structural-rules/python/PY003-broad-except-clause.d.ts +11 -0
- package/dist/structural-rules/python/PY003-broad-except-clause.d.ts.map +1 -0
- package/dist/structural-rules/python/PY003-broad-except-clause.js +86 -0
- package/dist/structural-rules/python/PY003-broad-except-clause.js.map +1 -0
- package/dist/structural-rules/python/PY004-swallowed-async-exception.d.ts +11 -0
- package/dist/structural-rules/python/PY004-swallowed-async-exception.d.ts.map +1 -0
- package/dist/structural-rules/python/PY004-swallowed-async-exception.js +167 -0
- package/dist/structural-rules/python/PY004-swallowed-async-exception.js.map +1 -0
- package/dist/structural-rules/python/PY005-fastapi-without-pydantic.d.ts +11 -0
- package/dist/structural-rules/python/PY005-fastapi-without-pydantic.d.ts.map +1 -0
- package/dist/structural-rules/python/PY005-fastapi-without-pydantic.js +154 -0
- package/dist/structural-rules/python/PY005-fastapi-without-pydantic.js.map +1 -0
- package/dist/structural-rules/python/PY006-blocking-io-in-async.d.ts +11 -0
- package/dist/structural-rules/python/PY006-blocking-io-in-async.d.ts.map +1 -0
- package/dist/structural-rules/python/PY006-blocking-io-in-async.js +130 -0
- package/dist/structural-rules/python/PY006-blocking-io-in-async.js.map +1 -0
- package/dist/structural-rules/python/PY007-sqlalchemy-session-leak.d.ts +11 -0
- package/dist/structural-rules/python/PY007-sqlalchemy-session-leak.d.ts.map +1 -0
- package/dist/structural-rules/python/PY007-sqlalchemy-session-leak.js +93 -0
- package/dist/structural-rules/python/PY007-sqlalchemy-session-leak.js.map +1 -0
- package/dist/structural-rules/python/PY008-celery-task-without-retry.d.ts +11 -0
- package/dist/structural-rules/python/PY008-celery-task-without-retry.d.ts.map +1 -0
- package/dist/structural-rules/python/PY008-celery-task-without-retry.js +154 -0
- package/dist/structural-rules/python/PY008-celery-task-without-retry.js.map +1 -0
- package/dist/structural-rules/python/PY009-unsafe-pickle-deserialization.d.ts +11 -0
- package/dist/structural-rules/python/PY009-unsafe-pickle-deserialization.d.ts.map +1 -0
- package/dist/structural-rules/python/PY009-unsafe-pickle-deserialization.js +133 -0
- package/dist/structural-rules/python/PY009-unsafe-pickle-deserialization.js.map +1 -0
- package/dist/structural-rules/python/PY010-leaked-aiohttp-session.d.ts +11 -0
- package/dist/structural-rules/python/PY010-leaked-aiohttp-session.d.ts.map +1 -0
- package/dist/structural-rules/python/PY010-leaked-aiohttp-session.js +80 -0
- package/dist/structural-rules/python/PY010-leaked-aiohttp-session.js.map +1 -0
- package/dist/structural-rules/rules/SR001-swallowed-async-rejection.d.ts +11 -0
- package/dist/structural-rules/rules/SR001-swallowed-async-rejection.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR001-swallowed-async-rejection.js +145 -0
- package/dist/structural-rules/rules/SR001-swallowed-async-rejection.js.map +1 -0
- package/dist/structural-rules/rules/SR002-unbounded-collection.d.ts +11 -0
- package/dist/structural-rules/rules/SR002-unbounded-collection.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR002-unbounded-collection.js +196 -0
- package/dist/structural-rules/rules/SR002-unbounded-collection.js.map +1 -0
- package/dist/structural-rules/rules/SR003-timer-without-cleanup.d.ts +11 -0
- package/dist/structural-rules/rules/SR003-timer-without-cleanup.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR003-timer-without-cleanup.js +148 -0
- package/dist/structural-rules/rules/SR003-timer-without-cleanup.js.map +1 -0
- package/dist/structural-rules/rules/SR004-request-boundary-no-validation.d.ts +11 -0
- package/dist/structural-rules/rules/SR004-request-boundary-no-validation.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR004-request-boundary-no-validation.js +162 -0
- package/dist/structural-rules/rules/SR004-request-boundary-no-validation.js.map +1 -0
- package/dist/structural-rules/rules/SR005-halfopen-probe-gate.d.ts +11 -0
- package/dist/structural-rules/rules/SR005-halfopen-probe-gate.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR005-halfopen-probe-gate.js +150 -0
- package/dist/structural-rules/rules/SR005-halfopen-probe-gate.js.map +1 -0
- package/dist/structural-rules/rules/SR006-fanout-error-sanitization.d.ts +11 -0
- package/dist/structural-rules/rules/SR006-fanout-error-sanitization.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR006-fanout-error-sanitization.js +161 -0
- package/dist/structural-rules/rules/SR006-fanout-error-sanitization.js.map +1 -0
- package/dist/structural-rules/rules/SR007-cross-request-error.d.ts +11 -0
- package/dist/structural-rules/rules/SR007-cross-request-error.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR007-cross-request-error.js +175 -0
- package/dist/structural-rules/rules/SR007-cross-request-error.js.map +1 -0
- package/dist/structural-rules/rules/SR008-background-task-orphan.d.ts +11 -0
- package/dist/structural-rules/rules/SR008-background-task-orphan.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR008-background-task-orphan.js +176 -0
- package/dist/structural-rules/rules/SR008-background-task-orphan.js.map +1 -0
- package/dist/structural-rules/rules/SR009-missing-retry-backoff.d.ts +11 -0
- package/dist/structural-rules/rules/SR009-missing-retry-backoff.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR009-missing-retry-backoff.js +168 -0
- package/dist/structural-rules/rules/SR009-missing-retry-backoff.js.map +1 -0
- package/dist/structural-rules/rules/SR010-retry-storm.d.ts +11 -0
- package/dist/structural-rules/rules/SR010-retry-storm.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR010-retry-storm.js +181 -0
- package/dist/structural-rules/rules/SR010-retry-storm.js.map +1 -0
- package/dist/structural-rules/rules/SR011-event-listener-leak.d.ts +11 -0
- package/dist/structural-rules/rules/SR011-event-listener-leak.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR011-event-listener-leak.js +208 -0
- package/dist/structural-rules/rules/SR011-event-listener-leak.js.map +1 -0
- package/dist/structural-rules/rules/SR012-promise-race-leak.d.ts +11 -0
- package/dist/structural-rules/rules/SR012-promise-race-leak.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR012-promise-race-leak.js +191 -0
- package/dist/structural-rules/rules/SR012-promise-race-leak.js.map +1 -0
- package/dist/structural-rules/rules/SR013-missing-idempotency-key.d.ts +11 -0
- package/dist/structural-rules/rules/SR013-missing-idempotency-key.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR013-missing-idempotency-key.js +219 -0
- package/dist/structural-rules/rules/SR013-missing-idempotency-key.js.map +1 -0
- package/dist/structural-rules/rules/SR014-mutable-closure-async.d.ts +11 -0
- package/dist/structural-rules/rules/SR014-mutable-closure-async.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR014-mutable-closure-async.js +208 -0
- package/dist/structural-rules/rules/SR014-mutable-closure-async.js.map +1 -0
- package/dist/structural-rules/rules/SR015-dangling-abort-controller.d.ts +11 -0
- package/dist/structural-rules/rules/SR015-dangling-abort-controller.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR015-dangling-abort-controller.js +190 -0
- package/dist/structural-rules/rules/SR015-dangling-abort-controller.js.map +1 -0
- package/dist/structural-rules/rules/SR016-unsafe-json-parse.d.ts +11 -0
- package/dist/structural-rules/rules/SR016-unsafe-json-parse.d.ts.map +1 -0
- package/dist/structural-rules/rules/SR016-unsafe-json-parse.js +187 -0
- package/dist/structural-rules/rules/SR016-unsafe-json-parse.js.map +1 -0
- package/dist/structural-rules/suppressions.d.ts +43 -0
- package/dist/structural-rules/suppressions.d.ts.map +1 -0
- package/dist/structural-rules/suppressions.js +115 -0
- package/dist/structural-rules/suppressions.js.map +1 -0
- package/dist/structural-rules/types.d.ts +43 -0
- package/dist/structural-rules/types.d.ts.map +1 -0
- package/dist/structural-rules/types.js +3 -0
- package/dist/structural-rules/types.js.map +1 -0
- package/dist/utils/brain-cache.d.ts +100 -0
- package/dist/utils/brain-cache.d.ts.map +1 -0
- package/dist/utils/brain-cache.js +346 -0
- package/dist/utils/brain-cache.js.map +1 -0
- package/dist/utils/governance-provenance.d.ts +95 -0
- package/dist/utils/governance-provenance.d.ts.map +1 -0
- package/dist/utils/governance-provenance.js +187 -0
- package/dist/utils/governance-provenance.js.map +1 -0
- package/dist/utils/pilot-metrics.d.ts +46 -0
- package/dist/utils/pilot-metrics.d.ts.map +1 -0
- package/dist/utils/pilot-metrics.js +240 -0
- package/dist/utils/pilot-metrics.js.map +1 -0
- package/dist/utils/replay-runtime.d.ts +34 -0
- package/dist/utils/replay-runtime.d.ts.map +1 -1
- package/dist/utils/replay-runtime.js +207 -0
- package/dist/utils/replay-runtime.js.map +1 -1
- package/dist/workspace/cross-repo-graph.d.ts +111 -0
- package/dist/workspace/cross-repo-graph.d.ts.map +1 -0
- package/dist/workspace/cross-repo-graph.js +450 -0
- package/dist/workspace/cross-repo-graph.js.map +1 -0
- package/dist/workspace/federated-context.d.ts +144 -0
- package/dist/workspace/federated-context.d.ts.map +1 -0
- package/dist/workspace/federated-context.js +347 -0
- package/dist/workspace/federated-context.js.map +1 -0
- package/dist/workspace/index.d.ts +38 -0
- package/dist/workspace/index.d.ts.map +1 -0
- package/dist/workspace/index.js +48 -0
- package/dist/workspace/index.js.map +1 -0
- package/package.json +9 -9
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export { StructuralRuleEngine } from './engine';
|
|
2
|
+
export type { StructuralRule, StructuralViolation, StructuralRuleResult, DeterminismLevel, RuleSeverity, } from './types';
|
|
3
|
+
export { parseSuppressionDirectives, applySuppressions, } from './suppressions';
|
|
4
|
+
export type { SuppressionDirective, SuppressedViolation, } from './suppressions';
|
|
5
|
+
export { classifyFileContext, adjustViolationSeverity, applyContextualSeverity, } from './context-severity';
|
|
6
|
+
export type { SeverityContext, SeverityAdjustment, } from './context-severity';
|
|
7
|
+
export { SR001SwallowedAsyncRejection } from './rules/SR001-swallowed-async-rejection';
|
|
8
|
+
export { SR002UnboundedCollection } from './rules/SR002-unbounded-collection';
|
|
9
|
+
export { SR003TimerWithoutCleanup } from './rules/SR003-timer-without-cleanup';
|
|
10
|
+
export { SR004RequestBoundaryNoValidation } from './rules/SR004-request-boundary-no-validation';
|
|
11
|
+
export { SR005HalfOpenProbeGate } from './rules/SR005-halfopen-probe-gate';
|
|
12
|
+
export { SR006FanoutErrorSanitization } from './rules/SR006-fanout-error-sanitization';
|
|
13
|
+
export { SR007CrossRequestError } from './rules/SR007-cross-request-error';
|
|
14
|
+
export { SR008BackgroundTaskOrphan } from './rules/SR008-background-task-orphan';
|
|
15
|
+
export { SR009MissingRetryBackoff } from './rules/SR009-missing-retry-backoff';
|
|
16
|
+
export { SR010RetryStorm } from './rules/SR010-retry-storm';
|
|
17
|
+
export { PY001AsyncioTaskWithoutCancel } from './python/PY001-asyncio-task-without-cancel';
|
|
18
|
+
export { PY002UnboundedDictSingleton } from './python/PY002-unbounded-dict-singleton';
|
|
19
|
+
export { PY003BroadExceptClause } from './python/PY003-broad-except-clause';
|
|
20
|
+
export { PY004SwallowedAsyncException } from './python/PY004-swallowed-async-exception';
|
|
21
|
+
export { PY005FastAPIWithoutPydantic } from './python/PY005-fastapi-without-pydantic';
|
|
22
|
+
export { PY006BlockingIOInAsync } from './python/PY006-blocking-io-in-async';
|
|
23
|
+
export { PY007SQLAlchemySessionLeak } from './python/PY007-sqlalchemy-session-leak';
|
|
24
|
+
export { PY008CeleryTaskWithoutRetry } from './python/PY008-celery-task-without-retry';
|
|
25
|
+
export { PY009UnsafePickleDeserialization } from './python/PY009-unsafe-pickle-deserialization';
|
|
26
|
+
export { PY010LeakedAiohttpSession } from './python/PY010-leaked-aiohttp-session';
|
|
27
|
+
export { SR011EventListenerLeak } from './rules/SR011-event-listener-leak';
|
|
28
|
+
export { SR012PromiseRaceLeak } from './rules/SR012-promise-race-leak';
|
|
29
|
+
export { SR013MissingIdempotencyKey } from './rules/SR013-missing-idempotency-key';
|
|
30
|
+
export { SR014MutableClosureAsync } from './rules/SR014-mutable-closure-async';
|
|
31
|
+
export { SR015DanglingAbortController } from './rules/SR015-dangling-abort-controller';
|
|
32
|
+
export { SR016UnsafeJSONParse } from './rules/SR016-unsafe-json-parse';
|
|
33
|
+
export { DS001SagaRollbackAbsence } from './distributed/DS001-saga-rollback-absence';
|
|
34
|
+
export { DS002MissingCorrelationId } from './distributed/DS002-missing-correlation-id';
|
|
35
|
+
import { StructuralRuleEngine } from './engine';
|
|
36
|
+
/**
|
|
37
|
+
* Creates and returns a pre-configured StructuralRuleEngine with all rules registered.
|
|
38
|
+
* This is the standard way to get a ready-to-use engine.
|
|
39
|
+
*/
|
|
40
|
+
export declare function createDefaultStructuralRuleEngine(): StructuralRuleEngine;
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/structural-rules/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAChD,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,YAAY,GACb,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,0BAA0B,EAC1B,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,eAAe,EACf,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,gCAAgC,EAAE,MAAM,8CAA8C,CAAC;AAChG,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAG5D,OAAO,EAAE,6BAA6B,EAAE,MAAM,4CAA4C,CAAC;AAC3F,OAAO,EAAE,2BAA2B,EAAE,MAAM,yCAAyC,CAAC;AACtF,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,4BAA4B,EAAE,MAAM,0CAA0C,CAAC;AACxF,OAAO,EAAE,2BAA2B,EAAE,MAAM,yCAAyC,CAAC;AACtF,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,0BAA0B,EAAE,MAAM,wCAAwC,CAAC;AACpF,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,gCAAgC,EAAE,MAAM,8CAA8C,CAAC;AAChG,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;AAGlF,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AACrF,OAAO,EAAE,yBAAyB,EAAE,MAAM,4CAA4C,CAAC;AAEvF,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AA8BhD;;;GAGG;AACH,wBAAgB,iCAAiC,IAAI,oBAAoB,CAiCxE"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DS002MissingCorrelationId = exports.DS001SagaRollbackAbsence = exports.SR016UnsafeJSONParse = exports.SR015DanglingAbortController = exports.SR014MutableClosureAsync = exports.SR013MissingIdempotencyKey = exports.SR012PromiseRaceLeak = exports.SR011EventListenerLeak = exports.PY010LeakedAiohttpSession = exports.PY009UnsafePickleDeserialization = exports.PY008CeleryTaskWithoutRetry = exports.PY007SQLAlchemySessionLeak = exports.PY006BlockingIOInAsync = exports.PY005FastAPIWithoutPydantic = exports.PY004SwallowedAsyncException = exports.PY003BroadExceptClause = exports.PY002UnboundedDictSingleton = exports.PY001AsyncioTaskWithoutCancel = exports.SR010RetryStorm = exports.SR009MissingRetryBackoff = exports.SR008BackgroundTaskOrphan = exports.SR007CrossRequestError = exports.SR006FanoutErrorSanitization = exports.SR005HalfOpenProbeGate = exports.SR004RequestBoundaryNoValidation = exports.SR003TimerWithoutCleanup = exports.SR002UnboundedCollection = exports.SR001SwallowedAsyncRejection = exports.applyContextualSeverity = exports.adjustViolationSeverity = exports.classifyFileContext = exports.applySuppressions = exports.parseSuppressionDirectives = exports.StructuralRuleEngine = void 0;
|
|
4
|
+
exports.createDefaultStructuralRuleEngine = createDefaultStructuralRuleEngine;
|
|
5
|
+
var engine_1 = require("./engine");
|
|
6
|
+
Object.defineProperty(exports, "StructuralRuleEngine", { enumerable: true, get: function () { return engine_1.StructuralRuleEngine; } });
|
|
7
|
+
var suppressions_1 = require("./suppressions");
|
|
8
|
+
Object.defineProperty(exports, "parseSuppressionDirectives", { enumerable: true, get: function () { return suppressions_1.parseSuppressionDirectives; } });
|
|
9
|
+
Object.defineProperty(exports, "applySuppressions", { enumerable: true, get: function () { return suppressions_1.applySuppressions; } });
|
|
10
|
+
var context_severity_1 = require("./context-severity");
|
|
11
|
+
Object.defineProperty(exports, "classifyFileContext", { enumerable: true, get: function () { return context_severity_1.classifyFileContext; } });
|
|
12
|
+
Object.defineProperty(exports, "adjustViolationSeverity", { enumerable: true, get: function () { return context_severity_1.adjustViolationSeverity; } });
|
|
13
|
+
Object.defineProperty(exports, "applyContextualSeverity", { enumerable: true, get: function () { return context_severity_1.applyContextualSeverity; } });
|
|
14
|
+
// TypeScript rules
|
|
15
|
+
var SR001_swallowed_async_rejection_1 = require("./rules/SR001-swallowed-async-rejection");
|
|
16
|
+
Object.defineProperty(exports, "SR001SwallowedAsyncRejection", { enumerable: true, get: function () { return SR001_swallowed_async_rejection_1.SR001SwallowedAsyncRejection; } });
|
|
17
|
+
var SR002_unbounded_collection_1 = require("./rules/SR002-unbounded-collection");
|
|
18
|
+
Object.defineProperty(exports, "SR002UnboundedCollection", { enumerable: true, get: function () { return SR002_unbounded_collection_1.SR002UnboundedCollection; } });
|
|
19
|
+
var SR003_timer_without_cleanup_1 = require("./rules/SR003-timer-without-cleanup");
|
|
20
|
+
Object.defineProperty(exports, "SR003TimerWithoutCleanup", { enumerable: true, get: function () { return SR003_timer_without_cleanup_1.SR003TimerWithoutCleanup; } });
|
|
21
|
+
var SR004_request_boundary_no_validation_1 = require("./rules/SR004-request-boundary-no-validation");
|
|
22
|
+
Object.defineProperty(exports, "SR004RequestBoundaryNoValidation", { enumerable: true, get: function () { return SR004_request_boundary_no_validation_1.SR004RequestBoundaryNoValidation; } });
|
|
23
|
+
var SR005_halfopen_probe_gate_1 = require("./rules/SR005-halfopen-probe-gate");
|
|
24
|
+
Object.defineProperty(exports, "SR005HalfOpenProbeGate", { enumerable: true, get: function () { return SR005_halfopen_probe_gate_1.SR005HalfOpenProbeGate; } });
|
|
25
|
+
var SR006_fanout_error_sanitization_1 = require("./rules/SR006-fanout-error-sanitization");
|
|
26
|
+
Object.defineProperty(exports, "SR006FanoutErrorSanitization", { enumerable: true, get: function () { return SR006_fanout_error_sanitization_1.SR006FanoutErrorSanitization; } });
|
|
27
|
+
var SR007_cross_request_error_1 = require("./rules/SR007-cross-request-error");
|
|
28
|
+
Object.defineProperty(exports, "SR007CrossRequestError", { enumerable: true, get: function () { return SR007_cross_request_error_1.SR007CrossRequestError; } });
|
|
29
|
+
var SR008_background_task_orphan_1 = require("./rules/SR008-background-task-orphan");
|
|
30
|
+
Object.defineProperty(exports, "SR008BackgroundTaskOrphan", { enumerable: true, get: function () { return SR008_background_task_orphan_1.SR008BackgroundTaskOrphan; } });
|
|
31
|
+
var SR009_missing_retry_backoff_1 = require("./rules/SR009-missing-retry-backoff");
|
|
32
|
+
Object.defineProperty(exports, "SR009MissingRetryBackoff", { enumerable: true, get: function () { return SR009_missing_retry_backoff_1.SR009MissingRetryBackoff; } });
|
|
33
|
+
var SR010_retry_storm_1 = require("./rules/SR010-retry-storm");
|
|
34
|
+
Object.defineProperty(exports, "SR010RetryStorm", { enumerable: true, get: function () { return SR010_retry_storm_1.SR010RetryStorm; } });
|
|
35
|
+
// Python rules
|
|
36
|
+
var PY001_asyncio_task_without_cancel_1 = require("./python/PY001-asyncio-task-without-cancel");
|
|
37
|
+
Object.defineProperty(exports, "PY001AsyncioTaskWithoutCancel", { enumerable: true, get: function () { return PY001_asyncio_task_without_cancel_1.PY001AsyncioTaskWithoutCancel; } });
|
|
38
|
+
var PY002_unbounded_dict_singleton_1 = require("./python/PY002-unbounded-dict-singleton");
|
|
39
|
+
Object.defineProperty(exports, "PY002UnboundedDictSingleton", { enumerable: true, get: function () { return PY002_unbounded_dict_singleton_1.PY002UnboundedDictSingleton; } });
|
|
40
|
+
var PY003_broad_except_clause_1 = require("./python/PY003-broad-except-clause");
|
|
41
|
+
Object.defineProperty(exports, "PY003BroadExceptClause", { enumerable: true, get: function () { return PY003_broad_except_clause_1.PY003BroadExceptClause; } });
|
|
42
|
+
var PY004_swallowed_async_exception_1 = require("./python/PY004-swallowed-async-exception");
|
|
43
|
+
Object.defineProperty(exports, "PY004SwallowedAsyncException", { enumerable: true, get: function () { return PY004_swallowed_async_exception_1.PY004SwallowedAsyncException; } });
|
|
44
|
+
var PY005_fastapi_without_pydantic_1 = require("./python/PY005-fastapi-without-pydantic");
|
|
45
|
+
Object.defineProperty(exports, "PY005FastAPIWithoutPydantic", { enumerable: true, get: function () { return PY005_fastapi_without_pydantic_1.PY005FastAPIWithoutPydantic; } });
|
|
46
|
+
var PY006_blocking_io_in_async_1 = require("./python/PY006-blocking-io-in-async");
|
|
47
|
+
Object.defineProperty(exports, "PY006BlockingIOInAsync", { enumerable: true, get: function () { return PY006_blocking_io_in_async_1.PY006BlockingIOInAsync; } });
|
|
48
|
+
var PY007_sqlalchemy_session_leak_1 = require("./python/PY007-sqlalchemy-session-leak");
|
|
49
|
+
Object.defineProperty(exports, "PY007SQLAlchemySessionLeak", { enumerable: true, get: function () { return PY007_sqlalchemy_session_leak_1.PY007SQLAlchemySessionLeak; } });
|
|
50
|
+
var PY008_celery_task_without_retry_1 = require("./python/PY008-celery-task-without-retry");
|
|
51
|
+
Object.defineProperty(exports, "PY008CeleryTaskWithoutRetry", { enumerable: true, get: function () { return PY008_celery_task_without_retry_1.PY008CeleryTaskWithoutRetry; } });
|
|
52
|
+
var PY009_unsafe_pickle_deserialization_1 = require("./python/PY009-unsafe-pickle-deserialization");
|
|
53
|
+
Object.defineProperty(exports, "PY009UnsafePickleDeserialization", { enumerable: true, get: function () { return PY009_unsafe_pickle_deserialization_1.PY009UnsafePickleDeserialization; } });
|
|
54
|
+
var PY010_leaked_aiohttp_session_1 = require("./python/PY010-leaked-aiohttp-session");
|
|
55
|
+
Object.defineProperty(exports, "PY010LeakedAiohttpSession", { enumerable: true, get: function () { return PY010_leaked_aiohttp_session_1.PY010LeakedAiohttpSession; } });
|
|
56
|
+
// TypeScript rules — extended set
|
|
57
|
+
var SR011_event_listener_leak_1 = require("./rules/SR011-event-listener-leak");
|
|
58
|
+
Object.defineProperty(exports, "SR011EventListenerLeak", { enumerable: true, get: function () { return SR011_event_listener_leak_1.SR011EventListenerLeak; } });
|
|
59
|
+
var SR012_promise_race_leak_1 = require("./rules/SR012-promise-race-leak");
|
|
60
|
+
Object.defineProperty(exports, "SR012PromiseRaceLeak", { enumerable: true, get: function () { return SR012_promise_race_leak_1.SR012PromiseRaceLeak; } });
|
|
61
|
+
var SR013_missing_idempotency_key_1 = require("./rules/SR013-missing-idempotency-key");
|
|
62
|
+
Object.defineProperty(exports, "SR013MissingIdempotencyKey", { enumerable: true, get: function () { return SR013_missing_idempotency_key_1.SR013MissingIdempotencyKey; } });
|
|
63
|
+
var SR014_mutable_closure_async_1 = require("./rules/SR014-mutable-closure-async");
|
|
64
|
+
Object.defineProperty(exports, "SR014MutableClosureAsync", { enumerable: true, get: function () { return SR014_mutable_closure_async_1.SR014MutableClosureAsync; } });
|
|
65
|
+
var SR015_dangling_abort_controller_1 = require("./rules/SR015-dangling-abort-controller");
|
|
66
|
+
Object.defineProperty(exports, "SR015DanglingAbortController", { enumerable: true, get: function () { return SR015_dangling_abort_controller_1.SR015DanglingAbortController; } });
|
|
67
|
+
var SR016_unsafe_json_parse_1 = require("./rules/SR016-unsafe-json-parse");
|
|
68
|
+
Object.defineProperty(exports, "SR016UnsafeJSONParse", { enumerable: true, get: function () { return SR016_unsafe_json_parse_1.SR016UnsafeJSONParse; } });
|
|
69
|
+
// Distributed rules
|
|
70
|
+
var DS001_saga_rollback_absence_1 = require("./distributed/DS001-saga-rollback-absence");
|
|
71
|
+
Object.defineProperty(exports, "DS001SagaRollbackAbsence", { enumerable: true, get: function () { return DS001_saga_rollback_absence_1.DS001SagaRollbackAbsence; } });
|
|
72
|
+
var DS002_missing_correlation_id_1 = require("./distributed/DS002-missing-correlation-id");
|
|
73
|
+
Object.defineProperty(exports, "DS002MissingCorrelationId", { enumerable: true, get: function () { return DS002_missing_correlation_id_1.DS002MissingCorrelationId; } });
|
|
74
|
+
const engine_2 = require("./engine");
|
|
75
|
+
const SR001_swallowed_async_rejection_2 = require("./rules/SR001-swallowed-async-rejection");
|
|
76
|
+
const SR002_unbounded_collection_2 = require("./rules/SR002-unbounded-collection");
|
|
77
|
+
const SR003_timer_without_cleanup_2 = require("./rules/SR003-timer-without-cleanup");
|
|
78
|
+
const SR004_request_boundary_no_validation_2 = require("./rules/SR004-request-boundary-no-validation");
|
|
79
|
+
const SR005_halfopen_probe_gate_2 = require("./rules/SR005-halfopen-probe-gate");
|
|
80
|
+
const SR006_fanout_error_sanitization_2 = require("./rules/SR006-fanout-error-sanitization");
|
|
81
|
+
const SR007_cross_request_error_2 = require("./rules/SR007-cross-request-error");
|
|
82
|
+
const SR008_background_task_orphan_2 = require("./rules/SR008-background-task-orphan");
|
|
83
|
+
const SR009_missing_retry_backoff_2 = require("./rules/SR009-missing-retry-backoff");
|
|
84
|
+
const SR010_retry_storm_2 = require("./rules/SR010-retry-storm");
|
|
85
|
+
const PY001_asyncio_task_without_cancel_2 = require("./python/PY001-asyncio-task-without-cancel");
|
|
86
|
+
const PY002_unbounded_dict_singleton_2 = require("./python/PY002-unbounded-dict-singleton");
|
|
87
|
+
const PY003_broad_except_clause_2 = require("./python/PY003-broad-except-clause");
|
|
88
|
+
const PY004_swallowed_async_exception_2 = require("./python/PY004-swallowed-async-exception");
|
|
89
|
+
const PY005_fastapi_without_pydantic_2 = require("./python/PY005-fastapi-without-pydantic");
|
|
90
|
+
const PY006_blocking_io_in_async_2 = require("./python/PY006-blocking-io-in-async");
|
|
91
|
+
const PY007_sqlalchemy_session_leak_2 = require("./python/PY007-sqlalchemy-session-leak");
|
|
92
|
+
const PY008_celery_task_without_retry_2 = require("./python/PY008-celery-task-without-retry");
|
|
93
|
+
const PY009_unsafe_pickle_deserialization_2 = require("./python/PY009-unsafe-pickle-deserialization");
|
|
94
|
+
const PY010_leaked_aiohttp_session_2 = require("./python/PY010-leaked-aiohttp-session");
|
|
95
|
+
const SR011_event_listener_leak_2 = require("./rules/SR011-event-listener-leak");
|
|
96
|
+
const SR012_promise_race_leak_2 = require("./rules/SR012-promise-race-leak");
|
|
97
|
+
const SR013_missing_idempotency_key_2 = require("./rules/SR013-missing-idempotency-key");
|
|
98
|
+
const SR014_mutable_closure_async_2 = require("./rules/SR014-mutable-closure-async");
|
|
99
|
+
const SR015_dangling_abort_controller_2 = require("./rules/SR015-dangling-abort-controller");
|
|
100
|
+
const SR016_unsafe_json_parse_2 = require("./rules/SR016-unsafe-json-parse");
|
|
101
|
+
const DS001_saga_rollback_absence_2 = require("./distributed/DS001-saga-rollback-absence");
|
|
102
|
+
const DS002_missing_correlation_id_2 = require("./distributed/DS002-missing-correlation-id");
|
|
103
|
+
/**
|
|
104
|
+
* Creates and returns a pre-configured StructuralRuleEngine with all rules registered.
|
|
105
|
+
* This is the standard way to get a ready-to-use engine.
|
|
106
|
+
*/
|
|
107
|
+
function createDefaultStructuralRuleEngine() {
|
|
108
|
+
const engine = new engine_2.StructuralRuleEngine();
|
|
109
|
+
engine.registerAll([
|
|
110
|
+
new SR001_swallowed_async_rejection_2.SR001SwallowedAsyncRejection(),
|
|
111
|
+
new SR002_unbounded_collection_2.SR002UnboundedCollection(),
|
|
112
|
+
new SR003_timer_without_cleanup_2.SR003TimerWithoutCleanup(),
|
|
113
|
+
new SR004_request_boundary_no_validation_2.SR004RequestBoundaryNoValidation(),
|
|
114
|
+
new SR005_halfopen_probe_gate_2.SR005HalfOpenProbeGate(),
|
|
115
|
+
new SR006_fanout_error_sanitization_2.SR006FanoutErrorSanitization(),
|
|
116
|
+
new SR007_cross_request_error_2.SR007CrossRequestError(),
|
|
117
|
+
new SR008_background_task_orphan_2.SR008BackgroundTaskOrphan(),
|
|
118
|
+
new SR009_missing_retry_backoff_2.SR009MissingRetryBackoff(),
|
|
119
|
+
new SR010_retry_storm_2.SR010RetryStorm(),
|
|
120
|
+
new PY001_asyncio_task_without_cancel_2.PY001AsyncioTaskWithoutCancel(),
|
|
121
|
+
new PY002_unbounded_dict_singleton_2.PY002UnboundedDictSingleton(),
|
|
122
|
+
new PY003_broad_except_clause_2.PY003BroadExceptClause(),
|
|
123
|
+
new PY004_swallowed_async_exception_2.PY004SwallowedAsyncException(),
|
|
124
|
+
new PY005_fastapi_without_pydantic_2.PY005FastAPIWithoutPydantic(),
|
|
125
|
+
new PY006_blocking_io_in_async_2.PY006BlockingIOInAsync(),
|
|
126
|
+
new PY007_sqlalchemy_session_leak_2.PY007SQLAlchemySessionLeak(),
|
|
127
|
+
new PY008_celery_task_without_retry_2.PY008CeleryTaskWithoutRetry(),
|
|
128
|
+
new PY009_unsafe_pickle_deserialization_2.PY009UnsafePickleDeserialization(),
|
|
129
|
+
new PY010_leaked_aiohttp_session_2.PY010LeakedAiohttpSession(),
|
|
130
|
+
new SR011_event_listener_leak_2.SR011EventListenerLeak(),
|
|
131
|
+
new SR012_promise_race_leak_2.SR012PromiseRaceLeak(),
|
|
132
|
+
new SR013_missing_idempotency_key_2.SR013MissingIdempotencyKey(),
|
|
133
|
+
new SR014_mutable_closure_async_2.SR014MutableClosureAsync(),
|
|
134
|
+
new SR015_dangling_abort_controller_2.SR015DanglingAbortController(),
|
|
135
|
+
new SR016_unsafe_json_parse_2.SR016UnsafeJSONParse(),
|
|
136
|
+
new DS001_saga_rollback_absence_2.DS001SagaRollbackAbsence(),
|
|
137
|
+
new DS002_missing_correlation_id_2.DS002MissingCorrelationId(),
|
|
138
|
+
]);
|
|
139
|
+
return engine;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/structural-rules/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { StructuralRule, StructuralViolation, RuleLanguage } from '../types';
|
|
2
|
+
export declare class PY001AsyncioTaskWithoutCancel implements StructuralRule {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
policyRef: string;
|
|
6
|
+
severity: "ADVISORY";
|
|
7
|
+
languages: RuleLanguage[];
|
|
8
|
+
description: string;
|
|
9
|
+
check(filePath: string, sourceText: string): StructuralViolation[];
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=PY001-asyncio-task-without-cancel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PY001-asyncio-task-without-cancel.d.ts","sourceRoot":"","sources":["../../../src/structural-rules/python/PY001-asyncio-task-without-cancel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAM7E,qBAAa,6BAA8B,YAAW,cAAc;IAClE,EAAE,SAAW;IACb,IAAI,SAA+C;IACnD,SAAS,SAAU;IACnB,QAAQ,EAAG,UAAU,CAAU;IAC/B,SAAS,EAAE,YAAY,EAAE,CAAc;IACvC,WAAW,SACyG;IAEpH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,mBAAmB,EAAE;CAoDnE"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PY001AsyncioTaskWithoutCancel = void 0;
|
|
4
|
+
function getLineNumber(lines, index) {
|
|
5
|
+
return index + 1;
|
|
6
|
+
}
|
|
7
|
+
class PY001AsyncioTaskWithoutCancel {
|
|
8
|
+
id = 'PY001';
|
|
9
|
+
name = 'asyncio.create_task without cancel handle';
|
|
10
|
+
policyRef = 'P015';
|
|
11
|
+
severity = 'ADVISORY';
|
|
12
|
+
languages = ['python'];
|
|
13
|
+
description = 'asyncio.create_task() whose return value is not stored cannot be cancelled, causing orphaned tasks on shutdown.';
|
|
14
|
+
check(filePath, sourceText) {
|
|
15
|
+
try {
|
|
16
|
+
const violations = [];
|
|
17
|
+
const lines = sourceText.split('\n');
|
|
18
|
+
for (let i = 0; i < lines.length; i++) {
|
|
19
|
+
const line = lines[i];
|
|
20
|
+
const trimmed = line.trimStart();
|
|
21
|
+
// Check if line contains asyncio.create_task(
|
|
22
|
+
if (!trimmed.includes('asyncio.create_task('))
|
|
23
|
+
continue;
|
|
24
|
+
// Skip if the line starts with an assignment: varname = asyncio.create_task(
|
|
25
|
+
// or self.xxx = asyncio.create_task(
|
|
26
|
+
if (/^\s*\w[\w.]*\s*=\s*asyncio\.create_task\s*\(/.test(line))
|
|
27
|
+
continue;
|
|
28
|
+
// Also skip augmented assignment
|
|
29
|
+
if (/^\s*\w[\w.]*\s*\+=/.test(line))
|
|
30
|
+
continue;
|
|
31
|
+
// Skip if appended to a list: tasks.append(asyncio.create_task(
|
|
32
|
+
if (/\.append\s*\(\s*asyncio\.create_task\s*\(/.test(line))
|
|
33
|
+
continue;
|
|
34
|
+
// Skip if stored in list literal context: [asyncio.create_task(...)]
|
|
35
|
+
// (heuristic: line contains = [...asyncio)
|
|
36
|
+
if (/=\s*\[.*asyncio\.create_task/.test(line))
|
|
37
|
+
continue;
|
|
38
|
+
const evidence = line.slice(0, 120);
|
|
39
|
+
violations.push({
|
|
40
|
+
ruleId: this.id,
|
|
41
|
+
ruleName: this.name,
|
|
42
|
+
policyRef: this.policyRef,
|
|
43
|
+
severity: this.severity,
|
|
44
|
+
filePath,
|
|
45
|
+
line: getLineNumber(lines, i),
|
|
46
|
+
column: line.indexOf('asyncio.create_task') + 1,
|
|
47
|
+
evidence,
|
|
48
|
+
operationalRisk: 'Tasks whose handles are discarded cannot be awaited or cancelled. ' +
|
|
49
|
+
'On application shutdown, these tasks are abandoned mid-execution, ' +
|
|
50
|
+
'potentially leaving resources locked or writes incomplete.',
|
|
51
|
+
remediation: 'Store the task handle: `task = asyncio.create_task(...)` and cancel it on cleanup: ' +
|
|
52
|
+
'`task.cancel(); await asyncio.gather(task, return_exceptions=True)`.',
|
|
53
|
+
determinism: 'deterministic-structural',
|
|
54
|
+
confidence: 0.80,
|
|
55
|
+
language: 'python',
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return violations;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.PY001AsyncioTaskWithoutCancel = PY001AsyncioTaskWithoutCancel;
|
|
66
|
+
//# sourceMappingURL=PY001-asyncio-task-without-cancel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PY001-asyncio-task-without-cancel.js","sourceRoot":"","sources":["../../../src/structural-rules/python/PY001-asyncio-task-without-cancel.ts"],"names":[],"mappings":";;;AAEA,SAAS,aAAa,CAAC,KAAe,EAAE,KAAa;IACnD,OAAO,KAAK,GAAG,CAAC,CAAC;AACnB,CAAC;AAED,MAAa,6BAA6B;IACxC,EAAE,GAAG,OAAO,CAAC;IACb,IAAI,GAAG,2CAA2C,CAAC;IACnD,SAAS,GAAG,MAAM,CAAC;IACnB,QAAQ,GAAG,UAAmB,CAAC;IAC/B,SAAS,GAAmB,CAAC,QAAQ,CAAC,CAAC;IACvC,WAAW,GACT,iHAAiH,CAAC;IAEpH,KAAK,CAAC,QAAgB,EAAE,UAAkB;QACxC,IAAI,CAAC;YACH,MAAM,UAAU,GAA0B,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAErC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;gBAEjC,8CAA8C;gBAC9C,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC;oBAAE,SAAS;gBAExD,6EAA6E;gBAC7E,qCAAqC;gBACrC,IAAI,8CAA8C,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,SAAS;gBACxE,iCAAiC;gBACjC,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,SAAS;gBAC9C,gEAAgE;gBAChE,IAAI,2CAA2C,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,SAAS;gBACrE,qEAAqE;gBACrE,2CAA2C;gBAC3C,IAAI,8BAA8B,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,SAAS;gBAExD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;gBAEpC,UAAU,CAAC,IAAI,CAAC;oBACd,MAAM,EAAE,IAAI,CAAC,EAAE;oBACf,QAAQ,EAAE,IAAI,CAAC,IAAI;oBACnB,SAAS,EAAE,IAAI,CAAC,SAAS;oBACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,QAAQ;oBACR,IAAI,EAAE,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC;oBAC7B,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,CAAC;oBAC/C,QAAQ;oBACR,eAAe,EACb,oEAAoE;wBACpE,oEAAoE;wBACpE,4DAA4D;oBAC9D,WAAW,EACT,qFAAqF;wBACrF,sEAAsE;oBACxE,WAAW,EAAE,0BAA0B;oBACvC,UAAU,EAAE,IAAI;oBAChB,QAAQ,EAAE,QAAQ;iBACnB,CAAC,CAAC;YACL,CAAC;YAED,OAAO,UAAU,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;CACF;AA7DD,sEA6DC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { StructuralRule, StructuralViolation, RuleLanguage } from '../types';
|
|
2
|
+
export declare class PY002UnboundedDictSingleton implements StructuralRule {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
policyRef: string;
|
|
6
|
+
severity: "ADVISORY";
|
|
7
|
+
languages: RuleLanguage[];
|
|
8
|
+
description: string;
|
|
9
|
+
check(filePath: string, sourceText: string): StructuralViolation[];
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=PY002-unbounded-dict-singleton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PY002-unbounded-dict-singleton.d.ts","sourceRoot":"","sources":["../../../src/structural-rules/python/PY002-unbounded-dict-singleton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAU7E,qBAAa,2BAA4B,YAAW,cAAc;IAChE,EAAE,SAAW;IACb,IAAI,SAA4C;IAChD,SAAS,SAAU;IACnB,QAAQ,EAAG,UAAU,CAAU;IAC/B,SAAS,EAAE,YAAY,EAAE,CAAc;IACvC,WAAW,SAC4G;IAEvH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,mBAAmB,EAAE;CA4GnE"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PY002UnboundedDictSingleton = void 0;
|
|
4
|
+
const CACHE_LIKE_NAMES = /cache|store|pending|registry|pool|map|queue|buffer|index/i;
|
|
5
|
+
// Match self.<name> = {} or self.<name> = [] inside __init__ or class methods
|
|
6
|
+
const SELF_ASSIGN_RE = /^(\s*)self\.(\w+)\s*=\s*(\{\}|\[\])\s*$/;
|
|
7
|
+
// Match class-level dict/list (top-level inside class, indented once)
|
|
8
|
+
const CLASS_FIELD_RE = /^(\s+)(\w+)\s*:\s*(Dict|List|dict|list|Set|set)[\[<]?/;
|
|
9
|
+
class PY002UnboundedDictSingleton {
|
|
10
|
+
id = 'PY002';
|
|
11
|
+
name = 'Unbounded dict/list singleton in class';
|
|
12
|
+
policyRef = 'P016';
|
|
13
|
+
severity = 'ADVISORY';
|
|
14
|
+
languages = ['python'];
|
|
15
|
+
description = 'Class-level dicts or lists used as caches/registries with cache-like names but no maxsize or TTL grow unboundedly.';
|
|
16
|
+
check(filePath, sourceText) {
|
|
17
|
+
try {
|
|
18
|
+
const violations = [];
|
|
19
|
+
const lines = sourceText.split('\n');
|
|
20
|
+
// Track if we're inside a class
|
|
21
|
+
let insideClass = false;
|
|
22
|
+
let classIndent = '';
|
|
23
|
+
let insideInit = false;
|
|
24
|
+
let initIndent = '';
|
|
25
|
+
for (let i = 0; i < lines.length; i++) {
|
|
26
|
+
const line = lines[i];
|
|
27
|
+
const trimmed = line.trimStart();
|
|
28
|
+
// Detect class definition
|
|
29
|
+
if (/^class\s+\w+/.test(trimmed)) {
|
|
30
|
+
insideClass = true;
|
|
31
|
+
classIndent = line.match(/^(\s*)/)?.[1] ?? '';
|
|
32
|
+
insideInit = false;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (!insideClass)
|
|
36
|
+
continue;
|
|
37
|
+
// Detect __init__ method
|
|
38
|
+
if (/def\s+__init__\s*\(/.test(trimmed)) {
|
|
39
|
+
insideInit = true;
|
|
40
|
+
initIndent = line.match(/^(\s*)/)?.[1] ?? '';
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
// Track leaving __init__: next def at same indent level
|
|
44
|
+
if (insideInit &&
|
|
45
|
+
/^\s+def\s+\w+/.test(line) &&
|
|
46
|
+
!line.startsWith(initIndent + ' ')) {
|
|
47
|
+
insideInit = false;
|
|
48
|
+
}
|
|
49
|
+
// Check self.xxx = {} or self.xxx = [] inside __init__
|
|
50
|
+
const selfMatch = SELF_ASSIGN_RE.exec(line);
|
|
51
|
+
if (selfMatch && insideInit) {
|
|
52
|
+
const fieldName = selfMatch[2];
|
|
53
|
+
if (CACHE_LIKE_NAMES.test(fieldName)) {
|
|
54
|
+
// Check if there's any maxsize/TTL reference in the whole class source
|
|
55
|
+
const evidence = line.slice(0, 120);
|
|
56
|
+
if (!hasBoundIndicator(sourceText, fieldName)) {
|
|
57
|
+
violations.push({
|
|
58
|
+
ruleId: this.id,
|
|
59
|
+
ruleName: this.name,
|
|
60
|
+
policyRef: this.policyRef,
|
|
61
|
+
severity: this.severity,
|
|
62
|
+
filePath,
|
|
63
|
+
line: i + 1,
|
|
64
|
+
column: line.indexOf('self.') + 1,
|
|
65
|
+
evidence,
|
|
66
|
+
operationalRisk: 'Instance-level cache/registry with no size bound grows indefinitely under load. ' +
|
|
67
|
+
'Long-running services accumulate entries without eviction, causing OOM.',
|
|
68
|
+
remediation: 'Replace with `functools.lru_cache`, `cachetools.TTLCache(maxsize=1000, ttl=300)`, ' +
|
|
69
|
+
'or add explicit eviction logic with a max size check before each insert.',
|
|
70
|
+
determinism: 'heuristic-advisory',
|
|
71
|
+
confidence: 0.75,
|
|
72
|
+
language: 'python',
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Also check class-level type-annotated fields (outside __init__)
|
|
78
|
+
const classFieldMatch = CLASS_FIELD_RE.exec(line);
|
|
79
|
+
if (classFieldMatch && !insideInit) {
|
|
80
|
+
const fieldName = classFieldMatch[2];
|
|
81
|
+
if (CACHE_LIKE_NAMES.test(fieldName)) {
|
|
82
|
+
const evidence = line.slice(0, 120);
|
|
83
|
+
if (!hasBoundIndicator(sourceText, fieldName)) {
|
|
84
|
+
violations.push({
|
|
85
|
+
ruleId: this.id,
|
|
86
|
+
ruleName: this.name,
|
|
87
|
+
policyRef: this.policyRef,
|
|
88
|
+
severity: this.severity,
|
|
89
|
+
filePath,
|
|
90
|
+
line: i + 1,
|
|
91
|
+
column: (line.match(/^(\s*)/)?.[1].length ?? 0) + 1,
|
|
92
|
+
evidence,
|
|
93
|
+
operationalRisk: 'Class-level collection with a cache-like name has no visible size bound or TTL. ' +
|
|
94
|
+
'Unbounded growth causes OOM in long-running services.',
|
|
95
|
+
remediation: 'Add maxsize enforcement or replace with `cachetools.TTLCache` / `lru_cache`. ' +
|
|
96
|
+
'Document the intended bound with a comment.',
|
|
97
|
+
determinism: 'heuristic-advisory',
|
|
98
|
+
confidence: 0.75,
|
|
99
|
+
language: 'python',
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return violations;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
exports.PY002UnboundedDictSingleton = PY002UnboundedDictSingleton;
|
|
113
|
+
function hasBoundIndicator(sourceText, fieldName) {
|
|
114
|
+
const indicators = [
|
|
115
|
+
/maxsize/i,
|
|
116
|
+
/max_size/i,
|
|
117
|
+
/\bttl\b/i,
|
|
118
|
+
/lru_cache/i,
|
|
119
|
+
/TTLCache/i,
|
|
120
|
+
/LRUCache/i,
|
|
121
|
+
/bounded/i,
|
|
122
|
+
/evict/i,
|
|
123
|
+
/capacity/i,
|
|
124
|
+
];
|
|
125
|
+
// Check near the field name or anywhere in the file
|
|
126
|
+
const fieldPattern = new RegExp(`${fieldName}.*(?:maxsize|max_size|ttl|lru|evict|capacity)`, 'i');
|
|
127
|
+
if (fieldPattern.test(sourceText))
|
|
128
|
+
return true;
|
|
129
|
+
// Or if the file imports cachetools
|
|
130
|
+
if (/\bcachetools\b/.test(sourceText))
|
|
131
|
+
return true;
|
|
132
|
+
// Check for general indicators nearby
|
|
133
|
+
return indicators.some(p => p.test(sourceText));
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=PY002-unbounded-dict-singleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PY002-unbounded-dict-singleton.js","sourceRoot":"","sources":["../../../src/structural-rules/python/PY002-unbounded-dict-singleton.ts"],"names":[],"mappings":";;;AAEA,MAAM,gBAAgB,GAAG,2DAA2D,CAAC;AAErF,8EAA8E;AAC9E,MAAM,cAAc,GAAG,yCAAyC,CAAC;AAEjE,sEAAsE;AACtE,MAAM,cAAc,GAAG,uDAAuD,CAAC;AAE/E,MAAa,2BAA2B;IACtC,EAAE,GAAG,OAAO,CAAC;IACb,IAAI,GAAG,wCAAwC,CAAC;IAChD,SAAS,GAAG,MAAM,CAAC;IACnB,QAAQ,GAAG,UAAmB,CAAC;IAC/B,SAAS,GAAmB,CAAC,QAAQ,CAAC,CAAC;IACvC,WAAW,GACT,oHAAoH,CAAC;IAEvH,KAAK,CAAC,QAAgB,EAAE,UAAkB;QACxC,IAAI,CAAC;YACH,MAAM,UAAU,GAA0B,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAErC,gCAAgC;YAChC,IAAI,WAAW,GAAG,KAAK,CAAC;YACxB,IAAI,WAAW,GAAG,EAAE,CAAC;YACrB,IAAI,UAAU,GAAG,KAAK,CAAC;YACvB,IAAI,UAAU,GAAG,EAAE,CAAC;YAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;gBAEjC,0BAA0B;gBAC1B,IAAI,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;oBACjC,WAAW,GAAG,IAAI,CAAC;oBACnB,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;oBAC9C,UAAU,GAAG,KAAK,CAAC;oBACnB,SAAS;gBACX,CAAC;gBAED,IAAI,CAAC,WAAW;oBAAE,SAAS;gBAE3B,yBAAyB;gBACzB,IAAI,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;oBACxC,UAAU,GAAG,IAAI,CAAC;oBAClB,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;oBAC7C,SAAS;gBACX,CAAC;gBAED,wDAAwD;gBACxD,IACE,UAAU;oBACV,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC1B,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,GAAG,MAAM,CAAC,EACrC,CAAC;oBACD,UAAU,GAAG,KAAK,CAAC;gBACrB,CAAC;gBAED,uDAAuD;gBACvD,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC5C,IAAI,SAAS,IAAI,UAAU,EAAE,CAAC;oBAC5B,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;oBAC/B,IAAI,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;wBACrC,uEAAuE;wBACvE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;wBACpC,IAAI,CAAC,iBAAiB,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,CAAC;4BAC9C,UAAU,CAAC,IAAI,CAAC;gCACd,MAAM,EAAE,IAAI,CAAC,EAAE;gCACf,QAAQ,EAAE,IAAI,CAAC,IAAI;gCACnB,SAAS,EAAE,IAAI,CAAC,SAAS;gCACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gCACvB,QAAQ;gCACR,IAAI,EAAE,CAAC,GAAG,CAAC;gCACX,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;gCACjC,QAAQ;gCACR,eAAe,EACb,kFAAkF;oCAClF,yEAAyE;gCAC3E,WAAW,EACT,oFAAoF;oCACpF,0EAA0E;gCAC5E,WAAW,EAAE,oBAAoB;gCACjC,UAAU,EAAE,IAAI;gCAChB,QAAQ,EAAE,QAAQ;6BACnB,CAAC,CAAC;wBACL,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,kEAAkE;gBAClE,MAAM,eAAe,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClD,IAAI,eAAe,IAAI,CAAC,UAAU,EAAE,CAAC;oBACnC,MAAM,SAAS,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;oBACrC,IAAI,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;wBACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;wBACpC,IAAI,CAAC,iBAAiB,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,CAAC;4BAC9C,UAAU,CAAC,IAAI,CAAC;gCACd,MAAM,EAAE,IAAI,CAAC,EAAE;gCACf,QAAQ,EAAE,IAAI,CAAC,IAAI;gCACnB,SAAS,EAAE,IAAI,CAAC,SAAS;gCACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gCACvB,QAAQ;gCACR,IAAI,EAAE,CAAC,GAAG,CAAC;gCACX,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC;gCACnD,QAAQ;gCACR,eAAe,EACb,kFAAkF;oCAClF,uDAAuD;gCACzD,WAAW,EACT,+EAA+E;oCAC/E,6CAA6C;gCAC/C,WAAW,EAAE,oBAAoB;gCACjC,UAAU,EAAE,IAAI;gCAChB,QAAQ,EAAE,QAAQ;6BACnB,CAAC,CAAC;wBACL,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAED,OAAO,UAAU,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;CACF;AArHD,kEAqHC;AAED,SAAS,iBAAiB,CAAC,UAAkB,EAAE,SAAiB;IAC9D,MAAM,UAAU,GAAG;QACjB,UAAU;QACV,WAAW;QACX,UAAU;QACV,YAAY;QACZ,WAAW;QACX,WAAW;QACX,UAAU;QACV,QAAQ;QACR,WAAW;KACZ,CAAC;IACF,oDAAoD;IACpD,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,GAAG,SAAS,+CAA+C,EAAE,GAAG,CAAC,CAAC;IAClG,IAAI,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,oCAAoC;IACpC,IAAI,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IACnD,sCAAsC;IACtC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { StructuralRule, StructuralViolation, RuleLanguage } from '../types';
|
|
2
|
+
export declare class PY003BroadExceptClause implements StructuralRule {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
policyRef: string;
|
|
6
|
+
severity: "BLOCKING";
|
|
7
|
+
languages: RuleLanguage[];
|
|
8
|
+
description: string;
|
|
9
|
+
check(filePath: string, sourceText: string): StructuralViolation[];
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=PY003-broad-except-clause.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PY003-broad-except-clause.d.ts","sourceRoot":"","sources":["../../../src/structural-rules/python/PY003-broad-except-clause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAQ7E,qBAAa,sBAAuB,YAAW,cAAc;IAC3D,EAAE,SAAW;IACb,IAAI,SAA2C;IAC/C,SAAS,SAAU;IACnB,QAAQ,EAAG,UAAU,CAAU;IAC/B,SAAS,EAAE,YAAY,EAAE,CAAc;IACvC,WAAW,SACyG;IAEpH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,mBAAmB,EAAE;CA8EnE"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PY003BroadExceptClause = void 0;
|
|
4
|
+
// Matches: except Exception: or except Exception as e:
|
|
5
|
+
const BROAD_EXCEPT_RE = /^(\s*)except\s+Exception(\s+as\s+\w+)?\s*:/;
|
|
6
|
+
// Logging/reporting call patterns
|
|
7
|
+
const LOGGING_RE = /\b(?:log|logger|logging|error|warn|warning|report|track|capture|sentry|bugsnag|rollbar|print)\s*[\.(]/i;
|
|
8
|
+
class PY003BroadExceptClause {
|
|
9
|
+
id = 'PY003';
|
|
10
|
+
name = 'Broad except clause swallowing errors';
|
|
11
|
+
policyRef = 'P017';
|
|
12
|
+
severity = 'BLOCKING';
|
|
13
|
+
languages = ['python'];
|
|
14
|
+
description = 'except Exception: blocks that neither re-raise nor log silently swallow all exceptions including system errors.';
|
|
15
|
+
check(filePath, sourceText) {
|
|
16
|
+
try {
|
|
17
|
+
const violations = [];
|
|
18
|
+
const lines = sourceText.split('\n');
|
|
19
|
+
for (let i = 0; i < lines.length; i++) {
|
|
20
|
+
const line = lines[i];
|
|
21
|
+
const match = BROAD_EXCEPT_RE.exec(line);
|
|
22
|
+
if (!match)
|
|
23
|
+
continue;
|
|
24
|
+
const exceptIndent = match[1].length;
|
|
25
|
+
// Collect the except block body (lines more indented than the except statement)
|
|
26
|
+
const bodyLines = [];
|
|
27
|
+
let j = i + 1;
|
|
28
|
+
while (j < lines.length) {
|
|
29
|
+
const bodyLine = lines[j];
|
|
30
|
+
const bodyTrimmed = bodyLine.trimStart();
|
|
31
|
+
// Empty line — continue collecting
|
|
32
|
+
if (bodyTrimmed.length === 0) {
|
|
33
|
+
j++;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const bodyIndent = bodyLine.length - bodyLine.trimStart().length;
|
|
37
|
+
// If indent is less than or equal to the except indent, block ended
|
|
38
|
+
if (bodyIndent <= exceptIndent)
|
|
39
|
+
break;
|
|
40
|
+
bodyLines.push(bodyLine);
|
|
41
|
+
j++;
|
|
42
|
+
}
|
|
43
|
+
if (bodyLines.length === 0)
|
|
44
|
+
continue;
|
|
45
|
+
const bodyText = bodyLines.join('\n');
|
|
46
|
+
// Check for re-raise
|
|
47
|
+
const hasReraise = /^\s*raise\b/.test(bodyText) || /\braise\b/.test(bodyText);
|
|
48
|
+
if (hasReraise)
|
|
49
|
+
continue;
|
|
50
|
+
// Check for logging
|
|
51
|
+
if (LOGGING_RE.test(bodyText))
|
|
52
|
+
continue;
|
|
53
|
+
// Skip if body only contains pass
|
|
54
|
+
const nonEmpty = bodyLines
|
|
55
|
+
.map(l => l.trim())
|
|
56
|
+
.filter(l => l.length > 0 && l !== 'pass' && !l.startsWith('#'));
|
|
57
|
+
// If the body is just `pass` or empty meaningful statements, it's swallowing
|
|
58
|
+
// If it has actual work (return something, set variable), still flag it
|
|
59
|
+
const evidence = line.slice(0, 120);
|
|
60
|
+
violations.push({
|
|
61
|
+
ruleId: this.id,
|
|
62
|
+
ruleName: this.name,
|
|
63
|
+
policyRef: this.policyRef,
|
|
64
|
+
severity: this.severity,
|
|
65
|
+
filePath,
|
|
66
|
+
line: i + 1,
|
|
67
|
+
column: exceptIndent + 1,
|
|
68
|
+
evidence,
|
|
69
|
+
operationalRisk: 'Catches ALL exceptions (including SystemExit, KeyboardInterrupt, MemoryError) without ' +
|
|
70
|
+
'logging or re-raising. Silent failures make debugging impossible and hide operational issues.',
|
|
71
|
+
remediation: 'Either re-raise after handling: `except Exception as e: logger.error(e); raise` ' +
|
|
72
|
+
'or narrow the exception type. Avoid bare `except Exception` without at minimum logging.',
|
|
73
|
+
determinism: 'deterministic-structural',
|
|
74
|
+
confidence: nonEmpty.length === 0 ? 0.95 : 0.85,
|
|
75
|
+
language: 'python',
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return violations;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.PY003BroadExceptClause = PY003BroadExceptClause;
|
|
86
|
+
//# sourceMappingURL=PY003-broad-except-clause.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PY003-broad-except-clause.js","sourceRoot":"","sources":["../../../src/structural-rules/python/PY003-broad-except-clause.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { StructuralRule, StructuralViolation, RuleLanguage } from '../types';
|
|
2
|
+
export declare class PY004SwallowedAsyncException implements StructuralRule {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
policyRef: string;
|
|
6
|
+
severity: "ADVISORY";
|
|
7
|
+
languages: RuleLanguage[];
|
|
8
|
+
description: string;
|
|
9
|
+
check(filePath: string, sourceText: string): StructuralViolation[];
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=PY004-swallowed-async-exception.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PY004-swallowed-async-exception.d.ts","sourceRoot":"","sources":["../../../src/structural-rules/python/PY004-swallowed-async-exception.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAc7E,qBAAa,4BAA6B,YAAW,cAAc;IACjE,EAAE,SAAW;IACb,IAAI,SAAiC;IACrC,SAAS,SAAU;IACnB,QAAQ,EAAG,UAAU,CAAU;IAC/B,SAAS,EAAE,YAAY,EAAE,CAAc;IACvC,WAAW,SAEsE;IAEjF,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,mBAAmB,EAAE;CAkJnE"}
|