mainsequence 9.0.30.dev73__py3-none-any.whl → 9.0.30.dev74__py3-none-any.whl

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.
@@ -148,7 +148,7 @@ person, read `User.get_by_uid(uid)`: a workload identity has `identity_type`
148
148
  endpoint's application policy using the verified user UID.
149
149
 
150
150
  To list the people, Teams and workloads the caller can see, for example to
151
- offer sharing candidates, read inside `reads_as_caller()` from
151
+ offer access candidates, read inside `reads_as_caller()` from
152
152
  `mainsequence.server.fastapi`: `User.filter`, `User.get_by_uid`, `Team.filter`
153
153
  and `Team.get_by_uid` then answer with the caller's visibility, and workload
154
154
  rows carry `managed_by_caller`. Outside a signed HTTP request it raises
@@ -250,8 +250,8 @@ def acting_identity() -> RequestUserIdentity:
250
250
  caller on any other. Never combine the caller's grants with the person's,
251
251
  and never fall back to the caller's rights when the person may not.
252
252
  - Before a write, check the exact object and action; the example's
253
- team-membership check is not a general edit, run, share or delete grant. The
254
- getter verifies identity, not operation permission.
253
+ team-membership check is not a general grant to edit, run, delete or give
254
+ access. The getter verifies identity, not operation permission.
255
255
  - Never parse the assertion, headers or MCP `_meta`, never read a person's UID
256
256
  from the request body, a header or a query parameter, and never let a caller
257
257
  name whom it acts for. Anyone can write a UID there. Only the signed
@@ -1,28 +1,28 @@
1
1
  ---
2
2
  name: mainsequence-access-control-and-sharing
3
- description: Use this skill when the task is about RBAC, resource sharing, or access verification in a Main Sequence CodeRepository. This skill owns organization and team access concepts, the policies of each shareable resource, choosing the correct shareable resource boundary, access checks across CodeRepositories, constants, secrets, buckets, artifacts, Agents, releases and Jobs, and whether an application uses its own grants or acts for its requester (`acts_for_requester`). It does not own job scheduling, domain-package data behavior, or API route design.
3
+ description: Use this skill when the task is about RBAC, giving people, workloads or teams access to a resource, or access verification in a Main Sequence CodeRepository. This skill owns organization and team access concepts, the policies of each shareable resource, choosing the correct resource boundary, access checks across CodeRepositories, constants, secrets, buckets, artifacts, Agents, releases and Jobs, and whether an application uses its own grants or acts for its requester (`acts_for_requester`). It does not own job scheduling, domain-package data behavior, or API route design.
4
4
  ---
5
5
 
6
6
  # Main Sequence Access Control And Sharing
7
7
 
8
8
  ## Overview
9
9
 
10
- Use this skill when the task is about who can view, edit, maintain, or administer a resource in a Main Sequence CodeRepository.
10
+ Use this skill when the task is about who can see, use, change, maintain, or administer a resource in a Main Sequence CodeRepository.
11
11
 
12
12
  This skill is for:
13
13
 
14
14
  - RBAC reasoning
15
15
  - organization, user, role, and team access concepts
16
- - direct sharing vs team sharing
16
+ - direct access vs team access
17
17
  - choosing the policy a person, a workload or a team needs
18
- - deciding which resource is the real sharing boundary
18
+ - deciding which resource is the real access boundary
19
19
  - choosing between `Constant` and `Secret`
20
- - access verification for shared resources
20
+ - verifying who has access to a resource
21
21
 
22
22
  ## This Skill Can Do
23
23
 
24
24
  - explain the Main Sequence access model in operational terms
25
- - decide whether a resource should be shared directly to a user or to a team
25
+ - decide whether a policy should go directly to a user or to a team
26
26
  - decide which policy a user, a workload or a team needs
27
27
  - identify the correct shareable object boundary:
28
28
  - `CodeRepository`
@@ -36,10 +36,10 @@ This skill is for:
36
36
  - `ResourceRelease`
37
37
  - `Job`
38
38
  - choose whether configuration belongs in a `Constant` or a `Secret`
39
- - review CLI sharing flows for existing resources
39
+ - review CLI access commands for existing resources
40
40
  - manage a team's members and decide who controls the team, through the
41
41
  team's policies
42
- - verify access assumptions before claiming a workflow is shareable
42
+ - verify access assumptions before claiming other people can use a workflow
43
43
  - decide whether an application uses its own grants or acts for its
44
44
  requester, and explain what acting for the requester allows
45
45
 
