I built a producer for a plane retired three weeks ago — so gate it, and close revoke server-side - #550
Merged
Merged
Conversation
Imgbot is free on the student pack. The only images in this repo where
compression changes what a user downloads are the 361 pet sprites under
CLIPulseCore/Sources/CLIPulseCore/Resources/Pet (4.7 MB). They are declared
via .process("Resources") in Package.swift, so they go into the app bundle --
and because that is a plain folder rather than an .xcassets catalog, actool's
compression never touches them.
Measured on a 30-file sample with zopflipng: 330.4 KB -> 283.8 KB, 14.1%,
pixel-identical when both are decoded to RGBA. Extrapolated, ~0.66 MB off the
bundle. Modest, but free and unattended.
Excluded on purpose:
*.xcassets - the App Store icon has hard requirements around alpha and
dimensions; a few hundred KB is not worth debugging a rejected
build, and actool recompresses these anyway.
screenshots - already uploaded to App Store Connect; keep them byte-identical
to what was submitted.
schedule=monthly and minKBReduced=50 keep this from becoming PR noise once the
one-time win is banked.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Asked to "build the consumer" for `pterm:`, I went to build it and found this,
in the source, measured:
RemoteSessionPlane.isEnabled = false
/// `false` — the app offers no remote sessions, TERMINALS or approvals.
remote_sessions 4 all the owner's own, last 2026-07-16
remote_session_commands 0 pending rows are never swept — a true never
remote_permission_requests 0
app_push_jobs 0 the durable zero
The remote session plane — starting CLI sessions from the phone, STREAMING THE
TERMINAL, remote approvals — was withdrawn across #499-#514, ~12,000 lines,
after measuring that no non-owner ever used it. The `pterm:` consumer was
removed with it. It has no consumer BY DESIGN, not by oversight.
So "build the consumer" is a request to un-retire that plane, and I am not
doing that as a side effect of a producer task. The replacement is alive and
shipping: the phone reaches the Mac over LAN/tailnet directly
(`LANTerminalHost` streams via `LANSessionControlClient.subscribeEvents`).
I proposed that consumer myself, last session, without checking. Same mistake
as the one in my own notes — count the population before building the
mechanism — made while quoting it.
── SO THE CORRECT ACTION IS THE OPPOSITE ─────────────────────────────
#549's producer consults only `remote_private_terminal_broadcast_enabled`.
`main.swift:496` already gates the cloud task on `RemoteSessionPlane`; the
producer did not. Flipping that ops flag would have redacted, batched and
POSTed a session's output to a topic nothing subscribes to, for a plane both
copies of that file declare retired. Not a leak — the relay authorizes and the
READ policy still scopes subscribers — but real work and real egress in
service of nothing.
`RemoteSessionPlane.shouldRunPrivateTerminalProducer(configEnabled:isPaired:)`
now ANDs the retirement. It lives there, not inline in main.swift, for the
reason that file already gives above its sibling: main.swift is an executable
target with no test bundle, and a predicate a test cannot reach is a predicate
nobody has checked — which is exactly how this one shipped unchecked.
── AND THE PYTHON PRODUCER, WHICH WAS DEFAULT-ON ─────────────────────
`helper/realtime_broadcast.py` is a complete `pterm:` producer whose gate has
DEFAULTED ON since helper 1.24.0. Two independent reasons it delivers nothing,
both measured: no consumer, and its write path (v0.65's direct mint+POST as
`r0_broadcast`) is refused by Realtime because that role holds no INSERT on
realtime.messages — invisibly, since the endpoint answers 202 either way. It
has not delivered a byte since at least 2026-08-30 while still minting a token
and issuing an HTTPS request per coalesced chunk.
New `helper/remote_session_plane.py` mirrors the flag as the third copy, and
`test_remote_session_plane.py` reads BOTH Swift sources and fails if any
disagree — the repo already runs that drift gate between the two Swift copies;
the Python one ships as a separate .pkg and is the copy most likely to be
forgotten.
── WATCHED FAIL ──────────────────────────────────────────────────────
un-retire the Swift plane -> "the ops flag must not outvote the
retirement" FAILS
set the Python copy True -> 3 tests fail, incl. both drift checks
drop the gate call from the
producer construction -> the wiring test FAILS
That last one matters: a predicate nothing calls gates nothing, and this file
family has shipped that mistake twice.
795 HelperSwift tests, 938 helper pytest (1 skipped).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…should never be filed
── v0.83 APPLIED: the server half of revoke ──────────────────────────
`remote_helper_authorize_broadcast` is the ENTIRE write-side boundary for the
private relay — `broadcast-terminal` runs as service_role, which is
rolbypassrls, so no RLS policy is consulted. It authorized on four predicates:
id, device, user, realtime_private. No status. No consent.
Revocation posts `status='stopped'`. The function never read it. So after a
user un-shared a session, the server kept authorizing writes to that session's
topic, and revocation was enforced entirely by a client that could be stale,
buggy, or replaced.
One predicate: `and rs.status in ('pending','running')`. An allowlist of live
states rather than `<> 'stopped'`, so a future terminal state does not keep
authorizing; 'pending' included so a helper broadcasting before its first
status post does not earn a 42501, which the Swift sink treats as an
authoritative denial and suppresses for 60 s.
Body is the LIVE definition read back with pg_get_functiondef plus the one
predicate — production function bodies drift, so it was not reconstructed from
the repo.
Dry-run first: all assertions passed inside a transaction, then rolled back,
and production was re-checked clean (predicate absent) before the real apply.
APPLIED as ledger 20260909013221, then verified BY HAND — and not only by
grepping the source, which proves nothing about behaviour:
row_status stopped
matched BEFORE v0.83 1 <- would have authorized
matched AFTER v0.83 0 <- raises 42501
Blast radius measured first: remote_sessions = 3, all realtime_private, all
'stopped', 0 running. It authorizes strictly less and breaks nothing live.
The three rows it newly refuses are the exact class it exists to refuse.
STILL OPEN, and the edge function now says so precisely: consent.
`cloudShared` is an in-memory helper flag never mirrored to the database, so a
never-shared but running session would still authorize. Revocation is now
enforced on both sides; consent is still client-only. The note that used to say
"do not describe revocation as server-enforced anywhere" was corrected rather
than deleted — it is half right now, and which half matters.
── v0.82: SUPERSEDED, DO NOT ASK ─────────────────────────────────────
That file's whole purpose was to obtain a grant via a Supabase support ticket.
Three things killed the ask:
1. The write path was BUILT WITHOUT IT — the relay uses service_role, which
already holds INSERT. Proven end to end before it shipped.
2. The feature it serves is RETIRED in three packages with a drift gate.
3. Its own header calls the ask a one-shot favour and says not to spend it
before knowing the design survives. It did not survive.
Marked superseded, kept not deleted: the measurements in it — the silent no-op
GRANT, the reserved membership, the NOINHERIT probe trap, the definer/bypassrls
trap — are the expensive part, and a deleted dead end gets rediscovered.
Edge function redeployed with the corrected note; boundary re-verified live
after the redeploy (bogus creds -> 403, not 500).
83 migrations, all numbers unique.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Four items, done in the order their dependencies allowed.
1 ·
broadcast-terminaldeployed ✅Live at v1,
verify_jwt=true. Verified against the deployed function, not the deploy log:tail_snapshot_resultmust be one of stdout, stderr, tail_snapshot_result2 · "Build the consumer" — I did not, and here is why
Going to build it, I found this in the source, measured:
The session plane — phone-started CLI sessions, terminal streaming, remote approvals — was withdrawn across #499–#514, ~12,000 lines, after measuring that no non-owner ever used it. The
pterm:consumer went with it. It has no consumer by design.So "build the consumer" is a request to un-retire that plane, and I am not doing that as a side effect of a producer task. The replacement is alive: the phone reaches the Mac over LAN/tailnet directly (
LANTerminalHost).I proposed that consumer myself last session without checking. Same mistake as the one in my own notes — count the population before building the mechanism — made while quoting it.
So the correct action was the opposite: #549's producer consulted only its ops flag.
main.swift:496already gates the cloud task onRemoteSessionPlane; the producer did not.shouldRunPrivateTerminalProducer(configEnabled:isPaired:)now ANDs the retirement — and lives inRemoteSessionPlanefor the reason that file already gives: main.swift is an executable target with no test bundle, and a predicate a test cannot reach is a predicate nobody has checked.3 · The Python producer, which was default-ON
helper/realtime_broadcast.pyhas had its gate defaulted ON since helper 1.24.0. Two independent reasons it delivers nothing, both measured: no consumer, and its write path is refused by Realtime becauser0_broadcastholds no INSERT — invisibly, since the endpoint answers 202 either way.New
helper/remote_session_plane.pyis the third copy of the flag;test_remote_session_plane.pyreads both Swift sources and fails if any disagree.4 · Parked items
v0.83 APPLIED — ledger
20260909013221.remote_helper_authorize_broadcasthad no status predicate, so a session retired tostatus='stopped'(exactly what revocation posts) kept authorizing. Dry-run + rollback first, then verified behaviourally, not by grep:Blast radius measured first: 3 sessions, all stopped, 0 running — authorizes strictly less, breaks nothing live.
v0.82 SUPERSEDED — do not file that support ticket. The write path was built without the grant, the feature is retired, and its own header called the ask a one-shot favour not to be spent before the design was proven. Kept, not deleted: the measurements in it are the expensive part.
Watched fail
795 HelperSwift tests · 938 helper pytest · 83 migrations unique.
🤖 Generated with Claude Code