valvet 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 33f178cef255bdb28655e535b3a1b8901611fca9473c7f972df42302775eedd4
4
+ data.tar.gz: 0e03ef112f57112481ffbc7beadd99c9894851961a3fa992eac4a6273851cb11
5
+ SHA512:
6
+ metadata.gz: a84ac8a7b64f0674755c258e9af9317446b77fe16c99568ef2b2b200402efb8069f14f019d79f5de51be30ed0bd3df29206ef9e4ca739bdccd395af4357d5db7
7
+ data.tar.gz: d6a5a0ca17f859749437b5fd2e9ae6be14cf2668849d555668cc078720ac082048f867f0722be7ae12293a4eae1792615cfcec253ce8e23ebb19714a9cdc211f
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2026-02-27
4
+
5
+ - Initial release
@@ -0,0 +1,10 @@
1
+ # Code of Conduct
2
+
3
+ "valvet" follows [The Ruby Community Conduct Guideline](https://www.ruby-lang.org/en/conduct) in all "collaborative space", which is defined as community communications channels (such as mailing lists, submitted patches, commit comments, etc.):
4
+
5
+ * Participants will be tolerant of opposing views.
6
+ * Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
7
+ * When interpreting the words and actions of others, participants should always assume good intentions.
8
+ * Behaviour which can be reasonably considered harassment will not be tolerated.
9
+
10
+ If you have any concerns about behaviour within this project, please contact us at ["kim@burgestrand.se"](mailto:"kim@burgestrand.se").
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Kim Burgestrand
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # Valvet
2
+
3
+ Keep secrets in your config files. Valvet encrypts sensitive values while leaving everything else readable, so you can check the whole file into version control, just like Rails credentials.
4
+
5
+ It uses asymmetric encryption ([NaCl sealed boxes](https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes) via [RbNaCl](https://github.com/RbNaCl/rbnacl)), which means anyone on the team can add new secrets using the public key — without ever needing the private key.
6
+
7
+ Give each environment its own keypair and they can all live in one file, each unable to decrypt the other's secrets.
8
+
9
+ ## Usage
10
+
11
+ ## CLI
12
+
13
+ Generate a keypair (public key to stdout, private key to stderr):
14
+
15
+ ```bash
16
+ valvet keypair # prints both, labeled
17
+ valvet keypair > public.key 2> private.key # saves each to a file
18
+ ```
19
+
20
+ Encrypt and decrypt individual values:
21
+
22
+ ```bash
23
+ valvet encrypt "my secret" --key public.key
24
+ valvet decrypt "ciphertext..." --key private.key
25
+ ```
26
+
27
+ ## Config files
28
+
29
+ Put your config in a YAML file with `!public_key` and `!encrypted` tags:
30
+
31
+ ```yaml
32
+ development:
33
+ public_key: !public_key cWgtEYZ3bDXYgiHGbanGr+vl4HQrDgiAmOlBRc+hhgo=
34
+ secret_key_base: !encrypted 7oc+QbPyIa3Oe4ty09tNWRhgkAvlFjyWcggfeRAz8olE5VRF3lNvJEVGs8xgGquoXvItXPWOfus0ntQaUphFEsANyAE=
35
+ database:
36
+ password: !encrypted 3ad2zo3NKQU1EZm7XB2uFiqE6wAWjPPqjvPTD8rUB3m+ya2xrE5YvEuxDYkswgxqMjRfm5V1OHyz4cnez0GLUTif1+0=
37
+
38
+ production:
39
+ public_key: !public_key R7ljpsyGiOm2Yz3ElbQwCDDapAMEhCHl6WYWS/ep4vM=
40
+ secret_key_base: !encrypted HWZrJnY+AxBW5+W71Ar6DHkW2clqmtccrcCy5iek+9H4BfYTS1VR5/P3p+YhNzIgd7+MTTJxSTXmGeG9k0CQfoUpnn0=
41
+ database:
42
+ password: !encrypted 8Z2QiPc7gKWqTmjs6mlNiKWPJ997ftzgpiMO/NdEEjzAvXAAckYIqeyOxem+OeCsDHsCwM8j2x8XPH/7VM383dmw+jA=
43
+ ```
44
+
45
+ ## Rails
46
+
47
+ Place your config in `config/valvet.yml` and set `VALVET_PRIVATE_KEY` in your environment. The Railtie is loaded automatically and exposes `Rails.configuration.valvet`:
48
+
49
+ ```ruby
50
+ Rails.configuration.valvet.secret_key_base
51
+ Rails.configuration.valvet.database.password
52
+ ```
53
+
54
+ ## Installation
55
+
56
+ ```bash
57
+ bundle add valvet
58
+ ```
59
+
60
+ ## Development
61
+
62
+ ```bash
63
+ bin/setup
64
+ rake # runs tests, linting, and RBS validation
65
+ ```
66
+
67
+ ## License
68
+
69
+ [MIT](LICENSE.txt)
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create do |t|
7
+ t.test_prelude = 'require "test_helper"'
8
+ end
9
+
10
+ require "standard/rake"
11
+
12
+ desc "Validate RBS type signatures"
13
+ task "rbs:validate" do
14
+ sh "bundle exec rbs -I sig validate"
15
+ end
16
+
17
+ task default: %i[test standard rbs:validate]
data/exe/valvet ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "valvet"
4
+ require "valvet/cli"
5
+
6
+ exit Valvet::CLI.start(ARGV)
data/lib/valvet/cli.rb ADDED
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "optparse"
4
+
5
+ module Valvet
6
+ class CLI
7
+ def self.start(argv, ...)
8
+ new(...).run(argv.dup)
9
+ end
10
+
11
+ def initialize(out: $stdout, err: $stderr)
12
+ @out = out
13
+ @err = err
14
+ @commands = {
15
+ "keypair" => method(:keypair), "g" => method(:keypair),
16
+ "encrypt" => method(:encrypt), "e" => method(:encrypt),
17
+ "decrypt" => method(:decrypt), "d" => method(:decrypt),
18
+ "help" => method(:help)
19
+ }
20
+ end
21
+
22
+ def run(argv)
23
+ command = @commands.fetch(argv.shift.to_s) { method(:help) }
24
+ command.call(argv) || 0
25
+ end
26
+
27
+ private
28
+
29
+ def keypair(_argv)
30
+ decryptor = Crypto.generate
31
+
32
+ if @out.tty?
33
+ @out.puts "public_key: #{decryptor.public_key}"
34
+ else
35
+ @out.puts decryptor.public_key
36
+ end
37
+
38
+ if @err.tty?
39
+ @err.puts "private_key: #{decryptor}"
40
+ @err.puts "\e[33mKeep the private key secret. Store it in an environment variable, not in version control.\e[0m"
41
+ else
42
+ @err.puts decryptor
43
+ end
44
+ end
45
+
46
+ def encrypt(argv)
47
+ key = nil
48
+ parser = OptionParser.new do |opts|
49
+ opts.banner = "Usage: valvet encrypt VALUE --key PUBLIC_KEY"
50
+ opts.on("-k", "--key KEY", "Public key (base64 or file path)") { |k| key = k }
51
+ end
52
+ parser.parse!(argv)
53
+
54
+ value = argv.shift
55
+ if value.nil? || key.nil?
56
+ @err.puts parser.to_s
57
+ return 1
58
+ end
59
+
60
+ @out.puts Crypto::Encryptor.new(read_key(key)).encrypt(value)
61
+ end
62
+
63
+ def decrypt(argv)
64
+ key = nil
65
+ parser = OptionParser.new do |opts|
66
+ opts.banner = "Usage: valvet decrypt CIPHERTEXT --key PRIVATE_KEY"
67
+ opts.on("-k", "--key KEY", "Private key (base64 or file path)") { |k| key = k }
68
+ end
69
+ parser.parse!(argv)
70
+
71
+ ciphertext = argv.shift
72
+ if ciphertext.nil? || key.nil?
73
+ @err.puts parser.to_s
74
+ return 1
75
+ end
76
+
77
+ @out.puts Crypto::Decryptor.new(read_key(key)).decrypt(ciphertext)
78
+ end
79
+
80
+ def read_key(key)
81
+ File.exist?(key) ? File.binread(key).strip : key
82
+ end
83
+
84
+ def help(_argv)
85
+ @out.puts <<~HELP
86
+ Usage: valvet COMMAND [OPTIONS]
87
+
88
+ Commands:
89
+ keypair, g Generate a new keypair
90
+ encrypt, e Encrypt a value (requires --key)
91
+ decrypt, d Decrypt a value (requires --key)
92
+ help Show this help
93
+
94
+ Run `valvet COMMAND --help` for more information.
95
+ HELP
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,40 @@
1
+ module Valvet
2
+ module Crypto
3
+ def self.encode(data) = Base64.strict_encode64(data)
4
+ def self.decode(data) = Base64.decode64(data)
5
+
6
+ def self.generate
7
+ key = encode(RbNaCl::PrivateKey.generate.to_s)
8
+ Decryptor.new(key)
9
+ end
10
+
11
+ class Encryptor
12
+ def initialize(public_key)
13
+ @public_key = RbNaCl::PublicKey.new(Crypto.decode(public_key))
14
+ end
15
+
16
+ def to_s = Crypto.encode(@public_key.to_s)
17
+
18
+ def encrypt(plaintext)
19
+ box = RbNaCl::Boxes::Sealed.from_public_key(@public_key)
20
+ Crypto.encode(box.encrypt(plaintext))
21
+ end
22
+ end
23
+
24
+ class Decryptor
25
+ def initialize(private_key)
26
+ @private_key = RbNaCl::PrivateKey.new(Crypto.decode(private_key))
27
+ end
28
+
29
+ def to_s = Crypto.encode(@private_key.to_s)
30
+ def public_key = Crypto.encode(@private_key.public_key.to_s)
31
+
32
+ def encryptor = Encryptor.new(public_key)
33
+
34
+ def decrypt(ciphertext)
35
+ box = RbNaCl::Boxes::Sealed.from_private_key(@private_key)
36
+ box.decrypt(Crypto.decode(ciphertext))
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,5 @@
1
+ module Valvet
2
+ Encrypted = Data.define(:ciphertext) do
3
+ def empty? = ciphertext.empty?
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ module Valvet
2
+ module Error
3
+ class Base < StandardError
4
+ end
5
+
6
+ class NoDecryptorError < Base
7
+ attr_reader :public_key
8
+ attr_reader :ciphertext
9
+
10
+ def initialize(public_key:, ciphertext:)
11
+ @public_key = public_key
12
+ @ciphertext = ciphertext
13
+ super("No decryptor for public key #{public_key}")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module Valvet
2
+ PublicKey = Data.define(:key)
3
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "valvet"
4
+ require "rails"
5
+
6
+ module Valvet
7
+ class Railtie < ::Rails::Railtie
8
+ config.valvet = ActiveSupport::OrderedOptions.new
9
+ config.valvet.private_keys = [ENV["VALVET_PRIVATE_KEY"]].compact
10
+
11
+ initializer "valvet.register_yaml_tags", before: :load_environment_config do
12
+ Valvet::YAML.register
13
+ end
14
+
15
+ initializer "valvet.configure" do |app|
16
+ valvet_path = app.root.join("config", "valvet.yml")
17
+
18
+ if valvet_path.exist?
19
+ hash = app.config_for(:valvet).to_h.deep_stringify_keys
20
+ app.config.valvet = Valvet.new(hash, private_keys: app.config.valvet.private_keys)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,86 @@
1
+ module Valvet
2
+ class Store
3
+ Decrypt = Data.define(:public_key, :ciphertext)
4
+ Encrypt = Data.define(:public_key, :plaintext)
5
+
6
+ def initialize(hash, public_key: nil, &handler)
7
+ @hash = hash
8
+ @handler = handler
9
+ @public_key = find_public_key(hash)&.key || public_key
10
+ end
11
+
12
+ def key?(key) = @hash.key?(key)
13
+
14
+ def each(path: [], &block)
15
+ @hash.each do |key, value|
16
+ case value
17
+ when Valvet::PublicKey
18
+ next
19
+ when Valvet::Encrypted
20
+ yield path + [key], value, self
21
+ when Hash
22
+ child_scope(value).each(path: path + [key], &block)
23
+ else
24
+ yield path + [key], value, self
25
+ end
26
+ end
27
+ end
28
+
29
+ def to_h
30
+ @hash.each_with_object({}) do |(key, value), result|
31
+ next if value.is_a?(Valvet::PublicKey)
32
+ result[key] = resolve(key)
33
+ result[key] = result[key].to_h if result[key].is_a?(self.class)
34
+ end
35
+ end
36
+
37
+ def resolve(key)
38
+ value = @hash[key]
39
+ case value
40
+ when Valvet::Encrypted then decrypt(value)
41
+ when Hash then child_scope(value)
42
+ else value
43
+ end
44
+ end
45
+
46
+ def method_missing(name, ...)
47
+ key = name.to_s
48
+ if key.end_with?("=")
49
+ assign(key.chomp("="), ...)
50
+ elsif @hash.key?(key)
51
+ resolve(key)
52
+ else
53
+ super
54
+ end
55
+ end
56
+
57
+ def respond_to_missing?(name, ...)
58
+ key = name.to_s
59
+ @hash.key?(key) || (key.end_with?("=") && @hash.key?(key.chomp("="))) || super
60
+ end
61
+
62
+ private
63
+
64
+ def assign(key, value)
65
+ if @hash[key].is_a?(Valvet::Encrypted)
66
+ ciphertext = @handler.call(Encrypt.new(@public_key, value))
67
+ @hash[key] = Valvet::Encrypted.new(ciphertext:)
68
+ else
69
+ @hash[key] = value
70
+ end
71
+ end
72
+
73
+ def decrypt(encrypted)
74
+ @handler.call(Decrypt.new(@public_key, encrypted.ciphertext))
75
+ end
76
+
77
+ def child_scope(hash)
78
+ self.class.new(hash, public_key: @public_key, &@handler)
79
+ end
80
+
81
+ def find_public_key(hash)
82
+ hash.each_value { |v| return v if v.is_a?(Valvet::PublicKey) }
83
+ nil
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Valvet
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,30 @@
1
+ require "yaml"
2
+
3
+ module Valvet
4
+ module YAML
5
+ def self.register
6
+ ::YAML.add_tag("!encrypted", Valvet::Encrypted)
7
+ ::YAML.add_tag("!public_key", Valvet::PublicKey)
8
+ end
9
+ end
10
+
11
+ class Encrypted
12
+ def init_with(coder) = initialize(ciphertext: coder.scalar)
13
+
14
+ def encode_with(coder)
15
+ coder.scalar = ciphertext
16
+ end
17
+ end
18
+
19
+ class PublicKey
20
+ def init_with(coder) = initialize(key: coder.scalar)
21
+
22
+ def encode_with(coder)
23
+ coder.scalar = key
24
+ end
25
+ end
26
+
27
+ class Store
28
+ def to_yaml(...) = ::YAML.dump(@hash, ...)
29
+ end
30
+ end
data/lib/valvet.rb ADDED
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "valvet/version"
4
+
5
+ require "rbnacl"
6
+ require "base64"
7
+
8
+ require "zeitwerk"
9
+ loader = Zeitwerk::Loader.for_gem
10
+ loader.inflector.inflect("yaml" => "YAML")
11
+ loader.ignore("#{__dir__}/valvet/version.rb")
12
+ loader.ignore("#{__dir__}/valvet/cli.rb")
13
+ loader.ignore("#{__dir__}/valvet/rails.rb")
14
+ loader.setup
15
+
16
+ module Valvet
17
+ def self.new(hash, private_keys: [])
18
+ decryptors = private_keys.to_h do |private_key|
19
+ decryptor = Crypto::Decryptor.new(private_key)
20
+ [decryptor.public_key, decryptor]
21
+ end
22
+
23
+ Store.new(hash) do |intent|
24
+ case intent
25
+ in Store::Decrypt(public_key:, ciphertext:)
26
+ decryptors.fetch(public_key) {
27
+ raise Error::NoDecryptorError.new(public_key:, ciphertext:)
28
+ }.decrypt(ciphertext)
29
+ in Store::Encrypt(public_key:, plaintext:)
30
+ Crypto::Encryptor.new(public_key).encrypt(plaintext)
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ require "valvet/rails" if defined?(Rails::Railtie)
data/log/test.log ADDED
File without changes
data/sig/valvet.rbs ADDED
@@ -0,0 +1,111 @@
1
+ module Valvet
2
+ VERSION: String
3
+
4
+ type base64_encoded = String
5
+
6
+ def self.new: (Hash[String, untyped] hash, ?private_keys: Array[base64_encoded]) -> Store
7
+
8
+ class Encrypted
9
+ attr_reader ciphertext: base64_encoded
10
+
11
+ def self.new: (ciphertext: base64_encoded) -> Encrypted
12
+
13
+ def empty?: () -> bool
14
+
15
+ def init_with: (untyped coder) -> void
16
+
17
+ def encode_with: (untyped coder) -> void
18
+ end
19
+
20
+ class PublicKey
21
+ attr_reader key: base64_encoded
22
+
23
+ def self.new: (key: base64_encoded) -> PublicKey
24
+
25
+ def init_with: (untyped coder) -> void
26
+
27
+ def encode_with: (untyped coder) -> void
28
+ end
29
+
30
+ module Error
31
+ class Base < StandardError
32
+ end
33
+
34
+ class NoDecryptorError < Base
35
+ attr_reader public_key: base64_encoded
36
+ attr_reader ciphertext: base64_encoded
37
+
38
+ def initialize: (public_key: base64_encoded, ciphertext: base64_encoded) -> void
39
+ end
40
+ end
41
+
42
+ module Crypto
43
+ def self.encode: (String data) -> base64_encoded
44
+
45
+ def self.decode: (base64_encoded data) -> String
46
+
47
+ def self.generate: () -> Decryptor
48
+
49
+ class Encryptor
50
+ def initialize: (base64_encoded public_key) -> void
51
+
52
+ def to_s: () -> base64_encoded
53
+
54
+ def encrypt: (String plaintext) -> base64_encoded
55
+ end
56
+
57
+ class Decryptor
58
+ def initialize: (base64_encoded private_key) -> void
59
+
60
+ def to_s: () -> base64_encoded
61
+
62
+ def public_key: () -> base64_encoded
63
+
64
+ def encryptor: () -> Encryptor
65
+
66
+ def decrypt: (base64_encoded ciphertext) -> String
67
+ end
68
+ end
69
+
70
+ class Store
71
+ class Decrypt
72
+ attr_reader public_key: base64_encoded
73
+ attr_reader ciphertext: base64_encoded
74
+
75
+ def self.new: (base64_encoded public_key, base64_encoded ciphertext) -> Decrypt
76
+ end
77
+
78
+ class Encrypt
79
+ attr_reader public_key: base64_encoded
80
+ attr_reader plaintext: String
81
+
82
+ def self.new: (base64_encoded public_key, String plaintext) -> Encrypt
83
+ end
84
+
85
+ def initialize: (Hash[String, untyped] hash, ?public_key: base64_encoded?) { (Store::Decrypt | Store::Encrypt) -> String } -> void
86
+
87
+ def key?: (String key) -> bool
88
+
89
+ def each: (?path: Array[String]) { (Array[String], untyped, Store) -> void } -> void
90
+
91
+ def to_h: () -> Hash[String, untyped]
92
+
93
+ def resolve: (String key) -> (String | Store | untyped)
94
+
95
+ def to_yaml: (*untyped) -> String
96
+
97
+ private
98
+
99
+ def assign: (String key, untyped value) -> void
100
+
101
+ def decrypt: (Encrypted encrypted) -> String
102
+
103
+ def child_scope: (Hash[String, untyped] hash) -> Store
104
+
105
+ def find_public_key: (Hash[String, untyped] hash) -> PublicKey?
106
+ end
107
+
108
+ module YAML
109
+ def self.register: () -> void
110
+ end
111
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: valvet
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kim Burgestrand
8
+ - Varvet
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 1980-01-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: base64
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rbnacl
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: zeitwerk
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Keep secrets in your config files. Valvet encrypts sensitive values while
56
+ leaving everything else readable, so you can check the whole file into version control.
57
+ Uses NaCl sealed boxes via RbNaCl.
58
+ email:
59
+ - kim@burgestrand.se
60
+ executables:
61
+ - valvet
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - CHANGELOG.md
66
+ - CODE_OF_CONDUCT.md
67
+ - LICENSE.txt
68
+ - README.md
69
+ - Rakefile
70
+ - exe/valvet
71
+ - lib/valvet.rb
72
+ - lib/valvet/cli.rb
73
+ - lib/valvet/crypto.rb
74
+ - lib/valvet/encrypted.rb
75
+ - lib/valvet/error.rb
76
+ - lib/valvet/public_key.rb
77
+ - lib/valvet/rails.rb
78
+ - lib/valvet/store.rb
79
+ - lib/valvet/version.rb
80
+ - lib/valvet/yaml.rb
81
+ - log/test.log
82
+ - sig/valvet.rbs
83
+ homepage: https://github.com/varvet/valvet
84
+ licenses:
85
+ - MIT
86
+ metadata:
87
+ allowed_push_host: https://rubygems.org
88
+ homepage_uri: https://github.com/varvet/valvet
89
+ source_code_uri: https://github.com/varvet/valvet
90
+ changelog_uri: https://github.com/varvet/valvet/blob/main/CHANGELOG.md
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: 3.2.0
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubygems_version: 4.0.3
106
+ specification_version: 4
107
+ summary: Encrypt secrets in your config files using asymmetric encryption
108
+ test_files: []