Metadata-Version: 2.4
Name: lr-serial
Version: 0.4.0
Summary: CLI client for interacting with LumenRadio serial generation backend service.
Author-email: Jonas Estberger <jonas.estberger@lumenradio.com>
License: MIT License
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.32
Requires-Dist: typer>=0.12
Requires-Dist: rich>=13.7
Requires-Dist: pydantic>=2.8
Provides-Extra: dev
Requires-Dist: build>=1.2.1; extra == "dev"
Requires-Dist: twine>=5.1.1; extra == "dev"
Requires-Dist: wheel; extra == "dev"
Requires-Dist: pytest>=8.4.2; extra == "dev"
Requires-Dist: black>=25.9.0; extra == "dev"
Requires-Dist: pytest-html; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Dynamic: license-file


# lr-serial

CLI + Python client for interacting with the LumenRadio Serial Number Generation Service.

## Install

```bash
pip install lr-serial
```

## CLI Usage

### Login Command

The `login` command supports two authentication modes:

#### User login (default)

Opens the system browser for interactive sign-in via OAuth 2.0 Authorization Code + PKCE.
No client secret required — suitable for human operators.

LumenRadio employees can log in with no arguments (client ID and tenant ID are baked in):

```bash
serial login
```

If the browser does not open automatically the auth URL is printed to the terminal so you
can paste it manually.

#### Machine-to-machine (M2M) login

Uses the OAuth 2.0 client credentials grant — suitable for automated pipelines.

```bash
serial login --mode m2m \
  --client-id <CLIENT_ID> \
  --client-secret <CLIENT_SECRET> \
  --tenant-id <TENANT_ID>
```

#### Common options

- `--mode [user|m2m]` — authentication mode (default: `user`) [env: SERIAL_AUTH_MODE]
- `--client-id` — Azure AD application client ID [env: SERIAL_CLIENT_ID]
- `--client-secret` — client secret, required for `m2m` [env: SERIAL_CLIENT_SECRET]
- `--tenant-id` — Azure AD tenant ID [env: SERIAL_TENANT_ID]
- `--token-url` — token endpoint URL override (m2m only) [env: SERIAL_TOKEN_URL]
- `--scope` — OAuth2 scope override [env: SERIAL_SCOPE]
- `--config-path` — override the login.json location

Stores the bearer token (and refresh token for user logins) in your config directory for
subsequent CLI commands.

### Status Command

Check backend reachability and token validity:

```bash
serial status
```

Reports:
- Backend reachable ✓ / unreachable ✗
- Token valid ✓ / invalid ✗

---

## Global Options

Most commands support:
- `--output [rich|json]` — output format (rich table default, json for scripting)
- `--config-path PATH` — override the login.json location

---

## Article Commands

### List Articles

```bash
serial list-articles
serial list-articles --output json
```

### Get Article

```bash
serial article get ARTICLE_NO
serial article get 710-4130 --output json
```

Returns full article details: article number, description, prefix, schema (version, fields, format, regexp), disabled flag.

### Create Article

```bash
serial article create \
  --article PROD-01 \
  --description "Production line 1" \
  --prefix PROD \
  --schema-file schema.json
```

The `--schema-file` must be a JSON file with the ArticleSchema object:

```json
{
  "version": 1,
  "fields": { "site": "string" },
  "format": "{prefix}-{site}-{counter:06d}",
  "regexp": "^[A-Z0-9]+-[A-Z0-9]+-[0-9]{6}$"
}
```

Options:
- `--article TEXT` — article number (1-32 chars, [A-Za-z0-9-]) [required]
- `--description TEXT` — human-readable description (1-100 chars) [required]
- `--prefix TEXT` — serial prefix (1-10 chars, [A-Za-z0-9]) [required]
- `--schema-file PATH` — path to JSON file containing the ArticleSchema [required]
- `--disabled / --no-disabled` — create as disabled (default: enabled)

### Update Article

```bash
serial article update ARTICLE_NO --description "New description"
serial article update ARTICLE_NO --prefix NEWP --disabled
```

At least one option must be provided. Options: `--description`, `--prefix`, `--disabled/--no-disabled`, `--schema-file`.

### Delete Article

```bash
serial article delete ARTICLE_NO
```

Idempotent — succeeds even if the article does not exist.

### Set Sequence Counter

```bash
serial article set-sequence ARTICLE_NO SEQUENCE_NO
serial article set-sequence 710-4130 1000
```

Sets the current counter value (integer ≥ 0) for the article.

---

## Serial Number Commands

### Generate Serial Numbers

```bash
serial generate ARTICLE_NO
serial generate ARTICLE_NO --quantity 5
serial generate ARTICLE_NO --field site=Stockholm --field year=2024
serial generate ARTICLE_NO --quantity 3 --output json
```

Options:
- `--quantity INT` — number of serials to generate (1-1000, default 1)
- `--field KEY=VALUE` — extra field value consumed by the article schema (repeatable)

### Lookup a Serial Number

```bash
serial lookup SERIAL_NO
serial lookup QWDNA010000001 --output json
```

Returns: serial value, article, created_by, created_at.

---

## Site Commands

### List Sites

```bash
serial site list
serial site list --output json
```

### Create Site

```bash
serial site create --site-no 5 --name "Helsinki"
```

Options:
- `--site-no INT` — site number (1-99) [required]
- `--name TEXT` — site name [required]

### Update Site

```bash
serial site update 5 --name "Helsinki" --contact-email ops@example.com
serial site update 5 --name "Helsinki" --disabled
```

Note: `--name` is required by the API even when only updating other fields.

Options:
- `--name TEXT` — new site name [required]
- `--client-id TEXT` — associated client ID (or empty to clear)
- `--contact-email TEXT` — contact email address (or empty to clear)
- `--disabled / --no-disabled` — enable or disable the site

### Delete Site

```bash
serial site delete 5
```

Idempotent — succeeds even if the site does not exist.

---

## Audit Commands

These commands require the `app.admin.api` scope.

### List Audit Entries

```bash
serial audit list
serial audit list --limit 50 --output json
```

Returns audit entries newest-first: id, touched_table, touched_key, change_type (create/update/delete), changed_by, changed_at.

Options:
- `--limit INT` — max entries to return (1-500, default 100)

### Restore an Audit Entry

```bash
serial audit restore AUDIT_ID
```

Undoes the audited change:
- `create` → deletes the created row
- `update` → restores previous values
- `delete` → re-inserts the deleted row

If the token lacks the admin scope, the API returns 403 and the CLI will display:
`Access denied. Ensure your credentials include the admin scope (app.admin.api).`
