Cloud import, Google Meet. What it costs the researcher today, why it costs that, and the one choice actually worth putting on screen.
One batch, twelve interviews. Every click, end to end.
| Step | Who asks | Clicks |
|---|---|---|
| Tick the recordings you want | Bristlenose | 12 |
| Import | Bristlenose | 1 |
| “Bristlenose” Wants to Use “accounts.google.com” to Sign In → Continue | macOS | 1 |
| Choose an account → your account | 1 | |
| Bristlenose wants to access your Google Account → Allow access | 1 | |
| Select the same twelve files again, in Google’s Picker | 12 | |
| Insert | 1 | |
| Total | 29 |
The manual route it replaces is about the same. Open Drive, then per file: click, download. Twelve files ≈ 24–30 clicks. We have not made this easier. And that is one batch — the fixed five recur on every subsequent import, because none of the grant survives the window closing.
The worst line is the sixth. The researcher picks the recordings in our list, and then picks the identical set again in Google’s Picker. That is not a consent step they are reading; it is the same decision, taken twice, in two different list UIs. Everything else on this table is defensible. That line is not.
| Scope | What the researcher is shown | Google tier | What it costs us |
|---|---|---|---|
drive.filetoday |
“See, edit, create, and delete only the specific Google Drive files you use with this app” | non-sensitive | Nothing. No verification, no audit. But the grant binds to file IDs — so a new file always means a new Picker. |
drive.meet.readonly |
“View Drive files created or edited by Google Meet” | restricted | Google OAuth verification, certainly. A CASA security assessment — developer-paid, annual — only if the third-party-server clause bites. See below; unresolved. |
drive.readonly |
“View and download all your Drive files” | restricted | Whatever the row above costs, exactly. |
That last row is why there is no three-way choice.
drive.meet.readonly and drive.readonly sit in the same
restricted tier, so whatever verification and assessment burden one carries, the other
carries identically — but one says “files Google Meet made” and the other says “all your
Drive”. Paying the same toll for the worse sentence would be indefensible.
If we ever go restricted, we go Meet-only. “All your Drive” is off the table
permanently, not deferred. This conclusion does not depend on the open question
below — it holds whichever way that lands.
Google’s condition is “requests access to restricted data and has the ability to access data from or through a third-party server”. Bristlenose downloads Drive → the researcher’s own Mac; there is no Bristlenose server in that path, which reads like exemption. What muddies it is the pipeline’s LLM call — whether transcript text derived from a restricted-scope file counts as that data transiting a third-party server is an assessor’s call, not one to settle from a doc. If it does apply: the developer engages a Google-empanelled assessor and pays them directly (Google is not party to the fee), commonly $500–$4,500 for an app of this complexity, repeated every 12 months. Verification itself is required either way.
And it cannot be folded into the first sign-in. Google refuses a Picker authorization that carries any other scope — the calendar scope this same app already holds included — so the media grant is structurally a second round trip. It also binds to specific file IDs, which do not exist until the researcher has a list to pick from. Asking at sign-in is not a thing we are choosing not to do; it is not available.
Three defects, all ours, none needing a scope change or a penny of audit.
| Fix | Where | Effect |
|---|---|---|
| Seed the Picker with the whole listing, not just the ticked rows | requestMediaGrant |
One grant covers everything in the window. The double-selection collapses to a single “Allow access”. |
| Skip the Picker when every wanted file is already granted | requestMediaGrant — it never consults grantedFileIDs |
Re-importing, or a second batch inside one listing, asks nothing at all. |
| Persist the grant across window opens | openLive builds a fresh source each time and drops it |
Tomorrow’s import of the same study asks nothing. |
| Stop forcing the consent screen | prompt=consent, hardcoded |
Google may skip the screen entirely for a grant it already holds. Verify against a live account — this one is a claim, not a measurement. |
| Journey | First import | Every one after |
|---|---|---|
| Today | 29 | 17 |
| After the free fixes | 17 | 13 |
With drive.meet.readonly | 16 | 13 |
Which is the finding. Once the double-selection is gone, the restricted scope buys one click. The ceremony is not really the consent — it is that we make the researcher choose the same files twice. Fix that and the scope question gets much less urgent, and can be decided on its merits rather than under duress.
drive.filedrive.file there was no Google gate at all,
reading only the Drive half. Import does not use drive.file alone. The
listing needs calendar.events.readonly and the Meet conference-records scope,
and both are sensitive. Google’s rule is verification for sensitive or
restricted — so verification applies to Bristlenose today, whatever we do about Drive.
drive.file decision still avoids the
paid tier completely, which was the thing worth protecting; it does not avoid verification,
because nothing that can list a Meet recording does.
drive.file is non-sensitive, so it adds nothing
to the burden the calendar and Meet scopes already carry. Choosing a restricted Drive scope
would add the paid assessment on top. That is the whole delta, and it is the delta the
decision below turns on.
GoogleOAuthConfig.resolve reads the
client ID from UserDefaults before the Info.plist, so a customer whose admin objects to
ours can point the app at one they registered themselves — an internal-only app being
exempt from everything.
What the steady state looks like once they are fixed. First import of a study: one grant, covering every recording in the listing. Every subsequent import of those recordings: nothing asked at all. New recordings appearing later: one grant, covering the new ones only. That is a perfectly good product — and it is reachable with a non-sensitive scope, no verification, and no annual anything.
The one number that decides whether that is true is whether a
drive.file grant persists server-side at Google, so a stored refresh token
keeps reading a previously-picked file indefinitely. If it does, the above holds. If it
expires, the ceiling is lower and we should know that before promising it. Unmeasured
— and the first thing to measure.
Settings ▸ Cloud Import. Not a first-run question — nobody can answer this before they have felt the cost. Drawn because it is cheap to keep, not because it is next.
How much of your Drive Bristlenose may read when it fetches recordings.
Only the files I pick
Bristlenose asks Google for permission each time you import recordings it has not seen before.
“See, edit, create, and delete only the specific Google Drive files you use with this app”
Anything Google Meet made
Ask once. Covers recordings, transcripts and meeting notes — and nothing else in your Drive.
“View Drive files created or edited by Google Meet”
Changing this signs you out of Google. You can revoke either at any time in your Google Account.
Each option quotes Google’s own consent sentence verbatim. The researcher is going to read that exact string on the next screen, and recognition is the whole mechanism — the same reason the MCP pane quotes macOS’s own dialog wording rather than paraphrasing it. Our label says what it means to them; the quote says what Google will say.
Not timidity — a Workspace admin can block restricted scopes outright, so the per-file path has to keep working on a client tenant whatever we prefer. A default that some researchers simply cannot use is not a default.
“Which OAuth scope would you like?” is unanswerable before you have felt the cost of the narrow one. The honest place is Settings, discovered after the second or third import — and pointed at from the import window once we can see the researcher re-granting repeatedly.
| Gate | Costs | State |
|---|---|---|
Does a drive.file grant persist server-side? Decides whether “ask once per recording, ever” is real | nothing — one live test | unmeasured — do this first |
Whether prompt=consent is genuinely required by the one-pick flow | nothing — delete it and watch | unmeasured — the code comment lumps it with trigger_onepick |
| The three free fixes land, and the journey is re-counted against a live account | engineering only | not started |
| Ask Google whether the assessment applies to a client-only app at all | nothing — an email | unresolved. The only thing that could revive the parked radio |
| CASA assessment, annually | $500–$4,500/yr, developer-paid | declined — not a cost this product carries |
| OAuth verification for a restricted scope | time + the above | not pursued, consequent on the row above |
Every live row costs nothing but attention. That is the useful outcome of this exercise: the expensive option turned out to be both unaffordable and nearly pointless — worth one click once the free work is done — and the free work was sitting there the whole time being mistaken for a stepping stone.
The two “unmeasured” rows are marked so on purpose. This feature has already had six reasoned-not-measured claims turn out wrong on contact with a real tenant. Neither belongs in a plan as an assumption, and both are answerable in an afternoon.