STD-025: Conditional Rendering Security

STD-025: Conditional Rendering Security

Purpose

Prevent accidental exposure of production infrastructure data in built documentation. All environment-specific values — IPs, hostnames, UUIDs, billing accounts, personnel names, pricing — MUST be gated behind ifdef conditional blocks with a zeroed fallback. A build without the correct environment flag MUST produce a document containing no operational data.

Classification

Field Value

Standard ID

STD-025

Domain

Security

Scope

universal

Status

Active

Created

2026-06-22

Owner

Evan Rosado

RFC 2119

Keywords MUST, MUST NOT, SHOULD, MAY per RFC 2119

Normative Requirements

MUST

  1. Every partials/attributes.adoc MUST wrap environment-specific values in ifdef::env-<name>[] blocks.

  2. Every partials/attributes.adoc MUST include a ifndef::env-*[] fallback block with zeroed/safe defaults.

  3. The fallback block MUST NOT contain real IPs, hostnames, UUIDs, billing accounts, or personnel names.

  4. UUIDs in fallback MUST be 00000000-0000-0000-0000-000000000000.

  5. IPs in fallback MUST be 0.0.0.0.

  6. Hostnames in fallback MUST be UNDEFINED or <purpose>.example.internal.

  7. Personnel names in fallback MUST be UNDEFINED.

  8. Pricing in fallback MUST be $0.00.

  9. Build commands in documentation MUST include the -a env-<name> flag.

  10. The environment flag MUST NOT be set inside attributes.adoc — it MUST be passed at build time (CLI or playbook).

SHOULD

  1. Antora diagrams SHOULD use Kroki blocks with subs=attributes+ so attributes resolve before rendering.

  2. Standalone diagram README files SHOULD document the attribute map (label → attribute → current value).

  3. Projects SHOULD support at least two environments (env-d001, env-d000) plus fallback.

MUST NOT

  1. Environment flags MUST NOT be hardcoded in attributes.adoc or any partial — they are build-time inputs only.

  2. Real production values MUST NOT appear outside ifdef blocks.

  3. The fallback environment MUST NOT produce a document that could be mistaken for a real environment.

Four-Layer Security Model

This standard is Layer 3 of the defense-in-depth model for documentation:

Layer Mechanism What It Protects

1. Encryption

d001 close.age files

Source at rest — partials encrypted when not in use

2. Gitignore

data/*/.adoc blocked

Source in version control — plaintext never tracked (except allowlisted)

3. Conditional Rendering

ifdef::env-*[] + zeroed fallback

Built output — no flag = no real data in HTML/PDF

4. Scrub Rules

Pre-push grep audit

Commit boundary — sensitive terms caught before push

No single layer is sufficient. Together they ensure that source, storage, output, and commit history are all independently protected.

Attribute Resolution Order

antora-playbook.yml / CLI -a flag     ← environment flag set HERE
        ↓
partials/attributes.adoc              ← ifdef selects env-specific values
        ↓
page content                          ← {attribute} substitution in prose
        ↓
Kroki block (subs=attributes+)        ← diagram sees resolved literals
        ↓
SVG/HTML output                       ← only real values if flag was passed

Pattern: attributes.adoc Template

// ============================================================
// CHLA Production
// ============================================================

// ============================================================
// Domus Digitalis Homelab
// ============================================================

// ============================================================
// Fallback — ZEROED (no environment flag passed)
// ============================================================
:hostname: UNDEFINED
:ip-address: 0.0.0.0
:billing-account: 00000000-0000-0000-0000-000000000000

// ============================================================
// Shared (environment-independent)
// ============================================================
:build-tool: build-adoc
:build-variant: light-cyan

Build Commands

# CHLA production — real values render
build-adoc $(find data/d001/projects/<slug> -maxdepth 1 -name '<slug>.adoc') html --variant light-cyan -a env-d001

# Domus homelab — real values render
build-adoc $(find data/d000/projects/<slug> -maxdepth 1 -name '<slug>.adoc') html --variant light-cyan -a env-d000

# No flag — zeroed fallback renders (safe for sharing, review, demo)
build-adoc $(find data/d000/projects/<slug> -maxdepth 1 -name '<slug>.adoc') html --variant light-cyan

Compliance Checklist

  • partials/attributes.adoc exists

  • All environment-specific values wrapped in ifdef::env-*[]

  • ifndef fallback block present with zeroed defaults

  • No real IPs, UUIDs, or hostnames outside ifdef blocks

  • Build command in README/assembler includes -a env-* flag

  • Diagram README documents attribute map (if external .dot/.d2 files exist)

  • Antora Kroki blocks use subs=attributes+ (if applicable)

  • Test: build without flag produces no operational data

Audit Command

# Find attributes.adoc files missing ifdef blocks
find data -name 'attributes.adoc' -exec sh -c '
  grep -qL "ifdef::" "$1" && echo "MISSING ifdef: $1"
' _ {} \;

# Find attributes.adoc files missing ifndef fallback
find data -name 'attributes.adoc' -exec sh -c '
  grep -qL "ifndef::" "$1" && echo "MISSING fallback: $1"
' _ {} \;

# Verify no real IPs leak in fallback blocks
find data -name 'attributes.adoc' -exec \
  awk '/^ifndef/,/^endif/{if(/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ && !/0\.0\.0\.0/) print FILENAME": "$0}' {} \;