Skip to main content
This guide records the agreed design in GEN-2824 and the intended operator response. It is not evidence of a production deployment. As of this revision, key rotation/lost-key browser flows (GEN-2873), recovery status and lifecycle audit metadata (GEN-2866), and bounded live portability checks (GEN-2875) are unfinished. Do not assume those controls or evidence exist in a deployed service until their work is complete and the release has been verified.

Trust and data boundaries

  • One Factorize user has one private credential collection, one credential proxy, and one user-owned Fly account/organization connection. That connection can own many execution configurations. Fly and exe.dev are the initial execution providers; the proxy design is provider-independent.
  • The user holds a generated, high-entropy unlock key. There is no password substitute or recovery backdoor. Integration bearer credentials and ChatGPT model tokens are encrypted under this key before Factorize receives them, then protected by Factorize’s independent server encryption. The key and plaintext upstream credentials must not appear in Factorize storage, launch configuration, logs, or backups.
  • The browser is trusted at secret entry: the key is entered into Factorize’s browser UI and trusted frontend code can read it. The browser sends it directly to the proxy over authenticated HTTPS for unlock; Factorize receives status only. The proxy’s public Fly hostname terminates TLS at Fly’s edge and forwards over Fly’s private network. This trusts Fly’s edge and private-network boundary; TLS does not continue to the guest.
  • Factorize is trusted to provision and pair the proxy, administer cloud machines, and authorize run enrollment. Initial pairing is trusted provisioning, not independent user verification. The paired identity includes proxy, Fly app/Machine, HTTPS origin, SSH host fingerprint, and generation. Unexpected identity changes must fail closed and require an authenticated owner’s explicit approval.
  • A named bearer integration is bound to one public HTTPS origin. A granted job can use HTTP methods, paths, queries, and bodies on that origin. Redirects are rejected and destinations must be public. Agent compromise can exercise all authority in that job’s grant. Already-sent requests cannot be recalled; upstream effects can persist independently, including tokens returned by an upstream service.
  • Factorize run API credentials are separate, per-run scoped/revocable credentials. They are not encrypted with the user’s key and are delivered to proxy memory over a separate control path; they must never be placed in a Fly agent VM. Keep grants explicit and minimal. Native exe.dev integrations remain available alongside portable integrations in a separate namespace; adding a portable integration must not change native behavior or implicitly grant it to a job.
  • Portable integration reflection is served at GET $FACTORIZE_PROXY_URL/integrations only through that VM’s authenticated tunnel. It lists the connection’s selected integration names, descriptions, local paths, examples, and availability; it omits upstream origins and all credentials. Locking clears decrypted grants and aborts in-flight forwarding while preserving safe metadata as locked for that established connection. A later unlock refreshes grants from the current run snapshot before restoring access. Each VM connection has an independent listener and reflection view.
  • Database or server-encryption-key theft alone does not reveal the inner user-encrypted records. A compromised Factorize control plane can authorize malicious workloads and administer provisioned cloud machines. A compromised proxy host can access secrets while unlocked. This design does not promise physical erasure of host memory, prevent a key holder from decrypting their ciphertext, or prevent upstream services from retaining access they have granted.

Lifecycle and recovery runbook

Use the browser lifecycle controls when available. The state distinctions matter: stopped has no running proxy; running/locked may serve separately authorized Factorize API access but not user integrations; unlocked can serve its authorized grants; disabled additionally blocks automatic startup and new enrollment. Stop and disable do not stop agent VMs. Re-enable does not unlock. No idle lock or automatic unlock after a crash is promised.
  1. Routine start or unlock: authenticate as the owner in Factorize. Start leaves the proxy locked. Enter the unlock key through the browser’s direct HTTPS flow. Apply pending encrypted edits before new agent connections. If unavailable or locked, dependent launches should report blocked and wait for an explicit retry; they must not silently launch with stale grants.
  2. Edit or update: stage encrypted credential changes in Factorize; they can be made while stopped. A deliberate pinned-image update restarts the proxy locked. Re-enter the key before using user integrations. A changed proxy identity/origin/fingerprint requires explicit owner review and pairing-generation replacement; never trust a DNS change, restart, or new certificate alone.
  3. Stop or disable: stop closes proxy connections and stops the Machine, preserving the Machine for a later start. Disable also revokes enrollment and prevents automatic starts and new enrollment until an owner explicitly enables it. Check agent runs separately: these controls do not stop their VMs, and in-flight upstream requests may complete.
  4. Rotation or lost key: rotation requires the current key and should atomically re-encrypt all current and pending records under a newly generated key, then require unlock with that key. If the key is lost, do not claim to recover it. The reset flow must stop the proxy, revoke grants/enrollments, delete encrypted integration/model-account records and pending changes, and create an empty generation. Preserve the Fly connection and execution configurations; repair jobs that reference deleted items. These browser flows are not yet complete (GEN-2873), so if needed now use the independent Fly shutdown below and wait for the shipped reset flow rather than improvising database edits.
  5. Restart/recovery: a cold or crash restart starts locked and does not restore unlock material. A surviving authorized run may reconnect only after a fresh enrollment is issued. A run that exited is never revived. Factorize may re-issue separate run credentials after restart without unlocking user integrations. A revoked upstream refresh token may require reconnecting that account; do not promise guaranteed refresh recovery.
  6. Image rollback: roll back only to a previously reviewed, digest-pinned proxy image through the normal deployment mechanism. Restart it locked and verify its identity and health before unlocking. Do not restore old secrets, ciphertext generations, pending changes, grants, or enrollments from an image backup. Reconcile any schema/data incompatibility explicitly; stop and reset through the supported owner flow if safe reconciliation is unavailable.

Independent Fly shutdown

If Factorize is unavailable or the proxy must be isolated, stop its Fly Machine from the Fly dashboard: open the owning organization, select the proxy app and its Machine, then choose Stop and verify the Machine is stopped. Identify the proxy Machine carefully; stopping it does not stop execution Machines. With the documented Fly CLI installed and authenticated to the owning organization, the equivalent command is:
Use the app and Machine identity recorded during provisioning. Verify the result in the Fly dashboard or with fly machine status <proxy-machine-id> -a <proxy-app-name> (status command reference). These are Fly CLI commands, not Factorize scripts. This independent stop halts the proxy Machine but does not by itself revoke enrollment or upstream credentials; perform owner-side disable/recovery when Factorize is available.

Verification evidence and release gate

Repository fixtures provide narrow evidence only: packages/app/test/https-pairing.browser.test.mjs exercises local HTTPS origin and pairing decisions; packages/app/test/unlock-crypto.test.mjs covers browser key parsing/cryptography; packages/credential-proxy/test/runtime-process.test.mjs checks the small locked/unlocked process runtime; packages/api/test/fly-machines-client.test.ts uses a local fake Fly API. None establishes live Fly behavior, production HTTPS termination, full browser lifecycle controls, actual upstream portability, or physical host-memory erasure. GEN-2875’s bounded opt-in live checks remain the place for explicitly authorized live evidence; fixture success must not be presented as live verification. Before enabling this design for operators, finish the dependent lifecycle/reset/recovery/live-check issues, run their deterministic local tests and the repository’s full validation, and record separately any bounded live evidence and its prerequisites. For current repository validation, use the instructions in operations and the repository root AGENTS.md; tests must use local fixtures and isolated databases. Do not use production deployment as a verification step for this guide.