Domain · Specifications

Themis Domain — Technical Specifications

Themis is a library-only domain.

17sections34 minread

On this page

Themis is implemented as 40 TypeScript library packages under libs/themis/. This document is the ground-truth reference for engineers working inside the domain: it lists every package, defines every core data model and schema, and specifies the event catalogue, graph module, database schema, voting mechanisms, originality-shield protocol, dispute-routing logic, and academic-integrity adjudication engine.

A new engineer should read this document alongside architecture.md (which explains why the pieces fit together the way they do) and features.md (which describes each capability in plain language). This document answers exactly what each module contains and how the types are shaped.


1. Library Inventory#

Themis is a library-only domain. There are no apps/themis/ or services/themis/ directories. All code lives under libs/themis/, which contains 40 library packages. Every package declares version: 0.1.0 in its package.json and is named under the @themis/ scope.

1.1 Foundation and full governance libraries#

The 33 packages below form the core governance platform. Each is tagged with a tier that indicates its position in the dependency graph: themis:tier:core for the single foundation package and themis:tier:domain for all others.

Package Path Tier tag
@themis/core libs/themis/core themis:tier:core
@themis/voting libs/themis/voting themis:tier:domain
@themis/deliberation libs/themis/deliberation themis:tier:domain
@themis/decisions libs/themis/decisions themis:tier:domain
@themis/reputation libs/themis/reputation themis:tier:domain
@themis/identity libs/themis/identity themis:tier:domain
@themis/accountability libs/themis/accountability themis:tier:domain
@themis/transparency libs/themis/transparency themis:tier:domain
@themis/privacy libs/themis/privacy themis:tier:domain
@themis/constitutions libs/themis/constitutions themis:tier:domain
@themis/dao libs/themis/dao themis:tier:domain
@themis/corporate libs/themis/corporate themis:tier:domain
@themis/nonprofit libs/themis/nonprofit themis:tier:domain
@themis/community libs/themis/community themis:tier:domain
@themis/civic libs/themis/civic themis:tier:domain
@themis/traditional libs/themis/traditional themis:tier:domain
@themis/digital libs/themis/digital themis:tier:domain
@themis/international libs/themis/international themis:tier:domain
@themis/justice libs/themis/justice themis:tier:domain
@themis/arbitration libs/themis/arbitration themis:tier:domain
@themis/sectors libs/themis/sectors themis:tier:domain
@themis/treasury libs/themis/treasury themis:tier:domain
@themis/funding libs/themis/funding themis:tier:domain
@themis/environmental libs/themis/environmental themis:tier:domain
@themis/crisis libs/themis/crisis themis:tier:domain
@themis/policy libs/themis/policy themis:tier:domain
@themis/analytics libs/themis/analytics themis:tier:domain
@themis/knowledge libs/themis/knowledge themis:tier:domain
@themis/frameworks libs/themis/frameworks themis:tier:domain
@themis/simulation libs/themis/simulation themis:tier:domain
@themis/ai libs/themis/ai themis:tier:domain
@themis/integrations libs/themis/integrations themis:tier:domain
@themis/academic-integrity libs/themis/academic-integrity themis:tier:domain

1.2 Dispute-resolution routing library#

@themis/dispute-resolution is tagged separately because it depends on @concordia/contracts rather than @themis/core, and because it was introduced as a discrete phase of work (Phase 179). It is a sibling to @themis/arbitration, not a layer above it.

Package Path Tags
@themis/dispute-resolution libs/themis/dispute-resolution scope:themis, layer:domain, type:lib, phase:179

@themis/dispute-resolution is distinct from @themis/arbitration. @themis/arbitration implements decentralized arbitration, dispute management, and mediation engines (≈5,700 LOC of source). @themis/dispute-resolution is a small (≈790 LOC) routing/intake layer that classifies a dispute and decides whether to route it into the Concordia mediation substrate; it also implements the V2 DSA Statement-of-Reasons and moderation/tournament dispute flows.

1.3 Originality / IP-protection libraries#

The six originality-shield libraries also depend on @concordia/contracts rather than @themis/core. They are intentionally thin: all verdict computation is delegated to the Concordia contract, so that the detection logic lives in one place and can be updated without touching six separate libraries.

There are six originality-shield libraries plus one shared core. They are real but thin: the five media shields are each ≈50 LOC wrappers that delegate all evaluation logic to @themis/originality-shields, which in turn delegates to the @concordia/contracts originality-shield contract.

Package Path Source size Tags
@themis/originality-shields libs/themis/originality-shields ≈365 LOC scope:themis, layer:domain, type:lib, domain:originality
@themis/music-shield libs/themis/music-shield ≈47 LOC scope:themis, layer:domain, type:lib, domain:originality
@themis/visual-shield libs/themis/visual-shield ≈57 LOC scope:themis, layer:domain, type:lib, domain:originality
@themis/text-shield libs/themis/text-shield ≈47 LOC scope:themis, layer:domain, type:lib, domain:originality
@themis/video-shield libs/themis/video-shield ≈47 LOC scope:themis, layer:domain, type:lib, domain:originality
@themis/design-shield libs/themis/design-shield ≈49 LOC scope:themis, layer:domain, type:lib, domain:originality

There is no model-shield, character-shield, game-shield, or animation-shield package, and no @themis/likeness package, in the codebase. See §7 for the shield specification, §11 for the forthcoming @themis/likeness NIL / likeness ledger, and §16 for the planned-work notes.

1.4 Forthcoming Themis-owned libraries#

One Themis-owned library is specified but not yet built. It is listed here for traceability and is described in full in §11; it is not present in libs/themis/ today and nothing in the rest of this document should be read as describing existing code for it.

Package Path Status
@themis/likeness (forthcoming, not yet implemented) libs/themis/likeness/ Specified in §11; reciprocal task tracker in §11.8

2. Technology Stack#

The table below lists every tool and runtime used across the domain. Note that the originality shields use tsup instead of the standard @nx/js:tsc executor because they require a slightly different build pipeline.

Component Technology
Language TypeScript (ESM, strict mode)
Runtime Node.js (engines.node >= 20)
Build Nx @nx/js:tsc (most libraries); nx:run-commands + tsup for the originality shields
Testing Vitest (per-library configs, shared vitest.shared.ts)
Database PostgreSQL (schema and migrations from @themis/core)
Validation Zod (@themis/core types are Zod schemas; many libraries use Zod)
Event transport Kafka publisher abstraction in @themis/core (with an in-memory implementation)
Shared config Domain-wide tsconfig.domain.json, eslint.config.js, prettier.config.js under libs/themis/

3. Core Data Models (@themis/core)#

@themis/core source is organized into four module groups: types/, events/, graph/, and database/. All public symbols are re-exported from libs/themis/core/src/index.ts. The core types are Zod schemas; each schema has a matching inferred TypeScript type and parse* / safeParse* helpers. The interfaces below are the inferred shapes — the Zod schemas are the authoritative runtime definitions, and these TypeScript interfaces should be understood as their structural projections.

3.1 Organization#

Defined in types/organization.ts. An Organization is the top-level aggregate — it contains the charter, governs members and roles, and is the anchor for all events in the audit log.

typescript
interface Organization {
  name: string; // 1–255 chars
  jurisdiction: Jurisdiction;
  type: OrganizationType;
  charter: Charter;
  foundingDate: string; // YYYY-MM-DD
  status: OrganizationStatus;
}

OrganizationType (ORGANIZATION_TYPE_VALUES) enumerates the 15 recognized organizational forms. Every Themis governance library is designed to work with at least one of these types:

