@orthacms/activity-server 0.4.3 → 0.5.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 (44) hide show
  1. package/dist/lib/activity/activity-filter.d.ts.map +1 -1
  2. package/dist/lib/activity/activity-filter.js +2 -0
  3. package/dist/lib/activity/activity.constants.d.ts +8 -3
  4. package/dist/lib/activity/activity.constants.d.ts.map +1 -1
  5. package/dist/lib/activity/activity.constants.js +9 -3
  6. package/dist/lib/activity/controllers/dead-letters.controller.d.ts +36 -0
  7. package/dist/lib/activity/controllers/dead-letters.controller.d.ts.map +1 -0
  8. package/dist/lib/activity/controllers/dead-letters.controller.js +61 -0
  9. package/dist/lib/activity/controllers/entry-activity.controller.d.ts +32 -0
  10. package/dist/lib/activity/controllers/entry-activity.controller.d.ts.map +1 -0
  11. package/dist/lib/activity/controllers/entry-activity.controller.js +69 -0
  12. package/dist/lib/activity/dto/dead-letters-query.dto.d.ts +14 -0
  13. package/dist/lib/activity/dto/dead-letters-query.dto.d.ts.map +1 -0
  14. package/dist/lib/activity/dto/dead-letters-query.dto.js +46 -0
  15. package/dist/lib/activity/dto/entry-activity-query.dto.d.ts +14 -0
  16. package/dist/lib/activity/dto/entry-activity-query.dto.d.ts.map +1 -0
  17. package/dist/lib/activity/dto/entry-activity-query.dto.js +50 -0
  18. package/dist/lib/activity/dto/list-activity-query.dto.d.ts +16 -0
  19. package/dist/lib/activity/dto/list-activity-query.dto.d.ts.map +1 -1
  20. package/dist/lib/activity/dto/list-activity-query.dto.js +38 -0
  21. package/dist/lib/activity/infrastructure/audit-event-mapping.d.ts +46 -0
  22. package/dist/lib/activity/infrastructure/audit-event-mapping.d.ts.map +1 -1
  23. package/dist/lib/activity/infrastructure/audit-event-mapping.js +515 -34
  24. package/dist/lib/activity/services/activity.service.d.ts.map +1 -1
  25. package/dist/lib/activity/services/activity.service.js +6 -0
  26. package/dist/lib/activity/types/activity-view.d.ts +18 -1
  27. package/dist/lib/activity/types/activity-view.d.ts.map +1 -1
  28. package/dist/lib/activity.module.d.ts.map +1 -1
  29. package/dist/lib/activity.module.js +12 -1
  30. package/dist/lib/docs/activity-schemas.d.ts +19 -0
  31. package/dist/lib/docs/activity-schemas.d.ts.map +1 -0
  32. package/dist/lib/docs/activity-schemas.js +167 -0
  33. package/dist/lib/docs/describe-activity-api.d.ts +17 -0
  34. package/dist/lib/docs/describe-activity-api.d.ts.map +1 -0
  35. package/dist/lib/docs/describe-activity-api.js +85 -0
  36. package/dist/lib/schema/activity-events.d.ts +56 -2
  37. package/dist/lib/schema/activity-events.d.ts.map +1 -1
  38. package/dist/lib/schema/activity-events.js +26 -3
  39. package/dist/lib/utils/activity-plugin.d.ts.map +1 -1
  40. package/dist/lib/utils/activity-plugin.js +5 -1
  41. package/migrations/0001_actor_type_and_workspace.sql +8 -0
  42. package/migrations/meta/0001_snapshot.json +192 -0
  43. package/migrations/meta/_journal.json +7 -0
  44. package/package.json +7 -8
