Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
849bc12
Refuse the R2 durable-origin route: Automatic placement is a choice, …
Sep 12, 2026
602b2c0
Cite R2Jurisdiction as the tag set; drop the same-tree roster count.
Sep 12, 2026
1a40c3f
Drop unused location-hint coproduct; transcribe the Logpush limitation.
Sep 12, 2026
250870b
Consume the existing tokens-page anchor and the vendor Cloudflare row.
Sep 13, 2026
b2e0dca
Delete the unused residency Bool and restriction rows from production.
Sep 13, 2026
7c2f730
Do not mint a ProviderRoute whose region is Automatic placement.
Sep 13, 2026
e0bf6a4
Invert the origin admit: there is no durable-origin route to permit.
Sep 13, 2026
d415d5b
Delete the admit_provider_use alias from the R2 supplier.
Sep 13, 2026
054aafe
Attach the leftover annotation to the facts population.
Sep 13, 2026
3adfe52
Assert the first production-facts refusal: unread downstream.
Sep 13, 2026
d31a910
Drop the vacuous, subsumed, and misnamed witness assertions.
Sep 13, 2026
f3cd7cc
Cite R2S3Endpoint as the route service, not the location docs.
Sep 13, 2026
f90ed29
Keep reported location, requested hint, and residency as three facts.
Sep 13, 2026
a91fa04
Keep the subprocessors coverage gap in the product obligation.
Sep 13, 2026
6fb24f9
Annotate why operator or jurisdiction alone cannot close a location p…
Sep 13, 2026
dad1c97
Hoist region observation and route standing onto provider_route.
Sep 13, 2026
bd08d4c
Cite SparkServingRoute as a non-member of the shared route standing.
Sep 13, 2026
1f5bcac
Fold R2 location readings into the existing R2 extdeps module.
Sep 13, 2026
b6ea8de
Hash location readings as a structural digest, not as a list.
Sep 13, 2026
e654fe7
Put company DPA and subprocessors on the vendor, not under R2S3Endpoint.
Sep 13, 2026
9248e4d
Call list concat as two arguments, not as a list of lists.
Sep 13, 2026
4edab5e
Merge remote-tracking branch 'origin/main' into session/calm-tern-382
Sep 13, 2026
7f72e46
Match the three ProviderUseRefusal arms #11194 added.
Sep 13, 2026
ecba73b
Escape braces in Create/Get Bucket path transcriptions.
Sep 13, 2026
d1c4f4d
Model fedramp-high and enroll the R2 facts-population frontier.
Sep 13, 2026
8bec69e
Keep the tokens as-of frontier: the digest is not a production consumer.
Sep 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 156 additions & 2 deletions dag/extdeps/cloudflare/r2.dag
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,41 @@ 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 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
Expand Down Expand Up @@ -99,19 +134,30 @@ 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,
r2_create_bucket_authority,
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 {
match jurisdiction {
R2JurisdictionDefault => "default"
R2JurisdictionEu => "eu"
R2JurisdictionFedramp => "fedramp"
R2JurisdictionFedrampHigh => "fedramp-high"
R2JurisdictionUs => "us"
}
}
Expand All @@ -126,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"], "")
}
}
Expand Down Expand Up @@ -329,9 +376,116 @@ fn r2_object_url(locator: R2ObjectLocator) -> String {
)
}

// 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.
//
// 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_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: 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_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_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://<ACCOUNT_ID>.us.r2.cloudflarestorage.com. Once an R2 bucket is created, its jurisdiction cannot be changed. Posted 2026-08-17. Read 2026-09-12."

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_tokens_default_jurisdiction_reading: NonEmptyStr = "A specific bucket is represented as com.cloudflare.edge.r2.bucket.<ACCOUNT_ID>_<JURISDICTION>_<BUCKET_NAME>. 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_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 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 these lists (and
// 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<NonEmptyStr> {
[
r2_data_location_reading,
r2_how_r2_works_reading,
r2_us_jurisdiction_changelog_reading,
r2_tokens_default_jurisdiction_reading,
r2_create_bucket_location_hint_reading,
r2_get_bucket_location_reading,
]
}

fn r2_published_location_citations() -> List<FactCitation> {
[
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 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<FrontierRow> = [
frontier_row_decl(
ref: decl_ref(module_path: "extdeps.cloudflare.r2", decl_name: "r2_account_resource_name"),
Expand Down
56 changes: 54 additions & 2 deletions dag/extdeps/vendor/cloudflare.dag
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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 {
Expand All @@ -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<Securities> = 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<NonEmptyStr> {
[cloudflare_subprocessors_reading, cloudflare_customer_dpa_reading]
}

fn cloudflare_company_document_citations() -> List<FactCitation> {
[cloudflare_subprocessors_citation, cloudflare_customer_dpa_citation]
}
2 changes: 2 additions & 0 deletions dag/gunbc/census_closure_frontier.dag
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down Expand Up @@ -75,6 +76,7 @@ fn census_closure_frontier_row_groups() -> List<List<FrontierRow>> {
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,
Expand Down
2 changes: 1 addition & 1 deletion dag/gunbc/cloudflare/r2_origin.dag
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
40 changes: 40 additions & 0 deletions dag/gunbc/product/fabric/provider_route.dag
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,46 @@ 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.
//
// 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
// 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
Expand Down
Loading
Loading