Repository navigation
Configuration Carcinisation
Configuration languages always start simple.
A few key-value pairs. Some nesting. Maybe a list.
Then something happens.
You add references to avoid duplication. You introduce variables. Conditionals creep in. Templating appears. Before long, your "configuration" is quietly executing logic.
This is inevitable.
Call it configuration carcinisation: the tendency of configuration formats to evolve into hidden programming languages.
The problem isn't that this happens. The problem is that it happens without boundaries.
Most discussions reduce the problem to a binary:
- Keep configs dumb and safe, but limited
- Make configs expressive and powerful, but dangerous
Both sides are reacting to the same failure mode:
Structure and meaning are mixed together.
Once that happens:
- evaluation order becomes unclear
- behavior becomes implicit
- security becomes fragile
- tooling becomes inconsistent
The format stops being data. It becomes a language—just not an honest one.
HTML is often brought up in these discussions, usually as either:
- proof that structured markup scales
- or an example of how things spiral out of control
Both are correct.
At its core, HTML is simple:
- a tree structure
- attributes for metadata
- no inherent execution
In that sense, it looks like a good model.
But HTML didn't stay there.
Tags began to carry meaning:
-
<table>became layout -
<b>became styling -
<div>became everything
Then execution was bolted on:
- JavaScript
- inline handlers
- templating systems
Structure, presentation, and behavior merged into a single layer.
HTML didn't fail because it had structure. It failed because structure was allowed to mean things.
Attributes are where this tension becomes obvious.
They look harmless:
distance@{unit="meters"} = 3
But in most systems, attributes become:
- hidden switches
- implicit conversions
- miniature DSLs
They bypass type systems. They bypass validation. They inject behavior from the side.
This is why people argue about them.
One side wants to remove them entirely. The other insists they are necessary.
Both are right—because the real issue isn't attributes.
It's what they're allowed to do.
In most systems, comments become hidden logic—implicit instructions that change behavior without being part of the published format semantics.
Example from AEON:
/(parse through tax-calculator.py)/
totalTax:number = 30_034
taxPercentage:number = .15 //? between 0 and 1
In other formats, these would silently control behavior. In AEON, they don't.
Configuration formats don't become problematic because they gain features.
They become problematic because:
structure absorbs meaning
- References become evaluation
- Attributes become behavior
- Comments become directives
Everything starts to do something.
And once it does, the system needs:
- execution rules
- ordering guarantees
- security constraints
At that point, it's no longer configuration. It's a programming language—without admitting it.
AEON doesn't try to stop this evolution.
It accepts that:
- data needs structure
- structure needs reuse
- reuse introduces complexity
But instead of collapsing everything into one layer, AEON separates them:
AEON → AES → AEOS → Tonic
- AEON describes structure
- AES preserves it as a stable event stream
- AEOS validates form
- Tonic interprets and materializes meaning
Each layer has a strict role.
References exist, but they are not resolved by default. They remain symbolic.
This means:
- no hidden evaluation
- no recursion surprises
- no implicit behavior
Attributes exist in the document and are preserved in AES:
distance@{unit="meters"} = 3
They carry information—like unit="meters"—but they don't execute anything.
They don't:
- convert values
- trigger logic
- change how data is parsed
A consumer has full visibility into the attribute. If they have a contract that requires units, they can validate during AEOS. But the format doesn't decide what units mean.
This is where AEON actually handles the carcinisation problem.
Semantic comments are parsed into a separate annotation stream, linked to data paths via AEON's addressing system:
/(parse through tax-calculator.py)/
totalTax:number = 30_034
taxPercentage:number = .15 //? between 0 and 1
AES sees:
totalTax:number = 30_034
taxPercentage:number = .15
Clean. Unaffected by the comments.
The semantic annotations are separate:
/(parse through tax-calculator.py)/ → document-level instruction
$.taxPercentage: //? between 0 and 1 → path-linked hint
A parser that doesn't understand these comments can still read the data.
A Tonic that understands the semantic language (defined by the profile) can merge the streams:
/[ if totalTax > 0 ]/
result = "taxes due"
/[ else ]/
result = "taxes paid"
/[ end ]/
A Tonic that follows this language can produce:
result = "taxes due"
But only because it runs the conditional logic defined in the profile's semantic language. The data itself is unchanged.
References exist in the data as symbols:
temperature = @celsius_reading
AES preserves this symbolically. It doesn't resolve it. No hidden evaluation.
A Tonic may resolve it—dereferencing @celsius_reading to find the actual value—but only if explicitly configured to do so.
This prevents:
- hidden recursion
- implicit evaluation order
- surprise reference chains
If something needs to mean something, it happens in one place:
the Tonic
The Tonic is where:
- semantic comments are interpreted
- references may be resolved
- values may be coerced
- behavior may be applied
And crucially:
- it is explicit (defined in a profile)
- it is isolated (doesn't mutate AES)
- it is optional (a consumer can ignore it)
- it is auditable (the consumer chose it)
Most systems try to prevent complexity in configs.
That doesn't work.
AEON does something different:
It allows complexity, but isolates it to where it belongs.
In AES (immutable data stream):
- Data is preserved as written
- Attributes carry metadata, not behavior
- References remain symbolic
- Semantic comments are parsed into a separate annotation stream
Power lives explicitly in:
- Semantic comment languages (defined by profiles)
- Tonic interpretation logic (consumer-chosen)
- AEOS validation rules (consumer-provided)
But never in AES itself.
Meaning is not prevented. It is explicitly deferred and optionally applied by the consumer.
This means:
- A parser without the semantic language can still read the data
- A consumer can reject input at validation time, before consumer-selected interpretation
- Multiple consumer-selected Tonics or materializers can interpret the same data differently, based on different profiles
- Power isn't hidden in the format—it's explicit in the profile
The practical benefit of layer separation:
A consumer can reject input before a consumer-selected Tonic or materializer interprets it.
Input → AES (immutable) → Consumer validates against contract →
If valid: consumer-selected Tonic/materializer interprets → If invalid: reject (no meaning created)
Example:
taxPercentage:number = 0.15 //? between 0 and 1
- Syntax valid ✅
- Structure valid ✅
- Form valid (number type) ✅
- Meaning check: "Does our profile understand this semantic comment language?" → depends on the consumer's contract
If the consumer doesn't understand the semantic comment language, they can still use the data—just without that interpretation.
Or they can reject it at validation time, before any Tonic runs.
This is key: other parsers create meaning first, then the consumer validates. AEON validates before meaning.
The goal isn't:
"Don't let configuration become powerful."
That doesn't work. Configs will become powerful.
The real rule is:
Don't let power hide in structure.
Make it opt-in, explicit, and profile-governed.
Configuration carcinisation isn't a bug. It's a natural outcome of systems that grow.
The mistake is pretending it won't happen and hiding it in the format.
AEON's approach:
- Accept that configs become powerful
- Refuse to hide that power in structure
- Require that power be explicit and profile-governed
- Allow consumers to validate before interpretation
If configuration languages are going to evolve into programming languages anyway, they should at least be honest about where that happens—and give consumers the choice to refuse it.
This wiki is the approachable AEON guide. Implementation information lives at aeon.altopelago.com. Specification publication lives at aeonite.org. Normative language behavior lives in aeonite-org/aeonite-specs, and conformance behavior lives in aeonite-org/aeonite-cts.