.. This file is part of PEPSI. Copyright (C) 2026 Pepsi contributors PEPSI is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. ============== pepsi-stage-if ============== *Branch the pipeline on a stored state value.* Role ==== ``pepsi-stage-if`` is a programmable fork: it tests one member of the message ``state`` JSON for equality against a configured value and advances the message to ``TRUE_STAGE`` when they are equal, otherwise to ``FALSE_STAGE``. It lets an operator route on any verdict an earlier stage recorded — ``state.spam``, ``state.auth.dkim``, ``state.local_origin``, … — without writing code. It only moves the ``stage`` column; it never rewrites, pauses or fails a message, and leaves ``state`` untouched. Reference: :manpage:`pepsi-stage-if(1)`. Features ======== * **Dotted state paths:** ``STATE_PATH`` is a dot-separated path into ``state``. Each segment indexes an object by key; a segment that parses as an integer indexes an array by position — e.g. ``spam``, ``auth.dkim``, ``dsn.rcpt.0.notify``. * **Scalar text comparison:** the value found is compared to ``VALUE`` by its natural textual form — a string matches its text, a boolean ``true``/``false``, a number its decimal rendering, JSON null the literal ``null``. * **False on absent or non-scalar:** a path that is missing, or that resolves to an array or object (which has no scalar form), is never equal and so takes the ``FALSE_STAGE`` branch. ``VALUE`` is required and may not be empty. * **Non-destructive:** the body is never loaded and ``state`` (including ``state.dsn``) is preserved across the branch, so the stage can be placed anywhere in the graph. A common use is to split the pipeline **by direction**: ``pepsi-ingress`` records ``state.local_origin = true`` for an authenticated submission, so a ``STATE_PATH = local_origin`` / ``VALUE = true`` test sends outbound mail down a signing/relay path and inbound mail down the filtering/delivery path (see :doc:`../getting-started`). Configuration ============= ``[stage-]``: ``PROGRAM = pepsi-stage-if``, ``STATE_PATH`` (the dotted path to test), ``VALUE`` (required, the value compared against), and the ``TRUE_STAGE``/``FALSE_STAGE`` branch targets. ``pepsi-setup`` checks that both branch targets resolve to real stages, like ``NEXT_STAGE``. See :manpage:`pepsi-stage-if(1)`. State ===== * **Inputs:** the single member of ``state`` selected by ``STATE_PATH``. * **Outputs:** none — the stage only advances the message and leaves ``state`` unchanged. See also ======== :doc:`pepsi-stage-check-whitelist`, :doc:`pepsi-stage-bounce`, :doc:`../features`, :doc:`../getting-started`, :manpage:`pepsi-stage-if(1)`.