Skip to content

feat: negotiate encryption policy per peer - #9562

Open
pjwerneck wants to merge 16 commits into
devfrom
pjwerneck/auto-encryption-settings
Open

pjwerneck wants to merge 16 commits into
devfrom
pjwerneck/auto-encryption-settings

Conversation

@pjwerneck

@pjwerneck pjwerneck commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Each client now advertises an encryption policy (off, optional or required) in its version
file, and a pair encrypts when either side requires it. Keys and bundles are set up automatically,
so a client of an enclave that requires encryption needs no setting. The default stays optional.

Changes

  • login(encryption=...) takes True (required), False (optional) or "off". The policy is the
    new encryption_policy field of SYFT_version.json.
  • An optional client makes keys only when a peer requires encryption. The key file records a
    required policy, so later logins and syft-bg stay required. A key file without the field reads
    as required.
  • An off and a required client conflict: each side skips the other with a warning. A peer whose
    version file has no policy runs an outdated syft and is skipped with a warning to upgrade.
  • A pair that encrypts refuses plaintext: the owner archives such a message unread, the scientist
    skips it, both with a warning.
  • A send that waits for the peer's policy or keys stays in memory until the next sync, with a
    warning. A scientist's send to a non-peer raises; the owner drops an outbox message to a
    non-peer with a warning.
  • Files at rest are encrypted when the client is required. Files written before a switch stay
    plaintext and remain readable.
  • A sync raises when another process made the key file required after this one started.
  • The scientist sends one message per datasite owner. Before, all queued changes went to the owner
    of the last path.
  • The enclave makes keys at boot and binds them to the attestation, also when optional. Clients
    follow the enclave's policy, so the demo scripts drop their encryption flag.

Note

Release note: clients skip an enclave image built before this change as outdated. Rebuild and
deploy the enclave image with, or before, this client release.

Testing

  • New tests/unit/test_encryption_policy.py (57 tests, mock Drive) and enclave tests for the
    negotiated job flow and boot-time keys.
  • Full suites pass: tests/unit 626, migrations 108, syft-enclave 298, syft-rds 151,
    syft-job 121, syft-datasets 51.
  • Live run on real Drive (two test accounts): job round trips with the DO required, with the DS
    required, and with both optional; an off/required conflict; and a policy change while a
    process runs. All five passed, with the raw Drive files checked as encrypted or plaintext.

Asana task

Clients advertise an encryption policy (optional or required) in
SYFT_version.json. A pair encrypts when one side requires it, so clients
of an enclave need no encryption setting.

WIP: not ready for review.
- Load the key file without a nested lock in ensure_keys (deadlock).
- Keep held messages on disk; save after each send.
- Read an earlier peer without a bundle as unknown for one load, then off.
- Advertise a switch to required also from a process that never wrote the
  version file.
- Hold sends before the first peer load.
- Re-read an unknown peer through PeerManager, before the message is
  converted.
- Skip a bundle that is already published; warn on a Drive error.
- Send queued outbox messages directly; keep only pending ones on disk,
  with one write per flush and no loss on errors.
- Reload the key file policy before direct event writes.
- Catch every pending error per recipient when sending changes.
- Read earlier peers' bundles in the parallel version load.
- Decode held hashes again only when the held file changes.
- Document the encryption policy and the earlier-client limit.
…ites

- Remember peers seen as required in the key file; ignore an advertised
  downgrade until the user trusts a new key for the peer.
- Encrypt plaintext files at rest before direct event writes too.
- Run the at-rest pass under its own lock, with parallel downloads.
- Key the held-hash cache on file content.
- Read earlier peers without a bundle again only every tenth load.
- Download in parallel batches when rejecting plaintext inbox messages.
- Take an earlier peer as required only for a valid bundle; a failed
  check or a junk file keeps the policy unknown and is checked again.
- Record a missing bundle only in a peer load, so add_peer keeps the grace.
- Wait on plaintext while the peer policy is unknown; keep the last known
  policy when the version file disappears.
- Hold unsent proposals when a send fails.
- Keep a version when only the bundle check fails.
- Treat an unreadable own bundle as not published.
- Name test SyftBox folders with uuid4, so tests do not share caches.
- Treat a peer without an encryption policy as outdated: skip it with a
  warning to upgrade, and raise on a send to it.
- Remove the use_encryption keyword shim; pass encryption_policy.
- Share the hold-or-drop rule through PeerStore.should_hold.
- Remove the held-hash cache, the parallel downloads and the holding of
  sends before the first peer load.
- Merge redundant tests and rename tests without filler words.
An off client keeps no record of required peers; say so in the docs.
…ected_ prefix

- Refuse plaintext at rest once the files at rest are encrypted
- Write only changes to remembered required peers
- Use the effective peer policy in add_peer
- Find rejected messages with a Drive name query
- Read the key file again only after it changes
- Share the file lock and atomic write helpers
- Record required_since; accept older plaintext outbox history
…ejected lookup

- Record when the files at rest were encrypted; accept older plaintext
- Read the key file once per batch of files at rest
- Take key file data in a process without keys
- Escape names in Drive queries; read every page
- Check resent names in one query per batch
- Drop plaintext to an encrypting pair with a warning; remove reject-and-resend
- Keep pending sends in memory until the next sync; remove held message files
- Encrypt only new files at rest; remove the one-time pass and required_since
- Remove remembered required peers (moved to a follow-up)
- Take the policy from the key file at startup only
- Warn when a message waits in memory for encryption, or is dropped
- Warn when messages from a peer wait to be read
- Refuse to sync when the key file became required after start
- Split the send loop out of process_file_changes_queue
- Remove unused PeerManagerConfig.use_encryption
- Rename tests with filler words; fix a docstring and an import
- Restore the original place of _with_pin and BUNDLE_FILE_KEY
@review-notebook-app

Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

- Integration test: the DS syncs after approval to send the job it held
- Apply prettier and nbstripout to files the branch changed
@pjwerneck
pjwerneck requested a review from rasswanth-s October 14, 2026 22:04

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant