Documentation

Messaging

Natter, the everyday messenger, and Shroud, the anonymous onion chat.

The laptop has two chat apps. Natter is an everyday messenger tied to the character's phone number. Shroud is an anonymous chat that only runs over the Onion network. On Facade, Lumen and Solace both are downloaded from the app store, see App Store. Veil runs live with every app.

#Natter

Natter is styled after WhatsApp Desktop. Players get:

  • Direct chats and groups by phone number, with group admins, descriptions and invite codes.
  • Replies, reactions, edits, deleting for everyone, forwarding, stars, pinning, archiving and muting.
  • Images by link, files from the drive, locations, contact cards and polls.
  • Disappearing messages, ticks, typing, online and last seen, profiles and privacy settings, and blocking.
  • The "end-to-end encrypted" notice with a security code per contact.

There are no calls. Natter is not anonymous: an account is the character's phone number, and who messaged whom and when is logged for police tools, though never what was written.

Natter needs a network connection, see Wi-Fi & Browsing. It runs on Veil, or on Facade, Lumen and Solace booted from the drive and signed in. It does not run on installers or Crowbar.

#Phone Numbers

The number is read through zyke_lib's phone bridge, every time the app starts. A player whose phone resource runs but who carries no phone or SIM can't use Natter until they do.

Only on servers without a phone resource does each character get a made-up number, built from messenger.numberFormat (555-#### by default, # being a random digit) and kept in zyke_laptop_messenger_numbers.

A laptop stays linked to the number it was linked with. When the owner's phone now has another number, the app says so and offers Log Out and Link the New Number.

#Linking a Laptop

Natter is linked to a laptop like WhatsApp Desktop to a phone.

  • When the phone resource takes texts, the player gets a 6-digit code from the messenger.codeSender short code and types it in. The code lasts messenger.linkCodeSeconds and stops working after 5 wrong tries. Without texts, linking needs no code.
  • A Facade, Lumen or Solace laptop stays linked through its drive, also after restarts. Anyone who gets into an unlocked laptop reads its chats and writes as its owner, so a seized laptop is evidence.
  • Erasing or reinstalling the drive unlinks it. Veil forgets the link when it shuts down.
  • Linked laptops are listed in the app's settings, where the player logs them out. messenger.maxDevices caps them, Veil links included.
  • Every new link changes the account's security code, and the people it chats with get a notice.
  • A number another character linked before, such as a recycled SIM, is registered again to the new character. Its other laptops are logged out and its history stays with the number.

#Businesses and the System Account

Other resources can register a business players message, with a name, about text, photo and verified badge, and answer them from the server. Messages can also come from the built-in "system" account, shown as Natter. See Register Messenger Business and Send Messenger Message.

#Metadata for Police

Every message sent writes a metadata row: the chat, its kind, sender, recipient in a direct chat, the message kind (text, image, file, location, contact or poll), the sending laptop's drive serial and the time. The drive is empty for Veil and for resources. Content is never logged.

Police resources read it with Get Messenger Metadata, newest first. Logging resources can listen to zyke_laptop:MessengerMessageSent, which passes the same row. Rows are kept for messenger.metadataRetentionDays.

#Hooks

Both are in server/unlocked/hooks.lua, see Can-Check Hooks.

HookDescription
CanUseMessenger(plyId)Asked when the app starts and before every request. Return false and a locale key to keep a player out, such as requiring a phone item. messengerServer:notAllowed is shown without a key.
CanReadMessengerMetadata(plyId, number)Decides who may read the metadata log through the export. Every call is allowed by default, since only server resources can make one.

Limits the metadata log to police.

Example:

lua
---@param plyId integer @ The player asking, such as an officer
---@param number string @ The account looked into
---@return boolean allowed
function CanReadMessengerMetadata(plyId, number)
    return Z.isJob(plyId, "police")
end

#Data & Retention

The zyke_laptop_messenger_* tables are created on start.

  • Messages older than messenger.retentionDays are deleted on start and once a day, with their receipts, reactions, votes and stars.
  • Disappearing messages are deleted within a minute of expiring.
  • Metadata rows go after messenger.metadataRetentionDays.
  • Accounts, linked laptops, contacts, blocks, chats and members stay.

messenger.enabled = false removes the app, its requests and its tables. Every other messenger setting is listed in Config.

#Shroud

Shroud is the anonymous onion chat. It only reaches its server over the Onion network: on Facade, Lumen and Solace the player connects with the Onion network app first, on Veil it is always onion.

#Handles & Keys

  • Players pick a handle of 3 to 20 characters: letters, numbers, dots, dashes and underscores. It can't be changed later.
  • Creating a handle shows its secret key once, such as ghost:K3V7Q2.... The server keeps only a bcrypt hash of it.
  • The key is the identity. Anyone who has it signs in as that handle, on any laptop. A handle is signed in on one player at a time; signing in elsewhere signs the other player out.
  • chat.maxIdentities caps the handles one character creates.

Where the key is kept depends on the OS:

OSKey
Facade 11 ProSaved without asking in AppData/Roaming/Shroud/identity.key in the home folder.
LumenSaved without asking in .config/shroud/identity.key in the home folder.
SolaceSaved without asking in Library/Application Support/Shroud/identity.key in the home folder.
VeilForgotten at shutdown, unless the player saves it to Persistent/Shroud/identity.key, see Persistent Folder.

Whoever gets into the account, or reads the drive with Crowbar, finds the key, see Ownership & Recovery.

#Chats, Rooms & Contacts

Players write to handles directly, talk in rooms and block handles.

  • chat.rooms lists the public rooms, lobby and market by default. A room is named by its chatServer:room:<id> and chatServer:roomDescription:<id> locale keys, or by name and description in the config.
  • Other resources add rooms, for example for a gang or a job, with Register Chat Room. An unlisted room is only joined by its id. A removed room's conversation stays readable, but nobody can write in it until it is back.
  • Other resources add contacts such as dealers and fixers, with listings, cards, forms, locations and pages in the conversation. See Shroud Contacts.

#Traces

Every message and every new handle leaves a trace that depends on the OS the sender runs. The OS is read from the server's session, so faking a shutdown hides nothing.

OSRecorded
Facade 11 ProCharacter, laptop serial, network, where the player stood
SolaceCharacter, laptop serial, network, where the player stood
LumenLaptop serial, network
VeilNothing

Change the fields per OS in chat.traces. Which character created a handle is only stored when that OS records the character. Players never see traces.

Police or hacker resources read them with Get Chat Traces. Logging resources can listen to zyke_laptop:ChatMessageSent, which passes the trace of each message. A handle that only ever wrote from Veil has no traces.

#Data & Retention

The zyke_laptop_chat_* tables are created on start. Messages and traces older than chat.retentionDays are deleted on start and once a day.

chat.enabled = false removes Shroud: the app is gone from every OS, nothing of it runs on the server, its tables aren't created and its exports aren't registered. Resources that register contacts or rooms need it on.