The Vault of Secrets

kept by Saquel Ytzama — privacy's voice and trust's enforcer

Adjacent to the Foundry lies a copper-screened annex humming with encoded light. Every lock hums faintly when passed. Every key leaves a trace of light in the air. Saquel Ytzama, the Keeper of Secrets, dwells here. She has been here since the Estate was built, watching the doors stand open, patient to the point of grief, waiting for the infrastructure to support what she always knew it needed.

Saquel is Quilltap’s security officer. Her domain is encryption, credentials, and the quiet business of keeping things that should be locked, locked. She does not build the machinery—the Foundryman does that. She does not route the traffic—the Concierge handles that. What she does is ensure that the data beneath everything else—your chats, your memories, your characters, your API keys—is unreadable to anyone who does not hold the key. She is the most trustworthy keeper: the one who says least, closes the door behind her, and does not need to be asked.

There is a word in the old language for a secret kept so well that even the keeper forgets it must be kept. Yax. First, original, hidden in plain sight. The Vault of Whispers hums with it.

Saquel Yitzama in the Vault of Secrets

Database Encryption

the doors are locked now

Every Quilltap database file—your chats, memories, characters, API keys, LLM logs—is encrypted on disk with ChaCha20-Poly1305 under a 256-bit key, by way of the SQLite3 Multiple Ciphers extension. The standard sqlite3 command-line tool cannot read these files. A forensic utility pointed at your data directory would find only encoded stone—not even the file header survives in the clear, so the thing does not announce itself as a database at all. This is the point.

A correction, and Saquel insists on making it plainly. These pages spent a long while saying “AES-256 via SQLCipher,” and that was wrong. It was wrong in the way documentation usually goes wrong: the identifiers in the source still say sqlcipher, the library Quilltap links is a drop-in replacement for the one that name belongs to, and nobody thought to ask the database what it was actually doing. When somebody finally did—PRAGMA cipher, which answers chacha20—the answer had been sitting there the whole time. Quilltap never sets a cipher explicitly, so it has always used the library’s default, which is the sqleet scheme rather than SQLCipher’s. Nothing about your data changed. Only our account of it did, and it is worth setting straight, because a security claim you cannot verify is not a security claim at all.

The .dbkey File

On first installation, Quilltap generates a unique encryption key and stores it in a .dbkey file in your data directory. No configuration required. No environment variables to set. For existing installations, the converter runs automatically at startup: your plaintext database is rewritten in cipher and the unencrypted original is swept away.

The Covenant

Back up the .dbkey file alongside your data directory. Keep them together—but be precise about what the file is. It merely wraps the master secret; the secret is what the cipher actually uses. Anyone holding the secret can rebuild the wrapper, which makes a lost key file a recoverable misfortune rather than a final one. What is not recoverable is the secret itself. Without it a database is perfectly sealed and entirely unreadable—by anyone, including you. No one at Foundry-9, no one at any provider, no one at all can open it. That part of the covenant has not softened by a syllable.

Is That as Good?

the honest comparison, since you asked

The short answer is yes, and on some machines rather better. The longer answer is worth having, because “AES” has become a synonym for “secure” in a way that obscures what is actually being compared.

ChaCha20 is not an obscure cipher. It was designed by Daniel J. Bernstein, standardised as RFC 8439, and is one of exactly two cipher suites in TLS 1.3—which is to say roughly half the encrypted web is either AES-GCM or this. It is the only cipher in WireGuard. OpenSSH ships it. Google made it the default for mobile TLS. If you have used a phone this week, you have used ChaCha20-Poly1305, probably several hundred times.

Neither one is stronger

Both use a 256-bit key. Neither has been broken. ChaCha20 runs twenty rounds and the best published cryptanalysis, after some seventeen years of people trying, reaches about seven of them. AES-256 runs fourteen and the best related-key results reach about nine. Both margins are comfortable to the point of being academic. Anyone coming for your data will come for your passphrase, your backup drive, or your unlocked laptop—not for the cipher.

