HARUMI
戻る

2026 / 02

NOEMA — 内省ライフシステム

Personal production system個人開発・運用

成果独自の認証モデルを持つ非公開の記録システムを構築し、Organization の境界による制約を回避しながらも保護ブランチの保護は維持しました。

概要

独自設計の二段階ログインを持つマルチユーザー型内省・記録アプリ。GitOps パイプラインは GitLab の権限上の本物の行き止まりを回避する必要がありました。

背景

その日に実際に起きたことを記録し、数ヶ月単位で振り返る場所。ただしそれは、書く人が「他に誰が読めるのか」を一切気にしなくていい場合にのみ成立します。この要求が認証モデルを決めました——セルフサービスのアカウント、意図的にログインの第二要素にはしていない回復キー、任意のパスキー、そしてすべての記録がアカウント単位で分離されています。

システム

Browser to Two-step auth to Next.js to PostgreSQLBrowserTwo-step authNext.jsPostgreSQL

課題

日常的な変更のデプロイで壁にぶつかりました。プロジェクトの保護された main ブランチは Maintainer のみ push 可能で、唯一の Maintainer は CI ボットアカウント、そして人間の管理者アカウントは GitLab 18 の Organizations 機能によりボットと異なる組織に属していたためメンバーに追加できませんでした——組織をまたぐメンバーシップは端的に拒否されます。

調査

最初の仮説

管理者を Maintainer として追加できると考えました。

管理者として非保護のフィーチャーブランチに push し(これは問題なく可能)、クラスター内の gitlab-rails コンソール経由でボットとしてマージを操作します。ボットユーザーとしてマージリクエストを作成し、マージ可否判定を強制実行(非同期計算のためポーリングが必要)し、マージ可能と判定されてからマージを実行します。

証拠

merge_request.check_mergeability
# poll until merge_status permits merge

GitLab 18 は Organization をまたぐメンバー追加を拒否し、保護された main へマージできるのは CI ボットだけでした。

判断

ボット所有の Merge Request をスクリプトで作成し、非同期のマージ可否判定をポーリングしました。

結果

一度きりの回避策ではなく、再現可能なスクリプト化された手順として確立。同じ組織分離の壁にぶつかる他リポジトリにもそのまま適用でき、ブランチ保護を弱めることも、構造的に付与できない Maintainer 権限を管理者アカウントに与えることもありません。

次に変えること

現在の制約: これは当面の移行制約を解決したものであり、望ましい長期的な運用モデルとして扱ってはいません。スクリプト経路はクラスター内の管理コンソールを通り、対象はこのリポジトリ 1 つに限定され、Merge Request 自体が監査記録として残ります——ボットが作成した MR であってもレビュー可能な成果物であり、無言の直接 push ではありません。

次の一手: Organization のメンバーシップ仕様により管理者が通常の Maintainer 権限を持てるようになった時点で、この特殊経路は完全に削除します。回避策は、それを生んだ制約より長く残すべきではありません。

技術構成

Next.js 14 · Prisma · PostgreSQL · Redis · GitLab CI · ArgoCD

次のプロジェクト

Camunda 8.8 フルスタックの運用