Repository navigation
Conversation
A stream processor may implement StreamProcessor::async_finish over the bytes its last process_chunk call returned. StreamProcessor::finish ends a processor once; a processor made of others ends each in order, so each is handed what the one before it finished with. Every publisher path that can await now ends its processor this way: the no-hold pipeline, both auction-hold loops, the serve pass on a shared template and the lazy stream. A body read whole takes the same chunk pipeline, and the synchronous stream_publisher_body path is removed. A middleware is also told the response status and whether the origin marked the response as one reader's, read before core writes its own cache policy.
The Encypher signing integration becomes a serve middleware in crates/provenance/encypher, selected by [provenance] module = "encypher" and placed by a [[serve]] entry. Its preparation applies the request gates with no I/O, and its stream processor signs the article in the asynchronous finish core now awaits. The worker token is a module secret setting. The enabled flag and path_prefixes give way to the selection and the entry's path, and the module is offered on every adapter and the CLI.
…arrow the module's data claims Adds a regression test that the parser-confirmed auction hold injects bids into a document a middleware processor held and finished asynchronously. States that the module skips pages the origin marks private but cannot detect other personalized pages, so a deployment places it on public article routes. Applies rustfmt and the docs formatter.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ports Encypher's text provenance contribution onto the module architecture of the stack tracked in #777, based on row 55 (#1423,
feature/55-scripts-in-cratesat 5be1147). It changes no row of the stack.What publishers get
A deployment can sign the article on its public pages with invisible provenance markers and a C2PA manifest link by selecting one module and placing its middleware, with core naming no vendor:
Every page the module cannot sign passes through unchanged.
Neutral core seams
StreamProcessor::async_finishandStreamProcessor::finish: a middleware's stream processor may finish its last output asynchronously, with a deadline. A processor made of others ends each in order. Every publisher path that can await now ends its processor this way (no-hold pipeline, both auction-hold loops, the serve pass on a shared template, the lazy stream). A body read whole takes the same chunk pipeline, and the synchronousstream_publisher_bodypath is removed so no path skips a finish.PlatformTimer, optional onRuntimeServices, provided on Cloudflare, Spin and Axum.MiddlewareContext::statusandMiddlewareContext::origin_private, read before core writes its own cache policy.trusted_server_kv) and Axum (TRUSTED_SERVER_KV_PATH, on the blocking pool). Cloudflare and Spin already open their declared store on the stack.The module
crates/provenance/encypher. Preparation applies the request gates with no I/O (GET, status200, configured domain, origin response not marked private); the stream processor holds the page and signs in its asynchronous finish. Serve phase only, so a failed signing is never stored for every reader. It requires no permission and reads no gated value. It sends the article's visible text and the page address without its query. A page whose origin set a cookie or forbade shared caching is never sent, but the module cannot detect other personalized pages: a deployment places it only on public article routes and marks personalized responses private at the origin.Removed in the port: the
enabledflag,path_prefixes(the entry'spathcovers it), the[integrations.encypher]table, the HTML stream processor factory and the shared-template refusal.Design:
docs/superpowers/specs/2026-10-24-encypher-provenance-module-design.md.Verification, run locally at e1690de or its parent
cargo fmt --all -- --checkcargo clippy-fastly,-axum,-cloudflare,-cloudflare-wasm,-spin-native,-spin-wasm,-cli,-codegencargo test -p trusted-server-provenance-encyphercargo test -p trusted-server-core --libcargo test-fastly,test-axum,test-cloudflare,test-spincargo check-cloudflare,check-spin,build-fastlycargo test --manifest-path crates/trusted-server-integration-tests/Cargo.toml --test parityscripts/lint-wasm-clock.shpython3 scripts/lint-core-platform-names.pynpx vitest run,npm run formatcd docs && npm run format; markdown prettier check outsidedocs/cargo test -p trusted-server-core --test template_build_digest, and its clippyuvx --from shellcheck-py),node --test,test.shAdapter suites ran before the last rustfmt-only change and the auction-hold test; core and module tests ran after the behavior edits.
Runtime smoke (Axum dev server, throwaway script, not committed): module selected,
[[serve]]on/news/, runtime KV on, local origin with a public and a private article. Both pages returned 200 with the article intact. The public page was held and passed through (outcome=passed_through reason=http_error, no reachable API). The private page was not held (gate=origin_private). The config sets[geo] assume_single_jurisdiction = true, which the stack requires with[ec] module;scripts/smoke-axum.shitself does not set it and stops at that check, from code and scripts this branch leaves unchanged.Limit: the runtime smoke pointed the module at a signing endpoint that was not available, to exercise fail-open. Successful signing is tested in process only, by the publisher-path tests (buffered and streaming finalizers, stub origin and stub API). The live Encypher API was not exercised.