tychat-contracts 1.6.8 → 1.6.9
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/.github/workflows/publish-npm.yml +25 -25
- package/dist/legal-terms/legal-term-dispatch.dto.d.ts +8 -1
- package/dist/legal-terms/legal-term-dispatch.dto.d.ts.map +1 -1
- package/dist/legal-terms/legal-term-preview.dto.d.ts +4 -0
- package/dist/legal-terms/legal-term-preview.dto.d.ts.map +1 -1
- package/dist/legal-terms/legal-term-preview.dto.js +13 -1
- package/package.json +29 -29
- package/src/analytics/analytics-kafka-topics.ts +24 -24
- package/src/analytics/create-tenant-audit-log.dto.ts +105 -105
- package/src/analytics/index.ts +8 -8
- package/src/analytics/list-tenant-audit-logs-query.dto.ts +45 -45
- package/src/auth/auth-kafka.payloads.ts +218 -218
- package/src/auth/change-own-password.dto.ts +34 -34
- package/src/auth/index.ts +28 -28
- package/src/auth/login-2fa.dto.ts +14 -14
- package/src/auth/password-reset-finalize-2fa.dto.ts +36 -36
- package/src/auth/request-password-reset-response.dto.ts +26 -26
- package/src/auth/revoke-device-session.dto.ts +19 -19
- package/src/auth/totp-user.dto.ts +58 -58
- package/src/configurations/app-module-policy.dto.ts +72 -72
- package/src/configurations/app-module-policy.enums.ts +30 -30
- package/src/configurations/configuration-tenant-summary.dto.ts +79 -79
- package/src/configurations/index.ts +13 -13
- package/src/legal-terms/legal-term-dispatch.dto.ts +12 -1
- package/src/legal-terms/legal-term-preview.dto.ts +15 -1
- package/src/storage/presign-download-rpc.dto.ts +38 -38
- package/src/storage/storage-rmq-patterns.ts +5 -5
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
name: Publish packages
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch:
|
|
5
|
-
push:
|
|
6
|
-
tags:
|
|
7
|
-
- 'v*.*.*'
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
build:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
permissions:
|
|
13
|
-
contents: read
|
|
14
|
-
id-token: write
|
|
15
|
-
steps:
|
|
16
|
-
- uses: actions/checkout@v5
|
|
17
|
-
- uses: actions/setup-node@v4
|
|
18
|
-
with:
|
|
19
|
-
node-version: '20'
|
|
20
|
-
registry-url: 'https://registry.npmjs.org'
|
|
21
|
-
cache: npm
|
|
22
|
-
- run: npm ci
|
|
23
|
-
- run: npm publish --provenance --access public
|
|
24
|
-
env:
|
|
25
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
1
|
+
name: Publish packages
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- 'v*.*.*'
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
id-token: write
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v5
|
|
17
|
+
- uses: actions/setup-node@v4
|
|
18
|
+
with:
|
|
19
|
+
node-version: '20'
|
|
20
|
+
registry-url: 'https://registry.npmjs.org'
|
|
21
|
+
cache: npm
|
|
22
|
+
- run: npm ci
|
|
23
|
+
- run: npm publish --provenance --access public
|
|
24
|
+
env:
|
|
25
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
/** Status do registro de envio na clínica (WhatsApp / fluxo). */
|
|
2
2
|
export type LegalTermDispatchStatusValue = 'created' | 'sent' | 'failed';
|
|
3
3
|
/** Status do documento na Clicksign (signature-service). */
|
|
4
|
-
export type SignatureDocumentStatusValue = 'pending' | 'signed' | 'refused' | 'cancelled' | 'expired'
|
|
4
|
+
export type SignatureDocumentStatusValue = 'pending' | 'signed' | 'refused' | 'cancelled' | 'expired'
|
|
5
|
+
/** Fluxo impresso: aguardando upload da digitalização assinada (sem registro em signature-service). */
|
|
6
|
+
| 'upload_required';
|
|
7
|
+
/** Método de assinatura escolhido no envio do termo. */
|
|
8
|
+
export type LegalTermSignatureMethodValue = 'digital' | 'printed';
|
|
9
|
+
/** Política por tenant (admin): quais métodos o produto oferece. */
|
|
10
|
+
export type LegalTermSignaturePolicyValue = 'printed_only' | 'printed_and_integrations';
|
|
5
11
|
/** Item agregado para a ficha do paciente (API: clinic + signature). */
|
|
6
12
|
export type PatientLegalTermDispatchItemDto = {
|
|
7
13
|
id: string;
|
|
@@ -10,6 +16,7 @@ export type PatientLegalTermDispatchItemDto = {
|
|
|
10
16
|
procedure_names: string[];
|
|
11
17
|
dispatch_status: LegalTermDispatchStatusValue;
|
|
12
18
|
error_code: string | null;
|
|
19
|
+
signature_method: LegalTermSignatureMethodValue;
|
|
13
20
|
signature_document_id: string | null;
|
|
14
21
|
signature_status: SignatureDocumentStatusValue | null;
|
|
15
22
|
signed_at: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"legal-term-dispatch.dto.d.ts","sourceRoot":"","sources":["../../src/legal-terms/legal-term-dispatch.dto.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,MAAM,MAAM,4BAA4B,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEzE,4DAA4D;AAC5D,MAAM,MAAM,4BAA4B,GACpC,SAAS,GACT,QAAQ,GACR,SAAS,GACT,WAAW,GACX,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"legal-term-dispatch.dto.d.ts","sourceRoot":"","sources":["../../src/legal-terms/legal-term-dispatch.dto.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,MAAM,MAAM,4BAA4B,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEzE,4DAA4D;AAC5D,MAAM,MAAM,4BAA4B,GACpC,SAAS,GACT,QAAQ,GACR,SAAS,GACT,WAAW,GACX,SAAS;AACX,uGAAuG;GACrG,iBAAiB,CAAC;AAEtB,wDAAwD;AACxD,MAAM,MAAM,6BAA6B,GAAG,SAAS,GAAG,SAAS,CAAC;AAElE,oEAAoE;AACpE,MAAM,MAAM,6BAA6B,GACrC,cAAc,GACd,0BAA0B,CAAC;AAE/B,wEAAwE;AACxE,MAAM,MAAM,+BAA+B,GAAG;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,4BAA4B,CAAC;IAC9C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gBAAgB,EAAE,6BAA6B,CAAC;IAChD,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,gBAAgB,EAAE,4BAA4B,GAAG,IAAI,CAAC;IACtD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,EAAE,OAAO,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,qCAAqC,GAAG;IAClD,KAAK,EAAE,+BAA+B,EAAE,CAAC;CAC1C,CAAC"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type LegalTermBodyFormat } from './legal-term-body-format';
|
|
2
|
+
declare const LEGAL_TERM_SIGNATURE_METHODS: readonly ["digital", "printed"];
|
|
3
|
+
export type LegalTermSignatureMethodDto = (typeof LEGAL_TERM_SIGNATURE_METHODS)[number];
|
|
2
4
|
/** Valores explícitos para substituição na pré-visualização (sem inferência heurística). */
|
|
3
5
|
export declare class LegalTermPreviewRequestDto {
|
|
4
6
|
body_html?: string;
|
|
@@ -10,6 +12,7 @@ export declare class LegalTermPreviewRequestDto {
|
|
|
10
12
|
data_hora_iso?: string;
|
|
11
13
|
}
|
|
12
14
|
export declare class LegalTermSendDto {
|
|
15
|
+
signatureMethod?: LegalTermSignatureMethodDto;
|
|
13
16
|
procedureIds: string[];
|
|
14
17
|
whatsappMessage: string;
|
|
15
18
|
signerEmail?: string;
|
|
@@ -21,4 +24,5 @@ export declare class LegalTermSendDto {
|
|
|
21
24
|
tenantSignerDocumentation?: string;
|
|
22
25
|
tenantSignerPhone?: string;
|
|
23
26
|
}
|
|
27
|
+
export {};
|
|
24
28
|
//# sourceMappingURL=legal-term-preview.dto.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"legal-term-preview.dto.d.ts","sourceRoot":"","sources":["../../src/legal-terms/legal-term-preview.dto.ts"],"names":[],"mappings":"AAcA,OAAO,EAA2B,KAAK,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE7F,4FAA4F;AAC5F,qBAAa,0BAA0B;IAQrC,SAAS,CAAC,EAAE,MAAM,CAAC;IAQnB,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAMlC,aAAa,CAAC,EAAE,MAAM,CAAC;IAMvB,WAAW,CAAC,EAAE,MAAM,CAAC;IAMrB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAU9B,+BAA+B,CAAC,EAAE,MAAM,EAAE,CAAC;IAM3C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,gBAAgB;
|
|
1
|
+
{"version":3,"file":"legal-term-preview.dto.d.ts","sourceRoot":"","sources":["../../src/legal-terms/legal-term-preview.dto.ts"],"names":[],"mappings":"AAcA,OAAO,EAA2B,KAAK,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE7F,QAAA,MAAM,4BAA4B,iCAAkC,CAAC;AACrE,MAAM,MAAM,2BAA2B,GAAG,CAAC,OAAO,4BAA4B,CAAC,CAAC,MAAM,CAAC,CAAC;AAExF,4FAA4F;AAC5F,qBAAa,0BAA0B;IAQrC,SAAS,CAAC,EAAE,MAAM,CAAC;IAQnB,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAMlC,aAAa,CAAC,EAAE,MAAM,CAAC;IAMvB,WAAW,CAAC,EAAE,MAAM,CAAC;IAMrB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAU9B,+BAA+B,CAAC,EAAE,MAAM,EAAE,CAAC;IAM3C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,gBAAgB;IAS3B,eAAe,CAAC,EAAE,2BAA2B,CAAC;IAK9C,YAAY,EAAE,MAAM,EAAE,CAAC;IAUvB,eAAe,EAAE,MAAM,CAAC;IAMxB,WAAW,CAAC,EAAE,MAAM,CAAC;IASrB,WAAW,CAAC,EAAE,MAAM,CAAC;IAQrB,cAAc,CAAC,EAAE,OAAO,CAAC;IAMzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAK1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAO3B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAM9B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IAWnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B"}
|
|
@@ -13,6 +13,7 @@ exports.LegalTermSendDto = exports.LegalTermPreviewRequestDto = void 0;
|
|
|
13
13
|
const swagger_1 = require("@nestjs/swagger");
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
15
|
const legal_term_body_format_1 = require("./legal-term-body-format");
|
|
16
|
+
const LEGAL_TERM_SIGNATURE_METHODS = ['digital', 'printed'];
|
|
16
17
|
/** Valores explícitos para substituição na pré-visualização (sem inferência heurística). */
|
|
17
18
|
class LegalTermPreviewRequestDto {
|
|
18
19
|
body_html;
|
|
@@ -82,6 +83,7 @@ __decorate([
|
|
|
82
83
|
__metadata("design:type", String)
|
|
83
84
|
], LegalTermPreviewRequestDto.prototype, "data_hora_iso", void 0);
|
|
84
85
|
class LegalTermSendDto {
|
|
86
|
+
signatureMethod;
|
|
85
87
|
procedureIds;
|
|
86
88
|
whatsappMessage;
|
|
87
89
|
signerEmail;
|
|
@@ -94,6 +96,16 @@ class LegalTermSendDto {
|
|
|
94
96
|
tenantSignerPhone;
|
|
95
97
|
}
|
|
96
98
|
exports.LegalTermSendDto = LegalTermSendDto;
|
|
99
|
+
__decorate([
|
|
100
|
+
(0, swagger_1.ApiPropertyOptional)({
|
|
101
|
+
enum: LEGAL_TERM_SIGNATURE_METHODS,
|
|
102
|
+
description: 'Método de assinatura: digital (Clicksign + link no WhatsApp) ou printed (PDF para impressão, sem Clicksign). Padrão: digital.',
|
|
103
|
+
default: 'digital',
|
|
104
|
+
}),
|
|
105
|
+
(0, class_validator_1.IsOptional)(),
|
|
106
|
+
(0, class_validator_1.IsIn)(LEGAL_TERM_SIGNATURE_METHODS),
|
|
107
|
+
__metadata("design:type", String)
|
|
108
|
+
], LegalTermSendDto.prototype, "signatureMethod", void 0);
|
|
97
109
|
__decorate([
|
|
98
110
|
(0, swagger_1.ApiProperty)({ type: [String], format: 'uuid' }),
|
|
99
111
|
(0, class_validator_1.IsArray)(),
|
|
@@ -102,7 +114,7 @@ __decorate([
|
|
|
102
114
|
], LegalTermSendDto.prototype, "procedureIds", void 0);
|
|
103
115
|
__decorate([
|
|
104
116
|
(0, swagger_1.ApiProperty)({
|
|
105
|
-
description: 'Mensagem WhatsApp
|
|
117
|
+
description: 'Mensagem WhatsApp. Com signatureMethod digital (padrão), deve conter exatamente {{ link_termo_juridico }}. Com printed, qualquer texto (sem esse placeholder).',
|
|
106
118
|
example: 'Olá, assine seu termo: {{ link_termo_juridico }}',
|
|
107
119
|
}),
|
|
108
120
|
(0, class_validator_1.IsString)(),
|
package/package.json
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "tychat-contracts",
|
|
3
|
-
"version": "1.6.
|
|
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.9",
|
|
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
|
+
}
|
package/src/analytics/index.ts
CHANGED
|
@@ -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
|
+
}
|