Summary
Add SDK-owned deep-copy primitives that let a host treat component calls as transactions: components receive isolated inputs, and the host commits only a successful result.
The need exists because embedded and managed execution currently have different mutation boundaries:
PackageRegistry.Get and PackageRegistry.All return stored *Package pointers.
MatchRequest and AnalyzeRequest carry mutable *Graph, *PackageRegistry, and *Dependency values.
Package.Clone and Dependency.Clone exist, but PackageRegistry and Graph do not expose a complete deep snapshot operation.
- A managed plugin crosses a JSON/gRPC boundary and naturally receives a copy. An embedded component receives host pointers and can mutate them before returning an error or observing cancellation.
This is an execution-mode semantic mismatch: the same module can produce different host state depending on whether it is compiled in or served out of process.
Desired contract
Provide efficient, explicit SDK primitives for producing mutation-isolated matcher/analyzer inputs without using a JSON round trip. At minimum, cover every reachable mutable value in MatchRequest and AnalyzeRequest:
- registry entries and all nested package enrichment;
- graph nodes, edges, and nested dependency data;
- target dependencies;
- mutable maps, slices, and pointers reachable through those values.
The API can be Clone methods on the owning models, request snapshot helpers, or a small combination. The important contract is no shared mutable memory between the source and snapshot for component-visible data.
The host will use these primitives in a separate CLI issue to commit Registry or PackageUpdates only after a successful call. The full-registry result remains the protocol v1 baseline; delta results remain an optional optimization.
Acceptance criteria
Compatibility and ownership
This should be an additive in-process Go API change in bomly-sdk; no wire field or RPC is required. Shared model copying belongs in the SDK under the source-of-truth rule. The CLI owns when to snapshot and when to commit.
An ADR is required if the work changes component-visible execution semantics beyond adding copy primitives. Any proposed change to merge precedence should be split into its own decision.
Out of scope
- Making all SDK model types immutable.
- Parallel matcher/analyzer scheduling.
- Removing the full-registry v1 result.
- Treating JSON marshal/unmarshal as the production clone implementation.
Verification
Run:
go test ./...
go vet ./...
gofmt -l .
go mod tidy -diff
Summary
Add SDK-owned deep-copy primitives that let a host treat component calls as transactions: components receive isolated inputs, and the host commits only a successful result.
The need exists because embedded and managed execution currently have different mutation boundaries:
PackageRegistry.GetandPackageRegistry.Allreturn stored*Packagepointers.MatchRequestandAnalyzeRequestcarry mutable*Graph,*PackageRegistry, and*Dependencyvalues.Package.CloneandDependency.Cloneexist, butPackageRegistryandGraphdo not expose a complete deep snapshot operation.This is an execution-mode semantic mismatch: the same module can produce different host state depending on whether it is compiled in or served out of process.
Desired contract
Provide efficient, explicit SDK primitives for producing mutation-isolated matcher/analyzer inputs without using a JSON round trip. At minimum, cover every reachable mutable value in
MatchRequestandAnalyzeRequest:The API can be
Clonemethods on the owning models, request snapshot helpers, or a small combination. The important contract is no shared mutable memory between the source and snapshot for component-visible data.The host will use these primitives in a separate CLI issue to commit
RegistryorPackageUpdatesonly after a successful call. The full-registry result remains the protocol v1 baseline; delta results remain an optional optimization.Acceptance criteria
PackageRegistryhas a documented deep clone/snapshot operation preserving canonical contents and deterministic iteration behavior.Graphhas a documented deep clone/snapshot operation preserving live nodes, edges, and graph invariants.Compatibility and ownership
This should be an additive in-process Go API change in
bomly-sdk; no wire field or RPC is required. Shared model copying belongs in the SDK under the source-of-truth rule. The CLI owns when to snapshot and when to commit.An ADR is required if the work changes component-visible execution semantics beyond adding copy primitives. Any proposed change to merge precedence should be split into its own decision.
Out of scope
Verification
Run: