docs(11-06): complete Centrifugo broadcast goldens and realtime route parity plan
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
---
|
||||
schema_version: 1
|
||||
open_count: 3
|
||||
open_count: 4
|
||||
waived_count: 0
|
||||
fixed_count: 4
|
||||
total_count: 7
|
||||
last_updated: 2026-09-29T00:27:33.153Z
|
||||
total_count: 8
|
||||
last_updated: 2026-09-30T11:32:37.302Z
|
||||
---
|
||||
|
||||
# Broken Windows Ledger
|
||||
@@ -22,6 +22,7 @@ last_updated: 2026-09-29T00:27:33.153Z
|
||||
| 5 | 10 | deviation | scripts/check-phase10.sh | | check-phase10.sh --go allow-lists exactly the two pre-existing fonoteka parity failures (TestMigrateSeedsCanonicalGenres, TestSchemaMatchesPHPSnapshot; deferred-items.md) and refuses once they pass; fix belongs to a Phase 9 follow-up | open | | 2026-09-27T16:22:23.140Z | |
|
||||
| 6 | 10.1 | stub | plugins/golem15/fonoteka/controllers/albums_admin_controller.go | 71 | fonoteka.go: discogsLookup widget action is a D-02 stub answering fixed fill {year: 1977, format: LP}; Phase 14 replaces it with the Discogs client | open | | 2026-09-29T00:27:32.945Z | |
|
||||
| 7 | 10.1 | stub | plugins/golem15/fonoteka/controllers/albums_admin_controller.go | 82 | fonoteka.go: discogsSync toolbar action is a D-02 stub answering stub_not_implemented and changing nothing; Phase 14 replaces it with the Discogs sync | open | | 2026-09-29T00:27:33.153Z | |
|
||||
| 8 | 11 | skipped-test | parity/broadcast_goldens_test.go | | fonoteka.go: TestBroadcastGoldens/created and /updated t.Skip as pending; Phase 12 turns the recorded PHP created/updated goldens into assertions (album subtree, literal created_at/updated_at and artist id handling) | open | | 2026-09-30T11:32:37.302Z | |
|
||||
|
||||
````json
|
||||
[
|
||||
@@ -115,6 +116,19 @@ last_updated: 2026-09-29T00:27:33.153Z
|
||||
"recorded_at": "2026-09-29T00:27:33.153Z",
|
||||
"resolved_at": null,
|
||||
"milestone": "v1.0"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"kind": "skipped-test",
|
||||
"phase": "11",
|
||||
"file": "parity/broadcast_goldens_test.go",
|
||||
"line": null,
|
||||
"description": "fonoteka.go: TestBroadcastGoldens/created and /updated t.Skip as pending; Phase 12 turns the recorded PHP created/updated goldens into assertions (album subtree, literal created_at/updated_at and artist id handling)",
|
||||
"status": "open",
|
||||
"reason": "",
|
||||
"recorded_at": "2026-09-30T11:32:37.302Z",
|
||||
"resolved_at": null,
|
||||
"milestone": "v1.0"
|
||||
}
|
||||
]
|
||||
````
|
||||
|
||||
@@ -0,0 +1,315 @@
|
||||
---
|
||||
phase: 11-jobs-realtime-and-search-infrastructure
|
||||
plan: 06
|
||||
subsystem: testing
|
||||
tags: [parity, tide, centrifugo, realtime, goldens, broadcasts, jwt]
|
||||
|
||||
requires:
|
||||
- phase: 11-jobs-realtime-and-search-infrastructure
|
||||
provides: "11-01 conga.StartWorker and lagoon.Transaction; 11-03 lighthouse (Bind, WithoutBroadcasting, Emit), the Centrifugo driver, the realtime token and subscribe routes"
|
||||
- phase: 02-api-parity-harness-bootstrap
|
||||
provides: "tide flows, RecordFlow, Store, structural JSON diff, loopback rules; the fonoteka parity corpus and php_parity.sh"
|
||||
provides:
|
||||
- "tide: CentrifugoRecorder (loopback fake Centrifugo), Publication, BroadcastGolden with LoadBroadcastGolden/WriteBroadcastGolden, NormalizePublications, DiffPublications, RecordBroadcasts"
|
||||
- "summer parity:broadcasts (flow, step, ids, pending, api-key)"
|
||||
- "fonoteka.go: PHP goldens deleted/bulk (asserted) and created/updated (pending Phase 12), TestBroadcastGoldens"
|
||||
- "fonoteka.go: realtime auth group, GET /api/realtime/token and POST /api/realtime/subscribe recorded from PHP and replayed green (171 tracked, 33 ported)"
|
||||
- "bouncer: jwt.auth 401 sends Cache-Control: no-cache, private"
|
||||
affects: [11-07 unit tests, 12 albums API (created/updated goldens), 15 cutover]
|
||||
|
||||
actuals:
|
||||
tokens: 27641
|
||||
tasks: 3
|
||||
commits: 2
|
||||
plan_head_before: fb4aed176a26405281702ebf466d3eb8d321a01d
|
||||
plan_head_after: 5382947ef864cdc05dbee46e344029ac57a8d8a5
|
||||
# fonoteka.go (separate repository) received 4 more commits from
|
||||
# 0ce04ab54a13c2c99f1bc02a32a089df5b0df0d6: 1223fd7, bd17fdb, 2164495, 504f6d6
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns:
|
||||
- "Broadcast parity: record PHP's Centrifugo requests through a loopback recorder, normalise only timestamps, actor and captured ids, diff structurally"
|
||||
- "One golden per event: parity:broadcasts --step runs earlier flow steps as setup and keeps only that step's publications"
|
||||
- "A masked number is a bare {{id:name}}, a masked string a quoted one, so a type change still diffs"
|
||||
- "Pending goldens are loaded, checked and reported as t.Skip, never as a pass"
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- modules/tide/centrifugo.go
|
||||
- modules/tide/centrifugo_golden.go
|
||||
- modules/tide/centrifugo_test.go
|
||||
- ../fonoteka.go/parity/broadcast_goldens_test.go
|
||||
- ../fonoteka.go/parity/realtime_seed_test.go
|
||||
- ../fonoteka.go/parity/fixtures/broadcasts/flows/album-lifecycle.yaml
|
||||
- ../fonoteka.go/parity/fixtures/broadcasts/flows/album-bulk.yaml
|
||||
- ../fonoteka.go/parity/fixtures/broadcasts/deleted.yaml
|
||||
- ../fonoteka.go/parity/fixtures/broadcasts/bulk.yaml
|
||||
- ../fonoteka.go/parity/fixtures/broadcasts/created.yaml
|
||||
- ../fonoteka.go/parity/fixtures/broadcasts/updated.yaml
|
||||
- ../fonoteka.go/parity/fixtures/routes/GET__api_realtime_token_realtime.yaml
|
||||
- ../fonoteka.go/parity/fixtures/routes/GET__api_realtime_token_realtime__no-bearer.yaml
|
||||
- ../fonoteka.go/parity/fixtures/routes/POST__api_realtime_subscribe_realtime.yaml
|
||||
- "../fonoteka.go/parity/fixtures/routes/POST__api_realtime_subscribe_realtime__{presence,wrong-secret,empty-user,unknown-namespace,double-presence,four-segments,non-member}.yaml"
|
||||
modified:
|
||||
- modules/tide/README.md
|
||||
- cmd/summer/parity.go
|
||||
- cmd/summer/main.go
|
||||
- cmd/summer/main_test.go
|
||||
- modules/bouncer/jwt.go
|
||||
- modules/bouncer/jwt_test.go
|
||||
- modules/bouncer/README.md
|
||||
- ../fonoteka.go/parity/php_parity.sh
|
||||
- ../fonoteka.go/parity/README.md
|
||||
- ../fonoteka.go/parity/manifest.yaml
|
||||
- ../fonoteka.go/parity/routes.snapshot
|
||||
- ../fonoteka.go/parity/check_corpus.go
|
||||
- ../fonoteka.go/parity/check_corpus_test.go
|
||||
- ../fonoteka.go/parity/parity_test.go
|
||||
- ../fonoteka.go/parity/parity_contract_test.go
|
||||
- ../fonoteka.go/parity/migrate_test.go
|
||||
- ../fonoteka.go/parity/genre_security_test.go
|
||||
- ../fonoteka.go/parity/capture-rules.yaml
|
||||
|
||||
key-decisions:
|
||||
- "Broadcast normalisation masks ids only under id/*_id/*_ids keys and as the numeric tail of a channel name, not every equal number, so a count such as bulk_create's count is never masked; a value matching two id variables is an error"
|
||||
- "Timestamps are masked only in the Carbon +00:00 ISO shape and the actor only when it is exactly {user_id, name}, so a format or shape change still diffs"
|
||||
- "parity:broadcasts records one golden per flow step (--step); the lifecycle flow first switches alice to the seeded id:collection so the channel uses a captured id"
|
||||
- "The recorder answers /presence, /unsubscribe and /info with empty results and 404s anything else; it never stores the Authorization value"
|
||||
- "PHP cannot allow any presence channel of this app (its collection authorizer reads the id from the second channel segment), so the corpus records the PHP deny on presence:collection:<id> and the Go port keeps it"
|
||||
- "CENTRIFUGO_SECRET test value is 40 bytes (parity-centrifugo-token-secret-test-only) because php-jwt refuses HS256 keys shorter than 32 bytes"
|
||||
- "The Go corpus target runs the Centrifugo driver with the php_parity.sh token/proxy secrets but no API key and an unreachable API URL, so replays never enqueue or send a broadcast"
|
||||
|
||||
patterns-established:
|
||||
- "Framework modules that answer on behalf of a PHP guard carry Laravel's Cache-Control: no-cache, private (bouncer write401, like wristband and the centrifugo handlers)"
|
||||
- "Case-level capture in the manifest when a route rule would also fire on a case whose response lacks the captured value"
|
||||
|
||||
requirements-completed: [RT-01, RT-02, RT-03]
|
||||
|
||||
coverage:
|
||||
- id: D1
|
||||
description: "tide fake Centrifugo recorder: records publish/broadcast (method, path, apikey match, body), answers presence/unsubscribe/info, 404 otherwise, loopback-only ListenAndServe"
|
||||
requirement: RT-03
|
||||
verification:
|
||||
- kind: unit
|
||||
ref: "modules/tide/centrifugo_test.go#TestCentrifugoRecorderRecordsPublishAndBroadcast"
|
||||
status: pass
|
||||
- kind: unit
|
||||
ref: "modules/tide/centrifugo_test.go#TestCentrifugoRecorderRefusesNonLoopback"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D2
|
||||
description: "Golden I/O, normalisation (timestamps, actor, captured ids, ambiguity error, no over-masking) and structural diff with $[i] paths; RecordBroadcasts --step against a loopback backend; parity:broadcasts registered"
|
||||
requirement: RT-03
|
||||
verification:
|
||||
- kind: unit
|
||||
ref: "modules/tide/centrifugo_test.go#TestNormalizePublications"
|
||||
status: pass
|
||||
- kind: unit
|
||||
ref: "modules/tide/centrifugo_test.go#TestDiffPublications"
|
||||
status: pass
|
||||
- kind: unit
|
||||
ref: "modules/tide/centrifugo_test.go#TestBroadcastGoldenRoundTrip"
|
||||
status: pass
|
||||
- kind: unit
|
||||
ref: "modules/tide/centrifugo_test.go#TestRecordBroadcastsStep"
|
||||
status: pass
|
||||
- kind: unit
|
||||
ref: "cmd/summer/main_test.go#TestToolCommandNames"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D3
|
||||
description: "Go deleted.fonoteka.album publication equals the PHP golden after normalisation"
|
||||
requirement: RT-03
|
||||
verification:
|
||||
- kind: integration
|
||||
ref: "../fonoteka.go/parity/broadcast_goldens_test.go#TestBroadcastGoldens/deleted"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D4
|
||||
description: "Go collection.bulk_updated {reason: bulk_create, count: 2} equals the PHP golden (exactly one publication)"
|
||||
requirement: RT-03
|
||||
verification:
|
||||
- kind: integration
|
||||
ref: "../fonoteka.go/parity/broadcast_goldens_test.go#TestBroadcastGoldens/bulk"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D5
|
||||
description: "created/updated PHP goldens recorded, parsed, event-checked and reported as SKIP pending Phase 12"
|
||||
requirement: RT-03
|
||||
verification:
|
||||
- kind: integration
|
||||
ref: "../fonoteka.go/parity/broadcast_goldens_test.go#TestBroadcastGoldens/created (SKIP by design)"
|
||||
status: pass
|
||||
human_judgment: true
|
||||
rationale: "Pending by design: Phase 12 must turn these goldens into assertions; the skip is tracked in .planning/WINDOWS.md"
|
||||
- id: D6
|
||||
description: "GET /api/realtime/token (200 token captured, 401 no bearer) and POST /api/realtime/subscribe (member allow, presence deny, wrong secret, empty user, unknown namespace, presence:presence:, four segments, non-member) recorded from PHP and replayed green; 171 recorded, 33 passing, 0 failing"
|
||||
requirement: RT-02
|
||||
verification:
|
||||
- kind: integration
|
||||
ref: "../fonoteka.go/parity/parity_test.go#TestParityCorpus/GET__api_realtime_token_realtime"
|
||||
status: pass
|
||||
- kind: integration
|
||||
ref: "../fonoteka.go/parity/parity_test.go#TestParityCorpus/POST__api_realtime_subscribe_realtime"
|
||||
status: pass
|
||||
- kind: integration
|
||||
ref: "../fonoteka.go/parity/parity_contract_test.go#TestParityContract"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
- id: D7
|
||||
description: "No Centrifugo test value, live secret or JWT in fixtures or goldens; the corpus secret scan checks Centrifugo values and X-Centrifugo-Secret headers"
|
||||
requirement: RT-01
|
||||
verification:
|
||||
- kind: unit
|
||||
ref: "../fonoteka.go/parity/check_corpus_test.go#TestUniqueAndSecretScan"
|
||||
status: pass
|
||||
- kind: other
|
||||
ref: "go run parity/check_corpus.go --manifest parity/manifest.yaml --routes <routes.php> --require-recorded --require-clients --check-secrets"
|
||||
status: pass
|
||||
human_judgment: false
|
||||
|
||||
duration: 23min
|
||||
completed: 2026-09-30
|
||||
status: complete
|
||||
---
|
||||
|
||||
# Phase 11 Plan 06: Centrifugo broadcast goldens and realtime route parity Summary
|
||||
|
||||
**`tide` now has a loopback fake Centrifugo recorder, broadcast golden files, a normaliser and a structural diff, driven by `summer parity:broadcasts`. PHP's album delete and bulk-add publications were recorded from isolated PHP, and the Go app reproduces them. The created and updated goldens are committed and pending Phase 12. The Nuxt token route and Centrifugo's subscribe proxy are recorded as 10 PHP cases and replay green against Go.**
|
||||
|
||||
## Performance
|
||||
|
||||
- **Duration:** 23 min
|
||||
- **Started:** 2026-09-30T11:08:51Z
|
||||
- **Completed:** 2026-09-30T11:32:21Z
|
||||
- **Tasks:** 3
|
||||
- **Files modified:** 39 (10 in summercms.go, 29 in fonoteka.go)
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- **tide recorder and goldens (D-10, user decision 5).**
|
||||
- `NewCentrifugoRecorder` records POSTs to `…/publish` and `…/broadcast` as `{method, path, authorization, body}`. `authorization` is only true when the header was `apikey <key>`, and the key is never stored. Bodies are capped at 1 MiB. `ListenAndServe` uses the proxy's loopback rule (T-02-01, T-11-29).
|
||||
- `NormalizePublications` masks only these values:
|
||||
- `data.timestamp` and `data.payload.timestamp` in the `+00:00` ISO shape;
|
||||
- `data.payload.actor` when it is exactly `{user_id, name}`;
|
||||
- captured `id:*` values (T-11-30).
|
||||
- `DiffPublications` checks the count, method, path, authorization flag and body. The body diff is structural and ignores key order.
|
||||
- `RecordBroadcasts` and `parity:broadcasts` refuse non-loopback targets. They refuse to write a golden that is empty or contains the API key, and they refuse a token-shaped body (T-11-28).
|
||||
- **PHP evidence.** Each PHP event produces exactly one publication. A soft delete publishes only `deleted.fonoteka.album` `{id, collection_id, action, actor, timestamp}` to `/api/publish`. Bulk publishes only `collection.bulk_updated` `{"reason":"bulk_create","count":2}`.
|
||||
- **Go matches.** `TestBroadcastGoldens/deleted` and `/bulk` pass: they boot the app with a River worker and the recorder standing in for Centrifugo. `created` and `updated` are reported as SKIP (pending).
|
||||
- **Realtime routes (D-12, D-13, RT-01, RT-02).**
|
||||
- The token route has two cases: alice's bearer gets 200 with the token captured as `jwt:centrifugo`, and a request without a bearer gets 401 `Token not provided`.
|
||||
- The subscribe proxy has eight cases. Only the member case is allowed, with `{"result":{"info":[]}}`. The other seven are HTTP 200 denies.
|
||||
- The corpus now reports 171 recorded, 33 ported, 33 passing, 0 failing and 138 pending, and the routes.php digest lock is unchanged.
|
||||
|
||||
## Task Commits
|
||||
|
||||
summercms.go:
|
||||
1. **Task 1: tide recorder, goldens and parity:broadcasts**: `9ecbf74` (feat)
|
||||
2. **Task 3 (Rule 1 fix): jwt.auth 401 Cache-Control**: `5382947` (fix)
|
||||
|
||||
fonoteka.go:
|
||||
1. **Task 1: deleted golden, php_parity.sh env, TestBroadcastGoldens/deleted**: `1223fd7` (feat)
|
||||
2. **Task 2: bulk golden, created/updated pending goldens, README section**: `bd17fdb` (feat)
|
||||
3. **Task 3: genre security test expects the PHP 401 header**: `2164495` (test)
|
||||
4. **Task 3: realtime routes recorded and replayed**: `504f6d6` (feat)
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `modules/tide/centrifugo.go`: `CentrifugoRecorder`, `Publication`, `RecordBroadcasts`, `BroadcastConfig` and the defaults.
|
||||
- `modules/tide/centrifugo_golden.go`: `BroadcastGolden` load and write, an ordered JSON codec, `NormalizePublications` and `DiffPublications`.
|
||||
- `modules/tide/centrifugo_test.go`: smoke tests for the recorder, normaliser, diff, round trip and step recording.
|
||||
- `modules/tide/README.md`: Features, Usage, API rows, and a new CLI commands section with the golden format.
|
||||
- `cmd/summer/parity.go`, `main.go`, `main_test.go`: the `parity:broadcasts` command.
|
||||
- `modules/bouncer/jwt.go`, `jwt_test.go`, `README.md`: the 401 now carries `Cache-Control: no-cache, private`.
|
||||
- fonoteka.go `parity/`:
|
||||
- `php_parity.sh`: the `CENTRIFUGO_*` values;
|
||||
- broadcast flows and goldens;
|
||||
- `broadcast_goldens_test.go` and `realtime_seed_test.go`;
|
||||
- manifest, snapshot, `check_corpus.go` and count updates;
|
||||
- capture rules;
|
||||
- the README sections "Broadcast goldens" and "Realtime routes".
|
||||
|
||||
## Decisions Made
|
||||
|
||||
See `key-decisions` in the frontmatter.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. [Rule 1 - Bug] The jwt.auth 401 lacked PHP's Cache-Control header**
|
||||
- **Found during:** Task 3 (Go replay of the `no-bearer` case)
|
||||
- **Issue:** PHP's 401 carries `Cache-Control: no-cache, private`, but bouncer's `write401` did not send it, so the replay failed with `header.Cache-Control: expected no-cache, private actual <missing>`.
|
||||
- **Fix:** `write401` now sets the header. The bouncer test asserts it, and the README mentions it. `genre_security_test.go` had used a missing Cache-Control header to prove the handler was not reached. It now asserts the header is present and relies on the jwt.auth body for that proof.
|
||||
- **Files modified:** modules/bouncer/jwt.go, jwt_test.go, README.md; ../fonoteka.go/parity/genre_security_test.go
|
||||
- **Verification:** `go test ./...` passes in both repos, and so does `TestParityCorpus/GET__api_realtime_token_realtime`.
|
||||
- **Committed in:** 5382947 (summercms.go), 2164495 (fonoteka.go)
|
||||
|
||||
**2. [Rule 3 - Blocking] The token secret was too short for php-jwt**
|
||||
- **Found during:** Task 3 (recording)
|
||||
- **Issue:** PHP returned 500 with `DomainException: Provided key is too short`, because firebase/php-jwt requires at least 32 bytes for HS256 and the planned `parity-centrifugo-token-secret` is 30 bytes.
|
||||
- **Fix:** The test-only default is now `parity-centrifugo-token-secret-test-only` (40 bytes) in php_parity.sh, the Go constant, the corpus scan list and the README.
|
||||
- **Committed in:** 504f6d6
|
||||
|
||||
**3. [Rule 3 - Blocking] The route capture rule fired on the no-bearer case**
|
||||
- **Found during:** Task 3 (recording)
|
||||
- **Issue:** The `capture-rules.yaml` `jwt:centrifugo` rule is merged into every case without its own captures. It therefore failed on the 401 `no-bearer` case, whose response has no `$.token`.
|
||||
- **Fix:** The capture is declared on the manifest `case` itself (the same rule), and recording runs without `--rules`. `capture-rules.yaml` gets only a `keep_request_headers` entry for the subscribe route. It deliberately has no capture: a capture from the request header would overwrite the vars value with the placeholder text or with the wrong-secret literal.
|
||||
- **Committed in:** 504f6d6
|
||||
|
||||
**4. [Rule 2 - Missing critical] Corpus secret scan for Centrifugo values (T-11-28)**
|
||||
- The scan in `check_corpus.go` now fails on any of the three php_parity.sh Centrifugo values. It also fails on an `X-Centrifugo-Secret` header that is neither a `{{var}}` reference nor the documented `not-the-proxy-secret` deny literal. `TestUniqueAndSecretScan` covers both checks.
|
||||
- **Committed in:** 504f6d6
|
||||
|
||||
**5. [Scope notes]**
|
||||
- **Presence case.** The must-have says "allow on a presence channel (allow and override keys)", but PHP cannot allow any presence channel in this app. For `presence:collection:<id>`, `CollectionChannelAuthorizer` parses segment 1 (`collection`) as the id, gets 0 and denies. As the plan's fallback allows, the corpus records the PHP deny, and Go matches it. The allow-and-override shape stays covered by 11-03's smoke test with a test authorizer.
|
||||
- **Normaliser scope.** `NormalizePublications` masks ids only under `id`, `*_id` and `*_ids` keys, and as the numeric tail of a channel name. The plan said "any string or number equal to a captured id". Masking every equal number would have hidden `count: 2` whenever a collection id is 2. This narrower rule masks less than the plan allowed, which is consistent with the transparency prohibition.
|
||||
- **Extra API and flags.** `RecordBroadcasts`, `BroadcastConfig`, `DefaultCentrifugoListen`, `DefaultBroadcastSettle` and `MaxPublicationBody` are new exported names, and `parity:broadcasts` gains `--step`, `--ids`, `--rules`, `--settle` and `--pending`. All of these are documented and checked with go doc.
|
||||
- **Extra fixture files.** The two planned fixture paths hold the `case` and `member` cases. The other cases use the corpus's `__<case>` suffix convention.
|
||||
- **Extra modified files.** `parity_contract_test.go` (the allow-list and count), `migrate_test.go` (`testConfig` realtime keys) and `check_corpus_test.go` were changed although the plan did not list them.
|
||||
- **Artist id.** The lifecycle flow also captures `id:artist`, so the Phase 12 album subtree has no coincidental id matches. The first recording masked an artist id as `{{id:album}}` because the two values were equal. The goldens were then re-recorded.
|
||||
|
||||
---
|
||||
|
||||
**Total deviations:** 4 auto-fixed (1 bug, 2 blocking, 1 missing critical), plus the scope notes above.
|
||||
**Impact on plan:** Fix 1 is a real parity fix in the framework guard, a non-breaking header addition. Fixes 2 and 3 were needed before PHP could be recorded at all. The scope notes narrow the masking and document one PHP behaviour. No scope creep.
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
- `pkill -f "artisan serve …"` matched the invoking shell and exited 144, which left the `php -S` child running with the old environment. The server was then stopped by its PID and restarted.
|
||||
- The deferred item from 11-05 about lighthouse callbacks running after commit for plain `gdb.Create` did not affect these goldens. All Go writes in `TestBroadcastGoldens` go through `lagoon.Transaction`, so it stays deferred to 11-07.
|
||||
|
||||
## Known Stubs
|
||||
|
||||
None. The pending created/updated goldens are intentional (the plan's user decision 5). They are tracked in `.planning/WINDOWS.md` as a skipped-test entry for Phase 12.
|
||||
|
||||
## User Setup Required
|
||||
|
||||
None. Recording needs the isolated PHP stack and `PARITY_CENTRIFUGO_API_KEY`; both are documented in the fonoteka.go parity README.
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
- **11-07 (unit tests)** should cover these recorder edges:
|
||||
- 405 and 413;
|
||||
- `waitListening` failures;
|
||||
- `flowIDNames`;
|
||||
- `decodePlaceholderJSON` error paths;
|
||||
- the `varsOutsideDir` refusal;
|
||||
- the `parity:broadcasts` flag errors.
|
||||
- **Phase 12** must turn `created.yaml` and `updated.yaml` into assertions (delete the `t.Skip` and resolve the WINDOWS.md entry). Their album subtree carries literal `created_at` and `updated_at` values, which Phase 12 must handle, for example with a broadcast normaliser extension or by re-recording with a fixed clock. It uses `{{id:album}}` and `{{id:artist}}`.
|
||||
|
||||
---
|
||||
*Phase: 11-jobs-realtime-and-search-infrastructure*
|
||||
*Completed: 2026-09-30*
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
- All 13 key created files checked exist on disk.
|
||||
- summercms.go commits 9ecbf74 and 5382947 exist, and so do fonoteka.go commits 1223fd7, bd17fdb, 2164495 and 504f6d6. Both working trees are clean apart from the pre-existing `.planning/milestone.lock` and `state.json` changes.
|
||||
- In summercms.go, `go vet ./... && go test ./...` passes. In fonoteka.go, vet and test of `./...`, `./plugins/golem15/fonoteka/...` and `./plugins/golem15/user/...` pass.
|
||||
- `TestBroadcastGoldens`: deleted and bulk PASS, created and updated SKIP.
|
||||
- `TestParityCorpus`: `recorded 171/171 passing 33 failing 0 unrecorded 0 pending 138`.
|
||||
- `check_corpus.go --require-recorded --require-clients --check-secrets` passes.
|
||||
- Every acceptance-criteria grep and go doc check of the three tasks passes.
|
||||
Reference in New Issue
Block a user