feat(contracts): convert a contract between organization and project level
JI
8h ago+1387+1387+0123456789012345678901234567890123456789-105-105-012345678901234567890123456789
Summary
Lets an organization admin convert an existing workflow contract between the organization level and a project level, in both directions. The contract keeps its ID, name, revisions, and workflows. This implements spec issue-3644.
- API: the contract update request gets an optional level field, either a project reference or
organization_scoped. When it is not set, the level does not change (R-001, R-011, R-009). - CLI:
chainloop workflow contract updategets--project <name>and--org-level, which cannot be used together. - Rules: a conversion creates no revision (R-003, R-007). A request for the current level changes nothing, and a move from one project to a different project is rejected (R-006). A conversion to a project is rejected when workflows of other projects use the contract, and the error lists them (R-005).
- Authorization: only organization owners and admins, and organization-level API tokens, can convert a contract (R-004).
- Audit: a new
WorkflowContractScopeChangedevent records the old and the new level, as read under the contract lock (R-008, D-010). - Workflows: workflow update now rejects a contract of a different project, as workflow create already did. Workflow create also checks the existing default contract of the workflow (R-010). Conversions and workflow changes lock the contract, so they cannot race (D-008).
Spec changes in this PR: D-009 supersedes D-003 (the flag is --org-level, because a local --org hides the global organization flag), R-011 supersedes R-002 (the same requirement with the new flag), and D-010 is new.
Closes #3644
AI disclosure: this change was implemented with the assistance of Claude Code.