Files
SentryAgent.ai Developer eea885db04 feat(phase-6): WS3+WS4+WS6 — Analytics, API Tiers, AGNTCY Compliance
WS3 — Advanced Analytics Dashboard:
- DB migration: analytics_events table (tenant_id, date, metric_type, count)
- AnalyticsService: recordEvent (fire-and-forget), getTokenTrend, getAgentActivity, getAgentUsageSummary
- Analytics hooks in OAuth2Service (token_issued) and AgentService (agent_registered/deactivated)
- AnalyticsController + routes/analytics.ts (gated by ANALYTICS_ENABLED flag)
- Portal: TokenTrendChart (recharts LineChart), AgentHeatmap (recharts heatmap), /analytics page

WS4 — API Gateway Tiers:
- DB migration: tenant_tiers table; src/config/tiers.ts (free/pro/enterprise limits)
- TierService: getStatus, initiateUpgrade (Stripe), applyUpgrade; TierLimitError in errors.ts
- tierEnforcement middleware (Redis-backed daily call/token counters; TIER_ENFORCEMENT flag)
- Agent count enforcement in AgentService.create()
- Stripe webhook updated to call TierService.applyUpgrade() on checkout.session.completed
- TierController + routes/tiers.ts; Portal: /settings/tier page with upgrade flow

WS6 — AGNTCY Compliance Certification:
- ComplianceService: generateReport() (Redis-cached 5 min), exportAgentCards()
- Compliance sections: agent-identity (DID + credential expiry checks), audit-trail (Merkle chain)
- ComplianceController updated with getComplianceReport, exportAgentCards handlers
- routes/compliance.ts: new AGNTCY routes (gated by COMPLIANCE_ENABLED flag); SOC2 routes unaffected

QA:
- 28 new unit tests: AnalyticsService (8), TierService (9), ComplianceService (11) — all pass
- 673 total unit tests passing; 0 TypeScript errors across API and portal
- AGNTCY conformance test suite at tests/agntcy-conformance/ (4 protocol tests)
- Portal builds cleanly: 9 routes including /analytics and /settings/tier
- Feature flags verified: ANALYTICS_ENABLED, TIER_ENFORCEMENT, COMPLIANCE_ENABLED

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 02:20:09 +00:00

68 lines
2.0 KiB
TypeScript

'use client';
import React from 'react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
interface NavLink {
href: string;
label: string;
}
const links: NavLink[] = [
{ href: '/', label: 'Home' },
{ href: '/api-explorer', label: 'API Explorer' },
{ href: '/get-started', label: 'Get Started' },
{ href: '/sdks', label: 'SDKs' },
{ href: '/pricing', label: 'Pricing' },
{ href: '/analytics', label: 'Analytics' },
];
export function Nav(): React.ReactElement {
const pathname = usePathname();
return (
<header className="sticky top-0 z-50 border-b border-slate-200 bg-white/90 backdrop-blur">
<nav className="mx-auto flex max-w-7xl items-center justify-between px-6 py-4">
<Link href="/" className="flex items-center gap-2">
<span className="text-xl font-bold text-brand-600">
SentryAgent
</span>
<span className="rounded bg-brand-100 px-1.5 py-0.5 text-xs font-semibold text-brand-700">
AgentIdP
</span>
</Link>
<ul className="flex items-center gap-1">
{links.map(({ href, label }) => {
const isActive =
href === '/' ? pathname === '/' : pathname.startsWith(href);
return (
<li key={href}>
<Link
href={href}
className={[
'rounded-md px-3 py-2 text-sm font-medium transition-colors',
isActive
? 'bg-brand-100 text-brand-700'
: 'text-slate-600 hover:bg-slate-100 hover:text-slate-900',
].join(' ')}
>
{label}
</Link>
</li>
);
})}
</ul>
<Link
href="/get-started"
className="rounded-lg bg-brand-600 px-4 py-2 text-sm font-semibold text-white shadow-sm transition-colors hover:bg-brand-700"
>
Get Started Free
</Link>
</nav>
</header>
);
}