Files
yoi/docs/report/2026-10-28-t787-authorization-boundary-inventory.md
Hare a35d9a3d45 fix: retain Host-bound Job input authority through every model supply
Bind immutable Job kind/id/input digest to retained input provenance. Recheck current Host authority after hooks and at each compactor request; restored or rewritten input cannot become a local grant or switch Job identities. Add actual Controller, lifecycle, correction and signed Host/model regressions for Journal and consolidation.
2026-10-28 12:53:48 +09:00

28 KiB
Raw Permalink Blame History

T-787 操作認可境界の棚卸し

観測範囲

2026-10-28、HEAD 618880d38ded5e501d7c926006d1869282f06892 に対する共有作業ツリーの未commit差分を読んだ記録。T-787の本文とAGENTSの文書管理・検証規則を基準にした。実装とテストは並行して変更中であり、この記録は受入条件の充足、テスト成功、全入口の保護完了を示さない。将来の仕様正本や維持対象のAPI一覧ではなく、一律gate撤去で到達可能になる境界の調査証拠として残す。

共通の判断基準は 正本・権限・実行の原則 に置く。下表の操作名は完全一致の例であり、ticket が ticket.create を含むという意味ではない。Workspace 資源はcollection操作用で、別kindの個別資源を含まない。操作名を列挙した行も、列挙以外を許可するものではない。

Feature・経路別の境界

資源名は crates/server-api/src/authorization.rs::PermissionResource のvariantを指す。共通境界欄は読取り時点で確認した呼出し位置であり、provider欄の既存検査とは別の制約である。通常の登録はローカル処理であり、表の外部処理が起動に必須かどうかとは分離する。

以下、WB/ は crates/worker/src/feature/builtin/、WS/ は crates/workspace-server/src/server/、W/ は crates/worker/src/。

Feature・経路 操作例と実資源 共通境界・別入口 合成するprovider側の検査 起動必須性・拒否時の扱い
task 保護された外部操作なし WB/task/mod.rs のTaskStore・Tool登録・履歴replay セッション内の入力検証・保存契約。Subject policyを要求しない ローカル初期化。権限未設定でも起動・操作・restore可能であるべき
image・通常のファイル操作・Bash filesystem.read、filesystem.write、bash.execute / Workdir のID・path・再帰範囲 W/authorized_workdir.rs のsession wrapper。Toolごとの認可だけに頼らない attachment選択、provider scope、解決済みpath・symlink、capability、明示command grant Tool登録だけなら外部読取りなし。ViewImageの読取り・Workdir由来の起動入力は別途検査対象。画像bytesの再供給までの証明は未確認
web web.search / Network のprovider endpoint URL、web.fetch / 各取得・redirect先URL WB/web.rs::WorkspaceWebAuthorizer → crates/tools/src/web.rs。検索のsecret取得・network前、fetchのDNS・network前にcallback 公開HTTP(S)・private/local拒否、credential禁止、redirect・byte・timeout上限、secret provider 任意Toolの登録でsecret読取り・通信をしない。要求時の拒否を通信や空の検索結果に置き換えない
sub_worker subworker.spawn、subworker.send_input、subworker.stop、subworker.observe / Hostで束縛した親runtime/worker+子nameの SubWorker W/spawn/tool.rs、WB/manage_worker.rs、WB/worker_observation.rs → bound-check 親の委譲scope、明示command、子所有、name予約、Reviewer capability、現行委譲上限 登録はローカル。spawn・入力・観測・停止時は実操作。standaloneのローカル親所有child互換を他のWorker制御へ広げない
flow ローカルなFlow状態遷移にFeature起動権限なし。verifierのWorkdir読取りは filesystem.read / Workdir WB/flow_transition.rs のcoordinator・固定capture・read-only internal verifier Flow graph・typed verdict、Session commit、read-only wrapper。verifierにはWorkspaceやBashを渡さない 登録・復元はローカル。verifier実行やファイル読取りまで「ローカルだから無認可」と一般化しない。LLM/provider接続の独立検証はこの読取り調査では未確認
worker・worker observation worker.list、worker.create、worker.observe.list / Workspace。worker.send_input、worker.notify、worker.cancel、worker.stop、worker.restore、worker.remove、worker.observe / 正確な Worker WB/manage_worker.rs のcontrol/lifecycle service、WB/worker_observation.rs control/resource grant、Runtime/Worker所有・状態、観測範囲、削除・restore条件、Subject delegation専用経路 登録でWorker作成・復元を行わない。既存grantやWorker生存を操作認可の代わりにしない
workspace_worker_discovery worker.discover / Workspace WB/workspace_worker_discovery.rs のlist前 bounded query、cursor、Workspace一覧のprovider契約。発見はcontrol/observeの付与ではない 任意Tool。拒否時は下流一覧取得前に失敗
manage_workdir・workdir_catalog repository.list、workdir.list、workdir.attachment.list / Workspace。repository.read、workdir.create / Repository。workdir.read、workdir.attach、workdir.delete / Workdir。workdir.attachment.read、workdir.detach / WorkdirAttachment WB/manage_workdir.rs と manage_workdir/wip.rs。detachはHostがaliasからconnection IDを束縛 provider scope、attachment接続CAS・release fence、稼働占有・削除条件、repository materializer・既存資源grant 登録はローカル。設定済attachmentの準備と任意の作成/解除Toolを区別。解除と削除を分離し、古いalias観測で別接続を解除しない
workspace_config workspace_config.attach、workspace_config.observe、workspace_config.read、workspace_config.commit / WorkspaceConfig のpath・再帰範囲 WB/workspace_config/backend.rs::authorize_post → 共通HTTP送信。commitはroot entrypoint変更と各path、renameの両側を検査 config tree所有・path検証、observed content/CAS、commitのatomicity WIP登録はローカル。attach/read/observe/commit要求が保護操作であり、FeatureをONにしただけでは許可しない
drive drive.capabilities、drive.root、drive.search / Workspace。drive.metadata、drive.list、drive.read_text、drive.read_chunk、create/update/delete/relocate/uploadの各完全名 / DriveEntry。drive.request_status / DriveRequest WB/drive/backend.rs のtyped backend。Tool・WIPは同backend、chunk/imageは各読取り、relocateは元entry・移動先parentを検査 Drive grant、entry/version/hash、chunk条件、mutation CAS、request receipt・upload条件 登録でroot取得をしない。任意操作の拒否は下流取得/変更前。DriveはWorkdirでもfilesystem権限でもない
ticket ticket.create、ticket.query、ticket.list、ticket.tag.list 等 / Workspace。ticket.read、ticket.edit_item、ticket.case.update、ticket.assignment.answer、ticket.implementation_result.write 等 / 個別 Ticket WB/ticket.rs::WorkspaceHttpTicketBackend、ticket/assignment_tracking.rs、assignment_public.rs、notification_diagnostics.rs。Tool・WIP・typed serviceを照合 authenticated actor、対象canonical化、assignment/event CAS、operation key・exact replay、対象資源条件。relationは両Ticketを検査 登録・service公開だけでは起動認可なし。createは ticket.create のみで旧 ticket の追加要求なし。起動prompt投影の読取りも保護操作
objective objective.query、objective.create / Workspace。objective.read、objective.edit、objective.set_state、objective.link_ticket、objective.unlink_ticket / Objective。リンク情報取得の ticket.read / Ticket WB/objective.rs::WorkspaceHttpObjectiveBackend、native Tool/WIP adapter Objective/Ticket対象検証、Backendの更新条件。関連Ticket本文の読取りをObjectiveの権限に含めない 登録はローカル、明示操作時に認可。関連情報の追加読取りまで証拠を照合する必要あり
merge_request merge_request.open / Ticket。merge_request.read、merge_request.readiness、merge_request.review、merge_request.complete / MergeRequest WB/merge_request.rs::MergeRequestTool とnative WIP dispatch repository selector、source・Ticket digest・snapshot、review capability、actor、integration evidence 登録はローカル。操作認可は承認・統合の実証を代替しない
orchestration 下位の ticket.read / Ticket、worker.create / Workspace 等を合成。独立したFeature起動権限なし WB/orchestration.rs → TicketServiceとWorkerLifecycleService 現行Orchestrator assignment、Ticket targetから導くattachment access、Profile/Flow解決、資源finalization service依存の登録とspawnの実操作を分ける。Toolだけでなくserviceを直呼びする経路の作用0も照合対象
memory(Workspace・Subject) memory.query、memory.document.read、memory.document.update 等 / legacy Workspace。Subject側は memory.query、memory.read、memory.changes.list、memory.resident.read、memory.resident.supply、memory.staging.write 等 / Host束縛の Subject WB/memory.rs のtyped dispatch、WorkspaceSubjektivResidentSummarySource::fetch、load_initial_checked・refresh/restore/pre-requestのsupply検査 Subject本体所有・現行policy、Memory change/proposal条件、Job grant、履歴へのcommit・既存source provenance Subject resident contextは必須処理、Workspace summaryは任意処理。必須拒否は起動失敗、任意拒否は未開始診断。読取り許可は再供給の許可ではない
memory extraction・surface lifecycle memory.extract.read、memory.extract.supply、memory.extract.commit、memory.staging.write、memory.consolidation.request、memory.surface.supply 等 / 接続に応じた Subject またはlegacy Workspace WB/memory_lifecycle.rs::MemoryExtractionAuthority、memory_surface_lifecycle.rs、Host側Job要求 凍結input範囲、抽出cursor、stage/commit条件、Subject/Workspaceの分離、attempt・writer fence hook/task登録はローカル。任意背景処理でも開始・各読取り・モデル供給・commit・次の要求で再検査。取消受付と停止完了は別
Subject Journal・Subject Job入力 journal.startup.read、journal.startup.supply、journal.compaction.read、journal.compaction.supply、journal.recording.request、journal.job.input.read、journal.job.input.supply 等 / Host束縛の Subject WB/journal.rs、WB/backend_job_input.rs、W/subjektiv.rs → WS/subjektiv_journal.rs、subjektiv_job.rs、subjektiv_memory_journal.rs domain grant、現在の本体、Job immutable batch・origin・attempt・digest・期限・writer、receipt・journal位置 startup grantがない構成は読取りを開始しない。構成されたstartup contextは必須、recording/compaction補助は各拒否・unavailableを診断。Job入力は各モデル要求とrestore後にも再検査
MCP(暫定維持) 既存の完全名 mcp / Feature W/feature.rs::authorize_requested_manifest、controller discovery、既存activation guard 既存stdio設定・プロセスspawn/終了・Tool登録・cleanup/retry・restore契約 discovery前の既存拒否を保持。他Featureの新原則を用いて既存gateを削除しない。新しいserver/Tool/resource別認可や常時接続は対象外

旧grant・Job・文書の整合

差分の ScopedPermission::covers は操作名を完全一致で比較し、resource containmentはkindを跨がない。Feature variantと旧トップレベル名の保存形式は残るが、MCP以外の旧Feature grantは新しい操作の権限にならない。旧Workspace grantも個別Ticket/Subject/Worker等へ展開しない。schemaの自動書換えや全Subjectへの基礎権限付与を移行の説明にしない。

WS/subject_authorization.rs::job_permissions はJournal/consolidationの限定操作と同じSubject資源に絞り、現行policyとの積集合を取る。active_grant、凍結originの現在の本体所有も検査する。一般Jobは空のSubject権限であり、旧Jobのorigin欠落は拒否される。これはJob grantだけで許可する契約でも、Subject policy全体をJobへコピーする契約でもない。権限未設定・domain不一致・失効を非Subject Worker互換へfallbackさせない。

調査時点の維持文書 docs/principle/・docs/development/ には、一律のFeature起動認可を要求する旧説明は見つからなかった。principleへ明示的な境界原則を追加した。docs/report/ は過去の証拠であり、旧状態の記述を現行仕様に書き換えない。所有コードのコメントについては、W/feature.rs と server-api/src/authorization.rs の差分がMCP限定・操作境界へ更新されている。worker-runtime/src/worker_backend.rs::saved_subjektiv_authorization_fixture_grants_only_exact_feature_activation は依然 subjektiv・workdir_catalog の旧Feature名だけを許可するfixtureであり、新しいSubject resident操作・bound-checkの実接続証拠にはならない。

生成契約の所有とscope

実際の出力は web/workspace/src/lib/generated/ と openapi/server-api.json である。付与された apps/web/src/generated/ は既存出力先と一致しないため、新規folder作成・生成物コピー・手修正を行わなかった。所有者は crates/server-api/examples/ と src/repository_openapi_typescript.rs、ts-rs系は src/lib.rs の対応関数である。

  • OpenAPIの生成・照合は cargo run -p server-api --example export_openapi と cargo run -p server-api --example export_openapi -- --check。既定の書込み先は openapi/server-api.json。
  • OpenAPI closureからの出力は cargo run -q -p server-api --example generate_repository_openapi_types、generate_workdir_api_types、generate_runtime_api_types、generate_worker_launch_api_types、generate_ticket_api_types、generate_companion_api_types。各exampleの -- --check は既存出力との照合。出力名はそれぞれのexampleが参照する定数を正本とし、一般的な generated/ へredirectしない。
  • Memoryの出力は cargo run -q -p server-api --features typescript --example generate_memory_api_types > web/workspace/src/lib/generated/memory-api.ts。同様のts-rs系は generate_auth_api_types、generate_skill_api_types、generate_repository_access_types、generate_drive_api_types、generate_legacy_typescript。stdout出力と直接書込み型のexampleを混同しない。
  • server-api/src/lib.rs の generated_worker_launch_api_contract_is_current はOpenAPI closure出力を、generated_memory_api_contract_is_current はtypescript feature時のMemory出力を照合する。これらのCargo testはこの調査では実行していない。
  • 追加された authorization/bound-check と既存 authorization/check は openapi = false の内部契約。PermissionResource のts-rs deriveがあることだけから、全てのenumが既存Web artifactへ出力されるとは判断しない。新variantの影響するschema closureと実際の生成差分は所有者で確認する必要がある。生成物が古いとも差分不要とも、この読取りだけでは断定しない。

未確認の接続・coverage

以下はコード読取りから必要と判断した確認範囲であり、テスト失敗を観測したという意味ではない。

  • task-onlyの起動・direct install・restoreでFeature認可HTTPが0、Ticket Tool/WIP/serviceで未付与・範囲外・失効時に下流作用0、許可時に実作用完了を同じ接続で確認する。
  • providerの拒否、delegation失効・policy縮小・Subject本体交代、attachmentの入替え競合を実Host接続で確認する。fake clientで認可callbackを数えた証拠だけでは代替できない。
  • 初期resident入力の拒否時の読取り0・モデル供給0、許可時の取得・commit、optional Workspace summaryの未開始診断と通信障害分類を区別する。load_initial_checked が初期化で呼ばれる差分はあるが、その読取りだけでライフサイクル全体の成功を主張しない。
  • 保存済みpromptのsourceが設定変更等で除去されたrestore、同じbodyのcache再供給、Journal compactionの凍結済み参照、Subject Jobの凍結入力にも現行権限が適用されるか確認する。source objectが残る場合のcallback成功だけでは除去後の経路を証明できない。
  • Journal/consolidation Jobの限定grantと現行policy、origin欠落の旧Job、一般Job、current attempt・writer・期限拒否の組合せを確認する。Job入力のpre-request hook追加は、全Job操作のgrant整合の証明ではない。
  • 継続処理について取消要求後の停止確認、途中失敗cleanup、停止後の追加配送・読取り・作用0を確認する。登録時の拒否テストで継続中の権限変更を代替しない。
  • MCPのallow/deny、拒否時discovery spawn0、stdioの発見・各呼出し・restore・cleanup/retryを既存の粗い認可のまま回帰確認する。本Ticketの変更から新しい各呼出し認可を推論しない。
  • 旧保存grantを読めること、新しい操作へ暗黙展開されないこと、明示standalone・非Subject互換・Workspace障害が区別されること、生成契約の整合は実接続/生成チェックが別途必要。

この調査でCargo build/testや生成処理は実行していない。文書のみの静的検査は実装の受入判定を代替しない。

同日・候補安定後の追補

上記は棚卸し時点の観測であり、以下はその後に実装担当が行った検証である。独立レビューの判断とは分ける。

  • worker-runtime/src/worker_backend.rs の旧Feature名fixtureを、Subjectの実操作とbound targetを検査するfixtureに更新した。task-onlyのFIFO・receipt replayはHost呼出し0、pending head修復はresident/Journal取得と保護入力checkpointを検査する。既存headの再修復では保護入力を再取得しない。
  • worker.rs の protected_input_tests はcached prompt、source除去後restore、fork・compaction・rewind、未知provenance拒否とhook後の再検査を扱う。Journalはstartup/compactionを区別し、空payloadは保護入力として偽装しない。追加の backend_job_input.rs とcontroller結合テストは、凍結Job入力を各モデル要求前に再検査し、拒否時にモデル要求・結果送信が発生しないことを確認した。
  • server/tests/subject_authorization_tests.rs の署名Host接続テストで、unset task、MCPのdiscovery前拒否、Ticket作成の下流作用、alias正規化、provider scopeとの積集合、attachment再接続、本体交代を確認した。subjektiv_jobs_tests.rs は限定Job grantと現行policy、origin/attemptの失効を検査する。これは任意のFeatureコードを自動監視できるという主張ではない。
  • 安定候補でroot cargo check、変更crateの通常suite(server-api、tools、worker、worker-runtime、yoi-workspace-server)、server-api --features typescript のsuite、変更crateのrustdoc生成、format・差分・状態契約名検査が成功した。restoreを含むsuiteにはcheckout内 target/restore-test-environment/ 以下の専用config/data/runtimeを使用した。最初のServer再実行は隔離環境変数不足でpreflight失敗し、設定後の全suite再実行が成功した。preflightを削除して通してはいない。
  • OpenAPIと影響する各OpenAPI closure出力は所有exampleの --check で一致した。Webの型検査と変更型を使う関連APIテストが成功した。描画変更はなく、browser/E2E・稼働環境更新は実施していない。通常suiteで元から明示選択のignoredテストを実行済みとは扱わない。

初回レビューで確認されたJob入力供給の不足

初回候補の通常suite成功は、凍結Job入力をcompactorへ再供給する経路と、Jobの通常hook後に権限が失効する経路を証明していなかった。正式レビューは実Controllerと捕捉モデルで漏れを再現し、request_changesとした。上記の成功記録をこの境界の成功へ拡張してはならない。

修正では、Job種別・Job ID・入力digestの保持義務を既存の保護入力provenanceに追加し、Host由来の実行bindingとの一致と現行認可を共通供給guardで検査する。保存値はgrantではない。attemptは現在のHost正本で毎回検査し、同じ凍結入力への正当な再試行と別Jobへの付替えを区別する。通常hookは早期診断に留まり、hook後とcompactorの各dispatchを代替しない。

恒久回帰は worker_job_input_supply_tests.rs(rewrite/restoreとcompactor継続)、tests/controller/subject_job_input_supply.rs(実Controllerと後続hook失効)、server/tests/subject_job_model_supply_tests.rs(署名Host・実policy/Job台帳・捕捉モデル)へ追加した。Journal/consolidation双方で許可時の実供給と拒否時のモデル要求0を観測する。origin切断の履歴fixtureは稼働Controllerの停止確認を主張せず、既存のconnected release検証とは分ける。修正前の恒久回帰失敗と修正後の成功、最終suiteの結果はMRで区別して記録する。

件数・生ログ・source識別はMRの検証記録に置く。これらの成功だけで受入条件の網羅、正式承認、統合、Ticketの完了を推論しない。