メインコンテンツまでスキップ

生成ファイル

Ninka が生成する出力は、大きく二つに分かれます。

  1. ninka/out/ 以下に置かれる canonical artifact
  2. アプリケーションのソースツリーに生成される Consumer Projection

同じ「生成ファイル」でも、読む側と役割が違います。

出力主な場所主な利用者
canonical artifactninka/out/verify、Authorization Reference、artifact を扱うツール、必要に応じたディレクトリ読み込み型 runtime
TypeScript Consumer Projection<source root>/generated/ninka.ts または --outTypeScript アプリケーションと ninka-authz/runtime
C# Consumer Projection--out-csharp で指定したパス.NET アプリケーションと Ninka.Authz

ninka/out/ の構成

ninka/out/
├── policies/
│ ├── <id>.rego
│ ├── <id>.manifest.json
│ └── <id>.validation.json
├── bundles/
│ ├── <bundle-id>.wasm
│ └── <bundle-id>.build.json
└── input-contract.json

policies/ 以下のファイルは、一つのポリシーについて Rego、identity・lineage、validation を表します。bundles/ 以下は実行単位です。一つの bundle には一つの WASM module があり、その bundle に属する各ポリシーがそれぞれ entrypoint を持ちます。

artifact contract 上は複数 bundle を扱えますが、現在の toolchain はワークスペースに対して一つの bundle を生成します。bundle の分割単位は、利用者が認可設計として設定するものではありません。

artifact と Git 管理は別

Ninka の canonical artifact だからといって、すべてのリポジトリがそのファイルを Git で追跡する必要があるわけではありません

リポジトリの役割によって、追跡する生成物は変わります。

リポジトリの役割主に追跡するものraw WASMmodule identity の根拠
Projection-only application手形 + Consumer Projection不要projection に埋め込まれた module と build record
Reviewable-artifacts application (init の既定)手形 + raw WASM を除く ninka/out/ + projection不要build.json.wasm_sha256
Artifact / conformance corpusartifact 一式追跡するmodule 自体のバイト列

ninka-authz init/ninka/out/bundles/*.wasm.gitignore に追加します。通常の scaffold では、上の二つ目の構成になります。

どの構成でも verify を使えます。verify は Git を参照しないからです。必要なファイルが解決されたパス上に存在するか、現在の認可入力と toolchain から再現した状態と一致するかを filesystem 上で検査します。

普遍的なルールは「すべての artifact を commit する」ではありません。リポジトリが追跡すると決めた生成状態は、そのリポジトリが追跡する認可入力と、固定された toolchain の条件から再現できる必要があります。規範は TOOLCHAIN_SPEC §10.4 にあります。

ファイル一覧

ファイル生成される時点役割
policies/<id>.regoソース検査の成功後一つの手形から決定論的に生成された Rego
policies/<id>.manifest.jsonソース検査の成功後policy identity、Rego lineage、entrypoint、入力要件、Decision Log の開示情報
input-contract.jsonソース検査の成功後プロジェクト全体で統合した入力契約
bundles/<bundle-id>.wasmOPA build 成功後実行用 WASM module
bundles/<bundle-id>.build.jsonbundle とともに生成し、validation 後に validation 情報を確定module identity と policy-to-module binding
policies/<id>.validation.json生成された validation が新しい WASM に対して成功した後現在の手形から導いた validation table

Consumer Projection は ninka/out/ の外に生成され、埋め込む bundle がある場合だけ書き出されます。

OPA を解決できない場合、通常の compile は Rego・manifest・input contract など WASM を必要としない成果物までは生成できます。完全な実行 bundle が必須なら build を使います。


Consumer Projection

TypeScript

TypeScript の Consumer Projection は、アプリケーションが使う次のような API を export します。

import { createNinka, policies } from "@/src/generated/ninka";

const authz = await createNinka({
onDecision: (event) => logger.info(event),
});

const allowed = authz.check(policies.invoiceAccess, input);
export意味
createNinka(options?)埋め込まれた bundle から Ninka instance を作る。現在の生成 API では onDecision で Decision Log entry を受け取れる
policies各policyのpolicy idから導出した名前(ハイフンを取り除いたcamelCase)をキーにした table。各 entry が変換前の正確な id・tegataHash と生成された入力型を結び付ける

生成されたファイルには、意図的な runtime dependency が一つあります。ninka-authz/runtime を import します。一方、実行時に ninka/out/ のファイルを import したり読み込んだりはしません。build record / manifest の内容と WASM を base64 としてファイル内に保持し、runtime がそれを検証・instantiate できる形にしています。

Consumer Projection 自体が、認可ルールをアプリケーションの条件分岐として再実装するわけではありません。WASM の decode、artifact identity の検証、instantiate、Decision Log の masking、check() の評価は runtime が担います。

C#

C# の Consumer Projection は --out-csharp <file> を指定した場合だけ生成されます。Ninka.Authz から利用できるように、同等の bundle 情報と、生成された policy reference / input contract を保持します。

構文は TypeScript と異なりますが、目的は同じです。アプリケーション側で artifact binding を組み立て直すのではなく、生成されたソースをアプリケーションとの境界にします。

projection を最新に保つ

ファイルの先頭は、どのリリースとどの bundle から生成したかを記録します。ただし、そのヘッダーだけで「現在の手形に対して最新か」を判定するわけではありません。

ninka-authz verify は、解決した出力先、または --out / --out-csharp で指定したパスに Consumer Projection を再生成し、ディスク上のファイルとバイト単位で比較します。verify は projection を書き換えず、Git で追跡されているかどうかも確認しません。

実行時には、生成された policy reference が tegataHash も持っています。古い projection を別の仕様版の bundle と組み合わせた場合、check() は hash mismatch を整合性エラーとして拒否し、誤った契約で評価を続けません。

設計上の役割は Consumer Projection、API の詳細は runtime reference を参照してください。


policies/<id>.rego

一つのポリシーについて、Ninka コンパイラが決定論的に生成した Rego です。

認可判定のロジックは含みますが、policy.descriptionaudit のようなレビュー専用情報、build timestamp などは含みません。OPA build より前に生成されます。

TypeScript / .NET の runtime は .rego を直接評価せず、コンパイル済みの WASM を実行します。

verify は現在の手形から Rego を再生成し、ディスク上の .rego とバイト単位で一致することを確認します。


policies/<id>.manifest.json

manifest は、一つのポリシーについて 手形 → Rego の対応と runtime contract を持ちます。

フィールド意味
policy_id手形に書かれた正確な policy id
tegata_versionTegata の language/schema version。現在は "0.1"
artifact_format_versionartifact contract の version。現在は 2
generated_bymanifest を生成した Ninka package/release。仕様 identity ではなく provenance
tegata_hashcanonical な手形の認可内容を識別する hash
rego_sha256生成された Rego バイト列の SHA-256
entrypointcompiler が導出し、このポリシー用として宣言する WASM entrypoint
covered_resource_typesポリシーが対象とする resource type
input_requirementscompiler が導出した入力 key / type / requiredness / origin
decision_log.unmaskedDecision Log でマスクせず記録してよい属性

tegata_hashrego_sha256generated_by は別の役割を持ちます。仕様の hash は生成コードの hash ではなく、生成したリリース番号は仕様 identity ではありません。

runtime は、対応している artifact_format_version を要求します。version が無ければ安全に推測できないため拒否します。対応外の古い / 新しい artifact format も、再コンパイルまたは runtime upgrade が必要なことを示して拒否します。


bundles/<bundle-id>.build.json

build record は、一つの実行 bundle について Rego → entrypoint → WASM の対応を持ちます。

フィールド意味
bundle_idbundle id。build/module のファイル名と対応する
artifact_format_versionartifact contract version
generated_bybundle を build した Ninka リリース
opa_versionOPA build の provenance。通常は設定された固定 OPA version
wasm_sha256生成された WASM バイト列の SHA-256
policies[]bundle に含まれる各ポリシーの binding

各 binding には次が入ります。

フィールド意味
policy_idこの binding が表すポリシー
entrypointmodule 内でそのポリシーを評価する entrypoint
rego_sha256Rego lineage。対応する manifest と一致する必要がある
validationvalidation 成功時の vector 件数、digest、status

build record は tegata_hash を重複して持ちません。手形から Rego までを manifest が持ち、Rego から実行 module までを build record が持ちます。両者は rego_sha256 でつながります。

runtime は load 時に次を確認します。

  • module のハッシュ
  • artifact format
  • binding の policy id
  • Rego の系譜
  • manifest と binding の entrypoint が一致すること
  • 宣言した entrypoint が実際の module に存在すること

bundle は一つの実行成果物です。bundle 内のどれか一つの必須 binding を検証できなければ、「確認できたポリシーだけ」を使うのではなく bundle 全体を拒否します。


policies/<id>.validation.json

validation table は 現在の手形から生成され、新しく build した WASM が必要な期待判定と一致した後に書き出されます。

ファイルには policy id、tegata_hash、validation format version、生成された vector が含まれます。

現在の evidence family は主に次の三つです。

vector id の prefix目的
allow:<rule-id>policy 全体の条件下で allow rule が実際に許可を与える positive witness
what-if:<rule-id>:...生成した witness の一要素を変えた場合の判定
deny:<allow-rule-id>:<deny-rule-id>allow と deny が重なり、deny-overrides が働くケース

positive witness を作れない場合、validation は UNSATUNKNOWN を区別します。UNSAT は制約上成立しないことを証明できた場合、UNKNOWN は bounded search で witness を確定できなかった場合です。どちらも positive coverage の成功としては扱いません。

期待される判定は、生成された compiler output 自身から作るのではなく、Tegata semantics を独立に評価する reference evaluator が決めます。生成された Rego に「自分の正解」を答えさせて、その答えで同じ出力を検証する構造ではありません。

verify は table を現在の手形から再導出してディスク上のファイルと比較し、bundle build record に記録された vector count / digest も照合します。toolchain 条件が揃っている場合は、必要な vector を WASM に対して再実行します。


bundles/<bundle-id>.wasm

OPA が build した実行用 WASM module です。bundle に属する各ポリシーが、それぞれ別の entrypoint を持ちます。

実ファイルの SHA-256 は build.json.wasm_sha256 と一致する必要があります。WASM のバイト列は Rego だけでなく OPA build toolchain にも依存するため、opa_version を provenance として記録し、通常の CLI では OPA version を固定しています。

NINKA_OPA_PATH を使うと、既定の binary を明示的に上書きできます。ただし caller-supplied binary は、Ninka が pinned distribution として checksum 検証する対象ではありません。その override で再現性をどう管理するかは指定した側の責任です。


input-contract.json

コンパイル対象のポリシーを横断して統合した入力契約です。

{
"generated_by": { "package": "ninka-authz", "version": "0.7.0" },
"keys": [
{
"key": "subject.user_id",
"type": "string",
"required_by": ["invoice-access"],
"policies": ["invoice-access"]
}
]
}

各 key の型、どの policy が利用するか、どの policy が required としているかを記録します。policy manifest の input requirement と各言語の生成入力型は、同じ compiler-derived contract 情報から作られます。

言語別の型 projection を ninka/out/ に置くことはありません。

verify は現在の手形から contract を再導出し、ディスク上のファイルのうち再計算可能な内容と比較します。generated_by は contract identity ではなく provenance として別に扱います。


ディレクトリ読み込みと埋め込み読み込み

runtime が ディレクトリから成果物を読み込む場合、実行 bundle と、その bundle に含まれる各ポリシーの manifest が必要です。

bundles/<bundle-id>.wasm
bundles/<bundle-id>.build.json
policies/<id>.manifest.json

TypeScript の Ninka.load(dir) と .NET の Authz.Load(dir) がこの方式です。

通常の生成アプリケーション経路では、実行時に artifact directory は必要ありません。Consumer Projection が同等の bundle / module / manifest の情報を生成ソース内に持っているためです。runtime はそれをメモリ上の artifact の形へ戻し、ディレクトリ読み込みと同じ検証規則を適用します。

Rego、validation table、input-contract.json は、runtime が 1 回の判定を下すために必ずしも要りません。ただし、compile と verification のためのより広い artifact set には含まれます。


Authorization Reference の export は ninka/out/ とは別物

ninka-authz docs -o <dir> は静的な Authorization Reference snapshot を生成します。browser asset、data/reference.json、内容 digest を名前に含めた execution bundle module のコピーなどが入ります。

ninka/out/ とは形式も利用者も異なります。

ninka/out/docs -o snapshot
生成compile / builddocs -o。コンパイルはしない
利用verification / tooling、必要に応じて directory runtimebrowser
Git 管理repository role による通常は export 物として公開・保存・破棄を選ぶ
identityTegata / Rego / WASM それぞれの artifact identity取り込んだ認可状態の snapshot_hash

書き出した時刻は exported_at として別に記録され、snapshot_hash には含まれません。どちらも人間による承認状態を表すフィールドではありません。

LIVE / SNAPSHOT の使い方と公開時の注意点は Authorization Reference を参照してください。

関連項目