8.7 KiB
Phase 2 Plan 5: Complete contract, security and integration tests Summary
Public-API negative tests lock every named parity class, proxy/CLI/pending-state contracts fail closed, and scripts/check-phase2.sh --fresh-php proves 154/154 PHP self-replay plus testcontainers Postgres
Performance
- Duration: 15 min
- Started: 2026-09-17T12:00:43Z
- Completed: 2026-09-17T12:15:30Z
- Tasks: 3
- Files modified: 8 (7 created, 1 validation doc) plus this SUMMARY
Accomplishments
- Table-driven
TestDiffContract/TestFlowContract/TestManifestContractcover null vs[], Carbon+00:00vsZ, null vs absent dates, tri-state bools, envelope/conditional keys, money string vs number, integer ids, exact slug, capture-by-reference, missing variables, and per-step normalize disable — each failure names a JSON path. TestProxySecurityandTestParityCommandContractpin loopback-only proxy, body caps, traversal, scrub of JWT/inv_/OAuth secrets, and nonzero CLI errors without printing secrets.- App
TestParityContractkeeps 154 routes recorded/pending with zero Go passes, unknown seed hooks fail, and synthetic SQL still uses testcontainers Postgres. scripts/check-phase2.sh --fresh-phpis the repeatable gate: root and app vet/test/race,TestParitySyntheticPostgres, corpus--require-recorded --require-clients --check-secrets, CLI smoke, disposable MariaDB + artisan bootstrap + 154-route and client-flow PHP self-replay.
Task Commits
Each task was committed atomically:
- Task 1: Lock down every response parity class with negative tests -
59b5276(test, summercms.go) - Task 2: Cover proxy, scrub, CLI and Go pending-state boundaries -
5ed920b(test, summercms.go) andd93392d(test, fonoteka.go) - Task 3: Run and document the repeatable phase gate -
a296e98(feat),066c3d3(fix),84a5f00(docs VALIDATION)
Plan metadata: this SUMMARY commit
Files Created/Modified
tide/diff_contract_test.go— QA-02 parity-class mutations with path-level diffstide/flow_contract_test.go— Record/Replay continuation, capture-by-reference, headers/binarytide/manifest_contract_test.go— coverage reports, duplicate/missing ids, 154-route snapshottide/proxy_security_test.go— loopback bind/upstream, caps, scrub, traversal, atomic writecmd/summer/parity_contract_test.go— CLI discovery, error exit, unclassified JWT with--vars../fonoteka.go/parity/parity_contract_test.go— pending ≠ passing, Postgres, unknown hooksscripts/check-phase2.sh— root/app vet/test/race, corpus, CLI smoke,--fresh-phpMariaDB/PHP.planning/phases/02-api-parity-harness-bootstrap/02-VALIDATION.md— measured evidence,nyquist_compliant: true
Decisions Made
- Keep MariaDB for
--fresh-php(plan), not the 02-03 SQLite file; uniqueness isfonoteka_parity_<run-id>on an ephemeral loopback port. - Hex-only process credentials so
mysql/mariadb-pcannot treat a leading-as a flag. - Client OAuth replay still merges
/tmp/summercms-parity/pkce.vars;client_secretis redacted from gate logs. - Do not re-record PHP and do not implement Fonoteka Go API endpoints in this plan.
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] MariaDB urlsafe passwords broke -p and readiness
- Found during: Task 3 (
bash scripts/check-phase2.sh --fresh-php) - Issue:
token_urlsafepasswords could start with-, somariadb -p$PASSparsed them as flags. Container also needed a real SQL ping, not onlydocker inspect. - Fix: Switch to
token_hexcredentials and wait onmariadb ... -e 'SELECT 1'. - Files modified:
scripts/check-phase2.sh - Verification: Second
--fresh-phprun exited 0 in 116s withphase2 check passed - Committed in:
066c3d3
Total deviations: 1 auto-fixed (1 blocking MariaDB readiness) Impact on plan: Required for a true empty-DB PHP self-replay. No PHP/Nuxt/MCP source changes. No Go API endpoints.
Issues Encountered
- First
--fresh-phpattempt also found leftoverphp artisan serveon 8423 (pid 3289319); the process was killed so the gate could bind. Not a plan change. TestFlowContract/unknown_capture_sourceneededOpenStoresoCaptureStepruns; a nil store skipped capture and falsely passed.- Unclassified JWT CLI record succeeded until
--varswas passed soScrubStepran. Both were fixed before the Task 1/2 commits. PHP_PARITY_TARGET=http://example.com bash scripts/check-phase2.sh --fresh-phpexits 1 withrefuse: caller-supplied PHP_PARITY_TARGET is not permitted.
User Setup Required
None - no external service configuration required. Local Docker is required for --fresh-php and for go test ./parity without -short.
Next Phase Readiness
Phase 2 complete. Ready for Phase 3 (first vertical slice: GET /_fonoteka/api/v1/genres) to swap newTarget for the real app handler, mark that route ported, and keep PHP fixtures as the acceptance test.
Verification
- Task 1:
go test ./tide -run 'TestFlowContract|TestDiffContract|TestManifestContract' -count=1pass - Task 2:
go test ./tide ./cmd/summer -run 'TestProxySecurity|TestParityCommandContract'pass; appgo test ./parity -run 'TestParitySynthetic|TestParityCorpus|TestParityContract' -count=14.888s (Postgres started) - Task 3:
bash scripts/check-phase2.sh --fresh-php116s,phase2 check passed; corpusrecorded 154/154; PHP self-replay passing 154 failing 0 unrecorded 0; seed, nuxt-browse, mcp-tools, mcp-oauth matched - Root and app
go vet ./...,go test ./...,go test -race ./...green scripts/check-phase1.shstill present;PHP_PARITY_TARGEToverride refused
Self-Check: PASSED
- Key files exist on disk
git log --grep=02-05returns Task 1–3 commits in summercms.go; fonoteka.go hasd93392d- Task acceptance criteria re-run and pass
- Plan verification command
bash scripts/check-phase2.sh --fresh-phppassed 02-VALIDATION.mdrecords measured evidence andnyquist_compliant: true
Phase: 02-api-parity-harness-bootstrap Completed: 2026-09-17