116 lines
3.6 KiB
TypeScript
116 lines
3.6 KiB
TypeScript
import { apiFetch, type ApiSettings, type DeltaDeletedItem } from "@govoplan/core-webui";
|
|
|
|
export type AuditAdminItem = {
|
|
id: string;
|
|
scope: "tenant" | "system";
|
|
tenant_id?: string | null;
|
|
actor_email?: string | null;
|
|
action: string;
|
|
object_type?: string | null;
|
|
object_id?: string | null;
|
|
details: Record<string, unknown>;
|
|
created_at: string;
|
|
};
|
|
|
|
export type AuditSortBy = "time" | "actor" | "action" | "object" | "tenant";
|
|
|
|
export type AuditQueryOptions = {
|
|
tenantId?: string | null;
|
|
allTenants?: boolean;
|
|
scope?: "tenant" | "system";
|
|
limit?: number;
|
|
offset?: number;
|
|
page?: number;
|
|
pageSize?: number;
|
|
cursor?: string | null;
|
|
sortBy?: AuditSortBy;
|
|
sortDirection?: "asc" | "desc";
|
|
filters?: Partial<Record<AuditSortBy, string>>;
|
|
};
|
|
|
|
export type AuditAdminListResponse = {
|
|
items: AuditAdminItem[];
|
|
total: number;
|
|
page: number;
|
|
page_size: number;
|
|
pages: number;
|
|
cursor?: string | null;
|
|
next_cursor?: string | null;
|
|
};
|
|
|
|
export type AuditAdminDeltaResponse = AuditAdminListResponse & {
|
|
deleted: DeltaDeletedItem[];
|
|
watermark?: string | null;
|
|
has_more: boolean;
|
|
full: boolean;
|
|
};
|
|
|
|
export type EvidenceBundleExportRequest = {
|
|
scope: "tenant" | "system" | "all";
|
|
tenant_id?: string | null;
|
|
record_ids?: string[];
|
|
max_records?: number;
|
|
sign?: boolean;
|
|
};
|
|
|
|
export type EvidenceBundleResponse = {
|
|
id: string;
|
|
scope: "tenant" | "system" | "all";
|
|
tenant_id?: string | null;
|
|
status: "pending" | "ready" | "failed";
|
|
bundle_sha256?: string | null;
|
|
record_count: number;
|
|
reference_count: number;
|
|
generated_at?: string | null;
|
|
download_url?: string | null;
|
|
};
|
|
|
|
export type EvidenceBundleDownloadResponse = {
|
|
bundle: Record<string, unknown>;
|
|
};
|
|
|
|
function auditQuery(options: AuditQueryOptions & { since?: string | null } = {}): string {
|
|
const params = new URLSearchParams();
|
|
if (options.tenantId) params.set("tenant_id", options.tenantId);
|
|
if (options.allTenants) params.set("all_tenants", "true");
|
|
if (options.scope) params.set("scope", options.scope);
|
|
if (options.limit) params.set("limit", String(options.limit));
|
|
if (options.offset) params.set("offset", String(options.offset));
|
|
if (options.page) params.set("page", String(options.page));
|
|
if (options.pageSize) params.set("page_size", String(options.pageSize));
|
|
if (options.cursor) params.set("cursor", options.cursor);
|
|
if (options.sortBy) params.set("sort_by", options.sortBy);
|
|
if (options.sortDirection) params.set("sort_direction", options.sortDirection);
|
|
if (options.since) params.set("since", options.since);
|
|
for (const [column, value] of Object.entries(options.filters ?? {})) {
|
|
if (value?.trim()) params.set(`filter_${column}`, value);
|
|
}
|
|
const suffix = params.toString();
|
|
return suffix ? `?${suffix}` : "";
|
|
}
|
|
|
|
export function fetchAdminAudit(settings: ApiSettings, options: AuditQueryOptions = {}): Promise<AuditAdminListResponse> {
|
|
return apiFetch(settings, `/api/v1/admin/audit${auditQuery(options)}`);
|
|
}
|
|
|
|
export function fetchAdminAuditDelta(settings: ApiSettings, options: AuditQueryOptions & { since?: string | null } = {}): Promise<AuditAdminDeltaResponse> {
|
|
return apiFetch(settings, `/api/v1/admin/audit/delta${auditQuery(options)}`);
|
|
}
|
|
|
|
export function exportAuditEvidenceBundle(
|
|
settings: ApiSettings,
|
|
payload: EvidenceBundleExportRequest
|
|
): Promise<EvidenceBundleResponse> {
|
|
return apiFetch(settings, "/api/v1/admin/audit/evidence-bundles", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export function downloadAuditEvidenceBundle(
|
|
settings: ApiSettings,
|
|
bundleId: string
|
|
): Promise<EvidenceBundleDownloadResponse> {
|
|
return apiFetch(settings, `/api/v1/admin/audit/evidence-bundles/${bundleId}/download`);
|
|
}
|