# Finalization Runbook Everything that can be done without your credentials is done. This file is the copy-paste path through what remains. Work top to bottom. > Note: written while another agent (Codex) was editing files in this repo. The > line numbers in §5 are a snapshot — re-run the grep before trusting them. --- ## 0. What is already verified (no need to redo) Verified locally on 2026-07-26 with Docker 29.5.3 (linux/amd64): | Item | Result | |---|---| | `docker build` Q1 (`q1-deploy-monitor/app`) | builds clean → `ghaymah-api:latest`, 249 MB | | `docker build` Q5 (`q5-mithal-dashboard`) | builds clean → `mithal-monitor:latest`, 200 MB | | Q1 container | `/health` → 200 `{"status":"ok","uptime_s":11.254,...}`; `/metrics` counter increments; Docker healthcheck reports **healthy** | | Q5 container | `start.sh` launches collector + static server; collector wrote a real record inside the container (`up:true, code:200, ssl_days_left:50`); dashboard rendered at `/index.html` with badge, uptime tile, TLS card, chart and table; healthcheck **healthy** | | Q1 monitor | up/down transitions, `ALERT` after exactly 3 consecutive failures, `--once` exit codes | | Q5 collector | live measurements against mithal.space; unreachable-host run records all-nulls without crashing | **Both images are already built on this machine.** You can go straight to `docker push`. --- ## 1. Set your Docker Hub username once Everything below reuses this. Run in PowerShell: ```powershell $DH = "yourdockerhubusername" # <-- edit this line only ``` --- ## 2. Push both images (10 min) ```powershell docker login ``` ```powershell docker tag ghaymah-api:latest "docker.io/$DH/ghaymah-api:latest" docker tag mithal-monitor:latest "docker.io/$DH/mithal-monitor:latest" docker push "docker.io/$DH/ghaymah-api:latest" docker push "docker.io/$DH/mithal-monitor:latest" ``` Then, on hub.docker.com, confirm **both repositories are Public** — Ghaymah pulls them anonymously. A private repo is the single most common cause of a deployment that never leaves "pulling". --- ## 3. Deploy both apps on Ghaymah (30 min) Same form twice: | Field | Q1 | Q5 | |---|---|---| | Container Image URL | `docker.io//ghaymah-api:latest` | `docker.io//mithal-monitor:latest` | | Application Name | `ghaymah-api` | `mithal-monitor` | | Port Number | `8080` | `8080` | | Public Access | enabled | enabled | | Env vars (optional) | `APP_NAME=ghaymah-api`, `APP_VERSION=1.0.0` | `INTERVAL_S=60` | Record both public URLs — you need them in §5. Verify immediately: ```powershell curl.exe -f "/health" ``` Then open `/index.html` in a browser (it will show 1–2 checks at first). ### Start the Q1 monitor the moment Q1 is live This is the long pole — the Q1 dashboard is only convincing with hours of history. Leave this window open for the rest of the assessment: ```powershell $env:APP_URL=""; python q1-deploy-monitor\monitor\monitor.py ``` Q5 needs nothing — its collector runs inside the deployed container. --- ## 4. Resolve the Q3 blocker (the CLI question) — 20 min **What I established from public sources** (so you don't repeat the search): - Install: `curl -sSL https://cli.ghaymah.systems/install.sh | bash` - The installer downloads `gy-{platform}-{arch}` from `https://cli.ghaymah.systems` (override with `SERVER_URL`) and installs to `$HOME/ghaymah/bin/gy`. - The only env var the installer honours is `SERVER_URL`. **No token env var exists in the installer.** - Documented commands: `gy auth login` (browser-based), `gy auth status`, `gy resource project get`, `gy resource project create --set .name=my-new-project`, `gy resource application init --project-id `, `gy resource application launch`, `gy resource application logs`. - `.ghaymah.json` fields: `id`, `name`, `projectId`, `ports[].expose/.number`, `publicAccess.enabled/.domain`, `resourceTier`, `dockerFileName`, `env`, `domains`. - **Nothing public documents non-interactive auth, a registry hostname, or updating an application to an external image tag.** `/docs/cli` returns 404; the changelog and product pages list "container registry" and "CI/CD" as features with no syntax. **Run these three commands after `gy auth login`** — they are the fastest way to settle it, and their output is what I need to finish the workflow: ```bash gy auth login --help gy --help gy resource application --help ``` Look specifically for: a `--token` / `--api-key` flag, any `GHAYMAH_*` env var, a `gy resource application update`/`set-image` subcommand, or a `gy registry` group. Also check the authenticated dashboard for an **API tokens / service accounts** page and for the registry hostname. Paste whatever those print back to me and I will finish `deploy.yml`, `scripts/ghaymah_deploy.sh` and `CICD.md` in one pass. If it turns out no non-interactive path exists, that is a legitimate finding — the honest write-up (deploy job documented, adapter exits 78 rather than faking success, manual promotion step described) scores better than invented syntax. Do **not** invent a command to make the pipeline look green. --- ## 5. Replace the placeholders Snapshot of what is unfilled (re-run the grep after Codex finishes): ```powershell Select-String -Path (Get-ChildItem -Recurse -Include *.md,*.yml,*.sh -Path . | Where-Object FullName -notmatch '\\\.git\\') -Pattern 'MY_DOCKERHUB_USER|the public URL Ghaymah assigns|` × 5 | `q2-postmortem/POSTMORTEM.md:133`, `q3-cicd/CICD.md:111,125`, `q4-scalability/SCALABILITY.md:108,112` | see §6 | Bulk replacement (run **after** Codex is done, from the repo root): ```powershell $DH="yourdockerhubusername"; $Q1="https://your-q1-url"; $Q5="https://your-q5-url" Get-ChildItem -Recurse -Include *.md -File | Where-Object FullName -notmatch '\\\.git\\' | ForEach-Object { (Get-Content $_.FullName -Raw) ` -replace '', $DH ` -replace '', $Q1 | Set-Content $_.FullName -Encoding utf8 } ``` That sets the Q1 URL everywhere; then fix the single Q5 occurrence in `q5-mithal-dashboard/README.md` by hand (it is the `/index.html` line). --- ## 6. The five remaining VERIFY areas Each needs one look at the **authenticated** dashboard. What to check, and what to do with the answer: | # | File | Question to answer in the dashboard | |---|---|---| | 1 | `q2-postmortem/POSTMORTEM.md:133` | Does Ghaymah show per-container memory/CPU metrics, restart counts, and configurable alert rules + notification channels? Screenshot the monitoring page. | | 2 | `q3-cicd/CICD.md:111` | Non-interactive auth for CI — settled by §4. | | 3 | `q3-cicd/CICD.md:125` | External-image update syntax — settled by §4. | | 4 | `q4-scalability/SCALABILITY.md:108` | Block Storage: snapshots supported? retention/encryption/restore? | | 5 | `q4-scalability/SCALABILITY.md:112` | Block Storage: size limits, resize, IOPS/throughput, attachment/access modes, zone binding. | Rule for all five: if the platform confirms it, state it plainly and drop the marker. If the platform does **not** expose it, rewrite the sentence to describe the general requirement and say the platform-specific limits were not documented at the time of writing — then drop the marker. **No `VERIFY` string may survive in the submitted repo.** --- ## 7. Screenshots to capture Save under `docs/screenshots/` with these names so the READMEs can link them: - `q1-service-running.png` — the Ghaymah dashboard showing the running Q1 app - `q1-health-response.png` — browser or terminal showing `/health` → 200 JSON - `q1-monitor-dashboard.png` — the Q1 dashboard with a populated latency chart - `q3-approval-gate.png` — the GitHub Actions run paused on the production reviewer prompt - `q5-live-dashboard.png` — the deployed Q5 dashboard with ≥ 1 h of history - `ghaymah-monitoring.png` — optional, supports the Q2 detection section --- ## 8. GitHub, secrets, pipeline 1. Create the repo, add the remote, push. 2. Settings → Secrets and variables → Actions: add the secrets named in `.github/workflows/deploy.yml` (Docker Hub user/token, plus whatever §4 settles for Ghaymah). 3. Settings → Environments → `production` → **Required reviewers: yourself**. 4. Run the workflow → let it pause → screenshot the gate → approve. Decide before pushing whether `PLAN.md`, `PROMPTS.md` and `CHECKLIST.md` belong in the submission. They document your internal agent workflow; graders don't need them. Either delete them or list them in `.gitignore`. --- ## 9. Final gate before submitting ```powershell Select-String -Path (Get-ChildItem -Recurse -Include *.md,*.yml,*.sh -File | Where-Object FullName -notmatch '\\\.git\\') -Pattern 'VERIFY|MY_DOCKERHUB_USER|the public URL Ghaymah assigns' ``` Must return nothing. Then: - [ ] Both apps reachable at their public URLs - [ ] Q1 dashboard chart has hours of points; Q5 uptime tile computed over real 24 h data - [ ] All screenshots committed and linked from the root README - [ ] Every numbered sub-requirement of Q1–Q5 ticked (CHECKLIST.md §7.1) - [ ] Final commit pushed