Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
64 changes: 64 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
runs-on: ubuntu-latest
outputs:
web: ${{ steps.filter.outputs.web }}
university-web: ${{ steps.filter.outputs.university-web }}
admin: ${{ steps.filter.outputs.admin }}
root: ${{ steps.filter.outputs.root }}
steps:
Expand All @@ -26,12 +27,15 @@ jobs:
filters: |
web:
- 'apps/web/**'
university-web:
- 'apps/university-web/**'
admin:
- 'apps/admin/**'
root:
- 'package.json'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- 'scripts/**'
- 'turbo.json'
- '.github/workflows/**'

Expand Down Expand Up @@ -62,6 +66,33 @@ jobs:
- name: Run checks (lint & typecheck)
run: pnpm --filter @solid-connect/web run ci:check

# University Web 앱 품질 체크
university-web-quality-check:
name: University Web - Quality Check
runs-on: ubuntu-latest
needs: detect-changes
if: needs.detect-changes.outputs.university-web == 'true' || needs.detect-changes.outputs.root == 'true'
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: 9

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22.x"
cache: "pnpm"
Comment on lines +76 to +88
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 새로 추가된 university-web 잡의 액션 참조와 checkout 옵션을 점검합니다.
sed -n '69,95p;156,187p' .github/workflows/ci.yml

echo
echo '[uses references]'
rg -n 'uses:\s*(actions/checkout|actions/setup-node|pnpm/action-setup)@' .github/workflows/ci.yml

echo
echo '[checkout blocks]'
rg -n -A3 -B1 'name:\s*Checkout repository' .github/workflows/ci.yml

Repository: solid-connection/solid-connect-web

Length of output: 3441


CI 보안 강화: 액션 참조를 SHA로 고정하고 checkout에 persist-credentials: false 추가하기

  1. university-web-quality-check / university-web-builduses:actions/checkout@v4, pnpm/action-setup@v3, actions/setup-node@v4처럼 태그 기반이라 공급망 리스크가 커서 커밋 SHA로 고정해 주세요.
  2. 두 잡 모두 Checkout repositorypersist-credentials: false가 없어 읽기 전용 체크아웃에서도 불필요한 자격 증명이 유지될 수 있으니 추가해 주세요.
🔧 예시 수정안
       - name: Checkout repository
-        uses: actions/checkout@v4
+        uses: actions/checkout@<PINNED_SHA>
+        with:
+          persist-credentials: false

       - name: Install pnpm
-        uses: pnpm/action-setup@v3
+        uses: pnpm/action-setup@<PINNED_SHA>

       - name: Setup Node.js
-        uses: actions/setup-node@v4
+        uses: actions/setup-node@<PINNED_SHA>
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 76-77: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 77-77: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 80-80: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 85-85: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 76 - 88, Replace the tag-based action
references with pinned commit SHAs for actions/checkout, pnpm/action-setup, and
actions/setup-node in both the university-web-quality-check and
university-web-build jobs to reduce supply-chain risk (e.g., change uses:
actions/checkout@v4 → uses: actions/checkout@<commit-sha>), and add
persist-credentials: false to the Checkout repository step (the actions/checkout
invocation) in both jobs to avoid leaking credentials on read-only checkouts;
update the three uses: lines and the checkout step accordingly wherever they
appear.


- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Run checks (lint & typecheck)
run: pnpm --filter @solid-connect/university-web run ci:check

# Admin 앱 품질 체크
admin-quality-check:
name: Admin - Quality Check
Expand Down Expand Up @@ -120,6 +151,39 @@ jobs:
run: pnpm --filter @solid-connect/web run build
env:
NODE_ENV: production
UNIVERSITY_WEB_DOMAIN: https://university-web.ci.local

# University Web 앱 빌드
university-web-build:
name: University Web - Build
runs-on: ubuntu-latest
needs: [detect-changes, university-web-quality-check]
if: |
always() &&
(needs.detect-changes.outputs.university-web == 'true' || needs.detect-changes.outputs.root == 'true') &&
needs.university-web-quality-check.result == 'success'
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: 9

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22.x"
cache: "pnpm"

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build university web application
run: pnpm --filter @solid-connect/university-web run build
env:
NODE_ENV: production

# Admin 앱 빌드
admin-build:
Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ on:
workflow_dispatch:
inputs:
target:
description: "Promote target"
description: "Promote target (both keeps the legacy web+admin selection)"
required: true
default: "both"
type: choice
options:
- all
- both
- web
- admin
- university
force_redeploy:
description: "When up to date, skip divergence and print manual redeploy guidance"
required: true
Expand Down Expand Up @@ -71,6 +73,12 @@ jobs:
admin)
RELEASE_BRANCHES="release-admin"
;;
university)
RELEASE_BRANCHES="release-university"
;;
all)
RELEASE_BRANCHES="release-web release-admin release-university"
;;
both)
RELEASE_BRANCHES="release-web release-admin"
;;
Expand Down
13 changes: 11 additions & 2 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,23 @@ echo "🔍 Running CI parity checks before commit..."

CHANGED_FILES=$(git diff --cached --name-only)
RUN_WEB=0
RUN_UNIVERSITY_WEB=0
RUN_ADMIN=0

for FILE in $CHANGED_FILES; do
case "$FILE" in
apps/web/*)
RUN_WEB=1
;;
apps/university-web/*)
RUN_UNIVERSITY_WEB=1
;;
apps/admin/*)
RUN_ADMIN=1
;;
package.json|pnpm-lock.yaml|pnpm-workspace.yaml|turbo.json|.github/workflows/*)
package.json|pnpm-lock.yaml|pnpm-workspace.yaml|scripts/*|turbo.json|.github/workflows/*)
RUN_WEB=1
RUN_UNIVERSITY_WEB=1
RUN_ADMIN=1
;;
esac
Expand All @@ -23,11 +28,15 @@ if [ "$RUN_WEB" -eq 1 ]; then
pnpm --filter @solid-connect/web run ci:check
fi

if [ "$RUN_UNIVERSITY_WEB" -eq 1 ]; then
pnpm --filter @solid-connect/university-web run ci:check
fi

if [ "$RUN_ADMIN" -eq 1 ]; then
pnpm --filter @solid-connect/admin run ci:check
fi

if [ "$RUN_WEB" -eq 0 ] && [ "$RUN_ADMIN" -eq 0 ]; then
if [ "$RUN_WEB" -eq 0 ] && [ "$RUN_UNIVERSITY_WEB" -eq 0 ] && [ "$RUN_ADMIN" -eq 0 ]; then
echo "ℹ️ No CI-targeted changes detected; skipping parity checks."
fi

Expand Down
16 changes: 13 additions & 3 deletions .husky/pre-push
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,44 @@ else
fi

RUN_WEB=0
RUN_UNIVERSITY_WEB=0
RUN_ADMIN=0

for FILE in $CHANGED_FILES; do
case "$FILE" in
apps/web/*)
RUN_WEB=1
;;
apps/university-web/*)
RUN_UNIVERSITY_WEB=1
;;
apps/admin/*)
RUN_ADMIN=1
;;
package.json|pnpm-lock.yaml|pnpm-workspace.yaml|turbo.json|.github/workflows/*)
package.json|pnpm-lock.yaml|pnpm-workspace.yaml|scripts/*|turbo.json|.github/workflows/*)
RUN_WEB=1
RUN_UNIVERSITY_WEB=1
RUN_ADMIN=1
;;
esac
done

if [ "$RUN_WEB" -eq 1 ]; then
pnpm --filter @solid-connect/web run ci:check
NODE_ENV=production pnpm --filter @solid-connect/web run build
NODE_ENV=production UNIVERSITY_WEB_DOMAIN=https://university-web.ci.local pnpm --filter @solid-connect/web run build
fi

if [ "$RUN_UNIVERSITY_WEB" -eq 1 ]; then
pnpm --filter @solid-connect/university-web run ci:check
NODE_ENV=production pnpm --filter @solid-connect/university-web run build
fi

if [ "$RUN_ADMIN" -eq 1 ]; then
pnpm --filter @solid-connect/admin run ci:check
NODE_ENV=production pnpm --filter @solid-connect/admin run build
fi

if [ "$RUN_WEB" -eq 0 ] && [ "$RUN_ADMIN" -eq 0 ]; then
if [ "$RUN_WEB" -eq 0 ] && [ "$RUN_UNIVERSITY_WEB" -eq 0 ] && [ "$RUN_ADMIN" -eq 0 ]; then
echo "ℹ️ No CI-targeted changes detected; skipping parity builds."
fi

Expand Down
40 changes: 40 additions & 0 deletions apps/university-web/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Shared configuration across all environments
# Environment-specific values are in .env.development, .env.preview, .env.production

NEXT_PUBLIC_IMAGE_URL=https://cdn.default.solid-connection.com
NEXT_PUBLIC_UPLOADED_IMAGE_URL=https://cdn.upload.solid-connection.com

# google maps
NEXT_PUBLIC_GOOGLE_MAP_API_KEY=

# google analytics
NEXT_PUBLIC_GOOGLE_ANALYTICS_ID=G-V1KLYZC1DS

# apple
NEXT_PUBLIC_APPLE_CLIENT_ID=com.basakcrispy.solidconnection.auth
NEXT_PUBLIC_APPLE_SCOPE="email"

NEXT_PUBLIC_CONTACT_LINK=https://open.kakao.com/o/grTrKWdg

# AI Inspector (server-only)
# Set these values in .env.local or deployment environment variables.
# AI_INSPECTOR_FIREBASE_PROJECT_ID=
# AI_INSPECTOR_FIREBASE_CLIENT_EMAIL=
# AI_INSPECTOR_FIREBASE_PRIVATE_KEY=
# AI_INSPECTOR_FIRESTORE_COLLECTION=aiInspectorTasks

# BELOW IS EXAMPLE FOR .env.local

# firebase private
# FIREBASE_PROJECT_ID=
# FIREBASE_PRIVATE_KEY_ID=
# FIREBASE_PRIVATE_KEY=
# FIREBASE_CLIENT_EMAIL=
# FIREBASE_CLIENT_ID=
# FIREBASE_CLIENT_X509_CERT_URL=

# sentry
# SENTRY_PROJECT=
# SENTRY_ORG=
# SENTRY_DSN=
# SENTRY_ENVIRONMENT=
10 changes: 10 additions & 0 deletions apps/university-web/.env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
SENTRY_ENVIRONMENT=development

# web page
NEXT_PUBLIC_WEB_URL=http://localhost:3000

# api server
NEXT_PUBLIC_API_SERVER_URL=https://api.stage.solid-connection.com

# kakao
NEXT_PUBLIC_KAKAO_JS_KEY=
10 changes: 10 additions & 0 deletions apps/university-web/.env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
SENTRY_ENVIRONMENT=production

# web page
NEXT_PUBLIC_WEB_URL=https://www.solid-connection.com

# api server
NEXT_PUBLIC_API_SERVER_URL=https://api.solid-connection.com

# kakao
NEXT_PUBLIC_KAKAO_JS_KEY=
60 changes: 60 additions & 0 deletions apps/university-web/AUTHENTICATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Authentication & Authorization

## Overview

웹 인증은 **클라이언트 재발급/인터셉터 중심**으로 동작합니다.

- 서버 진입 시 middleware에서 보호 경로를 `/login`으로 선리다이렉트하지 않습니다.
- 인증 실패 시점은 페이지 렌더/데이터 요청 단계에서 결정됩니다.

## Current Flow

### 1. App Initialization

- `ReissueProvider`에서 앱 최초 진입 시 `/auth/reissue`를 시도합니다.
- 성공 시 access token이 스토어에 반영되고, 실패 시 비로그인 상태를 유지합니다.

### 2. Request Interceptor

- `axiosInstance` 요청 인터셉터가 access token 만료 여부를 검사합니다.
- 토큰이 없거나 만료된 경우 재발급을 시도하고, 실패하면 로그인 이동을 유도합니다.

### 3. Response Interceptor

- API 응답이 401이면 재발급 1회 후 원요청을 재시도합니다.
- 재시도 실패 시 로그인 페이지로 이동합니다.

### 4. Page-level Guards

- 인증이 필요한 UI(예: 멘토 페이지)는 클라이언트에서 재발급/토큰 상태를 확인합니다.
- 필요한 경우 페이지 내부 로직에서 `/login`으로 이동합니다.

## Middleware Responsibility

`apps/web/src/middleware.ts`는 현재 아래만 담당합니다.

- stage 환경 `robots.txt` 제어
- 스캐너/프로브 경로 차단 (`.php`, `/.git`, `/wp-admin` 등)
- 정적 리소스 경로 제외 matcher 유지

즉, middleware는 더 이상 인증 선검증(보호 경로 강제 로그인 리다이렉트)을 수행하지 않습니다.

## Tokens

### Refresh Token

- HTTP-only 쿠키로 관리
- 재발급 API 호출 시 서버가 검증

### Access Token

- Zustand store 기반으로 관리
- API 인증 헤더에 사용
- 만료 시 재발급을 통해 갱신

## Related Files

- `apps/web/src/lib/zustand/useAuthStore.ts`
- `apps/web/src/utils/axiosInstance.ts`
- `apps/web/src/components/layout/ReissueProvider/index.tsx`
- `apps/web/src/middleware.ts`
Loading
Loading