mainsequence 8.1.21.dev20__tar.gz → 8.1.22__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 (144) hide show
  1. {mainsequence-8.1.21.dev20/mainsequence.egg-info → mainsequence-8.1.22}/PKG-INFO +1 -1
  2. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +81 -22
  3. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +34 -100
  4. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/api.py +0 -368
  5. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/cli.py +0 -1227
  6. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/base.py +5 -0
  7. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/models_foundry.py +3 -71
  8. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/models_helpers.py +4 -544
  9. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22/mainsequence.egg-info}/PKG-INFO +1 -1
  10. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/pyproject.toml +1 -1
  11. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_cli.py +9 -1024
  12. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_code_repository_batch_jobs_from_file.py +1 -18
  13. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_filter_normalization.py +23 -309
  14. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_tolerant_value_sets.py +1 -26
  15. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/LICENSE +0 -0
  16. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/MANIFEST.in +0 -0
  17. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/README.md +0 -0
  18. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/AGENTS.md +0 -0
  19. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +0 -0
  20. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
  21. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
  22. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
  23. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/data_publishing/time_index_table_updates/SKILL.md +0 -0
  24. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  25. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/maintenance/code_repository_maintenance/SKILL.md +0 -0
  26. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  27. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/sdk_code_repository_execution/SKILL.md +0 -0
  28. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/__init__.py +0 -0
  29. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/__main__.py +0 -0
  30. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/bootstrap.py +0 -0
  31. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/__init__.py +0 -0
  32. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/browser_auth.py +0 -0
  33. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/code_repository_status.py +0 -0
  34. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/config.py +0 -0
  35. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/docker_utils.py +0 -0
  36. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/doctor.py +0 -0
  37. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/local_ops.py +0 -0
  38. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/migrations.py +0 -0
  39. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/model_filters.py +0 -0
  40. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/pydantic_cli.py +0 -0
  41. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/sdk_utils.py +0 -0
  42. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/ssh_utils.py +0 -0
  43. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/ui.py +0 -0
  44. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/__init__.py +0 -0
  45. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/agent_runtime_models.py +0 -0
  46. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/client.py +0 -0
  47. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/compute_validation.py +0 -0
  48. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
  49. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
  50. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
  51. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
  52. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/dtype_codec.py +0 -0
  53. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/exceptions.py +0 -0
  54. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/github_issues.py +0 -0
  55. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/metatables/__init__.py +0 -0
  56. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/metatables/core.py +0 -0
  57. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/models_user.py +0 -0
  58. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/observability.py +0 -0
  59. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/utils.py +0 -0
  60. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/value_sets.py +0 -0
  61. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/code_repository_context.py +0 -0
  62. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/code_repository_skills.py +0 -0
  63. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/defaults.py +0 -0
  64. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/instrumentation/__init__.py +0 -0
  65. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/instrumentation/utils.py +0 -0
  66. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/logconf.py +0 -0
  67. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/__init__.py +0 -0
  68. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/__main__.py +0 -0
  69. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
  70. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
  71. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/future_registry.py +0 -0
  72. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/hashing.py +0 -0
  73. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/__init__.py +0 -0
  74. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/alembic.py +0 -0
  75. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/env.py +0 -0
  76. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/provider.py +0 -0
  77. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/registry.py +0 -0
  78. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
  79. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
  80. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
  81. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
  82. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
  83. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/schema_names.py +0 -0
  84. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
  85. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_refs.py +0 -0
  86. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/__init__.py +0 -0
  87. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/configuration.py +0 -0
  88. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/dependencies.py +0 -0
  89. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/managers.py +0 -0
  90. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/namespacing.py +0 -0
  91. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/runner.py +0 -0
  92. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/updaters.py +0 -0
  93. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/utils.py +0 -0
  94. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/repository_identity_security.py +0 -0
  95. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/runtime_flags.py +0 -0
  96. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/scaffold_skills.py +0 -0
  97. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence.egg-info/SOURCES.txt +0 -0
  98. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence.egg-info/dependency_links.txt +0 -0
  99. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence.egg-info/entry_points.txt +0 -0
  100. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence.egg-info/requires.txt +0 -0
  101. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence.egg-info/top_level.txt +0 -0
  102. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/setup.cfg +0 -0
  103. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/fixtures/time_index_table_update_hash_v2_golden.json +0 -0
  104. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_auth_precedence.py +0 -0
  105. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_canonical_api_route_contract.py +0 -0
  106. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_cli_browser_auth.py +0 -0
  107. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_cli_migrations.py +0 -0
  108. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_client.py +0 -0
  109. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_code_repository_branch_contract.py +0 -0
  110. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_code_repository_documentation_contract.py +0 -0
  111. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_code_repository_runtime_context.py +0 -0
  112. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_code_repository_skills.py +0 -0
  113. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_dependency_extras.py +0 -0
  114. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_dev_release_version.py +0 -0
  115. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_duckdb_interface_dimensions.py +0 -0
  116. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_environment_resource_context.py +0 -0
  117. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_environment_response_contracts.py +0 -0
  118. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_github_issues_client.py +0 -0
  119. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_instrumentation.py +0 -0
  120. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_local_ops.py +0 -0
  121. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_logconf.py +0 -0
  122. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_meta_table_migrations.py +0 -0
  123. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_meta_tables_client_models.py +0 -0
  124. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
  125. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_models_user_request_bound_auth.py +0 -0
  126. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_notification_uid_contract.py +0 -0
  127. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_observability_client.py +0 -0
  128. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_pod_project_resolution.py +0 -0
  129. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_scaffold_skills.py +0 -0
  130. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_schema_names.py +0 -0
  131. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_secret_client_model.py +0 -0
  132. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_source_table_configuration.py +0 -0
  133. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_sqlite_interface_dimensions.py +0 -0
  134. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_ssh_utils.py +0 -0
  135. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_time_index_table_access_dimension_audit.py +0 -0
  136. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_time_index_table_dimension_queries.py +0 -0
  137. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_time_index_table_update_configuration.py +0 -0
  138. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_time_index_table_update_configuration_client.py +0 -0
  139. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_time_index_table_update_flow.py +0 -0
  140. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_time_index_table_update_hard_cut.py +0 -0
  141. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_tolerant_response_reading.py +0 -0
  142. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_update_runner_uid_runtime.py +0 -0
  143. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_update_statistics.py +0 -0
  144. {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_update_uid_guards.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 8.1.21.dev20
3
+ Version: 8.1.22
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: LicenseRef-MainSequence-Proprietary
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: mainsequence-command-center-fastapi
3
- description: Build, contract-test, release, and verify a FastAPI code repository resource that serves the Command Center frontend. Use when a Main Sequence API must implement a wire contract defined by the mainsequence-sdk/command-center-sdk GitHub repository and then move through local testing, code-repository sync, image and resource resolution, FastAPI ResourceRelease creation, and deployed frontend validation.
3
+ description: Build, contract-test, release, and verify a FastAPI code repository resource serving the Command Center frontend, including applications with public OAuth callback or webhook routes. Use when implementing a Command Center wire contract, declaring exact public ingress, or validating the deployed API.
4
4
  ---
5
5
 
6
6
  # Command Center FastAPI Release Lifecycle
@@ -92,7 +92,7 @@ Record:
92
92
  - whether the API uses backend transport or a contract-defined direct
93
93
  development transport
94
94
 
95
- FastAPI releases receive the authenticated human from the Main Sequence
95
+ Authenticated FastAPI routes receive the human caller from the Main Sequence
96
96
  platform through injected request state. No SDK authentication setup is
97
97
  required in repository code:
98
98
 
@@ -111,21 +111,74 @@ def get_me(request: Request) -> dict[str, str | None]:
111
111
  }
