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.
48 lines
1.6 KiB
Go
48 lines
1.6 KiB
Go
package store
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
|
|
core "agent-system-core"
|
|
)
|
|
|
|
func TestAccountCheckedEventAppendStopsAfterDisable(t *testing.T) {
|
|
st := openTestStore(t)
|
|
if err := st.CreateAccount("admin", "Admin", "hash", true); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := st.CreateAccount("alice", "Alice", "hash", false); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
project, err := st.CreateProject("alice", "fixture")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
conversation, err := st.CreateConversation("alice", string(project.ID), "fixture", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
one := []core.StreamEvent{{ConversationID: string(conversation.ID), Type: core.EvCardCreated, V: core.ProtocolVersion}}
|
|
if _, err := st.AppendEventsAccountChecked("admin", string(conversation.ID), one, false); !errors.Is(err, ErrNotFound) {
|
|
t.Fatalf("administrator bypassed conversation owner: %v", err)
|
|
}
|
|
if _, err := st.AppendEventsAccountChecked("alice", string(conversation.ID), one, false); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
account, err := st.GetAccountByOwner("alice")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := st.SetAccountEnabled("admin", account.ID, account.StateVersion, false); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := st.AppendEventsAccountChecked("alice", string(conversation.ID), one, false); !errors.Is(err, ErrAccountForbidden) {
|
|
t.Fatalf("disabled account appended event: %v", err)
|
|
}
|
|
var count int
|
|
if err := st.DB().QueryRow(st.q(`SELECT COUNT(*) FROM events WHERE conversation_id=?`), conversation.ID).Scan(&count); err != nil || count != 1 {
|
|
t.Fatalf("event count=%d err=%v", count, err)
|
|
}
|
|
}
|