コンテンツにスキップ

変更履歴

書式は Keep a Changelog、版は SemVer識別子を振り直せない体系で何を破壊的変更と みなすか方針にある。

未リリース

0.0.8 — 2026-08-29

認可サーバに寄せた構成でいちばん多い詰まりどころが、目に見えるようになった版。 client_id の綴りが 1 文字ずれると黙って 401 になっていたが、弾いた文字列を台帳が 持つようにしたので、打ち直さずに登録できる。あわせて、体験用の台帳から実在の機関名を 外した。

追加

  • 認可サーバから来た、登録の無い主体を画面に出す。 client_id の綴りが 1 文字 違うだけで 401 になり、しかも黙って落ちる——認可サーバに寄せた構成でいちばん多い 詰まりどころだった。弾いた瞬間に正しい文字列は手元にあるazp は署名検証を 通っている)ので、捨てずに残して一覧に出し、そこから打ち直さずに登録できるように した。認可サーバの資格情報は要らない。止めた主体は混ぜない——意図して止めた ものを「登録し忘れ」に並べると、消すために登録し直すことになる。

変更

  • デモの台帳から実在の機関名と NAAN を外したseed_demo.py / realm-arkhe.json)。 本物の名前を置くと、その機関が arkhe を使っているように読める。利用者は ops / naan-admin / org-admin、組織は「例示大学」など、NAAN は 99999 (仕様が試験用に予約)と例示の 12345 / 54321 にした。

  • 管理画面の文言を画面ごとのファイルに分けたapi/i18n/)。288 件が 1 ファイルに並んでいて、直したい語を探すのに全体を読むことになっていた。 分ける単位は言語ではなく画面——日本語と英語を別ファイルにすると対が 離れ、片方だけ足したことが差分に出なくなる。分割前後で辞書が完全に一致する ことを確かめてある(画面の見え方は変わらない)。

0.0.7 — 2026-08-29

台帳にはあるのに端末からは見えなかったものと、読んだ人を間違った方に導いて いた記述。 どちらも識別子の振る舞いは変えていない。

追加

  • AGENTS.md 改修の手順と、実際に踏んだ罠をまとめた。人にも コーディングエージェントにも同じものを渡す——片方だけの決まりを作ると、 もう片方が破る。
  • 参照ページが実装から遅れていないことを検査するtests/test_docs.py)。 Contributing に「設定と CLI のページは生成している」と書いてあったのは誤りで、 そのせいで設定 2 つとコマンド 1 つが未記載のまま残っていたARKHE_TRUSTED_PROXIESARKHE_LOG_LEVELarkhe manager policy)。記述を直し、埋め、二度開かないようにした。

  • arkhe ark list 画面に ARK 一覧があるのに CLI に無かった。絞り込みは 画面と同じ式を通す(domain/queries.py)——到達範囲を 2 か所に書くと、 片方だけ直したときにずれる。既定で 50 件で打ち切り、打ち切ったことと続きの --offset を標準エラーに出す(出さなければ「これで全部」と読まれる)。

0.0.6 — 2026-08-29

中身は変えず、同じコミットから同じものができるようにした版。 src/ は 1 行も 触っていないので挙動は変わらない。取る理由は、これ以降あるタグから焼き直した イメージが、そのタグで試したものと同じになること。

変更

  • 依存を uv.lock で固定した。 宣言は下限しか書いていないので、これが無いと 同じコミットから別のものができる——同じ Dockerfile で焼き直すたびに イメージの中身が変わり、「いつから壊れたか」が追えない。CI もイメージのビルドも uv sync --frozen にした(lock と pyproject.toml がずれていたらそこで落ちる)。 上限は書かない——lock があれば要らないし、上限はライブラリとして使われる ときに他と共存しにくくする。更新は Dependabot が毎週まとめて出す ——固定は「新しいものを見なくてよい」という意味ではない。動かすのは lock だけで、 宣言の下限は触らせない(入れた版まで引き上げるのは「それより古いと動かない」と 確かめずに言うことになる)。

0.0.5 — 2026-08-29

公開面の脆弱性を 1 件塞ぎ、NR の宣言を検証できるようにした版。 どちらも 既に配ってしまった識別子に関わるので、区切って出す。

通しでコードを読み直したときに出たものが大半で、画面を実際に触って初めて 見えたものがその次に多い。

