Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
6753360
A source module says where the publisher path and asset routes fetch …
jwrosewell Oct 14, 2026
dc7306d
A module sees the prefix request addressing removed
jwrosewell Oct 14, 2026
5494af9
An integration route is handed its request's evidence
jwrosewell Oct 14, 2026
d17b184
Merge 38-middleware-settings into 39-source-modules
jwrosewell Oct 14, 2026
d6d0da0
The testlight test gives its settings an origin source
jwrosewell Oct 14, 2026
a7a0428
The local test scripts set the origin's address under [source.origin]
jwrosewell Oct 15, 2026
ff33fea
A page names itself by the Host its source sends
jwrosewell Oct 15, 2026
6eabcc6
The source modules design states the stored keys and page host it cha…
jwrosewell Oct 15, 2026
0f51b33
The source modules design records its round 2 review
jwrosewell Oct 15, 2026
a3e32b9
Merge 38-middleware-settings into 39-source-modules
jwrosewell Oct 15, 2026
f389567
Merge 38-middleware-settings into 39-source-modules
jwrosewell Oct 15, 2026
4da47d7
Merge 38-middleware-settings into 39-source-modules
jwrosewell Oct 15, 2026
d3a9449
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 16, 2026
b8cba5d
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 16, 2026
0141e97
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 16, 2026
878941c
Set the config push tests' origin under [source.origin]
jwrosewell Oct 16, 2026
d10da96
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 16, 2026
a6c735a
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 16, 2026
14dfd6b
The CMP id test names its origin under the origin source
jwrosewell Oct 16, 2026
712a25e
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 16, 2026
217874b
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 16, 2026
c0efb11
The design header names the pull request that carries it
jwrosewell Oct 16, 2026
70cedb7
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 16, 2026
db06666
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 16, 2026
460aa83
Three tests name their origin in a source section
jwrosewell Oct 16, 2026
1ffdbfa
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 16, 2026
8b62f39
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 16, 2026
4118838
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 16, 2026
a1ae035
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 16, 2026
81f8be7
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 18, 2026
c0ca4bc
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 18, 2026
81fe7d0
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 18, 2026
2a90d97
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 18, 2026
00e99fa
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 18, 2026
6f7238f
The failed asset load test passes the route's source
jwrosewell Oct 18, 2026
9389389
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 19, 2026
eb8a763
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 19, 2026
17993dd
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 19, 2026
315cdf0
The header rewrite's messages, tests and guide name the source settings
jwrosewell Oct 19, 2026
ade271c
Merge split/38-middleware-settings into split/39-source-modules
jwrosewell Oct 19, 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
6 changes: 3 additions & 3 deletions .github/actions/setup-integration-test-env/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ runs:
if: ${{ inputs.build-wasm == 'true' }}
shell: bash
env:
TRUSTED_SERVER__PUBLISHER__ORIGIN_URL: http://127.0.0.1:${{ inputs.origin-port }}
TRUSTED_SERVER__SOURCE__ORIGIN__URL: http://127.0.0.1:${{ inputs.origin-port }}
TRUSTED_SERVER__PUBLISHER__PROXY_SECRET: integration-test-proxy-secret
TRUSTED_SERVER__EC__PASSPHRASE: integration-test-ec-secret-padded-32
TRUSTED_SERVER__EC__PARTNERS: >-
Expand All @@ -86,7 +86,7 @@ runs:
if: ${{ inputs.build-axum == 'true' }}
shell: bash
env:
TRUSTED_SERVER__PUBLISHER__ORIGIN_URL: http://127.0.0.1:${{ inputs.origin-port }}
TRUSTED_SERVER__SOURCE__ORIGIN__URL: http://127.0.0.1:${{ inputs.origin-port }}
TRUSTED_SERVER__PUBLISHER__PROXY_SECRET: integration-test-proxy-secret
TRUSTED_SERVER__EC__PASSPHRASE: integration-test-ec-secret-padded-32
TRUSTED_SERVER__PROXY__CERTIFICATE_CHECK: "false"
Expand Down Expand Up @@ -117,7 +117,7 @@ runs:
if: ${{ inputs.build-cloudflare == 'true' }}
shell: bash
env:
TRUSTED_SERVER__PUBLISHER__ORIGIN_URL: http://127.0.0.1:${{ inputs.origin-port }}
TRUSTED_SERVER__SOURCE__ORIGIN__URL: http://127.0.0.1:${{ inputs.origin-port }}
TRUSTED_SERVER__PUBLISHER__PROXY_SECRET: integration-test-proxy-secret
TRUSTED_SERVER__EC__PASSPHRASE: integration-test-ec-secret-padded-32
TRUSTED_SERVER__PROXY__CERTIFICATE_CHECK: "false"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ jobs:
# rejects (falling back to the generic 503 router). This proves the
# documented Spin artifact can boot, not just compile.
env:
TRUSTED_SERVER__PUBLISHER__ORIGIN_URL: http://127.0.0.1:8080
TRUSTED_SERVER__SOURCE__ORIGIN__URL: http://127.0.0.1:8080
TRUSTED_SERVER__PUBLISHER__PROXY_SECRET: integration-test-proxy-secret
TRUSTED_SERVER__EC__PASSPHRASE: integration-test-ec-secret-padded-32
TRUSTED_SERVER__PROXY__CERTIFICATE_CHECK: "false"
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- **Breaking:** Where content comes from is a source module. `[source]` selects the publisher's, and each `[[proxy.asset_routes]]` entry selects its own in a `source` table of the same shape, with `module` naming the source and its settings in the table beneath. Core supplies `origin`, an HTTP origin, and a module a build links can offer another through `IntegrationRegistrationBuilder::with_source_module`. A source answers for each request where that request's content comes from, and core fetches, caches, rewrites the origin host and follows the redirect rule from that answer. `[source]` is required. The origin settings move into the `origin` table, and a document that still writes one where it was is refused at startup naming the new place. An environment variable that set the address is now `TRUSTED_SERVER__SOURCE__ORIGIN__URL`. The old name is refused where the build reads variables, and `ts config push` ignores it, as it ignores any variable for a key the document does not hold. A path in an asset route's `url` names a folder the target path is added under, where a path was refused, a target path with a `.` or `..` segment under a folder is answered `400`, and a route applies `directory_index` as the publisher does. Stored pages and the publisher's stored assets are fetched again after the upgrade, because their keys hold a code worked out from the settings, but an asset route's stored copies keep their keys. Where `host_header` is set, the page pipeline and every middleware are now told that `Host` as the page's origin host, where they were told the address's host, so the page's own addresses under that name are rewritten to the request's host. **For crates outside core**, `handle_asset_proxy_request` takes the route's source, which `IntegrationRegistry::route_source` gives, and `Publisher::origin_host`, `origin_host_header` and `origin_query_is_stripped` are replaced by `Settings::origin_source` and the `SourceLocation` a source answers.

| Previous | Now |
| ----------------------------------------- | ----------------------------------------- |
| `[publisher] origin_url` | `[source.origin] url` |
| `[publisher] origin_host_header_override` | `[source.origin] host_header` |
| `[publisher] origin_auth` | `[source.origin] auth` |
| `[publisher] directory_index` | `[source.origin] directory_index` |
| `[[proxy.asset_routes]] origin_url` | `[proxy.asset_routes.source.origin] url` |
| `[[proxy.asset_routes]] auth` | `[proxy.asset_routes.source.origin] auth` |

- The mapping of origin URLs in response headers (#1128) follows a path in `origin_url`. A URL on the origin is mapped to the serving host only when it is in that folder, and it loses the folder, so the reader of a site served from a folder of object storage is sent to the right address. A URL on the origin's host outside the folder is unchanged, because no address on the serving host leads there, and a CSP source with no path still gains the serving host beside it. A reader of a publisher whose request addressing hook removes a path prefix is sent to an address without the prefix, which a Fastly service whose `__KEY` selector carries `{host}` answers `421` if every selector value misses.
- **Breaking:** a path in `publisher.origin_url` is kept, and the request path is added after it with one `/`. The path was discarded before, so a deployment whose `origin_url` has one now sends each request to the folder the path names, and answers `400` to a request path with a `.` or `..` segment, with or without `origin_auth`. A deployment whose `origin_url` has no path sends its requests as before. Before upgrading, check that the origin serves the site at that path, or remove the path.
- **Breaking:** the check that closes `/_ts/admin` and `/admin/keys` on every adapter now also answers `404` to a request path still changing after four rounds of percent-decoding and to a path that reaches either once an escape that is not valid UTF-8 is replaced. The publisher received both before, and no setting turns the check off.
Expand Down
7 changes: 6 additions & 1 deletion crates/auction/prebid-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3046,10 +3046,15 @@ mod tests {
[auction]
modules = ["prebid"]

[source]
module = "origin"

[source.origin]
url = "https://origin.test-publisher.com"

[publisher]
domain = "test-publisher.com"
cookie_domain = ".test-publisher.com"
origin_url = "https://origin.test-publisher.com"
proxy_secret = "test-secret"

[ec]
Expand Down
7 changes: 6 additions & 1 deletion crates/auction/prebid/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1743,10 +1743,15 @@ mod tests {
[auction]
modules = ["prebid"]

[source]
module = "origin"

[source.origin]
url = "https://origin.test-publisher.com"

[publisher]
domain = "test-publisher.com"
cookie_domain = ".test-publisher.com"
origin_url = "https://origin.test-publisher.com"
proxy_secret = "test-secret"

[ec]
Expand Down
4 changes: 3 additions & 1 deletion crates/cmp/inmobi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1150,7 +1150,9 @@ mod tests {
"cmp_id = {value}\n{}",
html_entry(None, &[MODULE])
));
settings.publisher.origin_url = "https://origin.publisher.example".to_owned();
settings.set_origin_source(&trusted_server_core::source::OriginSettings::new(
"https://origin.publisher.example",
));
settings
};
let load = |settings: &Settings| {
Expand Down
14 changes: 12 additions & 2 deletions crates/tag/google-tag-manager/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3122,10 +3122,15 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
#[test]
fn test_config_parsing() {
let toml_str = r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.test-publisher.com"

[publisher]
domain = "test-publisher.com"
cookie_domain = ".test-publisher.com"
origin_url = "https://origin.test-publisher.com"
proxy_secret = "test-secret"

[ec]
Expand Down Expand Up @@ -3157,10 +3162,15 @@ assume_single_jurisdiction = true
#[test]
fn a_block_for_an_unnamed_integration_is_refused() {
let toml_str = r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.test-publisher.com"

[publisher]
domain = "test-publisher.com"
cookie_domain = ".test-publisher.com"
origin_url = "https://origin.test-publisher.com"
proxy_secret = "test-secret"

[ec]
Expand Down
14 changes: 12 additions & 2 deletions crates/testing/seam-probe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1131,10 +1131,15 @@ mod tests {
fn settings_with_probe(body: &str) -> Settings {
Settings::from_toml(&format!(
r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.test-publisher.example.com"

[publisher]
domain = "test-publisher.example.com"
cookie_domain = ".test-publisher.example.com"
origin_url = "https://origin.test-publisher.example.com"
proxy_secret = "seam-probe-test-proxy-secret"

[ec]
Expand Down Expand Up @@ -1374,10 +1379,15 @@ mod tests {
fn validate_reports_not_selected_without_a_module_entry() {
let settings = Settings::from_toml(
r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.test-publisher.example.com"

[publisher]
domain = "test-publisher.example.com"
cookie_domain = ".test-publisher.example.com"
origin_url = "https://origin.test-publisher.example.com"
proxy_secret = "seam-probe-test-proxy-secret"

[ec]
Expand Down
3 changes: 3 additions & 0 deletions crates/testing/testlight/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,9 @@ mod tests {
</head><body></body></html>"#;

let mut settings = Settings::default();
settings.set_origin_source(&trusted_server_core::source::OriginSettings::new(
"https://origin.example.com",
));
let shim_src = "https://edge.example.com/static/testlight.js".to_owned();
settings
.insert_module_config(
Expand Down
14 changes: 12 additions & 2 deletions crates/trusted-server-adapter-axum/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -945,10 +945,15 @@ mod tests {
/// inject, with the `[ec.acme]` block that module's settings live in.
/// `acme` is a fictional vendor key.
const UNINJECTED_MODULE_TOML: &str = r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.test-publisher.example.com"

[publisher]
domain = "test-publisher.example.com"
cookie_domain = ".test-publisher.example.com"
origin_url = "https://origin.test-publisher.example.com"
proxy_secret = "unit-test-proxy-secret"

[ec]
Expand All @@ -970,10 +975,15 @@ mod tests {
fn a_requests_services_carry_the_publishers_prefixes() {
let settings = Settings::from_toml(
r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.publisher.example"

[publisher]
domain = "www.publisher.example"
cookie_domain = ".publisher.example"
origin_url = "https://origin.publisher.example"
proxy_secret = "fictional-proxy-secret-32-bytes-ok"

[geo]
Expand Down
7 changes: 6 additions & 1 deletion crates/trusted-server-adapter-axum/src/middleware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,15 @@ mod tests {
fn settings_with_response_headers(headers: Vec<(&str, &str)>) -> Settings {
let mut s = Settings::from_toml(
r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.test-publisher.example.com"

[publisher]
domain = "test-publisher.example.com"
cookie_domain = ".test-publisher.example.com"
origin_url = "https://origin.test-publisher.example.com"
proxy_secret = "unit-test-proxy-secret"

[ec]
Expand Down
21 changes: 18 additions & 3 deletions crates/trusted-server-adapter-axum/tests/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,15 @@ fn test_settings() -> trusted_server_core::settings::Settings {
fn test_settings_with(extra: &str) -> trusted_server_core::settings::Settings {
trusted_server_core::settings::Settings::from_toml(&format!(
r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.test-publisher.example.com"

[publisher]
domain = "test-publisher.example.com"
cookie_domain = ".test-publisher.example.com"
origin_url = "https://origin.test-publisher.example.com"
proxy_secret = "integration-test-proxy-secret"

[ec]
Expand Down Expand Up @@ -674,10 +679,15 @@ async fn first_party_proxy_rebuild_is_routed() {
/// inject, with the `[ec.acme]` block that module's settings live in.
/// `acme` is a fictional vendor key.
const UNINJECTED_MODULE_TOML: &str = r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.test-publisher.example.com"

[publisher]
domain = "test-publisher.example.com"
cookie_domain = ".test-publisher.example.com"
origin_url = "https://origin.test-publisher.example.com"
proxy_secret = "integration-test-proxy-secret"

[ec]
Expand Down Expand Up @@ -980,10 +990,15 @@ async fn the_sellers_module_makes_an_ads_txt_the_origin_does_not_have() {
fn settings_refusing_every_crawler() -> trusted_server_core::settings::Settings {
trusted_server_core::settings::Settings::from_toml(
r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.test-publisher.example.com"

[publisher]
domain = "test-publisher.example.com"
cookie_domain = ".test-publisher.example.com"
origin_url = "https://origin.test-publisher.example.com"
proxy_secret = "integration-test-proxy-secret"

[ec]
Expand Down
14 changes: 12 additions & 2 deletions crates/trusted-server-adapter-axum/tests/seam_probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,15 @@ assume_single_jurisdiction = true
};
Settings::from_toml(&format!(
r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.test-publisher.example.com"

[publisher]
domain = "test-publisher.example.com"
cookie_domain = ".test-publisher.example.com"
origin_url = "https://origin.test-publisher.example.com"
proxy_secret = "seam-probe-test-proxy-secret"

[ec]
Expand Down Expand Up @@ -931,10 +936,15 @@ fn deploy_validation_accepts_a_modules_ad_server_only_with_its_builder() {
fn settings_selecting_module(extra: &str) -> Settings {
Settings::from_toml(&format!(
r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.test-publisher.example.com"

[publisher]
domain = "test-publisher.example.com"
cookie_domain = ".test-publisher.example.com"
origin_url = "https://origin.test-publisher.example.com"
proxy_secret = "seam-probe-test-proxy-secret"

[geo]
Expand Down
35 changes: 30 additions & 5 deletions crates/trusted-server-adapter-cloudflare/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1001,10 +1001,15 @@ mod tests {
/// inject, with the `[ec.acme]` block that module's settings live in.
/// `acme` is a fictional vendor key.
const UNINJECTED_MODULE_TOML: &str = r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.test-publisher.example.com"

[publisher]
domain = "test-publisher.example.com"
cookie_domain = ".test-publisher.example.com"
origin_url = "https://origin.test-publisher.example.com"
proxy_secret = "unit-test-proxy-secret"

[ec]
Expand Down Expand Up @@ -1057,10 +1062,15 @@ mod tests {
fn aps_profile_settings() -> Settings {
let mut settings = Settings::from_toml(
r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.publisher.example"

[publisher]
domain = "publisher.example"
cookie_domain = ".publisher.example"
origin_url = "https://origin.publisher.example"
proxy_secret = "fictional-proxy-secret"

[ec]
Expand Down Expand Up @@ -1143,10 +1153,15 @@ mod tests {
fn a_requests_services_carry_the_publishers_prefixes() {
let settings = Settings::from_toml(
r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.publisher.example"

[publisher]
domain = "www.publisher.example"
cookie_domain = ".publisher.example"
origin_url = "https://origin.publisher.example"
proxy_secret = "fictional-proxy-secret-32-bytes-ok"

[geo]
Expand Down Expand Up @@ -1189,10 +1204,15 @@ mod tests {
fn disabled_startup_accepts_dormant_multi_provider_auction_plan() {
let mut settings = Settings::from_toml(
r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.publisher.example"

[publisher]
domain = "publisher.example"
cookie_domain = ".publisher.example"
origin_url = "https://origin.publisher.example"
proxy_secret = "fictional-proxy-secret"

[ec]
Expand All @@ -1214,10 +1234,15 @@ mod tests {
fn startup_rejects_multi_provider_auction_plan() {
let mut settings = Settings::from_toml(
r#"
[source]
module = "origin"

[source.origin]
url = "https://origin.publisher.example"

[publisher]
domain = "publisher.example"
cookie_domain = ".publisher.example"
origin_url = "https://origin.publisher.example"
proxy_secret = "fictional-proxy-secret"

[ec]
Expand Down
Loading
Loading