Research tooling. None of it is needed to manage privacy consents; it is what
was used to work out how to. Every run appends request/response pairs to
~/.local/state/tv-privacy/probe-logs/<command>-<timestamp>.jsonl, so results are
auditable rather than taken on trust. Pass --no-log to skip that.
| Command | Purpose |
|---|---|
info |
Model, firmware, pairingTypes, MAC addresses, SSDP fingerprint |
capabilities |
Sweep every read-only endpoint; reachable / errored / denied |
perms |
Map endpoints to the permission they need |
settings |
Probe candidate setting keys across all 26 categories |
set |
Write one setting; --subkey safely edits one field of an object |
methods |
Probe endpoint existence (404 absent, 401/500 present) |
raw |
Any SSAP/Luna URI with any payload |
discover |
Service list plus a settings sweep |
origins |
WebSocket Origin enforcement matrix |
roundtrip |
Instrumented power off → wait → wake → verify |
Reach for this instead of writing a new script.
tv-privacy lab raw ssap://audio/getVolume
tv-privacy lab raw ssap://settings/getSystemSettings '{"category":"picture","keys":["brightness"]}'
tv-privacy lab raw ssap://settings/getSystemSettings '{"keys":["eulaStatus"]}'On an error it prints the verbatim response frame, not just the error
string — the string alone hides whether the TV sent extra detail (such as
(not registered)) or a payload alongside the error.
The table distinguishes four outcomes, and conflating them is the mistake it exists to prevent:
| Verdict | Meaning |
|---|---|
OK |
Called successfully. |
REACHABLE |
Ran and returned 500 — the permission was granted, the arguments were wrong. |
DENIED |
401/403. The manifest genuinely lacks the permission. |
NO SUCH |
404. The endpoint does not exist on this firmware. |
setSystemSettings normally shows REACHABLE, because it is probed with an
empty settings object that the TV rejects — deliberately, so the probe cannot
change anything.
tv-privacy lab methods # the deletion-method hunt
tv-privacy lab methods --keys getVolume,setVolume # your own candidates
tv-privacy lab methods --category com.webos.service.eula # one serviceBecause 401 proves existence and 404 disproves it, a service/method matrix
maps the reachable surface without documentation.
This calls every combination. A method that exists and tolerates an empty payload may actually run. Only probe verbs whose effect you are willing to cause. The built-in candidate list is all
delete*/reset*names, which is exactly the case to think about before running — every one returned404on the test set, which is the finding, but that is not guaranteed on yours.
tv-privacy lab settings # built-in privacy candidates
tv-privacy lab settings --keys acrAllowed,livePlus
tv-privacy lab settings --category optionRuns known-good controls (picture/brightness, option/audioGuidance) first
and says so. If a control fails, every "not found" below it is meaningless and
the command tells you.
Since 500 means "no such key" rather than "forbidden", a null result is
evidence of absence — but only if the controls passed.
tv-privacy lab set --category picture --key brightness --value 51
tv-privacy lab set --key eulaStatus --subkey generalTermsAllowed --value true--subkey reads the whole object, changes one field, writes it all back, and
reports whether the other fields survived. Both forms read back afterwards and
report WRITE TOOK EFFECT or WRITE DID NOT PERSIST, because a
returnValue: true proves neither.
Values are coerced: true/false become booleans, digits become integers,
anything else stays a string.
Handshakes and registers under each Origin header, because registration
is the layer that actually enforces any allowlist — a handshake-only test is
misleading. Uses the stored key, so no prompt appears.
Relevant if you care whether a web page you visit could reach your TV.
Instrumented power cycle: reads state, sends turnOff, waits for SSAP to go
silent, holds, sends the magic packet, waits for the TV to answer again. Use it
to confirm Mobile TV On is actually enabled.
tv-privacy lab roundtrip --wait 30