Public Forge web API¶
The marketing explorer uses a deliberately narrow, read-only Forge surface. It is separate from the authenticated app API and may return only server-authorized, ciphertext-safe projections.
Routes¶
Every route is a GET below /public/v1 and answers application/json, except the one asset route
noted in the table. {org}/{repo} is the published alias described below. The only query parameters the
edge forwards to a projection are ref, path, base, head, state, after, and limit — every
other parameter is dropped rather than passed through, so an unrecognized one can never become an
unreviewed selector.
| Route | Projection |
|---|---|
/repositories |
The published catalog, filtered live by visibility |
/discovery |
The cross-repository aggregate the explorer's landing view uses |
/repositories/{org}/{repo} |
Public repository identity and summary |
/repositories/{org}/{repo}/snapshot |
Repository summary, recent changes, and proposals |
/repositories/{org}/{repo}/tree?ref=&path= |
Public tree entries |
/repositories/{org}/{repo}/blob?ref=&path= |
One clear file's contents |
/repositories/{org}/{repo}/blame?ref=&path= |
Per-line attribution for a clear file |
/repositories/{org}/{repo}/changes?ref= |
Public change summaries |
/repositories/{org}/{repo}/changes/{id} |
One public change |
/repositories/{org}/{repo}/changes/{id}/diff |
One change's diff |
/repositories/{org}/{repo}/compare?base=&head= |
The file-level comparison of two refs |
/repositories/{org}/{repo}/conflicts?ref= |
Open conflict summaries |
/repositories/{org}/{repo}/conflict?ref=&path= |
One conflict, with its clear sides |
/repositories/{org}/{repo}/lanes, /tags, /policies |
Lanes, tags, and the policy shapes |
/repositories/{org}/{repo}/proposals?after=&limit= |
Public proposal summaries |
/repositories/{org}/{repo}/proposals/{id} |
One public proposal |
/repositories/{org}/{repo}/insights |
The repository's aggregate activity view |
/repositories/{org}/{repo}/releases… |
Published releases (list, latest, one by id) |
/repositories/{org}/{repo}/releases/{id}/assets/{name} |
The asset bytes — the one route that is not JSON |
/repositories/{org}/{repo}/issues… |
Issues, one issue, and one issue's comments |
The exact response types live in the shared tovio-forge-domain::public_read module; this surface does
not introduce a second repository domain model. The edge derives them from verified commits, trees,
refs, and proposal records.
No protected content, ever. A policy-protected path never has its plaintext rendered here under any operation: it appears as metadata with its protection marker in a tree, and is excluded from the content-bearing shapes (blob, diff, blame, conflict). The edge holds no recipient key and does not decrypt — there is no caller to unseal for. A projection also omits account, membership, organization-administration, audit, billing, authentication, private-key, recipient-key, capability-chain, and mutation data.
This surface is read-only. /public/v1 exposes no mutation of any kind — writes reach the Forge only
through the authenticated app API, never from the marketing origin.
A deployment publishes nothing by default. A repository is reachable only when it has an exact alias in
PUBLIC_REPOSITORY_CATALOG and its live Forge repository marker remains public.
Browser boundary¶
- Allow CORS from exactly
https://tovio.devfor theseGETroutes. - Allow the authenticated API from exactly
https://app.tovio.dev; do not grant the marketing origin mutation methods or credentialed requests. - Reject redirects and non-JSON responses. Bound each response before parsing.
- Return an explicit unavailable/error response when the Forge cannot serve the projection. The website must never substitute demonstration data that looks live.
The Astro implementation enforces HTTPS outside loopback, omits credentials, accepts only GET, and caps
responses at 1 MiB. Authorization and disclosure decisions remain server responsibilities.
Last reviewed September 9, 2026
Suggest an improvement to this page Not for security reports — see disclosure