32a20b3498
Four real surfaces backed by live tenant-registry data:
/[slug]/settings read-only tenant identity + plan + status
+ lifecycle dates with badge for status
/[slug]/settings/api-keys full CRUD: list active + revoked keys,
create form, plaintext-shown-once banner,
revoke action
/[slug]/audit paginated table with cursor-based next-page
navigation, action+actor_id GET filters,
formatRelative timestamps, metadata
preview
/[slug]/products live entitlements (filtered to enabled),
trial expiry chip, links to catalog when
empty
Five remaining surfaces upgraded to milestone-aware empty states
(projects / users / integrations / billing / support) with CTAs where
useful — billing links to catalog, support points at oncall@.
ShellEmpty component grew a 'details' string and a 'cta' ReactNode
slot so the empty pages don't all look identical.
Library additions:
src/lib/format.ts formatRelative, formatDateTime, truncate
src/lib/tenant-registry fetchAPIKeys, createAPIKey, revokeAPIKey,
fetchAudit — typed result shapes so server
actions can branch cleanly
Tests:
src/lib/format.test.ts 12 cases, 100% coverage
src/lib/tenant-registry.test +14 cases for new client methods,
100% line+branch+function
tests/e2e/surfaces.spec.ts one canary per of 10 customer-area
routes (signed-out → 403)
CI all green: lint / typecheck / test / build.
Refs: M10.1
18 lines
681 B
TypeScript
18 lines
681 B
TypeScript
import { auth } from "@/auth";
|
|
import { NotAuthorized, ShellEmpty } from "@/components/ShellEmpty";
|
|
import type { SessionWithExtras } from "@/lib/session";
|
|
import { canSee } from "@/lib/session";
|
|
|
|
export default async function Page() {
|
|
const session = (await auth()) as SessionWithExtras | null;
|
|
if (!canSee(session, "integrations")) return <NotAuthorized />;
|
|
return (
|
|
<ShellEmpty
|
|
title="Integrations"
|
|
description="Webhooks, outbound integrations, and external IdP configuration."
|
|
milestone="M15.2"
|
|
details="Webhook delivery (signed payloads, retry-with-backoff, dead-letter queue) lands alongside the headless-product API surface."
|
|
/>
|
|
);
|
|
}
|