Pular para o conteúdo

Social Primitive — Phase 4 Foundation

The kit ships a provider-agnostic social-publishing primitive — capability-flag honesty across Meta and TikTok, encrypted-at-rest tokens, and a deterministic path through the Jun 15 2026 Meta v25→v26 cutover.

The kit now ships @kit/social-{core,meta,tiktok,api} — a provider-agnostic social-publishing primitive that treats Facebook Pages, Instagram Business, and TikTok as first-class citizens without pretending they behave the same way.

Each platform has its own quirks.

Meta gives you long-lived Page tokens that do not silently rotate. TikTok hands you a 60-day access token paired with a 365-day refresh token that absolutely does rotate on every refresh, with no extension beyond the year. Instagram Business sits inside the Meta graph but uses a different scope vocabulary and a different media-upload flow than Facebook Pages does.

Instead of papering over those differences with a lowest-common-denominator abstraction, the primitive surfaces them as capability flags on each provider — refreshRotates is the load-bearing one — so the calling code can branch honestly when the behaviour matters and stay generic when it does not.

Scopes are type-narrowed at the call site. Tokens are encrypted at rest with the kit's standard envelope-encryption pattern. And the upcoming Meta Graph v25→v26 cutover on Jun 15 2026 is wired into a build-time check rather than left to a future operator's memory.

This is the foundation — Phase 4 of the broader social-jobs work. It is not yet the publish path itself, and the changelog is honest about that distinction below.

What lands today

  • Six new Prisma tables. socialConnectedAccount, socialPost, socialMetric, socialWebhookEvent, socialJobAudit, and socialApiUsage ship with the full foreign-key and index strategy already in place.

    Per-tenant queries stay fast as connected-account count grows, and the audit / API-usage pair gives operators the receipts they need when a platform asks how a creator's data was handled. Webhook events are stored with their raw payload so re-processing a failed delivery is a re-read rather than a re-fetch.

  • RBAC social resource with seven verbs. connect, disconnect, publish, schedule, read, read:metrics, and moderate:comments are gated per role. Account owners, marketers, and analysts each see exactly the surface they should — a read-only analyst cannot accidentally publish, and a marketer cannot disconnect the workspace's accounts.

  • HMAC-signed OAuth state token. New signOAuthState and verifyOAuthState helpers close the cross-org CSRF gap so a state parameter from one tenant cannot be replayed against another.

    The signing key is derived from BETTER_AUTH_SECRET_ROOT per the standard fork-isolation pattern, so non-canonical forks get their own signing domain for free — a state token minted by your canonical app cannot be presented at a side fork's callback, and vice versa.

  • Scope-feature matrix. The UI knows, statically, which features are available given which scopes a creator has actually granted. No more "Publish" buttons that 403 at submit time, and no more partial-scope confusion when a creator approves the connect flow but skips the metrics permission.

  • Meta deprecation calendar with build-fail trigger. The v25→v26 cutover on Jun 15 2026 is encoded as a one-line version literal plus a build-time check.

    When the cutover date passes, the build fails until the version is bumped — silent drift against a deprecated Graph version is impossible. Adding the next quarterly cutover is also a one-line addition to the same calendar, so the same protection extends forward without operator vigilance.

  • Compliance documentation set. A cross-border transfer disclosure covering EU-Brazil and US-Brazil token flows, the TikTok app-audit operator runbook, the day-1 deploy runbook, and a privacy-policy diff ready for legal review.

    The set is meant to be lifted into your own corporate counsel's review process — it is opinionated about the structure and intentionally light on jurisdictional specifics. Replace the placeholders, sign, ship.

  • Security threat model and developer guide. The threat model walks the OAuth, token-storage, and webhook-verification paths.

    The developer guide is the canonical "I'm adding a new provider" onboarding — it covers the capability-flag contract, the scope-narrowing pattern, and the test fixtures the existing providers use. Both live alongside the code, not in a wiki that drifts.

What's deferred

The foundation is in. The method surfaces are not.

publish, schedule, and metrics handlers are typed and contract-defined but not yet wired to live providers.

Meta and TikTok OAuth-flow implementations are scaffolded — the routes exist, the state-token plumbing works — but the platform-specific token exchange and refresh logic ships in Phase 5.

Phase 7 lifecycle hooks (data-subject-access-request fan-out and right-to-erasure across connected accounts) and the Phase 8 in-app settings UI are also deferred. Both depend on having real provider data flowing first, which is exactly what Phase 5 unlocks.

The next ship boundary is the Phase 5 mid-pipeline checkpoint, where the publish path becomes real end-to-end on at least one provider and the kit can demo a real creator post going from form-submit to live content.

What operators should know

Three operational realities are worth pulling out before you deploy.

Non-canonical forks ship with OAuth disabled by default. Any worktree slot ≥ 1 starts up without the provider list pre-populated. This is the safe choice — a side fork picking up your canonical OAuth credentials would let it impersonate your production app against Meta and TikTok.

If you are running a side fork and genuinely need to test the connect flow against a separate sandbox app, set NEXT_PUBLIC_AUTH_OAUTH_PROVIDERS=... in your shell to override.

The Meta mTLS trust-store flip on 2026-03-31 already happened. It remains action-required for any deploy whose trust store has not been refreshed since. The webhook signature path will silently fail handshake until the new intermediate is trusted — the deploy runbook walks the verification step and the rollback path.

TikTok refresh tokens expire 365 days after issuance with no silent extension. There is no off-platform escape hatch — once the refresh token expires, the creator must walk the full OAuth flow again.

Operators should build a creator-facing reminder into their own UX (the socialConnectedAccount.refreshTokenExpiresAt column makes this trivial) or accept that creators will reconnect annually. The TikTok app-audit runbook in the references section below has the recommended reminder cadence.

References