Specification

nia-shift 仕様書

シフト管理Webアプリ「nia-shift(Pegasasu-Shift)」のCloudflare版(現行本番)についての詳細仕様書。実際のソースコード(cloudflare-app/)を精査し、動作を正確に記述している。

対象バージョン cloudflare-app (2026-09時点の本番コード) 本番URL pegasasu-shift.pages.dev ソース GitHub private repo: nia-shift-cloudflare 作成日 2026-09-27

0概要

nia-shiftは、複数の販路(営業チーム/拠点)を掛け持ちするメンバーのシフトを管理し、翌日・当日の稼働メンバーをLINE/Chatworkへ自動通知するWebアプリ。元はGoogle Apps Script(GAS) + Google Sheetsで構築されていたが、現在はCloudflare Pages + D1(SQLite互換)へ完全移植されている(§10 開発の経緯参照)。

  • メンバーは「販路(SalesChannels)」に所属し、日付ごとに「稼働 / 休み / 連絡不可」のいずれかのステータスでシフトを登録する
  • 管理者・一般ユーザーの権限に加えて、5段階の「役職(New Beginner〜Owner)」で表示・操作範囲が変わる
  • 15分おきのバッチ(notify-worker)が、販路ごと・全体まとめの両方でLINE/Chatworkに自動通知を送る
  • 全操作(作成・更新・削除)はShiftHistoryテーブルに変更履歴として記録される

1技術スタック

領域技術備考
フロントエンド素のHTML + CSS + JavaScript(public/index.html 1ファイル)フレームワーク不使用。約3,760行のSPA
バックエンドAPICloudflare Pages Functionsfunctions/api.js。/apiへの単一POSTエンドポイント(RPC方式)
データベースCloudflare D1(SQLite互換)8テーブル。wrangler.tomlでDBとしてバインド
定期実行バッチ独立したCloudflare Worker(notify-worker/)Cron Trigger(*/15 * * * *)。Pages Functions単体はCronを扱えないため分離
認証Web Crypto API(HMAC-SHA256 / SHA-256)Node標準crypto非使用。Workers環境向けに自前実装(functions/lib/auth.js)
外部通知連携LINE Messaging API / Chatwork APIトークンはCloudflare環境変数で管理
祝日データGoogleカレンダー公開iCalフィード都度fetch・パースのみ(DB保存なし)
ホームアイコン起動Firebase Hosting(別プロジェクト)standalone起動時に本体URLへ自動転送するだけの薄いページ

2アーキテクチャ

リクエストは大きく2系統。(A) ブラウザ→Pages Functions→D1 のオンデマンドAPI呼び出しと、(B) notify-worker→D1/外部API のバッチ通知。両者は同じD1データベース(nia-shift-db)を共有するが、デプロイ単位(Pages / Worker)は別々。

(A) オンデマンドAPIフロー

Browserpublic/index.html(SPA)
→ fetch('/api', {fn, args}) →
Pages Functionsfunctions/api.js
onRequestPost
→
D1nia-shift-db
応答は常に { ok: true, result } か { ok: false, error } のJSON。HTTPステータスは基本200固定(JSONパース失敗時のみ400)

(B) 通知バッチフロー(15分おき)

Cron Trigger*/15 * * * *
→
notify-workerscheduled()
→
D1Shifts / Destinations / Settings 読み取り
→
LINE / Chatwork API該当時刻のみ送信

同時に期限切れセッション(Sessionsテーブル)の削除も毎回実行される。

リクエスト方式の特徴

  • RESTではなくRPC方式: POST /api のボディに { fn: "api_xxx", args: [...] } を渡し、functions/api.js内の同名関数をそのまま呼び出す(GAS版のWebApp.jsを踏襲した設計)
  • 認証情報(teamToken / セッションtoken)は毎回のargsの先頭付近で明示的に渡す方式(Cookie不使用)。ブラウザ側はlocalStorageに保存して都度読み出す

3ディレクトリ構成

cloudflare-app/ 配下(現行本番のソース一式。GitHubリポジトリのルートと一致)。

cloudflare-app/ ├── public/ # Cloudflare Pagesの配信ルート(そのままデプロイされる) │ ├── index.html # アプリ本体。画面・状態管理・API呼び出しを含む単一ファイルSPA │ └── spec.html # この仕様書(本ファイル) ├── functions/ # Cloudflare Pages Functions(サーバーサイド) │ ├── api.js # /api の全エンドポイント定義(32関数)。認可チェックもここに集約 │ └── lib/ │ ├── auth.js # Web Crypto APIでのteamToken署名/検証・パスワードハッシュ │ ├── config.js # テーブル名・役職・権限などの定数定義 │ ├── dates.js # JST日付変換・表示フォーマット │ ├── db.js # D1クエリの薄いラッパー(SELECT/INSERT/UPDATE組み立て) │ ├── repositories.js # User/SalesChannel/Destination/Shift/SessionのCRUD │ └── notifications.js # 通知メッセージ組み立て・LINE/Chatwork送信・ログ記録 ├── notify-worker/ # 15分おき通知バッチ(独立したCloudflare Worker) │ ├── index.js # Cron本体。functions/lib配下のロジックをimportして再利用 │ └── wrangler.toml # Cron設定 + D1バインド(Pages側と同じdatabase_id) ├── migrations/ │ └── 0001_init.sql # D1の全テーブルDDL(このリポジトリで唯一のDBスキーマ定義) ├── scripts/ │ └── migrate-from-sheets.cjs # 旧GAS/Sheets環境からD1へのワンタイム移行データ生成スクリプト ├── wrangler.toml # Pages側の設定(pages_build_output_dir, D1バインド) ├── package.json # devDependency: wrangler / dependency: googleapis(移行スクリプト専用) └── README.md # セットアップ手順・環境変数一覧
備考: migrations/9999_migrate_data.sql(実データ生成物)と db-dump.html / infra-map.html はリポジトリのルート(cloudflare-app/直下)にローカルでのみ存在し、.gitignoreでGit管理対象外。理由は§12を参照。

4データモデル

D1(SQLite)上の8テーブル。全てmigrations/0001_init.sqlで定義され、列名は日本語(GAS版のSheetsヘッダーをそのまま踏襲)。

4.1 Users(メンバー)

列型内容
UserIDTEXT PKUSR-<timestamp>-<random>形式で自動採番
氏名 / よみがなTEXT表示名・ふりがな(あいまい検索・五十音ソートに使用)
所属販路IDTEXTメインで所属する販路(SalesChannels.販路ID)
権限TEXT管理者 / 一般の2値
役職TEXTNew Beginner / Beginner / Leader / Manager / Owner の5段階(§5)
直属リーダーUserIDTEXT樹形図表示・並び替えの親子関係に使用
優先順位INTEGER同グループ内の任意の表示順(未設定可)
自分を先頭表示INTEGER(0/1)グリッドで自分の行を常に先頭に固定表示するか
PasswordHash / PasswordSaltTEXTSHA-256(salt + password)。ソルトはcrypto.randomUUID()
メールアドレスTEXT現行フローでは未使用(GAS版のGoogleアカウント認証の名残。常に空文字)

4.2 SalesChannels(販路マスタ)

列内容
販路IDPK。CH-<timestamp>-<random>
販路名 / 表示順一覧・グリッドでの並び順
商材 / 備考① / 備考② / クライアント / 場所すべて自由記述の付帯情報

4.3 Shifts / ShiftHistory

列内容
ShiftIDPK。SFT-<timestamp>-<random>
日付yyyy-MM-ddのプレーン文字列(タイムゾーン変換はJS側で行う)
UserID / 販路ID誰の・どの販路のシフトか
ステータス稼働 / 休み / 連絡不可
開始時刻 / 終了時刻ステータス=稼働の時のみ値を持つ(他の値に変更すると自動でクリアされる。_normalizePatch)
備考自由記入。連絡不可の理由もここに統一
更新日時 / 更新者UserID保存のたびに自動更新
ShiftHistory(変更履歴。Shiftsの操作ごとに自動追記)
HistoryIDPK。HIS-<timestamp>-<random>
ShiftID / 変更日時 / 変更者UserID対象・タイミング・実行者
変更項目列名、または新規作成 / 削除
変更前 / 変更後作成時は変更前が空、削除時は変更後が空でJSON文字列を格納
更新(update/updateKnown)は、変更前後を列ごとに文字列比較し、差分があった列だけ1行ずつShiftHistoryに追記する。新規作成・削除は1行にまとめてJSON化して記録する。

4.4 Destinations(通知送信先)

販路1つにつき1行。「翌日通知」と「当日通知」それぞれ独立した送信先・有効フラグ・通知時刻を持つ(列名の先頭に当日が付くかどうかで区別)。

列(翌日分)列(当日分)内容
LINEグループID当日LINEグループIDLINE Messaging APIの送信先グループID
ChatworkルームID当日ChatworkルームIDChatworkの送信先ルームID
有効フラグ当日有効フラグ0/1。無効な販路は通知バッチでスキップ
通知時刻 / 通知分当日通知時刻 / 当日通知分0〜23時・0/15/30/45分の15分刻みで指定。未設定時は18:00がデフォルト

4.5 NotificationLogs / Settings / Sessions

テーブル役割
NotificationLogs全通知送信の成否ログ(日時・販路ID・LINE/Chatwork種別・成否・本文・エラー内容)。販路ID='ALL'は全体まとめ通知
SettingsKey/Value型の汎用設定テーブル。オーナーUserID・全体まとめ通知の設定(送信先・時刻・有効フラグ、翌日/当日分)を保持
Sessions個人ログインセッション(Token PK、有効期限1週間)。notify-worker実行のたびに期限切れ行を自動削除

5認証・権限モデル

nia-shiftには独立した3層の権限チェックがある。(1) チーム全体のゲート、(2) 個人ログイン(セッション)、(3) 役職・特定アカウントによる操作制限。

5.1 チームゲート(teamToken)

  • 全メンバー共通の「チームパスワード」(Cloudflare環境変数ACCESS_PASSWORD)をapi_verifyTeamAccessに渡して検証
  • 成功するとissueTeamToken()が base64url(expiresAt.HMAC-SHA256(expiresAt, TEAM_TOKEN_SECRET)) 形式の署名付きトークンを発行(有効期限6時間)
  • ブラウザはlocalStorage["niaShiftTeamToken"]に保存し、以降の閲覧系API呼び出し全てに付与する
  • サーバー側はverifyTeamToken()で署名のタイミングセーフ比較と有効期限を検証する(functions/lib/auth.js)
  • 他チーム(第三者)からの閲覧を防ぐための「入口の鍵」であり、個人の識別はしない

5.2 個人ログイン(セッション)

  • 名前を選択 + 個人パスワードでapi_login → SHA-256(salt + password)をPasswordHashと比較
  • 一致するとSessionsテーブルにトークンを発行(有効期限1週間)。localStorageに保存
  • 名前とパスワードは両方空欄でも入場可能(閲覧のみモード)。その場合state.tokenはnullのままで、編集系APIは全て拒否される
  • 新規メンバーは「新規登録」(api_register)からセルフサインアップ可能。ただし管理者ログイン中でないと実行できない(_assertAdmin)

5.3 役職(JOB_RANK)による操作範囲

New Beginner< Beginner< Leader< Manager< Owner
  • New Beginner / Beginner: グリッドで他の New Beginner ランクのメンバーが非表示になる(_visibleUsersFor)。新人同士の相互閲覧を制限する設計
  • Leader以上: 販路の新規作成・編集が可能(_assertLeaderOrAbove)。それ未満は閲覧のみ
  • 役職は権限(管理者/一般)とは独立した軸。一般ユーザーでもLeaderなら販路編集ができる

5.4 権限マトリクス

操作必要な条件
シフト閲覧teamTokenのみ(個人ログイン不要)
自分のシフト編集個人ログイン必須
他人のシフト編集権限=管理者
メンバー新規登録・編集権限=管理者
販路の新規作成・編集役職=Leader以上
販路の削除オーナー(Settings.OWNER_USER_ID)、または下記「特定アカウント」
メンバーの削除下記「特定アカウント」のみ(氏名の完全一致でハードコード)
通知送信先(Destinations)の管理下記「特定アカウント」のみ(氏名の完全一致でハードコード)
DB生データ閲覧(マスク付き)権限=管理者
注意: 「メンバー削除」と「通知送信先の管理」は役職やDB上のオーナー設定ではなく、functions/api.js内のMEMBER_DELETE_OWNER_NAME定数(特定1名の氏名の完全一致)でハードコードされている。実際の氏名はソースコード(functions/api.js冒頭)を直接確認のこと。このアカウントを削除・改名すると、誰もこれらの操作を行えなくなる。将来的には氏名ではなく役職・フラグベースのロール化を推奨。

6API リファレンス

