Repository navigation
Releases: doka-labs/Doka.EntityFrameworkCore.SafeMigrations
Release list
SafeMigrations 10.6.0
Version 10.6.0 updates all five packages. This minor release adds public
searched-CASE expressions, certified generated-column/CHECK support,
lossless signed-integer upgrades and authorized release lines. It corrects
ordered column/index/DROP proofs and deep-expression traversal, reduces measured
allocations, and updates the qualified dependency baseline. Captured
computed/CHECK contract fingerprints can change: review and renew affected
approval artifacts before use, without rewriting historical migration source
or bypassing mismatch checks. See the
upgrade notes.
Timing evidence is informational.
Added
- Qualify explicit lossless signed-integer widening on MySQL/MariaDB and
PostgreSQL underRepairIfSafe, with exact native source, unchanged ancillary
facets and provider-specific storage/dependency checks. Keep narrowing,
unsigned conversion, generated values and unproven sources outside this path. - Add immutable searched-CASE expressions and bounded EF computed-column SQL
capture. Preserve ordered conditions/results, optional ELSE, typed
two-argument SQL Server CONVERT and complete expression traversal instead of
retaining supported generated expressions as opaque SQL. Keep unsupported
grammar and provider-specific type, determinism, storage and index gates
fail-closed. - Retain validated original computed/CHECK SQL and numeric-token provenance
alongside its parsed structure. Native DDL, comparison and fingerprints do
not silently replace provider literal typing with CLR-derived casts.
Preserve dialect provenance and reject uncertified quoting, function/type
roles or lossy native catalog displays instead of trusting arbitrary SQL. - Support required MariaDB and SQL Server generated results only through
separate bounded semantic non-null proofs while retaining their actual
native nullable metadata. Verify supported operand/type bindings without
application-row scans; do not inject defaults, helper CHECKs or persistence.
Qualify PostgreSQL generated CASE operands against supported native built-in
types and SQL Server computed columns/indexes against native compilation,
physical metadata and effective session requirements.
Changed
- Pin every repository-defined GitHub-hosted Linux job to the x64
ubuntu-26.04image,
including qualification, publication, dependency review and maintenance.
Keep the .NET 10 SDK selection, engine images, timeouts and performance
budgets unchanged. Retain actual historical measurement attribution and
require complete hosted qualification rather than treating local ARM checks
or the label change as new native evidence. - Support explicitly authorized release lines through the existing five-package
pipeline, with branch-owned qualification, qualification-only execution,
current protected-main publication authority and exact same-run recovery.
Serialize publishers across lines and retain monotonic stable Latest,
historical provenance and the existing thirteen public release assets.
Extend registered-line PR checks and active-line scheduled qualification,
dependency targeting and transitive vulnerability audits. Keep only main/10
active, maintenance/10.x inactive and the .NET 10 toolchain unchanged. - Change contract fingerprints for successfully parsed EF computed-column and
CHECK definitions by retaining their original SQL spelling and numeric-token
provenance. Review affected migration artifacts, regenerate their stored
SafeMigrationContractFingerprintvalues and reapprove them before use; do
not reuse earlier approvals, disable mismatch checks or rewrite historical
migrations. Ordinary SQL defaults, opaque/unparsed expressions, explicit
uncaptured definitions and provider-owned operation fingerprints retain
their existing encoding; this is not a relational model-fingerprint format
change. - Retain exact authored spelling when comparing parsed CHECK definitions.
Whitespace or redundant-parenthesis differences can therefore be
Different, notUnsupported, even when their parsed trees agree.
Computed-column source was already compared exactly and remains ineligible
for automatic repair when that source differs. Review the intended authored
contract; provider-certified native catalog normalization does not make
arbitrary source changes equivalent or authorize a policy bypass. - Raise the MySQL/MariaDB provider's published Doka dependency to
[10.6.2,10.7.0)and qualify against public 10.6.2. Its complete physical
index-budget convention can change implicit indexed string/binary lengths;
review newly scaffolded model differences without rewriting existing
migrations. Retain the public migration SPI and other providers' dependency
isolation. Doka's transitive System.IO.Hashing minimum becomes 10.0.13.
The 10.6.2 floor also preserves explicit GUID SQL defaults through provider
model differences and scaffolding instead of layering implicit client GUID
generation over them. Explicit application generation choices and historical
migration metadata remain authoritative. It includes GUID-default metadata
fixes for secondary Entity Splitting tables and shared defaults; no historical
migration rewrite, GUID storage conversion or schema migration is implied. - Reject captured native expressions whose identifier keywords, cast targets,
function/operator bindings, dialect roles or catalog identity cannot be
proved. Pending operations previously accepted through weaker assumptions
can now be classifiedUnsupported; do not treat every refusal as invalid
native SQL or bypass it with another policy. MySQL/MariaDB generated clocks
remain outside the deterministic product contract, including MariaDB virtual
forms that native SQL permits. Ordinary clock defaults remain unchanged.
Preserve native source-dependency restrictions on MySQL generated-column
renames and SQL Server CHECK/computed dependencies instead of reporting a
projected rename as safe before a native refusal. - Reject source-column removal while a generated dependent survives, before
target DDL. Keep explicit dependent-first removal, unrelated removals and
missing-source no-ops; never cascade generated columns automatically.
Unproved dependency evidence remains unsupported. This also
prevents PostgreSQL 14's native automatic removal of a generated dependent.
On MySQL, a pending DROP can now be unsupported when its owner has generated
members but neither a complete operation-bound model candidate nor an earlier
explicit generated contract can be certified against native metadata.
PostgreSQL repeats the DROP classifier under an explicit owner lock; missing
lock authority, stale runtime snapshot semantics or an inherited/partition
hierarchy remains unsupported without changing rights or isolation. - Raise EF Core and dependency-injection minimums to 10.0.13; these are visible
in published NuGet dependency contracts. Update the SDK to 10.0.402,
dotnet-ef to 10.0.13, FsCheck.Xunit to 3.6.0, Microsoft.NET.Test.Sdk to 18.11.0,
xUnit's Visual Studio runner to 4.0.1, Scorecard to 2.5.0 and CodeQL to
4.39.1. Refresh qualification image patches/digests within every existing
MySQL/MariaDB, PostgreSQL and SQL Server series, and synchronize local defaults
and tooling. Preserve .NET 10 and the qualified runner contract; keep product
version selection separate from dependency maintenance. - Lock the SQL Server graph to SqlClient 6.1.7 and SNI.runtime 6.0.3. Retain
the patched PKCS 9.0.21 minimum and provider dependency isolation. Update only
the existing exact-version SNI license exception after confirming identical
vendor license bytes; do not broaden its development/testing or no-bundling
boundaries. - Use MariaDB 12.3.3 for local integration and design-time defaults and the shared
CI coverage/tooling engine. Retain explicit overrides and every existing
supported engine matrix cell without changing consumer configuration. - Organize provider and Core responsibilities into same-type partials with
repository-owned IDE nesting. Separate independent test contracts while
retaining shared container lifetimes, isolated database ownership and
migration/replay scenarios. - Reduce prerequisite, MySQL/MariaDB backfill, PostgreSQL data-probe and repeated
SQLite model-artifact construction allocations without changing SQL, policy,
report, history or proof-lifetime contracts. Performance timing remains
informational; source-bound attribution is documented in CONTRIBUTING.
Fixed
- Preserve SQL Server Unicode literal contents through native line-continuation
parsing, including catalog identities and nested dynamic statements. Retain
exact object names and reject real default drift instead of matching a
continuation-collapsed alias. Bind expression-valued procedure arguments
through private variables. Preserve valid schema and rename baselines for
line-bearing names without changing ordinary literal fast paths or
schema-transfer semantics. - Reuse already compiled migrations for every shared provider bundle build.
Avoid a non-RID locked restore after an earlier RID publish changes copied
lockfiles, without disabling CI lock validation or changing source locks. - Preserve SQL Server guarded payloads through EF's line normalization,
continuations, GO handling and idempotent indentation. Cover exact authored
long CRLF defaults, quoted identities, managed-data mutation and replay while
retaining private scopes, strict drift checks and the ordinary fast path. - Preserve exact PostgreSQL multiline literals through guarded baseline SQL
and EF's idempotent history framing. Keep generated CASE catalog comparisons,
defaults, comments, backslashes and dollar-delimiter payloads unchanged across
real script execution and replay, without normalizing expressions or relaxing
mismatch rejecti...
SafeMigrations 10.5.0
Prepare stable 10.5.0 for all five packages. This release adds actionable
diagnostics, optional MariaDB native UUID support through Doka 10.5, exact
persisted-default checks and isolated parallel provider tests. Existing
migration source, policies, fingerprint formats and history remain
unchanged. Consumers must account for new report schemas, owned MySQL/MariaDB
exception transport, the Doka dependency floor and default reclassification
described below. Source preparation is not publication evidence: the complete
hosted/native matrix, coverage, tooling, five primary/symbol pairs, provenance,
SBOM and public readback remain required. Timing comparisons are informational.
Added
- Support opt-in MariaDB native
uuidcolumns through Doka 10.5, including
16-byte row/index budgeting, keys, foreign keys and model-managed Guid data.
Keep unsupported engines, index prefixes and implicit GUID storage conversions
rejected; existing Binary16 and Char36 defaults are unchanged. - Add shared, bounded operation identity and human-readable diagnostics across
SafeMigrations failures. Include authored schema/table/member, FK principal,
rename endpoints, known operation/migration context, established reason and
corrective guidance without new data scans or automatic preflight. - Add assessment owner identity and explanations to canonical report schema 4
and filtered view schema 3; retain older packaged schemas and existing code,
fingerprint, objectName, ordering and selection semantics. Add streaming
SafeMigrationReportTextsummaries with explicit total and omitted counts.
Update schema validators and rebuild consumers of the compiled
SafeMigrationRunReport.CurrentSchemaVersionconstant; existing public
signatures remain available.
Changed
- Raise the MySQL/MariaDB provider's Doka dependency to
[10.5.0,10.6.0)and
lock qualification to published 10.5.0. Native UUID remains explicit and
requires MariaDB 10.7 or later within the qualified engine matrix. Doka also
changes implicit application-owned 16-byte binary mappings tovarbinary(17);
consumers must review newly scaffolded schema changes rather than treating
this dependency update as an automatic data or storage-format migration. - Reassess existing default identity exactly. MySQL generated string defaults
containing backslash, quote, NUL, newline, carriage return or Ctrl-Z no longer
qualify as matching merely from their SQL-mode-dependent display. Strict
ThrowIfDifferentcan therefore reject previously accepted defaults; an
otherwise eligible explicit default-onlyRepairIfSafeoperation can replace
their serialization without changing existing rows. Structured function
defaults now match the engine's compact argument separators. Exact binary
checks can also reject previously accepted truncated MySQL prefixes or
ambiguous legacy MariaDB text. Review such differences explicitly; this update
does not rewrite historical migrations or broaden repair permissions. - Translate only positively correlated MySQL/MariaDB owned runtime assertions
intoSafeMigrationExecutionException, preserving the exact native cause
after Doka cleanup. Consumers catching those assertions asMySqlException
must handle the new typed failure. Ordinary native errors, cancellation and
provider recovery failures remain unchanged. Generated scripts emit bounded
diagnostic results before their native assertion. - Enrich PostgreSQL, SQL Server and SQLite guard messages while retaining
native guard identities, SQLSTATEs/error numbers, scope ownership and rollback
contracts. Improve setup, scaffolding, model-contract and internal-invariant
guidance without changing decisions or inferred migration history. - Remove row identifiers from SQLite-authored foreign-key integrity diagnostics;
display only bounded structural ownership and relationship context. - Run independent provider test classes against assembly-owned containers and
isolated databases instead of serializing large partial suites or starting
a server per class. Share runner configuration with Rider and CLI, release
test-owned resources promptly, and isolate only process-wide observers and
measurements. Preserve test coverage, native platform boundaries and required
qualification; elapsed-time comparisons remain informational.
Fixed
- Preserve exact string-default bytes across MySQL/MariaDB table reopening and
SQL-mode changes. Render known structured string defaults and literal TEXT
defaults through UTF-8 hex conversion before native create/add/alter/repair
generation, and compare the persisted expression exactly. Keep opaque SQL,
GUID/numeric/temporal mappings and existing repair capability boundaries
unchanged. - Validate MySQL binary literal defaults against their exact native value,
not catalog text truncated at NUL. Preserve literalDEFAULT(column)
semantics, qualify native probes before binding identifiers and refresh
operation-local evidence after DDL without scanning table rows. Keep exact
generated-expression identity separate from literal defaults and clear
acquired proof state on failure or cancellation. Preserve MariaDB defaults
through binary hex conversion, including older catalogs that otherwise
serialize escaped or lossy text. Do not confuse a real question mark with
non-UTF-8 bytes replaced by legacy catalog conversion.
SafeMigrations 10.4.11
Prepare stable 10.4.11 for all five packages. This patch combines independently
captured live prerequisites with accepted ordered column/key lifetimes and
current row proofs, so valid nullable-column/index/FK streams do not require
redundant principal convergence. It corrects related native owner, supporting-
index, CHECK and index-input contracts without rewriting historical migrations.
Public signatures, policy selection, fingerprint formats, report schemas and
migration history remain compatible. The SQL Server PKCS dependency minimum
is raised to its patched version; other production ranges remain unchanged.
Earlier atomic concurrency and recovery guards remain in place. Source
preparation is not publication evidence: the full hosted/native matrix, coverage, tooling, exact
five-package primary/symbol set, provenance, SBOM and public readback remain
required. Timing comparisons remain informational; functional, cancellation,
invalid-evidence and artifact-write failures still block.
Security
- Raise the SQL Server provider's transitive
System.Security.Cryptography.Pkcsminimum from 9.0.11 to 9.0.21, fixing
the publicly disclosed CVE-2026-70162
and CVE-2026-84008.
Promote the central pin into the published NuGet dependency contract and
verify isolated consumers select the patched package. EF Core and SqlClient
versions, migration behavior and other provider runtime graphs are unchanged.
This package change does not update an application's installed .NET runtime
or SDK; apply Microsoft's platform servicing guidance separately.
Fixed
- Preserve independently captured MySQL/MariaDB column sources through accepted
PRIMARY/FK removal and ordinary nonunique BTREE creation. A same-layout
nullableAlterColumnorEnsureColumnno longer becomes structurally unknown
merely because its old composite PRIMARY was removed first. Keep intrinsic
column evidence separate from candidate-key and row lifetimes; retained or
recreated PRIMARY membership, source drift, writes and opaque changes cannot
acquire repair permission. Runtime rechecks the physical key and exact source
before DDL. Cover existing/missing supporting indexes, populated owners,
interrupted-prefix recovery, reruns and adversarial execution-time changes.
Recreated owners derive safety from their new accepted definitions, not the
previous owner's captured physical or row certificate. - Complete sparse ordered constraint and index prerequisites from independently
captured live metadata. Adding a nullable FK column to a populated existing
child no longer requires redundant convergence of its unchanged principal.
Preserve actual candidate-key identities, backing-index ownership, endpoint
compatibility, accepted-operation ordering and independent row proofs across
providers. Mixed old/new key parts retain native uniqueness semantics;
defaults, generated values, dropped or replaced keys and invalidated row
evidence do not acquire implicit authorization. - Remove SQLite's target-model/whole-segment nullable-FK shortcut. Only an
already accepted NULL-preserving addition or a current empty-owner proof can
qualify existing rows. A future or rejected addition, non-NULL default or
generated value cannot satisfy that proof. Native parent-key collations and
explicit unique-index equality facets remain independent requirements. - Preserve SQLite's strict allowed/required constraint multiplicity and prevent
EF from moving a separately appended FK ahead of its required column during
baseline generation. Keep original table-column contracts, owned transaction
boundaries and final foreign-key validation intact. - Qualify PostgreSQL mixed live/projected structured CHECK operand binding
without evaluating user functions or application-row expressions. Keep
unsupported or unresolved bindings blocked and preserve native postconditions. - Qualify PostgreSQL physical index-key types against native access-method and
operator-class selection. Reject incompatible inputs such as ordinary Btree
keys onjsonbefore DDL or unique-data probes; preserve supportedjsonb,
domain, array and explicitly bound operator-class contracts. INCLUDE columns
and genuinely computed key results are not substituted as physical inputs.
Preserve earlier typed EF column operations, ordered index replacements and
exact native identifier/cast deparsing without rewriting historical migrations.
Route occupied native names through the ordinary metadata classifier; only
eligible unoccupied candidates need the additional input fence before data
probes. Share identical certificates within that bounded statement to avoid
native SQL/JIT multiplication without changing session settings or weakening
capability, identity, cancellation or payload checks.
Keep UNIQUE conflict classification metadata-only before separately qualified
duplicate-row probes, and match unqualified explicit operator classes by
their actual visible native identity rather than a hidden same-named class. - Preserve source-qualified FK/key evidence through accepted, non-data,
unchanged-layout nullability-onlyEnsureColumnrepairs after FK removal.
Widening, unknown sources, writes and invalidated dependencies do not inherit
this certificate, and required-column staging retains its original live proof. - Invalidate affected projected index/UNIQUE aliases using the provider's
column-member comparer, without folding distinct table or schema owners. - Reject unsafe MySQL multi-valued FK supporting indexes and index removal
while an affected live FK remains. Preserve native ordinary supporting-index
eligibility and automatic-index name collision checks independently of
optimizer visibility and unrelated trailing keys. - Apply the independently observed MySQL/MariaDB table-case mode consistently
to live transition, unique-index and backfill catalogs. Connection-free
generation retains exact and folded owner alternatives and selects them only
through the native runtime mode; it does not infer a server profile. Preserve
mode-zero case-distinct owners, exact database qualifiers and independent
column/index identity rules. A later unique declaration cannot be hidden by
another spelling of the same native backfill owner.
SafeMigrations 10.4.10
Prepare stable 10.4.10 for all five packages. This patch corrects ordered
nullability, backfill, constraint, index and model-managed-data proofs; guards
concurrent required-column additions and PostgreSQL dependent writes; and
preserves verified schema and session ownership during execution and recovery.
Public signatures, dependency ranges, migration source, policy selection,
report schemas and migration history remain unchanged. Existing migrations do
not need regeneration. Required intermediate CHECKs remain owned recoverable
state, not a claim that MySQL/MariaDB DDL is transactional. Performance timing
comparisons remain informational; correctness and evidence failures still block.
Source preparation is not publication evidence: the complete qualification
matrix, signed v10.4.10 identity, all five exact primary/symbol packages,
provenance, SBOM and verified public readback remain required.
Changed
- Set explicit finite 120-second connection/transaction and command budgets on
owned SQL Server EF tooling CLI and bundle connections. SqlClient transaction
control does not use EF's command timeout. Keep product defaults, fatal errors
and CI job limits unchanged; do not retry failed work. Preserve owned server
logs and bounded wait diagnostics before failed tooling-container cleanup,
with executable positive/negative engineering regressions. - Refresh engineering-only Testcontainers to 4.16.0 and pinned GitHub Actions
through the reviewed dependency updates onmain. Production dependency
ranges and the five publishable package lockfiles remain unchanged. - Keep live pooled-catalog p95 overruns and SQL Server cancellation latency
informational in server-provider qualification instead of failing CI on
shared-runner timing variation. Preserve all 20 measured calls, unchanged
comparisons and false JSON budget verdicts. Deterministic report/scope and
cancellation assertions, invalid evidence, execution and artifact failures
remain blocking; no comparison limit is raised. - Document
projected_required_add_rows_unprovenand its fresh row-proof/backfill
remediation. Distinguish engine-bound observed ADD behavior from documented
DML and Instant ADD defaults; the proposed atomic-add ADR does not depend on
implicit required-ADD behavior and is not promoted by implementation or tests.
Fixed
- Return native SQL Server
bitmetadata for member-rename destination and
index-source probes, including mixed column/indexUNION ALLstatements.
Integer CASE values cannot satisfy the strict Boolean evidence reader.
Preserve the shared runtime integer renderer, source nullability, owner-local
predicates, parameterization and bounded transport; SQL-type-aware unit
doubles and native metadata regressions guard against recurrence. - Preserve MySQL/MariaDB column proofs after exact accepted foreign-key removals:
already matching columns remain no-ops, and source-proven same-layout,
value-preserving nullability alterations retain their explicitRepairIfSafe
path, including NULL-free tightening and multiple alterations on one owner.
Unresolved dependencies, intervening mutations and independent blockers remain
authoritative; no complete table-convergence operation is required. - Prove exact owned MySQL/MariaDB foreign-key replacements against compatible
endpoint storage, a complete principal candidate key and orphan-free rows.
Accepted FK removals and value-preserving nullable relaxation can retain that
bounded certificate; other relevant mutations invalidate it. A surviving
matching physical alias remains a no-op. Runtime guards recheck endpoint and
column presence, localSET NULLnullability, and orphan data; preflight's
exact storage/key certificate is not a new global runtime restriction. - Admit primary-key replacement from a current empty-table certificate and
accepted non-nullable target columns while retaining physical key validation.
Populated tables, nullable key parts and stale row evidence do not acquire a
replacement or implicit backfill permission. - Recognize Doka's exact boolean
RequiresExplicitBackfillcolumn annotation
without changing immutable definitions or fingerprints. A supported required
addition without a replacement value uses two atomic InnoDB ALTER stages:
nullable ADD with an enforced owned non-null CHECK, then required MODIFY with
CHECK removal. This prevents a read-then-add race from inventing row values;
populated tables still require an explicit backfill. Same-layout nullable-to-required
alterations use a fresh NULL proof or an approved non-null default, never an
invented GUID or other synthetic value. Unknown and malformed metadata remains
unsupported; dependency ranges are unchanged. - Resume an interrupted required-column addition only from its exact nullable
target and enforced owned CHECK. Keep that barrier after failure or
cancellation; do not hide or drop objects by reserved prefix. Resuming may
retain explicit writer values and is not an empty-table proof for later keys
or foreign keys. The two ALTERs are not one transaction, and matching targets
retain their no-op path. - Require strict SQL mode for actual nullable-to-required conversion, including
explicit alterations with an approved default UPDATE or type widening/narrowing.
An intervening NULL cannot be silently coerced during MODIFY. Matching targets
and already-required ordinary comment/default repairs retain their existing
path; no SQL mode is changed. - Require explicit TIMESTAMP-default semantics for required TIMESTAMP repairs,
including approved fixed defaults, without changing the session setting.
Missing no-default TIMESTAMP additions remain unsupported, and exact matching
columns remain no-ops. - Qualify missing required-column additions with authored SQL defaults against
InnoDB and strict SQL mode, plus explicit defaults for required TIMESTAMP.
A structurally known SQL NULL default cannot populate existing rows; its
empty-table native ADD rejects a raced row atomically rather than inventing a
value. Matching columns retain their no-op path and independent engine
representability limits remain enforced. General SQL defaults are not thereby
promoted into structural non-null backfill proofs. - Match ENUM/SET domains without folding quoted member case or member order.
Native keyword and literal display canonicalization respects quote/escape
modes; a different value domain cannot certify matching or owned recovery. - Reject non-matching ENUM/SET work when a native backslash-comment scope would
reinterpret the authored member domain. Such scopes require
NO_BACKSLASH_ESCAPES already enabled; their exact matching no-op remains
comparable after cleanup. Standard-only escaped-quote staging instead needs
its certified original mode and no opaque native setup. No domain is rewritten
and these guards introduce no new mode writes. - Compare supported structured TIMESTAMP/DATETIME string defaults against
native catalog fractional zero-padding without rounding, truncating or
mutating the authored SQL expression. MySQL generated-expression defaults use
their separate exact serialized display instead of plain/padded temporal
candidates; no arbitrary charset-prefix union is introduced.
Double-quoted ENUM/SET members also
retain the independent runtime ANSI_QUOTES exclusion, even when their domain
needs no backslash decoding. - Bind native session-mode cleanup to the certified setup that actually began.
Rejection before native setup cannot restore NULL or stale saved state from an
earlier operation. Unknown stateful cleanup shapes remain fail-closed, while
native commands without cleanup retain their ordinary path. - Reject MySQL/MariaDB required-column Ensure repairs and explicit alterations
while an ownedON DELETE SET NULLorON UPDATE SET NULLFK still references
that column, before any default backfill UPDATE or column DDL. An accepted
exact FK drop discharges only that dependency; NULL-free rows or an explicit
default do not remove the blocker.
Nullable Ensure repairs also reject retained PRIMARY membership; already
matching columns retain their no-op path. - Preserve accepted FK/UNIQUE/CHECK creation, removal and physical-alias facts
without requiring a complete projected table image. Repeated drops, including
the singleton primary key, retain their tombstones instead of reusing stale
live matching. MySQL/MariaDB FK and column member comparisons follow their
case-insensitive identity without folding table or database names. - Resolve atomic-add recovery owners according to native table-name mode, using
byte-exact lookup for mode zero and server-side LOWER for modes one/two.
Column, CHECK name/expression and the raw recovery fingerprint remain exact;
no foreign database qualifier is admitted by this owner lookup. - Capture MySQL/MariaDB column dependencies in tagged parameterized statements
with at most 32 distinct requests. Conservative current-database/raw-owner,
case-insensitive member and dependency-role deduplication retains each
operation's proof lifetime and complete SET NULL/PRIMARY facts. Malformed or
incomplete transport cannot publish a partial certificate; runtime guards
remain fresh. This bounds redundant transport, not a general speedup claim. - Keep existence-only acceptance distinct from physical matching. A different
object left unchanged byExistenceOnlycannot install its authored target as
column, key, constraint or index evidence for a later strict operation,
including SQLite's runtime structural segment. Existing matching aliases and
earlier exact physical facts retain their ordinary proof path. - Retain standalone accepted CHECK definitions and sparse physical index
creation/drop/rename state without requiring a complete projected table.
Rename destination absence needs an independent proof;...
SafeMigrations 10.4.9
Prepare stable 10.4.9 for all five packages. This patch adds provider-proven
SQL Server integer widening and populated-table CHECK validation, corrects
PostgreSQL column contracts and trigger-affected ordered proofs, enforces
lossless SQLite repairs, and reduces unnecessary PostgreSQL/SQL Server work.
Public signatures, dependency ranges, migration source, policy selection,
report schemas, and history remain unchanged; existing migrations do not need
regeneration. Classification changes and repair boundaries are detailed below.
This entry records source preparation, not publication. Completion requires
the full qualification matrix, signed v10.4.9 source identity, all five exact
NuGet primary and symbol packages, and verified GitHub Release, SBOM,
provenance, attestation, and public package readback evidence.
Fixed
- Reject unproved SQLite rebuild conversions under
RepairIfSafe, including
lossy affinity/CLR-domain and generation changes. Exact old-definition matching
alone is not a lossless certificate; compatible nullability/default repairs
retain their data and ownership gates in live and projected analysis. - Invalidate PostgreSQL row and physical catalog evidence after executable DDL
with session-active event triggers or inaccessible trigger metadata. Attribute
runtime validation to the actual preceding DDL; inactive triggers and initial
no-ops retain their ordinary proof path. - Extend SQL Server DDL-trigger freshness to structural dependencies and
metadata before Core matching/removed-owner shortcuts. A trigger-created
replacement dependency cannot reuse the accepted drop's stale certificate.
Runtime guards and independent invariant/permission blockers remain authoritative. - Invalidate PostgreSQL and SQL Server physical metadata after executable DML
when user triggers can execute unrelated DDL, including indirectly reached
FK-cascade triggers. Preserve the actual DML origin, initial no-ops, empty typed
writes and independent unsupported contracts; include provider-emitted column
backfills and preserve SQL Server's emptydboschema baseline. SQL Server
model-managed target trigger rejection also includes CLR triggers, not only
SQL implementations. - Admit explicit SQL Server built-in integer widenings under
RepairIfSafe
with exact source, preserved default/identity, declared-row layout, and ordered
dependency proofs. Reject numeric narrowing and unproven layouts without DDL. - Exclude encrypted and legacy-rule-bound SQL Server columns from ordinary
column matching. This applies to all column contracts, not only integer
widening: an existing encrypted or rule-bound column cannot become a matching
NoOp merely because its type and length agree. No encryption or rule is
silently removed; affected migrations require an independently reviewed path. - Reconcile ordered SQL Server FK-to-key drops against the exact backing-index
identity; do not retain a stale key blocker after its accepted FK drop or
promote wrong-kind and surviving-reference conflicts. - Preserve SQL Server standalone foreign-key prerequisites after accepted
creation of a fresh, initially empty child table. A captured unchanged live
principal key and exact compatible column storage can satisfy the ordered
proof; intervening writes, unknown state, orphan data, and permission refusals
do not acquire a bypass. Retain schema-wide name occupancy from live objects
and earlier accepted tables and PK/UNIQUE/CHECK/FK constraints instead of
promoting a conflicting standalone FK toMissing. - Guard protected SQL Server expression-dependency catalog reads with their
effective database and view permissions before delayed compilation. Missing
access reportsdependency_catalog_permissionwithout an unsafe absence proof,
automatic grants, or a raw catalog permission exception. - Preserve independent SQL Server permission refusals through ordered projection,
including initially absent owners. Require effective UPDATE permission for
approved integer/text ALTER mutations; matching NoOps do not require UPDATE. - Reject SQL Server text ALTER row classifiers without effective table SELECT
before binding, including matching replays. Retain the independent permission
refusal through ordered projection instead of leaking a raw provider exception. - Validate missing simple integer CHECK constraints on populated SQL Server
tables using FALSE-only probes; preserve UNKNOWN semantics, binding gates,
provenance, trust, ordered proof invalidation, and runtime rechecks. - Preserve qualified PostgreSQL collations in accepted column repairs instead
of resetting them duringALTER TYPEand failing the target postcondition. - Retain explicit PostgreSQL ALTER source authority when parent-only NOT NULL
metadata does not prove the queried descendant relation is non-NULL. - Keep SQL Server integer ALTER baselines within their captured operation:
do not infer extra index rebuilds from the target model or execute a redundant
default UPDATE whose zero affected rows would still fire DML triggers. - Invalidate SQL Server ordered row certificates after executable safe or typed
provider DDL when enabled DDL triggers or insufficient database/server metadata
visibility leave later rows unproven. Report affected assessments as
ValidateAtRuntimewith the DDL origin, distinguishing known trigger risk
from visibility uncertainty rather than blocking a least-privilege stream
or claiming read-only readiness. Preserve independent unsupported contracts,
invariant refusals and initial non-executing no-ops; supported row and structural
metadata captured before trigger-risk DDL require fresh runtime classification. - Preserve a conservative runtime-validation boundary after provider-specific
structural deferrals. Later supported safe operations retain the first
deferred structural origin instead of depending on an invented candidate key
or reporting a false missing prerequisite. All independently captured live
Unsupportedresults, including permission and capability refusals, and
identifier mismatches remain blocking. Later supported immutable state and
data classifications become runtime-validation assessments, not approval of
their stale batch observations; already blocked assessments stay blocked.
Changed
- Trigger-affected ordered operations can now report
RuntimeValidationRequiredrather than stale readiness or a false prerequisite
conflict. Deferred assessments retainValidateAtRuntimeand the actual
invalidating origin; runtime guards decide after the preceding mutation.
Independent permission, capability and invariant refusals still block.
Deployment consumers must distinguish deferred validation from both proven
readiness and rejection. SQLite affinity/CLR-domain or generation changes
without a lossless proof are rejected even when their old definition matches. - Skip unused SQL Server source/dependency captures for already matching integer
ALTER replays, including their unused row-growth reservations. Nonmatching
source and ordered dependency checks remain unchanged. - Bound PostgreSQL narrowing eligibility-plan lifetime to the current transport
statement and retain compact candidate identities instead of unused rendered
SQL. Submitted predicates, result attribution, deduplication, statement limits,
data checks and cancellation semantics remain unchanged. - Avoid evaluating SQL Server runtime repair predicates for matching states,
non-repair policies, or plans without a safe repair capability. Preserve fresh
classification, prerequisite gates, target postconditions, and transactions. - Classify fully matching PostgreSQL proof-bearing columns from fresh target
metadata before evaluating unused repair/data scopes, and avoid duplicate
explicit-collation OID lookups. Required row scans,
permissions, transaction boundaries, locked rechecks, and postconditions remain
authoritative; no cross-operation cache or new client roundtrip is introduced.
SafeMigrations 10.4.8
Prepare stable 10.4.8 for all five packages. This patch corrects explicit
lossless column transitions, ordered proof invalidation, model-managed seed
projection and rename-destination checks, and hardens MySQL/MariaDB default
identity and setup compaction.
Public APIs, dependency ranges, migration source, policies, report schemas,
and history remain unchanged; existing migrations do not need regeneration.
This entry records source preparation, not publication. Completion requires
the full qualification matrix, signed v10.4.8 source identity, all five exact
NuGet primary and symbol packages, and verified GitHub Release, SBOM,
provenance, attestation, and public package readback evidence.
Changed
- Multi-step model-managed writes into existing tables can now report
RuntimeValidationRequiredinstead ofReadywhen earlier operations make
their seed-row or dependency evidence stale. Deferred assessments use
ValidateAtRuntimewith nullObservedStateandPostconditionSatisfied;
DeferredOriginidentifies the invalidating operation.ThrowIfBlocked()
does not throw for this status: ordered runtime guards remain authoritative.
Consumers gating deployment onStatus == Readymust explicitly handle
runtime validation rather than treating it as either proven readiness or a
proven conflict. Migration source, public signatures and report schemas
do not change.
Fixed
- Preserve unrelated row-safety proofs across model-managed inserts into
newly created plain tables. Generated initial migrations can seed one table
before adding a deferred cyclic foreign key on another table in both strict
and convergence modes. Existing tables, opaque structures, SQL-bearing
artifacts, updates and deletes retain global data-proof invalidation.
Local mutation markers follow table renames and reset on physical recreation. - Invalidate exact seed-row and candidate-key evidence before unconfined
model-managed writes, provider DML, and data-changing repairs. Later seed
states that cannot be proven use the existingRuntimeValidationRequired
report outcome instead of stale live classifications or count-only delete
handoffs. Ordered child/parent deletes remain guarded at runtime, including
intervening trigger effects; untouched conflicts still block. Pure table
renames preserve owned row evidence, and discarded row knowledge cannot
recreate an empty-table proof. Newly projected incoming FKs absent from a
delete's frozen dependency metadata are rejected before execution. - Reuse provider-proven lossless column transitions for explicit
AlterColumnIfDifferentoperations underRepairIfSafe, including generated
AlterColumnIfDifferentFromModelcalls. MySQL/MariaDB retain their existing
string and Boolean allowlist; PostgreSQL retains its independentVARCHAR
length contract. Repair still requires the exact old definition, physical
eligibility and fresh row proofs where needed. Matching targets remain
no-ops; unsupported conversions and overlength data reject without truncation. - Preserve accepted column-transition evidence in ordered preflight, including
MySQL/MariaDB table renames and dependent index validation. Do not reuse row
proofs across intervening data changes, infer live column shapes from an
existence-only table container, or ignore an occupied rename destination.
Existing migration source, public signatures, report schemas and history
remain unchanged. - Preserve independent rename-destination evidence in all providers so a
table created earlier in the same stream cannot hide an occupied live target.
Genuine missing-source replay remains a no-op; an accepted earlier target
drop is evaluated against the ordered state. - Compare MySQL/MariaDB string defaults using their exact engine-specific
catalog representation. Preserve case, quoting and SQL NULL distinctions;
a different literal cannot impersonate the approved source or target default.
Explicit type transitions reject default forms that the engine or current
SQL mode cannot preserve, before any backfill or DDL. - Keep unterminated owned MySQL/MariaDB setup fragments outside transport
groups. Preserve exact SQL, opaque provider boundaries and larger caller
buffers; avoid unused UTF-8 accounting when composing large independent
fragments. Default-only and collation-only drift retain runtime checks. - Keep action-only planning allocation-free after garbage collection by
validating enum members without GC-sensitive reflection caches. Preserve
accepted values, exception ordering and the strict zero-allocation contract;
cover cache eviction and invalid enum boundaries with regression tests.
SafeMigrations 10.4.7
Prepare stable 10.4.7 for all five packages. This patch reduces MariaDB
analysis catalog work and MySQL/MariaDB runtime checks and command dispatches,
with bounded direct SQL rendering. Public APIs, dependency ranges, migration
source, policies, report schemas, and history remain unchanged. Core,
PostgreSQL, SQLite, and SQL Server execution behavior is unchanged; all
packages retain the shared release version.
This entry records source preparation, not publication. Completion requires
the full qualification matrix, signed v10.4.7 source identity, all five exact
NuGet primary and symbol packages, and verified GitHub Release, SBOM,
provenance, attestation, and public package readback evidence.
Changed
- Reduce MySQL/MariaDB runtime migration work independently of preflight:
check repair-capableEnsureColumnplans for a fresh exact match before
repair probes, and evaluate the final repair precondition only after aDifferent
classification. Group owned setup commands within a 4096-byte UTF-8 copy
bound without crossing provider, guarded-body, or cleanup boundaries.
Render grouped SQL directly from immutable pieces into the final string;
render large independent fragments directly from spans without retaining
an intermediate descriptor array. This reduces grouping overhead but does
not guarantee lower total allocations than the earlier ungrouped path.
Preserve operation-local evidence, postconditions, policies, cancellation,
and per-command timeouts; do not change the assertion table's storage engine. - Materialize MariaDB catalog metadata once per sufficiently large analysis
window to reduce repeated INFORMATION_SCHEMA work. Preserve live-catalog
fallback when temporary-table DDL is not permitted, cross-database incoming
foreign-key detection, quoted SQL values, and caller-owned session state.
MySQL and generated runtime migration commands continue to read the live
catalog. Classification semantics, policies, public APIs, and report schemas
remain unchanged; performance timings are informational rather than CI gates.
SafeMigrations 10.4.6
Prepare stable 10.4.6 for all five packages. The existing providers receive
compatible correctness and performance fixes; SQL Server is a new, optional
provider package. Core adds two included-index helpers and the sqlserver
engine-family value. Existing signatures, migration source, policies, report
schema versions, and migration history remain compatible.
This entry records source preparation, not publication. Completion requires
the full qualification matrix, signed v10.4.6 source identity, all five exact
NuGet primary and symbol packages, and verified GitHub Release, SBOM,
provenance, attestation, and public package readback evidence.
Added
- Add a separate SQL Server provider package for EF Core 10 and SQL Server
2019, 2022, and 2025. Provider catalog analysis, guarded execution,
design-time registration, package qualification, benchmarks, and x86-64
live-engine checks are independent of the existing adapters. - Add
CreateIndexWithIncludesIfNotExistsFromModeland
CreateCompositeIndexWithIncludesIfNotExistsFromModelto preserve SQL Server
included columns in scaffolded safe indexes. - Extend the report engine-family schema with
sqlserver. Report schema
versions and existing migration histories remain unchanged; consumers with
exhaustive engine-family handling must recognize the new value. - Recognize canonical provider-delimited single-column
IS NULLand
IS NOT NULLPostgreSQL raw index filters captured from EF. Preserve raw
filter bytes, immutable definitions and fingerprints; share predicate-column
prerequisites between ordered preflight projection and runtime validation.
Other opaque or noncanonical raw predicates remain unsupported.
Changed
- Keep MySQL/MariaDB strict table-column matching in one ordinal-count catalog
probe with constant database and table lookup values. Avoid derived joins
that open unrelated schema metadata on MariaDB. Preserve exact column count,
names, order, facets, and NULL rejection, with positive and negative provider
regressions; no row scan or timing-based CI gate is added. - Share one table-default collation lookup across MySQL/MariaDB table-column
predicates when every expected column inherits that default. Preserve
per-column comparisons for explicit collations and MariaDB JSON. Reduce
repeated catalog subqueries without changing matching or rejection semantics. - Share exact SQL Server delayed classifier templates within bounded statements
and evaluate outer catalog proofs through reusable parameterized scalar SQL.
Keep proof values fresh, gate order, lossless source mappings, nine-column
result ownership and complete payload/parameter limits unchanged. Group
managed-data type checks by physical table without weakening required facets. - Open SQL Server fixture connections without pooling so tests that change their
database collation do not reuse an incompatible login-reset baseline. Add
isolated reset controls and an opt-in complete local classifier replay;
native engine qualification and production connection settings are unchanged. - Match SQL Server classifier rows by their ordinal column instead of relying on
ordered delivery, so the catalog statements no longer carry a sort. Missing,
duplicate and unexpected rows still fail the analysis. - Reuse a completed SQL Server identifier-contract verdict for the
unexpected-object inventory only within the same active scope, context,
connection and transaction, with an identical reference set and a freshly
matching environment, principal and collation stamp.
Failed analysis, scope disposal, connection closure and session changes
invalidate reuse; separate inventory requests obtain fresh proofs. - Retain SQL Server fixture database ownership until cleanup succeeds, allowing
retries after failed opening, dropping, cancellation or lost acknowledgement.
Final cleanup removes only confirmed drops. Do not change the server's model
database recovery configuration to tune test setup. - Batch independent MySQL/MariaDB and PostgreSQL diagnostic, narrowing and
qualified row probes through the existing bounded catalog transport. Omit
prerequisite queries only when their captured builder predicate is constant
TRUE. Preserve prerequisite barriers, evidence, original ordinals, command
timeouts, cancellation, transaction ownership and sequential wrapper fallback. - Reuse SQLite's immutable unexpected-object inventory snapshot for its bounded
semantic-alias windows without retaining catalog or row proofs between
invocations, connections, transactions or runtime mutations. - Stream SQL Server delayed classifier results from isolated parameterized
dynamic scopes instead of aggregating throughINSERT ... EXECand a result
table variable. Keep the complete classifier template independent of original
ordinals and source values, with unchanged physical and name-binding guards,
typed source mappings, result validation and transport limits. - Evaluate the MySQL/MariaDB nullable-to-required row proof once per guarded
column operation and share it and the physical repair invariant between
classification and repair eligibility.
Skip the scan for physically non-nullable, missing or ineligible columns;
retain fresh evidence after every intervening operation and independent
cleanup on success, rejection, cancellation, timeout and provider failure.
Apply the same physical-nullability gate to inline live analysis. Avoid
copied eligibility SQL during analysis and generation. - Skip PostgreSQL NULL row proofs only when the fresh physical catalog proves
an enforced and validated NOT NULL contract for the complete queried
relation. Do not trust PostgreSQL 18's possibly-invalidattnotnullflag
alone or use a parent-only proof for inherited rows. Preserve fresh NULL
rejection, operation-local proof reuse and locked repair rechecks.
Share one fresh physical repair-eligibility value within each evaluation and
append guard components directly without intermediate SQL copies; preserve
collision-free dollar tags, canonical commands and independent postconditions. - Batch independent table-layout, key and unexpected-object metadata reads
through the existing bounded Core transport. Preserve complete statement
ownership, 512-value inventory chunks, provider parameter and packet limits,
sequential fallback and all-or-failure publication. - Capture SQLite main-schema metadata with five fixed read commands using
set-based table-valued PRAGMAs. Stream columns, index keys and foreign keys
into the invocation-owned snapshot; preserve effective collations, generated
columns, expressions, implicit primary-key references and artifact guards. - Append SQL Server action cases and delayed scalar wrappers directly into
their operation-owned guard buffer instead of copying intermediate strings.
Compose identifier guards directly from their complete statements and index
existing command lists without temporary selectors. Preserve complete private
scopes, SQL bytes and unchanged allocation budgets.
Detect repeated identifier scopes without allocating full grouping objects,
retaining complete identifier validation and rendered references. - Let MySQL/MariaDB, PostgreSQL and SQL Server action rendering consume the
same canonical Core decision table without constructing discarded public
decision results. Public planner results, codes and validation stay unchanged;
no decision or database evidence is cached. - Report Core and all provider benchmark budget overruns as informational CI
and release evidence instead of blocking qualification on shared hardware.
Preserve measured durations, allocations, comparison limits and JSON verdicts.
Keep malformed configuration, incomplete workloads, execution exceptions and
output failures blocking; retain strict manual budget evaluation. - Reduce MySQL/MariaDB migration transport exchanges by grouping owned setup
fragments and directly emitting prepared assignments with their immediate
controls within each guarded operation, without copying completed large SQL
strings. Preserve exact SQL text and order,
original scope bounds, opaque provider setup, the guarded body, and
independently attempted cleanup. Keep fresh per-operation checks and existing
transaction, history, and server durability contracts. - Reuse one immutable MySQL/MariaDB decision-SQL assignment per scoped handler
for identical operation-kind, policy, and structural repair-capability inputs.
Bound retained cache memory to one entry without caching live state or proofs. - Pack SQL Server's read-only catalog classifiers by binding mode within
bounded captures, retaining original operation ordinals and unchanged
ordered projection. Parameterize delayed classifier ordinals so identical
inner SQL can reuse its compilation plan. Payload and transport limits,
runtime operation order, and public contracts remain unchanged. - Coalesce equal SQL Server baseline classifier plans within each bounded
capture. Restore immutable evidence to original operation slots without
caching results across captures or analysis invocations. - Pack unresolved MySQL/MariaDB and PostgreSQL catalog classifications across
already classified gaps through one bounded Core ordinal-work selector.
Retain strict submitted-result validation and migration-order projection;
capture PostgreSQL runtime plans in 512-operation windows. - Read SQL Server table-name occupancy once per bounded capture. Skip complete
structure matching only for targets proven absent; a newly occupied target
remains different. Parameterize managed-data classifiers with lossless source
mappings and separate inner/outer binding scopes, retaining conversion,
encoding, size and prerequisite guards. Bound transport to 2,000 parameters
and 4 MiB of SQL plus source payload; runtime mutation SQL is unchanged. - Add optional analy...
SafeMigrations 10.4.5
Prepare a stable maintenance release that bounds composite-index catalog
analysis on MySQL and MariaDB and includes dependency-workflow maintenance.
Core, PostgreSQL, and SQLite behavior, public APIs, generated migrations,
runtime DDL, migration history, report schemas, and dependency ranges remain
unchanged. All four packages share this version.
These notes do not establish publication. Require the successful stable
release run, the authorized signed v10.4.5 tag, and verified public package,
symbol, GitHub Release, provenance, SBOM, and attestation readback before
selecting 10.4.5.
Changed
- Reduce the Dependabot cooldown for NuGet, GitHub Actions, and .NET SDK updates
from seven to three days while preserving weekly schedules, grouping, and
open pull request limits. Security updates remain unaffected. - Update the SHA-pinned CodeQL upload-sarif action from 4.38.1 to 4.38.2.
Fixed
- Match MySQL/MariaDB composite-index candidates by grouped
INFORMATION_SCHEMA.STATISTICSrows instead of correlated catalog queries
for every key part. Preserve ordered key, uniqueness, visibility, method,
sort, and prefix checks while keeping catalog references independent of key
count. This also applies to expected table-index prerequisites.
SafeMigrations 10.4.4
Prepared a stable bugfix for read-only preflight over mixed legacy-convergence
and strict migration streams containing raw SQL. Existing migration source,
ordered runtime guards, history, dependency ranges, and engine support remain
unchanged. All four packages share this version.
These notes do not establish publication. Require the successful stable
release run, the authorized signed v10.4.4 tag, and verified public package,
symbol, GitHub Release, provenance, SBOM, and attestation readback before
selecting 10.4.4.
Added
- Report deferred validation explicitly with
SafeMigrationAction.ValidateAtRuntime,
SafeMigrationReportStatus.RuntimeValidationRequired, and
SafeMigrationAssessment.DeferredOrigin. The origin identifies the preceding
raw SQL by migration ID, stream ordinal, and operation type without including
SQL text or data values.
Changed
ThrowIfBlocked()now permits a mixed pending stream whose later safe
operations cannot be classified after raw migration SQL. Such operations
reportValidateAtRuntimeand the SQL origin; their unchanged runtime guards
still decide after the SQL executes. Proven conflicts and invariantly
unsupported contracts remain blocked. This changes the preflight deployment
gate, not published migration source or runtime SQL.- The canonical report schema advances to v3 and the filtered view schema to
v2; previous schemas remain packaged. Breaking for consumers with exhaustive
SafeMigrationActionorSafeMigrationReportStatusswitches, or readers
restricted to run-report v2 or view v1: handle the new enum values and schemas
explicitly.
CurrentSchemaVersionis a compiled constant, so rebuild consumers that use
it after updating the package. - Group all four test projects directly under the solution's
testsfolder
without changing project paths or test execution settings.
Fixed
- Preserve diagnostic enrichment metadata and projection precedence across
providers so raw SQL does not conceal independently proven or invariant
rejections while catalog-dependent states remain deferred. - Do not claim that SQLite raw SQL preserves previously observed table state
during read-only preflight.