# Serving the GRIP artifacts Handoff for the foxora.dev site work. Source tree: `foxora-runtime/spec/grip/`. ## The one hard requirement The schema `$id` values are **absolute and baked into the files**: ``` https://grip.foxora.dev/schema/1.0-draft.2/common.schema.json https://grip.foxora.dev/schema/1.0-draft.2/mandate.schema.json https://grip.foxora.dev/schema/1.0-draft.2/grant.schema.json https://grip.foxora.dev/schema/1.0-draft.2/receipt.schema.json https://grip.foxora.dev/schema/1.0-draft.2/stop.schema.json https://grip.foxora.dev/schema/1.0-draft.2/settlement.schema.json https://grip.foxora.dev/schema/1.0-draft.2/context.schema.json ``` **These URLs must resolve to those exact files.** Other people's validators fetch `$id` and `$ref` by URL; a 404 makes the schemas unusable outside this repo. `common.schema.json` is referenced by relative `$ref` from the other six, so all seven must sit in the same directory. ## Layout The deploy took the site root of `grip.foxora.dev`, so the paths are one level shallower than the tree here — the artifacts sit at the root and the spec's own documents sit under `/spec/`: ``` / → the GRIP sheet (index.html) /schema/1.0-draft.2/ → the 7 schemas, at the URLs their $ids name /registry/ → the 5 registry JSON files /vectors/ → 7 vector dirs, 80 signed objects /tools/ → gripcore.py, grip_verify.py, make_vectors.py /conformance/ → run.py /spec/ → README.md, this file, LICENSE, CHECKSUMS.txt /paper/ → the paper, the ALM companion, CITATION.bib ``` Version the path, never overwrite it. When `1.0` is released, publish `schema/1.0/` alongside `schema/1.0-draft.2/` and leave the draft in place forever — an `$id` that changes meaning is worse than one that 404s. ## Headers | Path | Content-Type | | --- | --- | | `*.schema.json` | `application/schema+json` | | other `*.json` | `application/json` | | `*.py` | `text/plain; charset=utf-8` (serve as source, do not download-prompt) | Enable CORS (`Access-Control-Allow-Origin: *`) on everything under the site root. Validators fetch these cross-origin; without it they fail in browsers. Cache: `max-age=31536000, immutable` on the versioned schema path — it never changes. Short cache on the site root itself. ## /.well-known/grip GRIP-0 conformance requires a trust bundle at `/.well-known/grip` (§4.7, Appendix B). Not needed to publish the spec, but if foxora.dev ever claims a conformance level, that path has to serve a real bundle. See `vectors/refund-happy-path/trust-bundle.json` for the shape. ## Published — 2026-08-24 These paths are live at the `grip.foxora.dev` site root, served from `foxora-web/sites/grip/`, and the served bytes match this tree. The versioned schema path resolves every baked `$id`. The name is now effectively fixed: `$id`s are permanent identifiers, and anyone may implement against them from here on. The **Grip Security trademark question was still recorded open** when this went live (gate (1) in the paper header) — it is no longer a pre-publication gate, it is a rename cost, and a rename means publishing a new `$id` namespace and leaving `1.0-draft.2/` served forever. ## Verifying the deploy Fetch every artifact and compare it against this tree, then run the suite on what was served rather than on what was uploaded — a rewritten line ending changes a digest, and a changed digest breaks every signature downstream of it. ``` curl -sI https://grip.foxora.dev/schema/1.0-draft.2/mandate.schema.json curl -s https://grip.foxora.dev/registry/denial-reasons.json | head -5 ``` **Verified 2026-08-24.** All 111 served artifacts are byte-identical to `spec/grip/`, and `conformance/run.py`, run against the downloaded copies, returns 7/7 — the chains verify from the public URLs, not just from disk.