Skip to content

K1-10 / Q-STEP9-a: pools is reserved; the strip runs at exact depths; an entry named after a reserved key is refused - #599

Closed
MattJackson wants to merge 9 commits into
p6-d2-step4from
p6-k1-strip
Closed

MattJackson wants to merge 9 commits into
p6-d2-step4from
p6-k1-strip

Conversation

@MattJackson

@MattJackson MattJackson commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

K1-10 / Q-STEP9-a. ARCHITECT ruling 2026-10-07, approved. Spec BUSBAR-1.6.0.md (origin/predev) :561-570 (POOLS-VERBS; ":567 a plane entry named after any reserved key is refused at validation with a clear message (a generic check)"; ":568 one validated JSON object, reserved keys and secrets stripped"), decision #47, :4692. Stacked on #577 (p6-d2-money-labels, 6c963d2).

What changes

  1. pools is a reserved sub-key. deal::RESERVED_SUB_KEYS gains busbar_contract::section::RESERVED_POOLS_KEY.
  2. The strip runs at exact depths, with no recursion. busbar_kernel::config_validate::deal::strip strips at four depths: the section, each registration, pools.<p>, and pools.<p>.members[i] (when the member is a map). Each key it takes is recorded in Section::reserved at its exact path. Under a declared verb, the whole pools subtree leaves the blob and is recorded at [verb, "pools"]. The reserved keys of each pool and each member are also recorded at their own paths. A reserved word deeper than those four depths crosses unchanged.
  3. The root pools: section stays as it was in 1.5.5. This is the seat whose verb is RESERVED_POOLS_KEY. Only 1.5.5's two frozen words (hooks, upstream_credentials) are taken at section level. Every other depth-1 key is a pool. A pool named tier, work, breaker, rate_card and so on is a pool and crosses (v1.5.5 config/mod.rs:1503-1531).
  4. The generic refusal (spec :567).
    • Where it runs: config::prepass::plane_remainder reads each declared-verb section through the new deal::read_section. That is the load both --validate and boot run. The deal (validate_dealt) runs at boot only, so it was not used.
    • What it refuses: a depth-1 entry named after a reserved key whose value is plainly not that knob (deal::names_an_entry). It is refused at the entry's own path and position, before the plane is given anything. The rendering is the same as Document::refusal: config.yaml: invalid YAML: <section>.<key>: <sentence> at line L column C.
    • Root pools: is a core-owned concrete section and is not lifted, so 1.5.5's own PoolsCfg refusal still applies there, unchanged.
  5. busbar_contract::section::reserved_name_refusal is now pub. For the two section words it writes 1.5.5's sentence byte for byte. For the other reserved keys it uses the same form with a different parenthesis (below).
  6. docs/design/1.6.0-QUESTIONS.md: the Q-STEP9-a row now carries the ruling line.

