docs(privacy): private studysets as built (ADR 0019)
Learn's AGENTS.md says how private studysets work (keys, the envelope, locked rows, rewriting a tree) and what changed for the connector, publishing, uploads and the learner count; ADR 0019 records what was built otherwise than decided or not yet (a private studyset's files); the halkyon_app README describes the content cipher and device keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
9cdd4859d1
commit
dcdc9c1542
3 changed files with 41 additions and 5 deletions
File diff suppressed because one or more lines are too long
|
|
@ -114,3 +114,29 @@ millisecond), its table and the columns it changed.
|
||||||
rule 6's way back is taken.
|
rule 6's way back is taken.
|
||||||
- Making a large library private takes a sync of everything in it.
|
- Making a large library private takes a sync of everything in it.
|
||||||
- Nobody, the operator included, can restore a private studyset whose keys are lost.
|
- Nobody, the operator included, can restore a private studyset whose keys are lost.
|
||||||
|
|
||||||
|
## As built (21 Oct 2026)
|
||||||
|
|
||||||
|
- **Not yet:** a private studyset's files (D5) are still uploaded readable,
|
||||||
|
and an asset row's file name with them. The instance takes encrypted
|
||||||
|
uploads already (`startUpload`/`finishUpload`'s `encrypted`: no PDF check,
|
||||||
|
4 KiB more room); the app has yet to seal a file with its studyset's key
|
||||||
|
before hashing it, which every place adding a file (the editors, the PDF
|
||||||
|
import, copies, archives) must name the studyset for.
|
||||||
|
- **Count me** stays in the person's settings, which follow them to every
|
||||||
|
device, and the device mirrors it to the instance after each sync
|
||||||
|
(`counted_learner`), reporting the copies only while it is on: the
|
||||||
|
instance keeps the setting, as D2 asks, but the person's choice is still
|
||||||
|
made where it was.
|
||||||
|
- **Tag names:** the instance refuses a name sent for a tag that isn't the
|
||||||
|
person's and a release whose encrypted tag has none; names of the
|
||||||
|
person's tags the release doesn't carry are ignored rather than refused,
|
||||||
|
as the device sends all its tags' names.
|
||||||
|
- **Locked rows:** a studyset whose key doesn't open shows as locked; its
|
||||||
|
other rows read as blank, which the lists leave out; a tag or settings
|
||||||
|
row that doesn't open is left out entirely, so nothing folds or deletes
|
||||||
|
it on a device without the keys.
|
||||||
|
- **Identity binding:** each payload is sealed for its table, row id and
|
||||||
|
column, and signed by the account; the signature goes before the
|
||||||
|
ciphertext in the payload column.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,15 @@ Written as the apps are: Dart 3.13's primary constructors, Material from
|
||||||
hands it to the screens, which then offer no Add, and the start screen
|
hands it to the screens, which then offer no Add, and the start screen
|
||||||
offers an account to create in place of the app's sentence on adding
|
offers an account to create in place of the app's sentence on adding
|
||||||
GitHub; `gitHubProblemText` says why a GitHub sign-in was refused.
|
GitHub; `gitHubProblemText` says why a GitHub sign-in was refused.
|
||||||
|
- **Content sealed with data keys** (`lib/src/privacy/`, ADR 0019):
|
||||||
|
`ContentCipher` (`SodiumContentCipher`, on the isolate it is used on, as an
|
||||||
|
app seals and opens rows one by one; `FakeContentCipher` in tests) makes a
|
||||||
|
store's data keys, sealed to the account and signed by it, opens them, and
|
||||||
|
seals and opens a row's content for the row it is stored in (its table, id
|
||||||
|
and column), the payload holding the signature before the ciphertext. An
|
||||||
|
anonymous person's device makes key pairs of its own
|
||||||
|
(`AccountCrypto.newDeviceKeys`), which `makePassword` keeps as the account's
|
||||||
|
once they set a password.
|
||||||
- **A password and TOTP** (`lib/src/password/`, ADR 0017): `PasswordRepository`
|
- **A password and TOTP** (`lib/src/password/`, ADR 0017): `PasswordRepository`
|
||||||
on a `PasswordGateway` (`ServerpodPasswordGateway`), an `AccountCrypto`
|
on a `PasswordGateway` (`ServerpodPasswordGateway`), an `AccountCrypto`
|
||||||
(`SodiumAccountCrypto`: halkyon_keys and SRP's client half, each step on an
|
(`SodiumAccountCrypto`: halkyon_keys and SRP's client half, each step on an
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue