Raxx · internal docs

internal · gated

ADR 0098 — Flag Operator UX Hardening + Pony-Style Internal Docs

Status: Accepted Date: 2026-05-17 UTC Deciders: Kristerpher (operator), software-architect Design doc: flag-operator-ux-hardening-2026-05-17.md


Context

The console flag surface serves one primary use case: an operator stands in front of a prod flag, is about to flip it, and needs five answers in one click:

  1. What does this flag gate?
  2. What other flags or services depend on it?
  3. Does flipping it require a dyno restart?
  4. How do I confirm it's working post-flip?
  5. Where's the rollback path?

None of those answers are currently accessible without leaving the console. The description field is one sentence. The references chips (PR #2230) are rendered but not yet semantically typed. There is no runtime_behavior signal, no smoke-test affordance, and no per-flag knowledge page at a stable URL.

Three architecture decisions needed resolution before sub-cards could be split:

Decision A: Pony-Docs framework for internal-docs.raxx.app/flags/ Decision B: Where docs_path lives Decision C: Dependency declaration mechanism


Decision A — Pony-Docs framework

Options considered

Option Sidebar nav Templated pages Search Cross-refs New deps Notes
Hugo Yes Yes WASM Plugin Yes (Go binary) Extra toolchain
MkDocs + Material Yes Yes Built-in Plugin Yes (pip) Excellent but new stack
Docusaurus Yes Yes Built-in Plugin Yes (Node/npm) Aligns with Antlers; post-v1 migration candidate for public docs
Custom Python + Jinja2 Generated Templated Lunr.js Regex None Same pattern as build-internal-docs.py already in repo

Decision

Custom Python + Jinja2 builder (scripts/build-flag-docs.py), emitting static HTML/MD consumed by CF Pages.

Rationale

Consequences


Decision B — Where docs_path lives

Options considered

  1. Separate mapping file (docs/flag-docs-map.yaml): flag key → docs URL. Extra file, extra sync surface, likely to drift.
  2. Inline in feature_flags.yaml (optional field docs_path): single source of truth; additive and backwards-compatible; lintable in the same pass as other YAML validation.
  3. Auto-derived from flag_key + surface: /flags/<surface>/<flag_key>. Zero YAML authoring cost; works immediately for all 158 flags; operator cannot point a flag at a custom handwritten page.

Decision

Auto-derive as the default (/flags/<flag_key>), with an optional inline override (docs_path: in YAML) for flags that have a custom hand-authored page.

Rationale


Decision C — Dependency declaration mechanism

Options considered

  1. Implicit via references: parse references for flag: mentions and infer dependencies. Fragile; references are documentation, not a machine contract.
  2. Explicit dependencies: list in YAML: dependencies: [rbac_v2, ...]. Unambiguous; lintable; bidirectional reference graph derivable at build time.
  3. Separate dependency graph file: extra sync surface, same drift risk as Decision B option 1.

Decision

Explicit dependencies: list in YAML (empty list or absent = no dependencies).

Rationale