nativeconfig

package
v0.0.0-...-8a9dec9 Latest Latest
Warning

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

Go to latest
Published: Oct 10, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

README

Plain ExactFile

Kernel.BeginPlainExactFile opts into a private Darwin arm64 guard under the existing writer lock. Ordinary BeginExactFile and FileIO retain their behavior. Custom IO and unsupported metadata/platforms permit locked planning and unchanged noops, but refuse changed mutation. No client adapter or platform tuple is enabled.

Changed writes require owned writable single-link regular files and an invariant held parent on writable local APFS, null ACL/zero security GUIDs, flags zero, ordinary mode bits, and empty xattrs or sole bounded opaque com.apple.provenance. Actual staging and restoration must naturally match original security/provenance; the backend never sets, copies, strips or repairs metadata. Absent creation binds its natural metadata. Rollback requires the verified produced identity and epoch. Drift, query errors or ambiguous durability retain output with FileUncertain.

Repeated descriptor/name/security checks leave a final external syscall race; this is not linearizable byte CAS. Admission assumes well-formed native APFS and complete access to documented metadata channels. Native qualification is pending; Linux compilation and source handoff do not grant native or release availability.

The fixture-dependent Darwin operator tests use -tags=nativequalification. They require the independent TEST witness and control roots; ordinary package tests do not supply these inputs.

Documentation

Overview

Package nativeconfig applies ownership-aware MCP server patches to native JSON and JSONC client configuration files.

Index

Constants

View Source
const (
	OpenCodeMCPObjectKind   = "opencode_global_mcp_server"
	OpenCodeV2MCPObjectKind = "opencode_v2_global_mcp_server"
)
View Source
const MaxTransitionConfigBytes = 2 << 20

Storage constraints, checked before a provider can persist authority and on every reopen. These do not claim to bound ordinary native config reads.

View Source
const MaxTransitionEntries = 256

Variables

View Source
var (
	ErrAmbiguousConfig  = errors.New("both JSON and JSONC native config files exist")
	ErrCollision        = errors.New("native MCP entry already exists")
	ErrNotOwned         = errors.New("native MCP entry is not exactly owned")
	ErrMalformed        = errors.New("native config is malformed")
	ErrConcurrentChange = errors.New("native config changed during patch")
	// ErrNativeMigrationRequired rejects unqualified mixed-generation roots.
	// A managed-leaf writer cannot convert unrelated V1 configuration to V2.
	ErrNativeMigrationRequired = errors.New("native_migration_required")
)
View Source
var ErrOpenCodeV2Namespace = errors.New("OpenCode mcp.servers format is not yet supported by namespace preflight")

Functions

func IsCommittedCleanup

func IsCommittedCleanup(err error) bool

func ReadTransitionFileNoFollow

func ReadTransitionFileNoFollow(path string, limit int64) (body []byte, resultErr error)

ReadTransitionFileNoFollow reuses the native no-follow opener for private bounded journal/projection reads. Callers also enforce contained ancestors.

func ValidatePreparedTransition

func ValidatePreparedTransition(paths Paths, p PreparedTransition) error

ValidatePreparedTransition checks stored bytes, mode, paths and every receipt against both strict native documents, rather than trusting a phase or hash alone.

func WriterLockPaths

func WriterLockPaths(paths Paths, codec Codec) ([]string, error)

WriterLockPaths returns the exact lockfile identities used by the default native MCP writer, sorted by lock path in acquisition order. JSON is required; JSONC is optional. Both candidates are locked even when only one exists, so file selection and the ambiguous-config check happen under the locks. Paths must be absolute, clean and distinct, as for Apply; the codec must be supported.

This function performs no filesystem access, creates no locks and does not resolve symlinks or select a profile. Callers must validate their authority over the supplied paths. Do not append a suffix to the returned identities. Cline uses populated-directory .lock locks; all other codecs use regular-file .agentplugins.lock locks. This describes the default writer, not an injected NewWithLockAcquirer implementation, and does not acquire a lock on its behalf. Earlier binaries may acquire candidates in config-path order; multi-candidate interoperability requires that order to agree with the returned lock order.

Types

type Action

type Action string
const (
	ActionAdd    Action = "add"
	ActionUpdate Action = "update"
	ActionRemove Action = "remove"
)

type Codec

type Codec string
const (
	// CodecMCPServers is the explicit generic mcpServers profile: stdio uses
	// command/args/env/cwd and remote uses url/headers with no transport tag.
	// Clients with different native transport keys require their own codec.
	CodecMCPServers Codec = "mcpServers"
	CodecGemini     Codec = "gemini-mcpServers"
	CodecOpenCode   Codec = "opencode-mcp"
	CodecOpenCodeV2 Codec = "opencode-v2-mcp"
	CodecWindsurf   Codec = "windsurf-mcpServers"
	CodecCline      Codec = "cline-mcpServers"
)

func OpenCodeCodecForDialect

func OpenCodeCodecForDialect(dialect string) (Codec, error)

OpenCodeCodecForDialect is the closed prepared-profile/projection mapping. It accepts the serialized dialect so the config kernel does not depend on host qualification types. Stored ownership uses OpenCodeCodecForKind.

func OpenCodeCodecForKind

func OpenCodeCodecForKind(kind string) (Codec, bool, error)

OpenCodeCodecForKind is the closed stored-ownership decoder. Skills and package receipts are not MCP receipts. A claimed but unknown OpenCode kind fails closed rather than disappearing from verification or removal.

type CommittedCleanupError

type CommittedCleanupError struct{ Err error }

CommittedCleanupError reports that the requested native config bytes and receipts were committed, but releasing the cooperating writer lock did not complete cleanly. Callers must keep the returned receipts and must not roll back other state that was committed in the same provider transaction. The wrapped error remains available so the cleanup degradation is observable.

func (*CommittedCleanupError) Error

func (err *CommittedCleanupError) Error() string

func (*CommittedCleanupError) Unwrap

func (err *CommittedCleanupError) Unwrap() error

type ExactFile

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

ExactFile holds the normal nativeconfig writer lock across a caller's native transaction. It deliberately leaves parsing and ownership digests to the caller, for clients whose native shape differs from the generic MCP codec. Call Close exactly once, after commit or rollback. The portable content-CAS limitation documented on conditionalFileIO also applies here.

func (*ExactFile) Apply

func (file *ExactFile) Apply(body []byte) error

Apply compares the original bytes/existence at the write boundary, and reads back even when WriteAtomic reports an error after making its write visible. On error the caller must invoke Rollback before releasing the lock.

func (*ExactFile) Close

func (file *ExactFile) Close() error

Close reports lock cleanup separately from the observed file effect. The caller decides whether its complete native transaction committed.

func (*ExactFile) Effect

func (file *ExactFile) Effect() FileEffect

func (*ExactFile) Original

func (file *ExactFile) Original() FileSnapshot

func (*ExactFile) Rollback

func (file *ExactFile) Rollback() error

Rollback restores only our exact output. A late foreign version is retained and reported as uncertain, with its path. Restore errors also require readback.

type FileEffect

type FileEffect string
const (
	FileUnchanged FileEffect = "unchanged"
	FileCommitted FileEffect = "committed"
	FileUncertain FileEffect = "uncertain"
)

type FileIO

type FileIO interface {
	ReadNoFollow(path string) (body []byte, mode os.FileMode, exists bool, err error)
	WriteAtomic(path string, body []byte, mode os.FileMode) error
	RemoveNoFollow(path string) error
}

FileIO abstracts exact no-follow reads and atomic replacement. WriteAtomic preserves the requested file mode in the default implementation; platform metadata beyond the mode (for example ACLs and extended attributes) is not guaranteed to survive replacement.

type FileSnapshot

type FileSnapshot struct {
	Body   []byte
	Mode   os.FileMode
	Exists bool
}

FileSnapshot binds a mutation to exact bytes and existence. It is transient recovery data, never an ownership receipt or persisted client state.

type Kernel

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

func New

func New() Kernel

func NewWithFileIO

func NewWithFileIO(files FileIO) Kernel

func NewWithLockAcquirer

func NewWithLockAcquirer(acquireLocks func(Paths, Codec) (func() error, error)) Kernel

func (Kernel) Apply

func (kernel Kernel) Apply(req Request) (Receipt, error)

func (Kernel) ApplyBatch

func (kernel Kernel) ApplyBatch(requests []Request) (receipts []Receipt, err error)

ApplyBatch validates and renders related MCP entry mutations into one atomic replacement. The batch is all-or-none for cooperating agentplugins writers. See conditionalFileIO for the unavoidable portable race with clients that do not honor the same locks.

func (Kernel) ApplyDialectTransition

func (kernel Kernel) ApplyDialectTransition(req TransitionRequest) (receipts []Receipt, err error)

ApplyDialectTransition uses the same candidate locks, document and verified conditional writer as ApplyBatch. The one replacement switches all selected leaves; rollback is conditional on our exact output. The noncooperating writer syscall race documented on conditionalFileIO remains unchanged. Errors without IsCommittedCleanup must not publish target ownership; unknown write/rollback status requires provider recovery from the prepared facts.

