2,450
Tracked records — 2,308 physical assets plus 142 production areas and company aggregates
119
Countries holding assets
63/70
Within ±1 tier (90.0%)
32/70
Exact-tier match (45.7%)
What it does
The Atlas models structural supply-chain exposure. Given a disruption to a tracked entity (a chokepoint, refinery, mine, pipeline, terminal, or strategic facility), the engine computes which other entities and countries are downstream of that entity in the dependency graph, weights the cascade by physical capacity and substitutability, applies damping for normal market response, and produces a verdict tier.
The output is read as a structural reading — not a price forecast, not a probability of the event itself happening, and not a recommendation. It answers “if this happens, who’s exposed and how badly?”
The engine pipeline
Six stages. The engine output you see in any report is the result of these stages applied in sequence to the curated dependency graph.
Multi-hop cascade
Walk the dependency graph forward from the disrupted entity. Each edge carries weight + substitutability.
Country aggregation
Entity impacts rolled up into per-country exposure via country-of-residence and import-source maps.
Six dampers
Spare capacity, strategic stockpile, demand destruction, backfill, portfolio rebalance, regulatory response.
Four amplifiers
Regional contagion, commodity coupling, price-shock amplifier, political-response amplifier.
Tier classification
Four signals scored independently: mbpd anchor, composite score, % global lost, month-6 sustained. Highest wins.
Shape promotion
Trajectory shape adjusts the verdict: persistent or escalating shapes can promote tier; sharp recovery can demote.
The four-signal classifier is the engine’s honesty mechanism: any single signal can produce a high tier, but the binding signal is named in every report. If three signals point to MODERATE and one points to GLOBAL, the verdict is GLOBAL but the report tells you it’s anchored on a single dimension.
The data
The engine is anchored on 2,308 atomic physical assets across 227 commodity planes (crude oil, refined products, LNG, coal, base metals, battery materials, rare earth, fertilizer, grain, palm oil and sugar, container logistics, semiconductors and their materials, power generation, pipelines and much of the tail) — refineries, terminals, fields, mines, plants, pipelines, chokepoints, LNG trains, smelters, fabs. These are the only entities the platform counts as disruptable assets. Alongside them sit 142 production areas and company aggregates — basins, growing belts and multi-site companies — which exist as reference and scouting tools and are not traversed as cascade dependencies: an aggregate is not itself a party to a supply relationship (a power plant depends on a coal mine, not on “the grid”), so aggregate-sourced cascade weight is neutralised at build time and never counted toward asset coverage. The dependency graph wires the assets into 6,513 directed asset-to-asset relations, each carrying the sentence it was read from.
Each entity carries: name, type, country, operator, capacity, geographic coordinates, and a curated dependency graph linking it to upstream and downstream counterparts. Capacity values are sourced from operator IR filings, EIA chokepoint reports, S&P Global Platts plant-level data, and equivalent industry references. Source provenance is recorded per-entity.
Country portfolios — the import-side dependency profile of 86 countries — are hand-built; they encode for each country which entities supply which commodities at what weight.
Coverage is honest, not inflated: the platform tracks 2,308 atomic physical assets as its asset count, of which 2,307 carry a real coordinate. A further 142 production areas and company aggregates carry cross-class structure as reference nodes but are not themselves single assets and are excluded from every asset-coverage figure on this page. Every node is either wired to a counterparty or carries a written declaration of why it is not; none is silent. No fabricated assets, and no fabricated coordinates — an asset with no single real place gets none.
Probability layer
Each entity carries an annual disruption prior — a historical-frequency anchor that estimates how often, in a given year, an event matching the modeled disruption profile occurs at that entity. Priors come from three sources, in decreasing curated specificity:
The prior values are not published. Each curated chokepoint carries a fitted annual figure derived from its own incident record — tanker incidents and seizures, attack tempo, exercise frequency, transit restrictions, drought and water levels, depending on the lane. Those numbers are the calibration, and printing them would hand over the layer without the work behind it. What is published instead is what the layer is, what kind of evidence each prior rests on, and every verdict it contributes to.
For every other entity in the graph, the engine falls back to class-level priors (refinery base rate, terminal base rate, pipeline base rate, etc.) drawn from published incident corpora.
A prior is a historical-frequency anchor, not a forecast. The conditional probability (posterior given current indicators) is implemented for chokepoints via Bayesian update; for other entity classes, only the unconditional prior is surfaced.
Calibration
The engine is scored against 70 historical disruptions, from the 1973 oil embargo to the 2026 closure of Hormuz. Each carries a severity tier graded from what the market actually did, and a direction graded against that commodity’s own price record.
Every event is fired at the graph as it stands today — current capacities, current wiring, current world totals — not at a reconstruction of the world on the day. A 1973 embargo is scored against 2026 refineries. Where the world has since changed, the engine will read the event differently from the record. The test asks whether the mechanism reproduces history where the structure still matches, and misses are expected where it does not.
The denominators differ, and neither is trimmed. Severity is scored on all 70: a tier comes out of the engine even when it reaches nothing. Direction cannot be — with no asset reached there is no commodity moving, so there is nothing to be right or wrong about. The seven events that make up the difference are listed below, with what each one fires and why it goes nowhere.
Directional is the figure to weigh. Severity can be passed by over-reacting — the bar is “at least as severe”, so an engine that shouts at everything clears it. Directional cannot: the engine has to move the correct commodity the correct way, or it fails. What this product claims is which commodities move, in which direction, through which assets, with lead time. It does not claim the size of the move.
Where it will fail you. It under-called 4 of the 70 — events where it would have warned you less than the market required. It over-called 34. This engine leans loud, and that is the error we would rather have: a false alarm costs attention, a missed call costs the position. Exact tier on 32 of 70, within one tier on 63 of 70. A ratchet in the build stops the exact-tier count falling or the over-calls rising without a traced reason, so the score cannot be improved by shouting louder.
Per-event audit
Generated live from the engine every time this page opens. Each event is replayed, the engine’s reading is captured, and compared against the tier the market actually required. Nothing is typed and nothing is withheld: the events it under-called are in the table, in red.
The audit table renders from a live harness run when this page opens.
The seven events that reach nothing
These are the difference between the two figures above. Three fire a route that no longer carries anything — Nord Stream was severed in 2022 and Yamal-Europe stopped flowing west the same year, so a reading on today’s data finds no crisis because there is no longer a pipe to break. One is a demand event, which this engine does not model. The rest are real gaps in the graph, named as such and worked one at a time; two have been closed this way already, the 2024 Chinese urea export restriction and the 2023 Indian sugar ban, each by building the interface the event actually disrupts.
This table renders from the same live harness run.
What it does not model
- Market sentiment and trader positioning. The engine produces structural shortfall numbers; how spot and forward curves react depends on hedging behaviour, speculation, and macro positioning not captured here.
- Political response. Sanctions packages, military responses, OPEC+ supply decisions, central-bank rate response — all of these depend on political will and are not modeled. The engine assumes a baseline regulatory response only.
- Specific prices. The engine emits a peak price-shock band based on shortfall magnitude and class amplifier. Actual market prices depend on factors the engine doesn’t see.
- Second-order financial effects. Cross-asset contagion, currency moves, credit spreads, equity rotations — not modeled.
- Asset-level operational details. Maintenance schedules, weather windows, force-majeure clause specifics, contractual flexibility — the engine treats each entity as a single capacity unit.
Glossary
- Structural rank
- An ordinal, not a score: where an asset sits among all tracked assets by how much of the system passes through it (concentration × irreplaceability), before any disruption is modelled. Rank #1 is the most load-bearing asset in the graph. It is shown on the verdict panel; no report carries a stress index.
- Asset
- One real, located, disruptable thing: a mine, plant, refinery, terminal, port, pipeline, strait. Every dot on the map is an asset. Companies, countries and markets are not assets; they are columns on an asset or sinks the cascade ends in.
- Node
- Anything the cascade can touch: an asset, a demand sink, a market hub. When a report says a cascade "reaches 21 nodes", sinks and hubs are counted; when it says "assets", only the physical things are.
- Plane
- A commodity at one stage, written Commodity/stage — Copper/mine, Copper/smelter, Copper/refinery are three planes. Every quantity and every world total lives on one plane, so shares are never summed across stages.
- Wire
- A sourced supply relation between two assets, carrying the material that moves along it. Wires are where a disruption travels. A wire names both ends or it is a declared gap, never a guess.
- Order
- How many wires from the disrupted asset a reached node sits: first order is wired directly to it, second order is wired to a first-order node, and so on. Reports print the cascade order by order.
- Tier
- The engine's read of a disruption: minor, moderate, severe, systemic, global. The same five words everywhere — on the map, the verdict panel and every dossier.
- Dossier
- The long-form report on an asset, chokepoint, commodity, country or operator: the whole book, the cascade order by order, the crossings, the time path. The verdict panel on the map is the short read of the same engine run.
- Book and portfolio
- A country's book is everything it holds plus everything wired into it from outside. An operator's portfolio is the set of assets it runs. Both are read from the graph, never from a curated list.
- Tier (Minor / Moderate / High / Severe / Global)
- The composite verdict from the four-signal classifier. Tier captures the magnitude of the disruption’s structural impact; it does not capture probability or duration sensitivity, which are separate dimensions.
- Cascade depth
- The number of downstream entities the disruption propagates through before damping closes it out.
- Substitutability
- Edge-level parameter: how readily a downstream entity can replace the flow it receives from this source. High substitutability dampens cascade; low substitutability amplifies it.
- Mbpd anchor
- The volume of oil-equivalent flow removed by the disruption. Used as the primary anchor signal for tier classification because it has the longest calibration corpus.
- Month-6 sustained
- The residual cascade impact at month six, after the system has had time to adapt. High residual = structural impact persists past initial scramble.
- Trajectory shape
- Categorical descriptor of how the impact decays over time: sharp recovery (most flows back within 6 months), gradual (6–12 months), persistent (residual impact at month 6 remains high), escalation (impact grows over time).
- Annual disruption prior
- The historical frequency, per year, of a disruption matching this entity’s curated event profile. Anchored on 2000–2025 observation; not a forecast.
- Spare capacity damper
- Damping factor reflecting how much idle production capacity exists in the affected commodity class that could absorb the lost flow.
Robustness suite
A 19-stage adversarial test suite covering data integrity, renderer coverage, malicious input handling, type-system attacks, and engine math sanity. Results from the most recent build run.
Re-verified · 2026–09–07 · live graph: chokepoint, country, commodity and operator coverage, and engine breadth | adversarial stages re-run · 2026–09–07 · live build, stage by stage
| Stage | What it tests | Result |
| Data integrity | All curated globals load: entity registries, chokepoint set, historical corpus, country portfolios, engine entry points. | 12 / 12 pass |
| Chokepoint coverage | Every curated chokepoint produces a cascade and renders without exception. | 24 / 24 pass |
| Country coverage | Every country holding a tracked asset renders a portfolio without exception. | 119 / 119 pass |
| Commodity coverage | Every commodity plane in the graph renders without exception. | 229 / 229 pass |
| Operator coverage | Every operator with ≥3 tracked assets renders without exception. | 103 / 103 pass |
| Engine breadth | Cascade engine runs on all wired entities; no exceptions. | 5,411 / 5,411 pass |
| Renderer breadth | Every report family generates for every subject it covers, with exceptions caught rather than assumed. | country 119 · commodity 229 · operator 103 · chokepoint 24 — 0 exceptions |
| Null and wrong-type inputs | 18 null/undefined/wrong-type combinations to the public API. | 11 graceful · 2 loud reject · 5 throw |
| Malformed entity IDs | Path traversal, null bytes, SQL fragments, markup, ghost ids through the cascade API. | 10 / 10 graceful |
| Numeric extremes | 104 severity × duration combinations including Infinity, NaN, negatives and strings. | 48 graceful · 56 loud reject · 0 non-finite output |
| Cross-site scripting | 9 XSS payloads × 4 report generators, DOM-parsed verification. | 0 / 36 executed, 0 injected nodes |
| Unicode chaos | RTL overrides, zero-width joins, BOM, emoji, combining marks, 20k-character ids. | 9 / 9 graceful |
| Prototype pollution | Attempts to mutate Object prototype via crafted input keys. | not polluted |
| Resource exhaustion | 150-entry disruption array, 2,000-deep nested object, 50k-character id. | 70ms · 37ms · 34ms, no slow path |
| State corruption | Mid-run node mutation, graph freeze, a deleted global, verdict stability. | graph deep-frozen, writes rejected, tier stable |
| Pathological types | Symbols, Proxies with throwing getters, getter-on-id throws, array-likes, null-prototype objects, a sparse array declaring a length of one million, a self-referential array. | 3 graceful · 1 loud reject · 4 throw · 0 hang |
| Memory leak probe | 120 sequential engine runs; output-size drift measured byte-for-byte. | drift 0 bytes |
| Regex backtracking | 8 ReDoS-pattern payloads through the id field. | 184 ms total, no slow path |
| Cascade math sanity | No NaN or Infinity in output, cascade weights within [0,1], across 9 probes including the five nodes built today. | 9 sane, 0 insane |
What this run found, stated plainly. Five of the eighteen null/wrong-type inputs throw rather than returning empty: any non-array truthy input, and a non-string id. An earlier version of this table said two array shapes — a sparse array declaring a length of one million, and a self-referential array — hung the engine. That was wrong and is retracted. Measured directly, they return in 417 ms and 6 ms, and the cost is flat from a hundred entries to a hundred thousand. The harness that produced the claim was failing for an unrelated reason, and removing those two probes happened to coincide with fixing it. Publishing a weakness we do not have is the same fault as hiding one we do, so the correction is stated here rather than quietly edited out. The 56 loud rejects under numeric extremes are the input guard working as designed; the previous table counted them as "graceful", which hid them. Everything else held: no XSS payload executed in 36 combinations, the prototype was not polluted, the graph is deep-frozen with node writes rejected and the verdict stable under mutation, 120 sequential runs drifted by zero bytes, and no regex payload found a slow path.