Conversation
…tions Extract 4 @internal export functions from pollAutoYes() (~139 lines) to improve testability and SRP compliance: - validatePollingContext(): Pre-condition checks - captureAndCleanOutput(): tmux output capture + ANSI cleanup - processStopConditionDelta(): Stop condition delta-based check - detectAndRespondToPrompt(): Prompt detection + auto-response Also add getPollerState() internal helper for consistency with existing getAutoYesState() accessor pattern. pollAutoYes() is now a ~30-line orchestrator. No functional changes - all 82 existing tests pass unchanged. 20 new timer-independent unit tests added (102 total). Refs #323 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace 'manual' as 'expired' type cast with direct 'expired' value in validatePollingContext test. The original cast was misleading since AutoYesStopReason only accepts 'expired' | 'stop_pattern_matched'. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Issue #323 (pollAutoYes() refactoring) の pm-auto-issue2dev 全工程の 成果物を追加。Issueレビュー(8段階)→設計方針書→設計レビュー(4段階) →作業計画→TDD自動開発のレポートファイル一式。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
refactor(auto-yes-manager): decompose pollAutoYes() into single-responsibility functions
- Add src/lib/auth.ts core module (generateToken, hashToken, verifyToken with timingSafeEqual, parseDuration, parseCookies, createRateLimiter) - Add src/middleware.ts for Next.js request authentication - Add auth API routes (login, logout, status) - Add login page with i18n, rate limit display, and redirect logic - Add WebSocket authentication via Cookie header in ws-server.ts - Add HTTPS support in server.ts with certificate validation - Add CLI options: --auth, --auth-expire, --cert, --key, --allow-http - Add LogoutButton component in sidebar (desktop + mobile drawer) - Add auth i18n namespace (en/ja) - Update .env.example with auth/HTTPS documentation - All 89 new tests pass (unit + integration) - All 3724 existing unit tests pass Resolves #331 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Apply DRY, readability, and maintainability improvements to Issue #331 code: - Extract buildAuthCookieOptions() to centralize cookie security settings (login/logout DRY) - Extract isHttpsEnabled() helper for CM_HTTPS_CERT environment check - Extract DEFAULT_COOKIE_MAX_AGE_SECONDS constant (remove magic number 86400) - Extract MS_PER_MINUTE/MS_PER_HOUR/MS_PER_DAY time constants (eliminate magic numbers) - Replace switch-case in parseDuration() with data-driven unitMultipliers lookup - Simplify rate limiter cleanup condition (remove redundant null check) - Remove dead code (empty if-body) in daemon.ts auth env forwarding - Add 'as const' to authEnvKeys array in daemon.ts for type narrowing - Extract displayAuthToken() in start.ts (remove duplicated token display logic) - Extract isExpectedWebSocketError() in ws-server.ts (remove duplicated error patterns) - Add JSDoc to getClientIp(), displayAuthToken(), isExpectedWebSocketError() - Add AuthCookieOptions interface with C001 constraint documentation Security constraints maintained: - S001: crypto.timingSafeEqual() for token verification - S002: AUTH_EXCLUDED_PATHS exact match (===) - C001: No Next.js module dependencies in auth.ts Quality: tsc 0 errors, ESLint 0 errors, 3724/3724 tests pass Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Quick Start section for token auth + HTTPS to security-guide.md - Add mkcert certificate generation instructions for macOS and Linux - Add Linux CA certificate distribution procedures - Update Security Checklist with built-in auth options - Update Migration from CM_AUTH_TOKEN section (--auth warning note) - Add src/lib/auth.ts and src/middleware.ts to CLAUDE.md module list Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add design policy: issue-331-token-auth-design-policy.md - Add multi-stage design review reports (stage1-4) - Add multi-stage issue review reports - Add work plan: work-plan.md - Add pm-auto-dev iteration-1 reports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat(auth): トークン認証・HTTPS対応 #331
middleware.ts imported auth.ts which uses Node.js crypto.timingSafeEqual, causing ENVIRONMENT_FALLBACK errors since Next.js middleware runs in Edge Runtime. Changes: - Remove auth.ts import from middleware.ts - Inline Edge Runtime compatible token verification using Web Crypto API (crypto.subtle.digest for SHA-256, XOR loop for constant-time comparison) - Make middleware function async for Web Crypto API support - Update auth-middleware.test.ts to await async middleware calls Security maintained: - S001: XOR over fixed-length SHA-256 hex is equivalent to timingSafeEqual - S002: AUTH_EXCLUDED_PATHS exact match preserved Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
next-intl v4 throws ENVIRONMENT_FALLBACK during SSR of client components when timeZone is not set in NextIntlClientProvider. The root cause is that v4 validates the SSR environment by checking for timeZone on the server side. Fix: propagate timeZone through i18n.ts -> layout.tsx -> AppProviders.tsx so that useTranslations() in LogoutButton and other client components works correctly during server-side rendering. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously, LogoutButton fetched /api/auth/status on every mount, causing a visible layout shift (null -> button) that made the UI flicker. Fix: pass authEnabled from layout.tsx (server component reads CM_AUTH_TOKEN_HASH at SSR time) through AuthContext to LogoutButton. The button now renders correctly on first paint with no client-side fetch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…c status fetch Remove checkingAuth state and HEAD / request from login page. Auth status is now read synchronously from AuthContext (set server-side in layout.tsx), so the form renders immediately without a Loading... intermediate state. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On Node.js 19+, WebSocket upgrade requests can trigger the 'request' event (and middleware) even when an 'upgrade' listener is registered, causing TypeError in Next.js handleRequestImpl because the response object for upgrade requests lacks setHeader. Three-layer fix (Issue #331): - server.ts: early return for WebSocket upgrade in requestHandler - src/middleware.ts: early NextResponse.next() for upgrade requests; matcher updated to exclude all _next/ paths (not just static/image) - src/lib/ws-server.ts: properly close /_next/ sockets in production instead of leaving them unhandled (which triggers the fallback) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bug 1: /api/auth/status always returned authEnabled:false - Add `export const dynamic = 'force-dynamic'` to auth/status route - CM_AUTH_TOKEN_HASH is set at runtime, so static caching caused isAuthEnabled() to always evaluate with the build-time env (undefined) Bug 2: TypeError: Cannot read properties of undefined (reading 'bind') - Root cause: next() creates NextCustomServer which lazily calls setupWebSocketHandler() on the first HTTP request, registering its own 'upgrade' listener that passes the raw TCP socket as the HTTP response object, causing handleRequestImpl to fail at _res.setHeader.bind(_res) - Fix: make setupWebSocketHandler a no-op after next() call so Next.js never registers its upgrade listener; all WebSocket upgrades are handled exclusively by ws-server.ts - Add defense-in-depth guard: skip requestHandler if res has no setHeader - Forward auth env vars (CM_AUTH_TOKEN_HASH etc.) to daemon process via process.env so start --daemon passes them to the child Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… docs Extract AUTH_COOKIE_NAME and AUTH_EXCLUDED_PATHS from auth.ts/middleware.ts into a shared Edge Runtime-compatible module (src/config/auth-config.ts) to eliminate DRY violation. Add Issue #331 entry to implementation-history docs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- C1: Add token expiry check to middleware.ts (via shared computeExpireAt) - H1: Verify auth cookie on WebSocket upgrade requests in middleware - H2: Replace X-Forwarded-For-based rate limiting with global key to prevent IP spoofing bypass - H3: Pass hostname to server.listen() so CM_BIND is respected; add server 'error' event handler for EADDRINUSE - M1: Validate CM_AUTH_TOKEN_HASH is 64-char hex at startup - M3: Add 256-char token length limit on login endpoint - L1: Add Content-Length/Connection headers to WebSocket 401 response - Consolidate parseDuration/computeExpireAt into auth-config.ts (DRY) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix isAuthEnabled() inconsistency: use storedTokenHash instead of raw env var, preventing auth-enabled-but-login-impossible state when CM_AUTH_TOKEN_HASH is malformed (#2 Medium) - Add isValidTokenHash() type predicate to auth-config.ts for shared validation across auth.ts and middleware.ts - Fix CLI HTTPS protocol display: align with server.ts logic so --cert --key always shows https:// URL (#3 Medium) - Add --cert/--key mutual requirement validation (#3 Medium) - Fix auth-middleware test mocks: add headers.get() mock and WebSocket upgrade auth test cases (#4 Low) - Document global rate limit trade-off in login route (#1 High) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat(auth): add token authentication and HTTPS support (#331)
- Add 'skill' to SlashCommandCategory and SlashCommandSource types - Implement loadSkills() to read SKILL.md frontmatter (name, description) - Add safeParseFrontmatter() to disable gray-matter JS engine (S001) - Implement deduplicateByName() with command priority over skills - Add skillsCache independent from commandsCache, cleared together - Add 'skill' to CATEGORY_ORDER between workflow and standard-session - Update API route to include skill count in sources response - Add comprehensive tests (31 unit + 19 command-merger + 3 integration) - Coverage: slash-commands.ts 93%, command-merger.ts 93%, route.ts 84% Resolves #343 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add documentation comments to improve code maintainability for Issue #343: - filterCommands(): note that it only searches commandsCache, not skills - loadSlashCommands(): document dual commandsCache assignment pattern - loadSkills(): explain async declaration rationale (consistency) - parseSkillFile(): [D009] clarify cliTools vs allowed-tools distinction - route.ts: TODO for SlashCommandsResponse type unification with api-client.ts No logic changes. All tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…orts - Add slash-commands module entries to CLAUDE.md - Add Issue #343 to implementation-history.md - Add design policy, issue review, design review, and pm-auto-dev reports Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: スラッシュコマンドセレクターで .claude/skills も表示する (#343)
…frontmatter SKILL.md files with unquoted YAML special characters (colons, brackets) in fields like argument-hint cause gray-matter's js-yaml parser to throw YAMLException, silently dropping those skills. Add extractFrontmatterFields() as a regex-based fallback to extract name and description when full YAML parsing fails. Fixes skills like release and release-post not appearing in the slash command selector. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix(#343): add regex fallback for YAML-unfriendly SKILL.md frontmatter
…cess - Add src/lib/ip-restriction.ts with Edge Runtime compatible CIDR matching - Inject X-Real-IP header in server.ts for trusted IP identification - Add IP restriction check in middleware.ts (Step 1, before auth) - Add IP restriction check in ws-server.ts (defense-in-depth) - Extend CLI with --allowed-ips and --trust-proxy options - Add daemon.ts authEnvKeys for CM_ALLOWED_IPS/CM_TRUST_PROXY - Add 45 unit tests and 6 integration tests for IP restriction - All static analysis checks passed (tsc, ESLint) Resolves #332 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…le.log Reorganize ip-restriction.ts module-scope initialization before dependent functions for better readability. Enhance JSDoc with S4-001 future extension notes and S4-002/S4-005 rationale. Remove console.log statements from ws-server.ts per CLAUDE.md production rules. Fix daemon.ts REVERSE_PROXY_WARNING to account for CM_ALLOWED_IPS (consistent with start.ts). Improvements: - ip-restriction.ts: module-scope vars moved before getClientIp() that references them - ip-restriction.ts: enhanced JSDoc for S1-004, S4-001, S4-002, S4-005, S4-006 - ws-server.ts: removed 8 console.log calls, kept console.warn/error for security/errors - daemon.ts: added CM_ALLOWED_IPS check to suppress REVERSE_PROXY_WARNING Quality Metrics: - TypeScript errors: 0 - ESLint errors: 0 - Unit tests: 3796 passed (185 files) - Integration auth-middleware tests: 17 passed Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…orts - Add ip-restriction.ts entry to CLAUDE.md module list - Add Issue #332 to docs/implementation-history.md - Add design policy, issue review, design review, and TDD reports Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Detect auth redirect (307 → /login) in fetchApi and throw ApiError(401) - Check content-type before parsing response as JSON - Stop WorktreeSelectionContext polling on 401 errors to prevent console spam on login page - Update test mocks to use importOriginal pattern for ApiError export Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat(#332): アクセス元IP制限オプションの追加
fix(auth): handle auth redirects and stop polling on 401
…rors Values containing colons, parentheses, and long strings caused gray-matter YAML parsing failures during build. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
pollAutoYes()を責務ごとの関数群に分割するリファクタリング.claude/skills/ディレクトリのスキルをスラッシュコマンドセレクターに表示Changes
Test plan
npm run lintパス確認npx tsc --noEmit型チェックパス確認npm run test:unitユニットテストパス確認npm run buildビルド成功確認/入力時にスキルがセレクターに表示されることを確認🤖 Generated with Claude Code