Commit Graph

686 Commits

Author SHA1 Message Date
zerosaturation
a337f43f86 fix(config): port alignment + service test doubles (batch 4.1/4.5)
- gateway/config Dubbo URL 默认端口修正(原 20004/20005 与服务实际 20001/20004 不符);
- userService main.go 硬编码 WithPort(20000) 修死码, -port flag / PORT env 真正生效;
- .env.example 11 个 DUBBO URL 同步(对齐 serviceDefaultPorts map + 实际服务 bind);
- 删除 DUBBO_STARBOOK_SERVICE_URL 死引用(starbookService 已在 batch 4.2 删除);
- .env.example Service Ports 注释块补全 10 行, 与网关 Dubbo URL + port_test 三方一致;
- 10 个 service 各加 port_test.go, 断言 flag 默认与 serviceDefaultPorts map 一致;
- 11 个 port_test 总计 13 测试覆盖(网关 + 10 service);
- .gitignore 加 userService/main.go.bak 排除(临时备份)。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 14:02:14 +08:00
zerosaturation
9d538251b6 chore(gitignore): exclude userService/main.go.bak
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-24 14:02:07 +08:00
zerosaturation
e1326acaf9 fix(backend): service stability — bcrypt off-txn / login anti-enum / MQ stub / aiChat / event reliability / gateway aggregate (batch 3)
- 3.1 bcrypt 移出事务 (Register): repository.HashPassword 前移到 db.Transaction 之前,消除连接池占用。
- 3.2 Login 消除用户枚举 + 限流 + timing 抹平: pkg/errors 加 ErrInvalidCredential
  /ErrTooManyLoginAttempts; 用户不存在/密码错/密码空 三路径统一返回同一错误;
  mobile 5次/ip 20次 per 15min 限流 (Redis, fail-open 降级); user-not-found 走
  dummy bcrypt 抹平 ~100ms 时序差,完全消除枚举侧信道;空密码分支已核实无时序 leak。
- 3.3 MQ streams adapter 停用 → stub: 0 业务调用方, 新 stub EventProducer.Publish no-op;
  pkg/mq/mq.go Init 不再装配 streams; 全仓 grep 验证 11 处硬编码
  'gallery'/'default' 集中到 pkg/queue/consts (值不变, 仅消漂移)。
- 3.5 JWT 密钥治理: pkg/jwt MustInit fail-fast + atomic.Value (见上一个 commit 293c7b1)。
- 3.6 aiChat 健壮性: SaveContext 用 persona.ID(非 req.PersonaId); Redis/memory 错误
  记 WARN 不静默; Dify err 映射稳定用户文案,原始 err 仅服务端日志。
- 3.7 statistic.Client 重构: TrackEvent 改 buffered channel (cap 1024) + dispatchLoop
  worker; 失败 ERROR 日志带字段; drop 记 WARN; Close 可重复调用。
- 3.8 网关聚合: StarCache (60s TTL, singleflight) 替换 5+ 处 GetFanIdentities 链式调用;
  DeleteAccount 改网关直调 userService.DeleteAccount(避免改 hand-written triple.go
  风险,见报告 §5 proto 风险复盘); 铸造双写改异步 channel+consumer (3 retry)。
- 大量单测: 各子项 TDD (RED→GREEN), 关键并发 race_test (50 goroutine)。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 18:50:40 +08:00
zerosaturation
293c7b14ae fix(security): JWT key governance — MustInit fail-fast + atomic.Value
- pkg/jwt: 删 public SetSecret; 加 MustInit(secret string) 启动时强制注入,
  缺/为空/等于弱默认值时返回 error(运行期不可再改); 密钥用 atomic.Value
  存 []byte,所有读走 mustSecret() 原子 Load,消除 SetSecret/ParseToken 并发
  data race(go test -race 零告警)。
- gateway main + auth_provider: 启动时 MustInit 读 JWT_SECRET env,失败 fatal。
- scripts/loadgen/seed/tokens: 同步 MustInit。
- .env.example: JWT_SECRET 改为 ≥32 字节 base64 示例(原为空,被 MustInit
  立即拒);注释提示生产 MUST replace。
- 测试: 4 个 MustInit 行为 + 1 个 50-goroutine race 覆盖。
- 行为变更: 任何 .env 缺 JWT_SECRET 或用占位 secret 的服务,启动会 panic
  (这是 fail-fast 期望行为);其余 4 个 .env 文件占位由 ops 单独轮换。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 18:50:12 +08:00
zerosaturation
3407e30395 refactor(assetService): CreateMintOrder 3-phase txn + orphan reconciliation (P0-2)
- CreateMintOrder 拆三段: txn1(PENDING→PROCESSING,不调RPC/不写asset)
  → 事务外 UpdateCrystalBalance 扣水晶 → txn2(建asset+registry→SUCCESS);
  消除 DB 事务内嵌跨服务 gRPC(连接池占用+跨服务事务风险)。
- 任一步失败 markMintOrderFailed 独立事务标 FAILED(不回滚已扣水晶=审计流水,
  重试靠 Task1 source_id 幂等 + Task2 入口短路防双扣); nil-cause 防御。
- 孤儿订单对账 ReconcileStuckMintOrders: 扫陈旧 PROCESSING 单,查 mint_cost 流水—
  已扣未建→FOR UPDATE 行锁下幂等补完 SUCCESS(串行化并发防双建),未扣→FAILED,绝不退款。
- main.go 接线周期 worker(MINT_RECONCILE_INTERVAL_SEC 默认600s,0关,优雅退出)。
- 测试: RPC失败落FAILED / 对账未扣→FAILED / 已扣未建→补完(含幂等二次跑)。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 12:28:57 +08:00
zerosaturation
b7022d2dc1 fix(backend): auth boundary — trusted identity from ctx (batch 2)
- 新增 pkg/authctx: 从 Dubbo attachment/gRPC metadata 提取可信 user_id/star_id,
  统一覆盖 req 同名字段, 缺身份返 Unauthenticated。
- 各 provider 接入(堵身份伪造/越权):
  * moderation SubmitReport 等 6 RPC(举报人伪造)
  * asset CheckAssetLike/GetAssetQrcode/TrackShare(点赞/分享归因伪造)
  * social CheckFriendship(修 starID=0 隐私预言机)
  * activity PurchaseItem/BatchPurchaseItem(水晶扣费伪造)等 5 RPC
  * gallery/aiChat/task/notification 迁移 authctx, 删散落 extractUserInfo*
- social 正确性: GetUserLikedAssets OR 显式分组(防御); GetRandomUsersByStar 真随机(去 rand.Seed)。
- gateway: /auth/validate 移入 AuthMiddleware 保护组(/refresh 保留,依赖注入身份)。
- 删 userService 已迁移死函数; notification 缺身份错误码统一为 Unauthenticated。
- 各 provider 单测(伪造身份被覆盖 + 缺身份拒绝)。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 01:12:35 +08:00
zerosaturation
878bd46399 fix(backend): financial correctness — settlement/hours/mint idempotency (batch 1)
- settlement(1.1): exhibition_revenue_records 加 UNIQUE(exhibition_id,cycle_start_time)
  + CreateRevenueRecord ON CONFLICT DO NOTHING; MQ 用 settled_at 替代复用 is_processed;
  恢复扫描器过滤改 settled_at IS NULL; created_at 统一毫秒; 删死代码 cleanup_worker.go。
- hours(1.2): 新增 exhibition_hours_log/asset_exhibition_hours_log(source_id 唯一)幂等表;
  fan_profile/assetLevel 的 AddExhibitionHours 按 sourceID 幂等(事务包裹); 存量重算脚本。
- mint(1.4/1.5/1.6): crystal_transaction_records (source_id,change_type) 部分唯一索引
  + UpdateCrystalBalance/CreateMintOrder 幂等; 保底改 crypto/rand; 下线伪 tx_hash;
  doMint Redis Lua 原子限流。
- migrations 001/002/003; 各服务单测(自包含, 缺 DB t.Skip)。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 01:11:54 +08:00
zerosaturation
d026102a91 docs: backend audit report 2026-07-21 (findings + corrections)
后端全面审查报告:微服务耦合/边界、配置、各服务正确性与安全问题分级(P0/P1/P2),
含数据库实测复核(§七 结算超发/累计时长)与多处复核更正(peripheral 密钥、social OR)。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-23 01:11:13 +08:00
zerosaturation
946493a0ff fix:补齐appBUG 2026-07-22 16:29:39 +08:00
zerosaturation
d5103f7043 docs:新增后端bug修改文档 2026-07-21 21:14:22 +08:00
zerosaturation
b7f8f1b724 fix:修改登录页流程bug 2026-07-21 16:41:42 +08:00
zerosaturation
6f9b178fc1 fix:修改一键登录页到首页的bug 2026-07-21 15:00:49 +08:00
zerosaturation
cacc686e9a fix:notification/moderation service healthcheck 配置错误
两个服务的 healthcheck 配置都有历史遗留 bug,导致 docker ps
一直显示 unhealthy / health: starting:

1) notificationService
   - 现象: docker-compose healthcheck 路径写 /healthz,但 pkg/health
     只注册 /health (backend/pkg/health/health.go:29),wget 永远 404
   - 修复: compose 路径 /healthz -> /health,Dockerfile HEALTHCHECK
     同样改 /health (双保险,rebuild 后不会回退)

2) moderationService
   - 现象: main.go 没启 health server (只暴露 Dubbo Triple 协议),
     compose 原 healthcheck 端口 20011 永远 timeout,
     Dockerfile HEALTHCHECK 也指向 20011 同样错
   - 修复: compose 用 healthcheck: test: ["NONE"] 显式覆盖 image
     HEALTHCHECK,Dockerfile 改成 HEALTHCHECK NONE (image-level
     也禁掉,rebuild 后不会回退)

gateway depends_on moderationservice: service_started (不依赖 healthy),
不影响入口可用性。健康状态靠 gateway 间接覆盖。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-21 12:12:46 +08:00
zerosaturation
7bf4666cdb fix:restart 命令卡死问题
deploy.sh restart 命令原本 down && up --force-recreate + sleep 10,
在以下场景会卡死:
1) docker-compose up 中途异常退出,server-side 进程没回传 EOF,
   本地 ssh 客户端没设 ServerAliveInterval,死链检测不到,
   ssh 进程挂 25+ 分钟不退出 (2026-07-21 实测)
2) up --wait 等所有服务 healthy 才返回,但本 compose 里有
   oss-cors-init (restart: no, exited(0) 永远不 running) +
   moderationservice/notificationservice healthcheck 写错,
   永远卡住

修改:
- ssh_cmd / ssh_cmd_batch / scp_cmd 加 ServerAliveInterval=30 +
  ServerAliveCountMax=3,死链 90s 主动断
- restart 去掉前置 docker-compose down (up --force-recreate 自带 stop+create)
- restart 去掉末尾 sleep 10,改 polling gateway healthy (timeout 180s)

端到端实测 1:19 通过。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-21 12:12:27 +08:00
zerosaturation
d554d7be83 feat:修改周边验证 2026-07-17 16:53:57 +08:00
zerosaturation
1f7faba9a8 feat:先关闭dify的使用 2026-07-16 11:35:07 +08:00
zerosaturation
d4ee464bed fix:修复任务组件报错 2026-07-16 11:34:37 +08:00
zerosaturation
99775f1d11 feat:修改详细页面,修改为每个类型的页面不对 2026-07-15 19:16:28 +08:00
zerosaturation
18aff3b682 fix:修改bug 2026-07-15 13:12:27 +08:00
365f783ea0 feat:修改分享url 2026-07-15 12:40:39 +08:00
zerosaturation
c0b577dd40 feat:增加邮箱管理功能 2026-07-14 21:59:15 +08:00
zerosaturation
1f1696063d feat:修改分享页名次 2026-07-14 13:49:58 +08:00
zerosaturation
6425cbf747 docs(spec): 站内邮箱聚合收件箱设计 (v1.2.10)
10 轮迭代后定稿:
- 复用 notifications 表,扩 type 白名单 4 类
- like 暂不进邮箱 (保留旧 push 体验)
- 前端两页路由 pages/mailbox/{index,detail}.vue
- profile.vue 服务与工具 section 加入口 + Vuex getter inboxUnreadOnly
- uniPush receive + payload 含 unreads_by_type 零轮询
- 三道防线节流 (60s/10s + Vuex 幂等)
- +N 通知聚合
- 4 emitter + DELETE /notifications/clear
- 实施路径 ~3.7d

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 13:48:52 +08:00
zerosaturation
bf92ab3ac8 feat:修改路由 2026-07-13 15:23:50 +08:00
zerosaturation
c4b8800ea7 feat:增加骨架屏 2026-07-13 15:08:28 +08:00
zerosaturation
6a6d5f9deb feat:增加守卫组合式函数本身 2026-07-13 14:56:08 +08:00
zerosaturation
7467190e38 feat:增加清理临时文件的目录 2026-07-13 14:40:34 +08:00
zerosaturation
d900c0d8b2 feat:增加验证真伪访问次数和首次验证 2026-07-13 14:24:42 +08:00
zerosaturation
74853800b6 feat:增加二维码验证真伪的功能 2026-07-13 11:22:56 +08:00
345a22e5fa docs:增加周边扫描功能 2026-07-10 12:35:12 +08:00
zerosaturation
e5bd0c854c feat:增加忘记密码的功能 2026-07-09 19:00:03 +08:00
zerosaturation
31eee930ca feat:去掉无用的函数方法 2026-07-09 16:08:25 +08:00
fbf3e6c63c feat:增加分享页下载 2026-07-09 15:49:06 +08:00
5625f6ac28 feat:增加预加载接口 2026-07-09 13:27:25 +08:00
f6b2b31d76 feat:修改热更新 2026-07-08 18:19:17 +08:00
ce1ef491f8 feat:增加uniapp更新页面 2026-07-07 14:44:23 +08:00
zerosaturation
139d91d08b feat:修复光栅卡改为连续版,auto 2026-07-07 00:44:52 +08:00
zerosaturation
0a62b9cd10 feat:修改陀螺仪为手动控制并且增加自动控制 2026-07-07 00:29:01 +08:00
zerosaturation
a1e92448f1 feat:修改陀螺仪控制为手动控制 2026-07-06 21:20:24 +08:00
zerosaturation
217af65121 refactor(holographic): 移除 DeviceOrientationEvent 路径
- 删 startGyro / startDeviceOrientation / stopGyro
- 删 accelHandler / accelBaselineReady 等基线追踪状态
- simulate(x, y) 成为唯一驱动入口
- 保留 onMounted / onUnmounted 钩子(如果外部有需要可保留,否则删)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-06 18:58:04 +08:00
zerosaturation
a4836605e7 refactor(craft-tilt): 删除硬件传感器模块 + 同步清理 3 个其他页面
- 删 useLenticularStudioTilt.js (28KB, 894 行)
- 删 useOneEuroFilter.js (75 行)
- useLenticularCraftTiltPreview 移除对二者的引用与 3 个旧 API(scheduleTiltStart/stopTiltPreview/gyroSourceLabel)
- 同步清理 3 个其他消费方页面(discover/generation-result, castlove/success, asset-detail):
  - 删 3 个旧 destructure 键
  - 模板 :gyro-source 改静态 'simulation' + 删 :skip-built-in-touch
  - 删 12 处旧 API 调用
- 保留手动模拟入口 simulateTilt / simulateTiltFromNormalized / simulateTiltReset(Task 1)
- ★ 3 个页面用触摸事件替代硬件传感器(未加 slider,后续可补)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-06 18:48:09 +08:00
zerosaturation
34dd301a92 chore(manifest): 移除 imengyu 插件注册与传感器权限
- 删 nativePlugins.imengyu-UniAndroidGyro 段(30-44 行)
- 删 BODY_SENSORS 权限(69 行)
- 删 NSMotionUsageDescription 隐私描述(82 行)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-06 18:22:20 +08:00
zerosaturation
c992ddbf61 chore(native-plugin): 移除 imengyu-UniAndroidGyro 陀螺仪插件
- 28KB AAR + iOS Framework + package.json 全部删除
- 与 useLenticularStudioTilt.js 同步(Task 9 跟进)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-06 18:10:27 +08:00
zerosaturation
dcdbc041a9 feat(lenticular-result): 切换为手动倾斜模式 + 触摸滑块双向同步
- @simulate → onTouchSimulate:触摸 x 投影到滑块 + 驱动引擎
- @update:slider-value → onSliderChange:滑块拖动驱动引擎
- @slider-reset → onSliderReset:复位滑块+引擎
- v-model:slider-value 双向
- 删 3 处 scheduleTiltStart / stopTiltPreview / gyroSourceLabel 引用
- 触摸结束不强制回中

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-06 18:02:51 +08:00
zerosaturation
851a8f6c43 feat(castlove-preview): 透传 showSlider prop
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-06 17:53:04 +08:00
zerosaturation
b0dcb82276 feat(holographic-card): 接入 ManualTiltSlider + 修 touchend 行为
- 与 LenticularCard 对齐的 showSlider / sliderValue / v-model 接口
- 触摸结束不再 emit (0,0)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-06 17:48:42 +08:00
zerosaturation
c3b423cf23 feat(lenticular-card): 接入 ManualTiltSlider + 修 touchend 行为
- 新增 showSlider / sliderValue props
- 新增 update:sliderValue / sliderReset emits(v-model 配套)
- 触摸结束不再 emit (0,0),与滑块数据驱动相容

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-06 17:43:18 +08:00
zerosaturation
86a5fdfbb5 feat(lenticular): 新增 ManualTiltSlider 独立组件
- uniapp <slider> 包装,0..1 双向绑定
- 内置 ↺ 复位按钮
- value validator 拦截 0..1 范围外输入

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-06 17:36:07 +08:00
zerosaturation
c6cb55dfc0 feat(craft-tilt): 新增 simulateTilt 手动模拟入口
- simulateTilt(dx, dy) 单位度,校验 NaN/Infinity
- simulateTiltFromNormalized(x, y) 触摸归一化转度(系数 45)
- simulateTiltReset() 滑块复位用

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-06 17:14:00 +08:00
zerosaturation
958c867309 fix:修改举报/反馈的bug 2026-07-06 16:22:26 +08:00