jenkins b66c762f5d hermes(webui): add HUX card UI models with contract-locked suites
Standalone per-card browser model/security/view modules for HUX-01..10
plus node+pytest suites that read the hux.v1 contract schemas directly.
Reconciled drift found on integration: the activity model now accepts
all 32 hux.event.v1 kinds (delegation.*, memory.suppressed,
memory.retrieval_removed, budget.exhausted, side_effect.*), the
autonomy model carries the external_side_effect capability, and the
foundation boundary test now asserts the shipped static HUX surface
exists on disk and that images never bake activated HUX_FLAGS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BvMSXH8VH2tMWXanb8SJdf
2026-08-24 04:12:03 -03:00

77 lines
2.6 KiB
TypeScript

/** Display-only redaction. Raw event payloads must never cross this boundary. */
const CONTROL_CHARACTERS = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g;
const PEM_BLOCK = /-----BEGIN [^-]+-----[\s\S]*?-----END [^-]+-----/gi;
const AUTH_VALUE =
/\b(password|passwd|token|api[-_ ]?key|secret|authorization|cookie)\b\s*[:=]\s*[^\s,;]+/gi;
const BEARER = /\bbearer\s+[A-Za-z0-9._~+/-]+=*/gi;
const JWT = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g;
const CREDENTIAL_BLOB =
/\b(?=[A-Za-z0-9_+/#.-]{40,}\b)(?=[A-Za-z0-9_+/#.-]*[A-Za-z])(?=[A-Za-z0-9_+/#.-]*\d)[A-Za-z0-9_+/#.-]+\b/g;
const URI_USERINFO = /\b([a-z][a-z0-9+.-]*:\/\/)[^\s/@:]+:[^\s/@]+@/gi;
/** Return bounded plain text or a safe fallback; objects are never stringified. */
export function safeText(
value: unknown,
fallback: string,
maxLength = 280,
): string {
if (typeof value !== "string") return fallback;
const limit = Math.max(1, maxLength);
const redacted = value
.replace(PEM_BLOCK, "[redacted credential]")
.replace(AUTH_VALUE, "$1=[redacted]")
.replace(BEARER, "Bearer [redacted]")
.replace(JWT, "[redacted credential]")
.replace(URI_USERINFO, "$1[redacted]@")
.replace(CREDENTIAL_BLOB, "[redacted credential]")
.replace(CONTROL_CHARACTERS, " ")
.replace(/\s+/g, " ")
.trim();
if (!redacted) return fallback;
return redacted.length <= limit
? redacted
: limit === 1
? "…"
: `${redacted.slice(0, limit - 1).trimEnd()}`;
}
const EVIDENCE_LABELS: Readonly<Record<string, string>> = {
message: "Message",
tool_call: "Tool call",
tool_result: "Tool result",
artifact_version: "Artifact version",
source: "Source",
passage: "Supporting passage",
memory: "Memory record",
approval: "Approval",
run: "Run",
url: "Website",
file: "File",
build: "Build",
flux: "Flux reconciliation",
pod: "Workload",
};
/** Evidence labels are deliberately detached from IDs, URIs, and payloads. */
export function safeEvidenceLabel(
kind: unknown,
): { kind: string; label: string } | null {
if (typeof kind !== "string" || !(kind in EVIDENCE_LABELS)) return null;
return { kind, label: EVIDENCE_LABELS[kind] };
}
export function isRfc3339Utc(value: unknown): value is string {
return (
typeof value === "string" &&
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,6})?Z$/.test(value) &&
!Number.isNaN(Date.parse(value))
);
}
export function isOpaqueId(value: unknown, prefix?: string): value is string {
if (typeof value !== "string") return false;
if (!/^[a-z]{2,6}_[A-Za-z0-9._-]{4,80}$/.test(value)) return false;
return !prefix || value.startsWith(`${prefix}_`);
}