Implements macOS v0: verae-print stamp + install-macos PDF menu items.
Saves {name}.pdf, {name}-verae-timestamp-{RECEIPTID}.pdf, and .verae.json.
Channels: verae (api.veraetime.net JWT) and zapier (zap.verae.ai xVerae- + attachPdf).
145 lines
8.2 KiB
Markdown
145 lines
8.2 KiB
Markdown
# PrintToVeraeTimeStamp — Design Spec
|
|
|
|
**Date:** 2026-10-03
|
|
**Owner:** George Lambert / Verae
|
|
**Status:** Draft
|
|
|
|
## 1. Goal
|
|
|
|
Provide a "Verae Timestamp" printer on macOS, Linux, and Windows. Printing to it:
|
|
|
|
1. Captures the exact print output as a PDF.
|
|
2. Computes SHA-256 of the whole PDF and of each page.
|
|
3. Submits the digest(s) to the Verae Timestamping service (digest only).
|
|
4. Receives the receipt (JSON, and certificate PDF if the API provides one).
|
|
5. Lets the user **Save**, **Print**, or **Both**: the original PDF, the receipt, and optionally a combined "PDF + certificate page" or a PDF with the receipt embedded without altering the original bytes.
|
|
|
|
## 2. Non-goals
|
|
|
|
- Sending document content to Verae (never).
|
|
- Proving the *source* document (Word/Pages/etc.) — the proof is over the printed PDF bytes.
|
|
- Acting as a general PDF editor.
|
|
|
|
## 3. Key design facts
|
|
|
|
- **The proof is over exact bytes.** Printing the same document twice produces different PDFs (timestamps, IDs, fonts). Therefore the captured PDF must always be saved alongside the receipt; that file is the verifiable artifact.
|
|
- **Embedding without breaking the hash.** If the receipt is embedded, it is appended as a PDF *incremental update* (attachment + annotation/certificate page). The original byte range is unchanged, so `sha256(first N bytes)` still matches. The receipt records `N`.
|
|
- **Per-page hashes.** Each page is extracted as a single-page PDF (deterministic extraction via the same library/version) and hashed; the list is included in a canonical manifest whose SHA-256 is also stamped. This allows proving individual pages.
|
|
|
|
## 4. Verae Timestamp API (dual channel)
|
|
|
|
### 4.1 Verae Time (default — non-Zapier)
|
|
|
|
| Call | Purpose |
|
|
|---|---|
|
|
| `POST {base}/api/timestamp` body `{"data":<hex>,"digest":<hex>,"hashAlg":"SHA256","restamp":false}` | Stamp a digest. 200 with `certificate` or `existing` = done; otherwise returns a job id |
|
|
| `GET {base}/api/status/{jobId}` | Poll until completed |
|
|
| `GET {base}/api/hash/{digest}` | Look up existing stamp |
|
|
| `POST {base}/api/verify` | Verify |
|
|
|
|
- Default base: `https://api.veraetime.net`
|
|
- Auth: `Authorization: Bearer <token>` from `~/.verae/auth.properties` (keys `access_token` / `auth_token` / `id_token`)
|
|
- Certificate PDF: render locally from receipt when the API does not return a PDF body
|
|
|
|
### 4.2 Zapier / edge channel
|
|
|
|
| Call | Purpose |
|
|
|---|---|
|
|
| `POST https://zap.verae.ai/v1/timestamp` body `{sha256, attachPdf:true, wait:true, documentName}` | Stamp + optional registration PDF |
|
|
|
|
- Auth: `x-api-key: xVerae-…` (or Bearer) from Keychain / `~/.verae/xverae-token` / env `XVERAE_TOKEN`
|
|
- Certificate PDF: decode `pdfBase64` from the JSON response (or raw PDF when `Accept: application/pdf`)
|
|
|
|
## 5. Architecture
|
|
|
|
```
|
|
┌──────────── OS print system ────────────┐
|
|
App ──▶ Print │ macOS/Linux: CUPS queue "Verae Timestamp" │
|
|
│ backend: verae (runs as lp, sandboxed) │──▶ spool dir (per job: job.pdf + job.json)
|
|
│ Windows: virtual printer → PDF port │
|
|
└──────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
verae-print-helper (per-user, tray/menu-bar)
|
|
- watch spool, pick up job
|
|
- sha256 (doc + pages + manifest)
|
|
- stamp via API (queue offline → retry)
|
|
- dialog: Save / Print / Both / Cancel
|
|
- write: <name>.pdf, <name>.verae.json,
|
|
optional <name>.stamped.pdf
|
|
- optional: forward to real printer (+ cert page)
|
|
```
|
|
|
|
### 5.1 macOS
|
|
|
|
- **v0 (fast path):** PDF Services entry — "Timestamp with Verae" in the Print dialog's PDF menu. Installed to `~/Library/PDF Services/` as an app/script that receives the PDF path. No CUPS driver needed.
|
|
- Default channel: **Verae Time** (`api.veraetime.net` + MCP JWT from `~/.verae/auth.properties`).
|
|
- Optional second menu item **Timestamp with Verae (Zapier)** or `--channel=zapier`: `zap.verae.ai` + `xVerae-` token + `attachPdf: true`.
|
|
- Saves to `~/Documents/Verae Timestamps/` by default (override with `--out-dir` / preference).
|
|
- **v1:** CUPS queue with custom backend `/usr/libexec/cups/backend/verae` + PPD (or IPP Everywhere). The backend is sandboxed and cannot show UI, so it writes to `/Library/Application Support/Verae/spool/<user>/` and exits; the menu-bar helper (LaunchAgent) picks it up.
|
|
- Signed + notarized `.pkg`.
|
|
|
|
### 5.2 Linux
|
|
|
|
- CUPS queue `Verae-Timestamp`, backend `/usr/lib/cups/backend/verae`, PDF input via the standard filter chain (`pdftopdf`). Spool to `/var/spool/verae/<user>/`; user helper runs as systemd user service (+ tray icon via StatusNotifier, or desktop notification with actions). Headless mode: auto-save to `~/Documents/Verae Timestamps/` with no dialog.
|
|
- Packages: `.deb`, `.rpm`; optional Flatpak for the helper only.
|
|
|
|
### 5.3 Windows
|
|
|
|
Options, in order of preference:
|
|
|
|
1. **Microsoft Print to PDF driver + custom port monitor** writing to the spool folder (port monitor DLL, installed by MSI). Proven and simple.
|
|
2. **Local IPP printer service** (helper exposes IPP Everywhere on 127.0.0.1); Windows 10/11 IPP class driver sends PDF or PWG raster. Same code as macOS/Linux option below.
|
|
3. Print Support App (UWP/MSIX) for the modern print path — later, if enterprise deployment needs it.
|
|
|
|
Helper is a tray app; MSI signed with Authenticode.
|
|
|
|
### 5.4 Optional unified path
|
|
|
|
A single local **IPP Everywhere printer service** (e.g. built on PAPPL or a Go IPP server) advertised via DNS-SD on loopback. macOS and Linux discover it driverlessly; Windows adds it with the IPP class driver. Reduces per-OS driver code; evaluate in the spike.
|
|
|
|
## 6. Outputs
|
|
|
|
For a print job whose document name is `Contract` (extension stripped for the stem):
|
|
|
|
| File | Content |
|
|
|---|---|
|
|
| `Contract.pdf` | Exact captured bytes (the proven artifact) |
|
|
| `Contract-verae-timestamp-{RECEIPTID}.pdf` | Verae registration / certificate PDF only |
|
|
| `Contract.verae.json` | Receipt sidecar: doc sha256, receipt id, channel, API host, time, helper version, original byte length |
|
|
|
|
`RECEIPTID` is the Verae receipt / certificate CID, sanitized for filenames (safe charset). Long CIDs are kept in full when under filesystem limits.
|
|
|
|
**macOS v0 naming is fixed to the table above** (approved 2026-10-03). Later optional embed/combined outputs may still use `.stamped.pdf` but are out of scope for v0.
|
|
|
|
Certificate PDF source by channel:
|
|
- **Zapier channel:** `pdfBase64` from `POST https://zap.verae.ai/v1/timestamp` with `attachPdf: true`.
|
|
- **Verae Time / default:** stamp via `api.veraetime.net`; use API/MCP registration PDF when available, otherwise render a local certificate page from the receipt JSON (document name, SHA-256, time UTC + local, receipt id, verify URL).
|
|
|
|
## 7. Settings
|
|
|
|
- Default action: ask / save / print / both.
|
|
- Save folder; filename pattern.
|
|
- Forward printer (real printer) for "Print" and "Both".
|
|
- Embed receipt (on/off); add certificate page when printing (on/off).
|
|
- Per-page hashing (on/off).
|
|
- Verae base URL + login (reuse `~/.verae/auth.json`; login via browser flow).
|
|
- Offline queue: if API unreachable, save locally, mark "pending", stamp later, update receipt.
|
|
|
|
## 8. Security & privacy
|
|
|
|
- Digest only over TLS; never the document.
|
|
- Spool dirs per user, mode 0700; jobs deleted after handling.
|
|
- Backend never runs network code (keeps the root/lp component tiny); all network in the user helper.
|
|
- Code signing on all platforms; installer verifies helper signature.
|
|
- Token stored in OS keychain where available (Keychain, libsecret, Credential Manager), falling back to `~/.verae/auth.json`.
|
|
|
|
## 9. Verification
|
|
|
|
`verae-print verify Contract.pdf [Contract.verae.json]` recomputes digests (and for `.stamped.pdf`, the original byte range) and checks them against the Verae API (`/api/hash/{digest}` or `/api/verify`).
|
|
|
|
## 10. Open questions
|
|
|
|
1. Certificate PDF endpoint/format in the Verae API.
|
|
2. Batch stamping (doc + pages + manifest in one call) vs stamping only the manifest digest.
|
|
3. Licensing and distribution channel (direct download vs App Store/Microsoft Store).
|