Repository navigation
fix(contextual_access): redact post-hook content alongside output [PLT-3790] - #5
Merged
Merged
Conversation
…LT-3790) 10b2909 moved every example from examples/<name>/ into examples/contextual_access/<name>/ and updated the workflow's `file:` paths, but the Dockerfiles still COPY and build examples/<name>/. Every build-and-push job has failed on main since then with `"/examples/<name>": not found`. Point each Dockerfile's COPY and go build at the new path. The same commit raised go.mod to `go 1.26.0`, which the golang:1.25-alpine builder rejects at `go mod download`, so move the builder to golang:1.26-alpine. Also update the .dockerignore entry for the committed advanced_server binary, which was moved too, so it stays out of the build context. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Regenerate pkg/server/schema.gen.go from ArcadeAI/schemas main, which adds ContentBlock, the post-hook request's optional `content`, and `override.content`. It also picks up the tool metadata types (ToolBehavior, ToolClassification) that landed in the schema earlier. Related engine change: PLT-3746. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
wdawson
force-pushed
the
wils/plt-3746-examples-content
branch
from
September 28, 2026 22:24
a3ee41e to
63eeb0f
Compare
Post-hook requests from remote MCP servers now carry `content`, the content blocks the server returned alongside its structured result, and clients see those blocks too. A hook that rewrites only `output` leaves the server's own text in `content` as it was sent. pii_redactor and content_filter now apply their existing output handling to `content` text blocks, the blocks MCP gateways render, and return the result as `override.content`. Other block types pass through unchanged. advanced_server, the comprehensive example, scans and redacts every string field of every block (text, uri, annotations, _meta, an embedded resource's text) and leaves base64 payloads (image/audio `data`, resource `blob`) as-is, since a regex match inside them would alter the encoded bytes. Block modes and keyword checks consider content too. Related engine change: PLT-3746. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
basic_rules and advanced_server post rules can replace a tool's output with a fixed value. With a remote MCP server, the original `content` blocks would still reach the client beside the replacement. When the request carries content, such a rule now also returns an empty `override.content`, which removes the server's blocks so clients get the replacement output rendered as text. Related engine change: PLT-3746. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The post-hook flattened output and content into one string before matching rules. An anchored pattern such as ^secret$ could then never match: with no output, the flattened string starts with "<nil>", so a text block containing exactly "secret" passed through unfiltered, and with several output fields the join defeated anchors too. Check keywords and patterns against each output value and each value in content text blocks on its own. Replacements were already applied per string, so they are unchanged. The content matching was introduced in f6091a4. Refs PLT-3790. Related engine change: PLT-3746. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
wdawson
force-pushed
the
wils/plt-3746-examples-content
branch
from
September 28, 2026 22:48
63eeb0f to
8aaec30
Compare
…(PLT-3790) The READMEs, usage comments, example configs, and the cert script still used ./examples/<name> from before the move (and ./tools/webhook-test-server for basic_rules). They now use ./examples/contextual_access/<name>, run from the repository root. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The pre-hook joined every input value into one string, so an anchored input pattern missed when a tool had more than one input. It now checks each input value on its own with leafValues and anyField, as the post-hook does since 8aaec30. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…790)
The phone pattern began with \b, which can't match before "(" or "+", so
"(555) 123-4567" became "([PHONE REDACTED]" and "+1 555-123-4567" became
"+[PHONE REDACTED]". The match can now start at "(" or "+". It matches the
same strings as before and only extends the match to the left.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Formatting only. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every example server listens on -port 8888 by default, but the Dockerfiles exposed 8080. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The READMEs, usage comments, and example config headers passed -config files that aren't in the repo (experiments.yaml, filter-rules.yaml, blocked-users.yaml, config.yaml), or a bare example-config.yaml that isn't found from the repository root. They now point at each example's committed example-config.yaml. The go run paths were fixed in 9849e78. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
wdawson
marked this pull request as ready for review
September 28, 2026 23:18
sdreyer
approved these changes
Sep 28, 2026
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.
Linear: PLT-3790. Related engine change: PLT-3746 (ArcadeAI/monorepo#4556). Schema: ArcadeAI/schemas#31. Docs: ArcadeAI/docs#1217, which merges after this.
Why
Post-hook requests from remote MCP servers now include
content, the blocks the server returned alongsideoutput, and clients receive them. These examples now apply the same redaction and filtering tocontentas tooutput.Changes
COPYand buildexamples/contextual_access/<name>/, the builder image isgolang:1.26-alpineto matchgo.mod, and the.dockerignoreentry for the committedadvanced_serverbinary uses its new path. The earlier move (10b2909) had changed all three, and everybuild-and-pushjob had been failing since.pkg/server/schema.gen.go: regenerated from schemasmain(ContentBlock,content,override.content).contenttext blocks as well, in both redact and block modes.contenttext blocks, andreplacerules rewrite them. Rules match each field on its own, so anchored patterns work.contentblock. Fixed-output rules clearcontent.content.contentgets the same treatment.go run ./examples/contextual_access/<name>. They had used the paths from before the move, and./tools/webhook-test-serverfor basic_rules. Their-configflags point at each example's committedexample-config.yaml, so the documented commands find their config when run from the repository root.(or+:(555) 123-4567now becomes[PHONE REDACTED], not([PHONE REDACTED]. It matches the same strings as before.advanced_server/ab_testing.gois gofmt-clean.EXPOSE 8888, the servers' default port.Judgment calls
contenttext blocks, the blocks MCP gateways render, going as deep as they already go intooutput. Other block types pass through unchanged. advanced_server, the comprehensive example, walks every block but leaves base64 payloads (image/audiodata, resourceblob) untouched, since a pattern match inside them would alter the encoded bytes.outputwith a fixed value returnsoverride.content: []. Clients then receive the newoutputas a single text block.override.contentis sent only when the request carriedcontent, so responses for non-MCP tools are unchanged.Testing
No test suite exists.
go build ./...andgo vet ./...pass at every commit, andgofmt -l .is clean on the final commit.docker buildsucceeds for all six examples from the repo root, the same context the workflow uses. I ran each changed example locally and checked with curl that post-hook requests carryingcontentcome back withoverride.contentredacted or filtered. For the cleanups, I compared each change before and after with curl: pre-hook inputs with several fields, and phone numbers against ordinary numbers and other PII. I also ran one image withdocker run -p 8888:8888and checked/health.🤖 Generated with Claude Code