{"id":21304585,"url":"https://github.com/katafrakt/rom-encrypted_attribute","last_synced_at":"2026-01-26T19:35:50.465Z","repository":{"id":205823932,"uuid":"715327357","full_name":"katafrakt/rom-encrypted_attribute","owner":"katafrakt","description":"RomEncryptedAttribute: Rails-compatible encrypted attributes for ROM","archived":false,"fork":false,"pushed_at":"2024-10-26T20:02:29.000Z","size":31,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-31T22:04:43.059Z","etag":null,"topics":["rom","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/katafrakt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-11-06T23:19:05.000Z","updated_at":"2024-10-26T20:01:37.000Z","dependencies_parsed_at":null,"dependency_job_id":"73116901-4eb2-433e-8348-6e818a0e30e2","html_url":"https://github.com/katafrakt/rom-encrypted_attribute","commit_stats":null,"previous_names":["katafrakt/rom_encrypted_attribute","katafrakt/rom-encrypted_attribute"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/katafrakt/rom-encrypted_attribute","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katafrakt%2From-encrypted_attribute","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katafrakt%2From-encrypted_attribute/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katafrakt%2From-encrypted_attribute/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katafrakt%2From-encrypted_attribute/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/katafrakt","download_url":"https://codeload.github.com/katafrakt/rom-encrypted_attribute/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/katafrakt%2From-encrypted_attribute/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263833275,"owners_count":23517367,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rom","ruby"],"created_at":"2024-11-21T16:08:58.543Z","updated_at":"2026-01-26T19:35:50.439Z","avatar_url":"https://github.com/katafrakt.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ROM::EncryptedAttribute\n\nThis gem adds support for encrypted attributes to [ROM](https://rom-rb.org/).\n\nTraditionally ROM team [suggested](https://discourse.rom-rb.org/t/question-encryption-support-thoughts/387) to put encryption logic in repository code (more precisely, in the mapper from database struct to an entity). I personally think this is not the greatest idea. Repository lies logically in the application layer (or even domain layer), while encryption and decryption of data is a purely infrastructure concern. As such, it should be as low-level and hidden as possible.\n\nIn ROM terms it means doing it in a relation. The gem leverages custom types to achieve encryption and decryption.\n\nThe scheme is compatible with Rails' default settings for ActiveRecord encryption, so you can still read records encrypted with ActiveRecord from ROM (and vice versa) as long as you provide the same primary key and key derivation salt.\n\n## Installation\n\nInstall the gem and add to the application's Gemfile by executing:\n\n    $ bundle add rom-encrypted_attribute\n\nIf bundler is not being used to manage dependencies, install the gem by executing:\n\n    $ gem install rom-encrypted_attribute\n\n## Usage\n\nThere are two ways to use this library: via a ROM schema plugin or by a \"bare metal\" approach.\n\n### ROM plugin\n\nSomewhere in you code set the config for the gem. This is done using [`Dry::Configurable`](https://dry-rb.org/gems/dry-configurable/1.0/), so you can use all options available there. For example:\n\n``` ruby\nROM::EncryptedAttribute.configure do |config|\n  config.primary_key = \"your-primary-key\" # required\n  config.key_derivation_salt = \"your-derivation-salt\" # required\n  config.hash_digest_class = OpenSSL::Digest::SHA256 # SHA1 by default\nend\n```\n\nThen use the plugin in your ROM relation:\n\n``` ruby\nclass SecretNotes \u003c ::ROM::Relation[:sql]\n  schema(:secret_notes, infer: true) do\n    use :encrypted_attributes\n    encrypt :content\n  end\nend\n```\n\nYou can override individual configuration values if, for example, one database table uses different primary key:\n\n``` ruby\nclass SecretNotes \u003c ::ROM::Relation[:sql]\n  schema(:secret_notes, infer: true) do\n    use :encrypted_attributes, primary_key: ENV[\"SPECIAL_PRIMARY_KEY\"]\n    encrypt :content\n  end\nend\n```\n\nIf you specify all configuration options, or use defaults, you can skip setting the global config.\n\nYou can also override global per-schema settings on a per-field level:\n\n``` ruby\nclass SecretNotes \u003c ::ROM::Relation[:sql]\n  schema(:secret_notes, infer: true) do\n    use :encrypted_attributes\n    encrypt :content\n    encrypt :title, :hash_digest_class: OpenSSL::Digest::SHA256\n    encrypt :maybe_encrypted, support_unencrypted_data: true\n  end\nend\n\n```\n\n### \"Bare metal\"\n\nIn your relation, define custom types using a helper method from the gem. You need to provide the credentials to it somehow. This might be done via environmental variables, Hanami settings (if you're using Hanami) or any other means, really.\n\n```ruby\nclass SecretNotes \u003c ROM::Relation[:sql]\n  EncryptedString, EncryptedStringReader =\n    ROM::EncryptedAttribute.define_encrypted_attribute_types(\n      primary_key: ENV[\"ENCRYPTION_PRIMARY_KEY\"],\n      key_derivation_salt: ENV[\"ENCRYPTION_KEY_DERIVATION_SALT\"]\n    )\n    \n  schema(:secret_notes, infer: true) do\n    attribute :content, EncryptedString, read: EncryptedStringReader\n  end\nend\n```\n\nWith this approach you can define the types globally in your application and reuse it, without having to pass primary_key and key_derivation_salt every time in the schema.\n\n### Other considerations\n\nBy default the gem uses SHA1 for key derivation (same as Rails' default), but you can configure it by passing custom `hash_digest_class` option.\n\n``` ruby\nclass SecretNotes \u003c ROM::Relation[:sql]\n  EncryptedString, EncryptedStringReader =\n    ROM::EncryptedAttribute.define_encrypted_attribute_types(\n      primary_key: ENV[\"ENCRYPTION_PRIMARY_KEY\"],\n      key_derivation_salt: ENV[\"ENCRYPTION_KEY_DERIVATION_SALT\"],\n      hash_digest_class: OpenSSL::Digest::SHA256\n    )\n    \n  schema(:secret_notes, infer: true) do\n    attribute :content, EncryptedString, read: EncryptedStringReader\n  end\nend\n\n```\n\n### Caveats\n\n* Due to [a bug](https://github.com/rom-rb/rom-sql/issues/423) in `rom-sql`, reading unencrypted data requires a monkey patch to ROM. Since this is quite aggressive, you are expected to opt-in to this by calling `ROM::SQL::Patch432.install!`.\n* Support for deterministic encryption from `ActiveRecord::Encryption` is not (yet) implemented\n* Support for key rotation is not (yet) implemented\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/katafrakt/rom-encrypted_attribute.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkatafrakt%2From-encrypted_attribute","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkatafrakt%2From-encrypted_attribute","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkatafrakt%2From-encrypted_attribute/lists"}