miso-client 0.1.0__py3-none-any.whl → 3.7.2__py3-none-any.whl

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 (69) hide show
  1. miso_client/__init__.py +523 -130
  2. miso_client/api/__init__.py +35 -0
  3. miso_client/api/auth_api.py +367 -0
  4. miso_client/api/logs_api.py +91 -0
  5. miso_client/api/permissions_api.py +88 -0
  6. miso_client/api/roles_api.py +88 -0
  7. miso_client/api/types/__init__.py +75 -0
  8. miso_client/api/types/auth_types.py +183 -0
  9. miso_client/api/types/logs_types.py +71 -0
  10. miso_client/api/types/permissions_types.py +31 -0
  11. miso_client/api/types/roles_types.py +31 -0
  12. miso_client/errors.py +30 -4
  13. miso_client/models/__init__.py +4 -0
  14. miso_client/models/config.py +275 -72
  15. miso_client/models/error_response.py +39 -0
  16. miso_client/models/filter.py +255 -0
  17. miso_client/models/pagination.py +44 -0
  18. miso_client/models/sort.py +25 -0
  19. miso_client/services/__init__.py +6 -5
  20. miso_client/services/auth.py +496 -87
  21. miso_client/services/cache.py +42 -41
  22. miso_client/services/encryption.py +18 -17
  23. miso_client/services/logger.py +467 -328
  24. miso_client/services/logger_chain.py +288 -0
  25. miso_client/services/permission.py +130 -67
  26. miso_client/services/redis.py +28 -23
  27. miso_client/services/role.py +145 -62
  28. miso_client/utils/__init__.py +3 -3
  29. miso_client/utils/audit_log_queue.py +222 -0
  30. miso_client/utils/auth_strategy.py +88 -0
  31. miso_client/utils/auth_utils.py +65 -0
  32. miso_client/utils/circuit_breaker.py +125 -0
  33. miso_client/utils/client_token_manager.py +244 -0
  34. miso_client/utils/config_loader.py +88 -17
  35. miso_client/utils/controller_url_resolver.py +80 -0
  36. miso_client/utils/data_masker.py +104 -33
  37. miso_client/utils/environment_token.py +126 -0
  38. miso_client/utils/error_utils.py +216 -0
  39. miso_client/utils/fastapi_endpoints.py +166 -0
  40. miso_client/utils/filter.py +364 -0
  41. miso_client/utils/filter_applier.py +143 -0
  42. miso_client/utils/filter_parser.py +110 -0
  43. miso_client/utils/flask_endpoints.py +169 -0
  44. miso_client/utils/http_client.py +494 -262
  45. miso_client/utils/http_client_logging.py +352 -0
  46. miso_client/utils/http_client_logging_helpers.py +197 -0
  47. miso_client/utils/http_client_query_helpers.py +138 -0
  48. miso_client/utils/http_error_handler.py +92 -0
  49. miso_client/utils/http_log_formatter.py +115 -0
  50. miso_client/utils/http_log_masker.py +203 -0
  51. miso_client/utils/internal_http_client.py +435 -0
  52. miso_client/utils/jwt_tools.py +125 -16
  53. miso_client/utils/logger_helpers.py +206 -0
  54. miso_client/utils/logging_helpers.py +70 -0
  55. miso_client/utils/origin_validator.py +128 -0
  56. miso_client/utils/pagination.py +275 -0
  57. miso_client/utils/request_context.py +285 -0
  58. miso_client/utils/sensitive_fields_loader.py +116 -0
  59. miso_client/utils/sort.py +116 -0
  60. miso_client/utils/token_utils.py +114 -0
  61. miso_client/utils/url_validator.py +66 -0
  62. miso_client/utils/user_token_refresh.py +245 -0
  63. miso_client-3.7.2.dist-info/METADATA +1021 -0
  64. miso_client-3.7.2.dist-info/RECORD +68 -0
  65. miso_client-0.1.0.dist-info/METADATA +0 -551
  66. miso_client-0.1.0.dist-info/RECORD +0 -23
  67. {miso_client-0.1.0.dist-info → miso_client-3.7.2.dist-info}/WHEEL +0 -0
  68. {miso_client-0.1.0.dist-info → miso_client-3.7.2.dist-info}/licenses/LICENSE +0 -0
  69. {miso_client-0.1.0.dist-info → miso_client-3.7.2.dist-info}/top_level.txt +0 -0
