Some checks failed
Test / rust-fmt-check (pull_request) Successful in 2m3s
Test / frontend-tests (pull_request) Successful in 1m56s
Test / frontend-typecheck (pull_request) Successful in 1m58s
Test / rust-clippy (pull_request) Failing after 3m0s
Test / rust-tests (pull_request) Successful in 4m22s
PR Review Automation / review (pull_request) Successful in 4m35s
Addresses three findings from the third automated review: [BLOCKER] No frontend PII pre-check on attachments. Added detectPiiCmd call for each logFileId before chatMessageCmd. PII is not blocked (per explicit product decision: auto-redact and send) but the user now sees a non-blocking amber notice listing each file and the PII types that will be auto-redacted. Backend remains the authoritative redaction layer. [WARNING 2] Chat bubble showed original PII-laden message even though only the redacted form was sent to AI. Added updateMessageContent to sessionStore. After chatMessageCmd returns, if response.user_message is set the user bubble is updated to reflect what was actually stored in the DB, so the UI is consistent with the audit log. CI fix: cargo fmt changes to analysis.rs were not staged in the prior commit. Committed here — fmt check now passes cleanly.
57 lines
2.0 KiB
TypeScript
57 lines
2.0 KiB
TypeScript
import { create } from "zustand";
|
|
import type { Issue, TriageMessage, PiiSpan, ResolutionStep } from "@/lib/tauriCommands";
|
|
|
|
interface SessionState {
|
|
currentIssue: Issue | null;
|
|
messages: TriageMessage[];
|
|
piiSpans: PiiSpan[];
|
|
approvedRedactions: PiiSpan[];
|
|
currentWhyLevel: number;
|
|
activeDomain: string;
|
|
resolutionSteps: ResolutionStep[];
|
|
isLoading: boolean;
|
|
error: string | null;
|
|
|
|
startSession: (issue: Issue) => void;
|
|
addMessage: (message: TriageMessage) => void;
|
|
updateMessageContent: (id: string, content: string) => void;
|
|
setPiiSpans: (spans: PiiSpan[]) => void;
|
|
setApprovedRedactions: (spans: PiiSpan[]) => void;
|
|
setWhyLevel: (level: number) => void;
|
|
setActiveDomain: (domain: string) => void;
|
|
setResolutionSteps: (steps: ResolutionStep[]) => void;
|
|
setLoading: (loading: boolean) => void;
|
|
setError: (error: string | null) => void;
|
|
reset: () => void;
|
|
}
|
|
|
|
const initialState = {
|
|
currentIssue: null,
|
|
messages: [],
|
|
piiSpans: [],
|
|
approvedRedactions: [],
|
|
currentWhyLevel: 0,
|
|
activeDomain: "general",
|
|
resolutionSteps: [],
|
|
isLoading: false,
|
|
error: null,
|
|
};
|
|
|
|
export const useSessionStore = create<SessionState>((set) => ({
|
|
...initialState,
|
|
startSession: (issue) => set({ currentIssue: issue, messages: [], currentWhyLevel: 1, activeDomain: issue.category }),
|
|
addMessage: (message) => set((state) => ({ messages: [...state.messages, message] })),
|
|
updateMessageContent: (id, content) =>
|
|
set((state) => ({
|
|
messages: state.messages.map((m) => (m.id === id ? { ...m, content } : m)),
|
|
})),
|
|
setPiiSpans: (spans) => set({ piiSpans: spans }),
|
|
setApprovedRedactions: (spans) => set({ approvedRedactions: spans }),
|
|
setWhyLevel: (level) => set({ currentWhyLevel: level }),
|
|
setActiveDomain: (domain) => set({ activeDomain: domain }),
|
|
setResolutionSteps: (steps) => set({ resolutionSteps: steps }),
|
|
setLoading: (loading) => set({ isLoading: loading }),
|
|
setError: (error) => set({ error }),
|
|
reset: () => set(initialState),
|
|
}));
|