create-walle 0.9.21 → 0.9.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -5
- package/package.json +2 -2
- package/template/CLAUDE.md +2 -2
- package/template/LICENSE +1 -1
- package/template/bin/ctm-dev-cleanup.js +24 -3
- package/template/bin/ctm-launch.sh +13 -0
- package/template/bin/dev.sh +156 -18
- package/template/bin/node-bin.sh +84 -0
- package/template/bin/pin-node.sh +51 -0
- package/template/claude-task-manager/api-prompts.js +1203 -182
- package/template/claude-task-manager/api-reviews.js +109 -15
- package/template/claude-task-manager/approval-agent.js +1360 -280
- package/template/claude-task-manager/bin/restart-ctm.sh +64 -23
- package/template/claude-task-manager/bin/storage-migration-supervisor.js +338 -0
- package/template/claude-task-manager/db.js +4417 -295
- package/template/claude-task-manager/docs/app-update-refresh-protocol.md +69 -0
- package/template/claude-task-manager/docs/approval-ai-refinement.md +138 -0
- package/template/claude-task-manager/docs/approval-rescue-loop.md +74 -0
- package/template/claude-task-manager/docs/codex-operational-warning-health.md +107 -0
- package/template/claude-task-manager/docs/codex-resume-state-guard-design.md +17 -12
- package/template/claude-task-manager/docs/codex-terminal-render-controller-handoff.md +311 -0
- package/template/claude-task-manager/docs/coding-agent-hooks-architecture.md +418 -0
- package/template/claude-task-manager/docs/conversation-import-freshness.md +20 -0
- package/template/claude-task-manager/docs/google-workspace-auth-health.md +77 -0
- package/template/claude-task-manager/docs/image-paste-ux.md +13 -0
- package/template/claude-task-manager/docs/ipad-web-preview.md +88 -0
- package/template/claude-task-manager/docs/main-loop-offload-architecture.md +66 -0
- package/template/claude-task-manager/docs/microsoft-dev-tunnel-phone-access-design.md +274 -519
- package/template/claude-task-manager/docs/mobile-live-streaming.md +27 -5
- package/template/claude-task-manager/docs/mobile-remote-submission-lifecycle.md +69 -0
- package/template/claude-task-manager/docs/phone-access-design.md +53 -15
- package/template/claude-task-manager/docs/phone-passkey-identity.md +122 -0
- package/template/claude-task-manager/docs/phone-setup.md +3 -0
- package/template/claude-task-manager/docs/prompt-editing-tree-design.md +25 -1
- package/template/claude-task-manager/docs/remote-desktop-access-design.md +268 -0
- package/template/claude-task-manager/docs/restart-lifecycle-architecture.md +95 -0
- package/template/claude-task-manager/docs/runtime-work-control-plane.md +53 -0
- package/template/claude-task-manager/docs/session-interactive-wait-surfaces.md +38 -0
- package/template/claude-task-manager/docs/session-needs-you-dismissal.md +84 -0
- package/template/claude-task-manager/docs/session-render-state-management-design.md +91 -3
- package/template/claude-task-manager/docs/session-standup-command-center-design.md +25 -1
- package/template/claude-task-manager/docs/session-title-authority.md +32 -0
- package/template/claude-task-manager/docs/session-workspace-binding.md +33 -0
- package/template/claude-task-manager/docs/skill-intent-resolution-design.md +72 -0
- package/template/claude-task-manager/docs/walle-mcp-supervisor-health.md +86 -0
- package/template/claude-task-manager/docs/walle-relay-phone-access-design.md +24 -15
- package/template/claude-task-manager/docs/walle-session-history-hydration.md +114 -0
- package/template/claude-task-manager/docs/walle-session-input-queue.md +104 -0
- package/template/claude-task-manager/docs/walle-session-model-catalog.md +90 -0
- package/template/claude-task-manager/docs/walle-session-model-preferences.md +15 -6
- package/template/claude-task-manager/git-utils.js +897 -27
- package/template/claude-task-manager/lib/agent-capabilities.js +33 -0
- package/template/claude-task-manager/lib/agent-cli-cache.js +37 -7
- package/template/claude-task-manager/lib/agent-hooks-installer.js +26 -2
- package/template/claude-task-manager/lib/agent-presets.js +17 -1
- package/template/claude-task-manager/lib/all-sessions-query.js +108 -0
- package/template/claude-task-manager/lib/approval-ai-refinement.js +488 -0
- package/template/claude-task-manager/lib/approval-self-adapt.js +168 -0
- package/template/claude-task-manager/lib/async-semaphore.js +44 -0
- package/template/claude-task-manager/lib/auth-context.js +5 -0
- package/template/claude-task-manager/lib/auth-rate-limit.js +47 -4
- package/template/claude-task-manager/lib/auth-rules.js +29 -2
- package/template/claude-task-manager/lib/auto-approval-verifier.js +129 -16
- package/template/claude-task-manager/lib/background-llm.js +144 -17
- package/template/claude-task-manager/lib/branch-inventory.js +212 -0
- package/template/claude-task-manager/lib/claude-desktop-sessions.js +15 -3
- package/template/claude-task-manager/lib/coalesce-sync-frames.js +151 -0
- package/template/claude-task-manager/lib/codex-launch-health.js +762 -0
- package/template/claude-task-manager/lib/codex-transcript-pager.js +51 -0
- package/template/claude-task-manager/lib/codex-zst.js +124 -0
- package/template/claude-task-manager/lib/coding-agent-models.js +233 -30
- package/template/claude-task-manager/lib/connection-health.js +232 -0
- package/template/claude-task-manager/lib/conversation-blob-parser.js +42 -0
- package/template/claude-task-manager/lib/conversation-tail-merge.js +89 -26
- package/template/claude-task-manager/lib/ctm-session-context-api.js +39 -10
- package/template/claude-task-manager/lib/cursor-conversation-store.js +354 -0
- package/template/claude-task-manager/lib/db-owner-worker-client.js +315 -0
- package/template/claude-task-manager/lib/document-review.js +141 -6
- package/template/claude-task-manager/lib/escalation-review.js +152 -0
- package/template/claude-task-manager/lib/graceful-shutdown.js +159 -0
- package/template/claude-task-manager/lib/headless-term-service.js +678 -0
- package/template/claude-task-manager/lib/heavy-worker-fallback.js +38 -0
- package/template/claude-task-manager/lib/jsonl-conversation-parser.js +542 -0
- package/template/claude-task-manager/lib/jsonl-range-reader.js +112 -0
- package/template/claude-task-manager/lib/main-db-census.js +216 -0
- package/template/claude-task-manager/lib/message-pagination.js +106 -4
- package/template/claude-task-manager/lib/microsoft-dev-tunnel-setup.js +750 -26
- package/template/claude-task-manager/lib/mobile-auth-api.js +274 -7
- package/template/claude-task-manager/lib/mobile-auth-store.js +592 -10
- package/template/claude-task-manager/lib/mobile-notification-dispatcher.js +15 -0
- package/template/claude-task-manager/lib/model-overview-brain-fallback.js +311 -0
- package/template/claude-task-manager/lib/model-overview-cache.js +141 -0
- package/template/claude-task-manager/lib/models-health-routing-notice.js +126 -0
- package/template/claude-task-manager/lib/node-pin-guard.js +93 -0
- package/template/claude-task-manager/lib/perf-tracker.js +242 -6
- package/template/claude-task-manager/lib/permission-match.js +76 -0
- package/template/claude-task-manager/lib/permission-sync.js +133 -20
- package/template/claude-task-manager/lib/process-title.js +35 -0
- package/template/claude-task-manager/lib/prompt-executions-query.js +25 -0
- package/template/claude-task-manager/lib/prompt-index-disk-cache.js +44 -0
- package/template/claude-task-manager/lib/prompt-intent.js +132 -0
- package/template/claude-task-manager/lib/provider-user-context.js +34 -0
- package/template/claude-task-manager/lib/read-pool-client.js +313 -0
- package/template/claude-task-manager/lib/readpool-breaker.js +31 -0
- package/template/claude-task-manager/lib/recent-sessions-breaker.js +12 -0
- package/template/claude-task-manager/lib/remote-feedback-client.js +72 -0
- package/template/claude-task-manager/lib/remote-relay-protocol.js +37 -4
- package/template/claude-task-manager/lib/remote-relay-store.js +159 -0
- package/template/claude-task-manager/lib/remote-submission-observer.js +278 -0
- package/template/claude-task-manager/lib/restart-guard.js +109 -0
- package/template/claude-task-manager/lib/restore-interruption-detector.js +439 -0
- package/template/claude-task-manager/lib/restore-policy.js +13 -0
- package/template/claude-task-manager/lib/restore-resume-batch.js +74 -0
- package/template/claude-task-manager/lib/restore-runtime.js +68 -0
- package/template/claude-task-manager/lib/restore-storm.js +34 -0
- package/template/claude-task-manager/lib/resume-cwd.js +36 -0
- package/template/claude-task-manager/lib/resume-preflight.js +313 -0
- package/template/claude-task-manager/lib/runtime-work-registry.js +444 -0
- package/template/claude-task-manager/lib/sanitize-openai-auth.js +31 -0
- package/template/claude-task-manager/lib/scheduler.js +21 -1
- package/template/claude-task-manager/lib/scrollback-snapshot-store.js +159 -0
- package/template/claude-task-manager/lib/serial-task-queue.js +64 -0
- package/template/claude-task-manager/lib/server-listeners.js +239 -0
- package/template/claude-task-manager/lib/session-capture.js +42 -7
- package/template/claude-task-manager/lib/session-content-backfill.js +131 -0
- package/template/claude-task-manager/lib/session-history.js +388 -43
- package/template/claude-task-manager/lib/session-host-manager.js +287 -0
- package/template/claude-task-manager/lib/session-image-refs.js +209 -0
- package/template/claude-task-manager/lib/session-jobs.js +399 -59
- package/template/claude-task-manager/lib/session-prompt-index.js +137 -0
- package/template/claude-task-manager/lib/session-restore.js +53 -0
- package/template/claude-task-manager/lib/session-standup.js +123 -23
- package/template/claude-task-manager/lib/session-state-bus.js +14 -0
- package/template/claude-task-manager/lib/session-stream.js +64 -16
- package/template/claude-task-manager/lib/session-timeline-summary.js +260 -0
- package/template/claude-task-manager/lib/session-token-usage.js +494 -0
- package/template/claude-task-manager/lib/session-workspace-binding.js +356 -0
- package/template/claude-task-manager/lib/setup-network-config.js +9 -0
- package/template/claude-task-manager/lib/size-cap.js +45 -0
- package/template/claude-task-manager/lib/size-cap.test.js +62 -0
- package/template/claude-task-manager/lib/skill-autocomplete.js +180 -1
- package/template/claude-task-manager/lib/skill-intent-resolver.js +304 -0
- package/template/claude-task-manager/lib/sqlite-driver.js +19 -3
- package/template/claude-task-manager/lib/standup-attention.js +7 -3
- package/template/claude-task-manager/lib/status-authority.js +39 -0
- package/template/claude-task-manager/lib/status-hooks.js +4 -0
- package/template/claude-task-manager/lib/storage-migration.js +235 -0
- package/template/claude-task-manager/lib/structured-capture.js +298 -0
- package/template/claude-task-manager/lib/sync-io-census.js +163 -0
- package/template/claude-task-manager/lib/tailscale-setup.js +6 -0
- package/template/claude-task-manager/lib/terminal-activity-evidence.js +33 -0
- package/template/claude-task-manager/lib/terminal-choice.js +364 -0
- package/template/claude-task-manager/lib/terminal-control-sanitize.js +17 -0
- package/template/claude-task-manager/lib/terminal-fingerprint.js +48 -0
- package/template/claude-task-manager/lib/terminal-output-flush.js +84 -0
- package/template/claude-task-manager/lib/timeline-order.js +122 -0
- package/template/claude-task-manager/lib/transcript-store.js +348 -43
- package/template/claude-task-manager/lib/transport-security.js +84 -1
- package/template/claude-task-manager/lib/wait-state.js +184 -0
- package/template/claude-task-manager/lib/walle-client.js +47 -5
- package/template/claude-task-manager/lib/walle-ctm-history.js +564 -4
- package/template/claude-task-manager/lib/walle-external-actions.js +135 -16
- package/template/claude-task-manager/lib/walle-history-hydration.js +46 -0
- package/template/claude-task-manager/lib/walle-native-health.js +403 -0
- package/template/claude-task-manager/lib/walle-repair.js +701 -0
- package/template/claude-task-manager/lib/walle-session-cache.js +109 -0
- package/template/claude-task-manager/lib/walle-session-context.js +57 -21
- package/template/claude-task-manager/lib/walle-session-model-catalog.js +34 -0
- package/template/claude-task-manager/lib/walle-supervisor.js +539 -63
- package/template/claude-task-manager/lib/walle-transcript.js +52 -0
- package/template/claude-task-manager/lib/worktree-active-sync.js +11 -7
- package/template/claude-task-manager/lib/worktree-cwd.js +32 -1
- package/template/claude-task-manager/package.json +1 -1
- package/template/claude-task-manager/prompt-harvest.js +89 -66
- package/template/claude-task-manager/providers/claude-code.js +51 -3
- package/template/claude-task-manager/providers/cursor.js +140 -45
- package/template/claude-task-manager/public/css/reviews.css +551 -61
- package/template/claude-task-manager/public/css/setup.css +191 -0
- package/template/claude-task-manager/public/css/walle-session.css +865 -10
- package/template/claude-task-manager/public/css/walle.css +154 -0
- package/template/claude-task-manager/public/designs/ai-providers-consolidation-v2.html +830 -0
- package/template/claude-task-manager/public/index.html +18516 -2058
- package/template/claude-task-manager/public/ipad.html +363 -0
- package/template/claude-task-manager/public/js/document-review-links.js +301 -0
- package/template/claude-task-manager/public/js/image-normalize.js +69 -36
- package/template/claude-task-manager/public/js/message-renderer.js +1265 -77
- package/template/claude-task-manager/public/js/prompts.js +66 -29
- package/template/claude-task-manager/public/js/reviews.js +901 -133
- package/template/claude-task-manager/public/js/session-activity-utils.js +11 -1
- package/template/claude-task-manager/public/js/session-search-utils.js +94 -10
- package/template/claude-task-manager/public/js/session-status-precedence.js +23 -5
- package/template/claude-task-manager/public/js/setup.js +1273 -176
- package/template/claude-task-manager/public/js/stream-view.js +691 -73
- package/template/claude-task-manager/public/js/terminal-reconciler.js +210 -0
- package/template/claude-task-manager/public/js/walle-session.js +2455 -158
- package/template/claude-task-manager/public/js/walle.js +455 -28
- package/template/claude-task-manager/public/m/app.css +2909 -262
- package/template/claude-task-manager/public/m/app.js +6601 -398
- package/template/claude-task-manager/public/m/claim.html +224 -17
- package/template/claude-task-manager/public/m/index.html +117 -21
- package/template/claude-task-manager/public/m/sw.js +3 -1
- package/template/claude-task-manager/public/manifest.json +2 -2
- package/template/claude-task-manager/public/prompts.html +30 -14
- package/template/claude-task-manager/queue-engine.js +507 -28
- package/template/claude-task-manager/scripts/repair-claude-session-images.js +27 -8
- package/template/claude-task-manager/server.js +14341 -2197
- package/template/claude-task-manager/session-integrity.js +160 -18
- package/template/claude-task-manager/session-search-ranking.js +1 -0
- package/template/claude-task-manager/session-utils.js +25 -5
- package/template/claude-task-manager/workers/approval-blocklist.js +96 -6
- package/template/claude-task-manager/workers/approval-widget-validator.js +14 -8
- package/template/claude-task-manager/workers/conversation-import-worker.js +11 -50
- package/template/claude-task-manager/workers/db-owner-worker.js +386 -0
- package/template/claude-task-manager/workers/harvest-worker.js +9 -55
- package/template/claude-task-manager/workers/headless-term-worker.js +9 -530
- package/template/claude-task-manager/workers/read-pool-worker.js +387 -0
- package/template/claude-task-manager/workers/scrollback-worker.js +11 -72
- package/template/claude-task-manager/workers/session-host-process.js +146 -0
- package/template/claude-task-manager/workers/session-integrity-worker.js +10 -54
- package/template/claude-task-manager/workers/state-detectors/base.js +18 -1
- package/template/claude-task-manager/workers/state-detectors/claude-code.js +182 -9
- package/template/claude-task-manager/workers/state-detectors/codex.js +150 -2
- package/template/claude-task-manager/workers/state-detectors/cursor.js +127 -0
- package/template/claude-task-manager/workers/state-detectors/gemini.js +21 -0
- package/template/claude-task-manager/workers/state-detectors/index.js +29 -0
- package/template/claude-task-manager/workers/state-detectors/opencode.js +103 -0
- package/template/docs/design/markdown-review-pane.md +206 -0
- package/template/docs/designs/2026-05-17-portkey-gateway-provider-ux.md +129 -38
- package/template/docs/designs/2026-05-20-mobile-worktree-finish-command.md +27 -0
- package/template/docs/designs/2026-05-22-ai-configuration-consolidation.md +248 -0
- package/template/docs/designs/ai-configuration-consolidation-mock.html +812 -0
- package/template/docs/private-memory-and-pii-policy.md +69 -0
- package/template/package.json +2 -1
- package/template/scripts/check-private-data.js +201 -0
- package/template/shared/sqlite-owner-guard.js +30 -0
- package/template/shared/sqlite-owner-write-queue.js +225 -0
- package/template/shared/sqlite-storage-policy.js +111 -0
- package/template/shared/sqlite-write-lock.js +428 -0
- package/template/wall-e/agent-runners/claude-code.js +5 -0
- package/template/wall-e/agent.js +166 -22
- package/template/wall-e/api-walle.js +524 -70
- package/template/wall-e/auth/provider-flows.js +11 -1
- package/template/wall-e/bin/walle-mcp-stdio.js +341 -17
- package/template/wall-e/brain.js +1614 -141
- package/template/wall-e/chat/attachment-blocks.js +96 -0
- package/template/wall-e/chat/attachments.js +2 -1
- package/template/wall-e/chat/capability-resolver.js +7 -7
- package/template/wall-e/chat/context-messages.js +28 -0
- package/template/wall-e/chat/conversation-frame.js +630 -0
- package/template/wall-e/chat/provider-messages.js +125 -0
- package/template/wall-e/chat.js +1002 -233
- package/template/wall-e/coding/acceptance-contract.js +170 -0
- package/template/wall-e/coding/acp-adapter.js +1 -1
- package/template/wall-e/coding/agent-catalog.js +3 -0
- package/template/wall-e/coding/artifact-store.js +93 -0
- package/template/wall-e/coding/capability-router.js +120 -0
- package/template/wall-e/coding/coding-run-controller.js +423 -0
- package/template/wall-e/coding/compaction-service.js +157 -12
- package/template/wall-e/coding/frontend-verification.js +258 -0
- package/template/wall-e/coding/lifecycle-hooks.js +75 -0
- package/template/wall-e/coding/local-preview-contract.js +157 -0
- package/template/wall-e/coding/permission-service.js +57 -13
- package/template/wall-e/coding/prompt-bundle.js +19 -1
- package/template/wall-e/coding/prompt-section-registry.js +227 -0
- package/template/wall-e/coding/provider-compat.js +15 -0
- package/template/wall-e/coding/runtime-events.js +224 -0
- package/template/wall-e/coding/runtime-mode.js +3 -0
- package/template/wall-e/coding/side-git-snapshot.js +160 -4
- package/template/wall-e/coding/snapshot-service.js +143 -1
- package/template/wall-e/coding/stream-processor.js +388 -34
- package/template/wall-e/coding/task-tool.js +141 -4
- package/template/wall-e/coding/tool-execution-controller.js +365 -0
- package/template/wall-e/coding/tool-registry.js +43 -5
- package/template/wall-e/coding/user-hooks.js +217 -0
- package/template/wall-e/coding-orchestrator.js +1330 -221
- package/template/wall-e/coding-prompts.js +20 -4
- package/template/wall-e/context/context-builder.js +15 -2
- package/template/wall-e/decision/confidence.js +1 -1
- package/template/wall-e/docs/coding-acceptance-contract.md +41 -0
- package/template/wall-e/docs/external-action-controller.md +26 -6
- package/template/wall-e/docs/telemetry-lifecycle.md +8 -2
- package/template/wall-e/embeddings.js +591 -53
- package/template/wall-e/external-action-controller.js +12 -0
- package/template/wall-e/http/auth.js +1 -0
- package/template/wall-e/http/chat-api.js +46 -11
- package/template/wall-e/http/model-admin.js +836 -34
- package/template/wall-e/lib/boot-profile.js +88 -0
- package/template/wall-e/lib/event-loop-monitor.js +93 -0
- package/template/wall-e/lib/service-health.js +194 -0
- package/template/wall-e/llm/anthropic.js +130 -5
- package/template/wall-e/llm/client.js +266 -63
- package/template/wall-e/llm/default-fallback.js +382 -0
- package/template/wall-e/llm/health.js +19 -0
- package/template/wall-e/llm/message-guard.js +78 -0
- package/template/wall-e/llm/model-catalog.js +252 -1
- package/template/wall-e/llm/openai.js +26 -4
- package/template/wall-e/llm/portkey-sync.js +654 -0
- package/template/wall-e/llm/provider-error.js +30 -2
- package/template/wall-e/llm/registry.js +5 -1
- package/template/wall-e/llm/request-compat.js +67 -0
- package/template/wall-e/loops/backfill.js +79 -23
- package/template/wall-e/loops/brain-optimize.js +67 -0
- package/template/wall-e/loops/ingest.js +25 -10
- package/template/wall-e/loops/question-digest.js +160 -0
- package/template/wall-e/loops/reflect.js +6 -4
- package/template/wall-e/loops/think.js +39 -12
- package/template/wall-e/mcp-server.js +318 -36
- package/template/wall-e/memory/ctm-context-client.js +52 -14
- package/template/wall-e/memory/ctm-operational-context.js +237 -0
- package/template/wall-e/memory/ctm-prompt-executions-client.js +128 -0
- package/template/wall-e/memory/ctm-session-context.js +111 -63
- package/template/wall-e/prompts/coding/deepseek.txt +3 -0
- package/template/wall-e/prompts/coding/gemini.txt +6 -0
- package/template/wall-e/prompts/coding/gpt.txt +6 -0
- package/template/wall-e/prompts/coding/local.txt +7 -0
- package/template/wall-e/runtime/decision-hooks.js +115 -0
- package/template/wall-e/runtime/devbox-gateway.js +82 -8
- package/template/wall-e/runtime/prompt-manifest.js +86 -0
- package/template/wall-e/runtime/tool-executor.js +269 -0
- package/template/wall-e/runtime/tool-result-envelope.js +138 -0
- package/template/wall-e/runtime/transcript-projection.js +60 -0
- package/template/wall-e/runtime/walle-runtime.js +224 -0
- package/template/wall-e/scripts/db-optimize/migrate.js +162 -0
- package/template/wall-e/scripts/db-optimize/recall-eval.js +117 -0
- package/template/wall-e/server.js +15 -0
- package/template/wall-e/session-files.js +9 -0
- package/template/wall-e/skills/_bundled/google-calendar/run.js +1 -1
- package/template/wall-e/skills/_bundled/gws-workspace/run.js +1 -1
- package/template/wall-e/skills/_bundled/slack-mentions/run.js +76 -6
- package/template/wall-e/skills/claude-code-reader.js +7 -3
- package/template/wall-e/skills/script-skill-runner.js +10 -0
- package/template/wall-e/skills/skill-planner.js +38 -0
- package/template/wall-e/tools/builtin-middleware.js +19 -9
- package/template/wall-e/tools/local-tools.js +1428 -16
- package/template/wall-e/tools/permission-checker.js +73 -5
- package/template/wall-e/tools/question-manager.js +117 -7
- package/template/wall-e/training/harvester.js +12 -28
- package/template/wall-e/training/replay.js +25 -80
- package/template/website/index.html +10 -10
- package/template/wall-e/eval/ab-test.js +0 -203
- package/template/wall-e/eval/agent-runner.js +0 -772
- package/template/wall-e/eval/agent-scorer.js +0 -461
- package/template/wall-e/eval/aggregator.js +0 -414
- package/template/wall-e/eval/allowed-test-commands.js +0 -34
- package/template/wall-e/eval/benchmark-generator.js +0 -113
- package/template/wall-e/eval/benchmarks/chat-eval.json +0 -1662
- package/template/wall-e/eval/benchmarks/chat.json +0 -82
- package/template/wall-e/eval/benchmarks/coding-agent-real.json +0 -1
- package/template/wall-e/eval/benchmarks/coding-agent.json +0 -1581
- package/template/wall-e/eval/benchmarks/coding.json +0 -122
- package/template/wall-e/eval/benchmarks/memory-retrieval.json +0 -234
- package/template/wall-e/eval/benchmarks/reasoning.json +0 -82
- package/template/wall-e/eval/benchmarks/swebench-lite-30.json +0 -212
- package/template/wall-e/eval/benchmarks.js +0 -669
- package/template/wall-e/eval/cc-replay.js +0 -719
- package/template/wall-e/eval/chat-eval.js +0 -525
- package/template/wall-e/eval/check-keys.js +0 -15
- package/template/wall-e/eval/check-providers.js +0 -42
- package/template/wall-e/eval/codex-cli-baseline.js +0 -669
- package/template/wall-e/eval/coding-agent-real.js +0 -570
- package/template/wall-e/eval/context-compactor.js +0 -251
- package/template/wall-e/eval/debug-agent003.js +0 -68
- package/template/wall-e/eval/diagnostics.js +0 -216
- package/template/wall-e/eval/eval-orchestrator.js +0 -642
- package/template/wall-e/eval/evaluate.js +0 -202
- package/template/wall-e/eval/evaluator.js +0 -373
- package/template/wall-e/eval/exporter.js +0 -212
- package/template/wall-e/eval/fixtures/express-basic/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-basic/server.js +0 -115
- package/template/wall-e/eval/fixtures/express-basic/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-buggy/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-buggy/server.js +0 -113
- package/template/wall-e/eval/fixtures/express-buggy/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-buggy-items/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-buggy-items/server.js +0 -112
- package/template/wall-e/eval/fixtures/express-buggy-items/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-buggy-search/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-buggy-search/server.js +0 -121
- package/template/wall-e/eval/fixtures/express-buggy-search/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-rename-data/data.js +0 -34
- package/template/wall-e/eval/fixtures/express-rename-data/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-rename-data/server.js +0 -97
- package/template/wall-e/eval/fixtures/express-rename-data/test.js +0 -88
- package/template/wall-e/eval/fixtures/express-xss/package.json +0 -12
- package/template/wall-e/eval/fixtures/express-xss/server.js +0 -90
- package/template/wall-e/eval/fixtures/express-xss/test.js +0 -67
- package/template/wall-e/eval/fixtures/express-xss/views/profile.ejs +0 -9
- package/template/wall-e/eval/fixtures/fullstack-app/config/default.js +0 -9
- package/template/wall-e/eval/fixtures/fullstack-app/config/test.js +0 -13
- package/template/wall-e/eval/fixtures/fullstack-app/package.json +0 -11
- package/template/wall-e/eval/fixtures/fullstack-app/public/css/style.css +0 -137
- package/template/wall-e/eval/fixtures/fullstack-app/public/index.html +0 -46
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/app.js +0 -121
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/auth.js +0 -71
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/items.js +0 -80
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/users.js +0 -46
- package/template/wall-e/eval/fixtures/fullstack-app/public/login.html +0 -45
- package/template/wall-e/eval/fixtures/fullstack-app/public/register.html +0 -38
- package/template/wall-e/eval/fixtures/fullstack-app/scripts/migrate.js +0 -23
- package/template/wall-e/eval/fixtures/fullstack-app/scripts/seed.js +0 -46
- package/template/wall-e/eval/fixtures/fullstack-app/server/db.js +0 -99
- package/template/wall-e/eval/fixtures/fullstack-app/server/index.js +0 -94
- package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/auth.js +0 -19
- package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/logger.js +0 -19
- package/template/wall-e/eval/fixtures/fullstack-app/server/router.js +0 -50
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/auth.js +0 -69
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/health.js +0 -23
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/items.js +0 -88
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/users.js +0 -75
- package/template/wall-e/eval/fixtures/fullstack-app/server/test.js +0 -198
- package/template/wall-e/eval/fixtures/fullstack-app/server/utils/response.js +0 -34
- package/template/wall-e/eval/fixtures/fullstack-app/server/utils/validate.js +0 -26
- package/template/wall-e/eval/fixtures/fullstack-app/server.js +0 -8
- package/template/wall-e/eval/fixtures/fullstack-app/test.js +0 -12
- package/template/wall-e/eval/fixtures/monorepo-basic/package.json +0 -8
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/data.js +0 -58
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/middleware.js +0 -46
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/package.json +0 -8
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/routes.js +0 -64
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/server.js +0 -56
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/test.js +0 -116
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/commands.js +0 -61
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/index.js +0 -62
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/output.js +0 -43
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/package.json +0 -11
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/test.js +0 -44
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/formatters.js +0 -43
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/index.js +0 -12
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/package.json +0 -5
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/test.js +0 -55
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/validators.js +0 -29
- package/template/wall-e/eval/fixtures/monorepo-basic/test.js +0 -46
- package/template/wall-e/eval/fixtures/node-cli/index.js +0 -78
- package/template/wall-e/eval/fixtures/node-cli/package.json +0 -10
- package/template/wall-e/eval/fixtures/node-cli/test.js +0 -57
- package/template/wall-e/eval/fixtures/node-typed/package.json +0 -8
- package/template/wall-e/eval/fixtures/node-typed/src/handlers.js +0 -31
- package/template/wall-e/eval/fixtures/node-typed/src/utils.js +0 -33
- package/template/wall-e/eval/fixtures/node-typed/test.js +0 -36
- package/template/wall-e/eval/fixtures/python-flask/app.py +0 -14
- package/template/wall-e/eval/fixtures/python-flask/requirements.txt +0 -2
- package/template/wall-e/eval/fixtures/python-flask/test_app.py +0 -25
- package/template/wall-e/eval/fixtures/wall-e-subset/brain.js +0 -105
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/aggregator.js +0 -101
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/chat.json +0 -20
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/coding.json +0 -32
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks.js +0 -64
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/package.json +0 -6
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/server.js +0 -31
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/test.js +0 -18
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/utils.js +0 -34
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/runner.js +0 -104
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/scorer.js +0 -73
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/test.js +0 -134
- package/template/wall-e/eval/fixtures/wall-e-subset/llm/client.js +0 -99
- package/template/wall-e/eval/fixtures/wall-e-subset/llm/providers.js +0 -63
- package/template/wall-e/eval/fixtures/wall-e-subset/llm/test.js +0 -70
- package/template/wall-e/eval/fixtures/wall-e-subset/package.json +0 -10
- package/template/wall-e/eval/fixtures/wall-e-subset/test.js +0 -86
- package/template/wall-e/eval/harvester.js +0 -685
- package/template/wall-e/eval/head-to-head.js +0 -388
- package/template/wall-e/eval/humaneval-adapter.js +0 -321
- package/template/wall-e/eval/list-models.js +0 -31
- package/template/wall-e/eval/livecodebench-adapter.js +0 -291
- package/template/wall-e/eval/mail-integration.js +0 -443
- package/template/wall-e/eval/manifest.js +0 -186
- package/template/wall-e/eval/meta-harness/adapters/coding-agent.js +0 -57
- package/template/wall-e/eval/meta-harness/bootstrap-snapshot.js +0 -149
- package/template/wall-e/eval/meta-harness/candidate-store.js +0 -117
- package/template/wall-e/eval/meta-harness/cli.js +0 -86
- package/template/wall-e/eval/meta-harness/domain-spec.js +0 -154
- package/template/wall-e/eval/meta-harness/domains/coding-agent.domain.json +0 -84
- package/template/wall-e/eval/meta-harness/examples/env-bootstrap-candidate.js +0 -29
- package/template/wall-e/eval/meta-harness/experience-store.js +0 -174
- package/template/wall-e/eval/meta-harness/frontier.js +0 -96
- package/template/wall-e/eval/meta-harness/harness-interface.js +0 -90
- package/template/wall-e/eval/meta-harness/leakage-guard.js +0 -80
- package/template/wall-e/eval/meta-harness/optimizer.js +0 -207
- package/template/wall-e/eval/meta-harness/proposer-runner.js +0 -110
- package/template/wall-e/eval/meta-harness/reporting.js +0 -58
- package/template/wall-e/eval/meta-harness/telemetry.js +0 -27
- package/template/wall-e/eval/meta-harness/validation.js +0 -81
- package/template/wall-e/eval/promoter.js +0 -228
- package/template/wall-e/eval/provider-normalizer.js +0 -33
- package/template/wall-e/eval/replay.js +0 -395
- package/template/wall-e/eval/run-agent-benchmarks.js +0 -386
- package/template/wall-e/eval/run-codex-cli-baseline.js +0 -177
- package/template/wall-e/eval/run-coding-agent-real.js +0 -187
- package/template/wall-e/eval/run-eval.js +0 -435
- package/template/wall-e/eval/run-model-comparison.js +0 -142
- package/template/wall-e/eval/session-evaluator.js +0 -187
- package/template/wall-e/eval/session-miner.js +0 -207
- package/template/wall-e/eval/session-retrieval-benchmark.js +0 -150
- package/template/wall-e/eval/session-transcripts.js +0 -509
- package/template/wall-e/eval/shadow.js +0 -161
- package/template/wall-e/eval/swebench-adapter.js +0 -345
- package/template/wall-e/eval/swebench-docker.js +0 -192
- package/template/wall-e/eval/train.py +0 -320
- package/template/wall-e/eval/trainer.js +0 -232
- package/template/wall-e/eval/weekly-eval-loop.js +0 -241
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
# Microsoft Dev Tunnel
|
|
1
|
+
# Microsoft Dev Tunnel Client Access Design
|
|
2
2
|
|
|
3
|
-
Status:
|
|
4
|
-
Date: 2026-05-
|
|
3
|
+
Status: Design update
|
|
4
|
+
Date: 2026-05-30
|
|
5
5
|
Owner: CTM / Wall-E
|
|
6
6
|
Related docs:
|
|
7
|
+
- `claude-task-manager/docs/remote-desktop-access-design.md`
|
|
7
8
|
- `claude-task-manager/docs/phone-access-design.md`
|
|
8
9
|
- `claude-task-manager/docs/walle-relay-phone-access-design.md`
|
|
9
10
|
- `claude-task-manager/docs/phone-setup.md`
|
|
@@ -12,315 +13,255 @@ External references:
|
|
|
12
13
|
- Microsoft Dev Tunnels quickstart:
|
|
13
14
|
`https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/get-started`
|
|
14
15
|
- Microsoft Dev Tunnels security:
|
|
15
|
-
`https://learn.microsoft.com/en-
|
|
16
|
+
`https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/security`
|
|
16
17
|
- Microsoft Dev Tunnels CLI reference:
|
|
17
18
|
`https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/cli-commands`
|
|
18
|
-
-
|
|
19
|
-
`https://
|
|
19
|
+
- Tailscale quickstart:
|
|
20
|
+
`https://tailscale.com/docs/how-to/quickstart`
|
|
21
|
+
- Tailscale access controls:
|
|
22
|
+
`https://tailscale.com/docs/features/access-control/acls`
|
|
20
23
|
|
|
21
24
|
## Summary
|
|
22
25
|
|
|
23
|
-
Microsoft Dev Tunnel is
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
Microsoft Dev Tunnel is the default direct browser transport for secure CTM
|
|
27
|
+
access from another browser client, including phone and desktop. CTM supports
|
|
28
|
+
two explicit tunnel access modes:
|
|
29
|
+
|
|
30
|
+
1. **CTM-authenticated** - recommended for phones. Microsoft Dev Tunnels allows
|
|
31
|
+
anonymous `connect` to the CTM port, and CTM remains the application auth
|
|
32
|
+
gate with pairing, client-device token, origin checks, route scopes, passkey
|
|
33
|
+
step-up, audit, and revocation.
|
|
34
|
+
2. **Private Microsoft gate** - requires Microsoft/GitHub Dev Tunnel browser
|
|
35
|
+
auth before the request reaches CTM. This is useful when the user wants a
|
|
36
|
+
provider gate in front of CTM, but it can fail on mobile browsers before CTM
|
|
37
|
+
can display its pairing UI.
|
|
38
|
+
|
|
39
|
+
> **Invariant (2026-05-30): CTM-authenticated is the default; private is an
|
|
40
|
+
> explicit opt-in.** Dev Tunnels "private" mode enforces auth by redirecting the
|
|
41
|
+
> *initial request* to an interactive Microsoft/GitHub login page. The phone
|
|
42
|
+
> client is a PWA that reaches CTM via `fetch()` + a `WebSocket` on the same
|
|
43
|
+
> tunnel origin, and programmatic XHR/fetch/WebSocket cannot follow that
|
|
44
|
+
> cross-origin redirect — so forcing private silently bricks remote access
|
|
45
|
+
> ("can't connect / times out"). A brief earlier experiment that made private the
|
|
46
|
+
> default was reverted for this reason. Private is therefore honored only as a
|
|
47
|
+
> deliberate opt-in (an explicit UI selection, `CTM_MS_TUNNEL_ACCESS_MODE=private`,
|
|
48
|
+
> or `options.allowPrivateAccess`); a private value coming only from persisted
|
|
49
|
+
> state is treated as stale and migrated back to CTM-authenticated so the phone
|
|
50
|
+
> keeps working across headless restarts. If you want a true edge sign-in that is
|
|
51
|
+
> compatible with the PWA/WebSocket, use Cloudflare Access (GitHub/Google SSO via
|
|
52
|
+
> a JWT/cookie) or Tailscale (device identity) instead — both are already wired.
|
|
53
|
+
|
|
54
|
+
The CTM-authenticated flow exposes the local CTM host through a
|
|
55
|
+
Microsoft-managed tunnel like this:
|
|
30
56
|
|
|
31
57
|
```text
|
|
32
|
-
|
|
33
|
-
-> private devtunnels.ms
|
|
34
|
-
->
|
|
58
|
+
remote browser
|
|
59
|
+
-> private devtunnels.ms URL
|
|
60
|
+
-> Dev Tunnels connect-only forwarding
|
|
35
61
|
-> Azure Dev Tunnels service
|
|
36
|
-
-> devtunnel host process on Mac
|
|
62
|
+
-> devtunnel host process on the Mac
|
|
37
63
|
-> local CTM on 127.0.0.1:3456
|
|
38
|
-
-> CTM
|
|
64
|
+
-> CTM client-device auth, scopes, step-up, audit, and revocation
|
|
39
65
|
```
|
|
40
66
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
67
|
+
Anonymous tunnel `connect` is not the same as anonymous CTM access. It only
|
|
68
|
+
lets a browser reach CTM; the CTM app must still reject unpaired devices and
|
|
69
|
+
unauthorized routes. The setup UI must name the selected mode clearly and show
|
|
70
|
+
what is protecting the connection.
|
|
71
|
+
|
|
72
|
+
This doc covers the transport. The access-control architecture is shared with
|
|
73
|
+
mobile and desktop remote access in `remote-desktop-access-design.md`.
|
|
44
74
|
|
|
45
75
|
## Product Positioning
|
|
46
76
|
|
|
47
|
-
|
|
77
|
+
Direct browser access methods should be presented in this order:
|
|
48
78
|
|
|
49
|
-
1. **
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
79
|
+
1. **Microsoft Dev Tunnel** - default. CTM-authenticated phone-friendly browser
|
|
80
|
+
tunnel by default, with an optional private Microsoft/GitHub-gated mode.
|
|
81
|
+
2. **Tailscale** - private-network alternative when both devices are in the
|
|
82
|
+
user's tailnet or the Mac is shared into a tailnet.
|
|
83
|
+
3. **Walle Remote** - typed mobile relay for request/response control when a
|
|
84
|
+
full browser UI is not required.
|
|
53
85
|
|
|
54
|
-
|
|
86
|
+
Cloudflare Tunnel is out of scope for the CTM remote-desktop plan and should
|
|
87
|
+
not be shown in the main remote-access setup flow.
|
|
55
88
|
|
|
56
|
-
|
|
57
|
-
- Walle Relay is not deployed yet;
|
|
58
|
-
- the user does not want to install Tailscale on the phone;
|
|
59
|
-
- the user does not own or want to configure a domain;
|
|
60
|
-
- the user is comfortable signing into Microsoft or GitHub on the Mac to manage
|
|
61
|
-
the tunnel.
|
|
89
|
+
Microsoft Dev Tunnel is best when:
|
|
62
90
|
|
|
63
|
-
|
|
64
|
-
|
|
91
|
+
- the user wants full CTM browser access from another computer or phone;
|
|
92
|
+
- the user wants CTM's own pairing flow to load on the remote browser without
|
|
93
|
+
first completing Microsoft/GitHub browser auth;
|
|
94
|
+
- the user does not want a VPN or domain;
|
|
95
|
+
- CTM still owns app-level permissions, pairing, passkey step-up, and audit.
|
|
65
96
|
|
|
66
|
-
|
|
97
|
+
Tailscale is best when:
|
|
67
98
|
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
- the user cannot sign into the same Microsoft/GitHub identity on the phone;
|
|
72
|
-
- company policy blocks Microsoft Dev Tunnels domains or browser sign-in.
|
|
99
|
+
- both machines can be authenticated into the same tailnet;
|
|
100
|
+
- the user wants direct private-network access instead of a hosted tunnel;
|
|
101
|
+
- ACLs/grants can restrict CTM to the intended devices and port.
|
|
73
102
|
|
|
74
103
|
## Design Principles
|
|
75
104
|
|
|
76
|
-
1. **
|
|
77
|
-
CTM
|
|
78
|
-
|
|
79
|
-
2. **
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
3. **
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
105
|
+
1. **Name the transport gate explicitly.** CTM-authenticated mode lets the
|
|
106
|
+
browser reach CTM directly and relies on CTM app auth. Private Microsoft
|
|
107
|
+
gate mode requires Microsoft/GitHub tunnel auth before CTM loads.
|
|
108
|
+
2. **No anonymous CTM access.** CTM-authenticated mode may create a narrow
|
|
109
|
+
anonymous Dev Tunnel `connect` rule, but CTM must still require pairing,
|
|
110
|
+
device token, origin checks, route/WS authorization, passkey step-up, audit,
|
|
111
|
+
and revocation before exposing app data or controls.
|
|
112
|
+
3. **One client-device architecture.** Phone and desktop use the same device
|
|
113
|
+
identity, pairing, passkey step-up, scopes, audit log, origin binding, and
|
|
114
|
+
revocation model. The only difference is the UI surface: `/m/` for mobile,
|
|
115
|
+
`/` for desktop.
|
|
116
|
+
4. **Full desktop means full CTM UI.** A trusted desktop client opens the same
|
|
117
|
+
dashboard as local use: sessions, terminal, conversation view, prompts,
|
|
118
|
+
queue, reviews, models, setup, and raw terminal input where permitted.
|
|
119
|
+
5. **No temporary desktop mode.** Do not create a separate reduced desktop
|
|
120
|
+
product. Use normal CTM with remote auth and policy gates.
|
|
121
|
+
6. **Stable origin required.** CTM cookies and passkeys are origin-scoped.
|
|
122
|
+
Reuse a persistent tunnel ID and URL instead of temporary URLs.
|
|
123
|
+
7. **Make access failures precise.** Distinguish Microsoft/GitHub auth,
|
|
124
|
+
tunnel process, CTM origin, CTM device token, route scope, and passkey
|
|
125
|
+
step-up failures.
|
|
126
|
+
8. **Revocation must close live access.** Revoking a CTM client device closes
|
|
127
|
+
existing WebSockets and invalidates future HTTP/WS access.
|
|
128
|
+
|
|
129
|
+
## Recommended Setup Flow
|
|
95
130
|
|
|
96
131
|
### Desktop First-Time Setup
|
|
97
132
|
|
|
98
133
|
1. User opens `Setup -> Access`.
|
|
99
134
|
2. User selects `Microsoft Dev Tunnel`.
|
|
100
|
-
3. CTM shows
|
|
135
|
+
3. CTM shows one setup rail:
|
|
101
136
|
|
|
102
137
|
```text
|
|
103
|
-
1 Install 2 Sign in 3 Start tunnel 4 Pair
|
|
138
|
+
1 Install 2 Sign in 3 Start tunnel 4 Pair browser
|
|
104
139
|
```
|
|
105
140
|
|
|
106
|
-
4. CTM checks for `devtunnel` CLI.
|
|
107
|
-
5. If missing,
|
|
108
|
-
- `brew install --cask devtunnel`
|
|
109
|
-
- Microsoft install script / download link
|
|
110
|
-
- `Refresh`
|
|
141
|
+
4. CTM checks for the `devtunnel` CLI.
|
|
142
|
+
5. If missing, CTM offers install instructions and a refresh action.
|
|
111
143
|
6. CTM checks signed-in status with `devtunnel user show`.
|
|
112
|
-
7. If signed out,
|
|
113
|
-
- `Sign in with Microsoft`
|
|
114
|
-
- `Sign in with GitHub`
|
|
115
|
-
- `Use device code`
|
|
144
|
+
7. If signed out, CTM offers Microsoft, GitHub, and device-code sign-in.
|
|
116
145
|
8. CTM creates or reuses a persistent CTM tunnel ID.
|
|
117
146
|
9. CTM creates or verifies port `3456` with protocol `http`.
|
|
118
|
-
10.
|
|
119
|
-
|
|
147
|
+
10. User chooses the access mode:
|
|
148
|
+
- CTM-authenticated: create or verify anonymous `connect` access for this
|
|
149
|
+
tunnel port and rely on CTM app auth after forwarding.
|
|
150
|
+
- Private Microsoft gate: verify no anonymous `connect` access exists, and
|
|
151
|
+
offer `Reset to private` if stale anonymous access is detected.
|
|
120
152
|
11. CTM starts `devtunnel host <tunnel-id>` as a managed child process.
|
|
121
153
|
12. CTM parses the `https://...devtunnels.ms` URL from stdout.
|
|
122
|
-
13. CTM updates the
|
|
123
|
-
14. CTM enables
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
- Microsoft/GitHub
|
|
136
|
-
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
high-risk step-up, not as the primary proof that the phone can reach CTM.
|
|
147
|
-
7. Mac shows:
|
|
148
|
-
|
|
149
|
-
```text
|
|
150
|
-
Pair this phone?
|
|
151
|
-
Account: user@example.com or GitHub username
|
|
152
|
-
Device: iPhone / Safari
|
|
153
|
-
Origin: https://<tunnel>-3456.<region>.devtunnels.ms
|
|
154
|
-
Scopes: Read, Respond
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
9. User approves on Mac.
|
|
158
|
-
10. Phone lands on `/m/`.
|
|
154
|
+
13. CTM updates the origin allowlist for that exact URL.
|
|
155
|
+
14. CTM enables:
|
|
156
|
+
- `Pair Desktop Browser`
|
|
157
|
+
- `Pair Phone`
|
|
158
|
+
- `Copy Desktop URL`
|
|
159
|
+
- `Copy Mobile URL`
|
|
160
|
+
|
|
161
|
+
### Remote Browser Pairing
|
|
162
|
+
|
|
163
|
+
1. User opens the desktop or mobile URL:
|
|
164
|
+
- desktop: `https://<tunnel>-3456.<region>.devtunnels.ms/`
|
|
165
|
+
- mobile: `https://<tunnel>-3456.<region>.devtunnels.ms/m/`
|
|
166
|
+
2. In CTM-authenticated mode, the browser should reach CTM directly. In private
|
|
167
|
+
Microsoft gate mode, Microsoft may show anti-phishing and Microsoft/GitHub
|
|
168
|
+
sign-in before CTM receives the request.
|
|
169
|
+
3. After the request reaches CTM, CTM shows a pairing gate if the browser has
|
|
170
|
+
no CTM client-device token.
|
|
171
|
+
4. CTM creates a pending pairing request for the current origin and surface.
|
|
172
|
+
5. The Mac setup page shows the pending request with device hint, origin,
|
|
173
|
+
requested surface, scopes, and short code.
|
|
174
|
+
6. Local user approves or rejects.
|
|
175
|
+
7. Approval creates a CTM client-device token and registers or verifies a
|
|
176
|
+
passkey for high-risk step-up.
|
|
177
|
+
8. The browser lands on `/` for desktop or `/m/` for mobile.
|
|
159
178
|
|
|
160
179
|
### Returning Use
|
|
161
180
|
|
|
162
|
-
1. User opens saved
|
|
163
|
-
2.
|
|
164
|
-
|
|
165
|
-
3.
|
|
166
|
-
4.
|
|
167
|
-
|
|
181
|
+
1. User opens the saved URL.
|
|
182
|
+
2. CTM-authenticated mode forwards to CTM directly; private Microsoft gate mode
|
|
183
|
+
first gates network access with Microsoft/GitHub tunnel auth.
|
|
184
|
+
3. CTM client-device token gates app access in both modes.
|
|
185
|
+
4. If the tunnel origin is stable, CTM cookies and passkeys remain valid.
|
|
186
|
+
5. If CTM token is missing or expired, CTM shows the pairing gate again.
|
|
168
187
|
|
|
169
188
|
### Stop and Resume
|
|
170
189
|
|
|
171
190
|
1. User clicks `Stop Tunnel`.
|
|
172
191
|
2. CTM stops the `devtunnel host` process.
|
|
173
|
-
3.
|
|
174
|
-
4. CTM keeps
|
|
175
|
-
5. User clicks `Start Tunnel
|
|
192
|
+
3. Remote browsers can no longer reach CTM.
|
|
193
|
+
4. CTM keeps paired client-device records.
|
|
194
|
+
5. User clicks `Start Tunnel`.
|
|
176
195
|
6. CTM reuses the same persistent tunnel ID and origin.
|
|
177
|
-
7.
|
|
178
|
-
|
|
179
|
-
## Sleep and Idle Availability
|
|
180
|
-
|
|
181
|
-
Microsoft Dev Tunnel only forwards to CTM while the Mac can run the local CTM
|
|
182
|
-
server and the `devtunnel host` process. If macOS puts the laptop to sleep, the
|
|
183
|
-
phone cannot reconnect until the Mac wakes. Unlocking the laptop often appears
|
|
184
|
-
to "fix" phone access because it wakes the machine and gives the tunnel process
|
|
185
|
-
a chance to reconnect.
|
|
186
|
-
|
|
187
|
-
CTM should make this contract explicit rather than pretending the tunnel is an
|
|
188
|
-
always-on hosted service.
|
|
189
|
-
|
|
190
|
-
### Availability Modes
|
|
191
|
-
|
|
192
|
-
Default mode:
|
|
196
|
+
7. Existing remote browsers resume without re-pairing unless their CTM token or
|
|
197
|
+
passkey state expired.
|
|
193
198
|
|
|
194
|
-
|
|
195
|
-
- CTM watches for long event-loop gaps that imply sleep/wake.
|
|
196
|
-
- After wake, CTM verifies the managed tunnel process and restarts it if it is
|
|
197
|
-
missing, stale, or running with an incompatible host-header mode.
|
|
198
|
-
- CTM prefers `--host-header unchanged --origin-header unchanged`, but older
|
|
199
|
-
Dev Tunnels CLI builds can crash on those flags. When that happens, CTM
|
|
200
|
-
retries with the default header rewrite mode and relies on forwarded-host
|
|
201
|
-
recovery in the request/auth layer.
|
|
202
|
-
- The phone app reconnects when Safari returns to the foreground.
|
|
199
|
+
### Expiration And Renewal
|
|
203
200
|
|
|
204
|
-
|
|
201
|
+
The `devtunnel` CLI accepts a maximum tunnel/access expiration of 30 days. CTM
|
|
202
|
+
therefore cannot create a never-expiring Microsoft tunnel; it should make the
|
|
203
|
+
remote URL stable by reusing the same tunnel ID and proactively renewing the
|
|
204
|
+
service-side expiration.
|
|
205
205
|
|
|
206
|
-
|
|
207
|
-
- CTM starts a scoped macOS `caffeinate` process while the Microsoft tunnel is
|
|
208
|
-
desired-running.
|
|
209
|
-
- The assertion prevents idle system sleep but does not intentionally keep the
|
|
210
|
-
display awake.
|
|
211
|
-
- The UI shows the active assertion, warns about battery drain, and offers a
|
|
212
|
-
one-click disable action.
|
|
213
|
-
- CTM stops the assertion when the user disables the mode or stops the tunnel.
|
|
206
|
+
CTM policy:
|
|
214
207
|
|
|
215
|
-
|
|
216
|
-
|
|
208
|
+
- create persistent tunnels with `--expiration 30d`;
|
|
209
|
+
- renew the tunnel in place with `devtunnel update <tunnel-id> --expiration 30d`;
|
|
210
|
+
- mark renewal due after 25 days, leaving a buffer before the 30-day service
|
|
211
|
+
limit;
|
|
212
|
+
- for CTM-authenticated mode, recreate the port-level anonymous `connect` access
|
|
213
|
+
rule on the same 25-day cadence because the CLI exposes `access create` and
|
|
214
|
+
`access delete`, but not `access update`;
|
|
215
|
+
- keep renewal checks cheap in the normal watchdog path by reading local renewal
|
|
216
|
+
timestamps first and only calling the CLI when renewal is due, manual setup is
|
|
217
|
+
run, or access repair is requested.
|
|
217
218
|
|
|
218
|
-
|
|
219
|
+
Renewal does not bypass Microsoft/GitHub account requirements for managing the
|
|
220
|
+
tunnel. If the local `devtunnel` credential expires, CTM should surface a
|
|
221
|
+
sign-in-required state and resume renewal after the user signs in again.
|
|
219
222
|
|
|
220
|
-
|
|
221
|
-
`desired_running: true`.
|
|
223
|
+
## Tailscale Alternative
|
|
222
224
|
|
|
223
|
-
|
|
225
|
+
Tailscale is not anonymous. For the normal case, both sides must be signed into
|
|
226
|
+
the same tailnet. Other secure variants are also possible, such as sharing the
|
|
227
|
+
Mac into another authenticated tailnet user or using managed/auth-key device
|
|
228
|
+
enrollment, but they are still authenticated tailnet flows.
|
|
224
229
|
|
|
225
|
-
|
|
226
|
-
2. Verify the saved PID still belongs to `devtunnel host <tunnel-id>`.
|
|
227
|
-
3. Confirm the host-header mode is one CTM can authenticate: preferred
|
|
228
|
-
passthrough flags, or a recorded default-header fallback.
|
|
229
|
-
4. If the process is missing or invalid, call the same restore path used at CTM
|
|
230
|
-
startup.
|
|
231
|
-
5. If restore succeeds, re-apply the tunnel origin to the in-memory allowed
|
|
232
|
-
origins.
|
|
233
|
-
6. Persist `last_watchdog_check_at`, `last_watchdog_recovered_at`, and
|
|
234
|
-
`watchdog_error` for diagnostics.
|
|
230
|
+
CTM should treat Tailscale as a transport, not as the only auth layer:
|
|
235
231
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
232
|
+
- bind only to loopback and approved private/Tailscale interfaces;
|
|
233
|
+
- rely on Tailscale ACLs/grants to restrict network reachability;
|
|
234
|
+
- still require CTM client-device pairing for `/` and `/m/`;
|
|
235
|
+
- still enforce CTM route/WS scopes and passkey step-up.
|
|
239
236
|
|
|
240
|
-
|
|
237
|
+
## Access Policy
|
|
241
238
|
|
|
242
|
-
|
|
243
|
-
background. The mobile app should reconnect on:
|
|
239
|
+
### Trusted Desktop Client
|
|
244
240
|
|
|
245
|
-
|
|
246
|
-
- `focus`
|
|
247
|
-
- `pageshow`
|
|
248
|
-
- `visibilitychange` when the document becomes visible
|
|
241
|
+
A paired trusted desktop client can:
|
|
249
242
|
|
|
250
|
-
|
|
243
|
+
- load the full `/` CTM dashboard;
|
|
244
|
+
- open session tabs;
|
|
245
|
+
- view terminal and conversation history;
|
|
246
|
+
- send raw terminal input to sessions where CTM policy allows it;
|
|
247
|
+
- send Wall-E/coding messages;
|
|
248
|
+
- create sessions and prompts;
|
|
249
|
+
- use queue, review, model, and setup pages subject to scopes and step-up.
|
|
251
250
|
|
|
252
|
-
|
|
253
|
-
2. open a fresh WebSocket;
|
|
254
|
-
3. refresh session data immediately;
|
|
255
|
-
4. keep the user's draft text;
|
|
256
|
-
5. show a clear connection state if CTM is unreachable.
|
|
251
|
+
Protected operations still require additional gates:
|
|
257
252
|
|
|
258
|
-
|
|
259
|
-
|
|
253
|
+
- route/WS authorization from `auth-rules`;
|
|
254
|
+
- passkey step-up for high-risk remote actions;
|
|
255
|
+
- local-only restrictions for hooks, telemetry ingest, OAuth callbacks, and
|
|
256
|
+
other machine-local endpoints;
|
|
257
|
+
- audit events for auth, remote input, model changes, terminal control, and
|
|
258
|
+
revocation.
|
|
260
259
|
|
|
261
|
-
###
|
|
260
|
+
### Mobile Client
|
|
262
261
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
| Tunnel running, keep-awake on | CTM is preventing idle sleep | `Keeping this Mac awake for phone access.` |
|
|
267
|
-
| Wake recovery running | CTM detected sleep/wake or stale tunnel | `Recovering the Microsoft tunnel...` |
|
|
268
|
-
| Recovery failed | CTM could not restore the tunnel | `Tunnel recovery failed. Start the tunnel again.` |
|
|
269
|
-
| Phone resumed stale | Safari came back before WebSocket recovered | `Reconnecting to CTM...` |
|
|
270
|
-
|
|
271
|
-
### Security and Resource Notes
|
|
272
|
-
|
|
273
|
-
- Keep-awake mode is explicit and reversible.
|
|
274
|
-
- CTM uses `spawn('caffeinate', args)` with fixed argv, not shell strings.
|
|
275
|
-
- No tunnel tokens, Microsoft credentials, or phone pairing secrets are written
|
|
276
|
-
into power assertion state.
|
|
277
|
-
- Stopping the Microsoft tunnel should also stop the keep-awake assertion.
|
|
278
|
-
- If CTM exits, `caffeinate -w <ctm-pid>` should end with it.
|
|
279
|
-
- Battery users should see a warning before enabling keep-awake mode.
|
|
280
|
-
|
|
281
|
-
## Critical Origin Decision
|
|
282
|
-
|
|
283
|
-
Do not use a temporary tunnel as the normal phone setup path.
|
|
284
|
-
|
|
285
|
-
Temporary hosting is easy:
|
|
286
|
-
|
|
287
|
-
```bash
|
|
288
|
-
devtunnel host -p 3456
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
But it creates a new tunnel URL when the host process changes. That breaks
|
|
292
|
-
mobile UX because:
|
|
293
|
-
|
|
294
|
-
- CTM allowed origins need to change;
|
|
295
|
-
- CTM cookies are scoped to the old origin;
|
|
296
|
-
- WebAuthn/passkey credentials are scoped to the old RP ID;
|
|
297
|
-
- saved home-screen PWA icons point to the old URL;
|
|
298
|
-
- users experience this as "my paired phone stopped working."
|
|
299
|
-
|
|
300
|
-
Recommended CTM behavior:
|
|
301
|
-
|
|
302
|
-
```bash
|
|
303
|
-
devtunnel create ctm-<stable-random-id> --expiration 30d
|
|
304
|
-
devtunnel port create ctm-<stable-random-id> -p 3456 --protocol http
|
|
305
|
-
devtunnel host ctm-<stable-random-id> --host-header unchanged --origin-header unchanged
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
The tunnel ID should be random and non-sensitive. Do not include usernames,
|
|
309
|
-
company names, project names, repo names, or machine names.
|
|
310
|
-
|
|
311
|
-
If that host command exits immediately with the Dev Tunnels
|
|
312
|
-
`same key ... host` CLI error, CTM retries:
|
|
313
|
-
|
|
314
|
-
```bash
|
|
315
|
-
devtunnel host ctm-<stable-random-id>
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
This fallback is acceptable because CTM treats forwarded public tunnel headers
|
|
319
|
-
as the source of truth for origin and WebAuthn recovery when Dev Tunnels rewrites
|
|
320
|
-
`Host` or `Origin` to localhost.
|
|
321
|
-
|
|
322
|
-
Show the expiry date in the UI. Renew or recreate before expiry if Microsoft
|
|
323
|
-
allows it; otherwise tell the user exactly when re-pairing may be needed.
|
|
262
|
+
A paired mobile client uses the same auth stack, but the `/m/` UI remains
|
|
263
|
+
optimized for phone-sized interaction. Mobile may hide or reshape some controls,
|
|
264
|
+
but that is a UX choice, not a separate auth architecture.
|
|
324
265
|
|
|
325
266
|
## Desktop UX
|
|
326
267
|
|
|
@@ -335,22 +276,22 @@ Microsoft Dev Tunnel
|
|
|
335
276
|
Badge:
|
|
336
277
|
|
|
337
278
|
```text
|
|
338
|
-
|
|
279
|
+
Default secure browser access
|
|
339
280
|
```
|
|
340
281
|
|
|
341
282
|
Body:
|
|
342
283
|
|
|
343
284
|
```text
|
|
344
|
-
|
|
345
|
-
|
|
285
|
+
Open CTM from another computer or phone through a private Microsoft Dev Tunnel.
|
|
286
|
+
The remote browser signs into Microsoft/GitHub before CTM loads, then CTM
|
|
287
|
+
pairs and authorizes the browser.
|
|
346
288
|
```
|
|
347
289
|
|
|
348
290
|
Security note:
|
|
349
291
|
|
|
350
292
|
```text
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
Microsoft gate.
|
|
293
|
+
No anonymous tunnel access. CTM still controls device pairing, permissions,
|
|
294
|
+
passkey step-up, audit, and revocation.
|
|
354
295
|
```
|
|
355
296
|
|
|
356
297
|
Primary button by state:
|
|
@@ -359,9 +300,11 @@ Primary button by state:
|
|
|
359
300
|
| --- | --- |
|
|
360
301
|
| CLI missing | `Install CLI` |
|
|
361
302
|
| Signed out | `Sign in` |
|
|
362
|
-
|
|
|
363
|
-
| Running | `Pair
|
|
364
|
-
| Paired | `Open
|
|
303
|
+
| Private tunnel ready | `Start Tunnel` |
|
|
304
|
+
| Running | `Pair Browser` |
|
|
305
|
+
| Paired desktop | `Open Desktop URL` |
|
|
306
|
+
| Paired phone | `Open Phone URL` |
|
|
307
|
+
| Anonymous access detected | `Reset to Private` |
|
|
365
308
|
| Error | `Retry` |
|
|
366
309
|
|
|
367
310
|
Secondary buttons:
|
|
@@ -369,195 +312,8 @@ Secondary buttons:
|
|
|
369
312
|
- `Stop Tunnel`
|
|
370
313
|
- `Refresh`
|
|
371
314
|
- `Diagnostics`
|
|
372
|
-
- `Copy URL`
|
|
373
|
-
|
|
374
|
-
### Setup Panel Layout
|
|
375
|
-
|
|
376
|
-
Use one operational panel with a horizontal stepper on desktop and a vertical
|
|
377
|
-
stepper on narrow screens.
|
|
378
|
-
|
|
379
|
-
```text
|
|
380
|
-
Microsoft Dev Tunnel CTM protected
|
|
381
|
-
No DNS or VPN. Phone opens the browser URL, then pairs with CTM.
|
|
382
|
-
|
|
383
|
-
1 Install ----- 2 Sign in ----- 3 Start tunnel ----- 4 Pair phone
|
|
384
|
-
|
|
385
|
-
[Current step content]
|
|
386
|
-
|
|
387
|
-
Connection
|
|
388
|
-
Account: user@example.com
|
|
389
|
-
Tunnel: ctm-a8f39c
|
|
390
|
-
Phone URL: https://ctm-a8f39c-3456.usw2.devtunnels.ms/m/
|
|
391
|
-
Status: Running
|
|
392
|
-
|
|
393
|
-
[Pair Phone] [Copy URL] [Stop Tunnel]
|
|
394
|
-
```
|
|
395
|
-
|
|
396
|
-
Do not bury Cloudflare-style details in form fields. This setup should mostly
|
|
397
|
-
be buttons plus status.
|
|
398
|
-
|
|
399
|
-
### Step: Install
|
|
400
|
-
|
|
401
|
-
State copy:
|
|
402
|
-
|
|
403
|
-
```text
|
|
404
|
-
Install Microsoft's devtunnel CLI once on this Mac.
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
Actions:
|
|
408
|
-
|
|
409
|
-
- `Copy Homebrew command`
|
|
410
|
-
- `Open Microsoft install docs`
|
|
411
|
-
- `Refresh`
|
|
412
|
-
|
|
413
|
-
Detected state:
|
|
414
|
-
|
|
415
|
-
```text
|
|
416
|
-
devtunnel 1.x detected
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
### Step: Sign In
|
|
420
|
-
|
|
421
|
-
State copy:
|
|
422
|
-
|
|
423
|
-
```text
|
|
424
|
-
Sign into the account your phone will also use.
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
Controls:
|
|
428
|
-
|
|
429
|
-
- segmented control: `Microsoft` / `GitHub`
|
|
430
|
-
- `Sign in`
|
|
431
|
-
- `Use device code`
|
|
432
|
-
|
|
433
|
-
Signed-in state:
|
|
434
|
-
|
|
435
|
-
```text
|
|
436
|
-
Signed in as user@example.com
|
|
437
|
-
This account manages the tunnel on this Mac only.
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
### Step: Start Tunnel
|
|
441
|
-
|
|
442
|
-
Default settings:
|
|
443
|
-
|
|
444
|
-
- Access: `Private Microsoft/GitHub account access`
|
|
445
|
-
- Tunnel kind: `Persistent`
|
|
446
|
-
- Port: `3456`
|
|
447
|
-
- Protocol: `http`
|
|
448
|
-
- Expiration: `30 days` if supported
|
|
449
|
-
|
|
450
|
-
Primary CTA:
|
|
451
|
-
|
|
452
|
-
```text
|
|
453
|
-
Start Tunnel
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
Running state:
|
|
457
|
-
|
|
458
|
-
```text
|
|
459
|
-
Tunnel running
|
|
460
|
-
Phone access requires the same Microsoft/GitHub account plus CTM pairing.
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
Do not offer broad tunnel-level public mode. CTM should reset stale anonymous
|
|
464
|
-
rules back to Microsoft Dev Tunnels defaults rather than creating new anonymous
|
|
465
|
-
rules.
|
|
466
|
-
|
|
467
|
-
### Step: Pair Phone
|
|
468
|
-
|
|
469
|
-
Show only after the tunnel is running, the tunnel access is private, and CTM has
|
|
470
|
-
an exact allowed origin.
|
|
471
|
-
|
|
472
|
-
Content:
|
|
473
|
-
|
|
474
|
-
```text
|
|
475
|
-
Scan with iPhone. First sign into the tunnel account below if Microsoft asks.
|
|
476
|
-
|
|
477
|
-
Use this account:
|
|
478
|
-
user@example.com
|
|
479
|
-
|
|
480
|
-
Then CTM pairs this browser and records its device permissions.
|
|
481
|
-
```
|
|
482
|
-
|
|
483
|
-
QR payload:
|
|
484
|
-
|
|
485
|
-
```text
|
|
486
|
-
https://<tunnel>-3456.<region>.devtunnels.ms/m/claim?claim=...&secret=...
|
|
487
|
-
```
|
|
488
|
-
|
|
489
|
-
Below QR:
|
|
490
|
-
|
|
491
|
-
- `Copy Link`
|
|
492
|
-
- `Expires in 09:59`
|
|
493
|
-
- `Cancel Claim`
|
|
494
|
-
|
|
495
|
-
Device list:
|
|
496
|
-
|
|
497
|
-
```text
|
|
498
|
-
User's iPhone
|
|
499
|
-
Last used 2m ago
|
|
500
|
-
Scopes: Read, Respond
|
|
501
|
-
[Revoke]
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
## Phone UX
|
|
505
|
-
|
|
506
|
-
### Before CTM Loads
|
|
507
|
-
|
|
508
|
-
The user may see Microsoft-owned screens before CTM can render anything. The
|
|
509
|
-
desktop QR panel must set that expectation.
|
|
510
|
-
|
|
511
|
-
Expected Microsoft screens:
|
|
512
|
-
|
|
513
|
-
- anti-phishing interstitial;
|
|
514
|
-
- Microsoft/GitHub sign-in;
|
|
515
|
-
- access denied if wrong account.
|
|
516
|
-
|
|
517
|
-
CTM should not try to style or bypass these screens.
|
|
518
|
-
|
|
519
|
-
### CTM Claim Page
|
|
520
|
-
|
|
521
|
-
After Microsoft forwards to CTM, show a compact confirmation:
|
|
522
|
-
|
|
523
|
-
```text
|
|
524
|
-
Microsoft tunnel connected
|
|
525
|
-
|
|
526
|
-
Finish pairing this phone with CTM.
|
|
527
|
-
|
|
528
|
-
Tunnel account: user@example.com
|
|
529
|
-
Mac: User's MacBook
|
|
530
|
-
Access: Read, Respond
|
|
531
|
-
|
|
532
|
-
[Pair this phone]
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
If the user is on an unexpected origin:
|
|
536
|
-
|
|
537
|
-
```text
|
|
538
|
-
This link no longer matches the active Microsoft tunnel.
|
|
539
|
-
Generate a new pairing code on your Mac.
|
|
540
|
-
```
|
|
541
|
-
|
|
542
|
-
### CTM Home
|
|
543
|
-
|
|
544
|
-
Once paired, the phone home should include a transport pill:
|
|
545
|
-
|
|
546
|
-
```text
|
|
547
|
-
Microsoft Tunnel
|
|
548
|
-
Private
|
|
549
|
-
```
|
|
550
|
-
|
|
551
|
-
Status examples:
|
|
552
|
-
|
|
553
|
-
- `Connected`
|
|
554
|
-
- `Microsoft sign-in required`
|
|
555
|
-
- `Tunnel stopped`
|
|
556
|
-
- `Mac offline`
|
|
557
|
-
- `Tunnel expires in 3 days`
|
|
558
|
-
|
|
559
|
-
The transport pill should not dominate the home screen. It is a status signal,
|
|
560
|
-
not the task.
|
|
315
|
+
- `Copy Desktop URL`
|
|
316
|
+
- `Copy Mobile URL`
|
|
561
317
|
|
|
562
318
|
## Failure States
|
|
563
319
|
|
|
@@ -565,47 +321,38 @@ not the task.
|
|
|
565
321
|
| --- | --- | --- |
|
|
566
322
|
| CLI missing | `Microsoft devtunnel CLI is not installed.` | Install, then refresh |
|
|
567
323
|
| Auth missing | `Sign into Microsoft or GitHub before starting a tunnel.` | Sign in / device code |
|
|
568
|
-
|
|
|
569
|
-
| Anonymous access
|
|
324
|
+
| Provider sign-in required | `Sign into the private Microsoft tunnel before CTM can load.` | Complete provider sign-in |
|
|
325
|
+
| Anonymous access detected | `This tunnel allows anonymous browser access. Reset it to private before using CTM remote access.` | Reset to private |
|
|
570
326
|
| Tunnel start failed | `Tunnel did not start.` | Retry, copy diagnostics |
|
|
571
|
-
| Temporary URL changed | `This
|
|
327
|
+
| Temporary URL changed | `This browser link belongs to an old tunnel.` | Reuse persistent tunnel or re-pair |
|
|
572
328
|
| Origin not allowed | `CTM has not trusted this tunnel URL yet.` | Refresh setup, save origin |
|
|
329
|
+
| CTM device missing | `Pair this browser before using CTM remotely.` | Approve pairing on Mac |
|
|
573
330
|
| Claim expired | `Pairing code expired.` | Generate a new code |
|
|
574
|
-
| Microsoft service blocked | `This network blocks Microsoft Dev Tunnels.` | Use
|
|
331
|
+
| Microsoft service blocked | `This network blocks Microsoft Dev Tunnels.` | Use Tailscale |
|
|
575
332
|
| Tunnel stopped | `Microsoft tunnel is stopped.` | Start tunnel on Mac |
|
|
576
333
|
| Tunnel expiring | `Tunnel expires soon.` | Renew or recreate before expiry |
|
|
577
334
|
|
|
578
335
|
## Security Posture
|
|
579
336
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
- Microsoft/GitHub account required
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
-
|
|
588
|
-
-
|
|
589
|
-
-
|
|
590
|
-
|
|
591
|
-
-
|
|
592
|
-
-
|
|
593
|
-
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
rewrites headers for development scenarios. Treat Microsoft as part of the
|
|
600
|
-
trusted transport path.
|
|
601
|
-
|
|
602
|
-
That is acceptable for a fallback tunnel if:
|
|
603
|
-
|
|
604
|
-
- the Microsoft/GitHub private gate remains on;
|
|
605
|
-
- CTM app-layer auth remains strong;
|
|
606
|
-
- the user understands that Dev Tunnels is a Microsoft-hosted relay, not an E2E
|
|
607
|
-
blind relay;
|
|
608
|
-
- sensitive long-running remote access moves to Walle Remote once available.
|
|
337
|
+
Required:
|
|
338
|
+
|
|
339
|
+
- Microsoft/GitHub account required for Dev Tunnel management and remote
|
|
340
|
+
browser access.
|
|
341
|
+
- No anonymous CTM app access. CTM-authenticated mode may use a connect-only
|
|
342
|
+
anonymous Dev Tunnel rule, but CTM pairing, device token, route scopes, and
|
|
343
|
+
passkey step-up remain mandatory app gates.
|
|
344
|
+
- CTM client-device token required for app access.
|
|
345
|
+
- Local Mac approval required for first browser pairing.
|
|
346
|
+
- CTM route authorization registry applies to HTTP and WebSocket actions.
|
|
347
|
+
- High-risk remote actions require passkey step-up.
|
|
348
|
+
- No tunnel access tokens in QR codes or browser URLs.
|
|
349
|
+
- Revocation closes active WebSockets and blocks future HTTP/WS requests.
|
|
350
|
+
- Audit records include transport, origin, surface, device, scope, and action.
|
|
351
|
+
|
|
352
|
+
Microsoft Dev Tunnel does not provide relay-blind payload privacy. Microsoft is
|
|
353
|
+
part of the trusted transport path. That is acceptable for this product shape
|
|
354
|
+
because the user explicitly selected Microsoft as the default secure transport
|
|
355
|
+
and CTM still owns app-layer authorization.
|
|
609
356
|
|
|
610
357
|
## Implementation Notes
|
|
611
358
|
|
|
@@ -618,26 +365,28 @@ Store:
|
|
|
618
365
|
- port;
|
|
619
366
|
- protocol;
|
|
620
367
|
- signed-in account display;
|
|
621
|
-
- private access status
|
|
368
|
+
- private access status;
|
|
369
|
+
- anonymous-access drift status;
|
|
622
370
|
- expiration timestamp if available;
|
|
623
371
|
- managed process PID;
|
|
624
372
|
- last stdout/stderr lines for diagnostics;
|
|
625
|
-
-
|
|
373
|
+
- exact CTM allowed origin;
|
|
374
|
+
- paired client-device IDs for desktop and mobile surfaces.
|
|
626
375
|
|
|
627
376
|
Do not store Microsoft/GitHub passwords or login tokens. The `devtunnel` CLI
|
|
628
377
|
uses the system credential store.
|
|
629
378
|
|
|
630
379
|
### Process Management
|
|
631
380
|
|
|
632
|
-
CTM should manage `devtunnel host <tunnel-id>` as a child process
|
|
633
|
-
the Cloudflare fallback process model:
|
|
381
|
+
CTM should manage `devtunnel host <tunnel-id>` as a child process:
|
|
634
382
|
|
|
635
383
|
- start with fixed argv, not shell strings;
|
|
636
384
|
- capture stdout and stderr;
|
|
637
385
|
- parse the public URL;
|
|
638
386
|
- detect exit;
|
|
639
387
|
- expose `Stop Tunnel`;
|
|
640
|
-
-
|
|
388
|
+
- restore desired-running tunnel state after CTM restart or Mac wake;
|
|
389
|
+
- do not restart CTM unless local bind/origin config requires it.
|
|
641
390
|
|
|
642
391
|
### Readiness
|
|
643
392
|
|
|
@@ -647,23 +396,13 @@ the Cloudflare fallback process model:
|
|
|
647
396
|
- user signed in;
|
|
648
397
|
- persistent tunnel exists;
|
|
649
398
|
- port `3456` configured;
|
|
650
|
-
-
|
|
399
|
+
- tunnel access is private;
|
|
400
|
+
- no anonymous connect access is detected;
|
|
651
401
|
- host process running;
|
|
652
402
|
- CTM allowed origin includes the tunnel URL;
|
|
653
|
-
- CTM device
|
|
403
|
+
- CTM client-device pairing can be generated for that origin.
|
|
654
404
|
|
|
655
|
-
Do not show
|
|
656
|
-
|
|
657
|
-
## Accessibility and Responsive Design
|
|
658
|
-
|
|
659
|
-
- Stepper labels must be text, not color-only state.
|
|
660
|
-
- All buttons must be at least 44px tall.
|
|
661
|
-
- QR must have a copyable link and short-code fallback.
|
|
662
|
-
- Status updates should use `aria-live="polite"`.
|
|
663
|
-
- The account reminder must be visible near the QR on desktop and phone-sized
|
|
664
|
-
setup screens.
|
|
665
|
-
- Error copy should state whether the problem is Microsoft auth, tunnel
|
|
666
|
-
process, CTM origin, or CTM pairing.
|
|
405
|
+
Do not show remote URLs before these checks pass.
|
|
667
406
|
|
|
668
407
|
## Test Plan
|
|
669
408
|
|
|
@@ -671,23 +410,38 @@ Manual happy path:
|
|
|
671
410
|
|
|
672
411
|
1. Install `devtunnel`.
|
|
673
412
|
2. Sign into Microsoft or GitHub.
|
|
674
|
-
3. Start persistent tunnel.
|
|
675
|
-
4. Confirm CTM shows
|
|
676
|
-
5.
|
|
677
|
-
6. Complete
|
|
678
|
-
7.
|
|
679
|
-
8.
|
|
680
|
-
9.
|
|
413
|
+
3. Start persistent private tunnel.
|
|
414
|
+
4. Confirm CTM shows both desktop and mobile URLs.
|
|
415
|
+
5. Open desktop URL from another browser/computer.
|
|
416
|
+
6. Complete Microsoft/GitHub tunnel auth if prompted.
|
|
417
|
+
7. Approve CTM browser pairing on the Mac.
|
|
418
|
+
8. Open a session and send a low-risk terminal/message action.
|
|
419
|
+
9. Open mobile URL and confirm the same auth architecture with `/m/`.
|
|
420
|
+
10. Stop tunnel and confirm remote clients lose access.
|
|
421
|
+
11. Start tunnel again and confirm clients resume without re-pairing.
|
|
422
|
+
12. Revoke the remote browser and confirm existing WebSocket closes.
|
|
681
423
|
|
|
682
424
|
Negative cases:
|
|
683
425
|
|
|
426
|
+
- anonymous tunnel access detected;
|
|
684
427
|
- expired claim;
|
|
685
428
|
- tunnel host process crash;
|
|
686
429
|
- tunnel URL changes;
|
|
687
430
|
- CTM allowed origin missing;
|
|
688
|
-
-
|
|
431
|
+
- provider sign-in appears before CTM;
|
|
432
|
+
- CTM device token missing;
|
|
689
433
|
- high-risk action without CTM step-up.
|
|
690
434
|
|
|
435
|
+
Automated coverage should include:
|
|
436
|
+
|
|
437
|
+
- tunnel state normalization;
|
|
438
|
+
- anonymous-access drift detection;
|
|
439
|
+
- origin allowlist generation;
|
|
440
|
+
- pairing request lifecycle for desktop and mobile surfaces;
|
|
441
|
+
- HTTP route auth regression;
|
|
442
|
+
- WebSocket auth and revoke-close regression;
|
|
443
|
+
- audit event shape for remote desktop and mobile.
|
|
444
|
+
|
|
691
445
|
## MVP Cut Line
|
|
692
446
|
|
|
693
447
|
MVP includes:
|
|
@@ -695,26 +449,27 @@ MVP includes:
|
|
|
695
449
|
- setup card and stepper;
|
|
696
450
|
- CLI detection;
|
|
697
451
|
- sign-in status and account display;
|
|
698
|
-
- persistent tunnel create/reuse;
|
|
699
|
-
-
|
|
452
|
+
- persistent private tunnel create/reuse;
|
|
453
|
+
- anonymous-access drift detection and reset action;
|
|
700
454
|
- managed `devtunnel host` process;
|
|
701
455
|
- exact origin allowlist;
|
|
702
|
-
-
|
|
456
|
+
- desktop and mobile pairing links;
|
|
457
|
+
- shared client-device auth for `/` and `/m/`;
|
|
703
458
|
- stop tunnel;
|
|
704
459
|
- diagnostics copy.
|
|
705
460
|
|
|
706
461
|
MVP excludes:
|
|
707
462
|
|
|
708
|
-
-
|
|
463
|
+
- Cloudflare Tunnel;
|
|
464
|
+
- anonymous tunnel access;
|
|
465
|
+
- separate temporary desktop mode;
|
|
709
466
|
- team/tenant/org access controls;
|
|
710
|
-
- tunnel access tokens
|
|
711
|
-
- traffic inspection UI
|
|
712
|
-
- automatic public beta positioning as primary access.
|
|
467
|
+
- tunnel access tokens in browser URLs;
|
|
468
|
+
- traffic inspection UI.
|
|
713
469
|
|
|
714
470
|
## Recommendation
|
|
715
471
|
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
typed relay.
|
|
472
|
+
Use Microsoft Dev Tunnel as the default direct browser remote-access option.
|
|
473
|
+
Use Tailscale as the private-network alternative. Keep Walle Remote for typed
|
|
474
|
+
mobile relay workflows. Do not add Cloudflare Tunnel or a separate temporary
|
|
475
|
+
desktop mode to this plan.
|