Repository navigation
feat(governance): let a policy name the feature content hosts - #23717
iamwhatever wants to merge 1 commit into
Conversation
UX Review (Opus 5.5) — ⏭️ skippedRevision |
Design Review (Opus 5.5) — ✅ PASSDesign-level review of Design-Verdict: PASS Nothing blocks: the change only narrows when a policy names Notes
[DESIGN-REVIEWED] 05bd4d7 Description read[DESCRIPTION-READ] 6af6593106574dd1d0d15f80c681150158b22e953d5ce20f8831c18129bd2ebd That sha256 names everything this verdict read: the PR description, plus the 1 evidence file(s) the workflow collected from it and handed this review. It covers that evidence because the media strip replaces every attachment URL with the same placeholder, so an edit swapping one attachment for another would leave the description's captured text identical while what this review judged changed. Recompute it with |
First Principles Review (Opus 5.5) — ✅ PASSPremise-level review of First-Principles-Verdict: PASS Nothing blocks. A non-draft RFC row covers the hosts list. Two riders the description doesn't mention add new surface, so they are notes. Notes
What this change shipsInventory (6 items) — 4 justifiedIntent: let a managed fleet limit feature-video downloads to named hosts, such as its own mirror (ADDITION).
[FIRST-PRINCIPLES-REVIEWED] 05bd4d7 Description read[DESCRIPTION-READ] ac23effc58b904cbfad1460c90ab83fa64aa3f9afa87900753794d171f78200e That sha256 names the PR description this verdict read. Recompute it with |
Opus 5.5 Review — 🔴 changes requested (blocking)Reviewed
BLOCKING — src/kiro_crew/platform/governance_parts/archetypes.py:427 [BLOCK-MERGE] 05bd4d7 Verdict parsed from the review's SHA-scoped output markers for commit False positive or not applicable? A repository writer can comment: |
GPT 6.1 Review — 🔴 changes requested (blocking)GPT 6.1 found at least one blocking issue that must be resolved before merging This comment is updated in place on each push. BLOCKING -- src/kiro_crew/platform/governance_parts/archetypes.py:424 -- Valid host globs abort gateway startup
[BLOCK-MERGE] 05bd4d7 Adjudication (Opus 5.5) — is blocking on each finding proportionate?F1: the condition is ordinary, not extreme. A deny-all host list ( The IPv6 case is also real. The check at The refusal raises False positive or not applicable? A repository writer can comment: |
19ccf92 to
89e6c22
Compare
|
Fixed in 89e6c22: GPT BLOCKING on |
89e6c22 to
656b9e1
Compare
|
Fixed in 656b9e1: GPT BLOCKING ( |
656b9e1 to
db41ad4
Compare
db41ad4 to
6a6d928
Compare
cruisercohen
left a comment
There was a problem hiding this comment.
Reviewed d83c076895 merged onto current main (56b568a2be). Comment only: this is governance scope, so it gets no approval from us.
Default unchanged. This adds an opt-in hosts list (host matcher) to the existing capabilities.feature_videos_download row. The row keeps capability_default=True, the evaluator and CONTRACT_VERSION are untouched, and with no policy, or a policy without a hosts ruleset, every host is permitted as before (test_host_denied_permits_without_a_policy, test_no_policy_or_no_list_permits_as_before). The list can only narrow:
host_deniedruns before each manifest request in the walk and before each poster and clip request. It permits only when every reading of the host is permitted, and it fails closed on a probe error, logging the exception type only (no URL).build_opener(redirect_allowed=...)holds every manifest redirect hop to the same list, on top of the existing https and same-host pins. The handler is constructed only when a guard is passed, so other callers get the same handler class as before.- A refused host fails that one entry and leaves the
download_deniedmemo alone, so it can't switch the whole feature off.
Checks run. On the merge worktree, the new suite plus the feature-video and asset-downloader suites: 542 pass. Three test_feature_videos_boot_path failures are a local missing markdown_it module and fail the same way without this PR. Mutations:
host_deniedalways permits: 9 red.- Probe error permits instead of denying: 1 red.
- Redirect guard dropped from the manifest opener:
test_a_mirror_redirect_to_an_unlisted_host_is_refusedred.
Non-blocking note. The url_policy_hosts / _canonical_ip / _PLAIN_HOST_RE hunk in governance_parts/matching.py is byte-identical to #23719's. _match_host itself is unchanged from main.
buluoray
left a comment
There was a problem hiding this comment.
Approving at d83c076895a4c8cc2eabe95a9f89f197a05975d6.
What this gives a fleet: a policy can now pin which hosts the feature-video catalog and clips may come from, including a mirror named by KIROCREW_FEATURE_VIDEOS_MANIFEST_URL. A request to any other host is never made.
Checked against source:
capabilities.feature_videos_downloadonly gains ahostsruleset (host matcher) as aSCOPE_CATALOGdata row. The evaluator andCONTRACT_VERSIONare unchanged.host_deniedpermits only when every reading fromurl_policy_hostsis permitted. It denies on error and logs the exception class only, so a credentialed mirror URL cannot reach the log.- It runs before each manifest request, before the poster and before the clip, and on every redirect step of the manifest fetch through
redirect_allowed. That callback only narrows the existing redirect handlers. - Poster and clip downloads keep the same-host redirect handler, so a redirect cannot move them to another host.
Tests: feature-video and asset-downloader tests pass (530), and the new hosts test file passes. Mutations, one at a time: removing the poster check, the manifest check or the redirect guard; changing all-readings to any-reading; allowing on error; and dropping the percent-decoded reading each turned a named test red.
Non-blocking follow-up: removing the clip host check alone leaves the suite green. The poster check on the same host absorbs it, so the clip check is only exercised when the policy changes between poster and clip. A test that installs a hosts list after the poster downloads would pin it.
d83c076 to
3e36d0f
Compare
3e36d0f to
37c5351
Compare
37c5351 to
12ec3f1
Compare
12ec3f1 to
05bd4d7
Compare
|
Fixed the GPT/Opus BLOCK on the previous head ( |
Problem / Motivation
Goal: A security policy can name the exact hosts feature-video content may be downloaded from, and no request goes to any other host.
capabilities.feature_videos_downloadis an on/off gate with no list (RFC crew-enterprise-edition, appendix rows "Feature content download"partialand "Feature content hosts"feature_videos_download.hosts,no). A fleet that mirrors the content cannot say "fetch from our mirror only".Why it matters
A managed fleet that permits feature content from its own mirror must be able to refuse the vendor CDN and every other host, including a host a mirror redirects to.
Not a goal
_query_level: with no policy, or a policy without the list, behaviour is unchanged.What changed (motivation → approach → change)
Goal → the existing CapabilityGate inner-ruleset shape → one catalog row change, one probe, three request sites.
governance_parts/catalog.py:capabilities.feature_videos_downloadgainsscope_matchers={"hosts": "host"}. Queried ashosts:<host>.governance_parts/matching.url_policy_hosts: every host a client could connect to for a url (the standard library plain and host-percent-decoded,urllib3,yarl; non-ASCII in IDNA form);host_deniedpermits only when every reading is permitted. The same helper is added identically in feat(governance): let a policy name the OTLP collector hosts #23716 and feat(governance): let a policy name decision models, points and endpoints #23719.feature_videos_manifest.host_denied(url): audited, fail-closed, on the pinneddashboard:uisurface likedownload_denied. It does not touch thedownload_deniedmemo, so one refused host does not report the feature off.asset_downloader.build_openergains an optionalredirect_allowedpredicate, asked about every redirect hop. The manifest fetch passeshost_denied, because an operator mirror may redirect across hosts. Callers that pass nothing are unchanged.governance.md(feature-video section) and the user docfeature-videos.md.Call sites wired:
feature_videos_manifest.fetch_manifest: before each manifest request in the walk.feature_videos_manifest._fetch_json: every redirect hop of that request.feature_videos_cache.FeatureVideoCache._download_entry_into: before the poster request and before the clip request (HOST_DENIEDfails that entry only; those transfers already refuse cross-host redirects).Backwards compatibility
Compatible: with no policy, or a policy that does not name
hosts, every host is permitted, andbuild_openercallers that pass noredirect_allowedget the same handler class as before.Removes nothing: the list only narrows when a policy names it.
Tests
test/test_governance_list_feature_video_hosts.py: the key parses with thehostmatcher; a list allowing X permits X and denies Y; gate off denies; no policy or no list permits. Call sites:host_deniedfollows the list and auditshosts:<host>; it permits with no policy; the manifest walk makes no request to an unlisted host; a mirror redirect to an unlisted host is refused hop by hop; a clip on an unlisted host is not downloaded.Proof: not provable -- other: new feature; the tests assert behaviour that main does not have
Manual verification
N/A — unit coverage drives the real evaluator and each request site with the network stubbed.
Related Issues
Refs #23206. RFC: #23208.
Checklist
feat|fix|docs|style|refactor|perf|test|chore|ci|build|revert: ...)Contribution License Agreement
Contributions are accepted under the project's Apache-2.0 license.