> ## Documentation Index
> Fetch the complete documentation index at: https://blog.mapptech.com.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Core Workflow & Example

> Detailed explanation of the standard Client -> Action -> Machine -> Service flow, with a concrete Create User example.

## Flow Steps

1. **Client Interaction (Presentation Layer):** User interaction occurs in a React component (`page.tsx` or optional `container/`) within an `apps/*` application. It prepares data matching the expected input shape (e.g., `CreateUserInput`).
2. **Call Server Action (API Entry Point):** The component invokes an imported Server Action function (`@core/actions`). This function is marked with `'use server'`. It receives the raw input from the client.
3. **Resolve Validated Service Instance (Action):** The Server Action:
   * Determines the required service implementation type (e.g., based on context, tenant ID).
   * Calls the appropriate Service Factory function (e.g., `getValidatedUserService(type)` from `@core/services/[domain]/userServiceFactory.ts`). This factory internally uses the `serviceMap` to get the base implementation and then applies validation wrappers (like `createServiceMethod`) to its methods using the relevant argument schemas (`@core/lib/schemas`). The factory returns the **validated service instance**.
4. **Instantiate & Start Machine (Action):** The Action:
   * **Instantiates** (`interpret`) the relevant XState machine (`@core/machines`), providing the **resolved and validated service instance** via the initial `context`.
   * **Starts** the machine interpreter.
   * **Sends the initial event** (e.g., `{ type: 'CREATE', input: rawClientInput }`) to the machine, passing the *original input* received from the client. **Note:** Validation happens *later* when the service method is invoked.
   * Listens/awaits the machine reaching a final state.
5. **Orchestrate Logic (Machine):** The XState machine transitions through its states based on events and its internal context. Its primary role is orchestration.
6. **Prepare Service Input & Invoke (Machine):** Within specific states (often using `invoke` services or `entry`/`exit` actions), the machine:
   * **Constructs the appropriate Service Input DTO** (defined in `services/[domain]/domain/[Domain]Types.ts`) using data from its context (like the `input` received in the initial event).
   * **Calls the appropriate method on the validated Service implementation** (passed via context) using the prepared DTO (e.g., `context.userService.createUser(serviceInputDto)`). This call now triggers the validation wrapper.
7. **Validate & Execute (Service Wrapper -> Service Implementation):**
   * The `createServiceMethod` wrapper function executes.
   * It **validates** the arguments (containing the Service Input DTO) against its pre-configured Yup schema.
   * If validation fails, the wrapper **throws** a `yup.ValidationError`.
   * If validation succeeds, the wrapper calls the **original, unwrapped service implementation method**.
   * The core service logic executes, potentially throwing its own execution errors.
8. **Process Service Output/Error & Update Context (Machine):** When the invoked service call completes (or throws):
   * The machine's `invoke` configuration handles the outcome.
   * `onDone`: If successful, the machine receives the **Service Output DTO**. It updates its internal context based on the DTO's structure (e.g., extracting the `User` entity).
   * `onError`: If the `invoke` catches an error (either `yup.ValidationError` from the wrapper or an execution error from the implementation), the machine updates its context with error details (e.g., setting `context.error` and potentially `context.validationErrors`).
9. **Reach Final State (Machine):** The machine eventually transitions to a terminal state (e.g., `success`, `failure`), indicated by `type: 'final'`, potentially outputting its final context.
10. **Return Structured Result (Action → Client):** The Server Action, having awaited the machine's final state:
    * Inspects the machine's final state and output/context.
    * Formats the outcome into a standard `ActionResult` object (e.g., `{ success: true, data: finalMachineOutput.user }` or `{ success: false, error: finalMachineOutput.error, validationErrors: finalMachineOutput.validationErrors }`).
    * Returns this `ActionResult` to the calling client component.

<Note>
  **Clear Roles:**

  * **Client (`apps/*`)**: Renders UI, captures user input, calls Actions, displays results/errors from `ActionResult`.
  * **Action (`@core/actions`)**: API boundary. Resolves correct *validated* service, interprets & starts Machine, awaits result, formats `ActionResult` based on machine outcome. Initial *input validation* is now deferred to the service wrapper.
  * **Machine (`@core/machines`)**: Orchestrates flow (XState). Maps client input to Service DTOs, invokes *validated* Service methods, processes Service output DTOs or catches errors (including validation errors) from the `invoke`, manages internal state/context.
  * **Service Factory (`@core/services/[domain]/userServiceFactory.ts`)**: Retrieves base implementation (via `serviceMap`), applies validation wrappers (`createServiceMethod`) to methods, returns the composed, validated service object.
  * **Service Implementation (`@core/services/[domain]/implementations`)**: Executes discrete tasks, contains core logic. Defines contract (Interface + DTOs in `domain/`). Assumes input is valid by the time its methods are called.
