Files
hanarang-dashboard/frontend/lib/sisters.ts
narang-ai 033c142c0e feat(sprint-004): admin features + API auth guard
Sprint 003 non-blocking 처리:
- API Key Guard (passport-http-bearer) + AuthModule
- Helmet 적용 (main.ts)
- SisterNamePipe - name 파라미터 Controller 검증
- lib/sisters.ts - formatLastSeen/sisterEmojis/sisterDisplayNames 공통 추출

Sprint 004 본문:
- TASK-012: POST /api/admin/sisters/:name/{restart,reset} (ApiKeyGuard 적용)
- TASK-013: GET/PUT /api/admin/harness/:name/:file (허용 파일 allowlist)
- TASK-015: GET /api/admin/logs/:name
- 관리자 전 API @UseGuards(ApiKeyGuard)
- TASK-014: /admin 자매 관리 (재시작/리셋 + ConfirmModal)
- TASK-014: /admin/harness 하네스 편집 (CodeEditor + 파일트리)
- TASK-015: /admin/logs 로그 뷰어 (LogTerminal + 검색/에러필터)
- /admin/repos 저장소 목록
- AdminLayout (API Key 로컬스토리지 저장)
- 테스트 22/22 pass, FE 11 routes build 성공
2026-04-04 12:11:06 +09:00

33 lines
920 B
TypeScript

export const SISTER_EMOJIS: Record<string, string> = {
harang: '🦊',
narang: '🦊',
darang: '🐱',
erang: '🐺',
};
export const SISTER_DISPLAY_NAMES: Record<string, string> = {
harang: '하랑이',
narang: '나랑이',
darang: '다랑이',
erang: '이랑이',
};
export const SISTER_ROLES: Record<string, string> = {
harang: 'Orchestrator',
narang: 'Generator',
darang: 'Evaluator',
erang: 'Infra Manager',
};
export function formatLastSeen(lastSeen: string | Date | null | undefined): string {
if (!lastSeen) return '기록 없음';
const d = typeof lastSeen === 'string' ? new Date(lastSeen) : lastSeen;
const diff = Date.now() - d.getTime();
const min = Math.floor(diff / 60000);
if (min < 1) return '방금 전';
if (min < 60) return `${min}분 전`;
const hr = Math.floor(min / 60);
if (hr < 24) return `${hr}시간 전`;
return `${Math.floor(hr / 24)}일 전`;
}