Concordant.Core
0.1.0-beta.2
dotnet add package Concordant.Core --version 0.1.0-beta.2
NuGet\Install-Package Concordant.Core -Version 0.1.0-beta.2
<PackageReference Include="Concordant.Core" Version="0.1.0-beta.2" />
<PackageVersion Include="Concordant.Core" Version="0.1.0-beta.2" />
<PackageReference Include="Concordant.Core" />
paket add Concordant.Core --version 0.1.0-beta.2
#r "nuget: Concordant.Core, 0.1.0-beta.2"
#:package Concordant.Core@0.1.0-beta.2
#addin nuget:?package=Concordant.Core&version=0.1.0-beta.2&prerelease
#tool nuget:?package=Concordant.Core&version=0.1.0-beta.2&prerelease
<a id="readme-top"></a>
<div align="center"> <h3 align="center">Concordant</h3>
<p align="center"> An embeddable, correctness-first CRDT framework for .NET 8 and .NET 10. <br /> Shared text, maps, arrays, and nested containers; selective local undo; offline merge; and transport-agnostic sync over opaque update bytes—backed by a transactional YATA-style operation store. <br /> <br /> <a href="docs/design/concordant-framework.md"><strong>Explore the docs »</strong></a> <br /> <br /> <a href="samples/Concordant.Quickstart">View Quickstart</a> · <a href="https://github.com/malunes0418/concordant/issues">Report Bug</a> · <a href="https://github.com/malunes0418/concordant/issues">Request Feature</a> </p> </div>
<details> <summary>Table of Contents</summary> <ol> <li> <a href="#about-the-project">About The Project</a> <ul> <li><a href="#built-with">Built With</a></li> <li><a href="#packages--status">Packages & Status</a></li> </ul> </li> <li> <a href="#getting-started">Getting Started</a> <ul> <li><a href="#prerequisites">Prerequisites</a></li> <li><a href="#installation">Installation</a></li> </ul> </li> <li><a href="#usage">Usage</a></li> <li><a href="#roadmap">Roadmap</a></li> <li><a href="#documentation">Documentation</a></li> <li><a href="#contributing">Contributing</a></li> <li><a href="#license">License</a></li> <li><a href="#contact">Contact</a></li> <li><a href="#acknowledgments">Acknowledgments</a></li> </ol> </details>
About The Project
Concordant is a library you embed in your own .NET hosts. You own the wire and durability; Concordant owns the document model, merge semantics, and native update codec.
Features:
- Shared types —
SharedText,SharedMap,SharedArray, with nested maps/arrays/text - Transactional document — mutate inside
ConcordantDocument.Transact, integrate withApply/ApplyUpdate - Selective undo — session-local
UndoManager(remote updates are never stacked; undo is not checkpointed) - Offline merge — encode deltas with
EncodeUpdateSince, apply peer bytes withApplyUpdate - Transport-agnostic sync — you own the wire (HTTP, WebSockets, files, etc.); Concordant speaks update bytes
- Persistence abstractions —
IConcordantAppendLogandIConcordantCheckpointStorefor host-owned durability - Multi-target — public packages target
net8.0andnet10.0with equivalent APIs and native v1 wire format
Not in this prerelease: networking stacks, production storage adapters, rich text, schemas, presence, encryption, ecosystem codecs, or destructive tombstone GC.
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Built With
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Packages & Status
0.1.0-beta.2 — kernel stabilization prerelease (atomic transactions, scaling indexes, state-vector APIs, release gates). APIs may still change before 1.0.
| Package | Role |
|---|---|
Concordant.Core |
Document kernel, shared types, native codec, undo |
Concordant.Persistence.Abstractions |
Append-log / checkpoint host contracts |
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Getting Started
Clone the repo (or install the NuGet packages) and follow the steps below to build, test, and try the sample locally.
Prerequisites
- .NET 10 SDK (pinned in
global.json; roll-forward allowed) - .NET 8 runtime / targeting pack for dual-target restore, build, and test
Installation
- Clone the repo
git clone https://github.com/malunes0418/concordant.git cd concordant - Restore, build, and test
dotnet restore Concordant.slnx dotnet build Concordant.slnx --configuration Release --no-restore dotnet test Concordant.slnx --framework net8.0 --configuration Release --no-build dotnet test Concordant.slnx --framework net10.0 --configuration Release --no-build - Optional smoke / sample
dotnet run --project tests/Concordant.Fuzz.Tests --framework net8.0 --configuration Release -- --smoke dotnet run --project samples/Concordant.Quickstart --framework net8.0 --configuration Release
Install from packages
Concordant.Core and Concordant.Persistence.Abstractions are published on nuget.org (current line: 0.1.0-beta.2 once this release is tagged; 0.1.0-beta.1 is already available).
dotnet add package Concordant.Core --version 0.1.0-beta.2
dotnet add package Concordant.Persistence.Abstractions --version 0.1.0-beta.2
To pack locally from source:
dotnet pack Concordant.slnx --configuration Release
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Usage
Shared text, map, and sync
using Concordant;
using Concordant.Shared;
using Concordant.Values;
using var doc = new ConcordantDocument();
_ = doc.Transact(tx =>
{
SharedText notes = tx.GetOrCreateText("notes");
notes.Insert(0, "hello");
SharedMap meta = tx.GetOrCreateMap("meta");
meta.Set("rev", ConcordantScalar.Int64(1));
SharedArray tags = tx.GetOrCreateArray("tags");
tags.Add(ConcordantScalar.String("draft"));
});
// Empty remote state vector => full missing update for peers that know nothing.
byte[] update = doc.EncodeUpdateSince(new Dictionary<SessionId, ulong>());
byte[] frontier = doc.EncodeStateVector(); // canonical 24-byte-entry layout
using var peer = new ConcordantDocument();
ApplyResult result = peer.ApplyUpdate(update);
// result.Status is Integrated / Duplicate / Pending / Rejected, etc.
Console.WriteLine(peer.GetText("notes")); // "hello"
Nested types
_ = doc.Transact(tx =>
{
SharedMap root = tx.GetOrCreateMap("doc");
SharedMap chapter = root.CreateMap("ch1");
SharedText body = chapter.CreateText("body");
body.Insert(0, "Nested text");
});
Selective undo
using Concordant.History;
using var doc = new ConcordantDocument();
using var undo = new UndoManager(doc);
_ = doc.Transact(tx =>
{
SharedText t = tx.GetOrCreateText("notes");
t.Insert(0, "hello");
});
if (undo.CanUndo)
{
UndoResult ur = undo.Undo();
}
Offline merge + persistence boundary
Hosts append after a successful in-memory commit. Memory is not rolled back on a failed append—retry the same update bytes. Recovery loads a checkpoint with ConcordantDocument.CreateFromCheckpoint, then replays the append-log tail via ApplyUpdate.
using Concordant.Persistence;
// After Transact(...):
byte[] delta = doc.EncodeUpdateSince(remoteFrontier);
await appendLog.AppendAsync(delta); // host-owned IConcordantAppendLog
// Compact:
byte[] full = doc.EncodeFullState();
await checkpoints.SaveAsync(new ConcordantCheckpoint(full, stateVectorBytes, coveredLogSequence: tip));
// Recover:
ConcordantCheckpoint? cp = await checkpoints.TryLoadAsync();
using ConcordantDocument recovered = ConcordantDocument.CreateFromCheckpoint(cp!.FullState.Span);
await foreach (ConcordantLogEntry entry in appendLog.ReadFromAsync(cp.CoveredLogSequence))
{
_ = recovered.ApplyUpdate(entry.Payload.Span);
}
See the offline sync guide and the runnable sample samples/Concordant.Quickstart.
Project structure
src/Concordant.Core/ Document kernel & shared types
src/Concordant.Persistence.Abstractions/ Append-log & checkpoint contracts
samples/Concordant.Quickstart/ Durability / recovery demo
tests/ Core, model, persistence, fuzz tests
docs/ Design, ADR, format, guides, policy
benchmarks/ Performance harness docs & projects
.github/workflows/ CI
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Roadmap
- Document kernel with shared text/map/array and nested containers
- Native format v1 codec and transport-agnostic update bytes
- Session-local selective undo
- Persistence abstractions (
IConcordantAppendLog,IConcordantCheckpointStore) - Dual-target packages for
net8.0/net10.0 - Atomic local transactions + indexed pending/YATA paths (
0.1.0-beta.2) - Canonical state-vector encode/decode APIs (
0.1.0-beta.2) - Production storage adapters (target:
beta.3, prefer SQLite) - Reference host recovery/sync sample
- Networking stacks
- Rich text, schemas, presence
- Encryption and ecosystem codecs
- Destructive tombstone GC
See the open issues for a full list of proposed features (and known issues). Pre-1.0 stability notes live in the support policy and compatibility docs. Release history: CHANGELOG.md.
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Documentation
- Changelog
- Design
- ADR 0001: Transactional struct store
- Operation model
- Native format v1
- Security policy
- Security limits
- Offline sync
- Support policy
- Compatibility
- Coverage baseline
- Benchmarks
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Contributing
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
Issues and pull requests are welcome while the project is in early beta. Prefer small, well-tested changes that preserve dual-target (net8.0 / net10.0) behavior and the native v1 wire format.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Restore, build, and test as in Getting Started
- Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Publishing to NuGet.org
Releases are published from GitHub Actions via NuGet Trusted Publishing (no long-lived API keys in the repo).
- On nuget.org as user bmalunes, open Trusted Publishing and create a policy with:
- Owner: you (
bmalunes), or the org that owns the packages - Repository Owner:
malunes0418 - Repository:
concordant - Workflow File:
publish.yml(filename only; corresponds to.github/workflows/publish.yml) - Environment:
nuget(must match the GitHub Environment name below)
- Owner: you (
- Create a GitHub Environment named nuget under Settings → Environments (protection rules can be empty). The
publishjob setsenvironment: nugetso the OIDC token matches the nuget.org policy. - Publish a GitHub Release, or run the publish workflow via Actions > publish > Run workflow.
Don't forget to give the project a star! Thanks again!
<p align="right">(<a href="#readme-top">back to top</a>)</p>
License
Distributed under the MIT License. See LICENSE for more information.
Copyright (c) 2026 Concordant Contributors.
There is no separate third-party notices file in the repository at this time; NuGet packages declare PackageLicenseExpression=MIT.
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Contact
Concordant Contributors — github.com/malunes0418
Project Link: https://github.com/malunes0418/concordant
<p align="right">(<a href="#readme-top">back to top</a>)</p>
Acknowledgments
- Best-README-Template
- YATA — operation ordering inspiration for the document store
- Img Shields
- .NET
<p align="right">(<a href="#readme-top">back to top</a>)</p>
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0-beta.2 | 75 | 7/22/2026 |
| 0.1.0-beta.1 | 63 | 7/19/2026 |
0.1.0-beta.2: atomic Transact, indexed pending/YATA paths, EncodeStateVector APIs, release hardening, and re-baselined performance gates. See CHANGELOG.md and docs/benchmarks.