feat: admin tunnel — connect local dev to admin.deco.cx#79
Open
JonasJesus42 wants to merge 4 commits intomainfrom
Open
feat: admin tunnel — connect local dev to admin.deco.cx#79JonasJesus42 wants to merge 4 commits intomainfrom
JonasJesus42 wants to merge 4 commits intomainfrom
Conversation
Adds a daemon layer to the Vite dev server that exposes the local environment to admin.deco.cx through a reverse WebSocket tunnel (@deco-cx/warp-node). When DECO_SITE_NAME is set, the plugin registers with deco.host and serves daemon APIs for file editing, JSON patching, and real-time change broadcasting. New modules in src/daemon/: - tunnel.ts: warp-node connect() with auto-reconnect - auth.ts: JWT verification via Web Crypto (admin.deco.cx public key) - volumes.ts: file CRUD + JSON patch + WebSocket realtime broadcast - watch.ts: SSE endpoint for file change events - middleware.ts: x-daemon-api header interception + auth + routing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
7 issues found across 9 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/daemon/tunnel.ts">
<violation number="1" location="src/daemon/tunnel.ts:41">
P0: Remove the hardcoded tunnel token fallback; require `DECO_TUNNEL_SERVER_TOKEN` from environment.</violation>
<violation number="2" location="src/daemon/tunnel.ts:118">
P1: `close()` does not actually close the active tunnel connection; it only disables reconnect logic.</violation>
</file>
<file name="src/daemon/auth.ts">
<violation number="1" location="src/daemon/auth.ts:121">
P2: Missing bounds check: if `urnParts` has fewer colon-separated segments than `resourceParts`, accessing `urnParts[idx].split("/")` at the last index throws a `TypeError`. Add a length guard to return `false` instead of crashing.</violation>
</file>
<file name="src/daemon/middleware.ts">
<violation number="1" location="src/daemon/middleware.ts:99">
P1: Root SSE daemon requests with query params are misrouted because watch routing compares the full URL string instead of pathname.</violation>
</file>
<file name="src/daemon/volumes.ts">
<violation number="1" location="src/daemon/volumes.ts:152">
P0: Path traversal vulnerability: `filePath` from the URL is joined with `cwd` without verifying the resolved path stays within the project root. A path like `/../../../etc/passwd` would escape the project directory, allowing reads of arbitrary files on the host.
Resolve the path and validate it's a child of `cwd` before any filesystem access.</violation>
<violation number="2" location="src/daemon/volumes.ts:215">
P1: Premature write breaks the atomicity guarantee. The `isTextFileSet` branch writes the file to disk immediately, but the "atomic" commit block later only writes if *all* patches succeed. If a subsequent patch fails, these early writes persist on disk — defeating the stated atomicity.
Remove the `ensureFile`/`writeFile` calls from this branch and let the atomic section handle all writes.</violation>
</file>
<file name="src/daemon/watch.ts">
<violation number="1" location="src/daemon/watch.ts:94">
P2: Initial SSE scan incorrectly skips non-JSON `.deco` files, causing incomplete first sync.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| }; | ||
|
|
||
| const localAddr = `http://localhost:${port}`; | ||
| const apiKey = |
There was a problem hiding this comment.
P0: Remove the hardcoded tunnel token fallback; require DECO_TUNNEL_SERVER_TOKEN from environment.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/daemon/tunnel.ts, line 41:
<comment>Remove the hardcoded tunnel token fallback; require `DECO_TUNNEL_SERVER_TOKEN` from environment.</comment>
<file context>
@@ -0,0 +1,122 @@
+ };
+
+ const localAddr = `http://localhost:${port}`;
+ const apiKey =
+ process.env.DECO_TUNNEL_SERVER_TOKEN ??
+ "c309424a-2dc4-46fe-bfc7-a7c10df59477";
</file context>
- auth: add bounds check in URN matches() to prevent undefined access
- volumes: add safePath() to prevent path traversal attacks
- volumes: defer TextFileSet writes to atomic commit section
- middleware: use parsed pathname for route matching instead of raw URL
- tunnel: track activeConn for proper close() cleanup
- watch: inferMetadata returns { kind: "file" } for non-JSON files instead of null
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tadata - Add /fs/file/* REST API (GET/PATCH/DELETE) matching Deno daemon protocol - Enrich fs-sync SSE metadata with blockType, __resolveType, name, path - Auto-register commerce loaders (131) and actions (24) in admin schema - Fix module isolation: /live/_meta falls through to Vite SSR - Fetch meta-info SSE event via HTTP localhost - Add .deco.host to Vite allowedHosts for tunnel domain requests - Add .ts extensions to all daemon import chains for Bun/Node native ESM Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
New modules in src/daemon/:
Usage
Test plan
Generated with Claude Code
Summary by cubic
Connects local Vite dev to admin.deco.cx via a reverse WebSocket tunnel using
@deco-cx/warp-node, and adds a daemon API for live, authenticated file editing and previews. Enables real-time.decoediting with JSON patches, file CRUD, SSE updates, and instant previews from the admin UI.New Features
DECO_SITE_NAMEis set; usesDECO_ENV_NAME(defaultdev), auto-reconnects, prints preview/admin URLs, and allows.deco.hostand.decocdn.comin ViteallowedHosts. Usage:DECO_SITE_NAME=mysite DECO_ENV_NAME=dev-local npm run dev.x-daemon-api/x-hypervisor-api, applies JWT auth + CORS (bypass withDANGEROUSLY_ALLOW_PUBLIC_ACCESS=true), and routes to Volumes CRUD, FS REST, and Watch SSE; other requests fall through to Vite; adds/_healthcheckwith version./volumes/:id/files/*with JSON patch support, atomic commit, and WebSocket broadcasts; integrates with Vite’s watcher and ignoresnode_modules,.git, etc./fs/file/*supports GET/PATCH/DELETE with timestamps and metadata; broadcastsfs-syncevents./watchor/streams an initial.decosnapshot,worker-status, andmeta-infofetched fromhttp://localhost:<port>/live/_meta.fs-syncmetadata includesblockType,__resolveType,name, andpath.Bug Fixes
safePath()across Volumes and FS APIs.TextFileSetwrites to the atomic commit step./live/_metaand related admin routes run in Vite SSR; meta cache shared viaglobalThiswith proper ETag invalidation.close()cleanup.inferMetadatanow defaults to{ kind: "file" }for non-JSON files.Written for commit bd626f2. Summary will update on new commits.