@breadstone/archipel-mcp 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/data/guides/ai-text-generation.md +361 -0
  2. package/data/guides/analytics-and-error-tracking.md +189 -0
  3. package/data/guides/authentication-and-authorization.md +657 -0
  4. package/data/guides/blob-storage.md +242 -0
  5. package/data/guides/caching.md +255 -0
  6. package/data/guides/cryptography-and-otp.md +240 -0
  7. package/data/guides/document-generation.md +174 -0
  8. package/data/guides/email-delivery.md +196 -0
  9. package/data/guides/esigning-integration.md +231 -0
  10. package/data/guides/getting-started.md +351 -0
  11. package/data/guides/implementing-ports.md +317 -0
  12. package/data/guides/index.md +61 -0
  13. package/data/guides/mcp-server.md +222 -0
  14. package/data/guides/openapi-and-feature-discovery.md +266 -0
  15. package/data/guides/payments-and-feature-gating.md +244 -0
  16. package/data/guides/resource-management.md +352 -0
  17. package/data/guides/telemetry-and-observability.md +190 -0
  18. package/data/guides/testing.md +319 -0
  19. package/data/guides/tsdoc-guidelines.md +45 -0
  20. package/data/packages/platform-openapi/api/Class.SwaggerFeatureDiscovery.md +10 -6
  21. package/package.json +1 -1
  22. package/src/GuidesLoader.d.ts +13 -0
  23. package/src/GuidesLoader.js +81 -0
  24. package/src/main.js +36 -198
  25. package/src/models/IGuideDoc.d.ts +15 -0
  26. package/src/models/IGuideDoc.js +3 -0
  27. package/src/tools/registerGetConfigPatternTool.d.ts +5 -0
  28. package/src/tools/registerGetConfigPatternTool.js +15 -0
  29. package/src/tools/registerGetDtoPatternTool.d.ts +5 -0
  30. package/src/tools/registerGetDtoPatternTool.js +15 -0
  31. package/src/tools/registerGetErrorHandlingPatternTool.d.ts +5 -0
  32. package/src/tools/registerGetErrorHandlingPatternTool.js +15 -0
  33. package/src/tools/registerGetGuardPatternTool.d.ts +5 -0
  34. package/src/tools/registerGetGuardPatternTool.js +15 -0
  35. package/src/tools/registerGetGuideTool.d.ts +6 -0
  36. package/src/tools/registerGetGuideTool.js +32 -0
  37. package/src/tools/registerGetMappingPatternTool.d.ts +5 -0
  38. package/src/tools/registerGetMappingPatternTool.js +34 -0
  39. package/src/tools/registerGetModulePatternTool.d.ts +5 -0
  40. package/src/tools/registerGetModulePatternTool.js +29 -0
  41. package/src/tools/registerGetPackageDocTool.d.ts +6 -0
  42. package/src/tools/registerGetPackageDocTool.js +43 -0
  43. package/src/tools/registerGetQueryPatternTool.d.ts +5 -0
  44. package/src/tools/registerGetQueryPatternTool.js +29 -0
  45. package/src/tools/registerGetRepositoryPatternTool.d.ts +5 -0
  46. package/src/tools/registerGetRepositoryPatternTool.js +29 -0
  47. package/src/tools/registerGetTestingPatternTool.d.ts +5 -0
  48. package/src/tools/registerGetTestingPatternTool.js +15 -0
  49. package/src/tools/registerListGuidesTool.d.ts +6 -0
  50. package/src/tools/registerListGuidesTool.js +22 -0
  51. package/src/tools/registerListPackagesTool.d.ts +6 -0
  52. package/src/tools/registerListPackagesTool.js +20 -0
  53. package/src/tools/registerSearchDocsTool.d.ts +6 -0
  54. package/src/tools/registerSearchDocsTool.js +35 -0
  55. package/src/tools/registerSearchGuidesTool.d.ts +6 -0
  56. package/src/tools/registerSearchGuidesTool.js +28 -0
