localvault 1.3.2 → 1.3.3
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 +4 -4
- data/lib/localvault/cli/keys.rb +2 -2
- data/lib/localvault/cli/team.rb +4 -10
- data/lib/localvault/cli/team_helpers.rb +33 -5
- data/lib/localvault/cli.rb +8 -18
- data/lib/localvault/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ca1ee7041877b10f5964e4fc74e7edf9365f4a7e34d283c624c15bd45ab32c98
|
|
4
|
+
data.tar.gz: 59a54ac2d1591cbc6d5910f9222c3c89039edc4d89e45f50dc3fd09aa7720a29
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: db6ebd7b3e0371faa96ea772f28f8fb6447e03fe7184a596bccccdc8251d32ab9ee7a777ae1d772d985f9ed68f991fb6c2eaba988aded97fc710f2994f6aab7f
|
|
7
|
+
data.tar.gz: 93286e65a351b4995a438870782c147ae86c227bbe2f307080b76c39eeaa96dfa852f133821dfdc28466329529a2e540d1a0c8738ef26f421b22e1e156361797
|
data/lib/localvault/cli/keys.rb
CHANGED
|
@@ -32,7 +32,7 @@ module LocalVault
|
|
|
32
32
|
# Publish your X25519 public key to InventList.
|
|
33
33
|
#
|
|
34
34
|
# Requires a keypair (run +localvault keys generate+ first) and an active
|
|
35
|
-
#
|
|
35
|
+
# login session (run +localvault login+ first). Once published, other users
|
|
36
36
|
# can share vaults with you.
|
|
37
37
|
def publish
|
|
38
38
|
unless Identity.exists?
|
|
@@ -41,7 +41,7 @@ module LocalVault
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
unless Config.token
|
|
44
|
-
$stderr.puts "Error: Not
|
|
44
|
+
$stderr.puts "Error: Not logged in. Run: localvault login"
|
|
45
45
|
return
|
|
46
46
|
end
|
|
47
47
|
|
data/lib/localvault/cli/team.rb
CHANGED
|
@@ -31,11 +31,8 @@ module LocalVault
|
|
|
31
31
|
vault_name ||= options[:vault] || Config.default_vault
|
|
32
32
|
handle = Config.inventlist_handle
|
|
33
33
|
|
|
34
|
-
master_key =
|
|
35
|
-
unless master_key
|
|
36
|
-
$stderr.puts "Error: Vault '#{vault_name}' is not unlocked. Run: localvault unlock -v #{vault_name}"
|
|
37
|
-
return
|
|
38
|
-
end
|
|
34
|
+
master_key = ensure_master_key(vault_name)
|
|
35
|
+
return unless master_key
|
|
39
36
|
|
|
40
37
|
client = ApiClient.new(token: Config.token)
|
|
41
38
|
begin
|
|
@@ -171,11 +168,8 @@ module LocalVault
|
|
|
171
168
|
key_slots = team_data[:key_slots]
|
|
172
169
|
vault_owner = team_data[:owner]
|
|
173
170
|
|
|
174
|
-
master_key =
|
|
175
|
-
unless master_key
|
|
176
|
-
$stderr.puts "Error: Vault '#{vault_name}' is not unlocked."
|
|
177
|
-
return
|
|
178
|
-
end
|
|
171
|
+
master_key = ensure_master_key(vault_name)
|
|
172
|
+
return unless master_key
|
|
179
173
|
|
|
180
174
|
passphrase = prompt_passphrase("New passphrase for vault '#{vault_name}': ")
|
|
181
175
|
if passphrase.nil? || passphrase.empty?
|
|
@@ -10,6 +10,37 @@ module LocalVault
|
|
|
10
10
|
module TeamHelpers
|
|
11
11
|
private
|
|
12
12
|
|
|
13
|
+
# Return the master key for +vault_name+, prompting for the passphrase
|
|
14
|
+
# if the vault isn't already cached in the session. Returns +nil+ and
|
|
15
|
+
# emits an error if the vault doesn't exist or the passphrase is wrong.
|
|
16
|
+
#
|
|
17
|
+
# This is what lets team init / rotate / add / remove "just work"
|
|
18
|
+
# without a separate `localvault unlock` step. Delegates to
|
|
19
|
+
# +Vault.open+ (the canonical passphrase-to-vault constructor) and
|
|
20
|
+
# verifies the passphrase by calling +vault.all+ — +Vault.open+ alone
|
|
21
|
+
# doesn't verify, it just derives the key.
|
|
22
|
+
def ensure_master_key(vault_name)
|
|
23
|
+
if (cached = SessionCache.get(vault_name))
|
|
24
|
+
return cached
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
unless Store.new(vault_name).exists?
|
|
28
|
+
$stderr.puts "Error: Vault '#{vault_name}' does not exist. Run: localvault init #{vault_name}"
|
|
29
|
+
return nil
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
passphrase = prompt_passphrase("Passphrase for '#{vault_name}': ")
|
|
33
|
+
return nil if passphrase.nil? || passphrase.empty?
|
|
34
|
+
|
|
35
|
+
vault = Vault.open(name: vault_name, passphrase: passphrase)
|
|
36
|
+
vault.all # raises Crypto::DecryptionError on wrong passphrase
|
|
37
|
+
SessionCache.set(vault_name, vault.master_key)
|
|
38
|
+
vault.master_key
|
|
39
|
+
rescue Crypto::DecryptionError
|
|
40
|
+
$stderr.puts "Error: Wrong passphrase for vault '#{vault_name}'."
|
|
41
|
+
nil
|
|
42
|
+
end
|
|
43
|
+
|
|
13
44
|
def load_key_slots(client, vault_name)
|
|
14
45
|
data = load_team_data(client, vault_name)
|
|
15
46
|
data ? data[:key_slots] : nil
|
|
@@ -107,11 +138,8 @@ module LocalVault
|
|
|
107
138
|
key_slots.delete(handle)
|
|
108
139
|
|
|
109
140
|
if rotate
|
|
110
|
-
master_key =
|
|
111
|
-
unless master_key
|
|
112
|
-
$stderr.puts "Error: Vault '#{vault_name}' is not unlocked. Run: localvault show -v #{vault_name}"
|
|
113
|
-
return
|
|
114
|
-
end
|
|
141
|
+
master_key = ensure_master_key(vault_name)
|
|
142
|
+
return unless master_key
|
|
115
143
|
|
|
116
144
|
# Prompt for new passphrase
|
|
117
145
|
passphrase = prompt_passphrase("New passphrase for vault '#{vault_name}': ")
|
data/lib/localvault/cli.rb
CHANGED
|
@@ -59,6 +59,12 @@ module LocalVault
|
|
|
59
59
|
shell.say " localvault install-mcp Configure MCP server in your AI tool"
|
|
60
60
|
shell.say " localvault mcp Start MCP server (stdio)"
|
|
61
61
|
shell.say ""
|
|
62
|
+
shell.say "LEGACY SHARING (pre-v1.2 direct share, still works as fallback)"
|
|
63
|
+
shell.say " localvault keygen Generate X25519 keypair (same as `keys generate`)"
|
|
64
|
+
shell.say " localvault share [VAULT] Share a vault with a user, team, or crew (one-shot copy)"
|
|
65
|
+
shell.say " localvault receive Fetch and import vaults shared with you"
|
|
66
|
+
shell.say " localvault revoke SHARE_ID Revoke a direct vault share"
|
|
67
|
+
shell.say ""
|
|
62
68
|
shell.say "OTHER"
|
|
63
69
|
shell.say " localvault login --status Show current login status"
|
|
64
70
|
shell.say " localvault logout Log out"
|
|
@@ -598,19 +604,6 @@ module LocalVault
|
|
|
598
604
|
$stdout.puts "Logged out#{" @#{handle}" if handle}."
|
|
599
605
|
end
|
|
600
606
|
|
|
601
|
-
desc "connect", "Connect to InventList for vault sharing"
|
|
602
|
-
method_option :token, required: true, type: :string, desc: "InventList API token"
|
|
603
|
-
method_option :handle, required: true, type: :string, desc: "Your InventList handle"
|
|
604
|
-
def connect
|
|
605
|
-
Config.token = options[:token]
|
|
606
|
-
Config.inventlist_handle = options[:handle]
|
|
607
|
-
$stdout.puts "Connected as @#{options[:handle]}"
|
|
608
|
-
$stdout.puts
|
|
609
|
-
$stdout.puts "Next steps:"
|
|
610
|
-
$stdout.puts " localvault keys generate # generate your X25519 keypair"
|
|
611
|
-
$stdout.puts " localvault keys publish # upload your public key to InventList"
|
|
612
|
-
end
|
|
613
|
-
|
|
614
607
|
desc "share [VAULT]", "Share a vault with an InventList user, team, or crew"
|
|
615
608
|
method_option :with, required: true, type: :string,
|
|
616
609
|
desc: "Recipient: @handle, team:HANDLE, or crew:SLUG"
|
|
@@ -803,11 +796,8 @@ module LocalVault
|
|
|
803
796
|
vault_name = options[:vault] || Config.default_vault
|
|
804
797
|
scope_list = options[:scope]
|
|
805
798
|
|
|
806
|
-
master_key =
|
|
807
|
-
unless master_key
|
|
808
|
-
$stderr.puts "Error: Vault '#{vault_name}' is not unlocked. Run: localvault show -v #{vault_name}"
|
|
809
|
-
return
|
|
810
|
-
end
|
|
799
|
+
master_key = ensure_master_key(vault_name)
|
|
800
|
+
return unless master_key
|
|
811
801
|
|
|
812
802
|
client = ApiClient.new(token: Config.token)
|
|
813
803
|
|
data/lib/localvault/version.rb
CHANGED