Schema, application pages, and website pages. The database is written and tested; everything else here is the inventory to build against it. Phase tags match the PRD.
Three things exist on disk now: the D1 schema, the design tokens, and this plan. The schema is not a sketch. It applies cleanly to SQLite 3.51 and the derived logic has been smoke-tested, including the case most likely to be wrong.
Four design rules are enforced in the database rather than left to application code, because application code drifts and a schema does not.
| Rule | How it is enforced |
|---|---|
| Room state is append-only | room_state_events is never updated or deleted. A correction is a new row pointing at the old one via supersedes_id. Current state comes from the room_current_state view. Days-down is derived, never typed in. |
| N/A never counts as a failure | The inspection_scores view puts only pass and fail in the denominator. Verified: 2 pass, 1 fail, 1 N/A returns 66.7%, not 50%. |
| History cannot be rewritten | inspection_results stores frozen snapshots of the item text, section name and criticality. Editing a template next year cannot change last year's score. |
| Offline replay is idempotent | client_mutations is keyed on a UUID the device mints before it has network. A second sync of the same queue is a no-op, not a duplicate inspection. |
All three migrations apply cleanly. The scoring view returns 66.7% on a 2-pass / 1-fail / 1-N/A inspection and flags the critical failure. A room taken out of order at 09:02 on Aug 5 and returned at 14:00 on Aug 8 derives 3.21 room-nights down, which against the seeded ADR of $129.66 produces $415.81 revenue at risk. That number was computed by the database, not by me.
properties.adr_cents is deliberately nullable. When a pilot property will not share
ADR, the record shows room-nights only and says so. There is a dedicated
.figure__unavailable style for exactly this. A fabricated dollar figure on a document a
lender might read would end the product, so the honest empty state is designed rather than
improvised.
Field surface — charcoal, one-handed, offline. Everything a tech or GM touches on property.
| Route | Phase | What it does |
|---|---|---|
| /login | P0 | Server-side session auth. The page is gated, not just the action. |
| / | P0 | Today. Property picker with last score, or straight into the single property a tech can see. |
| /inspect/new | P0 | Pick property and template, choose which rooms to sample. |
| /inspect/:id | P0 | Walk & Tap. Property-scope sections. Assume-pass, live score, 44px targets. |
| /inspect/:id/room/:roomId | P0 | Room-scope sections, swipe room to room. |
| /inspect/:id/review | P0 | Score by section, deficiency list, submit. Last stop before it becomes a record. |
| /rooms | P0 | Room status board. Mark out of order with a reason; the clock starts. |
| /rooms/:id | P0 | Room detail and full state history. Return to service requires a resolution note. |
| /deficiencies | P0 | The punch-list. Filter by property, room, status. |
| /deficiencies/:id | P1 | Detail, photo, assign, and the vendor call action. |
| /vendors | P1 | Directory by trade. Tap-to-call via the device dialer. No telephony vendor. |
| /vendors/:id | P1 | Vendor detail and full contact history. |
| /inventory | P2 | Count entry and the below-par reorder list, linked to vendors. |
Record surface — white, printable. What the owner, and eventually their lender, reads.
| Route | Phase | What it does |
|---|---|---|
| /portfolio | P1 | All properties: latest score, 6-month trend, delta, open items, last walked. |
| /property/:id | P0 | Property dashboard. Rooms down now, open deficiencies, score trend. |
| /property/:id/record/:period | P0 | The Condition Record. The product. Revenue at risk with its arithmetic shown, rooms down, median days down, score. Prints to one page. |
| /vendors/performance | P1 | Vendor accountability. Suppresses any vendor under 5 completed jobs and says why. |
| /inspections/:id | P0 | A single completed inspection, read-only, with photos. |
| /capital/:year | P3 | Capital & renovation plan. Refuses to render under 12 months of data. |
| /admin/* | P1 | Properties, rooms, users, access, templates. |
Offline capture first, not last. The service worker and the IndexedDB replay queue are the only genuinely hard engineering in this phase; everything else is forms over a database. Building it last is how a project discovers in week six that its data model cannot survive a dead zone.
Suggested sequence: offline queue → Walk & Tap → room state → punch-list → the Record. The Record comes last because it is the easiest to build and the most satisfying to demo, and it is worth nothing if the capture underneath it is not trustworthy.
Two audiences, and they want different things. An owner wants to know what it recovers. A management company wants to know what it proves to the owners they answer to.
| Route | Phase | Job of the page |
|---|---|---|
| / | P0 | One promise: know what your property is costing you while it sits out of order. Hero is a real Condition Record, not an illustration. |
| /how-it-works | P0 | The loop in four steps: walk, flag, fix, report. Show the actual phone screens. |
| /for-owners | P1 | Revenue at risk, vendor accountability, and what you hand a lender at refinance. |
| /for-management-companies | P1 | Portfolio rollup and the reporting artifact you give the owners you answer to. |
| /the-record | P1 | The differentiator page. What a Condition Record is, why it compounds, and why it needs a year of data. |
| /pricing | P1 | Platform fee plus per property. Numbers wait for the pricing pass. |
| /about | P0 | Brian and Mandeep. Operator credibility plus build credibility. Endorsed by Ascend Systems. |
| /demo | P0 | Single form. The only conversion point on the site during pilot. |
| /legal/privacy | P0 | Required. Guest-adjacent data and photos of private property are involved. |
| /legal/terms | P0 | Required before any pilot agreement is signed. |
Nothing on the site may claim the capital report exists until it does. During the free pilot the honest position is the strong one: we are collecting the record now because the report that matters needs a year behind it. That is also the argument that creates urgency to start.
| Domain | Nothing is registered. roomprovenance.com, provenanceportfolio.com and provenance.management were confirmed available earlier today, but availability moves. Your card, your call. |
| Trademark | Still unsearched. It does not block the prototype. It does block spending on identity or signage. |
| ADR for the pilots | Ask Mandeep whether the pilot properties will share it. It decides whether the flagship report shows dollars or room-nights. |
| Cloudflare | The cloudflare-api connector is not authorised in this session, so I cannot create the D1 database or R2 bucket for you. Authorise it in your claude.ai connector settings, or run wrangler d1 create provenance and wrangler r2 bucket create provenance-photos yourself and paste me the database id. |