@@ -332,6 +332,14 @@ struct ReindexFileBody {
332332 file : String ,
333333}
334334
335+ #[ derive( Debug , Deserialize ) ]
336+ struct SetupBody {
337+ mode : String ,
338+ name : Option < String > ,
339+ role : Option < String > ,
340+ purpose : Option < String > ,
341+ }
342+
335343// ---------------------------------------------------------------------------
336344// CORS
337345// ---------------------------------------------------------------------------
@@ -388,6 +396,9 @@ pub fn build_router(state: ApiState) -> Router {
388396 . route ( "/api/delete" , post ( handle_delete) )
389397 // Index maintenance
390398 . route ( "/api/reindex-file" , post ( handle_reindex_file) )
399+ // Identity endpoints
400+ . route ( "/api/identity" , get ( handle_identity) )
401+ . route ( "/api/setup" , post ( handle_setup) )
391402 // Migration endpoints
392403 . route ( "/api/migrate/preview" , post ( handle_migrate_preview) )
393404 . route ( "/api/migrate/apply" , post ( handle_migrate_apply) )
@@ -1066,6 +1077,60 @@ async fn handle_reindex_file(
10661077 } ) ) )
10671078}
10681079
1080+ // ---------------------------------------------------------------------------
1081+ // Identity / setup endpoint handlers
1082+ // ---------------------------------------------------------------------------
1083+
1084+ async fn handle_identity (
1085+ State ( state) : State < ApiState > ,
1086+ headers : HeaderMap ,
1087+ ) -> Result < impl IntoResponse , ApiError > {
1088+ authorize ( & headers, & state, false ) ?;
1089+ let store = state. store . lock ( ) . await ;
1090+ let config = crate :: config:: Config :: load ( ) . unwrap_or_default ( ) ;
1091+ let block = crate :: identity:: format_identity_block ( & config, & store)
1092+ . map_err ( |e| ApiError :: internal ( & format ! ( "{e:#}" ) ) ) ?;
1093+ Ok ( Json ( serde_json:: json!( { "identity" : block } ) ) )
1094+ }
1095+
1096+ async fn handle_setup (
1097+ State ( state) : State < ApiState > ,
1098+ headers : HeaderMap ,
1099+ Json ( body) : Json < SetupBody > ,
1100+ ) -> Result < impl IntoResponse , ApiError > {
1101+ authorize ( & headers, & state, true ) ?;
1102+ match body. mode . as_str ( ) {
1103+ "detect" => {
1104+ let result = crate :: onboarding:: run_detect_json ( & state. vault_path )
1105+ . map_err ( |e| ApiError :: internal ( & format ! ( "{e:#}" ) ) ) ?;
1106+ Ok ( Json ( result) )
1107+ }
1108+ "apply" => {
1109+ let mut config = crate :: config:: Config :: load ( ) . unwrap_or_default ( ) ;
1110+ let data_dir = crate :: config:: Config :: data_dir ( )
1111+ . map_err ( |e| ApiError :: internal ( & format ! ( "{e:#}" ) ) ) ?;
1112+ let flags = crate :: onboarding:: ApplyFlags {
1113+ name : body. name ,
1114+ role : body. role ,
1115+ purpose : body. purpose ,
1116+ identity_only : false ,
1117+ reindex_only : false ,
1118+ } ;
1119+ let result = crate :: onboarding:: run_apply_json (
1120+ & state. vault_path ,
1121+ & mut config,
1122+ & data_dir,
1123+ flags,
1124+ )
1125+ . map_err ( |e| ApiError :: internal ( & format ! ( "{e:#}" ) ) ) ?;
1126+ Ok ( Json ( result) )
1127+ }
1128+ other => Err ( ApiError :: bad_request ( & format ! (
1129+ "Unknown mode: {other}. Use 'detect' or 'apply'."
1130+ ) ) ) ,
1131+ }
1132+ }
1133+
10691134// ---------------------------------------------------------------------------
10701135// Tests
10711136// ---------------------------------------------------------------------------
0 commit comments