From 849bc12e5d3fb490715c516c179f1f638f85d6ad Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sat, 12 Sep 2026 22:45:45 +0000 Subject: [PATCH 01/25] Refuse the R2 durable-origin route: Automatic placement is a choice, not a location. Cloudflare's data-location docs (read 2026-09-12) make residency a Jurisdictional Restriction; default/Automatic and location hints are not. The nine-path closure therefore stays Unread rather than Located, and admit_provider_use refuses. Co-authored-by: Cursor --- dag/extdeps/cloudflare/r2_data_location.dag | 233 +++++++++++++++ dag/gunbc/extdeps_scope_frontier.dag | 1 + dag/gunbc/product/supplier/cloudflare_r2.dag | 157 ++++++++++ .../cloudflare_r2_route_witness_test.dag | 267 ++++++++++++++++++ 4 files changed, 658 insertions(+) create mode 100644 dag/extdeps/cloudflare/r2_data_location.dag create mode 100644 dag/gunbc/product/supplier/cloudflare_r2.dag create mode 100644 dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag diff --git a/dag/extdeps/cloudflare/r2_data_location.dag b/dag/extdeps/cloudflare/r2_data_location.dag new file mode 100644 index 00000000000..95729ea8608 --- /dev/null +++ b/dag/extdeps/cloudflare/r2_data_location.dag @@ -0,0 +1,233 @@ +module extdeps.cloudflare.r2_data_location + +import std.types { Bool, NonEmptyStr, List } +import std.decl_ref { DeclarationRef, WholeDeclaration } +import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef } +import extdeps.uri { Uri, Https } + + +data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "developers.cloudflare.com/r2/reference/data-location" + } +} + +data r2_how_r2_works_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "developers.cloudflare.com/r2/how-r2-works" + } +} + +data r2_us_jurisdiction_changelog_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "developers.cloudflare.com/changelog/post/2026-08-17-r2-us-jurisdiction" + } +} + +data r2_tokens_jurisdiction_default_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "developers.cloudflare.com/r2/api/tokens" + } +} + +data cloudflare_subprocessors_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "www.cloudflare.com/gdpr/subprocessors/cloudflare-services" + } +} + +data cloudflare_customer_dpa_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "cf-assets.www.cloudflare.com/slt3lc6tev37/1TTgT35GoUNlKZYGuKWBFy/4e7dfc8cf402419a9b1cf624291fc69f/cloudflare_customer_dpa-v6.4_april_3_2026.pdf" + } +} + +data extdeps_model_scope: ExternalModelScope = ExternalModelScope { + subject: ExternalSubjectRef { + declaration: DeclarationRef { + module_path: "extdeps.cloudflare.r2_data_location", + decl_name: "r2_placement_automatic", + field: WholeDeclaration + } + }, + first_citation: extdeps_external_authority_anchor, + further_citations: [ + r2_how_r2_works_authority, + r2_us_jurisdiction_changelog_authority, + r2_tokens_jurisdiction_default_authority, + cloudflare_subprocessors_authority, + cloudflare_customer_dpa_authority, + ] +} + +// EACH ROW CARRIES THE DOCUMENT, THE DATE IT WAS READ, AND THE SENTENCE IT WAS READ FOR. The +// statement field is a TRANSCRIPTION of upstream's own words, not commentary about them. A reading +// is dated and never silently refreshed: upstream edits a page without telling anyone, so a +// statement that no longer appears at its URI is a NEW reading with a later date. +type CloudflarePublishedReading { + authority: ExternalAuthority + read_on: NonEmptyStr + statement: NonEmptyStr +} + +data r2_data_location_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: extdeps_external_authority_anchor, + read_on: "2026-09-12", + statement: "When you create a new bucket, the data location is set to Automatic by default. Currently, this option chooses a bucket location in the closest available region to the create bucket request based on the location of the caller. Location Hints are optional parameters you can provide during bucket creation to indicate the primary geographical location you expect data will be accessed from. Location Hints are a best effort and not a guarantee, and they should only be used as a way to optimize performance. Available hints: wnam Western North America, enam Eastern North America, weur Western Europe, eeur Eastern Europe, apac Asia-Pacific, oc Oceania. Jurisdictional Restrictions guarantee objects in a bucket are stored within a specific jurisdiction. Use Jurisdictional Restrictions when you need to ensure data is stored and processed within a jurisdiction to meet data residency requirements. Available jurisdictions: eu European Union, fedramp FedRAMP, us United States. Once an R2 bucket is created, the jurisdiction cannot be changed. Page last updated Aug 19, 2026.", +} + +data r2_how_r2_works_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: r2_how_r2_works_authority, + read_on: "2026-09-12", + statement: "R2 Gateway: The entry point for all API requests that handles authentication and routing logic. This service is deployed across Cloudflare's global network via Cloudflare Workers. Metadata Service: A distributed layer built on Durable Objects used to store and manage object metadata. Distributed Storage Infrastructure: The underlying infrastructure that persistently stores encrypted object data. On write, the Gateway determines which storage cluster to write the encrypted data to within the location set for the bucket. The encrypted data is written and stored in the distributed storage infrastructure, and replicated within the region (e.g. ENAM) for durability. On read, if the object is not in the tiered read cache, it retrieves the object from one of the distributed storage data centers within the region that holds the object data. Page last updated Apr 21, 2026.", +} + +data r2_us_jurisdiction_changelog_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: r2_us_jurisdiction_changelog_authority, + read_on: "2026-09-12", + statement: "New us jurisdiction for R2. R2 now supports a us jurisdiction, which guarantees that bucket data is stored and processed within the United States. Use this jurisdiction when you need explicit US data residency guarantees. Use the jurisdiction-specific S3 endpoint https://.us.r2.cloudflarestorage.com. Once an R2 bucket is created, its jurisdiction cannot be changed. Posted 2026-08-17.", +} + +data r2_tokens_default_jurisdiction_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: r2_tokens_jurisdiction_default_authority, + read_on: "2026-09-12", + statement: "A specific bucket is represented as com.cloudflare.edge.r2.bucket.__. JURISDICTION: The jurisdiction where the R2 bucket lives. For buckets not created in a specific jurisdiction this value will be default.", +} + +data cloudflare_subprocessors_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: cloudflare_subprocessors_authority, + read_on: "2026-09-12", + statement: "Last Updated: October 1, 2025. Cloudflare uses a handful of sub-processors to support the Cloudflare service. Some of these sub-processors are members of the Cloudflare Group (Cloudflare, Inc. and its subsidiaries) and some are third parties. Third-party entities include Slack Technologies, Inc. (Customer support communications, United States); Zendesk, Inc. (Customer support and account management, United States, the European Economic Area, Japan, and Australia); Salesforce, Inc. (Customer support and account management, United States); Google LLC (Cloudflare Developer Platform, Cloudflare Zero Trust and AI Gateway; European Economic Area, United States, Australia, India); Oracle America, Inc. (Cloudflare Developer Platform and Cache Reserve; United States, European Economic Area, UK, Japan, Australia, Canada, Singapore); Amazon Web Services (Cloudflare Email Security; United States, European Economic Area); CoreWeave, Inc., Nebius BV (Workers AI); Anthropic PBC, OpenAI, Inc., X.AI Corp., Groq, Inc. (AI Gateway). The page lists Cloudflare Group subsidiaries by location and does not key any row to a named R2 bucket or to the default jurisdiction.", +} + +data cloudflare_customer_dpa_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: cloudflare_customer_dpa_authority, + read_on: "2026-09-12", + statement: "Cloudflare, Inc. Data Processing Addendum, Version 6.4 April 3, 2026. The Customer grants a general written authorization: (a) to Cloudflare to appoint other members of the Cloudflare Group as sub-Processors, and (b) to Cloudflare and other members of the Cloudflare Group to appoint third party data center operators, and business, engineering and customer support providers as sub-Processors to support the performance of the Service. Cloudflare will maintain a list of sub-Processors at https://www.cloudflare.com/gdpr/subprocessors/. This DPA and any action related thereto shall be governed by and construed in accordance with the laws as specified in the Main Agreement, and the parties consent to the personal jurisdiction of, and venue in, the courts specified in the Main Agreement.", +} + +// THE LEGAL ENTITY THE DOCUMENTS NAME. A route's operator slot needs a party. The legal name is +// the same spelling already declared as extdeps.vendor.cloudflare cloudflare; the address is +// transcribed from the data-location page's publisher Organization on the same read date. +type CloudflareLegalEntity { + legal_name: NonEmptyStr + registered_address: NonEmptyStr + country: NonEmptyStr + reading: CloudflarePublishedReading +} + +data cloudflare_inc: CloudflareLegalEntity = CloudflareLegalEntity { + legal_name: "Cloudflare, Inc.", + registered_address: "101 Townsend St, San Francisco, CA 94107, US", + country: "United States", + reading: r2_data_location_reading, +} + +// LOCATION HINTS ARE A ROSTER OF CHOICES, NOT A ROSTER OF PLACES THE BYTES ARE. Upstream names them +// hints, says they are a best effort and not a guarantee, and uses them to optimize performance. +// A consumer that treated one as a residency location would be reading a different document than +// the one cited here. +type R2LocationHintRow { + hint: NonEmptyStr + description: NonEmptyStr + reading: CloudflarePublishedReading +} + +data r2_hint_wnam: R2LocationHintRow = R2LocationHintRow { + hint: "wnam", + description: "Western North America", + reading: r2_data_location_reading, +} + +data r2_hint_enam: R2LocationHintRow = R2LocationHintRow { + hint: "enam", + description: "Eastern North America", + reading: r2_data_location_reading, +} + +data r2_hint_weur: R2LocationHintRow = R2LocationHintRow { + hint: "weur", + description: "Western Europe", + reading: r2_data_location_reading, +} + +data r2_hint_eeur: R2LocationHintRow = R2LocationHintRow { + hint: "eeur", + description: "Eastern Europe", + reading: r2_data_location_reading, +} + +data r2_hint_apac: R2LocationHintRow = R2LocationHintRow { + hint: "apac", + description: "Asia-Pacific", + reading: r2_data_location_reading, +} + +data r2_hint_oc: R2LocationHintRow = R2LocationHintRow { + hint: "oc", + description: "Oceania", + reading: r2_data_location_reading, +} + +fn r2_location_hints() -> List { + [r2_hint_wnam, r2_hint_enam, r2_hint_weur, r2_hint_eeur, r2_hint_apac, r2_hint_oc] +} + +// JURISDICTIONAL RESTRICTIONS ARE THE ONLY ARM UPSTREAM CALLS A GUARANTEE. They are listed so a +// reader can see what was available and not taken; they are not this repository's durable origin. +type R2JurisdictionRestrictionRow { + jurisdiction: NonEmptyStr + description: NonEmptyStr + reading: CloudflarePublishedReading +} + +data r2_jurisdiction_eu: R2JurisdictionRestrictionRow = R2JurisdictionRestrictionRow { + jurisdiction: "eu", + description: "European Union", + reading: r2_data_location_reading, +} + +data r2_jurisdiction_fedramp: R2JurisdictionRestrictionRow = R2JurisdictionRestrictionRow { + jurisdiction: "fedramp", + description: "FedRAMP", + reading: r2_data_location_reading, +} + +data r2_jurisdiction_us: R2JurisdictionRestrictionRow = R2JurisdictionRestrictionRow { + jurisdiction: "us", + description: "United States", + reading: r2_us_jurisdiction_changelog_reading, +} + +fn r2_jurisdiction_restrictions() -> List { + [r2_jurisdiction_eu, r2_jurisdiction_fedramp, r2_jurisdiction_us] +} + +// AUTOMATIC IS A CHOICE MECHANISM, AND THAT IS WHAT THIS ROW RECORDS. It is the region a route +// cites when a bucket was created without a jurisdictional restriction: not a country, not a +// data-center park, and not a residency commitment. Treating R2JurisdictionDefault, a dashboard +// Location label, or a Location Hint as the place the bytes live is the reading this row exists +// to make unusable as a location fact. +type R2PlacementModeRow { + mode: NonEmptyStr + is_residency_guarantee: Bool + reading: CloudflarePublishedReading +} + +data r2_placement_automatic: R2PlacementModeRow = R2PlacementModeRow { + mode: "Automatic", + is_residency_guarantee: false, + reading: r2_data_location_reading, +} + +data r2_jurisdiction_wire_default: R2PlacementModeRow = R2PlacementModeRow { + mode: "default", + is_residency_guarantee: false, + reading: r2_tokens_default_jurisdiction_reading, +} diff --git a/dag/gunbc/extdeps_scope_frontier.dag b/dag/gunbc/extdeps_scope_frontier.dag index a5256db3b1f..ec7d5b6e659 100644 --- a/dag/gunbc/extdeps_scope_frontier.dag +++ b/dag/gunbc/extdeps_scope_frontier.dag @@ -496,6 +496,7 @@ data scope_carrier_paths: List = [ "dag/extdeps/cloudflare/client_v4.dag", "dag/extdeps/cloudflare/account_api_tokens.dag", "dag/extdeps/cloudflare/r2.dag", + "dag/extdeps/cloudflare/r2_data_location.dag", "dag/extdeps/deepseek/deepseek_v4_1_flash.dag", "dag/extdeps/docker/images/gitcommit90_glm_53_one_spark.dag", "dag/extdeps/docker/images/timothystewart6_vllm_gb10.dag", diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag new file mode 100644 index 00000000000..8fc2877fb6c --- /dev/null +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -0,0 +1,157 @@ +module product.supplier.cloudflare_r2 + +import std.types { List, NonEmptyStr } +import std.decl_ref { DeclarationRef, decl_ref } +import std.content_hash { as_content_hash_structural, content_hash_atom } +import product.fabric.identity { FabricIdentity, OfferKey } +import product.fabric.provider_route { + ProviderRoute, CompliancePostureRevision, ProviderRouteFacts, + ProviderDataPathClosure, ProviderPathUnread, + DownstreamProviderPopulation, DownstreamProvidersUnread, +} +import product.fabric.provider_admission { + RouteScopeSanction, ProviderUseScope, ProviderUseAdmission, admit_provider_use, +} + +// THE DURABLE-ORIGIN ROUTE THIS REPOSITORY ANSWERS THE NINE-PATH CLOSURE FOR, AND THE ROW REFUSES. +// +// WHAT WAS READ. Cloudflare's R2 data-location page, how-R2-works page, us-jurisdiction changelog, +// tokens page, subprocessors list and Customer DPA v6.4 were read on 2026-09-12 and transcribed +// in extdeps.cloudflare.r2_data_location. The durable origin in this fleet +// (gunbc.cloudflare.r2_origin fabric_durable_origin_standing, bucket gunbai-fabric-origin) carries +// R2JurisdictionDefault. That module already states that Default is not a data-residency +// commitment this fleet has made. The upstream reading confirms the same fact in Cloudflare's +// words: Automatic placement chooses a region from the caller's location at create time; Location +// Hints are a best effort and not a guarantee; only Jurisdictional Restrictions (eu, us, fedramp) +// guarantee objects are stored and processed within a jurisdiction. Default, on the tokens page, +// is the wire value for buckets not created in a specific jurisdiction. +// +// WHAT WAS NOT FOUND, AND THEREFORE WHAT THIS MODULE MUST NOT MINT. No document read names the +// country, the region, or the storage cluster that holds objects in THIS bucket. A dashboard +// label, a default jurisdiction setting, and a hint are choices. Reaching for ProviderPathLocated +// to make a compliance posture able to include R2 would manufacture the fact the posture is +// supposed to rest on. ProviderPathAbsent is also not taken: nobody has stated that any of these +// nine paths do not exist. +// +// BOTH THE REFUSING PRODUCTION ROW AND THE DISCRIMINATING PAIR ARE THE DELIVERABLE. + +fn cloudflare_r2_provider_ref() -> DeclarationRef { + decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_inc") +} + +fn cloudflare_r2_service_ref() -> DeclarationRef { + decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "extdeps_external_authority_anchor") +} + +fn cloudflare_r2_region_ref() -> DeclarationRef { + decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "r2_placement_automatic") +} + +fn cloudflare_r2_durable_origin_route() -> ProviderRoute { + ProviderRoute { + provider: cloudflare_r2_provider_ref(), + service: cloudflare_r2_service_ref(), + region: cloudflare_r2_region_ref(), + } +} + +data cloudflare_r2_execution_location_obligation: NonEmptyStr = "Where R2 executes object operations for a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2_data_location r2_how_r2_works_reading states that the R2 Gateway is deployed across Cloudflare's global network via Cloudflare Workers, close to the user, and that the Gateway then writes to a storage cluster within the location set for the bucket. That is an architecture of a CHOICE, not a location of this fleet's bucket. RESOLVED BY a Cloudflare statement naming the jurisdiction or operating entity of request handling for a named default-jurisdiction bucket -- at which point this path takes Located with that entity as operator. It is NOT resolved by R2JurisdictionDefault, by Automatic placement, or by a Location Hint." + +data cloudflare_r2_durable_storage_location_obligation: NonEmptyStr = "Where objects in this fleet's durable origin are stored is UNREAD, and that is a read of Cloudflare's own location rules rather than a missing document. gunbc.cloudflare.r2_origin fabric_durable_origin_standing places bucket gunbai-fabric-origin under R2JurisdictionDefault. extdeps.cloudflare.r2_data_location r2_data_location_reading (URI developers.cloudflare.com/r2/reference/data-location, read 2026-09-12) states that a new bucket's data location is Automatic by default, which chooses a bucket location in the closest available region to the create bucket request based on the location of the caller; that Location Hints are a best effort and not a guarantee; and that Jurisdictional Restrictions (eu, us, fedramp) are what guarantee objects are stored and processed within a jurisdiction. r2_tokens_default_jurisdiction_reading states that for buckets not created in a specific jurisdiction the wire value is default. THIS PATH IS THEREFORE A CHOICE, NOT A LOCATION. RESOLVED BY recreating the origin under a Jurisdictional Restriction that names a jurisdiction, or by a Cloudflare statement that objects in gunbai-fabric-origin are stored and processed within a named jurisdiction the way Jurisdictional Restrictions do. It is NOT resolved by reading the API location field (wnam/enam/weur/eeur/apac/oc), which upstream lists as a hint, nor by treating R2JurisdictionDefault as residency." + +data cloudflare_r2_backups_location_obligation: NonEmptyStr = "Where R2 replicates objects for durability on a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2_data_location r2_how_r2_works_reading states that encrypted data is replicated within the region (e.g. ENAM) for durability, and it names no region for a default-jurisdiction bucket and no country for that replication. RESOLVED BY a Cloudflare statement of the region or jurisdiction inside which objects of a named default-jurisdiction bucket are replicated. It is NOT resolved by the example token ENAM in that sentence." + +data cloudflare_r2_logs_location_obligation: NonEmptyStr = "Where R2 or the Cloudflare platform stores logs of access to a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2_data_location r2_data_location_reading states that Logpush does not interact with R2 resources with assigned jurisdictions, which is a fact about jurisdictional buckets and does not say where logs of a default-jurisdiction bucket go, nor that no such logs exist. THE ABSENT ARM IS DELIBERATELY NOT TAKEN. RESOLVED BY a Cloudflare statement about logging of R2 object access, in either direction: an explicit none makes this path Absent with that document as evidence, and a described store makes it Located at whoever receives it." + +data cloudflare_r2_telemetry_location_obligation: NonEmptyStr = "Whether Cloudflare collects telemetry about a default-jurisdiction R2 bucket, what it carries, and where it goes, is UNREAD. Nothing in the documents read on 2026-09-12 describes a telemetry or usage-reporting path for R2 object storage as a located destination. THE ABSENT ARM IS DELIBERATELY NOT TAKEN: silence is not a denial. RESOLVED BY a Cloudflare statement about R2 telemetry, in either direction." + +data cloudflare_r2_control_plane_location_obligation: NonEmptyStr = "Where the R2 control plane -- the Dashboard, the S3 API, the REST API that powers Wrangler, and the Metadata Service -- runs for a default-jurisdiction bucket, and under whose jurisdiction, is UNREAD. r2_how_r2_works_reading places the Gateway on the global network and the Metadata Service on Durable Objects and names no country for either. RESOLVED BY a Cloudflare document naming the location or the operating entity of those control-plane components for a given bucket jurisdiction." + +data cloudflare_r2_support_access_obligation: NonEmptyStr = "From which jurisdiction Cloudflare support reaches a default-jurisdiction R2 bucket is UNREAD. extdeps.cloudflare.r2_data_location cloudflare_subprocessors_reading names Slack, Zendesk and Salesforce for customer support, with locations that include the United States and, for Zendesk, also the EEA, Japan and Australia. That is a company-wide support-tool list, not a statement that support access to THIS bucket's objects is exercised from those places or that it is not. RESOLVED BY a Cloudflare statement of where support access to a given R2 bucket's objects is exercised from." + +data cloudflare_r2_administrative_access_obligation: NonEmptyStr = "From which jurisdiction administrative access to a default-jurisdiction R2 bucket is exercised is UNREAD. The subprocessors page states that Cloudflare Group companies may be sub-processors because employees of those affiliates may need to provide account and engineering support, and it lists subsidiaries in the United Kingdom, Singapore, Australia, Germany, Portugal, France, Japan, Canada, the Netherlands, the U.A.E., India, the United States, South Korea, Mexico, Malaysia, Sweden and Switzerland. That names WHO may provide support, not FROM WHERE administrative access to this bucket is exercised, and it does not locate this bucket. RESOLVED BY a Cloudflare statement of where administrative access to a named default-jurisdiction R2 bucket is exercised from." + +data cloudflare_r2_spill_location_obligation: NonEmptyStr = "Where customer material may SPILL on an R2 default-jurisdiction route -- caches, diagnostic captures, undeleted replicas, Local Uploads, tiered read cache -- is UNREAD. r2_how_r2_works_reading describes a Tiered Read Cache and Local Uploads and names no country for either, and it does not say that no other spill surface exists. THE ABSENT ARM IS DELIBERATELY NOT TAKEN. RESOLVED BY a Cloudflare statement about host-side or cache-side copies of R2 object bytes for default-jurisdiction buckets, which may resolve this path in either direction." + +data cloudflare_r2_downstream_obligation: NonEmptyStr = "Which parties process objects stored in a default-jurisdiction R2 bucket on Cloudflare's behalf is UNREAD. The Customer DPA v6.4 (read 2026-09-12) authorizes Cloudflare Group members and third-party data center operators as sub-Processors, and the subprocessors list (last updated October 1, 2025, read 2026-09-12) enumerates tools and platforms by activity, including Google LLC and Oracle America, Inc. for the Cloudflare Developer Platform. THAT LIST IS NOT KEYED TO A NAMED R2 BUCKET OR TO THE DEFAULT JURISDICTION, so enumerating it as this route's downstream population would claim coverage the table does not give, and reporting none would claim the negative the table also does not give. RESOLVED BY a Cloudflare statement that names which subprocessors process objects in a named default-jurisdiction R2 bucket -- at which point this population takes Enumerated with that document as coverage -- or an explicit none for that bucket, which takes NoDownstreamProviders with that document as evidence." + +fn cloudflare_r2_data_paths() -> ProviderDataPathClosure { + ProviderDataPathClosure { + execution: ProviderPathUnread { + obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_execution_location_obligation"), + }, + durable_storage: ProviderPathUnread { + obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_durable_storage_location_obligation"), + }, + backups: ProviderPathUnread { + obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_backups_location_obligation"), + }, + logs: ProviderPathUnread { + obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_logs_location_obligation"), + }, + telemetry: ProviderPathUnread { + obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_telemetry_location_obligation"), + }, + control_plane: ProviderPathUnread { + obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_control_plane_location_obligation"), + }, + support_access: ProviderPathUnread { + obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_support_access_obligation"), + }, + administrative_access: ProviderPathUnread { + obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_administrative_access_obligation"), + }, + spill: ProviderPathUnread { + obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_spill_location_obligation"), + }, + } +} + +fn cloudflare_r2_downstream() -> DownstreamProviderPopulation { + DownstreamProvidersUnread { + obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_downstream_obligation"), + } +} + +fn cloudflare_r2_durable_origin_route_facts() -> ProviderRouteFacts { + ProviderRouteFacts { + route: cloudflare_r2_durable_origin_route(), + contract_terms: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_customer_dpa_reading"), + data_paths: cloudflare_r2_data_paths(), + downstream: cloudflare_r2_downstream(), + observed_at: "2026-09-12T00:00:00Z", + facts_revision: as_content_hash_structural(structural: content_hash_atom(value: "product.supplier.cloudflare_r2.durable-origin-route-facts.2026-09-12" as NonEmptyStr)), + } +} + +fn cloudflare_r2_route_facts_population() -> List { + [cloudflare_r2_durable_origin_route_facts()] +} + +// THIS MODULE DECLARES NO SANCTION ROSTER AND NO POSTURE REVISION. Nobody has stated that we are +// willing to place work on this vendor's default-jurisdiction R2 under a named posture. Writing a +// roster row here to make the module look complete would be the fabricated authority the gate exists +// to close. The producer takes roster and posture from its caller and supplies only the route facts. +// +// DECLARED FRONTIER (DESIGN section 3c). The production consumer is a posture producer that mints a +// CompliancePostureRevision whose permitted_jurisdictions enumerate only routes whose facts have +// been read and cleared. TRIGGER: that producer, SUFFICIENT FOR this route to be included or +// omitted by matching these facts rather than by a dashboard label. Until then the executing +// consumer is the witness. +fn cloudflare_r2_route_admission

( + facts: ProviderRouteFacts, + roster: List, + active: CompliancePostureRevision, + scope: ProviderUseScope

, + offer: FabricIdentity, + decision_receipt: DeclarationRef, +) -> ProviderUseAdmission

