Route OpenBao configuration and provisioning away from the structure survey

Configuration intent (policies, auth roles) routes to the attended
openbao-platform-admin-login lane and value provisioning to openbao-api-key
custody; both fail closed when their front door is missing. The survey lane
now points at ops-mason's read-only ops-mason-survey grant (MASON-IN-0004).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 327285@bnt-lap001
Assistant-Session: d6532cd1-7cd5-417b-baac-b841c9103a6b
This commit is contained in:
tegwick 2026-10-08 23:21:46 +02:00
parent 4d912276e4
commit 139f77dd55
7 changed files with 115 additions and 11 deletions

View file

@ -199,6 +199,28 @@ class CatalogFreshness:
}
def _openbao_configuration_need(query: str) -> bool:
"""Separate explicit control-plane configuration from metadata discovery.
This is a routing distinction, never approval. Exact lane IDs are handled
first; reads and surveys continue through ordinary catalog ranking.
"""
text = query.lower().replace("-", " ")
control = re.search(r"\b(?:polic(?:y|ies)|auth\s+roles?|token\s+roles?|"
r"database\s*(?:/| )\s*config|secrets?\s+engine)\b", text)
change = re.search(r"\b(?:configure|configuring|create|apply|install|update|"
r"administration|administer)\b", text)
return bool(re.search(r"\bopenbao\b", text) and control and change)
def _openbao_provision_need(query: str) -> bool:
"""Value provisioning belongs to custody, never the structure survey."""
text = query.lower().replace("-", " ")
return bool(re.search(r"\bopenbao\b", text)
and re.search(r"\b(?:provision|provisioning|seed|seeding)\b", text)
and re.search(r"\b(?:keys?|credentials?|secrets?|tokens?|values?)\b", text))
@dataclass
class Catalog:
path: Path
@ -232,6 +254,19 @@ class Catalog:
scored = [(e.match_score(tokens), e) for e in pool]
scored = [(s, e) for s, e in scored if s > 0]
scored.sort(key=lambda pair: (-pair[0], pair[1].id))
if _openbao_provision_need(query):
custody = self.get("openbao-api-key")
if custody is None or not custody.is_active or custody.lane != "secret":
return []
return ([custody] + [entry for _, entry in scored if entry.id != custody.id])[:limit]
if _openbao_configuration_need(query):
admin = self.get("openbao-platform-admin-login")
# A missing/inactive administration front door must not fall back to
# a survey ceremony or a secret-read transport.
if admin is None or not admin.is_active or admin.lane != "login":
return []
ranked = [admin] + [entry for _, entry in scored if entry.id != admin.id]
return ranked[:limit]
return [e for _, e in scored[:limit]]
def stale(