Your Name
3f8860ab29
test(store): use millisecond deltas in ListDue ordering test to match PG precision
2026-05-11 14:10:41 +08:00
Your Name
135718836e
fix(e2e,store,delivery): fix E2E stability - lifecycle ordering, event ordering, callback_target NOT NULL, worker ticker loop
2026-05-11 14:08:19 +08:00
Your Name
34b175b130
feat(outbox): implement concurrent claim mechanism with UPDATE RETURNING + SKIP LOCKED
...
- Add migration 0004 to introduce 'claiming' status and timeout index
- Add StatusClaiming to platformevent domain and allow it in Validate()
- Rewrite ListDue as transactional UPDATE ... RETURNING with FOR UPDATE SKIP LOCKED
- Add ReleaseStaleClaims to reset expired claiming events back to retrying
- Worker Start() now runs a 30s ticker for stale claim recovery (5m timeout)
- Update stubEventStore in tests to satisfy new EventStore interface
Refs: D-02
2026-05-11 13:16:28 +08:00
Your Name
771304eabe
docs: add eventual-consistency annotations
...
D-03: document non-transactional boundaries.
- Comment in platform_webhook_handler.go explaining that dialog.Process
and outbox.InsertPendingBatch are not in a single transaction; 500 is
returned on outbox failure for caller retry.
- Package-level comment in dialog/service.go noting the lack of a unified
transactional outer box and the eventually-consistent nature of storage
operations.
2026-05-11 13:10:03 +08:00
Your Name
22384d155b
refactor(platformevent): remove CallbackTarget field and all usages
...
D-01: callback_target contract drift cleanup.
- Remove CallbackTarget from Event struct and Validate
- Remove CallbackTarget from PlatformInboundMeta
- Remove defaultCallbackTarget and assignment from builder
- Remove callback_target column from INSERT/SELECT/dead_letter SQL
- Clean up all test literals and assertions
DB migration left untouched; column remains empty until a future schema
cleanup migration.
2026-05-11 13:09:50 +08:00
Your Name
858a64880a
test: skip postgres store tests when PostgreSQL is unavailable
2026-05-11 12:46:06 +08:00
Your Name
a6ff7c88db
fix: add HTTP client connection pool limits, worker graceful shutdown, and PostgreSQL skip fallback for tests
2026-05-11 12:43:51 +08:00
Your Name
7e17e59ad1
feat: strict config parsing in production mode with mustGetEnvInt/Bool
2026-05-11 12:26:47 +08:00
Your Name
6fabac3359
fix: use net.SplitHostPort for rate limit key and add IPv6 tests
2026-05-11 12:24:47 +08:00
Your Name
a90c5dd6f3
perf: in-place filtering in RateLimiter to reduce GC pressure
2026-05-11 12:23:43 +08:00
Your Name
000c82747c
docs: document authz trust boundary and annotate RequireRoles
2026-05-11 12:23:16 +08:00
Your Name
781deae0b9
test: cover NewAPIAdapter.BuildIngressAck nil and with-meta branches
2026-05-11 12:22:35 +08:00
Your Name
0e7ec1ef94
test: cover TicketHandler.List success and error branches
2026-05-11 12:22:02 +08:00
Your Name
2308ae1261
fix: disable newapi assembly/worker and update Makefile test flags
2026-05-11 12:20:26 +08:00
Your Name
5beb002d2f
fix: platform event store and builder drift
2026-05-11 12:19:20 +08:00
Your Name
06eeb5776b
style(go): apply gofmt to repository
CI / verify (push) Failing after 24s
2026-05-06 12:22:41 +08:00
Your Name
dbf88bea07
fix(adapter): stabilize callback event ordering
2026-05-06 11:02:41 +08:00
Your Name
16e53361f2
feat(adapter): externalize platform worker runtime tuning
2026-05-06 10:54:08 +08:00
Your Name
cbbb553e9f
feat(adapter): add sub2api platform adapter stack
2026-05-06 10:45:51 +08:00
Your Name
6c3474e23b
feat(ai-customer-service): add gate readiness verification and handoff docs
2026-05-06 09:39:33 +08:00
Your Name
087de4e102
fix(audit): use uuid.New() for ticket workflow audit IDs
...
Fixes 'invalid input syntax for type uuid' error when writing ticket
workflow audit logs. The audit Event.ID field was using fmt.Sprintf
with nanoseconds ('wf-%d') which doesn't match PostgreSQL's uuid type.
Also adds uuid import to ticket_workflow.go.
Verified: full chain webhook→assign→resolve→close produces 3 audit
logs correctly, no more 'invalid uuid' errors in logs.
2026-05-04 13:44:39 +08:00
Your Name
3427f65330
fix(dialog): use uuid.New() for ticket and audit IDs
...
- Replace fmt.Sprintf with sess.ID+nanotime that generated non-UUID strings
- ticket creation and audit logging now use github.com/google/uuid
- Fixes 500 error when webhook processes messages with PG store
- All 23/23 tests pass, verified Gate B end-to-end
2026-05-04 08:25:46 +08:00
Your Name
142b991334
fix(config+app): production fail-fast + readiness收紧
...
1. config.go: AI_CS_ENV runtime mode with production restriction
- New RuntimeConfig.Env field (AI_CS_ENV / AI_CS_RUNTIME_ENV)
- production + Postgres.Enabled=false → Load() returns error
- production + empty webhook secret → Load() returns error
- normalizeRuntimeEnv: dev/dev/ → development, prod/production → production, test → test
2. app.go: probe.SetReady only when store is confirmed ready
- Postgres.Enabled: probe.SetReady(true) after DB+migration OK
- Memory mode: probe.SetReady(false) — not production-ready
3. health_handler_test.go: add probe live+ready state transition tests
4. config_test.go: add TestLoad_RejectsProdWhenPostgresDisabled,
TestLoad_RejectsProdWhenWebhookSecretMissing
5. app_test.go: add TestNew_RejectsMemoryModeWithoutExplicitNonProdEnv,
TestNew_AllowsMemoryModeInTestEnv, TestNew_WithPostgresEnabled_*
for invalid DSN and migration-failure paths
Phase 1 (code gate) objectives met:
✅ prod cannot fall back to memory store
✅ readiness reflects actual store readiness
✅ both changes have test coverage
2026-05-04 07:38:10 +08:00
Your Name
cf46b27610
fix: P0-1 RateLimiter并发写安全 + P0-2工单操作错误码区分 + P1 rows.Close修复
...
P0-1 (limits.go): Allow()方法改为全程使用写锁保护counters map读写,避免RLock写入时的data race
P0-2 (ticket_workflow.go+ticket_handler.go): Assign/Resolve/Close操作先查询ticket存在性和状态,返回明确的CS_TICKET_4001/CS_TKT_4002/CS_TICKET_4092/CS_TICKET_4093错误码,handler根据错误前缀路由HTTP状态码
P1-1 (ticket_store.go): 移除GetStats中3处手动rows.Close(),只保留defer Close()
2026-05-01 20:56:25 +08:00
Your Name
cefbe946b2
fix(ticket_handler): 将 auditTicketChange 死代码接入 Assign/Resolve/Close
...
auditTicketChange (ticket_handler.go:104) 自定义义以来从未被调用:
- Assign/Resolve/Close 成功后均未记录状态变更审计日志
- 已有的单元测试在 mockTicketService 里单独记录事件,但 handler 层缺失
修改内容:
- Assign/Resolve/Close 成功后调用 h.auditTicketChange()
- auditTicketChange 新增 actorID 参数(原来硬编码为 system)
- 修改后 handler 层和 service 层各自记录一条 audit 日志(测试断言相应改为 len==2,取 [1])
- nil 保护保持不变(h==nil || h.audit==nil)
同时更新 ticket_handler_test.go:
- assign/resolve 测试断言从 len==1 改为 len==2,取最后一条
- 新增 TestTicketHandlerCloseAuditsStateChange 测试
handlers 覆盖率:85.9% → 87.1%
2026-05-01 13:29:00 +08:00
Your Name
82a9306819
test(P1): 补齐 domain/intent、domain/message、domain/ticketstats、platform/logging、service/intent、config 测试
...
**新增测试文件**:
- internal/domain/intent/intent_test.go: 6 个测试(Recognize 各意图分支、containsAny)
- internal/domain/message/message_test.go: 4 个测试(UnifiedMessage 各字段)
- internal/domain/ticketstats/stats_test.go: 5 个测试(Stats 各字段、零值、nil map)
- internal/platform/logging/logger_test.go: 6 个测试(NewLogger 各日志级别)
- internal/service/intent/service_test.go: 6 个新增测试(通用意图、大小写、空格、containsAny)
**增强测试文件**:
- internal/config/config_test.go: +11 个测试(getEnvBool 全部分支、getEnvInt 无效值、getEnvInt64)
- internal/app/app_test.go: +3 个测试(Shutdown 关闭器顺序、nil 分支)
**覆盖率提升**:
- internal/service/intent: 80.8% → **100.0%** ✅
- internal/platform/logging: 0% → **100.0%** ✅
- internal/config: 70.6% → **82.4%** (+11.8%)
- 整体覆盖率: 76.6% → **77.1%** (+0.5%)
Ref: test/PHASE2_TEST_PLAN.md P1-1, P1-2
2026-05-01 11:43:05 +08:00
Your Name
533b4a1b0c
test(P1): 补齐 webhook HandleChannel 和 clientIP 测试
...
新增测试(internal/http/handlers):
- TestHandleChannel_OverridesChannel: channelOverride 覆盖请求 body 中的 channel
- TestHandleChannel_WithEmptyOverride: 空 channelOverride 使用 body 中的 channel
- TestHandleChannel_RejectsNonPost: GET 方法返回 405
- TestHandleChannel_RejectsMissingFields: 缺失必填字段返回 400
- TestHandleChannel_EmptyBody: 空 body 返回 400
- TestClientIP_WithPort: 带端口的 remoteAddr 解析
- TestClientIP_NoPort: 不带端口的 remoteAddr 解析
**覆盖率提升**:
- internal/http/handlers: 84.4% → **85.9%** (+1.5%)
- 整体覆盖率: 76.3% → **76.6%** (+0.3%)
- P1 目标达成 ✅ (handlers >85%)
Ref: test/PHASE2_TEST_PLAN.md P1
2026-05-01 10:41:39 +08:00
Your Name
3d18b1a34d
test(P0-5): 补齐 health handler 和 ticket stats handler 测试
...
新增 internal/http/handlers/health_handler_test.go:
- TestHealthHandler_Live_ReturnsUPWhenLive
- TestHealthHandler_Live_ReturnsDOWNWhenNotLive
- TestHealthHandler_Live_WithNilProbe
- TestHealthHandler_Ready_WithFailingChecker
- TestHealthHandler_Ready_WithPassingChecker
- TestHealthHandler_Health_ReturnsOK
- TestTicketStatsHandler_Get_Success
- TestTicketStatsHandler_Get_Error
- TestTicketStatsHandler_Get_NilAudit
**覆盖率提升**:
- internal/http/handlers: 78.4% → **84.4%** (+6.0%)
- 整体覆盖率: 74.8% → **76.3%** (+1.5%)
所有 P0 任务完成!Phase 2 测试补齐全部达成 🎉
Ref: test/PHASE2_TEST_PLAN.md P0-5
2026-05-01 10:03:51 +08:00
Your Name
417f627106
test(P0-4): 补齐 health platform 测试 - Evaluate 覆盖 100%
...
扩展 internal/platform/health/health_test.go(+5 个测试):
- TestEvaluate_NoCheckers_ReturnsTrue: nil checkers → true
- TestEvaluate_EmptyCheckers_ReturnsTrue: empty checkers → true
- TestEvaluate_AllCheckersPass_ReturnsTrue: 全通过 → true
- TestEvaluate_SomeCheckersFail_ReturnsFalse: 部分失败 → false
- TestEvaluate_NilChecker_Skipped: nil checker 跳过不 panic
- TestEvaluate_AllCheckersFail_ReturnsFalse: 全失败 → false
**覆盖率提升**:
- internal/platform/health: 38.1% → **100.0%** (+61.9%) ✅
- 整体覆盖率: 73.6% → **74.8%** (+1.2%)
Ref: test/PHASE2_TEST_PLAN.md P0-4
2026-05-01 09:58:31 +08:00
Your Name
55cfcd6503
test(P0-3): 补齐 router 测试覆盖
...
扩展 internal/http/router_test.go(+3 个测试):
- TestRouter_TicketsSubpaths: /assign、/resolve、/close 路由注册验证
- TestRouter_SessionsFeedbackHandoff: /feedback、/handoff 路由注册验证
- TestRouter_UnknownSessionsPath_Returns405: 未知 sessions 子路径返回 405
- TestRouter_UnknownTicketsPath_Returns405: 未知 tickets 子路径返回 405
使用 HEAD 方法避免触发 nil service panic(仅验证路由注册)
**覆盖率提升**:
- internal/http (router): 41.3% → **74.7%** (+33.4%)
- 整体覆盖率: 71.3% → **73.6%** (+2.3%)
Ref: test/PHASE2_TEST_PLAN.md P0-3
2026-05-01 09:53:59 +08:00
Your Name
4123cd9e1c
test(P0-2): 补齐 postgres store ticket workflow 测试
...
新增 internal/store/postgres/ticket_workflow_test.go(8 个测试):
- TestTicketWorkflowStore_ListOpen: 开放工单查询
- TestTicketWorkflowStore_Assign: 工单分配(正常+已分配冲突)
- TestTicketWorkflowStore_Resolve: 工单解决
- TestTicketWorkflowStore_Close: 工单关闭(正常+非resolved错误)
- TestTicketWorkflowStore_NilDB: nil db 错误处理(4 个子测试)
**覆盖率提升**:
- internal/store/postgres: 43.1% → **62.0%** (+18.9%)
- 整体覆盖率: 66.2% → **71.3%** (+5.1%)
✅ Phase 2 目标 >70% 已达成
Ref: test/PHASE2_TEST_PLAN.md P0-2
2026-05-01 09:38:52 +08:00
Your Name
9def7d0cd8
test(P0-1): 补齐 memory store ticket workflow 测试
...
新增 internal/store/memory/ticket_workflow_test.go:
- TestTicketStore_ListOpen: 测试开放工单过滤逻辑
- TestTicketStore_Assign: 测试工单分配(正常+已分配冲突)
- TestTicketStore_Resolve: 测试工单解决
- TestTicketStore_Close: 测试工单关闭(正常+非resolved错误)
**覆盖率提升**:
- internal/store/memory: 59.1% → **88.3%** (+29.2%)
- 整体覆盖率: 62.6% → **66.2%** (+3.6%)
Ref: test/PHASE2_TEST_PLAN.md P0-1
2026-05-01 09:08:59 +08:00
Your Name
a6b4e519fb
test: add router and health handler tests for Phase 2 coverage
...
- TestRouter_HealthEndpoint: health/live/ready endpoints return 200
- TestRouter_UnknownPath: unknown paths return 404
- TestRouter_WebhookChannel_MissingChannel: empty channel returns 400
- TestRouter_WebhookPath_CanBeCalledWithGET: GET /webhook returns 405
- TestRouter_TicketsList_POST_Returns405: POST /tickets returns 405
- TestRouter_SessionsRoute_OnlyPOST: nil Sessions returns 404
- TestProbe defaults: IsLive=true, IsReady=false on NewProbe()
- TestProbe_SetLive/SetReady: atomic load/store correctness
Ref: PRODUCTION_PHASE1_STATUS.md §8.3 P1/P2 coverage gaps
2026-05-01 08:47:04 +08:00