Design decisions
Hilde records each design decision in writing, with its reason and the ways that were set aside; every record stays open to revision. These are the main ones, each in two or three sentences.
"unsafe" by module, and only where C is bound
A whole module is unsafe or safe, marked with pragma Unsafe_Module, and only an unsafe module may bind C, embed C or import raw memory. Address and pointer work belongs to the bindings; the module a programme imports is safe, and the compiler checks it. The switch --forbid-unsafe-modules exempts the compiler's built-in modules by their origin rather than by a list of names, which someone would have to keep in step.
Structured concurrency on fibers
Tasks and their resources hang on a scope and end with it; channel ends and task handles are linear, so a handle cannot be forgotten. The first design used operating system threads without a scheduler of its own; it was replaced by fibers instead of callbacks, as easy as Go but safe.
Contracts after Ada
requires and ensures are checked at run time and cannot be switched off; invariants of records, random tests made from the contracts, and proofs of simple cases followed. The contract of a public function stands once, in its interface, where every caller reads it.
Regular expressions in linear time
Standard.Regex is written in Hilde, a parser for RE2's syntax, the Thompson construction and a Pike VM, so a pattern cannot make matching take exponential time. Back references and lookaround are refused; who needs them chooses Standard.Pcre, which binds PCRE2, on purpose.
Templates compiled with the programme
Templates use the syntax of Jinja2, but the compiler translates them into Hilde statements and checks them against one record type. Nothing of the template is left at run time, no parser and no lookup by name. Where Jinja2 drops text silently, Hilde refuses the template.
SQL checked when the programme is compiled
Every @query and @execute is checked against the schema that the migration files build. SQL outside the accepted forms is refused with a message rather than compiled unchecked.
A sandbox has to report
A sandbox that cannot say what it did is worse than none: Standard.Sandbox returns a report that names only the mechanisms that took effect. The code comes from the sandbox written for Hiawatha, rebuilt step by step for Hilde rather than moved over as C.
Refuse instead of crash
Bad input gives None or Left with a reason, not an abort of the programme. A parser refuses rather than guesses.
Stable error codes
Every error carries a code that names one place in the compiler. The wording of a message may improve; the code stays, and a code that leaves the compiler is never given again.
FastCGI behind Hiawatha
A Hilde service does not face the network: it speaks FastCGI on a Unix socket, and Hiawatha holds the connections and TLS. Standard.Fcgi is only the record format, with no socket of its own, because a codec that owns its connection cannot be tested without one.
ML-DSA from libcrux
ML-DSA comes from the C code of libcrux that OpenSSH carries, so that OpenBSD needs no OpenSSL; it moves to LibreSSL once LibreSSL offers ML-DSA. The composite ML-DSA-44 with Ed25519 is valid only when both signatures hold, so a break of one method alone forges nothing.
Raft as a state machine
Standard.Raft holds no network, disk or clock; those belong to the caller. That makes every run deterministic and testable with partitions, and the invariants of the Raft specification can be stated as contracts.
Database drivers on demand
Standard.Database is one interface over SQLite, SQLCipher, PostgreSQL and MariaDB, and a driver is in a programme only when its module is imported.
Command lines after clap
Standard.Arguments follows the builder form of clap 4; every declaration returns a key, and an error on the command line does not end the programme by itself. clap's derive form has no counterpart.
A package manager of its own
The compiler and the package tool are two programmes; versions are git tags chosen by minimal version selection, dependencies are checked in under vendor/, and signify keys are taken on first use. Only get and update use the network.
Documentation in two languages
The main documentation is written in English and German, and the build checks hold the two catalogs of error codes to each other.