Commit Graph

30 Commits

Author SHA1 Message Date
ttipo 9bcbc1564f revert: AI 코드 검토 기능 제거 (85ae82f 되돌림)
통짜 코드 전송 방식이 토큰 비효율·부정확해, 검색 기반(grep으로 좁힌 뒤 관련
스니펫만 판정) 방식으로 재설계하기 위해 일괄 제거. 추후 개선안으로 재작업 예정.

This reverts commit 85ae82f.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 17:56:43 +09:00
ttipo 85ae82f3ce feat: AI 코드 검토 — 연결된 Gitea 코드로 체크리스트 구현 여부 판정
- ChecklistItem.reviewVerdict('done'|'missing'|null) 컬럼 추가 + 응답/프론트 타입 전파
- GiteaService.fetchRepoCode: 기본 브랜치 텍스트 파일 스냅샷(의존성/빌드/바이너리 제외, ~120KB 예산)
- AiService.reviewChecklist: 코드+체크리스트를 Claude 에 보내 항목별 done/missing 판정 후 체크리스트에 반영
- POST /ai/review-checklist(throttle 6/분, Claude 타임아웃 60s), Gitea 미연동/코드없음/항목없음 400
- TaskService.getTaskForReview/applyReviewVerdicts
- 프론트: TaskDetailPage 승인 요청 카드(prog/changes)에 "AI 검토" 버튼 → 체크박스 ✓(초록)/✗(빨강), 요약 배너

베스트에포트 휴리스틱(코드 일부만 검토), Gitea 연동 저장소 한정.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 17:19:01 +09:00
ttipo 57a88ff741 feat: 업무 생성 화면 첨부파일 활성화 (제출 시 업로드)
업로드 API 가 기존 taskId 종속이라 막혀 있던 생성 화면 첨부를 2단계 제출로 해결.
선택한 파일을 메모리에 보유하다 업무 생성/수정 후 그 taskId 로 순차 업로드(베스트에포트,
실패 개수 안내). 수정 모드는 기존 첨부 표시·즉시 삭제 + 새 파일 업로드. 25MB 사전 필터.
백엔드 변경 없음(기존 업로드 엔드포인트 재사용).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 17:18:35 +09:00
ttipo df97719e0f fix: 첨부 다운로드 링크를 백엔드 절대 URL 로 변환
백엔드가 내려준 루트 상대경로(/api/.../download)를 <a href> 가 프론트 오리진으로
해석해 404 페이지가 뜨던 문제 수정. useApi 에 toAbsoluteApiUrl 추가, 첨부 매핑에 적용.
(dev 프론트 5273 / 백엔드 3100 오리진 분리 환경)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 17:18:14 +09:00
ttipo 406e13da1c fix: 업무 상세 활동 탭 내용·시간 간격 축소
활동 항목의 내용과 아래 시간 텍스트 사이 간격(.act-time margin-top)을 0.375rem→0.1875rem 으로 줄임.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 17:17:44 +09:00
ttipo 0976a5057b feat: 업무 작성 AI 할 일 추천
- POST /ai/suggest-checklist — 저장소 표시제목/설명 + 업무 제목/내용을 Claude 에 보내
  카테고리별(필수/추가/보안) 할 일 항목을 JSON 으로 받아 파싱(코드펜스/잡텍스트 방어, 빈 결과 502)
- AiSuggestController + SuggestChecklistDto + AiService.suggestChecklist/parseSuggestions
- 프론트: TaskCreatePage 액션바 "취소 / AI 추천 / 지시 보내기" + 체크리스트 추천 패널
  (카테고리별 항목 클릭 추가·전체 추가·중복 스킵), useAi.suggestChecklist(silent)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 15:05:34 +09:00
