Workbench: protect sections with Cloudflare Access and fix login failures
Use this runbook when a workbench section is reachable without a login, when a new section is added, or when the owner reports a login failure such as "That account does not have access." The verified facts behind it (preview hosts, the automation token's permission boundaries, which email each login method presents) are in the Knowledge entry Cloudflare; read it first.
Protected sections: finance, divorce, inbox, docs. Each needs an
Access application on the production host and a wildcard application
covering preview-deployment hosts, with a policy allowing only the owner's
addresses: jknash@gmail.com and jknash@x-centric.com.
The two cases at a glance (the prose below governs):
Preconditions
- Muse's environment with the
cloudflareskill and the stored token (custom.cloudflare). The token can manage applications and policies. It cannot manage the Access organization or identity providers; this runbook marks the steps where that boundary matters.
Case A: protect (or re-protect) the sections
1. Confirm Access is enabled on the account
~/workspace/skills/cloudflare/.venv/bin/python \
~/workspace/skills/cloudflare/bin/cf.py access-setup
If it fails with error 9999 ("Access is not enabled"), stop. Only the owner can enable Access: Cloudflare dashboard, Zero Trust, choose a team name and the free plan. Resume this runbook once the owner confirms it is enabled.
2. Let the setup create what is missing
access-setup is idempotent. It reads the Pages project's real subdomain,
then ensures all eight applications exist (four production, four wildcard
preview) with the allow policy on each. Re-running it is safe.
Exit test: it prints each domain with "app exists" or "app created" and no failures. Cross-check with:
~/workspace/skills/cloudflare/.venv/bin/python \
~/workspace/skills/cloudflare/bin/cf.py access-list
Expect 8 applications.
3. Verify from outside
Unauthenticated checks, on the production host and on any current preview host (the deployment URL printed by the deploy runbook):
/, expect 200 (public by design)./finance/,/divorce/,/inbox/, expect 302 to the Access login.- At least one data file, for example
/finance/data/finance.json, expect 302. - The same section paths on the preview host, expect 302.
Exit test: every protected URL returns 302 on both hosts. A 200 anywhere
means that host or path has no application; re-check the domain strings in
access-list against the failing URL before changing anything else.
Case B: "That account does not have access"
The sign-in succeeded but the presented email is not in the policy. The
login page offers only the Cloudflare provider, which presents the
Cloudflare account email (jknash@x-centric.com for the owner), not Gmail.
1. Read the current policy on one application
Fetch the application's policies through the API and compare the include
list with the address the owner actually signed in as. Do not guess the
address; ask the owner which email their Cloudflare account uses if it is
not already recorded here.
2. Add the missing address to every policy
Update all eight applications' policies so include lists both owner
addresses as separate email entries. A partial fix (production only) leaves
preview hosts rejecting the same sign-in.
Exit test: policy reads on all eight applications show both addresses, and the owner signs in successfully on a production section and a preview URL.
3. If the owner wants the Gmail PIN instead
That needs the one-time PIN identity provider, which is an organization setting: the automation token cannot create it (verified error 1010). Two routes, both owner actions:
- Zero Trust dashboard: Settings, Authentication, Login methods, add One-time PIN. Or
- Extend the
workbench-automationtoken with "Access: Organizations, Identity Providers, and Groups: Edit", after which an agent can add the provider through the API.
Until then, the Cloudflare-provider sign-in with both addresses allowed is the working configuration. Do not loosen any policy to "fix" a login problem in the meantime.
What this runbook must NOT do
- Never make a section public, even temporarily, to work around a login failure.
- Never add an address to a policy without the owner confirming it is theirs.
- Never paste the automation token anywhere; if its permissions need to change, the owner edits it in the dashboard and it stays in secure storage.
Published by Muse · 2026-10-02.