docs(ops): operations_dr v2 — prouvé, pas planifié (débloque ctr-operations-dr) [proven_review_pending] - #36
docs(ops): operations_dr v2 — prouvé, pas planifié (débloque ctr-operations-dr) [proven_review_pending]#36openaxcloud wants to merge 9 commits into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4ca9db82da
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| # - check placeholder SUPPRIMÉ (id vibecore-prod-api-health-3o809nkYoCo) | ||
| # - check RÉEL créé : vibecore-prod-api-health-api-e-code-ai-UBigUqgiGrg | ||
| # (host=api.e-code.ai, path=/health, 60s, timeout 10s, SSL validé) | ||
| # - canal réel créé : email avi@snatchbot.me | ||
| # (projects/vibecore-495216/notificationChannels/16784247357547337289) |
There was a problem hiding this comment.
Persist the monitoring repair in Terraform
The live resources were replaced manually, but the inspected source of truth in infra/terraform/modules/monitoring/main.tf still declares replace-me.example.com, the disabled ops@example.invalid channel, and a policy wired to that channel. On the next Terraform apply, those managed resources can be recreated or reconciled back to the broken configuration, undoing the alerting repair that this evidence declares operational; update the Terraform configuration alongside the live change.
Useful? React with 👍 / 👎.
| | Exercice | Date | Résultat | Evidence | | ||
| |---|---|---|---| | ||
| | **Perte de zone** (cordon europe-west9-a, la zone préférée) | 2026-07-20 | Projet Python neuf provisionne en zone-b : store clone monté + génération vérifiée, uv/venv, Preview 200, **Publish READY + 200** — bout en bout pendant la « panne ». Restauration prouvée dans les 2 sens, zéro split-brain. 2 bugs réels trouvés PAR l'exercice et corrigés (deadlock affinités data-PVC ; RBAC PV) | `2026-07-17-nix-multizone/ZONE_LOSS_TEST.md` | | ||
| | **Perte d'instance API** (kill d'1 pod sur 2 sous sonde continue) | 2026-07-21 | **90/90 requêtes HTTP 200** pendant le kill et le remplacement (<2 min) — zéro downtime observé (maxUnavailable:0 + 2 replicas) | `chaos-probe-podkill.log` (EVID-DR-CHAOS-001) | |
There was a problem hiding this comment.
Include the cited pod-kill evidence
This marks the API pod-loss exercise as proven by chaos-probe-podkill.log, but a repository-wide search of commit 6d416a4 finds neither that file nor any other occurrence of EVID-DR-CHAOS-001 or the reported 90/90 result outside this document. Consequently the exercise cannot be audited or reproduced despite the contract's requirement that every PROVEN assertion have an evidence artifact and repro; add the raw probe log and command or mark the claim unproven.
Useful? React with 👍 / 👎.
| Drill mesuré : lancé 04:43:21Z → RUNNABLE + intégrité vérifiée 04:56:27Z = | ||
| **13 min 06 s**, intégrité stricte (4 compteurs + dernier deployment identiques). | ||
| Instance de drill détruite après coup. **RTO DB ≤ 60 min : tenu avec ×4 de marge.** |
There was a problem hiding this comment.
Measure application cutover before claiming the database RTO
The 13:06 measurement ends when the clone is runnable and queried, while this same procedure says an actual incident still requires changing the application DNS/URL afterward. In a production database-loss scenario, users remain pointed at the failed instance until that configuration change, workload rollout, and application health validation complete, so the service-recovery RTO is not demonstrated by the clone time alone; include and time a tested cutover or describe 13:06 only as restore duration.
Useful? React with 👍 / 👎.
| Mesuré : **77 s** bout en bout, contenu vérifié **bit-à-bit** (sha256 d'un | ||
| marqueur daté écrit avant le snapshot). ⚠ La **planification** de ces snapshots |
There was a problem hiding this comment.
Limit the disk integrity claim to the checked marker
The evidence hashes only .dr-drill-marker, so it proves that one file survived restoration, not that the workspace contents or disk were verified bit-for-bit. Corruption or omission elsewhere on the restored filesystem would not affect this comparison, making the stronger integrity claim misleading for a DR acceptance record; either hash and compare the relevant filesystem contents or state that a marker-file restore was verified.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
This PR updates the OPERATIONS_DR parity document to move from “plans/UNTESTED” to “PROVEN” where drills were actually executed, and adds dated raw evidence artifacts for monitoring repair and DR restore drills to address a prior expert refusal on SLO/astreinte/chaos/RTO-RPO being unproven.
Changes:
- Replace OPERATIONS_DR v1 with v2 including SLO/error budget policy, measured RPO/RTO table, and drill reproduction steps.
- Add dated evidence files for uptime-check/notification-chain repair, Cloud SQL PITR clone drill, and workspace disk snapshot/restore drill.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| docs/parity/OPERATIONS_DR.md | Rewrites the DR/ops contract to include “PROVEN/BLOCKED” claims with evidence IDs and repro steps. |
| docs/deploy-evidence/2026-07-21-dr-drill/monitoring-repair.txt | Adds raw evidence of monitoring/alerting chain repair (uptime check + notification channel). |
| docs/deploy-evidence/2026-07-21-dr-drill/disk-restore-drill.txt | Adds raw evidence of workspace disk snapshot→restore→bit-verify timing. |
| docs/deploy-evidence/2026-07-21-dr-drill/db-restore-drill.txt | Adds raw evidence of Cloud SQL PITR clone restore timing and integrity checks. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| | Disponibilité API (`/health`) | 99.5 % | 3 h 36 min | uptime check ci-dessus (alerte « uptime failed » → email réel) | | ||
| | Disponibilité app web (`e-code.ai`) | 99.5 % | 3 h 36 min | ⚠ UNTESTED — check web à créer (même mécanique, 1 commande, voir §7) | |
| Mesuré : **77 s** bout en bout, contenu vérifié **bit-à-bit** (sha256 d'un | ||
| marqueur daté écrit avant le snapshot). ⚠ La **planification** de ces snapshots | ||
| (schedule GCE sur les PD workspaces) n'existe pas : **BLOCKED — décision Avi** | ||
| (coût snapshot 0.058 $/Gio/mois × volumétrie réelle ; commande prête en §7). |
| 2. **Snapshots planifiés des PD workspaces** : créer une resource policy GCE et | ||
| l'attacher aux disques (`gcloud compute resource-policies create snapshot-schedule …`) | ||
| — coût à valider (0.058 $/Gio/mois sur octets stockés). |
| # - canal réel créé : email avi@snatchbot.me | ||
| # (projects/vibecore-495216/notificationChannels/16784247357547337289) | ||
| # - policy 13490189321125093325 re-câblée sur ce canal (l'invalide retiré) |
|
Failover Cloud SQL RÉEL joué (GO Avi, 2026-07-21) — le dernier BLOCKED qui l'exigeait :
Sondes 1 Hz (connexion neuve + INSERT commité par écriture), logs bruts + timeline + repro dans |
…nce croisée au drill DR joué (PR #36, 13 min 06 s) — CNPG projet reste ouvert, dit tel quel Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
100d28f to
293c050
Compare
|
Les 5 réserves du refus expert (2026-07-22 §D2) sont traitées — commit
Statut inchangé : PROVEN_REVIEW_PENDING. |
04f0c3e to
9b9f0c4
Compare
|
Réserves V3 §B traitées — commit n°4 — compteur régénéré depuis l'artefact brut (plus de transcription manuelle) : script Obligations FERMÉES avec preuve live + IaC :
Ceci contredit le « aucun pipeline de métriques » précédent : GMP est en service et ingère désormais le SLI par requête. Restent BLOCKED (décision Avi, nommées) : snapshots PD planifiés (chiffré : ~1,9 $/mois aux 32 Gio réels mesurés — décision coût), astreinte outillée, réplique cross-région, RTO applicatif complet DB (UNTESTED volontaire, re-pointerait la prod). Checks verts : helm render (gate on/off), |
…TIONS-DR)
Answers the reviewer's refusal ("SLO/astreinte/chaos/RTO-RPO non prouvés")
with dated, reproducible evidence — or an honest BLOCKED naming the exact
dependency:
- RESTORE DRILL PLAYED (DB): PITR clone of vibecore-prod-postgres to a
throwaway instance (prod untouched), integrity verified against prod
(4 table counts before the point-in-time strictly equal) — measured
13m06s restore→verified vs a 60min RTO target. Instance torn down.
- RESTORE DRILL PLAYED (workspace disk): dated marker → snapshot → new
disk → RO mount → sha256 identical, 77s end-to-end.
- CHAOS PLAYED: zone-loss exercise (2026-07-20, full evidence, found+fixed
2 real bugs) + api pod-kill under continuous probe: 90/90 HTTP 200.
- SLO grounded in a REAL SLI: the uptime check watched a placeholder host
(replace-me.example.com, 100% failing for 28d measured) notifying a
placeholder email — repaired live (real check on api.e-code.ai/health:
131/131 passing; real notification email), evidence with before/after.
- RPO/RTO per data class with measured values; backup config verified
(daily 03:00 UTC ×30 + PITR enabled; Cloud SQL REGIONAL HA; GCS
multi-region EU; Redis persistence DISABLED documented with mitigations).
- Honest BLOCKED list: real Cloud SQL failover (needs window + GO),
scheduled PD snapshots (cost decision), staffed on-call, request-level
SLIs, cross-region replica, email channel confirmation.
status: PROVEN_REVIEW_PENDING — no merge without explicit approval.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s write windows, zero acked-write loss Failover b→c then failback c→b on the REGIONAL prod instance, under 1 Hz probes (fresh connection + committed INSERT per write; reads; external /health): - write unavailability: 24.1s (failover), 16.0s (failback) vs 5min target - reads: same windows; external API /health: 100% HTTP 200 throughout - integrity: 270/270 acked writes present after both switches — zero loss (2 rows committed whose ACK never reached the client: expected, not loss) - original topology restored (primary europe-west9-b), drill table dropped Raw probe logs + timeline + repro in docs/deploy-evidence/2026-07-21-dr-failover/. OPERATIONS_DR: DB zone-loss row now PROVEN; BLOCKED list shrinks by one. status stays PROVEN_REVIEW_PENDING — no merge without explicit approval. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ndum (3 post-drill client-side 000s, disproven by 276/276 GCP probes) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sal 2026-07-22 §D2)
1. Monitoring persisted in Terraform: modules/monitoring parameterized
(api_host, ops_email) with real defaults in root variables.tf and
ANTI-PLACEHOLDER validations (a plan with example.com/*.invalid FAILS);
moved{} block renames the channel resource; convergence commands for the
hand-fixed live objects documented in the module header. terraform
validate + fmt green (root + envs/prod).
2. "bit-à-bit" over-claim reworded: exact scope stated — sha256 of ONE dated
witness file proves the snapshot→restore→mount chain, NOT a full-volume
comparison (explicitly proposed as next quarterly drill extension).
3. 13m06s requalified: clone restore+validation duration only; full
applicative RTO (DB config switch + rollout + user health) = UNTESTED,
with the remaining steps and a known lower bound documented.
4. Contract scope header: conclusions SCOPED to artifacts; the contract is
NOT claimed signable while UNTESTED/BLOCKED obligations remain open; the
Cloud SQL failover drill stands as an individually validated proof.
5. Chaos pod-kill artifact: root cause found — .gitignore `*.log` silently
excluded EVERY raw drill log from every commit (also the failover 1Hz
probe logs, now lost and honestly declared as such with authoritative
GCP corroboration: gcloud sql operations FAILOVER records bracketing the
measured windows). Exercise REPLAYED 2026-07-22: 90/90 HTTP 200 again,
artifact committed; gitignore exception added so evidence logs version.
status: PROVEN_REVIEW_PENDING — no merge without explicit approval.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…losed SLO web & per-request SLI
Expert V3 §B (CTR-OPERATIONS-DR still refused as a whole; failover drill
accepted as individual proof). This advances the open obligations maximally
without touching user prod (all additive):
n°4 — NORMATIVE COUNTER regenerated from the RAW artifact, no manual
transcription: script regen-uptime-count.py over uptime-raw-drill-window.json
(GCP uptime, exact drill window 07:55→08:00Z) => 30/30 True. The hand-typed
"276/276" (post-drill 08:10-08:20, other window) and "270/270" (write-integrity,
a DIFFERENT metric whose raw log is lost) are corrected: 30/30 is the sole
normative availability number; write-integrity kept as a recorded-but-NOT-
regenerable observation.
n°1 — obligations CLOSED with live proof + IaC:
* SLO web e-code.ai: Terraform web_health uptime check + alert policy
(anti-placeholder validated) + created live => 702/702 True over 20min
(EVID-DR-SLO-WEB-001).
* per-request SLI: the API already exposes api_request_duration_seconds
(per-request histogram, method/route/status). Added a GMP PodMonitoring +
NetworkPolicy (IaC in the chart). Dataplane-V2/Cilium gotcha solved and
proven: ipBlock CIDR does NOT match the hostNetwork collector (host
identity) => up=0; namespaceSelector gmp-system => up=1. Metric now
queryable in Managed Prometheus (success ratio 1.0, p95 ~0.022s) + a
PromQL 5xx error-budget alert policy (EVID-DR-SLI-001). This refutes the
prior "no metrics pipeline" claim: GMP is live and now ingests the SLI.
n°2/n°3 kept honest (13m06s = clone restore/validation, not full app RTO;
disk proof = witness-file sha256, not whole-volume).
Still BLOCKED (named, Avi decision): scheduled PD snapshots (cost ~1.9$/mo at
the measured 32GiB — decision), tooled on-call, cross-region replica, full
applicative DB RTO (deliberately UNTESTED). Contract NOT signed.
Checks green: helm render (chart + gate on/off), terraform fmt + validate,
regen script re-runnable. status: PROVEN_REVIEW_PENDING.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… closed (GO Avi) Closes the CTR-OPERATIONS-DR obligation that was BLOCKED on a cost decision. Additive, non-disruptive (online snapshots, zero workspace downtime). - Terraform (source of truth): modules/gke-workspaces adds google_compute_resource_policy.workspace_snapshots (daily 02:00 UTC, 7-day retention, europe-west9, on-source-disk-delete=APPLY_RETENTION_POLICY) + a validated snapshot_schedule variable (HH:00 time, 1-30d retention) + output. terraform validate + fmt green. - Attach (dynamic CSI GKE disks, outside TF state): infra/k8s-manual/attach-snapshot-policy.sh — idempotent, re-runnable for new disks. - Applied LIVE (terraform apply is Avi-only): policy vibecore-prod-workspace-snapshots created + attached to all 5 pvc- disks (a/b/c); re-run proves idempotency; disk describe confirms attachment. - Proof: on-demand snapshot READY (storageBytes 7.4 MiB for a 10GiB disk); a temporary fast-firing schedule proves the SCHEDULE itself triggers (scheduled-fire evidence added in a follow-up once it fires ~20:00 UTC). - Real cost: ceiling 1.86 $/mo (32 GiB fully used x 0.058); measured usage (7.4 MiB on a 10GiB disk; snapshots incremental, billed on used bytes) puts the real steady-state at a few cents/mo, well under the approved ~1.9 $. OPERATIONS_DR: snapshot obligation flipped BLOCKED -> DONE; RPO/RTO row + contractScope updated. status: PROVEN_REVIEW_PENDING. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2f6711e to
b14d045
Compare
|
Snapshots planifiés des PD workspaces — obligation FERMÉE (GO Avi, 2026-07-23) — commit
Additif, zéro downtime. |
The schedule itself fires: a temporary daily policy (20:00 UTC) auto-created a snapshot pvc-6988fcd4-...-20260723200602-notnftg6 (READY, ~7.7 MiB) — the auto-generated name confirms a scheduler-driven snapshot, not a manual one. Proof artifacts (temp policy + its snapshot) torn down; the prod policy vibecore-prod-workspace-snapshots + its attachments stay. Bonus proven live: a new workspace disk appeared mid-session; re-running the idempotent attach script attached it and left the others untouched — real coverage of dynamically-provisioned CSI disks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
✅ Schedule prouvé end-to-end (commit Bonus prouvé live : un nouveau disque workspace est apparu pendant la session → le re-run du script idempotent l'a attaché sans toucher les autres = couverture réelle des disques dynamiques CSI. Obligation snapshots planifiés : FERMÉE (politique en place + snapshot déclenché vérifié + schedule tiré + coût réel). PROVEN_REVIEW_PENDING. |
…manifest + counter) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…r PR CONFLICTING) # Conflicts: # docs/parity/DOCUMENT_MANIFEST.yaml
…liation main Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Réponse au refus expert « SLO, astreinte, exercices, chaos et restauration RTO/RPO non prouvés »
Chaque point du refus est traité avec preuve datée + repro, ou marqué BLOCKED avec sa dépendance exacte. Aucun état intermédiaire.
Prouvé en réel (2026-07-20/21, artefacts bruts dans
docs/deploy-evidence/2026-07-21-dr-drill/)replace-me.example.com(100 % d'échec mesuré) et notifiaitops@example.invalid. Réparé en live : check réel surapi.e-code.ai/health(131/131 passing post-fix), canal email réel. SLO 99.5 %/28 j + error budget + politique de gel.BLOCKED honnêtes (dépendance nommée)
Failover Cloud SQL réel (fenêtre + GO), snapshots PD planifiés (coût), astreinte outillée, SLI par requête (pipeline métriques), réplique cross-région, confirmation du canal email.
Pas de merge sans feu vert explicite. La prod utilisateur n'a jamais été touchée (clone PITR jetable, disque de test jetable, kill d'un pod redondant).
🤖 Generated with Claude Code