Mímisbrunnr — the well of wisdom at Yggdrasil's roots, guarded by Mímir, where Odin traded an eye for a single drink of it.
Image credit: @norsemythologyclips — go follow them.
The reference-data store of the Norse Architecture — Norse.Reference.Data: the generated, browser-supported Reference.Data.Contracts and Reference.Data.Namespaces surfaces, the Reference.Data.EntityFramework entities and view models, TSV seeders (HyperTabular), and the Reference.Data.EntityFramework.Migrations/.PostgreSQL/.SqlServer family for canonical external-standard data. First tenants: ISO country codes, ISO currency codes, and IANA time zones. In the dependency chain it rides on Urðarbrunnr's EF foundation and everything below; Mímir rides on it.
Arrows point at the thing depended on. Dashed arrows are the realm's own source generator mounted as a build-time analyzer, not a compile dependency — its output compiles into the consuming assembly, so package consumers receive generated code, never the generator. The shape below is deliberately congruent with Himinbjörg's chart: this is the persistence-consumer stencil every norse_{context} realm follows.
flowchart BT
subgraph Mimisbrunnr["Mímisbrunnr — Norse.Reference.Data"]
MigrationsPg["Reference.Data.EntityFramework.Migrations.PostgreSQL"]
Migrations["Reference.Data.EntityFramework.Migrations"]
EntityFramework["Reference.Data.EntityFramework"]
RefPrimitives["Reference.Data.Contracts"]
Namespaces["Reference.Data.Namespaces"]
Generator["Reference.Data.Contracts.Generator"]
end
subgraph Asgard
Backend["Abstractions.Backend"]
Emit["Abstractions.Emit"]
end
subgraph Urdarbrunnr["Urðarbrunnr — Norse.Persistence"]
PEFPg["EntityFramework.PostgreSQL"]
PEFMigrations["EntityFramework.Migrations"]
PEF["EntityFramework"]
end
subgraph Svartalfheim["Svartálfheim"]
Primitives["Norse.Primitives"]
end
EntityFramework --> RefPrimitives
EntityFramework --> Backend
EntityFramework --> PEF
RefPrimitives --> Primitives
Migrations --> EntityFramework
Migrations --> PEFMigrations
Migrations --> Primitives
MigrationsPg --> Migrations
MigrationsPg --> PEFPg
RefPrimitives -.-> Generator
Namespaces -.-> Generator
Generator --> Emit
Reference.Data.EntityFramework.Migrations.SqlServer mirrors the PostgreSQL leg edge for edge (Reference.Data.EntityFramework.Migrations + Urðarbrunnr's EntityFramework.SqlServer) and is left off the chart for legibility, same as Himinbjörg's. Design-time-only references (NorseDesignRef on EntityFramework.Design, carried by both provider legs) stay off runtime charts. tools/SeedTool is dev-only tooling, never packed, and charts nothing.
The first seed case — UN M49 reference data (Region/CountryOrArea) — has its raw-source-to-TSV conversion tooling live: tools/SeedTool (a dev-only console app, never packed or AOT-published) reads seeds/raw/UNSD — Methodology.csv via HyperTabular (header-first, every column resolved by name) and produces the curated seeds/region.tsv/seeds/country-or-area.tsv, both committed as this realm's real seed data. The EF entities (Region, CountryOrArea, the RegionNode hierarchy), ReferenceDbContext, the InitialCreate migration (temporal apparatus and all), NorseReferenceMigrationContributor, and ReferenceDataSeedContributor are all live and load these TSVs into norse_reference (specced in Glitnir's docs/Mimisbrunnr/). Everything beyond this first seed case (currency, language, script, locale, timezone — see the ERD sketch below) remains unconverged; design happens first: brainstorm → spec → plan, recorded in Glitnir's docs/Mimisbrunnr/, before any further project is scaffolded here.
Both root tables carry Urðarbrunnr's ITemporalEntity marker — and that marker plus a re-issued migration is the entire adoption. This repository contains zero hand-written temporal SQL. ISO/UN canon is static data that changes rarely, and the record of when it changed — a country renamed, a code redenominated, a region re-parented — is exactly what system-time history is for. There is no non-temporal side here: the realm holds no secret stores, counters, or prunable runtime state. The owned CountryOrAreaView jsonb document graph takes no marker of its own, because owned and JSON-mapped types sit outside the temporal contract and the view column's contents ride the owner's history like any other column.
On PostgreSQL the apparatus is a database-owned system_period, a {table}_history table under a WITHOUT OVERLAPS primary key, a SECURITY DEFINER versioning function with insert/update/delete triggers bound to it, and a {table}_timeline view; on SQL Server it is engine-native SYSTEM_VERSIONING = ON. Seeding never versions — an INSERT opens a version, it does not close one — so the TSV seed mints zero history rows and every seeded row is a current version. The first amendment to a seeded row is the first history row.
erDiagram
region {
char(3) un_m49_code PK
varchar name
char(3) parent_m49 FK
smallint level
}
country {
char(2) iso_3166_1_alpha2 PK
char(3) iso_3166_1_alpha3
char(3) iso_3166_1_numeric
char(3) un_m49_code FK
varchar common_name
varchar official_name
bool is_independent
bool is_active
}
subdivision {
varchar iso_3166_2_code PK
char(2) country_alpha2 FK
varchar name
varchar type
}
language {
char(3) iso_639_3_code PK
char(2) iso_639_1_code
varchar name
char(4) iso_15924_script FK
varchar scope
varchar lang_type
}
script {
char(4) iso_15924_code PK
varchar name
smallint unicode_number
varchar unicode_alias
}
locale {
varchar bcp47_tag PK
char(3) language_code FK
char(4) script_code FK
char(2) country_alpha2 FK
varchar display_name
varchar number_format
varchar date_format
varchar first_day_of_week
}
currency {
char(3) iso_4217_code PK
varchar name
varchar symbol
smallint minor_unit
bool is_active
}
country_currency {
char(2) country_alpha2 FK
char(3) currency_code FK
bool is_primary
}
country_language {
char(2) country_alpha2 FK
char(3) language_code FK
varchar status
}
timezone {
varchar iana_key PK
varchar canonical_key FK
char(2) country_alpha2 FK
varchar region_hint
bool is_canonical
}
utc_offset {
varchar iana_key FK
varchar offset_code
smallint offset_minutes
varchar abbreviation
bool is_dst
date valid_from
date valid_until
}
calling_code {
serial id PK
char(2) country_alpha2 FK
varchar e164_prefix
bool is_primary
}
region ||--o{ region : "parent"
region ||--o{ country : "contains"
country ||--o{ subdivision : "has"
country ||--o{ country_currency : "uses"
country ||--o{ country_language : "speaks"
country ||--o{ timezone : "observes"
country ||--o{ calling_code : "assigned"
currency ||--o{ country_currency : "used by"
language ||--o{ country_language : "spoken in"
language }o--|| script : "written in"
script ||--o{ locale : "used by"
language ||--o{ locale : "defines"
country ||--o{ locale : "applies"
timezone ||--o{ utc_offset : "has rules"
timezone }o--o| timezone : "alias of"
Both provider migrations projects (src/Reference.Data.EntityFramework.Migrations.PostgreSQL, src/Reference.Data.EntityFramework.Migrations.SqlServer) carry a design-time factory that supplies an inert placeholder connection string, so the EF CLI runs entirely offline — no database, no network, ever. Applying migrations against a real database is the migrations service's job, not this CLI's.
First, restore the pinned dotnet-ef tool:
dotnet tool restore
Then, per provider:
dotnet ef migrations add <Name> --project src/Reference.Data.EntityFramework.Migrations.PostgreSQL --startup-project src/Reference.Data.EntityFramework.Migrations.PostgreSQL
dotnet ef migrations add <Name> --project src/Reference.Data.EntityFramework.Migrations.SqlServer --startup-project src/Reference.Data.EntityFramework.Migrations.SqlServer
Every add (and remove) auto-refreshes the provider's embedded schema/norse_reference.sql — that file is DDL emitted by the scaffolder, never hand-edited.
Platform law (squash migrations until the provider-defaults chassis settles) keeps exactly one InitialCreate per provider. A schema change is not a new migration stacked on top — delete the provider's Migrations/ folder and re-add InitialCreate:
rm src/Reference.Data.EntityFramework.Migrations.PostgreSQL/Migrations/*
dotnet ef migrations add InitialCreate --project src/Reference.Data.EntityFramework.Migrations.PostgreSQL --startup-project src/Reference.Data.EntityFramework.Migrations.PostgreSQL
(and the SqlServer twin).
Re-issuing InitialCreate mints a new migration id, which orphans any database that already applied the prior one — MigrateAsync sees the new id as pending and fails on CREATE TABLE region with "relation already exists", naming neither cause nor cure. Drop the norse_reference database (or Bifröst's norse-pg-primary volume) before the next run; migration plus seed restores full state by construction, which is exactly why this realm can afford the squash posture until the preview-7 V1 memorialization.
Temporal enablement was squashed in exactly that way, so the apparatus arrives at table birth alongside CREATE TABLE rather than bolted on by a stacked enable migration — nothing here carries a backfill UPDATE … SET system_period. The consequence for tests is worth stating outright: never assert on a migration name. The container facts assert on the PostgreSQL catalog (pg_class/pg_proc/pg_trigger), which survives every squash.
Mímisbrunnr and Mímir are one bounded context split across two repositories for a specific, verified reason: reference-data content (IANA reissuing time zone data, ISO adding or redenominating currencies) changes far more often than the service and component code that serves it, and the platform's release tooling only supports repo-scoped tags — packing and publishing happen for an entire repo at once, not per project. Splitting the repository is what lets Data cut a release without dragging Components/Web.Server/Worker along, and vice versa. This pair is a template for anyone whose own reference data has the same shape — not a pattern the platform applies by default.
Mímisbrunnr is one realm of the Norse Architecture. The whole platform composes at Bifröst — clone once, cross the bridge, and every session starts there so decisions get brainstormed across the entire landscape, not in isolation. Every design is tried in Glitnir, the design court, before code is forged here; this realm's specs and plans will live in the court's docs/Mímisbrunnr/ once they converge.

