Skip to main content

max / quasi

Seed quasi: the quasicoherent stack Router and scaffolder crates, both stubs. The repo exists so the boundary rule has a home: quasi owns the seams between code we own and the dependencies underneath, admitted only when a second implementation already exists. quasi-router may never import a host crate, and returns a description rather than markup. Design and sequencing in wiki quasi-overview.
Author: Max Johnson <me@maxj.phd> · 2026-07-28 20:19 UTC
Signed with PGP, not checked
Commit: 524055fe9e5877ebef8064143876d8159c235f5c
12 files changed, +306 insertions, -0 deletions
A .gitignore +7
@@ -1,0 +1,7 @@
1 + target/
2 + Cargo.lock.bak
3 + *.swp
4 + .DS_Store
5 + CLAUDE.md
6 + CLAUDE.local.md
7 + .claude/
@@ -1,0 +1,55 @@
1 + # Contributing
2 +
3 + Solo project. External contributions aren't accepted yet, the design is still
4 + moving. When that changes this file will grow.
5 +
6 + ## Working in this repo
7 +
8 + - Design and load-bearing decisions live in `~/Wiki/quasi-overview.md`, not here.
9 + - Work backlog is in GoingsOn (project `quasicoherent`), not `todo.md`.
10 + - Rust 2024 edition, latest stable toolchain.
11 + - `cargo deny check` must pass before commit. No GPL/LGPL/AGPL, ever.
12 + - `cargo fmt` + `cargo clippy --all-targets` clean.
13 + - Commits are concise, imperative, no emoji.
14 +
15 + ## The rule this repo exists to hold
16 +
17 + **Nothing in `quasi-router` may import a host crate.** Not `tauri`, not `axum`,
18 + not `wry`. Those are adapters written on top of the router, and the moment one
19 + of them appears in its dependency tree the stack has a host again.
20 +
21 + The same rule applies one level up: the router returns a description, never
22 + markup. A route that returns HTML is a webview route wearing a neutral name.
23 +
24 + ## Admitting a new boundary
25 +
26 + quasi owns seams, not vendors. Before adding a crate or a trait that wraps a
27 + dependency, answer one question:
28 +
29 + **Which two implementations does this have, today or already committed to?**
30 +
31 + If the answer is one, it is an indirection and it does not belong here yet. The
32 + lesson is recorded in `~/Wiki/makeover-geometry.md`: the hardest open question
33 + in that crate only got answered because a second consumer forced it, and the
34 + window to move the API shut within 48 hours of adoptions landing. Boundaries
35 + enter when the second implementation exists, not when it is imagined.
36 +
37 + Two further exclusions, both deliberate:
38 +
39 + - Ubiquitous and stable with no plausible alternative (`tokio`, `serde`,
40 + `tracing`, `chrono`, `uuid`, `thiserror`). Wrapping buys nothing.
41 + - Dependencies whose value *is* their API surface. `sqlx`'s compile-time-checked
42 + queries are the reason to use it, so quasi configures the driver and runs the
43 + migrations and queries stay written against `sqlx`.
44 +
45 + ## Adding a component crate
46 +
47 + Crates are scaffolded when they start, not up front:
48 +
49 + ```
50 + cargo new --lib crates/quasi-host-tauri
51 + ```
52 +
53 + Then add it to `Cargo.toml`'s `[workspace] members`, add the `[lints] workspace
54 + = true` block, and inherit `edition` / `rust-version` / `authors` / `repository`
55 + / `license` from `[workspace.package]`.
A Cargo.lock +11
@@ -1,0 +1,11 @@
1 + # This file is automatically @generated by Cargo.
2 + # It is not intended for manual editing.
3 + version = 4
4 +
5 + [[package]]
6 + name = "quasi"
7 + version = "0.0.0"
8 +
9 + [[package]]
10 + name = "quasi-router"
11 + version = "0.0.0"
A Cargo.toml +32
@@ -1,0 +1,32 @@
1 + [workspace]
2 + resolver = "3"
3 + members = [
4 + "crates/quasi",
5 + "crates/quasi-router",
6 + ]
7 +
8 + [workspace.dependencies]
9 +
10 + [workspace.package]
11 + edition = "2024"
12 + rust-version = "1.85"
13 + authors = ["Max Johnson <me@maxj.phd>"]
14 + repository = "https://makenot.work/git/max/quasi"
15 + license = "MIT"
16 +
17 + [workspace.lints.rust]
18 + unsafe_code = "forbid"
19 +
20 + [workspace.lints.clippy]
21 + pedantic = { level = "warn", priority = -1 }
22 + module_name_repetitions = "allow"
23 + missing_errors_doc = "allow"
24 + missing_panics_doc = "allow"
25 +
26 + [profile.release]
27 + lto = "thin"
28 + codegen-units = 1
29 + strip = "symbols"
30 +
31 + [profile.dev]
32 + opt-level = 1
A LICENSE +21
@@ -1,0 +1,21 @@
1 + MIT License
2 +
3 + Copyright (c) 2026 Max Johnson
4 +
5 + Permission is hereby granted, free of charge, to any person obtaining a copy
6 + of this software and associated documentation files (the "Software"), to deal
7 + in the Software without restriction, including without limitation the rights
8 + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 + copies of the Software, and to permit persons to whom the Software is
10 + furnished to do so, subject to the following conditions:
11 +
12 + The above copyright notice and this permission notice shall be included in all
13 + copies or substantial portions of the Software.
14 +
15 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 + SOFTWARE.
A README.md +71
@@ -1,0 +1,71 @@
1 + # quasi
2 +
3 + quasicoherent: the stack every Make Creative app is built on. `quasi` for short,
4 + and that is what you type.
5 +
6 + A quasi-coherent sheaf is determined by local module data on an affine cover and
7 + glues, with no finiteness demanded of the pieces. That is the architecture: one
8 + description per host context, agreeing on overlaps, renderers free to be unalike.
9 +
10 + ## What it is
11 +
12 + ```
13 + request (path + params)
14 + -> router this repo, imports no host crate
15 + -> description makeover-layout
16 + -> renderer webview | tui | egui
17 + -> host adapter axum route | Tauri protocol | wry | direct call
18 + ```
19 +
20 + The router answers with what a screen *is*. The host decides how that becomes
21 + pixels. One codebase reaches desktop, iOS, a terminal, egui, and a hosted web
22 + app, because the host is the boundary that stops mattering.
23 +
24 + ## What it owns
25 +
26 + Seams, not vendors. quasi owns the boundaries between code we own and the major
27 + dependencies underneath it, and the test for admitting one is:
28 +
29 + **Name two implementations that exist or are already committed to.** A boundary
30 + with one implementation forever is not a boundary, it is an indirection.
31 +
32 + By that test, in scope: the host (Tauri, wry, axum, direct call), the renderer
33 + (webview, tui, egui, via `makeover-layout`), database configuration and
34 + migration across SQLite and Postgres, and eventually a shared session and auth
35 + layer, which the server has and the desktop apps do not.
36 +
37 + Out of scope, deliberately: `tokio`, `serde`, `tracing`, `chrono`, `uuid`,
38 + `thiserror`. Ubiquitous, stable, and with no second implementation anyone would
39 + adopt, so wrapping them costs a translation tax and returns nothing.
40 +
41 + Also out of scope: anything whose value *is* its API surface. `sqlx`'s
42 + compile-time-checked query macros are the reason to use `sqlx`, so quasi owns
43 + which driver is configured and how migrations run, and queries stay written
44 + against `sqlx` directly.
45 +
46 + Boundaries already owned elsewhere stay where they are and are referenced rather
47 + than absorbed: `makeover` and `makeover-geometry` for colour and spacing,
48 + `synckit` for sync, `s3-storage` for blobs, `docengine` for rendered content,
49 + `tagtree` for tags. One repo per project. quasi names the stack and fills the
50 + seams that have no owner.
51 +
52 + ## Layout
53 +
54 + - `crates/quasi-router/` — the host-agnostic router. The keystone.
55 + - `crates/quasi/` — the scaffolder binary.
56 +
57 + Crates are added when their component starts, not up front.
58 +
59 + ## Status
60 +
61 + Nothing implemented. The repo exists so the boundary rule has a home and the
62 + router has somewhere to land. Both crates are stubs.
63 +
64 + The description layer this depends on is not written either, and the order of
65 + work runs vocabulary first, then renderers, then this. Design and sequencing
66 + live in the wiki note `quasi-overview`; the backlog is in GoingsOn under project
67 + `quasicoherent`.
68 +
69 + ## Licence
70 +
71 + MIT.
@@ -1,0 +1,15 @@
1 + [package]
2 + name = "quasi-router"
3 + version = "0.0.0"
4 + description = "Host-agnostic router: a request in, a renderer-agnostic description out"
5 + edition.workspace = true
6 + rust-version.workspace = true
7 + authors.workspace = true
8 + repository.workspace = true
9 + license.workspace = true
10 + publish = false
11 +
12 + [lints]
13 + workspace = true
14 +
15 + [dependencies]
@@ -1,0 +1,18 @@
1 + //! Host-agnostic routing: a request in, a renderer-agnostic description out.
2 + //!
3 + //! <!-- wiki: quasi-overview -->
4 + //!
5 + //! The keystone of the stack. A route answers with what a screen *is*, expressed
6 + //! in `makeover-layout`'s vocabulary, and the host decides how that becomes
7 + //! pixels. Returning markup instead would pin every consumer to a webview and
8 + //! hand the terminal and egui renderers an adapter, which is the failure the
9 + //! description layer exists to prevent.
10 + //!
11 + //! Nothing here may import a host crate. `tauri`, `axum` and `wry` are all thin
12 + //! adapters written on top of this, never dependencies of it. That rule is what
13 + //! keeps a host repriceable per app instead of welded into the view layer, and
14 + //! it is what lets the same route serve a desktop protocol handler and an HTTP
15 + //! endpoint with no second implementation.
16 + //!
17 + //! Not written yet. The vocabulary this returns has to exist first, and the
18 + //! order of work is on the wiki note.
@@ -1,0 +1,19 @@
1 + [package]
2 + name = "quasi"
3 + version = "0.0.0"
4 + description = "Scaffolder for the quasicoherent stack"
5 + edition.workspace = true
6 + rust-version.workspace = true
7 + authors.workspace = true
8 + repository.workspace = true
9 + license.workspace = true
10 + publish = false
11 +
12 + [lints]
13 + workspace = true
14 +
15 + [[bin]]
16 + name = "quasi"
17 + path = "src/main.rs"
18 +
19 + [dependencies]
@@ -1,0 +1,15 @@
1 + //! Scaffolder for the quasicoherent stack.
2 + //!
3 + //! <!-- wiki: quasi-overview -->
4 + //!
5 + //! The `create-t3-app` equivalent: produce a running app with a router, a
6 + //! description, renderers wired, migrations, themes materialised and a Bento
7 + //! config. Without it the stack is documentation about repos that happen to
8 + //! agree.
9 + //!
10 + //! Not written yet. It cannot generate a stack that does not exist, so it
11 + //! follows the router rather than leading it.
12 +
13 + fn main() {
14 + println!("quasi: not implemented yet. See wiki note quasi-overview.");
15 + }
A deny.toml +38
@@ -1,0 +1,38 @@
1 + # cargo-deny config. Load-bearing rule: NEVER GPL/LGPL/AGPL.
2 + # Per `~/Code/CLAUDE.md`, taking on a copyleft dep is incompatible with the
3 + # ecosystem's licensing plan (MIT for tooling, PolyForm-NC for products).
4 +
5 + [graph]
6 + all-features = true
7 +
8 + [advisories]
9 + version = 2
10 + yanked = "deny"
11 +
12 + [licenses]
13 + version = 2
14 + confidence-threshold = 0.9
15 + allow = [
16 + "MIT",
17 + "MIT-0",
18 + "Apache-2.0",
19 + "Apache-2.0 WITH LLVM-exception",
20 + "BSD-2-Clause",
21 + "BSD-3-Clause",
22 + "ISC",
23 + "Zlib",
24 + "Unicode-3.0",
25 + "Unicode-DFS-2016",
26 + "MPL-2.0",
27 + "CC0-1.0",
28 + "BSL-1.0",
29 + ]
30 +
31 + [bans]
32 + multiple-versions = "warn"
33 + wildcards = "deny"
34 +
35 + [sources]
36 + unknown-registry = "deny"
37 + unknown-git = "deny"
38 + allow-registry = ["https://github.com/rust-lang/crates.io-index"]
@@ -1,0 +1,4 @@
1 + [toolchain]
2 + channel = "stable"
3 + components = ["rustfmt", "clippy"]
4 + profile = "minimal"