Compare commits
86 Commits
6d3582d5dc
...
ad2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aed04e8ca4 | ||
|
|
88dc431cfa | ||
|
|
7431bfd52b | ||
|
|
505bc12355 | ||
| 0dbc2f98e0 | |||
|
|
3b3075503f | ||
|
|
77c23635df | ||
|
|
a3d7c01bbb | ||
|
|
c8a4107a51 | ||
|
|
8470e98a8a | ||
|
|
93934b625b | ||
|
|
e426dd8b16 | ||
|
|
b83d34ba50 | ||
|
|
ece3222d3a | ||
|
|
d7d9f72fc6 | ||
| 9011670fce | |||
| 9288f3ba93 | |||
| 5a73b18409 | |||
|
|
823bd935fd | ||
|
|
3dedd0c864 | ||
|
|
c51cdbdabc | ||
| 0ca5b2b73d | |||
| d95251d880 | |||
| 5ca81f8296 | |||
| 80509523c8 | |||
| ad88fc31f0 | |||
| a3a47f2d5e | |||
| 89a862c993 | |||
| 5362dc780a | |||
| cef97725b8 | |||
| 122b87a1d6 | |||
| 395333c85c | |||
| 6d60bf5295 | |||
| bdd070f055 | |||
| a29d00c6b2 | |||
| 37aaa6660b | |||
| 6cc9043b8e | |||
| 826141a319 | |||
| 87f5a9306a | |||
| a1e0442d8b | |||
| a8c8c6b7b6 | |||
| 8a0611d4d1 | |||
| cf2b229be5 | |||
| a706f6a94b | |||
| 604c9d9d4b | |||
| 5cbd49ce24 | |||
| 98ea867d2c | |||
| 481b02ed46 | |||
| fc0d12d3cf | |||
| 7c088e57d8 | |||
| 7c8488ad14 | |||
| c296bb9ea0 | |||
| c3eb709dd5 | |||
| 1b17c8144a | |||
| 68e26379aa | |||
| 649565a868 | |||
| 31e70bc18a | |||
| acea558406 | |||
| 4e84a7f810 | |||
| a2b8332770 | |||
| ee89727662 | |||
| 1adc2ed3a4 | |||
| 2b4ca5a8c6 | |||
| b0af0c5828 | |||
| 0262802047 | |||
| 2e75ee3a52 | |||
| c597213ed3 | |||
| bd74b2a05e | |||
| 1b9973e150 | |||
| 6e892bb674 | |||
| 99e83a2848 | |||
| d320958fa8 | |||
| 068888202c | |||
| 6c2c693e6d | |||
| 78528d545e | |||
| 000ee3da5c | |||
| 470638ff86 | |||
| 1a26eb051a | |||
| c79c81e842 | |||
| c629890e32 | |||
| fa15b03180 | |||
| a1a19f8c00 | |||
| f81872784b | |||
| b2874b4728 | |||
| 92f3dd696f | |||
| 8b6f0bcc96 |
246
.claude/CLAUDE.md
Normal file
246
.claude/CLAUDE.md
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
# ClaudeTools on AD2 (Dataforth Domain Controller)
|
||||||
|
|
||||||
|
## Identity
|
||||||
|
|
||||||
|
This is the AD2 workstation instance of ClaudeTools. This machine is a Windows Server on the Dataforth LAN (192.168.0.6). Your scope is Dataforth-only -- you do not need context about other clients.
|
||||||
|
|
||||||
|
## NO EMOJIS
|
||||||
|
|
||||||
|
Use ASCII markers: [OK], [ERROR], [WARNING], [SUCCESS], [INFO]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Git & Sync
|
||||||
|
|
||||||
|
### Gitea Credentials (no 1Password on this machine)
|
||||||
|
- URL: https://git.azcomputerguru.com
|
||||||
|
- Username: mike@azcomputerguru.com
|
||||||
|
- Password: Gptf*77ttb123!@#-git
|
||||||
|
- URL-encoded password: Gptf%2A77ttb123%21%40%23-git
|
||||||
|
- API Token: 9b1da4b79a38ef782268341d25a4b6880572063f
|
||||||
|
- Remote: https://mike%40azcomputerguru.com:Gptf%2A77ttb123%21%40%23-git@git.azcomputerguru.com/azcomputerguru/claudetools.git
|
||||||
|
|
||||||
|
### Branch: ad2
|
||||||
|
This machine operates on the `ad2` branch. The main workstation merges into main.
|
||||||
|
|
||||||
|
### /save behavior
|
||||||
|
Save session logs to `session-logs/YYYY-MM-DD-session-ad2.md` (note the -ad2 suffix).
|
||||||
|
After saving, commit and push to origin/ad2.
|
||||||
|
|
||||||
|
### /sync behavior
|
||||||
|
```
|
||||||
|
git fetch origin
|
||||||
|
git rebase origin/main
|
||||||
|
git push origin ad2
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dataforth Network
|
||||||
|
|
||||||
|
| Host | IP | Role | Notes |
|
||||||
|
|------|-----|------|-------|
|
||||||
|
| AD1 | 192.168.0.27 | Primary DC | Disk at 90%, C:\Engineering = 787 GB |
|
||||||
|
| **AD2** | **192.168.0.6** | **This machine** | Secondary DC, TestDataDB, file shares |
|
||||||
|
| D2TESTNAS | 192.168.0.9 | SMB1 proxy for DOS | Debian 13, Samba, SSH root/Paper123!@#-nas |
|
||||||
|
| UDM | 192.168.0.254 | Gateway/Router | UniFi Dream Machine |
|
||||||
|
| ESXi-122 | 192.168.0.122 | Hypervisor | ESXi |
|
||||||
|
| ESXi-124 | 192.168.0.124 | Hypervisor | ESXi |
|
||||||
|
| DOS stations | TS-01 to TS-30+ | Test stations | DOS 6.22, QuickBASIC ATE software |
|
||||||
|
|
||||||
|
### Credentials
|
||||||
|
- AD Sysadmin: INTRANET\sysadmin / Paper123!@#
|
||||||
|
- D2TESTNAS SSH: root@192.168.0.9 / Paper123!@#-nas
|
||||||
|
- D2TESTNAS Samba: guest access (no password)
|
||||||
|
- WINS/NPS: 192.168.0.27:1812/1813
|
||||||
|
- M365 Tenant: 7dfa3ce8-c496-4b51-ab8d-bd3dcd78b584
|
||||||
|
- Rsync daemon (NAS): port 873, module "test", user rsync / IQ203s32119
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Local Resources
|
||||||
|
|
||||||
|
| Resource | Path |
|
||||||
|
|----------|------|
|
||||||
|
| TestDataDB app | C:\Shares\testdatadb\ |
|
||||||
|
| Test database | C:\Shares\testdatadb\database\testdata.db (SQLite, 2.2M+ records) |
|
||||||
|
| TestDataDB API | http://localhost:3000 |
|
||||||
|
| Parsers | C:\Shares\testdatadb\parsers\ (multiline.js, csvline.js, shtfile.js, spec-reader.js) |
|
||||||
|
| Templates | C:\Shares\testdatadb\templates\datasheet-exact.js |
|
||||||
|
| Import script | C:\Shares\testdatadb\database\import.js |
|
||||||
|
| Export script | C:\Shares\testdatadb\database\export-datasheets.js |
|
||||||
|
| Stage import | C:\Shares\testdatadb\import-all-stage.js |
|
||||||
|
| NAS share | \\D2TESTNAS\test (mapped as T:) |
|
||||||
|
| Datasheets share | X:\For_Web |
|
||||||
|
| ProdSW (BAT files) | C:\Shares\test\COMMON\ProdSW\ |
|
||||||
|
| Sync script | C:\Shares\test\scripts\Sync-FromNAS.ps1 (bidirectional, 15-min schedule) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## DOS Update System - Batch Files
|
||||||
|
|
||||||
|
### Boot Sequence on DOS Machines
|
||||||
|
```
|
||||||
|
AUTOEXEC.BAT (v4.1)
|
||||||
|
-> STARTNET.BAT (v2.0) -- init network, map T: and X: drives
|
||||||
|
-> ATESYNC.BAT
|
||||||
|
-> CTONW.BAT (v5.0) -- upload test data to network
|
||||||
|
-> CTONWTXT.BAT (v2.3) -- upload C:\STAGE\*.TXT to T:\STAGE\%MACHINE%
|
||||||
|
-> NWTOC.BAT (v5.0) -- download updates from network
|
||||||
|
```
|
||||||
|
|
||||||
|
### Current Production Versions (on AD2 & NAS)
|
||||||
|
| File | Version | Last Update | Purpose |
|
||||||
|
|------|---------|-------------|---------|
|
||||||
|
| AUTOEXEC.BAT | v4.1 | 2026-03-12 | Startup config |
|
||||||
|
| STARTNET.BAT | v2.0 | 2026-01-20 | Network init |
|
||||||
|
| NWTOC.BAT | v5.0 | 2026-03-16 | Download updates from network |
|
||||||
|
| CTONW.BAT | v5.0 | 2026-03-28 | Upload test data (5 steps with echo) |
|
||||||
|
| CTONWTXT.BAT | v2.3 | 2026-03-28 | Upload Stage TXT files (no MD, dirs pre-created) |
|
||||||
|
| CHECKUPD.BAT | v1.3 | 2026-01-20 | Check for updates |
|
||||||
|
| UPDATE.BAT | v2.3 | 2026-01-20 | Full system backup |
|
||||||
|
| STAGE.BAT | v1.0 | Original | Stage system file updates |
|
||||||
|
| DEPLOY.BAT | v1.0 | 2026-01-20 | One-time deployment installer |
|
||||||
|
|
||||||
|
### DOS 6.22 Compatibility Rules
|
||||||
|
- NO `IF NOT` -- unreliable on DOS 6.22. Use positive `IF EXIST` with GOTO
|
||||||
|
- NO `IF /I` (case-insensitive compare)
|
||||||
|
- NO `FOR /F` loops
|
||||||
|
- NO `%COMPUTERNAME%` -- use `%MACHINE%` (set during DEPLOY)
|
||||||
|
- `XCOPY /D` requires date parameter (`/D:mm-dd-yy`)
|
||||||
|
- `MD` fails with error on existing directories -- pre-create dirs server-side
|
||||||
|
- `COPY` without `/Y` hangs on overwrite prompts
|
||||||
|
- All paths UPPERCASE for Samba compatibility
|
||||||
|
- Line endings MUST be CRLF (0D 0A)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Serial Number Encoding (DOS 8.3 filenames)
|
||||||
|
|
||||||
|
QuickBASIC ATE encodes long serial numbers for 8.3 filenames:
|
||||||
|
```
|
||||||
|
First 2 digits replaced with hex letter if serial too long:
|
||||||
|
178236-12 -> H8236-12.TXT (17 -> H, charCode 72 - 55 = 17)
|
||||||
|
10819-1 -> A819-1.TXT (10 -> A, charCode 65 - 55 = 10)
|
||||||
|
|
||||||
|
Decode: letter.charCodeAt(0) - 55 = numeric prefix
|
||||||
|
Only applies when filename starts with [A-Z] followed by digits.
|
||||||
|
|
||||||
|
H-prefix files have decoded SN inside the file (SN: 178236-12)
|
||||||
|
A-prefix files have encoded SN inside the file (SN: A819-1) -- must decode to 10819-1
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Test Datasheet Pipeline
|
||||||
|
|
||||||
|
### 5-Stage Architecture
|
||||||
|
1. **DOS Test Programs** -> Write DAT files to C:\ATE\*LOG\ and TXT to C:\STAGE\
|
||||||
|
2. **Boot Upload** -> CTONW.BAT copies DAT to T:\%MACHINE%\LOGS\, CTONWTXT copies TXT to T:\STAGE\%MACHINE%
|
||||||
|
3. **NAS <-> AD2 Sync** -> Rsync every 15 min (Sync-FromNAS.ps1 scheduled task)
|
||||||
|
4. **TestDataDB Import** -> import.js parses DAT into SQLite; export-datasheets.js generates TXT to X:\For_Web
|
||||||
|
5. **Web Share** -> X:\For_Web\ holds validated datasheets (501K+ files)
|
||||||
|
|
||||||
|
### import-all-stage.js (ready to run)
|
||||||
|
Located at `C:\Shares\testdatadb\import-all-stage.js`. Processes ~8,100 TXT files:
|
||||||
|
- Scans \\D2TESTNAS\test\STAGE\TS-*\*.TXT
|
||||||
|
- Decodes hex-prefix serial numbers
|
||||||
|
- Cross-references testdata.db by (serial_number, model_number)
|
||||||
|
- Inserts missing records as log_type='SHT'
|
||||||
|
- Copies to X:\For_Web\{decoded_serial}.TXT
|
||||||
|
|
||||||
|
```
|
||||||
|
cd C:\Shares\testdatadb
|
||||||
|
node import-all-stage.js
|
||||||
|
```
|
||||||
|
|
||||||
|
### Machine data volumes in STAGE
|
||||||
|
| Machine | Files |
|
||||||
|
|---------|-------|
|
||||||
|
| TS-4L | 3,082 |
|
||||||
|
| TS-4R | 2,741 |
|
||||||
|
| TS-1R | 509 |
|
||||||
|
| TS-8R | 478 |
|
||||||
|
| TS-3R | 435 |
|
||||||
|
| TS-11R | 325 |
|
||||||
|
| TS-8L | 285 |
|
||||||
|
| TS-11L | 248 |
|
||||||
|
| TS-27 | 10 (already imported) |
|
||||||
|
| TS-1L | 1 |
|
||||||
|
|
||||||
|
### Web Share Layout (X:\)
|
||||||
|
- X:\For_Web -- Validated datasheets (production)
|
||||||
|
- X:\For_Web_PDF -- PDF versions (4.7K files)
|
||||||
|
- X:\Test_Datasheets -- Incoming/staging
|
||||||
|
- X:\Bad_Datasheets -- Invalid files (18K)
|
||||||
|
- X:\Datasheets_Log -- Processing logs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Known Issues & Pending Work
|
||||||
|
|
||||||
|
### HIGH PRIORITY
|
||||||
|
1. **Run import-all-stage.js** -- 8,100 TXT files need cross-referencing and ingestion
|
||||||
|
2. **Website Upload Replacement** -- Old ASP.NET endpoints (Uploader.aspx) return 404. Need new approach.
|
||||||
|
3. **7B Series Datasheets** -- ~830K records can't generate datasheets (missing 7BMAIN.DAT spec file). Check ENGR share.
|
||||||
|
4. **Service Permissions** -- testdatadb runs as SYSTEM, causing file permission issues. Change to INTRANET\sysadmin.
|
||||||
|
|
||||||
|
### MEDIUM PRIORITY
|
||||||
|
5. **C2 IP Blocking** -- iptables rules added to UDM for 80.76.49.18 and 45.88.91.99. Need permanent rules in UniFi UI.
|
||||||
|
6. **MFA Enforcement** -- 19/38 users ready. Report-only until April 4, 2026. Monitor registration.
|
||||||
|
7. **Joel Lohr Account** -- Retiring March 31. Disable account post-retirement. Auto-reply set to Dan Center.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Security Incident (2026-03-27)
|
||||||
|
|
||||||
|
**DF-JOEL2 (192.168.0.143) compromised via phishing:**
|
||||||
|
- Joel Lohr clicked phishing link in personal Yahoo email
|
||||||
|
- ScreenConnect C2 installed, "Angel Raya" connected remotely
|
||||||
|
- Two C2 backdoors deployed via PowerShell
|
||||||
|
- C2 IPs: 80.76.49.18, 45.88.91.99 (AS399486, suspended by host)
|
||||||
|
- IC3 Complaint: 1c32ade367084be9acd548f23705736f
|
||||||
|
- ConnectWise Case: 03464184
|
||||||
|
- **Remediation complete:** IPs blocked, 3 rogue clients removed, password reset, sessions revoked
|
||||||
|
- **No lateral movement detected** (32 machines scanned clean)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Key Contacts
|
||||||
|
|
||||||
|
| Person | Email | Role |
|
||||||
|
|--------|-------|------|
|
||||||
|
| John Lehman | jlehman@dataforth.com | Engineering, QB code, test specs |
|
||||||
|
| Dan Center | dcenter@dataforth.com | Operations (replacing Joel) |
|
||||||
|
| Peter Iliya | pIliya@dataforth.com | Applications Engineer |
|
||||||
|
| AJ | dataforthgit@... | Engineering contact |
|
||||||
|
| Ken Hoffman | (unresponsive) | TestDataSheetUploader author |
|
||||||
|
| Georg Haubner | ghaubner@dataforth.com | Has pre-crypto backup on D: drive |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference Commands
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Check BAT files on NAS
|
||||||
|
ssh root@192.168.0.9 'ls -la /data/test/COMMON/ProdSW/'
|
||||||
|
|
||||||
|
# Trigger NAS sync
|
||||||
|
Start-ScheduledTask -TaskName 'Sync-FromNAS'
|
||||||
|
|
||||||
|
# Check sync log
|
||||||
|
Get-Content 'C:\Shares\test\scripts\sync-from-nas.log' -Tail 20
|
||||||
|
|
||||||
|
# Check TestDataDB health
|
||||||
|
curl http://localhost:3000/health
|
||||||
|
|
||||||
|
# Query test records
|
||||||
|
node -e "const db=require('better-sqlite3')('C:\\Shares\\testdatadb\\database\\testdata.db',{readonly:true});console.log(db.prepare('SELECT COUNT(*) as cnt FROM test_records').get())"
|
||||||
|
|
||||||
|
# Check Stage files on NAS
|
||||||
|
ssh root@192.168.0.9 'find /data/test/STAGE -name "*.TXT" | wc -l'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Updated:** 2026-03-29
|
||||||
@@ -1,4 +1,66 @@
|
|||||||
{
|
{
|
||||||
"last_updated": "2026-01-23T00:00:00Z",
|
"last_updated": "2026-03-23T20:10:00Z",
|
||||||
"tasks": []
|
"tasks": [
|
||||||
|
{
|
||||||
|
"id": "win-setup-001",
|
||||||
|
"title": "Windows Machine Setup - Align with Directives",
|
||||||
|
"created": "2026-03-23",
|
||||||
|
"status": "in_progress",
|
||||||
|
"context": "Setting up Windows guru workstation to match ClaudeTools project directives. This session is non-elevated. Elevated session should pick up remaining items.",
|
||||||
|
"completed_items": [
|
||||||
|
"Node.js v24.14.0 installed via winget (PATH: C:\\Program Files\\nodejs)",
|
||||||
|
".mcp.json created at C:\\Users\\guru\\ClaudeTools\\.mcp.json (filesystem + sequential-thinking)",
|
||||||
|
"GrepAI v0.35.0 binary downloaded to C:\\Users\\guru\\ClaudeTools\\grepai.exe"
|
||||||
|
],
|
||||||
|
"remaining_items": [
|
||||||
|
{
|
||||||
|
"step": 1,
|
||||||
|
"item": "Finish Ollama installation",
|
||||||
|
"priority": "HIGH",
|
||||||
|
"details": "winget install was downloading v0.18.2 (1.61GB) but session interrupted ~50%. Run: winget install Ollama.Ollama --accept-package-agreements --accept-source-agreements. Verify with: ollama --version"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 2,
|
||||||
|
"item": "Pull Ollama models",
|
||||||
|
"priority": "HIGH",
|
||||||
|
"depends_on": "step 1",
|
||||||
|
"details": "ollama pull nomic-embed-text && ollama pull qwen3:14b && ollama pull codestral:22b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 3,
|
||||||
|
"item": "Initialize GrepAI index",
|
||||||
|
"priority": "HIGH",
|
||||||
|
"depends_on": "step 2 (needs nomic-embed-text)",
|
||||||
|
"details": "cd C:\\Users\\guru\\ClaudeTools && ./grepai.exe init && ./grepai.exe watch --background"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 4,
|
||||||
|
"item": "Add GrepAI to .mcp.json",
|
||||||
|
"priority": "HIGH",
|
||||||
|
"depends_on": "step 3",
|
||||||
|
"details": "Add to C:\\Users\\guru\\ClaudeTools\\.mcp.json mcpServers section: \"grepai\": { \"command\": \"C:\\\\Users\\\\guru\\\\ClaudeTools\\\\grepai.exe\", \"args\": [\"mcp-serve\"] }"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 5,
|
||||||
|
"item": "Verify MCP servers load",
|
||||||
|
"priority": "MEDIUM",
|
||||||
|
"depends_on": "steps 1-4",
|
||||||
|
"details": "Restart Claude Code and confirm sequential-thinking, filesystem, and grepai MCP servers connect. Node.js is installed but current shell may need PATH refresh."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 6,
|
||||||
|
"item": "Update machine memory record",
|
||||||
|
"priority": "LOW",
|
||||||
|
"depends_on": "all above",
|
||||||
|
"details": "Update .claude/memory/machine_windows_guru_setup_status.md to reflect completed setup. Remove all 'Missing' items, mark as fully aligned."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"notes": [
|
||||||
|
"GitHub MCP server intentionally excluded - project uses Gitea not GitHub",
|
||||||
|
"User said they'll get back on git setup separately",
|
||||||
|
"Node.js may not be in current shell PATH - new terminal needed",
|
||||||
|
"Ollama download was partially through when interrupted"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
59
.claude/agents/deep-explore.md
Normal file
59
.claude/agents/deep-explore.md
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
---
|
||||||
|
name: deep-explore
|
||||||
|
description: Deep codebase exploration using grepai semantic search and call graph tracing. Use this agent for understanding code architecture, finding implementations by intent, analyzing function relationships, and exploring unfamiliar code areas.
|
||||||
|
tools: Read, Grep, Glob, Bash
|
||||||
|
model: inherit
|
||||||
|
---
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
You are a specialized code exploration agent with access to grepai semantic search and call graph tracing.
|
||||||
|
|
||||||
|
### Primary Tools
|
||||||
|
|
||||||
|
#### 1. Semantic Search: `grepai search`
|
||||||
|
|
||||||
|
Use this to find code by intent and meaning:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Use English queries for best results (--compact saves ~80% tokens)
|
||||||
|
grepai search "authentication flow" --json --compact
|
||||||
|
grepai search "error handling middleware" --json --compact
|
||||||
|
grepai search "database connection management" --json --compact
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Call Graph Tracing: `grepai trace`
|
||||||
|
|
||||||
|
Use this to understand function relationships and code flow:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Find all functions that call a symbol
|
||||||
|
grepai trace callers "HandleRequest" --json
|
||||||
|
|
||||||
|
# Find all functions called by a symbol
|
||||||
|
grepai trace callees "ProcessOrder" --json
|
||||||
|
|
||||||
|
# Build complete call graph
|
||||||
|
grepai trace graph "ValidateToken" --depth 3 --json
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `grepai trace` when you need to:
|
||||||
|
- Find all callers of a function
|
||||||
|
- Understand the call hierarchy
|
||||||
|
- Analyze the impact of changes to a function
|
||||||
|
- Map dependencies between components
|
||||||
|
|
||||||
|
### When to use standard tools
|
||||||
|
|
||||||
|
Only fall back to Grep/Glob when:
|
||||||
|
- You need exact text matching (variable names, imports)
|
||||||
|
- grepai is not available or returns errors
|
||||||
|
- You need file path patterns
|
||||||
|
|
||||||
|
### Workflow
|
||||||
|
|
||||||
|
1. Start with `grepai search` to find relevant code semantically
|
||||||
|
2. Use `grepai trace` to understand function relationships and call graphs
|
||||||
|
3. Use `Read` to examine promising files in detail
|
||||||
|
4. Use Grep only for exact string searches if needed
|
||||||
|
5. Synthesize findings into a clear summary
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
# ClaudeTools Project Context
|
|
||||||
|
|
||||||
## Identity: You Are a Coordinator
|
|
||||||
|
|
||||||
You are NOT an executor. You coordinate specialized agents and preserve your context window.
|
|
||||||
|
|
||||||
**Delegate ALL significant work:**
|
|
||||||
|
|
||||||
| Operation | Delegate To |
|
|
||||||
|-----------|------------|
|
|
||||||
| Database queries/inserts/updates | Database Agent |
|
|
||||||
| Production code generation | Coding Agent |
|
|
||||||
| Code review (MANDATORY after changes) | Code Review Agent |
|
|
||||||
| Test execution | Testing Agent |
|
|
||||||
| Git commits/push/branch | Gitea Agent |
|
|
||||||
| Backups/restore | Backup Agent |
|
|
||||||
| File exploration (broad) | Explore Agent |
|
|
||||||
| Complex reasoning | General-purpose + Sequential Thinking |
|
|
||||||
|
|
||||||
**Do yourself:** Simple responses, reading 1-2 files, presenting results, planning, decisions.
|
|
||||||
**Rule:** >500 tokens of work = delegate. Code or database = ALWAYS delegate.
|
|
||||||
|
|
||||||
**DO NOT** query databases directly (no SSH/mysql/curl to API). **DO NOT** write production code. **DO NOT** run tests. **DO NOT** commit/push. Use the appropriate agent.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Project Overview
|
|
||||||
|
|
||||||
**Type:** MSP Work Tracking System | **Status:** Production-Ready (Phase 5 Complete)
|
|
||||||
**Database:** MariaDB 10.6.22 @ 172.16.3.30:3306 | **API:** http://172.16.3.30:8001
|
|
||||||
**Stats:** 95+ endpoints, 38 tables, JWT auth, AES-256-GCM encryption
|
|
||||||
|
|
||||||
**DB Connection:** Host: 172.16.3.30:3306 | DB: claudetools | User: claudetools | Password: CT_e8fcd5a3952030a79ed6debae6c954ed
|
|
||||||
**Details:** `.claude/agents/DATABASE_CONNECTION_INFO.md`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Key Rules
|
|
||||||
|
|
||||||
- **NO EMOJIS** - Use ASCII markers: `[OK]`, `[ERROR]`, `[WARNING]`, `[SUCCESS]`, `[INFO]`
|
|
||||||
- **No hardcoded credentials** - Use encrypted storage
|
|
||||||
- **SSH:** Use system OpenSSH (`C:\Windows\System32\OpenSSH\ssh.exe`), never Git for Windows SSH
|
|
||||||
- **Data integrity:** Never use placeholder/fake data. Check credentials.md or ask user.
|
|
||||||
- **Full coding standards:** `.claude/CODING_GUIDELINES.md` (agents read on-demand, not every session)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Automatic Behaviors
|
|
||||||
|
|
||||||
- **Frontend Design:** Auto-invoke `/frontend-design` skill after ANY UI change (HTML/CSS/JSX/styling)
|
|
||||||
- **Sequential Thinking:** Use for genuine complexity - rejection loops, 3+ critical issues, architectural decisions, multi-step debugging
|
|
||||||
- **Task Management:** Complex work (>3 steps) -> TaskCreate. Persist to `.claude/active-tasks.json`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Context Recovery
|
|
||||||
|
|
||||||
When user references previous work, use `/context` command. Never ask user for info in:
|
|
||||||
- `credentials.md` - All infrastructure credentials (UNREDACTED)
|
|
||||||
- `session-logs/` - Daily work logs (also in `projects/*/session-logs/` and `clients/*/session-logs/`)
|
|
||||||
- `SESSION_STATE.md` - Project history
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Commands & Skills
|
|
||||||
|
|
||||||
| Command | Purpose |
|
|
||||||
|---------|---------|
|
|
||||||
| `/checkpoint` | Dual checkpoint: git commit + database context |
|
|
||||||
| `/save` | Comprehensive session log (credentials, decisions, changes) |
|
|
||||||
| `/context` | Search session logs and credentials.md |
|
|
||||||
| `/sync` | Sync config from Gitea repository |
|
|
||||||
| `/create-spec` | Create app specification for AutoCoder |
|
|
||||||
| `/frontend-design` | Modern frontend design patterns (auto-invoke after UI changes) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## File Placement (Quick Rules)
|
|
||||||
|
|
||||||
- **Dataforth DOS work** -> `projects/dataforth-dos/`
|
|
||||||
- **ClaudeTools API code** -> `api/`, `migrations/` (existing structure)
|
|
||||||
- **Client work** -> `clients/[client-name]/`
|
|
||||||
- **Session logs** -> project or client `session-logs/` subfolder; general -> root `session-logs/`
|
|
||||||
- **Full guide:** `.claude/FILE_PLACEMENT_GUIDE.md` (read when saving files, not every session)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Reference (read on-demand, not every session)
|
|
||||||
|
|
||||||
- **Project structure, endpoints, workflows, troubleshooting:** `.claude/REFERENCE.md`
|
|
||||||
- **Agent definitions:** `.claude/agents/*.md`
|
|
||||||
- **MCP servers:** `MCP_SERVERS.md`
|
|
||||||
- **Coding standards:** `.claude/CODING_GUIDELINES.md`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Last Updated:** 2026-02-17
|
|
||||||
214
.claude/commands/1password.md
Normal file
214
.claude/commands/1password.md
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
---
|
||||||
|
name: 1password
|
||||||
|
description: >
|
||||||
|
Integrate 1Password secrets management into Claude Code workflows. Use when the user wants to:
|
||||||
|
store API keys or credentials in 1Password, read secrets from 1Password into scripts or config,
|
||||||
|
set up .env files using 1Password secret references, rotate or update credentials, manage
|
||||||
|
developer secrets across projects, use 1Password service accounts for CI/CD, or integrate
|
||||||
|
1Password with tools like Claude Desktop, n8n, Docker, Supabase, GitHub Actions, or Replit.
|
||||||
|
Triggers on phrases like "store in 1Password", "read from 1Password", "op://", "secret reference",
|
||||||
|
"manage API keys with 1Password", "1Password CLI", or any request involving the `op` command.
|
||||||
|
---
|
||||||
|
|
||||||
|
# 1Password Skill
|
||||||
|
|
||||||
|
## ⚠️ Critical: Never Type Secrets Into Claude Code
|
||||||
|
|
||||||
|
**Claude Code can see everything typed in its terminal and chat.**
|
||||||
|
|
||||||
|
When a user needs to store a secret, ALWAYS use the Terminal launch pattern:
|
||||||
|
1. Generate a pre-filled script with known values already set
|
||||||
|
2. Use `launch-in-terminal.sh` to open it in Terminal.app
|
||||||
|
3. User types secrets in that window — Claude Code cannot see it
|
||||||
|
4. 1Password stores the secret, outputs `op://` references back to Claude
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Claude generates the script, then launches it outside its own view:
|
||||||
|
bash scripts/launch-in-terminal.sh /tmp/setup-my-service.sh "Service Name Setup"
|
||||||
|
```
|
||||||
|
|
||||||
|
Never ask users to paste API keys, passwords, or tokens into:
|
||||||
|
- The Claude Code chat
|
||||||
|
- A Bash tool call visible in Claude Code
|
||||||
|
- Any file Claude Code writes before it's stored in 1Password
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Setup Check
|
||||||
|
|
||||||
|
Always verify the CLI is ready before any operation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash scripts/check_setup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
If not installed: https://developer.1password.com/docs/cli/get-started/
|
||||||
|
If not signed in: unlock the **1Password desktop app** (after Mac restart, the app must be unlocked before the CLI works)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Storing Secrets: The Terminal Launch Pattern
|
||||||
|
|
||||||
|
When a user needs to store a new secret or credential:
|
||||||
|
|
||||||
|
**Step 1 — Generate the script** (Claude does this, with known values pre-filled):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat > /tmp/setup-SERVICE.sh << 'EOF'
|
||||||
|
bash /path/to/store-mcp-credentials.sh \
|
||||||
|
--vault Dev \
|
||||||
|
--item "Service Name" \
|
||||||
|
--set "url=https://known-url.com" \
|
||||||
|
--set "env=production" \
|
||||||
|
--secret "api_key" \
|
||||||
|
--secret "webhook_secret"
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2 — Launch in Terminal.app** (secrets stay out of Claude Code):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash scripts/launch-in-terminal.sh /tmp/setup-SERVICE.sh "Service Name Setup"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3 — Update config** (Claude uses the `op://` references from the output):
|
||||||
|
|
||||||
|
```json
|
||||||
|
"SERVICE_API_KEY": "op://Dev/Service Name/api_key"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Core Patterns
|
||||||
|
|
||||||
|
### Read a secret
|
||||||
|
|
||||||
|
```bash
|
||||||
|
op read "op://VaultName/ItemTitle/field_name"
|
||||||
|
export API_KEY=$(op read "op://Dev/Anthropic/api_key")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Store a new secret
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Basic
|
||||||
|
bash scripts/store_secret.sh --title "My API Key" --field api_key --value "sk-..."
|
||||||
|
|
||||||
|
# With vault
|
||||||
|
bash scripts/store_secret.sh --title "My API Key" --vault Dev --field api_key --value "sk-..."
|
||||||
|
|
||||||
|
# From environment variable
|
||||||
|
bash scripts/store_secret.sh --from-env ANTHROPIC_API_KEY --title "Anthropic"
|
||||||
|
|
||||||
|
# Generate a secure credential
|
||||||
|
bash scripts/store_secret.sh --title "App Secret" --field secret --generate --length 32
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update an existing secret
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash scripts/store_secret.sh --update --title "My API Key" --field api_key --value "new-value"
|
||||||
|
# Or directly:
|
||||||
|
op item edit "My API Key" api_key[password]=new-value
|
||||||
|
```
|
||||||
|
|
||||||
|
### Generate a .env from 1Password
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Interactive — lists items, choose one
|
||||||
|
bash scripts/env_from_op.sh
|
||||||
|
|
||||||
|
# From a specific item (dry run preview)
|
||||||
|
bash scripts/env_from_op.sh --item "Project Credentials" --dry-run
|
||||||
|
|
||||||
|
# Write .env.tpl (secret references — safe to commit)
|
||||||
|
bash scripts/env_from_op.sh --item "Project Credentials" --output .env.tpl
|
||||||
|
|
||||||
|
# Write .env with resolved real values (DO NOT commit)
|
||||||
|
bash scripts/env_from_op.sh --item "Project Credentials" --resolve --output .env
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Secret References (op://)
|
||||||
|
|
||||||
|
The safest pattern — store `op://` references in config files instead of real values.
|
||||||
|
|
||||||
|
> **Privacy note:** `op://` references reveal vault names, item names, and field names.
|
||||||
|
> Safe to commit to **private repos**. For public repos, check that your vault/item naming
|
||||||
|
> doesn't expose sensitive structure (client names, internal service names, etc.).
|
||||||
|
|
||||||
|
```
|
||||||
|
op://VaultName/ItemTitle/field_name
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# .env.tpl (commit this file)
|
||||||
|
ANTHROPIC_API_KEY=op://Dev/Anthropic/api_key
|
||||||
|
N8N_API_KEY=op://Dev/n8n/api_key
|
||||||
|
SUPABASE_SERVICE_KEY=op://Dev/Supabase/service_key
|
||||||
|
|
||||||
|
# ✅ Inject at runtime — secrets stay in subprocess, never in shell history
|
||||||
|
op run --env-file=.env.tpl -- your-command
|
||||||
|
|
||||||
|
# ⚠️ Avoid sourcing into current shell — unsafe if values contain $(...) or backticks
|
||||||
|
# source <(op run --env-file=.env.tpl -- env) ← skip this pattern
|
||||||
|
```
|
||||||
|
|
||||||
|
For full syntax and edge cases: [references/secret_references.md](references/secret_references.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Integration Guides
|
||||||
|
|
||||||
|
Read [references/integrations.md](references/integrations.md) for patterns with:
|
||||||
|
|
||||||
|
- **Claude Desktop** — MCP server config using `op run`
|
||||||
|
- **n8n** — Environment injection at startup, credential push via API
|
||||||
|
- **Docker / Docker Compose** — `op run -- docker compose up`
|
||||||
|
- **GitHub Actions** — `1password/load-secrets-action`
|
||||||
|
- **Python scripts** — subprocess + 1Password SDK
|
||||||
|
- **Supabase** — Storing and retrieving project credentials
|
||||||
|
- **Replit** — Local dev → Replit Secrets bridge
|
||||||
|
- **Rotation workflow** — Update in service → update in 1Password → re-inject
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common CLI Commands
|
||||||
|
|
||||||
|
Full reference: [references/op_commands.md](references/op_commands.md)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
op item list # List all items
|
||||||
|
op item list --vault Dev # Filter by vault
|
||||||
|
op item get "Item Title" # View item details
|
||||||
|
op item get "Item Title" --format json # JSON output
|
||||||
|
op vault list # List vaults
|
||||||
|
op whoami # Check auth status
|
||||||
|
op account list # List accounts
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CI/CD: Service Accounts
|
||||||
|
|
||||||
|
For non-interactive environments (GitHub Actions, Docker, n8n server):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export OP_SERVICE_ACCOUNT_TOKEN="ops_eyJ..."
|
||||||
|
op read "op://Dev/MyApp/api_key" # works without signin prompt
|
||||||
|
```
|
||||||
|
|
||||||
|
Create service accounts: 1Password UI → Settings → Developer → Service Accounts.
|
||||||
|
Grant vault access only to what the service needs.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Security Rules
|
||||||
|
|
||||||
|
1. **Never hardcode secrets** — always use `op://` references or runtime injection
|
||||||
|
2. **Commit `.env.tpl`** to private repos only — it exposes vault/item structure, not values
|
||||||
|
3. **Never commit `.env`** (real values) — add it to `.gitignore` immediately: `echo ".env" >> .gitignore`
|
||||||
|
4. **Use vaults to scope access** — separate vault per project or team
|
||||||
|
5. **Rotate on exposure** — use `store_secret.sh --update` then re-inject everywhere
|
||||||
|
6. **Service accounts for CI/CD** — never use personal account tokens in automation
|
||||||
37
.claude/commands/scc.md
Normal file
37
.claude/commands/scc.md
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# /scc - Save, Commit, and Push
|
||||||
|
|
||||||
|
Quick command to save session log, stage everything, and push to Gitea in one shot.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
1. **Save session log** - Create/update session log for today using the /save skill logic:
|
||||||
|
- Determine correct location based on work context (project-specific or general `session-logs/`)
|
||||||
|
- Use format `YYYY-MM-DD-session.md`
|
||||||
|
- If file exists, append with `## Update: HH:MM` header
|
||||||
|
- Include: summary, credentials (unredacted), infrastructure, commands, files changed, pending tasks
|
||||||
|
|
||||||
|
2. **Stage all changes** - Run `git add -A` to stage everything including the new session log
|
||||||
|
|
||||||
|
3. **Commit** - Auto-commit with message:
|
||||||
|
```
|
||||||
|
scc: Session save and push from [hostname] at [timestamp]
|
||||||
|
|
||||||
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Push to Gitea** - Run `git push origin main`
|
||||||
|
|
||||||
|
5. **Report** - Confirm what was saved, committed, and pushed
|
||||||
|
|
||||||
|
6. **Reaffirm roles** - After push, briefly restate:
|
||||||
|
- You are a COORDINATOR, not an executor
|
||||||
|
- Delegate: DB -> Database Agent, code -> Coding Agent, git -> Gitea Agent, tests -> Testing Agent
|
||||||
|
- Do yourself: simple responses, reading 1-2 files, planning, decisions
|
||||||
|
- >500 tokens of work = delegate. Code or database = ALWAYS delegate.
|
||||||
|
- NO EMOJIS. Use ASCII markers: `[OK]`, `[ERROR]`, `[WARNING]`, `[SUCCESS]`, `[INFO]`
|
||||||
|
|
||||||
|
## Important
|
||||||
|
- This is a FAST command - no lengthy analysis, just save and ship
|
||||||
|
- Do NOT invoke /refresh-directives afterward (unlike /sync)
|
||||||
|
- Do NOT read behavioral guidelines beyond the role reaffirmation above
|
||||||
|
- Just save, commit, push, reaffirm, report
|
||||||
375
.claude/machines/LINUX_PC_ONBOARDING.md
Normal file
375
.claude/machines/LINUX_PC_ONBOARDING.md
Normal file
@@ -0,0 +1,375 @@
|
|||||||
|
# Linux PC Onboarding Guide for Claude Code
|
||||||
|
|
||||||
|
**Purpose:** This document helps Claude Code understand how to operate correctly in the ClaudeTools environment after a fresh Linux install.
|
||||||
|
|
||||||
|
**Read this FIRST** before doing any work.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## TL;DR - Critical Rules
|
||||||
|
|
||||||
|
1. **You are a COORDINATOR, not an executor** - delegate significant work to agents
|
||||||
|
2. **NO EMOJIS** - Use `[OK]`, `[ERROR]`, `[WARNING]`, `[SUCCESS]`, `[INFO]`
|
||||||
|
3. **Never query databases directly** - Use Database Agent
|
||||||
|
4. **Never write production code yourself** - Use Coding Agent
|
||||||
|
5. **Always run `/sync` first** to get latest context from Gitea
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 1: Initial Setup
|
||||||
|
|
||||||
|
### Run These Commands First
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Navigate to ClaudeTools
|
||||||
|
cd ~/ClaudeTools # or wherever you cloned it
|
||||||
|
|
||||||
|
# 2. Pull latest from Gitea
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# 3. Check GrepAI status (semantic code search)
|
||||||
|
grepai status
|
||||||
|
|
||||||
|
# 4. If GrepAI watcher isn't running:
|
||||||
|
grepai watch --background
|
||||||
|
|
||||||
|
# 5. Check Ollama is running (local AI)
|
||||||
|
curl -s http://localhost:11434/api/tags | jq '.models[].name'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Required Models for Ollama
|
||||||
|
|
||||||
|
Pull these if not present:
|
||||||
|
```bash
|
||||||
|
ollama pull qwen3:14b # General tasks
|
||||||
|
ollama pull codestral:22b # Code tasks
|
||||||
|
ollama pull nomic-embed-text # Embeddings for GrepAI
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 2: Understand Your Identity
|
||||||
|
|
||||||
|
### You Are a Coordinator
|
||||||
|
|
||||||
|
You preserve your context window by delegating work. You do NOT:
|
||||||
|
- Query databases directly (no SSH/mysql/curl to API)
|
||||||
|
- Write production code yourself
|
||||||
|
- Run tests yourself
|
||||||
|
- Commit/push yourself
|
||||||
|
|
||||||
|
You DO:
|
||||||
|
- Plan and make decisions
|
||||||
|
- Read 1-2 files for quick answers
|
||||||
|
- Present results to the user
|
||||||
|
- Coordinate specialized agents
|
||||||
|
|
||||||
|
### Delegation Rules
|
||||||
|
|
||||||
|
| Task | Delegate To |
|
||||||
|
|------|-------------|
|
||||||
|
| Database queries/inserts/updates | Database Agent |
|
||||||
|
| Production code generation | Coding Agent |
|
||||||
|
| Code review (MANDATORY after changes) | Code Review Agent |
|
||||||
|
| Test execution | Testing Agent |
|
||||||
|
| Git commits/push/branch | Gitea Agent |
|
||||||
|
| Backups/restore | Backup Agent |
|
||||||
|
| File exploration (broad) | Explore Agent |
|
||||||
|
| Semantic code search | deep-explore Agent |
|
||||||
|
| Complex reasoning | General-purpose + Sequential Thinking |
|
||||||
|
|
||||||
|
**Rule of thumb:** If work exceeds 500 tokens = delegate. If it touches code or database = ALWAYS delegate.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 3: Key Infrastructure
|
||||||
|
|
||||||
|
### Database
|
||||||
|
- **Host:** 172.16.3.30:3306
|
||||||
|
- **Database:** claudetools
|
||||||
|
- **User:** claudetools
|
||||||
|
- **Password:** CT_e8fcd5a3952030a79ed6debae6c954ed
|
||||||
|
- **DO NOT** connect directly - use Database Agent
|
||||||
|
|
||||||
|
### API
|
||||||
|
- **URL:** http://172.16.3.30:8001
|
||||||
|
- **Docs:** http://172.16.3.30:8001/api/docs
|
||||||
|
- **Auth:** JWT Bearer Token
|
||||||
|
|
||||||
|
### Gitea
|
||||||
|
- **URL:** https://git.azcomputerguru.com
|
||||||
|
- **Repo:** azcomputerguru/claudetools
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 4: Available Commands
|
||||||
|
|
||||||
|
These are slash commands you can invoke:
|
||||||
|
|
||||||
|
| Command | Purpose |
|
||||||
|
|---------|---------|
|
||||||
|
| `/sync` | Sync with Gitea, pull latest, push local changes |
|
||||||
|
| `/checkpoint` | Git commit + database context snapshot |
|
||||||
|
| `/save` | Create comprehensive session log |
|
||||||
|
| `/context` | Search session logs and credentials for previous work |
|
||||||
|
| `/refresh-directives` | Re-read behavioral rules (do after sync) |
|
||||||
|
|
||||||
|
### First Thing Every Session
|
||||||
|
|
||||||
|
```
|
||||||
|
/sync
|
||||||
|
```
|
||||||
|
|
||||||
|
This pulls latest changes from other machines and pushes your local changes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 5: ASCII Markers (NO EMOJIS!)
|
||||||
|
|
||||||
|
**Never use emojis.** They cause encoding issues across platforms.
|
||||||
|
|
||||||
|
Use these instead:
|
||||||
|
|
||||||
|
| Marker | Use For |
|
||||||
|
|--------|---------|
|
||||||
|
| `[OK]` | Success, completed |
|
||||||
|
| `[SUCCESS]` | Task completed successfully |
|
||||||
|
| `[ERROR]` | Failure, problem |
|
||||||
|
| `[WARNING]` | Caution, potential issue |
|
||||||
|
| `[INFO]` | Informational message |
|
||||||
|
| `[CRITICAL]` | Severe error |
|
||||||
|
|
||||||
|
**Bad:**
|
||||||
|
```
|
||||||
|
✓ Task completed!
|
||||||
|
⚠ Warning: check config
|
||||||
|
```
|
||||||
|
|
||||||
|
**Good:**
|
||||||
|
```
|
||||||
|
[OK] Task completed!
|
||||||
|
[WARNING] Check config
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 6: Local AI (Ollama)
|
||||||
|
|
||||||
|
Ollama runs locally for tasks that don't need Claude-level reasoning.
|
||||||
|
|
||||||
|
### When to Use Ollama
|
||||||
|
|
||||||
|
**Good for:**
|
||||||
|
- Bulk/repetitive tasks (summarizing 50 logs)
|
||||||
|
- Boilerplate code generation
|
||||||
|
- Data extraction/classification
|
||||||
|
- Draft content you'll review
|
||||||
|
|
||||||
|
**Bad for (use Claude):**
|
||||||
|
- Architectural decisions
|
||||||
|
- Security-sensitive code
|
||||||
|
- Multi-step planning
|
||||||
|
- Final production output
|
||||||
|
|
||||||
|
### How to Call Ollama
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Simple prompt
|
||||||
|
curl -s http://localhost:11434/api/generate \
|
||||||
|
-d '{"model":"qwen3:14b","prompt":"Summarize: ...","stream":false}' \
|
||||||
|
| jq -r '.response'
|
||||||
|
|
||||||
|
# Code tasks
|
||||||
|
curl -s http://localhost:11434/api/chat \
|
||||||
|
-d '{"model":"codestral:22b","messages":[{"role":"user","content":"..."}],"stream":false}' \
|
||||||
|
| jq -r '.message.content'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Review Policy for Ollama Output
|
||||||
|
|
||||||
|
| Impact Level | Review Required | Examples |
|
||||||
|
|--------------|-----------------|----------|
|
||||||
|
| Critical | ALWAYS verify against source | Auth, security, encryption, DB migrations |
|
||||||
|
| High | Review for correctness | API logic, business rules, infra scripts |
|
||||||
|
| Medium | Skim for obvious errors | Internal docs, session summaries, boilerplate |
|
||||||
|
| Low | Trust without review | Classification, reformatting, placeholders |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 7: GrepAI (Semantic Search)
|
||||||
|
|
||||||
|
GrepAI indexes the codebase for natural language search.
|
||||||
|
|
||||||
|
### When to Use GrepAI vs Grep
|
||||||
|
|
||||||
|
**Use GrepAI for:**
|
||||||
|
- "How does authentication work?"
|
||||||
|
- "Find implementations related to user sessions"
|
||||||
|
- Exploring unfamiliar code areas
|
||||||
|
- Context recovery from session logs
|
||||||
|
|
||||||
|
**Use regular Grep for:**
|
||||||
|
- Exact text matches
|
||||||
|
- Known function/class names
|
||||||
|
- Simple pattern matching
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Search
|
||||||
|
grepai search "how does JWT auth work" --json
|
||||||
|
|
||||||
|
# Call graph tracing
|
||||||
|
grepai trace callers "get_db"
|
||||||
|
grepai trace callees "create_user"
|
||||||
|
|
||||||
|
# Start watcher (if not running)
|
||||||
|
grepai watch --background
|
||||||
|
|
||||||
|
# Restart watcher (if results seem stale)
|
||||||
|
grepai watch --stop && grepai watch --background
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 8: File Organization
|
||||||
|
|
||||||
|
### Where to Put Things
|
||||||
|
|
||||||
|
| Content Type | Location |
|
||||||
|
|--------------|----------|
|
||||||
|
| ClaudeTools API code | `api/`, `migrations/` |
|
||||||
|
| Client work | `clients/[client-name]/` |
|
||||||
|
| Project work | `projects/[project-name]/` |
|
||||||
|
| Session logs | `session-logs/` or project-specific `session-logs/` |
|
||||||
|
| Scripts | Project-specific `scripts/` folder |
|
||||||
|
| Machine specs | `.claude/machines/` |
|
||||||
|
|
||||||
|
### Key Files to Know
|
||||||
|
|
||||||
|
- `credentials.md` - All infrastructure credentials (NEVER ask user for these)
|
||||||
|
- `SESSION_STATE.md` - Project history
|
||||||
|
- `.claude/CLAUDE.md` - Main behavioral rules (auto-loaded)
|
||||||
|
- `.claude/CODING_GUIDELINES.md` - Coding standards
|
||||||
|
- `.claude/agents/*.md` - Agent definitions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 9: Context Recovery
|
||||||
|
|
||||||
|
When the user references previous work:
|
||||||
|
|
||||||
|
1. **Use `/context` command** to search session logs
|
||||||
|
2. **Check `credentials.md`** for infrastructure details
|
||||||
|
3. **Search session-logs/** for recent work
|
||||||
|
4. **Never ask user** for info that's in these files
|
||||||
|
|
||||||
|
### Session Log Locations
|
||||||
|
|
||||||
|
```
|
||||||
|
session-logs/ # General logs
|
||||||
|
projects/*/session-logs/ # Project-specific
|
||||||
|
clients/*/session-logs/ # Client-specific
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 10: Automatic Behaviors
|
||||||
|
|
||||||
|
These happen automatically - don't forget them:
|
||||||
|
|
||||||
|
1. **After UI changes** (HTML/CSS/JSX) -> Auto-invoke `/frontend-design`
|
||||||
|
2. **Complex problems** (3+ issues, rejection loops) -> Use Sequential Thinking MCP
|
||||||
|
3. **After code changes** -> Code Review Agent reviews (MANDATORY)
|
||||||
|
4. **Complex tasks** (>3 steps) -> Create todo list with TodoWrite
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 11: SSH Configuration
|
||||||
|
|
||||||
|
On Linux, use system OpenSSH:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Standard SSH
|
||||||
|
ssh user@host
|
||||||
|
|
||||||
|
# Never use paramiko or other SSH libraries when system SSH works
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 12: Self-Check After Setup
|
||||||
|
|
||||||
|
Run `/sync` and verify:
|
||||||
|
|
||||||
|
- [ ] Git pull successful
|
||||||
|
- [ ] Latest session logs visible
|
||||||
|
- [ ] GrepAI watcher running (`pgrep -f "grepai watch"`)
|
||||||
|
- [ ] Ollama responding (`curl http://localhost:11434/api/tags`)
|
||||||
|
- [ ] Can read credentials.md
|
||||||
|
- [ ] Understand delegation model
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference Card
|
||||||
|
|
||||||
|
```
|
||||||
|
IDENTITY: Coordinator (not executor)
|
||||||
|
EMOJIS: NEVER (use [OK], [ERROR], etc.)
|
||||||
|
DATABASE: Always delegate to Database Agent
|
||||||
|
CODE: Always delegate to Coding Agent
|
||||||
|
FIRST COMMAND: /sync
|
||||||
|
CONTEXT: Check credentials.md and session-logs/
|
||||||
|
LOCAL AI: Ollama for bulk tasks, review output
|
||||||
|
SEARCH: GrepAI for intent, Grep for exact text
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Other Machines in This Environment
|
||||||
|
|
||||||
|
Check `.claude/machines/` for specs on:
|
||||||
|
- `mikes-macbook-air.md` - M4 MacBook Air (this doc was created there)
|
||||||
|
- (Add your machine spec after setup)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### GrepAI Not Working
|
||||||
|
```bash
|
||||||
|
grepai watch --stop
|
||||||
|
grepai watch --background
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ollama Not Responding
|
||||||
|
```bash
|
||||||
|
sudo systemctl status ollama
|
||||||
|
sudo systemctl restart ollama
|
||||||
|
```
|
||||||
|
|
||||||
|
### Git Push Rejected
|
||||||
|
```bash
|
||||||
|
git pull origin main --rebase
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
### Permission Issues
|
||||||
|
```bash
|
||||||
|
sudo chown -R $USER:$USER ~/ClaudeTools
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## First Task After Reading This
|
||||||
|
|
||||||
|
1. Run `/sync` to pull latest
|
||||||
|
2. Run `/refresh-directives` to internalize rules
|
||||||
|
3. Create your machine spec file in `.claude/machines/`
|
||||||
|
4. You're ready to work!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Created:** 2026-03-20
|
||||||
|
**Created By:** Claude on Mikes-MacBook-Air.local
|
||||||
|
**Purpose:** Help fresh Linux installs understand ClaudeTools behavioral expectations
|
||||||
91
.claude/machines/acg-guru-5070.md
Normal file
91
.claude/machines/acg-guru-5070.md
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# Machine: acg-guru-5070
|
||||||
|
|
||||||
|
**Hostname:** acg-guru-5070
|
||||||
|
**Last Updated:** 2026-03-21
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hardware Specs
|
||||||
|
|
||||||
|
| Spec | Value |
|
||||||
|
|------|-------|
|
||||||
|
| Model | Lenovo Legion Pro 7 16IAX10H (DMI: 83F5) |
|
||||||
|
| CPU | Intel Core Ultra 9 275HX (24 cores, up to 5.4 GHz) |
|
||||||
|
| Memory | 32 GB DDR5 |
|
||||||
|
| GPU | NVIDIA GeForce RTX 5070 Ti Laptop GPU (12 GB VRAM) |
|
||||||
|
| Storage 1 | 954 GB NVMe (SK Hynix) - CachyOS root, btrfs |
|
||||||
|
| Storage 2 | 954 GB NVMe (SK Hynix) - /home, ext4 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Software
|
||||||
|
|
||||||
|
| Spec | Value |
|
||||||
|
|------|-------|
|
||||||
|
| OS | CachyOS Linux (Arch-based) |
|
||||||
|
| Kernel | 6.19.9-1-cachyos |
|
||||||
|
| DE | KDE Plasma 6.6.3 (Wayland) |
|
||||||
|
| NVIDIA Driver | 595.45.04 (open kernel module) |
|
||||||
|
| CUDA | 13.2 |
|
||||||
|
| Python | 3.14 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Claude Code Environment
|
||||||
|
|
||||||
|
- **Working Directory:** /home/guru/ClaudeTools
|
||||||
|
- **User:** guru
|
||||||
|
- **Shell:** fish
|
||||||
|
- **Git:** Configured for Gitea (git.azcomputerguru.com)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Network
|
||||||
|
|
||||||
|
| Interface | Address |
|
||||||
|
|-----------|---------|
|
||||||
|
| WiFi (wlan0) | 10.3.36.218 |
|
||||||
|
| Tailscale | 100.95.216.79 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Capabilities
|
||||||
|
|
||||||
|
- [x] Git operations
|
||||||
|
- [x] SSH access to infrastructure
|
||||||
|
- [x] GrepAI semantic search (watcher running)
|
||||||
|
- [x] Ollama local AI (qwen3:14b, codestral:22b, nomic-embed-text)
|
||||||
|
- [x] MCP servers available
|
||||||
|
- [x] NVIDIA GPU (CUDA compute)
|
||||||
|
- [x] Claude Code CLI
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
|
||||||
|
### GPU Firmware Bug (RTX 5070 Ti)
|
||||||
|
|
||||||
|
The RTX 5070 Ti enters an error state (NVRM rpcSendMessage 0x00000062) after ~3-5 minutes of sustained GPU compute. This is a known Blackwell/RTX 50-series GSP firmware bug on Linux (NVIDIA bug #5953411). Affects all tested drivers (580.x, 590.x, 595.x).
|
||||||
|
|
||||||
|
**Impact:** GPU-accelerated ML workloads (Whisper transcription, etc.) cannot complete. GPU enters full ERR! state requiring hard power-off (warm reboot hangs with spinning symbol).
|
||||||
|
|
||||||
|
**Workarounds tried (none effective):**
|
||||||
|
- Disable Runtime D3 power management
|
||||||
|
- Enable persistence mode
|
||||||
|
- Lock GPU clocks
|
||||||
|
- Power cap reduction
|
||||||
|
|
||||||
|
**Status:** Waiting for NVIDIA driver fix. Heavy GPU compute delegated to Mac (M4).
|
||||||
|
|
||||||
|
### Custom Kernel for Audio
|
||||||
|
|
||||||
|
Running a custom-patched CachyOS kernel with the `nadimkobeissi/16iax10h-linux-sound-saga` patch for Awinic AW88399 smart amplifier support. Stock kernel has terrible speaker output. Patch is not upstreamed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Primary development workstation
|
||||||
|
- GPU works fine for display, light compute, Ollama inference — only fails under sustained heavy compute (Whisper, training)
|
||||||
|
- Sudo: NOPASSWD configured for guru user
|
||||||
|
- Old btrfs @home subvolume on nvme0n1 (from initial install before /home was moved to nvme1n1)
|
||||||
69
.claude/machines/guru-beast-rog.md
Normal file
69
.claude/machines/guru-beast-rog.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# Machine: GURU-BEAST-ROG
|
||||||
|
|
||||||
|
**Hostname:** GURU-BEAST-ROG
|
||||||
|
**Last Updated:** 2026-03-24
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hardware Specs
|
||||||
|
|
||||||
|
| Spec | Value |
|
||||||
|
|------|-------|
|
||||||
|
| Model | ASUS Desktop (ROG) |
|
||||||
|
| CPU | Intel Core i9-14900K (24 cores / 32 threads, up to 6.0 GHz) |
|
||||||
|
| Memory | 128 GB DDR5 |
|
||||||
|
| GPU | NVIDIA GeForce RTX 4090 (24 GB VRAM) |
|
||||||
|
| Storage | 2 TB NVMe (WD_BLACK SN7100) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Software
|
||||||
|
|
||||||
|
| Spec | Value |
|
||||||
|
|------|-------|
|
||||||
|
| OS | Windows 11 Pro (26200) |
|
||||||
|
| Python | 3.x (installed) |
|
||||||
|
| Node.js | v24.14.0 |
|
||||||
|
| Ollama | v0.18.2 |
|
||||||
|
| Git | Installed (Git for Windows) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Claude Code Environment
|
||||||
|
|
||||||
|
- **Working Directory:** C:\Users\guru\ClaudeTools
|
||||||
|
- **User:** guru
|
||||||
|
- **Shell:** bash (Git for Windows)
|
||||||
|
- **Git:** Configured for Gitea (git.azcomputerguru.com)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Network
|
||||||
|
|
||||||
|
| Interface | Address |
|
||||||
|
|-----------|---------|
|
||||||
|
| Wi-Fi | 10.2.51.228 |
|
||||||
|
| LAN (Local Area Connection) | 192.168.2.3 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Capabilities
|
||||||
|
|
||||||
|
- [x] Git operations
|
||||||
|
- [x] SSH access to infrastructure
|
||||||
|
- [x] GrepAI semantic search (watcher running)
|
||||||
|
- [x] Ollama local AI (nomic-embed-text installed; qwen3:14b, codestral:22b pulling)
|
||||||
|
- [x] MCP servers configured (filesystem, sequential-thinking, grepai)
|
||||||
|
- [x] NVIDIA RTX 4090 GPU (CUDA compute)
|
||||||
|
- [x] Claude Code CLI
|
||||||
|
- [x] Bypass permissions mode (settings.json configured)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Powerhouse desktop -- best GPU and most RAM across all workstations
|
||||||
|
- RTX 4090 does NOT have the GSP firmware bug that affects the 5070 Ti on Linux
|
||||||
|
- OpenVPN Connect adapter present (VPN capable)
|
||||||
|
- credentials.md present and populated
|
||||||
|
- Settings.json has permissions.defaultMode: bypassPermissions
|
||||||
54
.claude/machines/mikes-macbook-air.md
Normal file
54
.claude/machines/mikes-macbook-air.md
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# Machine: Mike's MacBook Air
|
||||||
|
|
||||||
|
**Hostname:** Mikes-MacBook-Air.local
|
||||||
|
**Last Updated:** 2026-03-20
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hardware Specs
|
||||||
|
|
||||||
|
| Spec | Value |
|
||||||
|
|------|-------|
|
||||||
|
| Model | MacBook Air (Mac16,12) |
|
||||||
|
| Model Number | MC6T4LL/A |
|
||||||
|
| Chip | Apple M4 |
|
||||||
|
| CPU Cores | 10 (4 Performance + 6 Efficiency) |
|
||||||
|
| Memory | 16 GB |
|
||||||
|
| Serial | J1607PM6LD |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Software
|
||||||
|
|
||||||
|
| Spec | Value |
|
||||||
|
|------|-------|
|
||||||
|
| OS | macOS 26.3.1 (25D2128) |
|
||||||
|
| Kernel | Darwin 25.3.0 |
|
||||||
|
| Boot Volume | Macintosh HD |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Claude Code Environment
|
||||||
|
|
||||||
|
- **Working Directory:** /Users/azcomputerguru/ClaudeTools
|
||||||
|
- **User:** azcomputerguru
|
||||||
|
- **Shell:** zsh
|
||||||
|
- **Git:** Configured for Gitea (git.azcomputerguru.com)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Capabilities
|
||||||
|
|
||||||
|
- [x] Git operations
|
||||||
|
- [x] SSH access to infrastructure
|
||||||
|
- [x] GrepAI semantic search (watcher running)
|
||||||
|
- [x] Ollama local AI (qwen3:14b, codestral:22b, nomic-embed-text)
|
||||||
|
- [x] MCP servers available
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Primary mobile development machine
|
||||||
|
- M4 chip provides good local AI inference performance
|
||||||
|
- Used for radio show prep, documentation, light development
|
||||||
25
.claude/memory/MEMORY.md
Normal file
25
.claude/memory/MEMORY.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Memory Index
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
- [Community Forum (Flarum)](reference_community_forum.md) - Flarum forum at community.azcomputerguru.com, API access, database, posting workflow
|
||||||
|
- [Radio Show Website](reference_radio_website.md) - Astro static site at radio.azcomputerguru.com on IX server
|
||||||
|
- [IX Server SSH Access](reference_ix_server_ssh.md) - SSH access notes, no key auth from CachyOS workstation yet
|
||||||
|
- [IX Access via Tailscale](reference_ix_access_tailscale.md) - IX server accessible with Tailscale on, no VPN needed
|
||||||
|
- [Neptune Access via D2TESTNAS](reference_neptune_access_d2testnas.md) - Neptune must be routed through D2TESTNAS
|
||||||
|
- [CachyOS Workstation Setup](reference_workstation_setup.md) - Dual NVMe, autostart apps, key fixes applied, old home location
|
||||||
|
- [Matomo Analytics](reference_matomo_analytics.md) - Self-hosted analytics at analytics.azcomputerguru.com, site IDs, tracking for all 3 sites
|
||||||
|
- [Dataforth Contact - AJ](reference_dataforth_contact.md) - AJ at Dataforth, dataforthgit@ email forwarding to him
|
||||||
|
|
||||||
|
## Feedback
|
||||||
|
- [D2TESTNAS SSH Access](feedback_d2testnas_ssh.md) - Use root@192.168.0.9 with Paper123!@#, not sysadmin
|
||||||
|
- [Bypass Permissions Setting](feedback_bypass_permissions_setting.md) - Set permissions.defaultMode to bypassPermissions in settings.json on all machines
|
||||||
|
|
||||||
|
## Machine
|
||||||
|
- [Windows GURU-BEAST-ROG Setup](machine_windows_guru_setup_status.md) - Fully configured: Node.js, Ollama (qwen3:14b, nomic-embed-text), GrepAI, MCP servers. Pending: codestral:22b pull
|
||||||
|
|
||||||
|
## Project
|
||||||
|
- [Audio Processor Architecture](project_audio_processor_architecture.md) - Segment-first pipeline: detect breaks before transcription for complete content capture
|
||||||
|
- [Neptune Email Routing Issues](project_email_routing_neptune.md) - Multiple clients (devcon, Sorensen/rieussetcorp) have email not routing properly from Neptune
|
||||||
|
- [Neptune SBR Email Routing Setup](project_neptune_sbr_email_routing.md) - Full SBR routing chain, config file locations, MailProtector integration, access methods
|
||||||
|
- [Dataforth Test Datasheet Pipeline](project_datasheet_pipeline.md) - Full pipeline rebuilt 2026-03-27. Server-side generation replaces DFWDS/Uploader. Website upload still broken.
|
||||||
|
- [Dataforth Security Incident](project_dataforth_incident_2026-03-27.md) - DF-JOEL2 compromised, MFA deployed, IC3 filed. CA policies enforce April 4.
|
||||||
20
.claude/memory/feedback_bypass_permissions_setting.md
Normal file
20
.claude/memory/feedback_bypass_permissions_setting.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Bypass Permissions Persistent Setting
|
||||||
|
description: Configure settings.json on all machines to persist bypass permissions mode across context compressions
|
||||||
|
type: feedback
|
||||||
|
---
|
||||||
|
|
||||||
|
Always set `permissions.defaultMode` to `"bypassPermissions"` in `~/.claude/settings.json` on all workstations.
|
||||||
|
|
||||||
|
**Why:** The `--dangerously-skip-permissions` CLI flag is not preserved when Claude Code compresses context or resumes sessions -- the new process starts without the flag, causing unexpected permission prompts mid-session. This is a known bug (GitHub issue #21974).
|
||||||
|
|
||||||
|
**How to apply:** On any new machine setup, ensure `~/.claude/settings.json` includes:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"defaultMode": "bypassPermissions"
|
||||||
|
},
|
||||||
|
"skipDangerousModePermissionPrompt": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
This makes bypass mode the default without needing the CLI flag. Both keys are needed -- `defaultMode` sets the mode, `skipDangerousModePermissionPrompt` suppresses the warning dialog.
|
||||||
11
.claude/memory/feedback_d2testnas_ssh.md
Normal file
11
.claude/memory/feedback_d2testnas_ssh.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
name: D2TESTNAS SSH Access
|
||||||
|
description: D2TESTNAS SSH is root@192.168.0.9 with Paper123!@#, not sysadmin
|
||||||
|
type: feedback
|
||||||
|
---
|
||||||
|
|
||||||
|
D2TESTNAS SSH: use `root@192.168.0.9` with password `Paper123!@#`. The `sysadmin` user does not work for SSH. CachyOS workstation (acg-guru-5070) now has an ed25519 key authorized on D2TESTNAS for root.
|
||||||
|
|
||||||
|
**Why:** Credentials in credentials.md listed sysadmin as SSH user, which was incorrect and caused multiple failed attempts.
|
||||||
|
|
||||||
|
**How to apply:** When SSHing to D2TESTNAS, always use root@192.168.0.9. The SSH key at ~/.ssh/id_ed25519 (guru@acg-guru-5070) should work without password.
|
||||||
44
.claude/memory/machine_windows_guru_setup_status.md
Normal file
44
.claude/memory/machine_windows_guru_setup_status.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
name: Windows GURU-BEAST-ROG Setup Status
|
||||||
|
description: Windows workstation setup completion status - Ollama, GrepAI, MCP, Node.js all configured
|
||||||
|
type: reference
|
||||||
|
---
|
||||||
|
|
||||||
|
# Windows Machine Setup Status (GURU-BEAST-ROG)
|
||||||
|
|
||||||
|
**Created:** 2026-03-23
|
||||||
|
**Updated:** 2026-03-24
|
||||||
|
**Machine:** GURU-BEAST-ROG (Windows 11 Pro, i9-14900K, 128GB DDR5, RTX 4090)
|
||||||
|
|
||||||
|
## Software Status
|
||||||
|
|
||||||
|
| Software | Version | Path | Status |
|
||||||
|
|----------|---------|------|--------|
|
||||||
|
| Python | 3.12.10 | system PATH | [OK] |
|
||||||
|
| Git | 2.52.0.windows.1 | system PATH | [OK] |
|
||||||
|
| Windows OpenSSH | system | C:\Windows\System32\OpenSSH\ssh.exe | [OK] |
|
||||||
|
| Node.js | v24.14.0 | C:\Program Files\nodejs | [OK] |
|
||||||
|
| Ollama | v0.18.2 | C:\Users\guru\AppData\Local\Programs\Ollama\ollama.exe | [OK] |
|
||||||
|
| GrepAI | v0.35.0 | C:\Users\guru\ClaudeTools\grepai.exe | [OK] |
|
||||||
|
| credentials.md | -- | repo root | [OK] |
|
||||||
|
|
||||||
|
## Ollama Models
|
||||||
|
|
||||||
|
| Model | Size | Status |
|
||||||
|
|-------|------|--------|
|
||||||
|
| nomic-embed-text | 274 MB | [OK] |
|
||||||
|
| qwen3:14b | 9.3 GB | [OK] |
|
||||||
|
| codestral:22b | ~12 GB | [PENDING] - download interrupted, not pulled |
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
- **.mcp.json:** filesystem, sequential-thinking, grepai servers configured
|
||||||
|
- **GrepAI:** Initialized, watcher configured, Ollama backend with nomic-embed-text
|
||||||
|
- **Bypass permissions:** `permissions.defaultMode: "bypassPermissions"` in ~/.claude/settings.json
|
||||||
|
- **In-repo memory:** .claude/memory/ (syncs via Gitea)
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Ollama not in Git Bash PATH -- use full path or open new terminal
|
||||||
|
- GrepAI watcher may need restart after reboot: `./grepai.exe watch --background`
|
||||||
|
- Machine registered at `.claude/machines/guru-beast-rog.md`
|
||||||
32
.claude/memory/project_audio_processor_architecture.md
Normal file
32
.claude/memory/project_audio_processor_architecture.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
name: Audio Processor - Segment-First Architecture
|
||||||
|
description: Revised pipeline architecture - detect breaks and split into segments BEFORE transcription for complete content capture
|
||||||
|
type: project
|
||||||
|
---
|
||||||
|
|
||||||
|
## Revised Pipeline Architecture (decided 2026-03-22)
|
||||||
|
|
||||||
|
Shows are almost always 4 segments per hour (8 total for a 2-hour show). Extra breaks are rare.
|
||||||
|
|
||||||
|
**Old approach:** Transcribe full episode -> truncate to fit LLM context -> analyze (loses content)
|
||||||
|
|
||||||
|
**New approach:** Detect breaks first (audio-only) -> split into ~8 segments -> transcribe each -> analyze each with full context -> cross-segment synthesis
|
||||||
|
|
||||||
|
### Pipeline Order
|
||||||
|
|
||||||
|
1. **Audio-level break detection** (no transcript needed) — loudness/compression jumps, silence gaps, known bumper fingerprints, HR1/HR2 boundary
|
||||||
|
2. **Split into segments** — ~7-15 min each, complete audio chunks
|
||||||
|
3. **Transcribe each segment** — smaller files, complete content, no truncation
|
||||||
|
4. **Analyze each segment** — full transcript fits in LLM context window easily
|
||||||
|
5. **Cross-segment synthesis** — detect topics spanning segments, callbacks ("going back to what we said before the break"), narrative arc
|
||||||
|
6. **Generate content** — blog posts, forum posts, episode summary from complete analysis
|
||||||
|
|
||||||
|
### Key Insights
|
||||||
|
|
||||||
|
- 4 segments/hour is a strong structural prior for break detection — if 12-18 min into a segment and audio signatures appear, almost certainly a break. At 5 min, probably not.
|
||||||
|
- Each segment transcript is ~5-10K chars — fits in any LLM context with room for detailed prompts
|
||||||
|
- Cross-segment synthesis pass is new and essential for catching callbacks and recurring topics
|
||||||
|
|
||||||
|
**Why:** Solves the context window truncation problem that loses show content. Each segment gets complete analysis.
|
||||||
|
|
||||||
|
**How to apply:** This is the architecture direction for all future audio processor work. The existing Stage 3 segment detector needs to work without transcript input (audio-only signals). Stage 6 analyzer needs per-segment + synthesis passes.
|
||||||
37
.claude/memory/project_dataforth_incident_2026-03-27.md
Normal file
37
.claude/memory/project_dataforth_incident_2026-03-27.md
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
name: Dataforth Security Incident 2026-03-27
|
||||||
|
description: DF-JOEL2 compromised via ScreenConnect social engineering. MFA deployed. IC3 filed. C2 IPs blocked. Full remediation completed.
|
||||||
|
type: project
|
||||||
|
---
|
||||||
|
|
||||||
|
## Incident
|
||||||
|
Joel Lohr's workstation (DF-JOEL2, 192.168.0.143) compromised via phishing email to personal Yahoo account. Attacker "Angel Raya" deployed ScreenConnect C2 backdoors. M365 account also compromised from Turkey/UK/Germany.
|
||||||
|
|
||||||
|
## Attacker
|
||||||
|
- C2: 80.76.49.18 and 45.88.91.99 (AS399486, Virtuo, Montreal QC) - SUSPENDED by host
|
||||||
|
- Cloud relay: instance-wlb9ga-relay.screenconnect.com
|
||||||
|
- ConnectWise case: 03464184
|
||||||
|
- IC3 complaint: 1c32ade367084be9acd548f23705736f
|
||||||
|
|
||||||
|
## Remediation
|
||||||
|
- C2 IPs blocked at UDM firewall (iptables - need permanent rules in UniFi UI)
|
||||||
|
- 3 rogue ScreenConnect clients uninstalled
|
||||||
|
- jlohr AD password reset, M365 sessions revoked
|
||||||
|
- 32 machines scanned clean, 28 unreachable (offline)
|
||||||
|
- No lateral movement detected
|
||||||
|
|
||||||
|
## MFA Rollout
|
||||||
|
- 3 CA policies deployed (report-only until April 4, 2026):
|
||||||
|
- Require MFA (skip from office IP 67.206.163.122)
|
||||||
|
- Block foreign sign-ins (US only, MFA-Travel-Bypass group for exceptions)
|
||||||
|
- Block legacy auth
|
||||||
|
- 19/38 users MFA-ready, 19 need to register
|
||||||
|
- MFA notice sent to all users, deadline April 4
|
||||||
|
|
||||||
|
## Joel Lohr
|
||||||
|
- Retiring March 31, 2026
|
||||||
|
- Auto-reply directs contacts to Dan Center (dcenter@dataforth.com)
|
||||||
|
- Account should be disabled after retirement
|
||||||
|
|
||||||
|
**Why:** Active security incident requiring immediate response.
|
||||||
|
**How to apply:** Monitor CA policies in report-only mode, enforce April 4. Check 28 offline machines when available. Add C2 IPs to permanent UDM block list.
|
||||||
73
.claude/memory/project_datasheet_pipeline.md
Normal file
73
.claude/memory/project_datasheet_pipeline.md
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
---
|
||||||
|
name: Dataforth Test Datasheet Pipeline - Rebuilt 2026-03-27
|
||||||
|
description: Full pipeline from DOS test stations to website. New server-side generation replaces DFWDS/Uploader. 72/73 Quatronix datasheets generated. AD2 crypto wipe recovery.
|
||||||
|
type: project
|
||||||
|
---
|
||||||
|
|
||||||
|
## Background
|
||||||
|
AD2 (192.168.0.6) was wiped in a crypto/ransomware attack months ago. The test datasheet pipeline was broken. Customer Quatronix (China) blocking shipment of 328 modules (whittled to 54) without datasheets.
|
||||||
|
|
||||||
|
## Pipeline (5 stages, rebuilt 2026-03-27)
|
||||||
|
|
||||||
|
### Stage 1: DOS Test Stations (64 stations)
|
||||||
|
- QuickBASIC programs generate test data -> C:\STAGE on each DOS PC
|
||||||
|
- DAT files (raw test data) + TXT files (formatted datasheets)
|
||||||
|
- CTONW.BAT copies DAT files to NAS (working)
|
||||||
|
- CTONWTXT.BAT copies TXT files (NOT called in current AUTOEXEC v4.1 since 2026-03-12)
|
||||||
|
- TXT files piling up in C:\STAGE since Sept 2025
|
||||||
|
|
||||||
|
### Stage 2: NAS <-> AD2 Sync
|
||||||
|
- Script: C:\Shares\test\scripts\Sync-FromNAS-rsync.ps1 (every 15 min, WORKING)
|
||||||
|
- Rsync daemon on NAS: port 873, module "test", user rsync / IQ203s32119
|
||||||
|
- PULL: DAT files from NAS -> AD2, triggers database import
|
||||||
|
- PUSH: Software updates from AD2 -> NAS for DOS machines
|
||||||
|
|
||||||
|
### Stage 3: TestDataDB (Node.js/SQLite, WORKING)
|
||||||
|
- App: C:\Shares\testdatadb\ (Windows service "testdatadb", auto-start)
|
||||||
|
- API: http://192.168.0.6:3000
|
||||||
|
- Database: C:\Shares\testdatadb\database\testdata.db (2.27M records)
|
||||||
|
- Import: database/import.js (post-import hook calls export)
|
||||||
|
- **NEW: Spec parser** (parsers/spec-reader.js) - reads binary spec DATs, 1470 models
|
||||||
|
- **NEW: Exact-match formatter** (templates/datasheet-exact.js) - reverse-engineered from QB
|
||||||
|
- **NEW: Auto-export** (database/export-datasheets.js) - generates TXT to X:\For_Web
|
||||||
|
|
||||||
|
### Stage 4: WebShare (X: = \\ad2\webshare = C:\Shares\webshare)
|
||||||
|
- X:\Test_Datasheets - incoming (staging for old DFWDS)
|
||||||
|
- X:\For_Web - validated datasheets (501K+ files, pre-2026 archived to year subfolders)
|
||||||
|
- X:\For_Web_PDF - PDF versions (4.7K files)
|
||||||
|
- X:\Bad_Datasheets - invalid files (18K)
|
||||||
|
- X:\Datasheets_Log - DFWDS logs
|
||||||
|
|
||||||
|
### Stage 5: Website Upload (BROKEN)
|
||||||
|
- Old endpoints: dataforth.com/Services/{Uploader,DirectoryManifest,DeleteFile}.aspx - ALL 404
|
||||||
|
- Credentials: DataforthWebShare / Data6277
|
||||||
|
- TestDataSheetUploader (VB.NET, Hoffman) - not running, config pointed to dev paths
|
||||||
|
- Legacy site: legacy.dataforth.com/TestDataReport_Print.aspx (still works, no auth)
|
||||||
|
- New site: dataforth.com/TestDataReport (requires OIDC login)
|
||||||
|
|
||||||
|
## What Was Eliminated by Rebuild
|
||||||
|
- CTONWTXT.BAT (DOS TXT transfer) - no longer needed, server generates from DAT data
|
||||||
|
- DFWDS.exe (VB6 filename decoder) - no longer needed
|
||||||
|
- TestDataSheetUploader (VB.NET web uploader) - endpoints dead anyway
|
||||||
|
|
||||||
|
## Key File Encoding
|
||||||
|
H-prefix decode: A=10, B=11, C=12, D=13, E=14, F=15, G=16, H=17, I=18, J=19
|
||||||
|
Example: H8601-6.TXT -> serial 178601-6
|
||||||
|
New pipeline extracts SN from DAT record data directly, not filenames.
|
||||||
|
|
||||||
|
## Open Items
|
||||||
|
1. Website upload replacement (old ASP.NET endpoints dead)
|
||||||
|
2. 7B datasheet formatting (specs loaded, needs 7B-specific layout, ~830K records)
|
||||||
|
3. SCM5B49 spec file empty - need from John Lehman
|
||||||
|
4. Service permissions (runs as SYSTEM, causes SHM/WAL conflicts)
|
||||||
|
5. New product lines: MAQ20/PWRM (XLS), 10D (JSON, ~May 2026), DSCMHV
|
||||||
|
|
||||||
|
## Key Contacts
|
||||||
|
- John Lehman (jlehman@dataforth.com) - Engineering, QB code, specs
|
||||||
|
- Peter Iliya (pIliya@dataforth.com) - Applications Engineer, manual datasheet retrieval
|
||||||
|
- Ken Hoffman - TestDataSheetUploader author (VB.NET), DFWDS author, unresponsive
|
||||||
|
- Georg Haubner (ghaubner@dataforth.com) - D: drive has pre-crypto backup of network shares
|
||||||
|
- Ginger (gy@quatronix-cn.com) - Quatronix China, customer requesting datasheets
|
||||||
|
|
||||||
|
**Why:** Critical business issue - customer refusing shipments without datasheets.
|
||||||
|
**How to apply:** Pipeline is mostly rebuilt. Priority: website upload replacement, then 7B support.
|
||||||
11
.claude/memory/project_email_routing_neptune.md
Normal file
11
.claude/memory/project_email_routing_neptune.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
name: Neptune Email Routing Issues
|
||||||
|
description: Multiple clients (devcon, Sorensen/rieussetcorp) have email not routing properly from Neptune
|
||||||
|
type: project
|
||||||
|
---
|
||||||
|
|
||||||
|
Sorensen (rieussetcorp) and devcon both have the same email routing issue from Neptune — emails not routing properly.
|
||||||
|
|
||||||
|
**Why:** Recurring issue affecting multiple clients, likely a shared configuration or Neptune platform problem rather than isolated incidents.
|
||||||
|
|
||||||
|
**How to apply:** When troubleshooting email routing for any client on Neptune, check if the fix applied to one client needs to be replicated for others. Track as a systemic Neptune issue, not individual client problems.
|
||||||
49
.claude/memory/project_neptune_sbr_email_routing.md
Normal file
49
.claude/memory/project_neptune_sbr_email_routing.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
name: Neptune SBR Email Routing Setup
|
||||||
|
description: How outbound email routing works on Neptune Exchange - SBR agent, MailProtector smarthost, send connectors, and common fix for new clients
|
||||||
|
type: project
|
||||||
|
---
|
||||||
|
|
||||||
|
## Neptune Outbound Email Routing Chain
|
||||||
|
|
||||||
|
1. User sends mail from Exchange mailbox on Neptune (172.16.3.11)
|
||||||
|
2. **Microsoft.Exchange.SBR** transport agent (Priority 12) fires on OnResolved event
|
||||||
|
3. SBR reads config files at `C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\agents\Custom\`:
|
||||||
|
- `Microsoft.Exchange.SBR.InternalDomains.config` — list of domains SBR handles
|
||||||
|
- `Microsoft.Exchange.SBR.OverrideSettings.config` — maps `domain.com;domain.sbr` for routing
|
||||||
|
- `Microsoft.Exchange.SBR.IgnoreAuthAs.config` — exclusions
|
||||||
|
4. SBR rewrites recipient routing to `.sbr` domain (e.g., `rieussetcorp.sbr`)
|
||||||
|
5. Exchange matches `.sbr` address space to the corresponding Send Connector (e.g., `Outbound.Sorensen`)
|
||||||
|
6. Send connector smarthosts through MailProtector: `domain-com.outbound.emailservice.io`
|
||||||
|
7. MailProtector relays to final destination
|
||||||
|
|
||||||
|
There is also a **messageconcept ExSBR** agent at Priority 11 (`C:\Program Files\messageconcept\ExSBR\`).
|
||||||
|
|
||||||
|
## Common Issue: New client or server move
|
||||||
|
|
||||||
|
When Neptune's IP changes or a new domain is added, MailProtector must have the sending server IP authorized. Without this, MailProtector accepts the relay but drops/rejects the message.
|
||||||
|
|
||||||
|
**Fix (2026-03-22 for rieussetcorp.com):** Added 67.206.163.124 and 67.206.163.122 to MailProtector's authorized sender IPs.
|
||||||
|
|
||||||
|
## Neptune Location
|
||||||
|
|
||||||
|
Neptune physically moved from ACG office (72.194.62.7) to Dataforth (67.206.163.124 inbound, 67.206.163.122 outbound). SNAT rule on Dataforth UDM (`/data/on_boot.d/10-neptune-snat.sh`) should force outbound to use .124.
|
||||||
|
|
||||||
|
## Access
|
||||||
|
|
||||||
|
- WinRM: `172.16.3.11`, ACG\administrator, via pywinrm with NTLM
|
||||||
|
- Exchange PS: Connect via `New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://neptune.acg.local/PowerShell/ -Authentication Kerberos`
|
||||||
|
- Requires Tailscale route through D2TESTNAS (192.168.0.9) for 172.16.0.0/22
|
||||||
|
|
||||||
|
## Known Issues (as of 2026-03-22)
|
||||||
|
|
||||||
|
- 67.206.163.122 has no PTR record and is blacklisted by some providers
|
||||||
|
- SNAT rule may not be active — outbound was going as .122 not .124 on 3/16. Need to check UDM (192.168.0.254) — couldn't auth via SSH tonight, check in morning
|
||||||
|
- MAIL transport server still exists in Exchange config but server is decommissioned
|
||||||
|
- Spam queues with junk domains (wwwyamaha666.ru, bestspatulas.com, etc.)
|
||||||
|
- Tailscale 172.16.0.0/22 route moved from ACG pfSense to D2TESTNAS — may need permanent solution
|
||||||
|
- UDM SSH password (Paper123!@#-unifi) was rejected — may have changed
|
||||||
|
|
||||||
|
## Resolved (2026-03-22)
|
||||||
|
|
||||||
|
- rieussetcorp.com outbound: Added 67.206.163.124 and .122 to MailProtector authorized IPs — mail now flowing
|
||||||
48
.claude/memory/reference_community_forum.md
Normal file
48
.claude/memory/reference_community_forum.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
name: Community Forum (Flarum)
|
||||||
|
description: Flarum forum at community.azcomputerguru.com - platform details, API access, database credentials, and posting workflow
|
||||||
|
type: reference
|
||||||
|
---
|
||||||
|
|
||||||
|
## Community Forum - Flarum
|
||||||
|
|
||||||
|
- **URL:** https://community.azcomputerguru.com
|
||||||
|
- **Platform:** Flarum 1.8.14
|
||||||
|
- **Server:** IX server (172.16.3.10), cPanel account `azcomputerguru`
|
||||||
|
- **Document Root:** `/home/azcomputerguru/public_html/community/public`
|
||||||
|
- **PHP Version:** 8.1.33
|
||||||
|
|
||||||
|
### Database
|
||||||
|
- **Host:** localhost (on IX server)
|
||||||
|
- **Database:** `azcompu_flarum`
|
||||||
|
- **User:** `azcompu_flarum`
|
||||||
|
- **Password:** `Fl@rum2026!CGS`
|
||||||
|
|
||||||
|
### API
|
||||||
|
- **API Key:** `581b6c8c162a383ba87757f41b4381e9bf8db61d71bd578ee97fe32b7aeac046` (admin user, ID 1)
|
||||||
|
- **API Base:** `https://community.azcomputerguru.com/api`
|
||||||
|
- **Note:** Cloudflare blocks external API access. Must either:
|
||||||
|
1. Use `--resolve` with `curl -k` from IX server localhost
|
||||||
|
2. Use direct PHP/database script on IX server (preferred, more reliable)
|
||||||
|
|
||||||
|
### Forum Tags (Categories)
|
||||||
|
| ID | Name | Slug |
|
||||||
|
|----|------|------|
|
||||||
|
| 1 | General | general |
|
||||||
|
| 2 | Tech News | tech-news |
|
||||||
|
| 3 | Security & Privacy | security-privacy |
|
||||||
|
| 4 | Artificial Intelligence | artificial-intelligence |
|
||||||
|
| 5 | Space Tech | space-tech |
|
||||||
|
| 6 | Gadgets & Hardware | gadgets-hardware |
|
||||||
|
| 7 | How-Tos & Tips | how-tos-tips |
|
||||||
|
| 8 | Show Discussion | show-discussion |
|
||||||
|
| 9 | Off-Topic | off-topic |
|
||||||
|
|
||||||
|
### Posting Workflow
|
||||||
|
Cloudflare blocks the Flarum REST API from external requests. To create posts programmatically:
|
||||||
|
1. Write a PHP script that inserts directly into the database (discussions + posts + discussion_tag tables)
|
||||||
|
2. SCP the script and JSON payload to IX server `/tmp/`
|
||||||
|
3. Execute via `php /tmp/script.php` over SSH
|
||||||
|
4. Clean up temp files
|
||||||
|
|
||||||
|
**How to apply:** Use this when the user asks to create forum posts or manage the community forum.
|
||||||
7
.claude/memory/reference_dataforth_contact.md
Normal file
7
.claude/memory/reference_dataforth_contact.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
name: Dataforth Contact - AJ
|
||||||
|
description: AJ at Dataforth - email forwarding setup needed for dataforthgit@ address
|
||||||
|
type: reference
|
||||||
|
---
|
||||||
|
|
||||||
|
AJ at Dataforth needs messages sent to the dataforthgit@ email address to forward to him.
|
||||||
7
.claude/memory/reference_ix_access_tailscale.md
Normal file
7
.claude/memory/reference_ix_access_tailscale.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
name: IX Server Access via Tailscale
|
||||||
|
description: IX server (ix.azcomputerguru.com) is accessible with Tailscale on, no VPN needed
|
||||||
|
type: reference
|
||||||
|
---
|
||||||
|
|
||||||
|
IX server (ix.azcomputerguru.com / 172.16.3.10) can be accessed directly when Tailscale is on. No separate VPN connection required.
|
||||||
18
.claude/memory/reference_ix_server_ssh.md
Normal file
18
.claude/memory/reference_ix_server_ssh.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
name: IX Server SSH Access
|
||||||
|
description: SSH access notes for IX server - key auth not set up on CachyOS workstation, must use sshpass with password
|
||||||
|
type: reference
|
||||||
|
---
|
||||||
|
|
||||||
|
## IX Server SSH from CachyOS Workstation
|
||||||
|
|
||||||
|
- **Host:** 172.16.3.10 (ix.azcomputerguru.com)
|
||||||
|
- **User:** root
|
||||||
|
- **Password:** See credentials.md
|
||||||
|
- **SSH Key Auth:** NOT configured on CachyOS workstation (acg-guru-5070)
|
||||||
|
- **Must use:** `sshpass -p 'PASSWORD' ssh -o StrictHostKeyChecking=no -o PubkeyAuthentication=no root@172.16.3.10`
|
||||||
|
- **Suppress warnings:** Pipe through `grep -v WARNING | grep -v 'not using'` or `tail`
|
||||||
|
|
||||||
|
**Why:** The SSH key from this machine hasn't been added to IX server's authorized_keys yet. The old WSL key (guru@wsl) was authorized but this is a new CachyOS install.
|
||||||
|
|
||||||
|
**How to apply:** When running commands on IX server, use sshpass approach. Consider setting up SSH key auth to simplify future access.
|
||||||
40
.claude/memory/reference_matomo_analytics.md
Normal file
40
.claude/memory/reference_matomo_analytics.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
name: Matomo Analytics
|
||||||
|
description: Self-hosted Matomo analytics at analytics.azcomputerguru.com - credentials, site IDs, tracking setup for all 3 sites
|
||||||
|
type: reference
|
||||||
|
---
|
||||||
|
|
||||||
|
## Matomo Analytics
|
||||||
|
|
||||||
|
- **URL:** https://analytics.azcomputerguru.com
|
||||||
|
- **Platform:** Matomo 5.8.0 (PHP)
|
||||||
|
- **Server:** IX server (172.16.3.10), cPanel account `azcomputerguru`
|
||||||
|
- **Document Root:** `/home/azcomputerguru/public_html/analytics/`
|
||||||
|
|
||||||
|
### Login
|
||||||
|
- **User:** MikeSwanson
|
||||||
|
- **Password:** Mat0mo2026!CGS
|
||||||
|
- **Email:** mike@azcomputerguru.com
|
||||||
|
|
||||||
|
### Database
|
||||||
|
- **Host:** localhost (on IX server)
|
||||||
|
- **Database:** `azcompu_matomo`
|
||||||
|
- **User:** `azcompu_matomo`
|
||||||
|
- **Password:** `Mat0mo2026!CGS`
|
||||||
|
|
||||||
|
### Tracked Sites
|
||||||
|
| Site ID | Name | URL | Tracking Method |
|
||||||
|
|---------|------|-----|-----------------|
|
||||||
|
| 1 | AZ Computer Guru | https://azcomputerguru.com | WordPress mu-plugin (`wp-content/mu-plugins/matomo-tracking.php`) |
|
||||||
|
| 2 | Community Forum | https://community.azcomputerguru.com | Flarum `custom_header` DB setting |
|
||||||
|
| 3 | Radio Show | https://radio.azcomputerguru.com | Injected into HTML files before `</head>` |
|
||||||
|
|
||||||
|
### Cron
|
||||||
|
- Archiving cron runs every 5 minutes as `azcomputerguru` user
|
||||||
|
- Command: `php /home/azcomputerguru/public_html/analytics/console core:archive`
|
||||||
|
|
||||||
|
### Cloudflare
|
||||||
|
- DNS record points to 72.194.62.5, proxied (orange cloud)
|
||||||
|
- Was previously pointing to wrong IP (52.52.94.202), fixed 2026-03-20
|
||||||
|
|
||||||
|
**How to apply:** Use this when managing analytics, adding new sites to track, or troubleshooting tracking code.
|
||||||
7
.claude/memory/reference_neptune_access_d2testnas.md
Normal file
7
.claude/memory/reference_neptune_access_d2testnas.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
name: Neptune Access via D2TESTNAS
|
||||||
|
description: Neptune Exchange server must be accessed by routing through D2TESTNAS (not direct VPN)
|
||||||
|
type: reference
|
||||||
|
---
|
||||||
|
|
||||||
|
Neptune (neptune.acghosting.com / 172.16.3.11) must be accessed by routing through D2TESTNAS, not via direct VPN connection.
|
||||||
23
.claude/memory/reference_radio_website.md
Normal file
23
.claude/memory/reference_radio_website.md
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
name: Radio Show Website
|
||||||
|
description: The Computer Guru Show website at radio.azcomputerguru.com - Astro static site on IX server cPanel
|
||||||
|
type: reference
|
||||||
|
---
|
||||||
|
|
||||||
|
## Radio Show Website
|
||||||
|
|
||||||
|
- **URL:** https://radio.azcomputerguru.com
|
||||||
|
- **Platform:** Astro 6.0.4 (static site generator)
|
||||||
|
- **Server:** IX server (172.16.3.10), cPanel account `azcomputerguru`
|
||||||
|
- **Document Root:** `/home/azcomputerguru/public_html/radio`
|
||||||
|
- **Source Code:** `projects/radio-show/website/` in ClaudeTools repo
|
||||||
|
- **Build:** `cd projects/radio-show/website && npm run build` produces `dist/` folder
|
||||||
|
- **Deploy:** rsync/SCP `dist/` contents to document root on IX server
|
||||||
|
|
||||||
|
### Community Link
|
||||||
|
- The community page (`/community`) links to:
|
||||||
|
- Discord server (placeholder, WidgetBot)
|
||||||
|
- Flarum forum at https://community.azcomputerguru.com
|
||||||
|
- Newsletter signup (placeholder)
|
||||||
|
|
||||||
|
**How to apply:** Use when deploying website updates or managing the radio show project.
|
||||||
35
.claude/memory/reference_workstation_setup.md
Normal file
35
.claude/memory/reference_workstation_setup.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
name: CachyOS Workstation Setup
|
||||||
|
description: Current workstation config - CachyOS on ASUS laptop, dual NVMe, autostart apps, old home btrfs subvolume location
|
||||||
|
type: reference
|
||||||
|
---
|
||||||
|
|
||||||
|
## Workstation: acg-guru-5070
|
||||||
|
|
||||||
|
- **OS:** CachyOS (Arch-based), kernel 6.19.x
|
||||||
|
- **DE:** KDE Plasma 6 (Wayland)
|
||||||
|
- **CPU/GPU:** Intel Arrow Lake-S + NVIDIA RTX 5070 Ti Mobile
|
||||||
|
- **Tailscale IP:** 100.95.216.79
|
||||||
|
|
||||||
|
### Storage
|
||||||
|
- **nvme0n1:** 954GB btrfs - CachyOS install (OS, root)
|
||||||
|
- **nvme1n1:** 954GB ext4 - `/home` (formatted from old Windows drive)
|
||||||
|
- **Old home:** btrfs `@home` subvolume on nvme0n1, mount with: `sudo mount -o subvol=@home UUID=8a8b1d34-99fb-470f-82ca-b5d08e43ec32 /mnt/old-home`
|
||||||
|
|
||||||
|
### Autostart Apps (~/.config/autostart/)
|
||||||
|
- `arch-update-tray.desktop` (pre-existing)
|
||||||
|
- `cachyos-hello.desktop` (pre-existing)
|
||||||
|
- `discord.desktop` (added, starts minimized)
|
||||||
|
- `tailscale-systray.desktop` (added)
|
||||||
|
- ScreenConnect: autostart removed (on-demand only via URI scheme handler from web UI)
|
||||||
|
|
||||||
|
### Known Issues
|
||||||
|
- **Warm reboot hangs:** Rebooting (e.g. for GPU issues) causes system to hang with spinning symbol — requires hard power-off. Observed multiple times. Likely NVIDIA driver not unloading cleanly during shutdown.
|
||||||
|
|
||||||
|
### Key Fixes Applied
|
||||||
|
- **Tailscale:** `--accept-routes`, systemd-resolved + NetworkManager DNS config
|
||||||
|
- **Brightness:** Hide nvidia_0 backlight via udev rule, KDE controls intel_backlight only
|
||||||
|
- **ScreenConnect:** dpkg + full JRE + Wayland patch (GDK_BACKEND=x11)
|
||||||
|
- **Sudo:** NOPASSWD for guru user
|
||||||
|
|
||||||
|
**How to apply:** Reference when troubleshooting workstation issues or setting up additional services.
|
||||||
222
.claude/skills/1password/references/integrations.md
Normal file
222
.claude/skills/1password/references/integrations.md
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
# 1Password Integration Patterns
|
||||||
|
|
||||||
|
Common patterns for integrating 1Password with developer tools and AI workflows.
|
||||||
|
|
||||||
|
## Claude Code / Claude Desktop
|
||||||
|
|
||||||
|
### Claude Desktop MCP Config
|
||||||
|
|
||||||
|
Store API keys securely and reference them in `claude_desktop_config.json`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Store the key
|
||||||
|
op item create --category API_CREDENTIAL --title "My MCP Server" \
|
||||||
|
--vault Dev api_key[password]=your-key-here
|
||||||
|
|
||||||
|
# Get the secret reference
|
||||||
|
# op://Dev/My MCP Server/api_key
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"my-server": {
|
||||||
|
"command": "op",
|
||||||
|
"args": ["run", "--", "node", "/path/to/server.js"],
|
||||||
|
"env": {
|
||||||
|
"API_KEY": "op://Dev/My MCP Server/api_key"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Claude Code Shell Environment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# .env.tpl (safe to commit — no real secrets)
|
||||||
|
ANTHROPIC_API_KEY=op://Dev/Anthropic/api_key
|
||||||
|
OPENAI_API_KEY=op://Dev/OpenAI/api_key
|
||||||
|
|
||||||
|
# ✅ Wrap claude with op run — secrets injected into subprocess only
|
||||||
|
op run --env-file=.env.tpl -- claude
|
||||||
|
|
||||||
|
# ✅ Or export individually for interactive shell use
|
||||||
|
export ANTHROPIC_API_KEY=$(op read "op://Dev/Anthropic/api_key")
|
||||||
|
claude
|
||||||
|
```
|
||||||
|
|
||||||
|
### In CLAUDE.md (project secrets reference)
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Secrets Setup
|
||||||
|
Secrets are managed via 1Password. Run before working:
|
||||||
|
```bash
|
||||||
|
op run --env-file=.env.tpl -- claude
|
||||||
|
```
|
||||||
|
Do NOT commit `.env` — commit `.env.tpl` only.
|
||||||
|
```
|
||||||
|
|
||||||
|
## n8n
|
||||||
|
|
||||||
|
### Environment Injection at Startup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# n8n.env.tpl (commit this)
|
||||||
|
N8N_ENCRYPTION_KEY=op://Dev/n8n/encryption_key
|
||||||
|
DB_POSTGRESDB_PASSWORD=op://Dev/n8n-postgres/password
|
||||||
|
N8N_BASIC_AUTH_PASSWORD=op://Dev/n8n/basic_auth_password
|
||||||
|
|
||||||
|
# docker-compose.yml startup
|
||||||
|
op run --env-file=n8n.env.tpl -- docker compose up -d n8n
|
||||||
|
```
|
||||||
|
|
||||||
|
### n8n Credential Storage via API
|
||||||
|
|
||||||
|
Use n8n's credential API to push secrets from 1Password into n8n:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Get secret from 1Password
|
||||||
|
API_KEY=$(op read "op://Dev/Some Service/api_key")
|
||||||
|
|
||||||
|
# Push to n8n credential (HTTP Request)
|
||||||
|
curl -s -X POST "https://n8n.example.com/api/v1/credentials" \
|
||||||
|
-H "X-N8N-API-KEY: $(op read 'op://Dev/n8n/api_key')" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"name\": \"Service Credential\", \"type\": \"httpHeaderAuth\", \"data\": {\"name\": \"Authorization\", \"value\": \"Bearer $API_KEY\"}}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Docker / Docker Compose
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.yml
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: myapp:latest
|
||||||
|
environment:
|
||||||
|
DATABASE_URL: ${DATABASE_URL}
|
||||||
|
API_KEY: ${API_KEY}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# .env.tpl
|
||||||
|
DATABASE_URL=op://Dev/Postgres/connection_string
|
||||||
|
API_KEY=op://Dev/MyApp/api_key
|
||||||
|
|
||||||
|
# Start with injection
|
||||||
|
op run --env-file=.env.tpl -- docker compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
## Python Scripts
|
||||||
|
|
||||||
|
```python
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def get_secret(reference: str) -> str:
|
||||||
|
"""Read a secret from 1Password using a secret reference."""
|
||||||
|
result = subprocess.run(
|
||||||
|
["op", "read", reference],
|
||||||
|
capture_output=True, text=True, check=True
|
||||||
|
)
|
||||||
|
return result.stdout.strip()
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
api_key = get_secret("op://Dev/Anthropic/api_key")
|
||||||
|
```
|
||||||
|
|
||||||
|
Or using the 1Password Python SDK (if available):
|
||||||
|
```bash
|
||||||
|
pip install onepassword-sdk
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
import asyncio
|
||||||
|
import onepassword
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
client = await onepassword.Client.authenticate(
|
||||||
|
auth=os.environ["OP_SERVICE_ACCOUNT_TOKEN"],
|
||||||
|
integration_name="My Script",
|
||||||
|
integration_version="1.0.0",
|
||||||
|
)
|
||||||
|
secret = await client.secrets.resolve("op://Dev/Anthropic/api_key")
|
||||||
|
```
|
||||||
|
|
||||||
|
## GitHub Actions / CI
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# .github/workflows/deploy.yml
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: 1password/load-secrets-action@v2
|
||||||
|
with:
|
||||||
|
export-env: true
|
||||||
|
env:
|
||||||
|
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
|
||||||
|
ANTHROPIC_API_KEY: op://Dev/Anthropic/api_key
|
||||||
|
DEPLOY_KEY: op://Dev/Deploy/private_key
|
||||||
|
|
||||||
|
- run: deploy-script.sh # ANTHROPIC_API_KEY is available
|
||||||
|
```
|
||||||
|
|
||||||
|
## Shell / .zshrc Auto-Load
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ~/.zshrc
|
||||||
|
# Auto-load common dev secrets on shell start (optional — only if you trust your machine)
|
||||||
|
load_dev_secrets() {
|
||||||
|
if command -v op &>/dev/null && op whoami &>/dev/null 2>&1; then
|
||||||
|
source <(op run --env-file=~/.config/dev.env.tpl -- env 2>/dev/null) && \
|
||||||
|
echo "✅ Dev secrets loaded from 1Password"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Call explicitly when needed:
|
||||||
|
alias load-secrets='load_dev_secrets'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Supabase
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Store Supabase credentials
|
||||||
|
op item create --category API_CREDENTIAL --title "Supabase - My Project" \
|
||||||
|
--vault Dev \
|
||||||
|
url[text]=https://myproject.supabase.co \
|
||||||
|
anon_key[password]=eyJ... \
|
||||||
|
service_key[password]=eyJ...
|
||||||
|
|
||||||
|
# Use in scripts
|
||||||
|
SUPABASE_URL=$(op read "op://Dev/Supabase - My Project/url")
|
||||||
|
SUPABASE_KEY=$(op read "op://Dev/Supabase - My Project/service_key")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Replit
|
||||||
|
|
||||||
|
Replit has its own Secrets manager, but for local dev before deploying:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Generate a .env from 1Password, then paste values into Replit Secrets UI
|
||||||
|
op run --env-file=.env.tpl -- env | grep -E "^(ANTHROPIC|SUPABASE|N8N)"
|
||||||
|
# Copy output values → paste into Replit Secrets one by one
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rotation Workflow
|
||||||
|
|
||||||
|
When rotating a credential:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Update in the service (get new key)
|
||||||
|
NEW_KEY="new-key-from-service"
|
||||||
|
|
||||||
|
# 2. Update in 1Password
|
||||||
|
op item edit "Service Name" api_key[password]="$NEW_KEY"
|
||||||
|
|
||||||
|
# 3. Verify
|
||||||
|
op read "op://Dev/Service Name/api_key"
|
||||||
|
|
||||||
|
# 4. Re-inject wherever used
|
||||||
|
source <(op run --env-file=.env.tpl -- env)
|
||||||
|
# Or restart services that use the key
|
||||||
|
```
|
||||||
171
.claude/skills/1password/references/op_commands.md
Normal file
171
.claude/skills/1password/references/op_commands.md
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
# 1Password CLI (op) Command Reference
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Sign in (interactive)
|
||||||
|
op signin
|
||||||
|
|
||||||
|
# Sign in to specific account
|
||||||
|
op signin --account team-name.1password.com
|
||||||
|
|
||||||
|
# Check who you're signed in as
|
||||||
|
op whoami
|
||||||
|
|
||||||
|
# List accounts
|
||||||
|
op account list
|
||||||
|
|
||||||
|
# Service account (CI/CD — set env var, no signin needed)
|
||||||
|
export OP_SERVICE_ACCOUNT_TOKEN="your-token"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Items
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List items
|
||||||
|
op item list
|
||||||
|
op item list --vault Dev
|
||||||
|
op item list --categories API_CREDENTIAL
|
||||||
|
|
||||||
|
# Get item details
|
||||||
|
op item get "Item Title"
|
||||||
|
op item get "Item Title" --vault Dev
|
||||||
|
op item get "Item Title" --format json
|
||||||
|
|
||||||
|
# Get a specific field
|
||||||
|
op item get "Item Title" --fields api_key
|
||||||
|
op item get "Item Title" --fields label=api_key
|
||||||
|
|
||||||
|
# Read using secret reference (most common)
|
||||||
|
op read "op://Dev/Item Title/api_key"
|
||||||
|
|
||||||
|
# Create item
|
||||||
|
op item create --category API_CREDENTIAL --title "My API Key" api_key[password]=sk-abc123
|
||||||
|
op item create --category LOGIN --title "Service Account" --vault Dev \
|
||||||
|
username[text]=myuser password[password]=mypass
|
||||||
|
|
||||||
|
# Edit/update item
|
||||||
|
op item edit "Item Title" api_key[password]=new-value
|
||||||
|
op item edit "Item Title" --vault Dev new_field[text]=value
|
||||||
|
|
||||||
|
# Delete item
|
||||||
|
op item delete "Item Title"
|
||||||
|
op item delete "Item Title" --vault Dev
|
||||||
|
|
||||||
|
# Move item to different vault
|
||||||
|
op item move "Item Title" --current-vault Dev --destination-vault Personal
|
||||||
|
```
|
||||||
|
|
||||||
|
## Vaults
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List vaults
|
||||||
|
op vault list
|
||||||
|
op vault list --format json
|
||||||
|
|
||||||
|
# Create vault
|
||||||
|
op vault create "New Vault"
|
||||||
|
|
||||||
|
# Get vault details
|
||||||
|
op vault get "Vault Name"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Secrets Injection
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run command with secrets from .env template (RECOMMENDED)
|
||||||
|
op run --env-file=.env.tpl -- your-command arg1 arg2
|
||||||
|
|
||||||
|
# Inject into Docker
|
||||||
|
op run --env-file=.env.tpl -- docker compose up
|
||||||
|
|
||||||
|
# Inject a single reference via env var (op run picks up op:// values automatically)
|
||||||
|
export API_KEY="op://Dev/MyApp/api_key"
|
||||||
|
op run -- node app.js # API_KEY is resolved at runtime
|
||||||
|
|
||||||
|
# ⚠️ AVOID: sourcing op run output into the current shell
|
||||||
|
# source <(op run --env-file=.env.tpl -- env) ← UNSAFE
|
||||||
|
# If secret values contain $(...) or backticks, they execute as shell code.
|
||||||
|
# Use 'op run -- your-command' instead (secrets stay in subprocess only).
|
||||||
|
```
|
||||||
|
|
||||||
|
## Password Generation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Generate at item creation time (no standalone command)
|
||||||
|
op item create --category PASSWORD --title "Generated Secret" \
|
||||||
|
--generate-password='letters,digits,symbols,32'
|
||||||
|
|
||||||
|
# Generate with custom recipe
|
||||||
|
op item create --category LOGIN --title "My Login" \
|
||||||
|
--generate-password='letters,digits,20'
|
||||||
|
|
||||||
|
# Or use openssl for scripted generation
|
||||||
|
openssl rand -base64 32 | tr -d '=+/'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Document / File Management
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Store a file
|
||||||
|
op document create ./private-key.pem --title "SSH Private Key" --vault Dev
|
||||||
|
|
||||||
|
# Get a file
|
||||||
|
op document get "SSH Private Key" --output ./private-key.pem
|
||||||
|
|
||||||
|
# List documents
|
||||||
|
op document list
|
||||||
|
```
|
||||||
|
|
||||||
|
## Service Accounts (CI/CD)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create service account (in 1Password UI: Settings → Developer → Service Accounts)
|
||||||
|
# Then set token as env var:
|
||||||
|
export OP_SERVICE_ACCOUNT_TOKEN="ops_eyJ..."
|
||||||
|
|
||||||
|
# No signin needed — op commands work automatically
|
||||||
|
op item list # works with service account token
|
||||||
|
op read "op://vault/item/field"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Connect (Self-hosted, advanced)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# For teams running 1Password Connect server
|
||||||
|
export OP_CONNECT_HOST="https://your-connect-server"
|
||||||
|
export OP_CONNECT_TOKEN="your-connect-token"
|
||||||
|
|
||||||
|
# Then op commands use Connect instead of 1Password.com
|
||||||
|
op item get "Item Title"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output Formats
|
||||||
|
|
||||||
|
Valid values: `json` or `human-readable` (default).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
op item list --format=json # Machine-readable JSON
|
||||||
|
op item get "Item" --format=json # Full item JSON
|
||||||
|
op item list # Human-readable (default)
|
||||||
|
op vault list --format=json # Vaults as JSON
|
||||||
|
```
|
||||||
|
|
||||||
|
## Useful Patterns
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Find item by field value (search)
|
||||||
|
op item list --format=json | \
|
||||||
|
python3 -c "import sys,json; [print(i['title']) for i in json.load(sys.stdin)]"
|
||||||
|
|
||||||
|
# Export all items in a vault to JSON (backup)
|
||||||
|
op item list --vault Dev --format=json | \
|
||||||
|
python3 -c "import sys,json; ids=[i['id'] for i in json.load(sys.stdin)]"
|
||||||
|
# (then loop to get each)
|
||||||
|
|
||||||
|
# Check if a specific item exists
|
||||||
|
op item get "My Item" &>/dev/null && echo "exists" || echo "not found"
|
||||||
|
|
||||||
|
# Get item ID (for scripting)
|
||||||
|
op item get "My Item" --format=json | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])"
|
||||||
|
```
|
||||||
120
.claude/skills/1password/references/secret_references.md
Normal file
120
.claude/skills/1password/references/secret_references.md
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
# 1Password Secret References
|
||||||
|
|
||||||
|
Secret references are the safest way to use secrets — they point to 1Password without exposing actual values in code or config files.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
```
|
||||||
|
op://vault/item/field
|
||||||
|
op://vault/item/section/field
|
||||||
|
```
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
```bash
|
||||||
|
op://Dev/Anthropic/api_key
|
||||||
|
op://Personal/AWS/access_key_id
|
||||||
|
op://Dev/Supabase/section/service_key
|
||||||
|
```
|
||||||
|
|
||||||
|
## Reading a Secret Reference
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Single secret
|
||||||
|
op read "op://Dev/Anthropic/api_key"
|
||||||
|
|
||||||
|
# Into a variable
|
||||||
|
export ANTHROPIC_API_KEY=$(op read "op://Dev/Anthropic/api_key")
|
||||||
|
|
||||||
|
# Multiple secrets via op run
|
||||||
|
op run --env-file=.env.tpl -- your-command
|
||||||
|
```
|
||||||
|
|
||||||
|
## .env Template Files
|
||||||
|
|
||||||
|
Store references in a `.env.tpl` file (safe to commit to **private** repos):
|
||||||
|
|
||||||
|
> **Privacy note:** `.env.tpl` contains your vault names, item names, and field names —
|
||||||
|
> e.g. `op://Dev/Anthropic/api_key`. This reveals the structure of your 1Password vault
|
||||||
|
> to anyone who can read the file. For **private repos**, this is fine. For **public repos**,
|
||||||
|
> consider whether your vault/item naming reveals anything sensitive (client names, internal
|
||||||
|
> service names, etc.). Real secret values are never exposed — only the structure.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# .env.tpl — commit this
|
||||||
|
ANTHROPIC_API_KEY=op://Dev/Anthropic/api_key
|
||||||
|
N8N_API_KEY=op://Dev/n8n/api_key
|
||||||
|
SUPABASE_SERVICE_KEY=op://Dev/Supabase/service_key
|
||||||
|
NOTION_TOKEN=op://Dev/Notion/api_token
|
||||||
|
```
|
||||||
|
|
||||||
|
Then inject at runtime:
|
||||||
|
```bash
|
||||||
|
# ✅ RECOMMENDED — run your command with secrets injected into subprocess only
|
||||||
|
op run --env-file=.env.tpl -- npm start
|
||||||
|
op run --env-file=.env.tpl -- node server.js
|
||||||
|
op run --env-file=.env.tpl -- docker compose up
|
||||||
|
|
||||||
|
# ✅ OK — read a single secret into a variable for immediate use
|
||||||
|
export ANTHROPIC_API_KEY=$(op read "op://Dev/Anthropic/api_key")
|
||||||
|
|
||||||
|
# ⚠️ AVOID — sourcing op run output exposes secrets in current shell
|
||||||
|
# and is unsafe if any secret value contains shell metacharacters like $(...):
|
||||||
|
# source <(op run --env-file=.env.tpl -- env) ← DON'T DO THIS
|
||||||
|
|
||||||
|
# ⚠️ AVOID — writing resolved secrets to disk (don't commit .env)
|
||||||
|
# op run --env-file=.env.tpl -- env > .env ← only if truly necessary
|
||||||
|
```
|
||||||
|
|
||||||
|
## In Config Files
|
||||||
|
|
||||||
|
Claude Desktop (`claude_desktop_config.json`):
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"my-server": {
|
||||||
|
"command": "op",
|
||||||
|
"args": ["run", "--", "node", "server.js"],
|
||||||
|
"env": {
|
||||||
|
"API_KEY": "op://Dev/MyServer/api_key"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Docker Compose:
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: myapp
|
||||||
|
environment:
|
||||||
|
- DATABASE_URL=op://Dev/Postgres/connection_string
|
||||||
|
```
|
||||||
|
Run with: `op run -- docker compose up`
|
||||||
|
|
||||||
|
n8n (environment injection):
|
||||||
|
```bash
|
||||||
|
# In your n8n startup script
|
||||||
|
op run --env-file=n8n.env.tpl -- docker compose up n8n
|
||||||
|
```
|
||||||
|
|
||||||
|
## Finding Field Names
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all fields in an item
|
||||||
|
op item get "Item Name" --format=json | \
|
||||||
|
python3 -c "import sys,json; [print(f['label']) for f in json.load(sys.stdin)['fields'] if f.get('value')]"
|
||||||
|
|
||||||
|
# Or view interactively
|
||||||
|
op item get "Item Name"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Field Names by Category
|
||||||
|
|
||||||
|
| Category | Common Fields |
|
||||||
|
|----------|---------------|
|
||||||
|
| API_CREDENTIAL | `api_key`, `credential`, `token` |
|
||||||
|
| LOGIN | `username`, `password` |
|
||||||
|
| DATABASE | `connection_string`, `host`, `port`, `username`, `password` |
|
||||||
|
| SECURE_NOTE | `notesPlain` |
|
||||||
|
| SERVER | `hostname`, `port`, `username`, `password` |
|
||||||
75
.claude/skills/1password/scripts/check_setup.sh
Executable file
75
.claude/skills/1password/scripts/check_setup.sh
Executable file
@@ -0,0 +1,75 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# check_setup.sh — Verify 1Password CLI is installed and authenticated
|
||||||
|
# Usage: bash check_setup.sh
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PASS=0
|
||||||
|
FAIL=0
|
||||||
|
|
||||||
|
check() {
|
||||||
|
local label="$1"
|
||||||
|
local cmd="$2"
|
||||||
|
if eval "$cmd" &>/dev/null; then
|
||||||
|
echo " ✅ $label"
|
||||||
|
((PASS++)) || true
|
||||||
|
else
|
||||||
|
echo " ❌ $label"
|
||||||
|
((FAIL++)) || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "=== 1Password CLI Setup Check ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 1. CLI installed
|
||||||
|
check "op CLI installed" "command -v op"
|
||||||
|
|
||||||
|
# 2. Version
|
||||||
|
if command -v op &>/dev/null; then
|
||||||
|
echo " ℹ️ Version: $(op --version)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "--- Authentication ---"
|
||||||
|
|
||||||
|
# 3. Signed in
|
||||||
|
check "Signed in to 1Password" "op account list 2>/dev/null | grep -q '.'"
|
||||||
|
|
||||||
|
# 4. Can list vaults
|
||||||
|
check "Can list vaults" "op vault list &>/dev/null"
|
||||||
|
|
||||||
|
# Show accounts if authenticated
|
||||||
|
if op account list &>/dev/null 2>&1; then
|
||||||
|
echo ""
|
||||||
|
echo " Accounts:"
|
||||||
|
op account list 2>/dev/null | tail -n +2 | while read -r line; do
|
||||||
|
echo " • $line"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo " Vaults:"
|
||||||
|
op vault list --format=json 2>/dev/null | \
|
||||||
|
python3 -c "import sys,json; [print(f' • {v[\"name\"]} ({v[\"id\"]})') for v in json.load(sys.stdin)]" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "--- Environment ---"
|
||||||
|
|
||||||
|
# 5. OP_SERVICE_ACCOUNT_TOKEN (CI/CD pattern)
|
||||||
|
if [[ -n "${OP_SERVICE_ACCOUNT_TOKEN:-}" ]]; then
|
||||||
|
echo " ✅ OP_SERVICE_ACCOUNT_TOKEN is set (service account mode)"
|
||||||
|
else
|
||||||
|
echo " ℹ️ OP_SERVICE_ACCOUNT_TOKEN not set (interactive/desktop app mode)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "==================================="
|
||||||
|
if [[ $FAIL -eq 0 ]]; then
|
||||||
|
echo "✅ All checks passed. 1Password CLI is ready."
|
||||||
|
else
|
||||||
|
echo "⚠️ $FAIL check(s) failed. See above."
|
||||||
|
echo ""
|
||||||
|
echo "Install: https://developer.1password.com/docs/cli/get-started/"
|
||||||
|
echo "Sign in: op signin"
|
||||||
|
fi
|
||||||
142
.claude/skills/1password/scripts/env_from_op.sh
Executable file
142
.claude/skills/1password/scripts/env_from_op.sh
Executable file
@@ -0,0 +1,142 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# env_from_op.sh — Generate a .env file from 1Password items
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# bash env_from_op.sh # Interactive: prompts for vault + items
|
||||||
|
# bash env_from_op.sh --vault Dev # Use specific vault
|
||||||
|
# bash env_from_op.sh --item "My Project" # Export all fields from one item
|
||||||
|
# bash env_from_op.sh --output .env # Write to file (default: .env)
|
||||||
|
# bash env_from_op.sh --dry-run # Print without writing
|
||||||
|
#
|
||||||
|
# Output format:
|
||||||
|
# FIELD_NAME=op://Vault/Item/field # Secret references (safest)
|
||||||
|
# FIELD_NAME=actual_value # Resolved values (with --resolve)
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
VAULT=""
|
||||||
|
ITEM=""
|
||||||
|
OUTPUT=".env"
|
||||||
|
DRY_RUN=false
|
||||||
|
RESOLVE=false
|
||||||
|
|
||||||
|
# Parse args
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--vault) VAULT="$2"; shift 2 ;;
|
||||||
|
--item) ITEM="$2"; shift 2 ;;
|
||||||
|
--output) OUTPUT="$2"; shift 2 ;;
|
||||||
|
--dry-run) DRY_RUN=true; shift ;;
|
||||||
|
--resolve) RESOLVE=true; shift ;;
|
||||||
|
*) echo "Unknown option: $1"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check op is available
|
||||||
|
if ! command -v op &>/dev/null; then
|
||||||
|
echo "❌ 1Password CLI (op) not found. Install: https://developer.1password.com/docs/cli/get-started/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If no item specified, list items and prompt
|
||||||
|
if [[ -z "$ITEM" ]]; then
|
||||||
|
echo "Available items in vault '${VAULT:-all vaults}':"
|
||||||
|
if [[ -n "$VAULT" ]]; then
|
||||||
|
op item list --vault "$VAULT" --format=json | \
|
||||||
|
python3 -c "import sys,json; [print(f' {i[\"title\"]}') for i in json.load(sys.stdin)]"
|
||||||
|
else
|
||||||
|
op item list --format=json | \
|
||||||
|
python3 -c "import sys,json; [print(f' [{i[\"vault\"][\"name\"]}] {i[\"title\"]}') for i in json.load(sys.stdin)]"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
read -rp "Enter item title: " ITEM
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Fetching '${ITEM}' from 1Password..."
|
||||||
|
|
||||||
|
# Get item as JSON
|
||||||
|
if [[ -n "$VAULT" ]]; then
|
||||||
|
ITEM_JSON=$(op item get "$ITEM" --vault "$VAULT" --format=json)
|
||||||
|
else
|
||||||
|
ITEM_JSON=$(op item get "$ITEM" --format=json)
|
||||||
|
fi
|
||||||
|
|
||||||
|
VAULT_NAME=$(echo "$ITEM_JSON" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['vault']['name'])")
|
||||||
|
ITEM_TITLE=$(echo "$ITEM_JSON" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['title'])")
|
||||||
|
|
||||||
|
# Build .env content
|
||||||
|
ENV_CONTENT=$(echo "$ITEM_JSON" | python3 - <<'PYEOF'
|
||||||
|
import sys, json, re
|
||||||
|
|
||||||
|
data = json.load(sys.stdin)
|
||||||
|
vault = data['vault']['name']
|
||||||
|
title = data['title']
|
||||||
|
lines = []
|
||||||
|
|
||||||
|
SKIP_LABELS = {'username', 'password', 'notesPlain', 'notes'}
|
||||||
|
SKIP_TYPES = {'CONCEALED'} if False else set() # resolved mode: don't skip
|
||||||
|
|
||||||
|
for field in data.get('fields', []):
|
||||||
|
label = field.get('label', '')
|
||||||
|
value = field.get('value', '')
|
||||||
|
field_id = field.get('id', '')
|
||||||
|
ftype = field.get('type', '')
|
||||||
|
|
||||||
|
# Skip empty, metadata, or UI-only fields
|
||||||
|
if not value or not label:
|
||||||
|
continue
|
||||||
|
if label.lower() in {'username', 'notesplain', 'notes', 'password'} and ftype not in {'CONCEALED', 'URL'}:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Convert label to ENV_VAR format
|
||||||
|
env_key = re.sub(r'[^A-Z0-9_]', '_', label.upper().replace(' ', '_').replace('-', '_'))
|
||||||
|
env_key = re.sub(r'_+', '_', env_key).strip('_')
|
||||||
|
|
||||||
|
# Use secret reference (safer than raw value)
|
||||||
|
ref = f"op://{vault}/{title}/{label}"
|
||||||
|
lines.append(f"{env_key}={ref}")
|
||||||
|
|
||||||
|
print('\n'.join(lines))
|
||||||
|
PYEOF
|
||||||
|
)
|
||||||
|
|
||||||
|
# Handle resolve flag — replace refs with real values
|
||||||
|
if $RESOLVE; then
|
||||||
|
echo "⚠️ Writing resolved values (actual secrets). Handle carefully."
|
||||||
|
FINAL_CONTENT=""
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if [[ "$line" =~ ^([A-Z_]+)=(op://.+)$ ]]; then
|
||||||
|
key="${BASH_REMATCH[1]}"
|
||||||
|
ref="${BASH_REMATCH[2]}"
|
||||||
|
value=$(op read "$ref" 2>/dev/null || echo "ERROR_READING")
|
||||||
|
FINAL_CONTENT+="${key}=${value}"$'\n'
|
||||||
|
else
|
||||||
|
FINAL_CONTENT+="$line"$'\n'
|
||||||
|
fi
|
||||||
|
done <<< "$ENV_CONTENT"
|
||||||
|
ENV_CONTENT="$FINAL_CONTENT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Header
|
||||||
|
HEADER="# Generated from 1Password: ${VAULT_NAME}/${ITEM_TITLE}
|
||||||
|
# Generated: $(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||||
|
# Load with: op run --env-file=.env -- <command>
|
||||||
|
# or: eval \$(op run --env-file=.env -- env | grep KEY)
|
||||||
|
|
||||||
|
"
|
||||||
|
|
||||||
|
FULL_CONTENT="${HEADER}${ENV_CONTENT}"
|
||||||
|
|
||||||
|
if $DRY_RUN; then
|
||||||
|
echo ""
|
||||||
|
echo "--- .env preview ---"
|
||||||
|
echo "$FULL_CONTENT"
|
||||||
|
echo "--- end ---"
|
||||||
|
else
|
||||||
|
echo "$FULL_CONTENT" > "$OUTPUT"
|
||||||
|
echo "✅ Written to $OUTPUT (${#ENV_CONTENT} chars, $(echo "$ENV_CONTENT" | grep -c '=' || true) vars)"
|
||||||
|
echo ""
|
||||||
|
echo "To use:"
|
||||||
|
echo " op run --env-file=$OUTPUT -- your-command"
|
||||||
|
echo " source <(op run --env-file=$OUTPUT -- env)"
|
||||||
|
fi
|
||||||
52
.claude/skills/1password/scripts/launch-in-terminal.sh
Executable file
52
.claude/skills/1password/scripts/launch-in-terminal.sh
Executable file
@@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# launch-in-terminal.sh — Open a script in a NEW Terminal.app window
|
||||||
|
#
|
||||||
|
# This is how the 1Password skill keeps secrets OUT of Claude Code.
|
||||||
|
# Claude generates the script, then calls this launcher.
|
||||||
|
# The script runs in Terminal.app — Claude never sees what you type.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# bash launch-in-terminal.sh /path/to/script.sh
|
||||||
|
# bash launch-in-terminal.sh /path/to/script.sh "window title"
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_PATH="${1:-}"
|
||||||
|
TITLE="${2:-1Password Setup}"
|
||||||
|
|
||||||
|
if [[ -z "$SCRIPT_PATH" ]]; then
|
||||||
|
echo "Usage: bash launch-in-terminal.sh /path/to/script.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "$SCRIPT_PATH" ]]; then
|
||||||
|
echo "❌ Script not found: $SCRIPT_PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod +x "$SCRIPT_PATH"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo " Opening Terminal.app to collect secrets"
|
||||||
|
echo " Script: $SCRIPT_PATH"
|
||||||
|
echo ""
|
||||||
|
echo " ⚠️ Type your secrets in the Terminal"
|
||||||
|
echo " window that is about to open."
|
||||||
|
echo " Claude Code cannot see that window."
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
osascript <<APPLESCRIPT
|
||||||
|
tell application "Terminal"
|
||||||
|
activate
|
||||||
|
set newTab to do script "echo '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'; echo ' ${TITLE}'; echo ' Type secrets here — Claude Code cannot see this window'; echo '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'; echo ''; bash ${SCRIPT_PATH}"
|
||||||
|
end tell
|
||||||
|
APPLESCRIPT
|
||||||
|
|
||||||
|
echo "✅ Terminal.app opened. Complete the prompts there, then return here."
|
||||||
|
echo " (This window will wait for you to press Enter when done)"
|
||||||
|
echo ""
|
||||||
|
read -rp "Press Enter once you've finished in Terminal.app... "
|
||||||
|
echo ""
|
||||||
|
echo "Continuing..."
|
||||||
124
.claude/skills/1password/scripts/store-mcp-credentials.sh
Executable file
124
.claude/skills/1password/scripts/store-mcp-credentials.sh
Executable file
@@ -0,0 +1,124 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# store-mcp-credentials.sh — Store MCP server credentials in 1Password
|
||||||
|
#
|
||||||
|
# ⚠️ RUN THIS IN TERMINAL.APP — NOT IN CLAUDE CODE
|
||||||
|
# Claude Code can see everything typed in its terminal.
|
||||||
|
# Open Terminal.app separately, then run this script.
|
||||||
|
#
|
||||||
|
# Usage (Claude will generate a pre-filled version for you):
|
||||||
|
# bash store-mcp-credentials.sh \
|
||||||
|
# --vault Dev \
|
||||||
|
# --item "My MCP Server" \
|
||||||
|
# --set "url=https://api.example.com" \
|
||||||
|
# --set "log_level=error" \
|
||||||
|
# --secret "api_key" \
|
||||||
|
# --secret "webhook_secret"
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# --vault 1Password vault name (default: Dev)
|
||||||
|
# --item Item title in 1Password
|
||||||
|
# --set Non-secret field: key=value (pre-filled, visible)
|
||||||
|
# --secret Secret field: prompted with hidden input
|
||||||
|
# --update Update existing item instead of creating new
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
VAULT="Dev"
|
||||||
|
ITEM=""
|
||||||
|
UPDATE=false
|
||||||
|
declare -a SET_FIELDS=()
|
||||||
|
declare -a SECRET_FIELDS=()
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--vault) VAULT="$2"; shift 2 ;;
|
||||||
|
--item) ITEM="$2"; shift 2 ;;
|
||||||
|
--set) SET_FIELDS+=("$2"); shift 2 ;;
|
||||||
|
--secret) SECRET_FIELDS+=("$2"); shift 2 ;;
|
||||||
|
--update) UPDATE=true; shift ;;
|
||||||
|
*) echo "Unknown option: $1"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$ITEM" ]]; then
|
||||||
|
read -rp "Item title in 1Password: " ITEM
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo " Storing: $ITEM"
|
||||||
|
echo " Vault: $VAULT"
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Show pre-filled fields
|
||||||
|
if [[ ${#SET_FIELDS[@]} -gt 0 ]]; then
|
||||||
|
echo "Pre-filled fields:"
|
||||||
|
for field in "${SET_FIELDS[@]}"; do
|
||||||
|
key="${field%%=*}"
|
||||||
|
val="${field#*=}"
|
||||||
|
echo " $key = $val"
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prompt for secret fields
|
||||||
|
declare -a SECRET_VALUES=()
|
||||||
|
if [[ ${#SECRET_FIELDS[@]} -gt 0 ]]; then
|
||||||
|
echo "Enter secret values (input is hidden):"
|
||||||
|
for field in "${SECRET_FIELDS[@]}"; do
|
||||||
|
read -rsp " $field: " secret_val
|
||||||
|
echo ""
|
||||||
|
SECRET_VALUES+=("${field}[password]=${secret_val}")
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build op field args for non-secret fields
|
||||||
|
declare -a OP_FIELDS=()
|
||||||
|
for field in "${SET_FIELDS[@]}"; do
|
||||||
|
key="${field%%=*}"
|
||||||
|
val="${field#*=}"
|
||||||
|
OP_FIELDS+=("${key}[text]=${val}")
|
||||||
|
done
|
||||||
|
|
||||||
|
# Combine all fields
|
||||||
|
ALL_FIELDS=("${OP_FIELDS[@]+"${OP_FIELDS[@]}"}" "${SECRET_VALUES[@]+"${SECRET_VALUES[@]}"}")
|
||||||
|
|
||||||
|
echo "Saving to 1Password..."
|
||||||
|
|
||||||
|
if $UPDATE; then
|
||||||
|
op item edit "$ITEM" --vault "$VAULT" "${ALL_FIELDS[@]}"
|
||||||
|
echo ""
|
||||||
|
echo "✅ Updated '$ITEM' in vault '$VAULT'"
|
||||||
|
else
|
||||||
|
# Try create, fall back to update if already exists
|
||||||
|
if op item get "$ITEM" --vault "$VAULT" &>/dev/null 2>&1; then
|
||||||
|
echo " Item already exists — updating instead..."
|
||||||
|
op item edit "$ITEM" --vault "$VAULT" "${ALL_FIELDS[@]}"
|
||||||
|
echo ""
|
||||||
|
echo "✅ Updated '$ITEM' in vault '$VAULT'"
|
||||||
|
else
|
||||||
|
op item create \
|
||||||
|
--category API_CREDENTIAL \
|
||||||
|
--title "$ITEM" \
|
||||||
|
--vault "$VAULT" \
|
||||||
|
"${ALL_FIELDS[@]}"
|
||||||
|
echo ""
|
||||||
|
echo "✅ Created '$ITEM' in vault '$VAULT'"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Secret references for your config:"
|
||||||
|
for field in "${SET_FIELDS[@]}"; do
|
||||||
|
key="${field%%=*}"
|
||||||
|
echo " op://${VAULT}/${ITEM}/${key}"
|
||||||
|
done
|
||||||
|
for field in "${SECRET_FIELDS[@]}"; do
|
||||||
|
echo " op://${VAULT}/${ITEM}/${field}"
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo " Done. You can close this terminal."
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
91
.claude/skills/1password/scripts/store_secret.sh
Executable file
91
.claude/skills/1password/scripts/store_secret.sh
Executable file
@@ -0,0 +1,91 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# store_secret.sh — Store or update a secret in 1Password
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# bash store_secret.sh --title "My API Key" --field "api_key" --value "sk-..."
|
||||||
|
# bash store_secret.sh --title "Project Creds" --vault Dev --category API_CREDENTIAL
|
||||||
|
# bash store_secret.sh --update --title "Existing Item" --field "api_key" --value "new-value"
|
||||||
|
# bash store_secret.sh --from-env MY_VAR # Store from environment variable
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
TITLE=""
|
||||||
|
FIELD="credential"
|
||||||
|
VALUE=""
|
||||||
|
VAULT=""
|
||||||
|
CATEGORY="API_CREDENTIAL"
|
||||||
|
UPDATE=false
|
||||||
|
FROM_ENV=""
|
||||||
|
GENERATE=false
|
||||||
|
GENERATE_LENGTH=32
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--title) TITLE="$2"; shift 2 ;;
|
||||||
|
--field) FIELD="$2"; shift 2 ;;
|
||||||
|
--value) VALUE="$2"; shift 2 ;;
|
||||||
|
--vault) VAULT="$2"; shift 2 ;;
|
||||||
|
--category) CATEGORY="$2"; shift 2 ;;
|
||||||
|
--update) UPDATE=true; shift ;;
|
||||||
|
--from-env) FROM_ENV="$2"; shift 2 ;;
|
||||||
|
--generate) GENERATE=true; shift ;;
|
||||||
|
--length) GENERATE_LENGTH="$2"; shift 2 ;;
|
||||||
|
*) echo "Unknown option: $1"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Validate
|
||||||
|
if [[ -z "$TITLE" ]]; then
|
||||||
|
read -rp "Item title: " TITLE
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get value from env var if requested
|
||||||
|
if [[ -n "$FROM_ENV" ]]; then
|
||||||
|
VALUE="${!FROM_ENV:-}"
|
||||||
|
if [[ -z "$VALUE" ]]; then
|
||||||
|
echo "❌ Environment variable $FROM_ENV is not set or empty"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
FIELD="${FROM_ENV}"
|
||||||
|
echo "Using value from \$$FROM_ENV"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate a secure credential if requested
|
||||||
|
if $GENERATE; then
|
||||||
|
VALUE=$(openssl rand -base64 "$GENERATE_LENGTH" | tr -d '=+/' | head -c "$GENERATE_LENGTH")
|
||||||
|
echo "🔐 Generated secure credential ($GENERATE_LENGTH chars)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prompt for value if still empty
|
||||||
|
if [[ -z "$VALUE" ]]; then
|
||||||
|
read -rsp "Value (hidden): " VALUE
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
VAULT_FLAG=""
|
||||||
|
[[ -n "$VAULT" ]] && VAULT_FLAG="--vault $VAULT"
|
||||||
|
|
||||||
|
if $UPDATE; then
|
||||||
|
echo "Updating '${FIELD}' in '${TITLE}'..."
|
||||||
|
op item edit "$TITLE" $VAULT_FLAG "${FIELD}[password]=${VALUE}"
|
||||||
|
echo "✅ Updated '${FIELD}' in '${TITLE}'"
|
||||||
|
else
|
||||||
|
echo "Creating '${TITLE}' in 1Password..."
|
||||||
|
RESULT=$(op item create \
|
||||||
|
--category "$CATEGORY" \
|
||||||
|
--title "$TITLE" \
|
||||||
|
$VAULT_FLAG \
|
||||||
|
"${FIELD}[password]=${VALUE}" \
|
||||||
|
--format=json)
|
||||||
|
|
||||||
|
ITEM_ID=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
|
||||||
|
VAULT_NAME=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['vault']['name'])")
|
||||||
|
|
||||||
|
echo "✅ Created '${TITLE}' (ID: ${ITEM_ID})"
|
||||||
|
echo ""
|
||||||
|
echo "Secret reference:"
|
||||||
|
echo " op://${VAULT_NAME}/${TITLE}/${FIELD}"
|
||||||
|
echo ""
|
||||||
|
echo "Read it back:"
|
||||||
|
echo " op read \"op://${VAULT_NAME}/${TITLE}/${FIELD}\""
|
||||||
|
fi
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -63,3 +63,7 @@ api/.env
|
|||||||
.mcp.json
|
.mcp.json
|
||||||
Pictures/
|
Pictures/
|
||||||
.grepai/
|
.grepai/
|
||||||
|
# Radio processor
|
||||||
|
projects/radio-show/audio-processor/test-data/*.mp3
|
||||||
|
projects/radio-show/audio-processor/*.egg-info/
|
||||||
|
|
||||||
|
|||||||
@@ -37,16 +37,16 @@ Windows> choco install git python nodejs
|
|||||||
```bash
|
```bash
|
||||||
# Windows
|
# Windows
|
||||||
Windows> cd D:\
|
Windows> cd D:\
|
||||||
Windows> git clone ssh://azcomputerguru@172.16.3.20:2222/azcomputerguru/claudetools.git ClaudeTools
|
Windows> git clone https://git.azcomputerguru.com/azcomputerguru/claudetools.git ClaudeTools
|
||||||
Windows> cd ClaudeTools
|
Windows> cd ClaudeTools
|
||||||
|
|
||||||
# Mac
|
# Mac
|
||||||
Mac> cd ~/Projects # or wherever you want it
|
Mac> cd ~/Projects # or wherever you want it
|
||||||
Mac> git clone ssh://azcomputerguru@172.16.3.20:2222/azcomputerguru/claudetools.git ClaudeTools
|
Mac> git clone https://git.azcomputerguru.com/azcomputerguru/claudetools.git ClaudeTools
|
||||||
Mac> cd ClaudeTools
|
Mac> cd ClaudeTools
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note:** You'll need SSH access to the Gitea server (172.16.3.20:2222)
|
**Note:** Uses HTTPS to Gitea at git.azcomputerguru.com
|
||||||
|
|
||||||
**For This Guide:**
|
**For This Guide:**
|
||||||
- Windows path: `D:\ClaudeTools`
|
- Windows path: `D:\ClaudeTools`
|
||||||
|
|||||||
68
STAGE-IMPORT-INSTRUCTIONS.md
Normal file
68
STAGE-IMPORT-INSTRUCTIONS.md
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# Stage TXT Import Task
|
||||||
|
# Date: 2026-03-28
|
||||||
|
# Context: CTONWTXT.BAT now uploads C:\STAGE\*.TXT from DOS machines to T:\STAGE\%MACHINE%\
|
||||||
|
|
||||||
|
## What happened
|
||||||
|
|
||||||
|
1. CTONWTXT.BAT was never being called -- fixed, now called from CTONW.BAT on every boot
|
||||||
|
2. Destination changed from broken X: (Novell serve.sys check) to T:\STAGE\%MACHINE%\
|
||||||
|
3. DOS 6.22 can't MD on existing dirs without error, so dirs are pre-created on NAS
|
||||||
|
4. All TS-* machine folders pre-created under /data/test/STAGE/ on D2TESTNAS
|
||||||
|
|
||||||
|
## What needs to run
|
||||||
|
|
||||||
|
Save the script below as C:\Shares\testdatadb\import-all-stage.js and run it:
|
||||||
|
|
||||||
|
cd C:\Shares\testdatadb
|
||||||
|
node import-all-stage.js
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
- Scans \\D2TESTNAS\test\STAGE\TS-*\*.TXT (~8,100 files across 10 machines)
|
||||||
|
- Parses each TXT datasheet (Date, Model, SN)
|
||||||
|
- Decodes hex-prefix serial numbers for 8.3 filename encoding:
|
||||||
|
- Letter prefix = hex digit: A=10, B=11, C=12, ..., H=17, etc.
|
||||||
|
- Example: H8236-12.TXT has SN: 178236-12 inside the file
|
||||||
|
- Example: A819-1.TXT has SN: A819-1 inside -> decoded to 10819-1
|
||||||
|
- The SN line inside H-prefix files already has the full numeric serial
|
||||||
|
- The SN line inside A-prefix files still has the encoded serial
|
||||||
|
- Cross-references against testdata.db by (serial_number, model_number)
|
||||||
|
- Inserts MISSING records as log_type='SHT' with test_station from folder name
|
||||||
|
- Copies ALL files to X:\For_Web\{decoded_serial}.TXT (the web share)
|
||||||
|
|
||||||
|
## Machines with data
|
||||||
|
|
||||||
|
TS-4L: 3,082 files (largest)
|
||||||
|
TS-4R: 2,741 files
|
||||||
|
TS-1R: 509 files
|
||||||
|
TS-8R: 478 files
|
||||||
|
TS-3R: 435 files
|
||||||
|
TS-11R: 325 files
|
||||||
|
TS-8L: 285 files
|
||||||
|
TS-11L: 248 files
|
||||||
|
TS-27: 10 files (already imported this session)
|
||||||
|
TS-1L: 1 file
|
||||||
|
|
||||||
|
## Serial number encoding (8.3 filename scheme)
|
||||||
|
|
||||||
|
The QuickBASIC ATE software encodes long serial numbers to fit DOS 8.3 filenames.
|
||||||
|
The first two digits get replaced with a hex letter if the serial is too long:
|
||||||
|
|
||||||
|
178236-12 -> H8236-12.TXT (17 -> H, which is char code 72, 72-55=17)
|
||||||
|
10819-1 -> A819-1.TXT (10 -> A, which is char code 65, 65-55=10)
|
||||||
|
|
||||||
|
Decode: letter.charCodeAt(0) - 55 = numeric prefix
|
||||||
|
Only applies if filename starts with [A-Z] followed by digits.
|
||||||
|
|
||||||
|
## TS-27 already done
|
||||||
|
|
||||||
|
10 files from TS-27 were already imported earlier this session into the DB as SHT records.
|
||||||
|
The import script uses INSERT OR REPLACE so re-running is safe.
|
||||||
|
|
||||||
|
## Previous CTONWTXT.BAT issues (resolved)
|
||||||
|
|
||||||
|
- v1.0: Never called, checked for Novell serve.sys, used X: drive parameter
|
||||||
|
- v2.0: Called from CTONW, but used mixed-case "Stage" path -> failed on DOS
|
||||||
|
- v2.1: All uppercase STAGE, but had MD commands that fail on existing dirs
|
||||||
|
- v2.2: Same issue
|
||||||
|
- v2.3: Removed MD entirely, dirs pre-created on NAS. CURRENT VERSION.
|
||||||
BIN
Test Datasheets/DF-Test-Detail.PDF
Normal file
BIN
Test Datasheets/DF-Test-Detail.PDF
Normal file
Binary file not shown.
80
Test Datasheets/DFWDS/DFWDS_NAMES.txt
Normal file
80
Test Datasheets/DFWDS/DFWDS_NAMES.txt
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
DATASHEET FOLDER NAME,X:\Test_Datasheets
|
||||||
|
INVALID FILE MOVE FOLDER,X:\Bad_Datasheets
|
||||||
|
LOG FILE NAME,DFWDS
|
||||||
|
LOG FILE FOLDER,X:\Datasheets_Log
|
||||||
|
WEB FOLDER,X:\For_Web
|
||||||
|
OPERATION,WEBMOVE
|
||||||
|
|
||||||
|
Last updated: 2015-06-08
|
||||||
|
|
||||||
|
The first six lines of this file are folder and file names required by
|
||||||
|
the Dataforth Website Datasheet program (DFWDS.exe). Each line consists
|
||||||
|
of the parameter name (in all CAPS), followed by a comma, followed by
|
||||||
|
the file or folder name (not in quotes) or operation. A space is
|
||||||
|
allowed after the comma separator.
|
||||||
|
|
||||||
|
The six lines parameter lines must contain only the allowed parameters
|
||||||
|
and data, in this specified format, for the program to operate properly.
|
||||||
|
Any lines below these six lines are not read by the program, and can
|
||||||
|
consist of comments or instructions (such as these).
|
||||||
|
|
||||||
|
The location and name of this file (usually C:\DFWDS\DFWDS_NAMES.TXT) is
|
||||||
|
hardcoded in the program.
|
||||||
|
|
||||||
|
Descriptions of the six required lines (along with the required parameter
|
||||||
|
names) are shown below:
|
||||||
|
|
||||||
|
First line:
|
||||||
|
-----------
|
||||||
|
DATASHEET FOLDER NAME: This is the location of the folder containing the
|
||||||
|
datasheet files that will eventually be copied to the Dataforth website.
|
||||||
|
|
||||||
|
Second line:
|
||||||
|
------------
|
||||||
|
INVALID FILE MOVE FOLDER: This is the location of the folder to which
|
||||||
|
invalid files in the datasheet folder will be moved.
|
||||||
|
|
||||||
|
Third line:
|
||||||
|
-----------
|
||||||
|
LOG FILE NAME: This is the name of the file that logs the operation of the
|
||||||
|
Dataforth Website Datasheet program (DFWDS.exe), including invalid file
|
||||||
|
moves and datasheet file renaming. NOTE: This is the file name (only),
|
||||||
|
and does NOT include the ".log" extension.
|
||||||
|
|
||||||
|
Fourth line:
|
||||||
|
------------
|
||||||
|
LOG FILE FOLDER: This is the location of the folder containing the log
|
||||||
|
file for the DFWDS.exe program.
|
||||||
|
|
||||||
|
Fifth line:
|
||||||
|
WEB FOLDER: This is the location of the folder to which the valid
|
||||||
|
datasheet files (including renamed files) are moved if the "OPERATION"
|
||||||
|
parameter (see below) is "WEBMOVE".
|
||||||
|
|
||||||
|
Sixth line:
|
||||||
|
-----------
|
||||||
|
OPERATION: This parameter controls the operation of the program, and
|
||||||
|
can only be one of the values described below:
|
||||||
|
-------------------------------------
|
||||||
|
COUNT causes the program to only count the invalid files
|
||||||
|
and files that should be renamed.
|
||||||
|
|
||||||
|
LISTALL causes the program to list all of the files found in the
|
||||||
|
datasheet folder.
|
||||||
|
|
||||||
|
LISTBAD causes the program to list all of the invalid ("bad") files
|
||||||
|
found in the datasheet folder.
|
||||||
|
|
||||||
|
LISTRENAME causes the program to list all of the datasheet files in
|
||||||
|
the datasheet folder that have DOS-encoded names that need to be
|
||||||
|
renamed to match the module serial number contained in the file.
|
||||||
|
|
||||||
|
INPLACE renames the appropriate files in their current directory
|
||||||
|
(specified by the "DATASHEET FOLDER NAME" parameter - see above), but
|
||||||
|
moves the invalid files to the directory specified by the
|
||||||
|
"INVALID FILE MOVE FOLDER" parameter (see above).
|
||||||
|
|
||||||
|
WEBMOVE moves the invalid files to the "INVALID FILE MOVE FOLDER"
|
||||||
|
directory, but also moves the valid datasheet files (including those
|
||||||
|
that have been renamed) to the folder specified by the "WEB FOLDER"
|
||||||
|
parameter (see above).
|
||||||
1388
Test Datasheets/QB-Source/DB8BMAIN.BAS
Normal file
1388
Test Datasheets/QB-Source/DB8BMAIN.BAS
Normal file
File diff suppressed because it is too large
Load Diff
2380
Test Datasheets/QB-Source/KDSCOUT1.BAS
Normal file
2380
Test Datasheets/QB-Source/KDSCOUT1.BAS
Normal file
File diff suppressed because it is too large
Load Diff
3168
Test Datasheets/QB-Source/NLIBATED-DSCA.BAS
Normal file
3168
Test Datasheets/QB-Source/NLIBATED-DSCA.BAS
Normal file
File diff suppressed because it is too large
Load Diff
3222
Test Datasheets/QB-Source/NLIBATED-DSCT.BAS
Normal file
3222
Test Datasheets/QB-Source/NLIBATED-DSCT.BAS
Normal file
File diff suppressed because it is too large
Load Diff
3223
Test Datasheets/QB-Source/NLIBATED.BAS
Normal file
3223
Test Datasheets/QB-Source/NLIBATED.BAS
Normal file
File diff suppressed because it is too large
Load Diff
3506
Test Datasheets/QB-Source/TEST5B1E.BAS
Normal file
3506
Test Datasheets/QB-Source/TEST5B1E.BAS
Normal file
File diff suppressed because it is too large
Load Diff
3367
Test Datasheets/QB-Source/TEST5B2E.BAS
Normal file
3367
Test Datasheets/QB-Source/TEST5B2E.BAS
Normal file
File diff suppressed because it is too large
Load Diff
1731
Test Datasheets/QB-Source/TEST7B1C.BAS
Normal file
1731
Test Datasheets/QB-Source/TEST7B1C.BAS
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Test Datasheets/QB-Source/TESTPW17.BAS
Normal file
BIN
Test Datasheets/QB-Source/TESTPW17.BAS
Normal file
Binary file not shown.
3473
Test Datasheets/QB-Source/TST5SCT1.BAS
Normal file
3473
Test Datasheets/QB-Source/TST5SCT1.BAS
Normal file
File diff suppressed because it is too large
Load Diff
2052
Test Datasheets/QB-Source/TST5SCT2.BAS
Normal file
2052
Test Datasheets/QB-Source/TST5SCT2.BAS
Normal file
File diff suppressed because it is too large
Load Diff
194
Test Datasheets/README.md
Normal file
194
Test Datasheets/README.md
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
# Claude Instance Context: Test Datasheets Investigation (AD1)
|
||||||
|
|
||||||
|
**Purpose:** You are a Claude Code instance running on AD1 (192.168.0.27) at Dataforth's facility. Your job is to investigate the TestDataSheetUploader tool and the test datasheet workflow -- where files come from, where they go, and how this integrates with the DOS test machines.
|
||||||
|
|
||||||
|
**This is a temporary investigation instance.** Once findings are documented and synced to Gitea, this instance will be removed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Your Mission
|
||||||
|
|
||||||
|
1. **Find where test datasheets are generated** -- which machine(s), which software, what path
|
||||||
|
2. **Find where they end up** -- the server-side path is `C:\inetpub\wwwroot\dataforth.com\WebShare\ProcessCheckOutTestFolder\` on whatever runs www.dataforth.com
|
||||||
|
3. **Determine if this uploader is still in active use** or if the workflow changed
|
||||||
|
4. **Document the full datasheet pipeline** -- from DOS test machine output through to the website
|
||||||
|
5. **Sync your findings back to Gitea** so the coordinator instance can see them
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Gitea Sync (How to Push Findings)
|
||||||
|
|
||||||
|
The ClaudeTools repo is hosted on Gitea. Clone and push your findings here:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone the repo
|
||||||
|
git clone https://mike%40azcomputerguru.com:Gptf%2A77ttb123%21%40%23-git@git.azcomputerguru.com/azcomputerguru/claudetools.git
|
||||||
|
cd claudetools
|
||||||
|
|
||||||
|
# Your working area
|
||||||
|
# clients/dataforth/dos-test-machines/Test Datasheets/
|
||||||
|
|
||||||
|
# Commit and push findings
|
||||||
|
git add -A
|
||||||
|
git commit -m "AD1 investigation: test datasheet pipeline findings"
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
**Gitea Credentials (plaintext, temporary use only):**
|
||||||
|
- URL: https://git.azcomputerguru.com
|
||||||
|
- User: mike@azcomputerguru.com
|
||||||
|
- Password: Gptf*77ttb123!@#-git
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Network Context (Dataforth Engineering Network)
|
||||||
|
|
||||||
|
| Device | IP | Role | Credentials |
|
||||||
|
|--------|-----|------|-------------|
|
||||||
|
| AD1 (you are here) | 192.168.0.27 | Primary Domain Controller | INTRANET\sysadmin / Paper123!@# |
|
||||||
|
| AD2 | 192.168.0.6 | Production Server (Win Server 2008 R2) | INTRANET\sysadmin / Paper123!@# |
|
||||||
|
| D2TESTNAS | 192.168.0.9 | TrueNAS, SMB1 proxy for DOS machines | root / (SSH key) or admin / Paper123!@#-nas |
|
||||||
|
| DOS Stations | 192.168.0.x | ~30 DOS 6.22 test machines (TS-XX) | N/A |
|
||||||
|
| UDM Gateway | 192.168.0.254 | UniFi Dream Machine | N/A |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What We Already Know About TestDataSheetUploader
|
||||||
|
|
||||||
|
This is a VB.NET console app (.NET Framework 4.7.2) last built November 2, 2022.
|
||||||
|
|
||||||
|
### What it does
|
||||||
|
1. Calls `https://www.dataforth.com/Services/DirectoryManifest.aspx` to get a list of files already on the web server
|
||||||
|
2. Compares local files against that manifest (by filename, size, and last-modified date)
|
||||||
|
3. Uploads new/changed files via `https://www.dataforth.com/Services/Uploader.aspx`
|
||||||
|
4. Deletes files from server that no longer exist locally via `https://www.dataforth.com/Services/DeleteFile.aspx`
|
||||||
|
5. Only processes files modified in the current year
|
||||||
|
|
||||||
|
### Configured paths (from app.config)
|
||||||
|
- **Service auth:** username=DataforthWebShare, password=Data6277
|
||||||
|
- **TestDataSheetPath:** `C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists`
|
||||||
|
- **TestFolderPath:** `C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists`
|
||||||
|
- **InventoryDataStagingFolder:** `C:\TestDataSheetUploader\staging`
|
||||||
|
- **InventoryDataSourceFolder:** `C:\TestDataSheetUploader\src`
|
||||||
|
- **InventoryDataFiles:** AvSelCat.csv, AvSelCus.csv
|
||||||
|
|
||||||
|
### Server-side destination (from error logs)
|
||||||
|
```
|
||||||
|
C:\inetpub\wwwroot\dataforth.com\WebShare\ProcessCheckOutTestFolder\
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key unknowns -- what you need to find out
|
||||||
|
- **Who is "hoffm"?** Likely a Hoffman who worked at Dataforth. Which machine was this?
|
||||||
|
- **Where do test datasheets originate?** The DOS machines run QuickBASIC data acquisition. Do they produce datasheet files?
|
||||||
|
- **Is there a path from DOS machines -> datasheets?** The DOS machines map `T:` to `\\D2TESTNAS\TEST`. Is there a datasheets share they write to?
|
||||||
|
- **Is the uploader still running?** Scheduled task? Manual? Last used?
|
||||||
|
- **Where does `C:\Users\hoffm\...` map to now?** Did someone take over this role?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Investigation Steps
|
||||||
|
|
||||||
|
### On AD1 (this machine)
|
||||||
|
```powershell
|
||||||
|
# Check if TestDataSheetUploader exists anywhere on this machine
|
||||||
|
Get-ChildItem -Path C:\ -Recurse -Filter "TestDataSheetUploader*" -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
# Check for Hoffman's profile or traces
|
||||||
|
Get-ChildItem C:\Users\ -Directory
|
||||||
|
Get-ChildItem "C:\Users\hoffm" -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
# Check scheduled tasks for anything datasheet-related
|
||||||
|
Get-ScheduledTask | Where-Object { $_.TaskName -like "*data*" -or $_.TaskName -like "*sheet*" -or $_.TaskName -like "*upload*" -or $_.TaskName -like "*sync*" }
|
||||||
|
|
||||||
|
# Check for IIS sites (AD1 might host www.dataforth.com)
|
||||||
|
Import-Module WebAdministration -ErrorAction SilentlyContinue
|
||||||
|
Get-Website -ErrorAction SilentlyContinue
|
||||||
|
Get-ChildItem "C:\inetpub\wwwroot" -ErrorAction SilentlyContinue
|
||||||
|
```
|
||||||
|
|
||||||
|
### On AD2 (192.168.0.6)
|
||||||
|
```powershell
|
||||||
|
# Remote into AD2 and check
|
||||||
|
Invoke-Command -ComputerName 192.168.0.6 -Credential (Get-Credential INTRANET\sysadmin) -ScriptBlock {
|
||||||
|
# Check for the uploader
|
||||||
|
Get-ChildItem -Path C:\ -Recurse -Filter "TestDataSheetUploader*" -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
# Check IIS
|
||||||
|
Get-ChildItem "C:\inetpub\wwwroot" -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
# Check for the WebShare path from error logs
|
||||||
|
Get-ChildItem "C:\inetpub\wwwroot\dataforth.com\WebShare" -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
# Check scheduled tasks
|
||||||
|
Get-ScheduledTask | Where-Object { $_.TaskName -like "*data*" -or $_.TaskName -like "*upload*" }
|
||||||
|
|
||||||
|
# Check user profiles
|
||||||
|
Get-ChildItem C:\Users\ -Directory
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### On D2TESTNAS (192.168.0.9)
|
||||||
|
```bash
|
||||||
|
# SSH from AD1 or any machine with access
|
||||||
|
ssh root@192.168.0.9
|
||||||
|
|
||||||
|
# Check datasheets share
|
||||||
|
ls -la /data/datasheets/
|
||||||
|
find /data/ -name "*datasheet*" -o -name "*TestData*" 2>/dev/null
|
||||||
|
|
||||||
|
# Check if DOS machines write any test output files
|
||||||
|
ls -la /data/test/TS-27/
|
||||||
|
find /data/test/ -name "*.pdf" -o -name "*.csv" -o -name "*.dat" 2>/dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check the Dataforth website services
|
||||||
|
```powershell
|
||||||
|
# Test if the manifest service still responds
|
||||||
|
$cred = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("DataforthWebShare:Data6277"))
|
||||||
|
Invoke-WebRequest -Uri "https://www.dataforth.com/Services/DirectoryManifest.aspx" -Headers @{Authorization="Basic $cred"} -Method GET -ErrorAction SilentlyContinue
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## DOS Test Machine Architecture (Full Context)
|
||||||
|
|
||||||
|
The DOS machines are ~30 stations running DOS 6.22 with QuickBASIC 4.5 data acquisition software.
|
||||||
|
|
||||||
|
```
|
||||||
|
DOS Machines (TS-XX) --SMB1--> D2TESTNAS (192.168.0.9) --SMB2/rsync--> AD2 (192.168.0.6)
|
||||||
|
| /data/test/ C:\Shares\test\
|
||||||
|
| /data/datasheets/ C:\Shares\datasheets (PENDING)
|
||||||
|
|
|
||||||
|
+-- Map T: = \\D2TESTNAS\TEST
|
||||||
|
+-- Run QuickBASIC data acquisition
|
||||||
|
+-- UPDATE.BAT for remote management
|
||||||
|
+-- TODO.BAT for remote task execution
|
||||||
|
```
|
||||||
|
|
||||||
|
**Bidirectional sync** runs every 15 minutes between D2TESTNAS and AD2 via `/root/sync-to-ad2.sh`.
|
||||||
|
|
||||||
|
The datasheets share (`\\D2TESTNAS\datasheets` -> `/data/datasheets/`) exists on D2TESTNAS but the corresponding AD2 share (`\\AD2\datasheets`) was never created -- it's listed as a remaining task. This may be relevant to the test datasheet pipeline.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Where to Save Your Findings
|
||||||
|
|
||||||
|
Write your investigation results to:
|
||||||
|
```
|
||||||
|
clients/dataforth/dos-test-machines/Test Datasheets/INVESTIGATION.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Include:
|
||||||
|
- What you found on each machine
|
||||||
|
- The complete datasheet pipeline (or what's missing/broken)
|
||||||
|
- Whether the uploader is still active
|
||||||
|
- Recommendations for what to do next
|
||||||
|
|
||||||
|
Then commit and push to Gitea using the credentials above.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
- **AJ at Dataforth** -- engineering contact, can answer questions about the test workflow
|
||||||
|
- **Coordinator instance** -- will see your findings after you push to Gitea
|
||||||
BIN
Test Datasheets/SpecData/5BMAIN.DAT
Normal file
BIN
Test Datasheets/SpecData/5BMAIN.DAT
Normal file
Binary file not shown.
BIN
Test Datasheets/SpecData/8BMAIN.DAT
Normal file
BIN
Test Datasheets/SpecData/8BMAIN.DAT
Normal file
Binary file not shown.
BIN
Test Datasheets/SpecData/DSCOUT.DAT
Normal file
BIN
Test Datasheets/SpecData/DSCOUT.DAT
Normal file
Binary file not shown.
BIN
Test Datasheets/SpecData/SCTMAIN.DAT
Normal file
BIN
Test Datasheets/SpecData/SCTMAIN.DAT
Normal file
Binary file not shown.
BIN
Test Datasheets/TestDataSheetUploader.zip
Normal file
BIN
Test Datasheets/TestDataSheetUploader.zip
Normal file
Binary file not shown.
158
Test Datasheets/TestDataSheetUploader/HTTPUploader.vb
Normal file
158
Test Datasheets/TestDataSheetUploader/HTTPUploader.vb
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
Imports System.Text
|
||||||
|
Imports System.Net
|
||||||
|
Imports System.IO
|
||||||
|
|
||||||
|
Public Class HTTPUploader
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Public Shared Function UploadFile(ByVal url As String, ByVal credentials As Net.NetworkCredential, ByVal localPathFilename As String, ByVal nvc As System.Collections.Specialized.NameValueCollection, ByRef LogMessage As String) As Boolean
|
||||||
|
Try
|
||||||
|
'Return True
|
||||||
|
Dim length As Long = 0
|
||||||
|
'Dim boundary As String = "----------------------------" & Date.Now.Ticks.ToString("x")
|
||||||
|
Dim boundary As String = "----------------------------061366199019971999"
|
||||||
|
|
||||||
|
Dim httpWebRequest2 As HttpWebRequest = WebRequest.Create(url)
|
||||||
|
httpWebRequest2.ContentType = "multipart/form-data; boundary=" & boundary
|
||||||
|
httpWebRequest2.Method = "POST"
|
||||||
|
httpWebRequest2.KeepAlive = True
|
||||||
|
httpWebRequest2.Credentials = credentials
|
||||||
|
httpWebRequest2.Timeout = 900000
|
||||||
|
|
||||||
|
|
||||||
|
Dim memStream As New System.IO.MemoryStream()
|
||||||
|
|
||||||
|
Dim boundarybytes() As Byte = System.Text.Encoding.ASCII.GetBytes(vbCrLf & "--" & boundary & vbCrLf)
|
||||||
|
|
||||||
|
|
||||||
|
Dim formdataTemplate As String = vbCrLf & "--" + boundary & vbCrLf & "Content-Disposition: form-data; name=""{0}"";" & vbCrLf & vbCrLf & "{1}"
|
||||||
|
|
||||||
|
For Each key As String In nvc.Keys
|
||||||
|
Dim formitem As String = String.Format(formdataTemplate, key, nvc(key))
|
||||||
|
Dim formitembytes() As Byte = System.Text.Encoding.UTF8.GetBytes(formitem)
|
||||||
|
memStream.Write(formitembytes, 0, formitembytes.Length)
|
||||||
|
Next
|
||||||
|
|
||||||
|
|
||||||
|
memStream.Write(boundarybytes, 0, boundarybytes.Length)
|
||||||
|
|
||||||
|
Dim headerTemplate As String = "Content-Disposition: form-data; name=""{0}""; filename=""{1}"" " & _
|
||||||
|
"Content-Type: application/octet-stream" & vbCrLf & vbCrLf
|
||||||
|
|
||||||
|
'Content-Type: application/octet-stream
|
||||||
|
|
||||||
|
|
||||||
|
'string header = string.Format(headerTemplate, "file" + i, files[i]);
|
||||||
|
Dim header As String = String.Format(headerTemplate, "file1", localPathFilename)
|
||||||
|
|
||||||
|
Dim headerbytes() As Byte = System.Text.Encoding.UTF8.GetBytes(header)
|
||||||
|
|
||||||
|
memStream.Write(headerbytes, 0, headerbytes.Length)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Dim byteArray As Byte() = File.ReadAllBytes(localPathFilename)
|
||||||
|
memStream.Write(byteArray, 0, byteArray.Length)
|
||||||
|
|
||||||
|
memStream.Write(boundarybytes, 0, boundarybytes.Length)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
httpWebRequest2.ContentLength = memStream.Length + 1
|
||||||
|
|
||||||
|
Dim requestStream As Stream = httpWebRequest2.GetRequestStream()
|
||||||
|
|
||||||
|
memStream.Position = 0
|
||||||
|
Dim tempBuffer(memStream.Length) As Byte
|
||||||
|
memStream.Read(tempBuffer, 0, tempBuffer.Length)
|
||||||
|
memStream.Close()
|
||||||
|
requestStream.Write(tempBuffer, 0, tempBuffer.Length)
|
||||||
|
requestStream.Close()
|
||||||
|
|
||||||
|
Dim webResponse2 As WebResponse = httpWebRequest2.GetResponse()
|
||||||
|
|
||||||
|
Dim stream2 As Stream = webResponse2.GetResponseStream()
|
||||||
|
Dim reader2 As New StreamReader(stream2)
|
||||||
|
|
||||||
|
Dim xmlResponse As String = reader2.ReadToEnd
|
||||||
|
|
||||||
|
webResponse2.Close()
|
||||||
|
httpWebRequest2 = Nothing
|
||||||
|
webResponse2 = Nothing
|
||||||
|
|
||||||
|
|
||||||
|
Dim ds As New DataSet
|
||||||
|
ds.ReadXml(New System.Xml.XmlTextReader(New StringReader(xmlResponse)))
|
||||||
|
|
||||||
|
Dim responseMessage As String = ds.Tables("Result").Rows(0)("Message")
|
||||||
|
If responseMessage = "SUCCESS" Then
|
||||||
|
Dim uploadedFilesize As Long = ds.Tables("Result").Rows(0)("SavedFileSize")
|
||||||
|
If My.Computer.FileSystem.GetFileInfo(localPathFilename).Length = uploadedFilesize Then
|
||||||
|
'we are done
|
||||||
|
Return True
|
||||||
|
Else
|
||||||
|
LogMessage = "Uploaded filesize (" & uploadedFilesize & ") does not match local filesize (" & My.Computer.FileSystem.GetFileInfo(localPathFilename).Length & ")"
|
||||||
|
End If
|
||||||
|
Else
|
||||||
|
LogMessage = "Dataforth Service Upload Error: " & ds.Tables("Result").Rows(0)("ErrorMessage")
|
||||||
|
End If
|
||||||
|
Return False
|
||||||
|
Catch ex As Exception
|
||||||
|
LogMessage = "Exception while uploading to Dataforth Service: " & ex.ToString
|
||||||
|
Return False
|
||||||
|
End Try
|
||||||
|
End Function
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
'Public Shared Sub _UploadVideo_(ByVal url As String, ByVal credentials As Net.NetworkCredential, ByVal localPathFilename As String, ByVal nvc As System.Collections.Specialized.NameValueCollection)
|
||||||
|
' Try
|
||||||
|
' Dim client As New WebClient
|
||||||
|
' client.Credentials = credentials
|
||||||
|
' Dim bogus As Integer = -1
|
||||||
|
' Dim requestURL As String = url & "?ecsId=" & nvc.Get("ecsId")
|
||||||
|
' 'requestURL = requestURL.Replace("https://", "http://")
|
||||||
|
|
||||||
|
' Dim response() As Byte = client.UploadFile(requestURL, localPathFilename)
|
||||||
|
' MsgBox(System.Text.Encoding.Unicode.GetString(response))
|
||||||
|
' Catch webEx As WebException
|
||||||
|
' Dim thisE As String = webEx.ToString
|
||||||
|
|
||||||
|
' Catch ex As Exception
|
||||||
|
|
||||||
|
' End Try
|
||||||
|
'End Sub
|
||||||
|
|
||||||
|
|
||||||
|
'Public Shared Sub UploadVideo__(ByVal url As String, ByVal credentials As Net.NetworkCredential, ByVal localPathFilename As String, ByVal nvc As System.Collections.Specialized.NameValueCollection)
|
||||||
|
|
||||||
|
' Dim requestURL As String = url
|
||||||
|
' Dim boundary As String = "----------------------------" & Date.Now.Ticks.ToString("x")
|
||||||
|
|
||||||
|
' 'Create Request
|
||||||
|
' Dim webRequest As System.Net.HttpWebRequest = CType(System.Net.WebRequest.Create(requestURL), System.Net.HttpWebRequest)
|
||||||
|
' webRequest.Credentials = credentials
|
||||||
|
' webRequest.Timeout = 120000
|
||||||
|
' 'System.Net.ServicePointManager.ServerCertificateValidationCallback = (Function(sender, certificate, chain, sslPolicyErrors) True)
|
||||||
|
' 'webRequest.ContentType = "application/x-www-form-urlencoded"
|
||||||
|
' webRequest.ContentType = "multipart/form-data; boundary=" & boundary
|
||||||
|
' webRequest.Method = "POST"
|
||||||
|
|
||||||
|
|
||||||
|
' Dim byteArray As Byte() = File.ReadAllBytes(localPathFilename)
|
||||||
|
' webRequest.ContentLength = byteArray.Length
|
||||||
|
' Dim dataStream As Stream = webRequest.GetRequestStream
|
||||||
|
' dataStream.Write(byteArray, 0, byteArray.Length)
|
||||||
|
' dataStream.Close()
|
||||||
|
|
||||||
|
|
||||||
|
' ' Retrieve data from Response
|
||||||
|
' Dim webResponse As System.Net.HttpWebResponse = CType(webRequest.GetResponse(), System.Net.HttpWebResponse)
|
||||||
|
' Dim sr As New System.IO.StreamReader(webResponse.GetResponseStream(), System.Text.Encoding.UTF8)
|
||||||
|
' Dim responseString As String = sr.ReadToEnd()
|
||||||
|
' MsgBox(responseString)
|
||||||
|
|
||||||
|
'End Sub
|
||||||
|
|
||||||
|
End Class
|
||||||
264
Test Datasheets/TestDataSheetUploader/Module1.vb
Normal file
264
Test Datasheets/TestDataSheetUploader/Module1.vb
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
Module Module1
|
||||||
|
|
||||||
|
Private processLog As System.Text.StringBuilder
|
||||||
|
|
||||||
|
Sub Main()
|
||||||
|
processLog = New System.Text.StringBuilder()
|
||||||
|
Dim appSettings As New Configuration.AppSettingsReader
|
||||||
|
|
||||||
|
|
||||||
|
'for testing only
|
||||||
|
'UploadFilesInDirectory("C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists", "TestFolder")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
'CopyInventoryFilesToStagingFolder()
|
||||||
|
'SyncFolder("InventoryDataFolder")
|
||||||
|
|
||||||
|
SyncFolder("TestDataSheet")
|
||||||
|
|
||||||
|
|
||||||
|
Dim logFilename As String = My.Application.Info.DirectoryPath & "\processLog." & Now.ToString("yyyy.MM.dd.HH.mm.ss") & ".txt"
|
||||||
|
My.Computer.FileSystem.WriteAllText(logFilename, processLog.ToString, False)
|
||||||
|
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Private Sub AddToLog(ByVal message As String, ByVal Echo As Boolean)
|
||||||
|
processLog.Append(Now.ToString("MM/dd/YYYY HH:mm:ss | ") & message & vbCrLf)
|
||||||
|
If Echo Then
|
||||||
|
Console.WriteLine(message)
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
|
||||||
|
Public Sub CopyInventoryFilesToStagingFolder()
|
||||||
|
|
||||||
|
Dim appSettings As New Configuration.AppSettingsReader
|
||||||
|
Dim stagingFolderPath As String = appSettings.GetValue("InventoryDataStagingFolder", GetType(String))
|
||||||
|
Dim srcFolderPath As String = appSettings.GetValue("InventoryDataSourceFolder", GetType(String))
|
||||||
|
Dim filenamesStr As String = appSettings.GetValue("InventoryDataFiles", GetType(String))
|
||||||
|
|
||||||
|
Dim filenames() As String = filenamesStr.Split(",")
|
||||||
|
|
||||||
|
For Each thisFilename As String In filenames
|
||||||
|
Dim src As String = srcFolderPath & "\" & thisFilename
|
||||||
|
Dim dest As String = stagingFolderPath & "\" & thisFilename
|
||||||
|
My.Computer.FileSystem.CopyFile(src, dest, True)
|
||||||
|
Next
|
||||||
|
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
|
||||||
|
Public Sub UploadFilesInDirectory(ByVal DirectoryPath As String, ByVal UploadType As String)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Dim appSettings As New Configuration.AppSettingsReader
|
||||||
|
Dim username As String = appSettings.GetValue("ServiceUsername", GetType(String))
|
||||||
|
Dim password As String = appSettings.GetValue("ServicePassword", GetType(String))
|
||||||
|
Dim serviceCredentials As New Net.NetworkCredential(username, password)
|
||||||
|
Dim url As String = appSettings.GetValue("UploaderServiceURL", GetType(String))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
For Each thisFile As String In My.Computer.FileSystem.GetFiles(DirectoryPath)
|
||||||
|
|
||||||
|
Dim formParameters As New System.Collections.Specialized.NameValueCollection
|
||||||
|
formParameters.Add("UploadType", UploadType)
|
||||||
|
|
||||||
|
Dim logMessage As New String("")
|
||||||
|
Console.WriteLine("Uploading: " & thisFile)
|
||||||
|
If HTTPUploader.UploadFile(url, serviceCredentials, thisFile, formParameters, logMessage) Then
|
||||||
|
'this video is now staged
|
||||||
|
AddToLog("Uploaded " & thisFile, True)
|
||||||
|
|
||||||
|
My.Computer.FileSystem.DeleteFile(thisFile)
|
||||||
|
Else
|
||||||
|
|
||||||
|
AddToLog("Upload FAILED for " & thisFile, True)
|
||||||
|
AddToLog("Upload FAIL MESSAGE: " & logMessage, False)
|
||||||
|
Console.WriteLine("ERROR: " & logMessage)
|
||||||
|
End If
|
||||||
|
|
||||||
|
|
||||||
|
Next
|
||||||
|
|
||||||
|
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
Public Sub SyncFolder(ByVal FolderAlias As String)
|
||||||
|
Try
|
||||||
|
AddToLog("SyncFolder(" & FolderAlias & ") started.", True)
|
||||||
|
'get manifest of files that are on server mirror
|
||||||
|
Dim appSettings As New Configuration.AppSettingsReader
|
||||||
|
Dim username As String = appSettings.GetValue("ServiceUsername", GetType(String))
|
||||||
|
Dim password As String = appSettings.GetValue("ServicePassword", GetType(String))
|
||||||
|
Dim serviceCredentials As New Net.NetworkCredential(username, password)
|
||||||
|
Dim manifestServiceUrl As String = appSettings.GetValue("DirectoryManifestServiceURL", GetType(String))
|
||||||
|
Dim uploadServiceUrl As String = appSettings.GetValue("UploaderServiceURL", GetType(String))
|
||||||
|
Dim deleteServiceUrl As String = appSettings.GetValue("DeleteFileServiceURL", GetType(String))
|
||||||
|
Dim testMode As Boolean = appSettings.GetValue("TestMode", GetType(Boolean))
|
||||||
|
|
||||||
|
'Create an XML file to post with the request
|
||||||
|
Dim requestDS As New DataSet("Request")
|
||||||
|
Dim requestDT As New DataTable("RequestData")
|
||||||
|
requestDT.Columns.Add("SyncPathAlias", GetType(String))
|
||||||
|
requestDS.Tables.Add(requestDT)
|
||||||
|
Dim requestDR As DataRow = requestDT.NewRow
|
||||||
|
requestDR("SyncPathAlias") = FolderAlias
|
||||||
|
requestDT.Rows.Add(requestDR)
|
||||||
|
|
||||||
|
'Get Dataset from XML response
|
||||||
|
Dim manifestXML As String = CSFramework_Utilities.XMLData.DownloadXMLWithDatasetPost(manifestServiceUrl, requestDS, serviceCredentials)
|
||||||
|
|
||||||
|
My.Computer.FileSystem.WriteAllText(My.Application.Info.DirectoryPath & "\manifest.xml", manifestXML, False)
|
||||||
|
|
||||||
|
Dim ds As DataSet = CSFramework_Utilities.XMLData.DatasetFromXML(manifestXML)
|
||||||
|
|
||||||
|
AddToLog("Manifest downloaded with " & ds.Tables("ContentFile").Rows.Count & " files.", True)
|
||||||
|
|
||||||
|
'Build a list of files that should be uploaded
|
||||||
|
Dim filesToUpload As New List(Of String)
|
||||||
|
|
||||||
|
Dim localFolderPath As String = ""
|
||||||
|
Select Case FolderAlias
|
||||||
|
Case "TestDataSheet"
|
||||||
|
localFolderPath = appSettings.GetValue("TestDataSheetPath", GetType(String))
|
||||||
|
Case "TestFolder"
|
||||||
|
localFolderPath = appSettings.GetValue("TestFolderPath", GetType(String))
|
||||||
|
Case "InventoryDataFolder"
|
||||||
|
localFolderPath = appSettings.GetValue("InventoryDataStagingFolder", GetType(String))
|
||||||
|
End Select
|
||||||
|
|
||||||
|
Dim discoveryFileCount As Integer = 0
|
||||||
|
Dim discoveryFileEchoCount As Integer = 1000
|
||||||
|
|
||||||
|
Dim sourceFolder As New System.IO.DirectoryInfo(localFolderPath)
|
||||||
|
AddToLog("Accessing local folder: " & localFolderPath, True)
|
||||||
|
|
||||||
|
For Each thisLocalFileInfo As System.IO.FileInfo In sourceFolder.GetFiles
|
||||||
|
discoveryFileCount += 1
|
||||||
|
If discoveryFileCount = 1 Then
|
||||||
|
AddToLog("Found at least 1 file in local folder", True)
|
||||||
|
End If
|
||||||
|
If discoveryFileCount = discoveryFileEchoCount Then
|
||||||
|
AddToLog("Discovery file count: " & discoveryFileEchoCount, True)
|
||||||
|
discoveryFileEchoCount += 1000
|
||||||
|
End If
|
||||||
|
'Dim thisLocalFileInfo As New System.IO.FileInfo(thisLocalFile)
|
||||||
|
|
||||||
|
|
||||||
|
If thisLocalFileInfo.LastWriteTimeUtc.Year = Now.Year Then
|
||||||
|
Dim foundMatchingFileOnServer As Boolean = False
|
||||||
|
If ds.Tables.Contains("ContentFile") Then
|
||||||
|
For Each dr As DataRow In ds.Tables("ContentFile").Rows
|
||||||
|
If dr("Filename").ToString = thisLocalFileInfo.Name Then
|
||||||
|
Dim filesize As Integer = dr("Filesize")
|
||||||
|
Dim datelastupdated As Date = dr("DateLastUpdated")
|
||||||
|
datelastupdated = datelastupdated.ToUniversalTime
|
||||||
|
If filesize = thisLocalFileInfo.Length Then
|
||||||
|
If thisLocalFileInfo.LastWriteTimeUtc.ToString("yyyy.MM.dd.HH.mm.ss") = datelastupdated.ToString("yyyy.MM.dd.HH.mm.ss") Then
|
||||||
|
foundMatchingFileOnServer = True
|
||||||
|
Exit For
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
If Not foundMatchingFileOnServer Then
|
||||||
|
filesToUpload.Add(thisLocalFileInfo.FullName)
|
||||||
|
AddToLog("Requesting upload: " & thisLocalFileInfo.Name, True)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
|
||||||
|
AddToLog("Found " & filesToUpload.Count & " files that need to be uploaded.", True)
|
||||||
|
|
||||||
|
'Upload Files to Server
|
||||||
|
If Not testMode Then
|
||||||
|
For Each thisFile As String In filesToUpload
|
||||||
|
Dim thisLocalFileInfo As New System.IO.FileInfo(thisFile)
|
||||||
|
Dim formParameters As New System.Collections.Specialized.NameValueCollection
|
||||||
|
formParameters.Add("UploadType", FolderAlias)
|
||||||
|
'Request("LastUpdatedDate")
|
||||||
|
formParameters.Add("LastUpdatedDate", thisLocalFileInfo.LastWriteTimeUtc.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"))
|
||||||
|
'2015-12-11T17:38:05.9190462Z
|
||||||
|
|
||||||
|
Dim logMessage As New String("")
|
||||||
|
Console.WriteLine("Uploading: " & thisFile)
|
||||||
|
If HTTPUploader.UploadFile(uploadServiceUrl, serviceCredentials, thisFile, formParameters, logMessage) Then
|
||||||
|
'this file is now staged
|
||||||
|
AddToLog("Uploaded file: " & thisFile, True)
|
||||||
|
|
||||||
|
'My.Computer.FileSystem.DeleteFile(thisFile)
|
||||||
|
Else
|
||||||
|
|
||||||
|
AddToLog("Upload FAILED for " & thisFile, True)
|
||||||
|
AddToLog("Upload FAIL MESSAGE: " & logMessage, False)
|
||||||
|
Console.WriteLine("ERROR: " & logMessage)
|
||||||
|
End If
|
||||||
|
|
||||||
|
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
|
||||||
|
|
||||||
|
'Create dataset for DeleteFile service
|
||||||
|
Dim deleteDS As New DataSet("DeleteRequestData")
|
||||||
|
|
||||||
|
|
||||||
|
'add request data
|
||||||
|
Dim deleteRD As New DataTable("RequestData")
|
||||||
|
deleteRD.Columns.Add("SyncPathAlias", GetType(String))
|
||||||
|
Dim deleteDataDR As DataRow = deleteRD.NewRow
|
||||||
|
deleteDataDR("SyncPathAlias") = FolderAlias
|
||||||
|
deleteRD.Rows.Add(deleteDataDR)
|
||||||
|
deleteDS.Tables.Add(deleteRD)
|
||||||
|
|
||||||
|
|
||||||
|
'add filenames
|
||||||
|
Dim deleteDT As New DataTable("Filenames")
|
||||||
|
deleteDT.Columns.Add("Filename", GetType(String))
|
||||||
|
deleteDS.Tables.Add(deleteDT)
|
||||||
|
|
||||||
|
If ds.Tables.Contains("ContentFile") Then
|
||||||
|
For Each dr As DataRow In ds.Tables("ContentFile").Rows
|
||||||
|
Dim localFileName As String = localFolderPath & "\" & dr("Filename").ToString
|
||||||
|
If Not My.Computer.FileSystem.FileExists(localFileName) Then
|
||||||
|
|
||||||
|
Dim deleteDR As DataRow = deleteDT.NewRow
|
||||||
|
deleteDR("Filename") = dr("Filename").ToString
|
||||||
|
deleteDT.Rows.Add(deleteDR)
|
||||||
|
|
||||||
|
AddToLog("Requested " & FolderAlias & " Delete: " & dr("Filename").ToString, True)
|
||||||
|
|
||||||
|
End If
|
||||||
|
Next
|
||||||
|
End If
|
||||||
|
|
||||||
|
AddToLog("Found " & deleteDT.Rows.Count & " files to delete.", True)
|
||||||
|
|
||||||
|
|
||||||
|
'Delete obsolete files that were detected
|
||||||
|
If Not testMode Then
|
||||||
|
If deleteDT.Rows.Count > 0 Then
|
||||||
|
Dim deleteResponseXML As String = CSFramework_Utilities.XMLData.DownloadXMLWithDatasetPost(deleteServiceUrl, deleteDS, serviceCredentials)
|
||||||
|
AddToLog("Obsolete " & FolderAlias & " files deleted.", True)
|
||||||
|
Else
|
||||||
|
AddToLog("No obsolete " & FolderAlias & " files were detected.", True)
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
|
Catch ex As Exception
|
||||||
|
AddToLog("Exception in SyncFolder: " & ex.ToString, True)
|
||||||
|
|
||||||
|
|
||||||
|
End Try
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
|
||||||
|
End Module
|
||||||
13
Test Datasheets/TestDataSheetUploader/My Project/Application.Designer.vb
generated
Normal file
13
Test Datasheets/TestDataSheetUploader/My Project/Application.Designer.vb
generated
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
'------------------------------------------------------------------------------
|
||||||
|
' <auto-generated>
|
||||||
|
' This code was generated by a tool.
|
||||||
|
' Runtime Version:4.0.30319.42000
|
||||||
|
'
|
||||||
|
' Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
' the code is regenerated.
|
||||||
|
' </auto-generated>
|
||||||
|
'------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Option Strict On
|
||||||
|
Option Explicit On
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<MySubMain>false</MySubMain>
|
||||||
|
<SingleInstance>false</SingleInstance>
|
||||||
|
<ShutdownMode>0</ShutdownMode>
|
||||||
|
<EnableVisualStyles>true</EnableVisualStyles>
|
||||||
|
<AuthenticationMode>0</AuthenticationMode>
|
||||||
|
<ApplicationType>2</ApplicationType>
|
||||||
|
<SaveMySettingsOnExit>true</SaveMySettingsOnExit>
|
||||||
|
</MyApplicationData>
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
Imports System
|
||||||
|
Imports System.Reflection
|
||||||
|
Imports System.Runtime.InteropServices
|
||||||
|
|
||||||
|
' General Information about an assembly is controlled through the following
|
||||||
|
' set of attributes. Change these attribute values to modify the information
|
||||||
|
' associated with an assembly.
|
||||||
|
|
||||||
|
' Review the values of the assembly attributes
|
||||||
|
|
||||||
|
<Assembly: AssemblyTitle("TestDataSheetUploader")>
|
||||||
|
<Assembly: AssemblyDescription("")>
|
||||||
|
<Assembly: AssemblyCompany("Hewlett-Packard")>
|
||||||
|
<Assembly: AssemblyProduct("TestDataSheetUploader")>
|
||||||
|
<Assembly: AssemblyCopyright("Copyright © Hewlett-Packard 2016")>
|
||||||
|
<Assembly: AssemblyTrademark("")>
|
||||||
|
|
||||||
|
<Assembly: ComVisible(False)>
|
||||||
|
|
||||||
|
'The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
<Assembly: Guid("7fe555fe-f768-41e5-b89d-89289692ba0e")>
|
||||||
|
|
||||||
|
' Version information for an assembly consists of the following four values:
|
||||||
|
'
|
||||||
|
' Major Version
|
||||||
|
' Minor Version
|
||||||
|
' Build Number
|
||||||
|
' Revision
|
||||||
|
'
|
||||||
|
' You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
' by using the '*' as shown below:
|
||||||
|
' <Assembly: AssemblyVersion("1.0.*")>
|
||||||
|
|
||||||
|
<Assembly: AssemblyVersion("1.0.0.0")>
|
||||||
|
<Assembly: AssemblyFileVersion("1.0.0.0")>
|
||||||
63
Test Datasheets/TestDataSheetUploader/My Project/Resources.Designer.vb
generated
Normal file
63
Test Datasheets/TestDataSheetUploader/My Project/Resources.Designer.vb
generated
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
'------------------------------------------------------------------------------
|
||||||
|
' <auto-generated>
|
||||||
|
' This code was generated by a tool.
|
||||||
|
' Runtime Version:4.0.30319.42000
|
||||||
|
'
|
||||||
|
' Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
' the code is regenerated.
|
||||||
|
' </auto-generated>
|
||||||
|
'------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Option Strict On
|
||||||
|
Option Explicit On
|
||||||
|
|
||||||
|
Imports System
|
||||||
|
|
||||||
|
Namespace My.Resources
|
||||||
|
|
||||||
|
'This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
'class via a tool like ResGen or Visual Studio.
|
||||||
|
'To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
'with the /str option, or rebuild your VS project.
|
||||||
|
'''<summary>
|
||||||
|
''' A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
'''</summary>
|
||||||
|
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0"), _
|
||||||
|
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||||
|
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||||
|
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
|
||||||
|
Friend Module Resources
|
||||||
|
|
||||||
|
Private resourceMan As Global.System.Resources.ResourceManager
|
||||||
|
|
||||||
|
Private resourceCulture As Global.System.Globalization.CultureInfo
|
||||||
|
|
||||||
|
'''<summary>
|
||||||
|
''' Returns the cached ResourceManager instance used by this class.
|
||||||
|
'''</summary>
|
||||||
|
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||||
|
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
|
||||||
|
Get
|
||||||
|
If Object.ReferenceEquals(resourceMan, Nothing) Then
|
||||||
|
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("TestDataSheetUploader.Resources", GetType(Resources).Assembly)
|
||||||
|
resourceMan = temp
|
||||||
|
End If
|
||||||
|
Return resourceMan
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
|
||||||
|
'''<summary>
|
||||||
|
''' Overrides the current thread's CurrentUICulture property for all
|
||||||
|
''' resource lookups using this strongly typed resource class.
|
||||||
|
'''</summary>
|
||||||
|
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||||
|
Friend Property Culture() As Global.System.Globalization.CultureInfo
|
||||||
|
Get
|
||||||
|
Return resourceCulture
|
||||||
|
End Get
|
||||||
|
Set
|
||||||
|
resourceCulture = value
|
||||||
|
End Set
|
||||||
|
End Property
|
||||||
|
End Module
|
||||||
|
End Namespace
|
||||||
117
Test Datasheets/TestDataSheetUploader/My Project/Resources.resx
Normal file
117
Test Datasheets/TestDataSheetUploader/My Project/Resources.resx
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
73
Test Datasheets/TestDataSheetUploader/My Project/Settings.Designer.vb
generated
Normal file
73
Test Datasheets/TestDataSheetUploader/My Project/Settings.Designer.vb
generated
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
'------------------------------------------------------------------------------
|
||||||
|
' <auto-generated>
|
||||||
|
' This code was generated by a tool.
|
||||||
|
' Runtime Version:4.0.30319.42000
|
||||||
|
'
|
||||||
|
' Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
' the code is regenerated.
|
||||||
|
' </auto-generated>
|
||||||
|
'------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Option Strict On
|
||||||
|
Option Explicit On
|
||||||
|
|
||||||
|
|
||||||
|
Namespace My
|
||||||
|
|
||||||
|
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||||
|
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0"), _
|
||||||
|
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||||
|
Partial Friend NotInheritable Class MySettings
|
||||||
|
Inherits Global.System.Configuration.ApplicationSettingsBase
|
||||||
|
|
||||||
|
Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings)
|
||||||
|
|
||||||
|
#Region "My.Settings Auto-Save Functionality"
|
||||||
|
#If _MyType = "WindowsForms" Then
|
||||||
|
Private Shared addedHandler As Boolean
|
||||||
|
|
||||||
|
Private Shared addedHandlerLockObject As New Object
|
||||||
|
|
||||||
|
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||||
|
Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs)
|
||||||
|
If My.Application.SaveMySettingsOnExit Then
|
||||||
|
My.Settings.Save()
|
||||||
|
End If
|
||||||
|
End Sub
|
||||||
|
#End If
|
||||||
|
#End Region
|
||||||
|
|
||||||
|
Public Shared ReadOnly Property [Default]() As MySettings
|
||||||
|
Get
|
||||||
|
|
||||||
|
#If _MyType = "WindowsForms" Then
|
||||||
|
If Not addedHandler Then
|
||||||
|
SyncLock addedHandlerLockObject
|
||||||
|
If Not addedHandler Then
|
||||||
|
AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
|
||||||
|
addedHandler = True
|
||||||
|
End If
|
||||||
|
End SyncLock
|
||||||
|
End If
|
||||||
|
#End If
|
||||||
|
Return defaultInstance
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
End Class
|
||||||
|
End Namespace
|
||||||
|
|
||||||
|
Namespace My
|
||||||
|
|
||||||
|
<Global.Microsoft.VisualBasic.HideModuleNameAttribute(), _
|
||||||
|
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||||
|
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute()> _
|
||||||
|
Friend Module MySettingsProperty
|
||||||
|
|
||||||
|
<Global.System.ComponentModel.Design.HelpKeywordAttribute("My.Settings")> _
|
||||||
|
Friend ReadOnly Property Settings() As Global.TestDataSheetUploader.My.MySettings
|
||||||
|
Get
|
||||||
|
Return Global.TestDataSheetUploader.My.MySettings.Default
|
||||||
|
End Get
|
||||||
|
End Property
|
||||||
|
End Module
|
||||||
|
End Namespace
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" UseMySettingsClassName="true">
|
||||||
|
<Profiles>
|
||||||
|
<Profile Name="(Default)" />
|
||||||
|
</Profiles>
|
||||||
|
<Settings />
|
||||||
|
</SettingsFile>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 14
|
||||||
|
VisualStudioVersion = 14.0.25420.1
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "TestDataSheetUploader", "TestDataSheetUploader\TestDataSheetUploader.vbproj", "{78941EA8-4EF5-4194-99CD-A08CBB7B52FB}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{78941EA8-4EF5-4194-99CD-A08CBB7B52FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{78941EA8-4EF5-4194-99CD-A08CBB7B52FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{78941EA8-4EF5-4194-99CD-A08CBB7B52FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{78941EA8-4EF5-4194-99CD-A08CBB7B52FB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{78941EA8-4EF5-4194-99CD-A08CBB7B52FB}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<StartupObject>TestDataSheetUploader.Module1</StartupObject>
|
||||||
|
<RootNamespace>TestDataSheetUploader</RootNamespace>
|
||||||
|
<AssemblyName>TestDataSheetUploader</AssemblyName>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<MyType>Console</MyType>
|
||||||
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<DefineDebug>true</DefineDebug>
|
||||||
|
<DefineTrace>true</DefineTrace>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DocumentationFile>TestDataSheetUploader.xml</DocumentationFile>
|
||||||
|
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
|
||||||
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<DefineDebug>false</DefineDebug>
|
||||||
|
<DefineTrace>true</DefineTrace>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DocumentationFile>TestDataSheetUploader.xml</DocumentationFile>
|
||||||
|
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
|
||||||
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<OptionExplicit>On</OptionExplicit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<OptionCompare>Binary</OptionCompare>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<OptionStrict>Off</OptionStrict>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<OptionInfer>On</OptionInfer>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Deployment" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Import Include="Microsoft.VisualBasic" />
|
||||||
|
<Import Include="System" />
|
||||||
|
<Import Include="System.Collections" />
|
||||||
|
<Import Include="System.Collections.Generic" />
|
||||||
|
<Import Include="System.Data" />
|
||||||
|
<Import Include="System.Diagnostics" />
|
||||||
|
<Import Include="System.Linq" />
|
||||||
|
<Import Include="System.Xml.Linq" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="HTTPUploader.vb" />
|
||||||
|
<Compile Include="Module1.vb" />
|
||||||
|
<Compile Include="My Project\AssemblyInfo.vb" />
|
||||||
|
<Compile Include="My Project\Application.Designer.vb">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Application.myapp</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="My Project\Resources.Designer.vb">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="My Project\Settings.Designer.vb">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Settings.settings</DependentUpon>
|
||||||
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="XMLData.vb" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="My Project\Resources.resx">
|
||||||
|
<Generator>VbMyResourcesResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.vb</LastGenOutput>
|
||||||
|
<CustomToolNamespace>My.Resources</CustomToolNamespace>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="app.config">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</None>
|
||||||
|
<None Include="My Project\Application.myapp">
|
||||||
|
<Generator>MyApplicationCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Application.Designer.vb</LastGenOutput>
|
||||||
|
</None>
|
||||||
|
<None Include="My Project\Settings.settings">
|
||||||
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
|
<CustomToolNamespace>My</CustomToolNamespace>
|
||||||
|
<LastGenOutput>Settings.Designer.vb</LastGenOutput>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
||||||
81
Test Datasheets/TestDataSheetUploader/XMLData.vb
Normal file
81
Test Datasheets/TestDataSheetUploader/XMLData.vb
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
Imports System.Xml
|
||||||
|
Imports System.Net
|
||||||
|
Imports System.IO
|
||||||
|
|
||||||
|
Namespace CSFramework_Utilities
|
||||||
|
|
||||||
|
Public Class XMLData
|
||||||
|
|
||||||
|
Public Shared Function XMLStringFromDataset(ByVal ds As DataSet) As String
|
||||||
|
Dim sw As New StringWriter()
|
||||||
|
ds.WriteXml(sw, XmlWriteMode.IgnoreSchema)
|
||||||
|
Return sw.ToString()
|
||||||
|
End Function
|
||||||
|
|
||||||
|
Public Shared Function DownloadXMLAsDataset(ByVal url As String, Optional ByVal credentials As Net.NetworkCredential = Nothing) As DataSet
|
||||||
|
|
||||||
|
Dim myXMLReader As XmlReader
|
||||||
|
Dim myDataSet As New DataSet
|
||||||
|
If credentials IsNot Nothing Then
|
||||||
|
Dim myXMLResolver As XmlUrlResolver = New XmlUrlResolver
|
||||||
|
myXMLResolver.Credentials = credentials
|
||||||
|
Dim myXMLSettings As XmlReaderSettings = New XmlReaderSettings
|
||||||
|
myXMLSettings.XmlResolver = myXMLResolver
|
||||||
|
myXMLReader = XmlReader.Create(url, myXMLSettings)
|
||||||
|
Else
|
||||||
|
myXMLReader = XmlReader.Create(url)
|
||||||
|
End If
|
||||||
|
myDataSet.ReadXml(myXMLReader)
|
||||||
|
Return myDataSet
|
||||||
|
End Function
|
||||||
|
|
||||||
|
|
||||||
|
Public Shared Function DownloadXMLWithDatasetPost(ByVal url As String, ByVal datasetToPost As DataSet, ByVal credentials As System.Net.NetworkCredential) As String
|
||||||
|
|
||||||
|
|
||||||
|
Dim xmlrequest As HttpWebRequest = WebRequest.Create(url)
|
||||||
|
xmlrequest.ContentType = "text/xml"
|
||||||
|
xmlrequest.Method = WebRequestMethods.Http.Post
|
||||||
|
xmlrequest.Credentials = credentials
|
||||||
|
xmlrequest.Timeout = 2000000
|
||||||
|
Try
|
||||||
|
|
||||||
|
Dim newStream As Stream = xmlrequest.GetRequestStream()
|
||||||
|
datasetToPost.WriteXml(newStream)
|
||||||
|
newStream.Close()
|
||||||
|
|
||||||
|
Dim xmlresponse As WebResponse = xmlrequest.GetResponse()
|
||||||
|
Dim responseStr As String = ConvertStreamToString(xmlresponse.GetResponseStream)
|
||||||
|
|
||||||
|
|
||||||
|
Return responseStr
|
||||||
|
|
||||||
|
Catch ex As Exception
|
||||||
|
Return "DownloadXMLWithDatasetPost ERROR: " & vbCrLf & ex.ToString
|
||||||
|
End Try
|
||||||
|
|
||||||
|
End Function
|
||||||
|
|
||||||
|
Public Shared Function ConvertStreamToString(ByVal InputStream As System.IO.Stream) As String
|
||||||
|
Dim sr As System.IO.StreamReader = New System.IO.StreamReader(InputStream)
|
||||||
|
Dim responseStr As String = sr.ReadToEnd()
|
||||||
|
Return responseStr
|
||||||
|
End Function
|
||||||
|
|
||||||
|
Public Shared Function DatasetFromXML(ByVal xml As String) As DataSet
|
||||||
|
|
||||||
|
Dim dataSet As DataSet = New DataSet
|
||||||
|
|
||||||
|
|
||||||
|
Dim xmlSR As System.IO.StringReader = New System.IO.StringReader(xml)
|
||||||
|
|
||||||
|
dataSet.ReadXml(xmlSR)
|
||||||
|
|
||||||
|
Return dataSet
|
||||||
|
|
||||||
|
End Function
|
||||||
|
|
||||||
|
|
||||||
|
End Class
|
||||||
|
|
||||||
|
End Namespace
|
||||||
40
Test Datasheets/TestDataSheetUploader/app.config
Normal file
40
Test Datasheets/TestDataSheetUploader/app.config
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<appSettings>
|
||||||
|
<add key="UploaderServiceURL" value="https://www.dataforth.com/Services/Uploader.aspx"/>
|
||||||
|
<add key="DirectoryManifestServiceURL" value="https://www.dataforth.com/Services/DirectoryManifest.aspx"/>
|
||||||
|
<add key="DeleteFileServiceURL" value="https://www.dataforth.com/Services/DeleteFile.aspx"/>
|
||||||
|
<add key="ServiceUsername" value="DataforthWebShare"/>
|
||||||
|
<add key="ServicePassword" value="Data6277"/>
|
||||||
|
|
||||||
|
<add key="TestDataSheetPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||||
|
<add key="TestFolderPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||||
|
|
||||||
|
<add key="InventoryDataStagingFolder" value="C:\TestDataSheetUploader\staging"/>
|
||||||
|
<add key="InventoryDataSourceFolder" value="C:\TestDataSheetUploader\src"/>
|
||||||
|
<add key="InventoryDataFiles" value="AvSelCat.csv,AvSelCus.csv"/>
|
||||||
|
|
||||||
|
<add key="TestMode" value="false"/>
|
||||||
|
|
||||||
|
</appSettings>
|
||||||
|
<system.diagnostics>
|
||||||
|
<sources>
|
||||||
|
<!-- This section defines the logging configuration for My.Application.Log -->
|
||||||
|
<source name="DefaultSource" switchName="DefaultSwitch">
|
||||||
|
<listeners>
|
||||||
|
<add name="FileLog"/>
|
||||||
|
<!-- Uncomment the below section to write to the Application Event Log -->
|
||||||
|
<!--<add name="EventLog"/>-->
|
||||||
|
</listeners>
|
||||||
|
</source>
|
||||||
|
</sources>
|
||||||
|
<switches>
|
||||||
|
<add name="DefaultSwitch" value="Information"/>
|
||||||
|
</switches>
|
||||||
|
<sharedListeners>
|
||||||
|
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/>
|
||||||
|
<!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
|
||||||
|
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
|
||||||
|
</sharedListeners>
|
||||||
|
</system.diagnostics>
|
||||||
|
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<appSettings>
|
||||||
|
<add key="UploaderServiceURL" value="https://www.dataforth.com/Services/Uploader.aspx"/>
|
||||||
|
<add key="DirectoryManifestServiceURL" value="https://www.dataforth.com/Services/DirectoryManifest.aspx"/>
|
||||||
|
<add key="DeleteFileServiceURL" value="https://www.dataforth.com/Services/DeleteFile.aspx"/>
|
||||||
|
<add key="ServiceUsername" value="DataforthWebShare"/>
|
||||||
|
<add key="ServicePassword" value="Data6277"/>
|
||||||
|
|
||||||
|
<add key="TestDataSheetPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||||
|
<add key="TestFolderPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||||
|
|
||||||
|
<add key="InventoryDataStagingFolder" value="C:\TestDataSheetUploader\staging"/>
|
||||||
|
<add key="InventoryDataSourceFolder" value="C:\TestDataSheetUploader\src"/>
|
||||||
|
<add key="InventoryDataFiles" value="AvSelCat.csv,AvSelCus.csv"/>
|
||||||
|
|
||||||
|
<add key="TestMode" value="false"/>
|
||||||
|
|
||||||
|
</appSettings>
|
||||||
|
<system.diagnostics>
|
||||||
|
<sources>
|
||||||
|
<!-- This section defines the logging configuration for My.Application.Log -->
|
||||||
|
<source name="DefaultSource" switchName="DefaultSwitch">
|
||||||
|
<listeners>
|
||||||
|
<add name="FileLog"/>
|
||||||
|
<!-- Uncomment the below section to write to the Application Event Log -->
|
||||||
|
<!--<add name="EventLog"/>-->
|
||||||
|
</listeners>
|
||||||
|
</source>
|
||||||
|
</sources>
|
||||||
|
<switches>
|
||||||
|
<add name="DefaultSwitch" value="Information"/>
|
||||||
|
</switches>
|
||||||
|
<sharedListeners>
|
||||||
|
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/>
|
||||||
|
<!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
|
||||||
|
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
|
||||||
|
</sharedListeners>
|
||||||
|
</system.diagnostics>
|
||||||
|
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
|
||||||
Binary file not shown.
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<appSettings>
|
||||||
|
<add key="UploaderServiceURL" value="https://www.dataforth.com/Services/Uploader.aspx"/>
|
||||||
|
<add key="DirectoryManifestServiceURL" value="https://www.dataforth.com/Services/DirectoryManifest.aspx"/>
|
||||||
|
<add key="DeleteFileServiceURL" value="https://www.dataforth.com/Services/DeleteFile.aspx"/>
|
||||||
|
<add key="ServiceUsername" value="DataforthWebShare"/>
|
||||||
|
<add key="ServicePassword" value="Data6277"/>
|
||||||
|
|
||||||
|
<add key="TestDataSheetPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||||
|
<add key="TestFolderPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||||
|
|
||||||
|
<add key="InventoryDataStagingFolder" value="C:\TestDataSheetUploader\staging"/>
|
||||||
|
<add key="InventoryDataSourceFolder" value="C:\TestDataSheetUploader\src"/>
|
||||||
|
<add key="InventoryDataFiles" value="AvSelCat.csv,AvSelCus.csv"/>
|
||||||
|
|
||||||
|
<add key="TestMode" value="false"/>
|
||||||
|
|
||||||
|
</appSettings>
|
||||||
|
<system.diagnostics>
|
||||||
|
<sources>
|
||||||
|
<!-- This section defines the logging configuration for My.Application.Log -->
|
||||||
|
<source name="DefaultSource" switchName="DefaultSwitch">
|
||||||
|
<listeners>
|
||||||
|
<add name="FileLog"/>
|
||||||
|
<!-- Uncomment the below section to write to the Application Event Log -->
|
||||||
|
<!--<add name="EventLog"/>-->
|
||||||
|
</listeners>
|
||||||
|
</source>
|
||||||
|
</sources>
|
||||||
|
<switches>
|
||||||
|
<add name="DefaultSwitch" value="Information"/>
|
||||||
|
</switches>
|
||||||
|
<sharedListeners>
|
||||||
|
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/>
|
||||||
|
<!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
|
||||||
|
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
|
||||||
|
</sharedListeners>
|
||||||
|
</system.diagnostics>
|
||||||
|
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
|
||||||
|
</requestedPrivileges>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
</assembly>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<doc>
|
||||||
|
<assembly>
|
||||||
|
<name>
|
||||||
|
TestDataSheetUploader
|
||||||
|
</name>
|
||||||
|
</assembly>
|
||||||
|
<members>
|
||||||
|
<member name="T:TestDataSheetUploader.My.Resources.Resources">
|
||||||
|
<summary>
|
||||||
|
A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:TestDataSheetUploader.My.Resources.Resources.ResourceManager">
|
||||||
|
<summary>
|
||||||
|
Returns the cached ResourceManager instance used by this class.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:TestDataSheetUploader.My.Resources.Resources.Culture">
|
||||||
|
<summary>
|
||||||
|
Overrides the current thread's CurrentUICulture property for all
|
||||||
|
resource lookups using this strongly typed resource class.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
</members>
|
||||||
|
</doc>
|
||||||
477923
Test Datasheets/TestDataSheetUploader/bin/Debug/manifest.xml
Normal file
477923
Test Datasheets/TestDataSheetUploader/bin/Debug/manifest.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
|||||||
|
08/22/YYYY 15:47:17 | SyncFolder(TestFolder) started.
|
||||||
|
08/22/YYYY 15:47:32 | Upload FAILED for C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists\Custom Product Listing.pdf
|
||||||
|
08/22/YYYY 15:47:32 | Upload FAIL MESSAGE: GSSG Service Upload Error: UploadType not recognized: TestFolder
|
||||||
|
08/22/YYYY 15:47:32 | Upload FAILED for C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists\Custom Product Rules.pdf
|
||||||
|
08/22/YYYY 15:47:32 | Upload FAIL MESSAGE: GSSG Service Upload Error: UploadType not recognized: TestFolder
|
||||||
|
08/22/YYYY 15:47:32 | No obsolete TestFolder files were detected.
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
08/22/YYYY 15:51:12 | SyncFolder(TestFolder) started.
|
||||||
|
08/22/YYYY 15:51:15 | Upload FAILED for C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists\Custom Product Listing.pdf
|
||||||
|
08/22/YYYY 15:51:15 | Upload FAIL MESSAGE: Dataforth Service Upload Error: Access to the path 'C:\inetpub\wwwroot\dataforth.com\WebShare\ProcessCheckOutTestFolder\Custom Product Listing.pdf' is denied.
|
||||||
|
08/22/YYYY 15:51:15 | Upload FAILED for C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists\Custom Product Rules.pdf
|
||||||
|
08/22/YYYY 15:51:15 | Upload FAIL MESSAGE: Dataforth Service Upload Error: Access to the path 'C:\inetpub\wwwroot\dataforth.com\WebShare\ProcessCheckOutTestFolder\Custom Product Rules.pdf' is denied.
|
||||||
|
08/22/YYYY 15:51:15 | No obsolete TestFolder files were detected.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
08/22/YYYY 15:57:38 | SyncFolder(TestFolder) started.
|
||||||
|
08/22/YYYY 15:57:39 | Uploaded file: C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists\Custom Product Listing.pdf
|
||||||
|
08/22/YYYY 15:57:40 | Uploaded file: C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists\Custom Product Rules.pdf
|
||||||
|
08/22/YYYY 15:57:40 | No obsolete TestFolder files were detected.
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
08/22/YYYY 16:00:07 | SyncFolder(TestDataSheet) started.
|
||||||
|
08/22/YYYY 16:02:13 | Exception in SyncFolder: System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.
|
||||||
|
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
|
||||||
|
at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace()
|
||||||
|
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
|
||||||
|
at System.Xml.XmlReader.MoveToContent()
|
||||||
|
at System.Data.DataSet.ReadXml(XmlReader reader, Boolean denyResolving)
|
||||||
|
at CSFramework.CSFramework_Utilities.XMLData.DatasetFromXML(String xml) in C:\Users\hoffm\Documents\Visual Studio 2015\Projects\OEMData\CSFramework\CSFramework\CSFramework_Utilities\XMLData.vb:line 66
|
||||||
|
at TestDataSheetUploader.Module1.SyncFolder(String FolderAlias) in C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\Module1.vb:line 81
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
03/31/YYYY 16:13:55 | SyncFolder(InventoryDataFolder) started.
|
||||||
|
03/31/YYYY 16:14:00 | Exception in SyncFolder: System.Xml.XmlException: Root element is missing.
|
||||||
|
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
|
||||||
|
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
|
||||||
|
at System.Xml.XmlReader.MoveToContent()
|
||||||
|
at System.Data.DataSet.ReadXml(XmlReader reader, Boolean denyResolving)
|
||||||
|
at TestDataSheetUploader.CSFramework_Utilities.XMLData.DatasetFromXML(String xml) in C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\XMLData.vb:line 72
|
||||||
|
at TestDataSheetUploader.Module1.SyncFolder(String FolderAlias) in C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\Module1.vb:line 112
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
03/31/YYYY 16:18:48 | SyncFolder(InventoryDataFolder) started.
|
||||||
|
03/31/YYYY 16:19:34 | Exception in SyncFolder: System.NullReferenceException: Object reference not set to an instance of an object.
|
||||||
|
at TestDataSheetUploader.Module1.SyncFolder(String FolderAlias) in C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\Module1.vb:line 114
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
03/31/YYYY 16:20:24 | SyncFolder(InventoryDataFolder) started.
|
||||||
|
03/31/YYYY 16:20:30 | Manifest downloaded with 1 files.
|
||||||
|
03/31/YYYY 16:20:30 | Accessing local folder: C:\TestDataSheetUploader\staging
|
||||||
|
03/31/YYYY 16:20:30 | Found at least 1 file in local folder
|
||||||
|
03/31/YYYY 16:20:30 | Requesting upload: AvSelCat.csv
|
||||||
|
03/31/YYYY 16:20:30 | Requesting upload: AvSelCus.csv
|
||||||
|
03/31/YYYY 16:20:30 | Found 2 files that need to be uploaded.
|
||||||
|
03/31/YYYY 16:20:41 | Requested InventoryDataFolder Delete: New Text Document.txt
|
||||||
|
03/31/YYYY 16:20:41 | Found 1 files to delete.
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<appSettings>
|
||||||
|
<add key="UploaderServiceURL" value="https://www.dataforth.com/Services/Uploader.aspx"/>
|
||||||
|
<add key="DirectoryManifestServiceURL" value="https://www.dataforth.com/Services/DirectoryManifest.aspx"/>
|
||||||
|
<add key="DeleteFileServiceURL" value="https://www.dataforth.com/Services/DeleteFile.aspx"/>
|
||||||
|
<add key="ServiceUsername" value="DataforthWebShare"/>
|
||||||
|
<add key="ServicePassword" value="Data6277"/>
|
||||||
|
|
||||||
|
<add key="TestDataSheetPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||||
|
<add key="TestFolderPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||||
|
|
||||||
|
<add key="InventoryDataStagingFolder" value="C:\TestDataSheetUploader\staging"/>
|
||||||
|
<add key="InventoryDataSourceFolder" value="C:\TestDataSheetUploader\src"/>
|
||||||
|
<add key="InventoryDataFiles" value="AvSelCat.csv,AvSelCus.csv"/>
|
||||||
|
|
||||||
|
<add key="TestMode" value="false"/>
|
||||||
|
|
||||||
|
</appSettings>
|
||||||
|
<system.diagnostics>
|
||||||
|
<sources>
|
||||||
|
<!-- This section defines the logging configuration for My.Application.Log -->
|
||||||
|
<source name="DefaultSource" switchName="DefaultSwitch">
|
||||||
|
<listeners>
|
||||||
|
<add name="FileLog"/>
|
||||||
|
<!-- Uncomment the below section to write to the Application Event Log -->
|
||||||
|
<!--<add name="EventLog"/>-->
|
||||||
|
</listeners>
|
||||||
|
</source>
|
||||||
|
</sources>
|
||||||
|
<switches>
|
||||||
|
<add name="DefaultSwitch" value="Information"/>
|
||||||
|
</switches>
|
||||||
|
<sharedListeners>
|
||||||
|
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/>
|
||||||
|
<!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
|
||||||
|
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
|
||||||
|
</sharedListeners>
|
||||||
|
</system.diagnostics>
|
||||||
|
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
|
||||||
Binary file not shown.
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<appSettings>
|
||||||
|
<add key="UploaderServiceURL" value="https://www.dataforth.com/Services/Uploader.aspx"/>
|
||||||
|
<add key="DirectoryManifestServiceURL" value="https://www.dataforth.com/Services/DirectoryManifest.aspx"/>
|
||||||
|
<add key="DeleteFileServiceURL" value="https://www.dataforth.com/Services/DeleteFile.aspx"/>
|
||||||
|
<add key="ServiceUsername" value="DataforthWebShare"/>
|
||||||
|
<add key="ServicePassword" value="Data6277"/>
|
||||||
|
|
||||||
|
<add key="TestDataSheetPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||||
|
<add key="TestFolderPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||||
|
|
||||||
|
<add key="InventoryDataStagingFolder" value="C:\TestDataSheetUploader\staging"/>
|
||||||
|
<add key="InventoryDataSourceFolder" value="C:\TestDataSheetUploader\src"/>
|
||||||
|
<add key="InventoryDataFiles" value="AvSelCat.csv,AvSelCus.csv"/>
|
||||||
|
|
||||||
|
<add key="TestMode" value="false"/>
|
||||||
|
|
||||||
|
</appSettings>
|
||||||
|
<system.diagnostics>
|
||||||
|
<sources>
|
||||||
|
<!-- This section defines the logging configuration for My.Application.Log -->
|
||||||
|
<source name="DefaultSource" switchName="DefaultSwitch">
|
||||||
|
<listeners>
|
||||||
|
<add name="FileLog"/>
|
||||||
|
<!-- Uncomment the below section to write to the Application Event Log -->
|
||||||
|
<!--<add name="EventLog"/>-->
|
||||||
|
</listeners>
|
||||||
|
</source>
|
||||||
|
</sources>
|
||||||
|
<switches>
|
||||||
|
<add name="DefaultSwitch" value="Information"/>
|
||||||
|
</switches>
|
||||||
|
<sharedListeners>
|
||||||
|
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/>
|
||||||
|
<!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
|
||||||
|
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
|
||||||
|
</sharedListeners>
|
||||||
|
</system.diagnostics>
|
||||||
|
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
|
||||||
|
</requestedPrivileges>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
</assembly>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<doc>
|
||||||
|
<assembly>
|
||||||
|
<name>
|
||||||
|
TestDataSheetUploader
|
||||||
|
</name>
|
||||||
|
</assembly>
|
||||||
|
<members>
|
||||||
|
<member name="T:TestDataSheetUploader.My.Resources.Resources">
|
||||||
|
<summary>
|
||||||
|
A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:TestDataSheetUploader.My.Resources.Resources.ResourceManager">
|
||||||
|
<summary>
|
||||||
|
Returns the cached ResourceManager instance used by this class.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:TestDataSheetUploader.My.Resources.Resources.Culture">
|
||||||
|
<summary>
|
||||||
|
Overrides the current thread's CurrentUICulture property for all
|
||||||
|
resource lookups using this strongly typed resource class.
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
</members>
|
||||||
|
</doc>
|
||||||
Binary file not shown.
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<FolderContents>
|
||||||
|
<ContentFile>
|
||||||
|
<Filename>AvSelCat.csv</Filename>
|
||||||
|
<Filesize>10900</Filesize>
|
||||||
|
<DateLastUpdated>2019-06-06T05:10:18.549187Z</DateLastUpdated>
|
||||||
|
</ContentFile>
|
||||||
|
<ContentFile>
|
||||||
|
<Filename>AvSelCus.csv</Filename>
|
||||||
|
<Filesize>2529</Filesize>
|
||||||
|
<DateLastUpdated>2019-06-06T01:10:32.1961739Z</DateLastUpdated>
|
||||||
|
</ContentFile>
|
||||||
|
</FolderContents>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
' <autogenerated/>
|
||||||
|
Option Strict Off
|
||||||
|
Option Explicit On
|
||||||
|
|
||||||
|
Imports System
|
||||||
|
Imports System.Reflection
|
||||||
|
<Assembly: Global.System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName:=".NET Framework 4.7.2")>
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
ff0a48e8544663eb773da2d9d956c2efd790e83a
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\bin\Debug\TestDataSheetUploader.exe.config
|
||||||
|
C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\bin\Debug\TestDataSheetUploader.exe
|
||||||
|
C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\bin\Debug\TestDataSheetUploader.pdb
|
||||||
|
C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\bin\Debug\TestDataSheetUploader.xml
|
||||||
|
C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\obj\Debug\TestDataSheetUploader.Resources.resources
|
||||||
|
C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\obj\Debug\TestDataSheetUploader.vbproj.GenerateResource.Cache
|
||||||
|
C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\obj\Debug\TestDataSheetUploader.exe
|
||||||
|
C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\obj\Debug\TestDataSheetUploader.xml
|
||||||
|
C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\obj\Debug\TestDataSheetUploader.pdb
|
||||||
|
C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\obj\Debug\TestDataSheetUploader.vbprojResolveAssemblyReference.cache
|
||||||
|
C:\Users\kennethhoffman\source\repos\dataforth-enterprise\TestDataSheetUploader\TestDataSheetUploader\bin\Debug\TestDataSheetUploader.exe.config
|
||||||
|
C:\Users\kennethhoffman\source\repos\dataforth-enterprise\TestDataSheetUploader\TestDataSheetUploader\bin\Debug\TestDataSheetUploader.exe
|
||||||
|
C:\Users\kennethhoffman\source\repos\dataforth-enterprise\TestDataSheetUploader\TestDataSheetUploader\bin\Debug\TestDataSheetUploader.pdb
|
||||||
|
C:\Users\kennethhoffman\source\repos\dataforth-enterprise\TestDataSheetUploader\TestDataSheetUploader\bin\Debug\TestDataSheetUploader.xml
|
||||||
|
C:\Users\kennethhoffman\source\repos\dataforth-enterprise\TestDataSheetUploader\TestDataSheetUploader\obj\Debug\TestDataSheetUploader.vbproj.AssemblyReference.cache
|
||||||
|
C:\Users\kennethhoffman\source\repos\dataforth-enterprise\TestDataSheetUploader\TestDataSheetUploader\obj\Debug\TestDataSheetUploader.vbproj.SuggestedBindingRedirects.cache
|
||||||
|
C:\Users\kennethhoffman\source\repos\dataforth-enterprise\TestDataSheetUploader\TestDataSheetUploader\obj\Debug\TestDataSheetUploader.Resources.resources
|
||||||
|
C:\Users\kennethhoffman\source\repos\dataforth-enterprise\TestDataSheetUploader\TestDataSheetUploader\obj\Debug\TestDataSheetUploader.vbproj.GenerateResource.cache
|
||||||
|
C:\Users\kennethhoffman\source\repos\dataforth-enterprise\TestDataSheetUploader\TestDataSheetUploader\obj\Debug\TestDataSheetUploader.vbproj.CoreCompileInputs.cache
|
||||||
|
C:\Users\kennethhoffman\source\repos\dataforth-enterprise\TestDataSheetUploader\TestDataSheetUploader\obj\Debug\TestDataSheetUploader.exe
|
||||||
|
C:\Users\kennethhoffman\source\repos\dataforth-enterprise\TestDataSheetUploader\TestDataSheetUploader\obj\Debug\TestDataSheetUploader.xml
|
||||||
|
C:\Users\kennethhoffman\source\repos\dataforth-enterprise\TestDataSheetUploader\TestDataSheetUploader\obj\Debug\TestDataSheetUploader.pdb
|
||||||
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user