ttipo 51b608efeb feat: AI 채팅 다듬기 — 저장소 컨텍스트·표시제목·마크다운 렌더·말투
- 컨텍스트에 저장소 목록 추가(RepoService.findAll), slug 빼고 표시 제목만 노출
- AI 응답 마크다운 렌더링: shared/utils/markdown.ts (escapeHtml 후 신뢰 태그만 조립, 의존성 0, XSS 안전 — 굵게/목록/코드/제목/링크)
- 시스템 프롬프트: 간결·이모지/사과 남발 금지·과도한 존칭 지양·마크다운 사용·저장소는 표시제목으로 안내

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 15:03:59 +09:00
ttipo e432832c92 feat: AI 대화 DB 영속 + 다중 대화/기록 목록
- AiConversation·AiMessage 엔티티(user/conversation CASCADE), 제목 자동 생성
- 대화 스코프 API: GET/POST /ai/conversations, GET/:id, POST/:id/messages, DELETE/:id (전부 본인 소유 스코프 → IDOR 차단)
- 클라는 새 메시지 1건만 전송, 서버가 DB 이력으로 Claude 호출(무상태 /ai/chat 폐기)
- Claude 실패 시 사용자 메시지·빈 대화 롤백(고아 데이터 방지)
- 프론트: AgentChatPanel 채팅↔지난 대화 목록 뷰(열기/삭제), ai.store 재작성(목록·현재 대화)
- 다른 기기·재로그인·새로고침에도 기록 유지

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 08:58:40 +09:00
ttipo 5da3ec8818 feat: AI 채팅 패널 (Claude API)
- 백엔드 modules/ai: POST /ai/chat — Anthropic Messages API 프록시(키 서버 env 한정, 30s 타임아웃, throttle 20/분, 미설정 503/외부오류 502)
- ChatDto 검증(role enum, content 8000자, 메시지 50개 상한), 모델 CLAUDE_MODEL(기본 claude-sonnet-4-6)
- 프론트 AgentChatPanel: 우측 슬라이드 채팅(말풍선/타이핑/에러/새 대화), plain text 렌더로 XSS 안전
- AppShell 헤더에 AI 버튼 상시 노출 — 모든 화면에서 열림
- 대화 이력은 stores/ai.store(싱글톤)에 보관 → 화면 이동에도 유지, '새 대화'로만 초기화
- TaskDetailPage 의 기존 목업 에이전트 패널 전부 제거(보안 L1 해소)
- env.example 에 CLAUDE_MODEL 추가

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 00:04:48 +09:00
ttipo db6a80a6f4 feat: refresh 토큰 완전 회전 + 재사용 탐지
- RefreshSession(패밀리) 테이블 도입 — 한 로그인=1행(currentJti/prevJti/expiresAt)
- /auth/refresh 회전형으로 교체: 현재 jti→새 jti 회전, 옛 토큰 재제출 시 재사용 탐지→패밀리 폐기(401)
- 동시 갱신 오탐 방지: 직전 jti 15초 유예 + 프론트 useApi single-flight refresh
- 로그아웃=해당 세션만 폐기, revokeAllSessions(전 기기) 준비
- tokenVersion·jwt-refresh.strategy·JwtRefreshGuard 제거(refresh는 가드 없이 서비스 직접 처리)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 22:57:01 +09:00
ttipo df268d3b5e chore: env.example 파일 현행화 (development 기준)
- backend/.env.development.example: CLAUDE_API_KEY 추가(dev 실제와 키 셋 일치)
- backend/.env.production.example: 소셜 OAuth·APP_API_URL/FRONTEND_URL·CLAUDE_API_KEY 추가(운영 placeholder)
- frontend/.env.*.example: 고유 키 없음 + VITE_API_BASE_URL docker 주입 설명 헤더 추가

실제 시크릿/인프라 값은 미포함(전부 placeholder).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 22:01:59 +09:00
ttipo 8766a4f5b6 feat: 소셜 로그인(Google/Kakao) 및 회원가입 이메일 인증 추가
- User 엔티티 확장: passwordHash nullable, provider, emailVerified, 인증 토큰 해시/만료(select:false)
- 회원가입: 자동 로그인 폐지 → 미인증 계정 생성 + 인증 메일 발송(MailService 플레이스홀더, 백엔드 로그로 링크 출력)
- 이메일 인증: GET /auth/verify-email(해시 매칭+만료 검사) → 프론트로 리다이렉트, 재발송 엔드포인트
- 로그인 게이트: 미인증 로컬 403 차단, 소셜 전용 계정은 소셜 로그인 안내
- 소셜 OAuth: passport google/kakao 전략(키 미설정 시 자동 비활성), 이메일로 계정 매칭/생성
- 기존 로컬 계정 그랜드페더링(부팅 시 인증 완료 보정)
- 프론트: 가입 후 인증 메일 안내 화면, 로그인 소셜 버튼 실연동 + 인증 결과 배너
- env(APP_API_URL/FRONTEND_URL/GOOGLE_*/KAKAO_*) 문서화, 문서·계약 갱신

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 17:04:30 +09:00
ttipo 7a2c70a260 feat: 저장소 생성 이름 실시간 가용성 체크 + 소유자 아바타 제거
- GET /repos/name-available?slug= 추가(:repoId 앞 선언, Relay slug 중복만 검사)
- 생성 폼: 형식 즉시 검사 + 350ms 디바운스 서버 조회로 상태별(빈칸/형식위반/확인중/사용가능/중복) 색·아이콘 표기
- 항상 떠 있던 정적 "사용 가능한 이름입니다" 표시 제거
- 조직 이니셜 소유자 아바타 제거

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 17:03:59 +09:00
ttipo 8935f6e488 feat: 저장소 설정 권한 게이팅 + Gitea 역동기화 + 설정 로직 정비
설정 탭/권한:
- findOne/update 응답에 현재 사용자 권한(canManage=admin, isOwner=소유자) 포함
  (목록은 캐시·사용자 무관이라 미포함). RepoTabs 가 canManage 일 때만 설정 탭 노출,
  비관리자의 설정 화면 직접 진입은 저장소 상세로 리다이렉트. 입력 비활성화 처리 제거.
- 저장소 삭제는 isOwner 일 때만(비소유자 admin 엔 비활성+안내).

설정 로직 버그/정리:
- update 가 이전 값과 비교해 실제 변경분만 활동/Gitea/캐시 반영
  (무변경 저장 시 허위 'renamed'/'visibility_changed' 활동이 쌓이던 버그 수정).
- 위험구역의 미구현 'Gitea 저장소 이름 변경'(slug rename) 스텁 제거.
- 조직 owner 아바타(하드코딩 'M') 제거.

Gitea 역동기화(Gitea=SSOT):
- 동기화 매칭 시 slug(rename)·공개범위·기본 브랜치를 Gitea 기준으로 끌어옴
  → Gitea 에서 직접 바꿔도 Relay 가 따라가고 slugName 도 갱신돼 쓰기 경로 일치
  (rename 후 옛 이름으로 쓰기 호출이 404 나던 desync 해소). 중복 매칭 가드 추가.
- 표시명/설명은 Gitea 단일 description 합본 구조라 Relay-SSOT 유지(외부 편집 시 깨짐 방지).
- GiteaService.updateRepo 에 default_branch 추가 + update 가 브랜치도 Gitea 에 푸시(양방향 일치).

검증: 백엔드 build/lint 0·20 tests, 프론트 type-check/lint/build 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 15:39:41 +09:00
ttipo 56c89d9927 fix: 저장소 활동 피드 상태 변경 문구를 알림·상세 탭과 정렬
task.status_changed 를 일반 라벨('승인 대기로 변경')이 아닌 행위 중심 문구로
파생(statusFrom→statusTo): 시작/다시 시작·승인을 요청·수정을 요청·완료(승인).
업무 상세 활동 탭(task.store)·알림과 동일 표현으로 일관화. 안 쓰게 된
taskStatusLabel·TaskStatus import 제거.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 15:39:21 +09:00
ttipo 5351373694 feat: 프로필 이미지(avatarUrl) 필드 + UserAvatar 도입, 색상·이니셜 아바타 제거
- 백엔드: User.avatarUrl(nullable) 추가 → PublicUser/toPublic 로 모든 유저 응답에 노출.
- 프론트: 공용 UserAvatar(이미지 있으면 img, 없으면 사람 실루엣 placeholder)로
  전 화면 아바타 통일(상단바·저장소·멤버·담당자·활동·내업무·댓글·AI패널).
  화면마다 달랐던 색상+이니셜/하드코딩 청록 아바타 제거.
- 죽은 코드 정리: 색상·이니셜 시스템(avatarColor/initialOf/AvatarColor 유틸·타입,
  User/RepoActivityItem 의 initial/color, 전역·컴포넌트 .av-a~.av-f CSS) +
  미사용 정적 목업 데이터(USERS/REPOS/REPO_TASKS/TASK_DETAIL/MY_TASKS_*/REPO_MEMBERS/
  REPO_ACTIVITY 등) 전부 삭제. relay.mock.ts 는 뷰 타입 + countActive 만 유지.

avatar_url 컬럼은 dev synchronize 가 추가. 업로드(실제 사진 설정)는 추후 단계.
검증: 백엔드 build 0, 프론트 type-check/lint/build 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 14:04:09 +09:00
ttipo 47567b94a0 fix: 로그인 후 항상 저장소 목록으로 진입
미인증으로 보호 라우트 진입 시 가드가 붙이던 redirect 쿼리로 로그인 후 이전 화면에
복귀하던 동작 제거. LoginPage 는 항상 /repos 로 이동하고, 가드는 redirect 쿼리를
더 이상 보존하지 않는다(딥링크 복귀 제거).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 13:12:56 +09:00
ttipo d87726194b feat: 실시간 알림(인앱+SSE, Redis pub/sub) + Redis 캐싱 (8단계)
알림(8-2):
- Notification 모듈 + SSE 스트림(@Sse, @SkipTransform 으로 표준 래퍼 우회).
- 12종 알림 적재(업무 지시/해제/승인요청/승인/수정요청/시작/마감변경/삭제/댓글·답글,
  멤버 초대/역할변경/제거). 행위자 제외 + 중복 dedup. AppShell 종(미읽음 뱃지·드롭다운).
- 실시간 fan-out: REDIS_HOST 시 ioredis pub/sub(다중 인스턴스), 미설정 시 인메모리 폴백.

Redis 캐싱(8-3):
- CacheModule → @keyv/redis(미설정 시 인메모리 폴백). 저장소 목록을 버전 네임스페이스로
  캐시, 생성/수정/삭제·동기화·멤버 초대/제거 시 무효화(공유 버전 키라 다중 인스턴스 정합).
- enableShutdownHooks 로 종료 시 Redis 연결 graceful close.

검증: 백엔드 build/lint 0·20 tests, 프론트 build/lint/type-check 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 13:12:47 +09:00
ttipo ef858f6e34 feat: 저장소 업무 세그먼트·검색·더보기 + 멤버 전체 로드 (8-1 페이지네이션 마무리)
- 저장소 업무 목록(RepoDetailPage): 세그먼트/검색을 백엔드로 이전(클라 필터 제거),
  응답 counts 로 세그먼트 배지, 더보기(오프셋) 추가. task.store 에 total/counts/hasMore/loadMore.
- 멤버: member.store.fetchList 가 페이지네이션 API 를 끝까지 순회해 전체 로드
  (역할/검색 카운트 전수 + TaskCreatePage 담당자 후보 보장).
- 타입 신설: TaskSegment/TaskSegmentCounts/ApiRepoTaskListResult.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 13:12:21 +09:00
ttipo c128b19599 fix: 목록 페이지네이션 응답 계약 불일치 및 업무 목록 쿼리 크래시 수정
페이지네이션 도입 후 백엔드 목록 API 가 { items, total, ... } 를 반환하는데
프론트 멤버·업무 소비처가 배열로 기대해 list.map 이 깨지고, 멤버 탭과 업무
목록이 비어 보이던 회귀를 수정.

- backend(task): 업무 목록 쿼리에서 to-many 조인 컬럼(checklist.sort_order)
  으로 정렬해 페이지네이션 시 TypeORM 이 터지던 문제 제거(task.seq 만 정렬).
  목록 응답은 체크리스트 [완료/전체] 수만 쓰므로 항목 순서가 불필요.
- frontend(member/task): list 컴포저블이 Paginated<T> 를 반환하도록 맞추고
  스토어에서 .items 로 언래핑(저장소·내업무와 동일 계약).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 00:23:01 +09:00
ttipo a056d7f55a feat: 업무 상세 부속·활동 피드·내 업무 집계 + 페이지네이션 (5~8단계)
- 5단계(업무 상세 부속): 체크리스트(상세 읽기전용/수정폼 추가·삭제)·댓글/답글·파일 첨부(서버 로컬 업로드 폴더)·승인 워크플로우(요청/승인/수정요청 노트)
- 6단계(활동 피드): 저장소/멤버/업무 행위를 이벤트로 자동 적재, 저장소 활동 피드·업무 활동 탭 실연동(프론트가 type+payload로 문구 조립)
- 7단계(내 업무): 담당/지시 저장소 횡단 집계, MyTasksPage 실연동, TaskAssigneePage(/view) 제거
- 8단계(진행): 목록 페이지네이션 통일 — 백엔드 전체(공통 유틸 + 5개 목록, 저장소 업무는 세그먼트/검색/카운트) + 프론트 더보기(저장소 목록·내 업무 완료, 멤버·저장소 업무 대기)
- UI 보강: 업무 목록 댓글/첨부 분리표기, 첨부 배지 색상·라벨 통일, 완료 업무 D-Day 배지, 활동 이벤트 점검·보강(업무 수정/삭제·답글·첨부 삭제)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:13:17 +09:00
ttipo 875eddf659 feat: 업무(Task) 모듈 4단계 — CRUD·상태머신·진행률 집계·역할 기반 상세 UI
백엔드
- Task/ChecklistItem 엔티티(저장소 내 순번 seq, jsonb content, assignees ManyToMany, checklist)
- GET/POST/PATCH/DELETE /repos/:repoId/tasks[/:taskId] + POST .../status
- 상태 머신(todo→prog→review→done, review→changes, changes→{review,prog}) + 전이별 역할 검증
- 담당자=저장소 멤버만 지정, 승인 완료(→done) 시 체크리스트 일괄 완료(영속)
- 저장소 doneCount/totalCount·멤버 taskCount 실집계(RepoModule→TaskModule)
- Task.repo FK 컬럼명 snake_case 고정(@JoinColumn), task.service 단위 테스트

프론트
- types/task·useTask·task.store, format.ts 라벨 파생(상태/마감/dday)
- RepoDetailPage 업무 목록, TaskCreatePage 생성/수정 겸용(편집 라우트)
- TaskDetailPage 역할 기반 액션 분기(지시자 승인/수정요청, 담당자 시작/승인요청)
- 액션 카드·상태 뱃지 디자인 시안 정렬, 작성폼/목록 UI 정리

문서: api-contract·integration-progress 4단계 반영

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 18:12:11 +09:00
ttipo c01f8e535c feat: 멤버 관리 연동 + 사용자 검색 API (3단계)
- 멤버 목록/초대/역할변경/제거 프론트 연동(RepoMembersPage), 초대 자동완성
- GET /users 사용자 검색 API + UserController
- RepoMembersPage 역할 변경 드롭다운 잘림(overflow) 수정
- InviteMember/UpdateMember DTO, RepoMember 엔티티 정비

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 18:11:46 +09:00
ttipo e2fe089321 feat: Gitea 프론트 연동(클론바·원격없음 배지)·import-admin 인프라 마무리
- GiteaRepoBar 컴포넌트(클론 주소 복사 + Gitea 열기)를 RepoSettingsPage 에 적용
- repo.store 뷰에 cloneUrl/htmlUrl/giteaMissing 매핑
- repo-sync: import 저장소 owner-admin 자동 지정(REPO_IMPORT_ADMIN_EMAIL)
- env example·docker-compose.dev 에 Gitea/import-admin 키 정비

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 18:11:16 +09:00
ttipo b626bbdf6c chore: 브랜드 로고 에셋 추가 (logo png/svg)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 18:10:28 +09:00
ttipo ae385355b8 feat: Gitea 조직 저장소 역방향 동기화 (기동 시·매시간 import)
- GiteaService.listOrgRepos(): 조직 저장소 페이지네이션 조회
- RepoSyncService: OnApplicationBootstrap(비차단) + @Cron(매시간) 동기화
  - 추가형 import(멤버 0명), 연동정보 backfill, Gitea 누락 시 giteaMissing 표기
- Repo.giteaMissing 컬럼 + RepoResponse/프론트 ApiRepo 노출
- GET /repos 를 '조직 저장소 전체'(findAll)로, 단건은 인증 사용자 열람 허용
- docs(api-contract·integration-progress) 2.6단계 반영

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 13:16:20 +09:00
ttipo 2b38e21188 chore: env example 파일 정비 (루트·프론트 추가, 단독 실행 예시 제거)
- 루트 .env.{development,production}.example 신규 (비밀값 placeholder 마스킹)
- frontend .env.{development,production}.example 신규 (docker build arg 주입 설명)
- backend example 의 단독 실행(non-Docker) 예시 블록 제거

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 13:16:03 +09:00
ttipo 7f432a0013 feat: 저장소 생성 시 설명 필수화 + 템플릿 복제 생성
- 프로젝트 설명을 생성 필수 항목으로 변경(CreateRepoDto.description required + 프론트 검증)
- 템플릿 복제: useTemplate=true 면 Gitea generate API 로 GITEA_TEMPLATE_OWNER/REPO
  (기본 TtiPo/project-base) 저장소를 복제 생성(브랜치는 템플릿을 따름)
- GET /repos/owner → /repos/meta 로 확장({ owner, template }) — 생성폼 메타 일괄 제공
- 프론트 생성폼: 가짜 템플릿 목록 제거 → 실제 템플릿 옵션, 설명 필수 UI
- env.example/ api-contract/ 진행현황 문서 갱신

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 00:20:21 +09:00
ttipo 6652e79768 feat: 저장소 소유자(조직)를 백엔드 설정값으로 표시
생성 폼/목록의 하드코딩된 'marketing-team' 을 실제 설정값으로 교체한다.
- 백엔드: GET /repos/owner ({ owner }) — GITEA_ORG(미연동 시 기본 상수) 반환
- 프론트: useRepo.owner() + repo.store owner/fetchOwner(캐시)
- RepoCreatePage 소유자 고정 표시, RepoListPage 배너를 실제 조직명으로

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 23:53:39 +09:00
ttipo e1bc5a1dfc first commit 2026-06-16 17:12:08 +09:00