1414from .agent import Agent , StepSchema
1515from .base import BaseModel
1616from .controls import (
17+ ControlAction ,
1718 ControlDefinition ,
1819 TemplateControlInput ,
1920 TemplateDefinition ,
@@ -347,6 +348,9 @@ class GetControlResponse(BaseModel):
347348
348349 id : int = Field (..., description = "Control ID" )
349350 name : str = Field (..., description = "Control name" )
351+ cloned_from_control_id : int | None = Field (
352+ None , description = "Source control ID when this control is a clone."
353+ )
350354 data : ControlDefinition | UnrenderedTemplateControl = Field (
351355 description = (
352356 "Control configuration data. A ControlDefinition for raw/rendered "
@@ -514,14 +518,60 @@ class AgentRef(BaseModel):
514518 agent_name : str = Field (..., description = "Agent name" )
515519
516520
521+ class PolicyRef (BaseModel ):
522+ """Reference to a policy attached to a control."""
523+
524+ policy_id : int = Field (..., description = "Policy ID" )
525+
526+
527+ class TargetAttachmentRef (BaseModel ):
528+ """Reference to a target binding attached to a control."""
529+
530+ binding_id : int = Field (..., description = "Control binding ID" )
531+ target_type : str = Field (..., description = "Opaque target kind" )
532+ target_id : str = Field (..., description = "Opaque target identifier" )
533+ enabled : bool = Field (..., description = "Whether this target binding is enabled" )
534+
535+
536+ class ControlAttachments (BaseModel ):
537+ """Attachments for a listed control."""
538+
539+ agents : list [AgentRef ] = Field (
540+ default_factory = list ,
541+ description = "Direct agent associations for this control" ,
542+ )
543+ policies : list [PolicyRef ] = Field (
544+ default_factory = list ,
545+ description = "Policy associations for this control" ,
546+ )
547+ targets : list [TargetAttachmentRef ] = Field (
548+ default_factory = list ,
549+ description = "Target bindings for this control" ,
550+ )
551+ targets_total : int = Field (
552+ default = 0 ,
553+ description = "Total target bindings matching the attachment filters" ,
554+ )
555+ targets_truncated : bool = Field (
556+ default = False ,
557+ description = "Whether the target bindings list was capped" ,
558+ )
559+
560+
517561class ControlSummary (BaseModel ):
518562 """Summary of a control for list responses."""
519563
520564 id : int = Field (..., description = "Control ID" )
521565 name : str = Field (..., description = "Control name" )
566+ cloned_from_control_id : int | None = Field (
567+ None , description = "Source control ID when this control is a clone."
568+ )
522569 description : str | None = Field (None , description = "Control description" )
523570 enabled : bool = Field (True , description = "Whether control is enabled" )
524571 execution : str | None = Field (None , description = "'server' or 'sdk'" )
572+ action : ControlAction | None = Field (
573+ None , description = "Action applied when the control matches."
574+ )
525575 step_types : list [str ] | None = Field (None , description = "Step types in scope" )
526576 stages : list [str ] | None = Field (None , description = "Evaluation stages in scope" )
527577 tags : list [str ] = Field (default_factory = list , description = "Control tags" )
@@ -542,6 +592,13 @@ class ControlSummary(BaseModel):
542592 used_by_agents_count : int = Field (
543593 0 , description = "Number of unique agents using this control"
544594 )
595+ attachments : ControlAttachments | None = Field (
596+ None ,
597+ description = (
598+ "Expanded attachment details. Present when list controls is called "
599+ "with include_attachments=true."
600+ ),
601+ )
545602
546603
547604class ListControlsResponse (BaseModel ):
@@ -580,7 +637,7 @@ class GetControlVersionResponse(BaseModel):
580637 ...,
581638 description = (
582639 "Raw persisted snapshot of the control state at this version, including "
583- "metadata such as name, deleted_at, and cloned_control_id ."
640+ "metadata such as name, deleted_at, and cloned_from_control_id ."
584641 ),
585642 )
586643
@@ -635,6 +692,50 @@ class PatchControlResponse(BaseModel):
635692]
636693
637694
695+ class CloneAndBindTargetBinding (BaseModel ):
696+ """Target binding to create for a cloned control."""
697+
698+ model_config = ConfigDict (extra = "forbid" )
699+
700+ target_type : ControlBindingTargetField = Field (
701+ ...,
702+ description = "Opaque attachment kind (caller-defined; e.g. 'environment', 'session')." ,
703+ )
704+ target_id : ControlBindingTargetField = Field (
705+ ..., description = "Opaque external identifier within the target_type."
706+ )
707+ enabled : bool = Field (
708+ default = True ,
709+ description = "Whether the created binding is active." ,
710+ )
711+
712+
713+ class CloneAndBindControlRequest (BaseModel ):
714+ """Request to clone a control and attach the clone to one target."""
715+
716+ model_config = ConfigDict (extra = "forbid" )
717+
718+ name : SlugName | None = Field (
719+ None ,
720+ description = (
721+ "Optional unique name for the cloned control. If omitted, the server "
722+ "generates a name from the source control name."
723+ ),
724+ )
725+ target_binding : CloneAndBindTargetBinding = Field (
726+ ..., description = "Target binding to create for the cloned control."
727+ )
728+
729+
730+ class CloneAndBindControlResponse (BaseModel ):
731+ """Response from cloning and binding a control."""
732+
733+ id : int = Field (..., description = "Identifier of the cloned control." )
734+ name : str = Field (..., description = "Name of the cloned control." )
735+ cloned_from_control_id : int = Field (..., description = "Source control ID." )
736+ binding_id : int = Field (..., description = "Identifier of the created binding." )
737+
738+
638739class CreateControlBindingRequest (BaseModel ):
639740 """Request to attach a control to an opaque external target."""
640741
@@ -741,6 +842,21 @@ class UpsertControlBindingResponse(BaseModel):
741842 enabled : bool = Field (..., description = "Current enabled value." )
742843
743844
845+ class PatchControlBindingByKeyRequest (BaseModel ):
846+ """Request to update an existing control binding by natural key."""
847+
848+ target_type : ControlBindingTargetField = Field (
849+ ..., description = "Opaque attachment kind."
850+ )
851+ target_id : ControlBindingTargetField = Field (
852+ ..., description = "Opaque external identifier within the target_type."
853+ )
854+ control_id : int = Field (
855+ ..., gt = 0 , description = "ID of the bound control."
856+ )
857+ enabled : bool = Field (..., description = "New enabled value for the binding." )
858+
859+
744860class DeleteControlBindingByKeyRequest (BaseModel ):
745861 """Request to detach a control binding by natural key (idempotent)."""
746862
@@ -759,4 +875,3 @@ class DeleteControlBindingByKeyResponse(BaseModel):
759875 "binding existed."
760876 ),
761877 )
762-
0 commit comments