Module: Familia::Features::EncryptedFields::ModelClassMethods

Defined in:
lib/familia/features/encrypted_fields.rb

Instance Method Summary collapse

Instance Method Details

#encrypted_field(name, aad_fields: []) ⇒ Object

Define an encrypted field that transparently encrypts/decrypts values

Encrypted fields are stored as JSON objects containing the encrypted ciphertext along with cryptographic metadata. Values are automatically encrypted on assignment and decrypted on access.

Examples:

Basic encrypted field

class Vault < Familia::Horreum
  feature :encrypted_fields
  encrypted_field :secret_key
end

Encrypted field with additional authentication

class Document < Familia::Horreum
  feature :encrypted_fields
  field :doc_id, :owner_id
  encrypted_field :content, aad_fields: [:doc_id, :owner_id]
end

Encrypted field bound to dynamic entropy

class Secret < Familia::Horreum
  feature :encrypted_fields
  encrypted_field :payload, key_material: ->(rec) { rec.passphrase }
end

Parameters:

  • name (Symbol)

    Field name

  • aad_fields (Array<Symbol>) (defaults to: [])

    Additional fields to include in authentication

  • key_material (Proc, nil)

    Optional proc mixed into key derivation as extra entropy. It is called with the record instance and must return the entropy as a String (a RedactedString is unwrapped automatically); return nil to contribute no entropy for that record. Because the returned value participates in key derivation rather than authentication, supplying the wrong material yields a derivation mismatch (garbage/failed decrypt), not an auth-tag error. The value is not persisted, so it must be reproducible at decrypt time.

  • kwargs (Hash)

    Additional field options



312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/familia/features/encrypted_fields.rb', line 312

def encrypted_field(name, aad_fields: [], **)
  @encrypted_fields ||= []
  @encrypted_fields << name unless @encrypted_fields.include?(name)

  # Add to field_groups if the group exists
  if field_groups&.key?(:encrypted_fields)
    field_groups[:encrypted_fields] << name
  end

  field_type = EncryptedFieldType.new(name, aad_fields: aad_fields, **)
  register_field_type(field_type)
end

#encrypted_field?(field_name) ⇒ Boolean

Check if a field is encrypted

Parameters:

  • field_name (Symbol)

    The field name to check

Returns:

  • (Boolean)

    true if field is encrypted, false otherwise



338
339
340
# File 'lib/familia/features/encrypted_fields.rb', line 338

def encrypted_field?(field_name)
  encrypted_fields.include?(field_name.to_sym)
end

#encrypted_fieldsArray<Symbol>

Returns list of encrypted field names defined on this class

Returns:

  • (Array<Symbol>)

    Array of encrypted field names



329
330
331
# File 'lib/familia/features/encrypted_fields.rb', line 329

def encrypted_fields
  @encrypted_fields || []
end

#encryption_infoHash

Get encryption algorithm information

Returns:

  • (Hash)

    Hash containing encryption algorithm details



346
347
348
349
350
351
352
353
354
# File 'lib/familia/features/encrypted_fields.rb', line 346

def encryption_info
  provider = Familia::Encryption.current_provider
  {
    algorithm: provider.algorithm_name,
    key_size: provider.key_size,
    nonce_size: provider.nonce_size,
    tag_size: provider.tag_size,
  }
end