Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungI upgraded three Flutter apps to API 36. Here is what actually broke(20.09.2026 um 17:37 Uhr)
Sichere ProgrammierungSite-Wide Structured Data and Social Graph Integration(20.09.2026 um 17:44 Uhr)
Sichere ProgrammierungExact Match Or Fuzzy Logic For OFAC? 1,400 Tests Changed My Mind.(20.09.2026 um 17:45 Uhr)
Sichere ProgrammierungWhat Makes You Trust an APK Download?(20.09.2026 um 17:47 Uhr)
Sichere ProgrammierungGood News For Backend And Devops Buddy(20.09.2026 um 17:50 Uhr)
Linux Tipps & HardeningBeginner Guide: What Is Linux Mint and Why It Is So Popular(20.09.2026 um 17:54 Uhr)
Sichere ProgrammierungI upgraded three Flutter apps to API 36. Here is what actually broke(20.09.2026 um 17:37 Uhr)
Sichere ProgrammierungSite-Wide Structured Data and Social Graph Integration(20.09.2026 um 17:44 Uhr)
Sichere ProgrammierungExact Match Or Fuzzy Logic For OFAC? 1,400 Tests Changed My Mind.(20.09.2026 um 17:45 Uhr)
Sichere ProgrammierungWhat Makes You Trust an APK Download?(20.09.2026 um 17:47 Uhr)
Sichere ProgrammierungGood News For Backend And Devops Buddy(20.09.2026 um 17:50 Uhr)
Linux Tipps & HardeningBeginner Guide: What Is Linux Mint and Why It Is So Popular(20.09.2026 um 17:54 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

When One Enum Is Secretly Two

Reagiere als Erste:r — dein Feedback zählt!

I was one commit away from a bug that would never have thrown an error.

My system keeps every closed vocabulary in a single file — one source of truth for "here are the legal values for this field." One of those vocabularies described filesystem operations: read, create, modify, delete. Clean, small, obvious. Two different parts of the system were going to read it.

The first part is authorization. Every capability in the system declares a filesystem profile — what it's permitted to do. This worker may modify files but may not delete them. For that, the distinctions that matter live on the write axis: create, modify, and delete are three different permissions you might grant or withhold independently. Reading? Reading is just read. One bucket. The profile doesn't need to slice it finer.

The second part is audit. A taxonomy classifies every filesystem call the code makes, so a completeness check can prove that no category of access slips by unaccounted for. For that, the distinctions that matter live on the read axis: Path.read_text reads a file, Path.glob enumerates a directory, yaml.safe_load(path) parses a protected config off disk. Those are three different audit subjects. Writing? For the audit's purposes, writing collapses to a single write — because the policy it enforces is shaped like this namespace forbids the write class, full stop.

Look at the inversion. Authorization splits writes and collapses reads. Audit splits reads and collapses writes. Same domain — filesystem operations — sliced along perpendicular axes, because the two readers are answering different questions.

And they were about to share one enum.

The race that nearly buried it

The reason they were about to share it is almost funny. Two design decisions, written months apart, both declared they'd use "the filesystem operation vocabulary." A clause settled the overlap: whichever one gets implemented first creates the list; the second just uses what's already there. A materialization race — a data race, but for a vocabulary decision spread across two documents.

The authorization side shipped first and wrote [read, create, modify, delete]: the write axis. Which meant the audit side, when I finally got to it, would have inherited a vocabulary with no word for traverse and no word for parse. It would have had to lie in the only language it was given.

The tell

Here's the moment it stopped being a style preference and became undeniable.

Take Path.glob. Under the authorization vocabulary, the most honest label for it is read — it doesn't mutate anything. Under the audit vocabulary, read is flatly wrong; it's traverse, and that distinction is the entire point, because "this code enumerated a protected directory" is a different finding than "this code read a single file."

Same call. Two correct answers. The enum can only hold one.

That is the signature of one enum doing two jobs: a single concrete value that belongs in different buckets depending on who's asking. There is no naming fix for that. read isn't badly named. It's being asked to mean two things at once.

Why DRY was lying to me

The pull toward one enum was DRY, and DRY is usually right, which is exactly what makes this trap good. One vocabulary, one place, both consumers referencing it — that looks like the discipline you're supposed to practice. It feels like hygiene.

But DRY is about not duplicating knowledge, not about not duplicating shape. Two vocabularies that happen to overlap in spelling are not a repeated fact. They're two separate decisions that rhyme. Merging them doesn't remove duplication — it manufactures coupling, binding two things that change for different reasons. The authorization vocabulary changes when the permission model changes. The audit vocabulary changes when the set of call-classes you care about changes. Different forces, different cadence, different owners.

That's the Single Responsibility Principle, except aimed at a data type instead of a class: if two independent forces can each demand an edit, you're holding two things.

One spelling, one meaning

The rule I'd actually broken has a cleaner statement than any of this: one spelling, one meaning.

I had one spelling — fs_operation_class — quietly carrying two meanings. And that's the same defect as the version everybody already polices: two spellings for one meaning, userId in one file and user_id in the next. We catch the synonym on sight; linters scream about it.

The homonym hides. One word, two meanings, nothing visibly duplicated. It doesn't look like a smell. It looks like economy.

How I spot a fused enum now

Any one of these is a yellow flag. Two of them is a decision:

  • Two subsystems both branch on the enum, for unrelated decisions.
  • You keep wanting to add a value "just for" one consumer that's meaningless to the other.
  • A single concrete value belongs in different buckets depending on which consumer is reading it.
  • The description has to say "for X this means…, for Y this means…"

That last one is the confession. The moment your docstring needs the word "for," you have two enums.

The fix, and the line

The fix wasn't clever. Two enums.

One keeps [read, create, modify, delete] for authorization. A new one carries [read, traverse, parse, write, neutral] for audit. Their overlap is exactly one value — read — and even that is a coincidence of spelling, not a shared decision: it's just the single operation that means the same thing under both questions. Each vocabulary is now free to move along its own axis without dragging the other behind it.

The sentence I wrote into the decision record, the one I'll reuse for the rest of my life:

When a unification claim doesn't survive the material differences between two surfaces, the unification was the bug — not either surface.

Why this one kept me up

A normal refactor earns a shrug. This one didn't, and here's why.

Nothing about the fused enum would have crashed. In a fail-closed system, that's the nightmare case: it doesn't fail closed, because it doesn't fail at all. It validates fine. It loads fine. It quietly hands one of its two readers a lossy answer, forever.

The authorization side would have been correct. The audit side would have cheerfully reported all reads accounted for — while folding traversals and parses into a read bucket it could no longer tell apart. A completeness check that's complete only because it went blind.

The worst bugs in a governance system aren't the ones that throw. They're the ones that pass.

One enum, two meanings. Go check your docstrings for the word "for."

This is from CORE, an open-source constitutional governance runtime for AI-generated code. The decision above is ADR-080; the two enums live in the repo if you want to call my bluff: github.com/DariuszNewecki/CORE

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten When One Enum Is Secretly Two

Thematisch verwandte Begriffe: When, Enum, Secretly · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-93956 | A flaw has been found in olivier-ls PHP-FTS up to 1.1.2. Affected by thi…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick