| 1 |
# Local dev defaults. Override path with SANDO_CONFIG. |
| 2 |
listen = "127.0.0.1:7766" |
| 3 |
db_path = "./sando.db" |
| 4 |
topology_path = "../sando.toml" |
| 5 |
# Hostname (/proc/sys/kernel/hostname) this daemon may build on. build::run |
| 6 |
# refuses to compile on any other host, so a misdeployed daemon can't build on |
| 7 |
# prod. Required. |
| 8 |
build_host = "fw13" |
| 9 |
workdir = "./work" |
| 10 |
release_root = "./releases" |
| 11 |
# Shared cargo target dir across per-sha worktrees — incremental rebuilds reuse |
| 12 |
# the previous sha's compiled deps instead of clean-compiling each fresh |
| 13 |
# worktree. Safe because builds are serialized. Omit for per-worktree target/. |
| 14 |
cargo_target_dir = "./cargo-target" |
| 15 |
# Dropped and recreated on every migration_dry_run. Leave unset to skip. |
| 16 |
# The role must be SUPERUSER on the scratch cluster: the gates reset it, seed the |
| 17 |
# dump's owner role into it, and drop stale mnw_test_* clones left by a killed |
| 18 |
# run (including foreign-owned ones, which DROP DATABASE refuses without |
| 19 |
# superuser). The daemon asserts this at startup and refuses to boot otherwise. |
| 20 |
# ALTER ROLE sando SUPERUSER; |
| 21 |
scratch_db_url = "postgres://sando@127.0.0.1/sando_scratch" |
| 22 |
# Role that owns the objects in a prod pg_dump. The dump carries `ALTER ... OWNER |
| 23 |
# TO <role>` for every object, so it must exist in the scratch cluster before a |
| 24 |
# restore; reset_scratch creates it NOLOGIN and grants it CREATE on public, so no |
| 25 |
# manual SQL is needed on a fresh box. Must match the prod DB owner. |
| 26 |
scratch_owner_role = "makenotwork" |
| 27 |
|
| 28 |
# Databases the migration_dry_run gate dry-runs, in order: restore that |
| 29 |
# database's prod dump into a scratch DB, then run the worktree's migrations on |
| 30 |
# top. `backup` names a [[backup]] entry in the topology (sando.toml). Omit the |
| 31 |
# whole key to get just the first entry, which is the historical behavior. |
| 32 |
# |
| 33 |
# The server check leaves `scratch_db` unset, so it runs against scratch_db_url |
| 34 |
# itself and leaves it in migrated state for the cargo_test gate to reuse. Every |
| 35 |
# other check must name its own database; the daemon creates it (DROP + CREATE) |
| 36 |
# at the start of the check, so a new entry owes no host bootstrap step. |
| 37 |
[[migration_check]] |
| 38 |
dir = "server/migrations" |
| 39 |
backup = "server" |
| 40 |
|
| 41 |
# multithreaded applies its own 36+ migrations at boot (multithreaded/src/main.rs, |
| 42 |
# `sqlx::migrate!()`) against its own database, so it carried the server's |
| 43 |
# exposure with none of the server's gate: an edited already-applied migration |
| 44 |
# would not fail a dry run, it would fail to boot in prod. `owner_role` is that |
| 45 |
# dump's owner — pg_dump emits `ALTER ... OWNER TO multithreaded` for every |
| 46 |
# object, and the role must exist in the scratch cluster before the restore. |
| 47 |
[[migration_check]] |
| 48 |
dir = "multithreaded/migrations" |
| 49 |
backup = "multithreaded" |
| 50 |
scratch_db = "sando_scratch_mt" |
| 51 |
owner_role = "multithreaded" |
| 52 |
|
| 53 |
# TypeScript frontends the code_smoke gate compiles. Both build scripts downgrade |
| 54 |
# a tsc error to a cargo::warning so the Rust build still succeeds against a |
| 55 |
# stale static/dist/; this is where that failure is fatal instead. See the |
| 56 |
# frontend_build docs in daemon/src/config.rs. |
| 57 |
[[frontend_build]] |
| 58 |
dir = "server/frontend" |
| 59 |
|
| 60 |
[[frontend_build]] |
| 61 |
dir = "multithreaded/frontend" |
| 62 |
|
| 63 |
# Companion crates built from the same worktree/sha as the server and staged |
| 64 |
# into the release bundle, so a contract-coupled service can't drift out of |
| 65 |
# lockstep. mnw-cli is the public git-SSH server that proxies to /api/internal/* |
| 66 |
# — a two-month drift is what broke git hosting during the 0.10.14 deploy. Which |
| 67 |
# nodes install it is set per-node in the topology (see prod-1 in sando.toml). |
| 68 |
[[companion]] |
| 69 |
name = "mnw-cli" |
| 70 |
manifest_dir = "mnw-cli" |
| 71 |
bin = "mnw-cli" |
| 72 |
|
| 73 |
# multithreaded (forums.makenot.work) runs on alpha-west-1, the same host as the |
| 74 |
# server, x86_64, so the build host can compile it and the never-cross-compile |
| 75 |
# rule is satisfied. Its own deploy path was multithreaded/deploy/deploy-hetzner.sh, |
| 76 |
# which cross-compiled on macOS via cargo zigbuild and scp'd to root@ — against |
| 77 |
# that rule, and 41 commits behind by the time it was found (2026-07-30). |
| 78 |
# |
| 79 |
# mt is a single file to install because it embeds its own `static/` tree |
| 80 |
# (multithreaded/src/static_assets.rs). It used to serve those assets off disk |
| 81 |
# beside the binary, which the one-file companion mechanism cannot ship. |
| 82 |
# |
| 83 |
# Note this is a companion and NOT an entry in `bin_names`: bin_names lists the |
| 84 |
# bin targets of the SERVER crate, resolved under its own target/release, so |
| 85 |
# naming multithreaded there would fail the build looking for a binary the |
| 86 |
# server never produces. Wiki sando-mt-pom-pipelines had it wrong. |
| 87 |
[[companion]] |
| 88 |
name = "multithreaded" |
| 89 |
manifest_dir = "multithreaded" |
| 90 |
bin = "multithreaded" |
| 91 |
|
| 92 |
# Crates the cargo_test gate runs, in order. This list used to be hardcoded to |
| 93 |
# `server`, so every other crate in the repo shipped ungated — including |
| 94 |
# mnw-cli, which is BUILT as a companion and installed onto prod-1 in the same |
| 95 |
# promote it ships. All of these were verified green on 2026-07-21 before being |
| 96 |
# added; the gate stops at the first red one. |
| 97 |
# |
| 98 |
# scratch_db exports DATABASE_URL/TEST_DATABASE_URL. Only the server needs it |
| 99 |
# (its sqlx macros type-check against a live DB). Leaving it off elsewhere keeps |
| 100 |
# crates that ship offline `.sqlx` data in offline mode. |
| 101 |
[[test_target]] |
| 102 |
dir = "server" |
| 103 |
features = ["fast-tests"] |
| 104 |
scratch_db = true |
| 105 |
|
| 106 |
# Companion: ships to prod-1, so it is gated first among the rest. |
| 107 |
[[test_target]] |
| 108 |
dir = "mnw-cli" |
| 109 |
|
| 110 |
[[test_target]] |
| 111 |
dir = "multithreaded" |
| 112 |
scratch_db = true |
| 113 |
|
| 114 |
[[test_target]] |
| 115 |
dir = "pom" |
| 116 |
|
| 117 |
[[test_target]] |
| 118 |
dir = "wam" |
| 119 |
|
| 120 |
# docengine left the repo for Libraries/docengine on 2026-07-30 and is consumed |
| 121 |
# through the [[aux_repo]] checkout, which sits BESIDE the worktree rather than |
| 122 |
# under it. `dir = "shared/docengine"` therefore stopped resolving that day and |
| 123 |
# quietly became a warn-and-skip, indistinguishable from a bisect skip: the gate |
| 124 |
# stayed green having run one crate fewer than it claims. `aux_repo` names the |
| 125 |
# checkout, and `dir` is empty because the crate is at that repo's root. |
| 126 |
# |
| 127 |
# Still worth gating despite living in another repo: the checkout is at branch |
| 128 |
# HEAD and is compiled into these binaries, so a break there breaks this build. |
| 129 |
[[test_target]] |
| 130 |
aux_repo = "docengine" |
| 131 |
all_features = true |
| 132 |
|
| 133 |
# No tests of its own yet; listed so a compile break still fails the gate. |
| 134 |
[[test_target]] |
| 135 |
dir = "shared/egui-updater" |
| 136 |
|
| 137 |
[[test_target]] |
| 138 |
dir = "shared/kberg" |
| 139 |
all_features = true |
| 140 |
|
| 141 |
[[test_target]] |
| 142 |
dir = "shared/livechat" |
| 143 |
all_features = true |
| 144 |
|
| 145 |
[[test_target]] |
| 146 |
dir = "shared/ops-core" |
| 147 |
|
| 148 |
[[test_target]] |
| 149 |
dir = "shared/ops-exec" |
| 150 |
all_features = true |
| 151 |
|
| 152 |
[[test_target]] |
| 153 |
dir = "shared/pom-contract" |
| 154 |
|
| 155 |
[[test_target]] |
| 156 |
dir = "shared/s3-storage" |
| 157 |
|
| 158 |
[[test_target]] |
| 159 |
dir = "shared/synckit-client" |
| 160 |
all_features = true |
| 161 |
|
| 162 |
[[test_target]] |
| 163 |
dir = "shared/tagtree" |
| 164 |
|
| 165 |
# ---- products ---- |
| 166 |
# Products this daemon ships. Declaring any of these means this file is no longer |
| 167 |
# both halves: the daemon keys stay here and each product points at its own |
| 168 |
# pipeline config. `mnw` points back at this same file, which is what keeps the |
| 169 |
# rest of it meaningful and what makes the change a pure addition — the routes |
| 170 |
# an operator types (`/promote/b`) still address MNW, and pom lives under |
| 171 |
# `/apps/pom/`. |
| 172 |
[app.mnw] |
| 173 |
config = "sando-daemon.toml" |
| 174 |
|
| 175 |
# pom is intake-only: Bento builds it on astra (aarch64) and Hetzner (x86_64), |
| 176 |
# Sando gates and promotes what arrives. See sando-pom.toml. |
| 177 |
[app.pom] |
| 178 |
config = "sando-pom.toml" |
| 179 |
|