@aifabrix/miso-client 4.10.0 → 4.13.0
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.
- package/CHANGELOG.md +40 -0
- package/README.md +164 -139
- package/dist/api/applications.api.d.ts +3 -3
- package/dist/api/applications.api.d.ts.map +1 -1
- package/dist/api/applications.api.js +21 -16
- package/dist/api/applications.api.js.map +1 -1
- package/dist/api/auth-cache.api.d.ts +3 -3
- package/dist/api/auth-cache.api.d.ts.map +1 -1
- package/dist/api/auth-cache.api.js +30 -30
- package/dist/api/auth-cache.api.js.map +1 -1
- package/dist/api/auth-login.api.d.ts +3 -3
- package/dist/api/auth-login.api.d.ts.map +1 -1
- package/dist/api/auth-login.api.js +25 -23
- package/dist/api/auth-login.api.js.map +1 -1
- package/dist/api/auth-token.api.d.ts +3 -3
- package/dist/api/auth-token.api.d.ts.map +1 -1
- package/dist/api/auth-token.api.js +53 -41
- package/dist/api/auth-token.api.js.map +1 -1
- package/dist/api/auth-user.api.d.ts +3 -3
- package/dist/api/auth-user.api.d.ts.map +1 -1
- package/dist/api/auth-user.api.js +18 -18
- package/dist/api/auth-user.api.js.map +1 -1
- package/dist/api/auth.api.d.ts +3 -3
- package/dist/api/auth.api.d.ts.map +1 -1
- package/dist/api/auth.api.js.map +1 -1
- package/dist/api/encryption.api.d.ts +2 -2
- package/dist/api/encryption.api.js +8 -8
- package/dist/api/index.d.ts +7 -7
- package/dist/api/logs-create.api.d.ts +3 -3
- package/dist/api/logs-create.api.d.ts.map +1 -1
- package/dist/api/logs-create.api.js +41 -19
- package/dist/api/logs-create.api.js.map +1 -1
- package/dist/api/logs-export.api.d.ts +3 -3
- package/dist/api/logs-export.api.d.ts.map +1 -1
- package/dist/api/logs-export.api.js +8 -6
- package/dist/api/logs-export.api.js.map +1 -1
- package/dist/api/logs-list.api.d.ts +3 -3
- package/dist/api/logs-list.api.d.ts.map +1 -1
- package/dist/api/logs-list.api.js +39 -33
- package/dist/api/logs-list.api.js.map +1 -1
- package/dist/api/logs-stats.api.d.ts +3 -3
- package/dist/api/logs-stats.api.d.ts.map +1 -1
- package/dist/api/logs-stats.api.js +24 -24
- package/dist/api/logs-stats.api.js.map +1 -1
- package/dist/api/logs.api.d.ts +3 -3
- package/dist/api/permissions.api.d.ts +3 -3
- package/dist/api/permissions.api.d.ts.map +1 -1
- package/dist/api/permissions.api.js +12 -12
- package/dist/api/permissions.api.js.map +1 -1
- package/dist/api/roles.api.d.ts +3 -3
- package/dist/api/roles.api.d.ts.map +1 -1
- package/dist/api/roles.api.js +12 -12
- package/dist/api/roles.api.js.map +1 -1
- package/dist/api/types/auth.types.d.ts +1 -1
- package/dist/api/types/encryption.types.d.ts +1 -1
- package/dist/api/types/logs.types.d.ts +8 -8
- package/dist/express/client-token-endpoint.d.ts +25 -6
- package/dist/express/client-token-endpoint.d.ts.map +1 -1
- package/dist/express/client-token-endpoint.js +42 -13
- package/dist/express/client-token-endpoint.js.map +1 -1
- package/dist/express/error-handler.d.ts.map +1 -1
- package/dist/express/error-handler.js +30 -8
- package/dist/express/error-handler.js.map +1 -1
- package/dist/express/error-types.d.ts.map +1 -1
- package/dist/express/error-types.js +26 -9
- package/dist/express/error-types.js.map +1 -1
- package/dist/express/index.d.ts +4 -4
- package/dist/express/index.d.ts.map +1 -1
- package/dist/express/index.js.map +1 -1
- package/dist/express/logger-context.middleware.d.ts.map +1 -1
- package/dist/express/logger-context.middleware.js +12 -5
- package/dist/express/logger-context.middleware.js.map +1 -1
- package/dist/express/response-helper.d.ts.map +1 -1
- package/dist/express/response-helper.js.map +1 -1
- package/dist/express/validation-helper.d.ts.map +1 -1
- package/dist/express/validation-helper.js +6 -2
- package/dist/express/validation-helper.js.map +1 -1
- package/dist/miso-client.d.ts.map +1 -1
- package/dist/miso-client.js +11 -4
- package/dist/miso-client.js.map +1 -1
- package/dist/sdk-exports.d.ts +7 -5
- package/dist/sdk-exports.d.ts.map +1 -1
- package/dist/sdk-exports.js +24 -1
- package/dist/sdk-exports.js.map +1 -1
- package/dist/services/application-context.service.d.ts.map +1 -1
- package/dist/services/application-context.service.js +3 -1
- package/dist/services/application-context.service.js.map +1 -1
- package/dist/services/auth-cache-helpers.d.ts.map +1 -1
- package/dist/services/auth-cache-helpers.js +9 -6
- package/dist/services/auth-cache-helpers.js.map +1 -1
- package/dist/services/auth-environment-token.d.ts.map +1 -1
- package/dist/services/auth-environment-token.js.map +1 -1
- package/dist/services/auth-error-handler.d.ts.map +1 -1
- package/dist/services/auth-error-handler.js.map +1 -1
- package/dist/services/auth.service.d.ts +0 -10
- package/dist/services/auth.service.d.ts.map +1 -1
- package/dist/services/auth.service.helpers.d.ts +22 -0
- package/dist/services/auth.service.helpers.d.ts.map +1 -0
- package/dist/services/auth.service.helpers.js +45 -0
- package/dist/services/auth.service.helpers.js.map +1 -0
- package/dist/services/auth.service.js +21 -57
- package/dist/services/auth.service.js.map +1 -1
- package/dist/services/browser-permission.service.d.ts.map +1 -1
- package/dist/services/browser-permission.service.js +10 -4
- package/dist/services/browser-permission.service.js.map +1 -1
- package/dist/services/browser-role.service.d.ts.map +1 -1
- package/dist/services/browser-role.service.js +6 -2
- package/dist/services/browser-role.service.js.map +1 -1
- package/dist/services/cache.service.d.ts.map +1 -1
- package/dist/services/cache.service.js +2 -1
- package/dist/services/cache.service.js.map +1 -1
- package/dist/services/encryption.service.d.ts +3 -3
- package/dist/services/encryption.service.d.ts.map +1 -1
- package/dist/services/encryption.service.js +12 -6
- package/dist/services/encryption.service.js.map +1 -1
- package/dist/services/logger/index.d.ts +1 -1
- package/dist/services/logger/index.d.ts.map +1 -1
- package/dist/services/logger/index.js.map +1 -1
- package/dist/services/logger/log-entry-builder.d.ts.map +1 -1
- package/dist/services/logger/log-entry-builder.js.map +1 -1
- package/dist/services/logger/logger-chain.d.ts.map +1 -1
- package/dist/services/logger/logger-chain.js.map +1 -1
- package/dist/services/logger/logger-context.d.ts.map +1 -1
- package/dist/services/logger/logger-context.js +5 -3
- package/dist/services/logger/logger-context.js.map +1 -1
- package/dist/services/logger/logger-http-utils.d.ts.map +1 -1
- package/dist/services/logger/logger-http-utils.js.map +1 -1
- package/dist/services/logger/logger.service.d.ts.map +1 -1
- package/dist/services/logger/logger.service.js +2 -1
- package/dist/services/logger/logger.service.js.map +1 -1
- package/dist/services/logger/trace-field-utils.d.ts.map +1 -1
- package/dist/services/logger/trace-field-utils.js.map +1 -1
- package/dist/services/logger/unified-logger.service.d.ts.map +1 -1
- package/dist/services/logger/unified-logger.service.js.map +1 -1
- package/dist/services/permission.service.d.ts.map +1 -1
- package/dist/services/permission.service.js +6 -2
- package/dist/services/permission.service.js.map +1 -1
- package/dist/services/role.service.d.ts.map +1 -1
- package/dist/services/role.service.js +6 -2
- package/dist/services/role.service.js.map +1 -1
- package/dist/services/token-validation.service.d.ts.map +1 -1
- package/dist/services/token-validation.service.js +4 -2
- package/dist/services/token-validation.service.js.map +1 -1
- package/dist/types/config.types.d.ts +11 -0
- package/dist/types/config.types.d.ts.map +1 -1
- package/dist/types/config.types.js.map +1 -1
- package/dist/types/data-client.types.d.ts +34 -6
- package/dist/types/data-client.types.d.ts.map +1 -1
- package/dist/types/data-client.types.js.map +1 -1
- package/dist/types/errors.types.d.ts.map +1 -1
- package/dist/types/filter-schema.types.d.ts.map +1 -1
- package/dist/types/filter-schema.types.js.map +1 -1
- package/dist/utils/audit-log-queue.d.ts.map +1 -1
- package/dist/utils/audit-log-queue.js +3 -1
- package/dist/utils/audit-log-queue.js.map +1 -1
- package/dist/utils/browser-jwt-decoder.d.ts.map +1 -1
- package/dist/utils/browser-jwt-decoder.js +1 -4
- package/dist/utils/browser-jwt-decoder.js.map +1 -1
- package/dist/utils/client-token-manager.d.ts.map +1 -1
- package/dist/utils/client-token-manager.js +11 -4
- package/dist/utils/client-token-manager.js.map +1 -1
- package/dist/utils/config-loader.d.ts.map +1 -1
- package/dist/utils/config-loader.js +16 -9
- package/dist/utils/config-loader.js.map +1 -1
- package/dist/utils/controller-url-resolver.d.ts.map +1 -1
- package/dist/utils/controller-url-resolver.js +6 -4
- package/dist/utils/controller-url-resolver.js.map +1 -1
- package/dist/utils/data-client-audit.d.ts +1 -1
- package/dist/utils/data-client-audit.d.ts.map +1 -1
- package/dist/utils/data-client-audit.js +26 -6
- package/dist/utils/data-client-audit.js.map +1 -1
- package/dist/utils/data-client-auth.d.ts +8 -1
- package/dist/utils/data-client-auth.d.ts.map +1 -1
- package/dist/utils/data-client-auth.js +68 -5
- package/dist/utils/data-client-auth.js.map +1 -1
- package/dist/utils/data-client-auto-init.d.ts.map +1 -1
- package/dist/utils/data-client-auto-init.js +14 -6
- package/dist/utils/data-client-auto-init.js.map +1 -1
- package/dist/utils/data-client-cache.js +2 -2
- package/dist/utils/data-client-cache.js.map +1 -1
- package/dist/utils/data-client-core.d.ts +82 -0
- package/dist/utils/data-client-core.d.ts.map +1 -0
- package/dist/utils/data-client-core.js +304 -0
- package/dist/utils/data-client-core.js.map +1 -0
- package/dist/utils/data-client-init.d.ts +1 -1
- package/dist/utils/data-client-init.d.ts.map +1 -1
- package/dist/utils/data-client-init.js +7 -2
- package/dist/utils/data-client-init.js.map +1 -1
- package/dist/utils/data-client-oauth.d.ts.map +1 -1
- package/dist/utils/data-client-oauth.js +5 -2
- package/dist/utils/data-client-oauth.js.map +1 -1
- package/dist/utils/data-client-permissions.d.ts +1 -1
- package/dist/utils/data-client-permissions.d.ts.map +1 -1
- package/dist/utils/data-client-redirect.d.ts +1 -1
- package/dist/utils/data-client-redirect.d.ts.map +1 -1
- package/dist/utils/data-client-redirect.js +11 -10
- package/dist/utils/data-client-redirect.js.map +1 -1
- package/dist/utils/data-client-request.d.ts +4 -33
- package/dist/utils/data-client-request.d.ts.map +1 -1
- package/dist/utils/data-client-request.js +80 -43
- package/dist/utils/data-client-request.js.map +1 -1
- package/dist/utils/data-client-request.types.d.ts +68 -0
- package/dist/utils/data-client-request.types.d.ts.map +1 -0
- package/dist/utils/data-client-request.types.js +3 -0
- package/dist/utils/data-client-request.types.js.map +1 -0
- package/dist/utils/data-client-response.d.ts +1 -1
- package/dist/utils/data-client-response.d.ts.map +1 -1
- package/dist/utils/data-client-response.js +23 -9
- package/dist/utils/data-client-response.js.map +1 -1
- package/dist/utils/data-client-roles.d.ts +1 -1
- package/dist/utils/data-client-roles.d.ts.map +1 -1
- package/dist/utils/data-client-utils.d.ts.map +1 -1
- package/dist/utils/data-client-utils.js +2 -1
- package/dist/utils/data-client-utils.js.map +1 -1
- package/dist/utils/data-client.d.ts +3 -40
- package/dist/utils/data-client.d.ts.map +1 -1
- package/dist/utils/data-client.js +21 -242
- package/dist/utils/data-client.js.map +1 -1
- package/dist/utils/data-masker.d.ts.map +1 -1
- package/dist/utils/data-masker.js.map +1 -1
- package/dist/utils/encryption-error.d.ts +2 -2
- package/dist/utils/encryption-error.js +1 -1
- package/dist/utils/environment-token.d.ts +1 -1
- package/dist/utils/environment-token.d.ts.map +1 -1
- package/dist/utils/environment-token.js +6 -2
- package/dist/utils/environment-token.js.map +1 -1
- package/dist/utils/error-extractor.d.ts.map +1 -1
- package/dist/utils/error-extractor.js +4 -2
- package/dist/utils/error-extractor.js.map +1 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +29 -7
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/filter-colon.utils.d.ts.map +1 -1
- package/dist/utils/filter-colon.utils.js.map +1 -1
- package/dist/utils/filter-schema-loader.d.ts.map +1 -1
- package/dist/utils/filter-schema-loader.js +3 -1
- package/dist/utils/filter-schema-loader.js.map +1 -1
- package/dist/utils/filter-schema.utils.d.ts.map +1 -1
- package/dist/utils/filter-schema.utils.js.map +1 -1
- package/dist/utils/filter.utils.d.ts.map +1 -1
- package/dist/utils/filter.utils.js +11 -4
- package/dist/utils/filter.utils.js.map +1 -1
- package/dist/utils/http-client-audit.d.ts.map +1 -1
- package/dist/utils/http-client-audit.js +51 -14
- package/dist/utils/http-client-audit.js.map +1 -1
- package/dist/utils/http-client-masking.d.ts.map +1 -1
- package/dist/utils/http-client-masking.js +6 -2
- package/dist/utils/http-client-masking.js.map +1 -1
- package/dist/utils/http-client-metadata.d.ts.map +1 -1
- package/dist/utils/http-client-metadata.js.map +1 -1
- package/dist/utils/http-client.d.ts +4 -0
- package/dist/utils/http-client.d.ts.map +1 -1
- package/dist/utils/http-client.js +135 -2
- package/dist/utils/http-client.js.map +1 -1
- package/dist/utils/http-error-handler.d.ts.map +1 -1
- package/dist/utils/http-error-handler.js +6 -3
- package/dist/utils/http-error-handler.js.map +1 -1
- package/dist/utils/http-response-validator.d.ts.map +1 -1
- package/dist/utils/http-response-validator.js +30 -7
- package/dist/utils/http-response-validator.js.map +1 -1
- package/dist/utils/internal-http-client.d.ts.map +1 -1
- package/dist/utils/internal-http-client.js +21 -7
- package/dist/utils/internal-http-client.js.map +1 -1
- package/dist/utils/logging-helpers.d.ts.map +1 -1
- package/dist/utils/logging-helpers.js +2 -1
- package/dist/utils/logging-helpers.js.map +1 -1
- package/dist/utils/sensitive-fields.config.json +1 -7
- package/dist/utils/sensitive-fields.loader.d.ts.map +1 -1
- package/dist/utils/sensitive-fields.loader.js +3 -1
- package/dist/utils/sensitive-fields.loader.js.map +1 -1
- package/dist/utils/token-utils.d.ts.map +1 -1
- package/dist/utils/token-utils.js +3 -3
- package/dist/utils/token-utils.js.map +1 -1
- package/dist/utils/url-join.d.ts +99 -0
- package/dist/utils/url-join.d.ts.map +1 -0
- package/dist/utils/url-join.js +200 -0
- package/dist/utils/url-join.js.map +1 -0
- package/dist/utils/user-token-refresh.d.ts +40 -0
- package/dist/utils/user-token-refresh.d.ts.map +1 -0
- package/dist/utils/user-token-refresh.js +258 -0
- package/dist/utils/user-token-refresh.js.map +1 -0
- package/package.json +18 -1
package/README.md
CHANGED
|
@@ -138,7 +138,7 @@ REDIS_HOST=localhost
|
|
|
138
138
|
### Step 3: Use It
|
|
139
139
|
|
|
140
140
|
```typescript
|
|
141
|
-
import { MisoClient, loadConfig } from
|
|
141
|
+
import { MisoClient, loadConfig } from "@aifabrix/miso-client";
|
|
142
142
|
|
|
143
143
|
const client = new MisoClient(loadConfig());
|
|
144
144
|
await client.initialize();
|
|
@@ -157,7 +157,7 @@ For React, Vue, Angular, or other front-end applications, use **DataClient** - a
|
|
|
157
157
|
**⚠️ Security Warning:** Never expose `clientSecret` in browser/client-side code. Use the Server-Provided Client Token Pattern instead.
|
|
158
158
|
|
|
159
159
|
```typescript
|
|
160
|
-
import { DataClient } from
|
|
160
|
+
import { DataClient } from "@aifabrix/miso-client";
|
|
161
161
|
|
|
162
162
|
// Server provides client token (from initial page load or API endpoint)
|
|
163
163
|
const initialClientToken = window.INITIAL_CLIENT_TOKEN; // From server
|
|
@@ -165,20 +165,20 @@ const tokenExpiresAt = window.INITIAL_CLIENT_TOKEN_EXPIRES_AT;
|
|
|
165
165
|
|
|
166
166
|
// Browser-safe configuration WITHOUT clientSecret
|
|
167
167
|
const dataClient = new DataClient({
|
|
168
|
-
baseUrl:
|
|
168
|
+
baseUrl: "https://api.example.com",
|
|
169
169
|
misoConfig: {
|
|
170
|
-
controllerUrl:
|
|
171
|
-
clientId:
|
|
170
|
+
controllerUrl: "https://controller.aifabrix.ai",
|
|
171
|
+
clientId: "ctrl-dev-my-app",
|
|
172
172
|
// ❌ DO NOT include clientSecret in browser code
|
|
173
|
-
|
|
173
|
+
|
|
174
174
|
// ✅ Use server-provided token
|
|
175
175
|
clientToken: initialClientToken,
|
|
176
176
|
clientTokenExpiresAt: tokenExpiresAt,
|
|
177
|
-
|
|
177
|
+
|
|
178
178
|
// ✅ Refresh callback calls your server endpoint
|
|
179
179
|
onClientTokenRefresh: async () => {
|
|
180
|
-
const response = await fetch(
|
|
181
|
-
credentials:
|
|
180
|
+
const response = await fetch("/api/client-token", {
|
|
181
|
+
credentials: "include", // Include cookies for auth
|
|
182
182
|
});
|
|
183
183
|
return await response.json(); // { token: string, expiresIn: number }
|
|
184
184
|
},
|
|
@@ -186,8 +186,8 @@ const dataClient = new DataClient({
|
|
|
186
186
|
});
|
|
187
187
|
|
|
188
188
|
// Make authenticated requests with automatic audit logging
|
|
189
|
-
const users = await dataClient.get(
|
|
190
|
-
const newUser = await dataClient.post(
|
|
189
|
+
const users = await dataClient.get("/api/users");
|
|
190
|
+
const newUser = await dataClient.post("/api/users", { name: "John" });
|
|
191
191
|
|
|
192
192
|
// OAuth callback is automatically handled on initialization
|
|
193
193
|
// Token is extracted from URL hash fragment (#token=...) and stored securely
|
|
@@ -195,15 +195,26 @@ const newUser = await dataClient.post('/api/users', { name: 'John' });
|
|
|
195
195
|
|
|
196
196
|
// Token refresh callback (automatic refresh on 401 errors)
|
|
197
197
|
const dataClientWithRefresh = new DataClient({
|
|
198
|
-
baseUrl:
|
|
199
|
-
misoConfig: {
|
|
198
|
+
baseUrl: "https://api.example.com",
|
|
199
|
+
misoConfig: {
|
|
200
|
+
/* ... */
|
|
201
|
+
},
|
|
200
202
|
onTokenRefresh: async () => {
|
|
201
203
|
// Call your backend endpoint that handles refresh token securely
|
|
202
|
-
const response = await fetch(
|
|
203
|
-
credentials:
|
|
204
|
+
const response = await fetch("/api/refresh-token", {
|
|
205
|
+
credentials: "include", // Include cookies for auth
|
|
204
206
|
});
|
|
205
207
|
return await response.json(); // { token: string, expiresIn: number }
|
|
206
208
|
},
|
|
209
|
+
|
|
210
|
+
// Optional cookie-first restore callback (preferred for enterprise SSO)
|
|
211
|
+
onSessionRestore: async () => {
|
|
212
|
+
const response = await fetch("/api/session/restore", {
|
|
213
|
+
credentials: "include",
|
|
214
|
+
});
|
|
215
|
+
if (!response.ok) return null;
|
|
216
|
+
return await response.json(); // { token: string, expiresAt?: string }
|
|
217
|
+
},
|
|
207
218
|
});
|
|
208
219
|
```
|
|
209
220
|
|
|
@@ -243,7 +254,7 @@ aifabrix run miso-controller
|
|
|
243
254
|
**What happens:** Your app validates user tokens from Keycloak.
|
|
244
255
|
|
|
245
256
|
```typescript
|
|
246
|
-
import { MisoClient, loadConfig } from
|
|
257
|
+
import { MisoClient, loadConfig } from "@aifabrix/miso-client";
|
|
247
258
|
|
|
248
259
|
// Create client (loads from .env automatically)
|
|
249
260
|
const client = new MisoClient(loadConfig());
|
|
@@ -256,7 +267,7 @@ if (token) {
|
|
|
256
267
|
const isValid = await client.validateToken(token);
|
|
257
268
|
if (isValid) {
|
|
258
269
|
const user = await client.getUser(token);
|
|
259
|
-
console.log(
|
|
270
|
+
console.log("User:", user);
|
|
260
271
|
}
|
|
261
272
|
}
|
|
262
273
|
```
|
|
@@ -284,7 +295,7 @@ const result = await client.exchangeUserToken(entraOrExternalToken);
|
|
|
284
295
|
**What happens:** Check user roles to control access. Roles are cached in Redis for performance. Token validation is also cached (15-minute TTL) to reduce API calls.
|
|
285
296
|
|
|
286
297
|
```typescript
|
|
287
|
-
import { MisoClient, loadConfig } from
|
|
298
|
+
import { MisoClient, loadConfig } from "@aifabrix/miso-client";
|
|
288
299
|
|
|
289
300
|
// Build on Step 3 - add Redis in .env file
|
|
290
301
|
const client = new MisoClient(loadConfig());
|
|
@@ -293,7 +304,7 @@ await client.initialize();
|
|
|
293
304
|
const token = client.getToken(req);
|
|
294
305
|
|
|
295
306
|
// Check if user has role
|
|
296
|
-
const isAdmin = await client.hasRole(token,
|
|
307
|
+
const isAdmin = await client.hasRole(token, "admin");
|
|
297
308
|
const roles = await client.getRoles(token);
|
|
298
309
|
|
|
299
310
|
// Gate features by role
|
|
@@ -316,7 +327,7 @@ if (isAdmin) {
|
|
|
316
327
|
**Basic Logging:**
|
|
317
328
|
|
|
318
329
|
```typescript
|
|
319
|
-
import { MisoClient, loadConfig } from
|
|
330
|
+
import { MisoClient, loadConfig } from "@aifabrix/miso-client";
|
|
320
331
|
|
|
321
332
|
// Client token is automatically managed - no API key needed
|
|
322
333
|
const client = new MisoClient(loadConfig());
|
|
@@ -326,21 +337,19 @@ const token = client.getToken(req);
|
|
|
326
337
|
const user = await client.getUser(token);
|
|
327
338
|
|
|
328
339
|
// Log messages
|
|
329
|
-
await client.log.info(
|
|
330
|
-
await client.log.error(
|
|
331
|
-
await client.log.warn(
|
|
340
|
+
await client.log.info("User accessed dashboard", { userId: user?.id });
|
|
341
|
+
await client.log.error("Operation failed", { error: err.message });
|
|
342
|
+
await client.log.warn("Unusual activity", { details: "..." });
|
|
332
343
|
```
|
|
333
344
|
|
|
334
345
|
**Fluent API with Request Context (Express):**
|
|
335
346
|
|
|
336
347
|
```typescript
|
|
337
|
-
import { Request } from
|
|
348
|
+
import { Request } from "express";
|
|
338
349
|
|
|
339
350
|
// Auto-extract context from Express Request
|
|
340
|
-
app.get(
|
|
341
|
-
await client.log
|
|
342
|
-
.withRequest(req)
|
|
343
|
-
.info('Users list accessed');
|
|
351
|
+
app.get("/api/users", async (req: Request, res) => {
|
|
352
|
+
await client.log.withRequest(req).info("Users list accessed");
|
|
344
353
|
// Automatically includes: IP, method, path, userAgent, correlationId, userId
|
|
345
354
|
});
|
|
346
355
|
```
|
|
@@ -348,21 +357,21 @@ app.get('/api/users', async (req: Request, res) => {
|
|
|
348
357
|
**Indexed Context for Fast Queries:**
|
|
349
358
|
|
|
350
359
|
```typescript
|
|
351
|
-
import { extractLoggingContext } from
|
|
360
|
+
import { extractLoggingContext } from "@aifabrix/miso-client";
|
|
352
361
|
|
|
353
362
|
const logContext = extractLoggingContext({
|
|
354
363
|
source: {
|
|
355
|
-
key:
|
|
356
|
-
displayName:
|
|
357
|
-
externalSystem: { key:
|
|
364
|
+
key: "datasource-1",
|
|
365
|
+
displayName: "PostgreSQL DB",
|
|
366
|
+
externalSystem: { key: "system-1", displayName: "External API" },
|
|
358
367
|
},
|
|
359
|
-
record: { key:
|
|
368
|
+
record: { key: "record-123", displayName: "User Profile" },
|
|
360
369
|
});
|
|
361
370
|
|
|
362
371
|
await client.log
|
|
363
372
|
.withIndexedContext(logContext)
|
|
364
373
|
.withContext({ correlationId, userId })
|
|
365
|
-
.error(
|
|
374
|
+
.error("Sync failed");
|
|
366
375
|
```
|
|
367
376
|
|
|
368
377
|
**What happens to logs?** They're sent to the Miso Controller for centralized monitoring and analysis. Client token is automatically included. Indexed context fields enable fast database queries for observability and compliance.
|
|
@@ -372,11 +381,11 @@ await client.log
|
|
|
372
381
|
```typescript
|
|
373
382
|
const client = new MisoClient({
|
|
374
383
|
...loadConfig(),
|
|
375
|
-
emitEvents: true // Enable event emission mode
|
|
384
|
+
emitEvents: true, // Enable event emission mode
|
|
376
385
|
});
|
|
377
386
|
|
|
378
387
|
// Listen to log events
|
|
379
|
-
client.log.on(
|
|
388
|
+
client.log.on("log", (logEntry: LogEntry) => {
|
|
380
389
|
// Save directly to DB without HTTP
|
|
381
390
|
db.saveLog(logEntry);
|
|
382
391
|
});
|
|
@@ -393,7 +402,7 @@ client.log.on('log', (logEntry: LogEntry) => {
|
|
|
393
402
|
**What happens:** Create audit trails for compliance and security monitoring.
|
|
394
403
|
|
|
395
404
|
```typescript
|
|
396
|
-
import { MisoClient, loadConfig } from
|
|
405
|
+
import { MisoClient, loadConfig } from "@aifabrix/miso-client";
|
|
397
406
|
|
|
398
407
|
// Complete configuration (all in .env)
|
|
399
408
|
const client = new MisoClient(loadConfig());
|
|
@@ -401,28 +410,28 @@ await client.initialize();
|
|
|
401
410
|
|
|
402
411
|
const token = client.getToken(req);
|
|
403
412
|
const isValid = await client.validateToken(token);
|
|
404
|
-
const canEdit = await client.hasPermission(token,
|
|
413
|
+
const canEdit = await client.hasPermission(token, "edit:content");
|
|
405
414
|
const user = await client.getUser(token);
|
|
406
415
|
|
|
407
416
|
// Audit: User actions
|
|
408
|
-
await client.log.audit(
|
|
417
|
+
await client.log.audit("user.login", "authentication", {
|
|
409
418
|
userId: user?.id,
|
|
410
419
|
ip: req.ip,
|
|
411
|
-
userAgent: req.headers[
|
|
420
|
+
userAgent: req.headers["user-agent"],
|
|
412
421
|
});
|
|
413
422
|
|
|
414
423
|
// Audit: Content changes
|
|
415
|
-
await client.log.audit(
|
|
424
|
+
await client.log.audit("post.created", "content", {
|
|
416
425
|
userId: user?.id,
|
|
417
|
-
postId:
|
|
426
|
+
postId: "post-123",
|
|
418
427
|
postTitle: req.body.title,
|
|
419
428
|
});
|
|
420
429
|
|
|
421
430
|
// Audit: Permission checks
|
|
422
|
-
await client.log.audit(
|
|
431
|
+
await client.log.audit("access.denied", "authorization", {
|
|
423
432
|
userId: user?.id,
|
|
424
|
-
requiredPermission:
|
|
425
|
-
resource:
|
|
433
|
+
requiredPermission: "edit:content",
|
|
434
|
+
resource: "posts",
|
|
426
435
|
});
|
|
427
436
|
```
|
|
428
437
|
|
|
@@ -438,7 +447,7 @@ await client.log.audit('access.denied', 'authorization', {
|
|
|
438
447
|
**What happens:** All HTTP requests are automatically audited with sensitive data masking for ISO 27001 compliance.
|
|
439
448
|
|
|
440
449
|
```typescript
|
|
441
|
-
import { MisoClient, loadConfig } from
|
|
450
|
+
import { MisoClient, loadConfig } from "@aifabrix/miso-client";
|
|
442
451
|
|
|
443
452
|
const client = new MisoClient(loadConfig());
|
|
444
453
|
await client.initialize();
|
|
@@ -477,10 +486,10 @@ The SDK automatically optimizes audit logging performance:
|
|
|
477
486
|
const client = new MisoClient({
|
|
478
487
|
...loadConfig(),
|
|
479
488
|
audit: {
|
|
480
|
-
level:
|
|
489
|
+
level: "standard", // Light masking, good performance
|
|
481
490
|
batchSize: 20, // Batch 20 logs per request
|
|
482
|
-
maxResponseSize: 10000 // Truncate large responses
|
|
483
|
-
}
|
|
491
|
+
maxResponseSize: 10000, // Truncate large responses
|
|
492
|
+
},
|
|
484
493
|
});
|
|
485
494
|
```
|
|
486
495
|
|
|
@@ -511,23 +520,23 @@ const client = new MisoClient({
|
|
|
511
520
|
**What happens:** Use encryption for sensitive data and generic caching for improved performance.
|
|
512
521
|
|
|
513
522
|
```typescript
|
|
514
|
-
import { MisoClient, loadConfig } from
|
|
523
|
+
import { MisoClient, loadConfig } from "@aifabrix/miso-client";
|
|
515
524
|
|
|
516
525
|
const client = new MisoClient(loadConfig());
|
|
517
526
|
await client.initialize();
|
|
518
527
|
|
|
519
528
|
// Encryption (requires ENCRYPTION_KEY in .env or config.encryptionKey)
|
|
520
529
|
if (client.encryption) {
|
|
521
|
-
const encrypted = client.encryption.encrypt(
|
|
530
|
+
const encrypted = client.encryption.encrypt("sensitive-data");
|
|
522
531
|
const decrypted = client.encryption.decrypt(encrypted);
|
|
523
|
-
console.log(
|
|
532
|
+
console.log("Decrypted:", decrypted);
|
|
524
533
|
}
|
|
525
534
|
|
|
526
535
|
// Generic caching (automatically uses Redis if available, falls back to memory)
|
|
527
|
-
await client.cache.set(
|
|
528
|
-
const user = await client.cache.get<{ name: string; age: number }>(
|
|
536
|
+
await client.cache.set("user:123", { name: "John", age: 30 }, 600); // 10 minutes TTL
|
|
537
|
+
const user = await client.cache.get<{ name: string; age: number }>("user:123");
|
|
529
538
|
if (user) {
|
|
530
|
-
console.log(
|
|
539
|
+
console.log("Cached user:", user);
|
|
531
540
|
}
|
|
532
541
|
```
|
|
533
542
|
|
|
@@ -548,47 +557,50 @@ ENCRYPTION_KEY=your-32-byte-encryption-key
|
|
|
548
557
|
**What happens:** Use reusable utilities for pagination, filtering, and sorting following enterprise application best practices and industry standards (ISO 27001 compliant).
|
|
549
558
|
|
|
550
559
|
```typescript
|
|
551
|
-
import {
|
|
552
|
-
FilterBuilder,
|
|
553
|
-
parsePaginationParams,
|
|
560
|
+
import {
|
|
561
|
+
FilterBuilder,
|
|
562
|
+
parsePaginationParams,
|
|
554
563
|
parseSortParams,
|
|
555
564
|
buildQueryString,
|
|
556
|
-
createPaginatedListResponse
|
|
557
|
-
} from
|
|
565
|
+
createPaginatedListResponse,
|
|
566
|
+
} from "@aifabrix/miso-client";
|
|
558
567
|
|
|
559
568
|
const client = new MisoClient(loadConfig());
|
|
560
569
|
await client.initialize();
|
|
561
570
|
|
|
562
571
|
// Dynamic filter building (FilterBuilder)
|
|
563
572
|
const filterBuilder = new FilterBuilder()
|
|
564
|
-
.add(
|
|
565
|
-
.add(
|
|
566
|
-
.add(
|
|
573
|
+
.add("status", "eq", "active")
|
|
574
|
+
.add("region", "in", ["eu", "us"])
|
|
575
|
+
.add("created_at", "gte", "2024-01-01");
|
|
567
576
|
|
|
568
577
|
const queryString = filterBuilder.toQueryString();
|
|
569
578
|
// Returns: "filter=status:eq:active&filter=region:in:eu,us&filter=created_at:gte:2024-01-01"
|
|
570
579
|
|
|
571
580
|
// Parse pagination from query string
|
|
572
|
-
const { currentPage, pageSize } = parsePaginationParams({
|
|
581
|
+
const { currentPage, pageSize } = parsePaginationParams({
|
|
582
|
+
page: "1",
|
|
583
|
+
page_size: "25",
|
|
584
|
+
});
|
|
573
585
|
|
|
574
586
|
// Parse sort from query string
|
|
575
|
-
const sortOptions = parseSortParams({ sort:
|
|
587
|
+
const sortOptions = parseSortParams({ sort: "-updated_at" });
|
|
576
588
|
|
|
577
589
|
// Build complete query
|
|
578
590
|
const completeQuery = buildQueryString({
|
|
579
591
|
filters: filterBuilder.build(),
|
|
580
|
-
sort: [
|
|
592
|
+
sort: ["-updated_at"],
|
|
581
593
|
page: currentPage,
|
|
582
|
-
pageSize: pageSize
|
|
594
|
+
pageSize: pageSize,
|
|
583
595
|
});
|
|
584
596
|
|
|
585
597
|
// Create paginated response
|
|
586
598
|
const response = createPaginatedListResponse(
|
|
587
599
|
items,
|
|
588
600
|
120, // totalItems
|
|
589
|
-
1,
|
|
590
|
-
25,
|
|
591
|
-
|
|
601
|
+
1, // currentPage
|
|
602
|
+
25, // pageSize
|
|
603
|
+
"application", // type
|
|
592
604
|
);
|
|
593
605
|
```
|
|
594
606
|
|
|
@@ -615,14 +627,14 @@ pnpm add @aifabrix/miso-client express
|
|
|
615
627
|
#### Quick Start
|
|
616
628
|
|
|
617
629
|
```typescript
|
|
618
|
-
import express from
|
|
619
|
-
import {
|
|
630
|
+
import express from "express";
|
|
631
|
+
import {
|
|
620
632
|
injectResponseHelpers,
|
|
621
633
|
asyncHandler,
|
|
622
634
|
ValidationHelper,
|
|
623
635
|
setErrorLogger,
|
|
624
|
-
EncryptionUtil
|
|
625
|
-
} from
|
|
636
|
+
EncryptionUtil,
|
|
637
|
+
} from "@aifabrix/miso-client";
|
|
626
638
|
|
|
627
639
|
const app = express();
|
|
628
640
|
|
|
@@ -633,18 +645,21 @@ app.use(injectResponseHelpers);
|
|
|
633
645
|
setErrorLogger({
|
|
634
646
|
async logError(message, options) {
|
|
635
647
|
console.error(message, options);
|
|
636
|
-
}
|
|
648
|
+
},
|
|
637
649
|
});
|
|
638
650
|
|
|
639
651
|
// Use asyncHandler for automatic error handling
|
|
640
|
-
app.get(
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
652
|
+
app.get(
|
|
653
|
+
"/users/:id",
|
|
654
|
+
asyncHandler(async (req, res) => {
|
|
655
|
+
const user = await ValidationHelper.findOrFail(
|
|
656
|
+
() => db.user.findById(req.params.id),
|
|
657
|
+
"User",
|
|
658
|
+
req.params.id,
|
|
659
|
+
);
|
|
660
|
+
res.success(user, "User retrieved");
|
|
661
|
+
}),
|
|
662
|
+
);
|
|
648
663
|
```
|
|
649
664
|
|
|
650
665
|
#### Response Helpers
|
|
@@ -652,27 +667,27 @@ app.get('/users/:id', asyncHandler(async (req, res) => {
|
|
|
652
667
|
Standardized API response formatting:
|
|
653
668
|
|
|
654
669
|
```typescript
|
|
655
|
-
import { ResponseHelper } from
|
|
670
|
+
import { ResponseHelper } from "@aifabrix/miso-client";
|
|
656
671
|
|
|
657
672
|
// Success response (200)
|
|
658
|
-
return ResponseHelper.success(res, data,
|
|
673
|
+
return ResponseHelper.success(res, data, "Success message");
|
|
659
674
|
|
|
660
675
|
// Created response (201)
|
|
661
|
-
return ResponseHelper.created(res, newResource,
|
|
676
|
+
return ResponseHelper.created(res, newResource, "Resource created");
|
|
662
677
|
|
|
663
678
|
// Paginated response
|
|
664
679
|
return ResponseHelper.paginated(res, items, {
|
|
665
680
|
currentPage: 1,
|
|
666
681
|
pageSize: 20,
|
|
667
682
|
totalItems: 100,
|
|
668
|
-
type:
|
|
683
|
+
type: "user",
|
|
669
684
|
});
|
|
670
685
|
|
|
671
686
|
// No content (204)
|
|
672
687
|
return ResponseHelper.noContent(res);
|
|
673
688
|
|
|
674
689
|
// Accepted (202)
|
|
675
|
-
return ResponseHelper.accepted(res, { jobId:
|
|
690
|
+
return ResponseHelper.accepted(res, { jobId: "123" }, "Job queued");
|
|
676
691
|
|
|
677
692
|
// Or use injected methods on res object
|
|
678
693
|
res.success(user);
|
|
@@ -687,19 +702,25 @@ res.accepted(data);
|
|
|
687
702
|
Eliminates try-catch blocks in route handlers:
|
|
688
703
|
|
|
689
704
|
```typescript
|
|
690
|
-
import { asyncHandler } from
|
|
705
|
+
import { asyncHandler } from "@aifabrix/miso-client";
|
|
691
706
|
|
|
692
707
|
// Automatic error handling
|
|
693
|
-
router.post(
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
708
|
+
router.post(
|
|
709
|
+
"/users",
|
|
710
|
+
asyncHandler(async (req, res) => {
|
|
711
|
+
const user = await userService.create(req.body);
|
|
712
|
+
res.created(user, "User created");
|
|
713
|
+
}),
|
|
714
|
+
);
|
|
697
715
|
|
|
698
716
|
// Named variant for better error messages
|
|
699
|
-
router.get(
|
|
700
|
-
|
|
701
|
-
res
|
|
702
|
-
|
|
717
|
+
router.get(
|
|
718
|
+
"/users/:id",
|
|
719
|
+
asyncHandlerNamed("getUser", async (req, res) => {
|
|
720
|
+
const user = await userService.findById(req.params.id);
|
|
721
|
+
res.success(user);
|
|
722
|
+
}),
|
|
723
|
+
);
|
|
703
724
|
```
|
|
704
725
|
|
|
705
726
|
#### Validation Helper
|
|
@@ -707,30 +728,30 @@ router.get('/users/:id', asyncHandlerNamed('getUser', async (req, res) => {
|
|
|
707
728
|
Common validation patterns:
|
|
708
729
|
|
|
709
730
|
```typescript
|
|
710
|
-
import { ValidationHelper } from
|
|
731
|
+
import { ValidationHelper } from "@aifabrix/miso-client";
|
|
711
732
|
|
|
712
733
|
// Find or throw 404
|
|
713
734
|
const user = await ValidationHelper.findOrFail(
|
|
714
735
|
() => prisma.user.findUnique({ where: { id } }),
|
|
715
|
-
|
|
716
|
-
id
|
|
736
|
+
"User",
|
|
737
|
+
id,
|
|
717
738
|
);
|
|
718
739
|
|
|
719
740
|
// Ensure doesn't exist or throw 409
|
|
720
741
|
await ValidationHelper.ensureNotExists(
|
|
721
742
|
() => prisma.user.findUnique({ where: { email } }),
|
|
722
|
-
|
|
723
|
-
email
|
|
743
|
+
"User",
|
|
744
|
+
email,
|
|
724
745
|
);
|
|
725
746
|
|
|
726
747
|
// Check ownership or admin role
|
|
727
748
|
ValidationHelper.ensureOwnershipOrAdmin(req, resourceUserId);
|
|
728
749
|
|
|
729
750
|
// Validate required fields
|
|
730
|
-
ValidationHelper.validateRequiredFields(data, [
|
|
751
|
+
ValidationHelper.validateRequiredFields(data, ["name", "email"], "User");
|
|
731
752
|
|
|
732
753
|
// Validate string length
|
|
733
|
-
ValidationHelper.validateStringLength(password,
|
|
754
|
+
ValidationHelper.validateStringLength(password, "password", 8, 128);
|
|
734
755
|
```
|
|
735
756
|
|
|
736
757
|
#### Error Handling
|
|
@@ -738,13 +759,13 @@ ValidationHelper.validateStringLength(password, 'password', 8, 128);
|
|
|
738
759
|
RFC 7807 compliant error responses with optional custom logger:
|
|
739
760
|
|
|
740
761
|
```typescript
|
|
741
|
-
import { setErrorLogger } from
|
|
762
|
+
import { setErrorLogger } from "@aifabrix/miso-client";
|
|
742
763
|
|
|
743
764
|
// Configure during app initialization
|
|
744
765
|
setErrorLogger({
|
|
745
766
|
async logError(message, options) {
|
|
746
767
|
await yourLogger.error(message, options);
|
|
747
|
-
}
|
|
768
|
+
},
|
|
748
769
|
});
|
|
749
770
|
|
|
750
771
|
// Errors are automatically handled by asyncHandler
|
|
@@ -756,20 +777,20 @@ setErrorLogger({
|
|
|
756
777
|
AES-256-GCM encryption for sensitive data:
|
|
757
778
|
|
|
758
779
|
```typescript
|
|
759
|
-
import { EncryptionUtil } from
|
|
780
|
+
import { EncryptionUtil } from "@aifabrix/miso-client";
|
|
760
781
|
|
|
761
782
|
// Initialize once at startup (uses ENCRYPTION_KEY env var)
|
|
762
783
|
EncryptionUtil.initialize();
|
|
763
784
|
|
|
764
785
|
// Encrypt sensitive data
|
|
765
|
-
const encrypted = EncryptionUtil.encrypt(
|
|
786
|
+
const encrypted = EncryptionUtil.encrypt("sensitive-data");
|
|
766
787
|
|
|
767
788
|
// Decrypt
|
|
768
789
|
const decrypted = EncryptionUtil.decrypt(encrypted);
|
|
769
790
|
|
|
770
791
|
// Generate new key (for setup)
|
|
771
792
|
const key = EncryptionUtil.generateKey();
|
|
772
|
-
console.log(
|
|
793
|
+
console.log("ENCRYPTION_KEY=" + key);
|
|
773
794
|
```
|
|
774
795
|
|
|
775
796
|
#### Sort Utilities
|
|
@@ -777,21 +798,21 @@ console.log('ENCRYPTION_KEY=' + key);
|
|
|
777
798
|
Parse and apply sorting for API queries:
|
|
778
799
|
|
|
779
800
|
```typescript
|
|
780
|
-
import { parseSortParams, applySorting } from
|
|
801
|
+
import { parseSortParams, applySorting } from "@aifabrix/miso-client";
|
|
781
802
|
|
|
782
803
|
// Parse sort query parameters
|
|
783
|
-
const sortOptions = parseSortParams({ sort: [
|
|
804
|
+
const sortOptions = parseSortParams({ sort: ["-createdAt", "name"] });
|
|
784
805
|
// Returns: [{ field: 'createdAt', order: 'desc' }, { field: 'name', order: 'asc' }]
|
|
785
806
|
|
|
786
807
|
// Apply sorting to in-memory data (client-side)
|
|
787
808
|
const sortedData = applySorting(users, sortOptions);
|
|
788
809
|
|
|
789
810
|
// Or parse from Express request query
|
|
790
|
-
app.get(
|
|
811
|
+
app.get("/users", (req, res) => {
|
|
791
812
|
const sortOptions = parseSortParams(req.query);
|
|
792
813
|
// Use sortOptions to build database query with Prisma/SQL
|
|
793
814
|
const users = await prisma.user.findMany({
|
|
794
|
-
orderBy: sortOptions.map(s => ({ [s.field]: s.order }))
|
|
815
|
+
orderBy: sortOptions.map((s) => ({ [s.field]: s.order })),
|
|
795
816
|
});
|
|
796
817
|
res.success(users);
|
|
797
818
|
});
|
|
@@ -809,7 +830,7 @@ app.get('/users', (req, res) => {
|
|
|
809
830
|
**What happens:** Configure flexible authentication methods with priority-based fallback for advanced authentication scenarios.
|
|
810
831
|
|
|
811
832
|
```typescript
|
|
812
|
-
import { MisoClient, loadConfig } from
|
|
833
|
+
import { MisoClient, loadConfig } from "@aifabrix/miso-client";
|
|
813
834
|
|
|
814
835
|
const client = new MisoClient(loadConfig());
|
|
815
836
|
await client.initialize();
|
|
@@ -818,17 +839,21 @@ await client.initialize();
|
|
|
818
839
|
const client = new MisoClient({
|
|
819
840
|
...loadConfig(),
|
|
820
841
|
authStrategy: {
|
|
821
|
-
methods: [
|
|
822
|
-
}
|
|
842
|
+
methods: ["bearer", "client-token", "client-credentials"],
|
|
843
|
+
},
|
|
823
844
|
});
|
|
824
845
|
|
|
825
846
|
// Per-request strategy override
|
|
826
|
-
const strategy = client.createAuthStrategy(
|
|
847
|
+
const strategy = client.createAuthStrategy(
|
|
848
|
+
["bearer", "api-key"],
|
|
849
|
+
"token-123",
|
|
850
|
+
"api-key-456",
|
|
851
|
+
);
|
|
827
852
|
await client.getRoles(token, strategy);
|
|
828
853
|
|
|
829
854
|
// Using requestWithAuthStrategy for custom requests
|
|
830
|
-
await client.requestWithAuthStrategy(
|
|
831
|
-
methods: [
|
|
855
|
+
await client.requestWithAuthStrategy("GET", "/api/data", {
|
|
856
|
+
methods: ["client-token"],
|
|
832
857
|
});
|
|
833
858
|
|
|
834
859
|
// Get default strategy
|
|
@@ -863,27 +888,27 @@ MISO_API_KEY=optional-api-key
|
|
|
863
888
|
|
|
864
889
|
```typescript
|
|
865
890
|
interface MisoClientConfig {
|
|
866
|
-
controllerUrl: string;
|
|
867
|
-
clientId: string;
|
|
868
|
-
clientSecret: string;
|
|
869
|
-
redis?: RedisConfig;
|
|
870
|
-
logLevel?:
|
|
871
|
-
encryptionKey?: string;
|
|
891
|
+
controllerUrl: string; // Required: Controller URL
|
|
892
|
+
clientId: string; // Required: Client ID (e.g., 'ctrl-dev-my-app')
|
|
893
|
+
clientSecret: string; // Required: Client secret
|
|
894
|
+
redis?: RedisConfig; // Optional: For caching
|
|
895
|
+
logLevel?: "debug" | "info" | "warn" | "error";
|
|
896
|
+
encryptionKey?: string; // Optional: Encryption key (or use ENCRYPTION_KEY env var)
|
|
872
897
|
sensitiveFieldsConfig?: string; // Optional: Path to ISO 27001 sensitive fields config JSON
|
|
873
|
-
emitEvents?: boolean;
|
|
898
|
+
emitEvents?: boolean; // Optional: Emit log events instead of HTTP/Redis (for direct SDK embedding)
|
|
874
899
|
authStrategy?: AuthStrategy; // Optional: Default authentication strategy
|
|
875
900
|
cache?: {
|
|
876
|
-
roleTTL?: number;
|
|
877
|
-
permissionTTL?: number;
|
|
901
|
+
roleTTL?: number; // Role cache TTL (default: 900s)
|
|
902
|
+
permissionTTL?: number; // Permission cache TTL (default: 900s)
|
|
878
903
|
tokenValidationTTL?: number; // Token validation cache TTL (default: 900s)
|
|
879
904
|
};
|
|
880
|
-
audit?: AuditConfig;
|
|
905
|
+
audit?: AuditConfig; // Optional: Audit logging configuration
|
|
881
906
|
}
|
|
882
907
|
|
|
883
908
|
interface AuthStrategy {
|
|
884
|
-
methods: (
|
|
885
|
-
bearerToken?: string;
|
|
886
|
-
apiKey?: string;
|
|
909
|
+
methods: ("bearer" | "client-token" | "client-credentials" | "api-key")[];
|
|
910
|
+
bearerToken?: string; // Optional: Bearer token for bearer authentication
|
|
911
|
+
apiKey?: string; // Optional: API key for api-key authentication
|
|
887
912
|
}
|
|
888
913
|
```
|
|
889
914
|
|
|
@@ -972,15 +997,15 @@ app.use(async (req, res, next) => {
|
|
|
972
997
|
**Protect routes by role:**
|
|
973
998
|
|
|
974
999
|
```typescript
|
|
975
|
-
app.get(
|
|
1000
|
+
app.get("/admin", async (req, res) => {
|
|
976
1001
|
const token = client.getToken(req);
|
|
977
|
-
if (!token) return res.status(401).json({ error:
|
|
978
|
-
|
|
979
|
-
const isAdmin = await client.hasRole(token,
|
|
980
|
-
if (!isAdmin) return res.status(403).json({ error:
|
|
981
|
-
|
|
1002
|
+
if (!token) return res.status(401).json({ error: "Unauthorized" });
|
|
1003
|
+
|
|
1004
|
+
const isAdmin = await client.hasRole(token, "admin");
|
|
1005
|
+
if (!isAdmin) return res.status(403).json({ error: "Forbidden" });
|
|
1006
|
+
|
|
982
1007
|
// Admin only code
|
|
983
|
-
res.json({ message:
|
|
1008
|
+
res.json({ message: "Admin panel" });
|
|
984
1009
|
});
|
|
985
1010
|
```
|
|
986
1011
|
|