Reading a Data Model to Find the Rules Nobody Wrote Down
The data model a requirements register forces, drawn and read back move by move: eight rules the register never wrote down, and where each one goes.
Numbers in this note carry source tags ([POLICY], [THREADS n=10], [MINE]). What the tags mean.
This piece stands on the returns case published on this site: damaged-delivery refunds at a mid-size online retailer, built only from public sources - a published returns policy, help centre articles, ten public complaint threads I selected myself, consumer law and a walk through the published customer journey. No client, no interviews, no internal document, and so no database: nobody showed me a schema. This piece therefore runs the method the other way round. I draw the data model the case's five requirements force, read it the way you would read a real one, and count what the register never says. The model, the five reading moves and the sorting are mine [MINE]. You can redraw the model from the published register and argue with every row.
Finding business rules in a data model means reading every relationship, every field that may stay empty, every state a record can be in and every deletion as a decision someone made about the business, then checking whether that decision is written down anywhere a person could find it, own it and change it.
In short
- A data model is a second copy of the business rules, in a language most stakeholders never read. Every cardinality, optional field and status value is a rule, whether or not anyone wrote it as one.
- Five reading moves cover most of it: how many, must it be filled, which states, how long it lives, and who owns the list of allowed values.
- Run on the case, the model drawn from five requirements surfaced eight rules the register does not state. Six of them end up as open questions for someone who was never asked.
- A rule found in a model has no owner and no reason yet. It goes into the register as observed or proposed, or into the open questions, never straight into the build.
Why would a data model know rules the documents do not?
Because the model has to answer questions the prose can skip. Wikipedia's article on the entity-relationship model says such a model "is commonly formed to represent things a business needs to remember in order to perform business processes". What a business remembers, how many of each thing, and for how long, are business decisions. A sentence like "the case is reopened" can leave them open. A table cannot.
The PostgreSQL documentation on constraints calls data types alone "too coarse" and says of constraints: "If a user attempts to store data in a column that would violate a constraint, an error is raised." A constraint is a rule the system enforces on every record, whatever the policy page says.
The Business Rules Manifesto sets the standard a rule found this way has to reach: "Rules must be explicit. No rule is ever assumed about any concept or fact." A rule that lives only in a column definition is assumed by everyone who never opened the schema.
The model the register forces
Nine entities, each there because a line in the case needs somewhere to keep its data. If no line asks for it, it is not on the list. "REQ-014/2" means REQ-014, criterion 2.
| Entity | Forced by | What it has to hold |
|---|---|---|
| Order | BR-04, BR-11 | Delivery date (the 14 day window) and order value (the 40 EUR threshold) [POLICY] |
| Case | REQ-014/2, REQ-015/2 | Submission timestamp on the form, decision, due date |
| Photo | REQ-014/1, REQ-017/2 | Up to 3 customer files at 10 MB each [MINE], and at least one taken at the dock on a reopen |
| Assignment | REQ-015/1, REQ-015/3 | A named individual, never a group, with history, because "a reassignment sends one further message" |
| Decision | REQ-014/3, REQ-018/3 | Full, partial or refused, and for an automated approval the rule version behind it |
| Goods receipt | REQ-017/1 | The receipt date, because the goods-in reopen counts "five working days of receipt" |
| Reopen | REQ-017/1-2, REQ-015/3, REQ-016/2 | Who reopened, and a reason "in a list of stated reasons rather than free text" |
| Customer message | REQ-015/3 | Every message sent, because the criterion caps how many |
| Deletion log | REQ-016/3 | Case id and timestamp per deletion, kept after the photographs are gone |
| ## The five reading moves |
The same five questions work on a sketch from a register and on a production schema.
- How many? The cardinality of each relationship.
- Must it be filled? Every field that may stay empty, and who is responsible while it is.
- Which states, and what enters each one? Every status value, and the event that moves a record into it.
- How long does it live? What deletes a record, and what happens to the records pointing at it.
- Who owns the allowed values? Every list the system picks from instead of free text.
What did the five moves find in the case?
Eight rules the register depends on and does not write down.
| # | Move | Unwritten rule | Depends on it | Why the current wording does not settle it |
|---|---|---|---|---|
| U1 | How many | One case per order, or one per damaged item? | BR-11, REQ-014 | The help centre lists "partial damage to a multi-item order" among the daily exception paths [HELP]. BR-11 tests order value, whether one case or two |
| U2 | How many | When a case is reassigned, does the due date move? | REQ-015/2 | The due date is "the earlier of five working days from submission (BR-07) or 24 hours from assignment". Assignment has a history, so it can mean the first or the latest |
| U3 | Must it be filled | Who holds a case between the pre-check handing it over and the 48 hour breach? | REQ-018/2, REQ-015/1 | The pre-check passes what it does not approve "to a person". A named owner is required only "on breach of the 48 hour window". Until then the owner field may be empty |
| U4 | Must it be filled | Must the damaged item come back at all? | REQ-017 | The goods-in reopen counts from receipt, and nothing says a receipt has to exist. If the item stays with the customer, the guard rail on the condition risk never fires |
| U5 | Which states | What closes a case? | REQ-016/1-2 | Photographs are "deleted 90 days after the case closes" [MINE, OPEN, OQ-01], and the reopen rule turns on the same window. No requirement names the closing event: the decision, the payout, or the end of the goods-in window |
| U6 | Which states | Can a customer reopen a case, and until when? | REQ-015/3, REQ-016/2 | Both criteria describe what happens when a customer reopens. No requirement gives the customer a way to do it |
| U7 | How long | Do dock photographs follow the same retention as customer uploads? | REQ-016, REQ-017/2 | REQ-016 is written about "uploaded photographs". A dock photograph is taken by staff, possibly after the decision, and nothing says when its 90 days start |
| U8 | Who owns the values | What are the stated reasons for a goods-in reopen, and who maintains them? | REQ-017/2 | The criterion requires a list instead of free text. The list has no values and no owner |
U5 and U6 break together. If a case closes at the decision, the retention clock and the customer's reopen window start before the item has reached the dock. If it closes at the end of the goods-in window, retention starts later for every case and hangs on a receipt that U4 says may never happen. The register picks neither.
Is this not what the review already caught?
Partly. The BRD or SRS piece ran a swap test over the same register and found that the 24 hours in REQ-015/2 trace to no business rule. U2 is a different gap in the same sentence: not where the 24 hours come from, but which assignment they count from. The boundary questions under BR-04 and BR-11, raised in the decision tables piece, are about values. None of the eight above is: they are about structure.
The developer who reviewed the case asked "Under 48 hours from what moment?" (RL-02). U5 asks the same of the deletion job: 90 days from what moment? None of the five logged objections asks it.
Where does each found rule go?
Not into the build. A rule found in a model has no owner and no reason, which is what scorecard checks 16 and 17 exist to catch: a rule names who set it, and its reasoning is written down with inferences labelled. So each one goes to one of three places [MINE]: a proposed rule when the answer is a design choice I can defend (status "Proposed by me", as BR-12 is in the case), an open question when the answer belongs to someone with a decision right, or a criterion fix when the case has already decided and one criterion just needs to say it.
| # | Goes to | Owner, from the stakeholder map |
|---|---|---|
| U1 | Open question | Finance lead, who holds BR-11. It changes money out |
| U2 | Criterion fix: count from the latest assignment | None needed. REQ-015 exists "so that no case can sit without an owner" |
| U3 | Proposed rule: "A case without a named owner may exist only while its decision clock runs" | Head of Customer Care, if adopted |
| U4 | Open question | Returns goods-in lead, who inspects returned items |
| U5 | Open question, joined to OQ-01 | Legal. The closing event starts the retention clock |
| U6 | Open question | Head of Customer Care, who holds the public wording |
| U7 | Open question, joined to OQ-01 | Legal |
| U8 | Open question | Returns goods-in lead. The case asked nobody at the dock anything |
One criterion fix, one proposed rule, six open questions: the honest ratio for a case built from outside.
The rule harvest sheet, filled in
One sheet per found rule. This is U5, filled the way the case would carry it.
| Field | Content |
|---|---|
| Id | U5 |
| Found by | Which states: no requirement enters the state "closed" |
| Where the model needs it | Case status, and the start of the photograph retention clock |
| Lines that depend on it | REQ-016/1 ("90 days after the case closes"), REQ-016/2 (reopen inside or after the retention window) |
| Readings that fit the current wording | Closed at the decision. Closed at payout. Closed when the goods-in reopen window ends |
| What each reading changes | The first starts the deletion clock earliest, possibly before the item reaches the dock. The third keeps evidence longest for every case, and depends on a receipt that may never exist (U4) |
| Goes to | Open question, joined to OQ-01 |
| Owner | Legal |
| Status | Not in the register yet [MINE] |
The "Goes to" row matters most. A found rule with no destination is a note in a margin, and margins do not get baselined.
The rule harvest sheet, blank
| Field | Content |
|---|---|
| Id | [Your own numbering, separate from BR ids until the rule is adopted] |
| Found by | [Which of the five moves, and the entity or relationship it found] |
| Where the model needs it | [The field, relationship, status or list] |
| Lines that depend on it | [Requirement and criterion ids, quoted] |
| Readings that fit the current wording | [At least two. If only one fits, it may already be written down] |
| What each reading changes | [In money, time, evidence or customer messages] |
| Goes to | [Proposed rule / open question / criterion fix] |
| Owner | [A role from your stakeholder map with a decision right] |
| Status | [Observed, proposed, or not in the register yet] |
What changes when the schema is real?
The direction flips. A model drawn from a register finds rules the documents depend on and do not state. A real schema shows rules the system enforces that the documents may never mention: a field that cannot be empty, a status the code checks for, a deletion that takes other records with it. PostgreSQL describes that last one plainly: with CASCADE, "when a referenced row is deleted, row(s) referencing it should be automatically deleted as well". A deletion log tied to photographs that way would vanish with them, against REQ-016/3, which says the log outlives them.
The moves stay the same. A constraint in a live schema is evidence that someone once enforced a rule, not of who, why, or whether it still holds. It enters the register as observed with the owner slot open, the way BR-04 and BR-11 sit in the case with "Observed" status and OQ-03 against their owner. Where schema and published policy disagree, that is a finding, and the rule's owner decides which one is right.
Where does this method stop?
It finds structure, not values: not whether 40 is the right number. It works only if the model is drawn from the lines. Add an entity because "every returns system has one" and you will find rules in your own imagination.
And it does not replace a reviewer. All eight rules were findable in the register as published, and none was found until somebody drew the boxes. The process side of the same case is in as-is before to-be, where the parked branch is drawn step by step. The tags are explained on the method page, checks 01, 05, 16 and 17 of the scorecard are the ones a found rule has to pass, and the register this model was drawn from is at /case.
Read next
BRD or SRS: What Changes When Rules Meet a System
BRD vs SRS as one test: swap the system out and see which sentences survive. Run on all 19 rule and criterion lines of o
Turning Acceptance Criteria Into a UAT Script
A UAT script names who acts, what they do, the result they should see and the acceptance criterion each step proves. One
Get the Proof Pack
Six blank templates and one worked case. Free, one email. The scorecard is a separate file and needs none.
Send it to meAll field notes · The portfolio guide · More in The Case File