Skip to content

Add field-level encryption support for nested dict fields#1

Draft
Copilot wants to merge 5 commits intomasterfrom
copilot/support-field-level-encryption
Draft

Add field-level encryption support for nested dict fields#1
Copilot wants to merge 5 commits intomasterfrom
copilot/support-field-level-encryption

Conversation

Copy link
Copy Markdown

Copilot AI commented Nov 27, 2025

Field-level encryption previously only worked for top-level fields. This adds support for encrypting fields nested in dicts at any depth, with transparent encryption/decryption using standard dict notation.

Changes

EncryptedObject wrapper class (ming/encryption.py)

  • Dict subclass that intercepts __getitem__/__setitem__ to decrypt/encrypt on access
  • Automatically wraps nested dicts containing _encrypted fields
  • Provides transparent access: doc.full_name['first_name'] decrypts full_name['first_name_encrypted']

Recursive encryption (ming/encryption.py)

  • Extended encrypt_some_fields() to recursively process nested dicts using schema information
  • New _encrypt_nested_dict() identifies encrypted field pairs and encrypts decrypted counterparts
  • Supports arbitrary nesting depth

Automatic wrapping (ming/metadata.py)

  • Modified _FieldDescriptor.__get__() to wrap dict values with EncryptedObject when they contain encrypted fields (checked recursively)
  • Wrapping happens lazily on first access

Usage

class User(Document):
    _id = Field(schema.ObjectId)
    full_name = Field(dict(
        first_name_encrypted=schema.Binary,
        last_name_encrypted=schema.Binary
    ))

# Create with plain text - automatically encrypted
user = User.make_encr({
    '_id': ObjectId(),
    'full_name': {'first_name': 'John', 'last_name': 'Doe'}
})

# Access with dict notation - automatically decrypted
print(user.full_name['first_name'])  # 'John'

# Set with dict notation - automatically encrypted
user.full_name['first_name'] = 'Johnny'

Multi-level nesting works identically:

personal_info = Field(dict(
    address=dict(
        street_encrypted=schema.Binary,
        city_encrypted=schema.Binary
    )
))

# Access: doc.personal_info['address']['street']
Original prompt

Field level encryption is handled by defining an encrypted field and a decrypted field. For example, if I want to encrypt the field called email, I need to create a field called email_encrypted of type schema.Binary to store the encrypted value, and a decrypted field email of type DecryptedField(str, 'email_encrypted') which references the encrypted field by name. However, field level encryption only works for top level fields; it doesn't work for nested fields like those in dicts or values in a list. Create the code to support field level encryption for dict fields, with any level of nesting. Ideally, it should support schemas defined like the following example:

class User(Document):
class mongometa:
name = 'user'

m: 'Manager[User]'

_id = Field(schema.ObjectId)
username = Field(str)
full_name = Field(dict(first_name_encrypted=schema.Binary, first_name=DecryptedField(str, 'first_name_encrypted'), last_name_encrypted=schema.Binary, last_name=DecryptedField(str, 'last_name_encrypted')))

Additionally, when setting a value to a decrypted field, current functionality encrypts the value and automatically sets it in the encrypted field. Same thing happens when reading from the decrypted field, it takes the value in the encrypted field and decrypts it. For reference, look at how the get and set methods in DecyrptedField are defined. So, new code should support a similar pattern for setting and retrieving values from nested encrypted fields and their respective decrypted fields in dicts, while preserving the get/set dict notation like full_name['first_name'] = 'John', same for values in lists, preserving get/set index notation.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI self-assigned this Nov 27, 2025
Copilot AI and others added 4 commits November 27, 2025 18:46
Co-authored-by: jcarlosdev <8920902+jcarlosdev@users.noreply.github.com>
Co-authored-by: jcarlosdev <8920902+jcarlosdev@users.noreply.github.com>
Co-authored-by: jcarlosdev <8920902+jcarlosdev@users.noreply.github.com>
Co-authored-by: jcarlosdev <8920902+jcarlosdev@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement field level encryption for dict fields Add field-level encryption support for nested dict fields Nov 27, 2025
Copilot AI requested a review from jcarlosdev November 27, 2025 18:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants