# CONTRA

🤖 *This project — code and documentation — was written by an LLM (Claude),
on the ideas, instruction, and editing of humans, per
[factor X](https://11factor.org/#x).*

**A password manager where the server knows nothing about you.**

Not "we promise not to look." Not "we encrypt at rest." The server that
holds your vault cannot open it, cannot tell you apart from anyone else,
and does not know your email address. If it is stolen tomorrow, the thief
gets a pile of ciphertext and the times of day you connected.

CONTRA is a [CARLOS](https://carlosframework.com) app, built to the
strictest class the family publishes — **A1, host-blind**: keys live on
your devices, the instance never holds one that opens your content, and
nothing derived from your content is stored in the clear. Item names,
URLs, usernames, folder structure and vault names are sealed exactly like
the passwords are, because a name is a secret too.

## Honest trade-offs — read before trusting it

This is the part most password managers put in a support article. It goes
here instead.

- **Lose your kit and your passphrase and your data is gone. That is the
  product, not a gap in it.** There is no reset link, no support override,
  no "verify your identity and we'll restore it," because a server that
  could give your vault back is a server that could give it to someone
  else. Every password manager that can email you a way back in has, by
  definition, a way in. We don't, and we are not going to apologise for
  the consequence.
- **The clearest way to think about it: the kit is your vault. The
  passphrase is just the convenient way in.** On a device you already
  use, the passphrase is all you need. But a brand-new device asks for
  your Account Key — so if you lost the kit *and* every device you had,
  remembering the passphrase will not be enough. Same rule, and it
  surprises people, which is why we are saying it here rather than in a
  support article.
- **So do two things, and we will keep asking until you have.** Keep the
  kit somewhere real, and set up a second device. Either one alone
  rescues the other. If you lose the kit while a device is still signed
  in, reprint it that day — it works right up until your last device is
  gone.
- **Why we ask you to keep paper at all.** We could have let a passphrase
  alone open your vault from anywhere. Then the encrypted copy of your
  data would only ever be as strong as the phrase you chose, and most
  chosen phrases fall to a patient machine. The Account Key means that
  whatever you pick, the stored copy cannot be broken into. We would
  rather ask you to keep a piece of paper than quietly cap how safe your
  vault can be.
- **Removing someone from a shared vault does not un-give what they
  already have.** Their access dies immediately and the vault's key
  rotates forward, so they see nothing new. What they already downloaded
  is already theirs. Nobody's design changes that; ours says so.
- **The server still learns transport shape** — that someone connected,
  roughly when, and roughly how big the reply was. That is the residue A1
  permits, and we are not going to pretend it is zero.
- **Passkeys stored in 1Password cannot be exported.** Not by us, not by
  any tool — 1Password does not let them out. Everything else in your
  vault comes across; those need to be re-created by hand, and we will
  show you which ones.
- **A web browser trusts the server to send it honest code.** This one is
  subtle and most of our competitors do not say it. When you use the web
  console, the server hands your browser the JavaScript that handles your
  passphrase — so a server that has been *actively taken over* could send
  code that steals it as you type. Our at-rest promise ("steal the
  database and get nothing") holds absolutely. The stronger promise —
  "compromise the running server and still get nothing" — is only fully
  true for the signed native apps, where the code is not fetched from us
  each time. We serve the console from a separate, static, signed origin
  to narrow this as far as a browser allows, and we would rather tell you
  than let you assume.
- **The server can see who shares a vault with whom.** Not what is in it,
  not its name, not a single value — but the wrapped keys that let your
  colleague open a shared vault are visible as a shape, so the server
  learns that two accounts share something. Personal vaults reveal
  nothing. We could hide this and have chosen not to spend the complexity
  yet; it is listed here rather than left for someone to discover.
- **It is early.** What is built and what is not is in `PLAN.md`, with
  triggers for each deferral rather than vague intentions.

## Leaving 1Password

CONTRA imports 1Password's `.1pux` export — items, types, TOTP seeds,
attachments and vault structure. **The file never reaches our server**: it
is opened, parsed and sealed in your browser, and only ciphertext is
uploaded. Bitwarden and Apple Passwords importers are wanted and not built
yet.

## How you get in

- A **passphrase** signs you in to the web console.
- An **Emergency Kit** — printed once at signup, generated in your browser
  and never sent to us. It is **two documents**, on purpose:
  - an **Account Key card** — a new device asks for this once. **Store it
    somewhere safe**: a drawer, a wallet, the folder your documents live
    in. Somewhere you can find it and nobody else goes. On its own it
    opens nothing, because without your passphrase it is useless.
  - a **Recovery sheet** — the way back if you forget your passphrase.
    **Store this one securely**, and it is the stricter of the two: keep
    it where you'd keep a passport or a will, and never photograph it.
    This sheet alone can open your vault, and nobody can reissue it.
- On a device you have already set up, the passphrase alone is enough.
  Setting up a *new* one takes the Account Key — scan it from the kit, or
  let a device you already use hand it over.
- A **passkey** on a device you trust is a fast unlock on top — a
  convenience, never the only door. The passphrase is offered beside it on
  every screen, because passkey ceremonies fail in ways that are not the
  user's fault.

Your email address is stored only as a blind index — a keyed hash. There
is no address column in the database. It proves you are you, and it can
never decrypt anything.

## Agents

CONTRA can be driven by an AI agent, deliberately and narrowly. An agent
can **list** what is in a vault (names, sites, usernames), **use** a
secret without ever receiving it — the local daemon does the authenticated
thing on the agent's behalf — and **add** new secrets, which needs no
unlock at all. An agent cannot read a value into its own context. There is
no setting that turns that on.

## Status

Pre-alpha. Nothing to sign up for yet.

## Licence

**Mozilla Public License 2.0** — see `LICENSE`.

MPL's file-level copyleft is the right fit for a security product: anyone
who ships a modified CONTRA has to publish the modified files, so the
thing you are running can always be checked against the thing we
published. That is the same argument as the rest of this README — you
should not have to take our word for it. Factor VI, and it is not
deferred.
