The scoping note for landing record.dunin7.com as a real, deployed, authenticated site. The prototype validated the navigation, design language, and sort affordances. This phase moves from local-file prototype to served-from-the-web production deployment behind Cloudflare Access.
The sequence has Operator-side steps (Cloudflare dashboard work, DNS configuration, passkey enrollment) and Claude-side steps (build script production updates, GitHub Action, scoping documents). Each step is named with its actor so coordination is unambiguous.
On the operating-account domain (dunin7.com), not the product-family domain (doneinseven.com). The record is operator-facing infrastructure, not customer-facing product.
All folders, all documents. Methodology, architecture, protocols, phases, investigations, session handoffs, candidate seeds, queued directions, standing notes, brand, analyses, examples, change requests, current status, discovery. Not just the protocol specifications.
Documents at folder root are current and editable. Documents in archive/ subfolders are historical and read-only. Editor itself ships after the read viewer is in use and editing affordances are informed by lived experience.
Cloudflare Access authenticates before any request reaches the site. Primary auth: passkey (Touch ID, Face ID, hardware key). Fallback: TOTP via Cloudflare's one-time PIN by email. Editing operations (when the editor ships) require fresh re-authentication. Recovery codes printed and stored physically.
Quick edits to existing documents and capture of new artifacts (investigations, standing notes, session handoffs) from anywhere. NOT: CR drafting (stays in Claude.ai), phase work (stays in Claude.ai-and-Claude-Code), substantive document rewrites (stay in Claude.ai conversations).
GitHub Action runs the build script (tools/build_site.py, moved from Downloads into the repository) on every push to main. Generated site deployed to Cloudflare Pages. Same architecture as the prototype, but auto-rebuilt and served over HTTPS.
The prototype build script lives at /home/claude/build_site.py (in a session sandbox) and reads from a local repository copy. The production version lives at tools/build_site.py inside loomworks-record itself. Differences:
file:// iframes are blocked by browsers. Under HTTPS at the same origin, iframes work normally — HTML documents embed directly in the viewer page, preserving their letterpress styling.DUNIN7 · LOOMWORKS · RECORD with no qualifier.archive/ subfolder; archived rows visually dimmed and labeled read-only)..md documents.Eleven steps. Each named with its actor (Claude.ai = Claude.ai produces an artifact; Claude Code = build machine executes; Operator = dashboard work or DNS or enrollment). Sequence ordering matters — earlier steps unblock later ones.
Update build_site.py with the production changes named above: git log timestamps, inline HTML rendering, drop prototype chrome. Stage for Claude Code commit at tools/build_site.py.
YAML workflow at .github/workflows/deploy.yml. Triggers on push to main. Installs Python, runs the build script, deploys the output to Cloudflare Pages using the official Cloudflare deploy action. About fifty lines.
Kickoff prompt for Claude Code that lands tools/build_site.py and .github/workflows/deploy.yml on the repository. Single commit. The build script will not yet succeed because Cloudflare Pages doesn't exist — that's fine; the commit is sequencing-only.
In the Cloudflare dashboard: Workers & Pages → Pages → Create application → Connect to Git → select DUNIN7/loomworks-record. Build settings: framework preset = None; build command = python3 tools/build_site.py; build output directory = record-site/ (the build script writes here). Save. The first deploy fails because Python isn't installed in Cloudflare's default build image; the GitHub Action approach (next step) handles this.
Or, alternative simpler path: skip Cloudflare's Git integration entirely and have the GitHub Action push built artifacts to Cloudflare via the Wrangler CLI. Slightly more complex Action; simpler Cloudflare project setup. I'll recommend in the build script step which to use.
In the Cloudflare dashboard: My Profile → API Tokens → Create Token. Use the "Edit Cloudflare Workers" template (which includes Pages). Scope to the account level. Copy the token (Cloudflare shows it exactly once).
In the GitHub repository: Settings → Secrets and variables → Actions → New repository secret. Name: CLOUDFLARE_API_TOKEN. Value: paste the token. Also add CLOUDFLARE_ACCOUNT_ID (visible on the Cloudflare dashboard right sidebar).
After the secrets are in place, push a small commit (touching the workflow file is enough) to trigger the GitHub Action. The Action runs the build script, deploys to Cloudflare Pages. The site is now live at the Cloudflare-assigned *.pages.dev URL, but not yet at record.dunin7.com and not yet behind Access.
In the Cloudflare Pages project: Custom domains → Set up a custom domain → record.dunin7.com. Cloudflare creates the CNAME automatically because dunin7.com is already on Cloudflare DNS. Within a few minutes, record.dunin7.com resolves to the Pages project.
In the Cloudflare dashboard: Zero Trust → Access → Applications → Add an application → Self-hosted. Application name: "Loomworks Record". Application domain: record.dunin7.com. Session duration: 24 hours (sensible default; configurable).
Configure the policy: Action = Allow. Include = Emails (your email address). Require = Authentication method must include hardware key or passkey, with one-time PIN as fallback. This is configured in the Access policy builder, not in code.
Visit record.dunin7.com. Cloudflare Access intercepts. Choose authentication method → select passkey (or hardware key). Browser walks through enrollment (Touch ID, Face ID, or hardware key tap). Cloudflare records the credential.
Print and store the recovery codes Cloudflare provides. Physical storage. This is the path-back-in if you lose the phone and the laptop on the same day.
From a fresh browser session: visit record.dunin7.com. Authenticate. Land on the Record landing page. Navigate to a section. Open a document. Click Back. Confirm the experience matches the prototype, with HTML documents now rendering inline rather than opening in a new tab. Test from a phone if convenient.
Once record.dunin7.com is live, three follow-up considerations:
The operating instructions v0.2 mention "Cross-session sync — the open question" as the only unresolved item. record.dunin7.com doesn't fully resolve it (the MCP connector is still the target), but it changes the workable patterns. Specifically: Claude.ai sessions can be told to read documents from record.dunin7.com URLs rather than from uploaded files. The session-context record can name URLs alongside uploads. A small v0.3 of the operating instructions captures this change.
After one to two weeks of using the read viewer in lived experience, the editor build is scoped from what you actually missed. Today's design intent — Monaco editor, GitHub API commits, archive-move-on-version-bump — is informed by the prototype's chrome. A real editor scope comes from real use.
None of these block deployment, but they're worth tracking:
record.dunin7.com. This is operator-facing infrastructure only. Marketing pages, product documentation, and customer-facing content live elsewhere.Several points in the sequence where the right behavior is to pause and confirm before continuing.
If the Cloudflare Pages project's build settings don't accept Python or don't write to record-site/, the build will fail. Confirm the build command and output directory match what the build script produces before saving. If unclear, halt and ask Claude.ai.
Verify both CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID are set in GitHub Secrets. Without them the Action will fail. Look at GitHub → Settings → Secrets → Actions to confirm both names appear.
Confirm the policy is set to require authentication, not just identify. The default policy may allow anyone with a verified email; the policy this phase wants requires passkey (with TOTP fallback) for a specific email address. If unclear, halt and ask Claude.ai for screenshots of the right policy shape.
Recovery codes are shown exactly once. If they're not stored physically before closing the tab, regenerating them is a small administrative pain. Print them. Or write them down. Then move on.
If you concur with this scoping note, the next concrete step is for Claude.ai to produce two artifacts:
tools/build_site.py, with the production updates described above..github/workflows/deploy.yml.Both bundled into a single Claude Code kickoff that commits them to loomworks-record. After that commit lands, you start the Operator-side Cloudflare dashboard work (steps 04 through 11).
The kickoff also commits this scoping note itself to phases/phase-61-record-deployment/scoping-note-v0_1.html so the phase folder exists and the record of this decision is in the repository alongside the work it scopes.