@trismegisto/spine 2.0.0
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/LICENSE +56 -0
- package/README.md +207 -0
- package/fesm2022/trismegisto-spine-audit.mjs +1299 -0
- package/fesm2022/trismegisto-spine-audit.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-audit.component-CCiz-q8o.mjs +37 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-audit.component-CCiz-q8o.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-client-picker.component-Z0wCANF6.mjs +51 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-client-picker.component-Z0wCANF6.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-client.component-BYkUOwWL.mjs +595 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-client.component-BYkUOwWL.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-groups.component-CqIVe2LU.mjs +357 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service-groups.component-CqIVe2LU.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service.component-B5tyJ2zY.mjs +477 -0
- package/fesm2022/trismegisto-spine-auto-service-auto-service.component-B5tyJ2zY.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service-home.component-vl3BPFnk.mjs +238 -0
- package/fesm2022/trismegisto-spine-auto-service-home.component-vl3BPFnk.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-auto-service.mjs +154 -0
- package/fesm2022/trismegisto-spine-auto-service.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-graphql.mjs +347 -0
- package/fesm2022/trismegisto-spine-graphql.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-layout.mjs +2848 -0
- package/fesm2022/trismegisto-spine-layout.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-modal.mjs +141 -0
- package/fesm2022/trismegisto-spine-modal.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-notification.mjs +122 -0
- package/fesm2022/trismegisto-spine-notification.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-routing.mjs +398 -0
- package/fesm2022/trismegisto-spine-routing.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-shell.mjs +409 -0
- package/fesm2022/trismegisto-spine-shell.mjs.map +1 -0
- package/fesm2022/trismegisto-spine-side-panel.mjs +142 -0
- package/fesm2022/trismegisto-spine-side-panel.mjs.map +1 -0
- package/fesm2022/trismegisto-spine.mjs +2574 -0
- package/fesm2022/trismegisto-spine.mjs.map +1 -0
- package/package.json +94 -0
- package/types/trismegisto-spine-audit.d.ts +948 -0
- package/types/trismegisto-spine-audit.d.ts.map +1 -0
- package/types/trismegisto-spine-auto-service.d.ts +110 -0
- package/types/trismegisto-spine-auto-service.d.ts.map +1 -0
- package/types/trismegisto-spine-graphql.d.ts +72 -0
- package/types/trismegisto-spine-graphql.d.ts.map +1 -0
- package/types/trismegisto-spine-layout.d.ts +1054 -0
- package/types/trismegisto-spine-layout.d.ts.map +1 -0
- package/types/trismegisto-spine-modal.d.ts +68 -0
- package/types/trismegisto-spine-modal.d.ts.map +1 -0
- package/types/trismegisto-spine-notification.d.ts +62 -0
- package/types/trismegisto-spine-notification.d.ts.map +1 -0
- package/types/trismegisto-spine-routing.d.ts +205 -0
- package/types/trismegisto-spine-routing.d.ts.map +1 -0
- package/types/trismegisto-spine-shell.d.ts +143 -0
- package/types/trismegisto-spine-shell.d.ts.map +1 -0
- package/types/trismegisto-spine-side-panel.d.ts +66 -0
- package/types/trismegisto-spine-side-panel.d.ts.map +1 -0
- package/types/trismegisto-spine.d.ts +1161 -0
- package/types/trismegisto-spine.d.ts.map +1 -0
|
@@ -0,0 +1,948 @@
|
|
|
1
|
+
import { HttpParams } from '@angular/common/http';
|
|
2
|
+
import * as _angular_core from '@angular/core';
|
|
3
|
+
import { WritableSignal } from '@angular/core';
|
|
4
|
+
import * as _trismegisto_spine_audit from '@trismegisto/spine/audit';
|
|
5
|
+
import * as _trismegisto_primitives from '@trismegisto/primitives';
|
|
6
|
+
import { PluralMessage, formatMessage, PaginationState } from '@trismegisto/primitives';
|
|
7
|
+
import { SegmentedOption, FilterBarField, StateScreenSituation, DataGridColumn, FilterBarValue, TagColor } from '@trismegisto/angular';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Leitura da auditoria (`audit.events`) do argos admin-server, nos dois escopos:
|
|
11
|
+
* - `admin` → `GET {adminApi}/admin/audit/*` (painel central, todos os apps);
|
|
12
|
+
* - `client` → `GET {adminApi}/auto-service/:clientId/audit/*` (só os apps do projeto do client; o
|
|
13
|
+
* servidor recorta, `app_id` de fora → 403).
|
|
14
|
+
* Endpoints: `actions`, `events`, `events/:id`, `traces/:traceId`, `stats` e `tops/:kind` (rankings paginados).
|
|
15
|
+
* Unidade: a leitura padrão é por AÇÃO (uma linha por trace: o evento raiz + agregados dos spans);
|
|
16
|
+
* `unit=events` nas agregações mantém a contagem por evento (registro).
|
|
17
|
+
* Formatos e filtros fixados pelo contrato do admin-server; tudo aqui é TypeScript puro (tipos +
|
|
18
|
+
* montagem da consulta).
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
type AuditOutcome = 'success' | 'failure' | 'denied';
|
|
22
|
+
type AuditMethod = 'read' | 'write' | 'delete' | 'stream';
|
|
23
|
+
type AuditLevel = 'public' | 'private' | 'protected' | 'optional';
|
|
24
|
+
type AuditPermissionResult = 'allowed' | 'forbidden' | 'unauthorized' | 'public';
|
|
25
|
+
type AuditActorType = 'user' | 'app_token' | 'api_token' | 'public' | 'unauthenticated';
|
|
26
|
+
declare const AUDIT_METHODS: readonly AuditMethod[];
|
|
27
|
+
declare const AUDIT_OUTCOMES: readonly AuditOutcome[];
|
|
28
|
+
/** Um evento como vem na lista (`GET .../audit/events`). Datas em ISO-8601 UTC. */
|
|
29
|
+
interface AuditEvent {
|
|
30
|
+
event_id: string;
|
|
31
|
+
occurred_at: string;
|
|
32
|
+
duration_ms: number | null;
|
|
33
|
+
trace_id: string | null;
|
|
34
|
+
span_id: string | null;
|
|
35
|
+
parent_span_id: string | null;
|
|
36
|
+
/** `true` = a ação de entrada (feita pela pessoa); `false` = chamada entre apps dentro da cadeia. */
|
|
37
|
+
entry: boolean;
|
|
38
|
+
realm_id: string | null;
|
|
39
|
+
actor_type: AuditActorType | string | null;
|
|
40
|
+
user_id: string | null;
|
|
41
|
+
user_name: string | null;
|
|
42
|
+
token_id: string | null;
|
|
43
|
+
client_ip: string | null;
|
|
44
|
+
app_id: string | null;
|
|
45
|
+
app_name: string | null;
|
|
46
|
+
client_id: string | null;
|
|
47
|
+
route_id: string | null;
|
|
48
|
+
route_name: string | null;
|
|
49
|
+
operation_id: string | null;
|
|
50
|
+
operation_identifier: string | null;
|
|
51
|
+
operation_method: AuditMethod | string | null;
|
|
52
|
+
operation_level: AuditLevel | string | null;
|
|
53
|
+
operation_label: string | null;
|
|
54
|
+
target_type: string | null;
|
|
55
|
+
target_id: string | null;
|
|
56
|
+
permission_result: AuditPermissionResult | string | null;
|
|
57
|
+
outcome: AuditOutcome;
|
|
58
|
+
status: number | null;
|
|
59
|
+
message: string | null;
|
|
60
|
+
}
|
|
61
|
+
/** Unidade da leitura: `actions` (uma por trace, padrão) ou `events` (cada registro). */
|
|
62
|
+
type AuditUnit = 'actions' | 'events';
|
|
63
|
+
declare const AUDIT_UNITS: readonly AuditUnit[];
|
|
64
|
+
/**
|
|
65
|
+
* Uma AÇÃO (`GET .../audit/actions`): os campos do evento raiz (entry=true) do trace, com os agregados
|
|
66
|
+
* dos spans do mesmo trace dentro da janela. `outcome` = o pior dos spans (denied > failure > success);
|
|
67
|
+
* `root_outcome` = o do próprio raiz. `orphan` = trace sem raiz na janela (a linha é o 1º span interno).
|
|
68
|
+
* No escopo `client`, spans de apps de fora não entram nos agregados, só em `hidden_count`.
|
|
69
|
+
*/
|
|
70
|
+
interface AuditAction extends AuditEvent {
|
|
71
|
+
root_outcome?: AuditOutcome;
|
|
72
|
+
orphan?: boolean;
|
|
73
|
+
span_count: number;
|
|
74
|
+
hidden_count?: number;
|
|
75
|
+
apps?: string[];
|
|
76
|
+
failures?: number;
|
|
77
|
+
denied?: number;
|
|
78
|
+
}
|
|
79
|
+
interface AuditActionPage {
|
|
80
|
+
items: AuditAction[];
|
|
81
|
+
next_cursor: string | null;
|
|
82
|
+
}
|
|
83
|
+
/** O evento completo (`GET .../audit/events/:eventId?occurred_at=`). */
|
|
84
|
+
interface AuditEventDetail extends AuditEvent {
|
|
85
|
+
details?: unknown;
|
|
86
|
+
received_at?: string | null;
|
|
87
|
+
service_instance?: string | null;
|
|
88
|
+
sdk?: string | null;
|
|
89
|
+
}
|
|
90
|
+
interface AuditPage {
|
|
91
|
+
items: AuditEvent[];
|
|
92
|
+
next_cursor: string | null;
|
|
93
|
+
}
|
|
94
|
+
/** A cadeia (trace) recortada ao escopo do projeto; `hidden_count` = eventos de apps de fora. */
|
|
95
|
+
interface AuditTrace {
|
|
96
|
+
items: AuditEvent[];
|
|
97
|
+
hidden_count?: number;
|
|
98
|
+
}
|
|
99
|
+
interface AuditStats {
|
|
100
|
+
total: number;
|
|
101
|
+
/** Com `tops=false` na consulta, `by_app`/`top_operations`/`top_users` vêm vazios (use `tops/:kind`). */
|
|
102
|
+
by_outcome: {
|
|
103
|
+
success: number;
|
|
104
|
+
failure: number;
|
|
105
|
+
denied: number;
|
|
106
|
+
};
|
|
107
|
+
by_app: {
|
|
108
|
+
app_id: string;
|
|
109
|
+
app_name: string | null;
|
|
110
|
+
total: number;
|
|
111
|
+
failures: number;
|
|
112
|
+
denied: number;
|
|
113
|
+
}[];
|
|
114
|
+
top_operations: {
|
|
115
|
+
operation_identifier: string | null;
|
|
116
|
+
operation_label: string | null;
|
|
117
|
+
app_name: string | null;
|
|
118
|
+
total: number;
|
|
119
|
+
failures: number;
|
|
120
|
+
}[];
|
|
121
|
+
top_users: {
|
|
122
|
+
user_id: string | null;
|
|
123
|
+
user_name: string | null;
|
|
124
|
+
total: number;
|
|
125
|
+
}[];
|
|
126
|
+
timeline: {
|
|
127
|
+
bucket: string;
|
|
128
|
+
total: number;
|
|
129
|
+
failures: number;
|
|
130
|
+
denied: number;
|
|
131
|
+
}[];
|
|
132
|
+
}
|
|
133
|
+
/** Os rankings paginados de `GET .../audit/tops/:kind`. */
|
|
134
|
+
type AuditTopKind = 'apps' | 'operations' | 'users';
|
|
135
|
+
declare const AUDIT_TOP_KINDS: readonly AuditTopKind[];
|
|
136
|
+
/** Itens por página dos cards de ranking (o servidor aceita até 50). */
|
|
137
|
+
declare const AUDIT_TOP_PAGE_SIZE = 5;
|
|
138
|
+
/** Um item de ranking: os campos de identificação variam com o `kind`; contagens sempre presentes. */
|
|
139
|
+
interface AuditTopItem {
|
|
140
|
+
total: number;
|
|
141
|
+
failures: number;
|
|
142
|
+
denied: number;
|
|
143
|
+
/** `apps` e `operations`. */
|
|
144
|
+
app_id?: string | null;
|
|
145
|
+
app_name?: string | null;
|
|
146
|
+
/** `operations`. */
|
|
147
|
+
operation_identifier?: string | null;
|
|
148
|
+
operation_label?: string | null;
|
|
149
|
+
/** `users`. */
|
|
150
|
+
user_id?: string | null;
|
|
151
|
+
user_name?: string | null;
|
|
152
|
+
}
|
|
153
|
+
/** Uma página de ranking; `total` = quantos itens (grupos) existem na consulta. */
|
|
154
|
+
interface AuditTopPage {
|
|
155
|
+
items: AuditTopItem[];
|
|
156
|
+
total: number;
|
|
157
|
+
}
|
|
158
|
+
/** De onde a tela lê: o painel central (`admin`) ou o projeto de um client (`client`). */
|
|
159
|
+
type SpineAuditScope = 'admin' | 'client';
|
|
160
|
+
/**
|
|
161
|
+
* Base dos endpoints da auditoria para o escopo (sem barra no fim). `null` quando falta o necessário
|
|
162
|
+
* (sem `adminApi`, ou escopo `client` sem `clientId`).
|
|
163
|
+
*/
|
|
164
|
+
declare function auditApiBase(adminApi: string | null | undefined, scope: SpineAuditScope, clientId?: string | null): string | null;
|
|
165
|
+
/** Lista de apps para o filtro: todos (`admin`, `GET /admin/apps`) ou os do projeto do client. */
|
|
166
|
+
declare function auditAppsUrl(adminApi: string | null | undefined, scope: SpineAuditScope, clientId?: string | null): string | null;
|
|
167
|
+
/** Filtros da query string (todos opcionais). `app_id` repete o parâmetro. */
|
|
168
|
+
interface AuditQuery {
|
|
169
|
+
from?: string;
|
|
170
|
+
to?: string;
|
|
171
|
+
app_id?: readonly string[];
|
|
172
|
+
user_id?: string;
|
|
173
|
+
user?: string;
|
|
174
|
+
operation?: string;
|
|
175
|
+
method?: AuditMethod | string;
|
|
176
|
+
level?: AuditLevel | string;
|
|
177
|
+
outcome?: AuditOutcome | string;
|
|
178
|
+
permission_result?: AuditPermissionResult | string;
|
|
179
|
+
actor_type?: AuditActorType | string;
|
|
180
|
+
entry?: boolean;
|
|
181
|
+
trace_id?: string;
|
|
182
|
+
route_id?: string;
|
|
183
|
+
target_type?: string;
|
|
184
|
+
target_id?: string;
|
|
185
|
+
status?: number | string;
|
|
186
|
+
/** Agregações (stats/tops/daily): padrão do servidor = `actions`. Ignorado nas listas. */
|
|
187
|
+
unit?: AuditUnit;
|
|
188
|
+
}
|
|
189
|
+
/** Monta a query string: vazio/`null` some, lista repete a chave (`app_id=a&app_id=b`). */
|
|
190
|
+
declare function auditParams(query: AuditQuery, page?: {
|
|
191
|
+
limit?: number;
|
|
192
|
+
cursor?: string | null;
|
|
193
|
+
offset?: number;
|
|
194
|
+
}): HttpParams;
|
|
195
|
+
/** Escolhas rápidas de período da tela. */
|
|
196
|
+
type AuditPeriod = '1h' | '6h' | '24h' | '7d' | '30d';
|
|
197
|
+
declare const AUDIT_PERIOD_MS: Readonly<Record<AuditPeriod, number>>;
|
|
198
|
+
/** Janela máxima aceita pelo servidor (acima: 400 `range_too_large`). */
|
|
199
|
+
declare const AUDIT_MAX_WINDOW_MS: number;
|
|
200
|
+
/**
|
|
201
|
+
* Valor da faixa de filtros da tela (`hm-filter-bar`), por chave. `dates` é `{ start, end }` em
|
|
202
|
+
* AAAA-MM-DD (dia local); `app` é lista (multisseleção; aceita um id só); `entry` é booleano; o resto
|
|
203
|
+
* é texto.
|
|
204
|
+
*/
|
|
205
|
+
interface AuditFilterInput {
|
|
206
|
+
dates?: {
|
|
207
|
+
start: string | null;
|
|
208
|
+
end: string | null;
|
|
209
|
+
} | null;
|
|
210
|
+
app?: string | readonly string[] | null;
|
|
211
|
+
user?: string | null;
|
|
212
|
+
user_id?: string | null;
|
|
213
|
+
operation?: string | null;
|
|
214
|
+
method?: string | null;
|
|
215
|
+
level?: string | null;
|
|
216
|
+
outcome?: string | null;
|
|
217
|
+
permission_result?: string | null;
|
|
218
|
+
actor_type?: string | null;
|
|
219
|
+
status?: string | number | null;
|
|
220
|
+
trace_id?: string | null;
|
|
221
|
+
entry?: boolean | null;
|
|
222
|
+
}
|
|
223
|
+
type BuiltAuditQuery = {
|
|
224
|
+
ok: true;
|
|
225
|
+
query: AuditQuery;
|
|
226
|
+
} | {
|
|
227
|
+
ok: false;
|
|
228
|
+
reason: 'range_too_large';
|
|
229
|
+
};
|
|
230
|
+
/**
|
|
231
|
+
* Período + filtros da tela → consulta do contrato. As datas da faixa (dia local inteiro) vencem a
|
|
232
|
+
* escolha rápida; o fim nunca passa de `now`. A janela vira `from`/`to` absolutos, então as páginas
|
|
233
|
+
* seguintes (cursor) e o resumo enxergam exatamente o mesmo intervalo.
|
|
234
|
+
*/
|
|
235
|
+
declare function buildAuditQuery(period: AuditPeriod, filters: AuditFilterInput, now: Date): BuiltAuditQuery;
|
|
236
|
+
/**
|
|
237
|
+
* Lê as datas do servidor, que vêm em ISO UTC com MICROssegundos (`2026-10-05T13:18:40.564281Z`): o
|
|
238
|
+
* formato de data do ECMAScript só garante 3 casas, então a fração é cortada em milissegundos antes.
|
|
239
|
+
*/
|
|
240
|
+
declare function parseAuditDate(iso: string | null | undefined): Date | null;
|
|
241
|
+
/** Maior `limit` aceito por `GET .../audit/events`. */
|
|
242
|
+
declare const AUDIT_MAX_PAGE_SIZE = 200;
|
|
243
|
+
/** Busca uma fatia da lista (`cursor` `null` = do começo). */
|
|
244
|
+
type AuditPageFetcher = (cursor: string | null, limit: number) => Promise<AuditPage>;
|
|
245
|
+
/** Uma página resolvida por `AuditCursorPager.page`. `offset` pode ser menor que o pedido (pedido além do fim). */
|
|
246
|
+
interface AuditPagerResult {
|
|
247
|
+
items: AuditEvent[];
|
|
248
|
+
offset: number;
|
|
249
|
+
hasMore: boolean;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Paginação numerada ("página N de M") sobre a lista por cursor (keyset) do servidor, que não tem
|
|
253
|
+
* OFFSET. Guarda o cursor de cada posição já vista (posição 0 = sem cursor); para abrir uma página
|
|
254
|
+
* nunca vista, anda a partir da posição conhecida mais próxima em saltos de até 200 (o cursor só
|
|
255
|
+
* depende do último evento lido, não do `limit`). Vale para UMA consulta (`from`/`to` + filtros
|
|
256
|
+
* fixos): consulta nova = pager novo.
|
|
257
|
+
*/
|
|
258
|
+
declare class AuditCursorPager {
|
|
259
|
+
private readonly cursors;
|
|
260
|
+
/** Quantos eventos a consulta tem, quando a lista já chegou ao fim (`next_cursor` nulo). */
|
|
261
|
+
private endAt;
|
|
262
|
+
/** Total exato, conhecido depois de alguma página chegar ao fim da lista. */
|
|
263
|
+
get end(): number | null;
|
|
264
|
+
page(offset: number, size: number, fetch: AuditPageFetcher, retry?: boolean): Promise<AuditPagerResult>;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Total do rodapé: o exato quando a lista já chegou ao fim; senão o do resumo (`stats.total`, mesma
|
|
268
|
+
* consulta), nunca menor do que o que já se sabe existir (página atual + "tem mais").
|
|
269
|
+
*/
|
|
270
|
+
declare function auditPagerTotal(statsTotal: number | null | undefined, end: number | null, loaded: AuditPagerResult | null): number;
|
|
271
|
+
/** Pior resultado (denied > failure > success) — o `outcome` de uma ação. */
|
|
272
|
+
declare function worstOutcome(outcomes: readonly (string | null | undefined)[]): AuditOutcome;
|
|
273
|
+
/** Um span na linha do tempo de uma ação (`buildSpanTimeline`). */
|
|
274
|
+
interface AuditSpanRow {
|
|
275
|
+
event: AuditEvent;
|
|
276
|
+
/** Profundidade na hierarquia (parent_span_id → span_id); 0 = raiz(es). */
|
|
277
|
+
depth: number;
|
|
278
|
+
/** Início relativo ao 1º span, em ms. */
|
|
279
|
+
offsetMs: number;
|
|
280
|
+
/** Posição/largura da barra, em % da duração total (largura mínima para continuar visível). */
|
|
281
|
+
left: number;
|
|
282
|
+
width: number;
|
|
283
|
+
}
|
|
284
|
+
interface AuditSpanTimeline {
|
|
285
|
+
rows: AuditSpanRow[];
|
|
286
|
+
/** Do início do 1º span ao fim do último, em ms. */
|
|
287
|
+
totalMs: number;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Spans de um trace → linha do tempo: ordem em árvore (pai antes dos filhos, irmãos por início), com
|
|
291
|
+
* profundidade pela cadeia parent_span_id → span_id. Span cujo pai não está na lista (de fora do escopo,
|
|
292
|
+
* fora da janela) vira raiz. Fim do span = início + duration_ms (sem duração = instante).
|
|
293
|
+
*/
|
|
294
|
+
declare function buildSpanTimeline(items: readonly AuditEvent[]): AuditSpanTimeline;
|
|
295
|
+
/** Código de erro do envelope do admin-server (`{ error, detail }`), quando houver. */
|
|
296
|
+
declare function auditErrorCode(err: unknown): {
|
|
297
|
+
status: number;
|
|
298
|
+
code: string;
|
|
299
|
+
detail: string;
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* HTTP da auditoria (só leitura), igual nos dois escopos: cada método recebe a `base` já resolvida
|
|
304
|
+
* por `auditApiBase` (`{adminApi}/admin/audit` ou `{adminApi}/auto-service/:clientId/audit`). O
|
|
305
|
+
* recorte do escopo `client` é do servidor — nada aqui decide o que a pessoa pode ver.
|
|
306
|
+
*/
|
|
307
|
+
declare class SpineAuditService {
|
|
308
|
+
private readonly http;
|
|
309
|
+
private readonly auth;
|
|
310
|
+
private get headers();
|
|
311
|
+
events(base: string, query: AuditQuery, page?: {
|
|
312
|
+
limit?: number;
|
|
313
|
+
cursor?: string | null;
|
|
314
|
+
}): Promise<AuditPage>;
|
|
315
|
+
/** Uma linha por AÇÃO (raiz do trace + agregados dos spans), mesmos filtros/cursor de `events`. */
|
|
316
|
+
actions(base: string, query: AuditQuery, page?: {
|
|
317
|
+
limit?: number;
|
|
318
|
+
cursor?: string | null;
|
|
319
|
+
}): Promise<AuditActionPage>;
|
|
320
|
+
event(base: string, eventId: string, occurredAt: string): Promise<AuditEventDetail>;
|
|
321
|
+
/** `occurredAt` (opcional) = o do evento de origem: o servidor limita a busca da cadeia a ±1 dia dele. */
|
|
322
|
+
trace(base: string, traceId: string, occurredAt?: string | null): Promise<AuditTrace>;
|
|
323
|
+
/** Resumo (KPIs + linha do tempo). `tops: false` pula os rankings — a tela os pagina por `tops()`. */
|
|
324
|
+
stats(base: string, query: AuditQuery, opts?: {
|
|
325
|
+
tops?: boolean;
|
|
326
|
+
}): Promise<AuditStats>;
|
|
327
|
+
/** Um ranking paginado (`apps` | `operations` | `users`) com os mesmos filtros/janela do resumo. */
|
|
328
|
+
tops(base: string, kind: AuditTopKind, query: AuditQuery, page: {
|
|
329
|
+
offset: number;
|
|
330
|
+
limit: number;
|
|
331
|
+
}): Promise<AuditTopPage>;
|
|
332
|
+
/** Apps para o filtro (`{ apps: [{ id, name }] }` — `/admin/apps` ou `/auto-service/:clientId/apps`). */
|
|
333
|
+
apps(url: string): Promise<{
|
|
334
|
+
apps?: {
|
|
335
|
+
id: string;
|
|
336
|
+
name: string;
|
|
337
|
+
}[];
|
|
338
|
+
}>;
|
|
339
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpineAuditService, never>;
|
|
340
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<SpineAuditService>;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** Uma linha de ranking já pronta para mostrar (o card não sabe de que tipo é). */
|
|
344
|
+
interface AuditTopRow {
|
|
345
|
+
key: string;
|
|
346
|
+
name: string;
|
|
347
|
+
/** Texto secundário ao lado do nome (ex.: o app de uma operação). */
|
|
348
|
+
suffix?: string | null;
|
|
349
|
+
/** Dica (tooltip) do item — ex.: a descrição da operação. */
|
|
350
|
+
hint?: string | null;
|
|
351
|
+
total: number;
|
|
352
|
+
failures: number;
|
|
353
|
+
denied: number;
|
|
354
|
+
/** Sem como virar filtro (ex.: usuário sem nome nem id). */
|
|
355
|
+
disabled?: boolean;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Card de ranking da Auditoria ("Operações", "Usuários", "Por aplicação") com paginação compacta
|
|
359
|
+
* no servidor: `x–y de N` + anterior/próxima. Durante a troca de página as linhas atuais continuam
|
|
360
|
+
* (esmaecidas, `aria-busy`), sem esqueleto. A barra é proporcional ao `max` (o 1º item da 1ª página),
|
|
361
|
+
* então as páginas seguintes não "enchem" de novo. Clicar num item emite `picked` (vira filtro).
|
|
362
|
+
*/
|
|
363
|
+
declare class SpineAuditTopCardComponent {
|
|
364
|
+
readonly heading: _angular_core.InputSignal<string>;
|
|
365
|
+
readonly rows: _angular_core.InputSignal<readonly AuditTopRow[]>;
|
|
366
|
+
/** Quantos itens o ranking tem no total (todas as páginas). */
|
|
367
|
+
readonly total: _angular_core.InputSignal<number>;
|
|
368
|
+
readonly offset: _angular_core.InputSignal<number>;
|
|
369
|
+
readonly pageSize: _angular_core.InputSignal<number>;
|
|
370
|
+
/** Referência da barra (o maior total do ranking); 0 = o maior da página. */
|
|
371
|
+
readonly max: _angular_core.InputSignal<number>;
|
|
372
|
+
readonly loading: _angular_core.InputSignal<boolean>;
|
|
373
|
+
readonly failed: _angular_core.InputSignal<boolean>;
|
|
374
|
+
readonly picked: _angular_core.OutputEmitterRef<AuditTopRow>;
|
|
375
|
+
/** Novo `offset` pedido (anterior/próxima). */
|
|
376
|
+
readonly offsetChange: _angular_core.OutputEmitterRef<number>;
|
|
377
|
+
private readonly messages;
|
|
378
|
+
protected readonly text: {
|
|
379
|
+
title: string;
|
|
380
|
+
intro: string;
|
|
381
|
+
tabApps: string;
|
|
382
|
+
period: string;
|
|
383
|
+
periodLastHour: string;
|
|
384
|
+
period24h: string;
|
|
385
|
+
period7d: string;
|
|
386
|
+
period30d: string;
|
|
387
|
+
periodFromFilters: string;
|
|
388
|
+
filters: string;
|
|
389
|
+
filterDates: string;
|
|
390
|
+
filterApp: string;
|
|
391
|
+
filterUser: string;
|
|
392
|
+
filterOperation: string;
|
|
393
|
+
filterMethod: string;
|
|
394
|
+
filterOutcome: string;
|
|
395
|
+
filterEntry: string;
|
|
396
|
+
userPlaceholder: string;
|
|
397
|
+
operationPlaceholder: string;
|
|
398
|
+
methodRead: string;
|
|
399
|
+
methodWrite: string;
|
|
400
|
+
methodDelete: string;
|
|
401
|
+
methodStream: string;
|
|
402
|
+
outcomeSuccess: string;
|
|
403
|
+
outcomeFailure: string;
|
|
404
|
+
outcomeDenied: string;
|
|
405
|
+
kpiTotal: string;
|
|
406
|
+
kpiTotalDescription: string;
|
|
407
|
+
kpiFailures: string;
|
|
408
|
+
kpiDenied: string;
|
|
409
|
+
kpiShare: string;
|
|
410
|
+
kpis: string;
|
|
411
|
+
timeline: string;
|
|
412
|
+
timelineSummary: string;
|
|
413
|
+
bucketSummary: string;
|
|
414
|
+
timelineEmpty: string;
|
|
415
|
+
topOperations: string;
|
|
416
|
+
topUsers: string;
|
|
417
|
+
topApps: string;
|
|
418
|
+
noTop: string;
|
|
419
|
+
eventCount: PluralMessage;
|
|
420
|
+
failureCount: PluralMessage;
|
|
421
|
+
deniedCount: PluralMessage;
|
|
422
|
+
filterBy: string;
|
|
423
|
+
eventsCaption: string;
|
|
424
|
+
colWhen: string;
|
|
425
|
+
colApp: string;
|
|
426
|
+
colUser: string;
|
|
427
|
+
colOperation: string;
|
|
428
|
+
colMethod: string;
|
|
429
|
+
colOutcome: string;
|
|
430
|
+
colStatus: string;
|
|
431
|
+
colDuration: string;
|
|
432
|
+
durationMs: string;
|
|
433
|
+
pageItems: string;
|
|
434
|
+
pageSize: string;
|
|
435
|
+
pageError: string;
|
|
436
|
+
loading: string;
|
|
437
|
+
emptyTitle: string;
|
|
438
|
+
emptyText: string;
|
|
439
|
+
clearFilters: string;
|
|
440
|
+
errorTitle: string;
|
|
441
|
+
errorText: string;
|
|
442
|
+
retry: string;
|
|
443
|
+
rangeTooLarge: string;
|
|
444
|
+
forbidden: string;
|
|
445
|
+
anonymous: string;
|
|
446
|
+
detailHeading: string;
|
|
447
|
+
detailLoading: string;
|
|
448
|
+
detailError: string;
|
|
449
|
+
fieldWhen: string;
|
|
450
|
+
fieldApp: string;
|
|
451
|
+
fieldUser: string;
|
|
452
|
+
fieldActor: string;
|
|
453
|
+
fieldIp: string;
|
|
454
|
+
fieldOperation: string;
|
|
455
|
+
fieldIdentifier: string;
|
|
456
|
+
fieldMethod: string;
|
|
457
|
+
fieldLevel: string;
|
|
458
|
+
fieldPermission: string;
|
|
459
|
+
fieldOutcome: string;
|
|
460
|
+
fieldStatus: string;
|
|
461
|
+
fieldDuration: string;
|
|
462
|
+
fieldRoute: string;
|
|
463
|
+
fieldTarget: string;
|
|
464
|
+
fieldOrigin: string;
|
|
465
|
+
originEntry: string;
|
|
466
|
+
originInternal: string;
|
|
467
|
+
fieldTrace: string;
|
|
468
|
+
fieldEventId: string;
|
|
469
|
+
fieldMessage: string;
|
|
470
|
+
fieldReceivedAt: string;
|
|
471
|
+
fieldInstance: string;
|
|
472
|
+
fieldSdk: string;
|
|
473
|
+
fieldDetails: string;
|
|
474
|
+
viewTrace: string;
|
|
475
|
+
traceHeading: string;
|
|
476
|
+
traceLoading: string;
|
|
477
|
+
traceError: string;
|
|
478
|
+
traceEmpty: string;
|
|
479
|
+
traceHidden: PluralMessage;
|
|
480
|
+
traceCurrent: string;
|
|
481
|
+
openTraceEvent: string;
|
|
482
|
+
introAdmin: string;
|
|
483
|
+
period6h: string;
|
|
484
|
+
refresh: string;
|
|
485
|
+
autoRefresh: string;
|
|
486
|
+
updatedAt: string;
|
|
487
|
+
updating: string;
|
|
488
|
+
filterUserId: string;
|
|
489
|
+
filterLevel: string;
|
|
490
|
+
filterPermission: string;
|
|
491
|
+
filterActor: string;
|
|
492
|
+
filterStatus: string;
|
|
493
|
+
filterTrace: string;
|
|
494
|
+
userIdPlaceholder: string;
|
|
495
|
+
statusPlaceholder: string;
|
|
496
|
+
tracePlaceholder: string;
|
|
497
|
+
levelPublic: string;
|
|
498
|
+
levelPrivate: string;
|
|
499
|
+
levelProtected: string;
|
|
500
|
+
levelOptional: string;
|
|
501
|
+
permissionAllowed: string;
|
|
502
|
+
permissionForbidden: string;
|
|
503
|
+
permissionUnauthorized: string;
|
|
504
|
+
permissionPublic: string;
|
|
505
|
+
actorUser: string;
|
|
506
|
+
actorAppToken: string;
|
|
507
|
+
actorApiToken: string;
|
|
508
|
+
actorPublic: string;
|
|
509
|
+
actorUnauthenticated: string;
|
|
510
|
+
forbiddenAdmin: string;
|
|
511
|
+
invalidFilter: string;
|
|
512
|
+
kpiFilterHint: string;
|
|
513
|
+
topsRange: string;
|
|
514
|
+
topsPrevious: string;
|
|
515
|
+
topsNext: string;
|
|
516
|
+
topsError: string;
|
|
517
|
+
filterByTrace: string;
|
|
518
|
+
unitLabel: string;
|
|
519
|
+
unitActions: string;
|
|
520
|
+
unitEvents: string;
|
|
521
|
+
kpiTotalActions: string;
|
|
522
|
+
kpiTotalActionsDescription: string;
|
|
523
|
+
timelineSummaryActions: string;
|
|
524
|
+
bucketSummaryActions: string;
|
|
525
|
+
timelineEmptyActions: string;
|
|
526
|
+
actionsCaption: string;
|
|
527
|
+
pageItemsActions: string;
|
|
528
|
+
pageErrorActions: string;
|
|
529
|
+
emptyTitleActions: string;
|
|
530
|
+
colSpans: string;
|
|
531
|
+
spansApps: string;
|
|
532
|
+
spansHidden: PluralMessage;
|
|
533
|
+
actionDetailHeading: string;
|
|
534
|
+
orphanNote: string;
|
|
535
|
+
orphanTag: string;
|
|
536
|
+
spansHeading: string;
|
|
537
|
+
spansSummary: string;
|
|
538
|
+
spanRow: string;
|
|
539
|
+
};
|
|
540
|
+
private readonly locale;
|
|
541
|
+
protected readonly fmt: typeof formatMessage;
|
|
542
|
+
protected readonly headingId: string;
|
|
543
|
+
private readonly reference;
|
|
544
|
+
protected readonly range: _angular_core.Signal<string>;
|
|
545
|
+
protected go(direction: -1 | 1): void;
|
|
546
|
+
/** Fatia (em % da própria barra) de falhas/negados dentro do total da linha. */
|
|
547
|
+
protected share(part: number, total: number): number;
|
|
548
|
+
protected bar(total: number): number;
|
|
549
|
+
protected number(n: number): string;
|
|
550
|
+
protected plural(message: PluralMessage, count: number): string;
|
|
551
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpineAuditTopCardComponent, never>;
|
|
552
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SpineAuditTopCardComponent, "spine-audit-top-card", never, { "heading": { "alias": "heading"; "required": true; "isSignal": true; }; "rows": { "alias": "rows"; "required": true; "isSignal": true; }; "total": { "alias": "total"; "required": false; "isSignal": true; }; "offset": { "alias": "offset"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "failed": { "alias": "failed"; "required": false; "isSignal": true; }; }, { "picked": "picked"; "offsetChange": "offsetChange"; }, never, never, true, never>;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/** Eventos por página da tabela, de saída (o servidor aceita até 200 — `AUDIT_MAX_PAGE_SIZE`). */
|
|
556
|
+
declare const AUDIT_PAGE_SIZE = 10;
|
|
557
|
+
/** Opções do seletor de eventos por página (todas dentro do `limit` máximo do servidor). */
|
|
558
|
+
declare const AUDIT_PAGE_SIZES: readonly number[];
|
|
559
|
+
/** Intervalo da atualização automática (opcional, desligada por padrão). */
|
|
560
|
+
declare const AUDIT_AUTO_REFRESH_MS = 30000;
|
|
561
|
+
interface AuditApp {
|
|
562
|
+
id: string;
|
|
563
|
+
name: string;
|
|
564
|
+
}
|
|
565
|
+
interface DetailField {
|
|
566
|
+
label: string;
|
|
567
|
+
value: string;
|
|
568
|
+
code?: boolean;
|
|
569
|
+
}
|
|
570
|
+
interface TimelineBar {
|
|
571
|
+
key: string;
|
|
572
|
+
summary: string;
|
|
573
|
+
ok: number;
|
|
574
|
+
fail: number;
|
|
575
|
+
denied: number;
|
|
576
|
+
}
|
|
577
|
+
type ErrorKind = 'range' | 'forbidden' | 'invalid' | 'generic';
|
|
578
|
+
/** Estado de um card de ranking (página atual + total no servidor). */
|
|
579
|
+
interface TopState {
|
|
580
|
+
items: readonly AuditTopItem[];
|
|
581
|
+
total: number;
|
|
582
|
+
offset: number;
|
|
583
|
+
/** O maior total do ranking (1º item da 1ª página) — referência da barra nas páginas seguintes. */
|
|
584
|
+
max: number;
|
|
585
|
+
loading: boolean;
|
|
586
|
+
failed: boolean;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* A tela de Auditoria — a MESMA no auto-serviço e no painel central do argos admin. Só muda o escopo:
|
|
590
|
+
* - `scope="client"` + `clientId`: `{adminApi}/auto-service/:clientId/audit/*`, apps do projeto do client
|
|
591
|
+
* (recorte feito no servidor);
|
|
592
|
+
* - `scope="admin"`: `{adminApi}/admin/audit/*`, todos os apps (guard `admin:audit:*` no servidor).
|
|
593
|
+
* `adminApi` vem do input ou do `SPINE_ADMIN_API` (que o `provideAutoService` já fornece).
|
|
594
|
+
*
|
|
595
|
+
* Unidade: por padrão a tela lê AÇÕES (`GET .../actions`, uma linha por trace, coluna "Spans", detalhe
|
|
596
|
+
* com os spans numa linha do tempo); o alternador "Ações | Eventos" volta à leitura por registro. KPIs,
|
|
597
|
+
* linha do tempo e rankings seguem a unidade escolhida (`unit=` nas agregações).
|
|
598
|
+
*
|
|
599
|
+
* Conteúdo: período rápido (ou datas da faixa de filtros, que vencem), filtros, KPIs (falhas/negados
|
|
600
|
+
* clicáveis viram filtro), linha do tempo, 3 rankings paginados no servidor (`tops/:kind`), a tabela
|
|
601
|
+
* paginada no servidor (cursor) e o detalhe/cadeia (trace) de um evento.
|
|
602
|
+
*
|
|
603
|
+
* Recarga sem piscar: trocar de página (ou atualizar) mantém as linhas atuais à vista com um indicador
|
|
604
|
+
* por cima — a grade só mostra esqueleto na 1ª carga. Toda resposta carrega um número de sequência e a
|
|
605
|
+
* que chega fora de ordem (página/consulta já trocada) é descartada.
|
|
606
|
+
*
|
|
607
|
+
* Importe só de código carregado sob demanda (rota lazy, `import()`): o ponto `@trismegisto/spine/audit`
|
|
608
|
+
* existe para a tela não entrar no bundle inicial de quem só usa o resto do spine.
|
|
609
|
+
*/
|
|
610
|
+
declare class SpineAuditComponent {
|
|
611
|
+
/** `admin` = painel central (todos os apps); `client` = apps do projeto do `clientId`. */
|
|
612
|
+
readonly scope: _angular_core.InputSignal<SpineAuditScope>;
|
|
613
|
+
/** Obrigatório com `scope="client"`. */
|
|
614
|
+
readonly clientId: _angular_core.InputSignal<string | null>;
|
|
615
|
+
/** Base do argos admin-server; sem ele, vale o `SPINE_ADMIN_API`. */
|
|
616
|
+
readonly adminApi: _angular_core.InputSignal<string | null>;
|
|
617
|
+
private readonly service;
|
|
618
|
+
private readonly tokenApi;
|
|
619
|
+
private readonly messages;
|
|
620
|
+
protected readonly text: {
|
|
621
|
+
title: string;
|
|
622
|
+
intro: string;
|
|
623
|
+
tabApps: string;
|
|
624
|
+
period: string;
|
|
625
|
+
periodLastHour: string;
|
|
626
|
+
period24h: string;
|
|
627
|
+
period7d: string;
|
|
628
|
+
period30d: string;
|
|
629
|
+
periodFromFilters: string;
|
|
630
|
+
filters: string;
|
|
631
|
+
filterDates: string;
|
|
632
|
+
filterApp: string;
|
|
633
|
+
filterUser: string;
|
|
634
|
+
filterOperation: string;
|
|
635
|
+
filterMethod: string;
|
|
636
|
+
filterOutcome: string;
|
|
637
|
+
filterEntry: string;
|
|
638
|
+
userPlaceholder: string;
|
|
639
|
+
operationPlaceholder: string;
|
|
640
|
+
methodRead: string;
|
|
641
|
+
methodWrite: string;
|
|
642
|
+
methodDelete: string;
|
|
643
|
+
methodStream: string;
|
|
644
|
+
outcomeSuccess: string;
|
|
645
|
+
outcomeFailure: string;
|
|
646
|
+
outcomeDenied: string;
|
|
647
|
+
kpiTotal: string;
|
|
648
|
+
kpiTotalDescription: string;
|
|
649
|
+
kpiFailures: string;
|
|
650
|
+
kpiDenied: string;
|
|
651
|
+
kpiShare: string;
|
|
652
|
+
kpis: string;
|
|
653
|
+
timeline: string;
|
|
654
|
+
timelineSummary: string;
|
|
655
|
+
bucketSummary: string;
|
|
656
|
+
timelineEmpty: string;
|
|
657
|
+
topOperations: string;
|
|
658
|
+
topUsers: string;
|
|
659
|
+
topApps: string;
|
|
660
|
+
noTop: string;
|
|
661
|
+
eventCount: PluralMessage;
|
|
662
|
+
failureCount: PluralMessage;
|
|
663
|
+
deniedCount: PluralMessage;
|
|
664
|
+
filterBy: string;
|
|
665
|
+
eventsCaption: string;
|
|
666
|
+
colWhen: string;
|
|
667
|
+
colApp: string;
|
|
668
|
+
colUser: string;
|
|
669
|
+
colOperation: string;
|
|
670
|
+
colMethod: string;
|
|
671
|
+
colOutcome: string;
|
|
672
|
+
colStatus: string;
|
|
673
|
+
colDuration: string;
|
|
674
|
+
durationMs: string;
|
|
675
|
+
pageItems: string;
|
|
676
|
+
pageSize: string;
|
|
677
|
+
pageError: string;
|
|
678
|
+
loading: string;
|
|
679
|
+
emptyTitle: string;
|
|
680
|
+
emptyText: string;
|
|
681
|
+
clearFilters: string;
|
|
682
|
+
errorTitle: string;
|
|
683
|
+
errorText: string;
|
|
684
|
+
retry: string;
|
|
685
|
+
rangeTooLarge: string;
|
|
686
|
+
forbidden: string;
|
|
687
|
+
anonymous: string;
|
|
688
|
+
detailHeading: string;
|
|
689
|
+
detailLoading: string;
|
|
690
|
+
detailError: string;
|
|
691
|
+
fieldWhen: string;
|
|
692
|
+
fieldApp: string;
|
|
693
|
+
fieldUser: string;
|
|
694
|
+
fieldActor: string;
|
|
695
|
+
fieldIp: string;
|
|
696
|
+
fieldOperation: string;
|
|
697
|
+
fieldIdentifier: string;
|
|
698
|
+
fieldMethod: string;
|
|
699
|
+
fieldLevel: string;
|
|
700
|
+
fieldPermission: string;
|
|
701
|
+
fieldOutcome: string;
|
|
702
|
+
fieldStatus: string;
|
|
703
|
+
fieldDuration: string;
|
|
704
|
+
fieldRoute: string;
|
|
705
|
+
fieldTarget: string;
|
|
706
|
+
fieldOrigin: string;
|
|
707
|
+
originEntry: string;
|
|
708
|
+
originInternal: string;
|
|
709
|
+
fieldTrace: string;
|
|
710
|
+
fieldEventId: string;
|
|
711
|
+
fieldMessage: string;
|
|
712
|
+
fieldReceivedAt: string;
|
|
713
|
+
fieldInstance: string;
|
|
714
|
+
fieldSdk: string;
|
|
715
|
+
fieldDetails: string;
|
|
716
|
+
viewTrace: string;
|
|
717
|
+
traceHeading: string;
|
|
718
|
+
traceLoading: string;
|
|
719
|
+
traceError: string;
|
|
720
|
+
traceEmpty: string;
|
|
721
|
+
traceHidden: PluralMessage;
|
|
722
|
+
traceCurrent: string;
|
|
723
|
+
openTraceEvent: string;
|
|
724
|
+
introAdmin: string;
|
|
725
|
+
period6h: string;
|
|
726
|
+
refresh: string;
|
|
727
|
+
autoRefresh: string;
|
|
728
|
+
updatedAt: string;
|
|
729
|
+
updating: string;
|
|
730
|
+
filterUserId: string;
|
|
731
|
+
filterLevel: string;
|
|
732
|
+
filterPermission: string;
|
|
733
|
+
filterActor: string;
|
|
734
|
+
filterStatus: string;
|
|
735
|
+
filterTrace: string;
|
|
736
|
+
userIdPlaceholder: string;
|
|
737
|
+
statusPlaceholder: string;
|
|
738
|
+
tracePlaceholder: string;
|
|
739
|
+
levelPublic: string;
|
|
740
|
+
levelPrivate: string;
|
|
741
|
+
levelProtected: string;
|
|
742
|
+
levelOptional: string;
|
|
743
|
+
permissionAllowed: string;
|
|
744
|
+
permissionForbidden: string;
|
|
745
|
+
permissionUnauthorized: string;
|
|
746
|
+
permissionPublic: string;
|
|
747
|
+
actorUser: string;
|
|
748
|
+
actorAppToken: string;
|
|
749
|
+
actorApiToken: string;
|
|
750
|
+
actorPublic: string;
|
|
751
|
+
actorUnauthenticated: string;
|
|
752
|
+
forbiddenAdmin: string;
|
|
753
|
+
invalidFilter: string;
|
|
754
|
+
kpiFilterHint: string;
|
|
755
|
+
topsRange: string;
|
|
756
|
+
topsPrevious: string;
|
|
757
|
+
topsNext: string;
|
|
758
|
+
topsError: string;
|
|
759
|
+
filterByTrace: string;
|
|
760
|
+
unitLabel: string;
|
|
761
|
+
unitActions: string;
|
|
762
|
+
unitEvents: string;
|
|
763
|
+
kpiTotalActions: string;
|
|
764
|
+
kpiTotalActionsDescription: string;
|
|
765
|
+
timelineSummaryActions: string;
|
|
766
|
+
bucketSummaryActions: string;
|
|
767
|
+
timelineEmptyActions: string;
|
|
768
|
+
actionsCaption: string;
|
|
769
|
+
pageItemsActions: string;
|
|
770
|
+
pageErrorActions: string;
|
|
771
|
+
emptyTitleActions: string;
|
|
772
|
+
colSpans: string;
|
|
773
|
+
spansApps: string;
|
|
774
|
+
spansHidden: PluralMessage;
|
|
775
|
+
actionDetailHeading: string;
|
|
776
|
+
orphanNote: string;
|
|
777
|
+
orphanTag: string;
|
|
778
|
+
spansHeading: string;
|
|
779
|
+
spansSummary: string;
|
|
780
|
+
spanRow: string;
|
|
781
|
+
};
|
|
782
|
+
private readonly locale;
|
|
783
|
+
protected readonly fmt: typeof formatMessage;
|
|
784
|
+
/** Base dos endpoints do escopo; muda → tudo recomeça (filtros, página, detalhe). */
|
|
785
|
+
protected readonly base: _angular_core.Signal<string | null>;
|
|
786
|
+
private readonly appsUrl;
|
|
787
|
+
protected readonly period: WritableSignal<AuditPeriod>;
|
|
788
|
+
/** Ações (uma linha por trace) ou eventos (cada registro). */
|
|
789
|
+
protected readonly unit: WritableSignal<AuditUnit>;
|
|
790
|
+
protected readonly byActions: _angular_core.Signal<boolean>;
|
|
791
|
+
protected readonly unitOptions: readonly SegmentedOption[];
|
|
792
|
+
/** Textos que mudam com a unidade. */
|
|
793
|
+
protected readonly unitText: _angular_core.Signal<{
|
|
794
|
+
kpiTotal: string;
|
|
795
|
+
kpiTotalDescription: string;
|
|
796
|
+
timelineSummary: string;
|
|
797
|
+
bucketSummary: string;
|
|
798
|
+
timelineEmpty: string;
|
|
799
|
+
caption: string;
|
|
800
|
+
pageItems: string;
|
|
801
|
+
pageError: string;
|
|
802
|
+
emptyTitle: string;
|
|
803
|
+
}>;
|
|
804
|
+
protected readonly filterValue: WritableSignal<Readonly<Record<string, _trismegisto_primitives.FilterBarFieldValue>>>;
|
|
805
|
+
protected readonly apps: WritableSignal<readonly AuditApp[]>;
|
|
806
|
+
protected readonly stats: WritableSignal<AuditStats | null>;
|
|
807
|
+
protected readonly events: WritableSignal<readonly AuditEvent[]>;
|
|
808
|
+
protected readonly loading: WritableSignal<boolean>;
|
|
809
|
+
protected readonly pageLoading: WritableSignal<boolean>;
|
|
810
|
+
protected readonly pageFailed: WritableSignal<boolean>;
|
|
811
|
+
protected readonly pageState: WritableSignal<PaginationState>;
|
|
812
|
+
protected readonly pageSizes: readonly number[];
|
|
813
|
+
/** A página mostrada (posição + "tem mais") e o total exato quando a lista já chegou ao fim. */
|
|
814
|
+
private readonly loaded;
|
|
815
|
+
private readonly listEnd;
|
|
816
|
+
/** Total do rodapé da tabela. */
|
|
817
|
+
protected readonly total: _angular_core.Signal<number>;
|
|
818
|
+
protected readonly errorKind: WritableSignal<ErrorKind | null>;
|
|
819
|
+
private readonly errorDetail;
|
|
820
|
+
protected readonly lastUpdated: WritableSignal<Date | null>;
|
|
821
|
+
protected readonly autoRefresh: WritableSignal<boolean>;
|
|
822
|
+
/** Esqueleto da grade só quando ainda não há linha nenhuma para mostrar (1ª carga). */
|
|
823
|
+
protected readonly gridSkeleton: _angular_core.Signal<boolean>;
|
|
824
|
+
/** Recarga com linhas à vista: elas ficam, com o indicador por cima. */
|
|
825
|
+
protected readonly gridBusy: _angular_core.Signal<boolean>;
|
|
826
|
+
protected readonly tops: Readonly<Record<AuditTopKind, WritableSignal<TopState>>>;
|
|
827
|
+
protected readonly topPageSize = 5;
|
|
828
|
+
protected readonly detailOpen: WritableSignal<boolean>;
|
|
829
|
+
protected readonly selected: WritableSignal<AuditEventDetail | null>;
|
|
830
|
+
protected readonly detailLoading: WritableSignal<boolean>;
|
|
831
|
+
protected readonly detailFailed: WritableSignal<boolean>;
|
|
832
|
+
protected readonly trace: WritableSignal<AuditTrace | null>;
|
|
833
|
+
/** A ação aberta (linha da tabela por ações): agregados que o detalhe do evento raiz não traz. */
|
|
834
|
+
protected readonly selectedAction: WritableSignal<AuditAction | null>;
|
|
835
|
+
/** O detalhe mostra a ação (o raiz dela), não um span qualquer da cadeia. */
|
|
836
|
+
protected readonly showingAction: _angular_core.Signal<boolean>;
|
|
837
|
+
/** Resultado do cabeçalho do detalhe: o da ação (pior dos spans) ou o do evento. */
|
|
838
|
+
protected readonly headOutcome: _angular_core.Signal<_trismegisto_spine_audit.AuditOutcome | undefined>;
|
|
839
|
+
/** Os spans da cadeia numa linha do tempo (hierarquia por parent_span_id). */
|
|
840
|
+
protected readonly spanTimeline: _angular_core.Signal<AuditSpanTimeline | null>;
|
|
841
|
+
protected readonly traceLoading: WritableSignal<boolean>;
|
|
842
|
+
protected readonly traceFailed: WritableSignal<boolean>;
|
|
843
|
+
/** Consulta da última carga — a troca de página usa a mesma (mesma janela absoluta). */
|
|
844
|
+
private query;
|
|
845
|
+
/** Cursores da consulta atual (consulta nova = pager novo). */
|
|
846
|
+
private pager;
|
|
847
|
+
/** Descartam respostas velhas (consulta/página/ranking/detalhe já trocados). */
|
|
848
|
+
private seq;
|
|
849
|
+
private pageSeq;
|
|
850
|
+
private detailSeq;
|
|
851
|
+
private readonly topSeq;
|
|
852
|
+
protected readonly periodOptions: readonly SegmentedOption[];
|
|
853
|
+
/** Há mais de um app à vista: coluna, filtro e ranking "por aplicação" aparecem. */
|
|
854
|
+
protected readonly multiApp: _angular_core.Signal<boolean>;
|
|
855
|
+
/** As datas da faixa estão valendo (a escolha rápida fica sem efeito). */
|
|
856
|
+
protected readonly customDates: _angular_core.Signal<boolean>;
|
|
857
|
+
protected readonly hasFilters: _angular_core.Signal<boolean>;
|
|
858
|
+
protected readonly selectedOutcome: _angular_core.Signal<string | null>;
|
|
859
|
+
protected readonly storageKey: _angular_core.Signal<string>;
|
|
860
|
+
protected readonly filterFields: _angular_core.Signal<FilterBarField[]>;
|
|
861
|
+
protected readonly errorSituation: _angular_core.Signal<StateScreenSituation>;
|
|
862
|
+
protected readonly errorText: _angular_core.Signal<string>;
|
|
863
|
+
protected readonly empty: _angular_core.Signal<boolean>;
|
|
864
|
+
protected readonly columns: _angular_core.Signal<DataGridColumn<AuditEvent>[]>;
|
|
865
|
+
protected readonly rowId: (e: AuditEvent) => string;
|
|
866
|
+
protected readonly timelineBars: _angular_core.Signal<TimelineBar[]>;
|
|
867
|
+
protected readonly timelineEdges: _angular_core.Signal<{
|
|
868
|
+
from: string;
|
|
869
|
+
to: string;
|
|
870
|
+
} | null>;
|
|
871
|
+
protected readonly hasTimeline: _angular_core.Signal<boolean>;
|
|
872
|
+
protected readonly topOperationRows: _angular_core.Signal<AuditTopRow[]>;
|
|
873
|
+
protected readonly topUserRows: _angular_core.Signal<AuditTopRow[]>;
|
|
874
|
+
protected readonly topAppRows: _angular_core.Signal<AuditTopRow[]>;
|
|
875
|
+
protected readonly detailFields: _angular_core.Signal<DetailField[]>;
|
|
876
|
+
protected readonly detailsJson: _angular_core.Signal<string>;
|
|
877
|
+
constructor();
|
|
878
|
+
private readonly router;
|
|
879
|
+
private urlConsumed;
|
|
880
|
+
/** Filtros/evento da query string (`from`, `to` ISO; `app_id` repetível; demais filtros pelo nome). */
|
|
881
|
+
private readUrlState;
|
|
882
|
+
protected setPeriod(value: string): void;
|
|
883
|
+
protected setUnit(value: string): void;
|
|
884
|
+
protected setFilters(value: FilterBarValue): void;
|
|
885
|
+
private firstPage;
|
|
886
|
+
protected clearFilters(): void;
|
|
887
|
+
/** Clique num item de ranking ou atalho: vira filtro (soma aos que já estão). */
|
|
888
|
+
protected filterBy(key: keyof AuditFilterInput, value: string | readonly string[] | null | undefined): void;
|
|
889
|
+
protected pickTop(kind: AuditTopKind, row: AuditTopRow): void;
|
|
890
|
+
/** KPI "Falhas"/"Negados" clicável: liga/desliga o filtro de resultado. */
|
|
891
|
+
protected toggleOutcome(outcome: 'failure' | 'denied', on: boolean): void;
|
|
892
|
+
/** Recarrega resumo, rankings e a página atual com a janela recalculada (`now` novo, cursores descartados). */
|
|
893
|
+
reload(): Promise<void>;
|
|
894
|
+
/** Rodapé da tabela mudou de página ou de itens por página: busca só aquela página, mesma consulta. */
|
|
895
|
+
changePage(state: PaginationState): Promise<void>;
|
|
896
|
+
/** Card de ranking pediu outra página (mesma consulta da última carga). */
|
|
897
|
+
loadTop(kind: AuditTopKind, offset: number): Promise<void>;
|
|
898
|
+
private fetcher;
|
|
899
|
+
private showPage;
|
|
900
|
+
private clearData;
|
|
901
|
+
/** Clique numa linha da tabela: por ação abre o raiz e já carrega os spans; por evento, só o evento. */
|
|
902
|
+
protected openRow(row: AuditEvent): void;
|
|
903
|
+
/** Abre uma ação: o detalhe do evento raiz + a linha do tempo dos spans (trace) carregada junto. */
|
|
904
|
+
openAction(action: AuditAction): Promise<void>;
|
|
905
|
+
/** Abre o detalhe com o resumo da linha e completa com o evento inteiro. Da cadeia, mantém a cadeia. */
|
|
906
|
+
openEvent(event: AuditEvent, keepTrace?: boolean): Promise<void>;
|
|
907
|
+
showTrace(): Promise<void>;
|
|
908
|
+
/** "Filtrar a tabela por este trace" (do detalhe): fecha o detalhe e aplica o filtro. */
|
|
909
|
+
protected filterByTrace(traceId: string | null): void;
|
|
910
|
+
protected onDetailOpenChange(open: boolean): void;
|
|
911
|
+
private closeDetail;
|
|
912
|
+
private loadApps;
|
|
913
|
+
private setError;
|
|
914
|
+
protected number(n: number): string;
|
|
915
|
+
protected plural(message: PluralMessage, count: number): string;
|
|
916
|
+
protected share(part: number): string;
|
|
917
|
+
protected dateTime(iso: string | null | undefined): string;
|
|
918
|
+
protected time(iso: string): string;
|
|
919
|
+
protected clock(d: Date): string;
|
|
920
|
+
/** Rótulo do intervalo da linha do tempo: hora no dia, dia+hora até 3 dias, só o dia acima. */
|
|
921
|
+
private bucketTime;
|
|
922
|
+
protected duration(ms: number | null | undefined): string;
|
|
923
|
+
protected userName(e: {
|
|
924
|
+
user_name: string | null;
|
|
925
|
+
user_id?: string | null;
|
|
926
|
+
}): string;
|
|
927
|
+
/** Rótulo acessível de uma linha da linha do tempo dos spans. */
|
|
928
|
+
protected spanAria(row: AuditSpanRow): string;
|
|
929
|
+
/** Dica da célula "Spans": aplicações envolvidas (+ spans de fora do escopo). */
|
|
930
|
+
protected spansHint(a: AuditAction): string;
|
|
931
|
+
/** Nome da operação = o identificador (a descrição é complemento: dica e detalhe). */
|
|
932
|
+
protected operationName(e: {
|
|
933
|
+
operation_label: string | null;
|
|
934
|
+
operation_identifier: string | null;
|
|
935
|
+
}): string;
|
|
936
|
+
protected methodLabel(method: string | null | undefined): string;
|
|
937
|
+
protected levelLabel(level: string | null | undefined): string;
|
|
938
|
+
protected permissionLabel(result: string | null | undefined): string;
|
|
939
|
+
protected actorLabel(actor: string | null | undefined): string;
|
|
940
|
+
protected outcomeLabel(outcome: string | null | undefined): string;
|
|
941
|
+
protected outcomeColor(outcome: string | null | undefined): TagColor;
|
|
942
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SpineAuditComponent, never>;
|
|
943
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SpineAuditComponent, "spine-audit", never, { "scope": { "alias": "scope"; "required": true; "isSignal": true; }; "clientId": { "alias": "clientId"; "required": false; "isSignal": true; }; "adminApi": { "alias": "adminApi"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
export { AUDIT_AUTO_REFRESH_MS, AUDIT_MAX_PAGE_SIZE, AUDIT_MAX_WINDOW_MS, AUDIT_METHODS, AUDIT_OUTCOMES, AUDIT_PAGE_SIZE, AUDIT_PAGE_SIZES, AUDIT_PERIOD_MS, AUDIT_TOP_KINDS, AUDIT_TOP_PAGE_SIZE, AUDIT_UNITS, AuditCursorPager, SpineAuditComponent, SpineAuditService, SpineAuditTopCardComponent, auditApiBase, auditAppsUrl, auditErrorCode, auditPagerTotal, auditParams, buildAuditQuery, buildSpanTimeline, parseAuditDate, worstOutcome };
|
|
947
|
+
export type { AuditAction, AuditActionPage, AuditActorType, AuditEvent, AuditEventDetail, AuditFilterInput, AuditLevel, AuditMethod, AuditOutcome, AuditPage, AuditPageFetcher, AuditPagerResult, AuditPeriod, AuditPermissionResult, AuditQuery, AuditSpanRow, AuditSpanTimeline, AuditStats, AuditTopItem, AuditTopKind, AuditTopPage, AuditTopRow, AuditTrace, AuditUnit, BuiltAuditQuery, SpineAuditScope };
|
|
948
|
+
//# sourceMappingURL=trismegisto-spine-audit.d.ts.map
|