112
112
  ```
113
113
 
114
- Route code must not detect local versus deployed execution, parse
115
- authentication headers, or resolve the request user itself. Consume only the
114
+ Protected route code must not detect local versus deployed execution, parse
115
+ authentication headers, or resolve the request user itself. Consume the
116
116
  platform-injected human caller identity:
117
117
 
118
118
  - `request.state.user` contains canonical `uid` and optional `username`
119
119
  - `request.state.user_uid` is the canonical public user UUID
120
120
  - `request.state.user_id` does not exist
121
121
 
122
- This identity is the human making the current HTTP request. It is not the
123
- release creator, deployment owner, runtime workload principal, or runtime
124
- target. Pass request state explicitly to shared services; do not use
125
- `User.get_logged_user()` as a FastAPI entry point. Platform-injected identity is
122
+ On a protected route, this identity is the human making the current HTTP
123
+ request. It is not the release creator, deployment owner, runtime workload
124
+ principal, or runtime target. Pass request state explicitly to shared services;
125
+ do not use `User.get_logged_user()` as a FastAPI entry point. Platform-injected identity is
126
126
  not resource authorization; use `request.state.user_uid` when applying the
127
127
  endpoint's authorization policy.
128
128
 
129
+ ### Public provider callbacks and webhooks
130
+
131
+ An external OAuth redirect or webhook cannot supply a Main Sequence Bearer token.
132
+ For a FastAPI release that needs one, use the platform's exact `public_ingress`
133
+ policy. CORS configuration and an app-declared route alone do not make a path
134
+ public. Ordinary routes remain Bearer authenticated.
135
+
136
+ 1. Implement the provider handler in the FastAPI app loaded by the workflow's
137
+ `source_path`. Declare only its exact `GET` or `POST` method and literal
138
+ root-relative path under the `kind: fastapi` resource's
139
+ `spec.public_ingress`. The policy is not inferred from decorators or OpenAPI.
140
+ Do not include query strings, route parameters, wildcards, or a hostname.
141
+ The default empty list exposes no public paths. In a validated workflow
142
+ resource, the declaration has this shape:
143
+
144
+ ```yaml
145
+ kind: fastapi
146
+ spec:
147
+ source_path: api/provider/main.py
148
+ public_ingress:
149
+ - method: GET
150
+ path: /integrations/provider/oauth/callback/
151
+ - method: POST
152
+ path: /integrations/provider/webhook/
153
+ ```
154
+
155
+ 2. Fetch the exact CodeRepositoryBranch's current workflow template; use its
156
+ advertised version and fields. Validate the proposed workflow file through
157
+ the branch's `validate-workflow` action, then commit the handler and workflow
158
+ file and push the intended branch. Do not set the reserved
159
+ `FASTAPI_PUBLIC_INGRESS` environment value yourself.
160
+ 3. Follow the repository event and DeploymentRun to a ready active revision.
161
+ A validated file or successful push is not proof of public admission. Read
162
+ `resource_release.get` and confirm the pair appears in both desired
163
+ `public_ingress` and active `effective_public_ingress`. Only then append the
164
+ declared path to the backend-returned `public_url` and register that full
165
+ callback or webhook URI with the provider. Do not construct a hostname.
166
+ 4. Send a provider-style request without a Main Sequence Bearer token to the
167
+ exact public pair. Check that an unlisted path or wrong method is denied.
168
+ An admitted request has `request.state.user` and `user_uid` set to `None`
169
+ and `request.state.auth_outcome == "public_ingress"`. The handler must verify
170
+ OAuth state and exchange codes, or verify the webhook signature against the
171
+ original body and reject replays. Public admission supplies no User or
172
+ provider identity. Keep provider secrets and live codes out of workflow YAML,
173
+ logs, and test evidence.
174
+
175
+ An existing release can change its desired policy through the canonical
176
+ `resource_release.update` operation. Adding a pair still requires a later ready
177
+ revision containing the route before it becomes public. Removing a desired pair
178
+ denies it immediately. The platform skill
179
+ `mainsequence://platform/skills/code-repository-workflows` owns the detailed
180
+ automatic deployment procedure and current workflow shape.
181
+
129
182
  ### 2. Implement the provider
130
183
 
131
184
  Keep Command Center contract-bearing route code focused on transport and
@@ -187,35 +240,38 @@ Before release, verify local CodeRepository resolution:
187
240
  mainsequence code-repository current --debug --json
188
241
  ```
189
242
 
190
- Then move the tested code through the canonical lifecycle:
243
+ Declare the FastAPI resource in `.mainsequence/workflows/`, validate the
244
+ workflow against the backend template, then move the tested commit through the
245
+ canonical lifecycle:
191
246
 
192
247
  ```bash
193
248
  mainsequence code-repository sync -m "Release Command Center API"
194
- mainsequence code-repository images create
195
249
  mainsequence code-repository resources list --filter resource_type=fastapi
196
- mainsequence code-repository resources create_fastapi
197
250
  ```
198
251
 
199
252
  Verify that:
200
253
 
201
254
  - code-repository sync used the intended Git branch
202
- - the selected image contains the exact tested commit
203
- - resource discovery found the expected FastAPI path at that commit
204
- - the selected resource UID and image UID refer to the same commit
205
- - the created release kind is `fastapi`
255
+ - the workflow declaration identifies the tested FastAPI source path
256
+ - resource discovery found that path at the exact deployed commit
257
+ - Django resolved and built the exact image for the workflow event
258
+ - the resulting release kind is `fastapi`
259
+ - any declared `public_ingress` pair matches a mounted FastAPI handler
206
260
  - compute and spot settings are intentional
207
261
 
208
- Use `--automatic-deployment` only after the route paths, resource path, and
209
- frontend contracts are stable and the release should follow future repository
210
- syncs. Otherwise keep the release pinned and create deliberate replacements.
262
+ Enable automatic deployment in the repository workflow when the route paths,
263
+ resource path, and frontend contracts are stable enough for future repository
264
+ events to promote exact images.
211
265
 
212
266
  ### 6. Verify the deployed API
213
267
 
214
- Request runtime access for the deployed FastAPI `ResourceRelease` through
215
- Django and wait for Django's ready result. Use the returned access bundle for
216
- the deployed checks:
268
+ Request runtime access for protected routes on the deployed FastAPI
269
+ `ResourceRelease` through Django and wait for Django's ready result. Use the
270
+ returned access bundle for authenticated checks. For declared public routes,
271
+ use the provider URI without a Main Sequence Bearer token:
217
272
 
218
- 1. verify authentication behavior
273
+ 1. verify protected-route authentication and, when configured, exact
274
+ unauthenticated public-ingress method/path behavior
219
275
  2. execute representative contract-bearing requests
220
276
  3. validate returned JSON against the same repository-pinned schemas
221
277
  4. exercise the consuming Command Center frontend flow
@@ -235,6 +291,9 @@ Report:
235
291
  - Git commit, code repository image UID, code repository resource UID, and release identity
236
292
  - deployed contract validation and Command Center frontend result
237
293
  - whether automatic deployment is enabled and why
294
+ - for public provider routes, the declared method/path pairs, observed
295
+ `effective_public_ingress`, backend-returned provider URI, and unauthenticated
296
+ positive and negative request results
238
297
 
239
298
  The Command Center-facing release is complete only when the frontend consumes
240
299
  the deployed contract-bearing responses and they pass the contracts from the
@@ -21,17 +21,11 @@ This skill is for:
21
21
 
22
22
  ## This Skill Can Do
23
23
 
24
- - create or review manual jobs
25
- - create or review scheduled jobs
26
- - author backend-managed declarations under `.mainsequence/workflows/`
27
- - validate workflow files through the CodeRepositoryBranch workflow endpoints
28
- - create or select code repository images
29
- - bind every job to one exact code repository image
30
- - configure standalone Job automatic deployment as future exact-image promotion
31
- - inspect job runs and logs
32
- - reason about code repository resources and resource releases
33
- - decide whether a `ResourceRelease` should opt into `automatic_deployment`
34
- - inspect automatic deployment run state for release rotations
24
+ - author and validate Job, FastAPI, and Static Site workflow declarations
25
+ - inspect exact CodeRepository images, Jobs, ResourceReleases, and deployment runs
26
+ - run an existing Job manually and inspect logs
27
+ - update supported properties on an existing Job or release
28
+ - reason about automatic deployment and repository-event image promotion
35
29
  - review Artifact-based workflows in operational pipelines
36
30
 
37
31
  ## This Skill Must Not Claim
@@ -68,41 +62,19 @@ changing the operational workflow.
68
62
 
69
63
  ## Inputs This Skill Needs
70
64
 
71
- Before changing orchestration or release behavior, collect or infer:
72
-
73
- - the execution target:
74
- - `execution_path`
75
- - app entrypoint
76
- - whether the job is:
77
- - manual
78
- - interval
79
- - crontab
80
- - one-off
81
- - the image strategy:
82
- - existing image
83
- - new image
84
- - whether the workflow is:
85
- - direct CLI/client job creation
86
- - backend-managed code-repository workflow declarations
87
- - whether a `ResourceRelease` should be manually pinned or opted into repository-sync automatic deployment
88
- - whether Artifact inputs or outputs are part of the run
89
- - who owns the exact initial image: the caller for manual pinning or the
90
- backend for automatic deployment
91
- - whether future qualifying immutable repository events may promote a standalone Job
92
-
93
- If the execution target or image strategy is unclear, stop before scheduling anything.
65
+ Identify the repository source path or Job execution path, the product kind,
66
+ schedule and compute intent, and whether future qualifying repository events
67
+ should promote the target. For an existing target, obtain its public UID before
68
+ running or updating it. The repository workflow is the creation input; callers
69
+ do not select image, resource, Job, or release UIDs for creation.
94
70
 
95
71
  ## Required Decisions
96
72
 
97
- For every non-trivial orchestration task, decide:
98
-
99
- 1. Is this a one-off/manual workflow or a repository-managed recurring workflow?
100
- 2. Should the jobs live in a `.mainsequence/workflows/*.yaml` declaration?
101
- 3. Is the Job manually pinned to a caller-selected exact ready image, or does
102
- automatic deployment make the backend derive it from the synchronized commit?
103
- 4. Does the workflow depend on Artifacts?
104
- 5. Is the task actually a release/resource problem instead of only a job problem?
105
- 6. For a `ResourceRelease`, should repository sync be allowed to rotate the release automatically through `automatic_deployment`?
73
+ 1. Which repository workflow declaration owns the target?
74
+ 2. Is the Job manual, interval, crontab, or one-off?
75
+ 3. Should future exact repository events promote its image automatically?
76
+ 4. Are Artifacts inputs or outputs of the run?
77
+ 5. Which existing Job or release needs observation or an explicit operation?
106
78
 
107
79
  ## Build Rules
108
80
 
@@ -129,38 +101,11 @@ Do not hide important recurring schedules in ad hoc shell history or one-off man
129
101
 
130
102
  ### 2. Every Job requires one exact image
131
103
 
132
- Every persisted direct Job has one exact code repository image, but the creation mode
133
- determines who supplies it.
134
-
135
- Remember:
136
-
137
- - images are built from pushed commits
138
- - if a commit is not on the remote, it cannot be used for an image
139
- - there is no dynamic, blank-image, branch-tip, or `latest` Job mode
140
- - a manual Job requires the caller to select `related_image_uid`
141
- - an automatic Job forbids caller image selection; the backend derives the
142
- exact initial image from the CodeRepositoryBranch's persisted synchronized commit
143
-
144
- When standalone Job automatic deployment is enabled during creation, the
145
- backend prepares the exact initial image and later qualifying immutable
146
- repository events may atomically promote another exact image. On an existing
147
- Job, enabling or disabling it retains the current exact image. The backend owns
148
- repository-event truth, policy evaluation, image preparation, and promotion;
149
- CodeRepository code and the SDK must not choose a Job's deployment branch or image.
150
- This deployment-policy rule does not replace ADR-0037 runtime source discovery:
151
- code executing inside the resulting code repository image still resolves and validates
152
- its attached Git branch and exact commit.
153
-
154
- For direct creation use:
155
-
156
- - `--automatic-deployment` to permit future exact-image promotion
157
- - `--no-automatic-deployment` to keep future repository events from changing
158
- the Job image
159
- - `--automatic-redeployment-tag-regex` to require a full matching immutable
160
- tag; omit the regex for every otherwise-eligible exact event
161
-
162
- Use `--related-image-uid` only for manual pinning. Omit it with
163
- `--automatic-deployment`; passing both is invalid.
104
+ Django derives the initial image from the exact repository event when it
105
+ applies a `kind: job` workflow declaration. A later qualifying event may
106
+ promote another exact image under the Job's automatic deployment policy.
107
+ There is no dynamic, blank-image, branch-tip, or `latest` execution mode.
108
+ A caller does not create an image or Job by selecting a stored image UID.
164
109
 
165
110
  ### 3. Jobs must be verifiable after creation
166
111
 
@@ -201,7 +146,7 @@ Current support matrix:
201
146
  | `Job.run_job(command_args=[...])` | Supported for that manual run |
202
147
  | `mainsequence code-repository jobs run ... --arg/-- ...` | Supported for that manual run |
203
148
  | `Job.scheduled_command_args` | Persisted list copied into future scheduler-created runs |
204
- | `mainsequence code-repository jobs create/update --scheduled-arg ...` | Creates or replaces the persisted scheduled list |
149
+ | `mainsequence code-repository jobs update --scheduled-arg ...` | Replaces the persisted list on an existing Job |
205
150
  | `.mainsequence/workflows/*.yaml` Job declaration | Supports `scheduled_command_args` as an ordered `list[str]` |
206
151
 
207
152
  Keep `scheduled_command_args` separate from manual `command_args`. Retrieve the
@@ -298,36 +243,27 @@ Enable `automatic_deployment` only when:
298
243
 
299
244
  Keep `automatic_deployment` disabled when:
300
245
 
301
- - the release must stay pinned to a manually selected image or resource version
246
+ - the release should not promote on future repository events
302
247
  - each release rotation needs human approval
303
248
  - the resource path or entrypoint is still moving
304
249
  - API or widget contracts are not stable enough for automatic rotation
305
250
  - the current branch/CodeRepository sync target is not the intended deployment source
306
251
 
307
- Create opted-in releases with the CLI flags that exist:
308
-
309
- - `mainsequence code-repository resources create_fastapi --automatic-deployment`
310
- - use `--no-automatic-deployment` when the decision is explicitly to keep the release pinned/manual
311
-
312
- The SDK surface also accepts:
313
-
314
- - `CodeRepositoryResource.create_fastapi(..., automatic_deployment=True)`
315
- - `ResourceRelease.create(..., automatic_deployment=True)`
316
- - `ResourceRelease.deploy_current_version()` for an SDK-triggered manual deployment run; it returns `DeploymentRun`
317
- - `DeploymentRun.filter(target_type="resource_release", target_uid=release.uid)` to inspect runs for one release
252
+ Declare opted-in releases in the repository workflow and validate the file
253
+ against the backend template. Repository events create deployment runs.
254
+ `DeploymentRun.filter(target_type="resource_release", target_uid=release.uid)`
255
+ inspects runs for an existing release.
318
256
 
319
257
  Every release also exposes its immutable revision lifecycle:
320
258
 
321
259
  - `desired_revision` is the public UID of the accepted revision being materialized
322
260
  - `active_revision` is the public UID of the ready revision currently serving behind the stable release URL
323
261
  - the two UIDs may differ while a deployment is running or after a deployment fails
324
- - `revision_retention_count` is the positive release-owned retention setting; omission on create uses the backend default
325
- - configure retention with `ResourceRelease.create(..., revision_retention_count=3)` or `release.patch(revision_retention_count=5)`
262
+ - `revision_retention_count` is the positive release-owned retention setting; omission in the workflow uses the backend default
263
+ - configure retention in the workflow or update an existing release with `release.patch(revision_retention_count=5)`
326
264
 
327
265
  Treat `active_revision` and `desired_revision` as read-only public identities. Do not substitute provider revision names, deployment names, or internal database IDs.
328
266
 
329
- Do not claim there is a CLI command for `deploy_current_version` unless the local CLI actually exposes one. In this SDK, the manual detail action is available through the client model.
330
-
331
267
  Inspect the unified run's `state`, `phase`, `outcome`, `steps`, `logs`, and `error` fields. Do not use legacy resource-release deployment status fields or filters.
332
268
  Detail responses also expose `builder_image` and `builder_runtime`; these are empty strings when the run has no static-site builder metadata.
333
269
 
@@ -336,11 +272,9 @@ Detail responses also expose `builder_image` and `builder_runtime`; these are em
336
272
  When reviewing an orchestration task, look for:
337
273
 
338
274
  - schedules that should have been version-controlled
339
- - direct job creation where a batch file should exist
340
- - missing or wrong `related_image_uid`
341
- - jobs tied to moving repository state instead of a pinned image
342
- - manual Job creation that omits an exact ready image
343
- - automatic Job creation that supplies a caller-selected image
275
+ - a missing repository workflow declaration for a new Job
276
+ - a workflow with a caller-selected image or generated platform UID
277
+ - jobs tied to moving repository state instead of an exact image
344
278
  - client code that interprets automatic deployment as a branch-tip or `latest` selector
345
279
  - no run/log verification after creation
346
280
  - unsafe use of `--strict`
@@ -360,9 +294,9 @@ Do not claim success until you have checked:
360
294
  - interval
361
295
  - crontab
362
296
  - one-off
363
- - manual image selection or backend-owned automatic image preparation is intentional
297
+ - the exact repository event and backend-owned image preparation are intentional
364
298
  - standalone Job automatic deployment and tag policy are intentionally enabled or disabled
365
- - the job exists after direct creation or repository workflow application
299
+ - the Job exists after repository workflow application
366
300
  - runs and logs were inspected when execution success matters
367
301
  - resources and releases were verified when deployment success matters
368
302
  - `automatic_deployment` is intentionally enabled or disabled on each release
@@ -386,7 +320,7 @@ If the workflow uses Artifacts, also check:
386
320
  - the execution target is unclear
387
321
  - the image strategy is unclear but reproducibility matters
388
322
  - the backend rejects the workflow version, resource kind, or requested field
389
- - a manually pinned Job has no exact ready initial image
323
+ - a Job workflow cannot resolve an exact source image
390
324
  - an automatically deployed Job has no persisted synchronized CodeRepositoryBranch commit
391
325
  - the workflow depends on local file paths that should be platform Artifacts
392
326
  - automatic deployment is requested but the deployment source branch/current synced CodeRepository version is unclear