</Note>

***

## Abbreviated Example: Create User Flow (Action → Machine → Service with Wrapped Validation)

This simplified example demonstrates the core flow: Action resolves the validated service and starts the machine, the machine prepares a DTO and calls the validated service method, the wrapper validates, the implementation performs the work, and the result/error flows back through the machine to the action.

**1. Base Types (`@core/types`)**

```typescript theme={null}
// packages/core/types/entities/User.ts
export interface User {
  id: string;
  name: string;
  email: string;
  createdAt: Date;
}
```

```typescript theme={null}
// packages/core/types/common/ActionResult.ts
// Standardized Action Result Structure for the client
export interface ActionResult<TData = any, TError = string> {
	success: boolean;
	data?: TData; // Holds the final relevant data (e.g., the created User)
	error?: TError; // Holds general error message or structured error
	validationErrors?: { path: string; message: string }[]; // Specific validation errors
}
```

```typescript theme={null}
// packages/core/types/machines/user/UserCreationMachineTypes.ts
import type { User } from '../../entities/User';
// Use the type derived from the Yup schema for validated input
import type { CreateUserInput } from '../../../../validation/userSchema'; // Adjust path if needed
import type { UserService } from '../../../services/user/domain/UserService'; // Service Interface for context typing

// Machine Context: Stores input, potential result (User), error info, and service instance.
export interface UserCreationMachineContext {
	input?: CreateUserInput; // Holds the input received via the CREATE event
	user?: User; // Holds the final User entity after successful service call
	error?: string; // Holds error message from service failure or validation failure caught by invoke
	validationErrors?: { path: string; message: string }[]; // Specific validation errors caught by invoke
	userService?: UserService; // The resolved (and potentially validated) service instance
}

// Machine Events
export type UserCreationMachineEvent =
	| { type: 'CREATE'; input: CreateUserInput } // Event carries input
	| { type: 'RETRY' }; // Example event for retry logic
```

**2. Client Input Validation Schema (`@core/validation`)**

```typescript theme={null}
// packages/core/validation/userSchema.ts
// Defines the shape expected from the client / sent in the action payload.
import * as yup from 'yup';

export const userSchema = yup.object({
  name: yup.string().required("Name is required").min(2, 'Name is too short.'),
  email: yup.string().email("Invalid email format").required("Email is required"),
});

// Type derived from the validation schema
export type CreateUserInput = yup.InferType<typeof userSchema>;
```

**3. Service Definition (`@core/services/user/domain`)**

```typescript theme={null}
// packages/core/services/user/domain/UserTypes.ts
import type { User } from '../../../types/entities/User';

// --- Service Method DTOs ---
export interface CreateUserMethodInput {
  name: string;
  email: string;
}
export interface CreateUserMethodOutput {
  user: User;
}
```

```typescript theme={null}
// packages/core/services/user/domain/UserService.ts
import type { CreateUserMethodInput, CreateUserMethodOutput } from './UserTypes';

// --- Service Interface (Contract) ---
export interface UserService {
  createUser(data: CreateUserMethodInput): Promise<CreateUserMethodOutput>;
}
```

**4. Service Implementation (`@core/services/user/implementations`)**

```typescript theme={null}
// packages/core/services/user/implementations/DefaultUserService.ts
import type { UserService } from '../domain/UserService';
import type { CreateUserMethodInput, CreateUserMethodOutput } from '../domain/UserTypes';
import type { User } from '../../../types/entities/User';

// Concrete implementation - NO validation logic here.
export class DefaultUserService implements UserService {
  async createUser(data: CreateUserMethodInput): Promise<CreateUserMethodOutput> {
    console.log('IMPLEMENTATION (DefaultUserService): Processing DTO:', data);
    // Assumes 'data' is valid because the wrapper validated it
    const newUserEntity: User = {
      id: crypto.randomUUID(),
      name: data.name,
      email: data.email,
      createdAt: new Date(),
    };
    await new Promise((resolve) => setTimeout(resolve, 50)); // Simulate async work
    console.log('IMPLEMENTATION (DefaultUserService): Entity created:', newUserEntity);
    return { user: newUserEntity };
  }
}
```

