zerosaturation
|
7ff2d5cdc4
|
fix(gateway): restore /api/v1/starbook/* via assetService (recovery from Task 2 over-deletion)
- 恢复 /api/v1/starbook/home + /api/v1/starbook/items 网关路由
(owner 从被删的 starbookService 切到 assetService);
- assetService 加 GetAssetsByType RPC (type/category/grade 过滤), 仅改 asset.pb.go (不动 triple.go);
- gateway 新建 starbook_controller.go 薄壳 (auth + 参数解析 + RPC);
使用 Task 1 扩展接口 AssetServiceGetAssetsTypeClient (零装配增量, 复用现有 assetClient);
- 响应结构与原端点完全一致 (前端 4 处调用零修改, 实测 home 2514 bytes JSON shape 一致);
- items 支持 type/category/grade/page/page_size 完整参数;
- 路由注入到 AuthMiddleware 保护的 v1 group;
- 5/5 starbook 测试 + 完整 workspace build/vet 通过。
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-07-24 14:04:01 +08:00 |
|
zerosaturation
|
8a767fb400
|
fix(backend): service stability — batch 3 accumulated (bcrypt off-txn / login anti-enum / MQ stub / aiChat / event reliability / gateway aggregate)
- 3.1 bcrypt 移出事务 (Register): repository.HashPassword 前移到 db.Transaction 之前。
- 3.2 Login 消除用户枚举 + 限流 + timing 抹平: pkg/errors 加 ErrInvalidCredential / ErrTooManyLoginAttempts;
user-not-found 跑 dummy bcrypt 抹平 ~100ms 时序差; mobile 5次/ip 20次 per 15min 限流 (Redis, fail-open 降级)。
- 3.3 MQ streams adapter 停用 → stub: 0 业务调用方, noop EventProducer.Publish; Init 不再装配 streams;
11 处硬编码 'gallery'/'default' 抽常量到 pkg/queue/consts (值不变, 消漂移)。
- 3.5 JWT 密钥治理: pkg/jwt MustInit fail-fast + atomic.Value, 50-goroutine race_test 零告警;
MustInit 调用点 gateway main + auth_provider + loadgen 同步更新。
- 3.6 aiChat 健壮性: SaveContext 用 persona.ID(非 req.PersonaId); Redis/memory 错误 记 WARN 不静默;
Dify err 映射稳定用户文案。
- 3.7 statistic.Client 重构: TrackEvent 改 buffered channel (cap 1024) + dispatchLoop worker。
- 3.8 网关聚合: StarCache (60s TTL, singleflight) 替换 GetFanIdentities 链式调用;
DeleteAccount 改网关直调 userService.DeleteAccount(避免改 hand-written triple.go);
铸造双写改异步 channel+consumer (3 retry)。
- 大量单测: 各子项 TDD (RED→GREEN), 关键并发 race_test (50 goroutine)。
- .env.example JWT_SECRET 改为 ≥32 字节 base64 示例(原为空, 被 MustInit 立即拒)。
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-07-24 14:03:21 +08:00 |
|
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 |
|