fix(admin): hash-conflict routes served at sane path — resolve buttons were dead

The admin group already sits under the /api prefix, so registering
"/api/admin/hash-conflicts" produced /api/api/admin/hash-conflicts while the
hash-conflicts page's htmx buttons posted to /api/admin/hash-conflicts/:id/
resolve — a 404 that htmx swallows silently (no swap, no error), so duplicate-
content resolution has been broken since the feature shipped (03cb4c78).

Verified live: sane path 401 anon -> 200 with admin token; doubled path 404.
Caller audit found no other consumers (Android app, koplugin, web reader,
tests, Bruno: no references). Docs already describe the sane path and are now
correct without edits.
This commit is contained in:
John O'Keefe committed 2026-10-24 14:33:37 -04:00
1 parent 84cd6328f4
commit 11b179b91f
1 file changed
+7 -3
+7 -3
View File
@@ -409,9 +409,13 @@ func RegisterRoutes(cfg *Config) *handlers.Handler {
admin := protected.Group("", handlers.AdminMiddleware) admin := protected.Group("", handlers.AdminMiddleware)
registerScannerRoutes(protected, admin, scannerHandler) registerScannerRoutes(protected, admin, scannerHandler)
// Hash conflict routes (admin only) // Hash conflict routes (admin only). NOTE: `admin` already sits under the
admin.GET("/api/admin/hash-conflicts", cfg.HashConflictsHandler.ListHashConflicts) // /api group (protected), so these paths must NOT start with /api —
admin.POST("/api/admin/hash-conflicts/:id/resolve", cfg.HashConflictsHandler.ResolveHashConflict) // they used to, producing /api/api/admin/hash-conflicts while the admin
// page's htmx buttons posted to /api/admin/hash-conflicts/:id/resolve,
// which 404'd silently (htmx swaps nothing on error responses).
admin.GET("/admin/hash-conflicts", cfg.HashConflictsHandler.ListHashConflicts)
admin.POST("/admin/hash-conflicts/:id/resolve", cfg.HashConflictsHandler.ResolveHashConflict)
return scannerHandler return scannerHandler
} }