Add /_skill-validation monitoring endpoint#5472
Conversation
monitoringAuthToken is async, but handle-queue-status interpolated the un-awaited Promise into its comparison string, so /_queue-status actually authorized the literal token "[object Promise]" (and the test passed because it interpolated the same Promise client-side). Move the comparison into utils/monitoring.ts as isAuthorizedToViewMonitoring and await the token on both sides. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Validates that every skill in a realm still resolves: enumerates Skill cards via the index, imports each unique command codeRef module through the prerenderer (a real host in headless Chrome, with the same shims and virtual network a user's browser has), and returns structured pass/fail per skill with the failing module path. Motivated by the CS-10992/CS-11046 staging incident where a renamed host command path silently broke the AI assistant while API health checks stayed green. The module prerender response now carries all export names (not just BaseDef definitions) so the endpoint can also catch a renamed export whose module still loads. Authenticated with the monitoring bearer token, same as /_queue-status. A Checkly check in cardstack/infra will poll this per environment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Preview deploymentsHost Test Results 1 files ±0 1 suites ±0 3h 3m 23s ⏱️ +57s Results for commit fc85798. ± Comparison against earlier commit 8b2e697. Realm Server Test Results 1 files ±0 1 suites ±0 11m 42s ⏱️ +18s Results for commit fc85798. ± Comparison against earlier commit 8b2e697. |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop the CS-11093 tracker references and the staging-incident narrative from the handler and route comments; state the threat model as the live invariant instead. Rename the failure-reporting test timelessly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5c28187b96
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Permission rows are keyed by full Matrix user id, so fetching them with the bare username returned empty permissions and the prerender ran anonymously — private realms reported module auth failures for valid skills. Use the owner's user id and ensure owner permissions on the target realm, matching the indexer's render path. The healthy-skills test now runs against an owner-only realm to cover this. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A skill is either a legacy Skill card or a markdown file with boxel.kind: skill frontmatter, whose frontmatter.tools carries the same ToolField codeRefs as Skill.commands. The endpoint only searched Skill card instances, so a realm with broken markdown-skill tool modules reported pass. Query kind: 'skill' file entries via searchFiles and feed their tool refs through the same prerender validation, reading the legacy frontmatter.commands key when a pre-rename index row has no tools value (mirroring the host's getSkillSourceTools fallback). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The platform renamed skill-attached "commands" to "tools" to align with the agentic programming model, so this new endpoint's response reports toolsChecked rather than baking the deprecated term into monitoring consumers. Internal names and test fixtures follow; the Skill card's pre-rename commands field and the legacy frontmatter commands key keep their serialized spellings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
/_skill-validation monitoring endpoint
There was a problem hiding this comment.
Pull request overview
Adds a new realm-server monitoring endpoint (/_skill-validation) that Checkly can poll to verify that all skills in a realm reference tool modules/exports that the deployed host can actually load (via the prerenderer), preventing “silent” integration breakages (e.g. module renames / export renames) that won’t show up as unit-test failures.
Changes:
- Introduces
/_skill-validationrealm-server route + handler that finds skill sources (legacySkillcards + skill-markdown files) and validates referenced tool codeRefs by prerendering unique modules and checking export names. - Extends the module prerender/model response contract with an optional
exports?: string[]list, and populates it in the host/moduleroute. - Refactors monitoring auth into a shared async helper (
isAuthorizedToViewMonitoring) and adds comprehensive realm-server endpoint tests for both failure and success cases.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| packages/runtime-common/index.ts | Adds optional exports?: string[] to ModulePrerenderModel/ModuleRenderResponse contract for non-BaseDef export validation. |
| packages/runtime-common/constants.ts | Adds markdownDefRef to query for MarkdownDef file rows (skill-markdown discovery). |
| packages/realm-server/utils/monitoring.ts | Adds shared async isAuthorizedToViewMonitoring() used by monitoring endpoints. |
| packages/realm-server/handlers/handle-queue-status.ts | Switches to shared async monitoring auth helper (fixes token comparison correctness with async token derivation). |
| packages/realm-server/routes.ts | Registers new /_skill-validation endpoint. |
| packages/realm-server/handlers/handle-skill-validation.ts | Implements the monitoring endpoint: skill discovery + prerender-based module/export validation + JSON:API response. |
| packages/realm-server/tests/server-endpoints/skill-validation-test.ts | New tests covering auth requirements, bad params, module-load failures, missing-export failures, and private-realm success. |
| packages/realm-server/tests/server-endpoints/queue-status-test.ts | Fixes test to await the async monitoring token. |
| packages/realm-server/tests/index.ts | Adds the new skill-validation test file to the test suite. |
| packages/host/app/routes/module.ts | Adds exports: Object.keys(module) to ready module models so prerender responses can report export names. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The skill-validation endpoint found markdown skills with a
searchFiles({ on: MarkdownDef, eq: { kind: 'skill' } }) query. The
eq filter makes the query resolve MarkdownDef's field definition, and
when that lookup misses the search engine swallows the error into an
empty result set — so every markdown skill was silently dropped and the
endpoint under-reported its skill/tool counts. Switch to a type-only
file search (which matches the indexed types column and needs no field
definition) and narrow to kind: 'skill' in JS.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
In an early step of the
@cardstack/basemigration, the AI assistant was broken because skills imports had changed and there was no test suite failure, it’s more of an integration question.This adds an endpoint that Checkly can poll, it reports whether each loaded skill’s tools load properly.
With this branch deployed to staging:
The corresponding Checkly check passed when it was deployed:
Here’s an example response with failures: