fediversity core Constitution

Core Principles

I. Downward-Only Leaf

core is the library leaf of the fediversity monorepo. It MUST NOT know the api or panel sub-projects. Code, tests, names and comments in core/ MUST NOT import from api/ or panel/, read their files, or refer to their components, nodes, roles, modules or source files. A front-end adds its own components and data-model modules to the groups of core through the public fold helpers (principle IV), and then renders the result.

core MAY use shared infrastructure of the repository root that is not a sub-project (for example npins/, the contracts library under nix/, the overlays).

Rationale: the cli <-> api import cycle was the origin of the old cli and core split. That split was an accident, and it was merged away. api and panel depend on core, so knowledge in the other direction makes a cycle again, and a change in a front-end can then break core. A second front-end must be able to use core without the first one.

II. Agnostic to Front-End Business Logic

core gives three things: stateless deployment programs, the application catalog and the configuration model. It MUST NOT contain the business logic of a front-end: authentication of end users, multi-tenancy of accounts, billing, or queueing and authorization of deployment requests. These belong to the front-ends.

Authentication inside a deployment (for example the single sign-on of the deployed applications) is part of the product that core deploys, and is in scope.

III. Stateless Deployment Programs

A deployment program MUST get all its coordinates from environment variables that a module declares. core MUST publish the set of these variables, so a caller knows what to forward. A program MUST NOT keep state of its own between runs. The state of a deployment lives in the state backend that the caller gives. A program MUST refuse to continue when it finds that this state is lost, and MUST NOT silently create a new deployment over it.

Rationale: api runs the programs as jobs and keeps the state per deployment. Hidden state in core makes two runs of the same program give different results.

IV. Everything Is a Module

A consumer extends or changes the data model only with modules of the module system (components, resources, environments, policies). There MUST be one extension seam, not special override parameters. A value from the hosting configuration of a provider MUST have the type of the option it sets.

Rationale: the separate override paths (environmentsOverride, resolveEnvironments, resourcesOverride) were removed in favor of one seam. Each of them had its own rules, and none checked types.

V. Decide by Capability, Not by Name

A decision about wiring (DNS, TLS, secrets, resource routing, trust) MUST depend on what a component declares that it provides or needs, not on the name of a node or component. A want of a contract that no provider in the deployment satisfies MUST fail the evaluation.

Rationale: node-name checks break when a node is renamed, split or moved, and a missing provider made a deployment hang without an error.

VI. One Entrypoint

core/default.nix is the single source of truth for all outputs. core/flake.nix is a thin wrapper that adds the ${system} layer and MUST NOT add, remove or change outputs. The attribute names of the deployment programs follow one grammar, and core MUST publish the list of names that exist.

VII. Tested Decisions

Each pure decision function of the wiring MUST have a nix-unit test that asserts on the same expression that the deployment uses. Each check MUST have a description and a CI runner route. A check that has no route fails.

Constraints

  • All inputs are pinned with npins. The pinned nixpkgs is upstream nixpkgs, not a fork.
  • The public surface is the attributes of core/default.nix: the rendered outputs (nixosConfigurations, packages, apps, devShells, checks, formatter, legacyPackages, deploymentAttributeNames, attributeFamilies) and lib (render, foldGroupComponents, foldGroupModules, baseGroups, applications-type, the environment key sets, testers). A change to a name or the shape of this surface is a breaking change for api and panel, and MUST be named as such in the pull request.
  • The JSON Schema of the configuration uses draft 2020-12.

Development Workflow

  • Changes go through pull requests on git.fediversity.eu, with the title prefix core: . The treefmt check and the checks that CI routes for the change MUST pass.
  • A pull request that changes behavior updates the matching specification under core/specs/ in the same pull request.
  • Prose in comments, commit messages and pull requests uses ASD-STE100, US English and ASCII punctuation, with backticks around code.
  • Documentation describes the current state of the code. The description of an environment variable is next to the code that reads it.

Governance

This constitution has priority over other practices in core/. An amendment is a pull request that changes this file, updates the version and the Sync Impact Report, and updates any specification that the amendment affects. Versions follow semantic versioning: MAJOR for a removed or redefined principle, MINOR for a new principle or section, PATCH for clarifications.

Version: 1.0.0 | Ratified: 2026-09-22 | Last Amended: 2026-09-22