Refusal sentences

  • Section words (unchanged, 1.5.5's bytes): a {noun} may not be named `{name}`: that key is RESERVED at the `{section}:` section level (the all-{section} `hooks:` attach list and `upstream_credentials:` default). Rename the {noun}.
  • Added, for any other reserved key: a {noun} may not be named `{name}`: that key is RESERVED at the `{section}:` section level (the core-owned `{name}:` setting). Rename the {noun}.
  • {noun} is the section's plane subject_noun, or entry when no plane declares the section.

How the refusal decides that a value is not its knob

The shapes come from the kernel types that read each knob:

  • hooks, gates, repeatable: a list.
  • upstream_credentials, tier: a scalar.
  • Maps with known fields: breaker = BreakerCfg {base_cooldown_secs, max_cooldown_secs, trip}; on_exhausted = OnExhaustedCfg (a word, or {fallback_pool} / {queue}); affinity = AffinityCfg {mode, header_name}; work = WorkBounds::of_section {max_live, retain_s}; fees = PlaneFeesCfg {per_request, per_session}.
  • pools and rate_card: a map whose values are maps.

A test pins the field lists against the types' own expected one of lists. The check is generic and names no plane.

Limit, as the ruling asks me to state: pools and rate_card are maps of maps. A registration-shaped mapping whose values are all maps cannot be told apart from those knobs, so it is not refused. For example, tools.pools: {x: {...}} is read as pools. Only a clear mismatch is refused: a non-map value inside the map, a key the knob does not read, or a map where the knob is a list or a scalar. A knob of the right kind that is malformed is left to the knob's own reader.

Tests and REDs

The REDs come from one Latchkey job that ran these tests over the base code (6c963d2).

  • config_validate::deal::tests::red_each_exact_depth_is_stripped_and_recorded_at_its_path: RED. On base, tools.pools crossed whole, with its pool's breaker and its member's tier.
  • config_validate::deal::tests::a_reserved_word_below_the_exact_depths_is_not_stripped: RED on base only through pools crossing. The no-recursion half is a guard, because base did not recurse either.
  • config_validate::deal::tests::red_root_pools_named_after_a_knob_are_pools_and_cross: RED. On base, root pools named tier/work/breaker/rate_card were stripped and the blob was {"pools":{}}.
  • config::tests::a_plane_entry_named_after_a_reserved_key_is_refused_at_its_position: RED. On base, an entry named after each of the 12 reserved keys loaded. The test also checks that every well-shaped knob loads.
  • config::tests::root_pools_named_after_a_reserved_sub_key_load_as_in_1_5_5: guard. It passes on base, and hooks/upstream_credentials as pool names keep 1.5.5's sentence.
  • config_validate::deal::tests::red_a_value_plainly_not_its_knob_names_an_entry, the_knob_field_lists_are_the_kernel_types_own, the_reserved_name_sentence_is_1_5_5s: these use the new API (names_an_entry and the pub sentence), so they do not compile on base.
  • root::boot::tests::red_3g_deals_a_root_pool_named_after_a_knob_as_a_pool (busbar): RED. On base it got {"pools":{}}.
  • cli_validate::validate_accepts_root_pools_named_after_a_reserved_sub_key_as_1_5_5_did: guard. A 1.5.5-shaped config with pools tier and work prints ok: config valid — 1 provider(s), 1 model(s), 2 pool(s).

Proof (Latchkey, head 1ed7629)

  • cargo fmt --all --check: rc 0.
  • cargo clippy --locked --workspace --all-targets --all-features --exclude busbar-auth-oauth -- -D warnings: rc 0.
  • cargo test --locked -p busbar-kernel: 2983 passed, 1 failed, 1 ignored. The one failure is the known pre-existing root_key_spelling failure, and it names only auth/inbound.rs.
  • cargo test --locked -p busbar-contract: 1234 passed, 0 failed, 5 ignored.
  • The three examples, built first: rc 0.
  • cargo test --locked -p busbar --bin busbar: 641 passed, 0 failed, 1 ignored.
  • --test validate_matches_the_1_5_5_golden --test migration_corpus --test cli_validate --test docs_examples --test law7_served_surface: 49 passed, 0 failed.

Oracle: base 6c963d2 vs head 1ed7629

  • Engine 4a7a7bba2cef, with --id-filter. The work was split into two jobs per side.
  • Filter A, ^(config\.migrate\||boot\.refusal\||boot\.warning\||config\|): base and head each recorded 365 cells (rc 0), replay rc 1, 385 judged rows (229 ACCEPTED, 66 FAIL, 90 PASS). Rows sha256 afe497ff76f8243a488caf26a2dc6f2055a8a9f7e577bcc53fd7fa20fca49718 on both sides; byte-identical, empty diff.
  • Filter B, ^(admin\.ops\|): base and head each recorded 280 cells (rc 0), replay rc 3, 240 judged rows (5 ACCEPTED, 31 FAIL, 204 PASS). Rows sha256 efa0dcddf76c41de58ea36ef86a8a91cf3a97219fd6b12f5bd566392084f524e on both sides; byte-identical.
  • No 1.5.5 cell moves.

Follow-up (not fixed here)

The door planes' open/refresh blob is built in crates/busbar/src/root/serve.rs (open, settings_of, about l.1434-1500). It strips only work and none of the other reserved keys. So the spec's ":568 reserved keys stripped" is not yet met at open/refresh. deal::strip is the single function that path should call. P1b will do that.

Accepted limit: maps of maps (stated in QUESTIONS Q-STEP9-a too)

pools and rate_card are maps whose values are maps. A registration named pools or rate_card whose own value is also a map of maps cannot be told from the knob, so it is NOT refused. It is read as the knob and leaves the crossing blob.

  • Example that slips through: tools: {pools: {fs: {url: "https://x"}}}, where the operator meant a tool named pools. It is read as a pool named fs with no members. The shape judge checks only that each value of a map-of-maps knob is a map, and the door pool reader reads only members. So the operator's tool silently becomes an empty pool.
  • Refused instead: a non-map value inside the map (tools: {pools: {fs: 3}}), a field the knob does not read, or a map where the knob is a list or a scalar.

root_key_spelling, pair run (same job, base #577 6c963d2 vs head 1ed7629)

Both sides fail identically:

crates/busbar-kernel/src/auth/inbound.rs: 1 quoted root key(s), none armed — read it from Kind::verb()
test result: FAILED. 1 passed; 1 failed

It is pre-existing, inherited from DEL's older base, and green on DEL 913fb20+. #599 adds no spelling: its own first-run hit in deal.rs is fixed in 1ed7629.

Head is now ed7e8de. The two commits after 1ed7629 are QUESTIONS doc edits only.

…xact depths; an entry named after a reserved key is refused at load

ARCHITECT ruling 2026-10-07 (spec BUSBAR-1.6.0.md :561-570, decision #47):
- `pools` (busbar_contract::section::RESERVED_POOLS_KEY) joins the deal's reserved sub-keys.
- deal::strip takes reserved keys at exactly four depths, no recursion: the section, each
  registration, each pool (pools.<p>) and each member (pools.<p>.members[i]); every key is
  recorded at its path. Under a declared verb the whole `pools` subtree leaves and its pools'
  and members' keys are recorded too.
- The root `pools:` section keeps 1.5.5's two reserved words (hooks, upstream_credentials);
  a pool named tier/work/breaker/rate_card/... is a pool and crosses.
- spec :567 generic refusal: a declared-verb section's depth-1 entry named after a reserved
  key whose value is plainly not that knob is refused at load (--validate and boot), at the
  entry's own path and position, in reserved_name_refusal's sentence (1.5.5's bytes for the
  two section words).
@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

promote into p6-d2-money-labels: NO VERDICT @ae464907f

The hop ended without writing a verdict (runner lost, timeout, cancel, or it died before the engine judged): preflight: failure at step Run cargo run --locked --release --no-default-features -p busbar-release-cli --bin busbar-release -- ci preflight; publish: runner lost at step Run bash "$GITHUB_WORKSPACE/busbar-release/ci/promote/fallback.sh", Post Run actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1.

No failing-test list exists for this run. Run: https://github.com/GetBusbar/busbar/actions/runs/37718940617 . Re-run the hop, or read the job's step list in the run page.

…y pool), as the shape judge and pool reader read it
…finity beside its settings, never in them

ARCHITECT ruling P1b (b), 2026-10-07 (spec BUSBAR-1.6.0.md :552-554, :561-570): `affinity` is an
owner-locked reserved core-owned sub-key, read by the kernel and stripped before the ABI. The llm
plane read `pools.<p>.affinity.header_name` out of its own settings to derive the session key
(shaping.rs), so the strip would have taken 1.5.5's session affinity with it. The kernel now hands
the plane, beside its settings, the resolved directive of each pool:

- busbar-contract abi/plane: PlaneOpenIn.pool_affinity (a tail addition) and PlaneRefreshIn
  {refresh: RefreshIn, pool_affinity}, the plane lifecycle's `refresh` `in`; one JSON object
  `{"<pool>": {"header_name": "<header>"}}` (POOL_AFFINITY_HEADER_NAME), absent when no pool names a
  header. Layout golden re-seeded (pre-tag v1 layout, no ABI_VERSION moves) and the C header
  regenerated.
- busbar-kernel deal: `crossing(verb, section)` runs the one strip and returns, beside the stripped
  section, `pool_affinity(verb, reserved)`: every pool's `affinity` read off what the strip took
  (config::pools::AffinityCfg), the root `pools:` section's and a declared verb's alike, no plane
  named.
- plugin-loader: open_door / refresh_door carry the projection; the facing probe is handed none
  (it routes no session).
- busbar serve: a door plane's open and both refresh paths are handed its projection.
- llm plane: Shaping reads the session header off the projection (Shaping::with_affinity), never
  off its settings; decisions and the test plane door read PlaneRefreshIn.
…oss through the deal's one strip

Spec BUSBAR-1.6.0.md :561-570 ("A plane's settings reach it as ONE validated JSON object
{section: value} per open/refresh, reserved keys and secrets stripped; upstream_credentials is
kernel-owned"). Measured on predev 5e672d1 (Latchkey cli-d43752e9): serve.rs `open` removed only
the top-level `work`, `refresh` handed the section as written, and the owned sections and the
kernel's facing probe were handed as written, so breaker, on_exhausted, gates, hooks,
upstream_credentials, affinity, tier, repeatable, rate_card, fees, work and pools all crossed, at
the section, each registration and each pool.

- serve.rs `crossed`: the settings a door plane is handed at open and at both refresh paths
  (DoorApply::refreshed, DoorAppliers::refresh_models) go through
  busbar_kernel::config_validate::deal::strip (P1's one strip, its exact depths: section,
  registration, pools.<p>, pools.<p>.members[i]); the root llm `pools:` keeps only its two section
  words reserved, as P1 rules; the consumed sections the llm plane reads beside it (providers,
  models, limits) cross through the same strip; the pool affinity projection (P1b-a) is read off
  the same strip. The owned sections cross through it too.
- busbar-kernel door.rs: the facing probe's section and DoorOwned::bytes cross through it.

Secrets are not touched here (ARCHITECT, via SECURITY: P1b strips reserved keys only; the secret
references are sec-plane-secret-refs, which stacks on this).
SECURITY: P1b: a door plane's open, refresh, owned sections and facing probe cross through the deal's one strip
@MattJackson

Copy link
Copy Markdown
Collaborator Author

Superseded by #728: K1-10 / Q-STEP9-a carried onto predev, with predev's entry timeout kept as a ninth reserved sub-key. P1b (#670, merged into this branch) cannot be cherry-picked onto predev's serve path. It is task draft-670-p1b-crossing-strip (After: #727, #728), which carries the three rulings it needs. Branch bundled at ~/Library/Caches/busbar-release/salvage/GetBusbar_busbar-p6-k1-strip-1791610783.bundle and deleted.

@MattJackson
MattJackson deleted the p6-k1-strip branch October 10, 2026 06:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant