{"app":{"name":"Vantage Africa","version":"0.3.0","licence":"MIT (code) · CC BY 4.0 (derived datasets)","url":"/","api":"/api","openapi":"/openapi.json","catalogue":"/api/catalog","llms":"/llms.txt"},"standards":[{"id":"wcag-2.2-aa","name":"WCAG 2.2 Level AA","body":"W3C Web Content Accessibility Guidelines","category":"accessibility","status":"verified","claim":"Conformance target for the dashboard. Every view, both themes.","evidence":"axe-core 4.10.2 automated audit: 0 violations across 5 views and 2 themes; keyboard operability, visible focus, reduced-motion support and landmark/heading structure verified by hand and by test.","reproduce":"python -m pytest tests -q   # backend contract\n# frontend audit: /tmp/opencode/vantage-check/a11y.py"},{"id":"iso-3166-1","name":"ISO 3166-1 alpha-3","body":"ISO","category":"data","status":"applied","claim":"Country codes in every payload and alert.","evidence":"NGA, GHA, BEN, BFA, CIV, GMB, GIN, GNB, LBR, MLI, NER, SEN, SLE, TGO, BRA, UKR, KAZ, IND, IDN, SAU, ARG, USA, EGY, KEN, ETH, TZA, ZAF.","reproduce":"GET /api/stations"},{"id":"iso-4217","name":"ISO 4217 currency codes","body":"ISO","category":"data","status":"applied","claim":"Local currency codes for every market price.","evidence":"NGN, GHS, XOF, EGP, KES, ZAR with the live fixing rate and its date attached to each conversion.","reproduce":"GET /api/prices"},{"id":"iso-8601","name":"ISO 8601 timestamps","body":"ISO","category":"data","status":"applied","claim":"Every timestamp in every payload is ISO 8601 in UTC.","evidence":"Observations, alerts, advisory changes and crawl records all carry a UTC offset.","reproduce":"GET /api/overview"},{"id":"wmo-4677","name":"WMO weather interpretation codes","body":"World Meteorological Organization","category":"data","status":"applied","claim":"Conditions are reported with the standard WMO code alongside the description.","evidence":"Every observation carries its wmo_code; the mapping is unit-tested.","reproduce":"GET /api/region/lagos"},{"id":"codex-cxs-193","name":"Codex Alimentarius CXS 193 (contaminants in food)","body":"FAO/WHO Codex Alimentarius Commission","category":"food-safety","status":"referenced","claim":"The reference thresholds that a residue measurement would be judged against are published alongside the exposure indicator.","evidence":"The platform states the standard and shows modelled dust/PM exposure against WHO 2021 air-quality guidelines. It does not measure residues and does not claim a pass or fail against Codex.","reproduce":"GET /api/region/lagos"},{"id":"sendai-framework","name":"UNDRR Sendai Framework for Disaster Risk Reduction (2015–2030)","body":"UN Office for Disaster Risk Reduction","category":"risk","status":"applied","claim":"The risk layer is structured as hazard, exposure and response — the Sendai framing.","evidence":"Hazard (GDACS), exposure (ERA5 climate history and crop sensitivity), and the response dimension carried by official advisories and market signals.","reproduce":"GET /api/risk"},{"id":"sdmx-2.1","name":"SDMX 2.1 / SDMX-CSV","body":"SDMX Steering Committee","category":"interoperability","status":"applied","claim":"Statistical series are exportable as a flat observation table in SDMX-shaped CSV.","evidence":"GET /api/sdmx/{domain}.csv returns code, time, value and unit columns with a series key.","reproduce":"GET /api/sdmx/weather.csv"},{"id":"dcat-3","name":"DCAT 3 (W3C Recommendation)","body":"W3C","category":"interoperability","status":"applied","claim":"The dataset catalogue is expressed in DCAT terms.","evidence":"/api/catalog returns dcat:Dataset entries with distributions, licences and temporal/spatial coverage.","reproduce":"GET /api/catalog"},{"id":"schema-org-dataset","name":"schema.org Dataset markup","body":"schema.org","category":"interoperability","status":"applied","claim":"The catalogue is also served as JSON-LD for search engines and agents.","evidence":"/api/catalog includes a schema.org Dataset graph for each entry.","reproduce":"GET /api/catalog"},{"id":"gadm-4.1","name":"GADM 4.1 boundaries","body":"gadm.org (Utrecht University)","category":"licensing","status":"attributed","claim":"Administrative geometry for states and local governments.","evidence":"Free for non-commercial use with attribution. Boundaries are administrative and carry no legal weight; they are used for aggregation and display only.","reproduce":"GET /api/regions"},{"id":"faostat-wb","name":"FAO / World Bank public price reference values","body":"FAO and the World Bank","category":"licensing","status":"attributed","claim":"Wholesale/import-parity reference levels per market.","evidence":"Values carry a vintage and are labelled as reference levels, never as live quotes.","reproduce":"GET /api/prices"},{"id":"robots-compliance","name":"robots.txt compliance for all crawled hosts","body":"RFC 9309","category":"governance","status":"enforced","claim":"No crawled URL is fetched before its host's robots.txt has been consulted and obeyed.","evidence":"Google News RSS is disabled by this rule: news.google.com disallows /rss/search for every user-agent, so it is not read. Per-host rate limits and an identifying User-Agent are applied.","reproduce":"vantage/crawl.py — Crawler.allowed()"},{"id":"gdpr-minimal","name":"Data minimisation (GDPR principles, where applicable)","body":"EU GDPR / NDPR","category":"privacy","status":"enforced","claim":"The platform collects no personal data.","evidence":"No accounts, no cookies, no analytics, no third-party pixels. The only client-side storage is a localStorage key for the theme preference. Nothing identifies a user.","reproduce":"grep -rn 'localStorage' templates/index.html"},{"id":"no-certification-claimed","name":"Certifications we do NOT hold","body":"—","category":"governance","status":"declared","claim":"No ISO 27001, SOC 2 or certification of any kind is claimed.","evidence":"Security controls are listed as implemented practices (below), not as certifications.","reproduce":"GET /api/standards"}],"security_controls":[{"control":"Transport and headers","detail":"nginx terminates the request; the app sets Content-Security-Policy, Strict-Transport-Security, X-Content-Type-Options, Referrer-Policy, Permissions-Policy and X-Frame-Options on every response."},{"control":"Secrets","detail":"No credential is committed. API keys live in a git-ignored .env file with 0600 permissions and are read from the environment at start-up."},{"control":"Authentication","detail":"Read endpoints are deliberately public — they expose only public data. The one mutating endpoint (/api/refresh) is disabled unless VANTAGE_ADMIN_TOKEN is set, and then requires the token in X-Admin-Token."},{"control":"Error handling","detail":"Unhandled errors return a generic message; the detail stays in the server log. Upstream failures degrade into labelled partial results rather than exceptions."},{"control":"Upstream quotas","detail":"Per-host throttling, hourly request budgets and fail-fast into labelled degraded mode, so no provider is hammered and nothing is silently fabricated."},{"control":"Data minimisation","detail":"Only aggregate, public, non-personal data is stored: observations, provider health, hazard alerts and dated price quotes."},{"control":"Retention","detail":"Observations are pruned after 120 days, hazard alerts after 90 days, and the price corpus keeps every dated quote so the history stays auditable."},{"control":"Attribution","detail":"Every figure carries its source. Third-party licences (GADM, FAO/World Bank) are stated in the catalogue and in the UI."}],"governance_principles":[{"principle":"Provenance before presentation","detail":"A number without a source, an as-of date and a confidence band is not published."},{"principle":"Never inflate","detail":"Prices are medians with the range beside them; forecasts come with their ensemble spread; stress indices count a single unconfirmed headline at a third of its weight."},{"principle":"Degrade loudly","detail":"When an upstream source is unavailable, the board says so and lowers confidence — it never fills the gap with an estimate."},{"principle":"Validate against an independent source","detail":"Every new provider is cross-checked against a known magnitude before it is trusted (this is how the NASA POWER daily-precipitation error was caught)."},{"principle":"Claim only what is measured","detail":"SDG alignment is stated per goal with the specific contribution and the specific omission. Goals we do not address are marked as such."}],"sdg":{"note":"Vantage Africa is a contextual-information platform. It does not produce official SDG indicators and does not report against the goals; it publishes measurements that bear on them, with the measurement named in every case.","levels":{"informed":"the platform publishes a measurement that bears directly on this goal","partial":"the platform publishes one input, not the indicator itself","none":"not addressed"},"counts":{"informed":4,"partial":7,"none":6},"goals":[{"goal":1,"name":"No Poverty","colour":"#E5243B","level":"partial","targets":["1.1","1.2","1.3"],"why":"Farm-gate and market price levels are one input to farm income. The platform publishes prices and their dispersion; it does not model incomes or poverty rates.","contributes":["Local market price corpus","Reference price levels with live FX"],"does_not":["Income distributions","Household survey data"]},{"goal":2,"name":"Zero Hunger","colour":"#DDA63A","level":"informed","targets":["2.1","2.3","2.4"],"why":"Crop-quality projections, validated price levels and food-security exposure, at state and local-government resolution.","contributes":["Crop-quality projection","Food-security stress component","Market price corpus"],"does_not":["Official hunger indicators","Household consumption"]},{"goal":3,"name":"Good Health and Well-being","colour":"#4C9F38","level":"informed","targets":["3.9","3.d"],"why":"Dust and particulate exposure indicators and food-safety, contamination and outbreak signals.","contributes":["Contamination watch","Disease signal component","Saharan dust load"],"does_not":["Clinical outcomes","Laboratory residue measurement"]},{"goal":4,"name":"Quality Education","colour":"#C5192D","level":"none","why":"Not addressed. The platform produces no learning or training material.","contributes":[],"does_not":["Everything in this goal"]},{"goal":5,"name":"Gender Equality","colour":"#FF3A21","level":"none","why":"Not addressed. The platform carries no gender-disaggregated data and must not infer it.","contributes":[],"does_not":["Everything in this goal"]},{"goal":6,"name":"Clean Water and Sanitation","colour":"#26BDE2","level":"partial","targets":["6.4","6.b"],"why":"Drought indices describe agricultural water stress; the platform does not model household water, sanitation or water quality.","contributes":["Drought index and deficit","Dry-spell tracking"],"does_not":["Water services","Water quality","Irrigation efficiency"]},{"goal":7,"name":"Affordable and Clean Energy","colour":"#FCC30B","level":"none","why":"Not addressed, with one exception noted in the signals layer: energy and fuel stories appear as macro stress inputs, not as energy statistics.","contributes":[],"does_not":["Energy access","Energy prices as statistics"]},{"goal":8,"name":"Decent Work and Economic Growth","colour":"#A21942","level":"partial","targets":["8.1","8.3"],"why":"Price levels, FX and price dispersion bear on market conditions for smallholders; no employment or growth data is published.","contributes":["Validated price levels","Live FX","Price dispersion"],"does_not":["Employment","GDP","Value-chain economics"]},{"goal":9,"name":"Industry, Innovation and Infrastructure","colour":"#FD6925","level":"none","why":"Not addressed beyond the infrastructure signal carried in hazard alerts (pipeline vandalism, road disruption).","contributes":[],"does_not":["Infrastructure statistics"]},{"goal":10,"name":"Reduced Inequalities","colour":"#DD1367","level":"partial","targets":["10.2","10.3"],"why":"Local-government resolution exposes sub-state disparity in crop outlook and exposure; it is not a distributional measure.","contributes":["LGA-level crop quality and exposure","Regional price dispersion"],"does_not":["Income inequality","Marginalised groups"]},{"goal":11,"name":"Sustainable Cities and Communities","colour":"#FD9D24","level":"none","why":"Not addressed. Urban infrastructure and housing are outside the platform's scope.","contributes":[],"does_not":["Everything in this goal"]},{"goal":12,"name":"Responsible Consumption and Production","colour":"#BF8B2E","level":"partial","targets":["12.3","12.4"],"why":"Food-safety and chemical-use signals, crop-quality losses that affect marketable output, and post-harvest exposure.","contributes":["Contamination and food-safety signals","Crop-quality loss estimate"],"does_not":["Food waste measurement","Chemical inventories"]},{"goal":13,"name":"Climate Action","colour":"#3F7E44","level":"informed","targets":["13.1","13.3","13.2"],"why":"Seasonal drought and flood exposure computed from five years of daily reanalysis, with a published methodology.","contributes":["Drought and flood indices","Crop-quality projection","Hazard alerts"],"does_not":["Emissions accounting","Mitigation modelling"]},{"goal":14,"name":"Life Below Water","colour":"#0A97D9","level":"none","why":"Not addressed. Coastal and marine systems are outside the platform's scope.","contributes":[],"does_not":["Everything in this goal"]},{"goal":15,"name":"Life on Land","colour":"#56C02B","level":"partial","targets":["15.1","15.3"],"why":"Crop performance and land degradation signals by agro-ecological zone; no soil or biodiversity measurement.","contributes":["Agro-ecological crop suitability","Land-stress signals"],"does_not":["Soil quality","Biodiversity indices"]},{"goal":16,"name":"Peace, Justice and Strong Institutions","colour":"#00689D","level":"partial","targets":["16.1"],"why":"Official security advisories and terrorism signals give institutions and planners the same situational picture they act on.","contributes":["FCDO state-level advisory","Terrorism and insecurity signals","Security stress component"],"does_not":["Judicial or institutional statistics"]},{"goal":17,"name":"Partnerships for the Goals","colour":"#19486A","level":"informed","targets":["17.17","17.19"],"why":"Every figure is published with provenance, an open API, a data catalogue and a machine-readable summary for tooling.","contributes":["Open API with documented provenance","DCAT dataset catalogue","llms.txt for agent discovery"],"does_not":["Partnership agreements","Development finance data"]}]}}