feat(connect): connector status + Synka nu row in Settings -> Abonnemang (PR6b-3) (#2104)

* feat(connect): connector status + Synka nu row in Settings -> Abonnemang (PR6b-3)

Self-host only: shows per-upstream connector mode, key prefix, and the
active company's granted capabilities from GET /api/connector/status,
plus a manual run of the entitlement sync via the new authed
POST /api/connector/sync (requireWrite, 60s cooldown) instead of
waiting for the hourly cron. Hidden on hosted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KAUKbGUGtAmRhpDKfn84F5

* fix(connect): handle sync fetch rejection, count capabilities not rows, not_configured toast

Skeptic findings on the Synka nu flow: a rejected fetch (instance
restarting) was a silent no-op with an unhandled rejection; the success
toast printed grant rows (companies x scopes) as capabilities; a
not_configured outcome claimed the hosted service was unreachable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KAUKbGUGtAmRhpDKfn84F5

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Mattsson
2026-09-01 11:44:33 +02:00
committed by GitHub
co-authored by Claude Fable 5
parent aabddb592f
commit ee22c9c7b7
7 changed files with 451 additions and 2 deletions
@@ -18,6 +18,7 @@ import {
import { cn, formatCurrency } from '@/lib/utils'
import { useFormat } from '@/lib/hooks/use-format'
import { BillingActions } from '@/components/settings/BillingActions'
import { ConnectorSettingsSection } from '@/components/settings/ConnectorSettingsSection'
import { PLAN_PRICES } from '@/components/settings/billing-plans'
import type { BillingPlan } from '@/lib/stripe/client'
import { useBranding } from '@/lib/branding/brand-context'
@@ -74,6 +75,18 @@ function UnlockList({ className }: { className?: string }) {
* made, instead of repeated as reassurance copy around the page.
*/
export function BillingSettingsContent() {
return (
<>
<BillingCoreContent />
{/* Self-host only (renders null on hosted): connector status + manual
entitlement sync. Sits below the billing states, which is why the
core content is split out: it has several early returns. */}
<ConnectorSettingsSection />
</>
)
}
function BillingCoreContent() {
const tNav = useTranslations('settings_nav')
const tIntro = useTranslations('settings_intro')
const t = useTranslations('settings_billing')