Repository navigation
docs: architecture v2, internal maintainer docs, and error-handling guide #858
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ce868bf
43ac5cb
5755b74
ef2117d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| # Internal docs | ||
|
|
||
| Maintainer-facing documents. Everything here is publicly visible in the | ||
| repository (the repo is public), but none of it is published on the docs | ||
| site or written for end users: expect maintainer context, working notes, | ||
| and process detail. | ||
|
|
||
| ## Index | ||
|
|
||
| | Document | Contents | | ||
| |---|---| | ||
| | [licensing.md](licensing.md) | Licensing decisions and per-file/per-crate license layout for the workspace. | | ||
| | [session-domain-diag.md](session-domain-diag.md) | Session domain model: provider/session vernacular, deployment diagrams, socket lifecycle, and bootstrap rules. | | ||
|
|
||
| ## Related corpora outside this directory | ||
|
|
||
| - `docs/specs/`, design specifications. | ||
| - `docs/spikes/`, time-boxed investigations. | ||
|
|
||
| Both are, like this directory, excluded from the docs site but remain | ||
| publicly visible in the repository. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| --- | ||
| title: Licensing stance | ||
| description: Internal record of the project's license posture, LGPL exceptions, and redistribution obligations. | ||
| --- | ||
|
|
||
| > This is internal documentation. It is not published to the docs site. | ||
|
|
||
| # Licensing stance | ||
|
|
||
| Minimal is licensed under Apache-2.0 (declared once in the workspace | ||
| `Cargo.toml` and inherited by every crate via | ||
| `license.workspace = true`). The license text lives at the repo root | ||
| (`LICENSE`); redistribution attributions live in `NOTICE`. Inbound | ||
| contributions are governed by the Contributor License Agreement (see | ||
| `CONTRIBUTING.md` and `legal/`). Dependency license policy is enforced | ||
| by `cargo deny` against `deny.toml`, which points back at this document | ||
| for the exceptions explained below. | ||
|
|
||
| ## LGPL exceptions in deny.toml | ||
|
|
||
| ### malachite family: document-and-accept | ||
|
|
||
| Five crates (`malachite`, `malachite-base`, `malachite-float`, | ||
| `malachite-nz`, `malachite-q`) are licensed LGPL-3.0-only and are | ||
| statically linked into our binaries. They are pulled in transitively via | ||
| the `nickel-lang-core` git dependency; we do not depend on them | ||
| directly. | ||
|
|
||
| Stance: document and accept. LGPL-3.0 §4(d)(0) requires conveying both | ||
| the Minimal Corresponding Source (the LGPL library source) and the | ||
| Corresponding Application Code (everything else needed to relink) in a | ||
| form suitable for relinking, via one of the GPLv3 §6 conveyance methods. | ||
|
|
||
| **Source-conveyance mechanism:** We rely on GPLv3 §6(d), providing a | ||
| network location from which to download the Corresponding Source. The | ||
| malachite crates are published on crates.io at pinned versions recorded | ||
| in `Cargo.lock`. Note that `Cargo.lock` itself only records registry | ||
| URLs and checksums; it does not convey the sources. The actual | ||
| conveyance depends on crates.io remaining available and retaining those | ||
| versions. | ||
|
|
||
| **Relinking form:** This repository (Corresponding Application Code) is | ||
| public, and anyone can rebuild the binaries with a modified malachite by | ||
| editing `Cargo.toml` to override the dependency. The statically linked | ||
| binary format does not impede relinking because users have the complete | ||
| application source. | ||
|
|
||
| **Risk acknowledgment:** If crates.io were to remove the pinned | ||
| malachite versions, the §6(d) conveyance would fail. For distribution | ||
| channels requiring stronger guarantees (e.g., air-gapped environments or | ||
| long-term archival), vendoring malachite sources under `vendor/` or | ||
| providing a §6(b) written offer valid for three years would be required. | ||
| Neither is currently implemented; the current stance is acceptable for | ||
| our distribution model (source-available binaries rebuilt on demand). | ||
|
|
||
| ### hakoniwa: linking exception, Linux-only | ||
|
|
||
| `hakoniwa` ships under LGPL-3.0-only WITH LGPL-3.0-linking-exception, | ||
| so static linking is expressly permitted without LGPL relink | ||
| obligations. Its footprint is Linux-only: it is used by `sandbox2` and | ||
| `minimald`, and no longer reaches macOS builds since `mctx` was | ||
| decoupled from it in #721. | ||
|
|
||
| ## Redistributed binaries in darwin release artifacts | ||
|
|
||
| The macOS (darwin/arm64) release artifacts redistribute two prebuilt | ||
| Apache-2.0 components, pinned in `vendor/`: | ||
|
|
||
| - libkrun v1.19.4 (`vendor/libkrun/libkrun.lock`), shipped as | ||
| `libkrun.1.dylib`, https://github.com/containers/libkrun | ||
| - gvproxy v0.8.9 from gvisor-tap-vsock | ||
| (`vendor/gvproxy/gvproxy.lock`), | ||
| https://github.com/containers/gvisor-tap-vsock | ||
|
|
||
| Apache-2.0 redistribution requires retaining the license and notices; | ||
| both are attributed in the root `NOTICE` file. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| --- | ||
|
norrietaylor marked this conversation as resolved.
Resolved
|
||
| title: minvmd | ||
| description: The host daemon that boots the Linux microVM hosting minimald, bridging the CLI to a Linux session daemon. | ||
| --- | ||
|
|
||
| This page embeds the maintained crate document | ||
| [`crates/minvmd/README.md`](https://github.com/gominimal/minimal/blob/main/crates/minvmd/README.md). | ||
|
|
||
| <!--@include: ../../crates/minvmd/README.md--> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| --- | ||
| title: Session composition | ||
| description: How session contributions flow from declarative sources to the Composition consumed by the apply layer. | ||
| --- | ||
|
|
||
| This page embeds the maintained crate document | ||
| [`crates/sessions/docs/COMPOSITION.md`](https://github.com/gominimal/minimal/blob/main/crates/sessions/docs/COMPOSITION.md). | ||
|
|
||
| <!--@include: ../../crates/sessions/docs/COMPOSITION.md--> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,20 +3,20 @@ | |
| ## Functional over Imperative | ||
|
|
||
| - Iterator chains over manual loops. map, filter, collect, try_fold, flat_map instead of for with mutable accumulators. Use for only when side effects dominate or control flow makes a chain awkward. | ||
| - Combinators on Option/Result. map, and_then, ok_or, unwrap_or_else, map_err — not match that reconstructs the same enum. | ||
| - Combinators on Option/Result. map, and_then, ok_or, unwrap_or_else, map_err, not match that reconstructs the same enum. | ||
| - Immutable by default. Only mut when required. Building a Vec by push? Try .collect(). | ||
| - No index-based iteration. .iter(), .enumerate(), .zip(), .windows(), .chunks() over for i in 0..xs.len(). | ||
|
|
||
| ## Idiomaticity | ||
|
|
||
| - Cheapest reference that works. &str over &String, &[T] over &Vec<T>, &Path over &PathBuf, impl AsRef<Path> at boundaries. | ||
| - impl IntoIterator<Item = T> for consuming a sequence; impl Iterator<Item = T> for returning one (avoid allocating). | ||
| - Make illegal states unrepresentable. Encode invariants in the type system: enums for mutually exclusive states (not bool flags + Options), non-empty collections via Vec1 or (T, Vec<T>), parsed types instead of | ||
| - Cheapest reference that works. `&str` over `&String`, `&[T]` over `&Vec<T>`, `&Path` over `&PathBuf`, `impl AsRef<Path>` at boundaries. | ||
| - `impl IntoIterator<Item = T>` for consuming a sequence; `impl Iterator<Item = T>` for returning one (avoid allocating). | ||
| - Make illegal states unrepresentable. Encode invariants in the type system: enums for mutually exclusive states (not bool flags + Options), non-empty collections via Vec1 or `(T, Vec<T>)`, parsed types instead of | ||
| validated-then-passed-as-string. If a function can't be called in some state, that state shouldn't typecheck. | ||
| - Newtypes for domain values (struct UserId(u64)) over bare primitives. Use the https://crates.io/crates/nutype crate when the type needs trivial invariants enforced (non-empty, range bounds, regex, trimmed, etc.) — it generates the | ||
| - Newtypes for domain values (struct UserId(u64)) over bare primitives. Use the https://crates.io/crates/nutype crate when the type needs trivial invariants enforced (non-empty, range bounds, regex, trimmed, etc.), it generates the | ||
| validating constructor and keeps the inner value unconstructable elsewhere. | ||
| - Default only when the default is meaningful. | ||
| - Cow<'_, str> for sometimes-owned, sometimes-borrowed values. | ||
| - `Cow<'_, str>` for sometimes-owned, sometimes-borrowed values. | ||
| - Builder pattern for types with more than a couple of fields or any optional config. Owned style: pub fn with_x(mut self, x: T) -> Self, never &mut self -> &mut Self. | ||
| - Cloning discipline. .clone() is fine for Arc/Rc and small Copy-ish types; cloning a String/Vec/HashMap to dodge the borrow checker means restructure or borrow instead. | ||
| - Captured-identifier formatting. format!("{path}") over format!("{}", path). | ||
|
|
@@ -25,7 +25,7 @@ validating constructor and keeps the inner value unconstructable elsewhere. | |
|
|
||
| ## Error Handling | ||
|
|
||
| - Library crates: typed error enum via thiserror. `#[derive(Debug, thiserror::Error)]`; `#[error("...")]` for Display, `#[from]` for From. Variants are distinct failure modes. Keep `#[non_exhaustive]` on public error enums. See [decision 0001](decisions/0001-rust-error-handling-strategy.md). | ||
| - Library crates: typed error enum via thiserror. `#[derive(Debug, thiserror::Error)]`; `#[error("...")]` for Display, `#[from]` for From. Variants are distinct failure modes. Keep `#[non_exhaustive]` on public error enums. See [Rust error handling](error-handling.md). | ||
| - Application crates: anyhow::Result for opaque propagation. Attach .context(...) / .with_context(|| ...) at layer boundaries. User-facing CLIs use color_eyre instead of anyhow for better-formatted reports. | ||
| - unwrap()/panic! only for broken invariants. unwrap() in tests only; in production use expect("why the invariant holds"). Never for recoverable conditions. | ||
| - Never swallow errors. No let _ = result; or .ok() discards without a comment justifying it. | ||
|
|
@@ -35,20 +35,21 @@ validating constructor and keeps the inner value unconstructable elsewhere. | |
|
|
||
| ## Async & Concurrency | ||
|
|
||
| - No blocking in async context. No std::fs, std::thread::sleep, blocking network, or sync Mutex held across .await — use tokio::fs, tokio::time::sleep, tokio::sync::Mutex. | ||
| - Don't reach for Arc<Mutex<T>> reflexively. Plain Arc<T> suffices if T is immutable after construction. Spawned tasks must satisfy Send + 'static — design data flow accordingly. | ||
| - No blocking in async context. No std::fs, std::thread::sleep, blocking network, or sync Mutex held across .await, use tokio::fs, tokio::time::sleep, tokio::sync::Mutex. | ||
| - No `tokio::task::block_in_place`. It interacts poorly with `hakoniwa`; move blocking work to `tokio::task::spawn_blocking` or a dedicated thread. | ||
| - Don't reach for `Arc<Mutex<T>>` reflexively. Plain `Arc<T>` suffices if `T` is immutable after construction. Spawned tasks must satisfy `Send + 'static`, design data flow accordingly. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lets also add that
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added under Async & Concurrency: "No |
||
|
|
||
| ## Logging | ||
|
|
||
| - Use tracing — no println!/eprintln! outside user-facing CLI output. Structured fields and spans, not interpolated strings: tracing::info!(pkg = %name, "building"), not info!("building {name}"). | ||
| - Use tracing, no println!/eprintln! outside user-facing CLI output. Structured fields and spans, not interpolated strings: tracing::info!(pkg = %name, "building"), not info!("building {name}"). | ||
|
|
||
| ## Conventions | ||
|
|
||
| - Every change: cargo clippy --all-targets -- -D warnings, cargo test. Justify any #[allow(...)] with a comment. | ||
| - unsafe requires a // SAFETY: comment covering every caller invariant. | ||
| - #[must_use] on Result-shaped returns, builders, and anything where silently dropping the value is a bug. | ||
| - #[non_exhaustive] on public enums/structs that may grow. | ||
| - Private by default. Widen to pub(crate) before pub. Curate the public API via pub use at the crate root — internal module paths shouldn't be part of the public surface. | ||
| - Private by default. Widen to pub(crate) before pub. Curate the public API via pub use at the crate root, internal module paths shouldn't be part of the public surface. | ||
| - Testing: behavior, not implementation; one concept per test; insta for snapshot-shaped output; integration tests under tests/ for cross-crate flows. | ||
| - No dead code, commented-out code, or ownerless TODOs. | ||
| - Dependencies: prefer std, then crates already in the workspace, then crates listed on https://blessed.rs before reaching elsewhere. Versions are pinned in the workspace Cargo.toml; crate-level Cargo.tomls inherit via workspace = true, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.