Skip to content

Feature/atcoder verified voting#3319

Merged
KATO-Hiro merged 27 commits into
stagingfrom
feature/atcoder-verified-voting
Mar 29, 2026
Merged

Feature/atcoder verified voting#3319
KATO-Hiro merged 27 commits into
stagingfrom
feature/atcoder-verified-voting

Conversation

@river0525
Copy link
Copy Markdown
Collaborator

@river0525 river0525 commented Mar 27, 2026

認証機能を分離したPRです。
サーバーの用意後、マージいたします。

Summary by CodeRabbit

  • 新機能

    • 投票UIはAtCoder認証済みユーザー向けに制御され、未認証時はプロフィール編集への案内を表示します
    • ユーザー設定にAtCoder認証管理UIを復活・改善(検証コードのコピー/入力や検証状態表示)
  • 表示・動作

    • 課題一覧や投票ページで認証状態に応じた表示・操作が反映されます
    • 編集ページのAtCoderタブ自動表示制御を追加
  • ドキュメント

    • Svelte/SvelteKit、テスト(E2E/ユニット)ガイドラインを更新
  • その他

    • サイトマップの除外ルールと環境ファイルの注記を更新しました

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 27, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

AtCoder認証フラグをサーバーからページへ渡し、コンポーネントのプロップを flat から atCoderAccount に統一。投票アクションに未認証ガードを追加し、未認証ユーザー向けのUI誘導を導入した。

Changes

