Files
git.stella-ops.org/docs/modules/scanner/analyzers-bun.md
StellaOps Bot 6e45066e37
Some checks failed
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
up
2025-12-13 09:37:15 +02:00

82 lines
4.3 KiB
Markdown

# Bun Analyzer (Scanner)
## What it does
- Inventories npm-ecosystem dependencies from Bun-managed projects without executing `bun`.
- Supports installed inventory (`node_modules/**/package.json`), lockfile-only inventory (`bun.lock`), and declared-only fallback from `package.json`.
- Enriches output with deterministic scope signals (`dev`, `optional`, `peer`, `scopeUnknown`), patch attribution, and bounded sha256 evidence.
## Inputs and precedence
1. **Installed inventory** (`node_modules/` present): traverse installed packages and emit components from installed `package.json` (uses `bun.lock` for resolved/integrity + scope enrichment when present).
2. **Lockfile-only** (`bun.lock` present, no install): parse `bun.lock` and emit components from lock entries.
3. **Declared-only fallback** (project markers present but no `bun.lock`/install): emit explicit-key components from `package.json` dependency sections.
4. **Unsupported** (`bun.lockb` only): emit a remediation record explaining how to produce `bun.lock`.
## Project discovery (including container roots)
The analyzer discovers Bun project roots under:
- The analysis root (`context.RootPath`)
- Common OCI unpack layouts: `layers/*`, `.layers/*`, and `layer*` (direct children)
Discovery is bounded and deterministic:
- Sorted directory enumeration
- Explicit depth and root caps
- Never recurses into `node_modules/`
## Identity rules (PURL vs explicit key)
Concrete versions emit a PURL:
- `purl = pkg:npm/<name>@<version>`
- Concrete versions follow the Node-style guardrail (no ranges/tags/paths embedded as a "version"; see `Internal/BunVersionSpec.IsConcreteNpmVersion`).
Non-concrete versions emit an explicit key:
- `componentKey = explicit::<analyzerId>::npm::<name>::sha256:<digest>`
- `purl = null`, `version = null`
- Used for declared-only dependencies and any lock/installed records whose `version` is not concrete (e.g., `workspace:*`, `link:../...`, `file:../...`).
Explicit-key digest input (canonical, UTF-8):
```
npm\n<name>\n<spec>\n<originLocator>
```
Generated via `LanguageExplicitKey.Create(...)` and aligned with `docs/modules/scanner/language-analyzers-contract.md`.
## Evidence and locators
All evidence locators are relative and use `/` separators.
### File evidence
- Installed packages: `node_modules/.../package.json`
- Hashing: sha256 is computed for `package.json` only when size is within 1 MiB; when skipped, metadata includes:
- `packageJson.hashSkipped=true`
- `packageJson.hashSkipReason=<missing|unauthorized|io|size>...`
### Lockfile entry evidence
- Locator format: `<lockfileRelativePath>:packages[<name>@<version>]`
- Example: `bun.lock:packages[lodash@4.17.21]`
- Hashing: sha256 is computed for `bun.lock` only when size is within 50 MiB; when skipped, metadata includes:
- `bunLock.hashSkipped=true`
- `bunLock.hashSkipReason=<missing|unauthorized|io|size>...`
## Scope semantics (dev/optional/peer)
Scope is derived deterministically from the `bun.lock` dependency graph rooted at `package.json` declarations:
- `dev=true` only when dev reachability is provable.
- `optional=true` and `peer=true` are preserved when present in lock data or derived from declared scopes.
- If the graph cannot disambiguate (multiple candidates/specifier mismatch), the record is marked:
- `scopeUnknown=true`
- `dev=false` (do not guess)
`includeDev=false` filters only packages proven to be dev-only; unknown-scope packages are kept but marked `scopeUnknown=true`.
## Patches and workspaces
- Workspace patterns come from root `package.json` (`workspaces`).
- Patch attribution supports Bun's `patchedDependencies` and patch directories.
- Patch keys preserve version specificity (`name@version`) and patch paths are emitted as deterministic project-relative paths.
- Patch matching precedence: `name@version` first; then name-only only when unambiguous.
## Known limitations
- `bun.lockb` (binary lockfile) is not parsed; a remediation record is emitted instead.
- The analyzer does not execute `bun` and does not fetch registries; offline-only behavior is enforced.
## References
- Sprint: `docs/implplan/SPRINT_0407_0001_0001_scanner_bun_detection_gaps.md`
- Cross-analyzer contract: `docs/modules/scanner/language-analyzers-contract.md`
- Design notes: `docs/modules/scanner/prep/bun-analyzer-design.md`
- Gotchas: `docs/modules/scanner/bun-analyzer-gotchas.md`