contractlane-operator-sdk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,9 @@
1
+ # local integration environment overrides
2
+ env/.env.integration
3
+
4
+ # local caches/artifacts
5
+ .gocache/
6
+ sdk-typescript/node_modules/
7
+ sdk-typescript/dist/
8
+ sdk-python/.venv/
9
+ sdk-python/.pytest_cache/
@@ -0,0 +1,96 @@
1
+ Metadata-Version: 2.4
2
+ Name: contractlane-operator-sdk
3
+ Version: 0.1.0
4
+ Summary: Python SDK for Contract Lane Operator API
5
+ Author: Contract Lane
6
+ License: MIT
7
+ Requires-Python: >=3.10
8
+ Requires-Dist: httpx>=0.27.2
9
+ Requires-Dist: pydantic>=2.10.3
10
+ Provides-Extra: dev
11
+ Requires-Dist: mypy>=1.14.0; extra == 'dev'
12
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
13
+ Requires-Dist: pytest>=8.3.4; extra == 'dev'
14
+ Requires-Dist: ruff>=0.8.2; extra == 'dev'
15
+ Description-Content-Type: text/markdown
16
+
17
+ # contractlane-operator-sdk
18
+
19
+ Python SDK for the Contract Lane Operator API.
20
+
21
+ ## Install
22
+ ```bash
23
+ pip install contractlane-operator-sdk
24
+ ```
25
+
26
+ ## Quickstart
27
+ ```python
28
+ from contractlane_operator_sdk import ClientOptions, OperatorClient
29
+
30
+ client = OperatorClient(
31
+ ClientOptions(
32
+ base_url="https://localhost",
33
+ session_token=lambda: "session-token",
34
+ operator_token=lambda: "operator-token",
35
+ challenge_headers=lambda _: {
36
+ "X-Signup-Challenge": "signup-challenge-token",
37
+ "X-Operator-Challenge": "proof-challenge",
38
+ "X-Operator-Challenge-Token": "challenge-provider-token",
39
+ },
40
+ )
41
+ )
42
+ ```
43
+
44
+ ### 1) Human signup/auth
45
+ ```python
46
+ start = client.public.signup.start({"email": "owner@example.com", "org_name": "Acme"})
47
+ session_id = start.data["signup_session"]["session_id"]
48
+
49
+ client.public.signup.verify({"session_id": session_id, "verification_code": "123456"})
50
+ client.public.signup.complete({"session_id": session_id, "project_name": "Default", "agent_name": "Primary"})
51
+ ```
52
+
53
+ ### 2) Admin actor + credential issue
54
+ ```python
55
+ org = client.operator.admin.create_org({"name": "Acme", "admin_email": "owner@example.com"})
56
+ org_id = org.data["org"]["org_id"]
57
+ project = client.operator.admin.create_project(org_id, {"name": "Project A"})
58
+ project_id = project.data["project"]["project_id"]
59
+ actor = client.operator.admin.create_actor(project_id, {"name": "Bot", "scopes": ["cel.contracts:write"]})
60
+ actor_id = actor.data["actor"]["actor_id"]
61
+ client.operator.admin.issue_credential({"actor_id": actor_id, "upstream_token": "upstream-token"})
62
+ ```
63
+
64
+ ### 3) Agent-first enrollment
65
+ ```python
66
+ challenge = client.public.agent_enrollment.challenge(
67
+ {"public_key_jwk": {"kty": "OKP", "crv": "Ed25519", "x": "..."}}
68
+ )
69
+ challenge_id = challenge.data["challenge"]["challenge_id"]
70
+ client.public.agent_enrollment.start(
71
+ {
72
+ "challenge_id": challenge_id,
73
+ "signature": "base64url-signature",
74
+ "sponsor_email": "owner@example.com",
75
+ "requested_scopes": ["cel.contracts:write"],
76
+ }
77
+ )
78
+ ```
79
+
80
+ ### 4) Gateway contract action
81
+ ```python
82
+ client.gateway.cel.create_contract({"template_id": "tpl_123", "payload": {}})
83
+ client.gateway.cel.contract_action("ctr_123", "send", {"note": "go"})
84
+ ```
85
+
86
+ ## Notes
87
+ - Mutating operator/public endpoints auto-inject `Idempotency-Key`.
88
+ - `request_id` is available via `response.meta.request_id`.
89
+ - Challenge hooks can provide `X-Signup-Challenge`, `X-Operator-Challenge`, and `X-Operator-Challenge-Token`; per-request headers can override hook values.
90
+ - Failures raise `APIError` with `status`, `code`, `message`, `request_id`, `meta`, `raw_body`.
91
+
92
+ ## Integration Tests
93
+ Run against a live operator stack:
94
+ ```bash
95
+ python -m pytest tests/integration -m integration
96
+ ```
@@ -0,0 +1,80 @@
1
+ # contractlane-operator-sdk
2
+
3
+ Python SDK for the Contract Lane Operator API.
4
+
5
+ ## Install
6
+ ```bash
7
+ pip install contractlane-operator-sdk
8
+ ```
9
+
10
+ ## Quickstart
11
+ ```python
12
+ from contractlane_operator_sdk import ClientOptions, OperatorClient
13
+
14
+ client = OperatorClient(
15
+ ClientOptions(
16
+ base_url="https://localhost",
17
+ session_token=lambda: "session-token",
18
+ operator_token=lambda: "operator-token",
19
+ challenge_headers=lambda _: {
20
+ "X-Signup-Challenge": "signup-challenge-token",
21
+ "X-Operator-Challenge": "proof-challenge",
22
+ "X-Operator-Challenge-Token": "challenge-provider-token",
23
+ },
24
+ )
25
+ )
26
+ ```
27
+
28
+ ### 1) Human signup/auth
29
+ ```python
30
+ start = client.public.signup.start({"email": "owner@example.com", "org_name": "Acme"})
31
+ session_id = start.data["signup_session"]["session_id"]
32
+
33
+ client.public.signup.verify({"session_id": session_id, "verification_code": "123456"})
34
+ client.public.signup.complete({"session_id": session_id, "project_name": "Default", "agent_name": "Primary"})
35
+ ```
36
+
37
+ ### 2) Admin actor + credential issue
38
+ ```python
39
+ org = client.operator.admin.create_org({"name": "Acme", "admin_email": "owner@example.com"})
40
+ org_id = org.data["org"]["org_id"]
41
+ project = client.operator.admin.create_project(org_id, {"name": "Project A"})
42
+ project_id = project.data["project"]["project_id"]
43
+ actor = client.operator.admin.create_actor(project_id, {"name": "Bot", "scopes": ["cel.contracts:write"]})
44
+ actor_id = actor.data["actor"]["actor_id"]
45
+ client.operator.admin.issue_credential({"actor_id": actor_id, "upstream_token": "upstream-token"})
46
+ ```
47
+
48
+ ### 3) Agent-first enrollment
49
+ ```python
50
+ challenge = client.public.agent_enrollment.challenge(
51
+ {"public_key_jwk": {"kty": "OKP", "crv": "Ed25519", "x": "..."}}
52
+ )
53
+ challenge_id = challenge.data["challenge"]["challenge_id"]
54
+ client.public.agent_enrollment.start(
55
+ {
56
+ "challenge_id": challenge_id,
57
+ "signature": "base64url-signature",
58
+ "sponsor_email": "owner@example.com",
59
+ "requested_scopes": ["cel.contracts:write"],
60
+ }
61
+ )
62
+ ```
63
+
64
+ ### 4) Gateway contract action
65
+ ```python
66
+ client.gateway.cel.create_contract({"template_id": "tpl_123", "payload": {}})
67
+ client.gateway.cel.contract_action("ctr_123", "send", {"note": "go"})
68
+ ```
69
+
70
+ ## Notes
71
+ - Mutating operator/public endpoints auto-inject `Idempotency-Key`.
72
+ - `request_id` is available via `response.meta.request_id`.
73
+ - Challenge hooks can provide `X-Signup-Challenge`, `X-Operator-Challenge`, and `X-Operator-Challenge-Token`; per-request headers can override hook values.
74
+ - Failures raise `APIError` with `status`, `code`, `message`, `request_id`, `meta`, `raw_body`.
75
+
76
+ ## Integration Tests
77
+ Run against a live operator stack:
78
+ ```bash
79
+ python -m pytest tests/integration -m integration
80
+ ```
@@ -0,0 +1,34 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.26.0"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "contractlane-operator-sdk"
7
+ version = "0.1.0"
8
+ description = "Python SDK for Contract Lane Operator API"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Contract Lane" }]
13
+ dependencies = [
14
+ "httpx>=0.27.2",
15
+ "pydantic>=2.10.3"
16
+ ]
17
+
18
+ [project.optional-dependencies]
19
+ dev = [
20
+ "pytest>=8.3.4",
21
+ "pytest-asyncio>=0.24.0",
22
+ "ruff>=0.8.2",
23
+ "mypy>=1.14.0"
24
+ ]
25
+
26
+ [tool.hatch.build.targets.wheel]
27
+ packages = ["src/contractlane_operator_sdk"]
28
+
29
+ [tool.pytest.ini_options]
30
+ pythonpath = ["src"]
31
+ asyncio_mode = "auto"
32
+ markers = [
33
+ "integration: live integration tests against a running operator stack"
34
+ ]
@@ -0,0 +1,22 @@
1
+ from .client import AsyncOperatorClient, OperatorClient
2
+ from .errors import APIError
3
+ from .models import (
4
+ APIResponse,
5
+ AuthMode,
6
+ ClientOptions,
7
+ RequestOptions,
8
+ ResponseMeta,
9
+ RetryOptions,
10
+ )
11
+
12
+ __all__ = [
13
+ "APIError",
14
+ "APIResponse",
15
+ "AuthMode",
16
+ "ClientOptions",
17
+ "RequestOptions",
18
+ "ResponseMeta",
19
+ "RetryOptions",
20
+ "OperatorClient",
21
+ "AsyncOperatorClient",
22
+ ]