Files
Charon/backend/test_output_qa.txt
GitHub Actions 9eb0f31e75 chore: Refactor patch coverage remediation plan and create dedicated spec file
- Moved the existing patch coverage remediation plan from `current_spec.md` to a new file `patch_coverage_spec.md` for better organization and focus on security remediation.
- Updated the goal to emphasize restoring Codecov patch coverage to green by ensuring 100% of modified lines are executed by tests.
- Defined two workstreams: one for fixing patch coverage in specific backend files and another for updating prevention measures in instructions and agent files.
- Added a detailed missing files table to track Codecov patch report line ranges and corresponding test strategies.
- Included guidance on handling partial patch lines and common patterns for missed coverage.
- Specified a remediation plan with a test-first approach and per-file testing strategies for targeted coverage improvements.
- Updated relevant instructions and agent files to enforce patch coverage requirements and improve validation processes.
2026-01-10 03:06:07 +00:00

14135 lines
969 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
=== RUN TestResetPasswordCommand_Succeeds
time="2026-01-10T02:16:43Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
time="2026-01-10T02:16:43Z" level=info msg="SQLite database integrity check passed"
--- PASS: TestResetPasswordCommand_Succeeds (1.99s)
=== RUN TestMigrateCommand_Succeeds
time="2026-01-10T02:16:44Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
time="2026-01-10T02:16:44Z" level=info msg="SQLite database integrity check passed"
time="2026-01-10T02:16:46Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
time="2026-01-10T02:16:46Z" level=info msg="SQLite database integrity check passed"
--- PASS: TestMigrateCommand_Succeeds (1.27s)
=== RUN TestStartupVerification_MissingTables
time="2026-01-10T02:16:46Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
time="2026-01-10T02:16:46Z" level=info msg="SQLite database integrity check passed"
time="2026-01-10T02:16:46Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
time="2026-01-10T02:16:46Z" level=info msg="SQLite database integrity check passed"
main_test.go:171: Missing table for model *models.SecurityConfig
main_test.go:171: Missing table for model *models.SecurityDecision
main_test.go:171: Missing table for model *models.SecurityAudit
main_test.go:171: Missing table for model *models.SecurityRuleSet
main_test.go:171: Missing table for model *models.CrowdsecPresetEvent
main_test.go:171: Missing table for model *models.CrowdsecConsoleEnrollment
--- PASS: TestStartupVerification_MissingTables (0.06s)
PASS
coverage: 0.0% of statements
ok github.com/Wikid82/charon/backend/cmd/api (cached) coverage: 0.0% of statements
=== RUN TestSeedMain_Smoke
{"level":"info","msg":"✓ Database migrated successfully","time":"2026-01-10T02:16:43Z"}
{"level":"info","msg":"✓ Created remote server: Local Docker Registry (localhost:5000)","server":"Local Docker Registry","time":"2026-01-10T02:16:43Z"}
{"level":"info","msg":"✓ Created remote server: Development API Server (192.168.1.100:8080)","server":"Development API Server","time":"2026-01-10T02:16:43Z"}
{"level":"info","msg":"✓ Created remote server: Staging Web App (staging.internal:3000)","server":"Staging Web App","time":"2026-01-10T02:16:43Z"}
{"level":"info","msg":"✓ Created remote server: Database Admin (localhost:8081)","server":"Database Admin","time":"2026-01-10T02:16:43Z"}
{"host":"app.local.dev","level":"info","msg":"✓ Created proxy host: app.local.dev -\u003e http://localhost:3000","time":"2026-01-10T02:16:43Z"}
{"host":"api.local.dev","level":"info","msg":"✓ Created proxy host: api.local.dev -\u003e http://192.168.1.100:8080","time":"2026-01-10T02:16:43Z"}
{"host":"docker.local.dev","level":"info","msg":"✓ Created proxy host: docker.local.dev -\u003e http://localhost:5000","time":"2026-01-10T02:16:43Z"}
{"level":"info","msg":"✓ Created setting: app_name = Charon","setting":"app_name","time":"2026-01-10T02:16:43Z"}
{"level":"info","msg":"✓ Created setting: default_scheme = http","setting":"default_scheme","time":"2026-01-10T02:16:43Z"}
{"level":"info","msg":"✓ Created setting: enable_ssl_by_default = false","setting":"enable_ssl_by_default","time":"2026-01-10T02:16:43Z"}
{"level":"info","msg":"✓ Created default user: admin@localhost","time":"2026-01-10T02:16:43Z","user":"admin@localhost"}
{"level":"info","msg":"\n✓ Database seeding completed successfully!","time":"2026-01-10T02:16:43Z"}
{"level":"info","msg":" You can now start the application and see sample data.","time":"2026-01-10T02:16:43Z"}
--- PASS: TestSeedMain_Smoke (0.28s)
PASS
coverage: 63.2% of statements
ok github.com/Wikid82/charon/backend/cmd/seed (cached) coverage: 63.2% of statements
? github.com/Wikid82/charon/backend/integration [no test files]
=== RUN TestAccessListHandler_SetGeoIPService
--- PASS: TestAccessListHandler_SetGeoIPService (0.01s)
=== RUN TestAccessListHandler_SetGeoIPService_Nil
--- PASS: TestAccessListHandler_SetGeoIPService_Nil (0.01s)
=== RUN TestAccessListHandler_Get_InvalidID
--- PASS: TestAccessListHandler_Get_InvalidID (0.03s)
=== RUN TestAccessListHandler_Update_InvalidID
--- PASS: TestAccessListHandler_Update_InvalidID (0.02s)
=== RUN TestAccessListHandler_Update_InvalidJSON
--- PASS: TestAccessListHandler_Update_InvalidJSON (0.02s)
=== RUN TestAccessListHandler_Delete_InvalidID
--- PASS: TestAccessListHandler_Delete_InvalidID (0.02s)
=== RUN TestAccessListHandler_TestIP_InvalidID
--- PASS: TestAccessListHandler_TestIP_InvalidID (0.02s)
=== RUN TestAccessListHandler_TestIP_MissingIPAddress
--- PASS: TestAccessListHandler_TestIP_MissingIPAddress (0.02s)
=== RUN TestAccessListHandler_List_DBError
2026/01/10 02:17:36 /projects/Charon/backend/internal/services/access_list_service.go:129 no such table: access_lists
[1.585ms] [rows:0] SELECT * FROM `access_lists` ORDER BY updated_at desc
--- PASS: TestAccessListHandler_List_DBError (0.00s)
=== RUN TestAccessListHandler_Get_DBError
2026/01/10 02:17:36 /projects/Charon/backend/internal/services/access_list_service.go:105 no such table: access_lists
[2.493ms] [rows:0] SELECT * FROM `access_lists` WHERE `access_lists`.`id` = 1 ORDER BY `access_lists`.`id` LIMIT 1
--- PASS: TestAccessListHandler_Get_DBError (0.00s)
=== RUN TestAccessListHandler_Delete_InternalError
2026/01/10 02:17:36 /projects/Charon/backend/internal/services/access_list_service.go:162 no such table: proxy_hosts
[10.015ms] [rows:0] SELECT count(*) FROM `proxy_hosts` WHERE access_list_id = 1
--- PASS: TestAccessListHandler_Delete_InternalError (0.01s)
=== RUN TestAccessListHandler_Update_InvalidType
--- PASS: TestAccessListHandler_Update_InvalidType (0.03s)
=== RUN TestAccessListHandler_Create_InvalidJSON
--- PASS: TestAccessListHandler_Create_InvalidJSON (0.04s)
=== RUN TestAccessListHandler_TestIP_Blacklist
--- PASS: TestAccessListHandler_TestIP_Blacklist (0.03s)
=== RUN TestAccessListHandler_TestIP_GeoWhitelist
--- PASS: TestAccessListHandler_TestIP_GeoWhitelist (0.03s)
=== RUN TestAccessListHandler_TestIP_LocalNetworkOnly
--- PASS: TestAccessListHandler_TestIP_LocalNetworkOnly (0.02s)
=== RUN TestAccessListHandler_TestIP_InternalError
2026/01/10 02:17:36 /projects/Charon/backend/internal/services/access_list_service.go:105 no such table: access_lists
[0.993ms] [rows:0] SELECT * FROM `access_lists` WHERE `access_lists`.`id` = 1 ORDER BY `access_lists`.`id` LIMIT 1
--- PASS: TestAccessListHandler_TestIP_InternalError (0.00s)
=== RUN TestAccessListHandler_Create
=== RUN TestAccessListHandler_Create/create_whitelist_successfully
=== RUN TestAccessListHandler_Create/create_geo_whitelist_successfully
=== RUN TestAccessListHandler_Create/create_local_network_only
=== RUN TestAccessListHandler_Create/fail_with_invalid_type
=== RUN TestAccessListHandler_Create/fail_with_missing_name
--- PASS: TestAccessListHandler_Create (0.02s)
--- PASS: TestAccessListHandler_Create/create_whitelist_successfully (0.00s)
--- PASS: TestAccessListHandler_Create/create_geo_whitelist_successfully (0.00s)
--- PASS: TestAccessListHandler_Create/create_local_network_only (0.00s)
--- PASS: TestAccessListHandler_Create/fail_with_invalid_type (0.00s)
--- PASS: TestAccessListHandler_Create/fail_with_missing_name (0.00s)
=== RUN TestAccessListHandler_List
--- PASS: TestAccessListHandler_List (0.02s)
=== RUN TestAccessListHandler_Get
=== RUN TestAccessListHandler_Get/get_existing_ACL
=== RUN TestAccessListHandler_Get/get_non-existent_ACL
2026/01/10 02:17:36 /projects/Charon/backend/internal/services/access_list_service.go:105 record not found
[0.120ms] [rows:0] SELECT * FROM `access_lists` WHERE `access_lists`.`id` = 9999 ORDER BY `access_lists`.`id` LIMIT 1
--- PASS: TestAccessListHandler_Get (0.02s)
--- PASS: TestAccessListHandler_Get/get_existing_ACL (0.00s)
--- PASS: TestAccessListHandler_Get/get_non-existent_ACL (0.00s)
=== RUN TestAccessListHandler_Update
=== RUN TestAccessListHandler_Update/update_successfully
=== RUN TestAccessListHandler_Update/update_non-existent_ACL
2026/01/10 02:17:36 /projects/Charon/backend/internal/services/access_list_service.go:105 record not found
[0.098ms] [rows:0] SELECT * FROM `access_lists` WHERE `access_lists`.`id` = 9999 ORDER BY `access_lists`.`id` LIMIT 1
--- PASS: TestAccessListHandler_Update (0.03s)
--- PASS: TestAccessListHandler_Update/update_successfully (0.00s)
--- PASS: TestAccessListHandler_Update/update_non-existent_ACL (0.00s)
=== RUN TestAccessListHandler_Delete
=== RUN TestAccessListHandler_Delete/delete_successfully
=== RUN TestAccessListHandler_Delete/fail_to_delete_ACL_in_use
=== RUN TestAccessListHandler_Delete/delete_non-existent_ACL
--- PASS: TestAccessListHandler_Delete (0.05s)
--- PASS: TestAccessListHandler_Delete/delete_successfully (0.00s)
--- PASS: TestAccessListHandler_Delete/fail_to_delete_ACL_in_use (0.00s)
--- PASS: TestAccessListHandler_Delete/delete_non-existent_ACL (0.00s)
=== RUN TestAccessListHandler_TestIP
=== RUN TestAccessListHandler_TestIP/test_IP_in_whitelist
=== RUN TestAccessListHandler_TestIP/test_IP_not_in_whitelist
=== RUN TestAccessListHandler_TestIP/test_invalid_IP
=== RUN TestAccessListHandler_TestIP/test_non-existent_ACL
2026/01/10 02:17:36 /projects/Charon/backend/internal/services/access_list_service.go:105 record not found
[0.074ms] [rows:0] SELECT * FROM `access_lists` WHERE `access_lists`.`id` = 9999 ORDER BY `access_lists`.`id` LIMIT 1
--- PASS: TestAccessListHandler_TestIP (0.04s)
--- PASS: TestAccessListHandler_TestIP/test_IP_in_whitelist (0.00s)
--- PASS: TestAccessListHandler_TestIP/test_IP_not_in_whitelist (0.00s)
--- PASS: TestAccessListHandler_TestIP/test_invalid_IP (0.00s)
--- PASS: TestAccessListHandler_TestIP/test_non-existent_ACL (0.00s)
=== RUN TestAccessListHandler_GetTemplates
--- PASS: TestAccessListHandler_GetTemplates (0.02s)
=== RUN TestImportHandler_Commit_InvalidJSON
--- PASS: TestImportHandler_Commit_InvalidJSON (0.03s)
=== RUN TestImportHandler_Commit_InvalidSessionUUID
--- PASS: TestImportHandler_Commit_InvalidSessionUUID (0.03s)
=== RUN TestImportHandler_Commit_SessionNotFound
--- PASS: TestImportHandler_Commit_SessionNotFound (0.05s)
=== RUN TestRemoteServerHandler_TestConnection_Unreachable
--- PASS: TestRemoteServerHandler_TestConnection_Unreachable (5.01s)
=== RUN TestSecurityHandler_GetConfig_InternalError
--- PASS: TestSecurityHandler_GetConfig_InternalError (0.01s)
=== RUN TestSecurityHandler_UpdateConfig_ApplyCaddyError
--- PASS: TestSecurityHandler_UpdateConfig_ApplyCaddyError (0.01s)
=== RUN TestSecurityHandler_GenerateBreakGlass_Error
--- PASS: TestSecurityHandler_GenerateBreakGlass_Error (0.75s)
=== RUN TestSecurityHandler_ListDecisions_Error
--- PASS: TestSecurityHandler_ListDecisions_Error (0.01s)
=== RUN TestSecurityHandler_ListRuleSets_Error
--- PASS: TestSecurityHandler_ListRuleSets_Error (0.01s)
=== RUN TestSecurityHandler_UpsertRuleSet_Error
--- PASS: TestSecurityHandler_UpsertRuleSet_Error (0.01s)
=== RUN TestSecurityHandler_CreateDecision_LogError
--- PASS: TestSecurityHandler_CreateDecision_LogError (0.01s)
=== RUN TestSecurityHandler_DeleteRuleSet_Error
--- PASS: TestSecurityHandler_DeleteRuleSet_Error (0.01s)
=== RUN TestCrowdsec_ImportConfig_EmptyUpload
--- PASS: TestCrowdsec_ImportConfig_EmptyUpload (0.00s)
=== RUN TestBackupHandler_List_DBError
time="2026-01-10T02:17:42Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestBackupHandler_List_DBError (0.00s)
=== RUN TestImportHandler_UploadMulti_InvalidJSON
--- PASS: TestImportHandler_UploadMulti_InvalidJSON (0.02s)
=== RUN TestImportHandler_UploadMulti_MissingCaddyfile
--- PASS: TestImportHandler_UploadMulti_MissingCaddyfile (0.01s)
=== RUN TestImportHandler_UploadMulti_EmptyContent
--- PASS: TestImportHandler_UploadMulti_EmptyContent (0.02s)
=== RUN TestImportHandler_UploadMulti_PathTraversal
--- PASS: TestImportHandler_UploadMulti_PathTraversal (0.02s)
=== RUN TestLogsHandler_Download_PathTraversal
--- PASS: TestLogsHandler_Download_PathTraversal (0.00s)
=== RUN TestLogsHandler_Download_NotFound
--- PASS: TestLogsHandler_Download_NotFound (0.00s)
=== RUN TestLogsHandler_Download_Success
--- PASS: TestLogsHandler_Download_Success (0.01s)
=== RUN TestImportHandler_Upload_InvalidJSON
time="2026-01-10T02:17:42Z" level=error msg="Import Upload: failed to bind JSON" error="invalid character 'o' in literal null (expecting 'u')"
--- PASS: TestImportHandler_Upload_InvalidJSON (0.02s)
=== RUN TestImportHandler_Upload_EmptyContent
time="2026-01-10T02:17:42Z" level=error msg="Import Upload: failed to bind JSON" error="Key: 'Content' Error:Field validation for 'Content' failed on the 'required' tag"
--- PASS: TestImportHandler_Upload_EmptyContent (0.02s)
=== RUN TestBackupHandler_List_ServiceError
--- PASS: TestBackupHandler_List_ServiceError (0.00s)
=== RUN TestBackupHandler_Delete_PathTraversal
time="2026-01-10T02:17:42Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestBackupHandler_Delete_PathTraversal (0.00s)
=== RUN TestBackupHandler_Delete_InternalError2
time="2026-01-10T02:17:42Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestBackupHandler_Delete_InternalError2 (0.00s)
=== RUN TestRemoteServerHandler_TestConnection_NotFound2
--- PASS: TestRemoteServerHandler_TestConnection_NotFound2 (0.00s)
=== RUN TestRemoteServerHandler_TestConnectionCustom_Unreachable2
--- PASS: TestRemoteServerHandler_TestConnectionCustom_Unreachable2 (5.01s)
=== RUN TestAuthHandler_Register_InvalidJSON
--- PASS: TestAuthHandler_Register_InvalidJSON (0.02s)
=== RUN TestHealthHandler_Basic
--- PASS: TestHealthHandler_Basic (0.00s)
=== RUN TestBackupHandler_Create_Error
time="2026-01-10T02:17:47Z" level=error msg="Failed to create backup" action=create_backup error="database file not found: /tmp/TestBackupHandler_Create_Error62628796/001/data/charon.db"
time="2026-01-10T02:17:47Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestBackupHandler_Create_Error (0.00s)
=== RUN TestSettingsHandler_GetSettings_Error
--- PASS: TestSettingsHandler_GetSettings_Error (0.00s)
=== RUN TestSettingsHandler_UpdateSetting_InvalidJSON
--- PASS: TestSettingsHandler_UpdateSetting_InvalidJSON (0.00s)
=== RUN TestRemoteServerHandler_TestConnection_Reachable
--- PASS: TestRemoteServerHandler_TestConnection_Reachable (0.01s)
=== RUN TestRemoteServerHandler_TestConnection_EmptyHost
--- PASS: TestRemoteServerHandler_TestConnection_EmptyHost (0.00s)
=== RUN TestImportHandler_UploadMulti_ValidCaddyfile
time="2026-01-10T02:17:47Z" level=error msg="Import UploadMulti: import failed" error="caddy adapt failed: exec: \"caddy\": executable file not found in $PATH (output: )" mainCaddyfile=Caddyfile preview="example.com { reverse_proxy localhost:8080 }"
--- PASS: TestImportHandler_UploadMulti_ValidCaddyfile (0.02s)
=== RUN TestImportHandler_UploadMulti_SubdirFile
time="2026-01-10T02:17:47Z" level=error msg="Import UploadMulti: import failed" error="caddy adapt failed: exec: \"caddy\": executable file not found in $PATH (output: )" mainCaddyfile=Caddyfile preview="import sites/*"
--- PASS: TestImportHandler_UploadMulti_SubdirFile (0.02s)
=== RUN Test_getLocalIP_Additional
additional_handlers_test.go:29: getLocalIP returned: 217.15.170.144
--- PASS: Test_getLocalIP_Additional (0.00s)
=== RUN TestFeatureFlagsHandler_GetFlags_FromShortEnv
2026/01/10 02:17:47 /projects/Charon/backend/internal/api/handlers/feature_flags_handler.go:48 record not found
[0.064ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:47 /projects/Charon/backend/internal/api/handlers/feature_flags_handler.go:48 record not found
[0.056ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.uptime.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:47 /projects/Charon/backend/internal/api/handlers/feature_flags_handler.go:48 record not found
[0.094ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.crowdsec.console_enrollment" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestFeatureFlagsHandler_GetFlags_FromShortEnv (0.00s)
=== RUN TestFeatureFlagsHandler_UpdateFlags_UnknownFlag
--- PASS: TestFeatureFlagsHandler_UpdateFlags_UnknownFlag (0.00s)
=== RUN TestDomainHandler_List_Additional
--- PASS: TestDomainHandler_List_Additional (0.00s)
=== RUN TestDomainHandler_List_Empty_Additional
--- PASS: TestDomainHandler_List_Empty_Additional (0.00s)
=== RUN TestDomainHandler_Create_Additional
--- PASS: TestDomainHandler_Create_Additional (0.00s)
=== RUN TestDomainHandler_Create_MissingName_Additional
--- PASS: TestDomainHandler_Create_MissingName_Additional (0.00s)
=== RUN TestDomainHandler_Delete_Additional
--- PASS: TestDomainHandler_Delete_Additional (0.00s)
=== RUN TestDomainHandler_Delete_NotFound_Additional
2026/01/10 02:17:47 /projects/Charon/backend/internal/api/handlers/domain_handler.go:73 record not found
[0.094ms] [rows:0] SELECT * FROM `domains` WHERE uuid = "nonexistent" AND `domains`.`deleted_at` IS NULL ORDER BY `domains`.`id` LIMIT 1
--- PASS: TestDomainHandler_Delete_NotFound_Additional (0.00s)
=== RUN TestNotificationHandler_List_Additional
--- PASS: TestNotificationHandler_List_Additional (0.00s)
=== RUN TestNotificationHandler_MarkAsRead_Additional
--- PASS: TestNotificationHandler_MarkAsRead_Additional (0.00s)
=== RUN TestNotificationHandler_MarkAllAsRead_Additional
--- PASS: TestNotificationHandler_MarkAllAsRead_Additional (0.00s)
=== RUN TestCrowdsecExec_NewDefaultCrowdsecExecutor
--- PASS: TestCrowdsecExec_NewDefaultCrowdsecExecutor (0.00s)
=== RUN TestDefaultCrowdsecExecutor_isCrowdSecProcess
--- PASS: TestDefaultCrowdsecExecutor_isCrowdSecProcess (0.00s)
=== RUN TestDefaultCrowdsecExecutor_pidFile
--- PASS: TestDefaultCrowdsecExecutor_pidFile (0.00s)
=== RUN TestDefaultCrowdsecExecutor_Status
--- PASS: TestDefaultCrowdsecExecutor_Status (0.00s)
=== RUN Test_isSafePathUnderBase_Additional
=== RUN Test_isSafePathUnderBase_Additional/valid_relative_path_under_base
=== RUN Test_isSafePathUnderBase_Additional/valid_relative_path_with_subdir
=== RUN Test_isSafePathUnderBase_Additional/path_traversal_attempt
=== RUN Test_isSafePathUnderBase_Additional/empty_path
--- PASS: Test_isSafePathUnderBase_Additional (0.00s)
--- PASS: Test_isSafePathUnderBase_Additional/valid_relative_path_under_base (0.00s)
--- PASS: Test_isSafePathUnderBase_Additional/valid_relative_path_with_subdir (0.00s)
--- PASS: Test_isSafePathUnderBase_Additional/path_traversal_attempt (0.00s)
--- PASS: Test_isSafePathUnderBase_Additional/empty_path (0.00s)
=== RUN TestAuditLogHandler_List
=== RUN TestAuditLogHandler_List/List_all_audit_logs
=== RUN TestAuditLogHandler_List/Filter_by_actor
=== RUN TestAuditLogHandler_List/Filter_by_action
=== RUN TestAuditLogHandler_List/Filter_by_event_category
=== RUN TestAuditLogHandler_List/Pagination_-_page_1,_limit_1
--- PASS: TestAuditLogHandler_List (0.01s)
--- PASS: TestAuditLogHandler_List/List_all_audit_logs (0.00s)
--- PASS: TestAuditLogHandler_List/Filter_by_actor (0.00s)
--- PASS: TestAuditLogHandler_List/Filter_by_action (0.00s)
--- PASS: TestAuditLogHandler_List/Filter_by_event_category (0.00s)
--- PASS: TestAuditLogHandler_List/Pagination_-_page_1,_limit_1 (0.00s)
=== RUN TestAuditLogHandler_Get
=== RUN TestAuditLogHandler_Get/Get_existing_audit_log
=== RUN TestAuditLogHandler_Get/Get_non-existent_audit_log
2026/01/10 02:17:47 /projects/Charon/backend/internal/services/security_service.go:321 record not found
[0.092ms] [rows:0] SELECT * FROM `security_audits` WHERE uuid = "non-existent-uuid" ORDER BY `security_audits`.`id` LIMIT 1
=== RUN TestAuditLogHandler_Get/Get_with_empty_UUID
--- PASS: TestAuditLogHandler_Get (0.00s)
--- PASS: TestAuditLogHandler_Get/Get_existing_audit_log (0.00s)
--- PASS: TestAuditLogHandler_Get/Get_non-existent_audit_log (0.00s)
--- PASS: TestAuditLogHandler_Get/Get_with_empty_UUID (0.00s)
=== RUN TestAuditLogHandler_ListByProvider
=== RUN TestAuditLogHandler_ListByProvider/List_audit_logs_for_provider
=== RUN TestAuditLogHandler_ListByProvider/List_audit_logs_for_non-existent_provider
=== RUN TestAuditLogHandler_ListByProvider/Invalid_provider_ID
--- PASS: TestAuditLogHandler_ListByProvider (0.00s)
--- PASS: TestAuditLogHandler_ListByProvider/List_audit_logs_for_provider (0.00s)
--- PASS: TestAuditLogHandler_ListByProvider/List_audit_logs_for_non-existent_provider (0.00s)
--- PASS: TestAuditLogHandler_ListByProvider/Invalid_provider_ID (0.00s)
=== RUN TestAuditLogHandler_ListWithDateFilters
=== RUN TestAuditLogHandler_ListWithDateFilters/Filter_by_start_date
=== RUN TestAuditLogHandler_ListWithDateFilters/Filter_by_end_date
=== RUN TestAuditLogHandler_ListWithDateFilters/Filter_by_date_range
--- PASS: TestAuditLogHandler_ListWithDateFilters (0.01s)
--- PASS: TestAuditLogHandler_ListWithDateFilters/Filter_by_start_date (0.00s)
--- PASS: TestAuditLogHandler_ListWithDateFilters/Filter_by_end_date (0.00s)
--- PASS: TestAuditLogHandler_ListWithDateFilters/Filter_by_date_range (0.00s)
=== RUN TestAuditLogHandler_ServiceErrors
=== RUN TestAuditLogHandler_ServiceErrors/List_fails_when_database_unavailable
2026/01/10 02:17:47 /projects/Charon/backend/internal/services/security_service.go:305 sql: database is closed
[0.026ms] [rows:0] SELECT count(*) FROM `security_audits`
=== RUN TestAuditLogHandler_ServiceErrors/ListByProvider_fails_when_database_unavailable
2026/01/10 02:17:47 /projects/Charon/backend/internal/services/security_service.go:339 sql: database is closed
[0.039ms] [rows:0] SELECT count(*) FROM `security_audits` WHERE event_category = "dns_provider" AND resource_id = 123
=== RUN TestAuditLogHandler_ServiceErrors/Get_fails_when_database_unavailable
2026/01/10 02:17:47 /projects/Charon/backend/internal/services/security_service.go:321 sql: database is closed
[0.041ms] [rows:0] SELECT * FROM `security_audits` WHERE uuid = "some-uuid" ORDER BY `security_audits`.`id` LIMIT 1
--- PASS: TestAuditLogHandler_ServiceErrors (0.00s)
--- PASS: TestAuditLogHandler_ServiceErrors/List_fails_when_database_unavailable (0.00s)
--- PASS: TestAuditLogHandler_ServiceErrors/ListByProvider_fails_when_database_unavailable (0.00s)
--- PASS: TestAuditLogHandler_ServiceErrors/Get_fails_when_database_unavailable (0.00s)
=== RUN TestAuditLogHandler_List_PaginationBoundaryEdgeCases
=== RUN TestAuditLogHandler_List_PaginationBoundaryEdgeCases/Negative_page_defaults_to_1
=== RUN TestAuditLogHandler_List_PaginationBoundaryEdgeCases/Zero_page_defaults_to_1
=== RUN TestAuditLogHandler_List_PaginationBoundaryEdgeCases/Negative_limit_defaults_to_50
=== RUN TestAuditLogHandler_List_PaginationBoundaryEdgeCases/Zero_limit_defaults_to_50
=== RUN TestAuditLogHandler_List_PaginationBoundaryEdgeCases/Limit_over_100_defaults_to_50
=== RUN TestAuditLogHandler_List_PaginationBoundaryEdgeCases/Non-numeric_page_ignored
=== RUN TestAuditLogHandler_List_PaginationBoundaryEdgeCases/Non-numeric_limit_ignored
--- PASS: TestAuditLogHandler_List_PaginationBoundaryEdgeCases (0.01s)
--- PASS: TestAuditLogHandler_List_PaginationBoundaryEdgeCases/Negative_page_defaults_to_1 (0.00s)
--- PASS: TestAuditLogHandler_List_PaginationBoundaryEdgeCases/Zero_page_defaults_to_1 (0.00s)
--- PASS: TestAuditLogHandler_List_PaginationBoundaryEdgeCases/Negative_limit_defaults_to_50 (0.00s)
--- PASS: TestAuditLogHandler_List_PaginationBoundaryEdgeCases/Zero_limit_defaults_to_50 (0.00s)
--- PASS: TestAuditLogHandler_List_PaginationBoundaryEdgeCases/Limit_over_100_defaults_to_50 (0.00s)
--- PASS: TestAuditLogHandler_List_PaginationBoundaryEdgeCases/Non-numeric_page_ignored (0.00s)
--- PASS: TestAuditLogHandler_List_PaginationBoundaryEdgeCases/Non-numeric_limit_ignored (0.00s)
=== RUN TestAuditLogHandler_ListByProvider_PaginationBoundaryEdgeCases
=== RUN TestAuditLogHandler_ListByProvider_PaginationBoundaryEdgeCases/Negative_page_defaults_to_1
=== RUN TestAuditLogHandler_ListByProvider_PaginationBoundaryEdgeCases/Zero_limit_defaults_to_50
=== RUN TestAuditLogHandler_ListByProvider_PaginationBoundaryEdgeCases/Limit_over_100_defaults_to_50
--- PASS: TestAuditLogHandler_ListByProvider_PaginationBoundaryEdgeCases (0.01s)
--- PASS: TestAuditLogHandler_ListByProvider_PaginationBoundaryEdgeCases/Negative_page_defaults_to_1 (0.00s)
--- PASS: TestAuditLogHandler_ListByProvider_PaginationBoundaryEdgeCases/Zero_limit_defaults_to_50 (0.00s)
--- PASS: TestAuditLogHandler_ListByProvider_PaginationBoundaryEdgeCases/Limit_over_100_defaults_to_50 (0.00s)
=== RUN TestAuditLogHandler_List_InvalidDateFormats
=== RUN TestAuditLogHandler_List_InvalidDateFormats/Invalid_start_date_format
=== RUN TestAuditLogHandler_List_InvalidDateFormats/Invalid_end_date_format
=== RUN TestAuditLogHandler_List_InvalidDateFormats/Both_dates_invalid
--- PASS: TestAuditLogHandler_List_InvalidDateFormats (0.01s)
--- PASS: TestAuditLogHandler_List_InvalidDateFormats/Invalid_start_date_format (0.00s)
--- PASS: TestAuditLogHandler_List_InvalidDateFormats/Invalid_end_date_format (0.00s)
--- PASS: TestAuditLogHandler_List_InvalidDateFormats/Both_dates_invalid (0.00s)
=== RUN TestAuditLogHandler_Get_InternalError
2026/01/10 02:17:47 /projects/Charon/backend/internal/services/security_service.go:321 sql: database is closed
[0.033ms] [rows:0] SELECT * FROM `security_audits` WHERE uuid = "test-uuid" ORDER BY `security_audits`.`id` LIMIT 1
--- PASS: TestAuditLogHandler_Get_InternalError (0.00s)
=== RUN TestAuthHandler_Login
=== PAUSE TestAuthHandler_Login
=== RUN TestSetSecureCookie_HTTPS_Strict
--- PASS: TestSetSecureCookie_HTTPS_Strict (0.00s)
=== RUN TestSetSecureCookie_HTTP_Lax
=== PAUSE TestSetSecureCookie_HTTP_Lax
=== RUN TestAuthHandler_Login_Errors
=== PAUSE TestAuthHandler_Login_Errors
=== RUN TestAuthHandler_Register
=== PAUSE TestAuthHandler_Register
=== RUN TestAuthHandler_Register_Duplicate
=== PAUSE TestAuthHandler_Register_Duplicate
=== RUN TestAuthHandler_Logout
=== PAUSE TestAuthHandler_Logout
=== RUN TestAuthHandler_Me
=== PAUSE TestAuthHandler_Me
=== RUN TestAuthHandler_Me_NotFound
=== PAUSE TestAuthHandler_Me_NotFound
=== RUN TestAuthHandler_ChangePassword
=== PAUSE TestAuthHandler_ChangePassword
=== RUN TestAuthHandler_ChangePassword_WrongOld
=== PAUSE TestAuthHandler_ChangePassword_WrongOld
=== RUN TestAuthHandler_ChangePassword_Errors
=== PAUSE TestAuthHandler_ChangePassword_Errors
=== RUN TestNewAuthHandlerWithDB
=== PAUSE TestNewAuthHandlerWithDB
=== RUN TestAuthHandler_Verify_NoCookie
=== PAUSE TestAuthHandler_Verify_NoCookie
=== RUN TestAuthHandler_Verify_InvalidToken
=== PAUSE TestAuthHandler_Verify_InvalidToken
=== RUN TestAuthHandler_Verify_ValidToken
=== PAUSE TestAuthHandler_Verify_ValidToken
=== RUN TestAuthHandler_Verify_BearerToken
=== PAUSE TestAuthHandler_Verify_BearerToken
=== RUN TestAuthHandler_Verify_DisabledUser
=== PAUSE TestAuthHandler_Verify_DisabledUser
=== RUN TestAuthHandler_Verify_ForwardAuthDenied
=== PAUSE TestAuthHandler_Verify_ForwardAuthDenied
=== RUN TestAuthHandler_VerifyStatus_NotAuthenticated
=== PAUSE TestAuthHandler_VerifyStatus_NotAuthenticated
=== RUN TestAuthHandler_VerifyStatus_InvalidToken
=== PAUSE TestAuthHandler_VerifyStatus_InvalidToken
=== RUN TestAuthHandler_VerifyStatus_Authenticated
=== PAUSE TestAuthHandler_VerifyStatus_Authenticated
=== RUN TestAuthHandler_VerifyStatus_DisabledUser
=== PAUSE TestAuthHandler_VerifyStatus_DisabledUser
=== RUN TestAuthHandler_GetAccessibleHosts_Unauthorized
=== PAUSE TestAuthHandler_GetAccessibleHosts_Unauthorized
=== RUN TestAuthHandler_GetAccessibleHosts_AllowAll
=== PAUSE TestAuthHandler_GetAccessibleHosts_AllowAll
=== RUN TestAuthHandler_GetAccessibleHosts_DenyAll
=== PAUSE TestAuthHandler_GetAccessibleHosts_DenyAll
=== RUN TestAuthHandler_GetAccessibleHosts_PermittedHosts
=== PAUSE TestAuthHandler_GetAccessibleHosts_PermittedHosts
=== RUN TestAuthHandler_GetAccessibleHosts_UserNotFound
=== PAUSE TestAuthHandler_GetAccessibleHosts_UserNotFound
=== RUN TestAuthHandler_CheckHostAccess_Unauthorized
=== PAUSE TestAuthHandler_CheckHostAccess_Unauthorized
=== RUN TestAuthHandler_CheckHostAccess_InvalidHostID
=== PAUSE TestAuthHandler_CheckHostAccess_InvalidHostID
=== RUN TestAuthHandler_CheckHostAccess_Allowed
=== PAUSE TestAuthHandler_CheckHostAccess_Allowed
=== RUN TestAuthHandler_CheckHostAccess_Denied
=== PAUSE TestAuthHandler_CheckHostAccess_Denied
=== RUN TestBackupHandlerSanitizesFilename
--- PASS: TestBackupHandlerSanitizesFilename (0.00s)
=== RUN TestBackupLifecycle
--- PASS: TestBackupLifecycle (0.01s)
=== RUN TestBackupHandler_Errors
--- PASS: TestBackupHandler_Errors (0.00s)
=== RUN TestBackupHandler_List_Success
--- PASS: TestBackupHandler_List_Success (0.00s)
=== RUN TestBackupHandler_Create_Success
--- PASS: TestBackupHandler_Create_Success (0.00s)
=== RUN TestBackupHandler_Download_Success
--- PASS: TestBackupHandler_Download_Success (0.00s)
=== RUN TestBackupHandler_PathTraversal
--- PASS: TestBackupHandler_PathTraversal (0.00s)
=== RUN TestBackupHandler_Download_InvalidPath
--- PASS: TestBackupHandler_Download_InvalidPath (0.00s)
=== RUN TestBackupHandler_Create_ServiceError
--- PASS: TestBackupHandler_Create_ServiceError (0.00s)
=== RUN TestBackupHandler_Delete_InternalError
--- PASS: TestBackupHandler_Delete_InternalError (0.00s)
=== RUN TestBackupHandler_Restore_InternalError
--- PASS: TestBackupHandler_Restore_InternalError (0.00s)
=== RUN TestCerberusLogsHandler_NewHandler
=== PAUSE TestCerberusLogsHandler_NewHandler
=== RUN TestCerberusLogsHandler_SuccessfulConnection
=== PAUSE TestCerberusLogsHandler_SuccessfulConnection
=== RUN TestCerberusLogsHandler_ReceiveLogEntries
=== PAUSE TestCerberusLogsHandler_ReceiveLogEntries
=== RUN TestCerberusLogsHandler_SourceFilter
=== PAUSE TestCerberusLogsHandler_SourceFilter
=== RUN TestCerberusLogsHandler_BlockedOnlyFilter
=== PAUSE TestCerberusLogsHandler_BlockedOnlyFilter
=== RUN TestCerberusLogsHandler_IPFilter
=== PAUSE TestCerberusLogsHandler_IPFilter
=== RUN TestCerberusLogsHandler_ClientDisconnect
=== PAUSE TestCerberusLogsHandler_ClientDisconnect
=== RUN TestCerberusLogsHandler_MultipleClients
=== PAUSE TestCerberusLogsHandler_MultipleClients
=== RUN TestCerberusLogsHandler_UpgradeFailure
=== PAUSE TestCerberusLogsHandler_UpgradeFailure
=== RUN TestCertificateHandler_List_DBError
2026/01/10 02:17:47 /projects/Charon/backend/internal/services/certificate_service.go:198 no such table: ssl_certificates
[3.273ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE provider LIKE "letsencrypt%"
2026/01/10 02:17:47 /projects/Charon/backend/internal/services/certificate_service.go:226 no such table: ssl_certificates
[0.033ms] [rows:0] SELECT * FROM `ssl_certificates`
2026/01/10 02:17:47 /projects/Charon/backend/internal/services/certificate_service.go:226 no such table: ssl_certificates
[0.032ms] [rows:0] SELECT * FROM `ssl_certificates`
2026/01/10 02:17:47 /projects/Charon/backend/internal/services/certificate_service.go:198 no such table: ssl_certificates
[0.044ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE provider LIKE "letsencrypt%"
2026/01/10 02:17:47 /projects/Charon/backend/internal/services/certificate_service.go:226 no such table: ssl_certificates
[0.031ms] [rows:0] SELECT * FROM `ssl_certificates`
--- PASS: TestCertificateHandler_List_DBError (0.00s)
=== RUN TestCertificateHandler_Delete_InvalidID
--- PASS: TestCertificateHandler_Delete_InvalidID (0.02s)
=== RUN TestCertificateHandler_Delete_NotFound
2026/01/10 02:17:47 /projects/Charon/backend/internal/services/certificate_service.go:410 record not found
[0.076ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE `ssl_certificates`.`id` = 9999 ORDER BY `ssl_certificates`.`id` LIMIT 1
--- PASS: TestCertificateHandler_Delete_NotFound (0.01s)
=== RUN TestCertificateHandler_Delete_NoBackupService
--- PASS: TestCertificateHandler_Delete_NoBackupService (0.21s)
=== RUN TestCertificateHandler_Delete_CheckUsageDBError
2026/01/10 02:17:48 /projects/Charon/backend/internal/services/certificate_service.go:392 no such table: proxy_hosts
[6.492ms] [rows:0] SELECT count(*) FROM `proxy_hosts` WHERE certificate_id = 1
2026/01/10 02:17:48 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[5.901ms] [rows:0] SELECT * FROM `proxy_hosts`
--- PASS: TestCertificateHandler_Delete_CheckUsageDBError (0.01s)
=== RUN TestCertificateHandler_List_WithCertificates
--- PASS: TestCertificateHandler_List_WithCertificates (0.01s)
=== RUN TestCertificateHandler_Delete_ZeroID
--- PASS: TestCertificateHandler_Delete_ZeroID (0.02s)
=== RUN TestCertificateHandler_Delete_RequiresAuth
--- PASS: TestCertificateHandler_Delete_RequiresAuth (0.01s)
=== RUN TestCertificateHandler_List_RequiresAuth
--- PASS: TestCertificateHandler_List_RequiresAuth (0.01s)
=== RUN TestCertificateHandler_Upload_RequiresAuth
--- PASS: TestCertificateHandler_Upload_RequiresAuth (0.02s)
=== RUN TestCertificateHandler_Delete_DiskSpaceCheck
--- PASS: TestCertificateHandler_Delete_DiskSpaceCheck (0.01s)
=== RUN TestCertificateHandler_Delete_NotificationRateLimiting
--- PASS: TestCertificateHandler_Delete_NotificationRateLimiting (0.02s)
=== RUN TestDeleteCertificate_InUse
--- PASS: TestDeleteCertificate_InUse (0.02s)
=== RUN TestDeleteCertificate_CreatesBackup
2026/01/10 02:17:48 /projects/Charon/backend/internal/api/handlers/certificate_handler_test.go:134 record not found
[0.090ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE `ssl_certificates`.`id` = 1 ORDER BY `ssl_certificates`.`id` LIMIT 1
--- PASS: TestDeleteCertificate_CreatesBackup (0.01s)
=== RUN TestDeleteCertificate_BackupFailure
--- PASS: TestDeleteCertificate_BackupFailure (0.02s)
=== RUN TestDeleteCertificate_InUse_NoBackup
--- PASS: TestDeleteCertificate_InUse_NoBackup (0.01s)
=== RUN TestCertificateHandler_List
--- PASS: TestCertificateHandler_List (0.01s)
=== RUN TestCertificateHandler_Upload_MissingName
--- PASS: TestCertificateHandler_Upload_MissingName (0.01s)
=== RUN TestCertificateHandler_Upload_MissingCertFile
--- PASS: TestCertificateHandler_Upload_MissingCertFile (0.02s)
=== RUN TestCertificateHandler_Upload_MissingKeyFile
--- PASS: TestCertificateHandler_Upload_MissingKeyFile (0.02s)
=== RUN TestCertificateHandler_Upload_Success
--- PASS: TestCertificateHandler_Upload_Success (0.05s)
=== RUN TestDeleteCertificate_InvalidID
--- PASS: TestDeleteCertificate_InvalidID (0.01s)
=== RUN TestDeleteCertificate_ZeroID
--- PASS: TestDeleteCertificate_ZeroID (0.02s)
=== RUN TestDeleteCertificate_LowDiskSpace
--- PASS: TestDeleteCertificate_LowDiskSpace (0.02s)
=== RUN TestDeleteCertificate_DiskSpaceCheckError
2026/01/10 02:17:48 /projects/Charon/backend/internal/services/certificate_service.go:198 database table is locked: ssl_certificates
[0.359ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE provider LIKE "letsencrypt%"
--- PASS: TestDeleteCertificate_DiskSpaceCheckError (0.02s)
=== RUN TestDeleteCertificate_UsageCheckError
2026/01/10 02:17:48 /projects/Charon/backend/internal/services/certificate_service.go:392 no such table: proxy_hosts
[8.346ms] [rows:0] SELECT count(*) FROM `proxy_hosts` WHERE certificate_id = 1
2026/01/10 02:17:48 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[7.932ms] [rows:0] SELECT * FROM `proxy_hosts`
--- PASS: TestDeleteCertificate_UsageCheckError (0.01s)
=== RUN TestDeleteCertificate_NotificationRateLimit
--- PASS: TestDeleteCertificate_NotificationRateLimit (0.12s)
=== RUN TestSafeIntToUint
=== RUN TestSafeIntToUint/ValidPositive
=== RUN TestSafeIntToUint/Zero
=== RUN TestSafeIntToUint/Negative
--- PASS: TestSafeIntToUint (0.00s)
--- PASS: TestSafeIntToUint/ValidPositive (0.00s)
--- PASS: TestSafeIntToUint/Zero (0.00s)
--- PASS: TestSafeIntToUint/Negative (0.00s)
=== RUN TestSafeFloat64ToUint
=== RUN TestSafeFloat64ToUint/ValidPositive
=== RUN TestSafeFloat64ToUint/Zero
=== RUN TestSafeFloat64ToUint/Negative
=== RUN TestSafeFloat64ToUint/NotInteger
--- PASS: TestSafeFloat64ToUint (0.00s)
--- PASS: TestSafeFloat64ToUint/ValidPositive (0.00s)
--- PASS: TestSafeFloat64ToUint/Zero (0.00s)
--- PASS: TestSafeFloat64ToUint/Negative (0.00s)
--- PASS: TestSafeFloat64ToUint/NotInteger (0.00s)
=== RUN Test_ttlRemainingSeconds
=== RUN Test_ttlRemainingSeconds/zero_retrievedAt_returns_nil
=== RUN Test_ttlRemainingSeconds/zero_ttl_returns_nil
=== RUN Test_ttlRemainingSeconds/negative_ttl_returns_nil
=== RUN Test_ttlRemainingSeconds/expired_ttl_returns_zero
=== RUN Test_ttlRemainingSeconds/valid_remaining_time_returns_positive
--- PASS: Test_ttlRemainingSeconds (0.00s)
--- PASS: Test_ttlRemainingSeconds/zero_retrievedAt_returns_nil (0.00s)
--- PASS: Test_ttlRemainingSeconds/zero_ttl_returns_nil (0.00s)
--- PASS: Test_ttlRemainingSeconds/negative_ttl_returns_nil (0.00s)
--- PASS: Test_ttlRemainingSeconds/expired_ttl_returns_zero (0.00s)
--- PASS: Test_ttlRemainingSeconds/valid_remaining_time_returns_positive (0.00s)
=== RUN Test_mapCrowdsecStatus
=== RUN Test_mapCrowdsecStatus/deadline_exceeded_returns_gateway_timeout
=== RUN Test_mapCrowdsecStatus/context_canceled_returns_gateway_timeout
=== RUN Test_mapCrowdsecStatus/other_error_returns_default_code
=== RUN Test_mapCrowdsecStatus/other_error_returns_bad_request_default
--- PASS: Test_mapCrowdsecStatus (0.00s)
--- PASS: Test_mapCrowdsecStatus/deadline_exceeded_returns_gateway_timeout (0.00s)
--- PASS: Test_mapCrowdsecStatus/context_canceled_returns_gateway_timeout (0.00s)
--- PASS: Test_mapCrowdsecStatus/other_error_returns_default_code (0.00s)
--- PASS: Test_mapCrowdsecStatus/other_error_returns_bad_request_default (0.00s)
=== RUN Test_actorFromContext
=== RUN Test_actorFromContext/with_userID_in_context
=== RUN Test_actorFromContext/without_userID_in_context
=== RUN Test_actorFromContext/with_string_userID
--- PASS: Test_actorFromContext (0.00s)
--- PASS: Test_actorFromContext/with_userID_in_context (0.00s)
--- PASS: Test_actorFromContext/without_userID_in_context (0.00s)
--- PASS: Test_actorFromContext/with_string_userID (0.00s)
=== RUN Test_hubEndpoints
=== RUN Test_hubEndpoints/nil_Hub_returns_nil
--- PASS: Test_hubEndpoints (0.00s)
--- PASS: Test_hubEndpoints/nil_Hub_returns_nil (0.00s)
=== RUN TestRealCommandExecutor_Execute
=== RUN TestRealCommandExecutor_Execute/successful_command
=== RUN TestRealCommandExecutor_Execute/failed_command
=== RUN TestRealCommandExecutor_Execute/context_cancellation
--- PASS: TestRealCommandExecutor_Execute (0.00s)
--- PASS: TestRealCommandExecutor_Execute/successful_command (0.00s)
--- PASS: TestRealCommandExecutor_Execute/failed_command (0.00s)
--- PASS: TestRealCommandExecutor_Execute/context_cancellation (0.00s)
=== RUN Test_isCerberusEnabled
=== RUN Test_isCerberusEnabled/returns_true_when_no_setting_exists_(default)
=== RUN Test_isCerberusEnabled/enabled_when_setting_is_true
=== RUN Test_isCerberusEnabled/disabled_when_setting_is_false
--- PASS: Test_isCerberusEnabled (0.00s)
--- PASS: Test_isCerberusEnabled/returns_true_when_no_setting_exists_(default) (0.00s)
--- PASS: Test_isCerberusEnabled/enabled_when_setting_is_true (0.00s)
--- PASS: Test_isCerberusEnabled/disabled_when_setting_is_false (0.00s)
=== RUN Test_isConsoleEnrollmentEnabled
=== RUN Test_isConsoleEnrollmentEnabled/disabled_when_no_setting_exists
=== RUN Test_isConsoleEnrollmentEnabled/enabled_when_setting_is_true
=== RUN Test_isConsoleEnrollmentEnabled/disabled_when_setting_is_false
--- PASS: Test_isConsoleEnrollmentEnabled (0.00s)
--- PASS: Test_isConsoleEnrollmentEnabled/disabled_when_no_setting_exists (0.00s)
--- PASS: Test_isConsoleEnrollmentEnabled/enabled_when_setting_is_true (0.00s)
--- PASS: Test_isConsoleEnrollmentEnabled/disabled_when_setting_is_false (0.00s)
=== RUN TestCrowdsecHandler_ExportConfig
--- PASS: TestCrowdsecHandler_ExportConfig (0.01s)
=== RUN TestCrowdsecHandler_CheckLAPIHealth
--- PASS: TestCrowdsecHandler_CheckLAPIHealth (0.00s)
=== RUN TestCrowdsecHandler_ConsoleStatus
--- PASS: TestCrowdsecHandler_ConsoleStatus (0.01s)
=== RUN TestCrowdsecHandler_ConsoleEnroll_Disabled
--- PASS: TestCrowdsecHandler_ConsoleEnroll_Disabled (0.00s)
=== RUN TestCrowdsecHandler_DeleteConsoleEnrollment
--- PASS: TestCrowdsecHandler_DeleteConsoleEnrollment (0.00s)
=== RUN TestCrowdsecHandler_BanIP
--- PASS: TestCrowdsecHandler_BanIP (0.01s)
=== RUN TestCrowdsecHandler_UnbanIP
--- PASS: TestCrowdsecHandler_UnbanIP (0.00s)
=== RUN TestCrowdsecHandler_UpdateAcquisitionConfig
--- PASS: TestCrowdsecHandler_UpdateAcquisitionConfig (0.01s)
=== RUN Test_safeIntToUint
=== RUN Test_safeIntToUint/positive_int
=== RUN Test_safeIntToUint/zero
=== RUN Test_safeIntToUint/negative_int
=== RUN Test_safeIntToUint/large_positive
--- PASS: Test_safeIntToUint (0.00s)
--- PASS: Test_safeIntToUint/positive_int (0.00s)
--- PASS: Test_safeIntToUint/zero (0.00s)
--- PASS: Test_safeIntToUint/negative_int (0.00s)
--- PASS: Test_safeIntToUint/large_positive (0.00s)
=== RUN Test_safeFloat64ToUint
=== RUN Test_safeFloat64ToUint/positive_integer_float
=== RUN Test_safeFloat64ToUint/zero
=== RUN Test_safeFloat64ToUint/negative_float
=== RUN Test_safeFloat64ToUint/fractional_float
--- PASS: Test_safeFloat64ToUint (0.00s)
--- PASS: Test_safeFloat64ToUint/positive_integer_float (0.00s)
--- PASS: Test_safeFloat64ToUint/zero (0.00s)
--- PASS: Test_safeFloat64ToUint/negative_float (0.00s)
--- PASS: Test_safeFloat64ToUint/fractional_float (0.00s)
=== RUN TestBackupHandlerQuick
--- PASS: TestBackupHandlerQuick (0.00s)
=== RUN TestListPresetsShowsCachedStatus
--- PASS: TestListPresetsShowsCachedStatus (1.13s)
=== RUN TestCacheKeyPersistence
--- PASS: TestCacheKeyPersistence (0.00s)
=== RUN TestUpdateAcquisitionConfigMissingContent
--- PASS: TestUpdateAcquisitionConfigMissingContent (0.00s)
=== RUN TestUpdateAcquisitionConfigInvalidJSON
--- PASS: TestUpdateAcquisitionConfigInvalidJSON (0.00s)
=== RUN TestGetLAPIDecisionsWithIPFilter
--- PASS: TestGetLAPIDecisionsWithIPFilter (0.00s)
=== RUN TestGetLAPIDecisionsWithScopeFilter
--- PASS: TestGetLAPIDecisionsWithScopeFilter (0.00s)
=== RUN TestGetLAPIDecisionsWithTypeFilter
--- PASS: TestGetLAPIDecisionsWithTypeFilter (0.00s)
=== RUN TestGetLAPIDecisionsWithMultipleFilters
--- PASS: TestGetLAPIDecisionsWithMultipleFilters (0.00s)
=== RUN TestUpdateAcquisitionConfigSuccess
--- PASS: TestUpdateAcquisitionConfigSuccess (0.00s)
=== RUN TestRegisterBouncerScriptPathError
--- PASS: TestRegisterBouncerScriptPathError (0.00s)
=== RUN TestGetLAPIDecisionsEmptyResponse
--- PASS: TestGetLAPIDecisionsEmptyResponse (0.00s)
=== RUN TestGetLAPIDecisionsIPQueryParam
--- PASS: TestGetLAPIDecisionsIPQueryParam (0.00s)
=== RUN TestGetLAPIDecisionsScopeParam
--- PASS: TestGetLAPIDecisionsScopeParam (0.00s)
=== RUN TestGetLAPIDecisionsTypeParam
--- PASS: TestGetLAPIDecisionsTypeParam (0.00s)
=== RUN TestGetLAPIDecisionsCombinedParams
--- PASS: TestGetLAPIDecisionsCombinedParams (0.01s)
=== RUN TestCheckLAPIHealthRequest
--- PASS: TestCheckLAPIHealthRequest (0.00s)
=== RUN TestGetLAPIKeyLookup
--- PASS: TestGetLAPIKeyLookup (0.00s)
=== RUN TestGetLAPIKeyEmpty
--- PASS: TestGetLAPIKeyEmpty (0.00s)
=== RUN TestGetLAPIKeyAlternative
--- PASS: TestGetLAPIKeyAlternative (0.00s)
=== RUN TestStatusRequest
--- PASS: TestStatusRequest (0.00s)
=== RUN TestRegisterBouncerFlow
--- PASS: TestRegisterBouncerFlow (0.00s)
=== RUN TestRegisterBouncerExecutionFailure
--- PASS: TestRegisterBouncerExecutionFailure (0.00s)
=== RUN TestGetAcquisitionConfigNotPresent
--- PASS: TestGetAcquisitionConfigNotPresent (0.00s)
=== RUN TestListDecisions_Success
--- PASS: TestListDecisions_Success (0.00s)
=== RUN TestListDecisions_EmptyList
--- PASS: TestListDecisions_EmptyList (0.00s)
=== RUN TestListDecisions_CscliError
--- PASS: TestListDecisions_CscliError (0.00s)
=== RUN TestListDecisions_InvalidJSON
--- PASS: TestListDecisions_InvalidJSON (0.00s)
=== RUN TestBanIP_Success
--- PASS: TestBanIP_Success (0.00s)
=== RUN TestBanIP_DefaultDuration
--- PASS: TestBanIP_DefaultDuration (0.00s)
=== RUN TestBanIP_MissingIP
--- PASS: TestBanIP_MissingIP (0.00s)
=== RUN TestBanIP_EmptyIP
--- PASS: TestBanIP_EmptyIP (0.00s)
=== RUN TestBanIP_CscliError
--- PASS: TestBanIP_CscliError (0.00s)
=== RUN TestUnbanIP_Success
--- PASS: TestUnbanIP_Success (0.01s)
=== RUN TestUnbanIP_CscliError
--- PASS: TestUnbanIP_CscliError (0.00s)
=== RUN TestListDecisions_MultipleDecisions
--- PASS: TestListDecisions_MultipleDecisions (0.00s)
=== RUN TestBanIP_InvalidJSON
--- PASS: TestBanIP_InvalidJSON (0.00s)
=== RUN TestDefaultCrowdsecExecutorPidFile
--- PASS: TestDefaultCrowdsecExecutorPidFile (0.00s)
=== RUN TestDefaultCrowdsecExecutorStartStatusStop
--- PASS: TestDefaultCrowdsecExecutorStartStatusStop (0.20s)
=== RUN TestDefaultCrowdsecExecutor_Status_NoPidFile
--- PASS: TestDefaultCrowdsecExecutor_Status_NoPidFile (0.00s)
=== RUN TestDefaultCrowdsecExecutor_Status_InvalidPid
--- PASS: TestDefaultCrowdsecExecutor_Status_InvalidPid (0.00s)
=== RUN TestDefaultCrowdsecExecutor_Status_NonExistentProcess
--- PASS: TestDefaultCrowdsecExecutor_Status_NonExistentProcess (0.00s)
=== RUN TestDefaultCrowdsecExecutor_Stop_NoPidFile
--- PASS: TestDefaultCrowdsecExecutor_Stop_NoPidFile (0.00s)
=== RUN TestDefaultCrowdsecExecutor_Stop_InvalidPid
--- PASS: TestDefaultCrowdsecExecutor_Stop_InvalidPid (0.00s)
=== RUN TestDefaultCrowdsecExecutor_Stop_NonExistentProcess
--- PASS: TestDefaultCrowdsecExecutor_Stop_NonExistentProcess (0.00s)
=== RUN TestDefaultCrowdsecExecutor_Stop_Idempotent
--- PASS: TestDefaultCrowdsecExecutor_Stop_Idempotent (0.00s)
=== RUN TestDefaultCrowdsecExecutor_Start_InvalidBinary
--- PASS: TestDefaultCrowdsecExecutor_Start_InvalidBinary (0.00s)
=== RUN TestDefaultCrowdsecExecutor_isCrowdSecProcess_ValidProcess
--- PASS: TestDefaultCrowdsecExecutor_isCrowdSecProcess_ValidProcess (0.00s)
=== RUN TestDefaultCrowdsecExecutor_isCrowdSecProcess_DifferentProcess
--- PASS: TestDefaultCrowdsecExecutor_isCrowdSecProcess_DifferentProcess (0.00s)
=== RUN TestDefaultCrowdsecExecutor_isCrowdSecProcess_NonExistentProcess
--- PASS: TestDefaultCrowdsecExecutor_isCrowdSecProcess_NonExistentProcess (0.00s)
=== RUN TestDefaultCrowdsecExecutor_isCrowdSecProcess_EmptyCmdline
--- PASS: TestDefaultCrowdsecExecutor_isCrowdSecProcess_EmptyCmdline (0.00s)
=== RUN TestDefaultCrowdsecExecutor_Status_PIDReuse_DifferentProcess
--- PASS: TestDefaultCrowdsecExecutor_Status_PIDReuse_DifferentProcess (0.00s)
=== RUN TestDefaultCrowdsecExecutor_Status_PIDReuse_IsCrowdSec
--- PASS: TestDefaultCrowdsecExecutor_Status_PIDReuse_IsCrowdSec (0.00s)
=== RUN TestDefaultCrowdsecExecutor_Stop_SignalError
--- PASS: TestDefaultCrowdsecExecutor_Stop_SignalError (0.00s)
=== RUN TestTTLRemainingSeconds
=== RUN TestTTLRemainingSeconds/zero_retrieved_time
=== RUN TestTTLRemainingSeconds/zero_ttl
=== RUN TestTTLRemainingSeconds/expired_ttl
=== RUN TestTTLRemainingSeconds/valid_ttl
--- PASS: TestTTLRemainingSeconds (0.00s)
--- PASS: TestTTLRemainingSeconds/zero_retrieved_time (0.00s)
--- PASS: TestTTLRemainingSeconds/zero_ttl (0.00s)
--- PASS: TestTTLRemainingSeconds/expired_ttl (0.00s)
--- PASS: TestTTLRemainingSeconds/valid_ttl (0.00s)
=== RUN TestMapCrowdsecStatus
=== RUN TestMapCrowdsecStatus/no_error
=== RUN TestMapCrowdsecStatus/generic_error
--- PASS: TestMapCrowdsecStatus (0.00s)
--- PASS: TestMapCrowdsecStatus/no_error (0.00s)
--- PASS: TestMapCrowdsecStatus/generic_error (0.00s)
=== RUN TestIsConsoleEnrollmentEnabled
=== RUN TestIsConsoleEnrollmentEnabled/enabled_via_env
=== RUN TestIsConsoleEnrollmentEnabled/disabled_via_env
=== RUN TestIsConsoleEnrollmentEnabled/default_when_not_set
--- PASS: TestIsConsoleEnrollmentEnabled (0.00s)
--- PASS: TestIsConsoleEnrollmentEnabled/enabled_via_env (0.00s)
--- PASS: TestIsConsoleEnrollmentEnabled/disabled_via_env (0.00s)
--- PASS: TestIsConsoleEnrollmentEnabled/default_when_not_set (0.00s)
=== RUN TestActorFromContext
=== RUN TestActorFromContext/with_userID
=== RUN TestActorFromContext/without_userID
--- PASS: TestActorFromContext (0.00s)
--- PASS: TestActorFromContext/with_userID (0.00s)
--- PASS: TestActorFromContext/without_userID (0.00s)
=== RUN TestHubEndpoints
--- PASS: TestHubEndpoints (0.00s)
=== RUN TestGetCachedPreset
--- PASS: TestGetCachedPreset (0.00s)
=== RUN TestGetCachedPreset_NotFound
--- PASS: TestGetCachedPreset_NotFound (0.00s)
=== RUN TestGetLAPIDecisions
--- PASS: TestGetLAPIDecisions (0.01s)
=== RUN TestCheckLAPIHealth
--- PASS: TestCheckLAPIHealth (0.00s)
=== RUN TestListDecisions
--- PASS: TestListDecisions (0.00s)
=== RUN TestBanIP
--- PASS: TestBanIP (0.00s)
=== RUN TestUnbanIP
--- PASS: TestUnbanIP (0.00s)
=== RUN TestGetAcquisitionConfig
--- PASS: TestGetAcquisitionConfig (0.00s)
=== RUN TestUpdateAcquisitionConfig
--- PASS: TestUpdateAcquisitionConfig (0.00s)
=== RUN TestGetLAPIKey
--- PASS: TestGetLAPIKey (0.00s)
=== RUN TestCrowdsec_Start_Error
--- PASS: TestCrowdsec_Start_Error (0.00s)
=== RUN TestCrowdsec_Stop_Error
--- PASS: TestCrowdsec_Stop_Error (0.00s)
=== RUN TestCrowdsec_Status_Error
--- PASS: TestCrowdsec_Status_Error (0.00s)
=== RUN TestCrowdsec_ReadFile_MissingPath
--- PASS: TestCrowdsec_ReadFile_MissingPath (0.00s)
=== RUN TestCrowdsec_ReadFile_PathTraversal
--- PASS: TestCrowdsec_ReadFile_PathTraversal (0.00s)
=== RUN TestCrowdsec_ReadFile_NotFound
--- PASS: TestCrowdsec_ReadFile_NotFound (0.01s)
=== RUN TestCrowdsec_WriteFile_InvalidPayload
--- PASS: TestCrowdsec_WriteFile_InvalidPayload (0.00s)
=== RUN TestCrowdsec_WriteFile_MissingPath
--- PASS: TestCrowdsec_WriteFile_MissingPath (0.01s)
=== RUN TestCrowdsec_WriteFile_PathTraversal
--- PASS: TestCrowdsec_WriteFile_PathTraversal (0.00s)
=== RUN TestCrowdsec_ExportConfig_NotFound
--- PASS: TestCrowdsec_ExportConfig_NotFound (0.00s)
=== RUN TestCrowdsec_ListFiles_EmptyDir
--- PASS: TestCrowdsec_ListFiles_EmptyDir (0.00s)
=== RUN TestCrowdsec_ListFiles_NonExistent
--- PASS: TestCrowdsec_ListFiles_NonExistent (0.00s)
=== RUN TestCrowdsec_ImportConfig_NoFile
--- PASS: TestCrowdsec_ImportConfig_NoFile (0.00s)
=== RUN TestCrowdsec_ReadFile_NestedPath
--- PASS: TestCrowdsec_ReadFile_NestedPath (0.01s)
=== RUN TestCrowdsec_WriteFile_Success
--- PASS: TestCrowdsec_WriteFile_Success (0.00s)
=== RUN TestCrowdsec_ListPresets_Disabled
--- PASS: TestCrowdsec_ListPresets_Disabled (0.00s)
=== RUN TestCrowdsec_ListPresets_Success
--- PASS: TestCrowdsec_ListPresets_Success (0.92s)
=== RUN TestCrowdsec_PullPreset_Validation
--- PASS: TestCrowdsec_PullPreset_Validation (0.01s)
=== RUN TestCrowdsec_ApplyPreset_Validation
--- PASS: TestCrowdsec_ApplyPreset_Validation (0.00s)
=== RUN TestCrowdsecEndpoints
=== PAUSE TestCrowdsecEndpoints
=== RUN TestImportConfig
=== PAUSE TestImportConfig
=== RUN TestImportCreatesBackup
=== PAUSE TestImportCreatesBackup
=== RUN TestExportConfig
=== PAUSE TestExportConfig
=== RUN TestListAndReadFile
=== PAUSE TestListAndReadFile
=== RUN TestExportConfigStreamsArchive
=== PAUSE TestExportConfigStreamsArchive
=== RUN TestWriteFileCreatesBackup
=== PAUSE TestWriteFileCreatesBackup
=== RUN TestListPresetsCerberusDisabled
--- PASS: TestListPresetsCerberusDisabled (0.00s)
=== RUN TestReadFileInvalidPath
=== PAUSE TestReadFileInvalidPath
=== RUN TestWriteFileInvalidPath
=== PAUSE TestWriteFileInvalidPath
=== RUN TestWriteFileMissingPath
=== PAUSE TestWriteFileMissingPath
=== RUN TestWriteFileInvalidPayload
=== PAUSE TestWriteFileInvalidPayload
=== RUN TestImportConfigRequiresFile
=== PAUSE TestImportConfigRequiresFile
=== RUN TestImportConfigRejectsEmptyUpload
=== PAUSE TestImportConfigRejectsEmptyUpload
=== RUN TestListFilesMissingDir
=== PAUSE TestListFilesMissingDir
=== RUN TestListFilesReturnsEntries
=== PAUSE TestListFilesReturnsEntries
=== RUN TestIsCerberusEnabledFromDB
=== PAUSE TestIsCerberusEnabledFromDB
=== RUN TestIsCerberusEnabledInvalidEnv
--- PASS: TestIsCerberusEnabledInvalidEnv (0.00s)
=== RUN TestIsCerberusEnabledLegacyEnv
--- PASS: TestIsCerberusEnabledLegacyEnv (0.00s)
=== RUN TestConsoleEnrollDisabled
--- PASS: TestConsoleEnrollDisabled (0.00s)
=== RUN TestConsoleEnrollServiceUnavailable
--- PASS: TestConsoleEnrollServiceUnavailable (0.00s)
=== RUN TestConsoleEnrollInvalidPayload
--- PASS: TestConsoleEnrollInvalidPayload (0.01s)
=== RUN TestConsoleEnrollSuccess
--- PASS: TestConsoleEnrollSuccess (0.01s)
=== RUN TestConsoleEnrollMissingAgentName
--- PASS: TestConsoleEnrollMissingAgentName (0.01s)
=== RUN TestConsoleStatusDisabled
--- PASS: TestConsoleStatusDisabled (0.00s)
=== RUN TestConsoleStatusServiceUnavailable
--- PASS: TestConsoleStatusServiceUnavailable (0.00s)
=== RUN TestConsoleStatusSuccess
--- PASS: TestConsoleStatusSuccess (0.01s)
=== RUN TestConsoleStatusAfterEnroll
--- PASS: TestConsoleStatusAfterEnroll (0.01s)
=== RUN TestIsConsoleEnrollmentEnabledFromDB
=== PAUSE TestIsConsoleEnrollmentEnabledFromDB
=== RUN TestIsConsoleEnrollmentDisabledFromDB
=== PAUSE TestIsConsoleEnrollmentDisabledFromDB
=== RUN TestIsConsoleEnrollmentEnabledFromEnv
--- PASS: TestIsConsoleEnrollmentEnabledFromEnv (0.00s)
=== RUN TestIsConsoleEnrollmentDisabledFromEnv
--- PASS: TestIsConsoleEnrollmentDisabledFromEnv (0.00s)
=== RUN TestIsConsoleEnrollmentInvalidEnv
--- PASS: TestIsConsoleEnrollmentInvalidEnv (0.00s)
=== RUN TestIsConsoleEnrollmentDefaultDisabled
--- PASS: TestIsConsoleEnrollmentDefaultDisabled (0.00s)
=== RUN TestIsConsoleEnrollmentDBTrueVariants
=== RUN TestIsConsoleEnrollmentDBTrueVariants/true
=== RUN TestIsConsoleEnrollmentDBTrueVariants/TRUE
=== RUN TestIsConsoleEnrollmentDBTrueVariants/True
=== RUN TestIsConsoleEnrollmentDBTrueVariants/1
=== RUN TestIsConsoleEnrollmentDBTrueVariants/yes
=== RUN TestIsConsoleEnrollmentDBTrueVariants/YES
=== RUN TestIsConsoleEnrollmentDBTrueVariants/false
=== RUN TestIsConsoleEnrollmentDBTrueVariants/FALSE
=== RUN TestIsConsoleEnrollmentDBTrueVariants/0
=== RUN TestIsConsoleEnrollmentDBTrueVariants/no
--- PASS: TestIsConsoleEnrollmentDBTrueVariants (0.04s)
--- PASS: TestIsConsoleEnrollmentDBTrueVariants/true (0.00s)
--- PASS: TestIsConsoleEnrollmentDBTrueVariants/TRUE (0.01s)
--- PASS: TestIsConsoleEnrollmentDBTrueVariants/True (0.01s)
--- PASS: TestIsConsoleEnrollmentDBTrueVariants/1 (0.00s)
--- PASS: TestIsConsoleEnrollmentDBTrueVariants/yes (0.00s)
--- PASS: TestIsConsoleEnrollmentDBTrueVariants/YES (0.00s)
--- PASS: TestIsConsoleEnrollmentDBTrueVariants/false (0.00s)
--- PASS: TestIsConsoleEnrollmentDBTrueVariants/FALSE (0.00s)
--- PASS: TestIsConsoleEnrollmentDBTrueVariants/0 (0.00s)
--- PASS: TestIsConsoleEnrollmentDBTrueVariants/no (0.00s)
=== RUN TestRegisterBouncerScriptNotFound
=== PAUSE TestRegisterBouncerScriptNotFound
=== RUN TestRegisterBouncerSuccess
=== PAUSE TestRegisterBouncerSuccess
=== RUN TestRegisterBouncerExecutionError
=== PAUSE TestRegisterBouncerExecutionError
=== RUN TestGetAcquisitionConfigNotFound
=== PAUSE TestGetAcquisitionConfigNotFound
=== RUN TestGetAcquisitionConfigSuccess
=== PAUSE TestGetAcquisitionConfigSuccess
=== RUN TestDeleteConsoleEnrollmentDisabled
--- PASS: TestDeleteConsoleEnrollmentDisabled (0.00s)
=== RUN TestDeleteConsoleEnrollmentServiceUnavailable
--- PASS: TestDeleteConsoleEnrollmentServiceUnavailable (0.00s)
=== RUN TestDeleteConsoleEnrollmentSuccess
--- PASS: TestDeleteConsoleEnrollmentSuccess (0.00s)
=== RUN TestDeleteConsoleEnrollmentNoRecordSuccess
--- PASS: TestDeleteConsoleEnrollmentNoRecordSuccess (0.00s)
=== RUN TestDeleteConsoleEnrollmentThenReenroll
--- PASS: TestDeleteConsoleEnrollmentThenReenroll (0.01s)
=== RUN TestCrowdsecStart_LAPINotReadyTimeout
=== PAUSE TestCrowdsecStart_LAPINotReadyTimeout
=== RUN TestCrowdsecHandler_Status_Error
=== PAUSE TestCrowdsecHandler_Status_Error
=== RUN TestCrowdsecHandler_Start_ExecutorError
=== PAUSE TestCrowdsecHandler_Start_ExecutorError
=== RUN TestCrowdsecHandler_ExportConfig_DirNotFound
=== PAUSE TestCrowdsecHandler_ExportConfig_DirNotFound
=== RUN TestCrowdsecHandler_ReadFile_NotFound
=== PAUSE TestCrowdsecHandler_ReadFile_NotFound
=== RUN TestCrowdsecHandler_ReadFile_MissingPath
=== PAUSE TestCrowdsecHandler_ReadFile_MissingPath
=== RUN TestCrowdsecHandler_ListDecisions_Success
=== PAUSE TestCrowdsecHandler_ListDecisions_Success
=== RUN TestCrowdsecHandler_ListDecisions_Empty
=== PAUSE TestCrowdsecHandler_ListDecisions_Empty
=== RUN TestCrowdsecHandler_ListDecisions_CscliError
=== PAUSE TestCrowdsecHandler_ListDecisions_CscliError
=== RUN TestCrowdsecHandler_ListDecisions_InvalidJSON
=== PAUSE TestCrowdsecHandler_ListDecisions_InvalidJSON
=== RUN TestCrowdsecHandler_BanIP_Success
=== PAUSE TestCrowdsecHandler_BanIP_Success
=== RUN TestCrowdsecHandler_BanIP_MissingIP
=== PAUSE TestCrowdsecHandler_BanIP_MissingIP
=== RUN TestCrowdsecHandler_BanIP_EmptyIP
=== PAUSE TestCrowdsecHandler_BanIP_EmptyIP
=== RUN TestCrowdsecHandler_BanIP_DefaultDuration
=== PAUSE TestCrowdsecHandler_BanIP_DefaultDuration
=== RUN TestCrowdsecHandler_UnbanIP_Success
=== PAUSE TestCrowdsecHandler_UnbanIP_Success
=== RUN TestCrowdsecHandler_UnbanIP_Error
=== PAUSE TestCrowdsecHandler_UnbanIP_Error
=== RUN TestCrowdsecHandler_BanIP_ExecutionError
=== PAUSE TestCrowdsecHandler_BanIP_ExecutionError
=== RUN TestCrowdsecHandler_CheckLAPIHealth_InvalidURL
=== PAUSE TestCrowdsecHandler_CheckLAPIHealth_InvalidURL
=== RUN TestCrowdsecHandler_GetLAPIDecisions_Fallback
=== PAUSE TestCrowdsecHandler_GetLAPIDecisions_Fallback
=== RUN TestCrowdsecHandler_PullPreset_CerberusDisabled
--- PASS: TestCrowdsecHandler_PullPreset_CerberusDisabled (0.00s)
=== RUN TestCrowdsecHandler_PullPreset_InvalidPayload
--- PASS: TestCrowdsecHandler_PullPreset_InvalidPayload (0.00s)
=== RUN TestCrowdsecHandler_PullPreset_EmptySlug
--- PASS: TestCrowdsecHandler_PullPreset_EmptySlug (0.00s)
=== RUN TestCrowdsecHandler_PullPreset_HubUnavailable
--- PASS: TestCrowdsecHandler_PullPreset_HubUnavailable (0.00s)
=== RUN TestCrowdsecHandler_ApplyPreset_CerberusDisabled
--- PASS: TestCrowdsecHandler_ApplyPreset_CerberusDisabled (0.00s)
=== RUN TestCrowdsecHandler_ApplyPreset_InvalidPayload
--- PASS: TestCrowdsecHandler_ApplyPreset_InvalidPayload (0.01s)
=== RUN TestCrowdsecHandler_ApplyPreset_EmptySlug
--- PASS: TestCrowdsecHandler_ApplyPreset_EmptySlug (0.00s)
=== RUN TestCrowdsecHandler_ApplyPreset_HubUnavailable
--- PASS: TestCrowdsecHandler_ApplyPreset_HubUnavailable (0.00s)
=== RUN TestCrowdsecHandler_UpdateAcquisitionConfig_MissingContent
=== PAUSE TestCrowdsecHandler_UpdateAcquisitionConfig_MissingContent
=== RUN TestCrowdsecHandler_UpdateAcquisitionConfig_InvalidJSON
=== PAUSE TestCrowdsecHandler_UpdateAcquisitionConfig_InvalidJSON
=== RUN TestCrowdsecHandler_ListDecisions_WithConfigYaml
=== PAUSE TestCrowdsecHandler_ListDecisions_WithConfigYaml
=== RUN TestCrowdsecHandler_BanIP_WithConfigYaml
=== PAUSE TestCrowdsecHandler_BanIP_WithConfigYaml
=== RUN TestCrowdsecHandler_UnbanIP_WithConfigYaml
=== PAUSE TestCrowdsecHandler_UnbanIP_WithConfigYaml
=== RUN TestCrowdsecHandler_Status_LAPIReady
=== PAUSE TestCrowdsecHandler_Status_LAPIReady
=== RUN TestCrowdsecHandler_Status_LAPINotReady
=== PAUSE TestCrowdsecHandler_Status_LAPINotReady
=== RUN TestCrowdsecHandler_ListDecisions_WithCreatedAt
=== PAUSE TestCrowdsecHandler_ListDecisions_WithCreatedAt
=== RUN TestCrowdsecHandler_HubEndpoints
=== PAUSE TestCrowdsecHandler_HubEndpoints
=== RUN TestCrowdsecHandler_ConsoleEnroll_ProgressConflict
--- PASS: TestCrowdsecHandler_ConsoleEnroll_ProgressConflict (0.01s)
=== RUN TestCrowdsecHandler_GetCachedPreset_CerberusDisabled
--- PASS: TestCrowdsecHandler_GetCachedPreset_CerberusDisabled (0.00s)
=== RUN TestCrowdsecHandler_GetCachedPreset_HubUnavailable
--- PASS: TestCrowdsecHandler_GetCachedPreset_HubUnavailable (0.00s)
=== RUN TestCrowdsecHandler_GetCachedPreset_EmptySlug
--- PASS: TestCrowdsecHandler_GetCachedPreset_EmptySlug (0.00s)
=== RUN TestGetLAPIDecisions_FallbackToCscli
--- PASS: TestGetLAPIDecisions_FallbackToCscli (0.00s)
=== RUN TestGetLAPIDecisions_EmptyResponse
--- PASS: TestGetLAPIDecisions_EmptyResponse (0.00s)
=== RUN TestCheckLAPIHealth_Handler
--- PASS: TestCheckLAPIHealth_Handler (0.00s)
=== RUN TestGetLAPIKey_FromEnv
--- PASS: TestGetLAPIKey_FromEnv (0.00s)
=== RUN TestGetLAPIKey_Empty
--- PASS: TestGetLAPIKey_Empty (0.00s)
=== RUN TestListPresetsIncludesCacheAndIndex
--- PASS: TestListPresetsIncludesCacheAndIndex (0.01s)
=== RUN TestPullPresetHandlerSuccess
--- PASS: TestPullPresetHandlerSuccess (0.01s)
=== RUN TestApplyPresetHandlerAudits
--- PASS: TestApplyPresetHandlerAudits (0.02s)
=== RUN TestPullPresetHandlerHubError
--- PASS: TestPullPresetHandlerHubError (0.00s)
=== RUN TestPullPresetHandlerTimeout
--- PASS: TestPullPresetHandlerTimeout (0.00s)
=== RUN TestGetCachedPresetNotFound
--- PASS: TestGetCachedPresetNotFound (0.00s)
=== RUN TestGetCachedPresetServiceUnavailable
--- PASS: TestGetCachedPresetServiceUnavailable (0.00s)
=== RUN TestApplyPresetHandlerBackupFailure
--- PASS: TestApplyPresetHandlerBackupFailure (0.00s)
=== RUN TestListPresetsMergesCuratedAndHub
--- PASS: TestListPresetsMergesCuratedAndHub (0.01s)
=== RUN TestGetCachedPresetSuccess
--- PASS: TestGetCachedPresetSuccess (0.00s)
=== RUN TestGetCachedPresetSlugRequired
--- PASS: TestGetCachedPresetSlugRequired (0.00s)
=== RUN TestGetCachedPresetPreviewError
--- PASS: TestGetCachedPresetPreviewError (0.00s)
=== RUN TestPullCuratedPresetSkipsHub
--- PASS: TestPullCuratedPresetSkipsHub (0.00s)
=== RUN TestApplyCuratedPresetSkipsHub
--- PASS: TestApplyCuratedPresetSkipsHub (0.00s)
=== RUN TestPullThenApplyIntegration
crowdsec_pull_apply_integration_test.go:67: User pulls preset
crowdsec_pull_apply_integration_test.go:83: Pull succeeded, cache_key: test/preset-1768011471
crowdsec_pull_apply_integration_test.go:90: Cache verified, slug: test/preset
crowdsec_pull_apply_integration_test.go:93: User applies preset
crowdsec_pull_apply_integration_test.go:109: Apply succeeded, backup: /tmp/TestPullThenApplyIntegration893046683/002.backup.20260110-021751
--- PASS: TestPullThenApplyIntegration (0.01s)
=== RUN TestApplyWithoutPullReturnsProperError
crowdsec_pull_apply_integration_test.go:138: User tries to apply preset without pulling first
crowdsec_pull_apply_integration_test.go:154: Proper error message returned: Preset cache missing or expired. Pull the preset again, then retry apply.
--- PASS: TestApplyWithoutPullReturnsProperError (0.01s)
=== RUN TestApplyRollbackWhenCacheMissingAndRepullFails
--- PASS: TestApplyRollbackWhenCacheMissingAndRepullFails (0.01s)
=== RUN TestStartSyncsSettingsTable
--- PASS: TestStartSyncsSettingsTable (60.13s)
=== RUN TestStopSyncsSettingsTable
--- PASS: TestStopSyncsSettingsTable (60.13s)
=== RUN TestStartAndStopStateConsistency
--- PASS: TestStartAndStopStateConsistency (180.39s)
=== RUN TestExistingSettingIsUpdated
--- PASS: TestExistingSettingIsUpdated (60.13s)
=== RUN TestStartFailureRevertsSettings
--- PASS: TestStartFailureRevertsSettings (0.01s)
=== RUN TestStatusResponseFormat
--- PASS: TestStatusResponseFormat (0.01s)
=== RUN TestCrowdsecHandler_Stop_Success
--- PASS: TestCrowdsecHandler_Stop_Success (0.01s)
=== RUN TestCrowdsecHandler_Stop_Error
--- PASS: TestCrowdsecHandler_Stop_Error (0.00s)
=== RUN TestCrowdsecHandler_Stop_NoSecurityConfig
--- PASS: TestCrowdsecHandler_Stop_NoSecurityConfig (0.00s)
=== RUN TestGetLAPIDecisions_WithMockServer
--- PASS: TestGetLAPIDecisions_WithMockServer (0.01s)
=== RUN TestGetLAPIDecisions_Unauthorized
--- PASS: TestGetLAPIDecisions_Unauthorized (0.01s)
=== RUN TestGetLAPIDecisions_NullResponse
--- PASS: TestGetLAPIDecisions_NullResponse (0.00s)
=== RUN TestGetLAPIDecisions_NonJSONContentType
--- PASS: TestGetLAPIDecisions_NonJSONContentType (0.01s)
=== RUN TestCheckLAPIHealth_WithMockServer
--- PASS: TestCheckLAPIHealth_WithMockServer (0.00s)
=== RUN TestCheckLAPIHealth_FallbackToDecisions
--- PASS: TestCheckLAPIHealth_FallbackToDecisions (0.01s)
=== RUN TestGetLAPIKey_AllEnvVars
=== RUN TestGetLAPIKey_AllEnvVars/CROWDSEC_API_KEY
=== RUN TestGetLAPIKey_AllEnvVars/CROWDSEC_BOUNCER_API_KEY
=== RUN TestGetLAPIKey_AllEnvVars/CERBERUS_SECURITY_CROWDSEC_API_KEY
=== RUN TestGetLAPIKey_AllEnvVars/CHARON_SECURITY_CROWDSEC_API_KEY
=== RUN TestGetLAPIKey_AllEnvVars/CPM_SECURITY_CROWDSEC_API_KEY
--- PASS: TestGetLAPIKey_AllEnvVars (0.00s)
--- PASS: TestGetLAPIKey_AllEnvVars/CROWDSEC_API_KEY (0.00s)
--- PASS: TestGetLAPIKey_AllEnvVars/CROWDSEC_BOUNCER_API_KEY (0.00s)
--- PASS: TestGetLAPIKey_AllEnvVars/CERBERUS_SECURITY_CROWDSEC_API_KEY (0.00s)
--- PASS: TestGetLAPIKey_AllEnvVars/CHARON_SECURITY_CROWDSEC_API_KEY (0.00s)
--- PASS: TestGetLAPIKey_AllEnvVars/CPM_SECURITY_CROWDSEC_API_KEY (0.00s)
=== RUN TestDBHealthHandler_Check_Healthy
--- PASS: TestDBHealthHandler_Check_Healthy (0.00s)
=== RUN TestDBHealthHandler_Check_WithBackupService
--- PASS: TestDBHealthHandler_Check_WithBackupService (0.00s)
=== RUN TestDBHealthHandler_Check_WALMode
--- PASS: TestDBHealthHandler_Check_WALMode (0.01s)
=== RUN TestDBHealthHandler_ResponseJSONTags
--- PASS: TestDBHealthHandler_ResponseJSONTags (0.00s)
=== RUN TestNewDBHealthHandler
--- PASS: TestNewDBHealthHandler (0.00s)
=== RUN TestDBHealthHandler_Check_CorruptedDatabase
2026/01/10 02:23:52 /projects/Charon/backend/internal/database/database.go:57 database disk image is malformed
[0.125ms] [rows:1] PRAGMA quick_check
2026/01/10 02:23:52 /projects/Charon/backend/internal/database/errors.go:63 database disk image is malformed
[0.092ms] [rows:1] PRAGMA quick_check
--- PASS: TestDBHealthHandler_Check_CorruptedDatabase (0.01s)
=== RUN TestDBHealthHandler_Check_BackupServiceError
--- PASS: TestDBHealthHandler_Check_BackupServiceError (0.00s)
=== RUN TestDBHealthHandler_Check_BackupTimeZero
--- PASS: TestDBHealthHandler_Check_BackupTimeZero (0.00s)
=== RUN TestNewDNSDetectionHandler
--- PASS: TestNewDNSDetectionHandler (0.00s)
=== RUN TestDetect_Success
=== RUN TestDetect_Success/successful_detection_without_configured_provider
=== RUN TestDetect_Success/successful_detection_with_configured_provider
=== RUN TestDetect_Success/detection_not_found
--- PASS: TestDetect_Success (0.00s)
--- PASS: TestDetect_Success/successful_detection_without_configured_provider (0.00s)
--- PASS: TestDetect_Success/successful_detection_with_configured_provider (0.00s)
--- PASS: TestDetect_Success/detection_not_found (0.00s)
=== RUN TestDetect_ValidationErrors
=== RUN TestDetect_ValidationErrors/missing_domain
=== RUN TestDetect_ValidationErrors/invalid_JSON
--- PASS: TestDetect_ValidationErrors (0.00s)
--- PASS: TestDetect_ValidationErrors/missing_domain (0.00s)
--- PASS: TestDetect_ValidationErrors/invalid_JSON (0.00s)
=== RUN TestDetect_ServiceError
--- PASS: TestDetect_ServiceError (0.00s)
=== RUN TestGetPatterns
--- PASS: TestGetPatterns (0.00s)
=== RUN TestDetect_WildcardDomain
--- PASS: TestDetect_WildcardDomain (0.00s)
=== RUN TestDetect_LowConfidence
--- PASS: TestDetect_LowConfidence (0.00s)
=== RUN TestDetect_DNSLookupError
--- PASS: TestDetect_DNSLookupError (0.00s)
=== RUN TestDetectRequest_Binding
=== RUN TestDetectRequest_Binding/valid_request
=== RUN TestDetectRequest_Binding/missing_domain
=== RUN TestDetectRequest_Binding/empty_domain
=== RUN TestDetectRequest_Binding/invalid_JSON
--- PASS: TestDetectRequest_Binding (0.00s)
--- PASS: TestDetectRequest_Binding/valid_request (0.00s)
--- PASS: TestDetectRequest_Binding/missing_domain (0.00s)
--- PASS: TestDetectRequest_Binding/empty_domain (0.00s)
--- PASS: TestDetectRequest_Binding/invalid_JSON (0.00s)
=== RUN TestDNSProviderHandler_List
=== RUN TestDNSProviderHandler_List/success
=== RUN TestDNSProviderHandler_List/service_error
--- PASS: TestDNSProviderHandler_List (0.00s)
--- PASS: TestDNSProviderHandler_List/success (0.00s)
--- PASS: TestDNSProviderHandler_List/service_error (0.00s)
=== RUN TestDNSProviderHandler_Get
=== RUN TestDNSProviderHandler_Get/success
=== RUN TestDNSProviderHandler_Get/not_found
=== RUN TestDNSProviderHandler_Get/invalid_id
--- PASS: TestDNSProviderHandler_Get (0.00s)
--- PASS: TestDNSProviderHandler_Get/success (0.00s)
--- PASS: TestDNSProviderHandler_Get/not_found (0.00s)
--- PASS: TestDNSProviderHandler_Get/invalid_id (0.00s)
=== RUN TestDNSProviderHandler_Create
=== RUN TestDNSProviderHandler_Create/success
=== RUN TestDNSProviderHandler_Create/validation_error
=== RUN TestDNSProviderHandler_Create/invalid_provider_type
=== RUN TestDNSProviderHandler_Create/invalid_credentials
--- PASS: TestDNSProviderHandler_Create (0.00s)
--- PASS: TestDNSProviderHandler_Create/success (0.00s)
--- PASS: TestDNSProviderHandler_Create/validation_error (0.00s)
--- PASS: TestDNSProviderHandler_Create/invalid_provider_type (0.00s)
--- PASS: TestDNSProviderHandler_Create/invalid_credentials (0.00s)
=== RUN TestDNSProviderHandler_Update
=== RUN TestDNSProviderHandler_Update/success
=== RUN TestDNSProviderHandler_Update/not_found
--- PASS: TestDNSProviderHandler_Update (0.00s)
--- PASS: TestDNSProviderHandler_Update/success (0.00s)
--- PASS: TestDNSProviderHandler_Update/not_found (0.00s)
=== RUN TestDNSProviderHandler_Delete
=== RUN TestDNSProviderHandler_Delete/success
=== RUN TestDNSProviderHandler_Delete/not_found
--- PASS: TestDNSProviderHandler_Delete (0.00s)
--- PASS: TestDNSProviderHandler_Delete/success (0.00s)
--- PASS: TestDNSProviderHandler_Delete/not_found (0.00s)
=== RUN TestDNSProviderHandler_Test
=== RUN TestDNSProviderHandler_Test/success
=== RUN TestDNSProviderHandler_Test/not_found
--- PASS: TestDNSProviderHandler_Test (0.00s)
--- PASS: TestDNSProviderHandler_Test/success (0.00s)
--- PASS: TestDNSProviderHandler_Test/not_found (0.00s)
=== RUN TestDNSProviderHandler_TestCredentials
=== RUN TestDNSProviderHandler_TestCredentials/success
=== RUN TestDNSProviderHandler_TestCredentials/validation_error
--- PASS: TestDNSProviderHandler_TestCredentials (0.00s)
--- PASS: TestDNSProviderHandler_TestCredentials/success (0.00s)
--- PASS: TestDNSProviderHandler_TestCredentials/validation_error (0.00s)
=== RUN TestDNSProviderHandler_GetTypes
--- PASS: TestDNSProviderHandler_GetTypes (0.00s)
=== RUN TestDNSProviderHandler_CredentialsNeverExposed
=== RUN TestDNSProviderHandler_CredentialsNeverExposed/Get_endpoint
=== RUN TestDNSProviderHandler_CredentialsNeverExposed/List_endpoint
--- PASS: TestDNSProviderHandler_CredentialsNeverExposed (0.00s)
--- PASS: TestDNSProviderHandler_CredentialsNeverExposed/Get_endpoint (0.00s)
--- PASS: TestDNSProviderHandler_CredentialsNeverExposed/List_endpoint (0.00s)
=== RUN TestDNSProviderHandler_UpdateInvalidID
--- PASS: TestDNSProviderHandler_UpdateInvalidID (0.00s)
=== RUN TestDNSProviderHandler_DeleteInvalidID
--- PASS: TestDNSProviderHandler_DeleteInvalidID (0.00s)
=== RUN TestDNSProviderHandler_TestInvalidID
--- PASS: TestDNSProviderHandler_TestInvalidID (0.00s)
=== RUN TestDNSProviderHandler_CreateEncryptionFailure
--- PASS: TestDNSProviderHandler_CreateEncryptionFailure (0.00s)
=== RUN TestDNSProviderHandler_UpdateEncryptionFailure
--- PASS: TestDNSProviderHandler_UpdateEncryptionFailure (0.00s)
=== RUN TestDNSProviderHandler_GetServiceError
--- PASS: TestDNSProviderHandler_GetServiceError (0.00s)
=== RUN TestDNSProviderHandler_DeleteServiceError
--- PASS: TestDNSProviderHandler_DeleteServiceError (0.00s)
=== RUN TestDNSProviderHandler_TestServiceError
--- PASS: TestDNSProviderHandler_TestServiceError (0.00s)
=== RUN TestDNSProviderHandler_TestCredentialsServiceError
--- PASS: TestDNSProviderHandler_TestCredentialsServiceError (0.00s)
=== RUN TestDNSProviderHandler_UpdateInvalidCredentials
--- PASS: TestDNSProviderHandler_UpdateInvalidCredentials (0.00s)
=== RUN TestDNSProviderHandler_UpdateBindJSONError
--- PASS: TestDNSProviderHandler_UpdateBindJSONError (0.00s)
=== RUN TestDNSProviderHandler_UpdateGenericError
--- PASS: TestDNSProviderHandler_UpdateGenericError (0.00s)
=== RUN TestDNSProviderHandler_CreateGenericError
--- PASS: TestDNSProviderHandler_CreateGenericError (0.00s)
=== RUN TestDockerHandler_ListContainers_InvalidHostRejected
--- PASS: TestDockerHandler_ListContainers_InvalidHostRejected (0.00s)
=== RUN TestDockerHandler_ListContainers_DockerUnavailableMappedTo503
--- PASS: TestDockerHandler_ListContainers_DockerUnavailableMappedTo503 (0.00s)
=== RUN TestDockerHandler_ListContainers_ServerIDResolvesToTCPHost
--- PASS: TestDockerHandler_ListContainers_ServerIDResolvesToTCPHost (0.00s)
=== RUN TestDockerHandler_ListContainers_ServerIDNotFoundReturns404
--- PASS: TestDockerHandler_ListContainers_ServerIDNotFoundReturns404 (0.00s)
=== RUN TestDockerHandler_ListContainers_Local
--- PASS: TestDockerHandler_ListContainers_Local (0.00s)
=== RUN TestDockerHandler_ListContainers_RemoteServerSuccess
--- PASS: TestDockerHandler_ListContainers_RemoteServerSuccess (0.00s)
=== RUN TestDockerHandler_ListContainers_RemoteServerNotFound
--- PASS: TestDockerHandler_ListContainers_RemoteServerNotFound (0.00s)
=== RUN TestDockerHandler_ListContainers_InvalidHost
=== RUN TestDockerHandler_ListContainers_InvalidHost/arbitrary_IP
=== RUN TestDockerHandler_ListContainers_InvalidHost/tcp_URL
=== RUN TestDockerHandler_ListContainers_InvalidHost/unix_socket
=== RUN TestDockerHandler_ListContainers_InvalidHost/http_URL
--- PASS: TestDockerHandler_ListContainers_InvalidHost (0.00s)
--- PASS: TestDockerHandler_ListContainers_InvalidHost/arbitrary_IP (0.00s)
--- PASS: TestDockerHandler_ListContainers_InvalidHost/tcp_URL (0.00s)
--- PASS: TestDockerHandler_ListContainers_InvalidHost/unix_socket (0.00s)
--- PASS: TestDockerHandler_ListContainers_InvalidHost/http_URL (0.00s)
=== RUN TestDockerHandler_ListContainers_DockerUnavailable
=== RUN TestDockerHandler_ListContainers_DockerUnavailable/daemon_not_running
=== RUN TestDockerHandler_ListContainers_DockerUnavailable/socket_permission_denied
=== RUN TestDockerHandler_ListContainers_DockerUnavailable/socket_not_found
--- PASS: TestDockerHandler_ListContainers_DockerUnavailable (0.00s)
--- PASS: TestDockerHandler_ListContainers_DockerUnavailable/daemon_not_running (0.00s)
--- PASS: TestDockerHandler_ListContainers_DockerUnavailable/socket_permission_denied (0.00s)
--- PASS: TestDockerHandler_ListContainers_DockerUnavailable/socket_not_found (0.00s)
=== RUN TestDockerHandler_ListContainers_GenericError
=== RUN TestDockerHandler_ListContainers_GenericError/API_error
=== RUN TestDockerHandler_ListContainers_GenericError/context_cancelled
=== RUN TestDockerHandler_ListContainers_GenericError/unknown_error
--- PASS: TestDockerHandler_ListContainers_GenericError (0.00s)
--- PASS: TestDockerHandler_ListContainers_GenericError/API_error (0.00s)
--- PASS: TestDockerHandler_ListContainers_GenericError/context_cancelled (0.00s)
--- PASS: TestDockerHandler_ListContainers_GenericError/unknown_error (0.00s)
=== RUN TestDomainLifecycle
--- PASS: TestDomainLifecycle (0.01s)
=== RUN TestDomainErrors
--- PASS: TestDomainErrors (0.01s)
=== RUN TestDomainDelete_NotFound
2026/01/10 02:23:52 /projects/Charon/backend/internal/api/handlers/domain_handler.go:73 record not found
[0.094ms] [rows:0] SELECT * FROM `domains` WHERE uuid = "nonexistent-uuid" AND `domains`.`deleted_at` IS NULL ORDER BY `domains`.`id` LIMIT 1
--- PASS: TestDomainDelete_NotFound (0.01s)
=== RUN TestDomainCreate_Duplicate
2026/01/10 02:23:52 /projects/Charon/backend/internal/api/handlers/domain_handler.go:49 UNIQUE constraint failed: domains.name
[0.211ms] [rows:0] INSERT INTO `domains` (`uuid`,`name`,`created_at`,`updated_at`,`deleted_at`) VALUES ("072e12ad-e893-484b-809c-c89d1c1a1dd5","duplicate.com","2026-01-10 02:23:52.233","2026-01-10 02:23:52.233",NULL) RETURNING `id`
--- PASS: TestDomainCreate_Duplicate (0.01s)
=== RUN TestDomainList_Empty
--- PASS: TestDomainList_Empty (0.01s)
=== RUN TestDomainCreate_LongName
--- PASS: TestDomainCreate_LongName (0.01s)
=== RUN TestEncryptionHandler_GetStatus
=== RUN TestEncryptionHandler_GetStatus/admin_can_get_status
=== RUN TestEncryptionHandler_GetStatus/non-admin_cannot_get_status
=== RUN TestEncryptionHandler_GetStatus/status_shows_next_key_when_configured
=== RUN TestEncryptionHandler_GetStatus/status_error_when_database_unavailable
2026/01/10 02:23:52 /projects/Charon/backend/internal/crypto/rotation_service.go:272 sql: database is closed
[0.041ms] [rows:0] SELECT `key_version` FROM `dns_providers`
--- PASS: TestEncryptionHandler_GetStatus (0.04s)
--- PASS: TestEncryptionHandler_GetStatus/admin_can_get_status (0.00s)
--- PASS: TestEncryptionHandler_GetStatus/non-admin_cannot_get_status (0.00s)
--- PASS: TestEncryptionHandler_GetStatus/status_shows_next_key_when_configured (0.00s)
--- PASS: TestEncryptionHandler_GetStatus/status_error_when_database_unavailable (0.00s)
=== RUN TestEncryptionHandler_Rotate
=== RUN TestEncryptionHandler_Rotate/admin_can_trigger_rotation
=== RUN TestEncryptionHandler_Rotate/non-admin_cannot_trigger_rotation
=== RUN TestEncryptionHandler_Rotate/rotation_fails_without_next_key
--- PASS: TestEncryptionHandler_Rotate (0.06s)
--- PASS: TestEncryptionHandler_Rotate/admin_can_trigger_rotation (0.02s)
--- PASS: TestEncryptionHandler_Rotate/non-admin_cannot_trigger_rotation (0.00s)
--- PASS: TestEncryptionHandler_Rotate/rotation_fails_without_next_key (0.00s)
=== RUN TestEncryptionHandler_GetHistory
=== RUN TestEncryptionHandler_GetHistory/admin_can_get_history
=== RUN TestEncryptionHandler_GetHistory/non-admin_cannot_get_history
=== RUN TestEncryptionHandler_GetHistory/supports_pagination
=== RUN TestEncryptionHandler_GetHistory/history_error_when_service_fails
2026/01/10 02:23:52 /projects/Charon/backend/internal/services/security_service.go:305 sql: database is closed
[0.049ms] [rows:0] SELECT count(*) FROM `security_audits` WHERE event_category = "encryption"
--- PASS: TestEncryptionHandler_GetHistory (0.07s)
--- PASS: TestEncryptionHandler_GetHistory/admin_can_get_history (0.00s)
--- PASS: TestEncryptionHandler_GetHistory/non-admin_cannot_get_history (0.00s)
--- PASS: TestEncryptionHandler_GetHistory/supports_pagination (0.00s)
--- PASS: TestEncryptionHandler_GetHistory/history_error_when_service_fails (0.03s)
=== RUN TestEncryptionHandler_Validate
=== RUN TestEncryptionHandler_Validate/admin_can_validate_keys
=== RUN TestEncryptionHandler_Validate/non-admin_cannot_validate_keys
=== RUN TestEncryptionHandler_Validate/validation_fails_with_invalid_key_configuration
--- PASS: TestEncryptionHandler_Validate (0.05s)
--- PASS: TestEncryptionHandler_Validate/admin_can_validate_keys (0.01s)
--- PASS: TestEncryptionHandler_Validate/non-admin_cannot_validate_keys (0.00s)
--- PASS: TestEncryptionHandler_Validate/validation_fails_with_invalid_key_configuration (0.00s)
=== RUN TestEncryptionHandler_IntegrationFlow
=== RUN TestEncryptionHandler_IntegrationFlow/complete_rotation_workflow
--- PASS: TestEncryptionHandler_IntegrationFlow (0.10s)
--- PASS: TestEncryptionHandler_IntegrationFlow/complete_rotation_workflow (0.06s)
=== RUN TestEncryptionHandler_HelperFunctions
=== RUN TestEncryptionHandler_HelperFunctions/isAdmin_with_invalid_role_type
=== RUN TestEncryptionHandler_HelperFunctions/getActorFromGinContext_with_string_user_id
=== RUN TestEncryptionHandler_HelperFunctions/getActorFromGinContext_with_uint_user_id
=== RUN TestEncryptionHandler_HelperFunctions/getActorFromGinContext_without_user_id_returns_system
--- PASS: TestEncryptionHandler_HelperFunctions (0.00s)
--- PASS: TestEncryptionHandler_HelperFunctions/isAdmin_with_invalid_role_type (0.00s)
--- PASS: TestEncryptionHandler_HelperFunctions/getActorFromGinContext_with_string_user_id (0.00s)
--- PASS: TestEncryptionHandler_HelperFunctions/getActorFromGinContext_with_uint_user_id (0.00s)
--- PASS: TestEncryptionHandler_HelperFunctions/getActorFromGinContext_without_user_id_returns_system (0.00s)
=== RUN TestEncryptionHandler_RefreshKey_RotatesCredentials
--- PASS: TestEncryptionHandler_RefreshKey_RotatesCredentials (0.06s)
=== RUN TestEncryptionHandler_RefreshKey_FailsWithoutProvider
--- PASS: TestEncryptionHandler_RefreshKey_FailsWithoutProvider (0.03s)
=== RUN TestEncryptionHandler_RefreshKey_InvalidOldKey
Failed to rotate provider 1 (Test Provider): failed to decrypt credentials: failed to decrypt with version 1 or any fallback version
--- PASS: TestEncryptionHandler_RefreshKey_InvalidOldKey (0.06s)
=== RUN TestEncryptionHandler_GetActorFromGinContext_InvalidType
--- PASS: TestEncryptionHandler_GetActorFromGinContext_InvalidType (0.00s)
=== RUN TestEncryptionHandler_RotateWithPartialFailures
Failed to rotate provider 2 (Invalid Provider): failed to decrypt credentials: failed to decrypt with version 1 or any fallback version
--- PASS: TestEncryptionHandler_RotateWithPartialFailures (0.05s)
=== RUN TestEncryptionHandler_isAdmin_NoRoleSet
--- PASS: TestEncryptionHandler_isAdmin_NoRoleSet (0.00s)
=== RUN TestEncryptionHandler_isAdmin_NonAdminRole
--- PASS: TestEncryptionHandler_isAdmin_NonAdminRole (0.00s)
=== RUN TestFeatureFlagsHandler_GetFlags_DBPrecedence
--- PASS: TestFeatureFlagsHandler_GetFlags_DBPrecedence (0.00s)
=== RUN TestFeatureFlagsHandler_GetFlags_EnvFallback
--- PASS: TestFeatureFlagsHandler_GetFlags_EnvFallback (0.00s)
=== RUN TestFeatureFlagsHandler_GetFlags_EnvShortForm
--- PASS: TestFeatureFlagsHandler_GetFlags_EnvShortForm (0.00s)
=== RUN TestFeatureFlagsHandler_GetFlags_EnvNumeric
--- PASS: TestFeatureFlagsHandler_GetFlags_EnvNumeric (0.00s)
=== RUN TestFeatureFlagsHandler_GetFlags_DefaultTrue
--- PASS: TestFeatureFlagsHandler_GetFlags_DefaultTrue (0.00s)
=== RUN TestFeatureFlagsHandler_GetFlags_AllDefaultFlagsPresent
--- PASS: TestFeatureFlagsHandler_GetFlags_AllDefaultFlagsPresent (0.00s)
=== RUN TestFeatureFlagsHandler_UpdateFlags_Success
--- PASS: TestFeatureFlagsHandler_UpdateFlags_Success (0.00s)
=== RUN TestFeatureFlagsHandler_UpdateFlags_Upsert
--- PASS: TestFeatureFlagsHandler_UpdateFlags_Upsert (0.00s)
=== RUN TestFeatureFlagsHandler_UpdateFlags_InvalidJSON
--- PASS: TestFeatureFlagsHandler_UpdateFlags_InvalidJSON (0.00s)
=== RUN TestFeatureFlagsHandler_UpdateFlags_OnlyAllowedKeys
--- PASS: TestFeatureFlagsHandler_UpdateFlags_OnlyAllowedKeys (0.00s)
=== RUN TestFeatureFlagsHandler_UpdateFlags_EmptyPayload
--- PASS: TestFeatureFlagsHandler_UpdateFlags_EmptyPayload (0.00s)
=== RUN TestFeatureFlagsHandler_GetFlags_DBValueVariants
=== RUN TestFeatureFlagsHandler_GetFlags_DBValueVariants/lowercase_true
=== RUN TestFeatureFlagsHandler_GetFlags_DBValueVariants/uppercase_TRUE
=== RUN TestFeatureFlagsHandler_GetFlags_DBValueVariants/mixed_case_True
=== RUN TestFeatureFlagsHandler_GetFlags_DBValueVariants/numeric_1
=== RUN TestFeatureFlagsHandler_GetFlags_DBValueVariants/yes
=== RUN TestFeatureFlagsHandler_GetFlags_DBValueVariants/YES_uppercase
=== RUN TestFeatureFlagsHandler_GetFlags_DBValueVariants/lowercase_false
=== RUN TestFeatureFlagsHandler_GetFlags_DBValueVariants/numeric_0
=== RUN TestFeatureFlagsHandler_GetFlags_DBValueVariants/no
=== RUN TestFeatureFlagsHandler_GetFlags_DBValueVariants/empty_string
=== RUN TestFeatureFlagsHandler_GetFlags_DBValueVariants/random_string
=== RUN TestFeatureFlagsHandler_GetFlags_DBValueVariants/whitespace_padded_true
=== RUN TestFeatureFlagsHandler_GetFlags_DBValueVariants/whitespace_padded_false
--- PASS: TestFeatureFlagsHandler_GetFlags_DBValueVariants (0.04s)
--- PASS: TestFeatureFlagsHandler_GetFlags_DBValueVariants/lowercase_true (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_DBValueVariants/uppercase_TRUE (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_DBValueVariants/mixed_case_True (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_DBValueVariants/numeric_1 (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_DBValueVariants/yes (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_DBValueVariants/YES_uppercase (0.01s)
--- PASS: TestFeatureFlagsHandler_GetFlags_DBValueVariants/lowercase_false (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_DBValueVariants/numeric_0 (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_DBValueVariants/no (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_DBValueVariants/empty_string (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_DBValueVariants/random_string (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_DBValueVariants/whitespace_padded_true (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_DBValueVariants/whitespace_padded_false (0.00s)
=== RUN TestFeatureFlagsHandler_GetFlags_EnvValueVariants
=== RUN TestFeatureFlagsHandler_GetFlags_EnvValueVariants/true_string
=== RUN TestFeatureFlagsHandler_GetFlags_EnvValueVariants/TRUE_uppercase
=== RUN TestFeatureFlagsHandler_GetFlags_EnvValueVariants/1_numeric
=== RUN TestFeatureFlagsHandler_GetFlags_EnvValueVariants/false_string
=== RUN TestFeatureFlagsHandler_GetFlags_EnvValueVariants/FALSE_uppercase
=== RUN TestFeatureFlagsHandler_GetFlags_EnvValueVariants/0_numeric
=== RUN TestFeatureFlagsHandler_GetFlags_EnvValueVariants/invalid_value_defaults_to_numeric_check
--- PASS: TestFeatureFlagsHandler_GetFlags_EnvValueVariants (0.03s)
--- PASS: TestFeatureFlagsHandler_GetFlags_EnvValueVariants/true_string (0.01s)
--- PASS: TestFeatureFlagsHandler_GetFlags_EnvValueVariants/TRUE_uppercase (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_EnvValueVariants/1_numeric (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_EnvValueVariants/false_string (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_EnvValueVariants/FALSE_uppercase (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_EnvValueVariants/0_numeric (0.00s)
--- PASS: TestFeatureFlagsHandler_GetFlags_EnvValueVariants/invalid_value_defaults_to_numeric_check (0.00s)
=== RUN TestFeatureFlagsHandler_UpdateFlags_BoolValues
=== RUN TestFeatureFlagsHandler_UpdateFlags_BoolValues/true
=== RUN TestFeatureFlagsHandler_UpdateFlags_BoolValues/false
--- PASS: TestFeatureFlagsHandler_UpdateFlags_BoolValues (0.00s)
--- PASS: TestFeatureFlagsHandler_UpdateFlags_BoolValues/true (0.00s)
--- PASS: TestFeatureFlagsHandler_UpdateFlags_BoolValues/false (0.00s)
=== RUN TestFeatureFlagsHandler_NewFeatureFlagsHandler
--- PASS: TestFeatureFlagsHandler_NewFeatureFlagsHandler (0.00s)
=== RUN TestFeatureFlags_GetAndUpdate
--- PASS: TestFeatureFlags_GetAndUpdate (0.00s)
=== RUN TestFeatureFlags_EnvFallback
--- PASS: TestFeatureFlags_EnvFallback (0.00s)
=== RUN TestHealthHandler
--- PASS: TestHealthHandler (0.00s)
=== RUN TestGetLocalIP
health_handler_test.go:36: getLocalIP returned: "217.15.170.144"
--- PASS: TestGetLocalIP (0.00s)
=== RUN TestIsSafePathUnderBase
--- PASS: TestIsSafePathUnderBase (0.00s)
=== RUN TestImportUploadSanitizesFilename
--- PASS: TestImportUploadSanitizesFilename (0.00s)
=== RUN TestLogsHandler_Read_FilterBySearch
--- PASS: TestLogsHandler_Read_FilterBySearch (0.00s)
=== RUN TestLogsHandler_Read_FilterByHost
--- PASS: TestLogsHandler_Read_FilterByHost (0.00s)
=== RUN TestLogsHandler_Read_FilterByLevel
--- PASS: TestLogsHandler_Read_FilterByLevel (0.00s)
=== RUN TestLogsHandler_Read_FilterByStatus
--- PASS: TestLogsHandler_Read_FilterByStatus (0.00s)
=== RUN TestLogsHandler_Read_SortAsc
--- PASS: TestLogsHandler_Read_SortAsc (0.00s)
=== RUN TestLogsHandler_List_DirectoryIsFile
--- PASS: TestLogsHandler_List_DirectoryIsFile (0.00s)
=== RUN TestLogsHandler_Download_TempFileError
--- PASS: TestLogsHandler_Download_TempFileError (0.00s)
=== RUN TestLogsLifecycle
--- PASS: TestLogsLifecycle (0.00s)
=== RUN TestLogsHandler_PathTraversal
--- PASS: TestLogsHandler_PathTraversal (0.00s)
=== RUN TestLogsWebSocketHandler_SuccessfulConnection
--- PASS: TestLogsWebSocketHandler_SuccessfulConnection (0.00s)
=== RUN TestLogsWebSocketHandler_ReceiveLogEntries
--- PASS: TestLogsWebSocketHandler_ReceiveLogEntries (0.00s)
=== RUN TestLogsWebSocketHandler_LevelFilter
--- PASS: TestLogsWebSocketHandler_LevelFilter (0.15s)
=== RUN TestLogsWebSocketHandler_SourceFilter
--- PASS: TestLogsWebSocketHandler_SourceFilter (0.00s)
=== RUN TestLogsWebSocketHandler_CombinedFilters
--- PASS: TestLogsWebSocketHandler_CombinedFilters (0.00s)
=== RUN TestLogsWebSocketHandler_CaseInsensitiveFilters
--- PASS: TestLogsWebSocketHandler_CaseInsensitiveFilters (0.00s)
=== RUN TestLogsWebSocketHandler_UpgradeFailure
--- PASS: TestLogsWebSocketHandler_UpgradeFailure (0.00s)
=== RUN TestLogsWebSocketHandler_ClientDisconnect
--- PASS: TestLogsWebSocketHandler_ClientDisconnect (0.02s)
=== RUN TestLogsWebSocketHandler_ChannelClosed
--- PASS: TestLogsWebSocketHandler_ChannelClosed (0.00s)
=== RUN TestLogsWebSocketHandler_MultipleConnections
--- PASS: TestLogsWebSocketHandler_MultipleConnections (0.01s)
=== RUN TestLogsWebSocketHandler_HighVolumeLogging
--- PASS: TestLogsWebSocketHandler_HighVolumeLogging (0.04s)
=== RUN TestLogsWebSocketHandler_EmptyLogFields
--- PASS: TestLogsWebSocketHandler_EmptyLogFields (0.02s)
=== RUN TestLogsWebSocketHandler_SubscriberIDUniqueness
--- PASS: TestLogsWebSocketHandler_SubscriberIDUniqueness (0.02s)
=== RUN TestLogsWebSocketHandler_WithRealLogger
--- PASS: TestLogsWebSocketHandler_WithRealLogger (0.00s)
=== RUN TestLogsWebSocketHandler_ConnectionLifecycle
--- PASS: TestLogsWebSocketHandler_ConnectionLifecycle (0.02s)
=== RUN TestDomainHandler_List_Error
--- PASS: TestDomainHandler_List_Error (0.00s)
=== RUN TestDomainHandler_Create_InvalidJSON
--- PASS: TestDomainHandler_Create_InvalidJSON (0.00s)
=== RUN TestDomainHandler_Create_DBError
--- PASS: TestDomainHandler_Create_DBError (0.00s)
=== RUN TestDomainHandler_Delete_Error
--- PASS: TestDomainHandler_Delete_Error (0.00s)
=== RUN TestRemoteServerHandler_List_Error
--- PASS: TestRemoteServerHandler_List_Error (0.00s)
=== RUN TestRemoteServerHandler_List_EnabledOnly
--- PASS: TestRemoteServerHandler_List_EnabledOnly (0.00s)
=== RUN TestRemoteServerHandler_Update_NotFound
--- PASS: TestRemoteServerHandler_Update_NotFound (0.00s)
=== RUN TestRemoteServerHandler_Update_InvalidJSON
--- PASS: TestRemoteServerHandler_Update_InvalidJSON (0.00s)
=== RUN TestRemoteServerHandler_TestConnection_NotFound
--- PASS: TestRemoteServerHandler_TestConnection_NotFound (0.00s)
=== RUN TestRemoteServerHandler_TestConnectionCustom_InvalidJSON
--- PASS: TestRemoteServerHandler_TestConnectionCustom_InvalidJSON (0.00s)
=== RUN TestRemoteServerHandler_TestConnectionCustom_Unreachable
--- PASS: TestRemoteServerHandler_TestConnectionCustom_Unreachable (5.00s)
=== RUN TestUptimeHandler_List_Error
--- PASS: TestUptimeHandler_List_Error (0.02s)
=== RUN TestUptimeHandler_GetHistory_Error
--- PASS: TestUptimeHandler_GetHistory_Error (0.02s)
=== RUN TestUptimeHandler_Update_InvalidJSON
--- PASS: TestUptimeHandler_Update_InvalidJSON (0.02s)
=== RUN TestUptimeHandler_Sync_Error
--- PASS: TestUptimeHandler_Sync_Error (0.02s)
=== RUN TestUptimeHandler_Delete_Error
--- PASS: TestUptimeHandler_Delete_Error (0.02s)
=== RUN TestUptimeHandler_CheckMonitor_NotFound
--- PASS: TestUptimeHandler_CheckMonitor_NotFound (0.02s)
=== RUN TestNotificationHandler_List_Error
--- PASS: TestNotificationHandler_List_Error (0.01s)
=== RUN TestNotificationHandler_List_UnreadOnly
--- PASS: TestNotificationHandler_List_UnreadOnly (0.01s)
=== RUN TestNotificationHandler_MarkAsRead_Error
--- PASS: TestNotificationHandler_MarkAsRead_Error (0.01s)
=== RUN TestNotificationHandler_MarkAllAsRead_Error
--- PASS: TestNotificationHandler_MarkAllAsRead_Error (0.01s)
=== RUN TestNotificationProviderHandler_List_Error
--- PASS: TestNotificationProviderHandler_List_Error (0.01s)
=== RUN TestNotificationProviderHandler_Create_InvalidJSON
--- PASS: TestNotificationProviderHandler_Create_InvalidJSON (0.01s)
=== RUN TestNotificationProviderHandler_Create_DBError
--- PASS: TestNotificationProviderHandler_Create_DBError (0.01s)
=== RUN TestNotificationProviderHandler_Create_InvalidTemplate
--- PASS: TestNotificationProviderHandler_Create_InvalidTemplate (0.01s)
=== RUN TestNotificationProviderHandler_Update_InvalidJSON
--- PASS: TestNotificationProviderHandler_Update_InvalidJSON (0.01s)
=== RUN TestNotificationProviderHandler_Update_InvalidTemplate
--- PASS: TestNotificationProviderHandler_Update_InvalidTemplate (0.01s)
=== RUN TestNotificationProviderHandler_Update_DBError
--- PASS: TestNotificationProviderHandler_Update_DBError (0.00s)
=== RUN TestNotificationProviderHandler_Delete_Error
--- PASS: TestNotificationProviderHandler_Delete_Error (0.01s)
=== RUN TestNotificationProviderHandler_Test_InvalidJSON
--- PASS: TestNotificationProviderHandler_Test_InvalidJSON (0.00s)
=== RUN TestNotificationProviderHandler_Templates
--- PASS: TestNotificationProviderHandler_Templates (0.00s)
=== RUN TestNotificationProviderHandler_Preview_InvalidJSON
--- PASS: TestNotificationProviderHandler_Preview_InvalidJSON (0.00s)
=== RUN TestNotificationProviderHandler_Preview_WithData
--- PASS: TestNotificationProviderHandler_Preview_WithData (0.01s)
=== RUN TestNotificationProviderHandler_Preview_InvalidTemplate
--- PASS: TestNotificationProviderHandler_Preview_InvalidTemplate (0.01s)
=== RUN TestNotificationTemplateHandler_List_Error
--- PASS: TestNotificationTemplateHandler_List_Error (0.01s)
=== RUN TestNotificationTemplateHandler_Create_BadJSON
--- PASS: TestNotificationTemplateHandler_Create_BadJSON (0.00s)
=== RUN TestNotificationTemplateHandler_Create_DBError
--- PASS: TestNotificationTemplateHandler_Create_DBError (0.01s)
=== RUN TestNotificationTemplateHandler_Update_BadJSON
--- PASS: TestNotificationTemplateHandler_Update_BadJSON (0.01s)
=== RUN TestNotificationTemplateHandler_Update_DBError
--- PASS: TestNotificationTemplateHandler_Update_DBError (0.01s)
=== RUN TestNotificationTemplateHandler_Delete_Error
--- PASS: TestNotificationTemplateHandler_Delete_Error (0.01s)
=== RUN TestNotificationTemplateHandler_Preview_BadJSON
--- PASS: TestNotificationTemplateHandler_Preview_BadJSON (0.01s)
=== RUN TestNotificationTemplateHandler_Preview_TemplateNotFound
--- PASS: TestNotificationTemplateHandler_Preview_TemplateNotFound (0.01s)
=== RUN TestNotificationTemplateHandler_Preview_WithStoredTemplate
--- PASS: TestNotificationTemplateHandler_Preview_WithStoredTemplate (0.01s)
=== RUN TestNotificationTemplateHandler_Preview_InvalidTemplate
--- PASS: TestNotificationTemplateHandler_Preview_InvalidTemplate (0.01s)
=== RUN TestNotificationTemplateHandler_CRUDAndPreview
--- PASS: TestNotificationTemplateHandler_CRUDAndPreview (0.01s)
=== RUN TestNotificationTemplateHandler_Create_InvalidJSON
--- PASS: TestNotificationTemplateHandler_Create_InvalidJSON (0.00s)
=== RUN TestNotificationTemplateHandler_Update_InvalidJSON
--- PASS: TestNotificationTemplateHandler_Update_InvalidJSON (0.00s)
=== RUN TestNotificationTemplateHandler_Preview_InvalidJSON
--- PASS: TestNotificationTemplateHandler_Preview_InvalidJSON (0.00s)
=== RUN TestPerf_GetStatus_AssertThreshold
perf_assert_test.go:107: GetStatus avg=0.386ms p95=0.520ms max=2.700ms
--- PASS: TestPerf_GetStatus_AssertThreshold (0.20s)
=== RUN TestPerf_GetStatus_Parallel_AssertThreshold
perf_assert_test.go:150: GetStatus Parallel avg=0.584ms p95=1.505ms max=4.662ms
--- PASS: TestPerf_GetStatus_Parallel_AssertThreshold (0.14s)
=== RUN TestPerf_ListDecisions_AssertThreshold
perf_assert_test.go:179: ListDecisions avg=2.203ms p95=2.787ms max=6.314ms
--- PASS: TestPerf_ListDecisions_AssertThreshold (0.68s)
=== RUN TestPluginHandler_NewPluginHandler
--- PASS: TestPluginHandler_NewPluginHandler (0.00s)
=== RUN TestPluginHandler_ListPlugins
--- PASS: TestPluginHandler_ListPlugins (0.06s)
=== RUN TestPluginHandler_GetPlugin_InvalidID
--- PASS: TestPluginHandler_GetPlugin_InvalidID (0.00s)
=== RUN TestPluginHandler_GetPlugin_NotFound
--- PASS: TestPluginHandler_GetPlugin_NotFound (0.00s)
=== RUN TestPluginHandler_GetPlugin_Success
--- PASS: TestPluginHandler_GetPlugin_Success (0.00s)
=== RUN TestPluginHandler_EnablePlugin_InvalidID
--- PASS: TestPluginHandler_EnablePlugin_InvalidID (0.00s)
=== RUN TestPluginHandler_EnablePlugin_NotFound
--- PASS: TestPluginHandler_EnablePlugin_NotFound (0.00s)
=== RUN TestPluginHandler_EnablePlugin_AlreadyEnabled
--- PASS: TestPluginHandler_EnablePlugin_AlreadyEnabled (0.00s)
=== RUN TestPluginHandler_EnablePlugin_Success
--- PASS: TestPluginHandler_EnablePlugin_Success (0.00s)
=== RUN TestPluginHandler_DisablePlugin_InvalidID
--- PASS: TestPluginHandler_DisablePlugin_InvalidID (0.00s)
=== RUN TestPluginHandler_DisablePlugin_NotFound
--- PASS: TestPluginHandler_DisablePlugin_NotFound (0.00s)
=== RUN TestPluginHandler_DisablePlugin_AlreadyDisabled
--- PASS: TestPluginHandler_DisablePlugin_AlreadyDisabled (0.00s)
=== RUN TestPluginHandler_DisablePlugin_InUse
--- PASS: TestPluginHandler_DisablePlugin_InUse (0.00s)
=== RUN TestPluginHandler_DisablePlugin_Success
--- PASS: TestPluginHandler_DisablePlugin_Success (0.00s)
=== RUN TestPluginHandler_ReloadPlugins_Success
--- PASS: TestPluginHandler_ReloadPlugins_Success (0.00s)
=== RUN TestPluginHandler_ListPlugins_WithBuiltInProviders
--- PASS: TestPluginHandler_ListPlugins_WithBuiltInProviders (0.00s)
=== RUN TestPluginHandler_ListPlugins_ExternalLoadedPlugin
--- PASS: TestPluginHandler_ListPlugins_ExternalLoadedPlugin (0.01s)
=== RUN TestPluginHandler_GetPlugin_WithProvider
--- PASS: TestPluginHandler_GetPlugin_WithProvider (0.00s)
=== RUN TestPluginHandler_EnablePlugin_WithLoadError
--- PASS: TestPluginHandler_EnablePlugin_WithLoadError (0.00s)
=== RUN TestPluginHandler_DisablePlugin_WithUnloadError
--- PASS: TestPluginHandler_DisablePlugin_WithUnloadError (0.01s)
=== RUN TestPluginHandler_DisablePlugin_MultipleProviders
--- PASS: TestPluginHandler_DisablePlugin_MultipleProviders (0.00s)
=== RUN TestPluginHandler_ReloadPlugins_WithErrors
--- PASS: TestPluginHandler_ReloadPlugins_WithErrors (0.00s)
=== RUN TestPluginHandler_ListPlugins_FailedPluginWithLoadedAt
--- PASS: TestPluginHandler_ListPlugins_FailedPluginWithLoadedAt (0.00s)
=== RUN TestPluginHandler_GetPlugin_WithLoadedAt
--- PASS: TestPluginHandler_GetPlugin_WithLoadedAt (0.01s)
=== RUN TestPluginHandler_Count
plugin_handler_test.go:851: Total plugin handler tests: Aim for 15-20 tests
--- PASS: TestPluginHandler_Count (0.00s)
=== RUN TestPluginHandler_EnablePlugin_DBUpdateError
--- PASS: TestPluginHandler_EnablePlugin_DBUpdateError (0.00s)
=== RUN TestPluginHandler_DisablePlugin_DBUpdateError
--- PASS: TestPluginHandler_DisablePlugin_DBUpdateError (0.00s)
=== RUN TestPluginHandler_GetPlugin_DBInternalError
--- PASS: TestPluginHandler_GetPlugin_DBInternalError (0.00s)
=== RUN TestPluginHandler_EnablePlugin_FirstDBLookupError
--- PASS: TestPluginHandler_EnablePlugin_FirstDBLookupError (0.00s)
=== RUN TestPluginHandler_DisablePlugin_FirstDBLookupError
--- PASS: TestPluginHandler_DisablePlugin_FirstDBLookupError (0.00s)
=== RUN TestPluginHandler_EnablePlugin_DatabaseUpdateError
--- PASS: TestPluginHandler_EnablePlugin_DatabaseUpdateError (0.00s)
=== RUN TestPluginHandler_DisablePlugin_DatabaseUpdateError
--- PASS: TestPluginHandler_DisablePlugin_DatabaseUpdateError (0.00s)
=== RUN TestPluginHandler_GetPlugin_DatabaseError
--- PASS: TestPluginHandler_GetPlugin_DatabaseError (0.00s)
=== RUN TestPluginHandler_EnablePlugin_DatabaseFirstError
--- PASS: TestPluginHandler_EnablePlugin_DatabaseFirstError (0.00s)
=== RUN TestPluginHandler_DisablePlugin_DatabaseFirstError
--- PASS: TestPluginHandler_DisablePlugin_DatabaseFirstError (0.00s)
=== RUN TestEncryptionHandler_Validate_NonAdminAccess
--- PASS: TestEncryptionHandler_Validate_NonAdminAccess (0.03s)
=== RUN TestEncryptionHandler_GetHistory_PaginationBoundary
--- PASS: TestEncryptionHandler_GetHistory_PaginationBoundary (0.03s)
=== RUN TestEncryptionHandler_GetStatus_VersionInfo
--- PASS: TestEncryptionHandler_GetStatus_VersionInfo (0.03s)
=== RUN TestSettingsHandler_TestPublicURL_RoleNotExists
--- PASS: TestSettingsHandler_TestPublicURL_RoleNotExists (0.00s)
=== RUN TestSettingsHandler_TestPublicURL_InvalidURLFormat
--- PASS: TestSettingsHandler_TestPublicURL_InvalidURLFormat (0.00s)
=== RUN TestSettingsHandler_TestPublicURL_PrivateIPBlocked_Coverage
--- PASS: TestSettingsHandler_TestPublicURL_PrivateIPBlocked_Coverage (0.00s)
=== RUN TestSettingsHandler_ValidatePublicURL_WithTrailingSlash
--- PASS: TestSettingsHandler_ValidatePublicURL_WithTrailingSlash (0.00s)
=== RUN TestSettingsHandler_ValidatePublicURL_MissingScheme
--- PASS: TestSettingsHandler_ValidatePublicURL_MissingScheme (0.00s)
=== RUN TestAuditLogHandler_List_PaginationEdgeCases
2026/01/10 02:23:59 /projects/Charon/backend/internal/api/handlers/pr_coverage_test.go:408 UNIQUE constraint failed: security_audits.uuid
[0.315ms] [rows:0] INSERT INTO `security_audits` (`uuid`,`actor`,`action`,`event_category`,`resource_id`,`resource_uuid`,`details`,`ip_address`,`user_agent`,`created_at`) VALUES ("","user1","action_1","test",NULL,"","{}","","","2026-01-10 02:23:59.873") RETURNING `id`
2026/01/10 02:23:59 /projects/Charon/backend/internal/api/handlers/pr_coverage_test.go:408 UNIQUE constraint failed: security_audits.uuid
[0.249ms] [rows:0] INSERT INTO `security_audits` (`uuid`,`actor`,`action`,`event_category`,`resource_id`,`resource_uuid`,`details`,`ip_address`,`user_agent`,`created_at`) VALUES ("","user1","action_2","test",NULL,"","{}","","","2026-01-10 02:23:59.873") RETURNING `id`
2026/01/10 02:23:59 /projects/Charon/backend/internal/api/handlers/pr_coverage_test.go:408 UNIQUE constraint failed: security_audits.uuid
[0.385ms] [rows:0] INSERT INTO `security_audits` (`uuid`,`actor`,`action`,`event_category`,`resource_id`,`resource_uuid`,`details`,`ip_address`,`user_agent`,`created_at`) VALUES ("","user1","action_3","test",NULL,"","{}","","","2026-01-10 02:23:59.873") RETURNING `id`
2026/01/10 02:23:59 /projects/Charon/backend/internal/api/handlers/pr_coverage_test.go:408 UNIQUE constraint failed: security_audits.uuid
[0.424ms] [rows:0] INSERT INTO `security_audits` (`uuid`,`actor`,`action`,`event_category`,`resource_id`,`resource_uuid`,`details`,`ip_address`,`user_agent`,`created_at`) VALUES ("","user1","action_4","test",NULL,"","{}","","","2026-01-10 02:23:59.874") RETURNING `id`
2026/01/10 02:23:59 /projects/Charon/backend/internal/api/handlers/pr_coverage_test.go:408 UNIQUE constraint failed: security_audits.uuid
[0.194ms] [rows:0] INSERT INTO `security_audits` (`uuid`,`actor`,`action`,`event_category`,`resource_id`,`resource_uuid`,`details`,`ip_address`,`user_agent`,`created_at`) VALUES ("","user1","action_5","test",NULL,"","{}","","","2026-01-10 02:23:59.875") RETURNING `id`
2026/01/10 02:23:59 /projects/Charon/backend/internal/api/handlers/pr_coverage_test.go:408 UNIQUE constraint failed: security_audits.uuid
[0.239ms] [rows:0] INSERT INTO `security_audits` (`uuid`,`actor`,`action`,`event_category`,`resource_id`,`resource_uuid`,`details`,`ip_address`,`user_agent`,`created_at`) VALUES ("","user1","action_6","test",NULL,"","{}","","","2026-01-10 02:23:59.875") RETURNING `id`
2026/01/10 02:23:59 /projects/Charon/backend/internal/api/handlers/pr_coverage_test.go:408 UNIQUE constraint failed: security_audits.uuid
[0.169ms] [rows:0] INSERT INTO `security_audits` (`uuid`,`actor`,`action`,`event_category`,`resource_id`,`resource_uuid`,`details`,`ip_address`,`user_agent`,`created_at`) VALUES ("","user1","action_7","test",NULL,"","{}","","","2026-01-10 02:23:59.875") RETURNING `id`
2026/01/10 02:23:59 /projects/Charon/backend/internal/api/handlers/pr_coverage_test.go:408 UNIQUE constraint failed: security_audits.uuid
[0.214ms] [rows:0] INSERT INTO `security_audits` (`uuid`,`actor`,`action`,`event_category`,`resource_id`,`resource_uuid`,`details`,`ip_address`,`user_agent`,`created_at`) VALUES ("","user1","action_8","test",NULL,"","{}","","","2026-01-10 02:23:59.875") RETURNING `id`
2026/01/10 02:23:59 /projects/Charon/backend/internal/api/handlers/pr_coverage_test.go:408 UNIQUE constraint failed: security_audits.uuid
[0.157ms] [rows:0] INSERT INTO `security_audits` (`uuid`,`actor`,`action`,`event_category`,`resource_id`,`resource_uuid`,`details`,`ip_address`,`user_agent`,`created_at`) VALUES ("","user1","action_9","test",NULL,"","{}","","","2026-01-10 02:23:59.876") RETURNING `id`
--- PASS: TestAuditLogHandler_List_PaginationEdgeCases (0.04s)
=== RUN TestAuditLogHandler_List_CategoryFilter
2026/01/10 02:23:59 /projects/Charon/backend/internal/api/handlers/pr_coverage_test.go:447 UNIQUE constraint failed: security_audits.uuid
[0.321ms] [rows:0] INSERT INTO `security_audits` (`uuid`,`actor`,`action`,`event_category`,`resource_id`,`resource_uuid`,`details`,`ip_address`,`user_agent`,`created_at`) VALUES ("","user2","action2","security",NULL,"","{}","","","2026-01-10 02:23:59.909") RETURNING `id`
--- PASS: TestAuditLogHandler_List_CategoryFilter (0.03s)
=== RUN TestAuditLogHandler_ListByProvider_DatabaseError
2026/01/10 02:23:59 /projects/Charon/backend/internal/services/security_service.go:339 sql: database is closed
[0.025ms] [rows:0] SELECT count(*) FROM `security_audits` WHERE event_category = "dns_provider" AND resource_id = 1
--- PASS: TestAuditLogHandler_ListByProvider_DatabaseError (0.03s)
=== RUN TestAuditLogHandler_ListByProvider_InvalidProviderID
--- PASS: TestAuditLogHandler_ListByProvider_InvalidProviderID (0.03s)
=== RUN TestGetActorFromGinContext_InvalidUserIDType
--- PASS: TestGetActorFromGinContext_InvalidUserIDType (0.00s)
=== RUN TestIsAdmin_NonAdminRole
--- PASS: TestIsAdmin_NonAdminRole (0.00s)
=== RUN TestCredentialHandler_Update_InvalidProviderType
--- PASS: TestCredentialHandler_Update_InvalidProviderType (0.01s)
=== RUN TestCredentialHandler_List_DatabaseClosed
2026/01/10 02:23:59 /projects/Charon/backend/internal/services/credential_service.go:86 sql: database is closed
[0.032ms] [rows:0] SELECT * FROM `dns_providers` WHERE `dns_providers`.`id` = 1 ORDER BY `dns_providers`.`id` LIMIT 1
--- PASS: TestCredentialHandler_List_DatabaseClosed (0.00s)
=== RUN TestSettingsHandler_MaskPasswordForTestFunction
=== RUN TestSettingsHandler_MaskPasswordForTestFunction/empty_string
=== RUN TestSettingsHandler_MaskPasswordForTestFunction/non-empty_password
=== RUN TestSettingsHandler_MaskPasswordForTestFunction/already_masked
=== RUN TestSettingsHandler_MaskPasswordForTestFunction/single_char
--- PASS: TestSettingsHandler_MaskPasswordForTestFunction (0.00s)
--- PASS: TestSettingsHandler_MaskPasswordForTestFunction/empty_string (0.00s)
--- PASS: TestSettingsHandler_MaskPasswordForTestFunction/non-empty_password (0.00s)
--- PASS: TestSettingsHandler_MaskPasswordForTestFunction/already_masked (0.00s)
--- PASS: TestSettingsHandler_MaskPasswordForTestFunction/single_char (0.00s)
=== RUN TestCredentialHandler_Update_NotFoundError
2026/01/10 02:23:59 /projects/Charon/backend/internal/services/credential_service.go:111 record not found
[0.132ms] [rows:0] SELECT * FROM `dns_provider_credentials` WHERE id = 9999 AND dns_provider_id = 1 ORDER BY `dns_provider_credentials`.`id` LIMIT 1
--- PASS: TestCredentialHandler_Update_NotFoundError (0.01s)
=== RUN TestCredentialHandler_Update_MalformedJSON
--- PASS: TestCredentialHandler_Update_MalformedJSON (0.01s)
=== RUN TestCredentialHandler_Update_BadCredentialID
--- PASS: TestCredentialHandler_Update_BadCredentialID (0.00s)
=== RUN TestCredentialHandler_Delete_NotFoundError
2026/01/10 02:24:00 /projects/Charon/backend/internal/services/credential_service.go:111 record not found
[0.118ms] [rows:0] SELECT * FROM `dns_provider_credentials` WHERE id = 9999 AND dns_provider_id = 1 ORDER BY `dns_provider_credentials`.`id` LIMIT 1
--- PASS: TestCredentialHandler_Delete_NotFoundError (0.01s)
=== RUN TestCredentialHandler_Delete_BadCredentialID
--- PASS: TestCredentialHandler_Delete_BadCredentialID (0.02s)
=== RUN TestCredentialHandler_Test_BadCredentialID
--- PASS: TestCredentialHandler_Test_BadCredentialID (0.01s)
=== RUN TestCredentialHandler_EnableMultiCredentials_BadProviderID
--- PASS: TestCredentialHandler_EnableMultiCredentials_BadProviderID (0.01s)
=== RUN TestEncryptionHandler_Validate_AdminSuccess
--- PASS: TestEncryptionHandler_Validate_AdminSuccess (0.09s)
=== RUN TestBulkUpdateSecurityHeaders_Success
--- PASS: TestBulkUpdateSecurityHeaders_Success (0.03s)
=== RUN TestBulkUpdateSecurityHeaders_RemoveProfile
--- PASS: TestBulkUpdateSecurityHeaders_RemoveProfile (0.02s)
=== RUN TestBulkUpdateSecurityHeaders_InvalidProfileID
2026/01/10 02:24:00 /projects/Charon/backend/internal/api/handlers/proxy_host_handler.go:615 record not found
[0.101ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE `security_header_profiles`.`id` = 99999 ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestBulkUpdateSecurityHeaders_InvalidProfileID (0.02s)
=== RUN TestBulkUpdateSecurityHeaders_EmptyUUIDs
--- PASS: TestBulkUpdateSecurityHeaders_EmptyUUIDs (0.02s)
=== RUN TestBulkUpdateSecurityHeaders_PartialFailure
2026/01/10 02:24:00 /projects/Charon/backend/internal/api/handlers/proxy_host_handler.go:638 record not found
[0.138ms] [rows:0] SELECT * FROM `proxy_hosts` WHERE uuid = "non-existent-uuid" ORDER BY `proxy_hosts`.`id` LIMIT 1
--- PASS: TestBulkUpdateSecurityHeaders_PartialFailure (0.03s)
=== RUN TestBulkUpdateSecurityHeaders_TransactionRollback
2026/01/10 02:24:00 /projects/Charon/backend/internal/api/handlers/proxy_host_handler.go:638 record not found
[0.144ms] [rows:0] SELECT * FROM `proxy_hosts` WHERE uuid = "invalid-uuid-1" ORDER BY `proxy_hosts`.`id` LIMIT 1
2026/01/10 02:24:00 /projects/Charon/backend/internal/api/handlers/proxy_host_handler.go:638 record not found
[0.137ms] [rows:0] SELECT * FROM `proxy_hosts` WHERE uuid = "invalid-uuid-2" ORDER BY `proxy_hosts`.`id` LIMIT 1
--- PASS: TestBulkUpdateSecurityHeaders_TransactionRollback (0.03s)
=== RUN TestBulkUpdateSecurityHeaders_InvalidJSON
--- PASS: TestBulkUpdateSecurityHeaders_InvalidJSON (0.02s)
=== RUN TestBulkUpdateSecurityHeaders_MixedProfileStates
--- PASS: TestBulkUpdateSecurityHeaders_MixedProfileStates (0.04s)
=== RUN TestBulkUpdateSecurityHeaders_SingleHost
--- PASS: TestBulkUpdateSecurityHeaders_SingleHost (0.02s)
=== RUN TestProxyHostLifecycle
=== PAUSE TestProxyHostLifecycle
=== RUN TestProxyHostDelete_WithUptimeCleanup
=== PAUSE TestProxyHostDelete_WithUptimeCleanup
=== RUN TestProxyHostErrors
=== PAUSE TestProxyHostErrors
=== RUN TestProxyHostValidation
=== PAUSE TestProxyHostValidation
=== RUN TestProxyHostCreate_AdvancedConfig_InvalidJSON
=== PAUSE TestProxyHostCreate_AdvancedConfig_InvalidJSON
=== RUN TestProxyHostCreate_AdvancedConfig_Normalization
=== PAUSE TestProxyHostCreate_AdvancedConfig_Normalization
=== RUN TestProxyHostUpdate_CertificateID_Null
=== PAUSE TestProxyHostUpdate_CertificateID_Null
=== RUN TestProxyHostConnection
=== PAUSE TestProxyHostConnection
=== RUN TestProxyHostHandler_List_Error
=== PAUSE TestProxyHostHandler_List_Error
=== RUN TestProxyHostWithCaddyIntegration
=== PAUSE TestProxyHostWithCaddyIntegration
=== RUN TestProxyHostHandler_BulkUpdateACL_Success
=== PAUSE TestProxyHostHandler_BulkUpdateACL_Success
=== RUN TestProxyHostHandler_BulkUpdateACL_RemoveACL
=== PAUSE TestProxyHostHandler_BulkUpdateACL_RemoveACL
=== RUN TestProxyHostHandler_BulkUpdateACL_PartialFailure
=== PAUSE TestProxyHostHandler_BulkUpdateACL_PartialFailure
=== RUN TestProxyHostHandler_BulkUpdateACL_EmptyUUIDs
=== PAUSE TestProxyHostHandler_BulkUpdateACL_EmptyUUIDs
=== RUN TestProxyHostHandler_BulkUpdateACL_InvalidJSON
=== PAUSE TestProxyHostHandler_BulkUpdateACL_InvalidJSON
=== RUN TestProxyHostUpdate_AdvancedConfig_ClearAndBackup
=== PAUSE TestProxyHostUpdate_AdvancedConfig_ClearAndBackup
=== RUN TestProxyHostUpdate_AdvancedConfig_InvalidJSON
=== PAUSE TestProxyHostUpdate_AdvancedConfig_InvalidJSON
=== RUN TestProxyHostUpdate_SetCertificateID
=== PAUSE TestProxyHostUpdate_SetCertificateID
=== RUN TestProxyHostUpdate_AdvancedConfig_SetBackup
=== PAUSE TestProxyHostUpdate_AdvancedConfig_SetBackup
=== RUN TestProxyHostUpdate_ForwardPort_StringValue
=== PAUSE TestProxyHostUpdate_ForwardPort_StringValue
=== RUN TestProxyHostUpdate_Locations_InvalidPayload
=== PAUSE TestProxyHostUpdate_Locations_InvalidPayload
=== RUN TestProxyHostUpdate_SetBooleansAndApplication
=== PAUSE TestProxyHostUpdate_SetBooleansAndApplication
=== RUN TestProxyHostUpdate_Locations_Replace
=== PAUSE TestProxyHostUpdate_Locations_Replace
=== RUN TestProxyHostCreate_WithCertificateAndLocations
=== PAUSE TestProxyHostCreate_WithCertificateAndLocations
=== RUN TestProxyHostCreate_WithSecurityHeaderProfile
=== PAUSE TestProxyHostCreate_WithSecurityHeaderProfile
=== RUN TestProxyHostUpdate_AssignSecurityHeaderProfile
=== PAUSE TestProxyHostUpdate_AssignSecurityHeaderProfile
=== RUN TestProxyHostUpdate_ChangeSecurityHeaderProfile
=== PAUSE TestProxyHostUpdate_ChangeSecurityHeaderProfile
=== RUN TestProxyHostUpdate_RemoveSecurityHeaderProfile
=== PAUSE TestProxyHostUpdate_RemoveSecurityHeaderProfile
=== RUN TestProxyHostUpdate_InvalidSecurityHeaderProfileID
=== PAUSE TestProxyHostUpdate_InvalidSecurityHeaderProfileID
=== RUN TestProxyHostUpdate_SecurityHeaderProfile_StrictToBasic
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfile_StrictToBasic
=== RUN TestProxyHostUpdate_SecurityHeaderProfile_ToNone
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfile_ToNone
=== RUN TestProxyHostUpdate_SecurityHeaderProfile_FromNoneToValid
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfile_FromNoneToValid
=== RUN TestProxyHostUpdate_SecurityHeaderProfile_InvalidString
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfile_InvalidString
=== RUN TestProxyHostUpdate_SecurityHeaderProfile_InvalidFloat
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfile_InvalidFloat
=== RUN TestProxyHostUpdate_SecurityHeaderProfile_ValidString
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfile_ValidString
=== RUN TestProxyHostUpdate_SecurityHeaderProfile_UnsupportedType
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfile_UnsupportedType
=== RUN TestUpdate_EnableStandardHeaders
=== PAUSE TestUpdate_EnableStandardHeaders
=== RUN TestUpdate_ForwardAuthEnabled
=== PAUSE TestUpdate_ForwardAuthEnabled
=== RUN TestUpdate_WAFDisabled
=== PAUSE TestUpdate_WAFDisabled
=== RUN TestUpdate_IntegrationCaddyConfig
=== PAUSE TestUpdate_IntegrationCaddyConfig
=== RUN TestUpdate_ExistingHostsBackwardCompatibility
=== PAUSE TestUpdate_ExistingHostsBackwardCompatibility
=== RUN TestProxyHostHandler_BulkUpdateSecurityHeaders_Success
=== PAUSE TestProxyHostHandler_BulkUpdateSecurityHeaders_Success
=== RUN TestProxyHostHandler_BulkUpdateSecurityHeaders_RemoveProfile
=== PAUSE TestProxyHostHandler_BulkUpdateSecurityHeaders_RemoveProfile
=== RUN TestProxyHostHandler_BulkUpdateSecurityHeaders_PartialFailure
=== PAUSE TestProxyHostHandler_BulkUpdateSecurityHeaders_PartialFailure
=== RUN TestProxyHostHandler_BulkUpdateSecurityHeaders_EmptyUUIDs
=== PAUSE TestProxyHostHandler_BulkUpdateSecurityHeaders_EmptyUUIDs
=== RUN TestProxyHostHandler_BulkUpdateSecurityHeaders_InvalidJSON
=== PAUSE TestProxyHostHandler_BulkUpdateSecurityHeaders_InvalidJSON
=== RUN TestProxyHostHandler_BulkUpdateSecurityHeaders_ProfileNotFound
=== PAUSE TestProxyHostHandler_BulkUpdateSecurityHeaders_ProfileNotFound
=== RUN TestProxyHostHandler_BulkUpdateSecurityHeaders_AllFail
=== PAUSE TestProxyHostHandler_BulkUpdateSecurityHeaders_AllFail
=== RUN TestProxyHostUpdate_NegativeIntCertificateID
=== PAUSE TestProxyHostUpdate_NegativeIntCertificateID
=== RUN TestProxyHostUpdate_AccessListID_StringValue
=== PAUSE TestProxyHostUpdate_AccessListID_StringValue
=== RUN TestProxyHostUpdate_AccessListID_IntValue
=== PAUSE TestProxyHostUpdate_AccessListID_IntValue
=== RUN TestProxyHostUpdate_CertificateID_IntValue
=== PAUSE TestProxyHostUpdate_CertificateID_IntValue
=== RUN TestProxyHostUpdate_CertificateID_StringValue
=== PAUSE TestProxyHostUpdate_CertificateID_StringValue
=== RUN TestProxyHostUpdate_EnableStandardHeaders_Null
=== PAUSE TestProxyHostUpdate_EnableStandardHeaders_Null
=== RUN TestProxyHostUpdate_EnableStandardHeaders_True
=== PAUSE TestProxyHostUpdate_EnableStandardHeaders_True
=== RUN TestProxyHostUpdate_EnableStandardHeaders_False
=== PAUSE TestProxyHostUpdate_EnableStandardHeaders_False
=== RUN TestProxyHostUpdate_ForwardAuthEnabled
=== PAUSE TestProxyHostUpdate_ForwardAuthEnabled
=== RUN TestProxyHostUpdate_WAFDisabled
=== PAUSE TestProxyHostUpdate_WAFDisabled
=== RUN TestProxyHostUpdate_SecurityHeaderProfileID_NegativeFloat
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfileID_NegativeFloat
=== RUN TestProxyHostUpdate_SecurityHeaderProfileID_NegativeInt
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfileID_NegativeInt
=== RUN TestProxyHostUpdate_SecurityHeaderProfileID_InvalidString
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfileID_InvalidString
=== RUN TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType
=== RUN TestProxyHostUpdate_SecurityHeaderProfileID_ValidAssignment
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfileID_ValidAssignment
=== RUN TestProxyHostUpdate_SecurityHeaderProfileID_SetToNull
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfileID_SetToNull
=== RUN TestBulkUpdateSecurityHeaders_DBError_NonNotFound
=== PAUSE TestBulkUpdateSecurityHeaders_DBError_NonNotFound
=== RUN TestSanitizeForLog
--- PASS: TestSanitizeForLog (0.00s)
=== RUN TestSecurityHandler_GetGeoIPStatus_NotInitialized
--- PASS: TestSecurityHandler_GetGeoIPStatus_NotInitialized (0.00s)
=== RUN TestSecurityHandler_GetGeoIPStatus_Initialized_NotLoaded
--- PASS: TestSecurityHandler_GetGeoIPStatus_Initialized_NotLoaded (0.00s)
=== RUN TestSecurityHandler_ReloadGeoIP_NotInitialized
--- PASS: TestSecurityHandler_ReloadGeoIP_NotInitialized (0.00s)
=== RUN TestSecurityHandler_ReloadGeoIP_LoadError
time="2026-01-10T02:24:00Z" level=error msg="Failed to reload GeoIP database" error="open : no such file or directory"
--- PASS: TestSecurityHandler_ReloadGeoIP_LoadError (0.00s)
=== RUN TestSecurityHandler_LookupGeoIP_MissingIPAddress
--- PASS: TestSecurityHandler_LookupGeoIP_MissingIPAddress (0.00s)
=== RUN TestSecurityHandler_LookupGeoIP_ServiceUnavailable
--- PASS: TestSecurityHandler_LookupGeoIP_ServiceUnavailable (0.00s)
=== RUN TestSecurityHandler_GetConfigAndUpdateConfig
2026/01/10 02:24:00 /projects/Charon/backend/internal/services/security_service.go:70 record not found
[0.082ms] [rows:0] SELECT * FROM `security_configs` ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:00 /projects/Charon/backend/internal/services/security_service.go:106 record not found
[0.107ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
--- PASS: TestSecurityHandler_GetConfigAndUpdateConfig (0.00s)
=== RUN TestSecurityHandler_GetStatus_SQLInjection
--- PASS: TestSecurityHandler_GetStatus_SQLInjection (0.03s)
=== RUN TestSecurityHandler_CreateDecision_SQLInjection
=== RUN TestSecurityHandler_CreateDecision_SQLInjection/payload_0
=== RUN TestSecurityHandler_CreateDecision_SQLInjection/payload_1
=== RUN TestSecurityHandler_CreateDecision_SQLInjection/payload_2
=== RUN TestSecurityHandler_CreateDecision_SQLInjection/payload_3
--- PASS: TestSecurityHandler_CreateDecision_SQLInjection (0.02s)
--- PASS: TestSecurityHandler_CreateDecision_SQLInjection/payload_0 (0.00s)
--- PASS: TestSecurityHandler_CreateDecision_SQLInjection/payload_1 (0.00s)
--- PASS: TestSecurityHandler_CreateDecision_SQLInjection/payload_2 (0.00s)
--- PASS: TestSecurityHandler_CreateDecision_SQLInjection/payload_3 (0.00s)
=== RUN TestSecurityHandler_UpsertRuleSet_MassivePayload
--- PASS: TestSecurityHandler_UpsertRuleSet_MassivePayload (0.57s)
=== RUN TestSecurityHandler_UpsertRuleSet_EmptyName
--- PASS: TestSecurityHandler_UpsertRuleSet_EmptyName (0.01s)
=== RUN TestSecurityHandler_CreateDecision_EmptyFields
=== RUN TestSecurityHandler_CreateDecision_EmptyFields/empty_ip
=== RUN TestSecurityHandler_CreateDecision_EmptyFields/empty_action
=== RUN TestSecurityHandler_CreateDecision_EmptyFields/both_empty
=== RUN TestSecurityHandler_CreateDecision_EmptyFields/valid
--- PASS: TestSecurityHandler_CreateDecision_EmptyFields (0.02s)
--- PASS: TestSecurityHandler_CreateDecision_EmptyFields/empty_ip (0.00s)
--- PASS: TestSecurityHandler_CreateDecision_EmptyFields/empty_action (0.00s)
--- PASS: TestSecurityHandler_CreateDecision_EmptyFields/both_empty (0.00s)
--- PASS: TestSecurityHandler_CreateDecision_EmptyFields/valid (0.00s)
=== RUN TestSecurityHandler_GetStatus_SettingsOverride
--- PASS: TestSecurityHandler_GetStatus_SettingsOverride (0.02s)
=== RUN TestSecurityHandler_GetStatus_DisabledViaSettings
--- PASS: TestSecurityHandler_GetStatus_DisabledViaSettings (0.02s)
=== RUN TestSecurityAudit_DeleteRuleSet_InvalidID
=== RUN TestSecurityAudit_DeleteRuleSet_InvalidID/empty_id
=== RUN TestSecurityAudit_DeleteRuleSet_InvalidID/non_numeric
=== RUN TestSecurityAudit_DeleteRuleSet_InvalidID/negative
=== RUN TestSecurityAudit_DeleteRuleSet_InvalidID/sql_injection
=== RUN TestSecurityAudit_DeleteRuleSet_InvalidID/not_found
--- PASS: TestSecurityAudit_DeleteRuleSet_InvalidID (0.02s)
--- PASS: TestSecurityAudit_DeleteRuleSet_InvalidID/empty_id (0.00s)
--- PASS: TestSecurityAudit_DeleteRuleSet_InvalidID/non_numeric (0.00s)
--- PASS: TestSecurityAudit_DeleteRuleSet_InvalidID/negative (0.00s)
--- PASS: TestSecurityAudit_DeleteRuleSet_InvalidID/sql_injection (0.00s)
--- PASS: TestSecurityAudit_DeleteRuleSet_InvalidID/not_found (0.00s)
=== RUN TestSecurityHandler_UpsertRuleSet_XSSInContent
--- PASS: TestSecurityHandler_UpsertRuleSet_XSSInContent (0.03s)
=== RUN TestSecurityHandler_UpdateConfig_RateLimitBounds
=== RUN TestSecurityHandler_UpdateConfig_RateLimitBounds/valid_limits
=== RUN TestSecurityHandler_UpdateConfig_RateLimitBounds/zero_requests
=== RUN TestSecurityHandler_UpdateConfig_RateLimitBounds/negative_burst
=== RUN TestSecurityHandler_UpdateConfig_RateLimitBounds/huge_values
--- PASS: TestSecurityHandler_UpdateConfig_RateLimitBounds (0.02s)
--- PASS: TestSecurityHandler_UpdateConfig_RateLimitBounds/valid_limits (0.00s)
--- PASS: TestSecurityHandler_UpdateConfig_RateLimitBounds/zero_requests (0.00s)
--- PASS: TestSecurityHandler_UpdateConfig_RateLimitBounds/negative_burst (0.00s)
--- PASS: TestSecurityHandler_UpdateConfig_RateLimitBounds/huge_values (0.00s)
=== RUN TestSecurityHandler_GetStatus_NilDB
--- PASS: TestSecurityHandler_GetStatus_NilDB (0.00s)
=== RUN TestSecurityHandler_Enable_WithoutWhitelist
--- PASS: TestSecurityHandler_Enable_WithoutWhitelist (0.01s)
=== RUN TestSecurityHandler_Disable_RequiresToken
--- PASS: TestSecurityHandler_Disable_RequiresToken (0.03s)
=== RUN TestSecurityHandler_GetStatus_CrowdSecModeValidation
=== RUN TestSecurityHandler_GetStatus_CrowdSecModeValidation/mode_remote
=== RUN TestSecurityHandler_GetStatus_CrowdSecModeValidation/mode_external
=== RUN TestSecurityHandler_GetStatus_CrowdSecModeValidation/mode_cloud
=== RUN TestSecurityHandler_GetStatus_CrowdSecModeValidation/mode_api
=== RUN TestSecurityHandler_GetStatus_CrowdSecModeValidation/mode_../../../etc/passwd
--- PASS: TestSecurityHandler_GetStatus_CrowdSecModeValidation (0.03s)
--- PASS: TestSecurityHandler_GetStatus_CrowdSecModeValidation/mode_remote (0.01s)
--- PASS: TestSecurityHandler_GetStatus_CrowdSecModeValidation/mode_external (0.00s)
--- PASS: TestSecurityHandler_GetStatus_CrowdSecModeValidation/mode_cloud (0.00s)
--- PASS: TestSecurityHandler_GetStatus_CrowdSecModeValidation/mode_api (0.00s)
--- PASS: TestSecurityHandler_GetStatus_CrowdSecModeValidation/mode_../../../etc/passwd (0.00s)
=== RUN TestSecurityHandler_GetStatus_Clean
--- PASS: TestSecurityHandler_GetStatus_Clean (0.00s)
=== RUN TestSecurityHandler_Cerberus_DBOverride
--- PASS: TestSecurityHandler_Cerberus_DBOverride (0.01s)
=== RUN TestSecurityHandler_ACL_DBOverride
--- PASS: TestSecurityHandler_ACL_DBOverride (0.02s)
=== RUN TestSecurityHandler_GenerateBreakGlass_ReturnsToken
--- PASS: TestSecurityHandler_GenerateBreakGlass_ReturnsToken (1.09s)
=== RUN TestSecurityHandler_ACL_DisabledWhenCerberusOff
--- PASS: TestSecurityHandler_ACL_DisabledWhenCerberusOff (0.01s)
=== RUN TestSecurityHandler_CrowdSec_Mode_DBOverride
--- PASS: TestSecurityHandler_CrowdSec_Mode_DBOverride (0.01s)
=== RUN TestSecurityHandler_CrowdSec_ExternalMappedToDisabled_DBOverride
--- PASS: TestSecurityHandler_CrowdSec_ExternalMappedToDisabled_DBOverride (0.01s)
=== RUN TestSecurityHandler_ExternalModeMappedToDisabled
--- PASS: TestSecurityHandler_ExternalModeMappedToDisabled (0.00s)
=== RUN TestSecurityHandler_Enable_Disable_WithAdminWhitelistAndToken
--- PASS: TestSecurityHandler_Enable_Disable_WithAdminWhitelistAndToken (1.52s)
=== RUN TestSecurityHandler_UpdateConfig_Success
--- PASS: TestSecurityHandler_UpdateConfig_Success (0.02s)
=== RUN TestSecurityHandler_UpdateConfig_DefaultName
--- PASS: TestSecurityHandler_UpdateConfig_DefaultName (0.02s)
=== RUN TestSecurityHandler_UpdateConfig_InvalidPayload
--- PASS: TestSecurityHandler_UpdateConfig_InvalidPayload (0.01s)
=== RUN TestSecurityHandler_GetConfig_Success
--- PASS: TestSecurityHandler_GetConfig_Success (0.01s)
=== RUN TestSecurityHandler_GetConfig_NotFound
--- PASS: TestSecurityHandler_GetConfig_NotFound (0.01s)
=== RUN TestSecurityHandler_ListDecisions_Success
--- PASS: TestSecurityHandler_ListDecisions_Success (0.01s)
=== RUN TestSecurityHandler_ListDecisions_WithLimit
--- PASS: TestSecurityHandler_ListDecisions_WithLimit (0.01s)
=== RUN TestSecurityHandler_CreateDecision_Success
--- PASS: TestSecurityHandler_CreateDecision_Success (0.01s)
=== RUN TestSecurityHandler_CreateDecision_MissingIP
--- PASS: TestSecurityHandler_CreateDecision_MissingIP (0.01s)
=== RUN TestSecurityHandler_CreateDecision_MissingAction
--- PASS: TestSecurityHandler_CreateDecision_MissingAction (0.01s)
=== RUN TestSecurityHandler_CreateDecision_InvalidPayload
--- PASS: TestSecurityHandler_CreateDecision_InvalidPayload (0.01s)
=== RUN TestSecurityHandler_ListRuleSets_Success
--- PASS: TestSecurityHandler_ListRuleSets_Success (0.01s)
=== RUN TestSecurityHandler_UpsertRuleSet_Success
--- PASS: TestSecurityHandler_UpsertRuleSet_Success (0.01s)
=== RUN TestSecurityHandler_UpsertRuleSet_MissingName
--- PASS: TestSecurityHandler_UpsertRuleSet_MissingName (0.00s)
=== RUN TestSecurityHandler_UpsertRuleSet_InvalidPayload
--- PASS: TestSecurityHandler_UpsertRuleSet_InvalidPayload (0.01s)
=== RUN TestSecurityHandler_DeleteRuleSet_Success
--- PASS: TestSecurityHandler_DeleteRuleSet_Success (0.01s)
=== RUN TestSecurityHandler_DeleteRuleSet_NotFound
--- PASS: TestSecurityHandler_DeleteRuleSet_NotFound (0.01s)
=== RUN TestSecurityHandler_DeleteRuleSet_InvalidID
--- PASS: TestSecurityHandler_DeleteRuleSet_InvalidID (0.01s)
=== RUN TestSecurityHandler_DeleteRuleSet_EmptyID
--- PASS: TestSecurityHandler_DeleteRuleSet_EmptyID (0.00s)
=== RUN TestSecurityHandler_Enable_NoConfigNoWhitelist
--- PASS: TestSecurityHandler_Enable_NoConfigNoWhitelist (0.01s)
=== RUN TestSecurityHandler_Enable_WithWhitelist
--- PASS: TestSecurityHandler_Enable_WithWhitelist (0.01s)
=== RUN TestSecurityHandler_Enable_IPNotInWhitelist
--- PASS: TestSecurityHandler_Enable_IPNotInWhitelist (0.01s)
=== RUN TestSecurityHandler_Enable_WithValidBreakGlassToken
--- PASS: TestSecurityHandler_Enable_WithValidBreakGlassToken (1.51s)
=== RUN TestSecurityHandler_Enable_WithInvalidBreakGlassToken
--- PASS: TestSecurityHandler_Enable_WithInvalidBreakGlassToken (0.01s)
=== RUN TestSecurityHandler_Disable_FromLocalhost
--- PASS: TestSecurityHandler_Disable_FromLocalhost (0.01s)
=== RUN TestSecurityHandler_Disable_FromRemoteWithToken
--- PASS: TestSecurityHandler_Disable_FromRemoteWithToken (1.49s)
=== RUN TestSecurityHandler_Disable_FromRemoteNoToken
--- PASS: TestSecurityHandler_Disable_FromRemoteNoToken (0.01s)
=== RUN TestSecurityHandler_Disable_FromRemoteInvalidToken
--- PASS: TestSecurityHandler_Disable_FromRemoteInvalidToken (0.01s)
=== RUN TestSecurityHandler_GenerateBreakGlass_NoConfig
--- PASS: TestSecurityHandler_GenerateBreakGlass_NoConfig (0.79s)
=== RUN TestSecurityHandler_Disable_FromIPv6Localhost
--- PASS: TestSecurityHandler_Disable_FromIPv6Localhost (0.01s)
=== RUN TestSecurityHandler_Enable_WithCIDRWhitelist
--- PASS: TestSecurityHandler_Enable_WithCIDRWhitelist (0.01s)
=== RUN TestSecurityHandler_Enable_WithExactIPWhitelist
--- PASS: TestSecurityHandler_Enable_WithExactIPWhitelist (0.01s)
=== RUN TestSecurityHandler_GetStatus_Fixed
=== RUN TestSecurityHandler_GetStatus_Fixed/All_Disabled
=== RUN TestSecurityHandler_GetStatus_Fixed/All_Enabled
--- PASS: TestSecurityHandler_GetStatus_Fixed (0.00s)
--- PASS: TestSecurityHandler_GetStatus_Fixed/All_Disabled (0.00s)
--- PASS: TestSecurityHandler_GetStatus_Fixed/All_Enabled (0.00s)
=== RUN TestSecurityHandler_CreateAndListDecisionAndRulesets
2026/01/10 02:24:08 /projects/Charon/backend/internal/services/security_service.go:366 record not found
[0.186ms] [rows:0] SELECT * FROM `security_rule_sets` WHERE name = "owasp-crs" ORDER BY `security_rule_sets`.`id` LIMIT 1
--- PASS: TestSecurityHandler_CreateAndListDecisionAndRulesets (0.27s)
=== RUN TestSecurityHandler_UpsertDeleteTriggersApplyConfig
2026/01/10 02:24:08 /projects/Charon/backend/internal/services/security_service.go:251 attempt to write a readonly database
[0.701ms] [rows:0] INSERT INTO `security_audits` (`uuid`,`actor`,`action`,`event_category`,`resource_id`,`resource_uuid`,`details`,`ip_address`,`user_agent`,`created_at`) VALUES ("6418b3c6-0b2e-46da-8fee-112ba3795600","192.0.2.1","delete_ruleset","",NULL,"","1","","","2026-01-10 02:24:08.191") RETURNING `id`
Failed to write audit log: attempt to write a readonly database
2026/01/10 02:24:08 /projects/Charon/backend/internal/services/security_service.go:366 record not found
[0.101ms] [rows:0] SELECT * FROM `security_rule_sets` WHERE name = "owasp-crs" ORDER BY `security_rule_sets`.`id` LIMIT 1
2026/01/10 02:24:08 /projects/Charon/backend/internal/caddy/manager.go:90 no such table: dns_providers
[0.044ms] [rows:0] SELECT * FROM `dns_providers` WHERE enabled = true
2026/01/10 02:24:08 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.706ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:08 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.083ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:08 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.094ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:08 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.097ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:08 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.067ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:08 /projects/Charon/backend/internal/caddy/manager.go:90 no such table: dns_providers
[0.106ms] [rows:0] SELECT * FROM `dns_providers` WHERE enabled = true
2026/01/10 02:24:08 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.098ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:08 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.102ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:08 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.065ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:08 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.065ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:08 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.059ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestSecurityHandler_UpsertDeleteTriggersApplyConfig (0.04s)
=== RUN TestSecurityHandler_GetStatus_RespectsSettingsTable
=== RUN TestSecurityHandler_GetStatus_RespectsSettingsTable/WAF_enabled_via_settings_overrides_disabled_config
=== RUN TestSecurityHandler_GetStatus_RespectsSettingsTable/Rate_Limit_enabled_via_settings_overrides_disabled_config
=== RUN TestSecurityHandler_GetStatus_RespectsSettingsTable/CrowdSec_enabled_via_settings_overrides_disabled_config
=== RUN TestSecurityHandler_GetStatus_RespectsSettingsTable/All_modules_enabled_via_settings
=== RUN TestSecurityHandler_GetStatus_RespectsSettingsTable/WAF_disabled_via_settings_overrides_enabled_config
=== RUN TestSecurityHandler_GetStatus_RespectsSettingsTable/No_settings_-_falls_back_to_config_(enabled)
--- PASS: TestSecurityHandler_GetStatus_RespectsSettingsTable (0.04s)
--- PASS: TestSecurityHandler_GetStatus_RespectsSettingsTable/WAF_enabled_via_settings_overrides_disabled_config (0.01s)
--- PASS: TestSecurityHandler_GetStatus_RespectsSettingsTable/Rate_Limit_enabled_via_settings_overrides_disabled_config (0.01s)
--- PASS: TestSecurityHandler_GetStatus_RespectsSettingsTable/CrowdSec_enabled_via_settings_overrides_disabled_config (0.01s)
--- PASS: TestSecurityHandler_GetStatus_RespectsSettingsTable/All_modules_enabled_via_settings (0.01s)
--- PASS: TestSecurityHandler_GetStatus_RespectsSettingsTable/WAF_disabled_via_settings_overrides_enabled_config (0.01s)
--- PASS: TestSecurityHandler_GetStatus_RespectsSettingsTable/No_settings_-_falls_back_to_config_(enabled) (0.01s)
=== RUN TestSecurityHandler_GetStatus_WAFModeFromSettings
--- PASS: TestSecurityHandler_GetStatus_WAFModeFromSettings (0.01s)
=== RUN TestSecurityHandler_GetStatus_RateLimitModeFromSettings
--- PASS: TestSecurityHandler_GetStatus_RateLimitModeFromSettings (0.01s)
=== RUN TestSecurityHandler_GetWAFExclusions_Empty
--- PASS: TestSecurityHandler_GetWAFExclusions_Empty (0.01s)
=== RUN TestSecurityHandler_GetWAFExclusions_WithExclusions
--- PASS: TestSecurityHandler_GetWAFExclusions_WithExclusions (0.01s)
=== RUN TestSecurityHandler_GetWAFExclusions_InvalidJSON
time="2026-01-10T02:24:08Z" level=warning msg="Failed to parse WAF exclusions" error="invalid character 'i' looking for beginning of value"
--- PASS: TestSecurityHandler_GetWAFExclusions_InvalidJSON (0.01s)
=== RUN TestSecurityHandler_AddWAFExclusion_Success
--- PASS: TestSecurityHandler_AddWAFExclusion_Success (0.02s)
=== RUN TestSecurityHandler_AddWAFExclusion_WithTarget
--- PASS: TestSecurityHandler_AddWAFExclusion_WithTarget (0.01s)
=== RUN TestSecurityHandler_AddWAFExclusion_ToExistingConfig
--- PASS: TestSecurityHandler_AddWAFExclusion_ToExistingConfig (0.02s)
=== RUN TestSecurityHandler_AddWAFExclusion_Duplicate
--- PASS: TestSecurityHandler_AddWAFExclusion_Duplicate (0.01s)
=== RUN TestSecurityHandler_AddWAFExclusion_DuplicateWithDifferentTarget
--- PASS: TestSecurityHandler_AddWAFExclusion_DuplicateWithDifferentTarget (0.02s)
=== RUN TestSecurityHandler_AddWAFExclusion_MissingRuleID
--- PASS: TestSecurityHandler_AddWAFExclusion_MissingRuleID (0.01s)
=== RUN TestSecurityHandler_AddWAFExclusion_InvalidRuleID
--- PASS: TestSecurityHandler_AddWAFExclusion_InvalidRuleID (0.01s)
=== RUN TestSecurityHandler_AddWAFExclusion_NegativeRuleID
--- PASS: TestSecurityHandler_AddWAFExclusion_NegativeRuleID (0.01s)
=== RUN TestSecurityHandler_AddWAFExclusion_InvalidPayload
--- PASS: TestSecurityHandler_AddWAFExclusion_InvalidPayload (0.01s)
=== RUN TestSecurityHandler_DeleteWAFExclusion_Success
--- PASS: TestSecurityHandler_DeleteWAFExclusion_Success (0.01s)
=== RUN TestSecurityHandler_DeleteWAFExclusion_WithTarget
--- PASS: TestSecurityHandler_DeleteWAFExclusion_WithTarget (0.02s)
=== RUN TestSecurityHandler_DeleteWAFExclusion_NotFound
--- PASS: TestSecurityHandler_DeleteWAFExclusion_NotFound (0.01s)
=== RUN TestSecurityHandler_DeleteWAFExclusion_NoConfig
--- PASS: TestSecurityHandler_DeleteWAFExclusion_NoConfig (0.01s)
=== RUN TestSecurityHandler_DeleteWAFExclusion_InvalidRuleID
--- PASS: TestSecurityHandler_DeleteWAFExclusion_InvalidRuleID (0.01s)
=== RUN TestSecurityHandler_DeleteWAFExclusion_ZeroRuleID
--- PASS: TestSecurityHandler_DeleteWAFExclusion_ZeroRuleID (0.01s)
=== RUN TestSecurityHandler_DeleteWAFExclusion_NegativeRuleID
--- PASS: TestSecurityHandler_DeleteWAFExclusion_NegativeRuleID (0.01s)
=== RUN TestSecurityHandler_WAFExclusion_FullWorkflow
--- PASS: TestSecurityHandler_WAFExclusion_FullWorkflow (0.01s)
=== RUN TestProxyHost_WAFDisabled_DefaultFalse
--- PASS: TestProxyHost_WAFDisabled_DefaultFalse (0.02s)
=== RUN TestProxyHost_WAFDisabled_SetTrue
--- PASS: TestProxyHost_WAFDisabled_SetTrue (0.02s)
=== RUN TestSecurityConfig_WAFParanoiaLevel_Default
--- PASS: TestSecurityConfig_WAFParanoiaLevel_Default (0.01s)
=== RUN TestSecurityConfig_WAFParanoiaLevel_CustomValue
--- PASS: TestSecurityConfig_WAFParanoiaLevel_CustomValue (0.01s)
=== RUN TestSecurityConfig_WAFExclusions_Empty
--- PASS: TestSecurityConfig_WAFExclusions_Empty (0.01s)
=== RUN TestSecurityConfig_WAFExclusions_JSONArray
--- PASS: TestSecurityConfig_WAFExclusions_JSONArray (0.01s)
=== RUN TestListProfiles
--- PASS: TestListProfiles (0.01s)
=== RUN TestGetProfile_ByID
--- PASS: TestGetProfile_ByID (0.02s)
=== RUN TestGetProfile_ByUUID
--- PASS: TestGetProfile_ByUUID (0.01s)
=== RUN TestGetProfile_NotFound
2026/01/10 02:24:08 /projects/Charon/backend/internal/api/handlers/security_headers_handler.go:72 record not found
[0.131ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE `security_header_profiles`.`id` = 99999 ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestGetProfile_NotFound (0.01s)
=== RUN TestCreateProfile
--- PASS: TestCreateProfile (0.01s)
=== RUN TestCreateProfile_MissingName
--- PASS: TestCreateProfile_MissingName (0.01s)
=== RUN TestUpdateProfile
--- PASS: TestUpdateProfile (0.01s)
=== RUN TestUpdateProfile_CannotModifyPreset
--- PASS: TestUpdateProfile_CannotModifyPreset (0.01s)
=== RUN TestDeleteProfile
--- PASS: TestDeleteProfile (0.01s)
=== RUN TestDeleteProfile_CannotDeletePreset
--- PASS: TestDeleteProfile_CannotDeletePreset (0.02s)
=== RUN TestDeleteProfile_InUse
--- PASS: TestDeleteProfile_InUse (0.01s)
=== RUN TestGetPresets
--- PASS: TestGetPresets (0.01s)
=== RUN TestApplyPreset
--- PASS: TestApplyPreset (0.02s)
=== RUN TestApplyPreset_InvalidType
--- PASS: TestApplyPreset_InvalidType (0.01s)
=== RUN TestCalculateScore
--- PASS: TestCalculateScore (0.01s)
=== RUN TestValidateCSP_Valid
--- PASS: TestValidateCSP_Valid (0.01s)
=== RUN TestValidateCSP_Invalid
--- PASS: TestValidateCSP_Invalid (0.01s)
=== RUN TestValidateCSP_UnsafeDirectives
--- PASS: TestValidateCSP_UnsafeDirectives (0.01s)
=== RUN TestBuildCSP
--- PASS: TestBuildCSP (0.01s)
=== RUN TestListProfiles_DBError
2026/01/10 02:24:08 /projects/Charon/backend/internal/api/handlers/security_headers_handler.go:56 sql: database is closed
[0.032ms] [rows:0] SELECT * FROM `security_header_profiles` ORDER BY is_preset DESC, name ASC
--- PASS: TestListProfiles_DBError (0.01s)
=== RUN TestGetProfile_UUID_NotFound
2026/01/10 02:24:08 /projects/Charon/backend/internal/api/handlers/security_headers_handler.go:82 record not found
[0.115ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "non-existent-uuid-12345" ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestGetProfile_UUID_NotFound (0.01s)
=== RUN TestGetProfile_ID_DBError
2026/01/10 02:24:08 /projects/Charon/backend/internal/api/handlers/security_headers_handler.go:72 sql: database is closed
[0.050ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE `security_header_profiles`.`id` = 1 ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestGetProfile_ID_DBError (0.01s)
=== RUN TestGetProfile_UUID_DBError
2026/01/10 02:24:08 /projects/Charon/backend/internal/api/handlers/security_headers_handler.go:82 sql: database is closed
[0.038ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "some-uuid-format" ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestGetProfile_UUID_DBError (0.01s)
=== RUN TestCreateProfile_InvalidJSON
--- PASS: TestCreateProfile_InvalidJSON (0.01s)
=== RUN TestCreateProfile_DBError
--- PASS: TestCreateProfile_DBError (0.02s)
=== RUN TestUpdateProfile_InvalidID
--- PASS: TestUpdateProfile_InvalidID (0.01s)
=== RUN TestUpdateProfile_NotFound
2026/01/10 02:24:08 /projects/Charon/backend/internal/api/handlers/security_headers_handler.go:136 record not found
[0.141ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE `security_header_profiles`.`id` = 99999 ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestUpdateProfile_NotFound (0.01s)
=== RUN TestUpdateProfile_InvalidJSON
--- PASS: TestUpdateProfile_InvalidJSON (0.01s)
=== RUN TestUpdateProfile_DBError
2026/01/10 02:24:08 /projects/Charon/backend/internal/api/handlers/security_headers_handler.go:136 sql: database is closed
[0.037ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE `security_header_profiles`.`id` = 1 ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestUpdateProfile_DBError (0.02s)
=== RUN TestUpdateProfile_LookupDBError
2026/01/10 02:24:09 /projects/Charon/backend/internal/api/handlers/security_headers_handler.go:136 sql: database is closed
[0.041ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE `security_header_profiles`.`id` = 1 ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestUpdateProfile_LookupDBError (0.01s)
=== RUN TestDeleteProfile_InvalidID
--- PASS: TestDeleteProfile_InvalidID (0.01s)
=== RUN TestDeleteProfile_NotFound
2026/01/10 02:24:09 /projects/Charon/backend/internal/api/handlers/security_headers_handler.go:183 record not found
[0.119ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE `security_header_profiles`.`id` = 99999 ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestDeleteProfile_NotFound (0.01s)
=== RUN TestDeleteProfile_LookupDBError
2026/01/10 02:24:09 /projects/Charon/backend/internal/api/handlers/security_headers_handler.go:183 sql: database is closed
[0.055ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE `security_header_profiles`.`id` = 1 ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestDeleteProfile_LookupDBError (0.02s)
=== RUN TestDeleteProfile_CountDBError
2026/01/10 02:24:09 /projects/Charon/backend/internal/api/handlers/security_headers_handler.go:200 no such table: proxy_hosts
[4.018ms] [rows:0] SELECT count(*) FROM `proxy_hosts` WHERE security_header_profile_id = 1
--- PASS: TestDeleteProfile_CountDBError (0.01s)
=== RUN TestDeleteProfile_DeleteDBError
2026/01/10 02:24:09 /projects/Charon/backend/internal/api/handlers/security_headers_handler.go:183 sql: database is closed
[0.063ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE `security_header_profiles`.`id` = 1 ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestDeleteProfile_DeleteDBError (0.01s)
=== RUN TestApplyPreset_InvalidJSON
--- PASS: TestApplyPreset_InvalidJSON (0.01s)
=== RUN TestCalculateScore_InvalidJSON
--- PASS: TestCalculateScore_InvalidJSON (0.02s)
=== RUN TestValidateCSP_InvalidJSON
--- PASS: TestValidateCSP_InvalidJSON (0.01s)
=== RUN TestValidateCSP_EmptyCSP
--- PASS: TestValidateCSP_EmptyCSP (0.01s)
=== RUN TestValidateCSP_UnknownDirective
--- PASS: TestValidateCSP_UnknownDirective (0.01s)
=== RUN TestBuildCSP_InvalidJSON
--- PASS: TestBuildCSP_InvalidJSON (0.02s)
=== RUN TestGetProfile_UUID_DBError_NonNotFound
2026/01/10 02:24:09 /projects/Charon/backend/internal/api/handlers/security_headers_handler.go:82 sql: database is closed
[0.042ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "550e8400-e29b-41d4-a716-446655440000" ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestGetProfile_UUID_DBError_NonNotFound (0.01s)
=== RUN TestUpdateProfile_SaveError
2026/01/10 02:24:09 /projects/Charon/backend/internal/api/handlers/security_headers_handler.go:136 sql: database is closed
[0.039ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE `security_header_profiles`.`id` = 1 ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestUpdateProfile_SaveError (0.01s)
=== RUN TestNewSecurityNotificationHandler
=== PAUSE TestNewSecurityNotificationHandler
=== RUN TestSecurityNotificationHandler_GetSettings_Success
=== PAUSE TestSecurityNotificationHandler_GetSettings_Success
=== RUN TestSecurityNotificationHandler_GetSettings_ServiceError
=== PAUSE TestSecurityNotificationHandler_GetSettings_ServiceError
=== RUN TestSecurityNotificationHandler_UpdateSettings_InvalidJSON
=== PAUSE TestSecurityNotificationHandler_UpdateSettings_InvalidJSON
=== RUN TestSecurityNotificationHandler_UpdateSettings_InvalidMinLogLevel
=== PAUSE TestSecurityNotificationHandler_UpdateSettings_InvalidMinLogLevel
=== RUN TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF
=== PAUSE TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF
=== RUN TestSecurityNotificationHandler_UpdateSettings_PrivateIPWebhook
=== PAUSE TestSecurityNotificationHandler_UpdateSettings_PrivateIPWebhook
=== RUN TestSecurityNotificationHandler_UpdateSettings_ServiceError
=== PAUSE TestSecurityNotificationHandler_UpdateSettings_ServiceError
=== RUN TestSecurityNotificationHandler_UpdateSettings_Success
=== PAUSE TestSecurityNotificationHandler_UpdateSettings_Success
=== RUN TestSecurityNotificationHandler_UpdateSettings_EmptyWebhookURL
=== PAUSE TestSecurityNotificationHandler_UpdateSettings_EmptyWebhookURL
=== RUN TestSecurityHandler_Priority_SettingsOverSecurityConfig
=== RUN TestSecurityHandler_Priority_SettingsOverSecurityConfig/Settings_table_overrides_SecurityConfig_DB
=== RUN TestSecurityHandler_Priority_SettingsOverSecurityConfig/SecurityConfig_DB_overrides_static_config
=== RUN TestSecurityHandler_Priority_SettingsOverSecurityConfig/Static_config_used_when_no_DB_overrides
--- PASS: TestSecurityHandler_Priority_SettingsOverSecurityConfig (0.04s)
--- PASS: TestSecurityHandler_Priority_SettingsOverSecurityConfig/Settings_table_overrides_SecurityConfig_DB (0.01s)
--- PASS: TestSecurityHandler_Priority_SettingsOverSecurityConfig/SecurityConfig_DB_overrides_static_config (0.01s)
--- PASS: TestSecurityHandler_Priority_SettingsOverSecurityConfig/Static_config_used_when_no_DB_overrides (0.01s)
=== RUN TestSecurityHandler_Priority_AllModules
--- PASS: TestSecurityHandler_Priority_AllModules (0.01s)
=== RUN TestSecurityHandler_GetRateLimitPresets
--- PASS: TestSecurityHandler_GetRateLimitPresets (0.00s)
=== RUN TestSecurityHandler_GetRateLimitPresets_StandardPreset
--- PASS: TestSecurityHandler_GetRateLimitPresets_StandardPreset (0.00s)
=== RUN TestSecurityHandler_GetRateLimitPresets_LoginPreset
--- PASS: TestSecurityHandler_GetRateLimitPresets_LoginPreset (0.00s)
=== RUN TestGetClientIPHeadersAndRemoteAddr
--- PASS: TestGetClientIPHeadersAndRemoteAddr (0.00s)
=== RUN TestGetMyIPHandler
=== RUN TestGetMyIPHandler/with_CF_header
=== RUN TestGetMyIPHandler/with_X-Forwarded-For_header
=== RUN TestGetMyIPHandler/with_X-Real-IP_header
=== RUN TestGetMyIPHandler/direct_connection
--- PASS: TestGetMyIPHandler (0.00s)
--- PASS: TestGetMyIPHandler/with_CF_header (0.00s)
--- PASS: TestGetMyIPHandler/with_X-Forwarded-For_header (0.00s)
--- PASS: TestGetMyIPHandler/with_X-Real-IP_header (0.00s)
--- PASS: TestGetMyIPHandler/direct_connection (0.00s)
=== RUN TestWaitForCondition_PassesImmediately
--- PASS: TestWaitForCondition_PassesImmediately (0.00s)
=== RUN TestWaitForCondition_PassesAfterIterations
--- PASS: TestWaitForCondition_PassesAfterIterations (0.02s)
=== RUN TestWaitForConditionWithInterval_PassesImmediately
--- PASS: TestWaitForConditionWithInterval_PassesImmediately (0.00s)
=== RUN TestWaitForConditionWithInterval_CustomInterval
--- PASS: TestWaitForConditionWithInterval_CustomInterval (0.06s)
=== RUN TestWaitForCondition_Timeout
--- PASS: TestWaitForCondition_Timeout (0.03s)
=== RUN TestWaitForConditionWithInterval_Timeout
--- PASS: TestWaitForConditionWithInterval_Timeout (0.06s)
=== RUN TestWaitForCondition_ZeroTimeout
--- PASS: TestWaitForCondition_ZeroTimeout (0.00s)
=== RUN TestGetTemplateDB
--- PASS: TestGetTemplateDB (0.00s)
=== RUN TestGetTemplateDB_HasTables
--- PASS: TestGetTemplateDB_HasTables (0.00s)
=== RUN TestOpenTestDB
--- PASS: TestOpenTestDB (0.00s)
=== RUN TestOpenTestDB_Uniqueness
--- PASS: TestOpenTestDB_Uniqueness (0.00s)
=== RUN TestOpenTestDBWithMigrations
--- PASS: TestOpenTestDBWithMigrations (0.00s)
=== RUN TestOpenTestDBWithMigrations_CanInsertData
--- PASS: TestOpenTestDBWithMigrations_CanInsertData (0.02s)
=== RUN TestOpenTestDBWithMigrations_MultipleModels
--- PASS: TestOpenTestDBWithMigrations_MultipleModels (0.01s)
=== RUN TestOpenTestDBWithMigrations_FallbackPath
--- PASS: TestOpenTestDBWithMigrations_FallbackPath (0.01s)
=== RUN TestOpenTestDB_ParallelSafety
=== PAUSE TestOpenTestDB_ParallelSafety
=== RUN TestOpenTestDBWithMigrations_ParallelSafety
=== RUN TestOpenTestDBWithMigrations_ParallelSafety/parallel-migrations-0
=== RUN TestOpenTestDBWithMigrations_ParallelSafety/parallel-migrations-1
=== RUN TestOpenTestDBWithMigrations_ParallelSafety/parallel-migrations-2
--- PASS: TestOpenTestDBWithMigrations_ParallelSafety (0.02s)
--- PASS: TestOpenTestDBWithMigrations_ParallelSafety/parallel-migrations-0 (0.01s)
--- PASS: TestOpenTestDBWithMigrations_ParallelSafety/parallel-migrations-1 (0.01s)
--- PASS: TestOpenTestDBWithMigrations_ParallelSafety/parallel-migrations-2 (0.01s)
=== RUN TestUpdateHandler_Check
--- PASS: TestUpdateHandler_Check (0.00s)
=== RUN TestUserHandler_GetSetupStatus_Error
--- PASS: TestUserHandler_GetSetupStatus_Error (0.02s)
=== RUN TestUserHandler_Setup_CheckStatusError
--- PASS: TestUserHandler_Setup_CheckStatusError (0.02s)
=== RUN TestUserHandler_Setup_AlreadyCompleted
--- PASS: TestUserHandler_Setup_AlreadyCompleted (0.74s)
=== RUN TestUserHandler_Setup_InvalidJSON
--- PASS: TestUserHandler_Setup_InvalidJSON (0.02s)
=== RUN TestUserHandler_RegenerateAPIKey_Unauthorized
--- PASS: TestUserHandler_RegenerateAPIKey_Unauthorized (0.02s)
=== RUN TestUserHandler_RegenerateAPIKey_DBError
--- PASS: TestUserHandler_RegenerateAPIKey_DBError (0.02s)
=== RUN TestUserHandler_GetProfile_Unauthorized
--- PASS: TestUserHandler_GetProfile_Unauthorized (0.02s)
=== RUN TestUserHandler_GetProfile_NotFound
--- PASS: TestUserHandler_GetProfile_NotFound (0.02s)
=== RUN TestUserHandler_UpdateProfile_Unauthorized
--- PASS: TestUserHandler_UpdateProfile_Unauthorized (0.01s)
=== RUN TestUserHandler_UpdateProfile_InvalidJSON
--- PASS: TestUserHandler_UpdateProfile_InvalidJSON (0.02s)
=== RUN TestUserHandler_UpdateProfile_UserNotFound
--- PASS: TestUserHandler_UpdateProfile_UserNotFound (0.02s)
=== RUN TestUserHandler_UpdateProfile_EmailConflict
--- PASS: TestUserHandler_UpdateProfile_EmailConflict (1.48s)
=== RUN TestUserHandler_UpdateProfile_EmailChangeNoPassword
--- PASS: TestUserHandler_UpdateProfile_EmailChangeNoPassword (0.75s)
=== RUN TestUserHandler_UpdateProfile_WrongPassword
--- PASS: TestUserHandler_UpdateProfile_WrongPassword (1.47s)
=== RUN TestUserHandler_GetSetupStatus
--- PASS: TestUserHandler_GetSetupStatus (0.02s)
=== RUN TestUserHandler_Setup
--- PASS: TestUserHandler_Setup (0.74s)
=== RUN TestUserHandler_Setup_DBError
--- PASS: TestUserHandler_Setup_DBError (0.00s)
=== RUN TestUserHandler_RegenerateAPIKey
--- PASS: TestUserHandler_RegenerateAPIKey (0.01s)
=== RUN TestUserHandler_GetProfile
--- PASS: TestUserHandler_GetProfile (0.02s)
=== RUN TestUserHandler_RegisterRoutes
--- PASS: TestUserHandler_RegisterRoutes (0.01s)
=== RUN TestUserHandler_Errors
2026/01/10 02:24:14 /projects/Charon/backend/internal/api/handlers/user_handler.go:171 record not found
[0.103ms] [rows:0] SELECT * FROM `users` WHERE `users`.`id` = 99999 ORDER BY `users`.`id` LIMIT 1
2026/01/10 02:24:14 /projects/Charon/backend/internal/api/handlers/user_handler.go:154 no such table: users
[0.155ms] [rows:0] UPDATE `users` SET `api_key`="e55dd8a0-c3ca-4679-a77b-509d128435d1",`updated_at`="2026-01-10 02:24:14.927" WHERE id = 99999
--- PASS: TestUserHandler_Errors (0.02s)
=== RUN TestUserHandler_UpdateProfile
=== RUN TestUserHandler_UpdateProfile/Success_Name_Only
=== RUN TestUserHandler_UpdateProfile/Success_Email_Change
=== RUN TestUserHandler_UpdateProfile/Fail_Email_Change_No_Password
=== RUN TestUserHandler_UpdateProfile/Fail_Email_Change_Wrong_Password
=== RUN TestUserHandler_UpdateProfile/Fail_Email_In_Use
--- PASS: TestUserHandler_UpdateProfile (2.36s)
--- PASS: TestUserHandler_UpdateProfile/Success_Name_Only (0.00s)
--- PASS: TestUserHandler_UpdateProfile/Success_Email_Change (0.77s)
--- PASS: TestUserHandler_UpdateProfile/Fail_Email_Change_No_Password (0.00s)
--- PASS: TestUserHandler_UpdateProfile/Fail_Email_Change_Wrong_Password (0.73s)
--- PASS: TestUserHandler_UpdateProfile/Fail_Email_In_Use (0.00s)
=== RUN TestUserHandler_UpdateProfile_Errors
2026/01/10 02:24:17 /projects/Charon/backend/internal/api/handlers/user_handler.go:207 record not found
[0.135ms] [rows:0] SELECT * FROM `users` WHERE `users`.`id` = 999 ORDER BY `users`.`id` LIMIT 1
--- PASS: TestUserHandler_UpdateProfile_Errors (0.01s)
=== RUN TestUserHandler_ListUsers_NonAdmin
--- PASS: TestUserHandler_ListUsers_NonAdmin (0.02s)
=== RUN TestUserHandler_ListUsers_Admin
--- PASS: TestUserHandler_ListUsers_Admin (0.01s)
=== RUN TestUserHandler_CreateUser_NonAdmin
--- PASS: TestUserHandler_CreateUser_NonAdmin (0.01s)
=== RUN TestUserHandler_CreateUser_Admin
--- PASS: TestUserHandler_CreateUser_Admin (0.73s)
=== RUN TestUserHandler_CreateUser_InvalidJSON
--- PASS: TestUserHandler_CreateUser_InvalidJSON (0.01s)
=== RUN TestUserHandler_CreateUser_DuplicateEmail
--- PASS: TestUserHandler_CreateUser_DuplicateEmail (0.01s)
=== RUN TestUserHandler_CreateUser_WithPermittedHosts
--- PASS: TestUserHandler_CreateUser_WithPermittedHosts (0.73s)
=== RUN TestUserHandler_GetUser_NonAdmin
--- PASS: TestUserHandler_GetUser_NonAdmin (0.01s)
=== RUN TestUserHandler_GetUser_InvalidID
--- PASS: TestUserHandler_GetUser_InvalidID (0.02s)
=== RUN TestUserHandler_GetUser_NotFound
2026/01/10 02:24:18 /projects/Charon/backend/internal/api/handlers/user_handler.go:571 record not found
[0.080ms] [rows:0] SELECT * FROM `users` WHERE `users`.`id` = 999 ORDER BY `users`.`id` LIMIT 1
--- PASS: TestUserHandler_GetUser_NotFound (0.02s)
=== RUN TestUserHandler_GetUser_Success
--- PASS: TestUserHandler_GetUser_Success (0.01s)
=== RUN TestUserHandler_UpdateUser_NonAdmin
--- PASS: TestUserHandler_UpdateUser_NonAdmin (0.02s)
=== RUN TestUserHandler_UpdateUser_InvalidID
--- PASS: TestUserHandler_UpdateUser_InvalidID (0.01s)
=== RUN TestUserHandler_UpdateUser_InvalidJSON
--- PASS: TestUserHandler_UpdateUser_InvalidJSON (0.01s)
=== RUN TestUserHandler_UpdateUser_NotFound
2026/01/10 02:24:18 /projects/Charon/backend/internal/api/handlers/user_handler.go:623 record not found
[0.103ms] [rows:0] SELECT * FROM `users` WHERE `users`.`id` = 999 ORDER BY `users`.`id` LIMIT 1
--- PASS: TestUserHandler_UpdateUser_NotFound (0.02s)
=== RUN TestUserHandler_UpdateUser_Success
--- PASS: TestUserHandler_UpdateUser_Success (0.02s)
=== RUN TestUserHandler_DeleteUser_NonAdmin
--- PASS: TestUserHandler_DeleteUser_NonAdmin (0.01s)
=== RUN TestUserHandler_DeleteUser_InvalidID
--- PASS: TestUserHandler_DeleteUser_InvalidID (0.02s)
=== RUN TestUserHandler_DeleteUser_NotFound
2026/01/10 02:24:19 /projects/Charon/backend/internal/api/handlers/user_handler.go:693 record not found
[0.096ms] [rows:0] SELECT * FROM `users` WHERE `users`.`id` = 999 ORDER BY `users`.`id` LIMIT 1
--- PASS: TestUserHandler_DeleteUser_NotFound (0.02s)
=== RUN TestUserHandler_DeleteUser_Success
--- PASS: TestUserHandler_DeleteUser_Success (0.02s)
=== RUN TestUserHandler_DeleteUser_CannotDeleteSelf
--- PASS: TestUserHandler_DeleteUser_CannotDeleteSelf (0.02s)
=== RUN TestUserHandler_UpdateUserPermissions_NonAdmin
--- PASS: TestUserHandler_UpdateUserPermissions_NonAdmin (0.01s)
=== RUN TestUserHandler_UpdateUserPermissions_InvalidID
--- PASS: TestUserHandler_UpdateUserPermissions_InvalidID (0.02s)
=== RUN TestUserHandler_UpdateUserPermissions_InvalidJSON
--- PASS: TestUserHandler_UpdateUserPermissions_InvalidJSON (0.01s)
=== RUN TestUserHandler_UpdateUserPermissions_NotFound
2026/01/10 02:24:19 /projects/Charon/backend/internal/api/handlers/user_handler.go:734 record not found
[0.079ms] [rows:0] SELECT * FROM `users` WHERE `users`.`id` = 999 ORDER BY `users`.`id` LIMIT 1
--- PASS: TestUserHandler_UpdateUserPermissions_NotFound (0.01s)
=== RUN TestUserHandler_UpdateUserPermissions_Success
--- PASS: TestUserHandler_UpdateUserPermissions_Success (0.02s)
=== RUN TestUserHandler_ValidateInvite_MissingToken
--- PASS: TestUserHandler_ValidateInvite_MissingToken (0.01s)
=== RUN TestUserHandler_ValidateInvite_InvalidToken
2026/01/10 02:24:19 /projects/Charon/backend/internal/api/handlers/user_handler.go:783 record not found
[0.091ms] [rows:0] SELECT * FROM `users` WHERE invite_token = "invalidtoken" ORDER BY `users`.`id` LIMIT 1
--- PASS: TestUserHandler_ValidateInvite_InvalidToken (0.01s)
=== RUN TestUserHandler_ValidateInvite_ExpiredToken
--- PASS: TestUserHandler_ValidateInvite_ExpiredToken (0.02s)
=== RUN TestUserHandler_ValidateInvite_AlreadyAccepted
--- PASS: TestUserHandler_ValidateInvite_AlreadyAccepted (0.01s)
=== RUN TestUserHandler_ValidateInvite_Success
--- PASS: TestUserHandler_ValidateInvite_Success (0.02s)
=== RUN TestUserHandler_AcceptInvite_InvalidJSON
--- PASS: TestUserHandler_AcceptInvite_InvalidJSON (0.02s)
=== RUN TestUserHandler_AcceptInvite_InvalidToken
2026/01/10 02:24:19 /projects/Charon/backend/internal/api/handlers/user_handler.go:822 record not found
[0.115ms] [rows:0] SELECT * FROM `users` WHERE invite_token = "invalidtoken" ORDER BY `users`.`id` LIMIT 1
--- PASS: TestUserHandler_AcceptInvite_InvalidToken (0.02s)
=== RUN TestUserHandler_AcceptInvite_Success
--- PASS: TestUserHandler_AcceptInvite_Success (0.78s)
=== RUN TestGenerateSecureToken
--- PASS: TestGenerateSecureToken (0.00s)
=== RUN TestUserHandler_InviteUser_NonAdmin
--- PASS: TestUserHandler_InviteUser_NonAdmin (0.02s)
=== RUN TestUserHandler_InviteUser_InvalidJSON
--- PASS: TestUserHandler_InviteUser_InvalidJSON (0.02s)
=== RUN TestUserHandler_InviteUser_DuplicateEmail
--- PASS: TestUserHandler_InviteUser_DuplicateEmail (0.02s)
=== RUN TestUserHandler_InviteUser_Success
2026/01/10 02:24:20 /projects/Charon/backend/internal/api/handlers/user_handler.go:422 record not found
[0.088ms] [rows:0] SELECT * FROM `users` WHERE email = "newinvite@example.com" ORDER BY `users`.`id` LIMIT 1
--- PASS: TestUserHandler_InviteUser_Success (0.02s)
=== RUN TestUserHandler_InviteUser_WithPermittedHosts
2026/01/10 02:24:20 /projects/Charon/backend/internal/api/handlers/user_handler.go:422 record not found
[0.098ms] [rows:0] SELECT * FROM `users` WHERE email = "invitee-perms@example.com" ORDER BY `users`.`id` LIMIT 1
--- PASS: TestUserHandler_InviteUser_WithPermittedHosts (0.02s)
=== RUN TestUserHandler_InviteUser_WithSMTPConfigured
2026/01/10 02:24:20 /projects/Charon/backend/internal/api/handlers/user_handler.go:422 record not found
[0.107ms] [rows:0] SELECT * FROM `users` WHERE email = "smtp-test@example.com" ORDER BY `users`.`id` LIMIT 1
2026/01/10 02:24:20 /projects/Charon/backend/internal/utils/url.go:17 record not found
[0.081ms] [rows:0] SELECT * FROM `settings` WHERE key = "app.public_url" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestUserHandler_InviteUser_WithSMTPConfigured (0.03s)
=== RUN TestUserHandler_InviteUser_WithSMTPConfigured_DefaultAppName
2026/01/10 02:24:20 /projects/Charon/backend/internal/api/handlers/user_handler.go:422 record not found
[0.117ms] [rows:0] SELECT * FROM `users` WHERE email = "smtp-test-default@example.com" ORDER BY `users`.`id` LIMIT 1
2026/01/10 02:24:20 /projects/Charon/backend/internal/utils/url.go:17 record not found
[0.087ms] [rows:0] SELECT * FROM `settings` WHERE key = "app.public_url" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:20 /projects/Charon/backend/internal/api/handlers/user_handler.go:549 record not found
[0.075ms] [rows:0] SELECT * FROM `settings` WHERE key = "app_name" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestUserHandler_InviteUser_WithSMTPConfigured_DefaultAppName (0.02s)
=== RUN TestUserHandler_AcceptInvite_ExpiredToken
--- PASS: TestUserHandler_AcceptInvite_ExpiredToken (0.02s)
=== RUN TestUserHandler_AcceptInvite_AlreadyAccepted
--- PASS: TestUserHandler_AcceptInvite_AlreadyAccepted (0.02s)
=== RUN TestUserHandler_PreviewInviteURL_NonAdmin
--- PASS: TestUserHandler_PreviewInviteURL_NonAdmin (0.01s)
=== RUN TestUserHandler_PreviewInviteURL_InvalidJSON
--- PASS: TestUserHandler_PreviewInviteURL_InvalidJSON (0.01s)
=== RUN TestUserHandler_PreviewInviteURL_Success_Unconfigured
2026/01/10 02:24:20 /projects/Charon/backend/internal/utils/url.go:17 record not found
[0.102ms] [rows:0] SELECT * FROM `settings` WHERE key = "app.public_url" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:20 /projects/Charon/backend/internal/api/handlers/user_handler.go:529 record not found
[0.069ms] [rows:0] SELECT * FROM `settings` WHERE key = "app.public_url" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestUserHandler_PreviewInviteURL_Success_Unconfigured (0.02s)
=== RUN TestUserHandler_PreviewInviteURL_Success_Configured
--- PASS: TestUserHandler_PreviewInviteURL_Success_Configured (0.02s)
=== RUN TestGetAppName_Default
2026/01/10 02:24:20 /projects/Charon/backend/internal/api/handlers/user_handler.go:549 record not found
[0.093ms] [rows:0] SELECT * FROM `settings` WHERE key = "app_name" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestGetAppName_Default (0.01s)
=== RUN TestGetAppName_FromSettings
--- PASS: TestGetAppName_FromSettings (0.02s)
=== RUN TestGetAppName_EmptyValue
--- PASS: TestGetAppName_EmptyValue (0.01s)
=== RUN TestUserHandler_UpdateUser_EmailConflict
--- PASS: TestUserHandler_UpdateUser_EmailConflict (0.02s)
=== RUN TestUserHandler_CreateUser_EmailNormalization
--- PASS: TestUserHandler_CreateUser_EmailNormalization (0.74s)
=== RUN TestUserHandler_InviteUser_EmailNormalization
2026/01/10 02:24:21 /projects/Charon/backend/internal/api/handlers/user_handler.go:422 record not found
[0.102ms] [rows:0] SELECT * FROM `users` WHERE email = "invite@example.com" ORDER BY `users`.`id` LIMIT 1
--- PASS: TestUserHandler_InviteUser_EmailNormalization (0.02s)
=== RUN TestUserHandler_CreateUser_DefaultPermissionMode
--- PASS: TestUserHandler_CreateUser_DefaultPermissionMode (0.76s)
=== RUN TestUserHandler_InviteUser_DefaultPermissionMode
2026/01/10 02:24:21 /projects/Charon/backend/internal/api/handlers/user_handler.go:422 record not found
[0.081ms] [rows:0] SELECT * FROM `users` WHERE email = "defaultinvite@example.com" ORDER BY `users`.`id` LIMIT 1
--- PASS: TestUserHandler_InviteUser_DefaultPermissionMode (0.02s)
=== RUN TestUserHandler_CreateUser_DefaultRole
--- PASS: TestUserHandler_CreateUser_DefaultRole (0.81s)
=== RUN TestUserHandler_InviteUser_DefaultRole
2026/01/10 02:24:22 /projects/Charon/backend/internal/api/handlers/user_handler.go:422 record not found
[0.104ms] [rows:0] SELECT * FROM `users` WHERE email = "defaultroleinvite@example.com" ORDER BY `users`.`id` LIMIT 1
--- PASS: TestUserHandler_InviteUser_DefaultRole (0.02s)
=== RUN TestUserHandler_CreateUser_EmptyPermittedHosts
--- PASS: TestUserHandler_CreateUser_EmptyPermittedHosts (0.75s)
=== RUN TestUserHandler_CreateUser_NonExistentPermittedHosts
--- PASS: TestUserHandler_CreateUser_NonExistentPermittedHosts (0.71s)
=== RUN TestUserLoginAfterEmailChange
--- PASS: TestUserLoginAfterEmailChange (3.64s)
=== RUN TestWebSocketStatusHandler_GetConnections
--- PASS: TestWebSocketStatusHandler_GetConnections (0.00s)
=== RUN TestWebSocketStatusHandler_GetConnectionsEmpty
--- PASS: TestWebSocketStatusHandler_GetConnectionsEmpty (0.00s)
=== RUN TestWebSocketStatusHandler_GetStats
--- PASS: TestWebSocketStatusHandler_GetStats (0.00s)
=== RUN TestWebSocketStatusHandler_GetStatsEmpty
--- PASS: TestWebSocketStatusHandler_GetStatsEmpty (0.00s)
=== RUN TestCredentialHandler_Create
--- PASS: TestCredentialHandler_Create (0.01s)
=== RUN TestCredentialHandler_Create_InvalidProviderID
--- PASS: TestCredentialHandler_Create_InvalidProviderID (0.01s)
=== RUN TestCredentialHandler_List
--- PASS: TestCredentialHandler_List (0.06s)
=== RUN TestCredentialHandler_Get
--- PASS: TestCredentialHandler_Get (0.01s)
=== RUN TestCredentialHandler_Get_NotFound
2026/01/10 02:24:27 /projects/Charon/backend/internal/services/credential_service.go:111 record not found
[0.111ms] [rows:0] SELECT * FROM `dns_provider_credentials` WHERE id = 9999 AND dns_provider_id = 1 ORDER BY `dns_provider_credentials`.`id` LIMIT 1
--- PASS: TestCredentialHandler_Get_NotFound (0.01s)
=== RUN TestCredentialHandler_Update
--- PASS: TestCredentialHandler_Update (0.02s)
=== RUN TestCredentialHandler_Delete
2026/01/10 02:24:27 /projects/Charon/backend/internal/services/credential_service.go:349 database table is locked
[0.198ms] [rows:0] DELETE FROM `dns_provider_credentials` WHERE `dns_provider_credentials`.`id` = 1
credential_handler_test.go:271:
Error Trace: /projects/Charon/backend/internal/api/handlers/credential_handler_test.go:271
Error: Not equal:
expected: 204
actual : 500
Test: TestCredentialHandler_Delete
credential_handler_test.go:275:
Error Trace: /projects/Charon/backend/internal/api/handlers/credential_handler_test.go:275
Error: Expected error with "credential not found" in chain but got nil.
Test: TestCredentialHandler_Delete
--- FAIL: TestCredentialHandler_Delete (0.01s)
=== RUN TestCredentialHandler_Test
2026/01/10 02:24:27 /projects/Charon/backend/internal/services/credential_service.go:431 database table is locked
[0.284ms] [rows:0] UPDATE `dns_provider_credentials` SET `uuid`="f40f619f-7684-4790-b783-ac5e44294763",`dns_provider_id`=1,`label`="Test",`zone_filter`="",`enabled`=true,`credentials_encrypted`="NBrnkSpfbFdR/MjU6p0DHJ+vnHw83TDcFg9uM543VBlnMlK1Sdw/IvMOMEVHGmAumg==",`key_version`=1,`propagation_timeout`=120,`polling_interval`=5,`last_used_at`=NULL,`success_count`=1,`failure_count`=0,`last_error`="",`created_at`="2026-01-10 02:24:27.934",`updated_at`="2026-01-10 02:24:27.935" WHERE `id` = 1
--- PASS: TestCredentialHandler_Test (0.01s)
=== RUN TestCredentialHandler_EnableMultiCredentials
--- PASS: TestCredentialHandler_EnableMultiCredentials (0.01s)
=== RUN TestCredentialHandler_List_InvalidProviderID
--- PASS: TestCredentialHandler_List_InvalidProviderID (0.01s)
=== RUN TestCredentialHandler_List_ProviderNotFound
2026/01/10 02:24:27 /projects/Charon/backend/internal/services/credential_service.go:86 record not found
[0.095ms] [rows:0] SELECT * FROM `dns_providers` WHERE `dns_providers`.`id` = 9999 ORDER BY `dns_providers`.`id` LIMIT 1
--- PASS: TestCredentialHandler_List_ProviderNotFound (0.01s)
=== RUN TestCredentialHandler_List_MultiCredentialNotEnabled
--- PASS: TestCredentialHandler_List_MultiCredentialNotEnabled (0.00s)
=== RUN TestCredentialHandler_Create_ProviderNotFound
2026/01/10 02:24:27 /projects/Charon/backend/internal/services/credential_service.go:127 record not found
[0.098ms] [rows:0] SELECT * FROM `dns_providers` WHERE `dns_providers`.`id` = 9999 ORDER BY `dns_providers`.`id` LIMIT 1
--- PASS: TestCredentialHandler_Create_ProviderNotFound (0.01s)
=== RUN TestCredentialHandler_Create_MultiCredentialNotEnabled
--- PASS: TestCredentialHandler_Create_MultiCredentialNotEnabled (0.01s)
=== RUN TestCredentialHandler_Create_InvalidJSON
--- PASS: TestCredentialHandler_Create_InvalidJSON (0.00s)
=== RUN TestCredentialHandler_Create_MissingRequiredFields
--- PASS: TestCredentialHandler_Create_MissingRequiredFields (0.01s)
=== RUN TestCredentialHandler_Create_InvalidProviderType
--- PASS: TestCredentialHandler_Create_InvalidProviderType (0.01s)
=== RUN TestCredentialHandler_Get_InvalidProviderID
--- PASS: TestCredentialHandler_Get_InvalidProviderID (0.01s)
=== RUN TestCredentialHandler_Get_InvalidCredentialID
--- PASS: TestCredentialHandler_Get_InvalidCredentialID (0.00s)
=== RUN TestCredentialHandler_Update_InvalidProviderID
--- PASS: TestCredentialHandler_Update_InvalidProviderID (0.01s)
=== RUN TestCredentialHandler_Update_InvalidCredentialID
--- PASS: TestCredentialHandler_Update_InvalidCredentialID (0.01s)
=== RUN TestCredentialHandler_Update_NotFound
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/credential_service.go:111 record not found
[0.103ms] [rows:0] SELECT * FROM `dns_provider_credentials` WHERE id = 9999 AND dns_provider_id = 1 ORDER BY `dns_provider_credentials`.`id` LIMIT 1
--- PASS: TestCredentialHandler_Update_NotFound (0.01s)
=== RUN TestCredentialHandler_Update_InvalidJSON
--- PASS: TestCredentialHandler_Update_InvalidJSON (0.01s)
=== RUN TestCredentialHandler_Delete_InvalidProviderID
--- PASS: TestCredentialHandler_Delete_InvalidProviderID (0.00s)
=== RUN TestCredentialHandler_Delete_InvalidCredentialID
--- PASS: TestCredentialHandler_Delete_InvalidCredentialID (0.00s)
=== RUN TestCredentialHandler_Delete_NotFound
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/credential_service.go:111 record not found
[0.136ms] [rows:0] SELECT * FROM `dns_provider_credentials` WHERE id = 9999 AND dns_provider_id = 1 ORDER BY `dns_provider_credentials`.`id` LIMIT 1
--- PASS: TestCredentialHandler_Delete_NotFound (0.00s)
=== RUN TestCredentialHandler_Test_InvalidProviderID
--- PASS: TestCredentialHandler_Test_InvalidProviderID (0.00s)
=== RUN TestCredentialHandler_Test_InvalidCredentialID
--- PASS: TestCredentialHandler_Test_InvalidCredentialID (0.00s)
=== RUN TestCredentialHandler_Test_NotFound
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/credential_service.go:111 record not found
[0.094ms] [rows:0] SELECT * FROM `dns_provider_credentials` WHERE id = 9999 AND dns_provider_id = 1 ORDER BY `dns_provider_credentials`.`id` LIMIT 1
--- PASS: TestCredentialHandler_Test_NotFound (0.01s)
=== RUN TestCredentialHandler_EnableMultiCredentials_InvalidProviderID
--- PASS: TestCredentialHandler_EnableMultiCredentials_InvalidProviderID (0.00s)
=== RUN TestCredentialHandler_EnableMultiCredentials_ProviderNotFound
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/credential_service.go:555 record not found
[0.115ms] [rows:0] SELECT * FROM `dns_providers` WHERE `dns_providers`.`id` = 9999 ORDER BY `dns_providers`.`id` LIMIT 1
--- PASS: TestCredentialHandler_EnableMultiCredentials_ProviderNotFound (0.01s)
=== RUN TestCredentialHandler_Create_EncryptionError
--- PASS: TestCredentialHandler_Create_EncryptionError (0.01s)
=== RUN TestCredentialHandler_Update_EncryptionError
--- PASS: TestCredentialHandler_Update_EncryptionError (0.02s)
=== RUN TestCredentialHandler_Update_InvalidProviderType
--- PASS: TestCredentialHandler_Update_InvalidProviderType (0.02s)
=== RUN TestCredentialHandler_Update_InvalidCredentials
--- PASS: TestCredentialHandler_Update_InvalidCredentials (0.02s)
=== RUN TestCredentialHandler_Create_EmptyLabel
--- PASS: TestCredentialHandler_Create_EmptyLabel (0.01s)
=== RUN TestCredentialHandler_Update_WithZoneFilter
--- PASS: TestCredentialHandler_Update_WithZoneFilter (0.02s)
=== RUN TestCredentialHandler_Delete_ProviderNotFound
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/credential_service.go:111 record not found
[0.109ms] [rows:0] SELECT * FROM `dns_provider_credentials` WHERE id = 1 AND dns_provider_id = 9999 ORDER BY `dns_provider_credentials`.`id` LIMIT 1
--- PASS: TestCredentialHandler_Delete_ProviderNotFound (0.01s)
=== RUN TestCredentialHandler_Test_ProviderNotFound
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/credential_service.go:111 record not found
[0.088ms] [rows:0] SELECT * FROM `dns_provider_credentials` WHERE id = 1 AND dns_provider_id = 9999 ORDER BY `dns_provider_credentials`.`id` LIMIT 1
--- PASS: TestCredentialHandler_Test_ProviderNotFound (0.01s)
=== RUN TestRemoteServerHandler_List
=== PAUSE TestRemoteServerHandler_List
=== RUN TestRemoteServerHandler_Create
=== PAUSE TestRemoteServerHandler_Create
=== RUN TestRemoteServerHandler_TestConnection
=== PAUSE TestRemoteServerHandler_TestConnection
=== RUN TestRemoteServerHandler_Get
=== PAUSE TestRemoteServerHandler_Get
=== RUN TestRemoteServerHandler_Update
=== PAUSE TestRemoteServerHandler_Update
=== RUN TestRemoteServerHandler_Delete
=== PAUSE TestRemoteServerHandler_Delete
=== RUN TestProxyHostHandler_List
=== PAUSE TestProxyHostHandler_List
=== RUN TestProxyHostHandler_Create
=== PAUSE TestProxyHostHandler_Create
=== RUN TestProxyHostHandler_PartialUpdate_DoesNotWipeFields
=== PAUSE TestProxyHostHandler_PartialUpdate_DoesNotWipeFields
=== RUN TestHealthHandler
=== PAUSE TestHealthHandler
=== RUN TestRemoteServerHandler_Errors
=== PAUSE TestRemoteServerHandler_Errors
=== RUN TestImportHandler_GetStatus
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/import_handler.go:60 record not found
[0.180ms] [rows:0] SELECT * FROM `import_sessions` WHERE status IN ("pending","reviewing") ORDER BY created_at DESC,`import_sessions`.`id` LIMIT 1
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/import_handler.go:60 record not found
[0.101ms] [rows:0] SELECT * FROM `import_sessions` WHERE status IN ("pending","reviewing") ORDER BY created_at DESC,`import_sessions`.`id` LIMIT 1
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/import_handler.go:70 record not found
[0.077ms] [rows:0] SELECT * FROM `import_sessions` WHERE source_file = "/tmp/TestImportHandler_GetStatus2696916650/001/mounted.caddyfile" AND status = "committed" ORDER BY committed_at DESC,`import_sessions`.`id` LIMIT 1
--- PASS: TestImportHandler_GetStatus (0.02s)
=== RUN TestImportHandler_GetPreview
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/import_handler.go:122 record not found
[0.193ms] [rows:0] SELECT * FROM `import_sessions` WHERE status IN ("pending","reviewing") ORDER BY created_at DESC,`import_sessions`.`id` LIMIT 1
--- PASS: TestImportHandler_GetPreview (0.02s)
=== RUN TestImportHandler_Cancel
--- PASS: TestImportHandler_Cancel (0.01s)
=== RUN TestImportHandler_Commit
--- PASS: TestImportHandler_Commit (0.01s)
=== RUN TestImportHandler_Upload
--- PASS: TestImportHandler_Upload (0.02s)
=== RUN TestImportHandler_GetPreview_WithContent
--- PASS: TestImportHandler_GetPreview_WithContent (0.02s)
=== RUN TestImportHandler_Commit_Errors
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/import_handler.go:583 record not found
[0.080ms] [rows:0] SELECT * FROM `import_sessions` WHERE uuid = "non-existent" AND status = "reviewing" ORDER BY `import_sessions`.`id` LIMIT 1
--- PASS: TestImportHandler_Commit_Errors (0.01s)
=== RUN TestImportHandler_Cancel_Errors
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/import_handler.go:734 record not found
[0.123ms] [rows:0] SELECT * FROM `import_sessions` WHERE uuid = "non-existent" ORDER BY `import_sessions`.`id` LIMIT 1
--- PASS: TestImportHandler_Cancel_Errors (0.01s)
=== RUN TestCheckMountedImport
--- PASS: TestCheckMountedImport (0.01s)
=== RUN TestImportHandler_Upload_Failure
--- PASS: TestImportHandler_Upload_Failure (0.02s)
=== RUN TestImportHandler_Upload_Conflict
--- PASS: TestImportHandler_Upload_Conflict (0.02s)
=== RUN TestImportHandler_GetPreview_BackupContent
--- PASS: TestImportHandler_GetPreview_BackupContent (0.02s)
=== RUN TestImportHandler_RegisterRoutes
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/import_handler.go:60 record not found
[0.152ms] [rows:0] SELECT * FROM `import_sessions` WHERE status IN ("pending","reviewing") ORDER BY created_at DESC,`import_sessions`.`id` LIMIT 1
--- PASS: TestImportHandler_RegisterRoutes (0.02s)
=== RUN TestImportHandler_GetPreview_TransientMount
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/import_handler.go:122 record not found
[0.162ms] [rows:0] SELECT * FROM `import_sessions` WHERE status IN ("pending","reviewing") ORDER BY created_at DESC,`import_sessions`.`id` LIMIT 1
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/import_handler.go:167 record not found
[0.074ms] [rows:0] SELECT * FROM `import_sessions` WHERE source_file = "/tmp/TestImportHandler_GetPreview_TransientMount3200069616/001/mounted.caddyfile" AND status = "committed" ORDER BY committed_at DESC,`import_sessions`.`id` LIMIT 1
--- PASS: TestImportHandler_GetPreview_TransientMount (0.02s)
=== RUN TestImportHandler_Commit_TransientUpload
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/import_handler.go:583 record not found
[0.101ms] [rows:0] SELECT * FROM `import_sessions` WHERE uuid = "07b56185-d75c-46c0-8e2d-ece5943f0c14" AND status = "reviewing" ORDER BY `import_sessions`.`id` LIMIT 1
--- PASS: TestImportHandler_Commit_TransientUpload (0.02s)
=== RUN TestImportHandler_Commit_TransientMount
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/import_handler.go:583 record not found
[0.112ms] [rows:0] SELECT * FROM `import_sessions` WHERE uuid = "7b3daafe-be1a-4222-a08f-4b5b10b631e8" AND status = "reviewing" ORDER BY `import_sessions`.`id` LIMIT 1
--- PASS: TestImportHandler_Commit_TransientMount (0.02s)
=== RUN TestImportHandler_Cancel_TransientUpload
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/import_handler.go:734 record not found
[0.108ms] [rows:0] SELECT * FROM `import_sessions` WHERE uuid = "49cca609-8bee-4ea1-bb1f-0381031e0894" ORDER BY `import_sessions`.`id` LIMIT 1
--- PASS: TestImportHandler_Cancel_TransientUpload (0.03s)
=== RUN TestImportHandler_Errors
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/import_handler.go:583 record not found
[0.156ms] [rows:0] SELECT * FROM `import_sessions` WHERE uuid = "non-existent" AND status = "reviewing" ORDER BY `import_sessions`.`id` LIMIT 1
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/import_handler.go:734 record not found
[0.063ms] [rows:0] SELECT * FROM `import_sessions` WHERE uuid = "non-existent" ORDER BY `import_sessions`.`id` LIMIT 1
--- PASS: TestImportHandler_Errors (0.01s)
=== RUN TestImportHandler_DetectImports
=== RUN TestImportHandler_DetectImports/no_imports
=== RUN TestImportHandler_DetectImports/single_import
=== RUN TestImportHandler_DetectImports/multiple_imports
=== RUN TestImportHandler_DetectImports/import_with_comment
--- PASS: TestImportHandler_DetectImports (0.02s)
--- PASS: TestImportHandler_DetectImports/no_imports (0.00s)
--- PASS: TestImportHandler_DetectImports/single_import (0.00s)
--- PASS: TestImportHandler_DetectImports/multiple_imports (0.00s)
--- PASS: TestImportHandler_DetectImports/import_with_comment (0.00s)
=== RUN TestImportHandler_DetectImports_InvalidJSON
--- PASS: TestImportHandler_DetectImports_InvalidJSON (0.01s)
=== RUN TestImportHandler_UploadMulti
=== RUN TestImportHandler_UploadMulti/single_Caddyfile
=== RUN TestImportHandler_UploadMulti/Caddyfile_with_site_files
=== RUN TestImportHandler_UploadMulti/missing_Caddyfile
=== RUN TestImportHandler_UploadMulti/path_traversal_in_filename
=== RUN TestImportHandler_UploadMulti/empty_file_content
--- PASS: TestImportHandler_UploadMulti (0.03s)
--- PASS: TestImportHandler_UploadMulti/single_Caddyfile (0.00s)
--- PASS: TestImportHandler_UploadMulti/Caddyfile_with_site_files (0.00s)
--- PASS: TestImportHandler_UploadMulti/missing_Caddyfile (0.00s)
--- PASS: TestImportHandler_UploadMulti/path_traversal_in_filename (0.00s)
--- PASS: TestImportHandler_UploadMulti/empty_file_content (0.00s)
=== RUN TestNotificationHandler_List
--- PASS: TestNotificationHandler_List (0.01s)
=== RUN TestNotificationHandler_MarkAsRead
--- PASS: TestNotificationHandler_MarkAsRead (0.01s)
=== RUN TestNotificationHandler_MarkAllAsRead
--- PASS: TestNotificationHandler_MarkAllAsRead (0.01s)
=== RUN TestNotificationHandler_MarkAllAsRead_Error
--- PASS: TestNotificationHandler_MarkAllAsRead_Error (0.01s)
=== RUN TestNotificationHandler_DBError
--- PASS: TestNotificationHandler_DBError (0.01s)
=== RUN TestNotificationProviderHandler_CRUD
[GIN] 2026/01/10 - 02:24:28 | 201 | 455.583µs | | POST "/api/v1/notifications/providers"
[GIN] 2026/01/10 - 02:24:28 | 200 | 237.03µs | | GET "/api/v1/notifications/providers"
[GIN] 2026/01/10 - 02:24:28 | 200 | 395.081µs | | PUT "/api/v1/notifications/providers/19f9ccc0-a4f6-421b-9541-c556bdee06d9"
[GIN] 2026/01/10 - 02:24:28 | 200 | 153.631µs | | DELETE "/api/v1/notifications/providers/19f9ccc0-a4f6-421b-9541-c556bdee06d9"
--- PASS: TestNotificationProviderHandler_CRUD (0.01s)
=== RUN TestNotificationProviderHandler_Templates
[GIN] 2026/01/10 - 02:24:28 | 200 | 84.391µs | | GET "/api/v1/notifications/templates"
--- PASS: TestNotificationProviderHandler_Templates (0.01s)
=== RUN TestNotificationProviderHandler_Test
[GIN] 2026/01/10 - 02:24:28 | 400 | 535.722µs | | POST "/api/v1/notifications/providers/test"
--- PASS: TestNotificationProviderHandler_Test (0.00s)
=== RUN TestNotificationProviderHandler_Errors
[GIN] 2026/01/10 - 02:24:28 | 400 | 38.21µs | | POST "/api/v1/notifications/providers"
[GIN] 2026/01/10 - 02:24:28 | 400 | 20.67µs | | PUT "/api/v1/notifications/providers/123"
[GIN] 2026/01/10 - 02:24:28 | 400 | 19.43µs | | POST "/api/v1/notifications/providers/test"
--- PASS: TestNotificationProviderHandler_Errors (0.00s)
=== RUN TestNotificationProviderHandler_InvalidCustomTemplate_Rejects
[GIN] 2026/01/10 - 02:24:28 | 400 | 203.791µs | | POST "/api/v1/notifications/providers"
[GIN] 2026/01/10 - 02:24:28 | 201 | 416.732µs | | POST "/api/v1/notifications/providers"
[GIN] 2026/01/10 - 02:24:28 | 400 | 137.501µs | | PUT "/api/v1/notifications/providers/c3d48686-6348-4440-8417-eaec4cd16093"
--- PASS: TestNotificationProviderHandler_InvalidCustomTemplate_Rejects (0.01s)
=== RUN TestNotificationProviderHandler_Preview
[GIN] 2026/01/10 - 02:24:28 | 200 | 415.902µs | | POST "/api/v1/notifications/providers/preview"
[GIN] 2026/01/10 - 02:24:28 | 400 | 248.891µs | | POST "/api/v1/notifications/providers/preview"
--- PASS: TestNotificationProviderHandler_Preview (0.00s)
=== RUN TestRemoteServerHandler_TestConnectionCustom
[GIN] 2026/01/10 - 02:24:28 | 200 | 1.952616ms | | POST "/api/v1/remote-servers/test"
--- PASS: TestRemoteServerHandler_TestConnectionCustom (0.03s)
=== RUN TestRemoteServerHandler_FullCRUD
[GIN] 2026/01/10 - 02:24:28 | 201 | 1.055584ms | | POST "/api/v1/remote-servers"
[GIN] 2026/01/10 - 02:24:28 | 200 | 274.871µs | | GET "/api/v1/remote-servers"
[GIN] 2026/01/10 - 02:24:28 | 200 | 233.741µs | | GET "/api/v1/remote-servers/5a619327-d8de-4d58-917a-f6d159264bbc"
[GIN] 2026/01/10 - 02:24:28 | 200 | 675.653µs | | PUT "/api/v1/remote-servers/5a619327-d8de-4d58-917a-f6d159264bbc"
[GIN] 2026/01/10 - 02:24:28 | 204 | 504.062µs | | DELETE "/api/v1/remote-servers/5a619327-d8de-4d58-917a-f6d159264bbc"
[GIN] 2026/01/10 - 02:24:28 | 400 | 32.881µs | | POST "/api/v1/remote-servers"
[GIN] 2026/01/10 - 02:24:28 | 404 | 131.18µs | | PUT "/api/v1/remote-servers/non-existent-uuid"
[GIN] 2026/01/10 - 02:24:28 | 404 | 113.17µs | | DELETE "/api/v1/remote-servers/non-existent-uuid"
--- PASS: TestRemoteServerHandler_FullCRUD (0.03s)
=== RUN TestSettingsHandler_GetSettings
--- PASS: TestSettingsHandler_GetSettings (0.00s)
=== RUN TestSettingsHandler_GetSettings_DatabaseError
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/settings_handler.go:30 sql: database is closed
[0.026ms] [rows:0] SELECT * FROM `settings`
--- PASS: TestSettingsHandler_GetSettings_DatabaseError (0.00s)
=== RUN TestSettingsHandler_UpdateSettings
--- PASS: TestSettingsHandler_UpdateSettings (0.00s)
=== RUN TestSettingsHandler_UpdateSetting_DatabaseError
2026/01/10 02:24:28 /projects/Charon/backend/internal/api/handlers/settings_handler.go:72 sql: database is closed
[0.026ms] [rows:0] SELECT * FROM `settings` WHERE `settings`.`key` = "test_key" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestSettingsHandler_UpdateSetting_DatabaseError (0.00s)
=== RUN TestSettingsHandler_Errors
--- PASS: TestSettingsHandler_Errors (0.00s)
=== RUN TestSettingsHandler_GetSMTPConfig
--- PASS: TestSettingsHandler_GetSMTPConfig (0.00s)
=== RUN TestSettingsHandler_GetSMTPConfig_Empty
--- PASS: TestSettingsHandler_GetSMTPConfig_Empty (0.01s)
=== RUN TestSettingsHandler_GetSMTPConfig_DatabaseError
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/mail_service.go:91 sql: database is closed
[0.019ms] [rows:0] SELECT * FROM `settings` WHERE category = "smtp"
--- PASS: TestSettingsHandler_GetSMTPConfig_DatabaseError (0.00s)
=== RUN TestSettingsHandler_UpdateSMTPConfig_NonAdmin
--- PASS: TestSettingsHandler_UpdateSMTPConfig_NonAdmin (0.00s)
=== RUN TestSettingsHandler_UpdateSMTPConfig_InvalidJSON
--- PASS: TestSettingsHandler_UpdateSMTPConfig_InvalidJSON (0.00s)
=== RUN TestSettingsHandler_UpdateSMTPConfig_Success
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/mail_service.go:142 record not found
[0.047ms] [rows:0] SELECT * FROM `settings` WHERE key = "smtp_host" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/mail_service.go:142 record not found
[0.078ms] [rows:0] SELECT * FROM `settings` WHERE key = "smtp_port" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/mail_service.go:142 record not found
[0.104ms] [rows:0] SELECT * FROM `settings` WHERE key = "smtp_username" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/mail_service.go:142 record not found
[0.069ms] [rows:0] SELECT * FROM `settings` WHERE key = "smtp_password" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/mail_service.go:142 record not found
[0.054ms] [rows:0] SELECT * FROM `settings` WHERE key = "smtp_from_address" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/mail_service.go:142 record not found
[0.080ms] [rows:0] SELECT * FROM `settings` WHERE key = "smtp_encryption" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestSettingsHandler_UpdateSMTPConfig_Success (0.00s)
=== RUN TestSettingsHandler_UpdateSMTPConfig_KeepExistingPassword
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/mail_service.go:142 record not found
[0.066ms] [rows:0] SELECT * FROM `settings` WHERE key = "smtp_username" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestSettingsHandler_UpdateSMTPConfig_KeepExistingPassword (0.00s)
=== RUN TestSettingsHandler_TestSMTPConfig_NonAdmin
--- PASS: TestSettingsHandler_TestSMTPConfig_NonAdmin (0.00s)
=== RUN TestSettingsHandler_TestSMTPConfig_NotConfigured
--- PASS: TestSettingsHandler_TestSMTPConfig_NotConfigured (0.00s)
=== RUN TestSettingsHandler_TestSMTPConfig_Success
--- PASS: TestSettingsHandler_TestSMTPConfig_Success (0.00s)
=== RUN TestSettingsHandler_SendTestEmail_NonAdmin
--- PASS: TestSettingsHandler_SendTestEmail_NonAdmin (0.00s)
=== RUN TestSettingsHandler_SendTestEmail_InvalidJSON
--- PASS: TestSettingsHandler_SendTestEmail_InvalidJSON (0.00s)
=== RUN TestSettingsHandler_SendTestEmail_NotConfigured
--- PASS: TestSettingsHandler_SendTestEmail_NotConfigured (0.00s)
=== RUN TestSettingsHandler_SendTestEmail_Success
--- PASS: TestSettingsHandler_SendTestEmail_Success (0.00s)
=== RUN TestMaskPassword
--- PASS: TestMaskPassword (0.00s)
=== RUN TestSettingsHandler_ValidatePublicURL_NonAdmin
--- PASS: TestSettingsHandler_ValidatePublicURL_NonAdmin (0.00s)
=== RUN TestSettingsHandler_ValidatePublicURL_InvalidFormat
=== RUN TestSettingsHandler_ValidatePublicURL_InvalidFormat/Missing_scheme
=== RUN TestSettingsHandler_ValidatePublicURL_InvalidFormat/Invalid_scheme
=== RUN TestSettingsHandler_ValidatePublicURL_InvalidFormat/URL_with_path
--- PASS: TestSettingsHandler_ValidatePublicURL_InvalidFormat (0.00s)
--- PASS: TestSettingsHandler_ValidatePublicURL_InvalidFormat/Missing_scheme (0.00s)
--- PASS: TestSettingsHandler_ValidatePublicURL_InvalidFormat/Invalid_scheme (0.00s)
--- PASS: TestSettingsHandler_ValidatePublicURL_InvalidFormat/URL_with_path (0.00s)
=== RUN TestSettingsHandler_ValidatePublicURL_Success
=== RUN TestSettingsHandler_ValidatePublicURL_Success/HTTPS_URL
=== RUN TestSettingsHandler_ValidatePublicURL_Success/HTTP_URL
=== RUN TestSettingsHandler_ValidatePublicURL_Success/URL_with_port
=== RUN TestSettingsHandler_ValidatePublicURL_Success/URL_with_trailing_slash
--- PASS: TestSettingsHandler_ValidatePublicURL_Success (0.00s)
--- PASS: TestSettingsHandler_ValidatePublicURL_Success/HTTPS_URL (0.00s)
--- PASS: TestSettingsHandler_ValidatePublicURL_Success/HTTP_URL (0.00s)
--- PASS: TestSettingsHandler_ValidatePublicURL_Success/URL_with_port (0.00s)
--- PASS: TestSettingsHandler_ValidatePublicURL_Success/URL_with_trailing_slash (0.00s)
=== RUN TestSettingsHandler_TestPublicURL_NonAdmin
--- PASS: TestSettingsHandler_TestPublicURL_NonAdmin (0.00s)
=== RUN TestSettingsHandler_TestPublicURL_NoRole
--- PASS: TestSettingsHandler_TestPublicURL_NoRole (0.00s)
=== RUN TestSettingsHandler_TestPublicURL_InvalidJSON
--- PASS: TestSettingsHandler_TestPublicURL_InvalidJSON (0.00s)
=== RUN TestSettingsHandler_TestPublicURL_InvalidURL
--- PASS: TestSettingsHandler_TestPublicURL_InvalidURL (0.00s)
=== RUN TestSettingsHandler_TestPublicURL_PrivateIPBlocked
=== RUN TestSettingsHandler_TestPublicURL_PrivateIPBlocked/localhost
=== RUN TestSettingsHandler_TestPublicURL_PrivateIPBlocked/127.0.0.1
=== RUN TestSettingsHandler_TestPublicURL_PrivateIPBlocked/Private_10.x
=== RUN TestSettingsHandler_TestPublicURL_PrivateIPBlocked/Private_192.168.x
=== RUN TestSettingsHandler_TestPublicURL_PrivateIPBlocked/AWS_metadata
--- PASS: TestSettingsHandler_TestPublicURL_PrivateIPBlocked (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_PrivateIPBlocked/localhost (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_PrivateIPBlocked/127.0.0.1 (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_PrivateIPBlocked/Private_10.x (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_PrivateIPBlocked/Private_192.168.x (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_PrivateIPBlocked/AWS_metadata (0.00s)
=== RUN TestSettingsHandler_TestPublicURL_Success
2026/01/10 02:24:28 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:24:28Z","action":"url_connectivity_test","host":"example.com","request_id":"test-1768011868760076519","result":"allowed","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestSettingsHandler_TestPublicURL_Success (0.08s)
=== RUN TestSettingsHandler_TestPublicURL_DNSFailure
--- PASS: TestSettingsHandler_TestPublicURL_DNSFailure (0.00s)
=== RUN TestSettingsHandler_TestPublicURL_ConnectivityError
--- PASS: TestSettingsHandler_TestPublicURL_ConnectivityError (0.00s)
=== RUN TestSettingsHandler_TestPublicURL_SSRFProtection
=== RUN TestSettingsHandler_TestPublicURL_SSRFProtection/blocks_RFC_1918_-_10.x
=== RUN TestSettingsHandler_TestPublicURL_SSRFProtection/blocks_RFC_1918_-_192.168.x
=== RUN TestSettingsHandler_TestPublicURL_SSRFProtection/blocks_RFC_1918_-_172.16.x
=== RUN TestSettingsHandler_TestPublicURL_SSRFProtection/blocks_localhost
=== RUN TestSettingsHandler_TestPublicURL_SSRFProtection/blocks_127.0.0.1
=== RUN TestSettingsHandler_TestPublicURL_SSRFProtection/blocks_cloud_metadata
=== RUN TestSettingsHandler_TestPublicURL_SSRFProtection/blocks_link-local
--- PASS: TestSettingsHandler_TestPublicURL_SSRFProtection (0.01s)
--- PASS: TestSettingsHandler_TestPublicURL_SSRFProtection/blocks_RFC_1918_-_10.x (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_SSRFProtection/blocks_RFC_1918_-_192.168.x (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_SSRFProtection/blocks_RFC_1918_-_172.16.x (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_SSRFProtection/blocks_localhost (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_SSRFProtection/blocks_127.0.0.1 (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_SSRFProtection/blocks_cloud_metadata (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_SSRFProtection/blocks_link-local (0.00s)
=== RUN TestSettingsHandler_TestPublicURL_EmbeddedCredentials
--- PASS: TestSettingsHandler_TestPublicURL_EmbeddedCredentials (0.00s)
=== RUN TestSettingsHandler_TestPublicURL_EmptyURL
=== RUN TestSettingsHandler_TestPublicURL_EmptyURL/empty_string
=== RUN TestSettingsHandler_TestPublicURL_EmptyURL/missing_field
--- PASS: TestSettingsHandler_TestPublicURL_EmptyURL (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_EmptyURL/empty_string (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_EmptyURL/missing_field (0.00s)
=== RUN TestSettingsHandler_TestPublicURL_InvalidScheme
=== RUN TestSettingsHandler_TestPublicURL_InvalidScheme/ftp_scheme
=== RUN TestSettingsHandler_TestPublicURL_InvalidScheme/file_scheme
=== RUN TestSettingsHandler_TestPublicURL_InvalidScheme/javascript_scheme
--- PASS: TestSettingsHandler_TestPublicURL_InvalidScheme (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_InvalidScheme/ftp_scheme (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_InvalidScheme/file_scheme (0.00s)
--- PASS: TestSettingsHandler_TestPublicURL_InvalidScheme/javascript_scheme (0.00s)
=== RUN TestSettingsHandler_ValidatePublicURL_InvalidJSON
--- PASS: TestSettingsHandler_ValidatePublicURL_InvalidJSON (0.00s)
=== RUN TestSettingsHandler_ValidatePublicURL_URLWithWarning
--- PASS: TestSettingsHandler_ValidatePublicURL_URLWithWarning (0.00s)
=== RUN TestSettingsHandler_UpdateSMTPConfig_DatabaseError
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/mail_service.go:91 sql: database is closed
[0.037ms] [rows:0] SELECT * FROM `settings` WHERE category = "smtp"
2026/01/10 02:24:28 /projects/Charon/backend/internal/services/mail_service.go:142 sql: database is closed
[0.026ms] [rows:0] SELECT * FROM `settings` WHERE key = "smtp_host" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestSettingsHandler_UpdateSMTPConfig_DatabaseError (0.00s)
=== RUN TestSettingsHandler_TestPublicURL_IPv6LocalhostBlocked
--- PASS: TestSettingsHandler_TestPublicURL_IPv6LocalhostBlocked (0.00s)
=== RUN TestUptimeHandler_List
[GIN] 2026/01/10 - 02:24:28 | 200 | 437.171µs | | GET "/api/v1/uptime"
--- PASS: TestUptimeHandler_List (0.03s)
=== RUN TestUptimeHandler_GetHistory
[GIN] 2026/01/10 - 02:24:28 | 200 | 266.771µs | | GET "/api/v1/uptime/monitor-1/history"
--- PASS: TestUptimeHandler_GetHistory (0.02s)
=== RUN TestUptimeHandler_CheckMonitor
[GIN] 2026/01/10 - 02:24:28 | 200 | 272.301µs | | POST "/api/v1/uptime/check-mon-1/check"
--- PASS: TestUptimeHandler_CheckMonitor (0.03s)
=== RUN TestUptimeHandler_CheckMonitor_NotFound
[GIN] 2026/01/10 - 02:24:28 | 404 | 286.201µs | | POST "/api/v1/uptime/nonexistent/check"
--- PASS: TestUptimeHandler_CheckMonitor_NotFound (0.02s)
=== RUN TestUptimeHandler_Update
=== RUN TestUptimeHandler_Update/success
[GIN] 2026/01/10 - 02:24:28 | 200 | 589.321µs | | PUT "/api/v1/uptime/monitor-update"
=== RUN TestUptimeHandler_Update/invalid_json
[GIN] 2026/01/10 - 02:24:29 | 400 | 159.921µs | | PUT "/api/v1/uptime/monitor-1"
=== RUN TestUptimeHandler_Update/not_found
[GIN] 2026/01/10 - 02:24:29 | 500 | 239.771µs | | PUT "/api/v1/uptime/nonexistent"
--- PASS: TestUptimeHandler_Update (0.08s)
--- PASS: TestUptimeHandler_Update/success (0.03s)
--- PASS: TestUptimeHandler_Update/invalid_json (0.02s)
--- PASS: TestUptimeHandler_Update/not_found (0.02s)
=== RUN TestUptimeHandler_DeleteAndSync
=== RUN TestUptimeHandler_DeleteAndSync/delete_monitor
[GIN] 2026/01/10 - 02:24:29 | 200 | 455.851µs | | DELETE "/api/v1/uptime/mon-delete"
=== RUN TestUptimeHandler_DeleteAndSync/sync_creates_monitor_for_proxy_host
[GIN] 2026/01/10 - 02:24:29 | 200 | 1.287745ms | | POST "/api/v1/uptime/sync"
=== RUN TestUptimeHandler_DeleteAndSync/update_enabled_via_PUT
[GIN] 2026/01/10 - 02:24:29 | 200 | 564.043µs | | PUT "/api/v1/uptime/mon-enable"
--- PASS: TestUptimeHandler_DeleteAndSync (0.07s)
--- PASS: TestUptimeHandler_DeleteAndSync/delete_monitor (0.02s)
--- PASS: TestUptimeHandler_DeleteAndSync/sync_creates_monitor_for_proxy_host (0.02s)
--- PASS: TestUptimeHandler_DeleteAndSync/update_enabled_via_PUT (0.02s)
=== RUN TestUptimeHandler_Sync_Success
[GIN] 2026/01/10 - 02:24:29 | 200 | 265.551µs | | POST "/api/v1/uptime/sync"
--- PASS: TestUptimeHandler_Sync_Success (0.03s)
=== RUN TestUptimeHandler_Delete_Error
[GIN] 2026/01/10 - 02:24:29 | 500 | 178.732µs | | DELETE "/api/v1/uptime/nonexistent"
--- PASS: TestUptimeHandler_Delete_Error (0.02s)
=== RUN TestUptimeHandler_List_Error
[GIN] 2026/01/10 - 02:24:29 | 500 | 230.432µs | | GET "/api/v1/uptime"
--- PASS: TestUptimeHandler_List_Error (0.02s)
=== RUN TestUptimeHandler_GetHistory_Error
[GIN] 2026/01/10 - 02:24:29 | 500 | 175.441µs | | GET "/api/v1/uptime/monitor-1/history"
--- PASS: TestUptimeHandler_GetHistory_Error (0.02s)
=== CONT TestAuthHandler_Login
=== CONT TestCrowdsecHandler_Status_LAPINotReady
=== CONT TestExportConfigStreamsArchive
=== CONT TestProxyHostHandler_BulkUpdateSecurityHeaders_RemoveProfile
--- PASS: TestExportConfigStreamsArchive (0.02s)
=== CONT TestExportConfig
--- PASS: TestCrowdsecHandler_Status_LAPINotReady (0.03s)
=== CONT TestImportCreatesBackup
--- PASS: TestExportConfig (0.01s)
=== CONT TestListAndReadFile
--- PASS: TestImportCreatesBackup (0.01s)
=== CONT TestRemoteServerHandler_Errors
--- PASS: TestListAndReadFile (0.00s)
=== CONT TestHealthHandler
--- PASS: TestHealthHandler (0.00s)
=== CONT TestProxyHostHandler_PartialUpdate_DoesNotWipeFields
--- PASS: TestProxyHostHandler_BulkUpdateSecurityHeaders_RemoveProfile (0.07s)
--- PASS: TestRemoteServerHandler_Errors (0.04s)
=== CONT TestProxyHostHandler_Create
=== CONT TestProxyHostHandler_List
--- PASS: TestProxyHostHandler_PartialUpdate_DoesNotWipeFields (0.06s)
=== CONT TestRemoteServerHandler_Update
--- PASS: TestProxyHostHandler_Create (0.03s)
=== CONT TestRemoteServerHandler_Get
--- PASS: TestProxyHostHandler_List (0.05s)
=== CONT TestRemoteServerHandler_TestConnection
--- PASS: TestRemoteServerHandler_Update (0.03s)
=== CONT TestRemoteServerHandler_Create
--- PASS: TestRemoteServerHandler_Get (0.03s)
=== CONT TestRemoteServerHandler_Delete
--- PASS: TestRemoteServerHandler_TestConnection (0.03s)
=== CONT TestOpenTestDB_ParallelSafety
=== RUN TestOpenTestDB_ParallelSafety/parallel-0
=== PAUSE TestOpenTestDB_ParallelSafety/parallel-0
=== RUN TestOpenTestDB_ParallelSafety/parallel-1
=== PAUSE TestOpenTestDB_ParallelSafety/parallel-1
=== RUN TestOpenTestDB_ParallelSafety/parallel-2
=== PAUSE TestOpenTestDB_ParallelSafety/parallel-2
=== RUN TestOpenTestDB_ParallelSafety/parallel-3
=== PAUSE TestOpenTestDB_ParallelSafety/parallel-3
=== RUN TestOpenTestDB_ParallelSafety/parallel-4
=== PAUSE TestOpenTestDB_ParallelSafety/parallel-4
=== CONT TestRemoteServerHandler_List
--- PASS: TestRemoteServerHandler_Create (0.04s)
=== CONT TestSecurityNotificationHandler_UpdateSettings_Success
--- PASS: TestSecurityNotificationHandler_UpdateSettings_Success (0.00s)
--- PASS: TestRemoteServerHandler_Delete (0.03s)
=== CONT TestSecurityNotificationHandler_UpdateSettings_ServiceError
--- PASS: TestSecurityNotificationHandler_UpdateSettings_ServiceError (0.00s)
=== CONT TestSecurityNotificationHandler_UpdateSettings_EmptyWebhookURL
--- PASS: TestSecurityNotificationHandler_UpdateSettings_EmptyWebhookURL (0.00s)
=== CONT TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF
=== RUN TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF/AWS_Metadata
=== CONT TestSecurityNotificationHandler_UpdateSettings_InvalidMinLogLevel
=== RUN TestSecurityNotificationHandler_UpdateSettings_InvalidMinLogLevel/trace
=== RUN TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF/GCP_Metadata
=== RUN TestSecurityNotificationHandler_UpdateSettings_InvalidMinLogLevel/critical
=== RUN TestSecurityNotificationHandler_UpdateSettings_InvalidMinLogLevel/fatal
=== RUN TestSecurityNotificationHandler_UpdateSettings_InvalidMinLogLevel/unknown
--- PASS: TestSecurityNotificationHandler_UpdateSettings_InvalidMinLogLevel (0.00s)
--- PASS: TestSecurityNotificationHandler_UpdateSettings_InvalidMinLogLevel/trace (0.00s)
--- PASS: TestSecurityNotificationHandler_UpdateSettings_InvalidMinLogLevel/critical (0.00s)
--- PASS: TestSecurityNotificationHandler_UpdateSettings_InvalidMinLogLevel/fatal (0.00s)
--- PASS: TestSecurityNotificationHandler_UpdateSettings_InvalidMinLogLevel/unknown (0.00s)
=== CONT TestSecurityNotificationHandler_UpdateSettings_PrivateIPWebhook
=== RUN TestSecurityNotificationHandler_UpdateSettings_PrivateIPWebhook/http://127.0.0.1/hook
=== RUN TestSecurityNotificationHandler_UpdateSettings_PrivateIPWebhook/http://localhost/webhook
=== RUN TestSecurityNotificationHandler_UpdateSettings_PrivateIPWebhook/http://[::1]/api
--- PASS: TestSecurityNotificationHandler_UpdateSettings_PrivateIPWebhook (0.00s)
--- PASS: TestSecurityNotificationHandler_UpdateSettings_PrivateIPWebhook/http://127.0.0.1/hook (0.00s)
--- PASS: TestSecurityNotificationHandler_UpdateSettings_PrivateIPWebhook/http://localhost/webhook (0.00s)
--- PASS: TestSecurityNotificationHandler_UpdateSettings_PrivateIPWebhook/http://[::1]/api (0.00s)
=== CONT TestSecurityNotificationHandler_GetSettings_ServiceError
--- PASS: TestSecurityNotificationHandler_GetSettings_ServiceError (0.00s)
=== CONT TestSecurityNotificationHandler_GetSettings_Success
--- PASS: TestSecurityNotificationHandler_GetSettings_Success (0.00s)
=== CONT TestSecurityNotificationHandler_UpdateSettings_InvalidJSON
--- PASS: TestSecurityNotificationHandler_UpdateSettings_InvalidJSON (0.00s)
=== CONT TestBulkUpdateSecurityHeaders_DBError_NonNotFound
=== RUN TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF/Azure_Metadata
=== RUN TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF/Private_IP_10.x
=== RUN TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF/Private_IP_172.16.x
=== RUN TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF/Private_IP_192.168.x
=== RUN TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF/Link-local
--- PASS: TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF (0.01s)
--- PASS: TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF/AWS_Metadata (0.00s)
--- PASS: TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF/GCP_Metadata (0.01s)
--- PASS: TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF/Azure_Metadata (0.00s)
--- PASS: TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF/Private_IP_10.x (0.00s)
--- PASS: TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF/Private_IP_172.16.x (0.00s)
--- PASS: TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF/Private_IP_192.168.x (0.00s)
--- PASS: TestSecurityNotificationHandler_UpdateSettings_InvalidWebhookURL_SSRF/Link-local (0.00s)
=== CONT TestProxyHostUpdate_SecurityHeaderProfileID_SetToNull
--- PASS: TestRemoteServerHandler_List (0.03s)
=== CONT TestNewSecurityNotificationHandler
--- PASS: TestNewSecurityNotificationHandler (0.00s)
=== CONT TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType
2026/01/10 02:24:29 /projects/Charon/backend/internal/api/handlers/proxy_host_handler.go:615 sql: database is closed
[0.029ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE `security_header_profiles`.`id` = 1 ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestBulkUpdateSecurityHeaders_DBError_NonNotFound (0.02s)
=== CONT TestProxyHostUpdate_SecurityHeaderProfileID_InvalidString
=== RUN TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/boolean_true
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/boolean_true
=== RUN TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/boolean_false
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/boolean_false
=== RUN TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/array
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/array
=== RUN TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/object
=== PAUSE TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/object
=== CONT TestProxyHostUpdate_SecurityHeaderProfileID_ValidAssignment
--- PASS: TestProxyHostUpdate_SecurityHeaderProfileID_SetToNull (0.05s)
=== CONT TestProxyHostUpdate_SecurityHeaderProfileID_NegativeFloat
--- PASS: TestProxyHostUpdate_SecurityHeaderProfileID_InvalidString (0.04s)
=== CONT TestProxyHostUpdate_SecurityHeaderProfileID_NegativeInt
--- PASS: TestProxyHostUpdate_SecurityHeaderProfileID_NegativeFloat (0.02s)
=== CONT TestProxyHostUpdate_ForwardAuthEnabled
=== RUN TestProxyHostUpdate_SecurityHeaderProfileID_ValidAssignment/as_float64
=== RUN TestProxyHostUpdate_SecurityHeaderProfileID_ValidAssignment/as_string
--- PASS: TestProxyHostUpdate_SecurityHeaderProfileID_NegativeInt (0.03s)
=== CONT TestProxyHostUpdate_EnableStandardHeaders_False
--- PASS: TestProxyHostUpdate_SecurityHeaderProfileID_ValidAssignment (0.05s)
--- PASS: TestProxyHostUpdate_SecurityHeaderProfileID_ValidAssignment/as_float64 (0.00s)
--- PASS: TestProxyHostUpdate_SecurityHeaderProfileID_ValidAssignment/as_string (0.01s)
=== CONT TestProxyHostUpdate_WAFDisabled
--- PASS: TestProxyHostUpdate_ForwardAuthEnabled (0.04s)
=== CONT TestProxyHostUpdate_EnableStandardHeaders_True
--- PASS: TestProxyHostUpdate_WAFDisabled (0.03s)
=== CONT TestProxyHostUpdate_CertificateID_StringValue
--- PASS: TestProxyHostUpdate_EnableStandardHeaders_False (0.03s)
=== CONT TestProxyHostUpdate_EnableStandardHeaders_Null
--- PASS: TestProxyHostUpdate_EnableStandardHeaders_True (0.02s)
=== CONT TestProxyHostUpdate_CertificateID_IntValue
--- PASS: TestProxyHostUpdate_EnableStandardHeaders_Null (0.03s)
=== CONT TestProxyHostUpdate_AccessListID_IntValue
--- PASS: TestProxyHostUpdate_CertificateID_StringValue (0.03s)
=== CONT TestProxyHostUpdate_NegativeIntCertificateID
--- PASS: TestProxyHostUpdate_CertificateID_IntValue (0.03s)
=== CONT TestProxyHostHandler_BulkUpdateSecurityHeaders_AllFail
--- PASS: TestProxyHostUpdate_NegativeIntCertificateID (0.02s)
=== CONT TestProxyHostHandler_BulkUpdateSecurityHeaders_ProfileNotFound
--- PASS: TestProxyHostUpdate_AccessListID_IntValue (0.04s)
=== CONT TestProxyHostUpdate_AccessListID_StringValue
2026/01/10 02:24:29 /projects/Charon/backend/internal/api/handlers/proxy_host_handler.go:615 record not found
[0.111ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE `security_header_profiles`.`id` = 99999 ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestProxyHostHandler_BulkUpdateSecurityHeaders_ProfileNotFound (0.04s)
=== CONT TestProxyHostHandler_BulkUpdateSecurityHeaders_EmptyUUIDs
2026/01/10 02:24:29 /projects/Charon/backend/internal/api/handlers/proxy_host_handler.go:638 record not found
[0.104ms] [rows:0] SELECT * FROM `proxy_hosts` WHERE uuid = "8c5c2bdf-0760-4ddb-9980-c72c43b5fe33" ORDER BY `proxy_hosts`.`id` LIMIT 1
2026/01/10 02:24:29 /projects/Charon/backend/internal/api/handlers/proxy_host_handler.go:638 record not found
[0.100ms] [rows:0] SELECT * FROM `proxy_hosts` WHERE uuid = "ea888497-0fec-4c2e-a9ba-9017bc322ac3" ORDER BY `proxy_hosts`.`id` LIMIT 1
--- PASS: TestProxyHostHandler_BulkUpdateSecurityHeaders_AllFail (0.05s)
=== CONT TestProxyHostHandler_BulkUpdateSecurityHeaders_InvalidJSON
--- PASS: TestProxyHostUpdate_AccessListID_StringValue (0.04s)
=== CONT TestProxyHostHandler_BulkUpdateSecurityHeaders_PartialFailure
--- PASS: TestProxyHostHandler_BulkUpdateSecurityHeaders_EmptyUUIDs (0.03s)
=== CONT TestUpdate_ExistingHostsBackwardCompatibility
--- PASS: TestProxyHostHandler_BulkUpdateSecurityHeaders_InvalidJSON (0.03s)
=== CONT TestUpdate_IntegrationCaddyConfig
2026/01/10 02:24:29 /projects/Charon/backend/internal/api/handlers/proxy_host_handler.go:638 record not found
[0.170ms] [rows:0] SELECT * FROM `proxy_hosts` WHERE uuid = "d6bdf056-cc3d-4ff3-bc3f-ce1e4dde3499" ORDER BY `proxy_hosts`.`id` LIMIT 1
--- PASS: TestProxyHostHandler_BulkUpdateSecurityHeaders_PartialFailure (0.06s)
=== CONT TestUpdate_WAFDisabled
2026/01/10 02:24:29 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.069ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:29 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.114ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:29 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[2.830ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:29 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.088ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:29 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.079ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:29 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.076ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:29 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.037ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:29 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[1.014ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:24:29 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[3.027ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestUpdate_WAFDisabled (0.04s)
=== CONT TestProxyHostHandler_BulkUpdateSecurityHeaders_Success
--- PASS: TestUpdate_IntegrationCaddyConfig (0.08s)
=== CONT TestUpdate_ForwardAuthEnabled
--- PASS: TestUpdate_ForwardAuthEnabled (0.04s)
=== CONT TestUpdate_EnableStandardHeaders
--- PASS: TestUpdate_ExistingHostsBackwardCompatibility (0.14s)
=== CONT TestProxyHostUpdate_SecurityHeaderProfile_UnsupportedType
--- PASS: TestProxyHostHandler_BulkUpdateSecurityHeaders_Success (0.07s)
=== CONT TestProxyHostUpdate_SecurityHeaderProfile_InvalidFloat
--- PASS: TestUpdate_EnableStandardHeaders (0.06s)
=== CONT TestProxyHostUpdate_SecurityHeaderProfile_InvalidString
--- PASS: TestProxyHostUpdate_SecurityHeaderProfile_InvalidFloat (0.04s)
=== CONT TestProxyHostUpdate_SecurityHeaderProfile_ValidString
--- PASS: TestProxyHostUpdate_SecurityHeaderProfile_UnsupportedType (0.07s)
=== CONT TestProxyHostUpdate_SecurityHeaderProfile_FromNoneToValid
--- PASS: TestProxyHostUpdate_SecurityHeaderProfile_InvalidString (0.03s)
=== CONT TestProxyHostUpdate_SecurityHeaderProfile_ToNone
--- PASS: TestProxyHostUpdate_SecurityHeaderProfile_ValidString (0.05s)
=== CONT TestProxyHostUpdate_InvalidSecurityHeaderProfileID
--- PASS: TestProxyHostUpdate_SecurityHeaderProfile_FromNoneToValid (0.05s)
=== CONT TestProxyHostUpdate_RemoveSecurityHeaderProfile
--- PASS: TestProxyHostUpdate_SecurityHeaderProfile_ToNone (0.05s)
=== CONT TestProxyHostUpdate_SecurityHeaderProfile_StrictToBasic
--- PASS: TestProxyHostUpdate_InvalidSecurityHeaderProfileID (0.10s)
=== CONT TestProxyHostUpdate_AssignSecurityHeaderProfile
--- PASS: TestProxyHostUpdate_RemoveSecurityHeaderProfile (0.10s)
=== CONT TestProxyHostUpdate_ChangeSecurityHeaderProfile
--- PASS: TestProxyHostUpdate_SecurityHeaderProfile_StrictToBasic (0.10s)
=== CONT TestProxyHostCreate_WithCertificateAndLocations
--- PASS: TestProxyHostUpdate_AssignSecurityHeaderProfile (0.04s)
=== CONT TestProxyHostCreate_WithSecurityHeaderProfile
--- PASS: TestProxyHostCreate_WithCertificateAndLocations (0.03s)
=== CONT TestProxyHostUpdate_SetBooleansAndApplication
--- PASS: TestProxyHostCreate_WithSecurityHeaderProfile (0.04s)
=== CONT TestProxyHostUpdate_Locations_InvalidPayload
--- PASS: TestProxyHostUpdate_ChangeSecurityHeaderProfile (0.06s)
=== CONT TestProxyHostUpdate_Locations_Replace
--- PASS: TestProxyHostUpdate_SetBooleansAndApplication (0.04s)
=== CONT TestProxyHostUpdate_ForwardPort_StringValue
--- PASS: TestProxyHostUpdate_Locations_InvalidPayload (0.02s)
=== CONT TestProxyHostUpdate_AdvancedConfig_SetBackup
--- PASS: TestProxyHostUpdate_ForwardPort_StringValue (0.03s)
=== CONT TestProxyHostUpdate_SetCertificateID
--- PASS: TestProxyHostUpdate_Locations_Replace (0.05s)
=== CONT TestProxyHostUpdate_AdvancedConfig_InvalidJSON
--- PASS: TestProxyHostUpdate_AdvancedConfig_SetBackup (0.03s)
=== CONT TestProxyHostUpdate_AdvancedConfig_ClearAndBackup
--- PASS: TestProxyHostUpdate_SetCertificateID (0.03s)
=== CONT TestProxyHostHandler_BulkUpdateACL_EmptyUUIDs
--- PASS: TestProxyHostUpdate_AdvancedConfig_InvalidJSON (0.03s)
=== CONT TestProxyHostHandler_BulkUpdateACL_PartialFailure
--- PASS: TestProxyHostUpdate_AdvancedConfig_ClearAndBackup (0.03s)
=== CONT TestProxyHostHandler_BulkUpdateACL_InvalidJSON
--- PASS: TestProxyHostHandler_BulkUpdateACL_InvalidJSON (0.03s)
=== CONT TestProxyHostHandler_BulkUpdateACL_Success
--- PASS: TestProxyHostHandler_BulkUpdateACL_EmptyUUIDs (0.04s)
=== CONT TestProxyHostWithCaddyIntegration
2026/01/10 02:24:30 /projects/Charon/backend/internal/services/proxyhost_service.go:117 record not found
[0.088ms] [rows:0] SELECT * FROM `proxy_hosts` WHERE uuid = "07e9e0fb-b069-425f-a470-33bdf2cf6e2e" ORDER BY `proxy_hosts`.`id` LIMIT 1
--- PASS: TestProxyHostHandler_BulkUpdateACL_PartialFailure (0.03s)
=== CONT TestProxyHostHandler_BulkUpdateACL_RemoveACL
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.061ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.061ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.273ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.126ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.092ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.104ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.033ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.826ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.760ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestProxyHostHandler_BulkUpdateACL_Success (0.03s)
=== CONT TestProxyHostConnection
--- PASS: TestProxyHostHandler_BulkUpdateACL_RemoveACL (0.04s)
=== CONT TestProxyHostHandler_List_Error
2026/01/10 02:24:30 /projects/Charon/backend/internal/services/notification_service.go:96 no such table: notification_providers
[1.014ms] [rows:0] SELECT * FROM `notification_providers` WHERE enabled = true
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.059ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.118ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[0.039ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.311ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.097ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.093ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.039ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.037ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.040ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.069ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.124ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[0.064ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.095ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.131ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.095ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.039ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.032ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.058ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
2026/01/10 02:24:30 /projects/Charon/backend/internal/services/notification_service.go:96 no such table: notification_providers
[0.069ms] [rows:0] SELECT * FROM `notification_providers` WHERE enabled = true
--- PASS: TestProxyHostWithCaddyIntegration (0.06s)
=== CONT TestProxyHostCreate_AdvancedConfig_Normalization
--- PASS: TestProxyHostConnection (0.03s)
=== CONT TestProxyHostUpdate_CertificateID_Null
2026/01/10 02:24:30 /projects/Charon/backend/internal/services/proxyhost_service.go:126 sql: database is closed
[0.031ms] [rows:0] SELECT * FROM `proxy_hosts` ORDER BY updated_at desc
--- PASS: TestProxyHostHandler_List_Error (0.02s)
=== CONT TestProxyHostValidation
--- PASS: TestProxyHostUpdate_CertificateID_Null (0.04s)
=== CONT TestProxyHostCreate_AdvancedConfig_InvalidJSON
--- PASS: TestProxyHostCreate_AdvancedConfig_Normalization (0.04s)
=== CONT TestProxyHostDelete_WithUptimeCleanup
--- PASS: TestProxyHostValidation (0.05s)
=== CONT TestProxyHostLifecycle
--- PASS: TestProxyHostCreate_AdvancedConfig_InvalidJSON (0.02s)
=== CONT TestCrowdsecHandler_HubEndpoints
2026/01/10 02:24:30 /projects/Charon/backend/internal/services/notification_service.go:96 no such table: notification_providers
[3.430ms] [rows:0] SELECT * FROM `notification_providers` WHERE enabled = true
2026/01/10 02:24:30 /projects/Charon/backend/internal/api/handlers/proxy_host_handler_test.go:143 record not found
[0.133ms] [rows:0] SELECT * FROM `proxy_hosts` WHERE uuid = "ph-delete-1" ORDER BY `proxy_hosts`.`id` LIMIT 1
--- PASS: TestProxyHostDelete_WithUptimeCleanup (0.03s)
=== CONT TestProxyHostErrors
--- PASS: TestCrowdsecHandler_HubEndpoints (0.01s)
=== CONT TestCrowdsecHandler_Status_LAPIReady
--- PASS: TestCrowdsecHandler_Status_LAPIReady (0.01s)
=== CONT TestCrowdsecHandler_ListDecisions_WithCreatedAt
--- PASS: TestCrowdsecHandler_ListDecisions_WithCreatedAt (0.01s)
=== CONT TestCrowdsecHandler_BanIP_WithConfigYaml
--- PASS: TestCrowdsecHandler_BanIP_WithConfigYaml (0.00s)
=== CONT TestCrowdsecHandler_UnbanIP_WithConfigYaml
2026/01/10 02:24:30 /projects/Charon/backend/internal/services/proxyhost_service.go:117 record not found
[0.108ms] [rows:0] SELECT * FROM `proxy_hosts` WHERE uuid = "baa89836-1f8a-4d50-9840-30e46e95211b" ORDER BY `proxy_hosts`.`id` LIMIT 1
--- PASS: TestProxyHostLifecycle (0.03s)
=== CONT TestCrowdsecHandler_UpdateAcquisitionConfig_InvalidJSON
--- PASS: TestCrowdsecHandler_UnbanIP_WithConfigYaml (0.01s)
=== CONT TestCrowdsecHandler_UpdateAcquisitionConfig_MissingContent
--- PASS: TestCrowdsecHandler_UpdateAcquisitionConfig_InvalidJSON (0.00s)
=== CONT TestCrowdsecHandler_ListDecisions_WithConfigYaml
--- PASS: TestCrowdsecHandler_UpdateAcquisitionConfig_MissingContent (0.00s)
=== CONT TestCrowdsecHandler_CheckLAPIHealth_InvalidURL
--- PASS: TestCrowdsecHandler_ListDecisions_WithConfigYaml (0.01s)
=== CONT TestCrowdsecHandler_BanIP_ExecutionError
--- PASS: TestCrowdsecHandler_BanIP_ExecutionError (0.11s)
=== CONT TestCrowdsecHandler_GetLAPIDecisions_Fallback
--- PASS: TestCrowdsecHandler_CheckLAPIHealth_InvalidURL (0.12s)
=== CONT TestCrowdsecHandler_UnbanIP_Error
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.094ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.068ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.028ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.068ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.075ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.069ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.025ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[3.112ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.784ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestCrowdsecHandler_UnbanIP_Error (0.01s)
=== CONT TestCrowdsecHandler_BanIP_DefaultDuration
--- PASS: TestCrowdsecHandler_GetLAPIDecisions_Fallback (0.02s)
=== CONT TestCrowdsecHandler_UnbanIP_Success
--- PASS: TestCrowdsecHandler_BanIP_DefaultDuration (0.01s)
=== CONT TestCrowdsecHandler_BanIP_EmptyIP
2026/01/10 02:24:30 /projects/Charon/backend/internal/services/proxyhost_service.go:117 record not found
[0.123ms] [rows:0] SELECT * FROM `proxy_hosts` WHERE uuid = "non-existent-uuid" ORDER BY `proxy_hosts`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/services/proxyhost_service.go:117 record not found
[0.119ms] [rows:0] SELECT * FROM `proxy_hosts` WHERE uuid = "non-existent-uuid" ORDER BY `proxy_hosts`.`id` LIMIT 1
--- PASS: TestCrowdsecHandler_UnbanIP_Success (0.01s)
=== CONT TestCrowdsecHandler_BanIP_MissingIP
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.092ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.105ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[0.086ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.084ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.093ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.092ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.045ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.081ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.037ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestCrowdsecHandler_BanIP_EmptyIP (0.01s)
=== CONT TestCrowdsecHandler_ListDecisions_InvalidJSON
--- PASS: TestCrowdsecHandler_BanIP_MissingIP (0.01s)
=== CONT TestCrowdsecHandler_BanIP_Success
2026/01/10 02:24:30 /projects/Charon/backend/internal/services/proxyhost_service.go:117 record not found
[0.159ms] [rows:0] SELECT * FROM `proxy_hosts` WHERE uuid = "non-existent-uuid" ORDER BY `proxy_hosts`.`id` LIMIT 1
--- PASS: TestCrowdsecHandler_ListDecisions_InvalidJSON (0.01s)
=== CONT TestCrowdsecHandler_ListDecisions_Empty
=== CONT TestCrowdsecHandler_ListDecisions_Success
--- PASS: TestCrowdsecHandler_ListDecisions_Empty (0.01s)
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.740ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.082ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestCrowdsecHandler_BanIP_Success (0.01s)
=== CONT TestCrowdsecHandler_ReadFile_MissingPath
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[0.082ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.076ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.104ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.110ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.057ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.063ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:24:30 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.069ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestCrowdsecHandler_ListDecisions_Success (0.01s)
=== CONT TestCrowdsecHandler_ListDecisions_CscliError
--- PASS: TestCrowdsecHandler_ReadFile_MissingPath (0.01s)
--- PASS: TestCrowdsecHandler_ListDecisions_CscliError (0.00s)
=== CONT TestCrowdsecHandler_Start_ExecutorError
=== CONT TestCrowdsecHandler_ExportConfig_DirNotFound
--- PASS: TestCrowdsecHandler_ExportConfig_DirNotFound (0.01s)
=== CONT TestCrowdsecHandler_ReadFile_NotFound
--- PASS: TestProxyHostErrors (0.20s)
=== CONT TestCrowdsecStart_LAPINotReadyTimeout
--- PASS: TestCrowdsecHandler_ReadFile_NotFound (0.00s)
=== CONT TestCrowdsecHandler_Status_Error
--- PASS: TestCrowdsecHandler_Start_ExecutorError (0.01s)
=== CONT TestGetAcquisitionConfigNotFound
--- PASS: TestGetAcquisitionConfigNotFound (0.00s)
=== CONT TestRegisterBouncerExecutionError
--- PASS: TestCrowdsecHandler_Status_Error (0.00s)
=== CONT TestGetAcquisitionConfigSuccess
--- PASS: TestRegisterBouncerExecutionError (0.00s)
=== CONT TestRegisterBouncerScriptNotFound
--- PASS: TestGetAcquisitionConfigSuccess (0.00s)
=== CONT TestRegisterBouncerSuccess
--- PASS: TestRegisterBouncerSuccess (0.00s)
=== CONT TestIsConsoleEnrollmentDisabledFromDB
--- PASS: TestRegisterBouncerScriptNotFound (0.00s)
=== CONT TestIsConsoleEnrollmentEnabledFromDB
--- PASS: TestIsConsoleEnrollmentDisabledFromDB (0.01s)
=== CONT TestIsCerberusEnabledFromDB
--- PASS: TestIsConsoleEnrollmentEnabledFromDB (0.01s)
=== CONT TestListFilesMissingDir
--- PASS: TestListFilesMissingDir (0.00s)
=== CONT TestImportConfigRejectsEmptyUpload
=== CONT TestListFilesReturnsEntries
--- PASS: TestImportConfigRejectsEmptyUpload (0.00s)
=== CONT TestWriteFileInvalidPayload
--- PASS: TestWriteFileInvalidPayload (0.00s)
=== CONT TestCrowdsecEndpoints
--- PASS: TestIsCerberusEnabledFromDB (0.00s)
--- PASS: TestListFilesReturnsEntries (0.00s)
=== CONT TestCerberusLogsHandler_UpgradeFailure
--- PASS: TestCerberusLogsHandler_UpgradeFailure (0.00s)
=== CONT TestCerberusLogsHandler_MultipleClients
--- PASS: TestCerberusLogsHandler_MultipleClients (0.40s)
=== CONT TestImportConfig
--- PASS: TestImportConfig (0.00s)
=== CONT TestCerberusLogsHandler_ClientDisconnect
--- PASS: TestCerberusLogsHandler_ClientDisconnect (0.10s)
=== CONT TestCerberusLogsHandler_IPFilter
--- PASS: TestAuthHandler_Login (1.84s)
=== CONT TestCerberusLogsHandler_SourceFilter
--- PASS: TestCerberusLogsHandler_IPFilter (0.30s)
=== CONT TestCerberusLogsHandler_BlockedOnlyFilter
=== CONT TestCerberusLogsHandler_ReceiveLogEntries
--- PASS: TestCerberusLogsHandler_SourceFilter (0.30s)
--- PASS: TestCerberusLogsHandler_BlockedOnlyFilter (0.30s)
=== CONT TestCerberusLogsHandler_NewHandler
--- PASS: TestCerberusLogsHandler_NewHandler (0.00s)
=== CONT TestAuthHandler_CheckHostAccess_Denied
--- PASS: TestAuthHandler_CheckHostAccess_Denied (0.02s)
=== CONT TestAuthHandler_CheckHostAccess_Allowed
--- PASS: TestCerberusLogsHandler_ReceiveLogEntries (0.30s)
=== CONT TestCerberusLogsHandler_SuccessfulConnection
--- PASS: TestCerberusLogsHandler_SuccessfulConnection (0.00s)
=== CONT TestAuthHandler_CheckHostAccess_Unauthorized
--- PASS: TestAuthHandler_CheckHostAccess_Allowed (0.02s)
=== CONT TestWriteFileMissingPath
--- PASS: TestWriteFileMissingPath (0.00s)
=== CONT TestImportConfigRequiresFile
--- PASS: TestImportConfigRequiresFile (0.00s)
=== CONT TestWriteFileInvalidPath
--- PASS: TestWriteFileInvalidPath (0.00s)
=== CONT TestReadFileInvalidPath
--- PASS: TestReadFileInvalidPath (0.00s)
=== CONT TestWriteFileCreatesBackup
--- PASS: TestAuthHandler_CheckHostAccess_Unauthorized (0.02s)
=== CONT TestAuthHandler_GetAccessibleHosts_UserNotFound
--- PASS: TestWriteFileCreatesBackup (0.00s)
=== CONT TestAuthHandler_GetAccessibleHosts_PermittedHosts
2026/01/10 02:24:31 /projects/Charon/backend/internal/api/handlers/auth_handler.go:334 record not found
[0.106ms] [rows:0] SELECT * FROM `users` WHERE `users`.`id` = 99999 ORDER BY `users`.`id` LIMIT 1
--- PASS: TestAuthHandler_GetAccessibleHosts_UserNotFound (0.02s)
=== CONT TestAuthHandler_GetAccessibleHosts_DenyAll
--- PASS: TestAuthHandler_GetAccessibleHosts_PermittedHosts (0.03s)
=== CONT TestAuthHandler_GetAccessibleHosts_AllowAll
--- PASS: TestAuthHandler_GetAccessibleHosts_DenyAll (0.02s)
=== CONT TestAuthHandler_GetAccessibleHosts_Unauthorized
--- PASS: TestAuthHandler_GetAccessibleHosts_AllowAll (0.02s)
=== CONT TestAuthHandler_VerifyStatus_DisabledUser
--- PASS: TestAuthHandler_GetAccessibleHosts_Unauthorized (0.02s)
=== CONT TestAuthHandler_VerifyStatus_Authenticated
--- PASS: TestAuthHandler_VerifyStatus_Authenticated (0.73s)
=== CONT TestAuthHandler_VerifyStatus_InvalidToken
--- PASS: TestAuthHandler_VerifyStatus_DisabledUser (0.75s)
=== CONT TestAuthHandler_CheckHostAccess_InvalidHostID
--- PASS: TestAuthHandler_VerifyStatus_InvalidToken (0.02s)
=== CONT TestAuthHandler_VerifyStatus_NotAuthenticated
--- PASS: TestAuthHandler_CheckHostAccess_InvalidHostID (0.02s)
=== CONT TestAuthHandler_Verify_ForwardAuthDenied
--- PASS: TestAuthHandler_VerifyStatus_NotAuthenticated (0.03s)
=== CONT TestAuthHandler_Verify_DisabledUser
--- PASS: TestAuthHandler_Verify_ForwardAuthDenied (0.75s)
=== CONT TestAuthHandler_Verify_ValidToken
--- PASS: TestAuthHandler_Verify_DisabledUser (0.77s)
=== CONT TestAuthHandler_Verify_InvalidToken
--- PASS: TestAuthHandler_Verify_InvalidToken (0.02s)
=== CONT TestAuthHandler_Verify_BearerToken
--- PASS: TestAuthHandler_Verify_ValidToken (0.75s)
=== CONT TestNewAuthHandlerWithDB
--- PASS: TestNewAuthHandlerWithDB (0.01s)
=== CONT TestAuthHandler_Verify_NoCookie
--- PASS: TestAuthHandler_Verify_NoCookie (0.02s)
=== CONT TestAuthHandler_ChangePassword_Errors
--- PASS: TestAuthHandler_ChangePassword_Errors (0.02s)
=== CONT TestAuthHandler_ChangePassword_WrongOld
--- PASS: TestAuthHandler_Verify_BearerToken (0.75s)
=== CONT TestAuthHandler_ChangePassword
--- PASS: TestAuthHandler_ChangePassword_WrongOld (1.71s)
=== CONT TestAuthHandler_Me
--- PASS: TestAuthHandler_Me (0.03s)
=== CONT TestAuthHandler_Me_NotFound
2026/01/10 02:24:35 /projects/Charon/backend/internal/services/auth_service.go:147 record not found
[0.110ms] [rows:0] SELECT * FROM `users` WHERE `users`.`id` = 999 ORDER BY `users`.`id` LIMIT 1
--- PASS: TestAuthHandler_Me_NotFound (0.02s)
=== CONT TestAuthHandler_Logout
--- PASS: TestAuthHandler_Logout (0.02s)
=== CONT TestAuthHandler_Register
--- PASS: TestAuthHandler_Register (0.78s)
=== CONT TestAuthHandler_Login_Errors
2026/01/10 02:24:36 /projects/Charon/backend/internal/services/auth_service.go:64 record not found
[0.126ms] [rows:0] SELECT * FROM `users` WHERE email = "nonexistent@example.com" ORDER BY `users`.`id` LIMIT 1
--- PASS: TestAuthHandler_Login_Errors (0.02s)
=== CONT TestAuthHandler_Register_Duplicate
--- PASS: TestAuthHandler_ChangePassword (3.20s)
=== CONT TestSetSecureCookie_HTTP_Lax
--- PASS: TestSetSecureCookie_HTTP_Lax (0.00s)
=== CONT TestOpenTestDB_ParallelSafety/parallel-3
=== CONT TestOpenTestDB_ParallelSafety/parallel-4
=== CONT TestOpenTestDB_ParallelSafety/parallel-2
=== CONT TestOpenTestDB_ParallelSafety/parallel-1
=== CONT TestOpenTestDB_ParallelSafety/parallel-0
--- PASS: TestOpenTestDB_ParallelSafety (0.00s)
--- PASS: TestOpenTestDB_ParallelSafety/parallel-3 (0.00s)
--- PASS: TestOpenTestDB_ParallelSafety/parallel-4 (0.00s)
--- PASS: TestOpenTestDB_ParallelSafety/parallel-2 (0.00s)
--- PASS: TestOpenTestDB_ParallelSafety/parallel-1 (0.00s)
--- PASS: TestOpenTestDB_ParallelSafety/parallel-0 (0.00s)
=== CONT TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/boolean_false
=== CONT TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/array
=== CONT TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/object
=== CONT TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/boolean_true
--- PASS: TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType (0.04s)
--- PASS: TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/boolean_false (0.00s)
--- PASS: TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/array (0.00s)
--- PASS: TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/object (0.00s)
--- PASS: TestProxyHostUpdate_SecurityHeaderProfileID_UnsupportedType/boolean_true (0.00s)
2026/01/10 02:24:37 /projects/Charon/backend/internal/services/auth_service.go:54 UNIQUE constraint failed: users.email
[0.517ms] [rows:0] INSERT INTO `users` (`uuid`,`email`,`api_key`,`password_hash`,`name`,`role`,`enabled`,`failed_login_attempts`,`locked_until`,`last_login`,`invite_token`,`invite_expires`,`invited_at`,`invited_by`,`invite_status`,`permission_mode`,`created_at`,`updated_at`) VALUES ("6fce0af7-2cd7-43c4-bd3c-4b55b59b90f9","dup@example.com","a727f701-f3cc-478a-b4ce-b0e4725a470f","$2a$10$wfJbDIjJM9wSS4ZzXClUTe1qVO5jZMtW9QpArDQ09rMPsAnaa/S5S","Dup User","user",true,0,NULL,NULL,"",NULL,NULL,NULL,"","allow_all","2026-01-10 02:24:36.614","2026-01-10 02:24:36.614") RETURNING `id`
--- PASS: TestAuthHandler_Register_Duplicate (0.76s)
--- PASS: TestCrowdsecStart_LAPINotReadyTimeout (60.12s)
--- PASS: TestCrowdsecEndpoints (60.14s)
FAIL
coverage: 86.9% of statements
FAIL github.com/Wikid82/charon/backend/internal/api/handlers 474.816s
=== RUN TestAuthMiddleware_MissingHeader
--- PASS: TestAuthMiddleware_MissingHeader (0.00s)
=== RUN TestRequireRole_Success
--- PASS: TestRequireRole_Success (0.00s)
=== RUN TestRequireRole_Forbidden
--- PASS: TestRequireRole_Forbidden (0.00s)
=== RUN TestAuthMiddleware_Cookie
--- PASS: TestAuthMiddleware_Cookie (1.22s)
=== RUN TestAuthMiddleware_ValidToken
--- PASS: TestAuthMiddleware_ValidToken (0.85s)
=== RUN TestAuthMiddleware_PrefersAuthorizationHeader
--- PASS: TestAuthMiddleware_PrefersAuthorizationHeader (0.82s)
=== RUN TestAuthMiddleware_InvalidToken
--- PASS: TestAuthMiddleware_InvalidToken (0.03s)
=== RUN TestRequireRole_MissingRoleInContext
--- PASS: TestRequireRole_MissingRoleInContext (0.00s)
=== RUN TestAuthMiddleware_QueryParamFallback
--- PASS: TestAuthMiddleware_QueryParamFallback (0.87s)
=== RUN TestAuthMiddleware_PrefersCookieOverQueryParam
--- PASS: TestAuthMiddleware_PrefersCookieOverQueryParam (1.64s)
=== RUN TestRecoveryLogsStacktraceVerbose
--- PASS: TestRecoveryLogsStacktraceVerbose (0.00s)
=== RUN TestRecoveryLogsBriefWhenNotVerbose
--- PASS: TestRecoveryLogsBriefWhenNotVerbose (0.00s)
=== RUN TestRecoveryDoesNotLogSensitiveHeaders
--- PASS: TestRecoveryDoesNotLogSensitiveHeaders (0.00s)
=== RUN TestRecoveryTruncatesLongPanicMessage
--- PASS: TestRecoveryTruncatesLongPanicMessage (0.00s)
=== RUN TestRecoveryNoPanicNormalFlow
--- PASS: TestRecoveryNoPanicNormalFlow (0.00s)
=== RUN TestRecoveryPanicWithNilValue
--- PASS: TestRecoveryPanicWithNilValue (0.00s)
=== RUN TestRequestIDAddsHeaderAndLogger
--- PASS: TestRequestIDAddsHeaderAndLogger (0.00s)
=== RUN TestRequestLoggerSanitizesPath
--- PASS: TestRequestLoggerSanitizesPath (0.00s)
=== RUN TestRequestLoggerIncludesRequestID
--- PASS: TestRequestLoggerIncludesRequestID (0.00s)
=== RUN TestSanitizeHeaders
=== RUN TestSanitizeHeaders/nil_headers
=== RUN TestSanitizeHeaders/redacts_sensitive_headers
=== RUN TestSanitizeHeaders/sanitizes_and_truncates_values
--- PASS: TestSanitizeHeaders (0.00s)
--- PASS: TestSanitizeHeaders/nil_headers (0.00s)
--- PASS: TestSanitizeHeaders/redacts_sensitive_headers (0.00s)
--- PASS: TestSanitizeHeaders/sanitizes_and_truncates_values (0.00s)
=== RUN TestSanitizePath
--- PASS: TestSanitizePath (0.00s)
=== RUN TestSecurityHeaders
=== RUN TestSecurityHeaders/production_mode_sets_HSTS
=== RUN TestSecurityHeaders/development_mode_skips_HSTS
=== RUN TestSecurityHeaders/sets_X-Frame-Options
=== RUN TestSecurityHeaders/sets_X-Content-Type-Options
=== RUN TestSecurityHeaders/sets_X-XSS-Protection
=== RUN TestSecurityHeaders/sets_Referrer-Policy
=== RUN TestSecurityHeaders/sets_Content-Security-Policy
=== RUN TestSecurityHeaders/development_mode_CSP_allows_unsafe-eval
=== RUN TestSecurityHeaders/sets_Permissions-Policy
=== RUN TestSecurityHeaders/sets_Cross-Origin-Opener-Policy_in_production
=== RUN TestSecurityHeaders/skips_Cross-Origin-Opener-Policy_in_development
=== RUN TestSecurityHeaders/sets_Cross-Origin-Resource-Policy
--- PASS: TestSecurityHeaders (0.00s)
--- PASS: TestSecurityHeaders/production_mode_sets_HSTS (0.00s)
--- PASS: TestSecurityHeaders/development_mode_skips_HSTS (0.00s)
--- PASS: TestSecurityHeaders/sets_X-Frame-Options (0.00s)
--- PASS: TestSecurityHeaders/sets_X-Content-Type-Options (0.00s)
--- PASS: TestSecurityHeaders/sets_X-XSS-Protection (0.00s)
--- PASS: TestSecurityHeaders/sets_Referrer-Policy (0.00s)
--- PASS: TestSecurityHeaders/sets_Content-Security-Policy (0.00s)
--- PASS: TestSecurityHeaders/development_mode_CSP_allows_unsafe-eval (0.00s)
--- PASS: TestSecurityHeaders/sets_Permissions-Policy (0.00s)
--- PASS: TestSecurityHeaders/sets_Cross-Origin-Opener-Policy_in_production (0.00s)
--- PASS: TestSecurityHeaders/skips_Cross-Origin-Opener-Policy_in_development (0.00s)
--- PASS: TestSecurityHeaders/sets_Cross-Origin-Resource-Policy (0.00s)
=== RUN TestSecurityHeadersCustomCSP
--- PASS: TestSecurityHeadersCustomCSP (0.00s)
=== RUN TestDefaultSecurityHeadersConfig
--- PASS: TestDefaultSecurityHeadersConfig (0.00s)
=== RUN TestSecurityHeaders_COOP_DevelopmentMode
--- PASS: TestSecurityHeaders_COOP_DevelopmentMode (0.00s)
=== RUN TestSecurityHeaders_COOP_ProductionMode
--- PASS: TestSecurityHeaders_COOP_ProductionMode (0.00s)
=== RUN TestBuildCSP
=== RUN TestBuildCSP/production_CSP
=== RUN TestBuildCSP/development_CSP
--- PASS: TestBuildCSP (0.00s)
--- PASS: TestBuildCSP/production_CSP (0.00s)
--- PASS: TestBuildCSP/development_CSP (0.00s)
=== RUN TestBuildPermissionsPolicy
--- PASS: TestBuildPermissionsPolicy (0.00s)
PASS
coverage: 99.1% of statements
ok github.com/Wikid82/charon/backend/internal/api/middleware (cached) coverage: 99.1% of statements
=== RUN TestRegister
time="2026-01-10T02:16:51Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:51Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:51Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
2026/01/10 02:16:51 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.131ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-basic" ORDER BY `security_header_profiles`.`id` LIMIT 1
2026/01/10 02:16:51 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.138ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-api-friendly" ORDER BY `security_header_profiles`.`id` LIMIT 1
2026/01/10 02:16:51 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.123ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-strict" ORDER BY `security_header_profiles`.`id` LIMIT 1
2026/01/10 02:16:51 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.164ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-paranoid" ORDER BY `security_header_profiles`.`id` LIMIT 1
time="2026-01-10T02:16:51Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:51Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:51Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
--- PASS: TestRegister (0.13s)
=== RUN TestRegister_WithDevelopmentEnvironment
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:51Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:51Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:51Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:51Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:51Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:51Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
--- PASS: TestRegister_WithDevelopmentEnvironment (0.48s)
=== RUN TestRegister_WithProductionEnvironment
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:51Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:51Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:51Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:51Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:51Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:51Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
--- PASS: TestRegister_WithProductionEnvironment (0.31s)
=== RUN TestRegister_AutoMigrateFailure
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: disk sync complete" count=0
2026/01/10 02:16:51 /projects/Charon/backend/internal/api/routes/routes.go:42 sql: database is closed
[0.005ms] [rows:0] CREATE TABLE `ssl_certificates` (`id` integer PRIMARY KEY AUTOINCREMENT,`uuid` text,`name` text,`provider` text,`domains` text,`certificate` text,`private_key` text,`expires_at` datetime,`auto_renew` numeric DEFAULT false,`created_at` datetime,`updated_at` datetime)
--- PASS: TestRegister_AutoMigrateFailure (0.04s)
=== RUN TestRegisterImportHandler
--- PASS: TestRegisterImportHandler (0.00s)
=== RUN TestRegister_RoutesRegistration
time="2026-01-10T02:16:52Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:52Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:52Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:52Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:52Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:52Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestRegister_RoutesRegistration (0.27s)
=== RUN TestRegister_ProxyHostsRequireAuth
time="2026-01-10T02:16:52Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:52Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:52Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:52Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:52Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:52Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
2026/01/10 02:16:52 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.099ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:52 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.062ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestRegister_ProxyHostsRequireAuth (0.17s)
=== RUN TestRegister_DNSProviders_NotRegisteredWhenEncryptionKeyMissing
time="2026-01-10T02:16:52Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:52Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:52Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:52Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:52Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:52Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
--- PASS: TestRegister_DNSProviders_NotRegisteredWhenEncryptionKeyMissing (0.15s)
=== RUN TestRegister_DNSProviders_NotRegisteredWhenEncryptionKeyInvalid
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:52Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:52Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:52Z" level=error msg="Failed to initialize encryption service - DNS provider features will be unavailable" error="invalid base64 key: illegal base64 data at input byte 3"
time="2026-01-10T02:16:52Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:52Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:52Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
--- PASS: TestRegister_DNSProviders_NotRegisteredWhenEncryptionKeyInvalid (0.18s)
=== RUN TestRegister_DNSProviders_RegisteredWhenEncryptionKeyValid
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:52Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:52Z" level=info msg="Backup service cron scheduler started"
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
time="2026-01-10T02:16:52Z" level=warning msg="Failed to initialize rotation service - key rotation features will be unavailable" error="CHARON_ENCRYPTION_KEY is required"
time="2026-01-10T02:16:52Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:52Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:52Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
--- PASS: TestRegister_DNSProviders_RegisteredWhenEncryptionKeyValid (0.19s)
=== RUN TestRegister_AllRoutesRegistered
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:52Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:53Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:53Z" level=info msg="Backup service cron scheduler started"
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
time="2026-01-10T02:16:53Z" level=warning msg="Failed to initialize rotation service - key rotation features will be unavailable" error="CHARON_ENCRYPTION_KEY is required"
time="2026-01-10T02:16:53Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:53Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:53Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestRegister_AllRoutesRegistered (0.17s)
=== RUN TestRegister_MiddlewareApplied
time="2026-01-10T02:16:53Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:53Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:53Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:53Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:53Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:53Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestRegister_MiddlewareApplied (0.18s)
=== RUN TestRegister_AuthenticatedRoutes
time="2026-01-10T02:16:53Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:53Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:53Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:53Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:53Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:53Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
=== RUN TestRegister_AuthenticatedRoutes/GET_/api/v1/backups
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.172ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.086ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
=== RUN TestRegister_AuthenticatedRoutes/POST_/api/v1/backups
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.269ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.094ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
=== RUN TestRegister_AuthenticatedRoutes/GET_/api/v1/logs
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.110ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: disk sync complete" count=0
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.531ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
=== RUN TestRegister_AuthenticatedRoutes/GET_/api/v1/settings
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.170ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.098ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
=== RUN TestRegister_AuthenticatedRoutes/GET_/api/v1/notifications
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.137ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.080ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
=== RUN TestRegister_AuthenticatedRoutes/GET_/api/v1/users
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.089ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.059ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
=== RUN TestRegister_AuthenticatedRoutes/GET_/api/v1/auth/me
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.094ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.076ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
=== RUN TestRegister_AuthenticatedRoutes/POST_/api/v1/auth/logout
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.086ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.067ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
=== RUN TestRegister_AuthenticatedRoutes/GET_/api/v1/uptime/monitors
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.104ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.062ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestRegister_AuthenticatedRoutes (0.20s)
--- PASS: TestRegister_AuthenticatedRoutes/GET_/api/v1/backups (0.00s)
--- PASS: TestRegister_AuthenticatedRoutes/POST_/api/v1/backups (0.00s)
--- PASS: TestRegister_AuthenticatedRoutes/GET_/api/v1/logs (0.00s)
--- PASS: TestRegister_AuthenticatedRoutes/GET_/api/v1/settings (0.00s)
--- PASS: TestRegister_AuthenticatedRoutes/GET_/api/v1/notifications (0.00s)
--- PASS: TestRegister_AuthenticatedRoutes/GET_/api/v1/users (0.00s)
--- PASS: TestRegister_AuthenticatedRoutes/GET_/api/v1/auth/me (0.00s)
--- PASS: TestRegister_AuthenticatedRoutes/POST_/api/v1/auth/logout (0.00s)
--- PASS: TestRegister_AuthenticatedRoutes/GET_/api/v1/uptime/monitors (0.00s)
=== RUN TestRegister_AdminRoutes
time="2026-01-10T02:16:53Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:53Z" level=info msg="Backup service cron scheduler started"
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
time="2026-01-10T02:16:53Z" level=warning msg="Failed to initialize rotation service - key rotation features will be unavailable" error="CHARON_ENCRYPTION_KEY is required"
time="2026-01-10T02:16:53Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:53Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:53Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.190ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.096ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.086ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: disk sync complete" count=0
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.120ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestRegister_AdminRoutes (0.17s)
=== RUN TestRegister_PublicRoutes
time="2026-01-10T02:16:53Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:53Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:53Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:53Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:53Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:53Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
=== RUN TestRegister_PublicRoutes/GET_/api/v1/health
=== RUN TestRegister_PublicRoutes/GET_/metrics
=== RUN TestRegister_PublicRoutes/GET_/api/v1/setup
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.312ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.098ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
=== RUN TestRegister_PublicRoutes/GET_/api/v1/auth/status
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.188ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
2026/01/10 02:16:53 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.359ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestRegister_PublicRoutes (0.20s)
--- PASS: TestRegister_PublicRoutes/GET_/api/v1/health (0.00s)
--- PASS: TestRegister_PublicRoutes/GET_/metrics (0.00s)
--- PASS: TestRegister_PublicRoutes/GET_/api/v1/setup (0.00s)
--- PASS: TestRegister_PublicRoutes/GET_/api/v1/auth/status (0.00s)
=== RUN TestRegister_HealthEndpoint
time="2026-01-10T02:16:53Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:54Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:54Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:54Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:54Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:54Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:54Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
--- PASS: TestRegister_HealthEndpoint (0.21s)
=== RUN TestRegister_MetricsEndpoint
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:54Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:54Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:54Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:54Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:54Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:54Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestRegister_MetricsEndpoint (0.19s)
=== RUN TestRegister_DBHealthEndpoint
time="2026-01-10T02:16:54Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:54Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:54Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:54Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:54Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:54Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestRegister_DBHealthEndpoint (0.18s)
=== RUN TestRegister_LoginEndpoint
time="2026-01-10T02:16:54Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:54Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:54Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:54Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:54Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:54Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
2026/01/10 02:16:54 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.237ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: disk sync complete" count=0
2026/01/10 02:16:54 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.640ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestRegister_LoginEndpoint (0.21s)
=== RUN TestRegister_SetupEndpoint
time="2026-01-10T02:16:54Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:54Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:54Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:54Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:54Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:54Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
2026/01/10 02:16:54 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.124ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:54 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.149ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestRegister_SetupEndpoint (0.22s)
time="2026-01-10T02:16:54Z" level=info msg="CertificateService: disk sync complete" count=0
=== RUN TestRegister_WithEncryptionRoutes
time="2026-01-10T02:16:55Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:55Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:55Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:55Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:55Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
--- PASS: TestRegister_WithEncryptionRoutes (0.21s)
=== RUN TestRegister_UptimeCheckEndpoint
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:55Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:55Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:55Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:55Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:55Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:55Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
2026/01/10 02:16:55 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.092ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:55 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.494ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestRegister_UptimeCheckEndpoint (0.17s)
=== RUN TestRegister_CrowdSecRoutes
time="2026-01-10T02:16:55Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:55Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:55Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:55Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:55Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:55Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
--- PASS: TestRegister_CrowdSecRoutes (0.19s)
=== RUN TestRegister_SecurityRoutes
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:55Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:55Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:55Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:55Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:55Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:55Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
--- PASS: TestRegister_SecurityRoutes (0.18s)
=== RUN TestRegister_AccessListRoutes
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:55Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:55Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:55Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:55Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:55Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:55Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
--- PASS: TestRegister_AccessListRoutes (0.17s)
=== RUN TestRegister_CertificateRoutes
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:55Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:55Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:55Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:55Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:55Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:55Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
--- PASS: TestRegister_CertificateRoutes (0.17s)
=== RUN TestRegister_NilHandlers
time="2026-01-10T02:16:55Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:56Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:56Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:56Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:56Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:56Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:56Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestRegister_NilHandlers (0.20s)
=== RUN TestRegister_MiddlewareOrder
time="2026-01-10T02:16:56Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:56Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:56Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:56Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:56Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:56Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
--- PASS: TestRegister_MiddlewareOrder (0.17s)
=== RUN TestRegister_GzipCompression
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:56Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:56Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:56Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:56Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:56Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:56Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestRegister_GzipCompression (0.20s)
=== RUN TestRegister_CerberusMiddleware
time="2026-01-10T02:16:56Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:56Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:56Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:56Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:56Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:56Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
--- PASS: TestRegister_CerberusMiddleware (0.17s)
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
=== RUN TestRegister_FeatureFlagsEndpoint
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:56Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:56Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:56Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:56Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:56Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:56Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
2026/01/10 02:16:56 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.094ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:56 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.074ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestRegister_FeatureFlagsEndpoint (0.23s)
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:56Z" level=info msg="CertificateService: disk sync complete" count=0
=== RUN TestRegister_WebSocketRoutes
time="2026-01-10T02:16:57Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:57Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:57Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:57Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:57Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:57Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
--- PASS: TestRegister_WebSocketRoutes (0.19s)
=== RUN TestRegister_NotificationRoutes
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:57Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:57Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:57Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:57Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:57Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:57Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
--- PASS: TestRegister_NotificationRoutes (0.18s)
=== RUN TestRegister_DomainRoutes
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:57Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:57Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:57Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:57Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:57Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:57Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestRegister_DomainRoutes (0.20s)
=== RUN TestRegister_VerifyAuthEndpoint
time="2026-01-10T02:16:57Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:57Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:57Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:57Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:57Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:57Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
2026/01/10 02:16:57 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.165ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:57 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.115ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestRegister_VerifyAuthEndpoint (0.21s)
=== RUN TestRegister_SMTPRoutes
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:57Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:57Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:57Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:57Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:57Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:57Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
--- PASS: TestRegister_SMTPRoutes (0.23s)
=== RUN TestRegisterImportHandler_RoutesExist
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:57Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestRegisterImportHandler_RoutesExist (0.00s)
=== RUN TestRegister_EncryptionRoutesWithValidKey
time="2026-01-10T02:16:58Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:58Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:58Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:58Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:58Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:58Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:58Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:58Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestRegister_EncryptionRoutesWithValidKey (0.26s)
=== RUN TestRegister_WAFExclusionRoutes
time="2026-01-10T02:16:58Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:58Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:58Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:58Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:58Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:58Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
--- PASS: TestRegister_WAFExclusionRoutes (0.18s)
=== RUN TestRegister_BreakGlassRoute
time="2026-01-10T02:16:58Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:58Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:58Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:58Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:58Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:58Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:58Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:58Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:58Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:58Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:58Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:58Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestRegister_BreakGlassRoute (0.20s)
=== RUN TestRegister_RateLimitPresetsRoute
time="2026-01-10T02:16:58Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:58Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:58Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:58Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:58Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:58Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=/data
time="2026-01-10T02:16:58Z" level=info msg="CertificateService: scanning cert directory" certRoot=/data/certificates
time="2026-01-10T02:16:58Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/data/certificates
time="2026-01-10T02:16:58Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestRegister_RateLimitPresetsRoute (0.16s)
=== RUN TestRegisterImportHandler
--- PASS: TestRegisterImportHandler (0.02s)
PASS
coverage: 87.1% of statements
ok github.com/Wikid82/charon/backend/internal/api/routes (cached) coverage: 87.1% of statements
=== RUN TestIntegration_WAF_BlockAndMonitor
time="2026-01-10T02:16:51Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:51Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:51Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
2026/01/10 02:16:51 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.091ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-basic" ORDER BY `security_header_profiles`.`id` LIMIT 1
2026/01/10 02:16:51 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.134ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-api-friendly" ORDER BY `security_header_profiles`.`id` LIMIT 1
2026/01/10 02:16:51 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.127ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-strict" ORDER BY `security_header_profiles`.`id` LIMIT 1
2026/01/10 02:16:51 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.094ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-paranoid" ORDER BY `security_header_profiles`.`id` LIMIT 1
time="2026-01-10T02:16:51Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:51Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:51Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=data/caddy/data
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: scanning cert directory" certRoot=data/caddy/data/certificates
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: cert directory does not exist" certRoot=data/caddy/data/certificates
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: disk sync complete" count=0
time="2026-01-10T02:16:51Z" level=info msg="Cleaning up invalid Let's Encrypt certificate associations..."
time="2026-01-10T02:16:51Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:16:51Z" level=warning msg="CHARON_ENCRYPTION_KEY not set - DNS provider and plugin features will be unavailable"
time="2026-01-10T02:16:51Z" level=info msg="GeoIP database not found - geo-blocking features will be unavailable" path=/app/data/geoip/GeoLite2-Country.mmdb
time="2026-01-10T02:16:51Z" level=info msg="LogWatcher started" path=/var/log/caddy/access.log
time="2026-01-10T02:16:51Z" level=info msg="Using Caddy data directory for certificates scan" caddy_data_dir=data/caddy/data
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: scanning cert directory" certRoot=data/caddy/data/certificates
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: cert directory does not exist" certRoot=data/caddy/data/certificates
time="2026-01-10T02:16:51Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestIntegration_WAF_BlockAndMonitor (0.55s)
=== RUN TestInviteToken_MustBeUnguessable
--- PASS: TestInviteToken_MustBeUnguessable (1.00s)
=== RUN TestInviteToken_ExpiredCannotBeUsed
--- PASS: TestInviteToken_ExpiredCannotBeUsed (0.84s)
=== RUN TestInviteToken_CannotBeReused
--- PASS: TestInviteToken_CannotBeReused (1.67s)
=== RUN TestInviteUser_EmailValidation
=== RUN TestInviteUser_EmailValidation/empty_email
=== RUN TestInviteUser_EmailValidation/invalid_email_no_@
=== RUN TestInviteUser_EmailValidation/invalid_email_no_domain
=== RUN TestInviteUser_EmailValidation/sql_injection_attempt
=== RUN TestInviteUser_EmailValidation/script_injection
=== RUN TestInviteUser_EmailValidation/valid_email
--- PASS: TestInviteUser_EmailValidation (0.83s)
--- PASS: TestInviteUser_EmailValidation/empty_email (0.00s)
--- PASS: TestInviteUser_EmailValidation/invalid_email_no_@ (0.00s)
--- PASS: TestInviteUser_EmailValidation/invalid_email_no_domain (0.00s)
--- PASS: TestInviteUser_EmailValidation/sql_injection_attempt (0.00s)
--- PASS: TestInviteUser_EmailValidation/script_injection (0.00s)
--- PASS: TestInviteUser_EmailValidation/valid_email (0.00s)
=== RUN TestAcceptInvite_PasswordValidation
=== RUN TestAcceptInvite_PasswordValidation/empty_password
=== RUN TestAcceptInvite_PasswordValidation/too_short
=== RUN TestAcceptInvite_PasswordValidation/7_chars
=== RUN TestAcceptInvite_PasswordValidation/8_chars_valid
--- PASS: TestAcceptInvite_PasswordValidation (1.71s)
--- PASS: TestAcceptInvite_PasswordValidation/empty_password (0.00s)
--- PASS: TestAcceptInvite_PasswordValidation/too_short (0.00s)
--- PASS: TestAcceptInvite_PasswordValidation/7_chars (0.00s)
--- PASS: TestAcceptInvite_PasswordValidation/8_chars_valid (0.85s)
=== RUN TestUserEndpoints_RequireAdmin
=== RUN TestUserEndpoints_RequireAdmin/GET_/api/users
=== RUN TestUserEndpoints_RequireAdmin/POST_/api/users
=== RUN TestUserEndpoints_RequireAdmin/POST_/api/users/invite
=== RUN TestUserEndpoints_RequireAdmin/GET_/api/users/1
=== RUN TestUserEndpoints_RequireAdmin/PUT_/api/users/1
=== RUN TestUserEndpoints_RequireAdmin/DELETE_/api/users/1
=== RUN TestUserEndpoints_RequireAdmin/PUT_/api/users/1/permissions
--- PASS: TestUserEndpoints_RequireAdmin (0.91s)
--- PASS: TestUserEndpoints_RequireAdmin/GET_/api/users (0.00s)
--- PASS: TestUserEndpoints_RequireAdmin/POST_/api/users (0.00s)
--- PASS: TestUserEndpoints_RequireAdmin/POST_/api/users/invite (0.00s)
--- PASS: TestUserEndpoints_RequireAdmin/GET_/api/users/1 (0.00s)
--- PASS: TestUserEndpoints_RequireAdmin/PUT_/api/users/1 (0.00s)
--- PASS: TestUserEndpoints_RequireAdmin/DELETE_/api/users/1 (0.00s)
--- PASS: TestUserEndpoints_RequireAdmin/PUT_/api/users/1/permissions (0.00s)
=== RUN TestSMTPEndpoints_RequireAdmin
=== RUN TestSMTPEndpoints_RequireAdmin/POST_/api/settings/smtp
=== RUN TestSMTPEndpoints_RequireAdmin/POST_/api/settings/smtp/test
=== RUN TestSMTPEndpoints_RequireAdmin/POST_/api/settings/smtp/test-email
--- PASS: TestSMTPEndpoints_RequireAdmin (0.82s)
--- PASS: TestSMTPEndpoints_RequireAdmin/POST_/api/settings/smtp (0.00s)
--- PASS: TestSMTPEndpoints_RequireAdmin/POST_/api/settings/smtp/test (0.00s)
--- PASS: TestSMTPEndpoints_RequireAdmin/POST_/api/settings/smtp/test-email (0.00s)
=== RUN TestSMTPConfig_PasswordMasked
--- PASS: TestSMTPConfig_PasswordMasked (0.78s)
=== RUN TestSMTPConfig_PortValidation
=== RUN TestSMTPConfig_PortValidation/port_0_invalid
=== RUN TestSMTPConfig_PortValidation/port_-1_invalid
=== RUN TestSMTPConfig_PortValidation/port_65536_invalid
=== RUN TestSMTPConfig_PortValidation/port_587_valid
=== RUN TestSMTPConfig_PortValidation/port_465_valid
=== RUN TestSMTPConfig_PortValidation/port_25_valid
--- PASS: TestSMTPConfig_PortValidation (0.99s)
--- PASS: TestSMTPConfig_PortValidation/port_0_invalid (0.00s)
--- PASS: TestSMTPConfig_PortValidation/port_-1_invalid (0.00s)
--- PASS: TestSMTPConfig_PortValidation/port_65536_invalid (0.00s)
--- PASS: TestSMTPConfig_PortValidation/port_587_valid (0.01s)
--- PASS: TestSMTPConfig_PortValidation/port_465_valid (0.00s)
--- PASS: TestSMTPConfig_PortValidation/port_25_valid (0.00s)
=== RUN TestSMTPConfig_EncryptionValidation
=== RUN TestSMTPConfig_EncryptionValidation/empty_encryption_invalid
=== RUN TestSMTPConfig_EncryptionValidation/invalid_encryption
=== RUN TestSMTPConfig_EncryptionValidation/tls_lowercase_valid
=== RUN TestSMTPConfig_EncryptionValidation/starttls_valid
=== RUN TestSMTPConfig_EncryptionValidation/none_valid
--- PASS: TestSMTPConfig_EncryptionValidation (2.40s)
--- PASS: TestSMTPConfig_EncryptionValidation/empty_encryption_invalid (0.00s)
--- PASS: TestSMTPConfig_EncryptionValidation/invalid_encryption (0.00s)
--- PASS: TestSMTPConfig_EncryptionValidation/tls_lowercase_valid (0.00s)
--- PASS: TestSMTPConfig_EncryptionValidation/starttls_valid (0.00s)
--- PASS: TestSMTPConfig_EncryptionValidation/none_valid (0.00s)
=== RUN TestInviteUser_DuplicateEmailBlocked
--- PASS: TestInviteUser_DuplicateEmailBlocked (0.93s)
=== RUN TestInviteUser_EmailCaseInsensitive
--- PASS: TestInviteUser_EmailCaseInsensitive (0.82s)
=== RUN TestDeleteUser_CannotDeleteSelf
--- PASS: TestDeleteUser_CannotDeleteSelf (0.83s)
=== RUN TestUpdatePermissions_ValidModes
=== RUN TestUpdatePermissions_ValidModes/allow_all_valid
=== RUN TestUpdatePermissions_ValidModes/deny_all_valid
=== RUN TestUpdatePermissions_ValidModes/invalid_mode
=== RUN TestUpdatePermissions_ValidModes/empty_mode
--- PASS: TestUpdatePermissions_ValidModes (0.85s)
--- PASS: TestUpdatePermissions_ValidModes/allow_all_valid (0.00s)
--- PASS: TestUpdatePermissions_ValidModes/deny_all_valid (0.00s)
--- PASS: TestUpdatePermissions_ValidModes/invalid_mode (0.00s)
--- PASS: TestUpdatePermissions_ValidModes/empty_mode (0.00s)
=== RUN TestPublicEndpoints_NoAuthRequired
--- PASS: TestPublicEndpoints_NoAuthRequired (0.81s)
PASS
coverage: [no statements]
ok github.com/Wikid82/charon/backend/internal/api/tests (cached) coverage: [no statements]
=== RUN TestClient_Load_Success
--- PASS: TestClient_Load_Success (0.01s)
=== RUN TestClient_Load_Failure
--- PASS: TestClient_Load_Failure (0.01s)
=== RUN TestClient_GetConfig_Success
--- PASS: TestClient_GetConfig_Success (0.00s)
=== RUN TestClient_Ping_Success
--- PASS: TestClient_Ping_Success (0.00s)
=== RUN TestClient_Ping_Unreachable
--- PASS: TestClient_Ping_Unreachable (0.00s)
=== RUN TestClient_Load_CreateRequestFailure
--- PASS: TestClient_Load_CreateRequestFailure (0.00s)
=== RUN TestClient_Ping_CreateRequestFailure
--- PASS: TestClient_Ping_CreateRequestFailure (0.00s)
=== RUN TestClient_GetConfig_Failure
--- PASS: TestClient_GetConfig_Failure (0.00s)
=== RUN TestClient_GetConfig_InvalidJSON
--- PASS: TestClient_GetConfig_InvalidJSON (0.00s)
=== RUN TestClient_Ping_Failure
--- PASS: TestClient_Ping_Failure (0.00s)
=== RUN TestClient_RequestCreationErrors
--- PASS: TestClient_RequestCreationErrors (0.00s)
=== RUN TestClient_NetworkErrors
--- PASS: TestClient_NetworkErrors (0.00s)
=== RUN TestClient_Load_MarshalFailure
--- PASS: TestClient_Load_MarshalFailure (0.00s)
=== RUN TestClient_Ping_TransportError
--- PASS: TestClient_Ping_TransportError (0.00s)
=== RUN TestClient_GetConfig_BaseURLNil_ReturnsError
--- PASS: TestClient_GetConfig_BaseURLNil_ReturnsError (0.00s)
=== RUN TestClient_RequestCreationErrors_FromInvalidResolvedURL
--- PASS: TestClient_RequestCreationErrors_FromInvalidResolvedURL (0.00s)
=== RUN TestBuildACLHandler_GeoBlacklist
--- PASS: TestBuildACLHandler_GeoBlacklist (0.00s)
=== RUN TestBuildACLHandler_UnknownTypeReturnsNil
--- PASS: TestBuildACLHandler_UnknownTypeReturnsNil (0.00s)
=== RUN TestBuildACLHandler_GeoWhitelist
--- PASS: TestBuildACLHandler_GeoWhitelist (0.00s)
=== RUN TestBuildACLHandler_LocalNetwork
--- PASS: TestBuildACLHandler_LocalNetwork (0.00s)
=== RUN TestBuildACLHandler_IPRules
--- PASS: TestBuildACLHandler_IPRules (0.00s)
=== RUN TestBuildACLHandler_InvalidIPJSON
--- PASS: TestBuildACLHandler_InvalidIPJSON (0.00s)
=== RUN TestBuildACLHandler_NoIPRulesReturnsNil
--- PASS: TestBuildACLHandler_NoIPRulesReturnsNil (0.00s)
=== RUN TestBuildACLHandler_Whitelist
--- PASS: TestBuildACLHandler_Whitelist (0.00s)
=== RUN TestBuildCrowdSecHandler_Disabled
--- PASS: TestBuildCrowdSecHandler_Disabled (0.00s)
=== RUN TestBuildCrowdSecHandler_EnabledWithoutConfig
--- PASS: TestBuildCrowdSecHandler_EnabledWithoutConfig (0.00s)
=== RUN TestBuildCrowdSecHandler_EnabledWithEmptyAPIURL
--- PASS: TestBuildCrowdSecHandler_EnabledWithEmptyAPIURL (0.00s)
=== RUN TestBuildCrowdSecHandler_EnabledWithCustomAPIURL
--- PASS: TestBuildCrowdSecHandler_EnabledWithCustomAPIURL (0.00s)
=== RUN TestBuildCrowdSecHandler_JSONFormat
--- PASS: TestBuildCrowdSecHandler_JSONFormat (0.00s)
=== RUN TestBuildCrowdSecHandler_WithHost
--- PASS: TestBuildCrowdSecHandler_WithHost (0.00s)
=== RUN TestGenerateConfig_WithCrowdSec
--- PASS: TestGenerateConfig_WithCrowdSec (0.00s)
=== RUN TestGenerateConfig_CrowdSecDisabled
--- PASS: TestGenerateConfig_CrowdSecDisabled (0.00s)
=== RUN TestGenerateConfig_CatchAllFrontend
--- PASS: TestGenerateConfig_CatchAllFrontend (0.00s)
=== RUN TestGenerateConfig_AdvancedInvalidJSON
time="2026-01-10T02:16:57Z" level=warning msg="Failed to parse advanced_config for host" error="invalid character 'i' looking for beginning of object key string" host=adv1
--- PASS: TestGenerateConfig_AdvancedInvalidJSON (0.00s)
=== RUN TestGenerateConfig_AdvancedArrayHandler
--- PASS: TestGenerateConfig_AdvancedArrayHandler (0.00s)
=== RUN TestGenerateConfig_LowercaseDomains
--- PASS: TestGenerateConfig_LowercaseDomains (0.00s)
=== RUN TestGenerateConfig_AdvancedObjectHandler
--- PASS: TestGenerateConfig_AdvancedObjectHandler (0.00s)
=== RUN TestGenerateConfig_AdvancedHeadersStringToArray
--- PASS: TestGenerateConfig_AdvancedHeadersStringToArray (0.00s)
=== RUN TestGenerateConfig_ACLWhitelistIncluded
--- PASS: TestGenerateConfig_ACLWhitelistIncluded (0.00s)
=== RUN TestGenerateConfig_SkipsEmptyDomainEntries
--- PASS: TestGenerateConfig_SkipsEmptyDomainEntries (0.00s)
=== RUN TestGenerateConfig_AdvancedNoHandlerKey
time="2026-01-10T02:16:57Z" level=warning msg="advanced_config for host is not a handler object" host=adv3
--- PASS: TestGenerateConfig_AdvancedNoHandlerKey (0.00s)
=== RUN TestGenerateConfig_AdvancedUnexpectedJSONStructure
time="2026-01-10T02:16:57Z" level=warning msg="advanced_config for host has unexpected JSON structure" host=adv4
--- PASS: TestGenerateConfig_AdvancedUnexpectedJSONStructure (0.00s)
=== RUN TestBuildACLHandler_UnknownIPTypeReturnsNil
--- PASS: TestBuildACLHandler_UnknownIPTypeReturnsNil (0.00s)
=== RUN TestGenerateConfig_SecurityPipeline_Order
--- PASS: TestGenerateConfig_SecurityPipeline_Order (0.00s)
=== RUN TestGenerateConfig_SecurityPipeline_OmitWhenDisabled
--- PASS: TestGenerateConfig_SecurityPipeline_OmitWhenDisabled (0.00s)
=== RUN TestGetAccessLogPath
=== RUN TestGetAccessLogPath/CrowdSecEnabled_UsesStandardPath
=== RUN TestGetAccessLogPath/Production_UsesStandardPath
=== RUN TestGetAccessLogPath/Development_UsesRelativePath
=== RUN TestGetAccessLogPath/NoEnv_CrowdSecEnabled_UsesStandardPath
--- PASS: TestGetAccessLogPath (0.00s)
--- PASS: TestGetAccessLogPath/CrowdSecEnabled_UsesStandardPath (0.00s)
--- PASS: TestGetAccessLogPath/Production_UsesStandardPath (0.00s)
--- PASS: TestGetAccessLogPath/Development_UsesRelativePath (0.00s)
--- PASS: TestGetAccessLogPath/NoEnv_CrowdSecEnabled_UsesStandardPath (0.00s)
=== RUN TestGenerateConfig_LoggingConfigured
--- PASS: TestGenerateConfig_LoggingConfigured (0.00s)
=== RUN TestGenerateConfig_ZerosslAndBothProviders
--- PASS: TestGenerateConfig_ZerosslAndBothProviders (0.00s)
=== RUN TestGenerateConfig_SecurityPipeline_Order_Locations
--- PASS: TestGenerateConfig_SecurityPipeline_Order_Locations (0.00s)
=== RUN TestGenerateConfig_ACLLogWarning
--- PASS: TestGenerateConfig_ACLLogWarning (0.00s)
=== RUN TestGenerateConfig_ACLHandlerIncluded
--- PASS: TestGenerateConfig_ACLHandlerIncluded (0.00s)
=== RUN TestGenerateConfig_DecisionsBlockWithAdminExclusion
config_generate_additional_test.go:147: handles: [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"body": "Access denied: Blocked by security decision",
"handler": "static_response",
"status_code": 403
}
],
"match": [
{
"remote_ip": {
"ranges": [
"1.2.3.4"
]
}
},
{
"not": [
{
"remote_ip": {
"ranges": [
"10.0.0.1/32"
]
}
}
]
}
],
"terminal": true
}
]
},
{
"flush_interval": -1,
"handler": "reverse_proxy",
"headers": {
"request": {
"set": {
"X-Forwarded-Host": [
"{http.request.host}"
],
"X-Forwarded-Port": [
"{http.request.port}"
],
"X-Forwarded-Proto": [
"{http.request.scheme}"
],
"X-Real-IP": [
"{http.request.remote.host}"
]
}
}
},
"upstreams": [
{
"dial": "app:8080"
}
]
}
]
--- PASS: TestGenerateConfig_DecisionsBlockWithAdminExclusion (0.00s)
=== RUN TestGenerateConfig_WAFModeAndRulesetReference
--- PASS: TestGenerateConfig_WAFModeAndRulesetReference (0.00s)
=== RUN TestGenerateConfig_WAFModeDisabledSkipsHandler
--- PASS: TestGenerateConfig_WAFModeDisabledSkipsHandler (0.00s)
=== RUN TestGenerateConfig_WAFSelectedSetsContentAndMode
--- PASS: TestGenerateConfig_WAFSelectedSetsContentAndMode (0.00s)
=== RUN TestGenerateConfig_DecisionAdminPartsEmpty
--- PASS: TestGenerateConfig_DecisionAdminPartsEmpty (0.00s)
=== RUN TestNormalizeHeaderOps_PreserveStringArray
--- PASS: TestNormalizeHeaderOps_PreserveStringArray (0.00s)
=== RUN TestGenerateConfig_WAFUsesRuleSet
--- PASS: TestGenerateConfig_WAFUsesRuleSet (0.00s)
=== RUN TestGenerateConfig_WAFUsesRuleSetFromAdvancedConfig
--- PASS: TestGenerateConfig_WAFUsesRuleSetFromAdvancedConfig (0.00s)
=== RUN TestGenerateConfig_WAFUsesRuleSetFromAdvancedConfig_Array
--- PASS: TestGenerateConfig_WAFUsesRuleSetFromAdvancedConfig_Array (0.00s)
=== RUN TestGenerateConfig_WAFUsesRulesetFromSecCfgFallback
--- PASS: TestGenerateConfig_WAFUsesRulesetFromSecCfgFallback (0.00s)
=== RUN TestGenerateConfig_RateLimitFromSecCfg
--- PASS: TestGenerateConfig_RateLimitFromSecCfg (0.00s)
=== RUN TestGenerateConfig_CrowdSecHandlerFromSecCfg
--- PASS: TestGenerateConfig_CrowdSecHandlerFromSecCfg (0.00s)
=== RUN TestGenerateConfig_EmptyHostsAndNoFrontend
--- PASS: TestGenerateConfig_EmptyHostsAndNoFrontend (0.00s)
=== RUN TestGenerateConfig_SkipsInvalidCustomCert
--- PASS: TestGenerateConfig_SkipsInvalidCustomCert (0.00s)
=== RUN TestGenerateConfig_SkipsDuplicateDomains
--- PASS: TestGenerateConfig_SkipsDuplicateDomains (0.00s)
=== RUN TestGenerateConfig_LoadPEMSetsTLSWhenNoACME
--- PASS: TestGenerateConfig_LoadPEMSetsTLSWhenNoACME (0.00s)
=== RUN TestGenerateConfig_DefaultAcmeStaging
--- PASS: TestGenerateConfig_DefaultAcmeStaging (0.00s)
=== RUN TestGenerateConfig_ACLHandlerBuildError
--- PASS: TestGenerateConfig_ACLHandlerBuildError (0.00s)
=== RUN TestGenerateConfig_SkipHostDomainEmptyAndDisabled
--- PASS: TestGenerateConfig_SkipHostDomainEmptyAndDisabled (0.00s)
=== RUN TestGenerateConfig_CustomCertsAndTLS
--- PASS: TestGenerateConfig_CustomCertsAndTLS (0.00s)
=== RUN TestGenerateConfig_DNSChallenge_LetsEncrypt_StagingCAAndPropagationTimeout
--- PASS: TestGenerateConfig_DNSChallenge_LetsEncrypt_StagingCAAndPropagationTimeout (0.00s)
=== RUN TestGenerateConfig_DNSChallenge_ZeroSSL_IssuerShape
--- PASS: TestGenerateConfig_DNSChallenge_ZeroSSL_IssuerShape (0.00s)
=== RUN TestGenerateConfig_DNSChallenge_SkipsPolicyWhenProviderConfigMissing
--- PASS: TestGenerateConfig_DNSChallenge_SkipsPolicyWhenProviderConfigMissing (0.00s)
=== RUN TestGenerateConfig_HTTPChallenge_ExcludesIPDomains
--- PASS: TestGenerateConfig_HTTPChallenge_ExcludesIPDomains (0.00s)
=== RUN TestGetCrowdSecAPIKey_EnvPriority
--- PASS: TestGetCrowdSecAPIKey_EnvPriority (0.00s)
=== RUN TestHasWildcard_TrueFalse
--- PASS: TestHasWildcard_TrueFalse (0.00s)
=== RUN TestGenerateConfig_MultiCredential_ZoneSpecificPolicies
--- PASS: TestGenerateConfig_MultiCredential_ZoneSpecificPolicies (0.00s)
=== RUN TestGenerateConfig_MultiCredential_ZeroSSL_Issuer
--- PASS: TestGenerateConfig_MultiCredential_ZeroSSL_Issuer (0.00s)
=== RUN TestGenerateConfig_MultiCredential_BothIssuers
--- PASS: TestGenerateConfig_MultiCredential_BothIssuers (0.00s)
=== RUN TestGenerateConfig_MultiCredential_ACMEStaging
--- PASS: TestGenerateConfig_MultiCredential_ACMEStaging (0.00s)
=== RUN TestGenerateConfig_MultiCredential_NoMatchingDomains
--- PASS: TestGenerateConfig_MultiCredential_NoMatchingDomains (0.00s)
=== RUN TestGenerateConfig_MultiCredential_ProviderTypeNotFound
--- PASS: TestGenerateConfig_MultiCredential_ProviderTypeNotFound (0.00s)
=== RUN TestGenerateConfig_MultiCredential_SupportsMultiCredential_UsesZoneConfigAndStagingBothIssuers
--- PASS: TestGenerateConfig_MultiCredential_SupportsMultiCredential_UsesZoneConfigAndStagingBothIssuers (0.00s)
=== RUN TestGenerateConfig_DNSChallenge_SingleCredential_BothIssuers_ACMEStaging
--- PASS: TestGenerateConfig_DNSChallenge_SingleCredential_BothIssuers_ACMEStaging (0.00s)
=== RUN TestGenerateConfig_DNSChallenge_SingleCredential_ProviderTypeNotFound_SkipsPolicy
--- PASS: TestGenerateConfig_DNSChallenge_SingleCredential_ProviderTypeNotFound_SkipsPolicy (0.00s)
=== RUN TestGenerateConfig_DefaultPolicy_LetsEncrypt_StagingCA
--- PASS: TestGenerateConfig_DefaultPolicy_LetsEncrypt_StagingCA (0.00s)
=== RUN TestGenerateConfig_DefaultPolicy_ZeroSSL_Issuer
--- PASS: TestGenerateConfig_DefaultPolicy_ZeroSSL_Issuer (0.00s)
=== RUN TestGenerateConfig_DefaultPolicy_BothIssuers_StagingCA
--- PASS: TestGenerateConfig_DefaultPolicy_BothIssuers_StagingCA (0.00s)
=== RUN TestGenerateConfig_IPSubjects_InitializesTLSAppAndAutomation
--- PASS: TestGenerateConfig_IPSubjects_InitializesTLSAppAndAutomation (0.00s)
=== RUN TestGetAccessLogPath_DockerEnv_UsesCrowdSecPath
--- PASS: TestGetAccessLogPath_DockerEnv_UsesCrowdSecPath (0.00s)
=== RUN TestBuildSecurityHeadersHandler_AllEnabled
--- PASS: TestBuildSecurityHeadersHandler_AllEnabled (0.00s)
=== RUN TestBuildSecurityHeadersHandler_HSTSOnly
--- PASS: TestBuildSecurityHeadersHandler_HSTSOnly (0.00s)
=== RUN TestBuildSecurityHeadersHandler_CSPOnly
--- PASS: TestBuildSecurityHeadersHandler_CSPOnly (0.00s)
=== RUN TestBuildSecurityHeadersHandler_CSPReportOnly
--- PASS: TestBuildSecurityHeadersHandler_CSPReportOnly (0.00s)
=== RUN TestBuildSecurityHeadersHandler_NoProfile
--- PASS: TestBuildSecurityHeadersHandler_NoProfile (0.00s)
=== RUN TestBuildSecurityHeadersHandler_Disabled
--- PASS: TestBuildSecurityHeadersHandler_Disabled (0.00s)
=== RUN TestBuildSecurityHeadersHandler_NilHost
--- PASS: TestBuildSecurityHeadersHandler_NilHost (0.00s)
=== RUN TestBuildCSPString
=== RUN TestBuildCSPString/simple_CSP
=== RUN TestBuildCSPString/multiple_directives
=== RUN TestBuildCSPString/empty_string
=== RUN TestBuildCSPString/invalid_JSON
--- PASS: TestBuildCSPString (0.00s)
--- PASS: TestBuildCSPString/simple_CSP (0.00s)
--- PASS: TestBuildCSPString/multiple_directives (0.00s)
--- PASS: TestBuildCSPString/empty_string (0.00s)
--- PASS: TestBuildCSPString/invalid_JSON (0.00s)
=== RUN TestBuildPermissionsPolicyString
=== RUN TestBuildPermissionsPolicyString/single_feature_no_allowlist
=== RUN TestBuildPermissionsPolicyString/single_feature_with_self
=== RUN TestBuildPermissionsPolicyString/multiple_features
=== RUN TestBuildPermissionsPolicyString/empty_string
=== RUN TestBuildPermissionsPolicyString/invalid_JSON
--- PASS: TestBuildPermissionsPolicyString (0.00s)
--- PASS: TestBuildPermissionsPolicyString/single_feature_no_allowlist (0.00s)
--- PASS: TestBuildPermissionsPolicyString/single_feature_with_self (0.00s)
--- PASS: TestBuildPermissionsPolicyString/multiple_features (0.00s)
--- PASS: TestBuildPermissionsPolicyString/empty_string (0.00s)
--- PASS: TestBuildPermissionsPolicyString/invalid_JSON (0.00s)
=== RUN TestGetDefaultSecurityHeaderProfile
--- PASS: TestGetDefaultSecurityHeaderProfile (0.00s)
=== RUN TestBuildSecurityHeadersHandler_PermissionsPolicy
--- PASS: TestBuildSecurityHeadersHandler_PermissionsPolicy (0.00s)
=== RUN TestBuildSecurityHeadersHandler_InvalidCSPJSON
--- PASS: TestBuildSecurityHeadersHandler_InvalidCSPJSON (0.00s)
=== RUN TestBuildSecurityHeadersHandler_InvalidPermissionsJSON
--- PASS: TestBuildSecurityHeadersHandler_InvalidPermissionsJSON (0.00s)
=== RUN TestBuildSecurityHeadersHandler_APIFriendlyPreset
--- PASS: TestBuildSecurityHeadersHandler_APIFriendlyPreset (0.00s)
=== RUN TestGenerateConfig_Empty
--- PASS: TestGenerateConfig_Empty (0.00s)
=== RUN TestGenerateConfig_SingleHost
--- PASS: TestGenerateConfig_SingleHost (0.00s)
=== RUN TestGenerateConfig_MultipleHosts
--- PASS: TestGenerateConfig_MultipleHosts (0.00s)
=== RUN TestGenerateConfig_WebSocketEnabled
--- PASS: TestGenerateConfig_WebSocketEnabled (0.00s)
=== RUN TestGenerateConfig_EmptyDomain
--- PASS: TestGenerateConfig_EmptyDomain (0.00s)
=== RUN TestGenerateConfig_Logging
--- PASS: TestGenerateConfig_Logging (0.00s)
=== RUN TestGenerateConfig_IPHostsSkipAutoHTTPS
--- PASS: TestGenerateConfig_IPHostsSkipAutoHTTPS (0.00s)
=== RUN TestGenerateConfig_Advanced
--- PASS: TestGenerateConfig_Advanced (0.00s)
=== RUN TestGenerateConfig_ACMEStaging
--- PASS: TestGenerateConfig_ACMEStaging (0.00s)
=== RUN TestBuildACLHandler_WhitelistAndBlacklistAdminMerge
--- PASS: TestBuildACLHandler_WhitelistAndBlacklistAdminMerge (0.00s)
=== RUN TestBuildACLHandler_GeoAndLocalNetwork
--- PASS: TestBuildACLHandler_GeoAndLocalNetwork (0.00s)
=== RUN TestBuildACLHandler_AdminWhitelistParsing
--- PASS: TestBuildACLHandler_AdminWhitelistParsing (0.00s)
=== RUN TestBuildRateLimitHandler_Disabled
--- PASS: TestBuildRateLimitHandler_Disabled (0.00s)
=== RUN TestBuildRateLimitHandler_InvalidValues
--- PASS: TestBuildRateLimitHandler_InvalidValues (0.00s)
=== RUN TestBuildRateLimitHandler_ValidConfig
--- PASS: TestBuildRateLimitHandler_ValidConfig (0.00s)
=== RUN TestBuildRateLimitHandler_JSONFormat
--- PASS: TestBuildRateLimitHandler_JSONFormat (0.00s)
=== RUN TestGenerateConfig_WithRateLimiting
--- PASS: TestGenerateConfig_WithRateLimiting (0.00s)
=== RUN TestBuildRateLimitHandler_UsesBurst
--- PASS: TestBuildRateLimitHandler_UsesBurst (0.00s)
=== RUN TestBuildRateLimitHandler_DefaultBurst
--- PASS: TestBuildRateLimitHandler_DefaultBurst (0.00s)
=== RUN TestGetAccessLogPath_CrowdSecEnabled
--- PASS: TestGetAccessLogPath_CrowdSecEnabled (0.00s)
=== RUN TestGetAccessLogPath_DockerEnv
--- PASS: TestGetAccessLogPath_DockerEnv (0.00s)
=== RUN TestGetAccessLogPath_Development
--- PASS: TestGetAccessLogPath_Development (0.00s)
=== RUN TestBuildPermissionsPolicyString_EmptyAllowlist
--- PASS: TestBuildPermissionsPolicyString_EmptyAllowlist (0.00s)
=== RUN TestBuildPermissionsPolicyString_SelfAndStar
--- PASS: TestBuildPermissionsPolicyString_SelfAndStar (0.00s)
=== RUN TestBuildPermissionsPolicyString_DomainValues
--- PASS: TestBuildPermissionsPolicyString_DomainValues (0.00s)
=== RUN TestBuildPermissionsPolicyString_Mixed
--- PASS: TestBuildPermissionsPolicyString_Mixed (0.00s)
=== RUN TestBuildPermissionsPolicyString_InvalidJSON
--- PASS: TestBuildPermissionsPolicyString_InvalidJSON (0.00s)
=== RUN TestBuildCSPString_EmptyDirective
--- PASS: TestBuildCSPString_EmptyDirective (0.00s)
=== RUN TestBuildCSPString_InvalidJSON
--- PASS: TestBuildCSPString_InvalidJSON (0.00s)
=== RUN TestBuildSecurityHeadersHandler_CompleteProfile
--- PASS: TestBuildSecurityHeadersHandler_CompleteProfile (0.00s)
=== RUN TestGenerateConfig_SSLProviderZeroSSL
--- PASS: TestGenerateConfig_SSLProviderZeroSSL (0.00s)
=== RUN TestGenerateConfig_SSLProviderBoth
--- PASS: TestGenerateConfig_SSLProviderBoth (0.00s)
=== RUN TestGenerateConfig_DuplicateDomains
--- PASS: TestGenerateConfig_DuplicateDomains (0.00s)
=== RUN TestGenerateConfig_WithCrowdSecApp
--- PASS: TestGenerateConfig_WithCrowdSecApp (0.00s)
=== RUN TestGenerateConfig_CrowdSecHandlerAdded
--- PASS: TestGenerateConfig_CrowdSecHandlerAdded (0.00s)
=== RUN TestGenerateConfig_WithSecurityDecisions
--- PASS: TestGenerateConfig_WithSecurityDecisions (0.00s)
=== RUN TestBuildRateLimitHandler_BypassList
--- PASS: TestBuildRateLimitHandler_BypassList (0.00s)
=== RUN TestBuildRateLimitHandler_BypassList_PlainIPs
--- PASS: TestBuildRateLimitHandler_BypassList_PlainIPs (0.00s)
=== RUN TestBuildRateLimitHandler_BypassList_InvalidEntries
--- PASS: TestBuildRateLimitHandler_BypassList_InvalidEntries (0.00s)
=== RUN TestBuildRateLimitHandler_BypassList_Empty
--- PASS: TestBuildRateLimitHandler_BypassList_Empty (0.00s)
=== RUN TestBuildRateLimitHandler_BypassList_AllInvalid
--- PASS: TestBuildRateLimitHandler_BypassList_AllInvalid (0.00s)
=== RUN TestParseBypassCIDRs
=== RUN TestParseBypassCIDRs/empty
=== RUN TestParseBypassCIDRs/single_cidr
=== RUN TestParseBypassCIDRs/multiple_cidrs
=== RUN TestParseBypassCIDRs/plain_ipv4
=== RUN TestParseBypassCIDRs/plain_ipv6
=== RUN TestParseBypassCIDRs/mixed
=== RUN TestParseBypassCIDRs/with_spaces
=== RUN TestParseBypassCIDRs/all_invalid
--- PASS: TestParseBypassCIDRs (0.00s)
--- PASS: TestParseBypassCIDRs/empty (0.00s)
--- PASS: TestParseBypassCIDRs/single_cidr (0.00s)
--- PASS: TestParseBypassCIDRs/multiple_cidrs (0.00s)
--- PASS: TestParseBypassCIDRs/plain_ipv4 (0.00s)
--- PASS: TestParseBypassCIDRs/plain_ipv6 (0.00s)
--- PASS: TestParseBypassCIDRs/mixed (0.00s)
--- PASS: TestParseBypassCIDRs/with_spaces (0.00s)
--- PASS: TestParseBypassCIDRs/all_invalid (0.00s)
=== RUN TestBuildWAFHandler_ParanoiaLevel
=== RUN TestBuildWAFHandler_ParanoiaLevel/level_1_default
=== RUN TestBuildWAFHandler_ParanoiaLevel/level_1_explicit
=== RUN TestBuildWAFHandler_ParanoiaLevel/level_2
=== RUN TestBuildWAFHandler_ParanoiaLevel/level_3
=== RUN TestBuildWAFHandler_ParanoiaLevel/level_4_max
=== RUN TestBuildWAFHandler_ParanoiaLevel/level_invalid_high
=== RUN TestBuildWAFHandler_ParanoiaLevel/level_invalid_neg
--- PASS: TestBuildWAFHandler_ParanoiaLevel (0.00s)
--- PASS: TestBuildWAFHandler_ParanoiaLevel/level_1_default (0.00s)
--- PASS: TestBuildWAFHandler_ParanoiaLevel/level_1_explicit (0.00s)
--- PASS: TestBuildWAFHandler_ParanoiaLevel/level_2 (0.00s)
--- PASS: TestBuildWAFHandler_ParanoiaLevel/level_3 (0.00s)
--- PASS: TestBuildWAFHandler_ParanoiaLevel/level_4_max (0.00s)
--- PASS: TestBuildWAFHandler_ParanoiaLevel/level_invalid_high (0.00s)
--- PASS: TestBuildWAFHandler_ParanoiaLevel/level_invalid_neg (0.00s)
=== RUN TestBuildWAFHandler_Exclusions
--- PASS: TestBuildWAFHandler_Exclusions (0.00s)
=== RUN TestBuildWAFHandler_ExclusionsWithTarget
--- PASS: TestBuildWAFHandler_ExclusionsWithTarget (0.00s)
=== RUN TestBuildWAFHandler_PerHostDisabled
--- PASS: TestBuildWAFHandler_PerHostDisabled (0.00s)
=== RUN TestBuildWAFHandler_MonitorMode
--- PASS: TestBuildWAFHandler_MonitorMode (0.00s)
=== RUN TestBuildWAFHandler_GlobalDisabled
--- PASS: TestBuildWAFHandler_GlobalDisabled (0.00s)
=== RUN TestBuildWAFHandler_NoRuleset
--- PASS: TestBuildWAFHandler_NoRuleset (0.00s)
=== RUN TestParseWAFExclusions
=== RUN TestParseWAFExclusions/empty
=== RUN TestParseWAFExclusions/single_exclusion
=== RUN TestParseWAFExclusions/multiple_exclusions
=== RUN TestParseWAFExclusions/invalid_json
--- PASS: TestParseWAFExclusions (0.00s)
--- PASS: TestParseWAFExclusions/empty (0.00s)
--- PASS: TestParseWAFExclusions/single_exclusion (0.00s)
--- PASS: TestParseWAFExclusions/multiple_exclusions (0.00s)
--- PASS: TestParseWAFExclusions/invalid_json (0.00s)
=== RUN TestGenerateConfig_WithWAFPerHostDisabled
--- PASS: TestGenerateConfig_WithWAFPerHostDisabled (0.00s)
=== RUN TestGenerateConfig_WithDisabledHost
--- PASS: TestGenerateConfig_WithDisabledHost (0.00s)
=== RUN TestGenerateConfig_WithFrontendDir
--- PASS: TestGenerateConfig_WithFrontendDir (0.00s)
=== RUN TestGenerateConfig_CustomCertificate
--- PASS: TestGenerateConfig_CustomCertificate (0.00s)
=== RUN TestGenerateConfig_CustomCertificateMissingData
--- PASS: TestGenerateConfig_CustomCertificateMissingData (0.00s)
=== RUN TestGenerateConfig_LetsEncryptCertificateNotLoaded
--- PASS: TestGenerateConfig_LetsEncryptCertificateNotLoaded (0.00s)
=== RUN TestGenerateConfig_NormalizeAdvancedConfig
--- PASS: TestGenerateConfig_NormalizeAdvancedConfig (0.00s)
=== RUN TestGenerateConfig_NoACMEEmailNoTLS
--- PASS: TestGenerateConfig_NoACMEEmailNoTLS (0.00s)
=== RUN TestGenerateConfig_SecurityDecisionsWithAdminWhitelist
--- PASS: TestGenerateConfig_SecurityDecisionsWithAdminWhitelist (0.00s)
=== RUN TestBuildSecurityHeadersHandler_DefaultProfile
--- PASS: TestBuildSecurityHeadersHandler_DefaultProfile (0.00s)
=== RUN TestHasWildcard
=== RUN TestHasWildcard/no_wildcard
=== RUN TestHasWildcard/with_wildcard
=== RUN TestHasWildcard/only_wildcard
=== RUN TestHasWildcard/empty
--- PASS: TestHasWildcard (0.00s)
--- PASS: TestHasWildcard/no_wildcard (0.00s)
--- PASS: TestHasWildcard/with_wildcard (0.00s)
--- PASS: TestHasWildcard/only_wildcard (0.00s)
--- PASS: TestHasWildcard/empty (0.00s)
=== RUN TestDedupeDomains
=== RUN TestDedupeDomains/no_dupes
=== RUN TestDedupeDomains/with_dupes
=== RUN TestDedupeDomains/all_dupes
=== RUN TestDedupeDomains/empty
--- PASS: TestDedupeDomains (0.00s)
--- PASS: TestDedupeDomains/no_dupes (0.00s)
--- PASS: TestDedupeDomains/with_dupes (0.00s)
--- PASS: TestDedupeDomains/all_dupes (0.00s)
--- PASS: TestDedupeDomains/empty (0.00s)
=== RUN TestNormalizeAdvancedConfig_NestedRoutes
--- PASS: TestNormalizeAdvancedConfig_NestedRoutes (0.00s)
=== RUN TestNormalizeAdvancedConfig_ArrayInput
--- PASS: TestNormalizeAdvancedConfig_ArrayInput (0.00s)
=== RUN TestGetCrowdSecAPIKey
--- PASS: TestGetCrowdSecAPIKey (0.00s)
=== RUN TestBuildWAFHandler_PathTraversalAttack
=== RUN TestBuildWAFHandler_PathTraversalAttack/Path_traversal_in_ruleset_name
=== RUN TestBuildWAFHandler_PathTraversalAttack/Null_byte_injection
=== RUN TestBuildWAFHandler_PathTraversalAttack/URL_encoded_traversal
--- PASS: TestBuildWAFHandler_PathTraversalAttack (0.00s)
--- PASS: TestBuildWAFHandler_PathTraversalAttack/Path_traversal_in_ruleset_name (0.00s)
--- PASS: TestBuildWAFHandler_PathTraversalAttack/Null_byte_injection (0.00s)
--- PASS: TestBuildWAFHandler_PathTraversalAttack/URL_encoded_traversal (0.00s)
=== RUN TestBuildWAFHandler_SQLInjectionInRulesetName
=== RUN TestBuildWAFHandler_SQLInjectionInRulesetName/';_DROP_TABLE_rulesets;_--
=== RUN TestBuildWAFHandler_SQLInjectionInRulesetName/1'_OR_'1'='1
=== RUN TestBuildWAFHandler_SQLInjectionInRulesetName/UNION_SELECT_*_FROM_users--
=== RUN TestBuildWAFHandler_SQLInjectionInRulesetName/admin'/*
--- PASS: TestBuildWAFHandler_SQLInjectionInRulesetName (0.00s)
--- PASS: TestBuildWAFHandler_SQLInjectionInRulesetName/';_DROP_TABLE_rulesets;_-- (0.00s)
--- PASS: TestBuildWAFHandler_SQLInjectionInRulesetName/1'_OR_'1'='1 (0.00s)
--- PASS: TestBuildWAFHandler_SQLInjectionInRulesetName/UNION_SELECT_*_FROM_users-- (0.00s)
--- PASS: TestBuildWAFHandler_SQLInjectionInRulesetName/admin'/* (0.00s)
=== RUN TestBuildWAFHandler_XSSInAdvancedConfig
=== RUN TestBuildWAFHandler_XSSInAdvancedConfig/{"ruleset_name":"<script>alert(1)</script>"}
=== RUN TestBuildWAFHandler_XSSInAdvancedConfig/{"ruleset_name":"<img_src=x_onerror=alert(1)>"}
=== RUN TestBuildWAFHandler_XSSInAdvancedConfig/{"ruleset_name":"javascript:alert(1)"}
=== RUN TestBuildWAFHandler_XSSInAdvancedConfig/{"ruleset_name":"<svg/onload=alert(1)>"}
--- PASS: TestBuildWAFHandler_XSSInAdvancedConfig (0.00s)
--- PASS: TestBuildWAFHandler_XSSInAdvancedConfig/{"ruleset_name":"<script>alert(1)</script>"} (0.00s)
--- PASS: TestBuildWAFHandler_XSSInAdvancedConfig/{"ruleset_name":"<img_src=x_onerror=alert(1)>"} (0.00s)
--- PASS: TestBuildWAFHandler_XSSInAdvancedConfig/{"ruleset_name":"javascript:alert(1)"} (0.00s)
--- PASS: TestBuildWAFHandler_XSSInAdvancedConfig/{"ruleset_name":"<svg/onload=alert(1)>"} (0.00s)
=== RUN TestBuildWAFHandler_HugePayload
--- PASS: TestBuildWAFHandler_HugePayload (0.00s)
=== RUN TestBuildWAFHandler_EmptyAndWhitespaceInputs
=== RUN TestBuildWAFHandler_EmptyAndWhitespaceInputs/Empty_string_WAFRulesSource
=== RUN TestBuildWAFHandler_EmptyAndWhitespaceInputs/Whitespace-only_WAFRulesSource
=== RUN TestBuildWAFHandler_EmptyAndWhitespaceInputs/Tab_and_newline_in_WAFRulesSource
--- PASS: TestBuildWAFHandler_EmptyAndWhitespaceInputs (0.00s)
--- PASS: TestBuildWAFHandler_EmptyAndWhitespaceInputs/Empty_string_WAFRulesSource (0.00s)
--- PASS: TestBuildWAFHandler_EmptyAndWhitespaceInputs/Whitespace-only_WAFRulesSource (0.00s)
--- PASS: TestBuildWAFHandler_EmptyAndWhitespaceInputs/Tab_and_newline_in_WAFRulesSource (0.00s)
=== RUN TestBuildWAFHandler_ConcurrentRulesetSelection
--- PASS: TestBuildWAFHandler_ConcurrentRulesetSelection (0.00s)
=== RUN TestBuildWAFHandler_NilSecCfg
--- PASS: TestBuildWAFHandler_NilSecCfg (0.00s)
=== RUN TestBuildWAFHandler_NilHost
--- PASS: TestBuildWAFHandler_NilHost (0.00s)
=== RUN TestBuildWAFHandler_SpecialCharactersInRulesetName
=== RUN TestBuildWAFHandler_SpecialCharactersInRulesetName/ruleset_with_spaces
=== RUN TestBuildWAFHandler_SpecialCharactersInRulesetName/ruleset/with/slashes
=== RUN TestBuildWAFHandler_SpecialCharactersInRulesetName/UPPERCASE-RULESET
=== RUN TestBuildWAFHandler_SpecialCharactersInRulesetName/ruleset_with_underscores
=== RUN TestBuildWAFHandler_SpecialCharactersInRulesetName/ruleset.with.dots
--- PASS: TestBuildWAFHandler_SpecialCharactersInRulesetName (0.00s)
--- PASS: TestBuildWAFHandler_SpecialCharactersInRulesetName/ruleset_with_spaces (0.00s)
--- PASS: TestBuildWAFHandler_SpecialCharactersInRulesetName/ruleset/with/slashes (0.00s)
--- PASS: TestBuildWAFHandler_SpecialCharactersInRulesetName/UPPERCASE-RULESET (0.00s)
--- PASS: TestBuildWAFHandler_SpecialCharactersInRulesetName/ruleset_with_underscores (0.00s)
--- PASS: TestBuildWAFHandler_SpecialCharactersInRulesetName/ruleset.with.dots (0.00s)
=== RUN TestBuildWAFHandler_RulesetSelectionPriority
=== RUN TestBuildWAFHandler_RulesetSelectionPriority/WAFRulesSource_takes_priority_over_owasp-crs
=== RUN TestBuildWAFHandler_RulesetSelectionPriority/hostRulesetName_takes_priority_over_owasp-crs
=== RUN TestBuildWAFHandler_RulesetSelectionPriority/host.Application_takes_priority_over_owasp-crs
=== RUN TestBuildWAFHandler_RulesetSelectionPriority/owasp-crs_used_as_fallback_when_no_other_match
=== RUN TestBuildWAFHandler_RulesetSelectionPriority/WAFRulesSource_takes_priority_over_host.Application_and_owasp-crs
--- PASS: TestBuildWAFHandler_RulesetSelectionPriority (0.00s)
--- PASS: TestBuildWAFHandler_RulesetSelectionPriority/WAFRulesSource_takes_priority_over_owasp-crs (0.00s)
--- PASS: TestBuildWAFHandler_RulesetSelectionPriority/hostRulesetName_takes_priority_over_owasp-crs (0.00s)
--- PASS: TestBuildWAFHandler_RulesetSelectionPriority/host.Application_takes_priority_over_owasp-crs (0.00s)
--- PASS: TestBuildWAFHandler_RulesetSelectionPriority/owasp-crs_used_as_fallback_when_no_other_match (0.00s)
--- PASS: TestBuildWAFHandler_RulesetSelectionPriority/WAFRulesSource_takes_priority_over_host.Application_and_owasp-crs (0.00s)
=== RUN TestBuildWAFHandler_NoDirectivesReturnsNil
=== RUN TestBuildWAFHandler_NoDirectivesReturnsNil/Empty_rulesets_returns_nil
=== RUN TestBuildWAFHandler_NoDirectivesReturnsNil/Ruleset_exists_but_no_path_mapping_returns_nil
=== RUN TestBuildWAFHandler_NoDirectivesReturnsNil/WAFRulesSource_specified_but_not_in_rulesets_or_paths_returns_nil
=== RUN TestBuildWAFHandler_NoDirectivesReturnsNil/Empty_path_in_rulesetPaths_returns_nil
--- PASS: TestBuildWAFHandler_NoDirectivesReturnsNil (0.00s)
--- PASS: TestBuildWAFHandler_NoDirectivesReturnsNil/Empty_rulesets_returns_nil (0.00s)
--- PASS: TestBuildWAFHandler_NoDirectivesReturnsNil/Ruleset_exists_but_no_path_mapping_returns_nil (0.00s)
--- PASS: TestBuildWAFHandler_NoDirectivesReturnsNil/WAFRulesSource_specified_but_not_in_rulesets_or_paths_returns_nil (0.00s)
--- PASS: TestBuildWAFHandler_NoDirectivesReturnsNil/Empty_path_in_rulesetPaths_returns_nil (0.00s)
=== RUN TestBuildWAFHandler_DisabledModes
=== RUN TestBuildWAFHandler_DisabledModes/wafEnabled_false_returns_nil
=== RUN TestBuildWAFHandler_DisabledModes/WAFMode_disabled_returns_nil
--- PASS: TestBuildWAFHandler_DisabledModes (0.00s)
--- PASS: TestBuildWAFHandler_DisabledModes/wafEnabled_false_returns_nil (0.00s)
--- PASS: TestBuildWAFHandler_DisabledModes/WAFMode_disabled_returns_nil (0.00s)
=== RUN TestBuildWAFHandler_HandlerStructure
--- PASS: TestBuildWAFHandler_HandlerStructure (0.00s)
=== RUN TestBuildWAFHandler_AdvancedConfigParsing
=== RUN TestBuildWAFHandler_AdvancedConfigParsing/Valid_ruleset_name_in_advanced_config
=== RUN TestBuildWAFHandler_AdvancedConfigParsing/Invalid_JSON_falls_back_to_owasp-crs
=== RUN TestBuildWAFHandler_AdvancedConfigParsing/Empty_advanced_config_falls_back_to_owasp-crs
=== RUN TestBuildWAFHandler_AdvancedConfigParsing/Empty_ruleset_name_string_falls_back_to_owasp-crs
=== RUN TestBuildWAFHandler_AdvancedConfigParsing/Non-string_ruleset_name_falls_back_to_owasp-crs
--- PASS: TestBuildWAFHandler_AdvancedConfigParsing (0.00s)
--- PASS: TestBuildWAFHandler_AdvancedConfigParsing/Valid_ruleset_name_in_advanced_config (0.00s)
--- PASS: TestBuildWAFHandler_AdvancedConfigParsing/Invalid_JSON_falls_back_to_owasp-crs (0.00s)
--- PASS: TestBuildWAFHandler_AdvancedConfigParsing/Empty_advanced_config_falls_back_to_owasp-crs (0.00s)
--- PASS: TestBuildWAFHandler_AdvancedConfigParsing/Empty_ruleset_name_string_falls_back_to_owasp-crs (0.00s)
--- PASS: TestBuildWAFHandler_AdvancedConfigParsing/Non-string_ruleset_name_falls_back_to_owasp-crs (0.00s)
=== RUN TestImporter_ExtractHosts_DialWithoutPortDefaultsTo80
--- PASS: TestImporter_ExtractHosts_DialWithoutPortDefaultsTo80 (0.00s)
=== RUN TestImporter_ExtractHosts_DetectsWebsocketFromHeaders
--- PASS: TestImporter_ExtractHosts_DetectsWebsocketFromHeaders (0.00s)
=== RUN TestImporter_ImportFile_ParseOutputInvalidJSON
--- PASS: TestImporter_ImportFile_ParseOutputInvalidJSON (0.00s)
=== RUN TestImporter_ImportFile_ExecutorError
--- PASS: TestImporter_ImportFile_ExecutorError (0.00s)
=== RUN TestImporter_ExtractHosts_TLSConnectionPolicyAndDialWithoutPort
--- PASS: TestImporter_ExtractHosts_TLSConnectionPolicyAndDialWithoutPort (0.00s)
=== RUN TestExtractHandlers_Subroute_WithUnsupportedSubhandle
--- PASS: TestExtractHandlers_Subroute_WithUnsupportedSubhandle (0.00s)
=== RUN TestExtractHandlers_Subroute_WithNonMapRoutes
--- PASS: TestExtractHandlers_Subroute_WithNonMapRoutes (0.00s)
=== RUN TestImporter_ExtractHosts_UpstreamsNonMapAndWarnings
--- PASS: TestImporter_ExtractHosts_UpstreamsNonMapAndWarnings (0.00s)
=== RUN TestBackupCaddyfile_ReadFailure
--- PASS: TestBackupCaddyfile_ReadFailure (0.00s)
=== RUN TestExtractHandlers_Subroute_EmptyAndHandleNotArray
--- PASS: TestExtractHandlers_Subroute_EmptyAndHandleNotArray (0.00s)
=== RUN TestImporter_ExtractHosts_ReverseProxyNoUpstreams
--- PASS: TestImporter_ExtractHosts_ReverseProxyNoUpstreams (0.00s)
=== RUN TestBackupCaddyfile_Success
--- PASS: TestBackupCaddyfile_Success (0.00s)
=== RUN TestExtractHandlers_Subroute_WithHeadersUpstreams
--- PASS: TestExtractHandlers_Subroute_WithHeadersUpstreams (0.00s)
=== RUN TestImporter_ExtractHosts_DuplicateHost
--- PASS: TestImporter_ExtractHosts_DuplicateHost (0.00s)
=== RUN TestBackupCaddyfile_WriteFailure
--- PASS: TestBackupCaddyfile_WriteFailure (0.00s)
=== RUN TestImporter_ExtractHosts_SSLForcedByDomainScheme
--- PASS: TestImporter_ExtractHosts_SSLForcedByDomainScheme (0.00s)
=== RUN TestImporter_ExtractHosts_MultipleHostsInMatch
--- PASS: TestImporter_ExtractHosts_MultipleHostsInMatch (0.00s)
=== RUN TestImporter_ExtractHosts_UpgradeHeaderAsString
--- PASS: TestImporter_ExtractHosts_UpgradeHeaderAsString (0.00s)
=== RUN TestImporter_ExtractHosts_SscanfFailureOnPort
--- PASS: TestImporter_ExtractHosts_SscanfFailureOnPort (0.00s)
=== RUN TestImporter_ExtractHosts_PartsSscanfFail
--- PASS: TestImporter_ExtractHosts_PartsSscanfFail (0.00s)
=== RUN TestImporter_ExtractHosts_PartsEmptyPortField
--- PASS: TestImporter_ExtractHosts_PartsEmptyPortField (0.00s)
=== RUN TestImporter_ExtractHosts_ForceSplitFallback_PartsNumericPort
--- PASS: TestImporter_ExtractHosts_ForceSplitFallback_PartsNumericPort (0.00s)
=== RUN TestImporter_ExtractHosts_ForceSplitFallback_PartsSscanfFail
--- PASS: TestImporter_ExtractHosts_ForceSplitFallback_PartsSscanfFail (0.00s)
=== RUN TestBackupCaddyfile_WriteErrorDeterministic
--- PASS: TestBackupCaddyfile_WriteErrorDeterministic (0.00s)
=== RUN TestParseCaddyfile_InvalidPath
--- PASS: TestParseCaddyfile_InvalidPath (0.00s)
=== RUN TestBackupCaddyfile_InvalidOriginalPath
--- PASS: TestBackupCaddyfile_InvalidOriginalPath (0.00s)
=== RUN TestExtractHandlers_Subroute
--- PASS: TestExtractHandlers_Subroute (0.00s)
=== RUN TestNewImporter
--- PASS: TestNewImporter (0.00s)
=== RUN TestImporter_ParseCaddyfile_NotFound
--- PASS: TestImporter_ParseCaddyfile_NotFound (0.00s)
=== RUN TestImporter_ParseCaddyfile_Success
--- PASS: TestImporter_ParseCaddyfile_Success (0.00s)
=== RUN TestImporter_ParseCaddyfile_Failure
--- PASS: TestImporter_ParseCaddyfile_Failure (0.00s)
=== RUN TestImporter_ExtractHosts
--- PASS: TestImporter_ExtractHosts (0.00s)
=== RUN TestImporter_ImportFile
--- PASS: TestImporter_ImportFile (0.00s)
=== RUN TestConvertToProxyHosts
--- PASS: TestConvertToProxyHosts (0.00s)
=== RUN TestImporter_ValidateCaddyBinary
--- PASS: TestImporter_ValidateCaddyBinary (0.00s)
=== RUN TestBackupCaddyfile
--- PASS: TestBackupCaddyfile (0.00s)
=== RUN TestDefaultExecutor_Execute
--- PASS: TestDefaultExecutor_Execute (0.01s)
=== RUN TestManager_ListSnapshots_ReadDirError
--- PASS: TestManager_ListSnapshots_ReadDirError (0.00s)
=== RUN TestManager_RotateSnapshots_NoOp
--- PASS: TestManager_RotateSnapshots_NoOp (0.00s)
=== RUN TestManager_Rollback_NoSnapshots
--- PASS: TestManager_Rollback_NoSnapshots (0.00s)
=== RUN TestManager_Rollback_UnmarshalError
--- PASS: TestManager_Rollback_UnmarshalError (0.00s)
=== RUN TestManager_Rollback_LoadSnapshotFail
--- PASS: TestManager_Rollback_LoadSnapshotFail (0.00s)
=== RUN TestManager_SaveSnapshot_WriteError
--- PASS: TestManager_SaveSnapshot_WriteError (0.00s)
=== RUN TestBackupCaddyfile_MkdirAllFailure
--- PASS: TestBackupCaddyfile_MkdirAllFailure (0.00s)
=== RUN TestManager_SaveSnapshot_Success
--- PASS: TestManager_SaveSnapshot_Success (0.00s)
=== RUN TestManager_ApplyConfig_WithSettings
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[0.870ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.071ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.058ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.080ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.029ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.660ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.009ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_WithSettings (0.05s)
=== RUN TestManager_RotateSnapshots_ListDirError
--- PASS: TestManager_RotateSnapshots_ListDirError (0.00s)
=== RUN TestManager_RotateSnapshots_DeletesOld
--- PASS: TestManager_RotateSnapshots_DeletesOld (0.00s)
=== RUN TestManager_ApplyConfig_RotateSnapshotsWarning
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.118ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.097ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[3.490ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.104ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.075ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.065ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.031ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.993ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.807ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_RotateSnapshotsWarning (0.04s)
=== RUN TestManager_ApplyConfig_LoadFailsAndRollbackFails
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.049ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.081ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[0.990ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.068ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.048ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.042ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.039ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.713ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.297ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_LoadFailsAndRollbackFails (0.05s)
=== RUN TestManager_ApplyConfig_SaveSnapshotFails
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.057ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.046ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[0.847ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.051ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.039ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.035ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.022ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[1.168ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.519ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_SaveSnapshotFails (0.03s)
=== RUN TestManager_ApplyConfig_LoadFailsThenRollbackSucceeds
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.053ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.071ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.532ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.106ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.279ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.089ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.052ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[2.196ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.848ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_LoadFailsThenRollbackSucceeds (0.04s)
=== RUN TestManager_SaveSnapshot_MarshalError
--- PASS: TestManager_SaveSnapshot_MarshalError (0.00s)
=== RUN TestManager_RotateSnapshots_DeleteError
--- PASS: TestManager_RotateSnapshots_DeleteError (0.00s)
=== RUN TestManager_ApplyConfig_GenerateConfigFails
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.076ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.229ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.226ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.086ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.106ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.079ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.047ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[3.675ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.945ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_GenerateConfigFails (0.03s)
=== RUN TestManager_ApplyConfig_WarnsWhenCerberusEnabledWithoutAdminWhitelist
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.084ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.076ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.109ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.071ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.054ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[2.722ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.750ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_WarnsWhenCerberusEnabledWithoutAdminWhitelist (0.03s)
=== RUN TestManager_ApplyConfig_ValidateFails
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.058ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.053ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[3.064ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.061ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.049ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.046ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.028ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[2.537ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.732ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_ValidateFails (0.02s)
=== RUN TestManager_Rollback_ReadFileError
--- PASS: TestManager_Rollback_ReadFileError (0.00s)
=== RUN TestManager_ApplyConfig_RotateSnapshotsWarning_Stderr
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.065ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.070ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.128ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.181ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.109ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.099ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.041ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[2.253ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.361ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_RotateSnapshotsWarning_Stderr (0.03s)
=== RUN TestManager_ApplyConfig_PassesAdminWhitelistToGenerateConfig
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.088ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.089ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.078ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.055ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.048ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.890ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.535ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_PassesAdminWhitelistToGenerateConfig (0.03s)
=== RUN TestManager_ApplyConfig_PassesRuleSetsToGenerateConfig
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.072ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.050ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.045ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.042ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.039ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.990ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_PassesRuleSetsToGenerateConfig (0.05s)
=== RUN TestManager_ApplyConfig_IncludesWAFHandlerWithRuleset
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.062ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.102ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.102ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.068ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.044ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.668ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
manager_additional_test.go:727: generated config: {"admin":{"listen":"0.0.0.0:2019"},"apps":{"http":{"servers":{"charon_server":{"listen":[":80",":443"],"routes":[{"match":[{"host":["ruleset.example.com"]}],"handle":[{"directives":"SecRuleEngine On\nSecRequestBodyAccess On\nSecResponseBodyAccess Off\nSecAction \"id:900000,phase:1,nolog,pass,t:none,setvar:tx.paranoia_level=1\"\nInclude /tmp/TestManager_ApplyConfig_IncludesWAFHandlerWithRuleset1320949653/001/coraza/rulesets/owasp-crs-05ec1bde.conf\n","handler":"waf"},{"handler":"headers","response":{"set":{"Cross-Origin-Opener-Policy":["same-origin"],"Cross-Origin-Resource-Policy":["same-origin"],"Referrer-Policy":["strict-origin-when-cross-origin"],"Strict-Transport-Security":["max-age=31536000"],"X-Content-Type-Options":["nosniff"],"X-Frame-Options":["SAMEORIGIN"],"X-XSS-Protection":["1; mode=block"]}}},{"handler":"vars"},{"flush_interval":-1,"handler":"reverse_proxy","headers":{"request":{"set":{"X-Forwarded-Host":["{http.request.host}"],"X-Forwarded-Port":["{http.request.port}"],"X-Forwarded-Proto":["{http.request.scheme}"],"X-Real-IP":["{http.request.remote.host}"]}}},"upstreams":[{"dial":"127.0.0.1:8080"}]}],"terminal":true}],"automatic_https":{},"logs":{"default_logger_name":"access_log"},"trusted_proxies":{"source":"static","ranges":["127.0.0.1/32","::1/128","172.16.0.0/12","10.0.0.0/8","192.168.0.0/16"]}}}}},"logging":{"logs":{"access":{"writer":{"output":"file","filename":"/tmp/TestManager_ApplyConfig_IncludesWAFHandlerWithRuleset1320949653/logs/access.log","roll":true,"roll_size_mb":10,"roll_keep":5,"roll_keep_days":7},"encoder":{"format":"json"},"level":"INFO","include":["http.log.access.access_log"]}}},"storage":{"module":"file_system","root":"/tmp/TestManager_ApplyConfig_IncludesWAFHandlerWithRuleset1320949653/001/data"}}
--- PASS: TestManager_ApplyConfig_IncludesWAFHandlerWithRuleset (0.03s)
=== RUN TestManager_ApplyConfig_RulesetWriteFileFailure
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.104ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.102ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.096ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.079ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.069ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.334ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_RulesetWriteFileFailure (0.04s)
=== RUN TestManager_ApplyConfig_RulesetDirMkdirFailure
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.054ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.054ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.053ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.057ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.052ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.739ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_RulesetDirMkdirFailure (0.04s)
=== RUN TestManager_ApplyConfig_ReappliesOnFlagChange
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.065ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.078ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.281ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.079ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.068ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.074ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.035ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[1.490ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.567ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.050ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.066ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[0.048ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.078ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.075ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.038ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.036ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.023ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.062ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.068ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[0.030ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.043ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.072ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.043ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.032ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.050ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_ReappliesOnFlagChange (0.05s)
=== RUN TestManager_ApplyConfig_PrependsSecRuleEngineDirectives
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.042ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.044ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.366ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.165ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.059ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.861ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_PrependsSecRuleEngineDirectives (0.04s)
=== RUN TestManager_ApplyConfig_DoesNotPrependIfSecRuleEngineExists
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.061ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.067ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.071ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.064ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.057ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[2.184ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_DoesNotPrependIfSecRuleEngineExists (0.03s)
=== RUN TestManager_ApplyConfig_DebugMarshalFailure
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.045ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.049ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.222ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.053ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.076ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.035ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_DebugMarshalFailure (0.03s)
=== RUN TestManager_ApplyConfig_WAFModeMonitorUsesDetectionOnly
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.041ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.046ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.039ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.059ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.039ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[2.842ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_WAFModeMonitorUsesDetectionOnly (0.04s)
=== RUN TestManager_ApplyConfig_PerRulesetModeOverride
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.053ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.061ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.055ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.059ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.061ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.123ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_PerRulesetModeOverride (0.04s)
=== RUN TestManager_ApplyConfig_RulesetFileCleanup
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.064ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.081ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.067ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.067ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.073ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.760ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_RulesetFileCleanup (0.03s)
=== RUN TestManager_ApplyConfig_RulesetCleanupReadDirError
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.093ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.069ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.053ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.044ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.037ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.134ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_RulesetCleanupReadDirError (0.03s)
=== RUN TestManager_ApplyConfig_RulesetCleanupRemoveError
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.055ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.063ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.052ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.050ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.048ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.576ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_RulesetCleanupRemoveError (0.03s)
=== RUN TestManager_ApplyConfig_WAFModeBlockExplicit
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.066ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.085ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.082ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.079ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.062ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.136ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_WAFModeBlockExplicit (0.03s)
=== RUN TestManager_ApplyConfig_RulesetNamePathTraversal
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.061ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.094ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.069ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.076ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.062ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[2.064ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_RulesetNamePathTraversal (0.03s)
=== RUN TestExtractBaseDomain_EmptyInput
--- PASS: TestExtractBaseDomain_EmptyInput (0.00s)
=== RUN TestExtractBaseDomain_OnlyCommas
--- PASS: TestExtractBaseDomain_OnlyCommas (0.00s)
=== RUN TestExtractBaseDomain_SingleDomain
--- PASS: TestExtractBaseDomain_SingleDomain (0.00s)
=== RUN TestExtractBaseDomain_WildcardDomain
--- PASS: TestExtractBaseDomain_WildcardDomain (0.00s)
=== RUN TestExtractBaseDomain_MultipleDomains
--- PASS: TestExtractBaseDomain_MultipleDomains (0.00s)
=== RUN TestExtractBaseDomain_MultipleDomainsWithWildcard
--- PASS: TestExtractBaseDomain_MultipleDomainsWithWildcard (0.00s)
=== RUN TestExtractBaseDomain_WithWhitespace
--- PASS: TestExtractBaseDomain_WithWhitespace (0.00s)
=== RUN TestExtractBaseDomain_CaseNormalization
--- PASS: TestExtractBaseDomain_CaseNormalization (0.00s)
=== RUN TestExtractBaseDomain_Subdomain
--- PASS: TestExtractBaseDomain_Subdomain (0.00s)
=== RUN TestExtractBaseDomain_MultiLevelSubdomain
--- PASS: TestExtractBaseDomain_MultiLevelSubdomain (0.00s)
=== RUN TestMatchesZoneFilter_EmptyFilter
--- PASS: TestMatchesZoneFilter_EmptyFilter (0.00s)
=== RUN TestMatchesZoneFilter_EmptyZonesInList
--- PASS: TestMatchesZoneFilter_EmptyZonesInList (0.00s)
=== RUN TestMatchesZoneFilter_ExactMatch
--- PASS: TestMatchesZoneFilter_ExactMatch (0.00s)
=== RUN TestMatchesZoneFilter_ExactMatchOnly
--- PASS: TestMatchesZoneFilter_ExactMatchOnly (0.00s)
=== RUN TestMatchesZoneFilter_WildcardMatch
--- PASS: TestMatchesZoneFilter_WildcardMatch (0.00s)
=== RUN TestMatchesZoneFilter_MultipleZones
--- PASS: TestMatchesZoneFilter_MultipleZones (0.00s)
=== RUN TestMatchesZoneFilter_MultipleZonesWithWildcard
--- PASS: TestMatchesZoneFilter_MultipleZonesWithWildcard (0.00s)
=== RUN TestMatchesZoneFilter_WhitespaceTrimming_Detailed
--- PASS: TestMatchesZoneFilter_WhitespaceTrimming_Detailed (0.00s)
=== RUN TestMatchesZoneFilter_DeepSubdomain
--- PASS: TestMatchesZoneFilter_DeepSubdomain (0.00s)
=== RUN TestGetCredentialForDomain_NoEncryptionKey
--- PASS: TestGetCredentialForDomain_NoEncryptionKey (0.00s)
=== RUN TestGetCredentialForDomain_MultiCredential_NoMatch
--- PASS: TestGetCredentialForDomain_MultiCredential_NoMatch (0.00s)
=== RUN TestGetCredentialForDomain_MultiCredential_DisabledSkipped
--- PASS: TestGetCredentialForDomain_MultiCredential_DisabledSkipped (0.00s)
=== RUN TestGetCredentialForDomain_MultiCredential_CatchAllMatch
--- PASS: TestGetCredentialForDomain_MultiCredential_CatchAllMatch (0.00s)
=== RUN TestComputeEffectiveFlags_DB_SecurityConfigWAFDisabled
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.045ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.061ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.039ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestComputeEffectiveFlags_DB_SecurityConfigWAFDisabled (0.01s)
=== RUN TestComputeEffectiveFlags_DB_RateLimitFromBooleanField
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.058ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.085ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.074ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestComputeEffectiveFlags_DB_RateLimitFromBooleanField (0.00s)
=== RUN TestComputeEffectiveFlags_DB_CrowdSecModeFromSecurityConfig
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.079ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.072ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.068ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestComputeEffectiveFlags_DB_CrowdSecModeFromSecurityConfig (0.01s)
=== RUN TestComputeEffectiveFlags_DB_LegacyCerberusKey
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.121ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.084ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.094ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" AND `settings`.`id` = 1 ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestComputeEffectiveFlags_DB_LegacyCerberusKey (0.00s)
=== RUN TestApplyConfig_SingleCredential_BackwardCompatibility
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.036ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:598 record not found
[0.102ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.086ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.067ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.062ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:285 record not found
[0.092ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.906ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.875ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:572 no such table: caddy_configs
[0.970ms] [rows:0] INSERT INTO `caddy_configs` (`config_hash`,`applied_at`,`success`,`error_msg`) VALUES ("5e816e57eb11055dffe0c15e31a606002ac4a0e55d5cffaf5a0d83b81d660105","2026-01-10 02:16:58.944",true,"") RETURNING `id`
--- PASS: TestApplyConfig_SingleCredential_BackwardCompatibility (0.03s)
=== RUN TestApplyConfig_MultiCredential_ExactMatch
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.064ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:598 record not found
[0.108ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.095ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.072ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.072ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:285 record not found
[0.087ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[1.132ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.930ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
2026/01/10 02:16:58 /projects/Charon/backend/internal/caddy/manager.go:572 no such table: caddy_configs
[2.050ms] [rows:0] INSERT INTO `caddy_configs` (`config_hash`,`applied_at`,`success`,`error_msg`) VALUES ("84844f433ace3d57bfa2bcb2f12ca1d13fe94265f9e4652ad1d94ab8627c9bca","2026-01-10 02:16:58.979",true,"") RETURNING `id`
--- PASS: TestApplyConfig_MultiCredential_ExactMatch (0.04s)
=== RUN TestApplyConfig_MultiCredential_WildcardMatch
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.380ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:598 record not found
[0.129ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.074ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.061ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.061ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:285 record not found
[0.108ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[1.125ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.346ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:572 no such table: caddy_configs
[0.904ms] [rows:0] INSERT INTO `caddy_configs` (`config_hash`,`applied_at`,`success`,`error_msg`) VALUES ("3b0f21b3fd87815befff8bee0f98a4e2a859adf7aecc02d7b8d0a627a477187e","2026-01-10 02:16:59.011",true,"") RETURNING `id`
--- PASS: TestApplyConfig_MultiCredential_WildcardMatch (0.03s)
=== RUN TestApplyConfig_MultiCredential_CatchAll
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.037ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:598 record not found
[0.096ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.059ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.087ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.072ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:285 record not found
[0.075ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.964ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[2.521ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:572 no such table: caddy_configs
[1.072ms] [rows:0] INSERT INTO `caddy_configs` (`config_hash`,`applied_at`,`success`,`error_msg`) VALUES ("03b090b404ed34a6054d2a728c08991e385b3587215219e1371b9d8944ce3099","2026-01-10 02:16:59.049",true,"") RETURNING `id`
--- PASS: TestApplyConfig_MultiCredential_CatchAll (0.04s)
=== RUN TestExtractBaseDomain
=== RUN TestExtractBaseDomain/wildcard_domain
=== RUN TestExtractBaseDomain/normal_domain
=== RUN TestExtractBaseDomain/multiple_domains
=== RUN TestExtractBaseDomain/empty
=== RUN TestExtractBaseDomain/with_spaces
--- PASS: TestExtractBaseDomain (0.00s)
--- PASS: TestExtractBaseDomain/wildcard_domain (0.00s)
--- PASS: TestExtractBaseDomain/normal_domain (0.00s)
--- PASS: TestExtractBaseDomain/multiple_domains (0.00s)
--- PASS: TestExtractBaseDomain/empty (0.00s)
--- PASS: TestExtractBaseDomain/with_spaces (0.00s)
=== RUN TestMatchesZoneFilter
=== RUN TestMatchesZoneFilter/exact_match
=== RUN TestMatchesZoneFilter/exact_match_(not_exact_only)
=== RUN TestMatchesZoneFilter/wildcard_match
=== RUN TestMatchesZoneFilter/wildcard_no_match_(exact_only)
=== RUN TestMatchesZoneFilter/wildcard_base_domain_match
=== RUN TestMatchesZoneFilter/no_match
=== RUN TestMatchesZoneFilter/comma-separated_zones
=== RUN TestMatchesZoneFilter/empty_filter
--- PASS: TestMatchesZoneFilter (0.00s)
--- PASS: TestMatchesZoneFilter/exact_match (0.00s)
--- PASS: TestMatchesZoneFilter/exact_match_(not_exact_only) (0.00s)
--- PASS: TestMatchesZoneFilter/wildcard_match (0.00s)
--- PASS: TestMatchesZoneFilter/wildcard_no_match_(exact_only) (0.00s)
--- PASS: TestMatchesZoneFilter/wildcard_base_domain_match (0.00s)
--- PASS: TestMatchesZoneFilter/no_match (0.00s)
--- PASS: TestMatchesZoneFilter/comma-separated_zones (0.00s)
--- PASS: TestMatchesZoneFilter/empty_filter (0.00s)
=== RUN TestManager_GetCredentialForDomain_NoMatch
--- PASS: TestManager_GetCredentialForDomain_NoMatch (0.00s)
=== RUN TestManager_GetCredentialForDomain_NoEncryptionKey
--- PASS: TestManager_GetCredentialForDomain_NoEncryptionKey (0.00s)
=== RUN TestManager_GetCredentialForDomain_DecryptionFailure
--- PASS: TestManager_GetCredentialForDomain_DecryptionFailure (0.00s)
=== RUN TestManager_GetCredentialForDomain_InvalidJSON
--- PASS: TestManager_GetCredentialForDomain_InvalidJSON (0.01s)
=== RUN TestManager_GetCredentialForDomain_SkipsDisabledCredentials
--- PASS: TestManager_GetCredentialForDomain_SkipsDisabledCredentials (0.00s)
=== RUN TestManager_GetCredentialForDomain_MultiCredential_DecryptionFailure
--- PASS: TestManager_GetCredentialForDomain_MultiCredential_DecryptionFailure (0.00s)
=== RUN TestManager_GetCredentialForDomain_MultiCredential_InvalidJSON
--- PASS: TestManager_GetCredentialForDomain_MultiCredential_InvalidJSON (0.00s)
=== RUN TestExtractBaseDomain_EmptyAfterSplit
--- PASS: TestExtractBaseDomain_EmptyAfterSplit (0.00s)
=== RUN TestMatchesZoneFilter_WhitespaceInFilter
--- PASS: TestMatchesZoneFilter_WhitespaceInFilter (0.00s)
=== RUN TestMatchesZoneFilter_CaseInsensitive
--- PASS: TestMatchesZoneFilter_CaseInsensitive (0.00s)
=== RUN TestManagerApplyConfig_DNSProviders_NoKey_SkipsDecryption
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.053ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.048ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.045ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.039ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.038ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestManagerApplyConfig_DNSProviders_NoKey_SkipsDecryption (0.03s)
=== RUN TestManagerApplyConfig_DNSProviders_UsesFallbackEnvKeys
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.078ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.057ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.055ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.051ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.050ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestManagerApplyConfig_DNSProviders_UsesFallbackEnvKeys (0.03s)
=== RUN TestManagerApplyConfig_DNSProviders_SkipsDecryptOrJSONFailures
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.074ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.089ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.071ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.086ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.086ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestManagerApplyConfig_DNSProviders_SkipsDecryptOrJSONFailures (0.03s)
=== RUN TestManager_ApplyConfig_SSLProvider_Auto
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.057ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[0.781ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.054ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.048ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.043ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.023ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.729ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[2.131ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_SSLProvider_Auto (0.03s)
=== RUN TestManager_ApplyConfig_SSLProvider_LetsEncryptStaging
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.074ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.286ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.084ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.064ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.059ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.030ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[1.013ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.887ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_SSLProvider_LetsEncryptStaging (0.03s)
=== RUN TestManager_ApplyConfig_SSLProvider_LetsEncryptProd
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.230ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.807ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.117ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.181ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.116ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.044ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[2.410ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.124ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_SSLProvider_LetsEncryptProd (0.04s)
=== RUN TestManager_ApplyConfig_SSLProvider_ZeroSSL
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.063ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.212ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.075ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.074ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.260ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.041ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[1.164ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[4.163ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_SSLProvider_ZeroSSL (0.03s)
=== RUN TestManager_ApplyConfig_SSLProvider_Empty
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.072ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.069ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[2.277ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.090ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.079ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.087ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.043ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[1.310ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.091ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_SSLProvider_Empty (0.04s)
=== RUN TestManager_ApplyConfig_SSLProvider_EmptyWithNoStaging
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.048ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.061ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.772ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.085ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.060ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.091ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.027ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.838ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.890ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_SSLProvider_EmptyWithNoStaging (0.03s)
=== RUN TestManager_ApplyConfig_SSLProvider_Unknown
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.089ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.455ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.081ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.109ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.089ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.148ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[1.627ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.903ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_SSLProvider_Unknown (0.03s)
=== RUN TestManager_ApplyConfig
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.068ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.061ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.067ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.071ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.068ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.064ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.036ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[2.232ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.888ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig (0.03s)
=== RUN TestManager_ApplyConfig_Failure
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.046ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.072ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[2.970ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.145ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.073ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.071ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.125ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[1.062ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.021ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_Failure (0.03s)
=== RUN TestManager_Ping
--- PASS: TestManager_Ping (0.00s)
=== RUN TestManager_GetCurrentConfig
--- PASS: TestManager_GetCurrentConfig (0.00s)
=== RUN TestManager_RotateSnapshots
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.077ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.146ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.042ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.088ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.146ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.380ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.064ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.854ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.975ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_RotateSnapshots (0.03s)
=== RUN TestManager_Rollback_Success
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.049ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.074ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[0.865ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.070ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.078ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.094ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.046ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[1.293ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:16:59 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.878ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.098ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.097ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[0.058ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.094ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.093ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.080ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.043ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.044ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[0.039ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_Rollback_Success (1.14s)
=== RUN TestManager_ApplyConfig_DBError
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:84 sql: database is closed
[0.073ms] [rows:0] SELECT * FROM `proxy_hosts`
--- PASS: TestManager_ApplyConfig_DBError (0.03s)
=== RUN TestManager_ApplyConfig_ValidationError
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.089ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.080ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[4.193ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.126ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.084ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.089ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.031ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[0.977ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[2.278ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_ApplyConfig_ValidationError (0.04s)
=== RUN TestManager_Rollback_Failure
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.064ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.065ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.903ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.091ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.065ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.060ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:285 no such table: security_configs
[0.044ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:295 no such table: security_rule_sets
[3.050ms] [rows:0] SELECT * FROM `security_rule_sets`
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:302 no such table: security_decisions
[1.947ms] [rows:0] SELECT * FROM `security_decisions` ORDER BY created_at desc
--- PASS: TestManager_Rollback_Failure (0.04s)
=== RUN TestComputeEffectiveFlags_DefaultsNoDB
--- PASS: TestComputeEffectiveFlags_DefaultsNoDB (0.00s)
=== RUN TestComputeEffectiveFlags_DB_CerberusDisabled
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.646ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.085ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" AND `settings`.`id` = 1 ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestComputeEffectiveFlags_DB_CerberusDisabled (0.00s)
=== RUN TestComputeEffectiveFlags_DB_CrowdSecExternal
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.790ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.115ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.082ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.068ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestComputeEffectiveFlags_DB_CrowdSecExternal (0.01s)
=== RUN TestComputeEffectiveFlags_DB_CrowdSecUnknown
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[0.991ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.114ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.072ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.051ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestComputeEffectiveFlags_DB_CrowdSecUnknown (0.00s)
=== RUN TestComputeEffectiveFlags_DB_CrowdSecLocal
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[2.212ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.272ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.081ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.093ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestComputeEffectiveFlags_DB_CrowdSecLocal (0.00s)
=== RUN TestComputeEffectiveFlags_DB_ACLTrueAndFalse
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[1.074ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.084ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.075ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:598 no such table: security_configs
[0.054ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.101ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.081ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestComputeEffectiveFlags_DB_ACLTrueAndFalse (0.01s)
=== RUN TestComputeEffectiveFlags_DB_WAFMonitor
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.178ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.121ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.098ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestComputeEffectiveFlags_DB_WAFMonitor (0.01s)
=== RUN TestManager_ApplyConfig_WAFMonitor
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:239 record not found
[0.056ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.acme_email" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:246 record not found
[0.055ms] [rows:0] SELECT * FROM `settings` WHERE key = "caddy.ssl_provider" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:627 record not found
[0.054ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:629 record not found
[0.080ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:00 /projects/Charon/backend/internal/caddy/manager.go:634 record not found
[0.061ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.acl.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestManager_ApplyConfig_WAFMonitor (0.04s)
=== RUN TestNormalizeAdvancedConfig_MapWithNestedHandles
--- PASS: TestNormalizeAdvancedConfig_MapWithNestedHandles (0.00s)
=== RUN TestNormalizeAdvancedConfig_ArrayTopLevel
--- PASS: TestNormalizeAdvancedConfig_ArrayTopLevel (0.00s)
=== RUN TestNormalizeAdvancedConfig_DefaultPrimitives
--- PASS: TestNormalizeAdvancedConfig_DefaultPrimitives (0.00s)
=== RUN TestNormalizeAdvancedConfig_CoerceNonStandardTypes
--- PASS: TestNormalizeAdvancedConfig_CoerceNonStandardTypes (0.00s)
=== RUN TestNormalizeAdvancedConfig_JSONRoundtrip
--- PASS: TestNormalizeAdvancedConfig_JSONRoundtrip (0.00s)
=== RUN TestNormalizeAdvancedConfig_TopLevelHeaders
--- PASS: TestNormalizeAdvancedConfig_TopLevelHeaders (0.00s)
=== RUN TestNormalizeAdvancedConfig_HeadersAlreadyArray
--- PASS: TestNormalizeAdvancedConfig_HeadersAlreadyArray (0.00s)
=== RUN TestNormalizeAdvancedConfig_MapWithTopLevelHandle
--- PASS: TestNormalizeAdvancedConfig_MapWithTopLevelHandle (0.00s)
=== RUN TestReverseProxyHandler_PlexAndOthers
--- PASS: TestReverseProxyHandler_PlexAndOthers (0.00s)
=== RUN TestReverseProxyHandler_WebSocketHeaders
--- PASS: TestReverseProxyHandler_WebSocketHeaders (0.00s)
=== RUN TestReverseProxyHandler_StandardProxyHeadersAlwaysSet
--- PASS: TestReverseProxyHandler_StandardProxyHeadersAlwaysSet (0.00s)
=== RUN TestReverseProxyHandler_ApplicationSpecificHeaders
--- PASS: TestReverseProxyHandler_ApplicationSpecificHeaders (0.00s)
=== RUN TestReverseProxyHandler_WebSocketWithApplication
--- PASS: TestReverseProxyHandler_WebSocketWithApplication (0.00s)
=== RUN TestReverseProxyHandler_FeatureFlagDisabled
--- PASS: TestReverseProxyHandler_FeatureFlagDisabled (0.00s)
=== RUN TestReverseProxyHandler_XForwardedForNotDuplicated
--- PASS: TestReverseProxyHandler_XForwardedForNotDuplicated (0.00s)
=== RUN TestReverseProxyHandler_TrustedProxiesConfiguration
--- PASS: TestReverseProxyHandler_TrustedProxiesConfiguration (0.00s)
=== RUN TestHandlers
--- PASS: TestHandlers (0.00s)
=== RUN TestReverseProxyHandler_NoWebSocket
--- PASS: TestReverseProxyHandler_NoWebSocket (0.00s)
=== RUN TestReverseProxyHandler_WithWebSocket
--- PASS: TestReverseProxyHandler_WithWebSocket (0.00s)
=== RUN TestReverseProxyHandler_StandardHeaders
--- PASS: TestReverseProxyHandler_StandardHeaders (0.00s)
=== RUN TestReverseProxyHandler_Plex
--- PASS: TestReverseProxyHandler_Plex (0.00s)
=== RUN TestReverseProxyHandler_PlexWithoutStandardHeaders
--- PASS: TestReverseProxyHandler_PlexWithoutStandardHeaders (0.00s)
=== RUN TestReverseProxyHandler_Jellyfin
--- PASS: TestReverseProxyHandler_Jellyfin (0.00s)
=== RUN TestReverseProxyHandler_JellyfinWithoutStandardHeaders
--- PASS: TestReverseProxyHandler_JellyfinWithoutStandardHeaders (0.00s)
=== RUN TestReverseProxyHandler_Emby
--- PASS: TestReverseProxyHandler_Emby (0.00s)
=== RUN TestReverseProxyHandler_HomeAssistant
--- PASS: TestReverseProxyHandler_HomeAssistant (0.00s)
=== RUN TestReverseProxyHandler_Nextcloud
--- PASS: TestReverseProxyHandler_Nextcloud (0.00s)
=== RUN TestReverseProxyHandler_Vaultwarden
--- PASS: TestReverseProxyHandler_Vaultwarden (0.00s)
=== RUN TestReverseProxyHandler_UnknownApplication
--- PASS: TestReverseProxyHandler_UnknownApplication (0.00s)
=== RUN TestReverseProxyHandler_NoHeaders
--- PASS: TestReverseProxyHandler_NoHeaders (0.00s)
=== RUN TestHeaderHandler_EmptyHeaders
--- PASS: TestHeaderHandler_EmptyHeaders (0.00s)
=== RUN TestHeaderHandler_MultipleHeaders
--- PASS: TestHeaderHandler_MultipleHeaders (0.00s)
=== RUN TestValidate_NilConfig
--- PASS: TestValidate_NilConfig (0.00s)
=== RUN TestValidateHandler_MissingHandlerField
--- PASS: TestValidateHandler_MissingHandlerField (0.00s)
=== RUN TestValidateHandler_UnknownHandlerAllowed
--- PASS: TestValidateHandler_UnknownHandlerAllowed (0.00s)
=== RUN TestValidateHandler_FileServerAndStaticResponseAllowed
--- PASS: TestValidateHandler_FileServerAndStaticResponseAllowed (0.00s)
=== RUN TestValidateRoute_InvalidHandler
--- PASS: TestValidateRoute_InvalidHandler (0.00s)
=== RUN TestValidateListenAddr_InvalidHostName
--- PASS: TestValidateListenAddr_InvalidHostName (0.00s)
=== RUN TestValidateListenAddr_InvalidPortNonNumeric
--- PASS: TestValidateListenAddr_InvalidPortNonNumeric (0.00s)
=== RUN TestValidate_MarshalError
--- PASS: TestValidate_MarshalError (0.00s)
=== RUN TestValidate_EmptyConfig
--- PASS: TestValidate_EmptyConfig (0.00s)
=== RUN TestValidate_ValidConfig
--- PASS: TestValidate_ValidConfig (0.00s)
=== RUN TestValidate_DuplicateHosts
--- PASS: TestValidate_DuplicateHosts (0.00s)
=== RUN TestValidate_NoListenAddresses
--- PASS: TestValidate_NoListenAddresses (0.00s)
=== RUN TestValidate_InvalidPort
--- PASS: TestValidate_InvalidPort (0.00s)
=== RUN TestValidate_NoHandlers
--- PASS: TestValidate_NoHandlers (0.00s)
=== RUN TestValidateListenAddr
=== RUN TestValidateListenAddr/Valid
=== RUN TestValidateListenAddr/ValidIP
=== RUN TestValidateListenAddr/ValidTCP
=== RUN TestValidateListenAddr/ValidUDP
=== RUN TestValidateListenAddr/InvalidFormat
=== RUN TestValidateListenAddr/InvalidPort
=== RUN TestValidateListenAddr/InvalidPortNegative
=== RUN TestValidateListenAddr/InvalidIP
--- PASS: TestValidateListenAddr (0.00s)
--- PASS: TestValidateListenAddr/Valid (0.00s)
--- PASS: TestValidateListenAddr/ValidIP (0.00s)
--- PASS: TestValidateListenAddr/ValidTCP (0.00s)
--- PASS: TestValidateListenAddr/ValidUDP (0.00s)
--- PASS: TestValidateListenAddr/InvalidFormat (0.00s)
--- PASS: TestValidateListenAddr/InvalidPort (0.00s)
--- PASS: TestValidateListenAddr/InvalidPortNegative (0.00s)
--- PASS: TestValidateListenAddr/InvalidIP (0.00s)
=== RUN TestValidateReverseProxy
=== RUN TestValidateReverseProxy/Valid
=== RUN TestValidateReverseProxy/MissingUpstreams
=== RUN TestValidateReverseProxy/EmptyUpstreams
=== RUN TestValidateReverseProxy/MissingDial
=== RUN TestValidateReverseProxy/InvalidDial
--- PASS: TestValidateReverseProxy (0.00s)
--- PASS: TestValidateReverseProxy/Valid (0.00s)
--- PASS: TestValidateReverseProxy/MissingUpstreams (0.00s)
--- PASS: TestValidateReverseProxy/EmptyUpstreams (0.00s)
--- PASS: TestValidateReverseProxy/MissingDial (0.00s)
--- PASS: TestValidateReverseProxy/InvalidDial (0.00s)
PASS
coverage: 98.7% of statements
ok github.com/Wikid82/charon/backend/internal/caddy (cached) coverage: 98.7% of statements
=== RUN TestIsEnabled_ConfigTrue
--- PASS: TestIsEnabled_ConfigTrue (0.00s)
=== RUN TestIsEnabled_WAFModeEnabled
--- PASS: TestIsEnabled_WAFModeEnabled (0.00s)
=== RUN TestIsEnabled_ACLModeEnabled
--- PASS: TestIsEnabled_ACLModeEnabled (0.00s)
=== RUN TestIsEnabled_RateLimitModeEnabled
--- PASS: TestIsEnabled_RateLimitModeEnabled (0.00s)
=== RUN TestIsEnabled_CrowdSecModeLocal
--- PASS: TestIsEnabled_CrowdSecModeLocal (0.00s)
=== RUN TestIsEnabled_DBSetting_FeatureFlag
--- PASS: TestIsEnabled_DBSetting_FeatureFlag (0.01s)
=== RUN TestIsEnabled_DBSetting_LegacyKey
2026/01/10 02:17:04 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.095ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestIsEnabled_DBSetting_LegacyKey (0.01s)
=== RUN TestIsEnabled_DBSetting_FeatureFlagTakesPrecedence
--- PASS: TestIsEnabled_DBSetting_FeatureFlagTakesPrecedence (0.00s)
=== RUN TestIsEnabled_DBSettingCaseInsensitive
--- PASS: TestIsEnabled_DBSettingCaseInsensitive (0.00s)
=== RUN TestIsEnabled_DBSettingFalse
--- PASS: TestIsEnabled_DBSettingFalse (0.00s)
=== RUN TestIsEnabled_DefaultTrue
--- PASS: TestIsEnabled_DefaultTrue (0.00s)
=== RUN TestMiddleware_WAFEnabledTracksMetrics
--- PASS: TestMiddleware_WAFEnabledTracksMetrics (0.01s)
=== RUN TestMiddleware_ACLBlocksClientIP
2026/01/10 02:17:04 /projects/Charon/backend/internal/services/security_notification_service.go:32 no such table: notification_configs
[3.914ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
--- PASS: TestMiddleware_ACLBlocksClientIP (0.01s)
=== RUN TestMiddleware_ACLAllowsClientIP
--- PASS: TestMiddleware_ACLAllowsClientIP (0.01s)
=== RUN TestMiddleware_NotEnabledSkips
2026/01/10 02:17:04 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.062ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
2026/01/10 02:17:04 /projects/Charon/backend/internal/cerberus/cerberus.go:61 record not found
[0.052ms] [rows:0] SELECT * FROM `settings` WHERE key = "security.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestMiddleware_NotEnabledSkips (0.01s)
=== RUN TestMiddleware_WAFPassesWithNoPayload
--- PASS: TestMiddleware_WAFPassesWithNoPayload (0.01s)
=== RUN TestMiddleware_WAFMonitorLogsButDoesNotBlock
--- PASS: TestMiddleware_WAFMonitorLogsButDoesNotBlock (0.02s)
=== RUN TestMiddleware_ACLDisabledDoesNotBlock
--- PASS: TestMiddleware_ACLDisabledDoesNotBlock (0.01s)
=== RUN TestCerberus_IsEnabled_ConfigTrue
--- PASS: TestCerberus_IsEnabled_ConfigTrue (0.00s)
=== RUN TestCerberus_IsEnabled_DBSetting
--- PASS: TestCerberus_IsEnabled_DBSetting (0.00s)
=== RUN TestCerberus_IsEnabled_Disabled
cerberus_test.go:68: cfg: {CrowdSecMode: CrowdSecAPIURL: CrowdSecAPIKey: CrowdSecConfigDir: WAFMode: RateLimitMode: ACLMode: CerberusEnabled:false}
cerberus_test.go:69: IsEnabled() -> false
--- PASS: TestCerberus_IsEnabled_Disabled (0.00s)
=== RUN TestCerberus_IsEnabled_CrowdSecLocal
--- PASS: TestCerberus_IsEnabled_CrowdSecLocal (0.00s)
=== RUN TestCerberus_IsEnabled_WAFEnabled
--- PASS: TestCerberus_IsEnabled_WAFEnabled (0.00s)
=== RUN TestCerberus_IsEnabled_RateLimitEnabled
--- PASS: TestCerberus_IsEnabled_RateLimitEnabled (0.00s)
=== RUN TestCerberus_IsEnabled_ACLEnabled
--- PASS: TestCerberus_IsEnabled_ACLEnabled (0.00s)
=== RUN TestCerberus_IsEnabled_LegacySetting
2026/01/10 02:17:04 /projects/Charon/backend/internal/cerberus/cerberus.go:57 record not found
[0.149ms] [rows:0] SELECT * FROM `settings` WHERE key = "feature.cerberus.enabled" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestCerberus_IsEnabled_LegacySetting (0.00s)
=== RUN TestCerberus_Middleware_Disabled
--- PASS: TestCerberus_Middleware_Disabled (0.00s)
=== RUN TestCerberus_Middleware_WAFEnabled
--- PASS: TestCerberus_Middleware_WAFEnabled (0.01s)
=== RUN TestCerberus_Middleware_ACLEnabled_NoAccessLists
--- PASS: TestCerberus_Middleware_ACLEnabled_NoAccessLists (0.01s)
=== RUN TestCerberus_Middleware_ACLEnabled_DisabledList
--- PASS: TestCerberus_Middleware_ACLEnabled_DisabledList (0.01s)
=== RUN TestCerberus_Middleware_ACLEnabled_Blocked
2026/01/10 02:17:04 /projects/Charon/backend/internal/services/security_notification_service.go:32 no such table: notification_configs
[3.089ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
--- PASS: TestCerberus_Middleware_ACLEnabled_Blocked (0.01s)
=== RUN TestCerberus_Middleware_CrowdSecLocal
--- PASS: TestCerberus_Middleware_CrowdSecLocal (0.01s)
PASS
coverage: 100.0% of statements
ok github.com/Wikid82/charon/backend/internal/cerberus (cached) coverage: 100.0% of statements
=== RUN TestLoad
--- PASS: TestLoad (0.00s)
=== RUN TestLoad_Defaults
--- PASS: TestLoad_Defaults (0.00s)
=== RUN TestLoad_CharonPrefersOverCPM
--- PASS: TestLoad_CharonPrefersOverCPM (0.00s)
=== RUN TestLoad_Error
--- PASS: TestLoad_Error (0.00s)
=== RUN TestGetEnvAny
--- PASS: TestGetEnvAny (0.00s)
=== RUN TestLoad_SecurityConfig
--- PASS: TestLoad_SecurityConfig (0.00s)
=== RUN TestLoad_DatabasePathError
--- PASS: TestLoad_DatabasePathError (0.00s)
=== RUN TestLoad_ACMEStaging
--- PASS: TestLoad_ACMEStaging (0.00s)
=== RUN TestLoad_DebugMode
--- PASS: TestLoad_DebugMode (0.00s)
PASS
coverage: 100.0% of statements
ok github.com/Wikid82/charon/backend/internal/config (cached) coverage: 100.0% of statements
=== RUN TestConsoleEnrollSuccess
time="2026-01-10T02:17:06Z" level=info msg="registering with crowdsec capi"
2026/01/10 02:17:06 /projects/Charon/backend/internal/crowdsec/console_enroll.go:327 record not found
[0.126ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
time="2026-01-10T02:17:06Z" level=info msg="starting crowdsec console enrollment" agent=agent-one config= correlation_id=ed782206-e7ca-420b-b94f-8fc8e147de23 force=false tenant=tenant-a
time="2026-01-10T02:17:06Z" level=info msg="crowdsec console enrollment request sent - pending acceptance on crowdsec.net" agent=agent-one correlation_id=ed782206-e7ca-420b-b94f-8fc8e147de23 tenant=tenant-a
--- PASS: TestConsoleEnrollSuccess (0.01s)
=== RUN TestConsoleEnrollFailureRedactsSecret
time="2026-01-10T02:17:06Z" level=info msg="registering with crowdsec capi"
2026/01/10 02:17:06 /projects/Charon/backend/internal/crowdsec/console_enroll.go:327 record not found
[0.098ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
time="2026-01-10T02:17:06Z" level=info msg="starting crowdsec console enrollment" agent=agent config= correlation_id=0892af32-2308-4d12-9c9d-773e6b81216c force=false tenant=tenant
time="2026-01-10T02:17:06Z" level=warning msg="crowdsec console enrollment failed" correlation_id=0892af32-2308-4d12-9c9d-773e6b81216c error="bad key <redacted>" output="invalid <redacted>" tenant=tenant
--- PASS: TestConsoleEnrollFailureRedactsSecret (0.01s)
=== RUN TestConsoleEnrollIdempotentWhenAlreadyEnrolled
time="2026-01-10T02:17:06Z" level=info msg="registering with crowdsec capi"
2026/01/10 02:17:06 /projects/Charon/backend/internal/crowdsec/console_enroll.go:327 record not found
[0.114ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
time="2026-01-10T02:17:06Z" level=info msg="starting crowdsec console enrollment" agent=agent config= correlation_id=7deabff7-eca2-4211-884e-f699e7f87a70 force=false tenant=tenant
time="2026-01-10T02:17:06Z" level=info msg="crowdsec console enrollment request sent - pending acceptance on crowdsec.net" agent=agent correlation_id=7deabff7-eca2-4211-884e-f699e7f87a70 tenant=tenant
time="2026-01-10T02:17:06Z" level=info msg="registering with crowdsec capi"
time="2026-01-10T02:17:06Z" level=info msg="console enrollment skipped: already enrolled or pending acceptance - use force=true to re-enroll" agent_name=agent status=pending_acceptance tenant=tenant
--- PASS: TestConsoleEnrollIdempotentWhenAlreadyEnrolled (0.01s)
=== RUN TestConsoleEnrollBlockedWhenInProgress
time="2026-01-10T02:17:06Z" level=info msg="registering with crowdsec capi"
--- PASS: TestConsoleEnrollBlockedWhenInProgress (0.01s)
=== RUN TestConsoleEnrollNormalizesFullCommand
time="2026-01-10T02:17:06Z" level=info msg="registering with crowdsec capi"
2026/01/10 02:17:06 /projects/Charon/backend/internal/crowdsec/console_enroll.go:327 record not found
[0.125ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
time="2026-01-10T02:17:06Z" level=info msg="starting crowdsec console enrollment" agent=agent config= correlation_id=4caeb337-bfc6-4fd1-ad6a-b2bae08fb89c force=false tenant=tenant
time="2026-01-10T02:17:06Z" level=info msg="crowdsec console enrollment request sent - pending acceptance on crowdsec.net" agent=agent correlation_id=4caeb337-bfc6-4fd1-ad6a-b2bae08fb89c tenant=tenant
--- PASS: TestConsoleEnrollNormalizesFullCommand (0.01s)
=== RUN TestConsoleEnrollRejectsUnsafeInput
--- PASS: TestConsoleEnrollRejectsUnsafeInput (0.01s)
=== RUN TestConsoleEnrollPassesTenantAsTags
time="2026-01-10T02:17:06Z" level=info msg="registering with crowdsec capi"
2026/01/10 02:17:06 /projects/Charon/backend/internal/crowdsec/console_enroll.go:327 record not found
[0.105ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
time="2026-01-10T02:17:06Z" level=info msg="starting crowdsec console enrollment" agent=agent-one config= correlation_id=74dd0030-7778-437b-b72d-b780578102b4 force=false tenant=some-tenant-id
time="2026-01-10T02:17:06Z" level=info msg="crowdsec console enrollment request sent - pending acceptance on crowdsec.net" agent=agent-one correlation_id=74dd0030-7778-437b-b72d-b780578102b4 tenant=some-tenant-id
--- PASS: TestConsoleEnrollPassesTenantAsTags (0.01s)
=== RUN TestConsoleEnrollNoTenantOmitsTags
time="2026-01-10T02:17:06Z" level=info msg="registering with crowdsec capi"
2026/01/10 02:17:06 /projects/Charon/backend/internal/crowdsec/console_enroll.go:327 record not found
[0.092ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
time="2026-01-10T02:17:06Z" level=info msg="starting crowdsec console enrollment" agent=agent-one config= correlation_id=55b45045-c01d-493d-be66-9f6abd028810 force=false tenant=
time="2026-01-10T02:17:06Z" level=info msg="crowdsec console enrollment request sent - pending acceptance on crowdsec.net" agent=agent-one correlation_id=55b45045-c01d-493d-be66-9f6abd028810 tenant=
--- PASS: TestConsoleEnrollNoTenantOmitsTags (0.01s)
=== RUN TestConsoleEnrollPassesForceAsOverwrite
time="2026-01-10T02:17:06Z" level=info msg="registering with crowdsec capi"
2026/01/10 02:17:06 /projects/Charon/backend/internal/crowdsec/console_enroll.go:327 record not found
[0.116ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
time="2026-01-10T02:17:06Z" level=info msg="starting crowdsec console enrollment" agent=agent-one config= correlation_id=4e911619-d08f-4515-8175-9568e2ab1387 force=true tenant=
time="2026-01-10T02:17:06Z" level=info msg="crowdsec console enrollment request sent - pending acceptance on crowdsec.net" agent=agent-one correlation_id=4e911619-d08f-4515-8175-9568e2ab1387 tenant=
--- PASS: TestConsoleEnrollPassesForceAsOverwrite (0.01s)
=== RUN TestConsoleEnrollNoForceOmitsOverwrite
time="2026-01-10T02:17:06Z" level=info msg="registering with crowdsec capi"
2026/01/10 02:17:06 /projects/Charon/backend/internal/crowdsec/console_enroll.go:327 record not found
[0.104ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
time="2026-01-10T02:17:06Z" level=info msg="starting crowdsec console enrollment" agent=agent-one config= correlation_id=7a445029-c21f-4ac6-b265-2eccc0e6b9c0 force=false tenant=
time="2026-01-10T02:17:06Z" level=info msg="crowdsec console enrollment request sent - pending acceptance on crowdsec.net" agent=agent-one correlation_id=7a445029-c21f-4ac6-b265-2eccc0e6b9c0 tenant=
--- PASS: TestConsoleEnrollNoForceOmitsOverwrite (0.01s)
=== RUN TestConsoleEnrollWithTenantAndForce
time="2026-01-10T02:17:06Z" level=info msg="registering with crowdsec capi"
2026/01/10 02:17:06 /projects/Charon/backend/internal/crowdsec/console_enroll.go:327 record not found
[0.079ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
time="2026-01-10T02:17:06Z" level=info msg="starting crowdsec console enrollment" agent=agent-one config= correlation_id=915fc0c4-36f4-4008-aef1-658e49da6714 force=true tenant=my-tenant
time="2026-01-10T02:17:06Z" level=info msg="crowdsec console enrollment request sent - pending acceptance on crowdsec.net" agent=agent-one correlation_id=915fc0c4-36f4-4008-aef1-658e49da6714 tenant=my-tenant
--- PASS: TestConsoleEnrollWithTenantAndForce (0.01s)
=== RUN TestSecureCommandExecutorExecuteWithEnv
=== RUN TestSecureCommandExecutorExecuteWithEnv/executes_command_successfully
=== RUN TestSecureCommandExecutorExecuteWithEnv/passes_environment_variables
=== RUN TestSecureCommandExecutorExecuteWithEnv/handles_empty_env_map
=== RUN TestSecureCommandExecutorExecuteWithEnv/handles_command_failure
=== RUN TestSecureCommandExecutorExecuteWithEnv/handles_context_timeout
--- PASS: TestSecureCommandExecutorExecuteWithEnv (0.01s)
--- PASS: TestSecureCommandExecutorExecuteWithEnv/executes_command_successfully (0.00s)
--- PASS: TestSecureCommandExecutorExecuteWithEnv/passes_environment_variables (0.00s)
--- PASS: TestSecureCommandExecutorExecuteWithEnv/handles_empty_env_map (0.00s)
--- PASS: TestSecureCommandExecutorExecuteWithEnv/handles_command_failure (0.00s)
--- PASS: TestSecureCommandExecutorExecuteWithEnv/handles_context_timeout (0.00s)
=== RUN TestFormatEnv
=== RUN TestFormatEnv/formats_single_env_var
=== RUN TestFormatEnv/formats_multiple_env_vars
=== RUN TestFormatEnv/handles_empty_map
=== RUN TestFormatEnv/handles_nil_map
=== RUN TestFormatEnv/handles_special_characters
--- PASS: TestFormatEnv (0.00s)
--- PASS: TestFormatEnv/formats_single_env_var (0.00s)
--- PASS: TestFormatEnv/formats_multiple_env_vars (0.00s)
--- PASS: TestFormatEnv/handles_empty_map (0.00s)
--- PASS: TestFormatEnv/handles_nil_map (0.00s)
--- PASS: TestFormatEnv/handles_special_characters (0.00s)
=== RUN TestConsoleEnrollmentStatus
=== RUN TestConsoleEnrollmentStatus/returns_not_enrolled_for_new_service
2026/01/10 02:17:06 /projects/Charon/backend/internal/crowdsec/console_enroll.go:327 record not found
[0.077ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
=== RUN TestConsoleEnrollmentStatus/returns_pending_acceptance_status_after_enrollment
time="2026-01-10T02:17:06Z" level=info msg="registering with crowdsec capi"
2026/01/10 02:17:06 /projects/Charon/backend/internal/crowdsec/console_enroll.go:327 record not found
[0.097ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
time="2026-01-10T02:17:06Z" level=info msg="starting crowdsec console enrollment" agent=test-agent config= correlation_id=52fce0c6-2ff8-4cc4-afc7-a8db06d702f5 force=false tenant=
time="2026-01-10T02:17:06Z" level=info msg="crowdsec console enrollment request sent - pending acceptance on crowdsec.net" agent=test-agent correlation_id=52fce0c6-2ff8-4cc4-afc7-a8db06d702f5 tenant=
=== RUN TestConsoleEnrollmentStatus/returns_failed_status_after_failed_enrollment
time="2026-01-10T02:17:06Z" level=info msg="registering with crowdsec capi"
2026/01/10 02:17:06 /projects/Charon/backend/internal/crowdsec/console_enroll.go:327 record not found
[0.116ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
time="2026-01-10T02:17:06Z" level=info msg="starting crowdsec console enrollment" agent=test-agent config= correlation_id=5a7b3017-86c9-4975-8525-afe1029750c1 force=false tenant=
time="2026-01-10T02:17:06Z" level=warning msg="crowdsec console enrollment failed" correlation_id=5a7b3017-86c9-4975-8525-afe1029750c1 error="enroll failed" output=error tenant=
--- PASS: TestConsoleEnrollmentStatus (0.02s)
--- PASS: TestConsoleEnrollmentStatus/returns_not_enrolled_for_new_service (0.00s)
--- PASS: TestConsoleEnrollmentStatus/returns_pending_acceptance_status_after_enrollment (0.00s)
--- PASS: TestConsoleEnrollmentStatus/returns_failed_status_after_failed_enrollment (0.01s)
=== RUN TestDeriveKey
=== RUN TestDeriveKey/derives_consistent_key
=== RUN TestDeriveKey/derives_different_keys_for_different_secrets
=== RUN TestDeriveKey/uses_default_for_empty_secret
--- PASS: TestDeriveKey (0.00s)
--- PASS: TestDeriveKey/derives_consistent_key (0.00s)
--- PASS: TestDeriveKey/derives_different_keys_for_different_secrets (0.00s)
--- PASS: TestDeriveKey/uses_default_for_empty_secret (0.00s)
=== RUN TestNormalizeEnrollmentKey
=== RUN TestNormalizeEnrollmentKey/valid_raw_key
=== RUN TestNormalizeEnrollmentKey/full_command_with_sudo
=== RUN TestNormalizeEnrollmentKey/full_command_without_sudo
=== RUN TestNormalizeEnrollmentKey/key_with_whitespace
=== RUN TestNormalizeEnrollmentKey/empty_key
=== RUN TestNormalizeEnrollmentKey/only_whitespace
=== RUN TestNormalizeEnrollmentKey/invalid_format
=== RUN TestNormalizeEnrollmentKey/injection_attempt
--- PASS: TestNormalizeEnrollmentKey (0.00s)
--- PASS: TestNormalizeEnrollmentKey/valid_raw_key (0.00s)
--- PASS: TestNormalizeEnrollmentKey/full_command_with_sudo (0.00s)
--- PASS: TestNormalizeEnrollmentKey/full_command_without_sudo (0.00s)
--- PASS: TestNormalizeEnrollmentKey/key_with_whitespace (0.00s)
--- PASS: TestNormalizeEnrollmentKey/empty_key (0.00s)
--- PASS: TestNormalizeEnrollmentKey/only_whitespace (0.00s)
--- PASS: TestNormalizeEnrollmentKey/invalid_format (0.00s)
--- PASS: TestNormalizeEnrollmentKey/injection_attempt (0.00s)
=== RUN TestRedactSecret
=== RUN TestRedactSecret/redacts_secret_from_message
=== RUN TestRedactSecret/handles_empty_secret
=== RUN TestRedactSecret/handles_secret_not_in_message
=== RUN TestRedactSecret/redacts_multiple_occurrences
--- PASS: TestRedactSecret (0.00s)
--- PASS: TestRedactSecret/redacts_secret_from_message (0.00s)
--- PASS: TestRedactSecret/handles_empty_secret (0.00s)
--- PASS: TestRedactSecret/handles_secret_not_in_message (0.00s)
--- PASS: TestRedactSecret/redacts_multiple_occurrences (0.00s)
=== RUN TestExtractCscliErrorMessage
=== RUN TestExtractCscliErrorMessage/msg_format_with_quotes
=== RUN TestExtractCscliErrorMessage/ERRO_format_with_timestamp
=== RUN TestExtractCscliErrorMessage/plain_error_message
=== RUN TestExtractCscliErrorMessage/multiline_with_error_in_middle
=== RUN TestExtractCscliErrorMessage/empty_output
=== RUN TestExtractCscliErrorMessage/whitespace_only
=== RUN TestExtractCscliErrorMessage/no_recognizable_pattern_-_returns_first_line
=== RUN TestExtractCscliErrorMessage/failed_keyword_detection
=== RUN TestExtractCscliErrorMessage/invalid_keyword_detection
=== RUN TestExtractCscliErrorMessage/complex_cscli_output_with_msg
--- PASS: TestExtractCscliErrorMessage (0.00s)
--- PASS: TestExtractCscliErrorMessage/msg_format_with_quotes (0.00s)
--- PASS: TestExtractCscliErrorMessage/ERRO_format_with_timestamp (0.00s)
--- PASS: TestExtractCscliErrorMessage/plain_error_message (0.00s)
--- PASS: TestExtractCscliErrorMessage/multiline_with_error_in_middle (0.00s)
--- PASS: TestExtractCscliErrorMessage/empty_output (0.00s)
--- PASS: TestExtractCscliErrorMessage/whitespace_only (0.00s)
--- PASS: TestExtractCscliErrorMessage/no_recognizable_pattern_-_returns_first_line (0.00s)
--- PASS: TestExtractCscliErrorMessage/failed_keyword_detection (0.00s)
--- PASS: TestExtractCscliErrorMessage/invalid_keyword_detection (0.00s)
--- PASS: TestExtractCscliErrorMessage/complex_cscli_output_with_msg (0.00s)
=== RUN TestEncryptDecrypt
=== RUN TestEncryptDecrypt/encrypts_and_decrypts_successfully
=== RUN TestEncryptDecrypt/handles_empty_string
=== RUN TestEncryptDecrypt/different_encryptions_produce_different_ciphertext
--- PASS: TestEncryptDecrypt (0.00s)
--- PASS: TestEncryptDecrypt/encrypts_and_decrypts_successfully (0.00s)
--- PASS: TestEncryptDecrypt/handles_empty_string (0.00s)
--- PASS: TestEncryptDecrypt/different_encryptions_produce_different_ciphertext (0.00s)
=== RUN TestCheckLAPIAvailable_Retries
--- PASS: TestCheckLAPIAvailable_Retries (4.00s)
=== RUN TestCheckLAPIAvailable_RetriesExhausted
--- PASS: TestCheckLAPIAvailable_RetriesExhausted (4.01s)
=== RUN TestCheckLAPIAvailable_FirstAttemptSuccess
--- PASS: TestCheckLAPIAvailable_FirstAttemptSuccess (0.01s)
=== RUN TestEnroll_RequiresLAPI
--- PASS: TestEnroll_RequiresLAPI (4.01s)
=== RUN TestConsoleEnrollService_ClearEnrollment
time="2026-01-10T02:17:18Z" level=info msg="clearing console enrollment state" previous_status=enrolled
--- PASS: TestConsoleEnrollService_ClearEnrollment (0.00s)
=== RUN TestConsoleEnrollService_ClearEnrollment_NoRecord
2026/01/10 02:17:18 /projects/Charon/backend/internal/crowdsec/console_enroll.go:355 record not found
[0.073ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
--- PASS: TestConsoleEnrollService_ClearEnrollment_NoRecord (0.00s)
=== RUN TestConsoleEnrollService_ClearEnrollment_NilDB
--- PASS: TestConsoleEnrollService_ClearEnrollment_NilDB (0.00s)
=== RUN TestConsoleEnrollService_ClearEnrollment_ThenReenroll
time="2026-01-10T02:17:18Z" level=info msg="registering with crowdsec capi"
2026/01/10 02:17:18 /projects/Charon/backend/internal/crowdsec/console_enroll.go:327 record not found
[0.087ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
time="2026-01-10T02:17:18Z" level=info msg="starting crowdsec console enrollment" agent=agent-one config= correlation_id=a1a86ed2-7fe3-4d42-a98c-fa439d219941 force=false tenant=
time="2026-01-10T02:17:18Z" level=info msg="crowdsec console enrollment request sent - pending acceptance on crowdsec.net" agent=agent-one correlation_id=a1a86ed2-7fe3-4d42-a98c-fa439d219941 tenant=
time="2026-01-10T02:17:18Z" level=info msg="clearing console enrollment state" previous_status=pending_acceptance
2026/01/10 02:17:18 /projects/Charon/backend/internal/crowdsec/console_enroll.go:327 record not found
[0.057ms] [rows:0] SELECT * FROM `crowdsec_console_enrollments` ORDER BY `crowdsec_console_enrollments`.`id` LIMIT 1
time="2026-01-10T02:17:18Z" level=info msg="registering with crowdsec capi"
time="2026-01-10T02:17:18Z" level=info msg="starting crowdsec console enrollment" agent=agent-two config= correlation_id=c2001970-5a34-40d1-9454-a2ac1d48c5b8 force=false tenant=
time="2026-01-10T02:17:18Z" level=info msg="crowdsec console enrollment request sent - pending acceptance on crowdsec.net" agent=agent-two correlation_id=c2001970-5a34-40d1-9454-a2ac1d48c5b8 tenant=
--- PASS: TestConsoleEnrollService_ClearEnrollment_ThenReenroll (0.01s)
=== RUN TestConsoleEnrollService_LogsWhenSkipped
time="2026-01-10T02:17:18Z" level=info msg="registering with crowdsec capi"
time="2026-01-10T02:17:18Z" level=info msg="console enrollment skipped: already enrolled or pending acceptance - use force=true to re-enroll" agent_name=test-agent status=enrolled tenant=test-tenant
--- PASS: TestConsoleEnrollService_LogsWhenSkipped (0.00s)
=== RUN TestConsoleEnrollService_LogsWhenSkipped_PendingAcceptance
time="2026-01-10T02:17:18Z" level=info msg="registering with crowdsec capi"
time="2026-01-10T02:17:18Z" level=info msg="console enrollment skipped: already enrolled or pending acceptance - use force=true to re-enroll" agent_name=test-agent status=pending_acceptance tenant=test-tenant
--- PASS: TestConsoleEnrollService_LogsWhenSkipped_PendingAcceptance (0.00s)
=== RUN TestConsoleEnrollService_ForceOverridesSkip
time="2026-01-10T02:17:18Z" level=info msg="registering with crowdsec capi"
time="2026-01-10T02:17:18Z" level=info msg="starting crowdsec console enrollment" agent=new-agent config= correlation_id=b0b9632b-d724-4339-a04b-171797fd2b39 force=true tenant=
time="2026-01-10T02:17:18Z" level=info msg="crowdsec console enrollment request sent - pending acceptance on crowdsec.net" agent=new-agent correlation_id=b0b9632b-d724-4339-a04b-171797fd2b39 tenant=
--- PASS: TestConsoleEnrollService_ForceOverridesSkip (0.00s)
=== RUN TestEnroll_InvalidAgentNameCharacters
--- PASS: TestEnroll_InvalidAgentNameCharacters (0.00s)
=== RUN TestEnroll_InvalidTenantNameCharacters
--- PASS: TestEnroll_InvalidTenantNameCharacters (0.00s)
=== RUN TestEnsureCAPIRegistered_StandardLayoutExists
--- PASS: TestEnsureCAPIRegistered_StandardLayoutExists (0.00s)
=== RUN TestEnsureCAPIRegistered_RegisterError
time="2026-01-10T02:17:18Z" level=info msg="registering with crowdsec capi"
--- PASS: TestEnsureCAPIRegistered_RegisterError (0.00s)
=== RUN TestFindConfigPath_StandardLayout
--- PASS: TestFindConfigPath_StandardLayout (0.00s)
=== RUN TestFindConfigPath_RootLayout
--- PASS: TestFindConfigPath_RootLayout (0.00s)
=== RUN TestFindConfigPath_NeitherExists
--- PASS: TestFindConfigPath_NeitherExists (0.00s)
=== RUN TestStatusFromModel_NilModel
--- PASS: TestStatusFromModel_NilModel (0.00s)
=== RUN TestNormalizeEnrollmentKey_InvalidCharacters
--- PASS: TestNormalizeEnrollmentKey_InvalidCharacters (0.00s)
=== RUN TestNormalizeEnrollmentKey_TooShort
--- PASS: TestNormalizeEnrollmentKey_TooShort (0.00s)
=== RUN TestNormalizeEnrollmentKey_NonMatchingFormat
--- PASS: TestNormalizeEnrollmentKey_NonMatchingFormat (0.00s)
=== RUN TestApplyWithOpenFileHandles
time="2026-01-10T02:17:18Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestApplyWithOpenFileHandles3946802142/001/test/preset/bundle.tgz cache_key=test/preset-1768011438 meta_path=/tmp/TestApplyWithOpenFileHandles3946802142/001/test/preset/metadata.json preview_path=/tmp/TestApplyWithOpenFileHandles3946802142/001/test/preset/preview.yaml slug=test/preset
time="2026-01-10T02:17:18Z" level=info msg="successfully loaded cached preset metadata" archive_path=/tmp/TestApplyWithOpenFileHandles3946802142/001/test/preset/bundle.tgz cache_key=test/preset-1768011438 slug=test/preset
--- PASS: TestApplyWithOpenFileHandles (0.02s)
=== RUN TestBackupPathOnlySetAfterSuccessfulBackup
=== RUN TestBackupPathOnlySetAfterSuccessfulBackup/backup_path_not_set_when_cache_missing
time="2026-01-10T02:17:18Z" level=warning msg="failed to load cached preset metadata" error="cache miss" slug=nonexistent/preset
time="2026-01-10T02:17:18Z" level=info msg="attempting to repull preset after cache load failure" error="load cache for nonexistent/preset: cache miss" slug=nonexistent/preset
time="2026-01-10T02:17:18Z" level=warning msg="hub index fetch failed, trying mirror" attempt=1 error="https://hub-data.crowdsec.net/api/index.json (status 403)" hub_index="https://hub-data.crowdsec.net/api/index.json"
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=true hub_index="https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json"
time="2026-01-10T02:17:19Z" level=warning msg="cache refresh failed; rolled back backup" backup_path=/tmp/TestBackupPathOnlySetAfterSuccessfulBackupbackup_path_not_set_w4106602953/002/crowdsec.backup.20260110-021718 error="load cache for nonexistent/preset: cache miss: refresh cache: preset not found in hub" slug=nonexistent/preset
=== RUN TestBackupPathOnlySetAfterSuccessfulBackup/backup_path_set_only_after_successful_backup
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestBackupPathOnlySetAfterSuccessfulBackupbackup_path_set_only_1030315152/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 meta_path=/tmp/TestBackupPathOnlySetAfterSuccessfulBackupbackup_path_set_only_1030315152/001/test/preset/metadata.json preview_path=/tmp/TestBackupPathOnlySetAfterSuccessfulBackupbackup_path_set_only_1030315152/001/test/preset/preview.yaml slug=test/preset
time="2026-01-10T02:17:19Z" level=info msg="successfully loaded cached preset metadata" archive_path=/tmp/TestBackupPathOnlySetAfterSuccessfulBackupbackup_path_set_only_1030315152/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 slug=test/preset
--- PASS: TestBackupPathOnlySetAfterSuccessfulBackup (1.24s)
--- PASS: TestBackupPathOnlySetAfterSuccessfulBackup/backup_path_not_set_when_cache_missing (1.24s)
--- PASS: TestBackupPathOnlySetAfterSuccessfulBackup/backup_path_set_only_after_successful_backup (0.01s)
=== RUN TestHubCacheStoreLoadAndExpire
=== PAUSE TestHubCacheStoreLoadAndExpire
=== RUN TestHubCacheRejectsBadSlug
=== PAUSE TestHubCacheRejectsBadSlug
=== RUN TestHubCacheListAndEvict
=== PAUSE TestHubCacheListAndEvict
=== RUN TestHubCacheTouchUpdatesTTL
=== PAUSE TestHubCacheTouchUpdatesTTL
=== RUN TestHubCachePreviewExistsAndSize
=== PAUSE TestHubCachePreviewExistsAndSize
=== RUN TestHubCacheExistsHonorsTTL
=== PAUSE TestHubCacheExistsHonorsTTL
=== RUN TestSanitizeSlugCases
=== PAUSE TestSanitizeSlugCases
=== RUN TestNewHubCacheRequiresBaseDir
=== PAUSE TestNewHubCacheRequiresBaseDir
=== RUN TestHubCacheTouchMissing
=== PAUSE TestHubCacheTouchMissing
=== RUN TestHubCacheTouchInvalidSlug
=== PAUSE TestHubCacheTouchInvalidSlug
=== RUN TestHubCacheStoreContextCanceled
=== PAUSE TestHubCacheStoreContextCanceled
=== RUN TestHubCacheLoadInvalidSlug
=== PAUSE TestHubCacheLoadInvalidSlug
=== RUN TestHubCacheExistsContextCanceled
=== PAUSE TestHubCacheExistsContextCanceled
=== RUN TestHubCacheListSkipsExpired
=== PAUSE TestHubCacheListSkipsExpired
=== RUN TestHubCacheEvictInvalidSlug
=== PAUSE TestHubCacheEvictInvalidSlug
=== RUN TestHubCacheListContextCanceled
=== PAUSE TestHubCacheListContextCanceled
=== RUN TestHubCacheTTL
=== PAUSE TestHubCacheTTL
=== RUN TestPullThenApplyFlow
hub_pull_apply_test.go:90: Step 1: Pulling preset
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="http://test.example.com/api/index.json"
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://test.example.com/test.tgz" fallback_used=false
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://test.example.com/test.yaml" fallback_used=false
time="2026-01-10T02:17:19Z" level=info msg="storing preset in cache" archive_size=158 etag=etag123 hub_endpoint="http://test.example.com/test.tgz" preview_size=24 slug=test/preset
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestPullThenApplyFlow2203214519/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 meta_path=/tmp/TestPullThenApplyFlow2203214519/001/test/preset/metadata.json preview_path=/tmp/TestPullThenApplyFlow2203214519/001/test/preset/preview.yaml slug=test/preset
time="2026-01-10T02:17:19Z" level=info msg="preset successfully cached" archive_path=/tmp/TestPullThenApplyFlow2203214519/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 preview_path=/tmp/TestPullThenApplyFlow2203214519/001/test/preset/preview.yaml slug=test/preset
hub_pull_apply_test.go:110: Step 2: Verifying cache can be loaded
hub_pull_apply_test.go:117: Step 3: Applying preset from cache
time="2026-01-10T02:17:19Z" level=info msg="successfully loaded cached preset metadata" archive_path=/tmp/TestPullThenApplyFlow2203214519/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 slug=test/preset
--- PASS: TestPullThenApplyFlow (0.01s)
=== RUN TestApplyRepullsOnCacheMissAfterCSCLIFailure
time="2026-01-10T02:17:19Z" level=warning msg="failed to load cached preset metadata" error="cache miss" slug=test/preset
time="2026-01-10T02:17:19Z" level=warning msg="cscli install failed; attempting cache fallback" error="install failed" slug=test/preset
time="2026-01-10T02:17:19Z" level=info msg="attempting to repull preset after cache load failure" error="load cache for test/preset: cache miss" slug=test/preset
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="http://test.example.com/api/index.json"
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://test.example.com/test/preset.tgz" fallback_used=false
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://test.example.com/test/preset.yaml" fallback_used=false
time="2026-01-10T02:17:19Z" level=info msg="storing preset in cache" archive_size=110 etag=e1 hub_endpoint="http://test.example.com/test/preset.tgz" preview_size=7 slug=test/preset
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestApplyRepullsOnCacheMissAfterCSCLIFailure1830341465/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 meta_path=/tmp/TestApplyRepullsOnCacheMissAfterCSCLIFailure1830341465/001/test/preset/metadata.json preview_path=/tmp/TestApplyRepullsOnCacheMissAfterCSCLIFailure1830341465/001/test/preset/preview.yaml slug=test/preset
time="2026-01-10T02:17:19Z" level=info msg="preset successfully cached" archive_path=/tmp/TestApplyRepullsOnCacheMissAfterCSCLIFailure1830341465/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 preview_path=/tmp/TestApplyRepullsOnCacheMissAfterCSCLIFailure1830341465/001/test/preset/preview.yaml slug=test/preset
--- PASS: TestApplyRepullsOnCacheMissAfterCSCLIFailure (0.01s)
=== RUN TestApplyRepullsOnCacheExpired
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestApplyRepullsOnCacheExpired748670146/001/expired/preset/bundle.tgz cache_key=expired/preset-1768011439 meta_path=/tmp/TestApplyRepullsOnCacheExpired748670146/001/expired/preset/metadata.json preview_path=/tmp/TestApplyRepullsOnCacheExpired748670146/001/expired/preset/preview.yaml slug=expired/preset
time="2026-01-10T02:17:19Z" level=warning msg="failed to load cached preset metadata" error="cache expired" slug=expired/preset
time="2026-01-10T02:17:19Z" level=info msg="attempting to repull preset after cache load failure" error="load cache for expired/preset: cache expired" slug=expired/preset
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="http://test.example.com/api/index.json"
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://test.example.com/expired/preset.tgz" fallback_used=false
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://test.example.com/expired/preset.yaml" fallback_used=false
time="2026-01-10T02:17:19Z" level=info msg="storing preset in cache" archive_size=112 etag=e2 hub_endpoint="http://test.example.com/expired/preset.tgz" preview_size=11 slug=expired/preset
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestApplyRepullsOnCacheExpired748670146/001/expired/preset/bundle.tgz cache_key=expired/preset-1768011439 meta_path=/tmp/TestApplyRepullsOnCacheExpired748670146/001/expired/preset/metadata.json preview_path=/tmp/TestApplyRepullsOnCacheExpired748670146/001/expired/preset/preview.yaml slug=expired/preset
time="2026-01-10T02:17:19Z" level=info msg="preset successfully cached" archive_path=/tmp/TestApplyRepullsOnCacheExpired748670146/001/expired/preset/bundle.tgz cache_key=expired/preset-1768011439 preview_path=/tmp/TestApplyRepullsOnCacheExpired748670146/001/expired/preset/preview.yaml slug=expired/preset
--- PASS: TestApplyRepullsOnCacheExpired (0.02s)
=== RUN TestPullAcceptsNamespacedIndexEntry
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="http://test.example.com/api/index.json"
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://test.example.com/crowdsecurity/bot-mitigation-essentials.tgz" fallback_used=false
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://test.example.com/crowdsecurity/bot-mitigation-essentials.yaml" fallback_used=false
time="2026-01-10T02:17:19Z" level=info msg="storing preset in cache" archive_size=114 etag=etag-bme hub_endpoint="http://test.example.com/crowdsecurity/bot-mitigation-essentials.tgz" preview_size=18 slug=bot-mitigation-essentials
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestPullAcceptsNamespacedIndexEntry586165543/001/bot-mitigation-essentials/bundle.tgz cache_key=bot-mitigation-essentials-1768011439 meta_path=/tmp/TestPullAcceptsNamespacedIndexEntry586165543/001/bot-mitigation-essentials/metadata.json preview_path=/tmp/TestPullAcceptsNamespacedIndexEntry586165543/001/bot-mitigation-essentials/preview.yaml slug=bot-mitigation-essentials
time="2026-01-10T02:17:19Z" level=info msg="preset successfully cached" archive_path=/tmp/TestPullAcceptsNamespacedIndexEntry586165543/001/bot-mitigation-essentials/bundle.tgz cache_key=bot-mitigation-essentials-1768011439 preview_path=/tmp/TestPullAcceptsNamespacedIndexEntry586165543/001/bot-mitigation-essentials/preview.yaml slug=bot-mitigation-essentials
--- PASS: TestPullAcceptsNamespacedIndexEntry (0.00s)
=== RUN TestHubFallbackToMirrorOnForbidden
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=1 error="http://primary.example.com/api/index.json (status 403)" hub_index="http://primary.example.com/api/index.json"
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=true hub_index="http://mirror.example.com/api/index.json"
time="2026-01-10T02:17:19Z" level=warning msg="hub fetch failed, attempting fallback" attempt=1 endpoint="http://primary.example.com/fallback/preset.tgz" error="http://primary.example.com/fallback/preset.tgz (status 403)"
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://mirror.example.com/fallback/preset.tgz" fallback_used=true
time="2026-01-10T02:17:19Z" level=warning msg="hub fetch failed, attempting fallback" attempt=1 endpoint="http://primary.example.com/fallback/preset.yaml" error="http://primary.example.com/fallback/preset.yaml (status 403)"
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://mirror.example.com/fallback/preset.yaml" fallback_used=true
time="2026-01-10T02:17:19Z" level=info msg="storing preset in cache" archive_size=104 etag=etag-mirror hub_endpoint="http://mirror.example.com/fallback/preset.tgz" preview_size=14 slug=fallback/preset
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestHubFallbackToMirrorOnForbidden3143303761/001/fallback/preset/bundle.tgz cache_key=fallback/preset-1768011439 meta_path=/tmp/TestHubFallbackToMirrorOnForbidden3143303761/001/fallback/preset/metadata.json preview_path=/tmp/TestHubFallbackToMirrorOnForbidden3143303761/001/fallback/preset/preview.yaml slug=fallback/preset
time="2026-01-10T02:17:19Z" level=info msg="preset successfully cached" archive_path=/tmp/TestHubFallbackToMirrorOnForbidden3143303761/001/fallback/preset/bundle.tgz cache_key=fallback/preset-1768011439 preview_path=/tmp/TestHubFallbackToMirrorOnForbidden3143303761/001/fallback/preset/preview.yaml slug=fallback/preset
--- PASS: TestHubFallbackToMirrorOnForbidden (0.01s)
=== RUN TestApplyWithoutPullFails
time="2026-01-10T02:17:19Z" level=warning msg="failed to load cached preset metadata" error="cache miss" slug=nonexistent/preset
time="2026-01-10T02:17:19Z" level=info msg="attempting to repull preset after cache load failure" error="load cache for nonexistent/preset: cache miss" slug=nonexistent/preset
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=1 error="http://test.example.com/api/index.json (status 500)" hub_index="http://test.example.com/api/index.json"
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=2 error="https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json (status 500)" hub_index="https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json"
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=3 error="https://raw.githubusercontent.com/crowdsecurity/hub/master/api/index.json (status 500)" hub_index="https://raw.githubusercontent.com/crowdsecurity/hub/master/api/index.json"
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=4 error="https://hub-data.crowdsec.net/api/index.json (status 500)" hub_index="https://hub-data.crowdsec.net/api/index.json"
time="2026-01-10T02:17:19Z" level=warning msg="cache refresh failed; rolled back backup" backup_path=/tmp/TestApplyWithoutPullFails1841293971/002.backup.20260110-021719 error="load cache for nonexistent/preset: cache miss: refresh cache: fetch hub index: http://test.example.com/api/index.json: http://test.example.com/api/index.json (status 500)\nhttps://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json: https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json (status 500)\nhttps://raw.githubusercontent.com/crowdsecurity/hub/master/api/index.json: https://raw.githubusercontent.com/crowdsecurity/hub/master/api/index.json (status 500)\nhttps://hub-data.crowdsec.net/api/index.json: https://hub-data.crowdsec.net/api/index.json (status 500)" slug=nonexistent/preset
--- PASS: TestApplyWithoutPullFails (0.00s)
=== RUN TestCacheExpiration
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestCacheExpiration2058278143/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 meta_path=/tmp/TestCacheExpiration2058278143/001/test/preset/metadata.json preview_path=/tmp/TestCacheExpiration2058278143/001/test/preset/preview.yaml slug=test/preset
--- PASS: TestCacheExpiration (0.01s)
=== RUN TestCacheListAfterPull
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="http://test.example.com/api/index.json"
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://test.example.com/preset1.tgz" fallback_used=false
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://test.example.com/preset1.yaml" fallback_used=false
time="2026-01-10T02:17:19Z" level=info msg="storing preset in cache" archive_size=105 etag=e1 hub_endpoint="http://test.example.com/preset1.tgz" preview_size=8 slug=preset1
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestCacheListAfterPull3507341671/001/preset1/bundle.tgz cache_key=preset1-1768011439 meta_path=/tmp/TestCacheListAfterPull3507341671/001/preset1/metadata.json preview_path=/tmp/TestCacheListAfterPull3507341671/001/preset1/preview.yaml slug=preset1
time="2026-01-10T02:17:19Z" level=info msg="preset successfully cached" archive_path=/tmp/TestCacheListAfterPull3507341671/001/preset1/bundle.tgz cache_key=preset1-1768011439 preview_path=/tmp/TestCacheListAfterPull3507341671/001/preset1/preview.yaml slug=preset1
--- PASS: TestCacheListAfterPull (0.01s)
=== RUN TestApplyReadsArchiveBeforeBackup
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestApplyReadsArchiveBeforeBackup1310230569/001/crowdsec/hub_cache/test/preset/bundle.tgz cache_key=test/preset-1768011439 meta_path=/tmp/TestApplyReadsArchiveBeforeBackup1310230569/001/crowdsec/hub_cache/test/preset/metadata.json preview_path=/tmp/TestApplyReadsArchiveBeforeBackup1310230569/001/crowdsec/hub_cache/test/preset/preview.yaml slug=test/preset
time="2026-01-10T02:17:19Z" level=info msg="successfully loaded cached preset metadata" archive_path=/tmp/TestApplyReadsArchiveBeforeBackup1310230569/001/crowdsec/hub_cache/test/preset/bundle.tgz cache_key=test/preset-1768011439 slug=test/preset
--- PASS: TestApplyReadsArchiveBeforeBackup (0.01s)
=== RUN TestFetchIndexParsesRawIndexFormat
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="http://example.com/api/index.json"
--- PASS: TestFetchIndexParsesRawIndexFormat (0.00s)
=== RUN TestFetchIndexPrefersCSCLI
=== PAUSE TestFetchIndexPrefersCSCLI
=== RUN TestFetchIndexFallbackHTTP
=== PAUSE TestFetchIndexFallbackHTTP
=== RUN TestFetchIndexHTTPRejectsRedirect
=== PAUSE TestFetchIndexHTTPRejectsRedirect
=== RUN TestFetchIndexHTTPRejectsHTML
=== PAUSE TestFetchIndexHTTPRejectsHTML
=== RUN TestFetchIndexHTTPFallsBackToDefaultHub
=== PAUSE TestFetchIndexHTTPFallsBackToDefaultHub
=== RUN TestFetchIndexFallsBackToMirrorOnForbidden
=== PAUSE TestFetchIndexFallsBackToMirrorOnForbidden
=== RUN TestPullCachesPreview
=== PAUSE TestPullCachesPreview
=== RUN TestApplyUsesCacheWhenCSCLIFails
=== PAUSE TestApplyUsesCacheWhenCSCLIFails
=== RUN TestApplyRollsBackOnBadArchive
=== PAUSE TestApplyRollsBackOnBadArchive
=== RUN TestApplyUsesCacheWhenCscliMissing
=== PAUSE TestApplyUsesCacheWhenCscliMissing
=== RUN TestPullReturnsCachedPreviewWithoutNetwork
=== PAUSE TestPullReturnsCachedPreviewWithoutNetwork
=== RUN TestPullEvictsExpiredCacheAndRefreshes
=== PAUSE TestPullEvictsExpiredCacheAndRefreshes
=== RUN TestPullFallsBackToArchivePreview
=== PAUSE TestPullFallsBackToArchivePreview
=== RUN TestPullFallsBackToMirrorArchiveOnForbidden
=== PAUSE TestPullFallsBackToMirrorArchiveOnForbidden
=== RUN TestFetchWithLimitRejectsLargePayload
=== PAUSE TestFetchWithLimitRejectsLargePayload
=== RUN TestExtractTarGzRejectsSymlink
=== PAUSE TestExtractTarGzRejectsSymlink
=== RUN TestExtractTarGzRejectsAbsolutePath
=== PAUSE TestExtractTarGzRejectsAbsolutePath
=== RUN TestFetchIndexHTTPError
=== PAUSE TestFetchIndexHTTPError
=== RUN TestPullValidatesSlugAndMissingPreset
=== PAUSE TestPullValidatesSlugAndMissingPreset
=== RUN TestFetchPreviewRequiresURL
=== PAUSE TestFetchPreviewRequiresURL
=== RUN TestFetchWithLimitRequiresClient
=== PAUSE TestFetchWithLimitRequiresClient
=== RUN TestRunCSCLIRejectsUnsafeSlug
=== PAUSE TestRunCSCLIRejectsUnsafeSlug
=== RUN TestApplyUsesCSCLISuccess
=== PAUSE TestApplyUsesCSCLISuccess
=== RUN TestFetchIndexCSCLIParseError
=== PAUSE TestFetchIndexCSCLIParseError
=== RUN TestFetchWithLimitStatusError
=== PAUSE TestFetchWithLimitStatusError
=== RUN TestApplyRollsBackWhenCacheMissing
=== PAUSE TestApplyRollsBackWhenCacheMissing
=== RUN TestNormalizeHubBaseURL
=== PAUSE TestNormalizeHubBaseURL
=== RUN TestBuildIndexURL
=== PAUSE TestBuildIndexURL
=== RUN TestUniqueStrings
=== PAUSE TestUniqueStrings
=== RUN TestFirstNonEmpty
=== PAUSE TestFirstNonEmpty
=== RUN TestCleanShellArg
=== PAUSE TestCleanShellArg
=== RUN TestHasCSCLI
=== PAUSE TestHasCSCLI
=== RUN TestFindPreviewFileFromArchive
=== PAUSE TestFindPreviewFileFromArchive
=== RUN TestApplyWithCopyBasedBackup
=== PAUSE TestApplyWithCopyBasedBackup
=== RUN TestBackupExistingHandlesDeviceBusy
=== PAUSE TestBackupExistingHandlesDeviceBusy
=== RUN TestCopyFile
=== PAUSE TestCopyFile
=== RUN TestCopyDir
=== PAUSE TestCopyDir
=== RUN TestFetchIndexHTTPAcceptsTextPlain
=== PAUSE TestFetchIndexHTTPAcceptsTextPlain
=== RUN TestValidateHubURL_ValidHTTPSProduction
=== PAUSE TestValidateHubURL_ValidHTTPSProduction
=== RUN TestValidateHubURL_InvalidSchemes
=== PAUSE TestValidateHubURL_InvalidSchemes
=== RUN TestValidateHubURL_LocalhostExceptions
=== PAUSE TestValidateHubURL_LocalhostExceptions
=== RUN TestValidateHubURL_UnknownDomainRejection
=== PAUSE TestValidateHubURL_UnknownDomainRejection
=== RUN TestValidateHubURL_HTTPRejectedForProduction
=== PAUSE TestValidateHubURL_HTTPRejectedForProduction
=== RUN TestBuildResourceURLs
=== PAUSE TestBuildResourceURLs
=== RUN TestParseRawIndex
=== PAUSE TestParseRawIndex
=== RUN TestFetchIndexHTTPFromURL_HTMLDetection
=== PAUSE TestFetchIndexHTTPFromURL_HTMLDetection
=== RUN TestHubService_Apply_ArchiveReadBeforeBackup
=== PAUSE TestHubService_Apply_ArchiveReadBeforeBackup
=== RUN TestHubService_Apply_CacheRefresh
=== PAUSE TestHubService_Apply_CacheRefresh
=== RUN TestHubService_Apply_RollbackOnExtractionFailure
=== PAUSE TestHubService_Apply_RollbackOnExtractionFailure
=== RUN TestCopyDirAndCopyFile
=== PAUSE TestCopyDirAndCopyFile
=== RUN TestEmptyDir
=== PAUSE TestEmptyDir
=== RUN TestExtractTarGz
=== PAUSE TestExtractTarGz
=== RUN TestBackupExisting
=== PAUSE TestBackupExisting
=== RUN TestRollback
=== PAUSE TestRollback
=== RUN TestHubHTTPErrorError
=== PAUSE TestHubHTTPErrorError
=== RUN TestHubHTTPErrorUnwrap
=== PAUSE TestHubHTTPErrorUnwrap
=== RUN TestHubHTTPErrorCanFallback
=== PAUSE TestHubHTTPErrorCanFallback
=== RUN TestValidateHubURL_EdgeCases
=== PAUSE TestValidateHubURL_EdgeCases
=== RUN TestNewHubService_DefaultTimeouts
=== PAUSE TestNewHubService_DefaultTimeouts
=== RUN TestNewHubService_EnvVarTimeouts_Valid
--- PASS: TestNewHubService_EnvVarTimeouts_Valid (0.00s)
=== RUN TestNewHubService_EnvVarTimeouts_Invalid
--- PASS: TestNewHubService_EnvVarTimeouts_Invalid (0.00s)
=== RUN TestNewHubService_EnvVarTimeouts_Negative
--- PASS: TestNewHubService_EnvVarTimeouts_Negative (0.00s)
=== RUN TestNewHubService_EnvVarTimeouts_Whitespace
--- PASS: TestNewHubService_EnvVarTimeouts_Whitespace (0.00s)
=== RUN TestNewHubService_CustomHubBaseURL
--- PASS: TestNewHubService_CustomHubBaseURL (0.00s)
=== RUN TestNewHubService_CustomMirrorBaseURL
--- PASS: TestNewHubService_CustomMirrorBaseURL (0.00s)
=== RUN TestBackupExisting_CopyFallback_Success
=== PAUSE TestBackupExisting_CopyFallback_Success
=== RUN TestBackupExisting_RenameSuccess
=== PAUSE TestBackupExisting_RenameSuccess
=== RUN TestBackupExisting_EmptyDirectory
=== PAUSE TestBackupExisting_EmptyDirectory
=== RUN TestBackupExisting_PreservesPermissions
=== PAUSE TestBackupExisting_PreservesPermissions
=== RUN TestExtractTarGz_NestedPathTraversal
=== PAUSE TestExtractTarGz_NestedPathTraversal
=== RUN TestExtractTarGz_AbsolutePathWithDots
=== PAUSE TestExtractTarGz_AbsolutePathWithDots
=== RUN TestExtractTarGz_EmptyArchive
=== PAUSE TestExtractTarGz_EmptyArchive
=== RUN TestExtractTarGz_InvalidTarAfterGzip
=== PAUSE TestExtractTarGz_InvalidTarAfterGzip
=== RUN TestExtractTarGz_LargeNestedStructure
=== PAUSE TestExtractTarGz_LargeNestedStructure
=== RUN TestExtractTarGz_SpecialCharactersInFilenames
=== PAUSE TestExtractTarGz_SpecialCharactersInFilenames
=== RUN TestExtractTarGz_DirectoriesWithoutFiles
=== PAUSE TestExtractTarGz_DirectoriesWithoutFiles
=== RUN TestExtractTarGz_SkipsSpecialFileTypes
=== PAUSE TestExtractTarGz_SkipsSpecialFileTypes
=== RUN TestAsString_Nil
=== PAUSE TestAsString_Nil
=== RUN TestAsString_String
=== PAUSE TestAsString_String
=== RUN TestAsString_Int
=== PAUSE TestAsString_Int
=== RUN TestAsString_Float
=== PAUSE TestAsString_Float
=== RUN TestAsString_Bool
=== PAUSE TestAsString_Bool
=== RUN TestAsString_Struct
=== PAUSE TestAsString_Struct
=== RUN TestAsString_EmptyString
=== PAUSE TestAsString_EmptyString
=== RUN TestFetchIndexHTTPFromURL_ParseRawIndexFallback
=== PAUSE TestFetchIndexHTTPFromURL_ParseRawIndexFallback
=== RUN TestFetchIndexHTTPFromURL_EmptyJSONArray
=== PAUSE TestFetchIndexHTTPFromURL_EmptyJSONArray
=== RUN TestFetchIndexHTTPFromURL_InvalidJSON
=== PAUSE TestFetchIndexHTTPFromURL_InvalidJSON
=== RUN TestIsGzip_ValidGzip
=== PAUSE TestIsGzip_ValidGzip
=== RUN TestIsGzip_NotGzip
=== PAUSE TestIsGzip_NotGzip
=== RUN TestIsGzip_TooShort
=== PAUSE TestIsGzip_TooShort
=== RUN TestPeekFirstYAML_FindsYAML
=== PAUSE TestPeekFirstYAML_FindsYAML
=== RUN TestPeekFirstYAML_NoYAMLFiles
=== PAUSE TestPeekFirstYAML_NoYAMLFiles
=== RUN TestPeekFirstYAML_InvalidArchive
=== PAUSE TestPeekFirstYAML_InvalidArchive
=== RUN TestFindIndexEntry_ExactMatch
=== PAUSE TestFindIndexEntry_ExactMatch
=== RUN TestFindIndexEntry_ShortName
=== PAUSE TestFindIndexEntry_ShortName
=== RUN TestFindIndexEntry_AmbiguousShortName
=== PAUSE TestFindIndexEntry_AmbiguousShortName
=== RUN TestFindIndexEntry_NotFound
=== PAUSE TestFindIndexEntry_NotFound
=== RUN TestFindIndexEntry_EmptySlug
=== PAUSE TestFindIndexEntry_EmptySlug
=== RUN TestListCuratedPresetsReturnsCopy
=== PAUSE TestListCuratedPresetsReturnsCopy
=== RUN TestFindPreset
=== PAUSE TestFindPreset
=== RUN TestFindPresetCaseVariants
=== PAUSE TestFindPresetCaseVariants
=== RUN TestListCuratedPresetsReturnsDifferentCopy
=== PAUSE TestListCuratedPresetsReturnsDifferentCopy
=== RUN TestCheckLAPIHealth_Healthy
--- PASS: TestCheckLAPIHealth_Healthy (0.00s)
=== RUN TestCheckLAPIHealth_Unhealthy
--- PASS: TestCheckLAPIHealth_Unhealthy (0.00s)
=== RUN TestCheckLAPIHealth_Unreachable
--- PASS: TestCheckLAPIHealth_Unreachable (0.00s)
=== RUN TestCheckLAPIHealth_FallbackToDecisions
--- PASS: TestCheckLAPIHealth_FallbackToDecisions (0.00s)
=== RUN TestCheckLAPIHealth_DefaultURL
--- PASS: TestCheckLAPIHealth_DefaultURL (0.00s)
=== RUN TestGetBouncerAPIKey_FromEnv
--- PASS: TestGetBouncerAPIKey_FromEnv (0.00s)
=== RUN TestGetBouncerAPIKey_Empty
--- PASS: TestGetBouncerAPIKey_Empty (0.00s)
=== RUN TestGetBouncerAPIKey_Fallback
--- PASS: TestGetBouncerAPIKey_Fallback (0.00s)
=== RUN TestEnsureBouncerRegistered_UsesEnvKey
--- PASS: TestEnsureBouncerRegistered_UsesEnvKey (0.00s)
=== RUN TestEnsureBouncerRegistered_NoEnvNoCSCLI
--- PASS: TestEnsureBouncerRegistered_NoEnvNoCSCLI (0.00s)
=== RUN TestEnsureBouncerRegistered_ReturnsExistingBouncerKey
--- PASS: TestEnsureBouncerRegistered_ReturnsExistingBouncerKey (0.00s)
=== RUN TestEnsureBouncerRegistered_RegistersNewWhenNoneExists
--- PASS: TestEnsureBouncerRegistered_RegistersNewWhenNoneExists (0.01s)
=== RUN TestGetLAPIVersion_JSON
--- PASS: TestGetLAPIVersion_JSON (0.00s)
=== RUN TestGetLAPIVersion_PlainText
--- PASS: TestGetLAPIVersion_PlainText (0.00s)
=== RUN TestValidateLAPIURL
=== RUN TestValidateLAPIURL/valid_localhost_with_port
=== RUN TestValidateLAPIURL/valid_127.0.0.1
=== RUN TestValidateLAPIURL/external_URL_blocked
=== RUN TestValidateLAPIURL/HTTPS_localhost
=== RUN TestValidateLAPIURL/invalid_scheme
=== RUN TestValidateLAPIURL/no_scheme
=== RUN TestValidateLAPIURL/empty_URL_allowed_(defaults_to_localhost)
=== RUN TestValidateLAPIURL/IPv6_localhost
=== RUN TestValidateLAPIURL/private_IP_192.168.x.x_blocked_(security)
=== RUN TestValidateLAPIURL/private_IP_10.x.x.x_blocked_(security)
=== RUN TestValidateLAPIURL/missing_hostname
--- PASS: TestValidateLAPIURL (0.00s)
--- PASS: TestValidateLAPIURL/valid_localhost_with_port (0.00s)
--- PASS: TestValidateLAPIURL/valid_127.0.0.1 (0.00s)
--- PASS: TestValidateLAPIURL/external_URL_blocked (0.00s)
--- PASS: TestValidateLAPIURL/HTTPS_localhost (0.00s)
--- PASS: TestValidateLAPIURL/invalid_scheme (0.00s)
--- PASS: TestValidateLAPIURL/no_scheme (0.00s)
--- PASS: TestValidateLAPIURL/empty_URL_allowed_(defaults_to_localhost) (0.00s)
--- PASS: TestValidateLAPIURL/IPv6_localhost (0.00s)
--- PASS: TestValidateLAPIURL/private_IP_192.168.x.x_blocked_(security) (0.00s)
--- PASS: TestValidateLAPIURL/private_IP_10.x.x.x_blocked_(security) (0.00s)
--- PASS: TestValidateLAPIURL/missing_hostname (0.00s)
=== RUN TestEnsureBouncerRegistered_InvalidURL
=== RUN TestEnsureBouncerRegistered_InvalidURL/external_URL_rejected
=== RUN TestEnsureBouncerRegistered_InvalidURL/invalid_scheme_rejected
--- PASS: TestEnsureBouncerRegistered_InvalidURL (0.00s)
--- PASS: TestEnsureBouncerRegistered_InvalidURL/external_URL_rejected (0.00s)
--- PASS: TestEnsureBouncerRegistered_InvalidURL/invalid_scheme_rejected (0.00s)
=== CONT TestHubCacheStoreLoadAndExpire
=== CONT TestPullEvictsExpiredCacheAndRefreshes
=== CONT TestValidateHubURL_UnknownDomainRejection
=== RUN TestValidateHubURL_UnknownDomainRejection/https://evil.com/index.json
=== CONT TestValidateHubURL_ValidHTTPSProduction
=== RUN TestValidateHubURL_ValidHTTPSProduction/https://hub-data.crowdsec.net/api/index.json
=== PAUSE TestValidateHubURL_ValidHTTPSProduction/https://hub-data.crowdsec.net/api/index.json
=== RUN TestValidateHubURL_ValidHTTPSProduction/https://hub.crowdsec.net/api/index.json
=== PAUSE TestValidateHubURL_ValidHTTPSProduction/https://hub.crowdsec.net/api/index.json
=== RUN TestValidateHubURL_ValidHTTPSProduction/https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json
=== PAUSE TestValidateHubURL_ValidHTTPSProduction/https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json
=== CONT TestFetchIndexHTTPAcceptsTextPlain
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="https://hub-data.crowdsec.net/api/index.json"
=== PAUSE TestValidateHubURL_UnknownDomainRejection/https://evil.com/index.json
=== RUN TestValidateHubURL_UnknownDomainRejection/https://attacker.net/hub/index.json
--- PASS: TestFetchIndexHTTPAcceptsTextPlain (0.00s)
=== PAUSE TestValidateHubURL_UnknownDomainRejection/https://attacker.net/hub/index.json
=== RUN TestValidateHubURL_UnknownDomainRejection/https://hub.evil.com/index.json
=== CONT TestCopyDir
=== PAUSE TestValidateHubURL_UnknownDomainRejection/https://hub.evil.com/index.json
=== CONT TestBackupExistingHandlesDeviceBusy
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestHubCacheStoreLoadAndExpire3016545954/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 meta_path=/tmp/TestHubCacheStoreLoadAndExpire3016545954/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestHubCacheStoreLoadAndExpire3016545954/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
--- PASS: TestBackupExistingHandlesDeviceBusy (0.00s)
=== CONT TestApplyWithCopyBasedBackup
--- PASS: TestHubCacheStoreLoadAndExpire (0.01s)
=== CONT TestCopyFile
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestPullEvictsExpiredCacheAndRefreshes3657415151/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011437 meta_path=/tmp/TestPullEvictsExpiredCacheAndRefreshes3657415151/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestPullEvictsExpiredCacheAndRefreshes3657415151/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="http://example.com/api/index.json"
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://example.com/demo.tgz" fallback_used=false
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://example.com/demo.yaml" fallback_used=false
time="2026-01-10T02:17:19Z" level=info msg="storing preset in cache" archive_size=99 etag=etag2 hub_endpoint="http://example.com/demo.tgz" preview_size=13 slug=crowdsecurity/demo
--- PASS: TestCopyFile (0.00s)
=== CONT TestFindPreviewFileFromArchive
=== RUN TestFindPreviewFileFromArchive/finds_yaml_in_archive
=== PAUSE TestFindPreviewFileFromArchive/finds_yaml_in_archive
=== RUN TestFindPreviewFileFromArchive/returns_empty_for_no_yaml
=== PAUSE TestFindPreviewFileFromArchive/returns_empty_for_no_yaml
=== RUN TestFindPreviewFileFromArchive/returns_empty_for_invalid_archive
=== PAUSE TestFindPreviewFileFromArchive/returns_empty_for_invalid_archive
=== CONT TestHasCSCLI
=== RUN TestHasCSCLI/cscli_available
=== PAUSE TestHasCSCLI/cscli_available
=== RUN TestHasCSCLI/cscli_not_found
=== PAUSE TestHasCSCLI/cscli_not_found
=== CONT TestCleanShellArg
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestPullEvictsExpiredCacheAndRefreshes3657415151/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011440 meta_path=/tmp/TestPullEvictsExpiredCacheAndRefreshes3657415151/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestPullEvictsExpiredCacheAndRefreshes3657415151/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=info msg="preset successfully cached" archive_path=/tmp/TestPullEvictsExpiredCacheAndRefreshes3657415151/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011440 preview_path=/tmp/TestPullEvictsExpiredCacheAndRefreshes3657415151/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
=== RUN TestCleanShellArg/clean_slug
=== PAUSE TestCleanShellArg/clean_slug
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestApplyWithCopyBasedBackup1615199222/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 meta_path=/tmp/TestApplyWithCopyBasedBackup1615199222/001/test/preset/metadata.json preview_path=/tmp/TestApplyWithCopyBasedBackup1615199222/001/test/preset/preview.yaml slug=test/preset
time="2026-01-10T02:17:19Z" level=info msg="successfully loaded cached preset metadata" archive_path=/tmp/TestApplyWithCopyBasedBackup1615199222/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 slug=test/preset
=== CONT TestBuildIndexURL
=== RUN TestBuildIndexURL/empty_base_uses_default
=== PAUSE TestBuildIndexURL/empty_base_uses_default
=== RUN TestBuildIndexURL/standard_base_appends_path
=== PAUSE TestBuildIndexURL/standard_base_appends_path
=== RUN TestBuildIndexURL/trailing_slash_removed
=== PAUSE TestBuildIndexURL/trailing_slash_removed
=== RUN TestBuildIndexURL/direct_json_url_unchanged
=== PAUSE TestBuildIndexURL/direct_json_url_unchanged
=== RUN TestBuildIndexURL/case_insensitive_json
=== PAUSE TestBuildIndexURL/case_insensitive_json
=== CONT TestNormalizeHubBaseURL
=== RUN TestNormalizeHubBaseURL/empty_uses_default
=== PAUSE TestNormalizeHubBaseURL/empty_uses_default
=== RUN TestNormalizeHubBaseURL/whitespace_uses_default
=== PAUSE TestNormalizeHubBaseURL/whitespace_uses_default
=== RUN TestNormalizeHubBaseURL/removes_trailing_slash
=== PAUSE TestNormalizeHubBaseURL/removes_trailing_slash
=== RUN TestNormalizeHubBaseURL/removes_multiple_trailing_slashes
=== PAUSE TestNormalizeHubBaseURL/removes_multiple_trailing_slashes
=== RUN TestNormalizeHubBaseURL/trims_spaces
=== PAUSE TestNormalizeHubBaseURL/trims_spaces
=== RUN TestNormalizeHubBaseURL/no_slash_unchanged
--- PASS: TestPullEvictsExpiredCacheAndRefreshes (0.02s)
--- PASS: TestCopyDir (0.01s)
=== RUN TestCleanShellArg/with_dash
--- PASS: TestApplyWithCopyBasedBackup (0.01s)
=== CONT TestApplyRollsBackWhenCacheMissing
time="2026-01-10T02:17:19Z" level=error msg="cache unavailable for apply" slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=warning msg="cache refresh failed; rolled back backup" backup_path=/tmp/TestApplyRollsBackWhenCacheMissing965748357/001/crowdsec.backup.20260110-021719 error="cache unavailable for manual apply" slug=crowdsecurity/demo
=== PAUSE TestCleanShellArg/with_dash
=== RUN TestCleanShellArg/with_underscore
=== PAUSE TestCleanShellArg/with_underscore
=== RUN TestCleanShellArg/with_dot
=== PAUSE TestNormalizeHubBaseURL/no_slash_unchanged
=== PAUSE TestCleanShellArg/with_dot
=== RUN TestCleanShellArg/path_traversal
=== CONT TestFirstNonEmpty
=== RUN TestFirstNonEmpty/first_non-empty
=== CONT TestFetchWithLimitStatusError
--- PASS: TestApplyRollsBackWhenCacheMissing (0.00s)
=== CONT TestUniqueStrings
=== CONT TestFetchIndexCSCLIParseError
=== RUN TestUniqueStrings/empty_slice
=== PAUSE TestUniqueStrings/empty_slice
=== RUN TestUniqueStrings/no_duplicates
=== PAUSE TestUniqueStrings/no_duplicates
=== RUN TestUniqueStrings/with_duplicates
=== PAUSE TestUniqueStrings/with_duplicates
=== RUN TestUniqueStrings/all_duplicates
=== PAUSE TestUniqueStrings/all_duplicates
=== RUN TestUniqueStrings/preserves_order
=== PAUSE TestUniqueStrings/preserves_order
=== CONT TestRunCSCLIRejectsUnsafeSlug
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=1 error="http://hub.example/api/index.json (status 500)" hub_index="http://hub.example/api/index.json"
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=2 error="https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json (status 500)" hub_index="https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json"
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=3 error="https://raw.githubusercontent.com/crowdsecurity/hub/master/api/index.json (status 500)" hub_index="https://raw.githubusercontent.com/crowdsecurity/hub/master/api/index.json"
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=4 error="https://hub-data.crowdsec.net/api/index.json (status 500)" hub_index="https://hub-data.crowdsec.net/api/index.json"
=== CONT TestApplyUsesCSCLISuccess
=== CONT TestFetchPreviewRequiresURL
=== CONT TestFetchWithLimitRequiresClient
=== CONT TestPullValidatesSlugAndMissingPreset
=== PAUSE TestCleanShellArg/path_traversal
=== RUN TestCleanShellArg/absolute_path
=== PAUSE TestCleanShellArg/absolute_path
=== RUN TestCleanShellArg/backslash_converted
=== PAUSE TestCleanShellArg/backslash_converted
=== RUN TestCleanShellArg/colon_not_allowed
=== PAUSE TestFirstNonEmpty/first_non-empty
=== PAUSE TestCleanShellArg/colon_not_allowed
=== RUN TestFirstNonEmpty/all_empty
=== RUN TestCleanShellArg/semicolon
=== PAUSE TestFirstNonEmpty/all_empty
=== PAUSE TestCleanShellArg/semicolon
=== RUN TestFirstNonEmpty/first_is_non-empty
=== PAUSE TestFirstNonEmpty/first_is_non-empty
=== RUN TestCleanShellArg/pipe
=== RUN TestFirstNonEmpty/whitespace_treated_as_empty
=== PAUSE TestFirstNonEmpty/whitespace_treated_as_empty
=== PAUSE TestCleanShellArg/pipe
=== RUN TestFirstNonEmpty/whitespace_with_content
=== PAUSE TestFirstNonEmpty/whitespace_with_content
=== RUN TestCleanShellArg/ampersand
=== RUN TestFirstNonEmpty/empty_slice
=== PAUSE TestCleanShellArg/ampersand
--- PASS: TestFetchWithLimitStatusError (0.00s)
=== PAUSE TestFirstNonEmpty/empty_slice
=== RUN TestFirstNonEmpty/tabs_and_newlines
=== RUN TestCleanShellArg/backtick
=== PAUSE TestCleanShellArg/backtick
--- PASS: TestRunCSCLIRejectsUnsafeSlug (0.00s)
=== PAUSE TestFirstNonEmpty/tabs_and_newlines
=== RUN TestCleanShellArg/dollar
--- PASS: TestFetchIndexCSCLIParseError (0.00s)
--- PASS: TestFetchPreviewRequiresURL (0.00s)
--- PASS: TestFetchWithLimitRequiresClient (0.00s)
=== CONT TestFetchIndexHTTPError
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=1 error="https://hub-data.crowdsec.net/api/index.json (status 503)" hub_index="https://hub-data.crowdsec.net/api/index.json"
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=2 error="https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json (status 503)" hub_index="https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json"
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=3 error="https://raw.githubusercontent.com/crowdsecurity/hub/master/api/index.json (status 503)" hub_index="https://raw.githubusercontent.com/crowdsecurity/hub/master/api/index.json"
--- PASS: TestFetchIndexHTTPError (0.00s)
=== PAUSE TestCleanShellArg/dollar
=== CONT TestExtractTarGzRejectsSymlink
=== RUN TestCleanShellArg/parenthesis
=== PAUSE TestCleanShellArg/parenthesis
=== CONT TestExtractTarGzRejectsAbsolutePath
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestApplyUsesCSCLISuccess2135085979/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 meta_path=/tmp/TestApplyUsesCSCLISuccess2135085979/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestApplyUsesCSCLISuccess2135085979/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="http://hub.example/api/index.json"
time="2026-01-10T02:17:19Z" level=info msg="successfully loaded cached preset metadata" archive_path=/tmp/TestApplyUsesCSCLISuccess2135085979/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 slug=crowdsecurity/demo
--- PASS: TestPullValidatesSlugAndMissingPreset (0.01s)
=== CONT TestPullFallsBackToMirrorArchiveOnForbidden
--- PASS: TestApplyUsesCSCLISuccess (0.01s)
=== CONT TestFetchWithLimitRejectsLargePayload
--- PASS: TestExtractTarGzRejectsSymlink (0.01s)
=== CONT TestHubCacheTTL
=== RUN TestHubCacheTTL/returns_configured_TTL
=== PAUSE TestHubCacheTTL/returns_configured_TTL
=== RUN TestHubCacheTTL/returns_minute_TTL
=== PAUSE TestHubCacheTTL/returns_minute_TTL
--- PASS: TestExtractTarGzRejectsAbsolutePath (0.01s)
=== CONT TestPullReturnsCachedPreviewWithoutNetwork
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="https://primary.example/api/index.json"
time="2026-01-10T02:17:19Z" level=warning msg="hub fetch failed, attempting fallback" attempt=1 endpoint="https://primary.example/crowdsecurity/demo.tgz" error="https://primary.example/crowdsecurity/demo.tgz (status 403)"
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="https://raw.githubusercontent.com/crowdsecurity/hub/master/crowdsecurity/demo.tgz" fallback_used=true
time="2026-01-10T02:17:19Z" level=warning msg="hub fetch failed, attempting fallback" attempt=1 endpoint="https://primary.example/crowdsecurity/demo.yaml" error="https://primary.example/crowdsecurity/demo.yaml (status 403)"
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="https://raw.githubusercontent.com/crowdsecurity/hub/master/crowdsecurity/demo.yaml" fallback_used=true
time="2026-01-10T02:17:19Z" level=info msg="storing preset in cache" archive_size=105 etag=etag1 hub_endpoint="https://raw.githubusercontent.com/crowdsecurity/hub/master/crowdsecurity/demo.tgz" preview_size=14 slug=crowdsecurity/demo
=== RUN TestHubCacheTTL/returns_zero_TTL_if_configured
=== PAUSE TestHubCacheTTL/returns_zero_TTL_if_configured
=== CONT TestApplyUsesCacheWhenCscliMissing
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestPullFallsBackToMirrorArchiveOnForbidden11765555/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 meta_path=/tmp/TestPullFallsBackToMirrorArchiveOnForbidden11765555/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestPullFallsBackToMirrorArchiveOnForbidden11765555/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=info msg="preset successfully cached" archive_path=/tmp/TestPullFallsBackToMirrorArchiveOnForbidden11765555/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 preview_path=/tmp/TestPullFallsBackToMirrorArchiveOnForbidden11765555/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
--- PASS: TestPullFallsBackToMirrorArchiveOnForbidden (0.01s)
=== CONT TestApplyRollsBackOnBadArchive
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestPullReturnsCachedPreviewWithoutNetwork3052954076/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 meta_path=/tmp/TestPullReturnsCachedPreviewWithoutNetwork3052954076/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestPullReturnsCachedPreviewWithoutNetwork3052954076/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
--- PASS: TestPullReturnsCachedPreviewWithoutNetwork (0.01s)
=== CONT TestPullFallsBackToArchivePreview
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestApplyRollsBackOnBadArchive1855248391/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 meta_path=/tmp/TestApplyRollsBackOnBadArchive1855248391/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestApplyRollsBackOnBadArchive1855248391/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="http://example.com/api/index.json"
time="2026-01-10T02:17:19Z" level=info msg="successfully loaded cached preset metadata" archive_path=/tmp/TestApplyRollsBackOnBadArchive1855248391/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://example.com/demo.tgz" fallback_used=false
time="2026-01-10T02:17:19Z" level=warning msg="hub fetch failed, attempting fallback" attempt=1 endpoint="http://example.com/demo.yaml" error="http://example.com/demo.yaml (status 500)"
time="2026-01-10T02:17:19Z" level=warning msg="failed to download preview, falling back to archive inspection" error="preview fetch failed (last endpoint http://example.com/crowdsecurity/demo.yaml): http://example.com/demo.yaml: http://example.com/demo.yaml (status 500)\nhttp://example.com/crowdsecurity/demo.yaml: http://example.com/crowdsecurity/demo.yaml (status 404)" slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestApplyUsesCacheWhenCscliMissing3901280632/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 meta_path=/tmp/TestApplyUsesCacheWhenCscliMissing3901280632/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestApplyUsesCacheWhenCscliMissing3901280632/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=info msg="successfully loaded cached preset metadata" archive_path=/tmp/TestApplyUsesCacheWhenCscliMissing3901280632/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 slug=crowdsecurity/demo
--- PASS: TestApplyRollsBackOnBadArchive (0.02s)
=== CONT TestPullCachesPreview
time="2026-01-10T02:17:19Z" level=info msg="storing preset in cache" archive_size=116 etag=etag1 hub_endpoint="http://example.com/demo.tgz" preview_size=11 slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestPullFallsBackToArchivePreview2937992452/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 meta_path=/tmp/TestPullFallsBackToArchivePreview2937992452/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestPullFallsBackToArchivePreview2937992452/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=info msg="preset successfully cached" archive_path=/tmp/TestPullFallsBackToArchivePreview2937992452/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 preview_path=/tmp/TestPullFallsBackToArchivePreview2937992452/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
--- PASS: TestApplyUsesCacheWhenCscliMissing (0.02s)
--- PASS: TestPullFallsBackToArchivePreview (0.02s)
=== CONT TestApplyUsesCacheWhenCSCLIFails
=== CONT TestFetchIndexFallsBackToMirrorOnForbidden
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=1 error="https://hub-data.crowdsec.net/api/index.json (status 403)" hub_index="https://hub-data.crowdsec.net/api/index.json"
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=true hub_index="https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json"
--- PASS: TestFetchIndexFallsBackToMirrorOnForbidden (0.00s)
=== CONT TestFetchIndexHTTPRejectsHTML
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=1 error="https://hub-data.crowdsec.net/api/index.json (status 200): hub index responded with HTML; install cscli or set HUB_BASE_URL to a JSON hub endpoint" hub_index="https://hub-data.crowdsec.net/api/index.json"
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=2 error="https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json (status 200): hub index responded with HTML; install cscli or set HUB_BASE_URL to a JSON hub endpoint" hub_index="https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json"
time="2026-01-10T02:17:19Z" level=warning msg="hub index fetch failed, trying mirror" attempt=3 error="https://raw.githubusercontent.com/crowdsecurity/hub/master/api/index.json (status 200): hub index responded with HTML; install cscli or set HUB_BASE_URL to a JSON hub endpoint" hub_index="https://raw.githubusercontent.com/crowdsecurity/hub/master/api/index.json"
--- PASS: TestFetchIndexHTTPRejectsHTML (0.00s)
=== CONT TestFetchIndexHTTPRejectsRedirect
--- PASS: TestFetchIndexHTTPRejectsRedirect (0.00s)
=== CONT TestFetchIndexHTTPFallsBackToDefaultHub
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="https://hub.crowdsec.net/api/index.json"
--- PASS: TestFetchIndexHTTPFallsBackToDefaultHub (0.00s)
=== CONT TestFetchIndexFallbackHTTP
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="http://example.com/api/index.json"
--- PASS: TestFetchIndexFallbackHTTP (0.00s)
=== CONT TestSanitizeSlugCases
--- PASS: TestSanitizeSlugCases (0.00s)
=== CONT TestFetchIndexPrefersCSCLI
--- PASS: TestFetchIndexPrefersCSCLI (0.00s)
=== CONT TestHubCacheListContextCanceled
--- PASS: TestHubCacheListContextCanceled (0.00s)
=== CONT TestExtractTarGz_LargeNestedStructure
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestApplyUsesCacheWhenCSCLIFails3365830785/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 meta_path=/tmp/TestApplyUsesCacheWhenCSCLIFails3365830785/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestApplyUsesCacheWhenCSCLIFails3365830785/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="http://example.com/api/index.json"
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://example.com/demo.tgz" fallback_used=false
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://example.com/demo.yaml" fallback_used=false
time="2026-01-10T02:17:19Z" level=info msg="successfully loaded cached preset metadata" archive_path=/tmp/TestApplyUsesCacheWhenCSCLIFails3365830785/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=warning msg="cscli install failed; attempting cache fallback" error="install failed" slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=info msg="storing preset in cache" archive_size=106 etag=etag1 hub_endpoint="http://example.com/demo.tgz" preview_size=12 slug=crowdsecurity/demo
--- PASS: TestApplyUsesCacheWhenCSCLIFails (0.01s)
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestPullCachesPreview1283738611/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 meta_path=/tmp/TestPullCachesPreview1283738611/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestPullCachesPreview1283738611/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=info msg="preset successfully cached" archive_path=/tmp/TestPullCachesPreview1283738611/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 preview_path=/tmp/TestPullCachesPreview1283738611/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
=== CONT TestFindPresetCaseVariants
=== RUN TestFindPresetCaseVariants/exact_match
=== PAUSE TestFindPresetCaseVariants/exact_match
=== RUN TestFindPresetCaseVariants/another_preset
=== PAUSE TestFindPresetCaseVariants/another_preset
=== RUN TestFindPresetCaseVariants/case_sensitive_miss
=== PAUSE TestFindPresetCaseVariants/case_sensitive_miss
=== RUN TestFindPresetCaseVariants/partial_match_miss
=== PAUSE TestFindPresetCaseVariants/partial_match_miss
=== RUN TestFindPresetCaseVariants/empty_slug
=== PAUSE TestFindPresetCaseVariants/empty_slug
=== CONT TestFindPreset
--- PASS: TestFindPreset (0.00s)
=== CONT TestListCuratedPresetsReturnsCopy
--- PASS: TestListCuratedPresetsReturnsCopy (0.00s)
=== CONT TestFindIndexEntry_EmptySlug
--- PASS: TestFindIndexEntry_EmptySlug (0.00s)
=== CONT TestFindIndexEntry_NotFound
--- PASS: TestPullCachesPreview (0.02s)
--- PASS: TestFindIndexEntry_NotFound (0.00s)
=== CONT TestListCuratedPresetsReturnsDifferentCopy
--- PASS: TestListCuratedPresetsReturnsDifferentCopy (0.00s)
=== CONT TestFindIndexEntry_ShortName
--- PASS: TestFindIndexEntry_ShortName (0.00s)
=== CONT TestFindIndexEntry_AmbiguousShortName
--- PASS: TestFindIndexEntry_AmbiguousShortName (0.00s)
=== CONT TestPeekFirstYAML_InvalidArchive
=== CONT TestPeekFirstYAML_NoYAMLFiles
--- PASS: TestPeekFirstYAML_InvalidArchive (0.00s)
=== CONT TestFindIndexEntry_ExactMatch
--- PASS: TestFindIndexEntry_ExactMatch (0.00s)
=== CONT TestPeekFirstYAML_FindsYAML
--- PASS: TestExtractTarGz_LargeNestedStructure (0.02s)
=== CONT TestIsGzip_NotGzip
--- PASS: TestIsGzip_NotGzip (0.00s)
=== CONT TestIsGzip_ValidGzip
--- PASS: TestPeekFirstYAML_NoYAMLFiles (0.01s)
=== CONT TestFetchIndexHTTPFromURL_InvalidJSON
--- PASS: TestFetchIndexHTTPFromURL_InvalidJSON (0.00s)
=== CONT TestFetchIndexHTTPFromURL_EmptyJSONArray
--- PASS: TestFetchIndexHTTPFromURL_EmptyJSONArray (0.00s)
=== CONT TestFetchIndexHTTPFromURL_ParseRawIndexFallback
--- PASS: TestFetchIndexHTTPFromURL_ParseRawIndexFallback (0.00s)
=== CONT TestAsString_EmptyString
--- PASS: TestAsString_EmptyString (0.00s)
=== CONT TestAsString_Struct
--- PASS: TestAsString_Struct (0.00s)
=== CONT TestAsString_Bool
--- PASS: TestPeekFirstYAML_FindsYAML (0.01s)
=== CONT TestAsString_Float
--- PASS: TestAsString_Float (0.00s)
=== CONT TestIsGzip_TooShort
--- PASS: TestIsGzip_TooShort (0.00s)
=== CONT TestAsString_String
--- PASS: TestAsString_Bool (0.00s)
=== CONT TestAsString_Nil
--- PASS: TestAsString_Nil (0.00s)
=== CONT TestAsString_Int
--- PASS: TestAsString_Int (0.00s)
=== CONT TestExtractTarGz_SkipsSpecialFileTypes
--- PASS: TestIsGzip_ValidGzip (0.01s)
=== CONT TestExtractTarGz_DirectoriesWithoutFiles
--- PASS: TestAsString_String (0.00s)
=== CONT TestRollback
=== RUN TestRollback/rollback_with_backup
=== PAUSE TestRollback/rollback_with_backup
=== RUN TestRollback/rollback_with_empty_backup_path
=== PAUSE TestRollback/rollback_with_empty_backup_path
=== RUN TestRollback/rollback_with_non-existent_backup
=== PAUSE TestRollback/rollback_with_non-existent_backup
=== CONT TestExtractTarGz_SpecialCharactersInFilenames
--- PASS: TestExtractTarGz_DirectoriesWithoutFiles (0.01s)
=== CONT TestExtractTarGz_EmptyArchive
--- PASS: TestExtractTarGz_SkipsSpecialFileTypes (0.01s)
=== CONT TestExtractTarGz_InvalidTarAfterGzip
--- PASS: TestExtractTarGz_SpecialCharactersInFilenames (0.01s)
=== CONT TestExtractTarGz_NestedPathTraversal
--- PASS: TestExtractTarGz_EmptyArchive (0.01s)
=== CONT TestBackupExisting_PreservesPermissions
--- PASS: TestBackupExisting_PreservesPermissions (0.00s)
=== CONT TestExtractTarGz_AbsolutePathWithDots
--- PASS: TestExtractTarGz_NestedPathTraversal (0.01s)
=== CONT TestBackupExisting_EmptyDirectory
--- PASS: TestExtractTarGz_InvalidTarAfterGzip (0.01s)
=== CONT TestBackupExisting_RenameSuccess
--- PASS: TestBackupExisting_RenameSuccess (0.00s)
=== CONT TestHubHTTPErrorUnwrap
=== RUN TestHubHTTPErrorUnwrap/unwrap_returns_inner_error
=== PAUSE TestHubHTTPErrorUnwrap/unwrap_returns_inner_error
=== RUN TestHubHTTPErrorUnwrap/unwrap_returns_nil_when_no_inner
=== PAUSE TestHubHTTPErrorUnwrap/unwrap_returns_nil_when_no_inner
=== RUN TestHubHTTPErrorUnwrap/errors.Is_works_through_Unwrap
=== PAUSE TestHubHTTPErrorUnwrap/errors.Is_works_through_Unwrap
=== CONT TestNewHubService_DefaultTimeouts
--- PASS: TestBackupExisting_EmptyDirectory (0.00s)
=== CONT TestBackupExisting_CopyFallback_Success
--- PASS: TestBackupExisting_CopyFallback_Success (0.00s)
=== CONT TestValidateHubURL_EdgeCases
=== RUN TestValidateHubURL_EdgeCases/Missing_hostname
=== PAUSE TestValidateHubURL_EdgeCases/Missing_hostname
=== RUN TestValidateHubURL_EdgeCases/Invalid_URL_format_-_unsupported_scheme_caught
=== PAUSE TestValidateHubURL_EdgeCases/Invalid_URL_format_-_unsupported_scheme_caught
=== RUN TestValidateHubURL_EdgeCases/FTP_scheme_rejected
=== PAUSE TestValidateHubURL_EdgeCases/FTP_scheme_rejected
=== RUN TestValidateHubURL_EdgeCases/File_scheme_rejected
=== PAUSE TestValidateHubURL_EdgeCases/File_scheme_rejected
=== RUN TestValidateHubURL_EdgeCases/Test_domain_allowed
=== PAUSE TestValidateHubURL_EdgeCases/Test_domain_allowed
=== RUN TestValidateHubURL_EdgeCases/Example.com_allowed_for_testing
=== PAUSE TestValidateHubURL_EdgeCases/Example.com_allowed_for_testing
=== RUN TestValidateHubURL_EdgeCases/.local_domain_allowed
=== PAUSE TestValidateHubURL_EdgeCases/.local_domain_allowed
=== RUN TestValidateHubURL_EdgeCases/Subdomain_of_example.com_allowed
=== PAUSE TestValidateHubURL_EdgeCases/Subdomain_of_example.com_allowed
=== RUN TestValidateHubURL_EdgeCases/IPv6_loopback_allowed
=== PAUSE TestValidateHubURL_EdgeCases/IPv6_loopback_allowed
=== RUN TestValidateHubURL_EdgeCases/Unknown_production_domain_rejected
=== PAUSE TestValidateHubURL_EdgeCases/Unknown_production_domain_rejected
=== CONT TestHubHTTPErrorCanFallback
=== RUN TestHubHTTPErrorCanFallback/returns_true_when_fallback_is_true
=== PAUSE TestHubHTTPErrorCanFallback/returns_true_when_fallback_is_true
=== RUN TestHubHTTPErrorCanFallback/returns_false_when_fallback_is_false
=== PAUSE TestHubHTTPErrorCanFallback/returns_false_when_fallback_is_false
--- PASS: TestNewHubService_DefaultTimeouts (0.00s)
=== CONT TestHubCacheTouchMissing
--- PASS: TestHubCacheTouchMissing (0.00s)
=== CONT TestHubCacheEvictInvalidSlug
--- PASS: TestHubCacheEvictInvalidSlug (0.00s)
=== CONT TestHubCacheListSkipsExpired
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestHubCacheListSkipsExpired1527189804/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1704110400 meta_path=/tmp/TestHubCacheListSkipsExpired1527189804/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestHubCacheListSkipsExpired1527189804/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
=== CONT TestHubCacheExistsContextCanceled
--- PASS: TestHubCacheExistsContextCanceled (0.00s)
--- PASS: TestHubCacheListSkipsExpired (0.00s)
=== CONT TestHubCacheTouchInvalidSlug
--- PASS: TestExtractTarGz_AbsolutePathWithDots (0.01s)
--- PASS: TestHubCacheTouchInvalidSlug (0.00s)
=== CONT TestHubCacheLoadInvalidSlug
=== CONT TestHubCacheStoreContextCanceled
--- PASS: TestHubCacheStoreContextCanceled (0.00s)
=== CONT TestHubCacheListAndEvict
--- PASS: TestHubCacheLoadInvalidSlug (0.00s)
=== CONT TestHubCachePreviewExistsAndSize
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestHubCacheListAndEvict1933366209/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 meta_path=/tmp/TestHubCacheListAndEvict1933366209/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestHubCacheListAndEvict1933366209/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestHubCacheListAndEvict1933366209/001/crowdsecurity/other/bundle.tgz cache_key=crowdsecurity/other-1768011439 meta_path=/tmp/TestHubCacheListAndEvict1933366209/001/crowdsecurity/other/metadata.json preview_path=/tmp/TestHubCacheListAndEvict1933366209/001/crowdsecurity/other/preview.yaml slug=crowdsecurity/other
=== CONT TestHubCacheExistsHonorsTTL
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestHubCacheExistsHonorsTTL4074854815/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 meta_path=/tmp/TestHubCacheExistsHonorsTTL4074854815/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestHubCacheExistsHonorsTTL4074854815/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
--- PASS: TestHubCacheExistsHonorsTTL (0.00s)
=== CONT TestNewHubCacheRequiresBaseDir
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestHubCachePreviewExistsAndSize2948237553/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 meta_path=/tmp/TestHubCachePreviewExistsAndSize2948237553/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestHubCachePreviewExistsAndSize2948237553/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
--- PASS: TestNewHubCacheRequiresBaseDir (0.00s)
=== CONT TestHubService_Apply_CacheRefresh
--- PASS: TestHubCachePreviewExistsAndSize (0.01s)
=== CONT TestBackupExisting
=== RUN TestBackupExisting/handles_non-existent_directory
=== PAUSE TestBackupExisting/handles_non-existent_directory
=== RUN TestBackupExisting/creates_backup_of_existing_directory
=== PAUSE TestBackupExisting/creates_backup_of_existing_directory
=== RUN TestBackupExisting/backup_contents_match_original
=== PAUSE TestBackupExisting/backup_contents_match_original
=== CONT TestExtractTarGz
=== RUN TestExtractTarGz/extracts_valid_archive
=== PAUSE TestExtractTarGz/extracts_valid_archive
=== RUN TestExtractTarGz/rejects_path_traversal
=== PAUSE TestExtractTarGz/rejects_path_traversal
=== RUN TestExtractTarGz/rejects_symlinks
=== PAUSE TestExtractTarGz/rejects_symlinks
=== RUN TestExtractTarGz/handles_corrupted_gzip
=== PAUSE TestExtractTarGz/handles_corrupted_gzip
=== RUN TestExtractTarGz/handles_context_cancellation
=== PAUSE TestExtractTarGz/handles_context_cancellation
=== RUN TestExtractTarGz/creates_nested_directories
=== PAUSE TestExtractTarGz/creates_nested_directories
=== CONT TestHubHTTPErrorError
=== RUN TestHubHTTPErrorError/error_with_inner_error
=== PAUSE TestHubHTTPErrorError/error_with_inner_error
=== RUN TestHubHTTPErrorError/error_without_inner_error
=== PAUSE TestHubHTTPErrorError/error_without_inner_error
=== CONT TestEmptyDir
=== RUN TestEmptyDir/empties_directory_with_files
=== PAUSE TestEmptyDir/empties_directory_with_files
=== RUN TestEmptyDir/empties_directory_with_subdirectories
=== PAUSE TestEmptyDir/empties_directory_with_subdirectories
=== RUN TestEmptyDir/handles_non-existent_directory
=== PAUSE TestEmptyDir/handles_non-existent_directory
=== RUN TestEmptyDir/handles_empty_directory
=== PAUSE TestEmptyDir/handles_empty_directory
=== CONT TestCopyDirAndCopyFile
=== RUN TestCopyDirAndCopyFile/copyFile_success
=== CONT TestHubService_Apply_RollbackOnExtractionFailure
--- PASS: TestHubCacheListAndEvict (0.01s)
=== PAUSE TestCopyDirAndCopyFile/copyFile_success
=== RUN TestCopyDirAndCopyFile/copyFile_preserves_permissions
=== PAUSE TestCopyDirAndCopyFile/copyFile_preserves_permissions
=== RUN TestCopyDirAndCopyFile/copyDir_with_nested_structure
=== PAUSE TestCopyDirAndCopyFile/copyDir_with_nested_structure
=== RUN TestCopyDirAndCopyFile/copyDir_fails_on_non-directory_source
=== PAUSE TestCopyDirAndCopyFile/copyDir_fails_on_non-directory_source
=== CONT TestHubCacheRejectsBadSlug
--- PASS: TestHubCacheRejectsBadSlug (0.00s)
=== CONT TestHubCacheTouchUpdatesTTL
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestHubCacheTouchUpdatesTTL3154057090/001/crowdsecurity/demo/bundle.tgz cache_key=crowdsecurity/demo-1768011439 meta_path=/tmp/TestHubCacheTouchUpdatesTTL3154057090/001/crowdsecurity/demo/metadata.json preview_path=/tmp/TestHubCacheTouchUpdatesTTL3154057090/001/crowdsecurity/demo/preview.yaml slug=crowdsecurity/demo
--- PASS: TestHubCacheTouchUpdatesTTL (0.00s)
=== CONT TestHubService_Apply_ArchiveReadBeforeBackup
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestHubService_Apply_CacheRefresh936131160/001/test/preset/bundle.tgz cache_key=test/preset-1768011434 meta_path=/tmp/TestHubService_Apply_CacheRefresh936131160/001/test/preset/metadata.json preview_path=/tmp/TestHubService_Apply_CacheRefresh936131160/001/test/preset/preview.yaml slug=test/preset
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestHubService_Apply_ArchiveReadBeforeBackup2498877560/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 meta_path=/tmp/TestHubService_Apply_ArchiveReadBeforeBackup2498877560/001/test/preset/metadata.json preview_path=/tmp/TestHubService_Apply_ArchiveReadBeforeBackup2498877560/001/test/preset/preview.yaml slug=test/preset
time="2026-01-10T02:17:19Z" level=info msg="successfully loaded cached preset metadata" archive_path=/tmp/TestHubService_Apply_ArchiveReadBeforeBackup2498877560/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 slug=test/preset
--- PASS: TestHubService_Apply_ArchiveReadBeforeBackup (0.01s)
=== CONT TestFetchIndexHTTPFromURL_HTMLDetection
--- PASS: TestFetchIndexHTTPFromURL_HTMLDetection (0.00s)
=== CONT TestParseRawIndex
=== RUN TestParseRawIndex/parses_valid_raw_index
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestHubService_Apply_RollbackOnExtractionFailure1106849730/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 meta_path=/tmp/TestHubService_Apply_RollbackOnExtractionFailure1106849730/001/test/preset/metadata.json preview_path=/tmp/TestHubService_Apply_RollbackOnExtractionFailure1106849730/001/test/preset/preview.yaml slug=test/preset
=== PAUSE TestParseRawIndex/parses_valid_raw_index
=== RUN TestParseRawIndex/returns_error_on_invalid_JSON
=== PAUSE TestParseRawIndex/returns_error_on_invalid_JSON
=== RUN TestParseRawIndex/returns_error_on_empty_index
=== PAUSE TestParseRawIndex/returns_error_on_empty_index
=== CONT TestValidateHubURL_HTTPRejectedForProduction
=== RUN TestValidateHubURL_HTTPRejectedForProduction/http://hub-data.crowdsec.net/api/index.json
=== PAUSE TestValidateHubURL_HTTPRejectedForProduction/http://hub-data.crowdsec.net/api/index.json
=== RUN TestValidateHubURL_HTTPRejectedForProduction/http://hub.crowdsec.net/api/index.json
=== PAUSE TestValidateHubURL_HTTPRejectedForProduction/http://hub.crowdsec.net/api/index.json
=== RUN TestValidateHubURL_HTTPRejectedForProduction/http://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json
=== PAUSE TestValidateHubURL_HTTPRejectedForProduction/http://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json
=== CONT TestBuildResourceURLs
=== RUN TestBuildResourceURLs/with_explicit_URL
=== PAUSE TestBuildResourceURLs/with_explicit_URL
=== RUN TestBuildResourceURLs/without_explicit_URL
=== PAUSE TestBuildResourceURLs/without_explicit_URL
=== RUN TestBuildResourceURLs/removes_duplicates
=== PAUSE TestBuildResourceURLs/removes_duplicates
=== RUN TestBuildResourceURLs/handles_empty_bases
=== PAUSE TestBuildResourceURLs/handles_empty_bases
=== CONT TestValidateHubURL_LocalhostExceptions
=== RUN TestValidateHubURL_LocalhostExceptions/http://localhost:8080/index.json
=== PAUSE TestValidateHubURL_LocalhostExceptions/http://localhost:8080/index.json
=== RUN TestValidateHubURL_LocalhostExceptions/http://127.0.0.1:8080/index.json
=== PAUSE TestValidateHubURL_LocalhostExceptions/http://127.0.0.1:8080/index.json
=== RUN TestValidateHubURL_LocalhostExceptions/http://[::1]:8080/index.json
=== PAUSE TestValidateHubURL_LocalhostExceptions/http://[::1]:8080/index.json
=== RUN TestValidateHubURL_LocalhostExceptions/http://test.hub/api/index.json
=== PAUSE TestValidateHubURL_LocalhostExceptions/http://test.hub/api/index.json
=== RUN TestValidateHubURL_LocalhostExceptions/http://example.com/api/index.json
=== PAUSE TestValidateHubURL_LocalhostExceptions/http://example.com/api/index.json
=== RUN TestValidateHubURL_LocalhostExceptions/http://test.example.com/api/index.json
=== PAUSE TestValidateHubURL_LocalhostExceptions/http://test.example.com/api/index.json
time="2026-01-10T02:17:19Z" level=warning msg="failed to load cached preset metadata" error="cache expired" slug=test/preset
=== RUN TestValidateHubURL_LocalhostExceptions/http://server.local/api/index.json
=== PAUSE TestValidateHubURL_LocalhostExceptions/http://server.local/api/index.json
=== CONT TestValidateHubURL_InvalidSchemes
=== RUN TestValidateHubURL_InvalidSchemes/ftp://hub.crowdsec.net/index.json
=== PAUSE TestValidateHubURL_InvalidSchemes/ftp://hub.crowdsec.net/index.json
time="2026-01-10T02:17:19Z" level=info msg="attempting to repull preset after cache load failure" error="load cache for test/preset: cache expired" slug=test/preset
=== RUN TestValidateHubURL_InvalidSchemes/file:///etc/passwd
=== PAUSE TestValidateHubURL_InvalidSchemes/file:///etc/passwd
=== RUN TestValidateHubURL_InvalidSchemes/gopher://attacker.com
=== PAUSE TestValidateHubURL_InvalidSchemes/gopher://attacker.com
=== RUN TestValidateHubURL_InvalidSchemes/data:text/html,<script>alert('xss')</script>
=== PAUSE TestValidateHubURL_InvalidSchemes/data:text/html,<script>alert('xss')</script>
=== CONT TestValidateHubURL_UnknownDomainRejection/https://attacker.net/hub/index.json
=== CONT TestValidateHubURL_ValidHTTPSProduction/https://hub.crowdsec.net/api/index.json
=== CONT TestValidateHubURL_ValidHTTPSProduction/https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json
=== CONT TestValidateHubURL_UnknownDomainRejection/https://hub.evil.com/index.json
time="2026-01-10T02:17:19Z" level=info msg="hub index fetched" fallback_used=false hub_index="http://test.hub/api/index.json"
=== CONT TestValidateHubURL_UnknownDomainRejection/https://evil.com/index.json
time="2026-01-10T02:17:19Z" level=info msg="hub fetch succeeded" endpoint="http://test.hub/preset.tgz" fallback_used=false
=== CONT TestValidateHubURL_ValidHTTPSProduction/https://hub-data.crowdsec.net/api/index.json
--- PASS: TestValidateHubURL_ValidHTTPSProduction (0.00s)
--- PASS: TestValidateHubURL_ValidHTTPSProduction/https://hub.crowdsec.net/api/index.json (0.00s)
--- PASS: TestValidateHubURL_ValidHTTPSProduction/https://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json (0.00s)
--- PASS: TestValidateHubURL_ValidHTTPSProduction/https://hub-data.crowdsec.net/api/index.json (0.00s)
--- PASS: TestValidateHubURL_UnknownDomainRejection (0.00s)
--- PASS: TestValidateHubURL_UnknownDomainRejection/https://attacker.net/hub/index.json (0.00s)
--- PASS: TestValidateHubURL_UnknownDomainRejection/https://hub.evil.com/index.json (0.00s)
--- PASS: TestValidateHubURL_UnknownDomainRejection/https://evil.com/index.json (0.00s)
=== CONT TestFindPreviewFileFromArchive/finds_yaml_in_archive
time="2026-01-10T02:17:19Z" level=warning msg="failed to download preview, falling back to archive inspection" error="preview fetch failed (last endpoint http://test.hub/test/preset.yaml): http://test.hub/test/preset.yaml: http://test.hub/test/preset.yaml (status 404)" slug=test/preset
time="2026-01-10T02:17:19Z" level=info msg="successfully loaded cached preset metadata" archive_path=/tmp/TestHubService_Apply_RollbackOnExtractionFailure1106849730/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 slug=test/preset
--- PASS: TestHubService_Apply_RollbackOnExtractionFailure (0.02s)
=== CONT TestFindPreviewFileFromArchive/returns_empty_for_no_yaml
time="2026-01-10T02:17:19Z" level=info msg="storing preset in cache" archive_size=102 etag=etag2 hub_endpoint="http://test.hub/preset.tgz" preview_size=3 slug=test/preset
time="2026-01-10T02:17:19Z" level=info msg="preset successfully stored in cache" archive_path=/tmp/TestHubService_Apply_CacheRefresh936131160/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 meta_path=/tmp/TestHubService_Apply_CacheRefresh936131160/001/test/preset/metadata.json preview_path=/tmp/TestHubService_Apply_CacheRefresh936131160/001/test/preset/preview.yaml slug=test/preset
time="2026-01-10T02:17:19Z" level=info msg="preset successfully cached" archive_path=/tmp/TestHubService_Apply_CacheRefresh936131160/001/test/preset/bundle.tgz cache_key=test/preset-1768011439 preview_path=/tmp/TestHubService_Apply_CacheRefresh936131160/001/test/preset/preview.yaml slug=test/preset
=== CONT TestFindPreviewFileFromArchive/returns_empty_for_invalid_archive
=== CONT TestHasCSCLI/cscli_available
--- PASS: TestHubService_Apply_CacheRefresh (0.04s)
=== CONT TestBuildIndexURL/empty_base_uses_default
=== CONT TestBuildIndexURL/case_insensitive_json
=== CONT TestBuildIndexURL/direct_json_url_unchanged
=== CONT TestBuildIndexURL/trailing_slash_removed
=== CONT TestHasCSCLI/cscli_not_found
=== CONT TestNormalizeHubBaseURL/empty_uses_default
=== CONT TestBuildIndexURL/standard_base_appends_path
--- PASS: TestBuildIndexURL (0.00s)
--- PASS: TestBuildIndexURL/empty_base_uses_default (0.00s)
--- PASS: TestBuildIndexURL/case_insensitive_json (0.00s)
--- PASS: TestBuildIndexURL/direct_json_url_unchanged (0.00s)
--- PASS: TestBuildIndexURL/trailing_slash_removed (0.00s)
--- PASS: TestBuildIndexURL/standard_base_appends_path (0.00s)
--- PASS: TestHasCSCLI (0.00s)
--- PASS: TestHasCSCLI/cscli_available (0.00s)
--- PASS: TestHasCSCLI/cscli_not_found (0.00s)
=== CONT TestUniqueStrings/preserves_order
=== CONT TestUniqueStrings/all_duplicates
=== CONT TestUniqueStrings/no_duplicates
=== CONT TestUniqueStrings/empty_slice
=== CONT TestUniqueStrings/with_duplicates
=== CONT TestNormalizeHubBaseURL/whitespace_uses_default
=== CONT TestNormalizeHubBaseURL/no_slash_unchanged
=== CONT TestNormalizeHubBaseURL/trims_spaces
=== CONT TestNormalizeHubBaseURL/removes_multiple_trailing_slashes
=== CONT TestFirstNonEmpty/whitespace_with_content
=== CONT TestFirstNonEmpty/tabs_and_newlines
=== CONT TestNormalizeHubBaseURL/removes_trailing_slash
=== CONT TestFirstNonEmpty/empty_slice
--- PASS: TestUniqueStrings (0.00s)
--- PASS: TestUniqueStrings/preserves_order (0.00s)
--- PASS: TestUniqueStrings/all_duplicates (0.00s)
--- PASS: TestUniqueStrings/empty_slice (0.00s)
--- PASS: TestUniqueStrings/with_duplicates (0.00s)
--- PASS: TestUniqueStrings/no_duplicates (0.00s)
--- PASS: TestNormalizeHubBaseURL (0.00s)
--- PASS: TestNormalizeHubBaseURL/empty_uses_default (0.00s)
--- PASS: TestNormalizeHubBaseURL/whitespace_uses_default (0.00s)
--- PASS: TestNormalizeHubBaseURL/no_slash_unchanged (0.00s)
--- PASS: TestNormalizeHubBaseURL/trims_spaces (0.00s)
--- PASS: TestNormalizeHubBaseURL/removes_multiple_trailing_slashes (0.00s)
--- PASS: TestNormalizeHubBaseURL/removes_trailing_slash (0.00s)
=== CONT TestFirstNonEmpty/whitespace_treated_as_empty
=== CONT TestFirstNonEmpty/first_is_non-empty
=== CONT TestFirstNonEmpty/all_empty
=== CONT TestFirstNonEmpty/first_non-empty
--- PASS: TestFirstNonEmpty (0.00s)
--- PASS: TestFirstNonEmpty/whitespace_with_content (0.00s)
--- PASS: TestFirstNonEmpty/tabs_and_newlines (0.00s)
--- PASS: TestFirstNonEmpty/empty_slice (0.00s)
--- PASS: TestFirstNonEmpty/first_is_non-empty (0.00s)
--- PASS: TestFirstNonEmpty/whitespace_treated_as_empty (0.00s)
--- PASS: TestFirstNonEmpty/all_empty (0.00s)
--- PASS: TestFirstNonEmpty/first_non-empty (0.00s)
=== CONT TestCleanShellArg/clean_slug
=== CONT TestCleanShellArg/parenthesis
=== CONT TestCleanShellArg/backslash_converted
=== CONT TestCleanShellArg/dollar
=== CONT TestCleanShellArg/backtick
=== CONT TestCleanShellArg/pipe
=== CONT TestCleanShellArg/ampersand
=== CONT TestCleanShellArg/colon_not_allowed
=== CONT TestCleanShellArg/with_dot
=== CONT TestCleanShellArg/semicolon
=== CONT TestCleanShellArg/absolute_path
=== CONT TestCleanShellArg/with_dash
=== CONT TestCleanShellArg/path_traversal
=== CONT TestHubCacheTTL/returns_zero_TTL_if_configured
=== CONT TestCleanShellArg/with_underscore
=== CONT TestHubCacheTTL/returns_minute_TTL
=== CONT TestHubCacheTTL/returns_configured_TTL
=== CONT TestFindPresetCaseVariants/another_preset
--- PASS: TestCleanShellArg (0.01s)
--- PASS: TestCleanShellArg/parenthesis (0.00s)
--- PASS: TestCleanShellArg/clean_slug (0.00s)
--- PASS: TestCleanShellArg/backslash_converted (0.00s)
--- PASS: TestCleanShellArg/backtick (0.00s)
--- PASS: TestCleanShellArg/dollar (0.00s)
--- PASS: TestCleanShellArg/pipe (0.00s)
--- PASS: TestCleanShellArg/colon_not_allowed (0.00s)
--- PASS: TestCleanShellArg/ampersand (0.00s)
--- PASS: TestCleanShellArg/semicolon (0.00s)
--- PASS: TestCleanShellArg/with_dash (0.00s)
--- PASS: TestCleanShellArg/absolute_path (0.00s)
--- PASS: TestCleanShellArg/with_dot (0.00s)
--- PASS: TestCleanShellArg/with_underscore (0.00s)
--- PASS: TestCleanShellArg/path_traversal (0.00s)
=== CONT TestFindPresetCaseVariants/empty_slug
=== CONT TestFindPresetCaseVariants/case_sensitive_miss
=== CONT TestFindPresetCaseVariants/partial_match_miss
=== CONT TestFindPresetCaseVariants/exact_match
=== CONT TestRollback/rollback_with_backup
=== CONT TestRollback/rollback_with_empty_backup_path
--- PASS: TestFindPresetCaseVariants (0.00s)
--- PASS: TestFindPresetCaseVariants/another_preset (0.00s)
--- PASS: TestFindPresetCaseVariants/empty_slug (0.00s)
--- PASS: TestFindPresetCaseVariants/case_sensitive_miss (0.00s)
--- PASS: TestFindPresetCaseVariants/partial_match_miss (0.00s)
--- PASS: TestFindPresetCaseVariants/exact_match (0.00s)
=== CONT TestValidateHubURL_EdgeCases/Missing_hostname
--- PASS: TestFindPreviewFileFromArchive (0.00s)
--- PASS: TestFindPreviewFileFromArchive/finds_yaml_in_archive (0.01s)
--- PASS: TestFindPreviewFileFromArchive/returns_empty_for_invalid_archive (0.00s)
--- PASS: TestFindPreviewFileFromArchive/returns_empty_for_no_yaml (0.02s)
=== CONT TestHubHTTPErrorUnwrap/unwrap_returns_nil_when_no_inner
=== CONT TestValidateHubURL_EdgeCases/IPv6_loopback_allowed
=== CONT TestValidateHubURL_EdgeCases/Subdomain_of_example.com_allowed
--- PASS: TestHubCacheTTL (0.01s)
--- PASS: TestHubCacheTTL/returns_zero_TTL_if_configured (0.00s)
--- PASS: TestHubCacheTTL/returns_minute_TTL (0.00s)
--- PASS: TestHubCacheTTL/returns_configured_TTL (0.00s)
=== CONT TestRollback/rollback_with_non-existent_backup
=== CONT TestValidateHubURL_EdgeCases/Unknown_production_domain_rejected
=== CONT TestValidateHubURL_EdgeCases/.local_domain_allowed
=== CONT TestValidateHubURL_EdgeCases/Example.com_allowed_for_testing
=== CONT TestValidateHubURL_EdgeCases/File_scheme_rejected
=== CONT TestValidateHubURL_EdgeCases/Test_domain_allowed
=== CONT TestValidateHubURL_EdgeCases/Invalid_URL_format_-_unsupported_scheme_caught
--- PASS: TestRollback (0.00s)
--- PASS: TestRollback/rollback_with_empty_backup_path (0.00s)
--- PASS: TestRollback/rollback_with_backup (0.00s)
--- PASS: TestRollback/rollback_with_non-existent_backup (0.00s)
=== CONT TestValidateHubURL_EdgeCases/FTP_scheme_rejected
=== CONT TestHubHTTPErrorCanFallback/returns_false_when_fallback_is_false
=== CONT TestHubHTTPErrorCanFallback/returns_true_when_fallback_is_true
=== CONT TestHubHTTPErrorUnwrap/errors.Is_works_through_Unwrap
=== CONT TestHubHTTPErrorUnwrap/unwrap_returns_inner_error
--- PASS: TestHubHTTPErrorUnwrap (0.00s)
--- PASS: TestHubHTTPErrorUnwrap/unwrap_returns_nil_when_no_inner (0.00s)
--- PASS: TestHubHTTPErrorUnwrap/errors.Is_works_through_Unwrap (0.00s)
--- PASS: TestHubHTTPErrorUnwrap/unwrap_returns_inner_error (0.00s)
=== CONT TestBackupExisting/backup_contents_match_original
--- PASS: TestHubHTTPErrorCanFallback (0.00s)
--- PASS: TestHubHTTPErrorCanFallback/returns_false_when_fallback_is_false (0.00s)
--- PASS: TestHubHTTPErrorCanFallback/returns_true_when_fallback_is_true (0.00s)
=== CONT TestBackupExisting/creates_backup_of_existing_directory
=== CONT TestBackupExisting/handles_non-existent_directory
=== CONT TestExtractTarGz/extracts_valid_archive
=== CONT TestExtractTarGz/handles_context_cancellation
=== CONT TestExtractTarGz/creates_nested_directories
=== CONT TestExtractTarGz/handles_corrupted_gzip
=== CONT TestExtractTarGz/rejects_symlinks
=== CONT TestExtractTarGz/rejects_path_traversal
--- PASS: TestBackupExisting (0.00s)
--- PASS: TestBackupExisting/backup_contents_match_original (0.00s)
--- PASS: TestBackupExisting/creates_backup_of_existing_directory (0.00s)
--- PASS: TestBackupExisting/handles_non-existent_directory (0.00s)
--- PASS: TestValidateHubURL_EdgeCases (0.00s)
--- PASS: TestValidateHubURL_EdgeCases/IPv6_loopback_allowed (0.00s)
--- PASS: TestValidateHubURL_EdgeCases/Missing_hostname (0.00s)
--- PASS: TestValidateHubURL_EdgeCases/Unknown_production_domain_rejected (0.00s)
--- PASS: TestValidateHubURL_EdgeCases/.local_domain_allowed (0.00s)
--- PASS: TestValidateHubURL_EdgeCases/Example.com_allowed_for_testing (0.00s)
--- PASS: TestValidateHubURL_EdgeCases/File_scheme_rejected (0.00s)
--- PASS: TestValidateHubURL_EdgeCases/Test_domain_allowed (0.00s)
--- PASS: TestValidateHubURL_EdgeCases/Invalid_URL_format_-_unsupported_scheme_caught (0.00s)
--- PASS: TestValidateHubURL_EdgeCases/FTP_scheme_rejected (0.00s)
--- PASS: TestValidateHubURL_EdgeCases/Subdomain_of_example.com_allowed (0.00s)
=== CONT TestHubHTTPErrorError/error_without_inner_error
=== CONT TestHubHTTPErrorError/error_with_inner_error
=== CONT TestEmptyDir/handles_non-existent_directory
--- PASS: TestHubHTTPErrorError (0.00s)
--- PASS: TestHubHTTPErrorError/error_without_inner_error (0.00s)
--- PASS: TestHubHTTPErrorError/error_with_inner_error (0.00s)
=== CONT TestEmptyDir/handles_empty_directory
=== CONT TestEmptyDir/empties_directory_with_subdirectories
=== CONT TestEmptyDir/empties_directory_with_files
=== CONT TestCopyDirAndCopyFile/copyFile_preserves_permissions
--- PASS: TestEmptyDir (0.00s)
--- PASS: TestEmptyDir/handles_non-existent_directory (0.00s)
--- PASS: TestEmptyDir/handles_empty_directory (0.00s)
--- PASS: TestEmptyDir/empties_directory_with_files (0.00s)
--- PASS: TestEmptyDir/empties_directory_with_subdirectories (0.01s)
=== CONT TestCopyDirAndCopyFile/copyDir_fails_on_non-directory_source
=== CONT TestCopyDirAndCopyFile/copyDir_with_nested_structure
=== CONT TestParseRawIndex/parses_valid_raw_index
--- PASS: TestExtractTarGz (0.00s)
--- PASS: TestExtractTarGz/extracts_valid_archive (0.01s)
--- PASS: TestExtractTarGz/handles_corrupted_gzip (0.00s)
--- PASS: TestExtractTarGz/creates_nested_directories (0.01s)
--- PASS: TestExtractTarGz/rejects_symlinks (0.01s)
--- PASS: TestExtractTarGz/handles_context_cancellation (0.03s)
--- PASS: TestExtractTarGz/rejects_path_traversal (0.02s)
=== CONT TestCopyDirAndCopyFile/copyFile_success
=== CONT TestParseRawIndex/returns_error_on_empty_index
=== CONT TestParseRawIndex/returns_error_on_invalid_JSON
=== CONT TestValidateHubURL_HTTPRejectedForProduction/http://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json
--- PASS: TestParseRawIndex (0.00s)
--- PASS: TestParseRawIndex/parses_valid_raw_index (0.00s)
--- PASS: TestParseRawIndex/returns_error_on_empty_index (0.00s)
--- PASS: TestParseRawIndex/returns_error_on_invalid_JSON (0.00s)
=== CONT TestValidateHubURL_HTTPRejectedForProduction/http://hub.crowdsec.net/api/index.json
=== CONT TestValidateHubURL_HTTPRejectedForProduction/http://hub-data.crowdsec.net/api/index.json
--- PASS: TestValidateHubURL_HTTPRejectedForProduction (0.00s)
--- PASS: TestValidateHubURL_HTTPRejectedForProduction/http://raw.githubusercontent.com/crowdsecurity/hub/master/.index.json (0.00s)
--- PASS: TestValidateHubURL_HTTPRejectedForProduction/http://hub.crowdsec.net/api/index.json (0.00s)
--- PASS: TestValidateHubURL_HTTPRejectedForProduction/http://hub-data.crowdsec.net/api/index.json (0.00s)
=== CONT TestBuildResourceURLs/removes_duplicates
=== CONT TestBuildResourceURLs/handles_empty_bases
=== CONT TestBuildResourceURLs/without_explicit_URL
=== CONT TestBuildResourceURLs/with_explicit_URL
=== CONT TestValidateHubURL_LocalhostExceptions/http://127.0.0.1:8080/index.json
=== CONT TestValidateHubURL_LocalhostExceptions/http://server.local/api/index.json
--- PASS: TestBuildResourceURLs (0.00s)
--- PASS: TestBuildResourceURLs/removes_duplicates (0.00s)
--- PASS: TestBuildResourceURLs/handles_empty_bases (0.00s)
--- PASS: TestBuildResourceURLs/without_explicit_URL (0.00s)
--- PASS: TestBuildResourceURLs/with_explicit_URL (0.00s)
=== CONT TestValidateHubURL_LocalhostExceptions/http://test.example.com/api/index.json
=== CONT TestValidateHubURL_LocalhostExceptions/http://example.com/api/index.json
=== CONT TestValidateHubURL_LocalhostExceptions/http://[::1]:8080/index.json
=== CONT TestValidateHubURL_LocalhostExceptions/http://test.hub/api/index.json
=== CONT TestValidateHubURL_LocalhostExceptions/http://localhost:8080/index.json
--- PASS: TestValidateHubURL_LocalhostExceptions (0.00s)
--- PASS: TestValidateHubURL_LocalhostExceptions/http://127.0.0.1:8080/index.json (0.00s)
--- PASS: TestValidateHubURL_LocalhostExceptions/http://server.local/api/index.json (0.00s)
--- PASS: TestValidateHubURL_LocalhostExceptions/http://test.example.com/api/index.json (0.00s)
--- PASS: TestValidateHubURL_LocalhostExceptions/http://example.com/api/index.json (0.00s)
--- PASS: TestValidateHubURL_LocalhostExceptions/http://[::1]:8080/index.json (0.00s)
--- PASS: TestValidateHubURL_LocalhostExceptions/http://test.hub/api/index.json (0.00s)
--- PASS: TestValidateHubURL_LocalhostExceptions/http://localhost:8080/index.json (0.00s)
=== CONT TestValidateHubURL_InvalidSchemes/ftp://hub.crowdsec.net/index.json
=== CONT TestValidateHubURL_InvalidSchemes/gopher://attacker.com
=== CONT TestValidateHubURL_InvalidSchemes/file:///etc/passwd
=== CONT TestValidateHubURL_InvalidSchemes/data:text/html,<script>alert('xss')</script>
--- PASS: TestValidateHubURL_InvalidSchemes (0.00s)
--- PASS: TestValidateHubURL_InvalidSchemes/ftp://hub.crowdsec.net/index.json (0.00s)
--- PASS: TestValidateHubURL_InvalidSchemes/gopher://attacker.com (0.00s)
--- PASS: TestValidateHubURL_InvalidSchemes/file:///etc/passwd (0.00s)
--- PASS: TestValidateHubURL_InvalidSchemes/data:text/html,<script>alert('xss')</script> (0.00s)
--- PASS: TestCopyDirAndCopyFile (0.00s)
--- PASS: TestCopyDirAndCopyFile/copyDir_fails_on_non-directory_source (0.00s)
--- PASS: TestCopyDirAndCopyFile/copyFile_preserves_permissions (0.01s)
--- PASS: TestCopyDirAndCopyFile/copyFile_success (0.01s)
--- PASS: TestCopyDirAndCopyFile/copyDir_with_nested_structure (0.01s)
--- PASS: TestFetchWithLimitRejectsLargePayload (0.77s)
PASS
coverage: 85.8% of statements
ok github.com/Wikid82/charon/backend/internal/crowdsec (cached) coverage: 85.8% of statements
=== RUN TestNewEncryptionService_ValidKey
--- PASS: TestNewEncryptionService_ValidKey (0.00s)
=== RUN TestNewEncryptionService_InvalidBase64
--- PASS: TestNewEncryptionService_InvalidBase64 (0.00s)
=== RUN TestNewEncryptionService_WrongKeyLength
=== RUN TestNewEncryptionService_WrongKeyLength/16_bytes
=== RUN TestNewEncryptionService_WrongKeyLength/24_bytes
=== RUN TestNewEncryptionService_WrongKeyLength/31_bytes
=== RUN TestNewEncryptionService_WrongKeyLength/33_bytes
=== RUN TestNewEncryptionService_WrongKeyLength/0_bytes
--- PASS: TestNewEncryptionService_WrongKeyLength (0.00s)
--- PASS: TestNewEncryptionService_WrongKeyLength/16_bytes (0.00s)
--- PASS: TestNewEncryptionService_WrongKeyLength/24_bytes (0.00s)
--- PASS: TestNewEncryptionService_WrongKeyLength/31_bytes (0.00s)
--- PASS: TestNewEncryptionService_WrongKeyLength/33_bytes (0.00s)
--- PASS: TestNewEncryptionService_WrongKeyLength/0_bytes (0.00s)
=== RUN TestEncryptDecrypt_RoundTrip
=== RUN TestEncryptDecrypt_RoundTrip/simple_text
=== RUN TestEncryptDecrypt_RoundTrip/with_special_chars
=== RUN TestEncryptDecrypt_RoundTrip/json_data
=== RUN TestEncryptDecrypt_RoundTrip/unicode
=== RUN TestEncryptDecrypt_RoundTrip/long_text
--- PASS: TestEncryptDecrypt_RoundTrip (0.00s)
--- PASS: TestEncryptDecrypt_RoundTrip/simple_text (0.00s)
--- PASS: TestEncryptDecrypt_RoundTrip/with_special_chars (0.00s)
--- PASS: TestEncryptDecrypt_RoundTrip/json_data (0.00s)
--- PASS: TestEncryptDecrypt_RoundTrip/unicode (0.00s)
--- PASS: TestEncryptDecrypt_RoundTrip/long_text (0.00s)
=== RUN TestEncrypt_EmptyPlaintext
--- PASS: TestEncrypt_EmptyPlaintext (0.00s)
=== RUN TestDecrypt_InvalidCiphertext
=== RUN TestDecrypt_InvalidCiphertext/invalid_base64
=== RUN TestDecrypt_InvalidCiphertext/too_short
=== RUN TestDecrypt_InvalidCiphertext/empty_string
--- PASS: TestDecrypt_InvalidCiphertext (0.00s)
--- PASS: TestDecrypt_InvalidCiphertext/invalid_base64 (0.00s)
--- PASS: TestDecrypt_InvalidCiphertext/too_short (0.00s)
--- PASS: TestDecrypt_InvalidCiphertext/empty_string (0.00s)
=== RUN TestDecrypt_TamperedCiphertext
--- PASS: TestDecrypt_TamperedCiphertext (0.00s)
=== RUN TestEncrypt_DifferentNonces
--- PASS: TestEncrypt_DifferentNonces (0.00s)
=== RUN TestDecrypt_WrongKey
--- PASS: TestDecrypt_WrongKey (0.00s)
=== RUN TestEncrypt_NilPlaintext
--- PASS: TestEncrypt_NilPlaintext (0.00s)
=== RUN TestDecrypt_ExactNonceSize
--- PASS: TestDecrypt_ExactNonceSize (0.00s)
=== RUN TestDecrypt_OneByteLessThanNonce
--- PASS: TestDecrypt_OneByteLessThanNonce (0.00s)
=== RUN TestEncryptDecrypt_BinaryData
--- PASS: TestEncryptDecrypt_BinaryData (0.00s)
=== RUN TestEncryptDecrypt_LargePlaintext
--- PASS: TestEncryptDecrypt_LargePlaintext (0.13s)
=== RUN TestDecrypt_CorruptedNonce
--- PASS: TestDecrypt_CorruptedNonce (0.00s)
=== RUN TestDecrypt_TruncatedCiphertext
--- PASS: TestDecrypt_TruncatedCiphertext (0.00s)
=== RUN TestDecrypt_AppendedData
--- PASS: TestDecrypt_AppendedData (0.00s)
=== RUN TestEncryptionService_ConcurrentAccess
--- PASS: TestEncryptionService_ConcurrentAccess (0.01s)
=== RUN TestDecrypt_AllZerosCiphertext
--- PASS: TestDecrypt_AllZerosCiphertext (0.00s)
=== RUN TestDecrypt_RandomGarbageCiphertext
--- PASS: TestDecrypt_RandomGarbageCiphertext (0.00s)
=== RUN TestNewEncryptionService_EmptyKey
--- PASS: TestNewEncryptionService_EmptyKey (0.00s)
=== RUN TestNewEncryptionService_WhitespaceKey
--- PASS: TestNewEncryptionService_WhitespaceKey (0.00s)
=== RUN TestEncrypt_CipherCreationError
--- PASS: TestEncrypt_CipherCreationError (0.00s)
=== RUN TestEncrypt_GCMCreationError
--- PASS: TestEncrypt_GCMCreationError (0.00s)
=== RUN TestEncrypt_NonceGenerationError
--- PASS: TestEncrypt_NonceGenerationError (0.00s)
=== RUN TestDecrypt_CipherCreationError
--- PASS: TestDecrypt_CipherCreationError (0.00s)
=== RUN TestDecrypt_GCMCreationError
--- PASS: TestDecrypt_GCMCreationError (0.00s)
=== RUN TestNewRotationService
=== RUN TestNewRotationService/successful_initialization_with_current_key_only
=== RUN TestNewRotationService/successful_initialization_with_next_key
=== RUN TestNewRotationService/successful_initialization_with_legacy_keys
=== RUN TestNewRotationService/fails_without_current_key
=== RUN TestNewRotationService/handles_invalid_next_key_gracefully
--- PASS: TestNewRotationService (0.01s)
--- PASS: TestNewRotationService/successful_initialization_with_current_key_only (0.00s)
--- PASS: TestNewRotationService/successful_initialization_with_next_key (0.00s)
--- PASS: TestNewRotationService/successful_initialization_with_legacy_keys (0.00s)
--- PASS: TestNewRotationService/fails_without_current_key (0.00s)
--- PASS: TestNewRotationService/handles_invalid_next_key_gracefully (0.00s)
=== RUN TestEncryptWithCurrentKey
=== RUN TestEncryptWithCurrentKey/encrypts_with_current_key_when_no_next_key
=== RUN TestEncryptWithCurrentKey/encrypts_with_next_key_when_configured
--- PASS: TestEncryptWithCurrentKey (0.01s)
--- PASS: TestEncryptWithCurrentKey/encrypts_with_current_key_when_no_next_key (0.00s)
--- PASS: TestEncryptWithCurrentKey/encrypts_with_next_key_when_configured (0.00s)
=== RUN TestDecryptWithVersion
=== RUN TestDecryptWithVersion/decrypts_with_correct_version
=== RUN TestDecryptWithVersion/falls_back_to_other_versions_on_failure
rotation_service_test.go:155: Version fallback edge case - functionality verified in integration test
=== RUN TestDecryptWithVersion/fails_when_no_keys_can_decrypt
--- PASS: TestDecryptWithVersion (0.01s)
--- PASS: TestDecryptWithVersion/decrypts_with_correct_version (0.00s)
--- SKIP: TestDecryptWithVersion/falls_back_to_other_versions_on_failure (0.00s)
--- PASS: TestDecryptWithVersion/fails_when_no_keys_can_decrypt (0.00s)
=== RUN TestRotateAllCredentials
=== RUN TestRotateAllCredentials/successfully_rotates_all_providers
=== RUN TestRotateAllCredentials/fails_when_next_key_not_configured
=== RUN TestRotateAllCredentials/handles_partial_failures
Failed to rotate provider 1 (Corrupted): failed to decrypt credentials: failed to decrypt with version 1 or any fallback version
--- PASS: TestRotateAllCredentials (0.02s)
--- PASS: TestRotateAllCredentials/successfully_rotates_all_providers (0.01s)
--- PASS: TestRotateAllCredentials/fails_when_next_key_not_configured (0.00s)
--- PASS: TestRotateAllCredentials/handles_partial_failures (0.01s)
=== RUN TestGetStatus
=== RUN TestGetStatus/returns_correct_status_with_no_providers
=== RUN TestGetStatus/returns_correct_status_with_next_key_configured
=== RUN TestGetStatus/returns_correct_status_with_legacy_keys
=== RUN TestGetStatus/counts_providers_by_version
--- PASS: TestGetStatus (0.00s)
--- PASS: TestGetStatus/returns_correct_status_with_no_providers (0.00s)
--- PASS: TestGetStatus/returns_correct_status_with_next_key_configured (0.00s)
--- PASS: TestGetStatus/returns_correct_status_with_legacy_keys (0.00s)
--- PASS: TestGetStatus/counts_providers_by_version (0.00s)
=== RUN TestValidateKeyConfiguration
=== RUN TestValidateKeyConfiguration/validates_current_key_successfully
=== RUN TestValidateKeyConfiguration/validates_next_key_successfully
=== RUN TestValidateKeyConfiguration/validates_legacy_keys_successfully
--- PASS: TestValidateKeyConfiguration (0.00s)
--- PASS: TestValidateKeyConfiguration/validates_current_key_successfully (0.00s)
--- PASS: TestValidateKeyConfiguration/validates_next_key_successfully (0.00s)
--- PASS: TestValidateKeyConfiguration/validates_legacy_keys_successfully (0.00s)
=== RUN TestGenerateNewKey
=== RUN TestGenerateNewKey/generates_valid_base64_key
=== RUN TestGenerateNewKey/generates_unique_keys
--- PASS: TestGenerateNewKey (0.00s)
--- PASS: TestGenerateNewKey/generates_valid_base64_key (0.00s)
--- PASS: TestGenerateNewKey/generates_unique_keys (0.00s)
=== RUN TestRotationServiceConcurrency
--- PASS: TestRotationServiceConcurrency (0.01s)
=== RUN TestRotationServiceZeroDowntime
=== RUN TestRotationServiceZeroDowntime/step_1:_initial_setup_with_current_key
=== RUN TestRotationServiceZeroDowntime/step_2:_configure_next_key_and_rotate
=== RUN TestRotationServiceZeroDowntime/step_3:_promote_next_to_current
Warning: credential decrypted with version 1 but was tagged as version 2
--- PASS: TestRotationServiceZeroDowntime (0.00s)
--- PASS: TestRotationServiceZeroDowntime/step_1:_initial_setup_with_current_key (0.00s)
--- PASS: TestRotationServiceZeroDowntime/step_2:_configure_next_key_and_rotate (0.00s)
--- PASS: TestRotationServiceZeroDowntime/step_3:_promote_next_to_current (0.00s)
PASS
coverage: 86.9% of statements
ok github.com/Wikid82/charon/backend/internal/crypto (cached) coverage: 86.9% of statements
=== RUN TestConnect
=== PAUSE TestConnect
=== RUN TestConnect_Error
=== PAUSE TestConnect_Error
=== RUN TestConnect_WALMode
=== PAUSE TestConnect_WALMode
=== RUN TestConnect_InvalidDSN
=== PAUSE TestConnect_InvalidDSN
=== RUN TestConnect_IntegrityCheckCorrupted
=== PAUSE TestConnect_IntegrityCheckCorrupted
=== RUN TestConnect_PRAGMAVerification
=== PAUSE TestConnect_PRAGMAVerification
=== RUN TestConnect_CorruptedDatabase_FullIntegrationScenario
=== PAUSE TestConnect_CorruptedDatabase_FullIntegrationScenario
=== RUN TestIsCorruptionError
=== PAUSE TestIsCorruptionError
=== RUN TestLogCorruptionError
=== PAUSE TestLogCorruptionError
=== RUN TestCheckIntegrity
=== PAUSE TestCheckIntegrity
=== RUN TestLogCorruptionError_EmptyContext
=== PAUSE TestLogCorruptionError_EmptyContext
=== RUN TestCheckIntegrity_ActualCorruption
=== PAUSE TestCheckIntegrity_ActualCorruption
=== RUN TestCheckIntegrity_PRAGMAError
=== PAUSE TestCheckIntegrity_PRAGMAError
=== CONT TestConnect
time="2026-01-10T02:17:08Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=memory
time="2026-01-10T02:17:08Z" level=info msg="SQLite database integrity check passed"
=== CONT TestIsCorruptionError
=== RUN TestIsCorruptionError/nil_error
=== CONT TestConnect_IntegrityCheckCorrupted
=== RUN TestIsCorruptionError/generic_error
=== RUN TestIsCorruptionError/database_disk_image_is_malformed
=== RUN TestIsCorruptionError/malformed_in_message
=== RUN TestIsCorruptionError/corrupt_database
=== CONT TestCheckIntegrity
=== RUN TestCheckIntegrity/healthy_database_returns_ok
=== RUN TestIsCorruptionError/disk_I/O_error
=== RUN TestIsCorruptionError/file_is_not_a_database
=== RUN TestIsCorruptionError/file_is_encrypted_or_is_not_a_database
=== RUN TestIsCorruptionError/database_or_disk_is_full
=== RUN TestIsCorruptionError/case_insensitive_-_MALFORMED_uppercase
=== RUN TestIsCorruptionError/wrapped_error_with_corruption
=== RUN TestIsCorruptionError/network_error_-_not_corruption
=== RUN TestIsCorruptionError/record_not_found_-_not_corruption
=== RUN TestIsCorruptionError/constraint_violation_-_not_corruption
time="2026-01-10T02:17:08Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=memory
--- PASS: TestIsCorruptionError (0.00s)
--- PASS: TestIsCorruptionError/nil_error (0.00s)
--- PASS: TestIsCorruptionError/generic_error (0.00s)
--- PASS: TestIsCorruptionError/database_disk_image_is_malformed (0.00s)
--- PASS: TestIsCorruptionError/malformed_in_message (0.00s)
--- PASS: TestIsCorruptionError/corrupt_database (0.00s)
--- PASS: TestIsCorruptionError/disk_I/O_error (0.00s)
--- PASS: TestIsCorruptionError/file_is_not_a_database (0.00s)
--- PASS: TestIsCorruptionError/file_is_encrypted_or_is_not_a_database (0.00s)
--- PASS: TestIsCorruptionError/database_or_disk_is_full (0.00s)
--- PASS: TestIsCorruptionError/case_insensitive_-_MALFORMED_uppercase (0.00s)
--- PASS: TestIsCorruptionError/wrapped_error_with_corruption (0.00s)
--- PASS: TestIsCorruptionError/network_error_-_not_corruption (0.00s)
--- PASS: TestIsCorruptionError/record_not_found_-_not_corruption (0.00s)
--- PASS: TestIsCorruptionError/constraint_violation_-_not_corruption (0.00s)
=== CONT TestCheckIntegrity_ActualCorruption
time="2026-01-10T02:17:08Z" level=info msg="SQLite database integrity check passed"
=== RUN TestCheckIntegrity/file-based_database_passes_check
time="2026-01-10T02:17:08Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
time="2026-01-10T02:17:08Z" level=info msg="SQLite database integrity check passed"
time="2026-01-10T02:17:08Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
time="2026-01-10T02:17:08Z" level=info msg="SQLite database integrity check passed"
--- PASS: TestConnect (0.02s)
=== CONT TestLogCorruptionError_EmptyContext
time="2026-01-10T02:17:08Z" level=error msg="SQLite database corruption detected" error="database disk image is malformed" error_type=database_corruption
--- PASS: TestLogCorruptionError_EmptyContext (0.00s)
=== CONT TestLogCorruptionError
=== RUN TestLogCorruptionError/nil_error_does_not_panic
=== RUN TestLogCorruptionError/logs_with_context
time="2026-01-10T02:17:08Z" level=error msg="SQLite database corruption detected" error="database disk image is malformed" error_type=database_corruption monitor_id=test-uuid operation=GetMonitorHistory table=uptime_heartbeats
=== RUN TestLogCorruptionError/logs_without_context
time="2026-01-10T02:17:08Z" level=error msg="SQLite database corruption detected" error="database corrupt" error_type=database_corruption
--- PASS: TestLogCorruptionError (0.00s)
--- PASS: TestLogCorruptionError/nil_error_does_not_panic (0.00s)
--- PASS: TestLogCorruptionError/logs_with_context (0.00s)
--- PASS: TestLogCorruptionError/logs_without_context (0.00s)
=== CONT TestCheckIntegrity_PRAGMAError
time="2026-01-10T02:17:08Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
time="2026-01-10T02:17:08Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
time="2026-01-10T02:17:08Z" level=info msg="SQLite database integrity check passed"
time="2026-01-10T02:17:08Z" level=info msg="SQLite database integrity check passed"
--- PASS: TestCheckIntegrity (0.02s)
--- PASS: TestCheckIntegrity/healthy_database_returns_ok (0.00s)
--- PASS: TestCheckIntegrity/file-based_database_passes_check (0.02s)
=== CONT TestConnect_InvalidDSN
time="2026-01-10T02:17:08Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
--- PASS: TestConnect_InvalidDSN (0.00s)
=== CONT TestConnect_PRAGMAVerification
time="2026-01-10T02:17:08Z" level=info msg="SQLite database integrity check passed"
2026/01/10 02:17:08 /projects/Charon/backend/internal/database/errors.go:63 sql: database is closed
[0.039ms] [rows:-] PRAGMA quick_check
--- PASS: TestCheckIntegrity_PRAGMAError (0.01s)
=== CONT TestConnect_CorruptedDatabase_FullIntegrationScenario
time="2026-01-10T02:17:08Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
time="2026-01-10T02:17:08Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
2026/01/10 02:17:08 /projects/Charon/backend/internal/database/database.go:57 database disk image is malformed
[0.207ms] [rows:1] PRAGMA quick_check
time="2026-01-10T02:17:08Z" level=warning msg="Failed to run SQLite integrity check on startup" error="database disk image is malformed"
2026/01/10 02:17:08 /projects/Charon/backend/internal/database/database.go:57 database disk image is malformed
[0.224ms] [rows:1] PRAGMA quick_check
time="2026-01-10T02:17:08Z" level=warning msg="Failed to run SQLite integrity check on startup" error="database disk image is malformed"
2026/01/10 02:17:08 /projects/Charon/backend/internal/database/errors.go:63 database disk image is malformed
[0.090ms] [rows:1] PRAGMA quick_check
--- PASS: TestConnect_IntegrityCheckCorrupted (0.03s)
=== CONT TestConnect_Error
--- PASS: TestCheckIntegrity_ActualCorruption (0.03s)
=== CONT TestConnect_WALMode
--- PASS: TestConnect_Error (0.00s)
time="2026-01-10T02:17:08Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
time="2026-01-10T02:17:08Z" level=info msg="SQLite database integrity check passed"
time="2026-01-10T02:17:08Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
time="2026-01-10T02:17:08Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
time="2026-01-10T02:17:08Z" level=info msg="SQLite database integrity check passed"
--- PASS: TestConnect_PRAGMAVerification (0.01s)
time="2026-01-10T02:17:08Z" level=info msg="SQLite database integrity check passed"
--- PASS: TestConnect_WALMode (0.01s)
time="2026-01-10T02:17:08Z" level=info msg="SQLite database connected with WAL mode enabled" journal_mode=wal
2026/01/10 02:17:08 /projects/Charon/backend/internal/database/database.go:57 database disk image is malformed
[0.098ms] [rows:1] PRAGMA quick_check
time="2026-01-10T02:17:08Z" level=warning msg="Failed to run SQLite integrity check on startup" error="database disk image is malformed"
2026/01/10 02:17:08 /projects/Charon/backend/internal/database/database_test.go:169 database disk image is malformed
[0.076ms] [rows:0] SELECT COUNT(*) FROM users
--- PASS: TestConnect_CorruptedDatabase_FullIntegrationScenario (0.02s)
PASS
coverage: 91.3% of statements
ok github.com/Wikid82/charon/backend/internal/database (cached) coverage: 91.3% of statements
=== RUN TestNewBroadcastHook
--- PASS: TestNewBroadcastHook (0.00s)
=== RUN TestBroadcastHook_Levels
--- PASS: TestBroadcastHook_Levels (0.00s)
=== RUN TestBroadcastHook_Subscribe
--- PASS: TestBroadcastHook_Subscribe (0.00s)
=== RUN TestBroadcastHook_Unsubscribe
--- PASS: TestBroadcastHook_Unsubscribe (0.00s)
=== RUN TestInit
--- PASS: TestInit (0.00s)
=== RUN TestLog
--- PASS: TestLog (0.00s)
=== RUN TestWithFields
--- PASS: TestWithFields (0.00s)
=== RUN TestBroadcastHook_Fire
--- PASS: TestBroadcastHook_Fire (0.00s)
=== RUN TestGetBroadcastHook
--- PASS: TestGetBroadcastHook (0.00s)
PASS
coverage: 85.7% of statements
ok github.com/Wikid82/charon/backend/internal/logger (cached) coverage: 85.7% of statements
=== RUN TestMetrics_Register
=== PAUSE TestMetrics_Register
=== RUN TestMetrics_Increment
=== PAUSE TestMetrics_Increment
=== RUN TestRecordURLValidation
=== PAUSE TestRecordURLValidation
=== RUN TestRecordSSRFBlock
=== PAUSE TestRecordSSRFBlock
=== RUN TestRecordURLTestDuration
=== PAUSE TestRecordURLTestDuration
=== RUN TestMetricsLabels
=== PAUSE TestMetricsLabels
=== RUN TestMetricsRegistration
=== PAUSE TestMetricsRegistration
=== CONT TestMetrics_Register
=== CONT TestMetricsRegistration
=== CONT TestRecordURLTestDuration
=== CONT TestRecordSSRFBlock
=== RUN TestRecordSSRFBlock/Private_IP_block
=== NAME TestRecordURLTestDuration
security_metrics_test.go:88: Successfully recorded histogram observations
--- PASS: TestRecordURLTestDuration (0.00s)
=== CONT TestMetrics_Increment
=== PAUSE TestRecordSSRFBlock/Private_IP_block
--- PASS: TestMetrics_Increment (0.00s)
=== CONT TestMetricsLabels
=== RUN TestRecordSSRFBlock/Loopback_block
--- PASS: TestMetricsRegistration (0.00s)
=== CONT TestRecordURLValidation
--- PASS: TestMetricsLabels (0.00s)
=== RUN TestRecordURLValidation/Allowed_validation
--- PASS: TestMetrics_Register (0.00s)
=== PAUSE TestRecordURLValidation/Allowed_validation
=== PAUSE TestRecordSSRFBlock/Loopback_block
=== RUN TestRecordURLValidation/Blocked_private_IP
=== PAUSE TestRecordURLValidation/Blocked_private_IP
=== RUN TestRecordSSRFBlock/Link-local_block
=== RUN TestRecordURLValidation/DNS_failure
=== PAUSE TestRecordSSRFBlock/Link-local_block
=== PAUSE TestRecordURLValidation/DNS_failure
=== RUN TestRecordSSRFBlock/Metadata_endpoint_block
=== RUN TestRecordURLValidation/Invalid_format
=== PAUSE TestRecordURLValidation/Invalid_format
=== PAUSE TestRecordSSRFBlock/Metadata_endpoint_block
=== CONT TestRecordURLValidation/DNS_failure
=== CONT TestRecordSSRFBlock/Link-local_block
=== CONT TestRecordSSRFBlock/Loopback_block
=== CONT TestRecordSSRFBlock/Metadata_endpoint_block
=== CONT TestRecordSSRFBlock/Private_IP_block
=== CONT TestRecordURLValidation/Blocked_private_IP
=== CONT TestRecordURLValidation/Invalid_format
=== CONT TestRecordURLValidation/Allowed_validation
--- PASS: TestRecordSSRFBlock (0.00s)
--- PASS: TestRecordSSRFBlock/Metadata_endpoint_block (0.00s)
--- PASS: TestRecordSSRFBlock/Link-local_block (0.00s)
--- PASS: TestRecordSSRFBlock/Loopback_block (0.00s)
--- PASS: TestRecordSSRFBlock/Private_IP_block (0.00s)
--- PASS: TestRecordURLValidation (0.00s)
--- PASS: TestRecordURLValidation/DNS_failure (0.00s)
--- PASS: TestRecordURLValidation/Blocked_private_IP (0.00s)
--- PASS: TestRecordURLValidation/Allowed_validation (0.00s)
--- PASS: TestRecordURLValidation/Invalid_format (0.00s)
PASS
coverage: 100.0% of statements
ok github.com/Wikid82/charon/backend/internal/metrics (cached) coverage: 100.0% of statements
=== RUN TestDNSProvider_TableName
--- PASS: TestDNSProvider_TableName (0.00s)
=== RUN TestDNSProvider_Fields
--- PASS: TestDNSProvider_Fields (0.00s)
=== RUN TestDNSProvider_CredentialsEncrypted_NotSerialized
--- PASS: TestDNSProvider_CredentialsEncrypted_NotSerialized (0.00s)
=== RUN TestDomain_BeforeCreate
--- PASS: TestDomain_BeforeCreate (0.01s)
=== RUN TestNotificationTemplate_BeforeCreate
--- PASS: TestNotificationTemplate_BeforeCreate (0.01s)
=== RUN TestUptimeHost_BeforeCreate
--- PASS: TestUptimeHost_BeforeCreate (0.02s)
=== RUN TestUptimeNotificationEvent_BeforeCreate
--- PASS: TestUptimeNotificationEvent_BeforeCreate (0.01s)
=== RUN TestNotification_BeforeCreate
--- PASS: TestNotification_BeforeCreate (0.00s)
=== RUN TestNotificationConfig_BeforeCreate
--- PASS: TestNotificationConfig_BeforeCreate (0.00s)
=== RUN TestSecurityHeaderProfile_Create
--- PASS: TestSecurityHeaderProfile_Create (0.01s)
=== RUN TestSecurityHeaderProfile_JSONSerialization
--- PASS: TestSecurityHeaderProfile_JSONSerialization (0.00s)
=== RUN TestCSPDirective_JSONSerialization
--- PASS: TestCSPDirective_JSONSerialization (0.00s)
=== RUN TestPermissionsPolicyItem_JSONSerialization
--- PASS: TestPermissionsPolicyItem_JSONSerialization (0.00s)
=== RUN TestSecurityHeaderProfile_Defaults
--- PASS: TestSecurityHeaderProfile_Defaults (0.00s)
=== RUN TestSecurityHeaderProfile_UniqueUUID
2026/01/10 02:17:11 /projects/Charon/backend/internal/models/security_header_profile_test.go:155 UNIQUE constraint failed: security_header_profiles.uuid
[0.409ms] [rows:0] INSERT INTO `security_header_profiles` (`uuid`,`name`,`hsts_enabled`,`hsts_max_age`,`hsts_include_subdomains`,`hsts_preload`,`csp_enabled`,`csp_directives`,`csp_report_only`,`csp_report_uri`,`x_frame_options`,`x_content_type_options`,`referrer_policy`,`permissions_policy`,`cross_origin_opener_policy`,`cross_origin_resource_policy`,`cross_origin_embedder_policy`,`xss_protection`,`cache_control_no_store`,`security_score`,`is_preset`,`preset_type`,`description`,`created_at`,`updated_at`) VALUES ("12b9b39c-6355-4693-9d69-e600f6161ac0","Profile 2",true,31536000,true,false,false,"",false,"","DENY",true,"strict-origin-when-cross-origin","","same-origin","same-origin","",true,false,0,false,"","","2026-01-10 02:17:11.033","2026-01-10 02:17:11.033") RETURNING `id`
--- PASS: TestSecurityHeaderProfile_UniqueUUID (0.00s)
=== RUN TestSecurityHeaderProfile_CSPDirectivesStorage
--- PASS: TestSecurityHeaderProfile_CSPDirectivesStorage (0.01s)
=== RUN TestSecurityHeaderProfile_PermissionsPolicyStorage
--- PASS: TestSecurityHeaderProfile_PermissionsPolicyStorage (0.00s)
=== RUN TestSecurityHeaderProfile_PresetFields
--- PASS: TestSecurityHeaderProfile_PresetFields (0.00s)
=== RUN TestUser_SetPassword
--- PASS: TestUser_SetPassword (3.06s)
=== RUN TestUser_CheckPassword
--- PASS: TestUser_CheckPassword (2.39s)
=== RUN TestUser_HasPendingInvite
=== RUN TestUser_HasPendingInvite/no_invite_token
=== RUN TestUser_HasPendingInvite/expired_invite
=== RUN TestUser_HasPendingInvite/valid_pending_invite
=== RUN TestUser_HasPendingInvite/already_accepted_invite
--- PASS: TestUser_HasPendingInvite (0.00s)
--- PASS: TestUser_HasPendingInvite/no_invite_token (0.00s)
--- PASS: TestUser_HasPendingInvite/expired_invite (0.00s)
--- PASS: TestUser_HasPendingInvite/valid_pending_invite (0.00s)
--- PASS: TestUser_HasPendingInvite/already_accepted_invite (0.00s)
=== RUN TestUser_CanAccessHost_AllowAll
--- PASS: TestUser_CanAccessHost_AllowAll (0.00s)
=== RUN TestUser_CanAccessHost_DenyAll
--- PASS: TestUser_CanAccessHost_DenyAll (0.00s)
=== RUN TestUser_CanAccessHost_AdminBypass
--- PASS: TestUser_CanAccessHost_AdminBypass (0.00s)
=== RUN TestUser_CanAccessHost_DefaultBehavior
--- PASS: TestUser_CanAccessHost_DefaultBehavior (0.00s)
=== RUN TestUser_CanAccessHost_EmptyPermittedHosts
=== RUN TestUser_CanAccessHost_EmptyPermittedHosts/allow_all_with_no_exceptions_allows_all
=== RUN TestUser_CanAccessHost_EmptyPermittedHosts/deny_all_with_no_exceptions_denies_all
--- PASS: TestUser_CanAccessHost_EmptyPermittedHosts (0.00s)
--- PASS: TestUser_CanAccessHost_EmptyPermittedHosts/allow_all_with_no_exceptions_allows_all (0.00s)
--- PASS: TestUser_CanAccessHost_EmptyPermittedHosts/deny_all_with_no_exceptions_denies_all (0.00s)
=== RUN TestPermissionMode_Constants
--- PASS: TestPermissionMode_Constants (0.00s)
=== RUN TestDNSProviderCredential_TableName
--- PASS: TestDNSProviderCredential_TableName (0.00s)
=== RUN TestDNSProviderCredential_Struct
--- PASS: TestDNSProviderCredential_Struct (0.00s)
=== RUN TestNotificationProvider_BeforeCreate
--- PASS: TestNotificationProvider_BeforeCreate (0.00s)
=== RUN TestUptimeMonitor_BeforeCreate
--- PASS: TestUptimeMonitor_BeforeCreate (0.02s)
PASS
coverage: 96.4% of statements
ok github.com/Wikid82/charon/backend/internal/models (cached) coverage: 96.4% of statements
=== RUN TestNewInternalServiceHTTPClient
=== PAUSE TestNewInternalServiceHTTPClient
=== RUN TestNewInternalServiceHTTPClient_TransportConfiguration
=== PAUSE TestNewInternalServiceHTTPClient_TransportConfiguration
=== RUN TestNewInternalServiceHTTPClient_RedirectsDisabled
=== PAUSE TestNewInternalServiceHTTPClient_RedirectsDisabled
=== RUN TestNewInternalServiceHTTPClient_CheckRedirectReturnsErrUseLastResponse
=== PAUSE TestNewInternalServiceHTTPClient_CheckRedirectReturnsErrUseLastResponse
=== RUN TestNewInternalServiceHTTPClient_ActualRequest
=== PAUSE TestNewInternalServiceHTTPClient_ActualRequest
=== RUN TestNewInternalServiceHTTPClient_TimeoutEnforced
=== PAUSE TestNewInternalServiceHTTPClient_TimeoutEnforced
=== RUN TestNewInternalServiceHTTPClient_MultipleClients
=== PAUSE TestNewInternalServiceHTTPClient_MultipleClients
=== RUN TestNewInternalServiceHTTPClient_ProxyIgnored
=== PAUSE TestNewInternalServiceHTTPClient_ProxyIgnored
=== RUN TestNewInternalServiceHTTPClient_PostRequest
=== PAUSE TestNewInternalServiceHTTPClient_PostRequest
=== RUN TestIsPrivateIP
=== PAUSE TestIsPrivateIP
=== RUN TestIsPrivateIP_NilIP
=== PAUSE TestIsPrivateIP_NilIP
=== RUN TestSafeDialer_BlocksPrivateIPs
=== PAUSE TestSafeDialer_BlocksPrivateIPs
=== RUN TestSafeDialer_AllowsLocalhost
=== PAUSE TestSafeDialer_AllowsLocalhost
=== RUN TestSafeDialer_AllowedDomains
=== PAUSE TestSafeDialer_AllowedDomains
=== RUN TestNewSafeHTTPClient_DefaultOptions
=== PAUSE TestNewSafeHTTPClient_DefaultOptions
=== RUN TestNewSafeHTTPClient_WithTimeout
=== PAUSE TestNewSafeHTTPClient_WithTimeout
=== RUN TestNewSafeHTTPClient_WithAllowLocalhost
=== PAUSE TestNewSafeHTTPClient_WithAllowLocalhost
=== RUN TestNewSafeHTTPClient_BlocksSSRF
=== PAUSE TestNewSafeHTTPClient_BlocksSSRF
=== RUN TestNewSafeHTTPClient_WithMaxRedirects
=== PAUSE TestNewSafeHTTPClient_WithMaxRedirects
=== RUN TestNewSafeHTTPClient_WithAllowedDomains
=== PAUSE TestNewSafeHTTPClient_WithAllowedDomains
=== RUN TestClientOptions_Defaults
=== PAUSE TestClientOptions_Defaults
=== RUN TestWithDialTimeout
=== PAUSE TestWithDialTimeout
=== RUN TestSafeDialer_InvalidAddress
=== PAUSE TestSafeDialer_InvalidAddress
=== RUN TestSafeDialer_LoopbackIPv6
=== PAUSE TestSafeDialer_LoopbackIPv6
=== RUN TestValidateRedirectTarget_EmptyHostname
=== PAUSE TestValidateRedirectTarget_EmptyHostname
=== RUN TestValidateRedirectTarget_Localhost
=== PAUSE TestValidateRedirectTarget_Localhost
=== RUN TestValidateRedirectTarget_127
=== PAUSE TestValidateRedirectTarget_127
=== RUN TestValidateRedirectTarget_IPv6Loopback
=== PAUSE TestValidateRedirectTarget_IPv6Loopback
=== RUN TestNewSafeHTTPClient_NoRedirectsByDefault
=== PAUSE TestNewSafeHTTPClient_NoRedirectsByDefault
=== RUN TestIsPrivateIP_IPv4MappedIPv6
=== PAUSE TestIsPrivateIP_IPv4MappedIPv6
=== RUN TestIsPrivateIP_Multicast
=== PAUSE TestIsPrivateIP_Multicast
=== RUN TestIsPrivateIP_Unspecified
=== PAUSE TestIsPrivateIP_Unspecified
=== RUN TestValidateRedirectTarget_DNSFailure
=== PAUSE TestValidateRedirectTarget_DNSFailure
=== RUN TestValidateRedirectTarget_PrivateIPInRedirect
=== PAUSE TestValidateRedirectTarget_PrivateIPInRedirect
=== RUN TestSafeDialer_AllIPsPrivate
=== PAUSE TestSafeDialer_AllIPsPrivate
=== RUN TestNewSafeHTTPClient_RedirectToPrivateIP
=== PAUSE TestNewSafeHTTPClient_RedirectToPrivateIP
=== RUN TestSafeDialer_DNSResolutionFailure
=== PAUSE TestSafeDialer_DNSResolutionFailure
=== RUN TestSafeDialer_NoIPsReturned
=== PAUSE TestSafeDialer_NoIPsReturned
=== RUN TestNewSafeHTTPClient_TooManyRedirects
=== PAUSE TestNewSafeHTTPClient_TooManyRedirects
=== RUN TestValidateRedirectTarget_AllowedLocalhost
=== PAUSE TestValidateRedirectTarget_AllowedLocalhost
=== RUN TestNewSafeHTTPClient_MetadataEndpoint
=== PAUSE TestNewSafeHTTPClient_MetadataEndpoint
=== RUN TestSafeDialer_IPv4MappedIPv6
=== PAUSE TestSafeDialer_IPv4MappedIPv6
=== RUN TestClientOptions_AllFunctionalOptions
=== PAUSE TestClientOptions_AllFunctionalOptions
=== RUN TestSafeDialer_ContextCancelled
=== PAUSE TestSafeDialer_ContextCancelled
=== RUN TestNewSafeHTTPClient_RedirectValidation
=== PAUSE TestNewSafeHTTPClient_RedirectValidation
=== CONT TestNewInternalServiceHTTPClient_RedirectsDisabled
=== CONT TestSafeDialer_LoopbackIPv6
=== CONT TestSafeDialer_NoIPsReturned
=== CONT TestSafeDialer_BlocksPrivateIPs
=== RUN TestSafeDialer_BlocksPrivateIPs/blocks_10.x.x.x
=== PAUSE TestSafeDialer_BlocksPrivateIPs/blocks_10.x.x.x
=== RUN TestSafeDialer_BlocksPrivateIPs/blocks_172.16.x.x
=== PAUSE TestSafeDialer_BlocksPrivateIPs/blocks_172.16.x.x
=== RUN TestSafeDialer_BlocksPrivateIPs/blocks_192.168.x.x
=== PAUSE TestSafeDialer_BlocksPrivateIPs/blocks_192.168.x.x
=== RUN TestSafeDialer_BlocksPrivateIPs/blocks_127.0.0.1
=== PAUSE TestSafeDialer_BlocksPrivateIPs/blocks_127.0.0.1
=== RUN TestSafeDialer_BlocksPrivateIPs/blocks_localhost
=== PAUSE TestSafeDialer_BlocksPrivateIPs/blocks_localhost
=== CONT TestNewSafeHTTPClient_RedirectValidation
--- PASS: TestSafeDialer_LoopbackIPv6 (0.00s)
=== CONT TestClientOptions_AllFunctionalOptions
--- PASS: TestNewInternalServiceHTTPClient_RedirectsDisabled (0.00s)
--- PASS: TestClientOptions_AllFunctionalOptions (0.00s)
=== CONT TestSafeDialer_IPv4MappedIPv6
--- PASS: TestSafeDialer_IPv4MappedIPv6 (0.00s)
=== CONT TestNewSafeHTTPClient_MetadataEndpoint
=== CONT TestSafeDialer_ContextCancelled
--- PASS: TestSafeDialer_ContextCancelled (0.00s)
=== CONT TestNewSafeHTTPClient_TooManyRedirects
--- PASS: TestNewSafeHTTPClient_MetadataEndpoint (0.00s)
=== CONT TestValidateRedirectTarget_AllowedLocalhost
=== RUN TestValidateRedirectTarget_AllowedLocalhost/http://localhost/path
=== PAUSE TestValidateRedirectTarget_AllowedLocalhost/http://localhost/path
=== RUN TestValidateRedirectTarget_AllowedLocalhost/http://127.0.0.1/path
=== PAUSE TestValidateRedirectTarget_AllowedLocalhost/http://127.0.0.1/path
=== RUN TestValidateRedirectTarget_AllowedLocalhost/http://[::1]/path
=== PAUSE TestValidateRedirectTarget_AllowedLocalhost/http://[::1]/path
=== CONT TestSafeDialer_DNSResolutionFailure
--- PASS: TestSafeDialer_NoIPsReturned (0.00s)
=== CONT TestNewSafeHTTPClient_RedirectToPrivateIP
--- PASS: TestSafeDialer_DNSResolutionFailure (0.00s)
=== CONT TestSafeDialer_AllIPsPrivate
=== RUN TestSafeDialer_AllIPsPrivate/10.0.0.1:80
=== PAUSE TestSafeDialer_AllIPsPrivate/10.0.0.1:80
=== RUN TestSafeDialer_AllIPsPrivate/172.16.0.1:443
=== PAUSE TestSafeDialer_AllIPsPrivate/172.16.0.1:443
=== RUN TestSafeDialer_AllIPsPrivate/192.168.0.1:8080
=== PAUSE TestSafeDialer_AllIPsPrivate/192.168.0.1:8080
=== RUN TestSafeDialer_AllIPsPrivate/169.254.169.254:80
=== PAUSE TestSafeDialer_AllIPsPrivate/169.254.169.254:80
=== CONT TestWithDialTimeout
--- PASS: TestWithDialTimeout (0.00s)
=== CONT TestClientOptions_Defaults
--- PASS: TestClientOptions_Defaults (0.00s)
=== CONT TestSafeDialer_InvalidAddress
--- PASS: TestSafeDialer_InvalidAddress (0.00s)
=== CONT TestNewSafeHTTPClient_WithMaxRedirects
--- PASS: TestNewSafeHTTPClient_RedirectToPrivateIP (0.00s)
=== CONT TestNewSafeHTTPClient_WithAllowedDomains
--- PASS: TestNewSafeHTTPClient_WithAllowedDomains (0.00s)
=== CONT TestNewSafeHTTPClient_WithAllowLocalhost
--- PASS: TestNewSafeHTTPClient_RedirectValidation (0.01s)
=== CONT TestNewSafeHTTPClient_BlocksSSRF
=== RUN TestNewSafeHTTPClient_BlocksSSRF/http://127.0.0.1/
=== PAUSE TestNewSafeHTTPClient_BlocksSSRF/http://127.0.0.1/
=== RUN TestNewSafeHTTPClient_BlocksSSRF/http://10.0.0.1/
=== PAUSE TestNewSafeHTTPClient_BlocksSSRF/http://10.0.0.1/
=== RUN TestNewSafeHTTPClient_BlocksSSRF/http://172.16.0.1/
=== PAUSE TestNewSafeHTTPClient_BlocksSSRF/http://172.16.0.1/
=== RUN TestNewSafeHTTPClient_BlocksSSRF/http://192.168.1.1/
--- PASS: TestNewSafeHTTPClient_WithAllowLocalhost (0.00s)
--- PASS: TestNewSafeHTTPClient_WithMaxRedirects (0.00s)
=== PAUSE TestNewSafeHTTPClient_BlocksSSRF/http://192.168.1.1/
--- PASS: TestNewSafeHTTPClient_TooManyRedirects (0.01s)
=== CONT TestSafeDialer_AllowedDomains
=== CONT TestNewSafeHTTPClient_WithTimeout
=== CONT TestSafeDialer_AllowsLocalhost
--- PASS: TestNewSafeHTTPClient_WithTimeout (0.00s)
=== CONT TestSafeDialer_BlocksPrivateIPs/blocks_172.16.x.x
=== CONT TestSafeDialer_BlocksPrivateIPs/blocks_localhost
=== RUN TestNewSafeHTTPClient_BlocksSSRF/http://localhost/
=== PAUSE TestNewSafeHTTPClient_BlocksSSRF/http://localhost/
--- PASS: TestSafeDialer_AllowsLocalhost (0.00s)
=== CONT TestSafeDialer_BlocksPrivateIPs/blocks_127.0.0.1
=== CONT TestIsPrivateIP_NilIP
--- PASS: TestIsPrivateIP_NilIP (0.00s)
=== CONT TestSafeDialer_BlocksPrivateIPs/blocks_10.x.x.x
=== CONT TestSafeDialer_BlocksPrivateIPs/blocks_192.168.x.x
=== CONT TestNewInternalServiceHTTPClient_PostRequest
=== CONT TestNewInternalServiceHTTPClient_ProxyIgnored
=== CONT TestNewSafeHTTPClient_DefaultOptions
--- PASS: TestNewSafeHTTPClient_DefaultOptions (0.00s)
=== CONT TestIsPrivateIP
=== RUN TestIsPrivateIP/10.0.0.0/8_start
=== PAUSE TestIsPrivateIP/10.0.0.0/8_start
--- PASS: TestSafeDialer_BlocksPrivateIPs (0.00s)
--- PASS: TestSafeDialer_BlocksPrivateIPs/blocks_172.16.x.x (0.00s)
--- PASS: TestSafeDialer_BlocksPrivateIPs/blocks_localhost (0.00s)
--- PASS: TestSafeDialer_BlocksPrivateIPs/blocks_127.0.0.1 (0.00s)
--- PASS: TestSafeDialer_BlocksPrivateIPs/blocks_10.x.x.x (0.00s)
--- PASS: TestSafeDialer_BlocksPrivateIPs/blocks_192.168.x.x (0.00s)
=== RUN TestIsPrivateIP/10.0.0.0/8_middle
=== PAUSE TestIsPrivateIP/10.0.0.0/8_middle
=== RUN TestIsPrivateIP/172.16.0.0/12_start
=== PAUSE TestIsPrivateIP/172.16.0.0/12_start
=== RUN TestIsPrivateIP/172.16.0.0/12_end
=== PAUSE TestIsPrivateIP/172.16.0.0/12_end
=== RUN TestIsPrivateIP/192.168.0.0/16_start
=== PAUSE TestIsPrivateIP/192.168.0.0/16_start
=== RUN TestIsPrivateIP/192.168.0.0/16_end
=== PAUSE TestIsPrivateIP/192.168.0.0/16_end
=== RUN TestIsPrivateIP/169.254.0.0/16_start
=== PAUSE TestIsPrivateIP/169.254.0.0/16_start
=== RUN TestIsPrivateIP/169.254.0.0/16_end
=== PAUSE TestIsPrivateIP/169.254.0.0/16_end
=== RUN TestIsPrivateIP/127.0.0.0/8_localhost
=== PAUSE TestIsPrivateIP/127.0.0.0/8_localhost
--- PASS: TestNewInternalServiceHTTPClient_ProxyIgnored (0.00s)
=== RUN TestIsPrivateIP/127.0.0.0/8_other
=== CONT TestNewInternalServiceHTTPClient_TimeoutEnforced
=== PAUSE TestIsPrivateIP/127.0.0.0/8_other
=== RUN TestIsPrivateIP/127.0.0.0/8_end
=== PAUSE TestIsPrivateIP/127.0.0.0/8_end
=== RUN TestIsPrivateIP/0.0.0.0/8
=== PAUSE TestIsPrivateIP/0.0.0.0/8
=== RUN TestIsPrivateIP/240.0.0.0/4_reserved
=== PAUSE TestIsPrivateIP/240.0.0.0/4_reserved
=== RUN TestIsPrivateIP/255.255.255.255_broadcast
=== PAUSE TestIsPrivateIP/255.255.255.255_broadcast
=== RUN TestIsPrivateIP/IPv6_loopback
=== PAUSE TestIsPrivateIP/IPv6_loopback
=== RUN TestIsPrivateIP/fc00::/7_unique_local
=== PAUSE TestIsPrivateIP/fc00::/7_unique_local
=== RUN TestIsPrivateIP/fd00::/8_unique_local
=== PAUSE TestIsPrivateIP/fd00::/8_unique_local
=== RUN TestIsPrivateIP/fe80::/10_link-local
=== PAUSE TestIsPrivateIP/fe80::/10_link-local
=== RUN TestIsPrivateIP/Public_IPv4_1
=== PAUSE TestIsPrivateIP/Public_IPv4_1
=== RUN TestIsPrivateIP/Public_IPv4_2
=== PAUSE TestIsPrivateIP/Public_IPv4_2
=== RUN TestIsPrivateIP/Public_IPv4_3
=== PAUSE TestIsPrivateIP/Public_IPv4_3
=== RUN TestIsPrivateIP/Public_IPv6
=== PAUSE TestIsPrivateIP/Public_IPv6
=== RUN TestIsPrivateIP/Just_outside_172.16
=== PAUSE TestIsPrivateIP/Just_outside_172.16
=== RUN TestIsPrivateIP/Just_outside_172.31
=== PAUSE TestIsPrivateIP/Just_outside_172.31
=== RUN TestIsPrivateIP/Just_outside_192.168
=== PAUSE TestIsPrivateIP/Just_outside_192.168
=== CONT TestNewInternalServiceHTTPClient_ActualRequest
--- PASS: TestNewInternalServiceHTTPClient_PostRequest (0.00s)
=== CONT TestNewInternalServiceHTTPClient_CheckRedirectReturnsErrUseLastResponse
=== CONT TestNewInternalServiceHTTPClient_MultipleClients
--- PASS: TestNewInternalServiceHTTPClient_CheckRedirectReturnsErrUseLastResponse (0.00s)
=== CONT TestNewInternalServiceHTTPClient
--- PASS: TestNewInternalServiceHTTPClient_MultipleClients (0.00s)
--- PASS: TestNewInternalServiceHTTPClient_ActualRequest (0.00s)
=== RUN TestNewInternalServiceHTTPClient/with_1_second_timeout
=== CONT TestNewInternalServiceHTTPClient_TransportConfiguration
=== PAUSE TestNewInternalServiceHTTPClient/with_1_second_timeout
--- PASS: TestNewInternalServiceHTTPClient_TransportConfiguration (0.00s)
=== RUN TestNewInternalServiceHTTPClient/with_5_second_timeout
=== CONT TestIsPrivateIP_IPv4MappedIPv6
=== PAUSE TestNewInternalServiceHTTPClient/with_5_second_timeout
=== RUN TestIsPrivateIP_IPv4MappedIPv6/IPv4-mapped_private
=== RUN TestNewInternalServiceHTTPClient/with_30_second_timeout
=== PAUSE TestNewInternalServiceHTTPClient/with_30_second_timeout
=== PAUSE TestIsPrivateIP_IPv4MappedIPv6/IPv4-mapped_private
=== RUN TestNewInternalServiceHTTPClient/with_100ms_timeout
=== PAUSE TestNewInternalServiceHTTPClient/with_100ms_timeout
=== RUN TestIsPrivateIP_IPv4MappedIPv6/IPv4-mapped_public
=== PAUSE TestIsPrivateIP_IPv4MappedIPv6/IPv4-mapped_public
=== RUN TestNewInternalServiceHTTPClient/with_zero_timeout
=== RUN TestIsPrivateIP_IPv4MappedIPv6/IPv4-mapped_loopback
=== PAUSE TestIsPrivateIP_IPv4MappedIPv6/IPv4-mapped_loopback
=== CONT TestValidateRedirectTarget_DNSFailure
=== PAUSE TestNewInternalServiceHTTPClient/with_zero_timeout
=== CONT TestValidateRedirectTarget_PrivateIPInRedirect
=== RUN TestValidateRedirectTarget_PrivateIPInRedirect/http://10.0.0.1/path
=== PAUSE TestValidateRedirectTarget_PrivateIPInRedirect/http://10.0.0.1/path
=== RUN TestValidateRedirectTarget_PrivateIPInRedirect/http://172.16.0.1/path
=== PAUSE TestValidateRedirectTarget_PrivateIPInRedirect/http://172.16.0.1/path
=== RUN TestValidateRedirectTarget_PrivateIPInRedirect/http://192.168.1.1/path
=== PAUSE TestValidateRedirectTarget_PrivateIPInRedirect/http://192.168.1.1/path
=== RUN TestValidateRedirectTarget_PrivateIPInRedirect/http://169.254.169.254/latest/meta-data/
=== PAUSE TestValidateRedirectTarget_PrivateIPInRedirect/http://169.254.169.254/latest/meta-data/
=== CONT TestIsPrivateIP_Unspecified
=== RUN TestIsPrivateIP_Unspecified/IPv4_unspecified
=== PAUSE TestIsPrivateIP_Unspecified/IPv4_unspecified
=== RUN TestIsPrivateIP_Unspecified/IPv6_unspecified
=== PAUSE TestIsPrivateIP_Unspecified/IPv6_unspecified
=== CONT TestIsPrivateIP_Multicast
=== RUN TestIsPrivateIP_Multicast/IPv4_multicast
=== PAUSE TestIsPrivateIP_Multicast/IPv4_multicast
=== RUN TestIsPrivateIP_Multicast/IPv6_multicast
=== PAUSE TestIsPrivateIP_Multicast/IPv6_multicast
=== CONT TestNewSafeHTTPClient_NoRedirectsByDefault
--- PASS: TestValidateRedirectTarget_DNSFailure (0.00s)
=== CONT TestValidateRedirectTarget_IPv6Loopback
--- PASS: TestValidateRedirectTarget_IPv6Loopback (0.00s)
=== CONT TestValidateRedirectTarget_127
--- PASS: TestValidateRedirectTarget_127 (0.00s)
=== CONT TestValidateRedirectTarget_EmptyHostname
--- PASS: TestValidateRedirectTarget_EmptyHostname (0.00s)
=== CONT TestValidateRedirectTarget_Localhost
--- PASS: TestValidateRedirectTarget_Localhost (0.00s)
=== CONT TestValidateRedirectTarget_AllowedLocalhost/http://127.0.0.1/path
=== CONT TestValidateRedirectTarget_AllowedLocalhost/http://[::1]/path
=== CONT TestValidateRedirectTarget_AllowedLocalhost/http://localhost/path
--- PASS: TestValidateRedirectTarget_AllowedLocalhost (0.00s)
--- PASS: TestValidateRedirectTarget_AllowedLocalhost/http://127.0.0.1/path (0.00s)
--- PASS: TestValidateRedirectTarget_AllowedLocalhost/http://[::1]/path (0.00s)
--- PASS: TestValidateRedirectTarget_AllowedLocalhost/http://localhost/path (0.00s)
=== CONT TestSafeDialer_AllIPsPrivate/10.0.0.1:80
=== CONT TestSafeDialer_AllIPsPrivate/169.254.169.254:80
--- PASS: TestNewSafeHTTPClient_NoRedirectsByDefault (0.00s)
=== CONT TestSafeDialer_AllIPsPrivate/192.168.0.1:8080
=== CONT TestSafeDialer_AllIPsPrivate/172.16.0.1:443
=== CONT TestNewSafeHTTPClient_BlocksSSRF/http://192.168.1.1/
=== CONT TestNewSafeHTTPClient_BlocksSSRF/http://127.0.0.1/
--- PASS: TestSafeDialer_AllIPsPrivate (0.00s)
--- PASS: TestSafeDialer_AllIPsPrivate/10.0.0.1:80 (0.00s)
--- PASS: TestSafeDialer_AllIPsPrivate/169.254.169.254:80 (0.00s)
--- PASS: TestSafeDialer_AllIPsPrivate/192.168.0.1:8080 (0.00s)
--- PASS: TestSafeDialer_AllIPsPrivate/172.16.0.1:443 (0.00s)
=== CONT TestNewSafeHTTPClient_BlocksSSRF/http://10.0.0.1/
=== CONT TestNewSafeHTTPClient_BlocksSSRF/http://localhost/
=== CONT TestNewSafeHTTPClient_BlocksSSRF/http://172.16.0.1/
=== CONT TestIsPrivateIP/10.0.0.0/8_start
=== CONT TestIsPrivateIP/Just_outside_192.168
=== CONT TestIsPrivateIP/Just_outside_172.16
=== CONT TestIsPrivateIP/240.0.0.0/4_reserved
--- PASS: TestNewSafeHTTPClient_BlocksSSRF (0.00s)
--- PASS: TestNewSafeHTTPClient_BlocksSSRF/http://127.0.0.1/ (0.00s)
--- PASS: TestNewSafeHTTPClient_BlocksSSRF/http://192.168.1.1/ (0.00s)
--- PASS: TestNewSafeHTTPClient_BlocksSSRF/http://10.0.0.1/ (0.00s)
--- PASS: TestNewSafeHTTPClient_BlocksSSRF/http://localhost/ (0.00s)
--- PASS: TestNewSafeHTTPClient_BlocksSSRF/http://172.16.0.1/ (0.00s)
=== CONT TestIsPrivateIP/Just_outside_172.31
=== CONT TestIsPrivateIP/Public_IPv6
=== CONT TestIsPrivateIP/Public_IPv4_2
=== CONT TestIsPrivateIP/Public_IPv4_3
=== CONT TestIsPrivateIP/fe80::/10_link-local
=== CONT TestIsPrivateIP/fd00::/8_unique_local
=== CONT TestIsPrivateIP/fc00::/7_unique_local
=== CONT TestIsPrivateIP/Public_IPv4_1
=== CONT TestIsPrivateIP/IPv6_loopback
=== CONT TestIsPrivateIP/255.255.255.255_broadcast
=== CONT TestIsPrivateIP/169.254.0.0/16_start
=== CONT TestIsPrivateIP/127.0.0.0/8_end
=== CONT TestIsPrivateIP/127.0.0.0/8_localhost
=== CONT TestIsPrivateIP/0.0.0.0/8
=== CONT TestIsPrivateIP/169.254.0.0/16_end
=== CONT TestIsPrivateIP/127.0.0.0/8_other
=== CONT TestIsPrivateIP/192.168.0.0/16_end
=== CONT TestIsPrivateIP/172.16.0.0/12_start
=== CONT TestIsPrivateIP/192.168.0.0/16_start
=== CONT TestIsPrivateIP/172.16.0.0/12_end
=== CONT TestIsPrivateIP/10.0.0.0/8_middle
=== CONT TestIsPrivateIP_IPv4MappedIPv6/IPv4-mapped_loopback
=== CONT TestIsPrivateIP_IPv4MappedIPv6/IPv4-mapped_public
=== CONT TestNewInternalServiceHTTPClient/with_1_second_timeout
=== CONT TestIsPrivateIP_IPv4MappedIPv6/IPv4-mapped_private
=== CONT TestNewInternalServiceHTTPClient/with_zero_timeout
=== CONT TestNewInternalServiceHTTPClient/with_100ms_timeout
=== CONT TestNewInternalServiceHTTPClient/with_30_second_timeout
--- PASS: TestIsPrivateIP (0.00s)
--- PASS: TestIsPrivateIP/10.0.0.0/8_start (0.00s)
--- PASS: TestIsPrivateIP/Just_outside_172.16 (0.00s)
--- PASS: TestIsPrivateIP/240.0.0.0/4_reserved (0.00s)
--- PASS: TestIsPrivateIP/Just_outside_172.31 (0.00s)
--- PASS: TestIsPrivateIP/Just_outside_192.168 (0.00s)
--- PASS: TestIsPrivateIP/Public_IPv6 (0.00s)
--- PASS: TestIsPrivateIP/Public_IPv4_2 (0.00s)
--- PASS: TestIsPrivateIP/Public_IPv4_3 (0.00s)
--- PASS: TestIsPrivateIP/fe80::/10_link-local (0.00s)
--- PASS: TestIsPrivateIP/fd00::/8_unique_local (0.00s)
--- PASS: TestIsPrivateIP/fc00::/7_unique_local (0.00s)
--- PASS: TestIsPrivateIP/IPv6_loopback (0.00s)
--- PASS: TestIsPrivateIP/255.255.255.255_broadcast (0.00s)
--- PASS: TestIsPrivateIP/Public_IPv4_1 (0.00s)
--- PASS: TestIsPrivateIP/169.254.0.0/16_start (0.00s)
--- PASS: TestIsPrivateIP/127.0.0.0/8_localhost (0.00s)
--- PASS: TestIsPrivateIP/169.254.0.0/16_end (0.00s)
--- PASS: TestIsPrivateIP/0.0.0.0/8 (0.00s)
--- PASS: TestIsPrivateIP/192.168.0.0/16_start (0.00s)
--- PASS: TestIsPrivateIP/192.168.0.0/16_end (0.00s)
--- PASS: TestIsPrivateIP/127.0.0.0/8_end (0.00s)
--- PASS: TestIsPrivateIP/172.16.0.0/12_start (0.00s)
--- PASS: TestIsPrivateIP/10.0.0.0/8_middle (0.00s)
--- PASS: TestIsPrivateIP/172.16.0.0/12_end (0.00s)
--- PASS: TestIsPrivateIP/127.0.0.0/8_other (0.00s)
=== CONT TestValidateRedirectTarget_PrivateIPInRedirect/http://192.168.1.1/path
--- PASS: TestIsPrivateIP_IPv4MappedIPv6 (0.00s)
--- PASS: TestIsPrivateIP_IPv4MappedIPv6/IPv4-mapped_loopback (0.00s)
--- PASS: TestIsPrivateIP_IPv4MappedIPv6/IPv4-mapped_public (0.00s)
--- PASS: TestIsPrivateIP_IPv4MappedIPv6/IPv4-mapped_private (0.00s)
=== CONT TestNewInternalServiceHTTPClient/with_5_second_timeout
--- PASS: TestNewInternalServiceHTTPClient (0.00s)
--- PASS: TestNewInternalServiceHTTPClient/with_1_second_timeout (0.00s)
--- PASS: TestNewInternalServiceHTTPClient/with_zero_timeout (0.00s)
--- PASS: TestNewInternalServiceHTTPClient/with_30_second_timeout (0.00s)
--- PASS: TestNewInternalServiceHTTPClient/with_100ms_timeout (0.00s)
--- PASS: TestNewInternalServiceHTTPClient/with_5_second_timeout (0.00s)
=== CONT TestValidateRedirectTarget_PrivateIPInRedirect/http://10.0.0.1/path
=== CONT TestIsPrivateIP_Unspecified/IPv4_unspecified
=== CONT TestIsPrivateIP_Unspecified/IPv6_unspecified
=== CONT TestIsPrivateIP_Multicast/IPv6_multicast
=== CONT TestValidateRedirectTarget_PrivateIPInRedirect/http://172.16.0.1/path
--- PASS: TestIsPrivateIP_Unspecified (0.00s)
--- PASS: TestIsPrivateIP_Unspecified/IPv4_unspecified (0.00s)
--- PASS: TestIsPrivateIP_Unspecified/IPv6_unspecified (0.00s)
=== CONT TestIsPrivateIP_Multicast/IPv4_multicast
=== CONT TestValidateRedirectTarget_PrivateIPInRedirect/http://169.254.169.254/latest/meta-data/
--- PASS: TestValidateRedirectTarget_PrivateIPInRedirect (0.00s)
--- PASS: TestValidateRedirectTarget_PrivateIPInRedirect/http://192.168.1.1/path (0.00s)
--- PASS: TestValidateRedirectTarget_PrivateIPInRedirect/http://10.0.0.1/path (0.00s)
--- PASS: TestValidateRedirectTarget_PrivateIPInRedirect/http://172.16.0.1/path (0.00s)
--- PASS: TestValidateRedirectTarget_PrivateIPInRedirect/http://169.254.169.254/latest/meta-data/ (0.00s)
--- PASS: TestIsPrivateIP_Multicast (0.00s)
--- PASS: TestIsPrivateIP_Multicast/IPv6_multicast (0.00s)
--- PASS: TestIsPrivateIP_Multicast/IPv4_multicast (0.00s)
=== NAME TestSafeDialer_AllowedDomains
safeclient_test.go:171: Got expected error type for allowed domain: *fmt.wrapError: DNS resolution failed for app.crowdsec.net: lookup app.crowdsec.net: i/o timeout
--- PASS: TestSafeDialer_AllowedDomains (0.10s)
--- PASS: TestNewInternalServiceHTTPClient_TimeoutEnforced (0.50s)
PASS
coverage: 81.3% of statements
ok github.com/Wikid82/charon/backend/internal/network (cached) coverage: 81.3% of statements
=== RUN TestAuditEvent_JSONSerialization
=== PAUSE TestAuditEvent_JSONSerialization
=== RUN TestAuditLogger_LogURLValidation
=== PAUSE TestAuditLogger_LogURLValidation
=== RUN TestAuditLogger_LogURLTest
=== PAUSE TestAuditLogger_LogURLTest
=== RUN TestAuditLogger_LogSSRFBlock
=== PAUSE TestAuditLogger_LogSSRFBlock
=== RUN TestGlobalAuditLogger
=== PAUSE TestGlobalAuditLogger
=== RUN TestAuditEvent_RequiredFields
=== PAUSE TestAuditEvent_RequiredFields
=== RUN TestAuditLogger_TimestampFormat
=== PAUSE TestAuditLogger_TimestampFormat
=== RUN TestParseExactHostnameAllowlist
--- PASS: TestParseExactHostnameAllowlist (0.00s)
=== RUN TestValidateInternalServiceBaseURL
=== RUN TestValidateInternalServiceBaseURL/OK_http_localhost_explicit_port
=== RUN TestValidateInternalServiceBaseURL/OK_http_localhost_path_normalized
=== RUN TestValidateInternalServiceBaseURL/OK_https_localhost_default_port
=== RUN TestValidateInternalServiceBaseURL/OK_ipv6_loopback_explicit_port
=== RUN TestValidateInternalServiceBaseURL/Reject_userinfo
=== RUN TestValidateInternalServiceBaseURL/Reject_unsupported_scheme
=== RUN TestValidateInternalServiceBaseURL/Reject_missing_hostname
=== RUN TestValidateInternalServiceBaseURL/Reject_hostname_not_allowed
=== RUN TestValidateInternalServiceBaseURL/Reject_unexpected_port_when_omitted
=== RUN TestValidateInternalServiceBaseURL/Reject_invalid_port
=== RUN TestValidateInternalServiceBaseURL/Reject_out-of-range_port
--- PASS: TestValidateInternalServiceBaseURL (0.00s)
--- PASS: TestValidateInternalServiceBaseURL/OK_http_localhost_explicit_port (0.00s)
--- PASS: TestValidateInternalServiceBaseURL/OK_http_localhost_path_normalized (0.00s)
--- PASS: TestValidateInternalServiceBaseURL/OK_https_localhost_default_port (0.00s)
--- PASS: TestValidateInternalServiceBaseURL/OK_ipv6_loopback_explicit_port (0.00s)
--- PASS: TestValidateInternalServiceBaseURL/Reject_userinfo (0.00s)
--- PASS: TestValidateInternalServiceBaseURL/Reject_unsupported_scheme (0.00s)
--- PASS: TestValidateInternalServiceBaseURL/Reject_missing_hostname (0.00s)
--- PASS: TestValidateInternalServiceBaseURL/Reject_hostname_not_allowed (0.00s)
--- PASS: TestValidateInternalServiceBaseURL/Reject_unexpected_port_when_omitted (0.00s)
--- PASS: TestValidateInternalServiceBaseURL/Reject_invalid_port (0.00s)
--- PASS: TestValidateInternalServiceBaseURL/Reject_out-of-range_port (0.00s)
=== RUN TestInternalServiceHostAllowlist
=== RUN TestInternalServiceHostAllowlist/DefaultLocalhostOnly
=== RUN TestInternalServiceHostAllowlist/WithAdditionalHosts
=== RUN TestInternalServiceHostAllowlist/WithEmptyAndWhitespaceEntries
=== RUN TestInternalServiceHostAllowlist/WithInvalidEntries
--- PASS: TestInternalServiceHostAllowlist (0.00s)
--- PASS: TestInternalServiceHostAllowlist/DefaultLocalhostOnly (0.00s)
--- PASS: TestInternalServiceHostAllowlist/WithAdditionalHosts (0.00s)
--- PASS: TestInternalServiceHostAllowlist/WithEmptyAndWhitespaceEntries (0.00s)
--- PASS: TestInternalServiceHostAllowlist/WithInvalidEntries (0.00s)
=== RUN TestWithMaxRedirects
=== RUN TestWithMaxRedirects/Zero_redirects
=== RUN TestWithMaxRedirects/Five_redirects
=== RUN TestWithMaxRedirects/Ten_redirects
--- PASS: TestWithMaxRedirects (0.00s)
--- PASS: TestWithMaxRedirects/Zero_redirects (0.00s)
--- PASS: TestWithMaxRedirects/Five_redirects (0.00s)
--- PASS: TestWithMaxRedirects/Ten_redirects (0.00s)
=== RUN TestValidateInternalServiceBaseURL_AdditionalCases
=== RUN TestValidateInternalServiceBaseURL_AdditionalCases/HTTPSWithDefaultPort
=== RUN TestValidateInternalServiceBaseURL_AdditionalCases/HTTPWithDefaultPort
=== RUN TestValidateInternalServiceBaseURL_AdditionalCases/PortMismatchWithDefaultHTTPS
=== RUN TestValidateInternalServiceBaseURL_AdditionalCases/PortMismatchWithDefaultHTTP
=== RUN TestValidateInternalServiceBaseURL_AdditionalCases/InvalidPortNumber
=== RUN TestValidateInternalServiceBaseURL_AdditionalCases/NegativePort
=== RUN TestValidateInternalServiceBaseURL_AdditionalCases/HostNotInAllowlist
=== RUN TestValidateInternalServiceBaseURL_AdditionalCases/EmptyAllowlist
=== RUN TestValidateInternalServiceBaseURL_AdditionalCases/CaseInsensitiveHostMatching
=== RUN TestValidateInternalServiceBaseURL_AdditionalCases/AllowedHostDifferentCase
--- PASS: TestValidateInternalServiceBaseURL_AdditionalCases (0.00s)
--- PASS: TestValidateInternalServiceBaseURL_AdditionalCases/HTTPSWithDefaultPort (0.00s)
--- PASS: TestValidateInternalServiceBaseURL_AdditionalCases/HTTPWithDefaultPort (0.00s)
--- PASS: TestValidateInternalServiceBaseURL_AdditionalCases/PortMismatchWithDefaultHTTPS (0.00s)
--- PASS: TestValidateInternalServiceBaseURL_AdditionalCases/PortMismatchWithDefaultHTTP (0.00s)
--- PASS: TestValidateInternalServiceBaseURL_AdditionalCases/InvalidPortNumber (0.00s)
--- PASS: TestValidateInternalServiceBaseURL_AdditionalCases/NegativePort (0.00s)
--- PASS: TestValidateInternalServiceBaseURL_AdditionalCases/HostNotInAllowlist (0.00s)
--- PASS: TestValidateInternalServiceBaseURL_AdditionalCases/EmptyAllowlist (0.00s)
--- PASS: TestValidateInternalServiceBaseURL_AdditionalCases/CaseInsensitiveHostMatching (0.00s)
--- PASS: TestValidateInternalServiceBaseURL_AdditionalCases/AllowedHostDifferentCase (0.00s)
=== RUN TestSanitizeIPForError_AdditionalCases
=== RUN TestSanitizeIPForError_AdditionalCases/InvalidIPString
=== RUN TestSanitizeIPForError_AdditionalCases/EmptyString
=== RUN TestSanitizeIPForError_AdditionalCases/IPv4Malformed
=== RUN TestSanitizeIPForError_AdditionalCases/IPv6SingleSegment
=== RUN TestSanitizeIPForError_AdditionalCases/IPv6MultipleSegments
=== RUN TestSanitizeIPForError_AdditionalCases/IPv6Compressed
=== RUN TestSanitizeIPForError_AdditionalCases/IPv4ThreeOctets
=== RUN TestSanitizeIPForError_AdditionalCases/IPv4FiveOctets
--- PASS: TestSanitizeIPForError_AdditionalCases (0.00s)
--- PASS: TestSanitizeIPForError_AdditionalCases/InvalidIPString (0.00s)
--- PASS: TestSanitizeIPForError_AdditionalCases/EmptyString (0.00s)
--- PASS: TestSanitizeIPForError_AdditionalCases/IPv4Malformed (0.00s)
--- PASS: TestSanitizeIPForError_AdditionalCases/IPv6SingleSegment (0.00s)
--- PASS: TestSanitizeIPForError_AdditionalCases/IPv6MultipleSegments (0.00s)
--- PASS: TestSanitizeIPForError_AdditionalCases/IPv6Compressed (0.00s)
--- PASS: TestSanitizeIPForError_AdditionalCases/IPv4ThreeOctets (0.00s)
--- PASS: TestSanitizeIPForError_AdditionalCases/IPv4FiveOctets (0.00s)
=== RUN TestValidateExternalURL_BasicValidation
=== PAUSE TestValidateExternalURL_BasicValidation
=== RUN TestValidateExternalURL_LocalhostHandling
=== PAUSE TestValidateExternalURL_LocalhostHandling
=== RUN TestValidateExternalURL_PrivateIPBlocking
=== PAUSE TestValidateExternalURL_PrivateIPBlocking
=== RUN TestValidateExternalURL_Options
=== PAUSE TestValidateExternalURL_Options
=== RUN TestIsPrivateIP
=== PAUSE TestIsPrivateIP
=== RUN TestValidateExternalURL_RealWorldURLs
=== PAUSE TestValidateExternalURL_RealWorldURLs
=== RUN TestValidateExternalURL_MultipleOptions
=== PAUSE TestValidateExternalURL_MultipleOptions
=== RUN TestValidateExternalURL_CustomTimeout
=== PAUSE TestValidateExternalURL_CustomTimeout
=== RUN TestValidateExternalURL_DNSTimeout
=== PAUSE TestValidateExternalURL_DNSTimeout
=== RUN TestValidateExternalURL_MultipleIPsAllPrivate
=== PAUSE TestValidateExternalURL_MultipleIPsAllPrivate
=== RUN TestValidateExternalURL_CloudMetadataDetection
=== PAUSE TestValidateExternalURL_CloudMetadataDetection
=== RUN TestIsPrivateIP_IPv6Comprehensive
=== PAUSE TestIsPrivateIP_IPv6Comprehensive
=== RUN TestIPv4MappedIPv6Detection
=== PAUSE TestIPv4MappedIPv6Detection
=== RUN TestValidateExternalURL_IPv4MappedIPv6Blocking
=== PAUSE TestValidateExternalURL_IPv4MappedIPv6Blocking
=== RUN TestValidateExternalURL_HostnameValidation
=== PAUSE TestValidateExternalURL_HostnameValidation
=== RUN TestValidateExternalURL_PortValidation
=== PAUSE TestValidateExternalURL_PortValidation
=== RUN TestSanitizeIPForError
=== PAUSE TestSanitizeIPForError
=== RUN TestParsePort
=== PAUSE TestParsePort
=== RUN TestValidateExternalURL_EdgeCases
=== PAUSE TestValidateExternalURL_EdgeCases
=== RUN TestIsIPv4MappedIPv6_EdgeCases
=== PAUSE TestIsIPv4MappedIPv6_EdgeCases
=== CONT TestAuditEvent_JSONSerialization
=== CONT TestValidateExternalURL_EdgeCases
=== RUN TestValidateExternalURL_EdgeCases/Port_with_non-numeric_characters
=== CONT TestIsIPv4MappedIPv6_EdgeCases
=== RUN TestIsIPv4MappedIPv6_EdgeCases/Standard_mapped
=== PAUSE TestIsIPv4MappedIPv6_EdgeCases/Standard_mapped
=== RUN TestIsIPv4MappedIPv6_EdgeCases/Mapped_public_IP
=== PAUSE TestValidateExternalURL_EdgeCases/Port_with_non-numeric_characters
=== RUN TestValidateExternalURL_EdgeCases/Maximum_valid_port
=== PAUSE TestIsIPv4MappedIPv6_EdgeCases/Mapped_public_IP
=== PAUSE TestValidateExternalURL_EdgeCases/Maximum_valid_port
=== RUN TestIsIPv4MappedIPv6_EdgeCases/Pure_IPv6_2001:db8
=== PAUSE TestIsIPv4MappedIPv6_EdgeCases/Pure_IPv6_2001:db8
=== RUN TestIsIPv4MappedIPv6_EdgeCases/IPv6_loopback
--- PASS: TestAuditEvent_JSONSerialization (0.00s)
=== RUN TestValidateExternalURL_EdgeCases/Port_1_(privileged_but_not_blocked_with_AllowLocalhost)
=== CONT TestParsePort
=== CONT TestValidateExternalURL_Options
=== PAUSE TestValidateExternalURL_EdgeCases/Port_1_(privileged_but_not_blocked_with_AllowLocalhost)
=== RUN TestValidateExternalURL_Options/WithTimeout
=== RUN TestValidateExternalURL_EdgeCases/Port_1023_(edge_of_privileged_range)
=== PAUSE TestValidateExternalURL_Options/WithTimeout
=== PAUSE TestValidateExternalURL_EdgeCases/Port_1023_(edge_of_privileged_range)
=== RUN TestValidateExternalURL_EdgeCases/Port_1024_(first_non-privileged)
=== RUN TestParsePort/Valid_port_80
=== RUN TestValidateExternalURL_Options/Multiple_options
=== PAUSE TestParsePort/Valid_port_80
=== PAUSE TestIsIPv4MappedIPv6_EdgeCases/IPv6_loopback
=== PAUSE TestValidateExternalURL_EdgeCases/Port_1024_(first_non-privileged)
=== RUN TestIsIPv4MappedIPv6_EdgeCases/All_zeros_except_prefix
=== RUN TestValidateExternalURL_EdgeCases/URL_with_username_only
=== PAUSE TestIsIPv4MappedIPv6_EdgeCases/All_zeros_except_prefix
=== PAUSE TestValidateExternalURL_Options/Multiple_options
=== RUN TestIsIPv4MappedIPv6_EdgeCases/All_ones
=== PAUSE TestValidateExternalURL_EdgeCases/URL_with_username_only
=== RUN TestParsePort/Valid_port_443
=== PAUSE TestIsIPv4MappedIPv6_EdgeCases/All_ones
=== CONT TestSanitizeIPForError
=== RUN TestSanitizeIPForError/Private_IPv4_192.168
=== PAUSE TestParsePort/Valid_port_443
=== RUN TestValidateExternalURL_EdgeCases/Hostname_with_single_dot
=== CONT TestValidateExternalURL_HostnameValidation
=== PAUSE TestValidateExternalURL_EdgeCases/Hostname_with_single_dot
=== PAUSE TestSanitizeIPForError/Private_IPv4_192.168
=== RUN TestParsePort/Valid_port_8080
=== RUN TestValidateExternalURL_HostnameValidation/Extremely_long_hostname_(254_chars)
=== RUN TestValidateExternalURL_EdgeCases/Triple_dots_in_hostname
=== RUN TestSanitizeIPForError/Private_IPv4_10.x
=== PAUSE TestParsePort/Valid_port_8080
=== PAUSE TestValidateExternalURL_EdgeCases/Triple_dots_in_hostname
=== RUN TestParsePort/Valid_port_65535
=== PAUSE TestSanitizeIPForError/Private_IPv4_10.x
=== PAUSE TestValidateExternalURL_HostnameValidation/Extremely_long_hostname_(254_chars)
=== RUN TestValidateExternalURL_EdgeCases/Hostname_at_252_chars_(just_under_limit)
=== RUN TestValidateExternalURL_HostnameValidation/Hostname_with_double_dots
=== RUN TestSanitizeIPForError/Private_IPv4_172.16
=== PAUSE TestValidateExternalURL_EdgeCases/Hostname_at_252_chars_(just_under_limit)
=== PAUSE TestValidateExternalURL_HostnameValidation/Hostname_with_double_dots
=== CONT TestValidateExternalURL_IPv4MappedIPv6Blocking
url_validator_test.go:707: DNS resolution of IPv4-mapped IPv6 not testable without custom DNS server
=== PAUSE TestSanitizeIPForError/Private_IPv4_172.16
=== PAUSE TestParsePort/Valid_port_65535
=== RUN TestParsePort/Empty_port
=== RUN TestSanitizeIPForError/Loopback_IPv4
=== PAUSE TestParsePort/Empty_port
=== RUN TestParsePort/Non-numeric_port
=== PAUSE TestSanitizeIPForError/Loopback_IPv4
=== PAUSE TestParsePort/Non-numeric_port
--- SKIP: TestValidateExternalURL_IPv4MappedIPv6Blocking (0.00s)
=== CONT TestIPv4MappedIPv6Detection
=== RUN TestIPv4MappedIPv6Detection/IPv4-mapped_loopback
=== RUN TestParsePort/Negative_port
=== PAUSE TestIPv4MappedIPv6Detection/IPv4-mapped_loopback
=== RUN TestValidateExternalURL_HostnameValidation/Hostname_with_double_dots_mid
=== PAUSE TestParsePort/Negative_port
=== RUN TestSanitizeIPForError/Metadata_IPv4
=== PAUSE TestValidateExternalURL_HostnameValidation/Hostname_with_double_dots_mid
=== PAUSE TestSanitizeIPForError/Metadata_IPv4
=== CONT TestValidateExternalURL_PortValidation
=== RUN TestValidateExternalURL_PortValidation/Port_80_(standard_HTTP)_-_should_allow
=== RUN TestIPv4MappedIPv6Detection/IPv4-mapped_private_10.x
=== RUN TestParsePort/Port_zero
=== PAUSE TestValidateExternalURL_PortValidation/Port_80_(standard_HTTP)_-_should_allow
=== RUN TestSanitizeIPForError/IPv6_link-local
=== PAUSE TestParsePort/Port_zero
=== RUN TestValidateExternalURL_PortValidation/Port_443_(standard_HTTPS)_-_should_allow
=== CONT TestValidateExternalURL_CloudMetadataDetection
=== PAUSE TestValidateExternalURL_PortValidation/Port_443_(standard_HTTPS)_-_should_allow
=== RUN TestValidateExternalURL_CloudMetadataDetection/AWS_metadata_service
=== PAUSE TestSanitizeIPForError/IPv6_link-local
=== PAUSE TestValidateExternalURL_CloudMetadataDetection/AWS_metadata_service
=== RUN TestSanitizeIPForError/IPv6_unique_local
=== PAUSE TestSanitizeIPForError/IPv6_unique_local
=== RUN TestValidateExternalURL_CloudMetadataDetection/AWS_metadata_IPv6
=== RUN TestValidateExternalURL_PortValidation/Port_22_(SSH)_-_should_block
=== PAUSE TestValidateExternalURL_PortValidation/Port_22_(SSH)_-_should_block
=== PAUSE TestValidateExternalURL_CloudMetadataDetection/AWS_metadata_IPv6
=== RUN TestValidateExternalURL_PortValidation/Port_25_(SMTP)_-_should_block
=== RUN TestValidateExternalURL_CloudMetadataDetection/GCP_metadata_service
=== RUN TestSanitizeIPForError/Invalid_IP
=== PAUSE TestValidateExternalURL_CloudMetadataDetection/GCP_metadata_service
=== RUN TestValidateExternalURL_CloudMetadataDetection/Azure_metadata_service
=== PAUSE TestValidateExternalURL_PortValidation/Port_25_(SMTP)_-_should_block
=== RUN TestValidateExternalURL_PortValidation/Port_3306_(MySQL)_-_should_block_if_<_1024
=== PAUSE TestValidateExternalURL_CloudMetadataDetection/Azure_metadata_service
=== CONT TestValidateExternalURL_MultipleIPsAllPrivate
=== PAUSE TestSanitizeIPForError/Invalid_IP
=== PAUSE TestValidateExternalURL_PortValidation/Port_3306_(MySQL)_-_should_block_if_<_1024
=== RUN TestValidateExternalURL_MultipleIPsAllPrivate/IP_10.0.0.1
=== RUN TestValidateExternalURL_PortValidation/Port_8080_(non-privileged)_-_should_allow
=== CONT TestValidateExternalURL_DNSTimeout
=== PAUSE TestValidateExternalURL_PortValidation/Port_8080_(non-privileged)_-_should_allow
=== RUN TestValidateExternalURL_PortValidation/Port_22_with_AllowLocalhost_-_should_allow
=== PAUSE TestValidateExternalURL_PortValidation/Port_22_with_AllowLocalhost_-_should_allow
=== RUN TestValidateExternalURL_PortValidation/Port_0_-_should_block
=== PAUSE TestValidateExternalURL_PortValidation/Port_0_-_should_block
=== RUN TestValidateExternalURL_PortValidation/Port_65536_-_should_block
=== PAUSE TestValidateExternalURL_PortValidation/Port_65536_-_should_block
=== CONT TestIsPrivateIP_IPv6Comprehensive
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_loopback
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv6_loopback
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_loopback_expanded
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv6_loopback_expanded
=== NAME TestValidateExternalURL_DNSTimeout
url_validator_test.go:527: Got acceptable error: connection to private ip addresses is blocked for security (detected IPv4-mapped IPv6: 10.255.255.1)
--- PASS: TestValidateExternalURL_DNSTimeout (0.00s)
=== PAUSE TestValidateExternalURL_MultipleIPsAllPrivate/IP_10.0.0.1
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local_start
=== RUN TestValidateExternalURL_MultipleIPsAllPrivate/IP_172.16.0.1
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local_start
=== CONT TestValidateExternalURL_MultipleOptions
=== PAUSE TestValidateExternalURL_MultipleIPsAllPrivate/IP_172.16.0.1
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local_mid
=== RUN TestValidateExternalURL_MultipleIPsAllPrivate/IP_192.168.1.1
=== PAUSE TestValidateExternalURL_MultipleIPsAllPrivate/IP_192.168.1.1
=== RUN TestValidateExternalURL_MultipleOptions/All_options_enabled
=== CONT TestValidateExternalURL_CustomTimeout
=== PAUSE TestValidateExternalURL_MultipleOptions/All_options_enabled
=== RUN TestValidateExternalURL_MultipleOptions/Custom_timeout_with_HTTPS
=== PAUSE TestValidateExternalURL_MultipleOptions/Custom_timeout_with_HTTPS
=== RUN TestValidateExternalURL_CustomTimeout/Very_short_timeout
=== PAUSE TestValidateExternalURL_CustomTimeout/Very_short_timeout
=== RUN TestValidateExternalURL_CustomTimeout/Standard_timeout
=== RUN TestValidateExternalURL_MultipleOptions/HTTP_without_AllowHTTP_fails
=== PAUSE TestIPv4MappedIPv6Detection/IPv4-mapped_private_10.x
=== PAUSE TestValidateExternalURL_CustomTimeout/Standard_timeout
=== RUN TestValidateExternalURL_CustomTimeout/Long_timeout
=== RUN TestIPv4MappedIPv6Detection/IPv4-mapped_private_192.168
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local_mid
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local_end
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local_end
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fc00
=== PAUSE TestValidateExternalURL_MultipleOptions/HTTP_without_AllowHTTP_fails
=== PAUSE TestValidateExternalURL_CustomTimeout/Long_timeout
=== PAUSE TestIPv4MappedIPv6Detection/IPv4-mapped_private_192.168
=== RUN TestValidateExternalURL_MultipleOptions/Localhost_without_AllowLocalhost_fails
=== RUN TestIPv4MappedIPv6Detection/IPv4-mapped_metadata
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fc00
=== PAUSE TestValidateExternalURL_MultipleOptions/Localhost_without_AllowLocalhost_fails
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fd00
=== CONT TestValidateExternalURL_RealWorldURLs
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fd00
=== CONT TestValidateExternalURL_PrivateIPBlocking
=== PAUSE TestIPv4MappedIPv6Detection/IPv4-mapped_metadata
=== RUN TestIPv4MappedIPv6Detection/IPv4-mapped_public
=== RUN TestValidateExternalURL_PrivateIPBlocking/Private_IP_10.x.x.x
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fd12
=== PAUSE TestIPv4MappedIPv6Detection/IPv4-mapped_public
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fd12
=== RUN TestIPv4MappedIPv6Detection/Regular_IPv6_loopback
=== RUN TestValidateExternalURL_RealWorldURLs/Slack_webhook_format
=== PAUSE TestIPv4MappedIPv6Detection/Regular_IPv6_loopback
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fdff
=== RUN TestIPv4MappedIPv6Detection/Regular_IPv6_link-local
=== PAUSE TestValidateExternalURL_RealWorldURLs/Slack_webhook_format
=== RUN TestValidateExternalURL_RealWorldURLs/Discord_webhook_format
=== PAUSE TestIPv4MappedIPv6Detection/Regular_IPv6_link-local
=== PAUSE TestValidateExternalURL_PrivateIPBlocking/Private_IP_10.x.x.x
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fdff
=== PAUSE TestValidateExternalURL_RealWorldURLs/Discord_webhook_format
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_Google_DNS
=== RUN TestValidateExternalURL_RealWorldURLs/Generic_API_endpoint
=== RUN TestValidateExternalURL_PrivateIPBlocking/Private_IP_192.168.x.x
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv6_Google_DNS
=== PAUSE TestValidateExternalURL_RealWorldURLs/Generic_API_endpoint
=== PAUSE TestValidateExternalURL_PrivateIPBlocking/Private_IP_192.168.x.x
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_Cloudflare_DNS
=== RUN TestIPv4MappedIPv6Detection/Regular_IPv6_public
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv6_Cloudflare_DNS
=== RUN TestValidateExternalURL_RealWorldURLs/Localhost_for_testing
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_documentation_range
=== PAUSE TestIPv4MappedIPv6Detection/Regular_IPv6_public
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv6_documentation_range
=== CONT TestValidateExternalURL_LocalhostHandling
=== PAUSE TestValidateExternalURL_RealWorldURLs/Localhost_for_testing
=== RUN TestValidateExternalURL_LocalhostHandling/Localhost_without_AllowLocalhost
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv4-mapped_public
=== CONT TestIsPrivateIP
=== PAUSE TestValidateExternalURL_LocalhostHandling/Localhost_without_AllowLocalhost
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv4-mapped_public
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv4-mapped_loopback
=== RUN TestIsPrivateIP/10.0.0.0
=== RUN TestValidateExternalURL_LocalhostHandling/Localhost_with_AllowLocalhost
=== PAUSE TestValidateExternalURL_LocalhostHandling/Localhost_with_AllowLocalhost
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv4-mapped_loopback
=== PAUSE TestIsPrivateIP/10.0.0.0
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv4-mapped_private
=== RUN TestValidateExternalURL_LocalhostHandling/127.0.0.1_with_AllowLocalhost_and_AllowHTTP
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv4-mapped_private
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_unspecified
=== PAUSE TestValidateExternalURL_LocalhostHandling/127.0.0.1_with_AllowLocalhost_and_AllowHTTP
=== RUN TestIsPrivateIP/10.255.255.255
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv6_unspecified
=== RUN TestValidateExternalURL_PrivateIPBlocking/Private_IP_172.16.x.x
=== PAUSE TestValidateExternalURL_PrivateIPBlocking/Private_IP_172.16.x.x
=== PAUSE TestIsPrivateIP/10.255.255.255
=== RUN TestValidateExternalURL_LocalhostHandling/IPv6_loopback_with_AllowLocalhost
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_multicast
=== PAUSE TestIsPrivateIP_IPv6Comprehensive/IPv6_multicast
=== PAUSE TestValidateExternalURL_LocalhostHandling/IPv6_loopback_with_AllowLocalhost
=== RUN TestValidateExternalURL_PrivateIPBlocking/AWS_Metadata_IP
=== RUN TestIsPrivateIP/172.16.0.0
=== PAUSE TestIsPrivateIP/172.16.0.0
=== CONT TestValidateExternalURL_BasicValidation
=== RUN TestValidateExternalURL_BasicValidation/Valid_HTTPS_URL
=== CONT TestAuditEvent_RequiredFields
--- PASS: TestAuditEvent_RequiredFields (0.00s)
=== CONT TestAuditLogger_TimestampFormat
2026/01/10 02:17:13 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:13Z","action":"test","host":"test.com","request_id":"","result":"","resolved_ips":null,"blocked_reason":"","user_id":"","source_ip":""}
--- PASS: TestAuditLogger_TimestampFormat (0.00s)
=== CONT TestGlobalAuditLogger
2026/01/10 02:17:13 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:13Z","action":"url_connectivity_test","host":"test.com","request_id":"req-global","result":"allowed","resolved_ips":null,"blocked_reason":"","user_id":"user-global","source_ip":"192.0.2.10"}
2026/01/10 02:17:13 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:13Z","action":"ssrf_block","host":"blocked.local","request_id":"","result":"blocked","resolved_ips":["127.0.0.1"],"blocked_reason":"loopback","user_id":"user-global","source_ip":"198.51.100.10"}
--- PASS: TestGlobalAuditLogger (0.00s)
=== PAUSE TestValidateExternalURL_PrivateIPBlocking/AWS_Metadata_IP
=== RUN TestIsPrivateIP/172.31.255.255
=== PAUSE TestIsPrivateIP/172.31.255.255
=== PAUSE TestValidateExternalURL_BasicValidation/Valid_HTTPS_URL
=== CONT TestAuditLogger_LogURLTest
2026/01/10 02:17:13 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:13Z","action":"url_connectivity_test","host":"example.com","request_id":"req-789","result":"allowed","resolved_ips":null,"blocked_reason":"","user_id":"user456","source_ip":"192.0.2.1"}
--- PASS: TestAuditLogger_LogURLTest (0.00s)
=== RUN TestValidateExternalURL_PrivateIPBlocking/Loopback_without_AllowLocalhost
=== RUN TestIsPrivateIP/192.168.0.0
=== RUN TestValidateExternalURL_BasicValidation/HTTP_without_AllowHTTP_option
=== PAUSE TestValidateExternalURL_BasicValidation/HTTP_without_AllowHTTP_option
=== CONT TestAuditLogger_LogURLValidation
2026/01/10 02:17:13 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:13Z","action":"url_test","host":"malicious.com","request_id":"req-456","result":"blocked","resolved_ips":["169.254.169.254"],"blocked_reason":"metadata_endpoint","user_id":"attacker","source_ip":"198.51.100.1"}
2026/01/10 02:17:13 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:13Z","action":"test","host":"test.com","request_id":"","result":"","resolved_ips":null,"blocked_reason":"","user_id":"","source_ip":""}
--- PASS: TestAuditLogger_LogURLValidation (0.00s)
=== PAUSE TestValidateExternalURL_PrivateIPBlocking/Loopback_without_AllowLocalhost
=== PAUSE TestIsPrivateIP/192.168.0.0
=== RUN TestIsPrivateIP/192.168.255.255
=== PAUSE TestIsPrivateIP/192.168.255.255
=== RUN TestValidateExternalURL_BasicValidation/HTTP_with_AllowHTTP_option
=== CONT TestAuditLogger_LogSSRFBlock
2026/01/10 02:17:13 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:13Z","action":"ssrf_block","host":"internal.local","request_id":"","result":"blocked","resolved_ips":["10.0.0.1","192.168.1.1"],"blocked_reason":"private_ip","user_id":"user123","source_ip":"203.0.113.5"}
--- PASS: TestAuditLogger_LogSSRFBlock (0.00s)
=== CONT TestValidateExternalURL_Options/WithTimeout
=== CONT TestIsIPv4MappedIPv6_EdgeCases/Mapped_public_IP
=== CONT TestValidateExternalURL_Options/Multiple_options
=== CONT TestIsIPv4MappedIPv6_EdgeCases/All_zeros_except_prefix
=== RUN TestIsPrivateIP/127.0.0.1
=== PAUSE TestIsPrivateIP/127.0.0.1
=== PAUSE TestValidateExternalURL_BasicValidation/HTTP_with_AllowHTTP_option
=== RUN TestValidateExternalURL_BasicValidation/Empty_URL
--- PASS: TestValidateExternalURL_Options (0.00s)
--- PASS: TestValidateExternalURL_Options/WithTimeout (0.00s)
--- PASS: TestValidateExternalURL_Options/Multiple_options (0.00s)
=== CONT TestIsIPv4MappedIPv6_EdgeCases/All_ones
=== CONT TestIsIPv4MappedIPv6_EdgeCases/Pure_IPv6_2001:db8
=== RUN TestIsPrivateIP/127.0.0.2
=== PAUSE TestValidateExternalURL_BasicValidation/Empty_URL
=== CONT TestIsIPv4MappedIPv6_EdgeCases/Standard_mapped
=== PAUSE TestIsPrivateIP/127.0.0.2
=== RUN TestValidateExternalURL_BasicValidation/Missing_scheme
=== RUN TestIsPrivateIP/IPv6_loopback
=== CONT TestValidateExternalURL_EdgeCases/Port_with_non-numeric_characters
=== PAUSE TestValidateExternalURL_BasicValidation/Missing_scheme
=== RUN TestValidateExternalURL_BasicValidation/Just_scheme
=== PAUSE TestIsPrivateIP/IPv6_loopback
=== PAUSE TestValidateExternalURL_BasicValidation/Just_scheme
=== CONT TestIsIPv4MappedIPv6_EdgeCases/IPv6_loopback
=== RUN TestIsPrivateIP/169.254.1.1
=== PAUSE TestIsPrivateIP/169.254.1.1
=== CONT TestValidateExternalURL_EdgeCases/Hostname_at_252_chars_(just_under_limit)
=== RUN TestIsPrivateIP/AWS_metadata
=== PAUSE TestIsPrivateIP/AWS_metadata
=== RUN TestValidateExternalURL_BasicValidation/FTP_protocol
=== RUN TestIsPrivateIP/0.0.0.0
=== PAUSE TestValidateExternalURL_BasicValidation/FTP_protocol
--- PASS: TestIsIPv4MappedIPv6_EdgeCases (0.00s)
--- PASS: TestIsIPv4MappedIPv6_EdgeCases/Mapped_public_IP (0.00s)
--- PASS: TestIsIPv4MappedIPv6_EdgeCases/All_zeros_except_prefix (0.00s)
--- PASS: TestIsIPv4MappedIPv6_EdgeCases/All_ones (0.00s)
--- PASS: TestIsIPv4MappedIPv6_EdgeCases/Pure_IPv6_2001:db8 (0.00s)
--- PASS: TestIsIPv4MappedIPv6_EdgeCases/Standard_mapped (0.00s)
--- PASS: TestIsIPv4MappedIPv6_EdgeCases/IPv6_loopback (0.00s)
=== RUN TestValidateExternalURL_BasicValidation/File_protocol
=== PAUSE TestValidateExternalURL_BasicValidation/File_protocol
=== PAUSE TestIsPrivateIP/0.0.0.0
=== RUN TestValidateExternalURL_BasicValidation/Gopher_protocol
=== CONT TestValidateExternalURL_EdgeCases/Hostname_with_single_dot
=== PAUSE TestValidateExternalURL_BasicValidation/Gopher_protocol
=== RUN TestIsPrivateIP/255.255.255.255
=== RUN TestValidateExternalURL_BasicValidation/Data_URL
=== PAUSE TestIsPrivateIP/255.255.255.255
=== PAUSE TestValidateExternalURL_BasicValidation/Data_URL
=== RUN TestValidateExternalURL_BasicValidation/URL_with_credentials
=== RUN TestIsPrivateIP/240.0.0.1
=== PAUSE TestValidateExternalURL_BasicValidation/URL_with_credentials
=== PAUSE TestIsPrivateIP/240.0.0.1
=== RUN TestValidateExternalURL_BasicValidation/Valid_with_port
=== RUN TestIsPrivateIP/IPv6_unique_local
=== PAUSE TestValidateExternalURL_BasicValidation/Valid_with_port
=== PAUSE TestIsPrivateIP/IPv6_unique_local
=== RUN TestValidateExternalURL_BasicValidation/Valid_with_path
=== RUN TestIsPrivateIP/IPv6_link-local
=== PAUSE TestValidateExternalURL_BasicValidation/Valid_with_path
=== RUN TestValidateExternalURL_BasicValidation/Valid_with_query
=== PAUSE TestIsPrivateIP/IPv6_link-local
=== RUN TestIsPrivateIP/Google_DNS
=== PAUSE TestValidateExternalURL_BasicValidation/Valid_with_query
=== CONT TestValidateExternalURL_EdgeCases/URL_with_username_only
=== PAUSE TestIsPrivateIP/Google_DNS
=== RUN TestIsPrivateIP/Cloudflare_DNS
=== CONT TestValidateExternalURL_EdgeCases/Port_1024_(first_non-privileged)
=== PAUSE TestIsPrivateIP/Cloudflare_DNS
=== RUN TestIsPrivateIP/Public_IPv6
=== PAUSE TestIsPrivateIP/Public_IPv6
=== CONT TestValidateExternalURL_EdgeCases/Triple_dots_in_hostname
=== CONT TestValidateExternalURL_EdgeCases/Port_1_(privileged_but_not_blocked_with_AllowLocalhost)
=== CONT TestValidateExternalURL_EdgeCases/Maximum_valid_port
=== CONT TestValidateExternalURL_EdgeCases/Port_1023_(edge_of_privileged_range)
=== CONT TestValidateExternalURL_HostnameValidation/Hostname_with_double_dots_mid
=== CONT TestValidateExternalURL_HostnameValidation/Extremely_long_hostname_(254_chars)
=== CONT TestParsePort/Valid_port_80
=== CONT TestParsePort/Negative_port
=== CONT TestParsePort/Port_zero
=== CONT TestParsePort/Non-numeric_port
=== CONT TestParsePort/Empty_port
=== CONT TestParsePort/Valid_port_8080
=== CONT TestParsePort/Valid_port_65535
=== CONT TestParsePort/Valid_port_443
=== CONT TestValidateExternalURL_CloudMetadataDetection/Azure_metadata_service
url_validator_test.go:600: Correctly blocked http://169.254.169.254/metadata/instance with error: connection to private ip addresses is blocked for security (detected IPv4-mapped IPv6: 169.254.169.254)
=== CONT TestValidateExternalURL_CloudMetadataDetection/GCP_metadata_service
=== CONT TestValidateExternalURL_CloudMetadataDetection/AWS_metadata_IPv6
--- PASS: TestParsePort (0.00s)
--- PASS: TestParsePort/Valid_port_80 (0.00s)
--- PASS: TestParsePort/Negative_port (0.00s)
--- PASS: TestParsePort/Port_zero (0.00s)
--- PASS: TestParsePort/Non-numeric_port (0.00s)
--- PASS: TestParsePort/Valid_port_8080 (0.00s)
--- PASS: TestParsePort/Valid_port_65535 (0.00s)
--- PASS: TestParsePort/Valid_port_443 (0.00s)
--- PASS: TestParsePort/Empty_port (0.00s)
=== NAME TestValidateExternalURL_CloudMetadataDetection/AWS_metadata_IPv6
url_validator_test.go:600: Correctly blocked http://[fd00:ec2::254]/latest/meta-data/ with error: connection to private ip addresses is blocked for security (detected: fd00::)
=== CONT TestValidateExternalURL_CloudMetadataDetection/AWS_metadata_service
url_validator_test.go:600: Correctly blocked http://169.254.169.254/latest/meta-data/ with error: connection to private ip addresses is blocked for security (detected IPv4-mapped IPv6: 169.254.169.254)
=== CONT TestSanitizeIPForError/Private_IPv4_192.168
=== CONT TestValidateExternalURL_PortValidation/Port_80_(standard_HTTP)_-_should_allow
=== NAME TestValidateExternalURL_CloudMetadataDetection/GCP_metadata_service
url_validator_test.go:600: Correctly blocked http://metadata.google.internal/computeMetadata/v1/ with error: dns resolution failed for metadata.google.internal: lookup metadata.google.internal on 127.0.0.53:53: no such host
=== CONT TestValidateExternalURL_PortValidation/Port_0_-_should_block
=== CONT TestValidateExternalURL_PortValidation/Port_22_with_AllowLocalhost_-_should_allow
=== CONT TestValidateExternalURL_PortValidation/Port_65536_-_should_block
--- PASS: TestValidateExternalURL_CloudMetadataDetection (0.00s)
--- PASS: TestValidateExternalURL_CloudMetadataDetection/Azure_metadata_service (0.00s)
--- PASS: TestValidateExternalURL_CloudMetadataDetection/AWS_metadata_IPv6 (0.00s)
--- PASS: TestValidateExternalURL_CloudMetadataDetection/AWS_metadata_service (0.00s)
--- PASS: TestValidateExternalURL_CloudMetadataDetection/GCP_metadata_service (0.00s)
=== CONT TestValidateExternalURL_PortValidation/Port_8080_(non-privileged)_-_should_allow
=== CONT TestValidateExternalURL_PortValidation/Port_3306_(MySQL)_-_should_block_if_<_1024
=== CONT TestValidateExternalURL_PortValidation/Port_22_(SSH)_-_should_block
=== CONT TestValidateExternalURL_PortValidation/Port_443_(standard_HTTPS)_-_should_allow
=== CONT TestSanitizeIPForError/Loopback_IPv4
--- PASS: TestValidateExternalURL_EdgeCases (0.00s)
--- PASS: TestValidateExternalURL_EdgeCases/Port_with_non-numeric_characters (0.00s)
--- PASS: TestValidateExternalURL_EdgeCases/URL_with_username_only (0.00s)
--- PASS: TestValidateExternalURL_EdgeCases/Hostname_at_252_chars_(just_under_limit) (0.00s)
--- PASS: TestValidateExternalURL_EdgeCases/Triple_dots_in_hostname (0.00s)
--- PASS: TestValidateExternalURL_EdgeCases/Port_1_(privileged_but_not_blocked_with_AllowLocalhost) (0.00s)
--- PASS: TestValidateExternalURL_EdgeCases/Port_1023_(edge_of_privileged_range) (0.00s)
--- PASS: TestValidateExternalURL_EdgeCases/Hostname_with_single_dot (0.00s)
--- PASS: TestValidateExternalURL_EdgeCases/Maximum_valid_port (0.01s)
--- PASS: TestValidateExternalURL_EdgeCases/Port_1024_(first_non-privileged) (0.01s)
=== CONT TestValidateExternalURL_PortValidation/Port_25_(SMTP)_-_should_block
=== CONT TestSanitizeIPForError/Invalid_IP
=== CONT TestSanitizeIPForError/IPv6_unique_local
=== CONT TestSanitizeIPForError/IPv6_link-local
=== CONT TestSanitizeIPForError/Private_IPv4_172.16
=== CONT TestSanitizeIPForError/Private_IPv4_10.x
=== CONT TestSanitizeIPForError/Metadata_IPv4
=== CONT TestValidateExternalURL_MultipleIPsAllPrivate/IP_192.168.1.1
=== CONT TestValidateExternalURL_MultipleIPsAllPrivate/IP_172.16.0.1
=== CONT TestValidateExternalURL_MultipleIPsAllPrivate/IP_10.0.0.1
=== CONT TestValidateExternalURL_CustomTimeout/Very_short_timeout
--- PASS: TestSanitizeIPForError (0.00s)
--- PASS: TestSanitizeIPForError/Private_IPv4_192.168 (0.00s)
--- PASS: TestSanitizeIPForError/Loopback_IPv4 (0.00s)
--- PASS: TestSanitizeIPForError/IPv6_unique_local (0.00s)
--- PASS: TestSanitizeIPForError/IPv6_link-local (0.00s)
--- PASS: TestSanitizeIPForError/Invalid_IP (0.00s)
--- PASS: TestSanitizeIPForError/Private_IPv4_172.16 (0.00s)
--- PASS: TestSanitizeIPForError/Metadata_IPv4 (0.00s)
--- PASS: TestSanitizeIPForError/Private_IPv4_10.x (0.00s)
=== NAME TestValidateExternalURL_CustomTimeout/Very_short_timeout
url_validator_test.go:499: Warning: timeout may not be strictly enforced (elapsed: 91.891µs, timeout: 1ns)
url_validator_test.go:504: URL: https://example.com, Timeout: 1ns, Elapsed: 91.891µs, Error: dns resolution failed for example.com: lookup example.com: i/o timeout
=== CONT TestValidateExternalURL_HostnameValidation/Hostname_with_double_dots
--- PASS: TestValidateExternalURL_HostnameValidation (0.00s)
--- PASS: TestValidateExternalURL_HostnameValidation/Hostname_with_double_dots_mid (0.00s)
--- PASS: TestValidateExternalURL_HostnameValidation/Extremely_long_hostname_(254_chars) (0.00s)
--- PASS: TestValidateExternalURL_HostnameValidation/Hostname_with_double_dots (0.00s)
--- PASS: TestValidateExternalURL_MultipleIPsAllPrivate (0.00s)
--- PASS: TestValidateExternalURL_MultipleIPsAllPrivate/IP_192.168.1.1 (0.00s)
--- PASS: TestValidateExternalURL_MultipleIPsAllPrivate/IP_172.16.0.1 (0.00s)
--- PASS: TestValidateExternalURL_MultipleIPsAllPrivate/IP_10.0.0.1 (0.00s)
=== CONT TestValidateExternalURL_CustomTimeout/Long_timeout
=== CONT TestValidateExternalURL_CustomTimeout/Standard_timeout
=== CONT TestValidateExternalURL_MultipleOptions/All_options_enabled
=== CONT TestValidateExternalURL_MultipleOptions/Localhost_without_AllowLocalhost_fails
=== CONT TestValidateExternalURL_MultipleOptions/HTTP_without_AllowHTTP_fails
=== CONT TestValidateExternalURL_MultipleOptions/Custom_timeout_with_HTTPS
=== CONT TestIPv4MappedIPv6Detection/IPv4-mapped_loopback
=== CONT TestIPv4MappedIPv6Detection/Regular_IPv6_link-local
=== CONT TestIPv4MappedIPv6Detection/Regular_IPv6_public
=== CONT TestIPv4MappedIPv6Detection/Regular_IPv6_loopback
--- PASS: TestValidateExternalURL_PortValidation (0.00s)
--- PASS: TestValidateExternalURL_PortValidation/Port_0_-_should_block (0.00s)
--- PASS: TestValidateExternalURL_PortValidation/Port_22_with_AllowLocalhost_-_should_allow (0.00s)
--- PASS: TestValidateExternalURL_PortValidation/Port_65536_-_should_block (0.00s)
--- PASS: TestValidateExternalURL_PortValidation/Port_80_(standard_HTTP)_-_should_allow (0.01s)
--- PASS: TestValidateExternalURL_PortValidation/Port_22_(SSH)_-_should_block (0.00s)
--- PASS: TestValidateExternalURL_PortValidation/Port_8080_(non-privileged)_-_should_allow (0.00s)
--- PASS: TestValidateExternalURL_PortValidation/Port_25_(SMTP)_-_should_block (0.00s)
--- PASS: TestValidateExternalURL_PortValidation/Port_3306_(MySQL)_-_should_block_if_<_1024 (0.00s)
--- PASS: TestValidateExternalURL_PortValidation/Port_443_(standard_HTTPS)_-_should_allow (0.00s)
=== CONT TestIPv4MappedIPv6Detection/IPv4-mapped_public
=== CONT TestIPv4MappedIPv6Detection/IPv4-mapped_private_10.x
=== CONT TestIPv4MappedIPv6Detection/IPv4-mapped_private_192.168
--- PASS: TestValidateExternalURL_MultipleOptions (0.00s)
--- PASS: TestValidateExternalURL_MultipleOptions/All_options_enabled (0.00s)
--- PASS: TestValidateExternalURL_MultipleOptions/Localhost_without_AllowLocalhost_fails (0.00s)
--- PASS: TestValidateExternalURL_MultipleOptions/HTTP_without_AllowHTTP_fails (0.00s)
--- PASS: TestValidateExternalURL_MultipleOptions/Custom_timeout_with_HTTPS (0.00s)
=== CONT TestIPv4MappedIPv6Detection/IPv4-mapped_metadata
=== CONT TestValidateExternalURL_RealWorldURLs/Discord_webhook_format
=== CONT TestValidateExternalURL_RealWorldURLs/Generic_API_endpoint
--- PASS: TestIPv4MappedIPv6Detection (0.00s)
--- PASS: TestIPv4MappedIPv6Detection/IPv4-mapped_loopback (0.00s)
--- PASS: TestIPv4MappedIPv6Detection/Regular_IPv6_link-local (0.00s)
--- PASS: TestIPv4MappedIPv6Detection/Regular_IPv6_public (0.00s)
--- PASS: TestIPv4MappedIPv6Detection/Regular_IPv6_loopback (0.00s)
--- PASS: TestIPv4MappedIPv6Detection/IPv4-mapped_public (0.00s)
--- PASS: TestIPv4MappedIPv6Detection/IPv4-mapped_private_10.x (0.00s)
--- PASS: TestIPv4MappedIPv6Detection/IPv4-mapped_private_192.168 (0.00s)
--- PASS: TestIPv4MappedIPv6Detection/IPv4-mapped_metadata (0.00s)
=== CONT TestValidateExternalURL_RealWorldURLs/Localhost_for_testing
=== CONT TestValidateExternalURL_RealWorldURLs/Slack_webhook_format
=== NAME TestValidateExternalURL_CustomTimeout/Standard_timeout
url_validator_test.go:504: URL: https://api.github.com, Timeout: 3s, Elapsed: 11.316478ms, Error: <nil>
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv6_loopback
=== CONT TestValidateExternalURL_LocalhostHandling/Localhost_without_AllowLocalhost
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv6_multicast
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv6_unspecified
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv4-mapped_private
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv4-mapped_loopback
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv4-mapped_public
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv6_Cloudflare_DNS
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fdff
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv6_Google_DNS
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fd12
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fd00
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv6_documentation_range
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fc00
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local_mid
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local_start
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv6_loopback_expanded
=== CONT TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local_end
=== CONT TestValidateExternalURL_LocalhostHandling/IPv6_loopback_with_AllowLocalhost
=== CONT TestValidateExternalURL_LocalhostHandling/Localhost_with_AllowLocalhost
=== CONT TestValidateExternalURL_LocalhostHandling/127.0.0.1_with_AllowLocalhost_and_AllowHTTP
--- PASS: TestIsPrivateIP_IPv6Comprehensive (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_loopback (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_multicast (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_unspecified (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv4-mapped_loopback (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv4-mapped_private (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_Cloudflare_DNS (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fdff (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv4-mapped_public (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_Google_DNS (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fd12 (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fd00 (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_documentation_range (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fc00 (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local_mid (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local_start (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_loopback_expanded (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local_end (0.00s)
=== CONT TestValidateExternalURL_PrivateIPBlocking/Private_IP_192.168.x.x
=== CONT TestValidateExternalURL_PrivateIPBlocking/AWS_Metadata_IP
=== CONT TestValidateExternalURL_PrivateIPBlocking/Private_IP_10.x.x.x
=== CONT TestValidateExternalURL_PrivateIPBlocking/Loopback_without_AllowLocalhost
=== CONT TestValidateExternalURL_PrivateIPBlocking/Private_IP_172.16.x.x
=== CONT TestValidateExternalURL_BasicValidation/HTTP_without_AllowHTTP_option
=== CONT TestValidateExternalURL_BasicValidation/Valid_with_query
=== CONT TestValidateExternalURL_BasicValidation/Valid_with_port
--- PASS: TestValidateExternalURL_LocalhostHandling (0.00s)
--- PASS: TestValidateExternalURL_LocalhostHandling/Localhost_without_AllowLocalhost (0.00s)
--- PASS: TestValidateExternalURL_LocalhostHandling/IPv6_loopback_with_AllowLocalhost (0.00s)
--- PASS: TestValidateExternalURL_LocalhostHandling/Localhost_with_AllowLocalhost (0.00s)
--- PASS: TestValidateExternalURL_LocalhostHandling/127.0.0.1_with_AllowLocalhost_and_AllowHTTP (0.00s)
--- PASS: TestValidateExternalURL_PrivateIPBlocking (0.00s)
--- PASS: TestValidateExternalURL_PrivateIPBlocking/Private_IP_192.168.x.x (0.00s)
--- PASS: TestValidateExternalURL_PrivateIPBlocking/AWS_Metadata_IP (0.00s)
--- PASS: TestValidateExternalURL_PrivateIPBlocking/Private_IP_10.x.x.x (0.00s)
--- PASS: TestValidateExternalURL_PrivateIPBlocking/Private_IP_172.16.x.x (0.00s)
--- PASS: TestValidateExternalURL_PrivateIPBlocking/Loopback_without_AllowLocalhost (0.00s)
=== CONT TestValidateExternalURL_BasicValidation/URL_with_credentials
=== CONT TestValidateExternalURL_BasicValidation/Valid_with_path
--- PASS: TestValidateExternalURL_RealWorldURLs (0.00s)
--- PASS: TestValidateExternalURL_RealWorldURLs/Generic_API_endpoint (0.01s)
--- PASS: TestValidateExternalURL_RealWorldURLs/Localhost_for_testing (0.00s)
--- PASS: TestValidateExternalURL_RealWorldURLs/Discord_webhook_format (0.01s)
--- PASS: TestValidateExternalURL_RealWorldURLs/Slack_webhook_format (0.01s)
=== NAME TestValidateExternalURL_BasicValidation/Valid_with_query
url_validator_test.go:133: Note: DNS resolution failed for https://api.example.com/webhook?token=abc123 (expected in test environment)
=== NAME TestValidateExternalURL_BasicValidation/Valid_with_path
url_validator_test.go:133: Note: DNS resolution failed for https://api.example.com/path/to/webhook (expected in test environment)
=== CONT TestValidateExternalURL_BasicValidation/File_protocol
=== NAME TestValidateExternalURL_BasicValidation/Valid_with_port
url_validator_test.go:133: Note: DNS resolution failed for https://api.example.com:8080/webhook (expected in test environment)
=== CONT TestValidateExternalURL_BasicValidation/FTP_protocol
=== CONT TestValidateExternalURL_BasicValidation/Just_scheme
=== CONT TestValidateExternalURL_BasicValidation/Missing_scheme
=== CONT TestValidateExternalURL_BasicValidation/Empty_URL
=== CONT TestValidateExternalURL_BasicValidation/HTTP_with_AllowHTTP_option
=== CONT TestValidateExternalURL_BasicValidation/Gopher_protocol
=== CONT TestValidateExternalURL_BasicValidation/Valid_HTTPS_URL
=== CONT TestValidateExternalURL_BasicValidation/Data_URL
=== CONT TestIsPrivateIP/10.0.0.0
=== CONT TestIsPrivateIP/Public_IPv6
=== CONT TestIsPrivateIP/Cloudflare_DNS
=== CONT TestIsPrivateIP/Google_DNS
=== CONT TestIsPrivateIP/IPv6_link-local
=== CONT TestIsPrivateIP/IPv6_unique_local
=== CONT TestIsPrivateIP/240.0.0.1
=== CONT TestIsPrivateIP/255.255.255.255
=== CONT TestIsPrivateIP/0.0.0.0
=== CONT TestIsPrivateIP/169.254.1.1
=== CONT TestIsPrivateIP/AWS_metadata
=== CONT TestIsPrivateIP/127.0.0.2
=== CONT TestIsPrivateIP/127.0.0.1
=== CONT TestIsPrivateIP/IPv6_loopback
=== CONT TestIsPrivateIP/192.168.0.0
=== CONT TestIsPrivateIP/172.31.255.255
=== CONT TestIsPrivateIP/192.168.255.255
=== CONT TestIsPrivateIP/10.255.255.255
=== CONT TestIsPrivateIP/172.16.0.0
--- PASS: TestIsPrivateIP (0.01s)
--- PASS: TestIsPrivateIP/10.0.0.0 (0.00s)
--- PASS: TestIsPrivateIP/Public_IPv6 (0.00s)
--- PASS: TestIsPrivateIP/Cloudflare_DNS (0.00s)
--- PASS: TestIsPrivateIP/Google_DNS (0.00s)
--- PASS: TestIsPrivateIP/IPv6_link-local (0.00s)
--- PASS: TestIsPrivateIP/IPv6_unique_local (0.00s)
--- PASS: TestIsPrivateIP/240.0.0.1 (0.00s)
--- PASS: TestIsPrivateIP/255.255.255.255 (0.00s)
--- PASS: TestIsPrivateIP/0.0.0.0 (0.00s)
--- PASS: TestIsPrivateIP/169.254.1.1 (0.00s)
--- PASS: TestIsPrivateIP/AWS_metadata (0.00s)
--- PASS: TestIsPrivateIP/127.0.0.2 (0.00s)
--- PASS: TestIsPrivateIP/127.0.0.1 (0.00s)
--- PASS: TestIsPrivateIP/IPv6_loopback (0.00s)
--- PASS: TestIsPrivateIP/192.168.0.0 (0.00s)
--- PASS: TestIsPrivateIP/172.31.255.255 (0.00s)
--- PASS: TestIsPrivateIP/192.168.255.255 (0.00s)
--- PASS: TestIsPrivateIP/10.255.255.255 (0.00s)
--- PASS: TestIsPrivateIP/172.16.0.0 (0.00s)
=== NAME TestValidateExternalURL_BasicValidation/Valid_HTTPS_URL
url_validator_test.go:133: Note: DNS resolution failed for https://api.example.com/webhook (expected in test environment)
=== NAME TestValidateExternalURL_BasicValidation/HTTP_with_AllowHTTP_option
url_validator_test.go:133: Note: DNS resolution failed for http://api.example.com/webhook (expected in test environment)
--- PASS: TestValidateExternalURL_BasicValidation (0.00s)
--- PASS: TestValidateExternalURL_BasicValidation/HTTP_without_AllowHTTP_option (0.00s)
--- PASS: TestValidateExternalURL_BasicValidation/URL_with_credentials (0.00s)
--- PASS: TestValidateExternalURL_BasicValidation/Valid_with_query (0.03s)
--- PASS: TestValidateExternalURL_BasicValidation/Valid_with_path (0.02s)
--- PASS: TestValidateExternalURL_BasicValidation/File_protocol (0.00s)
--- PASS: TestValidateExternalURL_BasicValidation/Valid_with_port (0.03s)
--- PASS: TestValidateExternalURL_BasicValidation/FTP_protocol (0.00s)
--- PASS: TestValidateExternalURL_BasicValidation/Just_scheme (0.00s)
--- PASS: TestValidateExternalURL_BasicValidation/Missing_scheme (0.00s)
--- PASS: TestValidateExternalURL_BasicValidation/Empty_URL (0.00s)
--- PASS: TestValidateExternalURL_BasicValidation/Gopher_protocol (0.00s)
--- PASS: TestValidateExternalURL_BasicValidation/Data_URL (0.00s)
--- PASS: TestValidateExternalURL_BasicValidation/Valid_HTTPS_URL (0.00s)
--- PASS: TestValidateExternalURL_BasicValidation/HTTP_with_AllowHTTP_option (0.00s)
=== NAME TestValidateExternalURL_CustomTimeout/Long_timeout
url_validator_test.go:504: URL: https://slow-dns-server.example, Timeout: 30s, Elapsed: 98.181784ms, Error: dns resolution failed for slow-dns-server.example: lookup slow-dns-server.example on 127.0.0.53:53: no such host
--- PASS: TestValidateExternalURL_CustomTimeout (0.00s)
--- PASS: TestValidateExternalURL_CustomTimeout/Very_short_timeout (0.00s)
--- PASS: TestValidateExternalURL_CustomTimeout/Standard_timeout (0.01s)
--- PASS: TestValidateExternalURL_CustomTimeout/Long_timeout (0.10s)
PASS
coverage: 95.7% of statements
ok github.com/Wikid82/charon/backend/internal/security (cached) coverage: 95.7% of statements
=== RUN TestNewRouter
[GIN] 2026/01/10 - 02:17:15 | 200 | 16.260065ms | | GET "/"
[GIN] 2026/01/10 - 02:17:15 | 404 | 168.03µs | | GET "/api/this-route-does-not-exist"
--- PASS: TestNewRouter (0.02s)
PASS
coverage: 93.3% of statements
ok github.com/Wikid82/charon/backend/internal/server (cached) coverage: 93.3% of statements
=== RUN TestAccessListService_Create
=== RUN TestAccessListService_Create/create_whitelist_with_valid_IP_rules
=== RUN TestAccessListService_Create/create_geo_whitelist_with_valid_country_codes
=== RUN TestAccessListService_Create/create_local_network_only_ACL
=== RUN TestAccessListService_Create/fail_with_empty_name
=== RUN TestAccessListService_Create/fail_with_invalid_type
=== RUN TestAccessListService_Create/fail_with_invalid_IP_address
=== RUN TestAccessListService_Create/fail_geo-blocking_without_country_codes
=== RUN TestAccessListService_Create/fail_with_invalid_country_code
--- PASS: TestAccessListService_Create (0.03s)
--- PASS: TestAccessListService_Create/create_whitelist_with_valid_IP_rules (0.00s)
--- PASS: TestAccessListService_Create/create_geo_whitelist_with_valid_country_codes (0.00s)
--- PASS: TestAccessListService_Create/create_local_network_only_ACL (0.00s)
--- PASS: TestAccessListService_Create/fail_with_empty_name (0.00s)
--- PASS: TestAccessListService_Create/fail_with_invalid_type (0.00s)
--- PASS: TestAccessListService_Create/fail_with_invalid_IP_address (0.00s)
--- PASS: TestAccessListService_Create/fail_geo-blocking_without_country_codes (0.00s)
--- PASS: TestAccessListService_Create/fail_with_invalid_country_code (0.00s)
=== RUN TestAccessListService_GetByID
=== RUN TestAccessListService_GetByID/get_existing_ACL
=== RUN TestAccessListService_GetByID/get_non-existent_ACL
2026/01/10 02:17:38 /projects/Charon/backend/internal/services/access_list_service.go:105 record not found
[0.089ms] [rows:0] SELECT * FROM `access_lists` WHERE `access_lists`.`id` = 99999 ORDER BY `access_lists`.`id` LIMIT 1
--- PASS: TestAccessListService_GetByID (0.02s)
--- PASS: TestAccessListService_GetByID/get_existing_ACL (0.00s)
--- PASS: TestAccessListService_GetByID/get_non-existent_ACL (0.00s)
=== RUN TestAccessListService_GetByUUID
=== RUN TestAccessListService_GetByUUID/get_existing_ACL_by_UUID
=== RUN TestAccessListService_GetByUUID/get_non-existent_ACL_by_UUID
2026/01/10 02:17:38 /projects/Charon/backend/internal/services/access_list_service.go:117 record not found
[0.099ms] [rows:0] SELECT * FROM `access_lists` WHERE uuid = "non-existent-uuid" ORDER BY `access_lists`.`id` LIMIT 1
--- PASS: TestAccessListService_GetByUUID (0.02s)
--- PASS: TestAccessListService_GetByUUID/get_existing_ACL_by_UUID (0.00s)
--- PASS: TestAccessListService_GetByUUID/get_non-existent_ACL_by_UUID (0.00s)
=== RUN TestAccessListService_List
=== RUN TestAccessListService_List/list_all_ACLs
--- PASS: TestAccessListService_List (0.02s)
--- PASS: TestAccessListService_List/list_all_ACLs (0.00s)
=== RUN TestAccessListService_Update
=== RUN TestAccessListService_Update/update_successfully
=== RUN TestAccessListService_Update/fail_update_on_non-existent_ACL
2026/01/10 02:17:38 /projects/Charon/backend/internal/services/access_list_service.go:105 record not found
[0.093ms] [rows:0] SELECT * FROM `access_lists` WHERE `access_lists`.`id` = 99999 ORDER BY `access_lists`.`id` LIMIT 1
=== RUN TestAccessListService_Update/fail_update_with_invalid_data
--- PASS: TestAccessListService_Update (0.03s)
--- PASS: TestAccessListService_Update/update_successfully (0.00s)
--- PASS: TestAccessListService_Update/fail_update_on_non-existent_ACL (0.00s)
--- PASS: TestAccessListService_Update/fail_update_with_invalid_data (0.00s)
=== RUN TestAccessListService_Delete
=== RUN TestAccessListService_Delete/delete_successfully
2026/01/10 02:17:38 /projects/Charon/backend/internal/services/access_list_service.go:105 record not found
[0.226ms] [rows:0] SELECT * FROM `access_lists` WHERE `access_lists`.`id` = 1 ORDER BY `access_lists`.`id` LIMIT 1
=== RUN TestAccessListService_Delete/fail_delete_non-existent_ACL
=== RUN TestAccessListService_Delete/fail_delete_ACL_in_use
--- PASS: TestAccessListService_Delete (0.03s)
--- PASS: TestAccessListService_Delete/delete_successfully (0.00s)
--- PASS: TestAccessListService_Delete/fail_delete_non-existent_ACL (0.00s)
--- PASS: TestAccessListService_Delete/fail_delete_ACL_in_use (0.00s)
=== RUN TestAccessListService_TestIP
=== RUN TestAccessListService_TestIP/whitelist_allows_matching_IP
=== RUN TestAccessListService_TestIP/whitelist_blocks_non-matching_IP
=== RUN TestAccessListService_TestIP/blacklist_blocks_matching_IP
=== RUN TestAccessListService_TestIP/blacklist_allows_non-matching_IP
=== RUN TestAccessListService_TestIP/local_network_only_allows_RFC1918
=== RUN TestAccessListService_TestIP/disabled_ACL_allows_all
=== RUN TestAccessListService_TestIP/fail_with_invalid_IP
--- PASS: TestAccessListService_TestIP (0.03s)
--- PASS: TestAccessListService_TestIP/whitelist_allows_matching_IP (0.00s)
--- PASS: TestAccessListService_TestIP/whitelist_blocks_non-matching_IP (0.00s)
--- PASS: TestAccessListService_TestIP/blacklist_blocks_matching_IP (0.00s)
--- PASS: TestAccessListService_TestIP/blacklist_allows_non-matching_IP (0.00s)
--- PASS: TestAccessListService_TestIP/local_network_only_allows_RFC1918 (0.00s)
--- PASS: TestAccessListService_TestIP/disabled_ACL_allows_all (0.00s)
--- PASS: TestAccessListService_TestIP/fail_with_invalid_IP (0.00s)
=== RUN TestAccessListService_GetTemplates
--- PASS: TestAccessListService_GetTemplates (0.02s)
=== RUN TestAccessListService_Validation
=== RUN TestAccessListService_Validation/validate_CIDR_formats
=== RUN TestAccessListService_Validation/validate_country_codes
=== RUN TestAccessListService_Validation/validate_types
--- PASS: TestAccessListService_Validation (0.02s)
--- PASS: TestAccessListService_Validation/validate_CIDR_formats (0.00s)
--- PASS: TestAccessListService_Validation/validate_country_codes (0.00s)
--- PASS: TestAccessListService_Validation/validate_types (0.00s)
=== RUN TestIPMatchesCIDR_Helper
=== RUN TestIPMatchesCIDR_Helper/IPv4_in_subnet
=== RUN TestIPMatchesCIDR_Helper/IPv4_not_in_subnet
=== RUN TestIPMatchesCIDR_Helper/IPv4_single_IP_match
=== RUN TestIPMatchesCIDR_Helper/IPv4_single_IP_no_match
=== RUN TestIPMatchesCIDR_Helper/IPv6_in_subnet
=== RUN TestIPMatchesCIDR_Helper/IPv6_not_in_subnet
=== RUN TestIPMatchesCIDR_Helper/Invalid_CIDR
--- PASS: TestIPMatchesCIDR_Helper (0.02s)
--- PASS: TestIPMatchesCIDR_Helper/IPv4_in_subnet (0.00s)
--- PASS: TestIPMatchesCIDR_Helper/IPv4_not_in_subnet (0.00s)
--- PASS: TestIPMatchesCIDR_Helper/IPv4_single_IP_match (0.00s)
--- PASS: TestIPMatchesCIDR_Helper/IPv4_single_IP_no_match (0.00s)
--- PASS: TestIPMatchesCIDR_Helper/IPv6_in_subnet (0.00s)
--- PASS: TestIPMatchesCIDR_Helper/IPv6_not_in_subnet (0.00s)
--- PASS: TestIPMatchesCIDR_Helper/Invalid_CIDR (0.00s)
=== RUN TestIsPrivateIP_Helper
=== RUN TestIsPrivateIP_Helper/Private_10.x.x.x
=== RUN TestIsPrivateIP_Helper/Private_172.16.x.x
=== RUN TestIsPrivateIP_Helper/Private_192.168.x.x
=== RUN TestIsPrivateIP_Helper/Private_127.0.0.1
=== RUN TestIsPrivateIP_Helper/Private_::1
=== RUN TestIsPrivateIP_Helper/Private_fc00::/7
=== RUN TestIsPrivateIP_Helper/Public_8.8.8.8
=== RUN TestIsPrivateIP_Helper/Public_1.1.1.1
=== RUN TestIsPrivateIP_Helper/Public_IPv6
--- PASS: TestIsPrivateIP_Helper (0.02s)
--- PASS: TestIsPrivateIP_Helper/Private_10.x.x.x (0.00s)
--- PASS: TestIsPrivateIP_Helper/Private_172.16.x.x (0.00s)
--- PASS: TestIsPrivateIP_Helper/Private_192.168.x.x (0.00s)
--- PASS: TestIsPrivateIP_Helper/Private_127.0.0.1 (0.00s)
--- PASS: TestIsPrivateIP_Helper/Private_::1 (0.00s)
--- PASS: TestIsPrivateIP_Helper/Private_fc00::/7 (0.00s)
--- PASS: TestIsPrivateIP_Helper/Public_8.8.8.8 (0.00s)
--- PASS: TestIsPrivateIP_Helper/Public_1.1.1.1 (0.00s)
--- PASS: TestIsPrivateIP_Helper/Public_IPv6 (0.00s)
=== RUN TestAccessListService_ListFunction
--- PASS: TestAccessListService_ListFunction (0.02s)
=== RUN TestAccessListService_SetGeoIPService
--- PASS: TestAccessListService_SetGeoIPService (0.01s)
=== RUN TestAccessListService_GeoACL_NoGeoIPService
=== RUN TestAccessListService_GeoACL_NoGeoIPService/geo_whitelist_without_GeoIP_service_allows_traffic
=== RUN TestAccessListService_GeoACL_NoGeoIPService/geo_blacklist_without_GeoIP_service_allows_traffic
--- PASS: TestAccessListService_GeoACL_NoGeoIPService (0.02s)
--- PASS: TestAccessListService_GeoACL_NoGeoIPService/geo_whitelist_without_GeoIP_service_allows_traffic (0.00s)
--- PASS: TestAccessListService_GeoACL_NoGeoIPService/geo_blacklist_without_GeoIP_service_allows_traffic (0.00s)
=== RUN TestAccessListService_ParseCountryCodes
=== RUN TestAccessListService_ParseCountryCodes/parse_single_code
=== RUN TestAccessListService_ParseCountryCodes/parse_multiple_codes
=== RUN TestAccessListService_ParseCountryCodes/parse_with_spaces
=== RUN TestAccessListService_ParseCountryCodes/parse_with_lowercase
=== RUN TestAccessListService_ParseCountryCodes/parse_empty_string
=== RUN TestAccessListService_ParseCountryCodes/parse_with_empty_entries
--- PASS: TestAccessListService_ParseCountryCodes (0.02s)
--- PASS: TestAccessListService_ParseCountryCodes/parse_single_code (0.00s)
--- PASS: TestAccessListService_ParseCountryCodes/parse_multiple_codes (0.00s)
--- PASS: TestAccessListService_ParseCountryCodes/parse_with_spaces (0.00s)
--- PASS: TestAccessListService_ParseCountryCodes/parse_with_lowercase (0.00s)
--- PASS: TestAccessListService_ParseCountryCodes/parse_empty_string (0.00s)
--- PASS: TestAccessListService_ParseCountryCodes/parse_with_empty_entries (0.00s)
=== RUN TestAuthService_Register
--- PASS: TestAuthService_Register (1.62s)
=== RUN TestAuthService_Login
--- PASS: TestAuthService_Login (5.20s)
=== RUN TestAuthService_ChangePassword
2026/01/10 02:17:49 /projects/Charon/backend/internal/services/auth_service.go:113 record not found
[0.178ms] [rows:0] SELECT * FROM `users` WHERE `users`.`id` = 999 ORDER BY `users`.`id` LIMIT 1
--- PASS: TestAuthService_ChangePassword (4.53s)
=== RUN TestAuthService_ValidateToken
--- PASS: TestAuthService_ValidateToken (1.59s)
=== RUN TestAuthService_GetUserByID
2026/01/10 02:17:52 /projects/Charon/backend/internal/services/auth_service.go:147 record not found
[0.064ms] [rows:0] SELECT * FROM `users` WHERE `users`.`id` = 999 ORDER BY `users`.`id` LIMIT 1
--- PASS: TestAuthService_GetUserByID (0.81s)
=== RUN TestBackupService_GetAvailableSpace
=== PAUSE TestBackupService_GetAvailableSpace
=== RUN TestBackupService_CreateAndList
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestBackupService_CreateAndList (0.00s)
=== RUN TestBackupService_Restore_ZipSlip
--- PASS: TestBackupService_Restore_ZipSlip (0.00s)
=== RUN TestBackupService_PathTraversal
--- PASS: TestBackupService_PathTraversal (0.00s)
=== RUN TestBackupService_RunScheduledBackup
time="2026-01-10T02:17:52Z" level=info msg="Starting scheduled backup"
time="2026-01-10T02:17:52Z" level=warning msg="Warning: could not backup caddy dir" error="lstat /tmp/TestBackupService_RunScheduledBackup1537072281/001/data/caddy: no such file or directory"
time="2026-01-10T02:17:52Z" level=info msg="Scheduled backup created" backup=backup_2026-01-10_02-17-52.zip
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestBackupService_RunScheduledBackup (0.00s)
=== RUN TestBackupService_CreateBackup_Errors
=== RUN TestBackupService_CreateBackup_Errors/missing_database_file
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
=== RUN TestBackupService_CreateBackup_Errors/cannot_create_backup_directory
--- PASS: TestBackupService_CreateBackup_Errors (0.00s)
--- PASS: TestBackupService_CreateBackup_Errors/missing_database_file (0.00s)
--- PASS: TestBackupService_CreateBackup_Errors/cannot_create_backup_directory (0.00s)
=== RUN TestBackupService_RestoreBackup_Errors
=== RUN TestBackupService_RestoreBackup_Errors/non-existent_backup
=== RUN TestBackupService_RestoreBackup_Errors/invalid_zip_file
--- PASS: TestBackupService_RestoreBackup_Errors (0.00s)
--- PASS: TestBackupService_RestoreBackup_Errors/non-existent_backup (0.00s)
--- PASS: TestBackupService_RestoreBackup_Errors/invalid_zip_file (0.00s)
=== RUN TestBackupService_ListBackups_EmptyDir
--- PASS: TestBackupService_ListBackups_EmptyDir (0.00s)
=== RUN TestBackupService_ListBackups_MissingDir
--- PASS: TestBackupService_ListBackups_MissingDir (0.00s)
=== RUN TestBackupService_CleanupOldBackups
=== RUN TestBackupService_CleanupOldBackups/deletes_backups_exceeding_retention
=== RUN TestBackupService_CleanupOldBackups/keeps_all_when_under_retention
=== RUN TestBackupService_CleanupOldBackups/minimum_retention_of_1
=== RUN TestBackupService_CleanupOldBackups/empty_backup_directory
--- PASS: TestBackupService_CleanupOldBackups (0.00s)
--- PASS: TestBackupService_CleanupOldBackups/deletes_backups_exceeding_retention (0.00s)
--- PASS: TestBackupService_CleanupOldBackups/keeps_all_when_under_retention (0.00s)
--- PASS: TestBackupService_CleanupOldBackups/minimum_retention_of_1 (0.00s)
--- PASS: TestBackupService_CleanupOldBackups/empty_backup_directory (0.00s)
=== RUN TestBackupService_GetLastBackupTime
=== RUN TestBackupService_GetLastBackupTime/returns_latest_backup_time
time="2026-01-10T02:17:52Z" level=warning msg="Warning: could not backup caddy dir" error="lstat /tmp/TestBackupService_GetLastBackupTimereturns_latest_backup_time1266614275/001/data/caddy: no such file or directory"
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
=== RUN TestBackupService_GetLastBackupTime/returns_zero_time_when_no_backups
--- PASS: TestBackupService_GetLastBackupTime (0.00s)
--- PASS: TestBackupService_GetLastBackupTime/returns_latest_backup_time (0.00s)
--- PASS: TestBackupService_GetLastBackupTime/returns_zero_time_when_no_backups (0.00s)
=== RUN TestDefaultBackupRetention
--- PASS: TestDefaultBackupRetention (0.00s)
=== RUN TestNewBackupService_BackupDirCreationError
time="2026-01-10T02:17:52Z" level=error msg="Failed to create backup directory" error="mkdir /tmp/TestNewBackupService_BackupDirCreationError2121673763/001/data/backups: not a directory"
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestNewBackupService_BackupDirCreationError (0.00s)
=== RUN TestNewBackupService_CronScheduleError
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestNewBackupService_CronScheduleError (0.00s)
=== RUN TestRunScheduledBackup_CreateBackupFails
time="2026-01-10T02:17:52Z" level=info msg="Starting scheduled backup"
time="2026-01-10T02:17:52Z" level=error msg="Scheduled backup failed" error="database file not found: /tmp/TestRunScheduledBackup_CreateBackupFails1566695776/001/data/charon.db"
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestRunScheduledBackup_CreateBackupFails (0.00s)
=== RUN TestRunScheduledBackup_CleanupFails
time="2026-01-10T02:17:52Z" level=warning msg="Warning: could not backup caddy dir" error="lstat /tmp/TestRunScheduledBackup_CleanupFails1518931621/001/data/caddy: no such file or directory"
time="2026-01-10T02:17:52Z" level=info msg="Starting scheduled backup"
time="2026-01-10T02:17:52Z" level=warning msg="Warning: could not backup caddy dir" error="lstat /tmp/TestRunScheduledBackup_CleanupFails1518931621/001/data/caddy: no such file or directory"
time="2026-01-10T02:17:52Z" level=info msg="Scheduled backup created" backup=backup_2026-01-10_02-17-52.zip
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestRunScheduledBackup_CleanupFails (0.01s)
=== RUN TestGetLastBackupTime_ListBackupsError
--- PASS: TestGetLastBackupTime_ListBackupsError (0.00s)
=== RUN TestRunScheduledBackup_CleanupDeletesZero
time="2026-01-10T02:17:52Z" level=info msg="Starting scheduled backup"
time="2026-01-10T02:17:52Z" level=warning msg="Warning: could not backup caddy dir" error="lstat /tmp/TestRunScheduledBackup_CleanupDeletesZero3348750762/001/data/caddy: no such file or directory"
time="2026-01-10T02:17:52Z" level=info msg="Scheduled backup created" backup=backup_2026-01-10_02-17-52.zip
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestRunScheduledBackup_CleanupDeletesZero (0.00s)
=== RUN TestCleanupOldBackups_PartialFailure
--- PASS: TestCleanupOldBackups_PartialFailure (0.00s)
=== RUN TestCreateBackup_CaddyDirMissing
time="2026-01-10T02:17:52Z" level=warning msg="Warning: could not backup caddy dir" error="lstat /tmp/TestCreateBackup_CaddyDirMissing2609396373/001/data/caddy: no such file or directory"
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestCreateBackup_CaddyDirMissing (0.00s)
=== RUN TestCreateBackup_CaddyDirUnreadable
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestCreateBackup_CaddyDirUnreadable (0.01s)
=== RUN TestBackupService_addToZip_FileNotFound
--- PASS: TestBackupService_addToZip_FileNotFound (0.00s)
=== RUN TestBackupService_addToZip_FileOpenError
backup_service_test.go:619: Skipping test that requires non-root user for permission testing
--- SKIP: TestBackupService_addToZip_FileOpenError (0.00s)
=== RUN TestBackupService_Start
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler started"
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestBackupService_Start (0.00s)
=== RUN TestRunScheduledBackup_CleanupSucceedsWithDeletions
time="2026-01-10T02:17:52Z" level=info msg="Starting scheduled backup"
time="2026-01-10T02:17:52Z" level=warning msg="Warning: could not backup caddy dir" error="lstat /tmp/TestRunScheduledBackup_CleanupSucceedsWithDeletions438938866/001/data/caddy: no such file or directory"
time="2026-01-10T02:17:52Z" level=info msg="Scheduled backup created" backup=backup_2026-01-10_02-17-52.zip
time="2026-01-10T02:17:52Z" level=info msg="Cleaned up old backups" deleted_count=4
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestRunScheduledBackup_CleanupSucceedsWithDeletions (0.00s)
=== RUN TestCleanupOldBackups_ListBackupsError
--- PASS: TestCleanupOldBackups_ListBackupsError (0.00s)
=== RUN TestListBackups_EntryInfoError
--- PASS: TestListBackups_EntryInfoError (0.00s)
=== RUN TestRestoreBackup_PathTraversal_FirstCheck
--- PASS: TestRestoreBackup_PathTraversal_FirstCheck (0.00s)
=== RUN TestRestoreBackup_PathTraversal_SecondCheck
--- PASS: TestRestoreBackup_PathTraversal_SecondCheck (0.00s)
=== RUN TestDeleteBackup_PathTraversal_SecondCheck
--- PASS: TestDeleteBackup_PathTraversal_SecondCheck (0.00s)
=== RUN TestGetBackupPath_PathTraversal_SecondCheck
--- PASS: TestGetBackupPath_PathTraversal_SecondCheck (0.00s)
=== RUN TestUnzip_DirectoryCreation
--- PASS: TestUnzip_DirectoryCreation (0.00s)
=== RUN TestUnzip_OpenFileError
backup_service_test.go:847: Skipping test that requires non-root user
--- SKIP: TestUnzip_OpenFileError (0.00s)
=== RUN TestUnzip_FileOpenInZipError
--- PASS: TestUnzip_FileOpenInZipError (0.00s)
=== RUN TestAddDirToZip_WalkError
--- PASS: TestAddDirToZip_WalkError (0.00s)
=== RUN TestAddDirToZip_SkipsDirectories
--- PASS: TestAddDirToZip_SkipsDirectories (0.00s)
=== RUN TestGetAvailableSpace_Success
--- PASS: TestGetAvailableSpace_Success (0.00s)
=== RUN TestGetAvailableSpace_NonExistentDir
--- PASS: TestGetAvailableSpace_NonExistentDir (0.00s)
=== RUN TestUnzip_CopyError
backup_service_test.go:991: Skipping test that requires non-root user
--- SKIP: TestUnzip_CopyError (0.00s)
=== RUN TestCreateBackup_ZipWriterCloseError
time="2026-01-10T02:17:52Z" level=warning msg="Warning: could not backup caddy dir" error="lstat /tmp/TestCreateBackup_ZipWriterCloseError1638110052/001/data/caddy: no such file or directory"
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestCreateBackup_ZipWriterCloseError (0.00s)
=== RUN TestAddToZip_CreateError
--- PASS: TestAddToZip_CreateError (0.00s)
=== RUN TestListBackups_IgnoresNonZipFiles
--- PASS: TestListBackups_IgnoresNonZipFiles (0.00s)
=== RUN TestRestoreBackup_CreatesNestedDirectories
--- PASS: TestRestoreBackup_CreatesNestedDirectories (0.00s)
=== RUN TestBackupService_FullCycle
time="2026-01-10T02:17:52Z" level=info msg="Backup service cron scheduler stopped"
--- PASS: TestBackupService_FullCycle (0.00s)
=== RUN TestNewCertificateService
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestNewCertificateService3827131621/001/certificates
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestNewCertificateService (0.12s)
=== RUN TestCertificateService_GetCertificateInfo
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/cert-test2326179515/certificates
2026/01/10 02:17:52 /projects/Charon/backend/internal/services/certificate_service.go:123 record not found
[0.183ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE domains = "example.com" ORDER BY `ssl_certificates`.`id` LIMIT 1
2026/01/10 02:17:52 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[5.836ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: disk sync complete" count=1
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/cert-test2326179515/certificates
2026/01/10 02:17:52 /projects/Charon/backend/internal/services/certificate_service.go:123 record not found
[0.086ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE domains = "expired.com" ORDER BY `ssl_certificates`.`id` LIMIT 1
2026/01/10 02:17:52 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[0.045ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: disk sync complete" count=2
--- PASS: TestCertificateService_GetCertificateInfo (0.22s)
=== RUN TestCertificateService_UploadAndDelete
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_UploadAndDelete2793602283/001/certificates
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/tmp/TestCertificateService_UploadAndDelete2793602283/001/certificates
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: disk sync complete" count=1
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_UploadAndDelete2793602283/001/certificates
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/tmp/TestCertificateService_UploadAndDelete2793602283/001/certificates
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestCertificateService_UploadAndDelete (0.13s)
=== RUN TestCertificateService_Persistence
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_Persistence2684953317/001/certificates
2026/01/10 02:17:52 /projects/Charon/backend/internal/services/certificate_service.go:123 record not found
[0.182ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE domains = "persist.example.com" ORDER BY `ssl_certificates`.`id` LIMIT 1
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: disk sync complete" count=1
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: deleting ACME cert file" path=/tmp/TestCertificateService_Persistence2684953317/001/certificates/acme-v02.api.letsencrypt.org-directory/persist.example.com/persist.example.com.crt
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_Persistence2684953317/001/certificates
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: disk sync complete" count=0
2026/01/10 02:17:52 /projects/Charon/backend/internal/services/certificate_service_test.go:289 record not found
[0.101ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE (domains = "persist.example.com" AND provider = "letsencrypt") AND `ssl_certificates`.`id` = 1 ORDER BY `ssl_certificates`.`id` LIMIT 1
--- PASS: TestCertificateService_Persistence (0.11s)
=== RUN TestCertificateService_UploadCertificate_Errors
=== RUN TestCertificateService_UploadCertificate_Errors/invalid_PEM_format
=== RUN TestCertificateService_UploadCertificate_Errors/empty_certificate
=== RUN TestCertificateService_UploadCertificate_Errors/certificate_without_key_allowed
=== RUN TestCertificateService_UploadCertificate_Errors/valid_certificate_with_name
=== RUN TestCertificateService_UploadCertificate_Errors/expired_certificate_can_be_uploaded
--- PASS: TestCertificateService_UploadCertificate_Errors (0.28s)
--- PASS: TestCertificateService_UploadCertificate_Errors/invalid_PEM_format (0.00s)
--- PASS: TestCertificateService_UploadCertificate_Errors/empty_certificate (0.00s)
--- PASS: TestCertificateService_UploadCertificate_Errors/certificate_without_key_allowed (0.03s)
--- PASS: TestCertificateService_UploadCertificate_Errors/valid_certificate_with_name (0.10s)
--- PASS: TestCertificateService_UploadCertificate_Errors/expired_certificate_can_be_uploaded (0.13s)
=== RUN TestCertificateService_ListCertificates_EdgeCases
=== RUN TestCertificateService_ListCertificates_EdgeCases/empty_certificates_directory
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_ListCertificates_EdgeCasesempty_certific1470065107/001/certificates
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/tmp/TestCertificateService_ListCertificates_EdgeCasesempty_certific1470065107/001/certificates
2026/01/10 02:17:52 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[4.390ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: disk sync complete" count=0
=== RUN TestCertificateService_ListCertificates_EdgeCases/certificates_directory_does_not_exist
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_ListCertificates_EdgeCasescertificates_d2286856882/001/does-not-exist/certificates
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/tmp/TestCertificateService_ListCertificates_EdgeCasescertificates_d2286856882/001/does-not-exist/certificates
2026/01/10 02:17:52 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[5.546ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: disk sync complete" count=0
=== RUN TestCertificateService_ListCertificates_EdgeCases/invalid_certificate_files_are_skipped
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_ListCertificates_EdgeCasesinvalid_certif3126530968/001/certificates
2026/01/10 02:17:52 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[5.902ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:52Z" level=info msg="CertificateService: disk sync complete" count=0
=== RUN TestCertificateService_ListCertificates_EdgeCases/multiple_certificates_from_different_providers
time="2026-01-10T02:17:53Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_ListCertificates_EdgeCasesmultiple_certi1140893787/001/certificates
2026/01/10 02:17:53 /projects/Charon/backend/internal/services/certificate_service.go:123 record not found
[0.147ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE domains = "le.example.com" ORDER BY `ssl_certificates`.`id` LIMIT 1
2026/01/10 02:17:53 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[5.423ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:53Z" level=info msg="CertificateService: disk sync complete" count=2
--- PASS: TestCertificateService_ListCertificates_EdgeCases (0.24s)
--- PASS: TestCertificateService_ListCertificates_EdgeCases/empty_certificates_directory (0.01s)
--- PASS: TestCertificateService_ListCertificates_EdgeCases/certificates_directory_does_not_exist (0.01s)
--- PASS: TestCertificateService_ListCertificates_EdgeCases/invalid_certificate_files_are_skipped (0.01s)
--- PASS: TestCertificateService_ListCertificates_EdgeCases/multiple_certificates_from_different_providers (0.22s)
=== RUN TestCertificateService_DeleteCertificate_Errors
=== RUN TestCertificateService_DeleteCertificate_Errors/delete_non-existent_certificate
2026/01/10 02:17:53 /projects/Charon/backend/internal/services/certificate_service.go:410 record not found
[0.098ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE `ssl_certificates`.`id` = 99999 ORDER BY `ssl_certificates`.`id` LIMIT 1
=== RUN TestCertificateService_DeleteCertificate_Errors/delete_certificate_in_use_returns_ErrCertInUse
=== RUN TestCertificateService_DeleteCertificate_Errors/delete_certificate_when_file_already_removed
2026/01/10 02:17:53 /projects/Charon/backend/internal/services/certificate_service_test.go:513 record not found
[0.091ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE id = 2 ORDER BY `ssl_certificates`.`id` LIMIT 1
--- PASS: TestCertificateService_DeleteCertificate_Errors (0.24s)
--- PASS: TestCertificateService_DeleteCertificate_Errors/delete_non-existent_certificate (0.00s)
--- PASS: TestCertificateService_DeleteCertificate_Errors/delete_certificate_in_use_returns_ErrCertInUse (0.05s)
--- PASS: TestCertificateService_DeleteCertificate_Errors/delete_certificate_when_file_already_removed (0.17s)
=== RUN TestCertificateService_StagingCertificates
=== RUN TestCertificateService_StagingCertificates/staging_certificate_detected_by_path
time="2026-01-10T02:17:53Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_StagingCertificatesstaging_certificate_d1544785683/001/certificates
2026/01/10 02:17:53 /projects/Charon/backend/internal/services/certificate_service.go:123 record not found
[0.212ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE domains = "staging.example.com" ORDER BY `ssl_certificates`.`id` LIMIT 1
2026/01/10 02:17:53 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[5.219ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:53Z" level=info msg="CertificateService: disk sync complete" count=1
=== RUN TestCertificateService_StagingCertificates/production_cert_preferred_over_staging
time="2026-01-10T02:17:53Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_StagingCertificatesproduction_cert_prefe1619917906/001/certificates
2026/01/10 02:17:53 /projects/Charon/backend/internal/services/certificate_service.go:123 record not found
[0.232ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE domains = "both.example.com" ORDER BY `ssl_certificates`.`id` LIMIT 1
2026/01/10 02:17:53 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[5.727ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:53Z" level=info msg="CertificateService: disk sync complete" count=1
=== RUN TestCertificateService_StagingCertificates/upgrade_from_staging_to_production
time="2026-01-10T02:17:53Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_StagingCertificatesupgrade_from_staging_3224756401/001/certificates
2026/01/10 02:17:53 /projects/Charon/backend/internal/services/certificate_service.go:123 record not found
[0.162ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE domains = "upgrade.example.com" ORDER BY `ssl_certificates`.`id` LIMIT 1
2026/01/10 02:17:53 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[5.372ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:53Z" level=info msg="CertificateService: disk sync complete" count=1
time="2026-01-10T02:17:53Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_StagingCertificatesupgrade_from_staging_3224756401/001/certificates
2026/01/10 02:17:53 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[0.018ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:53Z" level=info msg="CertificateService: disk sync complete" count=1
--- PASS: TestCertificateService_StagingCertificates (0.33s)
--- PASS: TestCertificateService_StagingCertificates/staging_certificate_detected_by_path (0.06s)
--- PASS: TestCertificateService_StagingCertificates/production_cert_preferred_over_staging (0.06s)
--- PASS: TestCertificateService_StagingCertificates/upgrade_from_staging_to_production (0.21s)
=== RUN TestCertificateService_ExpiringStatus
=== RUN TestCertificateService_ExpiringStatus/certificate_expiring_within_30_days
time="2026-01-10T02:17:53Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_ExpiringStatuscertificate_expiring_withi2710914074/001/certificates
2026/01/10 02:17:53 /projects/Charon/backend/internal/services/certificate_service.go:123 record not found
[0.202ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE domains = "expiring.example.com" ORDER BY `ssl_certificates`.`id` LIMIT 1
2026/01/10 02:17:53 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[4.068ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:53Z" level=info msg="CertificateService: disk sync complete" count=1
=== RUN TestCertificateService_ExpiringStatus/certificate_valid_for_more_than_30_days
time="2026-01-10T02:17:54Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_ExpiringStatuscertificate_valid_for_more2839624725/001/certificates
2026/01/10 02:17:54 /projects/Charon/backend/internal/services/certificate_service.go:123 record not found
[0.220ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE domains = "valid-long.example.com" ORDER BY `ssl_certificates`.`id` LIMIT 1
2026/01/10 02:17:54 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[6.358ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:54Z" level=info msg="CertificateService: disk sync complete" count=1
=== RUN TestCertificateService_ExpiringStatus/staging_cert_always_untrusted_even_if_expiring
time="2026-01-10T02:17:54Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_ExpiringStatusstaging_cert_always_untrus4054643254/001/certificates
2026/01/10 02:17:54 /projects/Charon/backend/internal/services/certificate_service.go:123 record not found
[0.169ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE domains = "staging-expiring.example.com" ORDER BY `ssl_certificates`.`id` LIMIT 1
2026/01/10 02:17:54 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[4.582ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:54Z" level=info msg="CertificateService: disk sync complete" count=1
--- PASS: TestCertificateService_ExpiringStatus (0.33s)
--- PASS: TestCertificateService_ExpiringStatus/certificate_expiring_within_30_days (0.03s)
--- PASS: TestCertificateService_ExpiringStatus/certificate_valid_for_more_than_30_days (0.25s)
--- PASS: TestCertificateService_ExpiringStatus/staging_cert_always_untrusted_even_if_expiring (0.05s)
=== RUN TestCertificateService_StaleCertCleanup
=== RUN TestCertificateService_StaleCertCleanup/stale_DB_entries_removed_when_file_deleted
time="2026-01-10T02:17:54Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_StaleCertCleanupstale_DB_entries_removed2164192469/001/certificates
2026/01/10 02:17:54 /projects/Charon/backend/internal/services/certificate_service.go:123 record not found
[0.158ms] [rows:0] SELECT * FROM `ssl_certificates` WHERE domains = "stale.example.com" ORDER BY `ssl_certificates`.`id` LIMIT 1
2026/01/10 02:17:54 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[5.359ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:54Z" level=info msg="CertificateService: disk sync complete" count=1
time="2026-01-10T02:17:54Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_StaleCertCleanupstale_DB_entries_removed2164192469/001/certificates
time="2026-01-10T02:17:54Z" level=info msg="CertificateService: removed stale DB cert" domain=stale.example.com
2026/01/10 02:17:54 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[0.028ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:54Z" level=info msg="CertificateService: disk sync complete" count=0
--- PASS: TestCertificateService_StaleCertCleanup (0.10s)
--- PASS: TestCertificateService_StaleCertCleanup/stale_DB_entries_removed_when_file_deleted (0.10s)
=== RUN TestCertificateService_CertificateWithSANs
=== RUN TestCertificateService_CertificateWithSANs/certificate_with_SANs_uses_joined_domains
--- PASS: TestCertificateService_CertificateWithSANs (0.05s)
--- PASS: TestCertificateService_CertificateWithSANs/certificate_with_SANs_uses_joined_domains (0.05s)
=== RUN TestCertificateService_IsCertificateInUse
=== RUN TestCertificateService_IsCertificateInUse/certificate_not_in_use
=== RUN TestCertificateService_IsCertificateInUse/certificate_used_by_one_proxy_host
=== RUN TestCertificateService_IsCertificateInUse/certificate_used_by_multiple_proxy_hosts
=== RUN TestCertificateService_IsCertificateInUse/non-existent_certificate
=== RUN TestCertificateService_IsCertificateInUse/certificate_freed_after_proxy_host_deletion
--- PASS: TestCertificateService_IsCertificateInUse (0.57s)
--- PASS: TestCertificateService_IsCertificateInUse/certificate_not_in_use (0.07s)
--- PASS: TestCertificateService_IsCertificateInUse/certificate_used_by_one_proxy_host (0.15s)
--- PASS: TestCertificateService_IsCertificateInUse/certificate_used_by_multiple_proxy_hosts (0.18s)
--- PASS: TestCertificateService_IsCertificateInUse/non-existent_certificate (0.00s)
--- PASS: TestCertificateService_IsCertificateInUse/certificate_freed_after_proxy_host_deletion (0.16s)
=== RUN TestCertificateService_CacheBehavior
=== RUN TestCertificateService_CacheBehavior/cache_returns_consistent_results
time="2026-01-10T02:17:54Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_CacheBehaviorcache_returns_consistent_re3010371691/001/certificates
time="2026-01-10T02:17:54Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/tmp/TestCertificateService_CacheBehaviorcache_returns_consistent_re3010371691/001/certificates
2026/01/10 02:17:54 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[5.504ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:54Z" level=info msg="CertificateService: disk sync complete" count=1
=== RUN TestCertificateService_CacheBehavior/invalidate_cache_forces_resync
time="2026-01-10T02:17:55Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_CacheBehaviorinvalidate_cache_forces_res1082538232/001/certificates
time="2026-01-10T02:17:55Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/tmp/TestCertificateService_CacheBehaviorinvalidate_cache_forces_res1082538232/001/certificates
2026/01/10 02:17:55 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[4.735ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:55Z" level=info msg="CertificateService: disk sync complete" count=1
time="2026-01-10T02:17:55Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_CacheBehaviorinvalidate_cache_forces_res1082538232/001/certificates
time="2026-01-10T02:17:55Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/tmp/TestCertificateService_CacheBehaviorinvalidate_cache_forces_res1082538232/001/certificates
2026/01/10 02:17:55 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[0.021ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:55Z" level=info msg="CertificateService: disk sync complete" count=2
=== RUN TestCertificateService_CacheBehavior/refreshCacheFromDB_used_when_directory_nonexistent
time="2026-01-10T02:17:55Z" level=info msg="CertificateService: scanning cert directory" certRoot=/tmp/TestCertificateService_CacheBehaviorrefreshCacheFromDB_used_whe4116796523/001/nonexistent/certificates
time="2026-01-10T02:17:55Z" level=info msg="CertificateService: cert directory does not exist" certRoot=/tmp/TestCertificateService_CacheBehaviorrefreshCacheFromDB_used_whe4116796523/001/nonexistent/certificates
2026/01/10 02:17:55 /projects/Charon/backend/internal/services/certificate_service.go:232 no such table: proxy_hosts
[4.656ms] [rows:0] SELECT * FROM `proxy_hosts`
time="2026-01-10T02:17:55Z" level=info msg="CertificateService: disk sync complete" count=1
--- PASS: TestCertificateService_CacheBehavior (0.32s)
--- PASS: TestCertificateService_CacheBehavior/cache_returns_consistent_results (0.14s)
--- PASS: TestCertificateService_CacheBehavior/invalidate_cache_forces_resync (0.18s)
--- PASS: TestCertificateService_CacheBehavior/refreshCacheFromDB_used_when_directory_nonexistent (0.01s)
=== RUN TestCoverageBoost_ErrorPaths
=== RUN TestCoverageBoost_ErrorPaths/ProxyHostService_GetByUUID_Error
=== RUN TestCoverageBoost_ErrorPaths/ProxyHostService_List_WithValidDB
=== RUN TestCoverageBoost_ErrorPaths/RemoteServerService_GetByUUID_Error
=== RUN TestCoverageBoost_ErrorPaths/RemoteServerService_List_WithValidDB
=== RUN TestCoverageBoost_ErrorPaths/SecurityService_Get_NotFound
=== RUN TestCoverageBoost_ErrorPaths/SecurityService_ListRuleSets_EmptyDB
=== RUN TestCoverageBoost_ErrorPaths/SecurityService_DeleteRuleSet_NotFound
=== RUN TestCoverageBoost_ErrorPaths/SecurityService_VerifyBreakGlass_MissingConfig
=== RUN TestCoverageBoost_ErrorPaths/SecurityService_GenerateBreakGlassToken_Success
=== RUN TestCoverageBoost_ErrorPaths/NotificationService_ListTemplates_EmptyDB
=== RUN TestCoverageBoost_ErrorPaths/NotificationService_GetTemplate_NotFound
--- PASS: TestCoverageBoost_ErrorPaths (0.74s)
--- PASS: TestCoverageBoost_ErrorPaths/ProxyHostService_GetByUUID_Error (0.00s)
--- PASS: TestCoverageBoost_ErrorPaths/ProxyHostService_List_WithValidDB (0.00s)
--- PASS: TestCoverageBoost_ErrorPaths/RemoteServerService_GetByUUID_Error (0.00s)
--- PASS: TestCoverageBoost_ErrorPaths/RemoteServerService_List_WithValidDB (0.00s)
--- PASS: TestCoverageBoost_ErrorPaths/SecurityService_Get_NotFound (0.00s)
--- PASS: TestCoverageBoost_ErrorPaths/SecurityService_ListRuleSets_EmptyDB (0.00s)
--- PASS: TestCoverageBoost_ErrorPaths/SecurityService_DeleteRuleSet_NotFound (0.00s)
--- PASS: TestCoverageBoost_ErrorPaths/SecurityService_VerifyBreakGlass_MissingConfig (0.00s)
--- PASS: TestCoverageBoost_ErrorPaths/SecurityService_GenerateBreakGlassToken_Success (0.72s)
--- PASS: TestCoverageBoost_ErrorPaths/NotificationService_ListTemplates_EmptyDB (0.00s)
--- PASS: TestCoverageBoost_ErrorPaths/NotificationService_GetTemplate_NotFound (0.00s)
=== RUN TestCoverageBoost_SecurityService_AdditionalPaths
=== RUN TestCoverageBoost_SecurityService_AdditionalPaths/Upsert_Create
=== RUN TestCoverageBoost_SecurityService_AdditionalPaths/UpsertRuleSet_Create
--- PASS: TestCoverageBoost_SecurityService_AdditionalPaths (0.01s)
--- PASS: TestCoverageBoost_SecurityService_AdditionalPaths/Upsert_Create (0.00s)
--- PASS: TestCoverageBoost_SecurityService_AdditionalPaths/UpsertRuleSet_Create (0.00s)
=== RUN TestCoverageBoost_MinInt
=== RUN TestCoverageBoost_MinInt/minInt_FirstSmaller
=== RUN TestCoverageBoost_MinInt/minInt_SecondSmaller
=== RUN TestCoverageBoost_MinInt/minInt_Equal
--- PASS: TestCoverageBoost_MinInt (0.00s)
--- PASS: TestCoverageBoost_MinInt/minInt_FirstSmaller (0.00s)
--- PASS: TestCoverageBoost_MinInt/minInt_SecondSmaller (0.00s)
--- PASS: TestCoverageBoost_MinInt/minInt_Equal (0.00s)
=== RUN TestCoverageBoost_MailService_ErrorPaths
=== RUN TestCoverageBoost_MailService_ErrorPaths/GetSMTPConfig_EmptyDB
=== RUN TestCoverageBoost_MailService_ErrorPaths/IsConfigured_NoConfig
=== RUN TestCoverageBoost_MailService_ErrorPaths/TestConnection_NoConfig
=== RUN TestCoverageBoost_MailService_ErrorPaths/SendEmail_NoConfig
--- PASS: TestCoverageBoost_MailService_ErrorPaths (0.00s)
--- PASS: TestCoverageBoost_MailService_ErrorPaths/GetSMTPConfig_EmptyDB (0.00s)
--- PASS: TestCoverageBoost_MailService_ErrorPaths/IsConfigured_NoConfig (0.00s)
--- PASS: TestCoverageBoost_MailService_ErrorPaths/TestConnection_NoConfig (0.00s)
--- PASS: TestCoverageBoost_MailService_ErrorPaths/SendEmail_NoConfig (0.00s)
=== RUN TestCoverageBoost_AccessListService_Paths
=== RUN TestCoverageBoost_AccessListService_Paths/GetByID_NotFound
=== RUN TestCoverageBoost_AccessListService_Paths/GetByUUID_NotFound
=== RUN TestCoverageBoost_AccessListService_Paths/List_EmptyDB
--- PASS: TestCoverageBoost_AccessListService_Paths (0.00s)
--- PASS: TestCoverageBoost_AccessListService_Paths/GetByID_NotFound (0.00s)
--- PASS: TestCoverageBoost_AccessListService_Paths/GetByUUID_NotFound (0.00s)
--- PASS: TestCoverageBoost_AccessListService_Paths/List_EmptyDB (0.00s)
=== RUN TestCoverageBoost_HelperFunctions
=== RUN TestCoverageBoost_HelperFunctions/extractPort_HTTP
=== RUN TestCoverageBoost_HelperFunctions/extractPort_HTTPS
=== RUN TestCoverageBoost_HelperFunctions/extractPort_Invalid
=== RUN TestCoverageBoost_HelperFunctions/hasHeader_Found
=== RUN TestCoverageBoost_HelperFunctions/hasHeader_NotFound
=== RUN TestCoverageBoost_HelperFunctions/hasHeader_EmptyMap
=== RUN TestCoverageBoost_HelperFunctions/isPrivateIP_PrivateRanges
=== RUN TestCoverageBoost_HelperFunctions/isPrivateIP_PublicIP
--- PASS: TestCoverageBoost_HelperFunctions (0.00s)
--- PASS: TestCoverageBoost_HelperFunctions/extractPort_HTTP (0.00s)
--- PASS: TestCoverageBoost_HelperFunctions/extractPort_HTTPS (0.00s)
--- PASS: TestCoverageBoost_HelperFunctions/extractPort_Invalid (0.00s)
--- PASS: TestCoverageBoost_HelperFunctions/hasHeader_Found (0.00s)
--- PASS: TestCoverageBoost_HelperFunctions/hasHeader_NotFound (0.00s)
--- PASS: TestCoverageBoost_HelperFunctions/hasHeader_EmptyMap (0.00s)
--- PASS: TestCoverageBoost_HelperFunctions/isPrivateIP_PrivateRanges (0.00s)
--- PASS: TestCoverageBoost_HelperFunctions/isPrivateIP_PublicIP (0.00s)
=== RUN TestCoverageBoost_ProxyHostService_DB
=== RUN TestCoverageBoost_ProxyHostService_DB/DB_ReturnsValidDB
--- PASS: TestCoverageBoost_ProxyHostService_DB (0.00s)
--- PASS: TestCoverageBoost_ProxyHostService_DB/DB_ReturnsValidDB (0.00s)
=== RUN TestCoverageBoost_DNSProviderService_SupportedTypes
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
=== RUN TestCoverageBoost_DNSProviderService_SupportedTypes/GetSupportedProviderTypes
=== RUN TestCoverageBoost_DNSProviderService_SupportedTypes/GetProviderCredentialFields_ValidProvider
=== RUN TestCoverageBoost_DNSProviderService_SupportedTypes/GetProviderCredentialFields_InvalidProvider
--- PASS: TestCoverageBoost_DNSProviderService_SupportedTypes (0.00s)
--- PASS: TestCoverageBoost_DNSProviderService_SupportedTypes/GetSupportedProviderTypes (0.00s)
--- PASS: TestCoverageBoost_DNSProviderService_SupportedTypes/GetProviderCredentialFields_ValidProvider (0.00s)
--- PASS: TestCoverageBoost_DNSProviderService_SupportedTypes/GetProviderCredentialFields_InvalidProvider (0.00s)
=== RUN TestCoverageBoost_SecurityService_Close
=== RUN TestCoverageBoost_SecurityService_Close/Close_Success
=== RUN TestCoverageBoost_SecurityService_Close/Flush_Success
--- PASS: TestCoverageBoost_SecurityService_Close (0.01s)
--- PASS: TestCoverageBoost_SecurityService_Close/Close_Success (0.00s)
--- PASS: TestCoverageBoost_SecurityService_Close/Flush_Success (0.01s)
=== RUN TestCoverageBoost_BackupService_GetAvailableSpace
coverage_boost_test.go:387: BackupService requires full config.Config, tested elsewhere
--- SKIP: TestCoverageBoost_BackupService_GetAvailableSpace (0.00s)
=== RUN TestCoverageBoost_CertificateService_ListCertificates
coverage_boost_test.go:393: Certificate models tested in certificate_service_test.go
--- SKIP: TestCoverageBoost_CertificateService_ListCertificates (0.00s)
=== RUN TestCoverageBoost_MailService_SendSSL
=== RUN TestCoverageBoost_MailService_SendSSL/SendEmail_SSL_InvalidHost
=== RUN TestCoverageBoost_MailService_SendSSL/SendEmail_STARTTLS_InvalidHost
--- PASS: TestCoverageBoost_MailService_SendSSL (0.01s)
--- PASS: TestCoverageBoost_MailService_SendSSL/SendEmail_SSL_InvalidHost (0.01s)
--- PASS: TestCoverageBoost_MailService_SendSSL/SendEmail_STARTTLS_InvalidHost (0.00s)
=== RUN TestCoverageBoost_CredentialService_ErrorPaths
coverage_boost_test.go:456: CredentialService requires crypto.EncryptionService, tested elsewhere
--- SKIP: TestCoverageBoost_CredentialService_ErrorPaths (0.00s)
=== RUN TestCoverageBoost_GeoIPService_ErrorPaths
=== RUN TestCoverageBoost_GeoIPService_ErrorPaths/NewGeoIPService_InvalidPath
--- PASS: TestCoverageBoost_GeoIPService_ErrorPaths (0.00s)
--- PASS: TestCoverageBoost_GeoIPService_ErrorPaths/NewGeoIPService_InvalidPath (0.00s)
=== RUN TestCoverageBoost_DockerService_ErrorPaths
coverage_boost_test.go:470: Docker service tests require specific setup, tested in docker_service_test.go
--- SKIP: TestCoverageBoost_DockerService_ErrorPaths (0.00s)
=== RUN TestCoverageBoost_UptimeService_FlushNotifications
=== RUN TestCoverageBoost_UptimeService_FlushNotifications/FlushPendingNotifications
--- PASS: TestCoverageBoost_UptimeService_FlushNotifications (0.02s)
--- PASS: TestCoverageBoost_UptimeService_FlushNotifications/FlushPendingNotifications (0.00s)
=== RUN TestCoverageBoost_LogService_NewLogService
coverage_boost_test.go:493: LogService requires full config, tested in log_service_test.go
--- SKIP: TestCoverageBoost_LogService_NewLogService (0.00s)
=== RUN TestCoverageBoost_UpdateService_ClearCache
=== RUN TestCoverageBoost_UpdateService_ClearCache/ClearCache
=== RUN TestCoverageBoost_UpdateService_ClearCache/SetCurrentVersion
--- PASS: TestCoverageBoost_UpdateService_ClearCache (0.00s)
--- PASS: TestCoverageBoost_UpdateService_ClearCache/ClearCache (0.00s)
--- PASS: TestCoverageBoost_UpdateService_ClearCache/SetCurrentVersion (0.00s)
=== RUN TestCoverageBoost_NotificationService_Providers
=== RUN TestCoverageBoost_NotificationService_Providers/ListProviders_EmptyDB
=== RUN TestCoverageBoost_NotificationService_Providers/CreateProvider
=== RUN TestCoverageBoost_NotificationService_Providers/UpdateProvider
=== RUN TestCoverageBoost_NotificationService_Providers/DeleteProvider
--- PASS: TestCoverageBoost_NotificationService_Providers (0.01s)
--- PASS: TestCoverageBoost_NotificationService_Providers/ListProviders_EmptyDB (0.00s)
--- PASS: TestCoverageBoost_NotificationService_Providers/CreateProvider (0.00s)
--- PASS: TestCoverageBoost_NotificationService_Providers/UpdateProvider (0.00s)
--- PASS: TestCoverageBoost_NotificationService_Providers/DeleteProvider (0.00s)
=== RUN TestCoverageBoost_NotificationService_CRUD
=== RUN TestCoverageBoost_NotificationService_CRUD/List_EmptyDB
=== RUN TestCoverageBoost_NotificationService_CRUD/MarkAllAsRead_Success
--- PASS: TestCoverageBoost_NotificationService_CRUD (0.00s)
--- PASS: TestCoverageBoost_NotificationService_CRUD/List_EmptyDB (0.00s)
--- PASS: TestCoverageBoost_NotificationService_CRUD/MarkAllAsRead_Success (0.00s)
=== RUN TestReconcileCrowdSecOnStartup_NilDB
time="2026-01-10T02:17:55Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=crowdsec data_dir=/tmp/crowdsec
--- PASS: TestReconcileCrowdSecOnStartup_NilDB (0.00s)
=== RUN TestReconcileCrowdSecOnStartup_NilExecutor
time="2026-01-10T02:17:55Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=crowdsec data_dir=/tmp/crowdsec
--- PASS: TestReconcileCrowdSecOnStartup_NilExecutor (0.00s)
=== RUN TestReconcileCrowdSecOnStartup_NoSecurityConfig_NoSettings
time="2026-01-10T02:17:55Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-3422589158/crowdsec data_dir=/tmp/crowdsec-test-3422589158/data
time="2026-01-10T02:17:55Z" level=info msg="CrowdSec reconciliation: no SecurityConfig found, checking Settings table for user preference"
time="2026-01-10T02:17:55Z" level=info msg="CrowdSec reconciliation: default SecurityConfig created from Settings preference" crowdsec_mode=disabled enabled=false source=settings_table
time="2026-01-10T02:17:55Z" level=info msg="CrowdSec reconciliation skipped: both SecurityConfig and Settings indicate disabled" db_mode=disabled setting_enabled=false
--- PASS: TestReconcileCrowdSecOnStartup_NoSecurityConfig_NoSettings (0.01s)
=== RUN TestReconcileCrowdSecOnStartup_NoSecurityConfig_SettingsEnabled
time="2026-01-10T02:17:55Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-1248194343/crowdsec data_dir=/tmp/crowdsec-test-1248194343/data
time="2026-01-10T02:17:55Z" level=info msg="CrowdSec reconciliation: no SecurityConfig found, checking Settings table for user preference"
time="2026-01-10T02:17:55Z" level=info msg="CrowdSec reconciliation: found existing Settings table preference" enabled=true setting_value=true
time="2026-01-10T02:17:55Z" level=info msg="CrowdSec reconciliation: default SecurityConfig created from Settings preference" crowdsec_mode=local enabled=true source=settings_table
time="2026-01-10T02:17:55Z" level=info msg="CrowdSec reconciliation: starting based on SecurityConfig mode='local'" mode=local
time="2026-01-10T02:17:55Z" level=info msg="CrowdSec reconciliation: starting CrowdSec (mode=local, not currently running)" bin_path=/tmp/crowdsec-test-1248194343/crowdsec data_dir=/tmp/crowdsec-test-1248194343/data
time="2026-01-10T02:17:57Z" level=info msg="CrowdSec reconciliation: successfully started and verified CrowdSec" pid=12345 verified=true
--- PASS: TestReconcileCrowdSecOnStartup_NoSecurityConfig_SettingsEnabled (2.01s)
=== RUN TestReconcileCrowdSecOnStartup_NoSecurityConfig_SettingsDisabled
time="2026-01-10T02:17:57Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-552327634/crowdsec data_dir=/tmp/crowdsec-test-552327634/data
time="2026-01-10T02:17:57Z" level=info msg="CrowdSec reconciliation: no SecurityConfig found, checking Settings table for user preference"
time="2026-01-10T02:17:57Z" level=info msg="CrowdSec reconciliation: found existing Settings table preference" enabled=false setting_value=false
time="2026-01-10T02:17:57Z" level=info msg="CrowdSec reconciliation: default SecurityConfig created from Settings preference" crowdsec_mode=disabled enabled=false source=settings_table
time="2026-01-10T02:17:57Z" level=info msg="CrowdSec reconciliation skipped: both SecurityConfig and Settings indicate disabled" db_mode=disabled setting_enabled=false
--- PASS: TestReconcileCrowdSecOnStartup_NoSecurityConfig_SettingsDisabled (0.01s)
=== RUN TestReconcileCrowdSecOnStartup_ModeDisabled
time="2026-01-10T02:17:57Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=crowdsec data_dir=/tmp/crowdsec
time="2026-01-10T02:17:57Z" level=info msg="CrowdSec reconciliation skipped: both SecurityConfig and Settings indicate disabled" db_mode=disabled setting_enabled=false
--- PASS: TestReconcileCrowdSecOnStartup_ModeDisabled (0.00s)
=== RUN TestReconcileCrowdSecOnStartup_ModeLocal_AlreadyRunning
time="2026-01-10T02:17:57Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-3437819381/crowdsec data_dir=/tmp/crowdsec-test-3437819381/data
time="2026-01-10T02:17:57Z" level=info msg="CrowdSec reconciliation: starting based on SecurityConfig mode='local'" mode=local
time="2026-01-10T02:17:57Z" level=info msg="CrowdSec reconciliation: already running" pid=12345
--- PASS: TestReconcileCrowdSecOnStartup_ModeLocal_AlreadyRunning (0.00s)
=== RUN TestReconcileCrowdSecOnStartup_ModeLocal_NotRunning_Starts
time="2026-01-10T02:17:58Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-3905439510/crowdsec data_dir=/tmp/crowdsec-test-3905439510/data
time="2026-01-10T02:17:58Z" level=info msg="CrowdSec reconciliation: starting based on SecurityConfig mode='local'" mode=local
time="2026-01-10T02:17:58Z" level=info msg="CrowdSec reconciliation: starting CrowdSec (mode=local, not currently running)" bin_path=/tmp/crowdsec-test-3905439510/crowdsec data_dir=/tmp/crowdsec-test-3905439510/data
time="2026-01-10T02:18:00Z" level=info msg="CrowdSec reconciliation: successfully started and verified CrowdSec" pid=99999 verified=true
--- PASS: TestReconcileCrowdSecOnStartup_ModeLocal_NotRunning_Starts (2.01s)
=== RUN TestReconcileCrowdSecOnStartup_ModeLocal_StartError
time="2026-01-10T02:18:00Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-2846461424/crowdsec data_dir=/tmp/crowdsec-test-2846461424/data
time="2026-01-10T02:18:00Z" level=info msg="CrowdSec reconciliation: starting based on SecurityConfig mode='local'" mode=local
time="2026-01-10T02:18:00Z" level=info msg="CrowdSec reconciliation: starting CrowdSec (mode=local, not currently running)" bin_path=/tmp/crowdsec-test-2846461424/crowdsec data_dir=/tmp/crowdsec-test-2846461424/data
time="2026-01-10T02:18:00Z" level=error msg="CrowdSec reconciliation: FAILED to start CrowdSec - check binary and config" bin_path=/tmp/crowdsec-test-2846461424/crowdsec data_dir=/tmp/crowdsec-test-2846461424/data error="assert.AnError general error for testing"
--- PASS: TestReconcileCrowdSecOnStartup_ModeLocal_StartError (0.01s)
=== RUN TestReconcileCrowdSecOnStartup_StatusError
time="2026-01-10T02:18:00Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-2368966688/crowdsec data_dir=/tmp/crowdsec-test-2368966688/data
time="2026-01-10T02:18:00Z" level=info msg="CrowdSec reconciliation: starting based on SecurityConfig mode='local'" mode=local
time="2026-01-10T02:18:00Z" level=warning msg="CrowdSec reconciliation: failed to check status" error="assert.AnError general error for testing"
--- PASS: TestReconcileCrowdSecOnStartup_StatusError (0.01s)
=== RUN TestReconcileCrowdSecOnStartup_BinaryNotFound
time="2026-01-10T02:18:00Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-1992083819/data/nonexistent_binary data_dir=/tmp/crowdsec-test-1992083819/data
time="2026-01-10T02:18:00Z" level=info msg="CrowdSec reconciliation: starting based on SecurityConfig mode='local'" mode=local
time="2026-01-10T02:18:00Z" level=error msg="CrowdSec reconciliation: binary not found, cannot start" path=/tmp/crowdsec-test-1992083819/data/nonexistent_binary
--- PASS: TestReconcileCrowdSecOnStartup_BinaryNotFound (0.01s)
=== RUN TestReconcileCrowdSecOnStartup_ConfigDirNotFound
time="2026-01-10T02:18:00Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-1748862425/crowdsec data_dir=/tmp/crowdsec-test-1748862425/data
time="2026-01-10T02:18:00Z" level=info msg="CrowdSec reconciliation: starting based on SecurityConfig mode='local'" mode=local
time="2026-01-10T02:18:00Z" level=error msg="CrowdSec reconciliation: config directory not found, cannot start" path=/tmp/crowdsec-test-1748862425/data/config
--- PASS: TestReconcileCrowdSecOnStartup_ConfigDirNotFound (0.01s)
=== RUN TestReconcileCrowdSecOnStartup_SettingsOverrideEnabled
time="2026-01-10T02:18:00Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-3010292195/crowdsec data_dir=/tmp/crowdsec-test-3010292195/data
time="2026-01-10T02:18:00Z" level=info msg="CrowdSec reconciliation: starting based on Settings table override" setting=true
time="2026-01-10T02:18:00Z" level=info msg="CrowdSec reconciliation: starting CrowdSec (mode=local, not currently running)" bin_path=/tmp/crowdsec-test-3010292195/crowdsec data_dir=/tmp/crowdsec-test-3010292195/data
time="2026-01-10T02:18:02Z" level=info msg="CrowdSec reconciliation: successfully started and verified CrowdSec" pid=12345 verified=true
--- PASS: TestReconcileCrowdSecOnStartup_SettingsOverrideEnabled (2.01s)
=== RUN TestReconcileCrowdSecOnStartup_VerificationFails
time="2026-01-10T02:18:02Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-903539656/crowdsec data_dir=/tmp/crowdsec-test-903539656/data
time="2026-01-10T02:18:02Z" level=info msg="CrowdSec reconciliation: starting based on SecurityConfig mode='local'" mode=local
time="2026-01-10T02:18:02Z" level=info msg="CrowdSec reconciliation: starting CrowdSec (mode=local, not currently running)" bin_path=/tmp/crowdsec-test-903539656/crowdsec data_dir=/tmp/crowdsec-test-903539656/data
time="2026-01-10T02:18:04Z" level=error msg="CrowdSec reconciliation: process started but is no longer running - may have crashed" actual_pid=0 expected_pid=12345 running=false
--- PASS: TestReconcileCrowdSecOnStartup_VerificationFails (2.01s)
=== RUN TestReconcileCrowdSecOnStartup_VerificationError
time="2026-01-10T02:18:04Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-265968278/crowdsec data_dir=/tmp/crowdsec-test-265968278/data
time="2026-01-10T02:18:04Z" level=info msg="CrowdSec reconciliation: starting based on SecurityConfig mode='local'" mode=local
time="2026-01-10T02:18:04Z" level=info msg="CrowdSec reconciliation: starting CrowdSec (mode=local, not currently running)" bin_path=/tmp/crowdsec-test-265968278/crowdsec data_dir=/tmp/crowdsec-test-265968278/data
time="2026-01-10T02:18:06Z" level=warning msg="CrowdSec reconciliation: started but failed to verify status" error="assert.AnError general error for testing" expected_pid=12345
--- PASS: TestReconcileCrowdSecOnStartup_VerificationError (2.01s)
=== RUN TestReconcileCrowdSecOnStartup_DBError
time="2026-01-10T02:18:06Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-3340642405/crowdsec data_dir=/tmp/crowdsec-test-3340642405/data
time="2026-01-10T02:18:06Z" level=warning msg="CrowdSec reconciliation skipped: SecurityConfig table not found - run 'charon migrate' to fix"
--- PASS: TestReconcileCrowdSecOnStartup_DBError (0.00s)
=== RUN TestReconcileCrowdSecOnStartup_CreateConfigDBError
time="2026-01-10T02:18:06Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-3639284342/crowdsec data_dir=/tmp/crowdsec-test-3639284342/data
time="2026-01-10T02:18:06Z" level=warning msg="CrowdSec reconciliation skipped: SecurityConfig table not found - run 'charon migrate' to fix"
--- PASS: TestReconcileCrowdSecOnStartup_CreateConfigDBError (0.00s)
=== RUN TestReconcileCrowdSecOnStartup_SettingsTableQueryError
time="2026-01-10T02:18:06Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-3773669688/crowdsec data_dir=/tmp/crowdsec-test-3773669688/data
time="2026-01-10T02:18:06Z" level=info msg="CrowdSec reconciliation skipped: both SecurityConfig and Settings indicate disabled" db_mode=remote setting_enabled=false
--- PASS: TestReconcileCrowdSecOnStartup_SettingsTableQueryError (0.00s)
=== RUN TestReconcileCrowdSecOnStartup_SettingsOverrideNonLocalMode
time="2026-01-10T02:18:06Z" level=info msg="CrowdSec reconciliation: starting startup check" bin_path=/tmp/crowdsec-test-1355592154/crowdsec data_dir=/tmp/crowdsec-test-1355592154/data
time="2026-01-10T02:18:06Z" level=info msg="CrowdSec reconciliation: starting based on Settings table override" setting=true
time="2026-01-10T02:18:06Z" level=info msg="CrowdSec reconciliation: starting CrowdSec (mode=local, not currently running)" bin_path=/tmp/crowdsec-test-1355592154/crowdsec data_dir=/tmp/crowdsec-test-1355592154/data
time="2026-01-10T02:18:08Z" level=info msg="CrowdSec reconciliation: successfully started and verified CrowdSec" pid=12345 verified=true
--- PASS: TestReconcileCrowdSecOnStartup_SettingsOverrideNonLocalMode (2.01s)
=== RUN TestNewDNSDetectionService
--- PASS: TestNewDNSDetectionService (0.00s)
=== RUN TestGetNameserverPatterns
--- PASS: TestGetNameserverPatterns (0.00s)
=== RUN TestMatchNameservers
=== RUN TestMatchNameservers/Cloudflare_-_high_confidence
=== RUN TestMatchNameservers/Route53_-_high_confidence
=== RUN TestMatchNameservers/DigitalOcean_-_high_confidence
=== RUN TestMatchNameservers/Hetzner_-_high_confidence
=== RUN TestMatchNameservers/Mixed_nameservers_-_medium_confidence
=== RUN TestMatchNameservers/Single_match_-_low_confidence
=== RUN TestMatchNameservers/No_match
=== RUN TestMatchNameservers/Empty_nameservers
--- PASS: TestMatchNameservers (0.00s)
--- PASS: TestMatchNameservers/Cloudflare_-_high_confidence (0.00s)
--- PASS: TestMatchNameservers/Route53_-_high_confidence (0.00s)
--- PASS: TestMatchNameservers/DigitalOcean_-_high_confidence (0.00s)
--- PASS: TestMatchNameservers/Hetzner_-_high_confidence (0.00s)
--- PASS: TestMatchNameservers/Mixed_nameservers_-_medium_confidence (0.00s)
--- PASS: TestMatchNameservers/Single_match_-_low_confidence (0.00s)
--- PASS: TestMatchNameservers/No_match (0.00s)
--- PASS: TestMatchNameservers/Empty_nameservers (0.00s)
=== RUN TestDetectProvider_WithMockedDNS
=== RUN TestDetectProvider_WithMockedDNS/handles_wildcard_domain
=== RUN TestDetectProvider_WithMockedDNS/handles_empty_domain
=== RUN TestDetectProvider_WithMockedDNS/normalizes_domain
--- PASS: TestDetectProvider_WithMockedDNS (0.00s)
--- PASS: TestDetectProvider_WithMockedDNS/handles_wildcard_domain (0.00s)
--- PASS: TestDetectProvider_WithMockedDNS/handles_empty_domain (0.00s)
--- PASS: TestDetectProvider_WithMockedDNS/normalizes_domain (0.00s)
=== RUN TestCaching
=== RUN TestCaching/retrieves_cached_result
=== RUN TestCaching/returns_nil_for_non-existent_cache
=== RUN TestCaching/expires_old_cache_entries
--- PASS: TestCaching (0.01s)
--- PASS: TestCaching/retrieves_cached_result (0.00s)
--- PASS: TestCaching/returns_nil_for_non-existent_cache (0.00s)
--- PASS: TestCaching/expires_old_cache_entries (0.01s)
=== RUN TestSuggestConfiguredProvider
=== RUN TestSuggestConfiguredProvider/suggests_default_cloudflare_provider
=== RUN TestSuggestConfiguredProvider/suggests_route53_provider
=== RUN TestSuggestConfiguredProvider/returns_nil_for_disabled_provider
=== RUN TestSuggestConfiguredProvider/returns_nil_for_unknown_provider
--- PASS: TestSuggestConfiguredProvider (0.01s)
--- PASS: TestSuggestConfiguredProvider/suggests_default_cloudflare_provider (0.00s)
--- PASS: TestSuggestConfiguredProvider/suggests_route53_provider (0.00s)
--- PASS: TestSuggestConfiguredProvider/returns_nil_for_disabled_provider (0.00s)
--- PASS: TestSuggestConfiguredProvider/returns_nil_for_unknown_provider (0.00s)
=== RUN TestDetectionResult_Validation
=== RUN TestDetectionResult_Validation/result_with_all_fields
=== RUN TestDetectionResult_Validation/result_with_error
--- PASS: TestDetectionResult_Validation (0.00s)
--- PASS: TestDetectionResult_Validation/result_with_all_fields (0.00s)
--- PASS: TestDetectionResult_Validation/result_with_error (0.00s)
=== RUN TestBuiltInNameserversCompleteness
--- PASS: TestBuiltInNameserversCompleteness (0.00s)
=== RUN TestCaseInsensitiveMatching
=== RUN TestCaseInsensitiveMatching/lowercase
=== RUN TestCaseInsensitiveMatching/uppercase
=== RUN TestCaseInsensitiveMatching/mixed_case
--- PASS: TestCaseInsensitiveMatching (0.00s)
--- PASS: TestCaseInsensitiveMatching/lowercase (0.00s)
--- PASS: TestCaseInsensitiveMatching/uppercase (0.00s)
--- PASS: TestCaseInsensitiveMatching/mixed_case (0.00s)
=== RUN TestConcurrentCacheAccess
--- PASS: TestConcurrentCacheAccess (0.00s)
=== RUN TestDatabaseError
2026/01/10 02:18:08 /projects/Charon/backend/internal/services/dns_detection_service.go:182 sql: database is closed
[0.358ms] [rows:0] SELECT * FROM `dns_providers` WHERE provider_type = "cloudflare" AND enabled = true ORDER BY is_default DESC, name ASC
--- PASS: TestDatabaseError (0.00s)
=== RUN TestDNSProviderService_Create
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
=== RUN TestDNSProviderService_Create/valid_cloudflare_provider
=== RUN TestDNSProviderService_Create/valid_route53_provider_with_defaults
=== RUN TestDNSProviderService_Create/invalid_provider_type
=== RUN TestDNSProviderService_Create/missing_required_credentials
--- PASS: TestDNSProviderService_Create (0.01s)
--- PASS: TestDNSProviderService_Create/valid_cloudflare_provider (0.00s)
--- PASS: TestDNSProviderService_Create/valid_route53_provider_with_defaults (0.00s)
--- PASS: TestDNSProviderService_Create/invalid_provider_type (0.00s)
--- PASS: TestDNSProviderService_Create/missing_required_credentials (0.00s)
=== RUN TestDNSProviderService_DefaultProviderLogic
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_DefaultProviderLogic (0.01s)
=== RUN TestDNSProviderService_List
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_List (0.01s)
=== RUN TestDNSProviderService_Get
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Get (0.01s)
=== RUN TestDNSProviderService_Update
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
=== RUN TestDNSProviderService_Update/update_name_only
=== RUN TestDNSProviderService_Update/update_credentials
=== RUN TestDNSProviderService_Update/update_enabled_status
=== RUN TestDNSProviderService_Update/update_non-existent_provider
=== RUN TestDNSProviderService_Update/update_to_set_default
--- PASS: TestDNSProviderService_Update (0.01s)
--- PASS: TestDNSProviderService_Update/update_name_only (0.00s)
--- PASS: TestDNSProviderService_Update/update_credentials (0.00s)
--- PASS: TestDNSProviderService_Update/update_enabled_status (0.00s)
--- PASS: TestDNSProviderService_Update/update_non-existent_provider (0.00s)
--- PASS: TestDNSProviderService_Update/update_to_set_default (0.00s)
=== RUN TestDNSProviderService_Delete
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Delete (0.01s)
=== RUN TestDNSProviderService_GetDecryptedCredentials
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_GetDecryptedCredentials (0.01s)
=== RUN TestDNSProviderService_TestCredentials
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
=== RUN TestDNSProviderService_TestCredentials/valid_credentials
=== RUN TestDNSProviderService_TestCredentials/invalid_provider_type
=== RUN TestDNSProviderService_TestCredentials/missing_credentials
--- PASS: TestDNSProviderService_TestCredentials (0.00s)
--- PASS: TestDNSProviderService_TestCredentials/valid_credentials (0.00s)
--- PASS: TestDNSProviderService_TestCredentials/invalid_provider_type (0.00s)
--- PASS: TestDNSProviderService_TestCredentials/missing_credentials (0.00s)
=== RUN TestDNSProviderService_Test
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Test (0.01s)
=== RUN TestValidateCredentials
=== RUN TestValidateCredentials/valid_cloudflare
=== RUN TestValidateCredentials/valid_route53
=== RUN TestValidateCredentials/missing_field
=== RUN TestValidateCredentials/empty_field_value
=== RUN TestValidateCredentials/invalid_provider_type
--- PASS: TestValidateCredentials (0.00s)
--- PASS: TestValidateCredentials/valid_cloudflare (0.00s)
--- PASS: TestValidateCredentials/valid_route53 (0.00s)
--- PASS: TestValidateCredentials/missing_field (0.00s)
--- PASS: TestValidateCredentials/empty_field_value (0.00s)
--- PASS: TestValidateCredentials/invalid_provider_type (0.00s)
=== RUN TestIsValidProviderType
=== RUN TestIsValidProviderType/cloudflare
=== RUN TestIsValidProviderType/route53
=== RUN TestIsValidProviderType/digitalocean
=== RUN TestIsValidProviderType/invalid
=== RUN TestIsValidProviderType/empty
--- PASS: TestIsValidProviderType (0.00s)
--- PASS: TestIsValidProviderType/cloudflare (0.00s)
--- PASS: TestIsValidProviderType/route53 (0.00s)
--- PASS: TestIsValidProviderType/digitalocean (0.00s)
--- PASS: TestIsValidProviderType/invalid (0.00s)
--- PASS: TestIsValidProviderType/empty (0.00s)
=== RUN TestCredentialEncryptionRoundtrip
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialEncryptionRoundtrip (0.01s)
=== RUN TestUpdatePreservesCredentials
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestUpdatePreservesCredentials (0.01s)
=== RUN TestEncryptionServiceIntegration
--- PASS: TestEncryptionServiceIntegration (0.01s)
=== RUN TestDNSProviderService_TestFailure
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_TestFailure (0.00s)
=== RUN TestDNSProviderService_GetDecryptedCredentialsError
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_GetDecryptedCredentialsError (0.01s)
=== RUN TestDNSProviderService_GetDecryptedCredentials_InvalidJSON_ReturnsErrDecryptionFailed
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_GetDecryptedCredentials_InvalidJSON_ReturnsErrDecryptionFailed (0.00s)
=== RUN TestDNSProviderService_UpdateDefaultLogic
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_UpdateDefaultLogic (0.01s)
=== RUN TestAllProviderTypes
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
=== RUN TestAllProviderTypes/route53
=== RUN TestAllProviderTypes/digitalocean
=== RUN TestAllProviderTypes/googleclouddns
=== RUN TestAllProviderTypes/vultr
=== RUN TestAllProviderTypes/cloudflare
=== RUN TestAllProviderTypes/namecheap
=== RUN TestAllProviderTypes/godaddy
=== RUN TestAllProviderTypes/azure
=== RUN TestAllProviderTypes/hetzner
=== RUN TestAllProviderTypes/dnsimple
--- PASS: TestAllProviderTypes (0.03s)
--- PASS: TestAllProviderTypes/route53 (0.00s)
--- PASS: TestAllProviderTypes/digitalocean (0.00s)
--- PASS: TestAllProviderTypes/googleclouddns (0.00s)
--- PASS: TestAllProviderTypes/vultr (0.00s)
--- PASS: TestAllProviderTypes/cloudflare (0.00s)
--- PASS: TestAllProviderTypes/namecheap (0.00s)
--- PASS: TestAllProviderTypes/godaddy (0.00s)
--- PASS: TestAllProviderTypes/azure (0.00s)
--- PASS: TestAllProviderTypes/hetzner (0.00s)
--- PASS: TestAllProviderTypes/dnsimple (0.00s)
=== RUN TestDNSProviderService_UpdateInvalidCredentials
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_UpdateInvalidCredentials (0.01s)
=== RUN TestDNSProviderService_CreateEncryptionError
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_CreateEncryptionError (0.00s)
=== RUN TestDNSProviderService_Update_PropagationTimeoutAndPollingInterval
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
=== RUN TestDNSProviderService_Update_PropagationTimeoutAndPollingInterval/update_propagation_timeout
=== RUN TestDNSProviderService_Update_PropagationTimeoutAndPollingInterval/update_polling_interval
=== RUN TestDNSProviderService_Update_PropagationTimeoutAndPollingInterval/update_both_timeout_and_interval
--- PASS: TestDNSProviderService_Update_PropagationTimeoutAndPollingInterval (0.01s)
--- PASS: TestDNSProviderService_Update_PropagationTimeoutAndPollingInterval/update_propagation_timeout (0.00s)
--- PASS: TestDNSProviderService_Update_PropagationTimeoutAndPollingInterval/update_polling_interval (0.00s)
--- PASS: TestDNSProviderService_Update_PropagationTimeoutAndPollingInterval/update_both_timeout_and_interval (0.00s)
=== RUN TestDNSProviderService_Test_NonExistentProvider
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Test_NonExistentProvider (0.00s)
=== RUN TestDNSProviderService_GetDecryptedCredentials_NonExistentProvider
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_GetDecryptedCredentials_NonExistentProvider (0.01s)
=== RUN TestDNSProviderService_TestWithFailedCredentials
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_TestWithFailedCredentials (0.01s)
=== RUN TestDNSProviderService_CreateWithEmptyCredentialValue
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_CreateWithEmptyCredentialValue (0.01s)
=== RUN TestDNSProviderService_Update_EmptyCredentials
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Update_EmptyCredentials (0.01s)
=== RUN TestDNSProviderService_Update_NilCredentials
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Update_NilCredentials (0.00s)
=== RUN TestDNSProviderService_Create_WithExistingDefault
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Create_WithExistingDefault (0.01s)
=== RUN TestDNSProviderService_Delete_AlreadyDeleted
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Delete_AlreadyDeleted (0.01s)
=== RUN TestTestDNSProviderCredentials_Validation
=== RUN TestTestDNSProviderCredentials_Validation/valid_cloudflare_credentials
=== RUN TestTestDNSProviderCredentials_Validation/missing_required_field
=== RUN TestTestDNSProviderCredentials_Validation/empty_required_field
--- PASS: TestTestDNSProviderCredentials_Validation (0.00s)
--- PASS: TestTestDNSProviderCredentials_Validation/valid_cloudflare_credentials (0.00s)
--- PASS: TestTestDNSProviderCredentials_Validation/missing_required_field (0.00s)
--- PASS: TestTestDNSProviderCredentials_Validation/empty_required_field (0.00s)
=== RUN TestDNSProviderService_Update_CredentialValidationError
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Update_CredentialValidationError (0.01s)
=== RUN TestDNSProviderService_TestCredentials_AllProviders
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
=== RUN TestDNSProviderService_TestCredentials_AllProviders/dnsimple
=== RUN TestDNSProviderService_TestCredentials_AllProviders/route53
=== RUN TestDNSProviderService_TestCredentials_AllProviders/digitalocean
=== RUN TestDNSProviderService_TestCredentials_AllProviders/googleclouddns
=== RUN TestDNSProviderService_TestCredentials_AllProviders/azure
=== RUN TestDNSProviderService_TestCredentials_AllProviders/hetzner
=== RUN TestDNSProviderService_TestCredentials_AllProviders/vultr
=== RUN TestDNSProviderService_TestCredentials_AllProviders/cloudflare
=== RUN TestDNSProviderService_TestCredentials_AllProviders/namecheap
=== RUN TestDNSProviderService_TestCredentials_AllProviders/godaddy
--- PASS: TestDNSProviderService_TestCredentials_AllProviders (0.01s)
--- PASS: TestDNSProviderService_TestCredentials_AllProviders/dnsimple (0.00s)
--- PASS: TestDNSProviderService_TestCredentials_AllProviders/route53 (0.00s)
--- PASS: TestDNSProviderService_TestCredentials_AllProviders/digitalocean (0.00s)
--- PASS: TestDNSProviderService_TestCredentials_AllProviders/googleclouddns (0.00s)
--- PASS: TestDNSProviderService_TestCredentials_AllProviders/azure (0.00s)
--- PASS: TestDNSProviderService_TestCredentials_AllProviders/hetzner (0.00s)
--- PASS: TestDNSProviderService_TestCredentials_AllProviders/vultr (0.00s)
--- PASS: TestDNSProviderService_TestCredentials_AllProviders/cloudflare (0.00s)
--- PASS: TestDNSProviderService_TestCredentials_AllProviders/namecheap (0.00s)
--- PASS: TestDNSProviderService_TestCredentials_AllProviders/godaddy (0.00s)
=== RUN TestDNSProviderService_List_Empty
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_List_Empty (0.01s)
=== RUN TestDNSProviderService_Create_DefaultsApplied
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Create_DefaultsApplied (0.01s)
=== RUN TestDNSProviderService_Create_CustomTimeouts
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Create_CustomTimeouts (0.00s)
=== RUN TestDNSProviderService_List_OrderByDefault
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_List_OrderByDefault (0.01s)
=== RUN TestDNSProviderService_Update_MultipleFields
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Update_MultipleFields (0.01s)
=== RUN TestDNSProviderService_GetDecryptedCredentials_UpdatesLastUsed
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_GetDecryptedCredentials_UpdatesLastUsed (0.01s)
=== RUN TestDNSProviderService_Test_UpdatesStatistics
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Test_UpdatesStatistics (0.01s)
=== RUN TestDNSProviderService_Test_FailureUpdatesStatistics
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Test_FailureUpdatesStatistics (0.01s)
=== RUN TestDNSProviderService_List_DBError
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_List_DBError (0.00s)
=== RUN TestDNSProviderService_Get_DBError
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Get_DBError (0.00s)
=== RUN TestDNSProviderService_Create_DBErrorOnDefaultUnset
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Create_DBErrorOnDefaultUnset (0.01s)
=== RUN TestDNSProviderService_Create_DBErrorOnCreate
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Create_DBErrorOnCreate (0.00s)
=== RUN TestDNSProviderService_Update_DBErrorOnSave
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Update_DBErrorOnSave (0.01s)
=== RUN TestDNSProviderService_Update_DBErrorOnDefaultUnset
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Update_DBErrorOnDefaultUnset (0.01s)
=== RUN TestDNSProviderService_Delete_DBError
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_Delete_DBError (0.01s)
=== RUN TestDNSProviderService_AuditLogging_Create
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_AuditLogging_Create (0.11s)
=== RUN TestDNSProviderService_AuditLogging_Update
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_AuditLogging_Update (0.31s)
=== RUN TestDNSProviderService_AuditLogging_Delete
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_AuditLogging_Delete (0.31s)
=== RUN TestDNSProviderService_AuditLogging_Test
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_AuditLogging_Test (0.31s)
=== RUN TestDNSProviderService_AuditLogging_GetDecryptedCredentials
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestDNSProviderService_AuditLogging_GetDecryptedCredentials (0.31s)
=== RUN TestDNSProviderService_AuditLogging_ContextHelpers
--- PASS: TestDNSProviderService_AuditLogging_ContextHelpers (0.00s)
=== RUN TestDockerService_New
--- PASS: TestDockerService_New (0.00s)
=== RUN TestDockerService_ListContainers
--- PASS: TestDockerService_ListContainers (0.01s)
=== RUN TestDockerUnavailableError_ErrorMethods
--- PASS: TestDockerUnavailableError_ErrorMethods (0.00s)
=== RUN TestIsDockerConnectivityError
=== RUN TestIsDockerConnectivityError/nil_error
=== RUN TestIsDockerConnectivityError/daemon_not_running
=== RUN TestIsDockerConnectivityError/daemon_running_check
=== RUN TestIsDockerConnectivityError/error_during_connect
=== RUN TestIsDockerConnectivityError/connection_refused
=== RUN TestIsDockerConnectivityError/no_such_file
=== RUN TestIsDockerConnectivityError/context_timeout
=== RUN TestIsDockerConnectivityError/permission_denied_-_EACCES
=== RUN TestIsDockerConnectivityError/permission_denied_-_EPERM
=== RUN TestIsDockerConnectivityError/no_entry_-_ENOENT
=== RUN TestIsDockerConnectivityError/random_error
=== RUN TestIsDockerConnectivityError/empty_error
--- PASS: TestIsDockerConnectivityError (0.00s)
--- PASS: TestIsDockerConnectivityError/nil_error (0.00s)
--- PASS: TestIsDockerConnectivityError/daemon_not_running (0.00s)
--- PASS: TestIsDockerConnectivityError/daemon_running_check (0.00s)
--- PASS: TestIsDockerConnectivityError/error_during_connect (0.00s)
--- PASS: TestIsDockerConnectivityError/connection_refused (0.00s)
--- PASS: TestIsDockerConnectivityError/no_such_file (0.00s)
--- PASS: TestIsDockerConnectivityError/context_timeout (0.00s)
--- PASS: TestIsDockerConnectivityError/permission_denied_-_EACCES (0.00s)
--- PASS: TestIsDockerConnectivityError/permission_denied_-_EPERM (0.00s)
--- PASS: TestIsDockerConnectivityError/no_entry_-_ENOENT (0.00s)
--- PASS: TestIsDockerConnectivityError/random_error (0.00s)
--- PASS: TestIsDockerConnectivityError/empty_error (0.00s)
=== RUN TestIsDockerConnectivityError_URLError
--- PASS: TestIsDockerConnectivityError_URLError (0.00s)
=== RUN TestIsDockerConnectivityError_OpError
--- PASS: TestIsDockerConnectivityError_OpError (0.00s)
=== RUN TestIsDockerConnectivityError_SyscallError
--- PASS: TestIsDockerConnectivityError_SyscallError (0.00s)
=== RUN TestIsDockerConnectivityError_NetErrorTimeout
--- PASS: TestIsDockerConnectivityError_NetErrorTimeout (0.00s)
=== RUN TestNewGeoIPService_InvalidPath
--- PASS: TestNewGeoIPService_InvalidPath (0.00s)
=== RUN TestGeoIPService_NotLoaded
--- PASS: TestGeoIPService_NotLoaded (0.00s)
=== RUN TestGeoIPService_InvalidIP
--- PASS: TestGeoIPService_InvalidIP (0.00s)
=== RUN TestGeoIPService_LookupCountry_CountryNotFound
--- PASS: TestGeoIPService_LookupCountry_CountryNotFound (0.00s)
=== RUN TestGeoIPService_LookupCountry_Success
--- PASS: TestGeoIPService_LookupCountry_Success (0.00s)
=== RUN TestGeoIPService_LookupCountry_ReaderError
--- PASS: TestGeoIPService_LookupCountry_ReaderError (0.00s)
=== RUN TestGeoIPService_Close
--- PASS: TestGeoIPService_Close (0.00s)
=== RUN TestGeoIPService_GetDatabasePath
--- PASS: TestGeoIPService_GetDatabasePath (0.00s)
=== RUN TestGeoIPService_ConcurrentAccess
--- PASS: TestGeoIPService_ConcurrentAccess (0.00s)
=== RUN TestGeoIPService_Integration
geoip_service_test.go:134: GeoIP database not found, skipping integration test
--- SKIP: TestGeoIPService_Integration (0.00s)
=== RUN TestGeoIPService_ErrorTypes
--- PASS: TestGeoIPService_ErrorTypes (0.00s)
=== RUN TestLogService
--- PASS: TestLogService (0.00s)
=== RUN TestNewLogWatcher
=== PAUSE TestNewLogWatcher
=== RUN TestLogWatcherStartStop
=== PAUSE TestLogWatcherStartStop
=== RUN TestLogWatcherSubscribeUnsubscribe
=== PAUSE TestLogWatcherSubscribeUnsubscribe
=== RUN TestLogWatcherBroadcast
=== PAUSE TestLogWatcherBroadcast
=== RUN TestLogWatcherBroadcastNonBlocking
=== PAUSE TestLogWatcherBroadcastNonBlocking
=== RUN TestParseLogEntryValidJSON
=== PAUSE TestParseLogEntryValidJSON
=== RUN TestParseLogEntryInvalidJSON
=== PAUSE TestParseLogEntryInvalidJSON
=== RUN TestParseLogEntryBlockedByWAF
=== PAUSE TestParseLogEntryBlockedByWAF
=== RUN TestParseLogEntryBlockedByRateLimit
=== PAUSE TestParseLogEntryBlockedByRateLimit
=== RUN TestParseLogEntry403CrowdSec
=== PAUSE TestParseLogEntry403CrowdSec
=== RUN TestParseLogEntry401Auth
=== PAUSE TestParseLogEntry401Auth
=== RUN TestParseLogEntry500Error
=== PAUSE TestParseLogEntry500Error
=== RUN TestHasHeader
=== PAUSE TestHasHeader
=== RUN TestLogWatcherIntegration
=== PAUSE TestLogWatcherIntegration
=== RUN TestLogWatcherConcurrentSubscribers
=== PAUSE TestLogWatcherConcurrentSubscribers
=== RUN TestLogWatcherMissingFile
=== PAUSE TestLogWatcherMissingFile
=== RUN TestMin
=== PAUSE TestMin
=== RUN TestLogWatcher_ReadLoop_EOFRetry
=== PAUSE TestLogWatcher_ReadLoop_EOFRetry
=== RUN TestDetectSecurityEvent_WAFWithCorazaId
=== PAUSE TestDetectSecurityEvent_WAFWithCorazaId
=== RUN TestDetectSecurityEvent_WAFWithCorazaRuleId
=== PAUSE TestDetectSecurityEvent_WAFWithCorazaRuleId
=== RUN TestDetectSecurityEvent_CrowdSecWithDecisionHeader
=== PAUSE TestDetectSecurityEvent_CrowdSecWithDecisionHeader
=== RUN TestDetectSecurityEvent_CrowdSecWithOriginHeader
=== PAUSE TestDetectSecurityEvent_CrowdSecWithOriginHeader
=== RUN TestDetectSecurityEvent_ACLDeniedHeader
=== PAUSE TestDetectSecurityEvent_ACLDeniedHeader
=== RUN TestDetectSecurityEvent_ACLBlockedHeader
=== PAUSE TestDetectSecurityEvent_ACLBlockedHeader
=== RUN TestDetectSecurityEvent_RateLimitAllHeaders
=== PAUSE TestDetectSecurityEvent_RateLimitAllHeaders
=== RUN TestDetectSecurityEvent_RateLimitPartialHeaders
=== PAUSE TestDetectSecurityEvent_RateLimitPartialHeaders
=== RUN TestDetectSecurityEvent_403WithoutHeaders
=== PAUSE TestDetectSecurityEvent_403WithoutHeaders
=== RUN TestMailService_SaveAndGetSMTPConfig
--- PASS: TestMailService_SaveAndGetSMTPConfig (0.00s)
=== RUN TestMailService_UpdateSMTPConfig
--- PASS: TestMailService_UpdateSMTPConfig (0.01s)
=== RUN TestMailService_IsConfigured
=== RUN TestMailService_IsConfigured/configured_with_all_fields
=== RUN TestMailService_IsConfigured/not_configured_-_missing_host
=== RUN TestMailService_IsConfigured/not_configured_-_missing_from_address
--- PASS: TestMailService_IsConfigured (0.02s)
--- PASS: TestMailService_IsConfigured/configured_with_all_fields (0.00s)
--- PASS: TestMailService_IsConfigured/not_configured_-_missing_host (0.01s)
--- PASS: TestMailService_IsConfigured/not_configured_-_missing_from_address (0.00s)
=== RUN TestMailService_GetSMTPConfig_Defaults
--- PASS: TestMailService_GetSMTPConfig_Defaults (0.00s)
=== RUN TestMailService_BuildEmail
--- PASS: TestMailService_BuildEmail (0.00s)
=== RUN TestParseEmailAddressForHeader
=== RUN TestParseEmailAddressForHeader/valid_email
=== RUN TestParseEmailAddressForHeader/valid_email_with_name
=== RUN TestParseEmailAddressForHeader/empty_email
=== RUN TestParseEmailAddressForHeader/invalid_format
=== RUN TestParseEmailAddressForHeader/missing_domain
=== RUN TestParseEmailAddressForHeader/injection_attempt
--- PASS: TestParseEmailAddressForHeader (0.00s)
--- PASS: TestParseEmailAddressForHeader/valid_email (0.00s)
--- PASS: TestParseEmailAddressForHeader/valid_email_with_name (0.00s)
--- PASS: TestParseEmailAddressForHeader/empty_email (0.00s)
--- PASS: TestParseEmailAddressForHeader/invalid_format (0.00s)
--- PASS: TestParseEmailAddressForHeader/missing_domain (0.00s)
--- PASS: TestParseEmailAddressForHeader/injection_attempt (0.00s)
=== RUN TestMailService_BuildEmail_RejectsCRLFInSubject
--- PASS: TestMailService_BuildEmail_RejectsCRLFInSubject (0.00s)
=== RUN TestMailService_BuildEmail_RejectsCRLFInReplyTo
--- PASS: TestMailService_BuildEmail_RejectsCRLFInReplyTo (0.00s)
=== RUN TestMailService_SMTPDotStuffing
=== RUN TestMailService_SMTPDotStuffing/body_with_leading_period_on_line
=== RUN TestMailService_SMTPDotStuffing/body_with_SMTP_terminator_sequence
=== RUN TestMailService_SMTPDotStuffing/body_with_multiple_leading_periods
=== RUN TestMailService_SMTPDotStuffing/body_without_leading_periods
--- PASS: TestMailService_SMTPDotStuffing (0.00s)
--- PASS: TestMailService_SMTPDotStuffing/body_with_leading_period_on_line (0.00s)
--- PASS: TestMailService_SMTPDotStuffing/body_with_SMTP_terminator_sequence (0.00s)
--- PASS: TestMailService_SMTPDotStuffing/body_with_multiple_leading_periods (0.00s)
--- PASS: TestMailService_SMTPDotStuffing/body_without_leading_periods (0.00s)
=== RUN TestSanitizeEmailBody
=== RUN TestSanitizeEmailBody/single_leading_period
=== RUN TestSanitizeEmailBody/period_in_middle
=== RUN TestSanitizeEmailBody/multiple_lines_with_periods
=== RUN TestSanitizeEmailBody/SMTP_terminator
=== RUN TestSanitizeEmailBody/no_periods
=== RUN TestSanitizeEmailBody/empty_string
--- PASS: TestSanitizeEmailBody (0.00s)
--- PASS: TestSanitizeEmailBody/single_leading_period (0.00s)
--- PASS: TestSanitizeEmailBody/period_in_middle (0.00s)
--- PASS: TestSanitizeEmailBody/multiple_lines_with_periods (0.00s)
--- PASS: TestSanitizeEmailBody/SMTP_terminator (0.00s)
--- PASS: TestSanitizeEmailBody/no_periods (0.00s)
--- PASS: TestSanitizeEmailBody/empty_string (0.00s)
=== RUN TestMailService_TestConnection_NotConfigured
--- PASS: TestMailService_TestConnection_NotConfigured (0.00s)
=== RUN TestMailService_SendEmail_NotConfigured
--- PASS: TestMailService_SendEmail_NotConfigured (0.00s)
=== RUN TestMailService_SendEmail_RejectsCRLFInSubject
--- PASS: TestMailService_SendEmail_RejectsCRLFInSubject (0.00s)
=== RUN TestSMTPConfigSerialization
--- PASS: TestSMTPConfigSerialization (0.01s)
=== RUN TestMailService_SendInvite_Template
time="2026-01-10T02:18:09Z" level=info msg="Sending invite email" email=test@example.com
--- PASS: TestMailService_SendInvite_Template (0.00s)
=== RUN TestMailService_SendInvite_InvalidBaseURL_CRLF
--- PASS: TestMailService_SendInvite_InvalidBaseURL_CRLF (0.00s)
=== RUN TestMailService_SendInvite_InvalidBaseURL_Path
--- PASS: TestMailService_SendInvite_InvalidBaseURL_Path (0.00s)
=== RUN TestMailService_Integration
mail_service_test.go:422: Integration test requires SMTP server
--- SKIP: TestMailService_Integration (0.00s)
=== RUN TestMailService_SendInvite_TokenFormat
time="2026-01-10T02:18:09Z" level=info msg="Sending invite email" email=test@example.com
time="2026-01-10T02:18:09Z" level=info msg="Sending invite email" email=test@example.com
--- PASS: TestMailService_SendInvite_TokenFormat (0.01s)
=== RUN TestMailService_SaveSMTPConfig_Concurrent
mail_service_test.go:444: In-memory SQLite doesn't support concurrent writes - test real DB in integration
--- SKIP: TestMailService_SaveSMTPConfig_Concurrent (0.00s)
=== RUN TestMailService_SendEmail_InvalidRecipient
--- PASS: TestMailService_SendEmail_InvalidRecipient (0.00s)
=== RUN TestMailService_SendEmail_InvalidFromAddress
--- PASS: TestMailService_SendEmail_InvalidFromAddress (0.00s)
=== RUN TestMailService_SendEmail_EncryptionModes
=== RUN TestMailService_SendEmail_EncryptionModes/ssl
=== RUN TestMailService_SendEmail_EncryptionModes/starttls
=== RUN TestMailService_SendEmail_EncryptionModes/none
=== RUN TestMailService_SendEmail_EncryptionModes/empty
--- PASS: TestMailService_SendEmail_EncryptionModes (0.02s)
--- PASS: TestMailService_SendEmail_EncryptionModes/ssl (0.01s)
--- PASS: TestMailService_SendEmail_EncryptionModes/starttls (0.00s)
--- PASS: TestMailService_SendEmail_EncryptionModes/none (0.00s)
--- PASS: TestMailService_SendEmail_EncryptionModes/empty (0.00s)
=== RUN TestMailService_SendEmail_CRLFInjection_Comprehensive
=== RUN TestMailService_SendEmail_CRLFInjection_Comprehensive/CRLF_in_recipient_address
=== RUN TestMailService_SendEmail_CRLFInjection_Comprehensive/CRLF_in_subject_line
=== RUN TestMailService_SendEmail_CRLFInjection_Comprehensive/LF_only_in_recipient
=== RUN TestMailService_SendEmail_CRLFInjection_Comprehensive/LF_only_in_subject
=== RUN TestMailService_SendEmail_CRLFInjection_Comprehensive/CR_only_in_recipient
=== RUN TestMailService_SendEmail_CRLFInjection_Comprehensive/multiple_CRLF_sequences
--- PASS: TestMailService_SendEmail_CRLFInjection_Comprehensive (0.01s)
--- PASS: TestMailService_SendEmail_CRLFInjection_Comprehensive/CRLF_in_recipient_address (0.00s)
--- PASS: TestMailService_SendEmail_CRLFInjection_Comprehensive/CRLF_in_subject_line (0.00s)
--- PASS: TestMailService_SendEmail_CRLFInjection_Comprehensive/LF_only_in_recipient (0.00s)
--- PASS: TestMailService_SendEmail_CRLFInjection_Comprehensive/LF_only_in_subject (0.00s)
--- PASS: TestMailService_SendEmail_CRLFInjection_Comprehensive/CR_only_in_recipient (0.00s)
--- PASS: TestMailService_SendEmail_CRLFInjection_Comprehensive/multiple_CRLF_sequences (0.00s)
=== RUN TestMailService_SendInvite_CRLFInjection
=== RUN TestMailService_SendInvite_CRLFInjection/CRLF_in_email_address
=== RUN TestMailService_SendInvite_CRLFInjection/CRLF_in_baseURL
=== RUN TestMailService_SendInvite_CRLFInjection/CRLF_in_app_name_(subject)
--- PASS: TestMailService_SendInvite_CRLFInjection (0.01s)
--- PASS: TestMailService_SendInvite_CRLFInjection/CRLF_in_email_address (0.00s)
--- PASS: TestMailService_SendInvite_CRLFInjection/CRLF_in_baseURL (0.00s)
--- PASS: TestMailService_SendInvite_CRLFInjection/CRLF_in_app_name_(subject) (0.00s)
=== RUN TestSupportsJSONTemplates
=== RUN TestSupportsJSONTemplates/webhook
=== RUN TestSupportsJSONTemplates/discord
=== RUN TestSupportsJSONTemplates/slack
=== RUN TestSupportsJSONTemplates/gotify
=== RUN TestSupportsJSONTemplates/generic
=== RUN TestSupportsJSONTemplates/telegram
=== RUN TestSupportsJSONTemplates/unknown
=== RUN TestSupportsJSONTemplates/WEBHOOK_uppercase
=== RUN TestSupportsJSONTemplates/Discord_mixed_case
--- PASS: TestSupportsJSONTemplates (0.00s)
--- PASS: TestSupportsJSONTemplates/webhook (0.00s)
--- PASS: TestSupportsJSONTemplates/discord (0.00s)
--- PASS: TestSupportsJSONTemplates/slack (0.00s)
--- PASS: TestSupportsJSONTemplates/gotify (0.00s)
--- PASS: TestSupportsJSONTemplates/generic (0.00s)
--- PASS: TestSupportsJSONTemplates/telegram (0.00s)
--- PASS: TestSupportsJSONTemplates/unknown (0.00s)
--- PASS: TestSupportsJSONTemplates/WEBHOOK_uppercase (0.00s)
--- PASS: TestSupportsJSONTemplates/Discord_mixed_case (0.00s)
=== RUN TestSendJSONPayload_Discord
--- PASS: TestSendJSONPayload_Discord (0.00s)
=== RUN TestSendJSONPayload_Slack
--- PASS: TestSendJSONPayload_Slack (0.00s)
=== RUN TestSendJSONPayload_Gotify
--- PASS: TestSendJSONPayload_Gotify (0.00s)
=== RUN TestSendJSONPayload_TemplateTimeout
--- PASS: TestSendJSONPayload_TemplateTimeout (0.00s)
=== RUN TestSendJSONPayload_TemplateSizeLimit
--- PASS: TestSendJSONPayload_TemplateSizeLimit (0.00s)
=== RUN TestSendJSONPayload_DiscordValidation
--- PASS: TestSendJSONPayload_DiscordValidation (0.00s)
=== RUN TestSendJSONPayload_SlackValidation
--- PASS: TestSendJSONPayload_SlackValidation (0.00s)
=== RUN TestSendJSONPayload_GotifyValidation
--- PASS: TestSendJSONPayload_GotifyValidation (0.00s)
=== RUN TestSendJSONPayload_InvalidJSON
--- PASS: TestSendJSONPayload_InvalidJSON (0.00s)
=== RUN TestNormalizeURL_DiscordWebhook_ConvertsToDiscordScheme
--- PASS: TestNormalizeURL_DiscordWebhook_ConvertsToDiscordScheme (0.00s)
=== RUN TestSendExternal_SkipsInvalidHTTPDestination
time="2026-01-10T02:18:09Z" level=warning msg="Skipping notification for provider due to invalid destination" provider=bad
--- PASS: TestSendExternal_SkipsInvalidHTTPDestination (0.16s)
=== RUN TestSendExternal_UsesJSONForSupportedServices
--- PASS: TestSendExternal_UsesJSONForSupportedServices (0.10s)
=== RUN TestTestProvider_UsesJSONForSupportedServices
--- PASS: TestTestProvider_UsesJSONForSupportedServices (0.00s)
=== RUN TestNotificationService_TemplateCRUD
=== PAUSE TestNotificationService_TemplateCRUD
=== RUN TestNotificationService_Create
--- PASS: TestNotificationService_Create (0.00s)
=== RUN TestNotificationService_List
--- PASS: TestNotificationService_List (0.00s)
=== RUN TestNotificationService_MarkAsRead
--- PASS: TestNotificationService_MarkAsRead (0.01s)
=== RUN TestNotificationService_MarkAllAsRead
--- PASS: TestNotificationService_MarkAllAsRead (0.00s)
=== RUN TestNotificationService_Providers
--- PASS: TestNotificationService_Providers (0.01s)
=== RUN TestNotificationService_TestProvider_Webhook
--- PASS: TestNotificationService_TestProvider_Webhook (0.01s)
=== RUN TestNotificationService_SendExternal
--- PASS: TestNotificationService_SendExternal (0.01s)
=== RUN TestNotificationService_SendExternal_MinimalVsDetailedTemplates
--- PASS: TestNotificationService_SendExternal_MinimalVsDetailedTemplates (0.01s)
=== RUN TestNotificationService_SendExternal_Filtered
--- PASS: TestNotificationService_SendExternal_Filtered (0.11s)
=== RUN TestNotificationService_SendExternal_Shoutrrr
time="2026-01-10T02:18:10Z" level=error msg="Failed to send JSON notification" error="invalid webhook url" provider="Test Discord"
--- PASS: TestNotificationService_SendExternal_Shoutrrr (0.10s)
=== RUN TestNormalizeURL
=== RUN TestNormalizeURL/Discord_HTTPS
=== RUN TestNormalizeURL/Discord_HTTPS_with_app
=== RUN TestNormalizeURL/Discord_Shoutrrr
=== RUN TestNormalizeURL/Other_Service
--- PASS: TestNormalizeURL (0.00s)
--- PASS: TestNormalizeURL/Discord_HTTPS (0.00s)
--- PASS: TestNormalizeURL/Discord_HTTPS_with_app (0.00s)
--- PASS: TestNormalizeURL/Discord_Shoutrrr (0.00s)
--- PASS: TestNormalizeURL/Other_Service (0.00s)
=== RUN TestNotificationService_SendCustomWebhook_Errors
=== RUN TestNotificationService_SendCustomWebhook_Errors/invalid_URL
=== RUN TestNotificationService_SendCustomWebhook_Errors/unreachable_host
=== RUN TestNotificationService_SendCustomWebhook_Errors/server_returns_error
=== RUN TestNotificationService_SendCustomWebhook_Errors/valid_custom_payload_template
=== RUN TestNotificationService_SendCustomWebhook_Errors/default_payload_without_template
--- PASS: TestNotificationService_SendCustomWebhook_Errors (0.01s)
--- PASS: TestNotificationService_SendCustomWebhook_Errors/invalid_URL (0.00s)
--- PASS: TestNotificationService_SendCustomWebhook_Errors/unreachable_host (0.00s)
--- PASS: TestNotificationService_SendCustomWebhook_Errors/server_returns_error (0.00s)
--- PASS: TestNotificationService_SendCustomWebhook_Errors/valid_custom_payload_template (0.00s)
--- PASS: TestNotificationService_SendCustomWebhook_Errors/default_payload_without_template (0.00s)
=== RUN TestNotificationService_SendCustomWebhook_PropagatesRequestID
--- PASS: TestNotificationService_SendCustomWebhook_PropagatesRequestID (0.01s)
=== RUN TestNotificationService_TestProvider_Errors
=== RUN TestNotificationService_TestProvider_Errors/unsupported_provider_type
=== RUN TestNotificationService_TestProvider_Errors/webhook_with_invalid_URL
=== RUN TestNotificationService_TestProvider_Errors/discord_with_invalid_URL_format
=== RUN TestNotificationService_TestProvider_Errors/slack_with_unreachable_webhook
=== RUN TestNotificationService_TestProvider_Errors/webhook_success
--- PASS: TestNotificationService_TestProvider_Errors (0.01s)
--- PASS: TestNotificationService_TestProvider_Errors/unsupported_provider_type (0.00s)
--- PASS: TestNotificationService_TestProvider_Errors/webhook_with_invalid_URL (0.00s)
--- PASS: TestNotificationService_TestProvider_Errors/discord_with_invalid_URL_format (0.00s)
--- PASS: TestNotificationService_TestProvider_Errors/slack_with_unreachable_webhook (0.00s)
--- PASS: TestNotificationService_TestProvider_Errors/webhook_success (0.00s)
=== RUN TestSSRF_URLValidation_PrivateIP
--- PASS: TestSSRF_URLValidation_PrivateIP (0.00s)
=== RUN TestSSRF_URLValidation_ComprehensiveBlocking
=== RUN TestSSRF_URLValidation_ComprehensiveBlocking/10.0.0.0/8
=== RUN TestSSRF_URLValidation_ComprehensiveBlocking/10.255.255.254
=== RUN TestSSRF_URLValidation_ComprehensiveBlocking/172.16.0.0/12
=== RUN TestSSRF_URLValidation_ComprehensiveBlocking/172.31.255.254
=== RUN TestSSRF_URLValidation_ComprehensiveBlocking/192.168.0.0/16
=== RUN TestSSRF_URLValidation_ComprehensiveBlocking/172.15.x_(not_private)
=== RUN TestSSRF_URLValidation_ComprehensiveBlocking/172.32.x_(not_private)
=== RUN TestSSRF_URLValidation_ComprehensiveBlocking/169.254.169.254
=== RUN TestSSRF_URLValidation_ComprehensiveBlocking/localhost
=== RUN TestSSRF_URLValidation_ComprehensiveBlocking/127.0.0.1
=== RUN TestSSRF_URLValidation_ComprehensiveBlocking/::1
=== RUN TestSSRF_URLValidation_ComprehensiveBlocking/google.com
--- PASS: TestSSRF_URLValidation_ComprehensiveBlocking (0.00s)
--- PASS: TestSSRF_URLValidation_ComprehensiveBlocking/10.0.0.0/8 (0.00s)
--- PASS: TestSSRF_URLValidation_ComprehensiveBlocking/10.255.255.254 (0.00s)
--- PASS: TestSSRF_URLValidation_ComprehensiveBlocking/172.16.0.0/12 (0.00s)
--- PASS: TestSSRF_URLValidation_ComprehensiveBlocking/172.31.255.254 (0.00s)
--- PASS: TestSSRF_URLValidation_ComprehensiveBlocking/192.168.0.0/16 (0.00s)
--- PASS: TestSSRF_URLValidation_ComprehensiveBlocking/172.15.x_(not_private) (0.00s)
--- PASS: TestSSRF_URLValidation_ComprehensiveBlocking/172.32.x_(not_private) (0.00s)
--- PASS: TestSSRF_URLValidation_ComprehensiveBlocking/169.254.169.254 (0.00s)
--- PASS: TestSSRF_URLValidation_ComprehensiveBlocking/localhost (0.00s)
--- PASS: TestSSRF_URLValidation_ComprehensiveBlocking/127.0.0.1 (0.00s)
--- PASS: TestSSRF_URLValidation_ComprehensiveBlocking/::1 (0.00s)
--- PASS: TestSSRF_URLValidation_ComprehensiveBlocking/google.com (0.00s)
=== RUN TestSSRF_WebhookIntegration
=== RUN TestSSRF_WebhookIntegration/blocks_private_IP_webhook
=== RUN TestSSRF_WebhookIntegration/blocks_cloud_metadata_endpoint
=== RUN TestSSRF_WebhookIntegration/allows_localhost_for_testing
--- PASS: TestSSRF_WebhookIntegration (0.01s)
--- PASS: TestSSRF_WebhookIntegration/blocks_private_IP_webhook (0.00s)
--- PASS: TestSSRF_WebhookIntegration/blocks_cloud_metadata_endpoint (0.00s)
--- PASS: TestSSRF_WebhookIntegration/allows_localhost_for_testing (0.00s)
=== RUN TestNotificationService_SendExternal_EdgeCases
=== RUN TestNotificationService_SendExternal_EdgeCases/no_enabled_providers
=== RUN TestNotificationService_SendExternal_EdgeCases/provider_filtered_by_category
=== RUN TestNotificationService_SendExternal_EdgeCases/custom_data_passed_to_webhook
--- PASS: TestNotificationService_SendExternal_EdgeCases (0.22s)
--- PASS: TestNotificationService_SendExternal_EdgeCases/no_enabled_providers (0.05s)
--- PASS: TestNotificationService_SendExternal_EdgeCases/provider_filtered_by_category (0.06s)
--- PASS: TestNotificationService_SendExternal_EdgeCases/custom_data_passed_to_webhook (0.11s)
=== RUN TestNotificationService_RenderTemplate
--- PASS: TestNotificationService_RenderTemplate (0.00s)
=== RUN TestNotificationService_CreateProvider_Validation
=== RUN TestNotificationService_CreateProvider_Validation/creates_provider_with_defaults
=== RUN TestNotificationService_CreateProvider_Validation/updates_existing_provider
=== RUN TestNotificationService_CreateProvider_Validation/deletes_non-existent_provider
--- PASS: TestNotificationService_CreateProvider_Validation (0.01s)
--- PASS: TestNotificationService_CreateProvider_Validation/creates_provider_with_defaults (0.00s)
--- PASS: TestNotificationService_CreateProvider_Validation/updates_existing_provider (0.00s)
--- PASS: TestNotificationService_CreateProvider_Validation/deletes_non-existent_provider (0.00s)
=== RUN TestNotificationService_IsPrivateIP
=== RUN TestNotificationService_IsPrivateIP/loopback_ipv4
=== RUN TestNotificationService_IsPrivateIP/loopback_ipv6
=== RUN TestNotificationService_IsPrivateIP/private_10.x
=== RUN TestNotificationService_IsPrivateIP/private_10.x_high
=== RUN TestNotificationService_IsPrivateIP/private_172.16-31
=== RUN TestNotificationService_IsPrivateIP/private_172.31
=== RUN TestNotificationService_IsPrivateIP/private_192.168
=== RUN TestNotificationService_IsPrivateIP/public_172.32
=== RUN TestNotificationService_IsPrivateIP/public_172.15
=== RUN TestNotificationService_IsPrivateIP/public_ip
=== RUN TestNotificationService_IsPrivateIP/public_ipv6
=== RUN TestNotificationService_IsPrivateIP/link_local_ipv4
=== RUN TestNotificationService_IsPrivateIP/link_local_ipv6
=== RUN TestNotificationService_IsPrivateIP/unique_local_ipv6_fc
=== RUN TestNotificationService_IsPrivateIP/unique_local_ipv6_fc_high
=== RUN TestNotificationService_IsPrivateIP/unique_local_ipv6_fd
--- PASS: TestNotificationService_IsPrivateIP (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/loopback_ipv4 (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/loopback_ipv6 (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/private_10.x (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/private_10.x_high (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/private_172.16-31 (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/private_172.31 (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/private_192.168 (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/public_172.32 (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/public_172.15 (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/public_ip (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/public_ipv6 (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/link_local_ipv4 (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/link_local_ipv6 (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/unique_local_ipv6_fc (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/unique_local_ipv6_fc_high (0.00s)
--- PASS: TestNotificationService_IsPrivateIP/unique_local_ipv6_fd (0.00s)
=== RUN TestNotificationService_CreateProvider_InvalidCustomTemplate
=== RUN TestNotificationService_CreateProvider_InvalidCustomTemplate/invalid_custom_template_on_create
=== RUN TestNotificationService_CreateProvider_InvalidCustomTemplate/invalid_custom_template_on_update
--- PASS: TestNotificationService_CreateProvider_InvalidCustomTemplate (0.00s)
--- PASS: TestNotificationService_CreateProvider_InvalidCustomTemplate/invalid_custom_template_on_create (0.00s)
--- PASS: TestNotificationService_CreateProvider_InvalidCustomTemplate/invalid_custom_template_on_update (0.00s)
=== RUN TestRenderTemplate_TemplateParseError
--- PASS: TestRenderTemplate_TemplateParseError (0.00s)
=== RUN TestRenderTemplate_TemplateExecutionError
--- PASS: TestRenderTemplate_TemplateExecutionError (0.00s)
=== RUN TestRenderTemplate_InvalidJSONOutput
--- PASS: TestRenderTemplate_InvalidJSONOutput (0.00s)
=== RUN TestSendCustomWebhook_HTTPStatusCodeErrors
=== RUN TestSendCustomWebhook_HTTPStatusCodeErrors/status_400
=== RUN TestSendCustomWebhook_HTTPStatusCodeErrors/status_404
=== RUN TestSendCustomWebhook_HTTPStatusCodeErrors/status_500
=== RUN TestSendCustomWebhook_HTTPStatusCodeErrors/status_502
=== RUN TestSendCustomWebhook_HTTPStatusCodeErrors/status_503
--- PASS: TestSendCustomWebhook_HTTPStatusCodeErrors (0.01s)
--- PASS: TestSendCustomWebhook_HTTPStatusCodeErrors/status_400 (0.00s)
--- PASS: TestSendCustomWebhook_HTTPStatusCodeErrors/status_404 (0.00s)
--- PASS: TestSendCustomWebhook_HTTPStatusCodeErrors/status_500 (0.00s)
--- PASS: TestSendCustomWebhook_HTTPStatusCodeErrors/status_502 (0.00s)
--- PASS: TestSendCustomWebhook_HTTPStatusCodeErrors/status_503 (0.00s)
=== RUN TestSendCustomWebhook_TemplateSelection
=== RUN TestSendCustomWebhook_TemplateSelection/minimal_template
=== RUN TestSendCustomWebhook_TemplateSelection/detailed_template
=== RUN TestSendCustomWebhook_TemplateSelection/custom_template
=== RUN TestSendCustomWebhook_TemplateSelection/empty_template_defaults_to_minimal
=== RUN TestSendCustomWebhook_TemplateSelection/unknown_template_defaults_to_minimal
--- PASS: TestSendCustomWebhook_TemplateSelection (0.01s)
--- PASS: TestSendCustomWebhook_TemplateSelection/minimal_template (0.00s)
--- PASS: TestSendCustomWebhook_TemplateSelection/detailed_template (0.00s)
--- PASS: TestSendCustomWebhook_TemplateSelection/custom_template (0.00s)
--- PASS: TestSendCustomWebhook_TemplateSelection/empty_template_defaults_to_minimal (0.00s)
--- PASS: TestSendCustomWebhook_TemplateSelection/unknown_template_defaults_to_minimal (0.00s)
=== RUN TestSendCustomWebhook_EmptyCustomTemplateDefaultsToMinimal
--- PASS: TestSendCustomWebhook_EmptyCustomTemplateDefaultsToMinimal (0.00s)
=== RUN TestCreateProvider_EmptyCustomTemplateAllowed
--- PASS: TestCreateProvider_EmptyCustomTemplateAllowed (0.00s)
=== RUN TestUpdateProvider_NonCustomTemplateSkipsValidation
--- PASS: TestUpdateProvider_NonCustomTemplateSkipsValidation (0.01s)
=== RUN TestIsPrivateIP_EdgeCases
=== RUN TestIsPrivateIP_EdgeCases/172.15.255.255_(just_before_private)
=== RUN TestIsPrivateIP_EdgeCases/172.16.0.0_(start_of_private)
=== RUN TestIsPrivateIP_EdgeCases/172.31.255.255_(end_of_private)
=== RUN TestIsPrivateIP_EdgeCases/172.32.0.0_(just_after_private)
=== RUN TestIsPrivateIP_EdgeCases/fbff:ffff:ffff:ffff:ffff:ffff:ffff:ffff_(before_ULA)
=== RUN TestIsPrivateIP_EdgeCases/fc00::0_(start_of_ULA)
=== RUN TestIsPrivateIP_EdgeCases/fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff_(end_of_ULA)
=== RUN TestIsPrivateIP_EdgeCases/fe00::0_(after_ULA)
=== RUN TestIsPrivateIP_EdgeCases/fe7f:ffff:ffff:ffff:ffff:ffff:ffff:ffff_(before_link-local)
=== RUN TestIsPrivateIP_EdgeCases/fe80::0_(start_of_link-local)
=== RUN TestIsPrivateIP_EdgeCases/febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff_(end_of_link-local)
=== RUN TestIsPrivateIP_EdgeCases/fec0::0_(after_link-local)
--- PASS: TestIsPrivateIP_EdgeCases (0.00s)
--- PASS: TestIsPrivateIP_EdgeCases/172.15.255.255_(just_before_private) (0.00s)
--- PASS: TestIsPrivateIP_EdgeCases/172.16.0.0_(start_of_private) (0.00s)
--- PASS: TestIsPrivateIP_EdgeCases/172.31.255.255_(end_of_private) (0.00s)
--- PASS: TestIsPrivateIP_EdgeCases/172.32.0.0_(just_after_private) (0.00s)
--- PASS: TestIsPrivateIP_EdgeCases/fbff:ffff:ffff:ffff:ffff:ffff:ffff:ffff_(before_ULA) (0.00s)
--- PASS: TestIsPrivateIP_EdgeCases/fc00::0_(start_of_ULA) (0.00s)
--- PASS: TestIsPrivateIP_EdgeCases/fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff_(end_of_ULA) (0.00s)
--- PASS: TestIsPrivateIP_EdgeCases/fe00::0_(after_ULA) (0.00s)
--- PASS: TestIsPrivateIP_EdgeCases/fe7f:ffff:ffff:ffff:ffff:ffff:ffff:ffff_(before_link-local) (0.00s)
--- PASS: TestIsPrivateIP_EdgeCases/fe80::0_(start_of_link-local) (0.00s)
--- PASS: TestIsPrivateIP_EdgeCases/febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff_(end_of_link-local) (0.00s)
--- PASS: TestIsPrivateIP_EdgeCases/fec0::0_(after_link-local) (0.00s)
=== RUN TestSendCustomWebhook_ContextCancellation
--- PASS: TestSendCustomWebhook_ContextCancellation (0.00s)
=== RUN TestSendExternal_UnknownEventTypeSendsToAll
--- PASS: TestSendExternal_UnknownEventTypeSendsToAll (0.11s)
=== RUN TestCreateProvider_ValidCustomTemplate
--- PASS: TestCreateProvider_ValidCustomTemplate (0.01s)
=== RUN TestUpdateProvider_ValidCustomTemplate
--- PASS: TestUpdateProvider_ValidCustomTemplate (0.01s)
=== RUN TestRenderTemplate_MinimalAndDetailedTemplates
=== RUN TestRenderTemplate_MinimalAndDetailedTemplates/minimal_template
=== RUN TestRenderTemplate_MinimalAndDetailedTemplates/detailed_template
--- PASS: TestRenderTemplate_MinimalAndDetailedTemplates (0.01s)
--- PASS: TestRenderTemplate_MinimalAndDetailedTemplates/minimal_template (0.00s)
--- PASS: TestRenderTemplate_MinimalAndDetailedTemplates/detailed_template (0.00s)
=== RUN TestSendJSONPayload_ServiceSpecificValidation
=== RUN TestSendJSONPayload_ServiceSpecificValidation/discord_requires_content_or_embeds
=== RUN TestSendJSONPayload_ServiceSpecificValidation/discord_with_content_succeeds
=== RUN TestSendJSONPayload_ServiceSpecificValidation/discord_with_embeds_succeeds
=== RUN TestSendJSONPayload_ServiceSpecificValidation/slack_requires_text_or_blocks
=== RUN TestSendJSONPayload_ServiceSpecificValidation/slack_with_text_succeeds
=== RUN TestSendJSONPayload_ServiceSpecificValidation/slack_with_blocks_succeeds
=== RUN TestSendJSONPayload_ServiceSpecificValidation/gotify_requires_message
=== RUN TestSendJSONPayload_ServiceSpecificValidation/gotify_with_message_succeeds
--- PASS: TestSendJSONPayload_ServiceSpecificValidation (0.01s)
--- PASS: TestSendJSONPayload_ServiceSpecificValidation/discord_requires_content_or_embeds (0.00s)
--- PASS: TestSendJSONPayload_ServiceSpecificValidation/discord_with_content_succeeds (0.00s)
--- PASS: TestSendJSONPayload_ServiceSpecificValidation/discord_with_embeds_succeeds (0.00s)
--- PASS: TestSendJSONPayload_ServiceSpecificValidation/slack_requires_text_or_blocks (0.00s)
--- PASS: TestSendJSONPayload_ServiceSpecificValidation/slack_with_text_succeeds (0.00s)
--- PASS: TestSendJSONPayload_ServiceSpecificValidation/slack_with_blocks_succeeds (0.00s)
--- PASS: TestSendJSONPayload_ServiceSpecificValidation/gotify_requires_message (0.00s)
--- PASS: TestSendJSONPayload_ServiceSpecificValidation/gotify_with_message_succeeds (0.00s)
=== RUN TestSendExternal_AllEventTypes
=== RUN TestSendExternal_AllEventTypes/proxy_host
=== RUN TestSendExternal_AllEventTypes/remote_server
=== RUN TestSendExternal_AllEventTypes/domain
=== RUN TestSendExternal_AllEventTypes/cert
=== RUN TestSendExternal_AllEventTypes/uptime
=== RUN TestSendExternal_AllEventTypes/test
=== RUN TestSendExternal_AllEventTypes/unknown
--- PASS: TestSendExternal_AllEventTypes (0.75s)
--- PASS: TestSendExternal_AllEventTypes/proxy_host (0.11s)
--- PASS: TestSendExternal_AllEventTypes/remote_server (0.11s)
--- PASS: TestSendExternal_AllEventTypes/domain (0.11s)
--- PASS: TestSendExternal_AllEventTypes/cert (0.11s)
--- PASS: TestSendExternal_AllEventTypes/uptime (0.11s)
--- PASS: TestSendExternal_AllEventTypes/test (0.11s)
--- PASS: TestSendExternal_AllEventTypes/unknown (0.11s)
=== RUN TestIsValidRedirectURL
=== RUN TestIsValidRedirectURL/valid_http
=== RUN TestIsValidRedirectURL/valid_https
=== RUN TestIsValidRedirectURL/invalid_scheme_ftp
=== RUN TestIsValidRedirectURL/invalid_scheme_file
=== RUN TestIsValidRedirectURL/no_scheme
=== RUN TestIsValidRedirectURL/empty_hostname
=== RUN TestIsValidRedirectURL/invalid_url
=== RUN TestIsValidRedirectURL/javascript_scheme
=== RUN TestIsValidRedirectURL/data_scheme
--- PASS: TestIsValidRedirectURL (0.00s)
--- PASS: TestIsValidRedirectURL/valid_http (0.00s)
--- PASS: TestIsValidRedirectURL/valid_https (0.00s)
--- PASS: TestIsValidRedirectURL/invalid_scheme_ftp (0.00s)
--- PASS: TestIsValidRedirectURL/invalid_scheme_file (0.00s)
--- PASS: TestIsValidRedirectURL/no_scheme (0.00s)
--- PASS: TestIsValidRedirectURL/empty_hostname (0.00s)
--- PASS: TestIsValidRedirectURL/invalid_url (0.00s)
--- PASS: TestIsValidRedirectURL/javascript_scheme (0.00s)
--- PASS: TestIsValidRedirectURL/data_scheme (0.00s)
=== RUN TestSendExternal_ShoutrrrPath
--- PASS: TestSendExternal_ShoutrrrPath (0.10s)
=== RUN TestSendExternal_ShoutrrrPathWithHTTPValidation
--- PASS: TestSendExternal_ShoutrrrPathWithHTTPValidation (0.11s)
=== RUN TestSendExternal_ShoutrrrPathBlocksPrivateIP
time="2026-01-10T02:18:11Z" level=warning msg="Skipping notification for provider due to invalid destination" provider=private-ip
--- PASS: TestSendExternal_ShoutrrrPathBlocksPrivateIP (0.10s)
=== RUN TestSendExternal_ShoutrrrError
time="2026-01-10T02:18:12Z" level=error msg="Failed to send notification" error="shoutrrr error: connection failed" provider=error-test
--- PASS: TestSendExternal_ShoutrrrError (0.01s)
=== RUN TestTestProvider_ShoutrrrPath
--- PASS: TestTestProvider_ShoutrrrPath (0.01s)
=== RUN TestTestProvider_HTTPURLValidation
=== RUN TestTestProvider_HTTPURLValidation/blocks_private_IP
=== RUN TestTestProvider_HTTPURLValidation/allows_localhost
--- PASS: TestTestProvider_HTTPURLValidation (0.00s)
--- PASS: TestTestProvider_HTTPURLValidation/blocks_private_IP (0.00s)
--- PASS: TestTestProvider_HTTPURLValidation/allows_localhost (0.00s)
=== RUN TestSendJSONPayload_TemplateExecutionError
--- PASS: TestSendJSONPayload_TemplateExecutionError (0.00s)
=== RUN TestSendJSONPayload_InvalidJSONFromTemplate
--- PASS: TestSendJSONPayload_InvalidJSONFromTemplate (0.01s)
=== RUN TestSendJSONPayload_RequestCreationError
--- PASS: TestSendJSONPayload_RequestCreationError (0.00s)
=== RUN TestRenderTemplate_CustomTemplateWithWhitespace
=== RUN TestRenderTemplate_CustomTemplateWithWhitespace/detailed_with_spaces
=== RUN TestRenderTemplate_CustomTemplateWithWhitespace/minimal_with_tabs
=== RUN TestRenderTemplate_CustomTemplateWithWhitespace/custom_with_newlines
=== RUN TestRenderTemplate_CustomTemplateWithWhitespace/DETAILED_uppercase
=== RUN TestRenderTemplate_CustomTemplateWithWhitespace/MiNiMaL_mixed_case
--- PASS: TestRenderTemplate_CustomTemplateWithWhitespace (0.01s)
--- PASS: TestRenderTemplate_CustomTemplateWithWhitespace/detailed_with_spaces (0.00s)
--- PASS: TestRenderTemplate_CustomTemplateWithWhitespace/minimal_with_tabs (0.00s)
--- PASS: TestRenderTemplate_CustomTemplateWithWhitespace/custom_with_newlines (0.00s)
--- PASS: TestRenderTemplate_CustomTemplateWithWhitespace/DETAILED_uppercase (0.00s)
--- PASS: TestRenderTemplate_CustomTemplateWithWhitespace/MiNiMaL_mixed_case (0.00s)
=== RUN TestListTemplates_DBError
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/notification_service.go:449 sql: database is closed
[0.028ms] [rows:0] SELECT * FROM `notification_templates` ORDER BY created_at desc
--- PASS: TestListTemplates_DBError (0.00s)
=== RUN TestSendExternal_DBFetchError
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/notification_service.go:96 sql: database is closed
[0.028ms] [rows:0] SELECT * FROM `notification_providers` WHERE enabled = true
time="2026-01-10T02:18:12Z" level=error msg="Failed to fetch notification providers" error="sql: database is closed"
--- PASS: TestSendExternal_DBFetchError (0.00s)
=== RUN TestSendExternal_JSONPayloadError
time="2026-01-10T02:18:12Z" level=error msg="Failed to send JSON notification" error="discord payload requires 'content' or 'embeds' field" provider=json-error
--- PASS: TestSendExternal_JSONPayloadError (0.10s)
=== RUN TestSendJSONPayload_HTTPScheme
=== RUN TestSendJSONPayload_HTTPScheme/http
=== RUN TestSendJSONPayload_HTTPScheme/https
--- PASS: TestSendJSONPayload_HTTPScheme (0.01s)
--- PASS: TestSendJSONPayload_HTTPScheme/http (0.00s)
--- PASS: TestSendJSONPayload_HTTPScheme/https (0.00s)
=== RUN TestProxyHostService_ValidateUniqueDomain
=== RUN TestProxyHostService_ValidateUniqueDomain/New_unique_domain
=== RUN TestProxyHostService_ValidateUniqueDomain/Duplicate_domain
=== RUN TestProxyHostService_ValidateUniqueDomain/Same_domain_but_excluded_ID_(update_self)
--- PASS: TestProxyHostService_ValidateUniqueDomain (0.02s)
--- PASS: TestProxyHostService_ValidateUniqueDomain/New_unique_domain (0.00s)
--- PASS: TestProxyHostService_ValidateUniqueDomain/Duplicate_domain (0.00s)
--- PASS: TestProxyHostService_ValidateUniqueDomain/Same_domain_but_excluded_ID_(update_self) (0.00s)
=== RUN TestProxyHostService_CRUD
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/proxyhost_service.go:108 record not found
[0.066ms] [rows:0] SELECT * FROM `proxy_hosts` WHERE `proxy_hosts`.`id` = 1 ORDER BY `proxy_hosts`.`id` LIMIT 1
--- PASS: TestProxyHostService_CRUD (0.02s)
=== RUN TestProxyHostService_TestConnection
--- PASS: TestProxyHostService_TestConnection (0.02s)
=== RUN TestProxyHostService_AdvancedConfig
=== RUN TestProxyHostService_AdvancedConfig/Empty_advanced_config
=== RUN TestProxyHostService_AdvancedConfig/Valid_JSON_object
=== RUN TestProxyHostService_AdvancedConfig/Valid_JSON_array
=== RUN TestProxyHostService_AdvancedConfig/Invalid_JSON
=== RUN TestProxyHostService_AdvancedConfig/Valid_nested_config
--- PASS: TestProxyHostService_AdvancedConfig (0.02s)
--- PASS: TestProxyHostService_AdvancedConfig/Empty_advanced_config (0.00s)
--- PASS: TestProxyHostService_AdvancedConfig/Valid_JSON_object (0.00s)
--- PASS: TestProxyHostService_AdvancedConfig/Valid_JSON_array (0.00s)
--- PASS: TestProxyHostService_AdvancedConfig/Invalid_JSON (0.00s)
--- PASS: TestProxyHostService_AdvancedConfig/Valid_nested_config (0.00s)
=== RUN TestProxyHostService_UpdateAdvancedConfig
--- PASS: TestProxyHostService_UpdateAdvancedConfig (0.01s)
=== RUN TestProxyHostService_EmptyDomain
--- PASS: TestProxyHostService_EmptyDomain (0.01s)
=== RUN TestRemoteServerService_ValidateUniqueServer
--- PASS: TestRemoteServerService_ValidateUniqueServer (0.00s)
=== RUN TestRemoteServerService_CRUD
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/remoteserver_service.go:68 record not found
[0.084ms] [rows:0] SELECT * FROM `remote_servers` WHERE `remote_servers`.`id` = 2 ORDER BY `remote_servers`.`id` LIMIT 1
--- PASS: TestRemoteServerService_CRUD (0.01s)
=== RUN TestGetPresets
--- PASS: TestGetPresets (0.00s)
=== RUN TestEnsurePresetsExist_Creates
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.092ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-basic" ORDER BY `security_header_profiles`.`id` LIMIT 1
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.077ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-api-friendly" ORDER BY `security_header_profiles`.`id` LIMIT 1
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.075ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-strict" ORDER BY `security_header_profiles`.`id` LIMIT 1
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.091ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-paranoid" ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestEnsurePresetsExist_Creates (0.00s)
=== RUN TestEnsurePresetsExist_NoOp
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.080ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-basic" ORDER BY `security_header_profiles`.`id` LIMIT 1
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.073ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-api-friendly" ORDER BY `security_header_profiles`.`id` LIMIT 1
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.092ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-strict" ORDER BY `security_header_profiles`.`id` LIMIT 1
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.071ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-paranoid" ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestEnsurePresetsExist_NoOp (0.01s)
=== RUN TestEnsurePresetsExist_Updates
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.093ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-api-friendly" ORDER BY `security_header_profiles`.`id` LIMIT 1
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.148ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-strict" ORDER BY `security_header_profiles`.`id` LIMIT 1
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_headers_service.go:116 record not found
[0.107ms] [rows:0] SELECT * FROM `security_header_profiles` WHERE uuid = "preset-paranoid" ORDER BY `security_header_profiles`.`id` LIMIT 1
--- PASS: TestEnsurePresetsExist_Updates (0.01s)
=== RUN TestApplyPreset_Success
--- PASS: TestApplyPreset_Success (0.00s)
=== RUN TestApplyPreset_StrictPreset
--- PASS: TestApplyPreset_StrictPreset (0.00s)
=== RUN TestApplyPreset_ParanoidPreset
--- PASS: TestApplyPreset_ParanoidPreset (0.00s)
=== RUN TestApplyPreset_APIFriendlyPreset
--- PASS: TestApplyPreset_APIFriendlyPreset (0.00s)
=== RUN TestGetPresets_IncludesAPIFriendly
--- PASS: TestGetPresets_IncludesAPIFriendly (0.00s)
=== RUN TestGetPresets_OrderByScore
--- PASS: TestGetPresets_OrderByScore (0.00s)
=== RUN TestApplyPreset_InvalidPreset
--- PASS: TestApplyPreset_InvalidPreset (0.00s)
=== RUN TestApplyPreset_MultipleProfiles
--- PASS: TestApplyPreset_MultipleProfiles (0.01s)
=== RUN TestNewSecurityNotificationService
--- PASS: TestNewSecurityNotificationService (0.00s)
=== RUN TestSecurityNotificationService_GetSettings_Default
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_notification_service.go:32 record not found
[0.101ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
--- PASS: TestSecurityNotificationService_GetSettings_Default (0.00s)
=== RUN TestSecurityNotificationService_UpdateSettings
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_notification_service.go:48 record not found
[0.066ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
--- PASS: TestSecurityNotificationService_UpdateSettings (0.00s)
=== RUN TestSecurityNotificationService_UpdateSettings_Existing
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_notification_service.go:48 record not found
[0.096ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
--- PASS: TestSecurityNotificationService_UpdateSettings_Existing (0.00s)
=== RUN TestSecurityNotificationService_Send_Disabled
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_notification_service.go:32 record not found
[0.086ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
--- PASS: TestSecurityNotificationService_Send_Disabled (0.00s)
=== RUN TestSecurityNotificationService_Send_FilteredByEventType
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_notification_service.go:48 record not found
[0.069ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
--- PASS: TestSecurityNotificationService_Send_FilteredByEventType (0.00s)
=== RUN TestSecurityNotificationService_Send_FilteredBySeverity
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_notification_service.go:48 record not found
[0.060ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
--- PASS: TestSecurityNotificationService_Send_FilteredBySeverity (0.00s)
=== RUN TestSecurityNotificationService_Send_WebhookFailure
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_notification_service.go:48 record not found
[0.078ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
time="2026-01-10T02:18:12Z" level=error msg="Failed to send webhook notification" error="webhook returned status 500"
--- PASS: TestSecurityNotificationService_Send_WebhookFailure (0.00s)
=== RUN TestShouldNotify
=== RUN TestShouldNotify/error_>=_error
=== RUN TestShouldNotify/warn_<_error
=== RUN TestShouldNotify/error_>=_warn
=== RUN TestShouldNotify/info_>=_info
=== RUN TestShouldNotify/debug_<_info
=== RUN TestShouldNotify/error_>=_debug
--- PASS: TestShouldNotify (0.00s)
--- PASS: TestShouldNotify/error_>=_error (0.00s)
--- PASS: TestShouldNotify/warn_<_error (0.00s)
--- PASS: TestShouldNotify/error_>=_warn (0.00s)
--- PASS: TestShouldNotify/info_>=_info (0.00s)
--- PASS: TestShouldNotify/debug_<_info (0.00s)
--- PASS: TestShouldNotify/error_>=_debug (0.00s)
=== RUN TestSecurityNotificationService_Send_ACLDeny
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_notification_service.go:48 record not found
[0.075ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
--- PASS: TestSecurityNotificationService_Send_ACLDeny (0.00s)
=== RUN TestSecurityNotificationService_Send_ContextTimeout
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_notification_service.go:48 record not found
[0.102ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
time="2026-01-10T02:18:12Z" level=error msg="Failed to send webhook notification" error="execute request: Post \"http://127.0.0.1:41325\": context deadline exceeded"
--- PASS: TestSecurityNotificationService_Send_ContextTimeout (0.10s)
=== RUN TestSecurityNotificationService_Send_EventTypeFiltering_WAFDisabled
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_notification_service.go:48 record not found
[0.088ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
--- PASS: TestSecurityNotificationService_Send_EventTypeFiltering_WAFDisabled (0.00s)
=== RUN TestSecurityNotificationService_Send_EventTypeFiltering_ACLDisabled
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_notification_service.go:48 record not found
[0.107ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
--- PASS: TestSecurityNotificationService_Send_EventTypeFiltering_ACLDisabled (0.00s)
=== RUN TestSecurityNotificationService_Send_SeverityBelowThreshold
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_notification_service.go:48 record not found
[0.120ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
--- PASS: TestSecurityNotificationService_Send_SeverityBelowThreshold (0.00s)
=== RUN TestSecurityNotificationService_Send_WebhookSuccess
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_notification_service.go:48 record not found
[0.095ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
--- PASS: TestSecurityNotificationService_Send_WebhookSuccess (0.00s)
=== RUN TestSecurityNotificationService_sendWebhook_SSRFBlocked
=== RUN TestSecurityNotificationService_sendWebhook_SSRFBlocked/http://169.254.169.254/latest/meta-data/
time="2026-01-10T02:18:12Z" level=warning msg="Blocked SSRF attempt in security notification webhook" error="connection to private ip addresses is blocked for security (detected IPv4-mapped IPv6: 169.254.169.254)" event_type=ssrf_blocked severity=HIGH url="http://169.254.169.254/latest/meta-data/"
=== RUN TestSecurityNotificationService_sendWebhook_SSRFBlocked/http://10.0.0.1/admin
time="2026-01-10T02:18:12Z" level=warning msg="Blocked SSRF attempt in security notification webhook" error="connection to private ip addresses is blocked for security (detected IPv4-mapped IPv6: 10.0.0.1)" event_type=ssrf_blocked severity=HIGH url="http://10.0.0.1/admin"
=== RUN TestSecurityNotificationService_sendWebhook_SSRFBlocked/http://172.16.0.1/config
time="2026-01-10T02:18:12Z" level=warning msg="Blocked SSRF attempt in security notification webhook" error="connection to private ip addresses is blocked for security (detected IPv4-mapped IPv6: 172.16.0.1)" event_type=ssrf_blocked severity=HIGH url="http://172.16.0.1/config"
=== RUN TestSecurityNotificationService_sendWebhook_SSRFBlocked/http://192.168.1.1/api
time="2026-01-10T02:18:12Z" level=warning msg="Blocked SSRF attempt in security notification webhook" error="connection to private ip addresses is blocked for security (detected IPv4-mapped IPv6: 192.168.1.1)" event_type=ssrf_blocked severity=HIGH url="http://192.168.1.1/api"
--- PASS: TestSecurityNotificationService_sendWebhook_SSRFBlocked (0.00s)
--- PASS: TestSecurityNotificationService_sendWebhook_SSRFBlocked/http://169.254.169.254/latest/meta-data/ (0.00s)
--- PASS: TestSecurityNotificationService_sendWebhook_SSRFBlocked/http://10.0.0.1/admin (0.00s)
--- PASS: TestSecurityNotificationService_sendWebhook_SSRFBlocked/http://172.16.0.1/config (0.00s)
--- PASS: TestSecurityNotificationService_sendWebhook_SSRFBlocked/http://192.168.1.1/api (0.00s)
=== RUN TestSecurityNotificationService_sendWebhook_MarshalError
security_notification_service_test.go:448: JSON marshal error cannot be easily triggered with current SecurityEvent structure
--- SKIP: TestSecurityNotificationService_sendWebhook_MarshalError (0.00s)
=== RUN TestSecurityNotificationService_sendWebhook_RequestCreationError
--- PASS: TestSecurityNotificationService_sendWebhook_RequestCreationError (0.00s)
=== RUN TestSecurityNotificationService_sendWebhook_RequestExecutionError
time="2026-01-10T02:18:12Z" level=warning msg="Blocked SSRF attempt in security notification webhook" error="dns resolution failed for invalid-nonexistent-domain-12345.test: lookup invalid-nonexistent-domain-12345.test on 127.0.0.53:53: no such host" event_type=ssrf_blocked severity=HIGH url="https://invalid-nonexistent-domain-12345.test/hook"
--- PASS: TestSecurityNotificationService_sendWebhook_RequestExecutionError (0.00s)
=== RUN TestSecurityNotificationService_sendWebhook_Non200Status
=== RUN TestSecurityNotificationService_sendWebhook_Non200Status/Bad_Request
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_notification_service.go:48 record not found
[0.130ms] [rows:0] SELECT * FROM `notification_configs` ORDER BY `notification_configs`.`id` LIMIT 1
time="2026-01-10T02:18:12Z" level=error msg="Failed to send webhook notification" error="webhook returned status 400"
=== RUN TestSecurityNotificationService_sendWebhook_Non200Status/Not_Found
time="2026-01-10T02:18:12Z" level=error msg="Failed to send webhook notification" error="webhook returned status 404"
=== RUN TestSecurityNotificationService_sendWebhook_Non200Status/Internal_Server_Error
time="2026-01-10T02:18:12Z" level=error msg="Failed to send webhook notification" error="webhook returned status 500"
=== RUN TestSecurityNotificationService_sendWebhook_Non200Status/Bad_Gateway
time="2026-01-10T02:18:12Z" level=error msg="Failed to send webhook notification" error="webhook returned status 502"
=== RUN TestSecurityNotificationService_sendWebhook_Non200Status/Service_Unavailable
time="2026-01-10T02:18:12Z" level=error msg="Failed to send webhook notification" error="webhook returned status 503"
--- PASS: TestSecurityNotificationService_sendWebhook_Non200Status (0.01s)
--- PASS: TestSecurityNotificationService_sendWebhook_Non200Status/Bad_Request (0.00s)
--- PASS: TestSecurityNotificationService_sendWebhook_Non200Status/Not_Found (0.00s)
--- PASS: TestSecurityNotificationService_sendWebhook_Non200Status/Internal_Server_Error (0.00s)
--- PASS: TestSecurityNotificationService_sendWebhook_Non200Status/Bad_Gateway (0.00s)
--- PASS: TestSecurityNotificationService_sendWebhook_Non200Status/Service_Unavailable (0.00s)
=== RUN TestShouldNotify_AllSeverityCombinations
=== RUN TestShouldNotify_AllSeverityCombinations/debug_>=_debug
=== RUN TestShouldNotify_AllSeverityCombinations/debug_<_info
=== RUN TestShouldNotify_AllSeverityCombinations/debug_<_warn
=== RUN TestShouldNotify_AllSeverityCombinations/debug_<_error
=== RUN TestShouldNotify_AllSeverityCombinations/info_>=_debug
=== RUN TestShouldNotify_AllSeverityCombinations/info_>=_info
=== RUN TestShouldNotify_AllSeverityCombinations/info_<_warn
=== RUN TestShouldNotify_AllSeverityCombinations/info_<_error
=== RUN TestShouldNotify_AllSeverityCombinations/warn_>=_debug
=== RUN TestShouldNotify_AllSeverityCombinations/warn_>=_info
=== RUN TestShouldNotify_AllSeverityCombinations/warn_>=_warn
=== RUN TestShouldNotify_AllSeverityCombinations/warn_<_error
=== RUN TestShouldNotify_AllSeverityCombinations/error_>=_debug
=== RUN TestShouldNotify_AllSeverityCombinations/error_>=_info
=== RUN TestShouldNotify_AllSeverityCombinations/error_>=_warn
=== RUN TestShouldNotify_AllSeverityCombinations/error_>=_error
--- PASS: TestShouldNotify_AllSeverityCombinations (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/debug_>=_debug (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/debug_<_info (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/debug_<_warn (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/debug_<_error (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/info_>=_debug (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/info_>=_info (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/info_<_warn (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/info_<_error (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/warn_>=_debug (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/warn_>=_info (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/warn_>=_warn (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/warn_<_error (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/error_>=_debug (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/error_>=_info (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/error_>=_warn (0.00s)
--- PASS: TestShouldNotify_AllSeverityCombinations/error_>=_error (0.00s)
=== RUN TestCalculateSecurityScore_AllEnabled
--- PASS: TestCalculateSecurityScore_AllEnabled (0.00s)
=== RUN TestCalculateSecurityScore_HSTSOnly
--- PASS: TestCalculateSecurityScore_HSTSOnly (0.00s)
=== RUN TestCalculateSecurityScore_NoHeaders
--- PASS: TestCalculateSecurityScore_NoHeaders (0.00s)
=== RUN TestCalculateSecurityScore_UnsafeCSP
--- PASS: TestCalculateSecurityScore_UnsafeCSP (0.00s)
=== RUN TestCalculateSecurityScore_PartialCrossOrigin
--- PASS: TestCalculateSecurityScore_PartialCrossOrigin (0.00s)
=== RUN TestCalculateSecurityScore_WeakReferrerPolicy
--- PASS: TestCalculateSecurityScore_WeakReferrerPolicy (0.00s)
=== RUN TestCalculateSecurityScore_UnknownReferrerPolicy
--- PASS: TestCalculateSecurityScore_UnknownReferrerPolicy (0.00s)
=== RUN TestCalculateSecurityScore_ShortHSTSMaxAge
--- PASS: TestCalculateSecurityScore_ShortHSTSMaxAge (0.00s)
=== RUN TestSecurityService_Upsert_ValidateAdminWhitelist
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_service.go:106 record not found
[0.097ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
--- PASS: TestSecurityService_Upsert_ValidateAdminWhitelist (0.01s)
=== RUN TestSecurityService_BreakGlassTokenLifecycle
2026/01/10 02:18:12 /projects/Charon/backend/internal/services/security_service.go:106 record not found
[0.120ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
--- PASS: TestSecurityService_BreakGlassTokenLifecycle (2.19s)
=== RUN TestSecurityService_LogDecisionAndList
--- PASS: TestSecurityService_LogDecisionAndList (0.01s)
=== RUN TestSecurityService_UpsertRuleSet
2026/01/10 02:18:14 /projects/Charon/backend/internal/services/security_service.go:366 record not found
[0.082ms] [rows:0] SELECT * FROM `security_rule_sets` WHERE name = "owasp-crs" ORDER BY `security_rule_sets`.`id` LIMIT 1
--- PASS: TestSecurityService_UpsertRuleSet (0.01s)
=== RUN TestSecurityService_UpsertRuleSet_ContentTooLarge
--- PASS: TestSecurityService_UpsertRuleSet_ContentTooLarge (0.02s)
=== RUN TestSecurityService_DeleteRuleSet
2026/01/10 02:18:14 /projects/Charon/backend/internal/services/security_service.go:366 record not found
[0.093ms] [rows:0] SELECT * FROM `security_rule_sets` WHERE name = "owasp-crs" ORDER BY `security_rule_sets`.`id` LIMIT 1
--- PASS: TestSecurityService_DeleteRuleSet (0.01s)
=== RUN TestSecurityService_Upsert_RejectExternalMode
2026/01/10 02:18:14 /projects/Charon/backend/internal/services/security_service.go:106 record not found
[0.100ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
--- PASS: TestSecurityService_Upsert_RejectExternalMode (0.01s)
=== RUN TestSecurityService_GenerateBreakGlassToken_NewConfig
2026/01/10 02:18:15 /projects/Charon/backend/internal/services/security_service.go:154 record not found
[0.245ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "newconfig" ORDER BY `security_configs`.`id` LIMIT 1
--- PASS: TestSecurityService_GenerateBreakGlassToken_NewConfig (1.54s)
=== RUN TestSecurityService_GenerateBreakGlassToken_UpdateExisting
2026/01/10 02:18:16 /projects/Charon/backend/internal/services/security_service.go:106 record not found
[0.118ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
--- PASS: TestSecurityService_GenerateBreakGlassToken_UpdateExisting (2.98s)
=== RUN TestSecurityService_VerifyBreakGlassToken_NoConfig
2026/01/10 02:18:19 /projects/Charon/backend/internal/services/security_service.go:175 record not found
[0.125ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "nonexistent" ORDER BY `security_configs`.`id` LIMIT 1
--- PASS: TestSecurityService_VerifyBreakGlassToken_NoConfig (0.01s)
=== RUN TestSecurityService_VerifyBreakGlassToken_NoHash
2026/01/10 02:18:19 /projects/Charon/backend/internal/services/security_service.go:106 record not found
[0.103ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
--- PASS: TestSecurityService_VerifyBreakGlassToken_NoHash (0.01s)
=== RUN TestSecurityService_VerifyBreakGlassToken_WrongToken
2026/01/10 02:18:20 /projects/Charon/backend/internal/services/security_service.go:154 record not found
[0.274ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
--- PASS: TestSecurityService_VerifyBreakGlassToken_WrongToken (4.42s)
=== RUN TestSecurityService_Get_NotFound
2026/01/10 02:18:23 /projects/Charon/backend/internal/services/security_service.go:70 record not found
[0.109ms] [rows:0] SELECT * FROM `security_configs` ORDER BY `security_configs`.`id` LIMIT 1
--- PASS: TestSecurityService_Get_NotFound (0.01s)
=== RUN TestSecurityService_Upsert_PreserveBreakGlassHash
2026/01/10 02:18:24 /projects/Charon/backend/internal/services/security_service.go:154 record not found
[0.259ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
--- PASS: TestSecurityService_Upsert_PreserveBreakGlassHash (1.43s)
=== RUN TestSecurityService_Upsert_RateLimitFieldsPersist
2026/01/10 02:18:25 /projects/Charon/backend/internal/services/security_service.go:106 record not found
[0.101ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
--- PASS: TestSecurityService_Upsert_RateLimitFieldsPersist (0.01s)
=== RUN TestSecurityService_LogAudit
--- PASS: TestSecurityService_LogAudit (0.16s)
=== RUN TestSecurityService_DeleteRuleSet_NotFound
2026/01/10 02:18:25 /projects/Charon/backend/internal/services/security_service.go:388 record not found
[0.070ms] [rows:0] SELECT * FROM `security_rule_sets` WHERE `security_rule_sets`.`id` = 9999 ORDER BY `security_rule_sets`.`id` LIMIT 1
--- PASS: TestSecurityService_DeleteRuleSet_NotFound (0.01s)
=== RUN TestSecurityService_ListDecisions_UnlimitedAndLimited
--- PASS: TestSecurityService_ListDecisions_UnlimitedAndLimited (0.01s)
=== RUN TestSecurityService_LogDecision_Nil
--- PASS: TestSecurityService_LogDecision_Nil (0.01s)
=== RUN TestSecurityService_LogDecision_PrefilledUUID
--- PASS: TestSecurityService_LogDecision_PrefilledUUID (0.01s)
=== RUN TestSecurityService_ListRuleSets_Empty
--- PASS: TestSecurityService_ListRuleSets_Empty (0.01s)
=== RUN TestSecurityService_Upsert_InvalidCrowdSecMode
2026/01/10 02:18:25 /projects/Charon/backend/internal/services/security_service.go:106 record not found
[0.097ms] [rows:0] SELECT * FROM `security_configs` WHERE name = "default" ORDER BY `security_configs`.`id` LIMIT 1
--- PASS: TestSecurityService_Upsert_InvalidCrowdSecMode (0.01s)
=== RUN TestSecurityService_ListAuditLogs
--- PASS: TestSecurityService_ListAuditLogs (0.01s)
=== RUN TestSecurityService_GetAuditLogByUUID
2026/01/10 02:18:25 /projects/Charon/backend/internal/services/security_service.go:321 record not found
[0.049ms] [rows:0] SELECT * FROM `security_audits` WHERE uuid = "non-existent-uuid" ORDER BY `security_audits`.`id` LIMIT 1
--- PASS: TestSecurityService_GetAuditLogByUUID (0.01s)
=== RUN TestSecurityService_ListAuditLogsByProvider
--- PASS: TestSecurityService_ListAuditLogsByProvider (0.01s)
=== RUN TestSecurityService_AsyncAuditLogging
--- PASS: TestSecurityService_AsyncAuditLogging (0.11s)
=== RUN TestUpdateService_CheckForUpdates
--- PASS: TestUpdateService_CheckForUpdates (0.00s)
=== RUN TestUpdateService_SetAPIURL_GitHubValidation
=== RUN TestUpdateService_SetAPIURL_GitHubValidation/valid_GitHub_API_HTTPS
=== RUN TestUpdateService_SetAPIURL_GitHubValidation/GitHub_with_HTTP_scheme
=== RUN TestUpdateService_SetAPIURL_GitHubValidation/non-GitHub_domain
=== RUN TestUpdateService_SetAPIURL_GitHubValidation/localhost_allowed
=== RUN TestUpdateService_SetAPIURL_GitHubValidation/127.0.0.1_allowed
=== RUN TestUpdateService_SetAPIURL_GitHubValidation/::1_IPv6_localhost_allowed
=== RUN TestUpdateService_SetAPIURL_GitHubValidation/invalid_URL
=== RUN TestUpdateService_SetAPIURL_GitHubValidation/ftp_scheme_not_allowed
=== RUN TestUpdateService_SetAPIURL_GitHubValidation/github.com_domain_allowed_with_HTTPS
=== RUN TestUpdateService_SetAPIURL_GitHubValidation/github.com_domain_with_HTTP_rejected
--- PASS: TestUpdateService_SetAPIURL_GitHubValidation (0.00s)
--- PASS: TestUpdateService_SetAPIURL_GitHubValidation/valid_GitHub_API_HTTPS (0.00s)
--- PASS: TestUpdateService_SetAPIURL_GitHubValidation/GitHub_with_HTTP_scheme (0.00s)
--- PASS: TestUpdateService_SetAPIURL_GitHubValidation/non-GitHub_domain (0.00s)
--- PASS: TestUpdateService_SetAPIURL_GitHubValidation/localhost_allowed (0.00s)
--- PASS: TestUpdateService_SetAPIURL_GitHubValidation/127.0.0.1_allowed (0.00s)
--- PASS: TestUpdateService_SetAPIURL_GitHubValidation/::1_IPv6_localhost_allowed (0.00s)
--- PASS: TestUpdateService_SetAPIURL_GitHubValidation/invalid_URL (0.00s)
--- PASS: TestUpdateService_SetAPIURL_GitHubValidation/ftp_scheme_not_allowed (0.00s)
--- PASS: TestUpdateService_SetAPIURL_GitHubValidation/github.com_domain_allowed_with_HTTPS (0.00s)
--- PASS: TestUpdateService_SetAPIURL_GitHubValidation/github.com_domain_with_HTTP_rejected (0.00s)
=== RUN TestUptimeService_sendRecoveryNotification
=== PAUSE TestUptimeService_sendRecoveryNotification
=== RUN TestCheckHost_RetryLogic
time="2026-01-10T02:18:25Z" level=info msg="Retrying TCP check" host_name="Test Host" max=2 retry=1
time="2026-01-10T02:18:27Z" level=info msg="Retrying TCP check" host_name="Test Host" max=2 retry=2
time="2026-01-10T02:18:29Z" level=warning msg="Host check failed, waiting for threshold" failure_count=1 host_name="Test Host" last_error="dial tcp 127.0.0.1:9: connect: connection refused" threshold=2
--- PASS: TestCheckHost_RetryLogic (4.03s)
=== RUN TestCheckHost_Debouncing
time="2026-01-10T02:18:30Z" level=warning msg="Host check failed, waiting for threshold" failure_count=1 host_name="Test Host" last_error="dial tcp 192.0.2.1:9999: i/o timeout" threshold=2
2026/01/10 02:18:30 /projects/Charon/backend/internal/services/uptime_service_race_test.go:100 unrecognized token: "176d"
[0.064ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE d5b1c420-176d-4157-b59e-c1f70a24303b AND `uptime_hosts`.`id` = "d5b1c420-176d-4157-b59e-c1f70a24303b" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:31Z" level=info msg="Host status changed" host_ip=192.0.2.1 host_name="Test Host" message="TCP check failed: dial tcp 192.0.2.1:9999: i/o timeout" new=down old=up
2026/01/10 02:18:31 /projects/Charon/backend/internal/services/uptime_service_race_test.go:106 unrecognized token: "176d"
[0.083ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE d5b1c420-176d-4157-b59e-c1f70a24303b AND `uptime_hosts`.`id` = "d5b1c420-176d-4157-b59e-c1f70a24303b" ORDER BY `uptime_hosts`.`id` LIMIT 1
--- PASS: TestCheckHost_Debouncing (2.03s)
=== RUN TestCheckHost_FailureCountReset
time="2026-01-10T02:18:31Z" level=info msg="Host status changed" host_ip=127.0.0.1 host_name="Test Host" message="TCP connection to 127.0.0.1:40061 successful (retry 0)" new=up old=down
2026/01/10 02:18:31 /projects/Charon/backend/internal/services/uptime_service_race_test.go:152 unrecognized token: "0251331e-0aa2"
[0.046ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE 0251331e-0aa2-485c-acee-3427ee4c31d5 AND `uptime_hosts`.`id` = "0251331e-0aa2-485c-acee-3427ee4c31d5" ORDER BY `uptime_hosts`.`id` LIMIT 1
--- PASS: TestCheckHost_FailureCountReset (0.03s)
=== RUN TestCheckAllHosts_Synchronization
time="2026-01-10T02:18:31Z" level=info msg="Starting host checks" host_count=5
time="2026-01-10T02:18:32Z" level=warning msg="Host check failed, waiting for threshold" failure_count=1 host_name="Host 1" last_error="dial tcp 192.0.2.1:9999: i/o timeout" threshold=2
time="2026-01-10T02:18:32Z" level=warning msg="Host check failed, waiting for threshold" failure_count=1 host_name="Host 2" last_error="dial tcp 192.0.2.2:9999: i/o timeout" threshold=2
time="2026-01-10T02:18:32Z" level=warning msg="Host check failed, waiting for threshold" failure_count=1 host_name="Host 3" last_error="dial tcp 192.0.2.3:9999: i/o timeout" threshold=2
time="2026-01-10T02:18:32Z" level=warning msg="Host check failed, waiting for threshold" failure_count=1 host_name="Host 4" last_error="dial tcp 192.0.2.4:9999: i/o timeout" threshold=2
time="2026-01-10T02:18:32Z" level=warning msg="Host check failed, waiting for threshold" failure_count=1 host_name="Host 5" last_error="dial tcp 192.0.2.5:9999: i/o timeout" threshold=2
time="2026-01-10T02:18:32Z" level=info msg="All host checks completed" host_count=5
--- PASS: TestCheckAllHosts_Synchronization (0.93s)
=== RUN TestCheckHost_ConcurrentChecks
--- PASS: TestCheckHost_ConcurrentChecks (0.03s)
=== RUN TestCheckHost_ContextCancellation
time="2026-01-10T02:18:32Z" level=warning msg="TCP check cancelled" host_name="Test Host"
--- PASS: TestCheckHost_ContextCancellation (0.03s)
=== RUN TestCheckAllHosts_StaggeredStartup
time="2026-01-10T02:18:32Z" level=info msg="Starting host checks" host_count=3
time="2026-01-10T02:18:33Z" level=warning msg="Host check failed, waiting for threshold" failure_count=1 host_name="Host 1" last_error="dial tcp 192.0.2.1:9999: i/o timeout" threshold=2
time="2026-01-10T02:18:33Z" level=warning msg="Host check failed, waiting for threshold" failure_count=1 host_name="Host 2" last_error="dial tcp 192.0.2.2:9999: i/o timeout" threshold=2
time="2026-01-10T02:18:33Z" level=warning msg="Host check failed, waiting for threshold" failure_count=1 host_name="Host 3" last_error="dial tcp 192.0.2.3:9999: i/o timeout" threshold=2
time="2026-01-10T02:18:33Z" level=info msg="All host checks completed" host_count=3
--- PASS: TestCheckAllHosts_StaggeredStartup (0.62s)
=== RUN TestUptimeConfig_Defaults
--- PASS: TestUptimeConfig_Defaults (0.02s)
=== RUN TestCheckHost_HostMutexPreventsRaceCondition
--- PASS: TestCheckHost_HostMutexPreventsRaceCondition (0.03s)
=== RUN TestUptimeService_CheckAll
2026/01/10 02:18:33 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.125ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:18:33 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.089ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "127.0.0.1" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:33Z" level=info msg="Created UptimeHost" host=127.0.0.1 host_id=e6915ec0-389e-4416-90d5-a31a824969f1
2026/01/10 02:18:33 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.088ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 2 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:18:33 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.087ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "127.0.0.2" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:33Z" level=info msg="Created UptimeHost" host=127.0.0.2 host_id=b8fb24fb-381f-4d60-9e94-9fde1d7981f3
time="2026-01-10T02:18:33Z" level=info msg="Starting host checks" host_count=2
time="2026-01-10T02:18:33Z" level=warning msg="Host check failed, waiting for threshold" failure_count=1 host_name="127.0.0.2:42303" last_error="dial tcp 127.0.0.2:42303: connect: connection refused" threshold=2
time="2026-01-10T02:18:33Z" level=info msg="All host checks completed" host_count=2
time="2026-01-10T02:18:33Z" level=info msg="Starting host checks" host_count=2
time="2026-01-10T02:18:33Z" level=info msg="All host checks completed" host_count=2
time="2026-01-10T02:18:33Z" level=info msg="Starting host checks" host_count=2
time="2026-01-10T02:18:33Z" level=info msg="All host checks completed" host_count=2
time="2026-01-10T02:18:34Z" level=info msg="Starting host checks" host_count=2
time="2026-01-10T02:18:34Z" level=warning msg="Host check failed, waiting for threshold" failure_count=1 host_name="127.0.0.1:35477" last_error="dial tcp 127.0.0.1:35477: connect: connection refused" threshold=2
time="2026-01-10T02:18:34Z" level=info msg="All host checks completed" host_count=2
time="2026-01-10T02:18:34Z" level=info msg="Starting host checks" host_count=2
time="2026-01-10T02:18:34Z" level=info msg="Host status changed" host_ip=127.0.0.1 host_name="127.0.0.1:35477" message="TCP check failed: dial tcp 127.0.0.1:35477: connect: connection refused" new=down old=up
time="2026-01-10T02:18:34Z" level=info msg="All host checks completed" host_count=2
time="2026-01-10T02:18:34Z" level=info msg="Sent consolidated DOWN notification" host_name="127.0.0.1:35477" service_count=1
time="2026-01-10T02:18:34Z" level=info msg="Starting host checks" host_count=2
time="2026-01-10T02:18:34Z" level=info msg="All host checks completed" host_count=2
--- PASS: TestUptimeService_CheckAll (1.78s)
=== RUN TestUptimeService_ListMonitors
--- PASS: TestUptimeService_ListMonitors (0.04s)
=== RUN TestUptimeService_GetMonitorByID
=== RUN TestUptimeService_GetMonitorByID/get_existing_monitor
=== RUN TestUptimeService_GetMonitorByID/get_non-existent_monitor
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:1045 record not found
[0.138ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE id = "non-existent" ORDER BY `uptime_monitors`.`id` LIMIT 1
--- PASS: TestUptimeService_GetMonitorByID (0.04s)
--- PASS: TestUptimeService_GetMonitorByID/get_existing_monitor (0.00s)
--- PASS: TestUptimeService_GetMonitorByID/get_non-existent_monitor (0.00s)
=== RUN TestUptimeService_GetMonitorHistory
--- PASS: TestUptimeService_GetMonitorHistory (0.03s)
=== RUN TestUptimeService_SyncMonitors_Errors
=== RUN TestUptimeService_SyncMonitors_Errors/database_error_during_proxy_host_fetch
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:129 sql: database is closed
[0.025ms] [rows:0] SELECT * FROM `proxy_hosts`
=== RUN TestUptimeService_SyncMonitors_Errors/creates_monitors_for_new_hosts
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.116ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.067ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host= host_id=2137c317-4661-4772-9158-45d5e83005c5
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.105ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 2 ORDER BY `uptime_monitors`.`id` LIMIT 1
=== RUN TestUptimeService_SyncMonitors_Errors/orphaned_monitors_persist_after_host_deletion
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.128ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.084ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host= host_id=3dca6b43-458c-4d6e-bfa4-4a50d4891384
--- PASS: TestUptimeService_SyncMonitors_Errors (0.10s)
--- PASS: TestUptimeService_SyncMonitors_Errors/database_error_during_proxy_host_fetch (0.03s)
--- PASS: TestUptimeService_SyncMonitors_Errors/creates_monitors_for_new_hosts (0.03s)
--- PASS: TestUptimeService_SyncMonitors_Errors/orphaned_monitors_persist_after_host_deletion (0.03s)
=== RUN TestUptimeService_SyncMonitors_NameSync
=== RUN TestUptimeService_SyncMonitors_NameSync/syncs_name_from_proxy_host_when_changed
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.105ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.076ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host= host_id=c69fc6e8-989f-4b3d-92c2-d3f689aba3da
=== RUN TestUptimeService_SyncMonitors_NameSync/uses_domain_name_when_proxy_host_name_is_empty
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.102ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.093ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host= host_id=78f116c2-01a9-4e44-bbe6-caf207ae87d9
=== RUN TestUptimeService_SyncMonitors_NameSync/updates_monitor_name_when_host_name_becomes_empty
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.102ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.098ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host= host_id=3e6136a3-8060-4333-8f49-68e669908345
--- PASS: TestUptimeService_SyncMonitors_NameSync (0.11s)
--- PASS: TestUptimeService_SyncMonitors_NameSync/syncs_name_from_proxy_host_when_changed (0.04s)
--- PASS: TestUptimeService_SyncMonitors_NameSync/uses_domain_name_when_proxy_host_name_is_empty (0.04s)
--- PASS: TestUptimeService_SyncMonitors_NameSync/updates_monitor_name_when_host_name_becomes_empty (0.04s)
=== RUN TestUptimeService_SyncMonitors_TCPMigration
=== RUN TestUptimeService_SyncMonitors_TCPMigration/migrates_TCP_monitor_to_HTTP_for_public_URL
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.093ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "backend.local" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host=backend.local host_id=d67854eb-c642-4b7f-bf4b-d53da0f93214
time="2026-01-10T02:18:35Z" level=info msg="Migrated monitor for host 1 to check public URL: http://public.com" host_id=1
=== RUN TestUptimeService_SyncMonitors_TCPMigration/does_not_migrate_TCP_monitor_with_custom_URL
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.103ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "backend.local" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host=backend.local host_id=7dba5d0e-a022-48c5-8d9f-0c5b672c8f07
--- PASS: TestUptimeService_SyncMonitors_TCPMigration (0.08s)
--- PASS: TestUptimeService_SyncMonitors_TCPMigration/migrates_TCP_monitor_to_HTTP_for_public_URL (0.04s)
--- PASS: TestUptimeService_SyncMonitors_TCPMigration/does_not_migrate_TCP_monitor_with_custom_URL (0.04s)
=== RUN TestUptimeService_SyncMonitors_HTTPSUpgrade
=== RUN TestUptimeService_SyncMonitors_HTTPSUpgrade/upgrades_HTTP_to_HTTPS_when_SSL_forced
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.106ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host= host_id=94b82ed6-4790-4bc8-9c7d-fa9b355e903c
time="2026-01-10T02:18:35Z" level=info msg="Upgraded monitor for host 1 to HTTPS: https://secure.com" host_id=1
=== RUN TestUptimeService_SyncMonitors_HTTPSUpgrade/does_not_downgrade_HTTPS_when_SSL_not_forced
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.067ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host= host_id=091224d1-161c-4a6a-9196-c8e23b6f7d58
--- PASS: TestUptimeService_SyncMonitors_HTTPSUpgrade (0.07s)
--- PASS: TestUptimeService_SyncMonitors_HTTPSUpgrade/upgrades_HTTP_to_HTTPS_when_SSL_forced (0.04s)
--- PASS: TestUptimeService_SyncMonitors_HTTPSUpgrade/does_not_downgrade_HTTPS_when_SSL_not_forced (0.03s)
=== RUN TestUptimeService_SyncMonitors_RemoteServers
=== RUN TestUptimeService_SyncMonitors_RemoteServers/creates_monitor_for_new_remote_server
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:234 record not found
[0.103ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE remote_server_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.062ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "backend.local" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host=backend.local host_id=24a184ca-2b50-45a3-a068-c90e570460eb
=== RUN TestUptimeService_SyncMonitors_RemoteServers/creates_TCP_monitor_for_remote_server_without_scheme
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:234 record not found
[0.085ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE remote_server_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.068ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "tcp.backend" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host=tcp.backend host_id=a2fded70-8b8b-433c-b7e1-8642785d0587
=== RUN TestUptimeService_SyncMonitors_RemoteServers/syncs_remote_server_name_changes
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:234 record not found
[0.090ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE remote_server_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.097ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "server.local" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host=server.local host_id=fc5ca180-6106-495e-98ce-9495a0f4b4fb
=== RUN TestUptimeService_SyncMonitors_RemoteServers/syncs_remote_server_URL_changes
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:234 record not found
[0.145ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE remote_server_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.089ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "old.host" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host=old.host host_id=c6102d5c-f657-4c2d-ab13-fe52c54d1e06
=== RUN TestUptimeService_SyncMonitors_RemoteServers/syncs_remote_server_enabled_status
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:234 record not found
[0.099ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE remote_server_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.092ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "server.local" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host=server.local host_id=bfc3d116-534e-4086-92f8-37f311fae8c4
=== RUN TestUptimeService_SyncMonitors_RemoteServers/syncs_scheme_change_from_TCP_to_HTTPS
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:234 record not found
[0.087ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE remote_server_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.068ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "server.local" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host=server.local host_id=d5af8ec7-caa3-43fb-8804-d6f606f0e25d
--- PASS: TestUptimeService_SyncMonitors_RemoteServers (0.23s)
--- PASS: TestUptimeService_SyncMonitors_RemoteServers/creates_monitor_for_new_remote_server (0.04s)
--- PASS: TestUptimeService_SyncMonitors_RemoteServers/creates_TCP_monitor_for_remote_server_without_scheme (0.03s)
--- PASS: TestUptimeService_SyncMonitors_RemoteServers/syncs_remote_server_name_changes (0.05s)
--- PASS: TestUptimeService_SyncMonitors_RemoteServers/syncs_remote_server_URL_changes (0.03s)
--- PASS: TestUptimeService_SyncMonitors_RemoteServers/syncs_remote_server_enabled_status (0.04s)
--- PASS: TestUptimeService_SyncMonitors_RemoteServers/syncs_scheme_change_from_TCP_to_HTTPS (0.03s)
=== RUN TestUptimeService_CheckAll_Errors
=== RUN TestUptimeService_CheckAll_Errors/handles_empty_monitor_list
=== RUN TestUptimeService_CheckAll_Errors/orphan_monitors_don't_prevent_check_execution
=== RUN TestUptimeService_CheckAll_Errors/handles_timeout_for_slow_hosts
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.125ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:18:35 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.109ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "192.0.2.1" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:18:35Z" level=info msg="Created UptimeHost" host=192.0.2.1 host_id=213383a2-0a2c-4133-8296-591fd0750afa
time="2026-01-10T02:18:35Z" level=info msg="Starting host checks" host_count=1
time="2026-01-10T02:18:45Z" level=info msg="Retrying TCP check" host_name="192.0.2.1:9999" max=2 retry=1
time="2026-01-10T02:18:57Z" level=info msg="Retrying TCP check" host_name="192.0.2.1:9999" max=2 retry=2
time="2026-01-10T02:19:09Z" level=warning msg="Host check failed, waiting for threshold" failure_count=1 host_name="192.0.2.1:9999" last_error="dial tcp 192.0.2.1:9999: i/o timeout" threshold=2
time="2026-01-10T02:19:09Z" level=info msg="All host checks completed" host_count=1
--- PASS: TestUptimeService_CheckAll_Errors (37.28s)
--- PASS: TestUptimeService_CheckAll_Errors/handles_empty_monitor_list (0.09s)
--- PASS: TestUptimeService_CheckAll_Errors/orphan_monitors_don't_prevent_check_execution (0.14s)
--- PASS: TestUptimeService_CheckAll_Errors/handles_timeout_for_slow_hosts (37.06s)
=== RUN TestUptimeService_CheckMonitor_EdgeCases
=== RUN TestUptimeService_CheckMonitor_EdgeCases/invalid_URL_format
=== RUN TestUptimeService_CheckMonitor_EdgeCases/http_404_response_treated_as_down
2026/01/10 02:19:13 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.148ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:19:13 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.101ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "127.0.0.1" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:19:13Z" level=info msg="Created UptimeHost" host=127.0.0.1 host_id=b82fccf5-3b66-41d1-9418-58cd622ff533
time="2026-01-10T02:19:13Z" level=info msg="Starting host checks" host_count=1
time="2026-01-10T02:19:13Z" level=info msg="All host checks completed" host_count=1
time="2026-01-10T02:19:13Z" level=info msg="Starting host checks" host_count=1
time="2026-01-10T02:19:13Z" level=info msg="All host checks completed" host_count=1
time="2026-01-10T02:19:13Z" level=info msg="Starting host checks" host_count=1
time="2026-01-10T02:19:13Z" level=info msg="All host checks completed" host_count=1
=== RUN TestUptimeService_CheckMonitor_EdgeCases/https_URL_without_valid_certificate
--- PASS: TestUptimeService_CheckMonitor_EdgeCases (3.98s)
--- PASS: TestUptimeService_CheckMonitor_EdgeCases/invalid_URL_format (0.54s)
--- PASS: TestUptimeService_CheckMonitor_EdgeCases/http_404_response_treated_as_down (0.40s)
--- PASS: TestUptimeService_CheckMonitor_EdgeCases/https_URL_without_valid_certificate (3.04s)
=== RUN TestUptimeService_GetMonitorHistory_EdgeCases
=== RUN TestUptimeService_GetMonitorHistory_EdgeCases/non-existent_monitor
=== RUN TestUptimeService_GetMonitorHistory_EdgeCases/limit_parameter_respected
--- PASS: TestUptimeService_GetMonitorHistory_EdgeCases (0.09s)
--- PASS: TestUptimeService_GetMonitorHistory_EdgeCases/non-existent_monitor (0.04s)
--- PASS: TestUptimeService_GetMonitorHistory_EdgeCases/limit_parameter_respected (0.05s)
=== RUN TestUptimeService_ListMonitors_EdgeCases
=== RUN TestUptimeService_ListMonitors_EdgeCases/empty_database
=== RUN TestUptimeService_ListMonitors_EdgeCases/monitors_with_associated_proxy_hosts
--- PASS: TestUptimeService_ListMonitors_EdgeCases (0.08s)
--- PASS: TestUptimeService_ListMonitors_EdgeCases/empty_database (0.04s)
--- PASS: TestUptimeService_ListMonitors_EdgeCases/monitors_with_associated_proxy_hosts (0.04s)
=== RUN TestUptimeService_UpdateMonitor
=== RUN TestUptimeService_UpdateMonitor/update_max_retries
=== RUN TestUptimeService_UpdateMonitor/update_interval
=== RUN TestUptimeService_UpdateMonitor/update_non-existent_monitor
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:1059 record not found
[0.113ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE id = "non-existent" ORDER BY `uptime_monitors`.`id` LIMIT 1
=== RUN TestUptimeService_UpdateMonitor/update_multiple_fields
--- PASS: TestUptimeService_UpdateMonitor (0.14s)
--- PASS: TestUptimeService_UpdateMonitor/update_max_retries (0.04s)
--- PASS: TestUptimeService_UpdateMonitor/update_interval (0.03s)
--- PASS: TestUptimeService_UpdateMonitor/update_non-existent_monitor (0.03s)
--- PASS: TestUptimeService_UpdateMonitor/update_multiple_fields (0.03s)
=== RUN TestUptimeService_NotificationBatching
=== RUN TestUptimeService_NotificationBatching/batches_multiple_service_failures_on_same_host
time="2026-01-10T02:19:17Z" level=info msg="Created pending notification batch" host="Test Server" monitor="Service A"
time="2026-01-10T02:19:17Z" level=info msg="Added to pending notification batch" count=2 host="Test Server" monitor="Service B"
time="2026-01-10T02:19:17Z" level=info msg="Added to pending notification batch" count=3 host="Test Server" monitor="Service C"
time="2026-01-10T02:19:17Z" level=info msg="Sent batched DOWN notification" count=3 host="Test Server"
=== RUN TestUptimeService_NotificationBatching/single_service_down_gets_individual_notification
time="2026-01-10T02:19:17Z" level=info msg="Created pending notification batch" host="Single Service Host" monitor="Lonely Service"
time="2026-01-10T02:19:17Z" level=info msg="Sent batched DOWN notification" count=1 host="Single Service Host"
--- PASS: TestUptimeService_NotificationBatching (0.07s)
--- PASS: TestUptimeService_NotificationBatching/batches_multiple_service_failures_on_same_host (0.03s)
--- PASS: TestUptimeService_NotificationBatching/single_service_down_gets_individual_notification (0.03s)
=== RUN TestUptimeService_HostLevelCheck
=== RUN TestUptimeService_HostLevelCheck/creates_uptime_host_during_sync
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.147ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.093ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "10.0.0.50" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:19:17Z" level=info msg="Created UptimeHost" host=10.0.0.50 host_id=87948aad-f1f9-4a9f-a940-d5e1729e1d0a
=== RUN TestUptimeService_HostLevelCheck/groups_multiple_services_on_same_host
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.116ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.119ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "10.0.0.100" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:19:17Z" level=info msg="Created UptimeHost" host=10.0.0.100 host_id=ee3c3763-ed2c-4f91-9d9e-470f2f6cc6da
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.104ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 2 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.078ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 3 ORDER BY `uptime_monitors`.`id` LIMIT 1
--- PASS: TestUptimeService_HostLevelCheck (0.08s)
--- PASS: TestUptimeService_HostLevelCheck/creates_uptime_host_during_sync (0.03s)
--- PASS: TestUptimeService_HostLevelCheck/groups_multiple_services_on_same_host (0.04s)
=== RUN TestFormatDuration
--- PASS: TestFormatDuration (0.00s)
=== RUN TestUptimeService_SyncMonitorForHost
=== RUN TestUptimeService_SyncMonitorForHost/updates_monitor_when_proxy_host_is_edited
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.142ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.105ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "10.0.0.1" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:19:17Z" level=info msg="Created UptimeHost" host=10.0.0.1 host_id=ec41d123-8daf-499f-84da-d1991ab2db39
=== RUN TestUptimeService_SyncMonitorForHost/returns_nil_when_no_monitor_exists
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:1004 record not found
[0.139ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
=== RUN TestUptimeService_SyncMonitorForHost/returns_error_when_host_does_not_exist
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:999 record not found
[0.131ms] [rows:0] SELECT * FROM `proxy_hosts` WHERE `proxy_hosts`.`id` = 99999 ORDER BY `proxy_hosts`.`id` LIMIT 1
=== RUN TestUptimeService_SyncMonitorForHost/uses_domain_name_when_proxy_host_name_is_empty
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.139ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.091ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "10.0.0.4" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:19:17Z" level=info msg="Created UptimeHost" host=10.0.0.4 host_id=a829a6d4-3a36-4c53-b23d-d77baba6f48b
=== RUN TestUptimeService_SyncMonitorForHost/handles_multiple_domains_correctly
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:135 record not found
[0.162ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE proxy_host_id = 1 ORDER BY `uptime_monitors`.`id` LIMIT 1
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:309 record not found
[0.126ms] [rows:0] SELECT * FROM `uptime_hosts` WHERE host = "10.0.0.5" ORDER BY `uptime_hosts`.`id` LIMIT 1
time="2026-01-10T02:19:17Z" level=info msg="Created UptimeHost" host=10.0.0.5 host_id=0ff2ee7f-55d2-4b95-9e5a-21d3039dc2e4
--- PASS: TestUptimeService_SyncMonitorForHost (0.18s)
--- PASS: TestUptimeService_SyncMonitorForHost/updates_monitor_when_proxy_host_is_edited (0.04s)
--- PASS: TestUptimeService_SyncMonitorForHost/returns_nil_when_no_monitor_exists (0.04s)
--- PASS: TestUptimeService_SyncMonitorForHost/returns_error_when_host_does_not_exist (0.04s)
--- PASS: TestUptimeService_SyncMonitorForHost/uses_domain_name_when_proxy_host_name_is_empty (0.04s)
--- PASS: TestUptimeService_SyncMonitorForHost/handles_multiple_domains_correctly (0.04s)
=== RUN TestUptimeService_DeleteMonitor
=== RUN TestUptimeService_DeleteMonitor/deletes_monitor_and_heartbeats
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service_test.go:1416 record not found
[0.082ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE id = "delete-test-1" ORDER BY `uptime_monitors`.`id` LIMIT 1
=== RUN TestUptimeService_DeleteMonitor/returns_error_for_non-existent_monitor
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service.go:1087 record not found
[0.081ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE id = "non-existent-id" ORDER BY `uptime_monitors`.`id` LIMIT 1
=== RUN TestUptimeService_DeleteMonitor/deletes_monitor_without_heartbeats
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service_test.go:1456 record not found
[0.080ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE id = "delete-no-hb" ORDER BY `uptime_monitors`.`id` LIMIT 1
--- PASS: TestUptimeService_DeleteMonitor (0.10s)
--- PASS: TestUptimeService_DeleteMonitor/deletes_monitor_and_heartbeats (0.04s)
--- PASS: TestUptimeService_DeleteMonitor/returns_error_for_non-existent_monitor (0.03s)
--- PASS: TestUptimeService_DeleteMonitor/deletes_monitor_without_heartbeats (0.03s)
=== RUN TestUptimeService_UpdateMonitor_EnabledField
--- PASS: TestUptimeService_UpdateMonitor_EnabledField (0.03s)
=== RUN TestExtractPort
=== RUN TestExtractPort/http_url_default
=== RUN TestExtractPort/https_url_default
=== RUN TestExtractPort/http_with_port
=== RUN TestExtractPort/https_with_port
=== RUN TestExtractPort/host:port
=== RUN TestExtractPort/plain_host
=== RUN TestExtractPort/localhost_with_port
=== RUN TestExtractPort/ip_with_port
=== RUN TestExtractPort/ipv6_with_port
--- PASS: TestExtractPort (0.00s)
--- PASS: TestExtractPort/http_url_default (0.00s)
--- PASS: TestExtractPort/https_url_default (0.00s)
--- PASS: TestExtractPort/http_with_port (0.00s)
--- PASS: TestExtractPort/https_with_port (0.00s)
--- PASS: TestExtractPort/host:port (0.00s)
--- PASS: TestExtractPort/plain_host (0.00s)
--- PASS: TestExtractPort/localhost_with_port (0.00s)
--- PASS: TestExtractPort/ip_with_port (0.00s)
--- PASS: TestExtractPort/ipv6_with_port (0.00s)
=== RUN TestUpdateMonitorEnabled_Unit
--- PASS: TestUpdateMonitorEnabled_Unit (0.02s)
=== RUN TestDeleteMonitorDeletesHeartbeats_Unit
2026/01/10 02:19:17 /projects/Charon/backend/internal/services/uptime_service_unit_test.go:77 record not found
[0.070ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE id = "c57faec9-44b0-4ec7-a50e-7acefc4aeba6" ORDER BY `uptime_monitors`.`id` LIMIT 1
--- PASS: TestDeleteMonitorDeletesHeartbeats_Unit (0.06s)
=== RUN TestCheckMonitor_PublicAPI
--- PASS: TestCheckMonitor_PublicAPI (0.23s)
=== RUN TestCheckMonitor_InvalidURL
--- PASS: TestCheckMonitor_InvalidURL (0.08s)
=== RUN TestCheckMonitor_TCPSuccess
--- PASS: TestCheckMonitor_TCPSuccess (0.08s)
=== RUN TestCheckMonitor_TCPFailure
--- PASS: TestCheckMonitor_TCPFailure (10.07s)
=== RUN TestCheckMonitor_UnknownType
--- PASS: TestCheckMonitor_UnknownType (0.06s)
=== RUN TestDeleteMonitor_NonExistent
2026/01/10 02:19:28 /projects/Charon/backend/internal/services/uptime_service.go:1087 record not found
[0.101ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE id = "non-existent-id" ORDER BY `uptime_monitors`.`id` LIMIT 1
--- PASS: TestDeleteMonitor_NonExistent (0.06s)
=== RUN TestUpdateMonitor_NonExistent
2026/01/10 02:19:28 /projects/Charon/backend/internal/services/uptime_service.go:1059 record not found
[0.111ms] [rows:0] SELECT * FROM `uptime_monitors` WHERE id = "non-existent-id" ORDER BY `uptime_monitors`.`id` LIMIT 1
--- PASS: TestUpdateMonitor_NonExistent (0.08s)
=== RUN TestNewWebSocketTracker
--- PASS: TestNewWebSocketTracker (0.00s)
=== RUN TestWebSocketTracker_Register
--- PASS: TestWebSocketTracker_Register (0.00s)
=== RUN TestWebSocketTracker_Unregister
--- PASS: TestWebSocketTracker_Unregister (0.00s)
=== RUN TestWebSocketTracker_UnregisterNonExistent
--- PASS: TestWebSocketTracker_UnregisterNonExistent (0.00s)
=== RUN TestWebSocketTracker_UpdateActivity
--- PASS: TestWebSocketTracker_UpdateActivity (0.01s)
=== RUN TestWebSocketTracker_UpdateActivityNonExistent
--- PASS: TestWebSocketTracker_UpdateActivityNonExistent (0.00s)
=== RUN TestWebSocketTracker_GetAllConnections
--- PASS: TestWebSocketTracker_GetAllConnections (0.00s)
=== RUN TestWebSocketTracker_GetStats
--- PASS: TestWebSocketTracker_GetStats (0.00s)
=== RUN TestWebSocketTracker_GetStatsEmpty
--- PASS: TestWebSocketTracker_GetStatsEmpty (0.00s)
=== RUN TestWebSocketTracker_ConcurrentAccess
--- PASS: TestWebSocketTracker_ConcurrentAccess (0.00s)
=== RUN TestCredentialService_Create
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_Create (0.01s)
=== RUN TestCredentialService_Create_MultiCredentialNotEnabled
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_Create_MultiCredentialNotEnabled (0.01s)
=== RUN TestCredentialService_Create_InvalidCredentials
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_Create_InvalidCredentials (0.01s)
=== RUN TestCredentialService_List
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
2026/01/10 02:19:28 /projects/Charon/backend/internal/services/credential_service.go:196 database table is locked
[0.253ms] [rows:0] INSERT INTO `dns_provider_credentials` (`uuid`,`dns_provider_id`,`label`,`zone_filter`,`enabled`,`credentials_encrypted`,`key_version`,`propagation_timeout`,`polling_interval`,`last_used_at`,`success_count`,`failure_count`,`last_error`,`created_at`,`updated_at`) VALUES ("a60759d1-40a0-4022-8e9f-5a06705b0176",1,"Credential B","",true,"BYNMQRrcsf8KNGUlXIMrgWbXW0atvE1fizPtKfyYxLLKfiXTu4RhMoSIQGwL9baDAA==",1,120,5,NULL,0,0,"","2026-01-10 02:19:28.539","2026-01-10 02:19:28.539") RETURNING `id`
credential_service_test.go:149:
Error Trace: /projects/Charon/backend/internal/services/credential_service_test.go:149
Error: Received unexpected error:
database table is locked
Test: TestCredentialService_List
--- FAIL: TestCredentialService_List (0.01s)
=== RUN TestCredentialService_Get
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_Get (0.01s)
=== RUN TestCredentialService_Get_NotFound
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
2026/01/10 02:19:28 /projects/Charon/backend/internal/services/credential_service.go:111 record not found
[0.308ms] [rows:0] SELECT * FROM `dns_provider_credentials` WHERE id = 9999 AND dns_provider_id = 1 ORDER BY `dns_provider_credentials`.`id` LIMIT 1
--- PASS: TestCredentialService_Get_NotFound (0.01s)
=== RUN TestCredentialService_Update
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_Update (0.01s)
=== RUN TestCredentialService_Delete
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
2026/01/10 02:19:28 /projects/Charon/backend/internal/services/credential_service.go:111 record not found
[0.069ms] [rows:0] SELECT * FROM `dns_provider_credentials` WHERE id = 1 AND dns_provider_id = 1 ORDER BY `dns_provider_credentials`.`id` LIMIT 1
--- PASS: TestCredentialService_Delete (0.01s)
=== RUN TestCredentialService_Test
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_Test (0.01s)
=== RUN TestCredentialService_GetCredentialForDomain_ExactMatch
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
2026/01/10 02:19:28 /projects/Charon/backend/internal/services/credential_service.go:196 database table is locked
[0.286ms] [rows:0] INSERT INTO `dns_provider_credentials` (`uuid`,`dns_provider_id`,`label`,`zone_filter`,`enabled`,`credentials_encrypted`,`key_version`,`propagation_timeout`,`polling_interval`,`last_used_at`,`success_count`,`failure_count`,`last_error`,`created_at`,`updated_at`) VALUES ("86f40fa1-bee2-4664-b3d1-d7bd1544248c",1,"Catch All","",true,"l3KUYfElVhFaDhUFgA45u5QLw4A067zoEoWT3yvrmgFeja/XfgPXsa+lgKh33p/YsmgSbR8ZRZA7Hw==",1,120,5,NULL,0,0,"","2026-01-10 02:19:28.578","2026-01-10 02:19:28.578") RETURNING `id`
credential_service_test.go:283:
Error Trace: /projects/Charon/backend/internal/services/credential_service_test.go:283
Error: Received unexpected error:
database table is locked
Test: TestCredentialService_GetCredentialForDomain_ExactMatch
--- FAIL: TestCredentialService_GetCredentialForDomain_ExactMatch (0.01s)
=== RUN TestCredentialService_GetCredentialForDomain_WildcardMatch
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_GetCredentialForDomain_WildcardMatch (0.01s)
=== RUN TestCredentialService_GetCredentialForDomain_CatchAll
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_GetCredentialForDomain_CatchAll (0.01s)
=== RUN TestCredentialService_GetCredentialForDomain_NoMatch
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_GetCredentialForDomain_NoMatch (0.01s)
=== RUN TestCredentialService_GetCredentialForDomain_MultiCredNotEnabled
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_GetCredentialForDomain_MultiCredNotEnabled (0.01s)
=== RUN TestCredentialService_GetCredentialForDomain_MultipleZones
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_GetCredentialForDomain_MultipleZones (0.01s)
=== RUN TestCredentialService_EnableMultiCredentials
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_EnableMultiCredentials (0.01s)
=== RUN TestCredentialService_EnableMultiCredentials_AlreadyEnabled
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_EnableMultiCredentials_AlreadyEnabled (0.01s)
=== RUN TestCredentialService_EnableMultiCredentials_NoCredentials
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_EnableMultiCredentials_NoCredentials (0.01s)
=== RUN TestCredentialService_GetCredentialForDomain_IDN
Warning: RotationService initialization failed, using basic encryption: CHARON_ENCRYPTION_KEY is required
--- PASS: TestCredentialService_GetCredentialForDomain_IDN (0.01s)
=== CONT TestBackupService_GetAvailableSpace
=== CONT TestLogWatcherConcurrentSubscribers
=== RUN TestBackupService_GetAvailableSpace/returns_space_for_existing_directory
=== PAUSE TestBackupService_GetAvailableSpace/returns_space_for_existing_directory
=== CONT TestLogWatcherIntegration
time="2026-01-10T02:19:28Z" level=info msg="LogWatcher started" path=/tmp/TestLogWatcherIntegration833592932/001/access.log
=== CONT TestHasHeader
--- PASS: TestHasHeader (0.00s)
=== RUN TestBackupService_GetAvailableSpace/errors_for_missing_directory
=== CONT TestParseLogEntryValidJSON
--- PASS: TestParseLogEntryValidJSON (0.00s)
=== CONT TestParseLogEntry401Auth
--- PASS: TestParseLogEntry401Auth (0.00s)
=== PAUSE TestBackupService_GetAvailableSpace/errors_for_missing_directory
=== CONT TestParseLogEntry403CrowdSec
--- PASS: TestParseLogEntry403CrowdSec (0.00s)
=== CONT TestParseLogEntry500Error
--- PASS: TestParseLogEntry500Error (0.00s)
=== CONT TestParseLogEntryBlockedByRateLimit
--- PASS: TestParseLogEntryBlockedByRateLimit (0.00s)
=== CONT TestParseLogEntryBlockedByWAF
--- PASS: TestParseLogEntryBlockedByWAF (0.00s)
=== CONT TestParseLogEntryInvalidJSON
=== RUN TestParseLogEntryInvalidJSON/empty
=== CONT TestUptimeService_sendRecoveryNotification
=== RUN TestParseLogEntryInvalidJSON/not_json
=== RUN TestParseLogEntryInvalidJSON/incomplete_json
=== RUN TestParseLogEntryInvalidJSON/array_instead_of_object
--- PASS: TestParseLogEntryInvalidJSON (0.01s)
--- PASS: TestParseLogEntryInvalidJSON/empty (0.00s)
--- PASS: TestParseLogEntryInvalidJSON/not_json (0.00s)
--- PASS: TestParseLogEntryInvalidJSON/incomplete_json (0.00s)
--- PASS: TestParseLogEntryInvalidJSON/array_instead_of_object (0.00s)
=== CONT TestDetectSecurityEvent_403WithoutHeaders
--- PASS: TestDetectSecurityEvent_403WithoutHeaders (0.00s)
=== CONT TestNotificationService_TemplateCRUD
--- PASS: TestUptimeService_sendRecoveryNotification (0.01s)
=== CONT TestDetectSecurityEvent_RateLimitPartialHeaders
--- PASS: TestDetectSecurityEvent_RateLimitPartialHeaders (0.00s)
=== CONT TestDetectSecurityEvent_RateLimitAllHeaders
--- PASS: TestDetectSecurityEvent_RateLimitAllHeaders (0.00s)
=== CONT TestDetectSecurityEvent_ACLBlockedHeader
--- PASS: TestDetectSecurityEvent_ACLBlockedHeader (0.00s)
=== CONT TestDetectSecurityEvent_CrowdSecWithOriginHeader
--- PASS: TestDetectSecurityEvent_CrowdSecWithOriginHeader (0.00s)
=== CONT TestDetectSecurityEvent_CrowdSecWithDecisionHeader
--- PASS: TestDetectSecurityEvent_CrowdSecWithDecisionHeader (0.00s)
=== CONT TestDetectSecurityEvent_ACLDeniedHeader
--- PASS: TestDetectSecurityEvent_ACLDeniedHeader (0.00s)
=== CONT TestDetectSecurityEvent_WAFWithCorazaRuleId
--- PASS: TestDetectSecurityEvent_WAFWithCorazaRuleId (0.00s)
=== CONT TestLogWatcher_ReadLoop_EOFRetry
time="2026-01-10T02:19:28Z" level=info msg="LogWatcher started" path=/tmp/TestLogWatcher_ReadLoop_EOFRetry3222960328/001/access.log
--- PASS: TestNotificationService_TemplateCRUD (0.01s)
=== CONT TestMin
--- PASS: TestMin (0.00s)
=== CONT TestDetectSecurityEvent_WAFWithCorazaId
--- PASS: TestDetectSecurityEvent_WAFWithCorazaId (0.00s)
=== CONT TestLogWatcherMissingFile
time="2026-01-10T02:19:28Z" level=info msg="LogWatcher started" path=/tmp/TestLogWatcherMissingFile4258081303/001/nonexistent/access.log
--- PASS: TestLogWatcherConcurrentSubscribers (0.02s)
=== CONT TestLogWatcherBroadcastNonBlocking
--- PASS: TestLogWatcherBroadcastNonBlocking (0.00s)
=== CONT TestLogWatcherSubscribeUnsubscribe
--- PASS: TestLogWatcherSubscribeUnsubscribe (0.00s)
=== CONT TestLogWatcherBroadcast
--- PASS: TestLogWatcherBroadcast (0.00s)
=== CONT TestLogWatcherStartStop
time="2026-01-10T02:19:28Z" level=info msg="LogWatcher started" path=/tmp/TestLogWatcherStartStop1684556410/001/access.log
time="2026-01-10T02:19:28Z" level=info msg="LogWatcher stopped"
--- PASS: TestLogWatcherStartStop (0.00s)
=== CONT TestNewLogWatcher
--- PASS: TestNewLogWatcher (0.00s)
=== CONT TestBackupService_GetAvailableSpace/returns_space_for_existing_directory
=== CONT TestBackupService_GetAvailableSpace/errors_for_missing_directory
--- PASS: TestBackupService_GetAvailableSpace (0.00s)
--- PASS: TestBackupService_GetAvailableSpace/returns_space_for_existing_directory (0.00s)
--- PASS: TestBackupService_GetAvailableSpace/errors_for_missing_directory (0.00s)
time="2026-01-10T02:19:28Z" level=info msg="LogWatcher stopped"
--- PASS: TestLogWatcherIntegration (0.20s)
time="2026-01-10T02:19:28Z" level=info msg="LogWatcher stopped"
--- PASS: TestLogWatcherMissingFile (0.20s)
time="2026-01-10T02:19:28Z" level=info msg="LogWatcher stopped"
--- PASS: TestLogWatcher_ReadLoop_EOFRetry (0.20s)
FAIL
coverage: 80.8% of statements
FAIL github.com/Wikid82/charon/backend/internal/services 111.017s
=== RUN TestWithTx_Success
--- PASS: TestWithTx_Success (0.00s)
=== RUN TestWithTx_Panic
--- PASS: TestWithTx_Panic (0.00s)
=== RUN TestWithTx_MultipleOperations
--- PASS: TestWithTx_MultipleOperations (0.00s)
=== RUN TestGetTestTx_Cleanup
=== RUN TestGetTestTx_Cleanup/Subtest
--- PASS: TestGetTestTx_Cleanup (0.01s)
--- PASS: TestGetTestTx_Cleanup/Subtest (0.00s)
=== RUN TestGetTestTx_MultipleTransactions
=== RUN TestGetTestTx_MultipleTransactions/Transaction1
=== RUN TestGetTestTx_MultipleTransactions/Transaction2
--- PASS: TestGetTestTx_MultipleTransactions (0.00s)
--- PASS: TestGetTestTx_MultipleTransactions/Transaction1 (0.00s)
--- PASS: TestGetTestTx_MultipleTransactions/Transaction2 (0.00s)
=== RUN TestGetTestTx_UsageInMultipleFunctions
=== RUN TestGetTestTx_UsageInMultipleFunctions/MultiFunction
--- PASS: TestGetTestTx_UsageInMultipleFunctions (0.00s)
--- PASS: TestGetTestTx_UsageInMultipleFunctions/MultiFunction (0.00s)
=== RUN TestGetTestTx_Parallel
=== RUN TestGetTestTx_Parallel/Isolation1
=== RUN TestGetTestTx_Parallel/Isolation2
--- PASS: TestGetTestTx_Parallel (0.00s)
--- PASS: TestGetTestTx_Parallel/Isolation1 (0.00s)
--- PASS: TestGetTestTx_Parallel/Isolation2 (0.00s)
=== RUN TestGetTestTx_WithActualTestFailure
=== RUN TestGetTestTx_WithActualTestFailure/FailingSubtest
--- PASS: TestGetTestTx_WithActualTestFailure (0.00s)
--- PASS: TestGetTestTx_WithActualTestFailure/FailingSubtest (0.00s)
PASS
coverage: 100.0% of statements
ok github.com/Wikid82/charon/backend/internal/testutil (cached) coverage: 100.0% of statements
? github.com/Wikid82/charon/backend/internal/trace [no test files]
=== RUN TestConstantTimeCompare
=== PAUSE TestConstantTimeCompare
=== RUN TestConstantTimeCompareBytes
=== PAUSE TestConstantTimeCompareBytes
=== RUN TestSanitizeForLog
=== PAUSE TestSanitizeForLog
=== CONT TestSanitizeForLog
=== RUN TestSanitizeForLog/empty_string
=== CONT TestConstantTimeCompareBytes
=== RUN TestConstantTimeCompareBytes/equal_bytes
=== CONT TestConstantTimeCompare
=== RUN TestConstantTimeCompare/equal_strings
=== RUN TestSanitizeForLog/clean_string
=== RUN TestConstantTimeCompare/different_strings
=== RUN TestConstantTimeCompareBytes/different_bytes
=== RUN TestConstantTimeCompare/different_lengths
=== RUN TestConstantTimeCompareBytes/different_lengths
=== RUN TestSanitizeForLog/string_with_newline
=== RUN TestConstantTimeCompareBytes/empty_slices
=== RUN TestSanitizeForLog/string_with_carriage_return_and_newline
=== RUN TestConstantTimeCompare/empty_strings
=== RUN TestConstantTimeCompareBytes/nil_slices
--- PASS: TestConstantTimeCompareBytes (0.00s)
--- PASS: TestConstantTimeCompareBytes/equal_bytes (0.00s)
--- PASS: TestConstantTimeCompareBytes/different_bytes (0.00s)
--- PASS: TestConstantTimeCompareBytes/different_lengths (0.00s)
--- PASS: TestConstantTimeCompareBytes/empty_slices (0.00s)
--- PASS: TestConstantTimeCompareBytes/nil_slices (0.00s)
=== RUN TestSanitizeForLog/string_with_multiple_newlines
=== RUN TestConstantTimeCompare/one_empty
=== RUN TestConstantTimeCompare/unicode_equal
=== RUN TestSanitizeForLog/string_with_control_characters
=== RUN TestConstantTimeCompare/unicode_different
=== RUN TestSanitizeForLog/string_with_DEL_character_(0x7F)
=== RUN TestConstantTimeCompare/special_chars_equal
=== RUN TestSanitizeForLog/complex_string_with_mixed_control_chars
=== RUN TestConstantTimeCompare/whitespace_matters
--- PASS: TestConstantTimeCompare (0.00s)
--- PASS: TestConstantTimeCompare/equal_strings (0.00s)
--- PASS: TestConstantTimeCompare/different_strings (0.00s)
--- PASS: TestConstantTimeCompare/different_lengths (0.00s)
--- PASS: TestConstantTimeCompare/empty_strings (0.00s)
--- PASS: TestConstantTimeCompare/one_empty (0.00s)
--- PASS: TestConstantTimeCompare/unicode_equal (0.00s)
--- PASS: TestConstantTimeCompare/unicode_different (0.00s)
--- PASS: TestConstantTimeCompare/special_chars_equal (0.00s)
--- PASS: TestConstantTimeCompare/whitespace_matters (0.00s)
=== RUN TestSanitizeForLog/string_with_tabs_(0x09_is_control_char)
=== RUN TestSanitizeForLog/string_with_only_control_chars
--- PASS: TestSanitizeForLog (0.01s)
--- PASS: TestSanitizeForLog/empty_string (0.00s)
--- PASS: TestSanitizeForLog/clean_string (0.00s)
--- PASS: TestSanitizeForLog/string_with_newline (0.00s)
--- PASS: TestSanitizeForLog/string_with_carriage_return_and_newline (0.00s)
--- PASS: TestSanitizeForLog/string_with_multiple_newlines (0.00s)
--- PASS: TestSanitizeForLog/string_with_control_characters (0.00s)
--- PASS: TestSanitizeForLog/string_with_DEL_character_(0x7F) (0.00s)
--- PASS: TestSanitizeForLog/complex_string_with_mixed_control_chars (0.00s)
--- PASS: TestSanitizeForLog/string_with_tabs_(0x09_is_control_char) (0.00s)
--- PASS: TestSanitizeForLog/string_with_only_control_chars (0.00s)
PASS
coverage: 100.0% of statements
ok github.com/Wikid82/charon/backend/internal/util (cached) coverage: 100.0% of statements
=== RUN TestIsPrivateIP
=== RUN TestIsPrivateIP/10.0.0.1_is_private
=== RUN TestIsPrivateIP/10.255.255.255_is_private
=== RUN TestIsPrivateIP/10.10.10.10_is_private
=== RUN TestIsPrivateIP/172.16.0.1_is_private
=== RUN TestIsPrivateIP/172.31.255.255_is_private
=== RUN TestIsPrivateIP/172.20.0.1_is_private
=== RUN TestIsPrivateIP/192.168.1.1_is_private
=== RUN TestIsPrivateIP/192.168.0.1_is_private
=== RUN TestIsPrivateIP/192.168.255.255_is_private
=== RUN TestIsPrivateIP/172.17.0.2_is_private
=== RUN TestIsPrivateIP/172.18.0.5_is_private
=== RUN TestIsPrivateIP/8.8.8.8_is_public
=== RUN TestIsPrivateIP/1.1.1.1_is_public
=== RUN TestIsPrivateIP/142.250.80.14_is_public
=== RUN TestIsPrivateIP/203.0.113.50_is_public
=== RUN TestIsPrivateIP/172.15.0.1_is_public
=== RUN TestIsPrivateIP/172.32.0.1_is_public
=== RUN TestIsPrivateIP/nginx_hostname
=== RUN TestIsPrivateIP/my-app_hostname
=== RUN TestIsPrivateIP/app.local_hostname
=== RUN TestIsPrivateIP/example.com_hostname
=== RUN TestIsPrivateIP/my-container.internal_hostname
=== RUN TestIsPrivateIP/empty_string
=== RUN TestIsPrivateIP/malformed_IP
=== RUN TestIsPrivateIP/too_many_octets
=== RUN TestIsPrivateIP/negative_octet
=== RUN TestIsPrivateIP/octet_out_of_range
=== RUN TestIsPrivateIP/letters_in_IP
=== RUN TestIsPrivateIP/IPv6_address
=== RUN TestIsPrivateIP/IPv6_full_address
=== RUN TestIsPrivateIP/localhost_127.0.0.1
=== RUN TestIsPrivateIP/0.0.0.0
--- PASS: TestIsPrivateIP (0.00s)
--- PASS: TestIsPrivateIP/10.0.0.1_is_private (0.00s)
--- PASS: TestIsPrivateIP/10.255.255.255_is_private (0.00s)
--- PASS: TestIsPrivateIP/10.10.10.10_is_private (0.00s)
--- PASS: TestIsPrivateIP/172.16.0.1_is_private (0.00s)
--- PASS: TestIsPrivateIP/172.31.255.255_is_private (0.00s)
--- PASS: TestIsPrivateIP/172.20.0.1_is_private (0.00s)
--- PASS: TestIsPrivateIP/192.168.1.1_is_private (0.00s)
--- PASS: TestIsPrivateIP/192.168.0.1_is_private (0.00s)
--- PASS: TestIsPrivateIP/192.168.255.255_is_private (0.00s)
--- PASS: TestIsPrivateIP/172.17.0.2_is_private (0.00s)
--- PASS: TestIsPrivateIP/172.18.0.5_is_private (0.00s)
--- PASS: TestIsPrivateIP/8.8.8.8_is_public (0.00s)
--- PASS: TestIsPrivateIP/1.1.1.1_is_public (0.00s)
--- PASS: TestIsPrivateIP/142.250.80.14_is_public (0.00s)
--- PASS: TestIsPrivateIP/203.0.113.50_is_public (0.00s)
--- PASS: TestIsPrivateIP/172.15.0.1_is_public (0.00s)
--- PASS: TestIsPrivateIP/172.32.0.1_is_public (0.00s)
--- PASS: TestIsPrivateIP/nginx_hostname (0.00s)
--- PASS: TestIsPrivateIP/my-app_hostname (0.00s)
--- PASS: TestIsPrivateIP/app.local_hostname (0.00s)
--- PASS: TestIsPrivateIP/example.com_hostname (0.00s)
--- PASS: TestIsPrivateIP/my-container.internal_hostname (0.00s)
--- PASS: TestIsPrivateIP/empty_string (0.00s)
--- PASS: TestIsPrivateIP/malformed_IP (0.00s)
--- PASS: TestIsPrivateIP/too_many_octets (0.00s)
--- PASS: TestIsPrivateIP/negative_octet (0.00s)
--- PASS: TestIsPrivateIP/octet_out_of_range (0.00s)
--- PASS: TestIsPrivateIP/letters_in_IP (0.00s)
--- PASS: TestIsPrivateIP/IPv6_address (0.00s)
--- PASS: TestIsPrivateIP/IPv6_full_address (0.00s)
--- PASS: TestIsPrivateIP/localhost_127.0.0.1 (0.00s)
--- PASS: TestIsPrivateIP/0.0.0.0 (0.00s)
=== RUN TestIsDockerBridgeIP
=== RUN TestIsDockerBridgeIP/172.17.0.1_is_Docker_bridge
=== RUN TestIsDockerBridgeIP/172.17.0.2_is_Docker_bridge
=== RUN TestIsDockerBridgeIP/172.17.255.255_is_Docker_bridge
=== RUN TestIsDockerBridgeIP/172.18.0.1_is_Docker_bridge
=== RUN TestIsDockerBridgeIP/172.18.0.5_is_Docker_bridge
=== RUN TestIsDockerBridgeIP/172.20.0.1_is_Docker_bridge
=== RUN TestIsDockerBridgeIP/172.31.0.1_is_Docker_bridge
=== RUN TestIsDockerBridgeIP/172.31.255.255_is_Docker_bridge
=== RUN TestIsDockerBridgeIP/172.16.0.1_is_in_Docker_range
=== RUN TestIsDockerBridgeIP/10.0.0.1_is_not_Docker_bridge
=== RUN TestIsDockerBridgeIP/192.168.1.1_is_not_Docker_bridge
=== RUN TestIsDockerBridgeIP/8.8.8.8_is_public
=== RUN TestIsDockerBridgeIP/1.1.1.1_is_public
=== RUN TestIsDockerBridgeIP/172.15.0.1_is_outside_Docker_range
=== RUN TestIsDockerBridgeIP/172.32.0.1_is_outside_Docker_range
=== RUN TestIsDockerBridgeIP/nginx_hostname
=== RUN TestIsDockerBridgeIP/my-app_hostname
=== RUN TestIsDockerBridgeIP/container-name_hostname
=== RUN TestIsDockerBridgeIP/empty_string
=== RUN TestIsDockerBridgeIP/malformed_IP
=== RUN TestIsDockerBridgeIP/too_many_octets
=== RUN TestIsDockerBridgeIP/letters_in_IP
=== RUN TestIsDockerBridgeIP/IPv6_address
=== RUN TestIsDockerBridgeIP/localhost_127.0.0.1
=== RUN TestIsDockerBridgeIP/0.0.0.0
--- PASS: TestIsDockerBridgeIP (0.00s)
--- PASS: TestIsDockerBridgeIP/172.17.0.1_is_Docker_bridge (0.00s)
--- PASS: TestIsDockerBridgeIP/172.17.0.2_is_Docker_bridge (0.00s)
--- PASS: TestIsDockerBridgeIP/172.17.255.255_is_Docker_bridge (0.00s)
--- PASS: TestIsDockerBridgeIP/172.18.0.1_is_Docker_bridge (0.00s)
--- PASS: TestIsDockerBridgeIP/172.18.0.5_is_Docker_bridge (0.00s)
--- PASS: TestIsDockerBridgeIP/172.20.0.1_is_Docker_bridge (0.00s)
--- PASS: TestIsDockerBridgeIP/172.31.0.1_is_Docker_bridge (0.00s)
--- PASS: TestIsDockerBridgeIP/172.31.255.255_is_Docker_bridge (0.00s)
--- PASS: TestIsDockerBridgeIP/172.16.0.1_is_in_Docker_range (0.00s)
--- PASS: TestIsDockerBridgeIP/10.0.0.1_is_not_Docker_bridge (0.00s)
--- PASS: TestIsDockerBridgeIP/192.168.1.1_is_not_Docker_bridge (0.00s)
--- PASS: TestIsDockerBridgeIP/8.8.8.8_is_public (0.00s)
--- PASS: TestIsDockerBridgeIP/1.1.1.1_is_public (0.00s)
--- PASS: TestIsDockerBridgeIP/172.15.0.1_is_outside_Docker_range (0.00s)
--- PASS: TestIsDockerBridgeIP/172.32.0.1_is_outside_Docker_range (0.00s)
--- PASS: TestIsDockerBridgeIP/nginx_hostname (0.00s)
--- PASS: TestIsDockerBridgeIP/my-app_hostname (0.00s)
--- PASS: TestIsDockerBridgeIP/container-name_hostname (0.00s)
--- PASS: TestIsDockerBridgeIP/empty_string (0.00s)
--- PASS: TestIsDockerBridgeIP/malformed_IP (0.00s)
--- PASS: TestIsDockerBridgeIP/too_many_octets (0.00s)
--- PASS: TestIsDockerBridgeIP/letters_in_IP (0.00s)
--- PASS: TestIsDockerBridgeIP/IPv6_address (0.00s)
--- PASS: TestIsDockerBridgeIP/localhost_127.0.0.1 (0.00s)
--- PASS: TestIsDockerBridgeIP/0.0.0.0 (0.00s)
=== RUN TestIsPrivateIP_IPv4Mapped
=== RUN TestIsPrivateIP_IPv4Mapped/::ffff:10.0.0.1_mapped
=== RUN TestIsPrivateIP_IPv4Mapped/::ffff:192.168.1.1_mapped
=== RUN TestIsPrivateIP_IPv4Mapped/::ffff:8.8.8.8_mapped
--- PASS: TestIsPrivateIP_IPv4Mapped (0.00s)
--- PASS: TestIsPrivateIP_IPv4Mapped/::ffff:10.0.0.1_mapped (0.00s)
--- PASS: TestIsPrivateIP_IPv4Mapped/::ffff:192.168.1.1_mapped (0.00s)
--- PASS: TestIsPrivateIP_IPv4Mapped/::ffff:8.8.8.8_mapped (0.00s)
=== RUN TestIsPrivateIP_CIDRParseError
=== RUN TestIsPrivateIP_CIDRParseError/10.0.0.1/8
=== RUN TestIsPrivateIP_CIDRParseError/10.0.0.256
=== RUN TestIsPrivateIP_CIDRParseError/999.999.999.999
=== RUN TestIsPrivateIP_CIDRParseError/10.0.0
=== RUN TestIsPrivateIP_CIDRParseError/not-an-ip
=== RUN TestIsPrivateIP_CIDRParseError/#00
=== RUN TestIsPrivateIP_CIDRParseError/10.0.0.1.1
--- PASS: TestIsPrivateIP_CIDRParseError (0.00s)
--- PASS: TestIsPrivateIP_CIDRParseError/10.0.0.1/8 (0.00s)
--- PASS: TestIsPrivateIP_CIDRParseError/10.0.0.256 (0.00s)
--- PASS: TestIsPrivateIP_CIDRParseError/999.999.999.999 (0.00s)
--- PASS: TestIsPrivateIP_CIDRParseError/10.0.0 (0.00s)
--- PASS: TestIsPrivateIP_CIDRParseError/not-an-ip (0.00s)
--- PASS: TestIsPrivateIP_CIDRParseError/#00 (0.00s)
--- PASS: TestIsPrivateIP_CIDRParseError/10.0.0.1.1 (0.00s)
=== RUN TestIsDockerBridgeIP_CIDRParseError
=== RUN TestIsDockerBridgeIP_CIDRParseError/172.17.0.1/16
=== RUN TestIsDockerBridgeIP_CIDRParseError/172.17.0.256
=== RUN TestIsDockerBridgeIP_CIDRParseError/999.999.999.999
=== RUN TestIsDockerBridgeIP_CIDRParseError/172.17
=== RUN TestIsDockerBridgeIP_CIDRParseError/not-an-ip
=== RUN TestIsDockerBridgeIP_CIDRParseError/#00
--- PASS: TestIsDockerBridgeIP_CIDRParseError (0.00s)
--- PASS: TestIsDockerBridgeIP_CIDRParseError/172.17.0.1/16 (0.00s)
--- PASS: TestIsDockerBridgeIP_CIDRParseError/172.17.0.256 (0.00s)
--- PASS: TestIsDockerBridgeIP_CIDRParseError/999.999.999.999 (0.00s)
--- PASS: TestIsDockerBridgeIP_CIDRParseError/172.17 (0.00s)
--- PASS: TestIsDockerBridgeIP_CIDRParseError/not-an-ip (0.00s)
--- PASS: TestIsDockerBridgeIP_CIDRParseError/#00 (0.00s)
=== RUN TestIsPrivateIP_IPv6Comprehensive
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_loopback
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_loopback_expanded
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local_2
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fc00
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fd00
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fdff
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_public_Google_DNS
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_public_Cloudflare
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_mapped_private
=== RUN TestIsPrivateIP_IPv6Comprehensive/IPv6_mapped_public
=== RUN TestIsPrivateIP_IPv6Comprehensive/Invalid_IPv6
=== RUN TestIsPrivateIP_IPv6Comprehensive/Incomplete_IPv6
--- PASS: TestIsPrivateIP_IPv6Comprehensive (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_loopback (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_loopback_expanded (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_link-local_2 (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fc00 (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fd00 (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_unique_local_fdff (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_public_Google_DNS (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_public_Cloudflare (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_mapped_private (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/IPv6_mapped_public (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/Invalid_IPv6 (0.00s)
--- PASS: TestIsPrivateIP_IPv6Comprehensive/Incomplete_IPv6 (0.00s)
=== RUN TestIsDockerBridgeIP_EdgeCases
=== RUN TestIsDockerBridgeIP_EdgeCases/Lower_boundary_-_1
=== RUN TestIsDockerBridgeIP_EdgeCases/Lower_boundary
=== RUN TestIsDockerBridgeIP_EdgeCases/Lower_boundary_+_1
=== RUN TestIsDockerBridgeIP_EdgeCases/Upper_boundary_-_1
=== RUN TestIsDockerBridgeIP_EdgeCases/Upper_boundary
=== RUN TestIsDockerBridgeIP_EdgeCases/Upper_boundary_+_1
=== RUN TestIsDockerBridgeIP_EdgeCases/Upper_boundary_+_2
=== RUN TestIsDockerBridgeIP_EdgeCases/Docker_default_bridge_start
=== RUN TestIsDockerBridgeIP_EdgeCases/Docker_default_bridge_gateway
=== RUN TestIsDockerBridgeIP_EdgeCases/Docker_default_bridge_host
=== RUN TestIsDockerBridgeIP_EdgeCases/Docker_default_bridge_end
=== RUN TestIsDockerBridgeIP_EdgeCases/User_network_1
=== RUN TestIsDockerBridgeIP_EdgeCases/User_network_2
=== RUN TestIsDockerBridgeIP_EdgeCases/User_network_30
=== RUN TestIsDockerBridgeIP_EdgeCases/User_network_31
=== RUN TestIsDockerBridgeIP_EdgeCases/172.0.0.1
=== RUN TestIsDockerBridgeIP_EdgeCases/172.15.0.1
=== RUN TestIsDockerBridgeIP_EdgeCases/172.32.0.1
=== RUN TestIsDockerBridgeIP_EdgeCases/172.255.255.255
--- PASS: TestIsDockerBridgeIP_EdgeCases (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/Lower_boundary_-_1 (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/Lower_boundary (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/Lower_boundary_+_1 (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/Upper_boundary_-_1 (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/Upper_boundary (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/Upper_boundary_+_1 (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/Upper_boundary_+_2 (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/Docker_default_bridge_start (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/Docker_default_bridge_gateway (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/Docker_default_bridge_host (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/Docker_default_bridge_end (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/User_network_1 (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/User_network_2 (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/User_network_30 (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/User_network_31 (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/172.0.0.1 (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/172.15.0.1 (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/172.32.0.1 (0.00s)
--- PASS: TestIsDockerBridgeIP_EdgeCases/172.255.255.255 (0.00s)
=== RUN TestTestURLConnectivity_Success
--- PASS: TestTestURLConnectivity_Success (0.00s)
=== RUN TestTestURLConnectivity_Redirect
--- PASS: TestTestURLConnectivity_Redirect (0.00s)
=== RUN TestTestURLConnectivity_TooManyRedirects
--- PASS: TestTestURLConnectivity_TooManyRedirects (0.00s)
=== RUN TestTestURLConnectivity_StatusCodes
=== RUN TestTestURLConnectivity_StatusCodes/200_OK
=== RUN TestTestURLConnectivity_StatusCodes/201_Created
=== RUN TestTestURLConnectivity_StatusCodes/204_No_Content
=== RUN TestTestURLConnectivity_StatusCodes/301_Moved_Permanently
=== RUN TestTestURLConnectivity_StatusCodes/302_Found
=== RUN TestTestURLConnectivity_StatusCodes/400_Bad_Request
=== RUN TestTestURLConnectivity_StatusCodes/401_Unauthorized
=== RUN TestTestURLConnectivity_StatusCodes/403_Forbidden
=== RUN TestTestURLConnectivity_StatusCodes/404_Not_Found
=== RUN TestTestURLConnectivity_StatusCodes/500_Internal_Server_Error
=== RUN TestTestURLConnectivity_StatusCodes/503_Service_Unavailable
--- PASS: TestTestURLConnectivity_StatusCodes (0.00s)
--- PASS: TestTestURLConnectivity_StatusCodes/200_OK (0.00s)
--- PASS: TestTestURLConnectivity_StatusCodes/201_Created (0.00s)
--- PASS: TestTestURLConnectivity_StatusCodes/204_No_Content (0.00s)
--- PASS: TestTestURLConnectivity_StatusCodes/301_Moved_Permanently (0.00s)
--- PASS: TestTestURLConnectivity_StatusCodes/302_Found (0.00s)
--- PASS: TestTestURLConnectivity_StatusCodes/400_Bad_Request (0.00s)
--- PASS: TestTestURLConnectivity_StatusCodes/401_Unauthorized (0.00s)
--- PASS: TestTestURLConnectivity_StatusCodes/403_Forbidden (0.00s)
--- PASS: TestTestURLConnectivity_StatusCodes/404_Not_Found (0.00s)
--- PASS: TestTestURLConnectivity_StatusCodes/500_Internal_Server_Error (0.00s)
--- PASS: TestTestURLConnectivity_StatusCodes/503_Service_Unavailable (0.00s)
=== RUN TestTestURLConnectivity_InvalidURL
=== RUN TestTestURLConnectivity_InvalidURL/Empty_URL
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"","request_id":"test-1768011443906317603","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_InvalidURL/Invalid_scheme
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"example.com","request_id":"test-1768011443906663215","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_InvalidURL/Malformed_URL
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"http://[invalid","request_id":"test-1768011443906774805","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_InvalidURL/No_scheme
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"","request_id":"test-1768011443906885665","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestTestURLConnectivity_InvalidURL (0.00s)
--- PASS: TestTestURLConnectivity_InvalidURL/Empty_URL (0.00s)
--- PASS: TestTestURLConnectivity_InvalidURL/Invalid_scheme (0.00s)
--- PASS: TestTestURLConnectivity_InvalidURL/Malformed_URL (0.00s)
--- PASS: TestTestURLConnectivity_InvalidURL/No_scheme (0.00s)
=== RUN TestTestURLConnectivity_DNSFailure
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"nonexistent-domain-12345.invalid","request_id":"test-1768011443907026076","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestTestURLConnectivity_DNSFailure (0.00s)
=== RUN TestTestURLConnectivity_Timeout
--- PASS: TestTestURLConnectivity_Timeout (0.00s)
=== RUN TestIsPrivateIP_PrivateIPv4Ranges
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/10.0.0.0/8_start
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/10.0.0.0/8_mid
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/10.0.0.0/8_end
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/172.16.0.0/12_start
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/172.16.0.0/12_mid
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/172.16.0.0/12_end
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/192.168.0.0/16_start
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/192.168.0.0/16_end
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/127.0.0.1_localhost
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/127.0.0.0/8_start
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/127.0.0.0/8_end
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/169.254.0.0/16_start
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/169.254.169.254_AWS_metadata
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/169.254.0.0/16_end
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/0.0.0.0/8
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/240.0.0.0/4
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/255.255.255.255_broadcast
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/8.8.8.8_Google_DNS
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/1.1.1.1_Cloudflare_DNS
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/93.184.216.34_example.com
=== RUN TestIsPrivateIP_PrivateIPv4Ranges/151.101.1.140_GitHub
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/10.0.0.0/8_start (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/10.0.0.0/8_mid (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/10.0.0.0/8_end (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/172.16.0.0/12_start (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/172.16.0.0/12_mid (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/172.16.0.0/12_end (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/192.168.0.0/16_start (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/192.168.0.0/16_end (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/127.0.0.1_localhost (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/127.0.0.0/8_start (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/127.0.0.0/8_end (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/169.254.0.0/16_start (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/169.254.169.254_AWS_metadata (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/169.254.0.0/16_end (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/0.0.0.0/8 (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/240.0.0.0/4 (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/255.255.255.255_broadcast (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/8.8.8.8_Google_DNS (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/1.1.1.1_Cloudflare_DNS (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/93.184.216.34_example.com (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv4Ranges/151.101.1.140_GitHub (0.00s)
=== RUN TestIsPrivateIP_PrivateIPv6Ranges
=== RUN TestIsPrivateIP_PrivateIPv6Ranges/::1_loopback
=== RUN TestIsPrivateIP_PrivateIPv6Ranges/fe80::/10_start
=== RUN TestIsPrivateIP_PrivateIPv6Ranges/fe80::/10_mid
=== RUN TestIsPrivateIP_PrivateIPv6Ranges/fc00::/7_start
=== RUN TestIsPrivateIP_PrivateIPv6Ranges/fc00::/7_mid
=== RUN TestIsPrivateIP_PrivateIPv6Ranges/2001:4860:4860::8888_Google_DNS
=== RUN TestIsPrivateIP_PrivateIPv6Ranges/2606:4700:4700::1111_Cloudflare_DNS
--- PASS: TestIsPrivateIP_PrivateIPv6Ranges (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv6Ranges/::1_loopback (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv6Ranges/fe80::/10_start (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv6Ranges/fe80::/10_mid (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv6Ranges/fc00::/7_start (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv6Ranges/fc00::/7_mid (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv6Ranges/2001:4860:4860::8888_Google_DNS (0.00s)
--- PASS: TestIsPrivateIP_PrivateIPv6Ranges/2606:4700:4700::1111_Cloudflare_DNS (0.00s)
=== RUN TestTestURLConnectivity_PrivateIP_Blocked
=== RUN TestTestURLConnectivity_PrivateIP_Blocked/localhost
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"localhost","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_PrivateIP_Blocked/127.0.0.1
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"127.0.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_PrivateIP_Blocked/Private_IP_10.x
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"10.0.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_PrivateIP_Blocked/Private_IP_192.168.x
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"192.168.1.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_PrivateIP_Blocked/AWS_metadata
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"169.254.169.254","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
--- PASS: TestTestURLConnectivity_PrivateIP_Blocked (0.00s)
--- PASS: TestTestURLConnectivity_PrivateIP_Blocked/localhost (0.00s)
--- PASS: TestTestURLConnectivity_PrivateIP_Blocked/127.0.0.1 (0.00s)
--- PASS: TestTestURLConnectivity_PrivateIP_Blocked/Private_IP_10.x (0.00s)
--- PASS: TestTestURLConnectivity_PrivateIP_Blocked/Private_IP_192.168.x (0.00s)
--- PASS: TestTestURLConnectivity_PrivateIP_Blocked/AWS_metadata (0.00s)
=== RUN TestTestURLConnectivity_SSRF_Protection_Comprehensive
=== RUN TestTestURLConnectivity_SSRF_Protection_Comprehensive/http://localhost:8080
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"localhost","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_SSRF_Protection_Comprehensive/http://127.0.0.1:8080
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"127.0.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_SSRF_Protection_Comprehensive/http://0.0.0.0:8080
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"0.0.0.0","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_SSRF_Protection_Comprehensive/http://[::1]:8080
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"::1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_SSRF_Protection_Comprehensive/http://169.254.169.254/latest/meta-data/
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"169.254.169.254","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_SSRF_Protection_Comprehensive/http://metadata.google.internal/computeMetadata/v1/
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"metadata.google.internal","request_id":"test-1768011443914517171","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestTestURLConnectivity_SSRF_Protection_Comprehensive (0.00s)
--- PASS: TestTestURLConnectivity_SSRF_Protection_Comprehensive/http://localhost:8080 (0.00s)
--- PASS: TestTestURLConnectivity_SSRF_Protection_Comprehensive/http://127.0.0.1:8080 (0.00s)
--- PASS: TestTestURLConnectivity_SSRF_Protection_Comprehensive/http://0.0.0.0:8080 (0.00s)
--- PASS: TestTestURLConnectivity_SSRF_Protection_Comprehensive/http://[::1]:8080 (0.00s)
--- PASS: TestTestURLConnectivity_SSRF_Protection_Comprehensive/http://169.254.169.254/latest/meta-data/ (0.00s)
--- PASS: TestTestURLConnectivity_SSRF_Protection_Comprehensive/http://metadata.google.internal/computeMetadata/v1/ (0.00s)
=== RUN TestTestURLConnectivity_HTTPSSupport
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"127.0.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
url_connectivity_test.go:345: HTTPS test failed (expected with self-signed cert): security validation failed: connection to private IP addresses is blocked for security (detected IPv4-mapped IPv6: 127.0.0.1)
--- PASS: TestTestURLConnectivity_HTTPSSupport (0.00s)
=== RUN TestTestURLConnectivity_RedirectLimit_ProductionPath
--- PASS: TestTestURLConnectivity_RedirectLimit_ProductionPath (0.00s)
=== RUN TestTestURLConnectivity_InvalidPortFormat
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"http://example.com:badport","request_id":"test-1768011443920778663","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestTestURLConnectivity_InvalidPortFormat (0.00s)
=== RUN TestTestURLConnectivity_EmptyDNSResult
--- PASS: TestTestURLConnectivity_EmptyDNSResult (0.00s)
=== RUN TestGetPublicURL_WithConfiguredURL
--- PASS: TestGetPublicURL_WithConfiguredURL (0.01s)
=== RUN TestGetPublicURL_WithTrailingSlash
--- PASS: TestGetPublicURL_WithTrailingSlash (0.00s)
=== RUN TestGetPublicURL_Fallback_HTTPSWithTLS
2026/01/10 02:17:23 /projects/Charon/backend/internal/utils/url.go:17 record not found
[0.108ms] [rows:0] SELECT * FROM `settings` WHERE key = "app.public_url" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestGetPublicURL_Fallback_HTTPSWithTLS (0.00s)
=== RUN TestGetPublicURL_Fallback_HTTP
2026/01/10 02:17:23 /projects/Charon/backend/internal/utils/url.go:17 record not found
[0.078ms] [rows:0] SELECT * FROM `settings` WHERE key = "app.public_url" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestGetPublicURL_Fallback_HTTP (0.00s)
=== RUN TestGetPublicURL_Fallback_XForwardedProto
2026/01/10 02:17:23 /projects/Charon/backend/internal/utils/url.go:17 record not found
[0.076ms] [rows:0] SELECT * FROM `settings` WHERE key = "app.public_url" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestGetPublicURL_Fallback_XForwardedProto (0.00s)
=== RUN TestGetPublicURL_EmptyValue
--- PASS: TestGetPublicURL_EmptyValue (0.00s)
=== RUN TestGetPublicURL_NoSettingInDB
2026/01/10 02:17:23 /projects/Charon/backend/internal/utils/url.go:17 record not found
[0.064ms] [rows:0] SELECT * FROM `settings` WHERE key = "app.public_url" ORDER BY `settings`.`id` LIMIT 1
--- PASS: TestGetPublicURL_NoSettingInDB (0.00s)
=== RUN TestValidateURL_ValidHTTPS
=== RUN TestValidateURL_ValidHTTPS/HTTPS_with_trailing_slash
=== RUN TestValidateURL_ValidHTTPS/HTTPS_without_path
=== RUN TestValidateURL_ValidHTTPS/HTTPS_with_port
=== RUN TestValidateURL_ValidHTTPS/HTTPS_with_subdomain
--- PASS: TestValidateURL_ValidHTTPS (0.00s)
--- PASS: TestValidateURL_ValidHTTPS/HTTPS_with_trailing_slash (0.00s)
--- PASS: TestValidateURL_ValidHTTPS/HTTPS_without_path (0.00s)
--- PASS: TestValidateURL_ValidHTTPS/HTTPS_with_port (0.00s)
--- PASS: TestValidateURL_ValidHTTPS/HTTPS_with_subdomain (0.00s)
=== RUN TestValidateURL_ValidHTTP
=== RUN TestValidateURL_ValidHTTP/HTTP_with_trailing_slash
=== RUN TestValidateURL_ValidHTTP/HTTP_without_path
=== RUN TestValidateURL_ValidHTTP/HTTP_with_port
--- PASS: TestValidateURL_ValidHTTP (0.00s)
--- PASS: TestValidateURL_ValidHTTP/HTTP_with_trailing_slash (0.00s)
--- PASS: TestValidateURL_ValidHTTP/HTTP_without_path (0.00s)
--- PASS: TestValidateURL_ValidHTTP/HTTP_with_port (0.00s)
=== RUN TestValidateURL_InvalidScheme
=== RUN TestValidateURL_InvalidScheme/ftp://example.com
=== RUN TestValidateURL_InvalidScheme/file:///etc/passwd
=== RUN TestValidateURL_InvalidScheme/javascript:alert(1)
=== RUN TestValidateURL_InvalidScheme/data:text/html,<script>alert(1)</script>
=== RUN TestValidateURL_InvalidScheme/ssh://user@host
--- PASS: TestValidateURL_InvalidScheme (0.00s)
--- PASS: TestValidateURL_InvalidScheme/ftp://example.com (0.00s)
--- PASS: TestValidateURL_InvalidScheme/file:///etc/passwd (0.00s)
--- PASS: TestValidateURL_InvalidScheme/javascript:alert(1) (0.00s)
--- PASS: TestValidateURL_InvalidScheme/data:text/html,<script>alert(1)</script> (0.00s)
--- PASS: TestValidateURL_InvalidScheme/ssh://user@host (0.00s)
=== RUN TestValidateURL_WithPath
=== RUN TestValidateURL_WithPath/https://example.com/api/v1
=== RUN TestValidateURL_WithPath/https://example.com/admin
=== RUN TestValidateURL_WithPath/http://example.com/path/to/resource
=== RUN TestValidateURL_WithPath/https://example.com/index.html
--- PASS: TestValidateURL_WithPath (0.00s)
--- PASS: TestValidateURL_WithPath/https://example.com/api/v1 (0.00s)
--- PASS: TestValidateURL_WithPath/https://example.com/admin (0.00s)
--- PASS: TestValidateURL_WithPath/http://example.com/path/to/resource (0.00s)
--- PASS: TestValidateURL_WithPath/https://example.com/index.html (0.00s)
=== RUN TestValidateURL_RootPathAllowed
=== RUN TestValidateURL_RootPathAllowed/https://example.com/
=== RUN TestValidateURL_RootPathAllowed/http://example.com/
--- PASS: TestValidateURL_RootPathAllowed (0.00s)
--- PASS: TestValidateURL_RootPathAllowed/https://example.com/ (0.00s)
--- PASS: TestValidateURL_RootPathAllowed/http://example.com/ (0.00s)
=== RUN TestValidateURL_MalformedURL
=== RUN TestValidateURL_MalformedURL/not_a_url
=== RUN TestValidateURL_MalformedURL/://missing-scheme
=== RUN TestValidateURL_MalformedURL/http://
=== RUN TestValidateURL_MalformedURL/https://[invalid
=== RUN TestValidateURL_MalformedURL/#00
--- PASS: TestValidateURL_MalformedURL (0.00s)
--- PASS: TestValidateURL_MalformedURL/not_a_url (0.00s)
--- PASS: TestValidateURL_MalformedURL/://missing-scheme (0.00s)
--- PASS: TestValidateURL_MalformedURL/http:// (0.00s)
--- PASS: TestValidateURL_MalformedURL/https://[invalid (0.00s)
--- PASS: TestValidateURL_MalformedURL/#00 (0.00s)
=== RUN TestValidateURL_SpecialCharacters
=== RUN TestValidateURL_SpecialCharacters/Punycode_domain
=== RUN TestValidateURL_SpecialCharacters/Port_with_special_chars
=== RUN TestValidateURL_SpecialCharacters/Query_string_(no_path_component)
=== RUN TestValidateURL_SpecialCharacters/Fragment_(no_path_component)
=== RUN TestValidateURL_SpecialCharacters/Userinfo
--- PASS: TestValidateURL_SpecialCharacters (0.00s)
--- PASS: TestValidateURL_SpecialCharacters/Punycode_domain (0.00s)
--- PASS: TestValidateURL_SpecialCharacters/Port_with_special_chars (0.00s)
--- PASS: TestValidateURL_SpecialCharacters/Query_string_(no_path_component) (0.00s)
--- PASS: TestValidateURL_SpecialCharacters/Fragment_(no_path_component) (0.00s)
--- PASS: TestValidateURL_SpecialCharacters/Userinfo (0.00s)
=== RUN TestValidateURL_Normalization
=== RUN TestValidateURL_Normalization/https://EXAMPLE.COM
=== RUN TestValidateURL_Normalization/https://example.com/
=== RUN TestValidateURL_Normalization/https://example.com///
=== RUN TestValidateURL_Normalization/http://example.com:80
=== RUN TestValidateURL_Normalization/https://example.com:443
--- PASS: TestValidateURL_Normalization (0.00s)
--- PASS: TestValidateURL_Normalization/https://EXAMPLE.COM (0.00s)
--- PASS: TestValidateURL_Normalization/https://example.com/ (0.00s)
--- PASS: TestValidateURL_Normalization/https://example.com/// (0.00s)
--- PASS: TestValidateURL_Normalization/http://example.com:80 (0.00s)
--- PASS: TestValidateURL_Normalization/https://example.com:443 (0.00s)
=== RUN TestGetBaseURL
=== RUN TestGetBaseURL/HTTPS_with_TLS
=== RUN TestGetBaseURL/HTTP_without_TLS
=== RUN TestGetBaseURL/X-Forwarded-Proto_HTTPS
=== RUN TestGetBaseURL/X-Forwarded-Proto_HTTP
=== RUN TestGetBaseURL/With_port
=== RUN TestGetBaseURL/IPv4_host
=== RUN TestGetBaseURL/IPv6_host
--- PASS: TestGetBaseURL (0.00s)
--- PASS: TestGetBaseURL/HTTPS_with_TLS (0.00s)
--- PASS: TestGetBaseURL/HTTP_without_TLS (0.00s)
--- PASS: TestGetBaseURL/X-Forwarded-Proto_HTTPS (0.00s)
--- PASS: TestGetBaseURL/X-Forwarded-Proto_HTTP (0.00s)
--- PASS: TestGetBaseURL/With_port (0.00s)
--- PASS: TestGetBaseURL/IPv4_host (0.00s)
--- PASS: TestGetBaseURL/IPv6_host (0.00s)
=== RUN TestGetBaseURL_PrecedenceOrder
--- PASS: TestGetBaseURL_PrecedenceOrder (0.00s)
=== RUN TestGetBaseURL_EmptyHost
--- PASS: TestGetBaseURL_EmptyHost (0.00s)
=== RUN TestTestURLConnectivity_EnhancedSSRF
=== RUN TestTestURLConnectivity_EnhancedSSRF/AWS_metadata_endpoint
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"169.254.169.254","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_EnhancedSSRF/GCP_metadata_endpoint
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"metadata.google.internal","request_id":"test-1768011443951185546","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_EnhancedSSRF/Azure_metadata_endpoint
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"169.254.169.254","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_EnhancedSSRF/Private_10.0.0.0/8
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"10.0.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_EnhancedSSRF/Private_172.16.0.0/12
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"172.16.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_EnhancedSSRF/Private_192.168.0.0/16
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"192.168.1.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_EnhancedSSRF/IPv4_loopback
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"127.0.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_EnhancedSSRF/IPv6_loopback
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"::1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_EnhancedSSRF/Link-local_IPv4
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"169.254.1.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_EnhancedSSRF/Link-local_IPv6
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"fe80::1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
--- PASS: TestTestURLConnectivity_EnhancedSSRF (0.00s)
--- PASS: TestTestURLConnectivity_EnhancedSSRF/AWS_metadata_endpoint (0.00s)
--- PASS: TestTestURLConnectivity_EnhancedSSRF/GCP_metadata_endpoint (0.00s)
--- PASS: TestTestURLConnectivity_EnhancedSSRF/Azure_metadata_endpoint (0.00s)
--- PASS: TestTestURLConnectivity_EnhancedSSRF/Private_10.0.0.0/8 (0.00s)
--- PASS: TestTestURLConnectivity_EnhancedSSRF/Private_172.16.0.0/12 (0.00s)
--- PASS: TestTestURLConnectivity_EnhancedSSRF/Private_192.168.0.0/16 (0.00s)
--- PASS: TestTestURLConnectivity_EnhancedSSRF/IPv4_loopback (0.00s)
--- PASS: TestTestURLConnectivity_EnhancedSSRF/IPv6_loopback (0.00s)
--- PASS: TestTestURLConnectivity_EnhancedSSRF/Link-local_IPv4 (0.00s)
--- PASS: TestTestURLConnectivity_EnhancedSSRF/Link-local_IPv6 (0.00s)
=== RUN TestTestURLConnectivity_RedirectValidation
=== RUN TestTestURLConnectivity_RedirectValidation/Redirect_to_private_IP_should_be_blocked
url_testing_enhanced_test.go:123: Redirect validation test requires complex HTTP client mocking
=== RUN TestTestURLConnectivity_RedirectValidation/Too_many_redirects_should_be_blocked
--- PASS: TestTestURLConnectivity_RedirectValidation (0.00s)
--- SKIP: TestTestURLConnectivity_RedirectValidation/Redirect_to_private_IP_should_be_blocked (0.00s)
--- PASS: TestTestURLConnectivity_RedirectValidation/Too_many_redirects_should_be_blocked (0.00s)
=== RUN TestTestURLConnectivity_UnicodeHomograph
=== RUN TestTestURLConnectivity_UnicodeHomograph/Cyrillic_homograph
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"gооgle.com","request_id":"test-1768011443957532178","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_UnicodeHomograph/Mixed_script_attack
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"раypal.com","request_id":"test-1768011443957740167","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestTestURLConnectivity_UnicodeHomograph (0.00s)
--- PASS: TestTestURLConnectivity_UnicodeHomograph/Cyrillic_homograph (0.00s)
--- PASS: TestTestURLConnectivity_UnicodeHomograph/Mixed_script_attack (0.00s)
=== RUN TestTestURLConnectivity_LongHostname
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com","request_id":"test-1768011443957966949","result":"blocked","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestTestURLConnectivity_LongHostname (0.00s)
=== RUN TestTestURLConnectivity_RequestTracingHeaders
--- PASS: TestTestURLConnectivity_RequestTracingHeaders (0.00s)
=== RUN TestTestURLConnectivity_MetricsIntegration
=== RUN TestTestURLConnectivity_MetricsIntegration/Valid_URL_records_metrics
=== RUN TestTestURLConnectivity_MetricsIntegration/Blocked_URL_records_metrics
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"127.0.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_MetricsIntegration/Invalid_URL_records_metrics
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"","request_id":"test-1768011443961052630","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestTestURLConnectivity_MetricsIntegration (0.00s)
--- PASS: TestTestURLConnectivity_MetricsIntegration/Valid_URL_records_metrics (0.00s)
--- PASS: TestTestURLConnectivity_MetricsIntegration/Blocked_URL_records_metrics (0.00s)
--- PASS: TestTestURLConnectivity_MetricsIntegration/Invalid_URL_records_metrics (0.00s)
=== RUN TestValidateRedirectTarget
=== RUN TestValidateRedirectTarget/Localhost_redirect_allowed
=== RUN TestValidateRedirectTarget/127.0.0.1_redirect_allowed
=== RUN TestValidateRedirectTarget/IPv6_loopback_allowed
=== RUN TestValidateRedirectTarget/Too_many_redirects
=== RUN TestValidateRedirectTarget/Three_redirects
=== RUN TestValidateRedirectTarget/Scheme_downgrade_blocked_(https_->_http)
--- PASS: TestValidateRedirectTarget (0.00s)
--- PASS: TestValidateRedirectTarget/Localhost_redirect_allowed (0.00s)
--- PASS: TestValidateRedirectTarget/127.0.0.1_redirect_allowed (0.00s)
--- PASS: TestValidateRedirectTarget/IPv6_loopback_allowed (0.00s)
--- PASS: TestValidateRedirectTarget/Too_many_redirects (0.00s)
--- PASS: TestValidateRedirectTarget/Three_redirects (0.00s)
--- PASS: TestValidateRedirectTarget/Scheme_downgrade_blocked_(https_->_http) (0.00s)
=== RUN TestTestURLConnectivity_AuditLogging
=== RUN TestTestURLConnectivity_AuditLogging/Invalid_URL_format_logs_audit_event
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"://invalid","request_id":"test-1768011443962054942","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_AuditLogging/Invalid_scheme_logs_audit_event
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"example.com","request_id":"test-1768011443962234283","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_AuditLogging/Private_IP_logs_SSRF_block_audit_event
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"10.0.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_AuditLogging/Metadata_endpoint_logs_SSRF_block_audit_event
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"169.254.169.254","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_AuditLogging/Valid_URL_with_mock_transport_logs_success
--- PASS: TestTestURLConnectivity_AuditLogging (0.00s)
--- PASS: TestTestURLConnectivity_AuditLogging/Invalid_URL_format_logs_audit_event (0.00s)
--- PASS: TestTestURLConnectivity_AuditLogging/Invalid_scheme_logs_audit_event (0.00s)
--- PASS: TestTestURLConnectivity_AuditLogging/Private_IP_logs_SSRF_block_audit_event (0.00s)
--- PASS: TestTestURLConnectivity_AuditLogging/Metadata_endpoint_logs_SSRF_block_audit_event (0.00s)
--- PASS: TestTestURLConnectivity_AuditLogging/Valid_URL_with_mock_transport_logs_success (0.00s)
=== RUN TestTestURLConnectivity_RequestIDConsistency
--- PASS: TestTestURLConnectivity_RequestIDConsistency (0.00s)
=== RUN TestResolveAllowedIP_EmptyHostname
--- PASS: TestResolveAllowedIP_EmptyHostname (0.00s)
=== RUN TestResolveAllowedIP_LoopbackIPLiteral
=== RUN TestResolveAllowedIP_LoopbackIPLiteral/127.0.0.1_without_allowLocalhost
=== RUN TestResolveAllowedIP_LoopbackIPLiteral/127.0.0.1_with_allowLocalhost
=== RUN TestResolveAllowedIP_LoopbackIPLiteral/::1_without_allowLocalhost
=== RUN TestResolveAllowedIP_LoopbackIPLiteral/::1_with_allowLocalhost
--- PASS: TestResolveAllowedIP_LoopbackIPLiteral (0.00s)
--- PASS: TestResolveAllowedIP_LoopbackIPLiteral/127.0.0.1_without_allowLocalhost (0.00s)
--- PASS: TestResolveAllowedIP_LoopbackIPLiteral/127.0.0.1_with_allowLocalhost (0.00s)
--- PASS: TestResolveAllowedIP_LoopbackIPLiteral/::1_without_allowLocalhost (0.00s)
--- PASS: TestResolveAllowedIP_LoopbackIPLiteral/::1_with_allowLocalhost (0.00s)
=== RUN TestResolveAllowedIP_PrivateIPLiterals
=== RUN TestResolveAllowedIP_PrivateIPLiterals/IP_10.0.0.1
=== RUN TestResolveAllowedIP_PrivateIPLiterals/IP_172.16.0.1
=== RUN TestResolveAllowedIP_PrivateIPLiterals/IP_192.168.1.1
=== RUN TestResolveAllowedIP_PrivateIPLiterals/IP_169.254.169.254
=== RUN TestResolveAllowedIP_PrivateIPLiterals/IP_fc00::1
=== RUN TestResolveAllowedIP_PrivateIPLiterals/IP_fe80::1
--- PASS: TestResolveAllowedIP_PrivateIPLiterals (0.00s)
--- PASS: TestResolveAllowedIP_PrivateIPLiterals/IP_10.0.0.1 (0.00s)
--- PASS: TestResolveAllowedIP_PrivateIPLiterals/IP_172.16.0.1 (0.00s)
--- PASS: TestResolveAllowedIP_PrivateIPLiterals/IP_192.168.1.1 (0.00s)
--- PASS: TestResolveAllowedIP_PrivateIPLiterals/IP_169.254.169.254 (0.00s)
--- PASS: TestResolveAllowedIP_PrivateIPLiterals/IP_fc00::1 (0.00s)
--- PASS: TestResolveAllowedIP_PrivateIPLiterals/IP_fe80::1 (0.00s)
=== RUN TestResolveAllowedIP_PublicIPLiteral
=== RUN TestResolveAllowedIP_PublicIPLiteral/IP_8.8.8.8
=== RUN TestResolveAllowedIP_PublicIPLiteral/IP_1.1.1.1
=== RUN TestResolveAllowedIP_PublicIPLiteral/IP_2001:4860:4860::8888
--- PASS: TestResolveAllowedIP_PublicIPLiteral (0.00s)
--- PASS: TestResolveAllowedIP_PublicIPLiteral/IP_8.8.8.8 (0.00s)
--- PASS: TestResolveAllowedIP_PublicIPLiteral/IP_1.1.1.1 (0.00s)
--- PASS: TestResolveAllowedIP_PublicIPLiteral/IP_2001:4860:4860::8888 (0.00s)
=== RUN TestResolveAllowedIP_Timeout
--- PASS: TestResolveAllowedIP_Timeout (0.00s)
=== RUN TestResolveAllowedIP_NoIPsResolved
url_testing_security_test.go:150: Requires custom DNS resolver to return empty IP list
--- SKIP: TestResolveAllowedIP_NoIPsResolved (0.00s)
=== RUN TestSSRFSafeDialer_Concept
url_testing_security_test.go:163: ssrfSafeDialer validates IPs at dial time to prevent DNS rebinding
url_testing_security_test.go:164: All resolved IPs must pass private IP check before connection
--- PASS: TestSSRFSafeDialer_Concept (0.00s)
=== RUN TestSSRFSafeDialer_InvalidAddress
=== RUN TestSSRFSafeDialer_InvalidAddress/No_port
=== RUN TestSSRFSafeDialer_InvalidAddress/Invalid_format
=== RUN TestSSRFSafeDialer_InvalidAddress/Empty_address
--- PASS: TestSSRFSafeDialer_InvalidAddress (0.00s)
--- PASS: TestSSRFSafeDialer_InvalidAddress/No_port (0.00s)
--- PASS: TestSSRFSafeDialer_InvalidAddress/Invalid_format (0.00s)
--- PASS: TestSSRFSafeDialer_InvalidAddress/Empty_address (0.00s)
=== RUN TestSSRFSafeDialer_ContextCancellation
--- PASS: TestSSRFSafeDialer_ContextCancellation (0.00s)
=== RUN TestTestURLConnectivity_ErrorPaths
=== RUN TestTestURLConnectivity_ErrorPaths/Invalid_URL_format
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"://invalid","request_id":"test-1768011443967837572","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_ErrorPaths/Unsupported_scheme_FTP
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"example.com","request_id":"test-1768011443967979832","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_ErrorPaths/Embedded_credentials
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"example.com","request_id":"test-1768011443968099643","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_ErrorPaths/Private_IP_10.x
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"10.0.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_ErrorPaths/Private_IP_192.168.x
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"192.168.1.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_ErrorPaths/AWS_metadata_endpoint
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"169.254.169.254","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
--- PASS: TestTestURLConnectivity_ErrorPaths (0.00s)
--- PASS: TestTestURLConnectivity_ErrorPaths/Invalid_URL_format (0.00s)
--- PASS: TestTestURLConnectivity_ErrorPaths/Unsupported_scheme_FTP (0.00s)
--- PASS: TestTestURLConnectivity_ErrorPaths/Embedded_credentials (0.00s)
--- PASS: TestTestURLConnectivity_ErrorPaths/Private_IP_10.x (0.00s)
--- PASS: TestTestURLConnectivity_ErrorPaths/Private_IP_192.168.x (0.00s)
--- PASS: TestTestURLConnectivity_ErrorPaths/AWS_metadata_endpoint (0.00s)
=== RUN TestTestURLConnectivity_InvalidPort
=== RUN TestTestURLConnectivity_InvalidPort/Port_out_of_range_(too_high)
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"example.com","request_id":"test-1768011443968785745","result":"blocked","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_InvalidPort/Port_zero
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"example.com","request_id":"test-1768011443968989516","result":"blocked","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestTestURLConnectivity_InvalidPort/Negative_port
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"https://example.com:-1","request_id":"test-1768011443969192356","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestTestURLConnectivity_InvalidPort (0.00s)
--- PASS: TestTestURLConnectivity_InvalidPort/Port_out_of_range_(too_high) (0.00s)
--- PASS: TestTestURLConnectivity_InvalidPort/Port_zero (0.00s)
--- PASS: TestTestURLConnectivity_InvalidPort/Negative_port (0.00s)
=== RUN TestSSRFSafeDialer_ValidPublicIP
--- PASS: TestSSRFSafeDialer_ValidPublicIP (0.01s)
=== RUN TestSSRFSafeDialer_PrivateIPBlocking
=== RUN TestSSRFSafeDialer_PrivateIPBlocking/10.0.0.1:80
=== RUN TestSSRFSafeDialer_PrivateIPBlocking/192.168.1.1:80
=== RUN TestSSRFSafeDialer_PrivateIPBlocking/172.16.0.1:80
=== RUN TestSSRFSafeDialer_PrivateIPBlocking/127.0.0.1:80
--- PASS: TestSSRFSafeDialer_PrivateIPBlocking (0.00s)
--- PASS: TestSSRFSafeDialer_PrivateIPBlocking/10.0.0.1:80 (0.00s)
--- PASS: TestSSRFSafeDialer_PrivateIPBlocking/192.168.1.1:80 (0.00s)
--- PASS: TestSSRFSafeDialer_PrivateIPBlocking/172.16.0.1:80 (0.00s)
--- PASS: TestSSRFSafeDialer_PrivateIPBlocking/127.0.0.1:80 (0.00s)
=== RUN TestSSRFSafeDialer_DNSResolutionFailure
--- PASS: TestSSRFSafeDialer_DNSResolutionFailure (0.00s)
=== RUN TestSSRFSafeDialer_MultipleIPsWithPrivate
--- PASS: TestSSRFSafeDialer_MultipleIPsWithPrivate (0.00s)
=== RUN TestURLConnectivity_ProductionPathValidation
=== RUN TestURLConnectivity_ProductionPathValidation/localhost_blocked_at_dial_time
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"localhost","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_ProductionPathValidation/127.0.0.1_blocked_at_dial_time
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"127.0.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_ProductionPathValidation/private_10.x_blocked_at_validation
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"10.0.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_ProductionPathValidation/private_192.168.x_blocked_at_validation
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"192.168.1.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_ProductionPathValidation/AWS_metadata_blocked_at_validation
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"169.254.169.254","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
--- PASS: TestURLConnectivity_ProductionPathValidation (0.00s)
--- PASS: TestURLConnectivity_ProductionPathValidation/localhost_blocked_at_dial_time (0.00s)
--- PASS: TestURLConnectivity_ProductionPathValidation/127.0.0.1_blocked_at_dial_time (0.00s)
--- PASS: TestURLConnectivity_ProductionPathValidation/private_10.x_blocked_at_validation (0.00s)
--- PASS: TestURLConnectivity_ProductionPathValidation/private_192.168.x_blocked_at_validation (0.00s)
--- PASS: TestURLConnectivity_ProductionPathValidation/AWS_metadata_blocked_at_validation (0.00s)
=== RUN TestURLConnectivity_TestHook_AllowsLocalhostWithInjectedTransport
--- PASS: TestURLConnectivity_TestHook_AllowsLocalhostWithInjectedTransport (0.00s)
=== RUN TestValidateRedirectTarget_AllowsLocalhost
--- PASS: TestValidateRedirectTarget_AllowsLocalhost (0.00s)
=== RUN TestValidateRedirectTarget_BlocksInvalidExternalRedirect
--- PASS: TestValidateRedirectTarget_BlocksInvalidExternalRedirect (0.00s)
=== RUN TestURLConnectivity_RejectsUserinfo
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"example.com","request_id":"test-1768011443983562626","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestURLConnectivity_RejectsUserinfo (0.00s)
=== RUN TestURLConnectivity_InvalidScheme
=== RUN TestURLConnectivity_InvalidScheme/ftp://example.com
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"example.com","request_id":"test-1768011443983744726","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_InvalidScheme/file:///etc/passwd
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"","request_id":"test-1768011443983856636","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_InvalidScheme/javascript:alert(1)
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"","request_id":"test-1768011443985204971","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_InvalidScheme/data:text/html,<script>alert(1)</script>
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"","request_id":"test-1768011443985477132","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_InvalidScheme/gopher://example.com
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"url_connectivity_test","host":"example.com","request_id":"test-1768011443985719173","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestURLConnectivity_InvalidScheme (0.00s)
--- PASS: TestURLConnectivity_InvalidScheme/ftp://example.com (0.00s)
--- PASS: TestURLConnectivity_InvalidScheme/file:///etc/passwd (0.00s)
--- PASS: TestURLConnectivity_InvalidScheme/javascript:alert(1) (0.00s)
--- PASS: TestURLConnectivity_InvalidScheme/data:text/html,<script>alert(1)</script> (0.00s)
--- PASS: TestURLConnectivity_InvalidScheme/gopher://example.com (0.00s)
=== RUN TestURLConnectivity_SSRFValidationFailure
=== RUN TestURLConnectivity_SSRFValidationFailure/http://10.0.0.1
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"10.0.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_SSRFValidationFailure/http://192.168.1.1
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"192.168.1.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_SSRFValidationFailure/http://172.16.0.1
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"172.16.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_SSRFValidationFailure/http://localhost
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"localhost","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_SSRFValidationFailure/http://127.0.0.1
2026/01/10 02:17:23 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:23Z","action":"ssrf_block","host":"127.0.0.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
--- PASS: TestURLConnectivity_SSRFValidationFailure (0.00s)
--- PASS: TestURLConnectivity_SSRFValidationFailure/http://10.0.0.1 (0.00s)
--- PASS: TestURLConnectivity_SSRFValidationFailure/http://192.168.1.1 (0.00s)
--- PASS: TestURLConnectivity_SSRFValidationFailure/http://172.16.0.1 (0.00s)
--- PASS: TestURLConnectivity_SSRFValidationFailure/http://localhost (0.00s)
--- PASS: TestURLConnectivity_SSRFValidationFailure/http://127.0.0.1 (0.00s)
=== RUN TestURLConnectivity_HTTPRequestFailure
--- PASS: TestURLConnectivity_HTTPRequestFailure (0.00s)
=== RUN TestURLConnectivity_RedirectHandling
--- PASS: TestURLConnectivity_RedirectHandling (0.00s)
=== RUN TestURLConnectivity_2xxSuccess
=== RUN TestURLConnectivity_2xxSuccess/status_200
=== RUN TestURLConnectivity_2xxSuccess/status_201
=== RUN TestURLConnectivity_2xxSuccess/status_204
--- PASS: TestURLConnectivity_2xxSuccess (0.00s)
--- PASS: TestURLConnectivity_2xxSuccess/status_200 (0.00s)
--- PASS: TestURLConnectivity_2xxSuccess/status_201 (0.00s)
--- PASS: TestURLConnectivity_2xxSuccess/status_204 (0.00s)
=== RUN TestURLConnectivity_3xxSuccess
=== RUN TestURLConnectivity_3xxSuccess/status_301
=== RUN TestURLConnectivity_3xxSuccess/status_302
=== RUN TestURLConnectivity_3xxSuccess/status_307
=== RUN TestURLConnectivity_3xxSuccess/status_308
--- PASS: TestURLConnectivity_3xxSuccess (0.01s)
--- PASS: TestURLConnectivity_3xxSuccess/status_301 (0.00s)
--- PASS: TestURLConnectivity_3xxSuccess/status_302 (0.00s)
--- PASS: TestURLConnectivity_3xxSuccess/status_307 (0.00s)
--- PASS: TestURLConnectivity_3xxSuccess/status_308 (0.00s)
=== RUN TestURLConnectivity_4xxFailure
=== RUN TestURLConnectivity_4xxFailure/status_400
=== RUN TestURLConnectivity_4xxFailure/status_401
=== RUN TestURLConnectivity_4xxFailure/status_403
=== RUN TestURLConnectivity_4xxFailure/status_404
=== RUN TestURLConnectivity_4xxFailure/status_429
--- PASS: TestURLConnectivity_4xxFailure (0.01s)
--- PASS: TestURLConnectivity_4xxFailure/status_400 (0.00s)
--- PASS: TestURLConnectivity_4xxFailure/status_401 (0.00s)
--- PASS: TestURLConnectivity_4xxFailure/status_403 (0.00s)
--- PASS: TestURLConnectivity_4xxFailure/status_404 (0.00s)
--- PASS: TestURLConnectivity_4xxFailure/status_429 (0.00s)
=== RUN TestIsPrivateIP_AllReservedRanges
=== RUN TestIsPrivateIP_AllReservedRanges/10.0.0.1
=== RUN TestIsPrivateIP_AllReservedRanges/10.255.255.255
=== RUN TestIsPrivateIP_AllReservedRanges/172.16.0.1
=== RUN TestIsPrivateIP_AllReservedRanges/172.31.255.255
=== RUN TestIsPrivateIP_AllReservedRanges/192.168.0.1
=== RUN TestIsPrivateIP_AllReservedRanges/192.168.255.255
=== RUN TestIsPrivateIP_AllReservedRanges/127.0.0.1
=== RUN TestIsPrivateIP_AllReservedRanges/127.0.0.2
=== RUN TestIsPrivateIP_AllReservedRanges/127.255.255.255
=== RUN TestIsPrivateIP_AllReservedRanges/169.254.0.1
=== RUN TestIsPrivateIP_AllReservedRanges/169.254.169.254
=== RUN TestIsPrivateIP_AllReservedRanges/169.254.255.255
=== RUN TestIsPrivateIP_AllReservedRanges/0.0.0.0
=== RUN TestIsPrivateIP_AllReservedRanges/0.0.0.1
=== RUN TestIsPrivateIP_AllReservedRanges/240.0.0.1
=== RUN TestIsPrivateIP_AllReservedRanges/255.255.255.255
=== RUN TestIsPrivateIP_AllReservedRanges/::1
=== RUN TestIsPrivateIP_AllReservedRanges/fc00::1
=== RUN TestIsPrivateIP_AllReservedRanges/fd00::1
=== RUN TestIsPrivateIP_AllReservedRanges/fe80::1
=== RUN TestIsPrivateIP_AllReservedRanges/8.8.8.8
=== RUN TestIsPrivateIP_AllReservedRanges/1.1.1.1
=== RUN TestIsPrivateIP_AllReservedRanges/93.184.216.34
=== RUN TestIsPrivateIP_AllReservedRanges/2606:2800:220:1:248:1893:25c8:1946
--- PASS: TestIsPrivateIP_AllReservedRanges (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/10.0.0.1 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/10.255.255.255 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/172.16.0.1 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/172.31.255.255 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/192.168.0.1 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/192.168.255.255 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/127.0.0.1 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/127.0.0.2 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/127.255.255.255 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/169.254.0.1 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/169.254.169.254 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/169.254.255.255 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/0.0.0.0 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/0.0.0.1 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/240.0.0.1 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/255.255.255.255 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/::1 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/fc00::1 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/fd00::1 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/fe80::1 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/8.8.8.8 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/1.1.1.1 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/93.184.216.34 (0.00s)
--- PASS: TestIsPrivateIP_AllReservedRanges/2606:2800:220:1:248:1893:25c8:1946 (0.00s)
=== RUN TestURLConnectivity_ErrorWrapping
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"url_connectivity_test","host":"://invalid","request_id":"test-1768011444010591117","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestURLConnectivity_ErrorWrapping (0.00s)
=== RUN TestURLConnectivity_UserAgent
--- PASS: TestURLConnectivity_UserAgent (0.00s)
=== RUN TestResolveAllowedIP_EmptyHost
--- PASS: TestResolveAllowedIP_EmptyHost (0.00s)
=== RUN TestResolveAllowedIP_IPLiteralPublic
--- PASS: TestResolveAllowedIP_IPLiteralPublic (0.00s)
=== RUN TestResolveAllowedIP_IPLiteralPrivateBlocked
=== RUN TestResolveAllowedIP_IPLiteralPrivateBlocked/10.0.0.1
=== RUN TestResolveAllowedIP_IPLiteralPrivateBlocked/192.168.1.1
=== RUN TestResolveAllowedIP_IPLiteralPrivateBlocked/172.16.0.1
--- PASS: TestResolveAllowedIP_IPLiteralPrivateBlocked (0.00s)
--- PASS: TestResolveAllowedIP_IPLiteralPrivateBlocked/10.0.0.1 (0.00s)
--- PASS: TestResolveAllowedIP_IPLiteralPrivateBlocked/192.168.1.1 (0.00s)
--- PASS: TestResolveAllowedIP_IPLiteralPrivateBlocked/172.16.0.1 (0.00s)
=== RUN TestResolveAllowedIP_DNSResolutionFailure
--- PASS: TestResolveAllowedIP_DNSResolutionFailure (0.00s)
=== RUN TestSSRFSafeDialer_InvalidAddressFormat
--- PASS: TestSSRFSafeDialer_InvalidAddressFormat (0.00s)
=== RUN TestSSRFSafeDialer_NoIPsFound
--- PASS: TestSSRFSafeDialer_NoIPsFound (0.00s)
=== RUN TestURLConnectivity_5xxServerErrors
=== RUN TestURLConnectivity_5xxServerErrors/status_500
=== RUN TestURLConnectivity_5xxServerErrors/status_502
=== RUN TestURLConnectivity_5xxServerErrors/status_503
=== RUN TestURLConnectivity_5xxServerErrors/status_504
--- PASS: TestURLConnectivity_5xxServerErrors (0.01s)
--- PASS: TestURLConnectivity_5xxServerErrors/status_500 (0.00s)
--- PASS: TestURLConnectivity_5xxServerErrors/status_502 (0.00s)
--- PASS: TestURLConnectivity_5xxServerErrors/status_503 (0.00s)
--- PASS: TestURLConnectivity_5xxServerErrors/status_504 (0.00s)
=== RUN TestURLConnectivity_TooManyRedirects
--- PASS: TestURLConnectivity_TooManyRedirects (0.00s)
=== RUN TestValidateRedirectTarget_TooManyRedirects
--- PASS: TestValidateRedirectTarget_TooManyRedirects (0.00s)
=== RUN TestValidateRedirectTarget_SchemeChangeBlocked
--- PASS: TestValidateRedirectTarget_SchemeChangeBlocked (0.00s)
=== RUN TestValidateRedirectTarget_HTTPToHTTPSAllowed
--- PASS: TestValidateRedirectTarget_HTTPToHTTPSAllowed (0.00s)
=== RUN TestValidateRedirectTarget_HTTPToHTTPSBlockedWhenNotAllowed
--- PASS: TestValidateRedirectTarget_HTTPToHTTPSBlockedWhenNotAllowed (0.00s)
=== RUN TestURLConnectivity_CloudMetadataBlocked
=== RUN TestURLConnectivity_CloudMetadataBlocked/http://169.254.169.254/latest/meta-data/
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"ssrf_block","host":"169.254.169.254","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_CloudMetadataBlocked/http://169.254.169.254
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"ssrf_block","host":"169.254.169.254","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
--- PASS: TestURLConnectivity_CloudMetadataBlocked (0.00s)
--- PASS: TestURLConnectivity_CloudMetadataBlocked/http://169.254.169.254/latest/meta-data/ (0.00s)
--- PASS: TestURLConnectivity_CloudMetadataBlocked/http://169.254.169.254 (0.00s)
=== RUN TestURLConnectivity_InvalidPort
=== RUN TestURLConnectivity_InvalidPort/port_zero
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"url_connectivity_test","host":"example.com","request_id":"test-1768011444027089363","result":"blocked","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_InvalidPort/port_negative
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"url_connectivity_test","host":"http://example.com:-1/path","request_id":"test-1768011444027214553","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_InvalidPort/port_too_large
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"url_connectivity_test","host":"example.com","request_id":"test-1768011444027317454","result":"blocked","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_InvalidPort/port_non_numeric
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"url_connectivity_test","host":"http://example.com:abc/path","request_id":"test-1768011444027442354","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestURLConnectivity_InvalidPort (0.00s)
--- PASS: TestURLConnectivity_InvalidPort/port_zero (0.00s)
--- PASS: TestURLConnectivity_InvalidPort/port_negative (0.00s)
--- PASS: TestURLConnectivity_InvalidPort/port_too_large (0.00s)
--- PASS: TestURLConnectivity_InvalidPort/port_non_numeric (0.00s)
=== RUN TestURLConnectivity_HTTPSScheme
--- PASS: TestURLConnectivity_HTTPSScheme (0.01s)
=== RUN TestURLConnectivity_ExplicitPort
--- PASS: TestURLConnectivity_ExplicitPort (0.00s)
=== RUN TestURLConnectivity_DefaultHTTPPort
--- PASS: TestURLConnectivity_DefaultHTTPPort (0.00s)
=== RUN TestURLConnectivity_ConnectionTimeout
--- PASS: TestURLConnectivity_ConnectionTimeout (0.10s)
=== RUN TestURLConnectivity_RequestHeaders
--- PASS: TestURLConnectivity_RequestHeaders (0.00s)
=== RUN TestURLConnectivity_EmptyURL
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"url_connectivity_test","host":"","request_id":"test-1768011444140529788","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestURLConnectivity_EmptyURL (0.00s)
=== RUN TestURLConnectivity_MalformedURL
=== RUN TestURLConnectivity_MalformedURL/://missing-scheme
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"url_connectivity_test","host":"://missing-scheme","request_id":"test-1768011444140750969","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_MalformedURL/http://
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"url_connectivity_test","host":"","request_id":"test-1768011444140886880","result":"blocked","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_MalformedURL/http:///no-host
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"url_connectivity_test","host":"","request_id":"test-1768011444141011500","result":"blocked","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestURLConnectivity_MalformedURL (0.00s)
--- PASS: TestURLConnectivity_MalformedURL/://missing-scheme (0.00s)
--- PASS: TestURLConnectivity_MalformedURL/http:// (0.00s)
--- PASS: TestURLConnectivity_MalformedURL/http:///no-host (0.00s)
=== RUN TestURLConnectivity_IPv6Loopback
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"ssrf_block","host":"::1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
--- PASS: TestURLConnectivity_IPv6Loopback (0.00s)
=== RUN TestURLConnectivity_HeadMethod
--- PASS: TestURLConnectivity_HeadMethod (0.00s)
=== RUN TestResolveAllowedIP_LoopbackWithAllowLocalhost
--- PASS: TestResolveAllowedIP_LoopbackWithAllowLocalhost (0.00s)
=== RUN TestResolveAllowedIP_LoopbackWithoutAllowLocalhost
--- PASS: TestResolveAllowedIP_LoopbackWithoutAllowLocalhost (0.00s)
=== RUN TestURLConnectivity_HTTPSDefaultPort
--- PASS: TestURLConnectivity_HTTPSDefaultPort (0.01s)
=== RUN TestURLConnectivity_ValidPortNumber
--- PASS: TestURLConnectivity_ValidPortNumber (0.00s)
=== RUN TestURLConnectivity_PublicIPLiteralHTTP
--- PASS: TestURLConnectivity_PublicIPLiteralHTTP (0.00s)
=== RUN TestURLConnectivity_DNSResolutionError
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"url_connectivity_test","host":"nonexistent-domain-xyz123456.invalid","request_id":"test-1768011444155460119","result":"error","resolved_ips":null,"blocked_reason":"","user_id":"system","source_ip":""}
--- PASS: TestURLConnectivity_DNSResolutionError (0.00s)
=== RUN TestResolveAllowedIP_PublicIPv4Literal
--- PASS: TestResolveAllowedIP_PublicIPv4Literal (0.00s)
=== RUN TestResolveAllowedIP_PublicIPv6Literal
--- PASS: TestResolveAllowedIP_PublicIPv6Literal (0.00s)
=== RUN TestResolveAllowedIP_PrivateIPBlocked
=== RUN TestResolveAllowedIP_PrivateIPBlocked/RFC1918_10x
=== RUN TestResolveAllowedIP_PrivateIPBlocked/RFC1918_172x
=== RUN TestResolveAllowedIP_PrivateIPBlocked/RFC1918_192x
=== RUN TestResolveAllowedIP_PrivateIPBlocked/LinkLocal
=== RUN TestResolveAllowedIP_PrivateIPBlocked/Metadata
--- PASS: TestResolveAllowedIP_PrivateIPBlocked (0.00s)
--- PASS: TestResolveAllowedIP_PrivateIPBlocked/RFC1918_10x (0.00s)
--- PASS: TestResolveAllowedIP_PrivateIPBlocked/RFC1918_172x (0.00s)
--- PASS: TestResolveAllowedIP_PrivateIPBlocked/RFC1918_192x (0.00s)
--- PASS: TestResolveAllowedIP_PrivateIPBlocked/LinkLocal (0.00s)
--- PASS: TestResolveAllowedIP_PrivateIPBlocked/Metadata (0.00s)
=== RUN TestURLConnectivity_PrivateNetworkRanges
=== RUN TestURLConnectivity_PrivateNetworkRanges/RFC1918_10x
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"ssrf_block","host":"10.255.255.255","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_PrivateNetworkRanges/RFC1918_172x
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"ssrf_block","host":"172.31.255.255","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_PrivateNetworkRanges/RFC1918_192x
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"ssrf_block","host":"192.168.255.255","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_PrivateNetworkRanges/LinkLocal
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"ssrf_block","host":"169.254.1.1","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_PrivateNetworkRanges/ZeroNet
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"ssrf_block","host":"0.0.0.0","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
=== RUN TestURLConnectivity_PrivateNetworkRanges/Broadcast
2026/01/10 02:17:24 [SECURITY AUDIT] {"timestamp":"2026-01-10T02:17:24Z","action":"ssrf_block","host":"255.255.255.255","request_id":"","result":"blocked","resolved_ips":null,"blocked_reason":"private_ip","user_id":"system","source_ip":""}
--- PASS: TestURLConnectivity_PrivateNetworkRanges (0.00s)
--- PASS: TestURLConnectivity_PrivateNetworkRanges/RFC1918_10x (0.00s)
--- PASS: TestURLConnectivity_PrivateNetworkRanges/RFC1918_172x (0.00s)
--- PASS: TestURLConnectivity_PrivateNetworkRanges/RFC1918_192x (0.00s)
--- PASS: TestURLConnectivity_PrivateNetworkRanges/LinkLocal (0.00s)
--- PASS: TestURLConnectivity_PrivateNetworkRanges/ZeroNet (0.00s)
--- PASS: TestURLConnectivity_PrivateNetworkRanges/Broadcast (0.00s)
=== RUN TestURLConnectivity_MultipleStatusCodes
=== RUN TestURLConnectivity_MultipleStatusCodes/200_OK
=== RUN TestURLConnectivity_MultipleStatusCodes/201_Created
=== RUN TestURLConnectivity_MultipleStatusCodes/204_NoContent
=== RUN TestURLConnectivity_MultipleStatusCodes/400_BadRequest
=== RUN TestURLConnectivity_MultipleStatusCodes/401_Unauthorized
=== RUN TestURLConnectivity_MultipleStatusCodes/403_Forbidden
=== RUN TestURLConnectivity_MultipleStatusCodes/404_NotFound
=== RUN TestURLConnectivity_MultipleStatusCodes/429_TooManyRequests
=== RUN TestURLConnectivity_MultipleStatusCodes/500_InternalServerError
=== RUN TestURLConnectivity_MultipleStatusCodes/502_BadGateway
=== RUN TestURLConnectivity_MultipleStatusCodes/503_ServiceUnavailable
=== RUN TestURLConnectivity_MultipleStatusCodes/504_GatewayTimeout
--- PASS: TestURLConnectivity_MultipleStatusCodes (0.02s)
--- PASS: TestURLConnectivity_MultipleStatusCodes/200_OK (0.00s)
--- PASS: TestURLConnectivity_MultipleStatusCodes/201_Created (0.00s)
--- PASS: TestURLConnectivity_MultipleStatusCodes/204_NoContent (0.00s)
--- PASS: TestURLConnectivity_MultipleStatusCodes/400_BadRequest (0.00s)
--- PASS: TestURLConnectivity_MultipleStatusCodes/401_Unauthorized (0.00s)
--- PASS: TestURLConnectivity_MultipleStatusCodes/403_Forbidden (0.00s)
--- PASS: TestURLConnectivity_MultipleStatusCodes/404_NotFound (0.00s)
--- PASS: TestURLConnectivity_MultipleStatusCodes/429_TooManyRequests (0.00s)
--- PASS: TestURLConnectivity_MultipleStatusCodes/500_InternalServerError (0.00s)
--- PASS: TestURLConnectivity_MultipleStatusCodes/502_BadGateway (0.00s)
--- PASS: TestURLConnectivity_MultipleStatusCodes/503_ServiceUnavailable (0.00s)
--- PASS: TestURLConnectivity_MultipleStatusCodes/504_GatewayTimeout (0.00s)
=== RUN TestURLConnectivity_RedirectToPrivateIP
--- PASS: TestURLConnectivity_RedirectToPrivateIP (0.00s)
=== RUN TestValidateRedirectTarget_ValidExternalRedirect
--- PASS: TestValidateRedirectTarget_ValidExternalRedirect (0.00s)
=== RUN TestValidateRedirectTarget_SameSchemeAllowed
--- PASS: TestValidateRedirectTarget_SameSchemeAllowed (0.00s)
=== RUN TestURLConnectivity_NetworkError
--- PASS: TestURLConnectivity_NetworkError (0.00s)
=== RUN TestURLConnectivity_HTTPSWithDefaultPort
--- PASS: TestURLConnectivity_HTTPSWithDefaultPort (0.01s)
=== RUN TestURLConnectivity_HTTPWithExplicitPortValidation
--- PASS: TestURLConnectivity_HTTPWithExplicitPortValidation (0.00s)
=== RUN TestIsDockerBridgeIP_AllCases
=== RUN TestIsDockerBridgeIP_AllCases/docker_bridge_172_17
=== RUN TestIsDockerBridgeIP_AllCases/docker_bridge_172_18
=== RUN TestIsDockerBridgeIP_AllCases/docker_bridge_172_31
=== RUN TestIsDockerBridgeIP_AllCases/public_ip
=== RUN TestIsDockerBridgeIP_AllCases/localhost
=== RUN TestIsDockerBridgeIP_AllCases/private_10x
=== RUN TestIsDockerBridgeIP_AllCases/private_192x
=== RUN TestIsDockerBridgeIP_AllCases/empty
=== RUN TestIsDockerBridgeIP_AllCases/invalid
=== RUN TestIsDockerBridgeIP_AllCases/hostname
=== RUN TestIsDockerBridgeIP_AllCases/ipv6_loopback
--- PASS: TestIsDockerBridgeIP_AllCases (0.00s)
--- PASS: TestIsDockerBridgeIP_AllCases/docker_bridge_172_17 (0.00s)
--- PASS: TestIsDockerBridgeIP_AllCases/docker_bridge_172_18 (0.00s)
--- PASS: TestIsDockerBridgeIP_AllCases/docker_bridge_172_31 (0.00s)
--- PASS: TestIsDockerBridgeIP_AllCases/public_ip (0.00s)
--- PASS: TestIsDockerBridgeIP_AllCases/localhost (0.00s)
--- PASS: TestIsDockerBridgeIP_AllCases/private_10x (0.00s)
--- PASS: TestIsDockerBridgeIP_AllCases/private_192x (0.00s)
--- PASS: TestIsDockerBridgeIP_AllCases/empty (0.00s)
--- PASS: TestIsDockerBridgeIP_AllCases/invalid (0.00s)
--- PASS: TestIsDockerBridgeIP_AllCases/hostname (0.00s)
--- PASS: TestIsDockerBridgeIP_AllCases/ipv6_loopback (0.00s)
=== RUN TestURLConnectivity_RedirectChain
--- PASS: TestURLConnectivity_RedirectChain (0.00s)
=== RUN TestValidateRedirectTarget_FirstRedirect
--- PASS: TestValidateRedirectTarget_FirstRedirect (0.00s)
=== RUN TestURLConnectivity_ResponseBodyClosed
--- PASS: TestURLConnectivity_ResponseBodyClosed (0.00s)
PASS
coverage: 89.2% of statements
ok github.com/Wikid82/charon/backend/internal/utils (cached) coverage: 89.2% of statements
=== RUN TestFull
=== PAUSE TestFull
=== CONT TestFull
--- PASS: TestFull (0.00s)
PASS
coverage: 100.0% of statements
ok github.com/Wikid82/charon/backend/internal/version (cached) coverage: 100.0% of statements
github.com/Wikid82/charon/backend/pkg/dnsprovider coverage: 0.0% of statements
=== RUN TestCloudflareProvider
--- PASS: TestCloudflareProvider (0.00s)
=== RUN TestRoute53Provider
--- PASS: TestRoute53Provider (0.00s)
=== RUN TestDigitalOceanProvider
--- PASS: TestDigitalOceanProvider (0.00s)
=== RUN TestGoogleCloudDNSProvider
--- PASS: TestGoogleCloudDNSProvider (0.00s)
=== RUN TestAzureProvider
--- PASS: TestAzureProvider (0.00s)
=== RUN TestNamecheapProvider
--- PASS: TestNamecheapProvider (0.00s)
=== RUN TestGoDaddyProvider
--- PASS: TestGoDaddyProvider (0.00s)
=== RUN TestHetznerProvider
--- PASS: TestHetznerProvider (0.00s)
=== RUN TestVultrProvider
--- PASS: TestVultrProvider (0.00s)
=== RUN TestDNSimpleProvider
--- PASS: TestDNSimpleProvider (0.00s)
=== RUN TestProviderRegistration
--- PASS: TestProviderRegistration (0.00s)
PASS
coverage: 30.4% of statements
ok github.com/Wikid82/charon/backend/pkg/dnsprovider/builtin (cached) coverage: 30.4% of statements
FAIL