Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/client-v1-conformance.yml

Large diffs are not rendered by default.

36 changes: 29 additions & 7 deletions docs/phase1-conformance.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,8 @@ diagnostic-only change.
- Coven daemon and observation-test source `8c3735f374d6bc95e5b6fd107f7e7308fa26a2f8`;
- Chat native client remains at `721437b84026c042e431b0882dcd14fdb29ac07d`
in its frozen Cargo manifest and lock;
- Chat conformance driver `d55b40c3315035be4267424b5d5d55c416bb609d`, tree
`ceb98c9ace85138ef8ddab5a6f7a0aeb7d2008fb`, retained in the producer ancestry;
- Chat conformance driver `ad8d5f3e5e937c398c5d6d8f7bbbb190b4ed499a`, tree
`dd4ffa0af4c39aefee9fc675ba5c804d7fe0e678`, retained in the producer ancestry;
- Historical schema-1 SDK evidence contract and registry
`4736bf2e0d5b16272d79ecf7784c75f376b39b94`;
- manifest digest
Expand Down Expand Up @@ -1544,7 +1544,7 @@ revision authorities can therefore have different workflow hashes:

| File | Bytes | SHA-256 |
| --- | ---: | --- |
| `.github/workflows/client-v1-conformance.yml` | 166,782 | `a64fcdaf3fbd51e6cc0d3eb293ec5ac6a27df820182f0e89c272ce9cadfea566` |
| `.github/workflows/client-v1-conformance.yml` | 167,054 | `e0d848fc82bd97d968b661a442420174d0690dd108d9a2c926c292f6505fb342` |
| `scripts/contract-canary.mjs` | 40,618 | `a4c2fe0a5eb6a5ff4653de5374c34c0fb46907c6806a5d23b86d8b37206ef958` |
| `scripts/executable-resolution.mjs` | 9,154 | `31e3c412ff8c835f14522f36a59e91f4a4ba82913210ae8e3b4455217503f430` |
| `scripts/owned-temp-directory.mjs` | 6,965 | `a9c55c85cf2b7d70310d278bafd2c8e7695d66f4ae38b9c3f1f12fce0b442095` |
Expand All @@ -1569,11 +1569,11 @@ revision authorities can therefore have different workflow hashes:
| `scripts/unix-producer-supervisor.test.sh` | 13,348 | `a8c6f48915b0c86a704a7ddc28eaa7f808ae0a3ddfcdb38c0c23ac0d83738f6d` |
| `scripts/phase1-windows-supervisor-build.sh` | 4,646 | `713a9e0282887ade3e243b5ba175794d74cdb02c28c38dcd41491c9505812770` |
| `scripts/phase1-windows-supervisor-install.ps1` | 1,743 | `2baab275f0bb6789884cded5f6185d00bfa5348b9e7c3ad1e5575353639101d5` |
| `scripts/windows-job-supervisor.cs` | 351,497 | `281acdeba5ee8dd022fd0451bd4ede6af8431aba8810f1683ce7077cc627fcb0` |
| `scripts/windows-job-supervisor.cs` | 352,878 | `d08748d1a7ce3cc3964ce4520cc501f514d5777ed102ac5f57ebc20b75e7bb65` |
| `scripts/windows-job-supervisor.test.ps1` | 187,115 | `9ebf051e1abfc08e86d99fd702fa410857005fdd22aa2e31978b17e1687ad3f3` |
| `scripts/windows-quota-diagnostics.test.ps1` | 25,774 | `c9a9a82a1d90da0da6a95732048946f83917de91bda76ac4a36cfaecdf6e0d42` |
| `scripts/windows-owner-directory-quota.test.ps1` | 11,186 | `41a028dae853502af7f06463983e74d0a798070a538852b7d8bb2773cb3e7fe3` |
| `scripts/windows-quota-isolated-reader.test.ps1` | 18,928 | `247778f13c4238d8b7a9f1e004571d91709790654e246896357fc497514476a6` |
| `scripts/windows-quota-diagnostics.test.ps1` | 29,480 | `b2160b083f6db3c4e6a328b026350c9ae80a2d688482849705705396ded1a998` |
| `scripts/windows-owner-directory-quota.test.ps1` | 14,775 | `605b57608bf4ef2939759d32df6ac1685027bdd864aaaab44dac15ab90de51ec` |
| `scripts/windows-quota-isolated-reader.test.ps1` | 22,262 | `fb6365248bd8286fa03a950e387f0925ff2c818e72ffc1676e4fc327636b5f03` |
| `scripts/windows-quota-lifetime.test.ps1` | 2,513 | `dd10741c19cd97cc1b9ee29ebe18b8381503d589680acd0eddaabda08b5e7aec` |
| `scripts/windows-identity-cleanup-diagnostics.test.ps1` | 6,025 | `43688191fcbf8807d5e33ba811f14b0f8a6e780fef30ae2e3f494d540608bdb2` |
| `scripts/windows-cleanup-delete-diagnostics.test.ps1` | 7,433 | `e9d30285a1fe0ad035637621c6a3840eb8a6194b2f23e1a4aa188c5884cd0c64` |
Expand Down Expand Up @@ -2153,3 +2153,25 @@ Chat #257 publishes `phase1.native-scenarios.launch.service-unavailable`; this
integration preserves that identifier alongside the six other allowlisted native
launch codes and the retained-handle termination correction. Service unavailability
is an observed native result and does not by itself establish a timeout.

Protected run `34773356378` used Chat `3a1f4e3` and SDK validator
`372fa9d`. Linux and Darwin passed. Windows failed during active Cave packaging
with `access-denied; root=cave-checkout; scope=none;
operation=directory-enumeration-depth-3-plus; repeat=readable`. No Windows
record was produced, so validation, attestation, and aggregation were skipped.

The fresh same-token enumeration had completed under the existing entry bound,
but the monitor discarded it and terminated the producer because every repeat
was diagnostic-only. Directory snapshots now recover only this narrow case:
an initial `UnauthorizedAccessException` followed immediately by a successful
fresh invocation of the same bounded snapshot core. The failed attempt's
partial entries are never used. Missing and persistent repeats, all
non-access-denied failures, and metadata reads remain fail-closed. Quota byte
limits, entry limits, reparse rejection, isolated identity, polling cadence,
process quarantine, cleanup, and private diagnostics remain unchanged.

Portable coverage demonstrates the prior failure before the repair and verifies
the returned fresh snapshot. Native Windows coverage keeps a real owner-only
denial across both reads to prove persistent denial remains terminal, then
restores only the test fixture between reads and verifies complete snapshot
accounting plus a real byte-limit breach.
37 changes: 29 additions & 8 deletions docs/windows-quota-repeat-outcome.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,37 @@ follow-up read:
- `persistent`: it threw another exception; this need not match the first error.
- `none`: no diagnostic follow-up was requested.

Every outcome preserves the original failure and rejects the quota measurement.
There is no additional read, wait, measurement acceptance, identity switch,
permission change, or change to any resource ceiling. These are observations
at follow-up time, not proof of the original filesystem state.
Protected run
[34773356378](https://github.com/OpenCoven/chat/actions/runs/34773356378)
later failed while Cave was being built with `access-denied`,
`root=cave-checkout`, `directory-enumeration-depth-3-plus`, and
`repeat=readable`. The monitor had discarded a fresh complete snapshot produced
by the same bounded traversal immediately after the first enumeration failure.

Directory enumeration now accepts only that `readable` result. The retry uses
the same validated isolated-user token, directory, search pattern, entry limit,
reparse rejection, and byte-accounting path as the first attempt. The first
attempt's partial list is discarded; only a fresh traversal that completes
under the existing bounds can become the measurement. There is no wait, third
read, identity switch, permission change, or resource-ceiling change.

`missing` and `persistent` repeats remain terminal, as do every initial failure
other than `UnauthorizedAccessException`. Attribute and file-length reads keep
their existing fail-closed diagnostic-only repeats. The terminal check performs
the same bounded recovery and still rejects any path that cannot produce a
complete readable snapshot.

Managed regression coverage exercises both missing exception types, a successful
follow-up, repeated access denial, and a different second error. It requires
exactly two callback calls, the original access-denied category, and suppression
of private exception text. Existing single-pass, first-failure, terminal and
background diagnostic checks remain in place.
metadata follow-up, repeated access denial, and a different second error. A
separate snapshot regression requires exactly two calls and verifies that the
accepted result contains the complete fresh directory contents. Native Windows
coverage first holds a real owner-only ACL denial across both reads and requires
the bounded `persistent` failure. The isolated-reader fixture then denies the
validated isolated identity, temporarily reverts only for the fixture ACL
restoration, verifies impersonation is restored before the second enumeration,
and requires two identity-checked reads to return the complete fresh snapshot.
A subsequent 512-byte limit check proves the production accounting path still
enforces the byte quota.

Status: local diagnostic tests pass after a demonstrated failing regression.
Native Windows validation, reviewed frozen-source binding, SDK rebinding and
Expand Down
29 changes: 29 additions & 0 deletions docs/windows-quota-reproduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,32 @@ both `FILE_LIST_DIRECTORY` and `FILE_READ_ATTRIBUTES`, requires quota rejection,
and records the attribute observation independently. Native verification of
this corrected control remains required; neither fixture identifies the
protected descendant's cause.

## Complete readable snapshot recovery

Protected run
[34773356378](https://github.com/OpenCoven/chat/actions/runs/34773356378)
failed during the Cave build with `access-denied`, `root=cave-checkout`,
`directory-enumeration-depth-3-plus`, and `repeat=readable`. This establishes
that the same isolated identity could complete a fresh enumeration immediately
after the first attempt failed. It does not identify the private descendant or
prove whether build-directory replacement, deletion completion, or another
filesystem transition caused the first denial.

The accounting defect was that the monitor discarded that complete fresh
snapshot and terminated the producer. The repaired enumeration path accepts a
second result only when the first failure is `UnauthorizedAccessException` and
the second invocation of the same bounded snapshot core completes. A missing
or failing repeat remains terminal. Non-access-denied failures and non-directory
metadata reads preserve the diagnostic-only repeat behavior.

The native fixtures supply deterministic controls without changing production
ACLs. The owner-directory fixture keeps a real owner-only denial in place for
both enumerations and requires `repeat=persistent`. The isolated-reader fixture
then applies a real enumeration denial to the validated isolated identity,
checks both recovery callbacks run under that identity, temporarily reverts
only to restore the fixture ACL, verifies the retry is back under the isolated
identity before enumerating, and requires the fresh complete snapshot.
Independent terminal checks below and above the byte limit exercise the
production accounting path. It retains the existing path, entry, byte,
reparse, process, output, and time bounds.
14 changes: 7 additions & 7 deletions phase1-conformance.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
},
"harness": {
"repository": "OpenCoven/chat",
"revision": "d55b40c3315035be4267424b5d5d55c416bb609d"
"revision": "ad8d5f3e5e937c398c5d6d8f7bbbb190b4ed499a"
},
"harnessAuthority": {
"revision": "d55b40c3315035be4267424b5d5d55c416bb609d",
"tree": "ceb98c9ace85138ef8ddab5a6f7a0aeb7d2008fb",
"revision": "ad8d5f3e5e937c398c5d6d8f7bbbb190b4ed499a",
"tree": "dd4ffa0af4c39aefee9fc675ba5c804d7fe0e678",
"files": [
{
"path": "scripts/phase1-conformance.mjs",
Expand Down Expand Up @@ -116,8 +116,8 @@
},
{
"path": "scripts/windows-job-supervisor.cs",
"blob": "9ba3284eafac595e8bf2bd6b598832f346e0750a",
"sha256": "281acdeba5ee8dd022fd0451bd4ede6af8431aba8810f1683ce7077cc627fcb0"
"blob": "5791b0ffb7a3d20bdcbfb4774c1bad649d2bdbd8",
"sha256": "d08748d1a7ce3cc3964ce4520cc501f514d5777ed102ac5f57ebc20b75e7bb65"
},
{
"path": "scripts/contract-canary.mjs",
Expand Down Expand Up @@ -146,8 +146,8 @@
},
{
"path": ".github/workflows/client-v1-conformance.yml",
"blob": "a45c9311de3dd1b33688270bfbaae015fd8163f8",
"sha256": "a64fcdaf3fbd51e6cc0d3eb293ec5ac6a27df820182f0e89c272ce9cadfea566"
"blob": "b1306d09d7730d941086374a32fc245c9e09d18d",
"sha256": "e0d848fc82bd97d968b661a442420174d0690dd108d9a2c926c292f6505fb342"
}
],
"productionDeltas": [
Expand Down
71 changes: 55 additions & 16 deletions scripts/windows-job-supervisor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7413,29 +7413,63 @@ private static List<FileSystemInfo> ReadBoundedDirectorySnapshot(
int maximumEntries,
int depth = -1, bool repeatDiagnostic = false)
{
try
{
return ReadBoundedDirectorySnapshotCore(
string operation = directoriesOnly ? "pattern-enumeration" :
depth == 0 ? "directory-enumeration-root" :
depth == 1 ? "directory-enumeration-depth-1" :
depth == 2 ? "directory-enumeration-depth-2" :
depth >= 3 ? "directory-enumeration-depth-3-plus" : "directory-enumeration";
return ReadDirectorySnapshotOperation(
operation,
() => ReadBoundedDirectorySnapshotCore(
directory,
searchPattern,
directoriesOnly,
maximumEntries);
}
catch (Exception error)
{
string repeat = repeatDiagnostic ? ClassifyQuotaReadRepeat(() =>
ReadBoundedDirectorySnapshotCore(
maximumEntries),
repeatDiagnostic,
() => ReadBoundedDirectorySnapshotCore(
directory,
searchPattern,
directoriesOnly,
maximumEntries)) : "none";
maximumEntries,
true));
}

private static List<FileSystemInfo> ReadDirectorySnapshotOperation(
string operation,
Func<List<FileSystemInfo>> read,
bool repeatDiagnostic,
Func<List<FileSystemInfo>> repeatRead = null)
{
try { return read(); }
catch (Exception error)
{
string repeat = "none";
if (repeatDiagnostic && error is UnauthorizedAccessException)
{
try
{
return (repeatRead ?? read)();
}
catch (FileNotFoundException)
{
repeat = "missing";
}
catch (DirectoryNotFoundException)
{
repeat = "missing";
}
catch
{
repeat = "persistent";
}
}
else if (repeatDiagnostic)
{
repeat = ClassifyQuotaReadRepeat(repeatRead ?? read);
}
throw new QuotaMonitorContextException(
null,
directoriesOnly ? "pattern-enumeration" :
depth == 0 ? "directory-enumeration-root" :
depth == 1 ? "directory-enumeration-depth-1" :
depth == 2 ? "directory-enumeration-depth-2" :
depth >= 3 ? "directory-enumeration-depth-3-plus" : "directory-enumeration",
operation,
null,
repeat,
error);
Expand All @@ -7446,7 +7480,8 @@ private static List<FileSystemInfo> ReadBoundedDirectorySnapshotCore(
string directory,
string searchPattern,
bool directoriesOnly,
int maximumEntries)
int maximumEntries,
bool requireComplete = false)
{
List<FileSystemInfo> snapshot = new List<FileSystemInfo>();
IEnumerable<FileSystemInfo> entries;
Expand All @@ -7465,10 +7500,12 @@ private static List<FileSystemInfo> ReadBoundedDirectorySnapshotCore(
}
catch (FileNotFoundException)
{
if (requireComplete) throw;
return snapshot;
}
catch (DirectoryNotFoundException)
{
if (requireComplete) throw;
return snapshot;
}
using (enumerator)
Expand All @@ -7482,10 +7519,12 @@ private static List<FileSystemInfo> ReadBoundedDirectorySnapshotCore(
}
catch (FileNotFoundException)
{
if (requireComplete) throw;
break;
}
catch (DirectoryNotFoundException)
{
if (requireComplete) throw;
break;
}
if (!moved)
Expand Down
Loading
Loading