# Eunomia Governance & the Ori Cross-Version Bridge

V7 — codename **Mawu** — is a _creator republic_, and a republic needs two
things a single-operator game does not: a way for communities to **govern
themselves** without being able to vote away the platform's safety floor, and a
way for a player's identity to **persist beyond any one realm or product
version**. Those are the two halves of the "Governance & Continuity" group.
**Eunomia** is the multi-tier governance data model — five sovereign rule spaces
from `platform` down to `guild`, six plural voting models, a strict proposal
lifecycle, and a non-negotiable safety floor that no vote can override. The
**Ori Passport** is the cross-version bridge — the seam that lets a V7
character, which is fundamentally a V6 _Ori_ identity record, incarnate into
V2–V6 destinations (and now realm-to-realm) carrying only a minimal, scoped
claim set, while the Ori itself remains the single source of truth no realm ever
holds. The two are connected by one idea: **sovereignty bounded by an inviolable
core.** A guild governs its charter but not child-safety; a realm renders your
character but never _owns_ it. This page grounds both halves in the code that
exists today and is explicit about which seams are compiled and which are still
mocked. The full section index lives at
[../V7_ARCHITECTURE.md](../V7_ARCHITECTURE.md).

## What ships, honestly

**Eunomia is a real, test-backed decision kernel — but a kernel, not yet a live
service.** `apps/v7/eunomia-governance-service/src/service.ts` (~1,575 lines) is
a library of pure, deterministic functions: tier/parent-override validation,
safety-floor evaluation, the proposal state machine, six plural-voting tally
formulas, Themis appeal routing, localized-proposal rendering, and the Maya
Variants/Crucible governance surface. Its `service.test.ts` carries **12 test
cases**, and the `eunomiaGovernanceServiceDescriptor` declares port **47302**
and **16 capabilities**. The honest qualification: the deployable binary
(`src/main.ts`) is a Node `http` server that answers exactly one route —
`/health` — returning the descriptor as JSON. There is **no Postgres, no live
proposal API, and no event bus wired in yet**; the governance logic decides, but
nothing yet persists or serves it over the wire. Treat Eunomia as a verified
rule engine awaiting its transport, not a running governance plane.

**The Ori Passport bridge is real, compiled Rust — and it genuinely links the V6
Ori store.** `libs/v7/substrate-bridge/src/lib.rs` (2,462 lines, **8 `#[test]`
blocks**) mints passports, runs the cross-version round-trip eval, and opens the
realm-federation corridor. Crucially, its `Cargo.toml` carries real path
dependencies —
`egbe-ori-service = { path = "../../../apps/v6/egbe-ori-service" }` and
`ori-model = { path = "../../v6/ori-model/rust" }` — so the V6 **Ori event
store, projection materializer, and operator-read audit path are compiled in and
exercised**, not stubbed. `default_substrate_bindings()` labels exactly the V6
Ori/Aye-Bridge and the Maya engine-core `Reused`; everything else — V1 identity
(`libs/shared/auth-primitives`), Aje, Lilith, Kuanyin, **Themis**, Iris, Psyche,
Isis, Sophia, Yemaya, and the V6 Egbe gateway — is `Mock`. Two consequences to
keep honest below: (1) the **Aye Bridge** is reused as the _contract owner_ of
the passport envelope (`generated_by = "@oshun/aye-bridge"`,
`v6_aye_bridge_package_ref = "libs/v6/aye-bridge"`), while the minting logic is
re-implemented natively in V7 Rust; and (2) Themis treaty signing remains a
reference string plus a boolean flag. Proposal appeals now have a separately
configured live HTTP dispatch boundary, but no live dispatch receipt was
captured in this repository slice.

## Eunomia — the multi-tier governance data model

### Five sovereign tiers, and the parent-override consent rule

