chore: auto-commit (23 archivos)

- app.md
- backend/auth.go
- backend/db.go
- backend/dist/assets/index-CPqSy0gZ.js
- backend/dist/index.html
- backend/handlers.go
- backend/main.go
- frontend/src/App.tsx
- frontend/src/api.ts
- frontend/src/components/KanbanCard.tsx
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-13 18:40:22 +02:00
parent f1ee116d3b
commit a34a8142cc
23 changed files with 2034 additions and 1184 deletions
+92 -2
View File
@@ -280,6 +280,91 @@ func handleMoveCard(db *DB) http.HandlerFunc {
}
}
// GET /api/cards/{id}/messages → [CardMessage, ...]
func handleListCardMessages(db *DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
msgs, err := db.ListCardMessages(id)
if err != nil {
serverError(w, err)
return
}
infra.HTTPJSONResponse(w, http.StatusOK, msgs)
}
}
// POST /api/cards/{id}/messages { body }
func handleCreateCardMessage(db *DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
var body struct {
Body string `json:"body"`
}
if err := infra.HTTPParseBody(r, &body, maxBodyBytes); err != nil {
badRequest(w, err.Error())
return
}
if strings.TrimSpace(body.Body) == "" {
badRequest(w, "body required")
return
}
actor, _ := infra.UserIDFromContext(r.Context(), userCtxKey)
if actor == "" {
infra.HTTPErrorResponse(w, infra.HTTPError{Status: http.StatusUnauthorized, Code: "unauthorized", Message: "session required"})
return
}
m, err := db.CreateCardMessage(id, actor, body.Body)
if err != nil {
if strings.Contains(err.Error(), "not found") {
notFound(w, err.Error())
return
}
serverError(w, err)
return
}
infra.HTTPJSONResponse(w, http.StatusCreated, m)
}
}
// DELETE /api/cards/{cid}/messages/{mid}
func handleDeleteCardMessage(db *DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
mid := r.PathValue("mid")
actor, _ := infra.UserIDFromContext(r.Context(), userCtxKey)
if actor == "" {
infra.HTTPErrorResponse(w, infra.HTTPError{Status: http.StatusUnauthorized, Code: "unauthorized", Message: "session required"})
return
}
if err := db.DeleteCardMessage(mid, actor); err != nil {
if strings.Contains(err.Error(), "not found") {
notFound(w, err.Error())
return
}
serverError(w, err)
return
}
w.WriteHeader(http.StatusNoContent)
}
}
// POST /api/cards/{id}/duplicate
func handleDuplicateCard(db *DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
actor, _ := infra.UserIDFromContext(r.Context(), userCtxKey)
c, err := db.DuplicateCard(id, actor)
if err != nil {
if strings.Contains(err.Error(), "not found") {
notFound(w, "card not found")
return
}
serverError(w, err)
return
}
infra.HTTPJSONResponse(w, http.StatusCreated, c)
}
}
// GET /api/cards/{id}/history → [HistoryEntry, ...]
func handleCardHistory(db *DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
@@ -330,9 +415,10 @@ func handlePurgeCard(db *DB) http.HandlerFunc {
}
}
func apiRoutes(db *DB, chatWorkdir string, logger *ChatLogger, internalToken string) []infra.Route {
func apiRoutes(db *DB, chatWorkdir string, logger *ChatLogger, internalToken string, flags *FeatureFlags) []infra.Route {
return []infra.Route{
{Method: "POST", Path: "/api/auth/register", Handler: handleRegister(db)},
{Method: "GET", Path: "/api/flags", Handler: handleListFlags(flags)},
{Method: "POST", Path: "/api/auth/register", Handler: handleRegister(db, flags)},
{Method: "POST", Path: "/api/auth/login", Handler: handleLogin(db)},
{Method: "POST", Path: "/api/auth/logout", Handler: handleLogout(db)},
{Method: "GET", Path: "/api/me", Handler: handleMe(db)},
@@ -348,6 +434,10 @@ func apiRoutes(db *DB, chatWorkdir string, logger *ChatLogger, internalToken str
{Method: "PUT", Path: "/api/cards/{id}/stickers", Handler: handleUpdateCardStickers(db)},
{Method: "DELETE", Path: "/api/cards/{id}", Handler: handleDeleteCard(db)},
{Method: "POST", Path: "/api/cards/{id}/move", Handler: handleMoveCard(db)},
{Method: "POST", Path: "/api/cards/{id}/duplicate", Handler: handleDuplicateCard(db)},
{Method: "GET", Path: "/api/cards/{id}/messages", Handler: handleListCardMessages(db)},
{Method: "POST", Path: "/api/cards/{id}/messages", Handler: handleCreateCardMessage(db)},
{Method: "DELETE", Path: "/api/cards/{id}/messages/{mid}", Handler: handleDeleteCardMessage(db)},
{Method: "GET", Path: "/api/cards/{id}/history", Handler: handleCardHistory(db)},
{Method: "GET", Path: "/api/trash", Handler: handleListTrash(db)},
{Method: "POST", Path: "/api/cards/{id}/restore", Handler: handleRestoreCard(db)},