tychat-contracts 1.6.82 → 1.6.83
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/dist/analytics/create-patient-audit-log.dto.d.ts +39 -0
- package/dist/analytics/create-patient-audit-log.dto.d.ts.map +1 -0
- package/dist/analytics/create-patient-audit-log.dto.js +179 -0
- package/dist/analytics/index.d.ts +1 -1
- package/dist/analytics/index.d.ts.map +1 -1
- package/dist/analytics/index.js +1 -1
- package/dist/analytics/list-tenant-audit-logs-query.dto.d.ts +2 -2
- package/dist/analytics/list-tenant-audit-logs-query.dto.d.ts.map +1 -1
- package/dist/analytics/list-tenant-audit-logs-query.dto.js +5 -7
- package/package.json +1 -1
- package/src/analytics/create-patient-audit-log.dto.ts +144 -0
- package/src/analytics/index.ts +1 -1
- package/src/analytics/list-tenant-audit-logs-query.dto.ts +5 -7
- package/src/analytics/create-tenant-audit-log.dto.ts +0 -105
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Who performed the audited patient mutation. */
|
|
2
|
+
export declare const PATIENT_AUDIT_ACTOR_TYPES: readonly ["user", "system", "patient"];
|
|
3
|
+
export type PatientAuditActorType = (typeof PATIENT_AUDIT_ACTOR_TYPES)[number];
|
|
4
|
+
/** Domain actions persisted in patient_audit_logs. */
|
|
5
|
+
export declare const PATIENT_AUDIT_ACTIONS: readonly ["patient.created", "patient.updated", "patient.deleted"];
|
|
6
|
+
export type PatientAuditAction = (typeof PATIENT_AUDIT_ACTIONS)[number];
|
|
7
|
+
/** Single field change on a patient record. */
|
|
8
|
+
export declare class PatientAuditChangeDto {
|
|
9
|
+
field: string;
|
|
10
|
+
previousValue?: unknown;
|
|
11
|
+
newValue?: unknown;
|
|
12
|
+
}
|
|
13
|
+
/** Caller context propagated over RPC for patient write operations. */
|
|
14
|
+
export declare class PatientAuditContextDto {
|
|
15
|
+
actorType: PatientAuditActorType;
|
|
16
|
+
actorId: string;
|
|
17
|
+
actorIp?: string;
|
|
18
|
+
actorUserAgent?: string;
|
|
19
|
+
source: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Payload for persisting a tenant-scoped patient audit row.
|
|
23
|
+
*/
|
|
24
|
+
export declare class CreatePatientAuditLogDto {
|
|
25
|
+
eventId: string;
|
|
26
|
+
tenant: string;
|
|
27
|
+
actorType: PatientAuditActorType;
|
|
28
|
+
actorId: string;
|
|
29
|
+
actorIp?: string | null;
|
|
30
|
+
actorUserAgent?: string | null;
|
|
31
|
+
action: PatientAuditAction;
|
|
32
|
+
resourceId: string;
|
|
33
|
+
source: string;
|
|
34
|
+
changes: PatientAuditChangeDto[];
|
|
35
|
+
occurredAt: string;
|
|
36
|
+
}
|
|
37
|
+
/** @deprecated Use CreatePatientAuditLogDto */
|
|
38
|
+
export type CreateTenantAuditLogDto = CreatePatientAuditLogDto;
|
|
39
|
+
//# sourceMappingURL=create-patient-audit-log.dto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-patient-audit-log.dto.d.ts","sourceRoot":"","sources":["../../src/analytics/create-patient-audit-log.dto.ts"],"names":[],"mappings":"AAeA,kDAAkD;AAClD,eAAO,MAAM,yBAAyB,wCAAyC,CAAC;AAChF,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/E,sDAAsD;AACtD,eAAO,MAAM,qBAAqB,oEAIxB,CAAC;AACX,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,+CAA+C;AAC/C,qBAAa,qBAAqB;IAKhC,KAAK,EAAE,MAAM,CAAC;IAId,aAAa,CAAC,EAAE,OAAO,CAAC;IAIxB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,uEAAuE;AACvE,qBAAa,sBAAsB;IAGjC,SAAS,EAAE,qBAAqB,CAAC;IAMjC,OAAO,EAAE,MAAM,CAAC;IAMhB,OAAO,CAAC,EAAE,MAAM,CAAC;IAMjB,cAAc,CAAC,EAAE,MAAM,CAAC;IASxB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,wBAAwB;IAGnC,OAAO,EAAE,MAAM,CAAC;IAOhB,MAAM,EAAE,MAAM,CAAC;IAIf,SAAS,EAAE,qBAAqB,CAAC;IAMjC,OAAO,EAAE,MAAM,CAAC;IAMhB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAMxB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAI/B,MAAM,EAAE,kBAAkB,CAAC;IAM3B,UAAU,EAAE,MAAM,CAAC;IAMnB,MAAM,EAAE,MAAM,CAAC;IAMf,OAAO,EAAE,qBAAqB,EAAE,CAAC;IAIjC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,+CAA+C;AAC/C,MAAM,MAAM,uBAAuB,GAAG,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
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.CreatePatientAuditLogDto = exports.PatientAuditContextDto = exports.PatientAuditChangeDto = exports.PATIENT_AUDIT_ACTIONS = exports.PATIENT_AUDIT_ACTOR_TYPES = void 0;
|
|
13
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
const class_transformer_1 = require("class-transformer");
|
|
16
|
+
/** Who performed the audited patient mutation. */
|
|
17
|
+
exports.PATIENT_AUDIT_ACTOR_TYPES = ['user', 'system', 'patient'];
|
|
18
|
+
/** Domain actions persisted in patient_audit_logs. */
|
|
19
|
+
exports.PATIENT_AUDIT_ACTIONS = [
|
|
20
|
+
'patient.created',
|
|
21
|
+
'patient.updated',
|
|
22
|
+
'patient.deleted',
|
|
23
|
+
];
|
|
24
|
+
/** Single field change on a patient record. */
|
|
25
|
+
class PatientAuditChangeDto {
|
|
26
|
+
field;
|
|
27
|
+
previousValue;
|
|
28
|
+
newValue;
|
|
29
|
+
}
|
|
30
|
+
exports.PatientAuditChangeDto = PatientAuditChangeDto;
|
|
31
|
+
__decorate([
|
|
32
|
+
(0, swagger_1.ApiProperty)({ example: 'name' }),
|
|
33
|
+
(0, class_validator_1.IsString)(),
|
|
34
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
35
|
+
(0, class_validator_1.MaxLength)(128),
|
|
36
|
+
__metadata("design:type", String)
|
|
37
|
+
], PatientAuditChangeDto.prototype, "field", void 0);
|
|
38
|
+
__decorate([
|
|
39
|
+
(0, swagger_1.ApiPropertyOptional)({ description: 'Previous value (null on create)' }),
|
|
40
|
+
(0, class_validator_1.IsOptional)(),
|
|
41
|
+
__metadata("design:type", Object)
|
|
42
|
+
], PatientAuditChangeDto.prototype, "previousValue", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
(0, swagger_1.ApiPropertyOptional)({ description: 'New value (null on delete of field)' }),
|
|
45
|
+
(0, class_validator_1.IsOptional)(),
|
|
46
|
+
__metadata("design:type", Object)
|
|
47
|
+
], PatientAuditChangeDto.prototype, "newValue", void 0);
|
|
48
|
+
/** Caller context propagated over RPC for patient write operations. */
|
|
49
|
+
class PatientAuditContextDto {
|
|
50
|
+
actorType;
|
|
51
|
+
actorId;
|
|
52
|
+
actorIp;
|
|
53
|
+
actorUserAgent;
|
|
54
|
+
source;
|
|
55
|
+
}
|
|
56
|
+
exports.PatientAuditContextDto = PatientAuditContextDto;
|
|
57
|
+
__decorate([
|
|
58
|
+
(0, swagger_1.ApiProperty)({ enum: exports.PATIENT_AUDIT_ACTOR_TYPES }),
|
|
59
|
+
(0, class_validator_1.IsIn)([...exports.PATIENT_AUDIT_ACTOR_TYPES]),
|
|
60
|
+
__metadata("design:type", String)
|
|
61
|
+
], PatientAuditContextDto.prototype, "actorType", void 0);
|
|
62
|
+
__decorate([
|
|
63
|
+
(0, swagger_1.ApiProperty)({ description: 'User sub, service name, or patient token id' }),
|
|
64
|
+
(0, class_validator_1.IsString)(),
|
|
65
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
66
|
+
(0, class_validator_1.MaxLength)(255),
|
|
67
|
+
__metadata("design:type", String)
|
|
68
|
+
], PatientAuditContextDto.prototype, "actorId", void 0);
|
|
69
|
+
__decorate([
|
|
70
|
+
(0, swagger_1.ApiPropertyOptional)({ example: '203.0.113.10' }),
|
|
71
|
+
(0, class_validator_1.IsOptional)(),
|
|
72
|
+
(0, class_validator_1.IsString)(),
|
|
73
|
+
(0, class_validator_1.MaxLength)(64),
|
|
74
|
+
__metadata("design:type", String)
|
|
75
|
+
], PatientAuditContextDto.prototype, "actorIp", void 0);
|
|
76
|
+
__decorate([
|
|
77
|
+
(0, swagger_1.ApiPropertyOptional)(),
|
|
78
|
+
(0, class_validator_1.IsOptional)(),
|
|
79
|
+
(0, class_validator_1.IsString)(),
|
|
80
|
+
(0, class_validator_1.MaxLength)(512),
|
|
81
|
+
__metadata("design:type", String)
|
|
82
|
+
], PatientAuditContextDto.prototype, "actorUserAgent", void 0);
|
|
83
|
+
__decorate([
|
|
84
|
+
(0, swagger_1.ApiProperty)({
|
|
85
|
+
example: 'patient_service.upsertPatientByPhone',
|
|
86
|
+
description: 'Deterministic origin of the mutation',
|
|
87
|
+
}),
|
|
88
|
+
(0, class_validator_1.IsString)(),
|
|
89
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
90
|
+
(0, class_validator_1.MaxLength)(255),
|
|
91
|
+
__metadata("design:type", String)
|
|
92
|
+
], PatientAuditContextDto.prototype, "source", void 0);
|
|
93
|
+
/**
|
|
94
|
+
* Payload for persisting a tenant-scoped patient audit row.
|
|
95
|
+
*/
|
|
96
|
+
class CreatePatientAuditLogDto {
|
|
97
|
+
eventId;
|
|
98
|
+
tenant;
|
|
99
|
+
actorType;
|
|
100
|
+
actorId;
|
|
101
|
+
actorIp;
|
|
102
|
+
actorUserAgent;
|
|
103
|
+
action;
|
|
104
|
+
resourceId;
|
|
105
|
+
source;
|
|
106
|
+
changes;
|
|
107
|
+
occurredAt;
|
|
108
|
+
}
|
|
109
|
+
exports.CreatePatientAuditLogDto = CreatePatientAuditLogDto;
|
|
110
|
+
__decorate([
|
|
111
|
+
(0, swagger_1.ApiProperty)({ description: 'Unique id for idempotent insert', format: 'uuid' }),
|
|
112
|
+
(0, class_validator_1.IsUUID)(),
|
|
113
|
+
__metadata("design:type", String)
|
|
114
|
+
], CreatePatientAuditLogDto.prototype, "eventId", void 0);
|
|
115
|
+
__decorate([
|
|
116
|
+
(0, swagger_1.ApiProperty)({ description: 'Tenant slug' }),
|
|
117
|
+
(0, class_validator_1.IsString)(),
|
|
118
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
119
|
+
(0, class_validator_1.MinLength)(1),
|
|
120
|
+
(0, class_validator_1.MaxLength)(255),
|
|
121
|
+
__metadata("design:type", String)
|
|
122
|
+
], CreatePatientAuditLogDto.prototype, "tenant", void 0);
|
|
123
|
+
__decorate([
|
|
124
|
+
(0, swagger_1.ApiProperty)({ enum: exports.PATIENT_AUDIT_ACTOR_TYPES }),
|
|
125
|
+
(0, class_validator_1.IsIn)([...exports.PATIENT_AUDIT_ACTOR_TYPES]),
|
|
126
|
+
__metadata("design:type", String)
|
|
127
|
+
], CreatePatientAuditLogDto.prototype, "actorType", void 0);
|
|
128
|
+
__decorate([
|
|
129
|
+
(0, swagger_1.ApiProperty)({ description: 'Authenticated user id, service name, or token id' }),
|
|
130
|
+
(0, class_validator_1.IsString)(),
|
|
131
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
132
|
+
(0, class_validator_1.MaxLength)(255),
|
|
133
|
+
__metadata("design:type", String)
|
|
134
|
+
], CreatePatientAuditLogDto.prototype, "actorId", void 0);
|
|
135
|
+
__decorate([
|
|
136
|
+
(0, swagger_1.ApiPropertyOptional)(),
|
|
137
|
+
(0, class_validator_1.IsOptional)(),
|
|
138
|
+
(0, class_validator_1.IsString)(),
|
|
139
|
+
(0, class_validator_1.MaxLength)(64),
|
|
140
|
+
__metadata("design:type", Object)
|
|
141
|
+
], CreatePatientAuditLogDto.prototype, "actorIp", void 0);
|
|
142
|
+
__decorate([
|
|
143
|
+
(0, swagger_1.ApiPropertyOptional)(),
|
|
144
|
+
(0, class_validator_1.IsOptional)(),
|
|
145
|
+
(0, class_validator_1.IsString)(),
|
|
146
|
+
(0, class_validator_1.MaxLength)(512),
|
|
147
|
+
__metadata("design:type", Object)
|
|
148
|
+
], CreatePatientAuditLogDto.prototype, "actorUserAgent", void 0);
|
|
149
|
+
__decorate([
|
|
150
|
+
(0, swagger_1.ApiProperty)({ enum: exports.PATIENT_AUDIT_ACTIONS }),
|
|
151
|
+
(0, class_validator_1.IsIn)([...exports.PATIENT_AUDIT_ACTIONS]),
|
|
152
|
+
__metadata("design:type", String)
|
|
153
|
+
], CreatePatientAuditLogDto.prototype, "action", void 0);
|
|
154
|
+
__decorate([
|
|
155
|
+
(0, swagger_1.ApiProperty)({ description: 'Patient UUID' }),
|
|
156
|
+
(0, class_validator_1.IsString)(),
|
|
157
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
158
|
+
(0, class_validator_1.MaxLength)(255),
|
|
159
|
+
__metadata("design:type", String)
|
|
160
|
+
], CreatePatientAuditLogDto.prototype, "resourceId", void 0);
|
|
161
|
+
__decorate([
|
|
162
|
+
(0, swagger_1.ApiProperty)({ example: 'patient_service.updatePatient' }),
|
|
163
|
+
(0, class_validator_1.IsString)(),
|
|
164
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
165
|
+
(0, class_validator_1.MaxLength)(255),
|
|
166
|
+
__metadata("design:type", String)
|
|
167
|
+
], CreatePatientAuditLogDto.prototype, "source", void 0);
|
|
168
|
+
__decorate([
|
|
169
|
+
(0, swagger_1.ApiProperty)({ type: [PatientAuditChangeDto] }),
|
|
170
|
+
(0, class_validator_1.IsArray)(),
|
|
171
|
+
(0, class_validator_1.ValidateNested)({ each: true }),
|
|
172
|
+
(0, class_transformer_1.Type)(() => PatientAuditChangeDto),
|
|
173
|
+
__metadata("design:type", Array)
|
|
174
|
+
], CreatePatientAuditLogDto.prototype, "changes", void 0);
|
|
175
|
+
__decorate([
|
|
176
|
+
(0, swagger_1.ApiProperty)({ description: 'When the mutation completed (UTC ISO-8601)' }),
|
|
177
|
+
(0, class_validator_1.IsISO8601)(),
|
|
178
|
+
__metadata("design:type", String)
|
|
179
|
+
], CreatePatientAuditLogDto.prototype, "occurredAt", void 0);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from './event-analytic.enum';
|
|
2
2
|
export * from './followup-analytic-event-type.util';
|
|
3
3
|
export * from './create-analytic-event.dto';
|
|
4
|
-
export * from './create-
|
|
4
|
+
export * from './create-patient-audit-log.dto';
|
|
5
5
|
export * from './list-tenant-audit-logs-query.dto';
|
|
6
6
|
export * from './analytics-query.dto';
|
|
7
7
|
export * from './analytics-kafka-topics';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analytics/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analytics/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,qCAAqC,CAAC;AACpD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oCAAoC,CAAC;AACnD,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC"}
|
package/dist/analytics/index.js
CHANGED
|
@@ -17,7 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./event-analytic.enum"), exports);
|
|
18
18
|
__exportStar(require("./followup-analytic-event-type.util"), exports);
|
|
19
19
|
__exportStar(require("./create-analytic-event.dto"), exports);
|
|
20
|
-
__exportStar(require("./create-
|
|
20
|
+
__exportStar(require("./create-patient-audit-log.dto"), exports);
|
|
21
21
|
__exportStar(require("./list-tenant-audit-logs-query.dto"), exports);
|
|
22
22
|
__exportStar(require("./analytics-query.dto"), exports);
|
|
23
23
|
__exportStar(require("./analytics-kafka-topics"), exports);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ParsedFilterDto } from '../filters/parsed-filter.dto';
|
|
2
2
|
/**
|
|
3
|
-
* Allowed
|
|
3
|
+
* Allowed patient_audit_logs columns for filtering (camelCase API keys).
|
|
4
4
|
*/
|
|
5
|
-
export declare const TENANT_AUDIT_LIST_FILTER_KEYS: readonly ["actorId", "action", "
|
|
5
|
+
export declare const TENANT_AUDIT_LIST_FILTER_KEYS: readonly ["actorId", "action", "resourceId", "source", "occurredAt"];
|
|
6
6
|
export type TenantAuditListFilterKeyDto = (typeof TENANT_AUDIT_LIST_FILTER_KEYS)[number];
|
|
7
7
|
export declare class ListTenantAuditLogsQueryDto {
|
|
8
8
|
page?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-tenant-audit-logs-query.dto.d.ts","sourceRoot":"","sources":["../../src/analytics/list-tenant-audit-logs-query.dto.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEpE;;GAEG;AACH,eAAO,MAAM,6BAA6B,
|
|
1
|
+
{"version":3,"file":"list-tenant-audit-logs-query.dto.d.ts","sourceRoot":"","sources":["../../src/analytics/list-tenant-audit-logs-query.dto.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEpE;;GAEG;AACH,eAAO,MAAM,6BAA6B,sEAMhC,CAAC;AACX,MAAM,MAAM,2BAA2B,GAAG,CAAC,OAAO,6BAA6B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzF,qBAAa,2BAA2B;IAMtC,IAAI,CAAC,EAAE,MAAM,CAAC;IAQd,KAAK,CAAC,EAAE,MAAM,CAAC;IAUf,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;CAC7B"}
|
|
@@ -14,15 +14,13 @@ const swagger_1 = require("@nestjs/swagger");
|
|
|
14
14
|
const class_transformer_1 = require("class-transformer");
|
|
15
15
|
const class_validator_1 = require("class-validator");
|
|
16
16
|
/**
|
|
17
|
-
* Allowed
|
|
17
|
+
* Allowed patient_audit_logs columns for filtering (camelCase API keys).
|
|
18
18
|
*/
|
|
19
19
|
exports.TENANT_AUDIT_LIST_FILTER_KEYS = [
|
|
20
20
|
'actorId',
|
|
21
21
|
'action',
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'httpPath',
|
|
25
|
-
'httpStatus',
|
|
22
|
+
'resourceId',
|
|
23
|
+
'source',
|
|
26
24
|
'occurredAt',
|
|
27
25
|
];
|
|
28
26
|
class ListTenantAuditLogsQueryDto {
|
|
@@ -51,9 +49,9 @@ __decorate([
|
|
|
51
49
|
__decorate([
|
|
52
50
|
(0, swagger_1.ApiPropertyOptional)({
|
|
53
51
|
description: 'JSON string with an array of filter objects `{ key, op, value }`. ' +
|
|
54
|
-
'Example: `[{"key":"
|
|
52
|
+
'Example: `[{"key":"action","op":"==","value":"patient.updated"}]`.',
|
|
55
53
|
type: String,
|
|
56
|
-
example: '[{"key":"
|
|
54
|
+
example: '[{"key":"action","op":"==","value":"patient.updated"}]',
|
|
57
55
|
}),
|
|
58
56
|
(0, class_validator_1.IsOptional)(),
|
|
59
57
|
__metadata("design:type", Array)
|
package/package.json
CHANGED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
|
2
|
+
import {
|
|
3
|
+
IsArray,
|
|
4
|
+
IsIn,
|
|
5
|
+
IsISO8601,
|
|
6
|
+
IsNotEmpty,
|
|
7
|
+
IsOptional,
|
|
8
|
+
IsString,
|
|
9
|
+
IsUUID,
|
|
10
|
+
MaxLength,
|
|
11
|
+
MinLength,
|
|
12
|
+
ValidateNested,
|
|
13
|
+
} from 'class-validator';
|
|
14
|
+
import { Type } from 'class-transformer';
|
|
15
|
+
|
|
16
|
+
/** Who performed the audited patient mutation. */
|
|
17
|
+
export const PATIENT_AUDIT_ACTOR_TYPES = ['user', 'system', 'patient'] as const;
|
|
18
|
+
export type PatientAuditActorType = (typeof PATIENT_AUDIT_ACTOR_TYPES)[number];
|
|
19
|
+
|
|
20
|
+
/** Domain actions persisted in patient_audit_logs. */
|
|
21
|
+
export const PATIENT_AUDIT_ACTIONS = [
|
|
22
|
+
'patient.created',
|
|
23
|
+
'patient.updated',
|
|
24
|
+
'patient.deleted',
|
|
25
|
+
] as const;
|
|
26
|
+
export type PatientAuditAction = (typeof PATIENT_AUDIT_ACTIONS)[number];
|
|
27
|
+
|
|
28
|
+
/** Single field change on a patient record. */
|
|
29
|
+
export class PatientAuditChangeDto {
|
|
30
|
+
@ApiProperty({ example: 'name' })
|
|
31
|
+
@IsString()
|
|
32
|
+
@IsNotEmpty()
|
|
33
|
+
@MaxLength(128)
|
|
34
|
+
field: string;
|
|
35
|
+
|
|
36
|
+
@ApiPropertyOptional({ description: 'Previous value (null on create)' })
|
|
37
|
+
@IsOptional()
|
|
38
|
+
previousValue?: unknown;
|
|
39
|
+
|
|
40
|
+
@ApiPropertyOptional({ description: 'New value (null on delete of field)' })
|
|
41
|
+
@IsOptional()
|
|
42
|
+
newValue?: unknown;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Caller context propagated over RPC for patient write operations. */
|
|
46
|
+
export class PatientAuditContextDto {
|
|
47
|
+
@ApiProperty({ enum: PATIENT_AUDIT_ACTOR_TYPES })
|
|
48
|
+
@IsIn([...PATIENT_AUDIT_ACTOR_TYPES])
|
|
49
|
+
actorType: PatientAuditActorType;
|
|
50
|
+
|
|
51
|
+
@ApiProperty({ description: 'User sub, service name, or patient token id' })
|
|
52
|
+
@IsString()
|
|
53
|
+
@IsNotEmpty()
|
|
54
|
+
@MaxLength(255)
|
|
55
|
+
actorId: string;
|
|
56
|
+
|
|
57
|
+
@ApiPropertyOptional({ example: '203.0.113.10' })
|
|
58
|
+
@IsOptional()
|
|
59
|
+
@IsString()
|
|
60
|
+
@MaxLength(64)
|
|
61
|
+
actorIp?: string;
|
|
62
|
+
|
|
63
|
+
@ApiPropertyOptional()
|
|
64
|
+
@IsOptional()
|
|
65
|
+
@IsString()
|
|
66
|
+
@MaxLength(512)
|
|
67
|
+
actorUserAgent?: string;
|
|
68
|
+
|
|
69
|
+
@ApiProperty({
|
|
70
|
+
example: 'patient_service.upsertPatientByPhone',
|
|
71
|
+
description: 'Deterministic origin of the mutation',
|
|
72
|
+
})
|
|
73
|
+
@IsString()
|
|
74
|
+
@IsNotEmpty()
|
|
75
|
+
@MaxLength(255)
|
|
76
|
+
source: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Payload for persisting a tenant-scoped patient audit row.
|
|
81
|
+
*/
|
|
82
|
+
export class CreatePatientAuditLogDto {
|
|
83
|
+
@ApiProperty({ description: 'Unique id for idempotent insert', format: 'uuid' })
|
|
84
|
+
@IsUUID()
|
|
85
|
+
eventId: string;
|
|
86
|
+
|
|
87
|
+
@ApiProperty({ description: 'Tenant slug' })
|
|
88
|
+
@IsString()
|
|
89
|
+
@IsNotEmpty()
|
|
90
|
+
@MinLength(1)
|
|
91
|
+
@MaxLength(255)
|
|
92
|
+
tenant: string;
|
|
93
|
+
|
|
94
|
+
@ApiProperty({ enum: PATIENT_AUDIT_ACTOR_TYPES })
|
|
95
|
+
@IsIn([...PATIENT_AUDIT_ACTOR_TYPES])
|
|
96
|
+
actorType: PatientAuditActorType;
|
|
97
|
+
|
|
98
|
+
@ApiProperty({ description: 'Authenticated user id, service name, or token id' })
|
|
99
|
+
@IsString()
|
|
100
|
+
@IsNotEmpty()
|
|
101
|
+
@MaxLength(255)
|
|
102
|
+
actorId: string;
|
|
103
|
+
|
|
104
|
+
@ApiPropertyOptional()
|
|
105
|
+
@IsOptional()
|
|
106
|
+
@IsString()
|
|
107
|
+
@MaxLength(64)
|
|
108
|
+
actorIp?: string | null;
|
|
109
|
+
|
|
110
|
+
@ApiPropertyOptional()
|
|
111
|
+
@IsOptional()
|
|
112
|
+
@IsString()
|
|
113
|
+
@MaxLength(512)
|
|
114
|
+
actorUserAgent?: string | null;
|
|
115
|
+
|
|
116
|
+
@ApiProperty({ enum: PATIENT_AUDIT_ACTIONS })
|
|
117
|
+
@IsIn([...PATIENT_AUDIT_ACTIONS])
|
|
118
|
+
action: PatientAuditAction;
|
|
119
|
+
|
|
120
|
+
@ApiProperty({ description: 'Patient UUID' })
|
|
121
|
+
@IsString()
|
|
122
|
+
@IsNotEmpty()
|
|
123
|
+
@MaxLength(255)
|
|
124
|
+
resourceId: string;
|
|
125
|
+
|
|
126
|
+
@ApiProperty({ example: 'patient_service.updatePatient' })
|
|
127
|
+
@IsString()
|
|
128
|
+
@IsNotEmpty()
|
|
129
|
+
@MaxLength(255)
|
|
130
|
+
source: string;
|
|
131
|
+
|
|
132
|
+
@ApiProperty({ type: [PatientAuditChangeDto] })
|
|
133
|
+
@IsArray()
|
|
134
|
+
@ValidateNested({ each: true })
|
|
135
|
+
@Type(() => PatientAuditChangeDto)
|
|
136
|
+
changes: PatientAuditChangeDto[];
|
|
137
|
+
|
|
138
|
+
@ApiProperty({ description: 'When the mutation completed (UTC ISO-8601)' })
|
|
139
|
+
@IsISO8601()
|
|
140
|
+
occurredAt: string;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** @deprecated Use CreatePatientAuditLogDto */
|
|
144
|
+
export type CreateTenantAuditLogDto = CreatePatientAuditLogDto;
|
package/src/analytics/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from './event-analytic.enum';
|
|
2
2
|
export * from './followup-analytic-event-type.util';
|
|
3
3
|
export * from './create-analytic-event.dto';
|
|
4
|
-
export * from './create-
|
|
4
|
+
export * from './create-patient-audit-log.dto';
|
|
5
5
|
export * from './list-tenant-audit-logs-query.dto';
|
|
6
6
|
export * from './analytics-query.dto';
|
|
7
7
|
export * from './analytics-kafka-topics';
|
|
@@ -4,15 +4,13 @@ import { IsInt, IsOptional, Max, Min } from 'class-validator';
|
|
|
4
4
|
import type { ParsedFilterDto } from '../filters/parsed-filter.dto';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Allowed
|
|
7
|
+
* Allowed patient_audit_logs columns for filtering (camelCase API keys).
|
|
8
8
|
*/
|
|
9
9
|
export const TENANT_AUDIT_LIST_FILTER_KEYS = [
|
|
10
10
|
'actorId',
|
|
11
11
|
'action',
|
|
12
|
-
'
|
|
13
|
-
'
|
|
14
|
-
'httpPath',
|
|
15
|
-
'httpStatus',
|
|
12
|
+
'resourceId',
|
|
13
|
+
'source',
|
|
16
14
|
'occurredAt',
|
|
17
15
|
] as const;
|
|
18
16
|
export type TenantAuditListFilterKeyDto = (typeof TENANT_AUDIT_LIST_FILTER_KEYS)[number];
|
|
@@ -36,9 +34,9 @@ export class ListTenantAuditLogsQueryDto {
|
|
|
36
34
|
@ApiPropertyOptional({
|
|
37
35
|
description:
|
|
38
36
|
'JSON string with an array of filter objects `{ key, op, value }`. ' +
|
|
39
|
-
'Example: `[{"key":"
|
|
37
|
+
'Example: `[{"key":"action","op":"==","value":"patient.updated"}]`.',
|
|
40
38
|
type: String,
|
|
41
|
-
example: '[{"key":"
|
|
39
|
+
example: '[{"key":"action","op":"==","value":"patient.updated"}]',
|
|
42
40
|
})
|
|
43
41
|
@IsOptional()
|
|
44
42
|
filters?: ParsedFilterDto[];
|
|
@@ -1,105 +0,0 @@
|
|
|
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
|
-
}
|