Governance is partitioned into five tiers, ordered by scope:
`EUNOMIA_GOVERNANCE_TIERS = ['platform', 'game', 'realm', 'server', 'guild']`.
Each tier holds a **sovereign rule space** a parent cannot silently override.
The parent chain is explicit in `EUNOMIA_PARENT_TIER` — `game→platform`,
`realm→game`, `server→realm`, `guild→server` — and `platform` deliberately has
no parent. The sovereignty is enforced in `executeGovernanceRuleChange()`: a
rule change with no `parentOverride` is marked `sovereignRuleSpace: true`, and a
parent may only reach into a child tier when `validateParentOverride()` passes
**all three** conditions — the override names the _correct_ parent tier for the
target (`parent_override_wrong_tier:*` otherwise), the target tier has actually
consented (`consentedByTargetTier`, else
`parent_override_requires_target_tier_consent`), and a non-empty reason is
given. An attempt to override at the `platform` tier fails with
`platform_tier_has_no_parent_override`. This is the "a parent cannot override
without consent" invariant rendered as code, not prose.

### The safety floor no vote can cross

Sovereignty stops at the platform safety floor. `EunomiaSafetyFloorPolicy`
enumerates the five non-negotiables — `minor_protection`, `harassment_abuse`,
`csam_blocking`, `identity_privacy`, and `real_money_firewall` — and every rule
change must ship a non-empty `safetyFloorChecks` array (absence yields
`safety_floor_checks_required`). `evaluateEunomiaSafetyFloor()` filters for any
check where `compliant === false`; a single violation pushes both
`safety_floor_violation` and a policy-scoped `safety_floor_violation:<policy>`
reason, and `accepted` flips to false. No quorum, no token weight, and no
parent-consent path can execute a change that fails the floor — the
Lilith/Kuanyin safety posture is structurally _above_ the most powerful vote.
The trust-and-safety machinery that backs these policies is described in
[./sekhmet-safety-and-anti-cheat.md](./sekhmet-safety-and-anti-cheat.md), and
the `real_money_firewall` policy is the governance face of the economy
separation in
[./abundantia-economy-firewall-and-anti-fraud.md](./abundantia-economy-firewall-and-anti-fraud.md).

### The proposal lifecycle as a strict state machine

`EUNOMIA_PROPOSAL_LIFECYCLE_ORDER` fixes the legal path:
`draft → deliberation → vote → execution → appeal`. `runProposalLifecycle()`
replays a submitted transition list against this order. Each transition must
carry a non-empty actor, timestamp, and reason (`transition_actor_required:*`
etc.); its `from` must equal the machine's current state
(`transition_from_state_mismatch:*`); and its `to` must be exactly the next
state returned by `nextProposalLifecycleState()` (`transition_not_allowed:*`
otherwise). A proposal is `complete` only when the walk reaches `appeal` with no
accumulated reasons. The state machine is therefore _append-only and
skip-proof_: you cannot jump from `draft` straight to `execution`, and the
report exposes the full `statesVisited` trail for audit.

### Plural voting — six models, six real formulas

Eunomia does not hard-code one democratic theory. `EunomiaPluralVotingModel`
offers six, and `pluralVotingBallotWeight()` gives each a distinct, real weight
function (mirrored as human-readable strings in `pluralVotingFormula()`):

- **`token`** → `tokenWeight` (stake-weighted).
- **`reputation`** → `reputationScore`.
- **`quadratic`** → `Math.sqrt(quadraticCredits)` — the Weyl/Posner quadratic-
  voting square-root, which taxes concentration of influence.
- **`conviction`** → `convictionStake × convictionAgeHours` — time-locked
  conviction voting, where a long-held position carries more weight.
- **`delegated`** → `baseWeight + Σ delegatedWeights` — liquid-democracy
  delegation.
- **`time_weighted`** → `baseWeight × min(membershipAgeDays, 365)` — tenure-
  weighted, capped at one year so longevity cannot become unbounded capture.

`tallyPluralVotingModel()` does the honest bookkeeping around those formulas: it
keeps only the **latest ballot per voter** (`latestPluralVotingBallots()`, dedup
by `castAt`), rejects any ballot whose computed weight is non-positive
(`ballot_weight_must_be_positive`), rounds to six decimal places to avoid
floating-point drift, tallies `for/against/abstain`, and computes
`passed = quorumMet && winningChoice === 'for' && totals.for > totals.against`.
Rejected ballots are surfaced with reasons rather than silently dropped.

### Appeals route to Themis

