OECD Pillar Two · GloBE Model Rules · Consolidated Commentary (May 2025) Per-jurisdiction ETR · Safe-harbour-aware · Replayable lineage Self-hosted · Postgres + FastAPI + React
G GloBE Top-Up Calculator OrbaOS · Capital governance suite
OECD Pillar Two · GloBE Edition 2026

Top-up tax figures your audit, tax authority, and Big-4 reviewer can replay, jurisdiction by jurisdiction.

A self-hosted GloBE calculator where every top-up flows from raw constituent-entity inputs through Articles 3.2, 4.1, and 5 — with QDMTT / IIR / UTPR routing determined by per-jurisdiction qualified status — and a regulator-ready GIR XML at the end. Drift any input, any line item, any parameter, and the verifier identifies the exact node where the chain breaks.

Institutional infrastructure, not a self-serve product. Access granted after a brief conversation. Marketing pages, doctrine, and verifier explainer are public.

Articles 3 · 4 · 5 GloBE Income · ACT · Top-Up
QDMTT · IIR · UTPR Qualified-status routing
Article 8 GIR XML Regulator-ready export
Calibrated against
OECD Model RulesSide-by-Side Package · Jan 2026 Consolidated CommentaryMay 2025 · Articles 1–10 Safe Harbours PDFTransitional CbCR · §1 Central RecordQualified IIR / UTPR / QDMTT EU Directive 2022/252327 member states UK MTT / DTTHMRC manual
§ 01  Doctrine

Why institutional tax teams choose it

GloBE programmes don't fail on the headline math. They fail because the group's 30+ subsidiary trial balances, the local accountants' calls on Article 3.2 adjustments, and the Big-4 reviewer's independent recompute never agree on which input row produced which top-up — and the GIR you file has no replayable chain back to the source data. This calculator is built on the inverse premise: admissibility before calculation.

/ 01

Admissibility before calculation

A jurisdictional top-up is a node in a Merkle DAG anchored to its constituent-entity input leaves and to the function identity that produced it. Drift any of those — book numbers, schema contract, engine version, regime parameters, Central Record qualified status — and the root hash changes. The verifier identifies the exact node where the chain breaks.

SHA-256 over canonical JSONPure-function verifier
/ 02

Self-hosted on your network

One make up brings up Postgres, the FastAPI backend, an nginx-fronted React UI, and this marketing site on a single host. Constituent-entity financials never leave your infrastructure. Cloud deploy via Railway templates if you prefer.

Docker ComposeOIDC / API keysRetention controls
/ 03

Verified math, falsifiable lineage

Articles 3.2 / 4.1 / 5 / 9 pinned to hand-computed expected values and validated against 32 external scenarios on every PR. Per-jurisdiction qualified status calibrated from the OECD Administrative Guidance Central Record. A stateless verifier replays every figure offline from the saved lineage.

491 tests · CI on every push32 external validation scenarios
/ 04

Three-mode adoption · warn → gate → block

Roll the doctrine out without breaking your existing upload paths. warn observes refusals as data. gate requires a paired-actor override token, scoped and single-use. block fails closed. Every refusal is a first-class, queryable persisted entity — the audit answer to “show me every refused computational state in the last quarter.”

423 Locked · 409 Conflict5-minute scoped tokens
§ 02  Admissibility flow

From constituent-entity ingest to GIR XML, seven steps

A constituent-entity row enters the system only after the caller has been shown its canonical form and echoed the hash back. A jurisdictional top-up is produced only from inputs whose hashes are recorded under a registered function reference. A GIR export ships only when the chain verifies. A refusal is itself a first-class persisted entity.

  1. 01
    POST /uploads/parse

    Parse and canonicalise

    Validates the row against globe_constituent_entity.v2 — 26 fields, every monetary value declared in EUR. Returns the canonicalised payload, payload_sha256, per-row leaf hashes, and a pending_upload_id.

  2. 02
    POST /uploads/{id}/commit

    Echo the hash back

    Only succeeds if the caller echoes payload_sha256 verbatim. Mismatches and double-commits return 409 plus a structured InadmissibilityEvent. On success, rows become provenance_node[input_leaf] + a ConstituentEntity on the filing group.

  3. 03
    GET /filing-groups/{id}/topup

    Articles 3.2 + 4.1 walks

    Per entity, book PBT → GloBE Income via the eight Article 3.2 line items; book current tax → Adjusted Covered Taxes via the four Article 4.1 line items. Filer overrides flow through marked filer_supplied: true. Walks are returned alongside the calc.

  4. 04
    GET /filing-groups/{id}/topup

    Article 9 transitional safe harbour

    Three OR-tests per jurisdiction: de minimis (revenue < €10M and PBT < €1M), simplified ETR (year-indexed threshold — 17% in 2026), routine profits (PBT ≤ SBIE). Once-out-always-out tracked across years. Passing jurisdictions short-circuit to zero top-up.

  5. 05
    GET /filing-groups/{id}/topup

    Article 5 top-up

    ETR = ACT / GloBE Income; top_up_rate = max(0, 15% − ETR); SBIE = payroll×rp + tangibles×rt (year-indexed Article 9.2 schedule); excess = max(0, GloBE Income − SBIE); top_up = rate × excess − QDMTT. Calc emits a Merkle root binding engine + regime + parameter-set hash.

  6. 06
    GET /filing-groups/{id}/topup

    QDMTT → IIR → UTPR routing

    Per-jurisdiction qualified status from the OECD Administrative Guidance Central Record drives routing: QDMTT-qualified source jurisdiction collects locally; else IIR collects at the parent if parent qualifies; else UTPR splits across substance jurisdictions per Article 2.6.2.

  7. 07
    GET /filing-groups/{id}/export/gir.xml

    Article 8 GIR XML

    Returns a regulator-ready GloBE Information Return XML conforming to the OECD Jan-2025 schema. The XML body's SHA-256 + the function-reference SHA + the output-root SHA all surface in response headers — a Big-4 reviewer running the verifier against the saved lineage gets a single yes/no on reconciliation.

