Skip to content

Persistent Findings Database and Security Posture Trend Reporting (chainproof history) #64

Description

@Nanle-code

Problem Statement

ChainProof can diff findings between two commits (see the closed "structured diff engine" work), but every scan is otherwise stateless — nothing is retained between runs. Teams adopting ChainProof in CI have no way to answer "is our security posture improving over time," "which findings have been open the longest," or track trends across releases, without manually archiving reports. This is a reasonable expectation for a tool positioning itself as a continuous audit companion, as ChainProof's own README describes it.

Proposed Solution

Add a chainproof history command family backed by a local SQLite database (default .chainproof/history.db, git-ignored by default) that durably records every scan:

  • Every chainproof scan run (opt-in via --record-history, or always-on once .chainproof/history.db already exists) persists: commit SHA, branch, timestamp, and the full finding set (id, rule, file, line, severity, first-seen commit).
  • chainproof history summary [--since <date>] [--branch <name>] — reports finding counts by severity over time, and highlights newly introduced vs. resolved findings between the two most recent recorded scans.
  • chainproof history trend --format json|markdown — emits a time series suitable for plotting (date → severity counts) so teams can render it in their own dashboards or paste it into a markdown report.
  • chainproof history age — lists currently open findings sorted by how many recorded scans (or how much wall-clock time) they've persisted, surfacing long-lived unresolved risk.
  • A finding is matched across scans using the same stable identity logic already used by the diff engine (rule + normalized file + line-range overlap), so a finding that moves a few lines due to unrelated edits is still tracked as the same finding rather than counted as both new and resolved.

Technical Scope

  • New packages/core/src/history/store.ts: SQLite schema and an insert/query layer.
  • New packages/core/src/history/trends.ts: aggregation logic for the summary/trend/age views, reusing the existing finding-identity matching from diff.ts.
  • New packages/cli/src/commands/history.ts wiring the summary, trend, and age subcommands into the existing CLI.
  • Database file path configurable via .chainproofrc.json; writes must be safe for concurrent CI runs (e.g., a busy-timeout/retry) without corrupting existing history.
  • Tests: identity matching across a simulated 5-scan history with findings introduced, resolved, and reintroduced; trend aggregation correctness; concurrent-write safety.

Acceptance Criteria

  • Running five successive scans against a fixture repo with deliberately evolving contracts produces a history summary that correctly reports introduced/resolved counts at each step.
  • history age correctly ranks findings by first-seen date across the recorded history.
  • History recording adds no more than a small, documented constant overhead to scan time.
  • Documentation includes a recommended .gitignore entry and a CI wiring example (e.g., persisting .chainproof/history.db as a CI cache/artifact between runs).

Estimated Scope

Approximately 700 lines of new TypeScript across the store, trend engine, CLI commands, and tests.

Metadata

Metadata

Assignees

No one assigned

    Labels

    GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions