lixi
|
7f1dd33097
|
feat: 单层评论——幂等创建/游标列表/作者软删与 comment_count 同事务维护(T3-07,ADR-019)
CI / backend-test (push) Successful in 7m33s
- POST /api/v1/posts/{postId}/comments:Idempotency-Key 必带,落
client_request_id + 规范化 request_hash(uq author×key,键按作者隔离);
同键同 payload 返回首条(201,不重复计数),异 payload 409/40905,
重试撞已删首评 404/40404(沿 T3-04 §2.4 先例);replyToUserId 可选
@ 回复,目标须为存活用户(404/40406);content trim 后 1~2000
- GET 评论列表:(created_at DESC, id DESC) 走 ix_comments_post_created
keyset 游标,仅 status=visible,作者与 @ 目标批量走 AuthorProfileGateway
(降级 id-only 同构复用)
- DELETE /api/v1/comments/{commentId} 顶层短路径:仅评论作者可删
(D3-7 拍板,帖主删他人评论不做);可见评论他人删 403/40301,
不存在/已删/所属帖不可见合并 404/40404;FOR UPDATE 锁定状态迁移,
comment_count 同事务 -1 恰一次
- 评论域同用互动门禁:帖子公开面之外(含作者本人草稿)一律 404/40403
逐字节一致
- ErrorCode 新增 40404 COMMENT_NOT_FOUND
- CommentIntegrationTest 14 例:六类路径、幂等矩阵专项、分页不丢不重、
计数对账专项(删评后列值 = visible 行数 = 列表长度)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-09 10:50:28 +08:00 |
|
lixi
|
19e8cba59f
|
feat: 点赞/收藏/关注幂等互动与同事务计数——PUT/DELETE 权威终态、我的收藏游标列表、follow-stats(T3-06/T3-08,ADR-018/019)
- PUT/DELETE like|bookmark:复合主键即幂等键(ON CONFLICT DO NOTHING /
条件 DELETE),计数列按关系写实际变更行数同事务增减,响应回
{liked,likeCount}/{bookmarked,bookmarkCount} 权威终态;并发重复施加
恰计 1、PUT+DELETE 竞态终态列值与关系表恒一致(真并发测试锚定)
- 互动门禁定型:只认帖子公开面(published 且未删)——作者本人草稿、
hidden/archived、软删、不存在合并逐字节一致 404/40403
- GET /api/v1/me/bookmarks:按 (bookmarks.created_at DESC, post_id DESC)
keyset 游标,卡片复用 FeedCard 装配;失效帖在页查询内静默剔除,
游标键在关系行上、分页正确性不受剔除影响
- PUT/DELETE /api/v1/users/{userId}/follow + GET follow-stats:
自关注 422/42204(ck_user_follows_self 库层兜底);目标不存在/注销
合并 404/40406,存在性走同库只读 identity.users(ADR-017 例外,
写门禁不适用 Feign 降级语义);计数实时 COUNT 双向索引
- ErrorCode 新增 40406 TARGET_USER_NOT_FOUND、42204 FOLLOW_RULE_VIOLATION
- 集成测试 14 例(LikeBookmark 9 + Follow 5):六类路径、并发幂等专项、
计数对账专项、收藏列表静默剔除与分页
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-09 10:50:06 +08:00 |
|
lixi
|
101ac0fbbc
|
feat: 帖子生命周期——草稿/编辑/发布/软删/详情/我的列表(ADR-019,T3-04)
CI / backend-test (push) Successful in 6m33s
- patbond-community 帖子域五端点:POST/GET/PATCH/DELETE /api/v1/posts(/{postId}) + GET /api/v1/me/posts
- 创建型幂等按 ADR-019:Idempotency-Key 必带(1~128)落 uq_posts_author_idempotency,
规范化 request_hash 比对——同键同 hash 返回首帖、异 hash 40905、键按作者隔离
- 权限/错误语义定型(T3-10 冻结输入):403/40301 仅发给可见者,一切不可见合并
404/40403 防枚举(hidden/archived 对作者同样 404);version 乐观锁 40902
- 发布 = PATCH 状态迁移 draft→published(publishedAt 恰写一次,重复发布幂等 no-op)
- 软删 deleted_at 为唯一判定基准,published 行归档为 archived 满足 ck_posts_publish_state
- post_media:仅本人 ready asset(同库只读 media.assets,ADR-017 先例;40405/42203),
position 全给或全不给、isCover 至多一、封面缺省落 position 0;PATCH media 整组替换
- 读取侧图片 URL 由 community 本地预签名 GET(与 user 共用 PATBOND_MINIO_* 配置,
compose 已注入;未配置降级 url=null)
- ErrorCode 增 40301/40403/40905/42203;异常处理补 MissingRequestHeaderException→40000
- 集成测试 +25(六类路径/幂等专项/草稿可见性矩阵/并发 PATCH 真竞争),全套 251 全绿
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-09 09:59:46 +08:00 |
|
lixi
|
10a43f876c
|
feat: media 域最小闭环——存储适配层 + MinIO 预签名两步上传(ADR-016/017,T3-03)
- ObjectStorage 适配层(供应商唯一缝)+ S3ObjectStorage(AWS SDK v2,
path-style,内网/公网双端点分离签发);endpoint 未配置时服务可启动、
media 端点 500(沿 JWT 公钥先例)
- POST /api/v1/media/uploads:白名单校验(purpose/mime/byteSize 全配置项)
→ uploading 行(objectKey 服务端生成不含用户输入)→ 预签名 PUT 凭据
(requiredHeaders 定型仅 Content-Type,TTL 10m)
- complete:HEAD 校验存在性/大小/类型 → uploading→ready(guarded UPDATE
并发幂等);对象缺失保持 uploading 可重试,内容不符置 failed 终态;
防枚举 40405;新错误码 40405/42205
- 读取侧预签名 GET(TTL 1h),桶保持私有
- compose 纳入 minio 第六容器(镜像与 Testcontainer 同 tag,桶初始化走
应用启动 ensureBucket,三环境零分叉);init-secrets.sh 幂等追加 MinIO
根凭证到 .env(凭证零入库,ADR-021)
- MediaUploadIntegrationTest 12 例:MinIO Testcontainer 全链路直传取回 +
六类失败路径 + 库层约束一致性;uploading 超时清理只记方案(报告 13 §6)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-08 17:11:44 +08:00 |
|
lixi
|
3b27f9fcbe
|
feat: 照护提醒接口与 pending 状态流转(T2-07)
CI / backend-test (push) Successful in 5m8s
- GET/POST /api/v1/pets/{petId}/care-reminders + PATCH /api/v1/care-reminders/{reminderId}
- 四类提醒白名单;创建恒为 pending;列表按 due_at ASC,
?status=pending 待办视图走 ix_care_reminders_due 部分索引
- 状态机 pending→completed/dismissed,终态不可迁移、同状态重放幂等;
completed 必带 completedAt、其余状态禁带(镜像 ck_care_reminder_completed),
违反 → 新错误码 42202 REMINDER_RULE_VIOLATION
- 表无 version 列:流转用当前状态条件更新守卫竞态(落空 → 40902);
顶层记录路径 40402 记录级防枚举;Idempotency-Key 派生主键幂等
- 仅 app 内数据接口,不做推送(D2-5,通知系统属 M6)
- Testcontainers 集成测试 10 例(六类路径 + 状态-completedAt 一致性)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-07 17:59:34 +08:00 |
|
lixi
|
4c2653c643
|
feat: 疫苗目录与疫苗记录接口、状态机与剂次唯一(T2-05)
CI / backend-test (push) Successful in 5m18s
- GET /api/v1/vaccine-catalog(只读字典,species 过滤,仅 enabled)
- GET/POST /api/v1/pets/{petId}/vaccinations、PATCH /api/v1/vaccinations/{id}
(顶层短路径,记录级防枚举:不可见记录一律 404/40402)
- 状态机 scheduled→completed/cancelled,completed/cancelled 终态;
日期规则镜像 ck_vaccination_dates/ck_vaccination_next_due,违反返回
422/42201(新码 VACCINATION_RULE_VIOLATION)
- 剂次唯一冲突 409/40904(新码 VACCINATION_DOSE_EXISTS,草案提议的
40903 已被 MICROCHIP_EXISTS 占用故改号);cancelled 释放唯一占位
- version 乐观锁 409/40902;Idempotency-Key 幂等与 T2-04 同机制
- 疫苗须存在/启用且物种与宠物匹配(40000)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-07 17:44:23 +08:00 |
|
lixi
|
8fbf44472d
|
feat: 宠物 CRUD 与 pet_owners 三角色权限框架(T2-03)
CI / backend-test (push) Successful in 7m22s
- GET/POST /api/v1/pets、GET/PATCH /api/v1/pets/{petId}、GET /api/v1/breeds
(species 过滤);创建者自动写入 pet_owners primary owner(同事务)
- PetAccessService 统一权限闸口(READ/WRITE/MANAGE 三档 × owner/caregiver/
viewer 三角色,ADR-015):无关系一律 404/40401 防枚举,可见越权 403/40300;
每请求实时查库无缓存,撤销关系即时生效;T2-04~07 复用同一入口
- PATCH version 乐观锁(40902);部分更新语义;status 白名单排除 deleted,
软删除不可经 PATCH 绕过 ck_pets_deleted
- ck_pets_breed 互斥 + 字典品种存在/物种匹配应用层先行校验(40000);
芯片号唯一冲突新错误码 40903 MICROCHIP_EXISTS
- pet 模块接入 RS256 bearer 鉴权(与 user 同一公钥约定),compose 挂载公钥
- 测试基建:test classpath 引入 patbond-user + Flyway,Testcontainers 上跑
完整 V1..V4 迁移链;三角色以测试数据直写 pet_owners 构造(T2-10)
- 集成测试覆盖六类路径 23 例;全套 118 测试全绿(基线 95)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-07 17:27:44 +08:00 |
|
lixi
|
49299fb4eb
|
feat: Flyway V3 pet_health 结构基线 + V4 字典种子 + pet 域错误码(T2-01)
- V3:pet_health schema 8 张表(breeds/pets/pet_owners/pet_weight_records/
vaccine_catalog/pet_vaccinations/health_events/care_reminders),列、CHECK、
部分唯一索引、updated_at 触发器与目标模型一致
- 强制裁剪:剥离 bootstrap SQL 1156~1166 行 4 条指向 marketplace 的跨 schema
外键(provider_id/booking_id 保留为裸可空 uuid,M5 迁移 marketplace 时补回)
- ADR-010:health_event_media 不建(media 剪出 M2,纯增量表后续补零成本)
- V4:breeds(28 条)与 vaccine_catalog(10 条)字典种子,生产参考数据走正式
迁移链不放 db/dev;正典目录内容由产品侧供稿(D2-6)
- ErrorCode 预置 pets 域四码:40300 PET_ACCESS_DENIED、40401 PET_NOT_FOUND、
40402 RECORD_NOT_FOUND、40902 VERSION_CONFLICT(第二波接口直接消费)
- 新增 PetHealthMigrationIntegrationTest:干净 postgres:18 上全量迁移验证
表数、结构抽查、4 条 FK 确不存在、触发器与种子数据
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-07 14:34:19 +08:00 |
|
lixi
|
8a799719ff
|
fix: 响应信封不再泄露派生字段 success,严格等于 {code, message, data}
- ApiResponse.isSuccess() 加 @JsonIgnore(common 引入 jackson-annotations,仅注解不含 databind);三波以来所有响应都多带了一个契约外的 success 字段,前端解析器忽略未知字段,无破坏
- 测试补断言 $.success doesNotExist;门禁:./mvnw clean test → BUILD SUCCESS,74 测试 0 失败
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-04 14:51:34 +08:00 |
|
lixi
|
8bdaf53222
|
feat: 会话记录接入客户端 X-Device-Id(auth_sessions.device_id)
- Flutter 端每次请求已携带 X-Device-Id;auth 读取该头(截断 128)经 CreateSessionRequest 透传,user 落 auth_sessions.device_id,为多设备会话列表备数据
- 门禁:./mvnw clean test → BUILD SUCCESS,74 测试 0 失败(新增 registerForwardsDeviceIdHeaderToTheSessionRecord + 会话落库断言)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-04 14:43:44 +08:00 |
|
lixi
|
4dc3dcdfa3
|
feat: JWT RS256 + refresh 会话轮换与 /api/v1 契约落地(ADR-003)
- 会话逻辑下沉 patbond-user(新 /internal/sessions;auth_sessions 只存 SHA-256 摘要,刷新即轮换并链 token_family,重用撤销整个 family,退出仅撤当前会话,多设备并行)
- patbond-auth 作薄入口签发 RS256 JWT(access 15m / refresh 30d 均为配置项;密钥经环境变量注入,仓库零密钥材料,测试密钥运行时生成);公开端点迁至 /api/v1,冻结契约字段零偏差,expiresAt 无时区遗留修复
- /internal/** 加 X-Internal-Token 服务间鉴权(无凭证 401);/api/v1/me 由 user 以公钥本地验签(40101/40102 新错误码)
- 登录失败限制:按用户名 15 分钟窗口 5 次锁 15 分钟(423/42300,DB 原子计数,可配置)
- 修复两处存量缺陷:ErrorDecoder 未注册进 Feign 子上下文、JDK HttpURLConnection 对流式 POST 的 401 读不到错误体(引入 feign-hc5)——真实调用中下游错误码此前一律折叠为 503
- 门禁:JAVA_HOME=/usr/lib/jvm/java-17-openjdk ./mvnw clean test → BUILD SUCCESS,73 测试 0 失败(37→73),含同 JVM 双服务真实 HTTP E2E:注册→me→刷新→旧 refresh 重用被拒且 family 撤销→退出后 refresh 失效;Testcontainers postgres:18,无遗留容器
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-04 12:15:40 +08:00 |
|
lixi
|
bd20adc700
|
feat: 用户 UUID 持久化与统一异常契约(Flyway baseline / UUIDv7 / 错误码透传)
- Flyway V1 baseline:identity 全部 5 表 + media.assets + platform 最小硬依赖(set_updated_at/regions),无 fixture 凭据;dev 种子独立为 afterMigrate 回调且默认不执行
- patbond-user 迁移到 PostgreSQL:UUIDv7 主键、JdbcClient 仓储、bcrypt 密码、唯一性依赖 DB 约束翻译为 409、E.164 手机号校验对齐 ck_users_phone
- 统一异常契约:common 新增 ErrorCode/BusinessException,两服务 GlobalExceptionHandler;auth 经 ApiErrorDecoder 原码透传下游错误,修复状态码折叠(审计 M1)
- 门禁:JAVA_HOME=jdk17 ./mvnw clean test,37 个测试 0 失败(含 Testcontainers postgres:16 集成测试),BUILD SUCCESS
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-04 10:34:48 +08:00 |
|
lixi
|
c7ddaecb76
|
重构底层框架
|
2026-09-03 17:59:56 +08:00 |
|
nmbh1122@126.com
|
b1252b991d
|
Initialize patbond microservice modules
|
2026-07-13 09:41:15 +08:00 |
|