Files
Gitea-Tools/webui/policy_views.py
T
sysadmin 261f0b82de fix(webui): remediate PR #856 REQUEST_CHANGES for policy visibility (#646)
Address review blockers (review #555):
- Graduate /policy nav item out of STUB_PAGES to live nav in webui/nav.py
- Update docs/webui-local-dev.md to list /policy as a live surface and remove stub copy
- Run console_redaction on HTML emit path in webui/policy_views.py before rendering HTML
- Add planted-secret HTML redaction test and nav graduation test in tests/test_webui_policy_visibility.py
2026-07-24 08:30:58 -04:00

146 lines
5.5 KiB
Python

"""HTML views for the workflow policy and guardrail inventory (#646)."""
from __future__ import annotations
import html
import json
from typing import Any
from webui import console_redaction
from webui.policy_inventory import (
PolicyEntry,
PolicyInventorySnapshot,
SourcePointer,
snapshot_to_dict,
)
def _source_pointer(source: dict[str, Any] | SourcePointer) -> str:
if isinstance(source, dict):
label = str(source.get("label") or "")
path = str(source.get("path") or "")
anchor = source.get("anchor")
kind = str(source.get("kind") or "")
else:
label = source.label
path = source.path
anchor = source.anchor
kind = source.kind
if anchor:
path = f"{path}#{anchor}"
return (
f"<li>{html.escape(label)} — "
f"<code>{html.escape(path)}</code> "
f"<span class='muted'>({html.escape(kind)})</span></li>"
)
def _active_block(entry: dict[str, Any] | PolicyEntry) -> str:
error = entry.get("error") if isinstance(entry, dict) else entry.error
active = entry.get("active") if isinstance(entry, dict) else entry.active
if error:
return (
"<p class='muted'><strong>Active value unavailable:</strong> "
f"{html.escape(error)}</p>"
)
if not active:
return "<p class='muted'>No live projection for this guardrail.</p>"
pretty = json.dumps(active, indent=2, sort_keys=True, default=str)
return f"<pre class='prompt-text'>{html.escape(pretty)}</pre>"
def _diff_block(entry: dict[str, Any] | PolicyEntry) -> str:
diff = entry.get("diff") if isinstance(entry, dict) else entry.diff
documented_default = entry.get("documented_default") if isinstance(entry, dict) else entry.documented_default
if diff is None:
if documented_default is None:
return "<p class='muted'>Diff vs documented default: not feasible (no declared default).</p>"
return "<p class='muted'>Diff vs documented default: unavailable.</p>"
status = str(diff.get("status") if isinstance(diff, dict) else "unknown")
badge = "badge-claimed" if status == "matches_documented_default" else "badge-blocked"
rows = []
checked = diff.get("checked") if isinstance(diff, dict) else {}
if isinstance(checked, dict):
for key, cell in checked.items():
cell_dict = cell if isinstance(cell, dict) else {}
marker = "✓" if cell_dict.get("matches") else "✗"
rows.append(
"<tr>"
f"<td><code>{html.escape(str(key))}</code></td>"
f"<td><code>{html.escape(str(cell_dict.get('expected')))}</code></td>"
f"<td><code>{html.escape(str(cell_dict.get('observed')))}</code></td>"
f"<td>{marker}</td>"
"</tr>"
)
table = ""
if rows:
table = (
"<table class='detail'><thead><tr>"
"<th>Key</th><th>Documented</th><th>Active</th><th>Match</th>"
"</tr></thead><tbody>"
f"{''.join(rows)}</tbody></table>"
)
return (
f"<p class='meta'>Diff vs documented default: "
f"<span class='badge {badge}'>{html.escape(status)}</span></p>"
f"{table}"
)
def _entry_card(entry: dict[str, Any] | PolicyEntry) -> str:
title = str(entry.get("title") if isinstance(entry, dict) else entry.title)
category = str(entry.get("category") if isinstance(entry, dict) else entry.category)
summary = str(entry.get("summary") if isinstance(entry, dict) else entry.summary)
sources_data = entry.get("sources", []) if isinstance(entry, dict) else entry.sources
sources = "".join(_source_pointer(s) for s in sources_data)
return (
"<div class='prompt-card'>"
f"<h3>{html.escape(title)} "
f"<span class='badge'>{html.escape(category)}</span></h3>"
f"<p>{html.escape(summary)}</p>"
"<p class='meta'><strong>Source pointers</strong></p>"
f"<ul>{sources}</ul>"
"<p class='meta'><strong>Active configuration</strong></p>"
f"{_active_block(entry)}"
f"{_diff_block(entry)}"
"</div>"
)
def render_policy_page(snapshot: PolicyInventorySnapshot | dict[str, Any]) -> str:
if isinstance(snapshot, PolicyInventorySnapshot):
payload = snapshot_to_dict(snapshot)
elif isinstance(snapshot, dict):
payload = console_redaction.redact_payload(snapshot)
else:
payload = {}
categories_list = payload.get("categories") or []
categories = ", ".join(html.escape(str(c)) for c in categories_list) or "none"
entries_list = payload.get("entries") or []
cards = "".join(_entry_card(e) for e in entries_list)
build_errors = ""
errors_list = payload.get("build_errors") or []
if errors_list:
items = "".join(
f"<li>{html.escape(str(err))}</li>" for err in errors_list
)
build_errors = (
"<div class='stub'><p><strong>Some guardrails could not be built:"
f"</strong></p><ul>{items}</ul></div>"
)
note = str(payload.get("note") or "")
schema_version = payload.get("schema_version") or 1
return (
"<h2>Workflow policy &amp; guardrails</h2>"
f"<p class='muted'>{html.escape(note)}</p>"
f"<p class='meta'>Schema v{schema_version} · "
f"{len(entries_list)} guardrails · categories: {categories}</p>"
f"{build_errors}"
f"{cards}"
"<p class='muted'>This page is read-only. It reports enforced policy "
"and never edits or weakens a gate. Secret values are redacted.</p>"
)