Skip to content

fix(tiles): delete the write path under a permanently-Gone endpoint - #79

Merged
rubenvdlinde merged 2 commits into
developmentfrom
fix/orphan-tile-writes
Aug 9, 2026
Merged

fix(tiles): delete the write path under a permanently-Gone endpoint#79
rubenvdlinde merged 2 commits into
developmentfrom
fix/orphan-tile-writes

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Closes one of gate-57's two orphaned write capabilities: 2 → 1.

What was wrong

TileApiController's create, update and destroy return HTTP 410 Gone unconditionally — tile creation moved onto widget placements (REQ-WDG-022 / REQ-TILE-PLACEMENT). The three TileService write methods behind them had no callers at all: not the controller, not the CLI commands, not the migrations, not the frontend. Their docblocks claimed they were "preserved for legacy callers and migration tooling" — there are neither.

Deleting rather than leaving them is the point. A write path with no caller, under a permanently-410 endpoint, is a way to put rows back into a table the app has deliberately stopped writing to — the deprecation would be bypassed by whoever wired it up next, with nothing to warn them.

getUserTiles stays: GET /api/tiles still reads the table, so existing rows remain visible. Read-only was the intended end state and is now the only state the class can express.

Why DELETE and not WIRE

"Zero callers" has two opposite fixes, and this repo contains one of each. The discriminator is the sibling seam: is there a live path that ought to be calling this and isn't?

  • Here: no. The 410 is the intended behaviour. → DELETE.
  • DashboardService::writeDashboardContent (gate-57's other finding): yes. → left alone, see below.

The other orphan is deliberately NOT fixed here

writeDashboardContent is not dead code. It is the write half of the groupfolder-storage-backend capability — 35 spec scenarios, two storage backends, a factory, two registered CLI commands — whose read, write and delete accessors all have zero callers, while launchpad:storage:migrate-to-groupfolder --prune-source already writes to that backend and NULLs the DB column.

Deleting the write half would be wrong. Wiring it means deciding where dashboard content lives — a design decision with a spec behind it, not a gate fix. Filed separately; gate-57 stays red at 1 with that reason.

Tests

The three tests asserted expects($this->never())->method('createTile') and friends. A mock expectation cannot name a method that does not exist — and it is the weaker check anyway. They now assert the methods are absent, so re-adding the write path fails a test instead of passing silently. Each test's real assertions (410 status, envelope, replacement hint) are untouched.

Measured

gate-57: 2 → 1 against this tree; still 2 against origin/development. php -l clean on both files.

Closes one of gate-57's two orphaned write capabilities.

TileApiController's create, update and destroy return HTTP 410 Gone
unconditionally — tile creation moved onto widget placements
(REQ-WDG-022 / REQ-TILE-PLACEMENT). The three TileService write methods
behind them had no callers at all: not the controller, not the CLI
commands, not the migrations, not the frontend. Their docblocks said they
were "preserved for legacy callers and migration tooling"; there are
neither, and the deprecation on the controller side is already complete.

Traced before choosing, because "zero callers" has two opposite fixes and
this repo has one of each. The other orphan gate-57 reports —
DashboardService::writeDashboardContent — is the WIRE case and is
deliberately left alone (see below). This one is the DELETE case, and the
discriminator is the sibling seam: there is no live path that ought to be
calling these and isn't. The 410 IS the intended behaviour, not a bug the
orphans would fix.

Deleting rather than leaving them is the point. A write path with no
caller, sitting under a permanently-410 endpoint, is a way to put rows
back into a table the app has deliberately stopped writing to — the
deprecation would be bypassed by whoever wired it up next, with nothing to
warn them. That is what gate-57 exists to catch.

getUserTiles stays: `GET /api/tiles` still reads the table, so existing
rows remain visible. Read-only was the intended end state and is now the
only state the class can express.

The three tests asserted `expects($this->never())->method('createTile')`
and friends. A mock expectation cannot name a method that does not exist,
and it would be the weaker check anyway — they now assert the methods are
absent, so re-adding the write path fails a test instead of passing
silently. Each test's real assertions (410 status + envelope + replacement
hint) are untouched.

NOT fixed here, deliberately: DashboardService::writeDashboardContent.
That one is not dead code — it is the write half of the
groupfolder-storage-backend capability (35 spec scenarios, two storage
backends, a factory and two registered CLI commands) whose read, write AND
delete accessors ALL have zero callers, while
`launchpad:storage:migrate-to-groupfolder --prune-source` already writes
to that backend and NULLs the DB column. Deleting the write half would be
wrong and wiring it means deciding where dashboard content lives — a
design decision with a spec behind it, not a gate fix. Filed separately.

Verified: gate-57 goes 2 -> 1 against this tree and still reports 2
against origin/development. php -l clean on both files.
…leService its @SPEC

Removing the three write methods left a blank line before the class
closer — phpcs's 'Expected 0 blank lines after function' error, and the
only ERROR in the run (everything else in that job is a pre-existing
WARNING). Also adds the canonical @SPEC tag the class docblock was
missing, pointing at openspec/specs/tiles/spec.md rather than a change
dir, since this commit rewrote that docblock anyway.
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/launchpad @ d8de3e1

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
composer ✅ 102/102
npm ✅ 548/548
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-09 15:08 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/launchpad @ bc7951f

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
composer ✅ 102/102
npm ✅ 548/548
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-09 15:14 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde
rubenvdlinde merged commit 218fe8d into development Aug 9, 2026
27 checks passed
@rubenvdlinde
rubenvdlinde deleted the fix/orphan-tile-writes branch August 9, 2026 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant