4.4 KiB
4.4 KiB
📑 MAM Web PTY WebSocket Bridge 개발 계획서
이 문서는 브라우저 환경에서 POSIX 가상 터미널(PTY) FFI에 직접 액세스할 수 없는 샌드박스 제약을 극복하고, apps/mam_web 클라이언트를 통해 세션 attach 및 제어 기능을 온전히 구동하기 위한 WebSocket PTY 브릿지 아키텍처 및 구현 계획을 정의합니다.
1. 아키텍처 개요 (Architecture Overview)
브라우저 단독으로는 로컬 리눅스의 시스템 호출(fork(), execvp(), fcntl(), waitpid())을 호출할 수 없으므로, 로컬 데몬으로 동작하는 초경량 WebSocket 프록시 브릿지 서버를 경유하여 양방향 터미널 스트림을 중계합니다.
graph TD
Client[\"MAM Web Client (Browser)\" - apps/mam_web]
Bridge[\"Shelf WebSocket Bridge (Daemon)\" - packages/mam_bridge]
PTY[\"POSIX PtySession (FFI)\" - packages/mam_pty]
Tmux[\"tmux -L multi-agent-mux attach\" - Local process]
Client -- \"1. ws://localhost:8080/attach?session=demo\" --> Bridge
Bridge -- \"2. spawn PTY (fork-safe FFI)\" --> PTY
PTY -- \"3. dup2 redirect\" --> Tmux
Client -- \"4. Send inputs (keystrokes)\" --> Bridge
Bridge -- \"5. pty.writeString()\" --> PTY
PTY -- \"6. Stream stdout bytes\" --> Bridge
Bridge -- \"7. WebSocket Frame (text/binary)" --> Client
2. 상세 구현 사양 (Implementation Details)
2.1 PTY WebSocket Bridge 데몬 (packages/mam_bridge)
- 역할:
shelf및shelf_web_socket을 사용하여 로컬 루프백(127.0.0.1) 또는 지정 바인딩 포트에서 대기하는 HTTP/WebSocket 중계 서버 구현. - 접속 엔드포인트:
/ws/attach?session=<name>&server=<server_name> - 동작 시퀀스:
- WebSocket 핸드셰이크 요청이 도달하면 쿼리 파라미터(
session,server)를 검증합니다. packages/mam_pty의PtySession.start('tmux', ['-L', server, 'attach', '-t', session])을 안전하게 비동기 스폰합니다.PtySession.stdout바이트 스트림을 수신하는 즉시 WebSocket binary/text 프레임으로 래핑해 웹 브라우저로 전송합니다.- 웹 브라우저가 WebSocket 채널로 보낸 키보드/마우스 입력 데이터는
PtySession.writeString()으로 포워딩합니다. - WebSocket 연결이 끊어지거나 브라우저 탭이 닫히면
PtySession.close()를 즉시 호출하여 자식 tmux 프로세스를waitpid()로 소거(reap)하고 PTY FFI 핸들을 원자적으로 닫습니다.
- WebSocket 핸드셰이크 요청이 도달하면 쿼리 파라미터(
2.2 MAM Web 클라이언트 UI (apps/mam_web)
- 역할: 대시보드 그리드 및 WebSocket 기반 터미널 위젯 이식.
- 상태 관리: 기존 M1/M2의
StatusRepository및 Riverpod 폴링 스트림을 웹 클라이언트 사양으로 동일하게 공유하여 대시보드 그리드를 유지합니다. TerminalPane웹 전용 컴포넌트:- PTY FFI 라이브러리를 임포트하지 않고
package:web_socket_channel/web_socket_channel.dart를 사용하여 백엔드 브릿지 서버에 소켓을 연결합니다. - 소켓 스트림(
channel.stream)을xtermv4.0.0Terminal로 바인딩합니다. Terminal.onOutput콜백을 통해 발생하는 사용자 타이핑 데이터는channel.sink.add()를 통해 WebSocket 프레임으로 쏩니다.- 터미널 리사이즈(
Terminal.onResize) 이벤트가 발생하면{"action": "resize", "cols": cols, "rows": rows}형태의 JSON 제어 프레임을 소켓으로 전송하여 백엔드 PTY FFI 단에서ioctl(TIOCSWINSZ)이 기동되도록 연동합니다.
- PTY FFI 라이브러리를 임포트하지 않고
3. 안정성 및 보안 요구사항 (DoD Requirements)
- 자원 누수 방지 (Anti-Leak): 웹 브라우저가 갑자기 종료되거나 네트워크 끊김 현상이 발생할 때, 백엔드 데몬이 하트비트 (Ping-Pong) 또는 소켓 에러 이벤트를 즉각 감지해
waitpid()를 호출함으로써 좀비 defunct 프로세스가 시스템에 잔존하지 않도록 확실히 보증합니다. - 비블로킹 보장 (Non-blocking): 데몬 서버 단에서도
fcntlO_NONBLOCK 및 non-blocking read loop가 동일하게 가동되어 다중 브라우저가 접속하더라도 백엔드 이벤트 루프가 정지되지 않도록 차단합니다. - 접속 권한 제어: 브릿지 서버는 기본적으로 로컬호스트(
127.0.0.1) 바인딩으로 기동하여 외부 원격지로부터의 악성 터미널 탈취 공격을 원천 봉쇄합니다.