Context
National macro requests are spelled two ways today:
- Omit
region — the sim API's own convention (contract tests, integration tests, docs examples).
region: "us" — what API v1 sends on every national US macro run (SimulationOptions.region is a required string in policyengine-api/policyengine_api/services/economy_service.py:79; the value is stored in a NOT NULL DB column on job records). v1 is the only production caller using this spelling.
The worker accepts both via the normalisation shim at simulation_runtime.py:212-218 (None/empty/"us"/"uk" → country), and as of #637 the segmented-national eligibility does too (is_plain_national_macro). Two spellings for the same semantics means every national-detection site must remember both — #637's review caught exactly this class of drift (eligibility initially treated region:"us" as regional, which would have excluded all v1 production traffic from segmentation).
Goal
One national spelling: omit region. region:"us"/"uk" becomes deprecated, then rejected.
Migration checklist
Phase 1 — v1 stops sending it (policyengine-api):
Phase 2 — contract + budget window (policyengine-sim-api):
Phase 3 — deprecation signal, then removal (policyengine-sim-api):
Interim state
Until Phase 1 lands, the sim API MUST keep treating region:"us" as national everywhere — it is the production national traffic. #637 aligned segmentation eligibility with the worker shim so both spellings behave identically.
Context
National macro requests are spelled two ways today:
region— the sim API's own convention (contract tests, integration tests, docs examples).region: "us"— what API v1 sends on every national US macro run (SimulationOptions.regionis a required string inpolicyengine-api/policyengine_api/services/economy_service.py:79; the value is stored in aNOT NULLDB column on job records). v1 is the only production caller using this spelling.The worker accepts both via the normalisation shim at
simulation_runtime.py:212-218(None/empty/"us"/"uk"→ country), and as of #637 the segmented-national eligibility does too (is_plain_national_macro). Two spellings for the same semantics means every national-detection site must remember both — #637's review caught exactly this class of drift (eligibility initially treatedregion:"us"as regional, which would have excluded all v1 production traffic from segmentation).Goal
One national spelling: omit
region.region:"us"/"uk"becomes deprecated, then rejected.Migration checklist
Phase 1 — v1 stops sending it (policyengine-api):
economy_service.py: makeSimulationOptions.regionoptional; send noregionfor national runs (:79,_setup_sim_options:972-1006,_setup_region:1137-1149)_classify_simulation_geography(:1254) currently detects national viaregion == country_id— needs the omitted-region casereform_impacttable:region VARCHAR(32) NOT NULL— decide sentinel (e.g.national) or schema changeregionquery param (economy_routes.py:52,:105-107)Phase 2 — contract + budget window (policyengine-sim-api):
BudgetWindowBatchRequest.regionis a requiredstr(gateway_models.py:178) — national budget windows currently must sendregion:"us"; make it optional with omitted == national (golden + client regen)gateway_models.pythat national == omitregion(or useregion_group)Phase 3 — deprecation signal, then removal (policyengine-sim-api):
_normalise_region_codeshim (simulation_runtime.py:212-218) whenregionin{"us","uk"}region:"us"traffic: remove the shim, remove theregion in ("", country)acceptance insegmented_national.is_plain_national_macro, and reject the spelling with a clear errorInterim state
Until Phase 1 lands, the sim API MUST keep treating
region:"us"as national everywhere — it is the production national traffic. #637 aligned segmentation eligibility with the worker shim so both spellings behave identically.