# Session Log: 2026-03-30

## Session Summary

Major infrastructure session on a fresh Windows 11 install (ACG-5070, formerly CachyOS). Three major accomplishments:

1. **Machine Setup** - Verified and installed all required tools on clean Windows install
2. **SOPS+age Credential Vault** - Built a complete local encrypted credential store, migrated all 1Password credentials, synced to Gitea
3. **ScreenConnect-Syncro Sync** - Built and ran a script to enrich 410 ScreenConnect sessions with company names and device types from Syncro data

---

## 1. Machine Setup (ACG-5070 - Windows 11 Pro)

### Pre-existing
- Node.js v24.14.1, npm 11.11.0
- Git 2.53.0
- Python 3.14.3
- 1Password CLI 2.33.1
- Ollama 0.18.3
- Claude Code 2.1.87
- jq, curl, Windows OpenSSH

### Installed This Session
- **sops** 3.7.3 (`winget install Mozilla.sops`)
- **age** 1.3.1 (`winget install FiloSottile.age`)
- **yq** 4.52.5 (`winget install MikeFarah.yq`)

### Ollama Models Pulled to D:\OllamaModels
- qwen3:14b (9.3 GB)
- codestral:22b (12 GB)
- nomic-embed-text (274 MB)

Environment variable `OLLAMA_MODELS=D:\OllamaModels` was already set.

### Still Missing
- gh (GitHub CLI)
- Global git config (only set in vault repo: Mike Swanson / mike@azcomputerguru.com)
- Hostname not yet set (will be ACG-5070)

### Machine Context
- CachyOS is gone -- this machine (ASUS laptop, Arrow Lake-S + RTX 5070 Ti) is now Windows 11 only
- Other machines: GURU-BEAST-ROG (Windows), Mikes-MacBook-Air (macOS) -- both need vault setup

---

## 2. SOPS+age Credential Vault

### Architecture
- **Dedicated Gitea repo**: git.azcomputerguru.com/azcomputerguru/vault (private)
- **Local path**: D:\vault
- **Encryption**: SOPS + age (AES-256), metadata stays plaintext for searchability
- **Selective encryption**: Only `credentials`, `notes`, `password`, `secret`, `api_key`, `token`, `pre_shared_key`, `content` fields are encrypted (via `encrypted_regex` in .sops.yaml)

### age Key
- **Public key**: age1qz7ct84m50u06h97artqddkj3c8se2yu4nxu59clq8rhj945jc0s5excpr
- **Private key location (Windows)**: %APPDATA%\sops\age\keys.txt AND ~/.config/sops/age/keys.txt
- **1Password backup**: "age Key - ACG-5070 (Windows)" in Infrastructure vault

### Credentials
- age private key: AGE-SECRET-KEY-1DE3V6V0ZLLZ45A7GA77M79CTN4LZQMTRCURP8VRGNLV6T2FSZEEQXUW2EU

### Vault Structure (59 encrypted files)
```
vault/
  .sops.yaml                     # Encryption config
  .gitignore
  .githooks/pre-commit           # Blocks unencrypted commits
  keys/recipients.txt            # Public keys (ACG-5070 active, Beast+Mac pending)
  scripts/vault.sh               # CLI wrapper (search, get, get-field, edit, add, list, rotate)
  infrastructure/                # 12 files (servers, network, OpenClaw)
  clients/                       # 25 files (Dataforth 10, VWP 4, Khalsa 3, etc.)
  services/                      # 5 files (Gitea, NPM, Cloudflare, Seafile, Matomo)
  projects/                      # 10 files (ClaudeTools 3, GuruRMM 6, GuruConnect 1)
  msp-tools/                     # 6 files (Syncro, Autotask, CIPP, Graph API, Google, ScreenConnect)
```

### Key Commands
```bash
# Search (no decryption needed)
bash D:/vault/scripts/vault.sh search "172.16.3.30"

# Get specific field
bash D:/vault/scripts/vault.sh get-field infrastructure/gururmm-server.sops.yaml credentials.password

# Full decrypt
bash D:/vault/scripts/vault.sh get services/gitea.sops.yaml

# List all entries
bash D:/vault/scripts/vault.sh list
```

### Migration Process
1. Exported all 1Password data via .1pux export (manual from 1Password app)
2. Agent parsed export.data JSON, created YAML files per item, encrypted with SOPS
3. Skipped Sorting vault (1776 duplicate items) and decommissioned items
4. All plaintext temp files deleted after migration

### CLAUDE.md Updated
- Credential access section now references SOPS vault as primary, 1Password as fallback
- New machine setup instructions for vault (install sops+age+yq, generate key, clone, rotate)

### Git
- Repo created on Gitea: azcomputerguru/vault (private)
- Git identity set (vault repo only): Mike Swanson / mike@azcomputerguru.com
- Two commits pushed:
  1. Initial vault: 59 SOPS+age encrypted credential files
  2. Add pre-commit hook to block unencrypted credential files

---

## 3. ScreenConnect-Syncro Sync

### Goal
Enrich generic ScreenConnect sessions (installed via Syncro's prebuilt installer) with proper company names, device types from Syncro asset data.

### ScreenConnect RESTful API Setup
- **URL**: https://computerguru.screenconnect.com
- **Extension GUID**: 2d558935-686a-4bd0-9991-07539f5fe749
- **Auth**: CTRLAuthHeader + Origin header required
- **API Secret**: FTnl15dK1uaKCOeFzkO1UnjGqpgtqCA5vRExWeXT38LjAV4vF9W/mYf8GpCyqlAv
- **API User**: acg-sc-api
- **Stored in vault**: msp-tools/screenconnect.sops.yaml

### SC Custom Property Mapping
| SC Field | CP# | What we populate |
|----------|-----|-----------------|
| Company | CP1 | Syncro customer.business_then_name |
| Site | CP2 | (blank - no site data in Syncro) |
| Department | CP3 | (blank) |
| Device Type | CP4 | Syncro form_factor (Laptop/Desktop/Virtual Server) |
| Tag | CP5 | "Syncro-Matched" or "Syncro-Deploy" or "Manual" |
| CP6-8 | | (blank) |

### SC API Endpoints Used
- `GetSessionDetailsBySessionID` (GET) - read session
- `GetSessionsByName` (GET) - search by name
- `UpdateSessionCustomProperties` (POST) - update custom fields
  - Body format: `["<guid>", ["CP1","CP2","CP3","CP4","CP5","CP6","CP7","CP8"]]`

### Key Discovery: Direct GUID Link
Syncro assets have `properties["ScreenConnect GUID"]` which maps directly to SC session GUIDs. No hostname matching needed.

### Sync Script
- **Path**: D:\claudetools\scripts\sync-sc-from-syncro.js
- **Language**: Node.js (zero npm dependencies)
- **CLI**: `node sync-sc-from-syncro.js [--dry-run] [--force] [--verbose]`
- **Credentials**: Loaded from SOPS vault via vault.sh

### Bug Fix During Run
Node.js `https` module wasn't sending `Content-Length` header, causing SC API to return NullReferenceException. Fixed by adding explicit `Content-Length` via `Buffer.byteLength()`.

### Results
```
Total Syncro assets: 4636
Assets with SC GUID: 690
Already tagged (skipped): 0
Updated: 410
Errors: 280 (stale GUIDs - sessions no longer exist in SC)
```

### Manual Updates
- DF-GAGETRAK (501340ab-7145-428e-a2c0-c86cb3860a53) -> Dataforth Corporation, Tag: "Manual" (not in Syncro)

### SC Deployment Script for Syncro
- **Path**: D:\claudetools\scripts\syncro-deploy-sc.ps1
- **Purpose**: PowerShell script to deploy in Syncro as a policy script
- **What it does**: Downloads SC MSI with company name baked into installer URL, installs silently
- **Checks**: Skips if SC already installed, auto-detects device type from chassis
- **Tags with**: "Syncro-Deploy" in CP5

---

## 4. 1Password Observations

### Rate Limiting
Service account token got rate-limited from an agent making too many parallel requests. Rate limit persisted for 30+ minutes. Desktop app integration worked as fallback but requires biometric per-call.

### Service Account Details
- **Item name**: "Service Account Auth Token: Agentic-RW" (in Infrastructure vault)
- **Token**: ops_eyJzaWduSW5BZGRyZXNzIjoibXkuMXBhc3N3b3JkLmNvbSIs... (stored in vault at infrastructure/1password-service-account.sops.yaml)

### Duplicate Analysis (Started, Not Completed)
- Sorting vault: 1776 items, 258 titles with duplicates
- Worst: microsoftonline.com (76 copies), acghosting.com (58 copies)
- This cleanup is a separate project

---

## 5. Files Created/Modified

### New Files
- D:\vault/ (entire repo - 62+ files)
- D:\claudetools\scripts\sync-sc-from-syncro.js
- D:\claudetools\scripts\syncro-deploy-sc.ps1
- D:\claudetools\.claude\memory\reference_workstation_setup.md (updated from CachyOS to Windows)

### Modified Files
- D:\claudetools\.claude\CLAUDE.md (credential access section updated for SOPS vault)
- D:\claudetools\.claude\memory\MEMORY.md (updated machine reference)

---

## 6. Pending/Next Steps

1. **Set hostname** to ACG-5070
2. **Install gh** (GitHub CLI): `winget install GitHub.cli`
3. **Set global git config** (currently only in vault repo)
4. **Vault setup on GURU-BEAST-ROG**: install sops+age+yq, generate age key, clone vault, add key to recipients.txt, run rotate
5. **Vault setup on Mac**: same as above
6. **1Password Sorting vault cleanup**: dedup 1776 items (separate project)
7. **Commit SC sync scripts** to ClaudeTools repo
8. **Deploy syncro-deploy-sc.ps1** via Syncro policy to cover ~3946 assets without SC
9. **SC sessions with no Syncro match**: ~280 stale GUIDs to clean up in Syncro
10. **Consider scheduled sync**: run sync-sc-from-syncro.js periodically to catch new assets
