Metadata-Version: 2.4
Name: scalio-platform
Version: 0.1.0
Summary: Shared building blocks of the Scalio apps: job leases, schema migrations, health, error reports, app links
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`). |

## 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))
```

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__`, add the CHANGELOG entry, 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.
