NEC-98: Say precisely what the hosted service holds that the passphrase bears on #197

Merged
nectenda-agent merged 4 commits from worktree-nec-98-say-precisely-what-the-hosted-service-hol into main 2026-09-28 14:39:44 +01:00
Collaborator

Task: NEC-98 — https://projectron.nerchure.com/tasks/98

Several copies of the security claim said the hosted service receives "nothing derived from the passphrase". That is false: it stores the private key wrapped under a passphrase-derived key. This narrows the privacy notice, terms, key-storage.md, the purchase email, the plugin's published comments and both READMEs to what is true, that no hash or verifier is sent, and pins the wording in security-model-claims.test.ts. Review found that security-model.md and CRYPTO-025 still overclaimed. They called the wrapped key the only passphrase-bound value held, but user_key_history keeps every earlier wrapping, and they said the master key is never stored, but the recovery blob is that key sealed. Both are now disclosed and pinned (NEC-140). Documentation and comments only; no code path changes.

Spec: docs/changes/NEC-98-passphrase-derived-claims/spec.md

Also fixes NEC-140: Security model says the wrapped private key is the only passphrase-bound value held
Also fixes NEC-141: README says keys are derived from the password and never reach the server

Changelog

The privacy notice, terms, security model and purchase email now say exactly what the hosted service holds that your passphrase bears on: never a hash or verifier of it, but your private key wrapped under it, including earlier wrappings kept after a passphrase change.

Task: NEC-98 — https://projectron.nerchure.com/tasks/98 Several copies of the security claim said the hosted service receives "nothing derived from the passphrase". That is false: it stores the private key wrapped under a passphrase-derived key. This narrows the privacy notice, terms, key-storage.md, the purchase email, the plugin's published comments and both READMEs to what is true, that no hash or verifier is sent, and pins the wording in security-model-claims.test.ts. Review found that security-model.md and CRYPTO-025 still overclaimed. They called the wrapped key the only passphrase-bound value held, but user_key_history keeps every earlier wrapping, and they said the master key is never stored, but the recovery blob is that key sealed. Both are now disclosed and pinned (NEC-140). Documentation and comments only; no code path changes. Spec: `docs/changes/NEC-98-passphrase-derived-claims/spec.md` Also fixes NEC-140: Security model says the wrapped private key is the only passphrase-bound value held Also fixes NEC-141: README says keys are derived from the password and never reach the server ## Changelog The privacy notice, terms, security model and purchase email now say exactly what the hosted service holds that your passphrase bears on: never a hash or verifier of it, but your private key wrapped under it, including earlier wrappings kept after a passphrase change.
The hosted service holds the private key wrapped under a passphrase-derived
key, so "nothing derived from the passphrase reaches us" was false. NEC-52
narrowed security-model.md, identity.md and CRYPTO-025; this narrows the
privacy notice, the terms, key-storage.md, the purchase email, the plugin's
published comments and the mirror README to the same claim, and pins it in
security-model-claims.test.ts so the broad form cannot come back.

Task: NEC-98
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016TPRS2zZaf7AQkXcFNfmJW
Review found both untrue: the identity service also keeps earlier wrappings
of the private key and the recovery blob, and the identity keypair and
folder keys are random rather than passphrase-derived. The plugin comment
also named the master key as the wrapping key where it is its HKDF output.

Task: NEC-98
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016TPRS2zZaf7AQkXcFNfmJW
security-model.md and CRYPTO-025 said the wrapped private key was the only
passphrase-bound value the hosted service holds, but user_key_history keeps
every superseded wrapping, so an old passphrase stays guessable after a
change. "The master key is never stored" likewise ignored the recovery blob,
which is that key sealed under the recovery key. Both are pinned.

Task: NEC-98
Also-fixes: NEC-140
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016TPRS2zZaf7AQkXcFNfmJW
Stop the README saying keys are password-derived and never reach the server
All checks were successful
Release note / release-note (pull_request) Successful in 14s
CI / build (pull_request) Successful in 5m19s
CI / e2e (pull_request) Successful in 5m33s
CI / promote (pull_request) Has been skipped
1c321dbc40
Folder-key wraps reach the sync server and the wrapped private key reaches
the identity service, and neither key is derived from the password. Same
wording as the mirror README now uses.

Task: NEC-98
Also-fixes: NEC-141
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016TPRS2zZaf7AQkXcFNfmJW
cruelacid force-pushed worktree-nec-98-say-precisely-what-the-hosted-service-hol from 1c321dbc40
All checks were successful
Release note / release-note (pull_request) Successful in 14s
CI / build (pull_request) Successful in 5m19s
CI / e2e (pull_request) Successful in 5m33s
CI / promote (pull_request) Has been skipped
to 8fecd219da
All checks were successful
Release note / release-note (pull_request) Successful in 12s
CI / build (pull_request) Successful in 4m44s
CI / e2e (pull_request) Successful in 5m20s
CI / promote (pull_request) Has been skipped
Deploy site / deploy (push) Successful in 58s
CI / e2e (push) Successful in 5m36s
CI / build (push) Successful in 5m55s
CI / promote (push) Successful in 36s
2026-09-28 14:33:43 +01:00
Compare
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Nectenda/nectenda!197
No description provided.