← all audits

How to actually test it

One-party, two-party, groups and servers, as a runbook.

Carrier testing workflow

Headline

No carrier has a recorded live protected round-trip today. The useful next move is to run Discord L2 first, attempt Discord L3/L4, run Telegram L1, and then build Telegram’s missing commit/receive path before L2/L3. Count a pass only when the receiving OSL profile opens a fresh private marker from the exact live carrier row. A task tick, sender readback, fixture, local inbox delivery, or green harness summary is not that receipt. [RULING D59; FULL SPEC §4 “Discord” and “Telegram”; TASK 7760; TASK 7761; TASK 7762b]

What this ladder is for

This ladder answers one question: can a protected message cross the named live carrier scope and be decoded where this level says it must be decoded? It does not test every control around that path. [TASK 7760; FULL SPEC §3 “Sending a protected message” and “Finding and unpacking a received message”]

The code observations in this runbook were read from canonical branch integration/full at 4d13b8a04f48767eb9c72c2432ae9ef01caf814a; the checked-out product worktree was on a different dirty branch and was not used as canonical evidence. [CODE integration/full]

Use the four levels in order for each applicable carrier:

LevelExact meaningA pass provesIt does not prove
L1 — one-party decryptOne OSL profile and one carrier account send a fresh protected message to that same account. OSL reads the carrier-stored result and decodes it locally.The local encoder and decoder agree, and that carrier scope preserved enough of the stored cover to recover this message.Another identity can receive; peer key wrapping works; the carrier adapter can send automatically; a DM, group, or server scope works. [TASK 7760; TASK 0081; TASK 1238r]
L2 — two-party DMTwo independent OSL profiles and two owner-controlled carrier accounts use a direct message. A sends to B; B decodes. Repeat B to A.Both directions of the real DM path: distinct sender and receiver state, exact DM binding, provider storage, receiver discovery, authentication, and decrypt.Group or server scope; timer, burn, view once, files, restart, or visual camouflage. [TASK 0941; TASK 4093; TASK 7760]
L3 — two-party groupThe same two OSL identities use a private group chat or group DM containing only owner-controlled test identities. A sends to B through the group; B decodes. Repeat B to A.The pair can carry and recover a protected message at a group-chat location, and OSL does not silently reuse the DM location.Encryption to every group member or real group membership/key management unless the receipt separately proves each member. Current Discord production context still constructs DM scope, so a low-level placement in a GC is not proof of group cryptography. [TASK 0940; TASK 1026; CODE integration/full:apps/osl-hub/src/broker.rs]
L4 — two-party serverTwo owner-controlled Discord identities use a private server channel visible only to owner-controlled test identities. A sends to B in that channel; B decodes. Repeat B to A. Run a thread separately if threads are advertised.The pair can carry and recover a protected message at the exact server/channel location, including server and channel binding.Server-wide group encryption, role handling, or thread support unless those are separately exercised. Current Discord production context still constructs DM scope, so composer placement in #channel alone is not a pass. [FULL SPEC §4 “Discord”; TASK 0929; TASK 0937; CODE integration/full:apps/osl-hub/src/broker.rs]

L1 is deliberately weak. It is a fast codec-and-carrier-storage smoke test. Never promote a carrier from L1. A self-send loopback is explicitly not a genuine two-party result. [TASK 1238r; TASK 3301; TASK 7760]

What to cut from this first pass

Do not hold L1–L4 behind screenshot pixel grading, cover naturalness/classifier scores, timer, view once, burn, attachments, restart, self-healing, or the complete lifecycle matrix. Those are separate tests. They do not answer whether B can decode A’s message, and combining them is how a dead transport acquires a large green checklist. Keep one nonblank live-surface capture only because it helps prove the run touched the provider rather than a fixture. Run fidelity and lifecycle after the first real round-trip exists. [OWNER RULING “CARRIER VISUAL FIDELITY IS A PASS BAR”; RULING D37; TASK 7761; TASK 7786]

Do not make the 60-digit safety-number ceremony a prerequisite for these local owner-controlled transport runs. Provision or reuse two known test OSL identities and record which profile is which. The ceremony tests trust UX, not carrier delivery. Keep exact peer keys and independent profile stores; otherwise L2 collapses into L1. [RULING D38; RULING D12; TASK 0941]

