// Package domain contains the canonical identity model for KeyCape. // This is the source of truth for all user, group, client, and MFA data. // All provisioning, tests, and migrations derive from these types. package domain import "time" // User is the canonical identity entity — source of truth for all user data. type User struct { ID string `yaml:"id" json:"id"` Username string `yaml:"username" json:"username"` DisplayName string `yaml:"displayName" json:"displayName"` Email string `yaml:"email" json:"email"` Enabled bool `yaml:"enabled" json:"enabled"` Groups []string `yaml:"groups" json:"groups"` Roles []string `yaml:"roles" json:"roles"` // Tenant is the NetKingdom IAM Profile tenant claim value // (e.g. "tenant:friendly:binky"), per net-kingdom/canon/standards/ // iam-profile_v0.3.md. Empty means "not yet assigned" -- token // issuance falls back to the platform default (KEY-WP-0005-T01) rather // than emitting an empty tenant claim, since the profile requires // tenant on every token. Tenant string `yaml:"tenant,omitempty" json:"tenant,omitempty"` MFAEnrollment *MFAEnrollment `yaml:"mfaEnrollment,omitempty" json:"mfaEnrollment,omitempty"` LDAPAttributes map[string]string `yaml:"ldapAttributes,omitempty" json:"ldapAttributes,omitempty"` } // Group is a named collection of users. type Group struct { ID string `yaml:"id" json:"id"` Name string `yaml:"name" json:"name"` Description string `yaml:"description" json:"description"` Members []string `yaml:"members" json:"members"` } // Role is a named permission set. type Role struct { ID string `yaml:"id" json:"id"` Name string `yaml:"name" json:"name"` Description string `yaml:"description" json:"description"` } // Client is a registered OIDC client (static in v0.1 — no dynamic registration). type Client struct { ClientID string `yaml:"clientId" json:"clientId"` DisplayName string `yaml:"displayName" json:"displayName"` RedirectURIs []string `yaml:"redirectUris" json:"redirectUris"` AllowedScopes []string `yaml:"allowedScopes" json:"allowedScopes"` GrantTypes []string `yaml:"grantTypes" json:"grantTypes"` ClientType string `yaml:"clientType" json:"clientType"` // "confidential" | "public" SecretRef string `yaml:"secretRef,omitempty" json:"secretRef,omitempty"` ClientSecret string `yaml:"-" json:"-"` Audience string `yaml:"audience,omitempty" json:"audience,omitempty"` ServiceSubject string `yaml:"serviceSubject,omitempty" json:"serviceSubject,omitempty"` Tenant string `yaml:"tenant,omitempty" json:"tenant,omitempty"` Roles []string `yaml:"roles,omitempty" json:"roles,omitempty"` // TokenLifetime overrides the server default for this confidential client. // It is internal runtime policy, not identity data serialized into tokens. TokenLifetime time.Duration `yaml:"-" json:"-"` MFARequired *bool `yaml:"mfaRequired,omitempty" json:"mfaRequired,omitempty"` RegistrationURL string `yaml:"registrationUrl,omitempty" json:"registrationUrl,omitempty"` EnrollmentURL string `yaml:"enrollmentUrl,omitempty" json:"enrollmentUrl,omitempty"` } // Membership links a user to a group. type Membership struct { UserID string `yaml:"userId" json:"userId"` GroupID string `yaml:"groupId" json:"groupId"` } // MFAEnrollment records that a user has enrolled MFA via privacyIDEA. type MFAEnrollment struct { UserID string `yaml:"userId" json:"userId"` Provider string `yaml:"provider" json:"provider"` // "privacyidea" State string `yaml:"state" json:"state"` // "enabled" | "disabled" | "pending" EnrolledAt time.Time `yaml:"enrolledAt,omitempty" json:"enrolledAt,omitempty"` } // Directory is the full canonical identity directory snapshot. // Used for provisioning, validation, and migration operations. type Directory struct { Users []User `yaml:"users" json:"users"` Groups []Group `yaml:"groups" json:"groups"` Roles []Role `yaml:"roles" json:"roles"` Clients []Client `yaml:"clients" json:"clients"` }