feat: LAD A-Team CIS Compliance Report, React SPA, i18n, report management, explorer UX fixes

- Professional Oracle-format compliance report with RAG remediation from ADB vector store
- React 19 SPA at /app/ (16 pages, TypeScript, Vite, Zustand, i18n pt/en 625 keys)
- Report delete endpoint, embed individual report files into vector store
- Terraform ZIP download (client-side, pure JS)
- Explorer silent polling during start/stop (no flickering)
- HTML report and compliance report sections start minimized
- Token auth fix for compliance report CSV download links
This commit is contained in:
nogueiraguh
2026-03-19 07:34:06 -03:00
parent baacc1ba21
commit 442e710b9f
60 changed files with 23094 additions and 13 deletions

View File

@@ -0,0 +1,129 @@
import client from '../client';
/* ── Types ─────────────────────────────────────────────────────────────────── */
export interface CompartmentNode {
id: string;
name: string;
parent_id: string | null;
lifecycle_state?: string;
}
export interface Region {
name: string;
key: string;
status: string;
is_home: boolean;
}
export interface CountEntry {
count: number;
updated_at: string;
}
export type CountsMap = Record<string, CountEntry>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type ResourceItem = Record<string, any>;
export interface ActionResult {
ok: boolean;
action: string;
[key: string]: unknown;
}
export interface MyIpResult {
ip: string;
}
/* ── API ───────────────────────────────────────────────────────────────────── */
export const explorerApi = {
/* Compartment tree (flat list with parent_id) */
getCompartmentTree: (cid: string) =>
client.get(`/oci/explore/${cid}/compartment-tree`) as unknown as Promise<CompartmentNode[]>,
/* Regions subscribed */
getRegions: (cid: string) =>
client.get(`/oci/explore/${cid}/regions`) as unknown as Promise<Region[]>,
/* Cached counts */
getCounts: (cid: string, compartmentId: string, regions: string = '') =>
client.get(`/oci/explore/${cid}/counts`, {
params: { compartment_id: compartmentId, regions },
}) as unknown as Promise<CountsMap>,
/* Trigger background counts refresh */
refreshCounts: (cid: string, compartmentId: string, regions: string[]) =>
client.post(`/oci/explore/${cid}/counts/refresh`, {
compartment_id: compartmentId,
regions,
}) as unknown as Promise<{ status: string; types: number }>,
/* Fetch resources of a given type */
getResources: (cid: string, resourceType: string, compartmentId: string, region?: string) =>
client.get(`/oci/explore/${cid}/${resourceType}`, {
params: { compartment_id: compartmentId, region: region || undefined },
}) as unknown as Promise<ResourceItem[]>,
/* ── Actions ─────────────────────────────────────────────────────────────── */
instanceAction: (id: string, action: 'START' | 'STOP', ociConfigId: string, region?: string) =>
client.post(`/oci/instances/${id}/action`, {
action, oci_config_id: ociConfigId, region,
}) as unknown as Promise<ActionResult>,
adbAction: (id: string, action: 'start' | 'stop', ociConfigId: string, region?: string) =>
client.post(`/oci/autonomous-databases/${id}/action`, {
action, oci_config_id: ociConfigId, region,
}) as unknown as Promise<ActionResult>,
dbSystemAction: (id: string, action: 'START' | 'STOP', ociConfigId: string, region?: string) =>
client.post(`/oci/db-systems/${id}/action`, {
action, oci_config_id: ociConfigId, region,
}) as unknown as Promise<ActionResult>,
mysqlAction: (id: string, action: 'start' | 'stop', ociConfigId: string, region?: string) =>
client.post(`/oci/mysql-db-systems/${id}/action`, {
action, oci_config_id: ociConfigId, region,
}) as unknown as Promise<ActionResult>,
containerAction: (id: string, action: 'start' | 'stop', ociConfigId: string, region?: string) =>
client.post(`/oci/container-instances/${id}/action`, {
action, oci_config_id: ociConfigId, region,
}) as unknown as Promise<ActionResult>,
getMyIp: () =>
client.get('/oci/my-ip') as unknown as Promise<MyIpResult>,
adbUpdateNetwork: (id: string, ip: string, ociConfigId: string, region?: string) =>
client.post(`/oci/autonomous-databases/${id}/update-network-access`, {
ip, oci_config_id: ociConfigId, region,
}) as unknown as Promise<ActionResult>,
/* ── Security List Rules ─────────────────────────────────────────────────── */
addSlRule: (cid: string, slId: string, body: {
direction: string; protocol: string; source_dest: string;
port_min?: number; port_max?: number; description?: string;
is_stateless?: boolean; region?: string;
}) =>
client.post(`/oci/explore/${cid}/security_lists/${slId}/rules`, body) as unknown as Promise<ActionResult>,
removeSlRule: (cid: string, slId: string, body: {
direction: string; rule_index: number; region?: string;
}) =>
client.delete(`/oci/explore/${cid}/security_lists/${slId}/rules`, { data: body }) as unknown as Promise<ActionResult>,
/* ── NSG Rules ───────────────────────────────────────────────────────────── */
addNsgRule: (cid: string, nsgId: string, body: {
direction: string; protocol: string; source_dest: string;
source_dest_type?: string; port_min?: number; port_max?: number;
description?: string; is_stateless?: boolean; region?: string;
}) =>
client.post(`/oci/explore/${cid}/nsgs/${nsgId}/rules`, body) as unknown as Promise<ActionResult>,
removeNsgRule: (cid: string, nsgId: string, ruleId: string, region?: string) =>
client.delete(`/oci/explore/${cid}/nsgs/${nsgId}/rules/${ruleId}${region ? `?region=${region}` : ''}`) as unknown as Promise<ActionResult>,
};