{
  "schema_version": "stockplatform_public_api_runtime_recovery_control_receipt_v1",
  "generated_at": "2026-06-30T18:52:40+08:00",
  "status": "api_upstream_recovered_data_readiness_not_green",
  "priority": "P0-006",
  "scope": "stockplatform_public_api_runtime_recovery_control_path",
  "target_selector": {
    "product": "stockplatform-v2",
    "public_base_url": "https://stock.wooo.work",
    "target_endpoints": [
      "/api/healthz",
      "/api/v1/system/freshness",
      "/api/v1/system/ingestion"
    ],
    "expected_after_apply": "all target endpoints return HTTP 200; freshness.status=ok; ingestion.status=ok"
  },
  "source_of_truth_diff": {
    "repo": "wooo/stockplatform-v2",
    "gitea_main_sha": "080bc2b2eed796b4412bb34b736c87121fb7b3b8",
    "commit_subject": "fix(ops): recover stock api upstream resolution",
    "supporting_commits": [
      {
        "sha": "3cd2d824047ed02336cfa4d8f2f39c5f9f4458b5",
        "subject": "fix(deploy): fail closed on stockplatform api health"
      },
      {
        "sha": "080bc2b2eed796b4412bb34b736c87121fb7b3b8",
        "subject": "fix(ops): recover stock api upstream resolution"
      }
    ],
    "files_changed": [
      "infra/nginx/stockplatform-v2-edge.admin-auth.conf",
      "infra/nginx/stockplatform-v2-edge.conf",
      "infra/scripts/deploy-production.sh",
      "package.json",
      "scripts/ops/stockplatform-api-upstream-recovery-gate.sh",
      "scripts/ops/test-stockplatform-api-upstream-recovery-gate.sh",
      "scripts/ops/test-production-deploy-contract.sh"
    ],
    "change_summary": [
      "production deploy uses .env.production.local instead of compose defaults",
      "edge is restarted after app containers are recreated to avoid stale api upstream resolution",
      "local /api/healthz must return 200 before deploy can emit success receipt",
      "edge nginx uses Docker DNS dynamic upstream resolution for api/web/admin",
      "api upstream recovery gate provides verify-only, dry-run, and bounded apply modes",
      "npm run check now includes the production deploy contract test"
    ]
  },
  "check_mode_or_dry_run": {
    "performed": true,
    "commands": [
      "npm run check",
      "python3 -m compileall -q apps/api services/worker services/scheduler scripts/ingestion scripts/migration",
      "curl https://stock.wooo.work/api/healthz",
      "curl https://stock.wooo.work/api/v1/system/freshness",
      "curl https://stock.wooo.work/api/v1/system/ingestion"
    ],
    "result": "source checks passed; live public API upstream is HTTP 200, but freshness and ingestion return status=not_configured with postgres_not_ready"
  },
  "rollback": {
    "available": true,
    "command": "git revert 080bc2b2eed796b4412bb34b736c87121fb7b3b8 3cd2d824047ed02336cfa4d8f2f39c5f9f4458b5 && rerun stockplatform production deploy and upstream recovery contract checks before any runtime apply"
  },
  "post_apply_public_api_verifier": {
    "prepared": true,
    "last_pre_apply_readback": {
      "public_web_healthz": 200,
      "public_api_healthz": 200,
      "freshness": 200,
      "freshness_status": "not_configured",
      "freshness_blockers": [
        "postgres_not_ready"
      ],
      "ingestion": 200,
      "ingestion_status": "not_configured",
      "ingestion_blockers": [
        "postgres_not_ready"
      ]
    },
    "passed": false
  },
  "provided_receipts": [
    "target_selector",
    "source_of_truth_diff_or_runtime_state_diff",
    "check_mode_or_dry_run",
    "rollback_command",
    "controlled_api_upstream_recovery_readback",
    "km_playbook_log_writeback_receipt"
  ],
  "missing_receipts": [
    "stockplatform_postgres_readiness_or_data_source_readback",
    "post_apply_public_api_verifier_green"
  ],
  "active_blockers": [
    "stockplatform_postgres_not_ready",
    "stockplatform_post_apply_public_api_verifier_not_green"
  ],
  "safe_recovery_channels": [
    "bounded_stockplatform_postgres_readiness_readback_without_manual_db_write",
    "bounded_ssh_or_runner_recovery_readback_without_docker_daemon_restart"
  ],
  "forbidden_recovery_channels": [
    "docker_daemon_restart",
    "host_reboot",
    "docker_prune_or_volume_restore",
    "manual_database_rows_or_fake_freshness",
    "restore_push_deploy_trigger_during_110_capacity_freeze",
    "read_secret_or_raw_session_values"
  ],
  "required_receipts": [
    "target_selector",
    "source_of_truth_diff_or_runtime_state_diff",
    "check_mode_or_dry_run",
    "rollback_command",
    "post_apply_public_api_verifier",
    "km_playbook_log_writeback_receipt"
  ],
  "operation_boundaries": {
    "workflow_dispatch_performed": false,
    "host_write_performed": false,
    "docker_restart_performed": false,
    "docker_daemon_restart_performed": false,
    "host_reboot_performed": false,
    "database_write_or_restore_performed": false,
    "secret_or_runner_token_read": false,
    "github_api_used": false
  }
}
