Context
PR <commit 4489eb8> shipped HTTP-level integration for the ahand gateway endpoints (controllers + guards + ValidationPipe + supertest, with the service layer mocked). That nails the wire contracts but explicitly skips the persistence + Redis layers.
This issue covers the remaining 5 scenarios from Phase 9 / Task 9.2 of the ahand integration plan (§ 9.4.4 / § 9.4.8 gateway integration matrix), which all need a testcontainer'd Postgres + Redis to exercise faithfully.
Scope
Add apps/server/apps/gateway/test/ahand-persistence.e2e-spec.ts plus a minimal Postgres + Redis fixture (testcontainers or shared pool — match existing wiki integration spec pattern at apps/server/apps/gateway/src/wikis/__tests__/integration/).
Cover:
- Idempotent webhook: same
eventId posted twice → first fires Redis presence + Socket.io emit, second returns 204 with no side effects.
- Ownership enforcement: user A POSTs
/devices/{B's id}/token/refresh → 404 (not 403; we don't reveal existence).
- Concurrent register collision: 10 simultaneous
POST /devices with the same hubDeviceId → exactly 1 succeeds, 9 get 409 (DB UNIQUE constraint on hub_device_id).
- Redis outage: kill Redis mid-test →
GET /devices still returns the row with isOnline: null, no 500.
- Hub 5xx during register: stub mock-hub-admin to 500 on the first register call → DB transaction rolls back, no row visible on retry.
Acceptance criteria
References
- Phase 9 / Task 9.2 in
docs/superpowers/plans/2026-04-22-ahand-integration-plan.md
- Existing HTTP-level integration:
apps/server/apps/gateway/test/ahand-integration.e2e-spec.ts
- Existing wiki integration spec for testcontainer pattern:
apps/server/apps/gateway/src/wikis/__tests__/integration/wiki-folder9.integration.spec.ts
Context
PR <commit 4489eb8> shipped HTTP-level integration for the ahand gateway endpoints (controllers + guards + ValidationPipe + supertest, with the service layer mocked). That nails the wire contracts but explicitly skips the persistence + Redis layers.
This issue covers the remaining 5 scenarios from Phase 9 / Task 9.2 of the ahand integration plan (§ 9.4.4 / § 9.4.8 gateway integration matrix), which all need a testcontainer'd Postgres + Redis to exercise faithfully.
Scope
Add
apps/server/apps/gateway/test/ahand-persistence.e2e-spec.tsplus a minimal Postgres + Redis fixture (testcontainers or shared pool — match existing wiki integration spec pattern atapps/server/apps/gateway/src/wikis/__tests__/integration/).Cover:
eventIdposted twice → first fires Redis presence + Socket.io emit, second returns 204 with no side effects./devices/{B's id}/token/refresh→ 404 (not 403; we don't reveal existence).POST /deviceswith the samehubDeviceId→ exactly 1 succeeds, 9 get 409 (DB UNIQUE constraint onhub_device_id).GET /devicesstill returns the row withisOnline: null, no 500.Acceptance criteria
pnpm --filter @team9/gateway test:e2e ahand-persistencetest/fixtures/and reusable from im-worker tests (Task 9.3)References
docs/superpowers/plans/2026-04-22-ahand-integration-plan.mdapps/server/apps/gateway/test/ahand-integration.e2e-spec.tsapps/server/apps/gateway/src/wikis/__tests__/integration/wiki-folder9.integration.spec.ts