@endora-commerce/mod-audit-logs 0.100.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 (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +55 -0
  3. package/dist/admin/index.d.ts +34 -0
  4. package/dist/admin/index.d.ts.map +1 -0
  5. package/dist/admin/index.js +39 -0
  6. package/dist/admin/index.js.map +1 -0
  7. package/dist/admin/pages/AuditLogViewer.d.ts +3 -0
  8. package/dist/admin/pages/AuditLogViewer.d.ts.map +1 -0
  9. package/dist/admin/pages/AuditLogViewer.js +112 -0
  10. package/dist/admin/pages/AuditLogViewer.js.map +1 -0
  11. package/dist/backend/cli/read.d.ts +20 -0
  12. package/dist/backend/cli/read.d.ts.map +1 -0
  13. package/dist/backend/cli/read.js +94 -0
  14. package/dist/backend/cli/read.js.map +1 -0
  15. package/dist/backend/commands/recent-activity-visibility.commands.d.ts +31 -0
  16. package/dist/backend/commands/recent-activity-visibility.commands.d.ts.map +1 -0
  17. package/dist/backend/commands/recent-activity-visibility.commands.js +55 -0
  18. package/dist/backend/commands/recent-activity-visibility.commands.js.map +1 -0
  19. package/dist/backend/index.d.ts +91 -0
  20. package/dist/backend/index.d.ts.map +1 -0
  21. package/dist/backend/index.js +117 -0
  22. package/dist/backend/index.js.map +1 -0
  23. package/dist/backend/routes.admin.d.ts +29 -0
  24. package/dist/backend/routes.admin.d.ts.map +1 -0
  25. package/dist/backend/routes.admin.js +85 -0
  26. package/dist/backend/routes.admin.js.map +1 -0
  27. package/dist/backend/routes.admin.recent-activity.d.ts +126 -0
  28. package/dist/backend/routes.admin.recent-activity.d.ts.map +1 -0
  29. package/dist/backend/routes.admin.recent-activity.js +106 -0
  30. package/dist/backend/routes.admin.recent-activity.js.map +1 -0
  31. package/dist/backend/services/audit-reference-registry.d.ts +28 -0
  32. package/dist/backend/services/audit-reference-registry.d.ts.map +1 -0
  33. package/dist/backend/services/audit-reference-registry.js +57 -0
  34. package/dist/backend/services/audit-reference-registry.js.map +1 -0
  35. package/dist/backend/services/recent-activity-catalog.d.ts +92 -0
  36. package/dist/backend/services/recent-activity-catalog.d.ts.map +1 -0
  37. package/dist/backend/services/recent-activity-catalog.js +82 -0
  38. package/dist/backend/services/recent-activity-catalog.js.map +1 -0
  39. package/dist/backend/services/recent-activity-service.d.ts +105 -0
  40. package/dist/backend/services/recent-activity-service.d.ts.map +1 -0
  41. package/dist/backend/services/recent-activity-service.js +308 -0
  42. package/dist/backend/services/recent-activity-service.js.map +1 -0
  43. package/dist/backend/services/recent-activity-visibility.d.ts +37 -0
  44. package/dist/backend/services/recent-activity-visibility.d.ts.map +1 -0
  45. package/dist/backend/services/recent-activity-visibility.js +81 -0
  46. package/dist/backend/services/recent-activity-visibility.js.map +1 -0
  47. package/dist/manifest.d.ts +191 -0
  48. package/dist/manifest.d.ts.map +1 -0
  49. package/dist/manifest.js +123 -0
  50. package/dist/manifest.js.map +1 -0
  51. package/docs/audit_logs.md +47 -0
  52. package/i18n/en.json +5 -0
  53. package/i18n/pl.json +5 -0
  54. package/package.json +86 -0
  55. package/tailwind.css +14 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Endora sp. z o.o. and the Endora Commerce contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,55 @@
1
+ <!-- Generated by `pnpm --filter backend run manifests:generate`. Delete this line to take the file over; a README without it is never regenerated. -->
2
+
3
+ # @endora-commerce/mod-audit-logs
4
+
5
+ Append-only audit log for sensitive admin and customer actions.
6
+
7
+ ## What this is
8
+
9
+ An **Endora Commerce module package**. Its module id is `audit_logs` — the identity of record in the platform's registries, in its migrations and in its setting, permission and translation codes.
10
+
11
+ A module is not imported by application code. The platform discovers the extension packages an instance has installed, reads the manifest on the root subpath and composes the module from it, so installing this package and starting the instance is the whole integration.
12
+
13
+ ## Entry points
14
+
15
+ | Import | Contents |
16
+ | --- | --- |
17
+ | `@endora-commerce/mod-audit-logs` | the module manifest — its id, version, dependencies, settings and activation |
18
+ | `@endora-commerce/mod-audit-logs/admin` | the Admin UI contribution: the screens, navigation and palette actions it adds |
19
+ | `@endora-commerce/mod-audit-logs/backend` | the composition root the platform calls, with the entities, services, routes and workers it registers |
20
+ | `@endora-commerce/mod-audit-logs/tailwind.css` | the Tailwind source declaration for the admin code above |
21
+
22
+ ## Depends on
23
+
24
+ Everything below is a **peer** dependency, so the application resolves exactly one copy of each — two copies of a host or of React are a runtime failure rather than a type error. An entry marked *optional* is needed only by the layers that use it.
25
+
26
+ **Endora packages**
27
+
28
+ - `@endora-commerce/admin-kit` — *optional*
29
+ - `@endora-commerce/contracts`
30
+ - `@endora-commerce/platform`
31
+
32
+ **Third-party**
33
+
34
+ - `@mikro-orm/postgresql` ^6
35
+ - `fastify` ^5
36
+ - `react` ^19 — *optional*
37
+ - `react-router-dom` ^7 — *optional*
38
+ - `zod` ^4
39
+
40
+ ## What the tarball carries
41
+
42
+ - `dist/` — the compiled JavaScript and its type declarations
43
+ - `i18n/` — the translation bundles this package ships (`en`, `pl`), loaded by the platform
44
+ - `docs/` — the package’s own pages in the Endora Commerce documentation site
45
+ - `tailwind.css` — the Tailwind source declaration
46
+
47
+ ## Install
48
+
49
+ ```bash
50
+ pnpm add @endora-commerce/mod-audit-logs
51
+ ```
52
+
53
+ ## Licence
54
+
55
+ MIT — the text is in `LICENSE`, beside this file.
@@ -0,0 +1,34 @@
1
+ /**
2
+ * `audit_logs`' admin surface — one route and one sidebar entry, declared by
3
+ * the module that owns them (feature 091, Phase 4, batch four;
4
+ * `specs/091-module-owned-admin-surfaces/contracts/admin-contribution.md`).
5
+ *
6
+ * **The locked-with-nav shape, and the module batch one rejected by name.**
7
+ * `plan.md`'s Ruling 2 retires the ground: `specs/deferred-defects.md` scopes
8
+ * Constitution XVII item 6 to the modules that declare an
9
+ * `activation.settingCode` *without* `nonDeactivatable`, so a locked module is
10
+ * outside that population by the owner's own measurement rather than by an
11
+ * exception anyone grants. Its off-state test asserts the axis it has — the
12
+ * permission one, which `useSurfaceVisibility` gates identically — and asserts
13
+ * the missing axis as a fact about the module read from the manifest, which is
14
+ * a stronger statement than a skipped file.
15
+ *
16
+ * **`audit_log:read` is the code, singular, and it is read from the route.**
17
+ * `GET /api/v1/admin/audit-log` enforces it
18
+ * (`packages/modules/audit_logs/src/backend/routes.admin.ts`). The module's
19
+ * other admin routes — the dashboard's recent-activity feed and the two
20
+ * module-activation endpoints under
21
+ * `routes.admin.recent-activity.ts` — are not this screen's, and two of them
22
+ * enforce `platform.modules.activate`, so copying the neighbourhood would have
23
+ * gated the viewer on a code that has nothing to do with reading an audit
24
+ * trail.
25
+ *
26
+ * **This entry exports data and nothing else** (R2), like every `./admin`
27
+ * layer: `check:module-boundary`'s D-171 rule designates a subpath as contract
28
+ * surface when it emits no runtime binding, and `./admin` deliberately does not
29
+ * qualify, so a consumer reaching into another module's `./admin` stays a
30
+ * counted boundary reach.
31
+ */
32
+ import type { AdminContributions } from '@endora-commerce/admin-kit/contributions';
33
+ export declare const contributions: AdminContributions;
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAKnF,eAAO,MAAM,aAAa,EAAE,kBAmC3B,CAAC"}
@@ -0,0 +1,39 @@
1
+ /** The module's only admin route: the append-only audit-log viewer. */
2
+ const ROUTE_PATH = '/audit-log';
3
+ export const contributions = {
4
+ routes: [
5
+ {
6
+ path: ROUTE_PATH,
7
+ component: () => import('./pages/AuditLogViewer.js'),
8
+ requiredPermission: 'audit_log:read',
9
+ index: true,
10
+ },
11
+ ],
12
+ nav: [
13
+ {
14
+ to: ROUTE_PATH,
15
+ // Module-relative (R8), resolved in this module's own namespace out of
16
+ // `packages/modules/audit_logs/i18n/`. It was `appShell.nav.auditLog` in
17
+ // the shared `_i18n` bundle, one of the four shared files a module author
18
+ // had to edit.
19
+ labelKey: 'nav.auditLog.label',
20
+ // The icon the hand-written NAV entry carried.
21
+ icon: 'ListChecks',
22
+ section: 'system',
23
+ // **The *System* section still holds host-declared entries**, unlike the
24
+ // *Analytics & Ads* section batch three emptied, so this weight orders
25
+ // the entry only against the other converted modules — the host block
26
+ // renders first whatever any weight says, and that is the batch's one
27
+ // operator-visible change. The scale is the hand-written table's own
28
+ // position times a hundred, so the three entries this batch converts keep
29
+ // the relative order they had (`/admin-users` 200, `/admin-roles` 300,
30
+ // `/audit-log` 600) and the eight System entries still to convert have a
31
+ // slot each waiting for them.
32
+ weight: 600,
33
+ // The code that opens the screen: the sidebar advertises a destination,
34
+ // so it gates on what the landing route enforces.
35
+ requiredPermission: 'audit_log:read',
36
+ },
37
+ ],
38
+ };
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAiCA,uEAAuE;AACvE,MAAM,UAAU,GAAG,YAAY,CAAC;AAEhC,MAAM,CAAC,MAAM,aAAa,GAAuB;IAC/C,MAAM,EAAE;QACN;YACE,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,2BAA2B,CAAC;YACpD,kBAAkB,EAAE,gBAAgB;YACpC,KAAK,EAAE,IAAI;SACZ;KACF;IACD,GAAG,EAAE;QACH;YACE,EAAE,EAAE,UAAU;YACd,uEAAuE;YACvE,yEAAyE;YACzE,0EAA0E;YAC1E,eAAe;YACf,QAAQ,EAAE,oBAAoB;YAC9B,+CAA+C;YAC/C,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,QAAQ;YACjB,yEAAyE;YACzE,uEAAuE;YACvE,sEAAsE;YACtE,sEAAsE;YACtE,qEAAqE;YACrE,0EAA0E;YAC1E,uEAAuE;YACvE,yEAAyE;YACzE,8BAA8B;YAC9B,MAAM,EAAE,GAAG;YACX,wEAAwE;YACxE,kDAAkD;YAClD,kBAAkB,EAAE,gBAAgB;SACrC;KACF;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type ReactNode } from 'react';
2
+ export default function AuditLogViewer(): ReactNode;
3
+ //# sourceMappingURL=AuditLogViewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuditLogViewer.d.ts","sourceRoot":"","sources":["../../../src/admin/pages/AuditLogViewer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA8D,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAiDnG,MAAM,CAAC,OAAO,UAAU,cAAc,IAAI,SAAS,CA8MlD"}
@@ -0,0 +1,112 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Fragment, useCallback, useEffect, useState } from 'react';
3
+ import { Link } from 'react-router-dom';
4
+ import { ApiError, apiClient, formatDateTime } from '@endora-commerce/admin-kit/lib';
5
+ import { Alert, AlertDescription, Button, Card, CardContent, Input, Label, PageHeader, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@endora-commerce/admin-kit/ui';
6
+ import { AdminUserPicker, CustomerPicker } from '@endora-commerce/admin-kit/components';
7
+ import { useTranslation, useTranslationContext } from '@endora-commerce/admin-kit/i18n';
8
+ export default function AuditLogViewer() {
9
+ const t = useTranslation('core');
10
+ const { t: translate } = useTranslationContext();
11
+ const [rows, setRows] = useState([]);
12
+ const [loading, setLoading] = useState(true);
13
+ const [error, setError] = useState(null);
14
+ const [actor, setActor] = useState('');
15
+ const [action, setAction] = useState('');
16
+ const [objectType, setObjectType] = useState('');
17
+ const [objectId, setObjectId] = useState('');
18
+ const [impersonated, setImpersonated] = useState('');
19
+ const [expandedId, setExpandedId] = useState(null);
20
+ const refresh = useCallback(async () => {
21
+ setLoading(true);
22
+ setError(null);
23
+ try {
24
+ const params = new URLSearchParams();
25
+ if (actor)
26
+ params.set('filter[actor]', actor);
27
+ if (action)
28
+ params.set('filter[action]', action);
29
+ if (objectType)
30
+ params.set('filter[objectType]', objectType);
31
+ if (objectId)
32
+ params.set('filter[objectId]', objectId);
33
+ if (impersonated)
34
+ params.set('filter[customer]', impersonated);
35
+ const path = '/api/v1/admin/audit-log' + (params.toString() ? `?${params.toString()}` : '');
36
+ const res = await apiClient.get(path);
37
+ setRows(res.data);
38
+ }
39
+ catch (err) {
40
+ setError(err instanceof ApiError ? err.envelope.error.message : t('auditLog.error.load'));
41
+ }
42
+ finally {
43
+ setLoading(false);
44
+ }
45
+ }, [actor, action, objectType, objectId, impersonated]);
46
+ useEffect(() => {
47
+ void refresh();
48
+ }, [refresh]);
49
+ return (_jsxs(_Fragment, { children: [_jsx(PageHeader, { title: t('auditLog.page.title'), description: t('auditLog.page.description') }), error ? (_jsx(Alert, { variant: "destructive", className: "mb-4", children: _jsx(AlertDescription, { children: error }) })) : null, _jsx(Card, { className: "mb-4", children: _jsx(CardContent, { className: "pt-6", children: _jsxs("form", { onSubmit: (e) => {
50
+ e.preventDefault();
51
+ void refresh();
52
+ }, className: "space-y-4", children: [_jsxs("div", { className: "grid gap-4 md:grid-cols-3", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "f-action", children: t('auditLog.filter.action') }), _jsx(Input, { id: "f-action", placeholder: "product.update", value: action, onChange: (e) => setAction(e.target.value.trim()) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "f-otype", children: t('auditLog.filter.objectType') }), _jsx(Input, { id: "f-otype", placeholder: "product", value: objectType, onChange: (e) => setObjectType(e.target.value.trim()) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "f-oid", children: t('auditLog.filter.objectId') }), _jsx(Input, { id: "f-oid", placeholder: "UUID", value: objectId, onChange: (e) => setObjectId(e.target.value.trim()) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "f-actor", children: t('auditLog.filter.actor') }), _jsx(AdminUserPicker, { id: "f-actor", value: actor || null, onChange: (v) => setActor(v ?? '') })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "f-customer", children: t('auditLog.filter.impersonatedCustomer') }), _jsx(CustomerPicker, { id: "f-customer", value: impersonated || null, onChange: (v) => setImpersonated(v ?? '') })] })] }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { type: "submit", children: t('auditLog.filter.apply') }), _jsx(Button, { type: "button", variant: "outline", onClick: () => {
53
+ setActor('');
54
+ setAction('');
55
+ setObjectType('');
56
+ setObjectId('');
57
+ setImpersonated('');
58
+ }, children: t('auditLog.filter.clear') })] })] }) }) }), _jsx(Card, { children: _jsx(CardContent, { className: "pt-6", children: loading ? (_jsx("p", { className: "text-sm text-muted-foreground", children: t('common.state.loading') })) : rows.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: t('auditLog.empty') })) : (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: t('auditLog.column.when') }), _jsx(TableHead, { children: t('auditLog.column.actor') }), _jsx(TableHead, { children: t('auditLog.column.action') }), _jsx(TableHead, { children: t('auditLog.column.object') }), _jsx(TableHead, {})] }) }), _jsx(TableBody, { children: rows.map((r) => (_jsxs(Fragment, { children: [_jsxs(TableRow, { children: [_jsx(TableCell, { children: formatDateTime(r.actedAt) }), _jsx(TableCell, { children: _jsx(ActorCell, { row: r }) }), _jsx(TableCell, { children: translateAuditAction(translate, r) }), _jsxs(TableCell, { children: [r.objectType, _jsx("br", {}), _jsx(ObjectIdCell, { objectType: r.objectType, objectId: r.objectId })] }), _jsx(TableCell, { children: _jsx(Button, { variant: "outline", size: "sm", onClick: () => setExpandedId(expandedId === r.id ? null : r.id), children: expandedId === r.id ? t('auditLog.action.hide') : t('auditLog.action.detail') }) })] }), expandedId === r.id ? (_jsx(TableRow, { children: _jsxs(TableCell, { colSpan: 5, children: [_jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [_jsxs("div", { children: [_jsx("strong", { children: t('auditLog.detail.before') }), _jsx("pre", { className: "mt-1 max-h-80 overflow-auto rounded-md bg-muted p-3 text-xs", children: JSON.stringify(r.stateBefore ?? null, null, 2) })] }), _jsxs("div", { children: [_jsx("strong", { children: t('auditLog.detail.after') }), _jsx("pre", { className: "mt-1 max-h-80 overflow-auto rounded-md bg-muted p-3 text-xs", children: JSON.stringify(r.stateAfter ?? null, null, 2) })] })] }), _jsxs("div", { className: "mt-2 text-xs text-muted-foreground", children: [t('auditLog.detail.ip'), " ", r.ipAddress ?? '—', " \u00B7 ", t('auditLog.detail.userAgent'), ' ', r.userAgent ? r.userAgent.slice(0, 60) : '—', " \u00B7 ", t('auditLog.detail.request'), ' ', r.requestId ?? '—', r.impersonatedCustomerAccountId ? (_jsxs(_Fragment, { children: [' ', "\u00B7 ", t('auditLog.detail.impersonatedCustomer'), ' ', r.impersonatedCustomerAccountId.slice(0, 8)] })) : null] })] }) })) : null] }, r.id))) })] })) }) })] }));
59
+ }
60
+ /**
61
+ * Maps an audit-log `objectType` to its admin detail route, when one exists.
62
+ * Only id-addressable detail pages are listed — object types without a
63
+ * standalone page (or whose route keys on a code/slug rather than the audit
64
+ * `objectId`) are intentionally omitted so we never produce a broken link.
65
+ */
66
+ const OBJECT_ROUTE = {
67
+ product: (id) => `/catalog/products/${id}`,
68
+ order: (id) => `/orders/${id}`,
69
+ organization: (id) => `/organizations/${id}`,
70
+ customer_account: (id) => `/customers/${id}`,
71
+ price_list: (id) => `/price-lists/${id}`,
72
+ warehouse: (id) => `/warehouses/${id}`,
73
+ cart: (id) => `/carts/${id}`,
74
+ bulk_operation: (id) => `/catalog/bulk-operations/${id}`,
75
+ admin_user: (id) => `/admin-users#admin-user-${id}`,
76
+ };
77
+ /**
78
+ * Renders the object id, linked to the object's admin detail page when its
79
+ * type has one; otherwise a plain truncated id.
80
+ */
81
+ function ObjectIdCell({ objectType, objectId, }) {
82
+ const build = OBJECT_ROUTE[objectType];
83
+ const short = objectId.slice(0, 8);
84
+ if (!build) {
85
+ return _jsx("span", { className: "text-xs text-muted-foreground", children: short });
86
+ }
87
+ return (_jsx(Link, { to: build(objectId), className: "text-xs text-muted-foreground underline underline-offset-2", title: objectId, children: short }));
88
+ }
89
+ /**
90
+ * Renders the actor column: an admin user's name + email (linked to the
91
+ * users admin page) when resolvable, the bare id as a fallback, or the
92
+ * "system" label when there is no actor.
93
+ */
94
+ function ActorCell({ row }) {
95
+ const t = useTranslation('core');
96
+ if (!row.actorAdminUserId) {
97
+ return _jsx("span", { className: "text-muted-foreground", children: t('auditLog.actor.system') });
98
+ }
99
+ const name = row.actorName?.trim();
100
+ if (!name) {
101
+ // Unknown / deleted admin user — keep the id so the row is still traceable.
102
+ return _jsx("span", { className: "font-mono text-xs", children: row.actorAdminUserId.slice(0, 8) });
103
+ }
104
+ return (_jsxs(Link, { to: `/admin-users#admin-user-${row.actorAdminUserId}`, className: "underline underline-offset-2", children: [name, row.actorEmail ? (_jsxs("span", { className: "text-muted-foreground", children: [" (", row.actorEmail, ")"] })) : null] }));
105
+ }
106
+ function translateAuditAction(translate, row) {
107
+ const moduleId = row.actionModuleId ?? 'core';
108
+ const key = `auditLog.${row.action}`;
109
+ const label = translate(moduleId, key);
110
+ return label === `${moduleId}.${key}` ? row.action : label;
111
+ }
112
+ //# sourceMappingURL=AuditLogViewer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuditLogViewer.js","sourceRoot":"","sources":["../../../src/admin/pages/AuditLogViewer.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ import type { ModuleCliCommandContext } from '@endora-commerce/contracts';
3
+ import { AuditLogEntry } from '@endora-commerce/platform/kernel';
4
+ import type { ModuleContext } from '@endora-commerce/platform/kernel';
5
+ declare const ArgsSchema: z.ZodObject<{
6
+ actor: z.ZodOptional<z.ZodString>;
7
+ action: z.ZodOptional<z.ZodString>;
8
+ objectType: z.ZodOptional<z.ZodString>;
9
+ objectId: z.ZodOptional<z.ZodString>;
10
+ limit: z.ZodDefault<z.ZodNumber>;
11
+ json: z.ZodDefault<z.ZodBoolean>;
12
+ }, z.core.$strip>;
13
+ type Args = z.infer<typeof ArgsSchema>;
14
+ export declare function parseArgv(argv: readonly string[]): Args | {
15
+ error: string;
16
+ };
17
+ export declare function formatTable(rows: readonly AuditLogEntry[]): string;
18
+ export declare function read({ ctx, argv, out, err, }: ModuleCliCommandContext<ModuleContext>): Promise<number>;
19
+ export {};
20
+ //# sourceMappingURL=read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/backend/cli/read.ts"],"names":[],"mappings":"AAqDA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAYtE,QAAA,MAAM,UAAU;;;;;;;iBAOd,CAAC;AAEH,KAAK,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AASvC,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CA2B3E;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAuBlE;AAOD,wBAAsB,IAAI,CAAC,EACzB,GAAG,EACH,IAAI,EACJ,GAAG,EACH,GAAG,GACJ,EAAE,uBAAuB,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAsB1D"}
@@ -0,0 +1,94 @@
1
+ import { z } from 'zod';
2
+ import { AuditLogEntry } from '@endora-commerce/platform/kernel';
3
+ /**
4
+ * The full `--help` text is the command's `help` declaration in `manifest.ts`,
5
+ * printed by the host before it composes (D-102 — the credential is host
6
+ * access, not a working connection string). This is the one line the error path
7
+ * needs, so a refused argument still says where to look.
8
+ */
9
+ const USAGE_LINE = 'usage: audit_logs read [--actor] [--action] [--object-type] [--object-id] ' +
10
+ '[--limit] [--json] — run with --help for the filters';
11
+ const ArgsSchema = z.object({
12
+ actor: z.string().uuid().optional(),
13
+ action: z.string().min(1).optional(),
14
+ objectType: z.string().min(1).optional(),
15
+ objectId: z.string().min(1).optional(),
16
+ limit: z.number().int().min(1).max(500).default(100),
17
+ json: z.boolean().default(false),
18
+ });
19
+ const FLAGS = {
20
+ '--actor': 'actor',
21
+ '--action': 'action',
22
+ '--object-type': 'objectType',
23
+ '--object-id': 'objectId',
24
+ };
25
+ export function parseArgv(argv) {
26
+ const candidate = {};
27
+ for (const arg of argv) {
28
+ if (arg === '--json') {
29
+ candidate['json'] = true;
30
+ continue;
31
+ }
32
+ const eq = arg.indexOf('=');
33
+ const [flag, value] = eq === -1 ? [arg, undefined] : [arg.slice(0, eq), arg.slice(eq + 1)];
34
+ const key = FLAGS[flag];
35
+ if (key !== undefined) {
36
+ if (value === undefined)
37
+ return { error: `${flag} needs a value` };
38
+ candidate[key] = value;
39
+ continue;
40
+ }
41
+ if (flag === '--limit') {
42
+ if (value === undefined)
43
+ return { error: '--limit needs a value' };
44
+ candidate['limit'] = Number.parseInt(value, 10);
45
+ continue;
46
+ }
47
+ return { error: `unknown argument: ${arg}` };
48
+ }
49
+ const parsed = ArgsSchema.safeParse(candidate);
50
+ if (!parsed.success) {
51
+ return { error: parsed.error.issues.map((issue) => issue.message).join('; ') };
52
+ }
53
+ return parsed.data;
54
+ }
55
+ export function formatTable(rows) {
56
+ if (rows.length === 0)
57
+ return '(no entries match)';
58
+ const width = (pick, header) => Math.max(header.length, ...rows.map((row) => pick(row).length));
59
+ const actor = (row) => row.actorAdminUserId ?? '—';
60
+ const object = (row) => `${row.objectType}/${row.objectId}`;
61
+ const widths = {
62
+ at: 24,
63
+ actor: width(actor, 'ACTOR'),
64
+ action: width((row) => row.action, 'ACTION'),
65
+ object: width(object, 'OBJECT'),
66
+ };
67
+ const pad = (value, to) => value.padEnd(to);
68
+ const lines = [
69
+ `${pad('ACTED AT', widths.at)} ${pad('ACTOR', widths.actor)} ` +
70
+ `${pad('ACTION', widths.action)} ${pad('OBJECT', widths.object)}`,
71
+ ...rows.map((row) => `${pad(row.actedAt.toISOString(), widths.at)} ${pad(actor(row), widths.actor)} ` +
72
+ `${pad(row.action, widths.action)} ${pad(object(row), widths.object)}`),
73
+ ];
74
+ return lines.join('\n');
75
+ }
76
+ export async function read({ ctx, argv, out, err, }) {
77
+ const parsed = parseArgv(argv);
78
+ if ('error' in parsed) {
79
+ err(`${USAGE_LINE}\n\nerror: ${parsed.error}`);
80
+ return 1;
81
+ }
82
+ const em = ctx.cradle().emFactory();
83
+ // A read, and only a read: no `em.create`, no `persist`, no `flush`. The
84
+ // trail is append-only and the Command Bus is its one writer.
85
+ const rows = await em.find(AuditLogEntry, {
86
+ ...(parsed.actor ? { actorAdminUserId: parsed.actor } : {}),
87
+ ...(parsed.action ? { action: parsed.action } : {}),
88
+ ...(parsed.objectType ? { objectType: parsed.objectType } : {}),
89
+ ...(parsed.objectId ? { objectId: parsed.objectId } : {}),
90
+ }, { orderBy: { actedAt: 'desc' }, limit: parsed.limit });
91
+ out(parsed.json ? JSON.stringify(rows, null, 2) : formatTable(rows));
92
+ return 0;
93
+ }
94
+ //# sourceMappingURL=read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.js","sourceRoot":"","sources":["../../../src/backend/cli/read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { Command } from '@endora-commerce/platform/commands';
2
+ import type { RecentActivityCatalog } from '../services/recent-activity-catalog.js';
3
+ /**
4
+ * The operator's dashboard-visibility flip — feature 080, T042j / D-163.1,
5
+ * Constitution XIII.
6
+ *
7
+ * A Command rather than a settings write for the reason the activation flip is
8
+ * one (`_lifecycle/commands/activation.commands.ts`): there is no `setting.*`
9
+ * Command to reuse, and `SettingsAdminService.setValue` audits by hand after
10
+ * `em.flush()` and outside any transaction. The Setting is `hidden`, so it does
11
+ * not render on the generic Settings screen at all — this is its only door, the
12
+ * same asymmetry activation has.
13
+ *
14
+ * The refusal is taken **before** the Command opens a transaction, and it is a
15
+ * refusal rather than a no-op: a control that silently does nothing is worse
16
+ * than an absent one, because the operator believes they switched something.
17
+ */
18
+ export interface SetRecentActivityVisibilityInput {
19
+ moduleId: string;
20
+ visible: boolean;
21
+ }
22
+ /**
23
+ * Refuse a module that declares no eligibility, naming the difference between
24
+ * the two axes so the message is actionable.
25
+ */
26
+ export declare function assertRecentActivityVisibilityWritable(catalog: RecentActivityCatalog, moduleId: string): string;
27
+ export declare function makeSetRecentActivityVisibilityCommand(catalog: RecentActivityCatalog, input: SetRecentActivityVisibilityInput): Command<{
28
+ moduleId: string;
29
+ visible: boolean;
30
+ }>;
31
+ //# sourceMappingURL=recent-activity-visibility.commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recent-activity-visibility.commands.d.ts","sourceRoot":"","sources":["../../../src/backend/commands/recent-activity-visibility.commands.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAGlE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAEpF;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,sCAAsC,CACpD,OAAO,EAAE,qBAAqB,EAC9B,QAAQ,EAAE,MAAM,GACf,MAAM,CAYR;AAED,wBAAgB,sCAAsC,CACpD,OAAO,EAAE,qBAAqB,EAC9B,KAAK,EAAE,gCAAgC,GACtC,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA0CjD"}
@@ -0,0 +1,55 @@
1
+ import { ERROR_CODES } from '@endora-commerce/contracts';
2
+ import { HttpError } from '@endora-commerce/platform/http';
3
+ import { Setting } from '@endora-commerce/platform/kernel';
4
+ /**
5
+ * Refuse a module that declares no eligibility, naming the difference between
6
+ * the two axes so the message is actionable.
7
+ */
8
+ export function assertRecentActivityVisibilityWritable(catalog, moduleId) {
9
+ const entry = catalog.eligibleModules().find((m) => m.moduleId === moduleId);
10
+ if (!entry) {
11
+ throw new HttpError(404, ERROR_CODES.MODULE_NOT_FOUND, `Module "${moduleId}" declares no recent-activity eligibility, so it contributes ` +
12
+ `nothing to the dashboard card and there is nothing to show or hide. Eligibility is ` +
13
+ `the module author's declaration; only what to do with it is yours.`);
14
+ }
15
+ return entry.settingCode;
16
+ }
17
+ export function makeSetRecentActivityVisibilityCommand(catalog, input) {
18
+ const settingCode = assertRecentActivityVisibilityWritable(catalog, input.moduleId);
19
+ return {
20
+ action: 'module.recent_activity_visibility.set',
21
+ objectType: 'module',
22
+ objectId: input.moduleId,
23
+ capture: async ({ em }) => {
24
+ const setting = await em.findOne(Setting, { code: settingCode });
25
+ const stored = setting?.globalValue ?? setting?.defaultValue;
26
+ return {
27
+ moduleId: input.moduleId,
28
+ settingCode,
29
+ // The **resolved** answer, not the raw jsonb: `global_value` is `null`
30
+ // both for "the operator never chose" and for a literal JSON null, so
31
+ // recording it would leave two consecutive audit rows unable to say
32
+ // what the module's visibility actually was at either moment. The same
33
+ // reasoning the activation command records for itself.
34
+ visible: typeof stored === 'boolean' ? stored : true,
35
+ };
36
+ },
37
+ run: async ({ em }) => {
38
+ const setting = await em.findOne(Setting, { code: settingCode });
39
+ if (!setting) {
40
+ // The row is reconciled from the derived settings manifest — at boot
41
+ // for a module this build ships, by `install` for a package. Its
42
+ // absence is a platform state, not an operator error.
43
+ throw new HttpError(500, ERROR_CODES.SETTING_NOT_REGISTERED, `Module "${input.moduleId}" is eligible for the dashboard card, but its ` +
44
+ `visibility setting "${settingCode}" is not registered.`);
45
+ }
46
+ setting.globalValue = input.visible;
47
+ await em.flush();
48
+ return {
49
+ result: { moduleId: input.moduleId, visible: input.visible },
50
+ after: { moduleId: input.moduleId, settingCode, visible: input.visible },
51
+ };
52
+ },
53
+ };
54
+ }
55
+ //# sourceMappingURL=recent-activity-visibility.commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recent-activity-visibility.commands.js","sourceRoot":"","sources":["../../../src/backend/commands/recent-activity-visibility.commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEzD,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAwB3D;;;GAGG;AACH,MAAM,UAAU,sCAAsC,CACpD,OAA8B,EAC9B,QAAgB;IAEhB,MAAM,KAAK,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;IAC7E,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,SAAS,CACjB,GAAG,EACH,WAAW,CAAC,gBAAgB,EAC5B,WAAW,QAAQ,+DAA+D;YAChF,qFAAqF;YACrF,oEAAoE,CACvE,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,WAAW,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,sCAAsC,CACpD,OAA8B,EAC9B,KAAuC;IAEvC,MAAM,WAAW,GAAG,sCAAsC,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEpF,OAAO;QACL,MAAM,EAAE,uCAAuC;QAC/C,UAAU,EAAE,QAAQ;QACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;YACxB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;YACjE,MAAM,MAAM,GAAG,OAAO,EAAE,WAAW,IAAI,OAAO,EAAE,YAAY,CAAC;YAC7D,OAAO;gBACL,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,WAAW;gBACX,uEAAuE;gBACvE,sEAAsE;gBACtE,oEAAoE;gBACpE,uEAAuE;gBACvE,uDAAuD;gBACvD,OAAO,EAAE,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;aACrD,CAAC;QACJ,CAAC;QACD,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;YACpB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;YACjE,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,qEAAqE;gBACrE,iEAAiE;gBACjE,sDAAsD;gBACtD,MAAM,IAAI,SAAS,CACjB,GAAG,EACH,WAAW,CAAC,sBAAsB,EAClC,WAAW,KAAK,CAAC,QAAQ,gDAAgD;oBACvE,uBAAuB,WAAW,sBAAsB,CAC3D,CAAC;YACJ,CAAC;YACD,OAAO,CAAC,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC;YACpC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;YACjB,OAAO;gBACL,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;gBAC5D,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;aACzE,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,91 @@
1
+ import type { AuditReferenceRegistryPort } from '@endora-commerce/contracts';
2
+ import type { EntityManager } from '@mikro-orm/postgresql';
3
+ import type { CommandBus } from '@endora-commerce/platform/commands';
4
+ import type { AuditPort } from '@endora-commerce/platform/kernel';
5
+ import type { ModuleContext } from '@endora-commerce/platform/kernel';
6
+ import type { RequireAdminFactory } from '@endora-commerce/platform/kernel';
7
+ import type { AuditActorIdentity } from './routes.admin.js';
8
+ import { RecentActivityCatalog, type RecentActivityDeclarationSource } from './services/recent-activity-catalog.js';
9
+ import { RecentActivityService } from './services/recent-activity-service.js';
10
+ import { RecentActivityVisibility } from './services/recent-activity-visibility.js';
11
+ /**
12
+ * `audit_logs` — the compliance surface that was a passenger (feature 072,
13
+ * wave 1, T084).
14
+ *
15
+ * The module owned two route files and a service and registered none of them.
16
+ * `admin_users/plugin.ts` imported both route modules, constructed
17
+ * `RecentActivityService` itself and mounted the lot inside its own plugin, so
18
+ * the audit log existed for exactly as long as the admin-users module happened
19
+ * to be composed. Its service and entity moved to the kernel in T016 —
20
+ * `AuditPort` is what every module writes through — and what is left here
21
+ * is the *reading* half, which is this module's own.
22
+ *
23
+ * **`auditActorResolver` is a contribution, not a dependency**, and the
24
+ * distinction is the whole design of this file. Turning a bare actor id into a
25
+ * name and an e-mail needs `admin_users`, but needing it for a *column* is not
26
+ * the same as needing it to function. So the name is owned and defaulted here,
27
+ * a composition root that ships `admin_users` overrides it, and the manifest
28
+ * declares no edge — because a `dependencies` entry would make the lifecycle
29
+ * refuse to disable `admin_users` while the audit log is on, which is precisely
30
+ * backwards.
31
+ *
32
+ * **What that buys, exactly — D-102.** The enrichment degrades and the *record*
33
+ * does not: with `admin_users` absent the audit rows still render, with raw
34
+ * actor ids in the actor column. That is a claim about this module's own
35
+ * handler and it stops there. The **route** is guarded by `requireAdmin`, whose
36
+ * permission check reads `adminUserReadPort` since feature 075 Phase C, so on a
37
+ * deployment that does not ship `admin_users` no admin-authenticated request
38
+ * reaches this handler at all. Reading the trail when the admin identity
39
+ * subsystem is itself absent needs a surface that is not an admin-authenticated
40
+ * HTTP route: `pnpm --filter backend run audit:read`, whose credential is
41
+ * access to the host rather than a session.
42
+ *
43
+ * This paragraph used to say that "an operator investigating an incident wants
44
+ * the record more, not less, when part of the platform is off". The sentiment
45
+ * is right and the module could not deliver it over HTTP; the withdrawal is
46
+ * recorded rather than quietly narrowed, because the interesting content of
47
+ * that sentence was the part that turned out to be false.
48
+ *
49
+ * The root registers a **gated** resolver, since deciding what "`admin_users`
50
+ * is present" means is a composition-root question, not one this module should
51
+ * answer by hard-coding another module's id. When `admin_users` converts it
52
+ * publishes the resolver itself and the root's entry disappears.
53
+ */
54
+ export interface AuditLogsCradle {
55
+ readonly emFactory: () => EntityManager;
56
+ readonly auditLogService: AuditPort;
57
+ readonly requireAdmin: RequireAdminFactory;
58
+ readonly auditActorResolver: ((ids: string[]) => Promise<AuditActorIdentity[]>) | undefined;
59
+ readonly auditReferenceRegistry: AuditReferenceRegistryPort;
60
+ readonly recentActivityService: RecentActivityService;
61
+ readonly recentActivityCatalog: RecentActivityCatalog;
62
+ readonly recentActivityVisibility: RecentActivityVisibility;
63
+ /**
64
+ * Which modules this composition ships, and what each declares — a
65
+ * composition-root input by nature and therefore a platform-owned container
66
+ * name, never a port (Constitution I: a module may not decide which modules a
67
+ * deployment has). It is the input the four retired action tables are derived
68
+ * from, and reading it here rather than importing `_lifecycle`'s registry is
69
+ * what keeps the derivation free of a cross-module reach.
70
+ */
71
+ readonly resolvedModuleRegistry: ReadonlyArray<RecentActivityDeclarationSource>;
72
+ /** Absent in a composition with no Command Bus; the card still reads. */
73
+ readonly commandBus: CommandBus | undefined;
74
+ }
75
+ export declare function registerModule(ctx: ModuleContext): void;
76
+ /**
77
+ * This module owns **no persisted entity**, and says so with an empty array
78
+ * rather than by omission (D-168).
79
+ *
80
+ * The two are not the same thing to the platform. When the package is
81
+ * *installed*, `src/packages/package-runtime.ts` reads `exported['entities']`
82
+ * and answers a missing export with `[]` — so "this module has no table" and
83
+ * "somebody forgot the array" arrive at the host as the same silence, and the
84
+ * only symptom of the second is a query against a table nobody created. The
85
+ * declaration is what makes the first case a statement.
86
+ *
87
+ * A first entity added here goes in this array in the same merge request, and
88
+ * `test/unit/packages/module-package-entity-surface.test.ts` is what says so.
89
+ */
90
+ export declare const entities: readonly never[];
91
+ //# sourceMappingURL=index.d.ts.map