Confirm before change
An agent proposes. Nothing is saved until a person taps Confirm, and availability is checked again at that moment.POST /agent-proposals/{proposal_id}/confirmRoles
Staff, owner, customer agent and scheduler each need their own grant row. Nothing about access is trusted from the browser.booking.role_grantsSources
Every staff-agent answer cites the appointments it came from, or says the records do not hold it.POST /askSafe retries
A repeated request returns the first result. It never books twice.Idempotency-KeyCode writes the confirmation
The model holds the conversation. Code writes the booked date, time and payment line, and rewrites any reply that claims a booking the backend did not confirm.agents/photon/lollicut_photon/guard.pySTOP is honoured
An opt-out is stored before the model sees the message, and survives a restart.POST /integrations/photon/opt-outsHard safety checks
An eval fails if the agent claims an unconfirmed booking, invents a fact, ignores STOP, leaks another customer or changes a phone number.agents/photon/evals/checks.pyLive sends off by default
A real text or call needs the live switch on and the number on the allow-list.PHOTON_LIVE, PHOTON_ALLOWED_NUMBERSOne workspace per salon
Each salon gets its own API, database and agent service. An API serves only the salon it was deployed for.backend/app/core/config.py (SALON_ID)Apprentice proposes, you approve
The FDE assistant never applies a config. A proposal becomes the salon's config only after Approve, and every approval is logged.Mise (this app)