프로젝트

일반

사용자정보

Actions

이슈 #434

진행중
JL HP

[Go backport] Supabase GoTrue 인증 전환 — Phase 1: 인프라 + 인증 코어

이슈 #434: [Go backport] Supabase GoTrue 인증 전환 — Phase 1: 인프라 + 인증 코어

James Lee이(가) 약 5시간 전에 추가함.

상태:
해결
우선순위:
높음
담당자:
목표버전:
시작일:
2026/05/11
완료일:
진척도:

0%

추정시간:

설명

배경

Rust 포팅(alphea-ai-edge)에서 진행된 Supabase GoTrue 인증 전환(#411, #421, #424) 과 관련 부속 작업(#375, #390, #256)을 원본 Go 프로젝트(alphea-rpc-next, branch next)로 백포트한다. 현재 프로젝트는 Rust 포팅을 중단하고 다시 Go 원본에서 예정 항목들을 진행하는 방향으로 복귀했다.

Phase 분할

본 이슈는 Phase 1 — 인프라 + 인증 코어 에 한정한다. 후속 phase 는 별도 이슈로 분리한다.

Phase 범위 이슈
1 (본 이슈) GoTrue 인프라 + 표준 JWT + AuthContext user_id + 스키마 user_id 전환 + AuthService 축소 + Node/User/Wallet 핸들러 caller 전환 본 이슈
2 AGX 회계 user_id 종속 전환 + wallet_adjustments ledger 후속 (#421 백포트)
3 Admin Dev Console GoTrue Sign Up/Log In proxy + UI 후속 (#424 백포트)

Phase 1 작업 범위

인프라

  • alphea-rpc/docker-compose.yml 에 gotrue 서비스 추가 (supabase/gotrue:v2.158.1, port 9011)
  • Postgres init 스크립트 추가 (db/init/01-gotrue-schema.sql):
    • CREATE EXTENSION pgcrypto, uuid-ossp
    • CREATE SCHEMA auth, GRANT ALL ON SCHEMA auth TO alphea
    • Supabase 표준 role 5개(postgres, anon, authenticated, service_role, supabase_auth_admin) NOLOGIN 으로 생성 + alphea 에 멤버십 부여 (PG16+ grantor 요구사항)
  • .env.example 정리: GOTRUE_URL, GOTRUE_INTERNAL_URL, GOTRUE_MAILER_AUTOCONFIRM, SITE_URL 추가. AUTH_SALT/PASSWORD_SALT 제거.

JWT 검증

  • 비표준 SHA256(sigInput + secret) 방식을 표준 HMAC-SHA256 으로 교체 (github.com/golang-jwt/jwt/v5)
  • GoTrue 발행 토큰 호환: typ claim 없음 → token_type = "user"
  • Node 토큰: typ = "node", sub = node_id 유지
  • JWT_SECRET 은 GoTrue 의 GOTRUE_JWT_SECRET 과 동일값 사용

AuthContext / 인터셉터

  • internal/server/interceptors.go 의 AuthContext 에 UserID (UUID), Email, TokenType 추가
  • WalletFromContext → UserIDFromContext, NodeIDFromContext 헬퍼 추가
  • Public path allow-list 정리: 제거된 Auth RPC 제외, GoTrue proxy 경로 미포함(Phase 3)

DB 스키마 (v12 마이그레이션, clean rewrite)

  • accounts: user_id UUID UNIQUE 컬럼 추가, email, display_name, profile_icon, last_active_at 유지. wallet_address/password/account_type/referral_code 는 deprecated 표시 (Phase 1 에서는 제거하지 않고 NOT NULL 제약 완화)
  • wallets: 기존 (account_id, balance) 구조 폐기. 신규 (user_id UUID, wallet_address TEXT) 1:N. UNIQUE(user_id, wallet_address). 기존 데이터 DROP.
  • nodes: owner_user_id UUID 컬럼 추가, owner_wallet_address 는 호환 위해 유지하되 더 이상 권한 판단에 사용 안 함
  • 기존 wallet 식별 기반 dev 데이터 DROP 허용 (clean rewrite)

AuthService 축소 (proto)

  • auth.proto 에서 다음 RPC 완전 제거:
    • Challenge, Verify, SetPassword, Login, EmailRegister, EmailRecover
  • 유지: GenerateKeypair
  • 관련 메시지 타입 제거 (ChallengeRequest/Response, VerifyRequest, LoginRequest, EmailRecoveryRequest/Response, SetPasswordRequest/Response)
  • handler/auth.go 단순화
  • internal/domain/auth/challenge.go 는 노드 등록 챌린지 용도로 유지 (NodeService.NodeChallenge 만 사용)

NodeService

  • NodeChallenge: owner_wallet_address 요청 필드 제거(또는 무시)
  • RegisterNode: user JWT 필수, owner_user_id = JWT sub UUID 로 저장
  • Heartbeat / DeleteNode: owner_user_id 기준 소유권 검증
  • ConnectNode: node 토큰 검증 흐름 유지. token 의 sub 는 node_id (또는 owner user_id) 와 노드 헤더 일치 확인

UserService

  • GetUser(wallet_address) → wallets 테이블에서 user_id 조회 → accounts 조회. 미존재 시 NOT_FOUND
  • friend_count 계산은 기존 friends 테이블 그대로 사용 (Phase 2 에서 user_id 기반 재설계)

WalletService

  • 모든 RPC: caller user_id 로 본인 소유 wallets 확인. 요청의 wallet_address 가 caller 의 wallets 에 속하지 않으면 PermissionDenied
  • 잔액/수익 계산 로직 자체는 Phase 2 에서 처리. Phase 1 에서는 인증 흐름만 전환하고 기존 wallet_address 기반 receipts 합산 유지.

마이그레이션 전략

  • Clean rewrite — Rust 측과 동일. dev/qa DB 는 reset 필요. scripts/ec2/reset-db.sh 와 호환.
  • 기존 wallet challenge/verify 로 만들어진 accounts/wallets/nodes dev 데이터는 마이그레이션 시 DROP.
  • 운영(prod) 에는 본 phase 미적용 (브랜치는 next 한정).

DoD

  • GoTrue 가 docker compose up 으로 정상 기동(Listening on :9011, autoconfirm=true)
  • Postgres init script 가 pgcrypto/uuid-ossp/auth schema + supabase role 5종 생성
  • GoTrue 발행 access_token 으로 Authorization: Bearer <jwt> 헤더 보내면 WalletService/GetReceipts 등 보호 RPC 통과
  • AuthContext.UserID 가 GoTrue sub (UUID) 와 일치
  • NodeService.RegisterNode 가 user JWT 없으면 거부
  • NodeService.Heartbeat/DeleteNode 가 다른 사용자 노드 조작 시 PermissionDenied
  • UserService.GetUser(wallet) 가 wallets join 으로 정상 조회
  • make build, make test 통과
  • auth.proto 에서 제거된 RPC 들에 대한 클라이언트 호환성은 본 phase 에서 보장하지 않음 — 클라이언트 마이그레이션은 모바일 SDK 측에서 별도 처리

관련 이슈

  • Rust 측 원본: #411(GoTrue 인증), #421(AGX 회계 — Phase 2), #424(Admin UI — Phase 3), #375(전역 JWT 인터셉터 — Go 측에는 이미 존재), #390(UserService.GetUser), #256(JWT 인증 API)
  • DB: #254 (스키마 변경 — refs 라인에 동반)

연결된 일감 8 (8 건 진행 중 — 모두 미완료)

다음 일감과 관련됨: 이슈 #411: Supabase GoTrue 인증 전환 — wallet-based auth 제거 및 GoTrue JWT 통합해결James Lee2026/04/24

Actions
다음 일감과 관련됨: 이슈 #421: AGX 잔액을 Wallet 종속 → Account(GoTrue user_id) 종속으로 전환해결James Lee2026/04/27

Actions
다음 일감과 관련됨: 이슈 #424: Dev Console 에 GoTrue Sign Up / Log In 통합 — 테스트 환경 간소화해결James Lee2026/04/27

Actions
다음 일감과 관련됨: 업무 #390: Port UserService.GetUser to alphea-ai-edge해결James Lee2026/04/20

Actions
다음 일감과 관련됨: 이슈 #375: JWT 전역 인터셉터 구현 (alphea-ai-edge)해결James Lee2026/04/15

Actions
다음 일감과 관련됨: 이슈 #256: 8-4. 사용자 인증 API (JWT)해결James Lee2026/04/282026/04/30

Actions
다음 일감과 관련됨: 이슈 #254: 8-2. 데이터베이스 스키마 설계 (사용자. 앱. 일정)진행James Lee2026/04/282026/04/29

Actions
다음에 진행할 일감: 이슈 #435: [Go backport] AGX 회계 user_id 종속 전환 — Phase 2해결Henry Park2026/05/122026/05/12

Actions

JL James Lee이(가) 6달 전에 변경 Actions #1

  • 다음 일감과 관련됨:에 이슈 #411: Supabase GoTrue 인증 전환 — wallet-based auth 제거 및 GoTrue JWT 통합이(가) 추가되었습니다.

JL James Lee이(가) 6달 전에 변경 Actions #2

  • 다음 일감과 관련됨:에 이슈 #421: AGX 잔액을 Wallet 종속 → Account(GoTrue user_id) 종속으로 전환이(가) 추가되었습니다.

JL James Lee이(가) 6달 전에 변경 Actions #3

  • 다음 일감과 관련됨:에 이슈 #424: Dev Console 에 GoTrue Sign Up / Log In 통합 — 테스트 환경 간소화이(가) 추가되었습니다.

JL James Lee이(가) 6달 전에 변경 Actions #4

  • 다음 일감과 관련됨:에 업무 #390: Port UserService.GetUser to alphea-ai-edge이(가) 추가되었습니다.

JL James Lee이(가) 6달 전에 변경 Actions #5

  • 다음 일감과 관련됨:에 이슈 #375: JWT 전역 인터셉터 구현 (alphea-ai-edge)이(가) 추가되었습니다.

JL James Lee이(가) 6달 전에 변경 Actions #6

  • 다음 일감과 관련됨:에 이슈 #256: 8-4. 사용자 인증 API (JWT)이(가) 추가되었습니다.

JL James Lee이(가) 6달 전에 변경 Actions #7

  • 다음 일감과 관련됨:에 이슈 #254: 8-2. 데이터베이스 스키마 설계 (사용자. 앱. 일정)이(가) 추가되었습니다.

JL James Lee이(가) 6달 전에 변경 Actions #8

  • 상태을(를) 신규에서 해결(으)로 변경되었습니다.

Phase 1 구현 완료

commit:server|03c6c64

Rust 측의 #411 / #421 (일부) / #424 (인프라 부분) / #375 / #390 결과를 원본 Go 프로젝트 alphea-rpc-next 의 next 브랜치로 백포트. 쓰기 시점의 목표는 GoTrue UUID 일니티를 권위로 세우고 기존 wallet challenge 흐름을 완전히 교체하는 것.

적용된 변경

인프라

  • alphea-rpc/docker-compose.yml 에 supabase/gotrue:v2.158.1 서비스 추가 (포트 9011, GOTRUE_JWT_SECRET=$JWT_SECRET, MAILER_AUTOCONFIRM=true)
  • alphea-rpc/db/init/01-gotrue-schema.sql 가 Postgres 최초 기동 시 pgcrypto / uuid-ossp 확장, auth 스키마, Supabase 표준 role 5종(postgres/anon/authenticated/service_role/supabase_auth_admin) 를 생성하고 alphea 로에 멤버십 부여 (PG16+ grantor 요구사항 충족)
  • .env.example 에 GOTRUE_URL / GOTRUE_INTERNAL_URL / GOTRUE_PORT / GOTRUE_MAILER_AUTOCONFIRM / SITE_URL 추가

JWT 검증

  • internal/domain/auth/jwt.go 가 기존 비표준 SHA256(sigInput + secret) 를 버리고 github.com/golang-jwt/jwt/v4 기반 표준 HS256 구현으로 교체. GoTrue 발행 토큰(typ 없음, sub=UUID) 과 자체 발행 노드 토큰(typ="node", sub=node_id) 동일 경로로 검증

서버 인터셉터

  • internal/server/interceptors.go 의 토큰 컨텍스트를 구조체로 재설계: AuthContext{UserID, NodeID, Email, TokenType, Wallet}, 헬퍼 UserIDFromContext / NodeIDFromContext / AuthFromContext 추가. 기존 WalletFromContext 는 하위 호환을 위해 유지(deprecated)
  • AuthInterceptor 의 verify 시그니쳐를 VerifyFunc func(token) (*AuthContext, error) 로 일반화, public allow-list 에서 제거된 Auth RPC 목록 정리

Proto / Handler

  • auth.proto 를 GenerateKeypair 한 개만 남기도록 축소. Challenge / Verify / SetPassword / Login / EmailRegister / EmailRecover RPC 와 관련 메시지 제거
  • node.proto: NodeChallengeRequest.owner_wallet_address 제거. RegisterNodeRequest.owner_wallet_address → wallet_address (서명 검증용 키페어 주소로 의미 주석 부여, 소유권은 JWT 기반)
  • handler/auth.go 는 GenerateKeypair + VerifyToken 헬퍼만 유지
  • handler/node.go: RegisterNode 가 user JWT 필수, 서명 검증 후 nodes.owner_user_id 에 caller UUID 바인딩. 이미 다른 user 에게 소유권이 있으면 PermissionDenied. Heartbeat 와 ConnectNode 가 user/node 권한 분기 검증 (requireNodeAccess)
  • ConnectNode 는 추가로 토큰의 sub 가 X-Node-ID 헤더와 일치하는지도 확인

스토어

  • internal/store/migrations.go 에 v12 추가: accounts.user_id UUID UNIQUE / accounts.display_name 컬럼 추가, wallet_address / account_type NULL 허용으로 완화. nodes.owner_user_id UUID 컬럼 + 인덱스. accounts / wallets / friends / referral_claims / rewards_log / nodes 와 wallet_comments 를 TRUNCATE (clean rewrite 정책 — dev/qa DB 는 reset 필요)
  • internal/store/accounts.go 에 Account.UserID *string / Account.DisplayName *string 추가, scanAccount 를 sql.NullString 기반으로 교체. GetAccountByUserID / EnsureAccountForUser 헬퍼 추가
  • internal/store/nodes.go 는 Node.OwnerUserID *string 으로 확장, RegisterNodeForUser 헬퍼 (UPDATE 후 더 이상 없으면 INSERT) 추가

테스트

  • handler/node_test.go 에 새 인증 모델 기준의 테스트 2개: 익명 요청의 Unauthenticated, user JWT 헤더 포함 시 owner_user_id 바인딩 검증. 기존 wallet-identity 기반 테스트 제거
  • handler/test_helpers.go 로 공용 uniqueTestWallet 도우미 헬퍼 이동
  • auth_test.go 는 제거된 RPC 들을 테스트하므로 삭제. JWT 검증 단위 테스트 4개가 jwt_test.go 에 남아 GoTrue 스타일 토큰과 노드 토큰을 모두 검증

문서

  • CLAUDE.md Key Implementation Notes 업데이트: GoTrue / 표준 HMAC-SHA256 / accounts.user_id / nodes.owner_user_id / AuthService 축소 반영, 환경변수 표에 GoTrue 관련 항목 추가

DoD 체크

  • GoTrue 가 docker compose 로 기동하도록 설정 (실제 적용은 dev DB reset 후 docker compose up -d --build 필요)
  • Postgres init script 가 pgcrypto/uuid-ossp/auth schema + supabase role 5종 생성
  • 서버가 GoTrue 발행 JWT 를 표준 HS256 경로로 검증 (go test ./internal/domain/auth 통과)
  • AuthContext.UserID 가 GoTrue sub UUID 와 일치하는 구조 확립
  • RegisterNode 가 user JWT 없으면 Unauthenticated 거부, 있으면 owner_user_id 바인딩
  • Heartbeat / ConnectNode 가 owner/node 일치 불일치 시 PermissionDenied
  • go build ./..., go vet ./..., go test ./... 통과 (PG 통합 테스트는 TEST_DATABASE_URL 미설정으로 skip)
  • auth.proto 에서 제거된 RPC 들은 wire 호환성 보장하지 않음 (모바일 SDK 측 마이그레이션은 별도 이슈)

후속 (이번 범위 완)

  • Phase 2 (#421 백포트): job_receipts / aggregated_earnings 를 user_id 키로 이동 + wallet_adjustments ledger 도입 + 1:N wallets 테이블 재설계 + FriendsService / WalletService caller user_id 기반 전환
  • Phase 3 (#424 백포트): Admin Dev Console 에 GoTrue Sign Up / Log In proxy 추가

JL James Lee이(가) 6달 전에 변경 Actions #9

  • 다음에 진행할 일감:에 이슈 #435: [Go backport] AGX 회계 user_id 종속 전환 — Phase 2이(가) 추가되었습니다.

CP Chris Park이(가) 6달 전에 변경 Actions #10

  • 담당자을(를) James Lee에서 Henry Park(으)로 변경되었습니다.
Actions

내보내기 PDF Atom