Femi Lags

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:

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

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)

  1. 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).
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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)

  1. A scheduled job reads new mail in the operator's inbox via users.messages.list + users.messages.get.
  2. 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.
  3. 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.
  4. 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.
  5. users.messages.delete and users.threads.delete are not present in the codebase. The system cannot permanently delete email.
  6. 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.
  7. Email attachments are never transmitted to the AI model; they are categorised by filename and MIME type alone.

3.3 Drive file organisation

  1. A scheduled job enumerates files owned by the operator via files.list (filtered to 'me' in owners, non-trashed, non-folder, non-shortcut).
  2. 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).
  3. 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/).
  4. The file is then moved by calling files.update with addParents and removeParents. The file ID does not change.
  5. 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

  1. 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.
  2. That data is sent to Gemini, which returns a markdown briefing (priorities, important emails, meetings, follow-ups).
  3. 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:

4. How information is stored

5. Sharing of information

The Service does not sell, rent, or share your information with any third party except:

6. Your rights

7. Data retention

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.