Presto Registry Architecture
The template registry is the distribution platform for the Presto template ecosystem, using a static JSON + CDN architecture -- no backend servers, no databases. All data is generated as static files during CI and distributed to global edge nodes via Cloudflare Pages.
System Overview
The entire system is powered by two repositories working together:
| Repository | Responsibility | Runtime Environment |
|---|---|---|
template-registry | Data collection, processing, builds | GitHub Actions |
registry-deploy | Static hosting, CDN distribution | Cloudflare Pages |
template-registry handles the "heavy lifting" -- searching templates, downloading binaries, extracting metadata, compiling preview images, and generating indexes. registry-deploy does just one thing: hosts static files as-is on the CDN, with the root directory serving as the deployment content, requiring no build steps.
Data Formats
registry.json v2 Schema
The core artifact of the registry is registry.json, at version 2. Clients obtain all template metadata and download URLs through this single file.
{
"version": 2,
"updatedAt": "2026-02-25T06:56:46Z",
"templates": [
{
"name": "gongwen",
"displayName": "Official Document Template",
"description": "Official document typesetting conforming to GB/T 9704-2012 standard",
"version": "1.0.0",
"author": "Presto-io",
"repo": "Presto-io/presto-official-templates",
"license": "MIT",
"category": "Official Document",
"keywords": ["official document", "notice", "report"],
"trust": "official",
"platforms": {
"darwin-arm64": {
"url": "https://github.com/.../presto-template-gongwen-darwin-arm64",
"sha256": "205aaa..."
}
},
"minPrestoVersion": "0.1.0",
"requiredFonts": [{ "name": "FZXiaoBiaoSong-B05", "displayName": "FangZheng XiaoBiaoSong" }],
"previewImages": ["gongwen/preview-1.svg"]
}
]
}Complete field reference:
| Field | Type | Description |
|---|---|---|
version | int | Schema version, currently fixed at 2 |
updatedAt | string | ISO 8601 UTC timestamp |
templates[].name | string | Unique template identifier, [a-z0-9-]+ |
templates[].displayName | string | Human-readable name |
templates[].trust | string | Trust level (see below) |
templates[].platforms | object | Platform to download URL + SHA256 mapping |
templates[].requiredFonts | array | Required font list |
templates[].previewImages | array | Relative paths to preview images on CDN |
manifest.json Schema
The metadata file embedded in each template, exported via the --manifest flag of the template protocol. See the binary protocol documentation for detailed field definitions.
Trust Levels
Trust levels determine how the client handles each template:
| Level | Determination Rule | Meaning |
|---|---|---|
official | repo.owner === "Presto-io" | Officially maintained, CI directly extracts |
verified | Listed in verified-templates.json and compiled | Third-party source, officially sandbox-compiled |
community | All other templates | Community published, binaries not executed |
unrecorded | Not in the registry | Locally installed by client, not registered |
Current status: 2 official templates (gongwen, jiaoan-shicao), verified list is empty (verified-templates.json is []), no community templates yet.
Platform Matrix
Each template supports up to 6 platform combinations:
| OS | arm64 | amd64 |
|---|---|---|
| darwin (macOS) | darwin-arm64 | darwin-amd64 |
| linux | linux-arm64 | linux-amd64 |
| windows | windows-arm64 | windows-amd64 |
Binary naming convention: presto-template-{name}-{os}-{arch}[.exe]
CI Pipeline Architecture
Main Flow: update-registry.yml
Triggered daily at UTC 08:00 by schedule, also supports manual triggering (with optional force_rebuild). The core design uses dual-job security isolation -- extract runs untrusted code in a low-privilege environment, while compile-and-deploy handles trusted data in a high-privilege environment.
Job 1 (extract) permissions and environment:
- Runs on
ubuntu-latest(GitHub-hosted runner) - Permissions:
contents: read-- read-only, cannot push code - Executes untrusted template binaries (official templates), protected by
safe_run()sandbox - Artifacts passed to Job 2 via
upload-artifact
Job 2 (compile-and-deploy) permissions and environment:
- Runs on
self-hosted, macOS, ARM64 - Permissions:
contents: write-- can push code - Uses
PRESTO_PATfor cross-repo push toregistry-deploy - Only processes static files produced by Job 1, does not execute any binaries
This isolation ensures: even if a template binary is malicious, it cannot obtain write permissions or access the PAT.
Verified Template Compilation: build-verified.yml
Triggered when verified-templates.json changes and is pushed to main. Also uses the dual-job architecture:
- Job 1 (build): Clone third-party source -> Docker sandbox cross-compilation for 6 platforms -> upload to
template-registryGitHub Release - Job 2 (compile-and-deploy): Same as the main flow, compiles SVG and deploys
Docker sandbox compilation security constraints:
CGO_ENABLED=0: Pure static linking, no C dependencies--network none: Network disabled during compilation--read-only+tmpfs /tmp: Read-only filesystem- Memory limit 2GB, CPU limit 2 cores
- 5-minute timeout, 50MB artifact size limit
Version Detection Automation: check-versions.yml
Runs daily at UTC 08:30 by schedule (offset 30 minutes from the main flow), checks whether templates in verified-templates.json have new version releases:
This forms a semi-automated pipeline: version detection is automated, but compilation requires manual review of the PR before triggering, maintaining human-in-the-loop security control.
Build Script Overview
scripts/build_registry.py provides 5 subcommands, executed in pipeline order:
| Subcommand | Function | Input | Output |
|---|---|---|---|
discover | Search GitHub topics + official repos | GitHub API | discovered.json |
extract | Download binaries, extract metadata | discovered.json | output/{name}/ |
build | Docker sandbox compile verified templates | verified-templates.json | GitHub Release |
compile | Typst CLI compile SVG previews | output/{name}/output.typ | output/deploy/ |
index | Aggregate and generate registry.json v2 | output/deploy/ | registry.json |
Processing differences between official and community templates:
| Step | Official Templates | Community Templates |
|---|---|---|
| Metadata | Download binary, execute --manifest | Read manifest.json from GitHub API |
| Example Document | Execute --example to export | Not retrieved |
| Typst Source | Pipeline conversion stdin -> binary -> stdout | Not generated |
| SVG Preview | Typst CLI compilation | No preview |
| Binary Execution | Yes (sandboxed) | No |
Security measures summary:
safe_run(): Sanitizes environment variables (keeps onlyPATH), 30-second timeout- Uses
unshare --neton Linux to isolate network, preventing binaries from exfiltrating data - Size limits: manifest < 1MB, example < 1MB, typst < 10MB
- SHA256 verification: Downloaded binaries compared against
SHA256SUMSfrom the Release
CDN Deployment
registry-deploy Repository Structure
registry-deploy/
_headers <- Cloudflare Pages custom headers
_redirects <- Redirect rules
templates/
registry.json <- Template index
gongwen/
manifest.json
README.md
example.md
preview-1.svg, preview-2.svg
hero-frame-0.svg, hero-frame-1.svg, hero-frame-2.svg
jiaoan-shicao/
manifest.json, README.md, example.md, preview-*.svg
plugins/ <- Future: plugin registry
agent-skills/ <- Future: Agent skill registryURL Mapping
The repository root directory maps directly to the CDN root path:
| CDN URL | Corresponding File |
|---|---|
https://presto.c-1o.top/templates/registry.json | templates/registry.json |
https://presto.c-1o.top/templates/gongwen/preview-1.svg | templates/gongwen/preview-1.svg |
https://presto.c-1o.top/templates/gongwen/manifest.json | templates/gongwen/manifest.json |
Caching Strategy
Cache behavior configured for Cloudflare Pages via the _headers file:
| Resource Type | Browser Cache | CDN Cache | Design Intent |
|---|---|---|---|
*.json | 60 seconds | 5 minutes | Index data needs faster updates |
*.svg | 1 hour | 24 hours | Preview images change infrequently |
*.md | 5 minutes | 1 hour | README and other text content |
| Other | 5 minutes | 1 hour | Default policy |
All responses include Access-Control-Allow-Origin: * (CORS fully open) and X-Content-Type-Options: nosniff.
End-to-End Flow
The complete pipeline from template developer publishing to user consumption:
Client Side: registry.go Caching Mechanism
The Presto client (internal/template/registry.go) implements a three-tier fallback strategy for registry access:
- In-memory cache:
registryCachestruct protected bysync.RWMutex - Disk cache:
registry-cache.jsonfile, TTL of 1 hour - CDN fetch:
https://presto.c-1o.top/templates/registry.json
Fallback logic: memory hit -> disk hit and not expired -> CDN fetch -> return expired disk cache if CDN fails -> return nil if all fail.
Security constraints:
- Response body size limit 10MB (
io.LimitReader, SEC-13) - Request timeout 15 seconds
- Redirect verification: only allows redirects to
presto.c-1o.topand known download domains (SEC-46) - Cache file permissions
0600(SEC-45)
Client-provided query interfaces:
VerifySHA256(name, hash): Verify that a local binary matches the registryLookupTrust(name): Query the trust level of a templateLookupByRepo(ownerRepo): Look up a template by repository name (SEC-39, server uses this to get trusted download URLs)
Security Model
Trust Chain
Dual-Job Permission Isolation
This is the cornerstone of the entire security model. Core principle: the environment executing untrusted code never holds write permissions or sensitive credentials.
| Dimension | Job 1 (extract/build) | Job 2 (compile-and-deploy) |
|---|---|---|
| Runner | GitHub-hosted Ubuntu | Self-hosted macOS ARM64 |
| Permissions | contents: read | contents: write |
| PAT | None | PRESTO_PAT |
| Binary Execution | Yes | No |
| Network Isolation | unshare --net | Not needed (no binary execution) |
| Data Transfer | upload-artifact | download-artifact |
Docker Sandbox Compilation (Verified Templates)
The compilation flow for verified templates has two phases, with network permissions switching between them:
- Dependency download phase:
go mod download, network allowed - Compilation phase:
go build,--network nonedisables network
This ensures the compilation phase cannot exfiltrate source code or secrets.
Security Boundary for Community Templates
Community template binaries are compiled and published by third parties; the registry does not execute these binaries. CI only reads manifest.json and README.md via the GitHub API -- it does not download or run any executable files. When users install community templates, the client displays a trust level warning.
