SCOPE: everything in progressdocs/todo.md · build 40bb41bdb460

Loading ticks…

Checklist and progress

What we are working on, what is finished and what comes next, grouped by phase and month, with the newest work first. Written for everyone on the team, technical or not. The technical detail behind each item is at the bottom of this page, under "Technical notes".

Done in October

The newest first within each group. What is still being built is under Phase 2 below.

Features

  • 29 Oct Security audit (SOC 2), the database half (#43, continuing): every change to every record is now kept, and a VP can read who changed what in a Change log on Reports, with Download CSV; records under a legal hold cannot be deleted, and a hold needs two different VPs to place or lift it; a retention report by kind of record; nothing in the database can be read without signing in, except the hub's own pages; and every build of the app is scanned so no key reaches the browser. Applied to the company database on 29 Oct, with the evidence written up
  • 28-29 Oct Security audit (SOC 2), the paperwork and the board (#43, continuing): seven more gaps found by reading the audit's own rules point by point; the drafts checked against each other and the board (25 contradictions settled); one sign-off pack for Kyle; the access review now lists machine keys and app connections as well as people; a list of the 25 security settings GitHub, Vercel and Supabase must have, read back automatically each month (the first run found 8 differences, 7 of them already open items); every change request now asks how it would be undone and whether it could take the app down. The readiness page gained a running readiness percentage, a "Kyle decides" filter, a search by SOC 2 code, a plain summary of what each SOC 2 code asks for, and a By priority sort
  • 27-28 Oct Getting ready for a security audit (SOC 2) (#43, continuing): every one of Kyle's 59 points checked against the code, plus nine more found by reading the audit's own rules; the company's GitHub, Vercel and Supabase accounts are now the only ones audited; main is protected (every change goes through a pull request that has to pass five automatic checks); the company database is up to date, with its permissions repaired and fresh demo passwords; the policies are written, free tools chosen wherever an auditor would accept them; security protections added to the app (browser security settings, location removed from photos, nothing callable without signing in). The list, with ticks, is the SOC 2 readiness page on this hub
  • 22 Oct Training: how often, and from when: any course can now say how often it is done again (every 12 months, say), not only the ones that renew a licence or certificate, and changing it applies to everyone who has already done it. A rule that gives a course to a whole job can count from the day someone started that job, not only from their hire, and can say what happens to people already there: the same number of days from today, nothing (new starters only), or one date for all of them
  • 15 Oct Training system, checked end to end and fixed: a fresh review found 28 problems, all now fixed. Every course assigned to someone reaches their home screen; every outcome (absent, not passed yet, sent back) is shown; every mistake (withdrawing a course, a wrong date, a wrong result) can be undone, with the reason recorded; a review goes to someone else when a supervisor is away; renewals become due 14 days early; 199 courses that had lost their link were linked again or withdrawn; renewals and standing rules run by themselves every night; people who have left owe no training
  • 15 Oct The Training page opens on a To do list: what has expired, what is waiting for approval and what is due in the next 90 days, one button per line; a calendar shows only who is left to book; a booking confirms it worked; Export to Excel
  • 15 Oct The database map searches and explains itself: type an everyday word (DVIR, CDL, med card, overdue) to find where it lives; a Connections view says every link in a plain sentence, and finds the chain between any two parts, for example from an incident to the retraining it caused
  • 14 Oct Rule mapping, first working version (#27, building continues): the rule book, the course catalogue and the corrective actions linked through a list of hazards, with no AI, so every link shows why it was made. On our own hub only, not in the demo
  • 14 Oct What connects incidents, corrective actions and training today, written up: the starting point for rule mapping
  • 13-14 Oct A client's COFI carries the client's own logo, as " powered by COFI"
  • 9 Oct The Training page opens on whether we are covered, with a 12-month renewal plan; a course page opens on who needs it
  • 7-9 Oct Training system, first stage: a library of courses, classroom sessions signed off by the trainer, training taken elsewhere (approved by a supervisor), automatic assignment by job and site, and renewals planned twelve months ahead
  • 5 Oct Equipment certifications: a driver needs both a licence and a company certificate for each type of machine before they can do its inspection, plus a report of who is covered for what
  • 7 Oct VP demo persona renamed Sal Hankins
  • 1 Oct Old reporting connection for Power BI removed; the app's own COFI screens do that job now

Novvia's copy of the code

  • 13-15 Oct Sign-in, first four steps built (#19, building continues): who may sign in; accounts created and removed automatically from a client's staff directory; an admin screen to approve people; a client's staff file loaded with a proposed access level for each person, approved one by one or all at once
  • 15 Oct A rehearsal of bringing in a client's files on the practice database: staff, equipment, qualifications and training history all load
  • 15 Oct The set-up guides: the steps to bring a new client on, the list of data we need from Novvia, and a first draft of the guide for their company login (OneLogin)
  • 15 Oct Database permissions tightened further in the Novvia copy: access that no screen uses was taken back (the second layer of #12)
  • 13 Oct Change tracking on every record (#20): every record shows who created it and who last changed it, and when
  • 13 Oct Sign-in plan written and reviewed from four angles
  • 13 Oct Two company copies of the code created; finishing the set-up is #18
  • 13 Oct Safe copy kept before the move (old #1): Dan's personal copy and the live demo were left untouched, so nothing the demo depends on was at risk during the move

Working documents on the hub

  • 29 Oct Safeguards, on one page: what keeps SCOPE safe today (the locked main branch, scanning for keys and risky code, access enforced by the database and proved every night, the automated tests) and what is not done yet. The SOC 2 drafts are now drawn under the readiness card instead of as a card of their own. Both waiting to be merged
  • 15 Oct One Checklist and progress page (this one) instead of two; ticks are saved for everyone
  • 14-15 Oct The questions page, by month with settled questions at the foot; anyone can answer
  • 14 Oct Business rules for review and comment: every rule the product applies, one sentence each, to mark Looks right, ask a question, or ask for a change
  • 9-14 Oct The hub reorganised: working documents first, a contents list on the long documents, and a Back to top button

Preparing for the database review

Patrick's database administrator will review the database before clients use it. This is everything prepared for that review.

  • 1 Oct Database map brought up to date: every table grouped, described in one line, with who may see and change it
  • 2 Oct Review pack for the database administrator: the complete database design as a file they can load, plus a factual inventory (sizes, record counts, what depends on what, and which parts are specific to the service the demo runs on)
  • 2 Oct Proof the design works on a standard database: the full design was loaded onto a plain PostgreSQL database, outside the demo's service, and every part came across
  • 6 Oct Review findings: speed, indexing, many people saving at once, and who can see what, all measured on the live demo database, with the questions they raise for the administrator
  • 2-9 Oct Available from the hub: the whole pack downloads as one file, under a "Database review" section; the database diagrams were redrawn so each one is readable
  • 1 Oct Research notes on platform decisions, and a side-by-side comparison of Patrick's architecture review with what is built

Testing and security

  • 14 Oct Automated checks for rule mapping, run as real users: only a VP can approve or reject a link, and nobody can get around that by talking to the database directly
  • 1 Oct Security review and fix: someone with a login who bypassed the app and talked to the database directly could have signed off their own work, signed in someone else's name, or given themselves training they never took. All of that is now blocked by the database itself, and 17 automated checks prove it
  • 1 Oct Automatic scan for leaked passwords and keys in the code, on every change, alongside the existing automatic checks
  • 1 Oct Testing plan for the company code: what is tested today, what is not yet, the biggest gap (no automated tests of the screens themselves), and the order to fix it in
  • 7-13 Oct New automated checks for the training system and for change tracking, run as real users would be
  • 13 Oct A practice database for Novvia: a throwaway copy to test changes on without touching the shared one

Questions from Dan are on the hub's questions page, beside this one in Working documents: type your answer into the box on each question and it is saved for everyone.

Item numbers (#) never change, so an older reference to "#13" still finds the same item. When something finishes, it gets a tick and the date. Tick a box on this page when something is done; ticks are saved for everyone who opens it.

September's feedback (the 9/22 and 9/23 emails, the 9/24 meeting and the 9/25 K+D touchbase) is kept as its own checklist below Phase 1, checked off where done.

Phase When What it is Status
1. Proof of concept and client demo Aug-Sep 2026 The sample data, the working app, the 28 September demo Done
2. Getting ready for Novvia Oct 2026 Sign-in, the company copy of the code, the database with Patrick, the training system, reports with no signal, rule mapping, a tutorial for new users Now. Being built; Patrick has started on the database
3. Going live with Novvia As Novvia commits Novvia's own login, their data, their tablets, controlled releases Built ahead where we can; the Novvia-specific pieces start as each commitment arrives

Phase 2: Getting ready for Novvia, October 2026 (NOW)

Working on now (from 15 Oct)

All of this is Novvia work and all of it is moving. Patrick has begun the database work, and the sign-in, the company copy of the code and the database preparation are being built alongside him.

# Who What Where it stands (15 Oct)
19 Dan Sign-in groundwork (single sign-on): get the design ready so a client's own company login can be switched on quickly once one is chosen The plan is written and was reviewed from four angles, and the first four of seven steps are built: who may sign in, automatic account creation and removal from a client's staff directory, and an admin screen to approve users. Next: PIN sign-in for shared tablets, and keeping the login system swappable, so the choice of provider changes one piece rather than the whole.
25 Dan Training system, next stages: sign in to a class by QR code, sign-off without signal, class sizes and waiting lists, hosting training videos, standard e-learning packages The first stage is live (7-9 Oct); these are the stages after it.
26 Dan Observations and incident reports with no signal: both are kept on the tablet and sent when signal returns, the way the daily vehicle inspection already is, with photos sent separately and retried until they arrive Today both need a connection to save. A report typed with no signal is kept as a draft, but cannot be filed until the tablet is back online.
27 Dan Rule mapping: the rule book, the course catalogue and the corrective actions linked through a list of hazards, every link explained, approved or rejected with a reason, the gaps listed, and tried out on any incident A first working version went up on 14 Oct, on our own hub only, not in the demo. Building on it continues.
43 Dan + Kyle Security audit readiness (SOC 2): everything an auditor will check, done or with a named owner; the list is the SOC 2 readiness page on this hub 29 Oct: of the 75 gaps (seven more found 29 Oct), 17 done, 31 part done, 14 not started and 13 company tasks; of the 36 tasks outside the code, 3 done and 16 part done. Only this repo is assessed, since Novvia will be cloned from it; the sign-in work built earlier in the old Novvia repo is listed as work to port. Waiting on Kyle: a second owner on each company account, switching on three Supabase settings only he can change (MFA required, encrypted connections only, stronger passwords), a password vault, approving the policies, and choosing the audit firm. Also waiting on Kyle: switching off "members can create public repositories" on GitHub. Waiting on decisions (the "Kyle decides" filter lists them all): paying for minute-by-minute database backups, or writing down that up to a day could be lost; keeping logs for 12 months; a compliance platform or a CPA firm directly; where an off-site copy of the database lives
28 Dan Tutorial and onboarding tool: walks a new user through the screens they will use, so they can get started without someone beside them Not started.

From the 23 Oct review: training, driver files, dashboards and sites

In the order we will build them. The guiding rule from the review: keep it simple, and hide detail unless it helps someone act. The training calendar stays as it is.

# Who What Where it stands (23 Oct)
29 Dan Training rules, part 2: each course says whether "annual" means 12 months from the last time it was done, or once every calendar year; settings that contradict each other are refused with a plain explanation. Tested with yearly bloodborne pathogens training for everyone Part done 23 Oct: each course can now be set to "once a calendar year" (due by the end of a chosen month the next year) or "every so many months"; contradictory settings, and two rules giving the same course to the same job at the same site, are refused. Tested with bloodborne pathogens for every employee. Not yet switched on for any course in the demo
30 Dan New hires join the yearly group session: a new hire does their first training soon after starting, then joins the company's next group session instead of running on their own date Built 23 Oct: a course can say "new hires join the next group session"; a new hire's first renewal then moves to the next class booked at their site, at least a set number of months after their first training and never later than it would have been due. Not yet switched on for any course in the demo
31 Dan "Run now" moves to the rules page, for admins only; rules otherwise run by themselves every night Done 23 Oct: Run now is now beside the Course catalog view, for GMs and VPs as before; the Schedule view no longer shows it
32 Dan Booking a class, one way: clicking a count on the calendar and opening a course lead to the same booking screen, with the people due now already ticked and the option to add people due in the next three months. Booked classes show on the supervisor, GM and VP dashboards too Done 23 Oct: every way of scheduling a class opens the same screen, which offers everyone else at that site due within three months of the class. The supervisor, GM and VP dashboards have a Classes list: classes in the next 30 days and who is due with no class, by course or by site
33 Dan Each course marked Regulatory or Company Done 23 Oct: 26 of the 95 courses are marked Regulatory, each with the law that requires it, as our draft until Wes's list arrives; a GM or VP can change any of them. A blue Regulatory label shows in the course list
34 Dan Driver qualification files in three parts: legally required documents (clearly marked), company certifications, and training. Licence and medical card stay here, never on the training calendar Done 23 Oct: the file opens in three parts, Legally required, Certifications and Training, and every line the law requires is labelled Regulatory with the rule. The legal papers that are not cards are in too, as our draft: the job application, the driving record at hire, previous employers' safety history, the yearly driving record review and the yearly drug and alcohol database check. The first three never expire. Wes's list replaces the draft
35 Dan Find a person fast: a search box at the top opens one page per person with their training and their full driver file. The compliance figure on the dashboard opens the list of who is overdue; course pages lose repeated information Done 23 Oct: a People button opens a name search, and a person's file ends with All courses. The Training figure on the dashboard opens on who is overdue (due soon a tap away), and the supervisor's Quals figure opens its expired cards. Course pages say each fact once
36 Dan Watchlist colours: yellow Watch, orange Act now, red Expired, with an explanation when you point at each Done 23 Oct: red Expired (someone whose licence, medical card, certificate or legal record has run out), orange Act now, yellow Watch, each counted once in its worst colour. Pointing at a count says what it means; an "i" beside the tabs explains all four on a tablet
37 Dan People on restricted duty: start and end dates, "X on restrictions" shown under DART next to who is off work (never counted twice), and a reminder every seven days Done 23 Oct: start and end dates on Restricted Work cases, and on Lost Time cases where someone comes back on light duty; "2 on restrictions" under DART for GMs and VPs, never counting anyone who is off work; a weekly "Still on restrictions?" question on the owner's Tasks, answered Back to full duty or Still restricted
38 Dan View as a person: a VP or admin can see exactly what any one person sees, including their reminders, without being able to change anything Done 23 Oct, for the demo: the "View as" tab on the left now has "Anyone…", a name search; picking a person opens the app as them, their own screens and reminders, with a banner saying who. How this would work for a client is decided later
39 Dan Sites page reworked: sections that open and close, and a place for site documents such as environmental permits and safety data sheets, with expiry dates where they have one Done 23 Oct: every section of a site's page opens and closes, and a closed one still says what needs attention. Site documents: safety data sheets, environmental permits and plans (a draft list until Wes's), filed by a supervisor, readable by everyone at the site, with dates; one coming due in 60 days goes on the site manager's Tasks. Rutland and Castleton have sample documents
40 Dan Reading expiry dates from uploaded documents: compare a text-reading-only approach with an AI one, and try both on a few sample cards Done 23 Oct: on six sample cards, reading the text on the tablet got 5 right and left the sixth blank for a person; an AI reader got all 6. Both are good enough to fill the date in for someone to check, neither to decide. Next step, if wanted: try 20-30 real redacted photos from a client. Write-up on the hub
41 Wes Send three lists: the legally required driver-file documents, the site-document categories, and the yearly OSHA reporting requirements Waiting on Wes
42 Dan + others Not building, but tracking: database architecture discussion continues (Dan + Kyle); demo notes to Paul if he still needs them (Dan); Wynn's site-document workflow, only if Wynn becomes an active opportunity; storage and pricing for training videos, raised again at our first client set-up Open

Platform and database, with Patrick

# Who What Where it stands (15 Oct)
18 Dan Move the code to Lucent Axis Two company-owned copies were created on 13 Oct, one for the demo and one as the clean starting point for Novvia (sample data and demo-only features removed). Dan's personal copy and the live demo site keep running until we retire them. Still to do: the demo copy gets its own database and its own web address; switch on the automatic checks and the "no change without review" rule; give Barry and Patrick access.
17 Dan + Kyle Go through the sign-in questions with Kyle: nine for Novvia, two about shared tablets for Novvia IT and Patrick, six for Patrick They are on the hub's questions page (numbers 16 to 32), where the answers go. They feed the last steps of #19.
16 Dan + Patrick Platform decisions Settled: client data will live in a standard enterprise database (Patrick's preference is PostgreSQL on Microsoft Azure), not in the service the demo uses; the code is owned by Lucent Axis (#18). Patrick has begun the database work. Still open: Patrick's final call on the database and login; how new versions are released to each client; importing client data (#22, #23); six questions for Novvia and Patrick.
20 Dan Change tracking on every record: every record shows who created it and who last changed it, and when Built and working in the Novvia copy. In the demo it is written and tested but not switched on, because switching it on changes the live demo database. Already live since September: a full history of every change to an incident. Since 7 Oct: the same for training.
12 Dan Tighten database permissions Half done. On 1 Oct the main fix went in: nobody can get around the app's rules by talking to the database directly. A second layer of the same protection is still to add. Nothing is exposed today.

Phase 3: Going live with Novvia

We build everything we can ahead of time. A few pieces can only finish once Novvia commits, because they need something only Novvia can give us:

  • Their data: the files we bring in (#22, #23)
  • Their architecture: where their copy runs and how it connects to their systems (#10, with Patrick, #16)
  • Their company login: OneLogin or Microsoft Entra, whichever they use (the last steps of #19)
  • Their tablet management: how their IT installs and controls the app on shared tablets
# Who What Why
22 Dan Bring in Novvia's existing data from files, with a second person approving before anything is saved So Novvia does not start empty, and no one person can load bad data alone
23 Dan A report of data that does not fit: anything in Novvia's files we cannot match to the system So nothing is silently dropped on the way in
24 Dan Control what each client gets and when: the demo gets every new feature at once, clients get tested releases So a client never sees an unfinished feature
10 Dan A separate database for each client Keeps each client's data completely apart. The demo getting its own copy (#18) is the first step

Also coming, from the engineering list: testing the offline inspection app on real tablets with no signal; a phone view of the dashboards; and off-road machines (dozers, loaders, compactors) on the vehicle watchlist. There will be no separate incident screen for drivers (decided 14 Oct).


Parked and housekeeping

# Who What Why
13 Dan Re-take the demo's reset point after every database change The demo can be put back to a saved starting point after each run. If the database changes and the reset point is not re-taken, a reset quietly undoes the change. Next due when #20 is switched on.
14 Dan Try Spotter, then decide when it goes in the demo: "Ask" is back as Spotter, for the VP only (built 26 Oct). Sal types a question in plain words, sees the filters it was read as, and gets the same rows Reports would show, or a plain reason why not It is on Sal's dashboard and on the hub's Features tab. It is not in the demo script yet: putting it there is your call. Each client gets it only when chosen. Added 29 Oct: the question box refines the answer on screen, and each "read as" chip can be changed in place (period, sites, values, grouping); an obvious typo is offered back as "Did you mean"; seven questions that read wrong now read right; about 120 everyday words ("who got hurt", "write-ups", "light duty", "circle checks") from the word list you approved; Open in Reports shows only when Reports holds exactly the same rows
7 Dan + Wes Collect ten questions from each of Wes, Paul and Kyle, in their own words, that they would type into Spotter Every real question becomes a test Spotter must pass. The questions log (Spotter, then Questions asked) already collects them as people type.
8 Dan Switch on the AI reader behind Spotter, or keep it off Built and switched off. Off, Spotter still answers everything it can read itself, at no cost. On, it understands more ways of asking. For a client it must run on our own AWS (Bedrock), never on the demo key.
11 Dan Password-protect every client demo, each on its own web address So one prospect cannot find another prospect's branded demo by guessing its address
2 Dan Give Barry access to the code Waiting on Barry's GitHub username.
3 Dan Send Barry the app link So he can look around. The hub is the one address to send.
4 Dan Set Daniel up as a guest in the Lucent Access environment So Daniel can get into the client environment.

Phase 1: Proof of concept and client demo, August-September 2026 (DONE)

The working app, two years of realistic sample data and the 28 September demo. The full list of what was built is in docs/decisions.md.

# Done What
6 28 Sep Chose the examples walked through in the demo, and checked each one is real in the data
15 22 Sep Fixed the injury rate for groups of sites, so a region's rate matches its sites' own rates
12a 18 Sep A Novvia-branded demo site went live, running on the same app and data
9 18 Sep A list of client demos on the hub, visible to our team only
5 10 Sep Dashboard rule decided: every number on a screen comes from real records; nothing is made up to fill a tile

September 2026 feedback: every item from the 9/22-9/25 emails and meetings

Every item from the 9/22 and 9/23 emails, the 9/24 meeting and the 9/25 K+D touchbase, in date order. Status as of 25 Sep 2026, afternoon.

9/22 email: Notes for our call

Driver profile

  • Driver dashboard shows only items expiring or overdue within 90 days (e.g. DOT med card, Professional Driver Series)
  • The four "valid" items no longer show in the driver view
  • The driver sees only upcoming expirations, not the full DQ file. The full file is one link away.
  • DVIR corrective actions (e.g. brakes) are off the driver's task list. His loop closes at the next pre-trip.
  • Fifth profile for maintenance, in its simplest form: Russ Delaney, whose screen is a shop queue. The brake job lands there.
  • Tire pressure entry and tire diagram on the DVIR (next iteration)
  • Sensor data for pressure, heat and tread (noted, not in scope)

Supervisor and GM views

  • Supervisor sees each driver's full DQ file (/dq) and upcoming expirations across their drivers
  • Canned reports tab, role-based (/reports: DQ files, DVIRs, observations, incidents, corrective actions)
  • "How bad was it?" is now "What is the severity?"
  • DVIR input removed for GM and VP. Supervisors keep it.
  • Full DVIR view owned by the maintenance supervisor. The shop queue and dispatch are built. The complete role is still Paul's to define.
  • DVIR and observation actions trace back to the DVIR or observation that raised them
  • Those links also work from the reports tab

Missing role: maintenance supervisor

  • Added to the roadmap. The simplest form is built: Tasks, shop queue, dispatch and sign-off.
  • Full workflow, as Paul brings it in after the demo
  • Maintenance reporting: pull DVIRs and action items by truck, person, date and action

COFI integration and Monday plan

  • COFI rebuilt inside SCOPE on the same live data, and on every build including clients'
  • Observation focus areas filled in from prior observations, telematics and drive cam. Only partly there: telematics already adds Driving Behavior. Confirm the rest with Kyle.
  • Corrective-action module linked to HR policy uploads (V2; don't bring it up Monday)

Minor UI bugs

  • Observation subcategories "only route ride-along has content": checked, and all five types have content. The checklist appears once an employee is picked. The default type also now opens with its focus areas selected.
  • Switching DVIR or observation types warns that inputs will be deleted
  • Observation progress is saved on the device and resumes
  • A list of every observation started but not finished. Partly there: an unfinished observation is now saved on the server and appears on its author's own Tasks list, where it can be reopened or discarded. Nobody else can see it yet.
  • The same for incidents. Same state: an unfinished incident report is on its author's Tasks list, and nobody else can see it yet.
  • Exiting a started DVIR shows a warning

9/22 email: Granola notes for COFI

Global

  • Data sources say "SCOPE synthetic data set", not ERP/ADP/QuickBooks
  • All Cascade Waste references removed. The build fails if one comes back.
  • Site names match SCOPE
  • Lighter, brighter borders on every tile, drill-through pages included
  • All tabs default to January–June 2026
  • At most 2 decimal places; millions formatted the same way everywhere
  • Trend lines on every chart with a month axis
  • Target lines wherever a benchmark or best practice exists. Count charts deliberately have none.

Tab organization

  • Tab order: State of the Business → PRISM → … → Metric Dictionary last
  • Home button and arrow centered; Metric Dictionary header centered

State of the Business

  • "Lifts per hour" gaps fixed. Sites that don't run routes are no longer drawn as empty bars.
  • Red/green arrows on the KPI cards vs the same period last year
  • Safety trend is a stacked bar of recordables and other incidents
  • Months with no data no longer show under the Jan–Jun filter

PRISM

  • Stray scroll bars cleaned up
  • State of the Business fixes applied here too
  • Months with no data fixed here too

P&L

  • Best-practice statement: gross revenue, disposal, net revenue, direct cost, gross profit, indirect cost, EBITDA and key ratios
  • Fill the wasted space; use district slicers to drill in. A District slicer is already on the page (one district = one site in our data), but nothing new fills the space.

Top Customers

  • Top 10 customers by revenue moved under the KPI cards
  • Customer detail table moved to the bottom
  • Customer slicer at the top of the page

Accounts Receivable

  • Outstanding by month is a bar chart stacked by aging bucket
  • District scorecard has aging buckets and a total outstanding column
  • Data checked for sense. It wasn't sensible: bad debt was piling up. Invoices unpaid at 180 days are now written off, and Dan decided to keep that.

Demo prep

  • Happy-path demo flows are in the demo script, starting from the SCOPE/COFI launcher

9/23 email #1: Bugs before Monday

  • Observation default type now opens with its focus areas selected
  • COFI speed on Top Customers and Accounts Receivable: measured on prod. Cold load is 2.7s and a page switch about 0.4s. Dan called it good enough.
  • Top 10 Customers visual resized
  • Back to the previous view on every screen, matching on Novvia and the generic demo
  • DVIR one-click clear ("Start over")

Asked and answered

  • Is the qualification alert tied to the DQ file? Yes. A driver's upload alone doesn't unlock the DVIR. The supervisor's sign-off does, and immediately; tested as the real logins. Note that the demo case is CDL-A: Daniel holds a B and is refused the Transfer Tractors.
  • SCOPE and COFI side by side on the hub landing for Novvia: done, as one card with two buttons
  • Label renames made it in: the owner's list says "To review", and the Tasks rows say "Response received" and "Response overdue"

9/23 email #2: Enhancements outstanding / October

Needed for Monday

  • Back buttons on all drill-through screens
  • Hub landing with SCOPE and COFI
  • One-click DVIR clear

Post-Monday / October

  • Real-time DQ file editing, one at a time and in bulk. One at a time partly exists: a supervisor can file and sign off a document.
  • Supervisor report of everyone on the clock and their hours remaining, in the reports tab
  • Hours remaining taken from payroll
  • DVIR build-out
  • Maintenance supervisor workflow (full version)
  • DQ file form creation
  • Login and user management (scoped in Novvia discovery)

9/24 meeting (all)

  • Reports button is visually distinct: a light tan/beige tint, drawn from each client's own accent color
  • Investigations show relevant history: the truck's DVIRs from the 30 days before the incident and the involved driver's last 3 observations, each opening its record. The incident record and its export carry it too.
  • Opening an investigation from a link scrolls the queue to that case
  • The incident report is one form: tick what happened (injury, vehicle accident, property damage, near miss) instead of choosing one of three paths

Demo walk

  • Reports leaves out the reader's own chain of command, so Kyle's qualification report no longer opens on Kristen and Paul
  • Records opened from Tasks and Reports open in place, so Back works; Reports keeps its filters when you come back
  • The Novvia footer's "no real employee data" stands: Devon is from the synthetic roster
  • A closed investigation says so and offers only Reopen. "Save: still investigating" used to reopen it silently.
  • Request rows read "To (name)" and "asked by (name)", "Show history" replaces "Record", and with nothing open the list folds away
  • The watchlist words your own row to you, and rollup counts say "people beneath them"
  • DQ upload has a real Choose a file button on desktop, and "Send for checking" is now "Send for approval"
  • Investigation queue: search, slicers for incident date, site, reported by, involved person and status; closed incidents load on demand

9/25 K+D touchbase: COFI final pass

Branding and global formatting

  • COFI logo as the main element across the header banner, Lucent Axis Advisors smaller. The logo is lucent-axis.com's own, with "Built by Lucent Axis" beside it as the site draws it, on every page
  • New COFI color palette on every page: every colour COFI draws is one of lucent-axis.com's own hex codes, from one file, and a test fails on any other
  • Every page fits one 1920×1080 screen with no vertical scrolling, State of the Business and P&L included
  • Source reads "Lucent Axis synthetic data set" everywhere
  • Every "i" icon removed for the demo
  • Descenders no longer clipped on the KPI change labels and drill headers
  • "← Back" centered in its box on every drill-through page

Cross-filtering

  • Left-clicking a month, site, cause, service type, line of business, customer type, customer or table row filters the rest of the page
  • The selection is per page and resets when you switch tabs; the top slicers still carry across
  • Top Customers: clicking a customer filters the other visuals on the page

Drill-through model

  • Right-clicking any chart, KPI card or table row offers "Drill through → [detail page]" for what was clicked. Three visuals have no detail page yet and say so: fleet downtime, telematics events by type, and training compliance by course.
  • "Drilled from" names the source page, site, period and clicked value; Back restores the filter you drilled from

Operations drill-through (Route Operations Detail)

  • One row per site, opening onto its routes with route number, regular driver and the existing metrics
  • New miles per route column
  • Reachable from Lifts per Hour and Service Exception Rate. The P&L location views drill to Route P&L Detail, which is also one row per route.

Accounts Receivable

  • "121–180" renamed "121+" everywhere
  • "ageing" spelled "aging" on the AR Invoice Detail page
  • Drilling from the 121+ bucket lists only 121+ invoices, and "Drilled from" shows it
  • AR Invoice Detail otherwise unchanged

PRISM: Corrective Actions card

  • KPIs for Open, Closed, Past due and "Avg days to close"
  • The bar shows only In Progress and Past Due; the large Closed bar is gone
  • Past Due still drills to Corrective Action Detail
  • Leading Indicators trend line left as is

Top Customers

  • Three rows: KPI tiles; Revenue by Month, Service Type, Line of Business, Customer Type; a narrower Top 10 beside the Customer Detail table
  • A top customer drills to its invoices, which shows one big project versus recurring monthly billing

Data realism

  • Per-route volumes by line of business: commercial 70–110 stops, roll-off 5–9 pulls, transfer 3–5 runs, missed pickups as a rate per stop. "Stops per day" is now per route-day, not every route at a site added together (it read 17,665 at Wallingford). Revenue holds within 0.4%.
  • Each route has a regular driver, who drives 92% of its days
  • Routes roll up exactly to the site, and sites to the company totals (a test checks this)

Metric Dictionary

  • Search box

Next pass (after Monday)

  • Right-click drill-through on every KPI and visual to its next level: recordables → incident detail, labor → site / route / driver, revenue → customer → invoice, AR outstanding → customer expandable to invoice, P&L line items → transactions. Partly there: every visual now drills to a detail page, but not yet down to each of these levels.
  • Click a metric to open its Metric Dictionary entry or a definition pop-up, replacing the "i" icons

Technical notes

The detail behind the items above, for whoever does the work.

Technical detail for open items

  • #43 SOC 2 (27-29 Oct): docs/soc2-readiness.md (the board, test compliance-plan.test.mts), docs/compliance/ (drafts, criteria matrix, control calendar, evidence/). Boundary: Lucent Axis accounts only. Code: apps/web/next.config.ts headers and report-only CSP, /api/health, packages/core/src/photo-location.ts, scripts/db/verify_rls.sql, verify_anon.sql, migrations 20261028120000 and 130000, scripts/compliance/. The company database zvxabodonzynkxmcpbji brought current 28 Oct (grants restored after the copy reset them). 29 Oct: app.row_change + report_change_log() (DB-4/LM-2/NP-2, migration 20261029120000), app.legal_hold + report_retention() (DB-6, 20261029130000), anon SELECT revoked outside the hub (DB-1), scripts/security/scan-bundle.mjs in CI (SC-3), scripts/compliance/capacity.sql (AV-5), baseline_check.py + docs/compliance/security-baseline.md (TS-13), machine credentials in access_review.sh (TS-12), packages/core/src/soc2-criteria.ts. DB-4/DB-6 applied to the company database with evidence in docs/compliance/evidence/2026/2026-10-29-change-history-applied.md (commit 4571b98, merged 29 Oct). Spotter's 29 Oct work: 5a07ffc to 0061c27, shipped 29 Oct. docs/safeguards.md and HubDoc.parent on claude/doc-structure-scope-646478.

  • #29 part 1 (23 Oct): 20261023120000_course_renewal_mode.sql, app.course_expiry() / courseExpiry(), verify_rule_timing.sql 13-18. Decisions entry "Once a calendar year".

  • #31-#32 (23 Oct): Run now on the catalog view (apps/web/app/training/page.tsx); dueLater() / loadDueLater() and the Also due list on /training/sessions/new; the dashboard's classes panel (classes-panel.ts in core and apps/web/app/dashboard/). Decisions entry "Run now moves to the catalog".

  • #40 (23 Oct): docs/internal/expiry-reading-evaluation.md; harness scripts/eval/expiry/ (Apple Vision via JXA, no download).

  • #39 (23 Oct): 20261023180000_site_documents.sql, site-documents.ts (core, db), seed_site_documents.mts, verify_site_documents.sql (8).

  • #36-#37 (23 Oct): WatchBand expired, BAND_HELP; 20261023160000_restricted_duty.sql, count_on_restrictions, my_restriction_checkins, verify_restricted_duty.sql (13).

  • #34 papers (23 Oct): 20261023150000_dq_records.sql (Record type, nullable expiry), REQ-031..035 in the generator, scripts/db/load_dq_records.sh (insert-only). Decisions entry "The DQ file's five legal papers".

  • #30 (23 Oct): 20261023130000_new_hire_group_session.sql, app.align_pass(), verify_rule_timing.sql 19-24. Decisions entry "A new hire joins the next group session".

  • #29-#42 (23 Oct review): decisions, schema and verification per phase in docs/internal/build-plan-2026-10-23.md.

  • #18 Move the code: repos lucent-axis/scope (full mirror, history and branches) and lucent-axis/novvia (fresh history; sample data, personas, hub, demo reset and COFI stripped). Remaining: Supabase and Vercel projects for lucent-axis/scope, Actions enabled on the org, branch protection on main. Checklist in docs/internal/platform-and-roadmap-notes.md A2.

  • #19 Client sign-in: docs/sso-access-plan.md (rev 2). Phases 0-3 built in ~/projects/novvia (build switch and database guard, identity and lifecycle, SCIM at /scim/v2, /admin/users); 6 commits not yet pushed to lucent-axis/novvia. Phase 4 (operator PINs) not started; Phase 5 (login adapter) waits on Patrick; Phase 6 (OneLogin guide, end-to-end) waits on 5.

  • #20 Change tracking: branch claude/scope-audit-fields-v1-6bb177, migration 20261015200000_audit_columns.sql over 78 tables, verify_audit_columns.sql (14 checks). Applying it is db push then re-taking the baseline, since demo_reset() refuses a stale one. Live already: incident_event and training_event.

  • #16 Platform decisions: docs/internal/platform-and-roadmap-notes.md A1, A3, B2 and the six questions at its foot.

  • #12 Permissions: 20261001140000_writes_go_through_the_verbs.sql narrowed the POLICIES (scripts/db/verify_raw_writes.sql, 17 checks). The table GRANTS are still Supabase's default grant all. Supabase sets alter default privileges ... grant all on tables to anon, authenticated, service_role at the project level, so every table created after 20260831174347_rls_policies.sql arrived with full insert/update/delete for all three roles. Nothing is reachable: RLS is on everywhere and the only policy an anonymous caller can match is hub_question_answer, open by design. Trace each write path before revoking (observation_item is written by capture_observation, benchmark by the VP, incident_attachment by the upload path), because a blanket revoke is how a working write path disappears silently. Found by verify_operator_gate.sql check 25 on 2026-09-18.

  • #13 Reset point: demo_reset() restores from a snapshot, so a one-time backfill inside a migration is undone by any reset taken before it: training.course_id was wiped exactly this way on 2026-09-18. reseed_reference.sql repairs that one. training_material is not in the reset's table list (it did not exist when the list was derived); the list is derived from the RLS policies and DEFINER writers, so a new table is only picked up if somebody re-derives it.

  • #14 Spotter (docs/ask-v2-plan.md, steps 0-10 done 2026-10-26): an add-on (apps/web/addons/README.md), on for _default by features.spotter, VP only. Into the demo is Act 6's two bullets in docs/demo-script.md, rewritten for Spotter. #7 feeds packages/spotter/test/words.test.mts (81 phrasings today). #8 is SPOTTER_MODEL_PROVIDER=anthropic + ANTHROPIC_API_KEY for the demo; bedrock + SPOTTER_AWS_REGION for any client (roadmap notes A4). Checks: qa_ask.mts, verify_addon_switch.sql, check-removable.mjs.

  • #26 No signal: the remaining half of CLAUDE.md "Next steps" 2. capture_observation and the incident capture RPC go into the IndexedDB outbox beside the DVIR's; each photo is its own retryable job that runs only after its record's item is confirmed, since incident_attachment cannot exist before its incident row. Drafts already persist.

  • #27 Rule mapping: 20261014180000_rule_mapping.sql, verify_rule_mapping.sql, the decisions entry; internal hub only.

  • #22-#25: notes B2 (upload, land raw, map, transform, validate, preview, approve, commit), the gap report, A3 (one main, a features block per tenant), and docs/lms-tier-1-2-plan.md "Deliberately deferred" (pg_cron, LTI 1.3, Tier 3 video, Tier 4 SCORM / xAPI).

  • Done in October, DBA pack: docs/dba/ (schema.sql, inventory.md, prerequisites.sql, review-findings.md), generated by scripts/db/gen_dba_pack.py; loads on PostgreSQL 17 with every object at the live counts (73 tables, 123 functions, 100 policies, 215 indexes). ERD from scripts/db/gen_erd.py. Testing plan docs/internal/testing-plan.md. CI secret scan is the gitleaks binary, not the action, so it works on an org account.

Technical detail for Phase 1

  • #15: rollUp() in packages/core/src/dashboard.ts accumulates each group's own Measured from measuredForSite(); regression test in dashboard.test.mts.
  • #12a: https://scope-novvia.vercel.app, same repo and Supabase, NEXT_PUBLIC_TENANT=novvia. NEXT_PUBLIC_INTERNAL_HUB=1 on scope-safety-poc keeps its hub's four tabs.
  • #9: a fourth /hub tab, compiled away on client builds; see tenants/README.md.
  • The questions list, answerable: /hub/docs/questions-for-client Filters by person, date added and status; an answer box and a Done tick on every row. Answers save to the database and are shared: no sign-in, so anyone with the hub link can type into it and overwrite an answer. Deliberate (2026-09-10); there is no delete grant, so a row can be blanked but never removed. The questions themselves stay in docs/questions-for-client.md and are read at build time.

Driver dashboard KPIs: DECIDED 2026-09-10, option A

Closed, and its PREMISE changed on 2026-09-16; see the note at the end of this section.

Kept here because the reasoning applies to every screen that follows.

The reference tile showed Lifts per hour and Service exceptions. Neither exists in the frozen data set: across all 174 columns in the 19 CSVs the only quantities of that family are odometer_miles, engine_hours and duration_hours. Both are route-productivity metrics that normally live in the hauling system, not a safety platform.

Decision: option A, substitute safety KPIs the data does carry. Dan, 2026-09-10. The same call was made for the supervisor, GM and VP dashboards on the same day and now applies to the whole product: every number on a screen is computed from real rows, and a panel the data cannot back is replaced rather than faked or stubbed. Option D (extend the generator with a route_day entity) stays available if Wes says SCOPE is ever meant to ingest route/ops data (question 9 in questions-for-client.md) but nothing is blocked on the answer.

What that principle already cost, on the three dashboards built 2026-09-10, and what replaced it:

The reference drawing showed Why it could not be built What is there instead
Rolling 12 months, and "vs prior year" deltas The window opens 2026-01-01. There is no twelfth month behind January and no prior year at all Year to date, cumulative. Every axis says YTD, and the cost panel states its window rather than implying a comparison
TRIR 2.14 against a site goal No target column exists in the data. An invented goal is the one number a client could read as a commitment The real rate (4.79 company) against the published NAICS 5621 industry band, labeled "industry"
Near-miss reporting, 147 and 18:1 Near miss is ~2% of events by design: the client's own source system captures almost none, and growing it is a target outcome A leading strip carrying observation coverage, telematics coaching closure and DVIR completion, with the near-miss gap stated out loud
Preventable per million miles No mileage feed per driver; odometer_miles is a point reading on an asset Telematics events by severity band, and what share got coached out
DQ tiles, Vermont site names Not this client's vocabulary or sites Qualification compliance, the ten real sites

AFR came back, on 2026-09-15. It was on the list above as "not this client's vocabulary", and a prospect's dashboard asked for it by name. It is now a column on the sites table and a tile on the KPI row, defined as vehicle accidents per 200,000 exposure hours, the same basis as TRIR, so the two read across one row on one assumption. It is deliberately NOT the trucking figure per million miles: there is no mileage feed, odometer_miles is a point reading on an asset, and an invented denominator is exactly the thing this page exists to refuse. The number carries no color, because no industry band is published for accidents per 200,000 hours; it gains one the moment somebody enters a benchmark. That is the same principle as the rest of this section, not an exception to it: the METRIC is real, the COMPARISON is not invented.

One assumption survives and is printed on the screen next to the number that rests on it: TRIR and DART need exposure hours, there is no clocked-hours feed, so both use headcount x 2,000 hours prorated by days, the same basis scripts/audit.py benchmarks against, which is why the dashboard reproduces the audited rate.

PREMISE CHANGED 2026-09-16: question 9 answered YES

Route and operations data IS meant to come into SCOPE. Option A was decided on the reading that it never would, so the decision now rests on a different foot: the tiles stay as safety KPIs because the route data does not exist yet, not because it never will. The rule underneath it is unchanged and is the part that matters: every number on a screen is computed from real rows, and a panel the data cannot back is replaced rather than faked or stubbed.

The headline consequence is not the driver tiles. It is that EXPOSURE becomes measured instead of assumed. Every rate on the platform (TRIR, DART, AFR) divides by headcount x 2,000 hours prorated to the window, which is an assumption printed beside the number on the dashboard. A route feed carrying start and end times replaces it, and only exposureHours() changes. Miles would also let AFR move to the per-million-miles basis the industry actually publishes, which it cannot use today for want of a mileage feed (odometer_miles is a point reading, not a trip distance).

There is no client and no extract to ask for. Like every other table here it gets MOCKED in the sample data set when we come to it: the stance is that the data exists in a real operation, so the generator should carry it.

Not started, and not to be started casually. It needs a new entity, a generator change and a full regeneration, and the generator's discipline is the hard part: a new random.*() call anywhere in that file shifts every subsequent draw and rewrites the seven LTI narratives, the Castleton decline and TRIR with them. The cost columns solved the same problem by deriving from a sha256 of the incident number rather than the shared stream, and route data would need the same treatment.

Cost: reserve and actual, DECIDED 2026-09-15

The record carried one cost figure and the dashboards called it "estimated cost". It is a RESERVE. What a case finally cost is a different number, exists only once the case is closed, and in this set the two differ by 21% overall and by up to 79% on a single case.

Decision: the generator now carries both, and the dashboards apply a role rule: GM and below see the reserve, VP sees the settled figure with the reserve beneath it, with a per-person override that can hide cost from anyone or grant the settled figure to anyone. This unfroze the data set for the first time since it was called complete; regeneration touched incident.csv and nothing else, and all four suites still report zero.

One thing to say out loud if it is ever asked in a room: the rule is enforced in the view every screen reads through, not in a column grant. A GM's raw API token can still read the settled figure directly. Nothing in the product shows it, and the fix is written down (see the migration header and CLAUDE.md) but it is an app boundary today, not a database one.

Incident statuses: DECIDED 2026-09-15

Four statuses became three: New · Open · Closed.

"Investigation Complete" and "Closed" required identically the same fields of the record, so one was a synonym for the other, and 29% of incidents marked Closed still had open corrective actions, because nothing stopped anyone. The other two were named backwards: "Open" meant nobody had touched it and "Under Investigation" meant somebody had, so the case with an OPEN INVESTIGATION was the one not called Open.

Closing means the investigation is finished, not the follow-up. Corrective actions and training belong to whoever they were assigned to and stay on the supervisor, GM and VP dashboards until somebody completes them: 91 open actions, 56 of them overdue, currently sit on already-closed incidents and every one is visible where it should be. Holding the investigation open to chase them kept a finished investigation open to track somebody else's work.

Closing is now a sign-off. The owner ticks two statements (evidence gathered, corrective action assigned or not needed) and the database records their name and the date. Those two cannot be checked in SQL: there are no attachments in the demo data at all, so requiring evidence would make every incident impossible to close, and 35 incidents legitimately need no corrective action. So the machine checks what it can and records who vouched for the rest.

Worth demoing: open an incident, tick the two boxes, close it, then show the corrective action it raised still sitting overdue on the dashboard. That is the whole argument for the separation in one click.

Observation checklist against the rule book

Done 2026-09-30 (Dan: the rule book is the truth). All 74 lines read the book's own rule (migrations 20260930100000 to 130000). Worth raising with the client rather than fixing: the book grants no general stop-work authority. Its only stop-work rule is a contractor hazard of immediate danger (1.1), so OB-043 now reads "Work paused to ask the supervisor when in doubt", which is the book's nearest rule. If they want stop-work authority on the checklist, it has to go into the book first.

Back to top