Files
tech-log-backend/docs/superpowers/plans/2026-07-28-redis-production-capability-foundation.md

94 lines
5.4 KiB
Markdown

# Redis Production Capability Foundation Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development
> (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use
> checkbox syntax for tracking.
**Goal:** Replace the adapter-only cache seam with a framework-free semantic cache contract, safe
physical key construction, and a versioned typed atomic-program foundation without claiming that a
real Redis runtime or any R2 capability is complete.
**Architecture:** `application-core` owns provider-neutral cache outcomes and mutation intent.
`adapter:outbound:cache-redis` owns physical key construction, digesting, Lua resources, program
descriptors, and typed primitive facades. Existing legacy routing remains compatible while migration
is incremental. No Redis SDK, raw command, raw key, or Lua concept crosses into core.
**Scope boundary:** This batch implements Phase 0 and selected Phase 1 foundations. Spring Data
Redis/Lettuce runtime, codec/envelope, real-service integration, topology, distributed rate limit,
idempotency, lease, session, and R2/R3 evidence remain separate implementation phases.
---
### Task 1: Add the provider-neutral cache contract
**Files:**
- Create: `src/application-core/src/main/java/dev/caskeleton/application/cache/CacheRegionPort.java`
- Create: `src/application-core/src/main/java/dev/caskeleton/application/cache/CacheLookup.java`
- Create: `src/application-core/src/main/java/dev/caskeleton/application/cache/CacheRecordMetadata.java`
- Create: `src/application-core/src/main/java/dev/caskeleton/application/cache/CacheRecordIntent.java`
- Create: `src/application-core/src/main/java/dev/caskeleton/application/cache/CacheRecordOutcome.java`
- Create: `src/application-core/src/main/java/dev/caskeleton/application/cache/CacheInvalidationOutcome.java`
- Create: `src/application-core/src/main/java/dev/caskeleton/application/cache/AuthoritativeAbsence.java`
- Test: `src/application-core/src/test/java/dev/caskeleton/application/cache/CacheRegionContractTest.java`
- [x] Write a failing test for hit/negative/miss/unavailable distinctions and immutable metadata.
- [x] Verify RED with `./gradlew :application-core:test --tests '*CacheRegionContractTest'`.
- [x] Implement only framework-free values and ports.
- [x] Verify GREEN.
### Task 2: Add canonical Redis physical keys
**Files:**
- Modify: `src/adapter/outbound/cache-redis/build.gradle`
- Create: `src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/key/RedisKeyNamespace.java`
- Create: `src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/key/RedisKeyBuilder.java`
- Create: `src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/key/RedisKeyDigest.java`
- Test: `src/adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/key/RedisKeyBuilderTest.java`
- [x] Write a failing test proving namespace isolation, one stable hash tag, bounded key bytes, and
absence of raw sensitive resource identifiers.
- [x] Verify RED.
- [x] Implement SHA-256 for opaque IDs and HMAC-SHA-256 for sensitive scopes using defensive secret
copies and length-prefixed component encoding.
- [x] Verify GREEN.
### Task 3: Add a typed, versioned atomic-program catalog
**Files:**
- Create: `src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/program/RedisProgramId.java`
- Create: `src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/program/RedisProgramDescriptor.java`
- Create: `src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/program/RedisProgramCatalog.java`
- Create: `src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/program/RedisProgramExecutor.java`
- Create: `src/adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/program/RedisAtomicPrimitives.java`
- Create: `src/adapter/outbound/cache-redis/src/main/resources/redis/scripts/compare-and-delete-v1.lua`
- Create: `src/adapter/outbound/cache-redis/src/main/resources/redis/scripts/compare-and-expire-v1.lua`
- Create: `src/adapter/outbound/cache-redis/src/main/resources/redis/scripts/set-if-absent-with-ttl-v1.lua`
- Test: `src/adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/program/RedisProgramCatalogTest.java`
- Test: `src/adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/program/RedisAtomicPrimitivesTest.java`
- [x] Write failing catalog and facade tests.
- [x] Verify RED.
- [x] Implement exact resource digest, key/argument bounds, typed status mapping, and no generic
application-facing execution surface.
- [x] Verify GREEN.
### Task 4: Record exact readiness and verify
**Files:**
- Modify: `src/adapter/outbound/cache-redis/README.md`
- Modify: `src/adapter/outbound/cache-redis/CLAUDE.md`
- Modify: `docs/superpowers/specs/2026-07-26-redis-production-capability-design.md`
- [x] Mark only contract/key/program foundation as implemented and all real runtime/capability
promotion as unimplemented.
- [x] Run:
```bash
cd src
./gradlew :application-core:check :adapter:outbound:cache-redis:check --console=plain
./gradlew verifyCleanArchitectureDependencies --console=plain
```
- [x] Do not claim Redis cache R1/R2 until a real standalone service lane and codec/runtime evidence
exist.