Class: LocalVault::SyncState

Inherits:
Object
  • Object
show all
Defined in:
lib/localvault/sync_state.rb

Overview

Per-vault sync state tracking. Stores the checksum of secrets.enc at the time of the last successful push or pull, so the next ‘localvault sync` can determine whether local, remote, or both sides have changed.

Stored as ‘~/.localvault/vaults/<name>/.sync_state` (YAML, mode 0600). Separate from meta.yml because meta.yml is part of the SyncBundle and including sync bookkeeping there would create a checksum feedback loop.

Constant Summary collapse

FILENAME =
".sync_state"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(vault_name) ⇒ SyncState

Returns a new instance of SyncState.



18
19
20
# File 'lib/localvault/sync_state.rb', line 18

def initialize(vault_name)
  @vault_name = vault_name
end

Instance Attribute Details

#vault_nameObject (readonly)

Returns the value of attribute vault_name.



16
17
18
# File 'lib/localvault/sync_state.rb', line 16

def vault_name
  @vault_name
end

Class Method Details

.local_checksum(store) ⇒ String?

Compute the SHA256 hex digest of a vault’s local secrets.enc.

Parameters:

  • store (Store)

    vault store

Returns:

  • (String, nil)

    hex digest or nil if no secrets file



65
66
67
68
69
# File 'lib/localvault/sync_state.rb', line 65

def self.local_checksum(store)
  bytes = store.read_encrypted
  return nil if bytes.nil? || bytes.empty?
  Digest::SHA256.hexdigest(bytes)
end

Instance Method Details

#exists?Boolean

Returns:

  • (Boolean)


26
27
28
# File 'lib/localvault/sync_state.rb', line 26

def exists?
  File.exist?(path)
end

#last_synced_atObject



42
43
44
# File 'lib/localvault/sync_state.rb', line 42

def last_synced_at
  read&.dig("last_synced_at")
end

#last_synced_checksumObject



38
39
40
# File 'lib/localvault/sync_state.rb', line 38

def last_synced_checksum
  read&.dig("last_synced_checksum")
end

#pathObject



22
23
24
# File 'lib/localvault/sync_state.rb', line 22

def path
  File.join(Config.vaults_path, vault_name, FILENAME)
end

#readHash?

Returns parsed YAML data or nil.

Returns:

  • (Hash, nil)

    parsed YAML data or nil



31
32
33
34
35
36
# File 'lib/localvault/sync_state.rb', line 31

def read
  return nil unless exists?
  YAML.safe_load_file(path)
rescue Psych::SyntaxError
  nil
end

#write!(checksum:, direction:) ⇒ Object

Record a successful sync operation.

Parameters:

  • checksum (String)

    SHA256 hex of the local secrets.enc

  • direction (String)

    “push” or “pull”



50
51
52
53
54
55
56
57
58
59
# File 'lib/localvault/sync_state.rb', line 50

def write!(checksum:, direction:)
  FileUtils.mkdir_p(File.dirname(path), mode: 0o700)
  data = {
    "last_synced_checksum" => checksum,
    "last_synced_at"       => Time.now.utc.iso8601,
    "direction"            => direction
  }
  File.write(path, YAML.dump(data))
  File.chmod(0o600, path)
end