Problem
The eval identifies that ISOProber._build_probe_list reads WG21Index's mutable internal fields (_max_rev and papers) directly when constructing HEAD request batches. These fields are prefixed with _ indicating they are private, yet ISOProber accesses them across the module boundary. This encapsulation breach creates a latent thread-safety risk: if the Bolt daemon thread or MessageQueue sender thread ever accessed WG21Index during an async refresh() call, there would be a TOCTOU race on the shared dicts. The eval rates the current risk as "latent rather than active" because accesses are confined to the async context, but notes this is "documented nowhere" — a future contributor adding a Slack command that reads index state from the Bolt thread would introduce a live race.
Acceptance Criteria
Implementation Notes
The eval's core concern is the async/sync boundary opacity. The fix has two parts: (1) stop ISOProber from reaching into WG21Index internals, and (2) document the threading contract. For the public API, consider returning MappingProxyType wrappers or simple dict copies. The thread-safety docstring is important — the eval calls the absence of per-type thread-safety documentation the "hub from which two compounding dynamics extend."
References
- Eval finding: Section 5, "Async/Sync Boundary Opacity" —
_max_rev and papers TOCTOU risk
- Related files:
sources.py (WG21Index, ISOProber), models.py
Problem
The eval identifies that
ISOProber._build_probe_listreadsWG21Index's mutable internal fields (_max_revandpapers) directly when constructing HEAD request batches. These fields are prefixed with_indicating they are private, yetISOProberaccesses them across the module boundary. This encapsulation breach creates a latent thread-safety risk: if the Bolt daemon thread or MessageQueue sender thread ever accessedWG21Indexduring an asyncrefresh()call, there would be a TOCTOU race on the shared dicts. The eval rates the current risk as "latent rather than active" because accesses are confined to the async context, but notes this is "documented nowhere" — a future contributor adding a Slack command that reads index state from the Bolt thread would introduce a live race.Acceptance Criteria
WG21Indexexposes a public, read-only API for the dataISOProberneeds (e.g.,get_max_revision(paper_number),get_known_paper_ids())ISOProber._build_probe_listuses the public API rather than accessing_max_revorpapersdirectlyWG21Indexdocuments thread-safety: "This class is designed for single-threaded async use. Do not access from the Bolt daemon thread."_build_probe_listcontinue to passImplementation Notes
The eval's core concern is the async/sync boundary opacity. The fix has two parts: (1) stop
ISOProberfrom reaching intoWG21Indexinternals, and (2) document the threading contract. For the public API, consider returningMappingProxyTypewrappers or simpledictcopies. The thread-safety docstring is important — the eval calls the absence of per-type thread-safety documentation the "hub from which two compounding dynamics extend."References
_max_revandpapersTOCTOU risksources.py(WG21Index, ISOProber),models.py