Proving it was you

Three of the four homeowners in this product have no account, so most signatures in it are made through a link. A link alone asserts; a link plus a code identifies; and only one of those puts money on a contract. The difference is drawn as a fact about the total, never as a fact about the person.

1 · Signing it, on a link
Ben Okonjo at Cedar Court. Cost plus, inside the walls, and the stack came up nine inches off the drawing. He has no app to open and no session to be in, so this page is the whole transaction.
DM
Dave Marsh Builders
Cedar Court
Rerouted waste line

Dave needs this signed before the plumber comes back on Friday.

What this adds
CO-2 · Rerouted waste line+$2,140

The stack came up nine inches off the drawing. Dave found it when the wall opened, and the run has to move before the plumber can close.

Sign it I have a question first
This is as of Thursday morning, when Dave sent it. The page doesn't update.
The sentence on the tick is the sentence stored

`change_order_signatures` has a `consent_text` column and it is `NOT NULL` — the row keeps the exact wording, not a version number pointing at whatever the wording is today. That column is the only reason this screen can be honest a year later, and it is already there.

Nothing here says he has no account

No no password needed, no lighter type, no second-class framing. `FICTION.md` is absolute about it and the reason is the record: a year on, the binder must not be able to tell a link signature from a session one, and must not care. What differs is what the money does, which is frame 3.

And the escape is the same escape every type 1 carries

I have a question first is not a decline and does not close anything. It is the deferral drawn on mockup 32, and a signature screen that dropped it would be the one place in the product where asking a question was not allowed.

Rung 2 · spoken
2 · The code, once
What follows the tap, the first time this number signs for money. Rung 2 because it interrupts: he cannot finish what he came to do without it, and the thing it is protecting is on the screen with it. He will not be asked again for six months.
DM
Dave Marsh Builders
Cedar Court
Confirm it's you

We sent six digits to the number this link came to: the first time it signs for money, and again if it has been a while. After this, the link is enough.

752
What you are signing
CO-2 · Rerouted waste line
+$2,140, and it goes on Cedar Court's contract once this comes back.
Didn't arrive? Send it again.
A consequence gate, never an entry gate

_ds/forms.css settled this before this page existed: "A page putting it in front of a login has misread the model." Nobody is stopped on the way into their own house to prove they own an address. What is gated is the one moment a number moves, which is why the amendment is drawn on the same screen as the boxes.

Once per number, not once per amendment

The code and the link arrive on the same phone, so a code on every signature re-proves a fact the link already proved. What it buys is one thing — a forwarded link cannot sign — and that is worth asking for once, when the number is new to us, and again if it has gone quiet long enough to be worth asking. Between those two moments the link plus the signed sentence is the record, which is what every e-signature product does and what this one should have said from the start. A second ask, back to back, is not a second proof; it is the same proof, charged twice to somebody doing you a favor.

And a new number is a new binding

The confirmation is against the number, not the person and not the amendment, so a signature arriving from somewhere this job has not seen asks again. That is one of two re-asks in the design and the one where the thing being proved has genuinely changed; the other is time passing rather than the number, and it is named further down.

This is the rung the backend reserved and never built

signature_assurance.go fixes the spelling — token_challenged — and deliberately does not declare it, because nothing writes it: "a value with no writer is the same defect as a column with no writer." There is no code table in any of the 86 migrations either. Frames 1 and 2 draw a mechanism that does not exist. What does exist is a fail-closed function ready to receive it.

And there is no countdown on the boxes

The component rule, and it holds here even though this is the highest-stakes place it appears. A code that is expiring says so in a line underneath at rung 1. A clock ticking on the box is anxiety with no action attached, and this is the screen with the least room for it.

3 · What lands on the contract
Dave's side on Monday, looking back at the Thursday. Two signatures on one job, one code between them, and both on the contract — and the screen never says which one cost the code.
It says whether, and it never says how

This is the frame most likely to break FICTION.md's rule and it is drawn to show that it does not have to. Neither row names a mechanism, a channel or an account. Signed Thursday 13 May by Ben Okonjo is the whole of what the record says about either of them, and the one that cost a code is indistinguishable from the one that did not — which is the point. The code is a fact about a number, never a fact about a signature.

