Ninka 0.8.0 へのアップグレード
0.8.0では、生成されたConsumer Projectionが持つpolicy referenceを、アプリケーションコードがどう指定
するかが両言語で変わります。成果物の形は変わりません。artifact_format_versionは2のままで、
Tegata・Rego・WASMのidentityにも影響しません。変わるのはconsumer側のソースだけです。TypeScriptでは
policiesテーブルの引き方、C#では生成された入力契約から参照を取り出す書き方です。
npm install ninka-authz@0.8.0
.NETプロジェクトもNinka.Authzパッケージの参照を0.8.0へ更新します。この改版は成果物の契約に触れない
ので、load時のversion拒否によって両者の順序が強制されることはありません。大きなコードベースでは、
都合の良い順に言語ごと進めてください。
ステップ1:ハイフンを取ると衝突するpolicy idがないか確認する
0.8.0は、すべてのpolicy idから参照名を導出します。ハイフンを取り除き、次の文字を大文字にする規則
です。この導出は単射ではありません。数字に大文字が無いので、a-1とa1はTypeScriptではどちらも
a1、C#ではどちらもA1になります。
規則C7(TEGATA_SPEC §10.1)が、どちらの言語の生成projectionが存在するより前、コンパイル時に
この組を拒否します。C7が見るのは、ハイフンを取り除いたidが一致するかどうかだけです。大文字化には
触れないので、規則の範囲は導出より広くなります。document-accessとdocumentaccessは
documentAccessとdocumentaccessという別々の名前になりますが、C7はこの組も拒否します。これは
意図した強化です。ハイフンの有無だけが違う2つのidは、どの言語がどう名付けるかと関係なく、差分を
読む人が取り違えます。したがって、プロジェクトを照らし合わせる相手は上の導出ではなく、次の一文
です。
1つのワークスペース内の2つのpolicy idが、ハイフンを取り除いた後に一致してはならない。
確認:
npx ninka-authz build
該当する組があるプロジェクトは、ここで初めて気づきます。数ステップ先の生成ファイルの中ではなく、 入り口で止まります。
[error] [C7] policy ids "a-1" and "a1" are the same once hyphens are removed; rename one so the two can be told apart in a diff
該当するTegataファイルの中で、どちらか一方のidを変更してください。この変更はそのpolicyの
tegata_hashを変えます。policy.idはcanonicalなフィールドだからです。仕様変更と同じ扱いで
レビューを通してください。そのpolicyの成果物はすべて再ビルドされます。ルール自体を変える必要は
ありません。
buildがすでに終了コード0で終わるなら、プロジェクト内に衝突はありません。ステップ2とステップ3が
アップグレードのすべてです。
ステップ2:TypeScript「policiesをidそのものではなく導出した名前で指定する」
// before — 0.7.x
const allowed = authz.check(policies["invoice-access"], input);
// after — 0.8.0
const allowed = authz.check(policies.invoiceAccess, input);
policiesは変わらず同じ生成ファイルからexportされ、reference自体も正確な、変換されていないidを
そのまま保持します(policies.invoiceAccess.id === "invoice-access")。変わるのはtableの引き方
だけです。
旧構文への橋渡しはありません。生成されたpoliciesはもう生の文字列で引けないので、この手順を
飛ばしたプロジェクトはtscで止まります。TypeScriptを使っていなくても同じです。check()に
policy idの文字列を渡すと実行時に例外になるので、JavaScriptから呼んでも判定には届きません。
低レベルのruntimeにあるcheckByPolicyIdはcheck()のオーバーロードではなく別のメソッドで、
以前からverification/CLI用の内部配管として文書化されていました。0.8.0はそれに合わせて
published typesから外すので、これを直接呼んでいたプロジェクトもこの経路を失います。
呼び出し箇所を洗い出す:
grep -rnE 'policies\["[^"]+"\]' --include='*.ts' --include='*.tsx' . | grep -v node_modules
見つけた箇所をそれぞれ書き換えます。角括弧と引用符を外し、idからハイフンを取り除き、取り除いた ハイフンの直後の文字を大文字にします。
ステップ3:C#「参照は入力型からではなくPoliciesから読む」
// before — 0.7.x
var allowed = authz.Check(InvoiceAccessInput.Policy, new InvoiceAccessInput { … });
// after — 0.8.0
var allowed = authz.Check(Policies.InvoiceAccess, new InvoiceAccessInput { … });
InvoiceAccessInput(入力契約の型)自体は変わりません。移るのはpolicy referenceだけで、移った先は
新しく生成されるPolicies containerです。
先にprojectionを再生成し、コンパイラが解決できるようPoliciesを存在させてください。
npx ninka-authz build --out-csharp Generated/Ninka.g.cs
呼び出し箇所を洗い出す:
grep -rnE '\w+Input\.Policy\b' --include='*.cs' . | grep -v /obj/ | grep -v /bin/
<Name>Input.PolicyをそれぞれPolicies.<Name>へ書き換えてください。書き換え漏れが残っていれば、
そこでビルドエラーになります。これはコンパイラがこのステップの残りを代わりにやっている状態です。
.Policyメンバはもう入力型に存在しません。
確認
npx ninka-authz build --out <projectionのpath> [--out-csharp <C# projectionのpath>]
npx ninka-authz verify --out <projectionのpath> [--out-csharp <C# projectionのpath>]
✔ invoice-access: match (tegata_hash c2b55b92fb53…)
✔ src/generated/ninka.ts: Consumer Projection matches (1 policy)
✔ Generated/Ninka.g.cs: Consumer Projection matches (1 policy)
verify: all artifacts match
続けてアプリケーション自身のテストを実行してください。TypeScriptでpolicies["<id>"]をmockまたは
assertしている箇所、C#で<Name>Input.Policyを参照している箇所は、上と同じ書き換えが必要です。
現行の形は認可をテストするを参照してください。
再生成したprojectionは、ソースの変更とあわせてコミットしてください。ステップ1でpolicyを改名した
場合は、再ビルドした成果物もコミットします。git statusは、生成物が未追跡や変更のまま残っていない
状態になっているはずです。
関連項目
- 0.7.0へのアップグレード:一つ前のアップグレード。CLIコマンド名を変更したもの。
- ランタイムAPI:
policiesテーブルと導出規則。 - .NETランタイムAPI:
Policiescontainer。 - 認可をテストする:現行の形での呼び出し例。