sync: update from private repo (c18b98e)
Some checks failed
CI / build-and-test (push) Has been cancelled

This commit is contained in:
oss-sync 2026-06-10 01:34:52 +00:00
parent a7f1b718ce
commit eb35e32f7a
3 changed files with 246 additions and 0 deletions

76
docs/operations/guide.css Normal file
View File

@ -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; }

View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>運用ガイド — MAESTRO</title>
<link rel="stylesheet" href="guide.css">
</head>
<body>
<div class="wrap">
<header class="doc">
<div class="crumbs">docs / operations</div>
<h1>運用ガイド</h1>
<p class="meta">MAESTRO のセットアップ・運用に関する HTML 資料の一覧。段階バッジ:
<span class="badge design">設計</span>
<span class="badge impl">実装</span>
<span class="badge done">完成</span>
</p>
</header>
<table>
<thead>
<tr><th>資料</th><th>段階</th><th>更新日</th><th>概要</th></tr>
</thead>
<tbody>
<tr>
<td><a href="initial-setup.html">初期セットアップ(認証・初回管理者)</a></td>
<td><span class="badge done">完成</span></td>
<td>2026-06-10</td>
<td>ローカル認証を有効化し、初回管理者アカウントを起動時 seed で作る手順。ログインID 運用も。</td>
</tr>
</tbody>
</table>
<div class="note">
<b>補足</b><br>
その他の技術ドキュメントアーキテクチャ・MCP・SSH 等)は <code>docs/</code> 配下に Markdown で置いています。
本ディレクトリは「セットアップ・運用の手順書」を段階別 HTML で集約する場所です。
</div>
<footer class="doc">MAESTRO — docs/operations/</footer>
</div>
</body>
</html>

View File

@ -0,0 +1,126 @@
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>初期セットアップ(認証・初回管理者) — MAESTRO</title>
<link rel="stylesheet" href="guide.css">
</head>
<body>
<div class="wrap">
<header class="doc">
<div class="crumbs"><a href="index.html">運用ガイド</a> / 初期セットアップ</div>
<h1>初期セットアップ — 認証と初回管理者アカウント <span class="badge done">完成</span></h1>
<p class="meta">対象: MAESTRO を認証ありで運用し、最初の管理者アカウントを作る人 更新日: 2026-06-10</p>
</header>
<h2>このガイドの範囲</h2>
<p>
MAESTRO は認証なしno-authでも動きますが、複数人で使う・外部に出す場合はログインを有効にします。
その際に最初に詰まるのが「<b>まだ誰もログインできない状態で、どうやって最初の管理者を作るか</b>」です。
本ガイドはローカル認証ID + パスワード)を前提に、その初回ブートストラップ手順をまとめます。
</p>
<div class="note">
<b>setup-wizard とは別です</b><br>
<code>npm run setup</code> のセットアップウィザードは <b>LLM 接続先の設定だけ</b>が対象で、認証・初期管理者は対象外です。
認証まわりは本ガイドで手動設定します。
</div>
<h2>前提</h2>
<ul>
<li><code>config.yaml</code> が存在すること(無ければ <code>config.yaml.example</code> をコピー)。</li>
<li>サーバーをビルド・起動できること(<code>scripts/server.sh start</code> 等)。</li>
</ul>
<h2>ステップ 1 — ローカル認証を有効化し、初回 admin を seed する</h2>
<p>
初回管理者は「セルフ登録」ではなく、<b><code>config.yaml</code> に書いておくと起動時に自動作成seedされる</b>方式です。
<code>auth:</code> ブロックに次を追加します。
</p>
<pre><code>auth:
session_secret: "ランダムな長い文字列" # 未設定だと再起動ごとにセッション失効
local:
enabled: true
allow_signup: false # 後述。true で他ユーザーのセルフ登録を許可
bootstrap_admin: # 起動時に id='local' の管理者を冪等 seed
email: "admin" # ← ログインIDメール形式でなくてOK
password: "強いパスワードを設定" # ← 平文で config に入る。初回ログイン後に変更推奨</code></pre>
<table>
<thead><tr><th>キー</th><th>意味</th></tr></thead>
<tbody>
<tr><td><code>auth.session_secret</code></td><td>セッション署名鍵。未設定だとプロセスごとのランダム値になり、再起動でログインが切れる。安定運用では必ず設定。</td></tr>
<tr><td><code>auth.local.enabled</code></td><td><code>true</code> でローカルID+パスワードログインを有効化。これだけで認証が有効になり、OAuth 無しでも保護される。</td></tr>
<tr><td><code>auth.local.bootstrap_admin.email</code></td><td>初回管理者のログインID。後述の通り<b>メール形式は不要</b></td></tr>
<tr><td><code>auth.local.bootstrap_admin.password</code></td><td>初回管理者のパスワード。<b>config に平文で保存される</b>ため、初回ログイン後に Settings から変更を推奨。</td></tr>
<tr><td><code>auth.local.allow_signup</code></td><td><code>true</code> で 2人目以降のセルフ登録を許可作成されるのは承認待ち状態</td></tr>
</tbody>
</table>
<div class="tip">
<b>no-auth からの移行はそのまま引き継げる</b><br>
seed される管理者は固定 ID <code>local</code> で作られます。これは no-auth 時代にデータの所有者として使われていた ID と同じなので、
認証なしで溜めたタスクやファイルを、そのまま初回 admin が引き継ぎます。
</div>
<h2>ステップ 2 — 再起動してログイン</h2>
<ol class="steps">
<li>サーバーを再起動する。</li>
<li>起動ログに <code>[auth] seeded local system admin id=local email=...</code> が出ることを確認するseed は冪等。再起動のたびに config の値でパスワードが更新される)。</li>
<li>ブラウザで <code>/auth/login</code> を開き、<b>ステップ1で設定した ID とパスワード</b>でログインする。そのまま管理者として入れる。</li>
</ol>
<h2>ログインID について(メール不要)</h2>
<p>
ローカル認証の識別子は内部的に「email」という名前のフィールドですが、<b>メール形式の検証はしていません</b>
<code>admin</code><code>team-taro</code> のような<b>自由な文字列をログインID として使えます</b>
ログイン/登録フォームの入力欄も <code>type="text"</code>・ラベル「ログインID」になっており、
ブラウザのメール形式チェックは外れています。
</p>
<div class="note">
<b>OAuth を併用する場合</b><br>
Google / Gitea OAuth も使う構成では、そちら側はメールアドレスで識別され、管理者自動昇格は <code>auth.admin_emails</code> のメール一致で判定されます。
ローカル認証だけなら自由ID で問題ありません。
</div>
<h2>ステップ 3 — 2人目以降のユーザー</h2>
<p>方法は2通りです。</p>
<ul>
<li><b>セルフ登録を許可する</b>: <code>auth.local.allow_signup: true</code> にすると、ログイン画面に登録フォームが出る。登録されたユーザーは<b>承認待ちpending</b>になり、そのままではアプリを使えない。管理者が <b>Settings → ユーザー管理</b> で承認すると有効化される。</li>
<li><b>管理者が用意する</b>: allow_signup を使わず、管理者がユーザーを作成・有効化する運用も可能。</li>
</ul>
<h2>よくある詰まり</h2>
<table>
<thead><tr><th>症状</th><th>原因 / 対処</th></tr></thead>
<tbody>
<tr>
<td>起動時に <code>Cannot read properties of undefined (reading 'google')</code> で落ちる</td>
<td>古いビルドで <code>auth.providers</code> 未設定だと発生した既知不具合(修正済み)。最新を pull・再ビルドすれば解消。暫定回避は <code>auth:</code> 直下に <code>providers: {}</code> を1行足す。</td>
</tr>
<tr>
<td>再起動のたびにログインが切れる</td>
<td><code>auth.session_secret</code> 未設定。安定した値を設定する。</td>
</tr>
<tr>
<td>初回 admin でログインできない</td>
<td>入力した ID/パスワードが <code>bootstrap_admin</code> の値と一致しているか確認。値を変えて再起動すればパスワードは上書き更新されるseed は冪等)。</td>
</tr>
<tr>
<td>UI 変更が反映されない</td>
<td>サーバー再起動だけでは UI は更新されない。<code>npm run build:ui</code> を実行してから再起動する。</td>
</tr>
</tbody>
</table>
<h2>背景・関連</h2>
<ul>
<li>設定の全項目は <code>config.yaml.example</code><code>auth:</code> ブロックのコメント参照。</li>
<li>LLM 接続先の初期設定はセットアップウィザード(<code>npm run setup</code>)が担当。本ガイドの認証はウィザードの対象外。</li>
<li>関連変更: 自由ログインID 対応PR #448<code>auth.providers</code> 未設定クラッシュ修正PR #447</li>
</ul>
<footer class="doc">MAESTRO — docs/operations/initial-setup.html 完成版2026-06-10</footer>
</div>
</body>
</html>