@@ -2362,6 +2362,13 @@ int db_init(arkilian **db_ptr, const char *filename) {
23622362 db -> chunk_enabled = get_env_bool_default ("ARKILIAN_WAL_DIRECT_S3" ,
23632363 (db -> s3_endpoint && db -> s3_endpoint [0 ] &&
23642364 db -> s3_access_key && db -> s3_access_key [0 ]) ? 1 : 0 );
2365+ if (db -> chunk_enabled && db -> s3_prefix == NULL ) {
2366+ if (db -> db_id && db -> db_id [0 ])
2367+ db -> s3_prefix = strdup (db -> db_id );
2368+ else
2369+ db -> s3_prefix = strdup ("db_default" );
2370+ ARK_STORE (& db -> s3_creds_loaded , 1 );
2371+ }
23652372 // ARKILIAN_ALLOW_INSECURE=1 opts into cleartext http:// endpoints that
23662373 // are NOT loopback/RFC1918 (e.g. an internal-but-public corporate
23672374 // aggregator). Default 0: anything non-https and non-local is refused.
@@ -2373,15 +2380,25 @@ int db_init(arkilian **db_ptr, const char *filename) {
23732380 // failure, per the §0 rule that the backup subsystem must not break
23742381 // the application.
23752382 if (db -> backup_enabled && (!db -> control_url || strlen (db -> control_url ) == 0 )) {
2376- ark_log (db , ARK_LOG_WARN ,
2377- "backup is enabled (ARKILIAN_ENABLE_BACKUP) but ARKILIAN_CONTROL_URL "
2378- "is not set — rows will accumulate in _pending_backup and never ship" );
2383+ if (ARK_LOAD (& db -> s3_creds_loaded )) {
2384+ ark_log (db , ARK_LOG_INFO ,
2385+ "no control plane configured — direct S3 backup active" );
2386+ } else {
2387+ ark_log (db , ARK_LOG_WARN ,
2388+ "backup is enabled (ARKILIAN_ENABLE_BACKUP) but ARKILIAN_CONTROL_URL "
2389+ "is not set — rows will accumulate in _pending_backup and never ship" );
2390+ }
23792391 }
23802392 if (db -> backup_enabled && (!db -> api_key || strlen (db -> api_key ) == 0 )) {
2381- ark_log (db , ARK_LOG_WARN ,
2382- "backup is enabled but ARKILIAN_API_KEY is not set — the "
2383- "control plane will reject every request; backup DISABLED" );
2384- ARK_STORE (& db -> backup_enabled , 0 );
2393+ if (ARK_LOAD (& db -> s3_creds_loaded )) {
2394+ ark_log (db , ARK_LOG_INFO ,
2395+ "no API key configured — direct S3 backup active" );
2396+ } else {
2397+ ark_log (db , ARK_LOG_WARN ,
2398+ "backup is enabled but ARKILIAN_API_KEY is not set — the "
2399+ "control plane will reject every request; backup DISABLED" );
2400+ ARK_STORE (& db -> backup_enabled , 0 );
2401+ }
23852402 }
23862403
23872404 // Credential transport hygiene: over http:// the API key and every
@@ -2421,7 +2438,12 @@ int db_init(arkilian **db_ptr, const char *filename) {
24212438 // async validation clears backup_enabled + alerts via the standard
24222439 // monitoring path. See struct arkilian.startup_auth_state.
24232440 int skip_auth = get_env_bool_default ("ARKILIAN_SKIP_STARTUP_AUTH" , 0 );
2424- ARK_STORE (& db -> startup_auth_state , skip_auth ? 1 : 0 );
2441+ if (skip_auth || (ARK_LOAD (& db -> s3_creds_loaded ) &&
2442+ (!db -> control_url || !db -> control_url [0 ]))) {
2443+ ARK_STORE (& db -> startup_auth_state , 1 );
2444+ } else {
2445+ ARK_STORE (& db -> startup_auth_state , 0 );
2446+ }
24252447
24262448 // libcurl global init must happen before ANY thread calls
24272449 // curl_easy_init — concurrent first use is not thread-safe. The
0 commit comments