Metadata-Version: 2.5
Name: glow-sdk
Version: 0.7.1
Summary: Python SDK for the Glow loyalty API
Project-URL: Homepage, https://gitlab.com/vinq/glow-sdk
Project-URL: Repository, https://gitlab.com/vinq/glow-sdk
Author: Gustav Ebbers
License-Expression: MIT
License-File: LICENSES/MIT.txt
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: loguru>=0.7.3
Requires-Dist: pydantic>=2.13.5
Requires-Dist: requests>=2.34.2
Requires-Dist: urllib3>=2.8.0
Description-Content-Type: text/markdown

<!--
SPDX-FileCopyrightText: 2026 Gustav Ebbers

SPDX-License-Identifier: MIT
-->

# glow-sdk

A typed Python SDK for the Glow loyalty API, published on PyPI under the MIT
license. Import package: `glow_sdk`.

Every release goes through a pipeline that proves the path from commit to
trusted artifact: version, commit SHA, pipeline, package checksums, SBOM and an
evidence pack. There is no container image and no deployment: the artifacts are
a wheel and an sdist.

The rules: no real member data in tests or CI (synthetic data only), standard
tools and standard Python packaging, least privilege for every token (PyPI
uploads use Trusted Publishing, so no PyPI token exists).

[![pipeline status](https://gitlab.com/vinq/glow-sdk/badges/main/pipeline.svg)](https://gitlab.com/vinq/glow-sdk/-/commits/main)
[![coverage report](https://gitlab.com/vinq/glow-sdk/badges/main/coverage.svg)](https://gitlab.com/vinq/glow-sdk/-/commits/main)

## Install and use

```sh
pip install glow-sdk        # Python 3.12 or newer
```

```python
from glow_sdk import SDK

sdk = SDK("https://api.example.com/", api_key="<key>", api_secret="<secret>")

for member in sdk.list_members(search="jane"):
    print(member.id, member.email, member.point_balance)

member = sdk.get_member(email="jane@example.com")  # or member_id=, platform_id=
sdk.update_member_points(point_balance=100, member=member)
sdk.delete_member(member_id=42)
```

- `list_members(ordering="desc", search=None)` follows the pagination of the API
  and returns a list of `Member` models.
- `get_member`, `delete_member` and `update_member_points` take a `Member` or an
  ID. A missing argument raises `ValueError`.
- Rate limited requests (HTTP 429) are retried with exponential backoff and the
  `Retry-After` header is honoured. A connection error or an authentication
  error (HTTP 403) raises `ValueError`; other HTTP errors raise
  `requests.exceptions.HTTPError`.
- The package is typed (`py.typed`). `glow_sdk.__version__` is the installed
  version. Details: [docs/architecture.md](docs/architecture.md).

## Quickstart

You need `uv` and Docker (for `make mdlint` and `make reuse` only). Python 3.13
is pinned in `.python-version`; the package supports 3.12 and newer.

```sh
uv sync --locked
make check              # all local checks, see below
make build              # wheel and sdist in dist/
```

`make check` runs these, in order:

| Target or command | What it checks |
| --- | --- |
| Ruff check and format check | Lint (including complexity, C90, and the bandit `S` rules) and formatting |
| `mypy --strict src tests tools ci` | Types |
| `deptry .` | Declared dependencies match the imports (DEP001-DEP004) |
| `pytest` | Tests, coverage at least 90 % (lines and branches) |
| `uv lock --check` | `uv.lock` matches `pyproject.toml` |
| `make deadcode` | Dead code (Vulture) |
| `make mdlint` | Markdown style (markdownlint-cli2 Docker image, needs Docker) |
| `make spell` | Spelling (codespell) |
| `make reuse` | SPDX copyright and license header on every file (REUSE Docker image; not inside a git worktree) |
| `make docs` | The Sphinx site builds with no warnings |

More targets:

- `make fmt` fixes formatting and auto-fixable lint issues in place.
- `make pre-commit` runs all pre-commit hooks on every file.
- `make docs` builds the documentation site into `docs/_build/html` (open
  `index.html`). Warnings fail the build.

Rules for new files and the reasons behind each check:
[docs/development.md](docs/development.md).

## Versioning and releases

- Dev builds (MR and `main` pipelines): PEP 440 version
  `X.Y.Z.dev<pipeline IID>`. Main builds are published to the project's GitLab
  package registry (members only).
- Releases: `X.Y.Z`, published to PyPI. Git tags have no `v` prefix. A `+` is
  never used.
- `X.Y.Z` comes from Conventional Commits, computed by Commitizen
  (`cz bump --get-next`).
- On every green `main` pipeline the `release` job runs `cz bump`. `feat` gives
  a minor release, `fix`, `refactor` and `perf` give a patch release, and `!` or
  `BREAKING CHANGE` gives a major one (a minor one while the version is 0.x,
  because `major_version_zero = true`). `chore`, `docs`, `test`, `ci`, `build`
  and `style` do not release. It pushes a `bump:` commit and the tag `X.Y.Z`.
  The tag pipeline builds, scans and publishes that version to PyPI (Trusted
  Publishing) and creates the GitLab release.
- The version is injected at build time (`uv version --frozen`, never
  committed). The wheel and sdist contain only the package, README, license and
  metadata; the pipeline fails otherwise.

Details: [docs/versioning.md](docs/versioning.md) and
[ADR-0004](docs/adr/0004-release-with-bump-commits.md) and
[ADR-0005](docs/adr/0005-release-skip-and-errata.md).

Release evidence: every release gets an evidence pack (with a SHA-256) (change control,
tests, code quality, security, supply chain, pipeline compliance). The latest
one is on the Pages front page `https://<pages-url>/` (members only). Every
release's pack is kept in the package registry and linked from its release. See
[docs/evidence.md](docs/evidence.md).

On every merge request, the `mr-summary` job posts one comment with the status
of all checks and the commands to fix what failed. It updates itself on each
pipeline.

## Documentation

Published site (with the API reference): `https://<pages-url>/`. Replace the
placeholder with the Pages URL of the project
([setup manual, 3.9](docs/setup-manual.md#39-gitlab-pages)). The site is for
project members only, and it shows the latest release. Build it locally with
`make docs`.

| Document | Content |
| --- | --- |
| [docs/architecture.md](docs/architecture.md) | The library, its layers, error handling, packaging and supported Pythons |
| [docs/pipeline.md](docs/pipeline.md) | Every stage and job, the release flow, schedules |
| [docs/evidence.md](docs/evidence.md) | The release evidence pack: contents, how it is judged, verify and export it |
| [docs/versioning.md](docs/versioning.md) | Version scheme per artifact, and how to trace a package to a commit |
| [docs/development.md](docs/development.md) | Daily workflow, commits, dependencies, review, code quality rules |
| [docs/security.md](docs/security.md) | Supply-chain measures, verifying packages, secret handling |
| [docs/setup-manual.md](docs/setup-manual.md) | Everything a maintainer configures in GitLab and external services |
| [docs/adr/README.md](docs/adr/README.md) | Architecture decision records |
| [CLAUDE.md](CLAUDE.md) | Conventions for the agents that work on this repo |
