hazo_audit 2.0.1 → 2.1.0

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.
Files changed (58) hide show
  1. package/CHANGE_LOG.md +80 -0
  2. package/README.md +57 -1
  3. package/config/hazo_audit_config.ini.sample +28 -0
  4. package/db_setup_postgres.sql +76 -0
  5. package/db_setup_sqlite.sql +72 -0
  6. package/dist/client/AuditViewer.js +1 -1
  7. package/dist/client/FieldAuditIcon.d.ts.map +1 -1
  8. package/dist/client/FieldAuditIcon.js +3 -3
  9. package/dist/client/FieldAuditIcon.js.map +1 -1
  10. package/dist/client/FieldAuditTrail.d.ts.map +1 -1
  11. package/dist/client/FieldAuditTrail.js +72 -9
  12. package/dist/client/FieldAuditTrail.js.map +1 -1
  13. package/dist/client/RevertConfirmDialog.js +1 -1
  14. package/dist/index.d.ts +43 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +9 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/lib/config/hazo_audit_config.d.ts +99 -0
  19. package/dist/lib/config/hazo_audit_config.d.ts.map +1 -0
  20. package/dist/lib/config/hazo_audit_config.js +67 -0
  21. package/dist/lib/config/hazo_audit_config.js.map +1 -0
  22. package/dist/nextjs/index.d.ts +12 -0
  23. package/dist/nextjs/index.d.ts.map +1 -1
  24. package/dist/nextjs/index.js +307 -218
  25. package/dist/nextjs/index.js.map +1 -1
  26. package/dist/server/audited_crud.js +3 -3
  27. package/dist/server/audited_crud.js.map +1 -1
  28. package/dist/server/context.js +3 -3
  29. package/dist/server/context.js.map +1 -1
  30. package/dist/server/diff.js +11 -3
  31. package/dist/server/diff.js.map +1 -1
  32. package/dist/server/errors.d.ts +10 -1
  33. package/dist/server/errors.d.ts.map +1 -1
  34. package/dist/server/errors.js +16 -2
  35. package/dist/server/errors.js.map +1 -1
  36. package/dist/server/intent.js +3 -3
  37. package/dist/server/intent.js.map +1 -1
  38. package/dist/server/outbox.js +2 -2
  39. package/dist/server/outbox.js.map +1 -1
  40. package/dist/server/worker.d.ts +7 -7
  41. package/dist/server/worker.d.ts.map +1 -1
  42. package/dist/server/worker.js +60 -15
  43. package/dist/server/worker.js.map +1 -1
  44. package/dist/server/wrap.js +2 -2
  45. package/dist/server/wrap.js.map +1 -1
  46. package/dist/utils/logger.d.ts +25 -0
  47. package/dist/utils/logger.d.ts.map +1 -0
  48. package/dist/utils/logger.js +42 -0
  49. package/dist/utils/logger.js.map +1 -0
  50. package/dist/utils/uuid.d.ts +19 -0
  51. package/dist/utils/uuid.d.ts.map +1 -0
  52. package/dist/utils/uuid.js +22 -0
  53. package/dist/utils/uuid.js.map +1 -0
  54. package/package.json +36 -21
  55. package/dist/client/cn.d.ts +0 -3
  56. package/dist/client/cn.d.ts.map +0 -1
  57. package/dist/client/cn.js +0 -6
  58. package/dist/client/cn.js.map +0 -1
package/CHANGE_LOG.md CHANGED
@@ -1,5 +1,85 @@
1
1
  # Change log
2
2
 
