What is wrong
CI seeds a PR's preview D1 with read fixtures and nothing else, so no preview carries a
review-ui test account. .github/workflows/ci.yml has one seeding step, Seed preview D1, and it
runs node packages/preview-seed/src/bin.ts run --database-id "${{ steps.preview.outputs.db }}".
packages/preview-seed/src/seed.ts writes terms, definitions, posts and the two FTS tables — no
user, no session. The sibling command that writes those rows, preview-seed test-account
(packages/preview-seed/src/bin.ts), is invoked by no workflow under .github/.
Triage note: verified at origin/main — the seed step is .github/workflows/ci.yml:1018-1023, and
grepping .github/ at main for test-account returns nothing.
Consequence: every review-ui render of a :auth or :auth-caylak surface refuses on 11 ("the
preview answered the seeded cookie as a visitor"), so a PR whose rendered change lives behind sign-in
ends the rendered gate at CANT-SEE with no route to a verdict. Hit twice in one evening — PR #9276
(lane 9265) and PR #9279 (lane 9273). The --flag path inherits the block, since a forced run names
a tier on every surface.
The fix, proven by hand
A driver cleared it manually, first try: resolve the preview's D1 uuid, then run
preview-seed test-account --database-id <uuid> with the two tier session tokens in the environment.
That provisioned @onizleme-mod at yazar and @onizleme-caylak at çaylak with seven-day sessions,
and the re-fired gate authenticated. No Cloudflare permission beyond the token CI already holds.
So the change is an addition beside Seed preview D1, gated on the same
steps.preview.outputs.skipped != 'true', carrying the same steps.preview.outputs.db and the same
CLOUDFLARE_API_TOKEN / CLOUDFLARE_ACCOUNT_ID, plus the two tier token variables the verb reads:
PREVIEW_TEST_SESSION_TOKEN (yazar) and PREVIEW_TEST_CAYLAK_SESSION_TOKEN (çaylak).
Prerequisite a builder cannot supply
Those two repo secrets do not exist yet — the repo's secret list holds only ALCHEMY_PASSWORD,
BETTER_AUTH_SECRET, BETTER_AUTH_SECRET_TEST, CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN. The
token value is the whole credential and must be the same string on both sides: the seeding side (CI)
and the capture side, which reads the same variable names from the driver's environment
(packages/fabrika-cli/src/capture/auth.ts). Creating the two repo secrets from the driver's
existing token values is an act for a person holding the repo's keys, not part of the diff. The
workflow change lands and reviews without them; the live proof needs them set.
Out of scope
Triage note: nothing on the board owns the "CI preview seeding" surface — the nearest tickets are the
four above, and each names a different artifact. Filed standalone.
Acceptance criteria
Original report (verbatim)
Summary
A pull request's preview is seeded with the sözlük and pano fixtures and with nothing else, so the
two review-ui test accounts exist on no preview. Every review-ui render of a :auth or
:auth-caylak surface therefore refuses on 11, and a PR whose only rendered change lives behind
sign-in ends the rendered gate at CANT-SEE with no path to a verdict from inside the gate.
What I was doing
Running the review-ui gate on PR #9276 (issue #9265). The PR's added state — the profile stat
strip's loading placeholders — paints on /profile alone, which is signed-in only.
What I observed
review-ui render --pr 9276 --surface /profile:auth --surface /u/onizleme-mod:auth refused every
tier-naming surface on 11 with surface "/profile:auth" at desktop did not render signed in (the preview answered the seeded cookie as a visitor), at both viewports. The tier tokens and
BETTER_AUTH_SECRET were all present in the run's environment, so the missing half is the account
and its session row on the preview's own D1, not the credentials.
The bare /u/onizleme-mod surface captured cleanly and shows the "kullanıcı bulunamadı" not-found
composition, which is the same fact from the other side: that account is not on this preview's D1.
The seeding step in .github/workflows/ci.yml ("Seed preview D1") runs
node packages/preview-seed/src/bin.ts run --database-id … and nothing else;
packages/preview-seed/src/seed.ts inserts terms, definitions, posts and the two search tables, and
writes no user, session or user_profile rows. preview-seed test-account, the command the
review-ui contract names as what puts each tier's account and session on a preview's D1, is
invoked nowhere in the workflows.
Why it matters
The :auth axis exists precisely so a signed-in-only composition stops being disclosed as unseen,
and today it cannot succeed on any preview. So every PR whose rendered delta is behind sign-in parks
its lane at CANT-SEE and costs a human — and the failure mode is quiet in the other direction too: a
bare route beside an auth-gated one captures the sign-in wall as a valid PNG, which is a clean-looking
shot of a state the PR did not add. The --flag path inherits the same block, since a forced run must
name a tier on every surface.
Pointers
Suggested next step (non-binding)
Extend the same CI step to run preview-seed test-account for both tiers against the preview D1 uuid
the deploy comment already carries, so a preview is seeded with accounts the same way it is seeded
with fixtures. Whether the platform-admin grant the --flag path needs rides along is a separate
call.
Filed by an agent · session 94113692-2733-4534-9963-c7ae534247d0 · 2026-09-15T23:34:37Z
What is wrong
CI seeds a PR's preview D1 with read fixtures and nothing else, so no preview carries a
review-uitest account..github/workflows/ci.ymlhas one seeding step,Seed preview D1, and itruns
node packages/preview-seed/src/bin.ts run --database-id "${{ steps.preview.outputs.db }}".packages/preview-seed/src/seed.tswrites terms, definitions, posts and the two FTS tables — nouser, nosession. The sibling command that writes those rows,preview-seed test-account(
packages/preview-seed/src/bin.ts), is invoked by no workflow under.github/.Triage note: verified at
origin/main— the seed step is.github/workflows/ci.yml:1018-1023, andgrepping
.github/at main fortest-accountreturns nothing.Consequence: every
review-ui renderof a:author:auth-caylaksurface refuses on11("thepreview answered the seeded cookie as a visitor"), so a PR whose rendered change lives behind sign-in
ends the rendered gate at CANT-SEE with no route to a verdict. Hit twice in one evening — PR #9276
(lane 9265) and PR #9279 (lane 9273). The
--flagpath inherits the block, since a forced run namesa tier on every surface.
The fix, proven by hand
A driver cleared it manually, first try: resolve the preview's D1 uuid, then run
preview-seed test-account --database-id <uuid>with the two tier session tokens in the environment.That provisioned
@onizleme-modat yazar and@onizleme-caylakat çaylak with seven-day sessions,and the re-fired gate authenticated. No Cloudflare permission beyond the token CI already holds.
So the change is an addition beside
Seed preview D1, gated on the samesteps.preview.outputs.skipped != 'true', carrying the samesteps.preview.outputs.dband the sameCLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_ID, plus the two tier token variables the verb reads:PREVIEW_TEST_SESSION_TOKEN(yazar) andPREVIEW_TEST_CAYLAK_SESSION_TOKEN(çaylak).Prerequisite a builder cannot supply
Those two repo secrets do not exist yet — the repo's secret list holds only
ALCHEMY_PASSWORD,BETTER_AUTH_SECRET,BETTER_AUTH_SECRET_TEST,CLOUDFLARE_ACCOUNT_ID,CLOUDFLARE_API_TOKEN. Thetoken value is the whole credential and must be the same string on both sides: the seeding side (CI)
and the capture side, which reads the same variable names from the driver's environment
(
packages/fabrika-cli/src/capture/auth.ts). Creating the two repo secrets from the driver'sexisting token values is an act for a person holding the repo's keys, not part of the diff. The
workflow change lands and reviews without them; the live proof needs them set.
Out of scope
user_profilerow for the yazar account (preview-seed writes no user_profile row for the yazar test account, so every profile surface it should render is a 404 #9286) — same gate, different defect, insidethe verb.
no-preview-renderparks (no-preview-render parks have no recipe row, so an unseeded preview costs a human on every auth-gated UI PR #9283).NaN new moderates tuple(s)in the verb's report (preview-seed test-account reports NaN moderates tuples against real D1 #7768), seen on the hand run.--flagpath additionally needs (Preview test accounts hold no platform-admin tuple, so review-ui cannot force a dark-shipped flag #7676).Triage note: nothing on the board owns the "CI preview seeding" surface — the nearest tickets are the
four above, and each names a different artifact. Filed standalone.
Acceptance criteria
.github/workflows/ci.ymlrunspreview-seed test-accountagainst the preview D1 in the same job asSeed preview D1, gated onsteps.preview.outputs.skipped != 'true'and passing--database-id "${{ steps.preview.outputs.db }}".envcarriesCLOUDFLARE_API_TOKEN,CLOUDFLARE_ACCOUNT_ID,PREVIEW_TEST_SESSION_TOKENandPREVIEW_TEST_CAYLAK_SESSION_TOKENfrom repo secrets.@onizleme-modat yazar,@onizleme-caylakat çaylak — and the job stays green.review-ui renderof a:authsurface against this PR's preview no longer refuses on11with "answered the seeded cookie as a visitor": it captures signed in, or refuses for a reason other than a missing account.Original report (verbatim)
Summary
A pull request's preview is seeded with the sözlük and pano fixtures and with nothing else, so the
two
review-uitest accounts exist on no preview. Everyreview-ui renderof a:author:auth-caylaksurface therefore refuses on 11, and a PR whose only rendered change lives behindsign-in ends the rendered gate at CANT-SEE with no path to a verdict from inside the gate.
What I was doing
Running the
review-uigate on PR #9276 (issue #9265). The PR's added state — the profile statstrip's loading placeholders — paints on
/profilealone, which is signed-in only.What I observed
review-ui render --pr 9276 --surface /profile:auth --surface /u/onizleme-mod:authrefused everytier-naming surface on 11 with
surface "/profile:auth" at desktop did not render signed in (the preview answered the seeded cookie as a visitor), at both viewports. The tier tokens andBETTER_AUTH_SECRETwere all present in the run's environment, so the missing half is the accountand its session row on the preview's own D1, not the credentials.
The bare
/u/onizleme-modsurface captured cleanly and shows the "kullanıcı bulunamadı" not-foundcomposition, which is the same fact from the other side: that account is not on this preview's D1.
The seeding step in
.github/workflows/ci.yml("Seed preview D1") runsnode packages/preview-seed/src/bin.ts run --database-id …and nothing else;packages/preview-seed/src/seed.tsinserts terms, definitions, posts and the two search tables, andwrites no
user,sessionoruser_profilerows.preview-seed test-account, the command thereview-uicontract names as what puts each tier's account and session on a preview's D1, isinvoked nowhere in the workflows.
Why it matters
The
:authaxis exists precisely so a signed-in-only composition stops being disclosed as unseen,and today it cannot succeed on any preview. So every PR whose rendered delta is behind sign-in parks
its lane at CANT-SEE and costs a human — and the failure mode is quiet in the other direction too: a
bare route beside an auth-gated one captures the sign-in wall as a valid PNG, which is a clean-looking
shot of a state the PR did not add. The
--flagpath inherits the same block, since a forced run mustname a tier on every surface.
Pointers
.github/workflows/ci.yml— the "Seed preview D1" steppackages/preview-seed/src/seed.ts,packages/preview-seed/src/test-account.ts,packages/preview-seed/src/bin.tsclaude-plugins/fabrika/skills/review-ui/contract.md— the render verb's tier section and its 11no URL), review-ui render cannot reach a popover-hosted control, so the account popover's pickers are unjudgeable #7746 (a control behind a popover)
Suggested next step (non-binding)
Extend the same CI step to run
preview-seed test-accountfor both tiers against the preview D1 uuidthe deploy comment already carries, so a preview is seeded with accounts the same way it is seeded
with fixtures. Whether the platform-admin grant the
--flagpath needs rides along is a separatecall.
Filed by an agent · session
94113692-2733-4534-9963-c7ae534247d0· 2026-09-15T23:34:37Z