- 옛 registry/numbering-rule, registry/v2-numbering-rule, V2NumberingRuleConfigPanel,
NumberingRuleTemplate 폐기 — InvFieldConfigPanel + InputComponent 로 통합
- input 에 numbering-picker / select-pickers 추가, autonum 타입 흡수
- 채번 관리 전용 admin 페이지(systemMng/numberingRuleList) + CreateDialog +
SequenceManagementPanel 신설
- backend NumberingRule controller/service/mapper 갱신 (시퀀스 관리 엔드포인트)
- input canonical 진행 노트 + 채번 관리 mockup 추가
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
충돌 해결 5개 파일:
- .gitignore: .envrc/.direnv (hjjeong direnv 셋업) + .omc/ (gbpark) 양쪽 보존
- docs/MULTI_TENANCY_ARCHITECTURE.md: *.localhost dev 분기 + *.invyone.com/solution.invyone.com 통합
- frontend/lib/api/client.ts: 1-b *.localhost:8081 dev + 1-c DEV_TENANT_HOST(nip.io):8083 + invyone.com 신 도메인
- frontend/lib/tenant/subdomain.ts: IPv4 차단 + *.invyone.com + DEV_TENANT_HOST + *.localhost 모두 처리
- frontend/app/(auth)/login/page.tsx: B안 채택 — buttons 항상 렌더, className 만 mounted 가드 (next-themes 표준 패턴)
검증:
- backend: ./gradlew compileJava 성공 (Java 21)
- frontend: 머지된 4개 파일 관련 타입 에러 0개
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 음성 인식 (scada-demo/js/voice.js) — 한국어 발화 → 키워드 매핑 → INVYONE_UI.select()
· 사이드바 마이크 버튼 + transcript 라벨, 매칭 시 청록 펄스
· Chrome/Edge HTTPS 환경 (운영 siflex.invyone.com OK)
- 경고시스템/다중경고 버튼을 음성 인식과 동일 톤
· 🚨 emoji → SVG 삼각형 아이콘, voice-btn 패턴 (다크 솔리드 + 컬러 액센트)
· 정적 (반짝 펄스 애니메이션 제거)
- client.ts stash pop conflict 정리 (DEV_TENANT_HOST + 도메인 정리 통합)
- ui.js 다중 경고 시연 wiring + scada 작업 노트 2건
- 기타 syncthing 보류분 batch (대시보드/레이아웃/로그인 layout 정리)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 1(사용자관리) 패턴을 권한관리에 동일 적용. 권한 그룹 CRUD,
멤버 토글, 메뉴 권한 토글 모두 회사 컨텍스트 임시 전환 후 처리.
신규 백엔드
- crosstenant/CrossTenantRoleController.java
/api/admin/cross-tenant/roles/** — 8개 endpoint
· POST — 권한 그룹 생성 (body.company_code 필수)
· PUT /{id} — 권한 그룹 수정 (body.company_code 필수)
· DELETE /{id}?company_code= — 삭제
· GET /{id}/workspace?company_code= — 그룹 + 멤버 + 메뉴 통합 로드
· GET /menus/all?company_code= — 회사 메뉴 트리 (권한 설정용)
· POST /{id}/members/{userId}?company_code= — 멤버 1명 추가
· DELETE /{id}/members/{userId}?company_code= — 멤버 1명 제거
· PATCH /{id}/menu-permissions/{menuObjid} — 토글
CrossTenantExecutor 재사용. 기존 RoleController 무수정 (회귀 0).
중요: @RequestAttribute("user_id") 가 토큰 없을 때 missing 에러로 500
떨어지는 문제 — required=false 로 가드까지 안전하게 도달하도록.
프론트
- lib/api/role.ts — 7개 메서드(create/update/delete/getWorkspace/
getAllMenus/addSingleMember/removeSingleMember/toggleMenuPermission)에
isCrossTenantMode() 분기 + companyCode 인자 추가
- RoleFormModal — update 시 editingRole.company_code 같이 전달
- RoleDeleteModal — delete 시 role.company_code 같이 전달
- rolesList/page.tsx — loadWorkspace / addSingleMember / removeSingleMember /
toggleMenuPermission 호출 시 selectedRole.company_code 전달
검증 (curl, SUPER_ADMIN 토큰):
- 토큰 없음 → 403 super_admin_required
- POST 권한 그룹 (TEST02) → 201, /roles fan-out 에 by={TEST01:1, TEST02:1}
- DELETE → 200, fan-out by={TEST01:1} 로 복귀
미구현 (Phase 2 후속, 별도 작업):
- 일괄 멤버 추가/제거/diff (PUT/POST /members)
- 메뉴 권한 일괄 설정 (PUT /menu-permissions)
- 사용자별 권한 그룹 조회
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
직전 Phase 1 의 후속 폴리시.
신규 백엔드
- crosstenant/CrossTenantDeptController.java
GET /api/admin/cross-tenant/departments?company_code=TEST02
단일 모드 GET /admin/departments 와 응답 형태 동일. company_code query param
으로 명시된 회사 DB 컨텍스트로 임시 전환해서 부서 트리 반환.
버그 수정: 메타 DB DEPT_INFO 시드 (qnc/COMPANY_7 등 다른 회사 부서) 가
TEST02 선택 시에도 dropdown 에 섞여 보이던 문제 해결.
프론트
- lib/api/user.ts — getDepartmentList(companyCode) 가 isCrossTenantMode() 면
/admin/cross-tenant/departments?company_code= 호출.
cross-tenant 모드 + companyCode 미지정 → 빈 배열 반환 (회사 안 골랐는데
메타 부서 보여주는 것 방지).
UserFormModal
- 회사 dropdown 을 폼 가장 위로 이동 — 사용자 ID 중복확인·부서 선택이
모두 회사에 의존하므로 자연스러운 입력 순서
- SUPER_ADMIN 인데 회사 미선택 상태에선 사용자 ID input + 중복확인 버튼
disable + placeholder "회사 먼저 선택"
- checkUserIdDuplicate 가드: 회사 미선택이면 "회사를 먼저 선택해주세요"
(백엔드의 400 "company_code 가 비어있음" 보다 친절)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
지금까지 cross-tenant 는 READ 전용. admin 도메인에서 사용자 등록하면
JWT.company_code='*' 가 그대로 박혀 메타 DB 에 INSERT 되던 버그 해결.
이제 SUPER_ADMIN 이 폼의 "회사" 드롭다운에서 TEST01/TEST02 등 선택하면
그 회사 DB 에 정확히 INSERT.
신규 백엔드
- crosstenant/CrossTenantExecutor.java — 회사 컨텍스트 임시 전환 헬퍼
(company_code → db_name → ensureTenantPool → set → run → restore)
- crosstenant/CrossTenantUserController.java — /api/admin/cross-tenant/users
9개 endpoint (POST/PUT/DELETE/PATCH/with-dept/check-duplicate/단건/이력)
- mapper/provisioning.xml — resolveDbNameByCompanyCode (active 회사만)
기존 단일 회사 모드 (POST /admin/users 등) 무수정 — 회사 도메인
컨텍스트에서 회귀 0.
프론트
- lib/api/user.ts — createUser/updateUser/updateUserStatus/checkDuplicateUserId/
saveUserWithDept 가 isCrossTenantMode() 면 새 endpoint + body.company_code 로 분기
- UserFormModal — checkDuplicateId 호출 시 formData.company_code 같이 전달
- useUserManagement — status toggle 시 row 의 company_code 같이 전달
검증 (curl, SUPER_ADMIN 토큰):
- 토큰 없음 → 403 super_admin_required
- company_code 없음 → 400 "company_code 가 비어있음"
- 잘못된 company_code → 400 "등록되지 않았거나 비활성 회사"
- check-duplicate: TEST01.test02_admin → not_dup, TEST02.test02_admin → dup ✓
- POST 사용자 → TEST02 USER_INFO +1, TEST01·메타 격리 ✓
- /users fan-out: by={'*':8, 'TEST01':1, 'TEST02':2}, hjtest_ct_001 in TEST02만 ✓
- DELETE → status=inactive (soft) ✓
미구현 (Phase 1 후속):
- 부서 dropdown (cross-tenant department endpoint 별도 필요)
- 비밀번호 초기화 모달의 cross-tenant 분기 (UserPasswordResetModal)
- Phase 2 권한관리 (별도 커밋)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SUPER_ADMIN cross-tenant 모드에서 회사당 cap 200 에 걸리거나 한 회사
조회 실패 시 화면 상단에 안내 배너 노출. 아무 메타 없으면 자리 안 잡음.
신규
- components/common/CrossTenantBanner.tsx — amber(truncated) + red(failed)
v5 토큰 (surface-solid + glow-sm) 기반 솔리드 배너. blur 안 씀
API 클라이언트 4개에 cross_tenant_meta 노출
- lib/api/user.ts — userAPI.getList 응답에 cross_tenant_meta 추가
- lib/api/role.ts — roleAPI.getList 동일
- lib/api/batch.ts — BatchAPI.getBatchConfigs 동일
- lib/api/multilang.ts — getLangKeys 동일 (i18nList 페이지는 아직 직접
호출 패턴이라 자동 적용 X — 후속에서 페이지를 getLangKeys 로 통일하면 동작)
페이지 마운트 (3개)
- userMng/userMngList — useUserManagement hook 에 crossTenantMeta state 추가
- userMng/rolesList — loadRoleGroups 에서 메타 set
- automaticMng/batchmngList — loadBatchConfigs 에서 메타 set
- systemMng/i18nList — 스킵 (cross-tenant aggregation 미적용 상태, 별도 작업)
설계서 §11 검증 (직전 §11.2 부분 실패 시뮬) 결과: failed 배너가
header X-CrossTenant-Failed 와 동일 정보로 화면에 노출됨.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SubdomainResolverFilter.extractSubdomain() 가 2파트 {sub}.localhost 호스트도
첫 파트로 파싱 (RFC 6761). 운영 3파트 경로 무변경. 단위 테스트 8건 추가.
frontend/lib/api/client.ts 에 *.localhost (bare 제외) 직접 호출 분기 1-b 추가.
8081 로 직결해 Host 헤더 보존. subdomain.ts 도 동일 규칙 적용.
application.yml CORS 디폴트에 http://*.localhost:[*] 패턴 추가.
docs/MULTI_TENANCY_ARCHITECTURE.md §4.2 (실행 모드 A/B) + §6 (1-b 분기) 갱신.
.gitignore 에 .envrc/.direnv 추가, .java-version=21 명시 (jenv 호환).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SUPER_ADMIN 토큰(company_code=*)이면 등록 회사들 DB 를 순회해 결과를
집계해 돌려주는 CrossTenantAggregator/Controller 추가. 사용자/권한그룹/
배치/다국어 키 4개 도메인의 list API 가 cross-tenant 모드 지원.
UserTable + ResponsiveDataView 에 compact/scrollContainer prop 추가.
페이지 헤더/툴바/페이지네이션은 고정, 테이블만 자체 스크롤.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
운영 도메인이 실제로는 v1.invyone.com / solution.invyone.com / api.invyone.com 인데
코드/문서 곳곳에 v1.invion.com / api.invion.com 등 미존재 도메인이 박혀 있어 정리.
변경 파일 (21):
- frontend lib/api/client.ts, lib/utils/apiUrl.ts: hostname 체크 endsWith(\".invyone.com\") 일반화
- frontend lib/api/dashboard.ts, file.ts, flow.ts, FileViewerModal*2.tsx: 도메인 치환
- frontend invion-layout-v5.html: 시안 내 placeholder 도메인 정리
- backend-spring SecurityConfig.java: CORS 주석 예시 정리
- docker/deploy/docker-compose.yml, k8s/traefik-dynamic.yaml: traefik Host 라벨 정리
- scripts/prod/deploy.sh: 안내 메시지 정리
- .cursor/rules/api-client-usage.mdc, project-conventions.mdc: AI 가이드 정리
- docs/* 4개: 아키텍처/플로우 문서 도메인 정리
- notes/gbpark/* 3개: 과거 메모 정리
신규:
- docs/DOMAIN_MAPPING.md: 운영/개발/폐기 도메인 영구 기록.
AI 에이전트와 신규 개발자가 헷갈리지 않도록 단일 진실 출처.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Introduced new routes and controllers for managing shipping orders, including listing, saving, and previewing next order numbers.
- Added design management routes and controller for handling design requests, projects, tasks, and work logs.
- Implemented company code filtering for multi-tenancy support in both shipping order and design request functionalities.
- Enhanced the shipping plan routes to include listing and updating plans, improving overall shipping management capabilities.
These changes aim to provide comprehensive management features for shipping orders and design processes, facilitating better organization and tracking within the application.
- Added planDate support in batch save operations for shipping plans, allowing for more accurate scheduling.
- Updated the ShippingPlanEditorComponent to handle planDate and splitKey for better management of shipping plans.
- Enhanced validation logic to ensure that the total planned quantity does not exceed available stock during the editing process.
- Introduced functionality to add and remove split rows dynamically, improving user experience in managing shipping plans.
These changes aim to provide a more robust and flexible shipping plan management experience, facilitating better tracking and scheduling of shipping operations.
- Added shipping plan routes and controller to handle aggregate and batch save operations.
- Introduced a new shipping plan editor component for bulk registration of shipping plans based on selected orders.
- Enhanced API client functions for fetching aggregated shipping plan data and saving plans in bulk.
- Updated the registry to include the new shipping plan editor component, improving the overall shipping management workflow.
These changes aim to streamline the shipping plan process, allowing for efficient management and registration of shipping plans in the application.