Skip to content

Roadmap

Last updated: 2026-09-05 · Current release: 1.0.0-beta.3 (2026-09-05)

This page mirrors ROADMAP.md in the repository; if they differ, the repository wins.

Affiant is a .NET framework that turns every AI-proposed database write into an Evidence Card — a per-write review record placed on a Docket, the queue of cards awaiting a human decision — carrying an Affidavit, a per-field record of where each value came from and how confident the framework is in it. It attaches to an agent framework through an adapterSemantic Kernel, Microsoft Agent Framework or Microsoft.Extensions.AI — and two first-party host applications, Meridian and HR Portal (both live public demos), exercise it end to end. See the README and affiant.dev for the full picture.

Items sit in one of four statuses:

  • Now — the current focus: what is in flight and what starts next. At most four items, so the list stays honest. Four items in Now does not mean four in parallel: it is the working set, and items inside it land one at a time.
  • Next — scoped and intended; starts when a Now item finishes or when feedback pulls it forward.
  • Later — direction, not a plan; may change shape entirely.
  • Not planned — decided against, with the reason, so nobody waits for it.

To influence it: open or upvote an issue labelled roadmap, or join GitHub Discussions, now open. Meridian’s public beta is the live feedback source — what it teaches lands here in the next revision.

Where “done” goes: a shipped item moves into Recently shipped below in the same change that ships it. Fine-grained detail lives in the CHANGELOG, under the heading of the release it belongs to, and in GitHub releases once tagged.

No delivery dates, ever: a solo-maintained project cannot promise one without it becoming a promise the maintainer cannot keep. Status — what is being worked on now — is the honest unit of information this page can offer.

  1. The invariant. Every Affidavit field carries provenance, no exceptions; nothing commits without evidence, nothing writes without approval. Enforced by two things at once: the ComplianceHarness — the test harness every .NET adapter must pass — and the conformance suite in affiant-protocol, which has shipped and which every implementation runs. Its 63 fixtures are what each implementation’s parity manifest is read against: the .NET line passes 63 of 63 at the rulebook’s v0.1.2 tag with eleven declared exemptions, and the TypeScript line passes 63 of 63 at that same v0.1.2 tag, exempting the same eleven rules on its own grounds and asserting the identical result on Node, Bun and workerd. Both readings are the ones published on the rulebook’s default branch; the parity snapshots frozen inside the v0.1.2 tag itself were cut before that republish and still name the tag before it.
  2. Field-level, not call-level. Approval of a whole tool call is commodity; Affiant’s unit is the field and its provenance chain.
  3. The honest boundary. Affiant only swears to writes it can intercept in-process. It will not claim otherwise.
  4. Library, not service. Affiant runs inside the adopter’s process. There is no hosted component, no licence server, and no phone-home.
  5. Licensing of what is already published. Every version of every package published to nuget.org is Apache-2.0 and stays Apache-2.0 — that never changes retroactively. Any future change to how new versions are licensed would be announced here before it happened.
  6. Statuses, not dates. This document never carries delivery dates.
  • A reusable Evidence Card: the <affiant-evidence-card> Web Component [evidence-card-ui] — Today both first-party hosts render their own Evidence Card in React — two independent implementations — because the .NET packages ship no UI by design. In scope: @affiant/contract — the typed wire shapes, plus a JSON Schema a host can vendor — and a framework-agnostic Web Component (custom element, Shadow DOM) that renders a card straight from that contract, in any front end or none. A thin @affiant/react wrapper comes after the custom element has proven its shape, not alongside it. The .NET packages still take no UI dependency; this is a separate, optional surface. State: in progress — these are the first artifacts of the TypeScript work below. Links: issue: to be filed; Docket & Evidence Cards, Transport & Wire Contract.
  • A TypeScript implementation, and the rulebook that holds it equivalent [typescript] — Two public repositories. affiant-protocol is the rulebook every implementation is measured against: schemas/ (the wire schemas), INVARIANTS.md (numbered rules, each one testable on its own) and conformance/ (the fixture suite, the runner specification, the driver contract, and the format of the per-implementation parity manifest) — versioned by git tags that every implementation pins, so “which rules does this build satisfy” has an exact answer. affiant-ts is the TypeScript implementation. @affiant/contract and the Web Component above were its first artifacts; @affiant/core exists alongside them, at 0.1.0-alpha.0 and published to npm, built and tested on Node, Cloudflare workerd and Bun from its first commit rather than made portable afterwards. The rulebook’s fixture suite was promoted out of that package byte for byte — the fixtures every implementation is now measured against are the ones the TypeScript package already ran, and the rulebook records the package version and commit they came from, so a renamed fixture cannot silently change what a published parity manifest refers to. @affiant/core goes to npm only once two things are true: a public parity report for the .NET packages exists, and the TypeScript conformance driver is green and merge-blocking in CI. Both are now true. The 1.0.0-beta.3 conformance release (2026-09-05) made the .NET packages pass that same fixture suite — all 63 fixtures at the rulebook’s v0.1.2 tag — and put the attestation record — who or what approved a write — on the Docket entry; its parity manifest declares an empty failing list and eleven rulebook exemptions, itemised under Recently shipped. And affiant-ts runs the driver on all three runtimes in a CI job named conformance, which is a required status check on main: a red run cannot merge. So neither gate stood in the way, and on 2026-09-06 @affiant/core, @affiant/contract and @affiant/evidence-card were published to npm at 0.1.0-alpha.0 under the alpha dist-tag, with SLSA provenance. State: in progress. Links: issue: to be filed; affiant-protocol, affiant-ts.
  • Path to 1.0: stabilise the beta API [stability] — Two of the three releases that come before 1.0 have shipped: 1.0.0-beta.1.1 (2026-09-04), a narrow point release, and 1.0.0-beta.3 (2026-09-05), the conformance release described in the TypeScript item above, whose parity manifest declares an empty failing list. 1.0.0-beta.2, the stabilisation scope listed below, is the one release left before 1.0, which follows once that list is clear. What “stable” will mean is already defined in Versioning & compatibility. 1.0.0-beta.1.1 raised one floor and nothing else: with the stock defaults, a Standing Order written by the book could never auto-approve, because the default risk calculator never returned Low while the default threshold was Low. The fix removed the stock formula — the risk scorer is now host-supplied, and the framework keeps only the comparison. Still in flight for beta.2: conversation-scope isolation when no ConversationId is supplied. Each adapter hands the neutral pipeline whatever service provider it has at hand, and the two sources differ. The Agent Framework and Extensions.AI adapters both read the provider the invoking client attaches to the function-call arguments, which in their documented host wirings is the application root provider, so both resolve the scoped conversation state to one process-global instance shared by every conversation. The Semantic Kernel adapter reads the Kernel’s own services instead, and the documented Semantic Kernel wiring resolves the Kernel from the per-request scope — the tool-authoring guide says in as many words that resolving it from the root provider defeats the isolation, and the shipped samples/quickstart-host injects the Kernel into a SignalR hub, one scope per invocation — so that adapter gets a per-turn fabric by the book. A Semantic Kernel host that resolved a root Kernel would share the defect. Where the defect does land it is not one backend’s quirk: the fallback that then keys inference idempotency on the shared object’s identity lives in the core, not in any adapter. The fix is per-turn scoping at host wiring — one fix that holds on every backend, not three per-adapter ones. Setting a ConversationId per conversation narrows the idempotency half rather than closing it: at the Extensions.AI seam the function-calling client of Microsoft.Extensions.AI 10.9.0, the version that adapter pins, re-derives that identity from each provider response, so against a provider that returns none the host’s id reaches every tool call of the turn’s first round and the fallback keys the rest. Also in flight for beta.2: SQLite/PostgreSQL store parity gaps, the review-outcome state machine (a card the approval-policy chain refers to a named reviewer today files Pending carrying a RequirementNotImplemented marker and refuses every decision on it; a reviewer’s own decision is approve or reject, and referral’s own semantics remain roadmap work), a test-isolation flake, and one removal already announced in the CHANGELOG — IDeterministicFieldSource, [Obsolete] today, removed no earlier than beta.2. Trust the invariant; expect the API to move until 1.0 — this is exactly what is moving. State: in progress. Links: affiant#41, affiant#33, affiant#34, affiant#37, affiant#17; issues: to be filed (referral outcome; the risk floor).
  • Evidence Card amendments: correct a field before approving [review] — A reviewer can edit a proposed value on the card before approving; the correction is recorded with the reviewer’s own provenance — UserStated at 1 for a value they set, Empty at 0 for one they cleared, both bound to the reviewer’s act on the entry — and the round-trip is part of the wire contract. The framework-side round-trip shipped in 1.0.0-beta.3, so this is no longer a deferred fast-follow: AffidavitAmendments.Apply is the single implementation of what an accepted correction does to the record — the reviewer’s tag goes on top of the field’s provenance chain with a ReviewerAct binding rather than merging into it, the machine’s displaced tag stays readable beneath it, a cleared field is resolved against the field rather than pasted over (a mandatory one stays on the card visibly empty, an optional one leaves the write), and all three confidence numbers are recomputed over the amended fields, so a card no longer reports the model’s pre-correction confidence after a person corrected exactly what the model got wrong. The gate hands the result back on ReviewOutcome.Approved.AmendedAffidavit, and the Docket entry keeps it. What remains is downstream of the framework: hosts that still fold the amendments themselves instead of using that Affidavit — both first-party demo hosts and the quickstart sample — which is a second, drifting copy of a merge the gate has already performed. Links: affiant#63, affiant#99.
  • An Affiant MCP server [adapters] — Expose the Docket and the approve/reject decision as MCP (Model Context Protocol) tools, so agents that are not written in .NET can route their writes through the same review gate. Framed as exploring: cheap to try with the official C# MCP SDK, and whether anyone wants it is exactly what Discussions is for. It reaches agents that want to use a Docket an Affiant host already runs; the TypeScript implementation in Now reaches teams that want to be that host. Links: issue: to be filed.
  • Adapter parity and the Semantic Kernel host gap [adapters] — All three adapters — Semantic Kernel, Microsoft Agent Framework, Microsoft.Extensions.AI — are gated by the same ComplianceHarness parity suite, but no first-party host exercises the Semantic Kernel adapter live: Meridian runs on Agent Framework, HR Portal on Extensions.AI. A community reference host on Semantic Kernel is welcome (help wanted). Post-1.0, folding Affiant.AgentFramework onto Affiant.Extensions.AI so there is one interception surface is a decision pending, not scheduled. Links: affiant#39; Interception Backends, The Compliance Harness.
  • Evidence for auditors, part 1: crosswalks [auditors] — A possible set of informational mappings — not compliance claims — from Affiant’s records (Evidence Card, Docket, Affidavit, the retained decision log) to what named regimes ask a deployer to evidence: the NIST AI Risk Management Framework and its Generative AI Profile (NIST AI 600-1), both free text and voluntary; and EU AI Act Articles 14 (human oversight), 12 (record-keeping) and 26 (deployer obligations, including keeping logs for at least six months). Under Regulation (EU) 2026/1744 (in force 2026-07-27), the Annex III high-risk obligations apply from 2027-12-02 and Annex I from 2028-08-02 — stated here as external legal fact, not an Affiant delivery date. Wording throughout: “maps to” or “could evidence”, never “compliant with”. Links: issue: to be filed; NIST AI RMF, NIST AI 600-1, EU AI Act Article 14, Article 12, Article 26.
  • Evidence for auditors, part 2: attestation export and retention [auditors] — A signed, portable export of a Docket’s Evidence Cards and Affidavits — a file an adopter hands to an auditor, not a hosted service — plus retention configuration so a deployer can meet a stated log-retention duty. ISO/IEC 42001 and SOC 2 mappings are on the table to evaluate; both attach to the adopting organisation’s management system or service audit, not to a library — Affiant will never claim to “be” certified. Links: issue: to be filed.
  • Review policies: multi-step and multi-party review [review] — Two review shapes run today: a person’s decision on a card, and a Standing Order — an auto-approval rule a host wrote in advance — which approves with nobody present and is attested as Attestor.StandingOrder, naming the policy and its version on the record. Two further requirement levels are declared and deliberately not run: MultiParty (more than one approver) and ReferralRequired (escalation) are recorded verbatim on the entry, which files Pending carrying a RequirementNotImplemented marker and refuses every decision on it — a level the framework cannot honour blocks rather than quietly collapsing onto one person’s single click. Sequential steps have a type (ReviewStep) and no implementation. Direction: real semantics for each of the three, then code. Links: issue: to be filed.
  • Synchronous (blocking) review mode [review] — A mode where the agent waits for the decision inside the tool call. The naive version deadlocks over a single SignalR connection (the real-time transport Affiant ships); the sound design needs a decision channel separate from the blocked connection, and no implementation is planned until the design settles. Links: affiant#29.
  • Provenance integrity [stability] — Harden source attribution so a field can never be attributed to the wrong tool. This sharpens the core claim (“sworn”); it is not a defect being fixed. What an Affidavit’s AggregateConfidence measures is settled and no longer on this list: rule AF-2 of the rulebook defines it normatively — the minimum over every proposed field’s current provenance tag, an Empty field counting as 0, so it reads 0 exactly when some proposed field has unknown provenance — and 1.0.0-beta.3 (2026-09-05) made the shipped projection compute that minimum in place of the mean it computed before. It is tested on both sides: ten unit facts over the three numbers in Affiant.Abstractions.Tests, and seven conformance fixtures that assert AF-2 across the gate, sequence and canonical suites — AF-2 is not among the eleven rules the .NET parity manifest exempts, so those fixtures are run rather than waived. What stays undefined is deliberate rather than pending: neither the rulebook nor a core package sets a threshold on any of the three numbers. A host policy floor predicates on PopulatedConfidence and EmptyFieldCount, never on the aggregate, which is the safety number a fixture pins. Links: issue: to be filed; conformance/parity/dotnet-v0.1.json, CHANGELOG.
  • Provider failover in the framework, for all three adapters [stability] — Normative Rule 5 promises graceful degradation when a provider fails. Today the Semantic Kernel adapter ships the configuration shape for a primary/secondary provider pair (AffiantProviderConfiguration, ProviderPair) and the core declares a degraded-mode counter (affiant.provider.degraded) for a host to record; nothing in the framework watches for an outage or swaps providers, so the failover itself is the host application’s, and the Agent Framework and Extensions.AI adapters carry no provider-pair shape at all. Direction: first-class failover executed inside the framework, the same on all three adapters. Links: issue: to be filed.
  • Observability contract [stability] — Document the affiant.* OpenTelemetry attributes and activities as a stable, versioned contract. Links: issue: to be filed.
  • dotnet new template [on-ramp] — A project template that scaffolds a wired host — DI, one read tool, one write tool, transport, card — so that the shape samples/quickstart-host demonstrates is generated rather than copied by hand. Links: issue: to be filed.
  • Intercepting hosted / provider-side tools — Tools the provider runs outside the host process (hosted MCP, code interpreter, web search) never reach the in-process tool call each of the three adapters wraps, so no Affiant filter or middleware runs and Affiant cannot swear to writes it never sees. This is a boundary, not a backlog item — see The Honest Boundary. Keep such writes read-only, or route them through a reviewed path.
  • A LangChain (tryAGI) adapter — Researched: there is no pre-execution interception seam in that stack. Would be revisited only if the stack gains a seam.
  • A hosted Affiant service (SaaS console or evidence vault) — Affiant is a library that sits in an adopter’s write path; a hosted service in that path would need 24/7 operation the project cannot promise. The attestation export planned in Later covers the auditor need without a service.
  • A hand-translated second codebase — but TypeScript is now being built, held equivalent by a shared rulebook — Hand-porting the framework into another language stays not planned, and Python stays not planned: two codebases kept in step by eye drift, and the drift stays invisible until a write slips past the gate on one of them and not the other. A second implementation is worth its maintenance cost only if something other than eyes holds it equivalent — published wire schemas, numbered testable invariants, a fixture suite both implementations pass in CI, and a published per-implementation parity manifest stating exactly which fixtures each one passes and which it does not. That rulebook is what is being built (see Now), and with it the cost of the second implementation is bounded by fixtures rather than by re-reading two codebases by hand. The alternative is worse than the cost: without it, every TypeScript host that wants these guarantees re-implements the review gate itself, once per team, with nothing to check the result against.
  • Relicensing existing versions — Every published version stays Apache-2.0 forever; see What will not change.
  • 2026-09-05 — 1.0.0-beta.3: the conformance release. The .NET packages pass all 63 fixtures at the rulebook’s v0.1.2 tag, so the parity manifest declares an empty failing list. Eleven rulebook rules are exempted rather than fixture-checked — SR-5, CV-2, CV-3, CV-5, AF-5, SR-3, RT-1, RT-2, RT-3, TL-1 and TL-2 — each recorded in conformance/parity/dotnet-v0.1.json with its reason and, where there is one, what is checked in its place; five of the eleven say plainly that no substitute check exists yet. RT-1 is the rule that a core package be runtime-neutral, and the exemption for it says in as many words that this implementation claims one runtime — net10.0 — and that the manifest names that one. The release also ships the compliance harness’s fixture runner (Affiant.Testing.ComplianceHarness.ConformanceSuite), so a host’s own compliance tests run the same rulebook suite the framework runs, and puts the attestation record — who or what approved a write — on the Docket entry. Release, CHANGELOG.
  • 2026-09-05 — The on-ramp shipped: a runnable sample host, and a Quickstart that ends at a rendered card. 1.0.0-beta.3 ships samples/quickstart-host — one domain (leave requests), one read tool, two write tools (request and amend), SQLite behind the domain rows, an in-memory Docket, and the <affiant-evidence-card> Web Component served from the host’s own wwwroot/. The two stores are deliberate and the sample says so in place: it registers the SQLite store first and the in-memory Docket store last, so the in-memory one is the one that resolves; a host that wants review state to survive a restart drops that last argument and lets the SQLite store stand. Run it, open the URL it prints, and the last thing on screen is the thing the framework exists for: an Evidence Card in a browser tab, one row per field, each row naming where its value came from — approve it, amend a field first, or reject it, and only then does a row appear in the database. A development-only seam files the same proposal with one curl, so the whole review lifecycle is reachable with no model key. The Playwright deck in the sample’s e2e/ declares eight specs — approve, reject, typed inputs, a live-data picker, the mandatory-field gate, the expiry lifecycle, a late decision whose amendments survive into a resubmission, and a re-broadcast card absorbed rather than redrawn — which the sample’s README frames as seven review behaviours plus one page behaviour. Seven of the eight pass at 1.0.0-beta.3. The late-amendments spec is the one that does not, and it stops at its own setup assertion rather than at the behaviour it was written for: it requires the entry to still read Pending past the deadline, and this release projects expiry onto every read, so the row already reads Expired before the late click lands. The Quickstart is that sample’s code step by step — including how a field gets its value, from the field schema a domain declares to the host-supplied projection that stamps an update-shaped write with its entity id and each field’s current value — and it ends at that card.
  • 2026-09-04 — 1.0.0-beta.1.1: the risk floor fix. With the stock defaults a Standing Order written by the book could never auto-approve, because the default risk calculator never returned Low while the default threshold was Low; the stock formula is removed, so the risk scorer is now host-supplied and the framework keeps only the comparison. Release, CHANGELOG.
  • 2026-09-04 — Front door for contributors shipped: CONTRIBUTING.md, SECURITY.md (a disclosure path), CODE_OF_CONDUCT.md, and issue and pull-request templates, alongside GitHub Discussions and the roadmap label. Discussions, open roadmap issues.
  • 2026-08-27 — HR Portal public demo went live at hrportal.affiant.dev — a second adapter (Microsoft.Extensions.AI), a second domain, the same guarantees. Try it live.
  • 2026-08-26 — Meridian public demo went live at meridian.affiant.dev. Try it live.
  • 2026-08-23 — 1.0.0-beta.1: first public release, ten co-versioned packages, three adapters. Release, CHANGELOG.
  • 2026-08-20 — Affiant.Extensions.AI: the Microsoft.Extensions.AI adapter joined the set. CHANGELOG.
  • 2026-07-05 — Affiant.AgentFramework: the Microsoft Agent Framework adapter joined the package set. FAQ.

Each Now / Next / Later item carries a bracketed theme tag, so a reader can follow one thread through the sections. The tags in use today:

[stability] [on-ramp] [evidence-card-ui] [typescript] [adapters] [review] [auditors]