Monorepo for Tangled
0

Configure Feed

Select the types of activity you want to include in your feed.

knotserver/xrpc: defer plc submission until repo setup succeeds

Previously, CreateRepo submitted the PLC DID before the remaining local setup steps had completed. If RBAC setup or hook installation failed after that point, the handler cleaned up local state but still left behind a published DID with no corresponding repo on disk. Move PLC submission to the end of the create flow so the DID is only published after local repo setup succeeds. Also roll back repo RBAC state during cleanup, and treat hook setup failure as fatal instead of silently continuing.

authored by

kppcn.tngl.sh and committed by tangled.org (Apr 8, 2026, 6:57 AM UTC) b907bf93 f0b47935

+29 -17
+29 -17
knotserver/xrpc/create_repo.go
··· 145 145 146 146 repoPath, _ := securejoin.SecureJoin(h.Config.Repo.ScanPath, repoDid) 147 147 rbacPath := repoDid 148 + repoAddedToRBAC := false 148 149 149 150 cleanup := func() { 150 151 if rmErr := os.RemoveAll(repoPath); rmErr != nil { ··· 153 154 } 154 155 155 156 cleanupAll := func() { 157 + if repoAddedToRBAC { 158 + if rmErr := h.Enforcer.RemoveRepo(actorDid.String(), rbac.ThisServer, rbacPath); rmErr != nil { 159 + l.Error("failed to clean up repo permissions", "error", rmErr.Error()) 160 + } 161 + } 156 162 cleanup() 157 163 if delErr := h.Db.DeleteRepoKey(repoDid); delErr != nil { 158 164 l.Error("failed to clean up repo key", "error", delErr.Error()) ··· 195 201 } 196 202 } 197 203 204 + // add perms for this user to access the repo 205 + err = h.Enforcer.AddRepo(actorDid.String(), rbac.ThisServer, rbacPath) 206 + if err != nil { 207 + l.Error("adding repo permissions", "error", err.Error()) 208 + cleanupAll() 209 + writeError(w, xrpcerr.GenericError(err), http.StatusInternalServerError) 210 + return 211 + } 212 + repoAddedToRBAC = true 213 + 214 + if err := hook.SetupRepo( 215 + hook.Config( 216 + hook.WithScanPath(h.Config.Repo.ScanPath), 217 + hook.WithInternalApi(h.Config.Server.InternalListenAddr), 218 + ), 219 + repoPath, 220 + ); err != nil { 221 + l.Error("setting up repo hooks", "error", err.Error()) 222 + cleanupAll() 223 + writeError(w, xrpcerr.GenericError(err), http.StatusInternalServerError) 224 + return 225 + } 226 + 198 227 if prepared != nil { 199 228 plcCtx, plcCancel := context.WithTimeout(context.Background(), 30*time.Second) 200 229 defer plcCancel() ··· 205 234 return 206 235 } 207 236 } 208 - 209 - // add perms for this user to access the repo 210 - err = h.Enforcer.AddRepo(actorDid.String(), rbac.ThisServer, rbacPath) 211 - if err != nil { 212 - l.Error("adding repo permissions", "error", err.Error()) 213 - cleanupAll() 214 - writeError(w, xrpcerr.GenericError(err), http.StatusInternalServerError) 215 - return 216 - } 217 - 218 - hook.SetupRepo( 219 - hook.Config( 220 - hook.WithScanPath(h.Config.Repo.ScanPath), 221 - hook.WithInternalApi(h.Config.Server.InternalListenAddr), 222 - ), 223 - repoPath, 224 - ) 225 237 226 238 // HACK: request crawl for this repository 227 239 // Users won't want to sync entire network from their local knotmirror.