A row can still be held, and it is rarer than this page used to draw it

Two cases, and they are the same card 13-money frame 3 gives CO-1: a first amendment signed and not yet confirmed, and one signed from a number this job has not seen before. Neither is on this screen because Cedar Court has neither — and drawing a held row here would have taught that holding is the normal state, which after the ruling it is not. Frame 2 is where a held amendment actually lives: it is the screen somebody is looking at while theirs is held.

Beside the total, never inside it — still the rule

When a row is held it renders as its own card and not as an ordinary line, because a held amount inside the total makes the total wrong, and one left off the screen makes the confirmation feel like paperwork about nothing. 13-money frame 3 carries the treatment for Sam, which is where it now appears twice rather than three times.

And the action stays his, never a nag aimed at Ben

On a held row the control is ask him to confirm it rather than a red count or a chase timer. The person who can resolve it is holding the phone, the thing they can do is send one message, and the account-less tier's send rule still applies: never send somebody something that does not need them.

Drawn twice, built zero times

Mockup 01 frame 7 drew the code on the front door and gave it to Sam, who by mockup 13's own argument will never see it. Mockup 13 frame 3 asserted that the signature code and the email code are one mechanism. The backend has never had either. What it does have is signature_assurance.go: two declared values, a third reserved by name and deliberately left undeclared, and a fail-closed default that refuses to promote money on a string it does not recognize. That file is the most careful thing in the gateway and it has been waiting for this page.

What it costs

A confirmation table — the number, a hash, an expiry, attempts — one send through the outbound path that already exists, the constant declared, and one case added to signatureAssurance. No column moves on change_order_signatures. The level was always derived rather than stored, and that decision is what makes this cheap: a policy that tightens later comes out retroactively right on every historic row instead of wrong on all of them.

The row binds a number, not a signature, which is the only structural consequence of the ruling below. Assurance is then a question about the number a signature arrived on, asked at read time — so confirming once counts everything that number has already signed, and everything it signs afterward.

What this page deliberately does not do

It does not put a code in front of a login, it does not draw a badge saying who has an account, and it does not give Ben a dashboard. Requiring a second factor at sign-in is a real question and a different one, and it is answered on 15 · Account & being told, frame 8, next to the rest of the account rather than next to this.

Which amendments require the code — ruled 2026-08-10

Once per number, and not again unless the number changes or the confirmation goes stale. An earlier draft of this page left the question open between three answers: unconditional, over a figure, or the builder's to set per job. It is none of them, and the reason the fourth answer was missing is that all three assumed the code proves something the link does not.

It does not. The code is sent to the number the link arrived on, so on every signature after the first it re-proves possession of a phone that possession of the link already proved. The one thing it genuinely buys is that a forwarded link cannot sign — and that is worth one interruption at the start of a relationship, not one per amendment.

The three rejected answers, and why:

How long a confirmation lasts — ruled 2026-08-10

Six months, and it resets every time it fires. A confirmation is not a permanent grant; it is evidence with an age, and the age that matters is confirmed_at, not the day the project opened. A number confirmed last week and a number confirmed two years ago read identically to a join that only asks is there a row — so the derivation gets a second clause: confirmed, and confirmed inside the window.

Six months clears US carrier number-recycling practice — a dormant number can be reassigned in as little as 45–90 days — with room to spare, without re-asking anyone who is actively signing. A signature does not reset the clock on its own; answering a fresh code does, so a homeowner mid-project who signs monthly is never interrupted, and one who goes quiet for two seasons is asked again before the next amendment counts.

It is a freshness floor, not a fraud check

Re-asking does not catch a number that already changed hands, because the new challenge goes to whoever holds the phone now — same as the old one did. What it buys is the same thing the first ask bought: a record that says the last person to answer this phone did so recently enough to mean something, on the row a dispute would actually read.

Same rule as the digest cadence floor: the window is not the builder's to extend. Six months is the constant, not a per-job setting.