**5. Service Argument Validation Schema (`@core/lib/schemas`)**

```typescript theme={null}
// packages/core/lib/schemas/user.schemas.ts
// Defines schemas for the *arguments* passed to service methods.
import * as yup from 'yup';
// Import the base validation schema to ensure consistency
import { userSchema } from '../../../validation/userSchema'; // Adjust path

// Schema for the arguments tuple of the createUser method.
// createUser expects one argument: an object matching CreateUserMethodInput (derived from userSchema).
export const CreateUserArgsSchema = yup.tuple([
    // Use the userSchema for the first (and only) argument.
    userSchema.required('User data is required.'),
]).defined();
```

**6. Service Resolution (`@core/services/user/serviceMap.ts` & `userServiceFactory.ts`)**

```typescript theme={null}
// packages/core/services/user/serviceMap.ts
import type { UserService } from './domain/UserService';
import { DefaultUserService } from './implementations/DefaultUserService';

// Holds UNWRAPPED instances
const serviceImplementations: Record<string, UserService> = {
  default: new DefaultUserService(),
  // clientA: new ClientAUserService(),
};

// Gets the BASE implementation
export function getBaseUserService(type: string = 'default'): UserService {
  const serviceKey = type.toLowerCase();
  const serviceInstance = serviceImplementations[serviceKey];
  if (!serviceInstance) {
    const fallbackInstance = serviceImplementations['default'];
    if (fallbackInstance) {
       console.warn(`UserService strategy type "${type}" not found, falling back to default.`);
       return fallbackInstance;
    }
    throw new Error(`UserService strategy type "${type}" not found and no default is available.`);
  }
  return serviceInstance;
}
```

```typescript theme={null}
// packages/core/services/user/userServiceFactory.ts
// *** Applies validation wrappers ***
import { getBaseUserService } from './serviceMap';
import type { UserService } from './domain/UserService';
// Adjust path to where your createServiceMethod utility resides
import { createServiceMethod } from '@/server-utils/utils/create-service-method';
// Import the *argument* schema for validation
import { CreateUserArgsSchema } from '../../lib/schemas/user.schemas';

// Factory that returns the VALIDATED service instance
export function getValidatedUserService(type: string = 'default'): UserService {
  // 1. Get the base implementation
  const baseServiceInstance = getBaseUserService(type);

  // 2. Wrap its methods with validation
  const validatedCreateUser = createServiceMethod(
    baseServiceInstance,
    'createUser',        // Method name from interface
    CreateUserArgsSchema // Argument validation schema
  );

  // 3. Return the composed service with wrapped methods
  return {
    createUser: validatedCreateUser,
    // wrap other methods...
  };
}
```

```typescript theme={null}
// packages/core/services/user/index.ts
// Barrel file exporting the factory function that provides the *validated* service
export { getValidatedUserService } from './userServiceFactory';
```

**7. XState Machine (`@core/machines`)**