Cohort / File(s) Summary
AtCoder 検証フォーム(高注意)
src/features/account/components/settings/AtCoderVerificationForm.svelte
プロップを個別フィールドから atCoderAccount { handle, validationCode, isValidated } に統一。内部で statuseditableHandle を導出。フォーム送信フィールド名を handle/validationCode に変更し、いくつかの hidden 入力を双方向バインドから一方通行の value に切替。動作・送信データの確認必須。
プロフィール編集ページ(高注意)
src/routes/users/edit/+page.server.ts, src/routes/users/edit/+page.svelte
サーバー側で form 解析・認可チェックを共通化し、load() の返却形状を flat → ネストした atCoderAccount に変更。クライアント側は $derived(data.atCoderAccount)shouldOpenAtCoderTab を導入してタブ開閉ロジックを変更。データ形状整合性とタブ動作確認必須。
投票アクション認可(高注意)
src/features/votes/actions/vote_actions.ts
voteAbsoluteGradelocals.user?.is_validated チェックを追加。未認証時は fail(FORBIDDEN, ...) を返す経路が追加。既存の投票フローとテストへの影響確認必須。
投票 UI / グレードコンポーネント(中〜高)
src/features/votes/components/VotableGrade.svelte, src/routes/votes/[slug]/+page.svelte
isAtCoderVerified prop を導入(optional)。未認証ユーザーでは投票ドロップダウンを抑止し、EDIT_PROFILE_PAGE + ?tab=atcoder への誘導リンクを表示する分岐を追加。表示とリンク先の確認推奨。
タスク一覧への伝播(中)
src/features/tasks/components/contest-table/TaskTable.svelte, src/features/tasks/components/contest-table/TaskTableBodyCell.svelte
isAtCoderVerified: boolean を親から子へ追加伝播。各セルで VotableGrade に渡す引数が増加。テーブルレンダリング確認推奨。
ページロードでのフラグ追加(中)
src/routes/problems/+page.server.ts, src/routes/votes/[slug]/+page.server.ts, src/routes/problems/+page.svelte
load() の返却に isAtCoderVerified = locals.user?.is_validated === true を追加。ページ側で $derived(data.isAtCoderVerified) を使用するよう変更。
プロフィール定数追加(低)
src/lib/constants/navbar-links.ts
EDIT_PROFILE_PAGE = '/users/edit' を追加。
Sitemap除外(低)
src/routes/sitemap.xml/+server.ts
サイトマップの除外パターンに '/votes/\\[slug\\]' を追加。
E2E / テスト修正(中)
e2e/*, .claude/rules/testing-e2e.md, .claude/rules/testing.md
Playwright テストでコンテナスコープ化、条件付きスキップ追加、Tailwind メディアクエリ期待値修正。E2E ルール文書を追加/再編。テスト安定性確認推奨。
ドキュメント(info)
.claude/rules/svelte-components.md, .claude/rules/sveltekit.md, .claude/rules/testing-e2e.md, .claude/rules/testing.md
Svelte/SvelteKit のプロップ設計ルールや E2E テストガイドを追加/再編(情報のみ)。
.env 例更新(info)
.env.example
CONFIRM_API_URL のコメント文を具体化(値は変更なし)。

Sequence Diagram(s)

sequenceDiagram
  participant Browser as Browser
  participant PageServer as PageServer (load/actions)
  participant App as Svelte Components
  participant DB as Database

  rect rgba(200,200,255,0.5)
  Browser->>PageServer: GET /votes/[slug] (セッション)
  PageServer->>DB: セッション/ユーザ検索
  DB-->>PageServer: user { is_validated }
  PageServer-->>Browser: page data { ..., isAtCoderVerified }
  end

  rect rgba(200,255,200,0.5)
  Browser->>App: レンダリング(data を受け渡し)
  App->>App: $derived(data.isAtCoderVerified)
  App-->>Browser: 投票 UI を表示(許可 or 誘導)
  end

  rect rgba(255,200,200,0.5)
  Browser->>PageServer: POST /vote action
  PageServer->>DB: check session.user.is_validated
  alt not validated
    PageServer-->>Browser: fail(FORBIDDEN)
  else validated
    PageServer->>DB: 投票記録
    PageServer-->>Browser: success
  end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

✨ プロップは束ねられ、旗は真偽を告げる、
コンポーネントは導出で踊り、タブは条件で開く、
投票の門番は検証を尋ね、道を案内するリンクが差す、
テストは狭く狙い、サイトはページを選ぶ、
小さな変更で流れは静かに整う。

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR タイトルは AtCoder 認証検証投票機能の実装という主要な変更内容を明確に表現している。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/atcoder-verified-voting

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

認証(AtCoderアカウント検証)を投票機能から独立させつつ、未認証ユーザーの投票をUI/サーバー両面で制限する変更です。投票導線からプロフィール編集(AtCoder認証タブ)へ誘導できるようにしています。

Changes:

  • 投票(詳細ページ/一覧のドロップダウン投票)を「ログイン + AtCoder認証済み」に制限
  • 未認証ユーザー向けに /users/edit?tab=atcoder への誘導UIを追加
  • ユーザー編集画面でAtCoder認証タブを復帰し、?tab=atcoder で初期表示タブを切替

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/routes/votes/[slug]/+page.svelte 未認証ログインユーザーへ認証誘導UIを追加
src/routes/votes/[slug]/+page.server.ts loadに isAtCoderVerified を追加
src/routes/users/edit/+page.svelte AtCoder認証タブ復帰、?tab=atcoder と form 結果でタブ自動オープン
src/routes/users/edit/+page.server.ts tab=atcoder をloadへ反映
src/routes/problems/+page.svelte TaskTableへ isAtCoderVerified を伝播
src/routes/problems/+page.server.ts loadに isAtCoderVerified を追加
src/lib/constants/navbar-links.ts EDIT_PROFILE_PAGE を追加
src/lib/components/AtCoderUserValidationForm.svelte バインド/状態管理を見直し、入力をローカルstate化
src/features/votes/components/VotableGrade.svelte 未認証時の投票UIを誘導に切替、isAtCoderVerified を追加
src/features/votes/actions/vote_actions.ts サーバー側で未認証投票を403で拒否
src/features/tasks/components/contest-table/TaskTableBodyCell.svelte isAtCoderVerified を VotableGradeへ伝播
src/features/tasks/components/contest-table/TaskTable.svelte isAtCoderVerified を子へ伝播

Comment on lines +121 to +132
{:else if data.isLoggedIn && !data.isAtCoderVerified}
<!-- ログイン済み・未認証 → 認証誘導 -->
<div
class="bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-700 rounded-lg p-4 mb-4"
>
<p class="text-yellow-800 dark:text-yellow-200 font-medium mb-2">
投票するにはAtCoderアカウントの認証が必要です。
</p>
<Button href={editProfileHref} color="yellow" size="sm">AtCoderアカウントを認証する</Button>
</div>
{:else if data.isLoggedIn}
<!-- 未投票・ログイン済み → 投票フォーム -->
<!-- 未投票・ログイン済み・認証済み → 投票フォーム -->
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new “logged in but unverified” branch only applies when data.myVote?.voted is false. If a user voted previously and later resets AtCoder verification, they will still hit the data.myVote?.voted branch and see the “投票を変更する” form, but the server action now rejects unverified users (403). Consider also gating the vote-change UI in the voted branch on data.isAtCoderVerified (or showing the same verification prompt there) to avoid a broken flow.

Copilot uses AI. Check for mistakes.

// Editable only in 'nothing' step; server is authoritative after each action.
// untrack: prop is the initial seed only — intentional one-time capture.
let editableAtcoderId = $state(untrack(() => atcoder_username));

Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

editableAtcoderId is seeded once from atcoder_username and never re-synced. After a successful reset (server clears atcoder_username and status becomes nothing), the input will still show the old AtCoder ID, diverging from server-authoritative state. Consider syncing editableAtcoderId when status becomes nothing (or when atcoder_username changes to an empty string) while still avoiding overwriting during user edits.

Suggested change
// Keep editableAtcoderId in sync with server after a reset:
// when the server clears atcoder_username and status returns to 'nothing',
// reset the local editable value as well.
$effect(() => {
if (status === 'nothing' && atcoder_username === '') {
editableAtcoderId = '';
}
});

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +35
if (!locals.user?.is_validated) {
return fail(FORBIDDEN, {
message: 'AtCoderアカウントの認証が必要です。',
});
}
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The verification check conflates “user is not AtCoder-verified” with “locals.user is missing”. Since locals.user is populated in hooks.server.ts by looking up the DB user, a deleted/missing user could yield locals.user === undefined even when session is valid; returning 403 with an AtCoder-verification message would be misleading. Consider explicitly handling !locals.user (e.g., treat it as UNAUTHORIZED/INTERNAL_SERVER_ERROR) and only return FORBIDDEN when the user exists but is_validated is false.

Copilot uses AI. Check for mistakes.
Base automatically changed from feature/absolute_evaluation_voting to staging March 27, 2026 13:50
KATO-Hiro

This comment was marked as outdated.

KATO-Hiro and others added 14 commits March 29, 2026 06:19
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ting

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eliminates 4 identical username-read + requireSelf blocks across
generate/validate/reset/delete actions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/routes/problems/`+page.svelte:
- Line 27: Replace the plain assignments from the load() store with derived
stores so they update when data reloads: import { derived } from 'svelte/store'
and change the variables isAdmin, isLoggedIn, isAtCoderVerified, and voteResults
to derived(data, d => d.isAdmin), derived(data, d => d.isLoggedIn),
derived(data, d => d.isAtCoderVerified), and derived(data, d => d.voteResults)
respectively (leave taskResults as-is since it is already derived); reference
the top-level store named data and the variable names isAdmin, isLoggedIn,
isAtCoderVerified, voteResults, and taskResults when making the edits.

In `@src/routes/users/edit/`+page.svelte:
- Around line 27-30: The page currently only reads data.* for alerts so action
results (validate/reset/delete) that return message_type/message are ignored;
update the component to prefer the action result contained in the server form
payload (use the existing let { data, form }: Props = $props() and render
form?.message_type / form?.message when present), fall back to data.* only if
form is null/empty, and move the tab open/close logic into a shared util (e.g.,
a new helper in utils/ that takes the action result or form and returns which
tab should be active) so the component only renders based on that util and
contains no business logic in its <script> block. Ensure the server action names
validate/reset/delete are used as keys when reading form to keep behavior
consistent with +page.server.ts.

In `@src/routes/votes/`[slug]/+page.svelte:
- Around line 121-133: The branch order allows data.myVote?.voted to render the
vote-change form before checking AtCoder verification, so move the
isAtCoderVerified check earlier: ensure the {:else if data.isLoggedIn &&
!data.isAtCoderVerified} branch appears before any branch that evaluates
data.myVote?.voted (and keep the {:else if data.isLoggedIn} branch for the
voting form after the verification check). Update the Svelte conditionals so
data.isAtCoderVerified is required before rendering the data.myVote?.voted form
(adjust the blocks that reference data.myVote?.voted, data.isLoggedIn, and
data.isAtCoderVerified accordingly).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d8d87cb3-4865-4d92-8e66-44840e31ed6c

📥 Commits

Reviewing files that changed from the base of the PR and between 8757704 and eef8613.

📒 Files selected for processing (14)
  • .claude/rules/svelte-components.md
  • .claude/rules/sveltekit.md
  • src/features/account/components/settings/AtCoderVerificationForm.svelte
  • src/features/tasks/components/contest-table/TaskTable.svelte
  • src/features/tasks/components/contest-table/TaskTableBodyCell.svelte
  • src/features/votes/actions/vote_actions.ts
  • src/features/votes/components/VotableGrade.svelte
  • src/lib/constants/navbar-links.ts
  • src/routes/problems/+page.server.ts
  • src/routes/problems/+page.svelte
  • src/routes/users/edit/+page.server.ts
  • src/routes/users/edit/+page.svelte
  • src/routes/votes/[slug]/+page.server.ts
  • src/routes/votes/[slug]/+page.svelte

Comment thread src/routes/problems/+page.svelte Outdated
Comment on lines +27 to +30
form: Record<string, unknown> | null;
}

let { data }: Props = $props();
// TODO: Restore when AtCoderUserValidationForm is re-enabled (svelte/valid-prop-names-in-kit-pages requires $bindable props to be declared in Props):
// interface Props { ...; status?: string; }
// let { data, status = $bindable('nothing') }: Props = $props();
// let status = $state('nothing');
let { data, form }: Props = $props();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

action の返却メッセージが画面に出ません

src/routes/users/edit/+page.server.tsvalidate / reset / deletemessage_type / message を action result で返していますが、このページは alert 用に data.* しか参照していません。load() は空文字を返しているので、本人確認失敗やリセット成功が無通知になります。form はタブ判定だけでなく表示メッセージにも使ってください。あわせて、タブ開閉判定は action 結果と密結合なので、utils/ 側へ寄せた方が分岐を揃えやすいです。

差分案
   let role = data.role;
   let username = data.username;
-  let message = data.message;
-  let message_type = data.message_type;
+  let message = $derived(typeof form?.message === 'string' ? form.message : data.message);
+  let message_type = $derived(
+    typeof form?.message_type === 'string' ? form.message_type : data.message_type,
+  );

As per coding guidelines, "Business logic belongs in utils/, not inside <script> blocks."

Also applies to: 32-35, 39-48

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/routes/users/edit/`+page.svelte around lines 27 - 30, The page currently
only reads data.* for alerts so action results (validate/reset/delete) that
return message_type/message are ignored; update the component to prefer the
action result contained in the server form payload (use the existing let { data,
form }: Props = $props() and render form?.message_type / form?.message when
present), fall back to data.* only if form is null/empty, and move the tab
open/close logic into a shared util (e.g., a new helper in utils/ that takes the
action result or form and returns which tab should be active) so the component
only renders based on that util and contains no business logic in its <script>
block. Ensure the server action names validate/reset/delete are used as keys
when reading form to keep behavior consistent with +page.server.ts.

Comment thread src/routes/votes/[slug]/+page.svelte
Clarify that the URL is for the NoviSteps organization crawler.
See team documentation for the actual endpoint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.env.example:
- Around line 1-2: Restore the real AtCoder affiliation confirmation API URL
into the placeholder in .env.example (replace the placeholder comment with the
actual URL string value for the environment variable used by the crawler), and
update the accompanying comment to point to a specific team document or path
where the URL is documented; if the real URL is sensitive and appears in git
history, consider removing it from history or rotating credentials before
committing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4c32874f-1df2-46ec-a7cb-38a72d43f84b

📥 Commits

Reviewing files that changed from the base of the PR and between 5af3d3b and 5c3515d.

📒 Files selected for processing (1)
  • .env.example

Comment thread .env.example
@river0525 river0525 force-pushed the feature/atcoder-verified-voting branch from 5c3515d to b8fd4ff Compare March 29, 2026 15:09
- +page.server.ts: wrap service calls in try/catch; return fail(500) on error
- +page.server.ts: rename is_tab_atcoder -> isTabAtcoder (camelCase consistency)
- +page.server.ts: import INTERNAL_SERVER_ERROR constant
- +page.svelte (users/edit): use $derived for role/username/message/message_type
- +page.svelte (users/edit): update form?.isTabAtcoder reference
- problems/+page.svelte: use $derived for isAdmin/isLoggedIn/isAtCoderVerified/voteResults
- votes/[slug]/+page.svelte: remove @ts-expect-error; append ?tab=atcoder after resolve()
- e2e/votes.spec.ts: wait for vote form or unverified message before isVisible() check
- AtCoderVerificationForm.svelte: consolidate imports at top of script block
- .claude/rules/sveltekit.md: soften "never" to "typically" for undefined handling
- .claude/rules/testing-e2e.md: allow type-only imports; add multi-test parameterized pattern
- .claude/rules/testing.md: clarify "basic conditionals" with examples

Skip: locals.user?.is_validated is correct — session.user type does not include is_validated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- +page.server.ts: rename is_validated -> isValidated (camelCase consistency)
- e2e/votes.spec.ts: reuse voteForm locator variable instead of redefining
- e2e/custom_colors.spec.ts: make xs breakpoint regex flexible for spaces around >=
- .claude/rules/testing-e2e.md: "URL string values" -> "string constant values";
  fix gradeButton(grade) -> gradeButton(page, grade) for consistent signature
- .claude/rules/testing.md: raise branch coverage target to 80%; clarify
  "real side effects" definition; require unit tests by default for components

Skip: locals.user?.is_validated changes (session.user type lacks is_validated;
locals.user is the correct authoritative source for AtCoder verification status)
Skip: problems/+page.svelte $derived removal (contradicts project rule and round 1 fix)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@e2e/votes.spec.ts`:
- Around line 159-162: The test "non-admin user is redirected to /" expects the
wrong URL; since validateAdminAccess redirects non-admins to /login, update the
test in votes.spec.ts (the test using loginAsUser and VOTE_MANAGEMENT_URL) to
assert page navigates to '/login' (use the same TIMEOUT constant and page
helpers) OR alternatively change validateAdminAccess to redirect to '/' so
behavior matches the test—pick one approach and make the expectation and the
validateAdminAccess redirect consistent.

In `@src/routes/users/edit/`+page.server.ts:
- Around line 85-96: Rename the snake_case variable is_validated to camelCase
isValidated throughout the handler that calls verificationService.validate
(replace const { username } = parsed; const is_validated = await
verificationService.validate(username); and all subsequent uses in the returned
object) so naming matches other variables like
validationCode/formData/isTabAtcoder; update the returned property names
(success, message_type, message) to reference isValidated instead of
is_validated and preserve the same boolean logic and messages.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: f7b0a9ce-9fa8-4e2d-928a-162e2ce7d427

📥 Commits

Reviewing files that changed from the base of the PR and between 5c3515d and 31c501a.

📒 Files selected for processing (10)
  • .claude/rules/sveltekit.md
  • .claude/rules/testing-e2e.md
  • .claude/rules/testing.md
  • .env.example
  • e2e/votes.spec.ts
  • src/features/account/components/settings/AtCoderVerificationForm.svelte
  • src/routes/problems/+page.svelte
  • src/routes/users/edit/+page.server.ts
  • src/routes/users/edit/+page.svelte
  • src/routes/votes/[slug]/+page.svelte

Comment thread e2e/votes.spec.ts
Comment thread src/routes/users/edit/+page.server.ts
- VotableGrade.svelte: remove @ts-expect-error; append ?tab=atcoder after resolve()
- e2e/votes.spec.ts: add clarifying comment on intentional voteForm visibility check
- .claude/rules/testing.md: rename cleanup subsection to "Integration Tests and Tests
  with Real Side Effects"; add note that it does not apply to Prisma-mock unit tests

Skip: locals.user?.is_validated -> session.user (session.user type lacks is_validated)
Skip: sitemap.xml /votes/[slug] exclusion (defensive pattern, not harmful)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@KATO-Hiro KATO-Hiro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@river0525
修正していただき、ありがとうございます。
マージします。

@KATO-Hiro KATO-Hiro merged commit c1b4620 into staging Mar 29, 2026
3 checks passed
@KATO-Hiro KATO-Hiro deleted the feature/atcoder-verified-voting branch March 29, 2026 22:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants