mainsequence 9.0.3.dev33__tar.gz → 9.0.4__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.
Files changed (101) hide show
  1. {mainsequence-9.0.3.dev33/mainsequence.egg-info → mainsequence-9.0.4}/PKG-INFO +1 -1
  2. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/server/caller_assertions.py +12 -11
  3. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4/mainsequence.egg-info}/PKG-INFO +1 -1
  4. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/pyproject.toml +1 -1
  5. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_caller_assertions.py +7 -7
  6. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_fastapi_request_identity.py +6 -6
  7. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/LICENSE +0 -0
  8. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/README.md +0 -0
  9. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/agent_scaffold/AGENTS.md +0 -0
  10. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +0 -0
  11. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
  12. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/agent_scaffold/skills/mainsequence-inference/SKILL.md +0 -0
  13. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  14. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/agent_scaffold/skills/maintenance/code_repository_maintenance/SKILL.md +0 -0
  15. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/agent_scaffold/skills/maintenance/metatables_transition/SKILL.md +0 -0
  16. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  17. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
  18. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/agent_scaffold/skills/sdk_code_repository_execution/SKILL.md +0 -0
  19. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/__init__.py +0 -0
  20. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/__main__.py +0 -0
  21. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/_request_identity.py +0 -0
  22. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/bootstrap.py +0 -0
  23. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/cli/__init__.py +0 -0
  24. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/cli/api.py +0 -0
  25. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/cli/browser_auth.py +0 -0
  26. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/cli/cli.py +0 -0
  27. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/cli/code_repository_status.py +0 -0
  28. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/cli/config.py +0 -0
  29. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/cli/docker_utils.py +0 -0
  30. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/cli/doctor.py +0 -0
  31. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/cli/local_ops.py +0 -0
  32. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/cli/model_filters.py +0 -0
  33. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/cli/pydantic_cli.py +0 -0
  34. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/cli/sdk_utils.py +0 -0
  35. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/cli/ssh_utils.py +0 -0
  36. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/cli/ui.py +0 -0
  37. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/client/__init__.py +0 -0
  38. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/client/agent_runtime_models.py +0 -0
  39. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/client/base.py +0 -0
  40. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/client/client.py +0 -0
  41. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/client/compute_validation.py +0 -0
  42. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/client/exceptions.py +0 -0
  43. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/client/github_issues.py +0 -0
  44. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/client/inference.py +0 -0
  45. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/client/models_foundry.py +0 -0
  46. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/client/models_helpers.py +0 -0
  47. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/client/models_user.py +0 -0
  48. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/client/observability.py +0 -0
  49. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/client/utils.py +0 -0
  50. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/client/value_sets.py +0 -0
  51. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/code_repository_context.py +0 -0
  52. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/code_repository_skills.py +0 -0
  53. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/defaults.py +0 -0
  54. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/instrumentation/__init__.py +0 -0
  55. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/instrumentation/utils.py +0 -0
  56. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/logconf.py +0 -0
  57. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/repository_identity_security.py +0 -0
  58. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/runtime_flags.py +0 -0
  59. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/scaffold_skills.py +0 -0
  60. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/server/__init__.py +0 -0
  61. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence/server/fastapi.py +0 -0
  62. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence.egg-info/SOURCES.txt +0 -0
  63. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence.egg-info/dependency_links.txt +0 -0
  64. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence.egg-info/entry_points.txt +0 -0
  65. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence.egg-info/requires.txt +0 -0
  66. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/mainsequence.egg-info/top_level.txt +0 -0
  67. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/setup.cfg +0 -0
  68. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_auth_bootstrap.py +0 -0
  69. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_auth_precedence.py +0 -0
  70. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_canonical_api_route_contract.py +0 -0
  71. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_cli.py +0 -0
  72. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_cli_auth_contract.py +0 -0
  73. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_cli_browser_auth.py +0 -0
  74. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_cli_secure_storage.py +0 -0
  75. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_client.py +0 -0
  76. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_code_repository_branch_contract.py +0 -0
  77. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_code_repository_documentation_contract.py +0 -0
  78. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_code_repository_runtime_context.py +0 -0
  79. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_code_repository_skills.py +0 -0
  80. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_dependency_extras.py +0 -0
  81. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_dev_release_version.py +0 -0
  82. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_environment_resource_context.py +0 -0
  83. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_environment_response_contracts.py +0 -0
  84. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_filter_normalization.py +0 -0
  85. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_github_issues_client.py +0 -0
  86. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_independent_context.py +0 -0
  87. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_inference_client.py +0 -0
  88. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_instrumentation.py +0 -0
  89. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_job_client.py +0 -0
  90. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_local_ops.py +0 -0
  91. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_logconf.py +0 -0
  92. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_models_user_request_bound_auth.py +0 -0
  93. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_notification_uid_contract.py +0 -0
  94. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_observability_client.py +0 -0
  95. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_scaffold_skills.py +0 -0
  96. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_secret_client_model.py +0 -0
  97. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_source_ownership.py +0 -0
  98. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_ssh_utils.py +0 -0
  99. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_tolerant_response_reading.py +0 -0
  100. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_tolerant_value_sets.py +0 -0
  101. {mainsequence-9.0.3.dev33 → mainsequence-9.0.4}/tests/test_user_application_facts.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 9.0.3.dev33
