tychat-contracts 1.6.8 → 1.6.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 (67) hide show
  1. package/.github/workflows/publish-npm.yml +25 -25
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +1 -0
  5. package/dist/legal-terms/legal-term-dispatch.dto.d.ts +8 -1
  6. package/dist/legal-terms/legal-term-dispatch.dto.d.ts.map +1 -1
  7. package/dist/legal-terms/legal-term-preview.dto.d.ts +4 -0
  8. package/dist/legal-terms/legal-term-preview.dto.d.ts.map +1 -1
  9. package/dist/legal-terms/legal-term-preview.dto.js +13 -1
  10. package/dist/panel-rbac/access-permission-item.dto.d.ts +6 -0
  11. package/dist/panel-rbac/access-permission-item.dto.d.ts.map +1 -0
  12. package/dist/panel-rbac/access-permission-item.dto.js +36 -0
  13. package/dist/panel-rbac/create-access-level.dto.d.ts +6 -0
  14. package/dist/panel-rbac/create-access-level.dto.d.ts.map +1 -0
  15. package/dist/panel-rbac/create-access-level.dto.js +39 -0
  16. package/dist/panel-rbac/dashboard-layout.dto.d.ts +27 -0
  17. package/dist/panel-rbac/dashboard-layout.dto.d.ts.map +1 -0
  18. package/dist/panel-rbac/dashboard-layout.dto.js +148 -0
  19. package/dist/panel-rbac/index.d.ts +8 -0
  20. package/dist/panel-rbac/index.d.ts.map +1 -0
  21. package/dist/panel-rbac/index.js +23 -0
  22. package/dist/panel-rbac/panel-context-response.dto.d.ts +12 -0
  23. package/dist/panel-rbac/panel-context-response.dto.d.ts.map +1 -0
  24. package/dist/panel-rbac/panel-context-response.dto.js +48 -0
  25. package/dist/panel-rbac/panel-permission-keys.d.ts +29 -0
  26. package/dist/panel-rbac/panel-permission-keys.d.ts.map +1 -0
  27. package/dist/panel-rbac/panel-permission-keys.js +48 -0
  28. package/dist/panel-rbac/panel-permission-keys.spec.d.ts +2 -0
  29. package/dist/panel-rbac/panel-permission-keys.spec.d.ts.map +1 -0
  30. package/dist/panel-rbac/panel-permission-keys.spec.js +16 -0
  31. package/dist/panel-rbac/replace-access-permissions.dto.d.ts +5 -0
  32. package/dist/panel-rbac/replace-access-permissions.dto.d.ts.map +1 -0
  33. package/dist/panel-rbac/replace-access-permissions.dto.js +28 -0
  34. package/dist/panel-rbac/update-access-level.dto.d.ts +8 -0
  35. package/dist/panel-rbac/update-access-level.dto.d.ts.map +1 -0
  36. package/dist/panel-rbac/update-access-level.dto.js +54 -0
  37. package/package.json +29 -29
  38. package/src/analytics/analytics-kafka-topics.ts +24 -24
  39. package/src/analytics/create-tenant-audit-log.dto.ts +105 -105
  40. package/src/analytics/index.ts +8 -8
  41. package/src/analytics/list-tenant-audit-logs-query.dto.ts +45 -45
  42. package/src/auth/auth-kafka.payloads.ts +218 -218
  43. package/src/auth/change-own-password.dto.ts +34 -34
  44. package/src/auth/index.ts +28 -28
  45. package/src/auth/login-2fa.dto.ts +14 -14
  46. package/src/auth/password-reset-finalize-2fa.dto.ts +36 -36
  47. package/src/auth/request-password-reset-response.dto.ts +26 -26
  48. package/src/auth/revoke-device-session.dto.ts +19 -19
  49. package/src/auth/totp-user.dto.ts +58 -58
  50. package/src/configurations/app-module-policy.dto.ts +72 -72
  51. package/src/configurations/app-module-policy.enums.ts +30 -30
  52. package/src/configurations/configuration-tenant-summary.dto.ts +79 -79
  53. package/src/configurations/index.ts +13 -13
  54. package/src/index.ts +1 -0
  55. package/src/legal-terms/legal-term-dispatch.dto.ts +12 -1
  56. package/src/legal-terms/legal-term-preview.dto.ts +15 -1
  57. package/src/panel-rbac/access-permission-item.dto.ts +20 -0
  58. package/src/panel-rbac/create-access-level.dto.ts +20 -0
  59. package/src/panel-rbac/dashboard-layout.dto.ts +133 -0
  60. package/src/panel-rbac/index.ts +7 -0
  61. package/src/panel-rbac/panel-context-response.dto.ts +28 -0
  62. package/src/panel-rbac/panel-permission-keys.spec.ts +20 -0
  63. package/src/panel-rbac/panel-permission-keys.ts +57 -0
  64. package/src/panel-rbac/replace-access-permissions.dto.ts +13 -0
  65. package/src/panel-rbac/update-access-level.dto.ts +40 -0
  66. package/src/storage/presign-download-rpc.dto.ts +38 -38
  67. package/src/storage/storage-rmq-patterns.ts +5 -5
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=panel-permission-keys.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panel-permission-keys.spec.d.ts","sourceRoot":"","sources":["../../src/panel-rbac/panel-permission-keys.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const panel_permission_keys_1 = require("./panel-permission-keys");
4
+ describe("panel-permission-keys", () => {
5
+ it("expõe chaves estáveis para cada recurso/ação", () => {
6
+ let expected = 0;
7
+ for (const [, actions] of Object.entries(panel_permission_keys_1.PANEL_RESOURCE_ACTIONS)) {
8
+ expected += actions.length;
9
+ }
10
+ expect(panel_permission_keys_1.PANEL_PERMISSION_KEYS.length).toBe(expected);
11
+ });
12
+ it("isPanelPermissionKey valida chaves canónicas", () => {
13
+ expect((0, panel_permission_keys_1.isPanelPermissionKey)("tenants.view")).toBe(true);
14
+ expect((0, panel_permission_keys_1.isPanelPermissionKey)("invalid.key")).toBe(false);
15
+ });
16
+ });
@@ -0,0 +1,5 @@
1
+ import { AccessPermissionItemDto } from './access-permission-item.dto';
2
+ export declare class ReplaceAccessPermissionsDto {
3
+ items: AccessPermissionItemDto[];
4
+ }
5
+ //# sourceMappingURL=replace-access-permissions.dto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replace-access-permissions.dto.d.ts","sourceRoot":"","sources":["../../src/panel-rbac/replace-access-permissions.dto.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,qBAAa,2BAA2B;IAMtC,KAAK,EAAE,uBAAuB,EAAE,CAAC;CAClC"}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ReplaceAccessPermissionsDto = void 0;
13
+ const swagger_1 = require("@nestjs/swagger");
14
+ const class_transformer_1 = require("class-transformer");
15
+ const class_validator_1 = require("class-validator");
16
+ const access_permission_item_dto_1 = require("./access-permission-item.dto");
17
+ class ReplaceAccessPermissionsDto {
18
+ items;
19
+ }
20
+ exports.ReplaceAccessPermissionsDto = ReplaceAccessPermissionsDto;
21
+ __decorate([
22
+ (0, swagger_1.ApiProperty)({ type: [access_permission_item_dto_1.AccessPermissionItemDto] }),
23
+ (0, class_validator_1.IsArray)(),
24
+ (0, class_validator_1.ArrayMinSize)(0),
25
+ (0, class_validator_1.ValidateNested)({ each: true }),
26
+ (0, class_transformer_1.Type)(() => access_permission_item_dto_1.AccessPermissionItemDto),
27
+ __metadata("design:type", Array)
28
+ ], ReplaceAccessPermissionsDto.prototype, "items", void 0);
@@ -0,0 +1,8 @@
1
+ import { DashboardLayoutDto } from './dashboard-layout.dto';
2
+ export declare class UpdateAccessLevelDto {
3
+ name?: string;
4
+ description?: string | null;
5
+ isActive?: boolean;
6
+ dashboardLayout?: DashboardLayoutDto | null;
7
+ }
8
+ //# sourceMappingURL=update-access-level.dto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-access-level.dto.d.ts","sourceRoot":"","sources":["../../src/panel-rbac/update-access-level.dto.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,qBAAa,oBAAoB;IAM/B,IAAI,CAAC,EAAE,MAAM,CAAC;IAMd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAK5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IASnB,eAAe,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;CAC7C"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.UpdateAccessLevelDto = void 0;
13
+ const swagger_1 = require("@nestjs/swagger");
14
+ const class_transformer_1 = require("class-transformer");
15
+ const class_validator_1 = require("class-validator");
16
+ const dashboard_layout_dto_1 = require("./dashboard-layout.dto");
17
+ class UpdateAccessLevelDto {
18
+ name;
19
+ description;
20
+ isActive;
21
+ dashboardLayout;
22
+ }
23
+ exports.UpdateAccessLevelDto = UpdateAccessLevelDto;
24
+ __decorate([
25
+ (0, swagger_1.ApiPropertyOptional)(),
26
+ (0, class_validator_1.IsOptional)(),
27
+ (0, class_validator_1.IsString)(),
28
+ (0, class_validator_1.MinLength)(1),
29
+ (0, class_validator_1.MaxLength)(120),
30
+ __metadata("design:type", String)
31
+ ], UpdateAccessLevelDto.prototype, "name", void 0);
32
+ __decorate([
33
+ (0, swagger_1.ApiPropertyOptional)(),
34
+ (0, class_validator_1.IsOptional)(),
35
+ (0, class_validator_1.IsString)(),
36
+ (0, class_validator_1.MaxLength)(500),
37
+ __metadata("design:type", Object)
38
+ ], UpdateAccessLevelDto.prototype, "description", void 0);
39
+ __decorate([
40
+ (0, swagger_1.ApiPropertyOptional)(),
41
+ (0, class_validator_1.IsOptional)(),
42
+ (0, class_validator_1.IsBoolean)(),
43
+ __metadata("design:type", Boolean)
44
+ ], UpdateAccessLevelDto.prototype, "isActive", void 0);
45
+ __decorate([
46
+ (0, swagger_1.ApiPropertyOptional)({
47
+ description: 'Layout do dashboard para utilizadores deste nível (master).',
48
+ type: dashboard_layout_dto_1.DashboardLayoutDto,
49
+ }),
50
+ (0, class_validator_1.IsOptional)(),
51
+ (0, class_validator_1.ValidateNested)(),
52
+ (0, class_transformer_1.Type)(() => dashboard_layout_dto_1.DashboardLayoutDto),
53
+ __metadata("design:type", Object)
54
+ ], UpdateAccessLevelDto.prototype, "dashboardLayout", void 0);
package/package.json CHANGED
@@ -1,29 +1,29 @@
1
- {
2
- "name": "tychat-contracts",
3
- "version": "1.6.8",
4
- "description": "DTOs compartilhados com class-validator (API e microserviços)",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "private": false,
8
- "scripts": {
9
- "build": "tsc",
10
- "prepublishOnly": "npm run build"
11
- },
12
- "dependencies": {
13
- "class-transformer": "^0.5.1",
14
- "class-validator": "^0.14.1",
15
- "ioredis": "^5.10.0",
16
- "jest": "^30.3.0",
17
- "reflect-metadata": "*"
18
- },
19
- "devDependencies": {
20
- "@nestjs/swagger": "^11.2.6",
21
- "@types/jest": "^30.0.0",
22
- "ts-jest": "^29.4.9",
23
- "typescript": "^5.7.3"
24
- },
25
- "peerDependencies": {
26
- "@nestjs/swagger": "^11.2.6",
27
- "reflect-metadata": "*"
28
- }
29
- }
1
+ {
2
+ "name": "tychat-contracts",
3
+ "version": "1.6.11",
4
+ "description": "DTOs compartilhados com class-validator (API e microserviços)",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "private": false,
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "prepublishOnly": "npm run build"
11
+ },
12
+ "dependencies": {
13
+ "class-transformer": "^0.5.1",
14
+ "class-validator": "^0.14.1",
15
+ "ioredis": "^5.10.0",
16
+ "jest": "^30.3.0",
17
+ "reflect-metadata": "*"
18
+ },
19
+ "devDependencies": {
20
+ "@nestjs/swagger": "^11.2.6",
21
+ "@types/jest": "^30.0.0",
22
+ "ts-jest": "^29.4.9",
23
+ "typescript": "^5.7.3"
24
+ },
25
+ "peerDependencies": {
26
+ "@nestjs/swagger": "^11.2.6",
27
+ "reflect-metadata": "*"
28
+ }
29
+ }
@@ -1,24 +1,24 @@
1
- /**
2
- * Kafka topic names used by the analytics service.
3
- */
4
-
5
- /** Topic for ingesting analytic events from all microservices. */
6
- export const TOPIC_ANALYTICS_EVENT = 'analytics.event';
7
-
8
- /** Topic for requesting a report grouped by event type and period. */
9
- export const TOPIC_ANALYTICS_REPORT = 'analytics.report';
10
-
11
- /** Topic for requesting a dashboard summary (counts per domain). */
12
- export const TOPIC_ANALYTICS_DASHBOARD = 'analytics.dashboard';
13
-
14
- /** Topic for requesting a time-series breakdown of events. */
15
- export const TOPIC_ANALYTICS_TIMESERIES = 'analytics.timeseries';
16
-
17
- /** Topic for requesting event details with pagination. */
18
- export const TOPIC_ANALYTICS_EVENTS_LIST = 'analytics.events.list';
19
-
20
- /** Topic for ingesting tenant user-action audit rows (dedicated table). */
21
- export const TOPIC_ANALYTICS_TENANT_AUDIT_INGEST = 'analytics.tenant_audit.ingest';
22
-
23
- /** Topic for paginated tenant audit log listing. */
24
- export const TOPIC_ANALYTICS_TENANT_AUDIT_LIST = 'analytics.tenant_audit.list';
1
+ /**
2
+ * Kafka topic names used by the analytics service.
3
+ */
4
+
5
+ /** Topic for ingesting analytic events from all microservices. */
6
+ export const TOPIC_ANALYTICS_EVENT = 'analytics.event';
7
+
8
+ /** Topic for requesting a report grouped by event type and period. */
9
+ export const TOPIC_ANALYTICS_REPORT = 'analytics.report';
10
+
11
+ /** Topic for requesting a dashboard summary (counts per domain). */
12
+ export const TOPIC_ANALYTICS_DASHBOARD = 'analytics.dashboard';
13
+
14
+ /** Topic for requesting a time-series breakdown of events. */
15
+ export const TOPIC_ANALYTICS_TIMESERIES = 'analytics.timeseries';
16
+
17
+ /** Topic for requesting event details with pagination. */
18
+ export const TOPIC_ANALYTICS_EVENTS_LIST = 'analytics.events.list';
19
+
20
+ /** Topic for ingesting tenant user-action audit rows (dedicated table). */
21
+ export const TOPIC_ANALYTICS_TENANT_AUDIT_INGEST = 'analytics.tenant_audit.ingest';
22
+
23
+ /** Topic for paginated tenant audit log listing. */
24
+ export const TOPIC_ANALYTICS_TENANT_AUDIT_LIST = 'analytics.tenant_audit.list';
@@ -1,105 +1,105 @@
1
- import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
2
- import {
3
- IsIn,
4
- IsInt,
5
- IsISO8601,
6
- IsNotEmpty,
7
- IsObject,
8
- IsOptional,
9
- IsString,
10
- IsUUID,
11
- Max,
12
- MaxLength,
13
- Min,
14
- MinLength,
15
- } from 'class-validator';
16
-
17
- /** Outcome of the audited HTTP mutation. */
18
- export const TENANT_AUDIT_OUTCOMES = ['success', 'failure'] as const;
19
- export type TenantAuditOutcome = (typeof TENANT_AUDIT_OUTCOMES)[number];
20
-
21
- /**
22
- * Payload for persisting a tenant-scoped user action audit row (HTTP mutation).
23
- */
24
- export class CreateTenantAuditLogDto {
25
- @ApiProperty({ description: 'Unique id for idempotent insert', format: 'uuid' })
26
- @IsUUID()
27
- eventId: string;
28
-
29
- @ApiProperty({ description: 'Tenant slug' })
30
- @IsString()
31
- @IsNotEmpty()
32
- @MinLength(1)
33
- @MaxLength(255)
34
- tenant: string;
35
-
36
- @ApiProperty({ example: 'user', description: 'Actor category' })
37
- @IsString()
38
- @IsNotEmpty()
39
- @MaxLength(64)
40
- actorType: string;
41
-
42
- @ApiProperty({ description: 'Authenticated user id (sub)' })
43
- @IsString()
44
- @IsNotEmpty()
45
- @MaxLength(255)
46
- actorId: string;
47
-
48
- @ApiProperty({
49
- example: 'http.mutation',
50
- description: 'Deterministic action key (e.g. http.mutation)',
51
- })
52
- @IsString()
53
- @IsNotEmpty()
54
- @MaxLength(128)
55
- action: string;
56
-
57
- @ApiPropertyOptional({ example: 'http' })
58
- @IsOptional()
59
- @IsString()
60
- @MaxLength(64)
61
- targetType?: string | null;
62
-
63
- @ApiPropertyOptional({ description: 'Route param id when present' })
64
- @IsOptional()
65
- @IsString()
66
- @MaxLength(255)
67
- targetId?: string | null;
68
-
69
- @ApiProperty({ enum: TENANT_AUDIT_OUTCOMES })
70
- @IsIn([...TENANT_AUDIT_OUTCOMES])
71
- outcome: TenantAuditOutcome;
72
-
73
- @ApiProperty({ example: 'POST' })
74
- @IsString()
75
- @IsNotEmpty()
76
- @MaxLength(16)
77
- httpMethod: string;
78
-
79
- @ApiProperty({ example: '/patients/123' })
80
- @IsString()
81
- @IsNotEmpty()
82
- @MaxLength(2048)
83
- httpPath: string;
84
-
85
- @ApiProperty({ example: 201 })
86
- @IsInt()
87
- @Min(100)
88
- @Max(599)
89
- httpStatus: number;
90
-
91
- @ApiPropertyOptional({ description: 'On failure, stable error code if available' })
92
- @IsOptional()
93
- @IsString()
94
- @MaxLength(128)
95
- errorCode?: string | null;
96
-
97
- @ApiPropertyOptional({ description: 'Minimal non-PII context' })
98
- @IsOptional()
99
- @IsObject()
100
- metadata?: Record<string, unknown> | null;
101
-
102
- @ApiProperty({ description: 'When the action completed (UTC ISO-8601)' })
103
- @IsISO8601()
104
- occurredAt: string;
105
- }
1
+ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
2
+ import {
3
+ IsIn,
4
+ IsInt,
5
+ IsISO8601,
6
+ IsNotEmpty,
7
+ IsObject,
8
+ IsOptional,
9
+ IsString,
10
+ IsUUID,
11
+ Max,
12
+ MaxLength,
13
+ Min,
14
+ MinLength,
15
+ } from 'class-validator';
16
+
17
+ /** Outcome of the audited HTTP mutation. */
18
+ export const TENANT_AUDIT_OUTCOMES = ['success', 'failure'] as const;
19
+ export type TenantAuditOutcome = (typeof TENANT_AUDIT_OUTCOMES)[number];
20
+
21
+ /**
22
+ * Payload for persisting a tenant-scoped user action audit row (HTTP mutation).
23
+ */
24
+ export class CreateTenantAuditLogDto {
25
+ @ApiProperty({ description: 'Unique id for idempotent insert', format: 'uuid' })
26
+ @IsUUID()
27
+ eventId: string;
28
+
29
+ @ApiProperty({ description: 'Tenant slug' })
30
+ @IsString()
31
+ @IsNotEmpty()
32
+ @MinLength(1)
33
+ @MaxLength(255)
34
+ tenant: string;
35
+
36
+ @ApiProperty({ example: 'user', description: 'Actor category' })
37
+ @IsString()
38
+ @IsNotEmpty()
39
+ @MaxLength(64)
40
+ actorType: string;
41
+
42
+ @ApiProperty({ description: 'Authenticated user id (sub)' })
43
+ @IsString()
44
+ @IsNotEmpty()
45
+ @MaxLength(255)
46
+ actorId: string;
47
+
48
+ @ApiProperty({
49
+ example: 'http.mutation',
50
+ description: 'Deterministic action key (e.g. http.mutation)',
51
+ })
52
+ @IsString()
53
+ @IsNotEmpty()
54
+ @MaxLength(128)
55
+ action: string;
56
+
57
+ @ApiPropertyOptional({ example: 'http' })
58
+ @IsOptional()
59
+ @IsString()
60
+ @MaxLength(64)
61
+ targetType?: string | null;
62
+
63
+ @ApiPropertyOptional({ description: 'Route param id when present' })
64
+ @IsOptional()
65
+ @IsString()
66
+ @MaxLength(255)
67
+ targetId?: string | null;
68
+
69
+ @ApiProperty({ enum: TENANT_AUDIT_OUTCOMES })
70
+ @IsIn([...TENANT_AUDIT_OUTCOMES])
71
+ outcome: TenantAuditOutcome;
72
+
73
+ @ApiProperty({ example: 'POST' })
74
+ @IsString()
75
+ @IsNotEmpty()
76
+ @MaxLength(16)
77
+ httpMethod: string;
78
+
79
+ @ApiProperty({ example: '/patients/123' })
80
+ @IsString()
81
+ @IsNotEmpty()
82
+ @MaxLength(2048)
83
+ httpPath: string;
84
+
85
+ @ApiProperty({ example: 201 })
86
+ @IsInt()
87
+ @Min(100)
88
+ @Max(599)
89
+ httpStatus: number;
90
+
91
+ @ApiPropertyOptional({ description: 'On failure, stable error code if available' })
92
+ @IsOptional()
93
+ @IsString()
94
+ @MaxLength(128)
95
+ errorCode?: string | null;
96
+
97
+ @ApiPropertyOptional({ description: 'Minimal non-PII context' })
98
+ @IsOptional()
99
+ @IsObject()
100
+ metadata?: Record<string, unknown> | null;
101
+
102
+ @ApiProperty({ description: 'When the action completed (UTC ISO-8601)' })
103
+ @IsISO8601()
104
+ occurredAt: string;
105
+ }
@@ -1,8 +1,8 @@
1
- export * from './event-analytic.enum';
2
- export * from './followup-analytic-event-type.util';
3
- export * from './create-analytic-event.dto';
4
- export * from './create-tenant-audit-log.dto';
5
- export * from './list-tenant-audit-logs-query.dto';
6
- export * from './analytics-query.dto';
7
- export * from './analytics-kafka-topics';
8
- export * from './analytics-emitter.helper';
1
+ export * from './event-analytic.enum';
2
+ export * from './followup-analytic-event-type.util';
3
+ export * from './create-analytic-event.dto';
4
+ export * from './create-tenant-audit-log.dto';
5
+ export * from './list-tenant-audit-logs-query.dto';
6
+ export * from './analytics-query.dto';
7
+ export * from './analytics-kafka-topics';
8
+ export * from './analytics-emitter.helper';
@@ -1,45 +1,45 @@
1
- import { ApiPropertyOptional } from '@nestjs/swagger';
2
- import { Type } from 'class-transformer';
3
- import { IsInt, IsOptional, Max, Min } from 'class-validator';
4
- import type { ParsedFilterDto } from '../filters/parsed-filter.dto';
5
-
6
- /**
7
- * Allowed tenant_audit_logs columns for filtering (camelCase API keys).
8
- */
9
- export const TENANT_AUDIT_LIST_FILTER_KEYS = [
10
- 'actorId',
11
- 'action',
12
- 'outcome',
13
- 'httpMethod',
14
- 'httpPath',
15
- 'httpStatus',
16
- 'occurredAt',
17
- ] as const;
18
- export type TenantAuditListFilterKeyDto = (typeof TENANT_AUDIT_LIST_FILTER_KEYS)[number];
19
-
20
- export class ListTenantAuditLogsQueryDto {
21
- @ApiPropertyOptional({ example: 1, minimum: 1, default: 1 })
22
- @IsOptional()
23
- @Type(() => Number)
24
- @IsInt()
25
- @Min(1)
26
- page?: number;
27
-
28
- @ApiPropertyOptional({ example: 20, minimum: 1, maximum: 100, default: 20 })
29
- @IsOptional()
30
- @Type(() => Number)
31
- @IsInt()
32
- @Min(1)
33
- @Max(100)
34
- limit?: number;
35
-
36
- @ApiPropertyOptional({
37
- description:
38
- 'JSON string with an array of filter objects `{ key, op, value }`. ' +
39
- 'Example: `[{"key":"outcome","op":"==","value":"success"}]`.',
40
- type: String,
41
- example: '[{"key":"outcome","op":"==","value":"success"}]',
42
- })
43
- @IsOptional()
44
- filters?: ParsedFilterDto[];
45
- }
1
+ import { ApiPropertyOptional } from '@nestjs/swagger';
2
+ import { Type } from 'class-transformer';
3
+ import { IsInt, IsOptional, Max, Min } from 'class-validator';
4
+ import type { ParsedFilterDto } from '../filters/parsed-filter.dto';
5
+
6
+ /**
7
+ * Allowed tenant_audit_logs columns for filtering (camelCase API keys).
8
+ */
9
+ export const TENANT_AUDIT_LIST_FILTER_KEYS = [
10
+ 'actorId',
11
+ 'action',
12
+ 'outcome',
13
+ 'httpMethod',
14
+ 'httpPath',
15
+ 'httpStatus',
16
+ 'occurredAt',
17
+ ] as const;
18
+ export type TenantAuditListFilterKeyDto = (typeof TENANT_AUDIT_LIST_FILTER_KEYS)[number];
19
+
20
+ export class ListTenantAuditLogsQueryDto {
21
+ @ApiPropertyOptional({ example: 1, minimum: 1, default: 1 })
22
+ @IsOptional()
23
+ @Type(() => Number)
24
+ @IsInt()
25
+ @Min(1)
26
+ page?: number;
27
+
28
+ @ApiPropertyOptional({ example: 20, minimum: 1, maximum: 100, default: 20 })
29
+ @IsOptional()
30
+ @Type(() => Number)
31
+ @IsInt()
32
+ @Min(1)
33
+ @Max(100)
34
+ limit?: number;
35
+
36
+ @ApiPropertyOptional({
37
+ description:
38
+ 'JSON string with an array of filter objects `{ key, op, value }`. ' +
39
+ 'Example: `[{"key":"outcome","op":"==","value":"success"}]`.',
40
+ type: String,
41
+ example: '[{"key":"outcome","op":"==","value":"success"}]',
42
+ })
43
+ @IsOptional()
44
+ filters?: ParsedFilterDto[];
45
+ }