23 KiB
需求清单
平台的需求权威索引与裁决档案:以「不依赖 NewAPI 平台管理员与用户体系的独立计费平台」为定位,按功能域记录平台做什么、不做什么、为什么(裁决脉络见 §9)。后续专门设计文档(API 契约 / 交互 / 引擎)回答「怎么做」;R 编号体系是被引用的锚点。R3 / R4 延后项存档于 §9,核心功能实现后重启;新需求按 R 体系增补。
| 项目 | 内容 |
|---|---|
| 状态 | 定稿(2026-10-01;R16 定稿 2026-10-10) |
| 关联 | README.md(背景、动因与架构约束)· 各篇表字段设计 · docs/references/NewAPI-接口范围.md(可用接口参考) |
| 取代 | 《设计议题》(2026-09-29 由本清单取代;其中双形态裁决与 CFW 调研结论已并入本文 §5/§7) |
0. 平台定位与背景
定位:不依赖 NewAPI 平台管理员与用户体系的独立计费平台。上游只提供 sk-key 级接口——没有账单、没有分摊、没有历史回填,一切计费性质的能力(采集、归集、折算、分摊、账单)都必须由平台自身承载。上游接口的完整实证见 docs/references/NewAPI-接口范围.md。
平台哲学(2026-09-29 裁决):平台不做价值判断,只提供事实服务——「谁该付谁多少钱」的分摊口径是人和人之间的事;平台提供分账所需的全部原材料(用量事实、来源标注、支付记录、多维统计),数字全部客观中立。
背景(三类问题促成当前设计阶段):
- 迭代部署成本:服务器部署形态下每次迭代都需实例运营方手工升级,测试阶段迭代频繁而运营方无暇跟随 → 双形态交付(R13,已裁决)
- 刻意收缩后重新纳入的部分:管理面固定口令不妥(R11)、充值折算(R7)、多订阅处理(R8)
- 已知设计问题:错误行
request_id去重(R15 必修项)
1. 数据采集域
| # | 需求 | 说明 | 状态 |
|---|---|---|---|
| R1 | sk-key 轮询采集与攒库 | 定时轮询 key 级接口、request_id 去重、全量日志入库——架构动因(上游无时间范围过滤接口)是物理约束,实现细节开放讨论 |
已裁决(2026-10-01,随 R15 表设计审阅定稿) |
| R2 | key 登记与生命周期 | 管理通道登记、手动启停(status 纯手动开关,引擎只读);401 等持续失败经引擎日志与数据截止显形,停用由作者手动执行(不做自动摘除——引擎记录、不决策) |
已裁决(2026-09-29,随 R15 审阅) |
2. 数据资产域(新增)
本地库是全量日志的唯一副本(上游不提供回填);上游窗口仅最近 1000 条(实测当前速率 ≈ 3 天),同步停摆超过窗口即永久丢数据。「不依赖上游」的直接推论:资产保护是平台自己的责任。
| # | 需求 | 说明 | 状态 |
|---|---|---|---|
| R3 | 数据资产保护 | 备份 / 导出 / 恢复策略——平台核心资产不能只有单副本 | 延后(2026-09-29 裁决:核心功能实现后再议;提案存档见裁决记录) |
| R4 | 采集健康与告警 | 同步停摆告警、数据连续性校验——3 天窗口的不可逆风险需要可观测兜底 | 延后(2026-09-29 裁决:核心功能实现后再议;提案存档见裁决记录) |
3. 计费域
| # | 需求 | 说明 | 状态 |
|---|---|---|---|
| R5 | 用量查询 | 时间范围 / 明细与汇总;查询入口已归位——成员视图(令牌)与管理面总览/下钻(口令),「凭 sk-key 的开放查询」已裁撤(见裁决记录 2026-09-29);统计维度含按 key / 成员 / 计费来源 / 模型(见 R9) | 已裁决(2026-10-01,数据层随表设计定稿;查询口径细节归 API 契约) |
| R6 | 美元换算与支付记录 | 重定义(2026-09-29):① quota → 额度美元换算(÷ quota_per_unit,qpu_history 时间线服务它)——纯客观单位换算,保留;② 裁撤每行日志的实付分摊金额(amount_rmb,「quota 占比 × 实付」)——它是分摊口径的派生值,随购买记录漂移,违反事实服务原则;③ 支付记录登记:支付金额 ↔ 额度的比率关系(币种无关——系统不预设币种,见 R9) |
已裁决(2026-09-29,重定义) |
| R7 | 充值登记 | 重定义(2026-09-29):充值与订阅同构——支付记录(金额 + 额度 + 比率)+ 日志来源标注(billing_source)+ 按来源统计;同样不做充值用量的金额分摊(原「池子加权平均」方案裁撤) |
已裁决(2026-09-29,重定义) |
| R8 | 多订阅并行处理 | 重定义(2026-09-29):① 支付记录允许多订阅期间重叠(不设互斥约束)② 日志-支付记录按 subscription_id 直连(上游标注的客观事实,不推算)——「整笔订阅一把尺」原则已随 amount_rmb 裁撤消亡,订阅维度无需任何「尺」③ 按订阅分组的统计为查询时聚合输出(非物理表——账本只存事实行,统计是随查随算的派生视图);「未关联订阅」为 LEFT JOIN 未匹配集的透明分组(无新字段,正常时恒为零——非零即异常信号:缺登记或上游行为变化),兼作数据健康指示器;扣费顺序(先旧后新等)是上游策略,日志忠实记录,平台不管 |
已裁决(2026-09-29,重定义) |
| R9 | 分摊原材料与多维统计 | 重定义(2026-09-29):平台不做应付款计算、不做分摊口径(闲置额度归谁之类是社交层问题)——只提供原材料:计费来源标注(billing_source:订阅 / 充值)、支付记录(币种无关:支付金额与额度之间的比率关系,不预设币种)、任意时段多维聚合(按 key / 成员 / 来源 / 模型) |
已裁决(2026-09-29,重定义) |
| R10 | 已裁撤(2026-09-29):周期 = 任意查询时段(订阅期间为预置选项);无平台侧账单(应付款不计算,期末快照无对象)。保留行以维持编号连续 | 已裁撤 |
4. 使用者域
平台自身的身份体系——实际使用者 ≈ 作者(管理)+ 若干分摊成员(查询)+ 运营方(信任模型内,本就能看到一切)。这不是多租户产品。
| # | 需求 | 说明 | 状态 |
|---|---|---|---|
| R11 | 平台身份体系与鉴权 | 访问主体 = 作者 + 成员(运营方完全信任,不设身份)。成员身份与管理面鉴权均已裁决(2026-09-29,见裁决记录) | 已裁决(2026-09-29) |
| R12 | 成员自助视图 | 令牌进成员视图:名下 key 的模型调用日志——每条记录额外携带所属订阅/充值的信息(具体携带形态待核查后设计)+ 用量聚合(quota / 美元,按来源分解);支付参数同账本域内可见(同域透明、跨域隔离;未标域默认藏,详见各表 billing_domain 与《API契约-成员视图》§5);无「应付」概念(分摊是社交层问题);登录壳交互(输令牌 → sessionStorage,关标签失效) |
已裁决(2026-09-29;2026-10-13 补账本域可见性) |
| R16 | 成员档案维护与空壳删除 | 修改:开户后可改 name / remark(误建、挂 key 前改名等真实场景);status 走启停、令牌走重发,不并入档案编辑。删除:仅当当前无任何 key 归属(key_count = 0)才允许硬删——清理空壳,不触碰账本事实;名下有 key 只能停用(软删除语义不变) |
已裁决(2026-10-10) |
5. 交付域(已裁决)
| # | 需求 | 说明 | 状态 |
|---|---|---|---|
| R13 | 双形态交付 | 完整前后端(先行,母体):服务器部署的前后端分离应用 + PostgreSQL(apps/server 承载 API 路由,apps/engine 独立进程同步——见《同步引擎设计》2026-10-05),功能全集在此形态上设计与实现;CFW 抽取版(后续,衍生):Cloudflare Workers(API + Cron Triggers 轮询)+ D1 攒库 + 前端静态资产托管,从母体中抽取业务核心、替换基础设施层——承载「部署权归作者」的目标形态 |
已裁决(2026-09-29;进程拆分修订 2026-10-05) |
| R14 | 可移植性分层 | R13 的横切约束:业务核心(轮询逻辑 / request_id 去重 / 折算链计算 / 加密体系 / API 语义)与形态耦合面(HTTP 框架 / 调度器 / 数据库驱动 / 托管部署)分离;数据访问层隔离 PostgreSQL 与 SQLite/D1 方言(jsonb → TEXT + SQLite JSON 函数、类型与索引映射);轮次语义统一(幂等、错过即补——每轮全量拉最近 1000 条天然补偿) |
已裁决(2026-09-29) |
6. 数据模型
| # | 需求 | 说明 | 状态 |
|---|---|---|---|
| R15 | 数据模型修订 | 表字段设计经作者逐篇审阅定稿(2026-10-01);其后 payments 按 2026-10-09 裁决拆为 subscriptions + topups(见裁决记录)——基线域现为 api_keys · usage_logs · subscriptions · topups · qpu_history + 访问主体三表 |
已裁决(2026-10-01;2026-10-09 拆表修订) |
7. R13 的支撑材料:CFW 可行性调研(2026-09-29,developers.cloudflare.com 官方文档核实,五项全部无阻断)
| # | 调研点 | 结论(Workers Free / Paid) |
|---|---|---|
| 1 | Cron 粒度与补偿 | */5 * * * * 支持(最小每分钟);UTC 执行;单次执行上限 15 分钟;controller.scheduledTime 可检测延迟;失败重试机制存在(noRetry() 可关);Cron Events 留存最近 100 次调用(可观测) |
| 2 | D1 限制 | 单库 500 MB / 10 GB;每 Worker 调用查询数 50 / 1000;单条 SQL ≤ 100 KB、绑定参数 ≤ 100/语句;库为单线程(写入串行)——本项目低频批量写入无碍 |
| 3 | Workers 运行时 | CPU:10 ms(网络等待不计)/ 30 s(<1h 间隔 cron;≥1h 为 15 min);外网子请求 50 / 1000 每调用;出站并发 6;Cron Triggers 每账号 5 / 250 |
| 4 | 免费额度 | Workers Free:10 万请求/天;D1 Free:读 500 万行/天、写 10 万行/天、存储 5 GB;静态资产请求免费无限(前端托管零成本) |
| 5 | 加密体系 | Workers 完整实现 Web Crypto:HKDF ✓ / AES-256-GCM ✓ / HMAC-SHA256 ✓(原生加速)——SK_KEY_ENCRYPTION_SECRET 体系可平移 |
负载画像对照(key 数按 10–25 估):
- 每轮 cron:外网子请求 = 2 × key 数(Free 上限 50 → 最多 25 key);CPU 主要花在 1000 条 JSON 解析 + SHA-256 指纹 + AES-GCM 解密——Free 10 ms 是唯一贴线风险点(实现期实测,超限则升 Paid)
- D1 写入:5 分钟一批、日增千行级 ≪ 10 万行/天;存储日增 MB 级 → Free 500 MB 可撑约两年,Paid 10 GB 富余
- 查询面:个人低频聚合查询 ≪ 500 万行读/天(时间范围需走索引避免全表扫描)
- 同步引擎防重入:D1 单线程天然串行化写入,多 cron 并发触发无竞态风险;每轮幂等(
request_id去重),失败重试零副作用
8. 推进方式
需求阶段收官(2026-10-01):15 项全部有归宿——R1 / R2 / R5 / R6 / R7 / R8 / R9 / R11 / R12 / R13 / R14 / R15 已裁决关闭,R10 裁撤,R3 / R4 延后(提案存档见 §9)。表字段设计与交互设计均经作者逐篇审阅定稿;其后 API 契约与同步引擎设计亦已立稿。
增补(2026-10-10):R16(成员档案维护与空壳删除)已裁决——成员操作面由「开户 / 启停 / 重发」扩为含档案修改与条件硬删;随 members / API / 交互三线落地。
9. 裁决记录
2026-09-29 · 访问主体模型(R11 · R12 · 关联 R5)
访问主体 = 作者 + 成员,一个模型两种凭证(运营方完全信任,不设身份;CFW 版可将来叠加 Cloudflare Access 作为前置纵深,不作鉴权主体)。
成员侧(成员视图):
- 成员实体(新增):基本用户字段(
id/name显示名 /remark备注 /status启停 /created_at)+ 受管理凭证(token_hash哈希存储 +token_issued_at;生成时明文展示一次,可吊销、可重发)+ key 归属(api_keys.member_id,1:N,允许空——未归属 key 存在) - 一层成员模型:key 创建权始终在作者(唯一 NewAPI 账号持有人);归属登记即层级——成员向下拼车 = 作者开新 key 挂其名下,平台不感知下级;算账口径 = 成员名下全部 key 的计费总和
- 成员视图:登录壳(输入令牌 → sessionStorage,关标签失效)→ 自己关联的 key 列表 + 每 key 计费 + 聚合(应付部分随 R9 裁决展开)
- 成员侧无注册、无密码、无会话;令牌泄露处置 = 作者吊销重发(朋友信任关系下凭证事务经作者,路径短于自助改密)
管理面侧(作者,唯一管理员)——最小登录体系:
- users 表(单行:作者
username+password_hash)+ sessions 表(随机 256bit 令牌哈希存储、expires_at如 7 天、登出即删,随时可踢) - 密码哈希 = PBKDF2-SHA256(WebCrypto 原生,高迭代)——Workers runtime 无 argon2/bcrypt,PBKDF2 是两形态统一实现(R14 的落地细节)
- 浏览器侧:
HttpOnly + Secure + SameSite=Laxcookie,路径限管理面——替代手动凭证管理 - 部署期初始化(空库双通道):初始用户名/密码经 env(母体)/ wrangler secret(CFW)传入;管理面入口幂等三态判断——非空 → 登录页;空库 + env 凭证在 → 静默落库(部署完成即就绪,无抢注窗口;母体启动 / 首次请求检查,CFW 首次请求 / 首次 Cron 检查);空库 + env 凭证无 → 引导页设新密码(重置兜底通道)
- 初始凭证为引导性质:仅空库时生效,此后改 env 不改密;改密走登录后的表单(旧密码验证 → 落库,登录体系的基本配套);env 凭证可留可删、无依赖——留着:删
users行即静默重建;删了:引导页当场设新密码(见users表字段设计.md3.1);抢注窗口仅存在于「删 env + 删行」的重置瞬间 - 无注册、无找回(忘记密码 = 服务器改库,管理员特权);登录节流为最小实现(失败延迟/计数)
- 基线三件套状态修正:作者侧登录页与会话解禁(最小形态);admin 角色不做(单管理员无角色引擎用武之地);成员侧维持令牌无会话
开放查看面裁撤(同日裁决):「凭 sk-key 查」入口取消——sk-key 明文从 web 界面消失(仅登记时输入一次、随即加密);场景归位:成员 → 令牌视图;作者 → 管理面(key 清单下钻 + 全员总览面板,总览为新增设计项)
审计日志(独立需求,与鉴权方案正交):管理面写操作(key 登记/启停、购买记录增删改、成员开户/停用、令牌签发/吊销、改密)逐条留痕:操作类型、时间、操作者(前向兼容多管理员扩展——审计是不可变历史,归属不能事后补写;系统触发事件如空库重建为 NULL)、关键内容摘要;属业务核心层,两形态共有。同理正交的还有同步引擎运行日志——记录语义两形态一致,落盘通道随形态(母体 stdout/journald,CFW Workers Logs)
2026-09-29 · 分摊哲学与原材料(R9 重定义 · R10 裁撤 · R6/R7 重定义 · R12 形态修正)
平台不做价值判断,只提供事实服务——「谁该付谁多少钱」是人和人之间的社交问题;平台提供分账所需的全部原材料,数字全部客观中立。
裁掉:
- 应付款计算与分摊口径——「闲置额度归谁」这类没有客观答案的问题,平台不回答(「按占额度分摊」vs「按占总用量分摊」的口径之争随之消失)
- 期末账单快照与周期管理(R10 裁撤)——周期 = 任意查询时段(订阅期间为预置选项),无平台侧账单
- 每行日志的实付分摊金额(
amount_rmb)——「quota 占比 × 实付」是分摊口径的派生值而非事实,且随购买记录修订漂移;明细行金额回归 quota + 额度美元(÷quota_per_unit,qpu_history时间线,纯客观单位换算);基线「查看面金额口径 = 折算实付人民币」的设计作废
保留与新增:
- 支付记录(订阅与充值同构):支付金额 ↔ 额度的比率关系——币种无关(系统不预设人民币或其他币种,币种是使用者之间的约定);订阅与充值两类支付事件统一建模(表结构与命名随 R15)
- 计费来源标注为一等维度:
billing_source(订阅 / 充值)随日志解析存储;按来源 / 成员 / key / 模型的任意时段多维聚合 - 充值登记(R7 重定义):与订阅同构——不做充值用量的金额分摊(原「池子加权平均」方案裁撤)
- 成员视角(R12 形态修正):名下 key 的模型调用日志,每条记录额外携带所属订阅/充值的信息(具体携带形态待核查后设计)、支付参数同账本域内可见、无「应付」概念
2026-10-01 · R15 审阅定稿
表字段设计经作者逐篇审阅,全部定稿。审阅期实质修订:key_id → api_key_id、note → remark、401 自动摘除状态机裁撤(api_keys 3.6——引擎记录不决策,status 纯手动开关)、管理员初始化与重置改为空库双通道(users 3.1——env 静默重建 / 引导页兜底,env 凭证降级为可弃);另有多处语义辨析随文入档(错误行去重指纹、量与换算率、sessions 与 members 零关系、QPU 存在必要性裁决保留)。
2026-10-01 · 交互设计定稿
交互设计八篇(共性 / 登录 / 总览 / key / 支付 / 成员 / 审计 / 成员视图)经作者逐篇审阅,全部定稿。审阅期修订:
- 纯用量模式(共性 §3.8,部门实例场景触发):无支付记录 = 完整可用子集——参数卡中性空态、展开行降级、核对提示全空静默、订阅期间快捷项隐藏
- 响应式范围收缩(作者裁决):只做布局响应,不做组件响应与移动端 UI 重设计
- 组件能力需求清单(共性 §3.7):组件库与前端框架归实现期自由度,本清单为选型验收标准
- 审计日志保留操作者列:前向兼容多管理员——审计是不可变历史,操作者归属不能事后补写;系统触发事件为 NULL
- 其余:成员视图「移动端优先级」随响应式裁决改为「窄屏说明」;Key 登记对话框补「+ 新建成员」快捷入口;统计容器表述「桶」统一为「分组」
2026-09-29 · 多订阅并行(R8 重定义)
- 「一把尺」原则已随
amount_rmb裁撤消亡——其唯一客户是分摊金额计算;quota → 美元走 QPU(站点参数),订阅维度无需任何「尺」 - 日志归属 = 上游事实,非推算:日志
other.subscription_id直接关联支付记录(实现期核查项:登录态钱包页的订阅编号与日志subscription_id是否同一体系——基线草案既有推测,与 R12 携带形态并作一批真实数据核查) - 未关联分组 = 查询层产物(LEFT JOIN 未匹配集,无新字段),正常时恒为零,非零即异常信号;两种未关联(日志缺 ID / 有 ID 无登记)的展示区分留设计期
- 统计 = 派生视图:数据库只存事实行,一切分组/分解/汇总为查询时聚合,无预计算存储
2026-10-09 · 支付建模拆表
- 裁决:
payments单表拆为subscriptions(订阅权益)+topups(充值入账事件)——paid_at在订阅行上语义污染(更像登记时刻),后补录无法按付款时间对齐用量窗口;对齐 NewAPI「权益 vs 入账」两分(评估见payments建模评估.md) - 三时刻钉死:
created_at(登记)·paid_at(钱出手,订阅可空)·period_*(用量覆盖期);筛选:订阅看期间重叠、充值看paid_at、补录看created_at - 展示仍称「支付记录」:管理面一菜单两 Tab;成员「支付参数」两组清单;R7/R8/R9 哲学不变(只存事实、
subscription_id直连、币种无关) - 原
payments表字段设计.md删除,由两篇表设计替代;契约与交互随拆表修订
2026-10-10 · 成员档案维护与空壳删除(R16)
动机:开户后挂 key 前发现名称不对(误建、占位名)——改比重发/重建好(令牌已发出时重建会作废旧令牌);另有从未使用的开户空壳需要清理,停用行会越积越多。
裁决:
- 修改成员档案:允许改
name/remark两字段。status与令牌不并入档案编辑(仍走启停 / 重发,生命周期语义不变);id/created_at/token_hash/token_issued_at不可直接改。name仍 UNIQUE(账目署名不可歧义,members 3.3);冲突409 member_name_taken。展示口径 = 当前名(日志 / 总览 / 成员视图联查实时取members.name,与 key 的token_name同则——历史账目署名随改名漂移可接受) - 删除成员(条件硬删):仅当
key_count = 0(当前无任何api_keys.member_id指向) 才允许物理删除。理由:用量事实经 key 归属联查,空壳行不承载任何账本事实;硬删释放 UNIQUE 名称,便于「删了重建」。名下有 key → 拒绝删除(409),只允许停用——软删除仍是账本实体的默认语义,硬删只是空壳例外 - 与支付删除的分界:支付记录是人工抄录、改错即修(全 CRUD);成员是账本锚点,默认软删除——空壳硬删不突破该哲学(无账本可保)
- 审计:
member.update(改名/改备注,按实际变更字段落痕)·member.delete(摘要含删除时名称);均属管理面写操作
2026-09-29 · 数据资产域延后(R3 / R4)
裁决:不纳入现阶段(锦上添花能力,核心功能实现后再议)。提案存档如下,供重启讨论时作起点:
- R4 采集健康与告警(三层提案):① 同步健康面板(数据截止 / 轮次成败 / 引擎状态——即管理面总览的一部分)② 缺口检测与留痕(停摆恢复轮检测时间缝隙,落「数据缺口事件」记录——丢了多少无法精确知道,但「丢过」可精确留痕)③ 主动告警(webhook 推送,作者自配钉钉/企微/TG bot;停摆判定 = 连续 N 轮失败或数据截止落后超阈值;不做邮件、不做分级路由)
- R3 资产保护(导出 + 备份 + 异地性提案):① 管理面一键导出(全量日志 JSONL + 支付记录 + 归属)② 形态差异——母体 pg_dump 定时 + 作者定期拉取;CFW 版 D1 Time Travel(PITR:付费 30 天 / 免费 7 天)+ wrangler d1 export ③ 异地性三选(作者手动拉起步 / 推 R2 对象存储 / 只信 Time Travel),倾向手动拉起步、导出与推送逻辑分离留升级口子