Keep these gates because removing any one either risks a wrong destination or lets the product claim work that did not happen:

The receipt that counts

Use a fresh marker for every direction, for example L2-DISCORD-A2B-20260816-<16 random hex>. Do not reuse a fixture phrase or a marker already present in logs. Record the exact private marker in the test note so a person can compare it with the receiver output. [TASK 0940; TASK 0941; TASK 4213]

A positive receipt is one joined record containing all of the following:

1. Carrier, level, direction, UTC time, integration/full commit, packaged executable path, and executable SHA-256. [TASK 7791]

2. OSL profile A and B data-directory identifiers. L1 records one; L2–L4 record two different directories and two different OSL identity fingerprints. [TASK 0941; docs/qa/two-identity-p2p-verification.md in canonical code]

3. Carrier account A and B and their independent store/workdir identifiers. Do not write credentials, cookies, tokens, or passwords. [RULING D59; reference/LOCAL-CARRIER-IDENTITIES.md; RULING D38]

4. The exact scope: DM peer IDs; group ID plus participant IDs; or server ID, channel ID, and thread ID when applicable. A visible name alone is not enough because names can repeat. [TASK 7760; TASK 7761b; TASK 0929]

5. A before observation showing zero matching provider rows, followed by exactly one new provider row or provider message ID after the trigger. [TASK 0940; TASK 4213]

6. The exact carrier-stored cover or its SHA-256 from a provider-side read, not the bytes OSL intended to place. The carrier row must not contain the private marker. [FULL SPEC §3 step 7; TASK 7760b]

7. On the receiving OSL profile: the same provider row ID, expected author and scope, closed-eye cover state, then opened-eye exact private marker. L1 performs this after clearing the draft and reopening the actual stored self row. [RULING D11; FULL SPEC §3 receive steps 1–4; TASK 7760]

8. One nonblank capture showing the live provider row and one showing the receiver’s opened result. These captures prove contact with the live surface; they are not a pixel-fidelity verdict. [OWNER RULING “CARRIER VISUAL FIDELITY IS A PASS BAR”; TASK 4213]

9. For L2–L4, proof that the receiving profile sent nothing during the A-to-B leg, then the corresponding joined record for B to A. [TASK 0941; TASK 4093]

Call the result PASS only when all required fields come from the same run and artifact. Call it FAIL when the live run reaches the product and a required observation is wrong or absent. Call it BLOCKED — IMPLEMENTATION when the shipping product has no callable send/receive path. Call it NOT APPLICABLE when the carrier does not have that scope. Call it NOT RUN when the account or owner-only destination has not been visibly confirmed. Never turn BLOCKED, N/A, UNKNOWN, or NOT RUN into green. [TASK 7791; TASK 7791b; FULL SPEC §4 invariant]

Standard run, exactly once per applicable cell

L1 run

1. Open the carrier’s real self conversation in the one signed-in account. If the carrier has no real self conversation, mark L1 N/A; do not substitute a DM to an alt account, a server channel, a local inbox, or a saved file. An alt account is L2. [TASK 0146; TASK 0085; TASK 0085b]

2. In OSL, generate the fresh L1 private marker and produce the protected cover. Use the shipping path if it can commit; if the product only exports a local .oslmessage, a manual send may be recorded only as local-envelope-survived-carrier, not as an adapter pass. [CODE integration/full:apps/osl-hub-ui/src/main.ts; TASK 7760]

3. Commit the message in the carrier, then read the exact stored self row back from the provider. Clear the OSL draft and transient result before decoding so OSL cannot display the original input. [TASK 7760; TASK 7760b]

4. Reopen that provider row in OSL and reveal it. Pass only if the revealed text exactly equals the fresh marker and the receipt contains the provider row ID and stored-cover readback. [FULL SPEC §3 receive steps 1–4; TASK 0081]

L1 false pass: an encode-then-decode unit test, sender history, exported file round-trip, or PlacedText = input; ReadBack = input can be green while the carrier is closed. The old one-person Discord helper did exactly this without opening Discord. L1 therefore requires an external provider row ID and a post-send provider read. [TODO 39-unfailable-gates.txt, finding ONE; TASK 0081c; TASK 7760b]

L2 run

