GuestOps/docs/replies.md

40 lines
5.4 KiB
Markdown

# AI drafts and staff-approved Gmail delivery
This milestone adds AI suggestions and a persistent send queue. It does not enable automatic replies, PMS writes or payments. No live OpenAI/Gmail acceptance testing has been performed; tests use HTTP fixtures that cannot forward requests to providers.
## Enable on the sandbox
1. Deploy the reviewed images using the deployment guide. Existing hotel records default to AI off and sending off.
2. Set `AI_API_KEY` and `AI_MODEL` in the server's private `.env`. Choose a model available to your OpenAI project that supports the Responses API and strict JSON-schema output. No model is silently selected and no key is stored in frontend code or MongoDB. Only the API container receives the AI key.
3. Recreate API/worker containers. In hotel Settings, the owner can enable AI drafts. The opt-in explains that staff-requested generation sends the message subject/body and selected approved hotel answers to OpenAI. Requests use `store: false`; this does not replace reviewing the provider's data-processing and retention arrangements.
4. For sending, set `GOOGLE_ENABLE_SENDING=true`, recreate API/worker, and reconnect Google. The OAuth request then includes `gmail.readonly` and `gmail.send`. An existing read-only refresh token is not assumed to have send permission; the returned grant must explicitly include `gmail.send`.
5. Enable staff-approved sending in that hotel's Settings. Use a dedicated test mailbox and synthetic guest messages for live acceptance tests before enabling a real hotel mailbox.
Google's consent-screen and verification requirements still apply. Never paste provider credentials into an issue, chat message or repository file.
## Staff workflow
Save edits before generating a new suggestion. Generation uses only approved answers from the signed-in hotel, with bounded keyword-based selection. The result includes answer IDs and a review note; invalid or foreign source IDs are rejected. Missing information or a provider-requested escalation leaves an empty draft for staff handling. The AI has no tools for sending, payments or PMS operations. Factual correctness still requires staff review and evaluation with representative guest emails.
Review and send shows the exact saved reply and destination before approval. The destination comes from a single valid Reply-To address, or From when Reply-To is absent. Staff cannot supply a different recipient through the API. No CC, BCC or reply-all is included. Check the address as well as the answer.
Approval atomically stores a body/recipient snapshot and stable message ID inside the conversation, using its current MongoDB version. The snapshot is locked against edits. One approval is allowed per imported incoming message. Multiple workers use the same version check before submitting the request. Gmail thread ID and RFC reply headers are included.
## Delivery and recovery
- **Pending:** approved and awaiting the worker. The worker checks hotel sending controls and mailbox permissions again before sending.
- **Sending:** a worker claimed the request. A token or metadata failure before entering Gmail send becomes Rejected.
- **Rejected:** nothing reached the Gmail send operation. Fix configuration and choose Retry approved reply; the original approved recipient/body are retained.
- **Sent:** Gmail returned a message ID, or a matching message was verified in Gmail Sent. This means Gmail accepted the message, not proof the recipient read or received it without a later bounce.
- **Needs verification:** a send timed out, returned an unexpected result, or was interrupted by restart. It is never automatically resent. Verify in Gmail Sent searches the stable message ID and checks the SENT label, sender and recipient. No unique match means the state stays uncertain; it is not evidence that sending failed. Staff must reconcile manually before any follow-up.
Switching off the hotel's sending control stops queued requests when the worker next checks them. It cannot recall an in-flight send. There is no automatic retry after entering Gmail send, even for an HTTP error. The worker's request deadline is shorter than the restart-recovery threshold.
Current limitations: messages imported before reply headers were stored must be handled in Gmail; this release does not backfill them. Full Gmail thread aggregation, reply-all, attachments, cancelling queued approval, a general reconciliation editor, staff invitation/recovery UI and automated FAQ sending remain later work. The sample preview never calls OpenAI or sends real mail.
## Verification
The test suite covers competing workers, send identity/thread headers, invalid recipients, header injection, uncertain outcomes, restart recovery, pre-send token failure, disabling hotel sending, cross-hotel access, Gmail reconciliation mismatches, AI source isolation, invalid citations, escalations and incomplete responses. CI also runs production container login/restart-persistence smoke checks. Live acceptance must additionally verify Google consent, actual threading, grant revocation, a representative AI draft evaluation set and provider error behaviour with the configured accounts.
Implementation references: [OpenAI Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs), [Gmail sending](https://developers.google.com/workspace/gmail/api/guides/sending), [Gmail threads](https://developers.google.com/workspace/gmail/api/guides/threads).