Skip to content

feat: add local-first Supabase account sync and template community - #84

Open
Turtle-Hwan wants to merge 14 commits into
mainfrom
feat/cloudflare-account-sync
Open

feat: add local-first Supabase account sync and template community#84
Turtle-Hwan wants to merge 14 commits into
mainfrom
feat/cloudflare-account-sync

Conversation

@Turtle-Hwan

@Turtle-Hwan Turtle-Hwan commented Aug 12, 2026

Copy link
Copy Markdown
Owner

목적

LinKU의 템플릿을 IndexedDB에 먼저 저장하고, 선택적인 Google 로그인으로 여러 기기 동기화와 템플릿 커뮤니티를 제공합니다. Supabase 장애나 미설정 상태에서도 로컬 생성, 편집, 적용, 백업, 복원은 계속 동작합니다.

포함된 변경

  • IndexedDB v5에 outbox, sync metadata, account binding을 additive하게 추가
  • 템플릿과 사용자 아이콘을 로컬 transaction으로 먼저 저장한 뒤 Supabase에 동기화
  • Chrome Identity와 PKCE 기반 Google OAuth, Chrome trusted context session 저장
  • Postgres revision 기반 낙관적 동시성 제어와 충돌 복사본 보존
  • 수동 게시 snapshot, 게시물 업데이트 필요 상태, 검색, 정렬, 좋아요, 복제
  • private/public Storage 경로와 계정별 RLS, Google provider 재검증
  • Supabase 미설정/장애 시 기본 템플릿 fallback과 로컬-only UX
  • 계정별 template 100개, icon 100개, publication 25개, public asset 900개 제한
  • MV3 runtime과 Supabase pgTAP/RLS의 로컬 검증, 가벼운 hosted PR gate

기존 backend 기능 대응

기존 영역 이번 구현
자체 OAuth/JWT, KU 인증 Supabase Auth의 Google 계정 로그인으로 교체
template CRUD, owned/cloned 조회 IndexedDB local-first CRUD와 계정 동기화로 교체
게시 목록/상세/게시/수정/삭제 공개 snapshot 조회와 publish/update/unpublish로 교체
좋아요, 템플릿 복제 authenticated 좋아요와 local-first 복제로 교체
custom icon upload/list IndexedDB asset과 private/public Supabase Storage 동기화로 교체

기존 frontend가 호출하지 않던 독립 icon rename/delete endpoint는 별도 API로 옮기지 않았습니다. 아이콘은 content-addressed asset으로 관리되고, 사용자가 템플릿을 수정·삭제하거나 전체 클라우드 데이터를 삭제하는 현재 흐름에서 정리됩니다.

제거한 범위

  • 기존 Spring backend client와 자체 JWT/재인증
  • KU 이메일 인증과 학과 구독
  • backend 공지 crawler
  • URL 기반 단일 템플릿 직접 공유
  • Cloudflare Worker, Edge Function, Realtime, cron

학교 공개 공지는 기존 frontend 직접 조회와 캐시만 유지합니다. 이전 backend 데이터는 자동 이관하지 않습니다.

보안과 비용 경계

  • 확장에는 Supabase URL과 publishable key만 포함
  • Google client secret과 service-role key는 source, fixture, VITE 변수에 포함하지 않음
  • account RPC와 Storage policy가 signed JWT의 Google provider를 재검사
  • OAuth code, PKCE verifier, session token, Google profile, template JSON, icon bytes를 Sentry에 기록하지 않음
  • Google nonce 검증 유지
  • 익명 사용자는 gallery를 읽고 로컬 복제할 수 있지만 clone counter를 포함한 원격 쓰기는 로그인 세션만 허용
  • 계정 쓰기 직렬화와 삭제 이력 100개 제한으로 무료 DB/Storage 사용량 경계 유지
  • release workflow가 운영 anonymous gallery RPC를 확인한 뒤에만 draft upload 진행

검증

  • pnpm install --frozen-lockfile
  • pnpm run lint
  • pnpm run build:local
  • pnpm exec playwright test tests/extension: 3 passed
  • application contract tests: 149 passed
  • Sentry popup/background/content bundle verification passed
  • Supabase db lint: no schema errors
  • generated Supabase TypeScript types match the migration
  • Supabase pgTAP: 37 passed
  • pnpm run build:gh-pages
  • actionlint
  • pnpm audit --prod --audit-level=high: no known vulnerabilities
  • gitleaks: source, migration, docs, workflows 모두 통과

Hosted PR CI는 lint, extension build, local-first template 55개, monitoring 23개와 Sentry bundle 계약만 검사합니다. Chromium과 Docker를 설치하는 MV3/Supabase 검사, 전체 기능 회귀와 중복 Pages 빌드는 로컬 검증 결과로 분리했습니다.

운영 연결 상태

  • Supabase Free 프로젝트를 Seoul region에 생성하고 migration 적용 완료
  • Google provider에 LinKU 전용 Web OAuth client를 연결하고 nonce 검증 유지
  • Supabase redirect allowlist에 로컬 unpacked ID와 Chrome Web Store ID의 chromiumapp.org/supabase URL 등록
  • GitHub Variables에 VITE_SUPABASE_URL, VITE_SUPABASE_PUBLISHABLE_KEY 등록
  • 운영 Auth health와 anonymous gallery RPC 응답 200 확인
  • 실제 Google 계정 선택 후 로컬 확장 callback에 code가 도착하고 PKCE token exchange가 200으로 성공하는지 확인
  • 발급 세션의 Google provider와 profile 자동 생성/RLS 조회를 확인한 뒤 테스트 세션 로그아웃

남은 수동 배포 게이트는 빌드된 unpacked extension의 chrome.identity.launchWebAuthFlow 전체 UI 흐름, 게시/복제/좋아요, 두 기기 충돌 시나리오입니다. 운영 release는 이 PR을 merge하기 전까지 배포되지 않습니다.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 12, 2026

Copy link
Copy Markdown

Deploying linku with  Cloudflare Pages  Cloudflare Pages

Latest commit: 9c9cbfe
Status:🚫  Build failed.

View logs

Base automatically changed from feat/indexeddb-local-first to main August 23, 2026 12:53
@Turtle-Hwan
Turtle-Hwan force-pushed the feat/cloudflare-account-sync branch from b49f2cc to 9b86056 Compare August 23, 2026 13:55
@Turtle-Hwan
Turtle-Hwan marked this pull request as ready for review August 23, 2026 13:56
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@Turtle-Hwan
Turtle-Hwan force-pushed the feat/cloudflare-account-sync branch 2 times, most recently from 9c9cbfe to b7560dc Compare August 27, 2026 04:02
@Turtle-Hwan
Turtle-Hwan force-pushed the feat/cloudflare-account-sync branch from a5d968c to f695f6a Compare August 30, 2026 17:02
@Turtle-Hwan Turtle-Hwan changed the title feat: add Cloudflare account sync layer feat: add local-first Supabase account sync and template community Aug 30, 2026
@Turtle-Hwan
Turtle-Hwan force-pushed the feat/cloudflare-account-sync branch from 31965c5 to 752a2ac Compare August 31, 2026 05:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant