// 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 const ( AccountTypeHuman AccountType = "human" AccountTypeSystem AccountType = "system" ) // AccountStatus represents the lifecycle state of an account. type AccountStatus string 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 { ID int64 `json:"-"` UUID string `json:"id"` Username string `json:"username"` AccountType AccountType `json:"account_type"` Status AccountStatus `json:"status"` TOTPRequired bool `json:"totp_required"` // PasswordHash is a PHC-format Argon2id string. Never returned in API // responses; populated only when reading from the database. PasswordHash string `json:"-"` // TOTPSecretEnc and TOTPSecretNonce hold the AES-256-GCM-encrypted TOTP // shared secret. Never returned in API responses. TOTPSecretEnc []byte `json:"-"` TOTPSecretNonce []byte `json:"-"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt *time.Time `json:"deleted_at,omitempty"` } // Role is a string label assigned to an account to grant permissions. type Role struct { ID int64 `json:"-"` AccountID int64 `json:"-"` Role string `json:"role"` GrantedBy *int64 `json:"-"` GrantedAt time.Time `json:"granted_at"` } // 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 { ID int64 `json:"-"` JTI string `json:"jti"` AccountID int64 `json:"-"` ExpiresAt time.Time `json:"expires_at"` IssuedAt time.Time `json:"issued_at"` RevokedAt *time.Time `json:"revoked_at,omitempty"` RevokeReason string `json:"revoke_reason,omitempty"` CreatedAt time.Time `json:"created_at"` } // 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 { ID int64 `json:"-"` AccountID int64 `json:"-"` JTI string `json:"jti"` ExpiresAt time.Time `json:"expires_at"` CreatedAt time.Time `json:"created_at"` } // 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. type PGCredential struct { ID int64 `json:"-"` AccountID int64 `json:"-"` PGHost string `json:"host"` PGPort int `json:"port"` PGDatabase string `json:"database"` PGUsername string `json:"username"` // PGPassword is plaintext only after decryption. Never log or serialise. PGPassword string `json:"-"` // PGPasswordEnc and PGPasswordNonce are the AES-256-GCM ciphertext and // nonce stored in the database. PGPasswordEnc []byte `json:"-"` PGPasswordNonce []byte `json:"-"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // AuditEvent represents a single entry in the append-only audit log. // Details must never contain credential material (passwords, tokens, secrets). type AuditEvent struct { ID int64 `json:"id"` EventTime time.Time `json:"event_time"` EventType string `json:"event_type"` ActorID *int64 `json:"-"` TargetID *int64 `json:"-"` IPAddress string `json:"ip_address,omitempty"` Details string `json:"details,omitempty"` // JSON string; no secrets } // 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" )