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.
28 KiB
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の完了を推論しない。