diff --git a/docs/evidence/2026-10-03-root-custody-finish-upload-rejected.json b/docs/evidence/2026-10-03-root-custody-finish-upload-rejected.json new file mode 100644 index 0000000..7145be6 --- /dev/null +++ b/docs/evidence/2026-10-03-root-custody-finish-upload-rejected.json @@ -0,0 +1 @@ +{"artifact": "root-custody-history-20261003T191242Z-7b4d49ff72344564adf69b498832ee20.json.age", "current_live_baseline_matches": true, "digest": "33a2ae086385028db1b654aa5646b7a98bcde1c5878c804e19315dadc3f87248", "error_code": "new_artifact_upload_failed", "finished_at": "2026-10-03T19:12:42.979494+00:00", "historical_config_present": true, "historical_credential_status": "historical-owner-and-revocation-unverified", "historical_share_matches_current_lane": false, "independent_escrow_recipient_matches_current_lane": true, "kv_version": 1, "ok": false, "record_id": "nk-custody:platform-root", "recorded_at": "2026-10-03T19:12:40.936033+00:00", "revision": 1, "stage": "provider_upload", "status": "failed", "upload_http_status": 401} \ No newline at end of file diff --git a/docs/evidence/2026-10-03-root-grant-delivery-progress.md b/docs/evidence/2026-10-03-root-grant-delivery-progress.md index 1e7bf1f..db21964 100644 --- a/docs/evidence/2026-10-03-root-grant-delivery-progress.md +++ b/docs/evidence/2026-10-03-root-grant-delivery-progress.md @@ -213,3 +213,35 @@ no key is created, reset or printed. A mismatch is a specific recovery blocker. Corrected attended retry with a new receipt is necessary to prove the actual provider roundtrip or expose its precise safe failure stage. The original failure's exact cause is still unknown, and provider readiness remains unproven. + +## Provider upload rejection diagnosed — 2026-10-03 + +Founder retried with fresh receipt +`/tmp/platform-root-finish-20261003T191229Z-333977.json`; the +[safe failure receipt](2026-10-03-root-custody-finish-upload-rejected.json) +reports `stage: provider_upload`, `error_code: new_artifact_upload_failed` and +HTTP 401. Current retained baseline matches revision 1/KV1/digest; existing +independent escrow recipient matches the governed lane. Historical local share +does not match the current lane; its revocation remains separately unverified. +No provider backup success is claimed. + +Source review found the custody upload omits `X-Requested-With: XMLHttpRequest`. +[Official Nextcloud WebDAV documentation](https://docs.nextcloud.com/server/stable/developer_manual/client_apis/WebDAV/basic.html) +requires this header on public DAV non-GET requests unless outgoing federation +is enabled; without it, the documented response is 401 Not Authenticated. +This is a concrete client defect and a likely explanation of the observed 401, +not proof that the current share credential is invalid or that header correction +already resolves this live instance. Producer is fixing/testing the protocol +request while retaining existing endpoint, credentials and permissions. A new +attended live result is still required. + +Producer protocol repair committed `50da37c`: custody public-DAV upload now sends +the required header, with a real local HTTP wire test verifying its presence and +conditional-create semantics. Shared migration request helper and common upload +client have the same scoped source correction. Forty-one tests passed (19 finish, +14 producer, eight backup credential checks); shell syntax and diff checks pass. +Failure receipts retain the backup lane's KV version. No token, endpoint, policy, +key or account-fallback change was made. Source synchronization does not establish +rollout of older vendored backup clients; owner records that refresh requirement +separately. The corrected custody finish command needs a new attended run and +fresh receipt to prove this live provider path. diff --git a/workplans/NK-WP-0045-root-grant-custody-record.md b/workplans/NK-WP-0045-root-grant-custody-record.md index 2e68384..6fb1afe 100644 --- a/workplans/NK-WP-0045-root-grant-custody-record.md +++ b/workplans/NK-WP-0045-root-grant-custody-record.md @@ -121,7 +121,7 @@ wait_kind: both blocked_on: message-from:railiance-platform needs_human: true intervention_note: "Run the prepared root-custody-finish-attended.sh through the existing founder OIDC/MFA route, with a fresh receipt. This is current restore/backup readback execution; design/go-forward approval is already recorded." -blocking_reason: "Live empty source, consumer rollout/restart/denial and audit correlation are verified. Remaining producer closure is attended current owner restore-check and governed encrypted retained-history provider upload/download/decryption evidence; no new design approval or real grant is required." +blocking_reason: "Live source/consumer/audit and current baseline/independent escrow checks pass. Provider upload rejected HTTP 401; producer is correcting the missing required public DAV request header. Closure requires a new attended encrypted history upload/readback/decryption receipt after the tested correction. No new design approval or real grant is required." priority: medium state_hub_task_id: "628e8a3b-17a4-5f97-a484-c564a87d650d" ``` @@ -389,3 +389,20 @@ real validator/age crypto and disposable backend/provider fixtures. Parent installed-wrapper smoke confirmed non-attended execution is refused with safe failure receipt. The same attended command is ready with a newly generated run ID; actual provider failure/success is not inferable until that receipt exists. + +Second actual finish attempt `20261003T191229Z-333977` produced a safe failure +receipt: current baseline and independent escrow checks pass; historical share +differs from current lane; provider upload returned HTTP 401. Review identified +a missing required public DAV `X-Requested-With: XMLHttpRequest` request header, +whose omission Nextcloud documents as a cause of 401. Producer is fixing the +client request without rotating credentials or expanding authority. T05 remains +blocked pending authenticated upload/readback/decryption after that correction; +the client defect alone does not establish an invalid provider credential. + +Protocol repair `50da37c` is implemented: exact public-DAV header added to custody +upload and shared platform clients, real HTTP wire test verifies the emitted +header and conditional-create request, failure receipt retains lane KV version. +Forty-one relevant tests pass; no credentials/endpoints/policies or account +fallback changed. Source-only refresh requirements for vendored backup workloads +are tracked by the platform owner and are not represented as deployed. T05 +awaits a fresh attended live finish receipt from the corrected source.