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
idthe 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_MSold 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 ofPAD_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,limitat 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, elsewritten), 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_MSon (any request expired long before; the mark refuses those written before it anyway). - trim_
others - Another device’s requests and outcomes
LATE_DAYSpast their time taken out here: texts never. - trim_
own - This device’s own requests and outcomes past
KEPT_DAYStaken 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 thanEXPIRY_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
padfield to a multiple ofPAD_STEPbytes, then sealed. No line says how long its words are.