# API / 模块合约 MVP 首先提供本地 Go application service 和 CLI;是否增加 loopback HTTP/WebSocket 在 T-203 决策。时间使用 RFC3339,路径使用规范化绝对路径。 ## 核心类型 代码权威类型位于 `internal/domain/browser.go`:`BrowserKind`、`LaunchSpec`、`InstanceStatus`、`InstanceView`、`BrowserEvent` 和稳定错误码。`LaunchSpec.Normalize()` 负责 browser kind、绝对 user data dir、受控的 loopback remote debugging port,以及非空时的 http/https URL 校验;空 URL 表示打开浏览器默认页。 `LaunchSpec` 使用已分配的 `RemoteDebugPort`;端口分配不属于 UI,也不允许由 `ExtraArgs` 覆盖。`InstanceView` 返回实际关联端口、PID、占用来源和归属。外部关联只公开经 `DevToolsActivePort` 与 `/json/version` 验证的端口,不公开 CDP WebSocket URL。 UI 编辑使用独立的 `EditableInstance` DTO(`ID`、名称、浏览器类型、User Data Dir、启动 URL、`ProxyID`),不将运行时 PID、状态、来源或实际远程调试端口写回配置。`ProxyProfile` DTO 只包含 `ID`、名称和已校验的无认证端点;不提供认证字段。状态刷新使用 `RefreshInstanceStatus(ctx, []InstanceSnapshot) ([]InstanceStatusResult, error)` 形状:每个结果以 `ID` 和快照版本对应,错误可按行返回;实现只能检查调用方提供的实例范围。 ## Application service ```go type BrowserManager interface { Start(ctx context.Context, spec LaunchSpec) (InstanceView, error) List(ctx context.Context) ([]InstanceView, error) Get(ctx context.Context, id string) (InstanceView, error) Stop(ctx context.Context, id string, force bool) error Restart(ctx context.Context, id string) (InstanceView, error) } ``` `Stop(force=false)` 只执行优雅关闭;强制关闭必须由明确用户动作或 CLI `--force` 触发。 平台实现通过实例级 `StopProfile(userDataDir, force)` 执行关闭;force 只对已注册并经过身份绑定的实例生效。 GUI 将优雅停止封装为异步 `InstanceStopper(ctx, InstanceRow) error` adapter;adapter 只接受当前配置行并执行 `force=false`,不暴露平台句柄或允许调用方传递任意 PID。 参数数组由 `internal/platform/browser.BuildArgs` 生成;Chrome/Edge executable 由同包 `Discoverer.Resolve` 解析。二者都不接收 shell 命令行字符串。CDP 端点检测和端口分配均通过 platform port 执行,UI 只消费 DTO 结果。 状态刷新和目录选择必须通过后台 adapter 回到 UI 结果通道;UI frame 不直接做进程、文件或 CDP I/O。刷新不构成外部实例接管授权。 ## CLI 当前合约 ```text chub start --browser chrome --user-data-dir