Deferred finding from the PR #234 access-control audit (internal/plans/pr234-dci-access-audit-findings.md, Finding 2). Confirmed real; filing for tracking (previously only noted in a PR #234 comment).
Finding
PR #234's _check_dci_sync_access guards only sync_for_partners(). A second route to the same outbound DCI fetch is not gated:
spp.data.cache.manager._compute_variable_values() # spp_dci_indicators/models/data_cache_manager_dci.py:15-18
-> spp.dci.cel.fetcher.fetch_values() # outbound DCI call + cache write, runs as caller, no check
Reached via precompute_variable() in spp_cel_domain/models/data_evaluator.py (no access check), which a programs officer can trigger through cycle eligibility (spp_programs/models/managers/cycle_manager_base.py → check_eligibility → precompute). So a programs officer can still trigger outbound fetches of disability/health data through that path, even though the directly-bindable surface (manual server action / sync) is now closed.
Design decision needed
Where to place the gate — fetcher vs cache-manager vs evaluator — without breaking the legitimate scheduled cron and cycle-eligibility precompute (which must keep working, likely via an env.su discriminator). The narrower reachability (needs a programs role + configured cycle) is why this was deferred rather than blocking.
Source: internal/plans/pr234-dci-access-audit-findings.md. Related: #234, PR #234 comment.
Deferred finding from the PR #234 access-control audit (
internal/plans/pr234-dci-access-audit-findings.md, Finding 2). Confirmed real; filing for tracking (previously only noted in a PR #234 comment).Finding
PR #234's
_check_dci_sync_accessguards onlysync_for_partners(). A second route to the same outbound DCI fetch is not gated:Reached via
precompute_variable()inspp_cel_domain/models/data_evaluator.py(no access check), which a programs officer can trigger through cycle eligibility (spp_programs/models/managers/cycle_manager_base.py→check_eligibility→ precompute). So a programs officer can still trigger outbound fetches of disability/health data through that path, even though the directly-bindable surface (manual server action / sync) is now closed.Design decision needed
Where to place the gate — fetcher vs cache-manager vs evaluator — without breaking the legitimate scheduled cron and cycle-eligibility precompute (which must keep working, likely via an
env.sudiscriminator). The narrower reachability (needs a programs role + configured cycle) is why this was deferred rather than blocking.Source:
internal/plans/pr234-dci-access-audit-findings.md. Related: #234, PR #234 comment.