22 KiB
phase, plan, subsystem, tags, requires, provides, affects, actuals, plan_head_before, plan_head_after, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, coverage, duration, completed, status
| phase | plan | subsystem | tags | requires | provides | affects | actuals | plan_head_before | plan_head_after | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | coverage | duration | completed | status | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 11-jobs-realtime-and-search-infrastructure | 07 | testing |
|
|
|
|
|
6562d94ef3 |
73cfed74ed |
|
|
|
|
|
|
59min | 2026-09-30 | complete |
Phase 11 Plan 07: Phase 11 unit tests, security evidence and the phase gate Summary
Phase 11 now has branch-level tests in both repositories: 80-96% coverage in every new package, with Postgres tests on testcontainers. Three real defects were found and fixed (broadcast jobs enqueued after a single write's commit, after-commit handles that carried the write's statement, savepoints left aborted by swallowed read errors). A fail-closed check-phase11.sh --all prints "phase11 all passed", and 13 scripted removal checks prove that every high threat's test fails when its protection is removed.
Performance
- Duration: 59 min
- Started: 2026-09-30T11:56:28Z
- Completed: 2026-09-30T12:55:22Z
- Tasks: 3
- Files modified: 40 (32 in summercms.go, 4 test files in fonoteka.go, plus 4 planning files)
Accomplishments
- Task 1: jobs, scheduler and lagoon seams.
- conga tests are split into
manager_test.go,worker_test.goandcommands_test.go. They cover every outcome rule, both cancellation paths,StopJobfrom inside a job, the PHP JobManager semantics, principals, delays, registration and worker errors, queue settings,queue:workfiltering, andqueue:clearover two 10000-job batches. Coverage is 92.5%. - Scheduler tests cover validation, ordering, a missing catalog, the log writer and
dueAtfor Every(90s). The DST cases in Europe/Warsaw were already there. TestQueueMigrationsUpDowncovers the River v7 table set, thesummer_jobscolumn types and defaults, rollback one step at a time, and an idempotent rerun.- Also added: bonfire
TestCallEdgesand pactTestCadence. - fonoteka
TestFonotekaScheduleSkipsUnregisteredPrunepins the Phase 14 skip.
- conga tests are split into
- Task 2: realtime, push, search and recorder.
- lighthouse has a Postgres harness and TestBroadcastTx, TestSuppression, TestBulkEmitsOnce, TestBroadcastEdges, TestBroadcastPublishFailure and TestMountSurfaces.
- centrifugo has TestTokenClaims, TestTokenHandler, TestClientRequests and a 29-case TestProxy that ports the PHP security tests.
- flare, beachcomber, typesense and the tide recorder got their own test sets.
- fonoteka has TestWsAuthorizer, TestAlbumBroadcastBinding and TestAlbumSearchable.
- Task 3: gate and evidence.
scripts/check-phase11.shruns the detector, hygiene, both repositories' suites (including -race and a -count=3 LISTEN run), every named test and the evidence check. Its--removalharness backs 13 RC rows.11-SECURITY-REVIEW.mdhas 31 threat rows, 13 removal checks and a table of the fixes.11-VALIDATION.mdis validated.- REQUIREMENTS.md marks the seven requirement IDs complete.
Task Commits
summercms.go:
c544319: fix(11-07), lagoon after-commit callbacks get a clean handle (deferred item b)6f50b6c: fix(11-07), broadcast jobs are enqueued before GORM commits a single write (deferred item a), plus the lighthouse harness35ac96d: test(11-07), Task 1: conga, lagoon, bonfire and pact33194a1: test(11-07), Task 2: lighthouse and centrifugo6dadbf6: test(11-07), Task 2: flare6df43d4: fix(11-07), savepoint rollback after a swallowed read failure, plus the beachcomber harness and sync tests18d3097: test(11-07), Task 2: Typesense wire contract11b5b4c: test(11-07), Task 2: tide recorder edgese55d234: test(11-07), Task 2: keyless Typesense engine registration7743487: test(11-07), Task 3: check-phase11.sh and the removal harnessa34c6ec: docs(11-07), Task 3: security review and validation73cfed7: fix(11-07), check-phase10.1.sh accepts the Phase 12 pending goldens
fonoteka.go:
1657cc1: test(11-07), Task 1: schedule entry skipc222e03: test(11-07), Task 2: ws authorizers and the Album realtime and search bindings
Files Created/Modified
See key-files in the frontmatter. The production changes are modules/lagoon/transaction.go, modules/lighthouse/broadcast.go, modules/beachcomber/sync.go and their READMEs, plus scripts/check-phase10.1.sh. Everything else is tests, the gate and planning docs.
Decisions Made
See key-decisions in the frontmatter.
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] Broadcast jobs of single-statement writes were enqueued after GORM's commit (deferred item a from 11-05)
- Found during: Task 2, first lighthouse test
- Issue:
lighthouse:after_create,after_updateandafter_deletenamed only anAfteranchor, so GORM appended them pastgorm:commit_or_rollback_transaction. A plaingdb.Createtherefore enqueued its broadcast job on the pool after the commit. - RED:
TestBroadcastTx/single_statement_write_enqueues_in_its_own_transactionreported that the channels ran on[false]rather than the write's*sql.Tx. - Fix: each callback also declares
Before("gorm:commit_or_rollback_transaction"). The README now states that this holds for single writes too. - Commit:
6f50b6c. RC-05 re-proves it.
2. [Rule 1 - Bug] After-commit callbacks got a handle carrying the written model's statement (deferred item b from 11-05)
- Found during: Task 1
- Issue:
flushStatementAfterCommit,Transactionand the immediateAfterCommitpath passedSession{NewDB, Context}or the callback's own handle, and both keep the write's statement. - RED:
TestTransactionAfterCommit/callback_handle_has_a_clean_statementranSELECT "lagoon_ac_items"."id","lagoon_ac_items"."label"for a query on another model. In the plain-transaction case it also aborted the caller's transaction. - Fix: one
cleanHandlehelper (Session{NewDB, Context},Clauses(),Session{NewDB}) serves all three paths. The old identity assertion inplain_gorm_transaction_runs_nownow checks for the same connection instead. README updated. - Commit:
c544319
3. [Rule 1 - Bug] A swallowed read failure left the caller's transaction aborted
- Found during: Task 2 (
TestSyncFailuresNonFatal) - Issue: beachcomber's and lighthouse's savepoint helpers rolled back only when the inner function returned an error. fonoteka's settings Gate treats a failed read as "off" and returns no error, and so do channel functions and the lighthouse delete snapshot. In those cases the helper released the savepoint on an aborted transaction, and the caller's next statement failed with 25P02. Both READMEs promised that a failed read never aborts the caller's transaction.
- RED:
failed_gate_read_keeps_the_callers_transactionandTestBroadcastSwallowedReadFailureboth failed with 25P02. - Fix: when
RELEASE SAVEPOINTfails, the helper rolls back to the savepoint and then releases it. - Commit:
6df43d4. This commit also carries the beachcomber harness and sync tests, because those tests hold the RED case and every commit must stay green.
4. [Rule 3 - Blocking] check-phase10.1.sh --all failed on the 11-06 pending goldens
- Found during: plan verification ("check-phase10.1.sh --all still passes")
- Issue: the 10.1 detector refuses every skip. Since 11-06,
TestBroadcastGoldens/createdand/updatedskip by design until Phase 12. - Fix: the 10.1 detector accepts exactly those two skips, and only when their output carries "pending: Phase 12". Two self-test cases cover this. The gate is not weakened in general.
- Commit:
73cfed7
Plan wording and additions
TestQueueClearkept its name. The new batch and state test is namedTestClearQueueStatesAndBatches, so thatgrep -c 'func TestQueueClear'still prints 1.- A
TestSync*-named test (TestSyncEngineRegistration) was added tobeachcomber/typesense. The plan'sgo test ./modules/beachcomber/... -run '^TestSync.*$'covers that package too and would otherwise print "no tests to run", which the plan's fails_when rejects. - The gate's
--namedstage usesgo test -jsoninstead of-vtext. It gives the same per-test pass and skip evidence and is parsed more reliably. --removalis an extra gate mode, and T-11-SC gets a removal check (RC-13) in addition to the nine threats the plan listed. T-11-02 and T-11-05 get several checks each: 13 RC rows in total.TestRegistrymoved fromchannel_test.gotoregistry_test.go, and the conga tests moved out oflisten_test.go.TestJobManagerOperations,TestAttemptOutcomes,TestCancelJobandTestQueueWorkCommandbecame the plan'sTestManagerPHPSemantics,TestOutcome*,TestCancel*andTestQueueWork.
Total deviations: 4 auto-fixed (3 bugs, 1 blocking), plus the notes above. Impact on plan: the fixes change behaviour only where the code broke its documented contract. No exported API changed, and each affected README was updated in the same commit.
TDD Gate Compliance
This is a test plan for code that already existed, so most tests passed on their first run by design. Their failing-when-broken evidence is the 13 removal checks. Each of the three behaviour fixes went RED first, with the failure recorded above, and then GREEN in a single fix commit, because green-at-every-commit forbids a failing test commit.
Issues Encountered
- golang-jwt HTML-escapes
<,>and&inside claims, while PHP leaves them raw. The token is opaque to Centrifugo and the decoded claims are equal, so the token test usesa/b. This is recorded as a decision, not changed. gofmt -l modules/still lists pre-existing drift in compass, party, tide and wristband files that this plan did not touch. It is out of scope.
Known Stubs
None. The created and updated broadcast goldens remain pending for Phase 12, as 11-06 intended (already in .planning/WINDOWS.md).
Threat Flags
None. No new endpoint, auth path or schema was added; the only production changes harden existing transaction handling.
User Setup Required
None.
Next Phase Readiness
- Phase 12 must:
- turn
TestBroadcastGoldens/createdand/updatedinto assertions, then remove them fromGOLDEN_SKIPSincheck-phase11.shandAPP_PENDING_SKIPSincheck-phase10.1.sh(both gates refuse a pending skip that passes); - re-gate
SearchIDsresults in SQL.
- turn
- Phase 13 must scope
summer_jobsids through the owning import (T-11-08, accepted). - Manual backstops for /gsd-verify-work: the Nuxt app receiving an album event through a real Centrifugo v6, and a real Typesense 26.0 receiving an upsert.
Self-Check: PASSED
- All 23 created files and 16 modified files listed in key-files exist on disk.
- summercms.go commits
c544319,6f50b6c,35ac96d,33194a1,6dadbf6,6df43d4,18d3097,11b5b4c,e55d234,7743487,a34c6ecand73cfed7exist, and so do fonoteka.go commits 1657cc1 and c222e03. scripts/check-phase11.sh --allprinted "phase11 all passed" (rc 0).scripts/check-phase11.sh --removalprinted "phase11 removal passed" with 13 of 13 failing as required.scripts/check-phase10.1.sh --allprinted "phase10.1 all passed".- Acceptance greps: 31 threat rows, 13 RC rows,
nyquist_compliant: trueonce, TestWsAuthorizer 1, TestProxy 1,func TestQueueClear1,func TestCancelRunningCancelsCtx1,func TestQueueMigrationsUpDown1, Europe/Warsaw 2; conga coverage 92.5%.