Skip to content

feat(core): capability manifests checked against the real API modules - #698

Open
seanspeaks wants to merge 6 commits into
claude/shared-conversation-8hgmbr-stack-6-previewsfrom
claude/shared-conversation-8hgmbr-stack-7-manifest-audit
Open

seanspeaks wants to merge 6 commits into
claude/shared-conversation-8hgmbr-stack-6-previewsfrom
claude/shared-conversation-8hgmbr-stack-7-manifest-audit

Conversation

@seanspeaks

@seanspeaks seanspeaks commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Stack 7 of 9. Stacked on #697.

Summary

The capability manifests started out as mocks. This PR checks each one against the Api class it names.

  • scripts/check-manifests.js. It loads each module's Api with no network calls and nothing instantiated. Then it checks that every method exists and that every call matches the method's real signature.
  • Positional arguments. Real methods take positional arguments (getContactById(id)), so a capability can now declare args:
    • input names, in order;
    • "$rest", the remaining inputs as one object;
    • { "value": x }, a constant.
  • Dropped inputs are refused. An input that is declared but never passed would be accepted and then silently dropped, so the check rejects it.
  • Missing methods warn. A capability whose method does not exist upstream is marked "status": "unimplemented". A definition that uses it validates with a warning, not an error.
  • AUDIT.md records the result per module: method renames, call-shape fixes, and what is missing upstream. It also notes the HubSpot updateDeal fix upstream.

PR 9 resolves the missing methods.

Test plan

  • Same 31 pre-existing failures as next at this commit. Nothing new fails.
  • real-manifests.test.js exercises warnings and args spreading.

Generated by Claude Code


Note

Medium Risk
Changes how data-defined integrations invoke module APIs (positional args); many capabilities are now marked unimplemented with validate-time warnings only, so workflows may pass validation but fail or skip behavior at runtime until modules catch up.

Overview
Aligns data-defined capability manifests with real API module Api classes instead of mock method names and single-object call shapes.

Adds scripts/check-manifests.js and capabilities/AUDIT.md to load each module’s Api (no network) and report method existence, arity, and webhook verify. Manifests for nine checked modules gain args (positional inputs, "$rest", { "value" } constants), status: "unimplemented" with notes where upstream is missing or mismatched, and corrected method names (e.g. HubSpot getContactById, Phone createUnifiedWebhook). Runtime now spreads arguments via argumentsFor through runtime.js, data-defined-integration.js, and tests/fakes.

Validation extends the manifest schema and manifests.js (strict args / no silent dropped inputs) and validate.js so definitions that reference unimplemented capabilities, sync paths, option lists, or webhook verification get warnings, not hard errors. Example definitions drop unsupported inputs (e.g. HubSpot properties, Asana opt_fields). ADRs 020 and 063 document manifest ↔ capability graph alignment and future co-location of manifests in module packages.

Reviewed by Cursor Bugbot for commit b1a2d30. Bugbot is set up for automated code reviews on this repo. Configure here.

📦 Published PR as canary version: 2.0.0--canary.698.b1a2d30.0

✨ Test out this PR locally via:

npm install @friggframework/admin-scripts@2.0.0--canary.698.b1a2d30.0
npm install @friggframework/core@2.0.0--canary.698.b1a2d30.0
npm install @friggframework/devtools@2.0.0--canary.698.b1a2d30.0
npm install @friggframework/eslint-config@2.0.0--canary.698.b1a2d30.0
npm install @friggframework/prettier-config@2.0.0--canary.698.b1a2d30.0
npm install @friggframework/schemas@2.0.0--canary.698.b1a2d30.0
npm install @friggframework/serverless-plugin@2.0.0--canary.698.b1a2d30.0
npm install @friggframework/test@2.0.0--canary.698.b1a2d30.0
npm install @friggframework/ui@2.0.0--canary.698.b1a2d30.0
# or 
yarn add @friggframework/admin-scripts@2.0.0--canary.698.b1a2d30.0
yarn add @friggframework/core@2.0.0--canary.698.b1a2d30.0
yarn add @friggframework/devtools@2.0.0--canary.698.b1a2d30.0
yarn add @friggframework/eslint-config@2.0.0--canary.698.b1a2d30.0
yarn add @friggframework/prettier-config@2.0.0--canary.698.b1a2d30.0
yarn add @friggframework/schemas@2.0.0--canary.698.b1a2d30.0
yarn add @friggframework/serverless-plugin@2.0.0--canary.698.b1a2d30.0
yarn add @friggframework/test@2.0.0--canary.698.b1a2d30.0
yarn add @friggframework/ui@2.0.0--canary.698.b1a2d30.0