§ 03  Three routes, one source-of-truth

QDMTT · IIR · UTPR — routed by qualified status, not by hope

Every per-jurisdiction top-up is routed through one of three mechanisms. Which one applies is a function of OECD-published facts (the Administrative Guidance Central Record), not a filer judgement call. The engine encodes the routing as a deterministic pipeline; the output enumerates exactly which mechanism collected which source.

First in line
QDMTT

Source collects, before anyone else.

If the source jurisdiction has qualified QDMTT in the regime params (IE, GB, NL, DE, JE, BM, KY-no, etc.), it collects the full top-up locally. IIR and UTPR see a residual of zero. This is the dominant outcome for 2026 filers — most low-tax jurisdictions have qualified QDMTT precisely so they collect their own top-up rather than ceding it.

qdmtt_collections[] source-resident
Second in line
IIR

Parent collects, if parent qualifies.

When QDMTT doesn't apply, the ultimate parent's jurisdiction collects the top-up via the Income Inclusion Rule — provided that jurisdiction has qualified IIR. Most EU + UK + CA + AU + JP qualify; US GILTI is not (yet) recognised as qualified IIR by OECD. Single-tier in the MVP; multi-tier ownership chains land in a later phase.

iir_allocations[] parent-collected
Backstop
UTPR

Substance jurisdictions split the rest.

When IIR can't apply (parent not qualified), the Undertaxed Profits Rule splits the unallocated top-up across UTPR-qualified jurisdictions where the group has substance, using ½ payroll-ratio + ½ tangible-assets-ratio per Article 2.6.2. Even-split fallback per Article 2.6.3 when neither denominator is positive.

utpr_allocations[] employee + asset split
§ 04  Adoption path

Three modes, one variable

Set ADMISSIBILITY_MODE on the backend container. The intended adoption path is warn → gate → block. Migration from warn to gate makes every override a paired audit event; migration to block removes the override entirely. Same doctrine as the FRTB calculator — the admissibility layer is regime-agnostic by design.

Default · onboarding
warn

Observe; preserve adoption.

A provenance gap on calc or export proceeds, but persists an InadmissibilityEvent so the gap is observable. Useful for rolling out the doctrine without breaking the legacy upload path.

HTTP 200 OK + event recorded
Operating posture
gate

Acknowledge; pair the actors.

Refuses with 423 Locked unless a single-use override token is presented. Tokens are scoped to (operation, filing_group_id, reason_code), expire in 5 minutes, and require different actors on issuance vs consumption.

HTTP 423 Locked 4-eyes override
Destination state
block

Fail closed. No override path.

Refuses with 409 Conflict. A bearer with a token in block mode still gets 409. Every figure that ships is anchored to a verified root. The doctrine, fully enforced.

HTTP 409 Conflict terminal posture
§ 05  Falsifiable lineage

Five things the verifier catches at the exact broken node

The verifier is a stateless, single-file program. Hand it a saved lineage payload — for an FRTB capital figure or a GloBE jurisdictional top-up, they verify identically — and it recomputes every claimed hash from its claimed payload. Each failure mode below is provable in a unit test against a deliberately tampered fixture. Download verify_lineage.py · Read the verifier explainer →

HASH_MISMATCH

Byte mutation in any leaf or interior payload — flagged at the tampered node, not at the root.

EDGE_LEAF_MISMATCH

A function_node whose payload claims a different set of leaves than its edges actually carry.

EDGE_FUNCTION_MISMATCH

An output_root pointing at a function_node not present in its edges. No silent re-parenting.

FUNCTION_REFERENCE_DRIFT

The function_node's claimed engine + regime + parameter-set hash differs from what the caller expects — silent parameter changes (e.g. a Central Record qualified-status flip) are caught.

ROOT_NOT_IN_NODE_SET

The lineage payload's claimed root has no matching node — orphan root, refused.

