feat: fill-manifest-sha256.ps1 + CERT local font-face first
Some checks failed
windows-msi / full-msi-unsigned (push) Has been cancelled
Some checks failed
windows-msi / full-msi-unsigned (push) Has been cancelled
Hash helper for DOWNLOADS-MANIFEST; certificate.html prefers fonts/*.woff2 when present.
This commit is contained in:
parent
042342bd69
commit
da4a0dc4e2
12 changed files with 366 additions and 82 deletions
|
|
@ -35,6 +35,7 @@ Repo now includes **authoring/docs scaffolds** for the two commercial gaps that
|
|||
| [`.github/workflows/windows-msi.yml`](../.github/workflows/windows-msi.yml) unsigned MSI on `windows-latest` + artifact upload | Wire org secrets and enable sign step; publish signed assets to site |
|
||||
| [`ci-notarize.yml.example`](../platform/macos/menubar/ci-notarize.yml.example) menubar GHA/Forgejo sketch (unsigned default; secret names) | Promote example → live workflow; automate `build-menubar-app.sh` sign when `SIGNING_ENV` set |
|
||||
| **0.3.6 Windows NSIS+MSI placeholder rows** ([`DOWNLOADS-MANIFEST.txt`](../site/printit.verae.ai/DOWNLOADS-MANIFEST.txt) + [`DOWNLOADS-MANIFEST.md`](../site/printit.verae.ai/DOWNLOADS-MANIFEST.md); sha256 **TBD**) | Build/upload signed 0.3.6 blobs; replace TBD with real digests |
|
||||
| [`fill-manifest-sha256.ps1`](../platform/windows/scripts/fill-manifest-sha256.ps1) local hash → DOWNLOADS-MANIFEST rows (linked from DUAL-SHIP + manifest.md; **no upload**) | Operator still must upload first, then paste digests over TBD |
|
||||
| **Printable VM A/B/C sheet** [`VM-DUAL-SHIP-CHECKLIST.md`](../platform/windows/wix/VM-DUAL-SHIP-CHECKLIST.md) | Operator sign-off on clean VMs (C blocked until CAs uncommented) |
|
||||
|
||||
**Still use for day-to-day presence (no WiX / no Apple certs):**
|
||||
|
|
@ -73,6 +74,7 @@ Related but out of scope for “done” above (still backlog-adjacent): Linux `.
|
|||
| **Dual-ship runbook** | [`wix/DUAL-SHIP.md`](../platform/windows/wix/DUAL-SHIP.md) | **Docs** — NSIS + MSI clean-VM matrix; CI artifact section; **thin-NSIS exit checklist** (A–E) |
|
||||
| **Printable VM checklist** | [`wix/VM-DUAL-SHIP-CHECKLIST.md`](../platform/windows/wix/VM-DUAL-SHIP-CHECKLIST.md) | **Docs** — tick boxes for shared pre-checks + VM A/B/C + side-by-side |
|
||||
| **0.3.6 download placeholders** | [`site/.../DOWNLOADS-MANIFEST.md`](../site/printit.verae.ai/DOWNLOADS-MANIFEST.md) + `.txt` TBD rows | **Docs** — NSIS setup + full MSI filenames reserved; digests TBD until publish |
|
||||
| **Manifest SHA-256 row helper** | [`scripts/fill-manifest-sha256.ps1`](../platform/windows/scripts/fill-manifest-sha256.ps1) | **Tool** — local `Get-FileHash` → SHA256SUMS / MD rows; does **not** upload or rewrite site files |
|
||||
| Shared version helper | [`platform/windows/scripts/common.ps1`](../platform/windows/scripts/common.ps1) `Get-VeraePackageVersion` | Aligns tray/full MSI/NSIS drivers with `HelperVersion` |
|
||||
| End-user Windows readme | [`platform/windows/README-WINDOWS.txt`](../platform/windows/README-WINDOWS.txt), [`README.txt`](../platform/windows/README.txt) | Documents NSIS flow; states **no elevated MSI** for tray |
|
||||
| Packaging policy doc | [PACKAGING.md](PACKAGING.md) | “**No elevated MSI**” for tray presence by design |
|
||||
|
|
@ -86,7 +88,7 @@ NSIS product already covers much of the *install experience* (files under Progra
|
|||
| Gap | Why it matters | Suggested work |
|
||||
|-----|----------------|----------------|
|
||||
| **Full-product WiX authoring + StageFull driver** | **Exists** — `Product-Full.wxs` + `build-full-msi.ps1` | MSI binary only on hosts with candle/light; still dual-ship NSIS |
|
||||
| **MSI output when WiX present** | `wix/out/VeraePrintStamp-windows-<arch>-<version>.msi` via `build-full-msi.ps1` | Not yet published to `dist/` / site downloads; no SHA256 release job |
|
||||
| **MSI output when WiX present** | `wix/out/VeraePrintStamp-windows-<arch>-<version>.msi` via `build-full-msi.ps1` | Not yet published to `dist/` / site downloads; local hash helper `fill-manifest-sha256.ps1` (no upload/CI publish job yet) |
|
||||
| **No Authenticode signing pipeline** in-repo | SmartScreen / enterprise trust | `signtool` (or Azure Trusted Signing) for EXE/DLL **and** MSI; store certs in CI secrets only — never in git. **Not shipped.** |
|
||||
| **Silent / unattended install contract** | Fleet deploy | Props documented (`SILENT_PROPS.md`); wire scheduled CAs to honor them |
|
||||
| **Upgrade / repair / ARP metadata** | Clean major-upgrade, Add/Remove Programs | WiX `UpgradeCode` present; migrate ARP fully from NSIS `UNINST_KEY` after dual-ship |
|
||||
|
|
@ -104,7 +106,7 @@ NSIS product already covers much of the *install experience* (files under Progra
|
|||
4. **Uncomment** + test printer/helper deferred CAs on clean VM (DUAL-SHIP VM C); keep NSIS primary until parity.
|
||||
5. Authenticode on binaries + MSI (**not shipped** — enable commented sign step; secret names in workflow + `CI-SIGN-NOTARY.md`).
|
||||
6. Honor silent props in live CAs + Intune sample command line proof.
|
||||
7. Publish 0.3.6 artifacts; refresh site `DOWNLOADS-MANIFEST` checksums; keep smoke on HelperVersion drift.
|
||||
7. Publish 0.3.6 artifacts; refresh site `DOWNLOADS-MANIFEST` checksums via `fill-manifest-sha256.ps1` (hash-only; no upload); keep smoke on HelperVersion drift.
|
||||
8. Deprecate or thin NSIS once MSI is the primary download (**thin-NSIS exit checklist** A–D in DUAL-SHIP.md — all boxes).
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -182,15 +182,16 @@ Site page: [`site/printit.verae.ai/certificate.html`](../site/printit.verae.ai/c
|
|||
|
||||
| Item | Status |
|
||||
|------|--------|
|
||||
| CERT-01 layout | **Shipped** — plum/gold double frame, Fraunces title via Google Fonts, gold rule, final banner, mono digests, digests-only footer |
|
||||
| CERT-01 layout | **Shipped** — plum/gold double frame, Fraunces title (local woff2 else CDN), gold rule, final banner, mono digests, digests-only footer |
|
||||
| Brand kit | Uses `brand/tokens.css`, `verae-ui-kit.css`, `brand/logo/verae-mark.svg` |
|
||||
| Multihash / BLAKE3 | Shown **only when present** (query, sidecar, or sample); never invented |
|
||||
| Load paths | Query string (`?sha256=&receipt=&…`), optional `.verae.json` sidecar drop, “Sample data” button |
|
||||
| Print CSS | Letter page, toolbar hidden, frame colors preserved |
|
||||
| Live verify | Link to `explorer.verae.ai/time?receipt=&sha256=` (same as `pdfcert.LookupURL`) |
|
||||
| Live QR (web) | **Shipped** — final + receipt/digest paints QR via qrcode.js CDN → data-URL; offline/provisional keeps SVG placeholder (print-safe) |
|
||||
| Residual gap | Full **CERT-01.html** pixel match (self-hosted design-kit Fraunces/Cantarell, Substrate extrinsic polish) still **not** claimed — web title ships CDN Fraunces + Georgia/serif offline fallback; issued artifact remains PDF (`internal/pdfcert` + `platform/registration-pdf/build.mjs`) |
|
||||
| Self-host fonts plan | [`site/printit.verae.ai/fonts/README.md`](../site/printit.verae.ai/fonts/README.md) — woff2 placeholder dir (empty + `.gitkeep`); binaries/CDN cutover not started |
|
||||
| Residual gap | Full **CERT-01.html** pixel match (self-hosted design-kit Fraunces/Cantarell, Substrate extrinsic polish) still **not** claimed — web title prefers local `fonts/*.woff2` else CDN Fraunces + Georgia/serif offline fallback; issued artifact remains PDF (`internal/pdfcert` + `platform/registration-pdf/build.mjs`) |
|
||||
| Self-host fonts plan | [`site/printit.verae.ai/fonts/README.md`](../site/printit.verae.ai/fonts/README.md) — drop-in woff2 dir (empty + `.gitkeep`); local-first probe in `certificate.html` |
|
||||
| Local-first fonts (Issue 7) | `certificate.html` probes planned `fonts/*.woff2` (magic `wOF2`); any hit → `@font-face` only; none → Google Fonts CDN. No proprietary binaries downloaded or committed |
|
||||
| Font fetch scaffold (TODO-7 A7) | [`site/printit.verae.ai/fonts/fetch-fonts.example.sh`](../site/printit.verae.ai/fonts/fetch-fonts.example.sh) — curl **placeholders only** (commented URLs, OFL reminder, `--check`); no licensed binaries downloaded or committed |
|
||||
| Layout spacing (TODO-7 A7) | `certificate.html` padding/margins nudged toward CERT-01 mock: sheet **56×64**, column **816px**, logo **40px**, title block **26/6/14**, gold rule **2×120**, banner **18** / check **34** / title **16px**, kv **20**, verify gap **22**, QR **130**; plum **1.5px** + gold **0.5px** inset frame. Still **not** full pixel match |
|
||||
|
||||
|
|
@ -201,9 +202,9 @@ Cross-product siblings (not owned here): Sign `certificate.html` (SG-P1), Verify
|
|||
|
||||
| Done this slice | Still left |
|
||||
|-----------------|------------|
|
||||
| `fetch-fonts.example.sh` example + `--check` | Real woff2 + `OFL.txt` committed; `@font-face` cutover; drop Google Fonts CDN links |
|
||||
| CERT sheet spacing closer to CERT-01 | Full CERT-01.html pixel match (Fraunces opsz, Cantarell body if required, Substrate extrinsic polish) |
|
||||
| PACKAGING rows above | PDF Fraunces embed in `internal/pdfcert` / `registration-pdf/build.mjs` (system Times/Helvetica only today) |
|
||||
| Local-first `@font-face` else CDN; fonts drop-in README | Real OFL woff2 + `OFL.txt` **committed** (operator drop-in only today) |
|
||||
| `fetch-fonts.example.sh` example + `--check` | Full CERT-01.html pixel match (Fraunces opsz, Cantarell body if required, Substrate extrinsic polish) |
|
||||
| CERT sheet spacing closer to CERT-01 | PDF Fraunces embed in `internal/pdfcert` / `registration-pdf/build.mjs` (system Times/Helvetica only today) |
|
||||
|
||||
## statuslang notify titles
|
||||
|
||||
|
|
|
|||
152
platform/windows/scripts/fill-manifest-sha256.ps1
Normal file
152
platform/windows/scripts/fill-manifest-sha256.ps1
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
#Requires -Version 5.1
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Compute SHA-256 of built MSI/NSIS (or companion EXE) and print DOWNLOADS-MANIFEST rows.
|
||||
|
||||
.DESCRIPTION
|
||||
Given one or more paths to release artifacts (setup.exe, .msi, bare helper .exe),
|
||||
prints SHA256SUMS-style lines matching site/printit.verae.ai/DOWNLOADS-MANIFEST.txt:
|
||||
|
||||
<lowercase-hex> <leaf-name>
|
||||
|
||||
Optionally prints a Markdown table row for DOWNLOADS-MANIFEST.md.
|
||||
|
||||
Does NOT upload, rewrite the site manifests, or sign. Operator order remains:
|
||||
build → sign (when required) → upload → hash → paste digests over TBD.
|
||||
|
||||
.EXITCODES
|
||||
0 At least one path hashed successfully.
|
||||
1 No paths, missing file, or terminating error.
|
||||
|
||||
.PARAMETER Path
|
||||
One or more artifact paths (MSI, NSIS setup.exe, optional bare helper).
|
||||
Also accepts leftover positional args and pipeline input (strings or FileInfo).
|
||||
|
||||
.PARAMETER Format
|
||||
txt — SHA256SUMS lines only (default; paste into DOWNLOADS-MANIFEST.txt).
|
||||
md — Markdown table rows for DOWNLOADS-MANIFEST.md.
|
||||
both — txt then md (md after a blank line).
|
||||
|
||||
.PARAMETER AsName
|
||||
Override the leaf name written in the row (single Path only). Use when the
|
||||
local build name differs from the CDN filename reserved in the manifest.
|
||||
|
||||
.EXAMPLE
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File fill-manifest-sha256.ps1 `
|
||||
-Path .\dist\VeraePrintStamp-windows-amd64-0.3.6-setup.exe,
|
||||
.\platform\windows\wix\out\VeraePrintStamp-windows-amd64-0.3.6.msi
|
||||
|
||||
.EXAMPLE
|
||||
.\fill-manifest-sha256.ps1 -Path .\out\product.msi -AsName VeraePrintStamp-windows-amd64-0.3.6.msi -Format both
|
||||
#>
|
||||
param(
|
||||
[Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
|
||||
[Alias("FullName", "PSPath")]
|
||||
[string[]]$Path = @(),
|
||||
|
||||
[ValidateSet("txt", "md", "both")]
|
||||
[string]$Format = "txt",
|
||||
|
||||
[string]$AsName = ""
|
||||
)
|
||||
|
||||
begin {
|
||||
$ErrorActionPreference = "Stop"
|
||||
$collected = New-Object System.Collections.Generic.List[string]
|
||||
}
|
||||
|
||||
process {
|
||||
foreach ($p in @($Path)) {
|
||||
if ($null -eq $p) { continue }
|
||||
$s = "$p".Trim()
|
||||
if (-not $s) { continue }
|
||||
# Pipeline FileInfo often arrives as Microsoft.PowerShell.Core\FileSystem::path
|
||||
if ($s -match '^Microsoft\.PowerShell\.Core\\FileSystem::(.+)$') {
|
||||
$s = $Matches[1]
|
||||
}
|
||||
[void]$collected.Add($s)
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
# Leftover unbound args (powershell -File script.ps1 a.msi b.exe)
|
||||
if ($args -and $args.Count -gt 0) {
|
||||
foreach ($a in $args) {
|
||||
$s = "$a".Trim()
|
||||
if ($s) { [void]$collected.Add($s) }
|
||||
}
|
||||
}
|
||||
|
||||
if ($collected.Count -eq 0) {
|
||||
Write-Error "No artifact paths given. Pass -Path <msi|setup.exe|...> (does not upload)."
|
||||
}
|
||||
|
||||
if ($AsName -and $collected.Count -gt 1) {
|
||||
Write-Error "-AsName applies to a single -Path only."
|
||||
}
|
||||
|
||||
$rows = New-Object System.Collections.Generic.List[object]
|
||||
foreach ($raw in $collected) {
|
||||
if (-not (Test-Path -LiteralPath $raw)) {
|
||||
Write-Error "Artifact not found: $raw"
|
||||
}
|
||||
$item = Get-Item -LiteralPath $raw
|
||||
if ($item.PSIsContainer) {
|
||||
Write-Error "Path is a directory (need file): $raw"
|
||||
}
|
||||
$hash = (Get-FileHash -LiteralPath $item.FullName -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
$leaf = if ($AsName) { $AsName.Trim() } else { $item.Name }
|
||||
if (-not $leaf) {
|
||||
Write-Error "Empty leaf name for $raw"
|
||||
}
|
||||
[void]$rows.Add([pscustomobject]@{
|
||||
Hash = $hash
|
||||
Name = $leaf
|
||||
FullName = $item.FullName
|
||||
Length = $item.Length
|
||||
})
|
||||
}
|
||||
|
||||
function Write-TxtRows {
|
||||
param($Items)
|
||||
foreach ($r in $Items) {
|
||||
# Two spaces between digest and name — same as DOWNLOADS-MANIFEST.txt / shasum -a 256
|
||||
Write-Output ("{0} {1}" -f $r.Hash, $r.Name)
|
||||
}
|
||||
}
|
||||
|
||||
function Write-MdRows {
|
||||
param($Items)
|
||||
foreach ($r in $Items) {
|
||||
$role = "artifact"
|
||||
$channel = "file"
|
||||
$n = $r.Name
|
||||
if ($n -match '\.msi$') {
|
||||
$channel = "Full MSI"
|
||||
$role = "Dual-ship / fleet path"
|
||||
} elseif ($n -match '-setup\.exe$') {
|
||||
$channel = "NSIS"
|
||||
$role = "Windows setup"
|
||||
} elseif ($n -match '^verae-print-windows-.*\.exe$') {
|
||||
$channel = "Bare helper"
|
||||
$role = "Optional companion EXE"
|
||||
}
|
||||
Write-Output ("| `{0}` | {1} | {2} | `{3}` | hashed locally (not uploaded by this script) |" -f $n, $channel, $role, $r.Hash)
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "# fill-manifest-sha256: local hash only — does not upload or edit site manifests." -ForegroundColor DarkGray
|
||||
Write-Host "# Paste over TBD in DOWNLOADS-MANIFEST.txt only after the blob is on the CDN." -ForegroundColor DarkGray
|
||||
|
||||
switch ($Format) {
|
||||
"txt" { Write-TxtRows $rows }
|
||||
"md" { Write-MdRows $rows }
|
||||
"both" {
|
||||
Write-TxtRows $rows
|
||||
Write-Output ""
|
||||
Write-MdRows $rows
|
||||
}
|
||||
}
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
|
@ -189,7 +189,7 @@ GHA/Forgejo copy-paste sketch (unsigned default, notary job gated off): [`ci-not
|
|||
2. **Sign** Windows PE + MSI with `signtool` (or Trusted Signing).
|
||||
3. **Notarize** macOS zip/pkg with `notarytool --wait`.
|
||||
4. **Staple** macOS artifacts; `stapler validate`.
|
||||
5. **Checksum** + upload release assets; update `site/printit.verae.ai/DOWNLOADS-MANIFEST.txt` out-of-band or via a docs job.
|
||||
5. **Checksum** + upload release assets; update `site/printit.verae.ai/DOWNLOADS-MANIFEST.txt` out-of-band (`platform/windows/scripts/fill-manifest-sha256.ps1` prints rows only — does not upload) or via a docs job.
|
||||
6. Never upload raw PFX / `.p8` as workflow artifacts.
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
**Do not** thin or deprecate NSIS until the **thin-NSIS exit criteria checklist** (below) is fully checked — clean-VM gates, live Authenticode, silent/fleet proof, and site cutover (see [COMMERCIAL-INSTALLER-BACKLOG.md](../../../docs/COMMERCIAL-INSTALLER-BACKLOG.md), [CI-SIGN-NOTARY.md](CI-SIGN-NOTARY.md)).
|
||||
|
||||
**Related:** [Product-Full.wxs](Product-Full.wxs) · [SILENT_PROPS.md](SILENT_PROPS.md) · [VM-DUAL-SHIP-CHECKLIST.md](VM-DUAL-SHIP-CHECKLIST.md) (printable A/B/C) · [../installer-windows.nsi](../installer-windows.nsi) · [PACKAGING.md](../../../docs/PACKAGING.md) · site [DOWNLOADS-MANIFEST.md](../../../site/printit.verae.ai/DOWNLOADS-MANIFEST.md) (0.3.6 TBD rows).
|
||||
**Related:** [Product-Full.wxs](Product-Full.wxs) · [SILENT_PROPS.md](SILENT_PROPS.md) · [VM-DUAL-SHIP-CHECKLIST.md](VM-DUAL-SHIP-CHECKLIST.md) (printable A/B/C) · [../installer-windows.nsi](../installer-windows.nsi) · [PACKAGING.md](../../../docs/PACKAGING.md) · site [DOWNLOADS-MANIFEST.md](../../../site/printit.verae.ai/DOWNLOADS-MANIFEST.md) (0.3.6 TBD rows) · [`fill-manifest-sha256.ps1`](../scripts/fill-manifest-sha256.ps1) (hash built MSI/NSIS → manifest row; no upload).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -47,10 +47,32 @@ Expected outputs (names vary by arch):
|
|||
| NSIS setup | `dist/` or build output `VeraePrintStamp-windows-amd64-<ver>-setup.exe` |
|
||||
| Full MSI | `platform/windows/wix/out/VeraePrintStamp-windows-amd64-<ver>.msi` |
|
||||
|
||||
Local SHA-256 for site manifest rows (**no upload**):
|
||||
|
||||
```powershell
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\fill-manifest-sha256.ps1 `
|
||||
-Path .\dist\VeraePrintStamp-windows-amd64-<ver>-setup.exe,
|
||||
.\platform\windows\wix\out\VeraePrintStamp-windows-amd64-<ver>.msi
|
||||
```
|
||||
|
||||
Paste printed digests over **TBD** in [DOWNLOADS-MANIFEST.txt](../../../site/printit.verae.ai/DOWNLOADS-MANIFEST.txt) only after the blob is on the CDN. See [DOWNLOADS-MANIFEST.md](../../../site/printit.verae.ai/DOWNLOADS-MANIFEST.md).
|
||||
|
||||
If WiX is missing, `build-full-msi.ps1` **exits 1** with an install tip — dual-ship **fails closed** for the MSI leg (do not claim MSI ready).
|
||||
|
||||
Cross-host NSIS-only: `platform/windows/build-installer.sh` (needs prebuilt Windows binaries).
|
||||
|
||||
### Manifest checksum rows (no upload)
|
||||
|
||||
After artifacts exist locally (and only after they are on the CDN when rewriting site TBD):
|
||||
|
||||
```powershell
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\fill-manifest-sha256.ps1 `
|
||||
-Path .\dist\VeraePrintStamp-windows-amd64-<ver>-setup.exe,
|
||||
.\platform\windows\wix\out\VeraePrintStamp-windows-amd64-<ver>.msi
|
||||
```
|
||||
|
||||
Prints `DOWNLOADS-MANIFEST.txt` lines (`<sha256> <leaf>`). `-Format md` prints Markdown table rows for [DOWNLOADS-MANIFEST.md](../../../site/printit.verae.ai/DOWNLOADS-MANIFEST.md). **Does not upload** or edit the site files.
|
||||
|
||||
---
|
||||
|
||||
## Clean-VM matrix (minimum)
|
||||
|
|
@ -195,7 +217,7 @@ Thin or demote NSIS to “key-wizard offline only” (or drop from primary downl
|
|||
|
||||
- [ ] Site **primary** Windows download points at signed full MSI (`VeraePrintStamp-windows-*-<ver>.msi`).
|
||||
- [ ] NSIS `setup.exe` linked as **alternate** only (or removed from primary CTA) — not the default button.
|
||||
- [ ] `DOWNLOADS-MANIFEST.txt` checksums refreshed for the promoted MSI (and remaining NSIS if kept).
|
||||
- [ ] `DOWNLOADS-MANIFEST.txt` checksums refreshed for the promoted MSI (and remaining NSIS if kept) — use [`fill-manifest-sha256.ps1`](../scripts/fill-manifest-sha256.ps1) after upload (script does **not** upload).
|
||||
- [ ] Release notes / PACKAGING state MSI as primary full-product Windows install.
|
||||
- [ ] OPEN-ISSUES Issue 1 **Still left** no longer lists dual-ship gate / thin-NSIS / “NSIS still primary”.
|
||||
|
||||
|
|
@ -254,4 +276,5 @@ Do **not** put PFX bytes or passwords in git. Do not upload the PFX as a workflo
|
|||
| Sign/notary draft | [CI-SIGN-NOTARY.md](CI-SIGN-NOTARY.md) |
|
||||
| Menubar CI notary example | [../../macos/menubar/ci-notarize.yml.example](../../macos/menubar/ci-notarize.yml.example) |
|
||||
| Site 0.3.6 placeholders | [DOWNLOADS-MANIFEST.md](../../../site/printit.verae.ai/DOWNLOADS-MANIFEST.md) · [DOWNLOADS-MANIFEST.txt](../../../site/printit.verae.ai/DOWNLOADS-MANIFEST.txt) |
|
||||
| Local SHA-256 → manifest rows | [../scripts/fill-manifest-sha256.ps1](../scripts/fill-manifest-sha256.ps1) (hash only; no upload) |
|
||||
| Commercial backlog | [docs/COMMERCIAL-INSTALLER-BACKLOG.md](../../../docs/COMMERCIAL-INSTALLER-BACKLOG.md) |
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ day-to-day full product. **Not** Authenticode-signed; printer CAs remain
|
|||
| `README.md` | This file |
|
||||
| `../scripts/build-tray-msi.ps1` | Tray candle/light driver; WiX tip exit 0 if missing |
|
||||
| `../scripts/build-full-msi.ps1` | Full StageFull + candle/light; WiX missing → exit 1 |
|
||||
| `../scripts/fill-manifest-sha256.ps1` | Hash built MSI/NSIS → DOWNLOADS-MANIFEST row (no upload) |
|
||||
|
||||
### Relation to other Windows paths
|
||||
|
||||
|
|
@ -182,6 +183,7 @@ day-to-day full product. **Not** Authenticode-signed; printer CAs remain
|
|||
| `../scripts/build-tray-startmenu.ps1` | WiX-free Start Menu + Startup |
|
||||
| `../scripts/build-tray-msi.ps1` | Builds tray presence MSI when WiX is installed |
|
||||
| `../scripts/build-full-msi.ps1` | Stages StageFull + builds full MSI when WiX is installed |
|
||||
| `../scripts/fill-manifest-sha256.ps1` | Local SHA-256 rows for site DOWNLOADS-MANIFEST (no upload) |
|
||||
| `../installer-windows.nsi` | Elevated **full product** setup.exe (primary until MSI validated) |
|
||||
| **`wix/` (this folder)** | Tray skeleton + full Product-Full authoring |
|
||||
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ UI install is fine for smoke; `/qn` proves fleet syntax.
|
|||
|------|---|
|
||||
| Record logs + exit codes in release notes / dual-ship folder | ☐ |
|
||||
| Authenticode still left → SmartScreen warn is **not** promote-ready | ☐ |
|
||||
| Update site `DOWNLOADS-MANIFEST` digests only after upload (0.3.6 rows are TBD until then) | ☐ |
|
||||
| Update site `DOWNLOADS-MANIFEST` digests only after upload (0.3.6 rows are TBD until then); hash with `fill-manifest-sha256.ps1` (no upload) | ☐ |
|
||||
| Thin-NSIS only when DUAL-SHIP exit checklist **A–D** all checked | ☐ |
|
||||
|
||||
**Overall dual-ship gate:** open / closed · notes: _______________________________
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ Human-readable companion to [`DOWNLOADS-MANIFEST.txt`](DOWNLOADS-MANIFEST.txt) (
|
|||
**Last-published CDN blobs:** mostly **0.3.2** (Windows amd64 NSIS / macOS / Linux) or **0.1.2** (Windows arm64, `.deb`, bare `.zip`).
|
||||
**Rule:** do not replace a checksum line until the matching artifact is built, signed (when required), uploaded, and the digest verified. `TBD` is intentional — not a shipping claim.
|
||||
|
||||
Related: [DUAL-SHIP.md](../../platform/windows/wix/DUAL-SHIP.md) · [VM-DUAL-SHIP-CHECKLIST.md](../../platform/windows/wix/VM-DUAL-SHIP-CHECKLIST.md) · [COMMERCIAL-INSTALLER-BACKLOG.md](../../docs/COMMERCIAL-INSTALLER-BACKLOG.md).
|
||||
Related: [DUAL-SHIP.md](../../platform/windows/wix/DUAL-SHIP.md) · [VM-DUAL-SHIP-CHECKLIST.md](../../platform/windows/wix/VM-DUAL-SHIP-CHECKLIST.md) · [COMMERCIAL-INSTALLER-BACKLOG.md](../../docs/COMMERCIAL-INSTALLER-BACKLOG.md) · [`fill-manifest-sha256.ps1`](../../platform/windows/scripts/fill-manifest-sha256.ps1) (local hash → manifest row; **does not upload**).
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -32,15 +32,26 @@ TBD VeraePrintStamp-windows-arm64-0.3.6.msi
|
|||
TBD verae-print-windows-amd64-0.3.6.exe
|
||||
```
|
||||
|
||||
After upload:
|
||||
After upload (hash only — this helper does **not** upload):
|
||||
|
||||
```powershell
|
||||
# Windows (preferred): SHA256SUMS-style rows for DOWNLOADS-MANIFEST.txt
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File platform\windows\scripts\fill-manifest-sha256.ps1 `
|
||||
-Path .\VeraePrintStamp-windows-amd64-0.3.6-setup.exe,
|
||||
.\VeraePrintStamp-windows-amd64-0.3.6.msi
|
||||
# -Format both → also print Markdown table rows for this file
|
||||
# -AsName <cdn-leaf> when local build name ≠ reserved CDN filename
|
||||
```
|
||||
|
||||
```bash
|
||||
# From the directory that holds the release blobs:
|
||||
# From the directory that holds the release blobs (POSIX equivalent):
|
||||
shasum -a 256 VeraePrintStamp-windows-amd64-0.3.6-setup.exe \
|
||||
VeraePrintStamp-windows-amd64-0.3.6.msi
|
||||
# Paste hex digests over TBD in DOWNLOADS-MANIFEST.txt (and this table).
|
||||
```
|
||||
|
||||
Helper: [`fill-manifest-sha256.ps1`](../../platform/windows/scripts/fill-manifest-sha256.ps1) · dual-ship runbook: [DUAL-SHIP.md](../../platform/windows/wix/DUAL-SHIP.md).
|
||||
|
||||
---
|
||||
|
||||
## Last-published (live checksums in `.txt`)
|
||||
|
|
@ -60,5 +71,5 @@ Exact digests: see [`DOWNLOADS-MANIFEST.txt`](DOWNLOADS-MANIFEST.txt).
|
|||
## Operator notes
|
||||
|
||||
1. Site product string may say **0.3.6** while CDN still serves **0.3.2** — that lag is documented on `index.html` and here.
|
||||
2. Filling TBD without uploading the blob breaks mirror checks; always upload first, hash second, rewrite third.
|
||||
2. Filling TBD without uploading the blob breaks mirror checks; always upload first, hash second (`fill-manifest-sha256.ps1`), rewrite third.
|
||||
3. Dual-ship print checklist for clean VMs: [VM-DUAL-SHIP-CHECKLIST.md](../../platform/windows/wix/VM-DUAL-SHIP-CHECKLIST.md).
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ TBD VeraePrintStamp-windows-arm64-0.3.6.msi
|
|||
# Optional companion EXE (parity with prior 0.3.x bare helper uploads):
|
||||
TBD verae-print-windows-amd64-0.3.6.exe
|
||||
# See also DOWNLOADS-MANIFEST.md (human table) and VM-DUAL-SHIP-CHECKLIST.md.
|
||||
# Fill digests: platform/windows/scripts/fill-manifest-sha256.ps1 -Path <msi|setup.exe> (prints rows; does not upload).
|
||||
56cb72d8d65c5d2e1292b0a05f235ded0a267e66530229a53980887fc5de1b72 verae-print-windows-amd64-0.3.1.exe
|
||||
aa2e7f1843ccbd4d466c66e92a5460f0e3d499e6af0dcba2f93cbd49bc2012e5 verae-print-windows-amd64-0.3.2.exe
|
||||
079482b38ae3b49b268863209e309bb35072a3ec136f076f0ec5062d67a7c26e verae-print_0.1.2_amd64.deb
|
||||
|
|
|
|||
|
|
@ -8,9 +8,57 @@
|
|||
<link rel="canonical" href="https://printit.verae.ai/certificate.html"/>
|
||||
<link rel="stylesheet" href="brand/tokens.css"/>
|
||||
<link rel="stylesheet" href="verae-ui-kit.css"/>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com"/>
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,600;9..144,700&family=JetBrains+Mono:wght@500&display=swap" rel="stylesheet"/>
|
||||
<!-- Fonts: local fonts/*.woff2 first when present; else Google Fonts CDN Fraunces.
|
||||
No binaries committed — drop OFL woff2 into fonts/ (see fonts/README.md). -->
|
||||
<script>
|
||||
(function () {
|
||||
var CDN = 'https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,600;9..144,700&family=JetBrains+Mono:wght@500&display=swap';
|
||||
var CANDIDATES = [
|
||||
{ file: 'fonts/fraunces-opsz-wght-700.woff2', family: 'Fraunces', weight: '700' },
|
||||
{ file: 'fonts/fraunces-opsz-wght-600.woff2', family: 'Fraunces', weight: '600' },
|
||||
{ file: 'fonts/jetbrains-mono-500.woff2', family: 'JetBrains Mono', weight: '500' }
|
||||
];
|
||||
function isWoff2(buf) {
|
||||
var u = new Uint8Array(buf);
|
||||
return u.length >= 4 && u[0] === 0x77 && u[1] === 0x4F && u[2] === 0x46 && u[3] === 0x32;
|
||||
}
|
||||
function addCdn() {
|
||||
var p1 = document.createElement('link');
|
||||
p1.rel = 'preconnect'; p1.href = 'https://fonts.googleapis.com';
|
||||
var p2 = document.createElement('link');
|
||||
p2.rel = 'preconnect'; p2.href = 'https://fonts.gstatic.com'; p2.crossOrigin = '';
|
||||
var l = document.createElement('link');
|
||||
l.rel = 'stylesheet'; l.href = CDN;
|
||||
document.head.appendChild(p1);
|
||||
document.head.appendChild(p2);
|
||||
document.head.appendChild(l);
|
||||
}
|
||||
function addLocal(faces) {
|
||||
var css = faces.map(function (f) {
|
||||
return '@font-face{font-family:\'' + f.family + '\';src:url(\'' + f.file + '\') format(\'woff2\');' +
|
||||
'font-weight:' + f.weight + ';font-style:normal;font-display:swap}';
|
||||
}).join('\n');
|
||||
var s = document.createElement('style');
|
||||
s.setAttribute('data-cert-fonts', 'local');
|
||||
s.textContent = css;
|
||||
document.head.appendChild(s);
|
||||
}
|
||||
Promise.all(CANDIDATES.map(function (c) {
|
||||
return fetch(c.file, { headers: { Range: 'bytes=0-3' }, cache: 'force-cache' })
|
||||
.then(function (r) {
|
||||
if (!r.ok && r.status !== 206) return null;
|
||||
return r.arrayBuffer().then(function (buf) {
|
||||
return isWoff2(buf) ? c : null;
|
||||
});
|
||||
})
|
||||
.catch(function () { return null; });
|
||||
})).then(function (results) {
|
||||
var found = results.filter(Boolean);
|
||||
if (found.length) addLocal(found);
|
||||
else addCdn();
|
||||
}).catch(addCdn);
|
||||
})();
|
||||
</script>
|
||||
<style>
|
||||
body{margin:0;background:var(--canvas,#E9E6EE);color:var(--ink,#1D1534);font-family:var(--font-sans),system-ui,-apple-system,Segoe UI,sans-serif}
|
||||
.toolbar{padding:12px 20px;background:var(--card,#fff);border-bottom:1px solid var(--line,#E3DEF0);display:flex;gap:10px;align-items:center;flex-wrap:wrap}
|
||||
|
|
@ -208,9 +256,9 @@
|
|||
Query params also work:
|
||||
<span class="mono">?document=&sha256=&receipt=&created_at=&merkle=&blake3=&block=&helper_version=</span>
|
||||
Multihash / BLAKE3 lines appear <b>only when data is present</b> — never invented.
|
||||
Title uses Fraunces (Google Fonts CDN) with Georgia/serif offline fallback; plum/gold frame kept.
|
||||
Title uses Fraunces: local <code>fonts/*.woff2</code> via @font-face when present, else Google Fonts CDN; Georgia/serif offline fallback. Plum/gold frame kept.
|
||||
Final certificates paint a live QR (qrcode.js CDN → data-URL) from the explorer lookup; offline / provisional keeps the SVG placeholder so print still works.
|
||||
Residual: self-hosted Fraunces/JetBrains woff2 + full CERT-01.html pixel / PDF embed.
|
||||
Residual: commit OFL woff2 binaries; full CERT-01.html pixel match; PDF Fraunces embed.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,32 +1,88 @@
|
|||
# CERT self-host fonts (printit.verae.ai)
|
||||
|
||||
Placeholder directory for **self-hosted woff2** used by the CERT-01 web
|
||||
viewer (`../certificate.html`). Binaries are **not** committed yet — only
|
||||
`.gitkeep` keeps the path in git.
|
||||
[](https://github.com/RichardLitt/standard-readme)
|
||||
|
||||
## Current state
|
||||
Drop-in woff2 directory for the CERT-01 web viewer (`../certificate.html`).
|
||||
|
||||
`certificate.html` probes this folder at load time. If any planned `.woff2`
|
||||
validates (woff2 magic `wOF2`), it injects local `@font-face` and **skips**
|
||||
the Google Fonts CDN. If none are present, it loads CDN Fraunces + JetBrains
|
||||
Mono. Binaries are **not** committed — only `.gitkeep` keeps the path in git.
|
||||
Do **not** download or commit proprietary fonts.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Install](#install)
|
||||
- [Usage](#usage)
|
||||
- [Background](#background)
|
||||
- [Planned filenames](#planned-filenames)
|
||||
- [Fetch scaffold](#fetch-scaffold)
|
||||
- [Out of scope](#out-of-scope)
|
||||
- [Status](#status)
|
||||
- [Contributing](#contributing)
|
||||
- [License](#license)
|
||||
|
||||
## Install
|
||||
|
||||
Place OFL-licensed files next to this README (no proprietary fonts):
|
||||
|
||||
```sh
|
||||
# From this directory (site/printit.verae.ai/fonts/)
|
||||
cp /path/to/fraunces-opsz-wght-700.woff2 .
|
||||
cp /path/to/fraunces-opsz-wght-600.woff2 . # optional weight 600
|
||||
cp /path/to/jetbrains-mono-500.woff2 . # optional mono
|
||||
cp /path/to/OFL.txt . # required beside binaries
|
||||
|
||||
./fetch-fonts.example.sh --check # exit 0 when required set present
|
||||
```
|
||||
|
||||
Deploy with the static site (`rsync` to `/var/www/printit.verae.ai/` — see
|
||||
parent `README.md`). No HTML edit is required: the viewer auto-selects local
|
||||
vs CDN.
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
# No woff2 yet → certificate.html uses Google Fonts CDN Fraunces
|
||||
open ../certificate.html
|
||||
|
||||
# After drop-in → local @font-face only (CDN not requested)
|
||||
./fetch-fonts.example.sh --check && open ../certificate.html
|
||||
# Smoke offline: block fonts.googleapis.com / fonts.gstatic.com;
|
||||
# title must still render Fraunces from local woff2 (or Georgia if missing).
|
||||
```
|
||||
|
||||
How drop-in works:
|
||||
|
||||
1. Obtain **OFL-licensed** Fraunces (and optional JetBrains Mono) as woff2
|
||||
from upstream or a subsetted build (title glyphs only is enough for CERT).
|
||||
2. Name files exactly as in [Planned filenames](#planned-filenames).
|
||||
3. Commit `OFL.txt` / `LICENSE` next to the binaries (keep copyright notices).
|
||||
4. Open `certificate.html` — head script HEADs each candidate, checks woff2
|
||||
magic (avoids Caddy `try_files` HTML false-positives), injects
|
||||
`@font-face` for hits, otherwise appends the CDN `<link>`.
|
||||
5. Keep the Georgia / Times New Roman / serif stack as final fallback in CSS.
|
||||
|
||||
Do **not** uncomment network fetches in `fetch-fonts.example.sh` until license
|
||||
review. This tree must not ship proprietary font files.
|
||||
|
||||
## Background
|
||||
|
||||
| Surface | Fonts today | Offline fallback |
|
||||
|---------|-------------|------------------|
|
||||
| `certificate.html` title | **Fraunces** 600/700 via Google Fonts CDN | Georgia / Times New Roman / serif |
|
||||
| Mono digests | **JetBrains Mono** 500 via same CDN | ui-monospace / SF Mono / Menlo |
|
||||
| `certificate.html` title | Local `fonts/*.woff2` if present, else **Fraunces** CDN | Georgia / Times New Roman / serif |
|
||||
| Mono digests | Local mono woff2 if present, else **JetBrains Mono** CDN | ui-monospace / SF Mono / Menlo |
|
||||
| UI kit (`verae-ui-kit.css`) | Inter + Material Symbols Rounded CDN | system stacks in `brand/tokens.css` |
|
||||
| Issued PDF (`internal/pdfcert`) | System / library serif — **not** Fraunces embed | N/A (separate from web) |
|
||||
|
||||
Design source of truth: `verae-2026-design/ui-designs/src/html/CERT-01.html`
|
||||
(tokens `--font-serif: 'Fraunces'`; design-kit `src/fonts/` currently ships
|
||||
Cantarell + Material Symbols TTF only — **no Fraunces binary in-repo yet**).
|
||||
(tokens `--font-serif: 'Fraunces'`; design-kit `src/fonts/` ships Cantarell +
|
||||
Material Symbols TTF only — **no Fraunces binary in-repo yet**).
|
||||
|
||||
**Not claimed:** full CERT-01.html pixel match, PDF Fraunces embed, or
|
||||
self-hosted production fonts.
|
||||
production binaries in git.
|
||||
|
||||
## Goal
|
||||
|
||||
Serve brand serif (and optional mono) from this origin so the certificate
|
||||
viewer works without `fonts.googleapis.com` / `fonts.gstatic.com`, and
|
||||
print/PDF-from-browser paths stay consistent offline.
|
||||
|
||||
## Planned files (when licensed binaries land)
|
||||
## Planned filenames
|
||||
|
||||
```
|
||||
fonts/
|
||||
|
|
@ -39,53 +95,25 @@ fonts/
|
|||
OFL.txt / LICENSE # required license text beside binaries
|
||||
```
|
||||
|
||||
### Fetch scaffold (TODO-7 A7)
|
||||
Exact names must stay stable once wired so deploys and the head probe match.
|
||||
|
||||
[`fetch-fonts.example.sh`](./fetch-fonts.example.sh) — **example only**. Comment-only
|
||||
upstream URLs (google/fonts OFL trees, gstatic discovery). Does not curl until
|
||||
an operator uncomments a pinned-commit block after license review. Smoke:
|
||||
## Fetch scaffold
|
||||
|
||||
```bash
|
||||
[`fetch-fonts.example.sh`](./fetch-fonts.example.sh) — **example only**.
|
||||
Comment-only upstream URLs (google/fonts OFL trees). Does not curl until an
|
||||
operator uncomments a pinned-commit block after license review.
|
||||
|
||||
```sh
|
||||
./fetch-fonts.example.sh # prints instructions; no network
|
||||
./fetch-fonts.example.sh --check # exit 1 until woff2 + OFL.txt present
|
||||
```
|
||||
|
||||
Exact filenames may follow upstream release naming; keep them stable once
|
||||
wired so deploys and cache busting stay simple.
|
||||
|
||||
## How to wire (later — do not claim done until files exist)
|
||||
|
||||
1. Obtain **OFL-licensed** Fraunces (and optional JetBrains Mono) woff2 from
|
||||
the upstream release or a subsetted build (title glyphs only is enough
|
||||
for CERT).
|
||||
2. Drop files into this directory; commit license text next to them.
|
||||
3. Add local `@font-face` in `certificate.html` (or a small
|
||||
`fonts/cert-fonts.css`):
|
||||
|
||||
```css
|
||||
@font-face {
|
||||
font-family: 'Fraunces';
|
||||
src: url('/fonts/fraunces-opsz-wght-700.woff2') format('woff2');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
```
|
||||
|
||||
4. Remove the three Google Fonts `<link>` tags from `certificate.html`
|
||||
head once local faces load cleanly.
|
||||
5. Keep the Georgia/serif stack as final fallback.
|
||||
6. Deploy with the rest of the static site (`rsync` to
|
||||
`/var/www/printit.verae.ai/` — see parent `README.md`).
|
||||
7. Smoke: open `/certificate.html` with network blocked; title must still
|
||||
render serif (local woff2 or Georgia).
|
||||
|
||||
## Out of scope here
|
||||
## Out of scope
|
||||
|
||||
| Item | Owner / later |
|
||||
|------|----------------|
|
||||
| PDF CERT Fraunces embed | **I7 done:** pdfcert/build.mjs note + test — Times/Helvetica only until embed lands |
|
||||
| Inter / Material Symbols self-host for whole site | optional; CERT title is the residual gap called out in OPEN-ISSUES #7 |
|
||||
| Inter / Material Symbols self-host for whole site | optional; CERT title is OPEN-ISSUES #7 residual |
|
||||
| Cantarell from design-kit TTFs | GNOME mock only; not required for CERT-01 web title |
|
||||
| Pixel-perfect CERT-01.html match | Still later (OPEN-ISSUES Advanced) |
|
||||
|
||||
|
|
@ -95,7 +123,23 @@ wired so deploys and cache busting stay simple.
|
|||
|------|-------|
|
||||
| Placeholder dir + this plan | **Done** (L7) |
|
||||
| `fetch-fonts.example.sh` placeholders | **Done** (TODO-7 A7) — no binaries fetched |
|
||||
| Web cert spacing toward CERT-01 | **Closer** (title-block 26/18, pad 56×64, rule 2×120, mh 2×6, verify center) — not full pixel |
|
||||
| woff2 binaries + LICENSE | Not started |
|
||||
| `@font-face` + drop CDN links | Not started |
|
||||
| Pixel match / PDF embed claim | Not started — do not claim |
|
||||
| Web cert spacing toward CERT-01 | **Closer** — not full pixel |
|
||||
| Local-first `@font-face` else CDN | **Done** — `certificate.html` probes `fonts/*.woff2` |
|
||||
| Drop-in docs (this README) | **Done** |
|
||||
| woff2 binaries + LICENSE in git | **Not started** — operator drop-in only |
|
||||
| Pixel match / PDF embed claim | **Not started** — do not claim |
|
||||
|
||||
## Contributing
|
||||
|
||||
Questions: Verae eng / printit site owners. PRs that add **OFL** woff2 +
|
||||
`OFL.txt` with stable planned names are welcome. PRs that vendor proprietary
|
||||
fonts or strip copyright notices will be rejected. Do not enable the example
|
||||
fetch script in CI.
|
||||
|
||||
## License
|
||||
|
||||
Documentation in this directory: UNLICENSED © Verae LLC.
|
||||
|
||||
Font binaries, when added, remain under their upstream licenses (typically
|
||||
SIL Open Font License 1.1 for Fraunces and JetBrains Mono). Ship `OFL.txt`
|
||||
beside any binary. This directory does not re-license font files.
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
# block and re-run. Binaries stay uncommitted until OFL/LICENSE is beside them.
|
||||
#
|
||||
# Target dir: this script's directory (site/printit.verae.ai/fonts/).
|
||||
# Wire-up: see README.md in this folder; certificate.html still uses CDN until
|
||||
# local @font-face + woff2 land.
|
||||
# Wire-up: see README.md. certificate.html probes this dir at load time —
|
||||
# any valid planned woff2 → local @font-face; none → Google Fonts CDN.
|
||||
#
|
||||
# License reminder:
|
||||
# Fraunces — SIL Open Font License 1.1 (OFL)
|
||||
|
|
@ -92,6 +92,6 @@ echo "No downloads performed."
|
|||
echo "1. Pin a google/fonts commit or upstream release."
|
||||
echo "2. Uncomment a curl block after license review."
|
||||
echo "3. Place woff2 + OFL.txt here; run: $0 --check"
|
||||
echo "4. Add @font-face in certificate.html; drop Google Fonts <link> tags."
|
||||
echo "4. Reload certificate.html — local @font-face auto-selects; CDN skipped."
|
||||
echo
|
||||
echo "Status: placeholder only — binaries not started (MULTI-AGENT-TODO-7 A7)."
|
||||
echo "Status: drop-in ready — binaries not committed (OPEN-ISSUES #7 still left)."
|
||||
|
|
|
|||
Loading…
Reference in a new issue