mainsequence 9.0.6.dev37__tar.gz → 9.0.6.dev39__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 (102) hide show
  1. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/PKG-INFO +4 -5
  2. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/README.md +2 -2
  3. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/agent_scaffold/skills/maintenance/code_repository_maintenance/SKILL.md +23 -4
  4. mainsequence-9.0.6.dev39/mainsequence/server/__init__.py +1 -0
  5. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/server/caller_assertions.py +3 -7
  6. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence.egg-info/PKG-INFO +4 -5
  7. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence.egg-info/requires.txt +1 -3
  8. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/pyproject.toml +2 -5
  9. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_caller_assertions.py +3 -4
  10. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_dependency_extras.py +32 -0
  11. mainsequence-9.0.6.dev37/mainsequence/server/__init__.py +0 -1
  12. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/LICENSE +0 -0
  13. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/agent_scaffold/AGENTS.md +0 -0
  14. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +0 -0
  15. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
  16. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/agent_scaffold/skills/mainsequence-inference/SKILL.md +0 -0
  17. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  18. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/agent_scaffold/skills/maintenance/metatables_transition/SKILL.md +0 -0
  19. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  20. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
  21. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/agent_scaffold/skills/sdk_code_repository_execution/SKILL.md +0 -0
  22. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/__init__.py +0 -0
  23. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/__main__.py +0 -0
  24. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/_request_identity.py +0 -0
  25. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/bootstrap.py +0 -0
  26. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/cli/__init__.py +0 -0
  27. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/cli/api.py +0 -0
  28. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/cli/browser_auth.py +0 -0
  29. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/cli/cli.py +0 -0
  30. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/cli/code_repository_status.py +0 -0
  31. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/cli/config.py +0 -0
  32. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/cli/docker_utils.py +0 -0
  33. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/cli/doctor.py +0 -0
  34. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/cli/local_ops.py +0 -0
  35. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/cli/model_filters.py +0 -0
  36. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/cli/pydantic_cli.py +0 -0
  37. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/cli/sdk_utils.py +0 -0
  38. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/cli/ssh_utils.py +0 -0
  39. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/cli/ui.py +0 -0
  40. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/client/__init__.py +0 -0
  41. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/client/agent_runtime_models.py +0 -0
  42. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/client/base.py +0 -0
  43. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/client/client.py +0 -0
  44. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/client/compute_validation.py +0 -0
  45. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/client/exceptions.py +0 -0
  46. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/client/github_issues.py +0 -0
  47. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/client/inference.py +0 -0
  48. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/client/models_foundry.py +0 -0
  49. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/client/models_helpers.py +0 -0
  50. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/client/models_user.py +0 -0
  51. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/client/observability.py +0 -0
  52. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/client/utils.py +0 -0
  53. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/client/value_sets.py +0 -0
  54. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/code_repository_context.py +0 -0
  55. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/code_repository_skills.py +0 -0
  56. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/defaults.py +0 -0
  57. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/instrumentation/__init__.py +0 -0
  58. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/instrumentation/utils.py +0 -0
  59. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/logconf.py +0 -0
  60. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/repository_identity_security.py +0 -0
  61. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/runtime_flags.py +0 -0
  62. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/scaffold_skills.py +0 -0
  63. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence/server/fastapi.py +0 -0
  64. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence.egg-info/SOURCES.txt +0 -0
  65. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence.egg-info/dependency_links.txt +0 -0
  66. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence.egg-info/entry_points.txt +0 -0
  67. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/mainsequence.egg-info/top_level.txt +0 -0
  68. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/setup.cfg +0 -0
  69. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_auth_bootstrap.py +0 -0
  70. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_auth_precedence.py +0 -0
  71. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_canonical_api_route_contract.py +0 -0
  72. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_cli.py +0 -0
  73. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_cli_auth_contract.py +0 -0
  74. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_cli_browser_auth.py +0 -0
  75. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_cli_secure_storage.py +0 -0
  76. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_client.py +0 -0
  77. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_code_repository_branch_contract.py +0 -0
  78. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_code_repository_documentation_contract.py +0 -0
  79. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_code_repository_runtime_context.py +0 -0
  80. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_code_repository_skills.py +0 -0
  81. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_dev_release_version.py +0 -0
  82. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_environment_resource_context.py +0 -0
  83. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_environment_response_contracts.py +0 -0
  84. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_fastapi_request_identity.py +0 -0
  85. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_filter_normalization.py +0 -0
  86. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_github_issues_client.py +0 -0
  87. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_independent_context.py +0 -0
  88. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_inference_client.py +0 -0
  89. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_instrumentation.py +0 -0
  90. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_job_client.py +0 -0
  91. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_local_ops.py +0 -0
  92. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_logconf.py +0 -0
  93. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_models_user_request_bound_auth.py +0 -0
  94. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_notification_uid_contract.py +0 -0
  95. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_observability_client.py +0 -0
  96. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_scaffold_skills.py +0 -0
  97. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_secret_client_model.py +0 -0
  98. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_source_ownership.py +0 -0
  99. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_ssh_utils.py +0 -0
  100. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_tolerant_response_reading.py +0 -0
  101. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/tests/test_tolerant_value_sets.py +0 -0
  102. {mainsequence-9.0.6.dev37 → mainsequence-9.0.6.dev39}/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.6.dev37
3
+ Version: 9.0.6.dev39
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: MIT
@@ -25,13 +25,12 @@ Requires-Dist: protobuf>=6.33.5
25
25
  Requires-Dist: psutil
26
26
  Requires-Dist: pydantic<3,>=2.11
27
27
  Requires-Dist: pygments>=2.20.0
28
+ Requires-Dist: PyJWT[crypto]<3,>=2.10
28
29
  Requires-Dist: pyyaml
29
30
  Requires-Dist: requests>=2.33.0
30
31
  Requires-Dist: structlog
31
32
  Requires-Dist: typer
32
33
  Requires-Dist: urllib3>=2.7.0
33
- Provides-Extra: server
34
- Requires-Dist: PyJWT[crypto]<3,>=2.10; extra == "server"
35
34
  Dynamic: license-file
36
35
 
37
36
  <p align="center">
@@ -75,7 +74,7 @@ Main package areas:
75
74
  authentication, platform resources, and local CodeRepository operations
76
75
  - `mainsequence.instrumentation` and `mainsequence.logconf`: SDK tracing and
77
76
  logging integration
78
- - `mainsequence.server`: optional server-side caller assertion verification
77
+ - `mainsequence.server`: server-side caller assertion verification
79
78
  - `mainsequence.scaffold_skills`: reusable, version-pinned skill copying for
80
79
  this SDK and extension libraries
81
80
 
@@ -148,7 +147,7 @@ another repository, use the explicitly scoped `filter_admin` path. See
148
147
  [Resource releases](docs/knowledge/infrastructure/resource_releases.md) for
149
148
  supported filters and examples.
150
149
 
151
- Server integrations can install `mainsequence[server]` for the
150
+ The standard `mainsequence` installation includes PyJWT and cryptography for the
152
151
  framework-independent [caller assertion verifier](docs/knowledge/server/caller_assertions.md).
153
152
  Applications remain responsible for resource authorization and storage
154
153
  operations.
@@ -39,7 +39,7 @@ Main package areas:
39
39
  authentication, platform resources, and local CodeRepository operations
40
40
  - `mainsequence.instrumentation` and `mainsequence.logconf`: SDK tracing and
41
41
  logging integration
42
- - `mainsequence.server`: optional server-side caller assertion verification
42
+ - `mainsequence.server`: server-side caller assertion verification
43
43
  - `mainsequence.scaffold_skills`: reusable, version-pinned skill copying for
44
44
  this SDK and extension libraries
45
45
 
@@ -112,7 +112,7 @@ another repository, use the explicitly scoped `filter_admin` path. See
112
112
  [Resource releases](docs/knowledge/infrastructure/resource_releases.md) for
113
113
  supported filters and examples.
114
114
 
115
- Server integrations can install `mainsequence[server]` for the
115
+ The standard `mainsequence` installation includes PyJWT and cryptography for the
116
116
  framework-independent [caller assertion verifier](docs/knowledge/server/caller_assertions.md).
117
117
  Applications remain responsible for resource authorization and storage
118
118
  operations.
@@ -374,10 +374,29 @@ another branch, deploys nothing for that target.
374
374
 
375
375
  ### Going Back To An Older Version
376
376
 
