) and scoped to an * account by the `owner` parameter. Idempotent by `reference`. */ class KitchenIngestController extends Controller { public function __construct(private PosSaleService $sales) {} public function store(Request $request): JsonResponse { abort_unless($this->service($request) !== null, 401, 'Invalid service key.'); $data = $request->validate([ 'owner' => ['required', 'string', 'max:255'], 'reference' => ['required', 'string', 'max:255'], 'customer_name' => ['nullable', 'string', 'max:120'], 'items' => ['required', 'array', 'min:1', 'max:100'], 'items.*.name' => ['required', 'string', 'max:200'], 'items.*.quantity' => ['nullable', 'integer', 'min:1', 'max:200'], 'items.*.unit_price_minor' => ['nullable', 'integer', 'min:0'], 'items.*.notes' => ['nullable', 'string', 'max:200'], ]); try { $sale = $this->sales->ingestExternalOrder($data); } catch (RuntimeException $e) { return response()->json(['message' => $e->getMessage()], 422); } // Owner doesn't run a POS kitchen — accept and ignore. if ($sale === null) { return response()->json(['skipped' => true], 200); } return response()->json(['id' => $sale->id, 'reference' => $sale->reference], 201); } private function service(Request $request): ?string { $token = (string) $request->bearerToken(); if ($token === '') { return null; } foreach ((array) config('pos.kitchen_api_keys', []) as $service => $key) { if ((string) $key !== '' && hash_equals((string) $key, $token)) { return (string) $service; } } return null; } }