Context
As the RegelRecht project grows, we need a structured way to document design decisions and architectural choices. Important decisions about law execution, article resolution, URI handling, and system architecture should be documented with their rationale for future reference.
Without a formal process, design decisions live in:
- Pull request discussions (hard to discover)
- Code comments (fragmented)
- Institutional memory (lost when team members change)
We need a lightweight but structured approach to capture these decisions.
Decision
We adopt an RFC (Request for Comments) process where significant design decisions are documented as markdown files in docs/src/content/rfcs/.
RFC Template
RFC metadata lives in the YAML frontmatter, not in a bold-labelled preamble.
The site renders status and implementation as tags and date / authors /
depends_on as a header line; the body starts at the first ## Context.
---
title: "RFC-NNN: Title"
status: Proposed # Draft | Proposed | Accepted | Rejected | Superseded
implementation: Not implemented # Implemented | Partially implemented | Not implemented
date: YYYY-MM-DD
authors:
- Name
depends_on: # optional; omit if none
- RFC-NNN (Short description)
# short_title: Sidebar Label # optional; defaults to the title
---
## Context
Why is this decision necessary? What problem does it solve?
## Decision
What was decided?
## Why
Benefits, tradeoffs, alternatives
Numbering Convention
- RFC-000 is reserved for this process document
- Subsequent RFCs are numbered sequentially: RFC-001, RFC-002, etc.
- Once a number is assigned, it is never reused (even for rejected RFCs)
Status Values
status is the RFC’s place in the decision lifecycle, not whether code exists:
- Draft: Work in progress, not yet ready for discussion
- Proposed: Under discussion, not yet decided
- Accepted: Decision is made and should be followed
- Rejected: Proposal was considered but not accepted
- Superseded: Replaced by a newer RFC (reference the new RFC)
An RFC whose decision has been acted on is Accepted even if the code is only
partially built. A built-and-merged RFC is not a Draft; “Draft” means the design
itself is unsettled.
Implementation Status
Whether the decision is built is tracked separately from status, in the
implementation field, so the lifecycle status stays clean:
- Implemented: the decision is fully realised in code
- Partially implemented: the core exists; the RFC describes more that is absent
- Not implemented: design only, no code yet
Every RFC sets implementation. Stating it explicitly (rather than leaving a
fully-built RFC blank) keeps an absent tag from reading as “unknown” next to
the RFCs that do carry one. The two fields are orthogonal: an Accepted RFC can
be Partially implemented, and code can land ahead of acceptance (a Proposed RFC
that is already Implemented).
When to Write an RFC
Write an RFC for:
- Law representation formats: Changes to YAML schema, article structure, machine_readable sections
- Execution engine architecture: Changes to how the engine processes articles, resolves URIs, handles parameters
- Integration patterns: How components interact (engine ↔ regulation files, API designs)
- Cross-cutting design patterns: Decisions that affect multiple parts of the system
Skip RFC for:
- Bug fixes: Unless they require architectural changes
- Individual law implementations: Adding new YAML files following existing patterns
- Routine implementation work: Following established patterns
- Temporary workarounds: Meant to be replaced soon
When in doubt, ask: “Would someone maintaining this code in 6 months benefit from understanding why we made this decision?”
Why
Benefits
- Future contributors understand why decisions were made
- Writing forces clear problem articulation
- Decisions don’t live only in people’s heads
- RFCs evolve alongside code in version control
- One place to find architectural decisions
Tradeoffs
- Adds process overhead for major decisions
- Requires discipline to maintain
- Can become outdated if not updated
We accept these tradeoffs because the benefits of documented decisions outweigh the cost of the process.
Alternatives Considered
- Code comments only: Hard to discover, fragmented across codebase
- Wiki/Confluence: Separate from code, unclear version control
- GitHub Issues: Good for discussions, but not structured for long-term documentation
- ADRs (Architecture Decision Records): Very similar to RFCs; we chose “RFC” terminology as it’s more familiar in open source
References