Parental controls: gate disappearing messages, stories and anything timed to delete #63

Open
opened 2026-09-04 18:40:50 +00:00 by paulhitt · 0 comments
paulhitt commented 2026-09-04 18:40:50 +00:00 (Migrated from gitlab.com)

Parental controls today gate three things — contactsGated, storiesHidden, callsDisabled — and every one of them is about who reaches the child. Nothing gates content that deletes itself, which is the other half of the problem and arguably the harder one.

What should be gateable

A single gate, on by default when parental controls are enabled, covering everything that removes evidence on a timer:

  • Disappearing messages — the per-conversation timer (§6.11) and the per-message one (§6.17). Both set and inbound: a child must not be able to turn one on, and a message arriving with secs set must not silently self-delete on their device.
  • Stories — already partly covered by storiesHidden, but that hides the feed rather than stopping the expiry. A story is timed content by definition (1h–7d, sender-side, inside the sealed envelope).
  • Send later / scheduled send, and anything else added later that is timed.

Why this is different from the existing three

🔴 The existing gates are about contact. This one is about evidence. A parent who suspects something is wrong can look at a phone; disappearing messages mean there is nothing to look at, and the child cannot show them anything either — including when the child is the one who wants to. That asymmetry is the whole reason grooming behaviour favours ephemeral channels, and it is why this belongs with parental controls rather than in general settings.

⚠️ The inbound half is the half that matters and is the harder one. Stopping the child setting a timer is a UI change. Stopping an inbound timed message from expiring on their device means deliberately not honouring a sender's instruction — which is a real departure from what the app promises everybody else, and it has to be a deliberate, stated one. The sender is told their message disappears; on a supervised device it would not. Two honest options, and this needs a decision rather than a default:

  1. Retain, and do not tell the sender. The supervised device keeps the message. The sender's expectation is broken silently. This is what actually protects the child.
  2. Refuse, and tell the sender. The device declines timed messages outright and the sender sees a delivery refusal. Honest to the sender, and it announces that the device is supervised — which is information a person grooming a child would find useful.

My reading is that (1) is right and (2) leaks more than it buys, but that is a call for the owner, not a default to pick quietly. Whichever way it goes, /metadata and the parental-controls screen both have to say it plainly: on a supervised device, disappearing messages do not disappear.

Where it goes

  • Android: app/.../ParentalControls.kt — a fourth key beside the three above, plus enforcement in Session's inbound path (where lifetimeSeconds is applied) and in Vault.pruneExpired.
  • iOS: Sources/App/ParentalControls.swift — same shape, plus E2EInbox.pruneDisappeared and the per-message timer path.

⚠️ Both clients, or neither. A gate that exists on one platform is a gate a child can defeat by using the other, and the family would have no way to know which one they were looking at.

Not in scope

Reporting or exporting what was retained. Retaining is one decision; building a surface that shows a parent everything a child ever received is a much larger one with its own privacy argument, and bundling them would smuggle it in.

Parental controls today gate three things — `contactsGated`, `storiesHidden`, `callsDisabled` — and every one of them is about *who reaches the child*. Nothing gates **content that deletes itself**, which is the other half of the problem and arguably the harder one. ## What should be gateable A single gate, on by default when parental controls are enabled, covering everything that removes evidence on a timer: - **Disappearing messages** — the per-conversation timer (§6.11) and the per-message one (§6.17). Both set and *inbound*: a child must not be able to turn one on, and a message arriving with `secs` set must not silently self-delete on their device. - **Stories** — already partly covered by `storiesHidden`, but that hides the feed rather than stopping the expiry. A story is timed content by definition (1h–7d, sender-side, inside the sealed envelope). - **Send later / scheduled send**, and anything else added later that is timed. ## Why this is different from the existing three 🔴 **The existing gates are about contact. This one is about evidence.** A parent who suspects something is wrong can look at a phone; disappearing messages mean there is nothing to look at, and the child cannot show them anything either — including when the child is the one who wants to. That asymmetry is the whole reason grooming behaviour favours ephemeral channels, and it is why this belongs with parental controls rather than in general settings. ⚠️ **The inbound half is the half that matters and is the harder one.** Stopping the child *setting* a timer is a UI change. Stopping an inbound timed message from expiring on their device means deliberately not honouring a sender's instruction — which is a real departure from what the app promises everybody else, and it has to be a deliberate, stated one. The sender is told their message disappears; on a supervised device it would not. Two honest options, and this needs a decision rather than a default: 1. **Retain, and do not tell the sender.** The supervised device keeps the message. The sender's expectation is broken silently. This is what actually protects the child. 2. **Refuse, and tell the sender.** The device declines timed messages outright and the sender sees a delivery refusal. Honest to the sender, and it announces that the device is supervised — which is information a person grooming a child would find useful. My reading is that (1) is right and (2) leaks more than it buys, but that is a call for the owner, not a default to pick quietly. Whichever way it goes, `/metadata` and the parental-controls screen both have to say it plainly: **on a supervised device, disappearing messages do not disappear.** ## Where it goes - Android: `app/.../ParentalControls.kt` — a fourth key beside the three above, plus enforcement in `Session`'s inbound path (where `lifetimeSeconds` is applied) and in `Vault.pruneExpired`. - iOS: `Sources/App/ParentalControls.swift` — same shape, plus `E2EInbox.pruneDisappeared` and the per-message timer path. ⚠️ Both clients, or neither. A gate that exists on one platform is a gate a child can defeat by using the other, and the family would have no way to know which one they were looking at. ## Not in scope Reporting or exporting what was retained. Retaining is one decision; building a surface that shows a parent everything a child ever received is a much larger one with its own privacy argument, and bundling them would smuggle it in.
Sign in to join this conversation.