diff --git a/apps/api/src/services/credential_escrow_evidence_intake_readiness.py b/apps/api/src/services/credential_escrow_evidence_intake_readiness.py index b362fab10..95e0d18a0 100644 --- a/apps/api/src/services/credential_escrow_evidence_intake_readiness.py +++ b/apps/api/src/services/credential_escrow_evidence_intake_readiness.py @@ -254,6 +254,7 @@ def _build_payload( ) if effective_missing == 0 and not blocked_items: status = "ready_for_escrow_marker_review" + safe_next_step = "collect_redacted_non_secret_evidence_refs_then_rerun_preflight" payload = { "schema_version": _SCHEMA_VERSION, @@ -261,6 +262,7 @@ def _build_payload( "priority": "P0-005", "scope": "credential_escrow_evidence_intake", "status": status, + "safe_next_step": safe_next_step, "readback": { "workplan_id": "P0-005", "workplan_title": "產品資料與備份 contract", @@ -270,9 +272,7 @@ def _build_payload( "source_backup_dr_readiness_matrix_ref": ( "docs/evaluations/backup_dr_readiness_matrix_2026-06-04.json" ), - "safe_next_step": ( - "collect_redacted_non_secret_evidence_refs_then_rerun_preflight" - ), + "safe_next_step": safe_next_step, }, "required_evidence_items": missing_items, "forbidden_values": forbidden_values, diff --git a/apps/api/tests/test_credential_escrow_evidence_intake_readiness_api.py b/apps/api/tests/test_credential_escrow_evidence_intake_readiness_api.py index 2471e5f95..cfda109a7 100644 --- a/apps/api/tests/test_credential_escrow_evidence_intake_readiness_api.py +++ b/apps/api/tests/test_credential_escrow_evidence_intake_readiness_api.py @@ -27,6 +27,10 @@ def test_credential_escrow_evidence_intake_reports_p0_blocker(): assert payload["schema_version"] == "credential_escrow_evidence_intake_readiness_v1" assert payload["priority"] == "P0-005" assert payload["status"] == "blocked_waiting_non_secret_credential_escrow_evidence" + assert payload["safe_next_step"] == ( + "collect_redacted_non_secret_evidence_refs_then_rerun_preflight" + ) + assert payload["readback"]["safe_next_step"] == payload["safe_next_step"] assert payload["rollups"]["required_item_count"] == 5 assert payload["rollups"]["missing_item_count"] == 5 assert payload["rollups"]["effective_escrow_missing_count"] == 5 @@ -56,6 +60,9 @@ def test_credential_escrow_evidence_intake_endpoint_returns_readiness(): assert response.status_code == 200 data = response.json() assert data["priority"] == "P0-005" + assert data["safe_next_step"] == ( + "collect_redacted_non_secret_evidence_refs_then_rerun_preflight" + ) assert data["rollups"]["missing_item_count"] == 5 assert data["operation_boundaries"]["restore_execution_allowed"] is False assert data["operation_boundaries"]["workflow_trigger_allowed"] is False diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index fc74175c7..ecf3f9857 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -49516,3 +49516,24 @@ production browser smoke: - 沒有重啟主機,沒有 restart Docker / Nginx / K3s / DB / firewall。 - 沒有讀 secret / token / `.env` / raw sessions / SQLite / auth,沒有寫 credential marker。 - 沒有使用 GitHub / gh / GitHub API / GitHub Actions。 + +## 2026-06-29 — 15:34 P0-005 credential escrow readiness safe next step source fix + +**照優先順序完成的讀回**: +- P0-006:重新 verify-only 讀回 110 timer `enabled/active`、metric present,latest artifact `/home/wooo/reboot-recovery/reboot-auto-recovery-slo-20260629-153112`;仍只有 `host_boot_observation_older_than_target_window`,沒有 fresh reboot window,不做重啟。 +- P0-005:production GET `/api/v1/agents/credential-escrow-evidence-intake-readiness` 回傳 `missing_item_count=5`、`owner_response_accepted_count=0`、`runtime_gate_count=0`、`secret_value_collection_allowed=false`;同時發現 top-level `safe_next_step=null`。 + +**完成內容**: +- 修正 `apps/api/src/services/credential_escrow_evidence_intake_readiness.py`,把既有 `readback.safe_next_step` 同步到 top-level `safe_next_step`。 +- 補測 `apps/api/tests/test_credential_escrow_evidence_intake_readiness_api.py`,鎖住 top-level / readback safe next step 一致。 +- 更新 `docs/operations/awoooi-priority-work-order-readback.snapshot.json`,P0-005 下一步改成先 deploy/readback safe_next_step,再收五個 non-secret refs 跑單一 preflight。 + +**本地驗證結果**: +- `DATABASE_URL=sqlite+aiosqlite:////tmp/awoooi-codex-api-test.db python3.11 -m pytest apps/api/tests/test_credential_escrow_evidence_intake_readiness_api.py scripts/reboot-recovery/tests/test_dr_escrow_evidence_checklist.py scripts/security/tests/test_gitea_private_inventory_p0_scorecard.py -q`:`16 passed`。 +- `python3.11 -m py_compile apps/api/src/services/credential_escrow_evidence_intake_readiness.py scripts/reboot-recovery/dr-escrow-evidence-checklist.py scripts/security/gitea-private-inventory-p0-scorecard.py`:通過。 +- 本地 service readback:`safe_next_step=collect_redacted_non_secret_evidence_refs_then_rerun_preflight`,`missing_item_count=5`,`owner_response_accepted_count=0`,`runtime_gate_count=0`。 + +**仍維持**: +- 沒有讀 secret / token / `.env` / raw sessions / SQLite / auth,沒有寫 credential marker。 +- 沒有重啟主機,沒有 restart Docker / Nginx / K3s / DB / firewall。 +- 沒有使用 GitHub / gh / GitHub API / GitHub Actions。 diff --git a/docs/operations/awoooi-priority-work-order-readback.snapshot.json b/docs/operations/awoooi-priority-work-order-readback.snapshot.json index d1e20b778..bbe26dd0d 100644 --- a/docs/operations/awoooi-priority-work-order-readback.snapshot.json +++ b/docs/operations/awoooi-priority-work-order-readback.snapshot.json @@ -1,11 +1,11 @@ { "schema_version": "awoooi_priority_work_order_readback_v1", - "generated_at": "2026-06-29T15:24:00+08:00", - "status": "p0_ordered_readback_p0_006_timer_live_p0_005_escrow_missing_p0_003_public_inventory_refreshed", + "generated_at": "2026-06-29T15:34:00+08:00", + "status": "p0_ordered_readback_p0_006_timer_live_p0_005_safe_next_step_source_fixed_p0_003_public_inventory_refreshed", "source_refs": { "global_scorecard": "~/.codex/product-runtime-governance-completion-scorecard.snapshot.json", "workstation_dashboard": "~/.codex/codex-workstation-sync-dashboard.snapshot.json", - "post_reboot_summary": "/home/wooo/reboot-recovery/reboot-auto-recovery-slo-20260629-151707/summary.txt", + "post_reboot_summary": "/home/wooo/reboot-recovery/reboot-auto-recovery-slo-20260629-153112/summary.txt", "full_stack_cold_start_check": "scripts/reboot-recovery/full-stack-cold-start-check.sh --monitor-read-only --no-color", "delivery_closure_workbench": "https://awoooi.wooo.work/api/v1/agents/delivery-closure-workbench", "public_gitea_queue_readback": "ops/runner/read-public-gitea-actions-queue.py --json", @@ -16,7 +16,10 @@ "reboot_auto_recovery_slo_metric": "/home/wooo/node_exporter_textfiles/reboot_auto_recovery_slo.prom", "credential_escrow_live_status": "/tmp/awoooi-p0-005-escrow-status-live.txt", "dr_escrow_evidence_checklist_latest": "/tmp/awoooi-dr-escrow-evidence-checklist-current.json", - "gitea_repo_inventory_snapshot": "docs/security/gitea-repo-inventory.snapshot.json" + "gitea_repo_inventory_snapshot": "docs/security/gitea-repo-inventory.snapshot.json", + "credential_escrow_intake_readiness_api": "/api/v1/agents/credential-escrow-evidence-intake-readiness", + "credential_escrow_intake_readiness_service": "apps/api/src/services/credential_escrow_evidence_intake_readiness.py", + "credential_escrow_intake_readiness_tests": "apps/api/tests/test_credential_escrow_evidence_intake_readiness_api.py" }, "current_head": { "gitea_main_sha": "fe42ed1b4368800fca43ce040f8f498f0e88494f", @@ -111,8 +114,8 @@ { "workplan_id": "P0-005", "title": "產品資料與備份 contract", - "status": "checklist_ready_waiting_non_secret_credential_escrow_evidence", - "reason": "Live no-secret backup status is green for backup/offsite freshness, but all five DR credential escrow evidence refs are still missing. This lane stays on the single checklist and one preflight only.", + "status": "source_fixed_waiting_non_secret_credential_escrow_evidence", + "reason": "Production GET still reports five missing non-secret DR credential escrow evidence refs and zero accepted owner responses. The API source now exposes a top-level safe_next_step so downstream readbacks no longer receive null while the escrow evidence blocker remains honest.", "evidence": { "product_data_green": true, "stock_freshness_status": "ok", @@ -133,7 +136,16 @@ "rclone_gdrive_fresh": true, "escrow_status_live_checked": true, "live_no_secret_status_path": "/tmp/awoooi-p0-005-escrow-status-live.txt", - "checklist_latest_path": "/tmp/awoooi-dr-escrow-evidence-checklist-current.json" + "checklist_latest_path": "/tmp/awoooi-dr-escrow-evidence-checklist-current.json", + "credential_escrow_intake_api_route_live_checked": true, + "production_missing_item_count": 5, + "production_owner_response_accepted_count": 0, + "production_runtime_gate_count": 0, + "production_secret_value_collection_allowed": false, + "production_top_level_safe_next_step_was_null_before_source_fix": true, + "source_top_level_safe_next_step_present": true, + "source_safe_next_step": "collect_redacted_non_secret_evidence_refs_then_rerun_preflight", + "focused_p0_005_tests_passed": 16 }, "missing_items": [ "restic_repository_password", @@ -157,7 +169,7 @@ "Do not create additional owner-package variants for the same five refs." ] }, - "safe_next_step": "fill_single_dr_escrow_evidence_checklist_with_five_non_secret_refs_then_run_one_preflight" + "safe_next_step": "deploy_and_read_back_credential_escrow_safe_next_step_then_collect_five_non_secret_refs_and_rerun_preflight" }, { "workplan_id": "P0-003", @@ -253,7 +265,7 @@ ], "host_188_service_green": true, "safe_next_step_from_scorecard": "timer_deployed_and_services_readback_green_wait_for_next_all_host_reboot_event_or_approved_reboot_drill_to_prove_10_minute_slo", - "latest_live_slo_artifact": "/home/wooo/reboot-recovery/reboot-auto-recovery-slo-20260629-151707" + "latest_live_slo_artifact": "/home/wooo/reboot-recovery/reboot-auto-recovery-slo-20260629-153112" }, "professional_fix": { "owner": "reboot auto-recovery lane", @@ -345,7 +357,7 @@ }, "next_execution_order": [ "P0-006: keep the live reboot SLO timer active; no reboot or service restart from this lane; next proof is the next fresh all-host reboot event or separately approved reboot drill.", - "P0-005: fill the single DR escrow evidence checklist with five non-secret refs, then rerun one preflight; backup/offsite freshness is already green.", + "P0-005: deploy/read back the credential escrow readiness safe_next_step source fix, then collect five non-secret refs and rerun one preflight; backup/offsite freshness is already green.", "P0-003: complete Gitea authenticated/admin redacted inventory export or owner coverage attestation; public-only live inventory is refreshed to four repos; GitHub remains stopped/retired/do_not_use." ] }