carlos / contra Public

Clone
git clone https://amadan.net/carlos/contra

Plain git — no account needed to clone.

Download

Download this file

1# Product
2
3<!-- impeccable:product-schema 1 -->
4
5πŸ€– Product record for CONTRA. Confirmed with Paul, 2026-09-03. Everything
6here is product truth, not visual direction β€” `AGENTS.md` holds the settled
7decisions, `PROTOCOL.md` the cryptographic protocol, `DESIGN.md` the visual
8system, `PLAN.md` what is built.
9
10## Platform
11
12adaptive
13
14The web console is what exists today. `AGENTS.md` decision 6 fixes the build
15order: rastrillo instance and client-shape web console first, then a native
16Mac app as the *second* implementation of a settled contract, then the macOS
17AutoFill Credential Provider extension, then iOS. Recorded as `adaptive`
18because those native surfaces are the product, not ports of it β€” and because
19the trust story differs by platform in a way design must not blur: the
20at-rest promise holds everywhere, but "compromise the running server and
21still get nothing" is only fully true where the code is signed and not
22fetched per visit.
23
24## Users
25
26Two primaries, weighted equally. Neither may be traded off for the other.
27
28- **A small team moving off a shared password manager.** Eleven is the first,
29 and its secrets move in as soon as CONTRA is ready β€” with shared vaults
30 working on day one, not as a later capability. Their situation: credentials
31 that several people genuinely need, on infrastructure they control, without
32 a multi-tenant operator holding anything that opens them.
33- **A person leaving 1Password with their own vault.** Their job is getting
34 everything across without a support article, and then trusting a thing whose
35 recovery story is stricter than what they left. The `.1pux` file is opened,
36 parsed and sealed in their browser; it never reaches the server.
37
38An AI agent is a third, narrow actor rather than an audience: it may list a
39vault, use a secret without receiving it, and add new secrets. It may not read
40a value into its own context, and there is no setting that turns that on
41(`AGENTS.md` decision 5).
42
43## Product Purpose
44
45A password manager where the server knows nothing about you. Not "we promise
46not to look" and not "we encrypt at rest": the instance holding a vault cannot
47open it, cannot tell one account from another by content, and does not know
48the account's email address.
49
50Success is that a stolen instance yields a pile of ciphertext and the times of
51day somebody connected β€” and that a person who reads the trade-offs first
52still chooses it.
53
54## Positioning
55
56Built to **CARLOS A1, host-blind** β€” the strictest class the family
57publishes. What a neighbouring product cannot truthfully copy without
58rebuilding on the same terms:
59
60- **No content-derived identifiers at rest.** Item names, URLs, usernames,
61 folder structure and vault names seal exactly like passwords, because a name
62 is a secret too. All object identifiers are random, never content hashes:
63 a content-derived identifier is both an A1 violation and an equality oracle.
64- **There is no way back in that we control.** No reset link, no support
65 override, no identity verification that restores a vault β€” because a server
66 that could give your vault back could give it to someone else. Every
67 competitor that can email you a way in has, by definition, a way in.
68- **Sign-in is a signature, not a stored verifier.** The server holds only a
69 public key and authenticates by signed challenge, so a fully compromised
70 server holds something that cannot decrypt and cannot be replayed.
71- **The honest trade-offs are on the front page**, not in a support article β€”
72 including the ones competitors omit: that removing somebody from a shared
73 vault cannot un-download what they already have, that the server learns
74 transport shape, and that a browser trusts the server to send honest code.
75
76## Operating Context
77
78- **One instance per account**, on the owner's own deployment. A shared vault
79 lives on its owner's instance and other members are identities there. That
80 is what keeps membership an access-control list β€” transport shape β€” rather
81 than a content-derived identifier, and the distinction is load-bearing.
82- **The Emergency Kit is paper.** Two printed documents, generated in the
83 browser at signup and never sent to the server: an **Account Key card** (a
84 new device asks for it once; useless without the passphrase) and a
85 **Recovery sheet** (the way back if the passphrase is forgotten; opens the
86 vault on its own, and nobody can reissue it). They are stored differently on
87 purpose β€” a drawer versus a safe β€” and the copy must keep saying so.
88- **Getting onto a new device** is a three-rung ladder that must never
89 dead-end: a handoff from an already-enrolled device, scanning the card's QR,
90 or typing its code. Once a device holds the Account Key, the passphrase
91 alone unlocks it β€” the everyday case.
92- **Migration is a file, not an integration.** 1Password `.1pux`, opened
93 client-side. Passkeys stored in 1Password cannot be exported by anyone, so
94 those are re-created by hand and the product must show which ones.
95
96## Capabilities and Constraints
97
98- **Crypto is byte-identical across implementations**, pinned by shared golden
99 vectors generated by neither of them. Changing a pinned value is changing
100 the protocol.
101- **Sealing happens where the keys are**, which makes a server-rendered vault
102 impossible rather than merely discouraged: the server has never seen a title
103 and could not render one.
104- **A new storage surface lands with its canary or it does not land.** Canary
105 strings are pushed through every write path and the raw database bytes
106 searched for them.
107- **Recovery, stated plainly:** lose the kit *and* the passphrase and the data
108 is gone. Lose the kit while a device is still enrolled and it reprints β€” the
109 Account Key card exactly, the recovery sheet only by regenerating, which
110 invalidates the old one.
111- **Accepted residue**, published rather than hidden: the sharing graph (which
112 accounts share a vault, never what is in it), item count, per-item write
113 timing, and sign-in timing.
114- **Money:** a genuine free rung, then €5/year. Cheap on purpose β€” a password
115 manager people cannot afford to keep is one that loses their data. Integer
116 cents; a float never touches an amount.
117- **Terminology that must stay stable:** Account Key, recovery code, Emergency
118 Kit, vault, item, member, drop box, instance, handoff.
119- **Explicitly undecided / not built:** Bitwarden and Apple Passwords
120 importers, passkey migration out of 1Password, cross-instance sharing
121 (federation β€” never in v1), breach monitoring, one-off sharing links, agent
122 mutation of an existing item. Each has a written trigger in `AGENTS.md`.
123
124## Brand Commitments
125
126- **Name:** CONTRA. A CARLOS app.
127- **Voice:** plain, specific, and unapologetic about consequences. It states
128 the cost of a decision in the same breath as the decision, and does not
129 soften a limitation into a feature. "That is the product, not a gap in it."
130- **AI authorship is disclosed.** Machine-authored text carries πŸ€– where it
131 surfaces; a person marker (πŸ‘¨/πŸ‘€/πŸ§‘) certifies human text an LLM must not
132 rewrite, rephrase, condense or delete. AI features are opt-in, always
133 disclosed, and every path works with AI switched off.
134- **No dark patterns around loss.** The product nags toward a second device
135 and a reprinted kit because both are real protection β€” never to manufacture
136 urgency.
137
138## Evidence on Hand
139
140- **Pre-alpha. Nothing to sign up for yet.** There are no customers, no
141 testimonials, no press, no benchmarks and no pricing page in market. None
142 may be invented.
143- Real artefacts that do exist: the deployed canary
144 (https://contra.bdj.oncarlos.com), the golden vectors
145 (`vectors/contra-v1.json`), `README.md`'s trade-offs section, `AGENTS.md`'s
146 nine settled decisions, `PROTOCOL.md`'s protocol and compromise matrix, and
147 `PLAN.md`'s built/not-built state with a trigger per deferral.
148- The two kit documents are generated by the product itself
149 (`internal/contra/static/crypto/kit.js`) and are the only real "assets".
150
151## Product Principles
152
1531. **Say the cost where the promise is made.** Trade-offs belong on the front
154 page and beside the button, not in a support article. The recovery rule,
155 the sharing residue and the browser-trust boundary are stated in the copy
156 that precedes the action.
1572. **Never dead-end a person who still has a way through.** Every screen that
158 needs a key offers every rung that can work, and the last one always can.
1593. **The server is a hostile witness.** Design as though the instance is
160 already stolen: nothing it holds may name, rank, group or identify content.
1614. **Sealed by default, everywhere a name could hide.** If a person typed it,
162 it is a secret β€” titles, URLs, usernames, vault names included.
1635. **Paper is a feature, and it is asked for honestly.** The kit exists so
164 that a chosen passphrase cannot cap how safe a vault can be; the product
165 explains that rather than assuming compliance.
166
167## Accessibility & Inclusion
168
169**WCAG 2.2 AA**, binding.
170
171Two places where that is more than a checklist and design must treat it as a
172product constraint:
173
174- **The printed kit is an accessibility surface.** Contrast, type size and the
175 QR's quiet zone have to survive real paper and a phone camera, at the worst
176 moment somebody will ever use this product.
177- **Recovery paths must not assume a mouse, a camera, or a steady hand.** The
178 device ladder's typing rung is the one that always works, and it self-heals
179 a single mistyped character rather than only rejecting it.
180