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
Secureby default (session_cookie_secure: true); plain-HTTP local dev must opt out explicitly. - 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.
MSSQL and Oracle add their own dialects on top (opt-in via the
-tags mssql/-tags oraclebuild tags). Hiding any of this 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. Oracle multi-block PL/SQL scripts are
split correctly by
db.ExecScriptso the slash-terminator works as developers expect (see Models & database → Multi-block scripts). - The CLI is deterministic: the same
nucleus migrateagainst the same database ends in the same state.nucleus migrate driftreports divergence between the live schema and the registered models on every supported engine.
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.