WRKLOG-2026-06-17
Summary
Wednesday. Fill summary at end of day.
URGENT - All Domains
Carryover Backlog (CRITICAL)
| Task | Details | Origin | Days | Status |
|---|---|---|---|---|
MSCHAPv2 Migration Report |
Report due. 6-sheet Standard Report (exec summary, trend, waves, device detail, stale, policy match). Sheet 6 added 05-14: policy match by protocol for removal planning + anonymous identity validation. Migration window 2026-05-04 to 2026-05-30. ~6,227 devices, 5 waves. |
2026-04-17 |
83 |
P0 - DUE — run report this week |
Abnormal Security — ✅ COMPLETE |
CR-2026-05-07-abnormal-read-write. CAB approved 2026-05-12. Implemented successfully 2026-05-13. Read/write enabled for pilot group. Post-deployment validation pending. |
2026-05-07 |
63 |
✅ IMPLEMENTED — post-validation pending |
SIEM QRadar → Sentinel Migration |
Lead role. Monad console error RESOLVED 2026-05-12 — secrets configured in CHLA production tenant. ISE secure syslog integration in progress — cert imported, remote logging target configured, streaming errors under investigation. Blocking: DCR not created (Rule ID + Stream Name). Azure private network policy unresolved. Victor + Mauricio action. |
2026-04-10 |
90 |
P0 - ACTIVE — ISE syslog + DCR blocking |
Monad Pipeline Evaluation |
Sentinel output connector. Console error resolved. 3 of 6 values configured. Remaining: Endpoint URL (have it), Rule ID + Stream Name (need DCR). ISE Remote Logging Target configured 2026-05-18 — TLS cert imported, secure syslog target created. Streaming errors in Monad console under investigation. |
2026-03-11 |
120 |
P0 - ACTIVE — ISE integration in progress |
Guest Redirect ACL |
Guest redirect ACL work needed. Related to Mandiant remediation findings. |
2026-05-12 |
58 |
P0 - TODO |
ISE Patch 10 (CVE-2026-20147 CVSS 9.9) |
ISE 3.2 Patch 10. Supersedes Patch 9. 61 days on a CVSS 9.9 — schedule maintenance window. Write CR if needed. |
2026-03-12 |
119 |
P0 - OVERDUE — schedule immediately |
k3s NAT verification |
NAT rule 170 for 10.42.0.0/16 pod network - test internet connectivity. 64 days — test this week or defer to Q3. |
2026-03-09 |
122 |
P0 - BLOCKING — TRIAGE: schedule or defer |
Wazuh indexer recovery |
Restart pod after NAT confirmed working - SIEM visibility blocked. Blocked by k3s NAT — cannot proceed until above resolved. |
2026-03-09 |
122 |
P0 - Blocked by k3s |
Strongline Gateway VLAN fix |
8 devices in wrong identity group (David Rukiza assigned) |
2026-03-16 |
115 |
P0 - TODO |
TCP Clocks deployment |
ISE identity group validation, query outputs, comms with team. Active d001 data Apr 22-23. |
2026-04-22 |
78 |
P0 - ACTIVE |
IoT Dr. Kim — recurring |
Sleep study devices (Apr 15-16), watches recurrence (Apr 22). 5 incident versions in d001. Validate iPSK enrollment. |
2026-04-15 |
85 |
P0 - RECURRING |
Murus Portae (WAF) — Phase 0 |
FMC cert expired, ACP returns zero rules. d001: zone map, architecture D2, FMC API reference, ops script. |
2026-04-16 |
84 |
P0 - INVESTIGATING |
Vocera EAP-TLS Supplicant Fix |
~10 phones failing 802.1X, missing supplicant config. 61 days — schedule with clinical engineering team. |
2026-03-12 |
119 |
P1 - TODO — schedule |
ISE MnT Messaging Service |
Enable "Use ISE Messaging Service for UDP syslogs delivery". 61 days — low risk, schedule with ISE Patch 10 maintenance window. |
2026-03-12 |
119 |
P2 - BUNDLE with Patch 10 |
| Professional backlog remains critical. Check Days column for priorities. |
BLOCKERS — Fix Immediately
| Task | Details | Origin | Days | Impact |
|---|---|---|---|---|
Z Fold 7 Termux |
gopass and SSH not working |
2026-03-10 |
58 |
BLOCKER — Cannot access passwords on mobile |
gopass v3 organization |
Inconsistent structure, poor key-value usage |
2026-03-20 |
48 |
Inefficient password management, no aggregation |
Git history scrub — sensitive personal terms |
Plaintext references to personal legal matters in committed worklogs (WRKLOG-2026-03-14, WRKLOG-2026-04-18). Forward-fixed but old commits still contain strings. Requires |
2026-04-22 |
15 |
SECURITY — sensitive terms in public git history |
Runbook: Git History Scrub (d000 Personal Terms)
Problem: Two committed worklogs contained plaintext references to personal legal matters. The files have been edited (forward-fix), but git history retains the original text in prior commits.
Affected commits: Any commit touching these files:
# Identify affected commits
git log --oneline -- \
docs/modules/ROOT/pages/2026/03/WRKLOG-2026-03-14.adoc \
docs/modules/ROOT/pages/2026/04/WRKLOG-2026-04-18.adoc
Scrub procedure:
# 1. BEFORE: Full backup of the repo
cp -a ~/atelier/_bibliotheca/domus-captures ~/atelier/_bibliotheca/domus-captures.bak
# 2. Install git-filter-repo (if not present)
# Arch: pacman -S git-filter-repo
# pip: pip install git-filter-repo
# 3. Create expressions file for replacement
cat > /tmp/scrub-expressions.txt << 'EXPR'
regex:(?i)divorce==[REDACTED]
regex:(?i)dissolutio(?!n\.adoc\.age)==[REDACTED-LEGAL]
regex:(?i)iliana==[REDACTED-NAME]
regex:(?i)angulo-arreola==[REDACTED-NAME]
regex:legal-divorce-notes\.age==legal-notes.age
regex:1099-NEC-iliana==1099-NEC
EXPR
# 4. Verify before (dry run — count matches in history)
git log -p --all -S 'divorce' -- '*.adoc' | grep -c 'divorce' || echo "0 matches"
git log -p --all -S 'iliana' -- '*.adoc' | grep -c 'iliana' || echo "0 matches"
# 5. Run filter-repo (DESTRUCTIVE — rewrites all commit hashes)
git filter-repo --replace-text /tmp/scrub-expressions.txt --force
# 6. Verify after
git log -p --all -S 'divorce' -- '*.adoc' | grep -c 'divorce' || echo "0 matches — CLEAN"
git log -p --all -S 'iliana' -- '*.adoc' | grep -c 'iliana' || echo "0 matches — CLEAN"
# 7. Re-add remotes (filter-repo removes them)
git remote add origin git@github.com:<user>/domus-captures.git
# Add any other remotes (Gitea, etc.)
# 8. Force-push to all remotes (DESTRUCTIVE — overwrites remote history)
git remote | xargs -I{} git push {} main --force
# 9. Clean up
rm /tmp/scrub-expressions.txt
rm -rf ~/atelier/_bibliotheca/domus-captures.bak # only after verifying
Post-scrub checklist:
-
Backup created before running
-
git filter-repoinstalled -
Expressions file reviewed — no false positives (e.g., Don Quijote "Angulo el Malo" is in
segunda-parte/texto/texto-011.adoc— the regex targetsangulo-arreolaspecifically to avoid this) -
Dry-run counts match expectations
-
Filter-repo executed
-
Post-scrub verification shows 0 matches
-
Remotes re-added
-
Force-pushed to all remotes
-
Cloudflare Pages rebuild verified
-
Local clones on other machines re-cloned or
git fetch --all && git reset --hard origin/main -
Backup removed
URGENT - Requires Immediate Action
| Item | Details | Deadline | Status | Impact |
|---|---|---|---|---|
Housing Search |
Granada Hills area - apartments/rooms |
TBD |
In Progress |
Quality of life, commute |
2025 Tax — IRS Transcript Review |
MFJ filed 2026-04-22. Pull IRS Return Transcript to verify contents. Consult attorney re: Form 8857 (Innocent Spouse Relief). Details in encrypted case file. |
Before attorney meeting |
In Progress |
Financial — liability exposure. See encrypted D000 case file. |
Rack Relocation |
Physical move of server rack. CR written: CR-2026-04-18 (pending in infra-ops). Borg backup completed. VM XML dumps, switch save, shutdown/startup procedure documented. |
TBD |
Pending |
Infrastructure downtime — all services offline during move |
D000 Legal Planning |
Encrypted D000 case file. Open: |
Before Jan 2029 |
Active — escalating |
Life transition — see case file for details |
Credit Report Review |
Pull reports from all 3 bureaus via annualcreditreport.com. Verify no unknown joint accounts or debts. Credentials in gopass: |
TBD |
In Progress |
Financial discovery — FL-142 preparation |
Gopass Security Audit |
Rotate passwords on shared/known accounts. Add 2FA backup codes to |
TBD |
Pending |
Digital security — pre-filing preparation |
Subscription Audit |
Download 3 months bank/CC statements (Chase, NFCU, USAA). Identify all recurring charges. Cancel unnecessary. Document active subscriptions for FL-150. |
TBD |
Pending |
Financial — expense documentation |
401(k) Enrollment |
Enroll in CHLA 401(k) immediately. Post-separation contributions are 100% separate property. Reduces gross income for support calculations. Max 2026: $23,500/yr. |
In progress (started 5/4) |
In Progress |
Financial — support calculation + retirement |
URGENT — Performance Review Certifications
| Certification | Provider | Deadline | Status | Impact |
|---|---|---|---|---|
CISSP |
ISC² — Certified Information Systems Security Professional |
July 12, 2026 |
ACTIVE — Week 2 of 10 (Project) |
Required for performance review. 10-week accelerated plan. |
RHCSA 9 |
Red Hat Certified System Administrator |
Q3 2026 |
ACTIVE — 21-phase curriculum (Project) |
After CISSP. Required for performance review. |
| CISSP: 41 days remaining (exam July 12). Domain 1 study in progress. Schedule exam today (06-01). |
Early Morning - 5:30am
Regex Training (CRITICAL CARRYOVER)
-
Session 3 - Character classes, word boundaries
-
Practice drills from regex-mastery curriculum
-
Status: 52 days carried over (since 2026-03-16) — CRITICAL
| Regex training continues to slip. This is the foundation for all CLI mastery. |
Daily Notes
Triage Status
| Item | Status | Destination |
|---|---|---|
Quijote chapters 37-43 — 21 missing attributes fixed |
done |
atributos-quijote.adoc — all 21 gaps filled, validated in browser |
P16g dual-screen + deep-sleep regression |
pending |
dots-quantum hyprland.conf — investigate kernel/DRM regression |
d001 acme-cert — next steps after POC |
active |
d001 open acme-cert |
d001 siem-qradar-to-sentinel — ISE syslog + DCR |
blocked |
d001 open siem-qradar-to-sentinel |
d001 tcp-clocks — onsite testing continues |
active |
d001 open tcp-clocks |
find/glob/regex skill improvement |
in progress |
codex + daily notes — build on 06-16 cli-search-patterns |
Annual review — submit to Sarah (CISO) TODAY |
urgent — DUE TODAY |
d000 cursus/annual-review — finalize + submit |
Linux research document — DUE |
urgent |
d001 linux-research — finalize deliverable |
CISSP — update annual review goal: scheduling Aug 2026 |
action |
Update goal-carryover.tex — not attained, rescheduling |
ISE cert expiry (was 06-16 urgent) |
verify scope |
Check if cert renewed |
d001 workflow redesign — 3 data loss incidents |
needs design |
Atomic workflow — carry forward |
Monad blockers (5 people) |
blocked |
Awaiting others |
Carry Forward
Carry Forward from 06-16
| Item | Status | Notes |
|---|---|---|
ISE cert expiry (was 06-16 urgent) |
verify scope |
Did the cert renew? Check ISE admin UI or |
d001 workflow redesign — 3 data loss incidents on 06-15 |
needs design |
Atomic open→edit→build→verify→close→commit workflow |
Monad blockers: Kenneth, Mauricio, Victor, Argam, Tony |
blocked |
Awaiting others — no action unless they respond |
ISE rotation (kvm-01) — phases 0-2 done |
carry forward |
Next: restore/patch/certs |
Vault SSH cert timer — not yet built |
carry forward |
systemd timer needed (8h validity) |
VPN SSL cert expiring 2026-07-28 |
tracking |
~41 days remaining |
ISE RabbitMQ PID limit at 310% |
carry forward |
Health warning from 06-10 |
Urgent
Annual Review — Submit to Sarah TODAY
Review period: CY2025 + H1 2026. Reports to: Sarah Clizer, Manager, Information Security.
Status
-
LaTeX portfolio artifact exists:
data/d000/cursus/annual-review/chla/2025/main.tex -
37 projects across 5 domains, 14 critical
-
6 domain partials complete (auth-access, vuln-compliance, network-infra, siem-monitoring, platform-cloud, doc-tooling)
-
Goal carryover section complete — 5/5 goals addressed
-
Summary section complete
-
✅ Self-eval draft complete:
data/d000/cursus/annual-review/chla/2025/self-eval-draft-2026.adoc -
✅ All sections drafted with evidence from d001 project notes
-
✅ 4 CRs documented (VLAN, Abnormal, Guest ACL, Anonymous Identity)
-
✅ Monad correctly framed as POC — Cribl and Microsoft-native under evaluation
-
✅ CISSP framed as rescheduled (August 2026) due to operational load
Action items
-
Review all 6 domain partials for accuracy against current project states
-
Draft self-eval with evidence from d001 projects (SIEM, Abnormal, MSCHAPv2, Mandiant, CRs, incidents)
-
Update CISSP goal line: "Scheduling exam ~Aug 2026" — communicate to Sarah that CISSP not yet attained, rescheduling
-
Final read-through of self-eval — adjust voice/tone
-
Copy self-eval sections into xlsx
-
Rebuild PDF:
cd data/d000/cursus/annual-review/chla/2025 && pdflatex main.tex && pdflatex main.tex -
Review output PDF
-
Submit to Sarah
Self-eval rating strategy
-
Exemplary: Job Skills, Outcomes, Growth/Innovation (3 of 8)
-
Effective: Service Excellence + all 4 remaining values (5 of 8)
-
Last year: self-rated all Effective; Sarah upgraded 3 to Exemplary
-
This year: self-rating Exemplary on same 3 — evidence is stronger, backed by numbers
Key numbers (receipts)
-
1,219 log sources inventoried, 437 types, 55% error rate
-
6,088 devices across 9 platforms (MSCHAPv2)
-
20 syslog transforms (POC), 23 SQL queries
-
30 M365 transport rules audited, 2 high-severity findings
-
7 Mandiant findings, 4 CRs through CAB, 20+ investigations
-
Cost analysis: $9.9K/yr → $3.9K/yr (ETL pipeline)
CISSP study commitment (starting 2026-06-17)
-
0530 wake — Domain reading (Sybex, 30-45 min)
-
Evening — 25 practice questions + wrong-answer review (45-60 min)
-
Priority order: Domain 1 → 8 → 6 → 2 → 3 → 4 → 5 → 7
-
Schedule exam this week for mid-August
Linux research document
-
d001 project:
d001 open linux-research -
Deliverable needed for review — enterprise Linux research deployment
Quijote Chapters 37-43 — AsciiDoc Syntax Fixes
URGENT. Chapters 37-43 notas files have broken syntax: undefined attributes (\{c1 loc}, {antitesis}), instead of proper AsciiDoc highlighting (text or text). Needs full audit and repair.
Scope:
-
data/d000/education/quijote-study/notas/p1-cap-037/throughp1-cap-043/ -
Each
*-notas.adocfile — check for undefined attributes and broken formatting -
Cross-reference with custom roles defined in build toolchain (STD-024)
Root cause:
-
21 attributes used in chapters 37-43 but never defined in
atributos-quijote.adoc -
Three categories: accented variants (7), new rhetorical figures (12), missing domain tags (3)
-
All 21 added to
atributos-quijote.adoc— verified zero gaps remain
Validation:
# Open existing builds (from repo root)
for cap in {037..043}; do
firefox "data/d000/education/quijote-study/notas/p1-cap-${cap}/output/texto-anotado.html" &
done
Rebuild with light-cyan (batch):
# d000 build uses fzf — not scriptable in loops.
# Call build-adoc.sh directly with deterministic paths.
_BUILD=~/atelier/_bibliotheca/domus-asciidoc-build/bin/build-adoc.sh
_BASE=~/atelier/_bibliotheca/domus-captures/data/d000
for cap in {037..043}; do
echo "=== p1-cap-${cap} ==="
"$_BUILD" "$_BASE/education/quijote-study/notas/p1-cap-${cap}/texto-anotado.adoc" html --variant light-cyan
done && for cap in {037..043}; do
firefox "$_BASE/education/quijote-study/notas/p1-cap-${cap}/output/texto-anotado.html" &
done
d000 build wraps build-adoc.sh with interactive fzf file discovery. In loops, call the underlying tool directly — wrappers add value for human selection; scripts need deterministic paths.
|
Upload to Boox Palma 2 (MTP via simple-mtpfs):
# Mount — Palma 2 must be unlocked + USB connected + "File Transfer" mode
mkdir -p /tmp/palma2
simple-mtpfs /tmp/palma2
# Verify mount
ls /tmp/palma2
# Build PDFs (light-cyan theme)
_BUILD=~/atelier/_bibliotheca/domus-asciidoc-build/bin/build-adoc.sh
_BASE=~/atelier/_bibliotheca/domus-captures/data/d000
for cap in {037..043}; do
echo "=== PDF: p1-cap-${cap} ==="
"$_BUILD" "$_BASE/education/quijote-study/notas/p1-cap-${cap}/texto-anotado.adoc" pdf --theme light-cyan
done
# Create target directory on device (if first time)
mkdir -p /tmp/palma2/Books/Quijote
# Copy all PDFs to Palma 2
for cap in {037..043}; do
local_pdf="$_BASE/education/quijote-study/notas/p1-cap-${cap}/output/texto-anotado.pdf"
[ -f "$local_pdf" ] && cp "$local_pdf" "/tmp/palma2/Books/Quijote/cap-${cap}-texto-anotado.pdf" \
&& echo " ✓ cap-${cap}" \
|| echo " ✗ cap-${cap} — missing"
done
# Verify
ls /tmp/palma2/Books/Quijote/
# Unmount when done (MUST unmount before unplugging)
fusermount -u /tmp/palma2
MTP is a transfer protocol, not a real filesystem — find -delete and some shell operations don’t work. Copy/mkdir work. For bulk deletes, use the device UI.
|
Kill background tabs (lsof + command substitution):
# Kill background firefox jobs from THIS shell
kill $(jobs -p)
# Kill by port (when process wasn't launched from this shell)
kill $(lsof -t -i :8080)
# lsof key flags:
# +D dir — recurse into directory (open files underneath)
# -c name — filter by command name
# -t — terse: PIDs only (pipeable to kill)
# -i :port — filter by network port
Session Work
P16g — Post-Update Regression (3 Symptoms, 1 Root Cause)
Carry forward from 06-16 screen lock fix. All symptoms appeared after the same 2-3 system updates. All were non-existent at project start (clean Razer→P16g migration).
Symptom 1: Dual screen not working
-
External monitor detection broken — was functional at project start
-
Regression window: last 2-3 system updates (kernel/Hyprland/mesa?)
Symptom 2: Deep sleep requires external monitor to wake
-
After deep sleep, laptop screen stays black — no hyprlock prompt
-
Connecting external monitor triggers laptop display to wake
-
Occasionally, laptop monitor resumes immediately upon external connection
-
Pattern: intermittent but reproducible over past 2-3 updates
Symptom 3: USB ports randomly stop working
-
USB ports become unresponsive — any port, random timing
-
Only fix: reboot (not suspend/resume — full reboot)
-
Blocks: MTP device access (Palma 2), USB peripherals
-
Same regression window as symptoms 1 and 2
Common thread
All three symptoms point to power management / PCI-e link state regression:
-
Display (eDP + DP), USB (xHCI), and sleep (S3/s2idle) all traverse PCI-e
-
Arrow Lake-S (P16g Gen 2) has known i915/Xe DRM + Thunderbolt/USB4 power state issues
-
Kernel 7.0.x series introduced changes to PCI-e ASPM and USB autosuspend
Investigation plan
# 1. Identify the regression window — what changed?
# Kernel upgrades
awk '/upgraded linux/{print}' /var/log/pacman.log | tail -10
# All upgrades in the regression window (last 3 updates)
awk '/upgraded/{print}' /var/log/pacman.log | tail -30
# Current kernel
uname -r
# 2. USB diagnostics
lsusb -t # USB tree topology
dmesg | grep -i 'xhci\|usb.*error\|usb.*reset\|usb.*disconnect'
cat /sys/bus/usb/devices/*/power/autosuspend_delay_ms # autosuspend timers
# 3. Display/DRM diagnostics
journalctl -b -g 'drm|i915|xe' --no-pager | tail -30
cat /sys/class/drm/card*/status # connector states
# 4. PCI-e power management
cat /sys/module/pcie_aspm/parameters/policy
lspci -vv | grep -i 'aspm\|lnkctl'
# 5. Sleep mode
cat /sys/power/mem_sleep # s2idle vs deep
Root cause identified
Kernel 6.19.14 → 7.0.9 (2026-05-22) introduced the regression. All three symptoms absent on 6.19.x.
| Kernel | USB | Display | Sleep | Status |
|---|---|---|---|---|
6.19.14 (pre May 22) |
OK |
OK |
OK |
Worked |
7.0.9 (May 22) |
Flapping |
PHY refclk fail |
Black screen |
Broke |
7.0.11 (Jun 6) |
Same |
Same |
Same |
Still broken |
6.18.34-lts |
Test |
Test |
Test |
Try this |
Evidence
-
PHY A failed to request refclk— appears twice at boot (i915 DRM, display C-state clock recovery failure) -
USB port 3-5 flapping — Palma 2 disconnected after 24s, Samsung phone reconnected 4× in 9 seconds (xHCI controller resetting port)
-
USB autosuspend
autoon 11/12 devices — 7.0.x more aggressive power management defaults -
PCI-e ASPM policy:
[default]— defers to BIOS, no explicit Linux override
Fix: Boot LTS kernel (no workarounds)
linux-lts 6.18.34 already installed, boot entry exists, kernel image in /boot.
# Option A — test once: reboot, select "Arch Linux LTS" from systemd-boot menu
# Option B — make LTS default now
# Before
bootctl list | grep -E 'title|default'
# Change
sudo bootctl set-default arch-lts.conf
# After
bootctl list | grep -E 'title|default'
After reboot on LTS:
# Confirm LTS
uname -r
# Verify PHY error gone
journalctl -b -g 'PHY.*failed'
# Test USB — plug in Palma 2, watch for flapping
journalctl -b -f -g 'usb 3-'
# Test sleep — close lid, reopen, check hyprlock appears on laptop screen
Keep linux 7.0.11 installed as fallback. When 7.1 or 7.2 lands with Arrow Lake fixes, switch back and retest.
Post-reboot test (2026-06-17, kernel 7.0.11)
Rebooted on mainline 7.0.11 — all three symptoms persist.
[720.579576] usb 3-1: New USB device found, idVendor=18d1, idProduct=4ee1
[720.710824] usb 3-1: Product: LAGOON-MTP _SN:2DF6C0DC
[720.710825] usb 3-1: Manufacturer: ONYX
[737.148826] usb 3-1: USB disconnect, device number 12 (1)
[739.085591] usb 3-1: new high-speed USB device number 13 (2)
| 1 | Disconnected after 17 seconds — no user action |
| 2 | Reconnected 2 seconds later as new device number — classic xHCI port reset |
The Palma 2 enumerates as MTP (idVendor=18d1 Google/Android, idProduct=4ee1).
MTP is a protocol-level device — it does not create a block device in /dev/sd* or /dev/nvme*.
lsblk only shows block devices.
To access MTP: gio mount mtp:// or jmtpfs /mnt/palma.
The absence from lsblk is normal; the 17-second disconnect is the regression symptom.
[559.615517] usb 3-5.4: New USB device found, idVendor=043e, idProduct=9a39
[559.615524] usb 3-5.4: Product: USB Controls
[559.615526] usb 3-5.4: Manufacturer: LG Electronics Inc.
[559.631308] cdc_acm 3-5.4:1.1: ttyACM0: USB ACM device
LG monitor DDC/CI controls bound on port 3-5.4 — USB not fully dead, confirming intermittent/selective failure pattern.
[56.004551] typec port0: bound usb4_port1 (ops connector_ops [thunderbolt])
[61.615271] typec port1: bound usb4_port1 (ops connector_ops [thunderbolt])
[67.132976] typec port2: bound usb4_port3 (ops connector_ops [thunderbolt])
TB4 enumeration succeeded — the regression is downstream of the controller, in USB power management.
Next step unchanged: boot LTS kernel 6.18.34 and retest all three symptoms.
Related
-
INC-2026-05-23-002 — same Arrow Lake-S DRM issue family
-
06-16 lid switch fix — brightnessctl workaround pending
-
P16g deploy project — appendix-issues.adoc candidate
d001 Projects — Active Today
| Project | Command | Focus |
|---|---|---|
ACME Cert Automation |
|
POC complete — next: move d001→d000, AppRole, Cloudflare into Vault |
SIEM QRadar → Sentinel |
|
ISE syslog + DCR blocking — Victor + Mauricio action items |
TCP Clocks |
|
Onsite testing continues — new switch RADIUS/AAA config |
find — Glob vs Regex Patterns
Yesterday covered find vs rg vs fzf tool selection. Today: mastering find pattern syntax — the glob/regex distinction that caused errors.
The error and why
# BROKEN — | is regex alternation, but -name uses glob
find -name '*03[7,8,9]|04[1,2]*'
# Also wrong — commas inside [] are literal characters
# [7,8,9] matches: 7 , 8 , 9 (five chars, not three)
# [789] matches: 7 8 9 (correct — three chars)
Glob patterns (find -name)
Globs have only three wildcards: * (any chars), ? (one char), […] (char class).
No alternation. No quantifiers. No grouping.
# Character class — correct
find -name '*03[789]*' -type d
# Multiple patterns with -o (OR)
find \( -name '*03[789]*' -o -name '*04[0123]*' \) -type d
# Brace expansion — shell expands BEFORE find sees it
find -name '*p1-cap-0'{37,38,39,40,41,42,43}'*' -type d
# Shell expands to 7 separate -name arguments
Regex patterns (find -regex)
-regex matches the full path, not just the filename. Uses POSIX BRE by default.
# POSIX BRE — escaped grouping and alternation
find -regex '.*p1-cap-0\(3[789]\|4[0-3]\).*' -type d
# Extended regex — cleaner syntax
find -regextype posix-extended -regex '.*p1-cap-0(3[789]|4[0-3]).*' -type d
Key distinction
| Feature | Glob (-name) |
Regex (-regex) |
|---|---|---|
Wildcards |
|
|
Alternation |
None (use |
|
Scope |
Filename only |
Full path |
Grouping |
None |
|
Default in find |
Yes ( |
No (must specify |
grep -w: whole-word matching prevents substring traps
Without -w, alternation patterns match substrings — MTP matches SMTP:
# Without -w — 12 false positives from SMTP in ghost-sender investigation
grep -rn 'MTP\|lsblk\|jmtpfs\|gio mount' $(find -name '*daily-notes*' -type d)
# With -w — only whole-word MTP, no SMTP matches
grep -rnw 'MTP\|lsblk\|jmtpfs\|gio mount' $(find -name '*daily-notes*' -type d)
-w wraps each alternation branch in \b…\b (word boundary). Critical when your search term is a substring of a longer word.
find + grep: two approaches, never nested
Option A — command substitution (fine when paths have no spaces):
grep -rnw 'MTP\|lsblk' $(find -name '*daily-notes*' -type d)
Option B — find -exec (safer, no word-splitting):
find -name '*daily-notes*' -type d -exec grep -rnw 'MTP\|lsblk' {} +
Never nest them. This breaks:
# BROKEN — find -exec grep output becomes arguments to outer grep
grep -rnw 'MTP' $(find -name '*daily-notes*' -type d -exec grep -rn 'MTP' {} +)
# grep output contains "lsblk --scsi" → outer grep parses --scsi as flag → error
The $(…) substitution feeds stdout as arguments. When grep output contains --flags, the outer grep chokes. These are alternatives, not layers.
sed -n address ranges: extract between patterns
sed -n '/start/,/end/p' prints all lines between two regex matches — useful for extracting content from structured files.
# Extract email body from an AsciiDoc partial (strip markup, keep text)
sed -n '/^Hi \[Medigate/,/^Evan$/p' partials/comms-2026-06-17-medigate-attributes.adoc
-
-nsuppresses default output — onlypprints -
/^Hi \[Medigate/— start pattern (the\[escapes the bracket —[is regex special) -
/^Evan$/— end pattern ($anchors to end of line — exact match) -
Inclusive: both the start and end lines are printed
find | while read: run shell aliases on found files
find -exec spawns a new process — it doesn’t inherit shell aliases. Pipe to while read to stay in your shell:
# BROKEN — build-adoc is an alias, find -exec can't see it
find data/d001/projects/siem-qradar-to-sentinel -maxdepth 1 -name '*.adoc' \
-exec build-adoc {} html --variant light-cyan \;
# WORKS — while read runs in your shell where aliases live
find data/d001/projects/siem-qradar-to-sentinel -maxdepth 1 -name '*.adoc' | \
while read -r f; do build-adoc "$f" html --variant light-cyan; done
Three approaches by power level:
# 1. while read — aliases work, sequential
find ... -name '*.adoc' | while read -r f; do build-adoc "$f" html; done
# 2. find -exec with full path — no alias, sequential
find ... -name '*.adoc' -exec ~/path/to/build-adoc.sh {} html \;
# 3. xargs -P for parallel — full path required, NOT bash -ic
find ... -name '*.adoc' -print0 | \
xargs -0 -P2 -I{} ~/atelier/_bibliotheca/domus-asciidoc-build/bin/build-adoc.sh {} html --variant light-cyan
Never use xargs -P bash -ic — interactive shells (-i) fight over the TTY when run in parallel. Processes suspend with "tty input" error. Use the full path to the script instead.
|
Showing file content with find: cat vs grep vs sed vs awk
cat does not take -exec — it’s not find. Don’t mix their syntax.
# BROKEN — cat doesn't have -exec
cat $(find -name 'rsyslog-central*.adoc') -exec grep -rn '[source]'
# grep — show lines matching a pattern with context
grep -n -B1 -A2 '\[source' $(find -name 'rsyslog-central*.adoc')
# sed -n — show a specific line range
sed -n '5,38p' $(find -name 'rsyslog-central*.adoc')
# awk — show range between two patterns
awk '/\[source\]/,/^----$/' $(find -name 'rsyslog-central*.adoc')
Three tools, three use cases:
| Tool | Use case | Pattern |
|---|---|---|
|
Find lines matching a pattern with surrounding context |
|
|
Extract exact line range (when you know the line numbers) |
|
|
Extract between two patterns (when you know the delimiters) |
|
$(find …) works with all three — it expands to the file path. The key: find finds, the other tool processes. Never give cat arguments meant for find.
Practice exercises
-
Find all Quijote chapters 1-10:
find -regex '.*p1-cap-0\(0[1-9]\|10\)' -type d -
Find all
.adocfiles modified in the last 2 days:find -name '*.adoc' -mtime -2 -type f -
Find all session files across d001:
find data/d001 -name 'session-.adoc' -not -name '.age'
find — Advanced Patterns (Tested Live)
All commands tested on this system. Real output confirmed.
Recency — what changed and when
find ~ -type f -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort -rn | head -20
find ~ -type f -mmin -30 -printf '%TY-%Tm-%Td %TH:%TM:%TS %12s %p\n' | sort -rn | head -15
find ~/atelier/_bibliotheca/domus-captures -type f -newermt "2026-06-17" \
! -path '*/.git/*' -printf '%TH:%TM %p\n' | sort -rn | head -20
-newermt takes a date string — compares mtime against it.
-mmin -N is minutes ago. -mtime -N is days ago.
Size — find what’s eating disk
find ~ -type f -size +50M -printf '%s %p\n' | sort -rn | head -10 \
| awk '{printf "%8.1fM %s\n", $1/1048576, $2}'
find ~/atelier/_bibliotheca/domus-captures -type f -empty -printf '%p\n'
Counting and grouping — awk as the aggregator
find ~/atelier/_bibliotheca/domus-captures -type f \
| awk -F. '{print $NF}' | sort | uniq -c | sort -rn | head -15
8759 adoc
3842 html
1683 js
657 ts
637 age
512 svg
327 md
294 json
259 sh
194 d2
Security audit — find what shouldn’t be there
find ~/atelier/_bibliotheca/domus-captures/data -type f \
\( -name '*.adoc' -o -name '*.json' -o -name '*.yaml' \) \
! -name 'README.adoc' ! -path '*/shared/*' ! -path '*/education/*' \
! -path '*/sessions/*'
Multi-predicate logic: \( -o \) is OR, ! is NOT.
This finds plaintext that escaped the gitignore net — run before every push.
Duplicate detection
find ~/atelier/_bibliotheca/domus-captures/docs -type f -name '*.adoc' \
-printf '%f\n' | sort | uniq -d
-printf '%f\n' prints just the filename (no path).
uniq -d shows only lines that appear more than once.
Remote history capture (new pattern — first use today)
ssh kvm-01 "cat ~/.bash_history" \
| tee data/d000/shell-history/kvm-01-bash-hist-"$(date +%F)"
echo y | encrypt-file data/d000/shell-history/kvm-01-bash-hist-"$(date +%F)"
tee writes to file and stdout — you see the output scroll while it’s captured.
$(date +%F) expands locally before ssh runs.
echo y pipes confirmation to the interactive "Remove original?" prompt.
-printf format reference
| Format | Meaning |
|---|---|
|
Full path |
|
Filename only (no directory) |
|
Directory only (no filename) |
|
Size in bytes |
|
Modified date (YYYY-MM-DD) |
|
Modified time (HH:MM:SS.fractional) |
|
Modified time as epoch seconds (best for sort) |
|
Owner username |
|
Permissions (octal) |
Predicate reference
| Predicate | Meaning |
|---|---|
|
Regular files only |
|
Directories only |
|
Glob match on filename |
|
Glob match on full path |
|
Larger than 50MB ( |
|
Modified within last 30 minutes |
|
Modified within last 24 hours |
|
Modified after this date |
|
Zero-size files |
|
Exclude .git directories |
|
OR (must escape parens from shell) |
|
Run cmd per match ( |
|
Run cmd with batched matches ( |
|
Null-delimited output (safe for |
Near-Miss: Glob Expansion Matched Pipeline Deletion Script
2026-06-17 — during screenshare
Incident
Attempted to build an AsciiDoc file using find with command substitution:
build-adoc $(find -name 'build-*.sh') html --variant light-cyan
The find -name 'build-*.sh' glob matched a shell script created to destroy a Monad pipeline.
The command substitution expanded the match and passed it as an argument to build-adoc.
This occurred during an active screenshare.
What prevented damage
-
dsucredential hygiene — API credentials had been unsourced after prior use (dsuclears all sourced vars). Even if the destructive script had somehow executed, it could not authenticate against the Monad API without sourced credentials. -
build-adocexpected.adoc, not.sh— the tool did not execute the matched script, but the expansion itself was the danger.
Root cause
find -name 'build-.sh' is unbounded — it recursively matches every file matching the pattern in the current directory tree.
Shell command substitution ($(…)) expands the result *before the outer command sees it.
There is no preview, no confirmation, and no scope restriction.
A destructive script named build-destroy-pipeline.sh or build-cleanup.sh is indistinguishable from build-adoc.sh to the glob pattern build-*.sh.
Lessons
| Rule | Rationale |
|---|---|
Always |
|
Scope |
|
Never use |
Use |
Name destructive scripts with a |
|
|
Credential unsourcing is the last line of defense when everything else fails |
Defensive patterns
# SAFE: preview what find matches
echo $(find docs/ -name 'build-*.adoc')
# SAFE: interactive confirmation with xargs
find docs/ -name '*.adoc' | xargs -p -I{} build-adoc {} html --variant light-cyan
# SAFE: scoped find with explicit directory
build-adoc $(find docs/ -name 'self-eval*.adoc') html --variant light-cyan
ds d001 lab/network # Source — 87 vars loaded
# ... do work ...
dsu # Unsource — 87 vars cleared
# API calls now fail safely — no credentials in environment
Status
-
Severity: Near-miss (no data loss, no pipeline destroyed)
-
Exposure: Active screenshare — credentials were NOT visible (dsu had cleared them)
-
Action: Document as discovery, add to codex defensive scripting patterns
-
Graduate to: Codex (glob safety) after 3+ references
Shell Function: d001 Project Builder
Generic function that builds any d001 project: renders changed diagrams, builds all assemblers in parallel, opens results. Add to shell config for reuse across all projects.
The function
build_d001() {
local project="${1:-$(pwd)}"
local diagrams="$project/diagrams"
local output="$project/output"
local builder="$HOME/atelier/_bibliotheca/domus-asciidoc-build/bin/build-adoc.sh"
printf 'Project: %s\n\n' "$project"
printf 'Rendering changed DOT diagrams...\n'
find "$diagrams" -type f -name '*.dot' -exec sh -c '
for f do
out="${f%.dot}.svg"
if [ ! -e "$out" ] || [ "$f" -nt "$out" ]; then
dot -Tsvg "$f" -o "$out"
printf " ✓ %s\n" "$out"
else
printf " - current: %s\n" "$out"
fi
done
' sh {} + 2>/dev/null
printf '\nBuilding AsciiDoc files...\n'
find "$project" -maxdepth 1 -type f -name '*.adoc' -not -name 'README.adoc' -print0 | \
xargs -0 -r -P3 -I{} "$builder" "{}" html --variant light-cyan
printf '\nOpening fresh HTML output...\n'
find "$output" -type f -name '*.html' -newer "$output" -exec firefox {} + &
printf 'Done.\n'
}
Usage
# From anywhere — pass the project path
build_d001 data/d001/projects/siem-qradar-to-sentinel
# From inside the project directory
cd data/d001/projects/tcp-clocks
build_d001
# Any d001 project with assemblers at root + diagrams/ dir
build_d001 data/d001/projects/ed-sewer-pump
What it does — three stages
| Stage | Tool | Why |
|---|---|---|
1. Diagrams |
|
Incremental — only renders |
2. Build |
|
Parallel — builds all assemblers simultaneously. Full path avoids alias issue. |
3. Open |
|
Only opens freshly built HTML, not stale artifacts |
Teaching points
-
-ron xargs — don’t run the builder iffindreturns nothing (no.adocfiles) -
-not -name 'README.adoc'— README is not an assembler, skip it -
-nt(newer than) — shell test:[ "$f" -nt "$out" ]returns true if source is newer than output. Prevents redundant diagram rendering. -
-newerin find — same concept: only match files modified after a reference point -
Full path for
build-adoc.sh—find -execandxargsdon’t inherit shell aliases. Use~/path/to/script.shdirectly. -
Never
xargs -P bash -ic— interactive shells fight over TTY in parallel. Processes suspend with "tty input" error.
Where to put it
This is a shell function, not a project script. Add to:
# ~/.config/zsh/functions/build_d001.zsh or equivalent
# Then source in .zshrc
Not in data/d001/projects/siem-qradar-to-sentinel/scripts/ — it’s generic, not project-specific.
SSH + gopass Workflow for Git Push
The ssh-agent only runs in user’s terminal session. Claude’s shell cannot push. This is the manual workflow.
Load SSH key for GitHub
# 1. Copy passphrase to clipboard (clears in 45s)
gopass show -c v3/domains/d000/identity/ssh/github
# 2. Add key to agent — paste passphrase when prompted
ssh-add ~/.ssh/id_ed25519_github
# 3. Verify
ssh-add -l
ssh -T git@github.com
Why this works
-
gopass show -ccopies the secret to clipboard without printing it to terminal -
ssh-addloads the key into ssh-agent for the session — no re-entry until reboot or agent restart -
The key comment (
github-arch-2026) identifies which key is loaded when multiple keys are in the agent
SSH config overview
Post-quantum hardened config (~/.ssh/config, ARS-SEC-SSH-001 v3.0):
-
ML-KEM-768 + NTRU Prime key exchange (requires OpenSSH 9.0+)
-
Least privilege — no legacy cryptography by default
-
Exception blocks for hosts requiring legacy ciphers
-
Socket multiplexing:
~/.ssh/sockets/for connection reuse -
Encrypted at rest:
ssh/.ssh/config.agetracked in git, plaintext gitignored
Adapt SSH config — TODO
-
Review exception blocks for work hosts (CHLA infrastructure)
-
Add any missing work jump hosts
-
Verify PQ KEX negotiation with home lab hosts
-
Test socket multiplexing performance with kvm-01/kvm-02 sessions
-
Re-encrypt after any edits:
age -e -R ~/.age/recipients/self.txt -o ssh/.ssh/config.age ssh/.ssh/config
domus-captures — Git Workflow Reference
Complete workflow: authenticate, commit, push, verify via API. domus-captures pushes to both GitHub (origin) and GitLab (gitlab). Cloudflare Pages auto-deploys from origin on push.
Remotes
| Name | URL | Purpose |
|---|---|---|
|
|
Primary — Cloudflare Pages deploys from here |
|
|
Mirror |
Step 1: Load SSH key
SSH agent is session-scoped — clears on reboot. Must reload after every boot.
gopass show -c v3/domains/d000/identity/ssh/github
ssh-add ~/.ssh/id_ed25519_github
ssh-add -l
ssh -T git@github.com
Step 3: Stage and commit
git add -A blindly)git add docs/modules/ROOT/partials/worklog/daily-notes/2026-06/2026-06-17/
git commit -m "$(cat <<'EOF'
docs(worklog): 2026-06-17 daily notes
- P16g regression: post-reboot dmesg evidence, MTP/lsblk explanation
- Copilot Lua merge prep: keybind collision fix, cmd list cleanup
- Rhetoric vocabulary: epithet, tricolon, isocolon figures
- Makefile: delegate export to build-antora-page.sh, fix nested includes
EOF
)"
Step 4: Push to remotes
git push origin main
git push gitlab main
git push origin main & git push gitlab main & wait
Step 5: Verify via GitHub API
gh api takes REST endpoint paths with leading / — not subcommands.
gh api /repos/EvanusModestus/domus-captures/commits --jq '.[0].commit.message | split("\n")[0]'
gh api /repos/EvanusModestus/domus-captures --jq '{size_kb: .size, pushed: .pushed_at, default_branch: .default_branch, visibility: .visibility}'
gh api /repos/EvanusModestus/domus-captures/commits --jq '.[:5] | .[] | "\(.sha[:7]) \(.commit.author.date[:10]) \(.commit.message | split("\n")[0])"'
gh api "/repos/EvanusModestus/domus-captures/commits?since=$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ)" --jq '.[] | "\(.sha[:7]) \(.commit.message | split("\n")[0])"'
gh api /repos/EvanusModestus/domus-captures/commits/main --jq '.files[] | "\(.status) \(.filename)"'
gh api /repos/EvanusModestus/domus-captures/branches --jq '.[].name'
gh api /repos/EvanusModestus/domus-captures/compare/main...HEAD --jq '{ahead: .ahead_by, behind: .behind_by, files: [.files[].filename]}'
gh api /repos/EvanusModestus/domus-captures/deployments --jq '.[:3] | .[] | {env: .environment, created: .created_at, description: .description}'
Quick reference — gh api patterns
| Endpoint | What it returns |
|---|---|
|
Authenticated user profile (login, public_repos, created_at) |
|
Repo metadata (stars, forks, size, pushed_at, visibility) |
|
Commit history (default: 30, paginated). Add |
|
Single commit detail with file list (status, filename, additions, deletions) |
|
Branch list with protection status |
|
Diff between two refs — ahead_by, behind_by, file list |
|
Deployment history (environment, status, created_at) |
|
CI/CD workflow runs (if using GitHub Actions) |
|
Contributor list with commit counts |
|
Language breakdown by bytes (Lua, AsciiDoc, etc.) |
gh api — key syntax rules
| Rule | Example |
|---|---|
Leading |
|
|
|
Query params with |
|
Pagination (default 30) |
|
No pager needed |
|
Common mistake: gh api user (no slash) — gh interprets it as a subcommand and fails. Always use /user, /repos/….
Aliases — existing shell functions
| Alias | Expands to |
|---|---|
|
|
|
|
|
Push to all remotes |
|
Push domus-captures to origin |
|
Check domus-captures status |
domus-nvim — Copilot Lua Merge Prep
Three commits on feature/copilot-lua: replace copilot.vim with copilot.lua + CopilotChat.nvim. Pre-merge cleanup: fix <leader>cf collision (Format lost when remapped to Fix), trim redundant cmd list, drop orphan CopilotChatOptimize.
Issue: <leader>cf collision
On main, <leader>cf = Format (conform.lua). On the branch, remapped to Fix code (CopilotChatFix). Format binding lost entirely.
Resolution: <leader>cf = Fix code (Copilot), <leader>cF = Format (conform).
Step 1: Find where Format is currently bound
cd ~/atelier/_projects/personal/domus-nvim
grep -rn 'format\|conform' lua/domus/plugins/specs/ lua/domus/plugins/config/ | grep -i 'leader\|keymap\|keys'
lua/domus/plugins/config/conform.lua:57: -- Manual format keymap
Format lives in conform.lua:57. Update its binding from <leader>cf to <leader>cF there.
Step 2: Add <leader>cF to which-key
sed -n '66,73p' lua/domus/plugins/config/which-key.lua
sed -i '71a\ { "<leader>cF", desc = "Format" },' lua/domus/plugins/config/which-key.lua
sed -n '66,75p' lua/domus/plugins/config/which-key.lua
Step 3: Trim redundant cmd list in coding.lua
The keys table already lazy-loads CopilotChat. The cmd list duplicates those triggers and includes CopilotChatOptimize which has no keymap.
grep -n 'cmd = {' lua/domus/plugins/specs/coding.lua
sed -i 's/cmd = { "CopilotChat", "CopilotChatExplain", "CopilotChatTests", "CopilotChatFix", "CopilotChatOptimize", "CopilotChatReview", "CopilotChatDocs" },/cmd = "CopilotChat",/' lua/domus/plugins/specs/coding.lua
grep -n 'cmd = ' lua/domus/plugins/specs/coding.lua
Step 4: Commit cleanup
git add -A
git commit -m "$(cat <<'EOF'
fix(copilot): restore Format bind as <leader>cF, trim CopilotChat cmd list
- <leader>cf was Format (conform), now Fix (CopilotChat) — add <leader>cF for Format
- Remove redundant cmd lazy-load triggers covered by keys table
- Drop orphan CopilotChatOptimize from cmd (no keymap)
EOF
)"
Step 5: Load SSH key and push feature branch
SSH agent is session-scoped — key must be loaded after every reboot. gopass copies the passphrase to clipboard (clears in 45s), then ssh-add loads the key.
gopass show -c v3/domains/d000/identity/ssh/github
ssh-add ~/.ssh/id_ed25519_github
ssh-add -l
git push origin feature/copilot-lua
Step 7: Push main
git push origin main
Step 8: Verify and clean up
git --no-pager log --oneline -5
git branch -d feature/copilot-lua
git push origin --delete feature/copilot-lua
Step 9: Verify via GitHub API
gh api takes a REST endpoint path, not a subcommand. The leading / is required.
gh api /repos/EvanusModestus/domus-nvim/commits --jq '.[0].commit.message' | head -1
gh api /user --jq '.login, .public_repos'
gh api /repos/EvanusModestus/domus-nvim --jq '{stars: .stargazers_count, forks: .forks_count, pushed: .pushed_at, default_branch: .default_branch}'
gh api /repos/EvanusModestus/domus-nvim/commits --jq '.[:5] | .[] | "\(.sha[:7]) \(.commit.message | split("\n")[0])"'
gh api /repos/EvanusModestus/domus-nvim/branches --jq '.[].name'
gh api /repos/EvanusModestus/domus-nvim/branches --jq '.[].name' | grep copilot || echo "Branch deleted — clean"
gh api /repos/EvanusModestus/domus-nvim --jq '.html_url'
Common mistake: gh api user (no slash) — gh interprets user as a subcommand, not an endpoint. Always /user, /repos/…, /orgs/….
Sharing with colleagues
The repo is ready. Give them:
git clone git@github.com:EvanusModestus/domus-nvim.git ~/.config/nvim
Prerequisites: Neovim 0.10+, a GitHub Copilot subscription, npm (for CopilotChat dependencies). On first launch, Lazy.nvim installs all plugins. Run :Copilot auth to authenticate.
Final keymap reference
| Bind | Action | Source |
|---|---|---|
|
Code action |
lsp |
|
Copilot chat |
CopilotChat |
|
Generate docs |
CopilotChat |
|
Explain code |
CopilotChat |
|
Fix code |
CopilotChat |
|
Format |
conform.lua |
|
Review code |
CopilotChat |
|
Generate tests |
CopilotChat |
|
Accept suggestion |
copilot.lua |
|
Next / prev suggestion |
copilot.lua |
|
Dismiss suggestion |
copilot.lua |
Education
Don Quijote — Lectura del día
Capítulo: XXXIX (Historia del cautivo, continuación)
Build: build-adoc data/d000/education/quijote-study/notas/p1-cap-039/p1-cap-039-notas.adoc html --variant light-cyan
Custom roles: .cervantes, .retorica, .testimonio, .teologia, .gramatica, .ironia, .pregunta
Lo que leí hoy
Escribe en español.
Vocabulario nuevo
| Palabra | Definición | Ejemplo en contexto |
|---|---|---|
palabra |
definición |
cita del texto |
Retórica que encontré
Figuras retóricas del capítulo — conectar con el vocabulario retórico del día (epithet, tricolon, isocolon).
Conexiones con Cicerón
De Inventione, prólogo (líneas 42–92) — ¿qué conecta con lo que leíste hoy?
Notas para SIELE/DELE
-
Registro formal observado:
-
Estructura sintáctica compleja:
Rhetorical Vocabulary — Figures and Power Words
Building a working register of rhetorical figures and high-impact vocabulary for professional and technical communication. Each term earns its place through use, not memorization.
Figures of speech — structural
| Figure | Definition | Example |
|---|---|---|
Tricolon |
Three parallel terms with ascending force |
Documented, verified, repeatable. |
Isocolon |
Parallel clauses of equal length and structure |
Methodical in structure, rigorous in verification, portable across colleagues. |
Epithet |
A characterizing phrase attached to a noun — compresses identity into description |
Meticulously methodical. Swift-footed Achilles. Wine-dark sea. |
Epitome |
The perfect embodiment of a type — the thing itself, not the description |
This workflow is the epitome of meticulously methodical engineering. |
Congeries |
Heaping synonyms for emotional weight — power through accumulation, not progression |
Thoroughly, copiously, meticulously (three ways to say "carefully" — use deliberately or not at all). |
Anaphora |
Repetition at the start of successive clauses — builds momentum |
We documented. We verified. We shipped. |
Asyndeton |
Deliberate omission of conjunctions — creates speed and urgency |
Document, verify, ship. |
Polysyndeton |
Deliberate excess of conjunctions — creates weight and deliberation |
Document and verify and test and ship. |
The tricolon test
A tricolon must ascend. Each term adds something the previous lacked. If you can drop one term and lose nothing, it wasn’t earning its place.
Thoroughly, copiously, meticulously methodical
Documented, verified, repeatable (self → proof → audience) Precise, defensible, transferable (quality → evidence → portability) Captured, validated, deployed (record → test → action)
Power words — high-impact professional vocabulary
| Word | Use and context |
|---|---|
Meticulous |
Extreme care in detail. Stronger than "careful" — implies nothing overlooked. Meticulous documentation ensures repeatability. |
Methodical |
Systematic, ordered approach. Implies process, not luck. Methodical verification catches what ad-hoc testing misses. |
Rigorous |
Exhaustively thorough, intellectually uncompromising. Rigorous analysis of the dmesg output isolated the regression window. |
Defensible |
Can withstand scrutiny or challenge. Stronger than "correct" — implies evidence. Every configuration change must be defensible in a post-incident review. |
Portable |
Works in any context, not coupled to one person’s knowledge. Portable runbooks let any team member execute at 3 AM. |
Authoritative |
Speaks with earned credibility. The antora.yml attributes are the authoritative source for mutable values. |
Canonical |
The one true reference — all others derive from it. INC-2026-04-12 is the canonical example of verify-before-acting. |
Deliberate |
Intentional, not accidental. Implies agency and ownership. Deliberate difficulty builds durable skill. |
Surgical |
Precise intervention with minimal collateral effect. A surgical sed edit — one line changed, system-wide impact. |
Durable |
Built to last, not expedient. Durable patterns outlive the project that created them. |
AsciiDoc — Data Table Formats Reference
Tables populated from structured data — CSV files, inline CSV, DSV, TSV. Single source of truth pattern: data lives in .csv, AsciiDoc renders it.
Three data formats
| Format | Delimiter | Shorthand | When to use |
|---|---|---|---|
CSV |
|
|
Default choice. Most portable. Importable by Excel, |
TSV |
tab ( |
none — use |
Tab-delimited exports. Set |
DSV |
|
|
When data contains commas. Avoid for MAC addresses (colons collide). |
Pattern 1: Inline CSV
[%header,format=csv]
|===
Name,Role,Status
Alice,Engineer,Active
Bob,PM,On Leave
|===
Pattern 2: CSV from file (reusable)
[%header,format=csv]
|===
include::../output/mac-list-all-clocks.csv[]
|===
The include:: pulls the CSV at build time. Edit the CSV, rebuild — table updates. One file feeds both the documentation and your awk/jq scripts.
Pattern 3: Shorthand notation
,===
Artist,Track,Genre
Baauer,Harlem Shake,Hip Hop
,===
The ,=== delimiter implies format=csv — no attribute needed. Add [%header] above to promote the first row.
Pattern 4: Collapsible with CSV include
.Full inventory (collapsible)
[%collapsible]
====
[%header,format=csv]
|===
include::../output/data.csv[]
|===
====
[%collapsible] wraps the table in a disclosure widget — click to expand. Keeps long tables from dominating the page.
Pattern 5: Column formatting on CSV data
CSV cells don’t support per-cell formatting. Use cols to format entire columns:
[%header,format=csv,cols="2,1,1"]
|===
include::data.csv[]
|===
cols="2,1,1" — first column gets 2x width. Add h for header style, a for AsciiDoc content:
[format=csv,cols="1h,2a"]
|===
Key,Value
Name,*Bold name*
|===
Escaping the pipe character in PSV tables
If cell content contains |, escape with \| or use |:
|===
| Command | Description
| grep foo \| wc -l
| Count matches
|===
Key rules
-
CSV/TSV: values can be enclosed in double quotes —
"value with, comma" -
CSV/TSV: empty lines are skipped (unless inside quotes)
-
DSV: escape delimiter with backslash —
value\:with\:colons -
Ragged tables: cells shuffle to fill rows (not padded like Excel)
-
No per-cell spans in data tables — use PSV (
|===) for row/column spans
Work — Exchange
Exchange Online — Policy Changes
ConnectExchange policy enablement during call. Commands and policy details encrypted in d001.
Location
Commands and output: d001 open abnormal → partials/
Context
-
Call with:
-
Reason:
-
Ticket/CR:
-
Policies changed (names only, no config):
-
Related: Today’s worklog
Workflow Demo — Docs-as-Code for Infrastructure Engineering
Prep for call with senior Linux engineer. Show the full pipeline: encrypted project data → AsciiDoc partials → Graphviz diagrams → single-command builds → PDF/HTML output. Everything version-controlled, everything reproducible.
Dispositio — Talk Structure
Exordium (hook — 30 seconds):
"Every project I work on — ISE onboarding, SIEM migration, Exchange policies — follows the same workflow. I write the commands, the notes, the diagrams, and the comms in AsciiDoc partials. One command builds a complete project document with topology diagrams, API queries, and email drafts. Everything is encrypted at rest, version-controlled in git, and deployable to a static site."
Narratio (the problem — 1 minute):
-
Confluence/SharePoint: stale the day it’s written, no version control, no CLI integration
-
OneNote/Word: can’t include code blocks with syntax highlighting, can’t
grepacross projects -
Tribal knowledge: the commands that solved the problem live in someone’s terminal history, not in a searchable system
Propositio (the thesis — 15 seconds):
"Infrastructure documentation should be written in the same tools and workflows as infrastructure code."
Confirmatio (the proof — live demo, 5 minutes):
Demo 1: Project lifecycle (tcp-clocks)
d001 open tcp-clocks
ls data/d001/projects/tcp-clocks/partials/
cat data/d001/projects/tcp-clocks/tcp-clocks.adoc
build-adoc $(find -name 'tcp-clocks.adoc') html --variant light-cyan
firefox data/d001/projects/tcp-clocks/output/tcp-clocks.html &
Demo 2: Diagrams as code (Graphviz)
cat data/d001/projects/tcp-clocks/images/tcp-clocks-profiling-chain.dot
dot -Tsvg data/d001/projects/tcp-clocks/images/tcp-clocks-profiling-chain.dot -o /tmp/demo.svg
firefox /tmp/demo.svg &
Key point: the diagram is diffable in git. When the profiling chain changes, git diff shows exactly what changed in the topology — not a binary blob.
Demo 3: Extract content with CLI tools
sed -n '/^Hi \[Medigate/,/^Evan$/p' $(find -name 'comms-2026-06-17-medigate-attributes.adoc')
grep -rnw 'assetVendor' $(find data/d001 -name '*.adoc' -not -name '*.age')
awk -F, 'NR>1 {s[$3]++} END {for (k in s) printf "%s: %d\n", k, s[k]}' data/d001/projects/tcp-clocks/output/mac-list-all-clocks.csv
Key point: the documentation IS the data. You don’t export from a GUI and paste into a doc — the doc contains the queries, the queries produce output, the output feeds the next query.
Demo 4: Encryption at rest
d001 close tcp-clocks
ls data/d001/projects/tcp-clocks/partials/*.age | head -5
d001 open tcp-clocks
Demo 5: Daily worklog system
ls docs/modules/ROOT/partials/worklog/daily-notes/2026-06/2026-06-17/
./scripts/build-antora-page.sh docs/modules/ROOT/pages/2026/06/WRKLOG-2026-06-17.adoc pdf --theme light-cyan
git push origin main
# → Cloudflare Pages builds → https://docs.domusdigitalis.dev
Peroratio (close — 30 seconds):
"The infrastructure I manage is complex — ISE, SIEM, Exchange, Claroty, 165 IoT devices. The documentation system has to match that complexity without adding friction. AsciiDoc + git + CLI tools + encryption gives me a workflow where writing documentation is the same act as doing the work. The notes I take while solving a problem ARE the documentation."
Philosophy — why this works
| Principle | Implementation |
|---|---|
Single source of truth |
Partials hold content once. Pages and assemblers are shells with |
One concern per file |
|
Verify-before, change, verify-after |
Every command block in the docs follows the same pattern the infrastructure follows. |
Encryption at rest |
|
Diagrams as code |
Graphviz |
CLI-native |
|
Automatic deployment |
|
Repos to show (if asked)
ls ~/atelier/_bibliotheca/domus-*/
-
domus-captures— worklogs, projects, sessions, codex (this repo) -
domus-infra-ops— infrastructure runbooks -
domus-ise-linux— 802.1X EAP-TLS documentation -
domus-docs— Antora aggregator hub -
domus-asciidoc-build— build toolchain with custom themes
Discoveries
Discovery: EAP-TEAP Compiled into Arch wpa_supplicant
2026-06-17 ~23:30 — confirmed via `strings $(which wpa_supplicant) | grep -i teap`
Finding
Arch Linux wpa_supplicant ships with EAP-TEAP support compiled in.
Key string found: OpenSSL: Enable cipher suites for anonymous EAP-TEAP provisioning.
This means Linux endpoints can authenticate via EAP-TEAP using the same ISE policy sets as Windows — no separate enrollment architecture required for the MSCHAPv2 migration.
Verification commands
# Confirm TEAP support
wpa_supplicant -h 2>&1 | grep -i teap
strings $(which wpa_supplicant) | grep -i teap
wpa_supplicant.conf — EAP-TEAP with inner MSCHAPv2
network={
ssid="CHLA-Secure"
key_mgmt=WPA-EAP
eap=TEAP
identity="user@chla.usc.edu"
anonymous_identity="anonymous@chla.usc.edu"
phase2="auth=MSCHAPV2"
ca_cert="/etc/ssl/certs/chla-ca.pem"
}
wpa_supplicant.conf — EAP-TEAP with inner EAP-TLS (cert-based)
network={
ssid="CHLA-Secure"
key_mgmt=WPA-EAP
eap=TEAP
identity="user@chla.usc.edu"
anonymous_identity="anonymous@chla.usc.edu"
phase2="auth=TLS"
ca_cert="/etc/ssl/certs/chla-ca.pem"
client_cert="/etc/ssl/certs/client.pem"
private_key="/etc/ssl/private/client.key"
}
Tomorrow (2026-06-18)
-
Test EAP-TEAP against ise-01 on kvm-01 (lab)
-
Create ISE authorization policy for Linux EAP-TEAP
-
Document wired 802.1X variant (
wpa_supplicantwithwireddriver) -
Check if Rocky 9 / Ubuntu Noble ship TEAP-enabled
wpa_supplicant -
Update Linux Research project with finding
Session Summary
Session Summary — 2026-06-17
18 partials produced. Multiple d001 projects advanced. Infrastructure changed in production.
Makefile & Build System
-
Fixed
make export-today— delegated PDF/HTML/DOCX/EPUB tobuild-antora-page.sh(recursivepartial$resolution) -
Fixed DOCX/EPUB pipeline — route through HTML intermediate instead of docbook5 (avoids nested markup XML error)
-
Changed default PDF theme to
light-cyan(Noto Sans font issue withdarktheme) -
Discovered
modules/ROOT/pages/2026/06/imagesrequired for standalone AsciiDoc builds — saved to memory
P16g Regression (Kernel 7.0.11)
-
Documented post-reboot dmesg evidence — USB flapping (ONYX Palma 2 disconnect/reconnect in 17s)
-
Documented MTP vs lsblk distinction — MTP is protocol-level, not a block device
-
LG monitor USB controls functional — proving selective/intermittent USB failure
-
All 3 Thunderbolt ports binding — regression is downstream in USB power management
gocryptfs Credential Gate
-
Documented Claude Code authentication behavior — vault unmounted = Sonnet/unauthenticated, vault mounted = Opus/Max
-
Defense-in-depth: LUKS + gocryptfs double encryption for API credentials
domus-nvim — Copilot Lua Merge
-
Merged
feature/copilot-luato main —copilot.vim→copilot.lua+ CopilotChat.nvim -
Fixed
<leader>cfkeybind collision — Format moved to<leader>cF -
Trimmed redundant
cmdlist, removed orphanCopilotChatOptimize -
Shared with colleagues — clone-ready on main
TCP Clocks (d001)
-
165 clocks — many lost identity group assignment overnight
-
Extended Step 2 API check — added
profileIdresolution viaers "/profilerprofile/{pid}" -
Profile name resolution tested and proven in d000 lab:
Winstars-Technology-Device -
Added DataConnect queries (Steps 2b, 2c) — endpoint profile + authz rule from RADIUS auth
-
Added CoA reauth commands (Step 7) + port bounce with confirmation (Step 8)
-
Created MAC inventory partial with CSV —
[%header,format=csv]table +awkexport commands -
Created Medigate email draft — requesting Claroty attribute push for all 165 clocks
-
Fixed all 73 bare
----listing blocks across all partials -
Created Graphviz profiling chain diagram (Catppuccin Mocha)
-
Added
dc_queryfunction directly in session file — paste-ready
ED Sewer Pump (d001 — new project)
-
Scaffolded full d001 project: README, assembler, 4 partials, images, Graphviz topology
-
CISO (Sarah) assigned — reaching out to Karen Patterson (PM) for device details
-
ISE response draft + Karen email draft
-
7 ISE validation queries (identity groups, dACLs, profiling policies, logical profiles, ED switches)
-
8-step action tracker
Exchange Online (d001)
-
Policy changes scaffold — breadcrumb in daily notes, actual commands in d001/abnormal-security
SIEM QRadar-to-Sentinel (d001)
-
Project audit: 25 includes verified, 0 broken. Deleted 8.2MB duplicate session dumps. Archived stale notes. Moved graphviz lesson to d000/education.
-
Assembler fix: moved
monad-vs-dcr.adocfrompartials/to project root (STD-001). Updatedbuild-monad-doc.sh. Verified both assemblers build clean. -
Replaced ASCII topology with Graphviz
rsyslog-collection-topology.dot(Catppuccin Mocha) -
Added
:imagesdir: modules/ROOT/pages/2026/06/diagramsto main assembler +modules/ROOT/pages/2026/06/imagesfor screenshots -
Updated
build-monad-doc.sh: parallel builds, incremental diagram rendering, both assemblers -
Switch 10.193.144.249 onboarded:
-
Configured:
logging source-interface Vlan144,logging host,snmp-server trap-source Vlan144,logging origin-id hostname -
Verified syslog arrives at CHLXSYSLOG01
-
Verified Monad receives events —
monad-observe.shlive sample confirmed
-
-
Monad pipeline expanded: 15→17 nodes, 14→16 edges:
-
Created
switch-sinkoutput node +switch-routeedge (single PATCH, slug-referenced) -
Created
switch-syslog-extracttransform (ID:9407d074) -
Rewired:
input-syslog → switch-extract → switch-sink -
Applied 10 enrichment operations:
source_type,facility,environment,collector,severity_tier,compliance_scope,retention_tier,pipeline_version,switch_name,location -
Dropped
prikey (saves ingestion cost) -
Proven live output with all enrichment tags
-
-
5 Monad API constraints documented:
-
POST /edgesdeprecated — returns 404 -
No multiple incoming edges per node
-
No orphan root nodes — node + edge must be added together
-
PATCH disables all nodes — must re-enable with
enabled: trueon every node -
Transform PATCH replaces entire object — always include
nameanddescription
-
-
Transform API discovery:
type: "jq"withconfig.expressiondoes NOT work. Onlyconfig.operationswithadd/drop_key/flatten. No regex extraction in transforms. -
Quick-reference pattern: GET → jq modify → PATCH for adding/removing transform keys without retyping
ISE API Reference (d000 — new)
-
Unified reference: ERS, MnT, DataConnect, pxGrid, OpenAPI — 5 API surfaces
-
Assembler with cross-API workflow patterns (full audit, CoA with verify, batch profile resolution)
-
Profile name resolution tested:
ers "/profilerprofile/{pid}"→ proven in d000 lab -
Graphviz topology diagram (Catppuccin Mocha)
-
Shared partials: pxGrid (4 stubs), OpenAPI (3 stubs)
-
ERS endpoints.adoc: group + profile name resolution pattern with test output
CLI Skills Learned
-
grep -w— whole-word matching prevents substring traps (MTP vs SMTP) -
find | while read— aliases work in shell loop, not infind -exec -
find -execvsxargs -P— parallel builds with full path (neverbash -ic) -
sed -n '/start/,/end/p'— address range extraction (Medigate email from AsciiDoc) -
awk '/pattern1/,/pattern2/'— range between delimiters -
catdoes not take-exec—findfinds, other tools process -
AsciiDoc CSV tables:
[%header,format=csv]withinclude::from file -
[%collapsible]for long tables -
build_d001shell function — generic d001 project builder with incremental diagrams + parallel
Education
-
Rhetoric vocabulary: epithet vs epitome, tricolon test, congeries, anaphora, asyndeton
-
Power words: meticulous, methodical, rigorous, defensible, portable, authoritative, canonical
-
Quijote cap XXXIX reading session scaffolded
-
Workflow demo prep for senior Linux engineer — dispositio structure, 5 live demos
Metrics
-
18 daily note partials produced
-
5 d001 projects touched (tcp-clocks, siem, ed-sewer-pump, abnormal, domus-nvim)
-
1 d000 project created (ISE API reference)
-
17 Monad pipeline nodes (from 15)
-
16 Monad pipeline edges (from 14)
-
1 switch onboarded end-to-end (config → syslog → rsyslog → Monad → enriched output)
-
10 enrichment tags per switch event
-
5 API constraints documented from production errors
-
73 bare listing blocks fixed across tcp-clocks partials
-
156 MAC addresses in CSV inventory
Ad-Hoc Requests
Ad-Hoc Requests
Capture walk-ups, Teams pings, and unplanned work here.
gocryptfs credential gate — Claude Code authentication
Claude Code requires API credentials at launch. Credentials are stored inside a gocryptfs vault (credentials), unmounted at rest.
| State | Result |
|---|---|
Vault unmounted |
Claude Code loads as Sonnet 4.6 / API Usage Billing / "Not logged in" — falls back to unauthenticated mode |
After |
Claude Code loads as Opus 4.6 / Claude Max — full authenticated session |
-
Credentials encrypted at rest via gocryptfs — reboot clears the mount
-
No plaintext credentials on disk until explicit
gcvault mount -
Failed auth is silent degradation (reduced model, no subscription), not a crash
-
Mount is session-scoped — survives sleep, cleared on reboot
This is intentional defense-in-depth: even with disk encryption (LUKS cryptroot + crypthome), the API credentials get a second layer via gocryptfs.
The tradeoff is a manual mount step after every reboot.
Work (CHLA)
| CHARGE TIME IN PEOPLESOFT - CRITICAL. Do this NOW before anything else. |
Critical (P0)
| Project | Description | Owner | Status | Due | Blocker |
|---|---|---|---|---|---|
Linux Research (Xianming Ding) |
EAP-TLS for Linux workstations, dACL, UFW |
Evan |
BEHIND (72 days overdue) |
02-24 |
Certificate "password required" - nmcli fix documented |
iPSK Manager |
Pre-shared key automation |
Ben Castillo |
BEHIND |
— |
DB replication issues |
MSCHAPv2 Migration |
Legacy auth deprecation — 6,227 devices, 5 waves. 6 batch SQL queries + 3-API endpoint profile script added (05-11). Report due. |
Evan |
25% — Report due, batch queries ready |
05-30 |
Report to turn in |
Research Segmentation |
All endpoints to Untrusted VLAN |
Evan |
BLOCKED |
— |
CISO decision pending |
Disaster Recovery |
ISE DR scoping — dot1x closed mode = total blackout |
Evan |
Scoping |
— |
— |
Mandiant Remediation |
Copy 4/16 findings, Guest ACL lab, Q2 assessment |
Evan |
Active |
— |
— |
SIEM QRadar → Sentinel |
Full SIEM platform transition. Monad console error resolved 05-12. Secrets configured. Blocked on DCR creation (Rule ID + Stream Name). Azure private network policy unresolved. |
Evan |
Active — blocked on DCR |
Q2 2026 |
Victor/Mauricio: create DCR, resolve Azure network policy |
Abnormal Security |
AI email platform — ESA cutover. CR assigned, CAB May 12 15:00. Implementation May 14 10:00. |
Evan |
Active — CAB today 15:00 |
05-14 |
Pre-CAB checklist: confirm Tyler, Jason, Sarah |
High Priority (P1)
| Project | Description | Owner | Status | Target |
|---|---|---|---|---|
ISE 3.4 Migration |
Upgrade from 3.2p9 |
Evan |
Blocked — maintenance window needed |
Q2 2026 |
Switch Upgrades |
IOS-XE fleet update (C9300, 3560CX) |
Evan |
Pending |
Q2 2026 |
Spikewell BYOD VPN |
dACL SQL, AD group integration |
Evan |
Active |
— |
Strongline Gateway |
MAC capture, Identity Group setup — 37 days aging |
Evan |
Active — David Rukiza assigned |
— |
Abnormal Security |
AI email security platform research, ESA cutover timeline |
Evan |
Newly assigned |
— |
DMZ Migration |
External services audit behind NetScaler |
Evan |
Audit phase |
— |
Firewall Audit (murus-portae) |
EtherChannel query, prefilter, policy assignments |
Evan |
Scoping — ASA API creds needed |
— |
iPSK Manager HA |
Server 2 config, TLS, SQL security audit |
Evan |
In progress |
— |
Sentinel KQL |
Build proficiency, distinguish from team |
Evan |
Onboarding |
— |
VNC Blocking |
Block and eliminate VNC protocol enterprise-wide |
Evan |
Active — Phase 0 (Discovery) |
Mid-June 2026 |
Strategic (P2)
| Project | Description | Owner | Status |
|---|---|---|---|
HHS Regulatory Compliance |
New HHS security policies implementation |
TBD |
NOT STARTED |
InfoSec Reporting Dashboard |
PowerBI metrics for executives |
TBD |
NOT STARTED |
EDR Migration (AMP → Defender) |
Endpoint protection consolidation |
TBD |
NOT STARTED |
Azure Legacy Migration |
Modern landing zone |
Team |
In Progress |
ChromeOS EAP-TLS |
SCEP + Victor, Paul testing |
Victor |
In Progress |
P0 — Critical / Blocking
Security & Compliance
-
ISE 3.2 Patch 10 upgrade — CVE-2026-20147 CVSS 9.9 / CVE-2026-20148. Propose maintenance window once patch confirmed on software.cisco.com.
-
ISE Advisory sa-ise-rce-traversal-8bYndVrZ — check Patch 10 availability
-
Mandiant Remediation — findings status tracked. Working session prep + defensive posture documented (comms-2026-04-24). Copy 4/16 updates into Excel at work. Guest ACL lockdown (WIR-M-01) pending lab validation. appendix-todos updated with MSCHAPv2 milestones.
-
Guest ACL update — guest redirect ACL work needed. Lab validate GUEST_CWA_REDIRECT_MAX_SECURITY in d000, then joint CR with NE. On today’s task list.
-
Disaster Recovery & Downtime Procedures — ISE top priority (dot1x closed mode = SPOF for network access)
-
ISE DR: Document failover sequence — PAN, MnT, PSN priority order
-
ISE DR: RADIUS dead-server detection on WLCs/switches — critical-auth VLAN fallback
-
ISE DR: Backup/restore procedures — scheduled config backups, tested restores
-
FTD/FMC DR: FMC loss = no policy management
-
Network DR: Core/distribution switch failure, STP reconvergence, HSRP failover
-
Document RTO/RPO per system
-
SIEM Migration (QRadar → Sentinel)
-
SIEM QRadar → Sentinel Migration — LEAD ROLE. 4 collection iterations (Apr 16, 17, 17-streamlined, 20-streamlined). Python chart pipeline built (
qradar-charts.py). Migration XLSX generated. Verification pending. Comms sent Apr 23.-
d001 artifacts: 8 JSON exports, 2 CSV inventories, migration XLSX, top5 source SVG/PNG, verification doc
-
Dependency: Monad pipeline for log source transition
-
Dependency: Sentinel KQL proficiency for query migration
-
-
Monad Pipeline Evaluation (origin: 2026-03-11) — lead role. Console error RESOLVED 05-12. 06-09: Architecture decision — rsyslog (CHLXSYSLOG01) as collection tier → Monad → Sentinel. ISE lab → rsyslog → Monad 6-step execution guide created with 10 API calls. ASA lab logs already flowing through rsyslog. DCR still needed — Victor + Mauricio.
-
Sentinel KQL — build proficiency, distinguish from team. Azure portal access acquired.
-
QRadar log source report — run AQL queries, fetch JSON, generate Python Excel
Active Deployments & Migrations
-
MSCHAPv2 Migration — 6-sheet Standard Report ready. Migration window 05-04 to 05-30 CLOSED. Confirm final report status and next steps with team. 6,227 MSCHAPv2 devices, 14,249 EAP-TLS/TEAP (70% migrated).
-
MSCHAPv2 weekly cadence — recurring Wednesday call established (first 04-22). Completed 2026-04-22.
-
MSCHAPv2 ownership matrix — sent in scoping email 4/24 with manager callouts (@Albert, @John). Completed 2026-04-24.
-
TCP Clocks deployment — Batch 1: 7 clocks validated (OUI 40:AC:8D). Batch 2 (06-09): 9 new MACs (OUI 40:AC:BD) added via ERS. 1 one-off reassigned. New switch deployed without RADIUS/AAA — clocks can’t authenticate. Switch onboarding template + 3 validation queries documented. ERS queries self-contained with
ersfunction. -
SRT Research VLAN — confirm roles with Tony Sun: Tony implementor, Evan tester. CAB approved 04-21.
-
Downtime Computers enforcement — draft ISE AuthZ rule: medigate_724 + Wireless = DenyAccess. Separate CR. d001: DC queries, audit CSVs (v1-v3), wireless violations report delivered 04-21.
-
Enterprise Linux 802.1X — standardize Shahab/Ding deployment (CISO priority). Overdue since 02-24. Blocked by nmcli cert fix. 06-15: Assembler build fixed (26 errors → 0). Segmentation document extension to 06-16.
d001 open linux-researchto work on it. -
Abnormal Security — CR-2026-05-07. Implemented 05-13. 06-09 update: Full policy review — 20-section EOP validation commands rebuilt, Hoxhunt SCL-1 investigation (intentional bypass confirmed), sclizer junk folder triage (~800 emails), Outlook reactions audit added, Connect-ExchangeOnline msalruntime fix documented. ESA migration expansion in progress — priority to move off ESA to full environment.
-
Team: Cox/William, Landeros/Jason, Rosado/Evan, Naranjo/Mauricio, Sandoval/Carlos
-
-
ASA VPN: Okta RADIUS → Entra SAML — (NEW 06-09) 5-phase migration plan built. ASA baseline captured (2 tunnel groups: CHLA_CORPORATE_USERS, CHLA_BYOD_USERS). 6 ISE policy screenshots. Tony Sun (ASA), Justin Halbmann (Entra/Okta), Evan (ISE). VPN cert expires 07-28. PDF deliverable ready. Share with team this week.
Tube System Upgrade (NEW — 06-01)
-
Tube System Upgrade — iTrack 3528165. 15x 10" TS stations need MAC addresses added to ISE identity group IoT_Onboard. MACs received from vendor (C8:1A:FE:20:xx:xx series). Station list spans ICU (CTICU, PICU, BMT, NICU, NICCU), ED, Surgery, Trauma, Pharmacy. Vendor contact: John Genest. Rationale: manufacturer no longer supports current system; failure risks delayed/missed patient care.
BMS Controller Segmentation (MIGRATED — 06-09)
-
BMS Controller Segmentation — Full migration from Principia LaTeX to d001. 12 partials, 5 Mermaid diagrams, 4 legacy PDFs, ISE screenshots.
d001 open bms-controller. Completed 2026-06-09.
BMS Device Inventory (NEW — 04-24)
-
BMS Device Inventory — 72 devices discovered across 37 switches (04-24). Profile-driven architecture (Claroty/Medigate). 16 queries built. Phase 0 complete. Next: cross-reference with Visio diagrams, classify by function, begin D2 diagrams. Cleanup: delete 4 orphaned test groups, migrate 4 retire-dACL devices, investigate 3 null-profile devices.
VNC Blocking (NEW — 05-11)
-
VNC Blocking — block and eliminate VNC enterprise-wide. Due mid-June 2026. Phase 0: discovery. January AQL query baseline to incorporate. Cross-reference BMS inventory for VNC-capable devices.
Investigations & Audits
-
Murus Portae (WAF) — Phase 0 discovery in progress. FMC cert expired. d001: DMZ NetScaler WAF investigation, zone map, architecture D2 diagrams (v1+v2 SVGs), FMC REST API reference guide, ops script. FMC API returning zero ACP rules — under investigation.
-
Firewall audit — FMC discovery inventory done (d001: fmc-discovery-2026-04-16). EtherChannel query, prefilter, policy assignments pending.
-
IoT Dr. Kim devices — RECURRING. All 4 MACs validated in IoT_iPSK_VLAN1620_Misc (04-24). v2 validation queries built with 7 deep analysis queries (group flapping, credential leakage, profile drift, NAS tracking, remediation timeline, deny audit, OUI scan). Revalidate — confirm no flapping since 04-24.
-
IoT device validation queries — v2 created with partials architecture, 16 queries across ERS/MnT/DataConnect/FMC. Completed 2026-04-24.
Stale Blockers (carried via carryover tracker)
-
k3s NAT verification — rule 170, 10.42.0.0/16 pod network (origin: 2026-03-09). 92 days. Blocks Wazuh indexer recovery → blocks SIEM visibility. Decide: test or defer to Q3.
-
Strongline Gateway VLAN fix — 8 devices wrong identity group (origin: 2026-03-16). 85 days. David Rukiza assigned — follow up on status.
Administrative
-
PeopleSoft — track time for current week
-
iTrack tickets — close open tickets
-
KQL library — build initial queries in codex + d001
-
Linux Research project — finalize and review
-
Tax filing 2025 (MFJ) — see encrypted case file in
data/d000/personal/for details and action items
P1 — Important
-
MSCHAPv2 action-item tracker — owner/status/next-steps per workstream
-
ISE admin MFA enforcement — recommendation tied to advisory (interim control pending Patch 10)
-
DMZ Migration — external services audit behind NetScaler. Linked to Murus Portae investigation.
-
Vocera/Wyse iTrack RCA — complete root cause report
-
GCC ISE Support — 3/4 nodes restored, PSN-04 deferred
-
Wazuh indexer recovery — blocked by k3s NAT (origin: 2026-03-09)
-
Vocera EAP-TLS Supplicant Fix (origin: 2026-03-12)
-
iPSK Manager HA — blocked by DB replication (Ben Castillo)
-
ISE 3.4 Migration — depends on Patch 10 completion first
-
Git history scrub — murus-portae-output.md + ise-analytics CSVs
-
Encrypt
prep-cmds-2026-04-15.adoc— plaintext committed to git -
ISE MnT Messaging Service — enable UDP syslog delivery (maintenance window needed)
Infrastructure (Personal)
-
Borg backups — test and validate on ALL systems (Razer, P16g, vault-01, bind-01, kvm-01, kvm-02)
-
Borg — verify backup script paths updated from dotfiles-optimus to dots-quantum
-
Borg — create initial archive for ThinkPad P16g if none exists
-
Libvirt VLAN hook debug on both KVMs
-
Te1/0/2 cable replacement and re-test
-
Vault Raft cluster — verify vault-01 rejoined
-
Fix EAP-TLS keyring/secrets issue on Razer workstation
Completed (confirmed — do not delete, archive only)
-
CR-2026-04-15 SRT Research VLAN — submitted to iTrack. Completed 2026-04-15.
-
CAB presentation 4/21 — SRT Research VLAN 233 → CHLA-Research. APPROVED. Completed 2026-04-21.
-
Downtime Computers wireless audit — 45 computers, 16 violating, v3 report delivered. Completed 2026-04-21.
-
Git identity fix — dots-quantum/git/.gitconfig email corrected. Completed 2026-04-21.
-
MSCHAPv2 10:30 meeting — next steps + ACL coordination. Completed 2026-04-17.
Service Requests (SR)
| SR# | Request | Requestor | Opened | Status |
|---|---|---|---|---|
3508542 |
Zoll cards connection issue |
— |
— |
STALE — verify in iTrack |
3508524 |
Disable dot1x on (2) network ports - 5th floor 3250 Wilshire (PXE-boot imaging issues) |
— |
— |
STALE — verify in iTrack (issues persisted after disable) |
3528165 |
Tube System Upgrade — 15 stations, MAC addresses for ISE IoT_Onboard identity group |
Genest, John (vendor contact) |
2026-06-01 |
NEW — MACs received, need ISE onboarding |
Incidents (INC)
| INC# | Priority | Description | Opened | SLA | Status |
|---|---|---|---|---|---|
1911859 |
— |
Strongline Gateways in Miscellaneous Subnet |
— |
— |
STALE — verify in iTrack (related to carryover P0) |
Change Requests - Emergency (ECAB)
| CR# | Description | Opened | Scheduled | Status |
|---|---|---|---|---|
No emergency changes |
Change Requests - Normal
| CR# | Description | Opened | Scheduled | Status |
|---|---|---|---|---|
No normal changes |
Change Requests - Scheduled/Standard
| CR# | Description | Opened | Window | Status |
|---|---|---|---|---|
No scheduled changes |
Change Requests - Root Cause / Post-Incident
| CR# | Description | Related INC | Opened | Status |
|---|---|---|---|---|
100451 |
Vocera Phones and Wyse devices went off network |
— |
— |
STALE — verify in iTrack |
Session Accomplishments (Claude Code)
Day-specific accomplishments here.
Personal
In Progress
| Project | Description | Status | Notes |
|---|---|---|---|
k3s Platform |
Production k3s cluster on kvm-01 |
Active |
Prometheus, Grafana, Wazuh deployed |
Wazuh Archives |
Enable archives indexing in Filebeat |
Active |
PVC fix pending |
kvm-02 Hardware |
Supermicro B deployment |
Active |
Hardware ready, RAM upgrade done |
Planned
| Project | Description | Target | Blocked By |
|---|---|---|---|
Vault HA (3-node) |
vault-02, vault-03 on kvm-02 |
Q2 2026 (slipped from Q1) |
kvm-02 deployment |
k3s HA (3-node) |
Control plane HA |
Q2 2026 (slipped from Q1) |
kvm-02 deployment |
ArgoCD GitOps |
k3s GitOps deployment |
After k3s stable |
— |
MinIO S3 |
Object storage for k3s |
After ArgoCD |
— |
Personal asset management (YAML + CLI + AsciiDoc) |
Q2 2026 |
Schema approved |
Active — Infrastructure
| Task | Details | Priority | Status | Due |
|---|---|---|---|---|
Wazuh agent deployment |
Deploy agents to all infrastructure hosts |
P2 |
Pending |
After archives fix |
k3s Platform |
Production k3s cluster on kvm-01 |
P1 |
In Progress |
— |
Wazuh Archives |
Enable archives indexing in Filebeat, PVC fix |
P1 |
In Progress |
— |
kvm-02 Hardware |
Supermicro B deployment, RAM upgrade done |
P1 |
In Progress |
— |
Active — Security & Encryption
| Task | Details | Priority | Status | Due |
|---|---|---|---|---|
Configure 4th YubiKey |
SSH FIDO2 keys |
P1 |
TODO |
— |
Cold storage M-DISC backup |
age-encrypted archives |
P1 |
TODO |
After YubiKey setup |
Active — Development & Tools
| Task | Details | Priority | Status | Due |
|---|---|---|---|---|
netapi Commercialization |
Go CLI rewrite with Cobra-style argument discovery, package for distribution |
P0 |
Active |
— |
Ollama API Service |
FastAPI (17 endpoints), productize — config audit, doc tools, runbook gen |
P0 |
Active |
— |
Shell functions (fe, fec, fef) |
File hunting helpers |
P3 |
TODO |
— |
Active — Documentation
| Task | Details | Priority | Status | Due |
|---|---|---|---|---|
D2 Catppuccin Mocha styling |
domus-* spoke repos (177 files total) |
P3 |
In Progress |
— |
Active — Financial
| Task | Details | Priority | Status | Due |
|---|---|---|---|---|
Amazon order history import |
Download CSV from Privacy Central → parse with awk → populate subscriptions tracker |
P1 |
Waiting |
Pending Amazon data export (requested 2026-04-04) |
Active — Education
| Task | Details | Priority | Status | Due |
|---|---|---|---|---|
No active education tasks — see education trackers |
Active — Personal & Life Admin
| Task | Details | Priority | Status | Due |
|---|---|---|---|---|
ThinkPad T16g Setup |
Arch install, stow dotfiles, Ollama stack, netapi dev env |
P0 |
Pending |
— |
P50 Arch to Ubuntu migration |
P2 |
In Progress |
— |
|
X1 Carbon Ubuntu installs |
2 laptops, LUKS encryption |
P2 |
In Progress |
— |
P50 Steam Test |
Test Flatpak Steam + apt cleanup of broken i386 packages |
P3 |
Pending |
— |
Documentation Sites
-
docs.domusdigitalis.dev - Private documentation hub
-
docs.architectus.dev - Public portfolio site
Education
Claude Code Mastery
| Resource | Details | Progress | Status |
|---|---|---|---|
Claude Code Full Course (4 hrs) |
Nick Saraev - YouTube comprehensive course |
26:49 / 4:00:00 |
IN PROGRESS |
Claude Code Certification |
Anthropic official certification (newly released) |
Not started |
GOAL |
Active Tracks (Focus)
-
Don Quijote - Primera Parte
Skills Mastery (Critical)
-
Regex Mastery - 10-module curriculum
-
AsciiDoc Docs - Documentation format
-
Antora Docs - Documentation pipeline
Certification Deadlines
-
CISSP - July 12, 2026 (10-week plan active — Week 1)
-
RHCSA 9 - Q3 2026 (after CISSP)
-
LPIC-1 - Renewal required (blocks LPIC-2)
Spanish C1 Certification Goals
| Certification | Provider | Target | Status | Strategy |
|---|---|---|---|---|
Instituto Cervantes / UNAM / Salamanca |
Q2 2026 |
ACTIVE |
Computer-based, faster results - take FIRST |
|
Q3/Q4 2026 |
PLANNED |
After SIELE success, harder exam |
||
2027 |
FUTURE |
Mastery level - requires extensive immersion |
| SIELE is computer-adaptive, results in 3 weeks. DELE is paper-based, results in 3-4 months. Do SIELE first to validate readiness. |
Don Quijote Writing Practice - DELE C1/C2 Initiative
Method:
-
Read chapter in original Spanish
-
Write personal analysis/understanding en espanol
-
AI review for grammar, vocabulary, register
-
Build comprehensive understanding of literary elements
Today’s Study
-
Focus: CISSP (41 days to July 12 exam — schedule exam today 06-01), MSCHAPv2 migration wrap-up
-
Secondary: RHCSA curriculum, Spanish SIELE C1
-
CISSP — Security & Risk Management (continuing). Schedule exam this afternoon.
-
RHCSA — continue curriculum phase
-
Spanish — Don Quijote reading + analysis (DTLA study day)
-
MSCHAPv2 — migration window closed 05-30, review final report
Regex Training (CRITICAL)
-
Status: 52 days carried over (since 2026-03-16)
-
Priority: After PeopleSoft, before Quijote
-
Session: Character classes, word boundaries
Infrastructure
Documentation Sites
| Site | URL | Status | Actions Needed |
|---|---|---|---|
Domus Digitalis |
Active |
Validate, harden, improve |
|
Architectus |
Active |
Public portfolio site - maintain |
HA Deployment Status
| System | Description | Status | Notes |
|---|---|---|---|
VyOS HA |
vyos-01 (kvm-01) + vyos-02 (kvm-02) with VRRP VIP |
✅ COMPLETE |
2026-03-07 - pfSense decommissioned |
BIND DNS HA |
bind-01 (kvm-01) + bind-02 (kvm-02) with AXFR |
✅ COMPLETE |
Zone transfer operational |
Vault HA |
Raft cluster (vault-01/02/03) |
✅ COMPLETE |
Integrated with PKI |
Keycloak Rebuild |
keycloak-01 corrupted, rebuild from scratch |
🔄 NEXT |
Priority P3 - SSO broken |
FreeIPA HA |
ipa-02 replica planned |
📋 PLANNED |
Linux auth redundancy |
AD DC HA |
home-dc02 replication |
📋 PLANNED |
Windows auth redundancy |
iPSK Manager HA |
ipsk-mgr-02 with MySQL replication |
📋 PLANNED |
PSK portal redundancy |
ISE HA |
PAN HA (ise-01 reconfigure) |
⏳ DEFERRED |
Wait until ise-02 stable |
ISE 3.5 Migration |
Upgrade path: 3.2p9 → 3.4 (P1) → 3.5 (target) |
📋 PLANNED |
After 3.4 Migration completes (Q2 2026) |
Single Points of Failure (CRITICAL)
| These systems have NO redundancy - outage impacts production. |
| System | Impact if Down | Mitigation |
|---|---|---|
ISE (ise-02) |
All 802.1X stops - wired and wireless auth fails |
ise-01 reconfiguration deferred until ise-02 stable |
Keycloak (keycloak-01) |
SAML/OIDC SSO broken (ISE admin, Grafana, etc.) |
NEXT PRIORITY - Rebuild runbook |
FreeIPA (ipa-01) |
Linux auth, sudo rules, HBAC fails |
ipa-02 replica planned |
AD DC (home-dc01) |
Windows auth, Kerberos, GPO fails |
home-dc02 replica planned |
iPSK Manager |
Self-service PSK portal unavailable |
ipsk-mgr-02 with MySQL replication planned |
Validation Tasks
| Task | Details | Status |
|---|---|---|
docs.domusdigitalis.dev validation |
Test all cross-references, search, rendering |
TODO |
docs.domusdigitalis.dev hardening |
HTTPS, CSP headers, security review |
TODO |
docs.architectus.dev validation |
Public site content review |
TODO |
Hub-spoke sync verification |
All components building correctly |
Ongoing |
Quick Commands
Git & GitHub CLI
gh repo create <name> --private --source . --remote origin --push
gh repo clone EvanusModestus/PowerShell ~/atelier/_projects/work/PowerShell
gh repo clone defaults to SSH. If key is passphrase-protected, load agent first: eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_ed25519_github
|
for repo in ~/atelier/_bibliotheca/domus-*/ ~/atelier/_projects/personal/domus-*/; do
[ -d "$repo/.git" ] || continue
name=$(basename "$repo")
git -C "$repo" log --since="2026-04-06" --until="2026-04-07" --format="%h %aI %s" 2>/dev/null |
awk -v r="$name" '{print r, $0}'
done
git log --oneline -- $(find . -name "*.adoc" -type f -newermt "$(date +%F)")
git restore --staged data/d001/api/ise-dataconnect/output/output-2026-04-24
Safe — removes from staging area only. Working tree is untouched. Use when you accidentally git add a plaintext or output file.
gh CLI — repo discovery and filtering
gh repo list --limit 100 --json name,description \
| jq -r '.[] | select(.name | test("domus|antora|asciidoc"; "i")) | "\(.name)\t\(.description)"'
gh repo list --limit 100 --json name,description,updatedAt \
| jq -r 'sort_by(.updatedAt) | reverse | .[:20] | .[] | "\(.updatedAt[:10])\t\(.name)\t\(.description)"'
gh repo list --limit 100 --json name,diskUsage \
| jq -r '.[] | "\(.diskUsage)\t\(.name)"' | sort -rn | head -10
gh repo clone EvanusModestus/<repo-name> ~/atelier/_bibliotheca/<repo-name>
find & grep
find . -name "*.adoc" -type f -newermt "$(date +%F)" | sort
-mtime 0 means "last 24 hours", not "today". -newermt "$(date +%F)" compares against midnight — exact.
|
find . -iname "*mschap*" -type f | sort
find . -type f \( -iname "*ise*" -o -iname "*mschap*" \) | sort
find . -type f -iregex '.*\(ise\|mschap\).*'
find . -type f -iname "*meeting*" \
-not -path "*/node_modules/*" \
-not -path "*/.git/*" \
-not -path "*/build/*"
find .drafts -type f -printf '%T@ %Tc %p\n' | sort -rn | awk '{$1="";print}' | head -3
grep -rl "pattern" . --include="*.adoc" # file count (which files)
grep -rn "pattern" . --include="*.adoc" # line matches (every occurrence)
grep -rc "pattern" . --include="*.adoc" | grep -v ':0$' # match count per file
grep -rn -E 'git init|gh repo create' docs/ --include='*.adoc' -B2 -A2
Search codex by content — which files contain a command?
find docs/modules/ROOT/examples/codex/powershell -type f -name "*.adoc" \
-exec grep -l 'Get-Process\|Start-Process\|pipeline\|Where-Object' {} \;
Pattern: find -exec grep -l returns only filenames with matches — like grep -rl but with find’s `-type f -name filtering. Use \| for OR in grep basic regex. Swap the pattern for any cmdlet or keyword to locate coverage across the codex.
find docs/modules/ROOT -name "powershell" -type d \
-exec sh -c 'echo "$1: $(find "$1" -type f | wc -l) files"' _ {} \;
for f in $(find docs/modules/ROOT/examples/codex/powershell -name "*.adoc" -type f); do
base=$(basename "$f")
dir_parent=$(basename $(dirname "$f"))
grep -rq "$dir_parent/$base" docs/modules/ROOT/pages/codex/powershell/ \
docs/modules/ROOT/examples/codex/powershell/*.adoc 2>/dev/null \
|| echo "ORPHAN: $f"
done
find → grep → open in nvim
nvim $(find -path '*oauth*' -name '*.adoc' -type f \
-exec grep -l 'timeout\|expire\|reconfig\|token' {} \;)
Command substitution $(…) feeds all matches as arguments to nvim — opens every hit as a buffer. :bn/:bp to cycle, :ls to list. One file? Opens directly. Five files? All loaded, ready to navigate.
nvim $(find docs/modules/ROOT -name '*.adoc' -type f \
-exec grep -l 'token.*expire\|oauth.*refresh' {} \;)
find -path '*oauth*' -name '*.adoc' -type f \
-exec grep -l 'timeout\|expire' {} \; \
-exec nvim {} \;
Trailing \| in grep patterns matches empty string — every file matches. Always end with a term, not a pipe: 'timeout\|expire\|token' not 'timeout\|expire\|token\|'.
|
Trace Antora partial inclusion chains
grep -rl 'commands/shell' docs/modules/ROOT/partials/
grep -rl 'quick-commands' docs/modules/ROOT | wc -l
file="commands/shell"
grep -rl "$file" docs/modules/ROOT/partials/ | while read f; do
parent=$(basename "$f" .adoc)
echo "$file -> $parent"
grep -rl "$parent" docs/modules/ROOT/pages/ | while read p; do
echo " -> $(basename "$p")"
done
done
Pattern: grep -rl finds which files contain the string. Chain two passes — first finds the assembler partial, second finds every page that includes it. Works for any partial in the Antora include hierarchy.
Multi-pattern file search — worklog partial discovery
find docs/modules/ROOT -name "*urgent.adoc*" -type f
find docs/modules/ROOT -name "*morning.adoc*" -type f
find docs/modules/ROOT -type f -regextype posix-extended \
-regex '.*(urgent|morning|work-chla|personal|education|infrastructure|quick-commands|related)\.adoc' \
| sort
Pattern: -regextype posix-extended enables | alternation without escaping. One process, one sort — versus 8 separate finds. The sort deduplicates visually and groups by path.
find docs/modules/ROOT -type f -name "*.adoc" \
| grep -E 'urgent|morning|work-chla|personal|education|infrastructure|quick-commands|related'
Trade-off: the pipeline version is more readable but spawns two processes. The regex version is a single find — faster on large trees, same result.
Cross-repo literary term search — bibliotheca-wide discovery
When searching for a term across the entire _bibliotheca (multiple repos, mixed file types), these patterns escalate from narrow to broad.
grep -rn --include='*.adoc' -c 'sanchuelo' . | grep -v ':0$'
grep -rl --include='*.adoc' -i 'sanchuelo' ~/atelier/_bibliotheca/ | sort
grep -rn --include='*.adoc' -i -B1 -A1 'sanchuelo' ~/atelier/_bibliotheca/domus-captures/
grep -rl -i 'sanchuelo' ~/atelier/_bibliotheca/ --include='*.txt' --include='*.adoc' | sort
find ~/atelier/_bibliotheca/ -type f \( -name '*.adoc' -o -name '*.txt' \) -print0 \
| xargs -0 grep -li 'sanchuelo' | sort
grep -rl -i 'sanchuelo' ~/atelier/_bibliotheca/ --include='*.adoc' --include='*.txt' | xargs nvim
Pattern escalation: #1 confirms the term exists and where. #2 expands to all repos. #3 shows context without opening files. #4 adds plain text sources (Quijote .txt originals). #5 is the safe version for automation. #6 opens everything for editing.
Trade-off: grep -r --include is faster for known file types. find | xargs grep is safer for paths with spaces and more extensible (add -name '*.md' etc.). For literary searches across the bibliotheca, #4 or #5 is usually the right starting point — the source texts are .txt, not .adoc.
Search daily notes — find commands, builds, and patterns across worklogs
Source: 2026-06-22 — searching for build-antora-page invocations and theme usage across partials
# Find files — filenames only
grep -rl 'build-antora-page' docs/modules/ROOT/partials/worklog/
# 3 lines of context around each hit
grep -rn -C3 'build-antora-page' docs/modules/ROOT/partials/worklog/
grep -rPn 'theme\s+(light-cyan|catppuccin|mocha)' docs/modules/ROOT/partials/
find docs/modules/ROOT/partials/worklog/daily-notes -name '*.adoc' \
-exec grep -l 'build-antora-page\|build-adoc\|--theme\|pdf' {} \;
find docs/modules/ROOT/partials/worklog/daily-notes -name '*.adoc' \
-exec awk '/build-antora-page|build-adoc|--theme/{print FILENAME": "$0}' {} \;
find docs/modules/ROOT/partials -name '*.adoc' -exec \
awk '/^\[source,bash\]/{block=1; buf=""} \
block{buf=buf"\n"$0} \
/^----$/ && block>1{if(buf~/build-antora-page/) print FILENAME":"buf; block=0} \
block{block++}' {} \;
The awk state machine: [source,bash] sets block=1 and starts buffering. Each line appends to buf. When the closing ---- arrives (and block>1 to skip the opening fence), check if the buffer contains the target command. If yes, print filename + entire block. Reset. One pass, arbitrary block size, no temp files.
find docs/modules/ROOT/partials/worklog -name '*.adoc' -exec \
sed -n '/\[source,bash\]/,/^----$/{/build-antora-page/p}' {} +
grep -rn 'build-antora-page\|build-adoc' data/ --include='*.adoc'
grep -rn 'build-antora-page' docs/modules/ROOT/partials/worklog/daily-notes/ \
| awk -F: '{print $1, $3}' | sort
Pattern escalation: grep -rl → "where is it". grep -rn -C3 → "what’s around it". find -exec awk → "extract the structured block". sed address ranges → "print between delimiters". Each tool has a different affordance — grep finds, awk extracts structure, sed filters ranges, find -exec scales across trees.
Email thread analysis — extract people, dates, commitments, silence
grep -P '(@\w+|^From:.*<)' comms.adoc
grep -nP '\d{1,2}/\d{1,2}/\d{2,4}|20\d{2}-\d{2}-\d{2}' comms.adoc
grep -niP '(I can |I will |I.ll |we will |we.ll )' comms.adoc
grep -niP '(\?|need to confirm|need to validate|TBD|pending)' comms.adoc
comm — set difference (who hasn’t replied)
# All recipients
grep -oP '<\K[^>]+' comms.adoc | sort -u > /tmp/all-recipients
# All senders
grep -P '^From:' comms.adoc | grep -oP '<\K[^>]+' | sort -u > /tmp/replied
# Who's silent — follow-up targets
comm -23 /tmp/all-recipients /tmp/replied
comm -23 outputs lines only in file 1 (recipients not in senders). Requires sorted input. grep -oP '<\K[^>]+' uses PCRE lookbehind — match < but don’t include it, capture until >.
Sort find results by modification time (newest first)
find discovers files but has no sort. Chain -printf with sort to order by mtime.
awk '{print $2}' truncates filenames with spaces — Familia Romana_ Lingva… becomes Familia. Always use the null-safe or sub() variants below for real data.
|
# Sort by mtime, strip epoch prefix — handles spaces in filenames
find ~/Downloads -maxdepth 1 -name '*.pdf' -printf '%T@ %p\n' | sort -rn | awk '{sub(/^[^ ]+ /,""); print}'
sub(/[ ]+ /,"") removes everything up to and including the first space (the epoch). {print $2} would split on every space — fatal for Familia Romana_ Lingva Latina.
# ISO 8601 timestamps — readable and lexicographically sortable
find ~/Downloads -maxdepth 1 -name '*.pdf' -printf '%T+ %p\n' | sort -r | head -20
%T+ renders YYYY-MM-DD+HH:MM:SS — no epoch math needed, still sorts correctly as text.
# Null-delimited: survives any filename (newlines, quotes, unicode)
find ~/Downloads -maxdepth 1 -name '*.pdf' -printf '%T@\t%p\0' | sort -zrn | awk -v RS='\0' -F'\t' '{print $2}'
-printf '%T@\t%p\0' — tab separates epoch from path, null terminates. sort -z sorts null-delimited records. awk -v RS='\0' -F'\t' reads null-terminated, splits on tab — $2 is now the full path regardless of spaces.
# GNU stat equivalent — works where -printf is unavailable
find ~/Downloads -maxdepth 1 -name '*latin*' -exec stat --format='%Y %n' {} + | sort -rn | awk '{sub(/^[^ ]+ /,""); print}'
-exec … {} + batches all files into one stat call (faster than \;). On macOS, use stat -f '%m %N' instead of --format='%Y %n'.
File intelligence — size, type, duplicates, age
Beyond finding files — interrogating them.
# Size in bytes (-printf %s), human-readable via numfmt
find ~/Downloads -type f -printf '%s\t%p\n' | sort -rn | head -10 | numfmt --to=iec --field=1
numfmt --to=iec --field=1 converts the first field from bytes to K/M/G. sort -rn on raw bytes is exact — ls -lhS rounds and sometimes mis-sorts.
# Files sharing a byte count — likely duplicates (confirm with md5sum)
find ~/Downloads -type f -printf '%s %p\n' | awk '{seen[$1]++; files[$1]=files[$1] "\n " $0} END {for (s in seen) if (seen[s]>1) print files[s]}'
# md5sum only files with duplicate sizes (two-pass: fast then precise)
find ~/Downloads -type f -printf '%s\n' | sort | uniq -d | while read -r size; do
find ~/Downloads -type f -size "${size}c" -exec md5sum {} +
done | sort | uniq -w32 -D
Two-pass: first find duplicate sizes (cheap), then md5sum only those (expensive). uniq -w32 -D compares first 32 chars (the hash) and prints all duplicates.
# Count files by MIME type (not extension — extensions lie)
find ~/Downloads -type f -exec file --mime-type -b {} + | sort | uniq -c | sort -rn
file --mime-type -b reports actual content type. -b suppresses filename. A .pdf that’s really text/html is a failed download.
# Files not accessed in 30 days — candidates for cleanup
find ~/Downloads -maxdepth 1 -type f -atime +30 -printf '%A+ %s\t%p\n' | sort | numfmt --to=iec --field=2
-atime 30` = access time older than 30 days. `-printf '%A' shows last access. Useful for Downloads cleanup without deleting something you just renamed.
# Which subdirectories consume the most space?
find . -maxdepth 1 -type d -exec du -sh {} + 2>/dev/null | sort -rh | head -20
Batch operations — rename, move, transform
# Dry run — show what would change (remove echo to execute)
find ~/Downloads -maxdepth 1 -type f -name '* *' -print0 | while IFS= read -r -d '' f; do
dir=$(dirname "$f")
base=$(basename "$f" | tr ' ' '-' | tr '[:upper:]' '[:lower:]')
echo mv "$f" "$dir/$base"
done
IFS= read -r -d '' — the holy trinity for null-safe filename reading. IFS= prevents whitespace trimming. -r prevents backslash interpretation. -d '' reads until null.
# Sort Downloads chaos into folders by type
find ~/Downloads -maxdepth 1 -type f -print0 | while IFS= read -r -d '' f; do
ext="${f##*.}"
case "$ext" in
pdf|epub) dest="books" ;;
jpg|png|svg) dest="images" ;;
sh|py|rb) dest="scripts" ;;
*) dest="other" ;;
esac
mkdir -p ~/Downloads/"$dest"
echo mv "$f" ~/Downloads/"$dest"/
done
${f##.} — parameter expansion: strip longest match of . from front, leaving only the extension. No basename or awk needed.
# Convert all epubs in a directory to asciidoc via pandoc
find . -name '*.epub' -type f -exec sh -c '
for epub; do
adoc="${epub%.epub}.adoc"
pandoc -f epub -t asciidoc "$epub" -o "$adoc" \
&& printf " → %s (%s lines)\n" "$adoc" "$(wc -l < "$adoc")" \
|| printf " ✗ failed: %s\n" "$epub"
done
' _ {} +
-exec sh -c '…' _ {} + — batch mode. _ fills $0 (script name, discarded). All matched files become $1, $2, … iterated by for epub. One sh invocation, not one per file.
xargs power patterns
# Checksum all PDFs in parallel (4 processes)
find ~/Downloads -name '*.pdf' -print0 | xargs -0 -P4 md5sum
-P4 runs 4 md5sum processes simultaneously. -print0 | xargs -0 is the null-safe pipeline — no filename can break it.
# Compare files pairwise with diff
find . -name '*.adoc' -print0 | xargs -0 -n2 diff --brief
-n2 feeds two arguments per invocation. Useful for pairwise comparisons, copy operations (-n2 with cp), or any command taking exactly two args.
# Backup every config file: cp <file> <file>.bak
find /etc -maxdepth 1 -name '*.conf' -print0 | xargs -0 -I{} cp {} {}.bak
-I{} replaces {} with each filename. Slower than + batching (one cp per file) but necessary when the filename must appear in a specific position.
Process substitution — diff without temp files
# What files exist in study-A but not study-B?
diff <(find data/d000/education/ciceron-study -type f -name '*.adoc' | sort) \
<(find data/d000/education/latin-study -type f -name '*.adoc' | sort)
<(cmd) creates a file descriptor from command output. diff sees two "files" — no temp files created, no cleanup needed.
# Side-by-side: file type census of two directories
paste <(find dir1 -type f -exec file --mime-type -b {} + | sort | uniq -c | sort -rn) \
<(find dir2 -type f -exec file --mime-type -b {} + | sort | uniq -c | sort -rn)
awk, sed, jq
awk — field extraction
awk '{print $2}' file.txt
awk -F: '{print $1, $3}' /etc/passwd
awk '/\[source,json\]/{getline; if ($0 ~ /^----/) {p=1; next}} p && /^----/{p=0; next} p' file.adoc
awk '{printf "%-30s %s\n", $1, $2}' file.txt
sed — stream editing
# Before
awk 'NR==73' /etc/ssh/sshd_config
# Change
sed -i '73s/#GSSAPIAuthentication no/GSSAPIAuthentication yes/' /etc/ssh/sshd_config
# After
awk 'NR==73' /etc/ssh/sshd_config
sed -n '10,20p' file.txt
sed — line-targeted replacement (verify-before / change / verify-after)
# 1. LOCATE: find the line number
grep -n 'adoc-pdf' zsh/.zshrc
# 2. VALIDATE: read the exact line before changing
awk 'NR==1760' zsh/.zshrc
# 3. CHANGE: target by line number — only hits that line
sed -i '1760s/alias adoc-pdf=/alias build-adoc=/' zsh/.zshrc
# 4. VERIFY: confirm change AND check for collateral
grep -n 'build-adoc\|adoc-pdf' zsh/.zshrc
Without the line number prefix (1760s/), sed replaces every match in the file — a shotgun. With it, surgical. The line number comes from grep -n.
awk 'NR==1218 || NR==1760' zsh/.zshrc
# grep found the error at line 44164 — read 50 lines of context
awk 'NR>=44160 && NR<=44210' session-dump.adoc
No head | tail chains. No sed -n '44160,44210p'. One awk, two numbers.
grep -oP with \K — value extraction from key-value logs
# ISE syslog — extract failure reasons
grep -oP 'FailureReason=\K[^,;]+' /var/log/syslog | sort | uniq -c | sort -rn
# ISE — extract MAC addresses
grep -oP 'Calling-Station-ID=\K[0-9A-Fa-f:.-]+' /var/log/syslog | sort -u
# ISE — extract NAS IPs
grep -oP 'NAS-IP-Address=\K[0-9.]+' /var/log/syslog | sort -u
# ISE — extract device names
grep -oP 'NetworkDeviceName=\K[^,;]+' /var/log/syslog | sort -u
\K resets the match start — everything before \K is required context but excluded from output. [^,;]+ captures until the next delimiter. Pipe to sort -u for unique, sort | uniq -c | sort -rn for counted frequency.
# Generic form — works for any key=value log format
grep -oP 'FIELD_NAME=\K[^,;]+' logfile | sort | uniq -c | sort -rn | head -20
jq — JSON processing
curl -s localhost:8080/stats | jq '.stats.total_files'
jq '.results[] | select(.category == "standards")' response.json
jq -r '.[] | [.title, .path] | @tsv' response.json | column -t -s $'\t'
gh api "repos/EvanusModestus/domus-captures/commits?path=docs/&per_page=10" |
jq -r '.[] | "\(.commit.author.date[:10]) \(.sha[:7]) \(.commit.message | split("\n")[0])"'
Shell Patterns
xargs — when the next command reads arguments, not stdin
| Next command reads… | Use |
|---|---|
stdin ( |
pipe directly |
arguments ( |
|
-I{} placeholdermkdir -p /tmp/adoc-backup-$(date +%F) && \
find . -name "*.adoc" -type f -newermt "$(date +%F)" | \
xargs -I{} cp {} /tmp/adoc-backup-$(date +%F)/
-P4 runs 4 at a timefind .drafts -name "*.adoc" -type f | xargs -P4 -I{} asciidoctor -o /dev/null {}
find . -name "*.adoc" -type f -print0 | xargs -0 wc -l
Process substitution — <(cmd) treats output as a file
diff <(grep '|' partials/trackers/work/adhoc/carryover.adoc | head -20) \
<(git show HEAD~1:partials/trackers/work/adhoc/carryover.adoc | grep '|' | head -20)
diff <(find docs/modules/ROOT/pages/projects/chla/mschapv2-migration -name "*.adoc" -type f | sort) \
<(grep -oP 'mschapv2-migration/[^[]+\.adoc' docs/modules/ROOT/nav.adoc | sort)
Command substitution — embed output as arguments
nvim "$(find data/ -name '*.adoc' -type f -printf '%T@ %p\n' | sort -rn | awk 'NR==1{print $2}')"
wc -l $(find docs/modules/ROOT -path '*mschapv2*' -name '*.adoc' -type f)
Conditional execution — capture, test, act
files=$(find .drafts -name 'in*' -type f) && [ -n "$files" ] && nvim $files
files=$(grep -rl '\[ \]' .drafts/*.adoc) && [ -n "$files" ] && nvim $files
grep -q 'TODO\|FIXME\|\[ \]' "$file" && nvim "$file"
Pattern: $(capture) → [ -n ] tests non-empty → && only proceeds if true.
grep -q is the idempotent guard — run repeatedly, only opens when there’s work.
Decrypt and open — find .age, decrypt, nvim in one shot
files=$(find . -name "*tcp-clock*.age" -type f) && \
[ -n "$files" ] && echo "$files" | xargs -I{} decrypt-file {} && \
nvim $(echo "$files" | sed 's/\.age$//')
Pattern: find .age only (never tries plaintext), sed derives the decrypted path, guard prevents empty nvim. Change the glob to match any project.
tee_clean — color on screen, clean text in file
tee_clean() {
tee >(sed 's/\x1b\[[0-9;]*m//g' > "$1")
}
# Color output on terminal, stripped in file
jq -C '.' data.json | tee_clean output.json
xq -C '.' data.xml | tee_clean output.json
# Wrap a whole block
{
echo "=== Summary ==="
jq -C '.[] | .name' data.json
} | tee_clean summary.txt
The >(cmd) is process substitution — tee writes to stdout AND to the subshell pipe. sed strips ANSI escape sequences (\x1b\[[0-9;]*m) before they hit the file.
Dependency check — verify toolchain in one shot
for cmd in asciidoctor asciidoctor-pdf pandoc rouge d2 mmdc age; do
printf "%-20s %s\n" "$cmd" "$(command -v $cmd >/dev/null 2>&1 && echo 'OK' || echo 'MISSING')"
done
Pattern: command -v checks if binary exists on PATH. >/dev/null 2>&1 suppresses output — we only care about exit code. Swap the tool list for any project’s dependencies.
printf safety — dashes as data, not options
--- as invalid optionprintf '---\n\n'
--- as dataprintf '%s\n\n' '---'
Kill stuck SSH sessions
lsof -i TCP -n -P | awk '/ssh.*ESTABLISHED/ {print $2, $9}'
lsof -i TCP -n -P | awk '/ssh.*kvm-01.*ESTABLISHED/ {print $2}' | sort -u | xargs kill
lsof -i TCP -n -P | awk '/ssh.*ESTABLISHED/ {print $2}' | sort -u | xargs kill
lsof -i TCP -n -P lists all TCP connections. awk filters for SSH + ESTABLISHED, prints only the PID ($2). sort -u deduplicates (multiple file descriptors per process). xargs kill sends SIGTERM to each.
File Descriptors & Redirection
The three file descriptors
| FD | Name | Purpose |
|---|---|---|
0 |
stdin |
input to the command |
1 |
stdout |
normal output (valid results) |
2 |
stderr |
error messages |
Split stdout and stderr into separate files
find / -name "*.conf" 1>results.txt 2>errors.txt
Suppress errors — 2>/dev/null
find / -name "*.conf" 2>/dev/null
Merge stderr into stdout — 2>&1
command 2>&1 | grep "pattern"
This sends both stdout and stderr through the pipe. Without 2>&1, only stdout reaches grep — errors print to the terminal and bypass the pipeline.
Heredoc patterns
cat <<'EOF'
Line 1
Line 2
EOF
git commit -m "$(cat <<'EOF'
feat: add new feature
Multi-line description here.
EOF
)"
API & curl/jq
domus-api — Documentation System REST API
cd ~/atelier/_projects/personal/domus-api && uv run uvicorn domus_api.main:app --host 0.0.0.0 --port 8080
curl -s localhost:8080/ | jq
curl -s 'localhost:8080/search?q=mandiant' | jq
curl -s 'localhost:8080/search?q=mandiant' | jq '.results[] | {path, title, match_count}'
curl -s 'localhost:8080/pages?category=standards' | jq
curl -s localhost:8080/attributes | jq
GitHub API
gh search code "vault seal" --owner EvanusModestus --json repository,path,textMatches |
jq '.[] | {repo: .repository.full_name, file: .path, match: .textMatches[].fragment}'
gh api 'repos/EvanusModestus/domus-captures/git/trees/main?recursive=1' |
jq '[.tree[] | select(.path | endswith(".adoc"))] | length'
Domus Workflows
Read content from terminal (meeting-ready)
bat docs/modules/ROOT/pages/2026/04/WRKLOG-$(date +%Y-%m-%d).adoc
bat docs/modules/ROOT/partials/trackers/work/priorities/current.adoc
bat docs/modules/ROOT/partials/trackers/work/adhoc/carryover.adoc
bat docs/modules/ROOT/partials/projects/mandiant-remediation/summary.adoc
Search and discovery
grep -rl "MSCHAPv2" docs/modules/ROOT/ --include="*.adoc" | sort
grep -rn "pattern" docs/modules/ROOT/partials/codex/ --include="*.adoc" -B1 -A3
ls -1 docs/modules/ROOT/pages/2026/04/WRKLOG-*.adoc
Tracker aging — calculate days from origin
echo $(( ($(date +%s) - $(date -d "2026-03-09" +%s)) / 86400 ))
Encrypted data access (d001)
age --decrypt -i ~/.secrets/.metadata/keys/master.age.key \
data/d001/projects/mandiant-remediation/findings-status-2026-04-16.adoc.age \
| bat --language asciidoc
for d in data/d001/projects/*/; do
total=$(find "$d" -type f | wc -l)
plain=$(find "$d" -type f ! -name '*.age' ! -name 'README.adoc' ! -name '.gitkeep' ! -name '*.py' | wc -l)
printf "%-25s %s files %s plaintext\n" "$(basename "$d")" "$total" "$plain"
done
d000 study builds
for d in p1-cap-03{7,8,9}; do
for f in data/d000/education/quijote-study/notas/$d/*.adoc; do
d000 build "$d/$(basename "$f" .adoc)" html --variant light-cyan
done
done
d000 build p1-cap-038/texto-anotado html --variant light-cyan
d000 build p1-cap-038/texto-anotado pdf --theme light-cyan
for d in p1-cap-03{7,8,9}; do
for f in data/d000/education/quijote-study/notas/$d/*.adoc; do
d000 build "$d/$(basename "$f" .adoc)" pdf --theme light-cyan
done
done
firefox data/d000/education/quijote-study/notas/p1-cap-03{7,8,9}/output/*.html &
firefox data/d000/education/quijote-study/notas/p1-cap-03{7,8,9}/output/*.pdf &
lp data/d000/education/quijote-study/notas/p1-cap-03{7,8,9}/output/*.pdf
d000 build annotated-text pdf --theme light-cyan
d000 build lpl-study/notas/texto-anotado pdf --theme light-cyan
d000 build de-oratore/libro-i/texto-anotado html --variant light-cyan
Available themes
ls ~/atelier/_bibliotheca/domus-asciidoc-build/themes/pdf/ | sed 's/-theme\.yml//'
# base blue burgundy catppuccin creative dark don-quijote green
# learning light-cyan navy operations orange purple reference royal
~/atelier/_bibliotheca/domus-asciidoc-build/docinfo/compose.sh --list
# light dark catppuccin royal light-cyan
ISE & Network Ops
ISE ERS API — endpoint CRUD
export ISE_HOST="{ise-ip}" ISE_USER="admin" ISE_PASS="$(gopass show -o ise/admin)"
curl -sk "https://$ISE_HOST:{ise-ers-port}/ers/config/identitygroup" \
-H "Accept: application/json" -u "$ISE_USER:$ISE_PASS" | jq '.SearchResult.resources[].name'
curl -sk "https://$ISE_HOST:{ise-ers-port}/ers/config/endpoint?filter=mac.EQ.AA:BB:CC:DD:EE:FF" \
-H "Accept: application/json" -u "$ISE_USER:$ISE_PASS" | jq '.SearchResult.total'
Certificate inspection
openssl x509 -in {cert-dir}/client.pem -text -noout | head -30
openssl x509 -in {cert-dir}/client.pem -enddate -noout
Network diagnostics
ss -tlnp | grep -E ':{port-https}|:{port-ssh}|:{port-ldaps}'
nc -zv {ise-ip} {ise-ers-port}
dig {ise-hostname} +short
ISE eval rotation — backup & restore
# SSH to ISE
ssh admin@ise-02.inside.domusdigitalis.dev
# Verify NAS repo
show repository nas-01
# Get encryption key (on workstation)
dsource d000 dev/storage
echo $ISE_BACKUP_KEY
# Run backup
backup pre-rotation-2026-06 repository nas-01 ise-config encryption-key plain <KEY>
ssh admin@ise-02.inside.domusdigitalis.dev
show repository nas-01
configure terminal
repository nas-01
url nfs://10.50.1.70:/volume1/ise_backups
exit
restore <backup-filename> repository nas-01 encryption-key plain <KEY>
VyOS — VRRP & VLAN inspection
show vrrp
show configuration commands | grep vrrp | grep 'address'
show configuration commands | grep 'firewall zone' | grep 'member'
show dhcp server leases
show arp
show interfaces
CUPS printing — validation & setup
command -v lpstat && echo "CUPS present" || echo "CUPS not installed"
lpstat -r # scheduler running?
lpstat -p -d # printers + default
sudo systemctl enable --now cups # start + persist
lpinfo -v # available backends/URIs
lpinfo -m | grep -i <brand> # available drivers
sudo lpadmin -p <name> -v <uri> -m everywhere -E
lpoptions -d <name>
lp file.pdf # default printer
lp -d <name> -o sides=two-sided-long-edge file.pdf
PowerShell (from zsh)
All PowerShell commands run inside pwsh -NoLogo -Command '…' from zsh. Running them bare fails — zsh interprets $, |, () as shell syntax.
|
Process management
pwsh -NoLogo -Command 'Get-Process | Sort-Object WorkingSet64 -Descending |
Select-Object -First 5 ProcessName, Id,
@{N="MB";E={[math]::Round($_.WorkingSet64/1MB)}} | Format-Table'
pwsh -NoLogo -Command 'Get-Process | Where-Object {$_.ProcessName -like "*teams*"} | Stop-Process'
pwsh -NoLogo -Command 'Start-Process "ms-teams"'
Export to JSON (pipe to jq)
pwsh -NoLogo -Command 'Get-Process | Sort-Object WorkingSet64 -Descending |
Select-Object -First 5 ProcessName, Id,
@{N="MB";E={[math]::Round($_.WorkingSet64/1MB)}} | ConvertTo-Json' | jq '.'
Never pipe Format-Table into ConvertTo-Json — it produces layout metadata, not data. Select-Object first, then ConvertTo-Json.
|
Wi-Fi management (netsh)
netsh wlan disconnect interface="Wi-Fi"
netsh wlan show networks mode=bssid
netsh wlan connect name="CHLA-Remote" interface="Wi-Fi"
SSH from PowerShell
ssh evan@modestus-razer.inside.domusdigitalis.dev
WSL ↔ Windows — Cross-Environment Commands
From zsh (WSL) — control Windows
pwsh -NoLogo -Command 'Get-Date'
pwsh -NoLogo -Command "$(cat <<'PS'
$procs = Get-Process | Where-Object { $_.WorkingSet64 -gt 100MB }
$procs | Sort-Object WorkingSet64 -Descending |
Select-Object ProcessName, Id, @{N="MB";E={[math]::Round($_.WorkingSet64/1MB)}} |
Format-Table -AutoSize
PS
)"
# Open in default Windows app
wslview /mnt/c/Users/erosado/Documents/report.pdf
# Open Explorer to current WSL directory
explorer.exe .
# Open specific Windows path
explorer.exe 'C:\Users\erosado\Downloads'
# Pipe anything to Windows clipboard
cat file.txt | clip.exe
# Copy a command's output
pwsh -NoLogo -Command 'Get-TransportRule | Format-List Name, State' | clip.exe
# Windows C: drive is at /mnt/c
ls /mnt/c/Users/erosado/Downloads/
# Copy from Windows to WSL
cp /mnt/c/Users/erosado/Downloads/report.pdf ~/atelier/
# Watch a Windows directory for new files
find /mnt/c/Users/erosado/Downloads -maxdepth 1 -mmin -5 -type f -printf '%T+ %p\n' | sort -r
From PowerShell — control WSL
wsl -e bash -c 'grep -rn "Ghost-Sender" ~/atelier/_bibliotheca/domus-captures/docs/'
$result = wsl -e bash -c 'git -C ~/atelier/_bibliotheca/domus-captures log --oneline -5'
$result
Process Management — Windows Side
pwsh -NoLogo -Command '
Get-Process | Sort-Object WorkingSet64 -Descending |
Select-Object -First 20 ProcessName, Id,
@{N="MB";E={[math]::Round($_.WorkingSet64/1MB)}},
@{N="CPU(s)";E={[math]::Round($_.CPU,1)}},
@{N="Handles";E={$_.HandleCount}} |
Format-Table -AutoSize'
pwsh -NoLogo -Command 'Get-Process | Where-Object { $_.ProcessName -like "*teams*" } |
Select-Object ProcessName, Id, @{N="MB";E={[math]::Round($_.WorkingSet64/1MB)}} |
Format-Table -AutoSize'
pwsh -NoLogo -Command 'Stop-Process -Name "Teams" -Force -ErrorAction SilentlyContinue'
pwsh -NoLogo -Command 'Stop-Process -Id 12345 -Force'
pwsh -NoLogo -Command 'Get-NetTCPConnection -State Listen |
Select-Object LocalAddress, LocalPort, OwningProcess,
@{N="Process";E={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).ProcessName}} |
Sort-Object LocalPort | Format-Table -AutoSize'
pwsh -NoLogo -Command 'Get-NetTCPConnection -LocalPort 8080 -ErrorAction SilentlyContinue |
Select-Object LocalAddress, LocalPort, RemoteAddress, State,
@{N="Process";E={(Get-Process -Id $_.OwningProcess).ProcessName}}'
Services — Windows Side
pwsh -NoLogo -Command 'Get-Service | Where-Object { $_.Status -eq "Running" } |
Sort-Object DisplayName | Format-Table Name, DisplayName, Status -AutoSize'
pwsh -NoLogo -Command 'Get-Service -Name "WinRM" | Format-List Name, DisplayName, Status, StartType'
Restart-Service -Name "WinRM" -Force
System Info — Quick Health from zsh
pwsh -NoLogo -Command '
Write-Host "=== Windows System ===" -ForegroundColor Cyan
Write-Host "Hostname: $env:COMPUTERNAME"
Write-Host "User: $env:USERNAME"
Write-Host "OS: $((Get-CimInstance Win32_OperatingSystem).Caption)"
Write-Host "Uptime: $((Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime)"
Write-Host "RAM: $([math]::Round((Get-CimInstance Win32_OperatingSystem).TotalVisibleMemorySize/1MB))GB total, $([math]::Round((Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory/1MB))GB free"
Write-Host "CPU: $((Get-CimInstance Win32_Processor).Name)"
Write-Host "Disk C: $([math]::Round((Get-PSDrive C).Free/1GB))GB free of $([math]::Round(((Get-PSDrive C).Used + (Get-PSDrive C).Free)/1GB))GB"'
pwsh -NoLogo -Command 'Get-PSDrive -PSProvider FileSystem |
Select-Object Name, @{N="Used(GB)";E={[math]::Round($_.Used/1GB,1)}},
@{N="Free(GB)";E={[math]::Round($_.Free/1GB,1)}},
@{N="Total(GB)";E={[math]::Round(($_.Used+$_.Free)/1GB,1)}} |
Format-Table -AutoSize'
Exchange Online — Connect from zsh
pwsh -NoLogo -Command 'Connect-ExchangeOnline -UserPrincipalName erosado@chla.usc.edu'
MFA prompt opens in the Windows browser. After auth, the session persists in the pwsh process. For multi-command sessions, start pwsh interactively instead of one-shot commands.
|
pwsh -NoLogo
# Then inside pwsh:
# Connect-ExchangeOnline
# Get-TransportRule | Format-List Name, State
# exit
File Transfer Patterns
# WSL → Windows Downloads
cp ~/atelier/_bibliotheca/domus-captures/output/report.pdf /mnt/c/Users/erosado/Downloads/
# Windows → WSL (glob)
cp /mnt/c/Users/erosado/Downloads/*.{png,pdf,jpg} ~/atelier/_staging/
# Bulk move with null safety
find /mnt/c/Users/erosado/Downloads -maxdepth 1 -name '*.pdf' -mmin -60 -print0 |
xargs -0 -I{} cp {} ~/atelier/_staging/
inotifywait -m /mnt/c/Users/erosado/Downloads -e create -e moved_to |
awk '{printf "%s %s\n", strftime("%H:%M:%S"), $3}'
inotifywait requires inotify-tools. Install with sudo pacman -S inotify-tools if not present.
|
Security & Encryption
View encrypted files without writing to disk
age --decrypt -i ~/.secrets/.metadata/keys/master.age.key \
data/d001/projects/mandiant-remediation/findings-status-2026-04-16.adoc.age \
| bat --language asciidoc --file-name "findings-status-2026-04-16.adoc"
Batch re-encrypt — brace expansion + loop
for f in data/d001/projects/mandiant-remediation/{findings-status,guest-acl-update,siem-report}-2026-04-16.adoc; do
rm -f "${f}.age" && echo y | encrypt-file "$f"
done
Always rm -f the .age first. If you skip it, encrypt-file prompts about overwrite and may only delete the plaintext without re-encrypting.
|
Detect stale plaintext — files needing re-encryption
for f in data/d001/projects/*/*.adoc; do
age="${f}.age"
if [ -f "$f" ] && [ -f "$age" ]; then
pt_mod=$(/usr/bin/stat -c'%Y' "$f")
age_mod=$(/usr/bin/stat -c'%Y' "$age")
[ "$pt_mod" -gt "$age_mod" ] && echo "STALE: $f"
fi
done
Secure delete — shred for sensitive plaintext
shred -u data/d001/projects/mandiant-remediation/man-report.txt
On SSD/NVMe, shred is less effective (wear leveling), but better than rm which only removes the directory entry.
|
Pre-push audit — find all unencrypted project files
find data/d001/projects -type f ! -name '*.age' ! -name 'README.adoc' ! -name '.gitkeep' ! -name '*.py' | sort
System & Infrastructure
PipeWire audio validation
wpctl status # PipeWire status
pactl list sinks short # list audio sinks
pw-play /usr/share/sounds/freedesktop/stereo/bell.oga # test default sink
journalctl -b --grep='sof|cs35l56' --no-pager | tail -20 # kernel audio firmware
cat /proc/asound/cards # ALSA sound cards
gopass — personal document management
gopass-personal-docs # interactive entry creation
gopass-query bills # list recurring bills with totals
gopass-query storage # list storage units with gate codes
gopass-query export bills # export category to JSON
Makefile — daily workflow
make new-day # create today's worklog + update attributes
make serve # build + local server (port 8000)
make # build only
make sync-nav # sync worklog nav entries
make update-index # rebuild monthly index
KVM — VM & ISO management
ssh kvm-01 "sudo virsh list --all"
ssh kvm-02 "sudo virsh list --all"
ssh kvm-01 "ls -lh /mnt/nas/isos/*[Ii][Ss][Ee]* /var/lib/libvirt/images/*[Ii][Ss][Ee]* /mnt/onboard-ssd/isos/*[Ii][Ss][Ee]* 2>/dev/null"
ssh kvm-02 "ls -lh /mnt/nas/isos/*[Ii][Ss][Ee]* /mnt/ssd/libvirt/images/*[Ii][Ss][Ee]* 2>/dev/null"
sudo virsh console <vm-name> # Escape: Ctrl+]
ssh kvm-01 "mount | grep nas; ls /mnt/"
Per-project file dashboard
for d in data/d001/projects/*/; do
total=$(find "$d" -type f | wc -l)
plain=$(find "$d" -type f ! -name '*.age' ! -name 'README.adoc' ! -name '.gitkeep' ! -name '*.py' | wc -l)
echo "$(basename "$d") | ${total} files | ${plain} plaintext"
done
USB-C / Thunderbolt Charging Diagnostics
{
echo "=== Power Supply ==="
cat /sys/class/power_supply/*/status
echo ""
cat /sys/class/power_supply/*/type
echo ""
echo "=== UPower ==="
upower -d | grep -E 'state|percentage|energy-rate|voltage'
echo ""
echo "=== dmesg (typec/thunderbolt/PD) ==="
sudo dmesg | grep -iE 'typec|thunderbolt|ucsi|PD|power.delivery|charging' | tail -20
echo ""
echo "=== Pacman log (kernel/typec) ==="
grep -iE 'thunderbolt|typec|ucsi|^.*upgraded linux ' /var/log/pacman.log | tail -20
} | tee /tmp/INC-$(date +%F)-usbc-charging.txt
Pattern: { } groups commands into a single stdout stream. tee writes to file AND displays on screen. Reusable for any multi-command evidence capture — change the commands inside, keep the structure.
pacman — package inspection
Source: 2026-06-25 — curl error 77 investigation, checking for package upgrades
# Check package version and install date (awk field filter)
pacman -Qi curl | awk '/^Version|^Install Date/'