Jun 26 MT-0 phase
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
# Control Plane (MT-0)
|
||||
|
||||
Tenant registry, plans, domains, provisioning state, and superadmin accounts
|
||||
for multi-tenant JQC. Self-contained and decoupled from `app/` — the existing
|
||||
single-tenant application is unaffected by this package.
|
||||
|
||||
See `../MULTI_TENANT_PLAN.md` for the full architecture and roadmap.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
control/
|
||||
├── __init__.py # package docs
|
||||
├── base.py # ControlBase + engine/session (from CONTROL_DATABASE_URL)
|
||||
├── crypto.py # Fernet encrypt/decrypt for tenant DB passwords
|
||||
├── time_utils.py # now_eastern() mirror (no app import)
|
||||
├── models.py # Plan, PlanFeature, Tenant, TenantDomain,
|
||||
│ # Superadmin, ProvisioningJob, TenantAudit
|
||||
├── seed.py # idempotent baseline-plan seeder
|
||||
├── cli.py # seed / create-superadmin / list-plans
|
||||
└── migrations/ # standalone Alembic chain (control{N}_…)
|
||||
└── versions/control0001_init.py ← HEAD
|
||||
```
|
||||
|
||||
## Environment variables (control plane only)
|
||||
|
||||
| Variable | Purpose |
|
||||
|---|---|
|
||||
| `CONTROL_DATABASE_URL` | e.g. `mysql+pymysql://jqc_control:pw@localhost/jqc_control` |
|
||||
| `CONTROL_FERNET_KEY` | Fernet key for encrypting tenant DB passwords |
|
||||
|
||||
Generate a Fernet key:
|
||||
|
||||
```bash
|
||||
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
|
||||
```
|
||||
|
||||
## Deploy — MT-0 bootstrap (run once)
|
||||
|
||||
Migrations are independent of the tenant chain and the data plane. The existing
|
||||
app does **not** need to be touched or restarted for MT-0.
|
||||
|
||||
```bash
|
||||
# 1. Create the control database + its MySQL user (run as a MySQL admin)
|
||||
mysql -e "CREATE DATABASE jqc_control CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
|
||||
mysql -e "CREATE USER 'jqc_control'@'localhost' IDENTIFIED BY '<pw>';"
|
||||
mysql -e "GRANT ALL PRIVILEGES ON jqc_control.* TO 'jqc_control'@'localhost'; FLUSH PRIVILEGES;"
|
||||
|
||||
# 2. Export the env vars (add to .env or the systemd unit for the control panel later)
|
||||
export CONTROL_DATABASE_URL='mysql+pymysql://jqc_control:<pw>@localhost/jqc_control'
|
||||
export CONTROL_FERNET_KEY='<generated key>'
|
||||
|
||||
# 3. Apply the control schema
|
||||
alembic -c control/migrations/alembic.ini upgrade head
|
||||
|
||||
# 4. Seed baseline plans (Free / Starter / Pro / Enterprise)
|
||||
python -m control.cli seed
|
||||
|
||||
# 5. Create the first superadmin
|
||||
python -m control.cli create-superadmin --username admin --email you@example.com
|
||||
```
|
||||
|
||||
Verify:
|
||||
|
||||
```bash
|
||||
alembic -c control/migrations/alembic.ini current # → control0001_init (head)
|
||||
python -m control.cli list-plans
|
||||
```
|
||||
|
||||
## Rollback
|
||||
|
||||
```bash
|
||||
alembic -c control/migrations/alembic.ini downgrade base # drops all control tables
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- The migration uses INFORMATION_SCHEMA existence checks (Rule 14) — safe to re-run.
|
||||
- Plan seeding is idempotent (upsert by `code`) — re-running updates in place.
|
||||
- Tenant DB passwords are stored Fernet-encrypted in `tenants.db_password_enc`;
|
||||
`Tenant.db_uri` decrypts on demand. Provisioning that *creates* per-tenant
|
||||
MySQL users/grants lands in MT-3.
|
||||
- Control-panel write auditing (`tenant_audit`) is wired in MT-4; the bootstrap
|
||||
CLI logs to stdout only.
|
||||
Reference in New Issue
Block a user