1. Start OSL-A and OSL-B with different data directories and identity fingerprints. Start carrier account A and B in their recorded independent stores. [RULING D59; reference/LOCAL-CARRIER-IDENTITIES.md; TASK 0941]

2. On both sides, visibly confirm the signed-in account and open the same owner-controlled DM. Record both account IDs and the DM/conversation ID before typing. [TASK 7760; TASK 7761b]

3. Record zero matching rows. A sends the fresh A-to-B marker through the shipping OSL trigger. Record the exact stored carrier row on A and its arrival on B. [TASK 0941; TASK 7760]

4. On OSL-B, use the receive/rehydrate path that reads B’s visible carrier transcript. Open the eye and compare the exact marker. A local OSL/keyserver inbox drain without a visible B-side carrier row fails this step. [FULL SPEC §3 receive steps 1–4; CODE integration/full:apps/osl-hub/src/main.rs; CODE integration/full:apps/osl-hub/src/broker.rs]

5. Repeat B to A with a new marker. One-way success is not L2 PASS. [TASK 4093]

L2 false pass: sender composer readback proves carry, not delivery. A green local inbox or broker-drain result can bypass the carrier, and a harness can grade a generic completed outcome as pass even when carrier placement failed. Require the B-visible provider row plus B-side transcript rehydrate and exact plaintext in one receipt. [TASK 7762b; CODE integration/full:scripts/qa/osl-p2p-loop.ps1; CODE integration/full:apps/osl-hub/src/main.rs]

L3 run

1. Open or create a private group containing only the chosen owner-controlled carrier identities. If the provider requires a third participant, use the third owner-controlled test identity; never add another person. Record the complete participant list and group ID. [RULING D38; TASK 0940; TASK 1026]

2. Run the L2 steps in the group in both directions, recording the group ID instead of a DM ID. [TASK 0940; TASK 1026]

3. In a second owner-only scope, present the same stored cover to the receiver and require refusal. This negative check is what proves the group binding rather than a carrier-blind decoder. Do not perform it in a scope containing anyone else. [TASK 7760b; FULL SPEC §2 scope-bound encryption]

L3 false pass: a low-level composer can accept text in a GC while encryption and receiver lookup remain bound to a DM pair. A DM pass replayed in a group, a group screenshot, or a locally injected group ID does not prove group scope. Current Discord canonical construction still uses HubConversationKind::Dm and ScopeKind::Dm; expect L3 to expose that missing implementation. [CODE integration/full:apps/osl-hub/src/broker.rs; TASK 0940]

L4 run

1. Create or open a private Discord test server channel whose member/role visibility contains only owner-controlled test identities. Record server ID, channel ID, both account IDs, and the visible member list. A normal server channel with other members is forbidden even if nobody appears online. [RULING D38; TASK 0929; TASK 0937]

2. Run the L2 steps in that channel in both directions. Record server and channel IDs on every sender and receiver observation. [FULL SPEC §4 “Discord”; TASK 7761]

3. Present the same stored cover in a different owner-only channel and require refusal. If threads are advertised, run a new two-direction test inside one private thread and require the parent channel copy to refuse. [TASK 7761b; FULL SPEC §2 scope binding]

L4 false pass: seeing Message #channel, placing cover in a channel composer, or decoding through the pair’s local inbox proves only location or local delivery. It does not prove server/channel scope. Current canonical production context constructs DM scope; L4 should remain red until the receiver authenticates the exact server/channel-bound row. [CODE integration/full:apps/osl-hub/src/broker.rs; CODE integration/full:apps/osl-hub/src/native_discord_adapter.rs; TASK 0937]

Carrier cards

The steps below are the provider-specific target for each cell. Every runnable cell inherits the standard level steps and the full receipt above. [TASK 7760]

Discord

Discord receipt addition: record Discord release channel, account ID, app data store, DM/group/server/channel/thread IDs, and B-side visible-transcript rehydrate. [RULING D59; TASK 0929; CODE integration/full:apps/osl-hub/src/main.rs]

Discord-specific lie: discord_release_gate.rs validates supplied booleans, not the live carrier. The old one-person helper returned its input as both placed and read-back without opening Discord. The P2 loop can open a keyserver-delivered local inbox item without reading Discord. Reject all three unless the joined receipt contains the fresh B-visible Discord row and B-side exact decrypt. [FULL SPEC §4 “Discord”; TODO 39-unfailable-gates.txt, finding ONE; CODE integration/full:apps/osl-hub/src/discord_release_gate.rs; CODE integration/full:scripts/qa/osl-p2p-loop.ps1]

Telegram

Telegram receipt addition: record both Telegram PIDs, their exact -workdir command lines, account IDs, chat/group ID, provider row ID, stored cover, and receiver-opened marker. [RULING D59; reference/LOCAL-CARRIER-IDENTITIES.md; TASK 7762]

Telegram-specific lie: the current native adapter places, reads, decodes, and clears the sender composer but has no commit verb; its live test says nothing is sent. TASK 7762’s green “two-party” test creates fake workdirs, rows, lifecycle actions, and private words in memory. The TASK 4093 runner also trusts JSON from a missing caller-supplied action script without binding it to either Telegram PID. None is a level receipt. [CODE integration/full:apps/osl-hub/src/native_telegram_adapter.rs; CODE integration/full:apps/osl-hub/tests/task_7762_telegram_protected_carrier.rs; CODE integration/full:scripts/qa/task-4093-telegram-private-bidirectional-live.ps1; FULL SPEC §4 “Telegram”]

Signal

Signal receipt addition: record both Signal PIDs, exact --user-data-dir values, account identities, conversation/group ID, and any moved-control repair or named refusal encountered before placement. [RULING “SELF-HEALING IS UNIVERSAL”; TASK 7763]

Signal-specific lie: selector and synthetic-input tests can go green without driving the live client. Canonical status says the adapter has never been driven live and refuses the only input technique shown to land. A fixture capture, composer match, or sent_count=0 run is not L1–L3. [FULL SPEC §4 “Signal”; TASK 7763b; evidence/1037.md]

WhatsApp

WhatsApp receipt addition: record the selected webview/profile, account identity, real message-document row ID and exact document readback. Accessibility Value is diagnostic only. [TASK 7764; TASK 7764b]

WhatsApp-specific lie: canonical evidence changed the accessibility Value while the real message document remained empty. A filled composer, matching Value, or captured-draft overlay can therefore look green while nothing was sent. Require the document row and other-account decrypt. [FULL SPEC §4 “WhatsApp”; TASK 7764b; evidence/7764.md]

Instagram

Instagram receipt addition: record browser/profile, signed-in account, Direct thread ID, exact recipient row, and receiver-opened marker. [TASK 7766]

Instagram-specific lie: canonical instagram_direct_message.rs is an abstract in-memory inbox. Dispatch acceptance, a contract test, a public/story composer, or one identity used twice can pass without an Instagram recipient row. [FULL SPEC §4 “Instagram”; CODE integration/full:apps/osl-hub/src/instagram_direct_message.rs; TASK 7766b]

Messenger

Messenger receipt addition: record browser/profile, account, exact private thread and provider row, author, and receiver-opened marker. [TASK 7767; TASK 7767b]

Messenger-specific lie: canonical MessengerTestMachine moves pending in-memory envelopes and private words between test accounts. A green pending-envelope, catalogue reader, Scrub reader, or sender placement has no provider row and cannot pass. [FULL SPEC §4 “Messenger”; CODE integration/full:apps/osl-hub/src/messenger_delivery.rs; TASK 7767b]

Gmail

Gmail-specific lie: opening a Gmail host, reading an Inbox list preview, or running the current BTreeMap seam can print two mailboxes and a decrypt without any Gmail request. Require the delivered provider message/thread ID and exact fetched body from the other mailbox. [FULL SPEC §4 “Shared mail implementation discrepancy”; TASK 7768b; TASK 7769b]

Outlook

Outlook-specific lie: FakeOutlookWebPage, a desktop window opening, or a web-only result can be reported as Outlook success while no desktop message is sent. Require the exact delivered body and other-mailbox decrypt for each advertised surface. Canonical status says no Outlook desktop carrier is wired. [FULL SPEC §4 “Outlook”; TASK 7770b; CODE integration/full:apps/osl-hub-ui/src/services.ts]

Proton Mail

