Skip to content

chore: release new version (canary) - #603

Merged
thevuong merged 1 commit into
mainfrom
changeset-release/main
Jul 20, 2026
Merged

chore: release new version (canary)#603
thevuong merged 1 commit into
mainfrom
changeset-release/main

Conversation

@github-actions

@github-actions github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

⚠️⚠️⚠️⚠️⚠️⚠️

main is currently in pre mode so this branch has prereleases rather than normal releases. If you want to exit prereleases, run changeset pre exit on main.

⚠️⚠️⚠️⚠️⚠️⚠️

Releases

@codefast/tracking@1.0.0-canary.7

Minor Changes

  • #605 cb46bdd Thanks @thevuong! - Adds the shared ad-destination frame for consuming one { ads, analytics } decision across ad platforms (spec-destinations §5): toAdConsentState(decision) normalizes it to the two independent levers — analytics drives whether events transmit, ads drives Limited Data Use — so per-vendor mappings cannot drift. Ships a reference Meta destination (createMetaDestination, toMetaDataProcessingOptions) that maps each event and the live ads decision to Meta's dataProcessingOptions (geolocated LDU when ads is denied) and hands it to an injected transport. Consent-restriction mapping only — the Pixel/CAPI transport and credentials are the integrator's to supply; an ad sink is never exempt.

  • #612 1337fc3 Thanks @thevuong! - Adds the TCF/GPP interop reconciler (spec-ad-consent-frameworks): the system reads an external CMP and reconciles it with the native { ads, analytics } decision — it never becomes a CMP or mints TC/GPP strings. reconcileAdFrameworkConsent({ native, cmp, hasGlobalPrivacyControlSignal }) applies the §3 precedence (a governing CMP overrides its categories; fail-closed to denied while the CMP is loading; a missing or out-of-scope CMP leaves native standing; GPC only tightens ads), covering conformance vectors V1–V6. hasTcfApi/hasGppApi detect the __tcfapi/__gpp read APIs without invoking them. TCF purpose ids and the Google vendor id are deliberately not hard-coded — that mapping is ad-ops policy, so the caller derives the CmpConsentSignal it passes in.

  • #615 2bcd31f Thanks @thevuong! - Let codefast mirror generate package.json#exports from dist/, the same as every other library package (di, theme), instead of hand-curating them under mirror's preserve mode. The per-module build output is unchanged, so mirror emits a subpath for each built module, and the root becomes the client entry.

    Breaking:

    • The root @codefast/tracking is now the client entry — it re-exports the isomorphic core plus the whole browser surface (createClientTracker, createConsentRuntime, the React bindings, the gtag + ad-network destinations). Server code must import the core it needs from @codefast/tracking/core/*, not from the root.
    • The ./client, ./server, ./core, ./react, and ./destinations group barrels are gone. Use the client root for browser code, or a module's own subpath for granular/server imports (@codefast/tracking/server/initial-consent, @codefast/tracking/client/gpc, …).
    • The TanStack Start adapter is now @codefast/tracking/adapters/tanstack-start (was /tanstack-start); the import-protection deny-list is @codefast/tracking/tooling/import-protection (was /import-protection). SERVER_ONLY_SUBPATHS now denies server/** and adapters/**.
  • #617 b979371 Thanks @thevuong! - Harden the package from a full audit — correctness, coverage, and a leaner public surface.

    • isConsentReceiptInput now validates method and subjectIdType against their enums, not just typeof === "string" — the untrusted-body guard no longer narrows a bogus value to a closed union member.
    • CookieAnonymousId gains current() — a non-minting read of the existing id (undefined when none) so a consent receipt stamps the id the visitor already carries instead of a throwaway that never correlates for erasure.
    • coarsenIp rejects out-of-range IPv4 octets ("999.…") rather than storing a malformed coarse value.
    • Microsoft UET consent routes through the shared toAdConsentState ad lever, so its ad_storage mapping can't drift from Meta/TikTok.
    • Dropped unused foreign type re-exports so each type has one home: InitialConsent no longer re-exported from adapters/tanstack-start or server/initial-consent (import it from core/consent), and the AnonymousIdResponseCookieOptions alias is gone — setAnonymousIdResponseCookie takes AnonymousIdCookieOptions from server/anonymous-id-cookie directly.
    • Collapsed the TrackedEvent envelope to a single interface — the unused TrackedEventBase and TrackEvent names are gone (TrackedEvent keeps the type: "track" discriminant for a future additive union).

    Also adds test coverage for the previously-untested recordConsentReceiptFromRequest adapter path (no-store header, body-IP rejection, coarsened IP, PII-free ack).

  • #617 b979371 Thanks @thevuong! - Remove two leftover indirection layers in the server lane that no call site used.

    Breaking:

    • The @codefast/tracking/adapters/request-context subpath is gone. Its RequestContext seam (a getHeader/setHeader interface) plus the parallel *FromContext/*OnContext helpers existed only to back a hypothetical future ./next/./remix adapter, but there was exactly one adapter and it duplicated every signature and doc comment. @codefast/tracking/adapters/tanstack-start now calls getRequestHeader/setResponseHeader directly; its public surface (resolveInitialConsentFromRequest, setAnonymousIdResponseCookie, clearAnonymousIdResponseCookie, recordConsentReceiptFromRequest) is unchanged.
    • resolveRegion(headers) is removed from @codefast/tracking/server/region. It was a pre-fail-closed leftover with no production call site, and its missing-geo semantics (unknown region → opt-out) contradicted the fail-closed invariant the server-first path relies on. Use resolveRegionFromCountryCode (what the production path already uses via resolveInitialConsent), or resolveInitialConsentFromRequest for the full per-request resolution.
  • #606 5a4ff42 Thanks @thevuong! - Adds createDurableReceiptStore({ backend }) — a durable ReceiptStore over an injected ReceiptStoreBackend (a minimal id-keyed get/put primitive). The package supplies the append-only contract and adaptation; the deployment supplies the backend client (Vercel KV, Postgres, an append-only log), so no database dependency is baked in. put MUST be idempotent-by-id so the append-only guarantee holds atomically under retries/concurrency (e.g. KV set-if-absent, Postgres INSERT … ON CONFLICT DO NOTHING) — the frame delegates rather than doing a racy get-then-put. Pair it with a real backend in production, where createInMemoryReceiptStore is not a lawful store on its own.

  • #604 7bb4be7 Thanks @thevuong! - createClientTracker now accepts an optional isExemptionAllowed gate, consulted before an exempt destination receives an event while the consent gate is closed. ePrivacy audience-measurement exemption is jurisdiction-dependent (spec-destinations §2), so it must be gateable per region rather than assumed global — returning false withholds even exempt sinks where exemption is not defensible. Omit it to keep the prior behavior (exempt everywhere). The gate is irrelevant once consent is granted, since every destination then receives the full envelope.

  • #608 6cdd930 Thanks @thevuong! - Adds GA4 DSR delegation (spec-data-subject-rights §3): the system delegates per-visitor deletion to the platform rather than building a deletion store. buildGa4UserDeletionRequest({ propertyId, clientId }) returns the network-free request shape and submitGa4UserDeletion({ …, accessToken, transport? }) POSTs it — targeting the current Analytics Admin API properties.submitUserDeletion (the legacy v3 userDeletionRequests:upsert was sunset with Universal Analytics), keyed by a flat clientId. Authorization is the caller's: pass a bearer token for the analytics.edit scope; no OAuth or HTTP client is baked in. Server-only (@codefast/tracking/server).

  • #617 b979371 Thanks @thevuong! - Adopt TanStack Start's first-class server helpers in the adapter instead of hand-rolling over raw request/response headers.

    • The anonymous-id cookie is now written with setCookie/deleteCookie (from @tanstack/react-start/server) rather than setResponseHeader("set-cookie", …). The raw header call replaces any existing Set-Cookie on the response — it would clobber a session or framework cookie set on the same response — whereas setCookie appends. No behavior change to the emitted cookie (still Path=/; Max-Age=1y; SameSite=Lax; Secure, not HttpOnly).
    • The connection IP for consent receipts is now read with getRequestIP({ xForwardedFor: true }) — the maintained, platform-aware path — instead of hand-parsing x-forwarded-for/x-real-ip.

    Breaking (@codefast/tracking/server/anonymous-id-cookie): the string builders buildAnonymousIdSetCookie/buildClearAnonymousIdSetCookie are replaced by resolveAnonymousIdCookie/resolveClearAnonymousIdCookie, which return the validated name/value plus cookie attributes for a framework setCookie/deleteCookie call. isValidAnonymousId is unchanged; the cookie-name guard is now the exported assertValidAnonymousIdCookieName.

  • #607 749dd16 Thanks @thevuong! - Adds server-side GA4 Measurement Protocol primitives for forwarding a server-owned event (re-added now that a consumer tracks one — a server-recorded consent decision): sendMeasurementProtocolEvents POSTs { client_id, events, consent? } to the credentialed /mp/collect endpoint through an injected transport (default fetch), so no HTTP client or credentials are baked in; extractGaClientId derives the GA4 client_id from a _ga cookie; toMeasurementProtocolConsent maps the package ConsentDecision to the MP consent signals. Server-only (@codefast/tracking/server). The caller owns the credentials and the consent gate.

  • #602 5ca04e2 Thanks @thevuong! - createClientTracker now accepts an optional onDeliveryError hook, called once per failed delivery (a destination throwing synchronously or rejecting) with { destination, error, event }. The tracker still swallows the failure so tracking never breaks the interaction — the hook is a metering seam for wiring delivery failures to a monitor in production. The hook is itself guarded, so a throwing observer can't break the interaction either. Exposes the DeliveryErrorContext type from @codefast/tracking/client.

  • #610 fdb8d7c Thanks @thevuong! - Adds the per-destination erasure capability for DSR withdrawal (spec-data-subject-rights §3, DSR-V2/V4): Destination gains an optional onErasure(id) hook, and createClientTracker returns an erase(id) method that invokes each destination's onErasure once on withdrawal, swallowing failures so a destination can never break the flow. The reference createMetaDestination implements onErasure as cookie-clear (via an injected clearCookies seam) plus stop-send — Meta exposes no per-visitor deletion API, so the binding never fabricates one. Destinations with nothing to erase omit the hook.

  • #611 a5527c3 Thanks @thevuong! - Extends the ad-destination frame with two more reference vendors (spec-destinations §5), consuming the same { ads, analytics } decision: createMicrosoftUetDestination / toMicrosoftUetConsent map ads to UET's only enforced signal, ad_storage (UET has no analytics_storage); createTiktokDestination / toTiktokConsent map ads to TikTok's single limited_data_use boolean (not Meta's dataProcessingOptions structure). Both take an injected transport (no pixel id, tag id, or network client baked in) and implement onErasure as cookie-clear + stop-send, since neither exposes a per-visitor deletion API. consentRequirement stays "required".

@codefast/typescript-config@1.0.0-canary.7

Minor Changes

  • 71cf664 Thanks @thevuong! - Add a library-build.json preset holding the shared emit options for the native tsc package build (noEmit: false, declaration, declarationMap, sourceMap, types: ["node"]). Each package's tsconfig.build.json now uses array extends (["./tsconfig.json", "@codefast/typescript-config/library-build.json"]) and keeps only its local outDir/rootDir and include — dropping the duplicated emit block across all library packages. Path-relative options stay local because extends resolves them against the file that declares them.

@codefast/ui@1.0.0-canary.7

Patch Changes

  • #632 44035ca Thanks @thevuong! - Annotate CheckboxGroupItem's onCheckedChange callback with a CheckedState type derived from the underlying Radix primitive. Radix's radix-ui umbrella namespace merge dropped the contextual type for the inline callback parameter, tripping noImplicitAny during the build; deriving the type from Root keeps it in lockstep with the primitive.

  • Updated dependencies []:

    • @codefast/tailwind-variants@1.0.0-canary.7

@codefast/cli@1.0.0-canary.7

@codefast/di@1.0.0-canary.7

@codefast/tailwind-variants@1.0.0-canary.7

@codefast/theme@1.0.0-canary.7

@codefast/benchmark-di-inversify@1.0.0-canary.7

Patch Changes

  • Updated dependencies []:
    • @codefast/benchmark-harness@1.0.0-canary.7
    • @codefast/benchmark-viewer@1.0.0-canary.7
    • @codefast/di@1.0.0-canary.7

@codefast/benchmark-tailwind-variants@1.0.0-canary.7

Patch Changes

  • Updated dependencies []:
    • @codefast/benchmark-harness@1.0.0-canary.7
    • @codefast/benchmark-viewer@1.0.0-canary.7
    • @codefast/tailwind-variants@1.0.0-canary.7

@codefast/benchmark-viewer@1.0.0-canary.7

Patch Changes

  • Updated dependencies []:
    • @codefast/benchmark-harness@1.0.0-canary.7
    • @codefast/tailwind-variants@1.0.0-canary.7

@codefast/benchmark-harness@1.0.0-canary.7

@vercel

vercel Bot commented Jul 18, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
codefast-tanstack-start Ready Ready Preview, Comment Jul 20, 2026 1:13pm
codefastlabs Ready Ready Preview, Comment Jul 20, 2026 1:13pm

@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 3e82628 to 8d2b066 Compare July 18, 2026 09:09
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 8d2b066 to 1903375 Compare July 18, 2026 09:17
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 1903375 to 80cbc5f Compare July 18, 2026 09:24
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 80cbc5f to f55247c Compare July 18, 2026 09:38
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from f55247c to 9e14e6f Compare July 18, 2026 09:46
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 9e14e6f to f6546ac Compare July 18, 2026 09:51
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from f6546ac to b065aaf Compare July 18, 2026 09:58
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from b065aaf to 67dbfc5 Compare July 18, 2026 10:04
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 67dbfc5 to 5761df2 Compare July 18, 2026 10:14
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from c391320 to 0bc46db Compare July 19, 2026 05:11
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 0bc46db to 9065c04 Compare July 19, 2026 08:58
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 9065c04 to d54966a Compare July 19, 2026 09:31
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from d54966a to d458af8 Compare July 20, 2026 10:17
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from d458af8 to 42c483d Compare July 20, 2026 10:45
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 42c483d to 10d5311 Compare July 20, 2026 10:50
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 10d5311 to 5149708 Compare July 20, 2026 11:03
@github-actions
github-actions Bot force-pushed the changeset-release/main branch from 5149708 to 10e8595 Compare July 20, 2026 11:07
@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
packages/cli/src/audit/cli-schema.ts 0.00% <ø> (ø)
packages/cli/src/audit/command.ts 0.00% <ø> (ø)
packages/cli/src/audit/domain/audit-file.ts 78.84% <ø> (ø)
packages/cli/src/audit/domain/mappings.ts 100.00% <ø> (ø)
packages/cli/src/audit/domain/tokenize.ts 76.08% <ø> (ø)
packages/cli/src/audit/output.ts 0.00% <ø> (ø)
packages/cli/src/audit/prepare.ts 0.00% <ø> (ø)
packages/cli/src/audit/run.ts 96.15% <ø> (ø)
packages/tracking/src/adapters/tanstack-start.ts 100.00% <ø> (ø)
...ckages/tracking/src/client/ad-framework-consent.ts 91.66% <ø> (ø)
... and 12 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@thevuong
thevuong merged commit bd21e52 into main Jul 20, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant