feat(actions): disclose requiredPlan on action schemas and document /api/features - #2362
feat(actions): disclose requiredPlan on action schemas and document /api/features#2362subheeksh5599 wants to merge 2 commits into
Conversation
About the
|
joelorzet
left a comment
There was a problem hiding this comment.
The shape is right. Resolving through resolveActionFeature rather than the static FEATURES table is the detail that makes this correct, because a table-only lookup misses every plugin gated by the egress catch-all. Blockscout is exactly that case, pro-gated with no registry entry naming its action types, and your test covers it.
Emitting the static requirement rather than the caller's plan is also the right call, and it keeps /api/mcp/schemas anonymous and cacheable. The precedent holds: app/api/workflows/public/route.ts already returns requiredPlan to unauthenticated callers.
Copying SYSTEM_ACTIONS instead of mutating it matters too, since the workflow validator and the builder UI share that constant.
One blocker, inline. Fix that and this merges.
| import { eq } from "drizzle-orm"; | ||
| import { db } from "@/lib/db"; | ||
| import { chains, explorerConfigs } from "@/lib/db/schema"; | ||
| import { resolveActionFeature } from "@/lib/features/action-egress"; |
There was a problem hiding this comment.
This import breaks an existing test suite, and test-integration is red because of it.
Eight cases in tests/integration/action-schemas-route.test.ts now fail during setup with the same error:
Error: [vitest] No "findActionById" export is defined on the "@/plugins/registry" mock.
Did you forget to return it from "vi.mock"?
Pulling in resolveActionFeature brings findActionById into that module graph, and the suite's vi.mock("@/plugins/registry") does not stub it. Every test in the file dies before it runs, so the route they cover is currently unexercised rather than merely failing.
Extend that mock to return findActionById, or break the import chain so the builder does not reach the registry. Either is fine.
… for egress resolution
4c4827d to
09036c6
Compare
Fixes #2279.
What
An agent building a workflow over REST or MCP cannot see which actions require a paid plan until
POST /api/workflows/createrejects the finished workflow withupgrade_required. The action catalog's wire projection (ActionSchema) carried no plan field, and the/api/featuressnapshot that would answer the question was undocumented with no pointer from any agent-facing page.lib/action-schemas/builder.ts-ActionSchemanow carriesrequiredPlan: string | null. Both write sites populate it throughresolveActionFeature, not the staticFEATUREStable, so the egress-derived catch-all gate is included (a plugin like blockscout that lets the user point at a destination of their choosing is pro-gated with no registry entry naming its action types):transformPluginAction(plugin actions):resolveActionFeature(actionType)?.requiredPlan ?? nullSYSTEM_ACTIONSentry is copied and enriched with its resolved requirement (the shared constant is not mutated; ungated system actions like Condition / For Each resolve to null)The field emits the static requirement, never the caller's plan, so
GET /api/mcp/schemasstays anonymous and publicly cacheable (same precedent asapp/api/workflows/public/route.tswhich already returnsrequiredPlanto unauthenticated callers).lib/mcp/tools.ts-search_protocol_actionscompact projection now carriesrequiredPlanthrough (its local type dropped unknown fields, so this is the one place the new field would otherwise vanish).docs/api/workflows.md- documentsrequiredPlanon the action-schema response and documentsGET /api/features(the org feature snapshot: plan, enabled feature ids, full registry) for the first time.specs/api-coverage.jsonregenerated (the new/api/featuressection is now fence-owned by workflows.md).Test
tests/unit/action-schema-required-plan.test.ts: explicitly gated plugin action (code/run-code-> pro), egress-gated plugin action with no FEATURES entry (blockscout -> pro, the case a table-only lookup misses), ungated plugin action (null), gated system actions (HTTP Request / Database Query -> pro), ungated system actions (null). 5 tests; related suites (features-egress-invariant, action-output-fields, action-config-helpers) pass.