Skip to content

AWS signing is a shared crate and core signs through an origin signer - #1391

Draft
jwrosewell wants to merge 36 commits into
feature/47-backend-namingfrom
feature/48-aws-signing
Draft

jwrosewell wants to merge 36 commits into
feature/47-backend-namingfrom
feature/48-aws-signing

Conversation

@jwrosewell

@jwrosewell jwrosewell commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Changes

Area Change
crates/trusted-server-core/src 14 files, 1675 lines added, 874 removed
crates/shared/aws 3 files, 832 lines added, 62 removed
docs/superpowers 1 file, 106 lines added, 0 removed
docs/guide 4 files, 89 lines added, 36 removed
Cargo.lock 1 file, 24 lines added, 0 removed
crates/shared/README.md 1 file, 18 lines added, 0 removed
trusted-server.example.toml 1 file, 8 lines added, 6 removed
.cargo/config.toml 1 file, 6 lines added, 6 removed
crates/trusted-server-adapter-axum/src 1 file, 4 lines added, 0 removed
crates/trusted-server-adapter-cloudflare/src 1 file, 4 lines added, 0 removed
crates/trusted-server-adapter-fastly/src 1 file, 4 lines added, 0 removed
crates/trusted-server-adapter-spin/src 1 file, 4 lines added, 0 removed
crates/trusted-server-cli/src 1 file, 3 lines added, 0 removed
Cargo.toml 1 file, 2 lines added, 0 removed
CHANGELOG.md 1 file, 1 line added, 0 removed
crates/trusted-server-adapter-axum/Cargo.toml 1 file, 1 line added, 0 removed
crates/trusted-server-adapter-cloudflare/Cargo.toml 1 file, 1 line added, 0 removed
crates/trusted-server-adapter-fastly/Cargo.toml 1 file, 1 line added, 0 removed
crates/trusted-server-adapter-spin/Cargo.toml 1 file, 1 line added, 0 removed
crates/trusted-server-cli/Cargo.toml 1 file, 1 line added, 0 removed

Closes

Closes #1338

Test plan

CI on this pull request at 8a69cb9 passed all 19 checks.

  • cargo test-fastly && cargo test-axum
  • cargo clippy-fastly && cargo clippy-axum
  • cargo fmt --all -- --check
  • JS tests: cd crates/trusted-server-js/lib && npx vitest run
  • JS format: cd crates/trusted-server-js/lib && npm run format
  • Docs format: cd docs && npm run format
  • WASM build: cargo build --package trusted-server-adapter-fastly --release --target wasm32-wasip1
  • Manual testing via fastly compute serve
  • Other: the full workflow set of this repository, run on this pull request at 8a69cb9

Checklist

  • Changes follow AGENTS.md conventions
  • No unwrap() in production code (clippy denies unwrap_used in CI)
  • Uses log macros as AGENTS.md asks (not println!)
  • New code has tests
  • No secrets or credentials committed