@@ -5,13 +5,17 @@ This module contains Pydantic models that define the configuration structure
5
5
  and data types used throughout the MisoClient SDK.
6
6
  """
7
7
 
8
- from typing import Optional, Dict, Any, List, Literal
8
+ from typing import Any, Dict, List, Literal, Optional, Union
9
+
9
10
  from pydantic import BaseModel, Field
10
11
 
12
+ # Authentication method types
13
+ AuthMethod = Literal["bearer", "client-token", "client-credentials", "api-key"]
14
+
11
15
 
12
16
  class RedisConfig(BaseModel):
13
17
  """Redis connection configuration."""
14
-
18
+
15
19
  host: str = Field(..., description="Redis host")
16
20
  port: int = Field(default=6379, description="Redis port")
17
21
  password: Optional[str] = Field(default=None, description="Redis password")
@@ -19,40 +23,119 @@ class RedisConfig(BaseModel):
19
23
  key_prefix: str = Field(default="miso:", description="Key prefix for Redis keys")
20
24
 
21
25
 
26
+ class AuditConfig(BaseModel):
27
+ """Audit logging configuration for HTTP client."""
28
+
29
+ enabled: Optional[bool] = Field(
30
+ default=True, description="Enable/disable audit logging (default: true)"
31
+ )
32
+ level: Optional[Literal["minimal", "standard", "detailed", "full"]] = Field(
33
+ default="detailed", description="Audit detail level (default: 'detailed')"
34
+ )
35
+ maxResponseSize: Optional[int] = Field(
36
+ default=10000, description="Truncate responses larger than this (default: 10000 bytes)"
37
+ )
38
+ maxMaskingSize: Optional[int] = Field(
39
+ default=50000,
40
+ description="Skip masking for objects larger than this (default: 50000 bytes)",
41
+ )
42
+ batchSize: Optional[int] = Field(
43
+ default=10, description="Batch size for queued logs (default: 10)"
44
+ )
45
+ batchInterval: Optional[int] = Field(
46
+ default=100, description="Flush interval in milliseconds (default: 100)"
47
+ )
48
+ skipEndpoints: Optional[List[str]] = Field(
49
+ default=None, description="Array of endpoint patterns to exclude from audit logging"
50
+ )
51
+ circuitBreaker: Optional["CircuitBreakerConfig"] = Field(
52
+ default=None, description="Circuit breaker configuration for HTTP logging"
53
+ )
54
+
55
+
56
+ class AuthStrategy(BaseModel):
57
+ """Authentication strategy configuration.
58
+
59
+ Defines which authentication methods to try and in what priority order.
60
+ Methods are tried in the order specified until one succeeds.
61
+ """
62
+
63
+ methods: List[AuthMethod] = Field(
64
+ default=["bearer", "client-token"],
65
+ description="Array of auth methods in priority order (default: ['bearer', 'client-token'])",
66
+ )
67
+ bearerToken: Optional[str] = Field(
68
+ default=None, description="Optional bearer token for bearer auth"
69
+ )
70
+ apiKey: Optional[str] = Field(default=None, description="Optional API key for api-key auth")
71
+
72
+
22
73
  class MisoClientConfig(BaseModel):
23
74
  """Main MisoClient configuration.
24
-
75
+
25
76
  Required fields:
26
77
  - controller_url: Miso Controller base URL
27
78
  - client_id: Client identifier for authentication
28
79
  - client_secret: Client secret for authentication
29
-
80
+
30
81
  Optional fields:
31
82
  - redis: Redis configuration for caching
