Heimdall API

Documentation GitHub

Centralized identity management for many client systems at once —
each isolated inside its own scope.

Heimdall answers one question for every system that delegates to it — who is this caller, and what are they allowed to do? — while keeping each client system’s identities isolated from every other’s.

Built with ASP.NET Core on .NET 10, in a layered architecture with CQRS.

Multi-tenant by scope

Every User belongs to exactly one scope, a ScopeAdmin owns one or more, and a SystemAdmin governs the whole system and belongs to none.

A person has no scope column at all — the relationship is derived from their role.

Authentication that scales out

Password login with Argon2id, optional two-factor (authenticator app, email, recovery codes), and per-scope Google Sign-In.

Tokens are stateless signed JWTs — authentication reads no database per request.

Human and non-human identities

Persons, applications owned by a Scope Admin, and Google Users — plus scope-specific permissions that fold into the JWT issued for that scope.

Logical and hard deletion, with defined cascade rules.

Getting started

Prerequisites, environment configuration, migrations, and running the API locally — plus the start-up guards that fail loudly instead of failing later.

Set it up

Architecture & flows

Class diagrams for the layers and the domain model, and sequence diagrams tracing login, two-factor, Google Sign-In, onboarding and audit logging end to end.

See the diagrams

The specification

Vision, numbered functional and non-functional requirements, every use case with its alternative flows, the testing standard, and the development workflow.

Read the requirements

Tested at two layers

Unit tests for every handler and validator, functional tests driving the real API over HTTP against a PostgreSQL database provisioned by Testcontainers.

Browse the coverage report

Traceable to a requirement

Every endpoint cites the use case it implements and the requirements behind it, and the source code cites them back — so a line of code leads to the flow that demanded it.

See the endpoints