Control Plan and inspection workflows 1 to 4. Checked against our architecture, design file and documents. Every section is open. Click any row to see what was tested, what failed and where. Flagged items are listed separately at the bottom.
37% passed overall · 59 tests · 22 pass · 10 partly · 23 fail · 4 not measured
Eight sections. The first four are the review points. The last four are extras.
| Rules | Result | Details | |
|---|---|---|---|
| Frontend calls only the gateway, never an RPC or the database | Pass | RuleThe screens may talk to one gateway file only. They must never call the database or an RPC directly. ResultWe scanned 249 frontend files. None breaks this. | |
| Only Workers talk to the database, only through named functions | Pass | RuleOnly the Workers reach the database, and only by calling a named function. ResultOne place in the code does it, and all 103 functions it calls exist. No raw SQL. | |
| Business logic lives in the Workers; RPCs only read and write rows | Fail | RuleThe business rules (who can approve, which status can change, limits) are written in the Workers. The database functions only save and read data. ResultThe opposite. The rules are in the database: 393 checks in SQL, against 413 lines of rules in the Worker, which only check the request. | |
| Each Worker domain has a rules module that decides the business rules | Fail | RuleEach area (plans, tasks, schedules...) has a rules file in the Worker that holds its business rules. ResultThe rules files exist, but they only check the request (which fields can change, the upload type). The real rules are in the database. | |
| Rules written in two places are kept equal by tests | Fail | RuleIf a rule is written twice (screen and database), a test proves both give the same answer. ResultOnly frequency reading has such a test. Reading pass or fail, the specification reader and the allowed actions have none. | |
| Every side effect goes through the outbox | Pass | RuleEmails, documents and other side effects start only from a saved event, never directly. ResultEvery change saves an audit row and an event in the same step. The tests confirm it. | |
| Tenant keys, forced row-level security, frozen versions | Pass | RuleEach customer’s data is kept apart, rows are locked to the customer, and an approved version cannot change. Result1,165 database tests pass, and 7 of 7 attempts to get around it were refused. |
| Rules | Result | Details | |
|---|---|---|---|
| Design tokens match the design file | Pass | RuleColours and sizes match the design file. ResultThe token file holds the design file’s values (brand blue, navy, greys). | |
| Colours come from named tokens, not typed in | Fail | RuleScreens use named colours from one place, not typed colour codes. Result70 typed colour codes are scattered through the screen files. | |
| Every feature has a Container, a Presenter and a View | Partly | RuleEach feature has three parts: a Container (gets the data), a Presenter (the logic) and a View (what is shown). Result62 views, 44 presenters, 27 containers. 2 of 19 feature folders (lifecycle, revision) have no Container. | |
| Views are display only | Pass | RuleA View only displays. It never fetches data. ResultNo View fetches data or calls the gateway. | |
| Presenters are plain logic | Partly | RuleA Presenter holds the screen logic. Result40 of 44 presenters are React hooks. The guide does not forbid it, but it is not the plain-logic style. | |
| Solid blue list table header, Inter font, no inline styles | Pass | RuleTables have a solid blue header, text is in Inter, and no styles are written inline. ResultAll three are met. | |
| Deviations from the design file are recorded | Pass | RuleAny difference from the design file is written down with a reason. ResultRecorded: red for delete buttons, tinted badges, no logo. | |
| Collapsible sidebar (56 px rail, Ctrl+B) | Fail | RuleThe sidebar collapses to a narrow icon bar, and Ctrl+B toggles it. ResultNot built. | |
| Each screen matched to a design frame | Not measured | RuleEach screen is tied to a frame in the design file. ResultThe tracking table is empty, so it cannot be judged. Screens were not compared by eye. |
| Rules | Result | Details | |
|---|---|---|---|
| Workflows 1 to 4 run end to end through the real API | Pass | RuleWorkflows 1 to 4 work from start to finish through the real system. Result181 and 112 checks ran through the real API and database. None failed on the repeat run. | |
| Import keeps raw text and cell; ambiguous values are never guessed | Pass | RuleImported Excel values keep their original text and cell, and unclear values are never guessed into numbers. Result121 parser tests and the import tests on the Venturi workbook pass. | |
| Workflow 1 step 5: validate before submit | Fail | RuleA plan with missing or unclear data cannot be submitted or approved. ResultOnly 1 rule exists, so incomplete plans can still be approved. | |
| Workflow 5: NC trigger and reaction (C1, C2, C3, MRB) | Fail | RuleA failed inspection starts a reaction: stop, contain, correct, decide what to do with the parts. ResultNot built. A failed result is recorded, but nothing reacts to it. | |
| PDF and Excel output, evidence packs | Fail | RuleThe system produces PDF and Excel documents and evidence packs. ResultNot built. The document service is a placeholder. | |
| PFMEA linking, gauge checks beyond the calibration date | Fail | RulePFMEA is linked to the plan, and gauges are checked for more than their calibration date. ResultNot built. | |
| Functional requirements covered (41) | Partly | RuleAll 41 requirements in the functional requirements document are built. Result15 built, 13 partly built, 13 not built. |
| Rules | Result | Details | |
|---|---|---|---|
| TypeScript strict, zero lint warnings, locked install | Pass | RuleThe code has no type errors and no lint warnings, and installs from the locked versions. Result0 errors and 0 warnings. | |
| No any, ts-ignore, TODO, service_role, hard-coded IDs, inline secrets | Pass | RuleNo shortcuts in the code: no loose types, skipped checks, TODO notes, hard-coded IDs or secrets. ResultNone found. | |
| File size limit (400 code lines) | Pass | RuleA file holds at most 400 lines of code. ResultEnforced by the lint check, and it passes. | |
| Code formatting | Fail | RuleAll files follow one code style. Result2 files are not formatted. 659 more are flagged only because of Windows line endings. | |
| Unit and database tests | Partly | RuleAll tests pass. Result2,671 of 2,679 pass. The 8 failures come from Windows file paths and line endings. 22 database tests also fail on real Postgres because of how the tests are run. | |
| Tests can fail | Pass | RuleRemoving a safety rule must make a test fail. Result106 rules were removed on purpose. 103 were caught, 3 change nothing, and none were real gaps. | |
| Dependencies free of high and critical issues | Fail | RuleLibraries have no high or critical known security issues. Resultreact-router 6.30.6 has 2 moderate issues. vitest 3.2.7 (development only) has 2 critical. | |
| Database list queries page before doing heavy work | Fail | RuleA list query picks the page of rows first, then does the heavy work only for those rows. ResultThe checking-aids list builds the full record for every gauge in the plant, then keeps 200. Fine for a few gauges, slow for thousands. | |
| Database lists have a size limit | Fail | RuleEvery database list is paged, so one answer never carries every row. ResultThe plant gauge list has no limit and returns every gauge at once. The process flow list was not checked. | |
| Screen lists let users reach every item | Fail | RuleA list screen lets the user reach every item, with page controls or load more. ResultTasks, schedules, production and inspection plans load 200 items and have no page controls. Item 201 onward cannot be reached. Only the plans list pages. | |
| Queue producers exist for every queue events can use | Partly | RuleEvery queue that an event can be routed to is connected to the Worker that sends to it. ResultOnly the events queue is connected. All events use it today, so nothing fails yet. Notification and document queues are not connected, and the notification routing list is empty. | |
| Database functions list their columns (no SELECT *) | Partly | RuleDatabase functions name the columns they read instead of using SELECT *. Result154 uses of SELECT *. Safe when filling one whole row variable, risky when filling separate variables. The ban comes from the Calispec checklist, not from our CLAUDE.md. | |
| Row locks are taken in a fixed order | Partly | RuleWhen a function locks several rows, it locks them in a fixed order so two users cannot block each other. ResultThe 3 multi-row lock loops we found are ordered. The other 54 lock statements were not reviewed. The NC code named in the audit is not in this repo. | |
| Bulk save keeps valid rows when one row is stale | Partly | RuleSaving many rows saves the valid ones even if one row is out of date. ResultIt is all or nothing by design. If one row is stale nothing is saved, but every row is reported with its conflict and changed fields. | |
| Part number and revision are upper-cased as typed | Partly | RuleFree-text codes such as part number and revision are turned into capitals as the user types. ResultThe create-plan form does not do it. The rule is written for Standards Room forms, and it is not clear that Control Plan counts. |
| Rules | Result | Details | |
|---|---|---|---|
| Direct database bypass attempts | Pass | RuleA browser that skips the API and calls the database directly is refused. Result7 of 7 attempts were refused. | |
| Secrets in the repo and its history | Pass | RuleNo keys or passwords anywhere in the code history. ResultNone found in all 262 commits. | |
| Every callable database function checks caller, tenant and plant | Pass | RuleEvery database function the API calls checks who is asking, which customer and which plant. Result139 functions checked. None left unguarded. | |
| Task tables writable only through named functions | Partly | RuleTask data can be changed only through the named functions. ResultThe API role still has direct write rights, held back only by a hidden setting. The API cannot reach that setting. | |
| Production login and token proof on hosted Supabase | Fail | RuleUsers sign in through a real login system, and the database token works on the hosted setup. ResultNo production login system yet. The token has not been tried on hosted Supabase. | |
| Customer separation does not trust the API | Fail | RuleThe database does not simply trust the customer that the API names. ResultIt does trust it. All customers share one database. | |
| Security headers (CSP) on the app | Not measured | RuleThe app sends security headers. ResultNo headers setting found. Needs a check on a hosted setup. |
| Rules | Result | Details | |
|---|---|---|---|
| Acceptance criteria have a passing proof recorded | Fail | RuleEach acceptance criterion is marked passing, with the test that proves it. Result9 criteria: 0 passing, 1 partly, 6 pending, 2 deferred. | |
| The proving test files named in the table exist | Fail | RuleThe test files named in the acceptance table exist. ResultThey do not. The e2e folder holds only a README, and Playwright is not installed. | |
| Appendix D tests (positive, negative, cross-tenant, bypass, immutability, separation of duties) | Pass | RuleEach slice has six standard tests: positive, negative, cross-customer, bypass, frozen version, separation of duties. Result65 of 86 database test files carry the tag. |
| Rules | Result | Details | |
|---|---|---|---|
| Accessibility lint rules active | Pass | RuleThe code is checked for accessibility mistakes automatically. ResultThe check is on, with 405 aria and role attributes and 23 focus styles in the app. | |
| Automated accessibility test | Fail | RuleAn automated test checks the screens for accessibility problems. ResultNone in the repo. | |
| Dates and numbers through the shared hooks | Pass | RuleDates and numbers are formatted by shared helpers, not typed into screens. ResultNo direct date or number formatting inside the screens. | |
| Empty values show an em dash | Pass | RuleAn empty value shows a dash. ResultUsed in 42 places. | |
| Contrast and keyboard use on real screens | Not measured | RuleText is easy to read and every action works with the keyboard. ResultNot measured. Needs a run in a browser. |
| Rules | Result | Details | |
|---|---|---|---|
| Performance budgets measured (DDD p.56) | Fail | RuleSpeed targets are measured, for example opening a 500-line plan in under 3 seconds. ResultThe targets are written but never measured. The test data generator is missing. | |
| Plan approval time | Fail | RuleApproving a plan finishes inside the database time limit (8 seconds). ResultOnce it took 7.8 seconds and was cancelled. | |
| CI/CD pipeline | Fail | RuleEvery change is built and tested automatically before it can be merged. ResultNo pipeline. The workflows folder holds only a README. | |
| Workers deployed and reachable | Fail | RuleThe Workers run on Cloudflare. ResultNot deployed. They ran only on this machine. | |
| Correlation ID and audit trail | Pass | RuleEach request has an ID, and every change is logged. ResultBoth are in place. | |
| Rate limits and real queue behaviour | Not measured | RuleToo many calls are refused, and queues retry failed messages. ResultNot measured. Dev limits are raised and queues are simulated. |
33 items failed or only partly passed: 13 high, 15 medium, 5 low. High means it blocks production, breaks the Workers-first rule, or hides or slows real data.
| Flag | Owner | Details | What to do | |
|---|---|---|---|---|
| Business logic lives in the Workers; RPCs only read and write rowsArchitecture | Decision, then rework · V-12 | RuleThe business rules (who can approve, which status can change, limits) are written in the Workers. The database functions only save and read data. ResultThe opposite. The rules are in the database: 393 checks in SQL, against 413 lines of rules in the Worker, which only check the request. | Decide where rules live. If the Workers must hold them, the live-data rules move out of SQL: most of about 22,200 lines and the 1,165 database tests are affected. If SQL stays, record that decision in docs/decisions. | |
| Each Worker domain has a rules module that decides the business rulesArchitecture | Follows the decision above · V-12 | RuleEach area (plans, tasks, schedules...) has a rules file in the Worker that holds its business rules. ResultThe rules files exist, but they only check the request (which fields can change, the upload type). The real rules are in the database. | The rule files hold only request rules today. They grow only if the decision above moves rules into the Workers. | |
| Workflow 1 step 5: validate before submitFunctionality | Later slice | RuleA plan with missing or unclear data cannot be submitted or approved. ResultOnly 1 rule exists, so incomplete plans can still be approved. | Build the validation engine and its rules, so incomplete plans cannot be approved. | |
| Database list queries page before doing heavy workCode quality | Developer | RuleA list query picks the page of rows first, then does the heavy work only for those rows. ResultThe checking-aids list builds the full record for every gauge in the plant, then keeps 200. Fine for a few gauges, slow for thousands. | Filter and page the gauge ids first, then build the full record only for that page. The "anomalous" filter needs the computed record, so it has to be handled separately. | |
| Database lists have a size limitCode quality | Developer | RuleEvery database list is paged, so one answer never carries every row. ResultThe plant gauge list has no limit and returns every gauge at once. The process flow list was not checked. | Add page parameters to get_cp_plant_gauges, and check get_cp_process_flow. | |
| Screen lists let users reach every itemCode quality | Developer | RuleA list screen lets the user reach every item, with page controls or load more. ResultTasks, schedules, production and inspection plans load 200 items and have no page controls. Item 201 onward cannot be reached. Only the plans list pages. | Add page controls (or load more) to the task, schedule, production and inspection plan lists. | |
| Queue producers exist for every queue events can useCode quality | Developer | RuleEvery queue that an event can be routed to is connected to the Worker that sends to it. ResultOnly the events queue is connected. All events use it today, so nothing fails yet. Notification and document queues are not connected, and the notification routing list is empty. | Connect the notification and document queues in producersFrom and fill NOTIFICATION_ROUTES before any event routes to them. | |
| Row locks are taken in a fixed orderCode quality | Developer | RuleWhen a function locks several rows, it locks them in a fixed order so two users cannot block each other. ResultThe 3 multi-row lock loops we found are ordered. The other 54 lock statements were not reviewed. The NC code named in the audit is not in this repo. | Review the other FOR UPDATE statements for a fixed order, and re-check once the NC migrations are in this repo. | |
| Part number and revision are upper-cased as typedCode quality | Decision | RuleFree-text codes such as part number and revision are turned into capitals as the user types. ResultThe create-plan form does not do it. The rule is written for Standards Room forms, and it is not clear that Control Plan counts. | Decide whether Control Plan forms must upper-case free text. If yes, upper-case the part number and revision fields. | |
| Production login and token proof on hosted SupabaseSecurity | Decision, then developer · V-01, V-02 | RuleUsers sign in through a real login system, and the database token works on the hosted setup. ResultNo production login system yet. The token has not been tried on hosted Supabase. | Choose the identity provider. Prove the token on hosted dev with a dedicated rotating key. | |
| Customer separation does not trust the APISecurity | CTO decision · V-04 | RuleThe database does not simply trust the customer that the API names. ResultIt does trust it. All customers share one database. | Record written acceptance of the shared-database design. | |
| CI/CD pipelineOperations | Developer · V-03 | RuleEvery change is built and tested automatically before it can be merged. ResultNo pipeline. The workflows folder holds only a README. | Build the pull-request pipeline, then deploy and smoke test. | |
| Workers deployed and reachableOperations | Developer and owner · T18 | RuleThe Workers run on Cloudflare. ResultNot deployed. They ran only on this machine. | Set up hosted dev and deploy the four Workers. |
| Flag | Owner | Details | What to do | |
|---|---|---|---|---|
| Rules written in two places are kept equal by testsArchitecture | Developer · V-10 | RuleIf a rule is written twice (screen and database), a test proves both give the same answer. ResultOnly frequency reading has such a test. Reading pass or fail, the specification reader and the allowed actions have none. | Add three parity tests (reading evaluation, specification parser, allowed-action tables). | |
| Colours come from named tokens, not typed inDesign | Developer | RuleScreens use named colours from one place, not typed colour codes. Result70 typed colour codes are scattered through the screen files. | Replace the 70 hex values in components with named tokens from tokens.css. | |
| Collapsible sidebar (56 px rail, Ctrl+B)Design | Developer | RuleThe sidebar collapses to a narrow icon bar, and Ctrl+B toggles it. ResultNot built. | Build the 56 px rail and the Ctrl+B toggle from the design file. | |
| Workflow 5: NC trigger and reaction (C1, C2, C3, MRB)Functionality | Later slice · T26 | RuleA failed inspection starts a reaction: stop, contain, correct, decide what to do with the parts. ResultNot built. A failed result is recorded, but nothing reacts to it. | Build the failure and reaction workflow. | |
| PDF and Excel output, evidence packsFunctionality | Later slice | RuleThe system produces PDF and Excel documents and evidence packs. ResultNot built. The document service is a placeholder. | Build document-api rendering, the documents queue and bucket. | |
| Functional requirements covered (41)Functionality | Later slice | RuleAll 41 requirements in the functional requirements document are built. Result15 built, 13 partly built, 13 not built. | Finish the 13 partly built and the 13 unbuilt requirements. | |
| Unit and database testsCode quality | Developer · V-07, V-08 | RuleAll tests pass. Result2,671 of 2,679 pass. The 8 failures come from Windows file paths and line endings. 22 database tests also fail on real Postgres because of how the tests are run. | Fix Windows paths and line endings. Make the database tests safe on real Postgres. | |
| Dependencies free of high and critical issuesCode quality | Developer · V-06 | RuleLibraries have no high or critical known security issues. Resultreact-router 6.30.6 has 2 moderate issues. vitest 3.2.7 (development only) has 2 critical. | Upgrade react-router to 7.18 or newer and vitest to 4.1.11 or newer. | |
| Bulk save keeps valid rows when one row is staleCode quality | Decision | RuleSaving many rows saves the valid ones even if one row is out of date. ResultIt is all or nothing by design. If one row is stale nothing is saved, but every row is reported with its conflict and changed fields. | Decide whether all-or-nothing is the intended behaviour for the grid save, and record it in docs/decisions. | |
| Task tables writable only through named functionsSecurity | Developer · V-05 | RuleTask data can be changed only through the named functions. ResultThe API role still has direct write rights, held back only by a hidden setting. The API cannot reach that setting. | Remove the direct write rights on the task tables (task T34). | |
| Acceptance criteria have a passing proof recordedTraceability | Developer | RuleEach acceptance criterion is marked passing, with the test that proves it. Result9 criteria: 0 passing, 1 partly, 6 pending, 2 deferred. | Update the acceptance table as each criterion passes, with the proving test file. | |
| The proving test files named in the table existTraceability | Developer | RuleThe test files named in the acceptance table exist. ResultThey do not. The e2e folder holds only a README, and Playwright is not installed. | Write the e2e specs the table names and install Playwright, or correct the table. | |
| Automated accessibility testAccessibility | Developer | RuleAn automated test checks the screens for accessibility problems. ResultNone in the repo. | Add axe-based tests for the main screens. | |
| Performance budgets measured (DDD p.56)Operations | Developer | RuleSpeed targets are measured, for example opening a 500-line plan in under 3 seconds. ResultThe targets are written but never measured. The test data generator is missing. | Write the synthetic-plan generator and measure the budgets. | |
| Plan approval timeOperations | Developer · V-09 | RuleApproving a plan finishes inside the database time limit (8 seconds). ResultOnce it took 7.8 seconds and was cancelled. | Measure approval on large plans and set an explicit database time limit. |
| Flag | Owner | Details | What to do | |
|---|---|---|---|---|
| Every feature has a Container, a Presenter and a ViewDesign | Developer | RuleEach feature has three parts: a Container (gets the data), a Presenter (the logic) and a View (what is shown). Result62 views, 44 presenters, 27 containers. 2 of 19 feature folders (lifecycle, revision) have no Container. | Add a Container to the lifecycle and revision folders, or change the frontend guide. | |
| Presenters are plain logicDesign | Decision | RuleA Presenter holds the screen logic. Result40 of 44 presenters are React hooks. The guide does not forbid it, but it is not the plain-logic style. | Confirm that hook-style presenters are accepted, and write it into the frontend guide. | |
| PFMEA linking, gauge checks beyond the calibration dateFunctionality | Later slice | RulePFMEA is linked to the plan, and gauges are checked for more than their calibration date. ResultNot built. | Build PFMEA linking and the gauge fitness (MSA) check. | |
| Code formattingCode quality | Developer · V-07 | RuleAll files follow one code style. Result2 files are not formatted. 659 more are flagged only because of Windows line endings. | Run prettier on 2 files and add .gitattributes. | |
| Database functions list their columns (no SELECT *)Code quality | Developer | RuleDatabase functions name the columns they read instead of using SELECT *. Result154 uses of SELECT *. Safe when filling one whole row variable, risky when filling separate variables. The ban comes from the Calispec checklist, not from our CLAUDE.md. | Replace select * with column lists where it fills separate variables. Decide whether the ban applies to whole row variables. |
| Item | Why |
|---|---|
| Each screen matched to a design frameDesign | docs/design-coverage.md is an empty table, so no screen is tied to a design frame. |
| Security headers (CSP) on the appSecurity | No security headers file found. Needs a check on a hosted environment. |
| Contrast and keyboard use on real screensAccessibility | Needs a run in a browser. |
| Rate limits and real queue behaviourOperations | Dev limits are raised and queues are simulated locally. |
Checked on 15 Oct 2026 at commit 44bde70. Test suites ran on 13 Oct 2026. The code has not changed since.