@burdenoff/microfe-adaptercloud 2026.720.2 → 2026.801.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adaptercloud/AdapterCloudRoutes.js +1 -1
- package/dist/adaptercloud/AdapterCloudRoutes.js.map +1 -1
- package/dist/adaptercloud/context/AdapterCloudContext.js +1 -1
- package/dist/adaptercloud/context/AdapterCloudContext.js.map +1 -1
- package/dist/adaptercloud/pages/adapters/AdapterDetailPage.js +1 -1
- package/dist/adaptercloud/pages/adapters/AdapterDetailPage.js.map +1 -1
- package/dist/adaptercloud/pages/adapters/AdapterFormPage.js +1 -1
- package/dist/adaptercloud/pages/adapters/AdapterFormPage.js.map +1 -1
- package/dist/adaptercloud/pages/connections/ConnectionDetailPage.js +1 -1
- package/dist/adaptercloud/pages/connections/ConnectionDetailPage.js.map +1 -1
- package/dist/adaptercloud/pages/connections/ConnectionFormPage.js +1 -1
- package/dist/adaptercloud/pages/connections/ConnectionFormPage.js.map +1 -1
- package/dist/adaptercloud/pages/policies/PolicyDetailPage.js +1 -1
- package/dist/adaptercloud/pages/policies/PolicyDetailPage.js.map +1 -1
- package/dist/adaptercloud/pages/policies/PolicyFormPage.js +1 -1
- package/dist/adaptercloud/pages/policies/PolicyFormPage.js.map +1 -1
- package/dist/adaptercloud/pages/resources/ResourceDetailPage.js +1 -1
- package/dist/adaptercloud/pages/resources/ResourceDetailPage.js.map +1 -1
- package/dist/adaptercloud/pages/resources/ResourcesListPage.js +1 -1
- package/dist/adaptercloud/pages/resources/ResourcesListPage.js.map +1 -1
- package/dist/adaptercloud/pages/violations/ViolationsListPage.js +1 -1
- package/dist/adaptercloud/pages/violations/ViolationsListPage.js.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ViolationsListPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/violations/ViolationsListPage.tsx"],"sourcesContent":["/**\n * Violations Queue Page\n * @module adaptercloud/pages/violations\n *\n * The governance work queue (`adaListViolations`). Filters by status (and by\n * policy/resource via URL params). Each open/acknowledged violation can be\n * transitioned via `adaResolveViolation` — acknowledge, resolve, or waive (a\n * waiver requires a reason, enforced both client-side and at the service).\n */\n\nimport { useState, useCallback } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n ShieldAlert,\n ChevronLeft,\n ChevronRight,\n ChevronDown,\n Check,\n CheckCheck,\n FileText,\n Loader2,\n} from 'lucide-react';\nimport {\n GlassCard,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { SeverityBadge } from '../../components/SeverityBadge';\nimport { DataState } from '../../components/DataState';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { useViolations, useResolveViolation } from '../../hooks/useAdapterCloudApi';\nimport { violationStatusLabels, severityRank } from '../../utils/domain';\nimport { formatDate } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { AdaPolicyViolation, AdaViolationStatus } from '../../types';\n\n/** Segmented status tabs — All plus each `AdaViolationStatus`, in queue order. */\nconst STATUS_TABS: (AdaViolationStatus | '')[] = ['', 'OPEN', 'ACKNOWLEDGED', 'RESOLVED', 'WAIVED'];\n\nconst PAGE_SIZE = 20;\n\nexport function ViolationsListPage() {\n const { navigateTo } = useAdapterCloud();\n const [searchParams] = useSearchParams();\n const policyId = searchParams.get('policyId') ?? undefined;\n const resourceId = searchParams.get('resourceId') ?? undefined;\n\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n const [status, setStatus] = useState<AdaViolationStatus | ''>('OPEN');\n const [offset, setOffset] = useState(0);\n const [waiveTarget, setWaiveTarget] = useState<AdaPolicyViolation | null>(null);\n const [waiverReason, setWaiverReason] = useState('');\n const [actionError, setActionError] = useState<string | null>(null);\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n\n const query = useViolations({\n policyId,\n resourceId,\n status: status || undefined,\n pagination: { limit: PAGE_SIZE, offset },\n });\n const resolve = useResolveViolation();\n\n // Live per-status counts for the segmented tabs. Each is a cheap `limit: 1`\n // query read for its `pageInfo.totalCount` (the estate-wide total for that\n // filter); \"All\" is the same query without a status. They respect the current\n // policy/resource URL scope so the badges match the visible queue.\n const countBase = { policyId, resourceId, pagination: { limit: 1, offset: 0 } };\n const allCount = useViolations(countBase);\n const openCount = useViolations({ ...countBase, status: 'OPEN' });\n const ackCount = useViolations({ ...countBase, status: 'ACKNOWLEDGED' });\n const resolvedCount = useViolations({ ...countBase, status: 'RESOLVED' });\n const waivedCount = useViolations({ ...countBase, status: 'WAIVED' });\n\n const tabCounts: Record<AdaViolationStatus | '', number | undefined> = {\n '': allCount.data?.pageInfo.totalCount ?? undefined,\n OPEN: openCount.data?.pageInfo.totalCount ?? undefined,\n ACKNOWLEDGED: ackCount.data?.pageInfo.totalCount ?? undefined,\n RESOLVED: resolvedCount.data?.pageInfo.totalCount ?? undefined,\n WAIVED: waivedCount.data?.pageInfo.totalCount ?? undefined,\n };\n\n const toggleEvidence = useCallback((id: string) => {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n }, []);\n\n // Severity ordering is applied ONLY within the current server page. The queue\n // pages by offset, so this does not globally reorder across pages — a page-2\n // CRITICAL still sorts below a page-1 LOW. Kept as a within-page readability\n // aid (the service has no severity sort arg to make it global).\n const items = [...(query.data?.items ?? [])].sort(\n (a, b) => severityRank[b.severity] - severityRank[a.severity]\n );\n const hasMore = query.data?.pageInfo.hasMore ?? false;\n\n const onError = useCallback(\n (err: unknown) =>\n setActionError(err instanceof Error ? err.message : 'Action failed. Please try again.'),\n []\n );\n\n const transition = useCallback(\n (id: string, newStatus: AdaViolationStatus) => {\n setActionError(null);\n resolve.mutate({ id, status: newStatus }, { onError });\n },\n [resolve, onError]\n );\n\n const confirmWaive = useCallback(() => {\n if (!waiveTarget) return;\n if (!waiverReason.trim()) {\n setActionError(t('adaptercloud.violations.reasonRequired', 'A waiver requires a reason.'));\n return;\n }\n setActionError(null);\n resolve.mutate(\n { id: waiveTarget.id, status: 'WAIVED', waiverReason: waiverReason.trim() },\n {\n onSuccess: () => {\n setWaiveTarget(null);\n setWaiverReason('');\n },\n onError,\n }\n );\n }, [waiveTarget, waiverReason, resolve, onError, t]);\n\n return (\n <PageLayout\n title={t('adaptercloud.violations.title', 'Violations')}\n description={t(\n 'adaptercloud.violations.subtitle',\n 'Work the governance queue — acknowledge, resolve, or waive policy breaches.'\n )}\n >\n <div\n className=\"mb-6 flex flex-wrap items-center gap-2\"\n role=\"tablist\"\n aria-label={t('adaptercloud.violations.filterByStatus', 'Filter by status')}\n >\n {STATUS_TABS.map((tab) => {\n const active = status === tab;\n const count = tabCounts[tab];\n const label =\n tab === ''\n ? t('adaptercloud.violations.allStatuses', 'All')\n : violationStatusLabels[tab];\n return (\n <button\n key={tab || 'all'}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n onClick={() => {\n setStatus(tab);\n setOffset(0);\n }}\n className={cn(\n 'inline-flex items-center gap-2 rounded-full border px-3.5 py-1.5 text-sm font-medium transition-colors',\n active\n ? 'border-transparent bg-action-primary-bg text-action-primary-text'\n : 'border-border-subtle text-text-secondary hover:bg-accent'\n )}\n >\n {label}\n {count !== undefined && (\n <span\n className={cn(\n 'inline-flex min-w-5 items-center justify-center rounded-full px-1.5 text-xs font-semibold tabular-nums',\n active\n ? 'bg-action-primary-text/20 text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary'\n )}\n >\n {count}\n </span>\n )}\n </button>\n );\n })}\n {(policyId || resourceId) && (\n <button\n type=\"button\"\n onClick={() => navigateTo('/violations')}\n className=\"inline-flex items-center gap-1.5 rounded-full bg-accent-blue-subtle px-2.5 py-1 text-xs text-accent-blue hover:underline\"\n >\n {t('adaptercloud.violations.clearScope', 'Clear scope ×')}\n </button>\n )}\n </div>\n\n {actionError && (\n <p\n role=\"alert\"\n aria-live=\"polite\"\n className=\"mb-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\"\n >\n {actionError}\n </p>\n )}\n\n <DataState\n isLoading={query.isLoading}\n isError={query.isError}\n isEmpty={items.length === 0}\n error={query.error}\n onRetry={() => void query.refetch()}\n emptyTitle={t('adaptercloud.violations.emptyTitle', 'No violations')}\n emptyDescription={t(\n 'adaptercloud.violations.emptyDescription',\n 'Nothing matches this filter — your estate is clean here.'\n )}\n emptyIcon={<ShieldAlert className=\"h-10 w-10\" />}\n >\n <div className=\"space-y-3\">\n {items.map((v) => {\n const isOpen = v.status === 'OPEN' || v.status === 'ACKNOWLEDGED';\n return (\n <GlassCard key={v.id} className=\"p-5\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"mb-1.5 flex flex-wrap items-center gap-2\">\n <SeverityBadge severity={v.severity} />\n <StatusBadge status={v.status} />\n {v.policy && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`/policies/${v.policyId}`)}\n className=\"text-xs font-medium text-accent-blue hover:underline\"\n >\n {v.policy.name}\n </button>\n )}\n </div>\n <p className=\"text-sm font-medium text-text-primary\">{v.message}</p>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {t('adaptercloud.violations.detected', 'Detected')} {formatDate(v.detectedAt)}\n {' · '}\n <button\n type=\"button\"\n onClick={() => navigateTo(`/resources/${v.resourceId}`)}\n className=\"hover:underline\"\n >\n {t('adaptercloud.violations.viewResource', 'View resource')}\n </button>\n </p>\n {v.waiverReason && (\n <p className=\"mt-2 rounded-lg bg-bg-sunken px-3 py-1.5 text-xs text-text-secondary\">\n {t('adaptercloud.violations.waiver', 'Waiver')}: {v.waiverReason}\n </p>\n )}\n {v.evidence != null && (\n <div className=\"mt-2\">\n <button\n type=\"button\"\n onClick={() => toggleEvidence(v.id)}\n aria-expanded={expanded.has(v.id)}\n className=\"inline-flex items-center gap-1 text-xs font-medium text-text-secondary transition-colors hover:text-text-primary\"\n >\n {expanded.has(v.id) ? (\n <ChevronDown className=\"h-3.5 w-3.5\" />\n ) : (\n <ChevronRight className=\"h-3.5 w-3.5\" />\n )}\n {t('adaptercloud.violations.evidence', 'Evidence')}\n </button>\n {expanded.has(v.id) && (\n <pre className=\"mt-2 overflow-x-auto rounded-lg border border-border-subtle bg-bg-sunken p-3 font-mono text-xs text-text-secondary\">\n {JSON.stringify(v.evidence, null, 2)}\n </pre>\n )}\n </div>\n )}\n </div>\n\n {isOpen && (\n <div className=\"flex shrink-0 flex-wrap gap-2\">\n {v.status === 'OPEN' && (\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={() => transition(v.id, 'ACKNOWLEDGED')}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-accent disabled:opacity-50\"\n >\n <Check className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.violations.acknowledge', 'Acknowledge')}\n </button>\n )}\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={() => transition(v.id, 'RESOLVED')}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-success-text transition-colors hover:bg-status-success-bg-subtle disabled:opacity-50\"\n >\n <CheckCheck className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.violations.resolve', 'Resolve')}\n </button>\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={() => {\n setActionError(null);\n setWaiverReason('');\n setWaiveTarget(v);\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-secondary transition-colors hover:bg-accent disabled:opacity-50\"\n >\n <FileText className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.violations.waive', 'Waive')}\n </button>\n </div>\n )}\n </div>\n </GlassCard>\n );\n })}\n </div>\n\n {(offset > 0 || hasMore) && (\n <div className=\"mt-6 flex items-center justify-between\">\n <button\n type=\"button\"\n disabled={offset === 0}\n onClick={() => setOffset((o) => Math.max(0, o - PAGE_SIZE))}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n {t('adaptercloud.common.prev', 'Previous')}\n </button>\n <span className=\"text-sm text-text-secondary\">\n {t('adaptercloud.common.showing', 'Showing')} {offset + 1}–{offset + items.length}\n </span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => setOffset((o) => o + PAGE_SIZE)}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {t('adaptercloud.common.next', 'Next')}\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n </DataState>\n\n {/* Waive dialog */}\n <ResponsiveDialog\n open={Boolean(waiveTarget)}\n onOpenChange={(open) => {\n if (!open) setWaiveTarget(null);\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>\n {t('adaptercloud.violations.waiveTitle', 'Waive violation')}\n </ResponsiveDialogTitle>\n </ResponsiveDialogHeader>\n <div className=\"px-1 py-2\">\n <label htmlFor=\"ada-waiver-reason\" className=\"mb-1.5 block text-sm text-text-secondary\">\n {t(\n 'adaptercloud.violations.waivePrompt',\n 'A waiver requires a documented reason and is recorded on the violation.'\n )}\n </label>\n <textarea\n id=\"ada-waiver-reason\"\n value={waiverReason}\n onChange={(e) => setWaiverReason(e.target.value)}\n rows={4}\n autoFocus\n aria-label={t('adaptercloud.violations.waiverReason', 'Waiver reason')}\n placeholder={t(\n 'adaptercloud.violations.waiveReasonPlaceholder',\n 'Why is this acceptable?'\n )}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n {actionError && (\n <p role=\"alert\" aria-live=\"polite\" className=\"mt-2 text-sm text-status-error-text\">\n {actionError}\n </p>\n )}\n </div>\n <ResponsiveDialogFooter>\n <button\n type=\"button\"\n onClick={() => setWaiveTarget(null)}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n {t('adaptercloud.common.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={confirmWaive}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90 disabled:opacity-50\"\n >\n {resolve.isPending && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {t('adaptercloud.violations.confirmWaive', 'Waive')}\n </button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ViolationsListPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/violations/ViolationsListPage.tsx"],"sourcesContent":["/**\n * Violations Queue Page\n * @module adaptercloud/pages/violations\n *\n * The governance work queue (`adaListViolations`). Filters by status (and by\n * policy/resource via URL params). Each open/acknowledged violation can be\n * transitioned via `adaResolveViolation` — acknowledge, resolve, or waive (a\n * waiver requires a reason, enforced both client-side and at the service).\n */\n\nimport { useState, useCallback } from 'react';\nimport { useSearchParams } from 'react-router';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n ShieldAlert,\n ChevronLeft,\n ChevronRight,\n ChevronDown,\n Check,\n CheckCheck,\n FileText,\n Loader2,\n} from 'lucide-react';\nimport {\n GlassCard,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { SeverityBadge } from '../../components/SeverityBadge';\nimport { DataState } from '../../components/DataState';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { useViolations, useResolveViolation } from '../../hooks/useAdapterCloudApi';\nimport { violationStatusLabels, severityRank } from '../../utils/domain';\nimport { formatDate } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { AdaPolicyViolation, AdaViolationStatus } from '../../types';\n\n/** Segmented status tabs — All plus each `AdaViolationStatus`, in queue order. */\nconst STATUS_TABS: (AdaViolationStatus | '')[] = ['', 'OPEN', 'ACKNOWLEDGED', 'RESOLVED', 'WAIVED'];\n\nconst PAGE_SIZE = 20;\n\nexport function ViolationsListPage() {\n const { navigateTo } = useAdapterCloud();\n const [searchParams] = useSearchParams();\n const policyId = searchParams.get('policyId') ?? undefined;\n const resourceId = searchParams.get('resourceId') ?? undefined;\n\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n const [status, setStatus] = useState<AdaViolationStatus | ''>('OPEN');\n const [offset, setOffset] = useState(0);\n const [waiveTarget, setWaiveTarget] = useState<AdaPolicyViolation | null>(null);\n const [waiverReason, setWaiverReason] = useState('');\n const [actionError, setActionError] = useState<string | null>(null);\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n\n const query = useViolations({\n policyId,\n resourceId,\n status: status || undefined,\n pagination: { limit: PAGE_SIZE, offset },\n });\n const resolve = useResolveViolation();\n\n // Live per-status counts for the segmented tabs. Each is a cheap `limit: 1`\n // query read for its `pageInfo.totalCount` (the estate-wide total for that\n // filter); \"All\" is the same query without a status. They respect the current\n // policy/resource URL scope so the badges match the visible queue.\n const countBase = { policyId, resourceId, pagination: { limit: 1, offset: 0 } };\n const allCount = useViolations(countBase);\n const openCount = useViolations({ ...countBase, status: 'OPEN' });\n const ackCount = useViolations({ ...countBase, status: 'ACKNOWLEDGED' });\n const resolvedCount = useViolations({ ...countBase, status: 'RESOLVED' });\n const waivedCount = useViolations({ ...countBase, status: 'WAIVED' });\n\n const tabCounts: Record<AdaViolationStatus | '', number | undefined> = {\n '': allCount.data?.pageInfo.totalCount ?? undefined,\n OPEN: openCount.data?.pageInfo.totalCount ?? undefined,\n ACKNOWLEDGED: ackCount.data?.pageInfo.totalCount ?? undefined,\n RESOLVED: resolvedCount.data?.pageInfo.totalCount ?? undefined,\n WAIVED: waivedCount.data?.pageInfo.totalCount ?? undefined,\n };\n\n const toggleEvidence = useCallback((id: string) => {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n }, []);\n\n // Severity ordering is applied ONLY within the current server page. The queue\n // pages by offset, so this does not globally reorder across pages — a page-2\n // CRITICAL still sorts below a page-1 LOW. Kept as a within-page readability\n // aid (the service has no severity sort arg to make it global).\n const items = [...(query.data?.items ?? [])].sort(\n (a, b) => severityRank[b.severity] - severityRank[a.severity]\n );\n const hasMore = query.data?.pageInfo.hasMore ?? false;\n\n const onError = useCallback(\n (err: unknown) =>\n setActionError(err instanceof Error ? err.message : 'Action failed. Please try again.'),\n []\n );\n\n const transition = useCallback(\n (id: string, newStatus: AdaViolationStatus) => {\n setActionError(null);\n resolve.mutate({ id, status: newStatus }, { onError });\n },\n [resolve, onError]\n );\n\n const confirmWaive = useCallback(() => {\n if (!waiveTarget) return;\n if (!waiverReason.trim()) {\n setActionError(t('adaptercloud.violations.reasonRequired', 'A waiver requires a reason.'));\n return;\n }\n setActionError(null);\n resolve.mutate(\n { id: waiveTarget.id, status: 'WAIVED', waiverReason: waiverReason.trim() },\n {\n onSuccess: () => {\n setWaiveTarget(null);\n setWaiverReason('');\n },\n onError,\n }\n );\n }, [waiveTarget, waiverReason, resolve, onError, t]);\n\n return (\n <PageLayout\n title={t('adaptercloud.violations.title', 'Violations')}\n description={t(\n 'adaptercloud.violations.subtitle',\n 'Work the governance queue — acknowledge, resolve, or waive policy breaches.'\n )}\n >\n <div\n className=\"mb-6 flex flex-wrap items-center gap-2\"\n role=\"tablist\"\n aria-label={t('adaptercloud.violations.filterByStatus', 'Filter by status')}\n >\n {STATUS_TABS.map((tab) => {\n const active = status === tab;\n const count = tabCounts[tab];\n const label =\n tab === ''\n ? t('adaptercloud.violations.allStatuses', 'All')\n : violationStatusLabels[tab];\n return (\n <button\n key={tab || 'all'}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n onClick={() => {\n setStatus(tab);\n setOffset(0);\n }}\n className={cn(\n 'inline-flex items-center gap-2 rounded-full border px-3.5 py-1.5 text-sm font-medium transition-colors',\n active\n ? 'border-transparent bg-action-primary-bg text-action-primary-text'\n : 'border-border-subtle text-text-secondary hover:bg-accent'\n )}\n >\n {label}\n {count !== undefined && (\n <span\n className={cn(\n 'inline-flex min-w-5 items-center justify-center rounded-full px-1.5 text-xs font-semibold tabular-nums',\n active\n ? 'bg-action-primary-text/20 text-action-primary-text'\n : 'bg-bg-sunken text-text-secondary'\n )}\n >\n {count}\n </span>\n )}\n </button>\n );\n })}\n {(policyId || resourceId) && (\n <button\n type=\"button\"\n onClick={() => navigateTo('/violations')}\n className=\"inline-flex items-center gap-1.5 rounded-full bg-accent-blue-subtle px-2.5 py-1 text-xs text-accent-blue hover:underline\"\n >\n {t('adaptercloud.violations.clearScope', 'Clear scope ×')}\n </button>\n )}\n </div>\n\n {actionError && (\n <p\n role=\"alert\"\n aria-live=\"polite\"\n className=\"mb-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\"\n >\n {actionError}\n </p>\n )}\n\n <DataState\n isLoading={query.isLoading}\n isError={query.isError}\n isEmpty={items.length === 0}\n error={query.error}\n onRetry={() => void query.refetch()}\n emptyTitle={t('adaptercloud.violations.emptyTitle', 'No violations')}\n emptyDescription={t(\n 'adaptercloud.violations.emptyDescription',\n 'Nothing matches this filter — your estate is clean here.'\n )}\n emptyIcon={<ShieldAlert className=\"h-10 w-10\" />}\n >\n <div className=\"space-y-3\">\n {items.map((v) => {\n const isOpen = v.status === 'OPEN' || v.status === 'ACKNOWLEDGED';\n return (\n <GlassCard key={v.id} className=\"p-5\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"mb-1.5 flex flex-wrap items-center gap-2\">\n <SeverityBadge severity={v.severity} />\n <StatusBadge status={v.status} />\n {v.policy && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`/policies/${v.policyId}`)}\n className=\"text-xs font-medium text-accent-blue hover:underline\"\n >\n {v.policy.name}\n </button>\n )}\n </div>\n <p className=\"text-sm font-medium text-text-primary\">{v.message}</p>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {t('adaptercloud.violations.detected', 'Detected')} {formatDate(v.detectedAt)}\n {' · '}\n <button\n type=\"button\"\n onClick={() => navigateTo(`/resources/${v.resourceId}`)}\n className=\"hover:underline\"\n >\n {t('adaptercloud.violations.viewResource', 'View resource')}\n </button>\n </p>\n {v.waiverReason && (\n <p className=\"mt-2 rounded-lg bg-bg-sunken px-3 py-1.5 text-xs text-text-secondary\">\n {t('adaptercloud.violations.waiver', 'Waiver')}: {v.waiverReason}\n </p>\n )}\n {v.evidence != null && (\n <div className=\"mt-2\">\n <button\n type=\"button\"\n onClick={() => toggleEvidence(v.id)}\n aria-expanded={expanded.has(v.id)}\n className=\"inline-flex items-center gap-1 text-xs font-medium text-text-secondary transition-colors hover:text-text-primary\"\n >\n {expanded.has(v.id) ? (\n <ChevronDown className=\"h-3.5 w-3.5\" />\n ) : (\n <ChevronRight className=\"h-3.5 w-3.5\" />\n )}\n {t('adaptercloud.violations.evidence', 'Evidence')}\n </button>\n {expanded.has(v.id) && (\n <pre className=\"mt-2 overflow-x-auto rounded-lg border border-border-subtle bg-bg-sunken p-3 font-mono text-xs text-text-secondary\">\n {JSON.stringify(v.evidence, null, 2)}\n </pre>\n )}\n </div>\n )}\n </div>\n\n {isOpen && (\n <div className=\"flex shrink-0 flex-wrap gap-2\">\n {v.status === 'OPEN' && (\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={() => transition(v.id, 'ACKNOWLEDGED')}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-accent disabled:opacity-50\"\n >\n <Check className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.violations.acknowledge', 'Acknowledge')}\n </button>\n )}\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={() => transition(v.id, 'RESOLVED')}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-success-text transition-colors hover:bg-status-success-bg-subtle disabled:opacity-50\"\n >\n <CheckCheck className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.violations.resolve', 'Resolve')}\n </button>\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={() => {\n setActionError(null);\n setWaiverReason('');\n setWaiveTarget(v);\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-secondary transition-colors hover:bg-accent disabled:opacity-50\"\n >\n <FileText className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.violations.waive', 'Waive')}\n </button>\n </div>\n )}\n </div>\n </GlassCard>\n );\n })}\n </div>\n\n {(offset > 0 || hasMore) && (\n <div className=\"mt-6 flex items-center justify-between\">\n <button\n type=\"button\"\n disabled={offset === 0}\n onClick={() => setOffset((o) => Math.max(0, o - PAGE_SIZE))}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n {t('adaptercloud.common.prev', 'Previous')}\n </button>\n <span className=\"text-sm text-text-secondary\">\n {t('adaptercloud.common.showing', 'Showing')} {offset + 1}–{offset + items.length}\n </span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => setOffset((o) => o + PAGE_SIZE)}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {t('adaptercloud.common.next', 'Next')}\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n </DataState>\n\n {/* Waive dialog */}\n <ResponsiveDialog\n open={Boolean(waiveTarget)}\n onOpenChange={(open) => {\n if (!open) setWaiveTarget(null);\n }}\n >\n <ResponsiveDialogContent>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>\n {t('adaptercloud.violations.waiveTitle', 'Waive violation')}\n </ResponsiveDialogTitle>\n </ResponsiveDialogHeader>\n <div className=\"px-1 py-2\">\n <label htmlFor=\"ada-waiver-reason\" className=\"mb-1.5 block text-sm text-text-secondary\">\n {t(\n 'adaptercloud.violations.waivePrompt',\n 'A waiver requires a documented reason and is recorded on the violation.'\n )}\n </label>\n <textarea\n id=\"ada-waiver-reason\"\n value={waiverReason}\n onChange={(e) => setWaiverReason(e.target.value)}\n rows={4}\n autoFocus\n aria-label={t('adaptercloud.violations.waiverReason', 'Waiver reason')}\n placeholder={t(\n 'adaptercloud.violations.waiveReasonPlaceholder',\n 'Why is this acceptable?'\n )}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n {actionError && (\n <p role=\"alert\" aria-live=\"polite\" className=\"mt-2 text-sm text-status-error-text\">\n {actionError}\n </p>\n )}\n </div>\n <ResponsiveDialogFooter>\n <button\n type=\"button\"\n onClick={() => setWaiveTarget(null)}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n {t('adaptercloud.common.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n disabled={resolve.isPending}\n onClick={confirmWaive}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90 disabled:opacity-50\"\n >\n {resolve.isPending && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n {t('adaptercloud.violations.confirmWaive', 'Waive')}\n </button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA2CA,IAAM,KAA2C;CAAC;CAAI;CAAQ;CAAgB;CAAY;AAAQ,GAE5F,IAAY;AAElB,SAAgB,IAAqB;CACnC,IAAM,EAAE,kBAAe,EAAgB,GACjC,CAAC,KAAgB,EAAgB,GACjC,IAAW,EAAa,IAAI,UAAU,KAAK,KAAA,GAC3C,IAAa,EAAa,IAAI,YAAY,KAAK,KAAA,GAE/C,EAAE,GAAG,MAAc,GAAQ,GAC3B,IAAI,GACP,GAAa,MAA6B;EACzC,IAAM,IAAQ,EAAU,CAAG;EAC3B,OAAO,MAAU,IAAM,IAAW;CACpC,GACA,CAAC,CAAS,CACZ,GAEM,CAAC,GAAQ,KAAa,EAAkC,MAAM,GAC9D,CAAC,GAAQ,KAAa,EAAS,CAAC,GAChC,CAAC,GAAa,KAAkB,EAAoC,IAAI,GACxE,CAAC,GAAc,KAAmB,EAAS,EAAE,GAC7C,CAAC,GAAa,KAAkB,EAAwB,IAAI,GAC5D,CAAC,GAAU,KAAe,kBAAsB,IAAI,IAAI,CAAC,GAEzD,IAAQ,EAAc;EAC1B;EACA;EACA,QAAQ,KAAU,KAAA;EAClB,YAAY;GAAE,OAAO;GAAW;EAAO;CACzC,CAAC,GACK,IAAU,EAAoB,GAM9B,IAAY;EAAE;EAAU;EAAY,YAAY;GAAE,OAAO;GAAG,QAAQ;EAAE;CAAE,GACxE,KAAW,EAAc,CAAS,GAClC,KAAY,EAAc;EAAE,GAAG;EAAW,QAAQ;CAAO,CAAC,GAC1D,KAAW,EAAc;EAAE,GAAG;EAAW,QAAQ;CAAe,CAAC,GACjE,KAAgB,EAAc;EAAE,GAAG;EAAW,QAAQ;CAAW,CAAC,GAClE,KAAc,EAAc;EAAE,GAAG;EAAW,QAAQ;CAAS,CAAC,GAE9D,KAAiE;EACrE,IAAI,GAAS,MAAM,SAAS,cAAc,KAAA;EAC1C,MAAM,GAAU,MAAM,SAAS,cAAc,KAAA;EAC7C,cAAc,GAAS,MAAM,SAAS,cAAc,KAAA;EACpD,UAAU,GAAc,MAAM,SAAS,cAAc,KAAA;EACrD,QAAQ,GAAY,MAAM,SAAS,cAAc,KAAA;CACnD,GAEM,IAAiB,GAAa,MAAe;EACjD,GAAa,MAAS;GACpB,IAAM,IAAO,IAAI,IAAI,CAAI;GAGzB,OAFI,EAAK,IAAI,CAAE,IAAG,EAAK,OAAO,CAAE,IAC3B,EAAK,IAAI,CAAE,GACT;EACT,CAAC;CACH,GAAG,CAAC,CAAC,GAMC,IAAQ,CAAC,GAAI,EAAM,MAAM,SAAS,CAAC,CAAE,EAAE,MAC1C,GAAG,MAAM,EAAa,EAAE,YAAY,EAAa,EAAE,SACtD,GACM,IAAU,EAAM,MAAM,SAAS,WAAW,IAE1C,IAAU,GACb,MACC,EAAe,aAAe,QAAQ,EAAI,UAAU,kCAAkC,GACxF,CAAC,CACH,GAEM,IAAa,GAChB,GAAY,MAAkC;EAE7C,AADA,EAAe,IAAI,GACnB,EAAQ,OAAO;GAAE;GAAI,QAAQ;EAAU,GAAG,EAAE,WAAQ,CAAC;CACvD,GACA,CAAC,GAAS,CAAO,CACnB,GAEM,KAAe,QAAkB;EAChC,OACL;OAAI,CAAC,EAAa,KAAK,GAAG;IACxB,EAAe,EAAE,0CAA0C,6BAA6B,CAAC;IACzF;GACF;GAEA,AADA,EAAe,IAAI,GACnB,EAAQ,OACN;IAAE,IAAI,EAAY;IAAI,QAAQ;IAAU,cAAc,EAAa,KAAK;GAAE,GAC1E;IACE,iBAAiB;KAEf,AADA,EAAe,IAAI,GACnB,EAAgB,EAAE;IACpB;IACA;GACF,CACF;EAXA;CAYF,GAAG;EAAC;EAAa;EAAc;EAAS;EAAS;CAAC,CAAC;CAEnD,OACE,kBAAC,GAAD;EACE,OAAO,EAAE,iCAAiC,YAAY;EACtD,aAAa,EACX,oCACA,6EACF;YALF;GAOE,kBAAC,OAAD;IACE,WAAU;IACV,MAAK;IACL,cAAY,EAAE,0CAA0C,kBAAkB;cAH5E,CAKG,GAAY,KAAK,MAAQ;KACxB,IAAM,IAAS,MAAW,GACpB,IAAQ,GAAU,IAClB,IACJ,MAAQ,KACJ,EAAE,uCAAuC,KAAK,IAC9C,EAAsB;KAC5B,OACE,kBAAC,UAAD;MAEE,MAAK;MACL,MAAK;MACL,iBAAe;MACf,eAAe;OAEb,AADA,EAAU,CAAG,GACb,EAAU,CAAC;MACb;MACA,WAAW,EACT,0GACA,IACI,qEACA,0DACN;gBAdF,CAgBG,GACA,MAAU,KAAA,KACT,kBAAC,QAAD;OACE,WAAW,EACT,0GACA,IACI,uDACA,kCACN;iBAEC;MACG,CAAA,CAEF;QA5BD,KAAO,KA4BN;IAEZ,CAAC,IACC,KAAY,MACZ,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,EAAW,aAAa;KACvC,WAAU;eAET,EAAE,sCAAsC,eAAe;IAClD,CAAA,CAEP;;GAEJ,KACC,kBAAC,KAAD;IACE,MAAK;IACL,aAAU;IACV,WAAU;cAET;GACA,CAAA;GAGL,kBAAC,IAAD;IACE,WAAW,EAAM;IACjB,SAAS,EAAM;IACf,SAAS,EAAM,WAAW;IAC1B,OAAO,EAAM;IACb,eAAe,KAAK,EAAM,QAAQ;IAClC,YAAY,EAAE,sCAAsC,eAAe;IACnE,kBAAkB,EAChB,4CACA,0DACF;IACA,WAAW,kBAAC,GAAD,EAAa,WAAU,YAAa,CAAA;cAXjD,CAaE,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAM,KAAK,MAAM;MAChB,IAAM,IAAS,EAAE,WAAW,UAAU,EAAE,WAAW;MACnD,OACE,kBAAC,GAAD;OAAsB,WAAU;iBAC9B,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACE,kBAAC,OAAD;WAAK,WAAU;qBAAf;YACE,kBAAC,IAAD,EAAe,UAAU,EAAE,SAAW,CAAA;YACtC,kBAAC,GAAD,EAAa,QAAQ,EAAE,OAAS,CAAA;YAC/B,EAAE,UACD,kBAAC,UAAD;aACE,MAAK;aACL,eAAe,EAAW,aAAa,EAAE,UAAU;aACnD,WAAU;uBAET,EAAE,OAAO;YACJ,CAAA;WAEP;;UACL,kBAAC,KAAD;WAAG,WAAU;qBAAyC,EAAE;UAAW,CAAA;UACnE,kBAAC,KAAD;WAAG,WAAU;qBAAb;YACG,EAAE,oCAAoC,UAAU;YAAE;YAAE,EAAW,EAAE,UAAU;YAC3E;YACD,kBAAC,UAAD;aACE,MAAK;aACL,eAAe,EAAW,cAAc,EAAE,YAAY;aACtD,WAAU;uBAET,EAAE,wCAAwC,eAAe;YACpD,CAAA;WACP;;UACF,EAAE,gBACD,kBAAC,KAAD;WAAG,WAAU;qBAAb;YACG,EAAE,kCAAkC,QAAQ;YAAE;YAAG,EAAE;WACnD;;UAEJ,EAAE,YAAY,QACb,kBAAC,OAAD;WAAK,WAAU;qBAAf,CACE,kBAAC,UAAD;YACE,MAAK;YACL,eAAe,EAAe,EAAE,EAAE;YAClC,iBAAe,EAAS,IAAI,EAAE,EAAE;YAChC,WAAU;sBAJZ,CAMG,EAAS,IAAI,EAAE,EAAE,IAChB,kBAAC,GAAD,EAAa,WAAU,cAAe,CAAA,IAEtC,kBAAC,GAAD,EAAc,WAAU,cAAe,CAAA,GAExC,EAAE,oCAAoC,UAAU,CAC3C;eACP,EAAS,IAAI,EAAE,EAAE,KAChB,kBAAC,OAAD;YAAK,WAAU;sBACZ,KAAK,UAAU,EAAE,UAAU,MAAM,CAAC;WAChC,CAAA,CAEJ;;SAEJ;YAEJ,KACC,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACG,EAAE,WAAW,UACZ,kBAAC,UAAD;WACE,MAAK;WACL,UAAU,EAAQ;WAClB,eAAe,EAAW,EAAE,IAAI,cAAc;WAC9C,WAAU;qBAJZ,CAME,kBAAC,IAAD,EAAO,WAAU,cAAe,CAAA,GAC/B,EAAE,uCAAuC,aAAa,CACjD;;UAEV,kBAAC,UAAD;WACE,MAAK;WACL,UAAU,EAAQ;WAClB,eAAe,EAAW,EAAE,IAAI,UAAU;WAC1C,WAAU;qBAJZ,CAME,kBAAC,GAAD,EAAY,WAAU,cAAe,CAAA,GACpC,EAAE,mCAAmC,SAAS,CACzC;;UACR,kBAAC,UAAD;WACE,MAAK;WACL,UAAU,EAAQ;WAClB,eAAe;YAGb,AAFA,EAAe,IAAI,GACnB,EAAgB,EAAE,GAClB,EAAe,CAAC;WAClB;WACA,WAAU;qBARZ,CAUE,kBAAC,GAAD,EAAU,WAAU,cAAe,CAAA,GAClC,EAAE,iCAAiC,OAAO,CACrC;;SACL;UAEJ;;MACI,GA/FK,EAAE,EA+FP;KAEf,CAAC;IACE,CAAA,IAEH,IAAS,KAAK,MACd,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,UAAD;OACE,MAAK;OACL,UAAU,MAAW;OACrB,eAAe,GAAW,MAAM,KAAK,IAAI,GAAG,IAAI,CAAS,CAAC;OAC1D,WAAU;iBAJZ,CAME,kBAAC,GAAD,EAAa,WAAU,UAAW,CAAA,GACjC,EAAE,4BAA4B,UAAU,CACnC;;MACR,kBAAC,QAAD;OAAM,WAAU;iBAAhB;QACG,EAAE,+BAA+B,SAAS;QAAE;QAAE,IAAS;QAAE;QAAE,IAAS,EAAM;OACvE;;MACN,kBAAC,UAAD;OACE,MAAK;OACL,UAAU,CAAC;OACX,eAAe,GAAW,MAAM,IAAI,CAAS;OAC7C,WAAU;iBAJZ,CAMG,EAAE,4BAA4B,MAAM,GACrC,kBAAC,GAAD,EAAc,WAAU,UAAW,CAAA,CAC7B;;KACL;MAEE;;GAGX,kBAAC,GAAD;IACE,MAAM,EAAQ;IACd,eAAe,MAAS;KACtB,AAAK,KAAM,EAAe,IAAI;IAChC;cAEA,kBAAC,GAAD,EAAA,UAAA;KACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UACG,EAAE,sCAAsC,iBAAiB,EACrC,CAAA,EACD,CAAA;KACxB,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,SAAD;QAAO,SAAQ;QAAoB,WAAU;kBAC1C,EACC,uCACA,yEACF;OACK,CAAA;OACP,kBAAC,YAAD;QACE,IAAG;QACH,OAAO;QACP,WAAW,MAAM,EAAgB,EAAE,OAAO,KAAK;QAC/C,MAAM;QACN,WAAA;QACA,cAAY,EAAE,wCAAwC,eAAe;QACrE,aAAa,EACX,kDACA,yBACF;QACA,WAAU;OACX,CAAA;OACA,KACC,kBAAC,KAAD;QAAG,MAAK;QAAQ,aAAU;QAAS,WAAU;kBAC1C;OACA,CAAA;MAEF;;KACL,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,EAAe,IAAI;MAClC,WAAU;gBAET,EAAE,8BAA8B,QAAQ;KACnC,CAAA,GACR,kBAAC,UAAD;MACE,MAAK;MACL,UAAU,EAAQ;MAClB,SAAS;MACT,WAAU;gBAJZ,CAMG,EAAQ,aAAa,kBAAC,GAAD,EAAS,WAAU,uBAAwB,CAAA,GAChE,EAAE,wCAAwC,OAAO,CAC5C;OACc,EAAA,CAAA;IACD,EAAA,CAAA;GACT,CAAA;EACR;;AAEhB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@burdenoff/microfe-adaptercloud",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.801.1",
|
|
4
4
|
"description": "Burdenoff AdapterCloud Microfrontend",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -26,15 +26,15 @@
|
|
|
26
26
|
"types": "./dist/index.d.ts",
|
|
27
27
|
"scripts": {
|
|
28
28
|
"dev": "vite",
|
|
29
|
-
"build": "tsc && vite build",
|
|
29
|
+
"build": "tsc && bash scripts/build-limits.sh --gate vite build",
|
|
30
30
|
"schema:pull": "graphql-codegen --project schema-wspace && graphql-codegen --project schema-global",
|
|
31
31
|
"codegen": "graphql-codegen --project wspace && graphql-codegen --project global",
|
|
32
32
|
"codegen:all": "bun run schema:pull && bun run codegen",
|
|
33
33
|
"lint": "eslint .",
|
|
34
34
|
"lint:sanity": "if [ \"${CI:-}\" = \"true\" ]; then bun run lint; else bun run lint -- --cache --cache-location .eslintcache; fi",
|
|
35
35
|
"format": "prettier --write \"src/**/*.{ts,tsx}\"",
|
|
36
|
-
"type:check": "tsc --noEmit",
|
|
37
|
-
"sanity": "bun run codegen && bun run lint:sanity && bun run format && bun run type:check && bun run build && bun run build-storybook",
|
|
36
|
+
"type:check": "bash scripts/build-limits.sh tsc --noEmit",
|
|
37
|
+
"sanity": "bash scripts/build-limits.sh --gate bash -c 'bun run codegen && bun run lint:sanity && bun run format && bun run type:check && bun run build && bun run build-storybook'",
|
|
38
38
|
"storybook": "storybook dev -p 6006",
|
|
39
39
|
"build-storybook": "storybook build",
|
|
40
40
|
"test:storybook": "test-storybook",
|
|
@@ -47,14 +47,14 @@
|
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@apollo/client": "^4.0.11",
|
|
50
|
-
"@burdenoff/fe-libs": "2026.
|
|
50
|
+
"@burdenoff/fe-libs": "2026.801.1",
|
|
51
51
|
"@tanstack/react-query": "^5.90.16",
|
|
52
52
|
"clsx": "^2.1.1",
|
|
53
53
|
"graphql": "^16.12.0",
|
|
54
54
|
"lucide-react": "^0.468.0",
|
|
55
55
|
"react": "^19.0.0",
|
|
56
56
|
"react-dom": "^19.0.0",
|
|
57
|
-
"react-router
|
|
57
|
+
"react-router": "^8.3.0",
|
|
58
58
|
"sonner": "^2.0.7",
|
|
59
59
|
"tailwind-merge": "^3.4.0",
|
|
60
60
|
"zustand": "^5.0.7"
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"access": "restricted"
|
|
103
103
|
},
|
|
104
104
|
"overrides": {
|
|
105
|
-
"@burdenoff/fe-libs": "2026.
|
|
105
|
+
"@burdenoff/fe-libs": "2026.801.1",
|
|
106
106
|
"lodash": ">=4.17.21",
|
|
107
107
|
"lodash-es": ">=4.17.21",
|
|
108
108
|
"dompurify": ">=3.3.4",
|