Golden Path E2E: Add Server → Create Project → Create Session → Create Terminal → Terminal I/O
Field
Value
Priority
P0 (Smoke)
Source
00-strategy.md, architecture/domain-model.md
Time budget
< 10 minutes from app launch to verified terminal output
Status
Active
Requirement
Details
OS
Linux (Ubuntu 24.04 LTS recommended) or macOS with Docker
Docker
Engine 24.0+, daemon running
Ports
50051 (gRPC), 8080 (REST/SSE) free
Network
Client machine can reach server on both ports
Git repo
A small public repository for cloning
Requirement
Details
OS
macOS 26+ (Apple Silicon)
App
Relay.app built and installed
# 1. Build the runner (or use a pre-built binary)
cd runner && cargo build --release
# 2. Initialize cloud mode
./target/release/relay-runner init --cloud
# Save the bearer token printed to stdout
# 3. Start the server
RUST_LOG=info ./target/release/relay-runner
# Confirm gRPC :50051 and REST :8080 in logs
Action
Open Relay.app. Sidebar → "+" (Add Server). Select Cloud REST . Fill: REST API URL = http://<host>:8080, Token = bearer token. Click Add .
Expected
Server appears in sidebar.
Fail
Form missing fields, Add unavailable, server not in list.
Action
Click server → Connect .
Expected
Green indicator. Projects list displayed (empty on fresh server).
Fail
Connect fails, error loading projects.
Action
Click "+" (Create Project). Fill: Name = e2e-test, Git URL = https://github.com/nicklockwood/SwiftFormat.git. Click Create .
Expected
Sheet dismisses. Project appears with badge cloning .
Fail
Validation error, project not appearing.
Step 4 — Wait for clone (SSE)
Action
Watch project list. No manual refresh.
Expected
Badge changes cloning → ready via SSE project_state_changed. < 60s for small repo.
Fail
Stays cloning > 2 min, goes to failed, manual refresh needed.
Step 5 — Open project sessions
Action
Click e2e-test project (state = ready ).
Expected
Session Management view. Sessions list empty. Project name in header.
Fail
Nothing happens, navigation broken.
Action
Click "+" (Create Session). Select a profile. Click Create .
Expected
Sheet dismisses. Session appears with badge starting .
Fail
Validation error, session not appearing.
Step 7 — Wait for session start (SSE)
Action
Watch session list. No manual refresh.
Expected
Badge starting → running via SSE session_state_changed. < 30s.
Fail
Stays starting > 2 min, goes to failed.
Action
Click "Open Terminal" on running session.
Expected
New terminal tab opens. Shell prompt visible. Tab title includes project/session name.
Fail
Button not enabled, tab doesn't open, blank terminal.
Step 9 — Verify terminal I/O
Action
Type echo e2e-ok and press Enter.
Expected
Terminal displays e2e-ok. No garbled characters, latency < 1s.
Fail
No output, garbled output, freeze.
Bonus
Try ls, pwd, whoami, clear.
Step 10 — Close terminal tab
Action
Close tab (Cmd+W or close button).
Expected
Tab closes. Session remains running in session list.
Fail
Session state changes, app crash.
Action
Click Stop on running session.
Expected
Badge → stopped via SSE. "Open Terminal" disabled.
Fail
Session stays running, no SSE update.
Step 12 — Verify final state
Action
Navigate back to project list, then server list.
Expected
Project = ready . Server = Connected . Stopped session visible with stopped badge.
Fail
Unexpected state changes.
SSE verification checklist
Step
SSE event
Observable effect
4
project_state_changed
Badge: cloning → ready
7
session_state_changed
Badge: starting → running
11
session_state_changed
Badge: running → stopped
Criteria
Requirement
All 12 steps pass without errors
MUST
SSE updates visible real-time (3 events)
MUST
Total scenario time < 10 minutes
MUST
No app crashes or hangs
MUST
Terminal I/O latency < 1 second
SHOULD
No manual refresh needed
SHOULD
Verdict: PASS only if all MUST criteria are met.
ServerListView (sidebar)
→ ServerFormView (Add Server sheet)
→ ServerFormFeature (validates, saves ServerCredential)
→ ServerListFeature (connects, green badge)
Cloud server tapped:
→ CloudNavigationFeature
→ ProjectListView
→ CreateProjectSheet / CreateProjectFormFeature
→ ProjectClient (REST: POST /api/v1/projects)
→ SSE: project_state_changed → ProjectListFeature updates state
→ Project tapped (ready):
→ SessionManagementView / SessionManagementFeature
→ CreateSessionSheet / CreateSessionFormFeature
→ SessionClient (REST: POST /api/v1/projects/{id}/sessions)
→ SSE: session_state_changed → SessionListFeature updates state
→ "Open Terminal":
→ CloudNavigationFeature.Delegate.openCloudTerminal(server, session)
→ MainFeature → TerminalFeature with remoteServer
→ REST: POST /api/v1/sessions/{id}/terminals
→ RemoteTerminalSession (gRPC: AttachTerminal)
→ TabFeature adds terminal tab
Tab closed:
→ TerminalFeature detaches (gRPC DetachRequest) — session stays running
Stop session:
→ SessionClient (REST: POST /api/v1/sessions/{id}/stop)
→ SSE: session_state_changed → stopped