Skip to content

Repository Structure

Callora is the framework repository: a set of packable .NET 10 libraries plus first-party plugins and the documentation site. The runnable entrypoint and package composition live in the separate callora-production repository. The solution that ties everything together is Callora.Host.sln.

Top-level layout

text
src/                 framework libraries (the platform)
custom/              first-party plugins + the plugin SDK
tests/               xUnit test projects (Core + analyzers) and test plugins
docfx/               this documentation site
docs/                local design notes, ADRs, runbooks (gitignored in part)
scripts/             dev helpers (dev-build.sh, dev-test.sh, dev-check.sh, build-repo-map.sh)
ops/                 frontdoor config, Asterisk interop fixtures, runbooks
Callora.Host.sln     the solution
Directory.Build.props / Directory.Packages.props   shared build + Central Package Management
global.json          pinned .NET 10 SDK

Note: the admin and surface shells run colocated in the framework libraries — the Vue 3 admin shell in src/Administration (served at /admin) and the server-side surface runtime in src/Surface.Rendering (served at /surface-app). The former standalone Nuxt shells under apps/ have been retired.

src/ — the framework libraries

ProjectPackage / purpose
src/CoreCallora.Core — domain-neutral platform core: Identity/RBAC, tenancy, plugin lifecycle, the event bus, persistence, the operator API host surface. This is the library the distribution publishes as the host backend.
src/AdministrationCallora.Administration — operator API plus the colocated Vue 3 admin shell (Resources/app/administration). Ships its built SPA as a static web asset served at /admin.
src/WorkspaceCallora.Workspace — the workspace (surface) API. To be renamed Callora.Surface.
src/Surface.RenderingCallora.Surface.Rendering — server-side surface template rendering (Nunjucks on a hardened Jint sandbox, ADR-015) plus the colocated Vue surface runtime (Resources/app/surface) served at /surface-app.
src/Host/CliCallora.Host.Cli — the callora CLI (plugin contract-test kit, plugin sign).
src/AnalyzersCallora.Analyzers — Roslyn governance analyzers (CAL0001 internal-consumption guard, CAL0003 contract-documentation, extension-point-id analyzer). Referenced as an analyzer by the framework projects.

Each framework library carries PublicAPI.Shipped.txt / PublicAPI.Unshipped.txt for public-surface baseline tracking (any change to the public API shows up as a reviewable diff).

custom/ — plugins and the SDK

PathPurpose
custom/static-plugins/CommunicationSystem-tier VoIP/communication plugin (Callora.Plugin.Communication), bundled with the distribution. Ships its public contracts in src/Abstractions (Callora.Plugin.Communication.Abstractions).
custom/static-plugins/ComposerSystem-tier surface editor (Callora.Plugin.Composer).
custom/plugins/Empty by design — the install target for application-tier plugins, filled at runtime by the distribution or the operator API.
src/Surface.Rendering/Resources/app/surface@callora/surface — the surface runtime, and the package plugins compile against. Its src/public/ directory is the contract; there is no separate SDK package restating it. Apache-2.0.

Plugins carry their own EF Core migrations and live in an isolated plugin_<id> PostgreSQL schema (e.g. plugin_communication). See Migration & Rollback.

tests/

ProjectScope
tests/Callora.Core.TestsHost/core behaviour, plus architecture tests that enforce the structure rules (no nested/partial types, one type per file, DDD layering).
tests/Callora.Analyzers.TestsRoslyn analyzer verification.
tests/TestPlugins/*Plugin fixtures (e.g. Callora.TestPlugin.Exporting) used by the lifecycle tests.

Fast tests run without external services (in-memory stores). Slow tests are tagged [Trait("Category","Slow")] and use Testcontainers PostgreSQL — see Build & Release.

docfx/

The conceptual documentation site (this guide included) is built with VitePress under docs-site/. The .NET API reference is generated separately by DocFX (docfx/docfx.json, from the XML docs of src/**/*.csproj and custom/plugins/**/*.csproj, excluding tests and bin/obj) and served at /api/.

Module boundaries and dependency direction

The dependency direction is strict and enforced by analyzers and architecture tests. It is the single most important structural invariant a maintainer protects.

  • Core never references the modules. Administration, Workspace, and Surface.Rendering all reference Core; Core references none of them. Identity/RBAC and tenancy stay in Core.
  • Within every project, the DDD layering from CODE_STRUCTURE_RULES.md holds: Domain depends on nothing (no EF, no ASP.NET); Application depends only on Domain and defines ports as interfaces; Infrastructure implements those ports; Api stays thin and delegates to Application. Wiring (port → adapter) happens only in the composition root.
  • The API top level splits Workspace/ (tenant-scoped) from Admin/ (operator-scoped).
  • Plugins build against the contract, not against internals. Framework assemblies set CalloraFrameworkAssembly=true in their .csproj and may consume the [CalloraInternal] surface. Any other compilation — every plugin — leaves it false, and the CAL0001 analyzer rejects consumption of the internal surface. The contract surface (public contracts, Extensibility, [CalloraExtensible]) is the defined extension boundary.

Where this is heading

The plugins under custom/static-plugins move into their own private repositories and come back as packages. Their contracts stay public, so a third party can build against ICommunicationChannelRegistry without seeing the implementation — the surface a marketplace needs. See ADR-020.

One rule keeps that possible, and it is enforced rather than documented: no project under src/ may reference a plugin implementation. A reference to a plugin's .Abstractions project is fine — the distribution has to load the contract into the default assembly load context for type identity to hold. The architecture test PlatformDependsOnPluginContractsOnlyTests fails the build the moment someone draws the other edge, rather than when an outsider's clone stops restoring.

scripts/golden-path.sh is the counterpart: it packs, installs the CLI as a dotnet tool, scaffolds a plugin, builds it against the packages, runs the contract test and signs it. That is the only run in this repository that crosses the package boundary — and every problem the boundary hides was found by crossing it, never by the test suite.

Status: docs/REPO_MAP.md is auto-generated and, at time of writing, still reflects an older layout (src/Host, src/Contracts, src/Abstractions). The live filesystem and this guide are authoritative; regenerate the map with scripts/build-repo-map.sh when it drifts.