Rulepath is Rust-native because static analysis benefits from predictable memory use, parallelism, single-binary distribution, and strong data modeling.
Normal scans should not require:
- Python interpreter.
- Node runtime.
- TypeScript compiler process.
- Docker.
- Network access.
Optional deep-analysis modes may use sidecars later, but those modes must be explicit.
Dependency resolution must be reproducible. Direct Cargo dependencies use exact version requirements, Cargo.lock stores registry checksums, CI runs with --locked, GitHub Actions are pinned to full commit SHAs, and the Rust toolchain is pinned by rust-toolchain.toml.
Prefer compact IDs internally:
FileIdSymbolIdRouteIdSinkIdSourceIdEvidenceId
Keep spans as file IDs plus byte offsets where practical. Convert to line and column for reports.
Safe parallel points include file parsing, fact extraction, data-layer extraction, rule evaluation over independent traces, and report formatting. Final output must remain deterministic.
Fatal errors include config load failures, schema violations, invalid baselines, and output write failures.
Non-fatal diagnostics include parse errors in individual files, unresolved relative imports, unsupported syntax, skipped non-UTF8 source files, and ambiguous resource inference. These diagnostics are carried separately from findings and review hints so analyzer health warnings do not become policy violations.
Uncertainty should reduce confidence or produce review hints.
The current analyzer builds a conservative trace index from parser-backed symbols and calls. Framework and data-layer adapters consume those parsed facts through deterministic registries, then dataflow connects route request sources to operations when parsed calls cross from route handlers into service functions.
Next.js extraction covers App Router handlers in app/api/**/route.{ts,tsx,js,jsx} and practical Pages Router API handlers in pages/api/**. Dynamic segments such as [invoiceId], [...slug], and [[...slug]] normalize to route parameter sources, while request body sources use the request.json() model for downstream Prisma findings.
Django extraction covers practical urls.py calls to path, re_path, and url, normalizing converter syntax such as <uuid:invoice_id> into common route parameter sources. Django REST Framework extraction covers APIView, ViewSet, ModelViewSet, common action method names, @action methods, router registrations, request body/query/path sources, and permission_classes evidence without requiring a Python runtime.
Prisma extraction is parser-call backed and recognizes configured client aliases, supported CRUD and bulk methods, nested where filters, and data mutation payloads while ignoring projection-only select and include arguments.
SQLAlchemy extraction is parser-call backed for session.get, select, update, delete, and session.execute(...) wrappers. Object assignment followed by session.commit() is modeled as a mutation so request-body field flows are visible to rules.
Django ORM extraction is parser-call backed for model manager calls such as Model.objects.get/filter/create, queryset update and delete chains, and common serializer save() patterns. Tenant fields from resolved config count as scope filters, while request.data, serializer input, kwargs, and path/query parameters are normalized as request-controlled sources.
Auth, authorization, scope, transaction, invariant, and idempotency evidence is normalized in rulepath_auth. Evidence classification is driven by resolved config where possible, with route middleware/dependencies and direct helper calls associated back to the nearest route or sink during IR assembly.
The trace remains intentionally narrow and fixture-backed, but it is import- and symbol-aware for simple local and relative imports. Route-to-service tracing respects analysis.service_layer_tracing and analysis.max_call_depth; unresolved or ambiguous paths should stay out of high-confidence findings rather than inheriting the first available route.