QuantumShield is a post-quantum encrypted chat platform available at quantumshield.co. It runs as a browser app, an installable PWA, and an Expo mobile app against the same Express API, OpenAPI clients, and PostgreSQL/Drizzle data layer.
QuantumShield is an experiment in truly ephemeral digital communication: content should be encrypted before transit, guarded during display, intentionally revealed only for the moment it is needed, and allowed to decay into useless ciphertext over time.
The privacy features this project combines:
| Icon | Feature | What it does |
|---|---|---|
| Camera | Front-camera recording-device detection | The web client uses the selfie camera with an on-device detector for phones, laptops, tablets, cameras, and webcams near the screen. The Expo app keeps a front-camera sentinel live and reports scan state. |
| Hold | One-at-a-time plaintext reveal | Messages stay encrypted in the UI until hover, tap, press, or hold reveal. Only one message is plaintext at a time, and it clears on release, blur, scroll, or background. |
| Mask | Codenamed people and rooms | Usernames, account names, and room names are hidden behind per-session codenames until hold-revealed. |
| Decay | Timed key expiry | TTL message keys are purged locally after expiry, and the API wipes expired wrapped key envelopes while retaining ciphertext. Without a usable key path, the message becomes unrecoverable noise. |
| Shield | Blur and tab awareness | Secure content is covered or blurred when the web app loses focus, the tab is hidden, printing starts, or the mobile app backgrounds. |
| Screen | Screenshot and print friction | The web client reacts to PrintScreen and print lifecycle events. Expo requests platform screen-capture prevention and warns on screenshot events where supported. |
| Key | Device-local identity keys | Post-quantum identity keys are generated locally during account creation. Private keys are not uploaded to the API. |
| Code | Rollable handles and invite codes | Users claim a globally unique handle and can mint invite codes with visibility scopes, use limits, allow lists, expirations, and roll/disable controls. |
| Passkey | Durable handle plus passkey login | Login shows only the user-created handle. The browser opens Face ID, Touch ID, Windows Hello, or the platform password manager to create or unlock the passkey. |
| Session | Rotating device sessions | Each successful login issues a fresh bearer session, and logout deletes only that session. Handles can be disabled or rolled without reusing old names. |
- Use the live app: quantumshield.co
- Read this README on GitHub: github.com/stevemoraco/qs#quantumshield
- Install and use the app: Using QuantumShield
- Review privacy protections: Privacy Behavior
- Review release notes: CHANGELOG.md
- Run the project locally: Development
- Report vulnerabilities privately: SECURITY.md
- Contribute patches: CONTRIBUTING.md
QuantumShield has three supported surfaces:
Web app: Open quantumshield.co in a modern browser and sign in or request clearance.PWA: Install quantumshield.co from Chrome, Edge, Safari, or a mobile browser so it launches from your home screen or app launcher.Expo mobile app: Run the native Expo client from this monorepo for device testing and mobile privacy controls.
All clients talk to the same API and use the same account system. Messages are encrypted client-side before they are sent. The server stores ciphertext, room metadata, push subscriptions, invite/alias code metadata, device-session records, and lead/account records, but not message plaintext.
Account access works the same way across web, PWA, and Expo:
- Create a permanent handle while the browser creates a passkey and post-quantum identity keys are generated locally.
- Use the same handle as your primary alias, then roll or disable it if it should stop working for login/discovery.
- Return from any browser or device with the handle plus its synced passkey. The API verifies the active handle and WebAuthn assertion before issuing a session.
- Use invite codes to link trusted devices or control who can discover and join you.
Chrome or Edge on desktop:
- Open quantumshield.co.
- Use the install icon in the address bar, or open the browser menu and choose
Install app. - Launch QuantumShield from the installed app window.
- Allow notifications when prompted so encrypted push alerts can be registered.
- Create a handle; the browser creates a passkey and post-quantum identity keys are generated locally on that device.
Chrome on Android:
- Open quantumshield.co.
- Open the browser menu and choose
Install apporAdd to Home screen. - Open QuantumShield from the home screen.
- Allow notifications before account creation.
Safari on iPhone or iPad:
- Open quantumshield.co in Safari.
- Tap
Share, thenAdd to Home Screen. - Open QuantumShield from the home screen.
- Enable notifications if the browser and OS version support web push.
The web registration flow intentionally checks for installed-app mode and notification permission before creating an account. This is implemented in artifacts/web/src/components/SignupGate.tsx.
The Expo app lives in artifacts/mobile and uses Expo Router. It is useful for native-device testing of chat, auth, push-adjacent flows, screenshot controls, and app-background behavior.
Run it locally:
pnpm install
pnpm --filter @workspace/api-server run dev
pnpm --filter @workspace/mobile run devThen open the Expo development URL or QR code with Expo Go or a compatible development build. The mobile app expects the API server to be reachable through the Replit/Expo environment variables configured in artifacts/mobile/package.json.
Mobile behavior to know:
- Message plaintext is not shown by default. Press and hold
Encrypted - hold to revealto decrypt a message whose key exists on the device. - Releasing the press hides plaintext again.
- Backgrounding the app clears any currently revealed plaintext.
expo-screen-captureattempts to prevent screen capture for the chat screen where the platform supports it.- If a screenshot event is reported, the app shows a warning banner.
- Web/PWA login requires the account handle plus the synced passkey, so cleared browser storage does not prevent sign-in.
- Alias and invite code behavior matches the web/PWA API: codes can be scoped, limited, expired, and rolled.
QuantumShield adds UI-level privacy controls on top of encryption. These controls reduce accidental exposure; they do not replace OS hardening, device security, or careful operational practice.
Web chat behavior:
- The chat surface is non-selectable and blocks the context menu.
- A global privacy shield covers the app when the window loses focus, the document is hidden, printing starts, or the
PrintScreenkey is detected. - Individual room contents blur when the tab/window is hidden or blurred.
- Any revealed message plaintext is cleared on blur, tab hide, pointer release, pointer cancel, pointer leave, or message-list scroll.
- Messages use
Encrypted - hold to reveal; plaintext is held in transient React state only while the interaction is active. - The web app attempts on-device camera scanning in chat using the selfie camera and local model pipeline. If the model or camera is unavailable, the UI reports that scanning is offline.
Expo mobile behavior:
- The chat screen uses
expo-screen-captureto request screenshot/screen-recording prevention where supported. - Screenshot listener events trigger a visible warning banner.
- App background transitions clear any currently revealed plaintext.
- Messages use the same hold-to-reveal pattern as the web client.
These features are implemented primarily in artifacts/web/src/pages/ChatApp.tsx, artifacts/web/src/index.css, and artifacts/mobile/app/app.tsx.
Identity and access behavior:
- Registration creates an internal opaque account identifier and a required user-created handle stored as an alias code.
- Handles, aliases, and invite codes support visibility scopes, max-use limits, allow lists, expirations, active/inactive state, and roll timestamps.
- Search only returns active, public, non-expired identity codes.
- Web/PWA passkeys are verified with WebAuthn. Legacy device-link passcodes are still argon2 hashed, and login is rate-limited by handle and client address.
- Session records are created on login and removed on logout.
This project is early-stage software. Treat cryptographic and security-sensitive changes as high risk: keep them small, reviewed, and covered by tests or documented manual verification.
- pnpm workspaces, Node.js 24, TypeScript 5.9
- Web: React, Vite, Tailwind CSS, shadcn/ui, Wouter
- Mobile: Expo, React Native, Expo Router
- API: Express 5, PostgreSQL, Drizzle ORM
- API contract: OpenAPI in
lib/api-spec/openapi.yaml, generated Zod schemas and React Query hooks - Crypto dependencies:
@noble/post-quantum, Web Crypto AES-GCM, argon2id
artifacts/web- React web clientartifacts/mobile- Expo mobile clientartifacts/api-server- Express API serverlib/api-spec- OpenAPI source of truth and code generation configlib/api-zod- generated/shared API validation schemaslib/api-client-react- generated/shared React Query clientlib/db- Drizzle schema and database configscripts- repository maintenance scripts
- Node.js 24
- pnpm 10.26.1
- PostgreSQL for the API server
pnpm installCreate local environment files as needed. Do not commit real secrets. At minimum, the API server expects:
DATABASE_URL=postgres://...
SESSION_SECRET=replace-mepnpm --filter @workspace/api-server run dev
pnpm --filter @workspace/web run dev
pnpm --filter @workspace/mobile run devRun these before opening a pull request:
pnpm run typecheck
pnpm run build
pnpm audit --audit-level moderateRegenerate API clients after changing the OpenAPI contract:
pnpm --filter @workspace/api-spec run codegenPush database schema changes in development only:
ALLOW_DB_PUSH=1 pnpm --filter @workspace/db run pushFor production or shared databases, do not use drizzle-kit push when it reports a data-risk prompt. Use the reviewed SQL scripts in lib/db/migrations/manual/ instead.
Security reports should follow SECURITY.md. The repo is configured with CI typechecks/builds, dependency review, Dependabot updates, CodeQL analysis, and a scheduled pnpm audit workflow.
See CONTRIBUTING.md for issue, pull request, review, and release guidance.
MIT. See LICENSE.