func (Kernel) BeginExactFile

func (kernel Kernel) BeginExactFile(path string) (*ExactFile, error)

func (Kernel) BeginPlainExactFile

func (kernel Kernel) BeginPlainExactFile(path string) (*ExactFile, error)

BeginPlainExactFile retains the existing writer lock and ExactFile lifecycle. Only the default Darwin arm64 OS backend can authorize changed mutation. Unsupported metadata/platforms and custom IO still allow locked planning.

func (Kernel) CheckDialectTransition

func (kernel Kernel) CheckDialectTransition(paths Paths, source, target Codec, owned []Receipt, names []string) (err error)

CheckDialectTransition is read-only admission for the closed same-ID provider transition. ApplyDialectTransition repeats every ownership/root proof under its commit lease with fully staged desired receipts.

func (Kernel) CheckOpenCodeNamespace

func (kernel Kernel) CheckOpenCodeNamespace(paths Paths, proposed, previous []string) error

CheckOpenCodeNamespace observes only the selected user-level config. It is process-inert and never modifies the config or starts OpenCode/MCP servers. previous names are omitted only when the same operation removes them.

func (Kernel) CheckOpenCodeNamespaceForCodec

func (kernel Kernel) CheckOpenCodeNamespaceForCodec(paths Paths, codec Codec, proposed, previous []string) error

CheckOpenCodeNamespaceForCodec is the closed dialect-aware preflight for a future prepared host. The legacy helper stays V1. This is a conservative name collision policy, not proof of a running host's tool catalog or mixed roots. proposed contains only names that the prepared operation will leave active.

func (Kernel) Inspect

func (kernel Kernel) Inspect(paths Paths, codec Codec, name string, owned *Receipt) (present bool, exactlyOwned bool, err error)

Inspect performs a strict read-only ownership check for one native entry.

func (Kernel) ReadExactFile

func (kernel Kernel) ReadExactFile(path string) (FileSnapshot, error)

func (Kernel) ReconcileDialectTransition

func (kernel Kernel) ReconcileDialectTransition(req TransitionRecoveryRequest) (observation TransitionObservation, resultErr error)

ReconcileDialectTransition holds exclusion across classification, authoritative state publication, and the immediate target->exact-preimage conditional write. Like Apply, portable CAS has a syscall-sized race against noncooperating hosts.

func (Kernel) RequireFileIO

func (kernel Kernel) RequireFileIO() error

RequireFileIO reports that this kernel can Inspect and Apply. A zero Kernel has no FileIO and must not be used as a hide-default on skill-only native paths that never call ApplyBatch.

type OpenCodeNamespaceConflict

type OpenCodeNamespaceConflict struct {
	Proposed string
	Existing string
	Reason   string
}

OpenCodeNamespaceConflict is a conservative server-name collision: the servers could expose tools with the same callable ID. Tool catalogs are not queried, so this does not claim that a particular tool has collided.

func (*OpenCodeNamespaceConflict) Error

func (e *OpenCodeNamespaceConflict) Error() string

type OpenCodeV2Options

type OpenCodeV2Options struct {
	Disabled bool               `json:"disabled"`
	Timeout  *OpenCodeV2Timeout `json:"timeout,omitempty"`
}

OpenCodeV2Options is a closed subset of the pinned native MCP entry schema. Nil options render disabled:false and omit timeout.

type OpenCodeV2Timeout

type OpenCodeV2Timeout struct {
	Startup   int `json:"startup,omitempty"`
	Catalog   int `json:"catalog,omitempty"`
	Execution int `json:"execution,omitempty"`
}

OpenCodeV2Timeout uses milliseconds. Zero omits a field; configured values must be positive, as in @opencode/schema 2.0.21 Mcp.TimeoutConfig.

type Paths

type Paths struct {
	JSON  string
	JSONC string
}

Paths names the mutually exclusive client config variants. If neither exists, JSON is created. The paths must be explicit and must not use HOME.

type Placeholders

type Placeholders struct {
	PackageRoot string
	DataRoot    string
}

type PreparedTransition

type PreparedTransition struct {
	Path                     string
	Original                 FileSnapshot
	TargetBytes              []byte
	TargetHash               string
	SourceCodec, TargetCodec Codec
	Entries                  []PreparedTransitionEntry
}

PreparedTransition contains bounded native facts only, never registry state. All mutable data is detached from both the request and the pending write. The recipient may retain/mutate this copy without changing committed bytes or returned receipts. TargetHash is SHA-256 of exact TargetBytes, distinct from the existing codec/name-domain ownership digest.

type PreparedTransitionEntry

type PreparedTransitionEntry struct {
	LogicalID             string
	Name                  string
	SourceReceipt         Receipt
	PreviouslyOwnedTarget *Receipt
	TargetReceipt         Receipt
}

type Receipt

type Receipt struct {
	Version string `json:"version"`
	Path    string `json:"path"`
	Codec   Codec  `json:"codec"`
	Name    string `json:"name"`
	Digest  string `json:"digest"`
}

Receipt identifies one exact projected entry. Ownership intentionally covers the complete entry: if another writer adds even one foreign field inside the entry, the receipt becomes stale and update/remove fail closed. It is safe to persist because it contains no original file bytes or unrelated config.

func DesiredReceipt

func DesiredReceipt(resolvedPath string, codec Codec, name string, server Server, placeholders Placeholders) (Receipt, error)

DesiredReceipt projects one exact server entry without reading or mutating a config file. resolvedPath must be the already-selected clean absolute JSON or JSONC path. Apply returns the same receipt when it applies the same request.

type Request

type Request struct {
	Paths        Paths
	Codec        Codec
	Action       Action
	Name         string
	Server       Server
	Placeholders Placeholders
	Owned        *Receipt
	// Desired optionally binds add/update to the exact projected receipt the
	// caller staged. ApplyBatch compares it before any config write, including
	// the selected JSON/JSONC path, so selection drift cannot commit first and
	// fail only during a provider postcondition.
	Desired *Receipt
}

type Server

type Server struct {
	// Trusted adapters set these only after portable expansion. They are not
	// native fields or persisted payload flags; projection readers restore them.
	StdioValuesResolved bool              `json:"-"`
	CWDResolved         bool              `json:"-"`
	Type                string            `json:"type"`
	Command             string            `json:"command,omitempty"`
	Args                []string          `json:"args,omitempty"`
	Env                 map[string]string `json:"env,omitempty"`
	CWD                 string            `json:"cwd,omitempty"`
	URL                 string            `json:"url,omitempty"`
	Headers             map[string]string `json:"headers,omitempty"`
	// RemoteTransport selects codec-specific native keys where supported.
	// OpenCode V2 accepts empty (native default) or streamable-http; V1 keeps
	// rejecting an explicit transport. Unsupported transports are never dropped.
	RemoteTransport string `json:"remote_transport,omitempty"`
	// OpenCodeV2 carries only the pinned V2 disabled/timeout contract. Other
	// codecs reject it rather than silently discard dialect-specific intent.
	OpenCodeV2 *OpenCodeV2Options `json:"opencode_v2,omitempty"`
}

Server is the transport-aware neutral MCP shape accepted by the supported codecs. Type must be "stdio" or "remote". Portable placeholders are resolved once in raw args, env values, and cwd. RemoteTransport is codec-specific and is rejected unless the selected codec explicitly defines it.

type TransitionEntry

type TransitionEntry struct {
	LogicalID          string
	Name               string
	SourceOwned        Receipt
	TargetOwned        *Receipt
	TargetServer       Server
	TargetPlaceholders Placeholders
	DesiredReceipt     Receipt
}

type TransitionObservation

type TransitionObservation string
const (
	TransitionSource TransitionObservation = "source"
	TransitionTarget TransitionObservation = "target"
)

type TransitionRecoveryRequest

type TransitionRecoveryRequest struct {
	Paths    Paths
	Prepared PreparedTransition
	// Callbacks run under the same candidate lease as classification and restore.
	// An error alone grants no restore authority. Desired or unknown never restores.
	Decide   func(TransitionObservation) (TransitionStateDecision, error)
	Complete func(TransitionObservation) error
}

type TransitionRequest

type TransitionRequest struct {
	Paths                    Paths
	SourceCodec, TargetCodec Codec
	Entries                  []TransitionEntry
	// PersistPrepared must durably persist the supplied facts before returning
	// nil. It runs under the native file locks: callers acquire their operation
	// lock first, and must not reenter the kernel here. The provider owns journal
	// IDs, projection/skill linkage and recovery/state publication. A callback is
	// required; kernel success alone does not complete that provider transaction.
	PersistPrepared func(PreparedTransition) error
}

TransitionRequest is the private provider handoff for a managed-leaf OpenCode V1 <-> V2 transition, not host selection or registry authority. Entries must be strictly sorted by Name. No arbitrary document edits occur.

type TransitionStateDecision

type TransitionStateDecision string
const (
	TransitionStateOld     TransitionStateDecision = "old"
	TransitionStateDesired TransitionStateDecision = "desired"
	TransitionStateUnknown TransitionStateDecision = "unknown"
)

Jump to

Keyboard shortcuts

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