Getting support without giving us access
Support for downpipes is built on a constraint the rest of the product already lives by. The vendor holds no Cloudflare token for your account, no dashboard seat, and no standing credential of any kind, so there is nothing on the vendor side that can reach into your account to look at a problem. Support works on evidence you hand out, not on access we hold.
That sounds like it would make support hard. In practice it makes the common case simpler than a screen-share: you download a redaction-safe diagnostics bundle from the console and attach it to your ticket, and that single file carries what support needs to read your situation. When a live ticket needs fresh evidence after that, the one escalation is a short, scoped credential that you mint and you revoke. There is no other inbound path, and there is never a standing one.
This page is the canonical account of that support model end to end. It states the premise, walks the default flow and the single escalation, and is precise about what “no vendor access” does and does not mean.
The premise: support without a credential we hold
The two easy answers a support team usually reaches for are a vendor-held Cloudflare token and a vendor seat in your dashboard. The product’s no-custody rule forbids both, and the support code is written around that absence rather than asking you to relax it for a ticket (engine/src/admin/support.ts).
So the question the design answers is: how does support get the evidence it needs when it holds nothing? The answer has two parts. By default, you hand evidence out as a file. When that is not enough during a live ticket, you mint a short-lived, read-only credential that lets support pull the same evidence a few times, then you revoke it. Both paths move evidence outward from your account under your control. Neither gives the vendor anything that outlasts the ticket.
The default flow: download a bundle, attach it to the ticket
The lowest-friction path needs no inbound vendor access at all. Any signed-in role can open the console, download the support bundle, and attach it to the ticket. The bundle is a redaction-safe aggregation of what support actually reads: the engine version and its release provenance, presence-only status, the preflight report, per-downpipe run-history rows with their coarse error vocabulary, notification delivery outcomes, the licence tier, and, for a volume-banded licence, an estate rollup used to check that band at intake (buildSupportBundle, engine/src/admin/support.ts).
What the bundle deliberately leaves out is the point. It never contains a key, a secret value, a record name beyond your own downpipe names, or your data. The console states this at the download button, so the redaction-safe property is visible where you act on it (renderSupportBundle, console/src/screens/settings/support.ts).
The bundle is also self-protecting in transit. The engine signs it with the same run signer it uses to sign every backup, so support can confirm the file came from your engine and was not altered on the way (signedSupportBundle, engine/src/admin/support.ts). When a vendor support key is configured, the bundle is additionally sealed to that key with the same hybrid encapsulation that protects an archive, so the file stays confidential through whatever ticket system carries it (sealedSupportBundle, engine/src/admin/support.ts). The console reports the seal and signature state honestly rather than implying a guarantee that is not in place: a pre-ceremony engine serves the bundle unsigned and says so, and with no vendor key configured it tells you to treat the file like any diagnostic attachment (vendorSealPresentation, console/src/screens/settings/support.ts).
The signature is over the bundle’s own contents, which is provenance, not full archive verification. It lets support confirm the file is from your engine and unmodified. It does not turn the file into proof that a backup is recoverable, which is a separate path described under recovery.
Sending a pack is also the only moment a volume-banded licence’s declared band is ever checked against your real estate. The engine itself never measures your estate against your tier and nothing about it phones home; the rollup sits locally in your console and in the engine’s own status API either way, and support only sees it inside a pack you chose to attach. The check itself is deterministic and never blocks a restore: a ticket about data loss, a restore, or a security concern is helped first regardless of what the numbers say, with any true-up handled afterwards, while a routine ticket from an over-band account gets a friendly note and an invitation to talk about the right plan before deeper work proceeds. For the full band definitions and this policy in detail, see licensing, editions, and the control-plane; for exactly what the estate rollup contains, see the support bundle.
The single escalation: a short, Owner-minted diagnostics pull
Sometimes a file attached at one moment is not enough, and support needs to pull fresh evidence while a ticket is live. That is the only case where evidence flows on the vendor’s request rather than yours, and even then you stay in control of it.
The mechanism is a platform-issued credential under the diagnostics scope. An Owner mints it, support presents it to fetch the same signed bundle once or a few times from a route that sits outside the admin API, and the Owner revokes it when the ticket is done (mintIngestCredential and handleSupportPull, engine/src/admin/support-ingest.ts). The credential grants exactly one read-only feed. It carries no admin route, no restore, no configuration write, and no access to your data (handleSupportPull, engine/src/admin/support-ingest.ts).
An Owner mints the credential
Minting is Owner-only, enforced server-side, and audited; a refused attempt is recorded the same way a refused role change is (
POST /admin/support/credentials,engine/src/admin/router-status.ts). Because opening a pull surface carries the custody weight of granting a role, the mint is an opt-in dual-control action: when dual control is on, a second Owner approves the decision before the credential is issued.The mint also asks you to re-authenticate with your passkey at the moment you make it, a step-up the engine requires on the route rather than a console prompt you could skip. Dual control is not a substitute for it and was not treated as one: dual control is opt-in, it needs a second Owner to exist, and a single-Owner self-hosted account would get nothing from it, so a stale browser session alone must not be able to open a read-only pull surface and hand back a bearer. The secret is shown once, behind a conceal and reveal field that copies without revealing, and the console never stores it (
oneTimeCredentialReveal,console/src/screens/settings/support.ts).Support pulls the bundle
Support presents the credential as a single bearer token to fetch the sealed and signed bundle. The engine verifies it with a constant-time hash comparison against the stored hash and enforces expiry on its own clock, so a stale credential simply stops working (
checkIngestCredential,engine/src/admin/support-ingest.ts). Every successful pull is recorded on the grant, and the console shows you when the credential was last used (supportGrantPresentation,console/src/screens/settings/support.ts).The Owner revokes it
Revocation is immediate and Owner-only: confirm it and support stops working at once. It asks for no step-up, deliberately and unlike the mint: requiring a fresh re-authentication to shut off a credential you suspect is stolen would be friction at the worst moment. Re-minting issues a fresh credential and kills the old secret straight away, which is the rotation path, and the fresh mint asks for the step-up the revoke did not (
POST /admin/support/credentials/delete,engine/src/admin/router-status.ts).
The credential is short by design. It defaults to 72 hours and is capped at 7 days, so even an un-revoked credential ages out on the engine’s own clock well inside the life of a ticket (INGEST_TTL_CAPS_SECONDS, engine/src/admin/support-ingest.ts). Only the secret’s SHA-384 is ever stored, never the secret, so neither the engine nor the console can hand the live secret to anyone after the one-time reveal. For the credential lifecycle in full, see pull credentials.
Default versus escalation, side by side
The two paths differ in who initiates the evidence flow and in whether any inbound access exists at all.
| Default flow | Escalation | |
|---|---|---|
| Who acts | Any signed-in role downloads the bundle | An Owner mints the credential; support pulls |
| Inbound vendor access | None: you attach the file to the ticket | One read-only diagnostics pull, time-boxed and revocable |
| What support receives | The redaction-safe bundle you choose to send | The same bundle, fetched while the credential is valid |
| Lifetime | The single file you attached | Default 72 hours, 7-day cap, or until you revoke |
| Control point | You decide what to attach and when | You mint it and you revoke it |
In both rows the evidence is the same redaction-safe bundle. The only difference the escalation adds is a short window in which support may fetch it without waiting for you to re-attach a file, and that window is opened and closed by an Owner.
What “no vendor access” means precisely
“No vendor access” is a statement about custody, not about what is reachable on the network. The honest claim is that the vendor holds no Cloudflare token, no dashboard seat, and no standing credential for your account. There is no credential sitting on the vendor side, by default or otherwise, that opens a door into your engine.
The Owner-minted diagnostics lease does not contradict that. A lease you create, scope to read-only, time-box, and revoke is consistent with no-custody precisely because the vendor never holds it as a standing capability: it exists only while you allow it, grants only one read-only feed, and the engine refuses it the moment it expires or you revoke (checkIngestCredential and handleSupportPull, engine/src/admin/support-ingest.ts). The control sits with you at every step, which is the property no-custody is about. For the full account of what the vendor and the engine can and cannot hold, see the no-custody trust model.
The bundle and the audit content carry operator identity, so they are not free of personal data. The bundle includes your own downpipe names and operational facts, and the separate audit feed records actor email, source address, role and approver identities. Treat both as evidence about your operators, sealed in transit when a vendor key is configured, not as anonymous telemetry.
A note on wording that matters here. The bundle’s integrity property is tamper-evident: the run signer’s signature lets support detect a file that was altered after your engine produced it. It is not a claim that the file cannot be altered, only that an alteration is detectable.
Where this fits
Deeper detail: the routes, the audit feed, and what is not in the CLI
Three scopes, three lifetimes. The platform issues a client and secret credential per scope. The diagnostics scope is the short-lived support pull described above. A separate audit-feed scope lets your own SIEM collector poll the hash-chained audit events on a long-lived schedule, defaulting to 90 days and capped at 365, cursored by sequence number for checkpointing. A third, metrics scope lets a Prometheus-compatible scraper pull the /metrics surface on the longest-lived schedule of the three, defaulting to 365 days and capped at 400 (INGEST_TTL_CAPS_SECONDS and handleSupportPull, engine/src/admin/support-ingest.ts). One credential is active per scope; re-granting replaces it. The audit feed and the metrics feed are both customer-operated, not a vendor path; the audit feed is described under the audit log and the metrics feed under backup health for your monitoring stack.
The pull route sits outside the admin API. Support never authenticates as a console user. The diagnostics pull is served from a route that takes no admin token and no Access seat, gated only by the bearer credential for the matching scope; a failed presentation is a plain unauthorised response with no detail (handleSupportPull, engine/src/admin/support-ingest.ts). The most recent 50 pulls are retained on the grant for you to see, and older entries roll over, so the console reports recent usage rather than a total it cannot know (supportGrantPresentation, console/src/screens/settings/support.ts).
The Go reader’s bundle is a different artefact. The open-source reader has no support path, no ingest credential, and no offboarding capability. Where its documentation says “bundle” it means the in-bucket recovery bundle: a verbatim copy of the format specification and plain recovery instructions, plus a SHA384SUMS over them with a detached hybrid signature, which the reader can verify with its --check-bundle option. That recovery-notes bundle is not the encrypted archive itself and is unrelated to the support bundle this page describes; do not read one as the other.
This page owns the support model for the site. For exactly what the downloaded file contains, field by field, see the support bundle. For the credential lifecycle, the dual-control gate and the usage trail, see pull credentials. When you are leaving the product, the controlled exit sequence (removing roles, deprovisioning identity in your own dashboard, and keeping your offline keys) lives in leave downpipes.
Last updated .