3
+ Version: 9.0.4
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: MIT
@@ -15,14 +15,14 @@ import requests
15
15
 
16
16
  try:
17
17
  import jwt
18
- from cryptography.hazmat.primitives.asymmetric import rsa
18
+ from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
19
19
  from jwt import InvalidKeyError, InvalidTokenError
20
20
  except ImportError as exc:
21
21
  raise ImportError("Caller verification requires the mainsequence[server] extra.") from exc
22
22
 
23
23
  ASSERTION_HEADER = "X-MainSequence-Caller-Assertion"
24
24
  ASSERTION_TYPE = "mainsequence-caller-assertion+jwt"
25
- ASSERTION_ALGORITHM = "RS256"
25
+ ASSERTION_ALGORITHM = "EdDSA"
26
26
  MAX_ASSERTION_SECONDS = 300
27
27
  KEY_CACHE_SECONDS = 60
28
28
  REQUIRED_CLAIMS = frozenset(
@@ -107,7 +107,7 @@ class CallerAssertionVerifier:
107
107
  self.issuer = issuer
108
108
  self.jwks_url = jwks_url
109
109
  self._fetch_jwks = fetch_jwks or self._fetch_public_keys
110
- self._keys: dict[str, rsa.RSAPublicKey] = {}
110
+ self._keys: dict[str, Ed25519PublicKey] = {}
111
111
  self._keys_until = 0.0
112
112
  self._lock = threading.Lock()
113
113
 
@@ -141,35 +141,36 @@ class CallerAssertionVerifier:
141
141
  raise CallerAssertionUnavailable("Caller public keys are unavailable.") from None
142
142
 
143
143
  @staticmethod
144
- def _parse_public_keys(document: object) -> dict[str, rsa.RSAPublicKey]:
144
+ def _parse_public_keys(document: object) -> dict[str, Ed25519PublicKey]:
145
145
  if not isinstance(document, dict) or set(document) != {"keys"}:
146
146
  raise CallerAssertionUnavailable("Caller public-key document is invalid.")
147
147
  entries = document["keys"]
148
148
  if not isinstance(entries, list) or not 1 <= len(entries) <= 16:
149
149
  raise CallerAssertionUnavailable("Caller public-key set is invalid.")
150
- keys: dict[str, rsa.RSAPublicKey] = {}
150
+ keys: dict[str, Ed25519PublicKey] = {}
151
151
  for entry in entries:
152
152
  if (
153
153
  not isinstance(entry, dict)
154
- or set(entry) != {"kid", "alg", "use", "kty", "n", "e"}
154
+ or set(entry) != {"kid", "alg", "use", "kty", "crv", "x"}
155
155
  or entry.get("alg") != ASSERTION_ALGORITHM
156
156
  or entry.get("use") != "sig"
157
- or entry.get("kty") != "RSA"
157
+ or entry.get("kty") != "OKP"
158
+ or entry.get("crv") != "Ed25519"
158
159
  ):
159
160
  raise CallerAssertionUnavailable("Caller public key is invalid.")
160
161
  kid = entry["kid"]
161
162
  if not isinstance(kid, str) or not kid or len(kid) > 128 or kid in keys:
162
163
  raise CallerAssertionUnavailable("Caller public-key ID is invalid.")
163
164
  try:
164
- key = jwt.algorithms.RSAAlgorithm.from_jwk(entry)
165
+ key = jwt.algorithms.OKPAlgorithm.from_jwk(entry)
165
166
  except (ValueError, TypeError, InvalidKeyError) as exc:
166
167
  raise CallerAssertionUnavailable("Caller public key is invalid.") from exc
167
- if not isinstance(key, rsa.RSAPublicKey) or key.key_size < 2048:
168
- raise CallerAssertionUnavailable("Caller public key is too small.")
168
+ if not isinstance(key, Ed25519PublicKey):
169
+ raise CallerAssertionUnavailable("Caller public key is not an Ed25519 public key.")
169
170
  keys[kid] = key
170
171
  return keys
171
172
 
172
- def _key_for(self, kid: str) -> rsa.RSAPublicKey:
173
+ def _key_for(self, kid: str) -> Ed25519PublicKey:
173
174
  with self._lock:
174
175
  if time.monotonic() >= self._keys_until or kid not in self._keys:
175
176
  self._keys = {}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 9.0.3.dev33
3
+ Version: 9.0.4
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mainsequence"
7
- version = "9.0.3.dev33"
7
+ version = "9.0.4"
8
8
  description = "Main Sequence SDK"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -8,7 +8,7 @@ import pytest
8
8
  import requests
9
9
 
10
10
  jwt = pytest.importorskip("jwt")
11
- rsa = pytest.importorskip("cryptography.hazmat.primitives.asymmetric.rsa")
11
+ ed25519 = pytest.importorskip("cryptography.hazmat.primitives.asymmetric.ed25519")
12
12
 
13
13
  from mainsequence.server.caller_assertions import ( # noqa: E402
14
14
  ASSERTION_TYPE,
@@ -28,16 +28,16 @@ KEYS_URL = f"{ISSUER}/caller-keys/"
28
28
  def keys():
29
29
  result = []
30
30
  for kid in ("first", "second"):
31
- key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
32
- public = jwt.algorithms.RSAAlgorithm.to_jwk(key.public_key(), as_dict=True)
31
+ key = ed25519.Ed25519PrivateKey.generate()
32
+ public = jwt.algorithms.OKPAlgorithm.to_jwk(key.public_key(), as_dict=True)
33
33
  result.append(
34
34
  (
35
35
  key,
36
36
  {
37
37
  "kid": kid,
38
- "alg": "RS256",
38
+ "alg": "EdDSA",
39
39
  "use": "sig",
40
- **{name: public[name] for name in ("kty", "n", "e")},
40
+ **{name: public[name] for name in ("kty", "crv", "x")},
41
41
  },
42
42
  )
43
43
  )
@@ -58,7 +58,7 @@ def token(key, *, kid="first", headers=None, **changes):
58
58
  }
59
59
  claims.update(changes)
60
60
  return jwt.encode(
61
- claims, key, algorithm="RS256", headers=headers or {"kid": kid, "typ": ASSERTION_TYPE}
61
+ claims, key, algorithm="EdDSA", headers=headers or {"kid": kid, "typ": ASSERTION_TYPE}
62
62
  )
63
63
 
64
64
 
@@ -131,7 +131,7 @@ def test_rejects_signature_algorithm_type_and_missing_claims(keys):
131
131
  with pytest.raises(InvalidCallerAssertion):
132
132
  check.verify(
133
133
  jwt.encode(
134
- claims, key, algorithm="RS256", headers={"kid": "first", "typ": ASSERTION_TYPE}
134
+ claims, key, algorithm="EdDSA", headers={"kid": "first", "typ": ASSERTION_TYPE}
135
135
  )
136
136
  )
137
137
 
@@ -7,7 +7,7 @@ from uuid import uuid4
7
7
 
8
8
  import jwt
9
9
  import pytest
10
- from cryptography.hazmat.primitives.asymmetric import rsa
10
+ from cryptography.hazmat.primitives.asymmetric import ed25519
11
11
  from fastapi import FastAPI, Request, WebSocket
12
12
  from fastapi.testclient import TestClient
13
13
 
@@ -42,10 +42,10 @@ def clean_environment(monkeypatch):
42
42
 
43
43
  @pytest.fixture
44
44
  def signed(monkeypatch):
45
- key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
46
- public = jwt.algorithms.RSAAlgorithm.to_jwk(key.public_key(), as_dict=True)
47
- jwk = {name: public[name] for name in ("kty", "n", "e")}
48
- fetch = Mock(return_value={"keys": [{"kid": "test", "alg": "RS256", "use": "sig", **jwk}]})
45
+ key = ed25519.Ed25519PrivateKey.generate()
46
+ public = jwt.algorithms.OKPAlgorithm.to_jwk(key.public_key(), as_dict=True)
47
+ jwk = {name: public[name] for name in ("kty", "crv", "x")}
48
+ fetch = Mock(return_value={"keys": [{"kid": "test", "alg": "EdDSA", "use": "sig", **jwk}]})
49
49
  verifier = CallerAssertionVerifier(
50
50
  issuer=ISSUER,
51
51
  jwks_url=ISSUER + "/fastapi/caller-keys/",
@@ -70,7 +70,7 @@ def signed(monkeypatch):
70
70
  )
71
71
  claims.update(changes)
72
72
  return jwt.encode(
73
- claims, key, algorithm="RS256", headers={"kid": "test", "typ": ASSERTION_TYPE}
73
+ claims, key, algorithm="EdDSA", headers={"kid": "test", "typ": ASSERTION_TYPE}
74
74
  )
75
75
 
76
76
  return token, fetch, verifier
File without changes