@@ -0,0 +1,240 @@
1
+ ---
2
+ title: Cryptography & OTP
3
+ description: Hash passwords with bcrypt, generate prefixed UUIDs, and implement TOTP-based multi-factor authentication with QR code enrollment.
4
+ order: 17
5
+ ---
6
+
7
+ # Cryptography & OTP
8
+
9
+ This guide covers cryptographic utilities provided by `platform-cryptography`: password hashing with bcrypt, prefixed UUID generation, and TOTP-based one-time password flows for multi-factor authentication.
10
+
11
+ ---
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ yarn add @breadstone/archipel-platform-cryptography
17
+ ```
18
+
19
+ ---
20
+
21
+ ## Password Hashing with Bcrypt
22
+
23
+ `BcryptService` wraps the `bcrypt` library to hash and verify passwords securely. It generates a unique salt per hash automatically.
24
+
25
+ ### Hashing a Password
26
+
27
+ ```typescript
28
+ import { Injectable } from '@nestjs/common';
29
+ import { BcryptService } from '@breadstone/archipel-platform-cryptography';
30
+
31
+ @Injectable()
32
+ export class UserService {
33
+ private readonly _bcrypt: BcryptService;
34
+
35
+ constructor(bcrypt: BcryptService) {
36
+ this._bcrypt = bcrypt;
37
+ }
38
+
39
+ public async createUser(email: string, password: string): Promise<void> {
40
+ const hashedPassword = await this._bcrypt.hash(password);
41
+ // Store hashedPassword in the database — never the plain password
42
+ await this._userRepository.create({ email, password: hashedPassword });
43
+ }
44
+ }
45
+ ```
46
+
47
+ ### Verifying a Password
48
+
49
+ ```typescript
50
+ public async authenticate(email: string, password: string): Promise<boolean> {
51
+ const user = await this._userRepository.findByEmail(email);
52
+ if (!user) {
53
+ return false;
54
+ }
55
+
56
+ return this._bcrypt.compare(password, user.password);
57
+ }
58
+ ```
59
+
60
+ `compare()` returns `true` if the plain-text password matches the stored hash.
61
+
62
+ ---
63
+
64
+ ## Generating Prefixed UUIDs
65
+
66
+ `CryptoService` generates UUIDs with a configurable prefix. This is useful for creating human-readable identifiers that indicate their resource type.
67
+
68
+ ```typescript
69
+ import { Injectable } from '@nestjs/common';
70
+ import { CryptoService } from '@breadstone/archipel-platform-cryptography';
71
+
72
+ @Injectable()
73
+ export class OrderService {
74
+ private readonly _crypto: CryptoService;
75
+
76
+ constructor(crypto: CryptoService) {
77
+ this._crypto = crypto;
78
+ }
79
+
80
+ public createOrderId(): string {
81
+ return this._crypto.getRandomGuid('ord');
82
+ // Example: "ord-a1b2c3d4-e5f6-7890-abcd-ef1234567890"
83
+ }
84
+ }
85
+ ```
86
+
87
+ The prefix is required and must be a non-empty string. Use short, descriptive prefixes that represent the resource type:
88
+
89
+ | Resource | Prefix | Example |
90
+ | ------------ | ------ | ------------------------------------------ |
91
+ | Order | `ord` | `ord-550e8400-e29b-41d4-a716-446655440000` |
92
+ | Invoice | `inv` | `inv-6ba7b810-9dad-11d1-80b4-00c04fd430c8` |
93
+ | Subscription | `sub` | `sub-f47ac10b-58cc-4372-a567-0e02b2c3d479` |
94
+ | User | `usr` | `usr-7c9e6679-7425-40de-944b-e07fc1f90ae7` |
95
+
96
+ ---
97
+
98
+ ## TOTP Multi-Factor Authentication
99
+
100
+ `OtpService` implements TOTP (Time-Based One-Time Password) as defined in [RFC 6238](https://datatracker.ietf.org/doc/html/rfc6238). It supports QR code enrollment and token verification.
101
+
102
+ ### Injecting OtpService
103
+
104
+ `OtpService` is provided behind the `OTP_SERVICE_TOKEN` injection token so consumers depend on the `IOtpService` interface:
105
+
106
+ ```typescript
107
+ import { Module } from '@nestjs/common';
108
+ import { OtpService, OTP_SERVICE_TOKEN } from '@breadstone/archipel-platform-cryptography';
109
+
110
+ @Module({
111
+ providers: [
112
+ {
113
+ provide: OTP_SERVICE_TOKEN,
114
+ useClass: OtpService,
115
+ },
116
+ ],
117
+ exports: [OTP_SERVICE_TOKEN],
118
+ })
119
+ export class SecurityModule {}
120
+ ```
121
+
122
+ ### Enrolling a User
123
+
124
+ Generate a secret and a QR code URI for the user's authenticator app:
125
+
126
+ ```typescript
127
+ import { Inject, Injectable } from '@nestjs/common';
128
+ import { OTP_SERVICE_TOKEN, type IOtpService } from '@breadstone/archipel-platform-cryptography';
129
+
130
+ @Injectable()
131
+ export class MfaService {
132
+ private readonly _otp: IOtpService;
133
+
134
+ constructor(@Inject(OTP_SERVICE_TOKEN) otp: IOtpService) {
135
+ this._otp = otp;
136
+ }
137
+
138
+ public async enroll(userId: string, email: string): Promise<{ secret: string; uri: string }> {
139
+ const secret = this._otp.generateSecret();
140
+ const uri = this._otp.generateUri({
141
+ issuer: 'MyApp',
142
+ label: email,
143
+ secret: secret,
144
+ });
145
+
146
+ // Store the secret securely alongside the user record
147
+ await this._userRepository.updateMfaSecret(userId, secret);
148
+
149
+ return { secret, uri };
150
+ // The URI can be encoded as a QR code for scanning with Google Authenticator, Authy, etc.
151
+ }
152
+ }
153
+ ```
154
+
155
+ ### Verifying a Token
156
+
157
+ Verify a 6-digit TOTP code entered by the user:
158
+
159
+ ```typescript
160
+ public verifyToken(token: string, secret: string): boolean {
161
+ return this._otp.verify(token, secret);
162
+ }
163
+ ```
164
+
165
+ Verification uses a configurable tolerance window (`TOTP_EPOCH_TOLERANCE`). The default tolerance is **30 seconds** (±1 time step), meaning the current code and the immediately preceding/following codes are accepted. This compensates for minor clock drift between the server and the user's device.
166
+
167
+ ### Tolerance Configuration
168
+
169
+ The `TOTP_EPOCH_TOLERANCE` constant controls the verification window:
170
+
171
+ | `TOTP_EPOCH_TOLERANCE` | Accepted range |
172
+ | ---------------------- | ----------------- |
173
+ | `0` | Current step only |
174
+ | `30` | ±1 step (±30 s) |
175
+ | `60` | ±2 steps (±60 s) |
176
+ | `90` | ±3 steps (±90 s) |
177
+
178
+ The default value is `30` (±1 step).
179
+
180
+ ---
181
+
182
+ ## Combining Services
183
+
184
+ A typical MFA login flow uses all three services:
185
+
186
+ ```typescript
187
+ @Injectable()
188
+ export class AuthService {
189
+ private readonly _bcrypt: BcryptService;
190
+ private readonly _otp: IOtpService;
191
+ private readonly _crypto: CryptoService;
192
+
193
+ constructor(bcrypt: BcryptService, @Inject(OTP_SERVICE_TOKEN) otp: IOtpService, crypto: CryptoService) {
194
+ this._bcrypt = bcrypt;
195
+ this._otp = otp;
196
+ this._crypto = crypto;
197
+ }
198
+
199
+ public async login(email: string, password: string, totpCode?: string): Promise<IAuthResult> {
200
+ const user = await this._userRepository.findByEmail(email);
201
+ if (!user) {
202
+ throw new UnauthorizedException();
203
+ }
204
+
205
+ // Step 1: Verify password
206
+ const validPassword = await this._bcrypt.compare(password, user.password);
207
+ if (!validPassword) {
208
+ throw new UnauthorizedException();
209
+ }
210
+
211
+ // Step 2: Verify TOTP (if MFA is enabled)
212
+ if (user.mfaEnabled) {
213
+ if (!totpCode) {
214
+ return { status: 'mfa-required' };
215
+ }
216
+ const validTotp = this._otp.verify(totpCode, user.mfaSecret);
217
+ if (!validTotp) {
218
+ throw new UnauthorizedException('Invalid MFA code');
219
+ }
220
+ }
221
+
222
+ // Step 3: Issue session
223
+ const sessionId = this._crypto.getRandomGuid('ses');
224
+ return { status: 'authenticated', sessionId };
225
+ }
226
+ }
227
+ ```
228
+
229
+ ---
230
+
231
+ ## Security Best Practices
232
+
233
+ | Practice | Why |
234
+ | ----------------------------------- | --------------------------------------------------------- |
235
+ | Never store plain-text passwords | Always use `BcryptService.hash()` before persisting |
236
+ | Store MFA secrets encrypted at rest | The TOTP secret is equivalent to a password |
237
+ | Use rate limiting on verification | Prevents brute-force attacks on 6-digit TOTP codes |
238
+ | Generate backup codes on enrollment | Users may lose access to their authenticator device |
239
+ | Log MFA events, not secrets | Never log secrets, tokens, or plain-text passwords |
240
+ | Use `OTP_SERVICE_TOKEN` for DI | Depend on `IOtpService` interface, not the concrete class |
@@ -0,0 +1,174 @@
1
+ ---
2
+ title: Document Generation
3
+ description: Generate PDF and DOCX documents from templates with variable substitution and image processing.
4
+ order: 11
5
+ ---
6
+
7
+ # Document Generation
8
+
9
+ This guide covers generating documents with `platform-documents`: template setup, variable substitution, image processing, and rendering to PDF or DOCX.
10
+
11
+ ---
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ yarn add @breadstone/archipel-platform-documents
17
+ ```
18
+
19
+ ---
20
+
21
+ ## Module Registration
22
+
23
+ ```typescript
24
+ import { Module } from '@nestjs/common';
25
+ import { DocumentModule } from '@breadstone/archipel-platform-documents';
26
+
27
+ @Module({
28
+ imports: [
29
+ DocumentModule.forRoot({
30
+ maxImageWidth: 1920,
31
+ maxImageHeight: 1080,
32
+ delimiters: { start: '[[', end: ']]' },
33
+ }),
34
+ ],
35
+ })
36
+ export class AppModule {}
37
+ ```
38
+
39
+ ### Options
40
+
41
+ | Option | Default | Description |
42
+ | ---------------- | ------- | ------------------------------------------------- |
43
+ | `maxImageWidth` | `1920` | Maximum width for embedded images (in pixels) |
44
+ | `maxImageHeight` | `1080` | Maximum height for embedded images (in pixels) |
45
+ | `delimiters` | `[[ ]]` | Start and end delimiters for template variables |
46
+ | `debug` | `false` | Enable verbose logging for the rendering pipeline |
47
+
48
+ ---
49
+
50
+ ## Creating Templates
51
+
52
+ Templates are document files (DOCX) with placeholder variables. By default, placeholders use double brackets:
53
+
54
+ ```
55
+ Dear [[customerName]],
56
+
57
+ Your order [[orderId]] has been confirmed.
58
+ Total: [[orderTotal]]
59
+
60
+ Thank you for your business.
61
+ ```
62
+
63
+ You can change the delimiter format:
64
+
65
+ ```typescript
66
+ DocumentModule.forRoot({
67
+ delimiters: { start: '{{', end: '}}' },
68
+ });
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Rendering Documents
74
+
75
+ Use `DocumentEngine` to render templates with data:
76
+
77
+ ```typescript
78
+ import { Injectable } from '@nestjs/common';
79
+ import { DocumentEngine } from '@breadstone/archipel-platform-documents';
80
+
81
+ @Injectable()
82
+ export class InvoiceService {
83
+ private readonly _documentEngine: DocumentEngine;
84
+
85
+ constructor(documentEngine: DocumentEngine) {
86
+ this._documentEngine = documentEngine;
87
+ }
88
+
89
+ public async generateInvoice(orderId: string, data: Record<string, unknown>): Promise<Buffer> {
90
+ return this._documentEngine.render({
91
+ template: 'invoice-template.docx',
92
+ data: {
93
+ customerName: data['customerName'],
94
+ orderId,
95
+ orderTotal: data['total'],
96
+ date: new Date().toLocaleDateString(),
97
+ },
98
+ format: 'pdf', // or 'docx'
99
+ });
100
+ }
101
+ }
102
+ ```
103
+
104
+ ### Supported Output Formats
105
+
106
+ | Format | Renderer | Description |
107
+ | ------ | ------------- | ------------------------------------- |
108
+ | `pdf` | PDF Renderer | Convert template to PDF |
109
+ | `docx` | DOCX Renderer | Keep as DOCX with filled placeholders |
110
+
111
+ ---
112
+
113
+ ## Image Processing
114
+
115
+ The `SharpImageProcessor` automatically optimizes embedded images:
116
+
117
+ - Resizes images that exceed `maxImageWidth` or `maxImageHeight`
118
+ - Preserves aspect ratio
119
+ - Compresses images for smaller file sizes
120
+
121
+ This is useful for templates that include dynamic images (logos, product photos, signatures).
122
+
123
+ ---
124
+
125
+ ## Serving Documents via HTTP
126
+
127
+ ```typescript
128
+ import { Controller, Get, Res, Param } from '@nestjs/common';
129
+ import { Response } from 'express';
130
+
131
+ @Controller('invoices')
132
+ export class InvoiceController {
133
+ private readonly _invoiceService: InvoiceService;
134
+
135
+ constructor(invoiceService: InvoiceService) {
136
+ this._invoiceService = invoiceService;
137
+ }
138
+
139
+ @Get(':orderId/pdf')
140
+ public async downloadInvoice(@Param('orderId') orderId: string, @Res() res: Response): Promise<void> {
141
+ const pdf = await this._invoiceService.generateInvoice(orderId, {
142
+ /* ... */
143
+ });
144
+
145
+ res.set({
146
+ 'Content-Type': 'application/pdf',
147
+ 'Content-Disposition': `attachment; filename="invoice-${orderId}.pdf"`,
148
+ });
149
+
150
+ res.send(pdf);
151
+ }
152
+ }
153
+ ```
154
+
155
+ ---
156
+
157
+ ## Debug Mode
158
+
159
+ Enable debug logging to trace the rendering pipeline:
160
+
161
+ ```typescript
162
+ DocumentModule.forRoot({
163
+ debug: true,
164
+ });
165
+ ```
166
+
167
+ This logs each step of the rendering process: template loading, placeholder parsing, variable substitution, image processing, and final output generation.
168
+
169
+ ---
170
+
171
+ ## Next Steps
172
+
173
+ - See the [Blob Storage](/guides/blob-storage) guide for storing generated documents
174
+ - Browse the [platform-documents API reference](/packages/platform-documents/api/) for complete method signatures
@@ -0,0 +1,196 @@
1
+ ---
2
+ title: Email Delivery
3
+ description: Send transactional emails with multiple providers, template engines, and email verification flows.
4
+ order: 8
5
+ ---
6
+
7
+ # Email Delivery
8
+
9
+ This guide covers sending emails with `platform-mailing`: choosing a delivery provider, configuring template rendering, sending transactional emails, and integrating email verification flows.
10
+
11
+ ---
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ yarn add @breadstone/archipel-platform-mailing
17
+ ```
18
+
19
+ ---
20
+
21
+ ## Choose a Delivery Strategy
22
+
23
+ `platform-mailing` supports multiple email providers. You select the strategy via environment variables — no code changes required to switch providers.
24
+
25
+ | Strategy | Value for `MAIL_DELIVERY_STRATEGY` | When to use |
26
+ | ------------ | ---------------------------------- | ------------------------------------ |
27
+ | **SMTP** | `smtp` | Any SMTP server (self-hosted, relay) |
28
+ | **Postmark** | `postmark` | Postmark transactional email |
29
+ | **Resend** | `resend` | Resend API |
30
+ | **SendGrid** | `sendgrid` | Twilio SendGrid |
31
+ | **Mailgun** | `mailgun` | Mailgun API |
32
+ | **Log** | `log` | Development only — logs to console |
33
+
34
+ ---
35
+
36
+ ## Module Registration
37
+
38
+ `MailModule` is a global module. Register it once in your root module:
39
+
40
+ ```typescript
41
+ import { Module } from '@nestjs/common';
42
+ import { MailModule } from '@breadstone/archipel-platform-mailing';
43
+
44
+ @Module({
45
+ imports: [MailModule],
46
+ })
47
+ export class AppModule {}
48
+ ```
49
+
50
+ The module reads all configuration from environment variables. No `register()` call is needed.
51
+
52
+ ---
53
+
54
+ ## Configuration
55
+
56
+ ### Core Variables
57
+
58
+ ```env
59
+ MAIL_DELIVERY_STRATEGY=resend
60
+ MAIL_TEMPLATE_STRATEGY=file
61
+ MAIL_TEMPLATE_ENGINE_FORMAT=html
62
+ MAIL_FROM_ADDRESS=noreply@yourapp.com
63
+ MAIL_FROM_NAME=YourApp
64
+ ```
65
+
66
+ ### Provider-Specific Variables
67
+
68
+ #### SMTP
69
+
70
+ ```env
71
+ MAIL_SMTP_HOST=smtp.example.com
72
+ MAIL_SMTP_PORT=587
73
+ MAIL_SMTP_USER=user@example.com
74
+ MAIL_SMTP_PASS=password
75
+ MAIL_SMTP_SECURE=true
76
+ ```
77
+
78
+ #### Resend
79
+
80
+ ```env
81
+ MAIL_RESEND_API_KEY=re_...
82
+ ```
83
+
84
+ #### Postmark
85
+
86
+ ```env
87
+ MAIL_POSTMARK_API_KEY=...
88
+ ```
89
+
90
+ #### SendGrid
91
+
92
+ ```env
93
+ MAIL_SENDGRID_API_KEY=SG...
94
+ ```
95
+
96
+ #### Mailgun
97
+
98
+ ```env
99
+ MAIL_MAILGUN_API_KEY=key-...
100
+ MAIL_MAILGUN_DOMAIN=mg.yourapp.com
101
+ ```
102
+
103
+ ### Template Strategies
104
+
105
+ Templates can be loaded from the filesystem or from blob storage:
106
+
107
+ | Strategy | Value for `MAIL_TEMPLATE_STRATEGY` | Description |
108
+ | -------- | ---------------------------------- | ------------------------------------------- |
109
+ | **File** | `file` | Load templates from a local directory |
110
+ | **Blob** | `blob` | Load templates from `platform-blob-storage` |
111
+
112
+ For file-based templates, place your `.html` or `.txt` files in the configured template directory.
113
+
114
+ ---
115
+
116
+ ## Sending Emails
117
+
118
+ Inject `MailService` to send emails with templates:
119
+
120
+ ```typescript
121
+ import { Injectable } from '@nestjs/common';
122
+ import { MailService } from '@breadstone/archipel-platform-mailing';
123
+
124
+ @Injectable()
125
+ export class NotificationService {
126
+ private readonly _mailService: MailService;
127
+
128
+ constructor(mailService: MailService) {
129
+ this._mailService = mailService;
130
+ }
131
+
132
+ public async sendWelcomeEmail(email: string, userName: string): Promise<void> {
133
+ await this._mailService.send({
134
+ to: email,
135
+ subject: 'Welcome to YourApp',
136
+ template: 'welcome',
137
+ context: {
138
+ userName,
139
+ dashboardUrl: 'https://yourapp.com/dashboard',
140
+ },
141
+ });
142
+ }
143
+ }
144
+ ```
145
+
146
+ The `template` field is the template name (without extension). The `context` object is passed to the template engine for variable substitution.
147
+
148
+ ---
149
+
150
+ ## Email Verification
151
+
152
+ `MailVerificationService` provides a complete email verification flow:
153
+
154
+ ```typescript
155
+ import { Injectable } from '@nestjs/common';
156
+ import { MailVerificationService } from '@breadstone/archipel-platform-mailing';
157
+ import { VerificationService } from '@breadstone/archipel-platform-authentication';
158
+
159
+ @Injectable()
160
+ export class RegistrationService {
161
+ private readonly _mailVerification: MailVerificationService;
162
+ private readonly _verification: VerificationService;
163
+
164
+ constructor(mailVerification: MailVerificationService, verification: VerificationService) {
165
+ this._mailVerification = mailVerification;
166
+ this._verification = verification;
167
+ }
168
+
169
+ public async sendVerificationEmail(userId: string, email: string): Promise<void> {
170
+ const token = await this._verification.exhibitToken({ userId, email });
171
+
172
+ await this._mailVerification.sendVerification(email, token);
173
+ }
174
+ }
175
+ ```
176
+
177
+ ---
178
+
179
+ ## Health Checks
180
+
181
+ `MailHealthIndicator` is registered automatically and verifies connectivity to the configured mail provider. It appears in your `/health` endpoint alongside other health indicators.
182
+
183
+ ---
184
+
185
+ ## Development Tips
186
+
187
+ - Use `MAIL_DELIVERY_STRATEGY=log` during local development to see email content in the console without sending real emails.
188
+ - Use the **blob** template strategy when templates are shared across multiple services or managed by a CMS.
189
+ - Template variables use the format defined by the template engine. Place templates in a well-organized directory structure (e.g., `templates/mail/welcome.html`).
190
+
191
+ ---
192
+
193
+ ## Next Steps
194
+
195
+ - See the [Authentication & Authorization](/guides/authentication-and-authorization) guide for integrating email verification into the login flow
196
+ - Browse the [platform-mailing API reference](/packages/platform-mailing/api/) for complete method signatures