Metadata-Version: 2.4
Name: scalio-platform
Version: 0.5.0
Summary: Shared building blocks of the Scalio apps: job leases, schema migrations, health, error reports, app links, setup wizard state, roles and permissions
License: Proprietary
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.27
Requires-Dist: pymongo>=4.6
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: fastapi>=0.110; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"
Requires-Dist: mongomock-motor>=0.0.29; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"

# scalio-platform

Shared building blocks of the Scalio apps (Nexus, Compass, Citadel, Foundry, Rosetta, Pulse, Beacon, Cockpit, ID,
Monitor). Before this package each app kept its own copy of these files (architecture review C2/C4, ADR 0058 in
scalio-docs). Nothing in this package is secret.

| Module | What it does |
| --- | --- |
| `scalio_platform.job_lease` | Runs a background loop on one instance at a time (lease in `db.job_leases`). During an update two instances run side by side; without the lease both would act. |
| `scalio_platform.migrations` | Schema migrations for MongoDB: ordered steps, each applied once, version in `db.meta` (`schema_version`). |
| `scalio_platform.health` | The answer of `GET /api/health` that Scalio Monitor reads (`ok` / `degraded` / `down`, leases of the loops). |
| `scalio_platform.error_report` | Sends unexpected errors to Scalio Monitor, only when `ERROR_REPORT_URL` and `ERROR_REPORT_TOKEN` are set. |
| `scalio_platform.app_links` | Links and features of the product switcher (`SCALIO_APP_LINKS`, `SCALIO_STAGE`, `SAAS_MODE`). |
| `scalio_platform.roles` | Permission catalog of the app, built-in and own roles (`app_roles`), `require_perm` for routes, shared role API (`roles_router`) for `RoleAdmin` in scalio-ui. |
| `scalio_platform.tenant_jobs` | Runs one job per tenant side by side (`for_each_tenant`): at most `TENANT_JOBS_PARALLEL` at once (default 4), a time budget per tenant (`TENANT_JOBS_TIMEOUT`, default 900 s), a failing tenant never stops the others; for MSP instances with many customers (ADR 0063 `mandant/M11`). |
| `scalio_platform.setup_wizard` | State of the Einrichtungsassistent (`GET/PUT /api/setup/wizard`, ADR 0060): `wizard_state`, `save_wizard`, `parse_update`. |

## Use in an app

```
scalio-platform==0.1.0            # backend/requirements.txt, exact version
```

```python
from scalio_platform import error_report, health, job_lease
from scalio_platform.migrations import BASELINE, run_migrations

MIGRATIONS = BASELINE                      # append (2, migrate_002_...) and so on, never edit past steps

async def startup():
    await run_migrations(db, MIGRATIONS)   # before the background loops
    for name, loop in LOOPS.items():
        asyncio.create_task(job_lease.run_exclusive(db, name, loop))

error_report.install(app, "citadel", build_info)
code, body = await health.health_report(db, build_info(), lease_jobs=sorted(LOOPS))

# probe of the provisioning engine (SaaS on the Docker engine), header X-Provision-Health-Secret
code, body = await health.provision_report(db, build_info(), secret=os.environ.get("PROVISION_HEALTH_SECRET", ""),
                                           provided=request.headers.get("x-provision-health-secret", ""))
```

A migration step must be safe to run twice: two instances can start at the same moment.

## Develop and release

- `pip install -e ".[dev]"`, then `pytest -q` and `ruff check .` (both run in CI).
- Release: bump `pyproject.toml` and `__version__`, open a scalio-docs PR with `python3 tools/changelog.py --repo scalio-platform release <version>` (changelog in scalio-docs `changelog/scalio-platform/`, ADR 0066), merge, then «Freigeben» in the Scalio
  Cockpit (workflow `publish.yml`: PyPI with trusted publishing, tag and GitHub release). Tags without `v`.
- A change of behaviour changes every app on its next upgrade: say so in the PR and the CHANGELOG.
