feat(peers): full trust-store UI — accept, reject, revoke, re-authorize

- /api/peers/reject forwards to the auth service's new /internal/reject
  (pending request denied + audited; peer stays on the no-op path).
- TrustedServices panel now has three sections: Requested (Accept/Reject),
  Accepted (Revoke), and Revoked (Re-authorize), with timestamps.
- The old pending 'Ignore' button mapped to revoke, which was the wrong
  operation for a never-approved request.
This commit is contained in:
2026-08-17 00:27:42 +01:00
parent becf3043e3
commit 73fd96d698
6 changed files with 151 additions and 21 deletions
+20
View File
@@ -114,6 +114,26 @@ func (h *Handler) Revoke(w http.ResponseWriter, r *http.Request) {
writeJSON(w, http.StatusOK, map[string]string{"status": "revoked"})
}
// Reject serves POST /api/peers/reject — denies a pending first-contact
// request without authorizing it (the auth service drops the request and
// audits the decision).
func (h *Handler) Reject(w http.ResponseWriter, r *http.Request) {
var action authzAction
if !decodeAction(r, w, &action) {
return
}
client, err := h.ensureClient()
if err != nil {
http.Error(w, "auth management client unavailable: "+err.Error(), http.StatusInternalServerError)
return
}
if err := client.Reject(r.Context(), action.Service, action.Fingerprint); err != nil {
http.Error(w, "failed to reject peer: "+err.Error(), http.StatusBadGateway)
return
}
writeJSON(w, http.StatusOK, map[string]string{"status": "rejected"})
}
func (h *Handler) ensureClient() (*authmgmt.Client, error) {
h.mu.Lock()
defer h.mu.Unlock()