377
- Revert the change and release a new version: `git revert <commit>`, raise the
378
- patch version with `uv version --bump patch`, commit, push, and let CI tag the
379
- result. The version keeps moving forward and every deployed commit matches its
380
- tag.
377
+ Two ways work. Use either only when the user asks for it.
378
+
379
+ - Revert and release a new version: `git revert <commit>`, raise the patch
380
+ version with `uv version --bump patch`, commit, push, and let CI tag the
381
+ result. This works for every target, including every-push targets, and keeps
382
+ the version moving forward.
383
+ - For a target with a `tag_regex`, push the older version's tag again. GitHub
384
+ sends an event only when a tag is created, so delete the tag on GitHub and
385
+ push it again; it still points at the same commit:
386
+
387
+ ```bash
388
+ git fetch --tags origin
389
+ git push origin :refs/tags/v1.2.0
390
+ git push origin v1.2.0
391
+ ```
392
+
393
+ The target redeploys that commit exactly as it was released: its code, its
394
+ image and its workflow file, whose settings replace the current ones. The
395
+ commit must still be on the branch and the tag must match the target's
396
+ current `tag_regex`. Every-push targets ignore the tag. Re-pushing a tag
397
+ also re-runs any GitHub Actions workflow that the tag triggers, and a tag
398
+ ruleset may forbid deleting it; use the revert route then. The next release
399
+ tag deploys a newer version again.
381
400
 
382
401
  ## Diagnose Partial Completion Before Retrying
383
402
 
@@ -0,0 +1 @@
1
+ """Server-side platform integrations. Import integrations explicitly."""
@@ -11,14 +11,10 @@ from collections.abc import Callable
11
11
  from dataclasses import dataclass
12
12
  from urllib.parse import urlsplit
13
13
 
14
+ import jwt
14
15
  import requests
15
-
16
- try:
17
- import jwt
18
- from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
19
- from jwt import InvalidKeyError, InvalidTokenError
20
- except ImportError as exc:
21
- raise ImportError("Caller verification requires the mainsequence[server] extra.") from exc
16
+ from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
17
+ from jwt import InvalidKeyError, InvalidTokenError
22
18
 
23
19
  ASSERTION_HEADER = "X-MainSequence-Caller-Assertion"
24
20
  ASSERTION_TYPE = "mainsequence-caller-assertion+jwt"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 9.0.6.dev37
3
+ Version: 9.0.6.dev39
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: MIT
@@ -25,13 +25,12 @@ Requires-Dist: protobuf>=6.33.5
25
25
  Requires-Dist: psutil
26
26
  Requires-Dist: pydantic<3,>=2.11
27
27
  Requires-Dist: pygments>=2.20.0
28
+ Requires-Dist: PyJWT[crypto]<3,>=2.10
28
29
  Requires-Dist: pyyaml
29
30
  Requires-Dist: requests>=2.33.0
30
31
  Requires-Dist: structlog
31
32
  Requires-Dist: typer
32
33
  Requires-Dist: urllib3>=2.7.0
33
- Provides-Extra: server
34
- Requires-Dist: PyJWT[crypto]<3,>=2.10; extra == "server"
35
34
  Dynamic: license-file
36
35
 
37
36
  <p align="center">
@@ -75,7 +74,7 @@ Main package areas:
75
74
  authentication, platform resources, and local CodeRepository operations
76
75
  - `mainsequence.instrumentation` and `mainsequence.logconf`: SDK tracing and
77
76
  logging integration
78
- - `mainsequence.server`: optional server-side caller assertion verification
77
+ - `mainsequence.server`: server-side caller assertion verification
79
78
  - `mainsequence.scaffold_skills`: reusable, version-pinned skill copying for
80
79
  this SDK and extension libraries
81
80
 
@@ -148,7 +147,7 @@ another repository, use the explicitly scoped `filter_admin` path. See
148
147
  [Resource releases](docs/knowledge/infrastructure/resource_releases.md) for
149
148
  supported filters and examples.
150
149
 
151
- Server integrations can install `mainsequence[server]` for the
150
+ The standard `mainsequence` installation includes PyJWT and cryptography for the
152
151
  framework-independent [caller assertion verifier](docs/knowledge/server/caller_assertions.md).
153
152
  Applications remain responsible for resource authorization and storage
154
153
  operations.
@@ -10,11 +10,9 @@ protobuf>=6.33.5
10
10
  psutil
11
11
  pydantic<3,>=2.11
12
12
  pygments>=2.20.0
13
+ PyJWT[crypto]<3,>=2.10
13
14
  pyyaml
14
15
  requests>=2.33.0
15
16
  structlog
16
17
  typer
17
18
  urllib3>=2.7.0
