generated from coulomb/repo-seed
feat(WARDEN-WP-0014): T2 — warden access advisory front door
Adds `warden access <need> [--domain X] [--json]`: resolves a credential need against the routing catalog and renders the structured handoff (owner, auth method, path template, command skeleton, policy gate status, proxy hint). SSH lane points at `warden sign`; routed lanes end "warden advises, the owner vends". New pure warden/access.py module (expand_handoff, policy_gate_status) reused by the T3 proxy lane. JSON output is stable and secret-free. tests/test_access.py added. 157 passed, lint clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
76
src/warden/access.py
Normal file
76
src/warden/access.py
Normal file
@@ -0,0 +1,76 @@
|
||||
"""Operator access assist — render structured handoff for a credential need.
|
||||
|
||||
The `warden access` front door (WP-0014) resolves a need to a `RouteEntry` and
|
||||
renders its **structured handoff**: how the caller authenticates to the owning
|
||||
subsystem, the owner-side path template, the command skeleton to run *as the
|
||||
caller*, and the policy check the fetch path gates on.
|
||||
|
||||
This module is **pure**: it expands templates and reports gate status. It never
|
||||
fetches, holds, or logs a secret value — that boundary is the whole point of the
|
||||
assist layer. Proxy execution (`--fetch`/`--exec`) lives in the CLI/T3 lane and
|
||||
reuses `expand_handoff` to build the command it runs as the caller.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
from warden.config import ConfigError, load_config
|
||||
from warden.routing.models import RouteEntry
|
||||
|
||||
|
||||
@dataclass
|
||||
class ExpandedHandoff:
|
||||
"""Handoff templates with `<domain>` substituted when a domain is supplied.
|
||||
|
||||
Remaining placeholders (`<workload>`, `<bundle>`, `<FIELD>`) are intentionally
|
||||
left for the caller/owner to fill — ops-warden does not invent owner-side names.
|
||||
"""
|
||||
|
||||
auth_method: Optional[str]
|
||||
path_template: Optional[str]
|
||||
fetch_command: Optional[str]
|
||||
policy_ref: Optional[str]
|
||||
exec_capable: bool
|
||||
|
||||
|
||||
def _sub_domain(value: Optional[str], domain: Optional[str]) -> Optional[str]:
|
||||
if value and domain:
|
||||
return value.replace("<domain>", domain)
|
||||
return value
|
||||
|
||||
|
||||
def expand_handoff(entry: RouteEntry, domain: Optional[str] = None) -> ExpandedHandoff:
|
||||
"""Expand an entry's handoff templates for display or proxy.
|
||||
|
||||
The catalog `fetch_command` may reference the literal token ``<path_template>``;
|
||||
we inline the entry's ``path_template`` so the rendered command is self-contained,
|
||||
then substitute ``<domain>`` across every field when a domain is given.
|
||||
"""
|
||||
path = entry.path_template
|
||||
fetch = entry.fetch_command
|
||||
if fetch and path and "<path_template>" in fetch:
|
||||
fetch = fetch.replace("<path_template>", path)
|
||||
|
||||
return ExpandedHandoff(
|
||||
auth_method=_sub_domain(entry.auth_method, domain),
|
||||
path_template=_sub_domain(path, domain),
|
||||
fetch_command=_sub_domain(fetch, domain),
|
||||
policy_ref=_sub_domain(entry.policy_ref, domain),
|
||||
exec_capable=entry.exec_capable,
|
||||
)
|
||||
|
||||
|
||||
def policy_gate_status() -> str:
|
||||
"""One-line description of whether the flex-auth gate is enforced for fetches.
|
||||
|
||||
Advisory output only — never raises. The proxy lane (T3) is what actually runs
|
||||
the gate before fetching; here we just report the configured posture.
|
||||
"""
|
||||
try:
|
||||
cfg = load_config()
|
||||
except ConfigError:
|
||||
return "advisory — no warden.yaml (caller identity; gate not enforced)"
|
||||
if cfg.policy.enabled:
|
||||
return f"enforced — flex-auth at {cfg.policy.flex_auth_url}"
|
||||
return "advisory — policy.enabled=false (gate ships with flex-auth deploy)"
|
||||
Reference in New Issue
Block a user