Proton-specific lie: the in-memory mailbox boundary or a swallowed provider error can return a synthetic body and decrypt. Require a real Proton message ID, exact recipient body, and visible provider error on failure. [FULL SPEC §4 “Proton Mail”; TASK 7771b]

Yahoo Mail

Yahoo-specific lie: a seeded mailbox snapshot or stale selector can supply the expected row without touching Yahoo. Require a new Yahoo message ID and provider-fetched body; a selector that moved must repair or refuse. [FULL SPEC §4 “Yahoo Mail”; TASK 7772b]

AOL Mail

AOL-specific lie: AolFakePageFixture, an in-memory row, list-only read, or swapped author/body can go green without a delivered AOL message. Require the other mailbox’s provider message ID and full author/body read. [FULL SPEC §4 “AOL Mail”; TASK 7773b]

iCloud Mail

iCloud-specific lie: SharedMailboxSnapshot, one mailbox labelled twice, list preview, or an in-process row can imitate two-party delivery. Require two distinct mailbox IDs and the receiving provider message/body. The second iCloud identity is not established in the current sources. [FULL SPEC §4 “iCloud Mail”; TASK 7774b; TASK 7792]

What can run today on this machine

“Runnable” below means the known local identities can reach the setup. It does not mean the product will pass. The owner’s current statement and D59 establish three live Discord release-channel identities and two live Telegram workdirs; the generated account-preconditions.json says UNKNOWN because its verifier could not observe them, not because they are absent. Do the visible account preflight and test; do not reintroduce a daily account gate or ask for accounts already supplied. [RULING D59; RULING D63; proof/account-preconditions.json]

CarrierLevelTodayWhat is still missing before PASS
DiscordL1N/ANo true Discord self conversation in the shipping scope inventory. [TASK 0146]
DiscordL2Run now first. Stable and PTB provide two independent carrier identities.Two distinct registered/paired OSL profiles; correct controlled DM adoption; fix or bypass the P1/P2 false-pass grading; one B-visible Discord row plus B-side rehydrate and exact marker. No recorded live result currently exists. [RULING D59; CODE integration/full:docs/qa/two-identity-p2p-verification.md; FULL SPEC §4 “Discord”]
DiscordL3Attempt now after L2. Three owner identities are enough to form a private GC.Confirm/create the owner-only GC; implement real group scope rather than DM scope placed in a GC; obtain the joined two-direction receipt. [TASK 0940; CODE integration/full:apps/osl-hub/src/broker.rs]
DiscordL4Attempt now after L2. Two owner identities are enough to create a private test server/channel.Confirm/create an owner-only server channel; implement real server/channel scope rather than DM scope placed in #channel; obtain the joined two-direction receipt. Existing inventory evidence is not a send. [TASK 0929; TASK 0937; CODE integration/full:apps/osl-hub/src/broker.rs]
TelegramL1Run now in A’s Saved Messages as a codec/storage smoke test.The native adapter cannot commit. Until that is built, a manual envelope result must be labelled local-envelope-survived-carrier, not adapter PASS. [TASK 1028; CODE integration/full:apps/osl-hub/src/native_telegram_adapter.rs]
TelegramL2Accounts are ready; the product path is implementation-blocked.Add a real commit/send verb, provider-row observation, production receive driver bound to A/B PIDs and workdirs, and exact B-side decrypt. The current green host is in memory. [RULING D59; TASK 7762b; FULL SPEC §4 “Telegram”]
TelegramL3Accounts are ready; run after L2 exists.Confirm/create an owner-only group, then add real group binding and receiver proof. [TASK 1026; TASK 7762]
TelegramL4N/ATelegram channel/supergroup is not this ladder’s server-channel scope. [TASK 1027]

No current receipt passes any of those rows. Discord canonical status says it has never carried a message through Discord and back in a recorded two-party run. Telegram canonical status records composer carry but never delivery. [CODE integration/full:apps/osl-hub-ui/src/services.ts; FULL SPEC §4 “Discord” and “Telegram”]

For the remaining carriers:

