Table of Contents

AsiBackbone 7.0.0 Release Notes

Release date: 2026-09-26

Summary

7.0.0 is a major release for the AsiBackbone package family. It strengthens acknowledgment actor binding, capability-grant execution binding, typed-artifact verification, and DLP fail-safe defaults. Two of those corrections change stable contracts: response-actor binding and the DLP enum value changes. The release also completes the 6.0 naming work by renaming the compatibility names that 6.0 retained, and renames five Entity Framework Core columns and one JSON property name to match.

Package IDs and the net10.0 target remain unchanged. Four namespaces and the retained AuditResidue*, LiabilityHandshake*, Handshake*, and CapabilityToken* types and members are renamed, with no [Obsolete] forwarding aliases. Signed and telemetry contracts keep their 6.x values: canonical artifact tags, signed payload bytes, OpenTelemetry event and attribute names, EF Core table names, reason codes, diagnostic IDs, and the AddAsiBackbone* registration methods are unchanged. JSON produced by serializing the renamed types uses the new property names, so auditResidueId becomes decisionReceiptId.

The GovernanceOutboxDrain and GovernanceOutboxDrainHostedService constructors are replaced by signatures with an optional trailing TimeProvider parameter. Assemblies built against 6.x must be rebuilt, and most consumers need source changes for the renames. AssemblyVersion advances to 7.0.0.0; package and file versions advance to 7.0.0 and 7.0.0.0 respectively.

Consumers moving from 6.x must follow the Upgrade from 6.x to 7.0 guide. Hosts that use AsiBackbone.EntityFrameworkCore must add and review a database migration before deploying, and hosts that store or parse decision receipt JSON must update for the new key.

Breaking changes

Acknowledgment responses are bound to the challenged actor

IAcknowledgmentChallengeService.HandleResponse now verifies that the responding actor is the actor the challenge was issued to before producing an AcknowledgmentResponse.

Previously the response was validated only against the handshake identifier and the required acknowledgment code, so any actor that could name an active challenge could satisfy a challenge issued to a different actor, and the resulting acknowledgment recorded whichever actor answered rather than whoever was challenged.

The actor argument must now match both the ActorId and the ActorType recorded by CreateChallenge. A mismatch returns a failed result carrying the new acknowledgment.challenge.actor_mismatch reason code, and no acknowledgment is created. A single reason code covers both comparisons so a caller cannot use the failure to determine which component differed.

Hosts that resolve the current actor per request must resolve the same principal on both legs of the round trip.

Challenge creation and response handling also require a known, authenticated actor whose type is not Unknown and whose identifier is not the shared "unknown" sentinel. An insufficient binding fails as acknowledgment.challenge.actor_unbound; endpoint governance returns 403 without issuing a challenge. A configured unauthenticated display name does not create a distinct identity. Hosts that deliberately establish another binding must provide a distinct, authenticated actor context through their actor resolver and document the binding's security properties.

This change does not add challenge expiry or single-use enforcement. Bounded challenge lifetime, revalidating authorization, and revalidating current policy before the consequential operation remain host responsibilities.

DLP classification enums no longer default to a permissive value

DlpFailureBehavior and DlpIntentRiskLevel each gained an Unspecified member at zero, shifting every other member up by one.

Previously DlpFailureBehavior.Allow and DlpIntentRiskLevel.Low occupied the zero slot, which is the value a .NET enum takes when it is never assigned. An unset property, an absent configuration value, a deserialized payload that omitted the field, or a database column default therefore resolved a screening failure to the most permissive outcome available. A governance policy that was never fully configured failed open, and nothing reported it.

Member 6.x value 7.0 value
DlpFailureBehavior.Unspecified — 0
DlpFailureBehavior.Allow 0 1
DlpFailureBehavior.WarnAndAllow 1 2
DlpFailureBehavior.Deny 2 3
DlpFailureBehavior.Defer 3 4
DlpFailureBehavior.RequireAcknowledgment 4 5
DlpFailureBehavior.Escalate 5 6
DlpIntentRiskLevel.Unspecified — 0
DlpIntentRiskLevel.Low 0 1
DlpIntentRiskLevel.Medium 1 2
DlpIntentRiskLevel.High 2 3

