diff --git a/docs/operations/guide.css b/docs/operations/guide.css new file mode 100644 index 0000000..5cfa17c --- /dev/null +++ b/docs/operations/guide.css @@ -0,0 +1,76 @@ +/* MAESTRO 運用ガイド 共通スタイル + 段階バッジ: 設計=青 / 実装=黄 / 完成=緑 */ +:root { + --bg: #f8fafc; + --surface: #ffffff; + --text: #0f172a; + --muted: #64748b; + --border: #e2e8f0; + --accent: #4f46e5; + --code-bg: #0f172a; + --code-text: #e2e8f0; + --stage-design: #2563eb; + --stage-impl: #d97706; + --stage-done: #16a34a; +} +@media (prefers-color-scheme: dark) { + :root { + --bg: #0b1120; --surface: #111827; --text: #e2e8f0; --muted: #94a3b8; + --border: #1f2937; --accent: #818cf8; --code-bg: #000; --code-text: #e5e7eb; + } +} +* { box-sizing: border-box; } +html { scroll-behavior: smooth; } +body { + margin: 0; background: var(--bg); color: var(--text); + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Hiragino Sans', 'Noto Sans JP', Roboto, sans-serif; + line-height: 1.75; font-size: 15px; +} +.wrap { max-width: 860px; margin: 0 auto; padding: 32px 24px 80px; } +header.doc { border-bottom: 1px solid var(--border); padding-bottom: 20px; margin-bottom: 32px; } +.crumbs { font-size: 13px; color: var(--muted); margin-bottom: 12px; } +.crumbs a { color: var(--accent); text-decoration: none; } +.crumbs a:hover { text-decoration: underline; } +h1 { font-size: 1.85rem; line-height: 1.3; margin: 6px 0 10px; letter-spacing: -0.01em; } +h2 { font-size: 1.3rem; margin: 40px 0 12px; padding-top: 8px; border-top: 1px solid var(--border); } +h2:first-of-type { border-top: none; } +h3 { font-size: 1.05rem; margin: 24px 0 8px; } +p, li { color: var(--text); } +.meta { color: var(--muted); font-size: 13px; margin-top: 8px; } +.badge { + display: inline-block; font-size: 12px; font-weight: 700; letter-spacing: .04em; + padding: 3px 10px; border-radius: 999px; color: #fff; vertical-align: middle; +} +.badge.design { background: var(--stage-design); } +.badge.impl { background: var(--stage-impl); } +.badge.done { background: var(--stage-done); } +code { + font-family: 'SF Mono', ui-monospace, Menlo, Consolas, monospace; font-size: 0.88em; + background: rgba(99,102,241,.12); color: var(--accent); padding: 1px 6px; border-radius: 5px; +} +pre { + background: var(--code-bg); color: var(--code-text); padding: 16px 18px; border-radius: 10px; + overflow-x: auto; font-size: 13px; line-height: 1.6; border: 1px solid var(--border); +} +pre code { background: none; color: inherit; padding: 0; } +table { border-collapse: collapse; width: 100%; margin: 16px 0; font-size: 14px; } +th, td { border: 1px solid var(--border); padding: 9px 12px; text-align: left; vertical-align: top; } +th { background: rgba(99,102,241,.08); font-weight: 600; } +tr:nth-child(even) td { background: rgba(148,163,184,.06); } +.note, .warn, .tip { + border-left: 4px solid var(--accent); background: var(--surface); + padding: 12px 16px; border-radius: 0 8px 8px 0; margin: 16px 0; font-size: 14px; +} +.warn { border-left-color: #dc2626; } +.tip { border-left-color: var(--stage-done); } +.note b, .warn b, .tip b { display: inline-block; margin-bottom: 2px; } +.steps { counter-reset: step; list-style: none; padding-left: 0; } +.steps > li { position: relative; padding-left: 42px; margin: 18px 0; } +.steps > li::before { + counter-increment: step; content: counter(step); + position: absolute; left: 0; top: 0; width: 28px; height: 28px; + background: var(--accent); color: #fff; border-radius: 50%; + display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 14px; +} +a { color: var(--accent); } +footer.doc { margin-top: 56px; padding-top: 16px; border-top: 1px solid var(--border); color: var(--muted); font-size: 13px; } diff --git a/docs/operations/index.html b/docs/operations/index.html new file mode 100644 index 0000000..f254ff7 --- /dev/null +++ b/docs/operations/index.html @@ -0,0 +1,44 @@ + + + + + +運用ガイド — MAESTRO + + + +
+
+
docs / operations
+

運用ガイド

+

MAESTRO のセットアップ・運用に関する HTML 資料の一覧。段階バッジ: + 設計 + 実装 + 完成 +

+
+ + + + + + + + + + + + + +
資料段階更新日概要
初期セットアップ(認証・初回管理者)完成2026-06-10ローカル認証を有効化し、初回管理者アカウントを起動時 seed で作る手順。ログインID 運用も。
+ +
+ 補足
+ その他の技術ドキュメント(アーキテクチャ・MCP・SSH 等)は docs/ 配下に Markdown で置いています。 + 本ディレクトリは「セットアップ・運用の手順書」を段階別 HTML で集約する場所です。 +
+ + +
+ + diff --git a/docs/operations/initial-setup.html b/docs/operations/initial-setup.html new file mode 100644 index 0000000..6e112cc --- /dev/null +++ b/docs/operations/initial-setup.html @@ -0,0 +1,126 @@ + + + + + +初期セットアップ(認証・初回管理者) — MAESTRO + + + +
+
+
運用ガイド / 初期セットアップ
+

初期セットアップ — 認証と初回管理者アカウント 完成

+

対象: MAESTRO を認証ありで運用し、最初の管理者アカウントを作る人 / 更新日: 2026-06-10

+
+ +

このガイドの範囲

+

+ MAESTRO は認証なし(no-auth)でも動きますが、複数人で使う・外部に出す場合はログインを有効にします。 + その際に最初に詰まるのが「まだ誰もログインできない状態で、どうやって最初の管理者を作るか」です。 + 本ガイドはローカル認証(ID + パスワード)を前提に、その初回ブートストラップ手順をまとめます。 +

+
+ setup-wizard とは別です
+ npm run setup のセットアップウィザードは LLM 接続先の設定だけが対象で、認証・初期管理者は対象外です。 + 認証まわりは本ガイドで手動設定します。 +
+ +

前提

+ + +

ステップ 1 — ローカル認証を有効化し、初回 admin を seed する

+

+ 初回管理者は「セルフ登録」ではなく、config.yaml に書いておくと起動時に自動作成(seed)される方式です。 + auth: ブロックに次を追加します。 +

+
auth:
+  session_secret: "ランダムな長い文字列"     # 未設定だと再起動ごとにセッション失効
+  local:
+    enabled: true
+    allow_signup: false                  # 後述。true で他ユーザーのセルフ登録を許可
+    bootstrap_admin:                      # 起動時に id='local' の管理者を冪等 seed
+      email: "admin"                      # ← ログインID(メール形式でなくてOK)
+      password: "強いパスワードを設定"        # ← 平文で config に入る。初回ログイン後に変更推奨
+ + + + + + + + + + +
キー意味
auth.session_secretセッション署名鍵。未設定だとプロセスごとのランダム値になり、再起動でログインが切れる。安定運用では必ず設定。
auth.local.enabledtrue でローカル(ID+パスワード)ログインを有効化。これだけで認証が有効になり、OAuth 無しでも保護される。
auth.local.bootstrap_admin.email初回管理者のログインID。後述の通りメール形式は不要
auth.local.bootstrap_admin.password初回管理者のパスワード。config に平文で保存されるため、初回ログイン後に Settings から変更を推奨。
auth.local.allow_signuptrue で 2人目以降のセルフ登録を許可(作成されるのは承認待ち状態)。
+ +
+ no-auth からの移行はそのまま引き継げる
+ seed される管理者は固定 ID local で作られます。これは no-auth 時代にデータの所有者として使われていた ID と同じなので、 + 認証なしで溜めたタスクやファイルを、そのまま初回 admin が引き継ぎます。 +
+ +

ステップ 2 — 再起動してログイン

+
    +
  1. サーバーを再起動する。
  2. +
  3. 起動ログに [auth] seeded local system admin id=local email=... が出ることを確認する(seed は冪等。再起動のたびに config の値でパスワードが更新される)。
  4. +
  5. ブラウザで /auth/login を開き、ステップ1で設定した ID とパスワードでログインする。そのまま管理者として入れる。
  6. +
+ +

ログインID について(メール不要)

+

+ ローカル認証の識別子は内部的に「email」という名前のフィールドですが、メール形式の検証はしていません。 + adminteam-taro のような自由な文字列をログインID として使えます。 + ログイン/登録フォームの入力欄も type="text"・ラベル「ログインID」になっており、 + ブラウザのメール形式チェックは外れています。 +

+
+ OAuth を併用する場合
+ Google / Gitea OAuth も使う構成では、そちら側はメールアドレスで識別され、管理者自動昇格は auth.admin_emails のメール一致で判定されます。 + ローカル認証だけなら自由ID で問題ありません。 +
+ +

ステップ 3 — 2人目以降のユーザー

+

方法は2通りです。

+ + +

よくある詰まり

+ + + + + + + + + + + + + + + + + + + + +
症状原因 / 対処
起動時に Cannot read properties of undefined (reading 'google') で落ちる古いビルドで auth.providers 未設定だと発生した既知不具合(修正済み)。最新を pull・再ビルドすれば解消。暫定回避は auth: 直下に providers: {} を1行足す。
再起動のたびにログインが切れるauth.session_secret 未設定。安定した値を設定する。
初回 admin でログインできない入力した ID/パスワードが bootstrap_admin の値と一致しているか確認。値を変えて再起動すればパスワードは上書き更新される(seed は冪等)。
UI 変更が反映されないサーバー再起動だけでは UI は更新されない。npm run build:ui を実行してから再起動する。
+ +

背景・関連

+ + + +
+ +