{
  "schemaVersion": "1.0",
  "generatedAt": "2026-11-04T03:38:58.322Z",
  "baseUrl": "https://world.yuanxuntech.com",
  "project": {
    "name": "ai-knowledge-universe",
    "displayName": "AI 知识宇宙（K-World）",
    "version": "0.1.0",
    "description": "K-World: turn documents into explorable knowledge universes.",
    "runtime": "Node.js >= 20, browser SPA, file-backed JSON persistence",
    "packageManager": "npm",
    "publicHome": "https://world.yuanxuntech.com/"
  },
  "entrypoints": {
    "home": "https://world.yuanxuntech.com/",
    "manifest": "https://world.yuanxuntech.com/api/ai/manifest",
    "openapi": "https://world.yuanxuntech.com/api/ai/openapi.json",
    "wellKnownManifest": "https://world.yuanxuntech.com/.well-known/ai-project.json",
    "llmsText": "https://world.yuanxuntech.com/llms.txt"
  },
  "access": {
    "authentication": "login-required-account-or-editor",
    "publicRead": false,
    "loginRequired": true,
    "publicWrite": false,
    "editorEnabled": true,
    "writeProtection": "New universes, research projects and write routes require an account or editor session; private universes are isolated by owner and membership role.",
    "warning": "本站已开启登录门禁：除 /api/health、账号登录注册、编辑模式登录、Stripe 回调和机器可读入口外，所有内容接口在未登录时返回 401 LOGIN_REQUIRED。"
  },
  "safety": {
    "secretsExcluded": true,
    "excludedPaths": [
      ".env",
      ".env.local",
      "node_modules",
      "data/generated",
      "server runtime logs"
    ],
    "readOnlyCrawlerDefault": true,
    "destructiveRoutesRequireExplicitOptIn": true,
    "expensiveRoutesRequireExplicitOptIn": true,
    "supportedAuditModes": {
      "liveReadOnly": "npm run audit:ai -- --base-url <url>",
      "isolatedWriteTests": "在临时数据目录启动服务后再执行写入或删除测试。",
      "sourceReview": "在项目工作区直接读取 sourceMap 中列出的文件。"
    }
  },
  "counts": {
    "apiRoutes": 85,
    "readOnlyRoutes": 44,
    "mutatingRoutes": 41,
    "uiViews": 17,
    "uiFlows": 21,
    "sourceFiles": 36
  },
  "auditChecklist": [
    "核对每个 API 的状态码、错误信息、输入边界和超时行为。",
    "检查 URL 抓取的 SSRF、重定向、DNS、IP 和响应体限制。",
    "检查文档解析的大小、编码、超时、内存和恶意输入处理。",
    "检查持久化、并发构建、删除中构建、重启恢复和文件残留。",
    "检查前端 XSS、注入、事件重复绑定、状态竞争和错误恢复。",
    "检查移动端、键盘、空数据、加载、失败和无障碍状态。",
    "检查模型调用成本、提示注入、输出格式校验和敏感信息泄露。",
    "检查公开写入模式下的资源耗尽、滥用和缺乏速率限制问题。"
  ],
  "api": [
    {
      "id": "getHealth",
      "method": "GET",
      "path": "/api/health",
      "summary": "读取服务健康状态、运行时间和模型公开配置。",
      "tags": [
        "system"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "always",
      "responses": {
        "200": {
          "description": "服务可用。",
          "schema": "Health"
        }
      }
    },
    {
      "id": "getModelStatus",
      "method": "GET",
      "path": "/api/model/status",
      "summary": "检查模型提供方、模式和缺少的配置项，不返回 API Key。",
      "tags": [
        "system",
        "model"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "always",
      "responses": {
        "200": {
          "description": "模型公开状态。",
          "schema": "ModelStatus"
        }
      }
    },
    {
      "id": "getEditorSession",
      "method": "GET",
      "path": "/api/editor/session",
      "summary": "检查写操作是否启用以及当前浏览器是否拥有编辑会话。",
      "tags": [
        "security"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "always",
      "responses": {
        "200": {
          "description": "编辑模式状态。"
        }
      }
    },
    {
      "id": "getAccountSession",
      "method": "GET",
      "path": "/api/accounts/session",
      "summary": "读取当前账号、套餐、额度和注册开关。",
      "tags": [
        "accounts"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "always",
      "responses": {
        "200": {
          "description": "账号会话与套餐信息。"
        }
      }
    },
    {
      "id": "registerAccount",
      "method": "POST",
      "path": "/api/accounts/register",
      "summary": "注册商业账号并创建免费套餐会话。",
      "tags": [
        "accounts"
      ],
      "risk": "auth",
      "cost": "none",
      "mutation": true,
      "requiresEditor": false,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "name": "研究用户",
        "email": "user@example.com",
        "password": "strong-password"
      },
      "responses": {
        "201": {
          "description": "账号已创建。公开注册只接受邮箱，提交的 username 会被忽略。"
        },
        "403": {
          "description": "注册已关闭（REGISTRATION_CLOSED）。"
        },
        "409": {
          "description": "邮箱已注册。"
        }
      }
    },
    {
      "id": "loginAccount",
      "method": "POST",
      "path": "/api/accounts/login",
      "summary": "登录账号并创建 30 天 HttpOnly 会话。identifier 可填邮箱或用户名，username 字段仅作兼容。",
      "tags": [
        "accounts"
      ],
      "risk": "auth",
      "cost": "none",
      "mutation": false,
      "requiresEditor": false,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "identifier": "user@example.com 或 admin",
        "password": "strong-password"
      },
      "responses": {
        "200": {
          "description": "登录成功。"
        },
        "401": {
          "description": "凭据错误。"
        },
        "403": {
          "description": "账号已被停用（ACCOUNT_DISABLED）。"
        }
      }
    },
    {
      "id": "changeOwnPassword",
      "method": "POST",
      "path": "/api/accounts/password",
      "summary": "修改自己的密码：必须提供当前密码，成功后吊销该账号的其它会话，保留当前会话。",
      "tags": [
        "accounts",
        "security"
      ],
      "risk": "auth",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "currentPassword": "old-password",
        "newPassword": "new-password"
      },
      "responses": {
        "200": {
          "description": "密码已更新，返回 revokedSessions 数量。"
        },
        "400": {
          "description": "新密码过短、过长或与当前密码相同。"
        },
        "401": {
          "description": "未登录，或当前密码不正确。"
        },
        "429": {
          "description": "尝试次数过多。"
        }
      }
    },
    {
      "id": "getAccountProfile",
      "method": "GET",
      "path": "/api/accounts/me",
      "summary": "读取当前账号、套餐和本月用量。",
      "tags": [
        "accounts"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "opt-in",
      "responses": {
        "200": {
          "description": "账号资料。"
        },
        "401": {
          "description": "需要登录。"
        }
      }
    },
    {
      "id": "updateAccountProfile",
      "method": "PATCH",
      "path": "/api/accounts/me",
      "summary": "更新账号显示名称。修改密码请用 POST /api/accounts/password（必须提供当前密码）。",
      "tags": [
        "accounts"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "name": "新的名称"
      },
      "responses": {
        "200": {
          "description": "账号已更新。"
        }
      }
    },
    {
      "id": "listAuditEvents",
      "method": "GET",
      "path": "/api/audit/events",
      "summary": "读取当前账号自己的操作审计记录。",
      "tags": [
        "accounts",
        "audit"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "opt-in",
      "responses": {
        "200": {
          "description": "审计事件列表。"
        },
        "401": {
          "description": "需要登录。"
        }
      }
    },
    {
      "id": "adminSession",
      "method": "GET",
      "path": "/api/admin/session",
      "summary": "查询当前访问者是否具备后台管理权限，以及权限来自编辑模式还是账号角色。",
      "tags": [
        "admin"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "always",
      "responses": {
        "200": {
          "description": "isAdmin、operator、source 和 editorEnabled。"
        }
      }
    },
    {
      "id": "adminOverview",
      "method": "GET",
      "path": "/api/admin/overview",
      "summary": "后台总览：账号统计、套餐目录、知识宇宙总数和任务队列状态。",
      "tags": [
        "admin"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresAdmin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "responses": {
        "200": {
          "description": "账号统计与套餐目录。"
        },
        "403": {
          "description": "需要管理员权限。"
        }
      }
    },
    {
      "id": "adminListUsers",
      "method": "GET",
      "path": "/api/admin/users",
      "summary": "后台用户列表：支持按名称、邮箱、套餐或角色搜索，并返回用量、积分和额度。",
      "tags": [
        "admin",
        "accounts"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresAdmin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "q",
          "in": "query",
          "required": false,
          "description": "搜索关键词。",
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "limit",
          "in": "query",
          "required": false,
          "description": "返回条数上限。",
          "schema": {
            "type": "integer"
          }
        },
        {
          "name": "offset",
          "in": "query",
          "required": false,
          "description": "分页偏移。",
          "schema": {
            "type": "integer"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "账号列表与目录统计。"
        },
        "403": {
          "description": "需要管理员权限。"
        }
      }
    },
    {
      "id": "adminCreateUser",
      "method": "POST",
      "path": "/api/admin/users",
      "summary": "后台新建用户，可直接指定角色、套餐、状态、初始积分和单独的额度覆盖。",
      "tags": [
        "admin",
        "accounts"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresAdmin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "name": "张三",
        "email": "zhangsan@example.com",
        "username": "zhangsan",
        "password": "strong-password",
        "role": "user",
        "plan": "pro",
        "credits": 500,
        "limitsOverride": {
          "monthlyAiRequests": 20
        }
      },
      "responses": {
        "201": {
          "description": "账号已创建。"
        },
        "403": {
          "description": "需要管理员权限。"
        },
        "409": {
          "description": "邮箱已被占用。"
        }
      }
    },
    {
      "id": "adminUpdateUser",
      "method": "PATCH",
      "path": "/api/admin/users/{userId}",
      "summary": "后台修改用户：名称、用户名、邮箱、密码、角色、套餐、启用状态和额度覆盖。用户名留空即清除；停用会立即注销其会话。",
      "tags": [
        "admin",
        "accounts"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresAdmin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "userId",
          "in": "path",
          "required": true,
          "description": "账号 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "role": "admin",
        "plan": "team",
        "status": "active",
        "limitsOverride": {
          "monthlyAiRequests": "unlimited"
        }
      },
      "responses": {
        "200": {
          "description": "账号已更新。"
        },
        "403": {
          "description": "需要管理员权限。"
        },
        "409": {
          "description": "邮箱冲突，或触发了最后一个管理员的保护规则。"
        }
      }
    },
    {
      "id": "adminDeleteUser",
      "method": "DELETE",
      "path": "/api/admin/users/{userId}",
      "summary": "后台删除用户，同时删除其知识宇宙与研究项目、移交其组织所有权并注销其全部会话。",
      "tags": [
        "admin",
        "accounts"
      ],
      "risk": "destructive",
      "cost": "none",
      "mutation": true,
      "requiresAdmin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "userId",
          "in": "path",
          "required": true,
          "description": "账号 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "账号及其数据已删除。"
        },
        "400": {
          "description": "试图删除当前登录的管理员账号。"
        },
        "403": {
          "description": "需要管理员权限。"
        },
        "409": {
          "description": "最后一个可用管理员不可删除。"
        }
      }
    },
    {
      "id": "adminAdjustCredits",
      "method": "POST",
      "path": "/api/admin/users/{userId}/credits",
      "summary": "增减用户积分，正数增加、负数扣减，余额不足会被拒绝；每次变动写入流水。",
      "tags": [
        "admin",
        "credits"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresAdmin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "userId",
          "in": "path",
          "required": true,
          "description": "账号 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "amount": 500,
        "reason": "开通赠送"
      },
      "requestExampleSetTo": {
        "setTo": 1000,
        "reason": "开通到 1000"
      },
      "responses": {
        "200": {
          "description": "积分已调整，返回新余额与本次流水。amount 为差值模式，setTo 为直接设为指定值。"
        },
        "400": {
          "description": "数量非整数、目标为负、与当前值相同或余额不足。"
        },
        "403": {
          "description": "需要管理员权限。"
        }
      }
    },
    {
      "id": "adminSiteSettings",
      "method": "GET",
      "path": "/api/admin/settings",
      "summary": "读取站点开关（注册开放状态、是否需要登录），并说明取值来自后台设置还是服务器环境。",
      "tags": [
        "admin",
        "settings"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresAdmin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "responses": {
        "200": {
          "description": "registrationOpen、requireLogin 及其来源与环境默认值。"
        },
        "403": {
          "description": "需要管理员权限。"
        }
      }
    },
    {
      "id": "adminUpdateSiteSettings",
      "method": "PATCH",
      "path": "/api/admin/settings",
      "summary": "后台一键开关公开注册与「需要登录」门禁；传 env 可恢复为跟随服务器环境变量。",
      "tags": [
        "admin",
        "settings"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresAdmin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "registrationOpen": false,
        "requireLogin": true
      },
      "responses": {
        "200": {
          "description": "设置已保存并返回生效值。requireLogin 开启时，未登录访客访问内容接口会收到 401 LOGIN_REQUIRED。"
        },
        "403": {
          "description": "需要管理员权限。"
        }
      }
    },
    {
      "id": "adminCreditLedger",
      "method": "GET",
      "path": "/api/admin/users/{userId}/credits",
      "summary": "读取某用户的积分余额与最近的积分流水。",
      "tags": [
        "admin",
        "credits"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresAdmin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "userId",
          "in": "path",
          "required": true,
          "description": "账号 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "余额与流水列表。"
        },
        "403": {
          "description": "需要管理员权限。"
        }
      }
    },
    {
      "id": "adminAuditEvents",
      "method": "GET",
      "path": "/api/admin/audit",
      "summary": "读取后台管理员操作审计（admin.* 事件）。",
      "tags": [
        "admin",
        "audit"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresAdmin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "responses": {
        "200": {
          "description": "管理员操作事件列表。"
        },
        "403": {
          "description": "需要管理员权限。"
        }
      }
    },
    {
      "id": "getBillingStatus",
      "method": "GET",
      "path": "/api/billing/status",
      "summary": "读取当前账号的套餐、订阅状态、可用升级项目和支付配置状态。",
      "tags": [
        "billing",
        "accounts"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "opt-in",
      "responses": {
        "200": {
          "description": "计费状态。"
        }
      }
    },
    {
      "id": "listOrganizations",
      "method": "GET",
      "path": "/api/organizations",
      "summary": "列出当前账号加入的组织 Workspace 和成员。",
      "tags": [
        "organizations",
        "accounts"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "opt-in",
      "responses": {
        "200": {
          "description": "组织列表。"
        }
      }
    },
    {
      "id": "createOrganization",
      "method": "POST",
      "path": "/api/organizations",
      "summary": "创建组织 Workspace；默认要求 Team 或 Enterprise 套餐。",
      "tags": [
        "organizations",
        "accounts"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "name": "AI 产业研究团队"
      },
      "responses": {
        "201": {
          "description": "组织已创建。"
        },
        "403": {
          "description": "套餐不支持组织。"
        }
      }
    },
    {
      "id": "getOrganization",
      "method": "GET",
      "path": "/api/organizations/{organizationId}",
      "summary": "读取组织详情和成员。",
      "tags": [
        "organizations"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "dynamic-read",
      "parameters": [
        {
          "name": "organizationId",
          "in": "path",
          "required": true,
          "description": "组织 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "组织详情。"
        },
        "404": {
          "description": "组织不存在或无权访问。"
        }
      }
    },
    {
      "id": "updateOrganization",
      "method": "PATCH",
      "path": "/api/organizations/{organizationId}",
      "summary": "组织 owner 或 admin 更新组织名称和 slug。",
      "tags": [
        "organizations"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "organizationId",
          "in": "path",
          "required": true,
          "description": "组织 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "name": "新的组织名称"
      },
      "responses": {
        "200": {
          "description": "组织已更新。"
        },
        "403": {
          "description": "需要管理员权限。"
        }
      }
    },
    {
      "id": "upsertOrganizationMember",
      "method": "POST",
      "path": "/api/organizations/{organizationId}/members",
      "summary": "组织 owner 或 admin 邀请账号并设置 admin、editor 或 viewer 角色。",
      "tags": [
        "organizations",
        "teams"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "organizationId",
          "in": "path",
          "required": true,
          "description": "组织 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "email": "member@example.com",
        "role": "editor"
      },
      "responses": {
        "200": {
          "description": "组织成员已更新。"
        },
        "403": {
          "description": "需要管理员权限。"
        }
      }
    },
    {
      "id": "removeOrganizationMember",
      "method": "DELETE",
      "path": "/api/organizations/{organizationId}/members/{userId}",
      "summary": "组织 owner 或 admin 移除成员；不能移除组织所有者。",
      "tags": [
        "organizations",
        "teams"
      ],
      "risk": "destructive",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "organizationId",
          "in": "path",
          "required": true,
          "description": "组织 ID。",
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "userId",
          "in": "path",
          "required": true,
          "description": "成员账号 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "成员已移除。"
        },
        "400": {
          "description": "不能移除所有者。"
        }
      }
    },
    {
      "id": "exportOrganizationAudit",
      "method": "GET",
      "path": "/api/organizations/{organizationId}/audit",
      "summary": "组织 owner 或 admin 导出组织审计记录，支持 JSON 或 CSV，最多 2000 条。",
      "tags": [
        "organizations",
        "audit",
        "enterprise"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "dynamic-read",
      "parameters": [
        {
          "name": "organizationId",
          "in": "path",
          "required": true,
          "description": "组织 ID。",
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "format",
          "in": "query",
          "required": false,
          "description": "csv 时返回可下载 CSV。",
          "schema": {
            "type": "string",
            "enum": [
              "json",
              "csv"
            ]
          }
        }
      ],
      "responses": {
        "200": {
          "description": "审计事件 JSON 或 CSV。"
        },
        "403": {
          "description": "需要组织管理员权限。"
        }
      }
    },
    {
      "id": "listOrganizationApiKeys",
      "method": "GET",
      "path": "/api/organizations/{organizationId}/api-keys",
      "summary": "组织 owner/admin 查看 API Key 元数据；不返回明文 Token 或哈希。",
      "tags": [
        "organizations",
        "api-keys",
        "enterprise"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "dynamic-read",
      "parameters": [
        {
          "name": "organizationId",
          "in": "path",
          "required": true,
          "description": "组织 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "API Key 元数据列表。"
        },
        "403": {
          "description": "需要管理员权限。"
        }
      }
    },
    {
      "id": "createOrganizationApiKey",
      "method": "POST",
      "path": "/api/organizations/{organizationId}/api-keys",
      "summary": "生成组织级 Enterprise API Key；明文 Token 只在创建响应中返回一次。",
      "tags": [
        "organizations",
        "api-keys",
        "enterprise"
      ],
      "risk": "auth",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "organizationId",
          "in": "path",
          "required": true,
          "description": "组织 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "name": "内部数据平台",
        "scopes": [
          "read",
          "write"
        ]
      },
      "responses": {
        "201": {
          "description": "返回一次性 Token 和 Key 元数据。"
        },
        "403": {
          "description": "需要管理员权限。"
        }
      }
    },
    {
      "id": "revokeOrganizationApiKey",
      "method": "DELETE",
      "path": "/api/organizations/{organizationId}/api-keys/{keyId}",
      "summary": "吊销组织 API Key；之后使用该 Key 的请求返回 401。",
      "tags": [
        "organizations",
        "api-keys",
        "destructive"
      ],
      "risk": "destructive",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "organizationId",
          "in": "path",
          "required": true,
          "description": "组织 ID。",
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "keyId",
          "in": "path",
          "required": true,
          "description": "API Key ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "Key 已吊销。"
        },
        "404": {
          "description": "Key 不存在。"
        }
      }
    },
    {
      "id": "createBillingCheckout",
      "method": "POST",
      "path": "/api/billing/checkout",
      "summary": "为 Pro 或 Team 套餐创建 Stripe Subscription Checkout 会话。",
      "tags": [
        "billing",
        "accounts"
      ],
      "risk": "external",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "plan": "pro"
      },
      "responses": {
        "201": {
          "description": "返回 Stripe Checkout URL。"
        },
        "503": {
          "description": "支付未配置。"
        }
      }
    },
    {
      "id": "stripeBillingWebhook",
      "method": "POST",
      "path": "/api/billing/webhook",
      "summary": "接收签名验证后的 Stripe Checkout 和 Subscription Webhook，更新账号套餐状态。",
      "tags": [
        "billing",
        "webhook"
      ],
      "risk": "external",
      "cost": "none",
      "mutation": true,
      "requiresEditor": false,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "id": "evt_...",
        "type": "checkout.session.completed",
        "data": {
          "object": {}
        }
      },
      "responses": {
        "200": {
          "description": "Webhook 已处理。"
        },
        "400": {
          "description": "签名或 JSON 无效。"
        },
        "503": {
          "description": "Webhook 未配置。"
        }
      }
    },
    {
      "id": "listResearchProjects",
      "method": "GET",
      "path": "/api/research-projects",
      "summary": "列出当前账号的云端研究项目。",
      "tags": [
        "research",
        "accounts"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "opt-in",
      "responses": {
        "200": {
          "description": "研究项目列表。"
        },
        "401": {
          "description": "需要登录。"
        }
      }
    },
    {
      "id": "createResearchProjectStored",
      "method": "POST",
      "path": "/api/research-projects",
      "summary": "创建持久化云端研究项目，保存实体、来源和研究笔记。",
      "tags": [
        "research",
        "accounts"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "title": "研究项目",
        "question": "待研究问题",
        "workspace": {
          "entities": [],
          "sources": [],
          "notes": []
        }
      },
      "responses": {
        "201": {
          "description": "项目已创建。"
        },
        "429": {
          "description": "项目数量达到套餐上限。"
        }
      }
    },
    {
      "id": "getResearchProjectStored",
      "method": "GET",
      "path": "/api/research-projects/{projectId}",
      "summary": "读取一个云端研究项目。",
      "tags": [
        "research",
        "accounts"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "dynamic-read",
      "parameters": [
        {
          "name": "projectId",
          "in": "path",
          "required": true,
          "description": "研究项目 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "研究项目。"
        },
        "404": {
          "description": "项目不存在。"
        }
      }
    },
    {
      "id": "updateResearchProjectStored",
      "method": "PATCH",
      "path": "/api/research-projects/{projectId}",
      "summary": "更新研究项目状态、问题、宇宙关联或工作台内容。",
      "tags": [
        "research",
        "accounts"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "projectId",
          "in": "path",
          "required": true,
          "description": "研究项目 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "status": "completed",
        "workspace": {
          "entities": [],
          "sources": [],
          "notes": []
        }
      },
      "responses": {
        "200": {
          "description": "项目已更新。"
        },
        "404": {
          "description": "项目不存在。"
        }
      }
    },
    {
      "id": "deleteResearchProjectStored",
      "method": "DELETE",
      "path": "/api/research-projects/{projectId}",
      "summary": "永久删除当前账号的一个研究项目。",
      "tags": [
        "research",
        "destructive"
      ],
      "risk": "destructive",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "projectId",
          "in": "path",
          "required": true,
          "description": "研究项目 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "项目已删除。"
        },
        "404": {
          "description": "项目不存在。"
        }
      }
    },
    {
      "id": "getProjectCollaboration",
      "method": "GET",
      "path": "/api/research-projects/{projectId}/collaboration",
      "summary": "读取研究项目评论、活动、审批状态和当前成员权限。",
      "tags": [
        "collaboration",
        "research"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "dynamic-read",
      "parameters": [
        {
          "name": "projectId",
          "in": "path",
          "required": true,
          "description": "研究项目 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "协作状态。"
        },
        "404": {
          "description": "项目不存在或无权访问。"
        }
      }
    },
    {
      "id": "createProjectComment",
      "method": "POST",
      "path": "/api/research-projects/{projectId}/comments",
      "summary": "在研究项目中发表评论，可附带实体、来源或章节锚点。",
      "tags": [
        "collaboration"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "projectId",
          "in": "path",
          "required": true,
          "description": "研究项目 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "body": "这个结论需要第二个来源。",
        "anchor": {
          "type": "entity",
          "id": "p-zhugeliang"
        }
      },
      "responses": {
        "201": {
          "description": "评论已创建。"
        }
      }
    },
    {
      "id": "updateProjectComment",
      "method": "PATCH",
      "path": "/api/research-projects/{projectId}/comments/{commentId}",
      "summary": "修改评论正文或把评论标记为已解决。",
      "tags": [
        "collaboration"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "projectId",
          "in": "path",
          "required": true,
          "description": "研究项目 ID。",
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "commentId",
          "in": "path",
          "required": true,
          "description": "评论 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "status": "resolved"
      },
      "responses": {
        "200": {
          "description": "评论已更新。"
        }
      }
    },
    {
      "id": "deleteProjectComment",
      "method": "DELETE",
      "path": "/api/research-projects/{projectId}/comments/{commentId}",
      "summary": "作者删除自己的评论，组织管理员可以删除任意评论。",
      "tags": [
        "collaboration",
        "destructive"
      ],
      "risk": "destructive",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "projectId",
          "in": "path",
          "required": true,
          "description": "研究项目 ID。",
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "commentId",
          "in": "path",
          "required": true,
          "description": "评论 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "评论已删除。"
        }
      }
    },
    {
      "id": "submitProjectReview",
      "method": "POST",
      "path": "/api/research-projects/{projectId}/review/submit",
      "summary": "editor、admin 或 owner 把研究项目提交给组织管理员审阅。",
      "tags": [
        "collaboration",
        "approval"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "projectId",
          "in": "path",
          "required": true,
          "description": "研究项目 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "note": "证据和结论已整理完成。"
      },
      "responses": {
        "200": {
          "description": "项目已进入审阅状态。"
        }
      }
    },
    {
      "id": "decideProjectReview",
      "method": "POST",
      "path": "/api/research-projects/{projectId}/review/decision",
      "summary": "组织 owner 或 admin 批准或退回研究项目。",
      "tags": [
        "collaboration",
        "approval"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "projectId",
          "in": "path",
          "required": true,
          "description": "研究项目 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "decision": "approved",
        "note": "通过审核。"
      },
      "responses": {
        "200": {
          "description": "项目审批已记录。"
        }
      }
    },
    {
      "id": "listResearchRuns",
      "method": "GET",
      "path": "/api/research/runs",
      "summary": "列出当前账号的多 Agent 研究任务及六个阶段的定义。",
      "tags": [
        "research",
        "agents"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "opt-in",
      "responses": {
        "200": {
          "description": "研究任务列表和阶段定义。"
        }
      }
    },
    {
      "id": "createResearchRun",
      "method": "POST",
      "path": "/api/research/runs",
      "summary": "启动持久化多 Agent 研究流水线：Research、Search、Extraction、Graph、Evidence、Writer。可指定 sourceScope 复用已有知识宇宙的资料池。",
      "tags": [
        "research",
        "agents"
      ],
      "risk": "external",
      "cost": "model+search+build",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "projectId": "prj_...",
        "question": "研究生成式 AI 的商业机会",
        "sourceScope": "hybrid",
        "universeId": "universe-..."
      },
      "responses": {
        "202": {
          "description": "研究任务已创建并在后台运行。"
        },
        "400": {
          "description": "缺少资料池宇宙（MISSING_SOURCE_UNIVERSE）或资料池为空（SOURCE_POOL_EMPTY）。"
        },
        "429": {
          "description": "套餐额度不足。"
        }
      }
    },
    {
      "id": "getResearchRun",
      "method": "GET",
      "path": "/api/research/runs/{runId}",
      "summary": "读取多 Agent 研究任务的当前阶段、进度、来源、错误和关键结果。",
      "tags": [
        "research",
        "agents"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "dynamic-read",
      "parameters": [
        {
          "name": "runId",
          "in": "path",
          "required": true,
          "description": "研究任务 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "研究任务状态。"
        },
        "404": {
          "description": "任务不存在或不属于当前账号。"
        }
      }
    },
    {
      "id": "retryResearchRun",
      "method": "POST",
      "path": "/api/research/runs/{runId}/retry",
      "summary": "重新启动失败或中断的多 Agent 研究流水线。",
      "tags": [
        "research",
        "agents"
      ],
      "risk": "external",
      "cost": "model+search+build",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "runId",
          "in": "path",
          "required": true,
          "description": "研究任务 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "202": {
          "description": "研究任务已重新启动。"
        },
        "404": {
          "description": "任务不存在。"
        }
      }
    },
    {
      "id": "loginEditor",
      "method": "POST",
      "path": "/api/editor/login",
      "summary": "验证编辑密码并创建 HttpOnly 编辑会话。公共读取不需要调用。",
      "tags": [
        "security"
      ],
      "risk": "auth",
      "cost": "none",
      "mutation": false,
      "requiresEditor": false,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "username": "editor",
        "password": "editor-password"
      },
      "responses": {
        "200": {
          "description": "编辑会话创建成功。"
        },
        "401": {
          "description": "编辑凭据错误。"
        },
        "429": {
          "description": "失败次数过多。"
        },
        "503": {
          "description": "服务器未启用编辑模式。"
        }
      }
    },
    {
      "id": "logoutEditor",
      "method": "POST",
      "path": "/api/editor/logout",
      "summary": "销毁当前编辑会话。",
      "tags": [
        "security"
      ],
      "risk": "auth",
      "cost": "none",
      "mutation": false,
      "requiresEditor": false,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {},
      "responses": {
        "200": {
          "description": "编辑会话已清除。"
        }
      }
    },
    {
      "id": "testModel",
      "method": "POST",
      "path": "/api/model/test",
      "summary": "向已配置模型发送一次连通性测试，会产生外部请求和模型费用。",
      "tags": [
        "model"
      ],
      "risk": "external",
      "cost": "model",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "opt-in",
      "requestExample": {},
      "responses": {
        "200": {
          "description": "模型连接正常。"
        },
        "503": {
          "description": "模型未配置。"
        }
      }
    },
    {
      "id": "parseDocument",
      "method": "POST",
      "path": "/api/documents/parse",
      "summary": "解析 Base64 文档并返回文本，支持 PDF、Word、Markdown、TXT、HTML 和电子书。",
      "tags": [
        "sources"
      ],
      "risk": "cpu",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "opt-in",
      "requestExample": {
        "name": "example.md",
        "mimeType": "text/markdown",
        "dataBase64": "SGVsbG8="
      },
      "constraints": [
        "单文件最多 32MB",
        "解析文本最多 150 万字符"
      ],
      "responses": {
        "200": {
          "description": "返回解析后的文档正文。"
        },
        "400": {
          "description": "格式不支持或正文为空。"
        },
        "413": {
          "description": "文件过大。"
        }
      }
    },
    {
      "id": "fetchSourceUrl",
      "method": "POST",
      "path": "/api/sources/fetch",
      "summary": "抓取公开 HTTP(S) 网页并提取正文，内网、元数据地址和本机地址会被拒绝。",
      "tags": [
        "sources"
      ],
      "risk": "external",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "opt-in",
      "requestExample": {
        "url": "https://example.com"
      },
      "constraints": [
        "最多 4 次跳转",
        "响应最多 4MB",
        "正文最多 40 万字符",
        "30 秒超时"
      ],
      "responses": {
        "200": {
          "description": "返回网页标题、正文和来源信息。"
        },
        "400": {
          "description": "URL 不合法或指向受限地址。"
        },
        "502": {
          "description": "网页无法访问或正文过少。"
        }
      }
    },
    {
      "id": "collectResearchSources",
      "method": "POST",
      "path": "/api/research/collect",
      "summary": "通过 Tavily、Brave、Serper 或自定义搜索提供商收集多个网页，抓取正文并整理为研究资料。",
      "tags": [
        "research",
        "search"
      ],
      "risk": "external",
      "cost": "search+fetch",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "opt-in",
      "requestExample": {
        "query": "生成式人工智能产业链 2026",
        "maxResults": 6,
        "maxPages": 4
      },
      "responses": {
        "200": {
          "description": "返回搜索结果、成功抓取的来源、正文、失败项和检索时间。"
        },
        "429": {
          "description": "账号网页抓取额度不足。"
        },
        "503": {
          "description": "未配置搜索提供商。"
        }
      }
    },
    {
      "id": "listUniverses",
      "method": "GET",
      "path": "/api/universes",
      "summary": "列出全部知识宇宙及其统计信息。",
      "tags": [
        "universes"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "always",
      "responses": {
        "200": {
          "description": "知识宇宙摘要列表。",
          "schema": "UniverseList"
        }
      }
    },
    {
      "id": "createUniverse",
      "method": "POST",
      "path": "/api/universes",
      "summary": "创建知识宇宙并异步启动解析、抽取和图谱生成。",
      "tags": [
        "universes",
        "build"
      ],
      "risk": "write",
      "cost": "model",
      "mutation": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "name": "AI 审计临时知识宇宙",
        "description": "用于审计，请在隔离环境中创建并删除。",
        "sourceTitles": [
          "example.md"
        ],
        "sourceText": "用于测试的短文本。",
        "mode": "research"
      },
      "constraints": [
        "请求体最多 24MB",
        "创建后由后台任务完成构建"
      ],
      "responses": {
        "202": {
          "description": "已创建并启动后台构建任务。"
        }
      }
    },
    {
      "id": "searchUniverse",
      "method": "GET",
      "path": "/api/search",
      "summary": "在一个知识宇宙中按关键词和实体类型搜索。",
      "tags": [
        "search"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "always",
      "parameters": [
        {
          "name": "universeId",
          "in": "query",
          "required": false,
          "description": "知识宇宙 ID；省略时使用默认宇宙。",
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "q",
          "in": "query",
          "required": true,
          "description": "搜索词。",
          "schema": {
            "type": "string"
          },
          "example": "曹操"
        },
        {
          "name": "type",
          "in": "query",
          "required": false,
          "description": "实体类型筛选。",
          "schema": {
            "type": "string"
          },
          "example": "person"
        }
      ],
      "responses": {
        "200": {
          "description": "匹配实体列表。"
        }
      }
    },
    {
      "id": "chatWithUniverse",
      "method": "POST",
      "path": "/api/chat",
      "summary": "基于指定知识宇宙和当前实体进行带证据的 AI 问答。",
      "tags": [
        "chat",
        "model"
      ],
      "risk": "external",
      "cost": "model",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "universeId": "three-kingdoms",
        "entityId": "p-caocao",
        "question": "曹操和诸葛亮之间有哪些关键关系？"
      },
      "responses": {
        "200": {
          "description": "包含 answer、sections、evidence 和 actions 的回答。"
        }
      }
    },
    {
      "id": "retryUniverseBuild",
      "method": "POST",
      "path": "/api/universes/{universeId}/retry",
      "summary": "重新启动失败或中断的知识宇宙构建任务。",
      "tags": [
        "build"
      ],
      "risk": "write",
      "cost": "model",
      "mutation": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {},
      "responses": {
        "202": {
          "description": "已重新启动后台构建。"
        },
        "404": {
          "description": "知识宇宙不存在。"
        },
        "409": {
          "description": "当前状态下不能重试。"
        }
      }
    },
    {
      "id": "getStudyGuide",
      "method": "GET",
      "path": "/api/universes/{universeId}/study-guide",
      "summary": "读取学习指南；首次生成或 force=1 时可能调用模型并持久化结果。",
      "tags": [
        "study",
        "model"
      ],
      "risk": "conditional-write",
      "cost": "conditional-model",
      "mutation": true,
      "source": "server.mjs#handleApi",
      "probe": "skip-default",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "force",
          "in": "query",
          "required": false,
          "description": "设为 1 时强制重新生成。",
          "schema": {
            "type": "string",
            "enum": [
              "1"
            ]
          }
        }
      ],
      "responses": {
        "200": {
          "description": "返回学习指南。"
        },
        "202": {
          "description": "知识宇宙仍在构建。"
        }
      }
    },
    {
      "id": "getResearchReport",
      "method": "GET",
      "path": "/api/universes/{universeId}/research-report",
      "summary": "把当前知识宇宙整理为执行摘要、关键实体、发展时间线、关系、证据、结论和限制。",
      "tags": [
        "research"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "dynamic-read",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "结构化研究报告。"
        },
        "202": {
          "description": "知识宇宙仍在构建。"
        }
      }
    },
    {
      "id": "getEvidenceVerification",
      "method": "GET",
      "path": "/api/universes/{universeId}/evidence-verification",
      "summary": "核验关系来源数量、来源类型、平均可信度、弱来源、无来源实体和无来源时间事件。",
      "tags": [
        "evidence",
        "research"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "dynamic-read",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "证据核验分数、摘要、关系状态和问题列表。"
        }
      }
    },
    {
      "id": "addManualEntity",
      "method": "POST",
      "path": "/api/universes/{universeId}/entities",
      "summary": "向一个知识宇宙手动添加实体，并可创建一条关系。",
      "tags": [
        "entities",
        "write"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "name": "审计临时实体",
        "type": "concept",
        "summary": "仅用于隔离环境中的审计。",
        "relatedEntityId": "p-caocao",
        "relationLabel": "测试关系"
      },
      "responses": {
        "201": {
          "description": "返回新增实体和可选关系。"
        },
        "404": {
          "description": "知识宇宙不存在。"
        }
      }
    },
    {
      "id": "deleteUniverse",
      "method": "DELETE",
      "path": "/api/universes/{universeId}",
      "summary": "永久删除知识宇宙及其持久化文件。",
      "tags": [
        "universes",
        "destructive"
      ],
      "risk": "destructive",
      "cost": "none",
      "mutation": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "删除完成。"
        },
        "404": {
          "description": "知识宇宙不存在。"
        }
      }
    },
    {
      "id": "updateUniverse",
      "method": "PATCH",
      "path": "/api/universes/{universeId}",
      "summary": "知识宇宙所有者更新名称、说明或公开读取状态。",
      "tags": [
        "universes",
        "permissions"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "visibility": "private",
        "name": "新的名称"
      },
      "responses": {
        "200": {
          "description": "知识宇宙已更新。"
        },
        "403": {
          "description": "只有所有者可以更新。"
        }
      }
    },
    {
      "id": "upsertUniverseMember",
      "method": "POST",
      "path": "/api/universes/{universeId}/members",
      "summary": "所有者邀请已注册账号并设置 viewer 或 editor 角色。",
      "tags": [
        "permissions",
        "teams"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "email": "member@example.com",
        "role": "viewer"
      },
      "responses": {
        "200": {
          "description": "成员权限已设置。"
        },
        "404": {
          "description": "邮箱未注册。"
        }
      }
    },
    {
      "id": "removeUniverseMember",
      "method": "DELETE",
      "path": "/api/universes/{universeId}/members/{userId}",
      "summary": "所有者移除知识宇宙成员。",
      "tags": [
        "permissions",
        "teams"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "userId",
          "in": "path",
          "required": true,
          "description": "成员账号 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "成员已移除。"
        },
        "400": {
          "description": "不能移除所有者。"
        }
      }
    },
    {
      "id": "getUniverse",
      "method": "GET",
      "path": "/api/universes/{universeId}",
      "summary": "读取一个知识宇宙的完整实体、关系、时间线、来源和学习指南。",
      "tags": [
        "universes"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "always",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "完整知识宇宙对象。",
          "schema": "Universe"
        },
        "404": {
          "description": "知识宇宙不存在。"
        }
      }
    },
    {
      "id": "getEntity",
      "method": "GET",
      "path": "/api/universes/{universeId}/entities/{entityId}",
      "summary": "读取单个实体及其关联证据。",
      "tags": [
        "entities"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "dynamic-read",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "entityId",
          "in": "path",
          "required": true,
          "description": "实体 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "实体及其证据。"
        },
        "404": {
          "description": "实体不存在。"
        }
      }
    },
    {
      "id": "runFactCheck",
      "method": "POST",
      "path": "/api/universes/{universeId}/fact-check",
      "summary": "使用 Wikidata 对知识宇宙实体做外部事实核查，并把冲突加入人工复核。",
      "tags": [
        "evidence",
        "fact-checking"
      ],
      "risk": "external",
      "cost": "external-free-api",
      "mutation": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "maxEntities": 20,
        "concurrency": 3
      },
      "responses": {
        "200": {
          "description": "事实核查和复核入队结果。"
        }
      }
    },
    {
      "id": "verifySourceMetadata",
      "method": "POST",
      "path": "/api/universes/{universeId}/sources/verify",
      "summary": "通过 DOI 或 ISBN 核验来源元数据。",
      "tags": [
        "evidence",
        "sources"
      ],
      "risk": "external",
      "cost": "external-free-api",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "doi": "10.1000/example"
      },
      "responses": {
        "200": {
          "description": "来源核验结果。"
        }
      }
    },
    {
      "id": "sourceVerificationCheck",
      "method": "POST",
      "path": "/api/source-verification/check",
      "summary": "按 URL、发布方、作者、日期和外部数据库信号计算来源可信度。",
      "tags": [
        "evidence",
        "credibility"
      ],
      "risk": "external",
      "cost": "external-free-api",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "source": {
          "title": "Demo",
          "url": "https://example.com",
          "publisher": "Example"
        }
      },
      "responses": {
        "200": {
          "description": "可信度评分和特征。"
        }
      }
    },
    {
      "id": "trainCredibilityModel",
      "method": "POST",
      "path": "/api/source-verification/feedback",
      "summary": "用人工标注反馈训练并持久化来源可信度权重。",
      "tags": [
        "evidence",
        "credibility"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "requestExample": {
        "label": true,
        "features": {
          "https": 1,
          "knownPublisher": 1,
          "hasAuthor": 1
        }
      },
      "responses": {
        "200": {
          "description": "更新后的模型。"
        }
      }
    },
    {
      "id": "listReviewQueue",
      "method": "GET",
      "path": "/api/review-queue",
      "summary": "读取知识宇宙的人工证据复核队列。",
      "tags": [
        "evidence",
        "review"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "dynamic-read",
      "parameters": [
        {
          "name": "universeId",
          "in": "query",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "复核事项和统计。"
        }
      }
    },
    {
      "id": "updateReviewItem",
      "method": "PATCH",
      "path": "/api/review-queue/{itemId}",
      "summary": "认领、确认、忽略或要求补充证据。",
      "tags": [
        "evidence",
        "review"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "itemId",
          "in": "path",
          "required": true,
          "description": "复核事项 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "decision": "accepted",
        "note": "已人工确认"
      },
      "responses": {
        "200": {
          "description": "更新后的复核事项。"
        }
      }
    },
    {
      "id": "runEntityResolution",
      "method": "POST",
      "path": "/api/universes/{universeId}/entity-resolution/run",
      "summary": "跨来源识别重复实体，自动合并高置信度项，并把冲突保留为人工候选。",
      "tags": [
        "entities",
        "resolution"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "threshold": 0.9,
        "reviewThreshold": 0.62
      },
      "responses": {
        "200": {
          "description": "实体合并结果。"
        }
      }
    },
    {
      "id": "incrementalSourceUpdate",
      "method": "POST",
      "path": "/api/universes/{universeId}/sources/incremental",
      "summary": "往已建好的知识宇宙补充资料：按来源指纹去重，重新用模型解析新增内容，只合并新增实体、关系、事件并标记受影响部分。",
      "tags": [
        "sources",
        "incremental"
      ],
      "risk": "write",
      "cost": "model",
      "mutation": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "sources": [
          {
            "title": "2026 更新报告",
            "text": "新增正文",
            "url": "https://example.com/report"
          },
          {
            "title": "补充访谈",
            "text": "另一份新增正文"
          }
        ]
      },
      "responses": {
        "200": {
          "description": "资料与已收录内容指纹一致，没有新增知识。"
        },
        "202": {
          "description": "增量分析任务已排队，返回任务与 incrementalUpdate 进度。"
        },
        "400": {
          "description": "单批资料数量超限。"
        },
        "409": {
          "description": "该知识宇宙已有增量任务在执行。"
        }
      }
    },
    {
      "id": "exportResearchReport",
      "method": "GET",
      "path": "/api/universes/{universeId}/research-report/export",
      "summary": "导出带引用的 Markdown、可编辑 Word 或 PDF 研究报告。",
      "tags": [
        "research",
        "reports"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "dynamic-read",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "format",
          "in": "query",
          "required": false,
          "description": "markdown、docx 或 pdf。",
          "schema": {
            "type": "string",
            "enum": [
              "markdown",
              "docx",
              "pdf"
            ]
          }
        }
      ],
      "responses": {
        "200": {
          "description": "报告文件。"
        }
      }
    },
    {
      "id": "listMarket",
      "method": "GET",
      "path": "/api/market",
      "summary": "公开搜索已发布知识宇宙市场。",
      "tags": [
        "community",
        "market"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "source": "server.mjs#handleApi",
      "probe": "always",
      "responses": {
        "200": {
          "description": "公开市场列表。"
        }
      }
    },
    {
      "id": "forkMarketUniverse",
      "method": "POST",
      "path": "/api/market/{listingId}/fork",
      "summary": "把公开知识宇宙复制到当前账号的私有空间。",
      "tags": [
        "community",
        "market"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "listingId",
          "in": "path",
          "required": true,
          "description": "市场条目 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "201": {
          "description": "已创建私有副本。"
        }
      }
    },
    {
      "id": "publishUniverse",
      "method": "POST",
      "path": "/api/universes/{universeId}/publish",
      "summary": "知识宇宙所有者把知识宇宙发布到公开市场。",
      "tags": [
        "community",
        "market"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "universeId",
          "in": "path",
          "required": true,
          "description": "知识宇宙 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "requestExample": {
        "title": "公开知识宇宙",
        "tags": [
          "AI"
        ]
      },
      "responses": {
        "201": {
          "description": "市场条目。"
        }
      }
    },
    {
      "id": "listPersonalization",
      "method": "GET",
      "path": "/api/personalization",
      "summary": "读取当前账号的个性化偏好。",
      "tags": [
        "personalization"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "opt-in",
      "responses": {
        "200": {
          "description": "个性化配置。"
        }
      }
    },
    {
      "id": "listJobs",
      "method": "GET",
      "path": "/api/jobs",
      "summary": "读取持久化任务队列、优先级、预算、重试和状态统计。",
      "tags": [
        "jobs"
      ],
      "risk": "read",
      "cost": "none",
      "mutation": false,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "opt-in",
      "responses": {
        "200": {
          "description": "任务列表和统计。"
        }
      }
    },
    {
      "id": "cancelJob",
      "method": "POST",
      "path": "/api/jobs/{jobId}/cancel",
      "summary": "取消排队或运行中的长任务。",
      "tags": [
        "jobs"
      ],
      "risk": "write",
      "cost": "none",
      "mutation": true,
      "requiresLogin": true,
      "source": "server.mjs#handleApi",
      "probe": "never",
      "parameters": [
        {
          "name": "jobId",
          "in": "path",
          "required": true,
          "description": "任务 ID。",
          "schema": {
            "type": "string"
          }
        }
      ],
      "responses": {
        "200": {
          "description": "取消后的任务。"
        }
      }
    }
  ],
  "ui": {
    "views": [
      {
        "id": "study",
        "title": "学习",
        "selector": "[data-view='study']",
        "panel": "[data-view-panel='study']",
        "purpose": "默认入口，展示学习指南、核心观点、模块、学习路径和常见问题。",
        "controls": [
          "#stage-title",
          "#study-loading",
          "#study-content",
          "#export-study-guide",
          "#retry-study-guide"
        ],
        "apiDependencies": [
          "listUniverses",
          "getUniverse",
          "getStudyGuide"
        ]
      },
      {
        "id": "graph",
        "title": "图谱",
        "selector": "[data-view='graph']",
        "panel": "[data-view-panel='graph']",
        "purpose": "探索实体关系，支持筛选、缩放、布局、关系路径追踪和手动添加实体。",
        "controls": [
          "#graph",
          "#map-mode",
          "#layout-button",
          "#motion-toggle",
          "#label-toggle",
          "#trace-button",
          "#add-entity-button",
          "#zoom-out",
          "#zoom-in",
          "#fit-graph"
        ],
        "apiDependencies": [
          "getUniverse",
          "addManualEntity",
          "searchUniverse"
        ]
      },
      {
        "id": "timeline",
        "title": "时间线",
        "selector": "[data-view='timeline']",
        "panel": "[data-view-panel='timeline']",
        "purpose": "让人物和事件按年份并排展示，支持最多 8 人比较。",
        "controls": [
          "#timeline-person-picks",
          "#timeline-canvas"
        ],
        "apiDependencies": [
          "getUniverse"
        ]
      },
      {
        "id": "evidence",
        "title": "证据库",
        "selector": "[data-view='evidence']",
        "panel": "[data-view-panel='evidence']",
        "purpose": "展示来源、引用数量和可追溯的原文片段。",
        "controls": [
          "#evidence-grid",
          "#source-count",
          "#citation-count",
          "#evidence-modal"
        ],
        "apiDependencies": [
          "getUniverse",
          "getEntity"
        ]
      },
      {
        "id": "wiki",
        "title": "实体 Wiki",
        "selector": "[data-inspector='wiki']",
        "panel": "[data-inspector-panel='wiki']",
        "purpose": "显示当前实体的摘要、属性、关系和证据。",
        "controls": [
          "#entity-wiki"
        ],
        "apiDependencies": [
          "getUniverse",
          "getEntity"
        ]
      },
      {
        "id": "ai",
        "title": "AI Explorer",
        "selector": "[data-inspector='ai']",
        "panel": "[data-inspector-panel='ai']",
        "purpose": "基于当前知识宇宙和实体进行上下文问答。",
        "controls": [
          "#chat-history",
          "#ai-suggestions",
          "#chat-form",
          "#chat-input"
        ],
        "apiDependencies": [
          "chatWithUniverse"
        ]
      },
      {
        "id": "research",
        "title": "AI 研究报告",
        "selector": "#research-button",
        "panel": "[data-view-panel='research']",
        "purpose": "输入研究问题，创建研究型知识宇宙，并展示结构化研究报告。",
        "controls": [
          "#research-view-form",
          "#research-view-input",
          "#research-report",
          "#agent-run-console",
          "#agent-stage-list"
        ],
        "apiDependencies": [
          "createResearchRun",
          "getResearchRun",
          "getResearchReport",
          "getUniverse"
        ]
      },
      {
        "id": "workspace",
        "title": "研究工坊",
        "selector": "#workspace-button",
        "panel": "[data-view-panel='workspace']",
        "purpose": "保存实体、来源和研究笔记，并导出 Markdown 工作台。",
        "controls": [
          "#workspace-entity-list",
          "#workspace-source-list",
          "#workspace-note-list",
          "#workspace-export",
          "#workspace-collaboration",
          "#comment-form"
        ],
        "apiDependencies": [
          "getUniverse",
          "getEntity",
          "getProjectCollaboration",
          "createProjectComment",
          "submitProjectReview",
          "decideProjectReview"
        ]
      },
      {
        "id": "account",
        "title": "账号与套餐",
        "selector": "#account-button",
        "panel": "#account-modal",
        "purpose": "注册、登录、查看套餐与月度用量、退出账号。",
        "controls": [
          "#account-form",
          "#account-email",
          "#account-password",
          "#account-logout"
        ],
        "apiDependencies": [
          "getAccountSession",
          "registerAccount",
          "loginAccount",
          "updateAccountProfile"
        ]
      },
      {
        "id": "team-members",
        "title": "团队与共享",
        "selector": "#share-universe-button",
        "panel": "#members-modal",
        "purpose": "知识宇宙所有者邀请成员、设置只读/编辑角色、移除成员和控制公开读取。",
        "controls": [
          "#member-invite-form",
          "#member-list",
          "#universe-visibility"
        ],
        "apiDependencies": [
          "upsertUniverseMember",
          "removeUniverseMember",
          "updateUniverse"
        ]
      },
      {
        "id": "organization-workspace",
        "title": "组织 Workspace",
        "selector": "#organization-button",
        "panel": "#organization-modal",
        "purpose": "Team/Enterprise 用户创建组织、切换组织、邀请组织成员并统一管理共享项目与知识宇宙。",
        "controls": [
          "#organization-modal",
          "#organization-select",
          "#organization-create-form",
          "#organization-member-form",
          "#api-key-form",
          "#api-key-list"
        ],
        "apiDependencies": [
          "listOrganizations",
          "createOrganization",
          "updateOrganization",
          "upsertOrganizationMember",
          "removeOrganizationMember",
          "listOrganizationApiKeys",
          "createOrganizationApiKey"
        ]
      },
      {
        "id": "review-queue",
        "title": "人工证据复核",
        "selector": "#review-queue",
        "panel": "[data-view-panel='evidence']",
        "purpose": "处理事实核查冲突、弱来源、无证据实体和无证据事件。",
        "controls": [
          "#fact-check-button",
          "#review-item-list",
          "#review-queue-count"
        ],
        "apiDependencies": [
          "runFactCheck",
          "listReviewQueue",
          "updateReviewItem"
        ]
      },
      {
        "id": "market",
        "title": "公开知识宇宙市场",
        "selector": "#market-button",
        "panel": "#market-modal",
        "purpose": "搜索公开知识宇宙、复制到私有空间，并发布自己的知识宇宙。",
        "controls": [
          "#market-modal",
          "#market-search-form",
          "#market-list"
        ],
        "apiDependencies": [
          "listMarket",
          "forkMarketUniverse",
          "publishUniverse"
        ]
      },
      {
        "id": "login-gate",
        "title": "登录门禁",
        "selector": "#auth-gate",
        "panel": "#auth-gate",
        "purpose": "开启「需要登录」后，打开网址先看到整屏登录/注册界面，未登录访问内容接口返回 401 LOGIN_REQUIRED。",
        "controls": [
          "#auth-gate",
          "#gate-form",
          "#gate-identifier",
          "#gate-password",
          "#gate-name",
          "#gate-editor-form",
          "#gate-editor-toggle",
          "#gate-submit"
        ],
        "apiDependencies": [
          "getAccountSession",
          "loginAccount",
          "registerAccount",
          "loginEditor",
          "adminUpdateSiteSettings"
        ]
      },
      {
        "id": "login-page",
        "title": "登录 / 注册入口",
        "selector": "#account-button",
        "panel": "#account-modal",
        "purpose": "POST /api/accounts/register 用邮箱注册；POST /api/accounts/login 的同一个输入框既接受邮箱也接受用户名。/login 可直接打开该弹窗。",
        "controls": [
          "#account-modal",
          "#account-form",
          "#account-email",
          "#account-password",
          "#account-name",
          "#account-identifier-label",
          "#account-logout",
          "#account-session-summary",
          "#account-password-change",
          "#password-form",
          "#password-current",
          "#password-new",
          "#password-confirm",
          "#password-submit"
        ],
        "apiDependencies": [
          "registerAccount",
          "loginAccount",
          "getAccountSession",
          "changeOwnPassword"
        ]
      },
      {
        "id": "admin-console",
        "title": "后台管理用户、权限与积分",
        "selector": "#admin-button",
        "panel": "#admin-modal",
        "purpose": "用户列表与搜索、新建/编辑/删除用户、角色与状态、套餐与单独额度覆盖、积分增减与流水、管理员操作审计。",
        "controls": [
          "#admin-modal",
          "#admin-stats",
          "#admin-user-list",
          "#admin-search",
          "#admin-create-form",
          "#admin-new-plan",
          "#admin-new-credits",
          "#admin-new-limits",
          "#admin-edit-modal",
          "#admin-edit-role",
          "#admin-edit-plan",
          "#admin-edit-status",
          "#admin-edit-limits",
          "#admin-delete-modal",
          "#admin-delete-confirm",
          "#credit-modal",
          "#credit-amount",
          "#credit-ledger",
          "#admin-registration-toggle",
          "#admin-registration-reset",
          "#credit-quick-set"
        ],
        "apiDependencies": [
          "adminSession",
          "adminOverview",
          "adminListUsers",
          "adminCreateUser",
          "adminUpdateUser",
          "adminDeleteUser",
          "adminAdjustCredits",
          "adminCreditLedger",
          "adminAuditEvents",
          "adminSiteSettings",
          "adminUpdateSiteSettings"
        ]
      },
      {
        "id": "incremental-update",
        "title": "新增资料与增量收录",
        "selector": "#add-knowledge-button",
        "panel": "#incremental-modal",
        "purpose": "在已建好的知识宇宙里上传文件、抓取网页或粘贴正文，AI 重新解析后只合并增量知识，并在页面底部显示分析进度。",
        "controls": [
          "#incremental-modal",
          "#incremental-form",
          "#incremental-target-name",
          "#incremental-drop-zone",
          "#incremental-files",
          "#incremental-token-list",
          "#incremental-url",
          "#incremental-add-url",
          "#incremental-title",
          "#incremental-text",
          "#incremental-pill",
          "#incremental-pill-progress",
          "#study-add-knowledge"
        ],
        "apiDependencies": [
          "incrementalSourceUpdate",
          "getJob",
          "parseDocument",
          "fetchSourceUrl"
        ]
      }
    ],
    "flows": [
      {
        "id": "open-app",
        "title": "打开应用并加载默认知识宇宙",
        "entry": "/",
        "steps": [
          "GET / 加载 public/index.html、styles.css 和 app.js。",
          "app.js 调用 GET /api/universes 和 GET /api/health。",
          "选择列表中的第一个知识宇宙并调用 GET /api/universes/{universeId}。",
          "初始化图谱、Wiki、时间线、证据库、搜索和 AI 面板。"
        ],
        "routes": [
          "getHealth",
          "listUniverses",
          "getUniverse"
        ],
        "uiTargets": [
          "#universe-list",
          "#graph",
          "#entity-wiki",
          "#timeline-canvas",
          "#evidence-grid"
        ]
      },
      {
        "id": "switch-universe",
        "title": "切换知识宇宙",
        "entry": "#universe-list",
        "steps": [
          "点击知识宇宙条目。",
          "前端销毁旧图实例并请求 GET /api/universes/{universeId}。",
          "重新渲染全部视图。"
        ],
        "routes": [
          "getUniverse"
        ],
        "uiTargets": [
          "#universe-list",
          "#current-universe-name"
        ]
      },
      {
        "id": "search-and-inspect",
        "title": "全局搜索并检查实体",
        "entry": "#global-search",
        "steps": [
          "输入人物、事件或概念关键词。",
          "前端请求 GET /api/search。",
          "选择结果后定位图谱节点并显示实体 Wiki 和证据。"
        ],
        "routes": [
          "searchUniverse",
          "getUniverse",
          "getEntity"
        ],
        "uiTargets": [
          "#global-search",
          "#search-popover",
          "#entity-wiki"
        ]
      },
      {
        "id": "float-graph",
        "title": "节点浮动、体积碰撞与前后层次",
        "entry": "#motion-toggle",
        "steps": [
          "进入图谱视图后，rAF 循环按 25ms 节流推进节点位置，只写 position，不写样式。",
          "每个节点围绕布局锚点向一个缓慢移动的目标点漂移（GRAPH_MOTION_SPRING）。",
          "随后按均匀网格做两遍松弛：气泡重叠时互相推开，形成 Obsidian 那种有机的挤靠感。",
          "每个节点带 0 到 1 的 depth：决定尺寸、透明度、边框、柔光晕、标签大小和 z-index。",
          "depth 每 900ms 缓慢呼吸一次，每次只改动少量节点。",
          "可见边数超过 560 / 1600 时逐级降为纯浮动或静态；帧间隔持续过慢时自动降级，平稳后可回升。",
          "偏好保存在 localStorage 的 k-world:graph-motion，并尊重 prefers-reduced-motion。",
          "离开图谱视图或标签页进入后台时停止循环并把节点放回布局位置。"
        ],
        "routes": [],
        "uiTargets": [
          "#motion-toggle",
          "#graph"
        ]
      },
      {
        "id": "trace-relationship",
        "title": "追踪两个实体之间的最短关系路径",
        "entry": "#trace-button",
        "steps": [
          "点击关系追踪。",
          "依次选择起点和终点实体。",
          "前端在已加载图谱中计算路径并高亮节点与边。"
        ],
        "routes": [
          "getUniverse"
        ],
        "uiTargets": [
          "#trace-button",
          "#trace-banner",
          "#graph"
        ]
      },
      {
        "id": "create-universe",
        "title": "创建知识宇宙",
        "entry": "#create-universe-button",
        "steps": [
          "打开创建对话框，输入名称、说明并添加文件、书名或 URL。",
          "URL 通过 POST /api/sources/fetch 抓取正文。",
          "文件通过 POST /api/documents/parse 解析，文本文件可在浏览器读取。",
          "POST /api/universes 创建知识宇宙并轮询构建进度。"
        ],
        "routes": [
          "fetchSourceUrl",
          "parseDocument",
          "createUniverse",
          "getUniverse"
        ],
        "uiTargets": [
          "#create-modal",
          "#create-form",
          "#drop-zone",
          "#source-input",
          "#source-token-list"
        ],
        "mutation": true
      },
      {
        "id": "audit-gated-site",
        "title": "对开启登录门禁的站点执行完整审计",
        "entry": "npm run audit:ai",
        "steps": [
          "不带凭据运行：识别门禁，确认公开入口正常，输出门禁报告并以退出码 0 结束。",
          "带凭据运行（--login/--password、--editor、--cookie，或对应 K_WORLD_AUDIT_* 环境变量）：先登录换取会话 cookie，再爬取全部内容。",
          "探测 /api/universes 判断是否真的被门禁拦住，而不是只看账号会话（运维身份用的是另一个 cookie）。",
          "凭据错误、缺少密码或登录后仍无读取权限时明确报错并以退出码 1 结束。",
          "凭据与 cookie 不写入报告，日志中的 cookie 脱敏为 kworld_account=***。"
        ],
        "routes": [],
        "uiTargets": []
      },
      {
        "id": "visit-gated-site",
        "title": "打开需要登录的站点",
        "entry": "/",
        "steps": [
          "GET / 仍然公开，返回应用外壳；应用随后调用 GET /api/accounts/session。",
          "会话返回 requiresLogin:true 且 authenticated:false 时，前端显示整屏登录门禁，不加载任何内容。",
          "此时任何内容接口都返回 401 LOGIN_REQUIRED；只有 health、账号登录注册、编辑模式登录、Stripe 回调和机器可读入口保持公开。",
          "通过门禁登录或注册成功后，前端隐藏门禁并启动应用、加载知识宇宙。",
          "登出后会重新载入页面并回到门禁，确保上一个用户的内容不残留在 DOM 中。"
        ],
        "routes": [
          "getAccountSession",
          "loginAccount",
          "registerAccount"
        ],
        "uiTargets": [
          "#auth-gate",
          "#gate-form",
          "#gate-identifier",
          "#gate-password"
        ],
        "mutation": false
      },
      {
        "id": "admin-manage-user",
        "title": "后台新增并管理一个用户",
        "entry": "#admin-button",
        "steps": [
          "用编辑模式登录，或让账号角色为 admin；GET /api/admin/session 决定入口是否显示。",
          "打开后台：GET /api/admin/overview 读套餐目录，GET /api/admin/users 读用户列表。",
          "新建用户：POST /api/admin/users 可指定角色、套餐、状态、初始积分与额度覆盖。",
          "编辑用户：PATCH /api/admin/users/{userId} 改角色、套餐、状态、密码与额度覆盖。",
          "停用用户后其会话立即失效，再次登录返回 ACCOUNT_DISABLED。",
          "调整积分：POST /api/admin/users/{userId}/credits，余额不足会被拒绝；GET 同路径读流水。",
          "删除用户：DELETE /api/admin/users/{userId}，同时删除其知识宇宙与研究项目。",
          "关闭注册：PATCH /api/admin/settings，公开注册入口与账号弹窗的注册标签同时隐藏；传 env 恢复为跟随环境变量。",
          "所有写操作写入 admin.* 审计，可在 GET /api/admin/audit 查看。"
        ],
        "routes": [
          "adminListUsers",
          "adminCreateUser",
          "adminUpdateUser",
          "adminDeleteUser",
          "adminAdjustCredits",
          "adminCreditLedger",
          "adminAuditEvents",
          "adminUpdateSiteSettings"
        ],
        "uiTargets": [
          "#admin-button",
          "#admin-modal",
          "#admin-user-list",
          "#admin-create-form",
          "#credit-modal",
          "#admin-delete-modal"
        ],
        "mutation": true
      },
      {
        "id": "add-material-to-universe",
        "title": "给已建好的知识宇宙新增资料",
        "entry": "#add-knowledge-button",
        "steps": [
          "在知识宇宙顶部或学习页点击「新增资料」，打开增量上传对话框。",
          "拖入或选择文件：POST /api/documents/parse 解析 PDF、Word、电子书正文。",
          "粘贴公开网址：POST /api/sources/fetch 抓取网页正文。",
          "也可以直接在对话框里粘贴正文并填写标题。",
          "POST /api/universes/{universeId}/sources/incremental 提交资料批次，返回 202 与已排队任务。",
          "前端每 4 秒轮询 GET /api/universes/{universeId}，用底部进度条展示 incrementalUpdate 进度。",
          "任务完成后再加载 GET /api/universes/{universeId} 和 GET /api/universes/{universeId}/study-guide 展示合并后的实体、关系和学习指南。"
        ],
        "routes": [
          "parseDocument",
          "fetchSourceUrl",
          "incrementalSourceUpdate",
          "getUniverse",
          "getStudyGuide"
        ],
        "uiTargets": [
          "#add-knowledge-button",
          "#incremental-modal",
          "#incremental-drop-zone",
          "#incremental-token-list",
          "#incremental-pill",
          "#study-add-knowledge"
        ],
        "mutation": true
      },
      {
        "id": "ai-research",
        "title": "AI Research",
        "entry": "#research-button",
        "steps": [
          "打开研究对话框并输入问题或网址。",
          "网址先经 POST /api/sources/fetch 抓取。",
          "使用研究模式 POST /api/universes 创建新的知识宇宙。"
        ],
        "routes": [
          "fetchSourceUrl",
          "createUniverse",
          "getUniverse"
        ],
        "uiTargets": [
          "#research-modal",
          "#research-form",
          "#research-question"
        ],
        "mutation": true
      },
      {
        "id": "ask-ai",
        "title": "根据知识库上下文向 AI 提问",
        "entry": "#chat-form",
        "steps": [
          "选择实体并切换到 AI Explorer。",
          "提交问题到 POST /api/chat。",
          "渲染回答、引用证据和可执行的图谱或时间线动作。"
        ],
        "routes": [
          "chatWithUniverse",
          "getEntity"
        ],
        "uiTargets": [
          "#chat-form",
          "#chat-input",
          "#chat-history",
          "#ai-suggestions"
        ]
      },
      {
        "id": "research-report",
        "title": "生成或查看 AI 研究报告",
        "entry": "/research",
        "steps": [
          "在 /research 输入研究问题、主题或公开网址。",
          "账号模式调用 POST /api/research/runs 创建持久化六阶段研究任务。",
          "前端轮询 GET /api/research/runs/{runId} 展示每个 Agent 的阶段状态。",
          "完成后加载 GET /api/universes/{universeId}/research-report。",
          "报告展示执行摘要、关键实体、时间线、关系、证据、核验结果、结论和研究限制。"
        ],
        "routes": [
          "createResearchRun",
          "getResearchRun",
          "getResearchReport",
          "getUniverse"
        ],
        "uiTargets": [
          "#research-view-form",
          "#research-view-input",
          "#research-report",
          "#agent-run-console",
          "#agent-stage-list"
        ],
        "mutation": true
      },
      {
        "id": "workspace",
        "title": "保存研究材料到工作台",
        "entry": "/workspace",
        "steps": [
          "在实体 Wiki 或证据详情中保存实体和来源。",
          "工作台把数据保存在当前浏览器 localStorage。",
          "用户可以添加研究笔记并导出 Markdown。",
          "项目成员可以评论、解决评论、提交审阅，组织管理员批准或退回。"
        ],
        "routes": [
          "getUniverse",
          "getEntity",
          "getProjectCollaboration",
          "createProjectComment",
          "updateProjectComment",
          "submitProjectReview",
          "decideProjectReview"
        ],
        "uiTargets": [
          "#workspace-entity-list",
          "#workspace-source-list",
          "#workspace-note-list",
          "#workspace-export",
          "#workspace-collaboration",
          "#comment-list"
        ]
      },
      {
        "id": "account-and-team",
        "title": "注册账号、建立私有宇宙并邀请团队",
        "entry": "#account-button",
        "steps": [
          "注册或登录账号，系统创建账号会话和免费套餐额度。",
          "创建知识宇宙，数据默认私有并归属于当前账号。",
          "打开团队与共享，输入已注册成员邮箱并设置 viewer 或 editor。",
          "所有者决定是否开放公开读取；所有付费和团队数据仍保持账号隔离。"
        ],
        "routes": [
          "registerAccount",
          "loginAccount",
          "createUniverse",
          "upsertUniverseMember",
          "updateUniverse"
        ],
        "uiTargets": [
          "#account-modal",
          "#members-modal",
          "#share-universe-button",
          "#universe-visibility"
        ],
        "mutation": true
      },
      {
        "id": "organization-workspace-flow",
        "title": "创建组织并共享研究资源",
        "entry": "#organization-button",
        "steps": [
          "Team 或 Enterprise 账号创建组织 Workspace。",
          "组织 owner 或 admin 通过邮箱邀请 admin、editor 或 viewer。",
          "组织成员共享研究项目和知识宇宙，角色决定读取和写入权限。",
          "移除成员后，组织项目与知识宇宙权限立即同步收回。"
        ],
        "routes": [
          "createOrganization",
          "upsertOrganizationMember",
          "listResearchProjects",
          "createResearchProjectStored",
          "listUniverses"
        ],
        "uiTargets": [
          "#organization-modal",
          "#organization-select",
          "#organization-member-form",
          "#organization-member-list"
        ],
        "mutation": true
      },
      {
        "id": "research-governance-flow",
        "title": "事实核查、人工复核和报告交付",
        "entry": "#fact-check-button",
        "steps": [
          "在证据库触发 Wikidata 事实核查。",
          "系统把冲突、弱来源和无证据结论送入人工复核队列。",
          "复核人员确认、忽略或要求补充证据。",
          "Writer 输出带引用的 Markdown、Word 和 PDF 报告。"
        ],
        "routes": [
          "runFactCheck",
          "listReviewQueue",
          "updateReviewItem",
          "exportResearchReport"
        ],
        "uiTargets": [
          "#fact-check-button",
          "#review-queue",
          "#review-item-list"
        ],
        "mutation": true
      },
      {
        "id": "community-market-flow",
        "title": "发布市场、社区建议和个性化",
        "entry": "#market-button",
        "steps": [
          "知识宇宙所有者发布公开市场条目。",
          "其他账号可以提交社区建议或复制为私有知识宇宙。",
          "所有者审核社区建议并应用到实体、关系或备注。",
          "系统根据账号交互偏好生成个性化实体推荐。"
        ],
        "routes": [
          "publishUniverse",
          "listMarket",
          "forkMarketUniverse",
          "listPersonalization"
        ],
        "uiTargets": [
          "#market-modal",
          "#market-list",
          "#workspace-collaboration"
        ],
        "mutation": true
      },
      {
        "id": "add-entity",
        "title": "手动添加实体和关系",
        "entry": "#add-entity-button",
        "steps": [
          "打开实体对话框并填写名称、类型、摘要、关联实体和关系。",
          "POST /api/universes/{universeId}/entities。",
          "重新加载当前知识宇宙并选中新实体。"
        ],
        "routes": [
          "addManualEntity",
          "getUniverse"
        ],
        "uiTargets": [
          "#entity-modal",
          "#entity-form",
          "#entity-name",
          "#entity-type",
          "#entity-related"
        ],
        "mutation": true
      },
      {
        "id": "export-study-guide",
        "title": "导出学习笔记",
        "entry": "#export-study-guide",
        "steps": [
          "在学习视图打开已生成的学习指南。",
          "前端将指南转换为 Markdown 并下载为文件。"
        ],
        "routes": [
          "getStudyGuide"
        ],
        "uiTargets": [
          "#study-content",
          "#export-study-guide"
        ]
      },
      {
        "id": "delete-universe",
        "title": "删除知识宇宙",
        "entry": ".universe-delete",
        "steps": [
          "点击知识宇宙条目上的删除按钮。",
          "输入完整名称进行二次确认。",
          "DELETE /api/universes/{universeId} 删除数据和持久化文件。"
        ],
        "routes": [
          "deleteUniverse"
        ],
        "uiTargets": [
          "#delete-modal",
          "#delete-confirm-input",
          "#delete-confirm-button"
        ],
        "mutation": true,
        "destructive": true
      }
    ],
    "dialogs": [
      {
        "id": "create-modal",
        "purpose": "创建知识宇宙并添加资料。"
      },
      {
        "id": "entity-modal",
        "purpose": "手动添加实体和关系。"
      },
      {
        "id": "processing-modal",
        "purpose": "展示长书后台构建进度。"
      },
      {
        "id": "evidence-modal",
        "purpose": "展示来源和引用原文。"
      },
      {
        "id": "research-modal",
        "purpose": "输入 AI Research 主题或网址。"
      },
      {
        "id": "delete-modal",
        "purpose": "输入名称后进行破坏性删除确认。"
      }
    ],
    "keyboardShortcuts": [
      {
        "keys": "Ctrl+K or Cmd+K",
        "action": "聚焦全局搜索。"
      },
      {
        "keys": "ArrowUp / ArrowDown",
        "action": "在搜索结果中移动选择。"
      },
      {
        "keys": "Enter",
        "action": "打开当前搜索结果；在聊天框发送问题。"
      },
      {
        "keys": "Shift+Enter",
        "action": "在聊天框插入换行。"
      },
      {
        "keys": "Escape",
        "action": "关闭搜索结果。"
      }
    ]
  },
  "sourceMap": [
    {
      "path": "server.mjs",
      "role": "HTTP 路由、持久化、知识抽取、学习指南和聊天服务。"
    },
    {
      "path": "public/index.html",
      "role": "应用壳、视图、表单、对话框和全部静态 DOM 标识。"
    },
    {
      "path": "public/app.js",
      "role": "浏览器状态、API 调用、渲染、事件绑定和交互流程。"
    },
    {
      "path": "public/styles.css",
      "role": "响应式布局、组件样式、状态和移动端行为。"
    },
    {
      "path": "lib/documents.mjs",
      "role": "文档和电子书解析。"
    },
    {
      "path": "lib/llm.mjs",
      "role": "模型配置和 OpenAI 兼容调用。"
    },
    {
      "path": "lib/url-fetch.mjs",
      "role": "网页抓取、正文提取和 SSRF 防护。"
    },
    {
      "path": "lib/ai-audit.mjs",
      "role": "AI 项目清单、OpenAPI 和 llms.txt 生成器。"
    },
    {
      "path": "lib/editor-auth.mjs",
      "role": "公开读取模式下的编辑会话、密码校验和失败限流。"
    },
    {
      "path": "lib/accounts.mjs",
      "role": "商业账号、套餐配额、团队数据隔离、研究项目、审计与账号会话。"
    },
    {
      "path": "lib/search-agent.mjs",
      "role": "Tavily、Brave、Serper 和自定义提供商的可插拔联网检索层。"
    },
    {
      "path": "lib/research-runs.mjs",
      "role": "多 Agent 研究任务的持久化状态、阶段、进度、恢复和重试。"
    },
    {
      "path": "lib/research-pipeline.mjs",
      "role": "Research、Search、Extraction、Graph、Evidence、Writer 顺序编排器。"
    },
    {
      "path": "lib/billing.mjs",
      "role": "Stripe Checkout、Webhook 签名验证、订阅状态和套餐同步。"
    },
    {
      "path": "lib/collaboration.mjs",
      "role": "研究项目评论、解决状态、活动日志和审批工作流。"
    },
    {
      "path": "lib/storage.mjs",
      "role": "JSON 原子写入和读取工具，降低崩溃或并发写入造成的数据损坏风险。"
    },
    {
      "path": "lib/api-keys.mjs",
      "role": "组织级 Enterprise API Key 的哈希存储、scope 校验、过期和吊销。"
    },
    {
      "path": "lib/job-queue.mjs",
      "role": "持久化长任务队列：优先级、取消、定时重试、超时、预算和使用量。"
    },
    {
      "path": "lib/fact-checking.mjs",
      "role": "Wikidata、Crossref、OpenLibrary 外部事实核查和来源元数据验证。"
    },
    {
      "path": "lib/review-queue.mjs",
      "role": "人工证据复核、来源冲突检测和裁决工作流。"
    },
    {
      "path": "lib/source-verification.mjs",
      "role": "来源特征、可信度评分和人工反馈训练。"
    },
    {
      "path": "lib/entity-resolution.mjs",
      "role": "实体消歧、别名归一、合并冲突和关系重映射。"
    },
    {
      "path": "lib/incremental-updates.mjs",
      "role": "来源指纹、变更定位和增量知识合并。"
    },
    {
      "path": "lib/report-writer.mjs",
      "role": "Markdown、可编辑 DOCX 和带引用 PDF 报告生成。"
    },
    {
      "path": "lib/community.mjs",
      "role": "公开知识宇宙市场、社区建议和个性化图谱。"
    },
    {
      "path": "lib/storage.mjs",
      "role": "JSON 原子写入和读取工具，降低崩溃或并发写入造成的数据损坏风险。"
    },
    {
      "path": "scripts/ai-crawl.mjs",
      "role": "默认只读的 AI 项目爬取和审计报告生成器；支持账号／运维／cookie 三种凭据以审计开启登录门禁的站点，凭据不入报告。"
    },
    {
      "path": "tests/server.test.mjs",
      "role": "服务端、API、持久化和后台任务回归测试。"
    },
    {
      "path": "tests/frontend-regression.test.mjs",
      "role": "前端关键 DOM、交互入口和公开访问回归测试。"
    },
    {
      "path": "tests/url-fetch.test.mjs",
      "role": "网页抓取与 SSRF 边界测试。"
    },
    {
      "path": "tests/documents.test.mjs",
      "role": "文档解析回归测试。"
    },
    {
      "path": "tests/llm.test.mjs",
      "role": "模型配置与 API 协议测试。"
    },
    {
      "path": "tests/ai-audit.test.mjs",
      "role": "AI 审计目录、OpenAPI 和爬取脚本测试。"
    },
    {
      "path": "docs/PRD_COMPLIANCE.md",
      "role": "PRD、DOCX 审查结论与当前实现、剩余边界的对照表。"
    },
    {
      "path": "docs/COMMERCIAL.md",
      "role": "商业账号、套餐、配额、团队权限、安全边界和后续商业化路线。"
    },
    {
      "path": "docs/AI_AUDIT.md",
      "role": "AI 爬取、审计提示词和写操作隔离说明。"
    }
  ],
  "tests": [
    {
      "command": "npm test",
      "purpose": "运行全部自动化测试。",
      "mutatesData": false
    },
    {
      "command": "npm run test:model",
      "purpose": "调用真实模型执行端到端检查。",
      "mutatesData": false,
      "cost": "model"
    },
    {
      "command": "npm run audit:ai",
      "purpose": "对本机服务执行默认只读的完整接口爬取并生成报告。",
      "mutatesData": false
    },
    {
      "command": "npm start",
      "purpose": "启动生产服务器。",
      "mutatesData": false
    },
    {
      "command": "npm run dev",
      "purpose": "以 watch 模式启动开发服务器。",
      "mutatesData": false
    }
  ],
  "auditPrompt": [
    "你是资深安全与质量审计员。先读取 manifest 和 OpenAPI，再对公开站点执行只读爬取。",
    "按 API、前端流程、持久化、模型调用、文档解析和网页抓取六个维度检查。",
    "每个问题必须给出严重级别、复现步骤或请求、实际结果、预期结果、源码定位和修复建议。",
    "优先报告可复现的安全漏洞、数据损坏、并发竞态、成本放大和用户可见故障。",
    "不要在公开生产实例上执行创建、重试、添加实体、强制生成学习指南或删除操作。"
  ]
}