Documentation
¶
Overview ¶
Package store is arca's on-disk secret store: a single JSON document holding cleartext metadata plus per-value age ciphertext.
Why JSON (and not, say, SQLite) for the store:
- it diffs and merges in git, so the store can live in a dotfiles repo as the source of truth, and `git log` gives a free "created/modified" history;
- metadata (names, tags, descriptions) stays human-readable, so `ls`/`show` can answer questions without ever decrypting a value.
Read tracking deliberately does NOT live here — it goes to the separate (local) audit DB — so a `get` never rewrites this file and never churns git. The store therefore only changes on real mutations (set/rotate/rm), which is exactly what you want versioned.
Index ¶
Constants ¶
const Version = 1
Version is the on-disk schema version, bumped if the JSON shape ever changes incompatibly.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Secret ¶
type Secret struct {
Value string `json:"value"` // armored age ciphertext
CreatedAt time.Time `json:"created_at"` // first set; preserved across rotate
UpdatedAt time.Time `json:"updated_at"` // last value change
Tags []string `json:"tags,omitempty"` // free-form labels for filtering
Description string `json:"description,omitempty"` // human note
RotateAfter *time.Time `json:"rotate_after,omitempty"` // rotation due date (drives `stale`)
ExpiresAt *time.Time `json:"expires_at,omitempty"` // hard expiry: reads/use refuse the value after this
Disabled bool `json:"disabled,omitempty"` // kill switch: refused on every access path until re-enabled; independent of ExpiresAt (SEC-13)
NoPrint bool `json:"no_print,omitempty"` // exec-only: never reveal to stdout
RequireApproval bool `json:"require_approval,omitempty"` // human must approve each release
Canary bool `json:"canary,omitempty"` // DEPRECATED (pre-0.6.2): decoy flag. Read for back-compat but no longer written — the designation now lives in the local canary registry, out of the synced store (SEC-04).
RequireGrant bool `json:"require_grant,omitempty"` // usable only via exec/MCP with a matching active grant
RateLimit int `json:"rate_limit,omitempty"` // max uses per RateWindow (0 = unlimited)
RateWindow string `json:"rate_window,omitempty"` // the window for RateLimit (e.g. "1h"); empty defaults to 1h
Meta map[string]string `json:"meta,omitempty"` // open-ended extensibility bag
}
Secret is one entry. Value is the armored age ciphertext; every other field is cleartext metadata so the store can be listed and queried without the decryption key.
type Store ¶
type Store struct {
Version int `json:"version"`
Generation int `json:"generation,omitempty"` // monotonic save counter; bumped on every Save so a rollback (a restored older copy) is detectable (SEC-14)
Recipients []string `json:"recipients"` // age recipients re-encrypted to on `set`
Secrets map[string]*Secret `json:"secrets"`
// contains filtered or unexported fields
}
Store is the whole document. path is where it loads from / saves to (not serialized).
func Load ¶
Load reads and parses the store at path. A missing file is reported as a friendly "run `arca init`" error rather than a raw os error.
func (*Store) Save ¶
Save writes the store atomically and with restrictive permissions:
- serialize to a temp file in the same directory (so rename is atomic on the same fs),
- chmod 0600 before writing any bytes,
- fsync-free rename over the destination.
The temp file is removed on any early-return error path via the deferred Remove.