DAO, Corporation, LLC, NonProfit, Cooperative, Association, Union, Foundation, Municipality, Legislature, PoliticalParty, SportsClub, CommunityOrg, NetworkState, HybridEntity.

OrganizationStatus (ORGANIZATION_STATUS_VALUES) tracks the lifecycle of an organization itself: forming, active, suspended, dissolved, merged.

Jurisdiction captures where the organization is legally anchored: country (2-letter ISO code, upper-cased), optional stateProvince, legalFramework, regulatoryBody.

3.2 Charter#

A Charter is the organization's constitutional document. It is embedded inside the Organization rather than being a separate top-level entity, because a charter is meaningless without the organization it governs.

typescript
interface Charter {
  preamble: string;
  articles: CharterArticle[]; // ≥1; { articleNumber, title, body }
  bylaws: CharterBylaw[]; // ≥1; { section, title, body }
  amendments: CharterAmendment[]; // { amendmentNumber, title, summary, effectiveDate }
  effectiveDate: string; // YYYY-MM-DD
  ratification: CharterRatification;
}

interface CharterRatification {
  status: RatificationStatus; // pending | ratified | rejected
  ratifiedBy: string[]; // ≥1
  ratificationDate: string; // YYYY-MM-DD
  method: string;
}

3.3 Member, Role, GovernanceIdentity, Delegation#

Defined in types/member-role.ts. These four types together describe who participates in governance and how their participation is structured. UUIDs are validated against UUID_REGEX (v1–v5 UUID form).

typescript
interface Member {
  id: string; // UUID
  identity: GovernanceIdentity;
  organizationId: string; // UUID
  roles: Role[];
  reputationScore: number;
  delegationStatus: DelegationStatus;
  votingPower: number; // ≥0
  joinDate: string; // YYYY-MM-DD
  status: MemberStatus;
}

interface GovernanceIdentity {
  did: string;
  verifiableCredentials: VerifiableCredential[];
  sybilScore: number; // 0–1
  eligibilityProofs: EligibilityProof[];
}

interface Role {
  name: string;
  permissions: Permission[]; // ≥1
  responsibilities: string[]; // ≥1
  term: RoleTerm; // { startDate, endDate?, renewable }
  electionMethod: ElectionMethod;
}

interface Delegation {
  delegator: string; // UUID
  delegate: string; // UUID
  scope: Record<string, unknown>;
  weight: number; // >0
  expiry: string | null; // ISO datetime
  revocable: boolean;
}

The following enums define the valid values for fields on these types:

  • Permission (PERMISSION_VALUES) — Propose, Vote, Delegate, Execute, Veto, Amend, Moderate, Audit, AdministerTreasury, ManageMembers, ConfigureGovernance.
  • MemberStatus (MEMBER_STATUS_VALUES) — invited, active, inactive, suspended, removed.
  • DelegationStatus (DELEGATION_STATUS_VALUES) — none, delegating, receiving, both, revoked.
  • ElectionMethod (ELECTION_METHOD_VALUES) — elected, appointed, sortition, rotating, consensus.

VerifiableCredential carries: credentialId, credentialType, issuer, issuedAt, optional expiresAt, claims.

EligibilityProof carries: proofType, proofValue, optional verifiedBy, verifiedAt, metadata.

3.4 Proposal and Vote#

Defined in types/proposal-vote.ts. The Proposal, Vote, and VotingResult types are the core of any active governance process. A proposal moves through a sequence of statuses; each status transition is recorded as an event in the audit log.

typescript
interface Proposal {
  id: string; // UUID
  organization: string; // UUID
  author: string; // UUID
  title: string; // 1–255 chars
  body: string;
  type: ProposalType;
  status: ProposalStatus;
  createdAt: string; // ISO datetime
  discussionEnd: string | null;
  votingStart: string | null;
  votingEnd: string | null;
  executionTime: string | null;
  quorumRequired: number; // 0–1
  thresholdRequired: number; // 0–1
  executionPayload: Record<string, unknown>;
}

interface Vote {
  voter: string; // UUID
  proposal: string; // UUID
  choice: VoteChoice;
  weight: number; // >0
  timestamp: string; // ISO datetime
  proof: Record<string, unknown>; // default {}
  delegationChain: string[]; // UUIDs; default []
}

interface VotingResult {
  proposal: string; // UUID
  totalVotes: number;
  forVotes: number;
  againstVotes: number;
  abstainVotes: number;
  quorumMet: boolean;
  thresholdMet: boolean;
  winner: string | null;
  detailedBreakdown: Record<string, unknown>;
}

ProposalType (PROPOSAL_TYPE_VALUES) covers the 11 recognized kinds of governance action a proposal can represent:

Constitutional, Legislative, Budgetary, Electoral, Membership, ParameterChange, TreasuryAllocation, DisputeResolution, Emergency, Ceremonial, MetaGovernance.

ProposalStatus (PROPOSAL_STATUS_VALUES) tracks the lifecycle of a proposal through 11 states:

Draft, Discussion, Deliberation, Voting, Passed, Failed, Queued, Executed, Vetoed, Expired, Cancelled.

VoteChoice is a discriminated union on type, allowing each voting mechanism to express its ballot format precisely. The type discriminant must be one of VOTE_CHOICE_TYPE_VALUES: For, Against, Abstain, RankedChoices, ConvictionAmount, QuadraticCredits, ApprovalSet.

Discriminant Extra field
For
Against
Abstain
RankedChoices rankings: { option, rank }[] (≥1)
ConvictionAmount convictionAmount: number (>0)
QuadraticCredits quadraticCredits: number (>0)
ApprovalSet approvals: string[] (≥1)

3.5 GovernanceFramework#

Defined in types/framework.ts. A GovernanceFramework describes the rules and parameters under which a specific governance process operates. It is separate from Organization so that the same framework can be applied to multiple organizations, and so that an organization can switch frameworks over time by versioning this object.

typescript
interface GovernanceFramework {
  type: FrameworkType;
  rules: GovernanceRule[]; // ≥1
  parameters: GovernanceParameter;
  version: string; // 1–64 chars
  phases: GovernancePhase[]; // ≥1; defaults to all phases
}

interface GovernanceRule {
  condition: string | Record<string, unknown>;
  action: string | Record<string, unknown>;
  threshold: number; // 0–1
  timelock: number; // non-negative integer
  vetoPower: { enabled: boolean; vetoRoles: string[]; vetoThreshold?: number };
}

interface GovernanceParameter {
  quorumThreshold: number; // 0–1
  passingThreshold: number; // 0–1
  votingPeriod: number; // positive integer
  executionDelay: number; // non-negative integer
  proposalDeposit: number; // ≥0
  delegationDepth: number; // non-negative integer
}

FrameworkType (FRAMEWORK_TYPE_VALUES) enumerates the 12 recognized governance system designs the platform can model:

DirectDemocracy, RepresentativeDemocracy, LiquidDemocracy, Sociocracy, Holacracy, ConsensusGovernance, FutarchyGovernance, ConvictionGovernance, QuadraticGovernance, BicameralGovernance, HybridGovernance, CustomFramework.

GovernancePhase (GOVERNANCE_PHASE_VALUES) names the phases a governance process moves through: discussion, deliberation, voting, execution, review.

3.6 Deliberation, Argument, CitizenAssembly#

Defined in types/deliberation.ts. These types model structured discussion before a vote is called. Deliberation produces a ConsensusLevel that informs whether a proposal is ready to proceed to voting.

typescript
interface Deliberation {
  topic: string; // 1–255 chars
  organization: string; // UUID
  participants: string[]; // UUIDs, ≥1
  phases: DeliberationPhase[]; // ≥1
  facilitator: string; // UUID
  outcome: ConsensusLevel | null;
  summary: string;
}

interface Argument {
  // recursive (z.lazy)
  claim: string;
  evidence: ArgumentEvidence[];
  author: string; // UUID
  supportsProposal: boolean;
  counterarguments: Argument[];
  endorsements: string[]; // UUIDs
  qualityScore: number; // 0–1
}

interface ArgumentMap {
  rootClaims: Argument[]; // ≥1
  relationships: ArgumentRelationship[];
  consensusClusters: ConsensusCluster[];
  disagreementPoints: string[];
}

interface CitizenAssembly {
  sortitionPool: string[]; // UUIDs, ≥1
  selectedMembers: string[]; // UUIDs, ≥1
  topic: string; // 1–255 chars
  duration: { start: string; end: string }; // ISO datetimes
  expertWitnesses: CitizenAssemblyExpertWitness[];
  recommendations: string[]; // ≥1
}

DeliberationPhase (DELIBERATION_PHASE_VALUES) describes the structured phases of a formal deliberation session: InformationGathering, SmallGroupDiscussion, PlenarySession, OpinionPolling, ProposalDrafting, FinalVote.

ConsensusLevel (CONSENSUS_LEVEL_VALUES) captures the quality of the agreement reached: StrongConsensus, RoughConsensus, MajorityAgreement, Divided, Deadlocked.

ArgumentRelationshipType (ARGUMENT_RELATIONSHIP_VALUES) — supports, rebuts, clarifies, extends.

3.7 Dispute, Ruling, Mediator#

Defined in types/dispute-resolution.ts. Note that these core types define the data shapes for governance disputes stored in @themis/core; the routing logic for sending disputes to the Concordia mediation substrate lives in the separate @themis/dispute-resolution library (§8), and the heavyweight mediation and arbitration engines live in @themis/arbitration.

typescript
interface Dispute {
  parties: string[]; // UUIDs, ≥2
  subject: string;
  evidence: Evidence[];
  status: DisputeStatus;
  resolutionMethod: ResolutionMethod;
  ruling: Ruling | null;
  appealStatus: AppealStatus;
}

interface Ruling {
  dispute: string; // UUID
  adjudicator: string;
  decision: string;
  reasoning: string;
  enforcement: {
    actions: string[];
    deadline: string | null;
    enforcementBody: string;
  };
  appealDeadline: string | null;
}

interface Mediator {
  identity: string;
  qualifications: string[]; // ≥1
  specializations: string[]; // ≥1
  trackRecord: { casesHandled; successfulResolutions; averageResolutionDays };
}

ResolutionMethod (RESOLUTION_METHOD_VALUES) lists the seven ways a dispute can be resolved: Negotiation, Mediation, Arbitration, DecentralizedCourt, RestorativeJustice, CommitteeReview, MemberVote.

DisputeStatus (DISPUTE_STATUS_VALUES) tracks where in the resolution pipeline a dispute sits: filed, review, mediation, arbitration, adjudicated, appealed, closed.

AppealStatus (APPEAL_STATUS_VALUES) — none, eligible, filed, under_review, resolved, rejected.

3.8 Treasury and fiscal types#

Defined in types/treasury-fiscal.ts. The treasury types model the financial governance of an organization — what assets it holds, how those assets may be spent, and who must authorize spending. These types are used by @themis/treasury and @themis/funding.

The key entities and their relationships are:

  • Treasury — top-level holder: organization, assets, totalValue, allocationRules, spendingLimits, signers (≥1).
  • TreasuryAsset — a single asset line in the treasury.
  • TreasuryAllocationRule — a rule constraining how treasury funds may be allocated.
  • TreasurySpendingLimit — a per-category or per-period spending cap.
  • TreasurySigner — an authorized co-signer for treasury transactions.
  • BudgetAllocation — an approved allocation of funds to a purpose.
  • FundingStream — a streaming or vesting distribution, with a FundingVestingSchedule.
  • SpendingProposal / SpendingApproval — the two-step flow for authorizing a disbursement.
  • FiscalPeriod — a time-bounded budget period for reporting and reconciliation.

TreasuryAssetType (TREASURY_ASSET_TYPE_VALUES) — Fiat, Stablecoin, Token, Equity, Bond, Commodity, NFT, Other.

BudgetExecutionStatus (BUDGET_EXECUTION_STATUS_VALUES) — proposed, approved, in_execution, completed, cancelled.

FiscalAuditStatus (FISCAL_AUDIT_STATUS_VALUES) — pending, in_review, approved, qualified, rejected.

3.9 Governance metrics#

Defined in types/governance-metrics.ts. All scores are in the 0–1 range unless noted. These metric types are computed by @themis/analytics and @themis/accountability and surfaced to consuming applications for dashboard display and health alerting.

  • GovernanceHealthScore — ten sub-scores: participationRate, proposalThroughput, decisionQuality, diversityIndex, transparencyScore, accountabilityScore, legitimacyScore, efficiencyScore, adaptabilityScore, overallHealth.
  • ParticipationMetricsvoterTurnout, proposalAuthors (count), deliberationActive, delegationRate, newMemberRate.
  • DecisionQualityMetricsimplementationSuccessRate, reversalRate, stakeholderSatisfaction, timeToDecision (non-negative), informedVotingRate.
  • TransparencyMetricsdocumentAvailability, meetingRecordCompleteness, financialDisclosure, decisionTraceability, auditCompliance.
  • GovernanceMetricsSnapshot — bundles all four metric groups plus a generatedAt timestamp.

4. Event System (@themis/core events module)#

Every governance action in Themis is expressed as a typed event appended to the immutable audit log. The event system has three parts: the catalogue of event types (§4.1), the event record structure (§4.2), and the hash-chaining and Kafka infrastructure (§4.3).

4.1 Event-type catalogue#

events/types.ts defines THEMIS_EVENT_TYPES, a frozen object of named event-type string constants. THEMIS_EVENT_TYPE_LIST and THEMIS_EVENT_TYPE_COUNT are derived from it, and isThemisEventType() is the runtime guard. Event types are grouped by domain prefix. There are 126 distinct event-type constants across twelve groups:

Prefix Coverage
themis.organization.* created, profile updated, jurisdiction added/removed, status changed, merged, dissolved, charter updated, metadata updated
themis.framework.* created, updated, activated, deactivated, rule added/updated/removed, version published, parameter changed
themis.member.* invited, joined, activated, suspended, removed, role assigned/revoked, identity verified/revoked, reputation adjusted, eligibility confirmed/revoked
themis.delegation.* created, changed, revoked, expired, scope updated, power rebalanced, chain updated
themis.proposal.* created, submitted, sponsored, updated, versioned, tagged/untagged, discussion opened, deliberation started/extended, voting started, quorum reached, threshold met, passed, failed, veto exercised, execution queued, executed, cancelled, expired
themis.vote.* cast, updated, invalidated, delegated, tally updated, recount requested/completed, receipt published, proof verified
themis.deliberation.* session created/started, participant joined/left, message posted, phase started/completed, outcome recorded, consensus measured
themis.constitution.* drafted, article added/updated/removed, amendment proposed/adopted/rejected, ratification started, ratified, superseded
themis.election.* announced, nomination opened/closed, candidate registered/withdrawn, voting opened, ballot cast, result recorded, certified, contested, closed
themis.treasury.* created, account added, asset registered, budget proposed/approved, allocation created, transfer initiated/completed, payout executed, rebalanced, stream status changed
themis.dispute.* filed, evidence submitted, mediation started, arbitration started, ruling issued, appeal filed/resolved, resolved, closed
themis.governance.* notification dispatched, integration sync started/completed, risk registered/mitigated, policy document anchored, audit checkpoint created, compliance report generated, health computed/alerted

