Phase 7: close, file, PDFs and prints
ci / frontend (push) Successful in 40s
ci / server (push) Successful in 10m56s
ci / image (push) Successful in 48s
ci / e2e (push) Successful in 2m44s

Clerical close and file: the VISUAL observed state beside the close confirm, a 409 with a second confirm when the
feed still shows work orders open, filing with a signature and the HMAC seal, the data book built on the server
and stored on the seal in the filing transaction, admin reopen keeping the broken seal with its data book.

Server PDFs with reportlab, pypdf and pypdfium2: the manufacturing data book page for page after the old build
(cover, index, drawings with VOID stamps, traceability and heat map rasters, weld maps and welding records, Q.C.
inspections, Q.C. and test documents, MTRs, record history), the job traveler with work order QR codes, the ITP
PDF filed automatically at sign-off, every print kind with the PRINTED COPY stamp, the controlled-copy stamp
signed with the seal key, PDF metadata, the traceability CSV with the formula guard, and the append-only
print_log with an audit row for every print and export (migration 0008).

Frontend: the close and file panel, the print menu and its entry points, the printed copies list on the History
tab, the ITP PDF buttons. Tests: server (close, file, reopen, seal, the builders, prints, CSV, stamps), frontend,
and the Playwright close and print scenarios. Docs updated; SECURITY closes M2, S6, S7 and S8.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
2026-10-17 23:49:14 -06:00
co-authored by Claude Fable 5.1
parent 00531cb329
commit 904437153d
59 changed files with 8226 additions and 136 deletions
@@ -0,0 +1,43 @@
-- Phase 7: close, file, PDFs and prints.
-- Every printed copy and every export, append-only. Who, when, what and how many pages.
CREATE TABLE print_log (
id bigserial PRIMARY KEY,
at timestamptz NOT NULL DEFAULT now(),
by uuid REFERENCES users (id),
by_name text,
session_id uuid,
packet_id bigint REFERENCES packets (id),
unit_id bigint REFERENCES units (id),
itp_id bigint REFERENCES itps (id),
-- traveler, map-h, map-w, clean, void, databook, doc, itp, csv, databook-export, itp-pdf
kind text NOT NULL,
-- the human label: "Job traveler", "Drawing with heat map (sheet 2)", "MTR - item 3"
what text NOT NULL,
pages int,
-- the document printed, for kind doc; the filed data book for databook
asset_id uuid REFERENCES assets (id),
-- the stamp line as printed, and the 16 hex characters signed into it
stamp text,
stamp_sig text,
ip text
);
CREATE INDEX print_log_packet ON print_log (packet_id, id);
CREATE INDEX print_log_itp ON print_log (itp_id, id);
CREATE TRIGGER print_log_append_only
BEFORE UPDATE OR DELETE ON print_log
FOR EACH ROW EXECUTE FUNCTION ps_append_only();
CREATE TRIGGER print_log_no_truncate
BEFORE TRUNCATE ON print_log
FOR EACH STATEMENT EXECUTE FUNCTION ps_append_only();
-- Explicit, after the default privileges: the app may only read and append the print log.
REVOKE UPDATE, DELETE, TRUNCATE ON print_log FROM ps_app;
GRANT SELECT, INSERT ON print_log TO ps_app;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO ps_app;
-- The data book filed with a seal, and the work orders the feed still showed open at filing.
ALTER TABLE packet_seals ADD COLUMN databook_asset_id uuid REFERENCES assets (id);
ALTER TABLE packet_seals ADD COLUMN databook_pages int;
ALTER TABLE packet_seals ADD COLUMN open_wos text[];