Files
summercms/.planning/phases/02-api-parity-harness-bootstrap/02-01-PLAN.md
2026-09-17 01:57:41 +02:00

9.5 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
02-api-parity-harness-bootstrap 01 execute 1
go.mod
go.sum
tide/flow.go
tide/fixture.go
tide/record.go
tide/replay.go
tide/diff.go
tide/testdata/one-route-spec.yaml
tide/roundtrip_test.go
cmd/summer/main.go
cmd/summer/parity.go
cmd/summer/parity_test.go
true
QA-01
QA-02
QA-03
truths artifacts key_links
D-04: A developer can invoke `summer parity:record` and `summer parity:replay` through bonfire against one HTTP route.
D-05 D-06: The recorded versioned YAML flow contains an ordered request/response step with verbatim JSON body text.
D-12 D-13: Replaying that fixture against an arbitrary httptest HTTP backend succeeds or reports an exact structural JSON path or raw byte mismatch.
path provides
tide/flow.go Framework-owned, versioned flow and step contracts
path provides
tide/fixture.go Validated YAML load and atomic save
path provides
tide/record.go HTTP recording engine
path provides
tide/replay.go Backend-independent replay engine
path provides
cmd/summer/parity.go Bonfire parity commands
from to via
cmd/summer/main.go cmd/summer/parity.go toolCommands registration
from to via
cmd/summer/parity.go tide/record.go RecordFlow API
from to via
cmd/summer/parity.go tide/replay.go ReplayFlow API
**As a** port developer, **I want to** record one HTTP route and replay it against another backend, **so that** I can see the first parity result before porting an endpoint.

Purpose: Establish a complete fixture-to-diff path on the Phase 1 command kernel. Output: Generic tide flow schema, fixture IO, one-route recorder/replayer, and two working summer parity:* commands.

<execution_context> @/home/jin/.codex/get-shit-done/workflows/execute-plan.md @/home/jin/.codex/get-shit-done/templates/summary.md </execution_context>

@.planning/ROADMAP.md @.planning/REQUIREMENTS.md @.planning/phases/02-api-parity-harness-bootstrap/02-CONTEXT.md @.planning/phases/02-api-parity-harness-bootstrap/02-RESEARCH.md @.planning/phases/02-api-parity-harness-bootstrap/02-VALIDATION.md @.planning/phases/02-api-parity-harness-bootstrap/02-PATTERNS.md @bonfire/command.go @cmd/summer/main.go `bonfire.Command` is a value with `Name`, `Description`, `Flags []bonfire.Flag`, `Args []bonfire.Arg`, and `Run(context.Context, bonfire.Input, bonfire.Output) error`. Flags are strings; `bonfire.Input.Flag(name)` retrieves them. `cmd/summer/main.go` assembles values in `toolCommands()` and `main()` maps command errors to exit status 1.

Define the public tide contract here for later plans: Flow{Version, Name, Description, SeedHook, Steps}, Step{ID, RouteID, Request, Response, Capture, Normalize, Headers}, Request{Method, Path, Query, Headers, Body} where Query preserves the raw query string, and Response{Status, Headers, Body, BodyFile, SHA256}. Use LoadFlow, SaveFlow, RecordFlow, ReplayFlow, and a Result carrying per-step differences. Keep transport/target, fixture filesystem and output injected; neither tide nor its tests import Fonoteka.

Task 1: Record and replay one route through the summer CLI go.mod, go.sum, tide/flow.go, tide/fixture.go, tide/record.go, tide/replay.go, tide/diff.go, tide/testdata/one-route-spec.yaml, tide/roundtrip_test.go, cmd/summer/main.go, cmd/summer/parity.go, cmd/summer/parity_test.go bonfire/command.go, bonfire/root.go, cmd/summer/main.go, cmd/summer/main_test.go, .planning/phases/02-api-parity-harness-bootstrap/02-CONTEXT.md, .planning/phases/02-api-parity-harness-bootstrap/02-RESEARCH.md A local httptest server answers GET /sample with JSON. `parity:record --spec one-route-spec.yaml --target URL --output PATH` produces one valid flow; `parity:replay --fixtures PATH --target URL` succeeds; a changed response fails with `$.data` and expected/actual values. A non-JSON response changed by one byte reports the byte offset. In one committing task, write a version-1 one-step YAML request spec and black-box tests through `bonfire.NewRoot("summer", toolCommands(), writer)` plus `httptest.Server` (D-04, D-05, D-06). Run the focused tests once to observe RED without committing, then implement enough `tide.Flow`, validated YAML load/save, HTTP record/replay and `bonfire` command registration to make the complete round trip GREEN. The fixture keeps request/response body bytes as YAML literal block scalars, records status and Content-Type, and saves atomically; changed JSON scalar or non-JSON byte returns a nonzero CLI error with expected/actual diagnostics. Include both original and changed handlers in the tests. Before adding direct goccy/go-yaml to `go.mod`, review RESEARCH.md Package Legitimacy Audit and run `/home/jin/.local/bin/slopcheck scan go.mod`; after module resolution inspect `git diff -- go.mod go.sum` and scan again. Keep the package generic, preserve `toolchain go1.27.0`, and commit only after full root vet/test is green. Plan 05 expands behavior coverage. /home/jin/.local/bin/slopcheck scan go.mod && go vet ./... && go test ./... && go test ./tide ./cmd/summer -run 'TestParityRoundTrip|TestParityCommands' -count=1 - RED is observed before implementation within the task, then all tests are GREEN before its single commit. - A real one-route fixture records and replays through `summer` against httptest; changed JSON or bytes report a mismatch. - Full root `go vet ./...` and `go test ./...` pass at commit; tests use temp fixtures and injected writers. A developer can already record and replay one HTTP route through the CLI after this task commits. Task 2: Make the one-route record/replay path work go.mod, go.sum, tide/flow.go, tide/fixture.go, tide/record.go, tide/replay.go, tide/diff.go, cmd/summer/main.go, cmd/summer/parity.go, tide/roundtrip_test.go, cmd/summer/parity_test.go go.mod, bonfire/command.go, bonfire/root.go, cmd/summer/main.go, tide/testdata/one-route-spec.yaml, tide/roundtrip_test.go, cmd/summer/parity_test.go, .planning/phases/02-api-parity-harness-bootstrap/02-PATTERNS.md Refine the working Plan 01 Task 1 path into the full public `tide` contract above: strict `version: 1` goccy/go-yaml decode rejects unknown fields, empty flow names, unsafe paths and duplicate step ids (D-05, D-06); atomic save syncs before rename. Inject `http.Client` and context, bound request/response body reads, and reject truncation before committing a fixture. In `diff.go`, decode JSON with `UseNumber`, recursively compare exact key sets, array lengths, scalar values and token types while ignoring object key order; report `$.path` with expected and actual values. For non-JSON content types, compare bytes and report offset plus printable escaped bytes. Keep `parity:record` and `parity:replay` in `toolCommands()` with string flags `--spec`, `--target`, `--output`, `--fixtures`; errors return through bonfire so main exits nonzero (D-04, D-12, D-13). Reinspect the `go.mod`/`go.sum` diff and rerun slopcheck if dependency metadata changes. Do not add an app route, PHP-specific field or standalone CLI. go vet ./... && go test ./... && go test ./tide ./cmd/summer -run 'TestParityRoundTrip|TestParityCommands' -count=1 - `parity:record` writes one replayable YAML flow and `parity:replay` accepts it. - Identical JSON with changed object key order passes; missing keys and changed string/number types fail at named paths. - Non-JSON changes fail with byte diagnostics; malformed YAML and oversized bodies fail before committing a fixture. - Root `go vet ./...` and `go test ./...` exit 0. A developer can record and replay one fixture using the installed summer tool.

<threat_model>

Trust Boundaries

Boundary Description
YAML spec and HTTP target → local process Untrusted paths, headers and bodies become outbound requests and fixture files.

STRIDE Threat Register

Threat ID Category Severity Component Disposition Mitigation Plan
T-02-01 Tampering/Denial of service high tide.LoadFlow, recorder and fixture writer mitigate Strict schema, bounded request/response body, context cancellation, safe output path and atomic writes; reject partial recordings.
T-02-SC Tampering high Go module changes mitigate Apply RESEARCH.md Package Legitimacy Audit before module resolution and run slopcheck; block any package marked ASSUMED/SUS pending human verification.
</threat_model>
Run the one-route CLI smoke against httptest, then root `go vet ./...` and `go test ./...`. Confirm the written YAML can be loaded and replayed without changing the input spec.

<success_criteria> One route fixture records and replays through bonfire, a modified JSON field produces a structural path diff, and modified non-JSON bytes produce a byte diff. </success_criteria>

Create `.planning/phases/02-api-parity-harness-bootstrap/02-01-SUMMARY.md` after completion.