Files
Agent-System-Backend/internal/store/platform_account_write.go
T
weichen adcd8fefd2 Fence U3 account writes and stabilize directory cursors
Why: Account disable could be followed by late Backend business writes, API key creation could implicitly create users, account bootstrap locks could invert, and directory cursors were process-local or leaked out-of-scope changes.

Evidence: Local go test ./... and isolated PostgreSQL package suites passed on the staged candidate; exact committed-head SELF replay and stage 6 human review remain pending.

Impact: Adds final account transactions and external-effect checks across HTTP, Host, Bus and run manager; tightens API key issuance and persists versioned cursor signing. Delegated RDM rename still needs the separately proposed real-operator contract, so A1 and stage 6 are not complete.

Refs: Documents U3 r1, approved A1-A4 amendment fb3a821, pending delegated-projection amendment 5783940, Dev feature/iam-u3-account-directory-recovery.
2026-10-14 07:33:54 +00:00

96 lines
3.8 KiB
Go

package store
import (
"database/sql"
"time"
core "agent-system-core"
)
func (s *Store) CreateBackgroundTaskAccountChecked(actor, kind, title, conversationID string, allowImplicitDefault bool) (BackgroundTask, error) {
now := time.Now().UTC().Format(time.RFC3339)
task := BackgroundTask{ID: NewID("task"), Owner: actor, Kind: kind, Title: title, Status: "queued",
ConversationID: conversationID, CreatedAt: now, UpdatedAt: now}
err := s.withEffectiveAccountWrite(actor, allowImplicitDefault, func(tx *sql.Tx, _ Account) error {
_, err := tx.Exec(s.q(`INSERT INTO background_tasks(id,owner,kind,title,status,progress,error,conversation_id,created_at,updated_at)
VALUES(?,?,?,?,?,?,?,?,?,?)`), task.ID, actor, task.Kind, task.Title, task.Status, task.Progress,
task.Error, task.ConversationID, task.CreatedAt, task.UpdatedAt)
return err
})
return task, err
}
func (s *Store) UpdateBackgroundTaskAccountChecked(actor, id, status string, progress int, errText string, allowImplicitDefault bool) error {
return s.withEffectiveAccountWrite(actor, allowImplicitDefault, func(tx *sql.Tx, _ Account) error {
res, err := tx.Exec(s.q(`UPDATE background_tasks SET status=?,progress=?,error=?,updated_at=? WHERE id=? AND owner=?`),
status, progress, errText, time.Now().UTC().Format(time.RFC3339), id, actor)
if err != nil {
return err
}
if n, err := res.RowsAffected(); err != nil {
return err
} else if n != 1 {
return ErrNotFound
}
return nil
})
}
func (s *Store) PutMemoryAccountChecked(actor string, entry core.MemoryEntry, allowImplicitDefault bool) (core.MemoryEntry, error) {
if entry.ID == "" {
entry.ID = NewID("mem")
}
now := time.Now().UTC()
if entry.CreatedAt.IsZero() {
entry.CreatedAt = now
}
entry.LastAccessed = now
expiry := ""
if entry.ExpiresAt != nil {
expiry = entry.ExpiresAt.UTC().Format(time.RFC3339)
}
err := s.withEffectiveAccountWrite(actor, allowImplicitDefault, func(tx *sql.Tx, _ Account) error {
_, err := tx.Exec(s.q(`INSERT INTO memory_entries(id,owner,scope,project_id,typ,content,source,confidence,created_at,last_accessed,expires_at)
VALUES(?,?,?,?,?,?,?,?,?,?,?)`), entry.ID, actor, entry.Scope, string(entry.ProjectID), entry.Type,
entry.Content, entry.Source, entry.Confidence, entry.CreatedAt.UTC().Format(time.RFC3339),
entry.LastAccessed.UTC().Format(time.RFC3339), expiry)
return err
})
return entry, err
}
func (s *Store) AppendAuditEventAccountChecked(actor string, event AuditEvent, allowImplicitDefault bool) error {
event.Owner = actor
if event.Actor == "" {
event.Actor = actor
}
if event.Time == "" {
event.Time = time.Now().UTC().Format(time.RFC3339)
}
return s.withEffectiveAccountWrite(actor, allowImplicitDefault, func(tx *sql.Tx, _ Account) error {
_, err := tx.Exec(s.q(`INSERT INTO audit_events(time,owner,action,actor,target,evidence,trace_id) VALUES(?,?,?,?,?,?,?)`),
event.Time, actor, event.Action, event.Actor, event.Target, event.Evidence, event.TraceID)
return err
})
}
func (s *Store) SetPluginEnabledAccountChecked(actor, pluginID string, enabled, allowImplicitDefault bool) error {
flag := 0
if enabled {
flag = 1
}
return s.withEffectiveAccountWrite(actor, allowImplicitDefault, func(tx *sql.Tx, _ Account) error {
_, err := tx.Exec(s.q(`INSERT INTO plugin_grants(owner,plugin_id,enabled) VALUES(?,?,?)
ON CONFLICT(owner,plugin_id) DO UPDATE SET enabled=excluded.enabled`), actor, pluginID, flag)
return err
})
}
func (s *Store) PutPluginKVAccountChecked(actor, pluginID, key, value string, allowImplicitDefault bool) error {
return s.withEffectiveAccountWrite(actor, allowImplicitDefault, func(tx *sql.Tx, _ Account) error {
_, err := tx.Exec(s.q(`INSERT INTO plugin_kv(plugin_id,owner,k,v) VALUES(?,?,?,?)
ON CONFLICT(plugin_id,owner,k) DO UPDATE SET v=excluded.v`), pluginID, actor, key, value)
return err
})
}