THEMIS_EVENT_TYPE_COUNT is derived from the list at runtime, so it always reflects the actual count in source. There is no themis.license.revoked event type, and no music/originality shield event types, in the @themis/core catalogue. (The originality-shield verdict audit event constant — see §7 — lives in the originality-shield code, not in THEMIS_EVENT_TYPES.)

4.2 Governance event record#

Every governance event is stored as a ThemisGovernanceEvent. The payload field is typed precisely via a conditional type, so the compiler enforces that a themis.proposal.* event carries a ProposalEventPayload and not some other payload shape.

typescript
interface ThemisGovernanceEvent<T extends ThemisEventType> {
  id: string;
  type: T;
  organizationId: string;
  actorMemberId: string | null;
  targetTable: string | null;
  targetId: string | null;
  payload: ThemisEventPayloadForType<T>; // payload shape inferred from event prefix
  metadata: GovernanceEventMetadata; // correlationId?, causationId?, schemaVersion?, labels?
  occurredAt: string;
  recordedAt: string;
  hashPrev: string | null;
  hashCurrent: string;
  merkleLeafHash: string;
  sourceSystem: string | null;
  ipAddress: string | null;
}

ThemisEventPayloadForType<T> is a conditional type that maps each event prefix to a payload interface: OrganizationEventPayload, GovernanceFrameworkEventPayload, MemberEventPayload, DelegationEventPayload, ProposalEventPayload, VoteEventPayload, DeliberationEventPayload, ConstitutionEventPayload, ElectionEventPayload, TreasuryEventPayload, DisputeEventPayload, and GovernanceOperationsEventPayload.

4.3 Hash-chained, Merkle-anchored audit log#

The audit log is designed to be tamper-evident. Each event's hash chains over the previous event's hash, and groups of events are organized into a Merkle tree whose root can be anchored on the Ethereum blockchain via the Aje SDK. This means any third party can verify that audit records have not been altered, even without access to the Themis database.

The implementation spans four source files:

  • events/hash-chain.ts — provides computeGovernanceEventHashes, computeHashChainCurrent, computeMerkleLeafHash, sha256Hex, toCanonicalJson, normalizeGovernanceJson, and the genesis-hash constant THEMIS_AUDIT_CHAIN_GENESIS_HASH. Each event's hashCurrent chains over its predecessor's hash; each event also yields a Merkle leaf hash.
  • events/service.tsThemisGovernanceEventService appends events inside a transaction, taking a per-organization Postgres advisory lock (pg_advisory_xact_lock) so the hash chain is serialized per organization. It also verifies chains (GovernanceChainVerificationReport, with issue codes hash_prev_mismatch, merkle_leaf_mismatch, hash_current_mismatch) and infers a target table from the event type.
  • events/audit-anchor.tsThemisGovernanceAuditAnchorService batches events into a Merkle tree and anchors the root on-chain. The default anchor chain is ethereum; an Ethereum anchorer (AjeEthereumMerkleRootAnchorer, createAjeSdkEthereumAnchorer) integrates with the Aje SDK. The default payload prefix is THEMIS_AUDIT_ROOT_V1.
  • events/kafka.tsThemisKafkaPublisher and InMemoryGovernanceKafkaPublisher publish governance events to Kafka; default topic from DEFAULT_THEMIS_GOVERNANCE_KAFKA_TOPIC.

5. Graph Module (@themis/core graph module)#

The graph module answers questions that relational queries handle poorly: who has influence over whom, how does voting power flow through delegation chains, and where are single points of failure in the governance network? It models governance actors and their relationships as nodes and edges in a Cypher-capable graph store.

The key types are:

  • GovernanceActorTypeindividual, organization, dao, institution.
  • GovernanceRelationshipTypeDELEGATES_TO, MEMBER_OF, REPORTS_TO, CONTROLS, INFLUENCES, OPPOSES, ALLIES_WITH.
  • GovernanceActorNodeactorId, organizationId, actorType, displayName, optional jurisdiction, metadata.
  • GovernanceRelationshipEdgefromActorId, toActorId, organizationId, type, optional weight, confidence, validFrom, validTo, metadata.

ThemisGovernanceGraphService and the Cypher query builders (buildUpsertActorCypher, buildUpsertRelationshipCypher, buildPowerFlowAnalysisCypher, buildTopologyQueryCypher, buildInfluencePathCypher) implement upserts plus power-flow, topology, and influence-path queries. getThemisGraphSchemaStatements returns the schema bootstrap statements.


6. Database Schema (@themis/core database module)#

@themis/core ships two SQL migrations, registered through THEMIS_CORE_MIGRATIONS. All objects live in a dedicated themis PostgreSQL schema and require the pgcrypto and pg_trgm extensions.

6.1 Migration 20260212150000_themis_governance_schema#

This first migration creates the foundational schema: the themis namespace, 14 PostgreSQL ENUM types, and 63 base tables (plus three audit_events range partitions). The tables cover every governance entity in the domain:

organizations, organization_profiles, organization_jurisdictions, members, member_identities, member_roles, delegation_edges, reputation_scores, reputation_events, governance_frameworks, governance_framework_versions, governance_framework_rules, constitutions, constitution_articles, constitution_amendments, constitution_ratifications, proposal_categories, proposals, proposal_versions, proposal_sponsors, proposal_sections, proposal_tags, proposal_status_history, deliberations, deliberation_phases, deliberation_participants, deliberation_messages, deliberation_outcomes, votes, vote_receipts, vote_proofs, elections, election_candidates, election_ballots, election_results, treasuries, treasury_accounts, treasury_assets, treasury_allocations, treasury_streams, treasury_transactions, disputes, dispute_parties, dispute_evidence, dispute_rulings, policy_documents, policy_analyses, compliance_requirements, compliance_assessments, governance_sessions, quorum_snapshots, decision_records, public_consultations, consultation_feedback, funding_rounds, funding_allocations, simulation_runs, simulation_results, integration_links, risk_register, notifications, audit_events, audit_hash_checkpoints.

Notable schema features worth understanding before writing queries:

  • audit_events is range-partitioned by occurred_at, with partitions audit_events_2026_h1, audit_events_2026_h2, and audit_events_default. It carries hash_prev, hash_current, merkle_leaf_hash columns for the hash-chained audit log.
  • audit_hash_checkpoints records Merkle roots with on-chain anchoring columns (anchored_chain, anchored_tx_hash, anchored_block_number).
  • GIN full-text indexes exist on constitution_articles.body, proposals (title + body), deliberation_messages.body, policy_documents.body, and consultation_feedback.feedback_text.
  • The schema's PostgreSQL enums use snake_case values (e.g. proposal_status = draft, review, deliberation, voting, approved, rejected, executed, withdrawn, expired). These intentionally differ from the TypeScript Zod enums in §3, which use PascalCase; the database layer is a separate storage representation.

6.2 Migration 20260212160000_themis_document_storage#

This second migration adds off-chain document storage support, enabling governance documents (constitutions, policy documents, session minutes, decision records) to be persisted on IPFS or Arweave in addition to the PostgreSQL row. It adds:

  • The governance_document_type and document_storage_status enums.
  • The document_storage_records and document_storage_events tables.
  • storage_record_id foreign keys on constitutions, policy_documents, governance_sessions (minutes), and decision_records (resolution).

ThemisDocumentStorageService and hashGovernanceDocument implement the storage layer.

6.3 Migration runner#

Four symbols manage the migration lifecycle: createThemisCoreMigrationService, migrateThemisCoreUp, migrateThemisCoreDown, and a CLI (migrations/cli.ts). The migration service takes a Postgres advisory lock (THEMIS_MIGRATION_LOCK_ID) to prevent concurrent migration runs in multi-instance deployments.


7. Originality / IP-Protection Shields#

7.1 Architecture#

The originality shields are a thin Themis layer over the @concordia/contracts originality-shield contract (resolved at libs/contracts/concordia/srcthemis-originality-shield/). Themis does not implement detection algorithms itself; it constructs an evidence bundle, delegates verdict computation to evaluateShield from @concordia/contracts, and maps the result to a Themis decision.

@themis/originality-shields exports buildThemisOriginalityShieldVerdict, which is the shared implementation. The five media shields each call it with a fixed config. The table below shows what each shield covers:

Shield mediaFamily supportedUploadKinds Default evidence kind
@themis/music-shield music music-swap, custom-championship audio_fingerprint
@themis/visual-shield visual custom-championship, decal, logo image_perceptual_hash
@themis/text-shield text custom-championship, logo lyric_text_embedding
@themis/video-shield video custom-championship video_perceptual_hash
@themis/design-shield design custom-championship, decal, logo image_perceptual_hash

Each shield also exports a package-name constant and a shieldId constant (e.g. THEMIS_MUSIC_SHIELD_ID = 'themis.music-shield.v1') and re-exports the scan input/verdict types.

7.2 Scan input#

A caller initiates an originality check by providing a ThemisOriginalityShieldScanInput (validated by a Zod schema). The fields are:

Field Type Notes
uploadId string non-empty
creatorAccountId string non-empty
uploadKind ThemisOriginalityUgcUploadKind custom-championship, decal, logo, music-swap
contentHashSha256 string matches ^(sha256:)?[A-Fa-f0-9]{64}$
sourceUri string non-empty
createdAtIso string ISO datetime with offset
referenceMatches ThemisOriginalityReferenceMatch[] optional; default []
licenseLineages LicenseLineage[] optional; from @concordia/contracts
reviewerSignedOff boolean default false
reviewerPartyId string optional

ThemisOriginalityReferenceMatch carries: matchId, priorWorkId, score01 (0–1), licensed (default false), optional licenseLineageId, optional region (kindtime_range_seconds, pixel_box, token_range, mesh_subgraph, lines_range, plus from/to).

7.3 Verdict#

buildThemisOriginalityShieldVerdict returns a ThemisOriginalityShieldVerdict. The most important fields for consumers are:

  • decision — the three-value accept-gate result (passed, review, blocked); see the mapping table below.
  • publicUgcAcceptGateStatuspassed only when decision === 'passed'; otherwise blocked. This is the field a UGC upload pipeline should check.
  • highestUnlicensedBand — the most severe confidence band among unlicensed matches.
  • maxSimilarity01 — the highest overlap score across all reference matches.
  • blockingReasons — human-readable list of reasons for a blocked decision.
  • evidenceUri — URI to the evidence bundle for audit purposes.
  • auditEventType — always themis.originality_shield.verdict_recorded.

Additional envelope fields: schemaVersion: 1, packageName, corePackageName, sourceContractPackageName, evaluatorVersion (themis-originality-shields.v1), shieldId, mediaFamily, uploadId, uploadKind, creatorAccountId, contentHashSha256, sourceUri, supportedUploadKinds, evidenceBundle (OriginalityEvidenceBundle), shieldOutcome (ShieldOutcome).

The contract assigns each reference match to one of six confidence bands based on its overlap score. The default calibration maps score thresholds 0 / 0.2 / 0.45 / 0.65 / 0.8 / 0.95 to the bands inconclusive, low_overlap, medium_overlap, high_overlap, substantial_match, identical respectively.

ShieldOutcome.verdict (from @concordia/contracts) produces one of seven verdicts, which Themis collapses into the three-value decision:

Themis decision Contract verdicts mapped
passed clear_for_distribution, clear_with_attribution, license_required_obtained
review unverified_chain_route_to_counsel, inconclusive_route_to_human_review
blocked license_required_pending, unlicensed_overlap_blocked

The evidence-bundle methodology id is <shieldId>:compound-v1.

The elaborate per-engine detection design (melodic / harmonic / rhythmic / spectral / lyric / vocal / structural engines, compound-escalation multipliers, ISRC/ISWC reference databases, perceptual-hash and CLIP/DINOv2 stacks, C2PA labelling) is the planned Phase 74 / Phase 75 scope — see §16. It is not present in the current shield libraries, which are the thin Concordia-backed wrappers described above.


8. Dispute-Resolution Routing (@themis/dispute-resolution)#

@themis/dispute-resolution (tagged phase:179) routes Themis governance disputes into the Concordia mediation substrate and implements three V2 intake flows. It depends on @concordia/contracts and zod. It is intentionally small (≈790 LOC) — the classification and routing logic lives here, but the mediation and adjudication work itself is handled by Concordia or @themis/arbitration.

8.1 Dispute routing#

ThemisDisputeKind (Zod enum) classifies what kind of governance dispute has arisen. The nine recognized kinds are:

proposal_amendment, election_challenge, delegate_misconduct, ip_originality_appeal, moderation_appeal, marketplace_conflict, inter_dao_agreement, standard_amendment, community_council_dispute.

routeThemisDispute(kind) returns a ThemisRoutingDecision: { disputeKind, routeToConcordia, operationalMode, reviewerQueues, rationale }. shouldRouteToConcordia(kind) is the boolean shorthand.

  • operationalMode selects how Concordia should run its mediation process. Valid modes: brainstorming, facilitated_mediation, procurement_negotiation, governance_process, arbitration_support, legal_review_required, restorative_circle, agent_to_agent, simulation_only.
  • reviewerQueues specifies which specialist queues should be notified. Valid queue identifiers: mediator, counsel, compliance, procurement, dao_steward, safety, governance, auditor.

Every dispute kind routes to Concordia except standard_amendment, which runs through normal governance rather than mediation.

8.2 V2 dispute flows#

v2-dispute-flows.ts exports package and flow-id constants and three builder functions used by V2's gaming and tournament platform:

  • buildThemisDsaStatementOfReasons — builds an EU Digital Services Act Statement of Reasons when content is moderated. Inputs cover:
    • surfacebattle-hub-chat, fighter-chat, replay-comment, creator-suite-upload, profile, ranked-match, tournament
    • actionTypecontent_removed, content_hidden, content_demoted, chat_restricted, creator_upload_rejected, account_suspended, account_banned, matchmaking_restricted, rank_penalty
    • reasonCategory, factSources, policyBasis
  • openThemisModerationAppeal — opens a moderation appeal case with a 7-day SLA (THEMIS_MODERATION_APPEAL_SLA_DAYS = 7).
  • openThemisTournamentResultDispute — opens a tournament-result dispute; themisDisputeKindForTournamentResult maps it to a ThemisDisputeKind.

Flow-id constants: THEMIS_DSA_STATEMENT_OF_REASONS_API_ID = 'themis.dsa.statement-of-reasons.v1', THEMIS_MODERATION_APPEAL_FLOW_ID = 'themis.moderation-appeal.v1', THEMIS_TOURNAMENT_RESULT_DISPUTE_FLOW_ID = 'themis.tournament-result-dispute.v1'.