On top of the backend naming series (#1390). Issue: #1338.

What this adds

What changes.

AWS request signing is a shared crate and core signs through an origin signer. Core's s3_sigv4.rs and the S3SigV4AuthConfig settings leave for crates/shared/aws, and core keeps an origin authentication interface that the source series' auth tables name a signer through.

[source.origin]
url = "https://storage.example.com/bucket/site"
auth = { type = "s3_sigv4", region = "eu-west-1", access_key_id = "example-key-id", secret_access_key = "example-secret-name" }

How it works.

  • One signer interface. crates/trusted-server-core/src/origin_auth.rs declares the OriginSigner a module offers under a name, the OriginAuth table every auth setting reads (its type, the vendor neutral origin_query rule, and the signer's own settings), and the secret fields a signer declares so the settings load resolves and masks them as before.
  • A builder offers a signer. IntegrationBuilder::with_origin_signer offers one, because a signer's secret settings must be known before the settings load, as a loading cache's are. The registry hands the signers on offer to the origin source when it builds the sources, and a type nothing supplies is refused at startup with the names on offer.
  • Deploy validation asks the signer. ts config validate builds every auth table that names an offered signer, as the settings load does, so a table the signer cannot use fails validation and not the first start, whichever crate offers the signer. A table naming a signer the build does not offer is left alone, as its key references already were.
  • The AWS crate. crates/shared/aws holds the Signature Version 4 code with its tests and the s3_sigv4 signer, and each adapter and the ts command list its builder, so the stock build signs as today. Its builder offers the signer as an implementation, with no page module and no validator of its own.
  • Core names no cloud vendor. The proxy and the publisher path sign through the location's signer and remove its namespace headers through it, and nothing in core names S3, AWS or the signature scheme.

Why

A signing scheme is a vendor's, and core offers the neutral interface a signer implements. The object storage origin came into the stack signing through core's one scheme because that was where the scheme lived, and this moves it to where it belongs.

What breaks

Nothing for a deployment whose build links the AWS crate, which the stock adapters do, except that the deprecated spelling s3_sig_v4 is no longer read, because a type is matched as written. A pushed settings document already carries s3_sigv4.

The commits

  1. AWS signing is a shared crate and core signs through an origin signer.
  2. The signer crate's tests read a registry refusal by matching on it.
  3. A merge of the client hints middleware, after which each adapter and the ts command list the AWS builder after the loading cache, where the removed modules crate listed it.
  4. A merge of the last names series, after which the registry keeps the signers beside the analytics modules, and the aliases, the guide and the tests drop both series' vendors.
  5. The lock lists the AWS crate after the merge.
  6. Three merges of the backend naming series, the last two carrying fixes made lower in the stack.
  7. Core checks each auth table with its signer at deploy validation, so the AWS builder needs no validator and offers the signer as an implementation. The S3 secret paths leave core's static list, because the signers the builders offer declare them.
  8. A merge of the backend naming series, which carries the page origin change. The publisher tests keep both sides, the page origin test and this series' object storage tests.
  9. The origin signing design states the gap in deploy validation and what changes for a deployment, and takes its round 2 corrections.
  10. Later merges of the series below carry Tech Lab main at fa9837f.

What is not in this pull request

A vendor's own source module cannot reach the signers on offer and holds its own signer, because the source factory's interface is unchanged. The design page records it.

Core signed reads from the publisher's origin and from each asset route's
origin with one cloud vendor's signing scheme, and its settings knew that
scheme's region and credential key names, so a signed read with another
scheme was a change to core.

Core now keeps an origin authentication interface. OriginSigner, in the
new origin_auth module, signs the headers of a request for a method on a
final address and removes every header in the scheme's own namespace. A
source's auth table keeps its shape: type names the signer, origin_query
is read by core, and the rest of the table belongs to the signer named. A
crate offers a signer on its builder with with_origin_signer, which also
declares the settings of the signer's table that hold the name of a
secret and the key name each takes when left out. The registry builds the
signer where a source names it, so a type nothing offers is refused at
startup naming the signers on offer, and a table the signer cannot use is
refused naming the setting. The declared secrets are looked up as the
settings load at both auth paths, a left out setting with a default is
written in before the lookup, a written one naming no key fails deploy
validation naming its path, and the configuration page masks them.

The s3_sigv4 signer moves to crates/shared/aws, the package
trusted-server-shared-aws, with the same settings, defaults, secret key
references and signing. The stock build offers it through
crates/trusted-server-modules, so a deployment's settings read as before.
The deprecated spelling s3_sig_v4 is no longer read.

Core's tests sign through a fixture signer the origin_auth module keeps
for them. The vendor crate's tests cover the published signature example,
the registry and deploy refusals, and the lookup and masking of its
credentials.

Design: docs/superpowers/specs/2026-10-14-origin-signing-design.md
A registry carries no Debug, so a test that expects a refusal from
building one matches on the result rather than calling expect_err,
which the check of the signer crate's tests refused.
The modules crate is gone, so the AWS signer is listed by each adapter and
the ts command after the loading cache, where the removed crate listed it.
The registry builds the sources with the signers on offer and keeps the
identifier modules, and the lib loses both the Flight rewriter and the
signing module to their crates.
Each series removed its own vendor from the same settings tests, so both
removals stand: the Tinybird and S3 canaries, helpers and the legacy store
test that only covered those two go. The registry keeps the origin signers
and the analytics modules, and the guide lists both builder methods.
# Conflicts:
#	CHANGELOG.md
Deploy validation builds every auth table that names an offered signer,
as the settings load does, so a table the signer cannot use fails
validation for any signer. The AWS builder then needs no validator of
its own and offers the signer as an implementation, with no page module,
which the shipped-modules test expects of a builder without a section.

The S3 secret paths leave core's static list, because the signers the
builders offer declare them, and the shared README and the AWS builder's
comment name the adapters' module lists in place of the deleted modules
crate.
# Conflicts:
#	crates/trusted-server-core/src/publisher.rs
…t changes for a deployment

Review round 1 found that the design named a modules crate that no longer
exists and deploy rules the AWS builder does not carry, and that a type
nothing offers passes ts config validate and ts config push and only stops
the adapter at startup. The design now says so, calls the removal of
s3_sig_v4 breaking, and leaves closing the gap as an open question. It
also gives the refusals by stage, the answers when signing fails, the
rollout, the adapters that run each path, the settings that change and the
tests that are missing or cannot fail, and records the review round.

The changelog entry, the integration guide and the configuration guide drop
the same stale sentences: the modules crate, the builder's validate
function, and a blank session token read as no token.
Review round 2 found that the specs pull request is now
#1342, because #1084 was closed, and three
statements to tighten. The design now names #1342, says that the
preflight signs without calling remove_namespace_headers, which makes no
difference for s3_sigv4, says that GET /health on Fastly and Spin and the
Fastly debug probes are still answered when an adapter cannot build its
state, and limits the missing test for an empty session_token to deploy
validation.

The Tinybird entry in the changelog no longer names the deleted modules
crate.
The analytics entry keeps the last names series' wording, which names the ts tool and says only the Fastly adapter hands the sink to the auction.
@jwrosewell
jwrosewell added this pull request to stack #1401 October 15, 2026 17:56
@jwrosewell
jwrosewell removed this pull request from stack #1401 October 15, 2026 20:51
@jwrosewell
jwrosewell removed this pull request from stack #1408 October 18, 2026 20:15
@jwrosewell jwrosewell closed this Oct 18, 2026
@jwrosewell jwrosewell reopened this Oct 18, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant