kbsecret 1.2.0 → 1.3.0.pre.1

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -5
  3. data/bin/kbsecret +6 -14
  4. data/lib/kbsecret/cli/command/abstract.rb +51 -0
  5. data/lib/kbsecret/cli/command/conf.rb +42 -0
  6. data/lib/kbsecret/cli/command/cp.rb +54 -0
  7. data/lib/kbsecret/cli/command/dump_fields.rb +53 -0
  8. data/lib/kbsecret/cli/command/env.rb +66 -0
  9. data/lib/kbsecret/cli/command/generator.rb +62 -0
  10. data/lib/kbsecret/cli/command/generators.rb +37 -0
  11. data/lib/kbsecret/cli/command/list.rb +48 -0
  12. data/lib/kbsecret/cli/command/login.rb +66 -0
  13. data/lib/kbsecret/cli/command/new.rb +82 -0
  14. data/lib/kbsecret/cli/command/pass.rb +51 -0
  15. data/lib/kbsecret/cli/command/raw_edit.rb +46 -0
  16. data/lib/kbsecret/cli/command/rm.rb +58 -0
  17. data/lib/kbsecret/cli/command/session.rb +128 -0
  18. data/lib/kbsecret/cli/command/sessions.rb +47 -0
  19. data/lib/kbsecret/cli/command/stash_file.rb +62 -0
  20. data/lib/kbsecret/cli/command/todo.rb +78 -0
  21. data/lib/kbsecret/cli/command.rb +45 -0
  22. data/lib/kbsecret/cli.rb +6 -4
  23. data/lib/kbsecret/config.rb +4 -3
  24. data/lib/kbsecret/record/abstract.rb +2 -2
  25. data/lib/kbsecret/record.rb +9 -7
  26. data/lib/kbsecret/version.rb +1 -1
  27. metadata +22 -20
  28. data/lib/kbsecret/cli/kbsecret-conf +0 -31
  29. data/lib/kbsecret/cli/kbsecret-cp +0 -44
  30. data/lib/kbsecret/cli/kbsecret-dump-fields +0 -39
  31. data/lib/kbsecret/cli/kbsecret-env +0 -53
  32. data/lib/kbsecret/cli/kbsecret-generator +0 -42
  33. data/lib/kbsecret/cli/kbsecret-generators +0 -28
  34. data/lib/kbsecret/cli/kbsecret-list +0 -36
  35. data/lib/kbsecret/cli/kbsecret-login +0 -53
  36. data/lib/kbsecret/cli/kbsecret-new +0 -68
  37. data/lib/kbsecret/cli/kbsecret-pass +0 -37
  38. data/lib/kbsecret/cli/kbsecret-raw-edit +0 -31
  39. data/lib/kbsecret/cli/kbsecret-rm +0 -44
  40. data/lib/kbsecret/cli/kbsecret-session +0 -105
  41. data/lib/kbsecret/cli/kbsecret-sessions +0 -38
  42. data/lib/kbsecret/cli/kbsecret-stash-file +0 -48
  43. data/lib/kbsecret/cli/kbsecret-todo +0 -47
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "clipboard"
4
+
5
+ module KBSecret
6
+ class CLI
7
+ module Command
8
+ # The implementation of `kbsecret pass`.
9
+ class Pass < Abstract
10
+ def initialize(argv)
11
+ super(argv) do |cli|
12
+ cli.slop do |o|
13
+ o.banner = <<~HELP
14
+ Usage:
15
+ kbsecret pass [options] <record>
16
+ HELP
17
+
18
+ o.string "-s", "--session", "the session to search in", default: :default
19
+ o.bool "-c", "--clipboard", "dump the password in the clipboard"
20
+ end
21
+
22
+ cli.dreck do
23
+ string :label
24
+ end
25
+
26
+ cli.ensure_session!
27
+ end
28
+ end
29
+
30
+ # @see Command::Abstract#setup!
31
+ def setup!
32
+ @record = cli.session[cli.args[:label]]
33
+ end
34
+
35
+ # @see Command::Abstract#validate!
36
+ def validate!
37
+ cli.die "No such login record." unless @record && @record.type == :login
38
+ end
39
+
40
+ # @see Command::Abstract#run!
41
+ def run!
42
+ if cli.opts.clipboard?
43
+ Clipboard.copy @record.password
44
+ else
45
+ puts @record.password
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KBSecret
4
+ class CLI
5
+ module Command
6
+ # The implementation of `kbsecret raw-edit`.
7
+ class RawEdit < Abstract
8
+ def initialize(argv)
9
+ super(argv) do |cli|
10
+ cli.slop do |o|
11
+ o.banner = <<~HELP
12
+ Usage:
13
+ kbsecret raw-edit [options] <record>
14
+ HELP
15
+
16
+ o.string "-s", "--session", "the session to search in", default: :default
17
+ end
18
+
19
+ cli.dreck do
20
+ string :label
21
+ end
22
+
23
+ cli.ensure_session!
24
+ end
25
+ end
26
+
27
+ # @see Command::Abstract#setup!
28
+ def setup!
29
+ @record = cli.session[cli.args[:label]]
30
+ end
31
+
32
+ # @see Command::Abstract#validate!
33
+ def validate!
34
+ cli.die "Missing $EDITOR." unless ENV["EDITOR"]
35
+ cli.die "No such record." unless @record
36
+ end
37
+
38
+ # @see Command::Abstract#run!
39
+ def run!
40
+ Process.spawn("#{ENV["EDITOR"]} #{@record.path}")
41
+ @record.sync! # just to bump the timestamp
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tty-prompt"
4
+
5
+ module KBSecret
6
+ class CLI
7
+ module Command
8
+ # The implementation of `kbsecret rm`.
9
+ class Rm < Abstract
10
+ def initialize(argv)
11
+ super(argv) do |cli|
12
+ cli.slop do |o|
13
+ o.banner = <<~HELP
14
+ Usage:
15
+ kbsecret rm [options] <record [record ...]>
16
+ HELP
17
+
18
+ o.string "-s", "--session", "the session containing the record", default: :default
19
+ o.bool "-i", "--interactive", "ask for confirmation before deleting"
20
+ end
21
+
22
+ cli.dreck do
23
+ list :string, :labels
24
+ end
25
+
26
+ cli.ensure_session!
27
+ end
28
+ end
29
+
30
+ # @see Command::Abstract#setup!
31
+ def setup!
32
+ @selected_records = cli.session.records.select do |record|
33
+ cli.args[:labels].include? record.label
34
+ end
35
+ end
36
+
37
+ # @see Command::Abstract#validate!
38
+ def validate!
39
+ cli.die "No such record(s)." if @selected_records.empty?
40
+ end
41
+
42
+ # @see Command::Abstract#run!
43
+ def run!
44
+ $VERBOSE = nil # tty-prompt blasts us with irrelevant warnings on 2.4
45
+
46
+ tty = TTY::Prompt.new
47
+
48
+ confirm = if cli.opts.interactive?
49
+ tty.yes?("Delete '#{selected_records.join(", ")}'?")
50
+ else true
51
+ end
52
+
53
+ @selected_records.each { |r| cli.session.delete_record(r.label) } if confirm
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KBSecret
4
+ class CLI
5
+ module Command
6
+ # The implementation of `kbsecret session`.
7
+ class Session < Abstract
8
+ # The list of subcommands supported by `kbsecret session`.
9
+ SUBCOMMANDS = %w[new rm].freeze
10
+
11
+ def initialize(argv)
12
+ super(argv) do |cli|
13
+ cli.slop cmds: SUBCOMMANDS do |o|
14
+ o.banner = <<~HELP
15
+ Usage:
16
+ kbsecret session [options] <new|rm> <label>
17
+ HELP
18
+
19
+ o.string "-t", "--team", "the team to create the session under"
20
+ o.array "-u", "--users", "the Keybase users", default: [Keybase::Local.current_user]
21
+ o.string "-r", "--root", "the secret root directory"
22
+ o.bool "-c", "--create-team", "create the Keybase team if it does not exist"
23
+ o.bool "-f", "--force", "force creation (ignore overwrites, etc.)"
24
+ o.bool "-n", "--no-notify", "do not send a notification to session members"
25
+ o.bool "-d", "--delete", "unlink the session in addition to deconfiguration"
26
+ end
27
+
28
+ cli.dreck do
29
+ string :command
30
+ string :session
31
+ end
32
+
33
+ cli.ensure_session! :argument if cli.args[:command] == "rm"
34
+ end
35
+ end
36
+
37
+ # @see Command::Abstract#setup!
38
+ def setup!
39
+ @label = cli.args[:session]
40
+ @subcmd = cli.args[:command]
41
+ end
42
+
43
+ # @see Command::Abstract#validate!
44
+ def validate!
45
+ cli.die "Unknown subcommand: #{@subcmd}." unless SUBCOMMANDS.include?(@subcmd)
46
+ end
47
+
48
+ # @see Command::Abstract#run!
49
+ def run!
50
+ case @subcmd
51
+ when "new"
52
+ new_session
53
+ when "rm"
54
+ rm_session
55
+ end
56
+ end
57
+
58
+ # @api private
59
+ # @return [void]
60
+ def new_session
61
+ if Config.session?(@label) && !cli.opts.force?
62
+ cli.die "Refusing to overwrite a session without --force."
63
+ end
64
+
65
+ if cli.opts[:team]
66
+ teams = Keybase::Local::Team.list_self_memberships.teams
67
+
68
+ unless teams.map(&:fq_name).include?(cli.opts[:team])
69
+ if cli.opts.create_team?
70
+ cli.guard do
71
+ Keybase::Local::Team.create_team cli.opts[:team]
72
+ Keybase::Local::Team.add_members cli.opts[:team], users: [{
73
+ username: Keybase::Local.current_user,
74
+ role: "admin",
75
+ }]
76
+ end
77
+ else
78
+ cli.die "No such team (either nonexistent or non-member)."
79
+ end
80
+ end
81
+
82
+ Config.configure_session(@label, team: cli.opts[:team], root: @label)
83
+ else
84
+ cli.die "Missing `-r', `--root' option." unless cli.opts[:root]
85
+
86
+ cli.opts[:users].each do |user|
87
+ cli.die "Nonexistent Keybase user: #{user}." unless Keybase::API.user? user
88
+ end
89
+
90
+ unless cli.opts[:users].include? Keybase::Local.current_user
91
+ cli.warn "You didn't include yourself in the user list, but I'll add you."
92
+ cli.opts[:users] << Keybase::Local.current_user
93
+ end
94
+
95
+ Config.configure_session(@label, users: cli.opts[:users], root: cli.opts[:root])
96
+
97
+ unless cli.opts.no_notify? && cli.opts[:users] != [Keybase::Local.current_user]
98
+ users = cli.opts[:users].join(",")
99
+
100
+ Keybase::Local::Chat.send_message cli.opts[:users], <<~MESSAGE
101
+ You've been added to a KBSecret session!
102
+
103
+ To access this session, please run the following:
104
+
105
+ ```
106
+ $ kbsecret session new -r '#{cli.opts[:root]}' -u #{users} <label>
107
+ ```
108
+
109
+ If you don't have KBSecret installed, you can install it from `gem`:
110
+
111
+ ```
112
+ $ gem install kbsecret
113
+ ```
114
+ MESSAGE
115
+ end
116
+ end
117
+ end
118
+
119
+ # @api private
120
+ # @return [void]
121
+ def rm_session
122
+ cli.session.unlink! if cli.opts.delete?
123
+ Config.deconfigure_session @label
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KBSecret
4
+ class CLI
5
+ module Command
6
+ # The implementation of `kbsecret sessions`.
7
+ class Sessions < Abstract
8
+ def initialize(argv)
9
+ super(argv) do |cli|
10
+ cli.slop do |o|
11
+ o.banner = <<~HELP
12
+ Usage:
13
+ kbsecret sessions [options]
14
+ HELP
15
+
16
+ o.bool "-a", "--show-all", "show each session in depth (i.e. metadata)"
17
+ end
18
+ end
19
+ end
20
+
21
+ # @see Command::Abstract#run!
22
+ def run!
23
+ Config.session_labels.each do |sess_name|
24
+ session_hash = Config.session(sess_name)
25
+ session = cli.guard { Session[sess_name] }
26
+
27
+ puts sess_name
28
+
29
+ next unless cli.opts.show_all?
30
+
31
+ if session_hash[:team]
32
+ puts <<~DETAIL
33
+ \tTeam: #{session_hash[:team]}
34
+ \tSecrets root: #{session_hash[:root]} (#{session.path})
35
+ DETAIL
36
+ else
37
+ puts <<~DETAIL
38
+ \tUsers: #{session_hash[:users].join(", ")}
39
+ \tSecrets root: #{session_hash[:root]} (#{session.path})
40
+ DETAIL
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "base64"
4
+
5
+ module KBSecret
6
+ class CLI
7
+ module Command
8
+ # The implementation of `kbsecret stash-file`.
9
+ class StashFile < Abstract
10
+ def initialize(argv)
11
+ super(argv) do |cli|
12
+ cli.slop do |o|
13
+ o.banner = <<~HELP
14
+ Usage:
15
+ kbsecret stash-file <record> [file]
16
+ HELP
17
+
18
+ o.string "-s", "--session", "the session to add to", default: :default
19
+ o.bool "-f", "--force", "force creation (ignore overwrites, etc.)"
20
+ o.bool "-b", "--base64", "encode the file as base64"
21
+ end
22
+
23
+ cli.dreck do
24
+ string :label
25
+ string :filename
26
+ end
27
+
28
+ cli.ensure_session!
29
+ end
30
+ end
31
+
32
+ # @see Command::Abstract#setup!
33
+ def setup!
34
+ @label = cli.args[:label]
35
+ @filename = cli.args[:filename]
36
+ end
37
+
38
+ # @see Command::Abstract#validate!
39
+ def validate!
40
+ if cli.session.record?(@label) && !cli.opts.force?
41
+ cli.die "Refusing to overwrite a record without --force."
42
+ end
43
+
44
+ cli.die "No such file." unless File.file?(@filename) || @filename == "-"
45
+ end
46
+
47
+ # @see Command::Abstract#run!
48
+ def run!
49
+ contents = if @filename == "-"
50
+ STDIN.read
51
+ elsif File.file?(@filename)
52
+ File.read(@filename)
53
+ end
54
+
55
+ contents = Base64.encode64(contents) if cli.opts.base64?
56
+
57
+ cli.guard { cli.session.add_record(:unstructured, @label, contents) }
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KBSecret
4
+ class CLI
5
+ module Command
6
+ # The implementation of `kbsecret todo`.
7
+ class Todo < Abstract
8
+ # The list of subcommands supported by `kbsecret todo`.
9
+ SUBCOMMANDS = %w[start suspend complete].freeze
10
+
11
+ def initialize(argv)
12
+ super(argv) do |cli|
13
+ cli.slop cmds: SUBCOMMANDS do |o|
14
+ o.banner = <<~HELP
15
+ Usage:
16
+ kbsecret todo <start|suspend|complete> <record>
17
+ HELP
18
+
19
+ o.string "-s", "--session", "the session to search in", default: :default
20
+ end
21
+
22
+ cli.dreck do
23
+ string :command
24
+ string :label
25
+ end
26
+
27
+ cli.ensure_session!
28
+ end
29
+ end
30
+
31
+ # @see Command::Abstract#setup!
32
+ def setup!
33
+ @todo = cli.session[cli.args[:label]]
34
+ @subcmd = cli.args[:command]
35
+ end
36
+
37
+ # @see Command::Abstract#validate!
38
+ def validate!
39
+ cli.die "No such todo record:." unless @todo && @todo.type == :todo
40
+ cli.die "Unknown subcommand: #{@subcmd}." unless SUBCOMMANDS.include?(@subcmd)
41
+ end
42
+
43
+ # @see Command::Abstract#setup!
44
+ def run!
45
+ case @subcmd
46
+ when "start" then start_todo
47
+ when "suspend" then suspend_todo
48
+ when "complete" then complete_todo
49
+ end
50
+ end
51
+
52
+ # Starts the todo associated with the current invocation, unless already started.
53
+ # @return [void]
54
+ def start_todo
55
+ cli.die "That task is already started!" if @todo.started?
56
+ @todo.start!
57
+ puts "#{@todo.label}: '#{@todo.todo}' marked as started at #{@todo.start}"
58
+ end
59
+
60
+ # Suspends the todo associated with the current invocation, unless already suspended.
61
+ # @return [void]
62
+ def suspend_todo
63
+ cli.die "That task is already suspended!" if @todo.suspended?
64
+ @todo.suspend!
65
+ puts "#{@todo.label}: '#{@todo.todo}' marked as suspended at #{@todo.stop}"
66
+ end
67
+
68
+ # Completes the todo associated with the current invocation, unless already completed.
69
+ # @return [void]
70
+ def complete_todo
71
+ cli.die "That task is already completed!" if @todo.completed?
72
+ @todo.complete!
73
+ puts "#{@todo.label}: '#{@todo.todo}' marked as completed at #{@todo.stop}"
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ # we have to require abstract first because ruby's module resolution is bad
4
+ require_relative "command/abstract"
5
+ Dir[File.join(__dir__, "command/*.rb")].each { |t| require_relative t }
6
+
7
+ module KBSecret
8
+ class CLI
9
+ # The namespace for {KBSecret}'s internal commands.
10
+ module Command
11
+ module_function
12
+
13
+ # @return [Array<Class>] the class objects of all non-abstract commands
14
+ def command_classes
15
+ klasses = constants.map(&Command.method(:const_get)).grep(Class)
16
+ klasses.delete(Command::Abstract)
17
+ klasses
18
+ end
19
+
20
+ # @return [Array<String>] the CLI-friendly names of all commands
21
+ def command_names
22
+ command_classes.map(&:command_name)
23
+ end
24
+
25
+ # @param command_name [String] the CLI-friendly name of the command
26
+ # @return [Class, nil] the command class corresponding to the given name, or `nil`
27
+ def command_for(command_name)
28
+ klass = command_classes.find { |c| c.command_name == command_name }
29
+ # TODO: raise here if nil?
30
+ klass
31
+ end
32
+
33
+ # @param command_name [String] the CLI-friendly name of the command to run
34
+ # @param args [Array<String>] the arguments, if any, to pass to the command
35
+ # @return [void]
36
+ def run!(command_name, *args)
37
+ klass = command_for command_name
38
+ cmd = klass.new(args)
39
+ cmd.setup!
40
+ cmd.validate!
41
+ cmd.run!
42
+ end
43
+ end
44
+ end
45
+ end
data/lib/kbsecret/cli.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "cli/command"
4
+
3
5
  require "slop"
4
6
  require "dreck"
5
7
  require "abbrev"
@@ -47,14 +49,14 @@ module KBSecret
47
49
  #
48
50
  # cmd.opts # => Slop::Result
49
51
  # cmd.args # => Dreck::Result
50
- def self.create(&block)
51
- CLI.new(&block)
52
+ def self.create(argv = ARGV, &block)
53
+ CLI.new(argv, &block)
52
54
  end
53
55
 
54
56
  # @api private
55
57
  # @deprecated see {create}
56
- def initialize
57
- @argv = ARGV.dup
58
+ def initialize(argv = ARGV)
59
+ @argv = argv.dup
58
60
  guard { yield self }
59
61
  end
60
62
 
@@ -65,7 +65,7 @@ module KBSecret
65
65
  # Writes the user's configuration to disk.
66
66
  # @return [void]
67
67
  def self.sync!
68
- File.open(CONFIG_FILE, "w") { |io| io.write @config.to_yaml }
68
+ File.write(CONFIG_FILE, @config.to_yaml)
69
69
  end
70
70
 
71
71
  # Retrieve a configured value.
@@ -167,8 +167,6 @@ module KBSecret
167
167
  user_config = if File.exist?(CONFIG_FILE)
168
168
  YAML.load_file(CONFIG_FILE)
169
169
  else
170
- FileUtils.mkdir_p CONFIG_DIR
171
- FileUtils.mkdir_p CUSTOM_TYPES_DIR
172
170
  DEFAULT_CONFIG
173
171
  end
174
172
 
@@ -182,6 +180,9 @@ module KBSecret
182
180
  @config[:sessions].merge!(DEFAULT_SESSION)
183
181
  @config[:generators].merge!(DEFAULT_GENERATOR)
184
182
 
183
+ FileUtils.mkdir_p CONFIG_DIR
184
+ FileUtils.mkdir_p CUSTOM_TYPES_DIR
185
+
185
186
  sync!
186
187
  end
187
188
  end
@@ -5,7 +5,7 @@ require "forwardable"
5
5
 
6
6
  module KBSecret
7
7
  module Record
8
- # Represents an abstract kbsecret record that can be subclassed to produce
8
+ # Represents an abstract {KBSecret} record that can be subclassed to produce
9
9
  # more useful records.
10
10
  # @abstract
11
11
  class Abstract
@@ -61,7 +61,7 @@ module KBSecret
61
61
  @timestamp = Time.now.to_i
62
62
  sync!
63
63
  end
64
- ]
64
+ ], __FILE__, __LINE__ - 10
65
65
  end
66
66
 
67
67
  # @param field [Symbol] the field's name
@@ -12,22 +12,24 @@ Dir[File.join(__dir__, "record/*.rb")].each { |t| require_relative t }
12
12
  module KBSecret
13
13
  # The namespace for {KBSecret} record types.
14
14
  module Record
15
+ module_function
16
+
15
17
  # @return [Array<Class>] the class objects of all non-abstract record types
16
- def self.record_classes
18
+ def record_classes
17
19
  klasses = constants.map(&Record.method(:const_get)).grep(Class)
18
20
  klasses.delete(Record::Abstract)
19
21
  klasses
20
22
  end
21
23
 
22
24
  # @return [Array<Symbol>] the types of all records
23
- def self.record_types
25
+ def record_types
24
26
  record_classes.map(&:type)
25
27
  end
26
28
 
27
29
  # @param type [String, Symbol] the record type
28
30
  # @return [Class] the record class corresponding to the given type
29
31
  # @raise [Exceptions::RecordTypeUnknownError] if the requested type is unknown
30
- def self.class_for(type)
32
+ def class_for(type)
31
33
  klass = record_classes.find { |c| c.type == type.to_sym }
32
34
  raise Exceptions::RecordTypeUnknownError, type unless klass
33
35
  klass
@@ -35,7 +37,7 @@ module KBSecret
35
37
 
36
38
  # @param type [String, Symbol] the record type
37
39
  # @return [Boolean] whether a record class exists of the given type
38
- def self.type?(type)
40
+ def type?(type)
39
41
  return false unless type
40
42
  record_types.include?(type.to_sym)
41
43
  end
@@ -46,11 +48,11 @@ module KBSecret
46
48
  # @return [Record::AbstractRecord] the loaded record
47
49
  # @raise [Exceptions::RecordLoadError] if an error occurs during record loading
48
50
  # @api private
49
- def self.load_record!(session, path)
51
+ def load_record!(session, path)
50
52
  hsh = JSON.parse(File.read(path), symbolize_names: true)
51
53
  klass = class_for hsh[:type]
52
- klass&.load!(session, hsh)
53
- rescue JSON::JSONError
54
+ klass.load!(session, hsh)
55
+ rescue Exceptions::RecordTypeUnknownError, JSON::JSONError
54
56
  raise Exceptions::RecordLoadError, path
55
57
  end
56
58
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module KBSecret
4
4
  # kbsecret's current version
5
- VERSION = "1.2.0"
5
+ VERSION = "1.3.0.pre.1"
6
6
  end