Commit Graph

4 Commits

Author SHA1 Message Date
mineracks
d7dd748fe4 #5 SH1E Pi-side decoder + fuzz harness
Two pieces required before any real-device release ships:

(1) cmd/sh1e-decode — a Pi-side CLI that validates and pretty-prints
    an SH1E envelope. Reads from stdin, a file, or a hex string
    (`-hex "53 48 31 45 ..."`, spaces/colons/pipes stripped so you
    can paste straight from the composer's hex dump pane).

    Output: ACCEPT line with byte count + fingerprint, then per-block
    summaries (plate type, every text block's font/size/anchor/align/
    rotation/content, every SVG path's anchor/scale/rotation/d-string).
    On rejection: REJECT <TAG>: <error> where TAG is a stable label
    matching the sentinel error name — easy to grep in CI fuzz runs.

    Run it like:
      sh1e-decode some-design.sh1e
      sh1e-decode < piped-stdin
      sh1e-decode -hex "53 48 31 45 01 4f 00 ..."

(2) engrave/wire/sh1e/fuzz_test.go — native Go 1.18+ fuzz harness for
    Decode and a faster envelope-only variant.

    Property: any input must either return a valid Design that
    round-trips through Encode to byte-identical output (canonical
    encoding) OR return a non-nil error. A panic, hang, or
    out-of-memory is a test failure — the Pi controller runs this
    parser on untrusted QR-scanned bytes and a crash there is a
    real-world fault.

    Seed corpus: valid envelopes from the existing tests +
    deliberately corrupted variants (length-field flipped, payload
    byte flipped) + obvious shape attacks (empty, wrong magic, wrong
    version, mostly-FF spam).

    Smoke-tested for 5 seconds → 0 crashes, 933k execs/sec, 60 new
    interesting inputs discovered, 72 corpus entries. Spec calls for
    1 CPU-week before any release ships; CI runs a shorter window
    per merge.

    Run with:
      go test -fuzz=FuzzDecode -fuzztime=10m ./engrave/wire/sh1e
      go test -fuzz=FuzzDecodeEnvelopeOnly -fuzztime=10m ./engrave/wire/sh1e

Plus a CRC-stdlib drift smoke test guarding against a future
dependency swap quietly changing the CRC table.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:41:34 +10:00
mineracks
9b3a3bba21 SH1E v0.1 reference encoder + decoder + tests
The new code we're adding ourselves — the envelope format that ships
plate designs from the browser-side composer to a Pi controller.
Full spec at docs/architecture/sh1e-spec.md.

Implementation:

  engrave/wire/sh1e/sh1e.go (~325 lines)

  - Envelope: 4-byte magic "SH1E" + 1-byte version + 2-byte LE
    payload_len + 4-byte LE CRC32-IEEE + N-byte CBOR payload.
    11-byte overhead. uint16 length cap = 65535-byte payload.
  - Public types: Design, TextBlock, SvgPath, PlateType (Small/
    Square/Large), FontID (Comfortaa/Poppins/Constant), Alignment
    (Left/Center/Right).
  - Encode(d Design) -> []byte: validates, computes the SHA-256
    design fingerprint over fields 1-3, canonical-CBOR encodes
    the whole Design (with fingerprint as field 4), wraps in
    envelope. Same Design always produces byte-identical output.
  - Decode([]byte) -> Design: header check, length check, CRC
    check, CBOR unmarshal, canonical-encoding round-trip check
    (re-encodes the decoded value and compares bytes — catches
    non-canonical input), structural validation, fingerprint
    recomputation + match.
  - Sentinel errors for every rejection mode (errors.Is-friendly):
    ErrBadMagic, ErrUnsupportedVersion, ErrLengthMismatch,
    ErrCRCMismatch, ErrBadCBOR, ErrNotCanonical, ErrTruncated,
    ErrFingerprintMismatch, ErrPayloadTooLarge, ErrTooManyBlocks,
    ErrTooManyPaths, ErrTextTooLong, ErrPathTooLong, ErrNonASCII,
    ErrInvalidEnum, ErrOutOfRange, ErrInvalidRotation.

  engrave/wire/sh1e/sh1e_test.go (~270 lines)

  - Round-trip: minimal design + design-with-logo.
  - Stability: same input -> byte-identical output across encodes.
  - Fingerprint independence: encoder overwrites caller-supplied
    Fingerprint with the recomputed one.
  - Envelope rejections: truncated, bad magic, wrong version,
    length-mismatch, corrupted CRC, fingerprint mismatch (forged
    payload with valid CRC).
  - Validation rejections: bad plate type, bad font ID, font size
    out of range, text too long, non-ASCII text, too many blocks,
    too many paths, path too long, bad alignment, bad rotation,
    bad scale percent.

All 17 test packages green. Strict-subset SVG path validator (M/L/
H/V/Q/C/Z only, no arcs / S / T) deliberately deferred to live
alongside the path renderer in a later commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 18:51:16 +10:00
mineracks
9261cf368a Lift composer substrate from upstream v1.3.0
Twelve packages lifted from seedhammer/seedhammer @ v1.3.0
(commit 2f071c1d8f23eb7fd39b15fc0acb8874113f801e):

  address/     — bitcoin address parsing
  backup/      — v1 plate dimensions + UR-coded multi-plate backup
  bc/          — Blockchain Commons: ur, fountain, bytewords, urtypes,
                 xoshiro256 (5 subpkgs)
  bip32/       — HD-key derivation
  bip39/       — mnemonic seed phrases + 2048-word wordlist
  engrave/     — text/QR → MoveTo/LineTo command stream conversion
  seedqr/      — SeedQR / CompactSeedQR encoders
  image/       — paletted, rgb565, alpha4, ninepatch image formats
  nonstandard/ — bitcoin descriptor + script parsing
  font/        — bitmap + vector font runtime
  font/{comfortaa,poppins,constant,bitmap,vector}/  — actual fonts
  driver/mjolnir/  — MarkingWay USB-serial engraver driver

Plus an earlier-aside backup_test.go restored (its deps are now lifted).

Import paths globally rewritten seedhammer.com → mineracks namespace
via single sed pass; verified no orphan refs remain. go.mod adopts
upstream's full dep set plus the replace-directive for the patched
kortschak/qr fork.

  go build ./...     clean (all 27 packages)
  go test ./...      clean (12 packages with tests, all passing)

NOT lifted in this commit:
  - driver/{wshat,drm,libcamera}  (hardware-specific GPIO/LCD/camera —
    will be platform-v1/-shaped abstractions instead)
  - gui/                (depends on the above; lifts in Phase 2)
  - cmd/{controller,...} (Pi binary entrypoints — not needed for the
    companion repo)
  - zbar/               (QR scanner — needs libcamera)

Next:
  - Write the SH1E reference encoder/decoder in engrave/wire/sh1e/
  - Lift Gangleri42's cmd/webnfc/ shell + retune to v1 plates
  - First buildable composer WASM with a working preview

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 18:36:40 +10:00
mineracks
3696dd6b34 Initial skeleton — Phase 1 scaffolding
A browser-based companion for SeedHammer v1 hardware. Three coordinated
PWAs (composer, emulator, combined-sim) plus an optional Android wrapper,
inspired by Gangleri42's SeedHammer II fork but retargeted to v1's
Pi-Zero / WaveShare / MarkingWay hardware.

What's in this commit:

- LICENSE: Unlicense (matching upstream)
- README.md: project overview + status + roadmap
- CREDITS.md: upstream provenance + pinned baseline SHAs
- docs/architecture/: five authoritative design docs (lifted from
  the prep work in mineracks-infrastructure):
  * BASELINES.md — pinned SHAs, license audit, path-mapping table
  * v1-engrave-spec.md — MarkingWay USB-serial wire protocol audit
  * v1-buttons-and-ui.md — GPIO map, UI screen flow, keyboard map
  * sh1e-spec.md — composer-to-Pi envelope format spec
  * seedsigner-reuse.md — Pyodide strategy + jumbo (SeedSigner+) support
- Go package skeleton with doc.go contracts:
  backup, bezier, bspline, engrave, engrave/wire, engrave/wire/sh1e,
  font (+ comfortaa, poppins, constant), gui, input, internal/golden,
  platform/v1
- cmd/ entrypoints with stub main(): composer, emulator, combined-sim,
  seedsigner-sim
- web/ static-shell skeleton
- go.mod (module github.com/mineracks/seedhammer-v1-companion, Go 1.22)
- go build ./... + go vet ./... both clean

Next: lift universal packages (backup, font, bezier, bspline) from
upstream seedhammer/seedhammer at v1.3.0 verbatim.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 18:25:03 +10:00