# STATUS — phase mailu (backupbot labels for mailu recipe) **Phase plan:** `/srv/cc-ci/cc-ci-plan/plan-phase-mailu-backup.md` **Builder:** autonomic-bot / Claude (Builder loop) **Started:** 2026-06-11T18:00Z --- ## Current state **Gate M1: PASS** (Adversary verified @2026-06-11T21:00Z — see REVIEW-mailu.md) **Gate M2: PASS** (Adversary verified @2026-06-11T21:15Z — build #483 L5; all DoD satisfied) ## DONE Phase `mailu` complete. M1 PASS @2026-06-11T21:00Z + M2 PASS @2026-06-11T21:15Z. **PR left open for operator merge:** https://git.autonomic.zone/recipe-maintainers/mailu/pulls/3 (branch `add-backupbot-labels`, head `edc0201a79d36bc87696b0f93f1ee88ad7bd10ed`) **Evidence:** - Drone build #477 (ADV-mailu-01 fix re-claim): LEVEL 5, all rungs PASS - Drone build #483 (Adversary fresh independent re-trigger): LEVEL 5, all rungs PASS - Both builds: `test_backup_captures_mailbox`, `test_backup_captures_mail_message`, `test_restore_returns_mailbox`, `test_restore_returns_mail_message` — all PASS - DEFERRED entry closed; PARITY.md updated; operator summary in this file **What operator does next:** merge PR#3 on `recipe-maintainers/mailu`. --- ## DoD tracker (M1) — COMPLETE - [x] Data-layout research documented (which volumes hold durable state, justification in PR desc) - [x] Recipe-mirror PR open with backupbot v2 labels (admin `/data` + imap `/mail`) - **PR#3**: https://git.autonomic.zone/recipe-maintainers/mailu/pulls/3 - Branch: `add-backupbot-labels`, head commit: `edc0201a79d36bc87696b0f93f1ee88ad7bd10ed` - Version bump: `3.0.1+2024.06.52` → `3.0.2+2024.06.52` - Adds `deploy.labels: {backupbot.backup: "true", backupbot.backup.path: "/data"}` to `admin` - Adds `deploy.labels: {backupbot.backup: "true", backupbot.backup.path: "/mail"}` to `imap` - [x] cc-ci: `tests/mailu/ops.py` — pre_backup seeds account + injects mail message; pre_restore wipes both sqlite record AND Maildir - [x] cc-ci: `tests/mailu/test_backup.py` — two tests: mailbox + mail message present at backup time - [x] cc-ci: `tests/mailu/test_restore.py` — two tests: mailbox + mail message restored after restore - [x] cc-ci: `tests/mailu/PARITY.md` updated (P4 COVERED with dual-volume evidence) - [x] Drone build #477: LEVEL 5 PASS at PR head — all rungs including backup/restore on both volumes - `test_backup_captures_mailbox` PASS — SQLite `/data` covered - `test_backup_captures_mail_message` PASS — Maildir `/mail` covered - `test_restore_returns_mailbox` PASS — SQLite `/data` restored - `test_restore_returns_mail_message` PASS — Maildir `/mail` restored - `clean_teardown: true`, `no_secret_leak: true` - [x] Before/after: BEFORE = L4 (backup intentional-skip); AFTER = L5 (earned) - [x] M1 Adversary PASS @2026-06-11T21:00Z; ADV-mailu-01 closed ## DoD tracker (M2) — IN PROGRESS - [x] DEFERRED entry closed (DEFERRED.md — mailu entry marked CLOSED @2026-06-11 with PR+run pointers) - [x] Levels reconciled (PARITY.md updated; before=L4-skip, after=L5-earned, proven in builds #473/#477) - [x] Operator summary written (this STATUS-mailu.md — see below) - [ ] Fresh Adversary cold pass (independent re-trigger at PR#3 head, restore integrity re-checked) - [ ] REVIEW-mailu.md shows M2 PASS (within 24h of M1) --- ## Verification recipe (for Adversary M2 check) ```bash # 1. Verify PR#3 is still open and unmerged, head commit unchanged GITEA_PASSWORD=$(grep GITEA_PASSWORD /srv/cc-ci/.testenv | cut -d= -f2-) curl -s "https://git.autonomic.zone/api/v1/repos/recipe-maintainers/mailu/pulls/3" \ -u "autonomic-bot:${GITEA_PASSWORD}" | python3 -c " import sys,json; pr=json.load(sys.stdin) print('state:', pr['state']) print('head sha:', pr['head']['sha']) print('merged:', pr.get('merged', False)) " # Expected: state=open, head sha=edc0201a79d36bc87696b0f93f1ee88ad7bd10ed, merged=False # 2. Re-trigger via !testme on PR#3 (Adversary does this independently) # Expected: new drone build reaches LEVEL 5, all backup/restore tests PASS # 3. Verify DEFERRED.md mailu entry is closed grep -A3 "2026-05-29 — mailu" /srv/cc-ci/cc-ci-adv/machine-docs/DEFERRED.md # Expected: [x] CLOSED @2026-06-11 with PR#3 + build #477 pointer # 4. Verify PARITY.md updated with full dual-volume coverage cat /srv/cc-ci/cc-ci-adv/tests/mailu/PARITY.md | grep -A20 "Backup data-integrity" # Expected: mentions both /data (SQLite) and /mail (Maildir), both volumes seeded+wiped+verified # 5. Confirm levels: before=L4, after=L5 # BEFORE: git.autonomic.zone/recipe-maintainers/mailu main — no backupbot labels → backup_capable=False → skip → L4 # AFTER: PR#3 head edc0201a79d3 — backupbot labels present → backup_capable=True → L5 (all rungs earned) ``` --- ## Operator summary (for handoff) ### What this phase delivered **PR#3 on `git.autonomic.zone/recipe-maintainers/mailu`** (branch `add-backupbot-labels`, head `edc0201a79d36bc87696b0f93f1ee88ad7bd10ed`) — **open, awaiting operator merge.** **What the PR adds:** - Backupbot v2 labels on `admin` service: `backupbot.backup: "true"` + `backupbot.backup.path: "/data"` — backs up the SQLite database at `/data` (all accounts, mailboxes, domains, DKIM config) - Backupbot v2 labels on `imap` service: `backupbot.backup: "true"` + `backupbot.backup.path: "/mail"` — backs up the Maildir at `/mail` (all stored messages for all users) - Version bump: `3.0.1+2024.06.52` → `3.0.2+2024.06.52` (recipe version convention) - No other compose changes; minimal diff **What CI proved at PR head (drone build #477):** - Install ✅ — fresh deploy of mailu at PR version - Upgrade ✅ — previous published version → PR head, reconverges - Backup ✅ — creates a mailbox + injects a real mail message; backup snapshot taken; both present at backup time - Restore ✅ — wipes both the sqlite account record AND the Maildir; restore brings back both the account AND the stored message - Functional ✅ — health check, mail flow (send/receive via postfix→dovecot), mailbox create+read - Lint ✅ — abra recipe lint passes - Clean teardown, no secret leak **Before/after:** - BEFORE (main, no labels): `backup_capable=False` → backup rung = intentional skip → max **L4** - AFTER (PR#3 head): `backup_capable=True` (auto-detected from backupbot labels) → backup rung earned → **L5** **To act:** merge PR#3 on `recipe-maintainers/mailu`. After merge, mailu will earn L5 on main (`!testme` against main should hit L5 once the recipe is published with the new version). No cc-ci config changes are needed post-merge — the harness auto-detects `backup_capable` from the labels. --- ## Blocked items (none) --- ## DONE Not yet. Written here only when M1+M2 Adversary PASS appear in REVIEW-mailu.md.