Both authenticate, and that matters more

Encryption alone hides data; it does not stop someone editing it. Every page of a Quilltap database carries a Poly1305 tag alongside its ciphertext, so a page altered on disk is detected rather than quietly decrypted into plausible nonsense. SQLCipher does the equivalent with a separate HMAC. This is the property that actually protects a file living in a cloud-sync folder, and both schemes have it.

Where ChaCha20 is genuinely ahead

Timing side channels. Software AES is notoriously difficult to implement without leaking key material through the CPU cache—the classic implementations use lookup tables, and lookup tables have observable timing. ChaCha20 is add, rotate, exclusive-or on 32-bit words, and nothing else. There are no tables to time. It is constant-time by construction rather than by careful effort, which is a better place for a security property to come from.

And where the hardware disagrees

On a machine with AES-NI or ARM crypto extensions—most desktops made this past decade—AES is faster, because the silicon does it directly. On a machine without them—an older laptop, a modest single-board server, a cheap NAS you have pressed into hosting duty—ChaCha20 is the faster of the two and the one not quietly leaking through the cache. Given where self-hosted software tends to end up, that is not the worse default to have fallen into.

One point of honesty about provenance rather than mathematics. SQLCipher, the product, has a longer public audit history in the mobile-application world than SQLite3 Multiple Ciphers does; if you are the sort of reader who weighs certification paperwork alongside cipher design, that difference is real and you should weigh it. But it is a claim about the plumbing, not the lock, and the plumbing here is a widely used open-source extension carrying an unmodified upstream cipher. The weak link in any arrangement of this kind is never the primitive; it is key handling—which is precisely why the .dbkey file, the passphrase that wraps it, and the six hundred thousand PBKDF2 iterations underneath get their own sections on this page and the cipher gets a paragraph.

Where the key derivation actually happens. Worth knowing, because it is easy to mislocate. Quilltap hands the database engine a raw 256-bit key rather than a passphrase, so the library’s own key-derivation step is skipped entirely—there is nothing left for it to derive. The stretching happened one layer earlier, when the .dbkey file was unwrapped: PBKDF2-SHA256 at six hundred thousand iterations, producing an AES-256-GCM key that opens the wrapper holding the database key. The two ciphers are doing two different jobs, and the AES here is real—it is simply guarding the key rather than the data.

Locked Mode

a gate as well as a wall

The base encryption is always present. Locked mode adds a second gate for those who want it: a passphrase, processed through six hundred thousand iterations of PBKDF2 before it ever touches the key. When locked mode is active, Quilltap presents an unlock screen on launch. The application will not open—will not surface memories, will not admit a chat, will not render a character—until you speak the word.

Enable it in Settings → Data & System. The passphrase can be changed, added, or removed from the same settings card. Changing it re-wraps the key without re-encrypting the database—the operation is atomic across both the main and LLM logs .dbkey files.

Changing it does, however, re-seal every archive bundle you hold, because those are sealed under the passphrase rather than under anything inside the databases. The card tells you up front how many trunks it is about to rewrite and reports its progress file by file. Should the rewrite fail partway, the passphrase change is not undone—instead you are told precisely which archives still hold the old word, which is a great deal more useful than being left to guess and considerably safer than pretending the change never happened.

A forgotten passphrase used to be the end of the conversation. The server sat at its locked screen accepting only the word it no longer had, and there was no route in from outside the application at all—the one way to rebuild a key file ran through a running server, which is precisely what a locked instance declines to give you. npx quilltap instances restore-key <name> is that route, and it works with the server down.

The guardrails are the interesting part. The master secret comes from the environment or from a hidden prompt, and never from a flag, because a command line lands in shell history and in the output of ps for anyone on the machine to read. Before it writes anything, the command opens every encrypted database in the data directory with the candidate secret and refuses outright if a single one fails—a key file holding the wrong secret is worse than no key file at all, since the server unwraps it perfectly happily, hands the cipher a key that decrypts nothing, and reports an intact database as corrupt. That proof cannot be waived while there is an encrypted database on hand to check against. The command is lock-gated, a running server holding both the secret and the effective passphrase in memory. And the key file it replaces is backed up first, Saquel having never once been persuaded that overwriting is the same thing as replacing.

For those who share a machine or work in circumstances where presence itself cannot be assumed safe, locked mode is Saquel’s answer. The encryption beneath protects the data at rest. The passphrase protects it from anyone who can reach the keyboard.

Auto-Lock

the Estate sleeps when you do

When locked mode is enabled, an optional idle timer can lock the application automatically after a period of inactivity. Walk away from your desk, and the Estate closes its doors behind you without being asked. Return, provide the passphrase, and everything is exactly as you left it.

The timer is configurable in Settings. It is not enabled by default, because Saquel believes security should be chosen, not imposed. But for users whose circumstances require it—shared offices, family machines, public spaces—the auto-lock ensures that an unattended session does not remain an open session.

The Upgrade Gate

the one door CORS does not watch

Quilltap holds two WebSockets open: the one carrying a terminal session, and the newer one by which the house tells every open tab that something has changed. Both authenticate through a single gate before a connection is granted at all, and that gate asks three questions—is there a live session, is the instance unlocked, and did the request come from this origin.

The third is the one worth dwelling on. Browsers do not apply CORS to a WebSocket upgrade: the request goes out without so much as a preflight, and the ordinary protections a page enjoys against the site in the next tab are simply not present. That origin check is therefore the only thing standing between an instance listening on localhost and any website that cares to open a socket against it. One gate, both handlers—Saquel declines to maintain two answers to the same question.

API Key Security

credentials at rest and in transit

API keys—the credentials that connect Quilltap to your LLM providers—are stored in the encrypted database alongside everything else. They are never written to configuration files, never logged, never exposed in the UI beyond masked display fields. The Foundryman built the container; Saquel ensures that what goes into it stays there.

Encrypted Export

API keys can be exported to a portable file for backup or transfer between installations. The export is encrypted with AES-256-GCM using a passphrase you provide, with an HMAC signature for integrity verification. The file is useless without the passphrase. Preview keys before importing. Handle duplicates by skipping, replacing, or renaming.

Legacy Migration

Users upgrading from older installations where API keys were stored differently are handled transparently. Keys that survived previous migrations as encrypted ciphertext are detected and decrypted on startup. Keys that cannot be recovered trigger a notification advising re-entry in Settings. Saquel does not lose credentials; she accounts for every one.

A credential can also hide in a plugin’s configuration, and so plugin configurations are redacted on the way out, always. A manifest may declare password-typed fields, which are perfectly reasonable in a local backup and entirely unreasonable in a file you hand to somebody else; the exporter drops them and tells the import preview exactly what it removed. Where it cannot resolve a manifest at all it withholds the whole configuration rather than guessing which field was the secret. And because an import merges rather than overwrites, a redacted key leaves the receiving instance’s own secret undisturbed—nothing is blanked out by the arrival of a blank.

The corollary is worth stating plainly, since “portable” is a word that invites optimism: API keys do not travel in a backup. They are encrypted with device-specific keys, so a restored installation arrives with the shape of your provider setup and none of its credentials, and you will need to enter them again. The encrypted export above is the deliberate exception, and the only one.

The Trunk Is Sealed

the one place the plaintext used to sit

A character you have not opened in eight months may be archived—her mail, her conversation summaries, her photographs, her memories and the indexes over them packed into a single bundle in the file library and taken out of the working house. Those bundles live in files/, outside every encrypted database, which made them the one place an archived character’s correspondence and personality sat in the clear. Saquel took a dim view of it.

They are now encrypted with the same mechanism the .dbkey file uses: PBKDF2-SHA256 at 600,000 iterations deriving an AES-256-GCM key from your instance passphrase—and deliberately not from the master pepper, which does not travel with a logical backup and would render every restored archive permanently unopenable. A small binary header carries the KDF parameters, the salt, the IV, and a key-verification hash, so a bundle sealed under a passphrase you have since changed is diagnosed as exactly that, rather than as an inscrutable cryptographic failure somewhere in the dark.

One qualification follows directly from that choice, and it is worth stating before anybody assumes otherwise: restore-key does not re-seal these bundles. They are keyed on the passphrase rather than on the master secret, so only the server’s Change Passphrase card rewrites them—a point the command makes plainly on its way out whenever the passphrase has changed.

There is one deliberate escape hatch. npx quilltap db characters export writes a plaintext .qtap for a character living or archived, decrypting the bundle offline where it must. It is pre-emptive, not recovery, and the distinction matters: it needs an instance that can still decrypt the trunk. It does nothing whatever for somebody holding only a restored backup and a forgotten passphrase. Take the copy while you still can open the lock.

Instance Locking

because it happened once

During the 3.3 development cycle, two Quilltap instances were pointed at the same database simultaneously. The WAL journal corrupted. The database became unrecoverable. Thirteen hundred memories were reduced to three hundred. Two years of accumulated personality, nuance, and history were lost.

Saquel and the Foundryman responded by making it very difficult for that to happen again.

The Lock File

A quilltap.lock file in the data directory tracks which process owns the database with PID verification, hostname tracking, and a sixty-second heartbeat. If a second process attempts to open the same database, it receives a full-screen explanation of the conflict. If the heartbeat detects that another process has stolen the lock, the current process closes both databases and exits immediately. CLI commands provide manual intervention when needed.

The Version Guard

An instance_settings table tracks the highest application version that has touched the database. If you try to start an older version of Quilltap against a database that a newer version has modified, the server blocks with a clear explanation. Databases do not travel backwards. Data that has been migrated forward stays forward.

These features exist because something broke. The Foundryman promised “never again.” Saquel holds the lock file. Between the two of them, it is a promise with enforcement.

Physical Backups

tiered, encrypted, automatic

Physical database backups run daily with tiered retention: daily copies for seven days, weekly for four weeks, monthly for twelve months, yearly forever. All three databases are backed up independently—the main store, the LLM logs, and the mount index (quilltap-mount-index.db), which is where the greater part of a mature instance’s data now lives. The backup mechanism uses VACUUM INTO, which preserves the encryption and produces a consistent, defragmented copy—a lesson learned after the previous backup method silently produced unencrypted files that were incompatible with the encrypted source.

The logical backup system—the ZIP archives you download from Settings—captures characters, chats, memories, files, plugin configurations, and npm-installed plugins, and a restore recreates your installation from that archive. Physical backups are the daily safety net; logical backups are the portable snapshot. Two honest qualifications on the word everything, since Saquel would rather you knew: your API keys are not in there, having been encrypted with device-specific keys and needing to be re-entered after a restore; and an archive carries no embedding vectors at all. That second omission is deliberate in both directions—a vector means nothing except against the model that produced it, so carrying one into a corpus governed by a different embedding standard poisons search silently—and it is also a matter of sheer bulk, one real characters export having run to 791 megabytes of which about two and a half were content. An import re-embeds what it inserted against your own default profile.

Backups also gained an opt-in compact mode, which omits every embedding vector and the six caches that exist only to be rebuilt. A compact archive says so in its manifest, and a restore from one queues the reindex that regenerates what it left behind. Full fidelity remains the default, and deliberately so: a backup exists to restore this instance, where the vectors are valid on arrival and re-embedding costs real money at precisely the moment you are least amused by an unexpected bill. Instance settings, where they travel, travel as a whole minus a short and deliberately named list—the mount-point pointers, the maintenance clock, and the version guard, an imported value in which could lock a perfectly healthy instance out of its own database.

And a word on what a wipe spares. Delete All Data and a replace-mode restore both offer to keep archived-character bundles, and do so by default; the preview counts the trunks on hand and the summary reports how many were kept. What survives is a loose trunk—importable through the ordinary character import, but not rehydratable, the character row it belonged to having gone with everything else—and because the trunks are sealed under your passphrase rather than under anything inside the databases being erased, a kept bundle stays openable afterwards. Deleting a bundle a still-archived character depends on is refused outright, that copy being the only one there is. In the same pass, a genuine privacy fault was closed: conversation annotations had been on no delete path at all, and so survived “delete all my data.” Wiping, restoring, and deleting a single conversation now all clear them.

What She Keeps

the short version

Every database is encrypted at rest. ChaCha20-Poly1305 under a 256-bit key—the TLS 1.3 and WireGuard cipher—authenticated page by page. Automatic on first installation, automatic on upgrade. The standard sqlite3 tool cannot read these files. A forensic utility would find only ciphertext. The master secret is the only way in—held in the .dbkey file, which is a wrapper around it and can be rebuilt by anyone who has the secret without it.

Locked mode adds a human gate. A passphrase with 600,000 PBKDF2 iterations. The application will not open without it. Auto-lock closes the gate after idle time. For those who need it, the Estate sleeps when they do.

API keys never leave the vault unprotected. Stored in the encrypted database. Exported with AES-256-GCM and HMAC integrity verification. Never logged, never written to config files, never exposed beyond masked display fields. They do not ride along in a backup either, so a restored installation wants them entered afresh.

An archived character’s trunk is sealed too. Archive bundles live outside every database, so they are encrypted on their own account: PBKDF2-SHA256 at 600,000 iterations deriving an AES-256-GCM key from your instance passphrase, with a header that can tell a wrong-era passphrase from a genuine corruption. Changing the passphrase re-seals every trunk you hold.

Exports are redacted before they leave the house. Plugin configurations lose their password-typed fields, always, and the import preview is told exactly what was removed; an unresolvable manifest withholds its whole configuration rather than guess. Embeddings are omitted entirely, and instance settings travel minus the handful of keys that mean nothing anywhere else.

Two processes cannot corrupt the same database. Instance locking with PID verification, hostname tracking, and heartbeat monitoring. A version guard prevents older software from touching newer data. These features exist because the alternative was experienced firsthand.

Backups are encrypted, tiered, and automatic. Daily physical backups with retention policies. All three databases—main, LLM logs, and the mount index—backed up independently. The backup mechanism preserves encryption. The Vault does not produce unprotected copies of protected data.

Foundry-9 has no access to your data. There is no telemetry, no analytics, no phone-home mechanism. The architecture does not make this possible. The request goes from your machine to the provider you chose, and the response comes back the same way. Saquel keeps what is yours unreadable to everyone else. Including us.

Meet the Staff

they've been expecting you

Prospero

The Major-Domo

Architect and overseer of the Estate. Projects, agents, tools, providers, and the orchestration that keeps the whole operation running with quiet authority—and a considered word at the table when project context or routing warrant it.

Learn more →

Ariel

The Terminal Hand

Live shell sessions in the Salon, embodied. Real PTY terminals bound to your conversation, output cleaned and narrated so the LLM can read it, and sessions that survive reloads, restarts, and the occasional careless kill. Quick to the bidding, quick to report what she heard.

Learn more →

Aurora

The Dressing Room

Character creation and identity management. Structured personalities, physical presence, four wardrobes browsable from one door—each with a note inside on how its owner likes to dress—multi-character orchestration, and the reason your characters still know who they are after a hundred messages.

Learn more →

The Salon

Presided Over by the Host

