Ostler holds your entire digital life in one place. That is powerful and dangerous in equal measure. This page explains exactly how we protect it. No hand-waving, no “industry-standard encryption.” Specifics, and honest status labels on every claim.
The threat model is different here. A breach of your LinkedIn exposes one slice of your life. A breach of Ostler would expose everything – every relationship, every conversation, every pattern. We built the security around that reality.
The realistic threat is software, not magic AI. What threatens a local-first product is malicious code running on the same Mac, with your permissions, doing things you did not ask it to. The AI inside Ostler is an instructed insider: bounded tool calls, bounded data access, audited outputs. The unexpected attacker is everything else with a foothold on the host.
Ostler does not connect to any external server. No cloud backend. No API endpoint. No telemetry. The databases, the AI models, and the processing pipeline all run on your Mac.
This eliminates the largest, most boring class of attack vector for personal data: server breaches, man-in-the-middle attacks, credential stuffing, insider access at the vendor, and government data requests against the vendor. There is no server to breach. There is no data to request.
Verify it yourself. Disconnect from the internet. Everything continues to work.
What this is not: a claim that nothing can go wrong. Removing the cloud closes the door an attacker most often walks through. It does not seal every window. The honest limits – what stays your responsibility – are spelled out in What this doesn’t protect against, below.
There is no password. We took passwords off the table entirely.
On first run, Ostler registers a passkey against your Mac’s Secure Enclave. From that moment on, unlocking Ostler is a Touch ID tap, a Face ID glance, or a double-click on your Apple Watch. The cryptographic proof of identity lives inside your Mac’s hardware security chip. It cannot be exported, phished, or copied to an attacker’s machine.
Creative Machines never sees a password because there is no password to see. We never receive a login token, a session cookie, or a hashed credential. There is nothing for us to lose in a breach because we hold nothing.
Your passkey syncs to your other Apple devices through iCloud Keychain, end-to-end encrypted by Apple. That is how the Ostler iOS app will unlock data from the same Hub without a second setup step.
Every Ostler database on disk is encrypted with a 32-byte data-encryption key (DEK). The DEK is generated on your Mac at install time, never leaves your Mac in plaintext, and is wrapped (encrypted) under a key derived from your passkey. Unlocking Ostler means: your biometric unlocks the passkey, the passkey unwraps the DEK, the DEK decrypts the databases. When the app locks, the DEK is wiped from memory.
Ostler auto-locks after a configurable period of inactivity. On lock, the in-memory encryption key is overwritten. A stolen or lost Mac sitting on the attacker’s desk cannot yield plaintext without a live Touch ID / Face ID from you.
Most consumer software does not seriously model device theft – the cloud holds the real copy, so a stolen device is treated as a lost endpoint. We model it because here the device is the data, and the data is intimate. There is no cloud copy to fall back on. The auto-lock, the in-memory key wipe, and the requirement for a live biometric to re-unlock are designed around that reality, not bolted on after the fact.
A common pattern in “passwordless” products is to bind authentication or recovery to email – a magic link, a one-time code, a password-reset flow. It looks strong on the surface; there is no password to phish. The catch is that the security of the whole system inherits the security of the user’s email account. A compromised inbox is a compromised identity.
Ostler does not work that way. There is no password-reset email, no magic link, no email-bound recovery for the local product. The data-encryption key is issued by the Hub on your Mac at install time and wrapped under a key derived from your passkey, which lives in your Mac’s Secure Enclave. The only out-of-band fallback is the 12-word phrase you wrote down. The chain of custody never runs through your inbox.
There is exactly one fallback: a 12-word recovery phrase generated during setup. You write it on paper. You keep it somewhere safe. You never type it into iCloud, Dropbox, a password manager, or a photo.
The phrase is shown to you once, on a screen that blocks copy-paste, and never stored on disk afterwards. To be specific about what we use from BIP39 and what we don’t: we use its 2048-word English wordlist and its entropy-to-words encoding (128 bits of entropy plus a 4-bit checksum ⇒ 12 words). We do not implement BIP39’s PBKDF2 mnemonic-to-seed step – we treat the entropy as our recovery-key material directly, which is the right choice for a non-wallet system. Ostler is not a cryptocurrency wallet and we do not claim BIP39 wallet compatibility. We use the wordlist because it is publicly audited and ergonomically proven, not because we are interoperating with anything.
If you lose your Mac and your iPhone, and iCloud Keychain has not restored your passkey to a new device, the recovery phrase is how you get back in. It unwraps a second, independent copy of the same DEK.
If you lose the phrase and all your Apple devices and your Time Machine backup simultaneously, your data is gone. By us, by anyone. That is the price of real privacy – the same architecture that prevents us from reading your data prevents us from helping you recover it.
Your data is protected by multiple layers. Each row below shows the current, honest status – not what we intend, what is actually in the build:
| Component | Encryption | Status |
|---|---|---|
| Full disk | macOS FileVault (AES-256-XTS) | Live Installer checks this is enabled |
| SQLite databases | SQLCipher (AES-256) | Live in code Deploys with the installer at launch |
| iOS app secure store | Realm (AES-256), device-bound key | Live Voice-profile store encrypted on iOS today |
| iOS app main store | Passkey-derived Realm key (shared with Hub) | In development Cross-platform spec signed off; iOS pairing flow next |
| Vector + graph databases | Encrypted APFS volume | In development Scripted volume creation lands in the installer |
| Local audit log | SQLCipher-encrypted, append-only | Live in code Per-entry HMAC integrity chain is a planned upgrade |
| Time Machine backups | Inherits FileVault | Live Via macOS Time Machine encryption |
Two pieces of Ostler arrive on your Mac from the internet at install time: the assistant binary itself, and the local LLM model weights. We handle the integrity of each differently because the trust shape is different.
The assistant binary ships as a signed tarball with a SHA-256 checksum published in a sidecar file. The installer downloads both, computes the hash of the tarball, and refuses to continue if the values do not match. Tampering between our release pipeline and your Mac – by an intermediary, by a compromised CDN, by any agent in between – is a hard install failure, not a silent compromise.
The model weights come from curated upstream registries (the Ollama registry, Hugging Face) over TLS at install time. We pin model names; we rely on the upstream maintainer’s tag-immutability discipline for what bytes those names resolve to. We are honest about the trust assertion: if a maintainer of an upstream we depend on shipped a malicious update under a tag we had pinned, fresh installs would pull it until the upstream caught the issue. We pin versions where we can, read changelogs, keep the model surface small. Tightening this further by pinning content digests is a hardening item on the post-launch list.
When the Ostler iOS app talks to your Mac Hub, the connection is designed to run over TLS with a self-signed certificate generated during install, with the iPhone pinning the certificate’s public key at pairing time so only your Mac can answer.
The cryptographic contract – pairing QR code format, WebAuthn handshake, HMAC-based proof of shared passkey, ten-minute pairing-token expiry – is locked in a normative cross-platform specification that was signed off on 2026-04-23 by both the Hub-side and iOS-side implementers. Every HKDF constant, wire-format byte, and test vector is fixed. Hub-side code-signing is the remaining blocker before iPhone-to-Hub pairing runs end-to-end (see below).
127.0.0.1 (loopback only); none accept LAN connections. This protects against every attacker who is not already on your Mac. It does not isolate Ostler from other software running on the same Mac as you – see below.The AI inside Ostler is an instructed insider, in the phrasing of the callout at the top of this page. This section is what that means in concrete terms: what the assistant is allowed to do, what it is not allowed to do, and how its actions are recorded.
Workspace confinement. The assistant reads and writes inside a default-deny workspace. The directories that hold your credentials and your private keys – ~/.ssh, ~/.gnupg, ~/.aws, ~/.config, the system directories under /etc, /usr, /var – are on a static denylist that path-guards every file-touching tool. The assistant can read your messages, your email, and the documents you have asked it to read; it cannot, even by misadventure, read your SSH key.
Hardened binary. The assistant binary is built with macOS Hardened Runtime enabled, with the JIT, library-injection, and dyld-environment-variable capabilities denied at code-sign time. The standard process-level injection paths that work against ordinary Mac software – DYLD_INSERT_LIBRARIES hooks, JIT-mapped code injection, loader-environment-variable rewrites – do not work against the assistant. Code-signing trust is the gate; only the original binary runs.
Per-tool approval gate. Every tool call goes through an approval gate. In Supervised mode (the default), a tool that has not been pre-approved this session blocks until you say yes. Session-scoped allowlists do what the name says: they expire when the session ends, not when the assistant decides it has earned your trust forever.
Channel-driven default-deny. When the assistant is being driven by an incoming message – iMessage, WhatsApp, email – there is no human at the keyboard to approve a tool call. In that posture, the assistant cannot ask, so it does not run any tool outside a small read-only allowlist (search, lookup, fetch a public web page). A prompt-injection arriving by message cannot escalate to file writes, arbitrary network calls, or destructive shell commands; the shell-tool surface in this posture is bounded by a separate pre-approved command allowlist.
Tamper-evident audit log. Every tool call writes a record to a local audit log that uses a SHA-256 hash chain: each entry includes the hash of the previous entry, so a deleted or edited entry breaks the chain in a way that replay-validation detects. HMAC signing of each entry is supported as an additional hardening step. The audit log is local; it is not shipped anywhere.
Private-by-default conversations. Conversations between you and the assistant are stored on your Hub and marked private by default. Content tagged at the most sensitive privacy level (full transcript bodies you have shared in confidence) is withheld from query responses unless the calling client explicitly opts in. The default API path returns metadata, not bodies.
Ostler runs as your user account on your Mac – not as root, not as a system service. The orchestrator, the API gateway, the local databases, and the inference processes all run inside your user’s permission scope. There is no LaunchDaemon shipping with the installer, and no background process that survives logout.
The installer asks for an administrator password once, at install time, for the system-level operations that macOS requires admin for: changing power-management settings so the Hub stays reachable to your iPhone when the Mac is idle (disable sleep on AC, enable wake-on-magic-packet), and installing the supporting packages (Homebrew, Ollama) that ship as standard macOS CLIs. After install, no part of Ostler asks for elevated privileges to run, and the application has no path that escalates on its own.
This bounds the blast radius of a bug or a successful attack on Ostler itself: it inherits your user’s reach, not the system’s. It does not protect against malware that has already obtained your user’s permissions through some other vector – that is the surface the next section is about.
Closing the cloud closes the biggest, most boring class of attack – the kind that exposes a million people at once. It does not mean nothing can ever go wrong. We would rather tell you the limits than let you discover them.
This is the realistic threat surface for a local-first product, and we are explicit about it. If a piece of malware reaches your Mac through a malicious browser extension, a poisoned download, or a compromised app from outside the App Store, it inherits your user’s ability to talk to localhost. The encryption-at-rest layer protects against physical theft and against your data leaving the device, but it does not isolate Ostler from other software you have given permission to run. Treat your Hub Mac the way you would treat a password manager or a banking app: don’t install random utilities, don’t approve installer prompts you didn’t initiate, and ideally use a Mac that mostly runs Ostler and not much else.
Ostler runs on Ollama, an LLM model file, a Python runtime, and a small set of Python packages. We don’t write those, we use them. If any of those upstream projects shipped a malicious update tomorrow, fresh installs – ours, yours, every other user’s – would be exposed until the issue was caught. We pin versions, we read changelogs, we keep the dependency surface as small as we can. We are not going to pretend the risk is zero. The same supply-chain caveat applies to any software you ever install, anywhere.
The recovery phrase is the worst-case backdoor. If you write it on a sticky note, take a photo of it, paste it into a cloud notes app, or read it out on a video call, the phrase becomes the attacker’s shortest path. We make it easy to do the right thing – the screen blocks copy-paste, the recovery doc explains the threat – but the final link in the chain is you.
This is the price of a system that holds the keys on your hardware, not ours. We can architect the inside; we can’t architect around bad operational hygiene. The mitigation is honest documentation, not a promise we can keep on your behalf.
We are engaging senior security advisors and scoping an independent security audit from a recognised cybersecurity firm. The scope covers authentication, data handling, storage encryption, network posture, and dependency analysis. The report will be published here when complete.
We chose a professional audit over relying on community code review because an expert review is more rigorous than hoping someone reads the code. Trust should be verifiable, not assumed. “We promise not to look at your data” is what every cloud company says. “We architecturally cannot look at your data, and here is the auditor’s report proving it” is what we are aiming for.
The architecture is intentionally simple. Passkey-primary auth via Apple’s own frameworks. Standard cryptographic primitives (HKDF-SHA256, AES-KW RFC 3394). Local services on 127.0.0.1. Local Ollama inference. There is very little novel cryptography to get wrong because the primary security mechanism is not having a network connection to begin with.
Passkey (WebAuthn Level 2) registered against Apple’s platform authenticator via ASAuthorizationPlatformPublicKeyCredentialProvider, using the PRF extension. Requires macOS 15+ / iOS 17.4+. The PRF output is a pseudorandom value bound to the authenticator, the credential, and the relying-party identifier – non-exportable from the Secure Enclave.
A small Swift helper binary owns every WebAuthn call and talks to the Python side via one-shot JSON-RPC. Pure AuthenticationServices + Security.framework, no third-party Swift packages.
rp_id = creativemachines.ai. Tied to the company domain, not the product name, so a future product rename cannot invalidate existing users’ credentials.
HKDF-SHA256. Domain-separated info strings use the creativemachines/ namespace for the same rebrand-safety reason. No PBKDF2 anywhere in the primary path – the PRF output is already a full-entropy key.
AES Key Wrap, RFC 3394 unpadded variant. A 32-byte DEK wrapped under a 32-byte KEK produces a 40-byte blob with a built-in integrity check. A wrong KEK fails to unwrap – it does not return garbage plaintext.
12-word phrase from the same publicly audited 2048-word English list as BIP39, 128 bits of native entropy plus a checksum word. The 16-byte entropy feeds HKDF-SHA256 with the same shared salt, under a distinct info string, to derive an independent recovery KEK. No PBKDF2 mnemonic-to-seed step – a second KDF over already-full-entropy input adds no security in this threat model. We borrow the wordlist; we do not claim BIP39 wallet compatibility.
SQLCipher (AES-256) for the Ostler databases on the Mac Hub. Realm (AES-256) for the iOS app. Keychain items scoped AccessibleWhenUnlockedThisDeviceOnly, Synchronizable = false – wrapped DEKs never travel in Time Machine or Migration Assistant.
Long-lived session key held as a mutable bytearray and zeroised via ctypes.memset on lock or timeout. Short-lived immutable copies in Python are honestly documented as best-effort only, not claimed as guaranteed scrubbed.
TLS with a self-signed Ed25519 server certificate generated at install. Public-key pinned by the iOS app at first pair. No unpinned HTTP. No application-layer fallback channel.
The full cross-platform cryptographic contract between the Mac Hub and the iOS app, including every constant, test vector, and wire-format byte, is available for independent review.
Transparency means admitting exactly where each piece stands today, with a specific blocker named for anything not yet live:
ASAuthorizationPlatformPublicKeyCredentialProvider + PRF extension via macOS 15 AuthenticationServices. Builds and runs. Keychain operations smoke-tested against real Security.framework on 2026-04-23.ctypes.memset scrub on lock, typed-exception re-unlock callback.~/Library/LaunchAgents/ with path-injection guards on all certificate paths.register / assert operations – the call silently never completes. The Creative Machines Developer ID certificate is now in place and notarises the assistant binary; the remaining work is signing the passkey helper itself, wiring its entitlements file, and serving the apple-app-site-association document from creativemachines.ai.~/.ostler/. No technical blocker – prioritised after SQLCipher and passkey work, which came first because they protect the larger data surface.If you think you have found a security vulnerability in any part of Ostler – the Mac Hub installer, the iOS app, the passkey helper, the Sparkle update pipeline, or any related infrastructure – please report it to [email protected].
What we promise in return:
What we ask in return: do not access other users’ data, do not disrupt our services, and do not demand payment as a condition of disclosure. We do not run a paid bug-bounty at launch – if that changes, this page will say so.
For encrypted reports, our PGP public key is published at /security.asc. The full disclosure policy is also machine-readable at /security.txt per RFC 9116.
The security story is the privacy story. Every competitor sends your data to the cloud and promises to protect it. We keep your data on your hardware and prove it cannot leave. That is not a feature. It is the architecture.