feat(draft): allow fast preview on local dev hosts and the dev tunnel - #1238
Conversation
The `?__draft=` fast preview was inert during local development: it only
rendered drafts on hosts named in `previewHosts` / `DECO_ALLOWED_PREVIEW_HOSTS`
or the deco-hosted `<site>.deco.site` / `envs-<site>--<hash>.decocdn.com`
domains. But `deno task start` serves on `localhost:<port>` and on the
per-developer dev tunnel `<env>--<site>.deco.{host,site}` (daemon/tunnel.ts),
so a draft never previewed locally without extra config.
Now local dev hosts (`localhost`, `127.0.0.1`, `*.localhost`, any port) are
always allowed, and the dev tunnel is inferred from the resolved site name with
its `<env>` label pinned to a single DNS label — the same anti-widening
constraint as the per-deploy `<hash>`. `DECO_ALLOWED_PREVIEW_HOSTS=none` still
kills everything, local and tunnel included. The signed `?__draft=` grant
remains the actual capability; host-scoping only bounds blast radius.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tagging OptionsShould a new tag be published when this PR is merged?
|
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 4 included reviews per hour; 2 remain after this review. 📝 WalkthroughWalkthroughDraft preview is enabled for local development by default. Local hosts and valid per-developer ChangesDraft preview gating
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Feature Sequence Diagram(s)sequenceDiagram
participant Request
participant resolveDraftForRequest
participant isDraftPreviewEnabled
participant isDraftHostAllowed
Request->>resolveDraftForRequest: provide request host
resolveDraftForRequest->>isDraftPreviewEnabled: check preview enablement
isDraftPreviewEnabled-->>resolveDraftForRequest: return enabled or disabled
resolveDraftForRequest->>isDraftHostAllowed: validate request host
isDraftHostAllowed-->>resolveDraftForRequest: return allowed or rejected
resolveDraftForRequest-->>Request: resolve draft or deny access
Merge Risk: ⚪ Minimal · up to Draft previews support local development and valid dev tunnels while preserving production-domain protection and the global kill switch. The change is ready to merge with normal checks. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
All reported issues were addressed across 2 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
…loopback Two issues from PR review: 1. The dev-tunnel match no longer accepts the `<env>--<site>.deco.site` simpletunnel fallback: `.deco.site` is also the stable production apex, so matching it widened the draft gate on production, not just dev machines. Only `<env>--<site>.deco.host` (the `DECO_HOST` default) is matched now; the rare `DECO_HOST=false` opt-out previews via localhost or an explicit allowlist. 2. `isLocalDevHost` now treats the IPv6 loopback as local — `::1`, `[::1]`, and `[::1]:port` — which the port-splitting previously mangled to a non-match. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Both cubic findings were valid — fixed in ebb6704: 1. 2. IPv6 loopback not matched (P3) — |
Problem
The
?__draft=fast preview was inert during local development.isDraftHostAllowedonly rendered drafts on:previewHostsorDECO_ALLOWED_PREVIEW_HOSTS<site>.deco.site(exact) andenvs-<site>--<hash>.decocdn.com(per-deploy) domainsBut
deno task startserves the local app onlocalhost:<port>and on the per-developer dev tunnel<env>--<site>.deco.{host,site}(seedaemon/tunnel.ts) — e.g.tavano--farmrio.deco.host. Neither matched, so a draft never previewed locally without extra config.Change
engine/decofile/draft.ts:localhost,127.0.0.1,*.localhost, with any port (isLocalDevHost).matchesDevTunnelmatches<env>--<site>.deco.host(thedecoHosttunnel) and<env>--<site>.deco.site(the simpletunnel fallback). The<env>label is pinned to a single DNS label, the same anti-widening constraint as the per-deploy<hash>, so nothing likex.evil--<site>.deco.hostcan widen the match.previewConfignow surfaceslocalAllowedand the resolvedsite; the early network-touch guards useisDraftPreviewEnabledinstead of an empty-allowlist check.DECO_ALLOWED_PREVIEW_HOSTS=nonedisables everything, local and tunnel included.Security
The signed
?__draft=grant remains the actual capability; host-scoping only bounds blast radius. Loopback hosts are only reachable on the dev machine. The tunnel/local match slightly widens the direct-to-origin surface (an attacker with a valid signed grant spoofingx-forwarded-host: localhost), consistent with the threat model already documented in the module.nonekills it without a deploy.Note
The
?__draft=feature lives in the current@deco/decoline; a site on an older version (e.g.1.202.1) picks up this behavior only after bumping the package.Tests
Updated
engine/decofile/draft.test.ts: the old "local requires config" assertions became "local always allowed"; new coverage for arbitrary ports, look-alike non-loopback hosts (localhost.evil.example,notlocalhost), the dev tunnel (both apexes, single-label enforcement, wrong site/apex), and the kill switch disabling local + tunnel. All passing.🤖 Generated with Claude Code
Summary by cubic
Makes the
?__draft=fast preview work out of the box during local development, sodeno task startcan render drafts without extra config.localhost,127.0.0.1,*.localhost, and the IPv6 loopback (::1/[::1], any port) now always allow drafts.<env>--<site>.deco.hostis inferred from the site name, with the<env>label pinned to a single DNS label to prevent widening; the.deco.sitetunnel fallback is deliberately not matched since it shares an apex with the production domain.DECO_ALLOWED_PREVIEW_HOSTS=nonestill disables everything, including local hosts and the tunnel.@deco/decoversions pick up the change only after bumping the package.Written for commit ebb6704. Summary will update on new commits.
Summary by CodeRabbit
New Features
<env>--<site>.deco.hostformat can access draft previews.Configuration
DECO_ALLOWED_PREVIEW_HOSTS=noneto disable draft previews, including local access.