Phase 5: Alembic baseline, per-site deploy, ADRs to docs/adr
Migration runner ready and a sister site can deploy from a clean
checkout with one .env file.
ADRs relocated (migrations/adr/ -> docs/adr/):
- migrations/ is now Alembic territory, not docs.
- All cross-references updated: CLAUDE.md, docs/PLUGIN-HOOKS.md,
docs/PLUGIN-QUICKSTART.md.
Alembic initialized (migrations/):
- env.py, script.py.mako, alembic.ini copied from Flask-Migrate
templates so `flask db migrate` and `flask db upgrade` work without
a one-time `flask db init` (which would clash with the existing
migrations/ directory).
- Baseline migration generated via autogenerate, captures all 47
tables (core models + 6 plugins) as the upgrade target. Ready for
per-site `flask db upgrade` from an empty schema.
Deploy artifacts:
- Dockerfile: python:3.12-slim base, gunicorn server, non-root user,
healthcheck against /api/auth/login. Single image bundles all six
plugins; sites enable via `flask plugin install <name>`.
- docker-compose.yml: MySQL 8 + API container, healthcheck-gated
startup, env-driven secrets that fail loud on missing values
(`${SECRET_KEY:?}` form).
- .env.example: full env-var inventory with comments. Calls out
required vs optional. Matches what ProductionConfig.validate
enforces.
docs/DEPLOY.md:
- Step-by-step per-site runbook: clone, configure .env, bring up
stack, run migrations, seed reference data, install plugins,
create admin, front with TLS, backups, updates.
- Common-issues table.
- Cross-links to ADR-004 (per-site rationale), ADR-003 (plugin
distribution), and the config source.
Skills:
- migrating-asset-schema: Alembic + one-shot data migration policy.
Rules: additive first, renames are three steps, destructive ops
need rollback, equipment migration filter per ADR-001 + ADR-005.
- hardening-flask-config: production validation, CORS allowlist
policy, JWT cookie hardening, per-site deploy isolation per ADR-004.
CLAUDE.md updated to reflect the post-Phase-5 state. No tests added
this commit; the Alembic baseline is exercised by the existing
db.create_all-based test suite (tests do not touch the migration
runner; that's by design until per-plugin migrations land).
Test count unchanged: 101 passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
42
CLAUDE.md
42
CLAUDE.md
@@ -8,7 +8,7 @@ Modern rewrite of the classic-ASP shopdb. Built as a framework so sister GE Aero
|
||||
- **Legacy database:** `shopdb` (Classic ASP schema, used only for one-time data import via `scripts/import_from_mysql.py`)
|
||||
- **Connection:** `.env` file. See `.env.example`.
|
||||
|
||||
Architecture decisions live in `migrations/adr/`. Read those before making schema or contract changes.
|
||||
Architecture decisions live in `docs/adr/`. Read those before making schema or contract changes.
|
||||
|
||||
- ADR-001: Asset model is the platform contract (Machine retires) - ACCEPTED
|
||||
- ADR-002: Plugin contract versioning (semver) - ACCEPTED
|
||||
@@ -23,29 +23,31 @@ Architecture decisions live in `migrations/adr/`. Read those before making schem
|
||||
|
||||
## Current state (as of 2026-05-08)
|
||||
|
||||
### Wired in
|
||||
Refactor phases 0-5 landed. Five commits on main, all pushed to gitea origin.
|
||||
|
||||
- App factory pattern, Flask 3 + SQLAlchemy + Flask-Migrate + JWT + Marshmallow + CORS + Caching
|
||||
- 6 plugins: computers, equipment, network, notifications, printers, usb
|
||||
- Plugin contract: `BasePlugin` ABC, `PluginMeta`, registry, dependency-aware loader
|
||||
- JWT auth with refresh tokens, audit logging, system settings, user management
|
||||
- Frontend: Vue 3 + Pinia + Vite, dynamic plugin routing, dark mode default
|
||||
- Search across all plugins via `get_searchable_fields` hook
|
||||
- Asset relationships (cross-plugin)
|
||||
### Phases done
|
||||
|
||||
### In progress / partial
|
||||
- **Phase 0**: 6 ADRs accepted, naming convention v1, pre-commit style hook
|
||||
- **Phase 1**: 8 smoke tests + 7 production-config tests, Flask-SQLAlchemy 3 fixtures, uv lockfile, hardened ProductionConfig
|
||||
- **Phase 2**: contract surface defined (`__contract_version__`, `BasePlugin` hooks, `docs/PLUGIN-HOOKS.md`), 51 contract tests
|
||||
- **Phase 3**: manifest-first loader, fail-loud/isolate policy, contract-version range checking, auto-register core blueprints, `shopdb.api` namespace, `BasePlugin.get_setting/set_setting` helpers
|
||||
- **Phase 4**: `flask plugin new <name>` CLI, scaffold templates, 14 canary tests, `docs/PLUGIN-QUICKSTART.md`
|
||||
- **Phase 5**: ADRs moved to `docs/adr/`, Alembic baseline migration, per-site deploy artifacts (`Dockerfile`, `docker-compose.yml`, `docs/DEPLOY.md`)
|
||||
|
||||
- **Dual model coexistence**: legacy `Machine` and new `Asset` both live. ADR-001 settles direction (Asset wins). Migration plan is the next concrete deliverable.
|
||||
- **Plugin verification**: 6 plugins follow `BasePlugin` interface but no contract test asserts compliance. Skill `enforcing-plugin-contract` and the contract test suite are pending.
|
||||
- **Tests**: hollow. `tests/conftest.py` exists but uses Flask-SQLAlchemy 2.x patterns that error on 3.x. No actual test files. Skill `pinning-flask-behavior` covers the rebuild.
|
||||
### Active state
|
||||
|
||||
### Pending
|
||||
- 101+ tests passing, naming/style check green
|
||||
- `__contract_version__` at 0.2.0
|
||||
- 6 bundled plugins all satisfy contract: computers, equipment, network, notifications, printers, usb
|
||||
- Pre-1.0 framework; sister sites should pin tight `core_version` ranges until contract reaches 1.0
|
||||
|
||||
- Alembic versions directory exists (`migrations/versions/`) but is empty. No migrations have been generated yet. Run `flask db init` is partial; need `flask db migrate` to capture current schema.
|
||||
- Plugin scaffold CLI (`flask plugin new <name>`)
|
||||
- Plugin author docs (`docs/PLUGIN-QUICKSTART.md`, `docs/PLUGIN-REFERENCE.md`)
|
||||
- Per-site deploy story (`Dockerfile`, `docs/DEPLOY.md`)
|
||||
- Frontend hook contract (asset-detail, map markers, search results)
|
||||
### Deferred
|
||||
|
||||
- Equipment data migration (one-shot script for legacy ASP shopdb -> assets). Per ADR-001, only `category='Equipment' AND machinenumber IS NOT NULL` migrates. Skill `migrating-asset-schema` documents the pattern; the actual one-shot script lives in `scripts/migration/` when run.
|
||||
- Printers retirement: legacy `PrinterData` model + frontend changes. Coordinated with the equipment data migration.
|
||||
- `measuringtools` plugin (ADR-005). First plugin to be built using the scaffold.
|
||||
- Frontend hook contract for asset-detail, map markers, search results
|
||||
- Alembic per-plugin migration chains (the framework supports them; bundled plugins haven't moved off `db.create_all()` yet)
|
||||
|
||||
## Quick start
|
||||
|
||||
@@ -112,7 +114,7 @@ Each plugin must have:
|
||||
- `shopdb/core/api/assets.py` - example of optional plugin imports
|
||||
- `frontend/src/router/index.js` - frontend routing
|
||||
- `frontend/src/components/AppSidebar.vue` - navigation menu
|
||||
- `migrations/adr/` - architecture decision records
|
||||
- `docs/adr/` - architecture decision records
|
||||
|
||||
## Migration notes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user