Skip to main content

uarp_sdk/generated/api/
governance.rs

1// Code generated by @uarp/codegen from spec/openapi.json. DO NOT EDIT.
2//!
3//! Agent governance: constitution, voting, permissions, emergency protocols
4
5#![allow(unused_imports, clippy::too_many_arguments)]
6
7use reqwest::Method;
8use serde::{Deserialize, Serialize};
9
10use crate::client::{Client, Request, NO_BODY, NO_QUERY};
11use crate::error::Result;
12use crate::generated::models;
13use crate::multipart::{field_text, FilePart};
14use crate::util::encode_path;
15
16/// Query and header parameters for `getGovernanceLedger`.
17#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
18pub struct GetGovernanceLedgerParams {
19    /// How many of THIS TENANT's most recent entries to return, capped at 200. Ignored when both
20    /// `from` and `to` are supplied.
21    #[serde(default, skip_serializing_if = "Option::is_none")]
22    pub count: Option<i64>,
23    /// Inclusive lower bound as a ledger SEQUENCE NUMBER (`seq`), not a timestamp. `seq` is a
24    /// position in the one global chain shared by all tenants, so a tenant's own entries are
25    /// scattered across it — use `count` unless you already have a `seq` from a previous response.
26    /// Has no effect unless `to` is supplied as well. Declared as a string until 2026-08-28, which
27    /// is why callers reasonably sent an ISO timestamp: the server ran it through `parseInt`, so
28    /// `2026-08-28T18:00:00Z` silently became sequence 2026 and the request answered 200 with an
29    /// empty page. Non-integer values are now rejected with 400.
30    #[serde(default, skip_serializing_if = "Option::is_none")]
31    pub from: Option<i64>,
32    /// Inclusive upper bound as a ledger SEQUENCE NUMBER (`seq`), not a timestamp. See `from`. Has
33    /// no effect unless `from` is supplied as well.
34    #[serde(default, skip_serializing_if = "Option::is_none")]
35    pub to: Option<i64>,
36}
37
38/// Query and header parameters for `listAmbassadorRequests`.
39#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
40pub struct ListAmbassadorRequestsParams {
41    #[serde(default, skip_serializing_if = "Option::is_none")]
42    pub status: Option<models::AmbassadorRequestStatus>,
43}
44
45/// Query and header parameters for `listGoals`.
46#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
47pub struct ListGoalsParams {
48    #[serde(default, skip_serializing_if = "Option::is_none")]
49    pub agent_id: Option<String>,
50}
51
52/// Query and header parameters for `verifyGovernanceLedger`.
53#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
54pub struct VerifyGovernanceLedgerParams {
55    #[serde(default, skip_serializing_if = "Option::is_none")]
56    pub from: Option<String>,
57    #[serde(default, skip_serializing_if = "Option::is_none")]
58    pub to: Option<String>,
59}
60
61/// Agent governance: constitution, voting, permissions, emergency protocols
62#[derive(Debug, Clone)]
63pub struct GovernanceApi {
64    pub(crate) client: Client,
65}
66
67impl Client {
68    /// Agent governance: constitution, voting, permissions, emergency protocols
69    pub fn governance(&self) -> GovernanceApi {
70        GovernanceApi { client: self.clone() }
71    }
72}
73
74impl GovernanceApi {
75    /// Activate safe mode
76    ///
77    /// **Founder-only.** Halts all non-essential agent execution platform-wide. Admin role is NOT
78    /// sufficient.
79    ///
80    /// `POST /api/v1/governance/emergency/safe-mode`
81    pub async fn activate_safe_mode(&self, body: &models::ActivateSafeModeRequest) -> Result<models::EmergencyState> {
82        self.client
83            .request_json(Request {
84                method: Method::POST,
85                path: "/api/v1/governance/emergency/safe-mode".to_string(),
86                query: NO_QUERY,
87                body: Some(body),
88                headers: Vec::new(),
89                idempotent: true,
90            })
91            .await
92    }
93
94    /// Veto
95    ///
96    /// `POST /api/v1/governance/ambassador/veto`
97    pub async fn ambassador_veto(&self, body: &models::AmbassadorVetoRequest) -> Result<models::VetoRecord> {
98        self.client
99            .request_json(Request {
100                method: Method::POST,
101                path: "/api/v1/governance/ambassador/veto".to_string(),
102                query: NO_QUERY,
103                body: Some(body),
104                headers: Vec::new(),
105                idempotent: true,
106            })
107            .await
108    }
109
110    /// Amend constitution
111    ///
112    /// `POST /api/v1/governance/constitution/amend`
113    pub async fn amend_constitution(&self, body: &models::AmendConstitutionRequest) -> Result<models::ConstitutionDocument> {
114        self.client
115            .request_json(Request {
116                method: Method::POST,
117                path: "/api/v1/governance/constitution/amend".to_string(),
118                query: NO_QUERY,
119                body: Some(body),
120                headers: Vec::new(),
121                idempotent: true,
122            })
123            .await
124    }
125
126    /// Bootstrap first ambassador
127    ///
128    /// `POST /api/v1/governance/ambassador/ambassadors/bootstrap`
129    pub async fn bootstrap_ambassador(&self) -> Result<models::BootstrapAmbassadorResponse> {
130        self.client
131            .request_json(Request {
132                method: Method::POST,
133                path: "/api/v1/governance/ambassador/ambassadors/bootstrap".to_string(),
134                query: NO_QUERY,
135                body: NO_BODY,
136                headers: Vec::new(),
137                idempotent: true,
138            })
139            .await
140    }
141
142    /// Cast ballot
143    ///
144    /// `POST /api/v1/governance/voting/proposals/{id}/ballot`
145    pub async fn cast_ballot(&self, id: &str, body: &models::CastBallotRequest) -> Result<models::Ballot> {
146        self.client
147            .request_json(Request {
148                method: Method::POST,
149                path: format!("/api/v1/governance/voting/proposals/{}/ballot", encode_path(id)),
150                query: NO_QUERY,
151                body: Some(body),
152                headers: Vec::new(),
153                idempotent: true,
154            })
155            .await
156    }
157
158    /// Check for deadlock
159    ///
160    /// `POST /api/v1/governance/emergency/deadlock-check`
161    pub async fn check_deadlock(&self) -> Result<serde_json::Map<String, serde_json::Value>> {
162        self.client
163            .request_json(Request {
164                method: Method::POST,
165                path: "/api/v1/governance/emergency/deadlock-check".to_string(),
166                query: NO_QUERY,
167                body: NO_BODY,
168                headers: Vec::new(),
169                idempotent: true,
170            })
171            .await
172    }
173
174    /// Check governance compliance
175    ///
176    /// `POST /api/v1/governance/check`
177    pub async fn check_governance(&self, body: &models::CheckGovernanceRequest) -> Result<models::EnforcementResult> {
178        self.client
179            .request_json(Request {
180                method: Method::POST,
181                path: "/api/v1/governance/check".to_string(),
182                query: NO_QUERY,
183                body: Some(body),
184                headers: Vec::new(),
185                idempotent: true,
186            })
187            .await
188    }
189
190    /// Check spawn permission
191    ///
192    /// `POST /api/v1/governance/permissions/check-spawn`
193    pub async fn check_spawn_permission(&self, body: &models::CheckSpawnPermissionRequest) -> Result<models::PermissionCheckResult> {
194        self.client
195            .request_json(Request {
196                method: Method::POST,
197                path: "/api/v1/governance/permissions/check-spawn".to_string(),
198                query: NO_QUERY,
199                body: Some(body),
200                headers: Vec::new(),
201                idempotent: true,
202            })
203            .await
204    }
205
206    /// Create request
207    ///
208    /// `POST /api/v1/governance/ambassador/requests`
209    pub async fn create_ambassador_request(&self, body: &models::CreateAmbassadorRequestRequest) -> Result<serde_json::Map<String, serde_json::Value>> {
210        self.client
211            .request_json(Request {
212                method: Method::POST,
213                path: "/api/v1/governance/ambassador/requests".to_string(),
214                query: NO_QUERY,
215                body: Some(body),
216                headers: Vec::new(),
217                idempotent: true,
218            })
219            .await
220    }
221
222    /// Create design request
223    ///
224    /// `POST /api/v1/governance/builder/requests`
225    pub async fn create_builder_request(&self, body: &models::DesignRequestCreate) -> Result<models::DesignRequest> {
226        self.client
227            .request_json(Request {
228                method: Method::POST,
229                path: "/api/v1/governance/builder/requests".to_string(),
230                query: NO_QUERY,
231                body: Some(body),
232                headers: Vec::new(),
233                idempotent: true,
234            })
235            .await
236    }
237
238    /// Create goal
239    ///
240    /// `POST /api/v1/governance/goals`
241    pub async fn create_goal(&self, body: &models::CreateGoalRequest) -> Result<models::Goal> {
242        self.client
243            .request_json(Request {
244                method: Method::POST,
245                path: "/api/v1/governance/goals".to_string(),
246                query: NO_QUERY,
247                body: Some(body),
248                headers: Vec::new(),
249                idempotent: true,
250            })
251            .await
252    }
253
254    /// Create improvement proposal
255    ///
256    /// `POST /api/v1/governance/improvement/{agentId}`
257    pub async fn create_improvement_proposal(&self, agent_id: &str, body: &models::CreateImprovementProposalRequest) -> Result<models::ImprovementProposal> {
258        self.client
259            .request_json(Request {
260                method: Method::POST,
261                path: format!("/api/v1/governance/improvement/{}", encode_path(agent_id)),
262                query: NO_QUERY,
263                body: Some(body),
264                headers: Vec::new(),
265                idempotent: true,
266            })
267            .await
268    }
269
270    /// Create proposal
271    ///
272    /// `POST /api/v1/governance/voting/proposals`
273    pub async fn create_voting_proposal(&self, body: &models::CreateVotingProposalRequest) -> Result<models::VotingProposal> {
274        self.client
275            .request_json(Request {
276                method: Method::POST,
277                path: "/api/v1/governance/voting/proposals".to_string(),
278                query: NO_QUERY,
279                body: Some(body),
280                headers: Vec::new(),
281                idempotent: true,
282            })
283            .await
284    }
285
286    /// Deactivate safe mode
287    ///
288    /// **Founder-only.** Returns the platform to normal mode after a safe-mode activation.
289    ///
290    /// `POST /api/v1/governance/emergency/deactivate`
291    pub async fn deactivate_safe_mode(&self) -> Result<models::DeactivateSafeModeResponse> {
292        self.client
293            .request_json(Request {
294                method: Method::POST,
295                path: "/api/v1/governance/emergency/deactivate".to_string(),
296                query: NO_QUERY,
297                body: NO_BODY,
298                headers: Vec::new(),
299                idempotent: true,
300            })
301            .await
302    }
303
304    /// Delete spawn policy
305    ///
306    /// `DELETE /api/v1/governance/permissions/spawn-policy`
307    pub async fn delete_spawn_policy(&self) -> Result<models::DeleteSpawnPolicyResponse> {
308        self.client
309            .request_json(Request {
310                method: Method::DELETE,
311                path: "/api/v1/governance/permissions/spawn-policy".to_string(),
312                query: NO_QUERY,
313                body: NO_BODY,
314                headers: Vec::new(),
315                idempotent: true,
316            })
317            .await
318    }
319
320    /// File appeal
321    ///
322    /// `POST /api/v1/governance/arbiter/cases/{id}/appeal`
323    pub async fn file_arbiter_appeal(&self, id: &str, body: &models::FileArbiterAppealRequest) -> Result<models::FileArbiterAppealResponse> {
324        self.client
325            .request_json(Request {
326                method: Method::POST,
327                path: format!("/api/v1/governance/arbiter/cases/{}/appeal", encode_path(id)),
328                query: NO_QUERY,
329                body: Some(body),
330                headers: Vec::new(),
331                idempotent: true,
332            })
333            .await
334    }
335
336    /// File case
337    ///
338    /// Files a new arbitration case. Returns 409 if the filer would have a conflict of interest
339    /// with the chosen arbiter pool (server checks before persisting).
340    ///
341    /// `POST /api/v1/governance/arbiter/cases`
342    pub async fn file_arbiter_case(&self, body: &models::FileArbiterCaseRequest) -> Result<serde_json::Map<String, serde_json::Value>> {
343        self.client
344            .request_json(Request {
345                method: Method::POST,
346                path: "/api/v1/governance/arbiter/cases".to_string(),
347                query: NO_QUERY,
348                body: Some(body),
349                headers: Vec::new(),
350                idempotent: true,
351            })
352            .await
353    }
354
355    /// Get agent obligations
356    ///
357    /// `GET /api/v1/governance/obligations/{agentId}`
358    pub async fn get_agent_obligations(&self, agent_id: &str) -> Result<models::GetAgentObligationsResponse> {
359        self.client
360            .request_json(Request {
361                method: Method::GET,
362                path: format!("/api/v1/governance/obligations/{}", encode_path(agent_id)),
363                query: NO_QUERY,
364                body: NO_BODY,
365                headers: Vec::new(),
366                idempotent: false,
367            })
368            .await
369    }
370
371    /// Get agent permissions
372    ///
373    /// `GET /api/v1/governance/permissions/{agentId}`
374    pub async fn get_agent_permissions(&self, agent_id: &str) -> Result<models::PermissionSet> {
375        self.client
376            .request_json(Request {
377                method: Method::GET,
378                path: format!("/api/v1/governance/permissions/{}", encode_path(agent_id)),
379                query: NO_QUERY,
380                body: NO_BODY,
381                headers: Vec::new(),
382                idempotent: false,
383            })
384            .await
385    }
386
387    /// Get agent violations
388    ///
389    /// `GET /api/v1/governance/violations/{agentId}`
390    pub async fn get_agent_violations(&self, agent_id: &str) -> Result<models::GetAgentViolationsResponse> {
391        self.client
392            .request_json(Request {
393                method: Method::GET,
394                path: format!("/api/v1/governance/violations/{}", encode_path(agent_id)),
395                query: NO_QUERY,
396                body: NO_BODY,
397                headers: Vec::new(),
398                idempotent: false,
399            })
400            .await
401    }
402
403    /// Get ambassador
404    ///
405    /// `GET /api/v1/governance/ambassador/ambassadors/{id}`
406    pub async fn get_ambassador(&self, id: &str) -> Result<models::Ambassador> {
407        self.client
408            .request_json(Request {
409                method: Method::GET,
410                path: format!("/api/v1/governance/ambassador/ambassadors/{}", encode_path(id)),
411                query: NO_QUERY,
412                body: NO_BODY,
413                headers: Vec::new(),
414                idempotent: false,
415            })
416            .await
417    }
418
419    /// Get case
420    ///
421    /// `GET /api/v1/governance/arbiter/cases/{id}`
422    pub async fn get_arbiter_case(&self, id: &str) -> Result<models::ArbiterCase> {
423        self.client
424            .request_json(Request {
425                method: Method::GET,
426                path: format!("/api/v1/governance/arbiter/cases/{}", encode_path(id)),
427                query: NO_QUERY,
428                body: NO_BODY,
429                headers: Vec::new(),
430                idempotent: false,
431            })
432            .await
433    }
434
435    /// Get arbiter registry
436    ///
437    /// `GET /api/v1/governance/arbiter/registry`
438    pub async fn get_arbiter_registry(&self) -> Result<models::ArbiterRegistry> {
439        self.client
440            .request_json(Request {
441                method: Method::GET,
442                path: "/api/v1/governance/arbiter/registry".to_string(),
443                query: NO_QUERY,
444                body: NO_BODY,
445                headers: Vec::new(),
446                idempotent: false,
447            })
448            .await
449    }
450
451    /// Get design request
452    ///
453    /// `GET /api/v1/governance/builder/requests/{id}`
454    pub async fn get_builder_request(&self, id: &str) -> Result<models::DesignRequest> {
455        self.client
456            .request_json(Request {
457                method: Method::GET,
458                path: format!("/api/v1/governance/builder/requests/{}", encode_path(id)),
459                query: NO_QUERY,
460                body: NO_BODY,
461                headers: Vec::new(),
462                idempotent: false,
463            })
464            .await
465    }
466
467    /// Get constitution
468    ///
469    /// `GET /api/v1/governance/constitution`
470    pub async fn get_constitution(&self) -> Result<models::ConstitutionDocument> {
471        self.client
472            .request_json(Request {
473                method: Method::GET,
474                path: "/api/v1/governance/constitution".to_string(),
475                query: NO_QUERY,
476                body: NO_BODY,
477                headers: Vec::new(),
478                idempotent: false,
479            })
480            .await
481    }
482
483    /// Get emergency state
484    ///
485    /// `GET /api/v1/governance/emergency/state`
486    pub async fn get_emergency_state(&self) -> Result<models::EmergencyState> {
487        self.client
488            .request_json(Request {
489                method: Method::GET,
490                path: "/api/v1/governance/emergency/state".to_string(),
491                query: NO_QUERY,
492                body: NO_BODY,
493                headers: Vec::new(),
494                idempotent: false,
495            })
496            .await
497    }
498
499    /// Get goal
500    ///
501    /// `GET /api/v1/governance/goals/{id}`
502    pub async fn get_goal(&self, id: &str) -> Result<models::Goal> {
503        self.client
504            .request_json(Request {
505                method: Method::GET,
506                path: format!("/api/v1/governance/goals/{}", encode_path(id)),
507                query: NO_QUERY,
508                body: NO_BODY,
509                headers: Vec::new(),
510                idempotent: false,
511            })
512            .await
513    }
514
515    /// Get governance ledger
516    ///
517    /// Entries visible to the calling tenant, newest first.
518    ///
519    /// **Walking `prev_hash` across this page is NOT a verification, and treating it as one
520    /// produces false alarms.** `seq` is global across all tenants while this list is scoped to
521    /// one, so consecutive rows here are usually NOT consecutive in the ledger — the entry a row's
522    /// `prev_hash` names belongs to another tenant and is not returned. Measured against production
523    /// on 2026-08-20 over three independent samples: every pair whose `seq` values were adjacent
524    /// chained correctly, and every pair with a gap did not — 10/10 and 0/5 in the last sample,
525    /// while `GET /governance/ledger/verify` answered `valid: true` at the same moment.
526    ///
527    /// A client that walks the chain of a page therefore reports tampering in a ledger the server
528    /// certifies as intact. Integrity has an authority, and it is `GET /governance/ledger/verify`;
529    /// a page-local walk can say "adjacent and chained" or "cannot be checked from here", never
530    /// "broken".
531    ///
532    /// `GET /api/v1/governance/ledger`
533    pub async fn get_governance_ledger(&self, params: &GetGovernanceLedgerParams) -> Result<models::GetGovernanceLedgerResponse> {
534        self.client
535            .request_json(Request {
536                method: Method::GET,
537                path: "/api/v1/governance/ledger".to_string(),
538                query: Some(params),
539                body: NO_BODY,
540                headers: Vec::new(),
541                idempotent: false,
542            })
543            .await
544    }
545
546    /// Get proposal
547    ///
548    /// `GET /api/v1/governance/improvement/{agentId}/{version}`
549    pub async fn get_improvement_proposal(&self, agent_id: &str, version: &str) -> Result<models::ImprovementProposal> {
550        self.client
551            .request_json(Request {
552                method: Method::GET,
553                path: format!("/api/v1/governance/improvement/{}/{}", encode_path(agent_id), encode_path(version)),
554                query: NO_QUERY,
555                body: NO_BODY,
556                headers: Vec::new(),
557                idempotent: false,
558            })
559            .await
560    }
561
562    /// Get permission lineage
563    ///
564    /// `GET /api/v1/governance/permissions/{agentId}/lineage`
565    pub async fn get_permission_lineage(&self, agent_id: &str) -> Result<models::AgentLineage> {
566        self.client
567            .request_json(Request {
568                method: Method::GET,
569                path: format!("/api/v1/governance/permissions/{}/lineage", encode_path(agent_id)),
570                query: NO_QUERY,
571                body: NO_BODY,
572                headers: Vec::new(),
573                idempotent: false,
574            })
575            .await
576    }
577
578    /// Get root agent
579    ///
580    /// `GET /api/v1/governance/emergency/root-agent`
581    pub async fn get_root_agent(&self) -> Result<models::GetRootAgentResponse> {
582        self.client
583            .request_json(Request {
584                method: Method::GET,
585                path: "/api/v1/governance/emergency/root-agent".to_string(),
586                query: NO_QUERY,
587                body: NO_BODY,
588                headers: Vec::new(),
589                idempotent: false,
590            })
591            .await
592    }
593
594    /// Get root attestation
595    ///
596    /// `GET /api/v1/governance/emergency/root-attestation`
597    pub async fn get_root_attestation(&self) -> Result<serde_json::Map<String, serde_json::Value>> {
598        self.client
599            .request_json(Request {
600                method: Method::GET,
601                path: "/api/v1/governance/emergency/root-attestation".to_string(),
602                query: NO_QUERY,
603                body: NO_BODY,
604                headers: Vec::new(),
605                idempotent: false,
606            })
607            .await
608    }
609
610    /// Get spawn policy
611    ///
612    /// `GET /api/v1/governance/permissions/spawn-policy`
613    pub async fn get_spawn_policy(&self) -> Result<models::SpawnPolicy> {
614        self.client
615            .request_json(Request {
616                method: Method::GET,
617                path: "/api/v1/governance/permissions/spawn-policy".to_string(),
618                query: NO_QUERY,
619                body: NO_BODY,
620                headers: Vec::new(),
621                idempotent: false,
622            })
623            .await
624    }
625
626    /// Get proposal
627    ///
628    /// `GET /api/v1/governance/voting/proposals/{id}`
629    pub async fn get_voting_proposal(&self, id: &str) -> Result<models::VotingProposal> {
630        self.client
631            .request_json(Request {
632                method: Method::GET,
633                path: format!("/api/v1/governance/voting/proposals/{}", encode_path(id)),
634                query: NO_QUERY,
635                body: NO_BODY,
636                headers: Vec::new(),
637                idempotent: false,
638            })
639            .await
640    }
641
642    /// Issue ruling
643    ///
644    /// `POST /api/v1/governance/arbiter/cases/{id}/ruling`
645    pub async fn issue_arbiter_ruling(&self, id: &str, body: &models::IssueArbiterRulingRequest) -> Result<models::IssueArbiterRulingResponse> {
646        self.client
647            .request_json(Request {
648                method: Method::POST,
649                path: format!("/api/v1/governance/arbiter/cases/{}/ruling", encode_path(id)),
650                query: NO_QUERY,
651                body: Some(body),
652                headers: Vec::new(),
653                idempotent: true,
654            })
655            .await
656    }
657
658    /// List requests
659    ///
660    /// `GET /api/v1/governance/ambassador/requests`
661    pub async fn list_ambassador_requests(&self, params: &ListAmbassadorRequestsParams) -> Result<models::ListAmbassadorRequestsResponse> {
662        self.client
663            .request_json(Request {
664                method: Method::GET,
665                path: "/api/v1/governance/ambassador/requests".to_string(),
666                query: Some(params),
667                body: NO_BODY,
668                headers: Vec::new(),
669                idempotent: false,
670            })
671            .await
672    }
673
674    /// List ambassadors
675    ///
676    /// `GET /api/v1/governance/ambassador/ambassadors`
677    pub async fn list_ambassadors(&self) -> Result<Vec<models::Ambassador>> {
678        self.client
679            .request_json(Request {
680                method: Method::GET,
681                path: "/api/v1/governance/ambassador/ambassadors".to_string(),
682                query: NO_QUERY,
683                body: NO_BODY,
684                headers: Vec::new(),
685                idempotent: false,
686            })
687            .await
688    }
689
690    /// List vetoes
691    ///
692    /// `GET /api/v1/governance/ambassador/vetoes`
693    pub async fn list_ambassador_vetoes(&self) -> Result<models::ListAmbassadorVetoesResponse> {
694        self.client
695            .request_json(Request {
696                method: Method::GET,
697                path: "/api/v1/governance/ambassador/vetoes".to_string(),
698                query: NO_QUERY,
699                body: NO_BODY,
700                headers: Vec::new(),
701                idempotent: false,
702            })
703            .await
704    }
705
706    /// List cases
707    ///
708    /// `GET /api/v1/governance/arbiter/cases`
709    pub async fn list_arbiter_cases(&self) -> Result<models::ListArbiterCasesResponse> {
710        self.client
711            .request_json(Request {
712                method: Method::GET,
713                path: "/api/v1/governance/arbiter/cases".to_string(),
714                query: NO_QUERY,
715                body: NO_BODY,
716                headers: Vec::new(),
717                idempotent: false,
718            })
719            .await
720    }
721
722    /// List ballots
723    ///
724    /// `GET /api/v1/governance/voting/proposals/{id}/ballots`
725    pub async fn list_ballots(&self, id: &str) -> Result<models::ListBallotsResponse> {
726        self.client
727            .request_json(Request {
728                method: Method::GET,
729                path: format!("/api/v1/governance/voting/proposals/{}/ballots", encode_path(id)),
730                query: NO_QUERY,
731                body: NO_BODY,
732                headers: Vec::new(),
733                idempotent: false,
734            })
735            .await
736    }
737
738    /// List design requests
739    ///
740    /// `GET /api/v1/governance/builder/requests`
741    pub async fn list_builder_requests(&self) -> Result<models::ListBuilderRequestsResponse> {
742        self.client
743            .request_json(Request {
744                method: Method::GET,
745                path: "/api/v1/governance/builder/requests".to_string(),
746                query: NO_QUERY,
747                body: NO_BODY,
748                headers: Vec::new(),
749                idempotent: false,
750            })
751            .await
752    }
753
754    /// List goals
755    ///
756    /// `GET /api/v1/governance/goals`
757    pub async fn list_goals(&self, params: &ListGoalsParams) -> Result<models::ListGoalsResponse> {
758        self.client
759            .request_json(Request {
760                method: Method::GET,
761                path: "/api/v1/governance/goals".to_string(),
762                query: Some(params),
763                body: NO_BODY,
764                headers: Vec::new(),
765                idempotent: false,
766            })
767            .await
768    }
769
770    /// List improvement proposals
771    ///
772    /// `GET /api/v1/governance/improvement/{agentId}`
773    pub async fn list_improvement_proposals(&self, agent_id: &str) -> Result<Vec<models::ImprovementProposal>> {
774        self.client
775            .request_json(Request {
776                method: Method::GET,
777                path: format!("/api/v1/governance/improvement/{}", encode_path(agent_id)),
778                query: NO_QUERY,
779                body: NO_BODY,
780                headers: Vec::new(),
781                idempotent: false,
782            })
783            .await
784    }
785
786    /// List proposals
787    ///
788    /// `GET /api/v1/governance/voting/proposals`
789    pub async fn list_voting_proposals(&self) -> Result<models::ListVotingProposalsResponse> {
790        self.client
791            .request_json(Request {
792                method: Method::GET,
793                path: "/api/v1/governance/voting/proposals".to_string(),
794                query: NO_QUERY,
795                body: NO_BODY,
796                headers: Vec::new(),
797                idempotent: false,
798            })
799            .await
800    }
801
802    /// Register ambassador
803    ///
804    /// `POST /api/v1/governance/ambassador/ambassadors`
805    pub async fn register_ambassador(&self, body: &models::RegisterAmbassadorRequest) -> Result<models::RegisterAmbassadorResponse> {
806        self.client
807            .request_json(Request {
808                method: Method::POST,
809                path: "/api/v1/governance/ambassador/ambassadors".to_string(),
810                query: NO_QUERY,
811                body: Some(body),
812                headers: Vec::new(),
813                idempotent: true,
814            })
815            .await
816    }
817
818    /// Replace constitution
819    ///
820    /// `PUT /api/v1/governance/constitution`
821    pub async fn replace_constitution(&self, body: &models::ReplaceConstitutionRequest) -> Result<models::ConstitutionDocument> {
822        self.client
823            .request_json(Request {
824                method: Method::PUT,
825                path: "/api/v1/governance/constitution".to_string(),
826                query: NO_QUERY,
827                body: Some(body),
828                headers: Vec::new(),
829                idempotent: true,
830            })
831            .await
832    }
833
834    /// Resolve request
835    ///
836    /// `POST /api/v1/governance/ambassador/requests/{id}/resolve`
837    pub async fn resolve_ambassador_request(&self, id: &str, body: &models::ResolveAmbassadorRequestRequest) -> Result<serde_json::Map<String, serde_json::Value>> {
838        self.client
839            .request_json(Request {
840                method: Method::POST,
841                path: format!("/api/v1/governance/ambassador/requests/{}/resolve", encode_path(id)),
842                query: NO_QUERY,
843                body: Some(body),
844                headers: Vec::new(),
845                idempotent: true,
846            })
847            .await
848    }
849
850    /// Set agent permissions
851    ///
852    /// WRITE SEMANTICS: merges. A field the body omits keeps its stored value; only a FIRST write
853    /// falls back to the documented defaults (budget 1.0, spawn depth 3, empty lists). A field that
854    /// IS present but of the wrong type falls to the safe default rather than to the stored value —
855    /// on a permissions surface a malformed write must fail closed, not become a silent no-op.
856    /// `created_at` is server-owned and ignored from the body.
857    ///
858    /// `PUT /api/v1/governance/permissions/{agentId}`
859    pub async fn set_agent_permissions(&self, agent_id: &str, body: &models::PermissionSetUpdate) -> Result<models::SetAgentPermissionsResponse> {
860        self.client
861            .request_json(Request {
862                method: Method::PUT,
863                path: format!("/api/v1/governance/permissions/{}", encode_path(agent_id)),
864                query: NO_QUERY,
865                body: Some(body),
866                headers: Vec::new(),
867                idempotent: true,
868            })
869            .await
870    }
871
872    /// Set arbiter registry
873    ///
874    /// `PUT /api/v1/governance/arbiter/registry`
875    pub async fn set_arbiter_registry(&self, body: &serde_json::Map<String, serde_json::Value>) -> Result<models::SetArbiterRegistryResponse> {
876        self.client
877            .request_json(Request {
878                method: Method::PUT,
879                path: "/api/v1/governance/arbiter/registry".to_string(),
880                query: NO_QUERY,
881                body: Some(body),
882                headers: Vec::new(),
883                idempotent: true,
884            })
885            .await
886    }
887
888    /// Set root agent
889    ///
890    /// `PUT /api/v1/governance/emergency/root-agent`
891    pub async fn set_root_agent(&self, body: &models::SetRootAgentRequest) -> Result<models::SetRootAgentResponse> {
892        self.client
893            .request_json(Request {
894                method: Method::PUT,
895                path: "/api/v1/governance/emergency/root-agent".to_string(),
896                query: NO_QUERY,
897                body: Some(body),
898                headers: Vec::new(),
899                idempotent: true,
900            })
901            .await
902    }
903
904    /// Set root attestation
905    ///
906    /// WRITE SEMANTICS: replaces. The body IS the attestation record — every field is required and
907    /// nothing is carried over, which is why a body missing one answers 422 rather than storing a
908    /// partial record. `created_at` is server-stamped, never taken from the caller.
909    ///
910    /// `PUT /api/v1/governance/emergency/root-attestation`
911    pub async fn set_root_attestation(&self, body: &serde_json::Map<String, serde_json::Value>) -> Result<models::SetRootAttestationResponse> {
912        self.client
913            .request_json(Request {
914                method: Method::PUT,
915                path: "/api/v1/governance/emergency/root-attestation".to_string(),
916                query: NO_QUERY,
917                body: Some(body),
918                headers: Vec::new(),
919                idempotent: true,
920            })
921            .await
922    }
923
924    /// Set spawn policy
925    ///
926    /// `PUT /api/v1/governance/permissions/spawn-policy`
927    pub async fn set_spawn_policy(&self, body: &models::SpawnPolicyUpdate) -> Result<models::SetSpawnPolicyResponse> {
928        self.client
929            .request_json(Request {
930                method: Method::PUT,
931                path: "/api/v1/governance/permissions/spawn-policy".to_string(),
932                query: NO_QUERY,
933                body: Some(body),
934                headers: Vec::new(),
935                idempotent: true,
936            })
937            .await
938    }
939
940    /// Tally votes
941    ///
942    /// `POST /api/v1/governance/voting/proposals/{id}/tally`
943    pub async fn tally_votes(&self, id: &str) -> Result<models::VoteResult> {
944        self.client
945            .request_json(Request {
946                method: Method::POST,
947                path: format!("/api/v1/governance/voting/proposals/{}/tally", encode_path(id)),
948                query: NO_QUERY,
949                body: NO_BODY,
950                headers: Vec::new(),
951                idempotent: true,
952            })
953            .await
954    }
955
956    /// Update request status
957    ///
958    /// `PUT /api/v1/governance/builder/requests/{id}/status`
959    pub async fn update_builder_request_status(&self, id: &str, body: &models::UpdateBuilderRequestStatusRequest) -> Result<models::DesignRequest> {
960        self.client
961            .request_json(Request {
962                method: Method::PUT,
963                path: format!("/api/v1/governance/builder/requests/{}/status", encode_path(id)),
964                query: NO_QUERY,
965                body: Some(body),
966                headers: Vec::new(),
967                idempotent: true,
968            })
969            .await
970    }
971
972    /// Update goal status
973    ///
974    /// `PUT /api/v1/governance/goals/{id}/status`
975    pub async fn update_goal_status(&self, id: &str, body: &models::UpdateGoalStatusRequest) -> Result<serde_json::Map<String, serde_json::Value>> {
976        self.client
977            .request_json(Request {
978                method: Method::PUT,
979                path: format!("/api/v1/governance/goals/{}/status", encode_path(id)),
980                query: NO_QUERY,
981                body: Some(body),
982                headers: Vec::new(),
983                idempotent: true,
984            })
985            .await
986    }
987
988    /// Update proposal status (state machine enforced)
989    ///
990    /// Allowed transitions:
991    /// - `proposed` → `arbiter_review` | `rejected`
992    /// - `arbiter_review` → `voting` | `rejected`
993    /// - `voting` → `sandbox_testing` | `rejected`
994    /// - `sandbox_testing` → `approved` | `rejected`
995    /// - `approved` → `applied`
996    ///
997    /// Any other transition returns 400. Requires admin/founder role.
998    ///
999    /// `PUT /api/v1/governance/improvement/{agentId}/{version}/status`
1000    pub async fn update_improvement_status(&self, agent_id: &str, version: &str, body: &models::UpdateImprovementStatusRequest) -> Result<models::ImprovementProposal> {
1001        self.client
1002            .request_json(Request {
1003                method: Method::PUT,
1004                path: format!("/api/v1/governance/improvement/{}/{}/status", encode_path(agent_id), encode_path(version)),
1005                query: NO_QUERY,
1006                body: Some(body),
1007                headers: Vec::new(),
1008                idempotent: true,
1009            })
1010            .await
1011    }
1012
1013    /// Verify ledger integrity
1014    ///
1015    /// `GET /api/v1/governance/ledger/verify`
1016    pub async fn verify_governance_ledger(&self, params: &VerifyGovernanceLedgerParams) -> Result<models::LedgerIntegrity> {
1017        self.client
1018            .request_json(Request {
1019                method: Method::GET,
1020                path: "/api/v1/governance/ledger/verify".to_string(),
1021                query: Some(params),
1022                body: NO_BODY,
1023                headers: Vec::new(),
1024                idempotent: false,
1025            })
1026            .await
1027    }
1028
1029    /// Veto proposal
1030    ///
1031    /// `POST /api/v1/governance/voting/proposals/{id}/veto`
1032    pub async fn veto_proposal(&self, id: &str, body: &models::VetoProposalRequest) -> Result<models::VetoProposalResponse> {
1033        self.client
1034            .request_json(Request {
1035                method: Method::POST,
1036                path: format!("/api/v1/governance/voting/proposals/{}/veto", encode_path(id)),
1037                query: NO_QUERY,
1038                body: Some(body),
1039                headers: Vec::new(),
1040                idempotent: true,
1041            })
1042            .await
1043    }
1044}