Commit Graph

64 Commits

Author SHA1 Message Date
posimai 4f6be0a21e fix(together): アーカイブSQL構文エラー修正(JS側でホスト名判定に変更) 2026-04-22 12:54:58 +09:00
posimai 5d1b6dfb2b fix(together): CASE文の型キャスト修正でアーカイブSQL修復 2026-04-22 12:54:24 +09:00
posimai 7446568adf fix(together): x.com などドメイン名タイトルをJina取得タイトルで上書き 2026-04-22 10:21:00 +09:00
posimai 324d892b28 fix(together): x.com ボット拒否検出・Gemini JSONコードブロック除去 2026-04-22 10:08:18 +09:00
posimai 9f0bb8eae7 fix(together): x.com 埋め込みURLのトラッキングパラメータを除去してJina取得精度改善 2026-04-22 10:04:24 +09:00
posimai b20393b8a9 fix(together): メンバー認証済みユーザーに invite_code を返すよう修正 2026-04-22 09:46:24 +09:00
posimai 4390748534 fix(together): JWT なし username 認証を復元(Posimai アカウント不要メンバー対応) 2026-04-22 09:37:11 +09:00
posimai 0d509461ac fix(together): legacy path 廃止(JWT必須化)・Gemini 2.5-flash 503 フォールバック追加 2026-04-22 09:02:11 +09:00
posimai b00e31cb90 feat(store): お問い合わせフォームを Resend API に切り替え(Formspree 廃止) 2026-04-21 19:52:53 +09:00
posimai 100064693d fix(together): JWT なしリクエストで invite_code を返さないよう修正 2026-04-21 19:40:55 +09:00
posimai 7210c8301c feat(together): AI要約の手動再試行エンドポイント追加(failed/skipped/summary欠落に対応) 2026-04-21 14:14:04 +09:00
posimai b2fce817bf fix(cors): PUT メソッドを許可(together/members/rename が CORS で弾かれていた) 2026-04-21 08:35:30 +09:00
posimai 4360f9090f fix(ai/generate): temperature クランプ・role バリデーション追加
- temperature を 0〜2 でクランプ(不正値でのSDKエラー防止)
- contents の role を user/model のみ許可(system injection 防止)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 06:52:46 +09:00
posimai cd4159fec9 feat(together): TOGETHER_GEMINI_API_KEY で Brain と Gemini quota を分離
TOGETHER_GEMINI_API_KEY が設定されている場合はそちらを使い、
未設定時は既存の GEMINI_API_KEY にフォールバック。
posimai-brain と posimai-together の quota が独立して管理できるようになる。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 22:51:31 +09:00
posimai e935eb6734 fix(together): 招待コードをメンバー全員に返す、JWT username 過剰チェック削除
af51a75で追加した「JWT なし時は invite_code を隠す」制限が原因で
グループ設定画面の招待コードが undefined になっていた。
メンバー確認済みなら全員に返すのが正しい動作。

create/join の「JWT username が一致しなければ 403」チェックも削除。
Together はニックネームベースで JWT identity と別名が普通に使われるため過剰な制限だった。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 22:47:36 +09:00
posimai 50e95577d7 fix(together): invite_code を JWT 必須に変更、Guard Web v1 方針を STATUS.md に明記 2026-04-20 22:31:07 +09:00
posimai ef7fccb255 fix(together): Gemini失敗時もJina成功ならarchive_status='done'にする
Gemini API 503 エラー時に全体を'failed'にしていたため、
Jina で本文取得済みの記事でもReaderボタンが表示されなかった。
Gemini だけ失敗した場合は summary=null/tags=[] で 'done' にし、
Readerは使える状態を保つ。既存の28件は DB で直接修正済み。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 21:17:07 +09:00
posimai af51a75244 fix(together): restore reader and AI metadata after mobile share
Allow Together endpoints to resolve username from JWT-backed candidates and return legacy-compatible feed/article fields so reader icon, summary, and category tags render without reload.

