npm package: @jeonghochoi/rbac
Description: Optional, async, multi-tenant RBAC module for NestJS
Author: jeonghochoi
Latest version: 0.1.7

# RBAC Module (NestJS)

> **Optional, Async, Multi-Tenant RBAC for NestJS**  
> 앱에 강제하지 않는 플러그인 형태의 RBAC (Role-Based Access Control) 모듈

---

## ✨ Features

- ✅ **Optional RBAC**
    - Provider 미등록 시 자동 비활성화
- ✅ **Async Permission Check**
    - DB / Redis / External API 기반 권한 검사 지원
- ✅ **Multi-Tenant 지원**
    - tenantId 기반 role → permission 분리
- ✅ **Decorator 기반 API 선언**
- ✅ **NestJS Guard 표준 구조**
- ✅ **Strict TypeScript / ESLint 호환**
    - `isolatedModules`, `no-unsafe-*` 대응

---

## 📦 Installation

```bash
npm install @jeonghochoi/rbac
```

---

## 🧠 Core Concept

RBAC 모듈은 **권한 데이터를 소유하지 않습니다.**

| 역할        | 책임                              |
| ----------- | --------------------------------- |
| RBAC 패키지 | 권한 검사 흐름                    |
| Application | tenant / role / permission 데이터 |
| API         | 요구 권한 선언                    |

> **Provider가 없으면 RBAC는 아무 일도 하지 않습니다.**

---

## 🔁 Request Flow

```
Request
 → @Public? → PASS
 → ContextProvider 없음? → PASS
 → PermissionChecker 없음? → PASS
 → @RequirePermissions 없음? → PASS
 → PermissionChecker.hasPermission (async)
```

---

## 🧩 Decorators

### `@Public()`

RBAC / Auth Guard를 모두 건너뜁니다.

```ts
@Public()
@Get('/health')
health() {}
```

---

### `@RequirePermissions()`

API 또는 Controller에 요구 권한을 선언합니다.

```ts
@RequirePermissions('user.read')
@Get('/users')
findUsers() {}
```

```ts
@RequirePermissions('admin.access')
@Controller('/admin')
export class AdminController {}
```

---

## 🔌 Interfaces

### `RbacContextProvider`

```ts
export interface RbacContextProvider {
    getContext(request: unknown): unknown;
}
```

> 요청에서 사용자 / 테넌트 / 역할 정보를 추출

---

### `PermissionChecker`

```ts
export interface PermissionChecker {
    hasPermission(context: unknown, permission: string): Promise<boolean>;
}
```

> DB / Cache / 외부 시스템 기반 권한 검사

---

## 🛡 RbacGuard

RBAC Guard는 **Global Guard** 또는 **Route Guard**로 사용 가능합니다.

### 특징

- Provider 미존재 시 자동 스킵
- Async permission 검사 지원
- Strict TypeScript 대응

---

## 🔑 Tokens

```ts
export const RBAC_CONTEXT_PROVIDER_TOKEN = Symbol(
    'RBAC_CONTEXT_PROVIDER_TOKEN',
);
export const PERMISSION_CHECKER_TOKEN = Symbol('PERMISSION_CHECKER_TOKEN');
```

---

## 🧪 Example: Application Integration

### 1️⃣ ContextProvider 구현

```ts
@Injectable()
export class AppContextProvider implements RbacContextProvider {
    getContext(req: Request): AppRequestContext {
        return {
            userId: req.user.id,
            tenantId: req.user.tenantId,
            roles: req.user.roles,
        };
    }
}
```

---

### 2️⃣ PermissionChecker 구현 (Async)

```ts
@Injectable()
export class AppPermissionChecker implements PermissionChecker {
    async hasPermission(
        context: AppRequestContext,
        permission: string,
    ): Promise<boolean> {
        const { tenantId, roles } = context;

        // Redis / DB / Cache 등
        return this.repo.hasPermission(tenantId, roles, permission);
    }
}
```

---

### 3️⃣ AppModule 바인딩

```ts
@Module({
    providers: [
        {
            provide: RBAC_CONTEXT_PROVIDER_TOKEN,
            useClass: AppContextProvider,
        },
        {
            provide: PERMISSION_CHECKER_TOKEN,
            useClass: AppPermissionChecker,
        },
    ],
})
export class AppModule {}
```

> ⚠️ 위 Provider 중 하나라도 없으면 RBAC는 자동 비활성화됩니다.

---

## 🌍 Multi-Tenant RBAC

RBAC 모듈은 tenant 구조를 **알지 못합니다**.

```ts
context = {
    tenantId,
    roles,
};
```

모든 tenant 별 권한 분리는 **Application 책임**입니다.

---

## ⚡ Performance Tips

- permission 단위 DB 조회 ❌
- role → permission 집합을 한 번에 조회 ✅
- Redis / Memory 캐시 적극 권장
- 권한 변경 시 cache invalidate

---

## 🧪 Testing

RBAC Provider 미등록 시 Guard는 항상 `true`를 반환합니다.

```ts
// TestModule
providers: [
    RbacGuard, // ContextProvider / PermissionChecker 없음
];
```

---

## 🚫 What This Module Does NOT Do

- ❌ DB 스키마 정의
- ❌ Role / Permission 관리 UI
- ❌ 권한 캐싱 전략
- ❌ Auth / JWT 처리

---

## 📌 When to Use

- SaaS / Multi-Tenant 서비스
- 점진적 RBAC 도입
- 마이크로서비스 일부만 RBAC 적용
- 테스트 / 배치 / 내부 API 분리

---

## 🏁 Summary

> **RBAC는 강제가 아니라 선택이다.**  
> Provider를 등록하는 순간 활성화되고,  
> 없으면 아무 일도 하지 않는다.

---