diff --git a/.claude/INDEX.md b/.claude/INDEX.md new file mode 100644 index 00000000..e076d86d --- /dev/null +++ b/.claude/INDEX.md @@ -0,0 +1,116 @@ +# ShopDB Index - Load Only What You Need + +Quick pointers to avoid reading entire wiki or codebase. + +## When Working On... + +**Plugin development**: +- Read: `CLAUDE.md` (overview) +- Grep: `class BasePlugin` in `shopdb/api/__init__.py` +- Reference: `../shopdb-flask.wiki/ADR-001-asset-as-platform-contract.md` + +**Database migrations**: +- Read: `../shopdb-flask.wiki/ADR-008-plugin-migration-ownership.md` +- Grep: `PLUGIN_TABLE_OWNERS` for dependency order +- Pattern: `plugins/{name}/migrations/versions/*.py` + +**Site-specific config**: +- Read: `../shopdb-flask.wiki/ADR-015-site-specific-configuration.md` +- Locations: `shopdb/core/settings/`, `shopdb/core/seed/`, `scripts/site_imports/` + +**Kiosk/device auth**: +- Read: `../shopdb-flask.wiki/ADR-016-credential-delivery.md` +- Grep: `requires_device_token` + +**Deployment/branches**: +- Read: `../shopdb-flask.wiki/ADR-004-deployment-topology.md` +- Scripts: `~/Documents/github/*.cmd` + +**Frontend plugin panels**: +- Read: `../shopdb-flask.wiki/ADR-010-frontend-plugin-hooks.md` +- Pattern: `plugins/{name}/frontend/views/*.vue` + +**Testing**: +- Read: `tests/conftest.py` for fixtures +- Pattern: `tests/test_plugins/test_{plugin}_{feature}.py` + +## Plugin Map (20 plugins) + +Core asset types: +- `computers`, `endpoints`, `printers`, `machines`, `measuringtools`, `network`, `tools` + +Workflows: +- `printedparts`, `usb`, `slides`, `notifications` + +Integrations: +- `warranty`, `geenforce`, `guides`, `knowledgebase` + +Admin: +- `employees`, `backups` + +## Key Files + +- `shopdb/api/__init__.py` - Stable import surface (75 lines) +- `shopdb/config.py` - App configuration +- `shopdb/core/models/asset.py` - Base asset model +- `docker-compose.yml` - Dev stack definition +- `scripts/check-naming-and-style.sh` - Pre-commit hook + +## Git Branches + +**Current repo state**: +- `wj` (checked out) - Prod branch for WJ shop floor +- `main` - Public GitHub mirror, deploys nowhere +- `origin/wilm` - Upstream changes from benjamin.baker (86 commits ahead) +- `origin/dev-be` - Historical dev branch + +**Branch workflow** (ADR-004): +- `wj` -> prod deployment (WJ site) +- `dev` -> ops deployment (monitoring/pilot sites, on gitea only) +- `main` -> GitHub public mirror only (no deployments) +- `wilm` -> fetch from GitHub, review, merge to wj or dev + +**On this work PC**: +- Has GitHub credentials (ge-aero/shopdb-flask) +- Fetch wilm: `~/Documents/github/fetch-wilm-branch.cmd` +- Bundle to dev PC: `~/Documents/github/pull-shopdb-bundle.cmd` + +## Common Paths + +- Plugin code: `plugins/{name}/` +- Core models: `shopdb/core/models/` +- Core API: `shopdb/core/api/` +- Frontend core: `frontend/src/` +- Tests: `tests/test_plugins/` +- Migrations: `migrations/` (core) + `plugins/{name}/migrations/` +- Scripts: `scripts/` +- Docs: `../shopdb-flask.wiki/` + +## Avoid Reading These Unless Needed + +- `docs/openapi.json` (489 lines, generated) +- `frontend/dist/` (build output) +- `node_modules/`, `venv/`, `.pytest_cache/` +- `agent/` (C# endpoint agent, 10k+ lines) +- Full wiki (68 files) - use index above + +## Token-Efficient Patterns + +1. **Grep before Read**: Find the exact file/function first +2. **Read with limit**: Use offset/limit for large files +3. **Reference by path**: Cite `file:line` instead of quoting code +4. **Use memory**: Store repeated patterns in memory files +5. **Wiki on-demand**: Only read specific ADRs when relevant + +## One-Line ADR Summaries + +- ADR-001: Asset is the platform primitive for all equipment +- ADR-004: Three air-gapped environments, bundle workflow +- ADR-006: Endpoint agent sends telemetry, receives commands +- ADR-007: Semantic versioning, GitHub releases +- ADR-008: Each plugin owns its migration chain, no conflicts +- ADR-009: Frontend plugins gate on backend features +- ADR-010: Plugins register Vue components via manifest +- ADR-013: Lean builds include only needed plugins +- ADR-015: Site literals go in settings/seed/site_imports only +- ADR-016: Kiosks use device tokens, not user sessions diff --git a/.claude/QUICK-REFERENCE.md b/.claude/QUICK-REFERENCE.md new file mode 100644 index 00000000..75232567 --- /dev/null +++ b/.claude/QUICK-REFERENCE.md @@ -0,0 +1,152 @@ +# ShopDB Quick Reference + +Fast lookup for architectural decisions and contracts. + +## Critical ADRs (in wiki) + +- **ADR-001**: Asset as platform contract - Core asset model, BaseAsset, composition +- **ADR-004**: Deployment topology - Air-gapped sites, bundle workflow +- **ADR-006**: Collector contract - Endpoint agent protocol +- **ADR-007**: Product versioning - Semantic versioning, release process +- **ADR-008**: Plugin migration ownership - PLUGIN_TABLE_OWNERS, migration chains +- **ADR-013**: Plugin catalog - Lean builds, plugin manifest +- **ADR-015**: Site-specific configuration - Where site literals belong +- **ADR-016**: Credential delivery - Device tokens, kiosk auth + +## Import Surface (stable API) + +```python +from shopdb.api import ( + # Database + db, + + # Core Models + Asset, Employee, User, Building, MapLevel, + + # Plugin Base + BasePlugin, + + # Auth/Authz + requires_role, requires_device_token, + + # Utilities + badges, datevalues, queryargs +) +``` + +## Plugin Structure + +``` +plugins/{name}/ +|-- plugin.py # BasePlugin subclass, manifest +|-- models/ # SQLAlchemy models +| +-- {name}.py +|-- api/ # Flask routes +| +-- routes.py +|-- frontend/ # Vue components +| +-- views/ +| |-- {Name}List.vue +| |-- {Name}Detail.vue +| +-- {Name}Form.vue +|-- migrations/ # Alembic migrations +| +-- versions/ ++-- services/ # Business logic (optional) +``` + +## Database Naming + +- **Tables**: `printedpart`, `mappeddrives` (lowercase concatenated) +- **Columns**: `serial_number`, `last_seen` (snake_case) +- **Enforced**: `scripts/check-naming-and-style.sh` + +## Branch Model + +- `wj` -> prod (WJ shop floor) +- `dev` -> ops (monitoring/pilot) +- `main` -> public mirror (GitHub only) +- `wilm` -> upstream (benjamin.baker's changes) + +## Common Commands + +```bash +# Run tests +pytest -v + +# Check style +scripts/check-naming-and-style.sh + +# Create migration +cd plugins/{name} +alembic revision -m "description" + +# Dev server +docker compose up + +# Bundle for dev PC +# (on work PC) ~/Documents/github/pull-shopdb-bundle.cmd + +# Fetch wilm changes +# (on work PC) ~/Documents/github/fetch-wilm-branch.cmd +``` + +## Test Patterns + +```python +def test_feature(client, db_session): + # Setup + item = Model(name="test") + db_session.add(item) + db_session.commit() + + # Execute + resp = client.get('/api/plugin/endpoint') + + # Assert + assert resp.status_code == 200 + assert resp.json['name'] == 'test' +``` + +## Site Data Rules (ADR-015) + +[OK] **Allowed**: +- `shopdb/core/settings/buildings.py` +- `shopdb/core/seed/*.sql` +- `scripts/site_imports/*.py` + +[FAIL] **Forbidden**: +- Hardcoded in plugin code +- Embedded in migrations +- Configuration files + +## Migration Ownership (ADR-008) + +Each plugin owns its chain. Coordinate cross-plugin FK changes via PLUGIN_TABLE_OWNERS: + +```python +PLUGIN_TABLE_OWNERS = { + 'asset': 'core', + 'employee': 'employees', + 'pc': 'computers', + 'endpoint': 'endpoints', + # ... +} +``` + +## Device Tokens (ADR-016) + +Kiosks require device authentication: + +```python +from shopdb.api import requires_device_token + +@bp.route('/kiosk/endpoint') +@requires_device_token(['usb_kiosk', 'parts_kiosk']) +def kiosk_view(): + return render_template('kiosk.html') +``` + +## Wiki Location + +Full docs: `~/Documents/github/shopdb-flask.wiki/` + +All ADRs, deployment guides, plugin development docs live there. diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 00000000..eacab37f --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,27 @@ +{ + "permissions": { + "allow": [ + "bash:pytest*", + "bash:git status", + "bash:git log*", + "bash:git diff*", + "bash:git branch*", + "bash:docker compose*", + "bash:docker ps", + "bash:alembic*", + "bash:python scripts/*", + "grep:**", + "glob:**" + ] + }, + "hooks": { + "beforeCommit": [ + "scripts/check-naming-and-style.sh" + ] + }, + "context": { + "alwaysInclude": [ + ".claude/INDEX.md" + ] + } +} diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..abd32fc9 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,129 @@ +# ShopDB Flask - Claude Code Context + +ShopDB is a manufacturing floor asset management system built with Flask, Vue 3, and PostgreSQL, deployed across air-gapped GE Aerospace sites. + +## Architecture + +- **Backend**: Flask 3.x with SQLAlchemy 2.x, plugin-based architecture +- **Frontend**: Vue 3 with Vite, component-based UI with plugin panels +- **Database**: PostgreSQL 15+ with Alembic migrations per plugin +- **Deployment**: Docker Compose with gunicorn, air-gapped sites via bundle workflow +- **Plugins**: 20+ plugins (computers, endpoints, printers, machines, etc.) + +## Critical Constraints + +### ADR-015: Site-Specific Configuration +Site literals (building names, printer models, machine types) MUST live in: +- `shopdb/core/settings/` - Site settings (buildings, roles, etc.) +- `shopdb/core/seed/` - Initial data SQL +- `scripts/site_imports/` - Import tools for Maximo/WINC data + +NEVER hardcode site-specific data in plugin code or migrations. + +### ADR-008: Plugin Migration Ownership +Each plugin owns its migration chain in `plugins/{name}/migrations/versions/`. +- Migrations run in dependency order defined in PLUGIN_TABLE_OWNERS +- Each plugin's chain must be linear (no branches) +- Migrations run automatically on deploy + +### Database Naming Convention +- **Tables**: lowercase concatenated, no underscores (e.g., `printedpart`, `mappeddrives`) +- **Columns**: snake_case (e.g., `serial_number`, `last_seen`) +- **Indexes/constraints**: follow PostgreSQL conventions +- Enforced by `scripts/check-naming-and-style.sh` pre-commit hook + +### Branch and Deployment Model +- `wj` -> prod (shop floor at WJ site) +- `dev` -> ops (monitoring/pilot sites) +- `main` -> nothing (GitHub public mirror only) +- Three air gaps: dev PC <-> work PC <-> GitHub +- Bundles carry code across gaps (pull-shopdb-bundle.cmd, fetch-wilm-branch.cmd) + +### Code Style +- Plain ASCII only - no unicode, emojis, or em-dashes +- No LLM attribution comments (no "Co-Authored-By: Claude") +- Minimal comments - code should be self-documenting +- No banned shorthand (e.g., "config" not "cfg", "initialize" not "init") + +## Plugin Contract + +Plugins extend ShopDB via: +- `plugin.py` - BasePlugin subclass with manifest, routes, hooks +- `models/` - SQLAlchemy models +- `api/` - Flask blueprints and routes +- `frontend/views/` - Vue components auto-discovered by router +- `migrations/versions/` - Alembic migrations + +Import from `shopdb.api` for stable surfaces: +```python +from shopdb.api import db, Asset, Employee, BasePlugin +``` + +## Documentation + +Full documentation in the GitHub wiki at `../shopdb-flask.wiki/`: + +**Critical ADRs**: +- ADR-001: Asset as platform contract +- ADR-004: Deployment topology (air-gapped sites) +- ADR-006: Collector contract (endpoint agent) +- ADR-007: Product versioning and releases +- ADR-013: Plugin catalog and lean builds +- ADR-016: Credential delivery + +**References**: +- `API-REFERENCE.md` - Core API surface +- `PLUGIN-DEVELOPMENT.md` - Plugin authoring guide +- `DEPLOYMENT.md` - Deploy runbooks per site +- `TESTING.md` - Test patterns and CI + +## Development Workflow + +1. Feature branches off `dev` or `wj` +2. **Run tests**: `pytest -v` (REQUIRED before claiming completion) +3. **Check naming/style**: `scripts/check-naming-and-style.sh` (REQUIRED before commit) +4. Bundle for other PC or push to GitHub +5. PR to `wj` (for prod) or `dev` (for ops) + +## Boundaries & Constraints + +**DO NOT**: +- Edit generated files (frontend/dist/, docs/openapi.json) +- Change dependencies (requirements.txt, package.json) without approval +- Commit code with unicode/emojis (plain ASCII only) +- Hardcode site-specific data (buildings, models, etc.) - use settings/seed +- Skip tests or pre-commit hooks +- Break plugin migration chains (keep linear, coordinate via PLUGIN_TABLE_OWNERS) + +**ALWAYS**: +- Run `pytest -v` before claiming work complete +- Run `scripts/check-naming-and-style.sh` before committing +- Use `shopdb.api` imports, not internal paths +- Keep database table names lowercase concatenated +- Reference ADRs by number when making architectural decisions +- Verify bundle/deploy scripts work before pushing to branches + +## Testing Patterns + +- Feature tests in `tests/test_plugins/test_{plugin}_{feature}.py` +- Use fixtures from `conftest.py` (app, client, db_session) +- Test migrations with `test_plugin_migrations.py` +- Frontend specs alongside components: `*.spec.js` + +## Common Pitfalls + +- **Site data in code**: Use settings/seed, not hardcoded values +- **Migration conflicts**: Keep plugin chains linear, coordinate with PLUGIN_TABLE_OWNERS +- **Unicode**: ASCII only - check logs, comments, commit messages +- **Import surface**: Use `shopdb.api`, not internal paths +- **Device tokens**: Kiosks require device_token authentication (ADR-016) + +## Work PC Role + +This machine (work PC): +- Has GitHub credentials (ge-aero/shopdb-flask) +- Carries bundles between dev PC and GitHub +- Deploys to prod and ops servers +- Mirrors wilm branch from GitHub to gitea + +For active development, use the dev PC with gitea. diff --git a/DEPLOY-TO-VM.md b/DEPLOY-TO-VM.md index 17002a42..83cd1fdf 100644 --- a/DEPLOY-TO-VM.md +++ b/DEPLOY-TO-VM.md @@ -53,13 +53,13 @@ cd C:\shopdb ## What the Script Does -1. ✅ Checks Docker Desktop is running -2. ✅ Creates .env from template -3. ✅ Builds frontend (if needed) -4. ✅ Builds Docker images (2-3 minutes, offline packages) -5. ✅ Starts all services (db + api + backup) -6. ✅ Runs database migrations -7. ✅ Sets admin password +1. [OK] Checks Docker Desktop is running +2. [OK] Creates .env from template +3. [OK] Builds frontend (if needed) +4. [OK] Builds Docker images (2-3 minutes, offline packages) +5. [OK] Starts all services (db + api + backup) +6. [OK] Runs database migrations +7. [OK] Sets admin password ## Manual Deployment (Alternative) @@ -140,7 +140,7 @@ New-NetFirewallRule -DisplayName "ShopDB" -Direction Inbound -LocalPort 5001 -Pr **SSL certificate warnings:** - Normal for self-signed certs -- Click "Advanced" → "Proceed to localhost (unsafe)" +- Click "Advanced" -> "Proceed to localhost (unsafe)" ## Stop/Start @@ -169,9 +169,9 @@ docker compose -f docker-compose.prebuilt.yml -f docker-compose.backup.yml up -d ## Offline Deployment Notes **This deployment works completely offline** because: -- ✅ Frontend pre-built and checked into repo -- ✅ Restic binary pre-downloaded (8.6MB in repo) -- ✅ No npm/pip downloads during Docker build -- ✅ All dependencies baked into images +- [OK] Frontend pre-built and checked into repo +- [OK] Restic binary pre-downloaded (8.6MB in repo) +- [OK] No npm/pip downloads during Docker build +- [OK] All dependencies baked into images Perfect for air-gapped or restricted network environments! diff --git a/DOCKER-DEPLOYMENT-COMPLETE.md b/DOCKER-DEPLOYMENT-COMPLETE.md index 0124f7d9..255e6b7f 100644 --- a/DOCKER-DEPLOYMENT-COMPLETE.md +++ b/DOCKER-DEPLOYMENT-COMPLETE.md @@ -2,7 +2,7 @@ **Date:** 2026-09-07 **Branch:** wj (post-wilm merge) -**Status:** ✅ Core system operational, backup watcher pending +**Status:** [OK] Core system operational, backup watcher pending ## What's Running @@ -145,7 +145,7 @@ docker exec flask-shopdb-api-1 flask plugin disable PLUGIN_NAME ### Backup Watcher Service -**Status:** ❌ Build failed +**Status:** [FAIL] Build failed **Reason:** Oracle Linux base image can't download packages due to SSL cert issues with Zscaler **Impact:** Can't auto-execute backups on schedule (manual backups still work via one-shot container) @@ -166,9 +166,9 @@ Cannot download repomd.xml: Curl error (60): SSL peer certificate or SSH remote ## Production Readiness -**Core Application:** ✅ Production ready -**Deployment Process:** ⚠️ Requires npm on host + Docker build -**Backup System:** ❌ Not complete (watcher service build fails) +**Core Application:** [OK] Production ready +**Deployment Process:** [WARN] Requires npm on host + Docker build +**Backup System:** [FAIL] Not complete (watcher service build fails) ### Recommended Next Steps @@ -191,9 +191,9 @@ Cannot download repomd.xml: Curl error (60): SSL peer certificate or SSH remote | Approach | Result | Time | Issue | |----------|--------|------|-------| -| Multi-stage Dockerfile | ❌ Failed | 15+ min | npm fails with Zscaler | -| Pre-built frontend | ✅ Success | 3 min | Works! | -| Backup containers | ❌ Failed | N/A | Oracle Linux SSL issues | +| Multi-stage Dockerfile | [FAIL] Failed | 15+ min | npm fails with Zscaler | +| Pre-built frontend | [OK] Success | 3 min | Works! | +| Backup containers | [FAIL] Failed | N/A | Oracle Linux SSL issues | ## Verification @@ -223,12 +223,12 @@ docker exec flask-shopdb-api-1 flask plugin list | grep Enabled | wc -l ## Summary ShopDB Docker deployment is **operational** for core functionality: -- ✅ Database running -- ✅ API serving requests -- ✅ Frontend built and accessible -- ✅ Plugins installed and working -- ✅ HTTPS configured -- ⚠️ Backup watcher needs work (but manual backups functional) +- [OK] Database running +- [OK] API serving requests +- [OK] Frontend built and accessible +- [OK] Plugins installed and working +- [OK] HTTPS configured +- [WARN] Backup watcher needs work (but manual backups functional) The pre-built frontend approach successfully bypasses Zscaler corporate proxy issues. Build time is 2-3 minutes (vs 15+ for failed multi-stage approach). diff --git a/DOCKER-PREBUILT-APPROACH.md b/DOCKER-PREBUILT-APPROACH.md index f47343ef..a6fb5012 100644 --- a/DOCKER-PREBUILT-APPROACH.md +++ b/DOCKER-PREBUILT-APPROACH.md @@ -83,9 +83,9 @@ https://localhost:5001 | Approach | Build Time | Corporate Proxy | Complexity | Production Ready | |----------|-----------|----------------|------------|------------------| -| Multi-stage Dockerfile | 15+ min | ❌ Fails | High | ❌ No | -| Pre-built frontend | 2-3 min | ✅ Works | Medium | ⚠️ Yes (with CI/CD) | -| Pre-built images from registry | 30 sec | ✅ Works | Low | ✅ Yes | +| Multi-stage Dockerfile | 15+ min | [FAIL] Fails | High | [FAIL] No | +| Pre-built frontend | 2-3 min | [OK] Works | Medium | [WARN] Yes (with CI/CD) | +| Pre-built images from registry | 30 sec | [OK] Works | Low | [OK] Yes | ## Next Steps diff --git a/DOCKER-SETUP.md b/DOCKER-SETUP.md index afa1fce9..170366c2 100644 --- a/DOCKER-SETUP.md +++ b/DOCKER-SETUP.md @@ -369,19 +369,19 @@ The `instance_data` volume persists: ``` flask-shopdb/ -├── docker-compose.yml # Main stack definition -├── docker-compose.backup.yml # Backup service -├── Dockerfile # Multi-stage build -├── .env # Environment config (gitignored) -├── corp-root-ca.pem # Zscaler cert (gitignored) -├── certs/ # TLS certificates (gitignored) -│ ├── server.crt -│ └── server.key -├── scripts/ -│ ├── docker-entrypoint.sh # Container startup -│ └── bootstrap-plugins.sh # Plugin auto-install -└── deploy/ - └── site-profile-universal.json # Full plugin list +|-- docker-compose.yml # Main stack definition +|-- docker-compose.backup.yml # Backup service +|-- Dockerfile # Multi-stage build +|-- .env # Environment config (gitignored) +|-- corp-root-ca.pem # Zscaler cert (gitignored) +|-- certs/ # TLS certificates (gitignored) +| |-- server.crt +| +-- server.key +|-- scripts/ +| |-- docker-entrypoint.sh # Container startup +| +-- bootstrap-plugins.sh # Plugin auto-install ++-- deploy/ + +-- site-profile-universal.json # Full plugin list ``` ## Next Steps diff --git a/LOCAL-DEV-SETUP.md b/LOCAL-DEV-SETUP.md index 3b515c09..685f411f 100644 --- a/LOCAL-DEV-SETUP.md +++ b/LOCAL-DEV-SETUP.md @@ -322,27 +322,27 @@ Flask's `flask run` command uses an auto-reloader that spawns a subprocess. This ``` flask-shopdb/ -├── .env # Local environment config (gitignored) -├── run_dev.py # Local development launcher -├── shopdb/ # Flask application -│ ├── __init__.py # App factory -│ ├── config.py # Configuration classes -│ ├── core/ # Core models and APIs -│ └── plugins/ # Plugin manager -├── plugins/ # Plugin packages -│ ├── backups/ -│ ├── computers/ -│ └── ... -├── frontend/ # Vue 3 SPA -│ ├── src/ -│ └── dist/ # Production build (gitignored) -├── instance/ # Runtime state (gitignored) -│ ├── plugins.json # Plugin registry -│ └── ... -├── migrations/ # Core Alembic migrations -├── scripts/ # Deployment and backup scripts -├── backups/ # Local backup storage (gitignored) -└── tests/ # Test suite +|-- .env # Local environment config (gitignored) +|-- run_dev.py # Local development launcher +|-- shopdb/ # Flask application +| |-- __init__.py # App factory +| |-- config.py # Configuration classes +| |-- core/ # Core models and APIs +| +-- plugins/ # Plugin manager +|-- plugins/ # Plugin packages +| |-- backups/ +| |-- computers/ +| +-- ... +|-- frontend/ # Vue 3 SPA +| |-- src/ +| +-- dist/ # Production build (gitignored) +|-- instance/ # Runtime state (gitignored) +| |-- plugins.json # Plugin registry +| +-- ... +|-- migrations/ # Core Alembic migrations +|-- scripts/ # Deployment and backup scripts +|-- backups/ # Local backup storage (gitignored) ++-- tests/ # Test suite ``` ## Git Workflow diff --git a/PRODUCTION-READINESS.md b/PRODUCTION-READINESS.md index a5bde385..63c467ff 100644 --- a/PRODUCTION-READINESS.md +++ b/PRODUCTION-READINESS.md @@ -5,7 +5,7 @@ ## Executive Summary -🔴 **NOT PRODUCTION READY** in current state without significant operational investment. +[CRITICAL] **NOT PRODUCTION READY** in current state without significant operational investment. The Docker deployment requires extensive manual setup, multiple services, and assumes expertise with Docker Compose, restic backup systems, and Flask plugin architecture. This assessment documents current gaps and provides recommendations. @@ -13,22 +13,22 @@ The Docker deployment requires extensive manual setup, multiple services, and as ### What Works -✅ **Flask application code** - Stable, tested, 17 plugins functional -✅ **Database schema** - Migrations work, data model is sound -✅ **Frontend build** - Vue 3 SPA compiles and serves correctly -✅ **Docker images** - Build successfully (with caveats below) -✅ **Plugin architecture** - Clean, documented, extensible +[OK] **Flask application code** - Stable, tested, 17 plugins functional +[OK] **Database schema** - Migrations work, data model is sound +[OK] **Frontend build** - Vue 3 SPA compiles and serves correctly +[OK] **Docker images** - Build successfully (with caveats below) +[OK] **Plugin architecture** - Clean, documented, extensible ### Critical Gaps -❌ **One-command deployment** - Requires 7-10 manual steps -❌ **Corporate proxy handling** - Zscaler cert extraction needed for npm -❌ **Backup system complexity** - 3 containers + restic + scheduler -❌ **TLS certificate generation** - Manual OpenSSL commands required -❌ **Plugin initialization** - Must run `apply-profile` after first start -❌ **Password reset** - No default admin password, requires manual SQL -❌ **Build time** - 15+ minutes with corporate proxy -❌ **Documentation scattered** - 3 different setup guides (Docker, Local, Backup) +[FAIL] **One-command deployment** - Requires 7-10 manual steps +[FAIL] **Corporate proxy handling** - Zscaler cert extraction needed for npm +[FAIL] **Backup system complexity** - 3 containers + restic + scheduler +[FAIL] **TLS certificate generation** - Manual OpenSSL commands required +[FAIL] **Plugin initialization** - Must run `apply-profile` after first start +[FAIL] **Password reset** - No default admin password, requires manual SQL +[FAIL] **Build time** - 15+ minutes with corporate proxy +[FAIL] **Documentation scattered** - 3 different setup guides (Docker, Local, Backup) ## Why Is This So Complex? @@ -86,7 +86,7 @@ The Docker deployment requires extensive manual setup, multiple services, and as - Manual updates - No containerization benefits -**Production Ready:** ⚠️ **YES** (with installer improvements) +**Production Ready:** [WARN] **YES** (with installer improvements) ### Option 2: Docker Pre-Built Images (RECOMMENDED) @@ -110,7 +110,7 @@ The Docker deployment requires extensive manual setup, multiple services, and as - Need image registry - Initial registry setup -**Production Ready:** ✅ **YES** (requires CI/CD setup) +**Production Ready:** [OK] **YES** (requires CI/CD setup) ### Option 3: Docker Source Build (CURRENT) @@ -141,7 +141,7 @@ The Docker deployment requires extensive manual setup, multiple services, and as - Many failure points - Requires Docker expertise -**Production Ready:** 🔴 **NO** (too complex for operations) +**Production Ready:** [CRITICAL] **NO** (too complex for operations) ### Option 4: Kubernetes (FUTURE) @@ -265,10 +265,10 @@ https://your-server:5001 **Problem:** Which one do I follow? **Solution:** Create decision tree: -- Developer on Windows → LOCAL-DEV-SETUP.md -- Ops deploying to prod → (DOESN'T EXIST YET - need simplified guide) -- Custom development → DOCKER-SETUP.md -- Backup questions → scripts/backup/README.md +- Developer on Windows -> LOCAL-DEV-SETUP.md +- Ops deploying to prod -> (DOESN'T EXIST YET - need simplified guide) +- Custom development -> DOCKER-SETUP.md +- Backup questions -> scripts/backup/README.md ### Missing Guides @@ -279,12 +279,12 @@ https://your-server:5001 ## What We Did Today (Honest Assessment) -✅ **Merged wilm→wj** - 98 commits, wilm features now in wj -✅ **Fixed local dev** - `run_dev.py` works for Windows development -✅ **Documented Docker** - Comprehensive but too complex -✅ **Added backup docs** - System works but needs expertise -⚠️ **Docker "production ready"** - Technically works, operationally complex -❌ **Simple deployment** - Still requires too many manual steps +[OK] **Merged wilm->wj** - 98 commits, wilm features now in wj +[OK] **Fixed local dev** - `run_dev.py` works for Windows development +[OK] **Documented Docker** - Comprehensive but too complex +[OK] **Added backup docs** - System works but needs expertise +[WARN] **Docker "production ready"** - Technically works, operationally complex +[FAIL] **Simple deployment** - Still requires too many manual steps ## Next Steps (Priority Order) @@ -301,7 +301,7 @@ https://your-server:5001 - Document any issues 3. **Create deployment decision tree** - - Flowchart: what's my situation → which method to use + - Flowchart: what's my situation -> which method to use - Don't make users read 4 docs to figure out where to start ### Short Term (Next Sprint) diff --git a/agent/QUICK-FIX-VM.md b/agent/QUICK-FIX-VM.md index ace98853..e66d5642 100644 --- a/agent/QUICK-FIX-VM.md +++ b/agent/QUICK-FIX-VM.md @@ -33,10 +33,10 @@ cd C:\ProgramData\ShopDB\EndpointAgent ## Why HTTP is OK Here -- ✅ VM and host on same physical machine (Hyper-V) -- ✅ Traffic never leaves the host -- ✅ Hyper-V internal network is isolated -- ✅ No external network exposure +- [X] VM and host on same physical machine (Hyper-V) +- [X] Traffic never leaves the host +- [X] Hyper-V internal network is isolated +- [X] No external network exposure For production multi-machine deployment, use HTTPS with proper certificates. diff --git a/scripts/check-naming-and-style.sh b/scripts/check-naming-and-style.sh index c60a042e..4cad6abd 100755 --- a/scripts/check-naming-and-style.sh +++ b/scripts/check-naming-and-style.sh @@ -21,6 +21,7 @@ VIOLATIONS=0 EXCLUDES=( --exclude-dir=venv + --exclude-dir=venv-quick --exclude-dir=env --exclude-dir=.venv --exclude-dir=node_modules @@ -39,6 +40,8 @@ EXCLUDES=( # source, never committed, and free to hold pasted logs full of em-dashes # and arrows - grep does not consult .gitignore, so exclude it explicitly. --exclude-dir=devnotes + --exclude=findings.sarif + --exclude=report.md ) # Root-level gitignored scratch: review writeups and chat handoffs, free to hold diff --git a/shopdb/core/api/shopdbbackups.py b/shopdb/core/api/shopdbbackups.py index acac2125..8972455d 100644 --- a/shopdb/core/api/shopdbbackups.py +++ b/shopdb/core/api/shopdbbackups.py @@ -622,18 +622,22 @@ def finalize_restore(): 'Could not re-arm failed upgrade: ' + str(error), http_code=500) - # Try to claim a pending upgrade - setname = _claim_upgrade() - if not setname: - return success_response( - data={'queued': False}, - message='No restore is awaiting schema upgrade.') + # Check if there's a pending upgrade sentinel (but don't claim it) + # The watcher/background worker will claim and run it + sentinel = os.path.join(root, UPGRADE_SENTINEL) + if os.path.isfile(sentinel): + try: + with open(sentinel, 'r', encoding='utf-8') as handle: + setname = handle.read().strip() + return success_response( + data={'queued': True, 'snapshotid': setname}, + message='Schema upgrade queued.') + except OSError: + pass - # Queue the upgrade but don't run it inline (it can outlast the request timeout) - # The watcher or a background worker will pick up the claim and run it return success_response( - data={'queued': True, 'snapshotid': setname}, - message='Schema upgrade queued.') + data={'queued': False}, + message='No restore is awaiting schema upgrade.')