{ + admit_provider_use( + roster: roster, + facts: facts, + active: active, + scope: scope, + offer: offer, + decision_receipt: decision_receipt, + ) +} diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag new file mode 100644 index 00000000000..ac489a8e61b --- /dev/null +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -0,0 +1,267 @@ +module test.claim.supplier.cloudflare_r2_route_witness + +import std.types { Bool, List, NonEmptyStr, String } +import std.decl_ref { DeclarationRef, decl_ref, declaration_ref_eq } +import std.content_hash { as_content_hash_structural, content_hash_atom } +import product.fabric.identity { FabricIdentity, DemandKey, WorkKey, OfferKey } +import product.fabric.provider_route { + ProviderRoute, CompliancePostureRevision, ProviderRouteFacts, + ProviderDataPathClosure, ProviderPathStanding, ProviderPathLocated, ProviderPathAbsent, + ProviderPathUnread, DownstreamProviderPopulation, NoDownstreamProviders, +} +import product.fabric.provider_admission { + RouteScopeSanction, ProviderUseScope, ProviderUseAdmission, + ProviderUseAdmitted, ProviderUseDenied, ProviderUseRefusal, + ProviderRouteUnclassified, ProviderRouteFactsIncomplete, DownstreamProviderUnassessed, + PostureRevisionStale, CustomerScopeUnsupported, DataHandlingUnsupported, + RequiredAgreementAuthorityAbsent, ProhibitedUseNotCleared, SanctionsNotCleared, ExportNotCleared, + DispositionStanding, DispositionCleared, +} +import product.supplier.cloudflare_r2 { + cloudflare_r2_durable_origin_route, + cloudflare_r2_durable_origin_route_facts, + cloudflare_r2_route_admission, + cloudflare_r2_route_facts_population, + cloudflare_r2_data_paths, +} +import extdeps.cloudflare.r2_data_location { + r2_placement_automatic, + r2_jurisdiction_wire_default, + r2_location_hints, + r2_jurisdiction_restrictions, +} + +data r2_witness_customer_profile: NonEmptyStr = "r2-witness-customer-profile" +data r2_witness_data_handling_profile: NonEmptyStr = "r2-witness-data-handling-profile" +data r2_witness_agreement: NonEmptyStr = "r2-witness-agreement" +data r2_witness_posture_authority: NonEmptyStr = "r2-witness-posture-authority" +data r2_witness_decision_receipt: NonEmptyStr = "r2-witness-decision-receipt" +data r2_witness_prohibited_use_cleared: NonEmptyStr = "r2-witness-prohibited-use-cleared" +data r2_witness_sanctions_cleared: NonEmptyStr = "r2-witness-sanctions-cleared" +data r2_witness_export_cleared: NonEmptyStr = "r2-witness-export-cleared" +data r2_witness_resolved_operator: NonEmptyStr = "r2-witness-resolved-operator" +data r2_witness_resolved_jurisdiction: NonEmptyStr = "r2-witness-resolved-jurisdiction" +data r2_witness_resolved_evidence: NonEmptyStr = "r2-witness-resolved-evidence" +data r2_witness_no_downstream: NonEmptyStr = "r2-witness-no-downstream" + +fn t_resolved() -> ProviderPathStanding { + ProviderPathLocated { + operator: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_resolved_operator"), + jurisdiction: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_resolved_jurisdiction"), + evidence: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_resolved_evidence"), + } +} + +fn t_posture() -> CompliancePostureRevision { + CompliancePostureRevision { + authority: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_posture_authority"), + revision: as_content_hash_structural(structural: content_hash_atom(value: "r2-witness-posture-r1" as NonEmptyStr)), + } +} + +fn t_customer_profile() -> DeclarationRef { + decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_customer_profile") +} + +fn t_data_handling_profile() -> DeclarationRef { + decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_data_handling_profile") +} + +fn t_agreement() -> DeclarationRef { + decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_agreement") +} + +fn t_sanction(route: ProviderRoute) -> RouteScopeSanction { + RouteScopeSanction { + route: route, + posture: t_posture(), + customer_profile: t_customer_profile(), + data_handling_profile: t_data_handling_profile(), + requires_agreement: t_agreement(), + } +} + +fn t_roster() -> List { + [t_sanction(route: cloudflare_r2_durable_origin_route())] +} + +fn t_scope() -> ProviderUseScope { + ProviderUseScope { + demand: FabricIdentity { principal: "gunbc" as NonEmptyStr, key: "r2-witness-demand-1" as DemandKey }, + work: FabricIdentity { principal: "gunbc" as NonEmptyStr, key: "r2-witness-work-1" as WorkKey }, + customer_profile: t_customer_profile(), + data_handling_profile: t_data_handling_profile(), + agreement: t_agreement(), + prohibited_use_disposition: DispositionCleared { + evidence: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_prohibited_use_cleared"), + }, + sanctions_disposition: DispositionCleared { + evidence: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_sanctions_cleared"), + }, + export_disposition: DispositionCleared { + evidence: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_export_cleared"), + }, + } +} + +fn t_offer() -> FabricIdentity { + FabricIdentity { principal: "gunbc" as NonEmptyStr, key: "r2-witness-offer-1" as OfferKey } +} + +fn t_decide(facts: ProviderRouteFacts) -> ProviderUseAdmission { + cloudflare_r2_route_admission( + facts: facts, + roster: t_roster(), + active: t_posture(), + scope: t_scope(), + offer: t_offer(), + decision_receipt: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_decision_receipt"), + ) +} + +fn t_refusal_tag(c: ProviderUseRefusal) -> String { + match c { + ProviderRouteUnclassified { route } => "route-unclassified", + ProviderRouteFactsIncomplete { route, obligation } => "facts-incomplete", + DownstreamProviderUnassessed { obligation } => "downstream-unassessed", + PostureRevisionStale { evaluated, active } => "posture-stale", + CustomerScopeUnsupported { cause } => "customer-unsupported", + DataHandlingUnsupported { cause } => "data-handling-unsupported", + RequiredAgreementAuthorityAbsent { accepted } => "agreement-absent", + ProhibitedUseNotCleared { obligation } => "prohibited-use-not-cleared", + SanctionsNotCleared { obligation } => "sanctions-not-cleared", + ExportNotCleared { obligation } => "export-not-cleared", + } +} + +fn t_refusal_located(c: ProviderUseRefusal) -> List { + match c { + ProviderRouteUnclassified { route } => [], + ProviderRouteFactsIncomplete { route, obligation } => [obligation], + DownstreamProviderUnassessed { obligation } => [obligation], + PostureRevisionStale { evaluated, active } => [], + CustomerScopeUnsupported { cause } => [cause], + DataHandlingUnsupported { cause } => [cause], + RequiredAgreementAuthorityAbsent { accepted } => accepted, + ProhibitedUseNotCleared { obligation } => [obligation], + SanctionsNotCleared { obligation } => [obligation], + ExportNotCleared { obligation } => [obligation], + } +} + +fn t_denied_with(a: ProviderUseAdmission, tag: String, located: DeclarationRef) -> Bool { + match a { + ProviderUseAdmitted { permit } => false, + ProviderUseDenied { decision, cause } => + t_refusal_tag(c: cause) == tag + && count(filter(t_refusal_located(c: cause), r => declaration_ref_eq(a: r, b: located))) == 1, + } +} + +test fn the_durable_origin_refuses_as_downstream_unassessed() -> Bool { + t_denied_with( + a: t_decide(facts: cloudflare_r2_durable_origin_route_facts()), + tag: "downstream-unassessed", + located: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_downstream_obligation"), + ) +} + +test fn the_durable_storage_path_is_unread_with_the_location_obligation() -> Bool { + match cloudflare_r2_data_paths().durable_storage { + ProviderPathLocated { operator, jurisdiction, evidence } => false, + ProviderPathAbsent { evidence } => false, + ProviderPathUnread { obligation } => declaration_ref_eq( + a: obligation, + b: decl_ref( + module_path: "product.supplier.cloudflare_r2", + decl_name: "cloudflare_r2_durable_storage_location_obligation", + ), + ), + } +} + +test fn no_production_path_is_absent() -> Bool { + let c = cloudflare_r2_data_paths() + let paths = [ + c.execution, c.durable_storage, c.backups, c.logs, c.telemetry, + c.control_plane, c.support_access, c.administrative_access, c.spill, + ] + count(filter(paths, p => match p { + ProviderPathAbsent { evidence } => true, + ProviderPathLocated { operator, jurisdiction, evidence } => false, + ProviderPathUnread { obligation } => false, + })) == 0 +} + +fn t_paths_with_durable_storage(storage: ProviderPathStanding) -> ProviderDataPathClosure { + ProviderDataPathClosure { + execution: t_resolved(), + durable_storage: storage, + backups: t_resolved(), + logs: t_resolved(), + telemetry: t_resolved(), + control_plane: t_resolved(), + support_access: t_resolved(), + administrative_access: t_resolved(), + spill: t_resolved(), + } +} + +fn t_synthetic_downstream() -> DownstreamProviderPopulation { + NoDownstreamProviders { + evidence: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_no_downstream"), + } +} + +fn t_facts_with_durable_storage(storage: ProviderPathStanding) -> ProviderRouteFacts { + ProviderRouteFacts { + route: cloudflare_r2_durable_origin_route(), + contract_terms: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_customer_dpa_reading"), + data_paths: t_paths_with_durable_storage(storage: storage), + downstream: t_synthetic_downstream(), + observed_at: "2026-09-12T00:00:00Z", + facts_revision: as_content_hash_structural(structural: content_hash_atom(value: "r2-witness-discriminator" as NonEmptyStr)), + } +} + +test fn one_unread_durable_storage_path_refuses_with_that_paths_obligation() -> Bool { + t_denied_with( + a: t_decide(facts: t_facts_with_durable_storage(storage: ProviderPathUnread { + obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_durable_storage_location_obligation"), + })), + tag: "facts-incomplete", + located: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_durable_storage_location_obligation"), + ) +} + +test fn the_same_route_admits_once_that_path_is_resolved() -> Bool { + match t_decide(facts: t_facts_with_durable_storage(storage: t_resolved())) { + ProviderUseDenied { decision, cause } => false, + ProviderUseAdmitted { permit } => + declaration_ref_eq( + a: permit.route.region, + b: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "r2_placement_automatic"), + ) + && declaration_ref_eq( + a: permit.evidence.customer_profile, + b: t_customer_profile(), + ), + } +} + +test fn every_r2_route_in_the_population_refuses() -> Bool { + count(cloudflare_r2_route_facts_population()) == 1 + && count(filter(cloudflare_r2_route_facts_population(), f => match t_decide(facts: f) { + ProviderUseAdmitted { permit } => true, + ProviderUseDenied { decision, cause } => false, + })) == 0 +} + +test fn automatic_placement_is_not_a_residency_guarantee() -> Bool { + !r2_placement_automatic.is_residency_guarantee + && !r2_jurisdiction_wire_default.is_residency_guarantee +} + +test fn the_hint_roster_has_six_choices_and_three_jurisdiction_guarantees() -> Bool { + count(r2_location_hints()) == 6 && count(r2_jurisdiction_restrictions()) == 3 +} From 602b2c032a579ad16c166feb172f5bd5e2f500ed Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sat, 12 Sep 2026 23:09:07 +0000 Subject: [PATCH 02/25] Cite R2Jurisdiction as the tag set; drop the same-tree roster count. The location module was re-spelling eu/us/fedramp/default as strings beside the coproduct extdeps.cloudflare.r2 already owns. Restriction rows now carry that type, hints are their own closed coproduct, and the witness joins those arms instead of counting lists we declared. Co-authored-by: Cursor --- dag/extdeps/cloudflare/r2_data_location.dag | 107 ++++++++++++------ .../cloudflare_r2_route_witness_test.dag | 81 +++++++++++-- 2 files changed, 144 insertions(+), 44 deletions(-) diff --git a/dag/extdeps/cloudflare/r2_data_location.dag b/dag/extdeps/cloudflare/r2_data_location.dag index 95729ea8608..cfd244b9b96 100644 --- a/dag/extdeps/cloudflare/r2_data_location.dag +++ b/dag/extdeps/cloudflare/r2_data_location.dag @@ -1,9 +1,16 @@ module extdeps.cloudflare.r2_data_location -import std.types { Bool, NonEmptyStr, List } +import std.types { Bool, NonEmptyStr, String } import std.decl_ref { DeclarationRef, WholeDeclaration } import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef } import extdeps.uri { Uri, Https } +import extdeps.cloudflare.r2 { + R2Jurisdiction, + R2JurisdictionDefault, + R2JurisdictionEu, + R2JurisdictionFedramp, + R2JurisdictionUs, +} data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { @@ -129,105 +136,131 @@ data cloudflare_inc: CloudflareLegalEntity = CloudflareLegalEntity { reading: r2_data_location_reading, } -// LOCATION HINTS ARE A ROSTER OF CHOICES, NOT A ROSTER OF PLACES THE BYTES ARE. Upstream names them -// hints, says they are a best effort and not a guarantee, and uses them to optimize performance. -// A consumer that treated one as a residency location would be reading a different document than -// the one cited here. +// LOCATION HINTS ARE A CLOSED COPRODUCT OF CHOICES, NOT A ROSTER OF PLACES THE BYTES ARE. +// Upstream names them hints, says they are a best effort and not a guarantee, and uses them to +// optimize performance. The tag set lives here because extdeps.cloudflare.r2 does not declare it; +// the wire spelling is produced from the coproduct rather than stored as a second stringly name. +type R2LocationHint + = R2HintWnam + | R2HintEnam + | R2HintWeur + | R2HintEeur + | R2HintApac + | R2HintOc + +fn r2_location_hint_wire(hint: R2LocationHint) -> String { + match hint { + R2HintWnam => "wnam" + R2HintEnam => "enam" + R2HintWeur => "weur" + R2HintEeur => "eeur" + R2HintApac => "apac" + R2HintOc => "oc" + } +} + +fn r2_location_hint_is_residency_guarantee(hint: R2LocationHint) -> Bool { + match hint { + R2HintWnam => false + R2HintEnam => false + R2HintWeur => false + R2HintEeur => false + R2HintApac => false + R2HintOc => false + } +} + type R2LocationHintRow { - hint: NonEmptyStr + hint: R2LocationHint description: NonEmptyStr reading: CloudflarePublishedReading } data r2_hint_wnam: R2LocationHintRow = R2LocationHintRow { - hint: "wnam", + hint: R2HintWnam, description: "Western North America", reading: r2_data_location_reading, } data r2_hint_enam: R2LocationHintRow = R2LocationHintRow { - hint: "enam", + hint: R2HintEnam, description: "Eastern North America", reading: r2_data_location_reading, } data r2_hint_weur: R2LocationHintRow = R2LocationHintRow { - hint: "weur", + hint: R2HintWeur, description: "Western Europe", reading: r2_data_location_reading, } data r2_hint_eeur: R2LocationHintRow = R2LocationHintRow { - hint: "eeur", + hint: R2HintEeur, description: "Eastern Europe", reading: r2_data_location_reading, } data r2_hint_apac: R2LocationHintRow = R2LocationHintRow { - hint: "apac", + hint: R2HintApac, description: "Asia-Pacific", reading: r2_data_location_reading, } data r2_hint_oc: R2LocationHintRow = R2LocationHintRow { - hint: "oc", + hint: R2HintOc, description: "Oceania", reading: r2_data_location_reading, } -fn r2_location_hints() -> List { - [r2_hint_wnam, r2_hint_enam, r2_hint_weur, r2_hint_eeur, r2_hint_apac, r2_hint_oc] +// JURISDICTIONAL RESTRICTIONS CITE extdeps.cloudflare.r2 R2Jurisdiction, WHICH IS THE CONSUMED +// AUTHORITY FOR THE FOUR WIRE VALUES. Re-spelling them as NonEmptyStr here would be a second name +// for one concept (DESIGN section 3). Default is in that coproduct and is NOT a restriction; +// the guarantee is derived by matching the existing type, so a fifth arm fails to compile rather +// than silently inheriting a string. +fn r2_jurisdiction_is_residency_guarantee(jurisdiction: R2Jurisdiction) -> Bool { + match jurisdiction { + R2JurisdictionDefault => false + R2JurisdictionEu => true + R2JurisdictionFedramp => true + R2JurisdictionUs => true + } } -// JURISDICTIONAL RESTRICTIONS ARE THE ONLY ARM UPSTREAM CALLS A GUARANTEE. They are listed so a -// reader can see what was available and not taken; they are not this repository's durable origin. type R2JurisdictionRestrictionRow { - jurisdiction: NonEmptyStr - description: NonEmptyStr + jurisdiction: R2Jurisdiction reading: CloudflarePublishedReading } data r2_jurisdiction_eu: R2JurisdictionRestrictionRow = R2JurisdictionRestrictionRow { - jurisdiction: "eu", - description: "European Union", + jurisdiction: R2JurisdictionEu, reading: r2_data_location_reading, } data r2_jurisdiction_fedramp: R2JurisdictionRestrictionRow = R2JurisdictionRestrictionRow { - jurisdiction: "fedramp", - description: "FedRAMP", + jurisdiction: R2JurisdictionFedramp, reading: r2_data_location_reading, } data r2_jurisdiction_us: R2JurisdictionRestrictionRow = R2JurisdictionRestrictionRow { - jurisdiction: "us", - description: "United States", + jurisdiction: R2JurisdictionUs, reading: r2_us_jurisdiction_changelog_reading, } -fn r2_jurisdiction_restrictions() -> List { - [r2_jurisdiction_eu, r2_jurisdiction_fedramp, r2_jurisdiction_us] +data r2_jurisdiction_default_standing: R2JurisdictionRestrictionRow = R2JurisdictionRestrictionRow { + jurisdiction: R2JurisdictionDefault, + reading: r2_tokens_default_jurisdiction_reading, } // AUTOMATIC IS A CHOICE MECHANISM, AND THAT IS WHAT THIS ROW RECORDS. It is the region a route // cites when a bucket was created without a jurisdictional restriction: not a country, not a // data-center park, and not a residency commitment. Treating R2JurisdictionDefault, a dashboard // Location label, or a Location Hint as the place the bytes live is the reading this row exists -// to make unusable as a location fact. +// to make unusable as a location fact. Automatic is not an arm of R2Jurisdiction — that type's +// corresponding non-guarantee is R2JurisdictionDefault, cited above. type R2PlacementModeRow { - mode: NonEmptyStr - is_residency_guarantee: Bool reading: CloudflarePublishedReading } data r2_placement_automatic: R2PlacementModeRow = R2PlacementModeRow { - mode: "Automatic", - is_residency_guarantee: false, reading: r2_data_location_reading, } - -data r2_jurisdiction_wire_default: R2PlacementModeRow = R2PlacementModeRow { - mode: "default", - is_residency_guarantee: false, - reading: r2_tokens_default_jurisdiction_reading, -} diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag index ac489a8e61b..680c2523576 100644 --- a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -26,9 +26,32 @@ import product.supplier.cloudflare_r2 { } import extdeps.cloudflare.r2_data_location { r2_placement_automatic, - r2_jurisdiction_wire_default, - r2_location_hints, - r2_jurisdiction_restrictions, + r2_jurisdiction_default_standing, + r2_jurisdiction_eu, + r2_jurisdiction_fedramp, + r2_jurisdiction_us, + r2_hint_wnam, + r2_hint_enam, + r2_hint_weur, + r2_hint_eeur, + r2_hint_apac, + r2_hint_oc, + r2_jurisdiction_is_residency_guarantee, + r2_location_hint_is_residency_guarantee, + r2_location_hint_wire, + R2HintWnam, + R2HintEnam, + R2HintWeur, + R2HintEeur, + R2HintApac, + R2HintOc, +} +import extdeps.cloudflare.r2 { + r2_jurisdiction_wire, + R2JurisdictionDefault, + R2JurisdictionEu, + R2JurisdictionFedramp, + R2JurisdictionUs, } data r2_witness_customer_profile: NonEmptyStr = "r2-witness-customer-profile" @@ -258,10 +281,54 @@ test fn every_r2_route_in_the_population_refuses() -> Bool { } test fn automatic_placement_is_not_a_residency_guarantee() -> Bool { - !r2_placement_automatic.is_residency_guarantee - && !r2_jurisdiction_wire_default.is_residency_guarantee + !r2_jurisdiction_is_residency_guarantee(jurisdiction: r2_jurisdiction_default_standing.jurisdiction) + && r2_jurisdiction_is_residency_guarantee(jurisdiction: r2_jurisdiction_eu.jurisdiction) + && r2_jurisdiction_is_residency_guarantee(jurisdiction: r2_jurisdiction_fedramp.jurisdiction) + && r2_jurisdiction_is_residency_guarantee(jurisdiction: r2_jurisdiction_us.jurisdiction) + && (r2_jurisdiction_wire(jurisdiction: r2_jurisdiction_default_standing.jurisdiction) as String) == "default" +} + +test fn restriction_rows_are_the_existing_jurisdiction_arms() -> Bool { + match r2_jurisdiction_eu.jurisdiction { + R2JurisdictionEu => true + R2JurisdictionDefault => false + R2JurisdictionFedramp => false + R2JurisdictionUs => false + } + && match r2_jurisdiction_fedramp.jurisdiction { + R2JurisdictionFedramp => true + R2JurisdictionDefault => false + R2JurisdictionEu => false + R2JurisdictionUs => false + } + && match r2_jurisdiction_us.jurisdiction { + R2JurisdictionUs => true + R2JurisdictionDefault => false + R2JurisdictionEu => false + R2JurisdictionFedramp => false + } + && match r2_jurisdiction_default_standing.jurisdiction { + R2JurisdictionDefault => true + R2JurisdictionEu => false + R2JurisdictionFedramp => false + R2JurisdictionUs => false + } } -test fn the_hint_roster_has_six_choices_and_three_jurisdiction_guarantees() -> Bool { - count(r2_location_hints()) == 6 && count(r2_jurisdiction_restrictions()) == 3 +test fn published_hints_are_choices_not_locations() -> Bool { + !r2_location_hint_is_residency_guarantee(hint: r2_hint_wnam.hint) + && !r2_location_hint_is_residency_guarantee(hint: r2_hint_enam.hint) + && !r2_location_hint_is_residency_guarantee(hint: r2_hint_weur.hint) + && !r2_location_hint_is_residency_guarantee(hint: r2_hint_eeur.hint) + && !r2_location_hint_is_residency_guarantee(hint: r2_hint_apac.hint) + && !r2_location_hint_is_residency_guarantee(hint: r2_hint_oc.hint) + && (r2_location_hint_wire(hint: r2_hint_wnam.hint) as String) == "wnam" + && match r2_hint_wnam.hint { + R2HintWnam => true + R2HintEnam => false + R2HintWeur => false + R2HintEeur => false + R2HintApac => false + R2HintOc => false + } } From 1a40c3f314fa9718d945ee0f19b52680771deab6 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sat, 12 Sep 2026 23:49:26 +0000 Subject: [PATCH 03/25] Drop unused location-hint coproduct; transcribe the Logpush limitation. Hints have no production consumer, and a constantly-false residency predicate is a permanently-green decoration. The data-location reading now includes upstream's Logpush-jurisdiction limitation, which the logs obligation already cited. Co-authored-by: Cursor --- dag/extdeps/cloudflare/r2_data_location.dag | 84 ++----------------- .../cloudflare_r2_route_witness_test.dag | 32 ------- 2 files changed, 5 insertions(+), 111 deletions(-) diff --git a/dag/extdeps/cloudflare/r2_data_location.dag b/dag/extdeps/cloudflare/r2_data_location.dag index cfd244b9b96..c46abaffb37 100644 --- a/dag/extdeps/cloudflare/r2_data_location.dag +++ b/dag/extdeps/cloudflare/r2_data_location.dag @@ -1,6 +1,6 @@ module extdeps.cloudflare.r2_data_location -import std.types { Bool, NonEmptyStr, String } +import std.types { Bool, NonEmptyStr } import std.decl_ref { DeclarationRef, WholeDeclaration } import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef } import extdeps.uri { Uri, Https } @@ -86,7 +86,7 @@ type CloudflarePublishedReading { data r2_data_location_reading: CloudflarePublishedReading = CloudflarePublishedReading { authority: extdeps_external_authority_anchor, read_on: "2026-09-12", - statement: "When you create a new bucket, the data location is set to Automatic by default. Currently, this option chooses a bucket location in the closest available region to the create bucket request based on the location of the caller. Location Hints are optional parameters you can provide during bucket creation to indicate the primary geographical location you expect data will be accessed from. Location Hints are a best effort and not a guarantee, and they should only be used as a way to optimize performance. Available hints: wnam Western North America, enam Eastern North America, weur Western Europe, eeur Eastern Europe, apac Asia-Pacific, oc Oceania. Jurisdictional Restrictions guarantee objects in a bucket are stored within a specific jurisdiction. Use Jurisdictional Restrictions when you need to ensure data is stored and processed within a jurisdiction to meet data residency requirements. Available jurisdictions: eu European Union, fedramp FedRAMP, us United States. Once an R2 bucket is created, the jurisdiction cannot be changed. Page last updated Aug 19, 2026.", + statement: "When you create a new bucket, the data location is set to Automatic by default. Currently, this option chooses a bucket location in the closest available region to the create bucket request based on the location of the caller. Location Hints are optional parameters you can provide during bucket creation to indicate the primary geographical location you expect data will be accessed from. Location Hints are a best effort and not a guarantee, and they should only be used as a way to optimize performance. Available hints: wnam Western North America, enam Eastern North America, weur Western Europe, eeur Eastern Europe, apac Asia-Pacific, oc Oceania. Jurisdictional Restrictions guarantee objects in a bucket are stored within a specific jurisdiction. Use Jurisdictional Restrictions when you need to ensure data is stored and processed within a jurisdiction to meet data residency requirements. Available jurisdictions: eu European Union, fedramp FedRAMP, us United States. The following services do not interact with R2 resources with assigned jurisdictions: Logpush. Once an R2 bucket is created, the jurisdiction cannot be changed. Page last updated Aug 19, 2026.", } data r2_how_r2_works_reading: CloudflarePublishedReading = CloudflarePublishedReading { @@ -136,87 +136,13 @@ data cloudflare_inc: CloudflareLegalEntity = CloudflareLegalEntity { reading: r2_data_location_reading, } -// LOCATION HINTS ARE A CLOSED COPRODUCT OF CHOICES, NOT A ROSTER OF PLACES THE BYTES ARE. -// Upstream names them hints, says they are a best effort and not a guarantee, and uses them to -// optimize performance. The tag set lives here because extdeps.cloudflare.r2 does not declare it; -// the wire spelling is produced from the coproduct rather than stored as a second stringly name. -type R2LocationHint - = R2HintWnam - | R2HintEnam - | R2HintWeur - | R2HintEeur - | R2HintApac - | R2HintOc - -fn r2_location_hint_wire(hint: R2LocationHint) -> String { - match hint { - R2HintWnam => "wnam" - R2HintEnam => "enam" - R2HintWeur => "weur" - R2HintEeur => "eeur" - R2HintApac => "apac" - R2HintOc => "oc" - } -} - -fn r2_location_hint_is_residency_guarantee(hint: R2LocationHint) -> Bool { - match hint { - R2HintWnam => false - R2HintEnam => false - R2HintWeur => false - R2HintEeur => false - R2HintApac => false - R2HintOc => false - } -} - -type R2LocationHintRow { - hint: R2LocationHint - description: NonEmptyStr - reading: CloudflarePublishedReading -} - -data r2_hint_wnam: R2LocationHintRow = R2LocationHintRow { - hint: R2HintWnam, - description: "Western North America", - reading: r2_data_location_reading, -} - -data r2_hint_enam: R2LocationHintRow = R2LocationHintRow { - hint: R2HintEnam, - description: "Eastern North America", - reading: r2_data_location_reading, -} - -data r2_hint_weur: R2LocationHintRow = R2LocationHintRow { - hint: R2HintWeur, - description: "Western Europe", - reading: r2_data_location_reading, -} - -data r2_hint_eeur: R2LocationHintRow = R2LocationHintRow { - hint: R2HintEeur, - description: "Eastern Europe", - reading: r2_data_location_reading, -} - -data r2_hint_apac: R2LocationHintRow = R2LocationHintRow { - hint: R2HintApac, - description: "Asia-Pacific", - reading: r2_data_location_reading, -} - -data r2_hint_oc: R2LocationHintRow = R2LocationHintRow { - hint: R2HintOc, - description: "Oceania", - reading: r2_data_location_reading, -} - // JURISDICTIONAL RESTRICTIONS CITE extdeps.cloudflare.r2 R2Jurisdiction, WHICH IS THE CONSUMED // AUTHORITY FOR THE FOUR WIRE VALUES. Re-spelling them as NonEmptyStr here would be a second name // for one concept (DESIGN section 3). Default is in that coproduct and is NOT a restriction; // the guarantee is derived by matching the existing type, so a fifth arm fails to compile rather -// than silently inheriting a string. +// than silently inheriting a string. Location hints stay in r2_data_location_reading rather than +// as a coproduct: no production path consults a hint identity, and a constantly-false residency +// predicate over one would be a permanently-green decoration (DESIGN sections 3c and 4b). fn r2_jurisdiction_is_residency_guarantee(jurisdiction: R2Jurisdiction) -> Bool { match jurisdiction { R2JurisdictionDefault => false diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag index 680c2523576..b74c171f1bd 100644 --- a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -30,21 +30,7 @@ import extdeps.cloudflare.r2_data_location { r2_jurisdiction_eu, r2_jurisdiction_fedramp, r2_jurisdiction_us, - r2_hint_wnam, - r2_hint_enam, - r2_hint_weur, - r2_hint_eeur, - r2_hint_apac, - r2_hint_oc, r2_jurisdiction_is_residency_guarantee, - r2_location_hint_is_residency_guarantee, - r2_location_hint_wire, - R2HintWnam, - R2HintEnam, - R2HintWeur, - R2HintEeur, - R2HintApac, - R2HintOc, } import extdeps.cloudflare.r2 { r2_jurisdiction_wire, @@ -314,21 +300,3 @@ test fn restriction_rows_are_the_existing_jurisdiction_arms() -> Bool { R2JurisdictionUs => false } } - -test fn published_hints_are_choices_not_locations() -> Bool { - !r2_location_hint_is_residency_guarantee(hint: r2_hint_wnam.hint) - && !r2_location_hint_is_residency_guarantee(hint: r2_hint_enam.hint) - && !r2_location_hint_is_residency_guarantee(hint: r2_hint_weur.hint) - && !r2_location_hint_is_residency_guarantee(hint: r2_hint_eeur.hint) - && !r2_location_hint_is_residency_guarantee(hint: r2_hint_apac.hint) - && !r2_location_hint_is_residency_guarantee(hint: r2_hint_oc.hint) - && (r2_location_hint_wire(hint: r2_hint_wnam.hint) as String) == "wnam" - && match r2_hint_wnam.hint { - R2HintWnam => true - R2HintEnam => false - R2HintWeur => false - R2HintEeur => false - R2HintApac => false - R2HintOc => false - } -} From 250870b85869e8c105a70e09eb4a4e06d5df6e83 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 00:22:28 +0000 Subject: [PATCH 04/25] Consume the existing tokens-page anchor and the vendor Cloudflare row. The tokens URI already lives as extdeps.cloudflare.r2's authority anchor; a second ExternalAuthority with the same locator was independently editable. The route's provider now cites extdeps.vendor.cloudflare cloudflare rather than reminting the legal name. Co-authored-by: Cursor --- dag/extdeps/cloudflare/r2_data_location.dag | 48 +++++++------------ dag/gunbc/product/supplier/cloudflare_r2.dag | 2 +- .../cloudflare_r2_route_witness_test.dag | 8 +++- 3 files changed, 23 insertions(+), 35 deletions(-) diff --git a/dag/extdeps/cloudflare/r2_data_location.dag b/dag/extdeps/cloudflare/r2_data_location.dag index c46abaffb37..25b068c3bce 100644 --- a/dag/extdeps/cloudflare/r2_data_location.dag +++ b/dag/extdeps/cloudflare/r2_data_location.dag @@ -1,7 +1,7 @@ module extdeps.cloudflare.r2_data_location import std.types { Bool, NonEmptyStr } -import std.decl_ref { DeclarationRef, WholeDeclaration } +import std.decl_ref { DeclarationRef, WholeDeclaration, decl_ref } import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef } import extdeps.uri { Uri, Https } import extdeps.cloudflare.r2 { @@ -34,13 +34,6 @@ data r2_us_jurisdiction_changelog_authority: ExternalAuthority = ExternalAuthori } } -data r2_tokens_jurisdiction_default_authority: ExternalAuthority = ExternalAuthority { - uri: Uri { - scheme: Https - locator: "developers.cloudflare.com/r2/api/tokens" - } -} - data cloudflare_subprocessors_authority: ExternalAuthority = ExternalAuthority { uri: Uri { scheme: Https @@ -67,7 +60,6 @@ data extdeps_model_scope: ExternalModelScope = ExternalModelScope { further_citations: [ r2_how_r2_works_authority, r2_us_jurisdiction_changelog_authority, - r2_tokens_jurisdiction_default_authority, cloudflare_subprocessors_authority, cloudflare_customer_dpa_authority, ] @@ -77,64 +69,56 @@ data extdeps_model_scope: ExternalModelScope = ExternalModelScope { // statement field is a TRANSCRIPTION of upstream's own words, not commentary about them. A reading // is dated and never silently refreshed: upstream edits a page without telling anyone, so a // statement that no longer appears at its URI is a NEW reading with a later date. +// AUTHORITY IS A CITATION TO THE PAGE'S EXISTING ROW, NOT A SECOND URI STRUCT. The tokens page +// already lives as extdeps.cloudflare.r2 extdeps_external_authority_anchor; a second ExternalAuthority +// with the same locator would be independently editable and is the nickname DESIGN section 3 +// forbids. Pages this module introduces keep their ExternalAuthority rows and are cited from here. type CloudflarePublishedReading { - authority: ExternalAuthority + authority: DeclarationRef read_on: NonEmptyStr statement: NonEmptyStr } data r2_data_location_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: extdeps_external_authority_anchor, + authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "extdeps_external_authority_anchor"), read_on: "2026-09-12", statement: "When you create a new bucket, the data location is set to Automatic by default. Currently, this option chooses a bucket location in the closest available region to the create bucket request based on the location of the caller. Location Hints are optional parameters you can provide during bucket creation to indicate the primary geographical location you expect data will be accessed from. Location Hints are a best effort and not a guarantee, and they should only be used as a way to optimize performance. Available hints: wnam Western North America, enam Eastern North America, weur Western Europe, eeur Eastern Europe, apac Asia-Pacific, oc Oceania. Jurisdictional Restrictions guarantee objects in a bucket are stored within a specific jurisdiction. Use Jurisdictional Restrictions when you need to ensure data is stored and processed within a jurisdiction to meet data residency requirements. Available jurisdictions: eu European Union, fedramp FedRAMP, us United States. The following services do not interact with R2 resources with assigned jurisdictions: Logpush. Once an R2 bucket is created, the jurisdiction cannot be changed. Page last updated Aug 19, 2026.", } data r2_how_r2_works_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: r2_how_r2_works_authority, + authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "r2_how_r2_works_authority"), read_on: "2026-09-12", statement: "R2 Gateway: The entry point for all API requests that handles authentication and routing logic. This service is deployed across Cloudflare's global network via Cloudflare Workers. Metadata Service: A distributed layer built on Durable Objects used to store and manage object metadata. Distributed Storage Infrastructure: The underlying infrastructure that persistently stores encrypted object data. On write, the Gateway determines which storage cluster to write the encrypted data to within the location set for the bucket. The encrypted data is written and stored in the distributed storage infrastructure, and replicated within the region (e.g. ENAM) for durability. On read, if the object is not in the tiered read cache, it retrieves the object from one of the distributed storage data centers within the region that holds the object data. Page last updated Apr 21, 2026.", } data r2_us_jurisdiction_changelog_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: r2_us_jurisdiction_changelog_authority, + authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "r2_us_jurisdiction_changelog_authority"), read_on: "2026-09-12", statement: "New us jurisdiction for R2. R2 now supports a us jurisdiction, which guarantees that bucket data is stored and processed within the United States. Use this jurisdiction when you need explicit US data residency guarantees. Use the jurisdiction-specific S3 endpoint https://.us.r2.cloudflarestorage.com. Once an R2 bucket is created, its jurisdiction cannot be changed. Posted 2026-08-17.", } data r2_tokens_default_jurisdiction_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: r2_tokens_jurisdiction_default_authority, + authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "extdeps_external_authority_anchor"), read_on: "2026-09-12", statement: "A specific bucket is represented as com.cloudflare.edge.r2.bucket.__. JURISDICTION: The jurisdiction where the R2 bucket lives. For buckets not created in a specific jurisdiction this value will be default.", } data cloudflare_subprocessors_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: cloudflare_subprocessors_authority, + authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_subprocessors_authority"), read_on: "2026-09-12", statement: "Last Updated: October 1, 2025. Cloudflare uses a handful of sub-processors to support the Cloudflare service. Some of these sub-processors are members of the Cloudflare Group (Cloudflare, Inc. and its subsidiaries) and some are third parties. Third-party entities include Slack Technologies, Inc. (Customer support communications, United States); Zendesk, Inc. (Customer support and account management, United States, the European Economic Area, Japan, and Australia); Salesforce, Inc. (Customer support and account management, United States); Google LLC (Cloudflare Developer Platform, Cloudflare Zero Trust and AI Gateway; European Economic Area, United States, Australia, India); Oracle America, Inc. (Cloudflare Developer Platform and Cache Reserve; United States, European Economic Area, UK, Japan, Australia, Canada, Singapore); Amazon Web Services (Cloudflare Email Security; United States, European Economic Area); CoreWeave, Inc., Nebius BV (Workers AI); Anthropic PBC, OpenAI, Inc., X.AI Corp., Groq, Inc. (AI Gateway). The page lists Cloudflare Group subsidiaries by location and does not key any row to a named R2 bucket or to the default jurisdiction.", } data cloudflare_customer_dpa_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: cloudflare_customer_dpa_authority, + authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_customer_dpa_authority"), read_on: "2026-09-12", statement: "Cloudflare, Inc. Data Processing Addendum, Version 6.4 April 3, 2026. The Customer grants a general written authorization: (a) to Cloudflare to appoint other members of the Cloudflare Group as sub-Processors, and (b) to Cloudflare and other members of the Cloudflare Group to appoint third party data center operators, and business, engineering and customer support providers as sub-Processors to support the performance of the Service. Cloudflare will maintain a list of sub-Processors at https://www.cloudflare.com/gdpr/subprocessors/. This DPA and any action related thereto shall be governed by and construed in accordance with the laws as specified in the Main Agreement, and the parties consent to the personal jurisdiction of, and venue in, the courts specified in the Main Agreement.", } -// THE LEGAL ENTITY THE DOCUMENTS NAME. A route's operator slot needs a party. The legal name is -// the same spelling already declared as extdeps.vendor.cloudflare cloudflare; the address is -// transcribed from the data-location page's publisher Organization on the same read date. -type CloudflareLegalEntity { - legal_name: NonEmptyStr - registered_address: NonEmptyStr - country: NonEmptyStr - reading: CloudflarePublishedReading -} - -data cloudflare_inc: CloudflareLegalEntity = CloudflareLegalEntity { - legal_name: "Cloudflare, Inc.", - registered_address: "101 Townsend St, San Francisco, CA 94107, US", - country: "United States", - reading: r2_data_location_reading, -} +// THE COMPANY PARTY IS extdeps.vendor.cloudflare cloudflare. A legal-name literal here would be +// a second name for that Vendor row (DESIGN section 3). Address and country from a docs publisher +// block are not a residency commitment and are not minted as a parallel party. The route's +// provider slot cites that vendor row. // JURISDICTIONAL RESTRICTIONS CITE extdeps.cloudflare.r2 R2Jurisdiction, WHICH IS THE CONSUMED // AUTHORITY FOR THE FOUR WIRE VALUES. Re-spelling them as NonEmptyStr here would be a second name diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag index 8fc2877fb6c..23540b1c7e9 100644 --- a/dag/gunbc/product/supplier/cloudflare_r2.dag +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -36,7 +36,7 @@ import product.fabric.provider_admission { // BOTH THE REFUSING PRODUCTION ROW AND THE DISCRIMINATING PAIR ARE THE DELIVERABLE. fn cloudflare_r2_provider_ref() -> DeclarationRef { - decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_inc") + decl_ref(module_path: "extdeps.vendor.cloudflare", decl_name: "cloudflare") } fn cloudflare_r2_service_ref() -> DeclarationRef { diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag index b74c171f1bd..88d48f689a9 100644 --- a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -248,9 +248,13 @@ test fn the_same_route_admits_once_that_path_is_resolved() -> Bool { ProviderUseDenied { decision, cause } => false, ProviderUseAdmitted { permit } => declaration_ref_eq( - a: permit.route.region, - b: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "r2_placement_automatic"), + a: permit.route.provider, + b: decl_ref(module_path: "extdeps.vendor.cloudflare", decl_name: "cloudflare"), ) + && declaration_ref_eq( + a: permit.route.region, + b: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "r2_placement_automatic"), + ) && declaration_ref_eq( a: permit.evidence.customer_profile, b: t_customer_profile(), From b2e0dcaa87cba3c91daf7d4edb6cbc09b39d764c Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 00:52:26 +0000 Subject: [PATCH 05/25] Delete the unused residency Bool and restriction rows from production. They had no non-witness consumer. Classification of R2Jurisdiction stays on the existing coproduct and its wire fold; the witness matches those arms locally rather than exporting a path_is_resolved-shaped predicate. Co-authored-by: Cursor --- dag/extdeps/cloudflare/r2_data_location.dag | 63 ++++--------------- .../cloudflare_r2_route_witness_test.dag | 43 ++----------- 2 files changed, 18 insertions(+), 88 deletions(-) diff --git a/dag/extdeps/cloudflare/r2_data_location.dag b/dag/extdeps/cloudflare/r2_data_location.dag index 25b068c3bce..b5a4ebb48b3 100644 --- a/dag/extdeps/cloudflare/r2_data_location.dag +++ b/dag/extdeps/cloudflare/r2_data_location.dag @@ -1,16 +1,9 @@ module extdeps.cloudflare.r2_data_location -import std.types { Bool, NonEmptyStr } +import std.types { NonEmptyStr } import std.decl_ref { DeclarationRef, WholeDeclaration, decl_ref } import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef } import extdeps.uri { Uri, Https } -import extdeps.cloudflare.r2 { - R2Jurisdiction, - R2JurisdictionDefault, - R2JurisdictionEu, - R2JurisdictionFedramp, - R2JurisdictionUs, -} data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { @@ -119,54 +112,24 @@ data cloudflare_customer_dpa_reading: CloudflarePublishedReading = CloudflarePub // a second name for that Vendor row (DESIGN section 3). Address and country from a docs publisher // block are not a residency commitment and are not minted as a parallel party. The route's // provider slot cites that vendor row. - -// JURISDICTIONAL RESTRICTIONS CITE extdeps.cloudflare.r2 R2Jurisdiction, WHICH IS THE CONSUMED -// AUTHORITY FOR THE FOUR WIRE VALUES. Re-spelling them as NonEmptyStr here would be a second name -// for one concept (DESIGN section 3). Default is in that coproduct and is NOT a restriction; -// the guarantee is derived by matching the existing type, so a fifth arm fails to compile rather -// than silently inheriting a string. Location hints stay in r2_data_location_reading rather than -// as a coproduct: no production path consults a hint identity, and a constantly-false residency -// predicate over one would be a permanently-green decoration (DESIGN sections 3c and 4b). -fn r2_jurisdiction_is_residency_guarantee(jurisdiction: R2Jurisdiction) -> Bool { - match jurisdiction { - R2JurisdictionDefault => false - R2JurisdictionEu => true - R2JurisdictionFedramp => true - R2JurisdictionUs => true - } -} - -type R2JurisdictionRestrictionRow { - jurisdiction: R2Jurisdiction - reading: CloudflarePublishedReading -} - -data r2_jurisdiction_eu: R2JurisdictionRestrictionRow = R2JurisdictionRestrictionRow { - jurisdiction: R2JurisdictionEu, - reading: r2_data_location_reading, -} - -data r2_jurisdiction_fedramp: R2JurisdictionRestrictionRow = R2JurisdictionRestrictionRow { - jurisdiction: R2JurisdictionFedramp, - reading: r2_data_location_reading, -} - -data r2_jurisdiction_us: R2JurisdictionRestrictionRow = R2JurisdictionRestrictionRow { - jurisdiction: R2JurisdictionUs, - reading: r2_us_jurisdiction_changelog_reading, -} - -data r2_jurisdiction_default_standing: R2JurisdictionRestrictionRow = R2JurisdictionRestrictionRow { - jurisdiction: R2JurisdictionDefault, - reading: r2_tokens_default_jurisdiction_reading, -} +// +// JURISDICTION TAGS LIVE ON extdeps.cloudflare.r2 R2Jurisdiction. This module does not re-export +// them, does not wrap them in unused restriction rows, and does not export a Bool over the +// coproduct. A Bool over that type would be the same attractor product.fabric.provider_admission +// deleted from path_is_resolved: it discards the arm, so a later caller walks the value again. +// Location hints stay in r2_data_location_reading rather than as a coproduct: no production path +// consults a hint identity, and a constantly-false residency predicate over one would be a +// permanently-green decoration (DESIGN sections 3c and 4b). The same argument forbids a production +// Bool over R2Jurisdiction. The default wire value is transcribed in +// r2_tokens_default_jurisdiction_reading; the fleet bucket's jurisdiction is +// gunbc.cloudflare.r2_origin fabric_durable_origin_standing. // AUTOMATIC IS A CHOICE MECHANISM, AND THAT IS WHAT THIS ROW RECORDS. It is the region a route // cites when a bucket was created without a jurisdictional restriction: not a country, not a // data-center park, and not a residency commitment. Treating R2JurisdictionDefault, a dashboard // Location label, or a Location Hint as the place the bytes live is the reading this row exists // to make unusable as a location fact. Automatic is not an arm of R2Jurisdiction — that type's -// corresponding non-guarantee is R2JurisdictionDefault, cited above. +// corresponding non-guarantee is R2JurisdictionDefault, owned by extdeps.cloudflare.r2. type R2PlacementModeRow { reading: CloudflarePublishedReading } diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag index 88d48f689a9..c8a44f525fb 100644 --- a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -26,11 +26,6 @@ import product.supplier.cloudflare_r2 { } import extdeps.cloudflare.r2_data_location { r2_placement_automatic, - r2_jurisdiction_default_standing, - r2_jurisdiction_eu, - r2_jurisdiction_fedramp, - r2_jurisdiction_us, - r2_jurisdiction_is_residency_guarantee, } import extdeps.cloudflare.r2 { r2_jurisdiction_wire, @@ -270,37 +265,9 @@ test fn every_r2_route_in_the_population_refuses() -> Bool { })) == 0 } -test fn automatic_placement_is_not_a_residency_guarantee() -> Bool { - !r2_jurisdiction_is_residency_guarantee(jurisdiction: r2_jurisdiction_default_standing.jurisdiction) - && r2_jurisdiction_is_residency_guarantee(jurisdiction: r2_jurisdiction_eu.jurisdiction) - && r2_jurisdiction_is_residency_guarantee(jurisdiction: r2_jurisdiction_fedramp.jurisdiction) - && r2_jurisdiction_is_residency_guarantee(jurisdiction: r2_jurisdiction_us.jurisdiction) - && (r2_jurisdiction_wire(jurisdiction: r2_jurisdiction_default_standing.jurisdiction) as String) == "default" -} - -test fn restriction_rows_are_the_existing_jurisdiction_arms() -> Bool { - match r2_jurisdiction_eu.jurisdiction { - R2JurisdictionEu => true - R2JurisdictionDefault => false - R2JurisdictionFedramp => false - R2JurisdictionUs => false - } - && match r2_jurisdiction_fedramp.jurisdiction { - R2JurisdictionFedramp => true - R2JurisdictionDefault => false - R2JurisdictionEu => false - R2JurisdictionUs => false - } - && match r2_jurisdiction_us.jurisdiction { - R2JurisdictionUs => true - R2JurisdictionDefault => false - R2JurisdictionEu => false - R2JurisdictionFedramp => false - } - && match r2_jurisdiction_default_standing.jurisdiction { - R2JurisdictionDefault => true - R2JurisdictionEu => false - R2JurisdictionFedramp => false - R2JurisdictionUs => false - } +test fn default_jurisdiction_wire_is_not_a_restriction() -> Bool { + (r2_jurisdiction_wire(jurisdiction: R2JurisdictionDefault) as String) == "default" + && (r2_jurisdiction_wire(jurisdiction: R2JurisdictionEu) as String) == "eu" + && (r2_jurisdiction_wire(jurisdiction: R2JurisdictionUs) as String) == "us" + && (r2_jurisdiction_wire(jurisdiction: R2JurisdictionFedramp) as String) == "fedramp" } From 7c2f730a9c61007d16c8d9c37724c2554b13ad0a Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 01:33:54 +0000 Subject: [PATCH 06/25] Do not mint a ProviderRoute whose region is Automatic placement. Automatic is a choice mechanism, not where the durable origin runs. A route is now minted only from a read region, matching product.supplier.ubicloud; the production standing stays RegionUnobserved and the facts population is empty. The admit/refuse pair uses a witness route so Automatic cannot become an admitted location. Co-authored-by: Cursor --- dag/gunbc/product/supplier/cloudflare_r2.dag | 57 ++++++++++--- .../cloudflare_r2_route_witness_test.dag | 79 ++++++++++++++----- 2 files changed, 104 insertions(+), 32 deletions(-) diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag index 23540b1c7e9..b34a6afdfa2 100644 --- a/dag/gunbc/product/supplier/cloudflare_r2.dag +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -33,7 +33,16 @@ import product.fabric.provider_admission { // supposed to rest on. ProviderPathAbsent is also not taken: nobody has stated that any of these // nine paths do not exist. // -// BOTH THE REFUSING PRODUCTION ROW AND THE DISCRIMINATING PAIR ARE THE DELIVERABLE. +// THE REGION SLOT IS NOT A PLACE TO RECORD THAT FINDING. product.fabric.provider_route says the +// cited region is where the work actually runs, observed at a declared boundary and never +// fabricated. extdeps.cloudflare.r2_data_location r2_placement_automatic is a CHOICE MECHANISM, +// and putting it in ProviderRoute.region would make Automatic an admitted location the moment a +// roster row and a resolved path closure exist -- which is validation standing where construction +// was available (DESIGN section 5). product.supplier.ubicloud already ruled that shape out: +// a ProviderRoute is minted ONLY from a read region. Automatic stays in the location module as +// the reading of the choice; it does not occupy this slot. +// +// BOTH THE REFUSING PRODUCTION STANDING AND THE DISCRIMINATING PAIR ARE THE DELIVERABLE. fn cloudflare_r2_provider_ref() -> DeclarationRef { decl_ref(module_path: "extdeps.vendor.cloudflare", decl_name: "cloudflare") @@ -43,18 +52,41 @@ fn cloudflare_r2_service_ref() -> DeclarationRef { decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "extdeps_external_authority_anchor") } -fn cloudflare_r2_region_ref() -> DeclarationRef { - decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "r2_placement_automatic") +type CloudflareR2RegionObservation + = CloudflareR2RegionRead { region: DeclarationRef } + | CloudflareR2RegionUnread { obligation: DeclarationRef } + +type CloudflareR2RouteStanding + = CloudflareR2RouteObserved { route: ProviderRoute } + | CloudflareR2RouteRegionUnobserved { obligation: DeclarationRef } + +data cloudflare_r2_region_unread_obligation: NonEmptyStr = "Where this fleet's durable origin actually runs is UNREAD. gunbc.cloudflare.r2_origin fabric_durable_origin_standing places bucket gunbai-fabric-origin under R2JurisdictionDefault. extdeps.cloudflare.r2_data_location r2_data_location_reading states that Automatic placement chooses a region from the caller's location at create time and that Location Hints are a best effort, not a guarantee. Automatic is therefore a CHOICE, not a location, and it is not a value of ProviderRoute.region. RESOLVED BY a Cloudflare statement that names the jurisdiction or operating region of gunbai-fabric-origin the way Jurisdictional Restrictions do, or by recreating the origin under such a restriction -- at which point this standing takes CloudflareR2RegionRead with that named location as region. It is NOT resolved by citing r2_placement_automatic, R2JurisdictionDefault, a dashboard Location label, or a Location Hint." + +fn cloudflare_r2_durable_origin_region() -> CloudflareR2RegionObservation { + CloudflareR2RegionUnread { + obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_region_unread_obligation"), + } } -fn cloudflare_r2_durable_origin_route() -> ProviderRoute { - ProviderRoute { - provider: cloudflare_r2_provider_ref(), - service: cloudflare_r2_service_ref(), - region: cloudflare_r2_region_ref(), +fn cloudflare_r2_route(region: CloudflareR2RegionObservation) -> CloudflareR2RouteStanding { + match region { + CloudflareR2RegionUnread { obligation } => + CloudflareR2RouteRegionUnobserved { obligation: obligation }, + CloudflareR2RegionRead { region: observed } => + CloudflareR2RouteObserved { + route: ProviderRoute { + provider: cloudflare_r2_provider_ref(), + service: cloudflare_r2_service_ref(), + region: observed, + }, + }, } } +fn cloudflare_r2_durable_origin_route_standing() -> CloudflareR2RouteStanding { + cloudflare_r2_route(region: cloudflare_r2_durable_origin_region()) +} + data cloudflare_r2_execution_location_obligation: NonEmptyStr = "Where R2 executes object operations for a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2_data_location r2_how_r2_works_reading states that the R2 Gateway is deployed across Cloudflare's global network via Cloudflare Workers, close to the user, and that the Gateway then writes to a storage cluster within the location set for the bucket. That is an architecture of a CHOICE, not a location of this fleet's bucket. RESOLVED BY a Cloudflare statement naming the jurisdiction or operating entity of request handling for a named default-jurisdiction bucket -- at which point this path takes Located with that entity as operator. It is NOT resolved by R2JurisdictionDefault, by Automatic placement, or by a Location Hint." data cloudflare_r2_durable_storage_location_obligation: NonEmptyStr = "Where objects in this fleet's durable origin are stored is UNREAD, and that is a read of Cloudflare's own location rules rather than a missing document. gunbc.cloudflare.r2_origin fabric_durable_origin_standing places bucket gunbai-fabric-origin under R2JurisdictionDefault. extdeps.cloudflare.r2_data_location r2_data_location_reading (URI developers.cloudflare.com/r2/reference/data-location, read 2026-09-12) states that a new bucket's data location is Automatic by default, which chooses a bucket location in the closest available region to the create bucket request based on the location of the caller; that Location Hints are a best effort and not a guarantee; and that Jurisdictional Restrictions (eu, us, fedramp) are what guarantee objects are stored and processed within a jurisdiction. r2_tokens_default_jurisdiction_reading states that for buckets not created in a specific jurisdiction the wire value is default. THIS PATH IS THEREFORE A CHOICE, NOT A LOCATION. RESOLVED BY recreating the origin under a Jurisdictional Restriction that names a jurisdiction, or by a Cloudflare statement that objects in gunbai-fabric-origin are stored and processed within a named jurisdiction the way Jurisdictional Restrictions do. It is NOT resolved by reading the API location field (wnam/enam/weur/eeur/apac/oc), which upstream lists as a hint, nor by treating R2JurisdictionDefault as residency." @@ -113,9 +145,9 @@ fn cloudflare_r2_downstream() -> DownstreamProviderPopulation { } } -fn cloudflare_r2_durable_origin_route_facts() -> ProviderRouteFacts { +fn cloudflare_r2_facts(route: ProviderRoute) -> ProviderRouteFacts { ProviderRouteFacts { - route: cloudflare_r2_durable_origin_route(), + route: route, contract_terms: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_customer_dpa_reading"), data_paths: cloudflare_r2_data_paths(), downstream: cloudflare_r2_downstream(), @@ -125,7 +157,10 @@ fn cloudflare_r2_durable_origin_route_facts() -> ProviderRouteFacts { } fn cloudflare_r2_route_facts_population() -> List { - [cloudflare_r2_durable_origin_route_facts()] + match cloudflare_r2_durable_origin_route_standing() { + CloudflareR2RouteRegionUnobserved { obligation } => [], + CloudflareR2RouteObserved { route } => [cloudflare_r2_facts(route: route)], + } } // THIS MODULE DECLARES NO SANCTION ROSTER AND NO POSTURE REVISION. Nobody has stated that we are diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag index c8a44f525fb..4ba9e52a7f2 100644 --- a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -15,17 +15,17 @@ import product.fabric.provider_admission { ProviderRouteUnclassified, ProviderRouteFactsIncomplete, DownstreamProviderUnassessed, PostureRevisionStale, CustomerScopeUnsupported, DataHandlingUnsupported, RequiredAgreementAuthorityAbsent, ProhibitedUseNotCleared, SanctionsNotCleared, ExportNotCleared, - DispositionStanding, DispositionCleared, + DispositionCleared, } import product.supplier.cloudflare_r2 { - cloudflare_r2_durable_origin_route, - cloudflare_r2_durable_origin_route_facts, + cloudflare_r2_route, + cloudflare_r2_durable_origin_route_standing, cloudflare_r2_route_admission, cloudflare_r2_route_facts_population, cloudflare_r2_data_paths, -} -import extdeps.cloudflare.r2_data_location { - r2_placement_automatic, + CloudflareR2RegionRead, + CloudflareR2RouteObserved, + CloudflareR2RouteRegionUnobserved, } import extdeps.cloudflare.r2 { r2_jurisdiction_wire, @@ -47,6 +47,7 @@ data r2_witness_resolved_operator: NonEmptyStr = "r2-witness-resolved-operator" data r2_witness_resolved_jurisdiction: NonEmptyStr = "r2-witness-resolved-jurisdiction" data r2_witness_resolved_evidence: NonEmptyStr = "r2-witness-resolved-evidence" data r2_witness_no_downstream: NonEmptyStr = "r2-witness-no-downstream" +data r2_witness_synthetic_region: NonEmptyStr = "r2-witness-synthetic-region" fn t_resolved() -> ProviderPathStanding { ProviderPathLocated { @@ -75,6 +76,18 @@ fn t_agreement() -> DeclarationRef { decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_agreement") } +// THE DISCRIMINATOR ROUTE IS A WITNESS SUBJECT, NOT AUTOMATIC. Production standing does not mint +// a ProviderRoute for the durable origin, because Automatic is a choice mechanism. The pair +// below needs some route identity so admit_provider_use can run; that identity is this fixture +// and is not a location fact about gunbai-fabric-origin. +fn t_synthetic_route() -> ProviderRoute { + ProviderRoute { + provider: decl_ref(module_path: "extdeps.vendor.cloudflare", decl_name: "cloudflare"), + service: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "extdeps_external_authority_anchor"), + region: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_synthetic_region"), + } +} + fn t_sanction(route: ProviderRoute) -> RouteScopeSanction { RouteScopeSanction { route: route, @@ -86,7 +99,7 @@ fn t_sanction(route: ProviderRoute) -> RouteScopeSanction { } fn t_roster() -> List { - [t_sanction(route: cloudflare_r2_durable_origin_route())] + [t_sanction(route: t_synthetic_route())] } fn t_scope() -> ProviderUseScope { @@ -162,12 +175,17 @@ fn t_denied_with(a: ProviderUseAdmission, tag: String, located: Dec } } -test fn the_durable_origin_refuses_as_downstream_unassessed() -> Bool { - t_denied_with( - a: t_decide(facts: cloudflare_r2_durable_origin_route_facts()), - tag: "downstream-unassessed", - located: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_downstream_obligation"), - ) +test fn the_durable_origin_region_is_unread() -> Bool { + match cloudflare_r2_durable_origin_route_standing() { + CloudflareR2RouteObserved { route } => false, + CloudflareR2RouteRegionUnobserved { obligation } => declaration_ref_eq( + a: obligation, + b: decl_ref( + module_path: "product.supplier.cloudflare_r2", + decl_name: "cloudflare_r2_region_unread_obligation", + ), + ), + } } test fn the_durable_storage_path_is_unread_with_the_location_obligation() -> Bool { @@ -197,6 +215,19 @@ test fn no_production_path_is_absent() -> Bool { })) == 0 } +test fn every_production_path_is_unread() -> Bool { + let c = cloudflare_r2_data_paths() + let paths = [ + c.execution, c.durable_storage, c.backups, c.logs, c.telemetry, + c.control_plane, c.support_access, c.administrative_access, c.spill, + ] + count(filter(paths, p => match p { + ProviderPathUnread { obligation } => true, + ProviderPathLocated { operator, jurisdiction, evidence } => false, + ProviderPathAbsent { evidence } => false, + })) == 9 +} + fn t_paths_with_durable_storage(storage: ProviderPathStanding) -> ProviderDataPathClosure { ProviderDataPathClosure { execution: t_resolved(), @@ -219,7 +250,7 @@ fn t_synthetic_downstream() -> DownstreamProviderPopulation { fn t_facts_with_durable_storage(storage: ProviderPathStanding) -> ProviderRouteFacts { ProviderRouteFacts { - route: cloudflare_r2_durable_origin_route(), + route: t_synthetic_route(), contract_terms: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_customer_dpa_reading"), data_paths: t_paths_with_durable_storage(storage: storage), downstream: t_synthetic_downstream(), @@ -248,7 +279,7 @@ test fn the_same_route_admits_once_that_path_is_resolved() -> Bool { ) && declaration_ref_eq( a: permit.route.region, - b: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "r2_placement_automatic"), + b: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_synthetic_region"), ) && declaration_ref_eq( a: permit.evidence.customer_profile, @@ -257,12 +288,18 @@ test fn the_same_route_admits_once_that_path_is_resolved() -> Bool { } } -test fn every_r2_route_in_the_population_refuses() -> Bool { - count(cloudflare_r2_route_facts_population()) == 1 - && count(filter(cloudflare_r2_route_facts_population(), f => match t_decide(facts: f) { - ProviderUseAdmitted { permit } => true, - ProviderUseDenied { decision, cause } => false, - })) == 0 +test fn a_read_region_mints_a_route_and_an_unread_region_does_not() -> Bool { + match cloudflare_r2_route(region: CloudflareR2RegionRead { + region: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_synthetic_region"), + }) { + CloudflareR2RouteRegionUnobserved { obligation } => false, + CloudflareR2RouteObserved { route } => + declaration_ref_eq( + a: route.region, + b: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_synthetic_region"), + ) + && count(cloudflare_r2_route_facts_population()) == 0, + } } test fn default_jurisdiction_wire_is_not_a_restriction() -> Bool { From e0bf6a4a5114d5bb82c94bbe9ee3aac8ce3d0a7f Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 01:35:49 +0000 Subject: [PATCH 07/25] Invert the origin admit: there is no durable-origin route to permit. product.supplier.ubicloud already mints a ProviderRoute only in the read arm. The witness now asserts that standing for gunbai-fabric-origin: Unobserved yields an empty facts population, so resolving data paths cannot admit this origin. The unread-path discriminator still runs, but only on a route the same coproduct mints from a read region. Co-authored-by: Cursor --- .../cloudflare_r2_route_witness_test.dag | 113 +++++++++++------- 1 file changed, 67 insertions(+), 46 deletions(-) diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag index 4ba9e52a7f2..040e8c386a7 100644 --- a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -23,6 +23,8 @@ import product.supplier.cloudflare_r2 { cloudflare_r2_route_admission, cloudflare_r2_route_facts_population, cloudflare_r2_data_paths, + cloudflare_r2_facts, + CloudflareR2RegionObservation, CloudflareR2RegionRead, CloudflareR2RouteObserved, CloudflareR2RouteRegionUnobserved, @@ -76,14 +78,12 @@ fn t_agreement() -> DeclarationRef { decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_agreement") } -// THE DISCRIMINATOR ROUTE IS A WITNESS SUBJECT, NOT AUTOMATIC. Production standing does not mint -// a ProviderRoute for the durable origin, because Automatic is a choice mechanism. The pair -// below needs some route identity so admit_provider_use can run; that identity is this fixture -// and is not a location fact about gunbai-fabric-origin. -fn t_synthetic_route() -> ProviderRoute { - ProviderRoute { - provider: decl_ref(module_path: "extdeps.vendor.cloudflare", decl_name: "cloudflare"), - service: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "extdeps_external_authority_anchor"), +// THE DISCRIMINATOR ROUTE IS MINTED ONLY IN THE READ ARM, SAME CONSTRUCTION AS PRODUCTION. +// It is not gunbai-fabric-origin: that standing is Unobserved, so no origin route exists to +// admit. The pair below asks whether admit_provider_use still refuses an unread path and +// admits once that path is resolved, on a route the coproduct is allowed to mint. +fn t_read_region() -> CloudflareR2RegionObservation { + CloudflareR2RegionRead { region: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_synthetic_region"), } } @@ -98,8 +98,8 @@ fn t_sanction(route: ProviderRoute) -> RouteScopeSanction { } } -fn t_roster() -> List { - [t_sanction(route: t_synthetic_route())] +fn t_roster(route: ProviderRoute) -> List { + [t_sanction(route: route)] } fn t_scope() -> ProviderUseScope { @@ -125,10 +125,10 @@ fn t_offer() -> FabricIdentity { FabricIdentity { principal: "gunbc" as NonEmptyStr, key: "r2-witness-offer-1" as OfferKey } } -fn t_decide(facts: ProviderRouteFacts) -> ProviderUseAdmission { +fn t_decide(route: ProviderRoute, facts: ProviderRouteFacts) -> ProviderUseAdmission { cloudflare_r2_route_admission( facts: facts, - roster: t_roster(), + roster: t_roster(route: route), active: t_posture(), scope: t_scope(), offer: t_offer(), @@ -248,9 +248,9 @@ fn t_synthetic_downstream() -> DownstreamProviderPopulation { } } -fn t_facts_with_durable_storage(storage: ProviderPathStanding) -> ProviderRouteFacts { +fn t_facts_with_durable_storage(route: ProviderRoute, storage: ProviderPathStanding) -> ProviderRouteFacts { ProviderRouteFacts { - route: t_synthetic_route(), + route: route, contract_terms: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_customer_dpa_reading"), data_paths: t_paths_with_durable_storage(storage: storage), downstream: t_synthetic_downstream(), @@ -259,46 +259,67 @@ fn t_facts_with_durable_storage(storage: ProviderPathStanding) -> ProviderRouteF } } +test fn resolving_every_data_path_does_not_admit_the_durable_origin() -> Bool { + match cloudflare_r2_durable_origin_route_standing() { + CloudflareR2RouteObserved { route } => false, + CloudflareR2RouteRegionUnobserved { obligation } => + count(cloudflare_r2_route_facts_population()) == 0 + && count(filter(cloudflare_r2_route_facts_population(), f => match t_decide(route: f.route, facts: f) { + ProviderUseAdmitted { permit } => true, + ProviderUseDenied { decision, cause } => false, + })) == 0, + } +} + test fn one_unread_durable_storage_path_refuses_with_that_paths_obligation() -> Bool { - t_denied_with( - a: t_decide(facts: t_facts_with_durable_storage(storage: ProviderPathUnread { - obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_durable_storage_location_obligation"), - })), - tag: "facts-incomplete", - located: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_durable_storage_location_obligation"), - ) + match cloudflare_r2_route(region: t_read_region()) { + CloudflareR2RouteRegionUnobserved { obligation } => false, + CloudflareR2RouteObserved { route } => t_denied_with( + a: t_decide( + route: route, + facts: t_facts_with_durable_storage(route: route, storage: ProviderPathUnread { + obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_durable_storage_location_obligation"), + }), + ), + tag: "facts-incomplete", + located: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_durable_storage_location_obligation"), + ), + } } -test fn the_same_route_admits_once_that_path_is_resolved() -> Bool { - match t_decide(facts: t_facts_with_durable_storage(storage: t_resolved())) { - ProviderUseDenied { decision, cause } => false, - ProviderUseAdmitted { permit } => - declaration_ref_eq( - a: permit.route.provider, - b: decl_ref(module_path: "extdeps.vendor.cloudflare", decl_name: "cloudflare"), - ) - && declaration_ref_eq( - a: permit.route.region, - b: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_synthetic_region"), +test fn a_read_region_route_admits_once_that_path_is_resolved() -> Bool { + match cloudflare_r2_route(region: t_read_region()) { + CloudflareR2RouteRegionUnobserved { obligation } => false, + CloudflareR2RouteObserved { route } => match t_decide( + route: route, + facts: t_facts_with_durable_storage(route: route, storage: t_resolved()), + ) { + ProviderUseDenied { decision, cause } => false, + ProviderUseAdmitted { permit } => + declaration_ref_eq( + a: permit.route.provider, + b: decl_ref(module_path: "extdeps.vendor.cloudflare", decl_name: "cloudflare"), ) - && declaration_ref_eq( - a: permit.evidence.customer_profile, - b: t_customer_profile(), - ), + && declaration_ref_eq( + a: permit.route.region, + b: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_synthetic_region"), + ) + && declaration_ref_eq( + a: permit.evidence.customer_profile, + b: t_customer_profile(), + ), + }, } } -test fn a_read_region_mints_a_route_and_an_unread_region_does_not() -> Bool { - match cloudflare_r2_route(region: CloudflareR2RegionRead { - region: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_synthetic_region"), - }) { +test fn production_unread_paths_on_a_read_region_route_still_refuse() -> Bool { + match cloudflare_r2_route(region: t_read_region()) { CloudflareR2RouteRegionUnobserved { obligation } => false, - CloudflareR2RouteObserved { route } => - declaration_ref_eq( - a: route.region, - b: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_synthetic_region"), - ) - && count(cloudflare_r2_route_facts_population()) == 0, + CloudflareR2RouteObserved { route } => t_denied_with( + a: t_decide(route: route, facts: cloudflare_r2_facts(route: route)), + tag: "facts-incomplete", + located: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_execution_location_obligation"), + ), } } From d415d5b08c33b7cb322232791ae157a76d0e8857 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 01:36:58 +0000 Subject: [PATCH 08/25] Delete the admit_provider_use alias from the R2 supplier. cloudflare_r2_route_admission forwarded six parameters unchanged. The module has no roster or posture to bind, so the wrapper was a second name for the admission fold. The witness now calls admit_provider_use directly. Co-authored-by: Cursor --- dag/gunbc/product/supplier/cloudflare_r2.dag | 27 +++---------------- .../cloudflare_r2_route_witness_test.dag | 6 ++--- 2 files changed, 7 insertions(+), 26 deletions(-) diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag index b34a6afdfa2..b8b5ef85220 100644 --- a/dag/gunbc/product/supplier/cloudflare_r2.dag +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -3,15 +3,11 @@ module product.supplier.cloudflare_r2 import std.types { List, NonEmptyStr } import std.decl_ref { DeclarationRef, decl_ref } import std.content_hash { as_content_hash_structural, content_hash_atom } -import product.fabric.identity { FabricIdentity, OfferKey } import product.fabric.provider_route { - ProviderRoute, CompliancePostureRevision, ProviderRouteFacts, + ProviderRoute, ProviderRouteFacts, ProviderDataPathClosure, ProviderPathUnread, DownstreamProviderPopulation, DownstreamProvidersUnread, } -import product.fabric.provider_admission { - RouteScopeSanction, ProviderUseScope, ProviderUseAdmission, admit_provider_use, -} // THE DURABLE-ORIGIN ROUTE THIS REPOSITORY ANSWERS THE NINE-PATH CLOSURE FOR, AND THE ROW REFUSES. // @@ -166,27 +162,12 @@ fn cloudflare_r2_route_facts_population() -> List { // THIS MODULE DECLARES NO SANCTION ROSTER AND NO POSTURE REVISION. Nobody has stated that we are // willing to place work on this vendor's default-jurisdiction R2 under a named posture. Writing a // roster row here to make the module look complete would be the fabricated authority the gate exists -// to close. The producer takes roster and posture from its caller and supplies only the route facts. +// to close. The module supplies only the route facts. Callers that need a permit call +// product.fabric.provider_admission admit_provider_use with those facts; there is no wrapper here +// because a wrapper with nothing of its own to bind would be a second name for that fold. // // DECLARED FRONTIER (DESIGN section 3c). The production consumer is a posture producer that mints a // CompliancePostureRevision whose permitted_jurisdictions enumerate only routes whose facts have // been read and cleared. TRIGGER: that producer, SUFFICIENT FOR this route to be included or // omitted by matching these facts rather than by a dashboard label. Until then the executing // consumer is the witness. -fn cloudflare_r2_route_admission

( - facts: ProviderRouteFacts, - roster: List, - active: CompliancePostureRevision, - scope: ProviderUseScope

, - offer: FabricIdentity, - decision_receipt: DeclarationRef, -) -> ProviderUseAdmission

{ - admit_provider_use( - roster: roster, - facts: facts, - active: active, - scope: scope, - offer: offer, - decision_receipt: decision_receipt, - ) -} diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag index 040e8c386a7..c391ccab6c6 100644 --- a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -16,11 +16,11 @@ import product.fabric.provider_admission { PostureRevisionStale, CustomerScopeUnsupported, DataHandlingUnsupported, RequiredAgreementAuthorityAbsent, ProhibitedUseNotCleared, SanctionsNotCleared, ExportNotCleared, DispositionCleared, + admit_provider_use, } import product.supplier.cloudflare_r2 { cloudflare_r2_route, cloudflare_r2_durable_origin_route_standing, - cloudflare_r2_route_admission, cloudflare_r2_route_facts_population, cloudflare_r2_data_paths, cloudflare_r2_facts, @@ -126,9 +126,9 @@ fn t_offer() -> FabricIdentity { } fn t_decide(route: ProviderRoute, facts: ProviderRouteFacts) -> ProviderUseAdmission { - cloudflare_r2_route_admission( - facts: facts, + admit_provider_use( roster: t_roster(route: route), + facts: facts, active: t_posture(), scope: t_scope(), offer: t_offer(), From 054aafe2a6f1d34258d05b6497218e35b6f67cf4 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 03:05:39 +0000 Subject: [PATCH 09/25] Attach the leftover annotation to the facts population. Deleting the admission alias left a leading // block with no following declaration. claim_batch does not check attachment; required-ci parse does. Co-authored-by: Cursor --- dag/gunbc/product/supplier/cloudflare_r2.dag | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag index b8b5ef85220..f5f86383f71 100644 --- a/dag/gunbc/product/supplier/cloudflare_r2.dag +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -152,13 +152,6 @@ fn cloudflare_r2_facts(route: ProviderRoute) -> ProviderRouteFacts { } } -fn cloudflare_r2_route_facts_population() -> List { - match cloudflare_r2_durable_origin_route_standing() { - CloudflareR2RouteRegionUnobserved { obligation } => [], - CloudflareR2RouteObserved { route } => [cloudflare_r2_facts(route: route)], - } -} - // THIS MODULE DECLARES NO SANCTION ROSTER AND NO POSTURE REVISION. Nobody has stated that we are // willing to place work on this vendor's default-jurisdiction R2 under a named posture. Writing a // roster row here to make the module look complete would be the fabricated authority the gate exists @@ -171,3 +164,9 @@ fn cloudflare_r2_route_facts_population() -> List { // been read and cleared. TRIGGER: that producer, SUFFICIENT FOR this route to be included or // omitted by matching these facts rather than by a dashboard label. Until then the executing // consumer is the witness. +fn cloudflare_r2_route_facts_population() -> List { + match cloudflare_r2_durable_origin_route_standing() { + CloudflareR2RouteRegionUnobserved { obligation } => [], + CloudflareR2RouteObserved { route } => [cloudflare_r2_facts(route: route)], + } +} From 3adfe52c16336c0378161b1f4ee8895dd5639f60 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 03:54:45 +0000 Subject: [PATCH 10/25] Assert the first production-facts refusal: unread downstream. admit_provider_use concatenates downstream before path obligations, so cloudflare_r2_facts refuse as DownstreamProviderUnassessed, not as an execution-path incomplete. The unread-path discriminator is unchanged. Co-authored-by: Cursor --- dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag index c391ccab6c6..dfeb02d850d 100644 --- a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -317,8 +317,8 @@ test fn production_unread_paths_on_a_read_region_route_still_refuse() -> Bool { CloudflareR2RouteRegionUnobserved { obligation } => false, CloudflareR2RouteObserved { route } => t_denied_with( a: t_decide(route: route, facts: cloudflare_r2_facts(route: route)), - tag: "facts-incomplete", - located: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_execution_location_obligation"), + tag: "downstream-unassessed", + located: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_downstream_obligation"), ), } } From d31a9105ccd11debf4f516e2ae9f9644c0fde7c8 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 04:24:11 +0000 Subject: [PATCH 11/25] Drop the vacuous, subsumed, and misnamed witness assertions. Empty-population filtering cannot go red once the population is empty. Nine Unread paths already entail zero Absent. Wire spellings of R2Jurisdiction do not prove Default is not a residency restriction. Co-authored-by: Cursor --- .../cloudflare_r2_route_witness_test.dag | 44 ++----------------- 1 file changed, 3 insertions(+), 41 deletions(-) diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag index dfeb02d850d..6249c6d4582 100644 --- a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -29,13 +29,6 @@ import product.supplier.cloudflare_r2 { CloudflareR2RouteObserved, CloudflareR2RouteRegionUnobserved, } -import extdeps.cloudflare.r2 { - r2_jurisdiction_wire, - R2JurisdictionDefault, - R2JurisdictionEu, - R2JurisdictionFedramp, - R2JurisdictionUs, -} data r2_witness_customer_profile: NonEmptyStr = "r2-witness-customer-profile" data r2_witness_data_handling_profile: NonEmptyStr = "r2-witness-data-handling-profile" @@ -175,7 +168,7 @@ fn t_denied_with(a: ProviderUseAdmission, tag: String, located: Dec } } -test fn the_durable_origin_region_is_unread() -> Bool { +test fn the_durable_origin_has_no_admissible_facts() -> Bool { match cloudflare_r2_durable_origin_route_standing() { CloudflareR2RouteObserved { route } => false, CloudflareR2RouteRegionUnobserved { obligation } => declaration_ref_eq( @@ -184,7 +177,8 @@ test fn the_durable_origin_region_is_unread() -> Bool { module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_region_unread_obligation", ), - ), + ) + && count(cloudflare_r2_route_facts_population()) == 0, } } @@ -202,19 +196,6 @@ test fn the_durable_storage_path_is_unread_with_the_location_obligation() -> Boo } } -test fn no_production_path_is_absent() -> Bool { - let c = cloudflare_r2_data_paths() - let paths = [ - c.execution, c.durable_storage, c.backups, c.logs, c.telemetry, - c.control_plane, c.support_access, c.administrative_access, c.spill, - ] - count(filter(paths, p => match p { - ProviderPathAbsent { evidence } => true, - ProviderPathLocated { operator, jurisdiction, evidence } => false, - ProviderPathUnread { obligation } => false, - })) == 0 -} - test fn every_production_path_is_unread() -> Bool { let c = cloudflare_r2_data_paths() let paths = [ @@ -259,18 +240,6 @@ fn t_facts_with_durable_storage(route: ProviderRoute, storage: ProviderPathStand } } -test fn resolving_every_data_path_does_not_admit_the_durable_origin() -> Bool { - match cloudflare_r2_durable_origin_route_standing() { - CloudflareR2RouteObserved { route } => false, - CloudflareR2RouteRegionUnobserved { obligation } => - count(cloudflare_r2_route_facts_population()) == 0 - && count(filter(cloudflare_r2_route_facts_population(), f => match t_decide(route: f.route, facts: f) { - ProviderUseAdmitted { permit } => true, - ProviderUseDenied { decision, cause } => false, - })) == 0, - } -} - test fn one_unread_durable_storage_path_refuses_with_that_paths_obligation() -> Bool { match cloudflare_r2_route(region: t_read_region()) { CloudflareR2RouteRegionUnobserved { obligation } => false, @@ -322,10 +291,3 @@ test fn production_unread_paths_on_a_read_region_route_still_refuse() -> Bool { ), } } - -test fn default_jurisdiction_wire_is_not_a_restriction() -> Bool { - (r2_jurisdiction_wire(jurisdiction: R2JurisdictionDefault) as String) == "default" - && (r2_jurisdiction_wire(jurisdiction: R2JurisdictionEu) as String) == "eu" - && (r2_jurisdiction_wire(jurisdiction: R2JurisdictionUs) as String) == "us" - && (r2_jurisdiction_wire(jurisdiction: R2JurisdictionFedramp) as String) == "fedramp" -} From f3cd7cc10d57c0358ff78a4da4e01cbd485ea0c1 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 04:49:02 +0000 Subject: [PATCH 12/25] Cite R2S3Endpoint as the route service, not the location docs. ProviderRoute.service is product identity. The data-location page is a reading about placement; it already lives in path obligations and must not be a second name for the R2 service. Co-authored-by: Cursor --- dag/gunbc/product/supplier/cloudflare_r2.dag | 2 +- dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag index f5f86383f71..33e3e27f722 100644 --- a/dag/gunbc/product/supplier/cloudflare_r2.dag +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -45,7 +45,7 @@ fn cloudflare_r2_provider_ref() -> DeclarationRef { } fn cloudflare_r2_service_ref() -> DeclarationRef { - decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "extdeps_external_authority_anchor") + decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "R2S3Endpoint") } type CloudflareR2RegionObservation diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag index 6249c6d4582..9cedaa6c2a2 100644 --- a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -269,6 +269,10 @@ test fn a_read_region_route_admits_once_that_path_is_resolved() -> Bool { a: permit.route.provider, b: decl_ref(module_path: "extdeps.vendor.cloudflare", decl_name: "cloudflare"), ) + && declaration_ref_eq( + a: permit.route.service, + b: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "R2S3Endpoint"), + ) && declaration_ref_eq( a: permit.route.region, b: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_synthetic_region"), From f90ed290fa686647cc6f5bbc616fdb5e818b75df Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 06:57:20 +0000 Subject: [PATCH 13/25] Keep reported location, requested hint, and residency as three facts. Get Bucket location is not Create Bucket locationHint. Transcription rows carry only Cloudflare's words; the subprocessors coverage gap is a labelled reader finding. Path resolution now requires operator and jurisdiction both. Annotations describe RegionUnobserved production, not a pre-repair route. Co-authored-by: Cursor --- dag/extdeps/cloudflare/r2_data_location.dag | 48 +++++++++++-- dag/gunbc/product/supplier/cloudflare_r2.dag | 73 +++++++++----------- 2 files changed, 75 insertions(+), 46 deletions(-) diff --git a/dag/extdeps/cloudflare/r2_data_location.dag b/dag/extdeps/cloudflare/r2_data_location.dag index b5a4ebb48b3..a7aa346c322 100644 --- a/dag/extdeps/cloudflare/r2_data_location.dag +++ b/dag/extdeps/cloudflare/r2_data_location.dag @@ -41,6 +41,20 @@ data cloudflare_customer_dpa_authority: ExternalAuthority = ExternalAuthority { } } +data r2_create_bucket_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "developers.cloudflare.com/api/resources/r2/subresources/buckets/methods/create" + } +} + +data r2_get_bucket_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "developers.cloudflare.com/api/resources/r2/subresources/buckets/methods/get" + } +} + data extdeps_model_scope: ExternalModelScope = ExternalModelScope { subject: ExternalSubjectRef { declaration: DeclarationRef { @@ -55,6 +69,8 @@ data extdeps_model_scope: ExternalModelScope = ExternalModelScope { r2_us_jurisdiction_changelog_authority, cloudflare_subprocessors_authority, cloudflare_customer_dpa_authority, + r2_create_bucket_authority, + r2_get_bucket_authority, ] } @@ -99,9 +115,25 @@ data r2_tokens_default_jurisdiction_reading: CloudflarePublishedReading = Cloudf data cloudflare_subprocessors_reading: CloudflarePublishedReading = CloudflarePublishedReading { authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_subprocessors_authority"), read_on: "2026-09-12", - statement: "Last Updated: October 1, 2025. Cloudflare uses a handful of sub-processors to support the Cloudflare service. Some of these sub-processors are members of the Cloudflare Group (Cloudflare, Inc. and its subsidiaries) and some are third parties. Third-party entities include Slack Technologies, Inc. (Customer support communications, United States); Zendesk, Inc. (Customer support and account management, United States, the European Economic Area, Japan, and Australia); Salesforce, Inc. (Customer support and account management, United States); Google LLC (Cloudflare Developer Platform, Cloudflare Zero Trust and AI Gateway; European Economic Area, United States, Australia, India); Oracle America, Inc. (Cloudflare Developer Platform and Cache Reserve; United States, European Economic Area, UK, Japan, Australia, Canada, Singapore); Amazon Web Services (Cloudflare Email Security; United States, European Economic Area); CoreWeave, Inc., Nebius BV (Workers AI); Anthropic PBC, OpenAI, Inc., X.AI Corp., Groq, Inc. (AI Gateway). The page lists Cloudflare Group subsidiaries by location and does not key any row to a named R2 bucket or to the default jurisdiction.", + statement: "Last Updated: October 1, 2025. Cloudflare uses a handful of sub-processors to support the Cloudflare service. Some of these sub-processors are members of the Cloudflare Group (Cloudflare, Inc. and its subsidiaries) and some are third parties. Third-party entities include Slack Technologies, Inc. (Customer support communications, United States); Zendesk, Inc. (Customer support and account management, United States, the European Economic Area, Japan, and Australia); Salesforce, Inc. (Customer support and account management, United States); Google LLC (Cloudflare Developer Platform, Cloudflare Zero Trust and AI Gateway; European Economic Area, United States, Australia, India); Oracle America, Inc. (Cloudflare Developer Platform and Cache Reserve; United States, European Economic Area, UK, Japan, Australia, Canada, Singapore); Amazon Web Services (Cloudflare Email Security; United States, European Economic Area); CoreWeave, Inc., Nebius BV (Workers AI); Anthropic PBC, OpenAI, Inc., X.AI Corp., Groq, Inc. (AI Gateway). The page lists Cloudflare Group subsidiaries by location.", +} + +data r2_create_bucket_location_hint_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "r2_create_bucket_authority"), + read_on: "2026-09-13", + statement: "Create Bucket POST /accounts/{account_id}/r2/buckets. Body parameter locationHint, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Header cf-r2-jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13.", } +data r2_get_bucket_location_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "r2_get_bucket_authority"), + read_on: "2026-09-13", + statement: "Get Bucket GET /accounts/{account_id}/r2/buckets/{bucket_name}. Result field location, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Result field jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13.", +} + +// READER FINDING, not a Cloudflare sentence. CloudflarePublishedReading.statement carries only +// transcription. This row is the absence claim that the table does not cover a named bucket. +data cloudflare_subprocessors_not_keyed_to_this_bucket: NonEmptyStr = "READER FINDING, not a Cloudflare sentence: cloudflare_subprocessors_reading transcribes a company-wide activity table. That table is not keyed to a named R2 bucket or to the default jurisdiction. It does not cover gunbai-fabric-origin and it does not establish an empty downstream population." + data cloudflare_customer_dpa_reading: CloudflarePublishedReading = CloudflarePublishedReading { authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_customer_dpa_authority"), read_on: "2026-09-12", @@ -124,12 +156,14 @@ data cloudflare_customer_dpa_reading: CloudflarePublishedReading = CloudflarePub // r2_tokens_default_jurisdiction_reading; the fleet bucket's jurisdiction is // gunbc.cloudflare.r2_origin fabric_durable_origin_standing. -// AUTOMATIC IS A CHOICE MECHANISM, AND THAT IS WHAT THIS ROW RECORDS. It is the region a route -// cites when a bucket was created without a jurisdictional restriction: not a country, not a -// data-center park, and not a residency commitment. Treating R2JurisdictionDefault, a dashboard -// Location label, or a Location Hint as the place the bytes live is the reading this row exists -// to make unusable as a location fact. Automatic is not an arm of R2Jurisdiction — that type's -// corresponding non-guarantee is R2JurisdictionDefault, owned by extdeps.cloudflare.r2. +// AUTOMATIC IS A CHOICE MECHANISM, AND THAT IS WHAT THIS ROW RECORDS. It is not a country, not a +// data-center park, not a residency commitment, and not a value of ProviderRoute.region. product.supplier.cloudflare_r2 +// mints a ProviderRoute only in the read arm; Automatic is excluded from that slot. Treating +// R2JurisdictionDefault, a dashboard Location label, Create Bucket locationHint, or Get Bucket +// location as interchangeable is the section 3 fork this row exists to keep unusable: requested +// placement, reported location, and residency guarantee are three facts. Automatic is not an arm +// of R2Jurisdiction — that type's corresponding non-guarantee is R2JurisdictionDefault, owned by +// extdeps.cloudflare.r2. type R2PlacementModeRow { reading: CloudflarePublishedReading } diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag index 33e3e27f722..e1c50bdd136 100644 --- a/dag/gunbc/product/supplier/cloudflare_r2.dag +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -9,36 +9,31 @@ import product.fabric.provider_route { DownstreamProviderPopulation, DownstreamProvidersUnread, } -// THE DURABLE-ORIGIN ROUTE THIS REPOSITORY ANSWERS THE NINE-PATH CLOSURE FOR, AND THE ROW REFUSES. +// THE DURABLE-ORIGIN THIS REPOSITORY ANSWERS THE NINE-PATH CLOSURE FOR. PRODUCTION DOES NOT MINT A ROUTE. // // WHAT WAS READ. Cloudflare's R2 data-location page, how-R2-works page, us-jurisdiction changelog, -// tokens page, subprocessors list and Customer DPA v6.4 were read on 2026-09-12 and transcribed -// in extdeps.cloudflare.r2_data_location. The durable origin in this fleet +// tokens page, subprocessors list, Customer DPA v6.4 (2026-09-12), and the Create Bucket / +// Get Bucket API method pages (2026-09-13) were transcribed in +// extdeps.cloudflare.r2_data_location. The durable origin in this fleet // (gunbc.cloudflare.r2_origin fabric_durable_origin_standing, bucket gunbai-fabric-origin) carries // R2JurisdictionDefault. That module already states that Default is not a data-residency -// commitment this fleet has made. The upstream reading confirms the same fact in Cloudflare's -// words: Automatic placement chooses a region from the caller's location at create time; Location -// Hints are a best effort and not a guarantee; only Jurisdictional Restrictions (eu, us, fedramp) -// guarantee objects are stored and processed within a jurisdiction. Default, on the tokens page, -// is the wire value for buckets not created in a specific jurisdiction. +// commitment this fleet has made. Create Bucket's locationHint is a requested placement; Get +// Bucket's location is a reported location; cf-r2-jurisdiction / Jurisdictional Restrictions are +// the residency guarantee. Those three are not one field. This repository has not queried +// gunbai-fabric-origin's Get Bucket location, so no reported-location observation is minted here. // -// WHAT WAS NOT FOUND, AND THEREFORE WHAT THIS MODULE MUST NOT MINT. No document read names the -// country, the region, or the storage cluster that holds objects in THIS bucket. A dashboard -// label, a default jurisdiction setting, and a hint are choices. Reaching for ProviderPathLocated -// to make a compliance posture able to include R2 would manufacture the fact the posture is -// supposed to rest on. ProviderPathAbsent is also not taken: nobody has stated that any of these -// nine paths do not exist. +// WHAT PRODUCTION EXECUTES. cloudflare_r2_durable_origin_route_standing is +// CloudflareR2RouteRegionUnobserved carrying cloudflare_r2_region_unread_obligation. +// cloudflare_r2_route_facts_population is therefore empty: there is no origin ProviderRoute, so +// there is no origin row for admit_provider_use. The nine-path closure and downstream population +// are still answered (every path Unread; Absent taken zero times). The admit_provider_use pair +// lives only in the witness, over a route minted in the CloudflareR2RegionRead arm of the same +// coproduct — a synthetic observed region, not this origin. // -// THE REGION SLOT IS NOT A PLACE TO RECORD THAT FINDING. product.fabric.provider_route says the +// THE REGION SLOT IS NOT A PLACE TO RECORD AUTOMATIC. product.fabric.provider_route says the // cited region is where the work actually runs, observed at a declared boundary and never -// fabricated. extdeps.cloudflare.r2_data_location r2_placement_automatic is a CHOICE MECHANISM, -// and putting it in ProviderRoute.region would make Automatic an admitted location the moment a -// roster row and a resolved path closure exist -- which is validation standing where construction -// was available (DESIGN section 5). product.supplier.ubicloud already ruled that shape out: -// a ProviderRoute is minted ONLY from a read region. Automatic stays in the location module as -// the reading of the choice; it does not occupy this slot. -// -// BOTH THE REFUSING PRODUCTION STANDING AND THE DISCRIMINATING PAIR ARE THE DELIVERABLE. +// fabricated. r2_placement_automatic is a CHOICE MECHANISM. product.supplier.ubicloud already +// ruled that shape out: a ProviderRoute is minted ONLY from a read region. fn cloudflare_r2_provider_ref() -> DeclarationRef { decl_ref(module_path: "extdeps.vendor.cloudflare", decl_name: "cloudflare") @@ -56,7 +51,7 @@ type CloudflareR2RouteStanding = CloudflareR2RouteObserved { route: ProviderRoute } | CloudflareR2RouteRegionUnobserved { obligation: DeclarationRef } -data cloudflare_r2_region_unread_obligation: NonEmptyStr = "Where this fleet's durable origin actually runs is UNREAD. gunbc.cloudflare.r2_origin fabric_durable_origin_standing places bucket gunbai-fabric-origin under R2JurisdictionDefault. extdeps.cloudflare.r2_data_location r2_data_location_reading states that Automatic placement chooses a region from the caller's location at create time and that Location Hints are a best effort, not a guarantee. Automatic is therefore a CHOICE, not a location, and it is not a value of ProviderRoute.region. RESOLVED BY a Cloudflare statement that names the jurisdiction or operating region of gunbai-fabric-origin the way Jurisdictional Restrictions do, or by recreating the origin under such a restriction -- at which point this standing takes CloudflareR2RegionRead with that named location as region. It is NOT resolved by citing r2_placement_automatic, R2JurisdictionDefault, a dashboard Location label, or a Location Hint." +data cloudflare_r2_region_unread_obligation: NonEmptyStr = "Where this fleet's durable origin actually runs is UNREAD. gunbc.cloudflare.r2_origin fabric_durable_origin_standing places bucket gunbai-fabric-origin under R2JurisdictionDefault. Create Bucket locationHint (r2_create_bucket_location_hint_reading, read 2026-09-13) is a requested placement. Get Bucket location (r2_get_bucket_location_reading, read 2026-09-13) is a reported location. Those are two upstream fields that share location tokens; collapsing them is a section 3 meaning-fork. This repository has not queried gunbai-fabric-origin, so no Get Bucket location is an observation of ours. Automatic and R2JurisdictionDefault are not values of ProviderRoute.region. RESOLVED BY a Get Bucket (or equivalent) observation of this bucket's location field sufficient to name the operating region, or by recreating the origin under a Jurisdictional Restriction that names a jurisdiction — at which point this standing takes CloudflareR2RegionRead with that named location as region. A reported location is not a residency guarantee and is not the nine-path closure. It is NOT resolved by citing r2_placement_automatic, R2JurisdictionDefault, a dashboard Location label, or Create Bucket locationHint." fn cloudflare_r2_durable_origin_region() -> CloudflareR2RegionObservation { CloudflareR2RegionUnread { @@ -83,25 +78,25 @@ fn cloudflare_r2_durable_origin_route_standing() -> CloudflareR2RouteStanding { cloudflare_r2_route(region: cloudflare_r2_durable_origin_region()) } -data cloudflare_r2_execution_location_obligation: NonEmptyStr = "Where R2 executes object operations for a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2_data_location r2_how_r2_works_reading states that the R2 Gateway is deployed across Cloudflare's global network via Cloudflare Workers, close to the user, and that the Gateway then writes to a storage cluster within the location set for the bucket. That is an architecture of a CHOICE, not a location of this fleet's bucket. RESOLVED BY a Cloudflare statement naming the jurisdiction or operating entity of request handling for a named default-jurisdiction bucket -- at which point this path takes Located with that entity as operator. It is NOT resolved by R2JurisdictionDefault, by Automatic placement, or by a Location Hint." +data cloudflare_r2_execution_location_obligation: NonEmptyStr = "Where R2 executes object operations for a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2_data_location r2_how_r2_works_reading states that the R2 Gateway is deployed across Cloudflare's global network via Cloudflare Workers, close to the user, and that the Gateway then writes to a storage cluster within the location set for the bucket. That is an architecture of a CHOICE, not a location of this fleet's bucket. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — a Cloudflare statement that names who handles requests for a named default-jurisdiction bucket and the jurisdiction of that handling. Naming an operating entity without a jurisdiction, or a jurisdiction without an operator, does not close this path. It is NOT resolved by R2JurisdictionDefault, by Automatic placement, by Create Bucket locationHint, or by an unqueried Get Bucket location." -data cloudflare_r2_durable_storage_location_obligation: NonEmptyStr = "Where objects in this fleet's durable origin are stored is UNREAD, and that is a read of Cloudflare's own location rules rather than a missing document. gunbc.cloudflare.r2_origin fabric_durable_origin_standing places bucket gunbai-fabric-origin under R2JurisdictionDefault. extdeps.cloudflare.r2_data_location r2_data_location_reading (URI developers.cloudflare.com/r2/reference/data-location, read 2026-09-12) states that a new bucket's data location is Automatic by default, which chooses a bucket location in the closest available region to the create bucket request based on the location of the caller; that Location Hints are a best effort and not a guarantee; and that Jurisdictional Restrictions (eu, us, fedramp) are what guarantee objects are stored and processed within a jurisdiction. r2_tokens_default_jurisdiction_reading states that for buckets not created in a specific jurisdiction the wire value is default. THIS PATH IS THEREFORE A CHOICE, NOT A LOCATION. RESOLVED BY recreating the origin under a Jurisdictional Restriction that names a jurisdiction, or by a Cloudflare statement that objects in gunbai-fabric-origin are stored and processed within a named jurisdiction the way Jurisdictional Restrictions do. It is NOT resolved by reading the API location field (wnam/enam/weur/eeur/apac/oc), which upstream lists as a hint, nor by treating R2JurisdictionDefault as residency." +data cloudflare_r2_durable_storage_location_obligation: NonEmptyStr = "Where objects in this fleet's durable origin are stored is UNREAD. gunbc.cloudflare.r2_origin fabric_durable_origin_standing places bucket gunbai-fabric-origin under R2JurisdictionDefault. Requested placement, reported location, and residency guarantee are three facts: Create Bucket locationHint (r2_create_bucket_location_hint_reading) is requested placement; Get Bucket location (r2_get_bucket_location_reading) is reported location; Jurisdictional Restrictions / the Get Bucket jurisdiction field are the guarantee that objects are stored and processed within a jurisdiction. This repository has not queried gunbai-fabric-origin, so no Get Bucket location is an observation of ours. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — recreating the origin under a Jurisdictional Restriction that names a jurisdiction, or a Cloudflare statement that objects in gunbai-fabric-origin are stored and processed within a named jurisdiction by a named operator. A reported location is not that guarantee and is not the nine-path closure. It is NOT resolved by Create Bucket locationHint, by treating Get Bucket location as a hint, or by treating R2JurisdictionDefault as residency." -data cloudflare_r2_backups_location_obligation: NonEmptyStr = "Where R2 replicates objects for durability on a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2_data_location r2_how_r2_works_reading states that encrypted data is replicated within the region (e.g. ENAM) for durability, and it names no region for a default-jurisdiction bucket and no country for that replication. RESOLVED BY a Cloudflare statement of the region or jurisdiction inside which objects of a named default-jurisdiction bucket are replicated. It is NOT resolved by the example token ENAM in that sentence." +data cloudflare_r2_backups_location_obligation: NonEmptyStr = "Where R2 replicates objects for durability on a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2_data_location r2_how_r2_works_reading states that encrypted data is replicated within the region (e.g. ENAM) for durability, and it names no region for a default-jurisdiction bucket and no country for that replication. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — a Cloudflare statement of the operator and the region or jurisdiction inside which objects of a named default-jurisdiction bucket are replicated. It is NOT resolved by the example token ENAM in that sentence." -data cloudflare_r2_logs_location_obligation: NonEmptyStr = "Where R2 or the Cloudflare platform stores logs of access to a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2_data_location r2_data_location_reading states that Logpush does not interact with R2 resources with assigned jurisdictions, which is a fact about jurisdictional buckets and does not say where logs of a default-jurisdiction bucket go, nor that no such logs exist. THE ABSENT ARM IS DELIBERATELY NOT TAKEN. RESOLVED BY a Cloudflare statement about logging of R2 object access, in either direction: an explicit none makes this path Absent with that document as evidence, and a described store makes it Located at whoever receives it." +data cloudflare_r2_logs_location_obligation: NonEmptyStr = "Where R2 or the Cloudflare platform stores logs of access to a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2_data_location r2_data_location_reading states that Logpush does not interact with R2 resources with assigned jurisdictions, which is a fact about jurisdictional buckets and does not say where logs of a default-jurisdiction bucket go, nor that no such logs exist. THE ABSENT ARM IS DELIBERATELY NOT TAKEN. RESOLVED BY a Cloudflare statement about logging of R2 object access, in either direction: an explicit none makes this path Absent with that document as evidence, and a described store makes it Located with evidence sufficient for OPERATOR AND JURISDICTION both." -data cloudflare_r2_telemetry_location_obligation: NonEmptyStr = "Whether Cloudflare collects telemetry about a default-jurisdiction R2 bucket, what it carries, and where it goes, is UNREAD. Nothing in the documents read on 2026-09-12 describes a telemetry or usage-reporting path for R2 object storage as a located destination. THE ABSENT ARM IS DELIBERATELY NOT TAKEN: silence is not a denial. RESOLVED BY a Cloudflare statement about R2 telemetry, in either direction." +data cloudflare_r2_telemetry_location_obligation: NonEmptyStr = "Whether Cloudflare collects telemetry about a default-jurisdiction R2 bucket, what it carries, and where it goes, is UNREAD. Nothing in the documents read on 2026-09-12 describes a telemetry or usage-reporting path for R2 object storage as a located destination. THE ABSENT ARM IS DELIBERATELY NOT TAKEN: silence is not a denial. RESOLVED BY a Cloudflare statement about R2 telemetry, in either direction, sufficient for OPERATOR AND JURISDICTION both when the arm is Located." -data cloudflare_r2_control_plane_location_obligation: NonEmptyStr = "Where the R2 control plane -- the Dashboard, the S3 API, the REST API that powers Wrangler, and the Metadata Service -- runs for a default-jurisdiction bucket, and under whose jurisdiction, is UNREAD. r2_how_r2_works_reading places the Gateway on the global network and the Metadata Service on Durable Objects and names no country for either. RESOLVED BY a Cloudflare document naming the location or the operating entity of those control-plane components for a given bucket jurisdiction." +data cloudflare_r2_control_plane_location_obligation: NonEmptyStr = "Where the R2 control plane -- the Dashboard, the S3 API, the REST API that powers Wrangler, and the Metadata Service -- runs for a default-jurisdiction bucket, and under whose jurisdiction, is UNREAD. r2_how_r2_works_reading places the Gateway on the global network and the Metadata Service on Durable Objects and names no country for either. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both. Naming an operating entity without a jurisdiction, or a jurisdiction without an operator, does not close this path." -data cloudflare_r2_support_access_obligation: NonEmptyStr = "From which jurisdiction Cloudflare support reaches a default-jurisdiction R2 bucket is UNREAD. extdeps.cloudflare.r2_data_location cloudflare_subprocessors_reading names Slack, Zendesk and Salesforce for customer support, with locations that include the United States and, for Zendesk, also the EEA, Japan and Australia. That is a company-wide support-tool list, not a statement that support access to THIS bucket's objects is exercised from those places or that it is not. RESOLVED BY a Cloudflare statement of where support access to a given R2 bucket's objects is exercised from." +data cloudflare_r2_support_access_obligation: NonEmptyStr = "From which jurisdiction Cloudflare support reaches a default-jurisdiction R2 bucket is UNREAD. extdeps.cloudflare.r2_data_location cloudflare_subprocessors_reading names Slack, Zendesk and Salesforce for customer support, with locations that include the United States and, for Zendesk, also the EEA, Japan and Australia. That is a company-wide support-tool list, not a statement that support access to THIS bucket's objects is exercised from those places or that it is not. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — a Cloudflare statement of where support access to a given R2 bucket's objects is exercised from and by whom." -data cloudflare_r2_administrative_access_obligation: NonEmptyStr = "From which jurisdiction administrative access to a default-jurisdiction R2 bucket is exercised is UNREAD. The subprocessors page states that Cloudflare Group companies may be sub-processors because employees of those affiliates may need to provide account and engineering support, and it lists subsidiaries in the United Kingdom, Singapore, Australia, Germany, Portugal, France, Japan, Canada, the Netherlands, the U.A.E., India, the United States, South Korea, Mexico, Malaysia, Sweden and Switzerland. That names WHO may provide support, not FROM WHERE administrative access to this bucket is exercised, and it does not locate this bucket. RESOLVED BY a Cloudflare statement of where administrative access to a named default-jurisdiction R2 bucket is exercised from." +data cloudflare_r2_administrative_access_obligation: NonEmptyStr = "From which jurisdiction administrative access to a default-jurisdiction R2 bucket is exercised is UNREAD. The subprocessors page states that Cloudflare Group companies may be sub-processors because employees of those affiliates may need to provide account and engineering support, and it lists subsidiaries in the United Kingdom, Singapore, Australia, Germany, Portugal, France, Japan, Canada, the Netherlands, the U.A.E., India, the United States, South Korea, Mexico, Malaysia, Sweden and Switzerland. That names WHO may provide support, not FROM WHERE administrative access to this bucket is exercised, and it does not locate this bucket. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both." -data cloudflare_r2_spill_location_obligation: NonEmptyStr = "Where customer material may SPILL on an R2 default-jurisdiction route -- caches, diagnostic captures, undeleted replicas, Local Uploads, tiered read cache -- is UNREAD. r2_how_r2_works_reading describes a Tiered Read Cache and Local Uploads and names no country for either, and it does not say that no other spill surface exists. THE ABSENT ARM IS DELIBERATELY NOT TAKEN. RESOLVED BY a Cloudflare statement about host-side or cache-side copies of R2 object bytes for default-jurisdiction buckets, which may resolve this path in either direction." +data cloudflare_r2_spill_location_obligation: NonEmptyStr = "Where customer material may SPILL on an R2 default-jurisdiction route -- caches, diagnostic captures, undeleted replicas, Local Uploads, tiered read cache -- is UNREAD. r2_how_r2_works_reading describes a Tiered Read Cache and Local Uploads and names no country for either, and it does not say that no other spill surface exists. THE ABSENT ARM IS DELIBERATELY NOT TAKEN. RESOLVED BY a Cloudflare statement about host-side or cache-side copies of R2 object bytes for default-jurisdiction buckets, which may resolve this path in either direction, with Located requiring OPERATOR AND JURISDICTION both." -data cloudflare_r2_downstream_obligation: NonEmptyStr = "Which parties process objects stored in a default-jurisdiction R2 bucket on Cloudflare's behalf is UNREAD. The Customer DPA v6.4 (read 2026-09-12) authorizes Cloudflare Group members and third-party data center operators as sub-Processors, and the subprocessors list (last updated October 1, 2025, read 2026-09-12) enumerates tools and platforms by activity, including Google LLC and Oracle America, Inc. for the Cloudflare Developer Platform. THAT LIST IS NOT KEYED TO A NAMED R2 BUCKET OR TO THE DEFAULT JURISDICTION, so enumerating it as this route's downstream population would claim coverage the table does not give, and reporting none would claim the negative the table also does not give. RESOLVED BY a Cloudflare statement that names which subprocessors process objects in a named default-jurisdiction R2 bucket -- at which point this population takes Enumerated with that document as coverage -- or an explicit none for that bucket, which takes NoDownstreamProviders with that document as evidence." +data cloudflare_r2_downstream_obligation: NonEmptyStr = "Which parties process objects stored in a default-jurisdiction R2 bucket on Cloudflare's behalf is UNREAD. The Customer DPA v6.4 (read 2026-09-12) authorizes Cloudflare Group members and third-party data center operators as sub-Processors, and cloudflare_subprocessors_reading transcribes the company-wide table. The coverage gap is cloudflare_subprocessors_not_keyed_to_this_bucket (READER FINDING): that table is not keyed to a named R2 bucket or to the default jurisdiction. Enumerating it as this route's downstream population would claim coverage the table does not give, and reporting none would claim the negative the table also does not give. RESOLVED BY a Cloudflare statement that names which subprocessors process objects in a named default-jurisdiction R2 bucket -- at which point this population takes Enumerated with that document as coverage -- or an explicit none for that bucket, which takes NoDownstreamProviders with that document as evidence." fn cloudflare_r2_data_paths() -> ProviderDataPathClosure { ProviderDataPathClosure { @@ -155,15 +150,15 @@ fn cloudflare_r2_facts(route: ProviderRoute) -> ProviderRouteFacts { // THIS MODULE DECLARES NO SANCTION ROSTER AND NO POSTURE REVISION. Nobody has stated that we are // willing to place work on this vendor's default-jurisdiction R2 under a named posture. Writing a // roster row here to make the module look complete would be the fabricated authority the gate exists -// to close. The module supplies only the route facts. Callers that need a permit call -// product.fabric.provider_admission admit_provider_use with those facts; there is no wrapper here -// because a wrapper with nothing of its own to bind would be a second name for that fold. +// to close. Production standing is CloudflareR2RouteRegionUnobserved; this function projects that +// standing to an empty facts list. admit_provider_use is not invoked here. The witness mints a +// synthetic CloudflareR2RegionRead route and calls admit_provider_use on that pair. // // DECLARED FRONTIER (DESIGN section 3c). The production consumer is a posture producer that mints a // CompliancePostureRevision whose permitted_jurisdictions enumerate only routes whose facts have -// been read and cleared. TRIGGER: that producer, SUFFICIENT FOR this route to be included or +// been read and cleared. TRIGGER: that producer, SUFFICIENT FOR this origin to be included or // omitted by matching these facts rather than by a dashboard label. Until then the executing -// consumer is the witness. +// consumer of the admission pair is the witness. fn cloudflare_r2_route_facts_population() -> List { match cloudflare_r2_durable_origin_route_standing() { CloudflareR2RouteRegionUnobserved { obligation } => [], From a91fa043e8fadefb489a5debe16a43f87f050c6d Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 07:24:35 +0000 Subject: [PATCH 14/25] Keep the subprocessors coverage gap in the product obligation. The unkeyed-table finding is a fleet observation of gunbai-fabric-origin, not an upstream fact. It does not belong in extdeps. Co-authored-by: Cursor --- dag/extdeps/cloudflare/r2_data_location.dag | 4 ---- dag/gunbc/product/supplier/cloudflare_r2.dag | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/dag/extdeps/cloudflare/r2_data_location.dag b/dag/extdeps/cloudflare/r2_data_location.dag index a7aa346c322..f0652d5f745 100644 --- a/dag/extdeps/cloudflare/r2_data_location.dag +++ b/dag/extdeps/cloudflare/r2_data_location.dag @@ -130,10 +130,6 @@ data r2_get_bucket_location_reading: CloudflarePublishedReading = CloudflarePubl statement: "Get Bucket GET /accounts/{account_id}/r2/buckets/{bucket_name}. Result field location, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Result field jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13.", } -// READER FINDING, not a Cloudflare sentence. CloudflarePublishedReading.statement carries only -// transcription. This row is the absence claim that the table does not cover a named bucket. -data cloudflare_subprocessors_not_keyed_to_this_bucket: NonEmptyStr = "READER FINDING, not a Cloudflare sentence: cloudflare_subprocessors_reading transcribes a company-wide activity table. That table is not keyed to a named R2 bucket or to the default jurisdiction. It does not cover gunbai-fabric-origin and it does not establish an empty downstream population." - data cloudflare_customer_dpa_reading: CloudflarePublishedReading = CloudflarePublishedReading { authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_customer_dpa_authority"), read_on: "2026-09-12", diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag index e1c50bdd136..86451d8b721 100644 --- a/dag/gunbc/product/supplier/cloudflare_r2.dag +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -96,7 +96,7 @@ data cloudflare_r2_administrative_access_obligation: NonEmptyStr = "From which j data cloudflare_r2_spill_location_obligation: NonEmptyStr = "Where customer material may SPILL on an R2 default-jurisdiction route -- caches, diagnostic captures, undeleted replicas, Local Uploads, tiered read cache -- is UNREAD. r2_how_r2_works_reading describes a Tiered Read Cache and Local Uploads and names no country for either, and it does not say that no other spill surface exists. THE ABSENT ARM IS DELIBERATELY NOT TAKEN. RESOLVED BY a Cloudflare statement about host-side or cache-side copies of R2 object bytes for default-jurisdiction buckets, which may resolve this path in either direction, with Located requiring OPERATOR AND JURISDICTION both." -data cloudflare_r2_downstream_obligation: NonEmptyStr = "Which parties process objects stored in a default-jurisdiction R2 bucket on Cloudflare's behalf is UNREAD. The Customer DPA v6.4 (read 2026-09-12) authorizes Cloudflare Group members and third-party data center operators as sub-Processors, and cloudflare_subprocessors_reading transcribes the company-wide table. The coverage gap is cloudflare_subprocessors_not_keyed_to_this_bucket (READER FINDING): that table is not keyed to a named R2 bucket or to the default jurisdiction. Enumerating it as this route's downstream population would claim coverage the table does not give, and reporting none would claim the negative the table also does not give. RESOLVED BY a Cloudflare statement that names which subprocessors process objects in a named default-jurisdiction R2 bucket -- at which point this population takes Enumerated with that document as coverage -- or an explicit none for that bucket, which takes NoDownstreamProviders with that document as evidence." +data cloudflare_r2_downstream_obligation: NonEmptyStr = "Which parties process objects stored in a default-jurisdiction R2 bucket on Cloudflare's behalf is UNREAD. The Customer DPA v6.4 (read 2026-09-12) authorizes Cloudflare Group members and third-party data center operators as sub-Processors, and cloudflare_subprocessors_reading transcribes the company-wide table. READER FINDING, not a Cloudflare sentence: that table is not keyed to a named R2 bucket or to the default jurisdiction, so it does not cover gunbai-fabric-origin and it does not establish an empty downstream population. Enumerating it as this route's downstream population would claim coverage the table does not give, and reporting none would claim the negative the table also does not give. RESOLVED BY a Cloudflare statement that names which subprocessors process objects in a named default-jurisdiction R2 bucket -- at which point this population takes Enumerated with that document as coverage -- or an explicit none for that bucket, which takes NoDownstreamProviders with that document as evidence." fn cloudflare_r2_data_paths() -> ProviderDataPathClosure { ProviderDataPathClosure { From 6fb24f9af3ced7ec887cb1a5195f6aeb0b47e4f5 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 07:48:18 +0000 Subject: [PATCH 15/25] Annotate why operator or jurisdiction alone cannot close a location path. Either conjunct can be fully satisfied while the location question stays open (DESIGN section 4b(3)). Held locally for the #11194 integration push. Co-authored-by: Cursor --- dag/gunbc/product/supplier/cloudflare_r2.dag | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag index 86451d8b721..0c39316a0e6 100644 --- a/dag/gunbc/product/supplier/cloudflare_r2.dag +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -78,6 +78,12 @@ fn cloudflare_r2_durable_origin_route_standing() -> CloudflareR2RouteStanding { cloudflare_r2_route(region: cloudflare_r2_durable_origin_region()) } +// A LOCATION PATH IS CLOSED ONLY BY OPERATOR AND JURISDICTION TOGETHER (DESIGN section 4b(3)). +// Naming an operating entity leaves the jurisdiction unknown; naming a jurisdiction without who +// operates it leaves the operator unknown. Either conjunct can be fully satisfied while the +// question this obligation exists to close stays open — the same defect as a trigger retired by +// affordability alone when the real requirement was affordability AND a passing check. Either +// alone is therefore not a resolution. data cloudflare_r2_execution_location_obligation: NonEmptyStr = "Where R2 executes object operations for a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2_data_location r2_how_r2_works_reading states that the R2 Gateway is deployed across Cloudflare's global network via Cloudflare Workers, close to the user, and that the Gateway then writes to a storage cluster within the location set for the bucket. That is an architecture of a CHOICE, not a location of this fleet's bucket. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — a Cloudflare statement that names who handles requests for a named default-jurisdiction bucket and the jurisdiction of that handling. Naming an operating entity without a jurisdiction, or a jurisdiction without an operator, does not close this path. It is NOT resolved by R2JurisdictionDefault, by Automatic placement, by Create Bucket locationHint, or by an unqueried Get Bucket location." data cloudflare_r2_durable_storage_location_obligation: NonEmptyStr = "Where objects in this fleet's durable origin are stored is UNREAD. gunbc.cloudflare.r2_origin fabric_durable_origin_standing places bucket gunbai-fabric-origin under R2JurisdictionDefault. Requested placement, reported location, and residency guarantee are three facts: Create Bucket locationHint (r2_create_bucket_location_hint_reading) is requested placement; Get Bucket location (r2_get_bucket_location_reading) is reported location; Jurisdictional Restrictions / the Get Bucket jurisdiction field are the guarantee that objects are stored and processed within a jurisdiction. This repository has not queried gunbai-fabric-origin, so no Get Bucket location is an observation of ours. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — recreating the origin under a Jurisdictional Restriction that names a jurisdiction, or a Cloudflare statement that objects in gunbai-fabric-origin are stored and processed within a named jurisdiction by a named operator. A reported location is not that guarantee and is not the nine-path closure. It is NOT resolved by Create Bucket locationHint, by treating Get Bucket location as a hint, or by treating R2JurisdictionDefault as residency." From dad1c97d7353d758e65c98bda35fc2eec0cc05ab Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 08:11:50 +0000 Subject: [PATCH 16/25] Hoist region observation and route standing onto provider_route. A second supplier copied Ubicloud's mint-only-in-read-arm coproduct; the shared authority now owns that law, with obligation as DeclarationRef like path unread. Co-authored-by: Cursor --- dag/gunbc/product/fabric/provider_route.dag | 37 +++++++++++ dag/gunbc/product/supplier/cloudflare_r2.dag | 50 ++++++--------- dag/gunbc/product/supplier/ubicloud.dag | 64 ++++++++++--------- dag/gunbc/spark/serving_offer.dag | 4 +- .../fabric/ubicloud_binding_witness_test.dag | 16 +++-- .../cloudflare_r2_route_witness_test.dag | 26 ++++---- 6 files changed, 113 insertions(+), 84 deletions(-) diff --git a/dag/gunbc/product/fabric/provider_route.dag b/dag/gunbc/product/fabric/provider_route.dag index 91fb0a8b720..59afedfeaea 100644 --- a/dag/gunbc/product/fabric/provider_route.dag +++ b/dag/gunbc/product/fabric/provider_route.dag @@ -55,6 +55,43 @@ fn provider_route_eq(a: ProviderRoute, b: ProviderRoute) -> Bool { && declaration_ref_eq(a: a.region, b: b.region) } +// A REGION IS OBSERVED OR THE ROUTE DOES NOT EXIST. product.supplier.ubicloud wrote this +// coproduct first (UbicloudRegionObservation / UbicloudRouteStanding); product.supplier.cloudflare_r2 +// was the proven coincidence (DESIGN section 6). The minting law lives here so a third supplier +// cannot independently edit it. A ProviderRoute is minted ONLY in the read arm: there is no +// value of ProviderRegionObservation that yields a route with an unobserved region. +// +// OBLIGATION IS DeclarationRef, NOT NonEmptyStr. That is the grain ProviderPathUnread already +// uses, so a refusal can locate the named row. Ubicloud's first instance carried the sentence +// itself; the coincidence is the reason that form is retired rather than kept as a stated +// divergence. +type ProviderRegionObservation + = ProviderRegionRead { region: DeclarationRef } + | ProviderRegionUnread { obligation: DeclarationRef } + +type ProviderRouteStanding + = ProviderRouteObserved { route: ProviderRoute } + | ProviderRouteRegionUnobserved { obligation: DeclarationRef } + +fn provider_route_from_region( + provider: DeclarationRef, + service: DeclarationRef, + region: ProviderRegionObservation, +) -> ProviderRouteStanding { + match region { + ProviderRegionUnread { obligation } => + ProviderRouteRegionUnobserved { obligation: obligation }, + ProviderRegionRead { region: observed } => + ProviderRouteObserved { + route: ProviderRoute { + provider: provider, + service: service, + region: observed, + }, + }, + } +} + // The posture is a REVISION, never an ambient "current". A permit records the exact revision it // was evaluated against, so a posture change makes standing permits STALE rather than silently // tolerated - the difference between a decision that can be re-derived and one that merely diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag index 0c39316a0e6..e9a2d8afa82 100644 --- a/dag/gunbc/product/supplier/cloudflare_r2.dag +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -7,6 +7,9 @@ import product.fabric.provider_route { ProviderRoute, ProviderRouteFacts, ProviderDataPathClosure, ProviderPathUnread, DownstreamProviderPopulation, DownstreamProvidersUnread, + ProviderRegionObservation, ProviderRegionUnread, + ProviderRouteStanding, ProviderRouteObserved, ProviderRouteRegionUnobserved, + provider_route_from_region, } // THE DURABLE-ORIGIN THIS REPOSITORY ANSWERS THE NINE-PATH CLOSURE FOR. PRODUCTION DOES NOT MINT A ROUTE. @@ -23,11 +26,11 @@ import product.fabric.provider_route { // gunbai-fabric-origin's Get Bucket location, so no reported-location observation is minted here. // // WHAT PRODUCTION EXECUTES. cloudflare_r2_durable_origin_route_standing is -// CloudflareR2RouteRegionUnobserved carrying cloudflare_r2_region_unread_obligation. +// ProviderRouteRegionUnobserved carrying cloudflare_r2_region_unread_obligation. // cloudflare_r2_route_facts_population is therefore empty: there is no origin ProviderRoute, so // there is no origin row for admit_provider_use. The nine-path closure and downstream population // are still answered (every path Unread; Absent taken zero times). The admit_provider_use pair -// lives only in the witness, over a route minted in the CloudflareR2RegionRead arm of the same +// lives only in the witness, over a route minted in the ProviderRegionRead arm of the same // coproduct — a synthetic observed region, not this origin. // // THE REGION SLOT IS NOT A PLACE TO RECORD AUTOMATIC. product.fabric.provider_route says the @@ -43,38 +46,23 @@ fn cloudflare_r2_service_ref() -> DeclarationRef { decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "R2S3Endpoint") } -type CloudflareR2RegionObservation - = CloudflareR2RegionRead { region: DeclarationRef } - | CloudflareR2RegionUnread { obligation: DeclarationRef } +data cloudflare_r2_region_unread_obligation: NonEmptyStr = "Where this fleet's durable origin actually runs is UNREAD. gunbc.cloudflare.r2_origin fabric_durable_origin_standing places bucket gunbai-fabric-origin under R2JurisdictionDefault. Create Bucket locationHint (r2_create_bucket_location_hint_reading, read 2026-09-13) is a requested placement. Get Bucket location (r2_get_bucket_location_reading, read 2026-09-13) is a reported location. Those are two upstream fields that share location tokens; collapsing them is a section 3 meaning-fork. This repository has not queried gunbai-fabric-origin, so no Get Bucket location is an observation of ours. Automatic and R2JurisdictionDefault are not values of ProviderRoute.region. RESOLVED BY a Get Bucket (or equivalent) observation of this bucket's location field sufficient to name the operating region, or by recreating the origin under a Jurisdictional Restriction that names a jurisdiction — at which point this standing takes ProviderRegionRead with that named location as region. A reported location is not a residency guarantee and is not the nine-path closure. It is NOT resolved by citing r2_placement_automatic, R2JurisdictionDefault, a dashboard Location label, or Create Bucket locationHint." -type CloudflareR2RouteStanding - = CloudflareR2RouteObserved { route: ProviderRoute } - | CloudflareR2RouteRegionUnobserved { obligation: DeclarationRef } - -data cloudflare_r2_region_unread_obligation: NonEmptyStr = "Where this fleet's durable origin actually runs is UNREAD. gunbc.cloudflare.r2_origin fabric_durable_origin_standing places bucket gunbai-fabric-origin under R2JurisdictionDefault. Create Bucket locationHint (r2_create_bucket_location_hint_reading, read 2026-09-13) is a requested placement. Get Bucket location (r2_get_bucket_location_reading, read 2026-09-13) is a reported location. Those are two upstream fields that share location tokens; collapsing them is a section 3 meaning-fork. This repository has not queried gunbai-fabric-origin, so no Get Bucket location is an observation of ours. Automatic and R2JurisdictionDefault are not values of ProviderRoute.region. RESOLVED BY a Get Bucket (or equivalent) observation of this bucket's location field sufficient to name the operating region, or by recreating the origin under a Jurisdictional Restriction that names a jurisdiction — at which point this standing takes CloudflareR2RegionRead with that named location as region. A reported location is not a residency guarantee and is not the nine-path closure. It is NOT resolved by citing r2_placement_automatic, R2JurisdictionDefault, a dashboard Location label, or Create Bucket locationHint." - -fn cloudflare_r2_durable_origin_region() -> CloudflareR2RegionObservation { - CloudflareR2RegionUnread { +fn cloudflare_r2_durable_origin_region() -> ProviderRegionObservation { + ProviderRegionUnread { obligation: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_region_unread_obligation"), } } -fn cloudflare_r2_route(region: CloudflareR2RegionObservation) -> CloudflareR2RouteStanding { - match region { - CloudflareR2RegionUnread { obligation } => - CloudflareR2RouteRegionUnobserved { obligation: obligation }, - CloudflareR2RegionRead { region: observed } => - CloudflareR2RouteObserved { - route: ProviderRoute { - provider: cloudflare_r2_provider_ref(), - service: cloudflare_r2_service_ref(), - region: observed, - }, - }, - } +fn cloudflare_r2_route(region: ProviderRegionObservation) -> ProviderRouteStanding { + provider_route_from_region( + provider: cloudflare_r2_provider_ref(), + service: cloudflare_r2_service_ref(), + region: region, + ) } -fn cloudflare_r2_durable_origin_route_standing() -> CloudflareR2RouteStanding { +fn cloudflare_r2_durable_origin_route_standing() -> ProviderRouteStanding { cloudflare_r2_route(region: cloudflare_r2_durable_origin_region()) } @@ -156,9 +144,9 @@ fn cloudflare_r2_facts(route: ProviderRoute) -> ProviderRouteFacts { // THIS MODULE DECLARES NO SANCTION ROSTER AND NO POSTURE REVISION. Nobody has stated that we are // willing to place work on this vendor's default-jurisdiction R2 under a named posture. Writing a // roster row here to make the module look complete would be the fabricated authority the gate exists -// to close. Production standing is CloudflareR2RouteRegionUnobserved; this function projects that +// to close. Production standing is ProviderRouteRegionUnobserved; this function projects that // standing to an empty facts list. admit_provider_use is not invoked here. The witness mints a -// synthetic CloudflareR2RegionRead route and calls admit_provider_use on that pair. +// synthetic ProviderRegionRead route and calls admit_provider_use on that pair. // // DECLARED FRONTIER (DESIGN section 3c). The production consumer is a posture producer that mints a // CompliancePostureRevision whose permitted_jurisdictions enumerate only routes whose facts have @@ -167,7 +155,7 @@ fn cloudflare_r2_facts(route: ProviderRoute) -> ProviderRouteFacts { // consumer of the admission pair is the witness. fn cloudflare_r2_route_facts_population() -> List { match cloudflare_r2_durable_origin_route_standing() { - CloudflareR2RouteRegionUnobserved { obligation } => [], - CloudflareR2RouteObserved { route } => [cloudflare_r2_facts(route: route)], + ProviderRouteRegionUnobserved { obligation } => [], + ProviderRouteObserved { route } => [cloudflare_r2_facts(route: route)], } } diff --git a/dag/gunbc/product/supplier/ubicloud.dag b/dag/gunbc/product/supplier/ubicloud.dag index d02f4d60c5c..872ca05d3df 100644 --- a/dag/gunbc/product/supplier/ubicloud.dag +++ b/dag/gunbc/product/supplier/ubicloud.dag @@ -9,7 +9,12 @@ import product.fabric.work { Shape, HardRequirements, CapabilityManifestRef, Tru import product.fabric.envelope { cpu_memory_envelope } import product.fabric.isolation { IsolationProfile } import product.fabric.supply { SupplierOffer, OfferQuote, QuotedPerMinute, OfferEvidence, QuotedSupply } -import product.fabric.provider_route { ProviderRoute } +import product.fabric.provider_route { + ProviderRoute, + ProviderRegionObservation, ProviderRegionUnread, + ProviderRouteStanding, ProviderRouteObserved, ProviderRouteRegionUnobserved, + provider_route_from_region, +} import std.decl_ref { decl_ref, DeclarationRef } import extdeps.pricing.ubicloud { UbicloudRunnerPriceRow, ubicloud_runner_price_catalog, @@ -122,15 +127,17 @@ fn ubicloud_unobserved_isolation() -> IsolationProfile { // UNWRITABLE, not for the currently-empty set of writers to be pointed at. // // So the observation is its own coproduct and a ProviderRoute is minted ONLY in the read arm. -// There is no value of UbicloudRegionObservation that yields a route with an unobserved region, -// which is what makes this construction rather than validation. -type UbicloudRegionObservation - = UbicloudRegionRead { region: DeclarationRef } - | UbicloudRegionUnread { obligation: NonEmptyStr } +// There is no value of ProviderRegionObservation that yields a route with an unobserved region, +// which is what makes this construction rather than validation. The coproduct itself lives in +// product.fabric.provider_route (review 65274): this module was the first instance, and the +// Cloudflare R2 coincidence is why it moved rather than being copied. +fn ubicloud_provider_ref() -> DeclarationRef { + decl_ref(module_path: "extdeps.cloud.ubicloud", decl_name: "extdeps_external_authority_anchor") +} -type UbicloudRouteStanding - = UbicloudRouteObserved { route: ProviderRoute } - | UbicloudRouteRegionUnobserved { obligation: NonEmptyStr } +fn ubicloud_service_ref() -> DeclarationRef { + decl_ref(module_path: "extdeps.cloud.ubicloud", decl_name: "ubicloud_runner_types_authority") +} // NOBODY HAS READ THIS VENDOR'S REGIONS, stated as the standing production observation. Nothing // in the cited catalog names a location, so any region written here would be invented. This is @@ -138,23 +145,18 @@ type UbicloudRouteStanding // obligation is one named thing rather than a sentence repeated per caller. data ubicloud_region_unread_obligation: NonEmptyStr = "No cited Ubicloud row names a region for a runner. Until one is read and cited, this vendor's offers cannot be placed on a route, and binding refuses rather than inventing a location." -fn ubicloud_region_unread() -> UbicloudRegionObservation { - UbicloudRegionUnread { obligation: ubicloud_region_unread_obligation } +fn ubicloud_region_unread() -> ProviderRegionObservation { + ProviderRegionUnread { + obligation: decl_ref(module_path: "product.supplier.ubicloud", decl_name: "ubicloud_region_unread_obligation"), + } } -fn ubicloud_route(region: UbicloudRegionObservation) -> UbicloudRouteStanding { - match region { - UbicloudRegionUnread { obligation } => - UbicloudRouteRegionUnobserved { obligation: obligation }, - UbicloudRegionRead { region: observed } => - UbicloudRouteObserved { - route: ProviderRoute { - provider: decl_ref(module_path: "extdeps.cloud.ubicloud", decl_name: "extdeps_external_authority_anchor"), - service: decl_ref(module_path: "extdeps.cloud.ubicloud", decl_name: "ubicloud_runner_types_authority"), - region: observed, - }, - }, - } +fn ubicloud_route(region: ProviderRegionObservation) -> ProviderRouteStanding { + provider_route_from_region( + provider: ubicloud_provider_ref(), + service: ubicloud_service_ref(), + region: region, + ) } fn ubicloud_unexpressed(catalog: UbicloudRunnerCatalogRow) -> List { @@ -190,15 +192,17 @@ data placement_concurrency_bound: Int = 64 // than binding an offer that would rank on a fabricated number. type ReadinessObservation = ReadinessMeasured { ready_at: Timestamp, receipt: ObservationReceiptRef } - | ReadinessUnmeasured { obligation: NonEmptyStr } + | ReadinessUnmeasured { obligation: DeclarationRef } + +data ubicloud_readiness_unread_obligation: NonEmptyStr = "Provisioning delay from job dispatch to a Ubicloud runner accepting work has not been measured. Start one job per shape, record dispatch and first-heartbeat timestamps, and land the receipt. Until then no Ubicloud offer may be ranked by a delay-valuing policy." data ubicloud_readiness: ReadinessObservation = ReadinessUnmeasured { - obligation: "Provisioning delay from job dispatch to a Ubicloud runner accepting work has not been measured. Start one job per shape, record dispatch and first-heartbeat timestamps, and land the receipt. Until then no Ubicloud offer may be ranked by a delay-valuing policy.", + obligation: decl_ref(module_path: "product.supplier.ubicloud", decl_name: "ubicloud_readiness_unread_obligation"), } type OfferBinding

= OfferBound { bound: SupplierOfferProjection

} - | OfferBindingRefused { runs_on_label: NonEmptyStr, cause: NonEmptyStr } + | OfferBindingRefused { runs_on_label: NonEmptyStr, cause: DeclarationRef } fn bind_ubicloud_offer

( principal: P, @@ -207,15 +211,15 @@ fn bind_ubicloud_offer

( capabilities: CapabilityManifestRef, trust_domain: TrustDomainRef, readiness: ReadinessObservation, - region: UbicloudRegionObservation, + region: ProviderRegionObservation, quoted_at: Timestamp, valid_until: Timestamp, receipt: ObservationReceiptRef, ) -> OfferBinding

{ match ubicloud_route(region: region) { - UbicloudRouteRegionUnobserved { obligation } => + ProviderRouteRegionUnobserved { obligation } => OfferBindingRefused { runs_on_label: row.catalog.runs_on_label, cause: obligation }, - UbicloudRouteObserved { route: bound_route } => + ProviderRouteObserved { route: bound_route } => match readiness { ReadinessUnmeasured { obligation } => OfferBindingRefused { runs_on_label: row.catalog.runs_on_label, cause: obligation }, diff --git a/dag/gunbc/spark/serving_offer.dag b/dag/gunbc/spark/serving_offer.dag index be157b4c116..9d75bd569f5 100644 --- a/dag/gunbc/spark/serving_offer.dag +++ b/dag/gunbc/spark/serving_offer.dag @@ -104,8 +104,8 @@ type SparkServingReadiness // // SupplierOffer carries a ProviderRoute because admission is decided over provider x service x // region and never over a company. A route's region is therefore an OBSERVATION, exactly as -// product.supplier.ubicloud ubicloud_route treats it: unread, it refuses as -// UbicloudRouteRegionUnobserved rather than filling the slot. This module has the same obligation +// product.fabric.provider_route provider_route_from_region treats it: unread, it refuses as +// ProviderRouteRegionUnobserved rather than filling the slot. This module has the same obligation // and, today, no observer -- so it refuses for the same reason the readiness arm above refuses. // Binding an offer whose route nothing established would put a candidate in front of selection // carrying a region no one measured, and every admission decision downstream would be taken diff --git a/dag/test/claim/fabric/ubicloud_binding_witness_test.dag b/dag/test/claim/fabric/ubicloud_binding_witness_test.dag index c39ace7d641..980adc387dd 100644 --- a/dag/test/claim/fabric/ubicloud_binding_witness_test.dag +++ b/dag/test/claim/fabric/ubicloud_binding_witness_test.dag @@ -3,11 +3,13 @@ module test.claim.fabric.ubicloud_binding_witness import std.types { NonEmptyStr } import std.logic { Bool } import std.decl_ref { decl_ref, declaration_ref_eq } -import product.fabric.provider_route { provider_route_eq, ProviderRoute } +import product.fabric.provider_route { + provider_route_eq, ProviderRoute, + ProviderRegionObservation, ProviderRegionRead, +} import product.supplier.ubicloud { bind_ubicloud_offer, ReadinessMeasured, OfferBound, OfferBindingRefused, - UbicloudRegionObservation, UbicloudRegionRead, ubicloud_region_unread, - ubicloud_region_unread_obligation, + ubicloud_region_unread, ubicloud_region_unread_obligation, } import extdeps.pricing.ubicloud { ubicloud_premium_standard_2_price } @@ -25,15 +27,15 @@ import extdeps.pricing.ubicloud { ubicloud_premium_standard_2_price } // observation someone made, and a fixture standing in for that observation belongs to the fixture. data observed_region: NonEmptyStr = "observed-region-for-this-witness" -fn a_read_region() -> UbicloudRegionObservation { - UbicloudRegionRead { +fn a_read_region() -> ProviderRegionObservation { + ProviderRegionRead { region: decl_ref( module_path: "test.claim.fabric.ubicloud_binding_witness", decl_name: "observed_region"), } } -fn bind(region: UbicloudRegionObservation) -> NonEmptyStr { +fn bind(region: ProviderRegionObservation) -> NonEmptyStr { match bind_ubicloud_offer( principal: "gunbc", executor: "gunbc", @@ -54,7 +56,7 @@ fn bind(region: UbicloudRegionObservation) -> NonEmptyStr { } } -fn bound_region_matches(region: UbicloudRegionObservation, expected: ProviderRoute) -> Bool { +fn bound_region_matches(region: ProviderRegionObservation, expected: ProviderRoute) -> Bool { match bind_ubicloud_offer( principal: "gunbc", executor: "gunbc", diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag index 9cedaa6c2a2..36aa38d1b6d 100644 --- a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -8,6 +8,8 @@ import product.fabric.provider_route { ProviderRoute, CompliancePostureRevision, ProviderRouteFacts, ProviderDataPathClosure, ProviderPathStanding, ProviderPathLocated, ProviderPathAbsent, ProviderPathUnread, DownstreamProviderPopulation, NoDownstreamProviders, + ProviderRegionObservation, ProviderRegionRead, + ProviderRouteObserved, ProviderRouteRegionUnobserved, } import product.fabric.provider_admission { RouteScopeSanction, ProviderUseScope, ProviderUseAdmission, @@ -24,10 +26,6 @@ import product.supplier.cloudflare_r2 { cloudflare_r2_route_facts_population, cloudflare_r2_data_paths, cloudflare_r2_facts, - CloudflareR2RegionObservation, - CloudflareR2RegionRead, - CloudflareR2RouteObserved, - CloudflareR2RouteRegionUnobserved, } data r2_witness_customer_profile: NonEmptyStr = "r2-witness-customer-profile" @@ -75,8 +73,8 @@ fn t_agreement() -> DeclarationRef { // It is not gunbai-fabric-origin: that standing is Unobserved, so no origin route exists to // admit. The pair below asks whether admit_provider_use still refuses an unread path and // admits once that path is resolved, on a route the coproduct is allowed to mint. -fn t_read_region() -> CloudflareR2RegionObservation { - CloudflareR2RegionRead { +fn t_read_region() -> ProviderRegionObservation { + ProviderRegionRead { region: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_synthetic_region"), } } @@ -170,8 +168,8 @@ fn t_denied_with(a: ProviderUseAdmission, tag: String, located: Dec test fn the_durable_origin_has_no_admissible_facts() -> Bool { match cloudflare_r2_durable_origin_route_standing() { - CloudflareR2RouteObserved { route } => false, - CloudflareR2RouteRegionUnobserved { obligation } => declaration_ref_eq( + ProviderRouteObserved { route } => false, + ProviderRouteRegionUnobserved { obligation } => declaration_ref_eq( a: obligation, b: decl_ref( module_path: "product.supplier.cloudflare_r2", @@ -242,8 +240,8 @@ fn t_facts_with_durable_storage(route: ProviderRoute, storage: ProviderPathStand test fn one_unread_durable_storage_path_refuses_with_that_paths_obligation() -> Bool { match cloudflare_r2_route(region: t_read_region()) { - CloudflareR2RouteRegionUnobserved { obligation } => false, - CloudflareR2RouteObserved { route } => t_denied_with( + ProviderRouteRegionUnobserved { obligation } => false, + ProviderRouteObserved { route } => t_denied_with( a: t_decide( route: route, facts: t_facts_with_durable_storage(route: route, storage: ProviderPathUnread { @@ -258,8 +256,8 @@ test fn one_unread_durable_storage_path_refuses_with_that_paths_obligation() -> test fn a_read_region_route_admits_once_that_path_is_resolved() -> Bool { match cloudflare_r2_route(region: t_read_region()) { - CloudflareR2RouteRegionUnobserved { obligation } => false, - CloudflareR2RouteObserved { route } => match t_decide( + ProviderRouteRegionUnobserved { obligation } => false, + ProviderRouteObserved { route } => match t_decide( route: route, facts: t_facts_with_durable_storage(route: route, storage: t_resolved()), ) { @@ -287,8 +285,8 @@ test fn a_read_region_route_admits_once_that_path_is_resolved() -> Bool { test fn production_unread_paths_on_a_read_region_route_still_refuse() -> Bool { match cloudflare_r2_route(region: t_read_region()) { - CloudflareR2RouteRegionUnobserved { obligation } => false, - CloudflareR2RouteObserved { route } => t_denied_with( + ProviderRouteRegionUnobserved { obligation } => false, + ProviderRouteObserved { route } => t_denied_with( a: t_decide(route: route, facts: cloudflare_r2_facts(route: route)), tag: "downstream-unassessed", located: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_downstream_obligation"), From bd08d4ca7ad4599e398758b4b9429f842267b4bd Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 08:32:08 +0000 Subject: [PATCH 17/25] Cite SparkServingRoute as a non-member of the shared route standing. The reason lives at that type; this sentence only makes the divergence findable from the new attractor. Co-authored-by: Cursor --- dag/gunbc/product/fabric/provider_route.dag | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dag/gunbc/product/fabric/provider_route.dag b/dag/gunbc/product/fabric/provider_route.dag index 59afedfeaea..0ea9bdfb924 100644 --- a/dag/gunbc/product/fabric/provider_route.dag +++ b/dag/gunbc/product/fabric/provider_route.dag @@ -61,6 +61,9 @@ fn provider_route_eq(a: ProviderRoute, b: ProviderRoute) -> Bool { // cannot independently edit it. A ProviderRoute is minted ONLY in the read arm: there is no // value of ProviderRegionObservation that yields a route with an unobserved region. // +// NOT A MEMBER: gunbc.spark.serving_offer SparkServingRoute. The reason it is not this coproduct +// is stated at that type's declaration (DESIGN section 3b: diverges with a stated reason). +// // OBLIGATION IS DeclarationRef, NOT NonEmptyStr. That is the grain ProviderPathUnread already // uses, so a refusal can locate the named row. Ubicloud's first instance carried the sentence // itself; the coincidence is the reason that form is retired rather than kept as a stated From 1f5bcacf97d65e31401f51dce7f6dbd8a4fc14d1 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 09:01:36 +0000 Subject: [PATCH 18/25] Fold R2 location readings into the existing R2 extdeps module. A second module whose subject was a wrapper around one reading was a second authority for one product. The facts revision now hashes those readings so they have an executing consumer. Co-authored-by: Cursor --- dag/extdeps/cloudflare/r2.dag | 141 ++++++++++++++- dag/extdeps/cloudflare/r2_data_location.dag | 169 ------------------ dag/gunbc/extdeps_scope_frontier.dag | 1 - dag/gunbc/product/supplier/cloudflare_r2.dag | 19 +- .../cloudflare_r2_route_witness_test.dag | 2 +- 5 files changed, 151 insertions(+), 181 deletions(-) delete mode 100644 dag/extdeps/cloudflare/r2_data_location.dag diff --git a/dag/extdeps/cloudflare/r2.dag b/dag/extdeps/cloudflare/r2.dag index e9130ee5d30..9ed30558cfa 100644 --- a/dag/extdeps/cloudflare/r2.dag +++ b/dag/extdeps/cloudflare/r2.dag @@ -31,6 +31,55 @@ data r2_s3_api_citation: ExternalAuthority = ExternalAuthority { } } +data r2_data_location_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "developers.cloudflare.com/r2/reference/data-location" + } +} + +data r2_how_r2_works_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "developers.cloudflare.com/r2/how-r2-works" + } +} + +data r2_us_jurisdiction_changelog_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "developers.cloudflare.com/changelog/post/2026-08-17-r2-us-jurisdiction" + } +} + +data cloudflare_subprocessors_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "www.cloudflare.com/gdpr/subprocessors/cloudflare-services" + } +} + +data cloudflare_customer_dpa_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "cf-assets.www.cloudflare.com/slt3lc6tev37/1TTgT35GoUNlKZYGuKWBFy/4e7dfc8cf402419a9b1cf624291fc69f/cloudflare_customer_dpa-v6.4_april_3_2026.pdf" + } +} + +data r2_create_bucket_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "developers.cloudflare.com/api/resources/r2/subresources/buckets/methods/create" + } +} + +data r2_get_bucket_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "developers.cloudflare.com/api/resources/r2/subresources/buckets/methods/get" + } +} + data r2_tokens_doc_as_of: Timestamp = "2026-08-18" // THE READ ID IS THE ONE PERMISSION GROUP ID THIS MODULE PINS, AND THE WRITE ID IS DELIBERATELY NOT @@ -99,7 +148,16 @@ data extdeps_model_scope: ExternalModelScope = ExternalModelScope { } }, first_citation: extdeps_external_authority_anchor, - further_citations: [r2_s3_api_citation] + further_citations: [ + r2_s3_api_citation, + r2_data_location_authority, + r2_how_r2_works_authority, + r2_us_jurisdiction_changelog_authority, + cloudflare_subprocessors_authority, + cloudflare_customer_dpa_authority, + r2_create_bucket_authority, + r2_get_bucket_authority, + ] } type R2Jurisdiction = R2JurisdictionDefault @@ -329,6 +387,87 @@ fn r2_object_url(locator: R2ObjectLocator) -> String { ) } +// LOCATION AND RESIDENCY READINGS FOR THIS SAME PRODUCT. They were briefly a second module +// (extdeps.cloudflare.r2_data_location) whose subject was a wrapper around one reading. R2 is one +// independently versioned product; DESIGN section 3's external-upstream rule does not mint a +// second module authority per documentation page. The tokens-page default-jurisdiction sentence +// cites this module's existing anchor rather than a parallel ExternalAuthority for the same URI. +// +// EACH ROW CARRIES THE DOCUMENT, THE DATE IT WAS READ, AND THE SENTENCE IT WAS READ FOR. The +// statement field is a TRANSCRIPTION of upstream's own words, not commentary about them. A reading +// is dated and never silently refreshed: upstream edits a page without telling anyone, so a +// statement that no longer appears at its URI is a NEW reading with a later date. +type CloudflarePublishedReading { + authority: DeclarationRef + read_on: NonEmptyStr + statement: NonEmptyStr +} + +data r2_data_location_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_data_location_authority"), + read_on: "2026-09-12", + statement: "When you create a new bucket, the data location is set to Automatic by default. Currently, this option chooses a bucket location in the closest available region to the create bucket request based on the location of the caller. Location Hints are optional parameters you can provide during bucket creation to indicate the primary geographical location you expect data will be accessed from. Location Hints are a best effort and not a guarantee, and they should only be used as a way to optimize performance. Available hints: wnam Western North America, enam Eastern North America, weur Western Europe, eeur Eastern Europe, apac Asia-Pacific, oc Oceania. Jurisdictional Restrictions guarantee objects in a bucket are stored within a specific jurisdiction. Use Jurisdictional Restrictions when you need to ensure data is stored and processed within a jurisdiction to meet data residency requirements. Available jurisdictions: eu European Union, fedramp FedRAMP, us United States. The following services do not interact with R2 resources with assigned jurisdictions: Logpush. Once an R2 bucket is created, the jurisdiction cannot be changed. Page last updated Aug 19, 2026.", +} + +data r2_how_r2_works_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_how_r2_works_authority"), + read_on: "2026-09-12", + statement: "R2 Gateway: The entry point for all API requests that handles authentication and routing logic. This service is deployed across Cloudflare's global network via Cloudflare Workers. Metadata Service: A distributed layer built on Durable Objects used to store and manage object metadata. Distributed Storage Infrastructure: The underlying infrastructure that persistently stores encrypted object data. On write, the Gateway determines which storage cluster to write the encrypted data to within the location set for the bucket. The encrypted data is written and stored in the distributed storage infrastructure, and replicated within the region (e.g. ENAM) for durability. On read, if the object is not in the tiered read cache, it retrieves the object from one of the distributed storage data centers within the region that holds the object data. Page last updated Apr 21, 2026.", +} + +data r2_us_jurisdiction_changelog_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_us_jurisdiction_changelog_authority"), + read_on: "2026-09-12", + statement: "New us jurisdiction for R2. R2 now supports a us jurisdiction, which guarantees that bucket data is stored and processed within the United States. Use this jurisdiction when you need explicit US data residency guarantees. Use the jurisdiction-specific S3 endpoint https://.us.r2.cloudflarestorage.com. Once an R2 bucket is created, its jurisdiction cannot be changed. Posted 2026-08-17.", +} + +data r2_tokens_default_jurisdiction_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "extdeps_external_authority_anchor"), + read_on: "2026-09-12", + statement: "A specific bucket is represented as com.cloudflare.edge.r2.bucket.__. JURISDICTION: The jurisdiction where the R2 bucket lives. For buckets not created in a specific jurisdiction this value will be default.", +} + +data cloudflare_subprocessors_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "cloudflare_subprocessors_authority"), + read_on: "2026-09-12", + statement: "Last Updated: October 1, 2025. Cloudflare uses a handful of sub-processors to support the Cloudflare service. Some of these sub-processors are members of the Cloudflare Group (Cloudflare, Inc. and its subsidiaries) and some are third parties. Third-party entities include Slack Technologies, Inc. (Customer support communications, United States); Zendesk, Inc. (Customer support and account management, United States, the European Economic Area, Japan, and Australia); Salesforce, Inc. (Customer support and account management, United States); Google LLC (Cloudflare Developer Platform, Cloudflare Zero Trust and AI Gateway; European Economic Area, United States, Australia, India); Oracle America, Inc. (Cloudflare Developer Platform and Cache Reserve; United States, European Economic Area, UK, Japan, Australia, Canada, Singapore); Amazon Web Services (Cloudflare Email Security; United States, European Economic Area); CoreWeave, Inc., Nebius BV (Workers AI); Anthropic PBC, OpenAI, Inc., X.AI Corp., Groq, Inc. (AI Gateway). The page lists Cloudflare Group subsidiaries by location.", +} + +data r2_create_bucket_location_hint_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_create_bucket_authority"), + read_on: "2026-09-13", + statement: "Create Bucket POST /accounts/{account_id}/r2/buckets. Body parameter locationHint, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Header cf-r2-jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13.", +} + +data r2_get_bucket_location_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_get_bucket_authority"), + read_on: "2026-09-13", + statement: "Get Bucket GET /accounts/{account_id}/r2/buckets/{bucket_name}. Result field location, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Result field jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13.", +} + +data cloudflare_customer_dpa_reading: CloudflarePublishedReading = CloudflarePublishedReading { + authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "cloudflare_customer_dpa_authority"), + read_on: "2026-09-12", + statement: "Cloudflare, Inc. Data Processing Addendum, Version 6.4 April 3, 2026. The Customer grants a general written authorization: (a) to Cloudflare to appoint other members of the Cloudflare Group as sub-Processors, and (b) to Cloudflare and other members of the Cloudflare Group to appoint third party data center operators, and business, engineering and customer support providers as sub-Processors to support the performance of the Service. Cloudflare will maintain a list of sub-Processors at https://www.cloudflare.com/gdpr/subprocessors/. This DPA and any action related thereto shall be governed by and construed in accordance with the laws as specified in the Main Agreement, and the parties consent to the personal jurisdiction of, and venue in, the courts specified in the Main Agreement.", +} + +// THE READINGS ARE ONE CLOSURE. product.supplier.cloudflare_r2 hashes this list into +// ProviderRouteFacts.facts_revision, so a changed transcription is a different facts row rather than +// a silent edit behind a pinned string. Automatic placement is recorded IN r2_data_location_reading; +// it is not a second model-scope subject and not a value of ProviderRoute.region. +fn r2_published_location_readings() -> List { + [ + r2_data_location_reading, + r2_how_r2_works_reading, + r2_us_jurisdiction_changelog_reading, + r2_tokens_default_jurisdiction_reading, + cloudflare_subprocessors_reading, + r2_create_bucket_location_hint_reading, + r2_get_bucket_location_reading, + cloudflare_customer_dpa_reading, + ] +} + // THE r2_s3_endpoint_url ROW IS RETIRED: gunbc.cloudflare.r2_origin_object reaches it through // r2_object_url on the executing put_origin_object and fetch_origin_object entries, which is the // consumer the row named. The list is the membership of what remains. diff --git a/dag/extdeps/cloudflare/r2_data_location.dag b/dag/extdeps/cloudflare/r2_data_location.dag deleted file mode 100644 index f0652d5f745..00000000000 --- a/dag/extdeps/cloudflare/r2_data_location.dag +++ /dev/null @@ -1,169 +0,0 @@ -module extdeps.cloudflare.r2_data_location - -import std.types { NonEmptyStr } -import std.decl_ref { DeclarationRef, WholeDeclaration, decl_ref } -import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef } -import extdeps.uri { Uri, Https } - - -data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { - uri: Uri { - scheme: Https - locator: "developers.cloudflare.com/r2/reference/data-location" - } -} - -data r2_how_r2_works_authority: ExternalAuthority = ExternalAuthority { - uri: Uri { - scheme: Https - locator: "developers.cloudflare.com/r2/how-r2-works" - } -} - -data r2_us_jurisdiction_changelog_authority: ExternalAuthority = ExternalAuthority { - uri: Uri { - scheme: Https - locator: "developers.cloudflare.com/changelog/post/2026-08-17-r2-us-jurisdiction" - } -} - -data cloudflare_subprocessors_authority: ExternalAuthority = ExternalAuthority { - uri: Uri { - scheme: Https - locator: "www.cloudflare.com/gdpr/subprocessors/cloudflare-services" - } -} - -data cloudflare_customer_dpa_authority: ExternalAuthority = ExternalAuthority { - uri: Uri { - scheme: Https - locator: "cf-assets.www.cloudflare.com/slt3lc6tev37/1TTgT35GoUNlKZYGuKWBFy/4e7dfc8cf402419a9b1cf624291fc69f/cloudflare_customer_dpa-v6.4_april_3_2026.pdf" - } -} - -data r2_create_bucket_authority: ExternalAuthority = ExternalAuthority { - uri: Uri { - scheme: Https - locator: "developers.cloudflare.com/api/resources/r2/subresources/buckets/methods/create" - } -} - -data r2_get_bucket_authority: ExternalAuthority = ExternalAuthority { - uri: Uri { - scheme: Https - locator: "developers.cloudflare.com/api/resources/r2/subresources/buckets/methods/get" - } -} - -data extdeps_model_scope: ExternalModelScope = ExternalModelScope { - subject: ExternalSubjectRef { - declaration: DeclarationRef { - module_path: "extdeps.cloudflare.r2_data_location", - decl_name: "r2_placement_automatic", - field: WholeDeclaration - } - }, - first_citation: extdeps_external_authority_anchor, - further_citations: [ - r2_how_r2_works_authority, - r2_us_jurisdiction_changelog_authority, - cloudflare_subprocessors_authority, - cloudflare_customer_dpa_authority, - r2_create_bucket_authority, - r2_get_bucket_authority, - ] -} - -// EACH ROW CARRIES THE DOCUMENT, THE DATE IT WAS READ, AND THE SENTENCE IT WAS READ FOR. The -// statement field is a TRANSCRIPTION of upstream's own words, not commentary about them. A reading -// is dated and never silently refreshed: upstream edits a page without telling anyone, so a -// statement that no longer appears at its URI is a NEW reading with a later date. -// AUTHORITY IS A CITATION TO THE PAGE'S EXISTING ROW, NOT A SECOND URI STRUCT. The tokens page -// already lives as extdeps.cloudflare.r2 extdeps_external_authority_anchor; a second ExternalAuthority -// with the same locator would be independently editable and is the nickname DESIGN section 3 -// forbids. Pages this module introduces keep their ExternalAuthority rows and are cited from here. -type CloudflarePublishedReading { - authority: DeclarationRef - read_on: NonEmptyStr - statement: NonEmptyStr -} - -data r2_data_location_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "extdeps_external_authority_anchor"), - read_on: "2026-09-12", - statement: "When you create a new bucket, the data location is set to Automatic by default. Currently, this option chooses a bucket location in the closest available region to the create bucket request based on the location of the caller. Location Hints are optional parameters you can provide during bucket creation to indicate the primary geographical location you expect data will be accessed from. Location Hints are a best effort and not a guarantee, and they should only be used as a way to optimize performance. Available hints: wnam Western North America, enam Eastern North America, weur Western Europe, eeur Eastern Europe, apac Asia-Pacific, oc Oceania. Jurisdictional Restrictions guarantee objects in a bucket are stored within a specific jurisdiction. Use Jurisdictional Restrictions when you need to ensure data is stored and processed within a jurisdiction to meet data residency requirements. Available jurisdictions: eu European Union, fedramp FedRAMP, us United States. The following services do not interact with R2 resources with assigned jurisdictions: Logpush. Once an R2 bucket is created, the jurisdiction cannot be changed. Page last updated Aug 19, 2026.", -} - -data r2_how_r2_works_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "r2_how_r2_works_authority"), - read_on: "2026-09-12", - statement: "R2 Gateway: The entry point for all API requests that handles authentication and routing logic. This service is deployed across Cloudflare's global network via Cloudflare Workers. Metadata Service: A distributed layer built on Durable Objects used to store and manage object metadata. Distributed Storage Infrastructure: The underlying infrastructure that persistently stores encrypted object data. On write, the Gateway determines which storage cluster to write the encrypted data to within the location set for the bucket. The encrypted data is written and stored in the distributed storage infrastructure, and replicated within the region (e.g. ENAM) for durability. On read, if the object is not in the tiered read cache, it retrieves the object from one of the distributed storage data centers within the region that holds the object data. Page last updated Apr 21, 2026.", -} - -data r2_us_jurisdiction_changelog_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "r2_us_jurisdiction_changelog_authority"), - read_on: "2026-09-12", - statement: "New us jurisdiction for R2. R2 now supports a us jurisdiction, which guarantees that bucket data is stored and processed within the United States. Use this jurisdiction when you need explicit US data residency guarantees. Use the jurisdiction-specific S3 endpoint https://.us.r2.cloudflarestorage.com. Once an R2 bucket is created, its jurisdiction cannot be changed. Posted 2026-08-17.", -} - -data r2_tokens_default_jurisdiction_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "extdeps_external_authority_anchor"), - read_on: "2026-09-12", - statement: "A specific bucket is represented as com.cloudflare.edge.r2.bucket.__. JURISDICTION: The jurisdiction where the R2 bucket lives. For buckets not created in a specific jurisdiction this value will be default.", -} - -data cloudflare_subprocessors_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_subprocessors_authority"), - read_on: "2026-09-12", - statement: "Last Updated: October 1, 2025. Cloudflare uses a handful of sub-processors to support the Cloudflare service. Some of these sub-processors are members of the Cloudflare Group (Cloudflare, Inc. and its subsidiaries) and some are third parties. Third-party entities include Slack Technologies, Inc. (Customer support communications, United States); Zendesk, Inc. (Customer support and account management, United States, the European Economic Area, Japan, and Australia); Salesforce, Inc. (Customer support and account management, United States); Google LLC (Cloudflare Developer Platform, Cloudflare Zero Trust and AI Gateway; European Economic Area, United States, Australia, India); Oracle America, Inc. (Cloudflare Developer Platform and Cache Reserve; United States, European Economic Area, UK, Japan, Australia, Canada, Singapore); Amazon Web Services (Cloudflare Email Security; United States, European Economic Area); CoreWeave, Inc., Nebius BV (Workers AI); Anthropic PBC, OpenAI, Inc., X.AI Corp., Groq, Inc. (AI Gateway). The page lists Cloudflare Group subsidiaries by location.", -} - -data r2_create_bucket_location_hint_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "r2_create_bucket_authority"), - read_on: "2026-09-13", - statement: "Create Bucket POST /accounts/{account_id}/r2/buckets. Body parameter locationHint, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Header cf-r2-jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13.", -} - -data r2_get_bucket_location_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "r2_get_bucket_authority"), - read_on: "2026-09-13", - statement: "Get Bucket GET /accounts/{account_id}/r2/buckets/{bucket_name}. Result field location, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Result field jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13.", -} - -data cloudflare_customer_dpa_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_customer_dpa_authority"), - read_on: "2026-09-12", - statement: "Cloudflare, Inc. Data Processing Addendum, Version 6.4 April 3, 2026. The Customer grants a general written authorization: (a) to Cloudflare to appoint other members of the Cloudflare Group as sub-Processors, and (b) to Cloudflare and other members of the Cloudflare Group to appoint third party data center operators, and business, engineering and customer support providers as sub-Processors to support the performance of the Service. Cloudflare will maintain a list of sub-Processors at https://www.cloudflare.com/gdpr/subprocessors/. This DPA and any action related thereto shall be governed by and construed in accordance with the laws as specified in the Main Agreement, and the parties consent to the personal jurisdiction of, and venue in, the courts specified in the Main Agreement.", -} - -// THE COMPANY PARTY IS extdeps.vendor.cloudflare cloudflare. A legal-name literal here would be -// a second name for that Vendor row (DESIGN section 3). Address and country from a docs publisher -// block are not a residency commitment and are not minted as a parallel party. The route's -// provider slot cites that vendor row. -// -// JURISDICTION TAGS LIVE ON extdeps.cloudflare.r2 R2Jurisdiction. This module does not re-export -// them, does not wrap them in unused restriction rows, and does not export a Bool over the -// coproduct. A Bool over that type would be the same attractor product.fabric.provider_admission -// deleted from path_is_resolved: it discards the arm, so a later caller walks the value again. -// Location hints stay in r2_data_location_reading rather than as a coproduct: no production path -// consults a hint identity, and a constantly-false residency predicate over one would be a -// permanently-green decoration (DESIGN sections 3c and 4b). The same argument forbids a production -// Bool over R2Jurisdiction. The default wire value is transcribed in -// r2_tokens_default_jurisdiction_reading; the fleet bucket's jurisdiction is -// gunbc.cloudflare.r2_origin fabric_durable_origin_standing. - -// AUTOMATIC IS A CHOICE MECHANISM, AND THAT IS WHAT THIS ROW RECORDS. It is not a country, not a -// data-center park, not a residency commitment, and not a value of ProviderRoute.region. product.supplier.cloudflare_r2 -// mints a ProviderRoute only in the read arm; Automatic is excluded from that slot. Treating -// R2JurisdictionDefault, a dashboard Location label, Create Bucket locationHint, or Get Bucket -// location as interchangeable is the section 3 fork this row exists to keep unusable: requested -// placement, reported location, and residency guarantee are three facts. Automatic is not an arm -// of R2Jurisdiction — that type's corresponding non-guarantee is R2JurisdictionDefault, owned by -// extdeps.cloudflare.r2. -type R2PlacementModeRow { - reading: CloudflarePublishedReading -} - -data r2_placement_automatic: R2PlacementModeRow = R2PlacementModeRow { - reading: r2_data_location_reading, -} diff --git a/dag/gunbc/extdeps_scope_frontier.dag b/dag/gunbc/extdeps_scope_frontier.dag index ec7d5b6e659..a5256db3b1f 100644 --- a/dag/gunbc/extdeps_scope_frontier.dag +++ b/dag/gunbc/extdeps_scope_frontier.dag @@ -496,7 +496,6 @@ data scope_carrier_paths: List = [ "dag/extdeps/cloudflare/client_v4.dag", "dag/extdeps/cloudflare/account_api_tokens.dag", "dag/extdeps/cloudflare/r2.dag", - "dag/extdeps/cloudflare/r2_data_location.dag", "dag/extdeps/deepseek/deepseek_v4_1_flash.dag", "dag/extdeps/docker/images/gitcommit90_glm_53_one_spark.dag", "dag/extdeps/docker/images/timothystewart6_vllm_gb10.dag", diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag index e9a2d8afa82..b77a61b86ea 100644 --- a/dag/gunbc/product/supplier/cloudflare_r2.dag +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -2,7 +2,7 @@ module product.supplier.cloudflare_r2 import std.types { List, NonEmptyStr } import std.decl_ref { DeclarationRef, decl_ref } -import std.content_hash { as_content_hash_structural, content_hash_atom } +import std.content_hash { as_content_hash_structural } import product.fabric.provider_route { ProviderRoute, ProviderRouteFacts, ProviderDataPathClosure, ProviderPathUnread, @@ -11,13 +11,14 @@ import product.fabric.provider_route { ProviderRouteStanding, ProviderRouteObserved, ProviderRouteRegionUnobserved, provider_route_from_region, } +import extdeps.cloudflare.r2 { r2_published_location_readings } // THE DURABLE-ORIGIN THIS REPOSITORY ANSWERS THE NINE-PATH CLOSURE FOR. PRODUCTION DOES NOT MINT A ROUTE. // // WHAT WAS READ. Cloudflare's R2 data-location page, how-R2-works page, us-jurisdiction changelog, // tokens page, subprocessors list, Customer DPA v6.4 (2026-09-12), and the Create Bucket / // Get Bucket API method pages (2026-09-13) were transcribed in -// extdeps.cloudflare.r2_data_location. The durable origin in this fleet +// extdeps.cloudflare.r2. The durable origin in this fleet // (gunbc.cloudflare.r2_origin fabric_durable_origin_standing, bucket gunbai-fabric-origin) carries // R2JurisdictionDefault. That module already states that Default is not a data-residency // commitment this fleet has made. Create Bucket's locationHint is a requested placement; Get @@ -35,7 +36,7 @@ import product.fabric.provider_route { // // THE REGION SLOT IS NOT A PLACE TO RECORD AUTOMATIC. product.fabric.provider_route says the // cited region is where the work actually runs, observed at a declared boundary and never -// fabricated. r2_placement_automatic is a CHOICE MECHANISM. product.supplier.ubicloud already +// fabricated. Automatic placement, as transcribed in r2_data_location_reading, is a CHOICE MECHANISM. product.supplier.ubicloud already // ruled that shape out: a ProviderRoute is minted ONLY from a read region. fn cloudflare_r2_provider_ref() -> DeclarationRef { @@ -72,19 +73,19 @@ fn cloudflare_r2_durable_origin_route_standing() -> ProviderRouteStanding { // question this obligation exists to close stays open — the same defect as a trigger retired by // affordability alone when the real requirement was affordability AND a passing check. Either // alone is therefore not a resolution. -data cloudflare_r2_execution_location_obligation: NonEmptyStr = "Where R2 executes object operations for a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2_data_location r2_how_r2_works_reading states that the R2 Gateway is deployed across Cloudflare's global network via Cloudflare Workers, close to the user, and that the Gateway then writes to a storage cluster within the location set for the bucket. That is an architecture of a CHOICE, not a location of this fleet's bucket. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — a Cloudflare statement that names who handles requests for a named default-jurisdiction bucket and the jurisdiction of that handling. Naming an operating entity without a jurisdiction, or a jurisdiction without an operator, does not close this path. It is NOT resolved by R2JurisdictionDefault, by Automatic placement, by Create Bucket locationHint, or by an unqueried Get Bucket location." +data cloudflare_r2_execution_location_obligation: NonEmptyStr = "Where R2 executes object operations for a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2 r2_how_r2_works_reading states that the R2 Gateway is deployed across Cloudflare's global network via Cloudflare Workers, close to the user, and that the Gateway then writes to a storage cluster within the location set for the bucket. That is an architecture of a CHOICE, not a location of this fleet's bucket. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — a Cloudflare statement that names who handles requests for a named default-jurisdiction bucket and the jurisdiction of that handling. Naming an operating entity without a jurisdiction, or a jurisdiction without an operator, does not close this path. It is NOT resolved by R2JurisdictionDefault, by Automatic placement, by Create Bucket locationHint, or by an unqueried Get Bucket location." data cloudflare_r2_durable_storage_location_obligation: NonEmptyStr = "Where objects in this fleet's durable origin are stored is UNREAD. gunbc.cloudflare.r2_origin fabric_durable_origin_standing places bucket gunbai-fabric-origin under R2JurisdictionDefault. Requested placement, reported location, and residency guarantee are three facts: Create Bucket locationHint (r2_create_bucket_location_hint_reading) is requested placement; Get Bucket location (r2_get_bucket_location_reading) is reported location; Jurisdictional Restrictions / the Get Bucket jurisdiction field are the guarantee that objects are stored and processed within a jurisdiction. This repository has not queried gunbai-fabric-origin, so no Get Bucket location is an observation of ours. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — recreating the origin under a Jurisdictional Restriction that names a jurisdiction, or a Cloudflare statement that objects in gunbai-fabric-origin are stored and processed within a named jurisdiction by a named operator. A reported location is not that guarantee and is not the nine-path closure. It is NOT resolved by Create Bucket locationHint, by treating Get Bucket location as a hint, or by treating R2JurisdictionDefault as residency." -data cloudflare_r2_backups_location_obligation: NonEmptyStr = "Where R2 replicates objects for durability on a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2_data_location r2_how_r2_works_reading states that encrypted data is replicated within the region (e.g. ENAM) for durability, and it names no region for a default-jurisdiction bucket and no country for that replication. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — a Cloudflare statement of the operator and the region or jurisdiction inside which objects of a named default-jurisdiction bucket are replicated. It is NOT resolved by the example token ENAM in that sentence." +data cloudflare_r2_backups_location_obligation: NonEmptyStr = "Where R2 replicates objects for durability on a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2 r2_how_r2_works_reading states that encrypted data is replicated within the region (e.g. ENAM) for durability, and it names no region for a default-jurisdiction bucket and no country for that replication. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — a Cloudflare statement of the operator and the region or jurisdiction inside which objects of a named default-jurisdiction bucket are replicated. It is NOT resolved by the example token ENAM in that sentence." -data cloudflare_r2_logs_location_obligation: NonEmptyStr = "Where R2 or the Cloudflare platform stores logs of access to a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2_data_location r2_data_location_reading states that Logpush does not interact with R2 resources with assigned jurisdictions, which is a fact about jurisdictional buckets and does not say where logs of a default-jurisdiction bucket go, nor that no such logs exist. THE ABSENT ARM IS DELIBERATELY NOT TAKEN. RESOLVED BY a Cloudflare statement about logging of R2 object access, in either direction: an explicit none makes this path Absent with that document as evidence, and a described store makes it Located with evidence sufficient for OPERATOR AND JURISDICTION both." +data cloudflare_r2_logs_location_obligation: NonEmptyStr = "Where R2 or the Cloudflare platform stores logs of access to a default-jurisdiction bucket is UNREAD. extdeps.cloudflare.r2 r2_data_location_reading states that Logpush does not interact with R2 resources with assigned jurisdictions, which is a fact about jurisdictional buckets and does not say where logs of a default-jurisdiction bucket go, nor that no such logs exist. THE ABSENT ARM IS DELIBERATELY NOT TAKEN. RESOLVED BY a Cloudflare statement about logging of R2 object access, in either direction: an explicit none makes this path Absent with that document as evidence, and a described store makes it Located with evidence sufficient for OPERATOR AND JURISDICTION both." data cloudflare_r2_telemetry_location_obligation: NonEmptyStr = "Whether Cloudflare collects telemetry about a default-jurisdiction R2 bucket, what it carries, and where it goes, is UNREAD. Nothing in the documents read on 2026-09-12 describes a telemetry or usage-reporting path for R2 object storage as a located destination. THE ABSENT ARM IS DELIBERATELY NOT TAKEN: silence is not a denial. RESOLVED BY a Cloudflare statement about R2 telemetry, in either direction, sufficient for OPERATOR AND JURISDICTION both when the arm is Located." data cloudflare_r2_control_plane_location_obligation: NonEmptyStr = "Where the R2 control plane -- the Dashboard, the S3 API, the REST API that powers Wrangler, and the Metadata Service -- runs for a default-jurisdiction bucket, and under whose jurisdiction, is UNREAD. r2_how_r2_works_reading places the Gateway on the global network and the Metadata Service on Durable Objects and names no country for either. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both. Naming an operating entity without a jurisdiction, or a jurisdiction without an operator, does not close this path." -data cloudflare_r2_support_access_obligation: NonEmptyStr = "From which jurisdiction Cloudflare support reaches a default-jurisdiction R2 bucket is UNREAD. extdeps.cloudflare.r2_data_location cloudflare_subprocessors_reading names Slack, Zendesk and Salesforce for customer support, with locations that include the United States and, for Zendesk, also the EEA, Japan and Australia. That is a company-wide support-tool list, not a statement that support access to THIS bucket's objects is exercised from those places or that it is not. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — a Cloudflare statement of where support access to a given R2 bucket's objects is exercised from and by whom." +data cloudflare_r2_support_access_obligation: NonEmptyStr = "From which jurisdiction Cloudflare support reaches a default-jurisdiction R2 bucket is UNREAD. extdeps.cloudflare.r2 cloudflare_subprocessors_reading names Slack, Zendesk and Salesforce for customer support, with locations that include the United States and, for Zendesk, also the EEA, Japan and Australia. That is a company-wide support-tool list, not a statement that support access to THIS bucket's objects is exercised from those places or that it is not. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — a Cloudflare statement of where support access to a given R2 bucket's objects is exercised from and by whom." data cloudflare_r2_administrative_access_obligation: NonEmptyStr = "From which jurisdiction administrative access to a default-jurisdiction R2 bucket is exercised is UNREAD. The subprocessors page states that Cloudflare Group companies may be sub-processors because employees of those affiliates may need to provide account and engineering support, and it lists subsidiaries in the United Kingdom, Singapore, Australia, Germany, Portugal, France, Japan, Canada, the Netherlands, the U.A.E., India, the United States, South Korea, Mexico, Malaysia, Sweden and Switzerland. That names WHO may provide support, not FROM WHERE administrative access to this bucket is exercised, and it does not locate this bucket. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both." @@ -133,11 +134,11 @@ fn cloudflare_r2_downstream() -> DownstreamProviderPopulation { fn cloudflare_r2_facts(route: ProviderRoute) -> ProviderRouteFacts { ProviderRouteFacts { route: route, - contract_terms: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_customer_dpa_reading"), + contract_terms: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "cloudflare_customer_dpa_reading"), data_paths: cloudflare_r2_data_paths(), downstream: cloudflare_r2_downstream(), observed_at: "2026-09-12T00:00:00Z", - facts_revision: as_content_hash_structural(structural: content_hash_atom(value: "product.supplier.cloudflare_r2.durable-origin-route-facts.2026-09-12" as NonEmptyStr)), + facts_revision: as_content_hash_structural(structural: r2_published_location_readings()), } } diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag index 36aa38d1b6d..3d55c0010ae 100644 --- a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -230,7 +230,7 @@ fn t_synthetic_downstream() -> DownstreamProviderPopulation { fn t_facts_with_durable_storage(route: ProviderRoute, storage: ProviderPathStanding) -> ProviderRouteFacts { ProviderRouteFacts { route: route, - contract_terms: decl_ref(module_path: "extdeps.cloudflare.r2_data_location", decl_name: "cloudflare_customer_dpa_reading"), + contract_terms: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "cloudflare_customer_dpa_reading"), data_paths: t_paths_with_durable_storage(storage: storage), downstream: t_synthetic_downstream(), observed_at: "2026-09-12T00:00:00Z", From b6ea8de1d474627b5326e58bb4286b66f8bfb4a9 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 09:34:50 +0000 Subject: [PATCH 19/25] Hash location readings as a structural digest, not as a list. as_content_hash_structural takes Fnv1a64Structural; passing the reading roster there would not typecheck when the floor lane actually runs. Co-authored-by: Cursor --- dag/gunbc/product/supplier/cloudflare_r2.dag | 23 ++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag index b77a61b86ea..3bdb4fd9ec5 100644 --- a/dag/gunbc/product/supplier/cloudflare_r2.dag +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -2,7 +2,7 @@ module product.supplier.cloudflare_r2 import std.types { List, NonEmptyStr } import std.decl_ref { DeclarationRef, decl_ref } -import std.content_hash { as_content_hash_structural } +import std.content_hash { as_content_hash_structural, content_hash_atom, content_hash_combine_structural, Fnv1a64Structural } import product.fabric.provider_route { ProviderRoute, ProviderRouteFacts, ProviderDataPathClosure, ProviderPathUnread, @@ -131,6 +131,25 @@ fn cloudflare_r2_downstream() -> DownstreamProviderPopulation { } } +fn cloudflare_r2_location_readings_digest() -> Fnv1a64Structural { + fold( + r2_published_location_readings(), + init: content_hash_atom(value: "product.supplier.cloudflare_r2.location-readings" as NonEmptyStr), + f: fn(acc, reading) { + content_hash_combine_structural( + left: acc, + right: content_hash_combine_structural( + left: content_hash_atom(value: reading.authority.decl_name), + right: content_hash_combine_structural( + left: content_hash_atom(value: reading.read_on), + right: content_hash_atom(value: reading.statement), + ), + ), + ) + }, + ) +} + fn cloudflare_r2_facts(route: ProviderRoute) -> ProviderRouteFacts { ProviderRouteFacts { route: route, @@ -138,7 +157,7 @@ fn cloudflare_r2_facts(route: ProviderRoute) -> ProviderRouteFacts { data_paths: cloudflare_r2_data_paths(), downstream: cloudflare_r2_downstream(), observed_at: "2026-09-12T00:00:00Z", - facts_revision: as_content_hash_structural(structural: r2_published_location_readings()), + facts_revision: as_content_hash_structural(structural: cloudflare_r2_location_readings_digest()), } } From e654fe7a0470bd1b02502d56d38a691818c095d4 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 09:38:13 +0000 Subject: [PATCH 20/25] Put company DPA and subprocessors on the vendor, not under R2S3Endpoint. CloudflarePublishedReading reminted the as-of carrier the tokens-doc frontier already named; transcriptions are now cited NonEmptyStr rows with FactCitation, and the tokens as-of pin is hashed by the facts digest. Co-authored-by: Cursor --- dag/extdeps/cloudflare/r2.dag | 152 +++++++++--------- dag/extdeps/vendor/cloudflare.dag | 56 ++++++- dag/gunbc/product/supplier/cloudflare_r2.dag | 39 +++-- .../cloudflare_r2_route_witness_test.dag | 2 +- 4 files changed, 158 insertions(+), 91 deletions(-) diff --git a/dag/extdeps/cloudflare/r2.dag b/dag/extdeps/cloudflare/r2.dag index 9ed30558cfa..16d32937f71 100644 --- a/dag/extdeps/cloudflare/r2.dag +++ b/dag/extdeps/cloudflare/r2.dag @@ -52,20 +52,6 @@ data r2_us_jurisdiction_changelog_authority: ExternalAuthority = ExternalAuthori } } -data cloudflare_subprocessors_authority: ExternalAuthority = ExternalAuthority { - uri: Uri { - scheme: Https - locator: "www.cloudflare.com/gdpr/subprocessors/cloudflare-services" - } -} - -data cloudflare_customer_dpa_authority: ExternalAuthority = ExternalAuthority { - uri: Uri { - scheme: Https - locator: "cf-assets.www.cloudflare.com/slt3lc6tev37/1TTgT35GoUNlKZYGuKWBFy/4e7dfc8cf402419a9b1cf624291fc69f/cloudflare_customer_dpa-v6.4_april_3_2026.pdf" - } -} - data r2_create_bucket_authority: ExternalAuthority = ExternalAuthority { uri: Uri { scheme: Https @@ -153,8 +139,6 @@ data extdeps_model_scope: ExternalModelScope = ExternalModelScope { r2_data_location_authority, r2_how_r2_works_authority, r2_us_jurisdiction_changelog_authority, - cloudflare_subprocessors_authority, - cloudflare_customer_dpa_authority, r2_create_bucket_authority, r2_get_bucket_authority, ] @@ -387,90 +371,115 @@ fn r2_object_url(locator: R2ObjectLocator) -> String { ) } -// LOCATION AND RESIDENCY READINGS FOR THIS SAME PRODUCT. They were briefly a second module +// LOCATION AND RESIDENCY TRANSCRIPTIONS FOR THIS SAME PRODUCT. They were briefly a second module // (extdeps.cloudflare.r2_data_location) whose subject was a wrapper around one reading. R2 is one // independently versioned product; DESIGN section 3's external-upstream rule does not mint a // second module authority per documentation page. The tokens-page default-jurisdiction sentence // cites this module's existing anchor rather than a parallel ExternalAuthority for the same URI. // -// EACH ROW CARRIES THE DOCUMENT, THE DATE IT WAS READ, AND THE SENTENCE IT WAS READ FOR. The -// statement field is a TRANSCRIPTION of upstream's own words, not commentary about them. A reading -// is dated and never silently refreshed: upstream edits a page without telling anyone, so a -// statement that no longer appears at its URI is a NEW reading with a later date. -type CloudflarePublishedReading { - authority: DeclarationRef - read_on: NonEmptyStr - statement: NonEmptyStr -} +// THERE IS NO CloudflarePublishedReading. Dated attestation is FactCitation (fact + authority); +// the transcription is the cited NonEmptyStr. A second as-of record would remint the carrier +// r2_tokens_doc_as_of's frontier already named. Company DPA and subprocessors live on +// extdeps.vendor.cloudflare, not under R2S3Endpoint. +data r2_data_location_reading: NonEmptyStr = "When you create a new bucket, the data location is set to Automatic by default. Currently, this option chooses a bucket location in the closest available region to the create bucket request based on the location of the caller. Location Hints are optional parameters you can provide during bucket creation to indicate the primary geographical location you expect data will be accessed from. Location Hints are a best effort and not a guarantee, and they should only be used as a way to optimize performance. Available hints: wnam Western North America, enam Eastern North America, weur Western Europe, eeur Eastern Europe, apac Asia-Pacific, oc Oceania. Jurisdictional Restrictions guarantee objects in a bucket are stored within a specific jurisdiction. Use Jurisdictional Restrictions when you need to ensure data is stored and processed within a jurisdiction to meet data residency requirements. Available jurisdictions: eu European Union, fedramp FedRAMP, us United States. The following services do not interact with R2 resources with assigned jurisdictions: Logpush. Once an R2 bucket is created, the jurisdiction cannot be changed. Page last updated Aug 19, 2026. Read 2026-09-12." -data r2_data_location_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_data_location_authority"), - read_on: "2026-09-12", - statement: "When you create a new bucket, the data location is set to Automatic by default. Currently, this option chooses a bucket location in the closest available region to the create bucket request based on the location of the caller. Location Hints are optional parameters you can provide during bucket creation to indicate the primary geographical location you expect data will be accessed from. Location Hints are a best effort and not a guarantee, and they should only be used as a way to optimize performance. Available hints: wnam Western North America, enam Eastern North America, weur Western Europe, eeur Eastern Europe, apac Asia-Pacific, oc Oceania. Jurisdictional Restrictions guarantee objects in a bucket are stored within a specific jurisdiction. Use Jurisdictional Restrictions when you need to ensure data is stored and processed within a jurisdiction to meet data residency requirements. Available jurisdictions: eu European Union, fedramp FedRAMP, us United States. The following services do not interact with R2 resources with assigned jurisdictions: Logpush. Once an R2 bucket is created, the jurisdiction cannot be changed. Page last updated Aug 19, 2026.", +data r2_data_location_citation: FactCitation = FactCitation { + fact: DeclarationRef { + module_path: "extdeps.cloudflare.r2", + decl_name: "r2_data_location_reading", + field: WholeDeclaration + }, + authority: r2_data_location_authority, } -data r2_how_r2_works_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_how_r2_works_authority"), - read_on: "2026-09-12", - statement: "R2 Gateway: The entry point for all API requests that handles authentication and routing logic. This service is deployed across Cloudflare's global network via Cloudflare Workers. Metadata Service: A distributed layer built on Durable Objects used to store and manage object metadata. Distributed Storage Infrastructure: The underlying infrastructure that persistently stores encrypted object data. On write, the Gateway determines which storage cluster to write the encrypted data to within the location set for the bucket. The encrypted data is written and stored in the distributed storage infrastructure, and replicated within the region (e.g. ENAM) for durability. On read, if the object is not in the tiered read cache, it retrieves the object from one of the distributed storage data centers within the region that holds the object data. Page last updated Apr 21, 2026.", -} +data r2_how_r2_works_reading: NonEmptyStr = "R2 Gateway: The entry point for all API requests that handles authentication and routing logic. This service is deployed across Cloudflare's global network via Cloudflare Workers. Metadata Service: A distributed layer built on Durable Objects used to store and manage object metadata. Distributed Storage Infrastructure: The underlying infrastructure that persistently stores encrypted object data. On write, the Gateway determines which storage cluster to write the encrypted data to within the location set for the bucket. The encrypted data is written and stored in the distributed storage infrastructure, and replicated within the region (e.g. ENAM) for durability. On read, if the object is not in the tiered read cache, it retrieves the object from one of the distributed storage data centers within the region that holds the object data. Page last updated Apr 21, 2026. Read 2026-09-12." -data r2_us_jurisdiction_changelog_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_us_jurisdiction_changelog_authority"), - read_on: "2026-09-12", - statement: "New us jurisdiction for R2. R2 now supports a us jurisdiction, which guarantees that bucket data is stored and processed within the United States. Use this jurisdiction when you need explicit US data residency guarantees. Use the jurisdiction-specific S3 endpoint https://.us.r2.cloudflarestorage.com. Once an R2 bucket is created, its jurisdiction cannot be changed. Posted 2026-08-17.", +data r2_how_r2_works_citation: FactCitation = FactCitation { + fact: DeclarationRef { + module_path: "extdeps.cloudflare.r2", + decl_name: "r2_how_r2_works_reading", + field: WholeDeclaration + }, + authority: r2_how_r2_works_authority, } -data r2_tokens_default_jurisdiction_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "extdeps_external_authority_anchor"), - read_on: "2026-09-12", - statement: "A specific bucket is represented as com.cloudflare.edge.r2.bucket.__. JURISDICTION: The jurisdiction where the R2 bucket lives. For buckets not created in a specific jurisdiction this value will be default.", -} +data r2_us_jurisdiction_changelog_reading: NonEmptyStr = "New us jurisdiction for R2. R2 now supports a us jurisdiction, which guarantees that bucket data is stored and processed within the United States. Use this jurisdiction when you need explicit US data residency guarantees. Use the jurisdiction-specific S3 endpoint https://.us.r2.cloudflarestorage.com. Once an R2 bucket is created, its jurisdiction cannot be changed. Posted 2026-08-17. Read 2026-09-12." -data cloudflare_subprocessors_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "cloudflare_subprocessors_authority"), - read_on: "2026-09-12", - statement: "Last Updated: October 1, 2025. Cloudflare uses a handful of sub-processors to support the Cloudflare service. Some of these sub-processors are members of the Cloudflare Group (Cloudflare, Inc. and its subsidiaries) and some are third parties. Third-party entities include Slack Technologies, Inc. (Customer support communications, United States); Zendesk, Inc. (Customer support and account management, United States, the European Economic Area, Japan, and Australia); Salesforce, Inc. (Customer support and account management, United States); Google LLC (Cloudflare Developer Platform, Cloudflare Zero Trust and AI Gateway; European Economic Area, United States, Australia, India); Oracle America, Inc. (Cloudflare Developer Platform and Cache Reserve; United States, European Economic Area, UK, Japan, Australia, Canada, Singapore); Amazon Web Services (Cloudflare Email Security; United States, European Economic Area); CoreWeave, Inc., Nebius BV (Workers AI); Anthropic PBC, OpenAI, Inc., X.AI Corp., Groq, Inc. (AI Gateway). The page lists Cloudflare Group subsidiaries by location.", +data r2_us_jurisdiction_changelog_citation: FactCitation = FactCitation { + fact: DeclarationRef { + module_path: "extdeps.cloudflare.r2", + decl_name: "r2_us_jurisdiction_changelog_reading", + field: WholeDeclaration + }, + authority: r2_us_jurisdiction_changelog_authority, } -data r2_create_bucket_location_hint_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_create_bucket_authority"), - read_on: "2026-09-13", - statement: "Create Bucket POST /accounts/{account_id}/r2/buckets. Body parameter locationHint, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Header cf-r2-jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13.", +data r2_tokens_default_jurisdiction_reading: NonEmptyStr = "A specific bucket is represented as com.cloudflare.edge.r2.bucket.__. JURISDICTION: The jurisdiction where the R2 bucket lives. For buckets not created in a specific jurisdiction this value will be default. Read 2026-09-12." + +data r2_tokens_default_jurisdiction_citation: FactCitation = FactCitation { + fact: DeclarationRef { + module_path: "extdeps.cloudflare.r2", + decl_name: "r2_tokens_default_jurisdiction_reading", + field: WholeDeclaration + }, + authority: extdeps_external_authority_anchor, } -data r2_get_bucket_location_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_get_bucket_authority"), - read_on: "2026-09-13", - statement: "Get Bucket GET /accounts/{account_id}/r2/buckets/{bucket_name}. Result field location, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Result field jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13.", +data r2_create_bucket_location_hint_reading: NonEmptyStr = "Create Bucket POST /accounts/{account_id}/r2/buckets. Body parameter locationHint, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Header cf-r2-jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13." + +data r2_create_bucket_location_hint_citation: FactCitation = FactCitation { + fact: DeclarationRef { + module_path: "extdeps.cloudflare.r2", + decl_name: "r2_create_bucket_location_hint_reading", + field: WholeDeclaration + }, + authority: r2_create_bucket_authority, } -data cloudflare_customer_dpa_reading: CloudflarePublishedReading = CloudflarePublishedReading { - authority: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "cloudflare_customer_dpa_authority"), - read_on: "2026-09-12", - statement: "Cloudflare, Inc. Data Processing Addendum, Version 6.4 April 3, 2026. The Customer grants a general written authorization: (a) to Cloudflare to appoint other members of the Cloudflare Group as sub-Processors, and (b) to Cloudflare and other members of the Cloudflare Group to appoint third party data center operators, and business, engineering and customer support providers as sub-Processors to support the performance of the Service. Cloudflare will maintain a list of sub-Processors at https://www.cloudflare.com/gdpr/subprocessors/. This DPA and any action related thereto shall be governed by and construed in accordance with the laws as specified in the Main Agreement, and the parties consent to the personal jurisdiction of, and venue in, the courts specified in the Main Agreement.", +data r2_get_bucket_location_reading: NonEmptyStr = "Get Bucket GET /accounts/{account_id}/r2/buckets/{bucket_name}. Result field location, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Result field jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13." + +data r2_get_bucket_location_citation: FactCitation = FactCitation { + fact: DeclarationRef { + module_path: "extdeps.cloudflare.r2", + decl_name: "r2_get_bucket_location_reading", + field: WholeDeclaration + }, + authority: r2_get_bucket_authority, } -// THE READINGS ARE ONE CLOSURE. product.supplier.cloudflare_r2 hashes this list into -// ProviderRouteFacts.facts_revision, so a changed transcription is a different facts row rather than -// a silent edit behind a pinned string. Automatic placement is recorded IN r2_data_location_reading; -// it is not a second model-scope subject and not a value of ProviderRoute.region. -fn r2_published_location_readings() -> List { +// THE READINGS ARE ONE CLOSURE. product.supplier.cloudflare_r2 hashes these lists (and +// r2_tokens_doc_as_of) into ProviderRouteFacts.facts_revision, so a changed transcription is a +// different facts row rather than a silent edit behind a pinned string. Automatic placement is +// recorded IN r2_data_location_reading; it is not a second model-scope subject and not a value of +// ProviderRoute.region. +fn r2_published_location_readings() -> List { [ r2_data_location_reading, r2_how_r2_works_reading, r2_us_jurisdiction_changelog_reading, r2_tokens_default_jurisdiction_reading, - cloudflare_subprocessors_reading, r2_create_bucket_location_hint_reading, r2_get_bucket_location_reading, - cloudflare_customer_dpa_reading, ] } +fn r2_published_location_citations() -> List { + [ + r2_data_location_citation, + r2_how_r2_works_citation, + r2_us_jurisdiction_changelog_citation, + r2_tokens_default_jurisdiction_citation, + r2_create_bucket_location_hint_citation, + r2_get_bucket_location_citation, + ] +} + + // THE r2_s3_endpoint_url ROW IS RETIRED: gunbc.cloudflare.r2_origin_object reaches it through // r2_object_url on the executing put_origin_object and fetch_origin_object entries, which is the -// consumer the row named. The list is the membership of what remains. +// consumer the row named. The list is the membership of what remains. r2_tokens_doc_as_of is +// consumed by product.supplier.cloudflare_r2 cloudflare_r2_location_readings_digest as the cited +// tokens-page date, which is the executing-fold dissolution the frontier row named. data cloudflare_r2_frontier_rows: List = [ frontier_row_decl( ref: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_account_resource_name"), @@ -478,12 +487,5 @@ data cloudflare_r2_frontier_rows: List = [ dissolution: unbound_dissolution( description: "dissolves when a gunbc declaration consumes r2_account_resource_name in an executing token policy or S3 IAM grant; a witness that the fold exists does not fire this" ) - ), - frontier_row_decl( - ref: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_tokens_doc_as_of"), - reason: "as-of pin is unread outside the claim witness; ExternalAuthority has no as-of field", - dissolution: unbound_dissolution( - description: "dissolves when ExternalAuthority or FactCitation carries an as-of date and this pin inhabits that field, or a gunbc executing fold reads r2_tokens_doc_as_of as the cited document date" - ) ) ] diff --git a/dag/extdeps/vendor/cloudflare.dag b/dag/extdeps/vendor/cloudflare.dag index 7f7eb6e7317..03abdacb9d1 100644 --- a/dag/extdeps/vendor/cloudflare.dag +++ b/dag/extdeps/vendor/cloudflare.dag @@ -1,10 +1,11 @@ module extdeps.vendor.cloudflare +import std.types { NonEmptyStr, List } import std.decl_ref { DeclarationRef, WholeDeclaration } import extdeps.vendor { Vendor } import extdeps.securities { Securities } -import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef } +import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef, FactCitation } import extdeps.uri { Uri, Https } data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { @@ -14,6 +15,20 @@ data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority { } } +data cloudflare_subprocessors_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "www.cloudflare.com/gdpr/subprocessors/cloudflare-services" + } +} + +data cloudflare_customer_dpa_authority: ExternalAuthority = ExternalAuthority { + uri: Uri { + scheme: Https + locator: "cf-assets.www.cloudflare.com/slt3lc6tev37/1TTgT35GoUNlKZYGuKWBFy/4e7dfc8cf402419a9b1cf624291fc69f/cloudflare_customer_dpa-v6.4_april_3_2026.pdf" + } +} + data extdeps_model_scope: ExternalModelScope = ExternalModelScope { subject: ExternalSubjectRef { declaration: DeclarationRef { @@ -23,7 +38,44 @@ data extdeps_model_scope: ExternalModelScope = ExternalModelScope { } }, first_citation: extdeps.vendor.cloudflare.extdeps_external_authority_anchor, - further_citations: [] + further_citations: [ + cloudflare_subprocessors_authority, + cloudflare_customer_dpa_authority, + ] } data cloudflare: Vendor = Vendor { legal_name: "Cloudflare, Inc." } + +// COMPANY DOCUMENTS, NOT R2 PRODUCT FACTS. The Customer DPA and the subprocessors table are +// independently versioned on Cloudflare's company cadence. They sit on this vendor subject so a +// Workers or Zero Trust module does not import extdeps.cloudflare.r2 for a company fact, and so an +// R2 change does not rewrite them. +data cloudflare_subprocessors_reading: NonEmptyStr = "Last Updated: October 1, 2025. Cloudflare uses a handful of sub-processors to support the Cloudflare service. Some of these sub-processors are members of the Cloudflare Group (Cloudflare, Inc. and its subsidiaries) and some are third parties. Third-party entities include Slack Technologies, Inc. (Customer support communications, United States); Zendesk, Inc. (Customer support and account management, United States, the European Economic Area, Japan, and Australia); Salesforce, Inc. (Customer support and account management, United States); Google LLC (Cloudflare Developer Platform, Cloudflare Zero Trust and AI Gateway; European Economic Area, United States, Australia, India); Oracle America, Inc. (Cloudflare Developer Platform and Cache Reserve; United States, European Economic Area, UK, Japan, Australia, Canada, Singapore); Amazon Web Services (Cloudflare Email Security; United States, European Economic Area); CoreWeave, Inc., Nebius BV (Workers AI); Anthropic PBC, OpenAI, Inc., X.AI Corp., Groq, Inc. (AI Gateway). The page lists Cloudflare Group subsidiaries by location." + +data cloudflare_subprocessors_citation: FactCitation = FactCitation { + fact: DeclarationRef { + module_path: "extdeps.vendor.cloudflare", + decl_name: "cloudflare_subprocessors_reading", + field: WholeDeclaration + }, + authority: cloudflare_subprocessors_authority, +} + +data cloudflare_customer_dpa_reading: NonEmptyStr = "Cloudflare, Inc. Data Processing Addendum, Version 6.4 April 3, 2026. The Customer grants a general written authorization: (a) to Cloudflare to appoint other members of the Cloudflare Group as sub-Processors, and (b) to Cloudflare and other members of the Cloudflare Group to appoint third party data center operators, and business, engineering and customer support providers as sub-Processors to support the performance of the Service. Cloudflare will maintain a list of sub-Processors at https://www.cloudflare.com/gdpr/subprocessors/. This DPA and any action related thereto shall be governed by and construed in accordance with the laws as specified in the Main Agreement, and the parties consent to the personal jurisdiction of, and venue in, the courts specified in the Main Agreement." + +data cloudflare_customer_dpa_citation: FactCitation = FactCitation { + fact: DeclarationRef { + module_path: "extdeps.vendor.cloudflare", + decl_name: "cloudflare_customer_dpa_reading", + field: WholeDeclaration + }, + authority: cloudflare_customer_dpa_authority, +} + +fn cloudflare_company_document_readings() -> List { + [cloudflare_subprocessors_reading, cloudflare_customer_dpa_reading] +} + +fn cloudflare_company_document_citations() -> List { + [cloudflare_subprocessors_citation, cloudflare_customer_dpa_citation] +} diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag index 3bdb4fd9ec5..80dbef9e372 100644 --- a/dag/gunbc/product/supplier/cloudflare_r2.dag +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -11,7 +11,15 @@ import product.fabric.provider_route { ProviderRouteStanding, ProviderRouteObserved, ProviderRouteRegionUnobserved, provider_route_from_region, } -import extdeps.cloudflare.r2 { r2_published_location_readings } +import extdeps.cloudflare.r2 { + r2_published_location_readings, + r2_published_location_citations, + r2_tokens_doc_as_of, +} +import extdeps.vendor.cloudflare { + cloudflare_company_document_readings, + cloudflare_company_document_citations, +} // THE DURABLE-ORIGIN THIS REPOSITORY ANSWERS THE NINE-PATH CLOSURE FOR. PRODUCTION DOES NOT MINT A ROUTE. // @@ -85,7 +93,7 @@ data cloudflare_r2_telemetry_location_obligation: NonEmptyStr = "Whether Cloudfl data cloudflare_r2_control_plane_location_obligation: NonEmptyStr = "Where the R2 control plane -- the Dashboard, the S3 API, the REST API that powers Wrangler, and the Metadata Service -- runs for a default-jurisdiction bucket, and under whose jurisdiction, is UNREAD. r2_how_r2_works_reading places the Gateway on the global network and the Metadata Service on Durable Objects and names no country for either. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both. Naming an operating entity without a jurisdiction, or a jurisdiction without an operator, does not close this path." -data cloudflare_r2_support_access_obligation: NonEmptyStr = "From which jurisdiction Cloudflare support reaches a default-jurisdiction R2 bucket is UNREAD. extdeps.cloudflare.r2 cloudflare_subprocessors_reading names Slack, Zendesk and Salesforce for customer support, with locations that include the United States and, for Zendesk, also the EEA, Japan and Australia. That is a company-wide support-tool list, not a statement that support access to THIS bucket's objects is exercised from those places or that it is not. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — a Cloudflare statement of where support access to a given R2 bucket's objects is exercised from and by whom." +data cloudflare_r2_support_access_obligation: NonEmptyStr = "From which jurisdiction Cloudflare support reaches a default-jurisdiction R2 bucket is UNREAD. extdeps.vendor.cloudflare cloudflare_subprocessors_reading names Slack, Zendesk and Salesforce for customer support, with locations that include the United States and, for Zendesk, also the EEA, Japan and Australia. That is a company-wide support-tool list, not a statement that support access to THIS bucket's objects is exercised from those places or that it is not. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both — a Cloudflare statement of where support access to a given R2 bucket's objects is exercised from and by whom." data cloudflare_r2_administrative_access_obligation: NonEmptyStr = "From which jurisdiction administrative access to a default-jurisdiction R2 bucket is exercised is UNREAD. The subprocessors page states that Cloudflare Group companies may be sub-processors because employees of those affiliates may need to provide account and engineering support, and it lists subsidiaries in the United Kingdom, Singapore, Australia, Germany, Portugal, France, Japan, Canada, the Netherlands, the U.A.E., India, the United States, South Korea, Mexico, Malaysia, Sweden and Switzerland. That names WHO may provide support, not FROM WHERE administrative access to this bucket is exercised, and it does not locate this bucket. RESOLVED BY evidence sufficient for this path's OPERATOR AND JURISDICTION both." @@ -132,28 +140,33 @@ fn cloudflare_r2_downstream() -> DownstreamProviderPopulation { } fn cloudflare_r2_location_readings_digest() -> Fnv1a64Structural { - fold( - r2_published_location_readings(), + let after_statements = fold( + concat([r2_published_location_readings(), cloudflare_company_document_readings()]), init: content_hash_atom(value: "product.supplier.cloudflare_r2.location-readings" as NonEmptyStr), - f: fn(acc, reading) { + f: fn(acc, statement) { + content_hash_combine_structural(left: acc, right: content_hash_atom(value: statement)) + }, + ) + let after_citations = fold( + concat([r2_published_location_citations(), cloudflare_company_document_citations()]), + init: after_statements, + f: fn(acc, citation) { content_hash_combine_structural( left: acc, - right: content_hash_combine_structural( - left: content_hash_atom(value: reading.authority.decl_name), - right: content_hash_combine_structural( - left: content_hash_atom(value: reading.read_on), - right: content_hash_atom(value: reading.statement), - ), - ), + right: content_hash_atom(value: citation.authority.uri.locator as NonEmptyStr), ) }, ) + content_hash_combine_structural( + left: after_citations, + right: content_hash_atom(value: r2_tokens_doc_as_of as NonEmptyStr), + ) } fn cloudflare_r2_facts(route: ProviderRoute) -> ProviderRouteFacts { ProviderRouteFacts { route: route, - contract_terms: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "cloudflare_customer_dpa_reading"), + contract_terms: decl_ref(module_path: "extdeps.vendor.cloudflare", decl_name: "cloudflare_customer_dpa_reading"), data_paths: cloudflare_r2_data_paths(), downstream: cloudflare_r2_downstream(), observed_at: "2026-09-12T00:00:00Z", diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag index 3d55c0010ae..26c616d3f2f 100644 --- a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -230,7 +230,7 @@ fn t_synthetic_downstream() -> DownstreamProviderPopulation { fn t_facts_with_durable_storage(route: ProviderRoute, storage: ProviderPathStanding) -> ProviderRouteFacts { ProviderRouteFacts { route: route, - contract_terms: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "cloudflare_customer_dpa_reading"), + contract_terms: decl_ref(module_path: "extdeps.vendor.cloudflare", decl_name: "cloudflare_customer_dpa_reading"), data_paths: t_paths_with_durable_storage(storage: storage), downstream: t_synthetic_downstream(), observed_at: "2026-09-12T00:00:00Z", From 9248e4d44c46be71ebc3bc3fdfcd7291b4624591 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 10:04:18 +0000 Subject: [PATCH 21/25] Call list concat as two arguments, not as a list of lists. The digest fold was the only consumer that mixed R2 and vendor transcriptions; a single-argument concat would not join them. Co-authored-by: Cursor --- dag/gunbc/product/supplier/cloudflare_r2.dag | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag index 80dbef9e372..dd1e057a5d8 100644 --- a/dag/gunbc/product/supplier/cloudflare_r2.dag +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -141,14 +141,14 @@ fn cloudflare_r2_downstream() -> DownstreamProviderPopulation { fn cloudflare_r2_location_readings_digest() -> Fnv1a64Structural { let after_statements = fold( - concat([r2_published_location_readings(), cloudflare_company_document_readings()]), + concat(r2_published_location_readings(), cloudflare_company_document_readings()), init: content_hash_atom(value: "product.supplier.cloudflare_r2.location-readings" as NonEmptyStr), f: fn(acc, statement) { content_hash_combine_structural(left: acc, right: content_hash_atom(value: statement)) }, ) let after_citations = fold( - concat([r2_published_location_citations(), cloudflare_company_document_citations()]), + concat(r2_published_location_citations(), cloudflare_company_document_citations()), init: after_statements, f: fn(acc, citation) { content_hash_combine_structural( From 7f72e46d098d140d7407d8c1dbdd02bdfe10e387 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 10:48:54 +0000 Subject: [PATCH 22/25] Match the three ProviderUseRefusal arms #11194 added. A catch-all would swallow the next growth of this coproduct; each arm stays explicit, same as the admission witness. Co-authored-by: Cursor --- .../supplier/cloudflare_r2_route_witness_test.dag | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag index 26c616d3f2f..12b10fce145 100644 --- a/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag +++ b/dag/test/claim/supplier/cloudflare_r2_route_witness_test.dag @@ -10,6 +10,7 @@ import product.fabric.provider_route { ProviderPathUnread, DownstreamProviderPopulation, NoDownstreamProviders, ProviderRegionObservation, ProviderRegionRead, ProviderRouteObserved, ProviderRouteRegionUnobserved, + PermittedJurisdictionsEnumerated, } import product.fabric.provider_admission { RouteScopeSanction, ProviderUseScope, ProviderUseAdmission, @@ -17,6 +18,7 @@ import product.fabric.provider_admission { ProviderRouteUnclassified, ProviderRouteFactsIncomplete, DownstreamProviderUnassessed, PostureRevisionStale, CustomerScopeUnsupported, DataHandlingUnsupported, RequiredAgreementAuthorityAbsent, ProhibitedUseNotCleared, SanctionsNotCleared, ExportNotCleared, + PostureJurisdictionsUnread, TransferOrLocationUnresolved, ProviderAccessPathUnsupported, DispositionCleared, admit_provider_use, } @@ -54,6 +56,11 @@ fn t_posture() -> CompliancePostureRevision { CompliancePostureRevision { authority: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_posture_authority"), revision: as_content_hash_structural(structural: content_hash_atom(value: "r2-witness-posture-r1" as NonEmptyStr)), + permitted_jurisdictions: PermittedJurisdictionsEnumerated { + first: decl_ref(module_path: "test.claim.supplier.cloudflare_r2_route_witness", decl_name: "r2_witness_resolved_jurisdiction"), + further: [], + }, + jurisdiction_drop_enrollments: [], } } @@ -132,6 +139,9 @@ fn t_refusal_tag(c: ProviderUseRefusal) -> String { ProviderRouteUnclassified { route } => "route-unclassified", ProviderRouteFactsIncomplete { route, obligation } => "facts-incomplete", DownstreamProviderUnassessed { obligation } => "downstream-unassessed", + PostureJurisdictionsUnread { obligation } => "posture-jurisdictions-unread", + TransferOrLocationUnresolved { route, jurisdiction } => "transfer-or-location-unresolved", + ProviderAccessPathUnsupported { route, operator, jurisdiction } => "provider-access-path-unsupported", PostureRevisionStale { evaluated, active } => "posture-stale", CustomerScopeUnsupported { cause } => "customer-unsupported", DataHandlingUnsupported { cause } => "data-handling-unsupported", @@ -147,6 +157,9 @@ fn t_refusal_located(c: ProviderUseRefusal) -> List { ProviderRouteUnclassified { route } => [], ProviderRouteFactsIncomplete { route, obligation } => [obligation], DownstreamProviderUnassessed { obligation } => [obligation], + PostureJurisdictionsUnread { obligation } => [obligation], + TransferOrLocationUnresolved { route, jurisdiction } => [jurisdiction], + ProviderAccessPathUnsupported { route, operator, jurisdiction } => [operator, jurisdiction], PostureRevisionStale { evaluated, active } => [], CustomerScopeUnsupported { cause } => [cause], DataHandlingUnsupported { cause } => [cause], From ecba73bab64601fc25db7c89d7503164bb9d2b63 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 11:16:51 +0000 Subject: [PATCH 23/25] Escape braces in Create/Get Bucket path transcriptions. .dag string bodies interpolate {name}; the corpus already writes \{account_id\} on the tokens API paths. Co-authored-by: Cursor --- dag/extdeps/cloudflare/r2.dag | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dag/extdeps/cloudflare/r2.dag b/dag/extdeps/cloudflare/r2.dag index 16d32937f71..8fd9d268064 100644 --- a/dag/extdeps/cloudflare/r2.dag +++ b/dag/extdeps/cloudflare/r2.dag @@ -425,7 +425,7 @@ data r2_tokens_default_jurisdiction_citation: FactCitation = FactCitation { authority: extdeps_external_authority_anchor, } -data r2_create_bucket_location_hint_reading: NonEmptyStr = "Create Bucket POST /accounts/{account_id}/r2/buckets. Body parameter locationHint, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Header cf-r2-jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13." +data r2_create_bucket_location_hint_reading: NonEmptyStr = "Create Bucket POST /accounts/\{account_id\}/r2/buckets. Body parameter locationHint, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Header cf-r2-jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13." data r2_create_bucket_location_hint_citation: FactCitation = FactCitation { fact: DeclarationRef { @@ -436,7 +436,7 @@ data r2_create_bucket_location_hint_citation: FactCitation = FactCitation { authority: r2_create_bucket_authority, } -data r2_get_bucket_location_reading: NonEmptyStr = "Get Bucket GET /accounts/{account_id}/r2/buckets/{bucket_name}. Result field location, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Result field jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13." +data r2_get_bucket_location_reading: NonEmptyStr = "Get Bucket GET /accounts/\{account_id\}/r2/buckets/\{bucket_name\}. Result field location, optional, one of apac, eeur, enam, weur, wnam, oc, described as Location of the bucket. Result field jurisdiction, optional, one of default, eu, us, fedramp, fedramp-high, described as Jurisdiction where objects in this bucket are guaranteed to be stored. Read 2026-09-13." data r2_get_bucket_location_citation: FactCitation = FactCitation { fact: DeclarationRef { From d1c4f4dd76554d3c04c29643390eb7263eae1f5b Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 11:45:47 +0000 Subject: [PATCH 24/25] Model fedramp-high and enroll the R2 facts-population frontier. The Create/Get Bucket transcriptions already named five jurisdiction wires; the closed coproduct stopped at four, so a fedramp-high bucket had no host. The declared 3c consumer of the empty production facts list was only a comment. Co-authored-by: Cursor --- dag/extdeps/cloudflare/r2.dag | 5 ++++ dag/gunbc/census_closure_frontier.dag | 2 ++ dag/gunbc/cloudflare/r2_origin.dag | 2 +- dag/gunbc/product/supplier/cloudflare_r2.dag | 18 ++++++++++----- ...oudflare_r2_origin_object_witness_test.dag | 20 ++++++++++++++++ .../cloudflare_r2_token_witness_test.dag | 23 +++++++++++++++++++ 6 files changed, 63 insertions(+), 7 deletions(-) diff --git a/dag/extdeps/cloudflare/r2.dag b/dag/extdeps/cloudflare/r2.dag index 8fd9d268064..599f29d4248 100644 --- a/dag/extdeps/cloudflare/r2.dag +++ b/dag/extdeps/cloudflare/r2.dag @@ -143,10 +143,13 @@ data extdeps_model_scope: ExternalModelScope = ExternalModelScope { r2_get_bucket_authority, ] } +// THE FIVE ARMS ARE THE CREATE/GET BUCKET JURISDICTION VALUE SET (r2_create_bucket_location_hint_reading, +// r2_get_bucket_location_reading). Host suffixes follow the same wire token as eu/us/fedramp. type R2Jurisdiction = R2JurisdictionDefault | R2JurisdictionEu | R2JurisdictionFedramp + | R2JurisdictionFedrampHigh | R2JurisdictionUs fn r2_jurisdiction_wire(jurisdiction: R2Jurisdiction) -> String { @@ -154,6 +157,7 @@ fn r2_jurisdiction_wire(jurisdiction: R2Jurisdiction) -> String { R2JurisdictionDefault => "default" R2JurisdictionEu => "eu" R2JurisdictionFedramp => "fedramp" + R2JurisdictionFedrampHigh => "fedramp-high" R2JurisdictionUs => "us" } } @@ -168,6 +172,7 @@ fn r2_s3_endpoint_host(endpoint: R2S3Endpoint) -> String { R2JurisdictionDefault => join([endpoint.account_id, ".r2.cloudflarestorage.com"], "") R2JurisdictionEu => join([endpoint.account_id, ".eu.r2.cloudflarestorage.com"], "") R2JurisdictionFedramp => join([endpoint.account_id, ".fedramp.r2.cloudflarestorage.com"], "") + R2JurisdictionFedrampHigh => join([endpoint.account_id, ".fedramp-high.r2.cloudflarestorage.com"], "") R2JurisdictionUs => join([endpoint.account_id, ".us.r2.cloudflarestorage.com"], "") } } diff --git a/dag/gunbc/census_closure_frontier.dag b/dag/gunbc/census_closure_frontier.dag index 0d1e53c80cd..bd82ba47269 100644 --- a/dag/gunbc/census_closure_frontier.dag +++ b/dag/gunbc/census_closure_frontier.dag @@ -38,6 +38,7 @@ import extdeps.tools.sha256sum { sha256_verify_native_transport_frontier_rows } import gunbc.cloudflare.r2_token_mint { cloudflare_r2_token_mint_frontier_rows } import extdeps.cloudflare.account_api_tokens { cloudflare_account_api_tokens_frontier_rows } import extdeps.cloudflare.r2 { cloudflare_r2_frontier_rows } +import product.supplier.cloudflare_r2 { cloudflare_r2_supplier_frontier_rows } import extdeps.backblaze.b2 { backblaze_b2_frontier_rows } import extdeps.cloud.gcp.storage { gcs_storage_frontier_rows } import extdeps.ebay.browse { ebay_browse_frontier_rows } @@ -75,6 +76,7 @@ fn census_closure_frontier_row_groups() -> List> { cloudflare_r2_token_mint_frontier_rows, cloudflare_account_api_tokens_frontier_rows, cloudflare_r2_frontier_rows, + cloudflare_r2_supplier_frontier_rows, backblaze_b2_frontier_rows, gcs_storage_frontier_rows, ebay_browse_frontier_rows, diff --git a/dag/gunbc/cloudflare/r2_origin.dag b/dag/gunbc/cloudflare/r2_origin.dag index 1077d2b10cc..3400ec2cb39 100644 --- a/dag/gunbc/cloudflare/r2_origin.dag +++ b/dag/gunbc/cloudflare/r2_origin.dag @@ -204,7 +204,7 @@ type DurableOriginStanding = DurableOriginAllocated { bucket: DurableOriginBucket } | DurableOriginUnallocated { purpose: BucketPurpose } -// DEFAULT JURISDICTION, STATED RATHER THAN DEFAULTED. R2JurisdictionEu and R2JurisdictionFedramp are +// DEFAULT JURISDICTION, STATED RATHER THAN DEFAULTED. Eu, Us, Fedramp, and FedrampHigh are // data-residency commitments this fleet has not made and cannot honour, and picking one would assert // a compliance boundary nothing enforces. fn fabric_durable_origin_standing() -> DurableOriginStanding { diff --git a/dag/gunbc/product/supplier/cloudflare_r2.dag b/dag/gunbc/product/supplier/cloudflare_r2.dag index dd1e057a5d8..128d9505193 100644 --- a/dag/gunbc/product/supplier/cloudflare_r2.dag +++ b/dag/gunbc/product/supplier/cloudflare_r2.dag @@ -2,6 +2,8 @@ module product.supplier.cloudflare_r2 import std.types { List, NonEmptyStr } import std.decl_ref { DeclarationRef, decl_ref } +import std.roster_frontier { FrontierRow, frontier_row_decl } +import std.dissolution { unbound_dissolution } import std.content_hash { as_content_hash_structural, content_hash_atom, content_hash_combine_structural, Fnv1a64Structural } import product.fabric.provider_route { ProviderRoute, ProviderRouteFacts, @@ -180,12 +182,16 @@ fn cloudflare_r2_facts(route: ProviderRoute) -> ProviderRouteFacts { // to close. Production standing is ProviderRouteRegionUnobserved; this function projects that // standing to an empty facts list. admit_provider_use is not invoked here. The witness mints a // synthetic ProviderRegionRead route and calls admit_provider_use on that pair. -// -// DECLARED FRONTIER (DESIGN section 3c). The production consumer is a posture producer that mints a -// CompliancePostureRevision whose permitted_jurisdictions enumerate only routes whose facts have -// been read and cleared. TRIGGER: that producer, SUFFICIENT FOR this origin to be included or -// omitted by matching these facts rather than by a dashboard label. Until then the executing -// consumer of the admission pair is the witness. +data cloudflare_r2_supplier_frontier_rows: List = [ + frontier_row_decl( + ref: decl_ref(module_path: "product.supplier.cloudflare_r2", decl_name: "cloudflare_r2_route_facts_population"), + reason: "production does not consume this population; the executing consumer of the admission pair is the witness", + dissolution: unbound_dissolution( + description: "TRIGGER: a posture producer that mints a CompliancePostureRevision whose permitted_jurisdictions include or omit this origin by matching these facts. SUFFICIENT FOR: this population is read on an executing production path, not only by a witness." + ) + ) +] + fn cloudflare_r2_route_facts_population() -> List { match cloudflare_r2_durable_origin_route_standing() { ProviderRouteRegionUnobserved { obligation } => [], diff --git a/dag/test/claim/cloudflare_r2_origin_object_witness_test.dag b/dag/test/claim/cloudflare_r2_origin_object_witness_test.dag index f19ecac4d16..4b75ffaf41a 100644 --- a/dag/test/claim/cloudflare_r2_origin_object_witness_test.dag +++ b/dag/test/claim/cloudflare_r2_origin_object_witness_test.dag @@ -10,6 +10,9 @@ import extdeps.cloudflare.r2 { R2S3Endpoint, R2JurisdictionDefault, R2JurisdictionEu, + R2JurisdictionFedramp, + R2JurisdictionFedrampHigh, + R2JurisdictionUs, R2ObjectLocator, r2_object_url, r2_s3_sigv4_region, @@ -39,6 +42,7 @@ import gunbc.cloudflare.r2_permission_group_observe { cloudflare_permission_group_observation_frontier_rows, } import gunbc.cloudflare.r2_token_mint { cloudflare_r2_token_mint_frontier_rows } +import product.supplier.cloudflare_r2 { cloudflare_r2_supplier_frontier_rows } import gunbc.cloudflare.r2_origin_object { S3TransferAnswer, S3Answered, @@ -108,6 +112,21 @@ test fn r2_object_url_is_path_style_under_the_jurisdiction_host() -> Bool { bucket_name: "a-bucket", key: "k", }) == "https://4793d734c0b8e484dfc37ec392b5fa8a.eu.r2.cloudflarestorage.com/a-bucket/k" + && r2_object_url(locator: R2ObjectLocator { + endpoint: R2S3Endpoint { account_id: "4793d734c0b8e484dfc37ec392b5fa8a", jurisdiction: R2JurisdictionUs }, + bucket_name: "a-bucket", + key: "k", + }) == "https://4793d734c0b8e484dfc37ec392b5fa8a.us.r2.cloudflarestorage.com/a-bucket/k" + && r2_object_url(locator: R2ObjectLocator { + endpoint: R2S3Endpoint { account_id: "4793d734c0b8e484dfc37ec392b5fa8a", jurisdiction: R2JurisdictionFedramp }, + bucket_name: "a-bucket", + key: "k", + }) == "https://4793d734c0b8e484dfc37ec392b5fa8a.fedramp.r2.cloudflarestorage.com/a-bucket/k" + && r2_object_url(locator: R2ObjectLocator { + endpoint: R2S3Endpoint { account_id: "4793d734c0b8e484dfc37ec392b5fa8a", jurisdiction: R2JurisdictionFedrampHigh }, + bucket_name: "a-bucket", + key: "k", + }) == "https://4793d734c0b8e484dfc37ec392b5fa8a.fedramp-high.r2.cloudflarestorage.com/a-bucket/k" && (r2_s3_sigv4_region as String) == "auto" && curl_aws_sigv4_s3_provider(region: r2_s3_sigv4_region) == "aws:amz:auto:s3" } @@ -386,6 +405,7 @@ fn frontier_row_names_decl(row: FrontierRow, ref: DeclarationRef) -> Bool { // the observed-write-id row is still open for the same reason. test fn r2_origin_object_frontier_rows_reflect_the_executed_evidence() -> Bool { frontier_rows_well_formed(rows: cloudflare_r2_frontier_rows) + && frontier_rows_well_formed(rows: cloudflare_r2_supplier_frontier_rows) && !any(cloudflare_r2_frontier_rows, row => frontier_row_names_decl( row: row, ref: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_s3_endpoint_url"))) && frontier_rows_well_formed(rows: cloudflare_r2_token_mint_frontier_rows) diff --git a/dag/test/claim/cloudflare_r2_token_witness_test.dag b/dag/test/claim/cloudflare_r2_token_witness_test.dag index 80e023825f4..d9ab495d953 100644 --- a/dag/test/claim/cloudflare_r2_token_witness_test.dag +++ b/dag/test/claim/cloudflare_r2_token_witness_test.dag @@ -42,6 +42,9 @@ import extdeps.cloudflare.r2 { R2S3Endpoint, R2JurisdictionDefault, R2JurisdictionEu, + R2JurisdictionFedramp, + R2JurisdictionFedrampHigh, + R2JurisdictionUs, r2_s3_endpoint_url, r2_bucket_resource_name, r2_account_resource_name, @@ -52,6 +55,7 @@ import extdeps.cloudflare.r2 { r2_object_read_grant, cloudflare_r2_frontier_rows } +import product.supplier.cloudflare_r2 { cloudflare_r2_supplier_frontier_rows } import std.roster_frontier { FrontierRow, DeclSubject, PathSubject, frontier_rows_well_formed, frontier_subject_eq } import std.decl_ref { DeclarationRef, decl_ref, declaration_ref_eq } import std.human_intervention { @@ -166,6 +170,24 @@ test fn r2_endpoints_and_iam_resource_names_follow_the_r2_token_docs() -> Bool { jurisdiction: R2JurisdictionEu } ) == "https://4793d734c0b8e484dfc37ec392b5fa8a.eu.r2.cloudflarestorage.com" + && r2_s3_endpoint_url( + endpoint: R2S3Endpoint { + account_id: "4793d734c0b8e484dfc37ec392b5fa8a", + jurisdiction: R2JurisdictionUs + } + ) == "https://4793d734c0b8e484dfc37ec392b5fa8a.us.r2.cloudflarestorage.com" + && r2_s3_endpoint_url( + endpoint: R2S3Endpoint { + account_id: "4793d734c0b8e484dfc37ec392b5fa8a", + jurisdiction: R2JurisdictionFedramp + } + ) == "https://4793d734c0b8e484dfc37ec392b5fa8a.fedramp.r2.cloudflarestorage.com" + && r2_s3_endpoint_url( + endpoint: R2S3Endpoint { + account_id: "4793d734c0b8e484dfc37ec392b5fa8a", + jurisdiction: R2JurisdictionFedrampHigh + } + ) == "https://4793d734c0b8e484dfc37ec392b5fa8a.fedramp-high.r2.cloudflarestorage.com" && r2_bucket_resource_name( account_id: "4793d734c0b8e484dfc37ec392b5fa8a", jurisdiction: R2JurisdictionDefault, @@ -418,4 +440,5 @@ test fn cloudflare_frontier_rows_are_in_the_census() -> Bool { all(cloudflare_r2_token_mint_frontier_rows, row => census_contains_frontier_subject(row: row)) && all(cloudflare_account_api_tokens_frontier_rows, row => census_contains_frontier_subject(row: row)) && all(cloudflare_r2_frontier_rows, row => census_contains_frontier_subject(row: row)) + && all(cloudflare_r2_supplier_frontier_rows, row => census_contains_frontier_subject(row: row)) } From 8bec69e471bec4138f1c2e08ee40853c957c1470 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Sun, 13 Sep 2026 12:14:26 +0000 Subject: [PATCH 25/25] Keep the tokens as-of frontier: the digest is not a production consumer. cloudflare_r2_location_readings_digest still hashes the pin, but that fold is only reached from a dead Observed arm and the claim witness, which is the unread condition the row already recorded. Co-authored-by: Cursor --- dag/extdeps/cloudflare/r2.dag | 22 +++++++++++++------ ...oudflare_r2_origin_object_witness_test.dag | 2 ++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/dag/extdeps/cloudflare/r2.dag b/dag/extdeps/cloudflare/r2.dag index 599f29d4248..20789ee10ac 100644 --- a/dag/extdeps/cloudflare/r2.dag +++ b/dag/extdeps/cloudflare/r2.dag @@ -453,10 +453,11 @@ data r2_get_bucket_location_citation: FactCitation = FactCitation { } // THE READINGS ARE ONE CLOSURE. product.supplier.cloudflare_r2 hashes these lists (and -// r2_tokens_doc_as_of) into ProviderRouteFacts.facts_revision, so a changed transcription is a -// different facts row rather than a silent edit behind a pinned string. Automatic placement is -// recorded IN r2_data_location_reading; it is not a second model-scope subject and not a value of -// ProviderRoute.region. +// r2_tokens_doc_as_of) into ProviderRouteFacts.facts_revision, so a changed transcription would +// be a different facts row rather than a silent edit behind a pinned string. That hash is not +// a production consumer of the pin: no origin ProviderRoute is minted, so the as-of frontier +// row remains. Automatic placement is recorded IN r2_data_location_reading; it is not a second +// model-scope subject and not a value of ProviderRoute.region. fn r2_published_location_readings() -> List { [ r2_data_location_reading, @@ -482,9 +483,9 @@ fn r2_published_location_citations() -> List { // THE r2_s3_endpoint_url ROW IS RETIRED: gunbc.cloudflare.r2_origin_object reaches it through // r2_object_url on the executing put_origin_object and fetch_origin_object entries, which is the -// consumer the row named. The list is the membership of what remains. r2_tokens_doc_as_of is -// consumed by product.supplier.cloudflare_r2 cloudflare_r2_location_readings_digest as the cited -// tokens-page date, which is the executing-fold dissolution the frontier row named. +// consumer the row named. The list is the membership of what remains. r2_tokens_doc_as_of stays: +// the digest that cites it is reached only from the dead ProviderRouteObserved arm and the claim +// witness, which is the unread-outside-witness condition the row already recorded. data cloudflare_r2_frontier_rows: List = [ frontier_row_decl( ref: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_account_resource_name"), @@ -492,5 +493,12 @@ data cloudflare_r2_frontier_rows: List = [ dissolution: unbound_dissolution( description: "dissolves when a gunbc declaration consumes r2_account_resource_name in an executing token policy or S3 IAM grant; a witness that the fold exists does not fire this" ) + ), + frontier_row_decl( + ref: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_tokens_doc_as_of"), + reason: "as-of pin is unread outside the claim witness; ExternalAuthority has no as-of field", + dissolution: unbound_dissolution( + description: "dissolves when ExternalAuthority or FactCitation carries an as-of date and this pin inhabits that field, or a gunbc executing fold reads r2_tokens_doc_as_of as the cited document date" + ) ) ] diff --git a/dag/test/claim/cloudflare_r2_origin_object_witness_test.dag b/dag/test/claim/cloudflare_r2_origin_object_witness_test.dag index 4b75ffaf41a..7aad2cdde32 100644 --- a/dag/test/claim/cloudflare_r2_origin_object_witness_test.dag +++ b/dag/test/claim/cloudflare_r2_origin_object_witness_test.dag @@ -408,6 +408,8 @@ test fn r2_origin_object_frontier_rows_reflect_the_executed_evidence() -> Bool { && frontier_rows_well_formed(rows: cloudflare_r2_supplier_frontier_rows) && !any(cloudflare_r2_frontier_rows, row => frontier_row_names_decl( row: row, ref: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_s3_endpoint_url"))) + && any(cloudflare_r2_frontier_rows, row => frontier_row_names_decl( + row: row, ref: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_tokens_doc_as_of"))) && frontier_rows_well_formed(rows: cloudflare_r2_token_mint_frontier_rows) && any(cloudflare_r2_token_mint_frontier_rows, row => frontier_row_names_decl( row: row, ref: decl_ref(module_path: "gunbc.cloudflare.r2_token_mint", decl_name: "admit_r2_object_write_api_mint")))