@@ -78,15 +78,15 @@ This skill only reasons about access to deployed resources such as `ResourceRele
78
78
  and <https://mainsequence-sdk.github.io/mainsequence-sdk/knowledge/infrastructure/artifacts/>
79
79
  for releases, Jobs, buckets and Artifacts
80
80
 
81
- The pages above are the authoritative reference for access control and sharing.
81
+ The pages above are the authoritative reference for access control.
82
82
  If the task is specifically about a resource type, also read that resource's own
83
83
  page from the documentation root at <https://mainsequence-sdk.github.io/mainsequence-sdk/>.
84
84
 
85
85
  ## Inputs This Skill Needs
86
86
 
87
- Before changing access or advising on sharing, collect or infer:
87
+ Before changing access or advising on it, collect or infer:
88
88
 
89
- - the exact resource type being shared
89
+ - the exact resource type that access is given on
90
90
  - whether the actor is:
91
91
  - a user
92
92
  - a team
@@ -116,7 +116,7 @@ Before changing access or advising on sharing, collect or infer:
116
116
  - whether the resource contains sensitive configuration
117
117
  - whether the task is about the resource itself or about the workflow that uses it
118
118
 
119
- If the resource boundary or intended access level is unclear, stop before changing permissions.
119
+ If the resource boundary or the intended policy is unclear, stop before changing access.
120
120
 
121
121
  ## Required Decisions
122
122
 
@@ -138,15 +138,16 @@ For every non-trivial access task, decide:
138
138
 
139
139
  ## Build Rules
140
140
 
141
- ### 1. Share the real resource boundary
141
+ ### 1. Give access on the real resource boundary
142
142
 
143
- Do not speak loosely about sharing "the code" when the operational boundary is a platform object.
143
+ Do not speak loosely about giving access to "the code" when the operational boundary is a platform object.
144
144
 
145
145
  Examples:
146
146
 
147
- - sharing a deployed experience usually means a policy on the
147
+ - giving access to a deployed experience usually means a policy on the
148
148
  `ResourceRelease`, or on the `Agent` when the release backs one
149
- - sharing runtime configuration means sharing the `Constant` or `Secret`
149
+ - giving access to runtime configuration means a policy on the `Constant` or
150
+ `Secret`
150
151
 
151
152
  ### 2. Consumers get the narrowest policy, maintainers get `editor`
152
153
 
@@ -157,8 +158,7 @@ Use the simplest rule unless the task requires something more specific:
157
158
  - `editor` for people who need to maintain or update
158
159
  - `owner` only for the people who decide who has access
159
160
 
160
- Do not grant `editor` when a reading or using policy is enough. No resource
161
- uses view and edit sharing any more.
161
+ Do not grant `editor` when a reading or using policy is enough.
162
162
 
163
163
  A `Constant` is decided by its policies:
164
164
 
@@ -169,8 +169,8 @@ A `Constant` is decided by its policies:
169
169
  The person or workload that creates a constant holds `owner`. Give `reader` to
170
170
  consumers and `editor` to maintainers, with the access methods on `Constant`
171
171
  (`get_access()`, `attach_policy()`, `detach_policy()`, `explain_access()`) or
172
- `mainsequence constants access list|grant|revoke|explain`. A constant has no
173
- `add_to_view()` or `add_to_edit()`, and its access methods need no Environment.
172
+ `mainsequence constants access list|grant|revoke|explain`. Its access methods
173
+ need no Environment.
174
174
 
175
175
  A `Secret` is decided by its policies too:
176
176
 
@@ -186,15 +186,14 @@ The person or workload that creates a secret holds `owner`. Give
186
186
  use the secret but must never know it. A workload holding only `reader` cannot
187
187
  read the value: `Secret.get()` raises `PermissionDeniedError` with
188
188
  `required_action` `secrets.read_value`. Use the access methods on `Secret` or
189
- `mainsequence secrets access list|grant|revoke|explain`; a secret has no
190
- `add_to_view()` or `add_to_edit()`. A repository workflow file's `access` entry
191
- for a secret names the policy it gives (`policy: reader`, `value_reader`,
192
- `editor` or `owner`). A secret the platform manages, such as a hosted database
193
- password, cannot get a new value or be deleted.
189
+ `mainsequence secrets access list|grant|revoke|explain`. A repository workflow
190
+ file's `access` entry for a secret names the policy it gives (`policy: reader`,
191
+ `value_reader`, `editor` or `owner`). A secret the platform manages, such as a
192
+ hosted database password, cannot get a new value or be deleted.
194
193
 
195
194
  A `Bucket` is decided by its policies too:
196
195
 
197
- - `reader` browses its folders and the Artifacts in it shared with the person;
196
+ - `reader` browses its folders and the Artifacts in it that the person can see;
198
197
  - `contributor` also uploads Artifacts and creates folders;
199
198
  - `editor` also renames the bucket, renames and deletes folders, deletes the
200
199
  bucket with every Artifact in it and sees who has access;
@@ -205,10 +204,9 @@ Artifact upload creates it by name. Give `contributor` to the people and the
205
204
  workloads that upload into a bucket, and `editor` to maintainers. Uploading
206
205
  into an existing bucket without `contributor` raises `PermissionDeniedError`
207
206
  with `required_action` `buckets.add_artifact`. Use the access methods on
208
- `Bucket`; a bucket has no `add_to_view()` or `add_to_edit()`, and the CLI has
209
- no bucket commands. A repository workflow file's `access` entry for a bucket
210
- names the policy it gives (`policy: reader`, `contributor`, `editor` or
211
- `owner`).
207
+ `Bucket`; the CLI has no bucket commands. A repository workflow file's `access`
208
+ entry for a bucket names the policy it gives (`policy: reader`, `contributor`,
209
+ `editor` or `owner`).
212
210
 
213
211
  A `CodeRepository`, its `CodeRepositoryBranch` objects and an
214
212
  `OrganizationProject` are decided by their policies too, each with `reader`,
@@ -229,8 +227,8 @@ A `CodeRepository`, its `CodeRepositoryBranch` objects and an
229
227
  A repository's creator and a Project's creator hold `owner`; a branch's
230
228
  creator holds nothing for being its creator. Repository and Project policies
231
229
  pass down to the branches: `reader` gives branch `reader`, and `editor` and
232
- `owner` give branch `editor`, so share the repository or the Project when
233
- every branch should follow. Using a repository or a branch needs the
230
+ `owner` give branch `editor`, so give access on the repository or the Project
231
+ when every branch should follow. Using a repository or a branch needs the
234
232
  platform's `user` product role: without it every route, the access methods
235
233
  included, raises `PermissionDeniedError` with `code` `missing_product_role`,
236
234
  also through a Team, and no policy gives it. Use the access methods on
@@ -326,11 +324,11 @@ repository workflows and holds no policy on them. The access methods of all
326
324
  four take no Environment; with a workload's runtime credentials they reach
327
325
  only the objects of that workload's Environment.
328
326
 
329
- ### 3. Team sharing is for repeated access patterns
327
+ ### 3. Team access is for repeated access patterns
330
328
 
331
- Prefer team sharing when the same access needs to be reused across several people or resources.
329
+ Prefer giving access to a team when the same access needs to be reused across several people or resources.
332
330
 
333
- Prefer direct sharing when:
331
+ Prefer giving access directly when:
334
332
 
335
333
  - the access is one-off
336
334
  - the access is personal
@@ -342,11 +340,10 @@ Do not claim that a user can manage a team just because they inherit access thro
342
340
 
343
341
  Keep these separate:
344
342
 
345
- - inherited access to shared resources
343
+ - access inherited through the team's policies
346
344
  - administration of the team itself
347
345
 
348
- Membership is who is in the team. Control is the policies on the team, not view
349
- and edit sharing:
346
+ Membership is who is in the team. Control is the policies on the team:
350
347
 
351
348
  - `viewer` sees the team and its members;
352
349
  - `membership_manager` adds and removes members;
@@ -357,16 +354,16 @@ and edit sharing:
357
354
  Any person can create a team and becomes its owner and first member. Use
358
355
  `Team.add_member()`, `remove_member()`, `leave()` and the access methods
359
356
  (`get_access()`, `attach_policy()`, `detach_policy()`, `explain_access()`), or
360
- `mainsequence organization teams members ...`, `leave` and `access ...`. A
361
- team has no `add_to_view()` or `add_to_edit()`. Before saying who can change a
362
- team, read it with `team.get_access()` or `explain_access()`.
357
+ `mainsequence organization teams members ...`, `leave` and `access ...`. Before
358
+ saying who can change a team, read it with `team.get_access()` or
359
+ `explain_access()`.
363
360
 
364
361
  Working in an Organization Environment is a policy too: `member` works in it
365
362
  and creates Projects, Buckets, Constants, Secrets, model providers and
366
363
  repositories there; `observer` works in it without creating anything. Only
367
364
  Organization admins attach them, to people and Teams, with the access methods
368
- on `OrganizationEnvironment`. Admission never shows objects that are not shared
369
- with the person.
365
+ on `OrganizationEnvironment`. Admission never shows objects the person has no
366
+ access to.
370
367
 
371
368
  An application that checks whether its caller or requester belongs to a team
372
369
  uses `in_teams()`; the identity carries no team list. See
@@ -427,7 +424,7 @@ output is interpreted through public UID fields.
427
424
 
428
425
  ### 8. Access assumptions must be verified
429
426
 
430
- If the task claims a resource is shareable, readable, or maintainable by another actor, verify that path explicitly with the relevant CLI or client workflow.
427
+ If the task claims another actor can see, use, or maintain a resource, verify that path explicitly with the relevant CLI or client workflow.
431
428
 
432
429
  Do not claim access based only on naming, role titles, or intuition.
433
430
 
@@ -476,9 +473,9 @@ whose own request it is serving. The platform setting is `acts_for_requester`.
476
473
  who pushed it is an Organization admin. Otherwise that resource fails
477
474
  before it deploys.
478
475
  - An application that should act only for people, for example a data analyst
479
- Agent, holds no grants of its own. Do not share data with its workload User
480
- to make it work: everyone who can use the application could then reach that
481
- data through it.
476
+ Agent, holds no grants of its own. Do not give its workload User policies on
477
+ data to make it work: everyone who can use the application could then reach
478
+ that data through it.
482
479
 
483
480
  ### What the requester's access covers
484
481
 
@@ -487,7 +484,7 @@ no delegation, the caller's own ordinary permissions; with a valid delegation,
487
484
  the person's ordinary permissions, including administrative ones; an invalid or
488
485
  expired delegation is rejected, never switched to another identity.
489
486
 
490
- - The reads, creates, updates, runs, sharing changes and deletes the person
487
+ - The reads, creates, updates, runs, access changes and deletes the person
491
488
  may make through supported operations.
492
489
  - Check the person's permission for the exact object and operation on every
493
490
  call. A read grant or team membership alone does not authorize a write.
@@ -532,16 +529,17 @@ read-only or claim that it cannot change, share or delete anything.
532
529
 
533
530
  Explain the risk alongside the statement: a model-driven Agent can be steered
534
531
  by prompt injection. Its reads and writes can reach as far as the person's
535
- ordinary permissions allow, administrative ones included, such as sharing and
536
- deleting through supported operations, for at most 24 hours after the original
537
- request. Only Organization admins decide which Agents may receive this
538
- authority; the application's per-operation permission checks remain necessary.
532
+ ordinary permissions allow, administrative ones included, such as changing who
533
+ has access and deleting through supported operations, for at most 24 hours
534
+ after the original request. Only Organization admins decide which Agents may
535
+ receive this authority; the application's per-operation permission checks
536
+ remain necessary.
539
537
 
540
538
  ## Review Rules
541
539
 
542
540
  When reviewing an access-control task, look for:
543
541
 
544
- - sharing the wrong resource boundary
542
+ - giving access on the wrong resource boundary
545
543
  - granting `editor` or `owner` when a reading or using policy is sufficient
546
544
  - a policy on a release that backs an Agent instead of on the Agent
547
545
  - using direct user grants where a team should be used
@@ -585,7 +583,7 @@ Do not claim success until you have checked:
585
583
  - the task is using `Constant` vs `Secret` correctly
586
584
  - any `Constant` or `Secret` creation path first resolved existence by name when idempotency matters
587
585
  - the access claim was verified against the actual resource path
588
- - the task did not confuse sharing policy with orchestration or producer logic
586
+ - the task did not confuse access policy with orchestration or producer logic
589
587
  - an application that acts for its requester takes the person only from the
590
588
  platform, and its own grants are intentional
591
589
  - requester-bound writes enforce the person's permission for the operation,
@@ -597,7 +595,7 @@ Do not claim success until you have checked:
597
595
  - the actor should probably be a team, but team structure is unknown
598
596
  - the task mixes access policy with job scheduling or release mechanics
599
597
  - the task asks for sensitive data to be stored in a `Constant`
600
- - the task assumes cross-organization sharing without explicit documentation
598
+ - the task assumes cross-organization access without explicit documentation
601
599
  - the request requires a policy decision the user has not made
602
600
  - the task needs `acts_for_requester` and no Organization admin has decided to
603
601
  enable it
@@ -34,7 +34,7 @@ This skill must not claim ownership of:
34
34
 
35
35
  - domain-package data production and schema semantics
36
36
  - Command Center FastAPI wire contracts
37
- - RBAC or sharing policy
37
+ - RBAC or access policies
38
38
  - application UI implementation details
39
39
 
40
40
  ## Route Adjacent Work
@@ -43,7 +43,7 @@ This skill must not claim ownership of:
43
43
  package skills and documentation
44
44
  - Command Center FastAPI provider implementation and contract validation:
45
45
  `.agents/skills/mainsequence/application_surfaces/api_surfaces/SKILL.md`
46
- - RBAC and sharing:
46
+ - RBAC and access policies:
47
47
  `.agents/skills/mainsequence/platform_operations/access_control_and_sharing/SKILL.md`
48
48
 
49
49
  ## Read First
@@ -40,7 +40,7 @@ CodeRepository-to-Agent setup and other platform capabilities.
40
40
  `.agents/skills/mainsequence/application_surfaces/api_surfaces/SKILL.md`
41
41
  - Jobs, schedules, images, resources, releases, and Artifacts:
42
42
  `.agents/skills/mainsequence/platform_operations/orchestration_and_releases/SKILL.md`
43
- - RBAC, sharing, constants, secrets, and acting for a requester:
43
+ - RBAC, access policies, constants, secrets, and acting for a requester:
44
44
  `.agents/skills/mainsequence/platform_operations/access_control_and_sharing/SKILL.md`
45
45
  - Recorded model calls, structured extraction, provider options, history, and replay:
46
46
  `.agents/skills/mainsequence/mainsequence-inference/SKILL.md`
mainsequence/cli/cli.py CHANGED
@@ -2526,7 +2526,7 @@ def _format_team_member(member: dict[str, object]) -> list[tuple[str, str]]:
2526
2526
  ("Kind", str(member.get("member_kind") or "-")),
2527
2527
  ("Username", str(member.get("username") or "-")),
2528
2528
  ("Email", str(member.get("email") or "-")),
2529
- ("Name", _render_shareable_user_name(member)),
2529
+ ("Name", _render_user_name(member)),
2530
2530
  ]
2531
2531
 
2532
2532
 
@@ -2591,7 +2591,7 @@ def _organization_team_members_list_impl(*, team_uid: str, timeout: int | None)
2591
2591
  str(member.get("uid") or "-"),
2592
2592
  str(member.get("member_kind") or "-"),
2593
2593
  str(member.get("email") or "-"),
2594
- _render_shareable_user_name(member),
2594
+ _render_user_name(member),
2595
2595
  ]
2596
2596
  for member in members
2597
2597
  ]
@@ -3488,7 +3488,7 @@ def _format_team_preview(team: dict[str, object]) -> list[tuple[str, str]]:
3488
3488
  ]
3489
3489
 
3490
3490
 
3491
- def _render_shareable_user_name(user: dict[str, object]) -> str:
3491
+ def _render_user_name(user: dict[str, object]) -> str:
3492
3492
  first_name = str(user.get("first_name") or "").strip()
3493
3493
  last_name = str(user.get("last_name") or "").strip()
3494
3494
  full_name = " ".join(part for part in (first_name, last_name) if part)
@@ -916,243 +916,6 @@ class DetailActionObjectMixin:
916
916
  return response.json()
917
917
 
918
918
 
919
- class PermissionManagedObjectMixin(DetailActionObjectMixin):
920
- PERMISSION_ACTION_PATHS: ClassVar[dict[str, str]] = {
921
- "add_to_view": "add-to-view",
922
- "add_to_edit": "add-to-edit",
923
- "add_team_to_view": "add-team-to-view",
924
- "add_team_to_edit": "add-team-to-edit",
925
- "remove_from_edit": "remove-from-edit",
926
- "remove_from_view": "remove-from-view",
927
- "remove_team_from_edit": "remove-team-from-edit",
928
- "remove_team_from_view": "remove-team-from-view",
929
- "can_view": "can-view",
930
- "can_edit": "can-edit",
931
- "users_can_view": "can-view",
932
- "users_can_edit": "can-edit",
933
- }
934
- SHARING_ACTION_PATHS: ClassVar[dict[str, str]] = PERMISSION_ACTION_PATHS
935
-
936
- @classmethod
937
- def _coerce_principal_uid(cls, value: Any, *, field_name: str) -> str:
938
- normalized = cls._coerce_filter_uid(value, field_name=field_name)
939
- try:
940
- return str(UUID(normalized))
941
- except ValueError as exc:
942
- raise ValueError(f"{field_name} must be a valid UUID.") from exc
943
-
944
- def _post_sharing_action(
945
- self,
946
- action_name: str,
947
- *,
948
- subject_key: str,
949
- subject_uid: Any,
950
- timeout: int | float | tuple[float, float] | None = None,
951
- ) -> dict[str, Any]:
952
- normalized_subject_uid = type(self)._coerce_principal_uid(
953
- subject_uid,
954
- field_name=subject_key,
955
- )
956
- payload = {"json": {subject_key: normalized_subject_uid}}
957
- data = self._request_detail_action(
958
- r_type="POST",
959
- action_name=action_name,
960
- payload=payload,
961
- timeout=timeout,
962
- expected_statuses=(200, 201, 202),
963
- empty_response={},
964
- )
965
- if not isinstance(data, dict):
966
- raise ApiError(
967
- f"Unexpected {type(self).__name__} permission response for action "
968
- f"{action_name!r}: {type(data)!r}"
969
- )
970
- return data
971
-
972
- def _get_sharing_state(
973
- self,
974
- action_name: str,
975
- *,
976
- timeout: int | float | tuple[float, float] | None = None,
977
- ) -> Any:
978
- data = self._request_detail_action(
979
- r_type="GET",
980
- action_name=action_name,
981
- payload={},
982
- timeout=timeout,
983
- expected_statuses=(200,),
984
- )
985
- if not isinstance(data, dict):
986
- raise ApiError(
987
- f"Unexpected {type(self).__name__} sharing response for action "
988
- f"{action_name!r}: {type(data)!r}"
989
- )
990
-
991
- from .models_user import ShareableAccessState
992
-
993
- return ShareableAccessState.model_validate(data)
994
-
995
- def add_to_view(
996
- self,
997
- user_uid: Any,
998
- *,
999
- timeout: int | float | tuple[float, float] | None = None,
1000
- ) -> dict[str, Any]:
1001
- return self._post_sharing_action(
1002
- self.SHARING_ACTION_PATHS["add_to_view"],
1003
- subject_key="user_uid",
1004
- subject_uid=user_uid,
1005
- timeout=timeout,
1006
- )
1007
-
1008
- def add_to_edit(
1009
- self,
1010
- user_uid: Any,
1011
- *,
1012
- timeout: int | float | tuple[float, float] | None = None,
1013
- ) -> dict[str, Any]:
1014
- return self._post_sharing_action(
1015
- self.SHARING_ACTION_PATHS["add_to_edit"],
1016
- subject_key="user_uid",
1017
- subject_uid=user_uid,
1018
- timeout=timeout,
1019
- )
1020
-
1021
- def remove_from_edit(
1022
- self,
1023
- user_uid: Any,
1024
- *,
1025
- timeout: int | float | tuple[float, float] | None = None,
1026
- ) -> dict[str, Any]:
1027
- return self._post_sharing_action(
1028
- self.SHARING_ACTION_PATHS["remove_from_edit"],
1029
- subject_key="user_uid",
1030
- subject_uid=user_uid,
1031
- timeout=timeout,
1032
- )
1033
-
1034
- def remove_from_view(
1035
- self,
1036
- user_uid: Any,
1037
- *,
1038
- timeout: int | float | tuple[float, float] | None = None,
1039
- ) -> dict[str, Any]:
1040
- return self._post_sharing_action(
1041
- self.SHARING_ACTION_PATHS["remove_from_view"],
1042
- subject_key="user_uid",
1043
- subject_uid=user_uid,
1044
- timeout=timeout,
1045
- )
1046
-
1047
- def add_team_to_view(
1048
- self,
1049
- team_uid: Any,
1050
- *,
1051
- timeout: int | float | tuple[float, float] | None = None,
1052
- ) -> dict[str, Any]:
1053
- return self._post_sharing_action(
1054
- self.SHARING_ACTION_PATHS["add_team_to_view"],
1055
- subject_key="team_uid",
1056
- subject_uid=team_uid,
1057
- timeout=timeout,
1058
- )
1059
-
1060
- def add_team_to_edit(
1061
- self,
1062
- team_uid: Any,
1063
- *,
1064
- timeout: int | float | tuple[float, float] | None = None,
1065
- ) -> dict[str, Any]:
1066
- return self._post_sharing_action(
1067
- self.SHARING_ACTION_PATHS["add_team_to_edit"],
1068
- subject_key="team_uid",
1069
- subject_uid=team_uid,
1070
- timeout=timeout,
1071
- )
1072
-
1073
- def remove_team_from_edit(
1074
- self,
1075
- team_uid: Any,
1076
- *,
1077
- timeout: int | float | tuple[float, float] | None = None,
1078
- ) -> dict[str, Any]:
1079
- return self._post_sharing_action(
1080
- self.SHARING_ACTION_PATHS["remove_team_from_edit"],
1081
- subject_key="team_uid",
1082
- subject_uid=team_uid,
1083
- timeout=timeout,
1084
- )
1085
-
1086
- def remove_team_from_view(
1087
- self,
1088
- team_uid: Any,
1089
- *,
1090
- timeout: int | float | tuple[float, float] | None = None,
1091
- ) -> dict[str, Any]:
1092
- return self._post_sharing_action(
1093
- self.SHARING_ACTION_PATHS["remove_team_from_view"],
1094
- subject_key="team_uid",
1095
- subject_uid=team_uid,
1096
- timeout=timeout,
1097
- )
1098
-
1099
- def can_view(
1100
- self,
1101
- *,
1102
- timeout: int | float | tuple[float, float] | None = None,
1103
- ) -> Any:
1104
- return self._get_sharing_state(
1105
- self.SHARING_ACTION_PATHS["can_view"],
1106
- timeout=timeout,
1107
- )
1108
-
1109
- def users_can_view(
1110
- self,
1111
- *,
1112
- timeout: int | float | tuple[float, float] | None = None,
1113
- ) -> Any:
1114
- return self.can_view(timeout=timeout)
1115
-
1116
- def list_users_can_view(
1117
- self,
1118
- *,
1119
- timeout: int | float | tuple[float, float] | None = None,
1120
- ) -> Any:
1121
- return self.can_view(timeout=timeout)
1122
-
1123
- def can_edit(
1124
- self,
1125
- *,
1126
- timeout: int | float | tuple[float, float] | None = None,
1127
- ) -> Any:
1128
- return self._get_sharing_state(
1129
- self.SHARING_ACTION_PATHS["can_edit"],
1130
- timeout=timeout,
1131
- )
1132
-
1133
- def users_can_edit(
1134
- self,
1135
- *,
1136
- timeout: int | float | tuple[float, float] | None = None,
1137
- ) -> Any:
1138
- return self.can_edit(timeout=timeout)
1139
-
1140
- def list_users_can_edit(
1141
- self,
1142
- *,
1143
- timeout: int | float | tuple[float, float] | None = None,
1144
- ) -> Any:
1145
- return self.can_edit(timeout=timeout)
1146
-
1147
-
1148
- class ShareableObjectMixin(PermissionManagedObjectMixin):
1149
- """
1150
- Backward-compatible alias for models that expose permission-sharing detail actions.
1151
- """
1152
-
1153
- pass
1154
-
1155
-
1156
919
  class LabelRecord(BasePydanticModel):
1157
920
  """Backend label payload attached to labelable objects."""
1158
921
 
@@ -801,7 +801,7 @@ class Bucket(
801
801
  """A named container of Artifacts, owned by one Organization Environment.
802
802
 
803
803
  Who may use a Bucket is decided by its policies: `reader` browses its
804
- folders and the Artifacts in it that are shared with the person;
804
+ folders and the Artifacts in it that the person can see;
805
805
  `contributor` also uploads Artifacts and creates folders; `editor` also
806
806
  renames the Bucket, renames and deletes folders, deletes the Bucket with
807
807
  every Artifact in it, and sees who has access; `owner` also decides who has
@@ -131,13 +131,14 @@ class UserApiBaseObjectOrm(BaseObjectOrm):
131
131
  class OrganizationEnvironment(AccessManagedObjectMixin, UserApiBaseObjectOrm, BasePydanticModel):
132
132
  """Public Environment metadata, scoped by authenticated platform visibility.
133
133
 
134
- Working in an Environment is a policy. `member` works in it, opens what is
135
- shared with the person there, and creates Projects, Buckets, Constants,
136
- Secrets, model providers and repositories in it; `observer` works in it
137
- without creating anything. Both go to people and Teams, never to workload
138
- identities, and only Organization admins attach or detach them. The access
139
- methods (`get_access()`, `attach_policy()`, ...) read and change them;
140
- being admitted never shows objects that are not shared with the person.
134
+ Working in an Environment is a policy. `member` works in it, opens the
135
+ objects there that the person has access to, and creates Projects,
136
+ Buckets, Constants, Secrets, model providers and repositories in it;
137
+ `observer` works in it without creating anything. Both go to people and
138
+ Teams, never to workload identities, and only Organization admins attach
139
+ or detach them. The access methods (`get_access()`, `attach_policy()`, ...)
140
+ read and change them; being admitted never shows objects the person has no
141
+ access to.
141
142
  """
142
143
 
143
144
  ENDPOINT: ClassVar[str] = "organization-environments"
@@ -228,7 +229,7 @@ class Group(BasePydanticModel):
228
229
 
229
230
 
230
231
  class UserSummary(BasePydanticModel):
231
- """A person or workload identity in a team or sharing response.
232
+ """A person or workload identity in a team response.
232
233
 
233
234
  Personal fields are ``None`` for workload identities or when not supplied.
234
235
  Team responses carry ``member_kind`` to distinguish people from workloads.
@@ -285,40 +286,6 @@ class UserSummary(BasePydanticModel):
285
286
  return value
286
287
 
287
288
 
288
- class ShareableTeamSummary(BasePydanticModel):
289
- uid: str | None = Field(
290
- None,
291
- title="Team UID",
292
- description="Stable public unique identifier of the team in shareable-access responses.",
293
- examples=["3f1cc452-43ec-49cb-b2ba-87dbac164d29"],
294
- )
295
- name: str = Field(
296
- ...,
297
- title="Team Name",
298
- description="Human-readable name of the team.",
299
- examples=["Research"],
300
- )
301
- description: str = Field(
302
- "",
303
- title="Team Description",
304
- description="Optional textual description of the team.",
305
- examples=["Team responsible for model research and validation."],
306
- )
307
- member_count: int = Field(
308
- 0,
309
- title="Member Count",
310
- description="Number of members currently in the team.",
311
- examples=[5],
312
- )
313
-
314
- @model_validator(mode="before")
315
- @classmethod
316
- def _drop_internal_id(cls, value: Any) -> Any:
317
- if isinstance(value, dict):
318
- value = {key: item for key, item in value.items() if key != "id"}
319
- return value
320
-
321
-
322
289
  class UserTeamSummary(BasePydanticModel):
323
290
  model_config = ConfigDict(extra="ignore")
324
291
 
@@ -405,7 +372,7 @@ class Team(
405
372
  ):
406
373
  """A group of people and workload identities in one Organization.
407
374
 
408
- Membership is who is in the Team: who receives what is shared with it.
375
+ Membership is who is in the Team: who receives the policies the Team holds.
409
376
  Control is the policies on the Team: `viewer` sees it and its members,
410
377
  `membership_manager` adds and removes members, `editor` renames,
411
378
  describes, activates or deactivates it and sees its policies, and `owner`
@@ -1082,47 +1049,6 @@ class Notification(DetailActionObjectMixin, BasePydanticModel, UserApiBaseObject
1082
1049
  return NotificationBulkActionResult.model_validate(response.json())
1083
1050
 
1084
1051
 
1085
- class ShareableAccessState(BasePydanticModel):
1086
- object_uid: str | None = Field(
1087
- ...,
1088
- title="Object UID",
1089
- description="Public uid of the shareable object whose access is being described.",
1090
- examples=["24001fc7-098c-40fa-b398-1d2352b7c224"],
1091
- )
1092
- object_type: str = Field(
1093
- ...,
1094
- title="Object Type",
1095
- description="Backend object type identifier for the shareable object.",
1096
- examples=["tdag.constant"],
1097
- )
1098
- access_level: OpenValueSet[Literal["view", "edit"]] = Field(
1099
- ...,
1100
- title="Access Level",
1101
- description="Permission level represented by this access-state payload.",
1102
- examples=["view"],
1103
- )
1104
- users: list[UserSummary] = Field(
1105
- default_factory=list,
1106
- title="Users",
1107
- description="Users with this explicit access level on the object.",
1108
- )
1109
- teams: list[ShareableTeamSummary] = Field(
1110
- default_factory=list,
1111
- title="Teams",
1112
- description="Teams with this access level on the object.",
1113
- examples=[
1114
- [
1115
- {
1116
- "uid": "3f1cc452-43ec-49cb-b2ba-87dbac164d29",
1117
- "name": "Research",
1118
- "description": "Research team",
1119
- "member_count": 5,
1120
- }
1121
- ]
1122
- ],
1123
- )
1124
-
1125
-
1126
1052
  class User(_CallerDirectoryReadMixin, UserApiBaseObjectOrm, BasePydanticModel):
1127
1053
  """A platform User: a person, or the workload identity a deployed Job,
1128
1054
  FastAPI release or Agent runs as.
@@ -145,8 +145,8 @@ class AccessBinding(BasePydanticModel):
145
145
  description=(
146
146
  "Why the binding exists: `explicit` (someone attached it), `creator` (given to "
147
147
  "the object's creator), `workflow` (declared in a repository workflow file) or "
148
- "`migrated` (converted from an earlier view or edit grant). The source grants "
149
- "nothing by itself."
148
+ "`migrated` (created by the platform when it moved existing access to policies). "
149
+ "The source grants nothing by itself."
150
150
  ),
151
151
  )
152
152
  granted_by: AccessGrantor | None = Field(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 9.0.30.dev73
3
+ Version: 9.0.30.dev74
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: MIT
@@ -49,7 +49,8 @@ Dynamic: license-file
49
49
  The Main Sequence Python SDK is the client and development toolkit for the Main
50
50
  Sequence platform. It provides authentication, typed platform resources,
51
51
  CodeRepository development and release operations, Agent and A2A workflows,
52
- jobs, sharing, observability, logging, tracing, and reusable scaffold tooling.
52
+ jobs, access policies, observability, logging, tracing, and reusable scaffold
53
+ tooling.
53
54
 
54
55
  MetaTables is now an independent domain package, installed as
55
56
  `mainsequence-metatable` and imported as `metatables`. Table models, time-index
@@ -70,8 +71,8 @@ execution are no longer implemented by this distribution.
70
71
  Main package areas:
71
72
 
72
73
  - `mainsequence.client`: API client models for users, CodeRepositories, jobs,
73
- Agents, artifacts, constants, secrets, sharing, releases, and other platform
74
- resources
74
+ Agents, artifacts, constants, secrets, access policies, releases, and other
75
+ platform resources
75
76
  - `mainsequence.cli`: the complete `mainsequence` command-line interface for
76
77
  authentication, platform resources, and local CodeRepository operations
77
78
  - `mainsequence.instrumentation` and `mainsequence.logconf`: SDK tracing and
@@ -135,7 +136,8 @@ mainsequence code-repository build-local-venv --path .
135
136
  Use `mainsequence --help` and `mainsequence code-repository --help` for the
136
137
  installed command surface. The CLI includes Agent and AgentSession,
137
138
  CodeRepository, jobs and runs, images, resources and releases, constants,
138
- secrets, teams, sharing, scaffold, Docker, and local-development commands.
139
+ secrets, teams, access policies, scaffold, Docker, and local-development
140
+ commands.
139
141
 
140
142
  ## Python Client
141
143
 
@@ -1,12 +1,12 @@
1
1
  agent_scaffold/skills/a2a_sdk_execution/SKILL.md,sha256=NcwIQ1QgD4Ku0mG2Hb-Izee8p9fm9LTPHa6gDEWTOSQ,13200
2
- agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md,sha256=V2YW1oNlkKCr0_WwieVIZStl7rRfXlk02IdvkzyuneU,26820
2
+ agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md,sha256=rs2_TChiTrcNLHGdY8b8viO21d30uHiQcswtgTXItpM,26828
3
3
  agent_scaffold/skills/mainsequence-inference/SKILL.md,sha256=Kl1P_40_TCfZkYLM4hlAvlSIQspSMFALswwkmSJaDBI,12717
4
4
  agent_scaffold/skills/maintenance/bug_auditor/SKILL.md,sha256=lXoHxBAqyJ2MHgxbDNq-T6DDD2Yetlwv2hNoUnQG3w0,8935
5
5
  agent_scaffold/skills/maintenance/code_repository_maintenance/SKILL.md,sha256=3vHuR_43NbZ4cfGtoMM-FAYLwz137NSso-3J5AdNGQ4,18650
6
6
  agent_scaffold/skills/maintenance/metatables_transition/SKILL.md,sha256=PisgpytcksJnfZMS6aiPCmahsT3fm8DIwk_cefXA2qU,3759
7
- agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md,sha256=qvKtRly2yV1PkQFwnG2x2C90gcYwqeVq0B11oJRE0k0,29867
8
- agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md,sha256=Npb3N6wyuQOyj54BBhz5YPnuJ4uuR4F_LYkZ5IIc77s,17661
9
- agent_scaffold/skills/sdk_code_repository_execution/SKILL.md,sha256=7lZ9V4DwpiCOKRimK8QbPIEJ4TDjgBhoOPxyvsN3rhE,7038
7
+ agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md,sha256=k3SYqiU-IuWm1IunlrAQY9NaCANlq6EjqCFN0gGcuiQ,29673
8
+ agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md,sha256=hdGavnuDYYN8aBM3xWjOaKV3w7rc5rrLTRouRGnffc4,17670
9
+ agent_scaffold/skills/sdk_code_repository_execution/SKILL.md,sha256=7hBAJuDOKdZUcGoqR7Y4nMHZ9kX5fuY6CMOcgdDaPWI,7046
10
10
  mainsequence/__init__.py,sha256=70CbIo7ZG1mzi5uwkqDtVESunBE0RanHjeFg4ptfsA0,385
11
11
  mainsequence/__main__.py,sha256=KuAP69uduS2ImrPIgNMzbGBRepZzjqvUONu5vFh4v4A,176
12
12
  mainsequence/_request_identity.py,sha256=suRjESLA_YY_TAxE2htWHd07gvPhJGr-1GtpFnjaVTc,5543
@@ -24,7 +24,7 @@ mainsequence/scaffold_skills.py,sha256=k0V6eKC5AwbHr9wB9UGMJNF-8eJ0_1izF4-BU01KH
24
24
  mainsequence/cli/__init__.py,sha256=sMWTnomCaISjnureLuXFRqOzkH2Y77uYEivsd-M6_8Y,28
25
25
  mainsequence/cli/api.py,sha256=ExVKhvT99sXstS7aaL1Tx50_hbmf3X8X5aesOkTvXGo,128227
26
26
  mainsequence/cli/browser_auth.py,sha256=Vb5MBOnPC05HLZzVNUDODobJ_p5wEIzH_h8rIlpShlE,9984
27
- mainsequence/cli/cli.py,sha256=qi3Qz76U4H3sYbYdU0bji4Cg9Y_2Ld_3PoMmCQAGRso,277805
27
+ mainsequence/cli/cli.py,sha256=_KGmnmWhFRZ15RPuVJgwQo3mw6JYuFbXvI5_krGTM3c,277775
28
28
  mainsequence/cli/code_repository_status.py,sha256=SHEnU8YSWFowPG6dEdE4Yd8CS1tIcJSE1MXFLfvD3Os,5975
29
29
  mainsequence/cli/config.py,sha256=TJYnM11kg5pH2O7AGWFLpNEkC9UEu0g7k2RLjhAHCzo,45724
30
30
  mainsequence/cli/docker_utils.py,sha256=eAnp9MI042cHWwKasA5IF2I7INL3A6tV2JX-cSIe7rc,10687
@@ -38,16 +38,16 @@ mainsequence/cli/ui.py,sha256=memd6pmjALfGj8zndGCx_z80ztQeqTcOvcofU0un34U,2277
38
38
  mainsequence/client/__init__.py,sha256=V6BCS6O5VXpyy7fUYU4yF_2QUF3RiUHP-rzrmRhpmD8,759
39
39
  mainsequence/client/access_catalog.py,sha256=fZhSqb3xNQHwHk9YqbzaFyesz3KrZUUBS5GEuO8pmT4,11817
40
40
  mainsequence/client/agent_runtime_models.py,sha256=ydblB7UQ3HvtPJoqlzgsJZuhdRPvsCXex2YE5RSdjQo,76205
41
- mainsequence/client/base.py,sha256=iQQZJIwncRaLvfolZA3xi7DI3gnHYNHq144i-LAvlhQ,43531
41
+ mainsequence/client/base.py,sha256=c9LVgXvW8OaT22PSgARrJ1_Ftc8v79kkstdBBNQpuMU,36454
42
42
  mainsequence/client/client.py,sha256=Jaw9RYObdVDS5J2O0pln99-XpuW9e4vW-SsbJRNldfw,3866
43
43
  mainsequence/client/compute_validation.py,sha256=ByeX0CkIE7qq06ggZFfN92U3Qp2e9cvo2RTIGWa5_Vw,6662
44
44
  mainsequence/client/exceptions.py,sha256=xx2L4l3OMNsTybbYkiTKK398ahnutEascM0It35tGr0,3815
45
45
  mainsequence/client/github_issues.py,sha256=pSTUw3UPrmE6wqnpoJctartTaNSq6iu6PQRrd8hip6I,14568
46
46
  mainsequence/client/inference.py,sha256=tYKHRxLR6mA5iLmgd3qURwweWc2OPQuw0__tD3LQgSI,7748
47
- mainsequence/client/models_foundry.py,sha256=hLSUiNF9qKKuFjycMinvXMZ7xZks8z4c2jC1ruws6YU,46405
47
+ mainsequence/client/models_foundry.py,sha256=aHks-RcJtqNz-ZxZjxbd6x8B2Y79cV16G7GIEicYk-o,46397
48
48
  mainsequence/client/models_helpers.py,sha256=6we2XFTyp_G_EHXEcGiXHKgeDFplW135RFljgIN7v2o,52310
49
- mainsequence/client/models_user.py,sha256=YtBD-RwsnrSV8NuBFFrP21PsP2N6M0LyGany9Pr6p7U,56006
50
- mainsequence/client/object_access.py,sha256=wfLoASnwgqcLxu8FiXqHXDb1uBXsbirkfglItr9wciw,22879
49
+ mainsequence/client/models_user.py,sha256=txBjrW81jP1JvTwu_qMwiCgZZMaDc1X5C6SxBD9-zBw,53608
50
+ mainsequence/client/object_access.py,sha256=OUZvhOQNfe3Q6sr4K9tz3X35Myp1LteIX8IiAvo1W_4,22900
51
51
  mainsequence/client/observability.py,sha256=_WrDKCaNk_TXmKElKCXC1inork6Exxxe8FRY4m1GI9s,16008
52
52
  mainsequence/client/utils.py,sha256=Rk2z-78swO6GepibLlQNdxL1eqYy8vHGrjiZdV3G5CM,31641
53
53
  mainsequence/client/value_sets.py,sha256=7TA-mpuAd3hOduNgO1WTQQTuNOGaFgue-VqCsDWKaC8,6181
@@ -60,9 +60,9 @@ mainsequence/server/mcp_skills.py,sha256=-krRwAHCAMipScgGJ19uVkzznhTop1Nz4C_wRY1
60
60
  mainsequence/server/_mcp_skills_upstream/__init__.py,sha256=px283qBMf3z1nxCfN3WHrH9v8Y8jOb1xoBqZMRZcaD8,2694
61
61
  mainsequence/server/_mcp_skills_upstream/server.py,sha256=laHsfpoaYX3LcwQ04-GN7r0_C63fG6CzyXDci2rmbHE,7695
62
62
  mainsequence/server/_mcp_skills_upstream/shared.py,sha256=JmnX9PoLoyi93nBYnUEPWCdPXor_nQHjHptQDXpFzPs,11978
63
- mainsequence-9.0.30.dev73.dist-info/licenses/LICENSE,sha256=b6Ecsk8wjsEby3lbSzdljR6hHiFGHBizt9iWV2p1c_I,1074
64
- mainsequence-9.0.30.dev73.dist-info/METADATA,sha256=x8tXQ9UzLNTWgcjgDXrRsaruFBxLuZLu3PtBTKHv1_o,7531
65
- mainsequence-9.0.30.dev73.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
66
- mainsequence-9.0.30.dev73.dist-info/entry_points.txt,sha256=XGAOq3-mF2lWWpeRJvoaWyMarRcK167mH1g124aGdUs,88
67
- mainsequence-9.0.30.dev73.dist-info/top_level.txt,sha256=BFeblM_Q9q0cUWBvTxnfWcWQEHtf5XZi9nOS-Gdfwus,28
68
- mainsequence-9.0.30.dev73.dist-info/RECORD,,
63
+ mainsequence-9.0.30.dev74.dist-info/licenses/LICENSE,sha256=b6Ecsk8wjsEby3lbSzdljR6hHiFGHBizt9iWV2p1c_I,1074
64
+ mainsequence-9.0.30.dev74.dist-info/METADATA,sha256=3G-3S7NWjLuHg2IFfmBUJJ0tyukYI6fap8og6wQCqjs,7555
65
+ mainsequence-9.0.30.dev74.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
66
+ mainsequence-9.0.30.dev74.dist-info/entry_points.txt,sha256=XGAOq3-mF2lWWpeRJvoaWyMarRcK167mH1g124aGdUs,88
67
+ mainsequence-9.0.30.dev74.dist-info/top_level.txt,sha256=BFeblM_Q9q0cUWBvTxnfWcWQEHtf5XZi9nOS-Gdfwus,28
68
+ mainsequence-9.0.30.dev74.dist-info/RECORD,,