The Standard no-login CMS path needs an ORIGINAL ink signature on paper (CMS-10114: 'Stamped, faxed or copied signatures will not be accepted'). This adds a pipeline to redraw the provider's own captured strokes in real ink with a pen on a CR-10 V2 (or any Marlin/GRBL machine) — original, in ink, never copied. - migration 090: esign_records.signature_vector (JSONB stroke paths, 0..1). - signing page now captures normalized stroke paths alongside the PNG; API stores a size-bounded vector for drawn signatures. - ink_signature_plotter.py (hardware-independent): fit strokes to the signature anchor box, PDF-pt -> bed-mm via jig offset, emit Marlin/GRBL G-code (Z pen or M280 servo/BLTouch), SVG toolpath preview, and render_signature_on_pdf (a digital twin that proves the toolpath lands on the cert line). Gated serial sender (dry_run default). - ink_signature_cli.py: end-to-end load-record -> gcode+preview, --test-box jig calibration, --plot to stream over USB. - Corrected CMS-10114 signature anchor to sit inside the Section 4A signing cell (above the bottom rule, below the label). - docs/ink-signature-plotter.md documents the CR-10 retrofit + interpretive risk. Tests: test_ink_signature.py 30/30, test_cms10114.py 27/27, test_paper_batch.py 15/15, API tsc clean, Astro build 58 pages.
29 lines
1.5 KiB
SQL
29 lines
1.5 KiB
SQL
-- 090: Capture the vector (stroke-path) form of a drawn signature.
|
|
--
|
|
-- Today esign_records.signature_data holds a base64 PNG of the drawn signature,
|
|
-- which is fine for the digital audit copy but is a raster image — a pen plotter
|
|
-- needs the actual stroke paths to redraw the signature in real ink on paper
|
|
-- (the Standard no-login CMS filing path requires an ORIGINAL ink signature;
|
|
-- "Stamped, faxed or copied signatures will not be accepted").
|
|
--
|
|
-- We store the captured strokes as JSON so the same signing event yields both:
|
|
-- * signature_data — base64 PNG (digital stamp, audit trail)
|
|
-- * signature_vector — stroke paths (drives the pen plotter)
|
|
--
|
|
-- Format (normalized into a 0..1 box, origin top-left, matching canvas capture):
|
|
-- {
|
|
-- "v": 1,
|
|
-- "w": <canvas css width px>, "h": <canvas css height px>,
|
|
-- "strokes": [ [ {"x":0.12,"y":0.40,"t":12}, ... ], ... ]
|
|
-- }
|
|
-- x/y are fractions of the capture box (resolution-independent); t is ms since
|
|
-- stroke start (optional, for future pressure/speed modeling). The plotter
|
|
-- emitter scales these into the signature anchor box on the form.
|
|
|
|
ALTER TABLE esign_records
|
|
ADD COLUMN IF NOT EXISTS signature_vector JSONB;
|
|
|
|
COMMENT ON COLUMN esign_records.signature_vector IS
|
|
'Stroke-path form of a drawn signature (normalized 0..1, origin top-left). '
|
|
'Drives the pen-plotter ink-signature pipeline. NULL for typed signatures '
|
|
'or signatures captured before this column existed.';
|