Feature Flag Access
Lets a reader request access to a gated feature directly from the docs, without the page ever naming the internal flag.
What it does
Some Harness features roll out behind a flag before general availability. Earlier versions of the docs handled this by publishing the raw flag name and telling readers to ask their account team to enable it, which meant an internal implementation detail sat in public documentation, and every request still had to be handled by hand.
This integration renders a feature card with a Request access button. A reader selects it, fills in a short form, and the request goes straight to the support queue as a Zendesk ticket, with the flag key carried in the payload and never shown on the page.
An author never hand-writes that card. They declare the flag once, in the body of whichever page documents the feature, and an automated job does the rest — it reads every declaration across the docs and renders the same information in two places, from one source of truth.
Why it is built this way
The split between the visible card and the request itself is deliberate:
The card and its modal form are a webframe — display and input only. It collects what the reader types and reports it, nothing more.
Submitting the form is handled by the integration's backend worker, the part of the code that holds credentials and calls out to the ticketing system. The flag key is resolved and attached there, server-side, where a reader's browser cannot see it.
That is a general rule for anything in this space that touches a secret or an external API: the webframe never holds a credential, and the worker is the only part allowed to make the outbound call.
How a page declares a flag
A page that documents a gated feature carries this JSON block, placed just after the H1, wrapped in a condition that always evaluates to false so nothing here ever renders to a reader — it exists purely for the automated job to read:
{ % if "HAS_FEATURE_FLAG" === true % }
```
{
"featureFlags": [{
"key": "YOUR_FLAG_KEY",
"name": "Your feature name",
"status": "BETA",
"description": "What enabling the flag does, in one or two sentences."
}]
}
```
{ % endif % }The spaces inside { % and % } above are deliberate, not a typo. A real, unbroken block anywhere on this page would be picked up by the automated job as a genuine declaration: it would write a live banner and a working Request access button onto this page, and add a real row to the production Feature Availability table, both wired to the real support queue. Nothing on this page is safe to write as functional GitBook syntax unless it is meant to go live — this example is deliberately inert.
status controls what the automated job does with a real declaration: BETA and LIMITED_GA both get a banner on the page and a row on the feature availability page; GA removes both surfaces and leaves only the bare declaration, so the flag stays on record without asking a reader to request access to something everyone already has.
Where else it renders
The same declaration above renders in two places, both written by the automated job, never by hand:
On the page itself, as a hint banner with the request-access card embedded inside it:
On the feature availability page, as a row in the table every gated feature is collected into:
Your feature name
Whichever module the page belongs to
What enabling the flag does, in one or two sentences.
BETA
[ Request access ]
Both mock-ups above are static — this page illustrates the pattern rather than running it. The button in each is not wired to the ticketing queue, on purpose: a working submit button in a space anyone with the link can reach means real tickets from test clicks, indistinguishable from genuine access requests once they land. That is not a trade worth making for a showcase page. The version a reader actually clicks is the one the automated job writes onto a real feature's documentation page, wired to the real support queue.
Last updated
Was this helpful?