Context
Supersedes #9, which was closed as completed although no snippet endpoint exists. Sharing today is lib/shareState.ts: the whole snippet, engine selection and flag map are base64url-encoded into the s query parameter. A long snippet produces a URL that messengers and Twitter mangle, and there is no way to revoke, update, or count a share.
Redis is already wired into the gateway for cache and rate limiting.
Proposal
POST /api/snippets — store {code, engines, flags} in Redis under a short id, return {id, url}. Rate-limited on the general bucket, size-capped at MAX_SOURCE_LENGTH.
GET /api/snippets/:id — fetch; 404 after expiry.
- Public page
/s/:id that restores playground state, with the existing base64 links kept working forever (they need no server).
- TTL by default, with an explicit "keep" that pins an entry; document the retention rule in SECURITY.md since this is the first user-submitted content the service stores.
Acceptance criteria
- A share link for a 20k-character snippet is under 64 characters.
- Old
?s= links still open.
- An expired id returns a clear message, not a broken playground.
Context
Supersedes #9, which was closed as completed although no snippet endpoint exists. Sharing today is
lib/shareState.ts: the whole snippet, engine selection and flag map are base64url-encoded into thesquery parameter. A long snippet produces a URL that messengers and Twitter mangle, and there is no way to revoke, update, or count a share.Redis is already wired into the gateway for cache and rate limiting.
Proposal
POST /api/snippets— store{code, engines, flags}in Redis under a short id, return{id, url}. Rate-limited on the general bucket, size-capped atMAX_SOURCE_LENGTH.GET /api/snippets/:id— fetch; 404 after expiry./s/:idthat restores playground state, with the existing base64 links kept working forever (they need no server).Acceptance criteria
?s=links still open.