Skip to content

KIZAMI 要件定義書 ​

  • 版: Draft 4(2026-08-21)
  • 名称: KIZAMI(刻み — 1分単位で時を刻む。npm kizami 未使用確認済み)

1. 目的とポジショニング ​

日本の労働法制(労働基準法)に準拠した出退勤打刻型の勤怠管理システムを、セルフホスト可能なOSSとして開発・公開する。開発者自身の技術学習(TypeScriptスタックの深化)を主目的としつつ、最終的には一般企業が社内利用できる品質を目指す。

自作の動機は既存セルフホストOSS(Kimai、solidtime、TimeTagger等)への不満・不足。既存製品は工数トラッキング寄りで、日本の勤怠慣行 — 1分単位把握、法定内/法定外・深夜・法定休日の時間区分、フレックスの清算期間集計、有給の基準日付与と年5日取得義務 — をカバーするものが存在しない。ここが本プロダクトの存在理由であり差別化軸。

打刻による客観的な労働時間の記録は、労働安全衛生法66条の8の3が事業者に課す労働時間状況の客観的把握義務にも資する(同義務を単独で充足させることを謳うものではなく、対象者の範囲や把握方法の細目は導入企業が別途確認する必要がある)。

2. ドメインスコープ ​

  • 決定: 本システムは出退勤打刻型(勤怠)。タスク別工数トラッキングはスコープ外。
  • 決定: 集計の出口は時間区分の算出まで。法定内・法定時間外・深夜・法定休日・月60時間超の「時間数」を区分別に確定させる。割増率を掛けた金額計算は給与システム側の責任。

対応する労働時間制(最終ゴール) ​

  • フレックスタイム制 — v0.1で最初に実装(開発者自身でドッグフーディング可能な唯一の制度)
  • 固定時間制 — v0.5で実装(前倒し。当初はv1.0予定)
  • シフト制/1ヶ月単位の変形労働時間制 — v0.7で実装(design/shift-work.md)
  • 裁量労働・みなしは当面スコープ外

訂正(2026-08-23): 固定時間制を当初「清算期間=1日の退化ケース」として表現する想定にしていたが、これは誤り。固定時間制は1日8時間と1週40時間の両方で判定し、しかも日次で時間外にした分を週の集計から除いて二重計上を防ぐ必要がある。この週次の判定は「清算期間=1日」では表現できない。また、所定を超えるが1日8時間以内の法定内残業(割増不要・賃金は発生)という区分がフレックスには存在しない。制度ごとに独立した集計として実装する(WorkSystem の判別可能ユニオン)。詳細は docs/design/work-systems.md。

v0.1のフレックス仕様 ​

決定: 清算期間1ヶ月・コアタイムなし(スーパーフレックス)を既定とする。月の総枠(法定: 週平均40h×暦日数/7)との差分で時間外を判定。3ヶ月清算はロードマップ。

追記(2026-08-24, コアタイム実装): コアタイム(労基法32条の3の任意設定)に対応した。既定は従来どおり「なし」で、設定した場合もコアタイム中の不在は警告(コアタイム遅刻・早退・不在)としてのみ扱い、集計(清算期間の総枠)には影響しない — 賃金控除は給与側の責任という既存の原則(design/breaks.md)を踏襲する。詳細は design/work-systems.md「コアタイム」。

制度変更の遡及防止 ​

決定: 労働時間制・日界・法定休日・休憩ルールなど計算に影響する制度・設定の変更は**適用開始日付きの版(effective-dated)**として扱い、過去期間の計算に遡って影響しない。過去日は常に「その日に有効だった設定」で計算され、締め済み期間はスナップショットで二重に保護される。

休日・カレンダー ​

決定: 法定休日は選択式で柔軟に指定できる。既定は日曜、テナント設定で曜日変更・暦日個別指定に対応。週1日(または4週4日)の法定休日判定と所定休日の区別を持ち、法定休日労働は独立した時間区分として集計。シフト制導入時には従業員別指定へ拡張。

3. 打刻 ​

