네, 방향이 맞습니다. 그리고 그 선택을 하신 이상 "3개 OS 공통"이라는 성질이 저절로 따라오지는 않고, 딱 하나의 메커니즘이 그걸 보장합니다 — 에이전트가 자기 능력(capability)을 광고하고 UI가 그에 맞춰 기능을 켜고 끄는 것. 이게 "FreeBSD/Windows는 가능한 기능만 노출"이라는 이점을 실제로 만들어 주는 축입니다. 이 축을 중심으로 설계가 어떻게 잡히는지 구체화하겠습니다. 채널 동사 집합 — 콘솔/원격제어 MVP 지금 가진 stream(=TUNNEL) 위에 소수의 동사만 얹으면 됩니다. 원격 제어/콘솔에 실제로 필요한 건 이만큼입니다. 채널 type 용도 Linux FreeBSD Windows stream 소켓/유닉스소켓 바이트 파이프 (VNC·SSH·내부 HTTP) 보유 동일 동일 spawn (+pty 옵션) 프로세스 실행 / 터미널 forkpty forkpty ConPTY fs.read 파일 읽기 (청크) ✓ ✓ 경로 정규화 fs.write 원자적 쓰기 rename() rename() MoveFileEx fs.list 디렉터리 나열 ✓ ✓ 드라이브 레터 fs.watch 변경 감시 (선택) inotify kqueue RDCW 위 여섯이면 콘솔·터미널·파일 매니저가 다 열립니다. 그리고 이 목록에는 D-Bus도 metrics도 없다는 점이 중요합니다 — D-Bus는 Linux 전용이라 뺐고, 지표는 이미 eBPF/DTrace/ETW 자체 파이프라인이 Cockpit보다 낫기 때문에 포팅 대상이 아닙니다. 그래서 이 집합은 3개 OS에 균일하게 얹힙니다. 주의할 교차 OS 지점 두 개만 미리 짚으면, spawn은 셸 문자열이 아니라 argv 배열로 받아야 합니다(sh/cmd/powershell 인용 지옥 회피 — virt-xml 때 겪으신 그 문제와 동일). pty는 별도 동사가 아니라 spawn의 옵션 플래그입니다(Cockpit도 spawn + pty:true). Windows만 ConPTY(Win10 1809+)라 코드 경로가 갈리지만 동사는 하나로 유지됩니다. 프로토콜 일반화 — TUNNEL을 채널로 승격 지금은 사실상 "터널 하나 = 타겟 하나"에 가까울 텐데, 콘솔 플랫폼이 되려면 한 호스트에 터미널·파일 브라우저·VNC가 동시에 붙어야 합니다. 그래서 프레임에 채널 id를 넣어 하나의 에이전트↔릴레이 연결 위에서 다중화하는 게 첫 작업입니다. Cockpit이 WS 하나에 채널을 다중화하는 바로 그 구조입니다. { ch: <id>, op: OPEN | DATA | CTRL | CLOSE, type?, params? } 기존 TUNNEL_OPEN/DATA/CLOSE는 type="stream"인 채널의 op로 그대로 흡수됩니다. 즉 배관을 새로 짜는 게 아니라 봉투에 type과 ch만 추가하는 확장이라, 이미 만든 릴레이·프레이밍을 버리지 않습니다. 능력 광고 — "가능한 기능만 노출"의 실제 구현 에이전트가 agent_ready 시점에 지원 동사 목록을 함께 등록합니다. caps: ["stream", "spawn", "spawn.pty", "fs.read", "fs.write", "fs.list", "metrics.dtrace"] 대시보드는 이 목록을 읽어 버튼을 켜고 끕니다. FreeBSD 에이전트가 spawn.pty는 광고하되 Windows ETW 관련 능력은 광고하지 않으면, UI에서 해당 기능이 자동으로 비활성화됩니다. 이 광고-게이팅 한 쌍이 없으면 3개 OS 공통이라는 성질은 성립하지 않고, 있으면 공짜로 성립합니다. 이미 alias_uuid를 nodes 컬렉션에 등록하고 계시니, 그 레코드에 caps 배열을 얹는 정도의 확장입니다. 보안 — 동사마다 권한 상승임을 잊지 말 것 이건 반복해서 강조합니다. spawn은 임의 코드 실행, fs.write는 임의 파일 쓰기입니다. C2 성격이라 어느 정도 의도된 능력이지만, 각 동사는 policy.json 게이트를 통과해야 합니다 — fs.*는 허용 경로 루트, stream은 타겟 allowlist(앞서 SSRF 우려로 짚은 그것), spawn은 최소한 감사 로깅. 능력을 여는 순서와 정책을 여는 순서를 같이 가는 게 안전합니다. 권고 빌드 순서 첫째, 프레임에 ch id를 넣어 다중화부터 확보합니다(터미널·파일·VNC 동시 접속의 전제). 둘째, spawn+pty를 넣습니다 — stream과 가장 가까워 ROI가 제일 높고, 이걸로 터미널이 바로 열립니다. 셋째, fs.read/fs.list/fs.write 순으로 파일 매니저를 채웁니다. 넷째, caps 광고와 UI 게이팅을 붙여 3-OS 분기를 자동화합니다. fs.watch와 (원한다면) Linux 전용 D-Bus는 그 뒤로 미룹니다. 이 순서면 지금 붙들고 계신 VNC(=stream의 한 사례)를 끝내는 것이 곧 전체 채널 모델의 첫 벽돌이 됩니다. 헛일이 아니라 토대라는 뜻입니다. 시작점으로, 다중화용 채널 봉투 스키마(ch/op/type/params와 기존 TUNNEL_* 매핑)를 확정하는 것부터 잡으시겠어요, 아니면 spawn+pty의 3-OS 구현(forkpty/ConPTY 분기) 설계를 먼저 보시겠어요?