Ctrl K
ComunidadGuías…

docs/google-drive-setup.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Google Drive backup integration: maintainer setup

FloCafe can optionally upload database backups to a store owner's own Google Drive on a schedule.
This is off by default and needs two things before it works in a given build:

1. A Google Cloud OAuth client. This page covers that, and it is a one-time task for a maintainer.
2. The store owner explicitly acknowledging the warning and clicking **Connect** in
   **Settings > Backup & Data > Google Drive**, which is per-install and done by the owner.

If the OAuth client is not configured, the Backup & Data UI reports that the integration is not
configured for this build and the Connect button is disabled. The app does not attempt to reach
Google's APIs at all in that state.

Drive backups are full SQLite database copies and FloCafe does not encrypt them. They can contain
customer data, staff authentication data, and store settings. Anyone with access to the selected
Google Drive account or folder can read the copy; the FloCafe Master PIN is not a portable
encryption key. Automatic backups run only while the Electron app is running, with one startup
catch-up attempt when a backup is due. Drive retention moves only FloCafe-owned automatic files to
Trash. Manual files are kept indefinitely, and Drive retention never deletes local backup history.

## Why this cannot be pre-provisioned

A Google OAuth client is tied to a Google Cloud project owned by a human Google account, and creating
one means clicking through the Cloud Console UI. For a public app, an OAuth consent screen review is
also required. There is no way to script this, and a working client ID and secret cannot be shipped
in an open-source repository.

Supported packaged releases must ship a public Desktop client configuration for their distribution
channel. Self-hosted builds may supply their own client through environment variables. An
installed-app client secret is not confidential, and it is never stored in SQLite.

## 1. Create or select a Google Cloud project

1. Go to [console.cloud.google.com](https://console.cloud.google.com/).
2. Create a new project, or pick an existing one.

## 2. Enable the Google Drive API

1. In the left sidebar, open **APIs & Services > Library**.
2. Search for **Google Drive API** and click **Enable**.

## 3. Configure the OAuth consent screen

1. Go to **APIs & Services > OAuth consent screen**.
2. Choose **External**, unless every store using this build is a Google Workspace user in your own
   organization, in which case **Internal** is fine and skips verification.
3. Fill in the app name, a support email, and a developer contact email.
4. Under **Scopes**, add `https://www.googleapis.com/auth/drive.file`.
5. Add any test users who need to connect while the app is in **Testing** publishing status. Google
   caps this at 100 users, and access tokens expire after 7 days until the app is verified or
   published.
6. Save. If you intend to distribute this build outside your own organization, submit the app for
   Google's verification review to remove the unverified-app warning and the 7-day token expiry. This
   is not required for internal or self-hosted use.

## 4. Create the OAuth client ID

1. Go to **APIs & Services > Credentials**.
2. Click **Create Credentials > OAuth client ID**.
3. Choose application type **Desktop app**. This matches the loopback flow FloCafe uses: it opens
   the consent screen in the system browser and catches the redirect on a local server bound to
   `127.0.0.1` on an ephemeral port. No fixed redirect URI needs registering for this client type.
4. Name it.
5. Click **Create** and copy the generated **Client ID** and **Client secret**. You cannot see the
   secret again after leaving that screen, though you can generate a new one from the Credentials
   page.

## 5. Wire the credentials into a FloCafe build

Set two environment variables wherever the build is compiled and run:

```bash
GOOGLE_DRIVE_CLIENT_ID=xxxxxxxx.apps.googleusercontent.com
GOOGLE_DRIVE_CLIENT_SECRET=xxxxxxxx
```

For local development, copy `.env.example` to `.env` and fill these in. For packaged builds, set
them in the build environment, through CI secrets or your build pipeline. FloCafe reads them from
`process.env` at runtime, the same pattern used for `JWT_SECRET`.

Once both variables are set and the app is restarted, **Settings > Backup & Data > Google Drive**
shows a **Connect** button instead of the not-configured message.

## The connection flow

The flow is worth knowing before you change it, because several details are load-bearing.

- **Requested scopes are `drive.file`, `openid`, and `email`.** `drive.file` lets FloCafe see only
  the files it creates itself, never the user's whole Drive. `openid` and `email` are used to bind
  one stable Google account subject per installation. Do **not** add the broader `drive` or
  `drive.readonly` scopes. The constant `DRIVE_FILE_SCOPE` in
  [`main/services/google-drive.ts`](../main/services/google-drive.ts) is the single definition.
- **The flow uses PKCE with the S256 code challenge method.** The authorization URL carries
  `code_challenge` and `code_challenge_method: 'S256'`, and the verifier is presented at token
  exchange. A fresh verifier is generated for every connection attempt.
- **The redirect is a loopback listener on `127.0.0.1` with an ephemeral port**, created per
  attempt and closed as soon as the callback lands or the attempt times out. The callback path is
  `/oauth2callback`.
- **State is 32 random bytes**, base64url-encoded, and the returned state is compared with
  `crypto.timingSafeEqual` before the code is accepted. A missing code, a Google-side error, or a
  state mismatch all fail the attempt the same way.
- **The authorization URL is validated before it is opened.** FloCafe refuses to open a URL that
  does not pass `isSafeGoogleAuthorizationUrl`.
- **The flow requests `access_type: 'offline'` with `prompt: 'consent'`**, so a refresh token is
  issued without relying on a prior grant.

## Token storage and revocation

- **Tokens are encrypted at rest with Electron `safeStorage`**, the same mechanism used for the
  Master PIN, and are written to their own file. They are never written to the SQLite database.
  If `safeStorage` reports encryption unavailable, FloCafe does not store a token.
- **Account identity is read from the OpenID Connect userinfo endpoint** after connection, and the
  stable subject and email are stored so an install stays bound to one account.
- **Disconnecting revokes the token with Google**, by POSTing it to
  `https://oauth2.googleapis.com/revoke`. It does not only clear local UI state. A revocation that
  cannot be confirmed is recorded as an unconfirmed revocation and retried rather than being
  silently treated as done.
- **Uploaded backups are the same artifact local backups produce.** There is no separate Drive
  export path, so a Drive copy and a local copy of the same moment are the same database file.
- **Pre-existing Drive files without FloCafe app properties are preserved.** They are excluded from
  automatic retention and from in-app restore, and FloCafe does not guess whether an unmarked file
  was automatic or manual.