```typescript theme={null}
// packages/core/machines/userCreationMachine.ts
import { createMachine, assign } from 'xstate';
import * as yup from 'yup';
import type {
    UserCreationMachineContext,
    UserCreationMachineEvent
} from '../types/machines/user/UserCreationMachineTypes'; // Adjust path
import type {
    CreateUserMethodInput,
    CreateUserMethodOutput
} from '../services/user/domain/UserTypes'; // Adjust path
import type { UserService } from '../services/user/domain/UserService'; // Adjust path

export const userCreationMachine = createMachine({
  id: 'userCreation',
  types: {} as { context: UserCreationMachineContext, events: UserCreationMachineEvent },
  initial: 'idle',
  context: {
    input: undefined,
    user: undefined,
    error: undefined,
    validationErrors: undefined, // For storing Yup errors
    userService: undefined, // Injected, expected to be the *validated* one
  },
  states: {
    idle: {
      on: {
        CREATE: {
          target: 'creating',
          guard: ({ context }) => !!context.userService,
          actions: assign({
            input: ({ event }) => event.input, // Store raw input
            error: undefined,
            validationErrors: undefined,
          }),
        },
      },
    },
    creating: {
      invoke: {
        id: 'invokeCreateUserService',
        src: async ({ context }) => { // Calls the potentially validated service
          if (!context.userService || !context.input) {
            throw new Error('Machine context prerequisites not met.');
          }
          const serviceInput: CreateUserMethodInput = { // Prepare DTO
            name: context.input.name,
            email: context.input.email,
          };
          console.log('MACHINE: Invoking context.userService.createUser with DTO:', serviceInput);
          // This call might throw yup.ValidationError or an execution error
          return await context.userService.createUser(serviceInput);
        },
        onDone: { // Service call (including validation) succeeded
          target: 'success',
          actions: assign({
            user: ({ event }) => (event.output as CreateUserMethodOutput).user,
          }),
        },
        onError: { // Handle errors caught from invoke
						target: 'failure',
						actions: assign({
							error: ({ event }) => {
								const error = event.data as unknown;
								// <<< Check for ServiceValidationError FIRST >>>
								if (error instanceof ServiceValidationError) {
									console.error(
										'MACHINE: Caught Service Validation Error:',
										error.validationErrors,
									);
									// Use the message from the custom error
									return error.message;
								}
								// Fallback for other execution errors
								if (error instanceof Error) {
									console.error(
										'MACHINE: Caught Service Execution Error:',
										error.message,
									);
									return error.message;
								}
								return 'User creation failed due to an unknown service error';
							},
							validationErrors: ({ event }) => {
								const error = event.data as unknown;
								// <<< Extract details from ServiceValidationError >>>
								if (error instanceof ServiceValidationError) {
                                    // Reconstruct format if needed, or use error.validationErrors directly if structure matches
									return error.validationErrors.map(message => ({ path: error.path ?? 'unknown', message }));
								}
								return undefined; // Clear if not a validation error
							},
						}),
					},
      },
    },
    success: {
      type: 'final',
      output: ({ context }) => ({ user: context.user }), // Output final data
    },
    failure: {
      type: 'final',
      output: ({ context }) => ({ error: context.error, validationErrors: context.validationErrors }), // Output error info
    },
  },
});
```

**8. Server Action (`@core/actions`)**

```typescript theme={null}
// packages/core/actions/userActions.ts
'use server';

// Import the factory that provides the *validated* service
import { getValidatedUserService } from '../services/user/userServiceFactory'; // Adjust path
import { userCreationMachine } from '../machines/userCreationMachine'; // Adjust path
import { interpret, Actor } from 'xstate';
// Import types
import type { CreateUserInput } from '../validation/userSchema'; // Adjust path
import type { ActionResult } from '../types/common/ActionResult'; // Adjust path
import type { User } from '../types/entities/User'; // Adjust path
import type { UserCreationMachineContext } from '../types/machines/user/UserCreationMachineTypes';

// Server Action orchestrates service resolution and machine execution
export async function createUserAction(
  input: CreateUserInput, // Action receives raw client input
  serviceType: string = 'default' // Example: Determine service type
): Promise<ActionResult<User>> { // Promises the standard result structure
  console.log(`ACTION: Received input for service type "${serviceType}":`, input);
  let machineActor: Actor<typeof userCreationMachine> | undefined = undefined;

  try {
    // 1. Resolve the VALIDATED Service Instance using the factory
    const validatedUserService = getValidatedUserService(serviceType);
    console.log(`ACTION: Resolved validated UserService instance for type "${serviceType}"`);

    // 2. Interpret and run the XState machine
    console.log('ACTION: Interpreting userCreationMachine...');
    return new Promise((resolve) => {
      machineActor = interpret(
        userCreationMachine.withContext({
            // Inject the resolved **validated** service instance
            userService: validatedUserService,
            // Initialize other context fields
            input: undefined,
            user: undefined,
            error: undefined,
            validationErrors: undefined,
        })
      )
        .onDone((event) => { // Machine reached a final state
            const finalOutput = event.output as Partial<UserCreationMachineContext>; // Get data from final state
            console.log('ACTION: Machine finished. Final Output:', finalOutput);
            if (finalOutput?.user) { // Success case
                resolve({ success: true, data: finalOutput.user });
            } else { // Failure case (includes validation errors caught by machine)
                resolve({
                    success: false,
                    error: finalOutput?.error ?? 'Machine failed without specific error',
                    validationErrors: finalOutput?.validationErrors // Pass captured validation errors
                });
            }
        })
        .onStop(() => console.log("ACTION: Machine actor stopped."))
        .start(); // Start the machine

      // 3. Send the initial event with the raw client input
      // Validation will occur when the machine invokes the service method
      console.log('ACTION: Sending CREATE event to machine with input:', input);
      machineActor.send({ type: 'CREATE', input: input });
    });

  } catch (error) {
    // Handle errors during service resolution or machine setup
    console.error(`ACTION: Unexpected error during setup for service type "${serviceType}":`, error);
    return {
      success: false,
      error: error instanceof Error ? error.message : 'An unexpected server setup error occurred.',
    };
  } finally {
      // Optional: Ensure actor cleanup
      if (machineActor?.status === 1) machineActor.stop();
  }
}
```

**9. UI Page (`apps/[appName]/app/.../page.tsx`)**

```typescript theme={null}
// apps/radicacion/app/crear-usuario/page.tsx (Example - Simplified UI)
'use client';
import React, { useState, useTransition, FormEvent } from 'react';
// Use the action defined above
import { createUserAction } from '@core/actions/userActions'; // Adjust path
import type { CreateUserInput } from '@core/validation/userSchema'; // Adjust path
import type { ActionResult } from '@core/types/common/ActionResult'; // Adjust path
import type { User } from '@core/types/entities/User'; // Adjust path
// --- Import actual Design System components ---
// import { Button } from 'mappnext/ds-tw/atoms/Button';
// import { InputField } from 'mappnext/ds-tw/molecules/InputField';
// --- ---

// Mock Components for demo
const InputField = ({ label, name, value, onChange, error, ...props }: any) => (
	<div>
		<label htmlFor={name} className="block text-sm font-medium text-gray-700">{label}</label>
		<input id={name} name={name} value={value} onChange={onChange} {...props} className={`mt-1 block w-full px-3 py-2 border ${error ? 'border-red-500' : 'border-gray-300'} rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm disabled:opacity-50`} />
		{error && <p className="mt-1 text-xs text-red-600">{error}</p>}
	</div>
);
const Button = ({ children, ...props }: any) => (
	<button {...props} className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50">
		{children}
	</button>
);
// End Mock Components

export default function CreateUserPage() {
  const [formData, setFormData] = useState<CreateUserInput>({ name: '', email: '' });
  const [isPending, startTransition] = useTransition();
  const [result, setResult] = useState<ActionResult<User> | null>(null);
  const [selectedServiceType] = useState('default'); // Example: could be dynamic

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { name, value } = e.target;
    setFormData((prev) => ({ ...prev, [name]: value }));
    if (result) setResult(null);
  };

  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();
    setResult(null);
    startTransition(async () => {
      // Call the server action (pass serviceType if dynamic)
      const actionResult = await createUserAction(formData, selectedServiceType);
      setResult(actionResult); // Update state with the structured result
      if (actionResult.success) {
         setFormData({ name: '', email: '' }); // Reset form
         console.log("UI: User created!", actionResult.data);
         alert("User created successfully!");
      } else {
         console.error("UI: Creation failed:", actionResult.error || actionResult.validationErrors);
         // Errors (including validation errors) are now displayed via result state
         alert(`Failed: ${actionResult.error || 'Validation errors occurred.'}`);
      }
    });
  };

  // Helper to get validation error for a specific form field path
  // Now looks at the `validationErrors` array in the `ActionResult`
  const getValidationError = (path: string): string | undefined => {
    return result?.validationErrors?.find(err => err.path === path)?.message;
  };

  return (
    <div className="p-4 max-w-md mx-auto">
      <h1 className="text-2xl font-bold mb-4">Create User (Validated Service Example)</h1>
      {/* Service type display/selector could go here if dynamic */}
      <form onSubmit={handleSubmit} className="space-y-4">
        <InputField
          name="name"
          label="Name"
          value={formData.name}
          onChange={handleChange}
          error={getValidationError('name')} // Display specific validation error
          disabled={isPending}
          required
        />
        <InputField
          name="email"
          label="Email"
          type="email"
          value={formData.email}
          onChange={handleChange}
          error={getValidationError('email')} // Display specific validation error
          disabled={isPending}
          required
        />

        {/* Display general server error (from machine/service execution failure) */}
        {result && !result.success && result.error && (
           <p className="text-sm text-red-600 mt-2">Error: {result.error}</p>
        )}

        {/* Display specific validation errors NOT tied to a field */}
        {result?.validationErrors?.filter(err => !['name', 'email'].includes(err.path ?? '')).map(err => (
             <p key={err.path ?? 'unknown'} className="text-sm text-red-600 mt-1">Validation ({err.path ?? 'general'}): {err.message}</p>
        ))}

        {/* Display success message */}
        {result?.success && result.data && (
           <p className="text-sm text-green-600 mt-2">User "{result.data.name}" created successfully!</p>
        )}

        <Button type="submit" disabled={isPending} className="w-full mt-4">
          {isPending ? 'Creating...' : 'Create User'}
        </Button>
      </form>
    </div>
  );
}
```
