# `Lei.ReportFreshness`
[🔗](https://github.com/kitplummer/lowendinsight/blob/main/lib/lei/report_freshness.ex#L1)

Brings a stored report's time-dependent risk up to the present (#242).

Five of the six risk metrics are pure functions of a cloned git history: they
can only change when the upstream repository changes, so a stored value stays
correct for as long as the entry describes the same commit.
`commit_currency_risk` is the exception. It is derived from
`DateTime.utc_now()` and is therefore correct only at the instant it was
computed:

    weeks = TimeHelper.get_commit_delta(date) |> TimeHelper.sec_to_weeks()

Stored as a number and served unchanged, it reports the risk a repository
held when it was analysed rather than the risk it holds now -- so a project
drifting into abandonment keeps the verdict it had before it went quiet. That
is the one signal this analysis exists to raise, which made the cache a way
of suppressing it.

Nothing here re-analyses anything. `data.git.last_commit_date` is already
stored beside the frozen week count, and the true figure is that date against
the clock. No clone, no network, no new data -- only arithmetic that should
have been done on the way out rather than on the way in.

Operates on the string-keyed map a report decodes to from JSON.
`AnalyzerModule.determine_toplevel_risk/1` is not reusable for the rollup: it
reads atom keys, and it uses `Map.put_new/3`, so on a report that already
carries a risk -- which every stored report does -- it silently keeps the old
one.

# `refresh`

```elixir
@spec refresh(map()) :: map()
```

Returns the report with its commit currency, and the risk rolled up from it,
recomputed against the current time.

A report that cannot be recomputed is returned exactly as it was given: no
`data.git.last_commit_date`, a date that will not parse, or no results to
revise. Those entries predate the field or came from somewhere that does not
set it, and the alternative -- treating a missing date as zero elapsed weeks
-- would publish a confident "low" derived from nothing, which is the same
defect this function exists to remove.

# `refresh_json`

```elixir
@spec refresh_json(binary()) :: binary()
```

Decodes, refreshes and re-encodes a stored report.

Anything that is not a decodable report is passed through untouched: a read
returning what it found is a cache miss at worst, while raising here would
turn one malformed entry into a failed request.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
