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
16 changes: 8 additions & 8 deletions .github/workflows/client-v1-conformance.yml

Large diffs are not rendered by default.

77 changes: 68 additions & 9 deletions docs/phase1-conformance.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
# Phase 1 real-authority conformance

## Bounded quota retry categories

Protected [run 35146928092](https://github.com/OpenCoven/chat/actions/runs/35146928092)
used Chat #311 at `157fb3206b9b90f24049aa2043bae534d2b9a709` and SDK #293 at
`3459dcaad0877bbef2a25da24fbd521879ef020e`. Windows failed with `access-denied`,
root `harness-execution-aggregate`, scope `checkouts`, operation
`directory-enumeration-depth-3-plus`, and repeat `persistent`. Linux and macOS
records passed identity, timing, privacy, schema, and all 197 ordered assertions.
Windows emitted no record, and no accepted aggregate exists. This earlier quota
failure does not establish that the Cave build home repair passed isolation.

The legacy `persistent` label means the repeat threw a non-missing exception.
It does not prove a second access denial. The bounded diagnostic now preserves
the initial category and reports the repeat as `persistent-<category>`, using
only the existing fixed exception categories. For example, first-attempt access
denial followed by an I/O failure reports `access-denied` with `persistent-io`;
two access denials report `access-denied` with `persistent-access-denied`.
Legacy `persistent` remains accepted by the context normalizer.

Run the portable classification and non-recovery checks with:

```sh
pwsh -NoLogo -NoProfile -NonInteractive -File scripts/windows-quota-diagnostics.test.ps1
```

The regression matrix covers every fixed repeat category, rejects private text,
preserves the first failure, and requires one whole-pass attempt for each
non-recoverable result. The change adds no retries and changes no quotas,
permissions, or recovery predicates. Native Windows fixtures require the refined
labels; their execution remains a delivery gate. Reviewed producer binding,
actual-merge SDK rebinding, both scope rotations, and fresh protected validation
remain required before claiming acceptance or identifying the failing checkout.

## Cave build home isolation checkpoint

Protected run `35138402347` failed on Windows with
Expand Down Expand Up @@ -214,8 +247,8 @@ assignment, RPC decoder and primary/secondary exception pipeline. This fixture
correction does not establish the protected installation failure's cause or
relax the round-trip assertions.

The lock now selects reviewed source `a3dc4d91c89519747e5393792669ebcc0a8163c7`,
tree `dca75084413e733e04a7f43ca8aa7670815421b5`, including all 25 governed files
The lock now selects reviewed source `0a35e571de69c3f17b2f490974caec36b34205a5`,
tree `4f98b5cff7ac65d7229c136490265ea60d2cd764`, including all 25 governed files
and ten production deltas. The checkout regression exercises all five labels
from that immutable revision. SDK rebinding, both scope rotations and fresh
protected validation remain required; this binding alone is not acceptance.
Expand Down Expand Up @@ -2020,7 +2053,7 @@ revision authorities can therefore have different workflow hashes:

| File | Bytes | SHA-256 |
| --- | ---: | --- |
| `.github/workflows/client-v1-conformance.yml` | 177,934 | `79ba921d0bb49c2e88ac5253928e44489462fc80b2ac98b53ab9ed13533fba87` |
| `.github/workflows/client-v1-conformance.yml` | 178,086 | `3c2f0d5423533b7b2c6d601e9f91a250064704bceeb4e53090ebecc935cacb09` |
| `scripts/contract-canary.mjs` | 40,618 | `a4c2fe0a5eb6a5ff4653de5374c34c0fb46907c6806a5d23b86d8b37206ef958` |
| `scripts/executable-resolution.mjs` | 9,154 | `31e3c412ff8c835f14522f36a59e91f4a4ba82913210ae8e3b4455217503f430` |
| `scripts/owned-temp-directory.mjs` | 7,762 | `95f546ef9ed614f2a0f55d356ddfc54c943fc53b595b4eebebfcbd4db68e5c0b` |
Expand All @@ -2033,7 +2066,7 @@ revision authorities can therefore have different workflow hashes:
| `scripts/phase1-macos-keychain.mjs` | 5,091 | `ab0c2dd08cf606d9502f5da206175707d471d99f484e8c8c79b5b08a5772b9a4` |
| `scripts/phase1-process-supervisor.mjs` | 3,820 | `16b51fb1a33b4bfef98daca549aacf5dc2d2c098cfbd664753b69c940d1e6f6c` |
| `scripts/phase1-schema-v2-evidence.mjs` | 52,505 | `0aede2ab3abd76fabf5ac61d64d2dbaaffa497c8647b82236403de16a47751c8` |
| `scripts/phase1-schema-v2-producer.mjs` | 233,796 | `1d0c28f526c3e71256693da6ef26be6fe2327cb30e820960a4cf3761c4b8c4f6` |
| `scripts/phase1-schema-v2-producer.mjs` | 233,914 | `ea32a0b7d43f0558521de091666d66960bc033afafd5e619a728da1ec5d45929` |
| `scripts/process-owned-artifact-root.mjs` | 13,061 | `103cc789f12a6bbde16b2414aecf05813d9d28a2c40c7d6eaa2073b86e8e5d77` |
| `scripts/supervised-exec.mjs` | 2,875 | `a5edfd985b934d3b46247a0da3141682c411d30bb582edf87ae7b29791dad65b` |
| `scripts/supervisor-status.mjs` | 854 | `ac332ca7b6b040ecc846088bb3a6ad5e7112a0454eb3ea71d2a819d55e64254e` |
Expand All @@ -2045,11 +2078,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` | 396,176 | `6f7d0712e8f0b04d5c3fdff77a3cb975cc96a2f5c2bd5e565b43277b7085c030` |
| `scripts/windows-job-supervisor.cs` | 397,084 | `ec56ad9daf9cfd2e92de4420cfc5ce328e09a76b627a8253ef35f2e9ef151669` |
| `scripts/windows-job-supervisor.test.ps1` | 201,048 | `0b9828c2cd801799bc0055fe4047e1e914ee7fcc921345dee6b0caa3a389386a` |
| `scripts/windows-quota-diagnostics.test.ps1` | 38,067 | `97fdb3b08aca19ceb31e6affb5e211cada9a860ccceae26df03816507d981492` |
| `scripts/windows-owner-directory-quota.test.ps1` | 14,775 | `605b57608bf4ef2939759d32df6ac1685027bdd864aaaab44dac15ab90de51ec` |
| `scripts/windows-quota-isolated-reader.test.ps1` | 24,186 | `7b926d3f663eee69790ce01945efd83d14e332df876423eab7f6c44622824253` |
| `scripts/windows-quota-diagnostics.test.ps1` | 39,744 | `f22177fd3b079a29333627f9a37c55a0a288010062685ffc9b08392f7b65b97d` |
| `scripts/windows-owner-directory-quota.test.ps1` | 14,789 | `a6fccce4e1e41b06c655bc1a70bf870ba115f0848ee647777d2606294483cd1f` |
| `scripts/windows-quota-isolated-reader.test.ps1` | 24,200 | `22f3baa7272f0bf7f03e44b3dec98398a96e64a8b507ce5b11925bd777d58a31` |
| `scripts/windows-quota-lifetime.test.ps1` | 2,513 | `dd10741c19cd97cc1b9ee29ebe18b8381503d589680acd0eddaabda08b5e7aec` |
| `scripts/windows-identity-cleanup-diagnostics.test.ps1` | 7,317 | `d141b33fb24d8a819211c4d303cf55357f2ef249c639e51c87e738bb5725f410` |
| `scripts/windows-cleanup-delete-diagnostics.test.ps1` | 7,433 | `e9d30285a1fe0ad035637621c6a3840eb8a6194b2f23e1a4aa188c5884cd0c64` |
Expand Down Expand Up @@ -2788,6 +2821,32 @@ Fresh reviewed source binding, SDK rebinding, and protected validation are
required before attributing the Windows failure or claiming a repaired run.


### Unsupported custody installation

`secure_store_unavailable` covered two unrelated causes on the installation
preflight. `KeyringError::Unavailable` is returned both by a secure store that
is genuinely unavailable and by `CredentialCustody::installation_id`'s default
trait body, which a custody implementation reaches only by never overriding it.
`InstallationStage::classify` already rewrites `Unavailable` into
`installation_lock_unavailable`, `installation_entry_unavailable`,
`installation_read_unavailable`, `installation_write_unavailable` and
`installation_persistence_unavailable`, so those five stages were already
distinguishable; the default trait body was the remaining unclassified path.

It now returns the fixed code `installation_custody_unsupported`, published as
`phase1.native-scenarios.native-preflight-installation-custody-unsupported`.
The outer launcher derives its native-stage allowlist from the producer
registry, so the identifier survives extraction without a second edit. Only the
fixed identifier is published: no message, stack, path, credential or
subprocess output is added.

Protected run
[35100084575](https://github.com/OpenCoven/chat/actions/runs/35100084575)
reported `native-preflight-installation-secure-store-unavailable` on Windows
while Linux and macOS passed. This change does not repair that failure and does
not establish its cause; it separates the two causes so the next protected run
attributes it.

### Unexpected installation RPC failures

Protected run `34964120550` used Chat `d84195c61b86598e691ccd47163e46a15b154417`
Expand Down Expand Up @@ -2888,7 +2947,7 @@ validation, attestation, and aggregation were skipped.
`ReadBoundedDirectorySnapshot` materializes a bounded snapshot. On access denial,
`ReadDirectorySnapshotOperation` performs one fresh, complete snapshot read under the
existing quota-reader identity. A successful repeat supplies the measurement; a missing
directory is classified separately. Any other repeat exception produces `persistent`,
directory is classified separately. In that historical producer, any other repeat exception produced `persistent`,
while the initial access-denied category is preserved. An injected access denial followed
by an I/O exception now exercises that distinction through the production snapshot seam.
Thus the log does not prove two identical ACL failures, a particular checkout, a denied
Expand Down
26 changes: 25 additions & 1 deletion docs/roadmap.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
# Delivery roadmap and consolidation audit

## Current delivery and consolidation checkpoint, 2026-09-16 (Chat #305)
## Current protected-validation checkpoint, 2026-09-16 (Chat #311)

Chat [#311](https://github.com/OpenCoven/chat/pull/311) landed at
`157fb3206b9b90f24049aa2043bae534d2b9a709`. SDK
[#293](https://github.com/OpenCoven/sdk/pull/293) rebound that producer at
`3459dcaad0877bbef2a25da24fbd521879ef020e`; both validator scopes were rotated.
Protected [run 35146928092](https://github.com/OpenCoven/chat/actions/runs/35146928092)
failed on Windows during quota enumeration. Linux and macOS passed all 197 ordered
assertions and record checks. No Windows record or accepted aggregate exists.
The earlier quota failure leaves the Cave build home isolation repair unproven.

The next diagnostic distinguishes a repeated access denial from a changed I/O
failure while preserving first-failure reporting and fail-closed behavior. See
[bounded quota retry categories](phase1-conformance.md#bounded-quota-retry-categories).
Native Windows verification, reviewed producer delivery, SDK rebinding, both
scope rotations, and a fresh protected run remain open.

Custody integration [#313](https://github.com/OpenCoven/chat/pull/313) replaces the
stale binding in #307 and must land before its replacement can be closed. Preserve
active worktrees and the running Chat app. WorkOS #303, parked draft #86, the
managed HPKE iterator authority gap, and Project 9 reconciliation remain separate
open work. Historical inventories below are dated snapshots, not current deletion
authority. Publication remains disabled, and consolidation remains incomplete.

## Historical delivery and consolidation checkpoint, 2026-09-16 (Chat #305)

Chat [#305](https://github.com/OpenCoven/chat/pull/305) landed at
`1f69306293f8caf873e0a2d6459a5c402e77600a`, followed by SDK
Expand Down
22 changes: 11 additions & 11 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": "a3dc4d91c89519747e5393792669ebcc0a8163c7"
"revision": "0a35e571de69c3f17b2f490974caec36b34205a5"
},
"harnessAuthority": {
"revision": "a3dc4d91c89519747e5393792669ebcc0a8163c7",
"tree": "dca75084413e733e04a7f43ca8aa7670815421b5",
"revision": "0a35e571de69c3f17b2f490974caec36b34205a5",
"tree": "4f98b5cff7ac65d7229c136490265ea60d2cd764",
"files": [
{
"path": "scripts/phase1-conformance.mjs",
Expand Down Expand Up @@ -81,8 +81,8 @@
},
{
"path": "scripts/phase1-schema-v2-producer.mjs",
"blob": "942917311fbb26d60fa1d38d8becbd6193b6799d",
"sha256": "1d0c28f526c3e71256693da6ef26be6fe2327cb30e820960a4cf3761c4b8c4f6"
"blob": "720445dfaf8ceb071f966bccbc8111a350c31ed0",
"sha256": "ea32a0b7d43f0558521de091666d66960bc033afafd5e619a728da1ec5d45929"
},
{
"path": "scripts/phase1-linux-secret-service.mjs",
Expand Down Expand Up @@ -116,8 +116,8 @@
},
{
"path": "scripts/windows-job-supervisor.cs",
"blob": "8e4098edace18b95813e7cd6610f3338fe5292b4",
"sha256": "6f7d0712e8f0b04d5c3fdff77a3cb975cc96a2f5c2bd5e565b43277b7085c030"
"blob": "c6ddcb12a3b439b04e1272b8b26d110a8372c973",
"sha256": "ec56ad9daf9cfd2e92de4420cfc5ce328e09a76b627a8253ef35f2e9ef151669"
},
{
"path": "scripts/contract-canary.mjs",
Expand Down Expand Up @@ -146,8 +146,8 @@
},
{
"path": ".github/workflows/client-v1-conformance.yml",
"blob": "4e693a7c780265823bd041ec9f2972006bfd00b5",
"sha256": "79ba921d0bb49c2e88ac5253928e44489462fc80b2ac98b53ab9ed13533fba87"
"blob": "1bfcccfe5bbbc864182bcc8d8a5e3aa2ba7189ee",
"sha256": "3c2f0d5423533b7b2c6d601e9f91a250064704bceeb4e53090ebecc935cacb09"
}
],
"productionDeltas": [
Expand Down Expand Up @@ -193,8 +193,8 @@
},
{
"path": "src-tauri/src/keyring.rs",
"blob": "86596dc1b16caab42f9817e09a25e91bc8469527",
"sha256": "ce0a9216f645998d1944a69366ff49dcdb18e6068fec9a4c63bc8d61699e9e10"
"blob": "39309e546d975349df16acbca9b47dee5beab6ce",
"sha256": "8b143925f1796c79ad67d2dfe4b05a6396b7278875a67e7885ca7e7ae9605c54"
},
{
"path": "src-tauri/src/lib.rs",
Expand Down
2 changes: 2 additions & 0 deletions scripts/phase1-schema-v2-producer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ const nativeLaunchPublicationFailures = new WeakMap();
const nativeRpcFailureCategories = new WeakMap();
const nativeInstallationResponseCategories = new Map([
['secure_store_unavailable', 'secure-store-unavailable'],
['installation_custody_unsupported', 'custody-unsupported'],
['installation_lock_unavailable', 'lock-unavailable'],
['installation_entry_unavailable', 'entry-unavailable'],
['installation_read_unavailable', 'read-unavailable'],
Expand Down Expand Up @@ -173,6 +174,7 @@ const schemaV2NativeFailureStages = new Set([
'native-preflight-custody-proof',
'native-preflight-installation-rpc',
'native-preflight-installation-secure-store-unavailable',
'native-preflight-installation-custody-unsupported',
'native-preflight-installation-lock-unavailable',
'native-preflight-installation-entry-unavailable',
'native-preflight-installation-read-unavailable',
Expand Down
25 changes: 21 additions & 4 deletions scripts/windows-job-supervisor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8271,9 +8271,9 @@ private static List<FileSystemInfo> ReadDirectorySnapshotOperation(
{
repeat = "missing";
}
catch
catch (Exception repeatError)
{
repeat = "persistent";
repeat = ClassifyPersistentQuotaRepeat(repeatError);
}
}
else if (repeatDiagnostic)
Expand Down Expand Up @@ -8870,6 +8870,18 @@ private static string NormalizeQuotaRepeat(string repeat)
case "readable":
case "missing":
case "persistent":
case "persistent-entry-bound":
case "persistent-access-denied":
case "persistent-arithmetic-overflow":
case "persistent-io":
case "persistent-io-file-not-found":
case "persistent-io-path-not-found":
case "persistent-io-sharing-violation":
case "persistent-io-lock-violation":
case "persistent-io-name-too-long":
case "persistent-io-invalid-directory":
case "persistent-io-delete-pending":
case "persistent-unexpected":
return repeat;
default: return "none";
}
Expand All @@ -8890,12 +8902,17 @@ private static string ClassifyQuotaReadRepeat<T>(Func<T> retry)
{
return "missing";
}
catch
catch (Exception repeatError)
{
return "persistent";
return ClassifyPersistentQuotaRepeat(repeatError);
}
}

private static string ClassifyPersistentQuotaRepeat(Exception error)
{
return NormalizeQuotaRepeat("persistent-" + ClassifyQuotaMonitorError(error));
}

private static T ReadQuotaOperation<T>(string operation, Func<T> read, bool repeatDiagnostic = false, Func<T> repeatRead = null)
{
try { return read(); }
Expand Down
2 changes: 1 addition & 1 deletion scripts/windows-owner-directory-quota.test.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ try {
$readBoundedSnapshot,
$directory
)
if ($persistentOutcome -cne 'access-denied|directory-enumeration-depth-3-plus|persistent') {
if ($persistentOutcome -cne 'access-denied|directory-enumeration-depth-3-plus|persistent-access-denied') {
throw 'Persistent native directory denial did not remain fail-closed.'
}
[OpenCoven.Tests.QuotaSnapshotReadFixture]::BeforeReadableRepeat = [Action]{
Expand Down
30 changes: 14 additions & 16 deletions scripts/windows-quota-delete-pending.test.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -122,19 +122,17 @@ function Get-QuotaObservation([string] $Path) {
$property.GetValue($cause)
}
$result = $values -join ':'
if ($result -cnotin @(
'access-denied:directory-attributes:persistent',
'access-denied:directory-attributes:readable',
'access-denied:directory-attributes:missing',
'access-denied:directory-enumeration-root:persistent',
'access-denied:directory-enumeration-root:readable',
'access-denied:directory-enumeration-root:missing',
'io:directory-attributes:persistent',
'io:directory-attributes:readable',
'io:directory-attributes:missing',
'io:directory-enumeration-root:persistent',
'io:directory-enumeration-root:readable',
'io:directory-enumeration-root:missing')) {
$allowedRepeats = @(
'readable', 'missing', 'persistent', 'persistent-entry-bound',
'persistent-access-denied', 'persistent-arithmetic-overflow',
'persistent-io', 'persistent-io-file-not-found', 'persistent-io-path-not-found',
'persistent-io-sharing-violation', 'persistent-io-lock-violation',
'persistent-io-name-too-long', 'persistent-io-invalid-directory',
'persistent-io-delete-pending', 'persistent-unexpected'
)
if ($values[0] -cnotin @('access-denied', 'io') -or
$values[1] -cnotin @('directory-attributes', 'directory-enumeration-root') -or
$values[2] -cnotin $allowedRepeats) {
throw 'Unexpected bounded quota classification.'
}
return $result
Expand All @@ -158,8 +156,8 @@ try {
$pendingAttributes = Get-AttributeObservation $pendingPath
$pendingQuota = Get-QuotaObservation $pendingPath
Write-Host "Delete-pending fixture: attributes=$pendingAttributes; quota=$pendingQuota."
if ($pendingAttributes -ceq 'access-denied' -and $pendingQuota -ceq 'access-denied:directory-attributes:persistent') {
Write-Host 'Delete-pending fixture reproduced the managed quota signature; protected-run cause remains unproven.'
if ($pendingAttributes -ceq 'access-denied' -and $pendingQuota -ceq 'access-denied:directory-attributes:persistent-access-denied') {
Write-Host 'Delete-pending fixture reproduced the legacy first-error signature with a repeated access denial; protected-run cause remains unproven.'
} else {
Write-Host 'Delete-pending fixture did not reproduce the protected signature; deletion hypothesis remains inconclusive.'
}
Expand All @@ -173,7 +171,7 @@ try {
$deniedAttributes = Get-AttributeObservation $deniedPath
$deniedQuota = Get-QuotaObservation $deniedPath
Write-Host "ACL-denied fixture: attributes=$deniedAttributes; quota=$deniedQuota."
if ($deniedQuota -cnotin @('access-denied:directory-attributes:persistent', 'access-denied:directory-enumeration-root:persistent')) {
if ($deniedQuota -cnotin @('access-denied:directory-attributes:persistent-access-denied', 'access-denied:directory-enumeration-root:persistent-access-denied')) {
throw 'Explicit directory-read denial did not reject quota traversal.'
}
$security.Dispose()
Expand Down
Loading
Loading