Made-with: Cursor
2026-04-20 20:49:09 +09:00
posimai 1e9e19b4b6 feat(posimai-sc): 端末間再開同期を追加
Made-with: Cursor
2026-04-20 16:46:18 +09:00
posimai ec51c2ed6b fix: trust proxy を設定して req.ip を正しくクライアントIPに解決
nginx リバースプロキシ背後では req.ip がプロキシの内部 IP になる問題を修正。
app.set('trust proxy', 1) で X-Forwarded-For を信頼し、IP ベースの
レート制限(together/ponshu)が実際のクライアント IP で動作するようにする。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 13:34:22 +09:00
posimai 548c4fcca2 security: 認証・レート制限の5箇所を修正
- /journal/posts/public: 任意ユーザー列挙を廃止、SITE_PUBLIC_USER 固定
- /site/config/public: IDOR 修正 + 公開キーをホワイトリスト制限
- POST /together/groups: IP 単位 5回/時間 のレート制限を追加
- POST /together/join: IP 単位 10回/時間 のレート制限を追加
- POST /together/share: Gemini archive を shared_by 単位 20回/時間 に制限
- POST /ponshu/license/validate: IP 単位 10回/分 のブルートフォース防止

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 13:30:10 +09:00
posimai 222238f2b9 fix(together): require member auth on GET /together/groups/:groupId
invite_code was accessible without authentication to anyone who knew
the groupId (sequential integer). Now requires ?u= + member check.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 01:04:24 +09:00
posimai 6cae7daa87 fix(together): revert broken userCheck that caused 403 for all JWT users
userCheck required username to match users.user_id/name, but Together
usernames (mai, EIJI) never matched users table entries (maita, partner).
All JWT-bearing clients were getting 403. Reverts to member-row-only
check until user_id backfill is complete (Phase 1).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 19:08:36 +09:00
posimai 925638250b fix(together): include invite_code in GET /together/groups/:id response
Was accidentally excluded from SELECT, causing invite code to disappear
in the settings panel.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 13:37:24 +09:00
posimai 96f22b6a82 fix(together): close JWT legacy-fallback impersonation hole
When JWT is present but strict member check fails, verify the body
username belongs to the JWT user before allowing legacy access.
JWT-less clients (no Authorization header) are unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 13:06:14 +09:00
posimai 1eb94565d5 fix(together): add member auth to GET endpoints, remove comment_count JOIN 2026-04-18 08:51:16 +09:00
posimai 8f41c4736f feat(together): add 'read' to reaction type allowlist 2026-04-17 23:37:22 +09:00
posimai 147d85abf6 feat(together): cursor-based pagination API — limit/cursor クエリパラメーター追加 2026-04-17 18:34:06 +09:00
posimai e960b9e2ac fix(brain): comprehensive review fixes — placeholder persistence, count accuracy, dead code
- Gemini null 時: プレースホルダーを NULL で上書き(永続化バグ解消)
- /articles カウント: LIMIT後rows.filter()→専用COUNTクエリで正確化
- genAITogether 削除(genAI の alias で不要)
- quick-save: e.message のクライアント露出を固定メッセージに置換

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 09:11:27 +09:00
posimai 47f82586d2 fix(brain): retry 503 once, don't persist failure message to DB
- analyzeWithGemini: 503(一時高負荷)は4秒後に1回リトライ
- 失敗時は null を返し、呼び出し側で DB を更新しない
  → 「AI分析に失敗しました」がsummaryとして永続化されなくなる

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 23:39:46 +09:00
posimai b25b3f640e fix(brain): switch analyzeWithGemini from gemini-2.0-flash-lite to gemini-2.5-flash
gemini-2.0-flash-lite のフリー枠日次クォータが枯渇し AI 分析が全件失敗していた。
gemini-2.5-flash に統一してクォータ問題を解消する。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 23:12:50 +09:00
posimai 7aa79f4a7d fix: station VPS Users/Node ハイフン・CPU リング 0% 表示修正
Made-with: Cursor
2026-04-12 08:13:58 +09:00
posimai 47c75cae4f fix: Together API に投稿前グループメンバー確認を追加
/together/share, /together/react, /together/comments の各書き込みエンドポイントに
together_members テーブルでのメンバーチェックを追加。
非メンバーによる投稿・リアクション・コメントを 403 で拒否する。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 23:03:49 +09:00
posimai 10402464c5 feat: 購入後マジックリンクメール自動送信 + TTS に purchaseMiddleware 接続
Made-with: Cursor
2026-04-11 15:05:23 +09:00
posimai 85bd0cc879 fix: store URL を store.posimai.soar-enrich.com に統一
Made-with: Cursor
2026-04-11 14:36:33 +09:00
posimai 2cd7795202 feat: Ponshu Room Proライセンス管理をserver.jsへ統合
- routes/ponshu.js: ライセンス検証・失効エンドポイントを新規追加
  POST /api/ponshu/license/validate (認証不要、モバイルから直接呼ぶ)
  POST /api/ponshu/admin/license/revoke (APIキー認証必須)
