database

package
v0.0.0-...-871436d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: MIT Imports: 34 Imported by: 0

Documentation

Overview

Package database provides a pure-Go SQLite-backed credential store.

Index

Constants

View Source
const MaxSecretSize = 1 << 20 // 1 MiB

MaxSecretSize is the largest secret the store accepts. It applies however the store encrypts, so a secret that saves directly also saves through the agent, whose wire frames must carry it.

View Source
const VerifyPlaintext = "sesh-verify"

VerifyPlaintext is the known string sealed into the key record's verify blob. A successful open under the derived key proves the password.

Variables

View Source
var ErrDecrypt = errors.New("doesn't decrypt")

ErrDecrypt means a ciphertext doesn't decrypt with the key it was given: it's damaged, or was made with another key. Other errors (no key, a lost agent connection) are something else.

View Source
var ErrEntryChanged = errors.New("the entry was changed by another sesh command meanwhile; run this again")

ErrEntryChanged is an entry changed by another sesh command while an edit was re-sealing its secret.

View Source
var ErrNameTaken = errors.New("another entry has that name")

ErrNameTaken is an edit's new name being another entry's.

View Source
var ErrNoRecovery = errors.New("this vault has no recovery key")

ErrNoRecovery means the vault has no recovery key.

View Source
var ErrNoVault = errors.New("no vault yet")

ErrNoVault means there is no vault at the path yet, or one whose master password was never set: the next open creates it.

View Source
var ErrNoVersion = errors.New("no such version")

ErrNoVersion is a version number an entry's history doesn't have.

View Source
var ErrNotInTrash = errors.New("no entry in the trash has that id")

ErrNotInTrash is a trash id with no entry.

View Source
var ErrNothingToChange = errors.New("nothing to change")

ErrNothingToChange is an edit that would leave the entry as it is.

View Source
var ErrRecoveryChanged = errors.New("the vault's recovery key changed meanwhile")

ErrRecoveryChanged means the vault's recovery key record changed (another sesh command made or removed one) while a sync was taking the folder's: nothing was taken, and the next sync looks again.

View Source
var ErrRejoinOtherKey = errors.New("this vault synced with this folder before, but its master password, or the folder's, has changed since")

ErrRejoinOtherKey is a vault joining again the sync folder it synced with, but under another master password than the folder's now: one of them changed it since.

View Source
var ErrSecretTooLarge = errors.New("secret too large")

ErrSecretTooLarge is returned when a secret exceeds MaxSecretSize.

View Source
var ErrTryAnotherPassword = errors.New("choose a stronger master password")

ErrTryAnotherPassword is what a new-password check returns to have a different master password asked for.

View Source
var ErrVaultBusy = errors.New("another sesh command was using the vault")

ErrVaultBusy means another connection, such as another sesh command, was reading the vault for longer than Compact waits.

View Source
var ErrVaultKeyChanged = errors.New("the vault's master password was changed by another sesh command while this one ran; run this again")

ErrVaultKeyChanged means the vault's master password was changed after this command unlocked it: its key no longer opens the vault.

View Source
var ErrVaultNotEmpty = errors.New("this vault already has entries of its own, never synced with this folder")

ErrVaultNotEmpty is a vault that can't join a sync folder: it has entries, sealed with its own key (its own salt, even with the same master password).

View Source
var ErrVersionGone = errors.New("that earlier secret isn't in the history any more")

ErrVersionGone is a version, named by its row, that's no longer in the entry's history: another command forgot it, or dropped it to history.keep.

View Source
var ErrWrongPassword = errors.New("wrong master password")

ErrWrongPassword means every master password attempt failed.

Functions

func CanJoin

func CanJoin(dbPath string, m UnlockMaterial, folderID string) (rejoin bool, err error)

CanJoin says whether the vault at dbPath may join the sync folder folderID, whose vaults' key record is m: none there yet, an empty one, or one joining again the folder it synced with before, under its key (rejoin); ErrRejoinOtherKey for one that synced with it under another; ErrVaultNotEmpty for any other with entries, in the trash or in history. It changes nothing, so a command can check before asking for the master password.

func CheckFolderRename

func CheckFolderRename(from, to string) error

CheckFolderRename refuses renaming folder from to to without looking at the vault: a name either can't have, the same name, or a folder under from, which would move from into itself.

func CheckMasterPassword

func CheckMasterPassword(pw []byte, m UnlockMaterial) error

CheckMasterPassword says whether pw is the master password of the key record m, without a vault: an error when it isn't.

func CheckTagRename

func CheckTagRename(from, to string) error

CheckTagRename refuses renaming tag from to to without looking at the vault: a name either can't have, or the same name.

func CopyTo

func CopyTo(dbPath, dest string) (err error)

CopyTo writes a consistent copy of the vault at dbPath to dest, which must not exist: SQLite's VACUUM INTO, safe while other sesh commands use the vault. The copy holds what the vault does, secrets still encrypted, so making it needs no key. A vault SQLite's integrity check finds damaged is refused, so a damaged vault never replaces good backups. (The quick check doesn't compare indexes with their tables, and a personal vault is small enough for the full one.)

func Decrypt

func Decrypt(key, ciphertext []byte) ([]byte, error)

Decrypt decrypts ciphertext produced by Encrypt using AES-256-GCM. The key must be exactly 32 bytes.

func DecryptEntry

func DecryptEntry(masterKey, encryptedData, salt, aad []byte) ([]byte, error)

DecryptEntry decrypts data produced by EncryptEntry with the same aad.

func DefaultDBLocation

func DefaultDBLocation() (string, error)

DefaultDBLocation is DefaultDBPath without creating the directory, for showing the path without touching the filesystem.

func DefaultDBPath

func DefaultDBPath() (string, error)

DefaultDBPath returns the platform-appropriate path for the sesh database.

  • macOS: ~/Library/Application Support/sesh/passwords.db
  • Linux: $XDG_DATA_HOME/sesh/passwords.db (falls back to ~/.local/share/sesh/passwords.db; a relative $XDG_DATA_HOME is ignored per the XDG Base Directory spec)
  • Windows: %APPDATA%/sesh/passwords.db (falls back to ~/AppData/Roaming/sesh/passwords.db)

func DeriveKey

func DeriveKey(password, salt []byte, params Argon2idParams) []byte

DeriveKey uses Argon2id to derive an encryption key from a password and salt.

func Encrypt

func Encrypt(key, plaintext []byte) ([]byte, error)

Encrypt encrypts plaintext using AES-256-GCM with the provided key. The returned ciphertext is nonce || encrypted_data || tag. The key must be exactly 32 bytes; shorter keys are rejected rather than accepted as AES-128 or AES-192.

func EncryptEntry

func EncryptEntry(masterKey, plaintext, aad []byte) (encryptedData, salt []byte, err error)

EncryptEntry encrypts plaintext for storage, generating a per-entry salt and deriving a per-entry key from the master key material + salt. aad is authenticated but not encrypted: decrypting needs the same aad, which binds the ciphertext to what aad names (an entry's key). Returns (encryptedData, salt, error).

func GenerateSalt

func GenerateSalt(length int) ([]byte, error)

GenerateSalt produces a cryptographically random salt of the given length.

func IsDamaged

func IsDamaged(err error) bool

IsDamaged reports whether err shows the vault file is damaged: SQLite finding it corrupt or not a database, or a key record that fails its checks.

func JoinVault

func JoinVault(dbPath string, m UnlockMaterial, folderID string, links []syncfolder.KeyLink) (rejoin bool, err error)

JoinVault readies the vault at dbPath to join the sync folder folderID, whose vaults' key record is m, the master password already checked against it (CheckMasterPassword). A vault joining again the folder it synced with, under its key, is left as it is (rejoin): what it agreed with the folder before it left is kept, so what changed on both sides since merges as any change does. Any other with entries is refused (ErrVaultNotEmpty): with nothing agreed, it would bring back, as edits, entries deleted elsewhere. A new or empty vault gets m as its key record, so the same master password gives the same key; one that had another loses its recovery record, made for that key. Whatever it kept of an earlier sync (what it agreed, its sync ID, restored and forgotten marks) goes: it starts afresh.

links are the folder's key links, which a new or emptied vault takes.

func KeySealer

func KeySealer(key []byte) syncfolder.Sealer

KeySealer seals with key, held here.

func LinkProofHolds

func LinkProofHolds(old syncfolder.Sealer, l *syncfolder.KeyLink) bool

LinkProofHolds says whether l's proof opens with old, the sealer of the key l comes from: whether the change was made by a computer that had it.

func NewKeyLink(oldKey, newKey []byte, from, to string) (*syncfolder.KeyLink, error)

NewKeyLink is the master password change from oldKey, whose key record's ID is from, to newKey, whose is to.

func OpenKeyLink(sealer syncfolder.Sealer, l *syncfolder.KeyLink) ([]byte, error)

OpenKeyLink is the old key l holds, opened with sealer, the new key's. The caller zeroes it.

func RemoveRecovery

func RemoveRecovery(dbPath string) (err error)

RemoveRecovery removes the recovery key record of the vault at dbPath, if it has one.

func ReplaceVault

func ReplaceVault(dbPath, backupPath string, now time.Time) (aside string, err error)

ReplaceVault replaces the vault at dbPath, missing or damaged, with a copy of the backup at backupPath, which InspectBackup has passed. A vault there is moved aside, never deleted: to <vault>.before-restore-<time>, with its -wal and -shm, so what can still be read of it isn't lost, and its returned path says where. The -wal and -shm go with it rather than staying, where SQLite would apply them to the copy. A symlinked vault is replaced where it really is. No sesh command should be using the vault meanwhile. Once the copy is in place the restore stands: recording it only warns.

func RestoreInPlace

func RestoreInPlace(dbPath, backupPath string) error

RestoreInPlace replaces the sound vault at dbPath with the backup at backupPath, which InspectBackup has passed, in one transaction: every table but the audit log comes from the backup, and a "restore" event is added. A sesh command with the vault open never sees a half-restored vault, and one that unlocked it before is refused its next write if the key changed (ErrVaultKeyChanged). Once the transaction commits, the restore stands: tidying up after it only warns.

func UnionLinks(a, b []syncfolder.KeyLink) []syncfolder.KeyLink

UnionLinks are the links of a and b, each once (by the two key records it joins), a's first and kept over b's: callers give a vault's own, whose proofs were checked, before a folder's, where anyone can add one alongside the real one.

func UnlockID

func UnlockID(verify []byte) string

UnlockID names a vault's key record by its verify blob: the hex SHA-256 of it. The blob is stored in the vault, so the id is not a secret. A password change gives the vault a new one.

func ValidateUnlockMaterial

func ValidateUnlockMaterial(salt, verify []byte, params Argon2idParams) error

ValidateUnlockMaterial checks the fields an unlock derives from. The master-password source and the agent both call it, so they accept exactly the same material.

func VaultID

func VaultID(dbPath string) (_ string, err error)

VaultID returns the vault's id: random, made with it, and never changed. It reads the vault without writing to it.

func VaultKeyChange

func VaultKeyChange(dbPath string) (id string, err error)

VaultKeyChange is the vault at dbPath's SyncKeyChange, read without unlocking it: "" when there's no change to send, or no vault.

func VaultKeyLinks(dbPath string) (_ []syncfolder.KeyLink, err error)

VaultKeyLinks are the master password changes of the vault at dbPath, read without unlocking it; none when there's no vault.

func VaultSyncFolder

func VaultSyncFolder(dbPath string) (id string, err error)

VaultSyncFolder is the ID of the sync folder the vault at dbPath syncs with, or did before it left; "" when none, or there's no vault. It changes nothing.

func VerifiedLinks(key []byte, id string, links []syncfolder.KeyLink) []syncfolder.KeyLink

VerifiedLinks are those of links reached back from the key record id, whose key is key, each opening and its proof holding (NewCheckedOlderKeys).

func WriteRecovery

func WriteRecovery(dbPath string, r *RecoveryRecord) (err error)

WriteRecovery makes r the recovery key record of the vault at dbPath, replacing any earlier one. It refuses with ErrVaultKeyChanged when r was made for a key record the vault no longer has.

Types

type Argon2idParams

type Argon2idParams = kdf.Params

Argon2idParams are the Argon2id settings a vault's key record holds.

func DefaultArgon2idParams

func DefaultArgon2idParams() Argon2idParams

DefaultArgon2idParams returns the settings a new key record uses unless configured otherwise.

func UnmarshalArgon2idParams

func UnmarshalArgon2idParams(data string) (Argon2idParams, error)

UnmarshalArgon2idParams deserialises Argon2id parameters from JSON.

type AuditEntry

type AuditEntry struct {
	CreatedAt time.Time
	EventType string
	EntryID   string // nullable — empty for auth events
	Detail    string
	ID        int64
}

AuditEntry represents a row in the audit_log table.

type BackupSummary

type BackupSummary struct {
	VaultID string
	// Entries is how many entries the backup holds; Trashed, how many of
	// its entries are in the trash.
	Entries, Trashed int
}

BackupSummary is what InspectBackup found in a backup: whose it is, and how many entries it holds.

func InspectBackup

func InspectBackup(path string) (BackupSummary, error)

InspectBackup checks that the file at path is a sound sesh vault this build can restore: its schema is this build's, SQLite's integrity check passes, and it has a key record and an id. It never writes to the file.

func VaultSummary

func VaultSummary(dbPath string) (BackupSummary, error)

VaultSummary is InspectBackup for the vault itself, read only: its id and entries, or why it can't be read. A vault that's missing, or new (no key record and no entries), is ErrNoVault; a damaged one, IsDamaged.

type CryptoOracle

type CryptoOracle interface {
	// EncryptEntry seals plaintext under the master key and returns the
	// ciphertext plus the per-entry salt.
	EncryptEntry(plaintext, aad []byte) (encryptedData, salt []byte, err error)

	// DecryptEntry opens a blob produced by EncryptEntry.
	DecryptEntry(encryptedData, salt, aad []byte) ([]byte, error)
}

CryptoOracle encrypts and decrypts entry secrets without exposing the raw master key to the caller. Store depends only on this. The agent's key source implements it directly; a KeySource becomes one through NewKeySourceOracle.

func NewKeySourceOracle

func NewKeySourceOracle(ks KeySource) CryptoOracle

NewKeySourceOracle returns a CryptoOracle backed by ks. Closing the oracle closes ks when ks has a Close method.

type EntryEdit

type EntryEdit struct {
	To      *vault.Key
	Details *vault.DetailsChange
	Folder  *string
	Tags    *[]string
	TOTP    *totp.Params
	// FileName is a file entry's new file name, with its new content.
	FileName *string
	// AWSMFADevice is an AWS profile's entry's new MFA device (its ARN),
	// "" for none.
	AWSMFADevice *string
	Secret       []byte
}

EntryEdit is a change to an entry: To, its new key (nil keeps it); Secret, its new secret (nil keeps it; the caller zeroes it); Details, a change to its details (nil keeps them); Folder, the folder it's in after (nil keeps it, "" is none); Tags, all its tags after (nil keeps them); and TOTP, its code's settings after (nil keeps them).

type EntryProblem

type EntryProblem struct {
	Err  error
	Key  vault.Key
	Kind ProblemKind
	// TrashID is the entry's id in the trash, 0 for one that isn't.
	TrashID int64
	// Version is, for an earlier secret of a live entry's, its version
	// number (2 and up, as sesh history numbers them); 0 otherwise.
	Version int
}

EntryProblem is an entry Verify couldn't read: its secret or details don't decrypt, or its settings, times, or details don't parse.

type FolderCount

type FolderCount struct {
	Name           string
	Entries, Total int
}

FolderCount is a folder and how many entries it holds: Entries in it alone, Total with its subfolders'. Name "" counts the entries in no folder.

type ImportedHistory

type ImportedHistory struct {
	Kept, NoRoom, TooLarge int
}

ImportedHistory is what SaveImported did with an entry's earlier secrets, leaving out those the entry already had: how many it kept, and how many it didn't, for lack of room under history.keep or for being over MaxSecretSize.

type KeySource

type KeySource interface {
	// GetEncryptionKey returns the master encryption key.
	// The caller must zero the returned slice after use.
	GetEncryptionKey() ([]byte, error)
}

KeySource provides the master encryption key: MasterPasswordSource derives it from the master password.

type MasterPasswordSource

type MasterPasswordSource struct {
	// contains filtered or unexported fields
}

MasterPasswordSource derives the encryption key from a user-supplied passphrase via Argon2id, with the salt and settings in the vault's key record (vault_key.go).

func NewMasterPasswordSource

func NewMasterPasswordSource(dbPath string, prompt PasswordPromptFunc, opts ...Option) *MasterPasswordSource

NewMasterPasswordSource creates a MasterPasswordSource for the vault at dbPath, which must be absolute.

func (*MasterPasswordSource) Close

func (s *MasterPasswordSource) Close()

Close zeroes and releases the cached key. Safe to call multiple times and safe to call concurrently with GetEncryptionKey. Bumping cacheEpoch fences any in-flight derivation from re-populating the cache after Close returns.

func (*MasterPasswordSource) GetEncryptionKey

func (s *MasterPasswordSource) GetEncryptionKey() ([]byte, error)

GetEncryptionKey prompts for the master password and derives the encryption key. For a new vault it prompts twice for confirmation and creates the vault with its key record. Otherwise it checks the password against the key record's verify blob. The derived key is cached for the lifetime of this source so repeated Get/Set operations within one invocation do not re-prompt.

Per the KeySource contract the caller is free to zero the returned slice — the cache holds a private copy. Call Close() to clear the cached key when done.

func (*MasterPasswordSource) NewKey

func (s *MasterPasswordSource) NewKey() ([]byte, UnlockMaterial, error)

NewKey asks for a new master password, and returns the key it gives with a new salt and the key record for it, for a password change. Nothing is written. The caller zeroes the key.

func (*MasterPasswordSource) UnlockID

func (s *MasterPasswordSource) UnlockID() (string, error)

UnlockID is the id of the key record this source's key was checked against, unlocking first if it hasn't yet.

type OlderKeys

type OlderKeys struct {
	// contains filtered or unexported fields
}

OlderKeys are the keys a vault had before master password changes, reached through key links from a key whose sealer it has: every link whose new key is reached opens to its old one, whatever order or branch the changes came in. Opened when first asked for, and zeroed by Close.

func NewCheckedOlderKeys

func NewCheckedOlderKeys(sealer syncfolder.Sealer, id string, links []syncfolder.KeyLink) *OlderKeys

NewCheckedOlderKeys are NewOlderKeys taking only links whose proof holds with the key they open to: for links read from a sync folder, so each key reached is one a change was made from.

func NewOlderKeys

func NewOlderKeys(sealer syncfolder.Sealer, id string, links []syncfolder.KeyLink) *OlderKeys

NewOlderKeys are the keys reached back through links from the key record whose ID is id, which sealer opens with.

func (*OlderKeys) Close

func (o *OlderKeys) Close()

Close zeroes the keys opened.

func (*OlderKeys) Key

func (o *OlderKeys) Key(id string) []byte

Key is the older key whose key record's ID is id, nil when it isn't reached. It's zeroed by Close.

func (*OlderKeys) Sealer

func (o *OlderKeys) Sealer(id string) syncfolder.Sealer

Sealer is a sealer for the older key whose key record's ID is id, nil when it isn't reached.

func (*OlderKeys) Used

func (o *OlderKeys) Used() []syncfolder.KeyLink

Used are the links the walk opened (with NewCheckedOlderKeys, those whose proofs held), in the order given.

type Option

type Option func(*MasterPasswordSource)

Option configures a MasterPasswordSource. Use with NewMasterPasswordSource.

func WithKDFParams

func WithKDFParams(p Argon2idParams) Option

WithKDFParams sets the Argon2id settings a new key record gets (when the vault is created, or its master password changed); the default is kdf.Default(). Unlocking uses the settings the key record holds.

func WithMaxAttempts

func WithMaxAttempts(n int) Option

WithMaxAttempts sets the maximum number of password prompts the unlock loop will issue before giving up. Values < 1 are clamped to 1. Only wrong-password failures are retried; key record and I/O errors fail immediately.

The prompt callback must produce fresh user input on each invocation — a callback that returns a constant value (e.g., one backed by an env var) will derive the same wrong key N times and waste ~N × Argon2id cycles before failing. The CLI gates this via resolvePasswordPrompt in main.go, which only marks a prompt interactive when it actually reads fresh bytes; direct callers must apply the same discipline.

Only affects unlock(); first-run create+confirm always runs once.

func WithNewPasswordCheck

func WithNewPasswordCheck(check func(pw []byte) error) Option

WithNewPasswordCheck vets each new master password (at first run, or when a rotation or recovery sets a new one) before it's confirmed. Returning ErrTryAnotherPassword asks for another, up to newPasswordTries times; any other error stops creation. Unlocking never runs it.

type PasswordPromptFunc

type PasswordPromptFunc func(prompt string) ([]byte, error)

PasswordPromptFunc is called to obtain the master password from the user. Implementations should not echo the input.

type ProblemKind

type ProblemKind int

ProblemKind is what Verify couldn't read in an entry.

const (
	// ProblemSecret: the secret doesn't decrypt with the vault's key.
	ProblemSecret ProblemKind = iota + 1
	// ProblemSettings: the settings don't parse.
	ProblemSettings
	// ProblemTimes: the creation or update time doesn't read, or, in the
	// trash, when it was deleted.
	ProblemTimes
	// ProblemDetails: the notes and custom fields don't decrypt or read.
	ProblemDetails
	// ProblemTags: an entry in the trash's tags don't read.
	ProblemTags
)

The kinds of entry problem.

type RecoveryOutcome

type RecoveryOutcome int

RecoveryOutcome is what a password change did with the vault's recovery key record.

const (
	// RecoveryNone: the vault had no recovery key record.
	RecoveryNone RecoveryOutcome = iota
	// RecoveryKept: the record was re-wrapped to the new key.
	RecoveryKept
	// RecoveryRemoved: the record was removed, as a recovery asks.
	RecoveryRemoved
	// RecoveryStale: the record was for another vault, so it was removed.
	RecoveryStale
)

The outcomes.

type RecoveryRecord

type RecoveryRecord struct {
	CreatedAt time.Time
	// UnlockID is the id of the key record the wrap is bound to.
	UnlockID     string
	PublicKey    []byte
	EphemeralPub []byte
	Ciphertext   []byte
}

RecoveryRecord is what lets a recovery key open the vault: the recovery key's public key, and the vault key wrapped to it (internal/recovery). Nothing in it opens the vault without the written-down recovery key. A vault has at most one.

func ReadRecovery

func ReadRecovery(dbPath string) (_ *RecoveryRecord, err error)

ReadRecovery reads the recovery key record of the vault at dbPath: ErrNoRecovery when it has none, ErrNoVault when there's no vault there.

type RekeyOptions

type RekeyOptions struct {
	// Link is the change as a key link (NewKeyLink), kept with the vault's
	// others; nil when there's none to keep.
	Link *syncfolder.KeyLink
	// Links, with Sync RekeyAdopt, are the sync folder's links, which the
	// vault takes in place of its own.
	Links []syncfolder.KeyLink
	Sync  RekeySync
}

RekeyOptions are what a password change does beyond re-encrypting.

type RekeyResult

type RekeyResult struct {
	// NewID is the id of the vault's new key record.
	NewID string
	// Entries is how many entries were re-encrypted; Trashed, how many in
	// the trash.
	Entries, Trashed int
	Recovery         RecoveryOutcome
	// OldVaultInFile means another sesh command had the vault open, so the
	// change couldn't be folded into the vault file yet: until that command
	// ends, the file on its own still holds the vault under the old key.
	OldVaultInFile bool
}

RekeyResult reports a password change.

type RekeySync

type RekeySync int

RekeySync is what a password change means for syncing.

const (
	// RekeyLocal: nothing to sync (the vault doesn't sync now).
	RekeyLocal RekeySync = iota
	// RekeySend: a change made here, for the sync folder to take: the key
	// record the vault had, the folder's, is kept until it's sent.
	RekeySend
	// RekeyAdopt: the vault takes the sync folder's key record, changed on
	// another computer; any change of its own not sent is dropped.
	RekeyAdopt
)

The meanings.

type Restored

type Restored struct {
	Key      vault.Key
	TagsLost bool
}

Restored is an entry put back from the trash: its name, and whether its tags were damaged, so it came back without them.

type SeenRecovery

type SeenRecovery struct {
	// RestoredKey: see Restored.
	RestoredKey []byte
	syncfolder.Recovery
	// Mine says this vault sent it. Earlier says the folder's record goes
	// before it: it was seen under a key the vault had before a master
	// password change it took from another computer (someone who knew the
	// old password could have made it). Restored says the vault's own
	// record was put back by a restore since, with the key RestoredKey
	// (nil for none): while it's that one, it isn't a change to send, and
	// the folder's (or this one) is taken in its place.
	Mine, Earlier, Restored bool
}

SeenRecovery is the sync folder's recovery key record as the vault last saw it, taken or sent: a Count of 0 when it saw none.

func VaultSyncRecovery

func VaultSyncRecovery(dbPath string) (_ SeenRecovery, err error)

VaultSyncRecovery is the vault at dbPath's SyncRecovery, read without unlocking it.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is the vault: entries in a SQLite file, each encrypted, through the vault.Store methods (entries.go).

func Open

func Open(dbPath string, oracle CryptoOracle) (*Store, error)

Open creates or opens the SQLite database at dbPath, runs any pending migrations, and returns a ready-to-use Store.

func (*Store) AddTag

func (s *Store) AddTag(keys []vault.Key, tag string) (int, error)

AddTag tags the entries keys name, returning how many didn't have it.

func (*Store) AuditCountEstimate

func (s *Store) AuditCountEstimate() (int64, error)

AuditCountEstimate returns roughly how many events the audit log holds, without counting rows: the newest event's id minus the oldest's, plus one, each a single lookup at the end of the primary key (one query with both MIN and MAX would scan the table). It's exact while pruning removes the oldest events first, as it does unless the clock moved backward, and an overestimate otherwise.

func (*Store) AuditEvents

func (s *Store) AuditEvents(limit int) (_ []AuditEntry, err error)

AuditEvents returns the newest limit audit events, newest first; limit 0 returns them all.

func (*Store) AuditSummary

func (s *Store) AuditSummary() (count int64, oldest time.Time, err error)

AuditSummary returns how many events the audit log holds and when the oldest was written (zero when it's empty).

func (*Store) CheckKey

func (s *Store) CheckKey() error

CheckKey confirms that the store's oracle holds this vault's key: that the key record it was checked against is the one in the file the store has open. The vault's key can change between unlocking and opening, when another sesh command changes the master password; entries written then would be unreadable with the new key. Callers run it right after Open, before any read or write.

func (*Store) CheckUnlocked

func (s *Store) CheckUnlocked() error

CheckUnlocked says whether the store can still read the vault: an error when its key source can no longer serve it (an agent that locked, or stopped), or ErrVaultKeyChanged when the vault's master password changed since it was unlocked. Neither counts as a use of the key.

func (*Store) ClearAudit

func (s *Store) ClearAudit() (int64, error)

ClearAudit deletes every audit event, whatever its timestamp, and returns how many it deleted.

func (*Store) Close

func (s *Store) Close() error

Close releases the database connection and clears any cached key material held by the key source.

func (*Store) CodeKey

func (s *Store) CodeKey(k vault.Key) ([]byte, error)

CodeKey is the TOTP entry k's key, for drawing its codes on screen, which the audit log doesn't record, as it does reading a secret: a code shown isn't one copied or revealed. Only a TOTP entry's key is read so.

func (*Store) Compact

func (s *Store) Compact() error

Compact rewrites the vault without the free space that deleted rows leave behind (SQLite keeps it for reuse rather than shrinking the file), then folds the write-ahead log back into the file. That last step needs every other reader to have finished; it waits up to compactWait for them, then returns ErrVaultBusy.

func (*Store) DataVersion

func (s *Store) DataVersion() (int64, error)

DataVersion is a number that changes when another connection to the vault file, such as another sesh command, commits a change (SQLite's data_version, read on the store's one connection): two that differ say the vault may have changed between them.

func (*Store) Delete

func (s *Store) Delete(k vault.Key) error

Delete implements vault.Store, as DeleteMany does one entry.

func (*Store) DeleteMany

func (s *Store) DeleteMany(keys []vault.Key) error

DeleteMany implements vault.Store: the entries go, in one transaction, into the trash, or for good when it keeps none (see SetTrashDays).

func (*Store) Details

func (s *Store) Details(k vault.Key, reading string) (vault.Details, error)

Details implements vault.Store.

func (*Store) EachSecret

func (s *Store) EachSecret(reading string, kinds []vault.Kind, each func(e *vault.Entry, secret []byte, err error) error) (n int, err error)

EachSecret calls each with every entry of kinds and its secret, decrypted, which it zeroes after each call, and records the reads as one audit event: "<reading>: read N secrets". Other kinds' secrets aren't read. An entry whose secret doesn't decrypt (ErrDecrypt) is handed to each with that error and no secret; one deleted meanwhile is passed over. Any other error, or one from each, stops it.

func (*Store) Edit

func (s *Store) Edit(k vault.Key, given *EntryEdit) (string, error)

Edit changes the entry at k as e says, in one transaction. Its secret and details are sealed to its key (entryAAD, detailsAAD), so a new key re-seals them: decrypted, encrypted for the new key, and written with it. The details after the change must pass Details.Check for the new kind, so an entry keeping notes can't become a secure note. The row stays, so its folder, tags, settings, and creation time come along; its update time moves only with a new secret. A new key another entry has is ErrNameTaken; the entry changed meanwhile is ErrEntryChanged. It returns the change, in words, as the audit event records it.

func (*Store) EmptyTrash

func (s *Store) EmptyTrash() (int, error)

EmptyTrash deletes every entry in the trash for good, and returns how many there were.

func (*Store) Exists

func (s *Store) Exists(k vault.Key) error

Exists implements vault.Store.

func (*Store) ExpireTrash

func (s *Store) ExpireTrash(cutoff time.Time) (int, error)

ExpireTrash deletes for good the entries deleted before cutoff, and returns how many.

func (*Store) Fingerprint

func (s *Store) Fingerprint() ([sha256.Size]byte, error)

Fingerprint is a hash of what the entries are: every entry's names, filing, details and sealed values, their tags, and the key record. It changes when any of those does, and not for what else is written, such as the audit log, so a change it shows is one to what's stored.

func (*Store) Folders

func (s *Store) Folders() ([]FolderCount, error)

Folders returns every folder, with the folders above them that hold no entries of their own, ordered part by part so subfolders follow their folder. The entries in no folder come first, when there are any.

func (*Store) ForgetVersionOf

func (s *Store) ForgetVersionOf(k vault.Key, v Version) error

ForgetVersionOf deletes k's version v, as History listed it, for good, wherever it's numbered now: ErrVersionGone when it's no longer in the history, even if another command forgets it meanwhile.

func (*Store) ForgetVersions

func (s *Store) ForgetVersions(k vault.Key, ns ...int) error

ForgetVersions deletes k's versions ns (2 and up) for good, all or none: each is resolved before any is deleted, so the numbers mean what they meant when they were listed.

func (*Store) Get

func (s *Store) Get(k vault.Key) ([]byte, error)

Get implements vault.Store.

func (*Store) GetFor

func (s *Store) GetFor(k vault.Key, reading string) ([]byte, error)

GetFor is Get, recording in the audit log what the secret was read for: reading, such as "secret, to run".

func (*Store) HasEntries

func (s *Store) HasEntries() (bool, error)

HasEntries reports whether the vault holds any entry, in the trash or not, reading none.

func (*Store) History

func (s *Store) History(k vault.Key) (_ []Version, err error)

History is the entry k's earlier secrets, the newest first: version 2 is the first, as version 1 is the current secret.

func (*Store) HistoryKeep

func (s *Store) HistoryKeep() int

HistoryKeep is how many earlier secrets each entry keeps.

func (*Store) KeepAlive

func (s *Store) KeepAlive() error

KeepAlive tells the key source the vault is still in use, so an agent's idle timer starts again; a key source that doesn't time out has nothing to do.

func (*Store) LastAuditEvent

func (s *Store) LastAuditEvent(eventType string) (*AuditEntry, error)

LastAuditEvent is the newest audit event of eventType, or nil when the log has none.

func (*Store) LastReads

func (s *Store) LastReads(ignoring ...string) (map[string]int64, error)

LastReads is, for each entry the audit log has a read of, the id of its latest read: a higher id is a later read. Reads whose detail holds any of ignoring are left out.

func (*Store) List

func (s *Store) List(f *vault.Filter) (_ []vault.Entry, err error)

List implements vault.Store.

func (*Store) LogDoctor

func (s *Store) LogDoctor(detail string)

LogDoctor records a sesh doctor check of the vault in the audit log, with its result as detail.

func (*Store) LogImport

func (s *Store) LogImport(detail string)

LogImport records an import in the audit log, with what it brought in as detail.

func (*Store) LogSync

func (s *Store) LogSync(detail string)

LogSync records a sync with the sync folder in the audit log: detail says what it did.

func (*Store) Lookup

func (s *Store) Lookup(k vault.Key) (vault.Entry, error)

Lookup implements vault.Store.

func (*Store) MoveToFolder

func (s *Store) MoveToFolder(keys []vault.Key, folder string) (int, error)

MoveToFolder files the entries keys name in folder ("" for none), returning how many moved; those already there don't count.

func (*Store) Path

func (s *Store) Path() string

Path is the vault file the store opened.

func (*Store) PruneAudit

func (s *Store) PruneAudit(before time.Time) (int64, error)

PruneAudit deletes the audit events written before before and returns how many it deleted.

func (*Store) PruneHistory

func (s *Store) PruneHistory(keep int) (int, error)

PruneHistory drops, from every entry's history, live or in the trash, what's past the newest keep (all, for 0), and returns how many.

func (*Store) PurgeMany

func (s *Store) PurgeMany(keys []vault.Key) error

PurgeMany deletes the entries for good, not into the trash, in one transaction.

func (*Store) Put

func (s *Store) Put(k vault.Key, secret []byte) error

Put implements vault.Store.

func (*Store) ReadVersion

func (s *Store) ReadVersion(k vault.Key, n int, reading string) ([]byte, error)

ReadVersion is the secret of k's version n (2 and up), for reading, which the audit log records.

func (*Store) ReadVersionOf

func (s *Store) ReadVersionOf(k vault.Key, v Version, reading string) ([]byte, error)

ReadVersionOf is the secret of k's version v, as History listed it, for reading, which the audit log records: ErrVersionGone when it's no longer in the history.

func (*Store) Reader

func (s *Store) Reader() (*Store, error)

Reader is the vault opened again, on its own connection, for a long read (sesh doctor's checks) that would otherwise hold the one connection this store has, and with it every other read and write, until it's done. It shares this store's key, as it is (so it still notices a master password changed or an agent locked), which its Close leaves open. A vault file gone from its place isn't made again.

func (*Store) Recovery

func (s *Store) Recovery() (*RecoveryRecord, error)

Recovery is the vault's recovery key record: ErrNoRecovery when it has none.

func (*Store) Rekey

func (s *Store) Rekey(newKey []byte, rec UnlockMaterial, rewrap func(r *RecoveryRecord, newID string) (*RecoveryRecord, error), opts RekeyOptions) (RekeyResult, error)

Rekey re-encrypts the vault in place under newKey, whose key record is rec, in one transaction: every entry's secret and details, the key record, and the recovery key record, which rewrap re-wraps to the new key. The recovery key record is removed instead when rewrap is nil (a recovery, whose key has been used) or when it was made for another vault. Nothing changes unless all of it does, and the audit log is kept, with one event for the change.

The slow part, re-encrypting each entry, happens before the transaction, so other sesh commands wait for it only briefly; an entry saved in the meantime is re-encrypted inside it.

It refuses with ErrVaultKeyChanged when the vault's key isn't the one the store's key was checked against. Afterwards the store's key no longer opens the vault, so the caller closes it.

opts says what it means for syncing, and the key links kept.

func (*Store) RemoveFromTrash

func (s *Store) RemoveFromTrash(ids ...int64) ([]vault.Key, error)

RemoveFromTrash deletes the trash's entries ids for good, all or none: an id not in the trash deletes nothing. An id named twice counts once. It returns their names.

func (*Store) RemoveTag

func (s *Store) RemoveTag(keys []vault.Key, tag string) (int, error)

RemoveTag takes tag off the entries keys name, returning how many had it.

func (*Store) RenameFolder

func (s *Store) RenameFolder(from, to string) (n int, merged bool, err error)

RenameFolder renames folder from, and the folders under it, to to, returning how many entries moved. When to already held other entries, the two merge, and merged says so. It's refused when a subfolder's new name would be too long.

func (*Store) RenameTag

func (s *Store) RenameTag(from, to string) (n int, merged bool, err error)

RenameTag renames tag from to to on every entry, returning how many entries had it. When to was already in use, the two merge, and merged says so; an entry with both keeps one.

func (*Store) RestoreFromTrash

func (s *Store) RestoreFromTrash(id int64, as vault.Key) (Restored, error)

RestoreFromTrash puts the trash's entry id back, under as when it isn't the zero Key (its secret and details sealed again for that name), and returns the name it has. A name another entry has is refused with ErrNameTaken; as must keep the entry's kind. Sealing again happens before the write, as Edit's does, and the write checks the entry in the trash is as it was read (ErrEntryChanged, if a new master password sealed it again meanwhile).

func (*Store) RestoreVersion

func (s *Store) RestoreVersion(k vault.Key, n int) (kept bool, err error)

RestoreVersion makes k's version n (2 and up) its secret again; the secret it replaces goes into the history, as any replaced secret does. It reports whether that one was kept: not when none are, or when it's the same secret.

func (*Store) RestoreVersionOf

func (s *Store) RestoreVersionOf(k vault.Key, v Version) (kept bool, err error)

RestoreVersionOf is RestoreVersion of the version v, as History listed it, wherever it's numbered now: ErrVersionGone when it's no longer in the history.

func (*Store) Save

func (s *Store) Save(e *vault.Entry, secret []byte) error

Save implements vault.Store.

func (*Store) SaveImported

func (s *Store) SaveImported(e *vault.Entry, secret []byte, d *vault.Details, earlier []vault.Earlier) (ImportedHistory, error)

SaveImported is SaveWithDetails, or Save when d is nil, for an import that also brings the entry's earlier secrets, the newest first. They go into its history below what it has, and below the secret this replaces; one the entry already has, as its secret or an earlier one, isn't kept again, so importing twice adds nothing twice. Only as many as history.keep has room for are kept, the newest, and none over MaxSecretSize; the result says how many.

func (*Store) SaveWithDetails

func (s *Store) SaveWithDetails(e *vault.Entry, secret []byte, d *vault.Details) error

SaveWithDetails implements vault.Store.

func (*Store) SetDetails

func (s *Store) SetDetails(k vault.Key, d *vault.Details) error

SetDetails implements vault.Store. The update time stays: it follows the secret.

func (*Store) SetHistoryKeep

func (s *Store) SetHistoryKeep(n int)

SetHistoryKeep sets how many earlier secrets each entry keeps; 0 keeps none. A new Store keeps none.

func (*Store) SetSettings

func (s *Store) SetSettings(k vault.Key, settings *vault.Settings) error

SetSettings implements vault.Store.

func (*Store) SetTrashDays

func (s *Store) SetTrashDays(days int)

SetTrashDays sets how many days a deleted entry stays in the trash; 0 means none do, and deleting is for good. A new Store keeps none.

func (*Store) Size

func (s *Store) Size() (int64, error)

Size is the vault's size on disk in bytes: the database file and its write-ahead log.

func (*Store) SyncAddTyped

func (s *Store) SyncAddTyped(uid string, t *syncfolder.Typed) error

SyncAddTyped keeps t, typed in the entry uid and sent with the count t.N, folded in with what it kept before (syncfolder.Fold).

func (*Store) SyncAgree

func (s *Store) SyncAgree(uid string, rev int64, rec *syncfolder.Record, hash syncfolder.Hash) error

SyncAgree records that the entry uid, at rev here, and the folder's file of hash agree on rec: once this computer has written its version there, or found it the same. If uid's rev isn't rev any more (another command changed it meanwhile), nothing is recorded: ErrEntryChanged, for the next sync.

func (*Store) SyncApply

func (s *Store) SyncApply(uid string, rev int64, rec *syncfolder.Record, hash syncfolder.Hash) (int64, error)

SyncApply makes the entry uid here as rec has it, in one transaction, if its rev is still rev (ErrEntryChanged, for the next sync, if another command changed it meanwhile), and records it agreed with the folder's file of hash. A name another entry has is ErrNameTaken. It returns the entry's rev after; 0 for one deleted for good. The writes are quiet: the rev is set, not raised by them.

func (*Store) SyncBase

func (s *Store) SyncBase(uid string) (*syncfolder.Record, error)

SyncBase is the version uid was last agreed at, nil when it never was. The caller wipes it.

func (*Store) SyncCheck

func (s *Store) SyncCheck(rec *syncfolder.Record) error

SyncCheck says what's wrong with rec as an entry sesh would keep, if anything: a merged one may not fit (too many fields, notes too long).

func (*Store) SyncComputerID

func (s *Store) SyncComputerID() (string, error)

SyncComputerID is this computer's sync ID, made the first time it's asked for: random, kept in the vault, and not taken from a backup, so each computer's changes are counted as its own (syncfolder.Versions).

func (*Store) SyncDropEntry

func (s *Store) SyncDropEntry(uid string) error

SyncDropEntry forgets the entry uid, deleted for good here, as synced: nothing is sent for it.

func (*Store) SyncFolderID

func (s *Store) SyncFolderID() (string, error)

SyncFolderID is the ID of the sync folder the vault syncs with, or did before it left; "" when none.

func (*Store) SyncItems

func (s *Store) SyncItems() (_ []SyncItem, err error)

SyncItems is every entry, live, in the trash, or gone since it was synced, by uid.

func (*Store) SyncKeyChange

func (s *Store) SyncKeyChange() (string, error)

SyncKeyChange is the ID of the key record the vault had before a master password change made here that the sync folder hasn't taken yet (the folder's), or "" when there's none to send.

func (*Store) SyncKeyChangeSent

func (s *Store) SyncKeyChangeSent() error

SyncKeyChangeSent records that the sync folder has the vault's key record: there's no change to send.

func (*Store) SyncKeyID

func (s *Store) SyncKeyID() (string, error)

SyncKeyID is the ID of the vault's key record (UnlockID), which every sync file sealed with its key names.

func (s *Store) SyncKeyLinks() ([]syncfolder.KeyLink, error)

SyncKeyLinks are the vault's master password changes, oldest first.

func (*Store) SyncLeftDone

func (s *Store) SyncLeftDone(uid string) error

SyncLeftDone records that the entry uid, agreed under a key left behind (SyncItem.Left), was made again from the folder's version under the new key, with what was typed here: that's no longer kept.

func (*Store) SyncMendBase

func (s *Store) SyncMendBase(uid string, rec *syncfolder.Record) error

SyncMendBase keeps rec again as the version the entry uid was last agreed at, in place of one that doesn't open (damaged).

func (*Store) SyncNextChange

func (s *Store) SyncNextChange(seen uint64) (uint64, error)

SyncNextChange is the count of this computer's next change written to the sync folder: one more than any it gave before, and than seen (any of its counts in what it's writing over), counted in the vault before the change is written, so no two changes it writes, even one written and then lost to a crash, share a count.

func (*Store) SyncOlderKeys

func (s *Store) SyncOlderKeys() (*OlderKeys, error)

SyncOlderKeys are this vault's older keys, through its own links, from its key now.

func (*Store) SyncRecord

func (s *Store) SyncRecord(uid, computer string) (_ *syncfolder.Record, rev int64, err error)

SyncRecord is the entry uid as it is here, as a record made on computer: everything it holds, its secrets opened, with its rev as read. For one gone, it's a record of its deletion for good, now. The caller wipes it.

func (*Store) SyncRecovery

func (s *Store) SyncRecovery() (SeenRecovery, error)

SyncRecovery is the sync folder's recovery key record as the vault last saw it.

func (*Store) SyncRecoverySent

func (s *Store) SyncRecoverySent(r *syncfolder.Recovery) error

SyncRecoverySent records r as the sync folder's recovery key record, the vault's own, written there.

func (*Store) SyncSealer

func (s *Store) SyncSealer() syncfolder.Sealer

SyncSealer seals and opens sync files with the vault's key.

func (*Store) SyncSetForgotten

func (s *Store) SyncSetForgotten(uid string, marks []syncfolder.Forgotten) error

SyncSetForgotten makes the earlier secrets forgotten on purpose in the entry uid exactly marks, in place of what it had.

func (*Store) SyncStartFolder

func (s *Store) SyncStartFolder(folderID string) error

SyncStartFolder makes folderID the sync folder the vault syncs with. A vault that synced with another forgets what it agreed with that one, so every entry goes to the new folder as a change (entries restored from a backup stay marked so), and so does its recovery key record; one syncing with folderID already keeps it.

func (*Store) SyncTakeRecovery

func (s *Store) SyncTakeRecovery(r *SeenRecovery, rec *RecoveryRecord, had []byte) error

SyncTakeRecovery makes rec, nil for none, the vault's recovery key record, and r the folder's as the vault saw it, in one transaction; rec is for the vault's key record as it is. had is the public key of the vault's record the sync looked at (nil for none): when it isn't that any more, nothing changes (ErrRecoveryChanged).

func (*Store) SyncTyped

func (s *Store) SyncTyped(uid string) ([]*syncfolder.Typed, error)

SyncTyped is what was typed in the entry uid and kept (SyncAddTyped), in the order it was sent. One that doesn't open is left out.

func (*Store) SyncTypedChecks

func (s *Store) SyncTypedChecks() error

SyncTypedChecks checks, for each entry whose secret, notes, fields or earlier secrets changed or went since (sync_typed_check), that what's kept of what was typed in it the vault still has (SyncTypedKept): so nothing forgotten, trimmed or deleted for good stays there, synced or not.

func (*Store) SyncTypedKept

func (s *Store) SyncTypedKept(uid, computer string) error

SyncTypedKept drops, of what was typed in the entry uid and kept, any secret, notes or field the entry no longer has (syncfolder.Typed.Kept), computer naming this computer.

func (*Store) SyncWarnFresh

func (s *Store) SyncWarnFresh(line string, within time.Duration, now time.Time) (bool, error)

SyncWarnFresh says whether an automatic sync should say the warning line at now: it wasn't said in the last within. When it should, it's recorded as said now.

func (*Store) Tags

func (s *Store) Tags() (tags []TagCount, untagged int, err error)

Tags returns every tag in name order, and how many entries have none.

func (*Store) Trash

func (s *Store) Trash() (_ []TrashedEntry, err error)

Trash lists the trash, the most recently deleted first. A row whose times or tags don't read is still listed, without them, so it can be removed; sesh doctor names what's wrong with it.

func (*Store) TrashDays

func (s *Store) TrashDays() int

TrashDays is how many days a deleted entry stays in the trash.

func (*Store) Verify

func (s *Store) Verify() (VerifyReport, error)

Verify checks the vault without writing to it, from one read-only view of it: SQLite's integrity check of the file, then every entry's secret decrypted with the store's key and its settings and times read. It reports every problem rather than stopping at the first.

Only a secret that doesn't decrypt with the vault's key (ErrDecrypt) counts as a damaged entry. Any other failure, such as an agent that locked or went away, or a master password changed by another command (ErrVaultKeyChanged), means the check couldn't finish, and is returned as an error with a partial report.

type SyncAgreed

type SyncAgreed struct {
	Hash syncfolder.Hash
	Rev  int64
	// Intact says the version agreed is kept as it was sealed (its hash),
	// for this entry, with the vault's key now: it opens without being
	// opened to find out.
	Intact bool
}

SyncAgreed is what this computer and the folder last agreed on for an entry: its rev here then, and the hash of the folder's file (SyncBase is the version itself).

type SyncItem

type SyncItem struct {
	// Agreed is nil for an entry never synced.
	Agreed *SyncAgreed
	UID    string
	// Key is its name; the zero Key when gone.
	Key   vault.Key
	Place SyncPlace
	// Rev is 0 when gone.
	Rev int64
	// Restored says it was restored from a backup and hasn't synced since;
	// RestoredRev is its rev then (another now: changed since);
	// RestoredChanged, that the backup had it changed and not synced.
	RestoredRev     int64
	Restored        bool
	RestoredChanged bool
	// Left says it was agreed under a key this computer left behind,
	// taking a master password change made elsewhere: until it's made
	// again from the folder's version under the new key (SyncLeftDone),
	// nothing is sent for it.
	Left bool
}

SyncItem is an entry as sync sees it.

func (*SyncItem) Changed

func (i *SyncItem) Changed() bool

Changed says whether the entry changed here since it was last agreed: made, edited, moved to or from the trash, or deleted for good.

type SyncPlace

type SyncPlace int

SyncPlace is where an entry is.

const (
	// SyncLive is an entry in the vault.
	SyncLive SyncPlace = iota + 1
	// SyncTrashed is an entry in the trash.
	SyncTrashed
	// SyncGone is an entry deleted for good (or never here): only what
	// was last agreed of it is left.
	SyncGone
)

type TagCount

type TagCount struct {
	Name    string
	Entries int
}

TagCount is a tag and how many entries have it.

type TrashedEntry

type TrashedEntry struct {
	DeletedAt time.Time
	vault.Entry
	ID int64 // its trash id, which sesh trash names it by
}

TrashedEntry is an entry in the trash.

type UnlockMaterial

type UnlockMaterial struct {
	Salt   []byte
	Verify []byte
	Params Argon2idParams
}

UnlockMaterial is the vault's key record: what an unlock derives the key from and checks it against. Nothing here is the key.

func ReadUnlockMaterial

func ReadUnlockMaterial(dbPath string) (_ UnlockMaterial, err error)

ReadUnlockMaterial reads the key record of the vault at dbPath, without any key. It returns ErrNoVault when there is no vault there yet, and never creates one.

type VerifyReport

type VerifyReport struct {
	// Recovery is the recovery key record, nil when there's none or
	// RecoveryErr says it can't be read.
	Recovery    *RecoveryRecord
	RecoveryErr error
	// KeyID is the id of the vault's key record (UnlockID).
	KeyID string
	// Structure is what SQLite's integrity check found wrong with the
	// file, empty when it's sound. When the check itself couldn't run,
	// its error is the one line.
	Structure []string
	// Problems are the entries that can't be read, ordered by key.
	Problems []EntryProblem
	// TrashProblems are those of the entries in the trash.
	TrashProblems []EntryProblem
	// HistoryProblems are the entries' earlier secrets that can't be read:
	// of a live entry (with its Version) or one in the trash (TrashID).
	HistoryProblems []EntryProblem
	// Entries is how many entries the vault holds; Trashed, how many are
	// in the trash; History, how many earlier secrets they keep.
	Entries, Trashed, History int
}

VerifyReport is what Verify found, all from one consistent view of the vault.

type Version

type Version struct {
	ReplacedAt time.Time
	ID         int64
}

Version is one of an entry's earlier secrets: its row, and when it stopped being the secret.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL