feat: smart-place auto QR placement + &p= page tags + document-payload verify [HELD FOR MIKE'S GO] - #21
Merged
Merged
Conversation
…oad verify
- placement: "auto" for sealDocument via shared byte-identical contract
(src/smartPlace.ts chooseClearRect + src/pdfObstacles.ts extraction);
pdfjs-dist as OPTIONAL peer, all computed locally (blindness preserved)
- multi-page allPages seals stamp per-page &p= display-only page tags
(after ?t/&m, before #key); result gains pageVerifyUrls; buildVerifyUrl
gains page, embedQr gains pageTag
- sealed metadata discloses page_count (caller-supplied field wins)
- verifyIntent/verifySplitKeyIntent: document payloads (raw stamped file
bytes + file metadata on the intent) return payloadKind "document" with
{contentType, byteSize, declaredByteSize, sha256} instead of
invalid_payload; JSON payloads unchanged
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
HELD FOR MIKE'S GO — do not merge without explicit approval
Smart-place (Mike-approved) + two approved scope additions (page tags, document-payload verify). One of THREE cross-linked PRs plus a keyhalve-website display PR — links below.
1. Smart-place:
placement: "auto"forsealDocumentAutomatic clear-space QR placement, computed locally — the page content never leaves the process (blindness preserved). Shared contract, BYTE-IDENTICAL across the three ValidPay repos:
src/smartPlace.ts4e6c53fed872ccbd0a1bf675fda6928024cfc10606892b507276334719ead91bsrc/pdfObstacles.ts868e1e7e4ca30629800afb641da97818c3696c3567fa72661490fde2da0ee944(Hashes are of the committed git blobs —
git cat-file blob HEAD:src/smartPlace.ts | sha256sum— immune to autocrlf working-tree drift.)Contract (
chooseClearRect): deterministic candidate ladder — preferred corner (default bottom-right) → remaining corners in fixed order → bottom-center/top-center → three equal shrink steps 72→66→60→54 pt → fallback = preferred corner at 54 pt withfallback: true. FREE = candidate rect expanded by the 8 pt clearance strictly overlaps no obstacle (touching edges stay free; zero-area boxes are lines and still block).Obstacle coverage (this surface, via optional peer
pdfjs-dist): text runs (getTextContent, baseline + one font-height), images (all paintImage ops under a save/restore/transform-tracked CTM), vector paths where pdf.js exposes[minX,minY,maxX,maxY]bounds (verified present in pdfjs-dist 5.7.x for pdf-lib-drawn rects). NOT covered: annotations, shading patterns, clip subtraction; boxes covering ≥90% of the page are treated as background.pdfjs-distis an optional peer (same pattern as pdf-lib/qrcode) — clearmissing_dependencyerror naming the peer, thrown BEFORE any reservation is spent.Result gains
autoPlacement(per-page{x, y, widthPt, anchorTried, shrunk, fallback, obstacleCount}).2. Display-only page tags (
&p=) + sealed page countallPagesseals stamp each page's QR URL with&p=<page>(after?t/&m, before#key=). Single-page docs/placements stay byte-identical untagged. Result gainspageVerifyUrls; canonicalverifyUrlstays untagged.searchParams.get('m')+ pathname id + hash key, unknown params ignored; (b) dynamic — live verify.keyhalve.com engine driven headless onvp_8vw5lin43xu0with and without&p=7: byte-identical verdict text and identical request sequences (tenant 200 → intent 200 → rail piece 403 MAC-gate → fragment 200; the fail-closed MAC path, since no live key exists to produce a green A/B). The attested bundle was not touched.metadata.page_count(total pages) now disclosed on every seal; caller-suppliedpage_countfield wins.3. Document-payload verify (field-found bug fix)
verifyIntentfailed on v0.2 document seals withinvalid_payload: "Decrypted payload is not valid JSON"— those intents carry the raw stamped PDF. Now: JSON parse failure AND file metadata on the intent (file_content_type/file_size_bytes, per the livevp_lm0fqvitp3ztshape) →payloadKind: "document"+document: {contentType, byteSize, declaredByteSize, sha256}(sha256 of the decrypted bytes = the distributable artifact's fingerprint). JSON payloads unchanged; genuine non-JSON non-document payloads still throwinvalid_payload. Applied toverifySplitKeyIntenttoo.Tests / verification
p, peer-missing, binary round-trip + JSON regression).npm run build(tsc) clean. Auto pipeline empirically verified in plain Node (pdfjs-dist 5.7 legacy build, no canvas).Cross-links
🤖 Generated with Claude Code