01 底座模块
1. 仓库结构
monorepo/
├── core/
│ ├── auth/ billing/ storage/ jobs/ notify/ audit/ analytics/
│ ├── labeling/ # AI 标识
│ ├── compliance/ # 年龄、内容安全、授权、删除、休息提醒
│ ├── gateway/ # 模型网关(见 02)
│ └── growth/ # 增长组件(见 03)
├── media/audio/ media/video/
├── products/pixorder/ products/sonicflow/ products/talktale/
├── web/ miniapp/ deploy/ tests/
依赖方向:products → core / media;core 不依赖任何产品;产品之间互不依赖(01 复用 02、03 的能力时,通过 core.gateway 和 media 调用,而不是 import 另一个产品的代码)。
2. 配置
全部走环境变量。关键项:
| 变量 | 说明 |
|---|---|
REGION |
global / cn |
DATABASE_URL、REDIS_URL |
|
STORAGE_* |
R2 或 OSS |
GATEWAY_CONFIG |
模型网关配置文件路径(见 02) |
MOR_PROVIDER、MOR_* |
海外代理商户 |
WECHAT_PAY_*、WECHAT_MINIAPP_* |
国内 |
CONTENT_PRODUCER |
隐式标识里的服务提供者名称或编码 |
ALERT_WEBHOOK |
告警(企业微信 / Slack / Telegram 任选) |
3. 账号 core/auth
| 区域 | 登录方式 |
|---|---|
| global | 邮箱魔法链接;Google 登录(可选) |
| cn | 微信登录(小程序 wx.login);手机号验证码 |
- 匿名优先:02 的预览、03 的免费工具都允许不登录使用,付款或保存作品时再绑定账号(匿名会话里的数据自动合并过去)
- 管理员:密码 + TOTP,会话 12 小时
- 表:
core.users(id, region, email, phone_enc, wechat_openid, birth_year, created_at),以及core.sessions
4. 支付 core/billing
统一接口:
class PaymentProvider(Protocol):
name: str
def checkout(self, *, user_id: str, product: str, sku: str, amount_cents: int,
currency: str, mode: Literal["payment", "subscription"],
metadata: dict) -> CheckoutSession: ...
def parse_webhook(self, headers: dict, body: bytes) -> list[BillingEvent]: ...
def refund(self, payment_id: str, amount_cents: int, reason: str) -> None: ...
def cancel_subscription(self, sub_id: str) -> None: ...
| 实现 | 区域 | 说明 |
|---|---|---|
mor(Creem / Paddle / Lemon Squeezy 其中之一) |
global | 第 0 周确认哪家接受中国居民(个人或公司)入驻;费率约 3.9%+$0.3 至 5%+$0.5 |
wechat |
cn | JSAPI(小程序)+ H5;需要公司主体和商户号。只用于实物和 Android / 网页端 |
wechat_virtual |
cn | 微信"小程序虚拟支付":iOS 小程序里购买电子版、订阅、额度等虚拟商品时必须使用(有平台费,计入成本);接入条件、费率、支持的商品类型以微信当期规则为准,第 0 周确认 |
card_key |
cn | 闲鱼卡密(02 电子版) |
app_store |
两个区域 | 01 上架 App 后用应用内购买(RevenueCat 统一管理) |
统一的事件:payment.succeeded、payment.refunded、subscription.started / renewed / canceled / past_due。
表:
CREATE TABLE core.payments (
id TEXT PRIMARY KEY, user_id TEXT, product TEXT NOT NULL, sku TEXT NOT NULL,
provider TEXT NOT NULL, external_id TEXT NOT NULL,
amount_cents INT NOT NULL, currency TEXT NOT NULL, status TEXT NOT NULL,
ref_kind TEXT, ref_id TEXT, -- 关联到产品侧的订单
raw JSONB, created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE (provider, external_id)
);
CREATE TABLE core.subscriptions (
id TEXT PRIMARY KEY, user_id TEXT NOT NULL, product TEXT NOT NULL, plan TEXT NOT NULL,
provider TEXT NOT NULL, external_id TEXT NOT NULL UNIQUE,
status TEXT NOT NULL, current_period_end TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE core.entitlements ( -- 产品统一查这里判断权限和额度
user_id TEXT NOT NULL, product TEXT NOT NULL, key TEXT NOT NULL, -- 如 'pro', 'songs_month', 'season:s1'
value JSONB NOT NULL, expires_at TIMESTAMPTZ,
PRIMARY KEY (user_id, product, key)
);
所有回调都以 (provider, external_id) 做幂等;产品代码只读 entitlements,不直接判断订阅状态。
5. 存储 core/storage
- 预签名直传和下载;大文件分片上传(S3 兼容接口)
- 对象键:
{product}/{kind}/{yyyy}/{mm}/{owner_id}/{uuid}.{ext},键里不出现个人信息 - 生命周期(按前缀):
tmp/1 天;preview/7 天;upload/30 天;deliver/30 天;content/(01 的剧集素材)永久 - 按对象延期:以下对象不适用前缀的默认期限,由产品在元数据里写入
retain_until,删除任务以它为准: - 02 的印刷文件(
print/):保留到"签收后 45 天"(覆盖 30 天售后期 + 重印处理时间) - 03 付费用户的源文件:90 天(用户付费时,对其已有作品自动延期)
- 产品判断购买行为时,按平台区分支付方式:iOS 小程序的虚拟商品 →
wechat_virtual;其余 →wechat
6. 队列 core/jobs
| 队列 | 消费者 |
|---|---|
core.cpu |
通知、删除、打包、支付后处理 |
pix.gen |
02 生成、质检、放大(主要是调用 API,CPU worker 即可) |
snd.cpu / snd.gpu |
03 音频 |
tt.content / tt.runtime |
01 内容生产 / 运行时 |
media.video |
视频渲染 |
规则:任务函数必须幂等;默认重试 1 次,之后进死信队列并告警;GPU worker 不直连数据库,完成后投递 record_job_result 任务到 core.cpu(RQ 的回调在执行任务的进程里运行,所以不能用来写库)。
7. 通知 core/notify
| 渠道 | 用途 |
|---|---|
| 邮件(海外) | 交付、物流、召回、周报 |
| 微信订阅消息(国内) | 同上(用户需要先授权订阅) |
| 网页推送 | 01 的角色消息 |
| 告警 Webhook | 给运营者自己 |
模板存在数据库里,按 (product, template_id, locale) 管理。
8. AI 标识 core/labeling
依据《人工智能生成合成内容标识办法》(2025-09-01 施行),并满足欧盟 AI 法案和 Etsy 等平台的披露要求。
| 函数 | 说明 |
|---|---|
badge_image(img, text) |
显式角标 |
watermark_preview(img) |
预览图全屏水印 |
label_file(path, content_id) |
隐式标识:PNG tEXt / JPEG XMP / MP3 ID3 / WAV RIFF / MP4 元数据 |
spoken_disclosure(audio) |
合成语音类内容开头的语音提示(03 声音克隆、01 如有需要) |
隐式标识字段按国家标准《网络安全技术 人工智能生成合成内容标识方法》的要求实现,开发时以标准原文为准。
9. 合规组件 core/compliance
| 能力 | 说明 |
|---|---|
| 年龄确认 | 首次使用时询问出生年份;按区域和产品配置门槛(01:13 岁以上,未成年人受限;02:16 岁以上;03:13 岁以上,13~17 岁不开放声音克隆)。欧盟部分国家对 16 岁以下处理个人数据要求监护人同意,按国家配置 |
| 内容安全 | 输入和输出都检查(文本、图像、音频转写文本);国内接入已备案的内容安全服务 |
| 授权存证 | consents(user_id, product, kind, text_version, ip, ua, at) |
| 数据删除 | 按生命周期自动删除 + 用户主动删除账号(30 天内完成) |
| 休息提醒 | 01 使用:连续使用超过 3 小时(国内 2 小时)提醒 |
| 危机处理 | 01 使用:检测到自伤、自杀相关表达时中止对话,给出当地求助资源 |
10. 审计 core/audit
只追加的 core.audit_log,记录:授权、退款、删除、内容安全拦截、异常队列里的人工操作、网关熔断。
11. 异常队列
core.exceptions(id, product, ref_kind, ref_id, reason, detail, status, created_at, resolved_at)
- 各产品按规则写入;后台只有一个统一页面
- 积压超过 10 条,或最旧一条超过 24 小时 → 告警
- 日报统计原因分布,用来改进自动化规则
12. 分析 core/analytics
事件统一命名为 {product}.{object}.{action}(例如 pix.preview.generated、snd.song.exported、tt.episode.completed)。海外发送到 PostHog;国内写入自部署实例。每个产品 PRD 里的数据指标都必须能从这些事件算出来。