全エンドポイントはPOST /api に { "fn": "関数名", "args": [...] } を送る単一のRPC方式(functions/api.js)。凡例: 公開=認証不要、チーム=teamToken必須、個人=セッションtoken必須、管理者=権限チェック、特定=特定アカウントのハードコード判定。

関数認可概要
api_verifyTeamAccess公開チームパスワードを検証しteamTokenを発行
api_getLoginableUserNames公開ログイン画面の名前コンボボックス用に、全ユーザーの氏名/よみがなだけ返す
api_loginチーム個人パスワード照合 → セッション発行
api_register管理者新規メンバーのセルフ登録相当(実際は管理者が代理登録)
api_updateProfile個人自分の氏名・よみがな・所属販路・パスワードを更新
api_updateSelfTopPreference個人グリッドで自分の行を先頭固定表示するか切替
api_getBootstrapチーム初期表示用の販路一覧・ユーザー一覧をまとめて取得
api_getShiftsチーム指定期間のシフトを取得(閲覧可能ユーザーのみにフィルタ)
api_getHolidaysチームGoogle祝日iCalを都度取得・パースして返す(DB非保存)
api_getShiftHistoryチーム1シフトの変更履歴一覧(新しい順)
api_saveShift個人1件のシフト作成/更新(他人分は管理者のみ)
api_bulkApplyShifts個人グリッドで複数セル選択→同一内容を一括反映
api_registerMonth個人「月まとめて登録」モーダルからの一括新規登録
api_deleteShift個人1件のシフト削除(履歴に記録)
api_getUsersAdmin管理者ユーザー管理モーダル用の詳細一覧(パスワード設定有無を含む)
api_createUser管理者管理者画面からのメンバー新規作成
api_updateUser管理者メンバー情報の更新(最後の管理者の権限降格は禁止)
api_updateAccessPassword—常にエラーを返すダミー実装(§11参照)
api_getChannelsAdminチーム販路管理モーダル用の全項目付き一覧
api_createChannelLeader以上販路の新規作成
api_updateChannelLeader以上販路情報の更新
api_deleteChannel特定販路削除。オーナー、または特定アカウントのみ
api_claimChannelOwner管理者ログイン中の管理者を「オーナー」としてSettingsに登録(未設定時のみ)
api_deleteUser管理者+特定メンバー削除。実行条件は管理者かつ特定アカウント(§5.4)
api_getDestinationsAdmin特定通知送信先一覧(特定アカウント専用)
api_updateDestination特定1販路分の通知送信先・時刻を更新
api_sendAllNotificationsNow特定スケジュールを無視して今すぐ全販路に通知送信(手動トリガー)
api_getBulkNotificationSettings特定「全体まとめ通知」設定の取得(翌日/当日分)
api_updateBulkNotificationSettings特定「全体まとめ通知」設定の更新
api_logout公開渡されたセッションtokenをSessionsから削除
api_getRawDump管理者1テーブル全行取得。PasswordHash/PasswordSaltは••••••••に自動マスク
api_getRawDumpTables管理者ダンプ可能なテーブル名一覧(許可リスト。SQLインジェクション対策)
備考: 応答は常に {ok:true, result} / {ok:false, error}。errorにはそのままError.message(日本語の文言)が入るため、フロント側はそれをそのままエラーメッセージとして表示できる。

7フロントエンド機能(public/index.html)

単一HTMLファイルのSPA。ビルド工程なし、フレームワーク不使用で、stateというグローバルオブジェクトにアプリ全体の状態を保持する素朴な設計。

7.1 入口・認証系

  • チームゲート画面: 起動時にlocalStorageのteamTokenが無効/期限切れなら必ず表示。パスワード + (任意で)個人名・個人パスワードを同時入力可能
  • 新規登録モーダル: 管理者ログイン中のみ、氏名・よみがな・所属販路・役職・直属リーダー・初期パスワードを入力してメンバー追加
  • ログインモーダル: 閲覧のみモードから編集操作をしようとした際に割り込み表示(requireLogin)
  • プロフィール編集モーダル: 自分の氏名・よみがな・所属販路・パスワード変更

7.2 シフトグリッド(メイン画面)

  • 行=メンバー、列=日付のカレンダーグリッド。週表示/月表示を切替可能(state.viewMode)
  • 並び替えは5種類: 樹形図順(直属リーダーの階層)・販路順・名前順(よみがな)・優先順位順・役職順。各々昇順/降順切替あり
  • セルの色分け: 稼働=通常色+時間表示、休み=グレー「休」、連絡不可=赤背景「連絡不可」(備考があればツールチップ表示)
  • 土日は列の背景色を変えて視認性を確保(col-sun / col-sat)
  • 祝日はAPI経由で取得し、該当日の列にマーキング