3
+ ## 2.1.0 — 2026-05-29
4
+
5
+ ### Workspace v2 migration (Wave 2)
6
+
7
+ Standardisation onto the workspace foundation packages — adopt `hazo_core`,
8
+ align logging / errors / correlation IDs / config / UUIDs with the rest of
9
+ the ecosystem. No public API removed; the previous response shapes for
10
+ `/audit/events`, `reveal`, and `viewer` are preserved.
11
+
12
+ ### Added
13
+
14
+ - **`hazo_core` peer dependency (`^1.0.0`).** Required; supplies
15
+ `HazoError`, `withContext`, `generateRequestId`, `createLogger`,
16
+ `loadConfig`.
17
+ - **`hazo_ui` peer dependency (`^3.0.1`, optional).** Client components now
18
+ import `cn` from `hazo_ui` — consumers that use `<FieldAuditIcon>` etc.
19
+ must install it. Server-only consumers can skip it.
20
+ - **Workspace-standard logger** at `src/utils/logger.ts` — `get_logger()` /
21
+ `set_logger()` default to `createLogger('hazo_audit')`. Worker + Next.js
22
+ routes emit structured event names (`worker.started`,
23
+ `outbox.row_drained`, `outbox.row_failed`, `events.reveal.served`, etc.).
24
+ - **`withContext` wrapping** around every drained outbox row in the worker
25
+ and every Next.js handler — correlation IDs from the producing write flow
26
+ through every nested DB call and `fetchWithRequestId`.
27
+ - **`HazoError` subclasses** — `RecordNotFoundError` now extends
28
+ `HazoNotFoundError` (`HAZO_AUDIT_RECORD_NOT_FOUND`, httpStatus 404). Route
29
+ handlers use a `handleError(logger, event, error)` helper that maps
30
+ `HazoError.is(err)` to the right HTTP status + log level.
31
+ - **`src/lib/config/hazo_audit_config.ts`** — workspace-standard INI
32
+ loader via `hazo_core.loadConfig` for `[general]` / `[log.overrides]` /
33
+ `[retention]` / `[worker]` sections. Coexists with
34
+ `src/server/config.ts::loadAuditConfig()`, which keeps owning the
35
+ package-specific `[capture]` and `[overrides.*]` rules.
36
+ - **`config/hazo_audit_config.ini.sample`** now documents the
37
+ `[general]` and `[log.overrides]` sections and `HAZO_AUDIT_<SECTION>_<KEY>`
38
+ env-var overrides.
39
+ - **Root `db_setup_postgres.sql` + `db_setup_sqlite.sql`** — idempotent,
40
+ consumer-facing schema setup (S6). The historical `migrations/001_init.sql`
41
+ is preserved.
42
+ - **`AGENTS.md`** at root + `src/`, and `design/feature_requests/INDEX.md`
43
+ skeleton (S13 + S16).
44
+ - **`/autotest` route** in the test-app powered by
45
+ `hazo_ui/test-harness` — workspace-standard browser scenarios
46
+ (`cn` re-export, `generateRequestId`, `HazoError` subclasses,
47
+ `withContext` / `getCorrelationId`).
48
+
49
+ ### Changed
50
+
51
+ - **`crypto.randomUUID()` removed** from all server modules in favour of
52
+ `src/utils/uuid.ts::generateUUID()` (wraps
53
+ `generateRequestId().slice(4)` from `hazo_core`).
54
+ - **`src/client/cn.ts` deleted** — components now import `cn` from
55
+ `hazo_ui`. The local `clsx + tailwind-merge` duplicate is gone.
56
+ - **Worker logger interface** narrowed to the workspace `Logger` type and
57
+ defaults to `get_logger()` when the consumer doesn't pass one.
58
+ - **test-app/package.json** uses `"*"` for workspace-local resolution of
59
+ `hazo_audit`, `hazo_connect`, `hazo_core`, `hazo_ui` (previously
60
+ `file:..`). `next.config.js` adds `hazo_core`, `hazo_logs`, `hazo_ui` to
61
+ `transpilePackages`.
62
+ - **`engines` block removed** from package.json (workspace standard).
63
+ - **Workspace registration** — `hazo_audit/test-app` is now listed in the
64
+ root `package.json` `workspaces` array.
65
+
66
+ ## 2.0.2 — 2026-05-27
67
+
68
+ ### Added
69
+
70
+ - **`opLabels` prop** on `<FieldAuditTrail />` and `<FieldAuditIcon />` for
71
+ overriding the op badge text per app. Shape: `{ insert?, update?, delete? }`.
72
+ Exported alongside `DEFAULT_OP_LABELS` for apps that want to compose on top
73
+ of the defaults. Empty-string override falls back to the raw DB op so apps
74
+ can opt back into the legacy uppercase rendering per-op.
75
+
76
+ ### Changed
77
+
78
+ - **Op badge defaults** — `INSERT` / `UPDATE` / `DELETE` are now rendered as
79
+ `Added` / `Changed` / `Removed` (action-oriented, past tense). This reads
80
+ naturally next to the actor line: `Added · Pubs Abayasiri`. The uppercase
81
+ text-transform on the badge was dropped so casing in `opLabels` is honoured.
82
+
3
83
  ## 2.0.1 — 2026-05-20
4
84
 
5
85
  ### Fixed
package/README.md CHANGED
@@ -72,7 +72,7 @@ hazo_audit_field ◄──────────── /api/audit/events
72
72
 
73
73
  | Import | What |
74
74
  |---|---|
75
- | `hazo_audit` | Client-safe types and permission constants (`AUDIT_VIEW_HISTORY`, etc.). |
75
+ | `hazo_audit` | Client-safe types and permission constants (`AUDIT_VIEW_HISTORY`, etc.). Also exports `OpLabels` interface and `DEFAULT_OP_LABELS` constant. |
76
76
  | `hazo_audit/server` | `wrapWithAudit`, `startAuditWorker`, `runWithAuditContext`, `createAuditedCrudService`, `emitIntentEvent`. Server-only. |
77
77
  | `hazo_audit/nextjs` | `createAuditEventsRoutes` — Next.js GET + reveal POST handlers. |
78
78
  | `hazo_audit/client` | `<FieldAuditIcon />`, `<FieldAuditTrail />`. Safe in client components. |
@@ -172,6 +172,43 @@ await svc.updateById(folderId, patch, {
172
172
  Direct Layer-1 intent emission (no piggyback). `withAudit(name, payload, fn)`
173
173
  ergonomic is Phase 2.
174
174
 
175
+ ### `OpLabels` / `DEFAULT_OP_LABELS`
176
+
177
+ Override the badge labels rendered on each event in `<FieldAuditTrail />`:
178
+
179
+ ```ts
180
+ import { DEFAULT_OP_LABELS } from 'hazo_audit'
181
+ import { FieldAuditTrail } from 'hazo_audit/client'
182
+
183
+ // Keep defaults for insert/delete; rename update → "Edited"
184
+ <FieldAuditTrail
185
+ {...props}
186
+ opLabels={{ ...DEFAULT_OP_LABELS, update: 'Edited' }}
187
+ />
188
+ ```
189
+
190
+ Default labels: `insert → Added`, `update → Changed`, `delete → Removed`.
191
+ Pass an empty string for an op to fall back to the raw DB op.
192
+
193
+ ### Intent labels (`intentLabels`)
194
+
195
+ When events are fired inside `auditIntent(adapter, name, callback)`, the
196
+ trail can annotate each event with a human-readable source label:
197
+
198
+ ```tsx
199
+ <FieldAuditTrail
200
+ {...props}
201
+ intentLabels={{
202
+ survey_prefill_key_info: 'auto-fill',
203
+ wp_pdf_prefill: 'PDF import',
204
+ }}
205
+ />
206
+ // Renders: "Changed · Pubs Abayasiri (via auto-fill)"
207
+ ```
208
+
209
+ The component fetches the correlated intent events automatically when
210
+ `intentLabels` is non-empty; no extra setup required.
211
+
175
212
  ### `createAuditEventsRoutes({ audit_adapter, getAuth })` → `{ GET, reveal: { POST } }`
176
213
 
177
214
  Next.js route factory.
@@ -204,10 +241,29 @@ createAuditEventsRoutes({
204
241
  Renders a clock icon that opens a popover with the field's audit trail.
205
242
  Self-positioning, no Radix dep.
206
243
 
244
+ | Prop | Type | Default | Description |
245
+ |---|---|---|---|
246
+ | `subjectKind` | `string` | — | Required. Table-level subject kind (e.g. `"client_folder"`). |
247
+ | `subjectId` | `string` | — | Required. Record ID. |
248
+ | `fieldPath` | `string` | — | Field to scope the trail to. |
249
+ | `api_base` | `string` | `"/api/audit"` | Route prefix. |
250
+ | `opLabels` | `OpLabels` | `DEFAULT_OP_LABELS` | Override op badge text for individual ops. |
251
+ | `intentLabels` | `Record<string, string>` | — | Map of intent event names → display labels. Adds a "(via …)" annotation to events fired inside a named intent. |
252
+
207
253
  ### `<FieldAuditTrail subjectKind subjectId fieldPath? />`
208
254
 
209
255
  Renders the trail directly (use in a sidebar, modal, etc.).
210
256
 
257
+ | Prop | Type | Default | Description |
258
+ |---|---|---|---|
259
+ | `subjectKind` | `string` | — | Required. |
260
+ | `subjectId` | `string` | — | Required. |
261
+ | `fieldPath` | `string` | — | Filter to one field. Omit for the full record trail. |
262
+ | `api_base` | `string` | `"/api/audit"` | Route prefix. |
263
+ | `opLabels` | `OpLabels` | `DEFAULT_OP_LABELS` | Override op badge text. See `OpLabels` + `DEFAULT_OP_LABELS`. |
264
+ | `intentLabels` | `Record<string, string>` | — | Annotate changes with their originating intent. Key = bare event name (`.completed`/`.failed` stripped). |
265
+ | `limit` | `number` | `50` | Max events to fetch. |
266
+
211
267
  ## Schema
212
268
 
213
269
  Three tables (see `migrations/001_init.sql` for both Postgres + SQLite):
@@ -4,7 +4,35 @@
4
4
  ; and startAuditWorker() at startup. INI is the primary source of truth for
5
5
  ; capture rules; the only TypeScript-shaped escape hatch is the `resolvers`
6
6
  ; option on wrapWithAudit().
7
+ ;
8
+ ; Per hazo workspace standard S7, values may also be overridden via env vars:
9
+ ; HAZO_AUDIT_<SECTION>_<KEY>=value
10
+ ; e.g. HAZO_AUDIT_WORKER_POLL_MS=500
11
+ ;
12
+ ; Per D-019, a per-environment overlay file at
13
+ ; config/hazo_audit_config.<HAZO_ENV>.ini
14
+ ; is layered on top of this base file when HAZO_ENV is set.
15
+
16
+ ; ============================================================================
17
+ ; [general] - Workspace-standard general configuration
18
+ ; ============================================================================
19
+ [general]
20
+
21
+ ; Deployment environment label. Falls back to NODE_ENV, then 'development'.
22
+ ; env = production
7
23
 
24
+ ; ============================================================================
25
+ ; [log.overrides] - Per-namespace log level overrides (workspace standard)
26
+ ; Format: <namespace> = trace|debug|info|warn|error
27
+ ; ============================================================================
28
+ [log.overrides]
29
+
30
+ ; hazo_audit = info
31
+ ; hazo_audit/worker = warn
32
+
33
+ ; ============================================================================
34
+ ; [capture] - Which tables to audit
35
+ ; ============================================================================
8
36
  [capture]
9
37
  ; Whitelist by prefix or exact name. At least one of include_* must match for
10
38
  ; a write to be captured (after passing exclusions).
@@ -0,0 +1,76 @@
1
+ -- hazo_audit PostgreSQL schema setup (idempotent)
2
+ --
3
+ -- Three tables:
4
+ -- hazo_audit_outbox : queue produced by wrapWithAudit, drained by the worker
5
+ -- hazo_audit_field : per-leaf field events the UI reads from
6
+ -- hazo_audit_intent : Layer-1 named events (e.g., 'audit_reveal')
7
+
8
+ CREATE TABLE IF NOT EXISTS hazo_audit_outbox (
9
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
10
+ scope_id UUID,
11
+ correlation_id UUID NOT NULL,
12
+ table_name TEXT NOT NULL,
13
+ subject_kind TEXT NOT NULL,
14
+ subject_id TEXT NOT NULL,
15
+ op TEXT NOT NULL CHECK (op IN ('insert','update','delete')),
16
+ before_row JSONB,
17
+ after_row JSONB,
18
+ actor_kind TEXT NOT NULL,
19
+ actor_user_id UUID,
20
+ actor_label TEXT,
21
+ intent_event TEXT,
22
+ intent_payload JSONB,
23
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
24
+ drained_at TIMESTAMPTZ,
25
+ attempt_count INTEGER NOT NULL DEFAULT 0,
26
+ last_attempt_at TIMESTAMPTZ,
27
+ failed_at TIMESTAMPTZ,
28
+ failure_reason TEXT
29
+ );
30
+
31
+ CREATE INDEX IF NOT EXISTS ix_hazo_audit_outbox_drain
32
+ ON hazo_audit_outbox (drained_at, failed_at, attempt_count, last_attempt_at)
33
+ WHERE drained_at IS NULL AND failed_at IS NULL;
34
+
35
+ CREATE INDEX IF NOT EXISTS ix_hazo_audit_outbox_chain
36
+ ON hazo_audit_outbox (subject_kind, subject_id, created_at DESC)
37
+ WHERE drained_at IS NOT NULL;
38
+
39
+ CREATE TABLE IF NOT EXISTS hazo_audit_field (
40
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
41
+ scope_id UUID,
42
+ correlation_id UUID NOT NULL,
43
+ subject_kind TEXT NOT NULL,
44
+ subject_id TEXT NOT NULL,
45
+ field_path TEXT NOT NULL,
46
+ op TEXT NOT NULL CHECK (op IN ('insert','update','delete')),
47
+ before_value JSONB,
48
+ after_value JSONB,
49
+ is_sensitive BOOLEAN NOT NULL DEFAULT FALSE,
50
+ actor_kind TEXT NOT NULL,
51
+ actor_user_id UUID,
52
+ actor_label TEXT,
53
+ occurred_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
54
+ );
55
+
56
+ CREATE INDEX IF NOT EXISTS ix_hazo_audit_field_subject
57
+ ON hazo_audit_field (subject_kind, subject_id, field_path, occurred_at DESC);
58
+
59
+ CREATE TABLE IF NOT EXISTS hazo_audit_intent (
60
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
61
+ scope_id UUID,
62
+ correlation_id UUID NOT NULL,
63
+ event_name TEXT NOT NULL,
64
+ payload JSONB,
65
+ subject_kind TEXT,
66
+ subject_id TEXT,
67
+ actor_kind TEXT NOT NULL,
68
+ actor_user_id UUID,
69
+ actor_label TEXT,
70
+ occurred_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
71
+ );
72
+
73
+ CREATE INDEX IF NOT EXISTS ix_hazo_audit_intent_event
74
+ ON hazo_audit_intent (event_name, occurred_at DESC);
75
+
76
+ NOTIFY pgrst, 'reload schema';
@@ -0,0 +1,72 @@
1
+ -- hazo_audit SQLite schema setup (idempotent)
2
+ --
3
+ -- Three tables:
4
+ -- hazo_audit_outbox : queue produced by wrapWithAudit, drained by the worker
5
+ -- hazo_audit_field : per-leaf field events the UI reads from
6
+ -- hazo_audit_intent : Layer-1 named events (e.g., 'audit_reveal')
7
+
8
+ CREATE TABLE IF NOT EXISTS hazo_audit_outbox (
9
+ id TEXT PRIMARY KEY,
10
+ scope_id TEXT,
11
+ correlation_id TEXT NOT NULL,
12
+ table_name TEXT NOT NULL,
13
+ subject_kind TEXT NOT NULL,
14
+ subject_id TEXT NOT NULL,
15
+ op TEXT NOT NULL CHECK (op IN ('insert','update','delete')),
16
+ before_row TEXT,
17
+ after_row TEXT,
18
+ actor_kind TEXT NOT NULL,
19
+ actor_user_id TEXT,
20
+ actor_label TEXT,
21
+ intent_event TEXT,
22
+ intent_payload TEXT,
23
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
24
+ drained_at TEXT,
25
+ attempt_count INTEGER NOT NULL DEFAULT 0,
26
+ last_attempt_at TEXT,
27
+ failed_at TEXT,
28
+ failure_reason TEXT
29
+ );
30
+
31
+ CREATE INDEX IF NOT EXISTS ix_hazo_audit_outbox_drain
32
+ ON hazo_audit_outbox (drained_at, failed_at, attempt_count, last_attempt_at);
33
+
34
+ CREATE INDEX IF NOT EXISTS ix_hazo_audit_outbox_chain
35
+ ON hazo_audit_outbox (subject_kind, subject_id, created_at);
36
+
37
+ CREATE TABLE IF NOT EXISTS hazo_audit_field (
38
+ id TEXT PRIMARY KEY,
39
+ scope_id TEXT,
40
+ correlation_id TEXT NOT NULL,
41
+ subject_kind TEXT NOT NULL,
42
+ subject_id TEXT NOT NULL,
43
+ field_path TEXT NOT NULL,
44
+ op TEXT NOT NULL CHECK (op IN ('insert','update','delete')),
45
+ before_value TEXT,
46
+ after_value TEXT,
47
+ is_sensitive INTEGER NOT NULL DEFAULT 0,
48
+ actor_kind TEXT NOT NULL,
49
+ actor_user_id TEXT,
50
+ actor_label TEXT,
51
+ occurred_at TEXT NOT NULL DEFAULT (datetime('now'))
52
+ );
53
+
54
+ CREATE INDEX IF NOT EXISTS ix_hazo_audit_field_subject
55
+ ON hazo_audit_field (subject_kind, subject_id, field_path, occurred_at);
56
+
57
+ CREATE TABLE IF NOT EXISTS hazo_audit_intent (
58
+ id TEXT PRIMARY KEY,
59
+ scope_id TEXT,
60
+ correlation_id TEXT NOT NULL,
61
+ event_name TEXT NOT NULL,
62
+ payload TEXT,
63
+ subject_kind TEXT,
64
+ subject_id TEXT,
65
+ actor_kind TEXT NOT NULL,
66
+ actor_user_id TEXT,
67
+ actor_label TEXT,
68
+ occurred_at TEXT NOT NULL DEFAULT (datetime('now'))
69
+ );
70
+
71
+ CREATE INDEX IF NOT EXISTS ix_hazo_audit_intent_event
72
+ ON hazo_audit_intent (event_name, occurred_at);
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useState } from 'react';
4
- import { cn } from './cn.js';
4
+ import { cn } from 'hazo_ui';
5
5
  export function AuditViewer({ api_base = '/api/audit', initialFilters = {}, className, }) {
6
6
  const [filters, setFilters] = useState(initialFilters);
7
7
  const [events, setEvents] = useState([]);
@@ -1 +1 @@
1
- {"version":3,"file":"FieldAuditIcon.d.ts","sourceRoot":"","sources":["../../src/client/FieldAuditIcon.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,GAAG,CAAC,OAAO,CAwEtE"}
1
+ {"version":3,"file":"FieldAuditIcon.d.ts","sourceRoot":"","sources":["../../src/client/FieldAuditIcon.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,GAAG,CAAC,OAAO,CAmFtE"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from 'react';
4
- import { cn } from './cn.js';
4
+ import { cn } from 'hazo_ui';
5
5
  import { FieldAuditTrail } from './FieldAuditTrail.js';
6
6
  /**
7
7
  * Small clock-icon button that opens a popover with the field's audit trail.
@@ -12,7 +12,7 @@ import { FieldAuditTrail } from './FieldAuditTrail.js';
12
12
  * permission" hint.
13
13
  */
14
14
  export function FieldAuditIcon(props) {
15
- const { subjectKind, subjectId, fieldPath, api_base, className, label } = props;
15
+ const { subjectKind, subjectId, fieldPath, api_base, intentLabels, opLabels, className, label, } = props;
16
16
  const [open, setOpen] = React.useState(false);
17
17
  const rootRef = React.useRef(null);
18
18
  React.useEffect(() => {
@@ -35,7 +35,7 @@ export function FieldAuditIcon(props) {
35
35
  document.removeEventListener('keydown', onKey);
36
36
  };
37
37
  }, [open]);
38
- return (_jsxs("div", { ref: rootRef, className: "relative inline-block", children: [_jsx("button", { type: "button", "aria-label": label ?? `View audit history for ${fieldPath}`, title: label ?? 'View audit history', onClick: () => setOpen((v) => !v), className: cn('inline-flex h-6 w-6 items-center justify-center rounded-full', 'text-slate-400 transition-colors hover:bg-slate-100 hover:text-slate-700', 'focus:outline-none focus:ring-2 focus:ring-slate-400', 'dark:hover:bg-slate-800 dark:hover:text-slate-200', className), children: _jsx(ClockIcon, { className: "h-3.5 w-3.5" }) }), open && (_jsxs("div", { role: "dialog", "aria-label": "Audit history", className: cn('absolute right-0 z-50 mt-2 w-96 max-w-[calc(100vw-2rem)]', 'rounded-md border border-slate-200 bg-white p-3 shadow-lg', 'dark:border-slate-700 dark:bg-slate-900'), children: [_jsxs("div", { className: "mb-2 flex items-center justify-between", children: [_jsxs("h3", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: ["History \u00B7 ", fieldPath] }), _jsx("button", { type: "button", "aria-label": "Close", onClick: () => setOpen(false), className: "text-slate-400 hover:text-slate-700 dark:hover:text-slate-200", children: _jsx(CloseIcon, { className: "h-4 w-4" }) })] }), _jsx(FieldAuditTrail, { subjectKind: subjectKind, subjectId: subjectId, fieldPath: fieldPath, api_base: api_base })] }))] }));
38
+ return (_jsxs("div", { ref: rootRef, className: "relative inline-block", children: [_jsx("button", { type: "button", "aria-label": label ?? `View audit history for ${fieldPath}`, title: label ?? 'View audit history', onClick: () => setOpen((v) => !v), className: cn('inline-flex h-6 w-6 items-center justify-center rounded-full', 'text-slate-400 transition-colors hover:bg-slate-100 hover:text-slate-700', 'focus:outline-none focus:ring-2 focus:ring-slate-400', 'dark:hover:bg-slate-800 dark:hover:text-slate-200', className), children: _jsx(ClockIcon, { className: "h-3.5 w-3.5" }) }), open && (_jsxs("div", { role: "dialog", "aria-label": "Audit history", className: cn('absolute right-0 z-50 mt-2 w-96 max-w-[calc(100vw-2rem)]', 'rounded-md border border-slate-200 bg-white p-3 shadow-lg', 'dark:border-slate-700 dark:bg-slate-900'), children: [_jsxs("div", { className: "mb-2 flex items-center justify-between", children: [_jsxs("h3", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: ["History \u00B7 ", fieldPath] }), _jsx("button", { type: "button", "aria-label": "Close", onClick: () => setOpen(false), className: "text-slate-400 hover:text-slate-700 dark:hover:text-slate-200", children: _jsx(CloseIcon, { className: "h-4 w-4" }) })] }), _jsx(FieldAuditTrail, { subjectKind: subjectKind, subjectId: subjectId, fieldPath: fieldPath, api_base: api_base, intentLabels: intentLabels, opLabels: opLabels })] }))] }));
39
39
  }
40
40
  function ClockIcon({ className }) {
41
41
  return (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: className, "aria-hidden": true, children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("polyline", { points: "12 6 12 12 16 14" })] }));
@@ -1 +1 @@
1
- {"version":3,"file":"FieldAuditIcon.js","sourceRoot":"","sources":["../../src/client/FieldAuditIcon.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FieldAuditIcon.js","sourceRoot":"","sources":["../../src/client/FieldAuditIcon.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"FieldAuditTrail.d.ts","sourceRoot":"","sources":["../../src/client/FieldAuditTrail.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,GAAG,CAAC,OAAO,CA+JxE"}
1
+ {"version":3,"file":"FieldAuditTrail.d.ts","sourceRoot":"","sources":["../../src/client/FieldAuditTrail.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,GAAG,CAAC,OAAO,CAiNxE"}
@@ -1,15 +1,22 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from 'react';
4
- import { cn } from './cn.js';
4
+ import { cn } from 'hazo_ui';
5
+ import { DEFAULT_OP_LABELS } from '../index.js';
5
6
  /**
6
7
  * Renders an ordered list of field audit events for a subject (optionally
7
8
  * filtered to a single field_path). Sensitive rows show "[redacted]" with a
8
9
  * "Reveal" button that calls /audit/events/[id]/reveal.
9
10
  */
10
11
  export function FieldAuditTrail(props) {
11
- const { subjectKind, subjectId, fieldPath, api_base = '/api/audit', limit = 50, className, onRevealed, } = props;
12
- const [state, setState] = React.useState({ loading: true, events: [], revealed: {} });
12
+ const { subjectKind, subjectId, fieldPath, api_base = '/api/audit', intentLabels, opLabels, limit = 50, className, onRevealed, } = props;
13
+ const wantIntent = !!intentLabels && Object.keys(intentLabels).length > 0;
14
+ const [state, setState] = React.useState({
15
+ loading: true,
16
+ events: [],
17
+ intentByCorrelation: new Map(),
18
+ revealed: {},
19
+ });
13
20
  React.useEffect(() => {
14
21
  let cancelled = false;
15
22
  setState((s) => ({ ...s, loading: true, error: undefined }));
@@ -20,6 +27,8 @@ export function FieldAuditTrail(props) {
20
27
  });
21
28
  if (fieldPath)
22
29
  params.set('field_path', fieldPath);
30
+ if (wantIntent)
31
+ params.set('include', 'intent');
23
32
  fetch(`${api_base}/events?${params.toString()}`, { credentials: 'include' })
24
33
  .then(async (r) => {
25
34
  if (r.status === 403) {
@@ -37,14 +46,35 @@ export function FieldAuditTrail(props) {
37
46
  setState({
38
47
  loading: false,
39
48
  events: [],
49
+ intentByCorrelation: new Map(),
40
50
  revealed: {},
41
51
  error: 'You do not have permission to view audit history.',
42
52
  });
43
53
  return;
44
54
  }
55
+ // Build correlation_id → intent map. When multiple events share a
56
+ // correlation_id (e.g. `name` + `name.completed`), prefer the bare
57
+ // started event since `.completed`/`.failed` carry lifecycle status
58
+ // rather than the user-meaningful source label.
59
+ const intentMap = new Map();
60
+ for (const ie of data.intent_events ?? []) {
61
+ const existing = intentMap.get(ie.correlation_id);
62
+ if (!existing) {
63
+ intentMap.set(ie.correlation_id, ie);
64
+ continue;
65
+ }
66
+ const existingIsLifecycle = existing.event_name.endsWith('.completed') ||
67
+ existing.event_name.endsWith('.failed');
68
+ const candidateIsLifecycle = ie.event_name.endsWith('.completed') ||
69
+ ie.event_name.endsWith('.failed');
70
+ if (existingIsLifecycle && !candidateIsLifecycle) {
71
+ intentMap.set(ie.correlation_id, ie);
72
+ }
73
+ }
45
74
  setState({
46
75
  loading: false,
47
76
  events: data.field_events ?? [],
77
+ intentByCorrelation: intentMap,
48
78
  revealed: {},
49
79
  });
50
80
  })
@@ -54,6 +84,7 @@ export function FieldAuditTrail(props) {
54
84
  setState({
55
85
  loading: false,
56
86
  events: [],
87
+ intentByCorrelation: new Map(),
57
88
  revealed: {},
58
89
  error: err.message,
59
90
  });
@@ -61,7 +92,7 @@ export function FieldAuditTrail(props) {
61
92
  return () => {
62
93
  cancelled = true;
63
94
  };
64
- }, [subjectKind, subjectId, fieldPath, api_base, limit]);
95
+ }, [subjectKind, subjectId, fieldPath, api_base, limit, wantIntent]);
65
96
  async function handleReveal(id) {
66
97
  try {
67
98
  const r = await fetch(`${api_base}/events/${id}/reveal`, {
@@ -96,11 +127,43 @@ export function FieldAuditTrail(props) {
96
127
  if (state.events.length === 0) {
97
128
  return (_jsx("div", { className: cn('py-3 text-center text-xs text-slate-400', className), children: "No history yet." }));
98
129
  }
99
- return (_jsx("ol", { className: cn('space-y-2 text-sm', className), children: state.events.map((ev) => (_jsxs("li", { className: "rounded border border-slate-200 p-2 dark:border-slate-700", children: [_jsxs("div", { className: "mb-1 flex items-center justify-between gap-2 text-xs text-slate-500", children: [_jsxs("span", { children: [_jsx("span", { className: cn('mr-2 inline-block rounded px-1.5 py-0.5 text-[10px] font-medium uppercase', ev.op === 'insert'
100
- ? 'bg-emerald-100 text-emerald-700'
101
- : ev.op === 'delete'
102
- ? 'bg-rose-100 text-rose-700'
103
- : 'bg-sky-100 text-sky-700'), children: ev.op }), ev.actor_label || ev.actor_user_id || ev.actor_kind] }), _jsx("time", { dateTime: ev.occurred_at, title: ev.occurred_at, className: "text-[11px] text-slate-400", children: formatDate(ev.occurred_at) })] }), !fieldPath && (_jsx("div", { className: "mb-1 font-mono text-xs text-slate-600 dark:text-slate-300", children: ev.field_path })), _jsx(ValueDiff, { event: ev, revealed: state.revealed[ev.id], onReveal: () => handleReveal(ev.id) })] }, ev.id))) }));
130
+ return (_jsx("ol", { className: cn('space-y-2 text-sm', className), children: state.events.map((ev) => {
131
+ const sourceLabel = resolveIntentLabel(ev.correlation_id, state.intentByCorrelation, intentLabels);
132
+ const actor = ev.actor_label || ev.actor_user_id || ev.actor_kind;
133
+ return (_jsxs("li", { className: "rounded border border-slate-200 p-2 dark:border-slate-700", children: [_jsxs("div", { className: "mb-1 flex items-center justify-between gap-2 text-xs text-slate-500", children: [_jsxs("span", { children: [_jsx("span", { className: cn('mr-2 inline-block rounded px-1.5 py-0.5 text-[10px] font-semibold tracking-wide', ev.op === 'insert'
134
+ ? 'bg-emerald-600 text-white dark:bg-emerald-500'
135
+ : ev.op === 'delete'
136
+ ? 'bg-rose-600 text-white dark:bg-rose-500'
137
+ : 'bg-sky-600 text-white dark:bg-sky-500'), children: resolveOpLabel(ev.op, opLabels) }), actor, sourceLabel && (_jsxs("span", { className: "ml-1 text-slate-500 dark:text-slate-400", children: ["(via ", sourceLabel, ")"] }))] }), _jsx("time", { dateTime: ev.occurred_at, title: ev.occurred_at, className: "text-[11px] text-slate-400", children: formatDate(ev.occurred_at) })] }), !fieldPath && (_jsx("div", { className: "mb-1 font-mono text-xs text-slate-600 dark:text-slate-300", children: ev.field_path })), _jsx(ValueDiff, { event: ev, revealed: state.revealed[ev.id], onReveal: () => handleReveal(ev.id) })] }, ev.id));
138
+ }) }));
139
+ }
140
+ /**
141
+ * Resolve the friendly badge label for a field event op. Consumer-supplied
142
+ * overrides win; otherwise the package defaults (Added / Changed / Removed)
143
+ * apply. An explicit empty-string override falls back to the raw DB op so
144
+ * apps can opt into the legacy uppercase rendering per-op.
145
+ */
146
+ function resolveOpLabel(op, overrides) {
147
+ const override = overrides?.[op];
148
+ if (override !== undefined)
149
+ return override === '' ? op : override;
150
+ return DEFAULT_OP_LABELS[op];
151
+ }
152
+ /**
153
+ * Look up an intent label for a field event by correlation_id. `.completed`
154
+ * and `.failed` suffixes are stripped so the app's `intentLabels` map only
155
+ * needs the bare event names.
156
+ */
157
+ function resolveIntentLabel(correlation_id, intentByCorrelation, labels) {
158
+ if (!labels)
159
+ return undefined;
160
+ const intent = intentByCorrelation.get(correlation_id);
161
+ if (!intent)
162
+ return undefined;
163
+ const name = intent.event_name
164
+ .replace(/\.completed$/, '')
165
+ .replace(/\.failed$/, '');
166
+ return labels[name];
104
167
  }
105
168
  function ValueDiff({ event, revealed, onReveal, }) {
106
169
  if (event.is_sensitive && !revealed) {
@@ -1 +1 @@
1
- {"version":3,"file":"FieldAuditTrail.js","sourceRoot":"","sources":["../../src/client/FieldAuditTrail.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAQ7B;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAA2B;IACzD,MAAM,EACJ,WAAW,EACX,SAAS,EACT,SAAS,EACT,QAAQ,GAAG,YAAY,EACvB,KAAK,GAAG,EAAE,EACV,SAAS,EACT,UAAU,GACX,GAAG,KAAK,CAAC;IAEV,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAKrC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;IAEhD,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;YACjC,YAAY,EAAE,WAAW;YACzB,UAAU,EAAE,SAAS;YACrB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;SACrB,CAAC,CAAC;QACH,IAAI,SAAS;YAAE,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QACnD,KAAK,CAAC,GAAG,QAAQ,WAAW,MAAM,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;aACzE,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;YAChB,IAAI,CAAC,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACrB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAW,CAAC;YACvC,CAAC;YACD,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBACV,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YACtC,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAwB,CAAC;QACjD,CAAC,CAAC;aACD,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;YACb,IAAI,SAAS;gBAAE,OAAO;YACtB,IAAI,YAAY,IAAI,IAAI,EAAE,CAAC;gBACzB,QAAQ,CAAC;oBACP,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,EAAE;oBACV,QAAQ,EAAE,EAAE;oBACZ,KAAK,EAAE,mDAAmD;iBAC3D,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YACD,QAAQ,CAAC;gBACP,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,IAAI,CAAC,YAAY,IAAI,EAAE;gBAC/B,QAAQ,EAAE,EAAE;aACb,CAAC,CAAC;QACL,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;YACpB,IAAI,SAAS;gBAAE,OAAO;YACtB,QAAQ,CAAC;gBACP,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,EAAE;gBACV,QAAQ,EAAE,EAAE;gBACZ,KAAK,EAAE,GAAG,CAAC,OAAO;aACnB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IAEzD,KAAK,UAAU,YAAY,CAAC,EAAU;QACpC,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,WAAW,EAAE,SAAS,EAAE;gBACvD,MAAM,EAAE,MAAM;gBACd,WAAW,EAAE,SAAS;aACvB,CAAC,CAAC;YACH,IAAI,CAAC,CAAC,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YAC/C,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAmB,CAAC;YAChD,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACf,GAAG,CAAC;gBACJ,QAAQ,EAAE;oBACR,GAAG,CAAC,CAAC,QAAQ;oBACb,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE;iBAC7D;aACF,CAAC,CAAC,CAAC;YACJ,UAAU,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACf,GAAG,CAAC;gBACJ,KAAK,EAAE,kBAAkB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE;aAC1E,CAAC,CAAC,CAAC;QACN,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,CACL,cAAK,SAAS,EAAE,EAAE,CAAC,yCAAyC,EAAE,SAAS,CAAC,8BAElE,CACP,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,CACL,cAAK,SAAS,EAAE,EAAE,CAAC,yCAAyC,EAAE,SAAS,CAAC,YACrE,KAAK,CAAC,KAAK,GACR,CACP,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,CACL,cAAK,SAAS,EAAE,EAAE,CAAC,yCAAyC,EAAE,SAAS,CAAC,gCAElE,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,aAAI,SAAS,EAAE,EAAE,CAAC,mBAAmB,EAAE,SAAS,CAAC,YAC9C,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CACxB,cAEE,SAAS,EAAC,2DAA2D,aAErE,eAAK,SAAS,EAAC,qEAAqE,aAClF,2BACE,eACE,SAAS,EAAE,EAAE,CACX,2EAA2E,EAC3E,EAAE,CAAC,EAAE,KAAK,QAAQ;wCAChB,CAAC,CAAC,iCAAiC;wCACnC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,QAAQ;4CACpB,CAAC,CAAC,2BAA2B;4CAC7B,CAAC,CAAC,yBAAyB,CAC9B,YAEA,EAAE,CAAC,EAAE,GACD,EACN,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC,aAAa,IAAI,EAAE,CAAC,UAAU,IAC/C,EACP,eACE,QAAQ,EAAE,EAAE,CAAC,WAAW,EACxB,KAAK,EAAE,EAAE,CAAC,WAAW,EACrB,SAAS,EAAC,4BAA4B,YAErC,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC,GACtB,IACH,EACL,CAAC,SAAS,IAAI,CACb,cAAK,SAAS,EAAC,2DAA2D,YACvE,EAAE,CAAC,UAAU,GACV,CACP,EACD,KAAC,SAAS,IACR,KAAK,EAAE,EAAE,EACT,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,EAC/B,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC,GACnC,KApCG,EAAE,CAAC,EAAE,CAqCP,CACN,CAAC,GACC,CACN,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,EACjB,KAAK,EACL,QAAQ,EACR,QAAQ,GAKT;IACC,IAAI,KAAK,CAAC,YAAY,IAAI,CAAC,QAAQ,EAAE,CAAC;QACpC,OAAO,CACL,eAAK,SAAS,EAAC,yCAAyC,aACtD,eAAM,SAAS,EAAC,uBAAuB,2BAAkB,EACzD,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAC,4JAA4J,uBAG/J,IACL,CACP,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,EAAE,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC;IACtD,MAAM,KAAK,GAAG,QAAQ,EAAE,KAAK,IAAI,KAAK,CAAC,WAAW,CAAC;IACnD,OAAO,CACL,eAAK,SAAS,EAAC,mDAAmD,aAChE,eAAM,SAAS,EAAC,gBAAgB,uBAAc,EAC9C,eAAM,SAAS,EAAC,8CAA8C,YAC3D,WAAW,CAAC,MAAM,CAAC,GACf,EACP,eAAM,SAAS,EAAC,gBAAgB,sBAAa,EAC7C,eAAM,SAAS,EAAC,8CAA8C,YAC3D,WAAW,CAAC,KAAK,CAAC,GACd,IACH,CACP,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,CAAU;IAC7B,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,GAAG,CAAC;IAC1B,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACpC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YAAE,OAAO,GAAG,CAAC;QAC1C,OAAO,CAAC,CAAC,cAAc,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAC;IACb,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"FieldAuditTrail.js","sourceRoot":"","sources":["../../src/client/FieldAuditTrail.tsx"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState } from 'react';
4
- import { cn } from './cn.js';
4
+ import { cn } from 'hazo_ui';
5
5
  export function RevertConfirmDialog({ open, table, recordId, toTimestamp, onConfirm, onClose, className, }) {
6
6
  const [reason, setReason] = useState('');
7
7
  const [working, setWorking] = useState(false);