32
83
  - log_level: Logging level (debug, info, warn, error)
33
84
  - cache: Cache TTL settings for roles and permissions
85
+ - api_key: API key for testing (bypasses OAuth2 authentication)
34
86
  """
35
-
87
+
36
88
  controller_url: str = Field(..., description="Miso Controller base URL")
37
89
  client_id: str = Field(..., description="Client identifier for authentication")
38
90
  client_secret: str = Field(..., description="Client secret for authentication")
39
91
  redis: Optional[RedisConfig] = Field(default=None, description="Optional Redis configuration")
40
92
  log_level: Literal["debug", "info", "warn", "error"] = Field(
41
- default="info",
42
- description="Log level"
93
+ default="info", description="Log level"
43
94
  )
44
95
  cache: Optional[Dict[str, int]] = Field(
45
96
  default=None,
46
- description="Cache TTL settings: permission_ttl, role_ttl (default: 900 seconds)"
97
+ description="Cache TTL settings: permission_ttl, role_ttl (default: 900 seconds)",
98
+ )
99
+ api_key: Optional[str] = Field(
100
+ default=None,
101
+ description="API key for testing - when set, bearer tokens matching this key bypass OAuth2 validation",
47
102
  )
48
-
103
+ sensitive_fields_config: Optional[str] = Field(
104
+ default=None, description="Path to sensitive fields configuration JSON file"
105
+ )
106
+ audit: Optional["AuditConfig"] = Field(default=None, description="Audit logging configuration")
107
+ emit_events: Optional[bool] = Field(
108
+ default=False,
109
+ description="Emit log events instead of sending via HTTP/Redis (default: false)",
110
+ )
111
+ authStrategy: Optional["AuthStrategy"] = Field(
112
+ default=None,
113
+ description="Authentication strategy configuration (default: ['bearer', 'client-token'])",
114
+ )
115
+ clientTokenUri: Optional[str] = Field(
116
+ default=None,
117
+ description="URI for client token endpoint (default: '/api/v1/auth/token')",
118
+ )
119
+ allowedOrigins: Optional[List[str]] = Field(
120
+ default=None,
121
+ description="Array of allowed origins for CORS validation",
122
+ )
123
+ controllerPublicUrl: Optional[str] = Field(
124
+ default=None,
125
+ description="Public controller URL for browser environments (accessible from internet)",
126
+ )
127
+ controllerPrivateUrl: Optional[str] = Field(
128
+ default=None,
129
+ description="Private controller URL for server environments (internal network access)",
130
+ )
131
+
49
132
  @property
50
133
  def role_ttl(self) -> int:
51
134
  """Get role cache TTL in seconds."""
52
135
  if self.cache and "role_ttl" in self.cache:
53
136
  return self.cache["role_ttl"]
54
137
  return self.cache.get("roleTTL", 900) if self.cache else 900 # 15 minutes default
55
-
138
+
56
139
  @property
57
140
  def permission_ttl(self) -> int:
58
141
  """Get permission cache TTL in seconds."""
@@ -60,24 +143,45 @@ class MisoClientConfig(BaseModel):
60
143
  return self.cache["permission_ttl"]
61
144
  return self.cache.get("permissionTTL", 900) if self.cache else 900 # 15 minutes default
62
145
 
146
+ @property
147
+ def validation_ttl(self) -> int:
148
+ """Get token validation cache TTL in seconds."""
149
+ if self.cache and "validation_ttl" in self.cache:
150
+ return self.cache["validation_ttl"]
151
+ return self.cache.get("validationTTL", 120) if self.cache else 120 # 2 minutes default
152
+
153
+
154
+ class ForeignKeyReference(BaseModel):
155
+ """Foreign key reference object for API responses.
156
+
157
+ Provides essential context about referenced entities without requiring additional lookups.
158
+ Used consistently across all foreign keys in API response models.
159
+ """
160
+
161
+ id: str = Field(..., description="Entity ID (environment-specific identifier)")
162
+ key: str = Field(..., description="Entity key (environment-agnostic identifier)")
163
+ name: str = Field(
164
+ ..., description="Entity name (displayName, name, or firstName/lastName for User)"
165
+ )
166
+ type: str = Field(
167
+ ..., description="Entity type (e.g., 'Environment', 'User', 'Application', 'Controller')"
168
+ )
169
+
63
170
 
64
171
  class UserInfo(BaseModel):
65
172
  """User information from token validation."""
66
-
173
+
67
174
  id: str = Field(..., description="User ID")
68
175
  username: str = Field(..., description="Username")
69
176
  email: Optional[str] = Field(default=None, description="User email")
70
- firstName: Optional[str] = Field(default=None, alias="first_name", description="First name")
71
- lastName: Optional[str] = Field(default=None, alias="last_name", description="Last name")
177
+ firstName: Optional[str] = Field(default=None, description="First name")
178
+ lastName: Optional[str] = Field(default=None, description="Last name")
72
179
  roles: Optional[List[str]] = Field(default=None, description="User roles")
73
-
74
- class Config:
75
- populate_by_name = True # Allow both snake_case and camelCase
76
180
 
77
181
 
78
182
  class AuthResult(BaseModel):
79
183
  """Authentication result."""
80
-
184
+
81
185
  authenticated: bool = Field(..., description="Whether authentication was successful")
82
186
  user: Optional[UserInfo] = Field(default=None, description="User information if authenticated")
83
187
  error: Optional[str] = Field(default=None, description="Error message if authentication failed")
@@ -85,90 +189,189 @@ class AuthResult(BaseModel):
85
189
 
86
190
  class LogEntry(BaseModel):
87
191
  """Log entry structure."""
88
-
192
+
89
193
  timestamp: str = Field(..., description="ISO timestamp")
90
194
  level: Literal["error", "audit", "info", "debug"] = Field(..., description="Log level")
91
195
  environment: str = Field(..., description="Environment name (extracted by backend)")
92
196
  application: str = Field(..., description="Application identifier (clientId)")
93
- applicationId: Optional[str] = Field(default=None, alias="application_id", description="Application ID")
94
- userId: Optional[str] = Field(default=None, alias="user_id", description="User ID if available")
197
+ applicationId: Optional["ForeignKeyReference"] = Field(
198
+ default=None, description="Application reference (foreign key object)"
199
+ )
200
+ userId: Optional["ForeignKeyReference"] = Field(
201
+ default=None, description="User reference (foreign key object)"
202
+ )
95
203
  message: str = Field(..., description="Log message")
96
204
  context: Optional[Dict[str, Any]] = Field(default=None, description="Additional context")
97
- correlationId: Optional[str] = Field(default=None, alias="correlation_id", description="Correlation ID for tracing")
98
- requestId: Optional[str] = Field(default=None, alias="request_id", description="Request ID")
99
- sessionId: Optional[str] = Field(default=None, alias="session_id", description="Session ID")
100
- stackTrace: Optional[str] = Field(default=None, alias="stack_trace", description="Stack trace for errors")
101
- ipAddress: Optional[str] = Field(default=None, alias="ip_address", description="IP address")
102
- userAgent: Optional[str] = Field(default=None, alias="user_agent", description="User agent")
205
+ correlationId: Optional[str] = Field(default=None, description="Correlation ID for tracing")
206
+ requestId: Optional[str] = Field(default=None, description="Request ID")
207
+ sessionId: Optional[str] = Field(default=None, description="Session ID")
208
+ stackTrace: Optional[str] = Field(default=None, description="Stack trace for errors")
209
+ ipAddress: Optional[str] = Field(default=None, description="IP address")
210
+ userAgent: Optional[str] = Field(default=None, description="User agent")
103
211
  hostname: Optional[str] = Field(default=None, description="Hostname")
104
-
105
- class Config:
106
- populate_by_name = True
212
+
213
+ # Indexed context fields (top-level for fast queries)
214
+ sourceKey: Optional[str] = Field(default=None, description="ExternalDataSource.key")
215
+ sourceDisplayName: Optional[str] = Field(default=None, description="Human-readable source name")
216
+ externalSystemKey: Optional[str] = Field(default=None, description="ExternalSystem.key")
217
+ externalSystemDisplayName: Optional[str] = Field(
218
+ default=None, description="Human-readable system name"
219
+ )
220
+ recordKey: Optional[str] = Field(default=None, description="ExternalRecord.key")
221
+ recordDisplayName: Optional[str] = Field(
222
+ default=None, description="Human-readable record identifier"
223
+ )
224
+
225
+ # Credential context (for performance analysis)
226
+ credentialId: Optional[str] = Field(default=None, description="Credential ID")
227
+ credentialType: Optional[str] = Field(
228
+ default=None, description="Credential type (apiKey, oauth2, etc.)"
229
+ )
230
+
231
+ # Request/Response metrics
232
+ requestSize: Optional[int] = Field(default=None, description="Request body size in bytes")
233
+ responseSize: Optional[int] = Field(default=None, description="Response body size in bytes")
234
+ durationMs: Optional[int] = Field(default=None, description="Duration in milliseconds")
235
+ durationSeconds: Optional[float] = Field(default=None, description="Duration in seconds")
236
+ timeout: Optional[float] = Field(default=None, description="Request timeout in seconds")
237
+ retryCount: Optional[int] = Field(default=None, description="Number of retry attempts")
238
+
239
+ # Error classification
240
+ errorCategory: Optional[str] = Field(
241
+ default=None, description="Error category: network, timeout, auth, validation, server"
242
+ )
243
+ httpStatusCategory: Optional[str] = Field(
244
+ default=None, description="HTTP status category: 2xx, 4xx, 5xx"
245
+ )
107
246
 
108
247
 
109
248
  class RoleResult(BaseModel):
110
249
  """Role query result."""
111
-
112
- userId: str = Field(..., alias="user_id", description="User ID")
250
+
251
+ userId: str = Field(..., description="User ID")
113
252
  roles: List[str] = Field(..., description="List of user roles")
114
253
  environment: str = Field(..., description="Environment name")
115
254
  application: str = Field(..., description="Application name")
116
-
117
- class Config:
118
- populate_by_name = True
119
255
 
120
256
 
121
257
  class PermissionResult(BaseModel):
122
258
  """Permission query result."""
123
-
124
- userId: str = Field(..., alias="user_id", description="User ID")
259
+
260
+ userId: str = Field(..., description="User ID")
125
261
  permissions: List[str] = Field(..., description="List of user permissions")
126
262
  environment: str = Field(..., description="Environment name")
127
263
  application: str = Field(..., description="Application name")
128
-
129
- class Config:
130
- populate_by_name = True
131
264
 
132
265
 
133
266
  class ClientTokenResponse(BaseModel):
134
267
  """Client token response."""
135
-
268
+
136
269
  success: bool = Field(..., description="Whether token request was successful")
137
270
  token: str = Field(..., description="Client token")
138
- expiresIn: int = Field(..., alias="expires_in", description="Token expiration in seconds")
139
- expiresAt: str = Field(..., alias="expires_at", description="Token expiration ISO timestamp")
140
-
141
- class Config:
142
- populate_by_name = True
271
+ expiresIn: int = Field(..., description="Token expiration in seconds")
272
+ expiresAt: str = Field(..., description="Token expiration ISO timestamp")
143
273
 
144
274
 
145
- class PerformanceMetrics(BaseModel):
146
- """Performance metrics for logging."""
147
-
148
- startTime: int = Field(..., alias="start_time", description="Start time in milliseconds")
149
- endTime: Optional[int] = Field(default=None, alias="end_time", description="End time in milliseconds")
150
- duration: Optional[int] = Field(default=None, description="Duration in milliseconds")
151
- memoryUsage: Optional[Dict[str, int]] = Field(
152
- default=None,
153
- alias="memory_usage",
154
- description="Memory usage metrics (rss, heapTotal, heapUsed, external, arrayBuffers)"
155
- )
156
-
157
- class Config:
158
- populate_by_name = True
275
+ class ClientLoggingOptions(BaseModel):
276
+ """Options for client logging.
159
277
 
