feat(api): one API for curl and MCP, REST reads with keys, origin badge with key name
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m16s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m16s
API keys reach tasks and lists over plain REST too (GET /task-lists, GET /tasks with
status/due filters, PATCH/DELETE /thoughts/{id}, GET /lists, list items), guarded by a route
table; notes and settings stay closed. Rights hold for every access alike (webhook:task also
allows create_task over MCP, tasks:write also task delivery).
Tasks, thoughts and list items record which key created them and which one changed them last
(migration 13 replaces agent_mark; origin stays after the user's own edits and survives the
triage into a list item). OriginBadge shows the key name with a webhook or robot icon, details
on hover and tap, and replaces the Webhook and KI badges everywhere, now also on list items.
Settings: category "API" with rights grouped by tasks, lists and inbox and two tabs
(curl / smart home with a Home Assistant sensor, AI agents over MCP). Docs, help, README and
changelog updated; v0.30.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0ca715ba64
commit
b883315914
36 files changed
+1119
-563
No files matched your search
+14
-14
@@ -10,18 +10,18 @@ import (
|
||||
|
||||
// --- API KEYS & WEBHOOKS ---
|
||||
|
||||
// Scopes of an API key. The webhook scopes deliver data (inbox, /webhooks/ingest); the agent scopes
|
||||
// let AI agents read and change tasks and lists over the MCP endpoint. Notes are never reachable with
|
||||
// a key.
|
||||
// Rights of an API key. They hold the same over every access: REST (curl, smart home) and the MCP
|
||||
// endpoint for AI agents. The ids of the first three come from the time they only delivered data
|
||||
// (webhooks) and stay for existing keys. Notes are never reachable with a key.
|
||||
const (
|
||||
ScopeTriage = "webhook:triage" // thoughts into the inbox
|
||||
ScopeTask = "webhook:task" // tasks directly
|
||||
ScopeList = "webhook:list" // items into lists
|
||||
ScopeTask = "webhook:task" // create tasks
|
||||
ScopeList = "webhook:list" // add items to lists
|
||||
|
||||
ScopeTasksRead = "tasks:read" // MCP: task lists and tasks
|
||||
ScopeTasksWrite = "tasks:write" // MCP: create, change and complete tasks
|
||||
ScopeListsRead = "lists:read" // MCP: lists and their items
|
||||
ScopeListsWrite = "lists:write" // MCP: add, change and check off items
|
||||
ScopeTasksRead = "tasks:read" // task lists and tasks
|
||||
ScopeTasksWrite = "tasks:write" // create, change, complete and delete tasks
|
||||
ScopeListsRead = "lists:read" // lists and their items
|
||||
ScopeListsWrite = "lists:write" // add, change and check off items
|
||||
)
|
||||
|
||||
// AllScopes in display order.
|
||||
@@ -99,19 +99,19 @@ func (s *Store) DeleteAPIKey(userID, keyID string) error {
|
||||
}
|
||||
|
||||
func (s *Store) ValidateAPIKeyAndGetUser(rawKey string) (*domain.User, error) {
|
||||
u, _, err := s.ValidateAPIKey(rawKey)
|
||||
u, _, _, err := s.ValidateAPIKey(rawKey)
|
||||
return u, err
|
||||
}
|
||||
|
||||
// ValidateAPIKey returns the owner of a key and the key's scopes.
|
||||
func (s *Store) ValidateAPIKey(rawKey string) (*domain.User, []string, error) {
|
||||
// ValidateAPIKey returns the owner of a key, the key's scopes and its id.
|
||||
func (s *Store) ValidateAPIKey(rawKey string) (*domain.User, []string, string, error) {
|
||||
hash := auth.HashAPIKey(strings.TrimSpace(rawKey))
|
||||
var keyID, userID, scopes string
|
||||
err := s.db.QueryRow(`SELECT id, user_id, scopes FROM api_keys WHERE key_hash = ?`, hash).Scan(&keyID, &userID, &scopes)
|
||||
if err != nil {
|
||||
return nil, nil, errors.New("invalid API key")
|
||||
return nil, nil, "", errors.New("invalid API key")
|
||||
}
|
||||
_, _ = s.db.Exec(`UPDATE api_keys SET last_used_at = ? WHERE id = ?`, domain.NowISO(), keyID)
|
||||
u, err := s.GetUserByID(userID)
|
||||
return u, NormalizeScopes(strings.Split(scopes, ",")), err
|
||||
return u, NormalizeScopes(strings.Split(scopes, ",")), keyID, err
|
||||
}
|
||||
Reference in new issue
Block a user