fix: harden API, DB schema, and CLI safety
- Add 'reminder' to glyph CHECK constraint (was accepted by parser but
rejected by DB)
- Default serve bind to 127.0.0.1, add --host flag for LAN access
- Validate card_data as JSON in Store.Create/Update/Promote
- Return pagination envelope {data,total,limit,offset} from list endpoint
- Append absorb breadcrumb to source entity before soft-delete
- Add Levenshtein fuzzy match to catch command typos before routing to add
- Replace DDL string-matching migrations with versioned schema_version table
- Update web UI and API tests for envelope response format
This commit is contained in:
+28
-5
@@ -104,6 +104,9 @@ type EntityUpdate struct {
|
||||
}
|
||||
|
||||
func (s *Store) Create(e *Entity) error {
|
||||
if e.CardData != nil && !json.Valid([]byte(*e.CardData)) {
|
||||
return ErrInvalidCardData
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
e.ID = nibulid.New()
|
||||
e.CreatedAt = now
|
||||
@@ -179,7 +182,7 @@ func (s *Store) Get(id string) (*Entity, error) {
|
||||
return e, nil
|
||||
}
|
||||
|
||||
func (s *Store) List(params ListParams) ([]*Entity, error) {
|
||||
func listWhere(params ListParams) (string, []any) {
|
||||
var where []string
|
||||
var args []any
|
||||
|
||||
@@ -214,10 +217,23 @@ func (s *Store) List(params ListParams) ([]*Entity, error) {
|
||||
args = append(args, string(*params.CardTypeFilter))
|
||||
}
|
||||
|
||||
whereClause := ""
|
||||
clause := ""
|
||||
if len(where) > 0 {
|
||||
whereClause = "WHERE " + strings.Join(where, " AND ")
|
||||
clause = "WHERE " + strings.Join(where, " AND ")
|
||||
}
|
||||
return clause, args
|
||||
}
|
||||
|
||||
func (s *Store) Count(params ListParams) (int, error) {
|
||||
whereClause, args := listWhere(params)
|
||||
query := fmt.Sprintf("SELECT COUNT(*) FROM entities e %s", whereClause)
|
||||
var count int
|
||||
err := s.db.QueryRow(query, args...).Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (s *Store) List(params ListParams) ([]*Entity, error) {
|
||||
whereClause, args := listWhere(params)
|
||||
|
||||
orderCol := "e.created_at"
|
||||
switch params.Sort {
|
||||
@@ -336,6 +352,9 @@ func (s *Store) Update(id string, u *EntityUpdate) error {
|
||||
args = append(args, string(*u.CardType))
|
||||
}
|
||||
if u.CardData != nil {
|
||||
if !json.Valid([]byte(*u.CardData)) {
|
||||
return ErrInvalidCardData
|
||||
}
|
||||
sets = append(sets, "card_data = ?")
|
||||
args = append(args, *u.CardData)
|
||||
}
|
||||
@@ -370,6 +389,9 @@ func (s *Store) Promote(id string, cardType CardType, cardData *string) error {
|
||||
|
||||
dataVal := "{}"
|
||||
if cardData != nil {
|
||||
if !json.Valid([]byte(*cardData)) {
|
||||
return ErrInvalidCardData
|
||||
}
|
||||
dataVal = *cardData
|
||||
}
|
||||
|
||||
@@ -473,8 +495,9 @@ func (s *Store) Absorb(targetID, sourceID string) error {
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := tx.Exec("UPDATE entities SET deleted_at = ? WHERE id = ?",
|
||||
now, sourceID); err != nil {
|
||||
absorbNote := source.Body + "\n\n[absorbed into " + targetID + "]"
|
||||
if _, err := tx.Exec("UPDATE entities SET body = ?, deleted_at = ?, modified_at = ? WHERE id = ?",
|
||||
absorbNote, now, now, sourceID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user