···2828 // during registration. It is stored so the server can build the
2929 // allowCredentials list when requesting an assertion from the passkey.
3030 CredentialID []byte
3131+ // CompatMode enables user-side signing of service-auth JWTs.
3232+ CompatMode bool
3133 Rev string
3234 Root []byte
3335 Preferences []byte
+31-3
server/common.go
···33import (
44 "context"
5566- "pkg.rbrt.fr/vow/models"
76 "gorm.io/gorm"
77+ "pkg.rbrt.fr/vow/models"
88)
991010func (s *Server) getActorByHandle(ctx context.Context, handle string) (*models.Actor, error) {
···31313232func (s *Server) getRepoActorByEmail(ctx context.Context, email string) (*models.RepoActor, error) {
3333 var repo models.RepoActor
3434- if err := s.db.Raw(ctx, "SELECT r.*, a.* FROM repos r LEFT JOIN actors a ON r.did = a.did WHERE r.email= ?", nil, email).Scan(&repo).Error; err != nil {
3434+ // Use explicit column selection to ensure proper mapping to embedded structs.
3535+ if err := s.db.Raw(ctx, `
3636+ SELECT
3737+ r.did, r.created_at, r.email, r.email_confirmed_at, r.email_verification_code,
3838+ r.email_verification_code_expires_at, r.email_update_code, r.email_update_code_expires_at,
3939+ r.password_reset_code, r.password_reset_code_expires_at, r.plc_operation_code,
4040+ r.plc_operation_code_expires_at, r.account_delete_code, r.account_delete_code_expires_at,
4141+ r.password, r.auth_public_key, r.signing_public_key, r.credential_id, r.compat_mode,
4242+ r.rev, r.root, r.preferences, r.deactivated,
4343+ a.handle
4444+ FROM repos r
4545+ LEFT JOIN actors a ON r.did = a.did
4646+ WHERE r.email = ?
4747+ `, nil, email).Scan(&repo).Error; err != nil {
3548 return nil, err
3649 }
3750 if repo.Repo.Did == "" {
···42554356func (s *Server) getRepoActorByDid(ctx context.Context, did string) (*models.RepoActor, error) {
4457 var repo models.RepoActor
4545- if err := s.db.Raw(ctx, "SELECT r.*, a.* FROM repos r LEFT JOIN actors a ON r.did = a.did WHERE r.did = ?", nil, did).Scan(&repo).Error; err != nil {
5858+ // Use explicit column selection to ensure proper mapping to embedded structs.
5959+ // The r.*, a.* pattern can cause issues with GORM's Scan when structs have
6060+ // overlapping field names (both Repo and Actor have "Did").
6161+ if err := s.db.Raw(ctx, `
6262+ SELECT
6363+ r.did, r.created_at, r.email, r.email_confirmed_at, r.email_verification_code,
6464+ r.email_verification_code_expires_at, r.email_update_code, r.email_update_code_expires_at,
6565+ r.password_reset_code, r.password_reset_code_expires_at, r.plc_operation_code,
6666+ r.plc_operation_code_expires_at, r.account_delete_code, r.account_delete_code_expires_at,
6767+ r.password, r.auth_public_key, r.signing_public_key, r.credential_id, r.compat_mode,
6868+ r.rev, r.root, r.preferences, r.deactivated,
6969+ a.handle
7070+ FROM repos r
7171+ LEFT JOIN actors a ON r.did = a.did
7272+ WHERE r.did = ?
7373+ `, nil, did).Scan(&repo).Error; err != nil {
4674 return nil, err
4775 }
4876 if repo.Repo.Did == "" {