6 minute read

An ACL is the whole picture. Waitress, counter, cook — seen together.

Not a thing you build. A thing you see when you step back and look at the full translation path across a boundary.

Design A defined the port — the counter, a Passive Structure. Design B defined the adapter — the waitress and the cook, Active Structures with behavior. This document shows what happens when you put them together.

The Full Journey of an Order

Follow the ribeye from customer to kitchen.

The customer says: "I’d like the ribeye, medium-rare, with mashed potatoes."

Step 1: The waitress translates. She writes the slip in the format the counter accepts. Customer language becomes counter language. Active Structure doing its job.

Step 2: The slip sits on the counter. Passive Structure. It defines the shape. The slip conforms to the counter’s contract. Nobody is translating. The object just sits at the boundary.

Step 3: The cook translates. He pulls the slip and reads it in kitchen language. Counter language becomes kitchen language. Active Structure doing its job.

Three steps. Two translations. One boundary. The customer’s intent survived the crossing — medium-rare means medium-rare on both sides — but the language changed completely. The customer was thinking about dinner. The cook is thinking about sear temperatures.

That full path — Active Structure, Passive Structure, Active Structure — is the Anti-Corruption Layer.

Why "Anti-Corruption"?

Without the counter between them, the waitress would walk into the kitchen and tell the cook what to do. "Use the cast iron. Sear four minutes per side." She would be speaking kitchen language she does not understand, corrupting the cook’s process with her guesses about how cooking works.

Or the cook would walk into the dining room and interrogate the customer. "What internal temperature do you want? How do you feel about a reverse sear?" He would be speaking kitchen language to someone who cannot understand it, corrupting the customer’s experience.

The counter prevents this. Each side speaks only to the counter, in the counter’s language. The counter’s contract is simple enough that both sides can conform to it without understanding each other. The corruption cannot cross because the boundary is explicit and the contract is shared.

That is what "anti-corruption" means. Not security. Not validation. Protection of each side’s language from the other side’s assumptions.

A Convenience Construct

Nobody in the restaurant calls it "the Anti-Corruption Layer." The waitress thinks about customers. The cook thinks about food. Neither thinks about the ACL.

The ACL is what the architect sees when stepping back. It is an observation, not an instruction. You do not build an ACL. You build adapters that plug into ports. The ACL emerges from that assembly.

This matters for implementation. No class is called AntiCorruptionLayer. No package is named acl. There is a port interface. There are adapter implementations. When they are plugged together, the architect can point at the assembly and say "that is our ACL." But the developers building the adapters do not need to know or care about that label.

The ACL is a convenience construct — a name for a pattern that exists whether or not you name it. Every restaurant has one. No restaurant built one on purpose.

The Contract Lives in the Core

The port’s contract — the shape of the slip — is defined in the core domain. Not by the waitress, not by the cook. The restaurant owner decided what order slips look like. Both sides conform.

In software, this means the port interfaces and the objects that cross them are published by the domain. They are the SDK. When someone writes a new adapter — a new waitress, a new cook — they import the port’s contract and conform to it.

This is why the Babel fish from The Hitchhiker’s Guide is the wrong metaphor. The Babel fish is a magic translator with no explicit contract. It hides the boundary. You put it in your ear and suddenly understand Vogon poetry. There is no passport, no slip format, no shared shape that both sides agreed on. The fish just works.

An ACL is the opposite. The boundary is explicit. The contract is published. Both sides can see what shape the objects must take. A new adapter can be written by a stranger who has never met the other side — they only need the contract. The border patrol officer does not need to know you personally. Your passport conforms to the agreed shape. That is enough.

Total Recall: The Inbound ACL

The full path of store_memory:

Mind (customer)
  speaks: "store this memory about our conversation"
      │
      ▼
MCP Tool Handler (waitress -- Active Structure)
  listens: JSON-RPC tool call with arguments
  translates: assembles port object (content, metadata, tier, session_id)
  places on counter
      │
      ▼
MemoryPort (counter -- Passive Structure)
  contract: content, metadata, suggested_tier, session_id
  defined by: core domain
      │
      ▼
Domain Handler (cook -- Active Structure)
  picks up: port object
  translates: into StoreCommand, domain types, tier rules
  does the work: persist, score, associate

Three steps. Two translations. One boundary. The mind’s intent survived — "store this memory" means "store this memory" on both sides. But the language changed from JSON tool calls to domain commands.

The MCP Tool Handler does not know about StoreCommand. The domain handler does not know about JSON-RPC. They both know the shape of what crosses the MemoryPort — because the core domain published that contract.

Total Recall: The Outbound ACL

The full path of persisting a memory:

Hippocampus (cook -- Active Structure)
  finishes: processing StoreCommand
  translates: domain state into port object (Memory with tier, content, metadata, score)
  places on counter
      │
      ▼
BackingServicePort (counter -- Passive Structure)
  contract: Memory object shape
  defined by: core domain
      │
      ▼
Redis Adapter (waitress on the storage side -- Active Structure)
  picks up: Memory object
  translates: into Redis operations (HSET, key patterns, TTLs)
  does the work: the actual persistence

Same pattern. The domain does not know it is talking to Redis. Redis does not know about domain rules. They both know the shape of the Memory object — because the core domain published that contract.

If the Redis adapter is replaced by Postgres, only the bottom Active Structure changes. The counter stays the same. The contract stays the same. The domain does not notice.

What an ACL Is NOT

An ACL is not a class. There is no AntiCorruptionLayer.kt. The ACL is the assembly of adapter + port + adapter. You see it in the architecture diagram, not in the source tree.

An ACL is not middleware. Middleware sits in the middle and processes traffic. The ACL has no middle processor — the port is passive. The translations happen on the edges, in the adapters.

An ACL is not validation. Input validation is part of what an adapter does (the waitress checks the order makes sense before writing the slip). But the ACL’s purpose is language translation, not input checking.

An ACL is not a Babel fish. The Babel fish hides the boundary. The ACL makes the boundary explicit. The Babel fish has no published contract. The ACL’s entire power comes from the contract being published, visible, and shared.

The Two ACLs in Total Recall

ACL Outside Adapter Port (Contract) Inside Adapter

Inbound Memory

MCP Tool Handler

MemoryPort (content, metadata, tier, session_id)

Domain Command Handler

Inbound Lifecycle

Lifecycle Hook Handler

LifecyclePort (instance_id, reason, context)

Cortex Handler

Outbound Storage

Redis Adapter

BackingServicePort (Memory object)

Hippocampus

Outbound Notification

MCP Notification Adapter

NotificationPort (Notification object)

Subconscious

Outbound Relay (future)

Agora Adapter

RelayPort (Message object)

Domain Relay Handler

Five ports. Five ACLs. None of them were built as ACLs. Each was built as an adapter plugged into a port. The ACL is the name for the pattern, visible from the architect’s chair.


Previous: What is an Adapter? — the Active Structure, the waitress and the cook.

Next: Hexagon Sides — which ports exist, where they face, and what crosses each one.

Updated: