Cycle 5 までで、ミセバンAIは技術的に「動くプロダクト」になった。AI推論、DB永続化、リアルタイム通知、Stripe決済、プラン制限。しかし、日本でSaaSを公開するには「法的ページ」が必須だ。
Sprint Cycle 6 では3つの法務ページ (プライバシーポリシー・利用規約・特商法表記) を整備し、ダッシュボードに4ステップのオンボーディングウィザードを実装。セキュリティの強化も行い、クローズドベータ開始の準備を完了した。
1. なぜ法務ページが先なのか
日本でSaaSを公開・課金する場合、以下の法令対応が不可欠だ。
- 個人情報保護法 -- カメラ映像は個人情報に該当し得る。取得目的、利用範囲、第三者提供の有無を明示する義務がある
- 特定商取引法 -- オンラインでサブスクリプションを販売する事業者は、販売者の表示義務がある
- 電気通信事業法 -- 映像データをクラウドで処理する場合の通信の秘密保護
法務ページなしにクローズドベータを開始すると、初期ユーザーの信頼を損なう。特にカメラ映像を扱うサービスでは「映像データはどう扱われるのか」がユーザーの最大の関心事だ。技術の前に信頼。これが Cycle 6 の判断だ。
2. 法務ページ -- 3つのコンプライアンス文書
プライバシーポリシー
個人情報保護法準拠。カメラ映像の取得・処理・保存・削除ポリシーを明記。AI推論結果の取り扱いも含む。
利用規約
SaaS利用条件、料金プランと支払い条件、禁止事項、免責事項、解約・退会手続きを規定。
特定商取引法に基づく表記
販売事業者名、所在地、連絡先、料金、支払方法、サービス提供時期、返金ポリシーを記載。
プライバシーポリシー
カメラ映像を扱うAIサービスとして、特に重視した項目。
- カメラ映像の取り扱い -- 映像はAI推論に使用後、プランに応じた保持期間で自動削除。生映像はクラウドに永続保存しない
- AI推論結果の扱い -- 人数カウント、属性分析等の統計データは個人を特定しない形式で保存
- 第三者提供の制限 -- ユーザーの同意なく映像データを第三者に提供しない。AI学習への利用もオプトアウト可能
- Cookie・アクセスログ -- Supabase Authのセッション管理、アクセス解析の目的と範囲
- 開示・削除請求 -- 個人情報保護法に基づく開示・訂正・削除の手続きを明記
<!-- privacy.html -- カメラ映像セクション抜粋 -->
<section class="legal-section">
<h2>4. カメラ映像データの取り扱い</h2>
<p>当社は、お客様が接続したカメラから送信される
映像フレームを以下の目的で処理します。</p>
<ul>
<li>AI推論による来客数カウント、属性分析、行動分析</li>
<li>アラート(侵入検知、混雑検知等)の判定</li>
<li>ダッシュボードへの分析結果の表示</li>
</ul>
<p>映像フレームはAI推論完了後、ご契約プランに応じた
保持期間(Free: 7日、Starter: 30日、Pro: 90日、
Enterprise: 最大10年)を経過した時点で自動削除されます。</p>
</section>
利用規約
- 料金プランと変更 -- 4プランの内容、プラン変更時の日割り計算ルール
- 禁止事項 -- 公序良俗に反する映像の処理、他人のカメラへの不正接続、リバースエンジニアリング
- SLA -- 月間稼働率99.5%目標。計画メンテナンスは48時間前通知
- 解約・退会 -- Stripe Customer Portal から即時解約。データは30日以内に完全削除
- 免責事項 -- AI推論の精度保証なし。防犯目的の利用は補助手段としての位置づけ
特定商取引法に基づく表記
- 販売事業者 -- 事業者名、代表者、所在地、電話番号
- 販売価格 -- Free ¥0 / Starter ¥9,800 / Pro ¥29,800 / Enterprise ¥49,800 (税込)
- 支払方法 -- クレジットカード (Stripe経由)
- 役務の提供時期 -- 登録完了後、即時利用可能
- 返金ポリシー -- サブスクリプション型のため、当月分の返金は不可。翌月以降の課金停止は即時
3. オンボーディングウィザード -- 初回体験を設計する
法務ページが「信頼」なら、オンボーディングは「体験」だ。初回ログインからカメラ接続までの導線が悪いと、Free ユーザーは価値を体感する前に離脱する。
Welcome
ミセバンAIへようこそ。サービスの概要と3つのステップを説明。
Store Info
店舗名、業種、住所を入力。これがダッシュボードの基本情報になる。
Camera Setup
カメラのRTSP URLを入力して接続テスト。映像が届けば成功。
Done!
セットアップ完了。CSS-only紙吹雪アニメーションで達成感を演出。
4ステップ オンボーディングウィザード
- ステップ管理 --
currentStepstate で1-4を管理。戻る/進むボタンで遷移 - CSS-only 紙吹雪 -- Step 4 到達時に
@keyframes confettiを発火。JSライブラリ不要 - localStorage 永続化 --
miseban_onboarding_doneフラグで2回目以降はスキップ - バリデーション -- 各ステップの入力値を次へ進む前に検証
// オンボーディングウィザード -- コア実装
const STORAGE_KEY = 'miseban_onboarding_done';
function initOnboarding() {
// 既に完了済みならスキップ
if (localStorage.getItem(STORAGE_KEY) === 'true') return;
let currentStep = 1;
const totalSteps = 4;
const overlay = createOverlay();
function renderStep(step) {
switch (step) {
case 1: return renderWelcome();
case 2: return renderStoreInfo();
case 3: return renderCameraSetup();
case 4: return renderComplete();
}
}
function nextStep() {
if (!validateStep(currentStep)) return;
currentStep = Math.min(currentStep + 1, totalSteps);
overlay.innerHTML = renderStep(currentStep);
if (currentStep === totalSteps) triggerConfetti();
}
function complete() {
localStorage.setItem(STORAGE_KEY, 'true');
overlay.remove();
}
// 初期表示
document.body.appendChild(overlay);
overlay.innerHTML = renderStep(1);
}
CSS-only 紙吹雪アニメーション
/* CSS-only confetti -- JSライブラリ不要 */
@keyframes confetti-fall {
0% { transform: translateY(-100vh) rotate(0deg); opacity: 1; }
100% { transform: translateY(100vh) rotate(720deg); opacity: 0; }
}
.confetti-piece {
position: fixed;
width: 10px;
height: 10px;
top: -10px;
animation: confetti-fall 3s ease-in-out forwards;
}
.confetti-piece:nth-child(odd) { background: var(--indigo-500); }
.confetti-piece:nth-child(even) { background: var(--amber-500); }
/* 20個の紙吹雪を異なるタイミング・位置で配置 */
.confetti-piece:nth-child(1) { left: 5%; animation-delay: 0s; }
.confetti-piece:nth-child(2) { left: 15%; animation-delay: .1s; }
.confetti-piece:nth-child(3) { left: 25%; animation-delay: .2s; }
/* ... 20個まで展開 */
紙吹雪は純粋CSSで実装した。canvas-confetti 等の外部ライブラリを入れる選択肢もあったが、オンボーディングの最終ステップだけで使う演出に npm パッケージを追加するのはオーバーキル。20個の div と @keyframes だけで十分な達成感を演出できる。
4. セキュリティ強化
セッション管理・自動リダイレクト
- 401 自動リダイレクト -- APIが401を返したらログインページに自動遷移。セッション切れの UX を改善
- 5分間隔セッション検証 --
setIntervalでSupabaseにセッション有効性を問い合わせ。トークン失効を早期検知 - キーボードショートカット --
?キーでオーバーレイ表示。Shift+Dでダッシュボード、Shift+Aでアラートへ遷移
// セッション検証 -- 5分間隔
const SESSION_CHECK_INTERVAL = 5 * 60 * 1000; // 5分
function startSessionWatcher() {
setInterval(async () => {
const { data: { session }, error } = await supabase.auth.getSession();
if (error || !session) {
console.warn('Session expired, redirecting to login');
window.location.href = '/dashboard/login.html';
}
}, SESSION_CHECK_INTERVAL);
}
// 401 インターセプター
async function apiFetch(url, options = {}) {
const res = await fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${getAccessToken()}`,
},
});
if (res.status === 401) {
window.location.href = '/dashboard/login.html';
return;
}
return res;
}
apiFetch はダッシュボード内の全API呼び出しを統一するラッパー関数だ。認証ヘッダーの付与と 401 ハンドリングを集約することで、各ページでの個別実装を排除した。
5. Before / After -- ベータ開始前後の比較
| 項目 | Cycle 5 (Before) | Cycle 6 (After) |
|---|---|---|
| 法務ページ | なし (フッターリンクは # 空リンク) | privacy / terms / legal 3ページ完備 |
| 初回体験 | ログイン後いきなりダッシュボード | 4ステップウィザードで丁寧に誘導 |
| セッション管理 | トークン切れで無言のエラー | 5分検証 + 401自動リダイレクト |
| キーボード操作 | なし | ショートカットオーバーレイ |
| オンボーディング永続化 | なし | localStorage で完了フラグ管理 |
6. クローズドベータ開始チェックリスト
Cycle 1-6 の成果を総合すると、クローズドベータに必要な項目がすべて揃った。
6つのスプリントサイクルを経て、「技術デモ」から「ベータ公開可能なプロダクト」になった。法務、課金、オンボーディング。地味だが、これが本物のプロダクトと個人プロジェクトを分ける境界線だ。
7. 技術的判断
なぜこの設計にしたか
- 法務ページは静的HTML -- CMSやMarkdownからの生成ではなく、プレーンHTMLで作成。法務テキストの更新頻度は低く、ビルドパイプラインの複雑さを増やす理由がない
- CSS-only 紙吹雪 -- 外部ライブラリ依存を避け、数KBのCSSで実装。バンドルサイズを増やさない
- localStorage で永続化 -- オンボーディング完了フラグはサーバーに保存しない。個人デバイスのローカルで十分。DB往復を減らす
- 5分間隔のセッション検証 -- リアルタイムチェックは過剰。5分間隔で十分にセッション切れを検知でき、API負荷も最小限
- apiFetch ラッパー -- 認証処理を1箇所に集約。将来のリフレッシュトークン対応も、この関数だけ修正すれば済む
8. 成果と数字
作成・更新したファイル
web/landing/privacy.html-- プライバシーポリシー (新規、約180行)web/landing/terms.html-- 利用規約 (新規、約160行)web/landing/legal.html-- 特定商取引法に基づく表記 (新規、約100行)web/dashboard/onboarding.js-- オンボーディングウィザード (新規、約150行)web/dashboard/auth.js-- セッション検証 + 401リダイレクト (+60行)web/dashboard/index.html-- オンボーディング統合 + ショートカット (+50行)
9. 次のサイクルで何をするか
Cycle 7 ではいよいよクローズドベータテストを開始する。実際の店舗にカメラを接続し、本物の来客データでAI推論の精度を検証する。テスト環境と本番環境のギャップ、カメラ設置角度による精度変動、LINE通知の配信遅延。実データでしか見えない課題を洗い出すフェーズだ。
法務ページとオンボーディング。華やかさはないが、ユーザーの「信頼」と「体験」を支える基盤だ。この地味な仕事を飛ばしたプロダクトは、市場で必ずつまずく。
クローズドベータに参加しませんか? 実店舗での AI 見守りを一緒に検証しましょう。
ミセバンAIは、スプリントサイクルで高速に進化中。
既存の防犯カメラがAI店長に変わる、小規模店舗のための次世代AI分析。