- routes/stripe.js: 既存のStripe Webhookハンドラーを抽出し拡張
  metadata.product === 'ponshu_room_pro' の場合にライセンスキーを発行
  Stripe Webhook 冪等性チェック (stripe_session_id) を追加
  Resend でライセンスキーをメール送信
- server.js: ponshu_licenses テーブルをスキーマに追加
  インラインのhandleStripeWebhook関数を routes/stripe.js に置き換え
  ponshuRouterとstripeRouterをマウント

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 00:16:57 +09:00
posimai ada6eba333 fix: security — invite_code leakage, Atlas token in URL, RSS err.message exposure
- GET /together/groups/🆔 SELECT * -> SELECT id, name, created_at (invite_code 除外)
- Atlas github/vercel/tailscale-scan: token を query param から Authorization header へ移行
- /events/rss: err.message をクライアント返却しないよう固定メッセージに置換

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 00:05:18 +09:00
posimai 82a094f2f2 fix: refuse to start if JWT_SECRET is not set in environment
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 07:55:08 +09:00
posimai 5de1174363 fix: Together/Jina に SSRF ガード + Jina レスポンスサイズ上限 1MB 2026-04-09 23:49:25 +09:00
posimai 5a3a510331 fix: SSRF blocklist + レスポンスサイズ制限 + DB pool max 15 + pool.on(error) 2026-04-09 23:45:55 +09:00
posimai 1336b20c90 fix: POST /save と quick-save を即時保存に変更 — fetchMeta/Jina/AI をバックグラウンドへ移動してラグ解消 2026-04-09 20:48:17 +09:00
posimai 3cd8ebd0b6 fix: Feed API POST auth gate + sanitize e.message in error responses 2026-04-06 09:09:26 +09:00
posimai 2e326605cb feat: include plan in JWT, update session/verify to use plan column 2026-04-05 15:03:04 +09:00
posimai 8fdcb65f4b fix: skip express.json for stripe webhook to preserve raw body 2026-04-05 14:54:39 +09:00
posimai 955da8899b fix: allow server-to-server requests to /health without CORS block 2026-04-05 14:02:55 +09:00
posimai 8e9f232dba feat: stripe webhook plan upgrade/downgrade, add plan/subscription columns 2026-04-05 14:01:41 +09:00
posimai c7b6d0b2d3 feat: add Feed background RSS fetch job and /feed/articles endpoint 2026-04-05 12:29:48 +09:00
posimai ac8cc6db81 fix: security hardening round 2
- CORS: origin=null now rejected (was: allowed as same-origin)
- CORS: regex tightened to [\w-]+ to prevent subdomain bypass
- CORS: add *.posimai.soar-enrich.com and posimai.soar-enrich.com explicitly
- Stripe webhook: fix regex capture groups + add uppercase hex support

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 03:01:06 +09:00
posimai 0590d0995d feat: Stripe Webhook + purchase gate
- Add POST /api/stripe/webhook (signature verification, no stripe SDK)
- Add purchased_at + stripe_session_id columns to users table (migration)
- Add purchaseMiddleware (apikey users bypass, JWT users check purchased_at)
- Update /auth/session/verify to return purchased status

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 02:22:18 +09:00
posimai d6f7b487d0 fix: security hardening for commercial release
- Fix OAuth (Google/GitHub) DB column bug: SELECT id → SELECT user_id
- Add OAuth CSRF protection via state parameter (Google + GitHub)
- Restrict /health endpoint: detailed info requires authentication
- Add in-memory rate limiter utility (checkRateLimit)
- Add rate limit to passkey login/begin: 10 req/min per IP
- Add rate limit to Gemini AI analysis: 50 articles/hour per user
- Add rate limit to journal suggest-tags: 10 req/hour per user
- Update posimai-dev /api/vps-health proxy to send VPS_API_KEY header

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 23:04:20 +09:00