DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path session-handoffs/loomworks-dunin7-perimeter-session-handoff-v0_4.md

Loomworks — dunin7.com perimeter and sales-generator relocation — Session handoff — v0.4

Version. 0.4 Date. 2026-07-18 Author. Claude.ai, on Operator direction. Status. Session handoff. Stage 1 is built, verified, and closed in the record. This version orients a fresh chat for Stage 2 scoping — the sales-generator relocation. A fresh chat must run from this version; v0.2's build-facing sections are superseded by the completed work.

Change from v0.3. One evidence claim corrected (section 1, Auth). v0.3 stated that localhost:3001 dev sign-in was verified working. What was actually verified: Chrome accepting a Secure cookie from a header-identical probe served on localhost port 3007 — cookie acceptance, not a sign-in ceremony, and not on 3001. The secure-context conclusion holds (it is host-based, not port-based); the claim overstated the evidence. Flagged by Claude Code at filing time; corrected here per the discipline that a record must not assert a verification that did not happen.

Change from v0.2. Stage 1 executed to completion (2026-07-18, one session). All v0.2 Stage 1 premises either held or were corrected in flight; corrections are in section 4. The Stage 2 entry condition was reshaped by the Operator: per-principal metering plus a runaway ceiling, not calibrated quotas — quotas are deferred until diversified usage data exists (section 6).

Reads with. loomworks-dunin7-perimeter-session-handoff-v0_2 (the plan this executed), the Stage 1 completion report in loomworks-record/completion-records/, the three-level authorization design in analyses/, the persistent-run proposal in operations/, CR-2026-152 (sales generator, v0.26 in the record).


Plain-language summary

Where things stand. The authenticated perimeter is live. app.dunin7.com serves the production Operator Layer over HTTPS through the Cloudflare Tunnel, sign-in works end to end with the Operator's passkey, the browser reaches the engine only through the same-origin proxy (Path B), three authorization levels exist and refuse correctly, and both services run under launchd and survive kill -9. Stele v0.4.0 is published with multi-origin ceremony support.

What Stage 2 is. Port the sales-perspective generator's /api/sales/* chain off the marketing project (JavaScript Cloudflare Pages Functions) into the engine as Python/FastAPI routes, gated at the DUNIN7-representative level, reached through the tools menu on the perimeter. This retires the cross-domain carry for good and gives the generator its proper home per the domain rule (services on dunin7.com).

The entry condition. The rate limiter is functionally broken behind the tunnel — slowapi keys on request.client.host, which is the tunnel, so every user collapses into one bucket. The sales chain is LLM-cost-bearing. Stage 2 does not land the chain behind a shared bucket. What must exist at entry: per-principal usage attribution (metering keyed on the session principal) and a deliberately loose per-principal safety ceiling sized to cap runaway cost only. Calibrated quotas are explicitly deferred: usage is unknowable until a diversified set runs through the generators, so real limits are a later Operator ruling made on data Stage 3's representatives generate.