Supplying Unspecified now raises ArgumentOutOfRangeException rather than resolving to a behavior. DlpFailurePolicyContext.Create rejects an unassigned risk level, DlpFailurePolicyOptions.GetBehavior rejects an unconfigured risk-tier behavior or BehaviorOverrides entry, and DlpFailurePolicyResolution.Create rejects an unresolved behavior.

Source that refers to these members by name is unaffected. Consumers that persisted, serialized, or transmitted the numeric values must remap them, because enum constants compiled against 6.0.0 retain the previous numbers.

Retained 6.0 compatibility names are renamed

6.0 renamed most of the public surface but kept a set of names for compatibility and planned to remove them at the next major version. 7.0 renames them directly. The renames are mechanical: behavior and validation are unchanged, and signed contract values keep their 6.x form. JSON property names follow the renamed properties, as described below.

Area 6.x 7.0
Namespaces AsiBackbone.Core.Handshakes, AsiBackbone.AspNetCore.Handshakes AsiBackbone.Core.Acknowledgments, AsiBackbone.AspNetCore.Acknowledgments
Namespaces AsiBackbone.Core.CapabilityTokens, AsiBackbone.Storage.InMemory.CapabilityTokens AsiBackbone.Core.CapabilityGrants, AsiBackbone.Storage.InMemory.CapabilityGrants
Acknowledgment types LiabilityHandshakeRequest, LiabilityHandshakeAcknowledgment, LiabilityHandshakeRiskLevel AcknowledgmentRequest, AcknowledgmentResponse, AcknowledgmentRiskLevel
Endpoint metadata RequireLiabilityHandshakeAttribute, IEndpointLiabilityHandshakeMetadata RequireAcknowledgmentAttribute, IEndpointAcknowledgmentMetadata
Capability grants CapabilityTokenGrant, CapabilityTokenValidationCategory CapabilityGrant, CapabilityGrantValidationCategory
Persistence entities HandshakeRequest*Entity, HandshakeAcknowledgment*Entity AcknowledgmentRequest*Entity, AcknowledgmentResponse*Entity
Decision receipt members AuditResidueId, WithAuditResidueId, FindByAuditResidueIdAsync, CanonicalArtifactTypes.AuditResidue, GovernanceEmissionEventType.AuditResidue, AuditResidueCreatedEventName DecisionReceipt* equivalents

GovernanceEmissionEventType.DecisionReceipt keeps the numeric value 500. Consumers that persist that enum by name must map stored "AuditResidue" values. See Legacy compatibility names are renamed for the complete inventory and the contracts that do not change.

Canonical signing payloads are a deliberate exception to that name migration. Canonical v1 retains the 6.0 wire string "AuditResidue" for event type 500, so a 6.0 governance-emission payload reconstructs to the same bytes and hash under 7.0. All enum-derived signed fields now use explicit stable mappings rather than CLR Enum.ToString(): actor type, lifecycle stage, emission event type, governance decision and constraint outcomes, emission/outbox status, and governed-operation persistence outcome. This includes lifecycle-derived decisionStage and typed receipt outcome construction paths.

Entity Framework Core columns are renamed

Five columns are renamed to match the renamed properties. The dependent indexes and foreign keys are renamed with them; table names are unchanged.

Table 6.x column 7.0 column
AsiBackboneAuditLedgerRecords AuditResidueId DecisionReceiptId
AsiBackboneAuditResidueLifecycleEvents AuditResidueId DecisionReceiptId
AsiBackboneGovernanceOutboxEntries EnvelopeAuditResidueId EnvelopeDecisionReceiptId
AsiBackboneHandshakeRequestMetadata HandshakeRequestId AcknowledgmentRequestId
AsiBackboneHandshakeAcknowledgmentMetadata HandshakeAcknowledgmentId AcknowledgmentResponseId

Hosts own their migrations. Add one after upgrading and confirm that it renames these columns rather than dropping and re-adding them, which would delete the existing data. The reference migration lists every operation for Up and Down.

Decision receipt JSON uses decisionReceiptId

System.Text.Json names JSON properties after the C# property names, so JSON produced by serializing DecisionReceipt, AuditLedgerRecord, or GovernanceEmissionEnvelope now uses decisionReceiptId where 6.x used auditResidueId (DecisionReceiptId and AuditResidueId with default serializer options). Canonical signed payloads use explicit key names and are unaffected.

Consumers that read this JSON must use the new key. Stored 6.x JSON deserialized into a 7.0 type comes back with DecisionReceiptId set to null, because unrecognized members are ignored by default, so stored documents must be migrated or translated when read. See Decision receipt JSON uses decisionReceiptId.

Additional changes

  • Security: capability-grant execution-boundary validation now compares the signed grant's subject and operation with normalized host expectations. CreateBoundExecutionBoundary requires CapabilityGrantBindingExpectations; mismatches fail closed with stable subject- or operation-mismatch results. The retained CreateExecutionBoundary factory is obsolete and continues to fail closed.

  • Security: challenge creation and response handling reject unknown, unauthenticated, Unknown-typed, and shared "unknown" actors with acknowledgment.challenge.actor_unbound.

  • Security: GovernanceArtifactVerifier.VerifyTypedAsync authenticates a typed artifact by rebuilding its canonical payload before signature verification, closing the gap between an authentic retained payload and an unrelated supplied object.

  • Interoperability: canonical JSON v1 is now documented as the normative asibackbone.canonical-json.v1 format and has expanded golden vectors. The NCAT audit-completion adapter replays NCAT's pinned versioned contract vectors without adding a packaged or compile-time dependency between repositories.

  • Fixed: EF Core claim acquisition restates eligibility in the update so a waiting SQL Server or PostgreSQL worker cannot overwrite another worker's newly acquired claim.

  • Tooling: the repository-pinned DocFX tool is updated to 2.81.0.

  • Fixed: EfCoreGovernanceOutboxStore claim transitions no longer silently do nothing when the entry was enqueued through the same DbContext. Previously MarkClaimDeliveredAsync left such an entry Pending, so it could be re-claimed and emitted again after the lease expired.

  • Fixed: LocalDevelopmentSigningService creates its key with RSA.Create(int) and reports a provider-unsupported key size as InvalidOperationException.

  • Added: AcknowledgmentChallengeResult.CanProceed, which is true only for a handled acceptance. Succeeded is also true for a handled refusal.

  • Added: TimeProvider support in GovernanceOutboxDrain, GovernanceOutboxDrainHostedService, and LocalDevelopmentSigningService, resolved from dependency injection when registered.

  • Changed: local-development signing registration captures a snapshot of its options, and the outbox drain and worker constructors gained an optional TimeProvider parameter.

See Other changes that affect hosts for the migration details.

Why this required a major release

The repository's API compatibility and SemVer contract treats a change to a public enum value, and the renaming of a public type, member, or namespace, as affecting a stable package contract. The 6.x line also pins AssemblyVersion at 6.0.0.0 for every compatible release, so a consumer compiled against 6.0.0 binds the same assembly identity regardless of package version. Shipping the renumbering on 6.x would have let that consumer load a library that reinterprets the constants the compiler already inlined into its own assembly, with nothing in the assembly identity to signal the change.

The 6.0 public API naming record planned to deprecate the retained compatibility names during 6.x and remove them at the next major version. Because 7.0 is that version, they are renamed directly.

Validation

Package validation continues to run against the 5.1.0 baseline so the complete 5.1.0-to-7.0.0 compatibility surface remains checked. The intentional enum value changes and the type, member, and namespace renames are recorded as exact suppressions in each affected package's CompatibilitySuppressions.xml; all other package compatibility checks remain enabled. The committed public API baselines under eng/api-baseline/ record the new enum values, the added members, and the renamed surface. The EF Core model is checked so that the only schema differences from 6.x are the five documented column renames and their dependent indexes and foreign keys.