sha256 digestになります。一度取得し、それぞれのdigestを内容に照らして検証すれば、同じバイト列がオフラインでも、CIでも、エアギャップの内側でも、いつまでも実行されます。
Packがデプロイ単位である理由
Packは、本来なら3つの異なる方法で答えられがちな3つの問いに対する、単一の答えです。デプロイ
1つのアーティファクトを公開します。そのflowは、選択したlauncherでデプロイ可能になります。
バージョン管理
人間向けにはsemver、機械向けには不変のmanifest digestを提供します。
複製
RegistryはPackをdigestでミラーするため、固定され検証済みの状態で届きます。
@acme/pricing packを使います。これはsearch-price@1.2.0 browser toolとdaily-price-watch flowを保持しています(ブラウザーでの検索、変換、その後にシークレットwebhookへの条件付きhttp.post)。
packディレクトリのレイアウト
ディスク上のPackは、manifest、2つのフォルダー、readmeで構成されます。ToolContractとbodyを持ちます。search-priceの場合、そのbodyは正規化されたブラウザーRecordingであり、そのdigestがToolのprovenance.source_digestです(ブラウザーToolを参照)。各Flowディレクトリは、コンパイル済みで完全に固定されたFlowSpecを持ちます。そのうえで、manifestがそれらすべてをdigestで閉じ込めます。
PackManifestスキーマ
pack.jsonはPackManifestです。含まれるすべてのToolとFlowをdigestで列挙し、すべてのdependencyを固定します。これにより、Pack全体が再現可能になります。
@acme/pricingでは、tools[]が{ ref: "search-price@1.2.0", contract_digest: … }とそのhttp.post dependencyを持ち、flows[]が{ name: "daily-price-watch", flow_digest: … }を持ち、dependencies[]がFlowの依存する標準Packを固定します。トップレベルのdigestは、Pack全体の不変のアイデンティティです。
toolの
contract_digestは、その入力、出力、capabilitiesが変わるたびに変わります。そのため、互換性のない変更がpatchのふりをすることはできません。digest mismatchはruntimeではなくresolve時に表面化します。Packを公開する
Packのオーサリングは3つのコマンドで行います。manifestを初期化し、アーティファクトを追加して(そのdigestを計算し)、公開します。toolsとflowsを追加する
各
addはアーティファクトを正規化し、そのdigestをmanifestに記録します。toolはcontract digestで、flowはFlowSpec digestで記録されます。name@versionは常にまったく同じバイト列へresolveされます。Manifestの署名は任意であり、digestの上に重ねられるものです。完全性はdigestから、真正性は署名から得られます。またRegistryは、Packを受け入れる前に、信頼されたキーによる有効な署名を要求できます(replicationを参照)。
Packを利用する
利用側ではrangeを追加してからinstallします。追加するとresolveされて固定され、installすると取得と検証が行われます。browserflow installは固定済みのすべてのPackを取得し、何かがresolveまたは実行を許可される前に、すべてのdigestを内容に照らして検証します。改ざんされたPackや不完全なPackは、最初の段階で検証に失敗します。
lockfileは再現性の契約
browserflow compile(およびinstall / pack addコマンド)は、固定済みの各Tool refについて、正確にresolveされたversionとそのcontract digestを記録するbrowserflow.lockを書き出します。
browserflow.lockからinstallする2台のマシンはバイト単位で同一のtoolsを取得します。あるマシンがリプレイするsearch-price@1.2.0 Recordingは、別のマシンがリプレイするRecordingとbit-for-bitで同じです。これは、システムの残りの部分が前提としている性質です。
なぜ「npmだけ」ではなくpacksなのか
Packsはnpm、OCI registry、object storageを経由して移動できます。しかし、それらはtransport、つまりバイト列を運ぶ方法であり、Packが実際に追加するものではありません。 Packが任意のtransportの上に追加するのは、実行可能な振る舞いのcontent-addressed検証です。Packのアイデンティティは、そのtoolsのcontractsとbodies、およびflowsのspecsのdigestです。付け替え可能なlabelではありません。具体的には、次のとおりです。| 汎用タグ(npm / OCI) | Pack | |
|---|---|---|
| アイデンティティ | 変更可能なname@version label | contracts + bodies + specsのsha256 digest |
| 検証対象 | transportの完全性以外は何もない | 到着時に、すべてのtoolとflowのdigest |
| 付け替えリスク | tagはひそかに移動されうる | 不変のdigestは付け替えられない |
| エアギャップ | sourceを信頼する | バイト列が主張されたdigestへhashされることを検証する |
digest mismatchが起きるとどうなりますか?
digest mismatchが起きるとどうなりますか?
実行前に検証が失敗します。改ざんされた、切り詰められた、または部分的に取得されたPack、つまり内容がmanifestまたはlockfileに記録されたdigestへhashされないものは、install時またはmirror時に拒否され、黙って実行されることはありません。同じチェックは、バイト列がHTTPS、OCI、object storage、file bundleのどれで届いた場合でも同一に実行されます。
replication中のhard conflictとは何ですか?
replication中のhard conflictとは何ですか?
同じ
name@versionの下で2つの異なるbodyが公開されることはhard conflictであり、黙って上書きされることはありません。semverとdigestの不変性がそれを禁止します。sync mirrorは勝者を選ぶのではなく、conflictを表面化します。replicationを参照してください。シークレットがPack内に存在することはありますか?
シークレットがPack内に存在することはありますか?
ありません。
secret: true inputがFlowSpec、Journal、log line、公開済みPackに現れることは決してありません。daily-price-watchがpostする先のシークレットWEBHOOK_URLは参照としてのみ運ばれ、secrets capabilityを宣言する手順の中で実行時にresolveされます。secretsを参照してください。関連
Registryの複製
RegistryがPackをdigestでミラーする方法です。pull、push、sync、scheduledで、到着時に検証します。
スキーマ
PackManifest、ToolContract、FlowSpecの完全なスキーマを1つのリファレンスにまとめています。
エアギャップデプロイ
live registryなしで、エアギャップ越しにpacksをbundle、transfer、verifyします。
ToolとPackの概要
Tool contract、標準Pack、ブラウザーToolがどのように記録されるかを説明します。