Skip to content

0.9.3

Choose a tag to compare

@github-actions github-actions released this 25 Oct 12:25
· 62 commits to main since this release

A security fix for the BTP sign-in, current dependencies, and features: feature create and update, a flag for document images the API leaves out, project_name for calm_list, and an audit log for writes.

Security

  • Sign-in now asks the user to approve the client (GHSA-6935-r3wv-f646, high). With @arc-mcp/xsuaa-auth 1.1.0, a client registered by anyone could complete the XSUAA sign-in through an existing SSO session without the user's consent and act with the user's calmcp access. @arc-mcp/xsuaa-auth 1.2.0 shows an approval page with the client's name and return address before every sign-in; Deny ends it without access (#35, thanks @marianfoo).
  • XSUAA returns sign-ins only to calmcp's own callback. xs-security.json allowed https://*.hana.ondemand.com/**; mta.yaml now sets the exact <app route>/oauth/callback (#35). The token lifetimes from xs-security.json (1 hour, refresh 30 days) are kept (#37).
  • Dependencies with known vulnerabilities updated: MCP SDK 1.32.1, Express 5.3.0 (proxy-addr, critical), undici, zod, follow-redirects, hono, body-parser and others (#38). node-forge, used by the SAP Cloud SDK to read keystores, has no fixed version; per SAP's assessment calmcp does not reach the affected code. CI accepts this one advisory until 31 December 2026 (#38).
  • A local mbt build no longer packs local, gitignored files (notes, assistant settings) into the app (#39).

Upgrading a BTP deployment

  • Run a full cf deploy of the new mtar. Pushing only the app keeps the old wildcard callback in the XSUAA instance. With cf push, add https://<app route>/oauth/callback to xs-security.json and run cf update-service calmcp-xsuaa -c xs-security.json. Behind a custom domain, add its callback in an .mtaext.
  • Sign-ins in progress during the upgrade start again. Tokens issued before the upgrade are not revoked by it; if misuse is suspected, have the XSUAA administrator revoke them.
  • A reverse proxy in front of calmcp must pass Cookie, Set-Cookie and Origin through, and calmcp needs one public URL (CALM_PUBLIC_URL behind a custom domain). See docs/XSUAA-AUTH-UPGRADE.md.

Features

  • calm_create creates features with a title, an HTML description, status, priority and the other editable fields (#24).
  • calm_update changes existing features (title, description, status, priority, scope, responsible, release, workstream), behind the new switch CALM_UPDATE_ENABLED (off by default) and the Writer scope. It sends only changed fields with PATCH, refuses the call when the feature changed since it was read (expected_modified_at), refuses a description that would drop an image unless remove_images names it, and returns every changed field before and after. null clears scope, responsible, release or workstream (#24, see docs/UPDATES.md).
  • Rich text is checked before it is written. calm_create and calm_update refuse scripts, event handlers, javascript:/data: URLs and images from outside Cloud ALM's image service (#24).
  • Documents flag images the API leaves out. The Documents API returns content without <img> tags; calm_get and calm_list now mark such documents with imagesOmitted: true (#24).
  • calm_list takes project_name instead of project_id (case and spacing ignored); an unknown or ambiguous name is refused with the candidates (#28).
  • Audit log for writes. Every created entity and every applied update is logged with the caller (the BTP user, or local), the entity and the changed fields; refused calls and no-ops are not (#24, #26).

Fixes

  • Tool schemas no longer contain a regex lookahead. Hosts that validate schemas with a regex subset (OpenAI's strict mode, for one) rejected the whole tool list. . and .. are still refused as ids (#40).

Internal

  • CI runs the dependency audit with audit-ci (npm run audit:ci) so the one accepted advisory expires on a date (#38).
  • Tested against a productive Cloud ALM tenant (read checks, feature create and update) and on BTP (sign-in with approval and Deny, callback, token lifetime, API key).