9. Academic-Integrity Adjudication (@themis/academic-integrity)#

@themis/academic-integrity is the Themis adjudication engine for Metis academic-integrity cases. It exports the themisAcademicIntegrityModule identifier and six sub-modules. This library depends only on zod — it does not depend on @themis/core — because it operates as a self-contained adjudication engine that Metis invokes at the point of a suspected integrity violation.

Sub-module File Responsibility
signals signals/taxonomy.ts Academic-integrity signal taxonomy
classifier classifier/policy.ts, classifier/severity-actions.ts Calibrated classifier policy and severity→action map
appeals appeals/workflow.ts Appeals workflow
bias bias/monitor.ts Classifier bias monitor
verdict verdict/persistence.ts Verdict persistence
orchestrator orchestrator/adjudicator.ts End-to-end adjudication orchestration

10. Module Identifiers#

Most Themis libraries export a module-identifier constant from their index.ts. This constant allows a host application to verify at runtime which Themis modules are loaded, without depending on package metadata from the filesystem. The constant carries only a name field — there is no version field:

typescript
// @themis/core
export const themiscoreModule = { name: '@themis/core' } as const;

// @themis/voting
export const themisvotingModule = { name: '@themis/voting' } as const;

The constant name is themis<package>Module in lower case (e.g. themisaiModule, themisdaoModule). @themis/academic-integrity uses the PascalCase variant themisAcademicIntegrityModule because of the hyphenated package name.

The following libraries do not export a module-identifier constant: @themis/crisis, @themis/international, @themis/justice, @themis/dispute-resolution, @themis/originality-shields, and the five media shields (@themis/music-shield, @themis/visual-shield, @themis/text-shield, @themis/video-shield, @themis/design-shield).


11. NIL / Likeness Ledger (V2 Fighting-Game Consumer)#

The V2 fighting-game product consumes Themis as the authoritative name-image-likeness (NIL) rights registry for every real-person likeness it ships — licensed fighters, celebrity guests, stunt performers, and on-stage venue staff. The canonical registry is a new, Themis-owned library, @themis/likeness, which is still forthcoming and not yet implemented in libs/themis/likeness/. It is distinct from @themis/identity (governance identity — DID, eligibility, Sybil resistance) and from the originality shields in §7 (which protect uploaded UGC against prior works, not real-person likeness rights).

Two V2-side bridges already ship against the contract of this forthcoming ledger by structurally typing its stamp and its revocation event, without taking a package dependency on the unbuilt library:

  • @v2/aja-consent-nil-ledger links each Aja performer-consent record to a @themis/likeness ledger entry by likenessLicenseId, rightsManifestSha256, and consentChainRefs[], and emits the themis.license.revoked cascade on withdrawal.
  • @v2/kuanyin-performer-protection reads a @themis/likeness ledger stamp at the chat / commentary / creator-upload boundary and blocks any likeness surface (and the downstream Bellona cook) whose stamp is revoked, expired, out-of-scope, or whose rightsManifestSha256 does not match the active manifest.

These V2-side bridges such as @v2/aja-consent-nil-ledger and @v2/kuanyin-performer-protection are consumer safeguards; they enforce the ledger contract but they are not the ledger itself. Authoring the canonical @themis/likeness library remains Themis-owned work — see §11.8.

11.1 The canonical LikenessLicense schema#

The forthcoming @themis/likeness library will own a Zod-validated LikenessLicense aggregate — the per-subject, per-region, per-license-window grant of likeness rights. Its identity is a likenessLicenseId (lic_-prefixed slug, matching the pattern the V2 bridges already validate). Each license carries:

  • Subject identitysubjectId, subjectDisplayName, and subjectType (fighter, celebrity, stunt-performer, venue-staff), plus an alias set so downstream protection surfaces can detect mentions.
  • Rights envelopestatus (draft, active, paused, breach-cure, terminated, expired), validUntilEpochMs (a timestamp or perpetual), the set of allowedUses (playable character, cinematic cameo, cosmetic skin, voice-line bank, commentary mention, real-world venue stage, soundtrack, promotional art, merchandise spin-off, esports broadcast, creator-suite upload), and the licensed regions.
  • ProvenancerightsManifestSha256, an immutable sha256:-prefixed digest of the signed rights manifest, and consentChainRefs[], the ordered list of consent-record identifiers (from @aja/consent-management) that underwrite the grant.
  • Per-grant nuance — the schema must model per-mode toggles (a use may be granted in ranked but withheld from exhibition), distinct voice grants (a voice-line bank licensed separately from the visual likeness), group / faction rights (team or roster-level grants that fan out to individual members), sublicensee chains (studio → publisher → platform re-grants, each link auditable), and per-platform-store overrides (a use permitted on one storefront but blocked on another for territorial reasons).
  • Estate / postmortem rights — the schema must carry coverage for estate / postmortem rights so a deceased performer's likeness can remain governed by the executor-held grant, including a post-mortem expiry distinct from the living-subject window.

The license aggregate is the single source of truth that the V2 consumer bridges project into their narrower rightsStamp / ledger-stamp shapes.

11.2 Cook-time rights stamping via @bellona/interchange#

Every asset that embeds a real-person likeness must be stamped at cook time — the point where Bellona's @bellona/interchange packaging step seals a shippable asset bundle. The stamp is a compact, signed projection of the governing LikenessLicense: likenessLicenseId, rightsManifestSha256, the covered allowedUses, the consentChainRefs[] that back it, and the themis.license.revoked event topic that the asset's consumers must watch.

@bellona/interchange is the enforcement chokepoint: a bundle whose embedded likeness has no stamp, an out-of-scope stamp (the asset's actual use is not in allowedUses), or a stamp whose rightsManifestSha256 does not match the manifest sealed into the bundle, must be rejected at cook and never shipped. This mirrors the blocksBellonaCook gate that the V2 bridges already assert: when the ledger gate fails, the cook is blocked.

11.3 Revocation cascade#

A LikenessLicense can be revoked at any time — a performer withdraws consent, a contract lapses, an estate objects. Revocation emits a themis.license.revoked event keyed by likenessLicenseId. The cascade has three obligations, each of which the V2 consumers already honour:

  1. Notify the NIL ledger — flip the ledger entry status to revoked / terminated so no new stamp can be minted against it.
  2. Block future processing@v2/aja-consent-nil-ledger blocks further Aja ingest of the performer's capture data, and (when requested) deletes the associated capture data.
  3. Block the cook — any in-flight or future @bellona/interchange cook of an asset embedding the revoked likeness is blocked, and any live likeness surface (@v2/kuanyin-performer-protection) is shut to viewers.

The Aja consumer commits to executing the cascade within a 15-minute SLA of the withdrawal request. Revocation is append-only audit history: the ledger keeps the prior active entry and the revocation event, never a destructive edit.

The ledger does not mint or activate a LikenessLicense unless its consentChainRefs[] resolve to live, in-scope consent records in @aja/consent-management. Validation requires that every required consent purpose for the asset's intended uses is consented, that the chain's rightsManifestSha256 matches the license, and that no referenced consent record is withdrawn. @v2/aja-consent-nil-ledger builds the chain at grant time (one ref per ConsentRecord) and is the canonical integration point for this validation; @themis/likeness will own the validation rule itself.

11.5 DSA Statement-of-Reasons for likeness takedowns#

When a likeness asset is removed, demoted, or blocked because its NIL rights failed (revoked stamp, expired window, out-of-scope use, manifest mismatch), the affected creator or rights-holder is owed a machine-readable DSA Statement-of-Reasons. The ledger does not implement the SoR engine itself; it delegates to @themis/dispute-resolution, whose buildThemisDsaStatementOfReasons (§8.2) produces the notice and whose openThemisModerationAppeal opens the seven-day appeal. @themis/likeness will author the SoR templates specific to likeness actions (reason categories, fact sources, policy basis) and hand the structured input to @themis/dispute-resolution for issuance.

11.6 On-chain manifest publication (optional)#

For high-value grants (celebrity guests, estate-held rights), the ledger may optionally publish the signed rightsManifestSha256 and license envelope to an @aje/rwa on-chain real-world-asset manifest, anchoring the grant's provenance in the same Aje substrate the @themis/core audit-anchor service already uses (§4.3). On-chain publication is an option, not a requirement: the in-database ledger remains authoritative; the chain is a tamper-evident mirror.

11.7 Why this is a new library, not an extension#

@themis/likeness is deliberately a separate package rather than an addition to @themis/identity or the originality shields. Identity governs who may participate in governance; the originality shields protect uploaded works against prior art; the likeness ledger governs a real person's right to have their image, name, and voice embedded in a shipped product. These are distinct legal regimes (publicity / NIL rights vs. governance identity vs. copyright), distinct event topics (themis.license.revoked vs. themis.originality_shield.verdict_recorded), and distinct enforcement chokepoints (@bellona/interchange cook vs. UGC accept-gate). Collapsing them would entangle three independent compliance surfaces.

11.8 V2 reciprocal task tracker#

The following work is Themis-owned and remains in this domain backlog. It is the reciprocal of the V2 consumer bridges that already ship: those bridges enforce a contract this domain has not yet built. Until @themis/likeness exists, the contract lives only in the structural types the V2 bridges declare and in this specification. Each item below is unchecked and must be authored inside the Themis monorepo.

  • Stand up the new @themis/likeness library under libs/themis/likeness/ with package.json (@themis/likeness), project.json (scope:themis, layer:domain, type:lib), tsconfig.json, and Vitest config, separate from @themis/identity and the originality shields.
  • Implement the canonical LikenessLicense schema per § 11.1 as a Zod aggregate with parse* / safeParse* helpers and inferred types re-exported from likeness/src/index.ts.
  • Add schema coverage for estate / postmortem rights, including an executor-held grant holder and a post-mortem expiry distinct from the living-subject validUntilEpochMs.
  • Implement the cook-time stamp protocol per § 11.2 that projects a LikenessLicense into the signed rightsStamp (likenessLicenseId, rightsManifestSha256, consentChainRefs[], covered uses) that @bellona/interchange seals into a shippable bundle.
  • Wire @bellona/interchange to reject unstamped or out-of-scope likeness bundles at cook, including rightsManifestSha256 mismatches against the manifest sealed into the bundle.
  • Implement the revocation cascade per § 11.3 that emits themis.license.revoked, flips the ledger entry status, and signals the consumer-side blocks (Aja ingest, Bellona cook, live likeness surfaces).
  • Integrate canonical consent-chain validation with @aja/consent-management per § 11.4, rejecting activation when any required purpose is unconsented or any referenced consent record is withdrawn.
  • Implement venue, music-track, celebrity-guest, logo, and apparel-brand rights families, with per-mode toggles, distinct voice grants, group / faction rights, sublicensee chains, and per-platform-store overrides.
  • Add optional @aje/rwa on-chain manifest publication per § 11.6 for high-value grants, anchoring rightsManifestSha256 and the license envelope.
  • Author DSA Statement-of-Reasons templates for likeness takedowns and route them through @themis/dispute-resolution per § 11.5, opening the seven-day moderation appeal where the action is contestable.

12. Cross-Domain Integrations (@themis/integrations)#

@themis/integrations contains bridges to other Oshun domains. Each bridge is a separate source file responsible for the data and control flow between Themis and one counterpart domain. The files present in source are:

Bridge file Counterpart domain
veritas-themis-intelligence-pipeline.ts Veritas (inbound)
themis-veritas-governance-feed.ts Veritas (outbound)
governance-journalism-collaboration-hub.ts Veritas
veritas-open-journalism-governance.ts Veritas
themis-aje-governance-execution-bridge.ts Aje (on-chain execution)
aje-themis-governance-data-ingestion.ts Aje (data ingestion)
maat-themis-organizational-governance.ts Maat
themis-maat-governance-intelligence.ts Maat
lakshmi-themis-fiscal-governance.ts Lakshmi
kuan-yin-themis-ethical-governance.ts Kuanyin
iris-themis-governance-assistant.ts Iris
sophia-themis-knowledge-governance.ts Sophia
metis-themis-civic-education.ts Metis
maya-themis-virtual-governance.ts Maya
sector-specific-governance-bridges.ts Sector-specific

The Aje bridge pair is a representative example of how cross-domain boundaries are handled. themis-aje-governance-execution-bridge.ts translates a Themis governance decision (proposal passed, treasury disbursement approved) into an Aje on-chain execution call. aje-themis-governance-data-ingestion.ts flows in the other direction, pulling on-chain DAO votes and treasury events back into Themis for analysis and display. Neither direction owns the other's concerns. The audit-anchor service in @themis/core also integrates with the Aje SDK for Merkle-root anchoring (§4.3).


13. Configuration#

@themis/core reads its PostgreSQL connection from environment variables via resolveThemisPostgresConfigFromEnv (database/migrations/service.ts):

Variable Default Purpose
THEMIS_DB_HOST 127.0.0.1 PostgreSQL host
THEMIS_DB_PORT 5432 PostgreSQL port
THEMIS_DB_NAME oshun_dev Database name
THEMIS_DB_USER postgres Database user
THEMIS_DB_PASSWORD postgres Database password
THEMIS_DB_SSL false Enable SSL when set to true

There is no THEMIS_DATABASE_URL, THEMIS_BLOCKCHAIN_RPC_URL, THEMIS_CHAIN_ID, THEMIS_MUSIC_SHIELD_THRESHOLD, or THEMIS_AUDIT_LOG_BLOCKCHAIN variable in the codebase. Blockchain configuration for the audit-anchor service is passed programmatically via AjeEthereumMerkleRootAnchorerConfig / AjeSdkEthereumAnchorerConfig, not via environment variables. AI-agent libraries that call the Claude API rely on the monorepo-wide ANTHROPIC_API_KEY convention.


14. Voting Mechanisms (@themis/voting)#

@themis/voting ships 12 voting mechanism files (one source module each). Each mechanism is self-contained: it defines its own ballot format, tallying logic, and result computation. The mechanisms share no implementation code — each is independently testable and deployable.

The twelve mechanism modules are:

universal-ballot-system, delegation-engine, token-weighted-voting, quadratic-voting, ranked-choice-voting, approval-voting, condorcet-voting, conviction-voting-engine, holographic-consensus, optimistic-governance, vote-escrow-governance, multi-sig-voting.

Indicative mechanism parameters (from the engine implementations):

  • Quadratic voting — cost grows with the square of votes on an option; voters spend from a voice-credit budget.
  • Conviction voting — conviction accumulates over time toward a staked proposal; later staking has less effect than sustained staking.
  • Holographic consensus — staked attention fast-tracks proposals to the full DAO; routine proposals resolve locally.
  • Quadratic funding — matching is computed from the squared sum of contribution square roots (see @themis/funding).

15. Acceptance Criteria#

A change to the Themis domain is acceptance-complete when all six conditions are satisfied:

  1. Buildnpx tsc --noEmit passes in each touched library (Nx is unreliable under worktrees; type-check directly from the library directory).
  2. Testsnpx vitest run passes in each touched library; the domain uses Vitest with per-library configs and vitest.shared.ts.
  3. Core types — new domain objects added to @themis/core are Zod schemas with inferred types and parse* / safeParse* helpers, re-exported from core/src/index.ts.
  4. Events — new governance event types are registered in THEMIS_EVENT_TYPES, carry a payload interface, and append through the hash-chained ThemisGovernanceEventService.
  5. Schema — new persistent tables are added through a @themis/core migration in the themis schema and registered in THEMIS_CORE_MIGRATIONS.
  6. Lint — the shared eslint.config.js / prettier.config.js pass.

16. Planned Work#

The following are documented in the V1 backlog (TODOS.md) or V2 dependency docs as planned, not implemented. They are listed for traceability; nothing below should be read as describing existing code.

  • Phase 74 — Themis Music Shield. A full AI-music copyright-protection and originality-verification system for @themis/music-shield, with per-element detection engines and pipeline orchestration. Reference proposal: docs/domains/themis-music-shield-proposal.md. The current @themis/music-shield library is the thin Concordia-backed wrapper in §7, not this system.
  • Phase 75 — Themis Universal Originality Shield. Extension of Phase 74 to every generated media type, with @themis/visual-shield, @themis/text-shield, @themis/video-shield, and @themis/design-shield carrying media-specific detection. Reference proposal: docs/domains/themis-universal-originality-shield-proposal.md.
  • @themis/likeness (forthcoming). The NIL / likeness ledger is specified in full in §11, with its reciprocal Themis-owned task tracker in §11.8. V2 dependency docs (V2/V2_DEPENDENCIES.md) describe the same forthcoming, not-yet-created @themis/likeness library: a per-fighter / per-region / per-license-window name-image-likeness (NIL) ledger, explicitly noted as a new package separate from @themis/identity (whose scope is governance identity — DID, eligibility, Sybil resistance). No @themis/likeness package, no LikenessLicense type, and no themis.license.revoked event exist in the codebase today.
  • Phase 179 — Concordia integration. @themis/dispute-resolution (§8) is the implemented routing layer for this phase. Further mediated-amendment workflow expansion remains backlog.

V2 consumes Themis libraries through V2-side adapter packages (@v2/themis-originality-shields, @v2/themis-dispute-resolution, @v2/themis-community-governance, and others). Those adapters live in the V2 sister-monorepo and are documented there; they are not Themis libraries.


17. V2 Consumer Contracts#

The V2 fighting-game product binds several Themis libraries through thin V2-side service packages. Each binding is off rollback: it produces governance, moderation, disclosure, or voting outcomes that never read or write a live rollback-netcode frame and never influence deterministic simulation (offRollback: true, mayInfluenceRollback: false, deterministicImpact: 'none'). The sections below record the contract each binding upholds against the Themis source of truth.

17.1 V2 Community Governance Contract#

@v2/themis-community-governance projects Themis social governance for the four V2 player-community surfaces — crew, clique, stable, and faction — onto the real @themis/community managers. Crew, clique, and faction rule changes run through SportsClubGovernanceManager (createRulesCommittee, proposeRuleChange, castRuleProposalVote, finalizeRuleProposal); stable constitutions run through AssociationGovernanceManager (proposeConstitutionalAmendment → ratification → enactRatifiedAmendment).

The contract surface owns three projections:

  • rule committees — every rule change is sponsored by a committee of at least three members; a faction rule cannot publish (crewRulesPublicationGate flips to hold-for-revision) unless the committee vote is approved.
  • member reputation projection — a governanceReputationScore (0–100) and a trusted / good / probation / limited standing are derived from activity, committee membership, voting participation, and leadership role; the score gates who may sponsor a rule change.
  • constitution ratification — stable amendments require member ratification voting against quorum and approval thresholds before enactment.

All of this stays off rollback: community governance is social metadata, not gameplay state, and the V2 binding asserts offRollback: true.

17.2 V2 Dispute-Resolution Contract (DSA appeals + tournament disputes)#

@v2/themis-dispute-resolution binds @themis/dispute-resolution (§8) to the V2 product's two contestable surfaces. moderation appeals open through openThemisModerationAppeal with the seven-day Themis SLA and a machine-readable DSA Statement-of-Reasons; tournament-result disputes open through openThemisTournamentResultDispute, which holds the provisional result and routes the challenge to auditor-backed review. Both flows stay off rollback — they adjudicate after the fact and never touch the deterministic match frame.

17.3 V2 Performer-Protection cross-reference#

@v2/kuanyin-performer-protection (owned by Kuanyin, backed by the @kuanyin/performer-protection library, specified on the Kuanyin side) is the live-surface consumer of the forthcoming Themis NIL ledger described in §11. It reads a @themis/likeness ledger stamp at the chat, commentary-mention, and creator-suite-upload boundaries, compares the stamp's rightsManifestSha256 and consentChainRefs against the active manifest, and blocks the likeness surface and downstream Bellona cook when the stamp is revoked (themis.license.revoked), expired, out-of-scope, or mismatched. It takes no package dependency on the unbuilt @themis/likeness library — it binds the contract structurally. The canonical ledger work that backs this consumer is tracked in §11.8.

17.4 V2 EU AI Act surface (Themis side)#

Themis is the AI-system-of-record owner for every shipping V2 AI service under the EU AI Act conformity surface. @themis/accountability (v2-ai-system-record.ts) registers the V2 Adaptive AI Director, the AI commentary service, the anti-cheat classifier suite, and the V2 generation pipelines as regulator-ready AI-system-of-record entries with evidence links. The Model Cards for those systems are hosted by @nous/safety; Themis owns the audit export and applies the retain-for-product-lifetime-plus-six-years retention policy to each record. The composed @v2/eu-ai-act-surface package wires Psyche transparency, the Nous Model Card, and the Themis accountability record together; AI commentary is bound as off-rollback presentation content and never gates a deterministic frame.

17.5 V2 Photo Mode Tournament Voting Profile#

@v2/photo-mode-tournament-voting-bridge binds @themis/voting to community photo-mode tournaments under the V2 Photo Mode Tournament Voting Profile (v2.photo-mode-tournament-voting-profile). Jury rounds tally with the RankedChoiceVotingEngine; broad community rounds tally with the ApprovalVotingEngine. A @kuanyin/precognition moderation pre-pass screens each submission before it becomes vote-eligible, and ballots referencing moderated-out or unknown submissions are sanitized. The whole profile is off rollback — it ranks gallery content after matches, never during live gameplay frames.

17.6 V2 World Boss Governance Contract#

@v2/world-boss-community-raid-bridge binds @themis/community (alongside Maat intelligence, Hathor simulation, and Kuanyin raid defense) for community world-boss events under the V2 World Boss Governance Contract. Themis owns the rules for the community-shared HP pool: the rule committee must approve the shared-HP-and-contribution rule proposal before the raid manifest can publish. Per-fighter contributions are validated server-side against the v2.world-boss-contribution-validation schema (golden-replay hash, anti-cheat acceptance, event-window bounds, per-match damage cap) at match end only. The shared HP bar is HUD-display-only and gameplay-inert; the bridge rejects any live rollback-frame RPC and performs no live shared-HP reads, keeping the entire contract off rollback.