fix/audit-findings #5

Merged
trevon merged 14 commits from fix/audit-findings into main 2026-09-25 02:39:30 +00:00
2 changed files with 41 additions and 15 deletions
Showing only changes of commit 46698cd87d - Show all commits

docs: state resolution rules and limits as the code now implements them
Some checks failed
build / build-linux (pull_request) Successful in 1m3s
build / build-macos (pull_request) Has been cancelled
build / release (pull_request) Has been cancelled

The audit found README claims the code did not back: resolution was said
to respect lexical namespace everywhere (Python/Swift matched a
repo-wide unique name, Rust types their leaf name), "ambiguous targets
stay external" (not for rival using-directives or #else stubs), Dart
imports were said to resolve (no Dart symbol ever did across files), and
"C/C++" hid that C went through the C++ grammar.

The README now describes the fixed behaviour and its remaining limits:
per-language visibility rules (Python imports, Swift module-wide names,
Dart imported libraries without show/hide), Rust type identity by
declaring file, preprocessor alternatives excluded from resolution,
using-directive ambiguity, the C grammar for .c, Fold report
validation and producer-gated symbolic lane, lossy UTF-8 decoding,
diagnostic counts and empty-scan reporting, check recomputing metrics,
low call-site coverage on large C++ code, no virtual-override fan-out,
and unrecognized Catch2 TEST_CASE bodies. The research note lists the
pinned C grammar.
trvon 2026-09-24 20:21:29 -06:00
Signed by: trevon
GPG key ID: 38686EA797D7A8A7

View file

