@@ -575,34 +575,6 @@ fn display_network_exposure_warning(bind_addr: &str) {
575575 eprintln ! ( ) ;
576576}
577577
578- fn display_bootstrap_mode_warning ( bind_addr : & str ) {
579- eprintln ! ( ) ;
580- eprintln ! (
581- "{} {}" ,
582- style( "Bootstrap mode enabled:" ) . yellow( ) . bold( ) ,
583- style( "no preconfigured users were found." ) . yellow( )
584- ) ;
585- eprintln ! ( ) ;
586- eprintln ! (
587- "The service will start on {} and print an Initial One-Time Password (IOTP) in container logs." ,
588- style( bind_addr) . cyan( )
589- ) ;
590- eprintln ! (
591- "{}" ,
592- style( "Note: persisted users in /var/lib/opencode-users disable IOTP bootstrap." )
593- . yellow( )
594- . dim( )
595- ) ;
596- eprintln ! ( "Open the login page and use the first-time setup panel with that IOTP." ) ;
597- eprintln ! ( "The IOTP is invalidated immediately after the first successful passkey enrollment." ) ;
598- eprintln ! ( ) ;
599- eprintln ! (
600- "Admin alternative: {}" ,
601- style( "occ user add <username>" ) . dim( )
602- ) ;
603- eprintln ! ( ) ;
604- }
605-
606578/// Start the opencode service
607579///
608580/// This command:
@@ -715,12 +687,6 @@ pub async fn cmd_start(
715687 // Determine whether this is first container start
716688 let is_first_start = !container_exists ( & client, CONTAINER_NAME ) . await ?;
717689
718- let bootstrap_mode =
719- is_first_start && config. users . is_empty ( ) && !config. allow_unauthenticated_network ;
720- if bootstrap_mode && !quiet {
721- display_bootstrap_mode_warning ( bind_addr) ;
722- }
723-
724690 // Check for port mismatch on existing container
725691 if !is_first_start
726692 && !recreate_container
@@ -874,7 +840,7 @@ pub async fn cmd_start(
874840 quiet,
875841 host_name. as_deref ( ) ,
876842 ) ;
877- maybe_print_iotp_info ( & client, host_name. as_deref ( ) , & config, bootstrap_mode ) . await ;
843+ maybe_print_iotp_info ( & client, host_name. as_deref ( ) , & config) . await ;
878844 open_browser_if_requested ( args. open , port, bind_addr) ;
879845
880846 if args. no_daemon {
@@ -1204,12 +1170,13 @@ async fn maybe_print_iotp_info(
12041170 client : & DockerClient ,
12051171 host : Option < & str > ,
12061172 config : & opencode_cloud_core:: Config ,
1207- bootstrap_mode_hint : bool ,
12081173) {
12091174 if config. allow_unauthenticated_network || !config. users . is_empty ( ) {
12101175 return ;
12111176 }
12121177
1178+ // The bootstrap helper is the source of truth after container startup.
1179+ // Do not infer onboarding state from pre-start config heuristics.
12131180 let snapshot = fetch_iotp_snapshot ( client) . await ;
12141181
12151182 println ! ( ) ;
@@ -1234,23 +1201,16 @@ async fn maybe_print_iotp_info(
12341201 "{}" ,
12351202 style( "Could not retrieve an IOTP from bootstrap state." ) . yellow( )
12361203 ) ;
1237- println ! (
1238- "Reason: {}" ,
1239- iotp_unavailable_reason( & snapshot, bootstrap_mode_hint)
1240- ) ;
1204+ println ! ( "Reason: {}" , iotp_unavailable_reason( & snapshot) ) ;
12411205 println ! ( "Fetch logs with: {}" , style( "occ logs" ) . cyan( ) ) ;
12421206 println ! ( "Try extracting IOTP with:\n {IOTP_FALLBACK_COMMAND}" ) ;
12431207}
12441208
1245- fn iotp_unavailable_reason ( snapshot : & IotpSnapshot , bootstrap_mode_hint : bool ) -> String {
1209+ fn iotp_unavailable_reason ( snapshot : & IotpSnapshot ) -> String {
12461210 if let Some ( reason) = snapshot. detail . as_deref ( ) {
12471211 return reason. to_string ( ) ;
12481212 }
12491213
1250- if bootstrap_mode_hint {
1251- return "bootstrap mode was requested but no active IOTP is available" . to_string ( ) ;
1252- }
1253-
12541214 format ! ( "IOTP state is {}" , snapshot. state_label)
12551215}
12561216
@@ -1519,20 +1479,21 @@ mod tests {
15191479 otp : None ,
15201480 detail : Some ( "bootstrap helper unavailable" . to_string ( ) ) ,
15211481 } ;
1522- let reason = super :: iotp_unavailable_reason ( & snapshot, true ) ;
1482+ let reason = super :: iotp_unavailable_reason ( & snapshot) ;
15231483 assert_eq ! ( reason, "bootstrap helper unavailable" ) ;
15241484 }
15251485
15261486 #[ test]
1527- fn iotp_unavailable_reason_uses_bootstrap_hint ( ) {
1487+ fn iotp_unavailable_reason_does_not_invent_bootstrap_hint ( ) {
15281488 let snapshot = IotpSnapshot {
15291489 state : IotpState :: Unavailable ,
15301490 state_label : "unavailable" . to_string ( ) ,
15311491 otp : None ,
15321492 detail : None ,
15331493 } ;
1534- let reason = super :: iotp_unavailable_reason ( & snapshot, true ) ;
1535- assert ! ( reason. contains( "bootstrap mode was requested" ) ) ;
1494+ let reason = super :: iotp_unavailable_reason ( & snapshot) ;
1495+ assert_eq ! ( reason, "IOTP state is unavailable" ) ;
1496+ assert ! ( !reason. contains( "bootstrap mode was requested" ) ) ;
15361497 }
15371498
15381499 #[ test]
@@ -1543,7 +1504,7 @@ mod tests {
15431504 otp : None ,
15441505 detail : None ,
15451506 } ;
1546- let reason = super :: iotp_unavailable_reason ( & snapshot, false ) ;
1507+ let reason = super :: iotp_unavailable_reason ( & snapshot) ;
15471508 assert_eq ! ( reason, "IOTP state is inactive (users configured)" ) ;
15481509 }
15491510}
0 commit comments