Documentation
¶
Overview ¶
Package vault is the local, encrypted store of protected env files and their revision history (~/.syncmyenv/vault.db).
Package vault owns the local SQLite vault (~/.syncmyenv/vault.db): projects, files, revisions, sync_queue, devices, settings.
Revisions are full encrypted snapshots (env files are tiny). Paths and project names are stored encrypted; dedup uses HMAC(vault key, content). See docs/architecture.md.
Index ¶
- Variables
- func CleanPath(p string) (string, error)
- func CreateKeyFile(f *crypto.KeyFile) error
- func FromPortable(p string) string
- func KeyFilePath() (string, error)
- func LoadKeyFile() (*crypto.KeyFile, error)
- func SafeImportPath(p string) bool
- func ToPortable(abs string) string
- func UpdateKeyFile(f *crypto.KeyFile) error
- type File
- type ImportResult
- type PendingRevision
- type ProtectResult
- type RestoreResult
- type Revision
- type SnapshotResult
- type Vault
- func (v *Vault) Close() error
- func (v *Vault) CountPending(ctx context.Context) (int, error)
- func (v *Vault) DeviceCert(ctx context.Context) ([]byte, error)
- func (v *Vault) DeviceKey() (ed25519.PrivateKey, error)
- func (v *Vault) History(ctx context.Context, path string) ([]Revision, error)
- func (v *Vault) ImportRemote(ctx context.Context, key *crypto.VaultKey, p protocol.EntryPayload, ...) (*ImportResult, error)
- func (v *Vault) KeyFile() *crypto.KeyFile
- func (v *Vault) List(ctx context.Context) ([]File, error)
- func (v *Vault) MarkPushed(ctx context.Context, revisionIDs, objectIDs []string) error
- func (v *Vault) Missing(ctx context.Context) ([]File, error)
- func (v *Vault) NextDeviceSeq(ctx context.Context, n int) (int64, error)
- func (v *Vault) Pending(ctx context.Context, limit int) ([]PendingRevision, error)
- func (v *Vault) Protect(ctx context.Context, paths []string) ([]ProtectResult, error)
- func (v *Vault) Restore(ctx context.Context, key *crypto.VaultKey, path string, seq int, to string) (*RestoreResult, error)
- func (v *Vault) SetDeviceCert(ctx context.Context, cert []byte) error
- func (v *Vault) SetState(ctx context.Context, key, value string) error
- func (v *Vault) Snapshot(ctx context.Context) ([]SnapshotResult, error)
- func (v *Vault) SnapshotPaths(ctx context.Context, only []string) ([]SnapshotResult, error)
- func (v *Vault) State(ctx context.Context, key string) (string, error)
- func (v *Vault) Unprotect(ctx context.Context, path string) error
Constants ¶
This section is empty.
Variables ¶
var ( ErrNotProtected = errors.New("file is not protected — run `sme protect` first") ErrNoRevision = errors.New("no such revision") )
var ErrAlreadyInitialized = errors.New("vault already initialized")
ErrAlreadyInitialized protects an existing vault key from being overwritten (that would make every revision sealed to it unrecoverable).
var ErrNotInitialized = errors.New("vault not initialized — run `sme init`")
ErrNotInitialized means `sme init` hasn't been run for this SYNCMYENV_HOME.
Functions ¶
func CleanPath ¶
CleanPath makes a path absolute and clean, with symlinks in its directories resolved — even when some of those directories don't exist (yet, or any more): the deepest existing ancestor is resolved and the rest re-appended. So "/var/x/app/.env" and "/private/var/x/app/.env" (macOS) are the same file whether or not app/ still exists. The file itself is never resolved: a symlinked .env is not followed.
func CreateKeyFile ¶
CreateKeyFile writes a new key file, refusing to replace an existing one.
func FromPortable ¶
FromPortable is the inverse of ToPortable on this machine.
func LoadKeyFile ¶
LoadKeyFile reads the wrapped vault key.
func SafeImportPath ¶
SafeImportPath limits what a remote entry may name: a home-relative or absolute path, no ".." tricks, and an env-file name (.env, .env.*, env, env.*). Even a legitimate-but-compromised device can't make `restore` write ~/.bashrc or ~/.ssh/authorized_keys.
func ToPortable ¶
ToPortable turns an absolute path into "~/…" when it's under the home directory, so it maps onto other machines with different usernames.
func UpdateKeyFile ¶
UpdateKeyFile replaces the key file (e.g. after a password change).
Types ¶
type File ¶
type File struct {
ID string
Path string
Project string
ProtectedAt time.Time
Revisions int
LastChange time.Time
Size int
}
File is a protected (or formerly protected) env file.
type ImportResult ¶
type ImportResult struct {
Path string
Seq int // local seq assigned (0 = already had it)
Applied bool // written to disk (fast-forward)
Conflict bool // disk had local, unsnapshotted edits; kept them, remote is in history
OnlyStore bool // file missing on disk: stored in history (sme restore --missing)
}
ImportResult says what happened to a remote revision.
type PendingRevision ¶
type PendingRevision struct {
RevisionID string
Path string
Project string
Seq int
Size int
Source string
Device string
CreatedAt int64
Sealed []byte
}
PendingRevision is a local revision not yet pushed to the server.
type ProtectResult ¶
type ProtectResult struct {
Path string
Added bool // newly protected (false = already protected)
Skipped string
}
ProtectResult says what Protect did for one path.
type RestoreResult ¶
type RestoreResult struct {
Path string
FromSeq int // revision that was restored
SavedSeq int // revision capturing the overwritten content (0 if none/unchanged)
NewSeq int // revision recording the restore
Unchanged bool
}
RestoreResult describes a restore.
type Revision ¶
type Revision struct {
Seq int
Size int
Source string
Device string
CreatedAt time.Time
// contains filtered or unexported fields
}
Revision is one sealed version of a file. Contents need the vault key.
type SnapshotResult ¶
type SnapshotResult struct {
Path string
Seq int // new revision number, 0 if unchanged
Missing bool // file no longer exists on disk
Error string // unreadable, too large…
}
SnapshotResult reports what a snapshot found for one file.
type Vault ¶
type Vault struct {
// contains filtered or unexported fields
}
Vault is an open local vault. It can protect, snapshot and list without the master password; reading contents (Restore) needs an unlocked VaultKey.
func (*Vault) CountPending ¶
CountPending returns how many local revisions await pushing.
func (*Vault) DeviceCert ¶
DeviceCert returns this device's certificate, if one has been issued.
func (*Vault) DeviceKey ¶
func (v *Vault) DeviceKey() (ed25519.PrivateKey, error)
DeviceKey is this machine's log-signing key (~/.syncmyenv/device.key, 0600). It never leaves the device. Its public half is certified by the vault key.
func (*Vault) History ¶
History lists revisions of a file, newest first. Works for unprotected files too.
func (*Vault) ImportRemote ¶
func (v *Vault) ImportRemote(ctx context.Context, key *crypto.VaultKey, p protocol.EntryPayload, originDevice, objectID string, sealed []byte) (*ImportResult, error)
ImportRemote adds a revision that came from another device. key is needed to compute the change MAC (and to write the content to disk on fast-forward).
Fast-forward rule: if the file on disk still equals this device's latest known revision (no local edits since), the remote content is written to disk. Otherwise disk wins for now and the remote revision is kept in history — nothing is ever lost.
func (*Vault) MarkPushed ¶
MarkPushed records that revisions reached the server.
func (*Vault) Missing ¶
Missing returns protected files that don't exist on disk (e.g. new machine, deleted).
func (*Vault) NextDeviceSeq ¶
NextDeviceSeq atomically reserves n device sequence numbers, returning the first.
func (*Vault) Protect ¶
Protect starts protecting files and seals their current contents as revision 1.
func (*Vault) Restore ¶
func (v *Vault) Restore(ctx context.Context, key *crypto.VaultKey, path string, seq int, to string) (*RestoreResult, error)
Restore writes revision seq (0 = latest) back to disk, or to `to` if set. The current on-disk content is snapshotted first, so a restore never loses data.
func (*Vault) SetDeviceCert ¶
SetDeviceCert stores the certificate issued by an unlocked vault key.
func (*Vault) Snapshot ¶
func (v *Vault) Snapshot(ctx context.Context) ([]SnapshotResult, error)
Snapshot seals a new revision for every protected file whose content changed. Needs no password: it only uses the public recipient.
func (*Vault) SnapshotPaths ¶
SnapshotPaths is Snapshot limited to the given absolute paths (nil = all). Paths that aren't protected are ignored.