A proposal that reaches the `appeal` state can be escalated by
`routeProposalAppealToThemis()`. It refuses anything not in the `appeal`
lifecycle state (`proposal_not_in_appeal_state`) and, on success, emits a typed
route naming `themisModule: '@themis/arbitration'`, a deterministic
`themisCaseId` (`themis:eunomia:<proposalId>:<appealId>`), and an `appealRef`
URI (`themis://arbitration/eunomia/<proposalId>/<appealId>`). Honest seam: this
function only _constructs the routing contract_. The asynchronous
`dispatchProposalAppealToThemis()` path invokes a configured Themis HTTP
endpoint. Non-loopback endpoints require HTTPS and bearer authentication;
redirects are forbidden, response bytes are bounded before JSON parsing, and the
returned schema, service, case, appeal reference, receipt, and timestamp must
bind exactly to the request. Rejected lifecycle input never dispatches;
HTTP/network/schema failures remain explicit `dispatch-failed` results. The
gateway is executable and contract-tested, but there is no credentialed live
receipt in this slice.

### Game-tier governance: Maya Variants and the Crucible

The richest governance surface is at the `game` tier, where communities steward
forkable game _variants_. `publishMayaVariantFork()` produces a standalone
`MayaVariantPublication` with a full **attribution chain** and typed
`MayaVariantRevenueLink`s (`parent-fork`, `marketplace-asset`,
`inherited-dependency`), so revenue flows back along the fork lineage —
basis-points-validated against `MAX_REVENUE_SHARE_BASIS_POINTS = 10_000`.
`resolveCanonicalVariantVote()` runs the `canonical-variant-vote` proposal kind:
eligible variants are tallied by latest weighted vote, and the canonical "main"
branch is **reassigned only** when a challenger both wins and strictly
out-weighs the incumbent past quorum.

Before a realm can earn `Verified` status, it must survive the **Maya Crucible**
— an adversarial economic balance check. `runMayaCrucibleBalanceVerification()`
simulates two agent strategies against a realm's economy mods: a
`baseline-worker` that takes honest job payouts, and an `exploit-seeker` that
greedily chains the highest-net-yield mods. `detectCrucibleFindings()` then
flags three blocker classes — `excessive-mint` (net minted beyond the cap),
`runaway-growth` (balance growth past the bps ceiling), and
`infinite-currency-cycle` (a refund-multiplier loop whose per-tick yield grows
≥4×). `evaluateMayaRealmVerifiedGate()` finally gates the `Verified` registry
status on **all three** signals being clean: no blocking Crucible findings, a
clean Sekhmet scan, and clean moderation standing. This is governance enforcing
economic soundness, and it interlocks directly with the anti-fraud machinery in
[./abundantia-economy-firewall-and-anti-fraud.md](./abundantia-economy-firewall-and-anti-fraud.md).
Proposals themselves are launch-localized: `EUNOMIA_LAUNCH_LOCALES` covers eight
locales including RTL `ar` and `he`, and
`renderLocalizedGovernanceProposalForRegion()` maps five
`EunomiaGovernanceRegion`s to default locales, requiring an `approved`
moderation status before a translated proposal renders (else it falls back).

## The Ori Passport — cross-version incarnation bridge

### The principle: the Ori is the truth, a realm is a stage

A V7 character is not a realm's property. It is a `NanaCharacterRecord`
(`libs/v7/nana`) — `ori_id`, `realm_id`, `display_name`, optional employment,
and realm-scoped `NanaBalances` (`cash_minor`, `bank_minor`, `society_minor` as
`i64` minor units whose `validate()` refuses to go negative) — and the `ori_id`
keys a **V6 Ori identity record** that is the genuine source of truth. The
bridge's job is to let that identity be _rendered into_ other Oshun product
versions while the Ori root stays singular and intact. As the architecture puts
it: the Ori remains the truth; a realm, like any destination, is a stage it is
rendered into.

### Five incarnation destinations through the reused Aye Bridge

