Spike done. Recommendation: do not adopt a feature flag manager.docs/ops/feature-flags.md.
The finding
This project already has two flag mechanisms and uses both idiomatically.
Environment variables do per-environment gating — DEMO_MODE, REMBG_URL, BREVO_TRACKER_KEY, ANTHROPIC_API_KEY, USPS, SMTP — with a consistent documented convention: unset means the feature does not exist and the app is working, not broken. QA runs with several deliberately empty, which is precisely how it cannot reach PayPal, cannot email anyone, and cannot report browsing into the live Brevo account. That is a feature flag system; it just is not called one.
admin_settings does runtime tuning by whoever runs the shop. Its own header already states the principle a flag manager would sell you: a setting is changed by the person running the shop, not the person deploying it. drafting_model and intake_notify_email live there for exactly that reason.
What is actually missing
admin_settings supports hours, count, text and choice. There is no boolean.
So the single thing a manager would add that this project lacks — an admin-flippable on/off for a code path, without a rebuild — is a missing value type in a store that already does everything else. A definition entry, a parse branch, and a control.
That is the whole gap, and it is not a reason to run another service on a NAS already hosting Gitea, the CI runner, QA and production.
No tool was compared until that was established, because a spike that starts by comparing platforms will always find one.
Nothing to flag right now
The issue said a spike that cannot name a concrete change should conclude "not yet". It cannot.
Passkeys (#37–#42) is naturally incremental — nothing is user-visible until #41 puts it on the login form, so the ordering does the gating.
#313's trust proxy change cannot be flagged. It is only correct once Cloudflare is actually in front, so a runtime toggle would let it be wrong on purpose. Worse than not having one.
The strongest hypothetical is a kill switch for passkey login, since #41 records it as the one feature that cannot be fully proven in QA — credentials bind to the RP ID, so production is the first place it runs for real. Still not enough while passkeys are not being built and production is not live.
For whenever the answer changes
The comparison is in the doc, with the constraint that matters most stated plainly: fail-safe behaviour beats features. A flag service that takes the shop down when unreachable is worse than no flags — and admin_settings reads from the database the app already cannot run without, so it has no failure mode of its own. That is a real advantage over every hosted or sidecar option.
Flipt is the only candidate that obviously fits the machine. Unleash carries a caveat worth keeping: its OSS Edge sunsets 2026-12-31, which makes a free tool acquire a paid dependency inside a year.
The four conditions that would reopen this are written down rather than left implied.
Verification
Every claim about the repository was read from the code today: 10 settings in admin_settings, no boolean type, env-var gating across app.ts, envValidation.ts, anthropicClient.ts and draftingWorker.ts. Tool capabilities and pricing were checked 2026-09-08 and are worth re-confirming at decision time.
Docs-only — no code, no deploy, so the QA-before-production step does not apply here.
Spike done. **Recommendation: do not adopt a feature flag manager.** `docs/ops/feature-flags.md`.
## The finding
This project **already has two flag mechanisms** and uses both idiomatically.
**Environment variables** do per-environment gating — `DEMO_MODE`, `REMBG_URL`, `BREVO_TRACKER_KEY`, `ANTHROPIC_API_KEY`, USPS, SMTP — with a consistent documented convention: unset means the feature does not exist and the app is *working*, not broken. QA runs with several deliberately empty, which is precisely how it cannot reach PayPal, cannot email anyone, and cannot report browsing into the live Brevo account. That is a feature flag system; it just is not called one.
**`admin_settings`** does runtime tuning by whoever runs the shop. Its own header already states the principle a flag manager would sell you: a setting is changed by the person running the shop, not the person deploying it. `drafting_model` and `intake_notify_email` live there for exactly that reason.
## What is actually missing
`admin_settings` supports `hours`, `count`, `text` and `choice`. **There is no boolean.**
So the single thing a manager would add that this project lacks — an admin-flippable on/off for a code path, without a rebuild — is a missing value type in a store that already does everything else. A definition entry, a parse branch, and a control.
That is the whole gap, and it is not a reason to run another service on a NAS already hosting Gitea, the CI runner, QA and production.
**No tool was compared until that was established**, because a spike that starts by comparing platforms will always find one.
## Nothing to flag right now
The issue said a spike that cannot name a concrete change should conclude "not yet". It cannot.
- **Passkeys (#37–#42)** is naturally incremental — nothing is user-visible until #41 puts it on the login form, so the ordering does the gating.
- **#313's `trust proxy` change cannot be flagged.** It is only correct once Cloudflare is actually in front, so a runtime toggle would let it be wrong on purpose. Worse than not having one.
The strongest hypothetical is a **kill switch for passkey login**, since #41 records it as the one feature that cannot be fully proven in QA — credentials bind to the RP ID, so production is the first place it runs for real. Still not enough while passkeys are not being built and production is not live.
## For whenever the answer changes
The comparison is in the doc, with the constraint that matters most stated plainly: **fail-safe behaviour beats features.** A flag service that takes the shop down when unreachable is worse than no flags — and `admin_settings` reads from the database the app already cannot run without, so it has no failure mode of its own. That is a real advantage over every hosted or sidecar option.
Flipt is the only candidate that obviously fits the machine. **Unleash carries a caveat worth keeping: its OSS Edge sunsets 2026-12-31**, which makes a free tool acquire a paid dependency inside a year.
The four conditions that would reopen this are written down rather than left implied.
## Verification
Every claim about the repository was read from the code today: 10 settings in `admin_settings`, no `boolean` type, env-var gating across `app.ts`, `envValidation.ts`, `anthropicClient.ts` and `draftingWorker.ts`. Tool capabilities and pricing were checked 2026-09-08 and are worth re-confirming at decision time.
Docs-only — no code, no deploy, so the QA-before-production step does not apply here.
Closes #318
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The spike asked whether this project should adopt feature flag management and whether a free option fits. The answer is that it already has two flag mechanisms, uses both idiomatically, and is not short of a third.
Environment variables do per-environment gating, with a consistent and documented convention: unset means the feature does not exist and the application is working rather than broken. QA runs with several deliberately empty, which is how it cannot reach PayPal, cannot email anyone and cannot report browsing into the live Brevo account. That is a feature flag system; it is simply not called one.
admin_settings does runtime tuning by whoever runs the shop, and its own header already states the principle a flag manager would sell: a setting is changed by the person running the shop rather than the person deploying it. drafting_model and intake_notify_email live there for exactly that reason.
What is missing is one value type. admin_settings supports hours, count, text and choice, and has no boolean — so the single thing a manager would add that this project lacks is an admin-flippable on/off, in a store that already does everything else. That is a definition entry, a parse branch and a control. It is not a reason to run another service on a NAS that already hosts Gitea, the runner, QA and production.
No tool was compared until that was established, because a spike that starts by comparing platforms will always find one. The comparison is included for whenever the answer changes, with the constraint that matters most stated plainly: fail-safe behaviour beats features, and a flag service that takes the shop down when unreachable is worse than no flags. admin_settings reads from the database the application already cannot run without, so it has no failure mode of its own.
The issue said a spike that cannot name a concrete change needing a flag should conclude not yet, and it cannot. Seven of the nine open issues are the Passkeys epic, which is naturally incremental and gates itself by ordering, and #313, whose trust proxy change cannot be flagged at all — it is only correct once Cloudflare is in front, so a runtime toggle would let it be wrong on purpose. The strongest hypothetical is a kill switch for passkey login, because #41 records it as the one feature that cannot be fully proven in QA, and that is still not enough while passkeys are not being built and production is not live.
The conditions that would change the answer are written down rather than left implied, so this does not get reopened from scratch.
Unleash carries a caveat worth keeping: its OSS Edge sunsets on 2026-12-31, which makes a free tool acquire a paid dependency inside a year.
Closes#318
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Spike done. Recommendation: do not adopt a feature flag manager.
docs/ops/feature-flags.md.The finding
This project already has two flag mechanisms and uses both idiomatically.
Environment variables do per-environment gating —
DEMO_MODE,REMBG_URL,BREVO_TRACKER_KEY,ANTHROPIC_API_KEY, USPS, SMTP — with a consistent documented convention: unset means the feature does not exist and the app is working, not broken. QA runs with several deliberately empty, which is precisely how it cannot reach PayPal, cannot email anyone, and cannot report browsing into the live Brevo account. That is a feature flag system; it just is not called one.admin_settingsdoes runtime tuning by whoever runs the shop. Its own header already states the principle a flag manager would sell you: a setting is changed by the person running the shop, not the person deploying it.drafting_modelandintake_notify_emaillive there for exactly that reason.What is actually missing
admin_settingssupportshours,count,textandchoice. There is no boolean.So the single thing a manager would add that this project lacks — an admin-flippable on/off for a code path, without a rebuild — is a missing value type in a store that already does everything else. A definition entry, a parse branch, and a control.
That is the whole gap, and it is not a reason to run another service on a NAS already hosting Gitea, the CI runner, QA and production.
No tool was compared until that was established, because a spike that starts by comparing platforms will always find one.
Nothing to flag right now
The issue said a spike that cannot name a concrete change should conclude "not yet". It cannot.
trust proxychange cannot be flagged. It is only correct once Cloudflare is actually in front, so a runtime toggle would let it be wrong on purpose. Worse than not having one.The strongest hypothetical is a kill switch for passkey login, since #41 records it as the one feature that cannot be fully proven in QA — credentials bind to the RP ID, so production is the first place it runs for real. Still not enough while passkeys are not being built and production is not live.
For whenever the answer changes
The comparison is in the doc, with the constraint that matters most stated plainly: fail-safe behaviour beats features. A flag service that takes the shop down when unreachable is worse than no flags — and
admin_settingsreads from the database the app already cannot run without, so it has no failure mode of its own. That is a real advantage over every hosted or sidecar option.Flipt is the only candidate that obviously fits the machine. Unleash carries a caveat worth keeping: its OSS Edge sunsets 2026-12-31, which makes a free tool acquire a paid dependency inside a year.
The four conditions that would reopen this are written down rather than left implied.
Verification
Every claim about the repository was read from the code today: 10 settings in
admin_settings, nobooleantype, env-var gating acrossapp.ts,envValidation.ts,anthropicClient.tsanddraftingWorker.ts. Tool capabilities and pricing were checked 2026-09-08 and are worth re-confirming at decision time.Docs-only — no code, no deploy, so the QA-before-production step does not apply here.
Closes #318
🤖 Generated with Claude Code