diff --git a/README.md b/README.md index d3a80ce..32bfc22 100644 --- a/README.md +++ b/README.md @@ -59,15 +59,22 @@ The repo includes Playwright visual snapshots for the shipped viewer surfaces: - Fully static export with Next.js App Router (default product) - Fragment-based payloads (`#...`) so the static host never receives artifact contents - Public-safe naming and MIT-compatible dependencies -- Optional self-hosted mode for server-backed UUID links (see below) +- Optional self-hosted mode for public/share-friendly UUID links (see below) + +## Sharing Guidance + +Use fragment links for trusted direct sharing when the artifact fits the URL budget and you want the static host kept out of the payload path. + +Use UUID links for public, social, or corporate-proxy sharing when a short stable URL matters more than static zero-retention. UUID mode stores the payload server-side until it expires or is deleted, so treat the server as part of the sharing boundary. ## Self-Hosted UUID Mode (Optional) -In addition to the default static/fragment-based product, `agent-render` includes an optional self-hosted server mode that stores payloads in SQLite under UUID keys. +In addition to the default static/fragment-based product, `agent-render` includes an optional self-hosted server mode that stores payloads in SQLite under UUID keys. It is the recommended mode for public sharing contexts where long fragment links look risky, get truncated, or pass through URL-rewriting infrastructure. **When to use it:** - Payloads exceed the ~8 KB fragment budget - Links are shared on platforms that mangle long URLs +- Links are posted publicly, sent to broad groups, or routed through corporate proxy/link-scanning systems - You want short, stable links like `https://host/{uuid}` - Agent-driven workflows that create and manage artifacts programmatically @@ -92,6 +99,8 @@ See `skills/selfhosted-agent-render/SKILL.md` for agent workflow guidance. The self-hosted mode is an add-on. The existing static fragment-based viewer remains the default product and continues to work as-is. +UUID links are not zero-retention in the current implementation because the server stores the encoded payload. A future encrypted short-link design could store only ciphertext server-side while keeping the decryption key in the URL fragment, but that is not implemented yet. + ## Local Development ```bash diff --git a/docs/architecture.md b/docs/architecture.md index 5b38cb1..736ac3e 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -112,6 +112,8 @@ The static host does not receive fragment contents as part of the request, but t - client-side analytics would still be able to observe decoded payloads if added later - very large artifacts can exceed practical URL-sharing limits, which is why the shell enforces a fragment budget +Fragment links are best for trusted direct sharing where the URL length is acceptable and the static host should stay out of the payload path. They are not ideal for public feeds, broad corporate sharing, or chat systems that rewrite/truncate long URLs. + ## Routing and hosting constraints - `output: "export"` @@ -123,6 +125,8 @@ The static host does not receive fragment contents as part of the request, but t The repository includes an optional self-hosted server mode in `selfhosted/` that provides UUID-based artifact links backed by SQLite. This is a separate deployment mode — the static export remains the default product. +UUID mode is the public/share-friendly option. It trades static zero-retention for short stable links that survive public posts, email, Slack/Teams, and corporate proxy/link-scanning systems more predictably than long fragments. + ### How it works The self-hosted server is a standalone Node.js HTTP server that: @@ -146,6 +150,8 @@ SQLite with a single `artifacts` table: Artifacts use a 24-hour sliding TTL. Each successful read (API or viewer) extends `expires_at` by 24 hours. Expired entries are lazily deleted on read and can also be batch-cleaned via `POST /api/cleanup`. +UUID mode should not be described as zero-retention in its current form. The server stores the encoded payload until expiry or deletion. A future encrypted short-link mode could store ciphertext in SQLite while keeping the decryption key in the URL fragment, but that design is not implemented. + ### Separation from static mode The self-hosted mode does not alter the static export pipeline: diff --git a/docs/deployment.md b/docs/deployment.md index 258badb..c1a80a5 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -53,7 +53,14 @@ If you deploy at the domain root on Cloudflare Pages, leave `NEXT_PUBLIC_BASE_PA ## Self-hosted UUID mode (optional) -The repository includes an optional self-hosted server that stores artifact payloads in SQLite and serves them under UUID links. This is a separate deployment from the static export and is intended for power users and agents. +The repository includes an optional self-hosted server that stores artifact payloads in SQLite and serves them under UUID links. This is a separate deployment from the static export and is intended for power users, agents, and public sharing contexts where short stable URLs work better than long fragments. + +Choose the sharing mode by audience: + +- **Fragment links**: best for trusted direct sharing when the payload fits the fragment budget and static zero-retention matters. +- **UUID links**: best for public, social, email, Slack/Teams, or corporate-proxy contexts where long fragment URLs look suspicious, get truncated, or are rewritten. + +Current UUID links are server-retained: the server stores the encoded payload until the TTL expires or the artifact is deleted. Do not describe UUID mode as zero-retention unless an encrypted short-link design is implemented. ### Quick start @@ -133,11 +140,15 @@ Artifacts have a 24-hour sliding TTL. Each successful view extends the expiry. E The self-hosted server does not include built-in authentication. Options for protecting it: -- **Public**: No additional configuration. Fine for non-sensitive artifacts. +- **Public**: No additional configuration. Recommended for public/non-sensitive artifacts that benefit from short share-friendly links. - **Cloudflare Tunnel + Zero Trust**: Expose the server through a Cloudflare Tunnel and add Access policies for authentication. This is the recommended approach for remote access with SSO. - **Reverse proxy**: Place behind nginx, Caddy, or Traefik with HTTP basic auth, OAuth2 proxy, or mTLS. - **Local only**: Set `HOST=127.0.0.1` to bind to localhost only. +### Future encrypted short links + +A future mode could encrypt the payload in the browser or agent, store only ciphertext under the UUID, and keep the decryption key in the URL fragment. That would make the short-link server unable to read plaintext while still giving users a short public URL shape. This repository does not implement that mode today. + ### Same-machine deployment The simplest pattern is running the server on the same machine as the agent. The agent creates artifacts via `http://localhost:3000/api/artifacts` and returns viewer links. No network exposure required unless you want remote access. diff --git a/docs/payload-format.md b/docs/payload-format.md index d96db6a..e4ec47f 100644 --- a/docs/payload-format.md +++ b/docs/payload-format.md @@ -26,6 +26,8 @@ Supported codecs: The encoder now also supports a packed wire representation (`p: 1`) that shortens key names before compression. Packed mode is transport-only; decoded envelopes normalize back to the standard shape. +Fragment payloads are the trusted direct-sharing transport. For public posts, broad group sharing, social surfaces, or corporate proxy/link-scanning environments, prefer self-hosted UUID links so the visible URL is short and stable. + ## Envelope ```json @@ -102,6 +104,8 @@ Tuple fields: - Default async codec priority is `arx2 -> arx -> deflate -> lz -> plain` - Optional budget-aware encoding can target strict limits like 1,500 chars and returns the shortest fragment when none fit +When a payload does not fit the fragment budget or the target surface is hostile to long URLs, use UUID mode instead of weakening the fragment protocol. Current UUID mode stores the encoded payload server-side and is not zero-retention. + ### Codec benchmark Running `npm run bench:codecs` checks a fixed corpus across markdown, code, diff, CSV, JSON, and multi-artifact bundles. The current committed baseline shows: diff --git a/skills/agent-render-linking/SKILL.md b/skills/agent-render-linking/SKILL.md index 75670ae..98f7264 100644 --- a/skills/agent-render-linking/SKILL.md +++ b/skills/agent-render-linking/SKILL.md @@ -320,7 +320,11 @@ When sharing a link: ## Self-hosted UUID mode -If the payload exceeds the fragment budget or links are getting mangled by chat platforms, consider using the self-hosted UUID mode instead of fragment links. The self-hosted server stores payloads in SQLite and serves short `https://host/{uuid}` links that render the same viewer UI. +Use fragment links for trusted direct sharing when the payload fits the budget and static zero-retention matters. + +Use self-hosted UUID mode for public/social sharing, broad Slack/Teams/email distribution, corporate proxy/link-scanning environments, payloads that exceed the fragment budget, or any surface that mangles long URLs. The self-hosted server stores payloads in SQLite and serves short `https://host/{uuid}` links that render the same viewer UI. + +Current UUID mode is not zero-retention because the server stores the encoded payload until TTL expiry or deletion. Do not claim zero-retention for UUID links unless an encrypted short-link mode exists where the server stores ciphertext and the key stays in the fragment. See `skills/selfhosted-agent-render/SKILL.md` for API usage, deployment, and agent workflow guidance. diff --git a/skills/selfhosted-agent-render/SKILL.md b/skills/selfhosted-agent-render/SKILL.md index bb7b898..4a5372e 100644 --- a/skills/selfhosted-agent-render/SKILL.md +++ b/skills/selfhosted-agent-render/SKILL.md @@ -1,6 +1,6 @@ --- name: selfhosted-agent-render -description: Create and manage agent-render artifacts via a self-hosted UUID-based server. Use when an agent needs to share rendered artifacts through short UUID links instead of fragment-encoded URLs. Ideal when payloads exceed the ~8 KB fragment budget, when links will be shared on platforms that mangle long URLs, or when the agent and viewer run on the same machine. Supports markdown, code, diffs, CSV, and JSON — same artifact kinds and envelope validation as the fragment-based product. The self-hosted server stores payloads in SQLite with a 24-hour sliding TTL. +description: Create and manage agent-render artifacts via a self-hosted UUID-based server. Use when an agent needs public/share-friendly rendered artifacts through short UUID links instead of fragment-encoded URLs. Ideal for public/social sharing, corporate proxy/link-scanning environments, payloads that exceed the ~8 KB fragment budget, platforms that mangle long URLs, or when the agent and viewer run on the same machine. Supports markdown, code, diffs, CSV, and JSON — same artifact kinds and envelope validation as the fragment-based product. The self-hosted server stores payloads in SQLite with a 24-hour sliding TTL. --- # Self-Hosted Agent Render @@ -11,13 +11,17 @@ Create, view, and manage agent-render artifacts through a self-hosted server tha Use self-hosted UUID mode instead of fragment links when: +- Links will be posted publicly or shared with a broad audience +- Links will pass through corporate proxy, link-scanning, or URL-rewriting systems - The artifact payload exceeds the ~8,192 character fragment budget - Links will be shared on platforms that truncate or mangle long URLs (Slack, Teams, email) - The agent and viewer run on the same machine or local network - You want stable, short links that do not encode the payload in the URL - You need to update or delete artifacts after creation -If the payload fits in a fragment and the link will work on the target surface, prefer fragment-based links using the `agent-render-linking` skill instead. Fragment links are zero-retention, require no server, and work on the public `agent-render.com` deployment. +If the payload fits in a fragment and the link is going to trusted direct recipients, prefer fragment-based links using the `agent-render-linking` skill instead. Fragment links are zero-retention by static-host design, require no server, and work on the public `agent-render.com` deployment. + +Do not describe current UUID links as zero-retention. The self-hosted server stores the encoded payload until TTL expiry or deletion. ## API @@ -316,7 +320,7 @@ Options for protecting the server: ### Public access -If you want the server to be publicly accessible, no additional configuration is needed. This is fine for non-sensitive artifacts. +If you want the server to be publicly accessible, no additional configuration is needed. This is the recommended setup for non-sensitive artifacts that need short, share-friendly public URLs. ### Cloudflare Tunnel + Zero Trust (recommended for remote access) @@ -366,8 +370,12 @@ Artifacts auto-expire after 24 hours of inactivity. For proactive cleanup: ## Good defaults -- Use self-hosted mode for large payloads or agent-driven workflows -- Use fragment links for quick, one-off shares that fit in the budget +- Use self-hosted mode for public sharing, large payloads, corporate-proxy contexts, or agent-driven workflows +- Use fragment links for quick, trusted direct shares that fit in the budget - Keep the server on the same machine as the agent for simplicity - Use Cloudflare Tunnel if you need remote access with authentication - Let TTL handle cleanup for most cases + +## Future encrypted short-link mode + +A future design could encrypt the payload before upload, store only ciphertext in SQLite, and keep the decryption key in the URL fragment. That would preserve the short UUID path while preventing the server from reading plaintext. This skill must not assume that mode exists until the implementation ships.