Skip to main content

Module texts

Module texts 

Source
Expand description

Texts on your computers, read and sent through your phone, without Sioul being the phone’s SMS app (docs/texts.md; research: docs/research/sms.md, phase b). The phone’s SMS app stays the record: a fault of Sioul’s can delay a text on the computer, never lose one on the phone.

Reading, the whole history. With READ_SMS, the phone reads its texts from Android’s provider (the inbox and the sent box, multimedia messages and group threads included: Android shows no other app the drafts, the failed or queued texts, nor a multimedia message still to download) and writes a line per message in its own log, texts/log/<phone>.jsonl (Text), every column the provider gives kept for a faithful restore. The first import goes a batch at a time. The log only grows: a text deleted on the phone gets a line of its own saying so (Text::deleted), and every device keeps what it holds.

Media. Each part of a multimedia message the phone has downloaded (pictures, sound, video, cards, words) under a size you set travels as a sealed blob of the sharing (blobs/), never inside a line (Part).

An archive. The texts and their media are kept in Sioul’s data folder on every device that shares the part, never trimmed by age, with every column a later restore of a new phone would need; that restore is not built.

Sending. A computer writes a Request in its own file (texts/send/<device>.jsonl): a random key, the phone it must leave from, the number, the words, the SIM, when it was written. The phone decides at its step (verdict), claims the key in its private Ledger (written and flushed before Android is asked), hands the text to Android, and says what happened in its own texts/outcome/<phone>.jsonl (Outcome).

Never twice (verdict): a key already in the ledger is never sent again, whatever the sharing reads again; a request written before the ledger’s mark is refused (a ledger lost with the phone’s data cannot make old requests new); a request names its phone, and another phone never sends it; one older than EXPIRY_MS on the phone’s clock, corrected by how far the writer’s clock may run ahead, is not sent; Sioul never retries, Android does (three times, “reject duplicates”); after a crash between the claim and the result, Sioul looks for the row Android filed for it, and says “Your phone may not have sent it” when there is none (doubt_after), never sending again by itself. Send again makes a new key.

Sealed at rest: every line of these stores, and every file of their media, is sealed on the device that writes it (Sealer, with a key made from the sharing key, in each device’s keyring), lines padded to steps of PAD_STEP bytes inside: a computer’s copy is unreadable without the key.

Structs§

Claim
One line of the phone’s private ledger: a key, when, what was done.
Conversation
A conversation, as the Texts page lists it.
Found
One text found by search, with its conversation.
Ledger
The phone’s private ledger, never shared: every key it decided, and its mark.
Mark
The ledger’s mark: requests written before it are never sent (a ledger lost cannot make them new).
Message
One message of a conversation, or a text being sent.
Outcome
What became of a request, as its phone says it.
Part
One part of a multimedia message: its own columns, and where its content is.
Request
A text to send, as a computer writes it.
Said
A request’s state, as the computer says it.
Shown
A part of a message, as the page shows it.
Text
A text as the phone’s provider holds it, as it travels.
Viewer
What the view needs besides the lines.

Enums§

Verdict
What the phone does with a request.

Constants§

AHEAD_MS
A request dated further ahead of the phone’s clock than this is refused: the clocks disagree.
BATCH
The first import, and each step after: at most this many texts at a time.
DAY_MS 🔒
EXPIRY_MS
A request older than this on the phone’s clock is not sent.
FOLDER
Their folder, in the data folder (an archive, never a cache).
GSM_BASIC 🔒
GSM 03.38’s basic alphabet: one septet each.
GSM_EXTENDED 🔒
Its extension table: two septets each.
KEPT_DAYS
Requests and outcomes are taken out by their device after this many days…
LATE_DAYS
…and by any device this many days later (45 in all). Texts never are.
LEDGER
The phone’s private files, in the state folder, never shared: the ledger, its mark, the reader’s marks and the import’s progress, Java’s results.
LEDGER_KEPT_MS
The ledger keeps a key this long, past any request’s life.
LOG
Each phone’s texts, a line each, the whole history.
LOOK_AFTER_MS
A claim with no word from Android this long after is looked for in the provider.
MARK
MEDIA
The media of multimedia messages, each sealed at rest by its content’s hash; never shared as a store (they travel as blobs).
MEDIA_BATCH
…and this many bytes of media.
MEDIA_CAP_MB
A part over this many bytes stays on the phone, said, unless you set another size (MB, texts.toml).
OUTCOME
Each phone’s word on each text it was asked to send.
PAD_STEP
Each line’s plain length is a multiple of this before it is sealed.
PART
The sharing’s part that carries them.
PART_KINDS
A part’s words for its kind: “texts-part-picture” and the others take a size.
READER
RESULTS
SEND
Each computer’s texts to send.
STORES
The shared stores, in that order.
WRITE_MAX
A text written on a computer: at most this many characters.

