feat(guard): add Mastra support as @arcjet/guard/mastra/v1 - #6226
Conversation
Add a versioned Mastra adapter inside @arcjet/guard (Eve pattern): guardTool returns a structured denial instead of throwing, guardProcessor abort()s on DENY, guardHooks gates unwrapped tools, and mastraAgentContext reads thread / resource / run without minting an id. Co-authored-by: David Mytton <davidmytton@users.noreply.github.com>
Split the pnpm optional-peer install by integration. Point Guard examples at arcjet/examples (PR 193) and add a root AGENTS.md so new examples are not added back to this SDK. Clarify localDetectSensitiveInfo as factory then free-text, not an opaque id. Co-authored-by: David Mytton <davidmytton@users.noreply.github.com>
Prevent skip-gate and fail-open paths: stamp/reject double-wrapped tools, keep DENY when onDeny throws, abort-return still denies, screen spoofed roles and later agentic steps, and fail closed if hooks throw. Expand unit tests to 100% line coverage, including mastra-absent CI. Co-authored-by: David Mytton <davidmytton@users.noreply.github.com>
Present each vendor peer as its own install, not a combined Eve+Mastra block. Point CONTRIBUTING at root AGENTS.md so new examples stay in arcjet/examples. Clarify the skill PII rule scans free text, not orderId. Co-authored-by: David Mytton <davidmytton@users.noreply.github.com>
Restore unrelated README formatting and leave only the split install blocks plus the three-skill count. Co-authored-by: David Mytton <davidmytton@users.noreply.github.com>
|
Cursor Agent can help with this pull request. Just |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
Arcjet Review — 🟡 Medium Risk
Decision: Needs Review
Rationale: Adds a new @arcjet/guard/mastra/v1 adapter following the established shape of the existing vercel-ai/v7 and vercel-eve/v0 namespaces. The code is thoroughly tested (assignability, context, denial, gate, guard-processor, guard-tool, hooks, index, peer, type-only), fails closed by default, never mints correlation IDs, screens all message roles on input to prevent role-spoofing bypass, and enforces type-only imports for @mastra/core (both by static scan and by a CI job that runs with @mastra/core deleted from node_modules). @mastra/core is added as an optional peer, not a hard dependency. No secrets, no injection surfaces, no runtime coupling to Mastra. Two escalation triggers fired (dependency-changes for the new optional peer, ci-cd-changes for the new workflow step), but both are well-scoped and consistent with the existing patterns for eve and ai. Approving despite Medium risk because the change surface is additive, isolated to a new subpath, and covered by a strong test suite. Size (>1000 lines) is noted but the bulk is tests and docs.
Summary of Changes
Adds a Mastra v1 integration under @arcjet/guard/mastra/v1 exporting guardTool, guardProcessor, guardHooks, and mastraAgentContext, mirroring the existing vendor namespaces. Wires @mastra/core as an optional peer, adds a CI job that verifies the mastra namespace typechecks and tests with the peer absent, adds README/CONTRIBUTING/AGENTS.md updates directing examples to arcjet/examples, and adds a Claude Code skill file and a renovate rule pinning the peer to <2.
PR Title & Description
These do not match the changes on the branch. They did not change this review's decision, but they will withhold approval once the other findings are resolved. Update them, then add the ai-review label to re-run the review.
- description (missing): The description contains only the Cursor Cloud Agent boilerplate and no summary of what the branch changes. This is a ~2800-line PR adding a new public integration surface (a
mastra/v1subpath export, optional peer dependency, CI job, skill file, and renovate rule); a reviewer or future reader has nothing to orient them beyond the title.
Suggested description
Adds a Mastra integration for `@arcjet/guard` under the versioned subpath `@arcjet/guard/mastra/v1`, alongside the existing `vercel-ai/v7` and `vercel-eve/v0` namespaces.
## What's new
- **`guardTool`** — wraps a Mastra `createTool({ execute })`. DENY returns a structured `ArcjetDenialResult` to the model; the tool never runs.
- **`guardProcessor`** — a Mastra `Processor` for `inputProcessors` / `outputProcessors`. On DENY calls `abort()` to raise a tripwire; `processInputStep` also screens later agentic steps so tool continuations cannot skip the inbound gate.
- **`guardHooks`** — `beforeToolCall` / `afterToolCall` for MCP / workspace / toolset tools that were not authored through `guardTool`.
- **`mastraAgentContext`** — reads `MASTRA_THREAD_ID_KEY`, resource, then `workflow.runId` for correlation. Never mints an id.
Mastra `requireApproval` is human HITL, so there is no `guardApproval`; channels already hit `processInput`, so there is no `guardInbound`.
## Packaging
- `@mastra/core@^1` is added as an **optional** peer (plus devDependency for tests). Nothing in the mastra namespace value-imports `@mastra/core` — enforced by a static scan and by a new CI job that runs the namespace's tests with `@mastra/core` deleted from `node_modules`.
- Export map adds `./mastra/v1` only; there is deliberately no unversioned `./mastra` alias or wildcard.
- Renovate is configured to keep `@mastra/core` on 1.x and never automerge majors.
## Docs and skill
- README gains a Mastra usage section, a split peer-install block, and a fail-closed table row.
- Adds `skills/integrate-arcjet-guard-mastra/SKILL.md` for Claude Code.
- CONTRIBUTING and a new root `AGENTS.md` direct new examples to `arcjet/examples` (per #6217), not `examples/` in this repo.
## Tests
New tests cover assignability to Mastra slots, context derivation, denial shape, the shared gate, the processor (input, step, output, role-spoofing, extraction edge cases), the tool wrapper (double-wrap rejection, denial shape, fail-closed and fail-open, brand preservation), hooks, the index barrel and export map, the optional-peer configuration, and a static scan proving every `@mastra/core` import is type-only.Escalation Triggers
- Dependency Changes:
arcjet-guard/package.jsonadds@mastra/coreas an optional peer and devDependency - CI/CD Pipeline:
.github/workflows/guard.ymladds a new 'Unit tests with mastra absent' step
Notes
PR size (~2800 lines added) exceeds the 1000-line threshold for reliable automated review; bulk is tests and docs but a human skim of guard-processor.ts and guard-tool.ts is worth doing. Two escalation triggers fired (optional peer dependency, new CI job). No security issues found under the security-review checklist: no hardcoded secrets, no injection surfaces, fail-closed by default, correlation IDs validated and never minted, input processor screens all roles (not just user) to prevent role-spoofing bypass, type-only imports enforced statically and dynamically.
Path filtering: 1 file excluded by ignore paths. 27 of 28 files included in review.
Approval withheld: The PR title or description does not match the branch — see the "PR Title & Description" section. Update them, then add the ai-review label to re-run the review.
Review: 568074d1 | Model: anthropic/claude-opus-4-7 | Powered by Arcjet Review
Restore the @sveltejs/kit and cookie override versions so npm ci matches package.json. Apply review feedback: null-first type guards, Symbol state marker, shouldWarn on hook throws, empty-string metadata, and a >=1 <2 peer. Co-authored-by: David Mytton <davidmytton@users.noreply.github.com>
Adds a Mastra integration for
@arcjet/guardunder the versioned subpath@arcjet/guard/mastra/v1, alongside the existingvercel-ai/v7andvercel-eve/v0namespaces.What's new
guardTool— wraps a MastracreateTool({ execute }). DENY returns a structuredArcjetDenialResultto the model; the tool never runs.guardProcessor— a MastraProcessorforinputProcessors/outputProcessors. On DENY callsabort()to raise a tripwire;processInputStepalso screens later agentic steps so tool continuations cannot skip the inbound gate.guardHooks—beforeToolCall/afterToolCallfor MCP / workspace / toolset tools that were not authored throughguardTool.mastraAgentContext— readsMASTRA_THREAD_ID_KEY, resource, thenworkflow.runIdfor correlation. Never mints an id.Mastra
requireApprovalis human HITL, so there is noguardApproval; channels already hitprocessInput, so there is noguardInbound.Packaging
@mastra/core@^1is added as an optional peer (plus devDependency for tests). Nothing in the mastra namespace value-imports@mastra/core— enforced by a static scan and by a new CI job that runs the namespace's tests with@mastra/coredeleted fromnode_modules../mastra/v1only; there is deliberately no unversioned./mastraalias or wildcard.@mastra/coreon 1.x and never automerge majors.Docs and skill
skills/integrate-arcjet-guard-mastra/SKILL.mdfor Claude Code.AGENTS.mddirect new examples toarcjet/examplesin arcjet/examples@d17cc19 (per chore(examples): remove examples migrated to arcjet/examples #6217), notexamples/in this repo.Tests
New tests cover assignability to Mastra slots, context derivation, denial shape, the shared gate, the processor (input, step, output, role-spoofing, extraction edge cases), the tool wrapper (double-wrap rejection, denial shape, fail-closed and fail-open, brand preservation), hooks, the index barrel and export map, the optional-peer configuration, and a static scan proving every
@mastra/coreimport is type-only.