Principles
Five non-negotiable principles guide every decision in Nucleus. They are
formalised in SPEC.md;
this page is the human-readable summary.
1. Stdlib-first runtime
The runtime is built on net/http, database/sql, log/slog, and
context.Context. New third-party dependencies require an
ADR and a
dependency-impact review.
The reasoning is operational, not aesthetic:
- The standard library is the most reviewed Go code in existence; its semantics rarely surprise.
- Third-party deps are the dominant source of maintenance debt and supply-chain risk.
- Go's release cadence is predictable; building on the stdlib lets us adopt new features without coordinating across vendors.
When a dependency is genuinely worth taking — Asynq for the task queue, Casbin for RBAC, OpenTelemetry for tracing — the ADR records why, what the abstraction boundary is, and how we would replace it.
2. Explicit configuration & lifecycle
There are no hidden global singletons, no implicit init() registration,
no package-level state masquerading as the framework. Every Nucleus
application is created by an explicit call:
a, err := app.New(cfg, opts...)
The implications:
- Multiple
Appinstances coexist trivially in the same process — end-to-end tests run a realApp, not a mock. - Lifecycle is observable.
App.Runblocks;App.Shutdownruns hooks in reverse order;defer a.Shutdown(ctx)is enough. - Wiring is reviewable. The composition root is in
cmd/server/main.go(or in a fluent call when you opt in); nothing happens at import time.
3. Compatibility by contract
The stable surface is explicit:
- exported symbols in
pkg/*, - registered CLI commands,
- registered config keys.
Each of these is frozen by tests under
contracts/.
Removals require a deprecation entry; rename-and-keep-the-shim is the
default path. Details: Compatibility policy.
4. Security by default
Production-sensitive defaults ship enabled. The defaults are designed so that "I forgot to configure CSRF" looks like an explicit opt-out rather than a missing line:
- CSRF on for state-changing form posts.
- Session cookies
Secureinproduction. - CORS denies unknown origins.
- Rate limiting on every public endpoint.
- Argon2id password hashing with versioned cost parameters.
- TLS hardening on the embedded HTTP server when it is used directly.
Each setting is reachable from nucleus.yml. If you need to relax a
default, you do it deliberately, in writing.
5. SQL-first operations
There is no ORM. Migrations are SQL files; the CLI applies them in
order; queries are written in SQL. pkg/db adds database/sql
ergonomics, telemetry and health checks; pkg/model adds metadata for
the admin panel and CRUD helpers.
This is a constraint we want, not one we tolerate:
- Postgres, MySQL and SQLite all behave differently in subtle ways. Hiding that behind an ORM either produces the lowest-common-denominator query or quietly emits incompatible SQL.
- Migrations as SQL files are reviewable and replayable independently of the binary that wrote them.
- The CLI is deterministic: the same
nucleus migrateagainst the same database ends in the same state.
What follows from the principles
- The compatibility SLO has bite — see Compatibility policy.
- The CLI is a first-class product, not an afterthought — see CLI reference.
- The admin panel is part of the framework, not a separate project — see Features → Admin panel.