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.
105 lines
4.4 KiB
Go
105 lines
4.4 KiB
Go
package store
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
|
|
core "agent-system-core"
|
|
)
|
|
|
|
func TestSurfaceAccountCheckedWritesStopAfterDisable(t *testing.T) {
|
|
st := openTestStore(t)
|
|
for _, a := range []struct {
|
|
owner string
|
|
admin bool
|
|
}{{"admin", true}, {"alice", false}} {
|
|
if err := st.CreateAccount(a.owner, "", "", a.admin); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
activation, err := st.SetActivationAccountChecked("alice", "genui", true, false)
|
|
if err != nil || !activation.Enabled {
|
|
t.Fatalf("activation: %+v %v", activation, err)
|
|
}
|
|
snap := core.SurfaceSnapshot{Identity: core.SurfaceIdentity{SurfaceID: "surf_checked", Owner: "alice", PluginID: "genui"},
|
|
Compat: core.SurfaceCompat{SchemaVersion: core.SurfaceSchemaVersion, CatalogVersion: core.SurfaceCatalogVersion},
|
|
ActivationEpoch: activation.Epoch, Spec: core.SurfaceSpec{Title: "Before"}}
|
|
snap, err = st.SaveSurfaceSnapshotAccountChecked("alice", snap, false)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := st.SetSurfaceEventPendingAccountChecked("alice", snap.Identity.SurfaceID, snap.Revision, true, false); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
action := SurfaceActionRecord{Owner: "alice", SurfaceID: string(snap.Identity.SurfaceID), ActionID: "builtin.help", RequestID: "req1", Revision: snap.Revision, State: "submitted"}
|
|
if _, first, err := st.SaveSurfaceActionIfAbsentAccountChecked("alice", action, false); err != nil || !first {
|
|
t.Fatalf("action insert: %v %v", first, 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)
|
|
}
|
|
for name, write := range map[string]func() error{
|
|
"activation": func() error { _, err := st.SetActivationAccountChecked("alice", "genui", false, false); return err },
|
|
"snapshot": func() error { _, err := st.SaveSurfaceSnapshotAccountChecked("alice", snap, false); return err },
|
|
"pending": func() error {
|
|
return st.SetSurfaceEventPendingAccountChecked("alice", snap.Identity.SurfaceID, snap.Revision, false, false)
|
|
},
|
|
"action insert": func() error {
|
|
action.RequestID = "req2"
|
|
_, _, err := st.SaveSurfaceActionIfAbsentAccountChecked("alice", action, false)
|
|
return err
|
|
},
|
|
"action final": func() error {
|
|
return st.UpdateSurfaceActionStateAccountChecked("alice", action.SurfaceID, action.ActionID, "req1", "committed", "{}", "", false)
|
|
},
|
|
} {
|
|
if err := write(); !errors.Is(err, ErrAccountForbidden) {
|
|
t.Errorf("%s: got %v, want account forbidden", name, err)
|
|
}
|
|
}
|
|
got, err := st.GetSurfaceAction("alice", action.SurfaceID, action.ActionID, "req1")
|
|
if err != nil || got.State != "submitted" {
|
|
t.Fatalf("disabled actor changed action: %+v %v", got, err)
|
|
}
|
|
if _, err := st.GetSurfaceAction("alice", action.SurfaceID, action.ActionID, "req2"); !errors.Is(err, ErrNotFound) {
|
|
t.Fatalf("late action inserted: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSurfaceAccountCheckedOwnerAndImplicitDefault(t *testing.T) {
|
|
st := openTestStore(t)
|
|
if _, err := st.SetActivationAccountChecked(OwnerDefault, "genui", true, false); !errors.Is(err, ErrAccountForbidden) {
|
|
t.Fatalf("implicit owner without allowance: %v", err)
|
|
}
|
|
if _, err := st.SetActivationAccountChecked(OwnerDefault, "genui", true, true); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := st.CreateAccount("admin", "", "", true); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := st.CreateAccount("alice", "", "", false); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := st.SetActivationAccountChecked("alice", "genui", true, false); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
snap := core.SurfaceSnapshot{Identity: core.SurfaceIdentity{SurfaceID: "surf_alice", Owner: "alice", PluginID: "genui"}, Spec: core.SurfaceSpec{Title: "Owner"}}
|
|
if _, err := st.SaveSurfaceSnapshotAccountChecked("admin", snap, false); !errors.Is(err, ErrAccountForbidden) {
|
|
t.Fatalf("cross-owner snapshot: %v", err)
|
|
}
|
|
snap, err := st.SaveSurfaceSnapshotAccountChecked("alice", snap, false)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := st.SetSurfaceEventPendingAccountChecked("admin", snap.Identity.SurfaceID, snap.Revision, true, false); !errors.Is(err, ErrNotFound) {
|
|
t.Fatalf("cross-owner pending: %v", err)
|
|
}
|
|
if _, _, err := st.SaveSurfaceActionIfAbsentAccountChecked("admin", SurfaceActionRecord{Owner: "admin", SurfaceID: string(snap.Identity.SurfaceID), ActionID: "builtin.help", RequestID: "foreign"}, false); !errors.Is(err, ErrNotFound) {
|
|
t.Fatalf("cross-owner action: %v", err)
|
|
}
|
|
}
|