Skip to content

D772 — A routed ?kbs= follows a renamed KB through kb_aliases

Decision. kb rename records the old name in a top-level server config list, kb_aliases, one {from, to} item per old name, written in the same single config write as the kbs[] entry (when there is one). On /mcp/routed, a ?kbs= name that is not mounted but is the from of an alias whose to is mounted selects that KB: it is reported in kb_status.connection.renamed ({old: new}), the hint says the URL is stale and to run cartographer sync, and the server logs it once per distinct (set, renamed) pair. A call whose kb argument is the old name is dispatched to the new KB through its own callTool. A mounted name always beats an alias; an alias to an unmounted target stays unknown (D756). The list is single hop and flat (kb rename rewrites every to equal to the old name and drops the item of a restored name); kb unmount removes the items whose to or from is the unmounted name, in the write its backup covers (a from item is dormant while a KB is mounted under that name and would revive when it goes). Amends D756, D177 and D761.

Why. D756 left a stale URL connected but without the renamed KB until its client synced, even though the server knows where the KB went. The record cannot live on the kbs[] entry: a KB mounted by discovery under data: has no entry by design (D151) and is the most common kb rename; creating an entry only to hold an alias would change what governs the KB (its policy, age-key and machine-path defaults). A server-side list works for every KB, stays offline and bounded like kb rename itself (D177), and is shown with its origin by the config view (D743). A list of mappings follows every other structured setting of the schema (kbs[], auth.tokens, auth.roles); a map with free-form keys has no precedent in the schema renderer. The alias only decides which KB a URL selects: authorization runs at the target by its current name and scopes are not migrated (D177), so it cannot widen a token. It costs one more key an operator may need to know about, and a restart to apply, like kbs.

Alternatives rejected. renamed_from on the kbs[] entry, the original proposal: unreachable for a discovered KB. The record inside the KB (settings.yaml, D746): a name belongs to the mount, not to the KB, and git would carry the old name to another server where it means a different KB. Hidden state under data:: invisible to the config view and not reviewable. Aliases followed by the per-KB endpoints (/mcp?kb=, /mcp/<name>): they are plumbing and keep answering that the KB does not exist. Letting sync heal the client from the server's record: a separate plan, it needs the aliases advertised and a client-side rule against the stale-selection check (D754).

Consequences. A stale URL of a renamed KB keeps its KB. The pair is request-scoped (request context), never stored on the cached per-set Server, so URLs differing only in stale or aliased names share one view. A mounted name beating an alias is the rule that keeps an old URL from reaching a different KB later mounted under that name, which is also why kb unmount prunes aliases (comment in routedFor). The effective set is built after resolution, so an empty set stays an error. With no server config kb rename records nothing and says so.