Skip to content

Commit f8cf50a

Browse files
doc: update docs md to be inline with current code
1 parent fa05181 commit f8cf50a

21 files changed

Lines changed: 171 additions & 160 deletions

.dockerignore

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,3 @@
1-
# ---------------------------------------------------------------------------
2-
# Build context is intentionally minimal. Only what `pnpm install`, `db:generate`
3-
# and `nest build` (+ `pnpm typecheck`) need is shipped.
4-
#
5-
# KEPT (do NOT ignore): src/, test/, prisma/, package.json, pnpm-lock.yaml,
6-
# pnpm-workspace.yaml, .npmrc, tsconfig.json, nest-cli.json, .swcrc
7-
# (test/ is required: `build` runs `pnpm typecheck` and tsconfig includes test/**)
8-
# ---------------------------------------------------------------------------
9-
101
# Dependencies & build output (reinstalled / regenerated inside the image)
112
node_modules/
123
dist/

docs/authentication.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,13 +428,16 @@ Interface `IAuthJwtAccessTokenPayload`
428428

429429
Interface `IAuthJwtRefreshTokenPayload`
430430

431+
Derived as `Omit<IAuthJwtAccessTokenPayload, 'roleId' | 'username' | 'email'>` — the refresh payload drops `roleId`, `username`, and `email`, keeping the rest:
432+
431433
```typescript
432434
{
433435
loginAt: Date;
434436
loginFrom: EnumUserLoginFrom;
435-
loginWith: EnumUserSignUpWith;
437+
loginWith: EnumUserLoginWith;
436438
userId: string;
437439
sessionId: string;
440+
deviceOwnershipId: string;
438441

439442
// Standard JWT claims
440443
jti?: string; // JWT ID - unique token identifier

docs/authorization.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ flowchart TD
267267
### Important Notes
268268

269269
- `@RoleProtected()` **requires** `@AuthJwtAccessProtected()` and `@UserProtected()` to be applied
270-
- `@AuthJwtAccessProtected()` must be placed at the bottom, followed by `@RoleProtected()`, then `@UserProtected()`. See [Authentication Documentation][ref-doc-authentication] for `@AuthJwtAccessProtected()` details
270+
- Decorators must be stacked in this order from top to bottom: `@RoleProtected()` `@UserProtected()``@AuthJwtAccessProtected()`. See [Authentication Documentation][ref-doc-authentication] for `@AuthJwtAccessProtected()` details
271271
- This decorator stores role abilities via `RequestStoreService.set(RoleAbilityStoreKey, abilities)` (read back with `RequestStoreService.get(RoleAbilityStoreKey)`), which is required by policy guards
272272
- Incorrect ordering will result in runtime errors
273273
- Users with `superAdmin` role type have unrestricted access to all `@RoleProtected` routes, regardless of the specified required roles. The guard returns an empty abilities array for super admins, as they bypass ability checks.
@@ -416,7 +416,7 @@ The factory creates a CASL ability instance that can check if a user can perform
416416
### Important Notes
417417

418418
- `@PolicyAbilityProtected()` **requires** `@AuthJwtAccessProtected()`, `@RoleProtected()`, and `@UserProtected()` to be applied
419-
- Decorators must be stacked in this order from bottom to top: `@PolicyAbilityProtected()``@RoleProtected()``@UserProtected()``@AuthJwtAccessProtected()`. See [Authentication Documentation][ref-doc-authentication] for `@AuthJwtAccessProtected()` details
419+
- Decorators must be stacked in this order from top to bottom: `@PolicyAbilityProtected()``@RoleProtected()``@UserProtected()``@AuthJwtAccessProtected()`. See [Authentication Documentation][ref-doc-authentication] for `@AuthJwtAccessProtected()` details
420420
- Incorrect ordering will result in runtime errors
421421
- Users with `superAdmin` role type have unrestricted access to all `@PolicyAbilityProtected` routes, bypassing all ability checks.
422422
- All actions in a required ability must be present in the user's abilities. For example, if you require `[UPDATE, DELETE]` on `USER` subject, the user must have both actions, not just one.

docs/cache.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ export class SessionService {
150150
```typescript
151151
{
152152
cache: {
153-
url: process.env.CACHE_REDIS_URL ?? 'redis://localhost:6379',
153+
url: process.env.CACHE_REDIS_URL!,
154154
namespace: 'Cache',
155155
ttlInMs: 5 * 60 * 1000 // Default TTL: 5 minutes
156156
}

docs/configuration.md

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ The project uses a modular configuration approach through the NestJS `ConfigModu
1818

1919
- [Overview](#overview)
2020
- [Related Documents](#related-documents)
21-
- [Configuration Principles](#configuration-principles)
2221
- [Configuration Structure](#configuration-structure)
2322
- [App Configuration](#app-configuration)
2423
- [Auth Configuration](#auth-configuration)
@@ -39,7 +38,6 @@ The project uses a modular configuration approach through the NestJS `ConfigModu
3938
- [Feature Flag Configuration](#feature-flag-configuration)
4039
- [Response Configuration](#response-configuration)
4140
- [Firebase Configuration](#firebase-configuration)
42-
- [Conclusion](#conclusion)
4341

4442
## Configuration Structure
4543

@@ -139,7 +137,7 @@ encryptionSecretKey: string // Secret key used to derive AES-256 encryption
139137
**File**: `src/configs/auth.config.ts`
140138
**Interface**: `IConfigAuth`
141139

142-
This configuration manages JWT authentication settings including token configuration, password policies, social authentication, dan two-factor authentication.
140+
This configuration manages JWT authentication settings including token configuration, password policies, social authentication, and two-factor authentication.
143141

144142
> **Environment Variables**: See [Environment Documentation](environment.md) for detailed environment variable configuration.
145143
@@ -341,7 +339,7 @@ enable: boolean // Turn logging on/off
341339

342340
**`level`** - Log level configuration
343341
```typescript
344-
level: string // Log levels: silent, trace, debug, info, warn, error, fatal
342+
level: string // Log level: error, warn, info, verbose, debug, silly
345343
```
346344

347345
**`intoFile`** - File logging option
@@ -409,11 +407,8 @@ timeoutInMs: number // Request timeout in milliseconds (default: 300
409407
**`cors`** - CORS configuration
410408
```typescript
411409
cors: {
412-
allowedMethod: string[]; // Allowed HTTP methods (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
413-
allowedOrigin: string[] | string | boolean; // Allowed origins (from CORS_ALLOWED_ORIGIN env variable)
414-
// - string[]: Array of origins (e.g., ["*.example.com", "api.myapp.com"])
415-
// - string: Single origin or wildcard (e.g., "*.example.com" or "*")
416-
// - boolean: true=allow all, false=deny all
410+
allowedMethod: string[]; // Allowed HTTP methods (GET, DELETE, PUT, PATCH, POST, HEAD, OPTIONS)
411+
allowedOrigin: string[]; // Allowed origins, parsed from CORS_ALLOWED_ORIGIN (comma-separated into an array)
417412
allowedHeader: string[]; // Allowed headers for CORS requests
418413
}
419414
```
@@ -431,8 +426,8 @@ cors: {
431426
**`throttle`** - Rate limiting configuration
432427
```typescript
433428
throttle: {
434-
ttlInMs: number; // Time window in milliseconds (default: 500ms)
435-
limit: number; // Maximum requests per time window (default: 10)
429+
ttlInMs: number; // Time window in milliseconds (default: 60000ms / 60s)
430+
limit: number; // Maximum requests per time window (default: 100)
436431
}
437432
```
438433

@@ -488,6 +483,14 @@ usernamePattern: RegExp // Regex pattern for valid usernames
488483
uploadPhotoProfilePath: string // Path template for user profile photo uploads
489484
```
490485

486+
**`default`** - Default role and country assigned to new users
487+
```typescript
488+
default: {
489+
role: string; // Default role name (default: 'user')
490+
country: string; // Default country code (default: 'ID')
491+
}
492+
```
493+
491494
### Documentation Configuration
492495

493496

@@ -505,11 +508,6 @@ This configuration manages API documentation settings for Swagger/OpenAPI.
505508
name: string // API documentation title
506509
```
507510

508-
**`description`** - Documentation description
509-
```typescript
510-
description: string // API documentation description
511-
```
512-
513511
**`prefix`** - Documentation URL prefix
514512
```typescript
515513
prefix: string // URL prefix for API documentation (default: '/docs')
@@ -546,7 +544,7 @@ language: string // Default application language
546544
**File**: `src/configs/email.config.ts`
547545
**Interface**: `IConfigEmail`
548546

549-
This configuration manages default email addresses for system communications. Email addresses (`noreply`, `support`, `admin`) can be overridden via environment variables. If not set, they fall back to hardcoded default values.
547+
This configuration manages default email addresses for system communications. Email addresses (`noreply`, `support`, `admin`) come from environment variables and fall back to `null` when unset.
550548

551549
> **Environment Variables**: See [Environment Documentation](environment.md) for detailed environment variable configuration.
552550
@@ -705,11 +703,6 @@ uploadContentPath: string // Path pattern for uploading policy content fil
705703
contentPublicPath: string // Public path for accessing policy content
706704
```
707705

708-
**`filenamePattern`** - Filename pattern for policy files
709-
```typescript
710-
filenamePattern: string // Pattern for policy file names
711-
```
712-
713706
### Feature Flag Configuration
714707

715708
**File**: `src/configs/feature-flag.config.ts`
@@ -771,7 +764,7 @@ clientEmail?: string // Firebase service account client email
771764

772765
**`privateKey`** - Firebase service account private key
773766
```typescript
774-
privateKey?: string // Base64-encoded DER PKCS8 private key (from Firebase Console service account JSON)
767+
privateKey?: string // Service account private key (PEM); escaped `\n` sequences are converted to real newlines at load
775768
```
776769

777770
> [!NOTE]

docs/environment.md

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ APP_NAME=ACKNestJs
7878
APP_ENV=local
7979
APP_LANGUAGE=en
8080
APP_TIMEZONE=Asia/Jakarta
81-
APP_ENCRYPTION_SECRET_KEY=<your-random-string>
81+
APP_ENCRYPTION_SECRET_KEY=<your_app_encryption_secret_key>
8282

8383
# Home/Organization
8484
HOME_URL=https://example.com
@@ -112,21 +112,21 @@ AUTH_JWT_AUDIENCE=ACKNestJs
112112

113113
# Access Token Configuration
114114
AUTH_JWT_ACCESS_TOKEN_JWKS_URI=http://localhost:3011/.well-known/access-jwks.json
115-
AUTH_JWT_ACCESS_TOKEN_KID=ack-access-2024-001
116-
AUTH_JWT_ACCESS_TOKEN_PRIVATE_KEY=<your-random-string>
117-
AUTH_JWT_ACCESS_TOKEN_PUBLIC_KEY=<your-random-string>
115+
AUTH_JWT_ACCESS_TOKEN_KID=<your_jwt_access_token_kid>
116+
AUTH_JWT_ACCESS_TOKEN_PRIVATE_KEY=<your_jwt_access_token_private_key>
117+
AUTH_JWT_ACCESS_TOKEN_PUBLIC_KEY=<your_jwt_access_token_public_key>
118118
AUTH_JWT_ACCESS_TOKEN_EXPIRED=1h
119119

120120
# Refresh Token Configuration
121121
AUTH_JWT_REFRESH_TOKEN_JWKS_URI=http://localhost:3011/.well-known/refresh-jwks.json
122-
AUTH_JWT_REFRESH_TOKEN_KID=ack-refresh-2024-001
123-
AUTH_JWT_REFRESH_TOKEN_PRIVATE_KEY=<your-random-string>
124-
AUTH_JWT_REFRESH_TOKEN_PUBLIC_KEY=<your-random-string>
122+
AUTH_JWT_REFRESH_TOKEN_KID=<your_jwt_refresh_token_kid>
123+
AUTH_JWT_REFRESH_TOKEN_PRIVATE_KEY=<your_jwt_refresh_token_private_key>
124+
AUTH_JWT_REFRESH_TOKEN_PUBLIC_KEY=<your_jwt_refresh_token_public_key>
125125
AUTH_JWT_REFRESH_TOKEN_EXPIRED=30d
126126

127127
# Two-Factor Authentication
128128
AUTH_TWO_FACTOR_ISSUER=ACKNestJsTwoFactor
129-
AUTH_TWO_FACTOR_ENCRYPTION_KEY=<your-random-string>
129+
AUTH_TWO_FACTOR_ENCRYPTION_KEY=<your_two_factor_encryption_key>
130130

131131
# Social Authentication (Optional)
132132
AUTH_SOCIAL_GOOGLE_CLIENT_ID=
@@ -187,21 +187,21 @@ APP_ENV=local
187187
```
188188

189189
**`APP_LANGUAGE`** *(required)*
190-
Default language for the application. Supported: `en`, `id`
190+
Default language for the application. Validated against `EnumMessageLanguage`; currently only `en` is supported.
191191
```bash
192192
APP_LANGUAGE=en
193193
```
194194

195195
**`APP_TIMEZONE`** *(required)*
196-
Default timezone for date operations. Example: `Asia/Jakarta`, `UTC`
196+
Default timezone for date operations. Validated against `EnumRequestTimezone`; currently only `Asia/Jakarta` is supported.
197197
```bash
198198
APP_TIMEZONE=Asia/Jakarta
199199
```
200200

201201
**`APP_ENCRYPTION_SECRET_KEY`** *(required)*
202-
Secret key used to derive an AES-256 encryption key for encrypting sensitive data (recommended 32+ characters). Empty by default — startup validation rejects an unset value. Generate a unique key per environment (`openssl rand -base64 32`); never reuse the example below.
202+
Secret key used to derive an AES-256 encryption key for encrypting sensitive data. Must be 32-64 characters (enforced by `@MinLength(32)` / `@MaxLength(64)`). Empty by default — startup validation rejects an unset value. Generate a unique key per environment (`openssl rand -base64 32`); never reuse the example below.
203203
```bash
204-
APP_ENCRYPTION_SECRET_KEY=<your-random-string>
204+
APP_ENCRYPTION_SECRET_KEY=<your_app_encryption_secret_key>
205205
```
206206

207207
### Home/Organization Settings
@@ -221,7 +221,7 @@ HOME_URL=https://example.com
221221
### HTTP Server Settings
222222

223223
**`HTTP_HOST`** *(required)*
224-
Host/IP address for the HTTP server.
224+
Address to bind the HTTP server to. Accepts a hostname such as `localhost` or an IPv4 literal like `0.0.0.0` or `127.0.0.1`.
225225
```bash
226226
HTTP_HOST=localhost
227227
```
@@ -241,7 +241,7 @@ LOGGER_ENABLE=true
241241
```
242242

243243
**`LOGGER_LEVEL`** *(required)*
244-
Logging level using Pino logger. Options: `silent`, `trace`, `debug`, `info`, `warn`, `error`, `fatal`
244+
Logging level. Validated against `EnumLoggerLevel`. Options: `error`, `warn`, `info`, `verbose`, `debug`, `silly`
245245
```bash
246246
LOGGER_LEVEL=debug
247247
```
@@ -374,19 +374,19 @@ AUTH_JWT_ACCESS_TOKEN_JWKS_URI=http://localhost:3011/.well-known/access-jwks.jso
374374
**`AUTH_JWT_ACCESS_TOKEN_KID`** *(required)*
375375
Key ID for access token. Generated automatically by `pnpm generate:keys`.
376376
```bash
377-
AUTH_JWT_ACCESS_TOKEN_KID=ack-access-2024-001
377+
AUTH_JWT_ACCESS_TOKEN_KID=<your_jwt_access_token_kid>
378378
```
379379

380380
**`AUTH_JWT_ACCESS_TOKEN_PRIVATE_KEY`** *(required)*
381381
Private key content for signing access tokens.
382382
```bash
383-
AUTH_JWT_ACCESS_TOKEN_PRIVATE_KEY=<your-random-string>
383+
AUTH_JWT_ACCESS_TOKEN_PRIVATE_KEY=<your_jwt_access_token_private_key>
384384
```
385385

386386
**`AUTH_JWT_ACCESS_TOKEN_PUBLIC_KEY`** *(required)*
387387
Public key content for verifying access tokens.
388388
```bash
389-
AUTH_JWT_ACCESS_TOKEN_PUBLIC_KEY=<your-random-string>
389+
AUTH_JWT_ACCESS_TOKEN_PUBLIC_KEY=<your_jwt_access_token_public_key>
390390
```
391391

392392
**`AUTH_JWT_ACCESS_TOKEN_EXPIRED`** *(required)*
@@ -406,19 +406,19 @@ AUTH_JWT_REFRESH_TOKEN_JWKS_URI=http://localhost:3011/.well-known/refresh-jwks.j
406406
**`AUTH_JWT_REFRESH_TOKEN_KID`** *(required)*
407407
Key ID for refresh token. Generated automatically by `pnpm generate:keys`.
408408
```bash
409-
AUTH_JWT_REFRESH_TOKEN_KID=ack-refresh-2024-001
409+
AUTH_JWT_REFRESH_TOKEN_KID=<your_jwt_refresh_token_kid>
410410
```
411411

412412
**`AUTH_JWT_REFRESH_TOKEN_PRIVATE_KEY`** *(required)*
413413
Private key content for signing refresh tokens.
414414
```bash
415-
AUTH_JWT_REFRESH_TOKEN_PRIVATE_KEY=<your-random-string>
415+
AUTH_JWT_REFRESH_TOKEN_PRIVATE_KEY=<your_jwt_refresh_token_private_key>
416416
```
417417

418418
**`AUTH_JWT_REFRESH_TOKEN_PUBLIC_KEY`** *(required)*
419419
Public key content for verifying refresh tokens.
420420
```bash
421-
AUTH_JWT_REFRESH_TOKEN_PUBLIC_KEY=<your-random-string>
421+
AUTH_JWT_REFRESH_TOKEN_PUBLIC_KEY=<your_jwt_refresh_token_public_key>
422422
```
423423

424424
**`AUTH_JWT_REFRESH_TOKEN_EXPIRED`** *(required)*
@@ -458,16 +458,16 @@ AUTH_SOCIAL_APPLE_SIGN_IN_CLIENT_ID=
458458

459459
### Two-Factor Authentication Settings
460460

461-
**`AUTH_TWO_FACTOR_ISSUER`** *(optional)*
462-
Issuer name displayed in authenticator apps.
461+
**`AUTH_TWO_FACTOR_ISSUER`** *(required)*
462+
Issuer name displayed in authenticator apps. Empty by default — startup validation rejects an unset value.
463463
```bash
464464
AUTH_TWO_FACTOR_ISSUER=ACKNestJsTwoFactor
465465
```
466466

467-
**`AUTH_TWO_FACTOR_ENCRYPTION_KEY`** *(required for 2FA)*
467+
**`AUTH_TWO_FACTOR_ENCRYPTION_KEY`** *(required)*
468468
Secret used to derive an AES-256 key for encrypting TOTP secrets (recommended 32+ chars). Empty by default — startup validation rejects an unset value. Generate a unique key per environment (`openssl rand -base64 32`); never reuse the example below.
469469
```bash
470-
AUTH_TWO_FACTOR_ENCRYPTION_KEY=<your-random-string>
470+
AUTH_TWO_FACTOR_ENCRYPTION_KEY=<your_two_factor_encryption_key>
471471
```
472472

473473
### AWS Settings
@@ -489,8 +489,8 @@ AWS IAM secret access key for S3 bucket operations.
489489
AWS_S3_IAM_CREDENTIAL_SECRET=
490490
```
491491

492-
**`AWS_S3_IAM_ARN`** *(optional)*
493-
AWS IAM Role ARN for S3 operations. Used for role-based access control and temporary credentials.
492+
**`AWS_S3_IAM_ARN`** *(required when S3 credentials are set)*
493+
AWS IAM Role ARN for S3 operations. Used for role-based access control and temporary credentials. Validation requires it whenever `AWS_S3_IAM_CREDENTIAL_KEY` or `AWS_S3_IAM_CREDENTIAL_SECRET` is provided.
494494
```bash
495495
AWS_S3_IAM_ARN=
496496
```
@@ -548,8 +548,8 @@ AWS IAM secret access key for SES email service.
548548
AWS_SES_IAM_CREDENTIAL_SECRET=
549549
```
550550

551-
**`AWS_SES_IAM_ARN`** *(optional)*
552-
AWS IAM Role ARN for SES operations. Used for role-based access control and temporary credentials.
551+
**`AWS_SES_IAM_ARN`** *(required when SES credentials are set)*
552+
AWS IAM Role ARN for SES operations. Used for role-based access control and temporary credentials. Validation requires it whenever `AWS_SES_IAM_CREDENTIAL_KEY` or `AWS_SES_IAM_CREDENTIAL_SECRET` is provided.
553553
```bash
554554
AWS_SES_IAM_ARN=
555555
```

docs/installation.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,8 @@ After hosting your JWKS files, update your `.env` file:
138138

139139
```bash
140140
# Update with your actual JWKS URLs
141-
AUTH_JWT_ACCESS_TOKEN_JWKS_URI="https://your-domain.com/.well-known/access-jwks.json"
142-
AUTH_JWT_REFRESH_TOKEN_JWKS_URI="https://your-domain.com/.well-known/refresh-jwks.json"
141+
AUTH_JWT_ACCESS_TOKEN_JWKS_URI="https://<your_domain>/.well-known/access-jwks.json"
142+
AUTH_JWT_REFRESH_TOKEN_JWKS_URI="https://<your_domain>/.well-known/refresh-jwks.json"
143143
```
144144

145145

@@ -154,7 +154,7 @@ Docker provides the fastest and most reliable way to set up the ACK NestJS Boile
154154

155155
The Docker setup provides:
156156
- **MongoDB replica set** - Configured for transactions
157-
- **Redis instances** - Separate instances for caching and queues
157+
- **Redis** - Single instance serving both caching (`db:0`) and queues (`db:1`)
158158
- **JWKS server** - Hosts your JWT public keys automatically
159159
- **BullMQ Dashboard** - Queue monitoring interface
160160

@@ -257,7 +257,7 @@ docker-compose --profile apis up -d
257257
```
258258

259259
**What this command does:**
260-
- Starts MongoDB replica set with 1 nodes (ports 27017)
260+
- Starts MongoDB single-node replica set (port 27017)
261261
- Launches Redis server for caching and queues (port 6379)
262262
- Starts JWKS server to host your JWT public keys (port 3011)
263263
- Runs BullMQ dashboard for queue monitoring (port 3010)

docs/logger.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ LOGGER_PRETTIER=true
7777
LOGGER_AUTO=false
7878
7979
# Sentry Configuration (Optional)
80-
SENTRY_DSN=https://your-sentry-dsn@sentry.io/project-id
80+
SENTRY_DSN=<your_sentry_dsn>
8181
```
8282

8383
| Variable | Description | Type | Default | Required |
@@ -617,7 +617,7 @@ Configure Sentry by setting the `SENTRY_DSN` environment variable:
617617

618618
```env
619619
# .env.production
620-
SENTRY_DSN=https://your-public-key@o123456.ingest.sentry.io/7654321
620+
SENTRY_DSN=<your_sentry_dsn>
621621
```
622622

623623
### Configuration Details

0 commit comments

Comments
 (0)