An organizer who opens their own signup's link can't get to its responses from there
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 45/100
- issue の種類
- 機能追加
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- next.js, typescript
調査の方向性
Start with src/app/s/[slug]/page.tsx, src/auth/session.ts, and src/lib/policy.ts to trace how the public signup and organizer membership are loaded; review the linked discussion in #583 as well. Then inspect SignupView and the query budget and end to end specs named in the issue. Done means workspace members see the Responses and Build links on open and closed signups, visitors and nonmembers do not, and the listed budgets and checks pass.
索引モデルが issue の本文から書いたものです。
説明
Needs your OK: this changes what a signed-in organizer sees on their own signup's public page: a bar at the top with links to Responses and Build. Participants see no change. Swap pipeline:proposed for pipeline:ready to have it built.
What happens
An organizer opened their own open signup from the link they'd shared and asked where to see the responses. The page gave them no way to find out.
- The public page never checks who's signed in.
PublicSignupPageinsrc/app/s/[slug]/page.tsxreads only the returning-participant cookie (COMMIT_COOKIE_NAME). An organizer sees exactly what a participant sees: the title, the slots and the Sign up buttons. Nothing says it's their signup or where the responses are. - The only link off the page is the brand mark. It goes to
/, the home page, which doesn't send a signed-in organizer on to their dashboard. - Organizers land here a lot. It's the link they copy and send: the share panel, the share message, and
links.publicfrom the AI connector tools and Magic Compose. Opening it again later is the natural way to check on a signup. - The cookie that's needed is already sent. The Auth.js session cookie (
authjs.session-token) has path/, so it already reaches/s/[slug]. The returning-participant cookie is the wrong one for this. It only says this browser signed up for a slot, not who made the signup.
To see it: sign in, publish a signup, then open its public link in the same browser. Nothing on the page leads to Responses or Build.
Fix, in outline
- Read the session once the signup has loaded. In
PublicSignupPage, afterloadPublicSignupsucceeds (open or closed), callgetOrganizerSession()fromsrc/auth/session.ts. Run it alongsidegetOwnCommitmentsForSignupwithPromise.all, so it adds no wait. - Check membership through the policy module. Use
workspaceRole(toActor(session), sig.workspaceId)fromsrc/lib/policy.ts. Any role counts. No session, no role, or a nullworkspaceIdmeans no bar. This checks data the page already has, so open and closed signups need no new service read. - Show an organizer bar at the top of the page, above the signed-up bar and the title. It says this is their signup and has two links: "See responses" to
/app/signups/[id]/responsesand "Edit signup" to/app/signups/[id]/build. The wording is under "Choices this makes". - Render it on the server.
SignupViewis a server component. Give it an optional prop carrying the signup id, used inlivemode only. The bar is plain links, so/s/[slug]'s first-load JavaScript shouldn't grow. - Reuse the signed-up bar's look. The signed-up bar in
SignupViewBodyis already a line of text with a link, on this page. Move its outerdivinto a small shared component and use it for both bars, rather than adding a third style (CLAUDE.md: reuse banners).
Watch for
- This reverses one rule in #583. #583 says an open or closed signup's page "must not call
auth()", and its "Done when" checks that "an open signup's page reads no session". Its reason is that this is the participants' hot path. Participants still pay nothing: with no session cookie, Auth.js returns before it touches the database (session()in@auth/core'slib/actions/session.js:if (!sessionToken) return response). Only a signed-in organizer pays, about 2 more statements (the session lookup andloadOrganizerSessionById). If #583 lands first, remove its "reads no session" check in this change. If this lands first, #583's draft branch can reuse the session read. Whichever lands second has the merge. - Query budget.
GET /s/[slug]inbudgets.jsonis 5 and must stay 5.src/app/query-budget.db.test.tsruns that case with no session cookie. Add a second case signed in as the signup's organizer, with its own budget entry, so the organizer's cost is pinned too. - Participants are not users. Nothing a participant does changes, and the organizer keeps the same Sign up buttons. An organizer who also signed up for a slot sees both bars.
- Keep the id private. Render the bar and its links only for a member. Don't add the id or the membership check to
getPublicSignup's result or toGET /api/public/signups/[slug].toPublicSignupis an allow-list, and it should stay one. - Caching. The page already reads cookies and renders on every request. Check that
pnpm buildstill lists/s/[slug]as dynamic (ƒ). - e2e specs that open the public page while signed in.
loginAsSeededOrganizer(tests/e2e/helpers/auth.ts) signs in the whole browser context. Specs such asorganizer.spec.ts,responses.spec.tsanda11y.spec.tsthat open/s/[slug]in that context will now see the bar. Check their assertions still hold and the axe scan passes with the bar showing. The help walkthroughs open the public page in a freshbrowser.newPage(), so their screenshots stay participant-only. Check that's still true. - Help. No article says how to get from the public link to the responses.
create-and-publish-a-signupcould mention it. Run the help-pages skill'saffected-articles.mjsto check. - Legal pages. No new cookie, and nothing new is stored. The cookies page says the session cookie "keeps organizers signed in after they sign in", which is still true. The privacy and terms pages need no change.
- CHANGELOG entry under Unreleased › Added.
Choices this makes
- The words. "This is your signup. People who open the link see this page without this bar." Links: "See responses" and "Edit signup". Default: these words. They answer the organizer's question and make clear participants don't see the bar.
- Two links, not one. Default: both. Responses is what the organizer asked for, and Build is where they change the signup. A single link to
/app/signups/[id]would land on Build, one more step from the responses. - Who sees it: any member of the signup's workspace, viewers included. Default: any member, the same as #583. A viewer can open Responses.
- Which statuses: open and closed, where the page already has the signup's row. Default: open and closed. Draft is #583's job. An archived signup keeps its message with no link: the page doesn't load an archived row, so it would need #583's kind of guarded read, and an archived signup isn't being shared any more.
- Not signed in on this device: nothing shows. Default: no "Made this signup? Sign in" line for everyone, for the reason #583 gives: it puts organizer instructions in front of every participant.
- Telemetry.
recordPublicViewstill writes the organizer's own visit as asignup.viewedsystem row. Default: leave it. Skipping or tagging members' visits changes what the views query indocs/telemetry.mdcounts, so it can follow as its own issue. - Placement: at the top of the page, not fixed to the bottom. Default: the top. It's the first thing seen on a phone, and a fixed bar would cover the slots.
Done when
- A signed-in member of the signup's workspace who opens an open or closed signup's public link sees the bar, and its links go to the Responses and Build tabs.
- A signed-out visitor, and a signed-in organizer from another workspace, see the page exactly as today, with no bar.
GET /s/[slug]'s budget stays at 5 for a visitor with no session cookie, and a new budget case pins the count for a signed-in organizer.- Tests show the bar for a member and not for a non-member or a signed-out visitor: a
SignupViewcomponent test, and an e2e check with and withoutloginAsSeededOrganizer. pnpm build && pnpm budgetspass with/s/[slug]'s first-load JS budget unchanged.pnpm lint && pnpm typecheck && pnpm knip && pnpm testandpnpm test:dbpass.
From an organizer's question, passed on by the owner: on their live signup's page, they asked where to see the responses. Checked against the code on main at 7950b54, and against @auth/core 0.41.3's session action for what happens with no session cookie. https://claude.ai/code/session_013hhheErU4qtihAPTY6BjWA
- 主要言語
- TypeScript
- スター
- 19
- フォーク
- 4
- 平均マージ
- 20時間 9分
- マージ済み PR(30日)
- 156
環境構築
- Dockerfile または Docker Compose ファイルあり
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
richshaw/OpenSignup のほかの issue
-
enhancement pipeline:proposed pipeline:ux
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
richshaw/OpenSignup#654 ·
メンテナーはふだん 1 日以内に返信
-
enhancement pipeline:proposed pipeline:ux
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
richshaw/OpenSignup#653 ·
メンテナーはふだん 1 日以内に返信
-
enhancement pipeline:proposed pipeline:ux
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
richshaw/OpenSignup#652 ·
メンテナーはふだん 1 日以内に返信
-
enhancement good first issue pipeline:ready
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
richshaw/OpenSignup#645 ·
メンテナーはふだん 1 日以内に返信
-
bug good first issue pipeline:ready pipeline:ux
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
richshaw/OpenSignup#644 ·
メンテナーはふだん 1 日以内に返信
richshaw/OpenSignup の issue をすべて見る
似ている issue
-
type: bug
難易度 2/5 1〜3時間 初心者へのやさしさ 79/100
メンテナーはふだん 1 日以内に返信
-
0️⃣ phase/new
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
-
難易度 1/5 1時間未満 初心者へのやさしさ 70/100
microsoft/playwright#43640 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100