// Package model defines the shared data types used throughout MCIAS. // These are pure data definitions with no external dependencies. package model import "time" // AccountType distinguishes human interactive accounts from non-interactive // service accounts. type AccountType string // AccountTypeHuman and AccountTypeSystem are the two valid account types. const ( AccountTypeHuman AccountType = "human" AccountTypeSystem AccountType = "system" ) // AccountStatus represents the lifecycle state of an account. type AccountStatus string // AccountStatusActive, AccountStatusInactive, and AccountStatusDeleted are // the valid account lifecycle states. const ( AccountStatusActive AccountStatus = "active" AccountStatusInactive AccountStatus = "inactive" AccountStatusDeleted AccountStatus = "deleted" ) // Account represents a user or service identity in MCIAS. // Fields containing credential material (PasswordHash, TOTPSecretEnc) are // never serialised into API responses — callers must explicitly omit them. type Account struct { CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt *time.Time `json:"deleted_at,omitempty"` UUID string `json:"id"` Username string `json:"username"` AccountType AccountType `json:"account_type"` Status AccountStatus `json:"status"` PasswordHash string `json:"-"` TOTPSecretEnc []byte `json:"-"` TOTPSecretNonce []byte `json:"-"` ID int64 `json:"-"` TOTPRequired bool `json:"totp_required"` } // Role is a string label assigned to an account to grant permissions. type Role struct { GrantedAt time.Time `json:"granted_at"` GrantedBy *int64 `json:"-"` Role string `json:"role"` ID int64 `json:"-"` AccountID int64 `json:"-"` } // TokenRecord tracks an issued JWT by its JTI for revocation purposes. // The raw token string is never stored — only the JTI identifier. type TokenRecord struct { ExpiresAt time.Time `json:"expires_at"` IssuedAt time.Time `json:"issued_at"` CreatedAt time.Time `json:"created_at"` RevokedAt *time.Time `json:"revoked_at,omitempty"` JTI string `json:"jti"` RevokeReason string `json:"revoke_reason,omitempty"` ID int64 `json:"-"` AccountID int64 `json:"-"` } // IsRevoked reports whether the token has been explicitly revoked. func (t *TokenRecord) IsRevoked() bool { return t.RevokedAt != nil } // IsExpired reports whether the token is past its expiry time. func (t *TokenRecord) IsExpired() bool { return time.Now().After(t.ExpiresAt) } // SystemToken represents the current active service token for a system account. type SystemToken struct { ExpiresAt time.Time `json:"expires_at"` CreatedAt time.Time `json:"created_at"` JTI string `json:"jti"` ID int64 `json:"-"` AccountID int64 `json:"-"` } // PGCredential holds Postgres connection details for a system account. // The password is encrypted at rest; PGPassword is only populated after // decryption and must never be logged or included in API responses. // // OwnerID identifies the account permitted to update, delete, and manage // access grants for this credential set. A nil OwnerID means the credential // pre-dates ownership tracking; for backwards compatibility, nil is treated as // unowned (only admins can manage it via the UI). type PGCredential struct { CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` OwnerID *int64 `json:"-"` ServiceAccountUUID string `json:"service_account_uuid,omitempty"` PGUsername string `json:"username"` PGPassword string `json:"-"` ServiceUsername string `json:"service_username,omitempty"` PGDatabase string `json:"database"` PGHost string `json:"host"` PGPasswordEnc []byte `json:"-"` PGPasswordNonce []byte `json:"-"` ID int64 `json:"-"` AccountID int64 `json:"-"` PGPort int `json:"port"` } // AuditEvent represents a single entry in the append-only audit log. // Details must never contain credential material (passwords, tokens, secrets). type AuditEvent struct { EventTime time.Time `json:"event_time"` ActorID *int64 `json:"-"` TargetID *int64 `json:"-"` EventType string `json:"event_type"` IPAddress string `json:"ip_address,omitempty"` Details string `json:"details,omitempty"` ID int64 `json:"id"` } // Audit event type constants — exhaustive list, enforced at write time. const ( EventLoginOK = "login_ok" EventLoginFail = "login_fail" EventLoginTOTPFail = "login_totp_fail" EventTokenIssued = "token_issued" EventTokenRenewed = "token_renewed" EventTokenRevoked = "token_revoked" EventTokenExpired = "token_expired" EventAccountCreated = "account_created" EventAccountUpdated = "account_updated" EventAccountDeleted = "account_deleted" EventRoleGranted = "role_granted" EventRoleRevoked = "role_revoked" EventTOTPEnrolled = "totp_enrolled" EventTOTPRemoved = "totp_removed" EventPGCredAccessed = "pgcred_accessed" EventPGCredUpdated = "pgcred_updated" //nolint:gosec // G101: audit event type string, not a credential EventTagAdded = "tag_added" EventTagRemoved = "tag_removed" EventPolicyRuleCreated = "policy_rule_created" EventPolicyRuleUpdated = "policy_rule_updated" EventPolicyRuleDeleted = "policy_rule_deleted" EventPolicyDeny = "policy_deny" ) // PGCredAccessGrant records that a specific account has been granted read // access to a pg_credentials set. Only the credential owner can manage // grants; grantees can view connection metadata but never the plaintext // password, and they cannot update or delete the credential set. type PGCredAccessGrant struct { GrantedAt time.Time `json:"granted_at"` GrantedBy *int64 `json:"-"` GranteeUUID string `json:"grantee_id"` GranteeName string `json:"grantee_username"` ID int64 `json:"-"` CredentialID int64 `json:"-"` GranteeID int64 `json:"-"` } // Audit event type for pg_credential_access changes. const ( EventPGCredAccessGranted = "pgcred_access_granted" //nolint:gosec // G101: audit event type, not a credential EventPGCredAccessRevoked = "pgcred_access_revoked" //nolint:gosec // G101: audit event type, not a credential ) // PolicyRuleRecord is the database representation of a policy rule. // RuleJSON holds a JSON-encoded policy.RuleBody (all match and effect fields). // The ID, Priority, and Description are stored as dedicated columns. type PolicyRuleRecord struct { CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` CreatedBy *int64 `json:"-"` Description string `json:"description"` RuleJSON string `json:"rule_json"` ID int64 `json:"id"` Priority int `json:"priority"` Enabled bool `json:"enabled"` }