Tripbooks design system / lab 18 / the audit

Lab 18 / the whole platform, walked against the system

The audit.

Every route in the five workspaces, every doctrine in the module documents, walked against the ten archetypes, twenty-four components and forty-three laws. Accounting got the deepest pass because it is the module the labs never gave a dedicated screen: thirty-six routes, an append-only journal, three-way matching, bank reconciliation, period close, segregation of duties and an AI agent that posts within a delegation.

The honest headline: the system holds, and the audit still earned its keep. It found three places where the system contradicts itself or the platform's own facts, one of which would have made accounting unbuildable as written, plus eight primitives the modules need that the labs never named, and a handful of places where the existing wireframes will have to change to comply.

171Surfaces walked
158Covered as designed
3Contradictions found
8Primitives added
4New laws
2Rulings needed

01 / coverage

Where everything lands.

The strongest evidence came from accounting itself: its own design grammar, written independently, names five shapes, and they map onto the archetypes almost one to one. Two vocabularies arrived at the same building.

Accounting's own grammarMaps toNotes from the walk
Dashboard (Overview)BoardCohorts, deltas against the whole prior period, every figure a rate or a trend, nothing a count of rows. Already obeys the board laws. Its "colour flipped where lower is better" delta is achromatic under the movement chip rule, which reads even better: DSO down needs no judgement colour.
Register (every list)RegisterKPI strip as filters, tabs for natural states, seven visible columns default, one line per cell, money in the row's currency with functional behind Columns. Compatible clause for clause. Their "at most one row action" is tighter than ours and correct; adopted.
Record (invoice, bill, batch, bank account, journal entry)WorkspaceWorkspace header, facts band, tabs, one table per tab, verbs only in the header. The journal entry page is append-only with a reversal pointer both ways, which the frozen-flag grammar already expresses.
Profile (the supplier)ProfileIdentity band, badge layer, KV grid, document rows, section-edit sheets. The bank-detail change control (request, second approver, 24 hour cool-off, retired account kept) is the permission-mark and attestation grammar doing exactly what it was built for.
Dialog / page formOverlays / ComposerTheir dialog list (raise credit note, write off, apply credit, record payment, match statement line, review bill, convert) all pass the "one decision" test. New batch payment "stays a page because it previews", which is precisely the composer boundary.
Everything elseVerdictNotes
Journal + Issues + Audit trailcoveredIssues is a worklist ("a rule bug, made loud"). The audit log is a register of an append-only store; reason-gated views reuse the vault gate. Posted-by in words ("Tripbooks", "Tripbooks AI", a name) becomes a law below.
Bank reconciliationcoveredStatement lines are a register; Match is a dialog on the unreconciled row with candidates nearest-amount-first and the difference shown before recording, which is the consequence-band pattern verbatim. Sign-off enabled only when it ties is the gate generalised, below.
Period closecoveredSoft, hard, lock, each refusing with named reasons and signed by name. This is the Lab 08 condition counter applied to a process instead of a form. One primitive, below.
Service deskcovered, adoption notesRegister, ticket dialog, charges to the ledger. Two wireframe details conflict with the system and change on adoption, listed in section 05.
Workstation toolscoveredThe tool rule holds for all six. Event Calendar and the leave calendar promote the calendar to a shared primitive, below.
HR & Payroll (doctrine)covered, one gapEmployees are profiles, payroll runs are workspace records with the batch-payment grammar, claims are a worklist, leave is a calendar. The org chart is the one true hierarchy on the platform, below. Payslips join the document grammar as a third audience.
Consolidated Reportingcovered when it landsAccounts down the side, entities across, native currency per column, presentation total. That is a wide table with a pinned identity column, which Lab 17 already built. Charts for it stay parked with the rest.
Document vaultcovered, one primitiveThe gate (capability, purpose, reason, fifteen-minute grant, log) is designed. What is missing is the surface behind it: the viewer, below.
Settings › ControlscoveredThresholds, retention, legal holds all fit the three-column settings grammar; every change audited fits the who-may-change column.

02 / the three contradictions

Where the system disagreed with itself, or with the facts.

These are the reason to run an audit. All three are cheap to fix now and expensive after adoption.

F1 · law"No supplier on any screen" would make accounting unbuildable

