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.
- {mainsequence-8.1.21.dev20/mainsequence.egg-info → mainsequence-8.1.22}/PKG-INFO +1 -1
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +81 -22
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +34 -100
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/api.py +0 -368
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/cli.py +0 -1227
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/base.py +5 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/models_foundry.py +3 -71
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/models_helpers.py +4 -544
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22/mainsequence.egg-info}/PKG-INFO +1 -1
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/pyproject.toml +1 -1
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_cli.py +9 -1024
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_code_repository_batch_jobs_from_file.py +1 -18
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_filter_normalization.py +23 -309
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_tolerant_value_sets.py +1 -26
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/LICENSE +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/MANIFEST.in +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/README.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/data_publishing/time_index_table_updates/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/maintenance/code_repository_maintenance/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/agent_scaffold/skills/sdk_code_repository_execution/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/__main__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/bootstrap.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/code_repository_status.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/config.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/migrations.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/cli/ui.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/agent_runtime_models.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/client.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/compute_validation.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/dtype_codec.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/github_issues.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/metatables/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/metatables/core.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/models_user.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/observability.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/utils.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/client/value_sets.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/code_repository_context.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/code_repository_skills.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/defaults.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/logconf.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/__main__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/future_registry.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/hashing.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/alembic.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/env.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/provider.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/registry.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/schema_names.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_refs.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/configuration.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/dependencies.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/managers.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/namespacing.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/runner.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/updaters.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/meta_tables/time_index_table_updates/utils.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/repository_identity_security.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/runtime_flags.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence/scaffold_skills.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence.egg-info/SOURCES.txt +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence.egg-info/requires.txt +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/setup.cfg +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/fixtures/time_index_table_update_hash_v2_golden.json +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_auth_precedence.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_canonical_api_route_contract.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_cli_migrations.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_client.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_code_repository_branch_contract.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_code_repository_documentation_contract.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_code_repository_runtime_context.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_code_repository_skills.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_dependency_extras.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_dev_release_version.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_duckdb_interface_dimensions.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_environment_resource_context.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_environment_response_contracts.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_github_issues_client.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_instrumentation.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_local_ops.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_logconf.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_meta_table_migrations.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_meta_tables_client_models.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_notification_uid_contract.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_observability_client.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_pod_project_resolution.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_scaffold_skills.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_schema_names.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_secret_client_model.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_source_table_configuration.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_sqlite_interface_dimensions.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_ssh_utils.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_time_index_table_access_dimension_audit.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_time_index_table_dimension_queries.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_time_index_table_update_configuration.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_time_index_table_update_configuration_client.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_time_index_table_update_flow.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_time_index_table_update_hard_cut.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_tolerant_response_reading.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_update_runner_uid_runtime.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_update_statistics.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22}/tests/test_update_uid_guards.py +0 -0
|
@@ -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
|
|
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
|
|
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
|
-
|
|
115
|
-
authentication headers, or resolve the request user itself. Consume
|
|
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
|
-
|
|
123
|
-
release creator, deployment owner, runtime workload
|
|
124
|
-
target. Pass request state explicitly to shared services;
|
|
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
|
-
|
|
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
|
|
203
|
-
- resource discovery found
|
|
204
|
-
-
|
|
205
|
-
- the
|
|
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
|
-
|
|
209
|
-
frontend contracts are stable
|
|
210
|
-
|
|
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
|
|
215
|
-
Django and wait for Django's ready result. Use the
|
|
216
|
-
|
|
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
|
|
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
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
|
325
|
-
- configure retention
|
|
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
|
-
-
|
|
340
|
-
-
|
|
341
|
-
- jobs tied to moving repository state instead of
|
|
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
|
-
-
|
|
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
|
|
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
|
|
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
|