diff --git a/apps/web/worker/features/flagship/bildirim.invariant.test.ts b/apps/web/worker/features/flagship/bildirim.invariant.test.ts
index f6b941ff1..90bf3590c 100644
--- a/apps/web/worker/features/flagship/bildirim.invariant.test.ts
+++ b/apps/web/worker/features/flagship/bildirim.invariant.test.ts
@@ -2,7 +2,7 @@
* The dark-ship default-=-safe-state invariant for the bildirim (notification
* system) flag (#1694, epic #1666). Inspected off the exported `BILDIRIM_FLAG`
* record (the same object the factory spreads into `FlagshipFlag`), so no alchemy
- * resource is constructed — mirrors `funnel-readout.invariant.test.ts`.
+ * resource is constructed — mirrors `authorship-loop.invariant.test.ts`.
*/
import {assert, describe, it} from "@effect/vitest";
import {PHOENIX_BILDIRIM} from "../../../src/flags/keys.ts";
diff --git a/apps/web/worker/features/flagship/funnel-readout.invariant.test.ts b/apps/web/worker/features/flagship/funnel-readout.invariant.test.ts
deleted file mode 100644
index b78860781..000000000
--- a/apps/web/worker/features/flagship/funnel-readout.invariant.test.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * The dark-ship default-=-safe-state invariant for the conversion-funnel readout
- * (#1589). Inspected off the exported `FUNNEL_READOUT_FLAG` record (the same object
- * the factory spreads into `FlagshipFlag`), so no alchemy resource is constructed —
- * mirrors `authorship-loop.invariant.test.ts` (#1204).
- */
-import {assert, describe, it} from "@effect/vitest";
-import {PHOENIX_FUNNEL_READOUT} from "../../../src/flags/keys.ts";
-import {FUNNEL_READOUT_FLAG, funnelReadoutFlag} from "./resources.ts";
-
-describe("funnel readout — the IaC default is the safe (off) state", () => {
- it("the flag config ships defaultVariation off and variations.off === false", () => {
- assert.strictEqual(FUNNEL_READOUT_FLAG.defaultVariation, "off");
- assert.strictEqual(FUNNEL_READOUT_FLAG.variations.off, false);
- assert.strictEqual(FUNNEL_READOUT_FLAG.variations.on, true);
- assert.strictEqual(FUNNEL_READOUT_FLAG.key, "phoenix-funnel-readout");
- });
-
- it("the flag key is the shared constant (gate and declaration never diverge)", () => {
- assert.strictEqual(FUNNEL_READOUT_FLAG.key, PHOENIX_FUNNEL_READOUT);
- });
-
- it("the factory is a function of appId (deploy-resolved, not a module constant)", () => {
- assert.strictEqual(typeof funnelReadoutFlag, "function");
- });
-});
diff --git a/apps/web/worker/features/flagship/optimistic-edits.invariant.test.ts b/apps/web/worker/features/flagship/optimistic-edits.invariant.test.ts
index de77e739d..cb7b68f73 100644
--- a/apps/web/worker/features/flagship/optimistic-edits.invariant.test.ts
+++ b/apps/web/worker/features/flagship/optimistic-edits.invariant.test.ts
@@ -3,7 +3,7 @@
* content-edit flag (#1675, epic #1637). Inspected off the exported
* `OPTIMISTIC_EDITS_FLAG` record (the same object the factory spreads into
* `FlagshipFlag`), so no alchemy resource is constructed — mirrors
- * `funnel-readout.invariant.test.ts` (#1589).
+ * `authorship-loop.invariant.test.ts` (#1204).
*/
import {assert, describe, it} from "@effect/vitest";
import {PHOENIX_OPTIMISTIC_EDITS} from "../../../src/flags/keys.ts";
diff --git a/apps/web/worker/features/flagship/resources.ts b/apps/web/worker/features/flagship/resources.ts
index 9bb9bdb5e..cb825123d 100644
--- a/apps/web/worker/features/flagship/resources.ts
+++ b/apps/web/worker/features/flagship/resources.ts
@@ -22,7 +22,6 @@ import {
PHOENIX_EDGE_SHELL_BOOT,
PHOENIX_EMAIL_DELIVERY_ADMIN,
PHOENIX_EMAIL_DELIVERY_NOTICE,
- PHOENIX_FUNNEL_READOUT,
PHOENIX_KARMA_GATES,
PHOENIX_NAV_IA,
PHOENIX_OPTIMISTIC_DEFINITION_ADD,
@@ -98,7 +97,6 @@ export {
PANO_DRAFT_SAVE,
PHOENIX_AUTHORSHIP_LOOP,
PHOENIX_BILDIRIM,
- PHOENIX_FUNNEL_READOUT,
PHOENIX_KARMA_GATES,
PHOENIX_OPTIMISTIC_DEFINITION_ADD,
PHOENIX_OPTIMISTIC_EDITS,
@@ -274,39 +272,6 @@ export const authorshipLoopFlag = (appId: Input) =>
rules: AUTHORSHIP_LOOP_RULES,
});
-/**
- * The conversion-funnel readout dark-ship flag config (#1589) — the founder/mod
- * tier-count surface gates behind this key. Default-OFF so the readout reaches
- * production dark; flipping it on is the human release act (ADR 0083). Its own key
- * (not `phoenix-authorship-loop`) so the funnel destination has an independent
- * lifecycle.
- *
- * Exported as a plain object so the default-=-safe-state invariant is
- * unit-inspectable WITHOUT constructing the alchemy resource (mirrors
- * `PANO_DRAFT_SAVE_FLAG`, #746).
- *
- * Per-flag metadata (the IaC ownership record `feature-flags-schema-lifecycle.md`
- * asks for):
- * - owner: funnel (the conversion-readout founder/mod surface)
- * - originating: #1589 (the çaylak→yazar conversion readout)
- * - removal trigger: once the funnel readout graduates to on at 100% and stable
- * for one release, retire the flag and inline the surface.
- */
-export const FUNNEL_READOUT_FLAG = {
- key: PHOENIX_FUNNEL_READOUT,
- description:
- "conversion-funnel readout dark-ship (#1589). owner: funnel. removal: retire once on at 100% and stable.",
- defaultVariation: "off",
- variations: {off: false, on: true},
-} as const;
-
-/**
- * A plain boolean kill-switch, no targeting rules. `appId` is resolved at deploy
- * (see `demoTargetingFlag` for why it's a factory, not a module constant).
- */
-export const funnelReadoutFlag = (appId: Input) =>
- Cloudflare.Flagship.Flag("phoenix_funnel_readout", {appId, ...FUNNEL_READOUT_FLAG});
-
/**
* The optimistic in-place content-edit dark-ship flag config (#1675, epic #1637).
* The three Class-A content edits (`post.edit`/`comment.edit`/`definition.edit`)
@@ -532,7 +497,7 @@ export const karmaGatesFlag = (appId: Input) =>
* the human release act (ADR 0083).
*
* Exported as a plain object so the default-=-safe-state invariant is
- * unit-inspectable WITHOUT constructing the alchemy resource (mirrors `FUNNEL_READOUT_FLAG`).
+ * unit-inspectable WITHOUT constructing the alchemy resource (mirrors `PANO_DRAFT_SAVE_FLAG`).
*
* Per-flag metadata (`feature-flags-schema-lifecycle.md`):
* - owner: pasaport (the identity + session-boundary surface)
diff --git a/apps/web/worker/features/funnel/fate-module.ts b/apps/web/worker/features/funnel/fate-module.ts
index 7742eee61..f316aab89 100644
--- a/apps/web/worker/features/funnel/fate-module.ts
+++ b/apps/web/worker/features/funnel/fate-module.ts
@@ -4,8 +4,8 @@ import {queries} from "./queries.ts";
import {funnelSummaryDataView} from "./views.ts";
const roots: FateRootsRecord = {
- // The conversion-funnel readout (#1589) — founder/mod-gated, behind the
- // `phoenix-funnel-readout` flag; the `funnel.summary` resolver owns the gate.
+ // The conversion-funnel readout (#1589) — founder/mod-gated; the
+ // `funnel.summary` resolver owns the capability gate.
"funnel.summary": funnelSummaryDataView,
};
diff --git a/apps/web/worker/features/funnel/queries.ts b/apps/web/worker/features/funnel/queries.ts
index 91a94da21..2a13e1f7b 100644
--- a/apps/web/worker/features/funnel/queries.ts
+++ b/apps/web/worker/features/funnel/queries.ts
@@ -2,14 +2,9 @@
* The funnel root query resolver (#1589) — `funnel.summary`, the founder/mod
* conversion readout's single gated read.
*
- * Two gates, both enforced HERE (the `Funnel` service read is unconditional):
- *
- * 1. The `phoenix-funnel-readout` dark-ship flag (default-off, ADR 0083). Off ⇒
- * the read fails the invisible {@link Denied}, exactly like a non-mod read — so
- * with the flag off (default / Flagship outage) nothing leaks, even on a direct
- * call. Read with the safe `false` default (`stats`/`divan` idiom).
- * 2. The {@link requireFunnelAccess} capability gate — platform-moderation only.
- * `yield* ViewFunnel` makes the read unreachable without the discharged grant.
+ * The {@link requireFunnelAccess} capability gate — platform-moderation only —
+ * guards the read: `yield* ViewFunnel` makes it unreachable without the discharged
+ * grant, so a non-mod read fails the invisible {@link Denied}.
*
* A synthetic singleton like `stats.landingStats`: the wire type is the NAME string
* (`"FunnelSummary"`), not the view class, so the entity stays off the source-
@@ -20,21 +15,12 @@
import {Fate} from "@kampus/fate-effect";
import {Effect} from "effect";
import * as Schema from "effect/Schema";
-import {PHOENIX_FUNNEL_READOUT} from "../../../src/flags/keys.ts";
-import {Flags} from "../flagship/Flags.ts";
-import {provideRequestFlags} from "../flagship/FlagsContext.ts";
import {Denied} from "../kunye/errors.ts";
import {Funnel, promotionRate} from "./Funnel.ts";
import {requireFunnelAccess, ViewFunnel} from "./gate.ts";
const FUNNEL_SUMMARY_ID = "summary";
-/** Is the funnel readout on for this request? Safe-default `false` (dark). */
-const readoutOn = Effect.gen(function* () {
- const flags = yield* Flags;
- return yield* flags.getBoolean(PHOENIX_FUNNEL_READOUT, false).pipe(provideRequestFlags);
-});
-
// The post-gate summary read — `ViewFunnel`-gated in R (`requireFunnelAccess`
// provides the grant). `yield* ViewFunnel` requires the proof; the counts are
// unreachable without a discharged grant.
@@ -62,9 +48,6 @@ export const queries = {
"funnel.summary": Fate.query(
{type: "FunnelSummary", error: Schema.Union([Denied])},
Effect.fn("funnel.summary")(function* () {
- if (!(yield* readoutOn)) {
- return yield* Effect.fail(new Denied({message: "Dönüşüm metrikleri şu an kapalı."}));
- }
return yield* requireFunnelAccess(summaryGated());
}),
),