What the fresh chat does first. Scope Stage 2: a Step-0 inspection brief for Claude Code (the sales chain as it exists on the marketing branch, the engine's limiter and LLM seams as they exist now), then the Stage 2 build brief.


1. Stage 1 final state (verified 2026-07-18)

Perimeter. app.dunin7.com → production Operator Layer on 127.0.0.1:3002. api.dunin7.com → engine on 127.0.0.1:8000 (routes; no browser code points at it — Path B same-origin proxy is the only browser path). loomworks-dev.dunin7.com → dev server on 3001, preserved for development. Tunnel config at /etc/cloudflared/config.yml, mirrored to the home copy, all rules on 127.0.0.1.

Services. com.dunin7.loomworks-engine (8000) and com.dunin7.loomworks-operator-layer (3002), user LaunchAgents, mode 600, no secrets in plists, WorkingDirectory at repo roots so .env resolves. Both verified restarting after kill -9. Availability is login-dependent by design — LaunchAgents load at user login, not boot; the VPS cutover is the proper fix, auto-login was ruled out (signing keys on the machine).

Auth. WEBAUTHN_RP_ID=dunin7.com (apex, passkeys survived). WEBAUTHN_RP_ORIGIN=https://app.dunin7.com with WEBAUTHN_ADDITIONAL_ORIGINS=https://loomworks-dev.dunin7.com — Stele v0.4.0 multi-origin, TS-09 validation applies to every origin. Session cookies Secure via settings-backed cookie_secure() in a shared cookies.py; zero open-coded cookie writes remain. Secure-cookie acceptance on bare localhost verified in Chrome via a header-identical probe (port 3007) — localhost is a secure context, host-based not port-based, so localhost:3001 dev sign-in is expected to keep working; a full ceremony on 3001 was not run.

Three-level authorization. PlatformLevel ordered IntEnum (1 customer / 2 representative / 3 founder). resolve_platform_level is the seam GRANTHA later answers; answers are hardcoded now. Representative storage: system_config key dunin7_representative_person_ids beside platform_founder_person_id — moves to a host_account column at Stage 3 when representatives become administered rather than declared. require_founder untouched, live on six admin_grants routes. New: require_dunin7_representative, require_authenticated_customer, GET /me/platform-level (returns caller's level; the frontend will consume this for tools-menu visibility), and a representative-gated companion route that exists to demonstrate refusal. Verified live: Operator ceremony at app.dunin7.com returned {"level":"founder","rank":3}.

Repos, all in sync with remotes:

| Repo | Branch | Head | |---|---|---| | loomworks-engine | perimeter-stage-1 | 0bf3336 | | loomworks-engine | main | 4fe7541 | | loomworks (Operator Layer) | perimeter-stage-1 | c36a75f | | stele | main | 689de41, tag v0.4.0 | | stele | perimeter-stage-1 | a6b59fd | | loomworks-record | main | 43e8992 |

Note: the perimeter-stage-1 branches are pushed but not merged to main in loomworks-engine and loomworks (Operator Layer). Merge timing is a Stage 2 scoping question — the perimeter runs from the branch builds.

Record filings, seven documents: completion report (completion-records/), Stage 1 build brief + pre-flight findings (build-briefs/), three-level authorization design (analyses/), persistent-run proposal (operations/), test_stele_router_mount characterization (investigations/), secrets-hygiene sweep (queued-directions/), session-scoped-list scoping stub (scoping-notes/).

2. What Stage 2 delivers (from the v0.2 plan, still governing)

Port /api/sales/* into the engine, gated on the representative level (not founder-only). Retire the cross-domain carry (CR-2026-153's mint/verify, already superseded as transport). Stop-safe: the tool works behind the gate, reached through the menu. Content work (v0.25/v0.26/decision B) remains Stage 3 alongside identity provisioning for Aldous, Warwick, and test users.

3. Facts the port rests on (verified in Stage 0/1, re-verify at point of use)

4. Corrections from the Stage 1 build (preserved per discipline)

5. Stage 2 inheritance queue

  1. Rate limiter — entry condition, reshaped (section 6).
  2. Secrets-hygiene sweep — plists, .dev.vars (rotation is an Operator action, procedure recorded), permissions audit. .dev.vars key still live.
  3. Session-scoped-list scoping/engagements 200-empty vs 401; both sides recorded, no lean; own scoping with frontend empty-state handling.
  4. host_account revisit — Stage 3, when representatives become administered.
  5. Node symlink maintenance point~/.local/bin/loomworks-node; repoint after any nvm upgrade or app.dunin7.com silently stops serving at next reboot.
  6. test_stele_router_mount — harness-only (proven by two live ceremonies), test-correctness priority.

6. The entry condition, precisely (Operator ruling, 2026-07-18)

Usage cannot be known until a diversified set runs through the generators, so quotas cannot be set from judgment now. Therefore:

The sales chain does not land behind a shared bucket; it also does not wait for invented quota numbers.

7. Standing discipline (unchanged)

Two-role: Claude.ai scopes and writes; Claude Code executes, inspects against live code, halts before every push. Fresh chat per work type. Step-0 inspection before CR drafting. Halt-point documents are decision records and get filed (analyses/ for designs, operations/ for operational proposals). .env changes are machine state that never travel with a branch — name them in reports. Verification checks must fail on missing input and be anchored to controls that can disagree.


DUNIN7 — Done In Seven LLC — Miami, Florida Loomworks — dunin7.com perimeter and sales-generator relocation — Session handoff — v0_4 — 2026-07-18