Serein
Rust로 만든 가볍고 성능 좋은 Discord 전용 네이티브 클라이언트
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Private, invite-only event photo sharing for Nigerian weddings, church programmes and parties. Hosts upload the photos; guests take one selfie and see only the photos they appear in.
The previous travel app lives on the archive/travel-app branch.
pgvector).match_my_face(), and not stored.purge_expired_face_data()).Next.js 16 (App Router) · Supabase (auth, Postgres + pgvector) · Cloudflare R2 for photos
(falls back to Supabase Storage) · @vladmandic/face-api (TensorFlow.js, MIT) in the browser · Tailwind CSS 4.
supabase/migrations/0001_ancular_core.sql.
If you won't use R2, also run 0002_storage_bucket.sql.pg_cron, then run:
select cron.schedule('ancular-purge-faces', '15 3 * * *', 'select public.purge_expired_face_data()');
https://YOUR-DOMAIN/auth/callback (and http://localhost:3000/auth/callback) to redirect URLs.
Confirm email must be ON (Authentication → Providers → Email → “Confirm email”).
The app blocks hosts and guests until email_confirmed_at is set; without this dashboard
setting, accounts can skip the inbox step.[
{
"AllowedOrigins": ["https://YOUR-DOMAIN", "http://localhost:3000"],
"AllowedMethods": ["GET", "PUT"],
"AllowedHeaders": ["Content-Type"],
"MaxAgeSeconds": 3600
}
]
.env.example to .env.local and fill it in. On Vercel, add the same variables.npm install
npm run dev
app/
page.tsx landing page
privacy/ plain-language privacy page
(auth)/login, signup sign in / create account (supports ?next= for invites)
(app)/dashboard hosted and invited events
(app)/events/new create an event
(app)/events/[id] Photos · Guests · Share · Settings
e/[code] the guest invite: join → consent → selfie → your photos
api/events/[id]/photos create a photo + signed upload URLs
api/photos/[id]/[size] signed view/download, access checked by RLS
components/brand logo + adire pattern
components/events uploader, grid, guest list, share panel, settings
components/guest consent, selfie camera, results
lib/face.ts face finding in the browser
lib/storage.ts R2 / Supabase Storage
supabase/migrations schema, RLS, matching function
public/models, public/tfjs face models and the WebAssembly engine (for phones without WebGL)
match_my_face() treats distance ≤ 0.45 as "sure" and ≤ 0.55 as "maybe" (guest confirms).
Tune these once you have real event photos; lower numbers are stricter.
Email confirmation is the MVP second factor. To add authenticator-app MFA later:
supabase.auth.mfa.enroll({ factorType: "totp" }),
show the QR, then supabase.auth.mfa.challenge + verify on sign-in when aal is still aal1.aal2 in proxy.ts for host routes (/dashboard, /events) while leaving
guest invite browse lighter if needed.Already strong: selfie stays on device; guests only see matched photos via RLS; faces table host-only;
Stripe webhook signature + metadata.app; billing writes service-role only; share/view URLs signed after RLS;
invite pages noindex; local preview gated to development.
Quick wins: security headers/CSP; rate-limit join/match/upload/invite lookup; host-only Event pass checkout;
lock legacy match_my_face thresholds server-side; server-side age gate (not just checkbox).
Medium: shorter share-link TTL or one-time tokens; upload MIME/size verify after PUT; invite code entropy +
rotate; orphan uploading photo cleanup; structured logs without PII/embeddings.
Later: bot protection on signup; dependency scanning in CI; admin audit trail; MFA (above).
components/guest/ConsentStep.tsx)
and the privacy page. Consent records store CONSENT_VERSION from lib/events.ts; bump it when wording changes.