Files
ai-contract-platform/project-docs/V2-production-rollback-capacity-audit-2026-08-12.md
yuqei ce7e040e98
Build and Test Quality Gate / Contract Web typecheck and build (pull_request) Successful in 7m28s
Build and Test Quality Gate / Python tests and Contract API migration (pull_request) Failing after 26m12s
Security Quality Gate / npm audit, Bandit, pip-audit, detect-secrets (pull_request) Successful in 6m33s
feat: close production trust and operations gates
2026-08-12 12:58:10 +08:00

11 KiB

V2 production rollback and capacity audit

Date: 2026-08-12

Scope and safety boundary

This audit began with repository tests and read-only SSH checks, then used an authorized maintenance window for backup/restore verification and a complete application rollback/forward rehearsal. The public edge remained stopped. PostgreSQL, Redis and MinIO were not rolled back, no database downgrade was run, and DNS/public traffic were not changed.

Result

The primary-host capacity policy is currently within its configured limits, but it has little percentage headroom: the latest production health artifact reported / at 84.45% used with 28.90 GiB free, immediately below the 85% warning ceiling. /home was 16.94% used with 192.14 GiB free, and the off-host backup mount was 14.42% used with 68.24 GiB free. Both required paths were observed as separate mounts by the production health probe.

Capacity code and repository-level alert behavior pass their automated tests. The production health unit wires the protected PRODUCTION_ALERT_WEBHOOK_URL_FILE into the probe, and production preflight fails closed unless that file contains an owner-restricted HTTPS URL. A receiver on the independent host 47.94.178.212 accepted the controlled warning and returned a receiver-side event ID, receipt time and body hash. The normal 85% threshold was restored and reported / at 84.45%, status pass.

The production timer remains enabled while the edge is intentionally stopped, so the edge check is expected to fail closed. To avoid sending the identical known failure every minute, the probe now retains an atomic, non-secret alert state: the first failure, any check-set change and an hourly reminder are sent; failed delivery retries on the next run; a healthy run resets the state.

A complete application version rollback and forward restoration was rehearsed from current release d6a6752258a555f3a40894cdcf88917659538492 to approved previous release c24f7a4f1ee041d92feca96bf147e423e58da17c, then back to the current release. All four application services were stopped/recreated in both directions. The Contract API and worker digests were identical between those releases; the AI API image changed. This limitation is recorded rather than misrepresenting the exercise as four distinct image rollbacks. Health, schemas, worker readiness, contract/template reads and audit/outbox continuity passed in both directions. The alert and complete version rollback gates are closed.

Read-only field evidence

Primary host: 192.168.3.90 (host-reported name 10.20.0.11).

Observed production services:

  • Contract API, Contract review worker, AI Platform API, AI worker, PostgreSQL, Redis and MinIO were running and healthy.
  • Contract API was pinned to git.yuqei.com/yuqei/ai-contract-platform-contract-api@sha256:a6969d90680f866232f1ad2c09607fd63f226476028b6c0f34c3175e7407549f.
  • AI Platform API was pinned to git.yuqei.com/yuqei/ai-contract-platform-ai-api@sha256:05faf2aa67d258708387daa7007442928b8d786814f1c5e8a619db4b1ae9d8b3.
  • The latest normal-policy production health artifact had status fail only because edge_health returned HTTP 503. Contract/AI health, schema checks, Provider runtime, worker health, backup freshness and all three capacity checks passed.
  • A controlled capacity warning was received as event yuqei-alert-45b05755b2fc4c498dd4eb8cd3c426ed; its posted body SHA-256 was 933d5741e600efec3190e79892a93165bb94a57f00976184fde31ec43148eeff.
  • The receiver-owned mode 0600 receipt SHA-256 was 8816696a8829215ce7e7821a0965d35d48a27651c89b1a267846d84bd664f909.
  • Backup backup-20260812T025650Z completed in quiesced mode with four artifacts. Disposable restoration of all three PostgreSQL databases passed; summary SHA-256 was 70e6c223a6870dd0d8fe28365bda7f883fc6827a77ddcc0da397dd77cbee4370.
  • /etc/yuqei/production.env existed with mode 0600.
  • yuqei-production-health.timer was enabled and active at a one-minute cadence.
  • /etc/yuqei/monitoring/alert-webhook-url is configured without exposing its secret URL in repository evidence. It is mode 0600, owned by the unprivileged probe account. The receiver is loopback-bound behind HTTPS.
  • After deploying deduplication, the first expected edge_health failure was delivered as yuqei-alert-9014cb51c85241f5b63836bf8cb1a510; an immediate second identical run recorded duplicate_within_resend_window, did not call the receiver, left the timer active and kept the edge replica count at 0.
  • Current production read-only preflight passed with failed=0. Its retained summary SHA-256 is 3b1e2e3b25272adf4c1443fb98cbe7284b520d82808836f879de58c4e4240556.

Complete rollback and forward evidence

  • Remote evidence directory: /opt/apps/ai-contract-platform-v2-production/project-docs/qa-artifacts/v2-production-full-rollback/20260812T030852Z.
  • Manifest SHA-256: 2ac616acc69868a8274ab0047d42dcdcd2b8ff29660ac68486fcbdc007d1d4a4.
  • Evidence file count: 40; manifest status: passed.
  • Before, rollback and forward phases all passed Contract health/schema, AI health/schema, worker health, contract-list read, template-list read and audit/outbox count continuity.
  • The edge replica count remained 0. Provider readiness remained blocked by the intentional kill switch and, on the previous release, missing receipt binding. This is expected fail-closed behavior, not a failed recovery check.
  • An exit trap restored the current environment on any failure. Final inspection confirmed the current release and all four application services healthy.

Independent public-policy trust evidence

  • Legal approval ID: policy-approval-0887bbd5149bf7a1c41cb35e.
  • Trust request SHA-256: d2d76ee0789b235af67f1df3ae3a86237467ca72bbf76ad6a613e35a0f996eee.
  • Independent operations reviewer: Chen Yong, stable approver ID chenyong@yuqei.com, key ID policy-trust-ops-2026q3.
  • Independent public-key file SHA-256: 0e2b147e5da9d1084da368944c720821a053b866282f1c5f9385dbad529e4009.
  • Exact trust payload SHA-256: 1b783cb6a9f1976d50f7d8b4c77e286425d7c8bec7c597057a172b6eaa113442.
  • Signed trust approval ID: policy-key-trust-approval-09d9860e94d6df9fe74a0d1e; approval SHA-256: 5093462cefff6a75e5f9a320f8bd4e033d9327e0234f84e9bbc258c36148fbbc.
  • Trusted policy keyring SHA-256: 41f9517dcd375afbeea4aaa4dce5d8bbe07db8f71e2706d47e7aec5ccd8bd388.
  • Strict verification at 2026-08-12T12:40:02.047339+08:00 passed for all four exact policy files without candidate-keyring override.
  • The signed decision binds the out-of-band identity/authority and legal-key fingerprint attestations. policy_activation_authorized=false; the trusted keyring remains local and has not been installed in production. No policy was published or activated by this approval.

Host filesystem observations were also checked directly with df -P: root was 85% at df display precision, while /home was 17%. The application probe's non-reserved-capacity calculation is the authoritative threshold comparison and reported root at 84.45%.

Repository verification

Executed on 2026-08-12:

Command Result
python -m pytest yuqei-infra/tests/test_observability_capacity.py yuqei-infra/tests/test_alert_receiver.py -q 26 passed
python -m pytest yuqei-infra/tests -q 148 passed
python -m py_compile on all changed Python entrypoints passed
python -m bandit -q on all changed Python entrypoints passed
git diff --check passed; only existing line-ending warnings

The capacity tests cover warning/critical percent and free-space thresholds, reserved filesystem blocks, separate-mount fail-closed behavior, webhook success, webhook timeout, receiver authentication and immutable receipts, healthy no-alert behavior, changed-state and one-hour resend deduplication, production preflight thresholds, and the installed systemd arguments.

Capacity and alert operating policy

  1. Keep the HTTPS URL in its owner-restricted file; never put its secret path or token in the repository, environment file or audit report.
  2. Retain the receiver-side receipt, local summary and event ID for each acceptance test.
  3. Keep one-hour unchanged-alert deduplication enabled. Do not suppress the first failure, a changed check set, delivery retries or hourly reminders.
  4. Treat root at or above 85%, free below 20 GiB, or more than five percentage points growth in 24 hours as a release stop. Do not delete business volumes, Registry data or backups to satisfy the gate. Move rebuildable caches/logs only after an explicit inventory and retention approval, or extend the root LV.

Complete version rollback acceptance policy

The completed exercise followed these controls. Re-run it after a material release topology, image or migration change; do not infer future downgrade compatibility from this one result.

  1. Record the current release ID, all image digests, receipt/key fingerprints, Alembic heads, container health and golden-smoke results.
  2. Take and verify a new off-host production backup. Restore all three dumps into disposable yuqei_restore_check_* databases before continuing.
  3. Prove migration compatibility. If the previous application cannot read the current schema, stop: use forward-fix recovery unless a separately reviewed, data-preserving downgrade exists. Never infer downgrade safety from an Alembic command succeeding in an empty database.
  4. With edge and public traffic still disabled, switch application services only to the approved previous digests. Do not roll back PostgreSQL/Redis/MinIO data or delete audit/outbox records.
  5. Verify health, schema checks, immutable release fingerprints, login/workspace, contract list/detail, template drafting, review read path and audit continuity.
  6. Return to the current immutable digests, re-run migrations in the forward direction, and repeat the same checks.
  7. Capture start/end times, RTO, every command exit code, before/rollback/forward fingerprints, database heads, release-gate summaries and operator approval.
  8. Abort immediately on migration drift, partial health, missing audit/outbox data, receipt mismatch, unexpected writes, or any need to use an unpinned image.

Acceptance requires both rollback and forward-restoration checks to pass, the database and immutable audit history to remain intact, and an operator-owned evidence package. The 2026-08-12 rehearsal satisfies this gate for the recorded release pair.

Gate status

Gate Status Reason
Capacity thresholds and live primary-host readings pass, narrow headroom root 84.45% used; warning begins at 85%
Capacity timer and local alert contract pass timer active; automated warning/failure delivery semantics pass
Real external alert delivery pass HTTPS receiver event and immutable receipt hashes captured
Backup integrity and disposable DB restore pass from existing field evidence three dumps and restore checks completed
Complete production version rollback and forward restore pass 40-file evidence manifest passed for previous/current release pair
Independent public-policy trust approval pass, policy not activated Chen Yong signed the exact trust payload as operations reviewer; strict verification issued a non-activating trusted keyring
Public traffic authorization not in scope edge/DNS/traffic remain separately controlled