-
Notifications
You must be signed in to change notification settings - Fork 0
fix(gateway): scan csv variables element by element in guardrails #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a5b78aa
85506ee
5baaa3f
e455a77
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| --- | ||
| title: Feature Flags — One csv Variable, Flipped Without a Rebuild | ||
| description: Use a single REP_PUBLIC_FEATURE_FLAGS csv variable for deployment-wide feature flags. Manifest declaration, SDK reads, guardrail behaviour, flipping flags without a rebuild, and what REP flags are not. | ||
| --- | ||
|
|
||
| import { Aside } from '@astrojs/starlight/components'; | ||
|
|
||
| REP can carry simple feature flags: switches that are on or off for a whole deployment. Use one `csv` variable that lists the flags that are on. | ||
|
|
||
| ## Declare one variable | ||
|
|
||
| ```yaml | ||
| # .rep.yaml | ||
| variables: | ||
| FEATURE_FLAGS: | ||
| tier: public | ||
| type: csv | ||
| default: "" | ||
| pattern: "([a-z0-9-]+(,[a-z0-9-]+)*)?" # optional: kebab-case names, no spaces | ||
| description: "Flags that are on, comma-separated" | ||
| ``` | ||
|
|
||
| Use one variable for all flags, not one per flag. Adding a flag is then a value change, not a manifest change. | ||
|
|
||
| With `default: ""`, an unset `REP_PUBLIC_FEATURE_FLAGS` becomes an empty list, so every flag is off (see [Defaults](/guides/manifest/#defaults)). The optional `pattern` rejects typos such as stray spaces or capitals at startup. | ||
|
|
||
| ## Read it with the SDK | ||
|
|
||
| ```typescript | ||
| import { rep } from '@rep-protocol/sdk'; | ||
|
|
||
| const enabled = new Set( | ||
| rep.get('FEATURE_FLAGS', '').split(',').map((f) => f.trim()).filter(Boolean), | ||
| ); | ||
|
|
||
| export const isOn = (flag: string) => enabled.has(flag); | ||
|
Comment on lines
+32
to
+36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The guide constructs Artifacts
▶ Guide example before hot reload
Guide example before hot reload poster
▶ Guide example after SDK hot reload
Guide example after hot reload poster
|
||
| ``` | ||
|
|
||
| A flag is **off unless it is named**. There is no list of known flags to keep in sync and no "false" value to set. | ||
|
|
||
| The second argument to `rep.get()` covers the case with no gateway at all, such as unit tests or a plain `vite dev`. Behind the gateway, the manifest default already guarantees a string. | ||
|
|
||
| For example, a single image might serve a marketing landing page at `/` on its hosted deployment and redirect `/` straight to sign-in everywhere else: | ||
|
|
||
| ```bash | ||
| # hosted deployment | ||
| REP_PUBLIC_FEATURE_FLAGS=landing-page | ||
| # self-hosted deployment: leave it unset — every flag is off | ||
| ``` | ||
|
|
||
| ```typescript | ||
| if (location.pathname === '/' && !isOn('landing-page')) location.replace('/login'); | ||
| ``` | ||
|
|
||
| ## Flags are public | ||
|
|
||
| `FEATURE_FLAGS` is a PUBLIC variable, so its value is in the page source of every page the gateway serves. | ||
|
|
||
| - **Never put a secret in a flag name.** That includes a token, a customer name, or an unreleased product's codename you can't disclose. | ||
| - **A flag is not access control.** Hiding a button does not stop anyone calling the API behind it, so the server must still check permissions. | ||
|
|
||
| ## Guardrails judge each flag, not the list | ||
|
|
||
| The gateway's [guardrails](/concepts/variable-classification/#automatic-secret-detection-guardrails) check a `csv` value one element at a time. A long list of short flags can't make `--strict` refuse to start, and an element that looks like a secret is still flagged. | ||
|
|
||
| ### Dev plugins | ||
|
|
||
| <Aside type="caution"> | ||
| The Vite and Next.js dev plugins don't read `.rep.yaml`, so they check the whole value. With their `strict` option on, a flag list longer than 64 characters can still throw in development even though the gateway accepts it. Leave `strict` off in the dev plugins, or keep the local list short. | ||
| </Aside> | ||
|
|
||
| ## Flipping a flag | ||
|
|
||
| You flip a flag by changing the environment, not the image: | ||
|
|
||
| - **Restart:** set `REP_PUBLIC_FEATURE_FLAGS` and restart the container or roll the deployment. | ||
| - **Hot reload:** with `--hot-reload` and `--env-file`, the gateway picks up edits to that file without a restart; it does not see changes to its own process environment. Pages using `rep.onChange('FEATURE_FLAGS', …)` or a framework adapter update in place. See [Hot Reload](/concepts/hot-reload/), the [Kubernetes recipe](/deployment/kubernetes/), and the end-to-end [Next.js example](/examples/nextjs-csr-embedded/). | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The guide says ArtifactsAuthored live gateway reproduction script
Live gateway run and observed output
Gateway response before the env-file edit
Gateway response after the env-file edit without SIGHUP
Gateway response after sending SIGHUP
|
||
|
|
||
| ## What this is not | ||
|
|
||
| A REP flag has one value per deployment, shared by every visitor. That makes it a good fit for environment differences, kill switches and staged launches. It cannot do: | ||
|
|
||
| - per-user or per-account targeting; | ||
| - percentage or gradual rollouts; | ||
| - A/B tests or experiments; | ||
| - an audit trail or a UI for non-engineers. | ||
|
|
||
| If you need any of those, use a dedicated feature-flag service. REP can still deliver that service's public client key as a PUBLIC variable. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The YAML labeled
.rep.yamlomits the required top-levelversion. Copying it as a manifest makesrep validatefail before readers can use the feature flags. Add a version or clearly label the YAML as a fragment of an existing manifest.Artifacts
Feature-flags manifest validation script
Copied manifest fails validation
Manifest with version passes validation