…API modules

Audit every manifest method against the Api classes in api-module-library and
quo--frigg. Add args (positional calls), status: unimplemented (a definition
warning, never an error) and webhook.status, fix renamed methods and shapes,
add scripts/check-manifests.js and capabilities/AUDIT.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGC9SnFuqdjX2xH2qeu8vw

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization has no extra usage available to pay for this review.

If your organization's extra usage balance is empty, an organization admin can add extra usage credits at claude.ai/admin-settings/usage. If its monthly spend limit was reached, an admin can raise it on the same page. If neither applies, contact Anthropic support.

Once extra usage is available, someone with write access to this repository can comment @claude review on this pull request to trigger a review.

@seanspeaks seanspeaks added release Create a release when this pr is merged prerelease This change is available in a prerelease. labels Oct 19, 2026 — with Claude

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

if (t.type === 'webhook') {
if (!manifestOf[t.module]) err(`${p}.trigger.module`, `Unknown module key "${t.module}"`);
else if (!manifestOf[t.module].events?.[t.topic]) err(`${p}.trigger.topic`, `Module "${t.module}" emits no event "${t.topic}"`);
else if (manifestOf[t.module].webhook?.status === 'unimplemented' && (manifestOf[t.module].events[t.topic].delivery || 'webhook') === 'webhook') warn(`${p}.trigger`, `${t.module} events arrive by webhook, but the ${manifestOf[t.module].module} Api has no ${manifestOf[t.module].webhook.verify || 'verify'} method, so every delivery fails signature verification`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Webhook syncs skip verify warning

Medium Severity

Unimplemented webhook verification warns only for webhook-triggered workflows. A sync with ongoing.mode webhook gets no warning, even though onWebhook still calls verify and rejects every delivery when that method is missing, so the sync never receives events.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3f651f7. Configure here.

@seanspeaks

Copy link
Copy Markdown
Contributor Author

ADR reconciliation needed after Stack A/B — drafted with Claude Code at Sean's request

Severity: must-reconcile. Capability manifests (schema/capability-manifest.v0.1.schema.json, scripts/check-manifests.js) are a second declaration of what ADR-020 (on next) and ADR-045 (#648) already define. ADR-020 lives on next, so please include an ADR-020 amendment in this PR.

Overlap

ADR-020/045 (module Definition.capabilities) 063 manifest (separate JSON)
key crm.contact.list key contact.list (<object>.<verb>)
surface: data-read / data-write / webhook-source kind: read / write; events + webhook
implementedBy: { kind: 'api-class-method', ref: 'HubSpotApi.listContacts' } method: 'listContacts', args
traits (read.pageMax, delta.modifiedSince, time.modifiedAt) objects.<x>.sync (limit, since, updatedAt)

Module paging is also described in ADR-054 §6's objects descriptor (#669). check-manifests.js is ADR-045 §5's "traits must be falsifiable", applied to method existence.

Proposed ADR-020 amendment (in this PR)

  1. The capability manifest is the serialised form of a module's Definition.capabilities. It is checked or generated against the module, never hand-maintained separately. Map kind to surface and method to implementedBy.ref.
  2. Pick one capability key convention. Recommended: ADR-020's <domain>.<object>.<verb>, so contact.list becomes crm.contact.list, or record that the domain is implied by the module.
  3. Manifest events/webhook are webhook-source capabilities sourced from extension contract 2 (054 §2).
  4. Routes. ADR-020's GET /api/capabilities (Visibility consumption) is an unprefixed route, which ADR-053 (docs(adr): ADR-052 entity proxy security, ADR-053 Management API versioning #668) forbids. Change it to a registry route, GET /api/v2/capabilities. Also note that ADR-053's /api/meta capabilities array (API features such as entityProxy) is a different thing: rename one of them (for example meta features) to avoid two "capabilities". This PR adds no route itself, which is good.
  5. Fix the stale surface list in ADR-020's prose (045 already flags it).

Code: move manifests to ship with the API module, as 063 §9 intends, rather than under core/integrations/definitions/capabilities/. Once they live in the module, #700's args fixes travel with the module releases.

Merge order: #648 (045 traits) → this PR with the 020 amendment → #700. The api-module-library PRs #105–#110 come before #700.

…th modules

- ADR-020: Amendment (ADR-063). The manifest is the serialised form of a
  module's Definition.capabilities; key convention (domain implied by the
  module for now, crm.contact.list the target); webhook events are
  webhook-source capabilities (ADR-054 contract 2); GET /api/capabilities
  moves to /api/v2/capabilities; /api/meta "capabilities" naming clash.
- ADR-063 section 9: manifests should move to ship with each module.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGC9SnFuqdjX2xH2qeu8vw
…ier levels); neutral names in the manifest audit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGC9SnFuqdjX2xH2qeu8vw
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGC9SnFuqdjX2xH2qeu8vw
@sonarqubecloud

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b1a2d30. Configure here.

"output": "contact",
"args": [
"properties"
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create contact args unwrap properties wrapper

Medium Severity

hubspot.contact.create now sets args to ["properties"], so the runtime calls createContact with the inner properties object. The audited signature is createContact(body) with a single parameter, and HubSpot's create endpoint expects a properties envelope. Previously the whole input { properties: … } was passed as that one argument. Sync and workflow creates can POST a body the Api did not shape for, while contact.update already takes a bare properties argument as a second positional parameter.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b1a2d30. Configure here.

Copy link
Copy Markdown
Contributor Author

Release review follow-up: the ADR-020 amendment is now in this PR (b1a2d30f).

  • What a manifest is: the serialised form of a module's Definition.capabilities, checked or generated against the module. kind maps to surface, and method maps to implementedBy.ref.
  • Key convention: for now the domain is implied by the module. The target is crm.contact.list.
  • Webhook events: they are webhook-source capabilities from ADR-054 contract 2.
  • Routes: GET /api/capabilities becomes /api/v2/capabilities. The /api/meta "capabilities" name clash is noted and left for a decision.
  • ADR-063 §9: manifests should ship with each module. The move itself is a follow-up.

Generated by Claude Code

@cursor

cursor Bot commented Oct 24, 2026

Copy link
Copy Markdown

Stack B review (COMMENT only) — Group 4

Verdict (would merge?): would approve

Should-fix

  • Several modules remain AUDIT “unverified” but are not marked unimplemented, so definitions validate clean against mock manifests while runtime can hit missing Api methods. Documented; still a production footgun until audited.

Notes

argumentsFor / ordered callApi, check-manifests.js, and intentional webhook unimplemented fail-closed until later stack PRs look correct. No blocking items.

@@ -0,0 +1,451 @@
# Capability manifests against the real API modules

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[should-fix] Modules listed here as unverified (but not unimplemented) still validate clean against mock manifests; runtime can then hit missing Api methods. No blocking findings on the checker itself — see top-level Stack B COMMENT summary.

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

Labels

prerelease This change is available in a prerelease. release Create a release when this pr is merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants