From cb0c5b4614091ec62a21b3b9465e74626831c3fb Mon Sep 17 00:00:00 2001 From: Ivan Godwin Date: Wed, 2 Sep 2026 23:15:48 -0700 Subject: [PATCH] Move runbooks into domain directories od-db-backup.md becomes od/db-backup.md -- the hyphen becomes a slash, so the fetch command is exactly as long to type as before. That mattered: the length of a hand-typed command is the constraint this repo is organized around, and a reorganization that lengthened it would have been a net loss. Scripts deliberately stay flat in scripts/ with their domain prefix. Everything executable in one directory is the set worth reading before it runs, and nesting five files by domain would add characters without adding clarity. Updates every reference: README Contents (now grouped by directory), the layout section, both fetch examples, inter-runbook links, and the .NOTES headers in all five scripts. Verified every markdown link resolves on disk and that Contents and the filesystem agree in both directions. Records the naming rule in CONTRIBUTING so the next file lands correctly. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01HwcG1jLs1T425QRMxtjxP7 --- CONTRIBUTING.md | 15 ++++ README.md | 74 +++++++++++++------ .../backup-schedule.md | 18 ++--- od-backup-verify.md => od/backup-verify.md | 8 +- od-cfg-persist.md => od/cfg-persist.md | 0 od-db-backup.md => od/db-backup.md | 6 +- od-scan-duplex.md => od/scan-duplex.md | 0 od-smb-cred.md => od/smb-cred.md | 0 scripts/cg-disable.ps1 | 2 +- scripts/od-backup-check.ps1 | 4 +- scripts/od-cfg-acl.ps1 | 2 +- scripts/od-db-backup.ps1 | 2 +- .../google-compromise.md | 6 +- .../google-evidence.md | 2 +- 14 files changed, 91 insertions(+), 48 deletions(-) rename od-backup-schedule.md => od/backup-schedule.md (90%) rename od-backup-verify.md => od/backup-verify.md (93%) rename od-cfg-persist.md => od/cfg-persist.md (100%) rename od-db-backup.md => od/db-backup.md (97%) rename od-scan-duplex.md => od/scan-duplex.md (100%) rename od-smb-cred.md => od/smb-cred.md (100%) rename sec-google-compromise.md => sec/google-compromise.md (99%) rename sec-google-evidence.md => sec/google-evidence.md (97%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eb31541..a0dd636 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,6 +34,21 @@ Instead use placeholders: ``, ``, ``, ``, If a step can't be written without a real particular, it doesn't belong here — split the particular out to the private tier and reference it as a placeholder. +### Naming + +Runbooks go in a domain directory and drop the prefix — `od/db-backup.md`, not +`od-db-backup.md`. The directory *is* the prefix, which keeps the fetch command +exactly as short as it was. Existing domains are `od/` and `sec/`; add `win/`, +`m365/`, or `net/` when the first file needs one. + +Scripts stay flat in `scripts/` and keep their domain prefix. Everything +executable lives in one directory on purpose — that is the set worth reading +before it runs. Non-interactive scripts (Intune remediations) get their own +sibling directory, not `scripts/`. + +Filenames stay short: they are typed by hand on a client keyboard, often +mid-incident. That constraint outranks descriptiveness. + ## Before every commit 1. Re-read the diff. Would a stranger learn *who* the client is, or *how to diff --git a/README.md b/README.md index cb1be3c..58127cc 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,13 @@ client workstations during on-site work with short, hand-typeable commands. Fetch and read on the target workstation: ```powershell -irm rb.godwinsystems.com/ | more +irm rb.godwinsystems.com/od/db-backup.md | more ``` Run an executable runbook script directly (scripts live under `scripts/`): ```powershell -irm rb.godwinsystems.com/scripts/.ps1 | iex +irm rb.godwinsystems.com/scripts/od-db-backup.ps1 | iex ``` Scripts prompt for anything client-specific via `Read-Host` — nothing to edit @@ -44,7 +44,7 @@ mid-incident — the canonical URL is 63 characters before the filename. The canonical form still works and is what the redirect targets: ``` -https://gitea.ivangodwin.com/godwinsystems/rb/raw/branch/main/ +https://gitea.ivangodwin.com/godwinsystems/rb/raw/branch/main//.md ``` The redirect is a backendless Gateway API `HTTPRoute` defined in @@ -55,21 +55,37 @@ runbook here documents a dead URL. ## Layout & naming -- **Runbooks** (`.md`) live flat at the repo root with short, hand-typeable - filenames and light category prefixes. -- **Scripts** (`.ps1`) live under [`scripts/`](scripts/). `_template.ps1` - sorts first and is the convention reference, not a runnable runbook. -- **Meta** (`README.md`, `CONTRIBUTING.md`) stays at the root. +``` +od/ Open Dental +sec/ Security / incident response +scripts/ Executable .ps1 — one flat namespace, prefixed by domain +``` -Runbook prefixes: +- **Runbooks** (`.md`) live in a domain directory, named without a prefix — + the directory is the prefix. `od/db-backup.md`, not `od-db-backup.md`. +- **Scripts** (`.ps1`) stay flat in [`scripts/`](scripts/) and keep their + domain prefix. One directory holds everything executable, which is the set + worth auditing before a change; `_template.ps1` sorts first as the + convention reference, not a runnable runbook. +- **Meta** (`README.md`, `CONTRIBUTING.md`, `LICENSE`) stays at the root. -| Prefix | Domain | +The split is deliberate: the fetch command's length is the constraint this +repo is organized around, and `od/db-backup.md` is exactly as long to type as +`od-db-backup.md` was — the hyphen became a slash. Nesting scripts by domain +too would add characters without adding clarity to a five-file directory. + +Domain directories, as they are needed: + +| Directory | Domain | |---|---| -| `win-` | Windows workstation / server | -| `m365-` | Microsoft 365 / Entra | -| `od-` | Open Dental | -| `net-` | Networking | -| `sec-` | Security / incident response | +| `win/` | Windows workstation / server | +| `m365/` | Microsoft 365 / Entra | +| `od/` | Open Dental | +| `net/` | Networking | +| `sec/` | Security / incident response | + +Non-interactive scripts (Intune remediations) get their own sibling directory +when they arrive — not `scripts/`, which is for `iex`-safe interactive ones. ## Placeholder conventions @@ -87,16 +103,28 @@ run time — never commit filled-in values. ## Contents +### Open Dental — `od/` + +| File | Purpose | +|---|---| +| [`od/smb-cred.md`](od/smb-cred.md) | Open Dental SMB share — stored-credential fix | +| [`od/cfg-persist.md`](od/cfg-persist.md) | Open Dental — persist "Do not show this window on startup" (writable FreeDentalConfig.xml) | +| [`od/scan-duplex.md`](od/scan-duplex.md) | Open Dental — duplex ADF scanner captures only one side (TWAIN, Show TWAIN UI branches) | +| [`od/db-backup.md`](od/db-backup.md) | Open Dental — rock-solid cold backup of the database + images (stop/copy/start MySQL/MariaDB) | +| [`od/backup-verify.md`](od/backup-verify.md) | Open Dental — verify a backup by test-restoring into an isolated Hyper-V VM (health checklist) | +| [`od/backup-schedule.md`](od/backup-schedule.md) | Open Dental — schedule the backup + off-site upload and monitor it (dead-man's-switch heartbeat) | + +### Security / incident response — `sec/` + +| File | Purpose | +|---|---| +| [`sec/google-compromise.md`](sec/google-compromise.md) | Incident response — suspected compromise of a **consumer** Google/Gmail account (AiTM session theft; no Workspace admin console) | +| [`sec/google-evidence.md`](sec/google-evidence.md) | Google/Gmail account — evidence capture before changes + re-entry check after a password reset (numbered, field-usable) | + +### Scripts — `scripts/` + | File | Purpose | |---|---| -| [`od-smb-cred.md`](od-smb-cred.md) | Open Dental SMB share — stored-credential fix | -| [`od-cfg-persist.md`](od-cfg-persist.md) | Open Dental — persist "Do not show this window on startup" (writable FreeDentalConfig.xml) | -| [`od-scan-duplex.md`](od-scan-duplex.md) | Open Dental — duplex ADF scanner captures only one side (TWAIN, Show TWAIN UI branches) | -| [`od-db-backup.md`](od-db-backup.md) | Open Dental — rock-solid cold backup of the database + images (stop/copy/start MySQL/MariaDB) | -| [`od-backup-verify.md`](od-backup-verify.md) | Open Dental — verify a backup by test-restoring into an isolated Hyper-V VM (health checklist) | -| [`od-backup-schedule.md`](od-backup-schedule.md) | Open Dental — schedule the backup + off-site upload and monitor it (dead-man's-switch heartbeat) | -| [`sec-google-compromise.md`](sec-google-compromise.md) | Incident response — suspected compromise of a **consumer** Google/Gmail account (AiTM session theft; no Workspace admin console) | -| [`sec-google-evidence.md`](sec-google-evidence.md) | Google/Gmail account — evidence capture before changes + re-entry check after a password reset (numbered, field-usable) | | [`scripts/cg-disable.ps1`](scripts/cg-disable.ps1) | Disable Credential Guard, then reboot (prompts to confirm) | | [`scripts/od-cfg-acl.ps1`](scripts/od-cfg-acl.ps1) | Grant Users Modify on FreeDentalConfig.xml (Option B of od-cfg-persist) | | [`scripts/od-db-backup.ps1`](scripts/od-db-backup.ps1) | Cold backup: stop MySQL/MariaDB, copy whole data dir + OpenDentImages, always restart (od-db-backup) | diff --git a/od-backup-schedule.md b/od/backup-schedule.md similarity index 90% rename from od-backup-schedule.md rename to od/backup-schedule.md index acab298..c471863 100644 --- a/od-backup-schedule.md +++ b/od/backup-schedule.md @@ -3,7 +3,7 @@ > For qualified IT professionals, on systems they are authorized to administer. > Provided as-is, without warranty — verify it fits your environment. See LICENSE. -**Applies to:** The Open Dental database server, once [`od-db-backup.md`](od-db-backup.md) is proven to run by hand. +**Applies to:** The Open Dental database server, once [`od/db-backup.md`](db-backup.md) is proven to run by hand. **Goal:** Make the backup run **automatically every day**, replicate it **off-site**, and **monitor** it so a silent failure gets noticed within a day — not the day you need a restore. Open Dental's floor is **at least one backup per day**, with a combination of methods and at least one **automated**. ([Open Dental — Backups](https://opendental.com/manual/backups.html)) This runbook automates and watches the cold backup. @@ -26,10 +26,10 @@ Open Dental's floor is **at least one backup per day**, with a combination of me | Job | What | When | Runbook | |---|---|---|---| -| **1. Cold backup** | Stop DB, copy data + images, restart | Nightly, off-hours | [`od-db-backup.md`](od-db-backup.md) | -| **2. Off-site upload** | Replicate `` to cloud/immutable | After job 1 finishes | [`od-db-backup.md` §6](od-db-backup.md) | -| **3. Health check** | Verify newest backup + heartbeat ping | After job 1 finishes | this runbook + [`od-backup-check.ps1`](scripts/od-backup-check.ps1) | -| **4. Test-restore** | Full restore into isolated VM | Monthly | [`od-backup-verify.md`](od-backup-verify.md) | +| **1. Cold backup** | Stop DB, copy data + images, restart | Nightly, off-hours | [`od/db-backup.md`](db-backup.md) | +| **2. Off-site upload** | Replicate `` to cloud/immutable | After job 1 finishes | [`od/db-backup.md` §6](db-backup.md) | +| **3. Health check** | Verify newest backup + heartbeat ping | After job 1 finishes | this runbook + [`od-backup-check.ps1`](../scripts/od-backup-check.ps1) | +| **4. Test-restore** | Full restore into isolated VM | Monthly | [`od/backup-verify.md`](backup-verify.md) | Stagger them so nothing reads a half-written folder, e.g. **backup 23:30 → check 00:45 → off-site upload 01:00**. @@ -55,7 +55,7 @@ schtasks /Create /TN "OD Nightly Cold Backup" ^ ## 2. Schedule the off-site upload (after the backup) -Point your off-site tool (Duplicati → Backblaze B2, `rclone`, Veeam, etc.) at **``** — it uploads *this backup*, it does **not** re-run the stop/copy against the live database. Schedule it **after** job 1 completes and stagger the start. Enable that tool's **own** email/report and **object-lock/immutability** for the ransomware-resistant off-site copy. Details: [`od-db-backup.md` §6](od-db-backup.md). +Point your off-site tool (Duplicati → Backblaze B2, `rclone`, Veeam, etc.) at **``** — it uploads *this backup*, it does **not** re-run the stop/copy against the live database. Schedule it **after** job 1 completes and stagger the start. Enable that tool's **own** email/report and **object-lock/immutability** for the ransomware-resistant off-site copy. Details: [`od/db-backup.md` §6](db-backup.md). ## 3. Schedule the health check (and heartbeat) @@ -120,7 +120,7 @@ When Layer 2/3 flags a problem, in rough order: 1. **Is the database up?** `Get-Service ` — if the backup died mid-run, confirm the service **restarted** (the script's `finally` should have; verify). The practice being able to work comes first. 2. **Destination full / offline?** Free space on ``; is the disk/UNC reachable? Prune old `od-backup-` generations if space-bound. -3. **Partial/most-recent folder incomplete?** Check that run's `backup.log` for the `ERROR`/`CRITICAL` line; re-run the backup by hand ([`od-db-backup.md`](od-db-backup.md)). +3. **Partial/most-recent folder incomplete?** Check that run's `backup.log` for the `ERROR`/`CRITICAL` line; re-run the backup by hand ([`od/db-backup.md`](db-backup.md)). 4. **Version drift?** A recent Open Dental/MySQL update can change paths — reconcile against `MANIFEST.txt`. 5. **Off-site not uploading?** Check the cloud tool's log and that it sources `` (not the live datadir). @@ -128,7 +128,7 @@ Then re-run the health check and confirm the heartbeat goes green. ## Records / evidence -Keep the `\backup-check.log`, the monitor's uptime history, and the monthly **test-restore** results ([`od-backup-verify.md`](od-backup-verify.md)) together. That trail is your DR evidence for E&O / cyber insurance and HIPAA contingency-plan testing. +Keep the `\backup-check.log`, the monitor's uptime history, and the monthly **test-restore** results ([`od/backup-verify.md`](backup-verify.md)) together. That trail is your DR evidence for E&O / cyber insurance and HIPAA contingency-plan testing. --- @@ -141,4 +141,4 @@ Keep the `\backup-check.log`, the monitor's uptime history, and the monthl - Open Dental manual — Backups (daily minimum; automated + combined methods): - Microsoft — `schtasks` / Scheduled Tasks: - healthchecks.io — dead-man's-switch cron monitoring: -- Companion runbooks — [`od-db-backup.md`](od-db-backup.md) (produce the backup), [`od-backup-verify.md`](od-backup-verify.md) (test-restore) +- Companion runbooks — [`od/db-backup.md`](db-backup.md) (produce the backup), [`od/backup-verify.md`](backup-verify.md) (test-restore) diff --git a/od-backup-verify.md b/od/backup-verify.md similarity index 93% rename from od-backup-verify.md rename to od/backup-verify.md index eb42a93..8f8526a 100644 --- a/od-backup-verify.md +++ b/od/backup-verify.md @@ -3,7 +3,7 @@ > For qualified IT professionals, on systems they are authorized to administer. > Provided as-is, without warranty — verify it fits your environment. See LICENSE. -**Applies to:** Any Open Dental cold backup produced by [`od-db-backup.md`](od-db-backup.md) (an `od-backup-` folder holding `data\`, `OpenDentImages\`, `FreeDentalConfig.xml`, `MANIFEST.txt`). +**Applies to:** Any Open Dental cold backup produced by [`od/db-backup.md`](db-backup.md) (an `od-backup-` folder holding `data\`, `OpenDentImages\`, `FreeDentalConfig.xml`, `MANIFEST.txt`). **Goal:** Prove a backup is actually restorable and complete by restoring it into a **throwaway, network-isolated Hyper-V virtual machine** and running a short health checklist. A backup you have never restored is a guess. > [!IMPORTANT] @@ -66,7 +66,7 @@ Run these **inside the VM**, elevated. This mirrors Open Dental's documented res ``` robocopy "\data" "" /E /COPY:DAT /R:2 /W:5 ``` - > For **InnoDB** you must restore the shared tablespace and logs (`ibdata1`, `ib_logfile*`) that live at the datadir root alongside the `opendental` folder — that's why we restore the whole `data\`, matching how [`od-db-backup.md`](od-db-backup.md) captured it. Restoring only the `opendental` subfolder yields a database that won't start. + > For **InnoDB** you must restore the shared tablespace and logs (`ibdata1`, `ib_logfile*`) that live at the datadir root alongside the `opendental` folder — that's why we restore the whole `data\`, matching how [`od/db-backup.md`](db-backup.md) captured it. Restoring only the `opendental` subfolder yields a database that won't start. 4. **Restore the images:** ``` robocopy "\OpenDentImages" "" /E /COPY:DAT /R:2 /W:5 @@ -108,7 +108,7 @@ Log, outside the VM: **date verified**, `` timestamp, ` - Open Dental manual — Database Maintenance (Check/Fix health tool): - Open Dental manual — Backup Tool: -- Companion runbook — producing the backup: [`od-db-backup.md`](od-db-backup.md) +- Companion runbook — producing the backup: [`od/db-backup.md`](db-backup.md) diff --git a/od-cfg-persist.md b/od/cfg-persist.md similarity index 100% rename from od-cfg-persist.md rename to od/cfg-persist.md diff --git a/od-db-backup.md b/od/db-backup.md similarity index 97% rename from od-db-backup.md rename to od/db-backup.md index df22d67..be6acef 100644 --- a/od-db-backup.md +++ b/od/db-backup.md @@ -109,11 +109,11 @@ Register the cold backup as a nightly **Task Scheduler** job (runs off-hours, as schtasks /Create /TN "OD Nightly Cold Backup" /TR "powershell -NoProfile -ExecutionPolicy Bypass -File C:\ops\od-db-backup-local.ps1" /SC DAILY /ST 23:30 /RU SYSTEM /RL HIGHEST ``` -Full scheduling **and monitoring** (staggering the off-site upload, a daily health check, and a dead-man's-switch heartbeat so a silent failure gets caught): **[`od-backup-schedule.md`](od-backup-schedule.md)**. +Full scheduling **and monitoring** (staggering the off-site upload, a daily health check, and a dead-man's-switch heartbeat so a silent failure gets caught): **[`od/backup-schedule.md`](backup-schedule.md)**. ## 5. Verify — a backup you haven't restored is a guess -- **Test-restore** to an **isolated** machine periodically (matching Open Dental + MySQL/MariaDB versions): `net stop`, rename the existing `opendental` folder aside, drop in the backup's `data\` contents, `net start`, launch Open Dental, spot-check patients/images. Full step-by-step with a health checklist: **[`od-backup-verify.md`](od-backup-verify.md)** (isolated Hyper-V test-restore). +- **Test-restore** to an **isolated** machine periodically (matching Open Dental + MySQL/MariaDB versions): `net stop`, rename the existing `opendental` folder aside, drop in the backup's `data\` contents, `net start`, launch Open Dental, spot-check patients/images. Full step-by-step with a health checklist: **[`od/backup-verify.md`](backup-verify.md)** (isolated Hyper-V test-restore). - **Never restore over a live production database** — data loss is irreversible. - Confirm the nightly job is actually producing dated folders and that they leave the building (off-site / immutable copy) — ransomware that reaches the server will reach on-line backups too. @@ -138,7 +138,7 @@ Any off-site/cloud replication (Duplicati → Backblaze B2, Veeam, `rclone`, Was Backup media and dumps hold the **entire practice's PHI**. Treat them as the crown jewels: encrypt the destination, lock down share permissions, and keep at least one copy **off-line/immutable** so ransomware can't encrypt your backups along with production. Don't store `` in the scheduled command line — use a MySQL option file / limited account. -Note that the captured `FreeDentalConfig.xml` stores the MySQL password **obfuscated but reversible** on **direct-connection** setups. The backup already contains all PHI so this doesn't change the requirement — but it's one more reason the destination must be encrypted and access-controlled. (Middle Tier setups don't put DB credentials in that file — see `od-cfg-persist.md`.) +Note that the captured `FreeDentalConfig.xml` stores the MySQL password **obfuscated but reversible** on **direct-connection** setups. The backup already contains all PHI so this doesn't change the requirement — but it's one more reason the destination must be encrypted and access-controlled. (Middle Tier setups don't put DB credentials in that file — see `od/cfg-persist.md`.) ## References diff --git a/od-scan-duplex.md b/od/scan-duplex.md similarity index 100% rename from od-scan-duplex.md rename to od/scan-duplex.md diff --git a/od-smb-cred.md b/od/smb-cred.md similarity index 100% rename from od-smb-cred.md rename to od/smb-cred.md diff --git a/scripts/cg-disable.ps1 b/scripts/cg-disable.ps1 index c972c13..40c0185 100644 --- a/scripts/cg-disable.ps1 +++ b/scripts/cg-disable.ps1 @@ -12,7 +12,7 @@ .NOTES Run via: irm rb.godwinsystems.com/scripts/cg-disable.ps1 | iex - Referenced by od-smb-cred.md, Step 3. + Referenced by od/smb-cred.md, Step 3. If Credential Guard is still running after reboot, it was enabled with a UEFI lock (needs the bcdedit / physical-presence removal), or MDM policy is diff --git a/scripts/od-backup-check.ps1 b/scripts/od-backup-check.ps1 index 2b0e180..4cea251 100644 --- a/scripts/od-backup-check.ps1 +++ b/scripts/od-backup-check.ps1 @@ -26,7 +26,7 @@ For unattended monitoring, schedule a filled-in LOCAL copy (with and the heartbeat URL baked in) — keep that copy in the private tier, not here. See - od-backup-schedule.md. + od/backup-schedule.md. iex-safe: uses `return`, never `exit` (which would close an interactive session). PUBLIC REPO: no client specifics hard-coded; prompt at run time. @@ -148,4 +148,4 @@ if ($heartbeat) { } } -if (-not $healthy) { Write-Warning 'Investigate now — see od-backup-schedule.md triage.' } +if (-not $healthy) { Write-Warning 'Investigate now — see od/backup-schedule.md triage.' } diff --git a/scripts/od-cfg-acl.ps1 b/scripts/od-cfg-acl.ps1 index b9d1f8d..f914e8b 100644 --- a/scripts/od-cfg-acl.ps1 +++ b/scripts/od-cfg-acl.ps1 @@ -16,7 +16,7 @@ .NOTES Run via: irm rb.godwinsystems.com/scripts/od-cfg-acl.ps1 | iex - Referenced by od-cfg-persist.md, Option B. + Referenced by od/cfg-persist.md, Option B. SECURITY: on direct-connection setups FreeDentalConfig.xml also holds the MySQL password (obfuscated but reversible). Widening write access here does diff --git a/scripts/od-db-backup.ps1 b/scripts/od-db-backup.ps1 index f9f37b3..17c2acb 100644 --- a/scripts/od-db-backup.ps1 +++ b/scripts/od-db-backup.ps1 @@ -24,7 +24,7 @@ This is the primary "gold" backup. Pair it with an off-hours mysqldump for a portable logical copy and with off-site/immutable retention — see - od-db-backup.md. + od/db-backup.md. .NOTES Run ON THE DATABASE SERVER, elevated, when no one is using Open Dental: diff --git a/sec-google-compromise.md b/sec/google-compromise.md similarity index 99% rename from sec-google-compromise.md rename to sec/google-compromise.md index 97336a0..ed05713 100644 --- a/sec-google-compromise.md +++ b/sec/google-compromise.md @@ -12,7 +12,7 @@ > Nothing here decides whether a reportable breach occurred, whether notification is required, or what any deadline is. Those are legal determinations. Where this runbook reaches one, it tells you to **stop, document, and escalate** to the practice's compliance contact or counsel. Work the technical steps; do not opine on the legal ones — not in this document, not in email, not verbally to the client. > [!WARNING] -> **This repo is public-read.** This file is a **template with placeholders only**. Do not fill it in here and do not commit incident particulars, real account names, phishing domains, hostnames, or timestamps to this repo. Clone it to the **private tier** (private repo or Bitwarden secure note) and work the filled-in copy there. See [CONTRIBUTING.md](CONTRIBUTING.md). +> **This repo is public-read.** This file is a **template with placeholders only**. Do not fill it in here and do not commit incident particulars, real account names, phishing domains, hostnames, or timestamps to this repo. Clone it to the **private tier** (private repo or Bitwarden secure note) and work the filled-in copy there. See [CONTRIBUTING.md](../CONTRIBUTING.md). --- @@ -656,7 +656,7 @@ Deliver **in writing**, factually, with no legal characterization: - [ ] Deploy a password manager; eliminate reuse. - [ ] Add DNS filtering and configure UniFi **syslog export** so the next incident has logs. - [ ] Security awareness training covering AiTM phishing specifically — including that a correct-looking Google page and a working 2FA prompt prove nothing. -- [ ] Verify Duplicati backups are intact, versioned, and **not reachable with any credential exposed in this incident**; confirm the Open Dental/MariaDB backup chain per [`od-backup-verify.md`](od-backup-verify.md). +- [ ] Verify Duplicati backups are intact, versioned, and **not reachable with any credential exposed in this incident**; confirm the Open Dental/MariaDB backup chain per [`od/backup-verify.md`](../od/backup-verify.md). --- @@ -755,4 +755,4 @@ If a path doesn't match what you see: navigate from **[myaccount.google.com](htt - Microsoft — Microsoft Safety Scanner download: - Sysinternals — Autoruns: - Sysinternals — Process Explorer: -- Companion runbook — backup integrity after an incident: [`od-backup-verify.md`](od-backup-verify.md) +- Companion runbook — backup integrity after an incident: [`od/backup-verify.md`](../od/backup-verify.md) diff --git a/sec-google-evidence.md b/sec/google-evidence.md similarity index 97% rename from sec-google-evidence.md rename to sec/google-evidence.md index 84722dd..9a2540b 100644 --- a/sec-google-evidence.md +++ b/sec/google-evidence.md @@ -5,7 +5,7 @@ **Applies to:** A consumer Google/Gmail account, before or after containment. No Workspace admin console required. **Use it for:** (a) capturing account state **before** you change anything, and (b) checking whether anyone got back in **after** a password reset. -**Companion:** [`sec-google-compromise.md`](sec-google-compromise.md) — full containment procedure. +**Companion:** [`sec/google-compromise.md`](google-compromise.md) — full containment procedure. **Placeholders:**