Where a model processes prompts, and who made it
A model node (nodeType:LanguageModel) carries two marks, and they answer two different questions:
| Mark | Field | Question | Values |
|---|---|---|---|
| πͺπΊ / οΏ½οΏ½π / π / β Processing β the flag | dataResidency (+ dataRetention) |
Where are our prompts processed? | Eu, Global, CH (DataResidency.Switzerland), Unknown β open: any two-letter region code |
| Maker β text, never a flag | modelOrigin (+ modelMaker) |
Who made the model, and where are they based? | ISO country code: CN (Z.ai, Moonshot, DeepSeek, Qwen), US (OpenAI, Anthropic, xAI, Meta, Google), FR (Mistral), CA (Cohere), any other ISO code |
The two marks are independent. GLM 5.3 is made in China and can be processed in the EU; Claude
is made in the US and is processed wherever Anthropic or Azure route it. Both are open
string-constant vocabularies (policy open-vocabulary-string-constants): DataResidency and
ModelOrigin in MeshWeaver.AI.
The rule: only Eu is EU
DataResidency.IsEu is true for Eu and nothing else. Only an unset or blank mark becomes
Unknown. Any other value stays as authored, because the vocabulary is open: CH stays CH,
and so does a typo. None of them ever counts as EU, and each satisfies only a requirement that
names exactly that value.
DataResidency.Satisfies(actual, required) never admits Unknown, even when the requirement itself
names Unknown.
The mark describes the route, not the model:
| Route | Mark |
|---|---|
eu.openrouter.ai (OpenRouter's EU region: only EU provider endpoints) |
Eu |
openrouter.ai, api.openai.com, api.anthropic.com, the makers' own public APIs |
Global |
Azure, DataZoneStandard or regional Standard SKU in an EU-region resource |
Eu, but only when declared |
Azure, GlobalStandard |
Global, declared |
| Azure, undeclared | Unknown: the same host serves every SKU, so the host alone proves nothing |
| Claude in Microsoft Foundry | Global. Foundry offers Claude as Global Standard, plus a Data Zone for the US only. There is no EU zone. |
Where the marks come from
The model node's own dataResidency is the only value any consumer reads. The picker badge,
the provider page, tier resolution and the round's refusal all read it, so they cannot disagree.
The emitters seed it with ModelProvenance.Seed, and a value authored on the node always wins:
- Declared by the deployment.
{Section}:DataResidencyand{Section}:DataRetentionapply to every model of that catalog section, e.g.AzureFoundry__DataResidency=Eufor a DataZone-only account. - Implied by the endpoint (
DataResidency.FromEndpoint), for the hosts in the table above. - Otherwise unset, which reads
Unknown.
The maker and its country are inferred from the id. The org slug is tried first (z-ai/,
moonshotai/, anthropic/), then the family token (Kimi-K2.6, claude-haiku-4-5,
DeepSeek-V4-Flash). An id nothing recognises stays Unknown; the platform never guesses.
A ModelProvider node carries dataResidency / dataRetention too. This is a seed for the
models the provider creates, never a verdict. The built-in provider node is create-if-absent, so a
mark added to its configuration later reaches its model children, which are synced, and not the
provider node itself.
Where the marks show β ONE flag, and it is the processing location
π© A model, a harness or a route shows exactly one flag, and it says where prompts are processed
(maintainer, 2026-11-08: "eiger serves the qwen with chinese flag ==> convert to swiss flag").
Until then every row carried two badges, the processing mark and the maker's flag. A Qwen served
by a Mac Studio in Switzerland from its own Ollama showed π¨π³, which a reader takes for "my prompts
go to China" although nothing left the machine. GLM 5.3 through eu.openrouter.ai did the same.
The maker's flag never stands in for the processing location again:
dataResidency |
Flag (DataResidency.Glyph) |
|---|---|
Eu |
πͺπΊ |
CH |
π¨π β and any other two-letter code shows its own flag (SE β πΈπͺ) |
Global |
π |
Unknown, blank, or anything that is not a region code |
β β neutral, never πͺπΊ |
The maker moves to the tooltip, on a second line, and to a text column: "Processed in Switzerland
only" / "Alibaba (Qwen) β model maker based in China". One helper builds the badge for every
surface, ModelProvenance.Mark, and ModelOrigin.Label gives the maker as text
("Alibaba (Qwen) Β· CN"). There is no maker-flag helper any more.
- The model picker (
/modelin the composer) and the thread's/harnesspicker: one badge per row, tooltip and accessible name in the viewer's language. - The Threads app's harness cards: the same mark as one line.
- The provider page (Settings β Providers β a provider): Processing (flag + sentence) and Model maker (text) columns.
- The tier map (below), at the top of
/Provider/AiModelTiers. - The thread header, the token-usage tab and the React Native app render no provenance flag, so there was nothing to convert there.
- All text comes from
[Description]/[Translation]declarations on the constants and onModelProvenanceText, in English and German.
A locally served model carries its HOST's residency
A model served by the instance's own endpoint, or by a fleet Mac through the token queue, is
processed where that machine is. The install DECLARES it: OpenAICompatible:DataResidency
(env OpenAICompatible__DataResidency) is stamped on every Provider/OpenAICompatible model, by
the declared catalog at boot (static Models[]) and by the discovery sync
(OpenAICompatibleModelSync), which also back-fills a node created before the declaration existed.
It back-fills only a node that carries no mark, so an authored mark always wins. A fleet Mac states
its residency on the token queue (ModelRelay:Devices:N:Residency), and an instance refuses a
device whose declared residency does not match what it states.
On a memex-local install the declaration is the install's own: memex-local asks for it at
onboarding and writes it into the per-install model layer (MeshWeaver.Deploy). eiger (a Mac Studio
in Switzerland) declares CH in its overlay since 2026-11-08, so its qwen3.8:27b-mlx and
qwen3.6-code show π¨π. CH is not Eu: an EU-only instance correctly refuses them.
The tier map β which model serves each tier
/Provider/AiModelTiers opens with the tier map (ModelTierMap, area AiModelTierMap), a
framework DataGrid that resolves every tier live on the instance (utility, chat, reasoning,
coding, review, plus any tier the deployment added). It applies the same resolver, catalog,
configuration, ceiling and residency requirement a round uses. Per tier it shows:
- the model that runs, its route (provider node Β· endpoint host), its processing flag and its maker;
- which rung answered (the tier: a model labelled with it or the instance's choice; the configured
seed
AI:Tiers:*/ModelTier:*; or the deployment default because no model carries the tier); - the fallback chain: everything that takes over, in order (
ModelTierCatalog.Chain, whose first entry is pinned to be what resolution returns); - the region the instance requires.
Its Check column flags a tier that resolves to nothing (β, every round on it fails), a model whose mark does not meet the instance's requirement (β ), and a model with no declared processing location (β).
Requiring EU: fail closed
A requirement is set in one of two places. When both are set, both apply.
| Who | How | Effect |
|---|---|---|
| The instance | AI:RequiredDataResidency=Eu (env AI__RequiredDataResidency) |
The picker hides the instance's models not marked Eu. The default model, tier resolution and Auto skip them. The round refuses them, and so does the image generator. |
| An agent | front matter requiredDataResidency: Eu (AgentConfiguration.RequiredDataResidency) |
Tier and Auto resolution for that agent skip non-Eu models. A round of that agent on one is refused, including a hand-off to it. |
The refusal happens before any prompt leaves the process. The user sees a localized sentence
naming the model, its mark and who requires EU, and the refusal is logged at Warning. An explicit
pick of a non-admitted model is healed onto an admitted one, the same way an unusable pick is
healed. When none is admitted, the round is refused; it never falls back to a Global model. A bare
model id that matches several catalog entries with different marks reads Unknown: which entry
would serve it cannot be promised.
"No endpoint" never means "a US default". Under the instance switch, every request is also
checked at the point where it is built, by ChatClientCredentialResolver.InstanceRouteRefusal
(called by the OpenAI, Azure OpenAI, Anthropic and Azure Foundry factories and by the image
generator). A request with no endpoint is refused, because the OpenAI SDK would fall back to
api.openai.com and the image generator would use the same host. A request whose endpoint is a
known global host is refused too. An Azure host passes this check: the model node's own mark was
already checked. Listing a provider's models (ProviderModelLister, against the maker's API)
sends no prompts and is not gated.
What the instance switch does NOT cover:
- Per-user bring-your-own-key models (
{user}/_Memex/β¦,{user}/_Provider/β¦,ModelProvenance.IsPersonal) stay allowed and visible. They are still marked: a BYOK model is never seededEu. It readsGlobalfor a known global host andUnknownotherwise, because the person's account settings are theirs and not established here. - CLI harnesses (Claude Code, Copilot, Codex) run on the person's own subscription, straight to
Anthropic, GitHub and OpenAI. The maintainer decided they stay. They count like BYOK: allowed,
and marked NOT-EU (
Global) with originUS. - An agent requirement applies to every model, BYOK included.
Code review (policy code-review-eu-only): the reviewer's model is bound to
Provider/OpenRouterEU (eu.openrouter.ai) with a pinned providerRouting region, which the
review-binding change owns (MeshWeaver.Plugins#2446). Its DataResidencies.EU value "EU" reads
as Eu here, because the comparison is case-insensitive. The agent-level marker
requiredDataResidency: Eu is not set on Governance/Agent/reviewer yet, and that is deliberate.
That agent also reviews every governed activity, and no model on the control instance is marked
Eu today. Declaring the requirement now would refuse every review, including the approvals the
elimination below needs. Set it in the same change that marks the EU review model.
Pinned by:
DataResidencyRoundTest: on an EU-only instance, the provider is never called for a Global or an unmarked model. The negative control (the gate disabled) fails both cases.ModelProvenanceTest: the vocabulary, the seeding, the BYOK exemption, the route guard and the localized texts.
What a fleet audit found (2026-09-27)
A read-only audit covered every deployment record on the control instance, the
LanguageModel/ModelProvider nodes on each portal instance, every Azure AI Services account
(az cognitiveservices account deployment list, subscription explicit), and the OpenRouter EU
region (https://eu.openrouter.ai/api/v1/models/<id>/endpoints). The per-instance rows are
operational data and are not kept in this generic page; what generalises is below.
No chat or embedding model served by any instance was EU-only. The only EU-only rows were an
in-cluster speech model (a self-hosted Whisper pod) and two Azure deployments that no instance
referenced (one DataZoneStandard, one regional Standard).
- Every OpenRouter model on the global endpoint (
openrouter.ai) isGlobal, whoever's key it runs on, and none had a ZDR provider filter set. - Claude in Microsoft Foundry is offered in swedencentral as GlobalStandard only, and
claude-haiku-4-5v20251001 ishostedOn=anthropic, so it may be processed outside Azure. - Azure deployments were almost all
GlobalStandard, soGlobal. A provider section with an empty endpoint, or an embedding endpoint the record does not declare, readsUnknown. - CLI harnesses (Claude Code, GitHub Copilot) read
Global/Unknownas described above. - A client estate with its own Azure account can offer model names that account does not deploy β the provider node lists them, and a call to them fails. Worth checking on every audit.
Bring-your-own keys live as ModelProvider nodes at {user}/_Memex/<Provider>, with their models
at {user}/_Provider/<Provider>/<model> and the key stored enc:v1:. They are never seeded
Eu: a known global host reads Global, and anything else reads Unknown. Row-level security
hides other users' BYOK nodes, so an audit counts only the auditor's own.
Not established by the audit
- The running pods' configuration. The records are not the pods. Overlay-only helm keys and live environments were not read.
- Embeddings on client instances. One client record declares no
Embedding__*key; another client estate has no record on the control instance, so which embedding deployment it uses is probable but not proven. - Retention. It was not checked whether any Azure account has approved modified abuse
monitoring (zero retention), whether OpenRouter has account-level ZDR or provider filters, or
what Inceptron's terms are. On GLM 5.3, the EU Mistral endpoint is tagged
nvfp4, notzdr. - Inceptron's location. OpenRouter lists it in its EU region, and that is the only basis for calling it EU.
- GitHub Copilot CLI residency was not researched, so it is
Unknown. The build instance's mesh was not reachable.
A second compliant provider (2026-10-04)
On 2026-10-04 one OpenRouter key's daily limit (HTTP 403: Key limit exceeded) closed the control
instance's only Eu/ZDR provider at 14:47Z, and every review and agent round waited until the
next UTC midnight. The admission falls back by default (AgentAdmission Β§7),
but a fallback keeps the round's marks β an Eu round moves only to an Eu model, a ZDR
round only to a ZDR one, and the instance's AI:RequiredDataResidency binds every target β so it
needs a second provider that carries the same marks. Under this page's rules, none does yet.
What qualifies. A model node marked dataResidency: Eu and carrying the same
dataRetention as the round it stands in for (ZDR on every model of the OpenRouter EU route,
declared by its section). The marks must be true of the route, not hoped for.
| Candidate | Reading | Admissible on an EU-only instance? |
|---|---|---|
Anthropic direct (api.anthropic.com) |
Global by its endpoint (DataResidency.FromEndpoint) β a maker's public API, which this page never reads as EU |
No. The round refuses it before sending, and the fallback never offers it. It may serve only an instance or lane with no EU requirement. |
| Claude in Microsoft Foundry | Global Standard, plus a US-only Data Zone (above) | No. |
Azure, GlobalStandard deployments (every chat deployment on our EU-region account, measured) |
Global |
No. |
Azure, DataZoneStandard in the EU-region resource |
Eu once declared. The region offers it for tier members gpt-6-sol, gpt-6-luna, Mistral-Large-3, DeepSeek-V4-Flash (az cognitiveservices model list); the only such deployment today is an older reasoning model in no tier |
Residency yes, retention no β see below. |
| A second key on the OpenRouter account | The same EU route, the same marks | Yes, but it is the same provider and the same account: it survives a per-KEY limit, not an account-credit limit or an OpenRouter outage. |
Retention on Azure is not ZDR by default. Azure OpenAI's abuse monitoring stores prompts and
completions for up to 30 days (in the resource's geography) unless Microsoft has approved
modified abuse monitoring for the resource, which then lists the capability ContentLogging
with value false. Our account lists no ContentLogging capability (read with
az cognitiveservices account show β¦ --query properties.capabilities), so a DataZone deployment
there is Eu with retained prompts: it must be marked with its true retention, and the fallback
then does not offer it to a ZDR round.
The provider node on the control instance (Provider/AzureFoundry) has a key bound but no
endpoint and no models, so it serves nothing: a request with no endpoint is refused at build on an
EU-only instance (InstanceRouteRefusal).
Proposed (the maintainer's decision β creating cloud resources is not an agent's call)
- Deploy the tier members as
DataZoneStandardin the EU-region resource:gpt-6-sol(heavy),gpt-6-luna(light), andMistral-Large-3orDeepSeek-V4-Flash(standard). The cheapest useful set isgpt-6-sol+gpt-6-luna: they are the SAME models the EU route serves, so the fallback takes them first. - Apply for modified abuse monitoring on that resource. Only once the account shows
ContentLogging: falsemay its models be markeddataRetention: ZDR. Until then they are marked with their real retention, and they keep the fleet alive only for rounds that do not requireZDR: on the control instance, none, because every EU-route model declares it. Admitting EU processing with EU-stored abuse monitoring for some lane would be a policy decision, not a marking. - Seed them as their OWN catalog section, marked per model. Never set
AzureFoundry__DataResidency=Euon a section that also listsGlobalStandarddeployments: a section declaration marks every model of the section. Prefer a governedCreateNodestandard per model (as Dispatch's models are created) withdataResidency: Euand the measureddataRetentionon the node, and an endpoint that is the EU resource's. - Meanwhile: raising the OpenRouter key's daily limit, or a second key with its own limit, keeps the same compliant route and needs no new residency claim.
Pinned by DefaultAlternativesTest (the fallback keeps the marks; with no compliant second
provider a round waits rather than leave the route; with one, a closed key fails over to it).
Proposed elimination (not executed)
Every change below is a record change or an Azure deployment change. Each goes through a governed
Hosting/InstanceAction / Governance/Activity on the control instance, and each needs the
maintainer's approval. Nothing here has been applied.
The target tiers, as the maintainer decided, are all served through eu.openrouter.ai on our
OpenRouter account:
| tier | model | EU providers |
|---|---|---|
| heavy | anthropic/claude-opus-5.5 |
Amazon Bedrock eu-west-1, Google Vertex europe |
| standard, review | z-ai/glm-5.3 |
Inceptron, Mistral |
| light | openai/gpt-6-luna |
Azure (eu) |
| utility | mistralai/mistral-small-2603 |
Mistral (eu) |
These apply to every instance that runs on our OpenRouter account β Systemorph's own portal instances and the SME client instances hosted on them, which have no key of their own.
An enterprise client with its own OpenRouter account is out of this scope. Its models are its own to choose. They are marked the same way, with processing decided by its own route.
- Route the tiers above through the EU region. Use an
OpenRouterEUprovider section athttps://eu.openrouter.ai/api/v1, which is markedEuby its endpoint. It is config-seeded, and its chart and Hosting rendering are owned by the fleet-switch work. - Drop or mark the models with no EU route:
moonshotai/kimi-k3,openai/gpt-5.2,google/gemini-3.1-pro-preview,google/gemini-3.7-flash,deepseek/deepseek-v4-pro,x-ai/grok-4.6and every Qwen model. None of them has an EU provider on OpenRouter. The tiers above replace them; any that stay offered are markedGlobal. - Embeddings: deploy
text-embedding-3-smallas DataZoneStandard on our Azure AI Services account (offered in swedencentral) and pointEmbedding__Endpointthere. It is the same model, so no re-index is needed. The alternative ismistralai/mistral-embedon eu.openrouter.ai, which does need a re-index. - Claude in Foundry has no EU zone. The heavy tier moves to Claude through eu.openrouter.ai.
Any Foundry Claude still offered is marked
Global. - Azure GlobalStandard deployments on our accounts: redeploy as DataZoneStandard where
swedencentral offers it (
gpt-5-mini,gpt-5.4,Mistral-Large-3,DeepSeek-V4-Flash2026-04-23). Mark the rest only. Delete the unreferenced deployments. - Declare the marks on the records:
{Section}__DataResidencyper provider section (Anthropic__DataResidency=Global;AzureFoundry__DataResidency=Euonly once its deployments are DataZone or regional), andAI__RequiredDataResidency=Euon each instance that must be EU-only. π¨ Measured on core main: the portal chart renders none of these keys yet, and it renders noOpenRouter__EndpointorOpenRouterEU__*either. Its ConfigMap names every key explicitly, so a record that sets them reaches no container until the chart adds them.
Incidental findings from the audit, not about residency:
- A provider node can list model names with no deployment behind them (stale after a model retirement, or never deployed in that account); the call fails, the picker does not know.
- The records named
anthropic/claude-opus-5.5where the meshes listedanthropic/claude-opus-5.
Audit 2026-11-08: every declared model and every tier, per instance
Read-only audit of every LanguageModel, ModelProvider and ModelTier node on the public, control
and company instances (over MCP) and on eiger (its own database and overlay), against the deployment
records. No EU-only instance resolves any tier to a non-EU route, and no tier resolves to nothing.
Models whose mark disagrees with their route
| Instance | Model | Route | Declared | The route implies | Shown before β after this change |
|---|---|---|---|---|---|
| the public instance | Provider/OpenRouter/moonshotai/kimi-k2.7-code |
openrouter.ai |
blank | Global | β + no maker β β |
| the public instance | Provider/OpenRouter/qwen/qwen3.8-flash |
openrouter.ai |
blank | Global | β β β |
| the public instance | Provider/OpenRouter/qwen/qwen3.8-27b |
openrouter.ai |
blank | Global | β β β |
| the company instance | Provider/OpenRouter/moonshotai/kimi-k2.7-code |
openrouter.ai |
blank | Global | β β β |
| eiger | Provider/OpenAICompatible/qwen3.8:27b-mlx, qwen3.6-code |
the Mac's own Ollama | blank β CH (declared 2026-11-08) |
CH | β + π¨π³ β π¨π |
The four Provider/OpenRouter/* nodes were created by hand in September, before residency seeding
existed. No deployment record declares them, so they have no declared source of truth to fix. The
EU filter already refuses them on both EU-only instances, so routing is unaffected and only the
badge is wrong. The owner decides between deleting them as undeclared (they also sit outside the
company instance's ceiling) and declaring OpenRouter models in the record with
OpenRouter__DataResidency: Global. Provider/OpenRouter itself carries no Global seed on those
two instances (the control instance's does).
Every other model is consistent: all Provider/OpenRouterEU/* nodes on the three AKS instances
(14, 15 and 15) are Eu. The company instance's in-cluster Ollama qwen3.6 is Eu, which matches
OpenAICompatible__DataResidency: Eu and the fleet's EU region (inferred from the infra parameters,
not read from the cluster). None of the four instances has an Azure model node, so no Azure SKU
question arises. The one client record that deploys Azure models uses only DataZoneStandard in the
EU data zone.
Tier map per instance
| Instance (requirement) | utility | chat | reasoning | coding | review |
|---|---|---|---|---|---|
the public instance (Eu) |
πͺπΊ mistral-small-2603 Β· Mistral AI, FR Β· config | πͺπΊ gpt-6-luna Β· OpenAI, US Β· config | πͺπΊ glm-5.3 Β· Z.ai, CN Β· config | πͺπΊ claude-opus-5.5 Β· Anthropic, US Β· config | πͺπΊ glm-5.3 Β· default |
the control instance (Eu) |
πͺπΊ mistral-small-2603 Β· config | πͺπΊ gpt-6-luna Β· config | πͺπΊ glm-5.3 Β· config | πͺπΊ claude-opus-5.5 Β· config | πͺπΊ glm-5.3 Β· default |
the company instance (Eu, seed-and-ceiling) |
πͺπΊ OpenAICompatible/qwen3.6 (in-cluster Ollama) Β· Alibaba (Qwen), CN Β· config |
πͺπΊ gpt-6-luna Β· config | πͺπΊ glm-5.3 Β· config | πͺπΊ claude-opus-5.5 Β· config | πͺπΊ glm-5.3 Β· default |
| eiger (none) | π¨π qwen3.6-code Β· default | π¨π qwen3.8:27b-mlx Β· AI__Tiers__chat |
π¨π qwen3.6-code Β· default | π¨π qwen3.6-code Β· default | π¨π qwen3.6-code Β· default |
All the AKS-instance models route through eu.openrouter.ai except the company instance's
utility tier. Fallback chain on the EU-only instances: the configured model, then the
deployment default glm-5.3 (order -2), then the company instance's qwen3.6, then the order-7
EU set (Claude, DeepSeek, Gemini, Mistral, Kimi and GPT on OpenRouterEU). Every entry in that
chain is Eu. On eiger each tier falls back to the other local Qwen, both CH.
Notes on the mapping:
- No model on any instance carries a
tierlabel, and no tier node carries amodelchoice, so every tier is answered by configuration or by the default. reviewmatches no configuration key anywhere and always falls to the default. It lands onglm-5.3because the EU filter skips the public instance's lower-ordered, unmarkedOpenRouter/qwen/qwen3.8-27b.- On eiger a code-tuned model answers
reasoningandreview. That is a quality note, not a residency one.
Not established by this audit
- No rounds were run, so credential usability is assumed from the node shape. The tier map on the page shows the live answer.
- The running image of each instance was not checked. eiger's
chatrow assumes its image readsAI__Tiers. - The effective pod configuration on the AKS instances was not read; the values come from the
records on
main. - Personal bring-your-own-key models, the build instance and client instances were not read live.