// Package user owns the "主人" (owner) profile and account whitelist that the // channel-layer policy engine uses for identity recognition. Per DevDocs/design/11 // §0, owner identification is structural — channel actor metadata matched against // this whitelist — and is never driven by prompt text or an LLM judgment. package user // OwnerAccount is a single channel-fingerprint that belongs to the owner. The // policy engine matches channel-layer actor metadata (platform + account id) // against this list. type OwnerAccount struct { Platform string `yaml:"platform"` AccountID string `yaml:"accountId"` } // OwnerProfile is the owner's identity record: a display name, the default // persona bound to the owner, and the per-channel account whitelist. It is the // source data for owner recognition; it is not injected into the persona's // prompt as an authority. type OwnerProfile struct { ID string `yaml:"id"` DisplayName string `yaml:"displayName"` DefaultPersona string `yaml:"defaultPersona"` Accounts []OwnerAccount `yaml:"accounts"` // IdentityFile is the path to the LLM-visible identity/relationship note // (persona knowledge, NOT an access-control authority). IdentityFile string `yaml:"identityFile,omitempty"` Notes string `yaml:"notes,omitempty"` } // IsOwner reports whether the given (platform, accountID) pair belongs to the // owner according to the whitelist. func (p *OwnerProfile) IsOwner(platform, accountID string) bool { for _, a := range p.Accounts { if a.Platform == platform && a.AccountID == accountID { return true } } return false } // AccountIdentifiers returns the distinct channel account ids owned by the // owner, for diagnostics / listing. func (p *OwnerProfile) AccountIdentifiers() []string { seen := make(map[string]struct{}, len(p.Accounts)) out := make([]string, 0, len(p.Accounts)) for _, a := range p.Accounts { if _, ok := seen[a.Platform+":"+a.AccountID]; ok { continue } seen[a.Platform+":"+a.AccountID] = struct{}{} out = append(out, a.Platform+":"+a.AccountID) } return out }