Privacy Policy
Effective: 11 May 2026
This Privacy Policy describes how the Lagshaus Booking and Email Automation
system ("the Service", operated by Femi Lags) collects, uses, and stores
information from two distinct groups of people: visitors
who use the public booking page to request a meeting, and the
operator (the single Google account whose Gmail, Drive,
and Calendar the Service is authorised to manage on the operator's behalf).
The Service is operated by a single individual for the personal and
business management of one Google Workspace account. There is no
multi-tenant database, no advertising network, no analytics tracker,
and no third-party identity provider for visitors.
1. Information collected from booking-page visitors
When a visitor submits a meeting request via the booking form, we collect:
- Full name — used to identify the requester to the operator and (on approval) to populate the calendar event title.
- Email address — used to send the calendar invitation when a request is approved, and as a unique identifier when declining duplicate requests for the same time.
- Phone number (optional) — used only by the operator if direct contact is needed about the meeting.
- Purpose of meeting — a free-text description of what the visitor wishes to discuss; reviewed by the operator only.
- Requested start/end time — the calendar window the visitor selected.
- Submission timestamp — when the request was received.
No cookies, fingerprinting, IP-address logging, or third-party analytics
are used on the booking page. We do not embed any social-media buttons,
advertising, or behavioural tracking tags.
2. Information collected from the operator's Google account
With the operator's explicit consent through Google's standard OAuth flow,
the Service is granted scoped access to the operator's Gmail, Google Drive,
and Google Calendar. The data accessed is processed locally by the
Service and used only for the automation tasks the operator requested.
No operator-account data is ever exposed on the public booking page.
Google API scopes requested
gmail.readonly — read inbox messages for AI classification.
gmail.modify and gmail.labels — apply labels and archive non-priority mail per the operator's classification rules.
calendar — list events to render the busy/free view, and insert new events when the operator approves a booking.
drive — classify and re-file the operator's existing Drive files into a folder taxonomy. The Service never deletes Drive content.
3. How the system works — data flows in detail
The following subsections describe, step by step, every place where data
flows through the system. Each step names the underlying Google API
method so the description can be audited against the source code and
against the OAuth scope each method belongs to.
3.1 Booking workflow (Google Calendar)
- A visitor opens the public booking page at
/book. The page calls /api/booking/availability, which in turn calls Google Calendar's events.list across the operator's subscribed calendars (enumerated via calendarList.list).
- The results are anonymised on the server before being returned to the visitor's browser: only
start, end, and an all_day boolean are sent. Event titles, descriptions, locations, and attendee lists are stripped and never leave the server.
- The visitor picks a slot and submits the booking form. The request is stored in a local CSV (
data/automation-store/booking_requests.csv) with status pending. No Google API calls are made at this step.
- The operator signs in to the private admin queue, reviews the request, and clicks Approve. The server runs a final conflict check (another
events.list across the requested window) and refuses approval if any existing event overlaps.
- On a clean approval the server calls
events.insert on the operator's primary calendar. The event summary is Meeting: <requester name>; the description contains the requester's name, email, optional phone, and purpose; the requester is added as an attendee with sendUpdates=all, so Google sends them a standard calendar invitation.
- If the operator later cancels the booking, the server calls
events.delete with sendUpdates=all; Google sends the requester a cancellation notice.
3.2 Email classification and labelling (Gmail)
- A scheduled job reads new mail in the operator's inbox via
users.messages.list + users.messages.get.
- For each message the system extracts the subject, sender, internal date, and a 4,000-character truncated body excerpt. PII (account numbers, government IDs, etc.) is regex-redacted from this excerpt before any text leaves the local Python process.
- The redacted excerpt is sent to Google's Gemini family of models (via Google AI Studio) which returns a JSON object containing a primary label, a confidence score, and a one-sentence summary.
- If the model's confidence is at least 0.70, the chosen label is applied via
users.messages.modify. If the primary label is Archive-Promo AND the confidence is at least 0.90, the same call also removes the INBOX label, archiving the message. Lower-confidence results are routed to a Review label and left in the inbox.
users.messages.delete and users.threads.delete are not present in the codebase. The system cannot permanently delete email.
- A Protected-Sender Guard (a deterministic Python function, not an AI call) runs before every Gmail write. Mail from a hard-coded list of important senders (school, government, banking, family) is refused for archive or relabel regardless of any model output.
- Email attachments are never transmitted to the AI model; they are categorised by filename and MIME type alone.
3.3 Drive file organisation
- A scheduled job enumerates files owned by the operator via
files.list (filtered to 'me' in owners, non-trashed, non-folder, non-shortcut).
- For each candidate file the system reads metadata and a content snippet (≤4,000 characters) via
files.export (for Google-native docs) or files.get?alt=media (for binary types).
- The snippet is sent to Gemini, which returns a target folder name from a fixed human-readable taxonomy (e.g. Finance/Invoices/2026/, Legal/Contracts/, Reference/Research/).
- The file is then moved by calling
files.update with addParents and removeParents. The file ID does not change.
- The system never deletes, trashes, or overwrites Drive content; it never changes file permissions; it never shares files. The only mutating call in the codebase is
files.update(addParents=…, removeParents=…).
3.4 Daily executive briefing
- Once per day the operator can request a private summary of their own day on the dashboard. The system reads classified email rows from local storage and the operator's calendar events for the day via
events.list.
- That data is sent to Gemini, which returns a markdown briefing (priorities, important emails, meetings, follow-ups).
- The briefing is shown only on the authenticated dashboard. It is not emailed, shared, or stored beyond the request.
3.5 Code-level guardrails
Several invariants are enforced in code (not just by OAuth scope), so a
future code change cannot accidentally exceed the policy described above:
- Calendar verb allowlist — every Google Calendar API call goes through a wrapper that refuses any method outside
{events.insert, events.delete, events.list, calendarList.list}. Calls to ACL, calendar create/delete, free-busy, or watch endpoints raise PermissionError at runtime.
- No-delete invariants —
users.messages.delete, users.threads.delete, files.delete, and files.trash do not appear anywhere in the codebase.
- Protected-Sender Guard — a deterministic Python function, not an AI judgement, blocks every Gmail write for senders on its hard-coded list.
- PII redaction — regex redaction runs before any text is sent to the AI model.
- Audit log — every write action against Gmail, Drive, or Calendar appends a row to a local audit log including the timestamp, agent, action, and message/file/event identifier.
4. How information is stored
- Visitor booking requests are stored in a local CSV file on the operator's server (
data/automation-store/booking_requests.csv). They are not replicated, exported to third parties, or sent to any analytics service.
- Operator data stays on the operator's own machine in local CSV / JSONL files. AI Studio API calls are stateless from our side; whatever Google's AI Studio retains is governed by Google's privacy policy.
- OAuth tokens are stored on the operator's server in a local JSON file with file-system permissions restricted to the operator's user account.
5. Sharing of information
The Service does not sell, rent, or share your information with any third party except:
- Google — when calendar events are created on approved bookings, the requester's email is added as an attendee and Google sends them a calendar invitation. This is the standard Google Calendar invitation flow.
- Google AI Studio (operator data only) — redacted email and Drive content excerpts are sent to Google's Gemini models for classification. No visitor booking-form data is ever sent to AI models.
6. Your rights
- Visitors may request deletion of their booking record at any time by emailing the operator (see Contact). Approved bookings will also be removed from the calendar where the operator hosts the event.
- The operator may revoke OAuth access at any time via Google Account → Security → Third-party access. After revocation, the Service can no longer read or modify the operator's Google data.
7. Data retention
- Booking requests (pending, approved, rejected) are retained for as long as the Service is operated, unless deletion is requested.
- Local audit logs are retained on the operator's server.
- OAuth tokens are retained until the operator revokes them or the Service is decommissioned.
8. Security
All data is stored on a server controlled by the operator. The booking
application requires no visitor login and stores no passwords. Admin
access to the booking dashboard is gated by a username + password stored
in environment variables (not in source code) and a session-token system.
HTTPS / TLS encryption is provided by the operator's hosting infrastructure.
9. Children's privacy
The Service is not directed to children under 13 and we do not knowingly
collect personal information from them. If you believe a child has
submitted information through the booking page, please contact us so
we can remove it.
10. Changes to this policy
We may update this Privacy Policy from time to time. The "Effective"
date at the top will reflect the most recent revision.
11. Contact
Questions or requests about this policy can be sent to:
femi.lags@gmail.com.