- Amended CR-OC-001C to restrict execution to targets with a present, protected DACL, after three hosted Windows CI runs established that a successful `ReplaceFileW` does not preserve the required invariant on inheritance-enabled targets (documentation only): A new section 10.2b narrows the supported profile. CR-OC-001C now supports only targets whose pre-mutation DACL is present, non-NULL, and protected from inheritance (`SE_DACL_PROTECTED` set); any absent, NULL, or inheritance-enabled DACL is refused as `metadata_precondition_failed` with outcome `not_attempted`, before temporary-file creation and before any replacement attempt. This narrows the supported profile rather than weakening the invariant, and the amendment says so explicitly: the exact owner, DACL-state, control-bit, `AclRevision`, ACE-count, ACE-order, and complete-ACE-byte comparison of section 10.1 is unchanged, no comparison is relaxed or made unordered or partial or replaced by an effective-permissions rule, the section 10.1a `SE_DACL_AUTO_INHERITED` monotonic rule is unchanged, post-verification remains mandatory and authoritative rather than being displaced by the precondition, and unsupported targets are never normalized, repaired, protected automatically, or attempted — the executor does not modify a security descriptor to make a target supportable, it refuses. The discovery sequence is recorded in full. Hosted run `30689442321` classified a previously unexplained failure: on an ordinary inheritance-enabled target a **successful** `ReplaceFileW` changed exactly three components — `dacl_auto_inherited`, `ace_count`, and `ace_bytes_or_order`. Hosted run `30690450931` ran a paired protected-DACL control that was neither failed nor skipped, and that result is recorded deliberately as *not* evidence: as first written the control failed only on a metadata label beyond `dacl_auto_inherited`, so a refusal such as `temp_creation_failed` accompanied by no metadata differences would also have passed it, and the recorded `protected_replacement_result` property could not be recovered because the mandatory command failed before the structured gate or bounded summary exposed it and no artifact is uploaded. Absence from a failure list is not evidence, so the control was strengthened to require simultaneously a protected and nonempty fixture, `reason_code == ok`, outcome `replacement_verified`, target bytes exactly equal to the proposed bytes, and metadata differences of none or `dacl_auto_inherited` alone; each of those assertions was then verified to actually fail when its condition was forced, because an unverified control is the same defect one level up. Hosted run `30691068391` passed the strengthened control while the unprotected control reproduced the same three differences. What that establishes is stated narrowly: on the hosted runner, the unprotected profile violated the exact invariant while the present-and-protected profile completed a verified replacement under the exact same comparison. What it does **not** establish is stated just as plainly: it does not prove that inheritance recomputation is the underlying Windows mechanism, because the diagnostic reported field labels only and established neither that every new or changed ACE was inherited nor that effective access was unchanged. Microsoft documents `ReplaceFileW` as preserving the DACL and separately describes the operation as merging attribute and ACL information into the replacement file, without promising byte-identical ACE enumeration in every inheritance environment, and automatic inheritance can set `SE_DACL_AUTO_INHERITED`, materialize inherited ACEs, and order inherited entries after explicit ones — but the governance conclusion does not depend on which explanation is correct. The hosted environment is recorded as bounded evidence rather than a universal Windows guarantee: Windows Server 2025, build 10.0.26100, image `windows-2025-vs2026`, Python 3.12.10, NTFS. An effective-permissions rule was considered and rejected as materially harder to prove safely than exact equality, since ACE order affects access decisions and common effective-rights helpers omit owner rights, privileges, logon-session groups, resource-manager policy, and some inherited-deny cases; exact equality over a narrower profile is the conservative direction. `pre_dacl_nonempty` is documented as a diagnostic validity control whose only purpose was to prove the hosted success was not a trivial empty-ACL comparison, and explicitly not a production requirement — a present, non-NULL, protected DACL with zero ACEs remains supported, and section 10.1's three-state classification continues to distinguish present-empty from NULL and absent. Section 10.2's DACL carry-over bullet and section 11.2's merge language were revised so neither implies that `ReplaceFileW` alone establishes general exact preservation; both now state that documentation is trusted to choose the primitive and never to skip the check, that hosted evidence supports preservation only within the protected profile, and that post-verification remains the deciding evidence. Section 1 now records all three amendments as contract-discovery results found by running the contract against real Windows evidence. Rather than adding a thirty-seventh obligation, T21 is revised into four parts — an unprotected target refuses before temporary-file creation or `ReplaceFileW` with original bytes unchanged and no artifacts remaining, seam-injected absent and NULL DACL states refuse identically, a present and protected target completes with `ok`, `replacement_verified`, exact proposed bytes and the full exact metadata invariant, and existing injected post-replacement differences still produce `metadata_preservation_failed` — so obligation totals stay at 36 while mutants move from 30 to 31 (21 Windows, 10 Ubuntu). The new M31 defect is omitting the present-and-protected DACL precondition or treating an inheritance-enabled target as supported, killed by T21[W]'s unprotected-target test; it is Windows-scoped by necessity because its killer asserts refusal against a genuine NTFS security descriptor and a real mechanism call log, which the neutral core cannot produce. Section 21's acceptance contract and section 25.7's hosted acceptance now additionally require that every healthy replacement case run within the supported profile, that T35[W] confirm the supported pre-state before replacement, that every other participating component be exactly preserved, that absent, NULL, and unprotected profiles fail before mutation, and that M31 be killed cleanly. Sections 1, 10.2, 10.2b, 11.2, 19, 20, 21, 25.5, 25.6, and 25.7 are updated consistently. Three contradictions the amendment would otherwise have left behind are also corrected. T20's third part said "an ordinary target created by this process reaches `replacement_verified`", which under the amended contract either permitted or required a healthy result without establishing the supported profile; it now reads that a target created by this process, then placed into a present, non-NULL, protected DACL profile without changing its owner, reaches `replacement_verified` with post owner equal to pre owner, and the section 10.2a lineage entry above carries the same qualifier. Section 1's implementation status said "Proposed, not authorized", which has been false since implementation was explicitly authorized; it now records that implementation is authorized and in progress on draft PR #128, not merged, not accepted, not runtime-integrated, and not yet conformant with section 10.2b — the supported-profile gate, revised fixtures, T21 evidence, and M31 all remain pending — with the adjacent authority and approval-gate bullets adjusted so they no longer read as denying an authority that was in fact granted, while still stating that it came from a separate explicit approval bounded to the section 25.1 seven-path allowlist and is not merge authority. And the gate order is now explicit: the supported-profile gate is evaluated immediately after validating the pre-mutation security snapshot and before the `TokenOwner` ownership gate, despite the order the two bullets are written in, which gives T21's absent, NULL, and unprotected cases a precise cessation point and avoids querying the token's default owner for a profile already known to be unsupported. This entry changes no code, tests, workflow, dependency, fixture, or configuration; the implementation on draft PR #128 remains unmerged and will be corrected after this amendment lands, at which point the production profile gate and M31 remain outstanding work.
0 commit comments