§2.4 Decision Models: What Is Allowed?
The models so far have been descriptive: they say what the system is or does. A decision model says what the system may do. It represents alternatives and the rules that permit, require, or forbid them. That single change in mood — from does to may — is the subject of the section.
2.4.1 The Canonical Move: Permitted Alternatives
Engineering represents permission in several familiar forms: decision tables that map conditions to allowed actions, rule systems, access-control matrices that record which subject may act on which object,11. Butler W. Lampson, “Protection,” ACM SIGOPS Operating Systems Review 8, no. 1 (1974): 18–24, https://doi.org/10.1145/775265.775268. policy graphs, feature models that constrain which combinations of options are valid, and constraint systems that declare which assignments are admissible. What unifies them is not their shape but their mood.
This is the sharpest instance of the earlier lesson that topology does not fix meaning. A structural edge and a decision edge can be drawn identically and mean opposite kinds of thing: A → B as a structural edge says "A calls B," a fact about what happens; the same arrow as a decision edge says "A may call B," a rule about what is permitted. The consequence lives in the absent edge. A missing structural edge means "no such call happens"; a missing decision edge means "no such call is allowed." The gap between those two readings is the reason decision models exist (Figure 2.4-1).
Once permission is declared, the claims a policy designer wants become expressible: which alternatives are permitted or forbidden, which are mutually exclusive, which imply prerequisites, whether the policy is internally consistent, whether it is complete over the cases that can arise, and whether it achieves least privilege. The analyses follow — evaluating a rule against a case, checking or solving constraints, detecting conflicts between rules, testing completeness and consistency. A declared policy turns "is this allowed?" into an evaluation rather than an argument.
2.4.2 DocAble: Service-Flow Policy
DocAble declares which of its services may communicate with which. The model is a graph whose edges carry the normative reading: an edge means the call is part of the sanctioned policy, and an absent edge means the policy does not permit it.
MODEL CARDService-flow model · Decision
- Engineering question — Which service may call which, and what may be reached from outside?
- Model — a declared graph of services and the permitted edges between them; the deployment is wired from the graph rather than the graph inferred from the deployment.
- Property — internal communication is permitted only along a declared edge; one declared node is the public entry.
- Quality attribute — least privilege; architectural integrity; security.
Figure 2.4-2 draws the permitted calls. One node is declared publicly reachable; every other edge is an authenticated internal call. The model is the single source of truth for those edges, and the deployment is generated from it rather than inferred from it — so a completeness check can require every gated edge to be fully specified before the deployment is wired. That check is real and enforced, but it governs the declaration's internal consistency, not the running traffic: the model declares the topology; it is not a runtime firewall.
Declaring the policy exposes a question the running system cannot answer for itself: do the services call only along declared edges? That is a correspondence between an observed structural fact and a declared decision, and the two are different claims. The observed call graph reveals that A calls C; the decision model states whether A may call C. Figure 2.4-3 sets them side by side.
Agreement between observation and policy would establish correspondence — the implementation matching the declared intent — not correctness: a faithfully-obeyed rule can still be the wrong rule. DocAble generates its deployment from the declared graph, but nothing at runtime reconciles observed traffic back against the declaration. Whether the deployed services stay on the declared edges, and what a departure should cost, is Alignment's question in Chapter 3.
2.4.3 DocAble: When the System Changed but the Model Did Not
The service-flow policy was declared as intent, ahead of any violation. DocAble's upload-admission decision acquired its model in the opposite order: the system changed first, one representation of the decision did not, and the gap surfaced in production.
DocAble admits an upload only when the user is entitled to it. A user receives that entitlement through groups. A group may carry a finite credit balance, drawn down as pages are processed, or it may provide unlimited use. The admission decision therefore depends on two different facts: how many finite credits are available, and whether any applicable entitlement is unlimited (Figure 2.4-4).
DocAble originally represented upload entitlement in finite credits alone. In that system, reducing a user's groups to a single number — the sum of their credit balances — was adequate for deciding whether a document could be processed. The product later gained unlimited groups, and the domain change altered the admission question: entitlement was no longer a single finite quantity. No explicit model of the upload-admission decision existed at the time. The decision lived in several implementation sites — a server-side reduction, a client-side preflight, the server's admission gate — each with its own hand-rolled representation of the user's groups.
One of those representations did not evolve. In August 2026, a user whose one group carried unlimited entitlement was blocked from uploading a thirty-eight-page document by a paywall: the upload needs 38 credits, and you have 0. The root cause was a legacy server function that reduced a user's groups to one scalar, the sum of their finite credit balances. The function was not ignorant of unlimited entitlement. It read each group's unlimited flag twice, using it once to exclude unlimited groups from the sum and once to compute a display label. Its output type simply had no place to put the fact, so the distinction died at the return statement. A purely-unlimited user became 0 credits; the client compared 0 against 38 and rejected the upload; the server's authoritative admission logic, which handled unlimited correctly, was never reached. This was a representation failure, not an information-availability failure. The implementation held the fact and threw it away.
The production failure produced the model. The root-cause analysis made the engineering question explicit — given the user's group entitlements and the requested work, should this upload be admitted, and under which entitlement? — and an explicit entitlement decision model landed in response. It did not land alone. The founding change carried property tests, a cross-runtime parity corpus pinning the server and the client to the same decision table, and a check on the model's shape. The legacy scalar reduction was deleted with no compatibility shim, the remaining display projections were re-sourced from the model, and the admission gates themselves were delegated to it. From root-cause analysis to model to deletion of the wrong representation took roughly five hours.
MODEL CARDEntitlement decision model · Decision
- Engineering question — May this user upload this document, and under which entitlement?
- Model — per-group entitlements that keep finite and unlimited as distinct cases; the output is a structured admission decision: admitted or not, the group that authorizes it, and the ordered plan by which the verdict was reached.
- Property — an unlimited entitlement can never be reduced to zero credits; the displayed balance is a projection of the model, not an authority for admission.
- Quality attribute — decision correctness; fidelity between the domain and its representations.
The repair did more than patch the conditional that failed. It changed the representation through which the decision was made. Upload entitlement could no longer be represented as a scalar credit balance: the revised model preserves finite and unlimited entitlement as distinct cases and represents the admission decision explicitly — whether the upload is admitted, which group supplies the entitlement, and the ordered plan used to reach the verdict. The implementation was then changed to consume that model. The same triggering state that once read as 0 credits now reads as admit by unlimited entitlement. The finite-credit scalar still exists where that quantity is the actual question, displaying remaining credits, but it is no longer used as a model of upload permission (Figure 2.4-5).
The model did not document the repair. The model was part of the repair. The failure revealed that an engineering decision was being made through a representation that could no longer express the system's domain, and making the decision explicit forced the representation to preserve the distinction the system had acquired. The opening section defined a model as a purposeful reduction that preserves the distinctions its question requires. The old scalar was a reasonable model of how many finite credits remain. It was never a sufficient model of may this user upload, and when the domain changed, the gap between those two questions became a production failure.
A note in the first person: I changed the domain in one place — groups could now be unlimited — and did not carry the change into every representation of the same decision. An explicit model would not have made the change automatically correct; it would have made the inconsistency visible as an engineering obligation. When the domain contains a consequential distinction, every representation used to reason about that decision must be capable of expressing it. Chapter 3 gives the recurring pattern here — a failure converted into explicit structure that later work inherits — a name.
Decision models delimit what is allowed. The final section steps back from any single model to ask how a family of models works together as a system.
Works Cited
- Lampson, Butler W. “Protection.” ACM SIGOPS Operating Systems Review 8, no. 1 (1974): 18–24. https://doi.org/10.1145/775265.775268.