Skip to content

feat: 워크스페이스 유형을 운영 주체 기준 여덟 값으로 확장 - #135

Merged
yessjun merged 3 commits into
mainfrom
feat/workspace-kinds
Sep 18, 2026
Merged

yessjun merged 3 commits into
mainfrom
feat/workspace-kinds

Conversation

@yessjun

@yessjun yessjun commented Sep 17, 2026

Copy link
Copy Markdown
Member

📝 작업내용

  • 워크스페이스 유형을 여덟 값으로 확장 (V125). 개인, 교과, 비교과, 연구실, 동아리, 대회, 스터디, 프로젝트
  • 축은 그 공간을 운영하는 주체이며 활동의 출처가 아님. 분류와 표시 전용이라 개인을 가리는 판정 외에는 권한도 한도도 기간도 승인 경로도 읽지 않음
  • TEAM 폐기. 해당 행은 PROJECT로, 그보다 먼저 기존 PROJECT 행은 COURSE로 이관 (V126)
  • 소유자의 유형 변경 경로 신설. PATCH /workspaces/{workspaceId}kind 수용, 개인 워크스페이스는 422
  • 감사 액션 workspace.kind_update 추가, 이전 값 동반 기록
  • 생성 가능 유형을 CreatableWorkspaceKind 별도 스키마로 발행. findings R187 해소
  • API 명세 v0.82.0, 엔드포인트 243개 그대로

⭐️ 검증

  • 테스트 1,555개 통과, 실패 0. 리베이스 후 clean 포함 재실행
  • 유형 일곱 값 왕복, MEMBER 403, 개인 422, kind: null 422, 감사 previousKind 기록, 무변경 시 무기록을 실제 서버로 확인
  • 발행 명세가 런타임과 일치. 스키마 이름 축에서 CreatableWorkspaceKind 존재 확인
  • 테스트 픽스처 TEAM 치환 95건을 스크립트 보고가 아닌 grep 전수로 검증. 잔존 셋은 폐기 값을 일부러 보내는 자리
  • 적대 검토 둘의 지적을 처분. 실제 결함 셋 수정, 기각 다섯 건은 근거 기록

💬 리뷰 포인트

  • V126 두 UPDATE의 순서 의존. 역순이면 스모크 산출물 백여 행이 교과로 이관됨
  • PROJECT 행 전체를 COURSE로 옮기는 판단. 어느 행이 실제 수업인지는 환경 지식이라 선택 조건을 넣지 않음
  • 생성 요청에 폐기 값을 보낼 때의 422가 errors 없이 응답하는 형태

The kind held three values and only PERSONAL meant anything: TEAM and
PROJECT never branched anywhere, so courses were recorded as PROJECT and
told apart by reading the workspace name. Six values join them (V125) on
one axis, who runs the space rather than what the activity is called.

Classification and display only. No permission, quota, period or approval
path reads the kind; the round that would make it decide those is the
workspace quota model, still in the backlog.

TEAM is retired and its rows move to PROJECT, which now means a group
building something that none of the other kinds describes (V126). The
label survives in the enum because PostgreSQL cannot drop one.

An owner may reclassify, audited as workspace.kind_update with the value
it replaced. PERSONAL is closed in both directions: automatic creation,
undeletability, the closed member list and the withdrawal cleanup all
decide by asking whether the kind is PERSONAL.

The creatable kinds publish as their own schema rather than a sibling enum
beside a $ref, which openapi-typescript drops - that is how the console's
generated type came to accept values the server refuses.
Direct inserts would still pass, since the label stays in the enum for the
rows that already carry it. Leaving fixtures on a kind nothing can create
is what makes the next reader think it still can.
The PATCH field was marked nullable, so the published spec offered a null
the service answers with 422 and the hand-written master never allowed.
Three sources, two answers. Null is not a value this field can carry:
leaving the kind alone is the field being absent, which the presence flag
already tracks, and no workspace has a state with no kind.

@Schema(nullable = false) does not reach it; the jspecify annotation on the
field is what springdoc reads, so that is what comes off. A test now sends
an explicit null and expects the 422.

The remap migration's comment described one database's rows. It now says
why the statement moves every row instead of counting the ones it found.
@yessjun
yessjun merged commit 2b6bfc7 into main Sep 18, 2026
1 check passed
@yessjun
yessjun deleted the feat/workspace-kinds branch September 18, 2026 05:33
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