Annotation
범용 anchor 주석 — kind/visibility/parent 검증 + 가시성 정� (도메인 무관)
상태
| 항목 | 값 |
|---|---|
| Layer | core |
| Tier | L1 |
| Status | released |
| Version | 1.0.0 |
| 가격 | Free (free) |
| **카� | |
| �고리** | Content |
개요
개요
Annotation 은 multi-saas-kit 의 Layer 1 Core Plugin � 니다. paragraph anchor 단위 주석 (메모/답글/팁/번역) 의 표준 검증 + 가시성 정� 을 도메인 무관 Pure 로 제공합니다.
분리선 (ADR-039)
ADR-039 사례 11 — 기존 enum case 의 academy.how 도메인 �
�
(LESSON_SHARED, TEACHER_ONLY, STUDENT, TEACHER) 을 도메인 무관 �
�
으로 일반화. scripture.how 적용 검증 시도가 폭로한 도메인성 정정.
변경:
Visibility::LESSON_SHARED→Visibility::CONTEXT_SHAREDVisibility::TEACHER_ONLY→Visibility::STAFF_ONLYAuthorRole::STUDENT→AuthorRole::MEMBERAuthorRole::TEACHER→AuthorRole::STAFF- VisibilityResolver
in_same_lesson→in_same_context(하위 호환 fallback 유지) - layer
composite→core
핵심 컴포넌트
Enums (5�
)
| Enum | Cases |
|---|---|
AnnotationKind | note, tip, reply, translation |
Visibility | private, context_shared, staff_only (NOTE 만) |
TipStyle | highlight, tip, warning, note (TIP 만) |
AuthorRole | member, staff, admin (staff = staff | admin) |
BodyFormat | markdown, html_trix, html_tiptap |
Kind 별 capability 메서드 — requiresParent(), requiresLocale(), supportsVisibility(), supportsTipStyle().
AnchorIdValidator (Pure)
- DocumentProcessor 가 부여하는 anchor 패턴 (
/^[a-z0-9\-]{1,32}$/) 검증 - XPath / CSS selector 인젝� � 차단
- 빈 / 32자 초과 거부
AnnotationPayloadValidator (Pure)
kind/visibility/parent/locale 조합 검증 + 정규화.
VisibilityResolver (Pure)
| 조건 | 결과 |
|---|---|
| 본인 글 | 항상 보임 |
| TIP / TRANSLATION | 같은 컨� |
| �스트면 모두 보임 | |
| NOTE — PRIVATE | 본인만 |
| NOTE — CONTEXT_SHARED | 같은 컨� |
| �스트 모두 | |
| NOTE — STAFF_ONLY | 같은 컨� |
| �스트 + staff | |
| REPLY | parent 의 visibility 따라감 (호출자가 parent 메타로 재호출) |
SaaS 별 매핑 예시
| SaaS | MEMBER | STAFF | 컨� �스트 | |------|--------|-------|----------| | academy.how | 학생 | 교사 | lesson | | scripture.how | 참여� 자 | 메인저자/추가저자 | chapter | | commerce | 고객 | 운영자 | product | | forum | 일반사용자 | 모더레이터 | thread |
사용 예시
use App\Plugins\Annotation\Enums\{AnnotationKind, AuthorRole, Visibility};
use App\Plugins\Annotation\Services\{AnnotationPayloadValidator, VisibilityResolver};
$validator = AnnotationPayloadValidator::fromConfig(config('annotation'));
$normalized = $validator->validate($request->all(), AuthorRole::from($user->annotationRole()));
$resolver = new VisibilityResolver;
$canView = $resolver->canView(
annotation: [
'kind' => AnnotationKind::from($a->kind),
'visibility' => $a->visibility ? Visibility::from($a->visibility) : null,
'author_user_id' => $a->user_id,
'author_role' => AuthorRole::from($a->author_role),
],
viewer: [
'user_id' => $request->user()?->id,
'role' => AuthorRole::from($request->user()->annotationRole()),
'in_same_context' => true,
],
);
출처
academy.how AnnotationController + AnnotationPolicy + AuthorRoleResolver 추출 → ADR-039 사례 11 일반화.
의존성
- DocumentProcessor — anchor 패턴 호환 (선택)
라이선스
MIT
의존성
데모
- Platform 관리자 패널에서 메타 확인 🔒 로그인 필요
- 사용 예시 (PHP)
🛒 Plugin Store에서 보기: store.codebase.how/plugins/annotation