Skip to content

fix(track,growth): negotiate the API contract by date header instead of a v1 prefix - #355

Merged
BryanFRD merged 1 commit into
mainfrom
feat/track-growth-api-version
Sep 20, 2026
Merged

BryanFRD merged 1 commit into
mainfrom
feat/track-growth-api-version

Conversation

@BryanFRD

Copy link
Copy Markdown
Contributor

Closes #338

@ferrtrack/mcp and @ferrgrowth/mcp were the last two clients still calling a /v1 path. Both product APIs drop the prefix in FerrLabs/FerrTrack-Cloud#773 and FerrLabs/FerrGrowth-Cloud#846, so this moves the clients onto the date header, the same shape @ferrfleet/mcp already uses.

What changed

Each package gains a trackRequest / growthRequest helper in api-base.ts, pinning the base URL and the version header in one place so 27 call sites per package stop repeating either:

export const TRACK_API_VERSION = process.env.FERRTRACK_API_VERSION ?? '2026-08-04';

export function trackRequest<T>(path: string, options: TrackRequestOptions): Promise<T> {
  return apiRequest<T>(path, {
    ...rest,
    token,
    baseUrl: TRACK_API_URL,
    headers: { [API_VERSION_HEADER]: TRACK_API_VERSION },
  });
}

Paths lose /v1. FERRTRACK_API_VERSION and FERRGROWTH_API_VERSION override the sent version and are documented in the README, so a caller can pin an older contract once transforms exist without waiting for an MCP release.

Ordering

This is the client half. It must not ship before the two API PRs, or every tool in both packages 404s, which is exactly what happened to @ferrfleet/mcp between #317 and #323.

Since the APIs are the breaking side and these packages are unpublished against the new paths until a release goes out, the safe order is: merge and deploy #773 and #846 first, then merge this.

Verification

pnpm build, pnpm typecheck, pnpm format:check, pnpm test and pnpm smoke all pass. 117 tests, 2 skipped, 2 new.

The two new tests are the ones that matter here, one per package:

expect(call.headers['x-ferrtrack-api-version']).toBe('2026-08-04');
expect(call.url).not.toContain('/v1/');

The existing path assertions in both packages moved to the un-prefixed URLs, so a regression back to /v1 fails them rather than passing silently.

@BryanFRD BryanFRD added bug Something isn't working P2 Medium priority labels Sep 20, 2026

@ferrfleet ferrfleet 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.

Checked the sweep rather than the shape, since the risk in a change this mechanical is a missed call site.

At 0a24122, both packages are fully converted: 27 trackRequest and 27 growthRequest call sites, no remaining apiRequest, TRACK_API_URL or GROWTH_API_URL reference outside api-base.ts, no direct fetch anywhere in either package, and no /v1 left in either source tree. The remaining /v1 hits in the repo are the unified POST /v1/auth/exchange in the README, the CHANGELOG history, and ferrvault's vaults/v1 path segment, all unrelated.

Both helpers are byte-identical in shape to fleetRequest, and apiRequest merges headers before the credential headers, so the version header cannot displace Authorization or x-api-token. Test & Build is green.

The ordering constraint you flag is the real gate here, and it is a human call, not something this review can clear: #773 and #846 deployed before this merges.

@BryanFRD
BryanFRD merged commit 4eeba8e into main Sep 20, 2026
16 checks passed
@BryanFRD
BryanFRD deleted the feat/track-growth-api-version branch September 20, 2026 15:20
ferrflow Bot added a commit that referenced this pull request Sep 20, 2026
## [8.1.1] - 2026-09-20

### Bug Fixes

- fix(track,growth): negotiate the API contract by date header instead of a v1 prefix (#355)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working P2 Medium priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(mcp): FerrTrack and FerrGrowth still serve /v1 while the other two APIs dropped it

1 participant