Runtime conformance checker for TMForum Open API implementations — ESLint for TMF APIs
Project description
tmf-lint
Runtime conformance checker for TMForum Open API implementations.
tmf-lint points at a running TMF API server and validates its behaviour against the TMForum Open API v4.0.0 spec. Think ESLint for TMF APIs — not a Swagger/OAS linter (TMFValidator does that), but a live HTTP behaviour validator.
Part of the TMF DevKit open-source toolchain.
Quick start
pip install tmf-lint
# Option A — use tmf-mock as the target (recommended for a clean baseline)
pip install tmf-mock
tmf-mock start --apis 638,639,641
# Option B — point at your own server
# (read the "Target server requirements" section below first)
# Run all conformance checks
tmf-lint check --url http://localhost:8000 --apis 638,639,641
What it checks
39 rules across 5 categories for TMF638, TMF639, and TMF641.
| Category | What is validated |
|---|---|
http |
POST→201 with Location header, GET list→200 with X-Total-Count, GET unknown id→404, DELETE→204 |
mandatory-fields |
id, href, @type, @baseType present on every response; href is an absolute URL |
lifecycle |
Valid state transitions accepted (200), illegal transitions rejected (422), terminal states locked, same-state PATCH is a no-op (200) |
referential |
DELETE a resource referenced by a service→409, POST with a non-existent reference→422 |
pagination |
limit param respected, X-Total-Count accurate (verified by fetching limit=total), offset beyond total returns empty array not an error |
CLI reference
# Check all rules against all three supported APIs
tmf-lint check --url http://myserver:8080 --apis 638,639,641
# Check only specific rule categories
tmf-lint check --url http://myserver:8080 --apis 638 --rules http,lifecycle
# JSON output for CI/CD pipelines
tmf-lint check --url http://myserver:8080 --format json
# List all available rules
tmf-lint rules
# Filter rule list by API
tmf-lint rules --apis 639
# Show version
tmf-lint --version
Exit code 0 = all checks passed. Exit code 1 = one or more failures.
Target server requirements
tmf-lint creates, modifies, and deletes real data on the server it checks. It sends minimal spec-compliant payloads (only fields defined in the TMF v4.0.0 schema).
Always point tmf-lint at a test or mock instance — never at production.
If your server enforces fields beyond the TMF spec
Some implementations require fields that the spec marks as optional — for example relatedParty, resourceSpecification, a specific @type subclass, or a valid serviceSpecification reference. If a setup POST is rejected because of a missing field, the rule that depends on it will skip gracefully (you will see ⏭ in the output) rather than crash. You will not get a false failure, but you will not get a pass signal either.
In that case the recommended approach for v0.1 is to run tmf-lint against tmf-mock first to establish a clean baseline, then use the results to understand which rules your server needs to satisfy. A --fixtures option (v0.2) will allow you to supply custom POST payloads for your specific implementation.
URL base path
tmf-lint expects the standard TMForum base paths:
| API | Path |
|---|---|
| TMF638 | /tmf-api/serviceInventoryManagement/v4/service |
| TMF639 | /tmf-api/resourceInventoryManagement/v4/resource |
| TMF641 | /tmf-api/serviceOrdering/v4/serviceOrder |
Docker
# Run against a local server
docker run --rm --network host mchavan23/tmf-lint \
check --url http://localhost:8000 --apis 638,639,641
# JSON output
docker run --rm --network host mchavan23/tmf-lint \
check --url http://localhost:8000 --format json
CI/CD integration
# GitHub Actions example
- name: TMF API conformance check
run: |
pip install tmf-lint
tmf-lint check --url http://localhost:8000 --apis 638,639,641 --format json \
| tee tmf-lint-report.json
# exit code 1 if any rule fails — fails the build automatically
Programmatic use
from tmf_lint.runner import run
report = run(base_url="http://localhost:8000", apis=[638, 639, 641])
print(f"Passed: {report.n_passed} Failed: {report.n_failed} Skipped: {report.n_skipped}")
for result in report.results:
if not result.passed and not result.skipped:
print(f" FAIL [{result.rule_id}] {result.description}")
print(f" {result.message}")
Adding a new rule
The rule engine auto-discovers subclasses — no registration call is needed.
- Create
tmf_lint/rules/tmf{N}/r_mycheck.py - Subclass
BaseRuleand set four class attributes - Implement
async def check(self, client, ctx) -> RuleResult
from tmf_lint.rules.base import BaseRule, CATEGORY_HTTP
from tmf_lint.client import LintClient
from tmf_lint.context import LintContext
from tmf_lint.result import RuleResult
class TMF639MyNewRule(BaseRule):
rule_id = "TMF639-HTTP-005"
api = 639
category = CATEGORY_HTTP
description = "GET /resource supports ?fields= projection"
async def check(self, client: LintClient, ctx: LintContext) -> RuleResult:
try:
resp = await client.get("/tmf-api/resourceInventoryManagement/v4/resource",
params={"fields": "id,name"})
except Exception as exc:
return self.fail(str(exc))
if resp.status_code != 200:
return self.fail(f"Expected 200, got {resp.status_code}")
return self.ok()
See tmf_lint/rules/tmf639/r_http.py for a complete worked example.
Development
git clone https://github.com/tmf-devkit/tmf-lint
cd tmf-lint
# Windows
python -m venv .venv && .venv\Scripts\activate
# macOS / Linux
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest # all tests, no live server needed
ruff check tmf_lint # lint
Related projects
| Project | Purpose |
|---|---|
| tmf-mock | Smart TMF mock server — the recommended test target for tmf-lint |
| TMFValidator | OAS/Swagger schema linter — validates the API definition, not runtime behaviour |
Roadmap
| Version | Planned additions |
|---|---|
| v0.2 | --fixtures for custom POST payloads, TMF688 notification checks |
| v0.3 | TMF633 Service Catalog, TMF634 Resource Catalog |
License
Apache 2.0 © Manoj Chavan
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tmf_lint-0.1.0.tar.gz.
File metadata
- Download URL: tmf_lint-0.1.0.tar.gz
- Upload date:
- Size: 29.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e3482553bd35d3dc6fdc24b7c7c38ceee6dbdddc84b6c9e40512c9081c99dea6
|
|
| MD5 |
d541b1cceaf3065d10b48e0f17d0ca3a
|
|
| BLAKE2b-256 |
299a036ad539a231264fd0c6627e47052b741afb1796622ad85cf0f76aadad9a
|
File details
Details for the file tmf_lint-0.1.0-py3-none-any.whl.
File metadata
- Download URL: tmf_lint-0.1.0-py3-none-any.whl
- Upload date:
- Size: 37.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1f705ca980e684c416be67984d7480d5d06ef6e367a523ef32dc7d054bd3a068
|
|
| MD5 |
da5f1a2d2e9ca09f60d5bc276a5d61f5
|
|
| BLAKE2b-256 |
067a28b6291afe088ab004d5cc7fcaa73e93bd0bc35cd8043193a47d12499447
|