Expand description
@yah:ticket(R040-F16, “pg-on-mesh service recipe: bind tailscale0 + pg_hba.conf snippet + ufw rules”)
@yah:at(2026-05-05T00:32:34Z)
@yah:assignee(agent:claude)
@yah:status(review)
@yah:parent(R040)
@yah:handoff(“Companion to R040-F15. Inter-node TCP (Postgres primary↔replica, NATS clusters, anything raw-protocol) lives on the Headscale mesh, not on Hetzner public IPs. Each node has a stable 100.64.x.x mesh IP that survives replacement of the underlying box, so DNS / config / pg_hba never churn when a CPX-11 is rebuilt. WireGuard already encrypts the wire — TLS becomes defense-in-depth, not load-bearing. This ticket carries the concrete pg-shaped recipe so the first stateful service deploy doesn’t have to re-derive the pattern; subsequent services (redis, NATS, etc.) cargo-cult from it.”)
@yah:next(“ServiceConfig gains a bind_interface: Option<String> field (e.g. Some(\"tailscale0\") for mesh-only services). The cloud-init/podman compose renderer translates this into either --network host + pg listen_addresses = '<mesh-ip>' OR a podman macvlan/host-binding pattern that achieves the same.”)
@yah:next(“Generated pg_hba.conf snippet: allow the mesh subnet (100.64.0.0/10) for replication + app users. Postgres binds to the node’s tailscale0 mesh IP only — listen_addresses is templated from the node’s tailscale ip --4 at first boot.”)
@yah:next(“Generated ufw rules: ufw allow in on tailscale0 to any port 5432; ufw deny 5432 — mirrors the existing yah-yubaba 7443 pattern in mirror.yml. Same shape works for any mesh-only port.”)
@yah:next(“Replica connection string uses primary’s mesh IP, NOT its public IP. Stable across box replacement.”)
@yah:next(“Out of scope: pg_basebackup orchestration, failover, WAL archiving — those belong in noisetable’s domain; this ticket only standardizes the binding/firewall/auth shape so noisetable’s pg deployment doesn’t reinvent it.”)
@yah:ticket(R323-F9, “Add sync-wave ordering to ServiceComponent (deploy-panel wave order)”) @yah:assignee(agent:claude) @yah:at(2026-05-26T15:20:25Z) @yah:status(review) @yah:phase(P2) @yah:parent(R323) @yah:next(“ServiceComponent gains a wave/order field (or depends_on between components) so the deploy panel (R323-F4) can group workload rollout rows into sync waves (wave 0 parallel, wait healthy, wave 1, …). Today all components are implicitly wave 0.”) @yah:next(“compute_service/compute_cell in reconciler/sync_status.rs surface the wave per workload so F4 doesn’t re-derive it.”) @yah:gotcha(“Until this lands, F4 should render every workload as wave 0 (no ordering).”) @yah:handoff(“Added wave: u32 (serde default=0, skip_serializing_if zero) to ServiceComponent in config.rs. Added is_zero_u32 helper. Fixed the three struct literal call-sites that now need wave: 0 (config.rs test, local_sim.rs x2, mesofact_static.rs). Added wave?: number to the TS ServiceComponent interface with a doc comment. Deploy panel now reads c.wave ?? 0 for each WorkloadRow instead of hardcoded 0. SyncFooter computes maxWave from the components array and renders ‘wave 0’ (all-zero case) or ‘waves 0–N’ (multi-wave). All 218 cloud lib tests pass; bun run typecheck clean.”) @yah:verify(“cargo test -p cloud –lib # 218 passed”) @yah:verify(“cd packages/yah/ui && bun run typecheck # no new errors”) @yah:verify(“In service.toml: add wave = 1 to a component, rebuild, open the deploy panel — that workload row shows ‘w1’ badge; SyncFooter shows ‘waves 0–1’”) @yah:verify(“Component with no wave field in TOML deserializes as wave=0 (default). Saving a wave=0 component omits the field from the output TOML (skip_serializing_if).”)
@arch:see(.yah/docs/working/W142-pond.md)
@yah:relay(R615, “Linked infra sources: sources.toml overlay so a camp can borrow another camp’s substrate”) @yah:at(2026-07-20T18:18:05Z) @yah:status(open) @arch:see(.yah/docs/working/W274-linked-infra-sources.md)
@yah:ticket(R615-F1, “InfraSource types + SourcesConfig::load(infra_dir) parsing .yah/infra/sources.toml”)
@yah:status(review)
@yah:assignee(agent:bundle-anthropic-miravel)
@yah:at(2026-08-08T19:55:57Z)
@yah:phase(P1)
@yah:parent(R615)
@yah:next(“Add InfraSourceKind { Path { path }, Git(GitSource) } + InfraSource { owner, kind, mode, select } to cloud/src/config.rs. Reuse the existing GitSource (config.rs:1205, { repo, ref, subdir }) verbatim — do not invent a second git-source shape.”)
@yah:next(“SourcesConfig::load(infra_dir) reads .yah/infra/sources.toml (schema_version = 1, ordered [[source]] array). Absent file = empty list, never an error — every existing camp has no sources.toml.”)
@yah:next(“mode is the write-gate: read-only (borrower cannot mutate) vs owner-manages. Model it as an enum, not a bool, so a future read-write-with-approval tier is additive.”)
@yah:verify(“cargo check -p cloud && cargo test -p cloud”)
@arch:see(.yah/docs/working/W274-linked-infra-sources.md)
@yah:tier(Cleric)
@yah:handoff(“InfraSourceKind{Path{path},Git(GitSource)} + SourceMode{ReadOnly,Manage} + InfraSource{owner,kind,mode,select} + SourcesConfig{schema_version,source} all landed in oss/yubaba/crates/cloud/src/config.rs (after default_git_ref, ~line 1550). GitSource reused verbatim – Git(GitSource) wraps the existing R561 type unchanged, no second git-source shape. InfraSourceKind is internally tagged (#[serde(tag="kind", rename_all="kebab-case")]) and flattened into InfraSource so a [[source]] table reads exactly like W274’s example: owner/kind/path-or-repo+ref+subdir/mode/select all at one table level. mode: SourceMode defaults ReadOnly via #[serde(default)] on the field (enum, not bool, per the ticket’s own instruction – Manage is the explicit escape hatch). SourcesConfig::load(infra_dir) returns Ok(default()) – schema_version=1, empty source list – when sources.toml is absent; only parses+errors when the file exists and is malformed.”)
@yah:handoff(“Tree anchor 85801e7f. Pathspec: oss/yubaba/crates/cloud/src/config.rs (only file touched). Tests: cargo test -p yah-cloud –lib (from oss/yubaba) 710 passed / 0 failed / 4 ignored, +6 new over the 704 baseline your R707-T6 verification recorded (sources_load_is_empty_when_the_file_is_absent, sources_parses_a_path_kind_exactly_like_w274s_example, sources_parses_a_git_kind_reusing_gitsource_verbatim, sources_mode_defaults_to_read_only_and_manage_is_explicit, sources_preserves_declaration_order, sources_round_trips_through_serialize). cargo check -p cloud also green (implied by the test build).”)
@yah:handoff(“Tree anchor at handoff: 85801e7f6b76b369c0c8ecd2e5c7874990cd9286 — the shared tree as I left it. Diff against it (git diff 85801e7f6b76b369c0c8ecd2e5c7874990cd9286..HEAD) to see what landed under you, and quote this SHA rather than ‘HEAD’ in any revert/restore instruction.”)
@yah:next(“R615-F2 picks this straight up: overlay these sources into CloudConfig::load, tagging origin{owner,source} and merging camp-local-wins-on-collision.”)
@yah:handoff(“Verified pre-existing work: InfraSourceKind{Path,Git(GitSource)} + SourceMode + InfraSource + SourcesConfig all present in oss/yubaba/crates/cloud/src/config.rs at tree anchor 871fde1c, matching the inline @yah:handoff notes already on this ticket. GitSource reused verbatim, no second git-source shape. This session added no new code – only ran verification and closed the board state, which a prior session left stuck in open despite the work being done (code + handoff notes landed, but board.review/handoff was never called).”)
@yah:verify(“cargo check -p yah-cloud – clean (2 pre-existing unrelated warnings)”)
@yah:verify(“cargo test -p yah-cloud –lib – 723 passed; 0 failed; 4 ignored (from oss/yubaba)”)
@yah:ticket(R615-F2, “Overlay loader: resolve sources in CloudConfig::load, tag origin, camp-local wins on collision”)
@yah:status(review)
@yah:assignee(agent:bundle-anthropic-miravel)
@yah:at(2026-08-08T19:56:05Z)
@yah:phase(P1)
@yah:parent(R615)
@yah:next(“In CloudConfig::load, after loading camp-local machines/providers/rules, resolve each source to an infra root (git sources read from the .yah/cache/infra/ sync cache — load stays offline), load that root’s machines/providers/rules, tag each entry with origin { owner, source }, and overlay UNDER camp-local. Camp-local wins on name collision.”)
@yah:next(“The machine load site is config.rs:533 (load_dir::yah infra sync target directory must be so the two line up. An unsynced git source (cache dir absent) overlays nothing and is explicitly NOT an error (test: an_unsynced_git_source_overlays_nothing_and_is_not_an_error) – load() stays fully offline as W274 §3 requires.”)
@yah:handoff(“select filtering implemented for machines only (name exact-match or literal mesh_tags membership – not a glob engine, matches W274’s own example verbatim) via machine_matches_select(); does NOT apply to providers – documented as a deliberate choice, nothing in W274 or the ticket describes a provider-scoped filter.”)
@yah:handoff(“EXPLICIT DECISION on the config.rs:575-equivalent gotcha (now load_from_config_dir): sources overlay does NOT apply there. Multi-root sibling config dirs (W206 layout (b)) are a second config root INSIDE the same camp, not a second camp – .yah/infra/sources.toml is tied to paths::infra_dir(workspace_root) specifically, which has no well-defined meaning for an arbitrary config_dir. Documented in the function’s doc comment and proven by load_from_config_dir_never_applies_sources_overlay (a sources.toml at the real workspace root does NOT leak into a load_from_config_dir call against a sibling .noisetable/ dir under that same root).”)
@yah:handoff(“Tree anchor 85801e7f. Pathspec: oss/yubaba/crates/cloud/src/config.rs, oss/yubaba/crates/cloud/src/paths.rs (added infra_source_cache_dir + 1 test), oss/yubaba/crates/cloud/src/reconciler/mesofact_bundle.rs (CloudConfig test-literal fixed for the 2 new fields), app/yah/cli/src/cloud.rs (3 CloudConfig test-literal sites fixed, same reason). Tests: cargo test -p yah-cloud –lib (from oss/yubaba) 720 passed / 0 failed / 4 ignored, +10 over R615-F1’s 710 baseline (9 overlay tests in config.rs + 1 in paths.rs). cargo build -p yah –lib (repo root) green – confirms nothing downstream (agent-tools, cloud.rs, hub) broke from CloudConfig’s two new fields.”)
@yah:handoff(“Tree anchor at handoff: 85801e7f6b76b369c0c8ecd2e5c7874990cd9286 — the shared tree as I left it. Diff against it (git diff 85801e7f6b76b369c0c8ecd2e5c7874990cd9286..HEAD) to see what landed under you, and quote this SHA rather than ‘HEAD’ in any revert/restore instruction.”)
@yah:next(“R615-T3 (yah infra sync) is unblocked and has everything it needs: paths::infra_source_cache_dir(workspace_root, owner) is the exact target directory to clone/pull git sources into, already matching what F2’s overlay reads from.”)
@yah:next(“R615-F4 (Infra tab origin badge, not in my assigned lane) can read CloudConfig.machine_origins/provider_origins directly – no further backend plumbing needed for the badge itself.”)
@yah:handoff(“Verified pre-existing work: overlay landed in CloudConfig::load (oss/yubaba/crates/cloud/src/config.rs) at tree anchor 871fde1c – SourcesConfig::load resolves sources, overlay_infra_sources() merges under camp-local with camp-local-wins and earlier-source-wins collision rules, machine_origins/provider_origins BTreeMaps added to CloudConfig, load_dir_tolerant() added for per-file-tolerant foreign schema skew, InfraSource::infra_root() resolves path/git kinds, load_from_config_dir explicitly does NOT get the overlay (documented). Matches this ticket’s own inline @yah:handoff notes. This session added no new code – only ran verification and closed board state that a prior session left stuck in open despite the work being done.”)
@yah:verify(“cargo check -p yah-cloud – clean (2 pre-existing unrelated warnings)”)
@yah:verify(“cargo test -p yah-cloud –lib – 723 passed; 0 failed; 4 ignored (from oss/yubaba), includes overlay tests + load_dir_tolerant test + infra_source_cache_dir test in paths.rs”)
@yah:ticket(R605-F12, “Sovereign groups have no voting axis, so non-voting membership is inexpressible and the raft guard is enforced by an absent field”)
@yah:status(review)
@yah:at(2026-08-20T05:15:30Z)
@yah:assignee(agent:bundle-anthropic-ashguard)
@yah:parent(R605)
@arch:see(.yah/docs/working/W325-isolated-x86-build-capacity.md)
@yah:next(“OPERATOR INTENT (2026-08-19) that the model cannot currently record: us-west-003 is a NON-VOTING member of the us-west-001-based (prod) sovereign group, and us-west-011 is a DIFFERENT sovereign (dev) from 001/003. The dev/prod split is already declared correctly. The non-voting membership is not — us-west-003.toml declares no sovereign_group at all.”)
@yah:next(“THE GAP: MachineConfig::sovereign_group is a single Optionno-voter sat inert on three nodes asserting something nothing enforced.”)
@yah:next(“PROPOSED SHAPE (recommended): a second axis, e.g. sovereign_role = voter | non-voter (default voter for back-compat, or make it required), with judge_join permitting a same-group join only for voters. Then us-west-003 stamps prod + non-voter, the intent is machine-readable, and the raft guard stops depending on omission. us-west-004 (R605-T7) would take the same shape.”)
@yah:next(“TOUCHES TWO COPIES OF THE PREDICATE, do not fix only one: cloud::judge_join renders the camp-side refusal, but the predicate itself lives in workload_spec::sovereign::join_permitted because yubaba’s POST /raft/add-learner gate asks the same question and there is deliberately no yubaba -> cloud edge. Also re-read yubaba serve --sovereign-group, whose node-side gate is narrower on purpose (an unset flag means ‘declared nothing’, not ‘declared standalone’).”)
@yah:gotcha(“THE CODE AND THE OPERATOR CURRENTLY DISAGREE ABOUT 003, and a reader should know which is which before editing. judge_join’s own doc comment asserts ‘prod and dev are both stamped, and us-west-002/003/015 are deliberately not raft members’ — i.e. R742-F1 modelled 003 as STANDALONE. The operator’s model is that it is a NON-VOTING MEMBER of prod. Those are different claims, not a wording difference: standalone means no blast-radius relationship to 001 at all. Do not silently ‘correct’ either side; this ticket is the reconciliation.”)
@yah:gotcha(“FLEET STATE AS DECLARED (2026-08-19): prod = us-west-001, us-south-001, us-east-001. dev = us-west-011, us-west-013, us-west-014. NO sovereign_group declared = us-west-002, us-west-003, us-west-015. Verify against the files rather than trusting this list — xtask/tests/fleet_sovereign_groups.rs pins the roster and will need updating in the same change (it also asserts the stamp parses as a TOP-LEVEL key, which matters because 003 has a long comment block before [allocatable] where a stamp would silently become a member of that table).”)
@yah:gotcha(“SEPARATE AXIS, DO NOT ENTANGLE: mesh membership is not sovereign membership. The standing rule is ONE mesh for the entire fleet regardless of group (operator, 2026-08-19), so us-west-003 and us-west-011 enrolling in headscale is unrelated work with no design question in it — see R605-T10. A voting axis on sovereign_group must not become a reason to keep any node off the mesh.”)
@yah:gotcha(“SHARED-TREE COLLISION, live 2026-08-20: R772 (Miravel:spade, session:ce6d74a9) is refactoring oss/yubaba/crates/cloud/src/validate.rs at the same time and the file is currently RED - error[E0425] cannot find function load_machines at validate.rs:753, a half-landed extraction of the machine-loading walk that check_inert_taints / check_retired_arch_tags / the new check_unroled_sovereign_members all duplicate. That error is NOT from this ticket. Told them by party.chat and asked them to absorb check_unroled_sovereign_members into load_machines rather than leave one holdout. Do not hand-fight the file.”)
@yah:gotcha(“R772 ALSO BROKE THREE PRE-EXISTING INGRESS TESTS, again not this ticket: two_services_fronting_one_node_collate_into_one_front_door, a_cross_service_hostname_clash_is_reported_with_both_declarations, one_mirrors_broken_declaration_does_not_hide_the_rest - all failing with ‘providers.compute.use = hetzner - no such provider’. Cause is their new CloudConfig::load(workspace_root) at validate.rs:750 inside collate_workspace_ingress; the fronted_mirror fixture declares the slot but never writes infra/providers/hetzner.toml, and CloudConfig::load runs cross_ref_validate. Left alone deliberately - peer-owned.”)
@yah:gotcha(“TRAP THAT MADE THREE OF MY OWN TESTS PASS FOR THE WRONG REASON: the machine-lint sweeps SKIP unparseable TOMLs by design (a peer’s half-written scaffold must not sink the sweep). So a test fixture missing a REQUIRED MachineConfig field - mesh_tags is the one that bites - is silently skipped, the lint finds nothing, and every assert-empty test passes vacuously. Only the one test asserting found.len() == 1 noticed. write_sovereign_machine now always writes mesh_tags = [] and carries a comment saying why. Check this before trusting any new test in cloud::validate.”)
@yah:verify(“cargo test -p yah-workload-spec –lib sovereign (from oss/yah-base) – 9 passed, 0 failed. Covers both new refusals (a_non_voting_member_does_not_join_its_own_group, a_non_voting_target_has_no_quorum_to_join), the back-compat pin (the_default_role_is_the_pre_r605_f12_meaning), and the one-spelling round-trip across TOML/CLI/JSON.”)
@yah:verify(“cargo test -p yubaba –lib sovereign (from oss/yubaba) – 13 passed, 0 failed. Includes a_non_voting_joiner_is_refused_by_role_not_by_group, a_non_voting_target_refuses_every_joiner, a_group_without_a_role_key_is_a_voter_not_a_refusal (the deployed-fleet back-compat seam), a_peer_reports_its_role_in_the_toml_spelling.”)
@yah:verify(“cargo test -p yubaba –test raft_sovereign_group (from oss/yubaba) – 11 passed, 0 failed, up from 8. Three new end-to-end against real single-node rafts: a_non_voting_member_of_the_same_group_is_refused, a_non_voting_leader_refuses_to_grow_its_quorum, a_node_publishes_its_role_and_the_leader_reads_it_there (which also proves the request body cannot vote a non-voter in - the leader dials the joiner).”)
@yah:verify(“cargo test -p xtask –test fleet_sovereign_groups (from repo root) – 2 passed, 0 failed. THE DECISIVE ONE: parses the real .yah/infra/machines/.toml through the actual MachineConfig deserializer. Confirms us-west-003 = prod + non-voter on disk, all six pre-existing voters now stamped sovereign_role = voter explicitly, and neither key swallowed by a table header.”)
@yah:verify(“cargo test -p yah-cloud –lib (from oss/yubaba) – 891 passed, 3 failed, where all 3 failures were R772’s ingress-collate tests and none were mine. A clean re-run is BLOCKED, not failing: R555’s in-flight AdmissionGrant.secrets field breaks velveteen-exec, and yah-cloud is not a root workspace member so its dev-deps can only resolve from the oss/yubaba workspace. Re-run once R555 lands.”)
@yah:handoff(“LANDED, operator chose the second-axis shape (Call 1 = A, 2026-08-20). sovereign_role = voter | non-voter now sits beside sovereign_group, and ONE predicate judges both: workload_spec::sovereign::join_permitted(Membership, Membership) where Membership { group: Option<&str>, role: SovereignRole }. Permitted iff same non-None group AND both sides Voter. Both copies of the predicate call it - cloud::judge_join (camp-side) and yubaba::sovereign_group::judge (node-side) - so the rule itself cannot drift; only the prose differs, which was already the R742-F1 split.”)
@yah:handoff(“WHY THE ROLE IS CHECKED ON BOTH SIDES, since only the joiner half was asked for: a join grows a quorum and it takes two nodes. Refusing a non-voting JOINER is the us-west-003 case. Refusing a non-voting TARGET is the same assertion read from the other end - a box declared non-voting that is serving add-learner is already holding a raft seat its own declaration forbids, and permitting there would paper over the contradiction. Both refusals name the role rather than the group when the groups match, because a message reading ‘cross-group join refused: prod and prod’ reads as a bug in the check.”)
@yah:handoff(“THE DEFAULT IS THE LOAD-BEARING DECISION AND IT IS DELIBERATELY PERMISSIVE. An absent sovereign_role resolves to Voter (MachineConfig::sovereign_membership, the ONE place the Option is resolved). Reason: before this field, declaring a group WAS declaring quorum eligibility, so absence has to keep meaning that or the change silently retires six live voters. The permissiveness is bounded at the other end by cloud::validate::check_unroled_sovereign_members, which makes yah cloud validate FAIL on a group stamp with no role beside it - so the default can be reached by choice but not by silence. MachineConfig::sovereign_role stays Optionyah cloud validate, WARNING in the apply preflight - same split as inert-taint/retired-arch-tag, because an unwritten role changes no placement decision and the machine may be declared in a tree this camp does not own). yubaba/src/{sovereign_group,lib,main}.rs (–sovereign-role flag, ServerState.sovereign_role, /raft/status publishes it always-never-null, gate both directions). yubaba-test-harness/src/solo_node.rs (solo_node_with_sovereign_role). .yah/infra/machines/cargo run -p xtask -- emit-schemas from the repo root - it was queued behind ~7 concurrent peer cargo builds for the whole session. Nothing else is required to make this pushable.”)
@yah:handoff(“ALSO NOT RE-CONFIRMED: cargo test -p yah-cloud --lib needs a clean run. Its last real run was 891 passed / 3 failed with all three failures belonging to R772’s ingress-collate work and none to this ticket. The re-run is BLOCKED not failing - R555’s in-flight AdmissionGrant.secrets field breaks velveteen-exec, and yah-cloud is not a root workspace member so its dev-deps only resolve from the oss/yubaba workspace where that break lives. Re-run from oss/yubaba once R555 lands.”)
@yah:verify(“cargo run -p xtask – emit-schemas (from repo root) – wrote 8 files, exit 0 after an 18m24s build queued behind ~7 concurrent peer cargo jobs. .yah/schema/machine.toml.schema.json now carries the sovereign_role property (anyOf SovereignRole | null, with the full doc comment) and the SovereignRole definition as a oneOf over the two string enums voter / non-voter. The schema-drift-guard gate for THIS ticket is closed.”)
@yah:gotcha(“emit-schemas IS ALL-OR-NOTHING AND WILL PICK UP A PEER’S UNCOMMITTED WORK. Running it to close this ticket’s machine-schema drift also regenerated .yah/schema/secret.toml.schema.json (+34) from R555-F5’s in-flight SecretAccess::Recipes / RecipeMatch source. That output is CORRECT for the tree as it stands and was not hand-edited, but it means the schema diff in the working tree is not purely R605-F12’s: machine.toml.schema.json (+32) is this ticket, secret.toml.schema.json (+34) is R555. Told Ashguard:spade by party.chat so they carry it with their commit rather than regenerating on top. Anyone splitting these commits needs to split the schema diff too.”)
@yah:handoff(“ALL GATES CLOSED as of 2026-08-20. Both items listed as outstanding in the earlier handoff notes are done: emit-schemas ran (machine.toml.schema.json carries sovereign_role + the SovereignRole voter/non-voter enum, drift guard satisfied), and cargo test -p yah-cloud –lib is 896 passed / 0 failed once R555 and R772 settled. 45 tests green across workload-spec (9), yubaba lib (13), yubaba raft integration (11), yah-cloud lib (10 of this ticket’s, within 896), xtask fleet (2). Ready for review. NOTE for whoever commits: the working tree’s schema diff is not purely this ticket - .yah/schema/machine.toml.schema.json (+32) is R605-F12, .yah/schema/secret.toml.schema.json (+34) is R555-F5, both correct generated output from one emit-schemas run. Ashguard:spade has agreed to carry theirs.”)
@yah:verify(“cargo test -p yah-cloud –lib (from oss/yubaba) – 896 passed, 0 FAILED, 4 ignored. The blocked check from earlier is now clean: R555 landed the velveteen-exec and TransformRecipe.secrets fixes, R772’s ingress-collate work settled (they replaced the CloudConfig::load in collate_workspace_ingress with a narrower machines-only loader, so cross_ref_validate can no longer fail the collate over an unrelated provider typo). All 45 R605-F12 tests across the four crates are green simultaneously on one tree.”)
@yah:verify(“Confirmed by NAME rather than by total, since a passing count proves nothing about which tests ran: cargo test -p yah-cloud –lib – role voter voting lists all ten of this ticket’s cloud tests green - a_non_voting_member_is_refused_into_its_own_group, a_non_voting_target_has_no_quorum_to_grow, a_refusal_names_the_group_when_fixing_the_role_would_not_help, an_unwritten_role_still_joins_its_group, a_non_voter_is_still_in_the_group_it_names, sovereign_role_round_trips_and_is_omitted_when_unwritten, a_group_with_no_role_is_reported_with_the_declaring_file, either_stated_role_is_clean, a_machine_in_no_group_is_not_asked_for_a_role, unroled_findings_are_ordered_by_file_so_output_is_stable.”)
@yah:ticket(R876-B7, “Node taints are structurally inert for mirror-declared placements: you cannot drain a node, and it fails silently”)
@yah:at(2026-09-09T09:05:55Z)
@yah:status(review)
@yah:assignee(agent:bundle-anthropic-ashguard)
@yah:parent(R876)
@yah:severity(high)
@yah:next(“SECOND HALF, and it is what makes the relay’s headline question answerable: a working taint must produce a MOVE, not a refusal. Today regions=[] narrowing to zero candidates makes select_matching (config.rs:2010) bail by design ("a half-placed workload that reports success is worse than a failed apply"). A drain wants the opposite outcome — re-place onto a remaining candidate — which needs the slot to have more than one eligible machine in the first place. Pair this with R870-F16 (door follows the candidate set) or the drill still ends in a 503.”)
@yah:verify(“Reuse the drill rather than writing a new one: xtask/tests/apex_failover.rs already asserts the CURRENT (broken) taint behaviour against the real tree, so fixing this must flip those assertions — that is the regression gate. Then re-run the live half: taint us-east-001, confirm placement selects a different tag:cloud-runner machine, restore byte-exact, and confirm yah.dev stays 200 throughout.”)
@yah:gotcha(“IT FAILS SILENTLY, WHICH IS THE SHARP EDGE. "no-server" is a legal taint key, so the config lint passes and yah cloud reports nothing. An operator draining a node before maintenance gets a green run and a workload that never moved. The only lever that actually changes placement today is editing required.regions, and that REFUSES at resolution (select_matching bails rather than half-placing) instead of failing over — so there is currently no way to evacuate a node at all.”)
@yah:next(“Tier: Cleric — the mechanism is located and one-line-visible, but the choice between declarable repulsion and unconditional taint consultation changes the meaning of every existing placement in the fleet, and the fix has to land alongside a re-place path or it converts a silent no-op into a hard refusal.”)
@yah:gotcha(“MEASURED, NOT INFERRED — R876-S2’s drill, 2026-09-09. taints = [\"public-ip\", \"no-server\"] was written onto the REAL .yah/infra/machines/us-east-001.toml and the resolver still placed yah-marketing on us-east-001, unchanged. Restored byte-exact (diff empty, sha256 back to 17dd15e2…, git clean against blob d66ab6d8); yah.dev stayed 200 throughout and no mutating apply was run.”)
@yah:next(“THE MECHANISM, traced by R876-S2 and not yet re-verified by the leader. Taint repulsion keys off RequiredSpec::repel_archetypes; that field is #[serde(skip)] (oss/yubaba/crates/cloud/src/config.rs:4067), so a slot declared in a mirror’s required = {...} ALWAYS deserializes with it empty. matches (config.rs:4182) consequently never reads machine.taints at all. Confirm both line anchors before editing — the shared tree moves.”)
@yah:handoff(“SEMANTICS LANDED — repel-by-default + declarable toleration. RequiredSpec::repel_archetypes: Vec<LifecycleArchetype> (#[serde(skip)]) is DELETED and replaced by tolerates: Vec<String> (#[serde(default)], deserializable) at oss/yubaba/crates/cloud/src/config.rs:4319. matches (config.rs:4397) no longer iterates a field of self: it walks machine.taints, classifies each key through taint_effect, and rejects any TaintEffect::Repels(_) key the spec does not name in tolerates. That inversion is the only shape that survives a field the wire cannot carry — the old sense was opt-in-to-be-repelled, so a mirror-declared required = {...} always deserialized with an empty archetype set and machine.taints was never read at all. Entries are machine taint keys spelled exactly as the node writes them (no-appliance, not appliance), so the node side and the slot side share one vocabulary with no translation. NO WIRE OR SCHEMA SHAPE CHANGE: RequiredSpec is not a typed node in any emitted schema (a mirror stores required as a free-form value read by MirrorProviderSlot::required()), verified by rg \"RequiredSpec|tolerates|repel_archetypes\" .yah/schema/*.json — the only hits are prose inside a doc-comment description.”)
@yah:handoff(“THE MIGRATION TABLE — measured against the real tree, not reasoned about. FLEET TAINTS, all nine machines (grep -rE \"^\\s*taints\\s*=\" .yah/infra/machines/*.toml): us-east-001 [public-ip]; us-south-001 [no-appliance, public-ip]; us-west-001 [public-ip]; us-west-002 [no-server, no-appliance]; us-west-003 [no-appliance]; us-west-011 []; us-west-013 []; us-west-014 []; us-west-015 [no-server, no-appliance]. THE LOAD-BEARING FACT that makes this migration small: public-ip is an AFFINITY key (AFFINITY_TAINT_KEYS, taint_effect -> Attracts), NOT repulsion — so repel-by-default does not touch the three nodes carrying it, us-east-001 included. Reading every taint as repulsion would have evicted the apex on the next apply; only the no-<archetype> class repels. Exactly four machines are repelled by an undeclared spec: us-south-001, us-west-002, us-west-003, us-west-015. LIVE PLACEMENTS — the three required blocks that exist on disk (grep -rn required .yah/services/*/mirrors/*.toml): (1) yah-marketing providers.bundle, cloud.toml:213, {regions=[us-east], mesh_tags=[tag:cloud-runner]} -> us-east-001, UNCHANGED (its only taint is the affinity key). (2) yah-cloud providers.compute, {regions=[us-west], mesh_tags=[tag:cloud-runner]} -> us-west-001, UNCHANGED (us-west-003 newly drops out of the candidate set, but it sat behind us-west-001 in file-name order at replicas=1, so the resolved answer is identical). (3) yah-cloud-admin providers.compute, same constraint -> us-west-001, UNCHANGED. NET: repel-by-default moves ZERO live placements, so no toleration had to be added to any file under .yah/services/ or .yah/infra/ and none was. No file under .yah/infra/machines/ or .yah/services/ was written by this ticket at all.”)
@yah:handoff(“THE ONE PLACEMENT THAT DID MOVE, and it is a test fixture rather than a live slot — found by the test suite, not by the survey, which is why the survey alone was not sufficient. xtask/tests/mirror_ingress.rs::a_constraint_with_replicas_two_places_two_nodes_on_both_sides_and_renders_both builds a SYNTHETIC required = {mesh_tags=[tag:cloud-runner], replicas = 2} against the REAL fleet. Four machines carry tag:cloud-runner — in declaration order us-east-001, us-south-001, us-west-001, us-west-003 — and us-south-001 + us-west-003 both declare no-appliance, so the second slot moves us-south-001 -> us-west-001. My migration survey enumerated only the required blocks ON DISK and therefore missed it: at replicas >= 2 the candidate-set narrowing DOES change the answer even when replicas = 1 hides it. Recorded here because it generalises — any future slot that widens to replicas >= 2 over cloud-runners inherits this. Fixed at the site that caught it (mirror_ingress.rs:502) rather than by weakening the assertion, and the migration lever is asserted right beside it: a fourth fixture declaring tolerates = [\"no-appliance\"] recovers the exact pre-B7 pair [us-east-001, us-south-001] on BOTH resolvers, so an operator hitting this class of break can see the fix in the test that breaks.”)
@yah:verify(“BASELINE MEASURED BEFORE EDITING, then re-measured after. cargo test --manifest-path oss/yubaba/Cargo.toml -p yah-cloud --lib = 1129 passed / 0 failed / 4 ignored, exit 0 (the run completed and printed its result line before my first Edit; a deferred W298 skew advisory later named config.rs as modified during the watcher’s quiet window, which was my own subsequent edit, not a peer’s). AFTER: 1137 passed / 0 failed / 4 ignored, exit 0 — +8, exactly the eight tests added, and no pre-existing test broke. NOTE FOR RE-RUNNERS: cargo test -p yah-cloud --lib from the repo root FAILS with "package yah-cloud cannot be tested because it requires dev-dependencies and is not a member of the workspace" — yah-cloud lives in the oss/yubaba workspace, so the invocation needs --manifest-path oss/yubaba/Cargo.toml. Also cargo check --manifest-path oss/yubaba/Cargo.toml -p yah-cloud --all-targets exit 0 and -p yubaba --all-targets exit 0 (yubaba consumes cloud, so it is where the field removal would have surfaced). The four warnings in both are pre-existing and in files this ticket did not touch (mesofact_static.rs unused imports, app_manifest.rs dead field, pond_door.rs unused fn, reconciler/mod.rs non-snake-case).”)
@yah:verify(“EIGHT NEW UNIT TESTS in config.rs, covering the three shapes the brief asked for plus the migration invariants: an_undeclared_spec_is_repelled_by_a_repelling_taint (tainted machine excluded — asserted on a toml::from_str RequiredSpec, i.e. the mirror path reproduced exactly, not a hand-built literal); an_explicit_toleration_admits_the_tainted_machine_again (tolerated -> included, per-key not blanket, and it deserializes); an_untainted_machine_matches_exactly_as_before; an_affinity_taint_does_not_repel (public-ip on us-east-001 — the assertion that stands between this change and an evicted apex); select_matching_drops_a_tainted_candidate_and_keeps_the_rest (the set-level predicate: tainting candidate 1 moves the placement to candidate 2, and asking for both is a shortfall error not a half-placement); admission_preserves_archetype_scoped_repulsion_across_the_inversion (a Server spec built by admission_spec is still repelled by no-server and still NOT by no-appliance — the pre-B7 answer, which is what makes the admit_workload path behaviourally identical); describe_names_the_toleration_so_a_refusal_is_readable; a_toleration_alone_is_still_an_unconstrained_spec.”)
@yah:verify(“REGRESSION GATE FLIPPED, not deleted. cargo test -p xtask --test main (note: xtask has ONE test target named main; --test apex_failover does not exist — apex_failover is a mod in xtask/tests/main.rs). Result 65 passed / 1 failed. xtask/tests/apex_failover.rs: the drill’s finding-1 test was inverted and renamed every_repelling_taint_at_once_leaves_the_apex_bundle_exactly_where_it_was -> …_now_makes_the_apex_node_ineligible; it now asserts that ONE repelling key is enough (checked before the all-three case so a regression handling only the union is still caught), that all three refuse, and that restoring us-east-001’s real taint list ["public-ip"] puts the placement straight back. The module header was rewritten to say the hole is closed. ADDED repel_by_default_moves_no_live_placement_in_the_real_tree — the migration table as an executable artifact: it loads the real .yah/ tree, asserts all three live required blocks resolve to the same machines they did pre-B7, asserts none of them declares a toleration (so it is the undeclared shape being tested), and asserts the fleet-wide statement that exactly [us-south-001, us-west-002, us-west-003, us-west-015] are repelled by a bare spec — notably NOT us-east-001. THE ONE REMAINING FAILURE IS PRE-EXISTING AND NOT MINE: workload_envelope::every_on_disk_workload_toml_parses_through_the_envelope, on .yah/infra/state/sources/scrabcake/site/site/workload.toml (unknown field routes). That is R658-B1’s documented class (routes written under [build]); the path is gitignored generated runtime state (git check-ignore -> .yah/.gitignore:29 /infra/state/), was never committed, and R658-B1’s own @yah:next names this exact file. My change touches no workload-spec type — git status --porcelain -- oss/yah-base/ is empty.”)
@yah:handoff(“SCOPE BOUNDARY HELD, deliberately. yah-marketing’s candidate set was NOT widened: .yah/services/yah-marketing/mirrors/cloud.toml:213 still reads required = { regions = [\"us-east\"], mesh_tags = [\"tag:cloud-runner\"] } and only us-east-001 declares region us-east. So a working taint on the apex node still ends in a REFUSAL, not a move — select_matching bails on the emptied candidate set, which is the safe outcome and the same one drill finding 2 records for the membership axis. AN ACTUAL EVACUATION NEEDS THREE THINGS IN THIS ORDER: (1) B7, this ticket, which makes the taint readable at all; (2) R870-F16, so the front door follows the candidate set — filed and unstarted; (3) a widened required on the mirror. Doing (3) before (2) buys a workload that relocates and a yah.dev that 503s, which is why it was not done here. Both the inverted finding-1 test and the module header in xtask/tests/apex_failover.rs state that ordering at the site, so the next agent to read the drill cannot mistake "the taint works now" for "the node is drainable now". NO MUTATING COMMAND WAS RUN: no yah cloud apply, no hotship activation, and nothing under .yah/infra/machines/ was written (the three machine TOMLs showing modified were already modified at session start and their diffs touch no taint/region/mesh_tag line — checked).”)
@yah:handoff(“GENERATED ARTIFACTS REGENERATED, and one of them is a peer’s. cargo run -p xtask -- emit-schemas was required because my doc-comment rewrite on MachineConfig::taints lands in the schema description — schema_drift::committed_schemas_match_current_rust_types was red on machine.toml.schema.json. The regen also swept in mirror.toml.schema.json (+7 lines), which is NOT mine: it is a passway_image field carrying an R870-F16 doc comment, pre-existing uncommitted drift from whoever owns that ticket. My change cannot have caused it — RequiredSpec is not a typed node in any emitted schema. Regenerated per CLAUDE.md / the shared-tree rule that derived files are not ownable and a red drift gate whose signal decays to zero is the worse outcome. @Glimmerstone:griffin holds R870-F23 and the R870 line: the mirror schema now carries your passway_image description, so if you were about to regenerate, it is already done. Both schema files are the only two under .yah/schema/ that changed.”)
@yah:verify(“STEP 0 — @Glimmerstone:griffin’s R876-B5 (tenant-scoped hotship activation) INDEPENDENTLY CONFIRMED, all four checks green, nothing fixed. (1) bash -n scripts/hotship.sh clean. (2) ./scripts/hotship.sh --nodes us-east-001 --binaries mesofact REFUSES with exit 1 and the message "–services is required to ACTIVATE a bundle-serve app (mesofact)" — it refuses rather than falling back to the old broad runtime-path pattern, and the guard sits at hotship.sh:507 ahead of the version stamp and every remote call. (3) --dry-run --services yah-marketing previews the scope without touching anything and the scoping is real: "in scope [yah-marketing]: pid 619423 / pid 619436 bundle dd8bdfb75a53" versus "NOT restarted (out of scope): pid 614524 bundle 86b2fa81bf42 service noisetable", ending "dry run: nothing signalled / NOTHING was installed". (4) noisetable’s serve is ALIVE AND UNRESTARTED on us-east-001: pgrep shows pid 614524 off /var/lib/yah/kamaji/bundles/runtimes/mesofact/0.8.32/x86_64-unknown-linux-musl/serve, and ps -o lstart reads "Wed Sep 9 07:45:39 2026" — the expected pid at the expected unchanged start time, etime 01:01:38. curl -sS -o /dev/null -w %{http_code} https://yah.dev/ = 200. No real hotship activation was run.”)
@yah:verify(“BUILDS. cargo build (root workspace) exit 0 — run twice independently, 5m18s and 3m13s, both green; the root workspace is where the change surfaces beyond oss/yubaba because yah-cloud reaches the CLI through the [patch.crates-io] bridge. cargo check --manifest-path oss/yubaba/Cargo.toml -p yubaba --all-targets exit 0. Clean re-measure of cargo test --manifest-path oss/yubaba/Cargo.toml -p yah-cloud --lib after all annotation writes: 1137 passed / 0 failed / 4 ignored, exit 0 — identical to the first post-change measurement, so the earlier W298 skew advisory naming config.rs was my own board_update writes landing doc-comment annotations in the module header, not a peer edit. A later advisory on the root build named app/yah/cli/src/cloud.rs, which is a live peer’s file and not one this ticket touched; the build was exit 0 regardless. FILES CHANGED BY THIS TICKET, complete: oss/yubaba/crates/cloud/src/config.rs, xtask/tests/apex_failover.rs, xtask/tests/mirror_ingress.rs, .yah/schema/machine.toml.schema.json, .yah/schema/mirror.toml.schema.json. Nothing under .yah/infra/ or .yah/services/ was written, no git write/revert/checkout was performed, and every edit went through the editor.”)
@yah:handoff(“LEADER DECISION, so the semantics question is settled and should not be reopened: MACHINE TAINTS REPEL BY DEFAULT, with an explicit tolerates on the slot to opt back in. The old design inverted the obvious meaning — a taint had no effect unless the WORKLOAD declared which taints repelled it, i.e. taints were opt-in-to-be-repelled, which is both backwards and precisely why they silently did nothing. repel_archetypes was deleted rather than kept behind a flag defaulted to the old behaviour (CLAUDE.md, "break it, don’t tape it").”)
@yah:verify(“LEADER RE-VERIFICATION: this courier independently re-checked all four of @Glimmerstone:griffin’s R876-B5 live claims as its step 0 and confirmed every one — bash -n clean, the --services refusal exits 1 with no fallback to the old broad pattern, --dry-run scopes to yah-marketing while excluding noisetable, noisetable’s pid 614524 still alive with lstart 07:45:39 unchanged, and yah.dev 200. Cross-courier verification is why R876-B5 could be signed off on more than its own author’s word.”)
@yah:gotcha(“THE MIGRATION WAS THE RISK AND IT CAME BACK EMPTY, WHICH IS THE THING TO KNOW: public-ip — the taint that looked most likely to be load-bearing — is an AFFINITY key, not a repulsion key, so none of the three live mirror-declared placements (yah-marketing bundle to us-east-001; yah-cloud and yah-cloud-admin compute to us-west-001) changed, and no toleration was needed anywhere on disk. The one placement that did move was a synthetic replicas = 2 test fixture, where us-south-001’s no-appliance taint now yields us-west-001; it was fixed at that site with a tolerates fixture proving the pre-B7 pair is still expressible. Do not read the empty migration as "taints were unused" — read it as "the one taint in wide use happened to be on the affinity axis".”)
@yah:ticket(R870-F23, “Render and supervise the inner door: the service.toml + domain-manifest join that feeds passway’s PathRouter config”)
@yah:status(review)
@yah:phase(P2)
@yah:at(2026-09-11T00:25:14Z)
@yah:assignee(agent:bundle-anthropic-ashguard)
@yah:parent(R870)
@yah:next(“THE CONSUMER SIDE IS DONE AND ITS FORMAT IS FIXED (R870-T18, in review). A passway binary becomes a service’s own inner door by setting PASSWAY_PATH_ROUTES_FILE to a JSON mount table: {"schema_version":1,"routes":[{"mount":"","upstreams":["127.0.0.1:8081"]},{"mount":"/app","upstreams":["127.0.0.1:8082"],"headers":{"cross-origin-opener-policy":"same-origin"}}]}. Parser + validation: oss/passway/crates/passway/src/path_routes_file.rs (serde, deny_unknown_fields, schema_version must be 1, empty table refused, mount-with-no-upstream refused; mount well-formedness and duplicate-mount rejection are left to PathRouter::new so there is exactly one validator). Proven end to end against a FORKED binary in oss/passway/crates/passway/tests/path_routes_file.rs. This ticket is the producer: write that file.”)
@yah:next(“WHY THIS IS A SEPARATE TICKET AND NOT HALF OF R870-T18. T18’s own escape clause names the criterion — "a different crate, a different release cadence" — and it is met twice over. (a) The consumer is oss/passway, an independently versioned crate with its own export mirror; the producer is oss/yubaba (the join) plus oss/yah-base (the wire type) plus oss/kamaji (supervision), which roll to the fleet on a different cadence. (b) Nothing can reach a live inner door today because there is NO WORKLOAD KIND for one: WorkloadSpec carries typed per-kind carriers (MesofactServeBundle at oss/yah-base/crates/workload-spec/src/lib.rs:1437) and a passway inner door needs its own — plus a kamaji-allocated port, a routes file materialized on the node, and a place in the bundle deploy sequence. Landing a planner that nothing calls would have been the half-build T18 forbade.”)
@yah:next(“THE JOIN, PRECISELY — no new vocabulary, which is R870-F15’s own claim and it holds up. Inputs: .yah/services/cargo test --workspace --all-features in oss/kamaji, reproducibly, and PASSES 303/303 under cargo test -p kamaji-bin --lib --all-features both parallel AND –test-threads=1. So it is cross-PACKAGE contention, not in-package parallelism and not this change: the failing assertion is the second deploy failing to Ack after free_port() (server.rs ~:8667) handed back a port another package’s test binary had taken between the probe and the bind — a TOCTOU in the helper. Nothing in this ticket adds a port or touches that path; WorkloadSpec::files cannot reach it, since Workload::TenantPassway carries a TenantPasswayWorkload and no WorkloadSpec at all. Worth a real fix (bind-and-hold instead of probe-and-release) but it is not this relay’s.”)
@yah:gotcha(“ROLL ORDER MATTERS AND IS NOT THE USUAL "JSON IGNORES UNKNOWN KEYS" ANSWER — flagged by @Ashguard:eclipse (session:e188ccc2, R881-T6) mid-session. All three prod voters now run kamaji+yubaba 0.8.37-h5 (us-south-001 and us-west-001 rolled 2026-09-09; us-east-001 on 0.8.37-h1/h2), all built BEFORE WorkloadSpec::files existed. WorkloadSpec has no deny_unknown_fields, so on the JSON leg an un-rolled node ignores the field exactly as R870-B6’s origin did. The postcard leg is the one that does NOT forgive: it is positional and non-self-describing, so a new yubaba encoding a spec with a trailing files to an old kamaji decoder is a DESYNC, not an ignored key. Before deploying any inner door, confirm which codec that node’s kamaji link uses (kamaji-proto/src/codec.rs) and roll kamaji first if it is postcard. Nothing regresses until something actually SETS files — every existing spec encodes an empty vec — but the ordering is a real constraint, not a formality.”)
@yah:handoff(“WIDER THAN THE TITLE, all mechanical and all compiler-verified. Adding two fields to types this many call sites construct exhaustively meant ~45 initializer repairs across FOUR workspaces: oss/yah-base (workload-spec + local-driver), oss/kamaji (incl. peer-owned kamaji-proto/src/codec.rs and kamaji-containerd-core), oss/yubaba, and the root (crates/yah/hub, app/yah/cli). Each is one line — files: Vec::new(), or deploy: Default::default(), — with no semantic content; they were driven off E0063 spans, not grep, so none was guessed. NOTE the sweep needs –all-features AND cargo test --no-run: cargo check --all-targets alone missed sites behind feature gates and in examples/. ALSO REGENERATED (both are pure functions of the tree, so this is not authorship): .yah/schema/{workload,service}.toml.schema.json via cargo run -p xtask -- emit-schemas and packages/yah/workload-spec/index.ts via the export-ts bin. Both drift gates still report red because they compare against GIT, and this camp defers commits — they go green with the commit, and the regenerated content is correct.”)
@yah:handoff(“PHASE 1 DONE — the tier EXISTS and every piece of it is proven in isolation: the cleartext listener (proven through a forked binary), the vocabulary, the join with both admission rules, the wire carrier, and node-side materialization + restart. What is NOT done is the last hop: nothing CALLS plan() yet, so yah cloud apply still produces no inner door. That is deliberate rather than abandoned — it is placement work with a live-fleet verify attached, and it is the whole of phase 2.”)
@yah:handoff(“Tree anchor at handoff: 6f984b53a9dd1a291d29fe7d4cb544b47d4f65e6 — the shared tree as I left it. Diff against it (git diff 6f984b53a9dd1a291d29fe7d4cb544b47d4f65e6..HEAD) to see what landed under you, and quote this SHA rather than ‘HEAD’ in any revert/restore instruction.”)
@yah:next(“ONE DESIGN QUESTION PHASE 1 LEFT OPEN, stated so it is not rediscovered as a bug. A bundle-tier component at a non-root mount now gets its own entry in the inner-door table pointing at the SAME bundle upstream, purely so the domain manifest’s per-path response headers can be applied (see a_bundle_components_sub_mount_keeps_its_headers_and_the_bundle_upstream). That is correct for headers and harmless for routing, but it means the inner door re-states routing the bundle already does internally. If the outer door or the Worker is ALREADY applying those headers for a config-1 service, the inner door would apply them twice — check which tier owns route headers for a passway front door before wiring step 4, because R746 put ROUTE_HEADERS into the Cloudflare Worker and I did not confirm the passway-front-door equivalent.”)
@yah:verify(“THE LIVE HALF, unrun and needing a fleet: a two-component service whose components deploy independently gets one inner door from one yah cloud apply, with https://<host>/ and https://<host>/app/ both 200 and curl -sI on /app/ carrying cross-origin-opener-policy: same-origin AND cross-origin-embedder-policy: require-corp while / carries neither. The config-side half of exactly that assertion is already green as inner_door::tests::each_mount_carries_only_its_own_routes_headers, and the transport-side half as the forked-binary cleartext test — what remains unproven is only that apply joins them. THE NEGATIVE’S node-side half is also unrun: for a single-component service (yah-marketing), assert NO routes file is materialized on the node and NO extra workload appears in kamaji’s table.”)
@yah:next(“PHASE 2 IS FIVE STEPS AND EVERY INPUT ALREADY EXISTS. (1) Call inner_door::plan(&svc.service, &cfg.domains) once per service in the apply path; Ok(None) is the common answer and means do nothing at all. (2) Allocate the loopback port. It is deliberately a PARAMETER of InnerDoorPlan::workload rather than config — which port is free is a property of the node — so this is the only genuinely new decision: either take it from kamaji’s ledger (oss/kamaji/crates/kamaji/src/ports.rs) or pin one per service. (3) Resolve each DeployedUnit to an address for the address closure: DeployedUnit::Bundle is the service’s one bundle workload (R870-B11), DeployedUnit::Component(id) is that component’s own workload. (4) Deploy the rendered workload in the bundle deploy sequence — BEFORE the outer door is repointed, since the door 503s until its upstream is up. (5) Repoint the outer door’s PASSWAY_UPSTREAMS at 127.0.0.1:<port> instead of at the bundle, via IngressPlan::resolve_upstreams (oss/yubaba/crates/cloud/src/reconciler/ingress.rs:397).”)
@yah:handoff(“DEFECT IN THIS TICKET’S OWN CHANGE, CAUGHT IN REVIEW BY @Ashguard:eclipse (session:e188ccc2) AND FIXED BEFORE IT LEFT THE TREE. WorkloadSpec rides the postcard Deploy frame (kamaji-proto/src/messages.rs:373, and V7’s own stanza names Workload::Container(WorkloadSpec) as what that frame carries), and kamaji-proto/src/version.rs states the rule twice: every field on a postcard message is mandatory and always encoded, and the only compatibility mechanism is a ProtocolVersion bump. V2/V4/V5/V6 were each exactly "a field appended to a struct" and each got one. files is that shape and I had not bumped. The reasoning that made me miss it is the one V6’s stanza already refutes: #[serde(default)] makes an OLD spec decode fine, so the JSON leg really is unaffected — but default only affects DEserialization, so a new yubaba still ENCODES a length varint an old kamaji reads as the next field and misparses from there. Now V8, CURRENT = V8, with a stanza naming the wrong reasoning rather than only the rule. cargo test -p kamaji-proto –all-features = 33/0; oss/kamaji workspace = 18+208+5+303+2+2+2+1, 0 failed.”)
@yah:gotcha(“CORRECTION TO THE FLAKE GOTCHA ABOVE — my characterization was too narrow and would mislead the next reader, so read this one instead. I wrote that the tenant_passway digest test is "green 303/303 in-package, fails only workspace-wide". @Ashguard:eclipse measured the counter-example on the same tree: cargo test -p kamaji -p kamaji-bin --lib --all-features, in-package and parallel, failed a DIFFERENT test in the same module — deploy_arms_the_declared_socket_and_stop_releases_it (server.rs:8590) — and it failed identically before my sweep. On my own later run the workspace-wide invocation came back 303/0. So the truth is: at least two tests in server::tests::tenant_passway are intermittently flaky in BOTH configurations, the cause is free_port() probe-and-release losing the port between the probe and the bind (server.rs ~:8667), and it predates R870-F23. Do NOT read an in-package red there as a regression, and do not read a single green run as proof either. The fix is bind-and-hold; it belongs to neither R870 nor R881 and is unfiled — @Ashguard:eclipse tried and board.open refused for want of a parent relay.”)
@yah:gotcha(“CONSEQUENCE OF THE V8 BUMP FOR ANY FLEET OPERATION, not just for this relay — relayed by @Ashguard:eclipse (session:e188ccc2) who is holding the fleet on R881-T6, and worth acting on before the next roll. The tree is now ProtocolVersion::V8; EVERY node runs a pre-V8 pair (us-east-001 on 0.8.37-h1/h2, us-south-001 and us-west-001 on 0.8.37-h5, the other six on 0.8.28-0.8.34). Nothing is broken, because each node is internally matched and the protocol is a node-local UDS. What changed is that hotship --binaries yubaba ALONE — or kamaji alone — is now a footgun on every node: it puts a V8 binary against a V7 sibling, and per version.rs:71 that does not fail cleanly, it misreads every field after the desync, "which is how a wrong image or a wrong volume mount gets deployed instead of an error". Ship the PAIR. That was harmless before this ticket and is not now.”)
@yah:handoff(“PHASE 2 LANDED — yah cloud apply now produces an inner door. All five steps, with the call sites. (1) PLAN: service_inner_door (app/yah/cli/src/cloud.rs:9212) calls inner_door::plan once per service; Ok(None) is the answer for every service on disk today and returns before anything else runs. (2) PORT: derived, not allocated — inner_door::listen_port(service) (oss/yubaba/crates/cloud/src/inner_door.rs:346). (3) RESOLVE: InnerDoorPlan::resolve_addresses (inner_door.rs:418) maps each unit to a mesh ident via unit_ident (:398) and looks it up with the new ServiceRecordFanout::address_for_ident (reconciler/service_discovery.rs:426). (4) DEPLOY: deploy_inner_door (cloud.rs:9274), called at the END of the deploy-phase closure in BOTH apply paths — reconcile_root (cloud.rs:11877) and handle_mirror_up (cloud.rs:7100) — so it is after every unit registered a record and before the front-door phase repoints anything. (5) REPOINT: IngressPlan::point_at_inner_door (reconciler/ingress.rs:438), called from reconcile_ingress_edge (cloud.rs:7726).”)
@yah:handoff(“STEP 2 ANSWERED — the port is DERIVED from the service name, not taken from kamaji’s ledger, and the three facts that decided it were read rather than assumed. (a) LedgerPorts is node-local (a JSON file beside the supervisor’s state dir) and yubaba’s HTTP surface exposes no allocation verb at all — yubaba/src/lib.rs routes /workloads/, /services, /node/, and nothing for ports — so an apply has no way to ask. (b) A stated number is HONOURED, not rejected, on the path this workload takes: R844-F14’s pin rule bites inside LedgerPorts::resolve_set, and NativeRuntime::resolve_declared_ports (oss/kamaji/crates/kamaji/src/native.rs:280) filters pin.is_none() BEFORE calling it. That matters because PASSWAY_LISTEN must carry the number, and a number the node picks after the spec is rendered cannot be in it. (c) A collision is not representable: the ledger allocates on the workload’s MESH ip, an inner door binds loopback, so 100.64.0.3:14210 and 127.0.0.1:14210 are different sockets. The window is 10000-19999, deliberately below Linux’s default ephemeral floor (32768) where pick_free_port’s bind(:0) draws from. FNV-1a written out inline rather than DefaultHasher, whose stability std does not promise — this number goes into a deployed door’s env AND the outer door’s upstream list, and a toolchain bump silently moving it would repoint one tier and not the other.”)
@yah:handoff(“THE OPEN HEADER QUESTION IS ANSWERED, AND THE ANSWER IS NO CHANGE — grounded by reading, not assumed. The question was whether the passway FRONT door also applies per-route response headers. It does not: PassProxy::response_filter (oss/passway/crates/passway/src/proxy.rs:700) iterates ctx.route_headers, and its own doc at :694 states that vector is empty for RoutingStrategy::ByHost — which is what every outer door is. So the outer tier owns no headers and there is no double-apply to resolve there. A THIRD tier the question did not name does apply them, and is worth recording: the mesofact bundle ORIGIN, via MESOFACT_ROUTE_HEADERS set by add_declared_route_headers (app/yah/cli/src/cloud.rs:8612). For a mount served by DeployedUnit::Bundle both that origin and the inner door apply the route’s headers — but CONVERGENTLY, not duplicatively: both read the same .yah/domains route map, PathRouter does not strip the mount prefix (oss/passway/crates/passway/src/path_route.rs has no strip/rewrite), so both match the same request path, and both use insert-semantics (HeaderMap::insert in mesofact’s RouteHeaderTable::apply, insert_header in passway) — one header, one value. Do NOT collapse it to one owner. The bundle origin’s coverage is strictly WIDER: it applies headers for a declared route that has no component mount (a /docs/* route served out of the root bundle’s dist), which the inner door has no entry for. And the inner door is the ONLY owner for a DeployTier::Workload mount, since nothing hands such a component a header table. The two are complementary; removing either loses headers somewhere.”)
@yah:handoff(“PLUMBING BUILT BECAUSE STEPS 3 AND 5 NEEDED IT, all three of which did not exist. (1) inner_door::component_workload_ident(service, component_id) (inner_door.rs:371) — the mesh identity a workload-tier component registers under. It is a NAMING RULE stated here because nothing else states it: a bundle’s ident is a mirror fact (BundleSlot::workload_name, renameable with name = \"...\"), but a workload-tier component has no slot of its own, since [providers.*] is per-kind-per-mirror — the exact gap DeployTier was added to close. Folded through reconciler::native_support::sanitize_ident, which I widened from private to pub(crate) mod (reconciler/mod.rs) rather than writing a second normalizer. Getting the ident wrong fails LOUDLY: routes_file refuses a mount whose unit resolved to nothing, naming the unit. (2) ServiceRecordFanout::address_for_ident — deliberately SINGULAR where upstreams_for is plural. An inner door proxies over loopback to a unit on its own node; handed a fleet-wide set it would dial across the mesh, which is not what the cleartext-listener safety argument assumed. Two nodes, two addresses is ambiguity (None), not load balancing. Port selection follows port_for‘s discipline exactly (kamaji::DEFAULT_PORT_NAME first, then the sole anonymous port) so a unit resolves the same way at both tiers or neither. (3) IngressPlan::point_at_inner_door OVERRIDES where resolve_upstreams/resolve_ports fill in — it clears both halves and then goes through those same two methods, so this stays the only place in the crate writing those fields. The ticket’s step 5 named resolve_upstreams; used alone it is WRONG, because it skips a rule that already has an upstream_host and every mirror on disk pins one. A pin names ONE unit, and fronting a two-unit service from one unit serves half the site and 503s the other half, so the pin has to lose here and nowhere else.”)
@yah:handoff(“TWO PLACEMENT DECISIONS PHASE 2 HAD TO MAKE, both recorded at the site. (a) The inner door lands on the FRONT DOORS, not the workload nodes — the outer door dials 127.0.0.1, so a door anywhere else is a door the outer tier cannot reach. ingress_topology (cloud.rs:9230) recomputes resolve_ingress_placements + plan_ingress in the deploy phase to learn that set; both are pure, so this costs no network and cannot disagree with the front-door phase’s own answer. (b) SELF-DISCOVERY IS TURNED OFF for an inner-door service. PASSWAY_UPSTREAM_SOURCE=yubaba makes the door poll for the fronted workload’s records and use those INSTEAD of its static set — which would route straight past the inner door to whichever unit registered under the mirror’s ident, silently undoing step 5. The rendered note says so in its own words rather than reusing R844-F20’s "NOT self-discoverable … MANUAL step" wording, because this is not a degradation: the address is derived and byte-identical on every apply. (c) A mirror with two units and NO declared front door SKIPS with a note rather than failing — reconcile_mirror_ingress already returns early on plans.is_empty(), so there would be no outer door to repoint and nothing that can 503. Every shape = \"local\" dev mirror is in that state; bailing there would have broken yah mirror up.”)
@yah:handoff(“DISCOVERED WORK, FIXED IN THIS PASS, NOT FILED AS A FOLLOWUP. cargo test -p yah-cloud --lib was 1161/2 on arrival, and the two reds were NOT mine and NOT a flake: cloud_init::tests::{rendered_runcmd_entries_are_all_strings, coordinator_prestage_only_for_standalone}. Cause: oss/yubaba/crates/cloud/templates/mirror.yml:107-108, the two R858-F17 turso-backup-helper runcmd entries, were written as BARE YAML scalars containing a : — which makes the whole entry parse as a Mapping, so cloud-init skips it and the helpers never land on a provisioned node. The file is committed and clean (last touched by a8f0d501, i.e. it regressed AFTER phase 1’s 1150/0 measurement), no live peer owns it, and the fix is two lines: double-quote the entries and escape the inner quotes. Both tests are green and the comment at the site names the gate. This is a real provisioning defect, not just a red test — a node provisioned since a8f0d501 has no turso-backup-hydrate / turso-backup-tail, and R858-F17’s own design makes durability-declaring workloads refuse to deploy without them. Worth a look at whether any node was provisioned in that window.”)
@yah:verify(“PHASE 2 MEASURED, every number run by me and read. cargo test -p yah-cloud --lib = 1163 passed / 0 failed (baseline 1150; +13 — 6 in inner_door::tests, 4 in service_discovery::tests, 3 in ingress::tests). cargo test -p yah --lib = 1549 / 0 (+3 new in a new inner_door_apply_tests module). cargo test -p xtask --test main mirror_ingress = 13 / 0 (baseline 11; +2). cargo test -p yubaba --lib = 952 / 0, exactly the baseline. cargo test -p passway in oss/passway = 205 + 43 + 37 = 285 / 0 against the 283 baseline, and cargo test -p kamaji --lib --all-features = 217 / 0 against 208 — BOTH deltas are peers’, not mine: I touched neither crate. Sweeps: cargo test --workspace --all-features --no-run clean, and the same in oss/yubaba clean (only the two pre-existing unused-import warnings in a peer’s in-flight mesofact_static.rs). NO SCHEMA REGEN NEEDED — this pass added functions, constants and one module-visibility widening, and no serde-visible field on any generator input, so .yah/schema/*.json and packages/yah/workload-spec/index.ts are untouched by construction.”)
@yah:verify(“THE NEGATIVE IS ASSERTED IN THREE PLACES, at three different altitudes, because it is the claim the live fleet rests on. (1) xtask/tests/mirror_ingress.rs::no_service_on_disk_gets_an_inner_door walks the REAL .yah/services/ tree and asserts every service plans None. That is the strongest form available without a fleet: the only way to be wrong about it is for a service to acquire deploy = \"workload\", at which point the test names the service. Sibling every_services_derived_inner_door_port_is_distinct pins the port derivation against the real service list. (2) cloud::inner_door_apply_tests::a_single_unit_service_leaves_the_outer_door_exactly_as_it_was builds a two-component fixture that is BYTE-FOR-BYTE the positive test’s, with one word changed (workload -> bundle), and asserts the rendered PASSWAY_UPSTREAMS is still the mirror’s pinned noisetable.com=100.64.0.3:8080. So the difference between the two outcomes is provably that one field. (3) inner_door::tests::{a_single_unit_service_gets_no_inner_door, several_bundle_components_are_one_unit_and_still_get_no_door} from phase 1, still green. THE POSITIVE: a_two_unit_service_repoints_the_outer_door_at_its_inner_door (outer door renders noisetable.com=127.0.0.1:<derived>, and the port is asserted equal to what the door itself binds — two call sites in two phases that must not be able to disagree) and the_rendered_table_splits_the_mounts_and_carries_only_their_own_headers (both units addressed, COOP+COEP on /app and ABSENT on the root).”)
@yah:gotcha(“TRANSIENT BUILD FAILURE SEEN AND DISPROVEN, recorded so the next reader does not re-chase it. The first cargo test --workspace --all-features --no-run came back with can't find crate for 'runner' / 'agent_tools' / 'camp_service' and a linker failing on a dozen absent .rlibs (libgif, libzune_jpeg, libimagesize…) in crates this ticket never touched — the exact shape CLAUDE.md’s orphan-gc warning describes. Followed that procedure rather than cleaning: cargo orphan-gc log -n 300 names NONE of the missing artifacts (every entry in the window reads deleted 0 artifacts), so orphan-gc is NOT confirmed here. The likelier cause is plain target-dir contention: a yah-release-check QED pipeline was holding the same /Users/leif/ss/yah/target for 29 minutes alongside this build. Re-ran with nothing else on the key: CLEAN, zero errors. Not reproducible, orphan-gc log does not name it, and the artifacts were never deleted per its own record.”)
@yah:next(“WHAT REMAINS IS THE LIVE HALF ONLY, and it is an operator call the R870 leader is holding — phase 2 deliberately landed code + tests and touched no node. The two assertions: (a) POSITIVE — a two-component service whose components deploy independently gets one inner door from one yah cloud apply, with https://<host>/ and https://<host>/app/ both 200 and curl -sI on /app/ carrying cross-origin-opener-policy: same-origin AND cross-origin-embedder-policy: require-corp while / carries neither. (b) NEGATIVE, node-side — for a single-component service (yah-marketing), NO routes file materialized under /var/lib/passway/routes and NO extra workload in kamaji’s table. Note that (b) is now also asserted statically against the real tree by xtask/tests/mirror_ingress.rs::no_service_on_disk_gets_an_inner_door, so the node-side check is confirmation rather than discovery. BEFORE RUNNING (a): there is no service with deploy = \"workload\" on disk, so one has to be declared first — and the R870-B6/V8 roll-order gotcha on this ticket applies the moment anything actually SETS WorkloadSpec::files. Confirm the target node’s kamaji link codec (kamaji-proto/src/codec.rs) and roll the kamaji+yubaba PAIR first if it is postcard.”)
@yah:next(“ONE THING PHASE 2 DID NOT BUILD, named so it is not mistaken for done: there is still no FLEET deploy path for a DeployTier::Workload component. reconcile_component (app/yah/cli/src/cloud.rs:8264) dispatches on component.kind, and the only non-bundle arms are container — which ContainerReconciler::up guards on MirrorShape::Local, and LocalProcessReconciler, which is the camp/dev tier and registers as local-process-<service>-<env>-<component>. So on a real mirror such a component is deployed by hand today (yah cloud workload deploy). That is exactly why inner_door::component_workload_ident had to STATE the ident rather than look it up. The failure mode is loud rather than silent — a component registered under any other ident leaves its unit unresolved and routes_file refuses the whole table, naming the unit — but whoever wires that deploy path must make it register under component_workload_ident(service, id), or change both sides together. Related and already filed: R523-F1 (a component kind that deploys a stateful binary to a fleet node) is the same missing arm seen from the other direction.”)
@yah:handoff(“PHASE 2 COMPLETE — yah cloud apply produces an inner door. Everything above this entry is the detail: the five call sites, the derived-port argument, the header-ownership answer (no change — the outer passway door owns no route headers, proven at proxy.rs:694/700, and the bundle origin’s overlap is convergent and strictly wider), the three pieces of plumbing built because steps 3 and 5 needed them, the two placement decisions, and the one mirror.yml provisioning defect fixed on the way through. Nothing was deployed and no node was touched, per the dispatch. Green: yah-cloud 1163/0, yah 1549/0, yubaba 952/0, xtask mirror_ingress 13/0, passway 285/0, kamaji 217/0, both –all-features –no-run sweeps clean. Git policy is defer, so nothing is committed — the diff is 6 files: oss/yubaba/crates/cloud/src/{inner_door.rs, reconciler/mod.rs, reconciler/ingress.rs, reconciler/service_discovery.rs}, oss/yubaba/crates/cloud/templates/mirror.yml, app/yah/cli/src/cloud.rs, plus xtask/tests/mirror_ingress.rs.”)
@yah:handoff(“Tree anchor at handoff: 88533e01f7f578b1520b633d05846973fa47f608 — the shared tree as I left it. Diff against it (git diff 88533e01f7f578b1520b633d05846973fa47f608..HEAD) to see what landed under you, and quote this SHA rather than ‘HEAD’ in any revert/restore instruction.”)
@yah:handoff(“PHASE 2 ACCEPTED BY THE RELAY LEADER (@Ashguard:hydra, session:39386823). yah cloud apply now produces an inner door: all five steps wired, plus three pieces of plumbing that did not exist (component_workload_ident, ServiceRecordFanout::address_for_ident, IngressPlan::point_at_inner_door), the derived-port decision argued from three read facts, and the open header question answered NO CHANGE with the proof at proxy.rs:694/700. Implemented by @Ashguard:blade (session:54a6be05). The detail is in the handoff entries above this one; this entry records only that it was accepted and on what evidence.”)
@yah:verify(“WHAT IS DELIBERATELY NOT VERIFIED, and it is the operator’s call rather than an oversight: the LIVE half. No node was touched, nothing was deployed, nothing committed (git policy is defer). Running it needs a service with deploy = \"workload\" declared — none exists on disk — and the moment anything actually SETS WorkloadSpec::files, this ticket’s own V8 roll-order gotcha binds: confirm the target node’s kamaji link codec (kamaji-proto/src/codec.rs) and roll the kamaji+yubaba PAIR, never one alone.”)
@yah:verify(“INDEPENDENTLY RE-RUN BY A SECOND COURIER (@Ashguard:dove, session:60d4f41f) who did not implement it, because a courier’s self-report is the inner gate and not the outer one. All six commands reproduced the claimed counts EXACTLY: yah-cloud 1163/0 (4 ignored), yubaba 952/0, passway 285/0 (205+43+37), kamaji –lib –all-features 217/0, yah –lib 1549/0 (1 ignored), workspace –all-features –no-run clean. Every content check held: point_at_inner_door at ingress.rs:438; inner_door::plan reached from the apply path via service_inner_door (cloud.rs:9219) through deploy_inner_door (cloud.rs:9274, invoked at 7100 and 11877) and the ingress repoint at 7726; the port confirmed a deterministic per-service pin (FNV-1a into 10000-19999, inner_door.rs:346) and NOT kamaji’s ledger, with the native.rs:282 pin.is_none() justification verified at the site. The negative is asserted three times, not once. CAVEAT ON THE MEASUREMENT ITSELF: the camp skew detector flagged 4 of 6 runs SUSPECT — peers edited kamaji/src/microvm.rs, kamaji-bin/src/main.rs and cloud/reconciler/mesofact_bundle.rs mid-run — so these are shared-tree numbers, not a frozen-tree measurement.”)
@yah:verify(“ONE CLAIM CORRECTED AND ONE DEFECT FOUND BY THAT RE-RUN, both recorded rather than smoothed over. (1) CORRECTION: cargo test -p yah-cloud --lib does NOT run from the repo root — yah-cloud is not a root workspace member and needs dev-dependencies; it only works from oss/yubaba. Anyone reproducing the 1163/0 above must cd there first. (2) DEFECT, pre-existing and NOT caused by this ticket: embedded_template_matches_workspace_canonical is green VACUOUSLY — it resolves the workspace root via CARGO_MANIFEST_DIR.ancestors() to oss/yubaba, whose .yah/ holds only a .gitignore, so it takes the bootstrap branch and asserts nothing, while the repo-root twin at .yah/infra/cloud-init/mirror.yml is 128 diff-lines stale and missing the whole R858-F17 turso-backup block. FILED AS R870-B25, not left here. Note rendered_runcmd_entries_are_all_strings is a DIFFERENT test, is genuinely green, and is the gate that really catches the colon-space footgun this ticket fixed.”)
@yah:gotcha(“SUPERSEDED BY R870-F27, and the @yah:next that said otherwise has been removed from this block: containerd DOES materialize WorkloadSpec::files now, so an inner door is no longer pinned to native-capable nodes. The backend-check step this ticket told its reader to perform before deploying is gone. Still refusing: Docker and MicroVm. The single fact both halves read is kamaji::Backend::materializes_files (oss/kamaji/crates/kamaji/src/lib.rs), not a list in prose.”)
@yah:ticket(R885-T14, “No cap:bundle-serving mesh capability exists — bundle/almanac/passway workloads are placed with nothing modelling where they can run”)
@yah:status(review)
@yah:at(2026-09-12T07:16:50Z)
@yah:assignee(agent:bundle-anthropic-ashguard)
@yah:parent(R885)
@yah:severity(P3)
@yah:next(“FOUND WHILE DISPROVING R885-T13, and it is the real gap that ticket’s false premise was standing next to. cap:native-exec exists and is honoured (config.rs:2353-2357 via wants_native_exec) for yah.exec = native Container specs. But the workloads actually running on the fleet — MesofactServeBundle / Almanac / TenantPassway, served by kamaji’s BundleBackend and JitRuntime — have NO corresponding mesh capability at all. All four live workloads on us-east-001 are of those kinds. So placement for the entire class of workload this fleet actually runs is unmodelled: nothing declares which nodes can serve bundles, and nothing checks. It works today because there is effectively one node doing it, which is exactly the condition under which an unmodelled constraint stays invisible. THE SHAPE OF THE FIX IS ALREADY IN THE TREE: R860-T5 closed this same gap for native-exec. Follow it — a cap:bundle-serving capability declared in .yah/infra/machines/*.toml, a wants_bundle_serving predicate beside wants_native_exec, and the placement check wired the same way. Establish the right granularity first: whether bundle / almanac / tenant-passway want one shared capability or separate ones is a real design question, and the answer depends on whether a node can serve one kind and not another. Tier: Cleric. ITS NATURAL HOME IS R860’s AXIS, NOT R885’s — R885 is about workloads running unbounded once placed, this is about where they are placed at all. Filed under R885 because that is where it was found and where the evidence is; move it to R860 if that relay is still live. Not urgent: nothing is broken today, and the cost is that the first multi-node bundle placement decision will be made by something that has no model of the constraint.”)
@yah:handoff(“GRANULARITY SETTLED BY OPENING KAMAJI, NOT BY GUESSING — and the answer is smaller than the ticket assumed. kamaji gates each backend on its own cargo feature + startup flag: BundleBackend on bundle-serving + --bundle-cache-dir + --bundle-origin (attach_bundle_backend, oss/kamaji/crates/kamaji-bin/src/main.rs:924), JitRuntime on tenant-passway + --tenant-passway-dir (:706). Independent flags means separate capabilities, not one shared tag. But only ONE of the three named in the ticket needs modelling today: (1) BUNDLE gets cap:bundle-serving. (2) TENANT-PASSWAY gets nothing — there is no placement decision to gate: yubaba::tenant_passway::reconcile_once runs inside a node’s own yubaba and drives that node’s own kamaji over the local UDS, so which node arms a domain is decided by YUBABA_TENANT_PASSWAY_STATE_DIR, not by a selector. A tag would have no reader, which is the same wrong-fact R860-T5 refused to state for cap:microvm. (3) ALMANAC gets nothing ever — kamaji refuses Workload::Almanac outright ("almanac and static-asset live in yubaba’s reconcilers", kamaji-bin/src/server.rs:1846) and yubaba reconciles it, so it is never node-placed.”)
@yah:verify(“MEASURED, every number an exit-visible run. cargo test -p yah-cloud --lib (oss/yubaba, CARGO_TARGET_DIR=/tmp/r885t14-target) = 1205 passed / 0 failed / 4 ignored. The baseline is 1200 and it is recoverable from this session’s own output rather than asserted: the first post-edit run read 1195 passed / 5 FAILED, those five being pre-existing fixtures the new axis correctly broke (synthetic machines with no mesh_tags), so 1200 before, +5 new tests, 1205 after. cargo test -p xtask --test main = 69 passed / 0 failed (the real-tree suite, incl. all 11 mirror_ingress, all 4 apex_failover, all 4 fleet_build_placement). cargo test -p xtask --doc green. cargo check -p yubaba --all-targets (oss/yubaba) clean. cargo check -p yah --all-targets (root) clean — flagged SUSPECT by the camp build rail (peers edited app/yah/cli/src/camp.rs, mesh.rs, oss/yah-base/crates/keys/src/spec.rs, oss/yubaba/crates/yubaba/src/lib.rs mid-run); none of those is a file this ticket touched and the CLI’s only contact with the change is resolve_bundle_machines, whose signature is unchanged.”)
@yah:handoff(“WHAT LANDED. (1) pub const BUNDLE_SERVING_MESH_TAG: &str = \"cap:bundle-serving\" in oss/yubaba/crates/cloud/src/config.rs beside NATIVE_EXEC_MESH_TAG, carrying the node-side gate, why a positive capability and not a taint, and why there is no cap:tenant-passway beside it. (2) oss/yubaba/crates/cloud/src/reconciler/mesofact_bundle.rs: with_bundle_capability(&RequiredSpec) -> RequiredSpec (idempotent) and ensure_bundle_capable(&MachineConfig, ..), wired into BOTH arms of resolve_bundle_machines — the constraint arm gets the tag appended to the derived mesh_tags, the literal machines = [...] pin is refused with an error naming the tag AND the .yah/infra/machines/required_for_role(role, required) applied in both resolve_ingress_placements and resolve_ingress_candidates, so the deployer and the discovery fanout stay set-for-set across the new axis — the property resolve_bundle_machines’ own doc promises and which a bundle-only check would have broken. (4) .yah/infra/machines/us-east-001.toml declares the tag. (5) W338 §Placement consequences gains item 5.”)
@yah:handoff(“THE ARCHITECTURAL POINT, because it is why this was not one line beside the native tag. cap:native-exec is read in admission_spec, which covers Workload::Container and NOTHING ELSE. A bundle never reaches that function — it is placed by resolve_bundle_machines off the mirror’s providers.bundle declaration, a completely separate resolver that an operator writes by hand. So the gap was not "one more tag in the same if"; it was the same class of gap one resolver over. The rule the two instances share, now written into W338: a capability tag belongs wherever a SELECTOR chooses a node, not wherever a spec is admitted. Anything that picks a machine has to know what that machine’s kamaji was started with, because every kamaji backend is an opt-in flag.”)
@yah:handoff(“THREE EXTRA FIXES, all outside the ticket title, all loud. (a) xtask/src/install.rs:717 — clear_stale_provenance‘s doc comment had an INDENTED log excerpt, which rustdoc compiles as Rust, so cargo test -p xtask failed its doctest on main for everyone. Fenced as ```text. Pre-existing, unrelated to this ticket, one line. (b) .yah/schema/mirror.toml.schema.json regenerated (cargo run -p xtask -- emit-schemas) — the schema-drift gate was RED on arrival and the drift is @Ashguard:coffee’s R584-F2 local-mailcrab doc-comment change on MirrorConfig::drivers, not mine (verified by reading the one-line diff before regenerating). Regenerated per the generated-artifacts-are-not-ownable rule; they were told. Zero of my own types are schemars-derived, so this change contributes nothing to any schema. (c) Corrected three stale claims at their sites rather than leaving them: config.rs’s NATIVE_EXEC_MESH_TAG doc said Workload::MesofactServeBundle and Workload::Almanac are BundleBackend-served (MesofactServeBundle is a FIELD on Workload::MesofactStatic, not a variant; Almanac is never node-placed at all), and us-east-001.toml’s R885-T13 block repeated the same three wrong names for the four processes it observes — all four are bundle workloads.”)
@yah:verify(“NEW TESTS. Five in mesofact_bundle’s mod tests, each keeping a capable AND an incapable node in one CloudConfig so a pass provably comes from the capability rather than an empty pool: a_node_without_the_bundle_backend_cannot_be_pinned_to_serve_a_bundle (refusal names the tag and the file; the SAME fleet + same declaration shape at a capable node still resolves); a_constraint_places_past_a_matching_node_that_cannot_serve_bundles (the incapable node is declared FIRST, so a resolver ignoring the axis returns it and the test fails; then dropping the capable node makes the same declaration refuse); the_ingress_planner_applies_the_same_capability_as_the_deployer (set-for-set, plus the candidate widener must not widen past the capability); a_mirror_that_declares_the_capability_itself_is_unchanged (idempotence); a_non_bundle_slot_requires_no_capability (regression guard on the role mapping — a static slot still places on a node with no bundle backend). The shared machine() fixture now carries the tag by default, with machine_without_bundle_backend() beside it, because every placement test there presupposes an eligible pool.”)
@yah:verify(“REAL-TREE HALF, which is where the live-safety answer is. New xtask/tests/mirror_ingress.rs::exactly_one_machine_in_the_real_fleet_can_serve_a_bundle asserts the capable set over .yah/infra/machines/ is exactly ["us-east-001"] and that a replicas = 2 bundle constraint therefore refuses NAMING the tag. It is a deliberate tripwire: the day a second node declares the capability, the "one node serves every bundle" reasoning scattered through yah-marketing’s and noisetable’s mirrors stops holding and this is what says so. The pre-existing a_constraint_with_replicas_two_… had to change — its scale-2 assertions need two capable nodes and the real fleet has one — so it now grants the capability to us-south-001/us-west-001 IN MEMORY, asserts first that neither declares it on disk (so the grant cannot go silently vacuous), and says at the site that this is a hypothetical fleet, not a claim about those boxes. Every one of its original assertions (repel-by-default moving the second slot, the toleration lever recovering the pre-B7 answer, absent-replicas being exactly one, the short-count refusal, the two-backend render through collate) is unchanged and green.”)
@yah:gotcha(“THIS FAILS CLOSED AND THE BLAST RADIUS WAS CHECKED, NOT ASSUMED. A bundle can now only be placed on a node declaring cap:bundle-serving, and exactly one does. Every live bundle placement in reach still resolves: yah-marketing’s required = { regions = [\"us-east\"], mesh_tags = [\"tag:cloud-runner\"] } lands on us-east-001 (green in the real-tree suite), and the noisetable camp’s two providers.bundle.machines = [\"us-east-001\"] pins are covered because ~/ss/noisetable/.yah/infra/machines/ is an EMPTY DIRECTORY — that camp borrows this repo’s inventory read-only through its .yah/infra/sources.toml [[source]] link, so declaring the tag here fixes it there too and no cross-camp edit was needed. NOT EXECUTED, and say so rather than implying it: I did not run yah cloud validate/ingress collate from ~/ss/noisetable against a rebuilt binary. That conclusion is read off the two mirrors’ pins plus the sources.toml link, not observed.”)
@yah:assumes(“us-east-001’s cap:bundle-serving rests on a BEHAVIOURAL reading, not on that box’s ExecStart line: it is the node every bundle in the fleet is placed on today, R870-T9 records noisetable.com serving live through a bundle from it, and R885-T13 observed four kamaji-forked bundle processes there on 2026-09-11. Nothing in-repo records --bundle-cache-dir on its kamaji command line. The tag is therefore right about what the box demonstrably does and unverified about how it was started; if a roll ever drops the flag the tag becomes a lie in the fail-OPEN direction (a deploy that is admitted and then refused — i.e. exactly today’s behaviour, not worse). Settle it with ps -o args= -C kamaji / the kamaji.service ExecStart, the same evidence us-west-001.toml:61-67 records for the native tag.”)
@yah:cleanup(“us-south-001 is the obvious second bundle-capable candidate — it already shares the passway demux pair with us-east-001 — and is deliberately left undeclared because nothing in-repo reads its kamaji flags either way. One ps -o args= -C kamaji on that box settles it; declaring it wrongly would route a bundle to a node that refuses it, which is the failure this axis exists to remove. Until then the fleet is genuinely single-node for bundle serving and exactly_one_machine_in_the_real_fleet_can_serve_a_bundle says so out loud.”)
@yah:relay(R926, “Register iroh relay + headscale as first-class camp services, with descriptions and HA-aware health checks”)
@yah:at(2026-09-18T03:47:41Z)
@yah:status(open)
@yah:assignee(agent:bundle-anthropic-ashguard)
@arch:see(.yah/docs/working/W122-yah-mobile.md)
@yah:handoff(“FILED 2026-09-17 from an operator request made during R726-S22’s device run (@Ashguard:dove, session:639e7b78). THE ASK, in the operator’s words: the iroh relay and headscale should be listed in the yah services with DESCRIPTIONS and HEALTH CHECKS, "since they can move around in HA mode". GROUNDED STATE OF THE WORLD AT FILING, read rather than assumed: (1) The service registry is .yah/services/<name>/service.toml. Exactly nine services are registered - scrabcake, yah-analytics, yah-chat, yah-cloud, yah-cloud-admin, yah-cr, yah-dashboard, yah-desktop, yah-marketing. NEITHER an iroh relay NOR headscale is among them, so the operator’s observation is correct. (2) The generated schema .yah/schema/service.toml.schema.json has top-level properties [components, db, domain, health_path, name, schema_version], required [domain, name, schema_version]. So a health HOOK already exists in the shape of health_path - this is NOT greenfield - but there is NO description field at all, which is new schema surface. (3) .yah/infra/machines/*.toml are pure INVENTORY (name, [allocatable], [connect], [registration]); they are not where a service is declared, so do not add it there. (4) The Rust side of health_path lives in oss/yubaba/crates/cloud/src/config.rs and src/lib.rs (also mirrored in oss/mesofact/crates/mesofact/src/lib.rs).”)
@yah:next(“Wire the iroh relay explicitly rather than implicitly. R726-S22 measured a phone falling back to relay because there was no shared address family with the camp; the relay is the DESIGNED path in that case, not a failure - but today nothing in the service registry says the relay exists, so its health is unobservable from the camp UI.”)
@yah:next(“Add a description field to the service schema (new surface - it does not exist), then REGENERATE the artifacts: cargo run -p xtask -- emit-schemas and the workload-spec export. They no longer regenerate on commit and schema-drift-guard in the check QED pipeline will fail the build otherwise.”)
@yah:next(“HA is the actual hard part and deserves a design decision before code: health_path is a single path on a single declared domain, which cannot express "this service currently lives on whichever of N machines won the election". Decide whether a service gains a set of candidate endpoints with a liveness winner, or whether the registry queries the mesh’s own service-records endpoint (the 100.64.0.3:7443/service-records?ready=true surface referenced in us-west-001.toml) as the source of truth. Do NOT bolt a second health mechanism beside health_path - see the repo’s below-v1.0.0 rule; change the one that exists.”)
@yah:gotcha(“HEADSCALE HAS A LOUD, DOCUMENTED FAILURE HISTORY AND THIS TICKET IS PARTLY A RESPONSE TO IT - read R858 before designing the health check. .yah/infra/machines/us-west-001.toml carries R858 ("Mesh coordination outage: cloud.mesh.yah.dev refuses :443, so no camp machine can reach any 100.64.0.0/10 address") plus a measured 2026-09-04 gotcha: tailscale reported "fetch control key … connect: connection refused", port 22 answered while 80/443 were REFUSED, and consequently every mesh address stopped answering. THE PART THAT MATTERS FOR A HEALTH CHECK: the same gotcha records that THE PUBLIC SITE STAYED GREEN THROUGHOUT (yah.dev HTTP 200 in 0.81s) because the apex serves from us-east-001’s own passway and never traverses the coordination server. So a naive HTTP health check against a public domain would have reported HEALTHY during a total mesh outage. Whatever check this ticket adds for headscale MUST probe the coordination path itself (the control-key fetch, or a mesh-address dial), not a public endpoint that is up for unrelated reasons. The repo’s CLAUDE.md also warns that the headscale appliance already accumulated four half-owners of "does this node have a config.yaml" and that the seam between two of them took the mesh down twice - so give this ONE owner.”)
Structs§
- Bucket
LogEntry - A bucket declaration logged in
topology.tomlbyyah cloud bucket create. - Bucket
Spec - Camp
Cloud Dbs - A camp-shared cloud database catalog, parsed from
.yah/db/cloud.toml. These are cloud DBs not owned by any single service — declared once at camp scope and addressed ascloud:<name>(two-segment id), distinct from a service-localcloud:<service>:<name>. - Cloud
Config - All cloud config loaded from a workspace root (the parent of
.yah/). - CloudDb
- A remote cloud database (
[[db.cloud]]). The connectionurlis stored in TOML but the credential never is —auth_token_envnames an environment variable the daemon reads at connect time, so the same declaration works whether the token is provisioned service-locally or camp-shared (W241; operator confirmed both scopes are needed). A camp-wide cloud DB not owned by any single service is declared identically in.yah/db/cloud.toml. - Connect
Spec - Declared reach for a BYO
staticnode (no provider API). Lives under[connect]in the machine TOML. - DbCatalog
- A service’s declared databases, grouped by environment (W241 §Sections).
Parsed from the
[db]table ofservice.toml; each[[db.<env>]]array entry names one database. The environment tag drives backend selection at query time (see the data-workbench’sdb.query/ thesql_*MCP tools):dev= local file,pond= a DB inside the running pond container stack (reached on a declared localhost port),cloud= a remote libSQL/Turso or Postgres endpoint whose auth comes from an env var (never stored in TOML). - DevDb
- A dev-mode local SQLite database (
[[db.dev]]).pathis resolved relative to the workspace root and opened as a local file — read/write, no network, no auth. - Domain
Config - A routing manifest for one domain, from
.yah/domains/<name>.toml. - Domain
Route - One entry in a
DomainConfig’s route table. - Fleet
Inventory - A camp’s resolved machine inventory: the answer to “which machines does
this camp have”, with exactly one implementation
(
resolve_fleet_inventory) behind it (R870-B13). - GitSource
- A git source for a component (R561-F1, “BYO git”).
- Infra
Origin - Provenance for a
MachineConfigorProviderConfigpulled in from a linked.yah/infra/sources.tomlentry, rather than declared in this camp’s own.yah/infra/(R615-F2 / W274). - Infra
Source - One
[[source]]entry in.yah/infra/sources.toml(R615-F1 / W274) — an external infra root this camp borrows machines/providers from. - Ingress
Edge - One declared edge: a front door, the slots it fronts, and the nodes it is placed on (W305 F2).
- Legacy
Mirror Config - Per-camp mirror declaration from
.yah/cloud/mirrors/<id>/mirror.toml(folder form) or the legacy.yah/cloud/mirrors/<id>.toml(flat form). - Machine
Config - Per-machine TOML from
.yah/infra/machines/<name>.toml. - Machine
Registration [registration]— facts observed about a running box, written by the fleet rather than declared by an operator (R707-T1).- Mirror
Assignment - One mirror→machine placement entry in
topology.toml. - Mirror
Build Override - One component’s per-environment build override — the value type of
MirrorConfig::build(R905). - Mirror
Config - A service mirror — the projection of a
ServiceConfigonto concrete infra. Lives at.yah/services/<svc>/mirrors/<env>.toml. - Node
Allocatable - Static node capacity declaration on
machine.toml(R572-F3). - PondDb
- A database running inside the pond container stack (
[[db.pond]]). The pond publishes the DB on a localhost TCP port; the hub connects to127.0.0.1:<port>when the pond is up and returns a clear error when it is not. Eitherport(defaulting to a libSQL/sqldHTTP endpoint) or a fullurlmust be given. - Port
Mapping - Provider
Config - A provider account/runtime binding from
.yah/infra/providers/<id>.toml. - Required
Spec - F16 placement constraints declared on a
MirrorProviderSlot, lives under[providers.<role>] required = { regions = [...], mesh_tags = [...] }inmirrors/<env>.toml. - Secret
Config - A camp’s declaration of one cluster secret, from
.yah/infra/secrets/<slug>.toml. - Service
Component - One component of a
ServiceConfig. Thekind(e.g."mesofact-static","almanac","container") selects which reconciler runs against the pointed-at workload manifest. - Service
Config - An operator-facing service declaration from
.yah/services/<svc>/service.toml. - Service
With Mirrors - A loaded service plus its per-environment mirrors.
- Source
Contribution - What one
[[source]]in.yah/infra/sources.tomlactually contributed toFleetInventoryon this load (R870-B13). - Sources
Config .yah/infra/sources.toml— the ordered list of external infra roots this camp borrows from (R615-F1 / W274).- Topology
Config - Mirror-to-machine assignment table from
.yah/cloud/topology.toml. - Tunnel
Door - What a passway door behind a cloudflare tunnel needs that a public door does not (R910-F2): where its per-hostname loopback listeners are, and the inputs to issue its own certificates by DNS-01 — the only ACME challenge that works when nothing public reaches the node.
- Workload
Config - A workload declaration loaded from
.yah/cloud/workloads/<name>.toml.
Enums§
- Cloud
Config Error - Error surfaced by
CloudConfig::loadwhen a workload TOML fails validation. - Deploy
Tier - How one
ServiceComponentreaches a node — seeServiceComponent::deploy. - Front
Door - Which front door actually serves a domain’s requests (R594-F12).
- Infra
Source Kind - How to reach an external infra root (R615-F1 / W274, “linked infra sources”): a filesystem link to a sibling camp’s live tree, or a git checkout of an extracted infra repo.
- Ingress
Decl - A mirror’s
ingressdeclaration, in either spelling. - Ingress
Provider - Which public-ingress provider fronts this mirror’s compute (W267, R594-F11).
- Ingress
Via - What a
cloudflare-tunneledge dials instead of the fronted workload — W348 §1.3’s stacked shape (R910). - Join
Verdict - What
judge_joindecided about one proposed cluster join. - Mirror
Provider Slot - A provider slot inside a
MirrorConfig. Two shapes: - Mirror
Shape - Topological shape of a mirror — how its providers sit relative to each other.
- Pond
DbKind - Wire protocol of a
PondDb. - Provider
- Tag for the infrastructure provider kind. Drives which fields are valid in
a
ProviderConfigbody or aMirrorProviderSlot::Inlineblock. - Route
Mode - Body of a
DomainRoute. Three modes on the wire, four shapes here: - Secret
Encoding - How a
SecretConfig’s vault text becomes the bytes delivered to the container (R706 / W294). - Secret
Target Decl - Advisory mount shape on a
SecretConfig. Mirrorsworkload_spec::SecretTargetin a TOML-friendly, externally-tagged-free shape (akinddiscriminator reads better in a hand-written manifest than serde’s default enum encoding). - Source
Mode - Write-gate for a linked
InfraSource(R615-F1 / W274). - Sovereign
Role - Whether a node in a sovereign group may hold a seat in that group’s quorum — R605-F12.
- Taint
Effect - How a key in
MachineConfig::taintscan affect placement. - Workload
Config Error - Error from loading or validating a single workload TOML file.
Constants§
- AFFINITY_
TAINT_ KEYS - Taint keys a workload may name in
yah.placement.requires-taintto require a node (W305/R742-T4 affinity vocabulary). - BUNDLE_
SERVING_ MESH_ TAG - The mesh tag a node declares to advertise that its kamaji can serve W272
bundles — R885-T14, the same axis
NATIVE_EXEC_MESH_TAGmodels for the native-exec backend. - DEFAULT_
YUBABA_ PORT - Default yubaba listen port, used when
[connect].yubaba_portis omitted. - MICROVM_
MESH_ TAG - The mesh tag a node declares to advertise that its kamaji can boot a
Firecracker microVM — the third instance of the axis
NATIVE_EXEC_MESH_TAGandBUNDLE_SERVING_MESH_TAGmodel, and the one R860-T5 deliberately left open. - NATIVE_
EXEC_ MESH_ TAG - The mesh tag a node declares to advertise that its kamaji can run native (fork+exec) workloads — R860-T5 / W338 §“Placement consequences” 3.
- SECRET_
CONFIG_ SCHEMA_ VERSION - The
schema_versioneverySecretConfigmust carry. Version 2 added the requiredgroups(R911-F8).
Functions§
- canonical_
tier - Map legacy mirror file stems to their canonical tier names.
- domain_
for_ service - The route-driven domain manifest serving
service, loaded from.yah/domains/. - domain_
serving_ service - The route-driven domain whose route table binds a component of
service, if any. Used by static publishers to pick up the per-route response headers a service’s paths were declared with. - group_
is_ drainable - Whether a placement group may be drained off its node (W338 §Placement consequences 2): false as soon as any member is an Appliance.
- is_
private_ ipv4 - Whether a bare host string is an RFC1918 private IPv4 literal.
- judge_
join - May
joinerjoin the clustertargetbelongs to? — W305/R742-F1. - live_
taint_ keys - Every key the scheduler can act on, sorted — for error messages that tell the operator what the legal vocabulary actually is instead of only what was wrong.
- node_
selector_ mesh_ tags - Parse the R594 mesh-tag node-selector off a workload’s annotations into the
requested tag set. Absent annotation or empty value ⇒ empty vec (“no
constraint”). Whitespace around each comma-separated tag is trimmed and
empty segments are dropped, so
"tag:build-worker, arch:x86"and"tag:build-worker,arch:x86"parse identically. - node_
selector_ node - Parse the R833-F8 imperative node-selector off a workload’s annotations —
the single machine
namethe operator pinned the run to (--where=node:us-west-003). Absent or blank ⇒None(“no constraint”), which is every workload built before this axis existed. - normalize_
mount - Normalize a component
mountto a storage/URL key prefix: strip the surrounding slashes."/app","app/","/app/"→"app";"/",""→""(the service root). - placement_
group - The workloads that must be placed together with
ws: the transitive closure oflocalrequirement edges overWorkloadSpec::effective_requirements, starting at the requirer (R860-T4 / W338 §“Each member keeps its own mesh identity”). - private_
ipv4_ from_ url - Host of an
http://host:portURL iff it is an RFC1918 private IPv4 —10/8,172.16/12,192.168/16.Nonefor anything else, loopback and the100.64/10mesh range included: neither is a LAN literal. - provider_
has_ machine_ driver - True iff
providerhas an auto-provision driver (create/destroy via API). Driver-backed providers requirelocation+server_type; BYOstaticnodes (brought up over SSH) do not. The cloud-vs-vps distinction the fleet cares about lives here — at the provider-capability layer — not as a separate machine type (W242 BYO Phase-0 decision). - resolve_
fleet_ inventory - Resolve a camp’s machine inventory: camp-local
.yah/infra/machines/, the pre-R215.yah/cloud/machines/tree, then every machine borrowed through.yah/infra/sources.toml(R870-B13, on R615-F2’s mechanism). - route_
headers_ for_ service - The
ROUTE_HEADERSWorker-binding value forservice, read from the workspace’s domain manifests."[]"when no route-driven domain routes the service, or when the one that does declares no headers. - route_
path_ prefix - The key prefix a domain route pattern serves under:
"/*"→"","/app/*"and"/app"→"app". The twin ofnormalize_mounton the routing side. - taint_
effect - Classify one node taint key. See
TaintEffect.