Traits§

Sealer
What seals a line at rest and opens it: the caller’s, made from the sharing key.

Functions§

append
Lines added at the end of a device’s own file, under its lock, each written whole (padded, sealed), those whose id the file holds already left out (id_of; none: every line written). Returns how many were written.
conversation_id
A conversation’s id: its people’s keys, sorted, joined.
conversations
The conversations, newest first: every text’s, and those you wrote to from a computer.
day_and_time 🔒
A moment’s day and time, for a thread: (“Today”, “14:02”), (“Monday 5 October”, “14:02”), (“Friday 3 May 2024”, “09:15”).
doubt_after
After a crash between the claim and Android’s word: what to say of a claim LOOK_AFTER_MS old with no result, given whether the provider holds a sent row Sioul filed for it (found: its row). Found: sent. Not found: “doubt”, never sent again.
file_name
A device’s name as its files name it (a line’s device).
folder
The folder of the texts: the phones’ logs, the requests and outcomes, the media; in the data folder.
is_false 🔒
is_zero 🔒
is_zero_u64 🔒
kept
What a device keeps: how many texts, and how many bytes of media here (media: those whose sealed file is on this device).
kind_of 🔒
What a part is, in a word for the page.
known_reason 🔒
A failure’s reason as the words know it.
known_refusal 🔒
A refusal’s reason as the words know it.
last_sim
The SIM a conversation last used, on the phone that sends: its texts’ sub, the newest; -1 none.
messages
A conversation’s messages, oldest first: its texts, deleted ones said, and the texts you wrote to it from a computer with their states; a request Android filed is said on its row, once.
new_key
A random key, 32 hex digits, from the system’s randomness (/dev/urandom); the clock’s when none.
no_sim 🔒
own_file
A device’s file in one of the stores under root: <store>/<device>.jsonl.
padded
A JSON object padded inside: {…,"pad":" "}, its length a multiple of PAD_STEP.
parts
How many parts a text takes, and in which alphabet: GSM’s 7 bits (160 characters in one part, 153 in each of several) or UCS-2 (70, 67) as soon as one character is outside it. Android chooses alike (divideMessage).
private_folder
The phone’s private texts folder, in the state folder: never shared.
read_file
Every line of a file that opens and reads, in order; the rest passed over.
read_logs
Every phone’s texts, oldest first, each once (by phone and row), a deletion’s line folded into its text (deleted); the whole history.
read_outcomes
read_requests
read_store 🔒
Every device’s lines of a store under root, each with its device.
record
A line added to the ledger and flushed to the disk before this returns: the claim exists before Android is asked to send.
refusal
Why a number or words are refused from a computer, if they are: several recipients (an MMS group), a short number (premium risk; Android would ask on the phone), no words, too many. None: it may go.
said
A request’s state in words, never red, never “late”: waiting for the phone (and when it last shared), sending, sent at, delivered at (only when the carrier said so), not sent and why, expired, may not have been sent.
search
The texts holding every word of query, case and accents aside, in their words, a part’s name, or their people’s names or numbers; the newest first, limit at most. For a search of the archive (the MCP server’s).
shown 🔒
A part as the page shows it: what it is and its size; too large, or not downloaded, said; on its way when its file has not come yet. The SMIL, which only lays the message out, and the text parts (in the words) are not shown apart.
state_of
What a request’s outcomes say: its latest meaningful one (delivered over sent over handed…).
time_of 🔒
The time a line says (at, else written), opened; none when it does not open.
time_of_day
“14:02”: a moment (ms) as a time of day, in now’s zone.
title_of 🔒
“Dr Martin”, “Dr Martin, Alice”, “01 99 00 12 34”.
trim_ledger
The ledger’s old keys taken out, LEDGER_KEPT_MS on (any request expired long before; the mark refuses those written before it anyway).
trim_others
Another device’s requests and outcomes LATE_DAYS past their time taken out here: texts never.
trim_own
This device’s own requests and outcomes past KEPT_DAYS taken out; its texts never (an archive). A line that does not open stays. Returns how many went.
verdict
The never-twice decision, step for step: another phone’s; decided already (the ledger holds the key, whatever the sharing read again); refused (refusal); written before the ledger’s mark; dated ahead of the phone’s clock; older than EXPIRY_MS; else sent. The time written is corrected by how far the writer’s clock may run ahead (Request::ahead, measured by the writer as an upper bound: a request looks older, never younger).
when_words 🔒
“14:02” today, “Yesterday 14:02”, “Monday 5 October 14:02”.
words_hash
A text’s words, hashed as the ledger keeps them (FNV-1a, 16 hex digits).
write_flushed 🔒
Written (or appended) and flushed to the disk, yours alone.
written
A value as written: its JSON padded with spaces inside a pad field to a multiple of PAD_STEP bytes, then sealed. No line says how long its words are.