Mode — how much data leaves
Chokepoint · clampForSchemaOnly() in lib/parser.ts, applied at the HTTP edge in every /api/v1 route that accepts sample rows.
Routing
How much of your data leaves, which model catalogue is eligible, and which jurisdiction the work may stand in. They are three separate axes, they are resolved in one place each, and the answer is on the response — not in a support ticket.
Three axes
Conflating these is the classic mistake: “full-data” does not mean “PHI”, and “PHI” does not mean “EU”. Each axis has its own resolver, its own default, and its own failure direction.
Chokepoint · clampForSchemaOnly() in lib/parser.ts, applied at the HTTP edge in every /api/v1 route that accepts sample rows.
Resolver · resolveRunPhi() in lib/agreements.ts, threaded as phiOverride into match(), runTransform() and runReshapeRequest().
Rule · Zeroing the region on a standard run made every standard code-strategy reshape fail. It is pinned on both modes now — see /network.
The decision
Until 2026-09-01 an unconfigured workspace defaulted to PHI. That was reversed: standard is now what you get, and PHI is an explicit opt-in alongside accepting the BAA. Every fail-soft path resolves to standard too — an unreadable settings row must never silently upgrade unknown traffic into a surcharge and an agreement gate.
One resolver
resolveRunPhi(tenantId, requested) → lib/agreements.ts
What goes on the wire
Both branches call the same phi-cloud endpoint. The difference is two headers and whether we name a model at all. A standard call carries a concrete pinned id and the region that serves it; a PHI call carries the data class and the jurisdiction and lets the gateway that holds the BAA make the pick.
The allowlist sits underneath both: MAPR_PHI_ALLOWED_HOSTS names the hostnames permitted to receive full-data traffic, and in production an unset allowlist refuses rather than permits. See the fail-closed gates.
# Standard routing — the default for an unconfigured workspace.
POST /v1/chat/completions → phi-cloud
X-Region: US # the region that SERVES the pinned id
model: inception-mercury-2 # low rung, resolved by modelFor()
# no X-PHI header at all
# PHI · enterprise routing — only after the BAA is accepted in-app.
POST /v1/chat/completions → phi-cloud
X-PHI: true # forces the PHI-eligible catalogue
X-Region: CH # the workspace pin
model: auto # phi-cloud picks, in-regionThe general ladder
Non-PHI work runs on models we pin by id. The rungs are a capability and latency ladder, not a price ladder — and the ids are pinned precisely so nobody, including us, can quietly re-route them.
| Rung | Model | When it runs | Override |
|---|---|---|---|
| low | inception-mercury-2 | The default. Most turns, and every call that names no tier. | MAPR_GENERAL_MODEL_LOW |
| mid | zai-glm-5-3-flash | One real piece of work. | MAPR_GENERAL_MODEL_MID |
| high | zai-glm-5-3 | The rung a tier:"quality" codegen or critic turn is promoted to. | MAPR_GENERAL_MODEL_HIGH |
Every general call also ships X-Region: US, because those model rows serve US and a region-less call matches nothing. Set MAPR_GENERAL_MODEL_REGION to change it, or MAPR_GENERAL_LADDER=off to fall back to a single configured model everywhere.
Consequence · A pinned id must ship the region that serves it. Without X-Region the request reads as WORLD, matches no model, and auto-routes — a 200 from a model nobody chose.
Where · lib/models.ts. Override per rung with MAPR_GENERAL_MODEL_LOW / _MID / _HIGH, or turn the ladder off entirely with MAPR_GENERAL_LADDER=off.
Where · modelFor() is the one resolver both policies go through, so a call site cannot let them drift apart.
Where · rungForTier() maps the tier hint to a rung; MAPR_CODEGEN_TIER controls it, and “none” disables the promotion.
What routing costs
Not the routing it asked for, and not the policy the workspace has set. If a run was downgraded to standard for any reason, it is billed as standard and flagged as downgraded — that is a compliance rule wearing a pricing rule's clothes.
| What is charged | Rate | Notes |
|---|---|---|
| Every map, deterministic or not | Flat per-map fee (~$0.001) | Charged even when the cascade resolves every column without touching a model, and on a layout-fingerprint cache hit that uses no AI at all. |
| AI cleanup, convert, reshape | Provider cost × 2 | The AI tokens actually consumed. × 0.5 when you bring your own LLM key. |
| Excel macro execution | Per second, five-second floor | Only when you ask for a procedure to be run in real Excel. Authoring, linting and the read-back check are not metered per second. |
| PHI · enterprise routing | +20% on the whole charge | Flat fee included. Applied only when the run actually routed as PHI — see the rule below. |
Figures are the defaults in lib/pricing.ts, the single source of truth, and every one of them is environment-tunable. There is no free tier: the wallet is prepaid, from a $10 minimum, and shared across the phi-cloud suite.
# The kill switch that makes this rule necessary.
MAPR_RESHAPE_DISABLE_PHI=1
# It strips X-PHI from the sandbox execution call. The run therefore
# did NOT go through the PHI path, so effectiveRunPhi() returns false:
charge standard rate, no 20% uplift
audit payload phi_downgraded: true
response a user-visible warning saying so
# Charging a BAA premium for a run that bypassed the BAA gate is a
# claim we cannot make — /pricing sells the uplift as "routed
# in-region under a BAA", and this run was not.Why this matters
The 20% is sold as “routed in-region under a BAA”. If an operator kill-switch strips the PHI header from a sandbox execution, that particular sentence stops being true for that particular run — so the run is charged at the standard rate, phi_downgraded lands in the audit payload, and you see a warning in the result.
It would have been easier to bill the requested policy. It would also have been an invoice line describing something that did not happen. See the full pricing model and the BAA gate.
Routing, per run
Flip the switch per run in the Workbench, or send phi_mode in the request body. Either way the gate reads your acceptance before anything moves.