Skip to content

Architecture Decision Records

Every material design decision in boring is recorded as an ARD at the time it's made, so that "why is it like this?" is always answerable with one file open instead of by archaeology.

This page is the reader-facing index of all ARDs to date. Each entry includes a one-line summary of what the ARD decided. The full text is one click away.

If you're looking for the convention for writing new ARDs (full vs. mini, numbering, supersession, when to write one), see the ARD convention doc on GitHub.

ARDs at a glance

# Decided Title One-line takeaway
0001 2026-05-23 Boring v1 architecture The full v1 design: profile-in-repo, single CLI, compose sidecars, secrets resolved at start, egress allowlist, AI inside the box.
0002 2026-05-23 dbx as runtime dependency boring owns zero secret storage — dbx (and the other resolvers) is a runtime dependency; boring is a pure URI resolver.
0003 2026-05-23 devcontainer CLI as runtime dependency The @devcontainers/cli is the container-lifecycle layer; boring does not reimplement docker compose up.
0004 2026-05-23 Shopify-first as v1 dogfood path The first end-to-end slice is a real Shopify theme — defers dbx integration and the egress sidecar to v1.x.
0005 2026-05-23 Security model inversion v1's threat model is keeping non-engineers and AI from accidentally damaging prod, not preventing a malicious insider from exfiltrating data.
0006 2026-05-23 Profile is the trust anchor In-container agents must NOT be able to modify .boring/*, audit hooks, or their own settings — enforced by Claude deny rules + a system-wide git pre-commit hook.
0007 2026-05-23 preset: django-node + multi-service compose Second curated preset, multi-service compose with auto-wired depends_on, profile schema versioning, setup: lifecycle hooks, at-start secret resolution.
0008 2026-05-23 v0.3 → v1.0 release plan + thesis evolution The phased path to v1.0 (trust → egress → restore → headless → polish) and the thesis evolution from "easier dev environments" to "code as a thinking medium."
0009 2026-05-23 Guardrails codegen architecture Pre-push hook + command wrappers + Claude settings.json deep-merge — codegen happens host-side at boring open, bind-mounted RO into the container.
0010 2026-05-23 Audit log + prompt tracing Per-profile FIFO drained by a host-side collector; security events shared, prompt events per-user by default with opt-in audit.prompts: shared.
0011 2026-05-23 Egress enforcement via iptables-in-container CAP_NET_ADMIN (not --privileged), iptables-in-container, ships together with --learn-mode for authoring the allowlist.
0012 2026-05-23 dbx restore integration New restore: profile field; pipes prod-shape data through dbx restore --transform at stream time, never on disk unsanitized.
0013 2026-05-23 Headless boring run One-shot Claude invocation in a profile-scoped sandbox; fresh container per run, torn down with docker compose down -v on exit.
0014 2026-05-23 Preset versioning + v1.0 preset list Versions parameterized via Dockerfile ARGs + a preset_version: profile map; v1.0 ships python, node, node-postgres, django-node, shopify.
0015 2026-05-24 ulogd2 sidecar for cross-platform --learn-mode Replaces the dmesg-based learn-mode reader so the feature works on Mac+Orbstack, not just Linux native.
0016 2026-05-24 Repo-side safety nets as a boring prerequisite Branch protection + per-preset PR templates; boring doctor checks them at v1.0; extends ARD-0005 past the container boundary.
0017 2026-05-24 Agent workflow rules from guardrails: Universal preset-baked CLAUDE.md + per-profile snippet derived from guardrails: at codegen; rules are defaults, not constraints.
0018 2026-05-24 VS Code extensions are profile-declared extensions: + extension_settings: profile fields with preset defaults and runtime-add lock (v0.4 egress backstop); Marketplace-only at v1.0.
0019 2026-05-24 boring-ui — non-engineer browser surface (umbrella) Second user-facing surface alongside boring open; browser chat + live preview; v1.x flagship after v1.0.
0020 2026-05-24 OpenCode as boring-ui's agent harness Sub-ARD of 0019; subscription-billing verification is the precondition gate; v1.x ships Claude-only even if Codex/Gemini verify.
0021 2026-05-24 boring-ui host proxy + project picker Sub-ARD of 0019; always-running proxy at https://boring.local/; mkcert TLS; path-routing; Unix-socket isolation.
0022 2026-05-24 boring-ui session + trust model Sub-ARD of 0019; single chat per project; hidden auto-branching; silent execution + inline diffs + per-action undo; path allowlist; save: block.
0023 2026-05-24 tasks: primitive for long-running processes (Proposed) New profile primitive — tmux-supervised app servers launched after setup:; closes the "boring open and the app isn't running" gap. Targets v0.7.
0024 (unused — slot retained for future use)
0025 (unused — slot retained for future use)
0026 2026-05-24 Harness-agnostic guardrails + path allowlist (mini-ARD) Renames allowed_claude_tools:allowed_tools:; adds per-harness translation; adds allowed_paths:/disallowed_paths:. Amends ARD-0009.
0027 2026-05-24 OpenCode audit emit path (mini-ARD) Same FIFO + new agent: envelope field; native-hooks-or-wrapper fallback; boring audit --agent filter. Amends ARD-0010.
0028 2026-05-24 AGENTS.md codegen sibling to CLAUDE.md (mini-ARD) Same source emits both files; per-harness template substitutions; project-root AGENTS.md preserved. Amends ARD-0017.
0029 2026-05-25 claude --print shell-out as v0 boring-ui backend OpenCode harness deferred until a subscription provider is configurable; v0 backend shells out to claude per turn and maps stream-json to the envelope wire format.
0030 2026-05-26 dev: profile field (mini-ARD) cmd_open holds the foreground on the profile's dev.command (the app server) or an interactive shell; closes the "boring open and the app isn't running" gap.
0031 2026-05-26 Iframe-via-backend-proxy strips frame-blocking headers (mini-ARD) Backend reverse-proxies the preview, stripping X-Frame-Options + CSP frame-ancestors. Superseded by ARD-0033 (§1 sub-path mount).
0032 2026-05-26 boring secret — local keyring provisioning (mini-ARD) boring secret {set\|get\|rm} writes the OS keyring (Keychain/libsecret) so non-engineer launches resolve credentials with zero per-use auth; boring still owns no secret store.
0033 2026-05-26 Preview iframe on a dedicated origin (mini-ARD) Preview proxy moves from a same-origin sub-path to its own per-slug port, mounted at root, so Shopify-style root-absolute asset URLs resolve. Supersedes ARD-0031 §1.
0034 2026-06-06 External-API / data-warehouse readiness gaps (Proposed) Stress-test against a warehouse hitting BigQuery/Ads/Analytics/Shopify/cloud-DBs surfaces 11 findings. Headline: boot-time egress IP-pinning can't track rotating-IP cloud APIs; file-shaped creds (GCP SA JSON) fall outside the resolver. Proposes SNI-aware egress + secret-file://. Amends ARD-0011, ARD-0002.
0035 2026-06-07 boring-ui preview: multi-tab + editable address bar preview_urls: renders a tab strip (one dedicated-origin proxy per tab via --preview-urls); the address bar is editable with same-origin navigation only (containment); runtime +/× tabs reuse allowed origins. Implements ARD-0022 §6; builds on ARD-0033.

What "Status" means on each ARD

Every ARD's header carries a Status: line:

  • Accepted — the decision stands.
  • Accepted (partially amended) — most of it stands, but a later ARD changed some sections. The amended sections carry an inline callout pointing at the superseding ARD.
  • Superseded by ARD-NNNN — the decision was replaced wholesale. The file stays in place (never deleted) so the historical trail survives.
  • Proposed — written down but not yet adopted. (Rare; we usually decide and then write.)

How to navigate

  • Reading order for the architecture: ARD-0001 → ARD-0005 → ARD-0006 → ARD-0008 covers the spine.
  • Reading order for security model: ARD-0005 (framing) → ARD-0006 (trust anchor) → ARD-0009 (codegen) → ARD-0010 (audit) → ARD-0011 (egress) → ARD-0016 (repo-side safety nets) → ARD-0017 (agent workflow rules) → ARD-0018 (extensions).
  • Reading order for the dogfood path: ARD-0004 → ARD-0007 → ARD-0008.
  • Reading order for the data story: ARD-0002 → ARD-0012.
  • Reading order for boring-ui (v1.x flagship): ARD-0019 (umbrella) → ARD-0020 (OpenCode harness) → ARD-0021 (host proxy) → ARD-0022 (session + trust). Mini-ARDs ARD-0026 (harness-agnostic guardrails), ARD-0027 (audit emit), and ARD-0028 (AGENTS.md sibling) are the homework that landed alongside the boring-ui umbrella.

If you're new to the project, start with the Getting Started page first — it's the operational shape of all of this in 5 minutes of reading.