lixi
|
15c2e66519
|
feat: 宠物头像读写——PATCH 支持 avatarAssetId、详情与列表补 avatarUrl(T3.5-05,ADR-022)
- PATCH /api/v1/pets/{petId} 支持 avatarAssetId 三态:缺省不改、显式 null
清空、给值设置。这是 pets 域唯一的三态字段——M2 惯例「null 与缺省同义」
无法表达「删掉头像」,而 name/species/sex 本就不允许为空,故差异刻意限定
在本字段
- 权限按「本次请求碰了哪些字段」定档:仅改头像为 WRITE(owner+caregiver,
ADR-022:头像属日常照护信息,与体重/疫苗同档),碰到任一资料字段仍是
MANAGE(仅 owner),混合请求按更严的一半判;viewer 一律 403/40300
- 头像与资料共用同一把乐观锁:仅改头像也吃 version,旧版本必答 409/40902
- asset 校验复用 T3-03 引用侧协议 + purpose='pet_avatar':不存在/非本人/
已删/用途不符答 404/40405,本人未就绪答 422/42203(user_avatar 资源也不能
当宠物头像)
- 详情与列表响应补 avatarUrl(本地 SigV4 现签预签名 GET,沿用 community 读侧
先例):仅当 asset 为 ready 才签,指针在而资源退出 ready 时降级为 null,
不签一个下载必 404 的地址,也不隐式清理指针
- PetRepository 读改为返回 PetRow(含头像存储坐标),签名上移到 PetService,
与 community 的 PostRow → PostResponse 装配同构——过期 URL 不下沉到仓储层
- pet 模块加入 aws-sdk s3(仅本地签名,不直连对象存储)与读侧 patbond.media
配置;compose 补同一组 PATBOND_MINIO_* 环境变量
- 测试 +11(成功/清空/缺省保留/降级/caregiver 与 viewer 权限/防枚举 404/
asset 五态/畸形入参/乐观锁与重放),pet 模块 89 → 100
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-11 10:02:50 +08:00 |
|
lixi
|
0569585434
|
test: 契约冻结 v1.3.0 api 侧收尾——四模块字节级快照同步 + community/media 契约矩阵入场
CI / backend-test (push) Successful in 5m4s
- 正典 v1.3.0(doc main@f848476)字节级复制为 pet/auth/community/user 四份
openapi-v1.3.0.yaml 快照(md5 与正典一致),删除旧 v1.2.0(守卫只认一份,
历史由 git 承载);pet/auth 守卫期望升版 1.3.0/31 路径/43 操作/72 schemas
- CommunityContractConformanceTest:community 域 17 操作 64 单元格全响应矩阵
(Feed/帖子/评论/互动/关注,401/403/404/409/422 各格实证,零豁免)
- MediaContractConformanceTest(user 模块):media 两步上传 2 操作 8 单元格
全矩阵(真实 MinIO 直传,零豁免)
- ContractValidator 四副本加单分支 allOf 展平合并,修复 v1.3.0
nullable+allOf 模式(coverImage/replyToUser)被静默跳过的校验盲区,
定向 mutation 自证生效
- 实现与冻结契约零漂移;310 → 325 测试全绿;check-secrets --all 通过
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-09 11:31:45 +08:00 |
|
lixi
|
d026f2f63d
|
test: 契约一致性测试对冻结契约 v1.2.0 全矩阵校验(T2-09)
CI / backend-test (push) Successful in 5m14s
- 新增 ContractConformanceTest:pets 域 18 操作真实起服务(Testcontainers +
MockMvc)逐一发请求,对照冻结快照 src/test/resources/contract/
openapi-v1.2.0.yaml 严格校验响应结构(未声明字段即漂移、必填/nullable、
类型/枚举/格式/边界、错误码值);覆盖门禁断言契约声明的每个
(操作, 状态码) 单元格都被真实触发(唯一豁免:提醒 PATCH 409 并发守卫)。
- OpenApiContract/ContractValidator:snakeyaml 解析快照 + 自写严格断言,
零新增依赖;快照守卫锁 info.version=1.2.0 与 18 路径/24 操作/45 schema,
正典(doc 仓 docs/api/openapi.yaml)升版而快照未同步时 CI 立即变红。
- 修复漂移:CreatePetRequest.sex 按冻结契约改为必填(原实现缺省补
unknown,契约 required 含 sex);既有测试载荷补 sex 字段。
全套 ./mvnw clean test 182 项全绿(171 → 182,+11 契约测试)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-08 10:36:12 +08:00 |
|
lixi
|
00f7dbdb69
|
feat: 档案聚合摘要接口与四项聚合口径定型(T2-08)
CI / backend-test (push) Successful in 3m36s
- GET /api/v1/pets/{petId}/summary,READ 档(viewer 可读),四项聚合全部实时计算、零持久化(4.3 红线)
- 最新体重:measured_at DESC, id DESC 首行,与体重列表口径一致;无记录为 null
- 疫苗进度:completed 剂次 / 非 cancelled 总剂次;无非 cancelled 记录为 null
- 下次接种:scheduled planned_on 与 completed next_due_on(同系列更高剂次未登记时)取全候选最早日期,含逾期;source 区分 planned/nextDue
- 当月花费:health_events.amount_cents 按 tz 参数(IANA 时区,缺省 UTC)自然月半开区间求和,NULL 金额不计入;恒非 null,无支出为 0
- 集成测试 12 例:空数据语义、跨月边界(含时区口径)、cancelled 不计入、被接续加强针剔除、多宠隔离、防枚举 404、零写入断言
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-08 09:45:50 +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
|
d8303bf446
|
feat: 健康事件时间线接口与 occurred_at 游标分页(T2-06)
- GET/POST /api/v1/pets/{petId}/health-events + PATCH /api/v1/health-events/{eventId}
- 六类事件白名单、amount_cents 整数分非负(禁用 Jackson float→int 截断)、
created_by_user_id 记操作者
- occurred_at DESC, id DESC 游标分页对齐 ix_health_events_pet_time;
Idempotency-Key 派生主键幂等;version 乐观锁 40902;
顶层记录路径 40402 记录级防枚举
- health_event_media / provider / booking 不实现不外露(ADR-010)
- Testcontainers 集成测试 11 例(六类路径 + 分页专项)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-07 17:59:17 +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
|
825dde3928
|
feat: 体重记录接口与 cursor 分页、Idempotency-Key 幂等(T2-04)
- GET/POST /api/v1/pets/{petId}/weights,复用 PetAccessService 闸口
(READ 读 / WRITE 写,含 caregiver 写成功正向用例)
- cursor 分页按 (measured_at DESC, id DESC) 与 ix_pet_weight_pet_measured
对齐,limit+1 探测 hasMore,同刻记录跨页不丢不重
- Idempotency-Key 可选头:键派生确定性主键 + ON CONFLICT (id) DO NOTHING,
重试返回原记录,零新增迁移
- weight_kg 校验镜像 ck_pet_weight(>0 且 ≤500,两位小数)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-07 17:43:59 +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
|
0eae1c9bec
|
feat: 新建 patbond-pet 模块骨架(ADR-009,T2-02 前置)
- 新 Maven 模块挂入父 pom,依赖/插件管理对齐既有 user/auth 模式
(common 依赖、starter-web/validation/jdbc、exec classifier repackage)
- 骨架内容:PetApplication、/health 探活端点(含 DB 连通检查)、
GlobalExceptionHandler(同一 {code,message,data} 信封契约)
- 与 user 共库只读写 pet_health schema;不携带 Flyway——单一迁移链
(V1..V4)仍由 patbond-user 启动时统一执行,flyway_schema_history 不拆
- 配置走 .sample 模式(默认端口 8083,敏感信息经环境变量注入不入库)
- compose 编排纳入 pet 服务(依赖 postgres 健康 + user 先起保证迁移就绪);
Dockerfile 与既有服务同模式;Readme 模块清单同步
- 测试:Testcontainers postgres:18 上下文启动冒烟 + /health 探活断言
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-09-07 14:34:52 +08:00 |
|