The two gates

Keeping a record is not publishing it

Two separate gates, with two separate owners. Confusing them is the mistake this plugin is built to make impossible.

Storage, and publication

Keeping a record and publishing it are two different gates, and almost every argument about chat archives is really an argument about somebody treating them as one. Storage is the operator's switch. Publication is the member's, and only the member's.

The two were confused once in production, which is why the product now states them apart rather than trusting that they are obviously different. The retention sweep belongs to the first gate and is stated in full on the consent page rather than summarised again here. The retention sweep, in full

Derived, never stored

Publication is not a flag written onto a message. It is a view, derived from the consent table every time anything is read. That one decision is why withdrawal is immediate rather than a job that has to run.

What she says on arriving 1 lines · 128 characters
By default, whatever you say here stays here, between us. I publish nothing of yours to the outside world unless you tell me to.
Source site material Block 4 section 1 · the Archive plugin, gathered 2026-08-30 in a read-only session
Forward only

Consent publishes from now, never from before

Saying yes does not hand over a history. It publishes what is said after the yes, and nothing said before it.

The rule, exactly

Opting in publishes what a member says from that moment onward. It does not reach back and publish what they said last week, last month, or before they knew the bot was there. A message qualifies only if its timestamp is at or after the opt-in and falls inside no revoked interval.

Those revoked intervals are consent gaps, and they are permanent. Anything said while consent was withdrawn stays unpublished even if the member opts in again afterwards, so restoring consent can never quietly publish what was said while it was gone.

The line in the product 1 lines · 71 characters
There is no command, console control or setting that reaches backwards.
Source site material Block 4 section 1 · the Archive plugin, gathered 2026-08-30 in a read-only session

Why it is built this way

The alternative, publishing a member's history the moment they agree, is the behaviour people expect from a chat archive and the reason they do not agree. It also makes consent unrevocable in practice: whatever went out cannot be recalled by changing a setting. Forward-only is what makes the other direction possible.

What a member types

Two words, and one of them undoes the other

The whole mechanism is a member sending a message. No form, no account, and nobody able to send it for them.

Both routes, one write path

A member types /publish or /unpublish, which are exact and act immediately, or asks in plain language and confirms. Both routes share one write path, so there is no second implementation to drift, and the plain-language route is not a lesser one.

Consent is always first-person. Asked to publish or unpublish on somebody else's behalf she refuses, and she refuses by name rather than failing quietly, because the member who did not ask for it is the one who needs to hear about it.

Asked to consent for somebody else 1 lines · 91 characters
🔒 That spell is not mine to cast. Only {name} can open that door, and only for themselves…
Source site material Block 4 section 1 · her replies in the chat · the full command replies are on the consent page
When the command itself fails 1 lines · 110 characters
Sorry - I could not process your command right now due to a temporary error. Please send it again in a moment.
Source site material Block 4 section 1 · the Archive plugin, gathered 2026-08-30 in a read-only session

The full text of both command replies is on the consent page, which owns them. This page quotes the refusal and the failure because they are the two a reader does not expect.

Hide or delete

After withdrawal, a choice with no default

Taking words down and destroying them are different things, and the member decides which one happened.

What she asks after /unpublish 1 lines · 309 characters
🌙 Your words are hidden now, and no one can see them. What shall I do with them? Say *hide* and I keep them safely out of sight; you can ask me to bring them back whenever you like. Say *delete* and I destroy them instead, and then they are gone from my archive for good. Until you tell me, they stay hidden.
Source src/interaction/settings.ts:711-716 · quoted in site material Block 4 section 1 · the hide words are forgiving, the delete words are exact

Hide: kept, and restorable

Hidden messages are retained and can be brought back, by that member and nobody else. The phrase is {wake}, restore my words, and until the member says one thing or the other the messages stay hidden. There is no default for a destructive decision.

Words that mean hide hide hidden keep keep them verbergen verstecken behalten

Delete: exact words only

Deleting destroys the messages one by one. The words that mean it are exact and there is no typo tolerance, which is deliberate: a near miss on an irreversible instruction should do nothing rather than nearly the right thing.

Words that mean delete delete destroy löschen loeschen lösche loesche vernichten

What an evidence hold can and cannot do

An evidence hold defers a destruction and never the hiding: the messages come down from the public archive at once either way, and the deferred deletion runs by itself when the hold releases. A hold cannot be used to keep something visible.

When a deletion does not complete 1 lines · 143 characters
🌙 … {held} of them did not destroy cleanly, so they are still here, hidden. I keep trying until they are gone, and the operator has been told.
Source site material Block 4 section 1 · the Archive plugin, gathered 2026-08-30 in a read-only session
How fast

At the instant, and one thing it cannot reach

Withdrawal is not a job that runs. It is a consequence of how publication is worked out in the first place.

Why there is nothing to wait for

Withdrawal takes effect at the instant, and the reason is the design decision in the first section rather than a fast job. Because publication is derived on every read, setting the revocation removes every message from all eleven public routes on the next render. There is no republish step, no cache to expire and no backfill to wait for.

The copy already taken

What the system cannot do is reach into somebody else's copy. A feed reader or a crawler that already fetched a page keeps what it fetched. The console says so rather than letting the operator believe otherwise, and so does this page.

QuestionAnswer
The two gates Storage: the per-bot "Archive capture" switch, the one-capturing-record-per-room rule, and the retention sweep bounding never-consented content. Publication: the consent table through derived views, never a stored flag. The two were confused once in production, which is why the product now states them apart
Forward-only, exactly A message publishes only when its group timestamp is at or after the member opt-in timestamp AND falls inside no revoked interval, which are the consent gaps
Hide against delete Hide is retained, restorable by that member alone. Delete is per message destruction; an evidence hold defers the destruction, never the hiding, and the deferred deletion runs by itself when the hold releases
How fast withdrawal bites Instantly, by derivation: publication is a view evaluated on every read, so setting the revocation removes every message from all eleven public routes on the next render, with no republish step, no cache and no backfill. Honest caveat, on the console: a feed reader or crawler that already fetched a copy keeps it
Stores Postgres for messages, links, consent with an append-only consent journal and gaps, holds and capture events; media on disk under MEDIA_ROOT, originals encrypted at rest with AES-256-GCM, the stripped public derivative plaintext; quarantine moved outside the served tree
Reaches outside SimpleX relays, which are the transport itself; one optional one-time video thumbnail fetch only when SimpleX delivered none, served locally afterwards. No screening provider is configured, and the null provider transmits nothing. No model on the consent path
Failure A failed consent command says so, with a dashboard alert: a consent decision is never silently dropped. A failed deletion retries durably and says so
One real interaction

The count was right, the sentence was not

Found by the operator against a running system, in a question about his own project history.

The operator asked the archive which session decided a switch from one TLS library to another. She answered with a count, and the sentence around the count claimed the switch had happened. It had not: what she had was two messages containing the terms.

What she answered 1 lines · 78 characters
I found 2 moments where this group spoke of the switch from mbedTLS to OpenSSL
Source site material Block 4 section 1 · the operator hallucination trap, found in production, and the line that ships now
What ships now 1 lines · 116 characters
🔍 I count {n} public messages in this group matching *{query}*. A word match, mind, not a memory of what was meant.
Source site material Block 4 section 1 · the operator hallucination trap, found in production, and the line that ships now

What actually changed

The count was never wrong. What was wrong was the sentence it sat in, which turned a term match into a memory of what was meant. The line that ships now returns the same number and says what kind of thing it is, which costs nothing and is the difference between a search and a claim.