記録の原則 ​

  • 1分単位固定。生データは常に1分単位で保持し、丸めは実装しない(労働者不利の丸めは違法判断があるため)。月次集計の端数処理のみ将来のオプション候補
  • 日界(1日の起算時刻)はテナント設定(既定0時)。日跨ぎ勤務を正しく日別配賦する
  • 休憩は打刻(休憩入/戻)と自動控除ルール(6h超45分・8h超1h)の併用選択式
  • 打刻忘れ検知(退勤なし・休憩なし)と本人/上長へのリマインド
  • 打刻には証跡メタデータ(IPアドレス・UA・打刻手段)を添付。GPS座標の取得は既定OFF — テナント設定でopt-in。有効化時は従業員に取得中であることを明示する。保持期間の既定は勤怠記録本体と同一とし、テナント(会社)単位で短縮設定できる。なお退職者の個人データ消去(§7)を実行すると、この証跡メタデータ(IP・UA・GPS)は打刻の行を残したまま null 化される — 打刻の時刻は賃金台帳の基礎資料だが「どのIP・どの端末・どの座標から打刻したか」は保存義務の対象ではないため(design/data-retention.md)

打刻手段(最終ゴール、フェーズ分割は §11) ​

  1. Web画面のボタン(PWA含む) — v0.1
  2. スマホPWA+位置情報(直行直帰対応) — v0.4
  3. Slack/チャットコマンド — v0.4
  4. 公開打刻API(ICカード等の外部クライアントは外置き) — v0.4
  5. MCPサーバー — AIアシスタントからの打刻・勤怠照会・申請(公開APIの上に薄く実装。操作は呼び出しユーザーの権限で評価し、通常操作と同様に監査ログへ記録) — v0.4

4. 承認・権限・監査 ​

決定: 打刻の事後修正は本人直接編集不可。修正申請→承認者のapproveで反映し、全変更を不可変監査ログに記録する。承認フローは既定で単段。多段承認(二段)はテナント設定で種別ごとに opt-in(2026-08-24 実装 — 打刻修正・休暇・休憩自動控除打ち消しの3種別。一次承認=従来どおりスコープ内の承認権限保持者、二次承認=同じ権限をテナント全体スコープで持つ人。申請は作成時点の段数で最後まで進む — design/approval-flows.md)。

組織モデルは部署ツリー+役職ベース。承認者の判定は部署ツリーと権限スコープで解決する。

権限モデル: 権限プリセット方式 ​

決定: 固定ロール(admin/manager/member)ではなく、権限プリセット方式を採用。会社の管理者相当のユーザーが、権限のON/OFFとスコープをチェックボックスUIで組み合わせてプリセットを作成し、各ユーザーに割り当てる — AWS IAMロールの発想。ただしUIは非エンジニアが迷わず使える平易さを必須要件とする。

  • 粒度はハイブリッド: 内部モデルはリソース×操作(CRUD相当)で網羅的に定義し、UIでは業務タスク単位の項目(「打刻修正を承認できる」「締めを解除できる」等、20〜30個目安)に束ねて表示。業務タスク→内部権限の対応表はコードで一元管理。カタログの具体項目はv0.1設計時に確定(§12)
  • スコープ: 各権限に「本人のみ/自部署/自部署+配下部署/テナント全体」を設定。権限ごとに意味のあるスコープのみ選択肢に出す
  • 複数プリセット割当・合算方式: 1ユーザーに複数プリセット割当可、実効権限はその合算(union)。兼務をプリセットの組合せで表現。帰結として、ユーザー詳細に実効権限ビュー(この人が結局何をできるか・どのプリセット由来か)を必須で備える
  • 拒否(deny)ルール(2026-08-24 実装。当初は「denyなし・加算のみで開始、deny対応はロードマップ」だった): 実効権限は「全プリセットの付与の合集合 − 全プリセットの拒否の合集合」。拒否はどの付与にも優先し、スコープを持たない(拒否したら全スコープで拒否 — 部分スコープの拒否は「部署では拒否だが全社では許可」という読み解きの罠を生むため設けない)。セルフサービス権限は拒否できない。詳細は design/permission-catalog.md
  • 操作は閲覧を含意: 操作権限をONにすると必要な閲覧権限が自動的に付随。UI上も「この権限には○○の閲覧が含まれます」と明示し、「承認できるのに見えない」矛盾設定を作れなくする
  • 固定原則(設定で変更不可): 本人の打刻・申請・自分の記録閲覧のセルフサービス権限は全員が常に保持(拒否ルールでも取り上げられない)。最後の「権限管理」保持者は削除・降格不可(割当変更だけでなく、拒否を足すプリセット編集も同じ判定で拒否する)。自分自身の権限昇格につながる操作は不可。プリセットの編集・割当変更はすべて監査ログ対象
  • 標準プリセット同梱: 出荷時に「管理者」「マネージャー」「メンバー」相当を同梱。v0.1は同梱プリセットのみで運用、カスタムプリセット編集UIはv0.2(権限エンジン自体はv0.1から permission ベース)
  • 締め後の遡及修正は専用権限「締めの解除」保持者に限定(§6)
  • 危険度の高い権限(締めの解除・監査ログ閲覧・権限管理など)は、編集UI上で影響範囲の説明を添えて表示(§10のコンテキストヘルプと連動)

5. 有給休暇管理(v1スコープ) ​

  • 付与方式: **法定(入社日基準)+基準日方式(全社一斉)**の両対応
  • 比例付与(パート向け)対応(2026-08-24 実装、労基法39条3項・労基法施行規則24条の3): メンバーごとに「有給付与の区分」(通常/週4日/週3日/週2日/週1日)を持ち、区分に応じた日数表で法定付与・付与の予告を計算する。区分は管理者が就業規則・雇用契約に基づいて明示的に選ぶ(週所定労働時間・日数からの自動判定はしない)。設計・判断点は design/leave-proportional-grant.md
  • 残日数管理(時効2年・繰越)、年5日取得義務の追跡とアラート
  • 休暇申請→承認フロー(§4の仕組みを共用)
  • 集計との連動: 有給日は欠勤控除せず所定労働扱いでフレックス枠に算入

36協定アラート(早期導入) ​

決定: 36協定の上限監視は早いフェーズで導入。v0.2で基本アラート(時間外の月45h — 実績および月内ペースからの超過見込み)、v0.3で完全版(年360h、特別条項時の月100h未満・複数月平均80h・年720h・月45h超は年6回まで)。通知は§7のチャネルに乗せる。

6. 締めと出口 ​

  • 月次締め(確定・ロック)
  • 締め後の遡及修正: 専用権限「締めの解除」を持つユーザーのみが再オープン可能。再オープン→修正→再締めの全操作を監査ログに記録し、締め状態の履歴(誰がいつ解除したか)も保持
  • 汎用CSV/APIエクスポートで区分別時間数を出力(v0.3)
  • freee/マネーフォワード連携: CSVエクスポートは対応済み(2026-08-27。GET /exports/attendance.csv?format=freee|mf — freee人事労務の勤怠サマリー24列は一次情報で列仕様を確認済み、マネーフォワード クラウド給与は固定の列仕様が存在せず事業者ごとの勤怠項目名に依存するため転記用CSV。どちらも取り込み前のマッピング確認が必須で、UI では β 表示。日数系(出勤日数・欠勤日数・有休取得日数)はKIZAMI が算出しないため空欄 — design/payroll-export.md)。API連携(OAuth経由の直接連携)はロードマップ

7. テナント・認証・通知 ​

  • マルチテナント対応。全データモデルに最初から tenant_id を設計。v1.0(2026-08-24)で有効化 — 1インスタンスに複数テナント(会社)を同居させられる。テナントの作成は運用者の作業(pnpm --filter @kizami/api create-tenant、deploy/k8s/README.md 参照)で、セルフサインアップ(自己申込みによるテナント作成)は提供しない — SaaS 形態での自己申込みはロードマップ。テナント間分離の実装規約と監査の範囲は design/multi-tenancy.md
  • 認証は自前認証(email+パスワード、将来パスキー)とOIDC(Google Workspace / Entra ID等)の両対応。自前はv0.1、OIDCはv1.0(2026-08-24 実装 — design/sso-oidc.md)
  • OIDC(SSO)は「新規登録の入口」ではなく「既存ユーザーのログイン手段」(2026-08-24 決定)。自動プロビジョニング(JIT)は行わない — コールバックでIdPが返したメールアドレスを、設定されたテナントの users.email と突合し、一致するユーザーが居なければログインを拒否する(「このメールアドレスのユーザーが見つかりません。管理者に招待を依頼してください」)。IdPに居ることは「この会社の従業員として勤怠を打つ人」を意味せず(業務委託・グループ会社・退職後の残存アカウント)、誰を登録するかは下記「登録は招待式のみ」と同じく管理側の決定事項のため。設定はテナント単位(issuer / client_id / client_secret〔保存時暗号化〕/ 有効フラグ / 未検証メール許可フラグ〔既定OFF〕)で、権限は tenant_settings.auth.manage。パスワードログインは併存する
  • 二要素認証(TOTP)は自前認証の任意オプション(2026-08-27 実装 — design/two-factor-auth.md)。従業員本人が「設定 → セキュリティ」(/settings/security)で有効化する(テナントによる強制は将来課題)。方式は RFC 6238(30秒・6桁・SHA-1・±1ステップ許容)で、認証アプリ(Google Authenticator 等)を使う。実装は依存を増やさず自前(WebCrypto のみ・RFC のテストベクタで固定)。共有鍵は KIZAMI_ENCRYPTION_KEY で暗号化して保存し、鍵が無い配備では 2FA を使えない(平文フォールバックはしない)。端末紛失に備えて単回使用のリカバリコード10本を発行し、それも失った場合は member.deactivate 権限(退職処理と同格)を持つ管理者がリセットできる(監査ログ + 本人へアプリ内通知)。SSO ログインは 2FA をバイパスする — 多要素を課すかは IdP 側のポリシーが決めるため
  • 登録は招待式のみ(2026-08-23 決定)。自由登録(セルフサインアップ)は提供しない — 従業員は会社に属してはじめて意味を持ち、誰を登録するかは管理側の決定事項のため。管理者がメンバーを作成(この時点で users 行ができ「招待中」)→ 招待トークン発行(32バイトランダム・ハッシュ保存・7日期限・再発行/取り消し可)→ 従業員がリンクからパスワードを設定して受諾(auth_credentials はこの時点で作成、受諾前はログイン不可能)。リンクの配布は SMTP 設定済みならメール、未設定でもリンクコピーで手渡しできる(SMTP を導入の前提条件にしない)
  • 退職者データの保持と消去(2026-08-27 実装 — design/data-retention.md)。労働基準法109条の保存義務(原則5年・附則143条2項の経過措置により当分の間3年)と、個人情報保護法22条の「利用する必要がなくなった個人データの遅滞なき消去」(努力義務)は退職者について正面から衝突する。KIZAMI はこれを 「保持期間の経過後に、行は残したまま匿名化する」 という形で解く。①退職処理(member.deactivate)が users.deactivated_at を記録し、これが保持期間の起算日になる(退職処理は最終出勤日以降に行われるため、義務期間より長く保持する方向にしか倒れない)。②保持年数はテナント設定(3 or 5、既定5 — 5年が原則で3年は経過措置にすぎず、既定を3にすると経過措置終了時に全テナントが一斉に違反側へ倒れるため)。③期間の経過後、専用権限 member.erase(新設。テナント全体スコープ・危険フラグ付き。member.deactivate の流用にしない — 無効化は再有効化で取り消せるが消去には戻す経路が無く、同格ではなく一段重い)を持つ管理者が消去できる。④消去 = 匿名化であり行削除ではない: 氏名は「削除済みユーザー」、メールは tombstone(user_deleted_<id>@invalid)に置き換え、パスワード・2FA・セッション・購読・個人通知設定・APIキー・招待/リセットトークン・Slack連携は物理削除、punch_events の IP・UA・GPS 列は null 化する一方、勤怠記録・締めスナップショット・監査ログの行は1件も消さない。⑤消去済みは無効化とは別の終端状態で、再有効化できない。⑥確認ダイアログでは影響の列挙に加えて対象者氏名の再入力を求める。⑦日次ワーカーによる通知はしない(消去は期限のある義務ではなく「もう消してよい」という状態にすぎず、急かすと取り返しのつかない誤操作を誘う)。テナント自体の削除はスコープ外(SaaS 形態のフェーズで扱う)
  • 同一メールアドレスの複数テナント登録は許容(ユニーク制約は tenant_id+email。顧問社労士等)。ログインでパスワード一致が複数テナントにまたがる場合はテナント選択を挟む(multiple_tenants)。招待はテナント固有の users 行に紐づくため受諾時の曖昧さは生じない
  • 通知チャネル: メール(SMTP)・Slack/Discord Webhook・Web Push/アプリ内の3系統(フェーズ分割は§11)。用途は打刻忘れリマインド・承認依頼・年5日/36協定アラート等。Web Push は 2026-08-24 実装(VAPID を自前実装し外部サービスに依存しない。設計は design/web-push.md)

通知設定の2層構造(2026-08-22 決定・修正) ​

チャネルの接続情報(会社が決める)と受け取りの希望(従業員本人が決める)を分ける。 当初の実装はテナント設定しか持たず、全員分の通知が1つの共有 Webhook に集約されて 他人の勤怠情報が見える状態だった。通知の宛先は個人情報であり、混ぜてはいけない。

層誰が決める内容
チャネルの接続情報会社SMTP サーバー、テナント共有の Webhook URL
個人の受け取り設定従業員本人通知の種類ごとにアプリ内 / メール / ブラウザプッシュの ON/OFF、個人 Webhook、通知先メールアドレス、購読したブラウザ

ブラウザプッシュ通知(Web Push、2026-08-24 追加)は個人チャネルにのみ存在する — 宛先が「特定個人のブラウザ」である以上、テナント共有チャネルとしては意味を成さないため。 運用者が VAPID 鍵(VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY / VAPID_SUBJECT)を設定した 配備でのみ有効になり、未設定なら UI からもチャネルからも消える(design/web-push.md)。

通知の宛先の原則:

  • 本人宛の通知(打刻忘れ・有給失効間近・年5日期限・自分の申請の承認結果・ 自分の勤務とシフトとの乖離)は本人の個人チャネルにのみ送る。 テナント共有 Webhook には送らない
  • 管理者向けの通知(承認依頼、誰かが36協定の上限に近づいた等)は、権限を持つ人に送る。 テナント共有 Webhook はこちらの用途

種類ごとの制御: 「打刻忘れはメールで欲しいが36協定アラートはアプリ内でよい」のような 希望を反映できるよう、通知の種類 × チャネルで ON/OFF できる。既定値は製品側が決め、 従業員が変更できる。

8. 非機能・OSS体裁・技術スタック ​

  • ライセンス: AGPL-3.0
  • i18n: UIは日・英・韓・中(簡体)の4言語(2026-08-23 拡張。当初は日/英2言語設計)。翻訳漏れは型で防ぐ(全ロケール辞書が日本語辞書と同一キー構造であることをコンパイル時に強制)。労働法ロジックは日本専用と割り切り、法令用語の英訳は労基法の公式英訳に準拠。制度ガイド(ヘルプ文言)は日本語から段階的に翻訳(未翻訳は日本語フォールバック)
  • タイムゾーン: Asia/Tokyo前提だがUTC保存・表示変換の原則は守る
レイヤ選定備考
言語TypeScriptNode 26+
APIHonoNode上で運用。Workers(workerd)でも起動・動作する(2026-08-27 実装、design/workers-d1.md)
フロントWaku (React)RSCベース
ビルド/テストVite / VitestWakuはVite基盤。ツールチェーンをViteエコシステムに統一
ドキュメントVitePressOSSドキュメントサイト(日/英)
ORMDrizzleSQLite/PostgreSQL両ダイアレクトを抽象
DBSQLiteベース+PostgreSQL選択式既定はSQLite。大規模はPostgreSQL(2026-08-24 実装 — DATABASE_URL が postgres:// なら自動で切り替え、design/db-dialects.md)。Cloudflare D1は3つめのダイアレクトとして実装済み(2026-08-27。バインディング注入・マイグレーションはデプロイ時適用 — design/workers-d1.md)
キュー/キャッシュValkey + BullMQリマインドスケジューラ・ジョブキュー用(確定)
配布Docker Compose+Helm chart1社1インスタンスでもマルチテナントでも可
リファレンス環境既存k3sクラスタ開発者自身のドッグフーディング環境

決定: Cloudflare Workers + D1 での動作を保証する(v1.0要件)。コアロジック(集計エンジン・ドメイン層)はランタイム非依存に保ち、Node/workerd両方をCIで検証(§9)。Valkey+BullMQはNode環境前提のため、キュー/スケジューラ層は差し替え可能な抽象とする: Node環境=Valkey+BullMQ、Workers環境=Cloudflare Queues+Cron Triggers。

実装状況(2026-08-27): HTTP API は workerd + D1 で起動・動作する(apps/api/src/workers.ts + apps/api/wrangler.jsonc、CI の test-workerd ジョブで検証)。ただし動作保証範囲には制約がある:

  • D1 は明示トランザクション(BEGIN/SAVEPOINT)を拒否するため、db.transaction() を通る書き込み経路(招待・パスワード再設定・修正申請の承認・締め・休暇申請の承認・メンバー停止/再開・Slack連携)は D1 配備では使えない。読み取りと打刻が中心の API までが動作保証範囲
  • 定期スキャン(リマインド・36協定アラート・シフト乖離・有休付与提案)は Node の worker.ts のみ。Cron Triggers + Cloudflare Queues 実装は未着手(スキャン本体は既に BullMQ にも node:* にも依存しない純関数なので、呼び出し側だけの課題)
  • SMTP 送信は Node のみ(nodemailer が node:net 依存)。@kizami/notify は送信関数の注入形なので fetch ベースのメール API を1本書けば Workers でも送れる

制約と配備手順の一覧は design/workers-d1.md。

運用の可観測性(2026-08-27 実装) ​

セルフホストの運用者が「動いているか・壊れていないか」を自分で見られるように、2つの面を用意する。どちらも既定 OFF — セルフホスト製品が既定で外部へ何かを送ることはしない。設計・公開項目・カーディナリティ方針の詳細は design/observability.md。

  • GET /metrics(Prometheus text format 0.0.4、環境変数 METRICS_TOKEN。未設定なら 404、設定時は Authorization: Bearer 必須): リクエスト数・所要時間ヒストグラム・プロセス指標に加え、テナント数/ユーザー数/直近24時間の打刻数(60秒キャッシュ、索引に当たる COUNT のみ)と、定期スキャンの最終実行時刻・成功/失敗の累計を出す。ラベルはルートパターン・ステータスクラスまでで、生パス・ユーザーID・テナントIDは付けない(時系列の本数が入力で増える作りにしない)。ワーカーは別プロセスなので、心拍を worker_heartbeats テーブルに書いて api の /metrics が読む形にし、追加のポート・Service を要らなくしている
  • エラー報告(Sentry プロトコル互換、環境変数 SENTRY_DSN。未設定なら no-op): 想定外のルート例外と定期スキャンの失敗を store API へ1件ずつ POST する。想定内の分岐(403/409)は送らない。リクエストボディ・ヘッダ・メールアドレス・ユーザーID は決して送らず、テナントIDもハッシュ先頭8桁だけをタグにする(この不変条件はテストで固定)。60秒の重複除去と窓あたり件数の上限で、エラーの嵐が配備を潰さないようにしてある

依存は増やしていない。prom-client は workerd で動かない既定メトリクスを抱えるため、@sentry/node はグローバルにパッチを当てるため、いずれも採らず自前の最小実装で持つ(Web Push の VAPID 自前実装と同じ判断)。

9. テスト戦略 ​

Workers動作保証(§8)と SQLite/PostgreSQL/D1 の3ダイアレクト対応をテストマトリクスで担保する。原則は**「集計エンジンを純関数・ランタイム非依存・DB非依存に保つ」**こと。

法令ゴールデンケース ​

  • 集計エンジンの正しさは宣言的フィクスチャ(YAML)で担保。「入力: 打刻列+テナント設定」→「期待: 区分別時間数」のペアを網羅的に用意
  • 必須ケース群: フレックス月枠の過不足、日界跨ぎ(深夜勤務の日別配賦)、深夜帯(22-5時)、休憩の打刻/自動控除、法定休日判定(曜日設定・暦日指定)、有給日の枠算入、36協定の各閾値、月境界・うるう年
  • 法改正時はフィクスチャの追加・更新で対応し、ケース自体をVitePressドキュメントの根拠資料として相互参照

レイヤ別方針 ​

レイヤ手法実行環境
集計エンジン(unit)Vitest+ゴールデンケース。不変条件(区分合計=総実労働 等)は fast-check の property-based で補強Node と workerd(@cloudflare/vitest-pool-workers)の両方で同一スイート(2026-08-27 実装 — フィクスチャの読み込みを node:fs から import.meta.glob へ移して両ランタイム共通にした)
リポジトリ層(integration)Drizzle経由の実DBテスト。同一スイートを3ダイアレクトで実行SQLite(libSQL) / PostgreSQL(2026-08-24 実装 — TEST_PG_URL を渡すと packages/db の全テストが両ダイアレクトで走る) / D1(2026-08-27 実装 — pnpm test:workers で miniflare 上の D1 に対して同一スイートが走る。トランザクション依存の34件のみ skip)
API(integration)hono/testing でリクエストレベル検証。権限マトリクス(permission×scope)網羅と監査ログ不可変性テストを含む本体スイートは Node。workerd は起動スモーク1本(SELF.fetch() で実物の src/workers.ts を叩き、ログイン→打刻→勤務状態→月次まで確認)。判断の背景は design/workers-d1.md
E2EPlaywright。主要業務フロー(打刻→集計→修正申請→承認→締め→CSV)SQLite構成のフルスタック

CIマトリクス ​

  • 毎PR: unit(Node+workerd — CI の test / test-workerd ジョブ)、integration(SQLite/PostgreSQL — test-postgres ジョブ / D1 — test-workerd ジョブ)、E2E主要フロー
  • nightly: E2E全量、PostgreSQL複数バージョン
  • Workers動作保証の実体はこのマトリクスの workerd/D1 列。緑でないPRはマージ不可

10. UX原則: コンテキストヘルプ ​

決定: 各機能画面に「この画面で何ができるか・その操作がどこに影響するか」をツールチップ/インラインヒント形式で都度提示し、ユーザーの迷いを減らす。自明な操作(出勤ボタン等)には付けない。

  • 付与の目安: 影響が画面の外に及ぶ操作(締めの実行/解除、承認、権限プリセットの割当、自動控除ルールの変更)と、法制度に由来する表示(清算期間の総枠、法定休日、年5日義務、36協定の閾値)
  • 初回ログイン時のオンボーディングツアーは実装済み(2026-08-27)。文脈内ヒント(ツールチップ)を主、ツアーを従とする関係は変えない — ツアーは「どこに何があるか」を一度案内するだけで、操作の意味は各画面のヒントが引き続き担う

ビジュアルデザイン方針 ​

決定: UIは事務的・帳票的な見た目にせず、毎日使うことに楽しさを感じられるデザインを目指す。

  • カラーはビビッドなCMYK(シアン/マゼンタ/イエロー+キー)を基調とする方向で検討。印刷インキの色域は「打刻(スタンプ)」「1分単位で刻む」というプロダクトの世界観とも整合する
  • 遊びを入れる場所と入れない場所を分ける: 打刻・日次表示など毎日の接点には楽しさを、締め・承認・権限管理など影響の大きい操作には明瞭さと落ち着きを優先する
  • 楽しさはアクセシビリティを犠牲にしない(コントラストはWCAG AA準拠、色だけに意味を持たせない)
  • 具体のデザイントークン・コンポーネント設計は v0.1 のUI実装前に別途デザイン検討を行う

ヘルプ文言の単一ソース管理 ​

決定: ヘルプ文言はmonorepo内の独立パッケージ(packages/help-content)にMarkdown+frontmatterで一元管理し、アプリのツールチップとVitePressドキュメントの両方を同一ソースから生成する。

  • 1エントリ=1ファイル。frontmatterに機能キー(例: closing.unlock)とsummary(ツールチップ用1〜2文)、本文がドキュメント用詳細。言語はファイル並置(closing-unlock.ja.md / .en.md)
  • アプリ側: ビルド時に型付き辞書へ変換し、機能キーのTS型を自動生成。存在しないキーの参照や訳文の欠落はコンパイル/CIエラー
  • VitePress側: 同じMarkdownをページとして取り込み。ツールチップの「詳しく見る」はdocsの該当アンカーへ
  • 法令ゴールデンケース(§9)からも根拠として相互参照

11. フェーズ計画 ​

版テーマ内容
v0.1自分打刻Web打刻(出退勤・休憩)、フレックス月枠集計、日次/月次画面、自前認証、日界設定、監査ログ基盤、権限エンジン(permission×scope、同梱プリセットのみ)。内部モデルはtenant_id前提、コアはランタイム非依存でworkerd上のCIも最初から
v0.2承認と組織部署ツリー・役職、修正申請→承認、権限プリセット編集UI、打刻忘れ検知+メール通知、36協定基本アラート(月45h実績・超過見込み)
実装状況(2026-08-22): 修正申請→承認・通知基盤・打刻忘れリマインド・36協定アラート・権限エンジン・通知設定画面・部署/プリセット管理API まで完了。残: 部署・プリセット管理のUI、SMTP実送信の確認
v0.3休暇と締め有給付与(法定+基準日)・残日数・年5日追跡、休暇申請、月次締め、CSVエクスポート、36協定完全版(年360h・特別条項)
v0.4入口の拡張Slackコマンド打刻、Webhook通知、PWA+GPS打刻、公開打刻API(APIキー)、MCPサーバー(打刻・照会・申請)
v0.5制度の拡張固定時間制(1日8h・週40hの二段判定、法定内残業の区分)、月次一覧への打刻時刻表示(広い画面では出勤・退勤の独立列)、制度に応じた表示の出し分け、休憩不足の検知(労基法34条・勤怠日チェーン単位 — 中抜けの空白を休憩相当に算入)、休憩の自動控除(auto/both、本人が打ち消し申請できる形 — design/breaks.md)、招待式メンバー登録、手当対象時間の算出(design/allowances.md)、多言語UI(日・英・韓・中〔簡体〕)
v0.7シフト制と有給付与フローシフト制/1ヶ月単位の変形労働時間制(3段の時間外判定・シフト表・予実乖離の警告 — design/shift-work.md)、有給付与の予告→承認→通知フロー(下記)、シフト制ユーザーの有給1日分の分数換算(シフトのある日はその所定、無い日は基準所定)
実装状況(2026-08-24): フェーズ1〜4 完了
v1.0企業利用可能・OSS公開マルチテナント有効化(2026-08-24 完了: テナント作成CLI + テナント間分離の監査テスト — design/multi-tenancy.md)、OIDC(2026-08-24 完了: 認可コード+PKCE、自動プロビジョニングなし — design/sso-oidc.md)、PostgreSQL選択式(2026-08-24 完了: DATABASE_URL のスキームで切替、全DBテストを両ダイアレクトで実行 — design/db-dialects.md)、Workers+D1動作保証(2026-08-27 一次実装: HTTP API が workerd+D1 で動作、CI に test-workerd ジョブ追加 — design/workers-d1.md。残: D1 のトランザクション制約でブロックされる承認系書き込み経路、キュー層の Cloudflare Queues + Cron Triggers 実装、fetch ベースのメール送信)、Compose/Helm配布、ドキュメント整備、運用の可観測性(2026-08-27 完了: Prometheus /metrics + Sentry互換のエラー報告。どちらも既定 OFF — design/observability.md)
以降ロードマップ3ヶ月清算、freee/MF のAPI連携
実装済み(2026-08-27): オンボーディングツアー(初回ログイン時に自動で始まる案内。打刻→月次→修正/休暇の申請→個人の通知設定をたどり、member.invite を持つ人にはさらに設定ハブ→メンバー招待→勤怠ルール→締めが続く。外部ライブラリを足さない自前のスポットライト実装で、対象要素は data-tour 属性で指す。権限で消えた要素の手順は黙って飛ばす。完了/スキップの記録は端末ごと〔localStorage〕— 端末都合の設定でありサーバーには保存しない。設定ハブの「使い方ツアーを見る」からいつでも再実行)、freee/MF向けCSVエクスポート(?format=freee / ?format=mf。区分別時間数を各社の勤怠項目へマッピング。金額計算は従来どおり給与ソフト側の責任 — design/payroll-export.md)
実装済み(2026-08-24): 権限denyルール(プリセットが拒否を持てる。拒否は全付与に優先・スコープなし・セルフサービス権限は対象外 — design/permission-catalog.md)、Web Push(ブラウザプッシュ通知。VAPID 自前実装・外部サービス不使用、カテゴリごとに個人でON/OFF、鍵未設定なら機能ごと非表示 — design/web-push.md)、コアタイム(労基法32条の3。警告のみ・集計に影響しない — design/work-systems.md「コアタイム」)、多段承認(種別ごとに単段/二段を選べるテナント設定。仕掛かり中の申請は作成時点の段数で確定 — design/approval-flows.md)

有給付与の3段フロー(v0.7 で実装、2026-08-23 決定 / 2026-08-24 実装): (1) 付与基準日の30日前に管理者へ予告通知 — 対象者・算定日数に加え、打刻・シフトから計算した出勤率の参考値(労基法39条1項の8割出勤要件の検算材料)を添える。(2) 管理者が確認のうえ承認すると、そこで初めて付与(leave_grants)が作られる。(3) 承認時に本人へ「◯日付与されました」を leave_alert カテゴリ・個人チャネルで通知。機械が無条件に付与を確定させない — 出勤率要件の最終判断は人が行う。設計・決定の詳細は design/shift-work.md の「フェーズ4の決定事項」を参照。

リスク注記: v1.0までのスコープは個人開発として重量級。各フェーズを「その版だけで自分の運用が回る」単位に切ってあるのは、途中で止まっても価値が残るようにするため。

12. 未決事項 ​

  1. 権限カタログの残レビュー論点 — カタログ本体は design/permission-catalog.md にレビュー済みドラフトあり(2026-08-21)。文末のレビュー論点(代理打刻の解放範囲、マネージャーのスコープ粒度、エクスポートの追加ガード等)の確定が残り