<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Rebounder Tech Blog</title><description>株式会社Rebounder が自社で運用している本番システムで、実際に起きたことの記録。</description><link>https://tech.rebounder.jp/</link><language>ja</language><item><title>cqw(container-query)は、DOM構造の変更で黙って効かなくなる</title><link>https://tech.rebounder.jp/posts/css-container-query-cqw-context-dependent-fails-silently/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/css-container-query-cqw-context-dependent-fails-silently/</guid><description>container-query単位(cqw)でtransform:scaleさせていた盤面プレビューが、周辺DOM構造の変更で.frameの幅が定まらなくなり、原寸のまま16:9枠に入って右と下が切れた。ResizeObserverで実幅を計測しwidthを明示する方式に直した。</description><pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate></item><item><title>buildSignagePayloadForClassを使わない盤面プレビューは自動ブロックが実機と食い違う</title><link>https://tech.rebounder.jp/posts/editor-preview-hand-built-payload-drifts-from-device-builder/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/editor-preview-hand-built-payload-drifts-from-device-builder/</guid><description>クラスエディタの盤面プレビューはbase(boardBase)を手組みし、news/trainStatus等の自動コンテンツブロックをnull固定していた。実機は単一ソースのbuilderで全ブロックを取得するため、パターンによってはエディタと実機の表示が食い違っていた原因と直し方を書く。</description><pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate></item><item><title>pdfjs-distのstandard_fontsがNext.js standaloneに同梱されない</title><link>https://tech.rebounder.jp/posts/pdfjs-dist-standard-fonts-nextjs-standalone-not-bundled/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/pdfjs-dist-standard-fonts-nextjs-standalone-not-bundled/</guid><description>pdfjs-distは標準フォントをfile://で動的読込するため、Next.jsのfile tracingが追跡できずstandaloneビルドに同梱漏れする。v6ではgetTextContent()がUnknownErrorExceptionで壊れる。設定と起動時assertで対処した。</description><pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate></item><item><title>送信ボタンをFormDataで判定しないとハイドレーション前は押せない</title><link>https://tech.rebounder.jp/posts/react-controlled-disabled-button-breaks-progressive-enhancement/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/react-controlled-disabled-button-breaks-progressive-enhancement/</guid><description>サーバーの状態でdisabled属性を制御したところ、ハイドレーション前やJS失敗時にボタンが永久に無効なままになり、署名フォームの送信そのものが不能になっていた。required+常時有効化とFormData判定で直した。</description><pubDate>Fri, 04 Sep 2026 00:00:00 GMT</pubDate></item><item><title>同一フィードのURL重複でON CONFLICT DO UPDATEが21000で全断した</title><link>https://tech.rebounder.jp/posts/postgres-on-conflict-do-update-cannot-affect-row-twice-feed-dedup/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/postgres-on-conflict-do-update-cannot-affect-row-twice-feed-dedup/</guid><description>1本のON CONFLICT DO UPDATEで複数記事をupsertするニュース取得ジョブが、同一フィード内の同じURLでPostgresの21000エラーとなり、fail-softなcatchでフィード全体を無音でskipしていた。先勝ちdedupで解消。</description><pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate></item><item><title>Stripe webhook冪等台帳のINSERT失敗、23505以外も200で握り潰していた</title><link>https://tech.rebounder.jp/posts/stripe-webhook-ledger-insert-error-swallowed-as-duplicate/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/stripe-webhook-ledger-insert-error-swallowed-as-duplicate/</guid><description>Stripeのwebhookは冪等台帳stripe_eventsへのINSERT失敗を、理由を問わず二重配信の200 no-opとして返していた。UNIQUE制約違反(23505)以外のDB一時障害もこれに含まれるため、Stripeは成功と解釈して再送せず、イベントが恒久的に失われる。原因と直し方を書く。</description><pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate></item><item><title>turbo.jsonにpassThroughEnvが無いとテストが黙って全skipのままCIがgreenになる</title><link>https://tech.rebounder.jp/posts/turbo-passthroughenv-missing-rls-tests-silently-skipped/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/turbo-passthroughenv-missing-rls-tests-silently-skipped/</guid><description>turbo.jsonのtest taskにpassThroughEnvが無いと、CIにDATABASE_URLがあってもturboはそれをvitestへ渡さない。テストは未設定をdescribe.skipで検知するだけなのでCIはgreenのまま、RLSテスト24件が一度も実行されていなかった。</description><pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate></item><item><title>ポーリングだけDateが文字列化し、getTime is not a functionで盤面が落ちた</title><link>https://tech.rebounder.jp/posts/json-poll-response-date-string-gettime-not-a-function/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/json-poll-response-date-string-gettime-not-a-function/</guid><description>SSRの初期描画ではDateがそのまま復元されるのに、同じ画面の自動更新ポーリングだけres.json()経由でDateが文字列化する。ニュース日付整形が文字列に対し.getTime()を呼びTypeErrorで盤面ごとエラー画面に落ちた。JSON.parseのreviverで両方の描画経路を揃えて解消した。</description><pubDate>Wed, 02 Sep 2026 00:00:00 GMT</pubDate></item><item><title>setContentView前はinsetsControllerがnullでImmersiveが効かない</title><link>https://tech.rebounder.jp/posts/android-insetscontroller-null-before-setcontentview/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/android-insetscontroller-null-before-setcontentview/</guid><description>Android で setContentView() より前に window.insetsController を呼ぶと、DecorView 未確定で null が返り、hide() が動かずImmersiveモードが黙って効かない。呼び出し順序を setContentView 後へ移して直した。</description><pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate></item><item><title>キオスク端末の消灯がstartActivity1本頼りで、失敗すると朝まで点灯したままになる</title><link>https://tech.rebounder.jp/posts/android-kiosk-overlay-startactivity-can-silently-fail-leaving-screen-on/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/android-kiosk-overlay-startactivity-can-silently-fail-leaving-screen-on/</guid><description>常時起動のAndroidキオスク端末で夜間の黒画面表示をBlackScreenActivityへのstartActivity1回だけに頼っていると、BAL制限やSYSTEM_ALERT_WINDOW未許可でその呼び出しが失敗した瞬間、画面は消えないまま朝を迎える。</description><pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate></item><item><title>maybeSingleで1件決め打ちすると、複数行ヒットでPGRST116の404になる</title><link>https://tech.rebounder.jp/posts/supabase-maybesingle-multiple-rows-pgrst116-permanent-404/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/supabase-maybesingle-multiple-rows-pgrst116-permanent-404/</guid><description>署名の控えPDFを配信するAPIは一意制約が3列複合なのに、クエリは2列だけで絞り込んでmaybeSingle()に渡していた。同じ組で複数行が存在した瞬間PGRST116を返し、実在する控えが恒久404になっていた。</description><pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate></item><item><title>SECURITY DEFINER関数はPUBLIC EXECUTE既定でanonから直接呼べる</title><link>https://tech.rebounder.jp/posts/supabase-security-definer-function-default-public-execute-exposes-rpc/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/supabase-security-definer-function-default-public-execute-exposes-rpc/</guid><description>SECURITY DEFINERの書込RPCはPostgreSQLの既定でPUBLIC EXECUTEが付く。revokeしない限りSupabaseのPostgREST層を経由してanon/authenticatedロールから直接呼び出せる。実際に塞いだrevoke/grantの手順まで書く。</description><pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate></item><item><title>相乗りキーの設定行をロック無しで読んで→マージして→書くと、同時保存でキーが消える</title><link>https://tech.rebounder.jp/posts/colocated-config-key-lost-update-without-row-lock/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/colocated-config-key-lost-update-without-row-lock/</guid><description>1つのJSONB行に複数の設定キーを相乗りさせ、既存値を読んでスプレッドしてから書き戻すread-merge-write upsertは、その読み取りをSELECT ... FOR UPDATEで行ロックしない限り、並行更新と競合したとき相手が直前に書いたキーごと上書きして消す。原因と、行ロックでの直し方を書く。</description><pubDate>Sun, 30 Aug 2026 00:00:00 GMT</pubDate></item><item><title>学年はあるが学科は無い状態だけ「学科を追加」の導線が無かった</title><link>https://tech.rebounder.jp/posts/conditional-branch-hides-first-item-creation-entry-point-stuck-ui/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/conditional-branch-hides-first-item-creation-entry-point-stuck-ui/</guid><description>学校構成画面はisEmptyとhasDepartmentsという2つの真偽値で3状態に分岐し、学年はあるが学科が無い『クラス制』状態だけ学科を追加する導線が存在しなかった。原因とテストで見落とされた理由、直し方を書く。</description><pubDate>Sun, 30 Aug 2026 00:00:00 GMT</pubDate></item><item><title>規約改定の再同意フォームがauto_renewをリセットしない</title><link>https://tech.rebounder.jp/posts/contract-reconsent-does-not-reset-auto-renew/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/contract-reconsent-does-not-reset-auto-renew/</guid><description>自動更新条項を削除した改定版の規約に再同意しても、自動更新フラグがtrueのまま残ることがある。原因はフラグを立てる関数がfalse→trueの一方向にしか書き込まない設計で、再同意（署名リセット）の側で明示的に倒さない限りtrueが残り続け、満了時に後継契約が自動生成・自動請求される。</description><pubDate>Sun, 30 Aug 2026 00:00:00 GMT</pubDate></item><item><title>transform:scaleで固定サイズに縮小表示していても、メディアクエリは実ビューポート幅で評価される</title><link>https://tech.rebounder.jp/posts/media-query-still-uses-real-viewport-inside-scaled-fixed-stage/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/media-query-still-uses-real-viewport-inside-scaled-fixed-stage/</guid><description>1280×720の固定ステージをtransform:scaleで縮小表示するプレビューが、@media(min-width)は縮小後ではなく実デバイスのビューポート幅で評価されるため、大型モニタでは大画面向けプロファイルが適用されてステージからはみ出した。</description><pubDate>Sun, 30 Aug 2026 00:00:00 GMT</pubDate></item><item><title>left:50%とwidth:fit-contentを組むとmax-widthが効かない</title><link>https://tech.rebounder.jp/posts/absolute-left-50-fit-content-max-width-never-applies/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/absolute-left-50-fit-content-max-width-never-applies/</guid><description>position:absoluteをleft:50%+width:fit-contentで中央寄せしたら、指定したmax-widthより手前で強制的に折り返された。shrink-to-fitのavailable widthがleftオフセット分だけ縮むのが原因。</description><pubDate>Sat, 29 Aug 2026 00:00:00 GMT</pubDate></item><item><title>insetのbox-shadowで描いた縁取りが子要素の背景に隠れて消える</title><link>https://tech.rebounder.jp/posts/inset-box-shadow-ring-hidden-by-static-child-background/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/inset-box-shadow-ring-hidden-by-static-child-background/</guid><description>白い盤面の上でも暗幕の上でも見えるようにと縁取りをinset box-shadowで描いたら、入稿プレビューの背景を持つ子要素の下に隠れて消えました。insetのbox-shadowは要素自身の背景/ボーダー段で塗られるため、静的配置の子要素の背景に必ず負けるのが原因です。</description><pubDate>Sat, 29 Aug 2026 00:00:00 GMT</pubDate></item><item><title>編集フォームが最新の選択肢一覧に無い選択を自動で間引き、無関係な保存で対象が黙って消えた</title><link>https://tech.rebounder.jp/posts/edit-form-prunes-selections-missing-from-stale-list-silent-data-loss/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/edit-form-prunes-selections-missing-from-stale-list-silent-data-loss/</guid><description>編集フォームは、v2から取得し直したモニタ一覧に無い選択IDを検知すると自動でselectedから間引いて上書きしていた。価格だけ直すつもりで保存すると、一覧の側の変動につられて対象モニタが黙って減る。原因と、警告表示+hiddenで送りサーバーに弾かせるfail-closedな直し方を書く。</description><pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate></item><item><title>非数値のenv変数はNaNとして??をすり抜け、embeddingが0件・fetchが即abortになった</title><link>https://tech.rebounder.jp/posts/env-nan-parseint-nullish-coalescing-immediate-abort/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/env-nan-parseint-nullish-coalescing-immediate-abort/</guid><description>env変数が非数値だとNumber.parseIntはNaNを返す。truthyチェックと後段の?? 既定値の両方をすり抜け、embeddingは0件・fetchはsetTimeout(abort, NaN)で即中断され続けた。原因と直し方を書く。</description><pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate></item><item><title>親ページの許可ロールだけ絞り込み、子コンポーネント内の別ロールガードを直し忘れて未捕捉の403例外を出した</title><link>https://tech.rebounder.jp/posts/parent-page-role-narrowed-child-component-gate-left-behind-forbidden-error/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/parent-page-role-narrowed-child-component-gate-left-behind-forbidden-error/</guid><description>効果ダッシュボードのrequireRoleをSYSTEM_ADMIN_ROLES専用に絞り込んだが、ページ内のAI効果コメントパネルが呼ぶServer ActionはPUBLISHER_ROLES gateのままで、未捕捉のForbiddenErrorをレビューで見つけて同コミット内で撤去した経緯を書く。</description><pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate></item><item><title>決済成功後のDB反映失敗をカード失敗と誤認し、二重請求になりかけた</title><link>https://tech.rebounder.jp/posts/stripe-post-charge-db-failure-misdiagnosed-as-card-decline/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/stripe-post-charge-db-failure-misdiagnosed-as-card-decline/</guid><description>オフセッション課金でPaymentIntent作成の成否とDB反映(markContractPaid)の成否を同じtry/catchで扱うと、課金成立後の一過性DB書込エラーがカード失敗と誤診断され、課金済みのカードに対してさらに請求書フォールバックを発行し二重請求になる。原因と直し方を書く。</description><pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate></item><item><title>監査ログのRLS policyがactor_user_id=NULLを許すと、乗っ取られたアカウントが操作痕跡を消せる</title><link>https://tech.rebounder.jp/posts/audit-log-rls-null-actor-allows-repudiation/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/audit-log-rls-null-actor-allows-repudiation/</guid><description>監査ログテーブルへのINSERTを許すRLS policyがactor_user_id IS NULLを無条件に許可していた。乗っ取られたテナント内アカウントがactor=NULLで自分の操作を記録すれば、追跡から逃れられる。system_adminだけNULLを許す例外設計に直した話。</description><pubDate>Thu, 27 Aug 2026 00:00:00 GMT</pubDate></item><item><title>stickyのtop:0が残ったままfixedにすると下部固定バーが全画面化する</title><link>https://tech.rebounder.jp/posts/css-fixed-inherited-top-zero-bottom-zero-fullscreen-stretch/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/css-fixed-inherited-top-zero-bottom-zero-fullscreen-stretch/</guid><description>sticky用のtop:0をリセットしないままposition:fixedへ切り替えると、bottom:0と両立してボックスがviewport全高にストレッチする。モバイルの下部固定タブバーが画面全体を覆って操作不能になった事故を、CSSの差分だけで直した記録。</description><pubDate>Thu, 27 Aug 2026 00:00:00 GMT</pubDate></item><item><title>配布パッケージの漏洩検査は、grepの対象パスがパッケージの半分しか見ていなかった</title><link>https://tech.rebounder.jp/posts/dist-sanitizer-denylist-grep-misses-new-internal-string/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/dist-sanitizer-denylist-grep-misses-new-internal-string/</guid><description>販売用パッケージのビルドスクリプトに社内限定の文言を検出するgrep検査を入れていたが、実際に配布物へ社内限定の文言が混入して買い手のレビューで指摘された。原因は語彙の不足ではなく、検査対象のパスがパッケージの一部しか見ていなかったことだった。</description><pubDate>Thu, 27 Aug 2026 00:00:00 GMT</pubDate></item><item><title>新しい httpOnly cookie を追加してデプロイすると、ログイン済みユーザーだけ401になる</title><link>https://tech.rebounder.jp/posts/new-httponly-cookie-not-issued-until-relogin-after-deploy/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/new-httponly-cookie-not-issued-until-relogin-after-deploy/</guid><description>書き込みAPI専用のhttpOnly + HMAC署名cookieを新設してデプロイしたところ、デプロイ前からログイン中だった運営担当だけ、画面はログイン済みのまま一覧取得が401で失敗した。原因は新cookieがログイン時にしか配られないこと。401ハンドラで自動リロードして直した記録。</description><pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate></item><item><title>middlewareのmatcher除外に登録し忘れた公開ページが、匿名端末をログイン画面へ誤誘導していた</title><link>https://tech.rebounder.jp/posts/nextjs-middleware-matcher-missing-public-route-login-redirect/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/nextjs-middleware-matcher-missing-public-route-login-redirect/</guid><description>公開サイネージ表示は端末が__sessionを持たない匿名経路だが、middlewareのmatcher除外リストに登録し忘れていたため、そのままだと/loginへリダイレクトされ実機に到達できなかった。既存の/s/や/studentと同じnegative lookaheadにsignage/を足して解消した記録。</description><pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate></item><item><title>契約更新のたびに枠を複製し、旧行を終了し忘れると在庫定員が二重に消費される</title><link>https://tech.rebounder.jp/posts/renewal-successor-rows-without-retiring-predecessor-double-counts-capacity/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/renewal-successor-rows-without-retiring-predecessor-double-counts-capacity/</guid><description>自動更新バッチが後継契約へplacementsを複製する一方、元の行を終了扱いにしないと、残り枠の集計は両方をカウントし続ける。実装直後のレビューで見つかった在庫定員の二重消費と、複製失敗時は元行を残す安全側の直し方。</description><pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate></item><item><title>ORDER BYの無いLIMIT 1が、複数テナントのstagingで別の校のadminを返す</title><link>https://tech.rebounder.jp/posts/dev-login-missing-orderby-returns-wrong-tenant-admin/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/dev-login-missing-orderby-returns-wrong-tenant-admin/</guid><description>dev-loginのschool_admin解決はORDER BYの無いSELECT LIMIT 1で書かれており、複数テナントのテストデータが増えるとPostgreSQLの行順に依存して意図しない学校のuidを返しうる状態だった。DEVLOGIN_TEST校を優先する決定的なORDER BYで直した経緯を書く。</description><pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Next.js の proxy.ts が API キー認証のエンドポイントもログイン画面へ飛ばしていた</title><link>https://tech.rebounder.jp/posts/nextjs-middleware-external-api-key-auth-redirected-to-login/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/nextjs-middleware-external-api-key-auth-redirected-to-login/</guid><description>Next.js の proxy.ts はセッション認証の除外パスに /api/health しか列挙しておらず、独自の API キー認証を持つ /api/v1/ と /api/mcp/ を後から追加した際に除外し忘れ、外部からのリクエストがログイン画面へリダイレクトされていた。原因と直し方を書く。</description><pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Supabase の update で未送信フィールドを `??` の既定値にすると既存の値が上書きされる</title><link>https://tech.rebounder.jp/posts/supabase-update-partial-field-nullish-coalesce-overwrite/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/supabase-update-partial-field-nullish-coalesce-overwrite/</guid><description>編集フォームに availability 欄が無いだけで、保存のたびに掲載中の枠が空きへ巻き戻っていた。原因は `val(formData.get(&quot;availability&quot;)) ?? &quot;空き&quot;` という書き方で、未送信フィールドを既存値ではなく常にデフォルト値として扱っていたこと。直し方まで書く。</description><pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate></item><item><title>セット割引の判定を「保有しているか」だけにすると、買い増すたびに再発する</title><link>https://tech.rebounder.jp/posts/bundle-discount-reapplied-on-every-purchase-without-granted-check/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/bundle-discount-reapplied-on-every-purchase-without-granted-check/</guid><description>複数の申込枠をまとめて保有すると自動適用されるセット割引が、条件を「対象を全部保有しているか」だけで判定していたため、パック完成後に別の枠を追加購入するたびに同じ割引が繰り返し適用されていた。契約テーブルに『既に付与済みか』を追加して防いだ経緯。</description><pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate></item><item><title>ロックは効いているのに件数だけ二重になる。数えていたのは書き込みではなく「書くつもり」だった</title><link>https://tech.rebounder.jp/posts/for-update-count-intent-vs-actual-writes/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/for-update-count-intent-vs-actual-writes/</guid><description>TV死活チェッカのサマリがnewlyDown合計1のはずが2になるflakyテストの原因は、DBの行数ではなくサマリの数え方だった。FOR UPDATEで直列化されていても、classificationの長さで件数を返すと同時発火の敗者側まで計上される。実書込件数を返す直し方を書く。</description><pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate></item><item><title>仮パスワードの強制変更が直URLで素通りしていた。ガードを画面ごとに書くと必ず付け忘れる</title><link>https://tech.rebounder.jp/posts/forced-password-change-bypassed-by-direct-url/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/forced-password-change-bypassed-by-direct-url/</guid><description>must_change_passwordの広告主が/dashboard以外へ直URLでアクセスすると、強制パスワード変更を素通りできた。原因は強制リダイレクトが2画面にしか書かれておらず、チェックが画面ごとに散在していたこと。requireCustomer()に集約して直した記録。</description><pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate></item><item><title>RLSを有効にしても、TRUNCATE権限が残っていれば安全ではなかった</title><link>https://tech.rebounder.jp/posts/postgres-truncate-bypasses-rls-even-when-enabled/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/postgres-truncate-bypasses-rls-even-when-enabled/</guid><description>chat_knowledgeテーブルはRLSを有効にしポリシーを1つも作らずanon/authenticatedを閉め出したつもりだったが、Supabaseの既定権限でTRUNCATEまで付与されたままだった。TRUNCATEはRLS対象外の操作なので、ポリシーがゼロでもテーブルを空にできる。実測に基づく直し方を書く。</description><pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate></item><item><title>エラーメッセージを運用者向けの日本語にした副作用で、dead-letterから原因を辿れなくなった</title><link>https://tech.rebounder.jp/posts/dead-letter-error-humanized-loses-traceable-id/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/dead-letter-error-humanized-loses-traceable-id/</guid><description>配信の被覆検証は運営フォーム向けの日本語メッセージだけを返しており、それをdead-letterのlast_errorへ転用すると学校IDが失われ、ログからは原因の学校を特定できなくなっていた。検証結果に機械可読なcode/schoolsを足して分離した直し方を書く。</description><pubDate>Sat, 22 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Permissions-Policy: microphone=() は自オリジンの音声入力も塞ぐ</title><link>https://tech.rebounder.jp/posts/permissions-policy-microphone-self-blocks-web-speech/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/permissions-policy-microphone-self-blocks-web-speech/</guid><description>Permissions-Policy: microphone=() は「どのオリジンにも許可しない」という意味でselfを含まない。多層防御として追加した結果、自社アプリのWeb Speech APIによる音声入力がプロンプトすら出さずに全面遮断された。microphone=(self)へ変更して解消した経緯を書く。</description><pubDate>Sat, 22 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Checkout Session の期限を省くと、離脱した予約が24時間分の席を占有する</title><link>https://tech.rebounder.jp/posts/stripe-checkout-session-default-24h-expiry-holds-reservation-seat/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/stripe-checkout-session-default-24h-expiry-holds-reservation-seat/</guid><description>Stripe Checkout Session に expires_at を指定しないと既定で24時間有効になり、決済せず離脱した予約もその間ずっと定員を占有し続ける。予約サイトで実際に起きた事故と、Stripe が許す最短30分への短縮で解決した経緯。</description><pubDate>Sat, 22 Aug 2026 00:00:00 GMT</pubDate></item><item><title>streamObjectのabortでusage Promiseがunhandled rejectionになる</title><link>https://tech.rebounder.jp/posts/ai-sdk-streamobject-abort-unhandled-rejection/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/ai-sdk-streamobject-abort-unhandled-rejection/</guid><description>Vercel AI SDKのstreamObjectにAbortSignalを配線すると、中断時にresult.usage（完了後に解決するPromise）がrejectする。呼び出し元がその経路でdoneをawaitしていないと、誰にも拾われずNode.jsのunhandled rejectionになる。</description><pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Semgrep detect-non-literal-regexpの誤検知は、到達不能な分岐を型で消して直した</title><link>https://tech.rebounder.jp/posts/semgrep-non-literal-regexp-dead-branch-false-positive/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/semgrep-non-literal-regexp-dead-branch-false-positive/</guid><description>E2Eテストの`new RegExp(c.path.replace(...))`というフォールバック分岐がSemgrepのdetect-non-literal-regexpに引っかかりSASTが赤くなった。分岐自体は全ケースがallowUrlを持つため到達不能で、suppressせず型で分岐そのものを消して解消した話。</description><pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate></item><item><title>デプロイ後に無関係な機能が消えた。原因は分岐元が古いブランチだった</title><link>https://tech.rebounder.jp/posts/stale-branch-deploy-silently-reverts-merged-features/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/stale-branch-deploy-silently-reverts-merged-features/</guid><description>同じ手順でCloud Runのイメージタグを差し替えても、ビルド元のブランチの枝分かれ点が古いと、その後mainにマージ済みの機能はgit revertコミットを1つも作らずに本番から消える。デプロイの実体はgitの履歴ではなくタグの差し替えでしかないため、症状は無関係な2件の不具合として報告される。</description><pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate></item><item><title>YT.Playerでdivを置き換える埋め込み方式は、タイミング次第で黒画面のまま再生されない</title><link>https://tech.rebounder.jp/posts/youtube-iframe-player-div-replace-black-screen/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/youtube-iframe-player-div-replace-black-screen/</guid><description>YouTube IFrame APIでdiv要素をPlayerに渡して初期化する方式は、divがiframeに置き換わるまで画面に何も表示されず、タイミング次第で黒画面のまま再生が始まらないことがある。iframeをsrc付きで直接描画し、YT APIは後から紐づける方式に変えた経緯を書く。</description><pubDate>Fri, 21 Aug 2026 00:00:00 GMT</pubDate></item><item><title>唯一の呼出し元が消えたロール変更 seam を、それ自体が攻撃面として撤去する</title><link>https://tech.rebounder.jp/posts/dormant-privilege-escalation-seam-removed/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/dormant-privilege-escalation-seam-removed/</guid><description>任意ロール・任意スクールIDをIdPのclaimへ書き込めるロール変更関数は、唯一の呼出し元だった機能が撤去されたあとも本番の呼出し元ゼロのまま残存していた。docstringの安全保証は呼出し元の存在に依存しており、呼出し元が消えた時点で意味を失っていた。</description><pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate></item><item><title>pdf-lib + fontkit で生成した帳票PDFの電話番号がコピペで化ける</title><link>https://tech.rebounder.jp/posts/pdf-lib-fontkit-gsub-digit-garbling/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/pdf-lib-fontkit-gsub-digit-garbling/</guid><description>NotoSansJP を fontkit 経由で pdf-lib に埋め込むと、電話番号などの数字だけコピー・検索・pdftotext で化けることがある。原因は GSUB の文脈置換で、pdf-lib の ToUnicode CMap には既定グリフしか載らないためだった。</description><pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate></item><item><title>フォームをkeyで再マウントすると、検証エラー直後の保存で入力値が既定値に戻る</title><link>https://tech.rebounder.jp/posts/react-key-remount-resets-uncontrolled-input/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/react-key-remount-resets-uncontrolled-input/</guid><description>&lt;form key={formGen}&gt;で送信のたびに再マウントする実装では、defaultValueで渡した未制御の入力欄は検証エラー直後の再送信でも一緒にリセットされる。画面には入力し直した値が見えているのに、保存されるのは既定値になる不具合の原因と直し方を書く。</description><pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate></item><item><title>契約更新のバッチ処理で、後継行に外部キーを引き継ぐと同日中にステータスが巻き戻る</title><link>https://tech.rebounder.jp/posts/renewal-creative-id-revives-ended-placement/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/renewal-creative-id-revives-ended-placement/</guid><description>契約の自動更新バッチが枠(placements)行を複製する際、creative_idを新旧の行に残したまま元行を「終了」にすると、同じcron run内の別バッチが同じcreative_idを目印に元行を「申込済」へ巻き戻し、定員リークが標準経路で再発する。</description><pubDate>Thu, 20 Aug 2026 00:00:00 GMT</pubDate></item><item><title>マイグレーションファイルの連番が2つ重複していた</title><link>https://tech.rebounder.jp/posts/duplicate-migration-sequence-number/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/duplicate-migration-sequence-number/</guid><description>別々のfeatureブランチで作ったマイグレーションファイルが、どちらも0035番を使っていた。本番へは冪等なSQLとして両方適用され実害は無かったが、新規環境やstagingを連番順に流すと適用順序があいまいになる。衝突を警戒していたはずの側も、もう一方の存在には気づけなかった。</description><pubDate>Wed, 19 Aug 2026 00:00:00 GMT</pubDate></item><item><title>環境変数の既定値が staging バケットのままだと、destroy で本番画像が消える</title><link>https://tech.rebounder.jp/posts/env-default-bucket-leaks-across-environments/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/env-default-bucket-leaks-across-environments/</guid><description>seed スクリプトの環境変数に既定値（フォールバック）として他環境のバケット名を残していると、明示的に上書きしない限りその値がそのまま本番データベースに書き込まれる。staging を destroy した瞬間に本番の画像参照先ごと消えた実例と、原因・直し方・再発防止を書く。</description><pubDate>Wed, 19 Aug 2026 00:00:00 GMT</pubDate></item><item><title>フォームの一部だけ制御値にすると、保存失敗後の再送信で設定が黙って元に戻る</title><link>https://tech.rebounder.jp/posts/react-partial-controlled-fields-silent-revert/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/react-partial-controlled-fields-silent-revert/</guid><description>React 19 の &lt;form action&gt; は送信の成否に関わらず、制御していない入力を defaultValue へ戻します。一部の項目だけ制御値にしたフォームでは、検証エラーで戻った画面は制御外の項目だけが黙って元に戻り、フォームが無事に見えるぶん気づかず再送信してしまいます。</description><pubDate>Wed, 19 Aug 2026 00:00:00 GMT</pubDate></item><item><title>一部の設定にしか無い機能へのリンクを出しっぱなしにして502になった</title><link>https://tech.rebounder.jp/posts/unconditional-link-to-tenant-only-pdf-feature/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/unconditional-link-to-tenant-only-pdf-feature/</guid><description>申込書ページのPDF控えリンクは、特定の書式にしか対応していないPDF生成ルートを、対応・非対応を問わず全ユーザーに無条件で表示していた。非対応側の設定でリンクを踏むと、生成処理は失敗せず「対象外」を返しているのに、呼び出し元がそれを異常として扱い502になっていた。原因と直し方を書く。</description><pubDate>Wed, 19 Aug 2026 00:00:00 GMT</pubDate></item><item><title>CHECK 制約を張り替えるたび、別ブランチが足した値が消えていた</title><link>https://tech.rebounder.jp/posts/check-constraint-rewrite-drops-branch-value/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/check-constraint-rewrite-drops-branch-value/</guid><description>PostgreSQL の CHECK 制約を DROP して張り替える設計では、後から書いたマイグレーションが別ブランチで追加された値を知らないまま制約を書き直し、値ごと消してしまう。share_links.kind から receipt が消えた事故の原因と、和集合で冪等に復元する直し方。</description><pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate></item><item><title>23503 の外部キー違反が「競合しました」に化けて本番だけ全断した</title><link>https://tech.rebounder.jp/posts/fk-violation-masked-as-conflict/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/fk-violation-masked-as-conflict/</guid><description>system_admin による広告入稿が本番でだけ必ず失敗し、画面には「他の操作と競合しました」と出た。実際の原因は外部キー違反(23503)で、それを一意制約違反・検査制約違反と同じ扱いにするエラーハンドラが同じメッセージへ丸めていた。DBをモックしたテストは制約そのものを検証していなかった。</description><pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate></item><item><title>アプリ側のパスワード最小文字数がIdentity Platformの下限より緩くて本番だけ落ちた</title><link>https://tech.rebounder.jp/posts/idp-password-min-length-mismatch/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/idp-password-min-length-mismatch/</guid><description>system_adminが学校の教員共通パスワードを4〜5文字で設定すると、保存操作が本番で必ず失敗した。原因はアプリ側の下限(4文字)が、パスワードの実体を保管するIdentity Platformの下限(6文字)より緩く、IdPの拒否がcatchされずエラーバウンダリまで吹き上がっていたため。</description><pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate></item><item><title>教員ログインを有効化しても画面に出ない、原因は force-dynamic 書き忘れの静的プリレンダ</title><link>https://tech.rebounder.jp/posts/nextjs-static-prerender-hides-flag-flip/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/nextjs-static-prerender-hides-flag-flip/</guid><description>認証を経ない公開ページに動的 API の呼び出しが無いと、Next.js はビルド時点の状態でそのルートを静的プリレンダし、CDN が s-maxage で長期キャッシュします。DB の値を後から変えても、force-dynamic を明示しない限り画面には反映されません。本番ヘッダーから原因を特定した手順を書きます。</description><pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate></item><item><title>UIでは編集を凍結していても、サーバー側が同じ条件を見ていなければ偽装POSTで書き換えられる</title><link>https://tech.rebounder.jp/posts/ui-freeze-not-enforced-server-side/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/ui-freeze-not-enforced-server-side/</guid><description>配信枠の編集画面は「稼働中」または「団体が買い切り済み」のどちらかで入力欄を凍結表示していたが、更新処理は稼働中かどうかしか見ていなかった。買い切り直後で傘下の申込がまだ0件のタイミングだけ、フォームを直接POSTすると配信先を書き換えられる状態になっていた。</description><pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Androidの常駐サービスは、クラッシュせずに死ぬことがある</title><link>https://tech.rebounder.jp/posts/android-service-dies-without-crashing/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/android-service-dies-without-crashing/</guid><description>ポーリングループは pollOnce() だけを例外から守っても足りない。delay やバックオフ計算側で想定外の例外が出ると while(true) ごと静かに抜け、アプリはクラッシュせずに常駐サービスの中身だけが止まる。ループ全体の防御と、成功時刻ベースのウォッチドッグで検知・復帰させた設計を書く。</description><pubDate>Mon, 17 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Cloud Run Job を初めて有効化すると SecretsAccessCheckFailed で落ちる</title><link>https://tech.rebounder.jp/posts/cloud-run-job-secret-iam-race/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/cloud-run-job-secret-iam-race/</guid><description>Terraform で Cloud Run Job と Secret Manager の accessor IAM を同じ apply で新規作成すると、IAM 権限が伝播する前に作成時の secret アクセス検証が走り job が tainted される。depends_on で順序を固定する恒久対応まで書く。</description><pubDate>Mon, 17 Aug 2026 00:00:00 GMT</pubDate></item><item><title>スキャンPDFかどうかを非空白文字数/ページで判定してGeminiに直送する</title><link>https://tech.rebounder.jp/posts/gemini-pdf-ocr-fallback-threshold/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/gemini-pdf-ocr-fallback-threshold/</guid><description>pdfjs-dist はテキストレイヤをそのまま返すため、スキャンPDFはほぼ空文字になる。1ページあたりの非空白文字数が閾値を下回ったときだけPDFバイトをGeminiへfile partとして直送しOCRへフォールバックする、閾値の決め方と画像との送り方の違いを実装から書く。</description><pubDate>Mon, 17 Aug 2026 00:00:00 GMT</pubDate></item><item><title>認証ミドルウェアが robots.txt をログインへリダイレクトする</title><link>https://tech.rebounder.jp/posts/nextjs-middleware-robots-redirect/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/nextjs-middleware-robots-redirect/</guid><description>未ログイン時にログイン画面へ飛ばすミドルウェアは、robots.txt や sitemap.xml も同じ扱いにしてしまいがちです。クローラは 307 を受け取り、Lighthouse の SEO 監査が落ちます。原因は2層あり、片方だけ直しても再発します。</description><pubDate>Mon, 17 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Astro 7 でコンテンツコレクションが3箇所同時に壊れる</title><link>https://tech.rebounder.jp/posts/astro-legacy-content-config/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/astro-legacy-content-config/</guid><description>Astro を上げたら LegacyContentConfigError でビルドが落ちます。設定ファイルの置き場所・loader の必須化・描画 API の3つが同時に変わっているためで、1つ直しても次が出ます。3つまとめて直す形を書きます。</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>drizzle-kit migrate は手書きの SQL を適用しない</title><link>https://tech.rebounder.jp/posts/drizzle-migrate-skips-sql/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/drizzle-migrate-skips-sql/</guid><description>マイグレーションは成功したのに RLS ポリシーも監査トリガも本番に無い。drizzle-kit migrate が流すのは drizzle が生成した DDL だけで、隣のディレクトリに置いた手書き SQL は黙って飛ばされる。確認 SQL と、両方を確実に流す形まで。</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>最初の開発ボードは何を作りたいかで決まる</title><link>https://tech.rebounder.jp/posts/first-dev-board/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/first-dev-board/</guid><description>ESP32・Raspberry Pi・FPGA は守備範囲がまるで違う。通信する装置か、小さいコンピュータか、回路の学習か。実際に3枚とも触った結果と、本番会場で通信が混線したときの対処。</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>GitHub Actions から GCP に繋ぐとき実際に出る3つのエラー</title><link>https://tech.rebounder.jp/posts/gcp-workload-identity-errors/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/gcp-workload-identity-errors/</guid><description>Workload Identity 連携は設定が3層に分かれていて、どこが欠けても impersonation が失敗します。実際に出た3つのエラー文言を踏む順に並べ、どの層を見に行けばよいかと、疑わしいときの即時遮断まで書きます。</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Gemini の思考トークンが出力上限を食い応答が空になる</title><link>https://tech.rebounder.jp/posts/gemini-thinking-budget-hang/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/gemini-thinking-budget-hang/</guid><description>会話AIが「考えています」のまま本番だけ固まる事故があった。原因は Gemini の思考トークンが maxOutputTokens の枠を食いつぶし、構造化出力が始まる前にトークンが尽きること。クライアント側の終端検知・サーバのストール中断・thinking budget=0 の三層で塞いだ形を書く。</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>気象庁APIの夕方発表をそのまま upsert すると今日の気温が消える</title><link>https://tech.rebounder.jp/posts/jma-evening-forecast-temp-null/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/jma-evening-forecast-temp-null/</guid><description>気象庁の天気予報APIは17時の夕方発表で本日分の気温だけを予報から落とす。ON CONFLICTでそのまま書き込むと、朝に取得していた気温がnullで上書きされ表示が「—」になる。原因と、COALESCEで気温だけ既存値を保持する直し方を書く。</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>FLAG_KEEP_SCREEN_ON を入れても画面が黒くなるのはスクリーンセーバ</title><link>https://tech.rebounder.jp/posts/keep-screen-on-daydream/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/keep-screen-on-daydream/</guid><description>常時表示させたい Android 端末で、FLAG_KEEP_SCREEN_ON もスリープ無効も入れたのに画面が黒くなる。最有力の原因はスクリーンセーバ（Daydream）で、しかも settings put は再起動で全部元に戻る。恒久化までの手順。</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Next.js が wasm パッケージをバンドルすると本番だけ壊れる</title><link>https://tech.rebounder.jp/posts/nextjs-wasm-bundling-broken/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/nextjs-wasm-bundling-broken/</guid><description>PDF生成用WASMライブラリがNext.jsにバンドルされ、本番だけpathの型エラーで壊れた。原因はバンドルするとwasmの相対パス解決が変わること。serverExternalPackagesで外部化し、素のrequireで読ませる直し方まで書く。</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>本番だけ SECURITY DEFINER 関数が効かないのは実行ロールのせい</title><link>https://tech.rebounder.jp/posts/security-definer-owner-role/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/security-definer-owner-role/</guid><description>CI では通るのに本番だけ SECURITY DEFINER 関数が期待どおり動かない。関数のオーナーはマイグレーションを実行したロールになるため、非特権ロールで流すと RLS をバイパスできず常に0行が返る。確認 SQL と是正手順、そして再発しない形まで。</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>動画の静止を ffmpeg で検出するとき、閾値はビット深度で変わる</title><link>https://tech.rebounder.jp/posts/static-frame-threshold-bitdepth/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/static-frame-threshold-bitdepth/</guid><description>tblend と signalstats で静止フレームを機械的に検出するときの落とし穴。YAVG の閾値は輝度のレンジに比例するため、12bit で使っていた 4.8 を 10bit の素材にそのまま当てると判定が丸ごと狂う。実測値と確認手順。</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>supabase-js の条件付き UPDATE は error を見ないと処理済み判定を誤る</title><link>https://tech.rebounder.jp/posts/supabase-update-error-swallowed/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/supabase-update-error-swallowed/</guid><description>Stripe決済の冪等化に使う条件付きUPDATEは、対象0件のとき data:null と error を両方返す。data だけ見て error を捨てると、一時的な書込失敗を「既に処理済み」と誤認し、入金を検知したのに領収書発行を永久にスキップする。throw して Stripe の再配信に載せる直し方まで書く。</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>terraform の enabled = false では環境を撤去できない</title><link>https://tech.rebounder.jp/posts/terraform-enabled-false-cannot-destroy/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/terraform-enabled-false-cannot-destroy/</guid><description>モジュールに enabled フラグを持たせた構成で、環境を畳もうと一括して false にすると Invalid template interpolation value で落ちます。module 呼び出しは評価され続けるため出力が null になるのが原因で、撤去は destroy でしか行えません。</description><pubDate>Sun, 16 Aug 2026 00:00:00 GMT</pubDate></item><item><title>AI コーディングツールを一通り使って落ち着いた使い分け</title><link>https://tech.rebounder.jp/posts/ai-coding-tools/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/ai-coding-tools/</guid><description>Claude Code・Cursor・Codex・Gemini を実際に使い分けた結果。複雑な開発とサッと作るものを分け、日常の相棒は別に置く。強いツールほどコストが溶けるという正直な体感も含めて。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>アイキャッチを画像生成で量産するプロンプトの型</title><link>https://tech.rebounder.jp/posts/ai-eyecatch-template/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/ai-eyecatch-template/</guid><description>毎回ゼロから考えず、主役を大きく・下部にタイトル帯・トーンを固定、の3点を骨格にして主役とタイトルだけ差し替える。日本語が崩れる限界と、偽の実機写真を作らない線引きも。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Cloud Run Job はイメージが凍る。直したのに直らない理由</title><link>https://tech.rebounder.jp/posts/cloud-run-job-image-frozen/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/cloud-run-job-image-frozen/</guid><description>ソースを直して commit しても Cloud Run Job には届かない。job が使うイメージは tag で固定されているため、bump して apply しない限り古いコードが動き続ける。実行前の確認手順と、その場をしのぐ env 上書きまで。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>3Dモデルをマウスでこねるのをやめてコードで書く</title><link>https://tech.rebounder.jp/posts/code-cad-3dprint/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/code-cad-3dprint/</guid><description>OpenSCAD と Python で寸法を数値で書き、形を数式で決める。パラメータを変えるだけで寸法違いが量産でき、git で差分管理もできる。作例2つと、STL を手書きするときの法線の罠。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>FPGA 入門ボードに DE10-Lite を選ぶ理由</title><link>https://tech.rebounder.jp/posts/de10-lite-fpga-intro/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/de10-lite-fpga-intro/</guid><description>スイッチ・LED・7セグが基板に載っているので、外付け配線なしで書いた回路がすぐ動く。文法が C に近く、結果が目に見える。入門で効くのはこの2点だった。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>DeepL と Whisper は地味に時間を生む</title><link>https://tech.rebounder.jp/posts/deepl-whisper/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/deepl-whisper/</guid><description>派手さはないが確実に効く2本。英語は書く前に日本語で書いて整えるほうが速く、文字起こしはローカルで動かせるとクラウドに送らずに済む。実装に組み込むならこの差が効く。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>個人開発のインフラを用途で使い分ける</title><link>https://tech.rebounder.jp/posts/dev-infra-choice/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/dev-infra-choice/</guid><description>Vercel・Firebase・Supabase・GCP をどう選ぶか。最初から全部を使いこなす必要はなく、手軽なほうから始めて必要になったら広げる順番のほうが、実際には早く進む。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>開発機の発熱とバッテリーは二択になる</title><link>https://tech.rebounder.jp/posts/dev-laptop-heat-battery/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/dev-laptop-heat-battery/</guid><description>ThinkPad X1 Carbon を開発機として使うと、涼しさと電池持ちが両立しない。電源モードの切り替えで一方を選ぶことになる。使う場所を先に決めれば、この二択は表に出なくなる。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>ESP32 のセンサ値を Web Serial でブラウザに出す</title><link>https://tech.rebounder.jp/posts/esp32-web-serial/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/esp32-web-serial/</guid><description>Arduino IDE のシリアルモニタは数字が流れるだけで見づらい。Next.js と Web Serial API でブラウザの計器盤にする構成と、セキュアコンテキストやユーザー操作起点といった制約のまとめ。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>同じアプリを Firebase と Supabase の両方で作った</title><link>https://tech.rebounder.jp/posts/firebase-to-supabase/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/firebase-to-supabase/</guid><description>個人開発のバックエンドで迷うなら、Firebase は立ち上げの速さ、Supabase は自由度で選ぶ。同じアプリを両方で作り直して見えた素直な住み分けと、乗り換える順番について。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>最初の3Dプリンタは組立済みと自動レベリングで選ぶ</title><link>https://tech.rebounder.jp/posts/first-3d-printer/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/first-3d-printer/</guid><description>入門で挫折する場所は造形ではなく、組み立てと水平出しにある。95%組立済みと完全自動レベリングを条件にすると、最初の1個を出すまでの距離が大きく縮む。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Google TV をキオスク化して数ヶ月運用した記録</title><link>https://tech.rebounder.jp/posts/googletv-kiosk-ops/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/googletv-kiosk-ops/</guid><description>Android 端末を24時間落ちないサイネージ専用機にする作業は、表示ではなく電源と権限の問題だった。Device Owner の前提条件、無言で死ぬ権限、コマンドで消せないタイマー、設定を黙って無視する機種まで。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>ロゴと名刺なら Figma で足りる</title><link>https://tech.rebounder.jp/posts/illustrator-to-figma/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/illustrator-to-figma/</guid><description>Figma は本来 UI のツールだが、ベクターなのでロゴや名刺のレベルなら普通に成立する。細かいパス仕事と印刷入稿では専用ツールに分があるという線引きも含めて。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Ollama でローカル LLM を動かして RAG を組む</title><link>https://tech.rebounder.jp/posts/local-llm-rag/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/local-llm-rag/</guid><description>外部 API にデータを投げたくない場面でローカル LLM は現実的な選択肢になる。Qwen を Ollama で動かして専門分野の RAG を組んだ構成と、モデルより検索側の設計が効くという結論。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>3Dプリントでサポートが外れないときに変える2箇所</title><link>https://tech.rebounder.jp/posts/orcaslicer-support/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/orcaslicer-support/</guid><description>OrcaSlicer 自体は初期設定でもきれいに出る。初心者が最初に折れるのはサポートで、ツリータイプにして密度を下げるだけで、造形物を傷つけずに外せるようになる。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Raspberry Pi 5 で顔認証を組んで速度の壁に当たった</title><link>https://tech.rebounder.jp/posts/pi5-face-recognition/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/pi5-face-recognition/</guid><description>face_recognition と CSV だけの最小構成で顔認証は動く。ただし1人あたり約15秒かかり、人数が増えると行列になる。動くことと実用になることの間にある距離の話。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Raspberry Pi Pico で力率計を自作する</title><link>https://tech.rebounder.jp/posts/pico-power-meter/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/pico-power-meter/</guid><description>力率は電圧と電流の位相差で決まる。クランプ式の非侵襲センサで電流波形を取り、Pico 側で計算する構成と、実際に一番詰まったのが測定原理ではなく通信だった話。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Quartus で最初に詰まるのは回路ではなく環境</title><link>https://tech.rebounder.jp/posts/quartus-first-traps/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/quartus-first-traps/</guid><description>書き込み機が認識されない、ピン配置の漏れでコードが正しいのに動かない、7セグが 0 で点灯する。DE10-Lite と Quartus で最初に踏む3つと、実際に書いた Verilog 作例。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>サイネージ端末は Google TV か Raspberry Pi か</title><link>https://tech.rebounder.jp/posts/signage-android-vs-raspi/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/signage-android-vs-raspi/</guid><description>常時表示の端末を自作するとき、Android の Google TV と Raspberry Pi では設計思想が正反対になる。両方で組んで運用した結果と、24時間運用で共通して効いてくるストレージの話。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>SwitchBot 人感センサを Hub なしで BLE 直読みする</title><link>https://tech.rebounder.jp/posts/switchbot-ble-direct/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/switchbot-ble-direct/</guid><description>SwitchBot の人感センサは Hub とクラウドを前提に使うものだが、BLE アドバタイズを直接受信すればローカルだけで完結する。実装の要点3つと、位置情報権限が無いと無言で0件になる罠まで。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>タスク管理は入れる摩擦をゼロにすると続く</title><link>https://tech.rebounder.jp/posts/todoist-natural-language/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/todoist-natural-language/</guid><description>Todoist を AI から自然言語で操作できるようにしたら、手を止めずにタスクが増えるようになった。貯める側と捌く側を分ける発想と、通知を見に行かずメールへ流す設計。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>ハードを触るなら開発機を物理的に分ける</title><link>https://tech.rebounder.jp/posts/two-laptops-hardware-dev/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/two-laptops-hardware-dev/</guid><description>ノートPCの2台持ちは贅沢ではなくリスク管理だった。シリアルチップのドライバとポートの都合、そして配線ミスで壊れうる作業と壊れて困るデータを切り離すという理由。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item><item><title>Vercel で公開してから気づいた3つの落とし穴</title><link>https://tech.rebounder.jp/posts/vercel-deploy-traps/</link><guid isPermaLink="true">https://tech.rebounder.jp/posts/vercel-deploy-traps/</guid><description>Vercel へのデプロイ自体はつまずかない。問題はその先で、エイリアスが最新版を指さない、公開URLがログインを要求する、検索に載らない、の3点はドキュメントを読むだけでは見落とす。</description><pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate></item></channel></rss>