diff --git a/src/store/reducer.ts b/src/store/reducer.ts new file mode 100644 index 0000000..d27e7ed --- /dev/null +++ b/src/store/reducer.ts @@ -0,0 +1,44 @@ +// src/store/reducer.ts +// Pure reducer — no side effects, no localStorage, no async operations. + +import { WizardState, WizardAction, INITIAL_STATE } from './types'; + +export function wizardReducer( + state: WizardState = INITIAL_STATE, + action: WizardAction +): WizardState { + switch (action.type) { + case 'SET_STEP': + return { ...state, currentStep: action.payload }; + + case 'SET_BACKEND_TYPE': + return { + ...state, + remote: { ...state.remote, backendType: action.payload }, + }; + + case 'SET_REMOTE_NAME': + return { + ...state, + remote: { ...state.remote, name: action.payload }, + }; + + case 'SET_REMOTE_PARAMS': + return { + ...state, + remote: { ...state.remote, params: action.payload }, + }; + + case 'SET_DEPLOYMENT': + return { + ...state, + deployment: { ...state.deployment, ...action.payload }, + }; + + case 'RESET': + return INITIAL_STATE; + + default: + return state; + } +} diff --git a/src/store/types.ts b/src/store/types.ts new file mode 100644 index 0000000..8466292 --- /dev/null +++ b/src/store/types.ts @@ -0,0 +1,46 @@ +// src/store/types.ts +// WizardState shape, action union type, and initial state. +// SECURITY: This state is exclusively in-memory. +// NEVER add localStorage.setItem, sessionStorage.setItem, or IndexedDB here. +// Closing the browser tab is the intended "clear credentials" operation (SECU-03). + +import type { BackendType } from '../schemas/registry'; + +// Re-export BackendType so store consumers import from one place +export type { BackendType }; + +export interface WizardState { + currentStep: number; + remote: { + name: string; + backendType: BackendType | null; + params: Record; // backend-specific key/value pairs (rclone config keys) + }; + deployment: { + includeInstall: boolean; + configPath: 'machine-wide' | 'user-profile'; // machine-wide = C:\ProgramData\rclone\ + scriptTargets: ('intune' | 'rmm')[]; + }; +} + +export type WizardAction = + | { type: 'SET_STEP'; payload: number } + | { type: 'SET_BACKEND_TYPE'; payload: BackendType } + | { type: 'SET_REMOTE_NAME'; payload: string } + | { type: 'SET_REMOTE_PARAMS'; payload: Record } + | { type: 'SET_DEPLOYMENT'; payload: Partial } + | { type: 'RESET' }; + +export const INITIAL_STATE: WizardState = { + currentStep: 0, + remote: { + name: '', + backendType: null, + params: {}, + }, + deployment: { + includeInstall: false, + configPath: 'machine-wide', + scriptTargets: ['intune', 'rmm'], + }, +};