7.3 セル選択・一括編集

  • 複数セル選択モード: マウスドラッグで矩形選択 → 「一括反映モーダル」で同一のステータス/時間帯/備考をまとめて適用(api_bulkApplyShifts)
  • 詳細パネル(1セル): クリックで開き、「編集」タブと「変更履歴」タブを持つ。履歴タブは開いたときに遅延ロード

7.4 自分のシフトをまとめて操作する2つの画面

画面用途API
シフト登録モーダル(月まとめて登録)まだ登録していない日に対し、当月/翌月分をまとめて同じ稼働パターンで新規登録api_registerMonth
シフト変更モーダル既存の1ヶ月分を行ごとにその場編集(管理者は対象メンバーを切替可能)api_saveShift(行単位)

7.5 管理者向け画面

  • ユーザー管理モーダル: メンバー一覧・追加・編集・(条件付き)削除、チームパスワード変更UI(※非機能。§11)、販路削除オーナーの自認定ボタン
  • 販路管理モーダル: 販路の新規作成・編集・(条件付き)削除。Leader以上が閲覧可、編集はLeader以上
  • 通知設定モーダル: 販路ごとのLINE/Chatwork送信先・有効フラグ・送信時刻(翌日/当日別)。全体まとめ通知の設定もここに統合。「今すぐ送信」ボタンあり
  • DBダンプモーダル: 管理者がテーブルを選んで全行を閲覧(パスワード列はマスク済み)。フィルタ入力で行を絞り込み可能

8通知バッチ(notify-worker)

notify-worker/index.jsが15分おき(*/15 * * * *)にCloudflare Cron Triggerで起動し、以下4種類の通知を順に評価・送信する。

  1. sendTomorrowNotifications — 販路ごとの翌日稼働メンバー通知
  2. sendTodayNotifications — 販路ごとの当日稼働メンバー通知
  3. sendBulkAggregateNotification — 全販路まとめの翌日通知(単一のLINE/Chatwork送信先へ)
  4. sendTodayBulkAggregateNotification — 全販路まとめの当日通知

現在時刻(JST)は15分単位に切り捨て(currentJstHourMinute)、各販路/設定に登録された通知時刻と完全一致した回のみ送信する(15分粒度のスケジューラ)。一致しなければ何もしない。

メッセージ組み立てルール

  • 稼働者は「氏名 開始-終了」形式、備考があれば次の行に追記
  • 他販路がメインのメンバーが掛け持ちで入っている場合、「(掛け持ち・メインは○○)」を自動付記
  • 休みの人は「😴休みの人:」の見出しの下にまとめて列挙(備考=理由があれば併記)
  • 連絡不可の人は「本日連絡不可の人:」の見出しの下に列挙
  • 稼働者・休み・連絡不可のいずれも0件の販路は、その販路の通知自体を送らない(_buildChannelSectionがnullを返す)

送信・ログ

  • LINE: POST https://api.line.me/v2/bot/message/push(Bearer認証、LINE_CHANNEL_ACCESS_TOKEN)
  • Chatwork: POST https://api.chatwork.com/v2/rooms/{roomId}/messages(X-ChatWorkTokenヘッダー)
  • 送信結果(成功/失敗・エラー内容)は必ずNotificationLogsに1行記録される(失敗しても例外は握りつぶしログ化のみ)
  • バッチの最後にSessionRepository.removeExpired()で期限切れの個人セッションを掃除する

9デプロイ・環境変数

必要な環境変数(Cloudflare Pages: Settings > Environment variables)

変数名用途
ACCESS_PASSWORDチームゲートの共有パスワード本体
TEAM_TOKEN_SECRETteamTokenのHMAC署名鍵(ランダムな長い文字列)
LINE_CHANNEL_ACCESS_TOKEN(任意)LINE通知を使う場合。notify-worker側にも同じ値が必要
CHATWORK_API_TOKEN(任意)Chatwork通知を使う場合。notify-worker側にも同じ値が必要

D1データベースは環境変数ではなくwrangler.tomlの[[d1_databases]]でバインドする(binding = "DB")。Pages側とnotify-worker/wrangler.tomlは同一のdatabase_idを指す必要がある。

初回セットアップ手順

npx wrangler login
npx wrangler d1 create nia-shift-db
# 表示されたdatabase_idを wrangler.toml と notify-worker/wrangler.toml に設定
npx wrangler d1 execute nia-shift-db --remote --file=migrations/0001_init.sql
npx wrangler pages deploy public --project-name nia-shift
# Cloudflareダッシュボードで環境変数を設定 → 再デプロイ
cd notify-worker && npx wrangler deploy

日常のデプロイ

npm run deploy   # = wrangler pages deploy public --project-name nia-shift
npm run migrate  # = wrangler d1 execute nia-shift-db --file=migrations/0001_init.sql
notify-workerはPagesのデプロイに含まれない。notify-worker/index.jsを変更した場合はcd notify-worker && npx wrangler deployを別途実行する必要がある。

10開発の経緯

フェーズ構成状態
1. GAS版Google Apps Script + Google Sheets DB + HTML Serviceレガシー・参考(更新停止)
2. Netlify検討版netlify-app/(このリポジトリには含まれない)採用見送り
3. Cloudflare版(現行)Pages + Functions + D1 + Worker本番稼働中

GAS版からのデータ移行はscripts/migrate-from-sheets.cjs(Google Sheets APIで全シート読み込み→INSERT文生成)を1回だけ実行し、生成されたmigrations/9999_migrate_data.sqlをwrangler d1 execute --remoteでD1へ反映した。以後このスクリプトの再実行は想定していない(ワンタイム移行ツール)。

Cloudflare化に伴う主な設計変更: D1へのSQL直接クエリ化(全件取得+JSフィルタの廃止による高速化)、祝日データをGoogle公開iCalの都度取得に変更、15分おき通知を独立Workerへ分離。

11既知の制限・注意点

  • チームパスワード変更UIが非機能: ユーザー管理モーダルに「チームパスワードの変更」欄が存在するが、対応するapi_updateAccessPasswordは常にエラーを返すダミー実装。実際の変更はCloudflare環境変数ACCESS_PASSWORDを書き換えて再デプロイする必要がある。UIを削除するか、実装を合わせるかの整理が望ましい
  • 権限のハードコード: メンバー削除・通知送信先管理が特定1アカウントの氏名文字列に紐づいている(§5.4)。改名・退職時に運用が詰まるリスクがある
  • パスワードハッシュ方式: SHA-256(salt + password)はソルト付きだが、bcrypt/scrypt/Argon2のような低速化ハッシュではないため、DBが漏洩した場合のオフライン総当たりへの耐性は高くない。社内利用・低脅威モデルとしては許容範囲だが、より強固にする余地はある
  • teamTokenの性質: 個人を識別しない共有シークレット方式のため、退職者が把握しているチームパスワードは変更されるまで有効であり続ける
  • 祝日取得の外部依存: Googleの公開iCalフィードが仕様変更・停止した場合、祝日表示機能のみ静かに失敗する(グリッド自体は表示される)
  • RPC方式ゆえの型安全性: fn文字列とargs配列の順序はフロント/バック双方で手動同期が必要。関数シグネチャ変更時は両ファイルの整合を目視確認する必要がある

12セキュリティ対応履歴

2026-09-27: リポジトリ作成時、初回コミットに実在するスタッフの氏名・パスワードハッシュ・ソルト・シフト実績を含む migrations/9999_migrate_data.sql が誤って含まれていたことが判明。同日中に以下の対応を実施済み:
  • 該当ファイルをリポジトリから削除し、.gitignoreに追加(以後追跡対象外)
  • 初回コミットのみだったためgit commit --amend + git push --forceでGitHub上の履歴自体からも完全に除去(force push時点で他者によるcloneは無し)
  • 同様に実データ/内部情報を含むdb-dump.html・infra-map.html(チームパスワード等を平文記載)もGit管理対象外に設定
  • 運用基盤マップ(infra-map.html)経由でスタッフに共有する版は、既存のチームゲート認証(§5.1)を流用してアクセス制限をかけた上で公開

今後、実データを含む生成物(SQLダンプ・エクスポート等)を扱う際は、コミット前にgit statusで差分内容を確認することを推奨する。

本仕様書は実際のソースコード(functions/, public/index.html, notify-worker/, migrations/)を精査して作成。コードと本書に差異がある場合はコードを正とする。