eslint and build
Some checks failed
CI / Rustfmt (push) Successful in 22s
CI / Cargo Audit & Deny (push) Failing after 32s
CI / Web Blocking Checks (push) Successful in 47s
CI / Security Blocking Checks (push) Successful in 9s
CI / Clippy (push) Successful in 2m9s
CI / Web Advisory Checks (push) Successful in 37s
CI / Security Advisory Checks (push) Successful in 34s
CI / Tests (push) Failing after 8m37s

This commit is contained in:
2026-03-05 08:18:07 -06:00
parent 179180d604
commit c61fe26713
9 changed files with 51 additions and 27 deletions

View File

@@ -4,7 +4,9 @@ import { useCreatePack, useUpdatePack } from "@/hooks/usePacks";
import type { PackResponse } from "@/api"; import type { PackResponse } from "@/api";
import { labelToRef } from "@/lib/format-utils"; import { labelToRef } from "@/lib/format-utils";
import SchemaBuilder from "@/components/common/SchemaBuilder"; import SchemaBuilder from "@/components/common/SchemaBuilder";
import ParamSchemaForm from "@/components/common/ParamSchemaForm"; import ParamSchemaForm, {
type ParamSchema,
} from "@/components/common/ParamSchemaForm";
import { RotateCcw } from "lucide-react"; import { RotateCcw } from "lucide-react";
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -603,7 +605,7 @@ export default function PackForm({ pack, onSuccess, onCancel }: PackFormProps) {
</p> </p>
</div> </div>
<ParamSchemaForm <ParamSchemaForm
schema={confSchema} schema={confSchema as unknown as ParamSchema}
values={configValues} values={configValues}
onChange={setConfigValues} onChange={setConfigValues}
errors={errors} errors={errors}

View File

@@ -15,6 +15,7 @@ import type {
TriggerResponse, TriggerResponse,
ActionResponse, ActionResponse,
} from "@/types/api"; } from "@/types/api";
import type { CreateRuleRequest, UpdateRuleRequest } from "@/api";
import { labelToRef, extractLocalRef, combineRefs } from "@/lib/format-utils"; import { labelToRef, extractLocalRef, combineRefs } from "@/lib/format-utils";
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -205,7 +206,7 @@ export default function RuleForm({ rule, onSuccess, onCancel }: RuleFormProps) {
// Combine pack ref and local ref to create full ref // Combine pack ref and local ref to create full ref
const fullRef = combineRefs(selectedPackData?.ref || "", localRef.trim()); const fullRef = combineRefs(selectedPackData?.ref || "", localRef.trim());
const formData: Record<string, JsonValue> = { const formData: Record<string, JsonValue> & Partial<CreateRuleRequest> = {
pack_ref: selectedPackData?.ref || "", pack_ref: selectedPackData?.ref || "",
ref: fullRef, ref: fullRef,
label: label.trim(), label: label.trim(),
@@ -232,9 +233,14 @@ export default function RuleForm({ rule, onSuccess, onCancel }: RuleFormProps) {
try { try {
if (isEditing && rule) { if (isEditing && rule) {
await updateRule.mutateAsync({ ref: rule.ref, data: formData }); await updateRule.mutateAsync({
ref: rule.ref,
data: formData as unknown as UpdateRuleRequest,
});
} else { } else {
const newRuleResponse = await createRule.mutateAsync(formData); const newRuleResponse = await createRule.mutateAsync(
formData as unknown as CreateRuleRequest,
);
if (!onSuccess) { if (!onSuccess) {
navigate(`/rules/${newRuleResponse.data.ref}`); navigate(`/rules/${newRuleResponse.data.ref}`);
} }

View File

@@ -68,7 +68,9 @@ export default function TriggerForm({
setPackId(pack.id); setPackId(pack.id);
} }
// Extract local ref from full ref // Extract local ref from full ref
setLocalRef(extractLocalRef(initialData.ref, initialData.pack_ref)); setLocalRef(
extractLocalRef(initialData.ref, initialData.pack_ref ?? undefined),
);
} }
} }
}, [initialData, packs, isEditing]); }, [initialData, packs, isEditing]);

View File

@@ -213,7 +213,9 @@ export default function WorkflowInputsPanel({
<SchemaBuilder <SchemaBuilder
value={draftSchema} value={draftSchema}
onChange={(schema) => onChange={(schema) =>
setDraftSchema(schema as Record<string, ParamDefinition>) setDraftSchema(
schema as unknown as Record<string, ParamDefinition>,
)
} }
placeholder={ placeholder={
modalTarget === "parameters" modalTarget === "parameters"

View File

@@ -1,6 +1,9 @@
import { useCallback } from "react"; import { useCallback } from "react";
import { useQueryClient } from "@tanstack/react-query"; import { useQueryClient } from "@tanstack/react-query";
import { useEntityNotifications } from "@/contexts/WebSocketContext"; import {
useEntityNotifications,
type Notification,
} from "@/contexts/WebSocketContext";
interface UseArtifactStreamOptions { interface UseArtifactStreamOptions {
/** /**
@@ -62,7 +65,8 @@ export function useArtifactStream(options: UseArtifactStreamOptions = {}) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const handleNotification = useCallback( const handleNotification = useCallback(
(notification: ArtifactNotification) => { (raw: Notification) => {
const notification = raw as unknown as ArtifactNotification;
const payload = notification.payload; const payload = notification.payload;
// If we're filtering by execution ID, only process matching artifacts // If we're filtering by execution ID, only process matching artifacts

View File

@@ -1,6 +1,9 @@
import { useCallback } from "react"; import { useCallback } from "react";
import { useQueryClient } from "@tanstack/react-query"; import { useQueryClient } from "@tanstack/react-query";
import { useEntityNotifications } from "@/contexts/WebSocketContext"; import {
useEntityNotifications,
type Notification,
} from "@/contexts/WebSocketContext";
import type { EnforcementSummary } from "@/api"; import type { EnforcementSummary } from "@/api";
interface UseEnforcementStreamOptions { interface UseEnforcementStreamOptions {
@@ -120,7 +123,8 @@ export function useEnforcementStream(
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const handleNotification = useCallback( const handleNotification = useCallback(
(notification: EnforcementNotification) => { (raw: Notification) => {
const notification = raw as unknown as EnforcementNotification;
// Filter by enforcement ID if specified // Filter by enforcement ID if specified
if (enforcementId && notification.entity_id !== enforcementId) { if (enforcementId && notification.entity_id !== enforcementId) {
return; return;

View File

@@ -1,7 +1,10 @@
import { useCallback } from "react"; import { useCallback } from "react";
import { useQueryClient } from "@tanstack/react-query"; import { useQueryClient } from "@tanstack/react-query";
import { useEntityNotifications } from "@/contexts/WebSocketContext"; import {
import type { ExecutionSummary } from "@/api"; useEntityNotifications,
type Notification,
} from "@/contexts/WebSocketContext";
import type { ExecutionSummary, ExecutionStatus } from "@/api";
interface UseExecutionStreamOptions { interface UseExecutionStreamOptions {
/** /**
@@ -132,10 +135,8 @@ function executionMatchesParams(
return false; return false;
} }
// Check executor filter (may be present) // Note: executor is not part of ExecutionSummary so we cannot filter on it
if (params.executor !== undefined && execution.executor !== params.executor) { // from WebSocket payloads. Executor-filtered queries rely on API refetch.
return false;
}
// Note: rule_ref and trigger_ref are NOT checked here because they may not be // Note: rule_ref and trigger_ref are NOT checked here because they may not be
// present in WebSocket payloads (they come from enforcement data which is // present in WebSocket payloads (they come from enforcement data which is
@@ -152,7 +153,7 @@ function hasUnsupportedFilters(
params: ExecutionQueryParams | undefined, params: ExecutionQueryParams | undefined,
): boolean { ): boolean {
if (!params) return false; if (!params) return false;
return !!(params.ruleRef || params.triggerRef); return !!(params.ruleRef || params.triggerRef || params.executor);
} }
/** /**
@@ -175,21 +176,23 @@ export function useExecutionStream(options: UseExecutionStreamOptions = {}) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const handleNotification = useCallback( const handleNotification = useCallback(
(notification: ExecutionNotification) => { (notification: Notification) => {
const executionNotification =
notification as unknown as ExecutionNotification;
// Filter by execution ID if specified // Filter by execution ID if specified
if (executionId && notification.entity_id !== executionId) { if (executionId && executionNotification.entity_id !== executionId) {
return; return;
} }
// Extract execution data from notification payload (flat structure). // Extract execution data from notification payload (flat structure).
// Keep raw payload for old_status inspection, but use cleaned data for cache. // Keep raw payload for old_status inspection, but use cleaned data for cache.
const rawPayload = notification.payload; const rawPayload = executionNotification.payload;
const oldStatus: string | undefined = rawPayload?.old_status; const oldStatus: string | undefined = rawPayload?.old_status;
const executionData = stripNotificationMeta(rawPayload); const executionData = stripNotificationMeta(rawPayload);
// Update specific execution query if it exists // Update specific execution query if it exists
queryClient.setQueryData( queryClient.setQueryData(
["executions", notification.entity_id], ["executions", executionNotification.entity_id],
(old: ExecutionDetailCache | undefined) => { (old: ExecutionDetailCache | undefined) => {
if (!old) return old; if (!old) return old;
return { return {
@@ -223,7 +226,7 @@ export function useExecutionStream(options: UseExecutionStreamOptions = {}) {
// Check if execution already exists in the list // Check if execution already exists in the list
const existingIndex = old.data.findIndex( const existingIndex = old.data.findIndex(
(exec) => exec.id === notification.entity_id, (exec) => exec.id === executionNotification.entity_id,
); );
// Merge the updated fields to determine if the execution matches the query // Merge the updated fields to determine if the execution matches the query
@@ -266,7 +269,7 @@ export function useExecutionStream(options: UseExecutionStreamOptions = {}) {
// not in our local data array, total_items must stay accurate. // not in our local data array, total_items must stay accurate.
const virtualOldExecution = { const virtualOldExecution = {
...mergedExecution, ...mergedExecution,
status: oldStatus, status: oldStatus as ExecutionStatus,
}; };
const oldMatchedQuery = executionMatchesParams( const oldMatchedQuery = executionMatchesParams(
virtualOldExecution, virtualOldExecution,

View File

@@ -551,11 +551,11 @@ function ActionDetail({ actionRef }: { actionRef: string }) {
</span> </span>
<span <span
className={`px-2 py-1 text-xs rounded ${ className={`px-2 py-1 text-xs rounded ${
execution.status === "Completed" execution.status === "completed"
? "bg-green-100 text-green-800" ? "bg-green-100 text-green-800"
: execution.status === "Failed" : execution.status === "failed"
? "bg-red-100 text-red-800" ? "bg-red-100 text-red-800"
: execution.status === "Running" : execution.status === "running"
? "bg-blue-100 text-blue-800" ? "bg-blue-100 text-blue-800"
: "bg-gray-100 text-gray-800" : "bg-gray-100 text-gray-800"
}`} }`}

View File

@@ -219,6 +219,7 @@ export interface ParamDefinition {
secret?: boolean; secret?: boolean;
default?: unknown; default?: unknown;
enum?: string[]; enum?: string[];
[key: string]: unknown;
} }
/** Workflow definition as stored in the YAML file / API */ /** Workflow definition as stored in the YAML file / API */