@@ -1 +1 @@
1
- {"version":3,"file":"activity-filter.d.ts","sourceRoot":"","sources":["../../../src/lib/activity/activity-filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE5E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,EAAE,YASpC,CAAC"}
1
+ {"version":3,"file":"activity-filter.d.ts","sourceRoot":"","sources":["../../../src/lib/activity/activity-filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE5E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,EAAE,YAWpC,CAAC"}
@@ -19,7 +19,9 @@ exports.ACTIVITY_FILTER_SCHEMA = {
19
19
  subjectType: { type: utils_server_1.ScalarFieldType.String },
20
20
  subjectId: { type: utils_server_1.ScalarFieldType.String },
21
21
  actorId: { type: utils_server_1.ScalarFieldType.Uuid },
22
+ actorType: { type: utils_server_1.ScalarFieldType.String },
22
23
  actorEmail: { type: utils_server_1.ScalarFieldType.String },
24
+ workspaceId: { type: utils_server_1.ScalarFieldType.Uuid },
23
25
  at: { type: utils_server_1.ScalarFieldType.Date }
24
26
  }
25
27
  };
@@ -3,10 +3,15 @@ export declare const DEFAULT_PAGE_SIZE = 25;
3
3
  /** Upper bound on the requested page size (the largest option the UI offers). */
4
4
  export declare const MAX_PAGE_SIZE = 100;
5
5
  /**
6
- * Max length of the raw `?filter=` JSON string. A coarse first guard against
7
- * oversized payloads, ahead of the filter engine's node/depth caps.
6
+ * Max length of the raw `?filter=` JSON string a coarse first guard against
7
+ * oversized payloads, ahead of the filter engine's own budgets.
8
+ *
9
+ * Re-exported rather than declared: the number belongs to the engine that
10
+ * enforces the rest of the filter's limits, and four packages each declaring
11
+ * their own copy is how one of them (`alarms`) came to say 8192 while the other
12
+ * three said 4096. See `filters/budgets.ts` in `@orthacms/utils-server`.
8
13
  */
9
- export declare const FILTER_MAX_LENGTH = 4096;
14
+ export { FILTER_MAX_LENGTH } from '@orthacms/utils-server';
10
15
  /** Columns the read API permits sorting by (whitelist — keys are the wire values). */
11
16
  export declare const SORTABLE_FIELDS: readonly ["at", "kind"];
12
17
  /** A field the read API may sort by. */
@@ -1 +1 @@
1
- {"version":3,"file":"activity.constants.d.ts","sourceRoot":"","sources":["../../../src/lib/activity/activity.constants.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,iFAAiF;AACjF,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC;;;GAGG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC,sFAAsF;AACtF,eAAO,MAAM,eAAe,yBAA0B,CAAC;AAEvD,wCAAwC;AACxC,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,4CAA4C;AAC5C,eAAO,MAAM,WAAW,0BAA2B,CAAC;AAEpD,iDAAiD;AACjD,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"activity.constants.d.ts","sourceRoot":"","sources":["../../../src/lib/activity/activity.constants.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,iFAAiF;AACjF,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC;;;;;;;;GAQG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,sFAAsF;AACtF,eAAO,MAAM,eAAe,yBAA0B,CAAC;AAEvD,wCAAwC;AACxC,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D,4CAA4C;AAC5C,eAAO,MAAM,WAAW,0BAA2B,CAAC;AAEpD,iDAAiD;AACjD,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC"}
@@ -6,10 +6,16 @@ exports.DEFAULT_PAGE_SIZE = 25;
6
6
  /** Upper bound on the requested page size (the largest option the UI offers). */
7
7
  exports.MAX_PAGE_SIZE = 100;
8
8
  /**
9
- * Max length of the raw `?filter=` JSON string. A coarse first guard against
10
- * oversized payloads, ahead of the filter engine's node/depth caps.
9
+ * Max length of the raw `?filter=` JSON string a coarse first guard against
10
+ * oversized payloads, ahead of the filter engine's own budgets.
11
+ *
12
+ * Re-exported rather than declared: the number belongs to the engine that
13
+ * enforces the rest of the filter's limits, and four packages each declaring
14
+ * their own copy is how one of them (`alarms`) came to say 8192 while the other
15
+ * three said 4096. See `filters/budgets.ts` in `@orthacms/utils-server`.
11
16
  */
12
- exports.FILTER_MAX_LENGTH = 4096;
17
+ var utils_server_1 = require("@orthacms/utils-server");
18
+ Object.defineProperty(exports, "FILTER_MAX_LENGTH", { enumerable: true, get: function () { return utils_server_1.FILTER_MAX_LENGTH; } });
13
19
  /** Columns the read API permits sorting by (whitelist — keys are the wire values). */
14
20
  exports.SORTABLE_FIELDS = ['at', 'kind'];
15
21
  /** Sort directions the read API accepts. */
@@ -0,0 +1,36 @@
1
+ import { OutboxDispatcher, type DeadLetter } from '@orthacms/database';
2
+ import { DeadLettersQueryDto } from '../dto/dead-letters-query.dto';
3
+ /** The parked events, as `GET /api/activity/dead-letters` returns them. */
4
+ export interface DeadLetterListView {
5
+ /** How many events have given up in total, ignoring `limit`. */
6
+ total: number;
7
+ /** The most recent of them. */
8
+ items: DeadLetter[];
9
+ }
10
+ /**
11
+ * `GET /api/activity/dead-letters` — the events that should have been recorded
12
+ * and could not be.
13
+ *
14
+ * **This is the gap-in-the-trail route, and it belongs here rather than
15
+ * anywhere else.** A parked outbox row is an event no subscriber accepted after
16
+ * {@link MAX_DELIVERY_ATTEMPTS} tries, and the subscriber it was most often
17
+ * bound for is this plugin's: an audit row. The dispatcher already logs the
18
+ * moment one parks — but a log line is loud only to somebody tailing logs right
19
+ * then, and afterwards "is anything stuck, and why" had no answer short of a
20
+ * `psql` session. A hole in an audit trail that is only visible to a person who
21
+ * thinks to go looking is barely a hole that has been noticed.
22
+ *
23
+ * Gated on `activity:read`, the same key as the log itself: the question "what
24
+ * is missing from the trail" is the same question as "what is in it", and the
25
+ * answer names event kinds and aggregate ids.
26
+ *
27
+ * It reports rather than repairs. Replaying a parked row means clearing its
28
+ * `attempts` — a deliberate operator action against a fixed cause, not a button
29
+ * that re-runs whatever failed fifteen times.
30
+ */
31
+ export declare class DeadLettersController {
32
+ private readonly dispatcher;
33
+ constructor(dispatcher: OutboxDispatcher);
34
+ list(query: DeadLettersQueryDto): Promise<DeadLetterListView>;
35
+ }
36
+ //# sourceMappingURL=dead-letters.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dead-letters.controller.d.ts","sourceRoot":"","sources":["../../../../src/lib/activity/controllers/dead-letters.controller.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAMvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEpE,2EAA2E;AAC3E,MAAM,WAAW,kBAAkB;IAC/B,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,KAAK,EAAE,UAAU,EAAE,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAIa,qBAAqB;IAClB,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,gBAAgB;IAQnD,IAAI,CACG,KAAK,EAAE,mBAAmB,GACpC,OAAO,CAAC,kBAAkB,CAAC;CAMjC"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DeadLettersController = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@nestjs/common");
6
+ const swagger_1 = require("@nestjs/swagger");
7
+ const database_1 = require("@orthacms/database");
8
+ const identity_server_1 = require("@orthacms/identity-server");
9
+ const dead_letters_query_dto_1 = require("../dto/dead-letters-query.dto");
10
+ /**
11
+ * `GET /api/activity/dead-letters` — the events that should have been recorded
12
+ * and could not be.
13
+ *
14
+ * **This is the gap-in-the-trail route, and it belongs here rather than
15
+ * anywhere else.** A parked outbox row is an event no subscriber accepted after
16
+ * {@link MAX_DELIVERY_ATTEMPTS} tries, and the subscriber it was most often
17
+ * bound for is this plugin's: an audit row. The dispatcher already logs the
18
+ * moment one parks — but a log line is loud only to somebody tailing logs right
19
+ * then, and afterwards "is anything stuck, and why" had no answer short of a
20
+ * `psql` session. A hole in an audit trail that is only visible to a person who
21
+ * thinks to go looking is barely a hole that has been noticed.
22
+ *
23
+ * Gated on `activity:read`, the same key as the log itself: the question "what
24
+ * is missing from the trail" is the same question as "what is in it", and the
25
+ * answer names event kinds and aggregate ids.
26
+ *
27
+ * It reports rather than repairs. Replaying a parked row means clearing its
28
+ * `attempts` — a deliberate operator action against a fixed cause, not a button
29
+ * that re-runs whatever failed fifteen times.
30
+ */
31
+ let DeadLettersController = class DeadLettersController {
32
+ dispatcher;
33
+ constructor(dispatcher) {
34
+ this.dispatcher = dispatcher;
35
+ }
36
+ async list(query) {
37
+ return this.dispatcher.deadLetters({
38
+ limit: query.limit,
39
+ newerThan: query.since ? new Date(query.since) : undefined
40
+ });
41
+ }
42
+ };
43
+ exports.DeadLettersController = DeadLettersController;
44
+ tslib_1.__decorate([
45
+ (0, common_1.Get)('dead-letters'),
46
+ (0, swagger_1.ApiOperation)({
47
+ summary: 'Events that could not be recorded',
48
+ description: 'Outbox events that exhausted their delivery attempts and are no longer retried. Most often an audit row that was never written, so a non-zero `total` means the activity log is incomplete. Reports only — replaying one is an operator action against a fixed cause.'
49
+ }),
50
+ tslib_1.__param(0, (0, common_1.Query)()),
51
+ tslib_1.__metadata("design:type", Function),
52
+ tslib_1.__metadata("design:paramtypes", [dead_letters_query_dto_1.DeadLettersQueryDto]),
53
+ tslib_1.__metadata("design:returntype", Promise)
54
+ ], DeadLettersController.prototype, "list", null);
55
+ exports.DeadLettersController = DeadLettersController = tslib_1.__decorate([
56
+ (0, swagger_1.ApiTags)('Activity'),
57
+ (0, common_1.UseGuards)(identity_server_1.PermissionsGuard),
58
+ (0, identity_server_1.RequirePermissions)(identity_server_1.PERMISSIONS.ACTIVITY_READ),
59
+ (0, common_1.Controller)('activity'),
60
+ tslib_1.__metadata("design:paramtypes", [database_1.OutboxDispatcher])
61
+ ], DeadLettersController);
@@ -0,0 +1,32 @@
1
+ import { ActivityService } from '../services/activity.service';
2
+ import { EntryActivityQueryDto } from '../dto/entry-activity-query.dto';
3
+ import type { ActivityListView } from '../types/activity-view';
4
+ /**
5
+ * `GET /api/activity/entries/:entryId` — one entry's own audit trail.
6
+ *
7
+ * **Why this exists next to `GET /activity` rather than as a filter on it.**
8
+ * The full log is gated on `activity:read`, which is admin-only in the v1 role
9
+ * matrix and correctly so: it carries invites, role changes and sign-in
10
+ * failures across the whole deployment. The consequence was that an editor
11
+ * could not see the history of their **own** content — the entry editor's
12
+ * History tab shows version snapshots, which record what the words were and
13
+ * say nothing about who published it, who took it down, or who changed who may
14
+ * read it. Those are different facts and they live here.
15
+ *
16
+ * So this route asks a different question with a different key. `content:read`
17
+ * is the permission that already decides whether you may look at an entry at
18
+ * all, and everything returned is about an entry you may look at.
19
+ *
20
+ * **It is scoped by workspace, and fails closed.** `WorkspaceGuard` proves
21
+ * membership, and the query requires the row's `workspace_id` to match — so an
22
+ * entry id from another workspace reads as an empty history rather than as
23
+ * somebody else's. Rows written before `workspace_id` existed carry `null` and
24
+ * are therefore excluded: losing old history on this narrow route is the right
25
+ * side to err on, and the full log still has them.
26
+ */
27
+ export declare class EntryActivityController {
28
+ private readonly activity;
29
+ constructor(activity: ActivityService);
30
+ list(entryId: string, workspaceId: string, query: EntryActivityQueryDto): Promise<ActivityListView>;
31
+ }
32
+ //# sourceMappingURL=entry-activity.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry-activity.controller.d.ts","sourceRoot":"","sources":["../../../../src/lib/activity/controllers/entry-activity.controller.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAGa,uBAAuB;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,eAAe;IAStD,IAAI,CACiC,OAAO,EAAE,MAAM,EAC5B,WAAW,EAAE,MAAM,EAC9B,KAAK,EAAE,qBAAqB,GACtC,OAAO,CAAC,gBAAgB,CAAC;CAS/B"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EntryActivityController = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@nestjs/common");
6
+ const swagger_1 = require("@nestjs/swagger");
7
+ const identity_server_1 = require("@orthacms/identity-server");
8
+ const workspaces_server_1 = require("@orthacms/workspaces-server");
9
+ const activity_service_1 = require("../services/activity.service");
10
+ const entry_activity_query_dto_1 = require("../dto/entry-activity-query.dto");
11
+ /**
12
+ * `GET /api/activity/entries/:entryId` — one entry's own audit trail.
13
+ *
14
+ * **Why this exists next to `GET /activity` rather than as a filter on it.**
15
+ * The full log is gated on `activity:read`, which is admin-only in the v1 role
16
+ * matrix and correctly so: it carries invites, role changes and sign-in
17
+ * failures across the whole deployment. The consequence was that an editor
18
+ * could not see the history of their **own** content — the entry editor's
19
+ * History tab shows version snapshots, which record what the words were and
20
+ * say nothing about who published it, who took it down, or who changed who may
21
+ * read it. Those are different facts and they live here.
22
+ *
23
+ * So this route asks a different question with a different key. `content:read`
24
+ * is the permission that already decides whether you may look at an entry at
25
+ * all, and everything returned is about an entry you may look at.
26
+ *
27
+ * **It is scoped by workspace, and fails closed.** `WorkspaceGuard` proves
28
+ * membership, and the query requires the row's `workspace_id` to match — so an
29
+ * entry id from another workspace reads as an empty history rather than as
30
+ * somebody else's. Rows written before `workspace_id` existed carry `null` and
31
+ * are therefore excluded: losing old history on this narrow route is the right
32
+ * side to err on, and the full log still has them.
33
+ */
34
+ let EntryActivityController = class EntryActivityController {
35
+ activity;
36
+ constructor(activity) {
37
+ this.activity = activity;
38
+ }
39
+ list(entryId, workspaceId, query) {
40
+ return this.activity.list({
41
+ subjectType: 'content_entry',
42
+ subjectId: entryId,
43
+ workspaceId,
44
+ page: query.page,
45
+ pageSize: query.pageSize
46
+ });
47
+ }
48
+ };
49
+ exports.EntryActivityController = EntryActivityController;
50
+ tslib_1.__decorate([
51
+ (0, common_1.Get)(':entryId'),
52
+ (0, identity_server_1.RequirePermissions)(identity_server_1.PERMISSIONS.CONTENT_READ),
53
+ (0, swagger_1.ApiOperation)({
54
+ summary: 'One entry’s audit trail',
55
+ description: 'Every recorded action on this entry — created, edited, published, deleted, restored, and who may read it — newest first. Scoped to the open workspace; an id from another one reads as an empty history. Gated on `content:read` rather than `activity:read`, so an editor can see the history of content they can already open.'
56
+ }),
57
+ tslib_1.__param(0, (0, common_1.Param)('entryId', common_1.ParseUUIDPipe)),
58
+ tslib_1.__param(1, (0, workspaces_server_1.CurrentWorkspace)()),
59
+ tslib_1.__param(2, (0, common_1.Query)()),
60
+ tslib_1.__metadata("design:type", Function),
61
+ tslib_1.__metadata("design:paramtypes", [String, String, entry_activity_query_dto_1.EntryActivityQueryDto]),
62
+ tslib_1.__metadata("design:returntype", Promise)
63
+ ], EntryActivityController.prototype, "list", null);
64
+ exports.EntryActivityController = EntryActivityController = tslib_1.__decorate([
65
+ (0, swagger_1.ApiTags)('Activity'),
66
+ (0, common_1.UseGuards)(identity_server_1.PermissionsGuard, workspaces_server_1.WorkspaceGuard),
67
+ (0, common_1.Controller)('activity/entries'),
68
+ tslib_1.__metadata("design:paramtypes", [activity_service_1.ActivityService])
69
+ ], EntryActivityController);
@@ -0,0 +1,14 @@
1
+ /** Query parameters for `GET /api/activity/dead-letters`. */
2
+ export declare class DeadLettersQueryDto {
3
+ /**
4
+ * How many parked events to return, newest first.
5
+ *
6
+ * Capped rather than paginated: `total` already answers "how bad is it",
7
+ * and a dead-letter list long enough to page through is a different
8
+ * problem from the one this route exists to surface.
9
+ */
10
+ limit?: number;
11
+ /** Only events that occurred at or after this time (ISO 8601). */
12
+ since?: string;
13
+ }
14
+ //# sourceMappingURL=dead-letters-query.dto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dead-letters-query.dto.d.ts","sourceRoot":"","sources":["../../../../src/lib/activity/dto/dead-letters-query.dto.ts"],"names":[],"mappings":"AAIA,6DAA6D;AAC7D,qBAAa,mBAAmB;IAC5B;;;;;;OAMG;IAaH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,kEAAkE;IASlE,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DeadLettersQueryDto = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const swagger_1 = require("@nestjs/swagger");
6
+ const class_transformer_1 = require("class-transformer");
7
+ const class_validator_1 = require("class-validator");
8
+ /** Query parameters for `GET /api/activity/dead-letters`. */
9
+ class DeadLettersQueryDto {
10
+ /**
11
+ * How many parked events to return, newest first.
12
+ *
13
+ * Capped rather than paginated: `total` already answers "how bad is it",
14
+ * and a dead-letter list long enough to page through is a different
15
+ * problem from the one this route exists to surface.
16
+ */
17
+ limit;
18
+ /** Only events that occurred at or after this time (ISO 8601). */
19
+ since;
20
+ }
21
+ exports.DeadLettersQueryDto = DeadLettersQueryDto;
22
+ tslib_1.__decorate([
23
+ (0, swagger_1.ApiPropertyOptional)({
24
+ type: 'integer',
25
+ minimum: 1,
26
+ maximum: 200,
27
+ default: 50,
28
+ description: 'How many parked events to return, newest first.'
29
+ }),
30
+ (0, class_validator_1.IsOptional)(),
31
+ (0, class_transformer_1.Type)(() => Number),
32
+ (0, class_validator_1.IsInt)(),
33
+ (0, class_validator_1.Min)(1),
34
+ (0, class_validator_1.Max)(200),
35
+ tslib_1.__metadata("design:type", Number)
36
+ ], DeadLettersQueryDto.prototype, "limit", void 0);
37
+ tslib_1.__decorate([
38
+ (0, swagger_1.ApiPropertyOptional)({
39
+ type: String,
40
+ format: 'date-time',
41
+ description: 'Only events that occurred at or after this time — for a caller that has already acknowledged older failures.'
42
+ }),
43
+ (0, class_validator_1.IsOptional)(),
44
+ (0, class_validator_1.IsISO8601)(),
45
+ tslib_1.__metadata("design:type", String)
46
+ ], DeadLettersQueryDto.prototype, "since", void 0);
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Query parameters for `GET /api/activity/entries/:entryId`.
3
+ *
4
+ * Paging only. The subject is the URL, the workspace is the header, and every
5
+ * other filter the full log offers — actor, kind, date range — would be a way
6
+ * of asking a narrower question about a history short enough to read.
7
+ */
8
+ export declare class EntryActivityQueryDto {
9
+ /** 1-based page number. */
10
+ page?: number;
11
+ /** Rows per page, capped at {@link MAX_PAGE_SIZE}. */
12
+ pageSize?: number;
13
+ }
14
+ //# sourceMappingURL=entry-activity-query.dto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry-activity-query.dto.d.ts","sourceRoot":"","sources":["../../../../src/lib/activity/dto/entry-activity-query.dto.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,qBAAa,qBAAqB;IAC9B,2BAA2B;IAW3B,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,sDAAsD;IAatD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EntryActivityQueryDto = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const swagger_1 = require("@nestjs/swagger");
6
+ const class_transformer_1 = require("class-transformer");
7
+ const class_validator_1 = require("class-validator");
8
+ const activity_constants_1 = require("../activity.constants");
9
+ /**
10
+ * Query parameters for `GET /api/activity/entries/:entryId`.
11
+ *
12
+ * Paging only. The subject is the URL, the workspace is the header, and every
13
+ * other filter the full log offers — actor, kind, date range — would be a way
14
+ * of asking a narrower question about a history short enough to read.
15
+ */
16
+ class EntryActivityQueryDto {
17
+ /** 1-based page number. */
18
+ page;
19
+ /** Rows per page, capped at {@link MAX_PAGE_SIZE}. */
20
+ pageSize;
21
+ }
22
+ exports.EntryActivityQueryDto = EntryActivityQueryDto;
23
+ tslib_1.__decorate([
24
+ (0, swagger_1.ApiPropertyOptional)({
25
+ type: 'integer',
26
+ minimum: 1,
27
+ default: 1,
28
+ description: '1-based page number.'
29
+ }),
30
+ (0, class_validator_1.IsOptional)(),
31
+ (0, class_transformer_1.Type)(() => Number),
32
+ (0, class_validator_1.IsInt)(),
33
+ (0, class_validator_1.Min)(1),
34
+ tslib_1.__metadata("design:type", Number)
35
+ ], EntryActivityQueryDto.prototype, "page", void 0);
36
+ tslib_1.__decorate([
37
+ (0, swagger_1.ApiPropertyOptional)({
38
+ type: 'integer',
39
+ minimum: 1,
40
+ maximum: activity_constants_1.MAX_PAGE_SIZE,
41
+ default: activity_constants_1.DEFAULT_PAGE_SIZE,
42
+ description: `Rows per page, capped at ${activity_constants_1.MAX_PAGE_SIZE}.`
43
+ }),
44
+ (0, class_validator_1.IsOptional)(),
45
+ (0, class_transformer_1.Type)(() => Number),
46
+ (0, class_validator_1.IsInt)(),
47
+ (0, class_validator_1.Min)(1),
48
+ (0, class_validator_1.Max)(activity_constants_1.MAX_PAGE_SIZE),
49
+ tslib_1.__metadata("design:type", Number)
50
+ ], EntryActivityQueryDto.prototype, "pageSize", void 0);
@@ -13,6 +13,22 @@ export declare class ListActivityQueryDto {
13
13
  subjectId?: string;
14
14
  /** Restrict to one actor. */
15
15
  actorId?: string;
16
+ /**
17
+ * Restrict to actions performed by one kind of principal — `user` or
18
+ * `api_token`. Free text rather than an enum for the same reason `kind` is:
19
+ * the values are owned by `@orthacms/database`'s `EVENT_ACTOR_TYPE`, and a
20
+ * copy here would be a second catalogue to keep in step.
21
+ */
22
+ actorType?: string;
23
+ /**
24
+ * Restrict to one workspace's history.
25
+ *
26
+ * Narrows, never widens: the log is deployment-wide and `activity:read`
27
+ * is what bounds it, so this is a question a reader may ask rather than a
28
+ * boundary imposed on them. Rows belonging to no workspace (invites, role
29
+ * changes, workspace creation) are excluded by it, which is the point.
30
+ */
31
+ workspaceId?: string;
16
32
  /**
17
33
  * Restrict to one or more event kinds. Accepts a comma-separated list
18
34
  * (`?kind=user.invited,user.suspended`) → matched with `IN`. Kinds are
@@ -1 +1 @@
1
- {"version":3,"file":"list-activity-query.dto.d.ts","sourceRoot":"","sources":["../../../../src/lib/activity/dto/list-activity-query.dto.ts"],"names":[],"mappings":"AAcA,OAAO,EAMH,KAAK,aAAa,EAClB,KAAK,SAAS,EACjB,MAAM,uBAAuB,CAAC;AAE/B;;;;;;GAMG;AACH,qBAAa,oBAAoB;IAC7B,oDAAoD;IAUpD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,gEAAgE;IAUhE,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,6BAA6B;IAQ7B,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;;OAKG;IAmBH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB,uEAAuE;IAUvE,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;;OAMG;IAYH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,0DAA0D;IAS1D,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,0DAA0D;IAS1D,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ,2BAA2B;IAW3B,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,sDAAsD;IAatD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,yDAAyD;IAQzD,IAAI,CAAC,EAAE,aAAa,CAAC;IAErB,0CAA0C;IAQ1C,KAAK,CAAC,EAAE,SAAS,CAAC;CACrB"}
1
+ {"version":3,"file":"list-activity-query.dto.d.ts","sourceRoot":"","sources":["../../../../src/lib/activity/dto/list-activity-query.dto.ts"],"names":[],"mappings":"AAcA,OAAO,EAMH,KAAK,aAAa,EAClB,KAAK,SAAS,EACjB,MAAM,uBAAuB,CAAC;AAE/B;;;;;;GAMG;AACH,qBAAa,oBAAoB;IAC7B,oDAAoD;IAUpD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,gEAAgE;IAUhE,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,6BAA6B;IAQ7B,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;;OAKG;IAWH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;OAOG;IASH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;OAKG;IAmBH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB,uEAAuE;IAUvE,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;;;OAMG;IAYH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,0DAA0D;IAS1D,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,0DAA0D;IAS1D,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ,2BAA2B;IAW3B,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,sDAAsD;IAatD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,yDAAyD;IAQzD,IAAI,CAAC,EAAE,aAAa,CAAC;IAErB,0CAA0C;IAQ1C,KAAK,CAAC,EAAE,SAAS,CAAC;CACrB"}
@@ -20,6 +20,22 @@ class ListActivityQueryDto {
20
20
  subjectId;
21
21
  /** Restrict to one actor. */
22
22
  actorId;
23
+ /**
24
+ * Restrict to actions performed by one kind of principal — `user` or
25
+ * `api_token`. Free text rather than an enum for the same reason `kind` is:
26
+ * the values are owned by `@orthacms/database`'s `EVENT_ACTOR_TYPE`, and a
27
+ * copy here would be a second catalogue to keep in step.
28
+ */
29
+ actorType;
30
+ /**
31
+ * Restrict to one workspace's history.
32
+ *
33
+ * Narrows, never widens: the log is deployment-wide and `activity:read`
34
+ * is what bounds it, so this is a question a reader may ask rather than a
35
+ * boundary imposed on them. Rows belonging to no workspace (invites, role
36
+ * changes, workspace creation) are excluded by it, which is the point.
37
+ */
38
+ workspaceId;
23
39
  /**
24
40
  * Restrict to one or more event kinds. Accepts a comma-separated list
25
41
  * (`?kind=user.invited,user.suspended`) → matched with `IN`. Kinds are
@@ -84,6 +100,28 @@ tslib_1.__decorate([
84
100
  (0, class_validator_1.IsUUID)(),
85
101
  tslib_1.__metadata("design:type", String)
86
102
  ], ListActivityQueryDto.prototype, "actorId", void 0);
103
+ tslib_1.__decorate([
104
+ (0, swagger_1.ApiPropertyOptional)({
105
+ type: String,
106
+ maxLength: 255,
107
+ example: 'api_token',
108
+ description: 'Restrict to actions performed by one kind of principal (`user` / `api_token`).'
109
+ }),
110
+ (0, class_validator_1.IsOptional)(),
111
+ (0, class_validator_1.IsString)(),
112
+ (0, class_validator_1.MaxLength)(255),
113
+ tslib_1.__metadata("design:type", String)
114
+ ], ListActivityQueryDto.prototype, "actorType", void 0);
115
+ tslib_1.__decorate([
116
+ (0, swagger_1.ApiPropertyOptional)({
117
+ type: String,
118
+ format: 'uuid',
119
+ description: "Restrict to one workspace's history. Rows that belong to no workspace are excluded."
120
+ }),
121
+ (0, class_validator_1.IsOptional)(),
122
+ (0, class_validator_1.IsUUID)(),
123
+ tslib_1.__metadata("design:type", String)
124
+ ], ListActivityQueryDto.prototype, "workspaceId", void 0);
87
125
  tslib_1.__decorate([
88
126
  (0, swagger_1.ApiPropertyOptional)({
89
127
  type: String,
@@ -17,8 +17,22 @@ export interface AuditRow {
17
17
  subjectId: string;
18
18
  /** Who performed it, or `null` for a system-initiated event. */
19
19
  actorId: string | null;
20
+ /**
21
+ * What {@link actorId} names — `'user'`, `'api_token'`, or `null` when
22
+ * there is no actor. Defaults to `'user'` for an event whose actor predates
23
+ * the field, which is every actor the product had until API tokens could be
24
+ * one.
25
+ */
26
+ actorType: string | null;
20
27
  /** Frozen actor email snapshot, or `null`. */
21
28
  actorEmail: string | null;
29
+ /**
30
+ * The workspace the action happened in, or `null` when it happened in none
31
+ * (an invite, a role change, a workspace being created). Read from the
32
+ * event's own `payload.workspaceId` — a producer that has a workspace puts
33
+ * it there.
34
+ */
35
+ workspaceId: string | null;
22
36
  /** Open per-kind payload, or `null` when the kind carries none. */
23
37
  meta: Record<string, unknown> | null;
24
38
  /** Logical event time (the event's `occurredAt`). */
@@ -42,8 +56,40 @@ export declare class UnmappableAuditEventError extends Error {
42
56
  /**
43
57
  * Every event kind the activity subscriber audits — the dispatcher delivers
44
58
  * only these to it.
59
+ *
60
+ * These are the mappers' **inputs**. For the `kind` values they produce — the
61
+ * strings that reach the wire and that a client renders — see
62
+ * {@link AUDIT_KINDS}, which is a different and slightly shorter list
63
+ * (`member.*` and `user.disabled` collapse onto `user.*` audit kinds).
45
64
  */
46
65
  export declare const AUDITED_EVENT_KINDS: readonly string[];
66
+ /**
67
+ * Every audit `kind` this mapper can **produce** — the catalogue a client has
68
+ * to be able to render.
69
+ *
70
+ * It is declared rather than derived because deriving it would mean running
71
+ * every mapper, and several legitimately throw on a payload that cannot name
72
+ * their subject. `audit-event-mapping.spec.ts` drives each mapper once and
73
+ * asserts the two agree in both directions, so a kind added to `FACET_MAPPERS`
74
+ * and forgotten here fails a test rather than reaching the admin as a raw
75
+ * dotted token.
76
+ *
77
+ * That failure is the whole reason this exists. The admin restates these
78
+ * strings locally (it cannot import a server plugin), the mapper casts
79
+ * `dto.kind as ActivityKind` without checking, and a kind with no descriptor
80
+ * falls back to printing the wire token. No type error, no runtime error, no
81
+ * failing test — six `workspace.*` kinds, `user.activated`, all seven `media.*`
82
+ * kinds and all three `user.sso_*` kinds shipped that way.
83
+ */
84
+ export declare const AUDIT_KINDS: readonly ["user.invited", "user.invite_resent", "user.invite_revoked", "user.password_reset_issued", "user.activated", "user.profile_updated", "user.role_changed", "user.suspended", "user.reactivated", "user.password_changed", "user.signed_in", "user.signed_out", "user.sign_in_failed", "user.session_revoked", "user.sso_linked", "user.sso_provisioned", "user.sso_role_mapped", "workspace.created", "workspace.updated", "workspace.archived", "workspace.unarchived", "workspace.deleted", "workspace.member_added", "workspace.member_removed", "workspace.content_granted", "workspace.content_revoked", "entry.created", "entry.updated", "entry.published", "entry.unpublished", "entry.deleted", "entry.restored", "entry.purged", "token.created", "token.revoked", "token.used", "media.asset.uploaded", "media.asset.updated", "media.asset.moved", "media.asset.deleted", "media.folder.created", "media.folder.renamed", "media.folder.deleted", "transfer.content.exported", "transfer.content.imported", "segment.created", "segment.updated", "segment.deleted", "segment.entry_access_changed", "alarm.rule.created", "alarm.rule.updated", "alarm.rule.deleted", "alarm.rule.rescanned", "saved_view.created", "saved_view.updated", "saved_view.deleted", "copilot.skill.created", "copilot.skill.updated", "copilot.skill.deleted", "copilot.tool_permission.decided"];
85
+ /**
86
+ * Every `subject_type` this mapper can stamp — the column's whole range.
87
+ *
88
+ * Restated in the admin for the same reason as {@link AUDIT_KINDS}, and pinned
89
+ * by the same spec: the raw values are snake_cased machine tokens that a client
90
+ * has to translate into something a person reads.
91
+ */
92
+ export declare const AUDIT_SUBJECT_TYPES: readonly ["user", "workspace", "content_entry", "content_type", "api_token", "media_asset", "media_folder", "login_attempt", "segment", "alarm_rule", "saved_view", "copilot_skill", "copilot_run"];
47
93
  /**
48
94
  * Maps a domain event to the audit row it should produce, or `null` when the
49
95
  * kind is not audited. Pure and DB-free — the safety-net unit test asserts each
@@ -1 +1 @@
1
- {"version":3,"file":"audit-event-mapping.d.ts","sourceRoot":"","sources":["../../../../src/lib/activity/infrastructure/audit-event-mapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACrB,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACrC,qDAAqD;IACrD,EAAE,EAAE,IAAI,CAAC;CACZ;AAgKD;;;;;;;;;;;GAWG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;gBACpC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM;CAMjD;AAkRD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAE3B,SAAS,MAAM,EAAE,CAAC;AAgBvB;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,QAAQ,GAAG,IAAI,CAiB9D"}
1
+ {"version":3,"file":"audit-event-mapping.d.ts","sourceRoot":"","sources":["../../../../src/lib/activity/infrastructure/audit-event-mapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACrB,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;OAKG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACrC,qDAAqD;IACrD,EAAE,EAAE,IAAI,CAAC;CACZ;AAsRD;;;;;;;;;;;GAWG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;gBACpC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM;CAMjD;AA6gBD;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,EAE3B,SAAS,MAAM,EAAE,CAAC;AAEvB;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,WAAW,q0CA6Dc,CAAC;AAEvC;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,qMAcM,CAAC;AAiDvC;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,QAAQ,GAAG,IAAI,CAyB9D"}