@ -6,8 +6,8 @@ elements, and dependency edges show calls, imports, and inheritance. The same
model is emitted as versioned JSON for other tools, including a future Fold model is emitted as versioned JSON for other tools, including a future Fold
integration. integration.
The default extractor uses pinned Tree-sitter grammars for Rust, Dart, C/C++, The default extractor uses pinned Tree-sitter grammars for Rust, Dart, C
JavaScript/JSX, and TypeScript/TSX. Python and Swift retain the lexical preview; (`.c`), C++ (including headers), JavaScript/JSX, and TypeScript/TSX. Python and Swift retain the lexical preview;
P4_16 retains its separate lexical and optional pilot paths. Declarations are P4_16 retains its separate lexical and optional pilot paths. Declarations are
Syntactic evidence. Calls, imports, and inheritance retain Heuristic target Syntactic evidence. Calls, imports, and inheritance retain Heuristic target
resolution with backend, confidence, and source location, independently of resolution with backend, confidence, and source location, independently of
@ -32,8 +32,16 @@ Layer Fold findings onto the building:
--json fold.brick.json \ --json fold.brick.json \
--html fold.brick.html --html fold.brick.html
A report must be a SARIF log or a Fold findings report; anything else is an
error. Findings keep Fold's symbolic lane only when the report names Fold as its
producer (`tool.name` / `tool.driver.name`); other producers' findings are
imported, never symbolic. Findings without a file location are diagnosed, and
SARIF `file://` URIs are decoded before matching.
Fold artifact paths are normalized lexically across `/`, `\\`, `.`, and `..` Fold artifact paths are normalized lexically across `/`, `\\`, `.`, and `..`
components before exact repository-relative matching. Absolute paths are components before exact repository-relative matching; a path with `..` that
exists in this checkout follows the filesystem instead, so `link/..` resolves
through the symlink. Absolute paths are
accepted only beneath the model's scan root (including existing filesystem accepted only beneath the model's scan root (including existing filesystem
aliases whose canonical targets are beneath that root); leading traversal and unrelated aliases whose canonical targets are beneath that root); leading traversal and unrelated
suffix paths remain diagnostics. Findings for excluded, generated, or genuinely suffix paths remain diagnostics. Findings for excluded, generated, or genuinely
@ -152,26 +160,43 @@ Brick extracts syntax, without compiler type checking or build configuration.
Macro expansion, overload resolution, dynamic dispatch, generated code, and Macro expansion, overload resolution, dynamic dispatch, generated code, and
full package/build-system resolution remain outside the default frontend. full package/build-system resolution remain outside the default frontend.
Malformed syntax produces diagnostics; recoverable sibling facts remain visible. Malformed syntax produces diagnostics; recoverable sibling facts remain visible.
A file with invalid UTF-8 is decoded lossily with a diagnostic; files with NUL
bytes are skipped as binary. `build` prints diagnostic counts, and a scan that
finds no supported source says so. `check` recomputes metrics from the graph
(stored metrics are never trusted) and fails a model with no scanned source.
Its score is not proof of correctness, maintainability, Its score is not proof of correctness, maintainability,
or security. Use the component metrics and evidence records; do not rank teams or security. Use the component metrics and evidence records; do not rank teams
or repositories by the composite alone. or repositories by the composite alone.
Resolution respects language, file, declaration ownership, and lexical namespace. Grammar-based resolution respects language, file, declaration ownership, and
Relative JS/TS and Dart imports resolve against the importing directory; missing lexical namespace. Relative JS/TS and Dart imports resolve against the importing
paths never fall back to unrelated basenames. Explicit JS/TS named/default import directory (Dart `package:<own package>/` against `lib/`); missing paths never
bindings, module-scoped Rust grouped/aliased imports, and module-qualified Rust fall back to unrelated basenames. Explicit JS/TS named/default import bindings,
public calls can resolve across files. module-scoped Rust grouped/aliased imports, module-qualified Rust public calls,
and public top-level Dart names from imported libraries can resolve across files
(Dart `show`/`hide` combinators are not modelled). The lexical preview resolves
Python names in the calling file, then in files it imports; Swift names in the
calling file, then by a module-wide unique name (Swift files of one module see
each other without imports).
C++ calls resolve through the include closure: a header prototype pairs with C++ calls resolve through the include closure: a header prototype pairs with
its definition in another translation unit, lookup walks class (including its definition in another translation unit, lookup walks class (including
in-repository bases) and namespace scopes outward, and `static`/anonymous in-repository bases) and namespace scopes outward, and `static`/anonymous
definitions stay file-local. C++ and Rust member calls resolve only through an definitions stay file-local. Declarations in `#elif`/`#else` branches stay in
explicitly declared receiver type (parameter, local, field, `this`/`self`, the graph (`source.preprocessor-branch: alternative`) but are never call
smart pointer, or `Self`-returning constructor) and carry targets, because Brick does not evaluate conditions; several `using`
`source.resolution`. Calls inside Rust expression macros (`assert!`, `format!`, directives that nominate different declarations make a call ambiguous. C++ and
Rust member calls resolve only through an explicitly declared receiver type
(parameter, local, field, `this`/`self`, smart pointer, or `Self`-returning
constructor) and carry `source.resolution`. Rust types are identified by their
declaring file, so same-named types in different modules resolve through the
caller's `use` binding or stay ambiguous. Calls inside Rust expression macros (`assert!`, `format!`,
`vec!`, ...) are recovered by re-parsing and carry `source.extraction`. `vec!`, ...) are recovered by re-parsing and carry `source.extraction`.
Every unresolved call edge records `source.unresolved-reason`, and Every unresolved call edge records `source.unresolved-reason`, and
`metrics.resolution` reports per-language call-site coverage. Ambiguous `metrics.resolution` reports per-language call-site coverage; read the graph
targets stay external. Bare package specifiers, tsconfig aliases, Rust with that coverage in mind (on a large C++ repository only a minority of call
sites resolve). Ambiguous targets stay external. Virtual calls resolve to the
declared type's method only (overrides are not fanned out), and Catch2
`TEST_CASE` bodies are not yet recognized as functions. Bare package specifiers, tsconfig aliases, Rust
wildcard/block-local binding expansion, Cargo workspace module paths, wildcard/block-local binding expansion, Cargo workspace module paths,
`compile_commands.json` include paths, and compiler-grade dispatch need further `compile_commands.json` include paths, and compiler-grade dispatch need further
adapters. File fan-out remains an observation rather adapters. File fan-out remains an observation rather

View file

@ -42,7 +42,8 @@ change cycle, isolation, and fan metrics; no health weights are changed.
| Rust const/impl | Const function, distinct type-owned methods, stable IDs after unrelated insertions; unresolved impl cannot create cyclic ownership | | Rust const/impl | Const function, distinct type-owned methods, stable IDs after unrelated insertions; unresolved impl cannot create cyclic ownership |
| Fold absolute alias | `src/fold.rs` tests existing root aliases while rejecting outside and excluded files; original default-tempdir test passes | | Fold absolute alias | `src/fold.rs` tests existing root aliases while rejecting outside and excluded files; original default-tempdir test passes |
The grammar versions are pinned in Cargo.toml and Cargo.lock: C++ 0.23.4, The grammar versions are pinned in Cargo.toml and Cargo.lock: C 0.24.2 (`.c`
files), C++ 0.23.4,
JavaScript 0.25.0, TypeScript/TSX 0.23.2, Dart 0.2.0, Rust 0.24.2, with the JavaScript 0.25.0, TypeScript/TSX 0.23.2, Dart 0.2.0, Rust 0.24.2, with the
Tree-sitter Rust runtime at 0.26.13. Upstream API/grammar references: Tree-sitter Rust runtime at 0.26.13. Upstream API/grammar references:
[C++](https://docs.rs/tree-sitter-cpp/0.23.4/tree_sitter_cpp/), [C++](https://docs.rs/tree-sitter-cpp/0.23.4/tree_sitter_cpp/),