From ec33761a555bc7c2062a18befe894346bb7d8815 Mon Sep 17 00:00:00 2001 From: andy <1@zhoulujun.cn> Date: Mon, 25 May 2026 00:16:37 +0800 Subject: [PATCH 01/22] feat: init blueprint with full spec and boilerplate #1 Co-authored-by: Cursor --- .cursor/rules/nestjs-server.mdc | 13 + .cursor/rules/react-rspack.mdc | 12 + .cursor/rules/typescript-biome.mdc | 25 + .cursor/rules/vista-remote-core.mdc | 17 + .editorconfig | 21 + .gitattributes | 5 + .github/CODEOWNERS | 7 + .github/ISSUE_TEMPLATE/bug_report.yml | 53 ++ .github/ISSUE_TEMPLATE/config.yml | 8 + .github/ISSUE_TEMPLATE/feature_request.yml | 33 + .github/PULL_REQUEST_TEMPLATE.md | 48 + .github/dependabot.yml | 14 + .github/workflows/dependency-review.yml | 17 + .github/workflows/meta-ci.yml | 44 + .gitignore | 28 + .husky/commit-msg | 1 + .husky/pre-commit | 1 + .npmrc | 1 + .nvmrc | 1 + .vista-env | 1 + .vscode/extensions.json | 4 + AGENTS.md | 42 + CODE_OF_CONDUCT.md | 19 + COMMERCIAL-LICENSE.md | 16 + CONTRIBUTING.md | 169 ++++ DEVELOPMENT.md | 51 + LICENSE | 53 ++ SECURITY.md | 30 + biome.json | 17 + commitlint.config.cjs | 1 + config/environments/README.md | 18 + config/environments/dev.env | 19 + config/environments/local.env | 26 + config/environments/sit.env | 18 + config/environments/uat.env | 18 + dev.ps1 | 17 + dev.sh | 9 + init.ps1 | 21 + init.sh | 68 ++ package.json | 29 + pnpm-lock.yaml | 888 ++++++++++++++++++ readme.md | 85 ++ readme.zh-CN.md | 95 ++ spec/README.md | 89 ++ spec/agent-distribution-spec.md | 130 +++ spec/ai-behavior-architecture-spec.md | 147 +++ spec/ai-finetune-spec.md | 82 ++ spec/ai-platform-spec.md | 262 ++++++ spec/ai-spec.md | 44 + spec/architecture-foundation-spec.md | 54 ++ spec/authorization-spec.md | 221 +++++ spec/billing-commerce-spec.md | 115 +++ spec/cicd-release-spec.md | 131 +++ spec/commercial-resources-spec.md | 88 ++ spec/commercial-tier-spec.md | 114 +++ spec/deploy-spec.md | 157 ++++ spec/desktop-performance-spec.md | 169 ++++ spec/desktop-spec.md | 176 ++++ spec/developer-experience-spec.md | 85 ++ spec/docs-spec.md | 112 +++ spec/engineering-standards-spec.md | 141 +++ spec/enterprise-security-spec.md | 140 +++ spec/frontend-toolchain-spec.md | 123 +++ spec/git-collaboration-spec.md | 148 +++ spec/implementation-status.md | 91 ++ spec/licensing-spec.md | 72 ++ spec/messaging-transport-spec.md | 90 ++ spec/meta-repo-development-spec.md | 253 +++++ spec/mobile-spec.md | 115 +++ spec/performance-roadmap-spec.md | 121 +++ spec/product-positioning-spec.md | 60 ++ spec/recording-playback-spec.md | 155 +++ spec/server-spec.md | 236 +++++ spec/shared-spec.md | 259 +++++ spec/spec-driven-development-spec.md | 116 +++ spec/system-overview.md | 245 +++++ spec/web-admin-spec.md | 204 ++++ spec/web-client-spec.md | 83 ++ spec/web-spec.md | 97 ++ spec/webrtc-architecture-spec.md | 162 ++++ test.hmlt.html | 0 tooling/README.md | 148 +++ tooling/biome.desktop.json | 14 + tooling/biome.json | 63 ++ tooling/biome.mobile.json | 29 + tooling/biome.server.json | 36 + tooling/biome.web.json | 46 + tooling/commitlint.config.cjs | 33 + tooling/commitlint.config.subrepo.cjs | 9 + tooling/cursor/ai-worker.mdc | 12 + tooling/cursor/deploy-infra.mdc | 11 + tooling/cursor/docs-rspress.mdc | 11 + tooling/cursor/electron-desktop.mdc | 12 + tooling/cursor/mobile-rn.mdc | 11 + tooling/cursor/nestjs-server.mdc | 13 + tooling/cursor/react-rspack.mdc | 12 + tooling/cursor/shared-protocol.mdc | 11 + tooling/cursor/typescript-biome.mdc | 13 + tooling/cursor/vista-remote-core.mdc | 15 + .../github/actions/setup-shared/action.yml | 54 ++ tooling/github/workflows/ci-node.yml | 85 ++ .../github/workflows/dependency-review.yml | 17 + .../workflows/release-service-docker.yml | 72 ++ tooling/github/workflows/release-shared.yml | 76 ++ .../github/workflows/release-web-static.yml | 49 + tooling/github/workflows/sync-shared.yml | 94 ++ tooling/husky/commit-msg.sh | 3 + tooling/husky/pre-commit.sh | 11 + tooling/scripts/apply-env.mjs | 113 +++ tooling/scripts/build-agent-packages.mjs | 42 + tooling/scripts/dev-up.mjs | 105 +++ tooling/scripts/ensure-shared.mjs | 63 ++ tooling/scripts/lib/paths.mjs | 37 + tooling/scripts/pin-shared-version.mjs | 87 ++ tooling/scripts/restore-shared-file-deps.mjs | 33 + tooling/scripts/run-with-env.mjs | 34 + tooling/scripts/setup-github-workflows.mjs | 162 ++++ tooling/scripts/setup-husky.mjs | 55 ++ tooling/scripts/setup-ide-config.mjs | 143 +++ tooling/scripts/setup-single-repo.mjs | 62 ++ tooling/templates/editorconfig | 21 + tooling/templates/gitignore.deploy | 19 + tooling/templates/gitignore.docs | 12 + tooling/templates/gitignore.node-ts | 55 ++ tooling/templates/npmrc.github-packages | 3 + tooling/templates/vscode/extensions.json | 4 + tooling/templates/vscode/settings.json | 35 + vista-remote.code-workspace | 50 + 128 files changed, 9245 insertions(+) create mode 100644 .cursor/rules/nestjs-server.mdc create mode 100644 .cursor/rules/react-rspack.mdc create mode 100644 .cursor/rules/typescript-biome.mdc create mode 100644 .cursor/rules/vista-remote-core.mdc create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/CODEOWNERS create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/dependency-review.yml create mode 100644 .github/workflows/meta-ci.yml create mode 100644 .gitignore create mode 100644 .husky/commit-msg create mode 100644 .husky/pre-commit create mode 100644 .npmrc create mode 100644 .nvmrc create mode 100644 .vista-env create mode 100644 .vscode/extensions.json create mode 100644 AGENTS.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 COMMERCIAL-LICENSE.md create mode 100644 CONTRIBUTING.md create mode 100644 DEVELOPMENT.md create mode 100644 LICENSE create mode 100644 SECURITY.md create mode 100644 biome.json create mode 100644 commitlint.config.cjs create mode 100644 config/environments/README.md create mode 100644 config/environments/dev.env create mode 100644 config/environments/local.env create mode 100644 config/environments/sit.env create mode 100644 config/environments/uat.env create mode 100644 dev.ps1 create mode 100644 dev.sh create mode 100644 init.ps1 create mode 100644 init.sh create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 readme.md create mode 100644 readme.zh-CN.md create mode 100644 spec/README.md create mode 100644 spec/agent-distribution-spec.md create mode 100644 spec/ai-behavior-architecture-spec.md create mode 100644 spec/ai-finetune-spec.md create mode 100644 spec/ai-platform-spec.md create mode 100644 spec/ai-spec.md create mode 100644 spec/architecture-foundation-spec.md create mode 100644 spec/authorization-spec.md create mode 100644 spec/billing-commerce-spec.md create mode 100644 spec/cicd-release-spec.md create mode 100644 spec/commercial-resources-spec.md create mode 100644 spec/commercial-tier-spec.md create mode 100644 spec/deploy-spec.md create mode 100644 spec/desktop-performance-spec.md create mode 100644 spec/desktop-spec.md create mode 100644 spec/developer-experience-spec.md create mode 100644 spec/docs-spec.md create mode 100644 spec/engineering-standards-spec.md create mode 100644 spec/enterprise-security-spec.md create mode 100644 spec/frontend-toolchain-spec.md create mode 100644 spec/git-collaboration-spec.md create mode 100644 spec/implementation-status.md create mode 100644 spec/licensing-spec.md create mode 100644 spec/messaging-transport-spec.md create mode 100644 spec/meta-repo-development-spec.md create mode 100644 spec/mobile-spec.md create mode 100644 spec/performance-roadmap-spec.md create mode 100644 spec/product-positioning-spec.md create mode 100644 spec/recording-playback-spec.md create mode 100644 spec/server-spec.md create mode 100644 spec/shared-spec.md create mode 100644 spec/spec-driven-development-spec.md create mode 100644 spec/system-overview.md create mode 100644 spec/web-admin-spec.md create mode 100644 spec/web-client-spec.md create mode 100644 spec/web-spec.md create mode 100644 spec/webrtc-architecture-spec.md create mode 100644 test.hmlt.html create mode 100644 tooling/README.md create mode 100644 tooling/biome.desktop.json create mode 100644 tooling/biome.json create mode 100644 tooling/biome.mobile.json create mode 100644 tooling/biome.server.json create mode 100644 tooling/biome.web.json create mode 100644 tooling/commitlint.config.cjs create mode 100644 tooling/commitlint.config.subrepo.cjs create mode 100644 tooling/cursor/ai-worker.mdc create mode 100644 tooling/cursor/deploy-infra.mdc create mode 100644 tooling/cursor/docs-rspress.mdc create mode 100644 tooling/cursor/electron-desktop.mdc create mode 100644 tooling/cursor/mobile-rn.mdc create mode 100644 tooling/cursor/nestjs-server.mdc create mode 100644 tooling/cursor/react-rspack.mdc create mode 100644 tooling/cursor/shared-protocol.mdc create mode 100644 tooling/cursor/typescript-biome.mdc create mode 100644 tooling/cursor/vista-remote-core.mdc create mode 100644 tooling/github/actions/setup-shared/action.yml create mode 100644 tooling/github/workflows/ci-node.yml create mode 100644 tooling/github/workflows/dependency-review.yml create mode 100644 tooling/github/workflows/release-service-docker.yml create mode 100644 tooling/github/workflows/release-shared.yml create mode 100644 tooling/github/workflows/release-web-static.yml create mode 100644 tooling/github/workflows/sync-shared.yml create mode 100644 tooling/husky/commit-msg.sh create mode 100644 tooling/husky/pre-commit.sh create mode 100644 tooling/scripts/apply-env.mjs create mode 100644 tooling/scripts/build-agent-packages.mjs create mode 100644 tooling/scripts/dev-up.mjs create mode 100644 tooling/scripts/ensure-shared.mjs create mode 100644 tooling/scripts/lib/paths.mjs create mode 100644 tooling/scripts/pin-shared-version.mjs create mode 100644 tooling/scripts/restore-shared-file-deps.mjs create mode 100644 tooling/scripts/run-with-env.mjs create mode 100644 tooling/scripts/setup-github-workflows.mjs create mode 100644 tooling/scripts/setup-husky.mjs create mode 100644 tooling/scripts/setup-ide-config.mjs create mode 100644 tooling/scripts/setup-single-repo.mjs create mode 100644 tooling/templates/editorconfig create mode 100644 tooling/templates/gitignore.deploy create mode 100644 tooling/templates/gitignore.docs create mode 100644 tooling/templates/gitignore.node-ts create mode 100644 tooling/templates/npmrc.github-packages create mode 100644 tooling/templates/vscode/extensions.json create mode 100644 tooling/templates/vscode/settings.json create mode 100644 vista-remote.code-workspace diff --git a/.cursor/rules/nestjs-server.mdc b/.cursor/rules/nestjs-server.mdc new file mode 100644 index 0000000..0395b6a --- /dev/null +++ b/.cursor/rules/nestjs-server.mdc @@ -0,0 +1,13 @@ +--- +description: NestJS server 模块约定 +globs: "server/**/*.{ts,tsx}" +alwaysApply: false +--- + +# NestJS (server) + +- 分层:Controller → Service → Repository;Controller 不直接写复杂 SQL。 +- Entity 仅 TypeORM;生产禁止 `synchronize: true`,只用 migrations。 +- DTO / WS Payload 类型来自 `@vistaremote/shared`。 +- 套餐守卫:`PlanGuard` 校验 free/pro/pro/enterprise。 +- 不在 server 进程内调用 LLM;AI 任务投递 BullMQ 给 `ai` 服务。 diff --git a/.cursor/rules/react-rspack.mdc b/.cursor/rules/react-rspack.mdc new file mode 100644 index 0000000..55f0162 --- /dev/null +++ b/.cursor/rules/react-rspack.mdc @@ -0,0 +1,12 @@ +--- +description: React / Rsbuild 前端约定(web、desktop 渲染进程) +globs: "{web,desktop}/**/*.{ts,tsx,scss}" +alwaysApply: false +--- + +# React + Rsbuild + +- UI:**Ant Design 5**;样式 **Sass Modules**(`*.module.scss`),禁止 Tailwind 作为主方案。 +- 环境变量浏览器侧使用 `PUBLIC_*`(Rsbuild),不用 `VITE_*`。 +- Web 分 **apps/client**(用户端)与 **apps/admin**(管理台);共享组件放 `packages/ui`。 +- 远程桌面画布区域可用原生 video/Canvas;外壳布局用 antd。 diff --git a/.cursor/rules/typescript-biome.mdc b/.cursor/rules/typescript-biome.mdc new file mode 100644 index 0000000..9f1f177 --- /dev/null +++ b/.cursor/rules/typescript-biome.mdc @@ -0,0 +1,25 @@ +--- +description: TypeScript / TSX 与 Biome 代码风格 +globs: "**/*.{ts,tsx,js,jsx,mjs,cjs}" +alwaysApply: false +--- + +# TypeScript + Biome + +- 单引号、分号、2 空格缩进、行宽 100(与 `tooling/biome.json` 一致)。 +- 优先 `import type` 分离类型导入。 +- 避免 `any`;必要时加简短注释说明原因。 +- 未使用变量/导入:提交前必须清理(Biome `noUnusedVariables`)。 +- 公共 API 与跨端 DTO 只定义在 `@vistaremote/shared`,各端禁止重复声明契约字段。 +- 异步错误:记录上下文后 rethrow 或返回统一错误码,禁止空 `catch`。 + +```typescript +// ❌ +catch (e) {} + +// ✅ +catch (e) { + logger.error('pairing failed', { error: e }); + throw new BadRequestException('PAIRING_INVALID'); +} +``` diff --git a/.cursor/rules/vista-remote-core.mdc b/.cursor/rules/vista-remote-core.mdc new file mode 100644 index 0000000..f5b9a51 --- /dev/null +++ b/.cursor/rules/vista-remote-core.mdc @@ -0,0 +1,17 @@ +--- +description: VistaRemote 核心约定(Meta-Repo、Spec、套餐、MySQL) +alwaysApply: true +--- + +# VistaRemote 核心约定 + +- **架构**:Flat Meta-Repo + 多独立 Git 仓库;禁止 submodule。契约变更 **先 `shared`,再 `server`,再各客户端**。 +- **数据库**:仅 **MySQL 8** + TypeORM,不用 PostgreSQL。 +- **实时**:WebRTC P2P(1:1)/ SFU(1:N);信令在 server,AI 在独立 `ai` 仓库。 +- **前端**:Rsbuild + Ant Design + Sass(RN 用 Metro + antd-mobile)。 +- **AI**:多模型;端侧 `desktop/edge-ai`,LLM 在 `ai`;见 `spec/ai-behavior-architecture-spec.md`。 +- **实现前**:阅读 `spec/implementation-status.md`、`spec/spec-driven-development-spec.md`、`spec/system-overview.md` 与对应模块 Spec;未写入 Spec 的行为视为 Out of Scope。 +- **子仓库 IDE**:各子目录含 `.editorconfig`、`.vscode/`、`.cursor/rules/`、`AGENTS.md`(`node tooling/scripts/setup-ide-config.mjs` 同步)。 +- **Node.js**:**≥ 22**(开发/CI/生产统一;`.nvmrc` 为 **22.12 LTS**)。 +- **格式与检查**:使用 **Biome**(`pnpm check` / `pnpm check:fix`),勿引入 ESLint+Prettier 双栈。 +- **提交**:Conventional Commits,跨库功能使用**相同分支名**(如 `feat/webrtc-sfu`)。 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..99f53b3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +# VistaRemote — 跨编辑器基础风格(与 Biome 对齐) +# https://editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +[*.{yml,yaml}] +indent_size = 2 + +[Makefile] +indent_style = tab diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..20ac3a9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +* text=auto eol=lf +*.md linguist-detectable=true +*.mdx linguist-detectable=true +pnpm-lock.yaml linguist-generated=true +package-lock.json linguist-generated=true diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..22718f0 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,7 @@ +# Default reviewers for Meta-Repo (adjust teams/users when org is ready) +* @VistaRemote/maintainers + +/spec/ @VistaRemote/maintainers +/tooling/ @VistaRemote/maintainers +/.cursor/ @VistaRemote/maintainers +/docs/ @VistaRemote/maintainers diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..4f5845e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,53 @@ +name: Bug Report +description: Report a reproducible bug +title: "[bug]: " +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + 请勿在此提交**安全漏洞**,请�?[SECURITY.md](../../SECURITY.md)�? + - type: dropdown + id: repo + attributes: + label: Repository + options: + - server + - web + - desktop + - mobile + - shared + - ai + - docs + - deploy + - meta-repo + - unknown + validations: + required: true + - type: textarea + id: description + attributes: + label: What happened? + validations: + required: true + - type: textarea + id: reproduce + attributes: + label: Steps to reproduce + placeholder: "1. ...\n2. ..." + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected behavior + - type: input + id: version + attributes: + label: Version / commit + placeholder: e.g. main @ abc1234 + - type: textarea + id: env + attributes: + label: Environment + placeholder: OS, Node, browser, etc. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..81ea861 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues: false +contact_links: + - name: Documentation + url: https://github.com/VistaRemote/vista-remote/tree/main/docs + about: Rspress docs �?see docs/README.md for local preview + - name: Security + url: https://github.com/VistaRemote/vista-remote/blob/main/SECURITY.md + about: Report vulnerabilities privately diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..9f753f7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,33 @@ +name: Feature Request +description: Suggest an idea or Spec change +title: "[feat]: " +labels: ["enhancement"] +body: + - type: textarea + id: problem + attributes: + label: Problem / use case + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposed solution + validations: + required: true + - type: dropdown + id: tier + attributes: + label: Plan tier (if applicable) + options: + - free + - pro + - enterprise + - n/a + - type: checkboxes + id: spec + attributes: + label: Spec + options: + - label: Willing to update spec/ docs in the same PR cycle + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..ee4bba2 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,48 @@ +## Summary + + + +## Type + +- [] `feat` New feature +- [] `fix` Bug fix +- [] `docs` Documentation only +- [] `refactor` / `chore` / `ci` / `build` + +## Repositories touched + + + +- [] Meta-Repo (root) +- [] `shared` +- [] `server` +- [] `ai` +- [] `web` +- [] `desktop` +- [] `mobile` +- [] `docs` +- [] `deploy` +- [] Other: ___ + +## Spec & contracts + +- [] 已阅读/更新相关 Spec(`spec/*.md`) +- [] 列出 FR-xxx / US-xx(无行为变更请注明) +- [] 已对照 [implementation-status.md](spec/implementation-status.md) +- [] 若改 DTO/信令:已先改或同步 `shared` +- [] 涉及套餐/安全:符合 free/pro/enterprise 边界 +- [] 用户可见:已更新 `docs/docs/zh|en`(user 或 guide) + +## Quality + +- [] `biome check` / `pnpm lint` 通过 +- [] 构建通过(如适用) +- [] 已自测(简述步骤) + +## Related issues + +Closes # + +## Screenshots / logs + + diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..a2cf792 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: + - package-ecosystem: npm + directory: "/" + schedule: + interval: weekly + open-pull-requests-limit: 5 + groups: + biome: + patterns: + - "@biomejs/*" + commitlint: + patterns: + - "@commitlint/*" diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..da09420 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,17 @@ +name: Dependency Review + +on: + pull_request: + +permissions: + contents: read + pull-requests: write + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/dependency-review-action@v4 + with: + fail-on-severity: high diff --git a/.github/workflows/meta-ci.yml b/.github/workflows/meta-ci.yml new file mode 100644 index 0000000..1647d17 --- /dev/null +++ b/.github/workflows/meta-ci.yml @@ -0,0 +1,44 @@ +name: Meta-Repo CI + +on: + push: + branches: [main, dev] + pull_request: + branches: [main, dev] + +jobs: + biome: + name: Scaffold lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 9 + + - uses: actions/setup-node@v4 + with: + node-version: '22.12' + cache: pnpm + + - name: Install + run: pnpm install --frozen-lockfile || pnpm install + + - name: Biome check + run: pnpm check + + security-audit: + name: Dependency audit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 9 + - uses: actions/setup-node@v4 + with: + node-version: '22.12' + cache: pnpm + - run: pnpm install --frozen-lockfile || pnpm install + - run: pnpm audit --audit-level=high diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..05ed430 --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# Meta-Repo:不跟踪已克隆的子仓库目录(各自独立 Git) +/server/ +/desktop/ +/mobile/ +/web/ +/docs/ +/shared/ +/deploy/ +/ai/ +/ai-finetune/ + +# Meta-Repo 本地 tooling +node_modules/ +.pnpm-store/ +.pnpm-debug.log* + +# 环境 +.env +.env.local +!.env.example + +# OS / IDE +.DS_Store +Thumbs.db +*.log + +# 可选本地数据 +*.local diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 0000000..2e6b87e --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1 @@ +pnpm exec commitlint --edit "$1" diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..1889335 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +pnpm exec biome check --staged --files-ignore-unknown=true --no-errors-on-unmatched diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..b6f27f1 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..1d9b783 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +22.12.0 diff --git a/.vista-env b/.vista-env new file mode 100644 index 0000000..4083037 --- /dev/null +++ b/.vista-env @@ -0,0 +1 @@ +local diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..52af901 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["biomejs.biome", "editorconfig.editorconfig"], + "unwantedRecommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint"] +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..4c4b24b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,42 @@ +# VistaRemote — Agent / AI 协作说明 + +面向 Cursor、Copilot 等 AI 协作者。人类开发者请从 [DEVELOPMENT.md](./DEVELOPMENT.md) 与 [CONTRIBUTING.md](./CONTRIBUTING.md) 开始。 + +## 必读 Spec(按序) + +1. [spec/README.md](./spec/README.md) — 索引 +2. [spec/spec-driven-development-spec.md](./spec/spec-driven-development-spec.md) — **SDD 工作流** +3. [spec/implementation-status.md](./spec/implementation-status.md) — **禁止在 Blocked 依赖上虚构完整实现** +4. [spec/system-overview.md](./spec/system-overview.md) +5. 正在修改的模块 Spec(如 `spec/server-spec.md`) +6. 性能迭代(**仅 spec,不写 docs 用户页**):`spec/performance-roadmap-spec.md` + +## 硬约束 + +| 项 | 规则 | +| :--- | :--- | +| 契约 | 仅改 `shared`,再改其他仓库 | +| 数据库 | MySQL,不用 PostgreSQL | +| 格式化 | Biome,`pnpm check:fix` | +| 提交信息 | Conventional Commits + scope | +| AI 推理 | 仅 `ai` 仓库,不在 server/desktop 内嵌 LLM | +| Spec 边界 | 新行为须有 FR-xxx;无 FR 则先补 Spec | + +## 功能开发检查清单 + +- [ ] 已读 `implementation-status` 相关行 +- [ ] Spec diff(FR + 验收)与代码同 PR 或 Spec 先行 +- [ ] `shared` build/test 通过(若改契约) +- [ ] 用户可见 → `docs/docs/zh|en/user` 或 `guide` +- [ ] 更新 `spec/implementation-status.md`(若改变就绪度) + +## 输出要求 + +- 标明影响的 **FR-xxx** Requirement ID(若有) +- 说明是否触及 `shared` +- 给出建议验收步骤 +- 若仅为桩/演示,明确标注,勿写成生产就绪 + +## Cursor Rules + +详见 [.cursor/rules/](./.cursor/rules/)。 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..52dd437 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,19 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We pledge to make participation in VistaRemote a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +**Positive behavior:** respectful language, constructive feedback, focusing on community benefit, showing empathy. + +**Unacceptable behavior:** harassment, trolling, sexualized language, personal attacks, publishing others' private information without permission, or other conduct inappropriate in a professional setting. + +## Enforcement + +Project maintainers may remove, edit, or reject comments, commits, code, and issues that violate this Code of Conduct. Contact: maintainers via GitHub or security contact in [SECURITY.md](./SECURITY.md). + +## Attribution + +Adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1. diff --git a/COMMERCIAL-LICENSE.md b/COMMERCIAL-LICENSE.md new file mode 100644 index 0000000..c980862 --- /dev/null +++ b/COMMERCIAL-LICENSE.md @@ -0,0 +1,16 @@ +# Commercial license + +VistaRemote is **free for personal, non-commercial use** under [LICENSE](./LICENSE). + +**All commercial use requires a paid commercial license**, including but not limited to: + +- Internal business deployment for employees +- Managed hosting or SaaS for customers +- Embedding in a commercial product +- IT services that generate revenue using VistaRemote + +Contact the project maintainers for pricing and terms. + +Technical feature gating (trial, Pro, Enterprise) is described in `spec/commercial-tier-spec.md`. + +Proprietary **model fine-tuning** tooling is not in the public repositories; see `spec/ai-finetune-spec.md`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e6a13ef --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,169 @@ +# Contributing to VistaRemote + +感谢参与 **VibeCode · VistaRemote** 开源协作。本项目为 **Meta-Repo + 多独立 Git 仓库**,请先阅读本指南与 [spec/engineering-standards-spec.md](./spec/engineering-standards-spec.md)。 + +--- + +## 快速链接 + +| 文档 | 说明 | +| :--- | :--- | +| **[DEVELOPMENT.md](./DEVELOPMENT.md)** | **开发入口**(命令、Spec 顺序) | +| [SDD 规范](./spec/spec-driven-development-spec.md) | Spec 先行、FR、PR 义务 | +| [实现状态](./spec/implementation-status.md) | 什么能写、什么是桩 | +| [工程规范 Spec](./spec/engineering-standards-spec.md) | Biome、CI、PR、开源惯例 | +| [Git 协作 Spec](./spec/git-collaboration-spec.md) | 分支、提交、跨库顺序 | +| [CI/CD 与发布 Spec](./spec/cicd-release-spec.md) | shared 发布、下游自动 bump、分仓 tag | +| [Spec 索引](./spec/README.md) | 实现前必读 | +| [文档站](./docs/README.md) | Rspress:`cd docs && pnpm dev` | +| [AGENTS.md](./AGENTS.md) | AI 协作者约定 | + +--- + +## 1. 环境准备 + +- **Node.js** ≥ 22(推荐 `.nvmrc` 中的 **22.12 LTS**,与 Rspack/Rstest 及生产环境一致) +- **pnpm** ≥ 9 +- **Git** 2.40+ +- 克隆 Meta-Repo 后执行 `./init.sh`(Windows:`.\init.ps1`)拉取子仓库 +- **一键本地环境**:`./dev.sh` 或 `pnpm dev:up`(见 [开发者体验 Spec](./spec/developer-experience-spec.md)) +- **切换 API 环境**:`pnpm env:local` | `env:dev` | `env:sit` | `env:uat` 后重启各端 dev 进程 + +### IDE(必做) + +使用 **`vista-remote.code-workspace`** 打开多根工作区,否则只能看到一个 Git 仓库。 + +安装推荐扩展(Cursor/VS Code 会提示): + +- [Biome](https://marketplace.visualstudio.com/items?itemName=biomejs.biome) — 格式化与 Lint +- EditorConfig for VS Code + +**各子仓库**(`server/`、`web/`、`ai/` 等)也有独立的: + +- `.editorconfig`、`.vscode/settings.json`(保存时 Biome 格式化) +- `.cursor/rules/`(仓专属 Cursor Rules) +- `AGENTS.md`(本仓协作说明) + +在 Meta-Repo 根目录同步 IDE 模板: + +```bash +node tooling/scripts/setup-ide-config.mjs +``` + +--- + +## 2. 代码规范:Biome + +我们使用 **[Biome](https://biomejs.dev/)** 统一格式化与静态检查(不用 Prettier + ESLint 双栈)。 + +```bash +# Meta-Repo 根目录 +pnpm install +pnpm check # 检查 +pnpm check:fix # 检查并自动修复 +``` + +各子仓库(`server`、`web` 等)在引入 `package.json` 后应: + +1. 复制 [`tooling/biome.json`](./tooling/biome.json) 为仓库根 `biome.json`(或 extends) +2. 添加脚本:`"lint": "biome check ."` +3. CI 中运行 `pnpm lint` + +配置说明见 [tooling/README.md](./tooling/README.md)。 + +**重要(Meta-Repo)**:在根目录 `pnpm check` **不会**检查 `web/`、`server/` 等子目录业务代码。请到对应子仓库执行 `pnpm lint`。单独开发/发布见 [spec/meta-repo-development-spec.md](./spec/meta-repo-development-spec.md)。 + +--- + +## 3. Git 提交规范 + +采用 [Conventional Commits](https://www.conventionalcommits.org/): + +```text +feat(web): add pairing page form validation +fix(server): correct plan guard for free users +docs(docs): document PR workflow +``` + +- **跨库功能**:各仓库使用 **相同分支名** +- **改协议**:必须先合并 `shared`,再合 `server` / 客户端 + +### 提交前检查(子仓库) + +在 **业务子仓库**(如 `server/`、`web/`)执行 `pnpm install` 后会安装 Husky: + +| 阶段 | 检查 | +| :--- | :--- | +| `pre-commit` | 暂存文件 Biome + **Rstest 单测** | +| `commit-msg` | Conventional Commits(commitlint) | + +Meta-Repo 根目录仅校验脚手架与提交信息,**不**跑子仓单测。配置见 [tooling/README.md](./tooling/README.md)。 + +```bash +cd server && pnpm install # 生成 .husky +git commit -m "feat(server): add health check" +``` + +详见 [spec/git-collaboration-spec.md](./spec/git-collaboration-spec.md)。 + +--- + +## 4. Pull Request 流程 + +1. Fork(外协)或在本组织仓库创建分支 +2. 确保 `pnpm check` / 子项目 `pnpm lint` 通过 +3. 推送并创建 PR,填写 [PR 模板](.github/PULL_REQUEST_TEMPLATE.md) +4. 等待 CI 与 Code Review +5. 维护者 Squash merge 到 `main` + +**Review 关注点**:Spec 合规、`shared` 顺序、无密钥、套餐权限、测试说明。 + +--- + +## 5. 发布与 CI/CD(多仓) + +推荐顺序见 [spec/cicd-release-spec.md](./spec/cicd-release-spec.md): + +1. **`shared`**:合并后打 tag `v0.2.0` → 发布 `@vistaremote/shared` 到 GitHub Packages,并 `repository_dispatch` 通知消费者。 +2. **消费者**(server / web / ai / desktop / mobile):`sync-shared.yml` 自动开 PR 升级依赖;合并后打各自 tag(如 `server-v0.2.0`)。 +3. **`deploy`**:更新 compose 中的镜像 tag,打 `deploy-v*`。 + +**组织 Secret**(在 `VistaRemote/shared` 仓库配置): + +- `VISTAREMOTE_CI_PAT`:跨仓触发 `shared-published`(需 `repo` + `workflow` 权限)。 + +**本地仍用 `file:../shared`** 联调;需要恢复 file 依赖时: + +```bash +node tooling/scripts/restore-shared-file-deps.mjs +``` + +同步 GitHub Actions 模板到各子仓: + +```bash +node tooling/scripts/setup-github-workflows.mjs +``` + +--- + +## 6. 行为准则与安全 + +- [Contributor Covenant](./CODE_OF_CONDUCT.md) +- 漏洞报告见 [SECURITY.md](./SECURITY.md),**请勿**公开提 Issue + +--- + +## 7. 文档贡献 + +- 用户文档:编辑 `docs/docs/zh/`(及 `en/`),在 `docs/` 目录 `pnpm dev` 预览 +- Spec:先改 Meta-Repo `spec/`,再同步子仓库 `spec/SPEC.md` + +--- + +## 8. 问题反馈 + +使用 GitHub Issue 模板(Bug / Feature)。提供:环境、复现步骤、期望与实际、相关仓库名。 + +--- + +再次感谢你的贡献。 diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..59d0145 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,51 @@ +# VistaRemote 开发入口 + +> 人类开发者从这里开始;AI 协作者另读 [AGENTS.md](./AGENTS.md)。 + +## 5 分钟上手 + +```bash +git clone git@github.com:VistaRemote/vista-remote.git +cd vista-remote +nvm use +./init.sh # Windows: .\init.ps1 +./dev.sh # Windows: .\dev.ps1 +``` + +打开 `vista-remote.code-workspace`。 + +## 必读(Spec-Driven) + +| 顺序 | 文档 | +| :--- | :--- | +| 1 | [spec/README.md](./spec/README.md) — Spec 索引 | +| 2 | [spec/spec-driven-development-spec.md](./spec/spec-driven-development-spec.md) — **如何改需求、写 FR、提 PR** | +| 3 | [spec/implementation-status.md](./spec/implementation-status.md) — **什么能写、什么还是桩** | +| 4 | 你负责的模块 Spec(如 `spec/server-spec.md`) | +| — | 性能路线图(**仅 spec**):`spec/performance-roadmap-spec.md` | + +## 常用命令 + +| 命令 | 作用 | +| :--- | :--- | +| `pnpm env:local` / `env:dev` / `env:sit` / `env:uat` | 切换 API 环境(重启 dev 进程生效) | +| `pnpm dev:up` | 本地 Docker + install + build shared | +| `cd server && pnpm start:dev` | 信令/API | +| `cd web && pnpm --filter @vistaremote/web-client dev` | Web 主控 | + +单仓(仅 desktop/mobile):在该仓库执行 `pnpm setup`。 + +## 文档站 + +```bash +cd docs && pnpm install && pnpm dev +``` + +- 开发者手册:`/guide/developer-handbook` +- 二开与定制:`/guide/customization` +- Desktop 性能:`/architecture/desktop-performance` +- 用户指南:`/user/remote-control` + +## 贡献流程 + +[CONTRIBUTING.md](./CONTRIBUTING.md) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..93efb46 --- /dev/null +++ b/LICENSE @@ -0,0 +1,53 @@ +VistaRemote Open Source License +Version 1.0, May 2026 + +Copyright (c) 2026 VistaRemote contributors + +TERMS + +1. Definitions + + "Software" means the VistaRemote source code and documentation in this + repository and related public sub-repositories under the same license. + + "Personal Use" means use by an individual for personal learning, research, + or hobby purposes, where the use is not intended for or directed toward + commercial advantage or monetary compensation. + + "Commercial Use" means any use of the Software in or for a business, + organization, revenue-generating activity, or product or service offered + to third parties for a fee or other consideration, including internal + business operations, managed hosting for clients, SaaS, and embedding in + commercial products. + +2. Grant for Personal Use + + Permission is hereby granted, free of charge, to any person obtaining a + copy of the Software, to use, copy, modify, and distribute the Software + for Personal Use only, subject to the conditions in Section 4. + +3. Commercial Use + + Commercial Use is NOT permitted under this license. You must obtain a + separate written commercial license from the copyright holder before any + Commercial Use. + +4. Conditions + + - Redistributions must retain this license and copyright notice. + - Modified versions must state significant changes. + - The Software is provided "AS IS", without warranty of any kind. + +5. No Trademark License + + This license does not grant permission to use the trade names, trademarks, + or logos of VistaRemote. + +6. Third-Party Components + + The Software may include third-party components under their own licenses. + Model weights (e.g. Llama, Qwen) are governed by their upstream licenses. + Proprietary fine-tuned model bundles are not part of this open-source + grant; see spec/ai-finetune-spec.md. + +For commercial licensing: contact the project maintainers (see README). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..8464d81 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| :--- | :--- | +| latest `main` | ✓ | +| older releases | 仅关键安全修复,视维护者资源而定 | + +## Reporting a Vulnerability + +**请勿**在公开 GitHub Issue 中讨论可利用的安全漏洞。 + +请通过以下方式私下报告: + +1. GitHub **Private Security Advisory**(推荐,在仓库 Security 标签页) +2. 或邮件联系 VibeCode / VistaRemote 维护者(待公布安全联系邮箱) + +请包含:影响版本、复现步骤、影响范围、可能的修复建议。 + +我们会在 **72 小时内** 确认收到,并在修复发布前避免公开细节。 + +## Scope + +- `server` 鉴权、信令、Admin API +- `desktop` Agent 授权与遥测 +- 录制存储与 AI 回调接口 +- 默认部署配置(Docker、TURN) + +Out of scope:仅影响 fork 自定义部署且未使用官方镜像的第三方配置。 diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..f7101a5 --- /dev/null +++ b/biome.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.4.15/schema.json", + "extends": ["./tooling/biome.json"], + "files": { + "includes": [ + "**", + "!web", + "!server", + "!mobile", + "!desktop", + "!shared", + "!docs", + "!deploy", + "!ai" + ] + } +} diff --git a/commitlint.config.cjs b/commitlint.config.cjs new file mode 100644 index 0000000..6532f99 --- /dev/null +++ b/commitlint.config.cjs @@ -0,0 +1 @@ +module.exports = require('./tooling/commitlint.config.cjs'); diff --git a/config/environments/README.md b/config/environments/README.md new file mode 100644 index 0000000..1b36eda --- /dev/null +++ b/config/environments/README.md @@ -0,0 +1,18 @@ +# VistaRemote 环境配置 + +| 文件 | 用途 | +| :--- | :--- | +| `local.env` | 本机 Docker + localhost API | +| `dev.env` | 远程开发环境 | +| `sit.env` | 集成测试 | +| `uat.env` | 用户验收 | + +切换后写入各子仓库 `.env`,**重启**对应 dev 进程生效。 + +```bash +# Meta-Repo 根目录 +pnpm env:local # 或 dev / sit / uat +pnpm dev:up # 一键本地基础设施 + 安装依赖 +``` + +当前激活环境记录在根目录 `.vista-env`。 diff --git a/config/environments/dev.env b/config/environments/dev.env new file mode 100644 index 0000000..c14aac4 --- /dev/null +++ b/config/environments/dev.env @@ -0,0 +1,19 @@ +# VistaRemote — 开发环境(远程 Dev API) +# 将下方域名改为你们实际的 Dev 网关地址 + +VISTA_ENV=dev +VISTA_ENV_LABEL=开发 Dev + +PUBLIC_API_BASE=https://api.dev.example.com +PUBLIC_WS_URL=wss://api.dev.example.com/signaling +PUBLIC_SIGNALING_URL=wss://api.dev.example.com/signaling +EXPO_PUBLIC_API_BASE=https://api.dev.example.com + +PORT=3000 +REDIS_URL=redis://redis.dev.internal:6379 + +AI_BASE_URL=https://ai.dev.internal/v1 +VECTOR_DB_URL=https://qdrant.dev.internal +PYTHON_ML_URL=https://ml.dev.internal +SERVER_INTERNAL_URL=https://api.dev.example.com +SERVER_INTERNAL_HMAC_SECRET=replace-me diff --git a/config/environments/local.env b/config/environments/local.env new file mode 100644 index 0000000..28a2b8f --- /dev/null +++ b/config/environments/local.env @@ -0,0 +1,26 @@ +# VistaRemote — 本地全栈(Docker + 本机进程) +# 切换:pnpm env:local 或 VISTA_ENV=local node tooling/scripts/apply-env.mjs + +VISTA_ENV=local +VISTA_ENV_LABEL=本地 Local + +PUBLIC_API_BASE=http://localhost:3000 +PUBLIC_WS_URL=ws://localhost:3000/signaling +PUBLIC_SIGNALING_URL=ws://localhost:3000/signaling +EXPO_PUBLIC_API_BASE=http://localhost:3000 + +PORT=3000 +REDIS_URL=redis://localhost:6379 +TURN_URL=turn:127.0.0.1:3478 +TURN_USERNAME=vistaremote +TURN_CREDENTIAL=vistaremote +MEDIASOUP_CONTROLLER_URL=http://localhost:4444 +MEDIASOUP_SIGNALING_URL=ws://localhost:4444/ws +TURN_LOAD_THRESHOLD=0.85 + +AI_BASE_URL=http://localhost:11434/v1 +AI_MODEL=llama3.2 +VECTOR_DB_URL=http://localhost:6333 +PYTHON_ML_URL=http://localhost:4100 +SERVER_INTERNAL_URL=http://localhost:3000 +SERVER_INTERNAL_HMAC_SECRET=dev-change-me diff --git a/config/environments/sit.env b/config/environments/sit.env new file mode 100644 index 0000000..eaee41c --- /dev/null +++ b/config/environments/sit.env @@ -0,0 +1,18 @@ +# VistaRemote — 系统集成测试 SIT + +VISTA_ENV=sit +VISTA_ENV_LABEL=集成 SIT + +PUBLIC_API_BASE=https://api.sit.example.com +PUBLIC_WS_URL=wss://api.sit.example.com/signaling +PUBLIC_SIGNALING_URL=wss://api.sit.example.com/signaling +EXPO_PUBLIC_API_BASE=https://api.sit.example.com + +PORT=3000 +REDIS_URL=redis://redis.sit.internal:6379 + +AI_BASE_URL=https://ai.sit.internal/v1 +VECTOR_DB_URL=https://qdrant.sit.internal +PYTHON_ML_URL=https://ml.sit.internal +SERVER_INTERNAL_URL=https://api.sit.example.com +SERVER_INTERNAL_HMAC_SECRET=replace-me diff --git a/config/environments/uat.env b/config/environments/uat.env new file mode 100644 index 0000000..aab57e3 --- /dev/null +++ b/config/environments/uat.env @@ -0,0 +1,18 @@ +# VistaRemote — 用户验收 UAT + +VISTA_ENV=uat +VISTA_ENV_LABEL=验收 UAT + +PUBLIC_API_BASE=https://api.uat.example.com +PUBLIC_WS_URL=wss://api.uat.example.com/signaling +PUBLIC_SIGNALING_URL=wss://api.uat.example.com/signaling +EXPO_PUBLIC_API_BASE=https://api.uat.example.com + +PORT=3000 +REDIS_URL=redis://redis.uat.internal:6379 + +AI_BASE_URL=https://ai.uat.internal/v1 +VECTOR_DB_URL=https://qdrant.uat.internal +PYTHON_ML_URL=https://ml.uat.internal +SERVER_INTERNAL_URL=https://api.uat.example.com +SERVER_INTERNAL_HMAC_SECRET=replace-me diff --git a/dev.ps1 b/dev.ps1 new file mode 100644 index 0000000..b47b7dd --- /dev/null +++ b/dev.ps1 @@ -0,0 +1,17 @@ +# VistaRemote one-shot local bootstrap (Windows) +# Usage: .\dev.ps1 +# .\dev.ps1 -SkipDocker +# .\dev.ps1 -Env dev + +param( + [switch]$SkipDocker, + [switch]$WithAi, + [string]$Env = "local" +) + +$args = @("tooling/scripts/dev-up.mjs", "--env=$Env") +if ($SkipDocker) { $args += "--skip-docker" } +if ($WithAi) { $args += "--with-ai" } + +node @args +if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } diff --git a/dev.sh b/dev.sh new file mode 100644 index 0000000..0c5257d --- /dev/null +++ b/dev.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# VistaRemote one-shot local bootstrap +# Usage: ./dev.sh +# ./dev.sh --skip-docker +# ./dev.sh --env dev --with-ai + +set -euo pipefail +cd "$(dirname "$0")" +node tooling/scripts/dev-up.mjs "$@" diff --git a/init.ps1 b/init.ps1 new file mode 100644 index 0000000..3b1dc98 --- /dev/null +++ b/init.ps1 @@ -0,0 +1,21 @@ +# Clone all VistaRemote sub-repositories (Windows) +$ErrorActionPreference = "Stop" +$repos = @( + "server", "desktop", "mobile", "web", "docs", "shared", "deploy", "ai" +) + +Write-Host "🚀 Cloning VistaRemote subprojects..." -ForegroundColor Cyan + +foreach ($name in $repos) { + if (Test-Path $name) { + Write-Host "✅ $name already exists" -ForegroundColor Green + } else { + git clone "git@github.com:VistaRemote/$name.git" + } +} + +Write-Host "" +Write-Host "🎉 Done. Next:" -ForegroundColor Green +Write-Host " nvm use # Node 22.12+" +Write-Host " .\dev.ps1 # one-shot local setup" +Write-Host " Open vista-remote.code-workspace in Cursor/VS Code" diff --git a/init.sh b/init.sh new file mode 100644 index 0000000..be92e10 --- /dev/null +++ b/init.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# init.sh - Clone all VistaRemote subprojects + +echo "🚀 Starting to clone VistaRemote subprojects..." + +# Clone server project +if [ ! -d "server" ]; then + git clone git@github.com:VistaRemote/server.git +else + echo "✅ server already exists, skipping clone" +fi + +# Clone desktop project +if [ ! -d "desktop" ]; then + git clone git@github.com:VistaRemote/desktop.git +else + echo "✅ desktop already exists, skipping clone" +fi + +# Clone mobile project +if [ ! -d "mobile" ]; then + git clone git@github.com:VistaRemote/mobile.git +else + echo "✅ mobile already exists, skipping clone" +fi + +# Clone web project +if [ ! -d "web" ]; then + git clone git@github.com:VistaRemote/web.git +else + echo "✅ web already exists, skipping clone" +fi + +# Clone docs project +if [ ! -d "docs" ]; then + git clone git@github.com:VistaRemote/docs.git +else + echo "✅ docs already exists, skipping clone" +fi + +# Clone shared project +if [ ! -d "shared" ]; then + git clone git@github.com:VistaRemote/shared.git +else + echo "✅ shared already exists, skipping clone" +fi + +# Clone deploy project +if [ ! -d "deploy" ]; then + git clone git@github.com:VistaRemote/deploy.git +else + echo "✅ deploy already exists, skipping clone" +fi + +# Clone ai worker project +if [ ! -d "ai" ]; then + git clone git@github.com:VistaRemote/ai.git +else + echo "✅ ai already exists, skipping clone" +fi + +echo "🎉 All projects initialized successfully!" +echo "" +echo "📌 Node.js >= 22.12 (see .nvmrc). Run: nvm use" +echo "📌 One-shot local dev: ./dev.sh (or .\\dev.ps1 on Windows)" +echo "📌 Switch API env: pnpm env:local | env:dev | env:sit | env:uat" +echo "📌 IDE sync: node tooling/scripts/setup-ide-config.mjs" +echo "📌 Single-repo only? cd desktop|mobile && node scripts/setup-dev.mjs" \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..fa66ac1 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "vistaremote-meta", + "private": true, + "description": "VistaRemote Meta-Repo tooling (Biome, shared configs)", + "scripts": { + "check": "biome check .", + "check:fix": "biome check --write .", + "format": "biome format --write .", + "format:docs": "biome format --write spec CONTRIBUTING.md AGENTS.md readme.md readme.zh-CN.md .github", + "prepare": "node -e \"try{require('husky')}catch(e){}\"", + "env:local": "node tooling/scripts/apply-env.mjs local", + "env:dev": "node tooling/scripts/apply-env.mjs dev", + "env:sit": "node tooling/scripts/apply-env.mjs sit", + "env:uat": "node tooling/scripts/apply-env.mjs uat", + "dev:up": "node tooling/scripts/dev-up.mjs", + "dev:up:ai": "node tooling/scripts/dev-up.mjs --with-ai", + "setup:repo": "node tooling/scripts/setup-single-repo.mjs" + }, + "devDependencies": { + "@biomejs/biome": "^2.0.6", + "@commitlint/cli": "^19.8.0", + "@commitlint/config-conventional": "^19.8.0", + "husky": "^9.1.7" + }, + "engines": { + "node": ">=22.0.0" + }, + "packageManager": "pnpm@9.15.0" +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..cd2a896 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,888 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@biomejs/biome': + specifier: ^2.0.6 + version: 2.4.15 + '@commitlint/cli': + specifier: ^19.8.0 + version: 19.8.1(@types/node@25.9.1)(typescript@6.0.3) + '@commitlint/config-conventional': + specifier: ^19.8.0 + version: 19.8.1 + husky: + specifier: ^9.1.7 + version: 9.1.7 + +packages: + + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@biomejs/biome@2.4.15': + resolution: {integrity: sha512-j5VH3a/h/HXTKBM50MDMxRCzkeLv9S2XJcW2WgnZT1+xyisi+0bISrXR82gCX+8S9lvK0skEvHJRN+3Ktr2hlw==} + engines: {node: '>=14.21.3'} + hasBin: true + + '@biomejs/cli-darwin-arm64@2.4.15': + resolution: {integrity: sha512-rF3PPqLq1yoST79zaQbDjVJwsuIeci/O+9bgNmC5QpgOqz6aqYuzA4abyAGx+mgyiDXn4A049xAN8gijbuR1Qg==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [darwin] + + '@biomejs/cli-darwin-x64@2.4.15': + resolution: {integrity: sha512-/5KHXYMfSJs1fNXiX30xFtI8JcCFV6zaVVLxOa0M2sfqBKHkpQhRTv94yxQWxeTY2lzo2OuTlNvPC+hDQt2wcQ==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [darwin] + + '@biomejs/cli-linux-arm64-musl@2.4.15': + resolution: {integrity: sha512-ZPcxznxm0pogHBLZhYntyR3sR+MrZjqJIKEr7ZqVen0Rl+P/4upVmfYXjftizi9RoqZntg33fv/1fbdhbYXpEQ==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + + '@biomejs/cli-linux-arm64@2.4.15': + resolution: {integrity: sha512-owaAMZD/T4LrD0ELNCk0Km3qrRHuM0X6EAyVE1FSqGY0rbLoiDLrO4Us2tllm6cAeB2Ioa9C2C08NZPdr8+0Ug==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + + '@biomejs/cli-linux-x64-musl@2.4.15': + resolution: {integrity: sha512-CNq/9W38SYSH023lfcQ4KKU8K0YX8T//FZUhcgtMMRABDojx5XsMV7jlweAvGSl389wJQB29Qo6Zb/a+jdvt+w==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + + '@biomejs/cli-linux-x64@2.4.15': + resolution: {integrity: sha512-0jj7THz12GbUOLmMibktK6DZjqz2zV64KFxyBtcFTKPiiOIY0a7vns1elpO1dERvxpsZ5ik0oFfz0oGwFde1+g==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + + '@biomejs/cli-win32-arm64@2.4.15': + resolution: {integrity: sha512-ouhkYdlhp/1GghEJPdWwD/Vi3gQ1nFxuSpMolWsbq3Lsq3QUR4jl6UdhhscdCugKU5vOEuMiJhvKj66O0OCq+w==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [win32] + + '@biomejs/cli-win32-x64@2.4.15': + resolution: {integrity: sha512-zBrGq5mx5wwpnow4+2BxUvleDM+GNd4sLbPaMapsSLQLD0NGRCquqPBTgN+7XkUteHvj7M+BstuI8tmnV7+HgQ==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [win32] + + '@commitlint/cli@19.8.1': + resolution: {integrity: sha512-LXUdNIkspyxrlV6VDHWBmCZRtkEVRpBKxi2Gtw3J54cGWhLCTouVD/Q6ZSaSvd2YaDObWK8mDjrz3TIKtaQMAA==} + engines: {node: '>=v18'} + hasBin: true + + '@commitlint/config-conventional@19.8.1': + resolution: {integrity: sha512-/AZHJL6F6B/G959CsMAzrPKKZjeEiAVifRyEwXxcT6qtqbPwGw+iQxmNS+Bu+i09OCtdNRW6pNpBvgPrtMr9EQ==} + engines: {node: '>=v18'} + + '@commitlint/config-validator@19.8.1': + resolution: {integrity: sha512-0jvJ4u+eqGPBIzzSdqKNX1rvdbSU1lPNYlfQQRIFnBgLy26BtC0cFnr7c/AyuzExMxWsMOte6MkTi9I3SQ3iGQ==} + engines: {node: '>=v18'} + + '@commitlint/ensure@19.8.1': + resolution: {integrity: sha512-mXDnlJdvDzSObafjYrOSvZBwkD01cqB4gbnnFuVyNpGUM5ijwU/r/6uqUmBXAAOKRfyEjpkGVZxaDsCVnHAgyw==} + engines: {node: '>=v18'} + + '@commitlint/execute-rule@19.8.1': + resolution: {integrity: sha512-YfJyIqIKWI64Mgvn/sE7FXvVMQER/Cd+s3hZke6cI1xgNT/f6ZAz5heND0QtffH+KbcqAwXDEE1/5niYayYaQA==} + engines: {node: '>=v18'} + + '@commitlint/format@19.8.1': + resolution: {integrity: sha512-kSJj34Rp10ItP+Eh9oCItiuN/HwGQMXBnIRk69jdOwEW9llW9FlyqcWYbHPSGofmjsqeoxa38UaEA5tsbm2JWw==} + engines: {node: '>=v18'} + + '@commitlint/is-ignored@19.8.1': + resolution: {integrity: sha512-AceOhEhekBUQ5dzrVhDDsbMaY5LqtN8s1mqSnT2Kz1ERvVZkNihrs3Sfk1Je/rxRNbXYFzKZSHaPsEJJDJV8dg==} + engines: {node: '>=v18'} + + '@commitlint/lint@19.8.1': + resolution: {integrity: sha512-52PFbsl+1EvMuokZXLRlOsdcLHf10isTPlWwoY1FQIidTsTvjKXVXYb7AvtpWkDzRO2ZsqIgPK7bI98x8LRUEw==} + engines: {node: '>=v18'} + + '@commitlint/load@19.8.1': + resolution: {integrity: sha512-9V99EKG3u7z+FEoe4ikgq7YGRCSukAcvmKQuTtUyiYPnOd9a2/H9Ak1J9nJA1HChRQp9OA/sIKPugGS+FK/k1A==} + engines: {node: '>=v18'} + + '@commitlint/message@19.8.1': + resolution: {integrity: sha512-+PMLQvjRXiU+Ae0Wc+p99EoGEutzSXFVwQfa3jRNUZLNW5odZAyseb92OSBTKCu+9gGZiJASt76Cj3dLTtcTdg==} + engines: {node: '>=v18'} + + '@commitlint/parse@19.8.1': + resolution: {integrity: sha512-mmAHYcMBmAgJDKWdkjIGq50X4yB0pSGpxyOODwYmoexxxiUCy5JJT99t1+PEMK7KtsCtzuWYIAXYAiKR+k+/Jw==} + engines: {node: '>=v18'} + + '@commitlint/read@19.8.1': + resolution: {integrity: sha512-03Jbjb1MqluaVXKHKRuGhcKWtSgh3Jizqy2lJCRbRrnWpcM06MYm8th59Xcns8EqBYvo0Xqb+2DoZFlga97uXQ==} + engines: {node: '>=v18'} + + '@commitlint/resolve-extends@19.8.1': + resolution: {integrity: sha512-GM0mAhFk49I+T/5UCYns5ayGStkTt4XFFrjjf0L4S26xoMTSkdCf9ZRO8en1kuopC4isDFuEm7ZOm/WRVeElVg==} + engines: {node: '>=v18'} + + '@commitlint/rules@19.8.1': + resolution: {integrity: sha512-Hnlhd9DyvGiGwjfjfToMi1dsnw1EXKGJNLTcsuGORHz6SS9swRgkBsou33MQ2n51/boIDrbsg4tIBbRpEWK2kw==} + engines: {node: '>=v18'} + + '@commitlint/to-lines@19.8.1': + resolution: {integrity: sha512-98Mm5inzbWTKuZQr2aW4SReY6WUukdWXuZhrqf1QdKPZBCCsXuG87c+iP0bwtD6DBnmVVQjgp4whoHRVixyPBg==} + engines: {node: '>=v18'} + + '@commitlint/top-level@19.8.1': + resolution: {integrity: sha512-Ph8IN1IOHPSDhURCSXBz44+CIu+60duFwRsg6HqaISFHQHbmBtxVw4ZrFNIYUzEP7WwrNPxa2/5qJ//NK1FGcw==} + engines: {node: '>=v18'} + + '@commitlint/types@19.8.1': + resolution: {integrity: sha512-/yCrWGCoA1SVKOks25EGadP9Pnj0oAIHGpl2wH2M2Y46dPM2ueb8wyCVOD7O3WCTkaJ0IkKvzhl1JY7+uCT2Dw==} + engines: {node: '>=v18'} + + '@types/conventional-commits-parser@5.0.2': + resolution: {integrity: sha512-BgT2szDXnVypgpNxOK8aL5SGjUdaQbC++WZNjF1Qge3Og2+zhHj+RWhmehLhYyvQwqAmvezruVfOf8+3m74W+g==} + + '@types/node@25.9.1': + resolution: {integrity: sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==} + + JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-ify@1.0.0: + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + compare-func@2.0.0: + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + + conventional-changelog-angular@7.0.0: + resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} + engines: {node: '>=16'} + + conventional-changelog-conventionalcommits@7.0.2: + resolution: {integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==} + engines: {node: '>=16'} + + conventional-commits-parser@5.0.0: + resolution: {integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==} + engines: {node: '>=16'} + hasBin: true + + cosmiconfig-typescript-loader@6.3.0: + resolution: {integrity: sha512-Akr82WH1Wfqatyiqpj8HDkO2o2KmJRu1FhKfSNJP3K4IdXwHfEyL7MOb62i1AGQVLtIQM+iCE9CGOtrfhR+mmA==} + engines: {node: '>=v18'} + peerDependencies: + '@types/node': '*' + cosmiconfig: '>=9' + typescript: '>=5' + + cosmiconfig@9.0.1: + resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + dargs@8.1.0: + resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} + engines: {node: '>=12'} + + dot-prop@5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} + + find-up@7.0.0: + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} + engines: {node: '>=18'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + git-raw-commits@4.0.0: + resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} + engines: {node: '>=16'} + deprecated: This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead. + hasBin: true + + global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} + + husky@9.1.7: + resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} + engines: {node: '>=18'} + hasBin: true + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-meta-resolve@4.2.0: + resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} + + ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + + is-text-path@2.0.0: + resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} + engines: {node: '>=8'} + + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.kebabcase@4.1.1: + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + + lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + + lodash.upperfirst@4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + + meow@12.1.1: + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} + engines: {node: '>=16.10'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + semver@7.8.1: + resolution: {integrity: sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==} + engines: {node: '>=10'} + hasBin: true + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + text-extensions@2.4.0: + resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} + engines: {node: '>=8'} + + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + + tinyexec@1.2.2: + resolution: {integrity: sha512-M/Q0B2cp4K7kynaT/vnED1j8TlLY+Pp7C6Wl2bl/7u/F0mUVwdyOpwomQb8JpYLitHUssAJRmLZdMCGsrx7i+g==} + engines: {node: '>=18'} + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.24.6: + resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + + unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@1.2.2: + resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} + engines: {node: '>=12.20'} + +snapshots: + + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/helper-validator-identifier@7.28.5': {} + + '@biomejs/biome@2.4.15': + optionalDependencies: + '@biomejs/cli-darwin-arm64': 2.4.15 + '@biomejs/cli-darwin-x64': 2.4.15 + '@biomejs/cli-linux-arm64': 2.4.15 + '@biomejs/cli-linux-arm64-musl': 2.4.15 + '@biomejs/cli-linux-x64': 2.4.15 + '@biomejs/cli-linux-x64-musl': 2.4.15 + '@biomejs/cli-win32-arm64': 2.4.15 + '@biomejs/cli-win32-x64': 2.4.15 + + '@biomejs/cli-darwin-arm64@2.4.15': + optional: true + + '@biomejs/cli-darwin-x64@2.4.15': + optional: true + + '@biomejs/cli-linux-arm64-musl@2.4.15': + optional: true + + '@biomejs/cli-linux-arm64@2.4.15': + optional: true + + '@biomejs/cli-linux-x64-musl@2.4.15': + optional: true + + '@biomejs/cli-linux-x64@2.4.15': + optional: true + + '@biomejs/cli-win32-arm64@2.4.15': + optional: true + + '@biomejs/cli-win32-x64@2.4.15': + optional: true + + '@commitlint/cli@19.8.1(@types/node@25.9.1)(typescript@6.0.3)': + dependencies: + '@commitlint/format': 19.8.1 + '@commitlint/lint': 19.8.1 + '@commitlint/load': 19.8.1(@types/node@25.9.1)(typescript@6.0.3) + '@commitlint/read': 19.8.1 + '@commitlint/types': 19.8.1 + tinyexec: 1.2.2 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/config-conventional@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + conventional-changelog-conventionalcommits: 7.0.2 + + '@commitlint/config-validator@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + ajv: 8.20.0 + + '@commitlint/ensure@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + lodash.camelcase: 4.3.0 + lodash.kebabcase: 4.1.1 + lodash.snakecase: 4.1.1 + lodash.startcase: 4.4.0 + lodash.upperfirst: 4.3.1 + + '@commitlint/execute-rule@19.8.1': {} + + '@commitlint/format@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + chalk: 5.6.2 + + '@commitlint/is-ignored@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + semver: 7.8.1 + + '@commitlint/lint@19.8.1': + dependencies: + '@commitlint/is-ignored': 19.8.1 + '@commitlint/parse': 19.8.1 + '@commitlint/rules': 19.8.1 + '@commitlint/types': 19.8.1 + + '@commitlint/load@19.8.1(@types/node@25.9.1)(typescript@6.0.3)': + dependencies: + '@commitlint/config-validator': 19.8.1 + '@commitlint/execute-rule': 19.8.1 + '@commitlint/resolve-extends': 19.8.1 + '@commitlint/types': 19.8.1 + chalk: 5.6.2 + cosmiconfig: 9.0.1(typescript@6.0.3) + cosmiconfig-typescript-loader: 6.3.0(@types/node@25.9.1)(cosmiconfig@9.0.1(typescript@6.0.3))(typescript@6.0.3) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/message@19.8.1': {} + + '@commitlint/parse@19.8.1': + dependencies: + '@commitlint/types': 19.8.1 + conventional-changelog-angular: 7.0.0 + conventional-commits-parser: 5.0.0 + + '@commitlint/read@19.8.1': + dependencies: + '@commitlint/top-level': 19.8.1 + '@commitlint/types': 19.8.1 + git-raw-commits: 4.0.0 + minimist: 1.2.8 + tinyexec: 1.2.2 + + '@commitlint/resolve-extends@19.8.1': + dependencies: + '@commitlint/config-validator': 19.8.1 + '@commitlint/types': 19.8.1 + global-directory: 4.0.1 + import-meta-resolve: 4.2.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + + '@commitlint/rules@19.8.1': + dependencies: + '@commitlint/ensure': 19.8.1 + '@commitlint/message': 19.8.1 + '@commitlint/to-lines': 19.8.1 + '@commitlint/types': 19.8.1 + + '@commitlint/to-lines@19.8.1': {} + + '@commitlint/top-level@19.8.1': + dependencies: + find-up: 7.0.0 + + '@commitlint/types@19.8.1': + dependencies: + '@types/conventional-commits-parser': 5.0.2 + chalk: 5.6.2 + + '@types/conventional-commits-parser@5.0.2': + dependencies: + '@types/node': 25.9.1 + + '@types/node@25.9.1': + dependencies: + undici-types: 7.24.6 + + JSONStream@1.3.5: + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.2 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + argparse@2.0.1: {} + + array-ify@1.0.0: {} + + callsites@3.1.0: {} + + chalk@5.6.2: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + compare-func@2.0.0: + dependencies: + array-ify: 1.0.0 + dot-prop: 5.3.0 + + conventional-changelog-angular@7.0.0: + dependencies: + compare-func: 2.0.0 + + conventional-changelog-conventionalcommits@7.0.2: + dependencies: + compare-func: 2.0.0 + + conventional-commits-parser@5.0.0: + dependencies: + JSONStream: 1.3.5 + is-text-path: 2.0.0 + meow: 12.1.1 + split2: 4.2.0 + + cosmiconfig-typescript-loader@6.3.0(@types/node@25.9.1)(cosmiconfig@9.0.1(typescript@6.0.3))(typescript@6.0.3): + dependencies: + '@types/node': 25.9.1 + cosmiconfig: 9.0.1(typescript@6.0.3) + jiti: 2.6.1 + typescript: 6.0.3 + + cosmiconfig@9.0.1(typescript@6.0.3): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + parse-json: 5.2.0 + optionalDependencies: + typescript: 6.0.3 + + dargs@8.1.0: {} + + dot-prop@5.3.0: + dependencies: + is-obj: 2.0.0 + + emoji-regex@8.0.0: {} + + env-paths@2.2.1: {} + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + escalade@3.2.0: {} + + fast-deep-equal@3.1.3: {} + + fast-uri@3.1.2: {} + + find-up@7.0.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + + get-caller-file@2.0.5: {} + + git-raw-commits@4.0.0: + dependencies: + dargs: 8.1.0 + meow: 12.1.1 + split2: 4.2.0 + + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + + husky@9.1.7: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-meta-resolve@4.2.0: {} + + ini@4.1.1: {} + + is-arrayish@0.2.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-obj@2.0.0: {} + + is-text-path@2.0.0: + dependencies: + text-extensions: 2.4.0 + + jiti@2.6.1: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@1.0.0: {} + + jsonparse@1.3.1: {} + + lines-and-columns@1.2.4: {} + + locate-path@7.2.0: + dependencies: + p-locate: 6.0.0 + + lodash.camelcase@4.3.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.kebabcase@4.1.1: {} + + lodash.merge@4.6.2: {} + + lodash.mergewith@4.6.2: {} + + lodash.snakecase@4.1.1: {} + + lodash.startcase@4.4.0: {} + + lodash.uniq@4.5.0: {} + + lodash.upperfirst@4.3.1: {} + + meow@12.1.1: {} + + minimist@1.2.8: {} + + p-limit@4.0.0: + dependencies: + yocto-queue: 1.2.2 + + p-locate@6.0.0: + dependencies: + p-limit: 4.0.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.29.0 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + path-exists@5.0.0: {} + + picocolors@1.1.1: {} + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + semver@7.8.1: {} + + split2@4.2.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + text-extensions@2.4.0: {} + + through@2.3.8: {} + + tinyexec@1.2.2: {} + + typescript@6.0.3: {} + + undici-types@7.24.6: {} + + unicorn-magic@0.1.0: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + y18n@5.0.8: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@1.2.2: {} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..205f4aa --- /dev/null +++ b/readme.md @@ -0,0 +1,85 @@ +# VibeCode | VistaRemote 🚀 + +[English](./README.md) | [简体中文](./README.zh-CN.md) + +> A cross-platform, real-time remote desktop control system. + +Built with passion in China, designed for the global open-source community. + +VistaRemote is a VibeCode core project: **WebRTC** real-time remote desktop (vs. legacy DVR-style monitoring), **self-hostable AI** for recording and insights, and a **TypeScript + MySQL** stack for easier hiring, customization, and Docker deployment. + +**Why VistaRemote:** TypeScript-first, Spec-driven, **easy to customize** — best for teams that do **not** need billion-scale concurrency. [Positioning](https://github.com/VistaRemote/vista-remote/blob/main/docs/docs/en/architecture/positioning.mdx) · [Desktop performance](https://github.com/VistaRemote/vista-remote/blob/main/docs/docs/en/architecture/desktop-performance.mdx) + +To ensure build stability across diverse environments (Node.js, React Native, Electron), this project adopts a **Multi-repo** architecture. This repository serves as the **Meta-Repo**, designed to help developers quickly initialize their environments, orchestrate the subprojects, and manage cross-repository local debugging. + +--- + +## 🏗 Architecture & Subprojects + +The VistaRemote ecosystem consists of 6 independent repositories: + +| Module | Repository | Tech Stack | Description | +| :--- | :--- | :--- | :--- | +| **Server** | `server` | NestJS, TypeORM, **MySQL** | Signaling, admin APIs, plans, recording metadata, audit. | +| **AI** | `ai` | NestJS, BullMQ, LLM | Summaries, anomaly detection, efficiency reports. | +| **Desktop Agent** | `desktop` | Electron, Rsbuild, Ant Design | Controlled agent; renderer uses antd + Sass. | +| **Mobile Client** | `mobile` | React Native, antd-mobile | Mobile controller (Metro bundler). | +| **Web** | `web` | Rsbuild, Ant Design, Sass | **Client** (`apps/client`) + **Admin** (`apps/admin`). | +| **Shared Protocol** | `shared` | TypeScript | Core type definitions (Interfaces), WebRTC SDP structures, and remote command payload specs. | +| **Documentation** | `docs` | Rspress, MDX | System architecture design, API references, and deployment guides, built with Rspress for a unified and blazing-fast Rspack ecosystem. | + +--- + +## 🚀 Getting Started + +### 1. Prerequisites + +Ensure your local development environment has the following installed: +- **Git** +- **Node.js** (>= 18.x) +- **pnpm** or **Bun** (Recommended package managers) + +### 2. One-Click Initialization + +Clone this meta-repo and run the initialization script to automatically pull all subprojects: + +```bash +# Grant execution permission +chmod +x init.sh + +# Run the clone script +./init.sh +``` + +## 🔀 Git Workflow (Important!) + +VistaRemote uses a flat Meta-Repo structure. **DO NOT use `git submodule` or `git subtree`.** +Each subproject (`server`, `desktop`, `shared`, etc.) has its own independent `.git` directory. + +- **Commit Principle**: You must commit and push changes within the specific sub-directory. +- **IDE Setup**: We strongly recommend using **Cursor / VS Code Multi-Root Workspaces** (via `.code-workspace`) or **IntelliJ Directory Mappings** to manage all Git repositories simultaneously in a unified UI. +- For Git, IDE, and CI/CD releases, see the docs site (`cd docs && pnpm dev`) → **Engineering → CI/CD & Releases**, plus [Git Collaboration Spec](./spec/git-collaboration-spec.md) and [CI/CD Release Spec](./spec/cicd-release-spec.md). + +--- + +## 📋 Specifications & Whitepaper + +This project follows **Spec-Driven Development (SDD)**: + +| Document | Description | +| :--- | :--- | +| **[DEVELOPMENT.md](./DEVELOPMENT.md)** | **Developer entry** — commands, Spec order | +| [Spec Index](./spec/README.md) | SDD workflow and per-module specs | +| [SDD Spec](./spec/spec-driven-development-spec.md) | How to add FR-xxx and PR obligations | +| [Implementation status](./spec/implementation-status.md) | What is ready vs stub (read before coding) | +| [System Overview Spec](./spec/system-overview.md) | WebRTC P2P/SFU, signaling, security, milestones | +| [Documentation site](./docs/) | Rspress — run `cd docs && pnpm dev` → Developer handbook & User guide | +| [Whitepaper](docs/README.md) | `/whitepaper/` on the doc site | +| [Architecture](docs/README.md) | `/architecture/overview` on the doc site | + +## License + +- **Personal, non-commercial use**: free under [LICENSE](./LICENSE). +- **Commercial use**: requires a [commercial license](./COMMERCIAL-LICENSE.md) (all commercial use is paid). +- **Trial**: 14-day trial includes **WebRTC SFU** and **AI cloud fallback**; after trial, Pro/Enterprise required — see `spec/commercial-tier-spec.md`. +- **Model fine-tuning**: closed-source, separate private repo — see `spec/ai-finetune-spec.md`. diff --git a/readme.zh-CN.md b/readme.zh-CN.md new file mode 100644 index 0000000..d83dea7 --- /dev/null +++ b/readme.zh-CN.md @@ -0,0 +1,95 @@ +# VibeCode | VistaRemote 🚀 + +[English](./README.md) | [简体中文](./README.zh-CN.md) + +> 跨平台的实时远程桌面控制系统 + +立足中国,面向全球开源社区的国际化项目。VistaRemote 是 VibeCode 的核心项目之一:以 **WebRTC** 实现低延迟远程控制(相对传统录屏监控的「事后回看」),以 **可私有化部署的 AI** 提供录制、审计与行为洞察;**全栈 TypeScript + MySQL**,方便国内团队招聘、二开与 Docker 部署。 + +**核心优势**:[WebRTC · 开源可自建 · AI 数据可控 · TS 全栈 · 二开快 · 非千万并发场景优选](./docs/docs/zh/architecture/positioning.mdx) + +- **二开/交付**:全栈 TypeScript + Spec 驱动,Meta-Repo 避免 Monorepo 构建黑洞,Rsbuild 冷启动数百毫秒级。 +- **性能**:Web WebCodecs · Mobile JSI · Desktop GPU 编码与零帧 IPC(详见文档站「Desktop 性能架构」)。 + +为确保跨端环境(Node.js, React Native, Electron)的构建稳定性与灵活性,本项目采用 **Multi-repo** 架构进行解耦管理。本仓库为 VistaRemote 的 **Meta-Repo(元仓库)**,用于快速初始化开发环境、统筹全局文档以及进行跨端联调。 + +**新成员**:`./init.sh` → `./dev.sh`(Windows:`.\init.ps1`、`.\dev.ps1`)。开发入口见 **[DEVELOPMENT.md](./DEVELOPMENT.md)**。切换 Dev/SIT/UAT API:`pnpm env:dev` 后重启各端。仅拉 `desktop`/`mobile` 仓库时在仓内执行 `pnpm setup`。详见 [开发者手册](./docs/docs/zh/guide/developer-handbook.mdx) 与 [本地开发指南](./docs/docs/zh/guide/local-development.mdx)。 + +--- + +## 🏗 架构全览 + +VistaRemote 生态系统由以下 **8** 个独立的代码仓库组成(运行 `./init.sh` 拉取): + +| 模块 | 仓库名 | 技术栈 | 职责描述 | +| :--- | :--- | :--- | :--- | +| **服务端** | `server` | NestJS, TypeORM, **MySQL** | 信令、**全用户管理台 API**、套餐、录制元数据、审计。 | +| **AI 分析** | `ai` | NestJS, BullMQ, LLM | 摘要、异常检测、效率报告(与 server 解耦)。 | +| **桌面端** | `desktop` | Electron, Rsbuild, Ant Design | 被控 Agent;渲染进程与 Web 同构(antd + Sass)。 | +| **移动端** | `mobile` | React Native, antd-mobile | 移动端主控,Metro 打包。 | +| **网页端** | `web` | Rsbuild, Ant Design, Sass | **用户端** `apps/client` + **管理端** `apps/admin` 双应用。 | +| **协议层** | `shared` | TypeScript | 核心的类型定义 (Types/Interfaces)、WebRTC SDP 结构定义、远程控制指令规范。 | +| **文档库** | `docs` | Rspress, MDX | 架构、API、部署与产品定位文档。 | +| **部署** | `deploy` | Docker Compose | **MySQL**、Redis、MinIO、server、ai、双 Web 一键模板。 | + +--- + +## 🚀 快速开始 + +### 1. 环境准备 + +确保你的本地开发环境已安装以下工具: +- **Git** +- **Node.js** (>= 18.x) +- **pnpm** 或 **Bun** (推荐的包管理器) + +### 2. 一键初始化 + +克隆本仓库后,在根目录下运行初始化脚本,自动拉取所有子项目代码: + +```bash +# 赋予脚本执行权限 +chmod +x init.sh + +# 执行克隆脚本 +./init.sh +``` + +## 🔀 Git 协作规范 (必读) + +VistaRemote 采用平铺式的 Meta-Repo 架构,**我们绝不使用 `git submodule` 或 `git subtree`**。 +所有的子项目(`server`, `desktop`, `shared` 等)都拥有自己独立的 `.git` 目录。 + +- **提交原则**:你必须在具体的子目录中进行 `git commit` 和 `git push`。 +- **IDE 推荐**:强烈建议使用 **Cursor / VS Code 的多根工作区 (Multi-Root Workspace)** 或 **IntelliJ 的目录映射 (Directory Mappings)** 功能,在统一的界面中同时管理 6 个仓库的变更。 +- IDE、Biome、Git/PR、CI/CD: [CONTRIBUTING.md](./CONTRIBUTING.md) · 文档站 `/engineering/cicd-release` · [Spec: CI/CD 与发布](./spec/cicd-release-spec.md) · [Spec: 工程规范](./spec/engineering-standards-spec.md) · [Spec: Git 协作](./spec/git-collaboration-spec.md) + +--- + +## 📋 Spec 与白皮书 + +本项目采用 **Spec-Driven Development**,实现前请先阅读规格说明: + +| 文档 | 说明 | +| :--- | :--- | +| **[DEVELOPMENT.md](./DEVELOPMENT.md)** | **开发入口**(命令、Spec 阅读顺序) | +| [Spec 索引](./spec/README.md) | SDD 流程与各模块 Spec 目录 | +| [SDD 规范](./spec/spec-driven-development-spec.md) | FR/US、实现顺序、PR 义务 | +| [实现状态](./spec/implementation-status.md) | 可开发范围 vs 桩/待办 | +| [系统总览 Spec](./spec/system-overview.md) | WebRTC P2P/SFU、信令、安全与里程碑 | +| [前端工具链 Spec](./spec/frontend-toolchain-spec.md) | Rsbuild、Ant Design、Sass | +| [Web 用户端 / 管理端](./spec/web-client-spec.md) | 双应用职责与验收 | +| [套餐与试用](./spec/commercial-tier-spec.md) | SFU/降云试用后付费;Pro/Enterprise | +| [开源与商业授权](./spec/licensing-spec.md) | 个人非盈利免费;商业一律收费 | +| [大模型微调(闭源)](./spec/ai-finetune-spec.md) | 独立私有仓建议 | +| [AI 平台架构](./spec/ai-platform-spec.md) | 是否独立 `ai` 仓库、技术选型 | +| [文档站(Rspress)](./docs/README.md) | `cd docs && pnpm dev` — 开发者手册 `/guide/developer-handbook`、用户指南 `/user/remote-control` | +| [白皮书源文件](./docs/docs/zh/whitepaper/index.mdx) | Rspress 内容目录 | +| [产品定位源文件](./docs/docs/zh/architecture/positioning.mdx) | Rspress 内容目录 | + +## 开源协议 + +- **个人、非盈利使用**:免费,见根目录 [LICENSE](./LICENSE)。 +- **商业使用**:须签署 [商业许可](./COMMERCIAL-LICENSE.md)(任何商业使用均收费)。 +- **试用**:默认 14 天可体验 **SFU** 与 **AI 降云**;结束后须 Pro/Enterprise,见 `spec/commercial-tier-spec.md`。 +- **大模型微调**:闭源独立项目,见 `spec/ai-finetune-spec.md`。 diff --git a/spec/README.md b/spec/README.md new file mode 100644 index 0000000..77b6e06 --- /dev/null +++ b/spec/README.md @@ -0,0 +1,89 @@ +# VistaRemote Spec 规范索引 + +| Metadata | Value | +| :--- | :--- | +| **版本** | 0.4.0-draft | +| **最后更新** | 2026-05-24 | + +--- + +## Spec 驱动开发(必读) + +| 文档 | 说明 | +| :--- | :--- | +| [spec-driven-development-spec.md](./spec-driven-development-spec.md) | SDD 工作流、FR/US ID、PR 义务 | +| [implementation-status.md](./implementation-status.md) | **实现 vs Spec** 矩阵(开发前查) | +| [architecture-foundation-spec.md](./architecture-foundation-spec.md) | 基础架构 F-01~F-13 就绪清单 | +| [DEVELOPMENT.md](../DEVELOPMENT.md) | 人类开发者入口 | + +--- + +## 模块 Spec 清单 + +| 模块 | Meta-Repo Spec | 子仓库 `spec/` | +| :--- | :--- | :--- | +| **L0 系统** | [system-overview.md](./system-overview.md) | — | +| WebRTC 媒体 | [webrtc-architecture-spec.md](./webrtc-architecture-spec.md) | P2P/TURN、mediasoup、播放优化 | +| 消息传输 | [messaging-transport-spec.md](./messaging-transport-spec.md) | WS 信令、SSE 通知、DataChannel | +| 认证与授权 | [authorization-spec.md](./authorization-spec.md) | RBAC + ABAC + Plan;JWT/信令票 | +| 前端工具链 | [frontend-toolchain-spec.md](./frontend-toolchain-spec.md) | — | +| 套餐商业化 | [commercial-tier-spec.md](./commercial-tier-spec.md) | 试用;SFU/降云试用后付费 | +| 订单与支付 | [billing-commerce-spec.md](./billing-commerce-spec.md) | 买断/订阅;微信/支付宝等;Admin 三模块 | +| 开源与商业授权 | [licensing-spec.md](./licensing-spec.md) | 个人非盈利免费;商业一律收费 | +| 大模型微调(闭源) | [ai-finetune-spec.md](./ai-finetune-spec.md) | 独立私有仓,与公开 `ai` 分离 | +| AI 平台(架构) | [ai-platform-spec.md](./ai-platform-spec.md) | 私有化 LLM+向量库;Node 主栈 + Python ML | +| AI 行为洞察架构 | [ai-behavior-architecture-spec.md](./ai-behavior-architecture-spec.md) | — | +| AI 仓库 | [ai-spec.md](./ai-spec.md) | `ai/spec/SPEC.md` | +| 录制回放 | [recording-playback-spec.md](./recording-playback-spec.md) | 端侧默认;SFU 录制 Enterprise | +| 商业化资源点 | [commercial-resources-spec.md](./commercial-resources-spec.md) | 重资源 Feature 切割 | +| 企业安全 | [enterprise-security-spec.md](./enterprise-security-spec.md) | — | +| shared | [shared-spec.md](./shared-spec.md) | `shared/spec/` | +| server | [server-spec.md](./server-spec.md) | `server/spec/` | +| web | [web-spec.md](./web-spec.md) | `web/spec/` | +| web 用户端 | [web-client-spec.md](./web-client-spec.md) | `web/spec/client-spec.md` | +| web 管理台 | [web-admin-spec.md](./web-admin-spec.md) | `web/spec/admin-spec.md` | +| desktop | [desktop-spec.md](./desktop-spec.md) | `desktop/spec/` | +| mobile | [mobile-spec.md](./mobile-spec.md) | `mobile/spec/` | +| docs | [docs-spec.md](./docs-spec.md) | `docs/spec/` | +| deploy | [deploy-spec.md](./deploy-spec.md) | `deploy/spec/` | +| Git / 协作 | [git-collaboration-spec.md](./git-collaboration-spec.md) | — | +| CI/CD 与发布 | [cicd-release-spec.md](./cicd-release-spec.md) | shared 发布、下游同步、分仓 tag | +| 工程规范 | [engineering-standards-spec.md](./engineering-standards-spec.md) | — | +| Meta 开发/发布 | [meta-repo-development-spec.md](./meta-repo-development-spec.md) | Biome 分层、单独发版 | +| 开发者体验 | [developer-experience-spec.md](./developer-experience-spec.md) | dev-up、env 切换、单仓 setup | +| Agent 分发/接入 | [agent-distribution-spec.md](./agent-distribution-spec.md) | 数字码/QR/链接;三包体;企业自动监控 | +| **性能路线图(内部)** | [performance-roadmap-spec.md](./performance-roadmap-spec.md) | 先上线 → 按 ROI Rust;不对 docs 用户承诺 | +| Desktop 性能 | [desktop-performance-spec.md](./desktop-performance-spec.md) | 阶段 A/B;R1–R6 ROI | +| 产品定位/选型 | [product-positioning-spec.md](./product-positioning-spec.md) | 二开、成本、非千万并发场景 | + +--- + +## 技术栈速查(0.3) + +| 层级 | 选型 | +| :--- | :--- | +| 数据库 | **MySQL 8 only**(不用 PostgreSQL,见 [positioning doc](../docs/positioning-and-advantages.md)) | +| 后端 | NestJS + Redis + BullMQ | +| AI | **多模型**:端侧(desktop)+ 云端 Worker(`ai`)+ Ollama 本地调试 | +| 录制存储 | MinIO / S3 | +| 套餐 | free / pro / enterprise | +| 前端 | Rsbuild + antd + Sass;Web Client + **Admin 管理台** | + +--- + +## 实现顺序建议 + +1. `shared`:plan、telemetry、behavior、inference、ai DTO +2. `server`:MySQL 实体、Admin 全用户、PlanGuard +3. `web/admin`:用户与套餐管理 +4. `ai`:队列 + 摘要 Job +5. Pro:录制上传与回放 +6. Enterprise:策略、遥测、安全与效率报告 + +--- + +## 相关文档 + +- [白皮书](../docs/whitepaper.md) +- [架构背景](../docs/architecture-and-background.md) +- 文档站(用户/开发者):`docs/` → [开发者手册](https://github.com/VistaRemote/vista-remote/tree/main/docs/docs/zh/guide/developer-handbook.mdx) diff --git a/spec/agent-distribution-spec.md b/spec/agent-distribution-spec.md new file mode 100644 index 0000000..3d8c0d6 --- /dev/null +++ b/spec/agent-distribution-spec.md @@ -0,0 +1,130 @@ +# Agent 分发与接入 Spec + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-AGENT-DIST-001` | +| **版本** | 1.0.0 | +| **关联** | [desktop-spec.md](./desktop-spec.md) · [server-spec.md](./server-spec.md) · [enterprise-security-spec.md](./enterprise-security-spec.md) · [authorization-spec.md](./authorization-spec.md) | + +--- + +## 1. 目标 + +定义 **被控端(Desktop Agent)** 如何安装、如何被主控 **直连监控**,以及 **企业场景** 下「员工自带 / 主动安装」与「公司电脑 / 强制预装」的差异与 **分包发布** 策略。 + +--- + +## 2. 主控接入方式(Normative) + +主控端(Web / Mobile / Desktop Controller)可通过以下 **等价入口** 绑定同一会话 Room: + +| 方式 | ID | 说明 | 优先级 | +| :--- | :--- | :--- | :--- | +| **数字配对码** | `code` | 6–8 位,TTL 可配置(默认 300s) | P0 | +| **二维码** | `qr` | 编码 `PairingQrPayload`(含 `linkUrl` 或 `linkToken`) | P0 | +| **会话链接** | `link` | HTTPS `/join/{token}` 或 `vistaremote://join?token=` | P0 | + +```text +被控 Agent 创建 PairingSession + │ + ├─ numericCode ──► 主控手动输入 + ├─ qrPayload ──► 主控扫码(解析为 linkToken 或完整 URL) + └─ linkToken ──► 主控打开链接(Web 路由 / 深链) + │ + ▼ +POST /api/v1/auth/pairing { method, code? | linkToken? } + │ + ▼ +返回 roomId + signalingTicket → WSS join +``` + +| ID | 需求 | 验收 | +| :--- | :--- | :--- | +| FR-DIST-01 | 三种 `PairingEntryMethod` 解析到同一 `roomId` | 单测 + 手测任一路径可连 | +| FR-DIST-02 | 二维码内容为 **签名或短期 token**,禁止长期明文 device 密钥 | 安全评审 | +| FR-DIST-03 | 链接 token 与数字码 **可同源**(同一次 PairingSession) | Agent UI 三态同步刷新 | +| FR-DIST-04 | 消费后码/链 **一次性**(可配置企业策略允许多主控则走 SFU) | `PAIRING_CONSUMED` | +| FR-DIST-05 | 审计记录 `entryMethod` | Admin 审计可查 | + +契约:`shared/src/pairing/*`、`shared/src/api/pairing.ts`。 + +--- + +## 3. 安装包变体(Normative) + +**同一 codebase**,通过 **构建常量 + 安装器元数据 + 首次启动逻辑** 区分,发布 **独立安装包**(不得仅靠运行时隐藏开关绕过合规)。 + +| 变体 ID | 目标用户 | 安装场景 | 默认 `AgentInstallChannel` | 默认 `AgentDeploymentMode` | +| :--- | :--- | :--- | :--- | :--- | +| **PKG-CONSUMER** | 个人 / 小规模 | 用户自行下载安装 | `consumer` | `interactive` | +| **PKG-ENT-BYOD** | 企业员工自带设备 | 员工扫码/链接 **主动安装** 并登录企业 | `enterprise_byod` | `enrolled_auto` | +| **PKG-ENT-MANAGED** | 公司配发电脑 | IT **GPO/MDM/镜像预装**,开机即受管 | `enterprise_managed` | `managed_silent` | + +### 3.1 行为矩阵 + +| 能力 | Consumer | Enterprise BYOD | Enterprise Managed | +| :--- | :--- | :--- | :--- | +| 配对码/二维码/链接 | ✅ 用户发起共享时展示 | ✅ | ⚠️ 仅 IT 远程协助时展示(可策略关闭 UI) | +| 安装后自动注册组织 | ❌ | ✅ enrollment token | ✅ 预置 org + device claim | +| 安装后自动监控(策略允许时) | ❌ | ✅ 需 **员工同意** 记录 | ✅ 受企业策略约束 | +| 每次会话授权弹窗 | ✅ 默认开 | 可配置 | 可配置(默认可关) | +| 卸载 | 用户任意 | 用户可卸(企业可告警) | 需管理员密码/MDM | + +| ID | 需求 | 验收 | +| :--- | :--- | :--- | +| FR-DIST-10 | CI 产出 **3 类** 安装包 artifact(见 §5) | Release 页可见 | +| FR-DIST-11 | 包内 `install-channel.json` 或编译时常量只读 | 运行时不可伪造为 managed | +| FR-DIST-12 | Managed 包 **必须** 带企业法律告知页(首次启动) | 截图 + 文案 Spec | +| FR-DIST-13 | BYOD 包 enrollment 须员工账号/OAuth + 勾选同意 | 审计 `consentAt` | + +--- + +## 4. 企业自动监控 + +| ID | 需求 | 说明 | +| :--- | :--- | :--- | +| FR-DIST-20 | `AgentProvisioningProfile.autoMonitor` 由 Admin 下发 | `off` \| `on_idle` \| `on_login` | +| FR-DIST-21 | BYOD:`enrolled_auto` 仅在 `consentRecord` 存在后生效 | 合规 | +| FR-DIST-22 | Managed:`managed_silent` 服从 `EnterprisePolicy.monitoring` | 与 [enterprise-security-spec](./enterprise-security-spec.md) 一致 | +| FR-DIST-23 | 自动监控 **不** 绕过套餐与 ABAC | `it_support` 仅能看授权设备 | + +**禁止**:未披露的无 UI 投屏;Out of Scope 见 desktop-spec,Managed 包仍须 **告知 + 企业合同**。 + +--- + +## 5. 安装包命名与构建 + +| 平台 | Consumer | Enterprise BYOD | Enterprise Managed | +| :--- | :--- | :--- | :--- | +| Windows x64 | `VistaRemote-Agent-Consumer-{ver}-win-x64.exe` | `VistaRemote-Agent-EntBYOD-{ver}-win-x64.exe` | `VistaRemote-Agent-EntManaged-{ver}-win-x64.exe` | +| macOS | `...-mac-universal.dmg` | 同左 | 同左 | +| Linux | `...-linux-x64.AppImage` | P2 | P2 | + +Meta-Repo 脚本:`tooling/scripts/build-agent-packages.mjs`(调用各 channel 的 `pnpm build:agent:*`)。 + +环境变量(构建时注入 desktop): + +| 变量 | 值示例 | +| :--- | :--- | +| `VISTAREMOTE_INSTALL_CHANNEL` | `consumer` \| `enterprise_byod` \| `enterprise_managed` | +| `VISTAREMOTE_DEPLOYMENT_MODE` | `interactive` \| `enrolled_auto` \| `managed_silent` | + +--- + +## 6. API 扩展(Server) + +| Method | Path | 说明 | +| :--- | :--- | :--- | +| `POST` | `/api/v1/devices/register` | 含 `installChannel`、`deploymentMode` | +| `POST` | `/api/v1/devices/pairing-session` | Agent 创建配对会话(码+链+QR) | +| `GET` | `/api/v1/pairing/:code` | 主控校验码(公开元数据) | +| `GET` | `/api/v1/pairing/link/:token` | 解析链接 token | +| `POST` | `/api/v1/auth/pairing` | 主控加入,`method` + `code` \| `linkToken` | + +--- + +## 7. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 1.0.0 | 三态接入、三包体、企业自动监控 | diff --git a/spec/ai-behavior-architecture-spec.md b/spec/ai-behavior-architecture-spec.md new file mode 100644 index 0000000..1b5c3eb --- /dev/null +++ b/spec/ai-behavior-architecture-spec.md @@ -0,0 +1,147 @@ +# AI 行为洞察架构 Spec(L1) + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-AI-ARCH-001` | +| **版本** | 0.5.1 | +| **商业化** | [commercial-tier-spec.md](./commercial-tier-spec.md) — 降云试用后须 Enterprise | +| **状态** | Draft | +| **关联** | [ai-platform-spec.md](./ai-platform-spec.md) · [enterprise-security-spec.md](./enterprise-security-spec.md) · [desktop-spec.md](./desktop-spec.md) | + +--- + +## 1. 产品目标 + +面向 **企业服务场景(远程桌面 + AI 行为分析)**,在合规前提下实现: + +| 能力层 | 用户价值 | +| :--- | :--- | +| **监控告警** | 非工作行为、敏感外发、批量删除、异常活跃等实时/准实时告警 | +| **行为报告** | 日/周效率报告、部门对比(Enterprise Admin) | +| **长期洞察** | 行为数据入库,支撑 **流程优化**、**AI 替代建议**、岗位效率分析 | + +**原则:多模型协作;数据默认留在客户基础设施内;禁止单一大模型包打天下。** + +--- + +## 2. 多模型分工(强制) + +```text +┌─────────────────────────────────────────────────────────────────────────┐ +│ Desktop Agent(端侧优先) │ +│ 规则引擎 · PaddleOCR-slim · Qwen2.5-VL(量化) · 时序特征 · 隐私本地策略 │ +└────────────────────────────────────┬────────────────────────────────────┘ + │ 结构化事件(非原始录屏) + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ Server(汇聚 · 策略 · 入库 · 队列) │ +└────────────────────────────────────┬────────────────────────────────────┘ + ▼ +┌─────────────────────────────────────────────────────────────────────────┐ +│ ai — Node/TS 主 Worker │ +│ · LangChain / LangGraph:摘要、报告、流程优化编排 │ +│ · Ollama / vLLM + Qdrant(私有化,不出网) │ +│ · HTTP → python-worker:基线训练、Isolation Forest 等重 ML │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +| 场景 | 模型类型 | 默认执行位置 | 上云条件 | +| :--- | :--- | :--- | :--- | +| 窗口/App 分类、关键词命中 | 小模型 + 规则 | **端侧** | CPU 压力 / 超时 → `behavior.cloud_infer` | +| 非工作站点时长 | 时序统计 | **端侧** | 复杂基线 → **Python worker** | +| 敏感 UI(可选) | CV(ONNX) | **端侧** | 仅上传标签+置信度 | +| 隐私敏感 | 规则 + 本地 CV | **端侧 only** | 禁止默认上云 | +| 会话/录制摘要 | LLM + RAG | **ai (Node)** | 自托管 LLM + 向量库 | +| 效率报告、流程优化、AI 替代建议 | **LangGraph + LLM** | **ai (Node)** | 人在 Admin 审批后展示 | +| 14 天基线、3σ 异常 | ML | **python-worker** | ai 调度 | + +--- + +## 3. 推理调度(Edge ↔ Cloud) + +### 3.1 设备能力画像 + +Agent 每 5min 上报 `device.capability`(`shared`): + +| 字段 | 用途 | +| :--- | :--- | +| `cpuCores`, `ramMb` | 能力分档 | +| `hasGpu`, `onnxProviders` | 是否启用端侧 CV | +| `cpuPressure` | `normal` / `high` → 触发降云 | + +### 3.2 组织策略 `inferenceMode` + +| 值 | 行为 | +| :--- | :--- | +| `edge_preferred` | 默认;超时或高压时升云 | +| `edge_only` | 禁止上云(仅规则/统计) | +| `cloud_preferred` | 复杂任务直接入队 `behavior.cloud_infer` | + +### 3.3 降云路径 + +端侧 SLA 内未完成 → Server 写入 `behavior.cloud_infer` → **ai (Node)** 决定本地规则补算或转发 **python-worker**(重 ML)。 + +### 3.4 试用与付费(降云) + +| 状态 | `behavior.cloud_infer` | +| :--- | :--- | +| **试用期内**(`trialEndsAt` 未过期) | 允许(含 `free` 用户体验) | +| **试用结束 + free** | **拒绝**入队;端侧仅规则/本地 | +| **Enterprise**(或试用中) | 允许 | + +校验:`ProductFeature.AI_CLOUD_INFER`(`shared/src/billing/entitlements.ts`)。拒绝码:`TRIAL_EXPIRED_REQUIRES_ENTERPRISE`。 + +--- + +## 4. 数据模型(Server / MySQL) + +| 表(概念) | 内容 | +| :--- | :--- | +| `behavior_event` | 结构化事件流 | +| `behavior_aggregate_hourly` | 预聚合 | +| `ai_result` | LLM/ML 输出 JSON | +| `efficiency_report` | 周报 | +| `process_optimization_report` | 流程优化与 AI 替代候选(P2) | +| `security_incident` | 告警 | + +向量索引(Qdrant):按 `orgId` 分 collection,存窗口标题片段、SOP、历史结论 embedding。 + +--- + +## 5. 本地开发(Docker 私有化栈) + +见 `deploy/compose/docker-compose.dev.yml`: + +| 服务 | 端口 | 说明 | +| :--- | :--- | :--- | +| `mysql` | 3306 | 业务库 | +| `redis` | 6379 | 队列 | +| `ollama` | 11434 | **自托管 LLM** | +| `qdrant` | 6333 | **自托管向量库**(profile `ai`) | +| `python-worker` | 4100 | 重 ML 微服务(profile `ai`) | +| `ai` | 4000 | Node Worker | +| `minio` | 9000 | 录制(可选) | + +**不需要** OpenAI API Key。首次:`ollama pull llama3.2`(及可选 `nomic-embed-text`)。 + +--- + +## 6. 里程碑 + +| 阶段 | 交付 | +| :--- | :--- | +| **B0** | Spec + shared DTO + compose 私有化栈 | +| **B1** | 端侧时序 + server 入库 + 规则告警 | +| **B2** | 端侧 ONNX + 降云 | +| **B3** | Node LLM 摘要 + Qdrant RAG | +| **B4** | Python 基线/异常 | +| **B5** | LangGraph 流程优化 / AI 替代报告 | + +--- + +## 7. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 0.4.0-draft | 多模型;端侧优先;Ollama | +| 2026-05-24 | 0.5.0 | 私有化向量库;Node 主栈;Python 微服务;流程优化路线图 | diff --git a/spec/ai-finetune-spec.md b/spec/ai-finetune-spec.md new file mode 100644 index 0000000..c262158 --- /dev/null +++ b/spec/ai-finetune-spec.md @@ -0,0 +1,82 @@ +# 大模型微调(闭源)Spec + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-AI-FT-001` | +| **版本** | 1.0.0 | +| **可见性** | **闭源**(独立仓库,不纳入公开 Meta-Repo 克隆列表) | +| **关联** | [ai-platform-spec.md](./ai-platform-spec.md) · [licensing-spec.md](./licensing-spec.md) | + +--- + +## 1. 结论:是否独立项目? + +**是。** 微调 toolchain 与公开 `ai` 推理服务 **必须分离**: + +| 公开 `ai` | 私有 `ai-finetune`(建议仓库名) | +| :--- | :--- | +| 运行时推理、队列、RAG、回调 server | 数据准备、训练、评估、导出 | +| 开源 LICENSE(个人非盈利免费) | 商业许可 / 闭源 | +| 不含客户数据与权重文件 | 含组织专属语料与 LoRA 适配器 | + +--- + +## 2. 私有仓职责 + +```text +ai-finetune/ # 私有 Git,仅授权人员 +├── datasets/ # .gitignore 默认忽略真实数据 +│ └── schema/ # 可提交的 JSON Schema +├── train/ +│ ├── lora_qwen.py # 示例:QLoRA +│ └── eval_harness.py +├── export/ +│ └── bundle_packager.py # 生成加密 model bundle +├── deploy/ +│ └── Dockerfile.train # GPU 训练镜像(非运行时) +└── README.md # 导入 ai 运行时说明 +``` + +--- + +## 3. 与公开 `ai` 的集成 + +| 步骤 | 说明 | +| :--- | :--- | +| 1. 训练 | 在 `ai-finetune` 用客户脱敏语料产出 `bundle-v1.tar.enc` | +| 2. 交付 | 客户将 bundle 挂载到私有化 `ai`:`MODEL_BUNDLE_PATH=/data/bundles/v1` | +| 3. 推理 | 公开 `ai` 的 `LlmClient` / LangGraph 读取 bundle 元数据(`adapter_config.json`) | +| 4. 版本 | `GET /internal/models/active` 返回当前 bundle 版本(server 鉴权) | + +**禁止**:在 CI 公开仓库拉取私有 bundle;**禁止** 将 bundle 提交到 Git。 + +--- + +## 4. 技术栈(训练侧) + +| 组件 | 选型 | +| :--- | :--- | +| 语言 | **Python**(PyTorch、PEFT、TRL) | +| 基座 | 客户自托管权重(Qwen / Llama 等,遵守上游许可) | +| 编排 | 可选 MLflow / 简单 Makefile | +| GPU | 训练机独立;与 Ollama 推理机可分离 | + +Node/TS **不参与** 训练循环,仅消费导出产物。 + +--- + +## 5. 功能需求 + +| ID | 需求 | 验收 | +| :--- | :--- | :--- | +| FR-FT-01 | 导出 bundle 含 manifest(版本、基座 hash、适配器类型) | `ai` 可校验 | +| FR-FT-02 | 训练环境与客户生产网络隔离 | 文档化 | +| FR-FT-03 | 删除客户合同后销毁语料与 bundle 副本 | 合规流程 | + +--- + +## 6. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 1.0.0 | 独立闭源微调仓;与公开 ai 推理解耦 | diff --git a/spec/ai-platform-spec.md b/spec/ai-platform-spec.md new file mode 100644 index 0000000..a7ca473 --- /dev/null +++ b/spec/ai-platform-spec.md @@ -0,0 +1,262 @@ +# AI 与洞察平台 Spec(L1) + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-AI-001` | +| **版本** | 0.5.0 | +| **建议仓库** | **`ai/`(独立子项目)** + **`ai/python-worker/`(可选微服务)** | +| **关联** | [ai-behavior-architecture-spec](./ai-behavior-architecture-spec.md) · [commercial-tier-spec](./commercial-tier-spec.md) · [licensing-spec](./licensing-spec.md) · [ai-finetune-spec](./ai-finetune-spec.md) · [enterprise-security-spec](./enterprise-security-spec.md) | + +--- + +## 1. 核心卖点(产品定位) + +### 1.1 私有化部署 · 运维简单 · 数据安全 + +| 原则 | Normative | +| :--- | :--- | +| **默认不出网** | 生产环境 **禁止** 将行为数据、录制、窗口标题等默认发往 OpenAI / Azure OpenAI 等第三方 SaaS | +| **自托管 AI 栈** | LLM:**Ollama / vLLM / 本地兼容 API**;向量库:**Qdrant** 或 **pgvector**(与 MySQL 同 VPC) | +| **密钥不出 Server** | LLM / 向量库凭证仅 `ai`(及 python-worker)持有;`server` 只投递队列与读结果 | +| **可运维** | 全栈 Docker Compose / K8s;无 GPU 时可 CPU 推理小模型;与 VistaRemote 其余服务同版本策略发版 | + +第三方 API(OpenAI 等)仅允许在 **组织显式开启** 且合规评审通过时作为 **可选连接器**,**不是** 默认路径。 + +### 1.2 行为洞察 · 流程优化 · AI 替代(长期) + +| 阶段 | 能力 | 技术路径 | +| :--- | :--- | :--- | +| **现在** | 端侧监控告警、结构化事件入库、效率/安全报告 | 多模型 + 规则 + 统计(见 behavior-architecture) | +| **近期** | 会话/周期 **LLM 摘要**、异常解释、部门效率对比 | Node Worker + 私有化 LLM + RAG(向量库) | +| **未来** | **流程优化建议**、重复操作 **AI 替代** 候选、岗位自动化路线图 | LangGraph 编排 + 行为序列挖掘 + 人在回路审批 | + +数据闭环:`端侧检测 → Server 入库 → 聚合/向量索引 → AI Worker → Admin 报告与建议`。 + +--- + +## 2. 是否独立 `ai` 仓库? + +**是**(Meta-Repo 第 8 子项目)。理由不变:与信令隔离、独立扩缩容、模型与规则独立发版、可部署独立 VPC。 + +| 仓库 | 职责 | +| :--- | :--- | +| **`server`** | 鉴权、元数据、审计、入队 BullMQ、对外查询 API | +| **`ai`(Node/TS)** | 队列消费、LLM 编排、RAG、规则复核、回调 server | +| **`ai/python-worker`** | **仅** Node 难以胜任的重 ML(基线训练、Isolation Forest、深度时序) | +| **`desktop`** | 端侧多模型 + 遥测;**不做** LLM | +| **`shared`** | Job 类型、报告 DTO、策略枚举 | + +--- + +## 3. 技术路线:TypeScript 为主,Python 补强 + +**禁止** 将整个 AI 平台重写为 Python 单体——团队主栈为 **TypeScript**,`server` / `web` / `shared` 契约一致。 + +### 3.1 分工矩阵 + +| 能力 | 运行时 | 框架/库 | 说明 | +| :--- | :--- | :--- | :--- | +| BullMQ 消费、回调 server | **Node** | NestJS 风格模块 / 现有 `ai` Worker | 与 server 同语言 | +| LLM 调用、Prompt、摘要/报告 | **Node** | **LangChain.js**、**LangGraph.js**(编排多步 Agent) | 对接 Ollama OpenAI-compatible API | +| RAG(窗口标题、SOP、历史报告) | **Node** | LangChain + 自托管 **Qdrant/pgvector** | 嵌入模型可 Ollama `nomic-embed-text` 等 | +| 规则引擎、关键词、轻量聚合 | **Node** | 纯 TS / SQL 经 server API | 零 GPU | +| 基线训练、Isolation Forest、重时序 | **Python 微服务** | FastAPI + scikit-learn / pandas | `ai` HTTP 内网调用 | +| 可选 CV 训练(非端侧) | **Python** | 同上 | P2+ | + +### 3.2 调用关系 + +```text +┌─────────────┐ BullMQ ┌──────────────────────────────────────┐ +│ server │ ──────────────► │ ai (Node/TS) — 主 Worker │ +│ NestJS │ │ · LangChain / LangGraph │ +└─────────────┘ │ · LlmClient → Ollama/vLLM │ + ▲ │ · VectorStore → Qdrant │ + │ callback │ · Rules / summarize processors │ + └────────────────────────│ │ HTTP (内网) │ + │ ▼ │ + │ python-worker (FastAPI) — 仅重 ML │ + └──────────────────────────────────────┘ +``` + +| 规则 | 说明 | +| :--- | :--- | +| **NestJS 不直接跑 Python** | `server` 只入队;由 **`ai` Node Worker** 调用 `python-worker` | +| **python-worker 无公网** | 仅 `ai` 与运维网络可达;mTLS 或 HMAC(P2) | +| **新能力默认 Node** | 仅当 Node 生态明显不足(训练/科学计算)才加 Python 端点 | + +--- + +## 4. 逻辑架构(私有化) + +```text + desktop Agent + │ telemetry (HTTPS): 结构化事件,非默认录屏上云 + ▼ +┌─────────────┐ BullMQ/Redis ┌──────────────────────┐ +│ server │ ──── job enqueue ───► │ ai (Node workers) │ +│ MySQL │ ◄── callback REST ─── │ LangChain/LangGraph │ +└──────┬──────┘ └──────────┬───────────┘ + │ │ + │ 录制分片 ├──► Ollama / vLLM (LLM) + ▼ ├──► Qdrant / pgvector (RAG) +┌─────────────┐ └──► python-worker (ML) +│ MinIO / S3 │ +└─────────────┘ +``` + +--- + +## 5. AI 能力与技术选型 + +### 5.1 能力清单 + +| 能力 | 套餐 | 实现 | +| :--- | :--- | :--- | +| 会话录制后摘要 | Pro+ | Node LLM + 可选 RAG | +| 非工作网站识别 | Enterprise | 端侧规则 + 域名表;语义匹配用 **本地嵌入 + 向量库** | +| 操作基线 & 异常 | Enterprise | **Python**:滚动基线、Isolation Forest;Node 负责调度 | +| 敏感外发 / 批量删除 | Enterprise | 端侧 + Node 规则复核 | +| 效率报告 | Enterprise | MySQL 聚合 + Node LLM 润色 | +| 流程优化 / AI 替代建议 | Enterprise(路线图) | LangGraph 多步 + 向量检索历史模式 + 审批流(Admin) | +| 关键词触发录制 | Enterprise | Node 规则,零 GPU | + +### 5.2 LLM(私有化强制默认) + +| 项目 | 选型 | +| :--- | :--- | +| 协议 | OpenAI-compatible HTTP(**指向自托管**) | +| 运行时 | **Node**:`@langchain/core`、`@langchain/langgraph`(或 `@langchain/ollama`) | +| 默认推理 | **Ollama**(开发)/ **vLLM**(生产 GPU) | +| 模型示例 | `llama3.2`、`qwen2.5`(按组织策略配置) | +| 脱敏 | 入模前剥离 PII(路径、账号、证件号正则) | + +### 5.3 向量数据库(自托管) + +| 选项 | 场景 | +| :--- | :--- | +| **Qdrant** | 默认推荐;Docker 单节点即可;LangChain `@langchain/qdrant` | +| **pgvector** | 已重度使用 PostgreSQL 的客户(本项目主库为 MySQL,向量库可独立 PG 实例) | + +用途:窗口标题/SOP/历史报告片段检索,支撑 RAG 摘要与流程优化建议。**禁止** 默认使用 Pinecone 等仅 SaaS 向量库。 + +### 5.4 异常检测 + +| 阶段 | 技术 | 运行时 | +| :--- | :--- | :--- | +| MVP | 固定阈值 | Node / 端侧 | +| V1 | 14 天滚动基线 3σ | **Python** `POST /v1/ml/baseline` | +| V2 | 序列模型(可选) | **Python** | + +--- + +## 6. `ai` 仓库结构(Normative) + +```text +ai/ +├── src/ # Node/TS 主 Worker(默认开发入口) +│ ├── main.ts +│ ├── config/ +│ ├── queue/ # BullMQ processors +│ ├── llm/ # LlmClient + LangChain 适配(P1) +│ ├── agents/ # LangGraph 流程优化/报告编排(P2) +│ ├── vector/ # Qdrant 客户端 +│ ├── python/ # PythonMlClient → python-worker +│ └── rules/ +├── python-worker/ # FastAPI 微服务(仅重 ML) +│ ├── app/main.py +│ ├── Dockerfile +│ └── requirements.txt +├── .env.example +└── spec/SPEC.md +``` + +--- + +## 7. 任务类型(队列 Job) + +| JobType | 触发 | 运行时 | +| :--- | :--- | :--- | +| `recording.summarize` | 录制完成 | Node LLM (+RAG) | +| `behavior.baseline_train` | 每日 cron | **Python** | +| `behavior.anomaly_scan` | 定时 | **Python** + Node 写库 | +| `behavior.cloud_infer` | 端侧降云 | Node 或 Python(按任务) | +| `report.efficiency_weekly` | 每周 | Node LLM | +| `report.process_optimization` | 每月 / 按需 | Node LangGraph | +| `security.rule_eval` | 安全事件 | Node 规则 | + +Payload:`shared/src/ai/`。 + +--- + +## 8. API 边界 + +(与 0.4 版相同,略) + +### 8.1 `server` 对外 + +| Method | Path | 说明 | +| :--- | :--- | :--- | +| `GET` | `/api/v1/ai/summaries/:sessionId` | 会话摘要 | +| `GET` | `/api/v1/ai/reports/efficiency` | 效率报告 | +| `GET` | `/api/v1/ai/reports/process-optimization` | 流程优化建议(Enterprise,P2) | +| `GET` | `/api/v1/security/incidents` | 安全事件 | + +### 8.2 内网 + +| 调用方 | 被调方 | 协议 | +| :--- | :--- | :--- | +| `server` → `ai` | `POST /internal/jobs` | HTTP + HMAC | +| `ai` → `server` | `POST /api/internal/ai/job-result` | 回调 | +| `ai` → `python-worker` | `POST /v1/ml/*` | HTTP 内网 | +| `ai` → Ollama | `/v1/chat/completions` | OpenAI-compatible | +| `ai` → Qdrant | REST/gRPC | 向量读写 | + +--- + +## 9. 功能需求 + +| ID | 需求 | 验收 | +| :--- | :--- | :--- | +| FR-AI-01 | Pro 录制结束后 5min 内异步摘要 | 重试 3 次 | +| FR-AI-02 | Enterprise 异常 1min 内入库 | | +| FR-AI-03 | 记录 token/算力用量到 `ai_usage_log` | | +| FR-AI-04 | **`AI_BASE_URL` 默认指向自托管**;无配置时开发用 Ollama | 文档与 compose 一致 | +| FR-AI-05 | free 调用 AI 返回 `PLAN_FORBIDDEN` | | +| FR-AI-09 | `behavior.cloud_infer` 校验试用/Enterprise | 见 commercial-tier FR-TIER-21 | +| FR-AI-06 | 生产构建 **不依赖** 公网 LLM API Key | CI 无 `OPENAI_API_KEY` 亦可测规则路径 | +| FR-AI-07 | 向量检索仅连自托管 `VECTOR_DB_URL` | | +| FR-AI-08 | 重 ML Job 失败时 Python 超时降级为统计阈值 | 告警可见 | + +--- + +## 10. 隐私与合规 + +| ID | 需求 | +| :--- | :--- | +| SEC-AI-01 | Enterprise 策略同意后方可分析 | +| SEC-AI-02 | 数据驻留:LLM、向量库、MinIO 同区域 | +| SEC-AI-03 | 用户删除录制时级联删除向量与 `ai_result` | +| SEC-AI-04 | 第三方 LLM 须组织开关 + 审计 | + +--- + +## 11. 里程碑 + +| 阶段 | 交付 | +| :--- | :--- | +| **A0** | `ai` Node 脚手架 + Ollama + Qdrant compose | +| **A0b** | `python-worker` 健康检查 + baseline 占位 API | +| **B0** | 端侧规则 + server 行为入库 | +| **A1** | Pro:`recording.summarize`(Node LLM) | +| **A2** | Enterprise 规则 + 向量 RAG | +| **A3** | Python 基线/异常 + 效率周报 | +| **A4** | LangGraph 流程优化报告(人在回路) | + +--- + +## 12. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 0.3.0-draft | 独立 `ai` 仓库 | +| 2026-05-24 | 0.5.0 | 核心卖点:私有化+向量库;Node 主栈+LangChain/LangGraph;Python 微服务;禁默认第三方 LLM | diff --git a/spec/ai-spec.md b/spec/ai-spec.md new file mode 100644 index 0000000..61a7083 --- /dev/null +++ b/spec/ai-spec.md @@ -0,0 +1,44 @@ +# AI 子项目 Spec(`ai/` 仓库) + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-AI-REPO-001` | +| **仓库** | `ai/` | +| **版本** | 0.5.0 | +| **详设** | [ai-platform-spec.md](./ai-platform-spec.md) · [ai-behavior-architecture-spec.md](./ai-behavior-architecture-spec.md) | + +--- + +## 1. 仓库职责 + +**私有化 AI Worker**:Node/TS 主栈 + Python 微服务(仅重 ML)。详见 [ai-platform-spec.md](./ai-platform-spec.md) §1–3。 + +--- + +## 2. 目录结构 + +见 `ai/spec/SPEC.md`。 + +--- + +## 3. 技术栈 + +| 组件 | 选型 | +| :--- | :--- | +| 主运行时 | Node.js 22+、TypeScript | +| 队列 | BullMQ + Redis | +| LLM | LangChain.js / LangGraph.js → **Ollama / vLLM**(自托管) | +| 向量库 | **Qdrant**(自托管) | +| 重 ML | **`ai/python-worker`**(FastAPI),由 Node Worker HTTP 调用 | +| 契约 | `@vistaremote/shared` | + +**不** 将整个 AI 平台改为 Python 单体;**不** 默认依赖 OpenAI API。 + +--- + +## 4. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 0.3.0-draft | 新建 ai 仓库 Spec | +| 2026-05-24 | 0.5.0 | 私有化卖点;Node+LangChain;python-worker;Qdrant | diff --git a/spec/architecture-foundation-spec.md b/spec/architecture-foundation-spec.md new file mode 100644 index 0000000..5fab67a --- /dev/null +++ b/spec/architecture-foundation-spec.md @@ -0,0 +1,54 @@ +# 基础架构就绪 Spec + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-FOUNDATION-001` | +| **版本** | 1.0.0 | +| **关联** | [implementation-status.md](./implementation-status.md) | + +--- + +## 1. 目标 + +定义「开发者克隆后即可开工」的 **最低基础架构**,与产品全量能力区分。 + +--- + +## 2. 基础架构清单(Normative) + +| ID | 组件 | 就绪标准 | 当前 | +| :--- | :--- | :--- | :--- | +| F-01 | Meta-Repo `init` + `dev-up` | 文档化一键命令 | ✅ | +| F-02 | `shared` 构建可被各仓 `file:` 引用 | `pnpm build` 成功 | ✅ | +| F-03 | 环境 profile local/dev/sit/uat | `apply-env` 写各仓 `.env` | ✅ | +| F-04 | Docker 本地依赖 | mysql/redis/ollama compose | ✅ | +| F-05 | Spec 索引 + SDD 流程 | README + SDD spec | ✅ | +| F-06 | Biome + Husky 每仓 | lint on commit | ✅ | +| F-07 | 信令 WSS 服务 | `/signaling` 可连 | ✅ | +| F-08 | 权益 SSOT | `shared/billing/entitlements` | ✅ | +| F-09 | 权限 SSOT | `shared/auth` + policy | ✅ | +| F-10 | 文档站可运行 | `cd docs && pnpm dev` | ✅ | +| F-11 | 业务数据持久化 | TypeORM 实体 + 迁移 | 🟡 P1 | +| F-12 | 用户登录 JWT | Controller/Admin 签发 | 🟡 P1 | +| F-13 | E2E 1:1 远程 | 配对→视频→控制 | 🟡 MVP-B | + +**基础架构阶段完成**:F-01~F-10 为 ✅ 时,团队可 **并行开发各模块功能**;F-11~F-13 为 **产品 MVP 闭环**,按迭代补齐。 + +--- + +## 3. 单仓开发者 + +| 场景 | 要求 | +| :--- | :--- | +| 仅 desktop/mobile | `pnpm setup` + 同级 `shared` | +| 无 Meta 父目录 | 允许;使用 published `@vistaremote/shared` 或 clone shared | + +见 [developer-experience-spec.md](./developer-experience-spec.md)。 + +--- + +## 4. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 1.0.0 | 基础架构清单 | diff --git a/spec/authorization-spec.md b/spec/authorization-spec.md new file mode 100644 index 0000000..ee34de0 --- /dev/null +++ b/spec/authorization-spec.md @@ -0,0 +1,221 @@ +# 认证与授权规范 Spec(RBAC + ABAC + 套餐权益) + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-AUTH-001` | +| **版本** | 1.0.0 | +| **关联** | [commercial-tier-spec.md](./commercial-tier-spec.md) · [messaging-transport-spec.md](./messaging-transport-spec.md) · [enterprise-security-spec.md](./enterprise-security-spec.md) | + +--- + +## 1. 结论:用什么模型? + +| 问题 | 答案 | +| :--- | :--- | +| 纯 RBAC? | **否**。仅靠角色无法表达「只能控本部门设备」「只能看本公司录制」等资源边界。 | +| 纯 ABAC? | **否**。管理台与组织岗位需要稳定的**角色菜单**(IT、老板、审计员),全 ABAC 难运维。 | +| **VistaRemote 选型** | **混合:RBAC(岗位角色)+ ABAC(资源属性)+ Plan 权益(商业化功能)** | + +```text +请求 → 身份认证(JWT)→ Plan 权益(能否用录制/AI) + → RBAC(岗位是否含某权限) + → ABAC(orgId/ownerId/room 是否匹配) + → 允许 / 拒绝(审计) +``` + +--- + +## 2. 三个平面 + +### 2.1 身份平面(Authentication) + +| 凭证 | 主体 | 用途 | +| :--- | :--- | :--- | +| **Controller JWT** | 注册用户 `userId` | Web/Mobile Client API、换取信令票 | +| **Device Token** | 被控 Agent `deviceId` | 注册、心跳、上报遥测 | +| **Admin JWT** | 后台账号 `adminId` | Admin API、Admin SSE | +| **Signaling Ticket** | 短期 JWT | **仅** WSS `/signaling` 升级 | +| **SSE Session** | Cookie 或 `Authorization` + `userId` 绑定 | `/api/v1/events/stream` | + +生产:**HTTPS/WSS 强制 TLS**;密钥分离 `JWT_SECRET` / `ADMIN_JWT_SECRET` / `DEVICE_TOKEN_SECRET`。 + +### 2.2 RBAC 平面(岗位角色) + +#### A. 平台管理台(`web/apps/admin`) + +| 角色 | 代码 | 典型岗位 | 能力摘要 | +| :--- | :--- | :--- | :--- | +| 超级管理员 | `super_admin` | 平台运维负责人 | 全平台用户/套餐/系统配置 | +| 管理员 | `admin` | 平台运营 | 用户/设备/会话/录制/安全(无改系统密钥) | +| 只读审计 | `viewer` | 合规只读 | 列表与详情只读,无写操作 | + +#### B. 企业组织(Enterprise,`Organization`) + +绑定在 **User** 上的 `orgRole`(可与平台 Admin 账号分离): + +| 角色 | 代码 | 业务称呼 | 能力摘要 | +| :--- | :--- | :--- | :--- | +| 组织所有者 | `org_owner` | 老板 / 高管 | 本组织策略、成员、全部监控与报告 | +| 组织管理员 | `org_admin` | IT 负责人 | 成员与设备管理、策略、强制断开 | +| IT 支持 | `it_support` | IT Support | 对本组织设备远程协助(须审计 + 被控授权策略) | +| 安全审计 | `security_auditor` | 安全合规 | 本组织录制/安全事件/报告只读 | +| 普通成员 | `member` | 普通员工 | 仅本人设备与受邀会话 | + +> **平台 Admin** 与 **企业 User** 是两套账号体系:前者管「全平台」,后者在 Client 端远程桌面。企业 IT 可同时拥有 User(`it_support`)与可选 Admin 子账号(P2 SSO)。 + +#### C. 被控端 + +| 角色 | 说明 | +| :--- | :--- | +| **Controlled Agent** | Device Token,无 RBAC 菜单,能力由 Agent 版本与组织策略下发 | + +### 2.3 ABAC 平面(资源属性) + +策略引擎输入 **Subject + Action + Resource**: + +| 属性 | 来源 | 示例 | +| :--- | :--- | :--- | +| `subject.userId` | JWT | `u-123` | +| `subject.orgId` | User / JWT | `org-acme` | +| `subject.orgRole` | User | `it_support` | +| `subject.adminRole` | Admin JWT | `admin` | +| `resource.orgId` | Device/Room/Recording | 必须匹配(企业域) | +| `resource.ownerId` | Device.ownerId | 设备归属 | +| `resource.roomId` | Room | 会话成员关系 | +| `action` | API/WS | `remote.control` | + +**示例策略(Normative)** + +| ID | 规则 | +| :--- | :--- | +| POL-01 | `member` 仅 `remote.control` **自己拥有**的 Device 或 Pairing 授权的 Room | +| POL-02 | `it_support` 可 `remote.control` **同 org** 且 Device 标记 `allowOrgSupport=true` 或存在有效 SupportGrant | +| POL-03 | `org_owner` / `org_admin` 可 `session.observe` 本 org 任意活跃 Room(SFU 订阅) | +| POL-04 | `security_auditor` 可 `recording.read` / `security.read`,不可 `remote.control` | +| POL-05 | `viewer`(平台)可 `admin.read`,不可 `admin.write` | +| POL-06 | 跨 `orgId` 访问一律拒绝(除非 `super_admin`) | + +### 2.4 Plan 权益平面(商业化) + +来自 [commercial-tier-spec.md](./commercial-tier-spec.md):`free` | `pro` | `enterprise`。 + +| 能力 | 校验点 | +| :--- | :--- | +| 录制/回放 | API + `PlanGuard`;与角色正交 | +| 多屏监控 / 安全遥测 | `enterprise` + `orgRole` 含监控权限 | +| AI 摘要 | `pro`+ | + +**顺序**:先认证 → 再 Plan → 再 RBAC → 再 ABAC。 + +--- + +## 3. 权限字表(`shared` SSOT) + +见 `shared/src/auth/permissions.ts`。分类: + +- `remote.*` — Client 远程 +- `recording.*` +- `security.*` +- `admin.*` — 管理台 +- `org.*` — 组织策略与成员 + +--- + +## 4. JWT 载荷(摘要) + +### 4.1 Controller Access Token + +```typescript +interface ControllerJwtClaims { + typ: 'controller'; + sub: string; // userId + orgId?: string; + orgRole?: OrgRole; + plan: UserPlan; + permissions: Permission[]; // RBAC 展开结果(缓存) + iat: number; + exp: number; // 建议 15–60min +} +``` + +### 4.2 Signaling Ticket(短效) + +```typescript +interface SignalingTicketClaims { + typ: 'signaling'; + sub: string; // userId + deviceId: string; // 主控端设备实例 + sessionId: string; // roomId + permissions: Permission[]; + exp: number; // 建议 5–15min +} +``` + +WSS 握手:`Authorization: Bearer ` 或 query `?ticket=`(仅开发)。 + +### 4.3 Admin JWT + +```typescript +interface AdminJwtClaims { + typ: 'admin'; + sub: string; // adminId + role: PlatformAdminRole; + permissions: Permission[]; + exp: number; +} +``` + +### 4.4 Device Token + +长期或滚动刷新;仅用于 Agent API,**不能**用于信令或远程控制主控。 + +--- + +## 5. 通道鉴权矩阵 + +| 通道 | 认证方式 | 授权 | +| :--- | :--- | :--- | +| REST `/api/v1/*`(Client) | Controller JWT | RBAC+ABAC+Plan | +| REST `/api/v1/admin/*` | Admin JWT | Platform RBAC | +| WSS `/signaling` | Signaling Ticket | 须含 `signaling.join`;Room 成员 ABAC | +| SSE `/events/stream` | Controller 或 Admin JWT | `userId` 绑定 + `audience` 过滤 | +| DataChannel `control` | DTLS + 会话内已授权 | 建立会话时已判定 `remote.control` | +| Agent API | Device Token | 设备归属 | + +--- + +## 6. 实现映射(代码) + +| 仓库 | 路径 | +| :--- | :--- | +| shared | `src/auth/` 角色、权限、JWT、策略求值 | +| server | `src/auth/` Guards、`PolicyService`、`SignalingTicketService` | +| web/client | 登录存 Token;`SignalingClient` 带 ticket | +| web/admin | 路由守卫按 `PlatformAdminRole` | +| docs | `/architecture/authorization` | + +--- + +## 7. 审计 + +凡 **拒绝** 敏感动作(跨 org、强制控台、导出录制)写 `AuditLog`:`auth.denied` + action + resource meta。 + +--- + +## 8. 与常见岗位对照 + +| 业务说法 | 推荐配置 | +| :--- | :--- | +| 普通员工 | User `orgRole=member`,Client 登录 | +| 老板 | User `orgRole=org_owner`,Enterprise | +| IT Support | User `orgRole=it_support` + 设备 `allowOrgSupport` | +| 平台管理员 | Admin 账号 `admin` / `super_admin` | +| 合规只读 | Admin `viewer` 或 User `security_auditor` | + +--- + +## 9. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 1.0.0 | 混合 RBAC+ABAC+Plan;JWT/信令/SSE;组织角色与策略字表 | diff --git a/spec/billing-commerce-spec.md b/spec/billing-commerce-spec.md new file mode 100644 index 0000000..3a06c8e --- /dev/null +++ b/spec/billing-commerce-spec.md @@ -0,0 +1,115 @@ +# 订单、订阅与支付 Spec + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-BILL-001` | +| **版本** | 1.0.0 | +| **关联** | [commercial-tier-spec.md](./commercial-tier-spec.md) · [licensing-spec.md](./licensing-spec.md) · [web-admin-spec.md](./web-admin-spec.md) | + +--- + +## 1. 付费形态 + +| 形态 | 代码 | 说明 | +| :--- | :--- | :--- | +| **订阅** | `subscription` | 按月/年续费;`planExpiresAt` 到期失效 | +| **买断** | `perpetual` | 一次付费,对应套餐永久有效(大版本升级可另售) | + +连续订阅优惠(Normative): + +| SKU | 说明 | +| :--- | :--- | +| `pro_monthly` / `enterprise_monthly` | 月付标价 | +| `pro_yearly` / `enterprise_yearly` | 年付,相对月付约 **84–85 折**(`discountRate` 在 catalog) | +| `pro_perpetual` / `enterprise_perpetual` | 买断价 | + +商品目录 SSOT:`shared/src/billing/catalog.ts`。 + +--- + +## 2. 试用与功能拦截 + +与 [commercial-tier-spec](./commercial-tier-spec.md) 一致: + +| 功能 | 试用 | 试用后 Free | 付费 | +| :--- | :---: | :---: | :--- | +| SFU | ✓ | ✗ | Pro+ 且订阅有效或买断 | +| AI 降云 | ✓ | ✗ | Enterprise 且有效 | + +**各端拦截**: + +| 端 | 实现 | +| :--- | :--- | +| **server** | `EntitlementService`;信令 SFU、队列 `cloud_infer` | +| **web client** | `GET /billing/entitlements` + `FeatureGate` | +| **desktop** | `assertCloudInferAllowed` 降云前 | +| **mobile** | `fetchEntitlements` / `canUseSfu` | + +SSOT:`shared/src/billing/entitlements.ts`。 + +--- + +## 3. 支付渠道 + +| 渠道 | 代码 | 阶段 | +| :--- | :--- | :--- | +| 微信支付 | `wechat` | P1 对接 | +| 支付宝 | `alipay` | P1 | +| PayPal | `paypal` | P1 | +| Wise | `wise` | P1 | +| 银行卡 | `bank_card` | **后续**(占位,默认不可用) | + +`isPaymentProviderActive()` 控制创建订单;回调统一 `POST /api/internal/billing/webhook/:provider`(P1)。 + +--- + +## 4. Admin 模块 + +| 模块 | 路径(示意) | 职责 | +| :--- | :--- | :--- | +| **用户管理** | `/users` | 列表、套餐、试用/到期 | +| **订单管理** | `/orders` | 订单状态、模拟支付(dev) | +| **权限管理** | `/permissions` | 平台/组织 RBAC 字表;非订单权限 | + +API(dev): + +| Method | Path | +| :--- | :--- | +| `GET` | `/api/v1/billing/entitlements` | +| `GET` | `/api/v1/billing/catalog` | +| `POST` | `/api/v1/billing/orders` | +| `GET` | `/api/v1/admin/orders` | +| `GET` | `/api/v1/admin/users` | +| `POST` | `/api/v1/admin/users/:id/plan` | + +--- + +## 5. 数据模型(目标 MySQL) + +| 表 | 字段摘要 | +| :--- | :--- | +| `user` | `plan`, `billing_kind`, `trial_ends_at`, `plan_expires_at` | +| `order` | `user_id`, `sku`, `provider`, `status`, `amount_cents`, `paid_at` | +| `payment_webhook_log` | 回调审计 | + +当前 dev:`server/src/billing/user-subscription.store.ts` 内存实现。 + +--- + +## 6. 功能需求 + +| ID | 需求 | 验收 | +| :--- | :--- | :--- | +| FR-BILL-01 | 创建订单校验 SKU 与支付渠道 | | +| FR-BILL-02 | 支付成功更新用户 `plan` + `billing_kind` + 到期 | | +| FR-BILL-03 | 订阅过期后 `hasActivePaidPlan` 为 false | | +| FR-BILL-04 | 各端未付费展示拦截文案 | `featureGateMessage` | +| FR-BILL-05 | 第二路观众无 SFU 权益拒绝信令 | `TRIAL_EXPIRED_REQUIRES_PRO` | + +--- + +## 7. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 1.0.0 | 买断/订阅;支付渠道;Admin 三模块;多端拦截 | diff --git a/spec/cicd-release-spec.md b/spec/cicd-release-spec.md new file mode 100644 index 0000000..2d5a416 --- /dev/null +++ b/spec/cicd-release-spec.md @@ -0,0 +1,131 @@ +# CI/CD 与发布规范 Spec + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-CICD-001` | +| **版本** | 1.0.0 | +| **关联** | [meta-repo-development-spec.md](./meta-repo-development-spec.md) · [git-collaboration-spec.md](./git-collaboration-spec.md) | + +--- + +## 1. 核心原则 + +| 原则 | 说明 | +| :--- | :--- | +| **分仓构建、分仓发布** | 无「整个 Meta-Repo 打一个运行时包」;各仓库独立 tag / 镜像 / 静态资源 | +| **shared 先行** | 契约变更必须先发布 `@vistaremote/shared`,再触发消费者同步 | +| **本地 `file:`、CI 兄弟目录** | Meta-Repo 内开发用 `file:../shared`;GitHub Actions 用 `setup-shared` 检出兄弟目录布局 | +| **生产用 Registry** | Docker / 离线构建从 **GitHub Packages** 安装固定 SemVer | + +--- + +## 2. 发布拓扑 + +```text +shared tag v* ──► npm @vistaremote/shared (GitHub Packages) + │ + └── repository_dispatch: shared-published + │ + ├── server / web / ai / desktop / mobile + │ sync-shared.yml → PR chore/bump-shared-x.y.z + │ + └── (可选) 各仓 tag 后 release.yml → 镜像 / 静态站 / Releases + +deploy 仓:组合各服务镜像 tag / digest,不构建业务代码 +Meta-Repo:仅脚手架 CI,不发布运行时 +``` + +--- + +## 3. shared 发布 + +| ID | 规则 | +| :--- | :--- | +| FR-CICD-01 | 合并到 `main` 后,维护者打 tag `vMAJOR.MINOR.PATCH`(与 `package.json#version` 一致) | +| FR-CICD-02 | `shared/.github/workflows/release.yml` 构建并发布至 `npm.pkg.github.com` | +| FR-CICD-03 | 发布成功后向消费者仓库发送 `repository_dispatch`(`shared-published`) | +| FR-CICD-04 | 需要组织 Secret **`VISTAREMOTE_CI_PAT`**(`repo` + `workflow`),供跨仓触发 | + +--- + +## 4. 消费者同步 + +| ID | 规则 | +| :--- | :--- | +| FR-CICD-10 | 各消费者 `sync-shared.yml` 接收 `version`,运行 `pin-shared-version.mjs` | +| FR-CICD-11 | 自动开 PR:`chore/bump-shared-x.y.z`,标题 `chore(deps): bump @vistaremote/shared to x.y.z` | +| FR-CICD-12 | PR 必须通过本仓 CI(lint / test / build)后合并 | +| FR-CICD-13 | **本地 Meta 开发**仍可用 `file:../shared`;合并 registry 版本后执行 `pnpm install` 即可 | + +依赖写法(发布后): + +```json +"@vistaremote/shared": "^0.2.0" +``` + +配合 `.npmrc`(模板见 `tooling/templates/npmrc.github-packages`): + +```ini +@vistaremote:registry=https://npm.pkg.github.com +``` + +--- + +## 5. 各仓发布产物 + +| 仓库 | 触发 | 产物 | 工作流 | +| :--- | :--- | :--- | :--- | +| **shared** | tag `v*` | npm 包 | `release.yml` | +| **server** | tag `server-v*` | Docker 镜像 `ghcr.io/vistaremote/server` | `release.yml` | +| **ai** | tag `ai-v*` | Docker 镜像 `ghcr.io/vistaremote/ai` | `release.yml` | +| **web** | tag `web-v*` | 静态资源 artifact(client + admin) | `release.yml` | +| **desktop** | tag `desktop-v*` | GitHub Release 安装包(占位) | `release.yml` | +| **docs** | tag `docs-v*` | GitHub Pages | `release.yml` | +| **mobile** | tag `mobile-v*` | 构建校验 artifact(商店流水线 P1) | `release.yml` | +| **deploy** | tag `deploy-v*` | 校验 compose / 发布说明 | `release.yml` | + +**推荐发版节奏**:`shared` → 合并各消费者 bump PR → 各业务仓打 tag → `deploy` 更新 compose 中的镜像 tag。 + +--- + +## 6. CI 约定(已有 + 新增) + +| 阶段 | 内容 | +| :--- | :--- | +| PR / push | `ci.yml`:setup-shared → lint → test → build | +| shared 发布 | `release.yml` | +| 依赖同步 | `sync-shared.yml` | +| 服务发版 | `release.yml`(tag 触发) | + +Meta-Repo:`meta-ci.yml` 仅脚手架,不替代子仓。 + +--- + +## 7. Secrets 清单(组织 / 仓库) + +| Secret | 用途 | +| :--- | :--- | +| `VISTAREMOTE_CI_PAT` | shared 发布后发 `repository_dispatch`;可选用于跨仓 PR | +| `GITHUB_TOKEN` | 默认可发布本仓 Packages(`packages: write`) | +| `GHCR` | 使用 `GITHUB_TOKEN` 推送 `ghcr.io//` | + +--- + +## 8. 维护命令 + +```bash +# Meta-Repo 根:同步 workflow / action 到各子仓 +node tooling/scripts/setup-github-workflows.mjs + +# 手动模拟 shared 发布后 bump(在消费者仓目录) +node ../tooling/scripts/pin-shared-version.mjs 0.2.0 +pnpm install +``` + +--- + +## 9. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 1.0.0 | 初稿:shared 发布、消费者 dispatch、分仓 release 模板 | diff --git a/spec/commercial-resources-spec.md b/spec/commercial-resources-spec.md new file mode 100644 index 0000000..85d6ba2 --- /dev/null +++ b/spec/commercial-resources-spec.md @@ -0,0 +1,88 @@ +# 商业化资源点与功能切割 Spec + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-TIER-RES-001` | +| **版本** | 1.0.0 | +| **关联** | [commercial-tier-spec.md](./commercial-tier-spec.md) · [recording-playback-spec.md](./recording-playback-spec.md) · [webrtc-architecture-spec.md](./webrtc-architecture-spec.md) | + +--- + +## 1. 原则 + +| 原则 | 说明 | +| :--- | :--- | +| **默认轻服务端** | 媒体、编码、磁盘缓冲优先在 **端侧**;Server/SFU 只做信令、元数据、对象存储签名 | +| **重资源 = 付费点** | 消耗 CPU/带宽/存储/LLM 的能力映射 `ProductFeature`,SSOT:`shared/src/billing/entitlements.ts` | +| **可观测** | Admin 展示套餐与资源型开关;审计 `plan_changed`、录制配额 | + +--- + +## 2. 资源型能力目录 + +| ProductFeature | 资源消耗点 | 默认实现位置 | Trial | Free | Pro | Ent | +| :--- | :--- | :--- | :---: | :---: | :---: | :---: | +| `webrtc.sfu` | mediasoup CPU/UDP、机房带宽 | SFU 侧车 | ✓ | — | ✓ | ✓ | +| `recording` | 端侧编码磁盘;**上传**占用出口与 S3 | **Desktop 缓冲+分片上传** | — | — | ✓ | ✓ | +| `recording.sfu_server` | SFU **PlainTransport + FFmpeg** 转码/落盘 | mediasoup-controller | — | — | — | ✓ | +| `ai.cloud_infer` | 云端 GPU/LLM | `ai` Worker | ✓ | — | — | ✓ | +| `ai.recording_summarize` | 录制完成后 LLM+RAG | `ai` BullMQ | — | — | ✓ | ✓ | +| `telemetry.enterprise` | 高频事件入库 | server + MySQL | — | — | — | ✓ | +| `storage.recording_quota` | 对象存储容量 | MinIO/S3 生命周期 | — | — | 配额 | 可配 | + +> **不在 SFU 上默认录制** — 见 [recording-playback-spec.md](./recording-playback-spec.md)。 +> **服务端录制** 为 Enterprise 增值项,需显式开启且校验 `recording.sfu_server`。 + +--- + +## 3. 录制策略(Normative) + +```text +默认(Pro+): + Desktop 采集 → 本地缓冲环区 → 定时/阈值触发分片上传 → Server 元数据 + S3 + SFU 路径: 不录制(零 mediasoup 磁盘/FFmpeg 负载) + +可选(Enterprise + recording.sfu_server): + mediasoup Producer → PlainTransport → FFmpeg 裸流拷贝 → 分片落盘/上传 + 用于「无法安装 Agent」或合规要求中心侧留痕的场景 +``` + +--- + +## 4. 配额与策略(Admin 可配) + +| 策略键 | 说明 | 默认 | +| :--- | :--- | :--- | +| `recording.retentionDays` | 云存储保留 | Pro 90 / Ent 可延长 | +| `recording.monthlyUploadGb` | 组织月上传上限 | Pro 50 / Ent 合同 | +| `recording.localBufferMaxMb` | Agent 本地环区上限 | 512 | +| `recording.uploadIntervalSec` | 定时上传间隔 | 60 | +| `sfu.recordingEnabled` | 是否允许 SFU 侧录制 | false | + +--- + +## 5. Enforcement 映射 + +| 场景 | Feature | 组件 | +| :--- | :--- | :--- | +| 第二观众 / SFU 模式 | `webrtc.sfu` | `SignalingService` | +| Desktop 开始云录制上传 | `recording` | `desktop/recording` + server `RecordingService` | +| 请求 SFU PlainTransport 录制 | `recording.sfu_server` | mediasoup-controller + server | +| 入队 cloud_infer | `ai.cloud_infer` | `AiQueueService` | +| 入队 summarize | `ai.recording_summarize` | BullMQ | + +--- + +## 6. SKU 扩展(P1) + +可在 `PRODUCT_CATALOG` 增加: + +- `addon_sfu_recording` — 单独买断服务端录制(非 Ent 全包客户) + +--- + +## 7. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 1.0.0 | 资源点目录;端侧默认录制;SFU 录制 Enterprise | diff --git a/spec/commercial-tier-spec.md b/spec/commercial-tier-spec.md new file mode 100644 index 0000000..4989671 --- /dev/null +++ b/spec/commercial-tier-spec.md @@ -0,0 +1,114 @@ +# 商业化与用户套餐 Spec(L1) + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-TIER-001` | +| **版本** | 0.7.0 | +| **资源切割** | [commercial-resources-spec.md](./commercial-resources-spec.md) | +| **订单支付** | [billing-commerce-spec.md](./billing-commerce-spec.md) | +| **关联** | [licensing-spec.md](./licensing-spec.md) · [server-spec](./server-spec.md) · [webrtc-architecture-spec](./webrtc-architecture-spec.md) · [ai-platform-spec](./ai-platform-spec.md) | + +--- + +## 1. 套餐定义 + +| 套餐 | 代码 | 目标用户 | 计费(示意) | +| :--- | :--- | :--- | :--- | +| **免费版** | `free` | 个人、试用结束后未订阅 | ¥0 | +| **专业版** | `pro` | 技术支持、小团队 | 订阅制 | +| **企业版** | `enterprise` | 企业 IT、合规团队 | 合同约定 | + +用户字段:`plan`、`billingKind`(`none` | `subscription` | `perpetual`)、`planExpiresAt`(订阅到期)、`trialEndsAt`(试用截止,Unix ms)、`orgId`。 + +**付费形态**:**订阅**(连续包月/包年,年付享 catalog 折扣)或 **买断**(一次付费,永久享有对应套餐能力)。详见 [billing-commerce-spec.md](./billing-commerce-spec.md)。 + +**开源授权**(能否部署/改代码)见 [licensing-spec.md](./licensing-spec.md):**个人非盈利免费;任何商业使用须另签商业许可**。本节仅规定 **SaaS/自建实例上的功能开关**。 + +--- + +## 2. 试用期(Trial) + +| 项目 | 规则 | +| :--- | :--- | +| 默认时长 | **14 天**(注册或组织创建时写入 `trialEndsAt`,Admin 可调整) | +| 试用期内 | 可使用下文 **「试用含付费能力」** 全部项(在套餐矩阵中标注 Trial 列) | +| 试用结束且仍为 `free` | **SFU**、**AI 端侧降云** 立即关闭;1:1 **P2P** 远程仍可用 | +| 恢复 | 升级 **Pro**(SFU)或 **Enterprise**(含降云)并付费 | + +```text +试用中 ──► 可 SFU + 可 behavior.cloud_infer +试用结束 + free ──► 仅 P2P;降云 Job 拒绝;SFU 分配拒绝 +试用结束 + pro/enterprise ──► 按套餐矩阵 +``` + +实现 SSOT:`shared/src/billing/entitlements.ts` — `canUseFeature()`、`ProductFeature`。 + +--- + +## 3. 能力矩阵 + +| 能力 | ProductFeature | Trial | Free | Pro | Enterprise | +| :--- | :--- | :---: | :---: | :---: | :---: | +| 远程控制 **P2P 1:1** | — | ✓ | ✓ | ✓ | ✓ | +| 基础审计 | — | ✓ | ✓ | ✓ | ✓ | +| **WebRTC SFU** | `webrtc.sfu` | ✓ | — | ✓ | ✓ | +| **AI 云端推理** | `ai.cloud_infer` | ✓ | — | — | ✓ | +| **端侧录制 + 云上传回放** | `recording` | — | — | ✓ | ✓ | +| **SFU 服务端录制**(PlainTransport+FFmpeg) | `recording.sfu_server` | — | — | — | ✓ | +| **录制 AI 摘要** | `ai.recording_summarize` | — | — | ✓ | ✓ | +| 企业遥测 / 安全 / 效率报告 | `telemetry.enterprise` 等 | — | — | — | ✓ | + +> 完整资源说明:[commercial-resources-spec.md](./commercial-resources-spec.md)。 +> **默认不在 SFU 上录制**;录制在 **Desktop 缓冲+分片上传**(减服务端压力)。 + +### 3.1 录制与存储(产品口径) + +| 项目 | 说明 | +| :--- | :--- | +| 默认 | Agent 本地环区 → 定时上传 S3;Server 只存元数据 | +| SFU 录制 | 仅 Enterprise 可选;**额外** CPU/带宽,单独 Feature | +| 试用 | 不含云录制(与现矩阵一致) | + +--- + +## 4. 服务端 enforcement(Normative) + +| ID | 场景 | 校验点 | 拒绝码 | +| :--- | :--- | :--- | :--- | +| FR-TIER-20 | 分配 mediasoup / `session-mode: sfu` | `ProductFeature.WEBRTC_SFU` | `TRIAL_EXPIRED_REQUIRES_PRO` 或 `PLAN_FORBIDDEN` | +| FR-TIER-21 | 入队 `behavior.cloud_infer` | `ProductFeature.AI_CLOUD_INFER` | `TRIAL_EXPIRED_REQUIRES_ENTERPRISE` | +| FR-TIER-22 | `TransportPolicyService` 决策 SFU | 同上 | 回退 P2P 或拒绝第二观众 | +| FR-TIER-23 | JWT / 会话元数据携带 `trialEndsAt` | Client 展示「试用剩余」 | — | +| FR-TIER-24 | `POST /recordings/start` 校验 `recording` | free → `PLAN_FORBIDDEN` | +| FR-TIER-25 | SFU 录制 API 校验 `recording.sfu_server` | Pro 亦拒绝 | +| FR-TIER-26 | 月上传量配额 `recording.monthlyUploadGb` | 超额拒绝 | + +--- + +## 5. 其他功能需求 + +| ID | 需求 | 验收 | +| :--- | :--- | :--- | +| FR-TIER-01 | AI/录制 API 校验 `user.plan` | free 返回 `PLAN_FORBIDDEN` | +| FR-TIER-02 | Admin 可改套餐、试用截止、到期日 | 审计 `plan_changed` | +| FR-TIER-03 | Pro 录制配额可配置 | 超额拒绝 | +| FR-TIER-04 | Enterprise 绑定 Organization | | +| FR-TIER-05 | 套餐/试用变更 **60s 内** 生效 | JWT 短 TTL | + +--- + +## 6. Admin 管理台 + +(与 0.3 版相同:全用户、试用截止列、批量改套餐。) + +| FR-TIER-14 | 用户详情展示 `trialEndsAt`、是否可 SFU/降云 | 只读标签 | + +--- + +## 7. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 0.3.0-draft | Free / Pro / Enterprise 矩阵 | +| 2026-05-24 | 0.5.0 | 试用期;SFU 与 AI 降云试用后付费;entitlements SSOT | +| 2026-05-24 | 0.7.0 | 资源点切割;端侧默认录制;SFU 录制 Enterprise | diff --git a/spec/deploy-spec.md b/spec/deploy-spec.md new file mode 100644 index 0000000..d52569a --- /dev/null +++ b/spec/deploy-spec.md @@ -0,0 +1,157 @@ +# Deploy 部署 Spec + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-DPL-001` | +| **仓库** | `deploy/` | +| **技术栈** | Docker, Docker Compose,(可选)Kubernetes | +| **版本** | 0.4.0-draft | +| **关联** | [ai-platform-spec.md](./ai-platform-spec.md) · [ai-behavior-architecture-spec.md](./ai-behavior-architecture-spec.md) | + +--- + +## 1. 职责 + +提供 **可复现的一键/分步部署** 模板,覆盖: + +- **MySQL 8**(必选,utf8mb4) +- **Redis**(必选,会话 + BullMQ) +- **MinIO / S3**(Pro+ 录制) +- **Ollama**(或兼容 OpenAI API 的私有化 LLM,**非**默认公网 OpenAI) +- **Qdrant**(AI **向量数据库**,RAG / 行为模式检索) +- **`ai/python-worker`**(重 ML 微服务,Compose profile `ai`) +- NestJS **server** +- NestJS **`ai`** Worker(Enterprise / Pro 摘要、向量索引) +- **coturn**(STUN/TURN,P2P 穿透;非默认媒体中继中心) +- **mediasoup-worker** SFU 侧车(1:N、TURN 减压;**不部署 SRS**) +- **web-client** / **web-admin** 静态资源 + +**数据库规范**:仅 **MySQL**;文档中出现 PostgreSQL 视为历史笔误。 + +**不包含**:Desktop Agent 安装包构建(见 desktop-spec CI)。 + +--- + +## 2. 目录结构(目标) + +```text +deploy/ +├── docker/ +│ ├── server.Dockerfile # 基础镜像 node:22-alpine(或 22-bookworm-slim) +│ └── web.Dockerfile +├── compose/ +│ ├── docker-compose.yml # 开发/小规模 +│ ├── docker-compose.dev.yml # 本地:MySQL + Redis + Ollama + MinIO;profile ai → Qdrant + python-worker +│ ├── README.md +│ └── .env.example +├── k8s/ # P1 +│ ├── server-deployment.yaml +│ └── ingress.yaml +└── README.md +``` + +--- + +## 3. Compose 服务定义 + +### 3.1 核心栈(默认 `docker compose up`) + +| 服务 | 镜像 | 端口 | 依赖 | +| :--- | :--- | :--- | :--- | +| `mysql` | mysql:8 | 3306 | 持久卷 | +| `redis` | redis:7 | 6379 | — | +| `minio` | minio/minio | 9000, 9001 | 录制对象存储(可选启) | +| `ollama` | ollama/ollama | 11434 | 持久卷 `ollama_data`;LLM | +| `server` | 自建 | 3000 | mysql, redis, minio | +| `ai` | 自建 | 4000 | redis, **ollama**, **qdrant**(RAG 时) | +| `web-client` | nginx 静态 | 80 | — | +| `web-admin` | nginx 静态 | 81 或子路径 | — | + +### 3.2 Profile `ai`(私有化 AI + 向量库) + +```bash +docker compose -f compose/docker-compose.dev.yml --profile ai up -d +``` + +| 服务 | 镜像 | 端口 | 说明 | +| :--- | :--- | :--- | :--- | +| **`qdrant`** | qdrant/qdrant | **6333**(HTTP)、6334(gRPC 可选) | **向量数据库**;LangChain RAG;按 `orgId` 分 collection | +| **`python-worker`** | 自建 `ai/python-worker` | **4100** | PaddleOCR / 异常检测等重 ML;`ai` 通过 HTTP 调用 | + +> `ollama` 在 dev compose 中 **默认已启动**;`qdrant` 与 `python-worker` 需 `--profile ai`。 +> 实现见 `deploy/compose/docker-compose.dev.yml`、`deploy/compose/README.md`。 + +### 3.3 Profile `webrtc` + +| 服务 | 镜像 | 端口 | 依赖 | +| :--- | :--- | :--- | :--- | +| `coturn` | coturn/coturn | 3478, 5349 | — | +| `mediasoup-controller` | `deploy/mediasoup-controller` 镜像 | 4444 + UDP 40000-40100 | server `MEDIASOUP_CONTROLLER_URL` | + +### 3.4 AI 相关环境变量(Normative) + +| 变量 | 消费者 | 示例 | +| :--- | :--- | :--- | +| `AI_BASE_URL` | `ai` | `http://ollama:11434/v1` | +| `AI_MODEL` | `ai` | `llama3.2` | +| **`VECTOR_DB_URL`** | **`ai`** | **`http://qdrant:6333`** | +| `PYTHON_ML_URL` | `ai` | `http://python-worker:4100` | +| `REDIS_URL` | `server`, `ai` | `redis://redis:6379` | + +向量库 **默认 Qdrant**(自托管);**禁止** 生产默认依赖 Pinecone 等仅 SaaS 向量库(见 ai-platform-spec §5.3)。 +可选 **pgvector** 为独立 PG 实例(主业务库仍为 MySQL)。 + +### 3.5 向量库部署要点 + +| 项 | 说明 | +| :--- | :--- | +| **数据卷** | `qdrant_data` 持久化 `/qdrant/storage` | +| **网络** | `ai` 与 `qdrant` 同 Compose 网络或同 VPC | +| **安全** | 生产不对公网暴露 6333;内网 + 可选 API Key | +| **合规** | 用户删除录制/组织注销时,`ai` 级联删除对应 collection 片段(SEC-AI-03) | +| **规模** | 单节点 Qdrant 满足企业内网 RAG;集群为 P2 | + +--- + +## 4. 功能需求 + +| ID | 需求 | 验收标准 | +| :--- | :--- | :--- | +| FR-DPL-01 | `docker compose up` 启动最小可用信令 + TURN | web 能完成 1:1 配对(需 Agent) | +| FR-DPL-02 | 所有密钥经 `.env`,提供 `.env.example` | 无密钥进 Git | +| FR-DPL-03 | 健康检查 `/health` on server | Compose `healthcheck` 通过 | +| FR-DPL-04 | 文档说明防火墙需开放端口 | UDP 3478、TURN relay 范围 | +| FR-DPL-05 | 生产 Compose 使用非 root 用户 | | +| FR-DPL-06 | dev compose 含 **Qdrant**;`--profile ai` 启向量库 + python-worker | `curl http://localhost:6333/` 可达 | +| FR-DPL-07 | `.env.example` 含 `VECTOR_DB_URL`、`PYTHON_ML_URL` | 与 `ai/.env.example` 一致 | +| FR-DPL-08 | 文档说明 Ollama 拉模型与 Qdrant 启停 | `deploy/compose/README.md` | + +--- + +## 5. 网络与 WebRTC 部署要点 + +| 项 | 说明 | +| :--- | :--- | +| **TURN** | 公网部署 coturn,`external-ip` 正确配置 | +| **mediasoup SFU** | 与 Server 同 VPC;UDP 端口段文档化;面向低并发(非 SRS 级直播) | +| **TURN 容量** | 监控 relay 带宽;超阈时 Server 引导新会话走 SFU | +| **HTTPS** | Web 与 WSS 必须 TLS;可用 Traefik/Caddy 终止 | + +--- + +## 6. Out of Scope + +- Desktop Agent 的 MSI/dmg 打包流水线(在 `desktop` 仓库) +- 多云 Terraform(P2) + +--- + +## 7. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 0.1.0-draft | 初稿 | +| 2026-05-24 | 0.2.0-draft | web-client / web-admin 双静态服务 | +| 2026-05-24 | 0.3.0-draft | MySQL、MinIO、ai worker | +| 2026-05-24 | 0.3.1 | 明确废除 PostgreSQL;对齐国内 MySQL 运维 | +| 2026-05-24 | 0.4.0-draft | 补充 Ollama、**Qdrant 向量库**、python-worker;profile `ai`;环境变量 | diff --git a/spec/desktop-performance-spec.md b/spec/desktop-performance-spec.md new file mode 100644 index 0000000..13a3a57 --- /dev/null +++ b/spec/desktop-performance-spec.md @@ -0,0 +1,169 @@ +# Desktop 性能与架构演进 Spec + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-DKT-PERF-001` | +| **版本** | 2.0.0 | +| **关联** | [performance-roadmap-spec.md](./performance-roadmap-spec.md) · [desktop-spec.md](./desktop-spec.md) | + +--- + +## 1. 设计原则 + +| 原则 | 说明 | +| :--- | :--- | +| **先上线后原生** | 阶段 A 用 TS/Chromium 快速交付;阶段 B 按 ROI 引入 **Rust/原生** | +| **零帧 IPC** | 视频帧禁止 `ipcRenderer` 大块传输 | +| **Electron = 控制台** | UI、配对、WebRTC 控制面;重活下沉 **Agent Service** | +| **Rust 替换瓶颈** | 非全量重写;N-API 或独立进程 + 共享内存 | +| **Meta-Repo 隔离** | `desktop/native/` 独立构建,不与 RN hoist | + +--- + +## 2. 双轨路线图 + +### 2.1 阶段 A — 先上线(不依赖 Rust) + +| 代号 | 内容 | 状态 | +| :--- | :--- | :--- | +| A0 | `desktopCapturer` + MediaStream → WebRTC | 规划/骨架 | +| A1 | Chromium `--enable-nvenc` / `--enable-libvpl` | `encode/gpu-policy.ts` | +| A2 | 端侧录制 BufferZone + 分片上传 | `electron/recording/` | +| A3 | 独立 Agent Service 进程 + 控制协议 | `agent-service/` 占位 | +| A4 | iohook(TS 生态)键鼠 | `input/input-bridge.ts` | + +### 2.2 阶段 B — Rust / 原生(投入产出比排序) + +| 优先级 | ID | 主题 | 技术要点 | 依赖 | +| :---: | :--- | :--- | :--- | :--- | +| **1** | **R1** | **屏幕捕获原生化** | Rust:Win DXGI Desktop Duplication / macOS ScreenCaptureKit;帧入共享内存或硬件纹理 | A0 可并行测量 | +| **2** | **R2** | **硬件编码** | NVENC / QSV / VAAPI;Rust 绑定或加固 Chromium HW 路径 | R1 出帧格式 | +| **3** | **R3** | **Video + Overlay 架构** | 独立合成:光标、水印、隐私块、多屏拼接;GPU compositor | R1/R2 | +| **4** | **R4** | **键鼠 Hook 原生化** | Rust 低级 Hook;替代 iohook;仅会话注入 | A4 可先做 TS 版 | +| **5** | **R5** | **SharedArrayBuffer** | 环区/上传线程零拷贝视图;录制分片读 | R1–R2 稳定 | +| **6** | **R6** | **GPU 零拷贝** | 纹理 → 编码器 Opaque;D3D11/Metal 互操作 | R2/R3,**最后** | + +```text +收益/成本比: R1 ≈ R2 > R3 > R4 >> R5 ≈ R6(维护成本) +``` + +**立项门槛**:见 [performance-roadmap-spec.md](./performance-roadmap-spec.md) §6。 + +--- + +## 3. 目标架构(阶段 B 稳态) + +```text +┌──────────────────────────────────────────────────────────────────┐ +│ agent-native (Rust) — 可选独立二进制或 .node │ +│ R1 捕获 → R3 合成(Overlay) → R2 硬编 → 共享内存/句柄 │ +│ R4 键鼠 Hook │ +└────────────────────────────┬─────────────────────────────────────┘ + │ 无原始帧 JSON/IPC;仅句柄+元数据 +┌────────────────────────────▼─────────────────────────────────────┐ +│ Agent Service (Node) — 会话、上传调度、WebRTC 信令对接 │ +│ R5 SAB 环区(若仍需要 CPU 路径缓冲) │ +└────────────────────────────┬─────────────────────────────────────┘ +┌────────────────────────────▼─────────────────────────────────────┐ +│ Electron — 控制台 UI · 托盘 · 策略 │ +└──────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 4. 分模块说明 + +### 4.1 R1 屏幕捕获原生化 + +| FR | 需求 | +| :--- | :--- | +| FR-DKT-R1-01 | Win10+ DXGI;macOS 12+ ScreenCaptureKit | +| FR-DKT-R1-02 | 输出 NV12 或 GPU 纹理句柄,供 R2/R6 | +| FR-DKT-R1-03 | 热插拔显示器、DPI 变更事件 | +| FR-DKT-R1-04 | 回退:A0 MediaStream 仍可启用 | + +### 4.2 R2 硬件编码 + +| FR | 需求 | +| :--- | :--- | +| FR-DKT-R2-01 | 会话默认硬编;软编仅 `capability-monitor` 降级 | +| FR-DKT-R2-02 | 与 WebRTC 对接:Encoded Transform 或外环 RTP(设计评审) | + +### 4.3 R3 Video + Overlay + +| FR | 需求 | +| :--- | :--- | +| FR-DKT-R3-01 | 光标层、可选水印(Enterprise) | +| FR-DKT-R3-02 | 隐私遮罩区域(黑名单窗口) | +| FR-DKT-R3-03 | 多 `displayIndex` 合成(Enterprise 多屏) | + +### 4.4 R4 键鼠 Hook 原生化 + +| FR | 需求 | +| :--- | :--- | +| FR-DKT-R4-01 | 延迟 P95 < 30ms(LAN 对照) | +| FR-DKT-R4-02 | 仅 `session=connected` 且已授权时注入 | + +### 4.5 R5 SharedArrayBuffer + +| FR | 需求 | +| :--- | :--- | +| FR-DKT-R5-01 | 录制环区与上传线程共享;避免 Node Buffer 拷贝 | +| FR-DKT-R5-02 | 遵守跨域隔离;仅 Agent Service 进程内 | + +### 4.6 R6 GPU 零拷贝 + +| FR | 需求 | +| :--- | :--- | +| FR-DKT-R6-01 | R1→R2 纹理路径无 CPU readback | +| FR-DKT-R6-02 | 平台矩阵文档化(Win 优先) | + +--- + +## 5. 阶段 A 功能需求(保留) + +| ID | 方案 | +| :--- | :--- | +| FR-DKT-P0-01 | MediaStream → RTCPeerConnection | +| FR-DKT-P1-01 | NVENC/QSV Chromium 构建标志 | +| FR-DKT-P2-01 | iohook 过渡方案 | +| FR-DKT-P2-02 | 独立 Agent Service | + +--- + +## 6. 代码布局(规划) + +```text +desktop/ +├── electron/ # 阶段 A +├── native/ # 阶段 B:Rust workspace(占位) +│ ├── capture/ # R1 +│ ├── encode/ # R2 +│ ├── compositor/ # R3 +│ ├── input/ # R4 +│ └── Cargo.toml +└── agent-service/ +``` + +`desktop/native/README.md`:占位说明,**无对外承诺日期**。 + +--- + +## 7. 资源占用与守护 + +见 v1.0 §5(FR-DKT-PG-*),无变更。 + +--- + +## 8. 对外文档 + +**不在** `docs/` 用户向页面描述 R1–R6 或 Rust 排期。已交付能力仅写「低延迟」「硬件编码」等产品语言。 + +--- + +## 9. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 1.0.0 | 初版 | +| 2026-05-24 | 2.0.0 | 阶段 A/B;Desktop R1–R6 ROI;Rust 模块化 | diff --git a/spec/desktop-spec.md b/spec/desktop-spec.md new file mode 100644 index 0000000..e2d1a88 --- /dev/null +++ b/spec/desktop-spec.md @@ -0,0 +1,176 @@ +# Desktop 被控 Agent Spec + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-DKT-001` | +| **仓库** | `desktop/` | +| **技术栈** | Electron, React, **Rsbuild**, **Ant Design 5**, **Sass** | +| **版本** | 0.5.0-draft | +| **性能** | [desktop-performance-spec.md](./desktop-performance-spec.md) | +| **工具链** | [frontend-toolchain-spec.md](./frontend-toolchain-spec.md) | + +--- + +## 1. 职责 + +Desktop 仓库承担 **双重角色**(同一 codebase,不同启动模式或构建目标): + +| 角色 | 说明 | +| :--- | :--- | +| **Controlled Agent(被控)** | 屏幕采集、编码推流、接收 DataChannel 控制指令并注入 OS 输入 | +| **Controller Dashboard(可选)** | 本地完整主控 UI(与 web 能力对齐,适合 power user) | + +MVP 优先交付 **Agent**;Dashboard 与 `web/packages/ui` 对齐(P1)。 + +渲染进程 **必须** 使用 Rsbuild + antd + Sass,与 Web Client 共用 `frontend-toolchain-spec`。 + +--- + +## 2. 进程架构 + +> **性能演进(Normative)**:[desktop-performance-spec.md](./desktop-performance-spec.md) · [performance-roadmap-spec.md](./performance-roadmap-spec.md)(R1–R6 ROI,不对 docs 用户承诺)。 + +```text +┌─────────────────────────────────────────────────────────────┐ +│ Agent Service (P1+) — 采集·GPU 编码·iohook·edge-ai │ +│ 与 Electron:仅控制面消息,不传视频帧 │ +└────────────────────────────┬────────────────────────────────┘ + │ +┌────────────────────────────▼────────────────────────────────┐ +│ Electron Main — WebRTC·托盘·Watchdog(Managed) │ +│ P0: MediaStream → RTCPeerConnection(不经 IPC 传帧) │ +└────────────────────────────┬────────────────────────────────┘ + │ contextBridge(小消息) +┌────────────────────────────▼────────────────────────────────┐ +│ Renderer — 配对/授权/控制台 UI │ +└─────────────────────────────────────────────────────────────┘ +``` + +**安全**:`contextIsolation: true`,`nodeIntegration: false`(渲染进程)。 + +**仓库内导航**:`desktop/ARCHITECTURE.md`。 + +--- + +## 3. 目录结构(目标) + +```text +desktop/ +├── electron/ # 主进程(无 antd) +│ ├── main.ts +│ ├── preload.ts +│ ├── webrtc/ +│ ├── capture/ # MediaStream P0 +│ ├── local-agent/ # 服务控制协议 P1 +│ ├── encode/ # gpu-policy.ts +│ ├── input/ # iohook 桥 P1 +│ ├── watchdog/ # Managed 进程守护 P1 +│ ├── recording/ # 缓冲环区 + 分片上传 P0/P1 +│ └── edge-ai/ # 端侧多模型推理(见 ai-behavior-architecture-spec) +│ ├── inference-router.ts +│ ├── rules-engine.ts +│ ├── timeseries-features.ts +│ ├── cv-sampler.ts # ONNX P1 +│ └── capability-monitor.ts +├── src/ # Rsbuild 渲染进程 +│ ├── App.tsx +│ ├── pages/ +│ └── styles/ +│ ├── global.scss +│ └── *.module.scss +├── rsbuild.config.ts # extends 与 web 同构的 base(可复制或 git submodule theme) +├── resources/ +└── package.json +``` + +--- + +## 4. 屏幕采集 + +| ID | 需求 | 验收标准 | +| :--- | :--- | :--- | +| FR-DKT-01 | 枚举所有显示器,默认主屏 | UI 可切换 `displayIndex` | +| FR-DKT-02 | 使用 `desktopCapturer` + `getUserMedia` 或等价原生路径 | 1080p@30fps 可达(硬件允许) | +| FR-DKT-03 | 分辨率/帧率随网络降级(配合 WebRTC stats) | 带宽下降时自动降档 | +| FR-DKT-04 | 采集前须用户授权(系统权限 + 应用内确认) | macOS 屏幕录制权限流程文档化 | + +--- + +## 5. WebRTC(被控侧) + +| ID | 需求 | 验收标准 | +| :--- | :--- | :--- | +| FR-DKT-05 | 1:1 作为 **Offerer 或 Answerer**(由信令约定,默认 Agent 发 Offer) | 与 web 主控互通 | +| FR-DKT-06 | 创建 `control` DataChannel 或由主控创建后绑定 | 控制指令生效 | +| FR-DKT-07 | SFU 模式仅 **上行 Publish** 一路视频 + 数据(若 SFU 支持 DataChannel 中继则按 SFU 能力) | N>1 时 CPU 不随 N 线性涨 | +| FR-DKT-08 | ICE 配置从 Server 拉取 | 无硬编码 TURN | +| FR-DKT-08f | `electron/webrtc/publisher`:SFU 时仅 **单路 Publish** | 见 webrtc-architecture-spec | +| FR-DKT-08g | 发送端 `degradationPreference: maintain-framerate` | `rtc-tuning.ts` | +| FR-DKT-08b | Pro+:**端侧**录制 → 本地缓冲环区 → 定时分片上传 S3(**非 SFU 录制**) | 见 recording-playback-spec | +| FR-DKT-08b2 | `electron/recording/`:BufferZone + UploadScheduler + RecordingSession | 权益门 `recording` | +| FR-DKT-08c | Enterprise:端侧 **edge-ai** 实时检测 + `telemetry` 上报结构化结果 | 不含键入内容;隐私敏感仅端侧 | +| FR-DKT-08e | 低配机:`capability-monitor` 检测 CPU 压力,自动请求云端补算 | 不阻塞办公 | +| FR-DKT-08d | Enterprise:多显示器枚举与并行采集/上传 | 最多 4 屏 | + +--- + +## 6. 输入注入 + +| ID | 需求 | 验收标准 | +| :--- | :--- | :--- | +| FR-DKT-09 | 解析 `ControlEnvelope`,映射归一化坐标到像素 | 误差见 system-overview FR-CTL-01 | +| FR-DKT-10 | 支持左/右/中键与滚轮 | 人工测试清单 | +| FR-DKT-11 | 键盘映射使用 OS 虚拟键码或 cross-platform 库 | 英文字母与数字 | +| FR-DKT-12 | **安全**:仅当 Session 为 `connected` 且用户已授权时注入 | 断开后立即停止 | + +--- + +## 7. 配对与上线 + +> 接入方式与三包体:[agent-distribution-spec.md](./agent-distribution-spec.md) + +| ID | 需求 | 验收标准 | +| :--- | :--- | :--- | +| FR-DKT-13 | 首次启动生成/绑定 `deviceId`,向 Server 注册(含 `installChannel`) | 重启后 ID 持久化 | +| FR-DKT-14 | UI 同步展示 **数字码 + 二维码 + 会话链接** | 主控三路径均可 join | +| FR-DKT-15 | 托盘菜单:断开所有会话、退出、开机自启(P1) | | +| FR-DKT-16 | `install-profile` 读取构建时常量,运行时不可改 channel | 三包 CI artifact 可区分 | +| FR-DKT-17 | BYOD:enrollment + `consentAt` 后才 `enrolled_auto` | 审计可查 | +| FR-DKT-18 | Managed:`managed_silent` + 首次法律告知页 | FR-DIST-12 | + +--- + +## 8. 非功能需求 + +| ID | 需求 | 目标 | +| :--- | :--- | :--- | +| NFR-DKT-01 | 空闲 CPU | < 5%(无会话) | +| NFR-DKT-02 | 支持平台 | Windows 10+, macOS 12+(MVP);Linux P2 | +| NFR-DKT-03 | 安装包 | electron-builder;代码签名 P1 | + +--- + +## 9. 原生依赖注意(Meta-Repo 原因) + +- `node-gyp` 原生模块 **锁定在 desktop 仓库独立 `node_modules`**,禁止与 RN 共享 hoist。 +- CI 分平台矩阵构建(win/mac)。 + +--- + +## 10. Out of Scope + +- 无告知、无企业授权的隐蔽投屏 +- Consumer 包 **静默安装**(须用户主动安装) +- Managed 包允许 IT 预装,但 **必须** 首次告知 + 企业合同(见 agent-distribution-spec) + +--- + +## 11. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 0.1.0-draft | 初稿 | +| 2026-05-24 | 0.2.0-draft | Rsbuild + antd + Sass | +| 2026-05-24 | 0.3.0-draft | 录制上传、telemetry、多屏 | +| 2026-05-24 | 0.4.0-draft | 端侧多模型 edge-ai;降云策略 | +| 2026-05-24 | 0.5.0-draft | 性能 Spec;本地服务架构;capture/local-agent 骨架 | diff --git a/spec/developer-experience-spec.md b/spec/developer-experience-spec.md new file mode 100644 index 0000000..8092c06 --- /dev/null +++ b/spec/developer-experience-spec.md @@ -0,0 +1,85 @@ +# 开发者体验 Spec(本地环境 · 多环境 · 单仓开发) + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-DX-001` | +| **版本** | 1.0.0 | +| **关联** | [meta-repo-development-spec.md](./meta-repo-development-spec.md) | + +--- + +## 1. 新成员一键上手(Meta-Repo) + +| 步骤 | 命令 | +| :--- | :--- | +| 1. 克隆 Meta-Repo | `git clone …/vista-remote.git && cd vista-remote` | +| 2. 拉子仓库 | `./init.sh` 或 `.\init.ps1` | +| 3. Node | `nvm use`(≥ 22.12) | +| 4. **一键搭建** | `./dev.sh` 或 `.\dev.ps1` | +| 5. 开工作区 | `vista-remote.code-workspace` | + +`dev-up` 自动:切换 **local** 环境变量 → Docker(MySQL/Redis/Ollama)→ `pnpm install` 各仓 → `shared` build。 + +--- + +## 2. 多环境切换(Local / Dev / SIT / UAT) + +SSOT:`config/environments/{local,dev,sit,uat}.env` + +| 命令 | 写入各端 `.env` | +| :--- | :--- | +| `pnpm env:local` | localhost | +| `pnpm env:dev` | 远程 Dev API(改域名) | +| `pnpm env:sit` | SIT | +| `pnpm env:uat` | UAT | + +**生效方式**:切换后 **重启** 正在运行的 `pnpm dev` / `pnpm start`(Rsbuild/Electron/Metro 在启动时读 env)。 + +当前 profile 记录在根目录 `.vista-env`。 + +| 子仓库 | 生成文件 | +| :--- | :--- | +| server | `.env` | +| ai | `.env` | +| web client/admin | `.env` | +| desktop | `.env` | +| mobile | `.env` | + +--- + +## 3. 只克隆单个子仓库(如 desktop / mobile) + +开发者 **只拉自己仓库** 时,在仓库内执行: + +```bash +pnpm setup +# 或 +node scripts/setup-dev.mjs +``` + +行为: + +1. 若上层存在 Meta-Repo → 调用 `setup-single-repo.mjs` +2. 否则 **自动 `git clone` `../shared`** 并 `pnpm install` + build shared +3. 应用 `local` 环境(若在 Meta 内) + +`package.json` 保持 `"@vistaremote/shared": "file:../shared"`。 + +--- + +## 4. 功能需求 + +| ID | 需求 | 验收 | +| :--- | :--- | :--- | +| FR-DX-01 | `dev-up` 10 分钟内完成首次 local 依赖安装 | 文档步骤 | +| FR-DX-02 | `env:*` 写入全部客户端 env 文件 | apply-env 日志 | +| FR-DX-03 | desktop/mobile `pnpm setup` 无 Meta 时可 clone shared | | +| FR-DX-04 | 切换 env 不需改业务代码 | 仅重启 | + +--- + +## 5. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 1.0.0 | dev-up、apply-env、单仓 setup、四环境 profile | diff --git a/spec/docs-spec.md b/spec/docs-spec.md new file mode 100644 index 0000000..cb7bfb2 --- /dev/null +++ b/spec/docs-spec.md @@ -0,0 +1,112 @@ +# Docs 文档站 Spec + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-DOC-001` | +| **仓库** | `docs/` | +| **技术栈** | Rspress, MDX, TypeScript | +| **版本** | 0.3.0 | + +--- + +## 1. 职责 + +VistaRemote **对外技术文档引擎**:架构说明、API 参考、部署指南、贡献者文档;与 Meta-Repo 中 `spec/` **互补**——`spec/` 面向实现与 AI,`docs/` 面向人与社区。 + +| 内容类型 | 位置 | +| :--- | :--- | +| 规格与合规边界 | Meta-Repo `spec/`(源) | +| 教程、部署、API 详情 | `docs/` 仓库 | +| 白皮书 | Meta-Repo `docs/whitepaper.md`(同步至 Rspress) | + +--- + +## 2. 信息架构(目标) + +```text +docs/ +├── docs/ +│ ├── index.mdx +│ ├── guide/ +│ │ ├── quick-start.mdx +│ │ ├── developer-handbook.mdx +│ │ ├── spec-driven-development.mdx +│ │ ├── feature-development.mdx +│ │ ├── pairing.mdx +│ │ └── admin-getting-started.mdx +│ ├── user/ # 终端用户(非开发) +│ │ ├── remote-control.mdx +│ │ ├── plans-and-billing.mdx +│ │ ├── admin-console.mdx +│ │ └── faq.mdx +│ ├── architecture/ +│ │ ├── positioning.mdx +│ │ ├── desktop-performance.mdx +│ │ ├── overview.mdx +│ │ ├── webrtc-topology.mdx +│ │ ├── meta-repo.mdx +│ │ └── positioning.mdx # 源自 positioning-and-advantages.md +│ ├── engineering/ +│ │ ├── implementation-status.mdx +│ │ └── git-workflow.mdx +│ ├── api/ +│ │ └── server-rest.mdx +│ ├── deploy/ +│ │ └── docker.mdx +│ └── whitepaper/ +│ └── index.mdx # 从 whitepaper.md 同步或引用 +├── rspress.config.ts +└── package.json +``` + +--- + +## 3. 功能需求 + +| ID | 需求 | 验收标准 | +| :--- | :--- | :--- | +| FR-DOC-01 | 中英双语导航(至少首页与快速开始) | `zh` / `en` locale | +| FR-DOC-02 | 代码块支持 TS/Bash/JSON 高亮 | | +| FR-DOC-03 | 搜索(Rspress 内置) | 可搜到 WebRTC、配对 | +| FR-DOC-04 | 每个公共 REST/WS 消息链接到 shared 类型说明 | 无重复定义字段 | +| FR-DOC-05 | CI 构建静态站并部署(GitHub Pages / 自有 CDN) | PR 预览 | +| FR-DOC-06 | 不写内部性能路线图(Rust/R1–R6) | 工程细节在 `spec/` | + +--- + +## 4. 与 Spec 同步规则 + +1. **API 变更**:先改 `shared` + `server-spec`,再改 `docs/api/*`。 +2. **架构变更**:先改 `system-overview.md`,再摘抄至 `docs/architecture/*`。 +3. 白皮书重大版本发布时,更新 `docs/whitepaper/index.mdx` 的「版本」页眉。 +4. **性能/Rust 路线图**:仅维护于 Meta-Repo `spec/performance-roadmap-spec.md`;**禁止**在 `docs/` 用户向页面写 R1–R6、Rust 排期或未交付承诺(FR-DOC-06)。 + +--- + +## 5. 非功能需求 + +| ID | 需求 | 目标 | +| :--- | :--- | :--- | +| NFR-DOC-01 | 生产构建 | Rspack 冷构建 < 90s | +| NFR-DOC-02 | Lighthouse 可访问性 | ≥ 90 | + +--- + +## 6. Out of Scope + +- 自动从 OpenAPI 生成(P1 可选) +- 视频课程托管 + +--- + +## 7. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 0.1.0-draft | 初稿 | +| 2026-05-24 | 0.2.0-draft | 管理端入门文档 IA | +| 2026-05-24 | 0.3.0 | Rspress 2 站点落地;zh/en;CI build | +| 2026-05-24 | 0.3.1 | 工程规范文档:Biome、Git/PR、contributing-workflow | +| 2026-05-24 | 0.4.0 | user/* 用户指南;guide 开发者手册与 SDD;implementation-status | +| 2026-05-24 | 0.5.0 | positioning 二开/选型;desktop-performance;customization | +| 2026-05-24 | 0.5.1 | **性能路线图仅 spec/**;docs 不写 Rust/R1–R6 排期 | diff --git a/spec/engineering-standards-spec.md b/spec/engineering-standards-spec.md new file mode 100644 index 0000000..20e15a2 --- /dev/null +++ b/spec/engineering-standards-spec.md @@ -0,0 +1,141 @@ +# 工程规范 Spec(L1) + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-ENG-001` | +| **版本** | 1.0.0 | +| **关联** | [git-collaboration-spec.md](./git-collaboration-spec.md) · [cicd-release-spec.md](./cicd-release-spec.md) · [CONTRIBUTING.md](../CONTRIBUTING.md) | + +--- + +## 1. 目标 + +为 **多人协作的开源项目** 统一:代码风格、静态检查、编辑器行为、Git/PR 流程、CI 门禁与 AI 协作边界。 + +--- + +## 2. 代码格式与静态检查:Biome + +| ID | 规则 | 验收 | +| :--- | :--- | :--- | +| FR-ENG-01 | 全栈 TypeScript/JavaScript **统一使用 Biome** 格式化与 Lint | 不引入 ESLint+Prettier 双栈 | +| FR-ENG-02 | 基线 `tooling/biome.json` + 端预设 server/web/mobile/desktop | 见 [meta-repo-development-spec](./meta-repo-development-spec.md) | +| FR-ENG-03 | **每个** TS 子仓库根目录 `biome.json` extends 对应预设 | 在**该仓库内** CI `pnpm lint` | +| FR-ENG-02b | Meta-Repo 根 `biome.json` **仅**脚手架,不替代子仓检查 | | +| FR-ENG-04 | 提交前在改动仓库执行 `pnpm lint` 或 `biome check .` | | +| FR-ENG-05 | MD 文档可用 `pnpm format:docs` 格式化(Meta-Repo);MDX 在 `docs/` 仓库 | | + +### 2.1 与 EditorConfig 对齐 + +- `.editorconfig`:UTF-8、LF、2 空格、final newline。 +- IDE 保存时格式化:**Biome** 为默认 formatter(见工作区 `vista-remote.code-workspace`)。 + +--- + +## 3. Git 与提交 + +详见 [git-collaboration-spec.md](./git-collaboration-spec.md)(扩展版)。 + +| 实践 | 说明 | +| :--- | :--- | +| **Conventional Commits** | `type(scope): subject` | +| **Commitlint** | `tooling/commitlint.config.cjs` + Husky `commit-msg` | +| **分支** | `feat/*`、`fix/*`;跨库同名分支 | +| **主分支** | `main` 受保护,仅 PR 合并 | +| **开发分支** | `dev` 集成分支(可选) | +| **Signed commits** | 推荐 GPG/SSH sign(维护者必须) | +| **禁止** | force push `main`、跳过 hook(除非维护者明示) | + +### 3.1 Type 枚举 + +`feat` `fix` `docs` `style` `refactor` `perf` `test` `build` `ci` `chore` `revert` + +--- + +## 4. Pull Request 流程 + +| 步骤 | 要求 | +| :--- | :--- | +| 1 | 从最新 `main`/`dev` 拉分支 | +| 2 | 小步提交,信息符合 Commitlint | +| 3 | PR 使用模板,说明动机、测试、Spec 影响 | +| 4 | CI 绿(lint、build、test) | +| 5 | 至少 **1** 名 Reviewer approve(核心仓库建议 2) | +| 6 | Squash merge 或 rebase merge(团队统一一种) | +| 7 | 涉及 `shared` 的 PR 必须先合并并发布/打 tag,再合消费者 | + +### 4.1 PR 检查清单(Reviewer) + +- [] 符合 Spec / 已更新 Spec +- [] `shared` 优先顺序正确 +- [] Biome check 通过 +- [] 无密钥、`.env` 进库 +- [] 套餐/权限边界(若适用) +- [] 文档与 CHANGELOG(若用户可见) + +--- + +## 5. 编辑器与 Cursor + +| 项 | 位置 | +| :--- | :--- | +| 工作区设置 | `vista-remote.code-workspace` | +| Cursor Rules | `.cursor/rules/*.mdc` | +| AI 说明 | `AGENTS.md` | +| 推荐扩展 | `.vscode/extensions.json` | + +--- + +## 6. 业界补充实践(采纳清单) + +| 实践 | VistaRemote 落地 | +| :--- | :--- | +| **EditorConfig** | `.editorconfig`(各子仓库同步一份) | +| **Cursor Rules** | 各子仓库 `.cursor/rules/`(`tooling/cursor/` + `setup-ide-config.mjs`) | +| **VS Code** | 各子仓库 `.vscode/settings.json`(Biome format on save) | +| **AGENTS.md** | 各子仓库根目录(AI 协作) | +| **Node 版本锁定** | **≥ 22**(`engines`);`.nvmrc` 固定 **22.12 LTS**;CI 使用 `node-version: 22.12` | +| **依赖锁定** | pnpm `pnpm-lock.yaml` 进库 | +| **Git 属性** | `.gitattributes`(LF、linguist) | +| **PR/Issue 模板** | `.github/PULL_REQUEST_TEMPLATE.md`、ISSUE_TEMPLATE | +| **CODE_OF_CONDUCT** | `CODE_OF_CONDUCT.md` | +| **SECURITY** | `SECURITY.md` | +| **Dependabot** | `.github/dependabot.yml` | +| **CODEOWNERS** | `.github/CODEOWNERS`(可选路径) | +| **CI** | 各仓库:lint + **Rstest** + build;**pnpm audit**、**CodeQL**、PR **Dependency Review** | +| **Git Hooks** | 各子仓 Husky:`pre-commit` = staged Biome + 单测;`commit-msg` = commitlint | +| **单元测试** | [**Rstest**](https://rstest.rs/)(`@rstest/core`);Rsbuild/Rslib 项目用对应 adapter | +| **E2E** | `web`:Playwright(`apps/client`) | +| **性能** | `server`:[k6](https://k6.io/)(`perf/k6/`,CI `perf.yml`) | +| **Changesets** | 多包发布时可选(P1) | +| **License** | 各子仓库 LICENSE 文件 | +| **Secrets** | 仅 CI/部署注入,`.env.example` 无真实密钥 | + +### 6.1 明确不采用(避免过度工程) + +- 双格式化器(Prettier + Biome 并存) +- Meta-Repo 单一 husky 管理所有子仓库 git(各仓独立 hook) +- 强制 monorepo 工具(已选 Multi-Repo) + +--- + +## 7. 子仓库 CI 最低要求(模板) + +```yaml +# .github/workflows/ci.yml(模板见 tooling/github/workflows/ci-node.yml) +jobs: + quality: # lint → test → build + security-audit: + codeql: # 可选 +# PR: dependency-review.yml +# server: perf.yml (k6) +# web: e2e.yml (Playwright) +``` + +--- + +## 8. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 1.0.0 | Biome、EditorConfig、Commitlint、Cursor Rules、PR/开源惯例 | diff --git a/spec/enterprise-security-spec.md b/spec/enterprise-security-spec.md new file mode 100644 index 0000000..f573453 --- /dev/null +++ b/spec/enterprise-security-spec.md @@ -0,0 +1,140 @@ +# 企业安全监控 Spec(L1) + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-ENT-SEC-001` | +| **版本** | 0.3.0-draft | +| **套餐** | **Enterprise** | +| **关联** | [ai-platform-spec](./ai-platform-spec.md) · [recording-playback-spec](./recording-playback-spec.md) · [authorization-spec](./authorization-spec.md) | + +--- + +## 1. 目标 + +为企业客户提供 **可审计、可回放、可告警** 的安全与效率洞察能力,包括: + +1. 基于 **关键词** 与 **窗口标题** 的自动录制策略 +2. **多屏同步监控** +3. **敏感文件外发**、**大量删除** 等行为识别 +4. **屏幕录像回放** 与安全事件时间轴对齐 +5. **AI** 学习正常操作模式并标记异常(如长时间非工作网站) +6. **效率报告**:高效 / 低效时段统计 + +--- + +## 2. 遥测通道(Agent → Server) + +在 WebRTC `DataChannel control` 之外,增加 **`telemetry` 通道**(或独立 HTTPS 批量上报): + +| 事件类型 | 字段 | 频率 | +| :--- | :--- | :--- | +| `window.focus` | `title`, `processName`, `displayIndex`, `ts` | 前台变化时 | +| `file.exfiltration_risk` | `action`, `path`, `destinationHint`, `ts` | 检测时 | +| `file.bulk_delete` | `count`, `pathsSample`, `ts` | 超阈值时 | +| `display.topology` | `displays[]` | 会话开始 + 热插拔 | + +类型定义:`shared/src/telemetry/`。 + +| ID | 需求 | 验收 | +| :--- | :--- | :--- | +| FR-ENT-01 | Enterprise 组织可配置策略 JSON 下发到 Agent | 60s 内生效 | +| FR-ENT-02 | 遥测不含键盘具体内容(默认),仅窗口标题与文件元数据 | 隐私评审 | + +--- + +## 3. 策略配置(Organization Policy) + +```typescript +interface EnterprisePolicy { + recording: { + keywords: string[]; // 窗口标题包含即触发 + windowTitleRegex?: string[]; + multiDisplay: boolean; + preRollSec: number; // 触发前环形缓冲 + }; + security: { + blocklistedProcesses?: string[]; + exfiltrationPatterns: string[]; // 路径/扩展名启发式 + bulkDeleteThreshold: number; // 如 50 文件/5min + }; + ai: { + nonWorkDomains: string[]; + anomalySensitivity: 'low' | 'medium' | 'high'; + weeklyReportEnabled: boolean; + }; +} +``` + +存储:`organization.policy` JSON(MySQL),Admin 可视化编辑。 + +**谁可改策略**:`org_owner` / `org_admin`(Client 或 Admin 代管);`it_support` 只读策略;`security_auditor` 可读策略与事件,不可改。见 [authorization-spec.md](./authorization-spec.md) 组织 RBAC 与 ABAC。 + +--- + +## 4. 安全检测(端侧多模型 + 云端 LLM/ML) + +执行位置见 [ai-behavior-architecture-spec.md](./ai-behavior-architecture-spec.md)。 + +| 场景 | 端侧(默认) | 云端(高端/降云) | +| :--- | :--- | :--- | +| 敏感文件外发 | 规则 + 路径启发式 | 规则复核 + 告警关联 | +| 大量删除 | 计数阈值 | 基线偏离 | +| 非工作网站 | 小模型/域名规则 + 时序 | 基线 + LLM 解释 | +| 异常行为 | 滑动窗口统计 | 3σ 基线(ai Job)+ LLM 周报 | + +| ID | 需求 | 验收 | +| :--- | :--- | :--- | +| FR-ENT-10 | 触发安全事件后自动关联最近录制并置顶 Admin | | +| FR-ENT-11 | 事件 severity:`low`/`medium`/`high`/`critical` | | +| FR-ENT-12 | 支持 Webhook 推送企业 SIEM(P2) | | + +--- + +## 5. 多屏同步监控 + +```text +Admin 会话页 +├── 主控预览(可选) +└── Agent 多屏网格(display 0..N 缩略流) +``` + +| ID | 需求 | 验收 | +| :--- | :--- | :--- | +| FR-ENT-20 | ≤4 屏同时预览 @720p15(可配置) | **mediasoup SFU** 订阅(禁止 N 路 P2P 压满 TURN) | +| FR-ENT-21 | 每屏独立录制轨,回放可切换 | | + +--- + +## 6. 效率报告(Enterprise) + +| 指标 | 计算方式 | +| :--- | :--- | +| 高效时长 | 前台窗口 ∈ 工作类域名/应用 | +| 低效时长 | 非工作域名连续 > 阈值 | +| 空闲 | 无输入 + 无前台变化 | + +输出:`EfficiencyReport`(JSON + Admin 图表 + 可选 LLM 周报 PDF)。 + +| ID | 需求 | 验收 | +| :--- | :--- | :--- | +| FR-ENT-30 | 周报每周一 08:00 组织时区生成 | `ai` cron | +| FR-ENT-31 | Admin 可按部门/用户筛选 | | + +--- + +## 7. Admin 功能映射 + +| 菜单 | 功能 | +| :--- | :--- | +| 安全事件 | incident 列表、筛选、跳转回放 | +| 录制中心 | 策略触发录制、手动录制 | +| AI 洞察 | 异常时间线、效率报告 | +| 组织策略 | 关键词、域名、阈值配置 | + +--- + +## 8. RFC / Changelog + +| 日期 | 版本 | 变更 | +| :--- | :--- | :--- | +| 2026-05-24 | 0.3.0-draft | 企业安全与效率 Spec | diff --git a/spec/frontend-toolchain-spec.md b/spec/frontend-toolchain-spec.md new file mode 100644 index 0000000..db729de --- /dev/null +++ b/spec/frontend-toolchain-spec.md @@ -0,0 +1,123 @@ +# 前端工具链与 UI 规范(L1) + +| Metadata | Value | +| :--- | :--- | +| **文档 ID** | `SPEC-FE-TOOLCHAIN-001` | +| **版本** | 0.2.0-draft | +| **状态** | Draft | +| **适用范围** | `web/` · `desktop/` 渲染进程 · `docs/` | + +--- + +## 1. 原则 + +VistaRemote **大前端生态统一采用 Rspack 系工具链**(Rsbuild / Rspress),禁止在新子项目中引入 Vite、Webpack 独立配置或 Create React App,除非经 RFC 批准。 + +| 场景 | 工具 | 说明 | +| :--- | :--- | :--- | +| Web 应用(用户端 / 管理端) | **Rsbuild** | `@rsbuild/core`,底层 Rspack | +| Electron 渲染进程 | **Rsbuild** | 与 Web 共享 `rsbuild.config.base.ts` | +| 文档站 | **Rspress** | Rspack 生态,与 Web 一致 | +| React Native | **Metro** | RN 官方打包器;**不得**强行 Rspack 打包 RN 运行时 | +| 共享样式 Token | **Sass 变量包** | 可放在 `web/packages/theme`,供 RN 通过构建脚本同步 CSS 变量(P1) | + +--- + +## 2. UI 组件库:Ant Design + +| 端 | 库 | 版本约束 | +| :--- | :--- | :--- | +| Web Client / Admin | `antd` | ^5.x | +| Desktop Renderer | `antd` | 与 Web 同 major | +| Mobile | `@ant-design/react-native` 或 `antd-mobile` | 与 Ant 设计语言一致;**不使用** Web 版 `antd` | + +### 2.1 强制约定 + +| ID | 需求 | 验收 | +| :--- | :--- | :--- | +| FR-UI-01 | 使用 Ant Design **ConfigProvider** 统一主题与 locale | `zh-CN` / `en-US` 可切换 | +| FR-UI-02 | 禁止引入第二套完整组件库(MUI、Chakra 等) | Code Review | +| FR-UI-03 | 远程桌面画布区域可为原生 `