Law K1/L10, written during the marketplace lab, says no supplier exists on any screen. But the accounting module has a Suppliers register, supplier statements, supplier ledgers and remittance advices, and it must: an agency has its own direct suppliers, DMCs, local operators, its contracted airlines, and those are the agency's own data in the agency's own books. The concealment ruling was about the marketplace's upstream wholesalers, where the agency buys from Tripbooks and Tripbooks is supplier number one.

Fix, applied: the law is rescoped. Marketplace sourcing is invisible everywhere: no wholesaler name, rate id or third party code reaches subscriber or traveller, and marketplace purchases post against Tripbooks as the supplier. The agency's own suppliers are their data, fully visible in their own books, and still never on a customer artefact. One sentence of scoping keeps both truths.

F2 · lawDrift was already breaking the hue exception list

The specification names three places hue leaves disposition: the exposure tick, margin below floor, the destructive button. But the drift component, ruled in Lab 06, colours +1,240.00 red and −310.00 green, and the bills register colours a Difference beyond tolerance the same way. The list was wrong, not the component.

Fix, applied: the exceptions are restated as one family with one meaning: hue leaves disposition only for money moving against you: drift and match variance, margin below its floor, the exposure tick, the destructive button. Four members, one sentence, and the bills register's red Difference is now lawful instead of accidental.

F3 · law"Only Approvals carries row actions" is already false three times over

Bad debts has Approve on the row. The Tripbooks AI queue has Accept and Reject with the evidence on the row. Both are correct designs and both break the law as written, which named a page instead of a principle.

Fix, applied: restated at the level that survives: a row carries a decision in place only when the decision is one of two words and every fact needed to make it is on the row. Anything else opens a dialog that states its consequence. Approvals, bad-debt approvals and the AI queue all pass; everything else still links out.

03 / additions

Eight primitives the modules need, and four laws.

None of these bends an existing rule. Most are the fill rule and the gate finding yet more work to do.

A1 · primitiveThe gate, generalised

Lab 08 built a condition counter for forms. The audit found the same shape five more times: send a quotation, sign off a reconciliation (enabled only when it ties), soft-close a period (only when the checklist is green), activate a supplier (once onboarding names nothing missing), hard-close (only from soft, only at quarter end). One primitive: segments count the conditions, the outstanding ones are named in words beside the control, the control is never disabled without that sentence, and passing it records who and when. The attestation is the gate plus a signature.

A2 · primitiveThe group row

Already latent in three places: a marketplace rate point expanding to its options, batch payments grouped by supplier with subtotals, registers grouped by agent with per-currency rollups. Formalised: a parent row that expands to child rows and carries their subtotal. The parent obeys every cell rule; expansion is for children of the row, never for detail of the row, which stays the peek, the dialog or the record. This also settles the service desk's inline expansion, section 05.

A3 · primitiveThe statement

Profit and loss, balance sheet, cash flow, the aged matrix, the trial balance, the customer statement, TOMS. All one shape the labs never named: label rows with mono figures right, section heads, a heavy rule above every subtotal, indent for containment, signed minus for negatives. It is the table grammar minus the toolbar, and it is what prints.

A4 · primitiveThe currency pair

Every journal line carries a transaction amount and a functional amount with the stamped rate and its source. The registers show the row's currency and keep functional behind Columns. Formalised: transaction amount is primary, functional is secondary, the rate and source live in the tooltip, and the two never render at the same visual weight, so a converted figure can never be mistaken for an exact one. This is law L6 finally given its component.

A5 · primitiveUpload

Passport scans into the vault, supplier KYC files, recorded bills, brand logos, item library assets. No lab built a dropzone. Spec: a drop target that becomes a document row; an uploading file is hatched because it is literally open and in flight; refusal names the type or size limit; identity documents land straight behind the vault gate, never previewed on the way in. The fill rule's eighth job.

A6 · primitiveThe viewer

The vault's access half is designed; the surface that shows the file is not. Also needed by the tax document page, which renders the document beside its payload. Spec: a full-width document pane on the workspace grammar; for vaulted files it carries the grant countdown on the same clock component as the queue, and the file goes dark when the grant expires.

A7 · primitiveThe calendar

Departures, the Event Calendar, leave and availability, the service heatmap. Promoted from tool-space freedom to a specified component: a month grid where a day carries count and load, load is the sequential ramp (its second lawful use after the heatmap, same rule: colour carrying a quantity), and hard deadlines mark the day with a solid edge, soft with hatched.

A8 · primitiveThe org chart is an indented register

The one true hierarchy on the platform. No node-and-wire diagrams: hierarchy renders as indented disclosure rows on the register grammar, one line per person, the same row anatomy as everywhere else. If a future surface genuinely needs a drawn tree it makes its case in a lab; nothing today does.

The four laws

LawStatement
L13 · Negative money is a minusSigned mono, never parentheses on screen, and never red by virtue of being negative, because red is reserved for money moving against you. Debit and credit appear as words, only inside journal surfaces. A credit note is a negative the system is happy about.
L14 · A dash is not a zeroZero renders 0 and means measured-as-nothing. Null renders a dash and means no answer exists: no denominator, nothing landed, never asked. They sort differently and they never share a glyph. Already true in drift, conversion columns and consent; now true everywhere.
L15 · AI is an actor, not a decorationTripbooks AI appears as an actor in words, "Posted by Tripbooks AI", with confidence in the tooltip, evidence attached as chips, in the same registers and timelines as human acts. No robot glyphs, no special colour, no separate visual class. It acts only within its delegation, and above it, everything it produces is a proposal a person accepts by name.
L16 · Endless tables paginateWas folk law in the module docs; now platform law. 8,600 statement lines and 7,508 run lines are why. No infinite scroll anywhere money renders.

04 / stress

The hard scenarios, run on paper.

ScenarioHow the system holds
The flagship booking: 30 to 40 items, 25 suppliers, several currenciesThe item table paginates (L16), kind icons keep rows at 31px, the gate is per booking not per item, and post-F1 the supplier column shows the agency's own suppliers while marketplace items show Tripbooks references. Currency pairs (A4) keep mixed-currency items honest.
A journal of thousands of postings, multi-currency, append-onlyRegister + pagination + the currency pair. Reversal links both ways on the record; the frozen flag grammar covers immutability; a refused posting is loud in Issues, a worklist.
Month end on the busiest entityThe close pack is one gate (A1): nine checklist items as segments, refusal reasons named, sign-off recorded. C11 honestly red until suspense is coded is exactly the "never add surface to justify a wrong result" law doing compliance work.
The all-red morning: exposure, breached SLAs, overdue everywhereBecause severity is a hueless edge and status marks are small, a screen where everything is broken is still readable; the single inverted exposure row keeps its rank because inversion is not repeatable. This was the design bet of Lab 04 and it survives the worst day.
A zeroed brand-new tenantEvery register has a designed empty state naming the next action; the dashboard's cohorts render zero without division; percent-of-nothing renders a dash, not 0% (L14).
The colour-blind accountant on the dark theme, printingFill carries every distinction, dark is measured not flipped, the statement (A3) prints in ink on white with the hatch surviving. No scenario in the module docs requires a distinction the fill rule cannot carry.

05 / adoption notes

Where the existing wireframes will change to comply.

Not gaps in the system; places where the built product predates it. Recorded so adoption is a checklist, not archaeology.

Today in the wireframesUnder the system
Service desk: coloured SLA countdownCountdown becomes mono text; urgency is the severity edge on the row. Colour stays with disposition.
Service desk: single click expands a 3-step record in the tableRow detail is not row children (A2). The expansion becomes the ticket dialog it already has; the row keeps one action.
Enquiries: Kanban pipelineRuling needed, below: a board view as a register grouped by stage, or retired in favour of register + stage filters.
Overview deltas: "colour flipped where lower is better"Movement chips are achromatic, so the flip logic simply disappears. DSO down and revenue up read identically as direction plus magnitude.
Bills: Difference red beyond toleranceNow lawful under the restated F2 exception, unchanged. Listed because it looked like a violation and is not.
Facets and TanStack filters on twelve registersAlready scheduled as filtering phase 8; the system assumes the one-query model everywhere.

What I need from you

Two rulings, and the rest is recorded.

  1. Kanban. Enquiries has a pipeline board today. Options: keep it as a lawful register view (cards obey row content rules, drag moves stage with the same logging as the action menu), or retire it and let the register's stage filter and the workspace stage bar carry the job. I lean to keeping it as a view, because a pipeline of open enquiries is genuinely spatial in a way a table is not, but it is the only card surface in the operator interface and that costs consistency.
  2. The three fixes in section 02. All three are corrections of the system's own inconsistencies rather than new design, so I have applied them to the specification and handbook. If any reads wrong, say so and it reverts.