151 lines
7.8 KiB
Markdown
151 lines
7.8 KiB
Markdown
# PostgreSQL Admin State 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:** Build the authoritative PostgreSQL management-state module for config revisions,
|
|
Upstream/Routing mutations, Admin audit and reliable Outbox without storing Proxy or
|
|
per-extraction data.
|
|
|
|
**Architecture:** `domain/adminstate` defines narrow capability interfaces implemented by a
|
|
concurrency-safe MemoryStore and one deep PostgreSQL Adapter. Every mutation hides a single
|
|
transaction that commits state, audit and Outbox together. Both adapters run the same public
|
|
contract; Controller Admin maps its existing typed commands onto this seam.
|
|
|
|
**Tech Stack:** Go 1.26, standard library, pgx/v5, PostgreSQL 18, Docker Compose.
|
|
|
|
---
|
|
|
|
### Task 1: Domain Contracts and Immutable Values
|
|
|
|
**Files:**
|
|
- Create: `internal/domain/adminstate/adminstate.go`
|
|
- Create: `internal/domain/adminstate/validation_test.go`
|
|
|
|
- [x] Define `Mutator`, `SnapshotReader`, `AuditReader` and `Outbox` interfaces from ADR-006.
|
|
- [x] Define typed config, Upstream, Routing, actor, audit, event and mutation values.
|
|
- [x] Define stable errors for invalid input, missing resources, CAS conflict and unavailable
|
|
storage.
|
|
- [x] Validate non-empty bounded identifiers, UTC timestamps, unique lists, config checksum,
|
|
Routing references, claim limits and claim TTL.
|
|
- [x] Clone every slice/map/JSON value at the seam so callers cannot mutate stored state.
|
|
- [x] Run `go test -count=1 -timeout 60s ./internal/domain/adminstate` and verify the tests
|
|
fail before implementation, then pass after implementation.
|
|
- [x] Commit with `feat: define admin state transaction contracts`.
|
|
|
|
### Task 2: Memory Reference Adapter and Shared Contract
|
|
|
|
**Files:**
|
|
- Create: `internal/domain/adminstate/memory.go`
|
|
- Create: `internal/domain/adminstate/contracttest/contract.go`
|
|
- Create: `internal/domain/adminstate/contract_external_test.go`
|
|
|
|
- [x] Write a public contract factory that can create an isolated `adminstate.Store`
|
|
implementation over the four narrow capability interfaces.
|
|
- [x] Cover config commit/replay/conflict/invalid references and zero-write rollback.
|
|
- [x] Cover Upstream idempotency, monotonic revisions, mandatory audit and changed-only events.
|
|
- [x] Cover Routing CAS and 100 concurrent switches with at most one success.
|
|
- [x] Cover bounded claim, exclusive claim, lease expiry, ACK ownership and stable ordering.
|
|
- [x] Cover context cancellation and immutable Snapshot/output values.
|
|
- [x] Implement MemoryStore behind the seam with one mutex per atomic management state.
|
|
- [x] Run `go test -count=1 -timeout 60s ./internal/domain/adminstate/...`.
|
|
- [x] Commit with `feat: add transactional admin state reference store`.
|
|
|
|
### Task 3: Schema Migration and Static Data-Boundary Test
|
|
|
|
**Files:**
|
|
- Create: `internal/adapters/postgresadmin/migrations/0001_admin_state.sql`
|
|
- Create: `internal/adapters/postgresadmin/migrations.go`
|
|
- Create: `internal/adapters/postgresadmin/migrations_test.go`
|
|
|
|
- [x] Embed ordered migrations and expose one `Migrations() []Migration` read-only accessor.
|
|
- [x] Create only the six ADR-006 tables with primary/foreign keys, UTC timestamps, indexes,
|
|
outbox claim fields and bounded checks.
|
|
- [x] Add a static structure test that asserts required tables/columns are present and
|
|
forbidden Proxy/extraction/ownership/idempotency tables or columns are absent.
|
|
- [x] Test migration IDs are unique, strictly ordered and statements are transactional.
|
|
- [x] Run `go test -count=1 -timeout 60s ./internal/adapters/postgresadmin`.
|
|
- [x] Commit with `feat: add postgres admin state schema`.
|
|
|
|
### Task 4: PostgreSQL Deep Adapter
|
|
|
|
**Files:**
|
|
- Create: `internal/adapters/postgresadmin/adapter.go`
|
|
- Create: `internal/adapters/postgresadmin/mutate.go`
|
|
- Create: `internal/adapters/postgresadmin/snapshot.go`
|
|
- Create: `internal/adapters/postgresadmin/outbox.go`
|
|
- Create: `internal/adapters/postgresadmin/codec.go`
|
|
- Modify: `go.mod`
|
|
- Modify: `go.sum`
|
|
|
|
- [x] Add the approved pinned pgx/v5 dependency without changing unrelated modules.
|
|
- [x] Accept a narrow pgx pool interface and reject nil dependencies.
|
|
- [x] Implement Config/Upstream/Routing mutations with SQL validation, row locks/CAS and one
|
|
transaction for revision, state, audit and Outbox.
|
|
- [x] Map PostgreSQL constraint/CAS/connection errors to domain errors without leaking DSNs,
|
|
SQL or values.
|
|
- [x] Implement immutable Snapshot reads from one repeatable-read transaction.
|
|
- [x] Implement bounded Outbox claim using `FOR UPDATE SKIP LOCKED` and guarded ACK.
|
|
- [x] Keep SQL, tx retries, codecs and driver types private to the Adapter.
|
|
- [x] Run focused unit tests and `go vet ./internal/adapters/postgresadmin/...`.
|
|
- [x] Commit with `feat: implement postgres admin state adapter`.
|
|
|
|
### Task 5: Real PostgreSQL Contract Fixture
|
|
|
|
**Files:**
|
|
- Create: `deploy/docker-compose.postgres-test.yml`
|
|
- Create: `scripts/test-postgres.ps1`
|
|
- Create: `internal/adapters/postgresadmin/testpostgres_test.go`
|
|
- Create: `internal/adapters/postgresadmin/contract_integration_test.go`
|
|
- Create: `internal/adapters/postgresadmin/rollback_integration_test.go`
|
|
|
|
- [x] Start an isolated PostgreSQL 18 fixture on a dedicated loopback port and database.
|
|
- [x] Apply migrations through the same migration runner used by the production Adapter.
|
|
- [x] Run the public adminstate contract against a unique schema per test.
|
|
- [x] Inject audit and Outbox constraint failures and prove state/revision rollback.
|
|
- [x] Query `information_schema` and prove no Proxy, extraction, ownership or idempotency
|
|
detail tables/columns exist.
|
|
- [x] Clean only the unique test schema; do not drop shared databases or use broad cleanup.
|
|
- [x] Run `.\scripts\test-postgres.ps1` with every Go test timeout set to 60 seconds.
|
|
- [x] Commit with `test: add postgres admin state contract fixture`.
|
|
|
|
### Task 6: Admin Application Integration
|
|
|
|
**Files:**
|
|
- Create: `internal/controller/admin/service.go`
|
|
- Create: `internal/controller/admin/service_test.go`
|
|
- Modify: `internal/controller/admin/handler.go`
|
|
- Modify: `internal/controller/admin/handler_test.go`
|
|
|
|
- [x] Change Admin protection to resolve `httpsecurity.Identity` once and add actor/source IP
|
|
to mutation commands without exposing credentials.
|
|
- [x] Map typed Handler commands to `adminstate.Mutator`; map domain conflict/not-found/
|
|
invalid/unavailable errors to the existing HTTP contract.
|
|
- [x] Build Status from one adminstate Snapshot plus injected activity/worker aggregate readers.
|
|
- [x] Reload configuration with existing strict loader/validator, submit a secret-free management
|
|
snapshot, then atomically publish runtime config only after persistence succeeds.
|
|
- [x] Test persistence failure leaves the current runtime config unchanged and Redis Extract is
|
|
not referenced by the Admin module.
|
|
- [x] Run `go test -count=1 -timeout 60s ./internal/controller/admin/...`.
|
|
- [x] Commit with `feat: connect admin API to management state`.
|
|
|
|
### Task 7: Documentation and Delivery Verification
|
|
|
|
**Files:**
|
|
- Modify: `docs/development/implementation-plan.md`
|
|
- Modify: `docs/requirements/completion-audit.md`
|
|
- Modify: `docs/testing/test-strategy.md`
|
|
- Modify: `docs/operations/runbook.md`
|
|
- Modify: `progress.md`
|
|
|
|
- [x] Mark only verified PostgreSQL capabilities complete and retain command/runtime/load gaps.
|
|
- [x] Document migration, backup, Outbox backlog/replay and data-boundary checks.
|
|
- [x] Run `.\scripts\verify.ps1`, `.\scripts\test-redis.ps1`,
|
|
`.\scripts\test-postgres.ps1` and `git diff --check`.
|
|
- [x] Audit that Gateway has no PostgreSQL/Redis dependency and Distribution has no PostgreSQL
|
|
dependency.
|
|
- [x] Confirm the user-owned deletion of `proxy-pool-docs-v1.0.zip` is not staged.
|
|
- [x] Commit with `docs: record postgres admin state delivery`.
|
|
- [ ] Push the feature branch after working Git credentials are available.
|