Skip to content

feat(agent-readiness): close the agent-journey gaps — pricing/signup/support discovery + status advertisement fixes (#4850 #4854 #4856 #4857)#4867

Merged
koala73 merged 1 commit into
mainfrom
feat/agent-journey-gaps
Jul 5, 2026
Merged

feat(agent-readiness): close the agent-journey gaps — pricing/signup/support discovery + status advertisement fixes (#4850 #4854 #4856 #4857)#4867
koala73 merged 1 commit into
mainfrom
feat/agent-journey-gaps

Conversation

@koala73

@koala73 koala73 commented Jul 5, 2026

Copy link
Copy Markdown
Owner

What

One coordinated batch closing all four agent-journey readiness issues — they share llms.txt (×3), vercel.json (×3), and the well-known files (×2), so separate PRs would conflict on every shared surface.

Closes #4850 · Closes #4854 · Closes #4856 · Closes #4857

Why

Five external agent-journey runs (Claude Code · Sonnet 4.6) probed the site with real intents. The split was exact:

Intent Steps / tokens Outcome
Integration 16 / 83k clean — discovery chain self-bootstrapping
Developer auth 28 / 258k one bug (#4856)
Signup 25 / 212k #4850
Pricing 44 / 848k #4854
Support 37 / 851k #4857

Intents answerable via the Link-header → .well-knownauth.md/OpenAPI chain cost ~5–10× less. Pricing/signup/support lived only in llms.txt (or nowhere) — agents on the well-known chain guessed slugs, hit UA-403s, and parsed misleading-200 SPA shells.

Changes by issue

#4850 — signup

  • UA policy documented in llms.txt, llms-full.txt, auth.md: descriptive User-Agent required; the edge WAF challenges curl/*/python-requests/*/short UAs and masks 404s as 403s for them.
  • docs/accounts.mdx: free tier needs no account; Clerk modal flow (not fetchable — agents are told so); MCP OAuth path for agent credentials.
  • /blog/posts/blog 301 (posts live at /blog/posts/<slug>/; the parent had no index).

#4854 — pricing

  • .well-known/api-catalog: RFC 9727 service-meta on the API context advertising pricing.md, the live GET /api/product-catalog JSON, and support.md.
  • middleware.ts: /api/product-catalog added to PUBLIC_API_PATHS (was UA-403'd for the exact agents it exists to serve) + robots.txt Allow carve-out, mirroring the /api/llms.txt precedent. DELETE stays behind the endpoint's own auth — the bypass only skips UA filtering.
  • docs/pricing.mdx + tests/pricing-docs-drift.test.mjs: prices asserted against convex/config/productCatalog.ts source text (no generator import), so a catalog price change names every stale doc.
  • docs/openapi/CommerceService.openapi.yaml wired into the api-reference nav. Deliberately outside docs/api/ (fully generated dir — proto-check regen diff + injector scripts) and outside the root spec (fix(agent-readiness): $ref-dedupe error responses in /openapi.json — back under orank's ~1MB function-calling cap #4853 ~1MB size budget).
  • docs.json redirects for every slug the journey agent guessed: plans/tierspricing, rate-limit(s)usage-rate-limits, mcp-api-keyusage-auth.
  • pricing.md: Limits & Overage section (hard 429 + Retry-After, no silent overage billing — worded to survive feat(api): add Dodo overage event contract #4791), JSON catalog pointer, UA note.

#4856 — status advertisement (stale since #4715)

  • api-catalog status href + 3× vercel.json Link rel="status"/api/health?compact=1 (keyless 200; the bare form 401s since fix(security): require auth for detailed health metadata #4715).
  • /api/health 401 now carries WWW-Authenticate with RFC 9728 resource_metadata (RFC 7235 §3.1 — it was absent entirely) + a body hint naming the compact form.
  • New deploy-config guards: every advertised status URL must be the keyless compact form; the next auth-gating change can't silently strand the advertisements.

#4857 — support

  • public/support.md (root, sitemap-listed) + docs/support.mdx: all channels consolidated (support@ / enterprise@, GitHub issues, Discord, status page; Turnstile form marked human-only) + explicit per-tier no-SLA statement.
  • /contact, /support, /help 301 → /docs/support (all three served the misleading-200 dashboard SPA shell).
  • server-card.json documentation block: support repointed (was getting-started), pricing + productCatalog added.

Out of scope (deliberate)

Verification

  • tests/middleware-bot-gate.test.mts 53 pass (new product-catalog bypass block + exact-path negative)
  • tests/deploy-config.test.mjs 107 pass (status-compact + Link-header + service-meta guards)
  • tests/health-redis-down-status.test.mjs 8 pass (WWW-Authenticate + hint contract)
  • tests/pricing-docs-drift.test.mjs 7 pass (new)
  • llms/agent-mode/a2a/mcp-parity + product-catalog suites: 64 pass
  • docs:check green, tsc --noEmit green, all edited JSON/YAML parse

https://claude.ai/code/session_01N3xTXNUrCiy1xqy3VbkMRx

…support discovery + status advertisement fixes

Five external agent-journey runs (signup, pricing, developer-auth, support,
integration intents) showed a clean split: intents answerable via the
Link-header → .well-known → auth.md chain scored 90-100%, while pricing,
signup, and support — discoverable only via llms.txt or nowhere — forced
agents into slug-guessing, UA 403s, and misleading-200 SPA shells.

Closes #4850 (signup journey):
- llms.txt/llms-full.txt + auth.md: document the descriptive User-Agent
  policy (edge WAF challenges curl/*, python-requests/*, short UAs — and
  masks 404s as 403s for those UAs)
- docs/accounts.mdx (+ nav): agent-facing account-creation guide — free tier
  needs no account; Clerk modal flow; MCP OAuth path for agents
- vercel.json: 301 /blog/posts → /blog (posts live at /blog/posts/<slug>/,
  the parent had no index)

Closes #4854 (pricing journey):
- .well-known/api-catalog: RFC 9727 service-meta advertising pricing.md,
  the live product-catalog JSON, and support.md on the api context object
- middleware.ts: /api/product-catalog joins PUBLIC_API_PATHS — the keyless
  read-only pricing catalog was UA-403'd for the exact agents it serves;
  robots.txt gets the matching Allow carve-out (llms.txt precedent)
- docs/pricing.mdx (+ nav) with a drift guard test extracting prices from
  convex/config/productCatalog.ts source text (no generator import)
- docs/openapi/CommerceService.openapi.yaml wired into the api-reference
  nav — placed OUTSIDE docs/api/ (that directory is generated: proto-check
  regen diff + injector scripts would clobber a hand-authored spec); kept
  out of the root openapi.json to respect the #4853 ~1MB size budget
- docs.json redirects for the guessed slugs: plans/tiers → pricing,
  rate-limit(s) → usage-rate-limits, mcp-api-key → usage-auth
- pricing.md: Limits & Overage section (hard 429 + Retry-After, no silent
  overage billing) + live JSON catalog pointer + UA note

Closes #4856 (status advertisement, stale since #4715):
- api-catalog status href + 3x vercel.json Link rel="status" now point at
  the keyless /api/health?compact=1 form
- /api/health 401 carries WWW-Authenticate with RFC 9728 resource_metadata
  (RFC 7235 §3.1 made it mandatory; it was absent) and a body hint naming
  the public compact form
- deploy-config guards: every advertised status URL must be the keyless
  compact form; service-meta entries pinned

Closes #4857 (support journey):
- public/support.md (root, sitemap-listed) + docs/support.mdx (+ nav):
  consolidated channels (support@/enterprise@, GitHub issues, Discord,
  status page, Turnstile form marked human-only) + explicit no-SLA
  statement per tier
- vercel.json: /contact, /support, /help 301 → /docs/support (they served
  the misleading-200 dashboard SPA shell via the catch-all rewrite)
- server-card.json documentation block: support repointed to /docs/support
  (was getting-started), pricing + productCatalog entries added

Out of scope, noted: the Cloudflare-side WAF UA rule (dashboard config, not
repo) and the root openapi info.description (generated + size-budgeted).

Claude-Session: https://claude.ai/code/session_01N3xTXNUrCiy1xqy3VbkMRx
@mintlify

mintlify Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
WorldMonitor 🟢 Ready View Preview Jul 5, 2026, 1:27 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@vercel

vercel Bot commented Jul 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
worldmonitor Ready Ready Preview, Comment Jul 5, 2026 1:30pm

Request Review

@koala73
koala73 enabled auto-merge (squash) July 5, 2026 13:26
@koala73
koala73 merged commit 77ffdb2 into main Jul 5, 2026
27 checks passed
@greptile-apps

greptile-apps Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR closes four agent-journey readiness gaps in one coordinated batch — pricing/signup/support discovery and status URL advertisement fixes. The changes span agent-facing metadata files (llms.txt, api-catalog, server-card.json), runtime behaviour (middleware.ts, api/health.js), new documentation pages, and a new drift-guard test suite.

  • Fixes the status advertisement by repointing all three Link rel="status" headers and the api-catalog status href from the bare (auth-gated) /api/health to the keyless compact form ?compact=1, backed by a deploy-config test that prevents future regressions.
  • Opens /api/product-catalog to bot UAs via an exact-path PUBLIC_API_PATHS entry (mirroring the llms.txt precedent), adds RFC-compliant WWW-Authenticate + discovery hint to the health endpoint's 401, and publishes pricing/support/accounts docs with a new drift-guard test that asserts doc prices stay in sync with productCatalog.ts.
  • Consolidates support/contact/help slug redirects in both vercel.json and docs.json, adds service-meta entries to api-catalog so agents on the well-known chain can discover pricing and support without falling back to slug-guessing.

Confidence Score: 4/5

Safe to merge — the core runtime changes (middleware bypass, health 401 header) are narrow, well-tested, and guarded by new regression tests; the only issue is a latent false-failure risk in the new drift test for future prices above $999.

The pricing drift test's usd() helper strips commas before checking content.includes(dollars), so a plan priced at $1,000+ would produce token $1500.00 while docs would naturally contain $1,500.00, causing a false test failure when the price is actually correct. No current plan is affected (max is $399.99/year), but the pattern is worth hardening before a price change crosses that threshold. Everything else — middleware bypass, health WWW-Authenticate, status link corrections, slug redirects — is well-structured and backed by tests.

tests/pricing-docs-drift.test.mjs — the usd() comma-stripping logic; everything else looks solid.

Important Files Changed

Filename Overview
api/health.js Adds RFC-compliant WWW-Authenticate header and compact-endpoint hint to the 401 response for keyless callers; single guard block covers both bare and ?history=1 paths.
middleware.ts Adds /api/product-catalog to PUBLIC_API_PATHS with an exact-path bypass (not a prefix), mirroring the /api/llms.txt precedent; DELETE stays protected by the endpoint's own auth.
tests/pricing-docs-drift.test.mjs New test guards public/pricing.md and docs/pricing.mdx against productCatalog.ts drift; the usd() helper strips commas before doc-matching, which could produce false failures for plan prices >= $1,000.
vercel.json Updates all three Link rel=status headers to ?compact=1, adds /blog/posts→/blog (permanent) and /contact, /support, /help→/docs/support (temporary) redirects.
public/.well-known/api-catalog Adds service-meta entries (pricing.md, product-catalog, support.md) and corrects status href to the keyless compact form.
tests/deploy-config.test.mjs Extends status-href guard to assert the keyless compact form, adds Link header guard and service-meta guard; regression surface now well-covered.
docs/openapi/CommerceService.openapi.yaml Hand-authored OpenAPI 3.1.0 spec for /api/product-catalog; correctly placed outside the generated docs/api/ directory; example product IDs guarded by pricing-docs-drift test.
tests/middleware-bot-gate.test.mts Adds pass-through tests for four crawler UAs on /api/product-catalog and a negative test confirming the bypass is exact-path, not a prefix.
tests/health-redis-down-status.test.mjs New test asserts WWW-Authenticate challenge presence and compact-endpoint hint in 401 body; properly exercises the key-gate path added in api/health.js.
docs/docs.json Adds pricing, accounts, support pages to nav; wires CommerceService OpenAPI group; adds slug redirects for agent-guessed paths (plans, tiers, rate-limit(s), mcp-api-key, contact).

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Agent arrives at worldmonitor.app] --> B{Reads Link header}
    B --> C[api-catalog well-known]
    C --> D[service-desc: openapi.yaml]
    C --> E[service-meta: pricing.md + product-catalog + support.md]
    C --> F[status: api-health compact=1]
    C --> G[oauth-protected-resource]

    F --> F1{Has API key?}
    F1 -->|compact=1 keyless| F2[200 OK public status]
    F1 -->|bare URL keyless| F3[401 + WWW-Authenticate + compact hint]

    E --> H[GET api-product-catalog]
    H --> I{UA gate check}
    I -->|bot UA PUBLIC_API_PATHS bypass| J[200 JSON pricing catalog]
    I -->|unlisted path| K[403 Forbidden]

    G --> L[OAuth 2.1 PKCE flow]
    L --> M[Agent credentials minted]

    subgraph slugs [Slug Redirects]
        N[contact, support, help slugs] --> O[docs-support page]
        P[plans, tiers slugs] --> Q[pricing page]
        R[rate-limits slug] --> S[usage-rate-limits page]
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[Agent arrives at worldmonitor.app] --> B{Reads Link header}
    B --> C[api-catalog well-known]
    C --> D[service-desc: openapi.yaml]
    C --> E[service-meta: pricing.md + product-catalog + support.md]
    C --> F[status: api-health compact=1]
    C --> G[oauth-protected-resource]

    F --> F1{Has API key?}
    F1 -->|compact=1 keyless| F2[200 OK public status]
    F1 -->|bare URL keyless| F3[401 + WWW-Authenticate + compact hint]

    E --> H[GET api-product-catalog]
    H --> I{UA gate check}
    I -->|bot UA PUBLIC_API_PATHS bypass| J[200 JSON pricing catalog]
    I -->|unlisted path| K[403 Forbidden]

    G --> L[OAuth 2.1 PKCE flow]
    L --> M[Agent credentials minted]

    subgraph slugs [Slug Redirects]
        N[contact, support, help slugs] --> O[docs-support page]
        P[plans, tiers slugs] --> Q[pricing page]
        R[rate-limits slug] --> S[usage-rate-limits page]
    end
Loading

Reviews (1): Last reviewed commit: "feat(agent-readiness): close the agent-j..." | Re-trigger Greptile

Comment on lines +33 to +34
const usd = (cents) =>
(cents / 100).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }).replace(/,/g, '');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 The usd() helper strips commas via .replace(/,/g, ''), so a price of 150000 cents produces the search token $1500.00. If the docs file contains $1,500.00 (comma-formatted, which is the natural human-readable form), content.includes('$1500.00') returns false and the test fails even though the price is correct. All current plan prices are below $1,000 so no active failure, but any future plan priced at or above $1,000 would trigger this. Consider also checking the comma-formatted variant so the test stays green regardless of how the docs author wrote the number.

Suggested change
const usd = (cents) =>
(cents / 100).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }).replace(/,/g, '');
const usd = (cents) =>
(cents / 100).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
// Returns the set of dollar strings to search for in doc content: both with
// and without comma grouping, so $1,500.00 and $1500.00 both match.
const usdVariants = (cents) => {
const formatted = usd(cents);
return [formatted, formatted.replace(/,/g, '')];
};

koala73 added a commit that referenced this pull request Jul 5, 2026
… 401 and product-catalog, pin advertised markdown, cover the API annual plan (#4874)

Review of merged #4867 confirmed 5 of 6 findings (the sixth was half-right:
the Commerce spec IS fetchable via the Mintlify proxy — it just wasn't linked
from any descriptor).

- product-catalog partial-Dodo branch stamped X-Product-Catalog-Source: dodo
  while the body said priceSource: "partial" — header now carries the same
  source as the body. Spec: header enum gains partial, body priceSource
  documented, tier price nullable (Enterprise returns price: null).
- /api/health 401 advertised a Bearer/OAuth challenge, but validateApiKey
  only reads X-WorldMonitor-Key / X-Api-Key headers and tester cookies —
  agents were pointed at a flow that cannot succeed. Challenge is now
  ApiKey realm="worldmonitor-health", header="X-WorldMonitor-Key"; test
  asserts Bearer is absent.
- api-catalog service-meta links the Commerce OpenAPI spec URL (it lives
  outside the root bundle for the #4853 size budget; without the link no
  advertised descriptor reached it).
- pricing.md + support.md pinned like auth.md: SPA catch-all exclusions
  (both regex copies), explicit text/markdown + CORS header rules, and
  deploy-config guards incl. file-existence (deleting the static file must
  404, not fall through to the dashboard-HTML misleading-200).
- pricing.md prose + JSON summary and docs/pricing.mdx gain the active API
  annual plan ($999/year, currentForCheckout in productCatalog.ts, live in
  /api/product-catalog — previously omitted everywhere).
- drift test hardened: numeric comparison of pricing.md's machine-readable
  JSON block (stale JSON now fails even when prose was updated),
  comma-tolerant prose matching, api_starter_annual covered.

Claude-Session: https://claude.ai/code/session_01N3xTXNUrCiy1xqy3VbkMRx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment