Help us shape the future of Go! Take the 2026 Go Developer Survey

capture

package
v0.17.0 Latest Latest
Warning

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

Go to latest
Published: Oct 13, 2026 License: MIT Imports: 8 Imported by: 0

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

func Capture(home string, ingested *source.Canonical, opts Opts) (Result, error)

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:

  1. normalizes json.Number values in the MCP/LSP Extra passthrough maps to int64/float64 (normalizeExtraNumbers) so a UseNumber-decoded native integer is persisted as a TOML integer, not a string;
  2. 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;
  3. preserves MCP/LSP targeting the destination doesn't fully carry: `agents` is source-only (no native dest carries it) and is ALWAYS restored, so write-back can't silently broaden a server's exposure; `enabled` IS carried by some dests (Codex reads native `enabled` — issue #152), so the source value is restored only when the ingest carried none (nil) — a real native enable/disable round-trips, while a dest that omits `enabled` keeps the source state (so write-back still can't silently clear it);
  4. 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.

Jump to

Keyboard shortcuts

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