Skip to main content
net10.0

Reference .NET SDK for the vivarium-changeset spec: JCS canonicalization, fingerprinting, validation, unified diff, and authoring. No apply logic — the changeset is a contract, not an executor.

Published
Sep 24, 2026
25d ago
Total Downloads
723
723

Install

dotnet add package Vivarium.Changeset --version 0.6.0
ProductVersions
.NET
net10.0

README

Vivarium.Changeset — .NET reference SDK

Construct, canonicalize, fingerprint, and validate Vivarium Changeset documents. Contains no apply logic — appliers (e.g. vivarium-stage) are consumers of this format, not part of this SDK.

No runtime dependencies beyond the BCL. Targets .NET 10. Same surface as the TypeScript reference SDK; fingerprints are byte-identical across the two (proven by the shared conformance fixtures, including the interop-jcs-edges vector).

Usage

using System.Text.Json.Nodes;
using Vivarium.Changeset;

// the artifact's current source, and the source the agent proposes
var currentSource = "export function LoanScreen() { /* current */ }";
var nextSource = "export function LoanScreen() { /* renders dueDate */ }";

var doc = new ChangesetBuilder(
        intent: "Add a due-date to the loan screen",
        producedBy: "my-agent",
        createdAt: DateTimeOffset.UtcNow.ToString("o")) // caller supplies the clock
    .AddSchemaOp((JsonObject)JsonNode.Parse("""
        { "op": "field.add", "entity": "loan",
          "field": { "name": "dueDate", "type": "date" },
          "explanation": "Stores the loan's due date" }
        """)!)
    .AddUiPatch(
        artifactId: "screen-loans",
        baseContent: currentSource, // null for creation
        newContent: nextSource,     // review diff + base fingerprint are derived, never hand-written
        explanation: "Renders the due-date field")
    .Finalize();                    // validates, stamps fingerprint — or throws with structured errors

Verifying on the consuming side. Unlike Finalize, these APIs report — they do not throw; a conforming applier checks the results and refuses on failure (spec §7):

var result = ChangesetValidator.Validate(doc);  // spec §8 layer 1 — structure, vocabulary, diff consistency
if (!result.Valid)
    throw new InvalidOperationException($"refusing changeset: {string.Join(", ", result.Errors.Select(e => e.Path))}");

if (!ChangesetFingerprint.Verify(doc))          // spec §6 — content-addressed integrity
    throw new InvalidOperationException("refusing changeset: fingerprint mismatch");

Recording a review. The approval record's fingerprint is taken from the document, never passed in, so it names exactly what was reviewed; a document that was never finalized, or changed after it was, is refused. The caller supplies the clock, as for createdAt:

var approved = ChangesetApproval.Add(
    doc,
    approvedBy: "[email protected]",               // opaque to the SDK
    approvedAt: DateTimeOffset.UtcNow.ToString("o"),  // RFC 3339 date-time (spec §7)
    comment: "Checked the due-date rendering");       // optional
// approved["approvals"][0]["fingerprint"] equals doc["fingerprint"] — approvals sit outside the hash

Which approvals an applier trusts, and where records are kept, are the applier's decision (spec §7) — this only builds a record the gate can check.

verified-diff@0 UI patches (spec 0.2)

Surgical edits ride as a strict-dialect unified diff instead of a full artifact re-emission. ChangesetValidator.Validate covers the document-only layer; before applying, an applier MUST run the base-supplied layer (spec §8 layer 2):

using System.Text.Json.Nodes;
using Vivarium.Changeset;

var baseContent = "const title = \"Loans\";\n";
var nextContent = "const title = \"Active loans\";\n";
var patch = new JsonObject
{
    ["profile"] = "verified-diff@0",
    ["artifactId"] = "screen-loans",
    ["baseFingerprint"] = ChangesetFingerprint.OfArtifact(baseContent),
    ["diff"] = VerifiedDiff.Create(baseContent, nextContent), // deterministic, fail-closed dialect (spec §5.2.2)
    ["newFingerprint"] = ChangesetFingerprint.OfArtifact(nextContent),
    ["explanation"] = "Rename the title only",
};

var verdict = VerifiedDiff.VerifyAgainstBase(patch, baseContent); // ① base fingerprint ② apply + result fingerprint
if (!verdict.Ok)
    throw new InvalidOperationException("refusing patch: " + verdict.Errors[0].Message);
_ = verdict.NewContent; // exactly what the reviewer's diff described

Surface

Type Members
JsonCanonicalizer Canonicalize, CanonicalBytes — RFC 8785 (JCS)
ChangesetFingerprint Of, Stamp, Verify, OfArtifact, Prefix
UnifiedDiff Create, Apply, ReverseApply
VerifiedDiff Create, Apply, ParseStrict, VerifyAgainstBase — spec §5.2.2 dialect
ChangesetValidator Validate, SupportedSpecVersions, BaseStateKinds
ChangesetBuilder AddSchemaOp, AddUiPatch, AddVerifiedDiffPatch, AddDataPatch, ToDraft, Finalize
ChangesetApproval Add — spec §7

Conformance

dotnet test runs the unit suite plus the shared spec/fixtures/ corpus — the same vectors the TypeScript SDK runs. The fixtures are generated by the TypeScript reference implementation; this SDK reproduces them exactly.

Changes from Previous Version

No structural changes between v0.5.0 and v0.6.0.

Adoption Assessment

Assess this package against its supported frameworks, license, maintenance signals and dependency graph before making it a project standard.

Compatibility metadata lists 1 target framework; confirm the exact target used by your application.

Related Guides & Workflows

Learn how to evaluate, integrate, or audit this package in your .NET project.