`V7AyeIncarnationDestination` enumerates the five V-destinations a character may
incarnate into: `V2Maya`, `V3Lilith`, `V4Odysee`, `V5Oshun`, and `V6OriNative`
(the native Ori return path). Each carries a stable `adapter_ref` (`v2-fighter`,
`v3-citizen`, `v4-operator`, `v5-companion`, `v6-ori-service-native`) and a
versioned `capability_mapping_ref` (e.g.
`capability-mapping:v3-lilith:citizen:v1`), so a character's abilities are
**re-mapped per destination** rather than copied verbatim — a fighter in V2 is
not the same capability surface as a citizen in V3.
`default_v7_aye_incarnation_destinations()` returns the full inventory, which is
the V6 Aye Bridge incarnation model carried into V7 with one new corridor added
(federation, below).

### Minting a scoped passport: data minimisation by construction

`mint_v7_character_incarnation_passport()` produces a
`V7CharacterIncarnationPassport`. Two design choices matter. First, the passport
carries only what the destination needs: `scoped_claims_for_character()` emits a
**minimal claim set** — `identity.display`, `identity.characterKey`, and
`capabilities.mappingRef` — not the character's balances, record, or
relationships. Second, integrity is hashed: `ori_root_integrity_hash()` binds
the `ori_id`, the stable character key, and the scoped claims into an
`ori_integrity_hash` that must survive every subsequent lease, fault, and
concurrent claim. The envelope is stamped `generated_by: "@oshun/aye-bridge"`
and `v6_aye_bridge_package_ref: "libs/v6/aye-bridge"`, naming the V6 Aye Bridge
as the reused contract authority even though the mint runs in V7 Rust.

### The round-trip eval: integrity under fault and concurrency

`round_trip_v7_character_into_destination()` exercises the full journey:
`departure → destination actor → return → incarnation-journal write-back`. It is
adversarial by design. It **injects a disconnection** during return and recovers
via a `return_replay_buffer_ref`; it fires a **concurrent duplicate departure**
against the same Ori and asserts `concurrent_departure_blocked`; and it checks
that after the dust settles there is exactly **one** authoritative Ori copy
(`active_ori_copy_count == 1`) and **zero** lingering destination copies. The
receipt's `round_trip_ok()` returns true only when the copy counts hold, the
duplicate was blocked, `ori_integrity_hash_before == ori_integrity_hash_after`,
and the evidence proves both `round-trip-integrity` and
`incarnation-journal-writeback` — i.e. the journey is recorded back into the Ori
biography. This is the same "no window with two writers or zero owners"
discipline the mesh uses for authority handoff, applied to identity.

### The new V7 corridor: realm-to-realm federation under treaty

V7 adds one corridor the prior versions did not have: **realm-to-realm
federation**. `V7RealmFederationTreaty::themis_signed()` defines a corridor
between two realms with an explicit `allowed_state_keys` set and a
`lease_ttl_seconds`; the default treaty (`default_v7_realm_federation_treaty()`)
permits only `presence.status`, `position.cell`, `party.intent`, and
`realm.quest_state` for 900 seconds. `open_v7_realm_federation_corridor()` then
**filters the source realm's state down to exactly those keys**, hashes the
negotiated subset, and sets `out_of_scope_state_rejected` true only when there
genuinely was state outside the treaty that was excluded. Its `round_trip_ok()`
requires a non-empty Themis terms reference, a stable subset hash across the
round-trip, a preserved Ori integrity hash, resolved concurrent claims, and
out-of-scope rejection. Honest seam: `themis_signed` is a constructor that sets
the boolean and copies a terms reference — the corridor's _governance contract_
is real and validated, but no live Themis call signs it yet (Themis is `Mock`).

### `run_v7_passport_eval` — the combined continuity gate

`run_v7_passport_eval()` is the single gate that composes both legs. It
round-trips a character into a V-destination _with disconnection_, opens a
federation corridor _with disconnection_, and then asserts four properties:
`v_destination_round_trip_ok`, `federated_realm_round_trip_ok`,
`ori_integrity_preserved_under_disconnection` (both legs' before/after hashes
match despite injected faults), and `concurrency_preserved_ori_integrity` (the
duplicate departure was blocked, concurrent corridor claims were resolved, and
the two legs agree on the Ori hash). The test
`passport_eval_round_trips_v_destination_and_federated_realms_with_ori_integrity`
runs this end-to-end. Because the V6 Ori store is compiled in, the underlying
character write (`EgbeOriFacade::write_character_record`) really appends a
`MemoryFormed` event to `PartitionedPostgresOriEventStore` and reads it back
through the **audited** `operator_read_ori_projection` path — the bridge does
not fake the identity store it claims to use.