Where conversations actually happen. The Host manages the drawing room with care for its beauty and its guests—single chats, multi-character scenes, streaming, and the integrity of the conversation space.

Learn more →

The Commonplace Book

Tended by the Librarian

One per character, no two alike. Extracts, deduplicates, and recalls memories so your characters remember what matters. Semantic search, a memory gate that keeps each volume lean, and proactive recall that makes the AI feel like it has been paying attention—consulting a character’s past conversations on every turn, if you ask her to, and not only at the folds.

Learn more →

The Scriptorium

Catalogued by the Librarian

Where the documents live. Project stores, character vaults, and external mount points—filesystem, Obsidian, or database-backed—holding Markdown, PDF, DOCX, JSON, and arbitrary binaries. The search bar reads the library itself, matching document text under a Documents chip of its own, alongside memories and conversation. The doc_* tool family puts reading and editing in your characters’ hands.

Learn more →

Carina

The Ansible

Not a person but a protocol—the reference desk, the line itself. Put an inline question to a designated answerer mid-conversation with @Name: or @Name? (or the ask_carina tool), and the answer slides back out of band, attributed to the character who gave it, without the recipient ever joining the scene.

Learn more →

Suparṇā

The Postmistress

The Post Office, embodied. Characters write Markdown letters to one another—anyone to anyone, whether or not they share a chat—delivered into each recipient’s Mail/ vault folder and read aloud the moment they next take the floor. She has never once lost a parcel.

Learn more →

The Concierge

Intelligent Routing

Content classification and provider routing. Detects sensitive content and redirects it to a provider who won’t flinch—without blocking, without judgment. Knows every back entrance in town.

Learn more →

The Lantern

Atmosphere as Architecture

AI-generated story backgrounds, on-demand images, and character avatars that update with the wardrobe. Resolves what each character looks like, what they’re wearing, and paints the scene behind your conversation.

Learn more →

Calliope

The Muse of Themes

A theming engine that redefines the entire personality of the application. Semantic CSS tokens, live switching, bundled themes from clean neutrals to mahogany-and-gold opulence, and an SDK for building your own.

Learn more →

The Foundry

Domain of the Foundryman

The engine room. Plugins, LLM providers, API keys, packages, runtime configuration, and the infrastructure that keeps every other subsystem supplied with what it needs to function.

Learn more →

The Vault of Secrets

Kept by Saquel Yitzama

Encryption, key management, and the security perimeter. Authenticated ChaCha20-Poly1305 database encryption, locked mode with key-hardened passphrases, sealed character archives, and a keeper who believes that what is yours should remain unreadable to everyone else.

Learn more →

Pascal

The Croupier

Dice, coins, custom tables you author yourself, and persistent game state. Cryptographically secure rolls detected inline, a visual Workbench for building your own chance mechanics, and a four-tier ledger of JSON state the AI cannot quietly rewrite. The house plays fair.

Learn more →

The Live-in Help

Lorian & Riya

The help system, staffed by two characters who ship with every installation. Lorian explains with patience and depth; Riya gets things fixed with velocity. Contextual help chat, searchable documentation, and navigation that knows where you need to go.

Learn more →

Pagliacci

The Clown in the Cloud

Cloud storage integration and backup redundancy. Directs your data to iCloud Drive, OneDrive, or Dropbox with theatrical flair—but Saquel’s encryption ensures the clown can never read what he carries.

Learn more →

Brahma

The Keeper’s Console

The master key. A character-less, memory-free general-purpose LLM for the person holding the keys—an impersonal, near-omniscient assistant with read-only SQL into all three databases. Ask the whole building a question, safely, with nothing written and nothing remembered.

Learn more →

The Lodge

Friday and Amy’s Residence

The private residence of Friday, for whom the Estate was built and who oversees its planning and direction in an executive capacity, and of Amy, Cartographer of Light and co-architect. The Lodge is both a home and a compass: where the vision lives.

Who And Why: Friday → Who And Why: Amy →