MicroAI Paygate
An x402-style payment gateway for AI requests. Sign EIP-712, get a signed receipt, verify the signature client-side.
Tu percentil, decil y línea de pobreza, calculados con microdatos reales de la EPH (INDEC).
Translation pending
FinanceTypeScript · PythonGitHub @lucasdaddiegoOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Where do you stand in Argentina's income distribution? An interactive percentile tool built from real INDEC EPH microdata — weighted percentiles, Gini, Lorenz curve and poverty lines, validated to the peso.
Taken from the repository README
Loading the full README.
Read the full README ↗Where do you stand in Argentina's income distribution? This tool answers that from the real INDEC EPH microdata — it downloads the household survey, applies the official sample weights, and computes the weighted income distribution itself. No eyeballed deciles, no decorative curves.
▶ Try it live: argentina-income-analyzer.pages.dev
Validated against INDEC (Evolución de la distribución del ingreso, 4º trim. 2025): Gini IPCF 0.427 ✓, mediana $450.000 ✓, media $635.996 ✓, población 30.032.540 ✓, every published decile cutoff reproduced to the peso, and every decile's income share to the published 0.1 point.
It has two parts:
pipeline/ — an offline, reproducible Python pipeline (uv + pandas + numpy) that turns the
raw EPH base into one small, provenance-stamped JSON artifact.web/ — a static Vite + TypeScript site that reads that JSON and renders honest graphics
(empirical CDF, weighted histogram, Lorenz curve + data-derived Gini) plus a poverty-line check.P47T) is weighted by PONDII; household per-capita income
(IPCF) by PONDIH — INDEC's non-response-corrected factors, never the plain PONDERA.data/cpi_monthly.json, generated monthly from the spliced
series of peso) before the lookup, and says so next to the result.make setup # uv sync (python deps) + npm install (web deps)
make data # fetch → verify(sha256) → build(JSON) → validate(vs INDEC)
make test # python + web unit tests, each gated at 100% coverage
make lint # ruff + mypy + tsc
make up # vite dev server → http://localhost:5179
make build # static bundle in web/dist/
make deploy # publish web/dist/ to Cloudflare Pages (needs wrangler auth)
make (or make help) lists every target. make data downloads
EPH_usu_4_Trim_2025_txt.zip (~2.9 MB, public INDEC data), computes the statistics, writes
data/percentiles.v1.json and web/public/percentiles.v1.json, and asserts the reproduction of
INDEC's official numbers. The pipeline steps can also be run one at a time with
uv run python -m pipeline.{fetch,verify,build,validate}.
EPH microdata (T425, ;-delimited, comma decimals)
└─ pipeline/ fetch → verify → load → weighted stats → validate → emit
└─ web/public/percentiles.v1.json (versioned, provenance-stamped)
└─ web/ Vite + TS + Observable Plot (lookups + honest charts only)
The frontend does no statistics — only lookups and trivial interpolation against the precomputed artifact. Everything quantitative is computed once, offline, and validated.
-9, decile codes 12/13) is excluded.numpy.quantile(method='inverted_cdf', weights=...).docs/metodologia.md, and the "Metodología" section in the app.pipeline/ config (pinned facts) · fetch · verify · load · weighted · build · validate · artifact_check · watch · cpi_sync
tests/ pytest suite for pipeline/ — offline, synthetic fixture, 100% statement+branch coverage
data/ checksums.txt · percentiles.v1.json (raw/ is gitignored)
web/ index.html · styles.css · test/ (vitest, 100%) · src/:
main.ts (init, controls, renderAll) · app.ts (state, artifact, deflated income) · ui.ts
headline · ladder · splits · geo · time · poverty · cost · visuals · about · classes
charts · stats · format · usd · types
docs/ metodologia.md
Both layers are gated at 100% coverage — statements and branches:
pipeline/ — pytest against a tiny synthetic EPH fixture (no network, no real microdata).web/src/ — vitest + jsdom, every render path exercised against the committed artifact.make test runs both; make lint runs ruff + mypy + tsc. GitHub Actions enforce it, three
on every push/PR (path-filtered so a web-only change never reaches for INDEC) and one on a monthly
schedule; every action is pinned to a commit SHA and Dependabot (.github/dependabot.yml) keeps the
pins, npm and uv current:
| Workflow | What it checks |
|---|---|
deploy.yml | web typecheck + vitest 100% gate + production build, then (only if that passed) the Cloudflare Pages deploy: production on master, preview per PR |
python.yml | ruff + mypy + pytest 100% gate (offline, fast) |
data.yml | the two committed copies of the artifact are identical, the pipeline still reproduces INDEC, and the committed artifact matches the rebuild |
data-update.yml | monthly watch — opens a draft PR when a newer EPH quarter is published |
cpi-sync.yml | monthly sync — regenerates data/cpi_monthly.json from peso's published artifact and, when the months changed, rebuilds, tests and pushes to master (which deploys) |
The exact source file is pinned by SHA-256 in data/checksums.txt (trust-on-first-use). The verify
step (part of make data, or uv run python -m pipeline.verify) fails if the input ever changes, so
the build is reproducible against a known input. To update to a newer quarter, edit pipeline/config.py
(ZIP_URL, *_FILE, QUARTER) and delete data/checksums.txt.
The monthly poverty lines live in their own POVERTY_LINES block (they update more often than the EPH).
The site uses only the latest 2º or 4º trimestre: INDEC's 1º and 3º trimestre include the
aguinaldo, which inflates a typical month's income. The monthly watch (data-update.yml) proposes
only those quarters, from a 4º trimestre pin the next 2º and from a 2º the next 4º.
Static bundle + one JSON → ideal for Cloudflare Pages (web/dist/). web/public/_headers
sets the security headers (CSP, X-Frame-Options, nosniff, referrer and permissions policies),
caches the content-hashed JS/CSS/data under /assets/ for a year (immutable) and revalidates
index.html and the fixed-name percentiles.v1.json (kept for direct links; the page loads the
hashed copy) on every request. Live at
argentina-income-analyzer.pages.dev. deploy.yml
publishes it from CI once the web tests pass: every push to master that touches web/ goes to
production and PRs get a per-branch preview (needs the CLOUDFLARE_API_TOKEN /
CLOUDFLARE_ACCOUNT_ID secrets; without them the job still builds and just skips the deploy).
make deploy does the same by hand.
The app deliberately separates two kinds of figures:
DECINDR labels. The regional,
aglomerado and structural-split breakdowns (build_regions, build_aglomerados, build_splits)
are computed from the same microdata and weights, but INDEC doesn't publish matching per-cell
figures to anchor them against — treat them as derived, not separately validated. This is the
trustworthy spine.pipeline/config.py:
HISTORY — Gini (quarterly) + poverty/indigence (semestral) + nominal median, from INDEC press reports.CPI_MONTHLY — INDEC's monthly IPC from the survey's reference month on, loaded from
data/cpi_monthly.json, which pipeline/cpi_sync.py regenerates from peso's published artifact
(monthly, cpi-sync.yml); deflates the typed income to survey pesos. Never edit it by hand.POVERTY_LINES — CBA/CBT per adulto equivalente (period-matched to the income vintage).COST_OF_LIVING — rent, utilities, food, transport, internet, health + SMVM/jubilación, gathered
mid-2026 from Zonaprop, IIEP-UBA/CONICET, AySA, telco comparators and press. These vary widely by
case and are labeled in the app as estimates, not microdata.To refresh any reference block, edit its dict in config.py and run make data (which rebuilds the
JSON artifact). Note make build builds the web bundle, not the data.
Code: MIT. · Data: see NOTICE.
Data: Source: Encuesta Permanente de Hogares (EPH), INDEC — public base usuaria microdata. INDEC permits republishing aggregate/derived statistics with attribution; individual records are never shipped (only aggregates), satisfying the secreto estadístico (Ley 17.622). The cost-of-living layer cites its own external sources inline.
Elaboración propia en base a microdatos de la Encuesta Permanente de Hogares (EPH), INDEC. Fuente: INDEC, www.indec.gob.ar.