All five plus their happy-path counterparts are pinned in test_admissibility_falsification.py on every push. The 32 external GloBE validation scenarios (hand-derived from OECD source documents) re-verify every shipped calc surface on every PR.  ·  Field note: Pillar Two programmes don't burn capital on math →

§ 06  Inside the product

What you see once a credential is issued

The GloBE SPA sits behind authentication in production. Each module corresponds to a tab in the frontend. Click any thumbnail to view full-size.

Top-up tab — KPI strip with total top-up, per-jurisdiction ETR + safe-harbour table, and QDMTT collection routing
Top-up Total group top-up + per-jurisdiction breakdown. KPI strip for total / jurisdictions evaluated / safe-harboured / minimum ETR; per-jurisdiction table with ETR, safe-harbour status, SBIE, and routed top-up.
Per-jurisdiction tab — Article 5 walk with per-entity Article 3.2 and Article 4.1 line items
Per jurisdiction Article 5 walk with every line item visible. Minimum ETR → ETR → top-up rate → SBIE → excess profit → top-up before QDMTT → jurisdictional top-up. Per-entity Article 3.2 and Article 4.1 walks below.
Filing groups tab — list of filing groups + create form
Filing groups Create, list, select. Name, fiscal year, regime, UPE jurisdiction, consolidated revenue. One MNE group per row.
Upload tab — two-step admissibility ingest with the demo CSV loaded
Upload Two-step admissibility ingest. Parse → echo SHA-256 → commit. Byte drift between parse and commit is refused at the API boundary; the hash is shown to the operator before commit.
Explain tab — BYOK provenance-grounded movement explainer
Explain BYOK movement explainer. Compare two filing-group top-up roots; the LLM's output is constrained to hashes the engine can prove are real. Fabricated hashes are refused — refusals surface as first-class evidence, not failures.
§ 07  Deployment

Built to run in your environment

The same engine + admissibility layer that hosts the FRTB calculator hosts this one. Postgres + FastAPI + React, plus this static marketing site. Constituent-entity financials never leave your network. Same Docker Compose, same Railway deploy, same shared Postgres instance — the doctrine layer is regime-agnostic by design.

One command

make up brings up everything: db, backend, FRTB SPA, GloBE SPA, marketing. CORS_ORIGINS pre-configured for the four local ports.

$ make up

One Postgres

FRTB and GloBE share the same doctrine layer (provenance_nodes, provenance_edges, inadmissibility_events, csv_schema_contracts, function_references). Filing groups and portfolios live in different tables but the same DB — one backup, one migration path.

Health-gated

/health returns build, regime, and auth_required. Railway probes it; your monitoring can too.

GET /health → 200

OIDC or API keys

Set REQUIRE_AUTH=true + either BOOTSTRAP_API_KEY or OIDC_ISSUER + OIDC_AUDIENCE. Federated identity flows resolve to oidc:<sub> for audit attribution.

§ 08  Private demo tenant

Experience the doctrine on your group, before procurement.

Not a free trial — a per-prospect, isolated, time-boxed environment with synthetic constituent-entity data shaped like your group footprint and a guided governance-replay exercise. You log in on your own time, work through the exercise, and bring questions to the follow-up call. The tenant tears itself down after the engagement window closes.

What the exercise puts in your hands

Six steps, ~45 minutes. By the end you have personally walked the doctrine end-to-end against an MNE group shaped to your jurisdictional footprint.

  • Upload a constituent-entity CSV — watch the two-step admissibility ingest echo a hash back before commit
  • Compute top-up — receive the Merkle root, per-jurisdiction ETR walk, and QDMTT / IIR / UTPR routing inline
  • Mutate one entity's covered taxes, re-upload — see the verifier flag the exact broken node
  • Flip ADMISSIBILITY_MODE warn → gate — issue and consume a paired-actor override token
  • Run Compare between two filings — download the content-addressed attestation JSON with per-entity attribution
  • Export the OECD GIR XML and run the standalone verify_lineage.py offline against the attestation

How the tenant is scoped

Demo tenants are designed for experiential proof, not architecture exposure. Capability surface mirrors a production install; orchestration internals do not.

  • Dedicated subdomain · isolated Postgres · pre-minted read/write API key
  • Synthetic MNE group shaped to your jurisdictional footprint (UPE, IPE, POPE, JV chains)
  • Auto-teardown after the agreed window (default 14 days); extendable
  • Full lineage explorer · Article 3.2 + Article 4.1 walks · attestation download · GIR XML export
  • Orchestration, parameter-set editing (qualified-status flags), and enterprise connectors are not exposed
  • Download tarballs + production deployment available only after the engagement converts
§ 09  Request access

Tell me about your group.

Filing group size, jurisdictions in scope, fiscal-year start, and where you are in the Pillar Two readiness arc. Mention whether you'd like a private demo tenant first. I'll come back within two business days.

Marketing pages, doctrine, and the verifier are public — no form needed. The form is for a credentialed demo tenant + a working call to scope deployment to your infrastructure.