Design — Google Workspace admin access + inventory/cleanup audit
Date: 2026-06-09 · Owner: Both (Jonathan = Google Cloud + Admin console authorization; Claude = GAM operation on cbf-dev) · Status: In progress — GAM installed, auth blocked on 2SV (see "Where we left off") · Repo of record: documents (new it/ namespace)
Where we left off (2026-06-09)
- ✅ GAM installed & verified on cbf-dev (7.44.03,
~/bin/gamadv-xtd3/, config~/.gam/). No credentials minted yet (~/.gam/oauth2.txtandclient_secrets.jsondo not exist). - ⛔ Blocked: created
gam-admin@cloudbase.foundation(super-admin) but it cannot sign in — "your sign-in settings don't meet your organization's 2-Step Verification policy." Tried: moved it to anAutomationOU and relaxed that OU's 2SV; ruled out group-based enforcement (not in any group); incognito still blocked. So an org-root 2SV enforcement (or Google's mandatory-MFA for new admin accounts) is overriding the OU. Jonathan deleted thegam-admin@account at end of session. - Resume options next time:
- (A) Fix the dedicated account properly — enroll a 2nd factor on a recreated
gam-admin@(a super-admin should have 2SV); investigate why the OU-level enforcement override didn't take. - (B) Momentum path — run
gam create project+gam oauth create(read-only scopes) as an existing admin that already has working 2SV, start the audit, then migrate the token to a dedicated account later.
- (A) Fix the dedicated account properly — enroll a 2nd factor on a recreated
- Tooling note:
gam create projectandgam oauth createare multi-prompt + browser flows — run them in a real SSH terminal, not the chat!one-shot prefix (it can't feed interactive input).
Goal
Give Claude admin-level, least-privilege access to the Cloudbase Foundation Google Workspace so it can (1) run an inventory & cleanup audit of users, groups, aliases, org units, and licenses, and (2) make approved configuration changes to the Workspace. The immediate pain this solves: the Admin console is hard to navigate by hand, so routine inventory and cleanup is slow and error-prone.
Scope is Directory-level administration (identity, groups, aliases, OUs, licenses) — explicitly not end-user mailbox/Drive contents.
Decisions (locked)
- Tooling — GAM on
cbf-dev, driven via Bash. Mature, purpose-built CLI for Workspace admin; CSV-native for inventory; supports the batch-plan cleanup workflow. Fits the existing "operate the VM over Bash, secrets in untracked host files" pattern. (Installed: GAM 7.44.03 — theGAM-team/GAM"GAM7" successor that merged the GAMADV-XTD3 feature set; binary at~/bin/gamadv-xtd3/, config at~/.gam/.) - No service account / no domain-wide delegation. Inventory & cleanup only need the admin-OAuth path to the Directory API. Skipping delegation means Claude cannot read into any individual user's mailbox or Drive — deliberately small blast radius.
- Read-only first, write later. Phase 1 grants only
*.readonlyDirectory scopes, so nothing destructive is possible during the audit. Write scopes are added (re-rungam oauth create) only after the cleanup plan is approved. - Write autonomy = batch-plan-then-approve. Claude gathers the full change set, presents an itemized plan (with irreversible items flagged), the human approves all / a subset / cancels, then Claude executes and reports. No surprise writes.
- Docs live in
documents/it/— this is org IT-operations, not CRM. New IT namespace; the superseded location wasCBF-crm/docs/superpowers/specs/(rebrand docs relocated here alongside).
Access architecture
Setup (one-time)
- Install GAMADV-XTD3 on
cbf-devvia Bash. - In Google Cloud Console: create/choose a project, enable the Admin SDK API, create an OAuth Client ID (Desktop app). Claude provides the exact click-path and field values.
- Run
gam oauth create; at the scope prompt select read-only Directory scopes only (Phase 1). Authorize once in a browser as a super-admin. GAM stores the refresh token. - Credentials (
client_secrets.json,oauth2.txt, GAM config) live in GAM's config dir oncbf-dev,chmod 600, never committed — same convention as.envfiles.
Least-privilege posture
- Phase 1 scopes (read-only):
admin.directory.user.readonly,…group.readonly,…group.member.readonly,…orgunit.readonly,…domain.readonly,…userschema.readonly(+admin.reports.audit.readonlyif last-login/activity data is wanted). - Phase 2 scopes (write, added only on approval):
admin.directory.user,…group,…group.member,…orgunit. - Dedicated admin identity (locked): GAM authorizes under a dedicated admin account
(e.g.
gam-admin@cloudbase.foundation), not a personal one, so every change is cleanly attributable and access is revocable by disabling that single account.
Auditability
Every GAM write also lands in Google's Admin audit log, attributed to the authorizing admin. Claude additionally keeps a local command log on the VM. Nothing happens off-the-record.
Audit workflow
Phase 1 — Inventory audit (read-only)
- Pull full inventories with GAM: users, groups, group memberships, aliases, org units, domains, and (optionally) recent-login / last-active data.
- Raw exports stay in a host-only scratch dir outside any git repo (e.g.
~/workspace-audit/oncbf-dev,chmod 700) — they contain member PII and are never committed. - Produce a findings report: stale/suspended/never-logged-in accounts, orphaned or duplicate
aliases, empty/oversized groups, licenses assigned to inactive users, and rebrand-related gaps
(missing
@cloudbase.foundationaliases, thedmarc@destination, the sharedboard@cloudbase.foundationgroup). A sanitized version of the findings is committed underdocuments/it/.
Phase 2 — Cleanup (write, after scopes added)
- Assemble a batch plan from the findings — itemized and grouped (e.g.
suspend 12 users / delete 5 aliases / fix 3 groups), with irreversible items flagged distinctly. Default to reversible operations: prefer suspend over delete unless told otherwise (note: a deleted user is restorable only within Google's ~20-day window). - Human approves all / picks a subset / cancels.
- Execute the approved batch; dry-run against a single test object first to confirm command behavior; then report successes/failures with verification reads.
Safety model (summary)
- Phase 1 literally cannot write — no write scopes are granted.
- Every Phase 2 batch is plan → approve → execute; no write happens without an explicit approval.
- Single-object dry-run precedes any batch.
- Reversible operations preferred over destructive ones.
- All writes are double-logged (Google Admin audit log + local command log).
- Findings live in a board-gated space (see doc-space integration below), not a public repo.
Doc-space integration
This doc lives in the documents repo, which is moving to Markdown → Eleventy (11ty) → Cloudflare
Pages at board.cloudbase.foundation, gated by Cloudflare Access to the board@cloudbase.foundation
Google group — see it/2026-06-09-board-internal-doc-space-design.md (relocated alongside). That
board-gating is deliberately relied on here: Workspace audit findings are sensitive, so a board-only
space is the right home, but raw PII exports still never leave the host-only scratch dir (defense
in depth, not the sole control).
- PagesCMS is retired — the orphaned
.pages.ymlis being deleted by the doc-space workstream; nothing here depends on it. - When the 11ty build lands, wire
it/into it (add anitcollection + nav entry, andtitle/date/status/layout: docfrontmatter on these files) so the namespace renders branded and appears in the index. Until then these are plain Markdown, consistent with the repo's current hand-built state.
Ownership split
- Jonathan (super-admin): Google Cloud project + Admin SDK enablement + OAuth client creation; the
browser authorization of
gam oauth create; deciding the write-scope go-ahead. Claude supplies exact step-by-step navigation for each. - Claude: GAM install/config on
cbf-dev, running inventories, producing findings + cleanup plans, executing approved batches, verification.
Dependencies & sequencing
- The
board@cloudbase.foundationgroup is shared across three workstreams: the domain rebrand (board ACL), the internal doc space (Cloudflare Access policy), and this audit (a thing to verify / possibly create). Create it once and coordinate. - This work does not block on the rebrand's primary-domain flip; the audit can run against the current Workspace today.
Risks & rollback
- Over-broad access → mitigated by no-delegation + read-only-first + optional dedicated admin account.
- Accidental destructive change → mitigated by batch-plan approval, prefer-suspend, single-object dry-run, and the 20-day user-restore window.
- Credential leak → host-only secrets,
chmod 600, never committed; revocable by deleting the OAuth client / disabling the dedicated admin account. - PII in exports → raw inventory stays in a host-only scratch dir; only sanitized findings are committed, into a board-gated space.
Open / long-term (not blocking)
- Broader
documentsinformation architecture (whereit/sits relative totech/) — revisit with the doc-space build.