追加

  • 名前空間の決まりを NAAN 側に持たせた(入り方・自己登録・scope の上限)。 組織ごとにしか掛けられなかったが、組織が増えると 1 つずつ掛けるのは現実的で ない——800 機関に同じ制限を入れて回る運用は成立しない。原則を NAAN に置き、 組織ごとの設定はそこから狭めるだけ(広げられない)にした。重ねた結果は 1 か所で決め、発行・登録・認証の 3 か所ともそれを使う。
  • ARK の行き先が変わった記録ark_change)。これが無いと以前どこを 指していたかを復元できずNR を宣言しながら「変わらない」の検証手段が 利用者の側に無かった。監査ログとは別に持つ——監査は NAAN 単位以上の操作しか 残さないが、採番も付け替えも組織が行うので、監査だけでは肝心の変更が落ちる。
  • 発行した ARK の一覧。到達範囲でそのまま絞り、組織で絞り込め、詳細では ??? で公開される記述を全項目見られる。件数は増える一方なので、 検索とページ送りを最初から入れてある。
  • 画面から利用者を登録し、鍵を発行・失効できる。 一覧の「開く」「利用者を 登録」も、存在しないルートを指していて 404 だった。人には鍵の発行の口を 出さない——人に鍵を配ると、その人が組織を離れても鍵が生き残るため。
  • arkhe client disable / enable と画面の同じ操作。認可サーバに寄せた構成では これが arkhe 側の唯一の止め方(鍵を持たないので revoke に効く相手が無い)。
  • 構造化ログと要求 IDX-Request-Id)、/readyz。障害時に追う材料が DB を 直接見る以外に無く、/healthz と兼ねていたのでDB が落ちても Ready のまま だった。認証の失敗理由もサーバ側にだけ残す。
  • ログインとログアウトを監査に残す。 到達範囲で間引かない——失敗した ログインは成功したものより先に見たい記録である。
  • 採番の種別を候補から選べるように(DataCite の resourceTypeGeneral)。 縛りではない——ERC の what は語彙を定めないので、一覧に無いものは直接 入力できる。
  • ロゴ。ἀρχή の α をパスで描いた。favicon にも使う。

修正

  • 公開リゾルバの保存型 XSS。 転送先にスキームの制限が無く、javascript: を 採番できた——?info は認証を要さない公開ページなので、ark:mint を持つ主体が リゾルバのオリジンで動くスクリプトを他人に踏ませられた。登録は絞らない (ARK は物理オブジェクトにも他の識別子にも付けられるので urn: doi: ark: は 正当)。ブラウザに解釈させると危ないものだけ拒み、転送してよいかは別に判断 する。画面には CSP を付けた。
  • 一覧が使えなくなる規模に備えた。 組織管理の画面は毎回 ark 全体を集計して いた(30 万件で Seq Scan、実測 27.6ms → 読む行が 30 万から 7,500 件に)。 利用者一覧と監査ログにも検索とページ送りを入れた——監査は直近 200 件で頭打ち で、古いものを見る手段が無かった。
  • 押しても断られるだけのボタンや導線を出さない。 組織単位の管理者に監査ログの リンクが出て 403 になっていた。出ている導線を片端から開いて 1 つも断られない ことをテストで確かめている。
  • 認可サーバに寄せた構成で、正しく設定できている利用者が「未設定」に見えていた (鍵を持たないので「資格情報 0 有効」と出ていた)。列を入り方に変えた。 機構が無効な鍵は数えない——持っていても通らないので、あると言うと嘘になる。
  • その構成で使えない鍵を発行できてしまっていた。発行できる種別を、有効な機構 から決めるようにした。
  • 組織の制限が掛けられないように見えていた。約束の水準(組織自身の宣言)と 同じカードに並んでいて、誰が決めることなのかが読み取れなかった。
  • ログインの往復が失効したときに素のテキストを返していた(戻り道が無かった)。
  • 手のひらの幅で表がはみ出し、右側の列が読めなかった。ログアウトも サイドバーごと畳まれて押せなかった
  • ログアウトが GET だった(SameSite=Laxトップレベルの GET 遷移では Cookie を送る)。
  • 日本語の見出しのアンカーが _1 _2 … だった(深いリンクが使えなかった)。
  • 宣言だけで作られていなかった外部キー。use_altercreate_table の中では 後追いの ALTER にならない——alembic check が指していたのは誤検出ではなかった。

変更

  • api/admin.py 1,100 行を画面ごとに分割した(最大 316 行)。行を動かした だけで中身は変えていない。
  • 「できること」(scope)と組織の制限をチェックボックスにし、語彙を 1 か所から 出すようにした。自由入力だと、検査されない綴りを登録できてしまう

0.0.4 — 2026-08-29

管理画面を実際に触って出てきたものだけ。押せるのに何も起きないボタンと、 止めたいのに止められない主体——どちらも、画面が言っていることと実装が 食い違っていた例である。

追加

  • 画面から利用者を登録し、鍵を発行・失効できるようになった。 一覧の「開く」と 「利用者を登録」も、存在しないルートを指していて 404 だった。平文は発行の応答に しか載せない(リダイレクトすると取り出せなくなる)。人には鍵の発行の口を 出さない——人に鍵を配ると、その人が組織を離れても鍵が生き残るため。組織単位の 管理者も自組織の利用者を扱える。
  • arkhe client disable / enable と、管理画面の同じ操作。

変更

  • 認可サーバに寄せた構成の利用者画面に、その認可サーバの場所(issuer)を出す。 「秘密は認可サーバで作る」とだけ書いても、どの認可サーバのことか分からなかった。
  • ログイン画面と案内画面の言語切り替えを、管理画面と同じアイコンの形に統一した。 横並びのセグメントは、言語が増えると横に伸びて破綻する。
  • はじめて立ち上げるときの手引きに、認可サーバ側での鍵の作り方(Keycloak の コンソールと Admin API)と、入れ替え・停止をどちらでやるかの表を足した。

修正

  • 認可サーバに寄せた構成で、arkhe 側から利用者を止める手段が無かった。 oidc では資格情報を arkhe が持たないので revoke は効かず、Client.active を 落とす操作もどこにも無かった——認可サーバが出し続けるトークンで通り続ける。 「認証できることと、この名前空間を触ってよいことは別」と言いながら、その判断を 取り消せなかったことになる。去った組織の主体は戻せない(個別の復帰で離脱の 宣言を骨抜きにしない)。
  • 認可サーバに寄せた構成での「利用者を登録」が、何をする操作なのか画面に書いて いなかった。 鍵を出さないので何もしていないように見えるが、この登録が 認可サーバの主体と arkhe の到達範囲を結びつけている——登録が無ければ、正しい トークンを持っていても通らない。識別子として何を入れるか(機械は azpclient_idsub、人は preferred_usernameemailsub)も明記した。
  • その構成で使えない鍵を発行できてしまっていた。 authenticateARKHE_AUTH に挙がった機構しか試さないので、oauth2 を有効にしていない構成で client_secret を出しても、どこからも通らない(compose のデモがまさにこれ)。 発行できる種別を有効な機構から決めるようにした。
  • 押しても断られるだけのボタンや導線を出さないようにした。 組織単位の管理者に 監査ログのリンクが出ており、押すと 403 になっていた。採番の導線も ark:mint を 持たない主体に出ていた。判定はルートと同じ式を使う(別々に書くと、今度は逆に 「ボタンは出ないが URL は通る」穴になる)。出ている導線を片端から開いて、 1 つも断られないことをテストで確かめている。
  • ログインの往復が失効したときなどに、素のテキストを返していた。戻り道が無く、 利用者は URL を手で直すしかなかった。 ログイン画面と同じ外枠を共有する案内画面に し、「ログインし直す」を置いた。
  • 手のひらの幅で表がはみ出し、右側の列が読めなかった。カードに overflow: hidden があるためページは伸びず、代わりに切り取られていた。 640px 以下では 1 行を 1 枚に畳み、各値の前に見出しを出す。
  • 狭い画面ではログアウトが押せなかった。 サイドバーの底に名前の無いアイコンと して置いてあり、860px 以下ではそのサイドバーごと畳まれていた。ヘッダーに移した。
  • 日本語の見出しのアンカーが _1 _2 … になっていた。既定の slugify が非 ASCII を 落とすためで、日本語ページへの深いリンクが使えず、見出しを 1 つ足すと番号が ずれて既存のリンクが黙って別の場所を指していた。
  • 変更履歴を書いても公開が追随しなかった。docs ワークフローのパス条件に CHANGELOG*.md が入っていなかった(本文は --8<-- で取り込んでいる)。
  • バージョン方針のページに版番号を直書きしていて、0.0.1 のまま古くなっていた。 リリースのたびに古くなるものは文書に書かない。

0.0.3 — 2026-08-29

管理画面が、採番だけの画面から台帳を組める画面になった。0.0.2 と同じく、 出てきた欠陥はどれも実際に画面を触って見つけたもので、テストでは 1 つも 出ていない。

追加

  • 管理画面から台帳を組めるようになった。 一覧にあった「NAAN を登録」 「組織をオンボード」「shoulder を切り出す」「操作」の 4 つのボタンは、 いずれも存在しないルートを指していて 404 だった。実装し、NAAN と組織と shoulder の設定画面も足した。
  • 約束の水準を設定できるようになったarkhe manager commitmentarkhe onboard --commitment、管理画面)。??? で公開されるのに設定する 手段が無く、全組織が既定の permanent-dynamic を名乗ったままだった。組織が 述べていない約束を組織の名前で名乗ることになる——宣言していないものを宣言と して出すのは、何も出さないより悪い。 --commitment を付けずに迎えた場合は その旨を stderr に出す。未知の水準は拒む。 その組織の管理者自身も変えられる——約束は組織自身のもので、述べる主体が 述べられなければ意味がない。
  • arkhe manager list。組織の id は他のコマンドの入力になるが、一覧する手段が 無かった。
  • set_quota。採番上限をオンボード時にしか決められなかった。自組織では 変えられない——課された側が外せる上限は上限ではない。
  • コマンドが日本語と英語を話す。 言語は起動時に環境から決まる(ARKHE_LANG、 次に LC_ALL / LC_MESSAGES / LANG を POSIX の順で見て、既定は管理画面と 同じ ja)。Typer が help を組み立てるのは import の時点なので、実行時の --lang は作れない。
  • 一から立ち上げるときの手引き(日英)。arkhe の外で起きる手順——NAAN の 申請と、NAAN registry への解決先 URL の登録——も含めて並べた。後者が抜けると n2t.net/ark:/99999/… は自分のところに届かない。
  • compose/oidc/lan.yml。LAN の別の端末からデモを見るための上書き。公開先を 0.0.0.0 にするだけでは足りず、issuer と redirect_uri はブラウザが実際に打つ URL でなければならないので、ARKHE_DEMO_HOST で受け取り、redirect は realm JSON に焼き込まず起動時に登録する。既定の待ち受けは 127.0.0.1 のまま——この一式は 秘密値を平文で持っているため。

変更

  • 画面の言葉を、台帳を初めて見る人に向けて書き直した。 一覧の名前は 「委譲の構造」から 組織管理 へ。ボタンは何が起きるかを述べる形にした (「組織をオンボード」→「組織を追加」、「shoulder を切り出す」→ 「名前空間を追加」)。組織を追加する画面には、同時に名前空間を渡すことを 最初に書いた。「主体と資格情報」は「利用者と鍵」に——ここに並ぶのは組織そのもの ではなく、組織のシステムと人だから。採番の欄は「shoulder」ではなく 「採番する名前空間」に(選ぶのは NAAN と shoulder の組であって shoulder だけ ではない)。約束の水準が生の値のまま出ることも無くなった。
  • 用語は捨てず、括弧で残す。「名前空間(shoulder)」「永続・内容は変わりうる (permanent-dynamic)」のように平易な言い方を先に置いて用語を添える。初めての 人はそのまま読め、用語を知っている人は仕様・CLI・API と対応が取れる。
  • 名前空間を渡す先を指す語を「機関」から 組織 に統一し、NAAN を 「組織番号(NAAN)」と呼ぶことにした(Name Assigning Authority Number で、 番号を持つのは組織のほう)。画面・コマンド・エラー文言・文書まで通して揃えた。
  • 画面の「利用者」と、API・CLI の「主体(principal)」が同じものであることを 文書に明記した。読み手が違うので呼び方は分けたままにしてある。対応表を 管理画面とコマンドの両方のページに置いた。

修正

  • ログアウトできなかった。 こちらのセッション Cookie は消していたが、認可 サーバのセッションはそのままだったので、次に画面を開くと何も訊かれずに戻って きていた。OIDC の構成では認可サーバ側も終わらせる(RP-Initiated Logout)。 id_token_hint は渡さない——渡すには ID トークンを Cookie に抱えることになり、 claim の多い環境で 4 KB を超えてブラウザに黙って捨てられ、今度はログイン できなくなるend_session_endpoint を持たない認可サーバではこちら側だけで 終える。
  • NAA ポリシーを組織管理者が書き換えられた。 これは名前空間を配る側の宣言で NAAN 配下の全組織にかかるので、1 組織が他組織の分まで言い直せてはならない。 NAAN 単位以上を要求するようにした。組織が自分について述べるのは約束の水準の ほうで、そちらは組織管理者が変えられる——この分かれ方は権限表ではなく、 ARK の委譲の構造がそのまま出たもの。
  • NAAN の設定画面を組織管理者が開けてしまい、保存で 403 になっていた。編集できる ように見えて保存できないフォームは、ボタンが出ないのに URL は通るのと同じ欠陥 なので、開ける条件を保存できる条件に揃えた。

0.0.2 — 2026-08-28

すべて、0.0.1 を Kubernetes と compose に実際に載せて出たもの。テストでは 1 つも 出ていない——4 件とも「コードが正しい」と「デプロイできる」の間に落ちていた。

修正

  • /healthz をどのモードでも載せた。resolve ルータにしか無かったので、minter と admin は liveness probe に 404 を返し続け、繰り返し殺されていた。
  • resolver に認証設定を要求しないようにした。認証を通す口も管理画面も無いのに、 起動時に ARKHE_SESSION_SECRET と OIDC の設定を求めていた——使いもしない セッション署名鍵を、解決系の全ノードに配らせていたことになる。
  • shoulder を指定した主体が組織を継ぐようにした。--shoulder だけ渡すと manager が空のまま作られ、認可の入口で必ず弾かれていた。しかも「shoulder は 合っているのに通らない」という追いにくい形で。shoulder と食い違う manager を 明示した場合は、黙ってどちらかを優先せず拒む。
  • ラベルの一意性は、ラベルがあるときだけにした。(manager_id, label) の一意制約に 空文字が含まれていたため、1 組織にラベル無しの主体を 1 つしか置けなかった。 プロセスごとに鍵を分ける普通の構成(web-api / web-ui / worker)が通らず、 鍵を共有させる圧力になっていた。移行は 56e5e54db345
  • compose のブラウザログインが invalid_scope: openid profile email で落ちていた。 realm の import で clientScopes を宣言すると Keycloak 組み込みの一式は追加では なく置き換えになるため、profileemail が realm に存在していなかった。

変更

  • デモ realm の defaultDefaultClientScopes から arkhe-api を外した。realm の 既定に入れていたので、後から作ったどんなクライアントでも arkhe 宛だと名乗れる トークンを取れた。audience は「このトークンがどの API 向けか」の宣言であって、 既定で配るものではない。
  • compose の resolver を独立したサービス(:8058)にした。デプロイ時と同じ形に なるうえ、Keycloak を止めると採番が 401 になり解決は 302 のままであることが、 そのまま見える。

0.0.1 — 2026-08-28

最初のタグ。プレリリースであり、版が 0 で始まる間は MINOR が破壊的変更を運ぶ。

追加

  • ARK の採番と解決。? / ?? / ?info / ?json の inflection、suffix passthrough、 検査桁、未知 NAAN のグローバルリゾルバへの取次。
  • 3 段の委譲(system / naan / manager)。ARK が名前空間を受け渡す構造の写しで、 配られた側が配った側より広く届くことはない。
  • API の認証 3 機構(apikey / oauth2 / oidc)。排他ではなく個別に有効化でき、 どれで認証しても Principal 1 つに集約される。
  • 管理画面への入口 4 種類(bearer / password / oidc / proxy)。
  • 操作ベースの管理画面(日英)。テーブルの行編集は持たない——行編集はドメインの 禁則を素通りするため。
  • 承継と離脱。どちらも既存の識別子は解決し続ける。
  • 冪等な採番。同じ request_id の再送には、前回と同じ ARK を返す。
  • ドキュメントサイト(日英、一部は実装から生成)。

備考

  • Django から FastAPI + SQLAlchemy 2.0 へ書き直した。仕様の層(arkspec/domain/resolution.py)は無改造で運べ、97 本のテストがそのまま通った。
  • arkspec/ の一部は Internet Archive の arklet(MIT)から派生。NOTICE を参照。