summaryrefslogtreecommitdiff
path: root/makima/src/server/handlers/directives.rs
diff options
context:
space:
mode:
Diffstat (limited to 'makima/src/server/handlers/directives.rs')
-rw-r--r--makima/src/server/handlers/directives.rs60
1 files changed, 60 insertions, 0 deletions
diff --git a/makima/src/server/handlers/directives.rs b/makima/src/server/handlers/directives.rs
index 91f5892..7a7aff4 100644
--- a/makima/src/server/handlers/directives.rs
+++ b/makima/src/server/handlers/directives.rs
@@ -227,6 +227,17 @@ pub async fn update_directive(
"Snapshotted directive revision on PR creation"
);
}
+
+ // Transition the contract to 'inactive' now that its
+ // iteration is "shipped" — editing the goal again starts
+ // an amendment cycle, surfaced via the New draft action.
+ if let Err(e) = repository::set_directive_inactive(pool, directive.id).await {
+ tracing::warn!(
+ directive_id = %directive.id,
+ error = %e,
+ "Failed to mark directive inactive after PR creation"
+ );
+ }
}
}
Json(directive).into_response()
@@ -2094,6 +2105,55 @@ pub struct DirectiveRevisionListResponse {
pub total: i64,
}
+/// Reset a directive for a new draft cycle — clears its goal and detaches
+/// the current PR linkage. Past revisions remain attached as history.
+///
+/// Intended for the sidebar's "New draft" right-click on an inactive
+/// directive: the contract has shipped, the user wants to start the next
+/// iteration on a clean slate without losing the prior PR's record.
+#[utoipa::path(
+ post,
+ path = "/api/v1/directives/{id}/new-draft",
+ params(("id" = Uuid, Path, description = "Directive ID")),
+ responses(
+ (status = 200, description = "Directive reset to draft", body = Directive),
+ (status = 404, description = "Not found", body = ApiError),
+ (status = 503, description = "Database not configured", body = ApiError),
+ ),
+ security(("bearer_auth" = []), ("api_key" = [])),
+ tag = "Directives"
+)]
+pub async fn new_directive_draft(
+ State(state): State<SharedState>,
+ Authenticated(auth): Authenticated,
+ Path(id): Path<Uuid>,
+) -> impl IntoResponse {
+ let Some(ref pool) = state.db_pool else {
+ return (
+ StatusCode::SERVICE_UNAVAILABLE,
+ Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")),
+ )
+ .into_response();
+ };
+
+ match repository::reset_directive_for_new_draft(pool, auth.owner_id, id).await {
+ Ok(Some(directive)) => Json(directive).into_response(),
+ Ok(None) => (
+ StatusCode::NOT_FOUND,
+ Json(ApiError::new("NOT_FOUND", "Directive not found")),
+ )
+ .into_response(),
+ Err(e) => {
+ tracing::error!("Failed to reset directive for new draft: {}", e);
+ (
+ StatusCode::INTERNAL_SERVER_ERROR,
+ Json(ApiError::new("RESET_FAILED", &e.to_string())),
+ )
+ .into_response()
+ }
+ }
+}
+
/// List all per-PR revisions for a directive, newest first.
#[utoipa::path(
get,