18
-
19
- [server]
20
- PyJWT[crypto]<3,>=2.10
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mainsequence"
7
- version = "9.0.6.dev37"
7
+ version = "9.0.6.dev39"
8
8
  description = "Main Sequence SDK"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -34,6 +34,7 @@ dependencies = [
34
34
  "psutil",
35
35
  "pydantic>=2.11,<3",
36
36
  "pygments>=2.20.0",
37
+ "PyJWT[crypto]>=2.10,<3",
37
38
  "pyyaml",
38
39
  "requests>=2.33.0",
39
40
  "structlog",
@@ -41,9 +42,6 @@ dependencies = [
41
42
  "urllib3>=2.7.0",
42
43
  ]
43
44
 
44
- [project.optional-dependencies]
45
- server = ["PyJWT[crypto]>=2.10,<3"]
46
-
47
45
  [project.urls]
48
46
  Homepage = "https://github.com/mainsequence-sdk/mainsequence-sdk"
49
47
  Issues = "https://github.com/mainsequence-sdk/mainsequence-sdk/issues"
@@ -56,7 +54,6 @@ ms = "mainsequence.cli.cli:app"
56
54
  dev = [
57
55
  "fastapi>=0.110,<1",
58
56
  "httpx>=0.27,<1",
59
- "PyJWT[crypto]>=2.10,<3",
60
57
  "black>=26.3.1",
61
58
  "IPython",
62
59
  "mkdocs",
@@ -4,13 +4,12 @@ import json
4
4
  import time
5
5
  from uuid import uuid4
6
6
 
7
+ import jwt
7
8
  import pytest
8
9
  import requests
10
+ from cryptography.hazmat.primitives.asymmetric import ed25519
9
11
 
10
- jwt = pytest.importorskip("jwt")
11
- ed25519 = pytest.importorskip("cryptography.hazmat.primitives.asymmetric.ed25519")
12
-
13
- from mainsequence.server.caller_assertions import ( # noqa: E402
12
+ from mainsequence.server.caller_assertions import (
14
13
  ASSERTION_TYPE,
15
14
  CallerAssertionUnavailable,
16
15
  CallerAssertionVerifier,
@@ -6,6 +6,7 @@ import tomllib
6
6
  import types
7
7
 
8
8
  import pytest
9
+ from packaging.requirements import Requirement
9
10
 
10
11
 
11
12
  def _snapshot_mainsequence_modules() -> dict[str, types.ModuleType]:
@@ -57,3 +58,34 @@ def test_streamlit_is_absent_from_dependency_contracts() -> None:
57
58
  )
58
59
  assert '\nname = "streamlit"\n' not in (repo_root / "uv.lock").read_text(encoding="utf-8")
59
60
  assert "streamlit" not in (repo_root / "requirements.txt").read_text(encoding="utf-8").lower()
61
+
62
+
63
+ def test_caller_verification_dependencies_are_required() -> None:
64
+ repo_root = pathlib.Path(__file__).resolve().parents[1]
65
+ project = tomllib.loads((repo_root / "pyproject.toml").read_text(encoding="utf-8"))["project"]
66
+ dependencies = {
67
+ requirement.name.lower(): requirement
68
+ for requirement in map(Requirement, project["dependencies"])
69
+ }
70
+
71
+ assert "pyjwt" in dependencies
72
+ assert dependencies["pyjwt"].marker is None
73
+ assert "crypto" in dependencies["pyjwt"].extras
74
+ assert "server" not in project.get("optional-dependencies", {})
75
+
76
+ lock = tomllib.loads((repo_root / "uv.lock").read_text(encoding="utf-8"))
77
+ sdk = next(package for package in lock["package"] if package["name"] == "mainsequence")
78
+ jwt_dependency = next(item for item in sdk["dependencies"] if item["name"] == "pyjwt")
79
+ assert "crypto" in jwt_dependency["extra"]
80
+ assert "server" not in sdk.get("optional-dependencies", {})
81
+ assert "server" not in sdk["metadata"].get("provides-extras", [])
82
+
83
+ requirements = {
84
+ requirement.name.lower(): requirement
85
+ for line in (repo_root / "requirements.txt").read_text(encoding="utf-8").splitlines()
86
+ if line.strip() and not line.lstrip().startswith(("#", "-"))
87
+ for requirement in [Requirement(line)]
88
+ }
89
+ for name in ("pyjwt", "cryptography"):
90
+ assert name in requirements
91
+ assert requirements[name].marker is None
@@ -1 +0,0 @@
1
- """Optional server-side platform integrations. Import integrations explicitly."""