chore: dual licence (Apache-2.0 or MIT) + custody doc corrections#290
Merged
Conversation
README listed, under "What works today", that the server derives a no-wallet heir's key from (master_key, heir_email, vault_id). That reads as how the product works now. It isn't: #124 killed exactly that backdoor, and heir_derivation is null on every new vault, in both PasswordSetupPortal and AddHeirPortal. The claim is the wrong way round to be wrong about. It tells a reader (or an auditor) that one master-key breach exposes every no-wallet heir key, which is the custody weakness the project deliberately removed. Describe what actually happens: the browser generates the heir key and seals it under the one-time claim token, and the old derivation path stays reachable only so pre-#124 vaults can still be claimed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Same staleness the README had, but here it overstates live risk. The doc presents "F2 server-derived flow" as a current heir-key mode and A3.2 as a current blast radius. Since #124 no vault is created with heir_derivation, so the exposed set is exactly the F2 vaults that already existed, and it does not grow. An auditor reading this would model a blast radius that no new vault has. D1 was the sharper problem. It says an operator "cannot construct a valid witness without either the owner's xprv or the heir's xprv", and never cross-references A3.2, where the master key *derives* the heir xprv for F2 vaults. Both statements are individually true, so the gap only shows if you read them together. Now D1 says plainly that it does not hold for legacy F2 vaults. Also note the owner-xprv caveat under D1: an operator with the DB and the master key still has to break an Argon2id password KEK to spend as the owner (verified: deriveOwnerKek runs Argon2id over the password, then HKDF, never the master key). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The repo claimed two different things. LICENSE and the README said MIT; every crate said "MIT OR Apache-2.0", and no Apache-2.0 text existed anywhere. So the crates offered users a licence whose terms the project never shipped. CONTRIBUTING was the part that actually mattered: it told every contributor their work was licensed "MIT or Apache-2.0 at the user's option". People have been agreeing to terms the project doesn't publish. Settle on MIT, which is what LICENSE, the README, and the public framing have said all along: - Cargo.toml -> license = "MIT" (all five inheriting crates follow) - the two lightning crates declared it directly; updated too - ghostkey-web/package.json had no license field; add "MIT" - CONTRIBUTING points at LICENSE instead of naming a second licence Worth knowing: MIT alone has no express patent grant, which is the one thing Apache-2.0 would have added. Going MIT-only is the smaller promise, and it's the one already being made. Verified: cargo metadata reports MIT for every crate, cargo check and npm run build pass, no "apache" reference left in the repo. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Restores what the crates always claimed, and ships the text to back it up. Before this, Cargo.toml offered users Apache-2.0 while the repo contained only MIT, so the second option had no terms behind it. - LICENSE -> LICENSE-MIT (git tracks the rename, history preserved) - LICENSE-APACHE: the canonical text, fetched verbatim from apache.org rather than reproduced from memory (11,358 bytes) - LICENSE.md: explains the choice, and states that contributions are dual licensed unless the contributor says otherwise - Cargo.toml and the two lightning crates back to "MIT OR Apache-2.0" - ghostkey-web/package.json likewise - README and CONTRIBUTING name both licences and point at LICENSE.md Why both rather than either alone: Apache-2.0 carries an express patent grant, which MIT lacks, and MIT is GPLv2-compatible, which Apache-2.0 is not. Offering the pair means a downstream project takes whichever it needs, which matters for a codebase we want other wallets to borrow the inheritance pattern from. Verified: cargo metadata reports "MIT OR Apache-2.0" for every crate, cargo check passes, package.json parses, and no doc still links the old ./LICENSE path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #289. That PR was squash-merged from an early snapshot of the branch, so these four commits never reached
main. This lands the remainder.1. Dual licence
mainalready advertisedlicense = "MIT OR Apache-2.0"in every crate, but the repo only ever contained MIT. The second option had no terms behind it. So ship the text:README+CONTRIBUTINGname both licences and point atLICENSE.mdghostkey-web/package.jsonhad no licence field at all; now"MIT OR Apache-2.0"Cargo.tomlis untouched: it already said the right thingCONTRIBUTING was the part that mattered. It told contributors their work was licensed "MIT or Apache-2.0 at the user's option" while the repo published only one of those.
Why both: Apache-2.0 carries an express patent grant that MIT lacks; MIT is GPLv2-compatible and Apache-2.0 isn't. Offering the pair lets a downstream project take whichever it needs, which matters for a codebase we want other wallets to borrow the inheritance pattern from.
2. Custody doc corrections
Both are the same root cause: docs not re-read since #124 killed the master-key heir derivation.
README listed, under "What works today", that the server derives a no-wallet heir's key from
(master_key, heir_email, vault_id). That reads as current behaviour. It isn't:heir_derivationis null on every new vault, in bothPasswordSetupPortalandAddHeirPortal. The claim is wrong in the worst direction, telling a reader that one master-key breach exposes every no-wallet heir key, which is the exact weakness #124 removed.threat-model had the same staleness, and it overstated live risk: the F2 blast radius is closed for new vaults and does not grow.
The sharper find is D1. It says an operator "cannot construct a valid witness without either the owner's xprv or the heir's xprv", and never cross-references A3.2, where the master key derives the heir xprv for F2 vaults. Both statements are individually true, so the gap only shows if you read them together. D1 now says plainly that it does not hold for legacy F2 vaults, and notes the owner xprv is sealed under an Argon2id password KEK (verified:
deriveOwnerKekruns Argon2id over the password, then HKDF, never the master key).Verification
cargo check --workspace✓ ·cargo metadatareportsMIT OR Apache-2.0for all 7 crates ✓package.jsonparses, licence field present ✓./LICENSEpath ✓Cargo.tomlnet diff vs main is empty, as intended ✓🤖 Generated with Claude Code