### How the bridge composes shared identity

The passport's authority chain begins at the platform principal. A
`V7AuthenticatedPrincipal` carries `user_id`, `tenant_id`, `session_id`, scopes,
and a residency scope — the same claim shape an `@oshun/identity`
(`libs/shared/identity`) JWT issues for every other Oshun product. V7's binding
to that identity layer is currently the `Mock` `StaticIdentityProvider`
(`V7Substrate::V1Identity → libs/shared/auth-primitives`), so the _shape_ is the
shared one while the _wire_ is still a local stand-in. The continuity guarantee
sits on top of it: the `V7IdentityFirewall` projects the platform principal into
a `V7RealmScopedIdentity` whose `opaque_handle` is an **HMAC of
`(pepper, principal, realm_id)`** — so a realm sees a per-realm pseudonym, never
the platform account, and the same player in two realms gets two un-linkable
handles. The Ori passport then carries the _platform-authoritative_ `ori_id`
across version boundaries while each realm only ever touches the pseudonymous
projection. That is the through-line: one shared identity at the core, many
scoped renderings at the edges. The platform-side identity foundation this
composes is documented in
[../../platform/auth-identity.html](../../platform/auth-identity.html).

```mermaid
flowchart TD
    PRIN["Platform principal<br/>@oshun/identity JWT claim shape<br/>(V1 · Mock: StaticIdentityProvider)"]
    FW["V7IdentityFirewall.project()<br/>opaque_handle = HMAC(pepper, principal, realm)"]
    NANA["NanaCharacterRecord<br/>ori_id · realm-scoped balances"]
    ORI["V6 Ori event store<br/>PartitionedPostgresOriEventStore<br/>+ audited operator-read<br/>(Reused · compiled Rust)"]
    MINT["mint_v7_character_incarnation_passport()<br/>scoped_claims + ori_integrity_hash<br/>generated_by @oshun/aye-bridge"]
    subgraph DEST["V-destinations — per-destination capability mapping"]
      V2["V2 Maya"]
      V3["V3 Lilith"]
      V4["V4 Odysee"]
      V5["V5 Oshun"]
      V6["V6 Ori-native return"]
    end
    CORR["open_v7_realm_federation_corridor()<br/>Themis-signed treaty · allowed_state_keys<br/>(Themis binding · Mock)"]
    PRIN --> FW
    FW --> NANA
    NANA -- "character memory (MemoryFormed)" --> ORI
    ORI --> MINT
    MINT --> DEST
    MINT --> CORR
    DEST -. "round-trip: journal write-back<br/>ori_copy==1 · hash before==after" .-> ORI
    CORR -. "ori-remains-truth · out-of-scope rejected" .-> ORI
```

## Where to read next

- [./sekhmet-safety-and-anti-cheat.md](./sekhmet-safety-and-anti-cheat.md) — the
  trust-and-safety plane that backs Eunomia's non-negotiable safety floor, and
  the client-integrity/anti-cheat stack.
- [./abundantia-economy-firewall-and-anti-fraud.md](./abundantia-economy-firewall-and-anti-fraud.md)
  — the real-money/play-currency firewall the `real_money_firewall` policy
  governs, plus the payout-fraud and Crucible-gated `Verified` interlock.
- [../../platform/auth-identity.html](../../platform/auth-identity.html) — the
  shared `@oshun/identity` foundation whose JWT claim shape the Ori passport
  composes across versions.

## Related

- Section hub: [../V7_ARCHITECTURE.md](../V7_ARCHITECTURE.md)
- Real code cited here: `apps/v7/eunomia-governance-service/src/service.ts`,
  `apps/v7/eunomia-governance-service/src/main.ts`,
  `libs/v7/substrate-bridge/src/lib.rs`, `libs/v7/substrate-bridge/Cargo.toml`,
  `libs/v7/nana/src/lib.rs`, and `libs/v7/contracts/src/schemas.ts` (the
  `V7GovernanceContractSchema` and `V7CharacterContractSchema` Zod contracts).