CarrierAccount state to useProduct blocker
SignalD59 says do not request another account, but the exact second live session mapping is not established. Re-observe two identities and their data dirs before L2/L3.Adapter never driven against live Signal and send input currently refuses. [RULING D59; TASK 7763; FULL SPEC §4 “Signal”]
WhatsAppTwo owner-controlled identities are recorded. Re-observe both sessions; do not acquire another number.Accessibility Value changes but no real message-document row is created. [RULING D59; reference/LOCAL-CARRIER-IDENTITIES.md; TASK 7764]
InstagramA second isolated identity is not established.No production private composer/reader; current boundary is abstract/in-memory. [TASK 7793; TASK 7766; FULL SPEC §4 “Instagram”]
MessengerD59 says the needed accounts exist, but today’s exact two-session mapping is not established. Re-observe rather than recreate.Current carrier is MessengerTestMachine, not Messenger. [RULING D59; TASK 7767; CODE integration/full:apps/osl-hub/src/messenger_delivery.rs]
Gmail, Outlook, Proton, Yahoo, AOLD59 says the mail-pair account blocker was already met, but the current generated record is UNKNOWN. Visibly confirm each pair at preflight; do not ask the owner to recreate them.The shared mail seam creates synthetic rows and receipts in BTreeMaps; there is no live provider adapter receipt. Outlook desktop is also unwired. [RULING D59; proof/account-preconditions.json; FULL SPEC §4 “Shared mail implementation discrepancy”; CODE integration/full:apps/osl-hub/src/protected_mail_seam.rs]
iCloudOnly one mailbox is established by the current task sources; a second isolated mailbox remains missing.Same synthetic mail seam, plus the missing second mailbox for L2. [TASK 7792; TASK 7774; FULL SPEC §4 “iCloud Mail”]

X is not in this workflow. It is out of the V1 carrier roster, so testing it now would steal time from carriers the product actually claims. [RULING D20; TASK 7765; FULL SPEC §7 “Deliberately out of V1”]

Execution order

1. Discord L2. It is the shortest real two-party path with three known live identities and the only canonical live two-identity QA surface. Repair the receipt so local inbox delivery and generic green outcomes cannot pass. [RULING D59; CODE integration/full:scripts/qa/osl-p2p-loop.ps1]

2. Discord L3, then L4. Use the same two working profiles and move only the carrier location. Expect these tests to expose the current DM-only scope construction. That is useful product evidence, not a reason to avoid the run. [TASK 0940; TASK 0937; CODE integration/full:apps/osl-hub/src/broker.rs]

3. Telegram L1. Get the fast Saved Messages codec/storage result, labelled narrowly. [TASK 1028]

4. Build Telegram commit and real receiver, then run L2 and L3. Do not spend another cycle improving the fake TASK 7762 host or the ActionScript JSON contract. [TASK 7762b; CODE integration/full:apps/osl-hub/tests/task_7762_telegram_protected_carrier.rs]

5. WhatsApp next. Its two accounts exist and its blocker is already measured: the write must land in the real document. [TASK 7764; reference/LOCAL-CARRIER-IDENTITIES.md]

6. Signal, Instagram, Messenger, then mail. Re-observe existing identities first, build the real provider boundary, and run the smallest applicable level. Do not build more release gates around synthetic seams. [RULING D59; TASK 7763; TASK 7766; TASK 7767; TASK 7768b]

7. Only after the first real round-trip: run fidelity, timer, view once, burn, attachment, restart, and self-healing suites against that same working path. [OWNER RULING “CARRIER VISUAL FIDELITY IS A PASS BAR”; TASK 7786]

Result note template

RESULT: PASS | FAIL | BLOCKED — IMPLEMENTATION | NOT APPLICABLE | NOT RUN
carrier / level / direction:
integration/full commit:
packaged exe SHA-256:
OSL A profile + identity fingerprint:
OSL B profile + identity fingerprint:
carrier A account + store/workdir:
carrier B account + store/workdir:
scope type + immutable IDs:
owner-only participant check:
fresh private marker:
before matching-row count:
provider row/message ID:
exact stored-cover SHA-256:
private marker absent from carrier row:
receiver row author + scope:
receiver closed-eye value:
receiver opened-eye exact value:
receiver sent-nothing observation:
live provider capture:
receiver decrypt capture:
failure boundary, if any:

This note is evidence only when every asserted observation happened in the named live run. Leaving a field blank makes the run incomplete; filling it from a fixture, another digest, another run, or a hand-written boolean is a false proof. [TASK 7791; TASK 7791b; FULL SPEC §4 invariant]