evo360-types 1.3.656 → 1.3.662
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/apps/evo-csq/zod-schemas.d.ts +40 -40
- package/dist/apps/evo-modules/zod-schemas.d.ts +446 -0
- package/dist/apps/evo-modules/zod-schemas.js +143 -0
- package/dist/apps/evo-modules/zod-schemas.ts +153 -0
- package/dist/apps/evo-task/zod-schemas.d.ts +201 -4
- package/dist/apps/evo-task/zod-schemas.js +22 -2
- package/dist/apps/evo-task/zod-schemas.ts +23 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.ts +2 -0
- package/dist/types/evo-modules/activation.d.ts +46 -0
- package/dist/types/evo-modules/activation.js +131 -0
- package/dist/types/evo-modules/activation.ts +150 -0
- package/dist/types/evo-modules/catalog.d.ts +28 -0
- package/dist/types/evo-modules/catalog.js +130 -0
- package/dist/types/evo-modules/catalog.ts +131 -0
- package/dist/types/evo-modules/index.d.ts +227 -0
- package/dist/types/evo-modules/index.js +75 -0
- package/dist/types/evo-modules/index.ts +329 -0
- package/dist/types/evo-task/index.d.ts +14 -0
- package/dist/types/evo-task/index.js +3 -0
- package/dist/types/evo-task/index.ts +25 -0
- package/dist/types/evo-task-runner/index.d.ts +2 -1
- package/dist/types/evo-task-runner/index.ts +5 -1
- package/dist/types/evo-telemedicine/fb_collections.js +1 -1
- package/dist/types/evo-telemedicine/fb_collections.ts +1 -1
- package/dist/types/evo-telemedicine/index.d.ts +8 -12
- package/dist/types/evo-telemedicine/index.ts +8 -12
- package/dist/types/evo-tenant/index.ts +3 -1
- package/fixtures/tenant-modules/is-module-active.parity.json +364 -0
- package/package.json +7 -4
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import type { IFireDoc, IFireGlobalDoc } from "../shared";
|
|
2
|
+
import type { ITenantModuleEntitlement, TenantModuleSource, TenantModuleStatus } from "../evo-tenant";
|
|
3
|
+
import type { EntitlementAuditAction, IEntitlementAuditActor } from "../evo-telemedicine";
|
|
4
|
+
export * from "./catalog";
|
|
5
|
+
export * from "./activation";
|
|
6
|
+
export declare const EVO_MODULES_APP = "evo-modules";
|
|
7
|
+
export declare const MODULES_ENTITLEMENT_AUDIT_COLLECTION = "entitlement-audit";
|
|
8
|
+
export declare const MODULES_PROVISIONING_COLLECTION = "provisioning";
|
|
9
|
+
export declare const MODULES_ROLLOUT_PLATFORM_PATH = "platform/evo-modules/rollout";
|
|
10
|
+
/** TTL do lock por tenant+módulo durante um apply. */
|
|
11
|
+
export declare const MODULES_LOCK_TTL_MS: number;
|
|
12
|
+
/** Regex da chave de módulo (`tenants/{t}.modules[key]`). */
|
|
13
|
+
export declare const MODULE_KEY_PATTERN: RegExp;
|
|
14
|
+
export type ModuleAction = "enable" | "disable" | "trial" | "override";
|
|
15
|
+
export declare const ModuleActionEnum: {
|
|
16
|
+
readonly Enable: "enable";
|
|
17
|
+
readonly Disable: "disable";
|
|
18
|
+
readonly Trial: "trial";
|
|
19
|
+
readonly Override: "override";
|
|
20
|
+
};
|
|
21
|
+
export type ModuleStepKind = "entitlement" | "rbac_group" | "rbac_recompute" | "contract_allowance" | "contract_check" | "rollout_check";
|
|
22
|
+
export declare const ModuleStepKindEnum: {
|
|
23
|
+
readonly Entitlement: "entitlement";
|
|
24
|
+
readonly RbacGroup: "rbac_group";
|
|
25
|
+
readonly RbacRecompute: "rbac_recompute";
|
|
26
|
+
readonly ContractAllowance: "contract_allowance";
|
|
27
|
+
readonly ContractCheck: "contract_check";
|
|
28
|
+
readonly RolloutCheck: "rollout_check";
|
|
29
|
+
};
|
|
30
|
+
export declare const MODULE_STEP_KINDS: readonly ModuleStepKind[];
|
|
31
|
+
export interface IModuleRolloutDescriptor {
|
|
32
|
+
/** Path completo do doc (4 segmentos: `platform/<app>/<col>/<doc>`). */
|
|
33
|
+
path: string;
|
|
34
|
+
/**
|
|
35
|
+
* `flags_map`: doc genérico `{ flags: { [flag]: boolean }, emergency_kill }`.
|
|
36
|
+
* `legacy_fields`: doc com um campo booleano por flag (telemedicina).
|
|
37
|
+
*/
|
|
38
|
+
layout: "flags_map" | "legacy_fields";
|
|
39
|
+
/** flag -> campo do doc (`legacy_fields`) ou chave em `flags` (`flags_map`). */
|
|
40
|
+
flags: Record<string, string>;
|
|
41
|
+
}
|
|
42
|
+
export interface IModuleCapabilityDefinition {
|
|
43
|
+
label: string;
|
|
44
|
+
default: boolean | number | string;
|
|
45
|
+
}
|
|
46
|
+
export interface IModuleAllowanceMetric {
|
|
47
|
+
/** Chave de `NexFinopsMetricCatalog`. */
|
|
48
|
+
metric: string;
|
|
49
|
+
/** Gravado no contrato vigente quando a chave está ausente (Q6). */
|
|
50
|
+
default_included: number;
|
|
51
|
+
}
|
|
52
|
+
export interface IPlatformModuleDefinition {
|
|
53
|
+
/** `MODULE_KEY_PATTERN`; é a chave em `tenants/{t}.modules`. */
|
|
54
|
+
key: string;
|
|
55
|
+
label: string;
|
|
56
|
+
description?: string;
|
|
57
|
+
/** App do Firestore onde vivem os dados do módulo (`evo-telemedicine`, `evo-csq`). */
|
|
58
|
+
app_id: string;
|
|
59
|
+
capabilities: Record<string, IModuleCapabilityDefinition>;
|
|
60
|
+
/** Status/origem gravados no `enable` de um tenant sem entitlement. */
|
|
61
|
+
default_entitlement: {
|
|
62
|
+
status: TenantModuleStatus;
|
|
63
|
+
source: TenantModuleSource;
|
|
64
|
+
};
|
|
65
|
+
/** Tenant novo nasce com o módulo (`createTenant`). */
|
|
66
|
+
default_for_new_tenants: boolean;
|
|
67
|
+
/** Grupos RBAC globais que tornam os papéis do módulo atribuíveis. */
|
|
68
|
+
rbac_groups: string[];
|
|
69
|
+
allowance_metrics: IModuleAllowanceMetric[];
|
|
70
|
+
rollout: IModuleRolloutDescriptor | null;
|
|
71
|
+
depends_on: string[];
|
|
72
|
+
provisioning: {
|
|
73
|
+
enable: ModuleStepKind[];
|
|
74
|
+
disable: ModuleStepKind[];
|
|
75
|
+
};
|
|
76
|
+
legacy?: {
|
|
77
|
+
/** Trilhas antigas (relativas a `tenants/{t}/`), lidas pelo histórico e nunca escritas. */
|
|
78
|
+
audit_collections?: string[];
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export type ModuleStepStatus = "pending" | "noop" | "change" | "done" | "failed" | "blocked" | "skipped";
|
|
82
|
+
export interface IModuleProvisioningStep {
|
|
83
|
+
kind: ModuleStepKind;
|
|
84
|
+
status: ModuleStepStatus;
|
|
85
|
+
summary: string;
|
|
86
|
+
before?: unknown;
|
|
87
|
+
after?: unknown;
|
|
88
|
+
error?: string | null;
|
|
89
|
+
started_at?: Date | null;
|
|
90
|
+
finished_at?: Date | null;
|
|
91
|
+
}
|
|
92
|
+
export type ModuleRunMode = "plan" | "apply";
|
|
93
|
+
export type ModuleRunStatus = "planned" | "running" | "done" | "failed" | "blocked" | "superseded";
|
|
94
|
+
export interface IModuleChangeParams {
|
|
95
|
+
/** `trial`: obrigatório. */
|
|
96
|
+
expires_at?: Date | null;
|
|
97
|
+
/** `override`: obrigatório. */
|
|
98
|
+
override_until?: Date | null;
|
|
99
|
+
/** `enable`: libera o passo `contract_allowance` quando ele vem `blocked` (Q6). */
|
|
100
|
+
allow_without_contract?: boolean;
|
|
101
|
+
/** `disable`: remove o grupo RBAC se nenhum outro módulo ativo o declara (Q7). */
|
|
102
|
+
purge_rbac?: boolean;
|
|
103
|
+
/** `disable`: grava `suspended` em vez de `cancelled`. */
|
|
104
|
+
suspend?: boolean;
|
|
105
|
+
}
|
|
106
|
+
export interface IModuleRunActor extends IEntitlementAuditActor {
|
|
107
|
+
login_id?: string;
|
|
108
|
+
}
|
|
109
|
+
export interface IModuleProvisioningRun extends IFireDoc {
|
|
110
|
+
tenant: string;
|
|
111
|
+
module: string;
|
|
112
|
+
action: ModuleAction;
|
|
113
|
+
mode: ModuleRunMode;
|
|
114
|
+
status: ModuleRunStatus;
|
|
115
|
+
params: IModuleChangeParams;
|
|
116
|
+
/** Hash estável dos passos planejados (kind+status+after). Muda ⇒ `PLAN_DRIFT`. */
|
|
117
|
+
plan_hash: string;
|
|
118
|
+
/** `PLATFORM_MODULE_CATALOG_VERSION` de quem planejou/aplicou. */
|
|
119
|
+
types_version: string;
|
|
120
|
+
steps: IModuleProvisioningStep[];
|
|
121
|
+
actor: IModuleRunActor;
|
|
122
|
+
reason: string;
|
|
123
|
+
/** Run `apply` que este retoma. */
|
|
124
|
+
resumed_from?: string | null;
|
|
125
|
+
/** Run `plan` que originou este `apply`. */
|
|
126
|
+
plan_run_id?: string | null;
|
|
127
|
+
error?: string | null;
|
|
128
|
+
finished_at?: Date | null;
|
|
129
|
+
}
|
|
130
|
+
/** Lock no doc `tenants/{t}/apps/evo-modules`, campo `locks.{module}`. */
|
|
131
|
+
export interface IModuleLock {
|
|
132
|
+
run_id: string;
|
|
133
|
+
expires_at: Date;
|
|
134
|
+
}
|
|
135
|
+
export interface IModuleRolloutDoc extends IFireGlobalDoc {
|
|
136
|
+
flags: Record<string, boolean>;
|
|
137
|
+
emergency_kill: boolean;
|
|
138
|
+
updated_at: Date;
|
|
139
|
+
updated_by: string;
|
|
140
|
+
}
|
|
141
|
+
/** Estado de rollout normalizado (o mesmo para os dois layouts). */
|
|
142
|
+
export interface IModuleRolloutState {
|
|
143
|
+
module: string;
|
|
144
|
+
path: string;
|
|
145
|
+
/** `false` ⇒ doc ausente/ilegível: tudo negado. */
|
|
146
|
+
exists: boolean;
|
|
147
|
+
flags: Record<string, boolean>;
|
|
148
|
+
emergency_kill: boolean;
|
|
149
|
+
updated_at: Date | null;
|
|
150
|
+
updated_by: string | null;
|
|
151
|
+
}
|
|
152
|
+
export interface IModuleEntitlementAudit extends IFireDoc {
|
|
153
|
+
module: string;
|
|
154
|
+
action: EntitlementAuditAction;
|
|
155
|
+
before?: ITenantModuleEntitlement | null;
|
|
156
|
+
after: ITenantModuleEntitlement;
|
|
157
|
+
actor: IEntitlementAuditActor;
|
|
158
|
+
reason: string;
|
|
159
|
+
occurred_at: Date;
|
|
160
|
+
correlation_id?: string;
|
|
161
|
+
run_id?: string;
|
|
162
|
+
}
|
|
163
|
+
export interface IModuleStepContext {
|
|
164
|
+
tenant: string;
|
|
165
|
+
module: IPlatformModuleDefinition;
|
|
166
|
+
action: ModuleAction;
|
|
167
|
+
params: IModuleChangeParams;
|
|
168
|
+
actor_user_id: string | null;
|
|
169
|
+
/** Passos anteriores do mesmo run (estado corrente). */
|
|
170
|
+
previous_steps?: IModuleProvisioningStep[];
|
|
171
|
+
}
|
|
172
|
+
export type ModuleStepPlanResult = Pick<IModuleProvisioningStep, "status" | "summary" | "before" | "after">;
|
|
173
|
+
export type ModuleStepApplyResult = Pick<IModuleProvisioningStep, "status" | "summary" | "after">;
|
|
174
|
+
export interface IModuleStepExecutor {
|
|
175
|
+
plan(ctx: IModuleStepContext): Promise<ModuleStepPlanResult>;
|
|
176
|
+
apply(ctx: IModuleStepContext): Promise<ModuleStepApplyResult>;
|
|
177
|
+
}
|
|
178
|
+
export interface IModuleChangeRequest {
|
|
179
|
+
tenant: string;
|
|
180
|
+
module: string;
|
|
181
|
+
action: ModuleAction;
|
|
182
|
+
params?: IModuleChangeParams;
|
|
183
|
+
reason: string;
|
|
184
|
+
}
|
|
185
|
+
export interface IModuleApplyRequest {
|
|
186
|
+
tenant: string;
|
|
187
|
+
/** Aplica o plano deste run (`mode: 'plan'`). Exclusivo com `resume_run_id`. */
|
|
188
|
+
plan_run_id?: string;
|
|
189
|
+
/** Retoma um run `apply` em `failed`/`blocked`. */
|
|
190
|
+
resume_run_id?: string;
|
|
191
|
+
/** Sobrepõe params do plano (só `allow_without_contract` faz sentido aqui). */
|
|
192
|
+
params?: Pick<IModuleChangeParams, "allow_without_contract">;
|
|
193
|
+
}
|
|
194
|
+
export interface IModuleOverviewRequest {
|
|
195
|
+
tenant: string;
|
|
196
|
+
}
|
|
197
|
+
export interface IModuleOverviewEntry {
|
|
198
|
+
definition: IPlatformModuleDefinition;
|
|
199
|
+
entitlement: ITenantModuleEntitlement | null;
|
|
200
|
+
active: boolean;
|
|
201
|
+
rollout: IModuleRolloutState | null;
|
|
202
|
+
}
|
|
203
|
+
export interface IModuleOverviewResponse {
|
|
204
|
+
ok: true;
|
|
205
|
+
tenant: string;
|
|
206
|
+
catalog_version: string;
|
|
207
|
+
modules: IModuleOverviewEntry[];
|
|
208
|
+
/** Últimos 10 runs (plan e apply), mais recentes primeiro. */
|
|
209
|
+
runs: IModuleProvisioningRun[];
|
|
210
|
+
/** Últimas 30 entradas de auditoria (caminho genérico + legados), por `occurred_at` desc. */
|
|
211
|
+
audit: IModuleEntitlementAudit[];
|
|
212
|
+
}
|
|
213
|
+
export interface IModulePlanResponse {
|
|
214
|
+
ok: true;
|
|
215
|
+
run: IModuleProvisioningRun;
|
|
216
|
+
}
|
|
217
|
+
export type ModuleApplyErrorCode = "PLAN_DRIFT" | "MODULE_LOCKED" | "RUN_NOT_FOUND" | "RUN_NOT_RESUMABLE";
|
|
218
|
+
export type IModuleApplyResponse = {
|
|
219
|
+
ok: true;
|
|
220
|
+
run: IModuleProvisioningRun;
|
|
221
|
+
}
|
|
222
|
+
/** O estado mudou desde o plano: `plan` é o run novo (`mode: 'plan'`) para revisar. */
|
|
223
|
+
| {
|
|
224
|
+
ok: false;
|
|
225
|
+
error: "PLAN_DRIFT";
|
|
226
|
+
plan: IModuleProvisioningRun;
|
|
227
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ======================================================
|
|
3
|
+
// evo-modules (feat-263 — Módulos da plataforma)
|
|
4
|
+
//
|
|
5
|
+
// Entitlement de módulos por tenant: "este cliente tem direito ao módulo X?".
|
|
6
|
+
// NÃO é feature flag: o kill switch operacional de cada módulo é o `rollout`
|
|
7
|
+
// (doc de plataforma), um gate independente.
|
|
8
|
+
//
|
|
9
|
+
// Storage do estado continua em `tenants/{t}.modules[key]`
|
|
10
|
+
// (`ITenantModuleEntitlement`, feat-160 D5). Este namespace acrescenta:
|
|
11
|
+
// - o catálogo em código (`PLATFORM_MODULE_CATALOG`), que carrega
|
|
12
|
+
// comportamento (passos de provisionamento, grupos RBAC, métricas de franquia);
|
|
13
|
+
// - a decisão única `isModuleActive` / `hasModuleCapability`, usada por
|
|
14
|
+
// backend, web-app e Nexus (o Flutter espelha pela fixture de paridade);
|
|
15
|
+
// - os tipos do run de provisionamento, do doc de rollout genérico e da
|
|
16
|
+
// auditoria genérica.
|
|
17
|
+
//
|
|
18
|
+
// Firestore (por tenant):
|
|
19
|
+
// - App doc (locks): /tenants/{t}/apps/evo-modules campo `locks.{module}`
|
|
20
|
+
// - Auditoria: /tenants/{t}/apps/evo-modules/entitlement-audit/{id}
|
|
21
|
+
// - Provisionamento: /tenants/{t}/apps/evo-modules/provisioning/{runId}
|
|
22
|
+
//
|
|
23
|
+
// Plataforma (só backend):
|
|
24
|
+
// - Rollout genérico: /platform/evo-modules/rollout/{module}
|
|
25
|
+
// (a telemedicina continua em `platform/evo-telemedicine/config/rollout`,
|
|
26
|
+
// lida pelo mesmo reader via `rollout.layout = 'legacy_fields'`).
|
|
27
|
+
// ======================================================
|
|
28
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
29
|
+
if (k2 === undefined) k2 = k;
|
|
30
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
31
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
32
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
33
|
+
}
|
|
34
|
+
Object.defineProperty(o, k2, desc);
|
|
35
|
+
}) : (function(o, m, k, k2) {
|
|
36
|
+
if (k2 === undefined) k2 = k;
|
|
37
|
+
o[k2] = m[k];
|
|
38
|
+
}));
|
|
39
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
40
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
41
|
+
};
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.MODULE_STEP_KINDS = exports.ModuleStepKindEnum = exports.ModuleActionEnum = exports.MODULE_KEY_PATTERN = exports.MODULES_LOCK_TTL_MS = exports.MODULES_ROLLOUT_PLATFORM_PATH = exports.MODULES_PROVISIONING_COLLECTION = exports.MODULES_ENTITLEMENT_AUDIT_COLLECTION = exports.EVO_MODULES_APP = void 0;
|
|
44
|
+
__exportStar(require("./catalog"), exports);
|
|
45
|
+
__exportStar(require("./activation"), exports);
|
|
46
|
+
exports.EVO_MODULES_APP = "evo-modules";
|
|
47
|
+
exports.MODULES_ENTITLEMENT_AUDIT_COLLECTION = "entitlement-audit";
|
|
48
|
+
exports.MODULES_PROVISIONING_COLLECTION = "provisioning";
|
|
49
|
+
exports.MODULES_ROLLOUT_PLATFORM_PATH = "platform/evo-modules/rollout";
|
|
50
|
+
/** TTL do lock por tenant+módulo durante um apply. */
|
|
51
|
+
exports.MODULES_LOCK_TTL_MS = 10 * 60 * 1000;
|
|
52
|
+
/** Regex da chave de módulo (`tenants/{t}.modules[key]`). */
|
|
53
|
+
exports.MODULE_KEY_PATTERN = /^[a-z][a-z0-9_]{1,40}$/;
|
|
54
|
+
exports.ModuleActionEnum = {
|
|
55
|
+
Enable: "enable",
|
|
56
|
+
Disable: "disable",
|
|
57
|
+
Trial: "trial",
|
|
58
|
+
Override: "override",
|
|
59
|
+
};
|
|
60
|
+
exports.ModuleStepKindEnum = {
|
|
61
|
+
Entitlement: "entitlement",
|
|
62
|
+
RbacGroup: "rbac_group",
|
|
63
|
+
RbacRecompute: "rbac_recompute",
|
|
64
|
+
ContractAllowance: "contract_allowance",
|
|
65
|
+
ContractCheck: "contract_check",
|
|
66
|
+
RolloutCheck: "rollout_check",
|
|
67
|
+
};
|
|
68
|
+
exports.MODULE_STEP_KINDS = [
|
|
69
|
+
"entitlement",
|
|
70
|
+
"rbac_group",
|
|
71
|
+
"rbac_recompute",
|
|
72
|
+
"contract_allowance",
|
|
73
|
+
"contract_check",
|
|
74
|
+
"rollout_check",
|
|
75
|
+
];
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
// ======================================================
|
|
2
|
+
// evo-modules (feat-263 — Módulos da plataforma)
|
|
3
|
+
//
|
|
4
|
+
// Entitlement de módulos por tenant: "este cliente tem direito ao módulo X?".
|
|
5
|
+
// NÃO é feature flag: o kill switch operacional de cada módulo é o `rollout`
|
|
6
|
+
// (doc de plataforma), um gate independente.
|
|
7
|
+
//
|
|
8
|
+
// Storage do estado continua em `tenants/{t}.modules[key]`
|
|
9
|
+
// (`ITenantModuleEntitlement`, feat-160 D5). Este namespace acrescenta:
|
|
10
|
+
// - o catálogo em código (`PLATFORM_MODULE_CATALOG`), que carrega
|
|
11
|
+
// comportamento (passos de provisionamento, grupos RBAC, métricas de franquia);
|
|
12
|
+
// - a decisão única `isModuleActive` / `hasModuleCapability`, usada por
|
|
13
|
+
// backend, web-app e Nexus (o Flutter espelha pela fixture de paridade);
|
|
14
|
+
// - os tipos do run de provisionamento, do doc de rollout genérico e da
|
|
15
|
+
// auditoria genérica.
|
|
16
|
+
//
|
|
17
|
+
// Firestore (por tenant):
|
|
18
|
+
// - App doc (locks): /tenants/{t}/apps/evo-modules campo `locks.{module}`
|
|
19
|
+
// - Auditoria: /tenants/{t}/apps/evo-modules/entitlement-audit/{id}
|
|
20
|
+
// - Provisionamento: /tenants/{t}/apps/evo-modules/provisioning/{runId}
|
|
21
|
+
//
|
|
22
|
+
// Plataforma (só backend):
|
|
23
|
+
// - Rollout genérico: /platform/evo-modules/rollout/{module}
|
|
24
|
+
// (a telemedicina continua em `platform/evo-telemedicine/config/rollout`,
|
|
25
|
+
// lida pelo mesmo reader via `rollout.layout = 'legacy_fields'`).
|
|
26
|
+
// ======================================================
|
|
27
|
+
|
|
28
|
+
import type { IFireDoc, IFireGlobalDoc } from "../shared";
|
|
29
|
+
import type {
|
|
30
|
+
ITenantModuleEntitlement,
|
|
31
|
+
TenantModuleSource,
|
|
32
|
+
TenantModuleStatus,
|
|
33
|
+
} from "../evo-tenant";
|
|
34
|
+
import type {
|
|
35
|
+
EntitlementAuditAction,
|
|
36
|
+
IEntitlementAuditActor,
|
|
37
|
+
} from "../evo-telemedicine";
|
|
38
|
+
|
|
39
|
+
export * from "./catalog";
|
|
40
|
+
export * from "./activation";
|
|
41
|
+
|
|
42
|
+
export const EVO_MODULES_APP = "evo-modules";
|
|
43
|
+
export const MODULES_ENTITLEMENT_AUDIT_COLLECTION = "entitlement-audit";
|
|
44
|
+
export const MODULES_PROVISIONING_COLLECTION = "provisioning";
|
|
45
|
+
export const MODULES_ROLLOUT_PLATFORM_PATH = "platform/evo-modules/rollout";
|
|
46
|
+
/** TTL do lock por tenant+módulo durante um apply. */
|
|
47
|
+
export const MODULES_LOCK_TTL_MS = 10 * 60 * 1000;
|
|
48
|
+
|
|
49
|
+
/** Regex da chave de módulo (`tenants/{t}.modules[key]`). */
|
|
50
|
+
export const MODULE_KEY_PATTERN = /^[a-z][a-z0-9_]{1,40}$/;
|
|
51
|
+
|
|
52
|
+
export type ModuleAction = "enable" | "disable" | "trial" | "override";
|
|
53
|
+
export const ModuleActionEnum = {
|
|
54
|
+
Enable: "enable",
|
|
55
|
+
Disable: "disable",
|
|
56
|
+
Trial: "trial",
|
|
57
|
+
Override: "override",
|
|
58
|
+
} as const;
|
|
59
|
+
|
|
60
|
+
export type ModuleStepKind =
|
|
61
|
+
| "entitlement"
|
|
62
|
+
| "rbac_group"
|
|
63
|
+
| "rbac_recompute"
|
|
64
|
+
| "contract_allowance"
|
|
65
|
+
| "contract_check"
|
|
66
|
+
| "rollout_check";
|
|
67
|
+
export const ModuleStepKindEnum = {
|
|
68
|
+
Entitlement: "entitlement",
|
|
69
|
+
RbacGroup: "rbac_group",
|
|
70
|
+
RbacRecompute: "rbac_recompute",
|
|
71
|
+
ContractAllowance: "contract_allowance",
|
|
72
|
+
ContractCheck: "contract_check",
|
|
73
|
+
RolloutCheck: "rollout_check",
|
|
74
|
+
} as const;
|
|
75
|
+
export const MODULE_STEP_KINDS: readonly ModuleStepKind[] = [
|
|
76
|
+
"entitlement",
|
|
77
|
+
"rbac_group",
|
|
78
|
+
"rbac_recompute",
|
|
79
|
+
"contract_allowance",
|
|
80
|
+
"contract_check",
|
|
81
|
+
"rollout_check",
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
// ----- Catálogo
|
|
85
|
+
|
|
86
|
+
export interface IModuleRolloutDescriptor {
|
|
87
|
+
/** Path completo do doc (4 segmentos: `platform/<app>/<col>/<doc>`). */
|
|
88
|
+
path: string;
|
|
89
|
+
/**
|
|
90
|
+
* `flags_map`: doc genérico `{ flags: { [flag]: boolean }, emergency_kill }`.
|
|
91
|
+
* `legacy_fields`: doc com um campo booleano por flag (telemedicina).
|
|
92
|
+
*/
|
|
93
|
+
layout: "flags_map" | "legacy_fields";
|
|
94
|
+
/** flag -> campo do doc (`legacy_fields`) ou chave em `flags` (`flags_map`). */
|
|
95
|
+
flags: Record<string, string>;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface IModuleCapabilityDefinition {
|
|
99
|
+
label: string;
|
|
100
|
+
default: boolean | number | string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface IModuleAllowanceMetric {
|
|
104
|
+
/** Chave de `NexFinopsMetricCatalog`. */
|
|
105
|
+
metric: string;
|
|
106
|
+
/** Gravado no contrato vigente quando a chave está ausente (Q6). */
|
|
107
|
+
default_included: number;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface IPlatformModuleDefinition {
|
|
111
|
+
/** `MODULE_KEY_PATTERN`; é a chave em `tenants/{t}.modules`. */
|
|
112
|
+
key: string;
|
|
113
|
+
label: string;
|
|
114
|
+
description?: string;
|
|
115
|
+
/** App do Firestore onde vivem os dados do módulo (`evo-telemedicine`, `evo-csq`). */
|
|
116
|
+
app_id: string;
|
|
117
|
+
capabilities: Record<string, IModuleCapabilityDefinition>;
|
|
118
|
+
/** Status/origem gravados no `enable` de um tenant sem entitlement. */
|
|
119
|
+
default_entitlement: { status: TenantModuleStatus; source: TenantModuleSource };
|
|
120
|
+
/** Tenant novo nasce com o módulo (`createTenant`). */
|
|
121
|
+
default_for_new_tenants: boolean;
|
|
122
|
+
/** Grupos RBAC globais que tornam os papéis do módulo atribuíveis. */
|
|
123
|
+
rbac_groups: string[];
|
|
124
|
+
allowance_metrics: IModuleAllowanceMetric[];
|
|
125
|
+
rollout: IModuleRolloutDescriptor | null;
|
|
126
|
+
depends_on: string[];
|
|
127
|
+
provisioning: { enable: ModuleStepKind[]; disable: ModuleStepKind[] };
|
|
128
|
+
legacy?: {
|
|
129
|
+
/** Trilhas antigas (relativas a `tenants/{t}/`), lidas pelo histórico e nunca escritas. */
|
|
130
|
+
audit_collections?: string[];
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ----- Run de provisionamento: tenants/{t}/apps/evo-modules/provisioning/{runId}
|
|
135
|
+
|
|
136
|
+
export type ModuleStepStatus =
|
|
137
|
+
| "pending"
|
|
138
|
+
| "noop"
|
|
139
|
+
| "change"
|
|
140
|
+
| "done"
|
|
141
|
+
| "failed"
|
|
142
|
+
| "blocked"
|
|
143
|
+
| "skipped";
|
|
144
|
+
|
|
145
|
+
export interface IModuleProvisioningStep {
|
|
146
|
+
kind: ModuleStepKind;
|
|
147
|
+
status: ModuleStepStatus;
|
|
148
|
+
summary: string;
|
|
149
|
+
before?: unknown;
|
|
150
|
+
after?: unknown;
|
|
151
|
+
error?: string | null;
|
|
152
|
+
started_at?: Date | null;
|
|
153
|
+
finished_at?: Date | null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export type ModuleRunMode = "plan" | "apply";
|
|
157
|
+
export type ModuleRunStatus =
|
|
158
|
+
| "planned"
|
|
159
|
+
| "running"
|
|
160
|
+
| "done"
|
|
161
|
+
| "failed"
|
|
162
|
+
| "blocked"
|
|
163
|
+
| "superseded";
|
|
164
|
+
|
|
165
|
+
export interface IModuleChangeParams {
|
|
166
|
+
/** `trial`: obrigatório. */
|
|
167
|
+
expires_at?: Date | null;
|
|
168
|
+
/** `override`: obrigatório. */
|
|
169
|
+
override_until?: Date | null;
|
|
170
|
+
/** `enable`: libera o passo `contract_allowance` quando ele vem `blocked` (Q6). */
|
|
171
|
+
allow_without_contract?: boolean;
|
|
172
|
+
/** `disable`: remove o grupo RBAC se nenhum outro módulo ativo o declara (Q7). */
|
|
173
|
+
purge_rbac?: boolean;
|
|
174
|
+
/** `disable`: grava `suspended` em vez de `cancelled`. */
|
|
175
|
+
suspend?: boolean;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export interface IModuleRunActor extends IEntitlementAuditActor {
|
|
179
|
+
login_id?: string;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export interface IModuleProvisioningRun extends IFireDoc {
|
|
183
|
+
tenant: string;
|
|
184
|
+
module: string;
|
|
185
|
+
action: ModuleAction;
|
|
186
|
+
mode: ModuleRunMode;
|
|
187
|
+
status: ModuleRunStatus;
|
|
188
|
+
params: IModuleChangeParams;
|
|
189
|
+
/** Hash estável dos passos planejados (kind+status+after). Muda ⇒ `PLAN_DRIFT`. */
|
|
190
|
+
plan_hash: string;
|
|
191
|
+
/** `PLATFORM_MODULE_CATALOG_VERSION` de quem planejou/aplicou. */
|
|
192
|
+
types_version: string;
|
|
193
|
+
steps: IModuleProvisioningStep[];
|
|
194
|
+
actor: IModuleRunActor;
|
|
195
|
+
reason: string;
|
|
196
|
+
/** Run `apply` que este retoma. */
|
|
197
|
+
resumed_from?: string | null;
|
|
198
|
+
/** Run `plan` que originou este `apply`. */
|
|
199
|
+
plan_run_id?: string | null;
|
|
200
|
+
error?: string | null;
|
|
201
|
+
finished_at?: Date | null;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** Lock no doc `tenants/{t}/apps/evo-modules`, campo `locks.{module}`. */
|
|
205
|
+
export interface IModuleLock {
|
|
206
|
+
run_id: string;
|
|
207
|
+
expires_at: Date;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// ----- Rollout genérico: platform/evo-modules/rollout/{module}
|
|
211
|
+
|
|
212
|
+
export interface IModuleRolloutDoc extends IFireGlobalDoc {
|
|
213
|
+
flags: Record<string, boolean>;
|
|
214
|
+
emergency_kill: boolean;
|
|
215
|
+
updated_at: Date;
|
|
216
|
+
updated_by: string;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** Estado de rollout normalizado (o mesmo para os dois layouts). */
|
|
220
|
+
export interface IModuleRolloutState {
|
|
221
|
+
module: string;
|
|
222
|
+
path: string;
|
|
223
|
+
/** `false` ⇒ doc ausente/ilegível: tudo negado. */
|
|
224
|
+
exists: boolean;
|
|
225
|
+
flags: Record<string, boolean>;
|
|
226
|
+
emergency_kill: boolean;
|
|
227
|
+
updated_at: Date | null;
|
|
228
|
+
updated_by: string | null;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ----- Auditoria genérica: tenants/{t}/apps/evo-modules/entitlement-audit/{id}
|
|
232
|
+
|
|
233
|
+
export interface IModuleEntitlementAudit extends IFireDoc {
|
|
234
|
+
module: string;
|
|
235
|
+
action: EntitlementAuditAction;
|
|
236
|
+
before?: ITenantModuleEntitlement | null;
|
|
237
|
+
after: ITenantModuleEntitlement;
|
|
238
|
+
actor: IEntitlementAuditActor;
|
|
239
|
+
reason: string;
|
|
240
|
+
occurred_at: Date;
|
|
241
|
+
correlation_id?: string;
|
|
242
|
+
run_id?: string;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ----- Executor de passo injetável
|
|
246
|
+
//
|
|
247
|
+
// Permite que um passo seja implementado fora do `@evo/model` (ex.: a franquia
|
|
248
|
+
// no `@evo/nex-model`) sem dependência entre os packages: quem roda o runner
|
|
249
|
+
// (functions-nexus, CLI) registra o executor.
|
|
250
|
+
|
|
251
|
+
export interface IModuleStepContext {
|
|
252
|
+
tenant: string;
|
|
253
|
+
module: IPlatformModuleDefinition;
|
|
254
|
+
action: ModuleAction;
|
|
255
|
+
params: IModuleChangeParams;
|
|
256
|
+
actor_user_id: string | null;
|
|
257
|
+
/** Passos anteriores do mesmo run (estado corrente). */
|
|
258
|
+
previous_steps?: IModuleProvisioningStep[];
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export type ModuleStepPlanResult = Pick<
|
|
262
|
+
IModuleProvisioningStep,
|
|
263
|
+
"status" | "summary" | "before" | "after"
|
|
264
|
+
>;
|
|
265
|
+
export type ModuleStepApplyResult = Pick<
|
|
266
|
+
IModuleProvisioningStep,
|
|
267
|
+
"status" | "summary" | "after"
|
|
268
|
+
>;
|
|
269
|
+
|
|
270
|
+
export interface IModuleStepExecutor {
|
|
271
|
+
plan(ctx: IModuleStepContext): Promise<ModuleStepPlanResult>;
|
|
272
|
+
apply(ctx: IModuleStepContext): Promise<ModuleStepApplyResult>;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// ----- Callables do Nexus (`nex_tenants-*`)
|
|
276
|
+
//
|
|
277
|
+
// Datas atravessam o callable como ISO string.
|
|
278
|
+
|
|
279
|
+
export interface IModuleChangeRequest {
|
|
280
|
+
tenant: string;
|
|
281
|
+
module: string;
|
|
282
|
+
action: ModuleAction;
|
|
283
|
+
params?: IModuleChangeParams;
|
|
284
|
+
reason: string;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export interface IModuleApplyRequest {
|
|
288
|
+
tenant: string;
|
|
289
|
+
/** Aplica o plano deste run (`mode: 'plan'`). Exclusivo com `resume_run_id`. */
|
|
290
|
+
plan_run_id?: string;
|
|
291
|
+
/** Retoma um run `apply` em `failed`/`blocked`. */
|
|
292
|
+
resume_run_id?: string;
|
|
293
|
+
/** Sobrepõe params do plano (só `allow_without_contract` faz sentido aqui). */
|
|
294
|
+
params?: Pick<IModuleChangeParams, "allow_without_contract">;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export interface IModuleOverviewRequest {
|
|
298
|
+
tenant: string;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export interface IModuleOverviewEntry {
|
|
302
|
+
definition: IPlatformModuleDefinition;
|
|
303
|
+
entitlement: ITenantModuleEntitlement | null;
|
|
304
|
+
active: boolean;
|
|
305
|
+
rollout: IModuleRolloutState | null;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export interface IModuleOverviewResponse {
|
|
309
|
+
ok: true;
|
|
310
|
+
tenant: string;
|
|
311
|
+
catalog_version: string;
|
|
312
|
+
modules: IModuleOverviewEntry[];
|
|
313
|
+
/** Últimos 10 runs (plan e apply), mais recentes primeiro. */
|
|
314
|
+
runs: IModuleProvisioningRun[];
|
|
315
|
+
/** Últimas 30 entradas de auditoria (caminho genérico + legados), por `occurred_at` desc. */
|
|
316
|
+
audit: IModuleEntitlementAudit[];
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export interface IModulePlanResponse {
|
|
320
|
+
ok: true;
|
|
321
|
+
run: IModuleProvisioningRun;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export type ModuleApplyErrorCode = "PLAN_DRIFT" | "MODULE_LOCKED" | "RUN_NOT_FOUND" | "RUN_NOT_RESUMABLE";
|
|
325
|
+
|
|
326
|
+
export type IModuleApplyResponse =
|
|
327
|
+
| { ok: true; run: IModuleProvisioningRun }
|
|
328
|
+
/** O estado mudou desde o plano: `plan` é o run novo (`mode: 'plan'`) para revisar. */
|
|
329
|
+
| { ok: false; error: "PLAN_DRIFT"; plan: IModuleProvisioningRun };
|
|
@@ -191,6 +191,7 @@ export interface IAutoTask extends ITaskBase {
|
|
|
191
191
|
retry?: ITaskRetryPolicy;
|
|
192
192
|
on_failure?: ITaskOnFailure;
|
|
193
193
|
runner_state?: ITaskRunnerState;
|
|
194
|
+
outcome?: ITaskOutcome | null;
|
|
194
195
|
auto: ITaskAutoSpec;
|
|
195
196
|
}
|
|
196
197
|
export type ITask = IHumanTask | IAutoTask;
|
|
@@ -198,8 +199,20 @@ export declare const TaskExecutionStatusEnum: {
|
|
|
198
199
|
readonly Success: "success";
|
|
199
200
|
readonly Error: "error";
|
|
200
201
|
readonly Retry: "retry";
|
|
202
|
+
readonly Suppressed: "suppressed";
|
|
201
203
|
};
|
|
202
204
|
export type TaskExecutionStatus = (typeof TaskExecutionStatusEnum)[keyof typeof TaskExecutionStatusEnum];
|
|
205
|
+
export type TaskOutcomeClass = "legitimate" | "defect";
|
|
206
|
+
export interface ITaskOutcome {
|
|
207
|
+
class: TaskOutcomeClass;
|
|
208
|
+
reason: string;
|
|
209
|
+
label: string;
|
|
210
|
+
message: string;
|
|
211
|
+
action_hint?: string;
|
|
212
|
+
scope?: string;
|
|
213
|
+
details?: Record<string, unknown>;
|
|
214
|
+
at: Date;
|
|
215
|
+
}
|
|
203
216
|
export interface ITaskExecution extends IFireDoc {
|
|
204
217
|
taskId: string;
|
|
205
218
|
handler: TaskAutoHandler;
|
|
@@ -214,6 +227,7 @@ export interface ITaskExecution extends IFireDoc {
|
|
|
214
227
|
code?: string | number;
|
|
215
228
|
details?: Record<string, unknown>;
|
|
216
229
|
};
|
|
230
|
+
outcome?: ITaskOutcome;
|
|
217
231
|
provider?: {
|
|
218
232
|
name?: string;
|
|
219
233
|
message_id?: string;
|
|
@@ -167,4 +167,7 @@ exports.TaskExecutionStatusEnum = {
|
|
|
167
167
|
Success: "success",
|
|
168
168
|
Error: "error",
|
|
169
169
|
Retry: "retry",
|
|
170
|
+
// Handler ran and decided not to deliver; `outcome` says why. The runner
|
|
171
|
+
// finalizes the task directly (no retry, fallback or handoff).
|
|
172
|
+
Suppressed: "suppressed",
|
|
170
173
|
};
|