278
+ Supports both string IDs (for backward compatibility) and ForeignKeyReference objects.
279
+ When string IDs are provided, they will be converted to ForeignKeyReference objects
280
+ in LogEntry if needed (requires additional context from API responses).
281
+ """
160
282
 
161
- class ClientLoggingOptions(BaseModel):
162
- """Options for client logging."""
163
-
164
- applicationId: Optional[str] = Field(default=None, alias="application_id", description="Application ID")
165
- userId: Optional[str] = Field(default=None, alias="user_id", description="User ID")
166
- correlationId: Optional[str] = Field(default=None, alias="correlation_id", description="Correlation ID")
167
- requestId: Optional[str] = Field(default=None, alias="request_id", description="Request ID")
168
- sessionId: Optional[str] = Field(default=None, alias="session_id", description="Session ID")
283
+ applicationId: Optional[Union[str, "ForeignKeyReference"]] = Field(
284
+ default=None, description="Application ID (string) or Application reference (object)"
285
+ )
286
+ userId: Optional[Union[str, "ForeignKeyReference"]] = Field(
287
+ default=None, description="User ID (string) or User reference (object)"
288
+ )
289
+ correlationId: Optional[str] = Field(default=None, description="Correlation ID")
290
+ requestId: Optional[str] = Field(default=None, description="Request ID")
291
+ sessionId: Optional[str] = Field(default=None, description="Session ID")
169
292
  token: Optional[str] = Field(default=None, description="JWT token for context extraction")
170
- maskSensitiveData: Optional[bool] = Field(default=None, alias="mask_sensitive_data", description="Enable data masking")
171
- performanceMetrics: Optional[bool] = Field(default=None, alias="performance_metrics", description="Include performance metrics")
172
-
173
- class Config:
174
- populate_by_name = True
293
+ maskSensitiveData: Optional[bool] = Field(default=None, description="Enable data masking")
294
+ ipAddress: Optional[str] = Field(default=None, description="Client IP address")
295
+ userAgent: Optional[str] = Field(default=None, description="User agent string")
296
+
297
+ # Indexed context
298
+ sourceKey: Optional[str] = Field(default=None, description="ExternalDataSource.key")
299
+ sourceDisplayName: Optional[str] = Field(default=None, description="Human-readable source name")
300
+ externalSystemKey: Optional[str] = Field(default=None, description="ExternalSystem.key")
301
+ externalSystemDisplayName: Optional[str] = Field(
302
+ default=None, description="Human-readable system name"
303
+ )
304
+ recordKey: Optional[str] = Field(default=None, description="ExternalRecord.key")
305
+ recordDisplayName: Optional[str] = Field(
306
+ default=None, description="Human-readable record identifier"
307
+ )
308
+
309
+ # Credential context
310
+ credentialId: Optional[str] = Field(default=None, description="Credential ID")
311
+ credentialType: Optional[str] = Field(default=None, description="Credential type")
312
+
313
+ # Request metrics
314
+ requestSize: Optional[int] = Field(default=None, description="Request body size in bytes")
315
+ responseSize: Optional[int] = Field(default=None, description="Response body size in bytes")
316
+ durationMs: Optional[int] = Field(default=None, description="Duration in milliseconds")
317
+ durationSeconds: Optional[float] = Field(default=None, description="Duration in seconds")
318
+ timeout: Optional[float] = Field(default=None, description="Request timeout in seconds")
319
+ retryCount: Optional[int] = Field(default=None, description="Retry count")
320
+
321
+ # Error classification
322
+ errorCategory: Optional[str] = Field(default=None, description="Error category")
323
+ httpStatusCategory: Optional[str] = Field(default=None, description="HTTP status category")
324
+
325
+
326
+ class CircuitBreakerConfig(BaseModel):
327
+ """Circuit breaker configuration for HTTP logging."""
328
+
329
+ failureThreshold: Optional[int] = Field(
330
+ default=3, description="Number of consecutive failures before opening circuit (default: 3)"
331
+ )
332
+ resetTimeout: Optional[int] = Field(
333
+ default=60, description="Seconds to wait before resetting circuit (default: 60)"
334
+ )
335
+
336
+
337
+ class DataClientConfigResponse(BaseModel):
338
+ """DataClient configuration returned by client-token endpoint.
339
+
340
+ Contains all necessary configuration for browser-side DataClient initialization.
341
+ """
342
+
343
+ baseUrl: str = Field(..., description="API base URL (derived from request)")
344
+ controllerUrl: str = Field(..., description="MISO Controller URL (from misoClient config)")
345
+ controllerPublicUrl: Optional[str] = Field(
346
+ default=None, description="Public controller URL for browser environments (if set)"
347
+ )
348
+ clientId: str = Field(..., description="Client ID (from misoClient config)")
349
+ clientTokenUri: str = Field(..., description="Client token endpoint URI")
350
+
351
+
352
+ class ClientTokenEndpointResponse(BaseModel):
353
+ """Client token endpoint response.
354
+
355
+ Includes token, expiration, and DataClient configuration.
356
+ """
357
+
358
+ token: str = Field(..., description="Client token string")
359
+ expiresIn: int = Field(..., description="Token expiration time in seconds")
360
+ config: Optional[DataClientConfigResponse] = Field(
361
+ default=None, description="DataClient configuration (included when includeConfig is true)"
362
+ )
363
+
364
+
365
+ class ClientTokenEndpointOptions(BaseModel):
366
+ """Options for createClientTokenEndpoint."""
367
+
368
+ clientTokenUri: Optional[str] = Field(
369
+ default="/api/v1/auth/client-token",
370
+ description="Client token endpoint URI (default: '/api/v1/auth/client-token')",
371
+ )
372
+ expiresIn: Optional[int] = Field(
373
+ default=1800, description="Token expiration time in seconds (default: 1800)"
374
+ )
375
+ includeConfig: Optional[bool] = Field(
376
+ default=True, description="Whether to include DataClient config in response (default: true)"
377
+ )
@@ -0,0 +1,39 @@
1
+ """
2
+ Structured error response model following RFC 7807-style format.
3
+
4
+ This module provides a generic error response interface that can be used
5
+ across different applications for consistent error handling.
6
+ """
7
+
8
+ from typing import List, Optional
9
+
10
+ from pydantic import BaseModel, Field
11
+
12
+
13
+ class ErrorResponse(BaseModel):
14
+ """
15
+ Structured error response following RFC 7807-style format.
16
+
17
+ This model represents a standardized error response structure that includes:
18
+ - Multiple error messages
19
+ - Error type identifier
20
+ - Human-readable title
21
+ - HTTP status code
22
+ - Request instance URI (optional)
23
+
24
+ Example:
25
+ {
26
+ "errors": ["Error message 1", "Error message 2"],
27
+ "type": "/Errors/Bad Input",
28
+ "title": "Bad Request",
29
+ "statusCode": 400,
30
+ "instance": "/OpenApi/rest/Xzy"
31
+ }
32
+ """
33
+
34
+ errors: List[str] = Field(..., description="List of error messages")
35
+ type: str = Field(..., description="Error type URI (e.g., '/Errors/Bad Input')")
36
+ title: Optional[str] = Field(default=None, description="Human-readable error title")
37
+ statusCode: int = Field(..., description="HTTP status code")
38
+ instance: Optional[str] = Field(default=None, description="Request instance URI")
39
+ correlationId: Optional[str] = Field(default=None, description="Request key for error tracking")