docs(.profile): initial organization profile

Adds the README.md that serves as the Einherjar framework's landing page
on the Gitea organization.

Covers the framework name and mythology, the 14-module inventory with
dependency relationships, the ASCII dependency graph, the contracts
governance law, and the "for those who come after" philosophy section.
This commit is contained in:
2026-05-27 17:28:33 -06:00
commit 6dc6217313
2 changed files with 135 additions and 0 deletions

121
README.md Normal file
View File

@@ -0,0 +1,121 @@
# Einherjar
> *For those who come after.*
A Go framework built from battle-tested production code — organized for teams,
documented for the developer who was never in the room.
---
## The Name
In Norse mythology, the **Einherjar** are the chosen — warriors who fell in battle
and were carried to Valhalla by the Valkyries. There they train, day after day,
preparing for Ragnarök. Not for themselves. For what comes after.
This framework carries that name deliberately. Every interface defined here, every
architectural decision recorded, every module boundary enforced exists for the
developer who will build on this code without ever speaking to its authors. No
tribal knowledge. No implicit conventions. **The documentation is the system.**
---
## What Is This
Einherjar is a collection of composable Go modules, each addressing one
infrastructure concern. The mental model is Spring Boot starters — not one framework
binary, but a curated set of independent modules with isolated dependency graphs.
Each module is its own `go.mod`. Import only what your service needs. A minimal CRUD
API requires exactly three: **`core` + `web` + one `db-*`**.
---
## Modules
| Module | Purpose | Depends on |
|---|---|---|
| [`contracts`][contracts] | Pure interfaces. The constitution of the framework. | — |
| [`core`][core] | Lifecycle, logging, errors, validation | `contracts` |
| [`web`][web] | HTTP server, middleware, routing, health | `contracts` `core` |
| [`auth`][auth] | Auth middleware, RBAC | `contracts` `web` `core` |
| [`auth-jwt`][auth-jwt] | JWT signing, token pairs, refresh | `contracts` `auth` `core` |
| [`auth-firebase`][auth-firebase] | Firebase authentication | `contracts` `auth` `core` |
| [`db-postgres`][db-postgres] | PostgreSQL client | `contracts` `core` |
| [`db-mysql`][db-mysql] | MySQL client | `contracts` `core` |
| [`db-sqlite`][db-sqlite] | SQLite client | `contracts` `core` |
| [`cache-valkey`][cache-valkey] | Valkey / Redis-compatible cache | `contracts` `core` |
| [`storage-minio`][storage-minio] | Object storage | `contracts` `core` |
| [`telemetry`][telemetry] | OpenTelemetry — `main` packages only | `contracts` `core` |
| [`worker`][worker] | Concurrent background worker pool | `contracts` `core` |
| [`httpclient`][httpclient] | Resilient outbound HTTP client | `contracts` `core` |
---
## Dependency Graph
```
contracts
└── core
├── web
│ └── auth
│ ├── auth-jwt
│ └── auth-firebase
├── db-postgres
├── db-mysql
├── db-sqlite
├── cache-valkey
├── storage-minio
├── telemetry ← import from main only
├── worker
└── httpclient
```
Data modules (`db-*`, `cache-*`, `storage-*`) never import `web`. Repositories do
not know HTTP exists. This boundary is absolute.
---
## The Law
`contracts` is the constitution of this framework — pure interfaces, zero
dependencies, permanent signatures. Changes flow **outward from `contracts`**, never
inward. Before any change to `contracts`, the blast radius is calculated: which
interfaces are affected, which modules implement them, which modules consume those.
Release sequence: `contracts` first, then implementors, then consumers.
Adding a method to a published interface is a breaking change in Go. It is not
permitted without a major version bump and coordinated updates across all
implementing modules.
---
## For Those Who Come After
Good code is not written for the machine. It is not even written for the deadline.
It is written for the person who will read it at 11pm six months from now, under
pressure, trying to understand what this thing does and why it was built this way.
Every ADR in this organization exists because a decision was made and the reasoning
behind it matters as much as the outcome. Every interface in `contracts` is as small
as it can be because the developer implementing it in a new context deserves to know
exactly what is required and nothing more.
This is the standard. Not the deadline.
---
[contracts]: https://code.nochebuena.dev/einherjar/contracts
[core]: https://code.nochebuena.dev/einherjar/core
[web]: https://code.nochebuena.dev/einherjar/web
[auth]: https://code.nochebuena.dev/einherjar/auth
[auth-jwt]: https://code.nochebuena.dev/einherjar/auth-jwt
[auth-firebase]: https://code.nochebuena.dev/einherjar/auth-firebase
[db-postgres]: https://code.nochebuena.dev/einherjar/db-postgres
[db-mysql]: https://code.nochebuena.dev/einherjar/db-mysql
[db-sqlite]: https://code.nochebuena.dev/einherjar/db-sqlite
[cache-valkey]: https://code.nochebuena.dev/einherjar/cache-valkey
[storage-minio]: https://code.nochebuena.dev/einherjar/storage-minio
[telemetry]: https://code.nochebuena.dev/einherjar/telemetry
[worker]: https://code.nochebuena.dev/einherjar/worker
[httpclient]: https://code.nochebuena.dev/einherjar/httpclient