Documentation
¶
Overview ¶
Package capture owns the single dest->source write-back path. apply substitutes ${secret:…} into a destination as cleartext and may drop source-only fields the rendered dest never carries; any flow that reads a destination back into the canonical source (import, reconcile write-back, a future "adopt") must invert both, in exactly one place, or it reintroduces a recurring class of bugs (cleartext-secret persistence, source-only field drift, backup bypass).
Capture is that place. It re-references secrets, preserves source-only fields, and routes every write through internal/source/writer.go.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Opts ¶
type Opts struct {
// Warn receives a human-readable warning when a ${secret:…} reference in
// the current source cannot be resolved (backend unavailable / locked), so
// re-referencing may have left cleartext in the written-back file. nil
// discards it. This is the guard that keeps a secret from silently landing
// in ~/.agentsync.
Warn io.Writer
}
Opts tunes a Capture call.
type Result ¶
type Result struct {
// Written lists the source-relative paths written, in write order.
Written []string
}
Result reports what Capture wrote.
func Capture ¶
Capture persists ingested — a canonical reconstructed from a destination — back into the canonical source at home. It is the single dest->source path; both import and reconcile build a single-item canonical and call it.
For every component present in ingested it, in one place:
- re-references resolved secrets back to ${secret:…} against the current source (secrets.ReReferenceCanonical), so a live credential apply wrote into the destination is never persisted into ~/.agentsync;
- preserves source-only fields the rendered destination never carries (MCP/LSP agents + enabled), so write-back can't silently broaden a server's exposure or clear its enablement;
- writes through internal/source/writer.go (never iox.AtomicWrite directly).
The current source MUST load for Capture to run: re-referencing and source-only field preservation both read it. source.Load returns an empty Canonical (no error) for an empty/absent home — the first-import / "adopt a foreign dest item" case — so steps 1–2 run as harmless no-ops there, which is correct (apply only substitutes from a source ${secret:…}, so a brand-new item carries no secret WE resolved). But source.Load DOES error on any malformed file anywhere in the tree, and that is exactly when a user is most likely re-importing. Writing in that state would skip re-referencing and persist a resolved cleartext secret into ~/.agentsync (a committed dotfiles repo) with no warning. So Capture fails CLOSED: it refuses to write and surfaces the load error rather than risk leaking a credential.