@haneinfo/assignment 0.0.0-stage → 0.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 (60) hide show
  1. package/LICENSE +14 -0
  2. package/agent-guide.md +95 -0
  3. package/dist/assignment.controller.d.ts +53 -0
  4. package/dist/assignment.controller.d.ts.map +1 -0
  5. package/dist/assignment.controller.js +96 -0
  6. package/dist/assignment.controller.js.map +1 -0
  7. package/dist/assignment.module.d.ts +10 -0
  8. package/dist/assignment.module.d.ts.map +1 -0
  9. package/dist/assignment.module.js +58 -0
  10. package/dist/assignment.module.js.map +1 -0
  11. package/dist/assignment.service.d.ts +92 -0
  12. package/dist/assignment.service.d.ts.map +1 -0
  13. package/dist/assignment.service.js +267 -0
  14. package/dist/assignment.service.js.map +1 -0
  15. package/dist/index.d.ts +10 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +29 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/kind.d.ts +8 -0
  20. package/dist/kind.d.ts.map +1 -0
  21. package/dist/kind.js +37 -0
  22. package/dist/kind.js.map +1 -0
  23. package/dist/mcp-tools.d.ts +16 -0
  24. package/dist/mcp-tools.d.ts.map +1 -0
  25. package/dist/mcp-tools.js +79 -0
  26. package/dist/mcp-tools.js.map +1 -0
  27. package/dist/plugin.d.ts +10 -0
  28. package/dist/plugin.d.ts.map +1 -0
  29. package/dist/plugin.js +85 -0
  30. package/dist/plugin.js.map +1 -0
  31. package/dist/prisma-store.d.ts +7 -0
  32. package/dist/prisma-store.d.ts.map +1 -0
  33. package/dist/prisma-store.js +67 -0
  34. package/dist/prisma-store.js.map +1 -0
  35. package/dist/semantics.d.ts +9 -0
  36. package/dist/semantics.d.ts.map +1 -0
  37. package/dist/semantics.js +80 -0
  38. package/dist/semantics.js.map +1 -0
  39. package/dist/store.d.ts +52 -0
  40. package/dist/store.d.ts.map +1 -0
  41. package/dist/store.js +63 -0
  42. package/dist/store.js.map +1 -0
  43. package/dist/testing.d.ts +19 -0
  44. package/dist/testing.d.ts.map +1 -0
  45. package/dist/testing.js +23 -0
  46. package/dist/testing.js.map +1 -0
  47. package/dist/types.d.ts +24 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +3 -0
  50. package/dist/types.js.map +1 -0
  51. package/examples/definitions/equipment-loan/equipment-manager-approval.assignment.json +21 -0
  52. package/haneinfo.plugin.json +70 -0
  53. package/package.json +81 -3
  54. package/plugin.d.ts +2 -0
  55. package/plugin.js +4 -0
  56. package/prisma/assignment.prisma +32 -0
  57. package/schemas/assignment.spec.json +104 -0
  58. package/testing.d.ts +2 -0
  59. package/testing.js +2 -0
  60. package/README.md +0 -3
package/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ Copyright (c) 2026 Haneinfo. All Rights Reserved.
2
+
3
+ This software and associated documentation files (the "Software") are the proprietary and
4
+ confidential property of Haneinfo. No part of the Software may be copied, modified, merged,
5
+ published, distributed, sublicensed, or sold without the prior written permission of Haneinfo.
6
+
7
+ The Software is provided for internal use by Haneinfo and its authorized personnel only, and is
8
+ NOT licensed for external distribution or open-source use.
9
+
10
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
11
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
12
+ NONINFRINGEMENT. IN NO EVENT SHALL HANEINFO BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
13
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
14
+ THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/agent-guide.md ADDED
@@ -0,0 +1,95 @@
1
+ # @haneinfo/assignment — Agent Guide
2
+
3
+ ## Purpose
4
+
5
+ The assignment mechanism (decision `202610-00b3`, first batch; details in its own decision). An
6
+ `Assignment` definition says: when an instance of a StateMachine **enters a state**, these people
7
+ get a task, and their **response takes a transition**. It covers approvals, read-and-acknowledge
8
+ steps and task hand-offs.
9
+
10
+ ```json
11
+ {
12
+ "kind": "Assignment",
13
+ "schemaVersion": 1,
14
+ "metadata": { "code": "equipment-manager-approval", "name": "Approve equipment loan" },
15
+ "spec": {
16
+ "stateMachine": { "kind": "StateMachine", "code": "equipment-loan-flow" },
17
+ "onEnter": "SUBMITTED",
18
+ "assignees": [{ "type": "ROLE", "role": "EQUIPMENT_MANAGER" }],
19
+ "policy": "ANY_ONE",
20
+ "responses": [
21
+ { "key": "approve", "label": "Approve", "transition": "approve" },
22
+ { "key": "reject", "label": "Reject", "transition": "reject" }
23
+ ],
24
+ "dueIn": "P2D"
25
+ }
26
+ }
27
+ ```
28
+
29
+ ## When to use it, and when not
30
+
31
+ Use it whenever a person must act before a business object moves on. Do not use it for plain
32
+ notifications (that is a Timer `NOTIFY` action or the notification inbox) or for decisions a rule
33
+ could make (rules engine, later).
34
+
35
+ ## Kind and example definition
36
+
37
+ - `stateMachine`, `onEnter`: the machine and the state that opens the tasks. Not a FINAL state.
38
+ - `assignees`: person resolvers — `SPECIFIC_USER` (`userIds`), `ROLE` (role machine name, resolved
39
+ through RBAC), `FORM_FIELD_USER` (a `user_select` field of the machine's subject Form, by id),
40
+ `SUBMITTER`. Resolving to nobody makes the transition into `onEnter` fail with
41
+ `ASSIGNEE_UNRESOLVED` — fix the role membership or the field.
42
+ - `policy`: `ANY_ONE` (first response decides; use it for roles), `SINGLE` (same, but you expect
43
+ exactly one person — a warning if the resolvers can produce several), `JOINT` (everybody must give
44
+ the one non-`decisive` response; one `decisive` response — e.g. reject — decides at once).
45
+ - `responses[]`: `key`, `label`, `transition` (must leave `onEnter`), `decisive` (JOINT only).
46
+ - `dueIn`: ISO 8601 duration (`P2D`, `PT4H`); it only sets the task's due time. What happens when
47
+ it passes is a Timer with an `ASSIGNMENT_DUE` anchor.
48
+ - `title`: shown to the assignees; defaults to `metadata.name`.
49
+ - Permissions: `assignment:definition:read|write|publish`.
50
+
51
+ Instances pin the published assignments of their machine when they start; re-entering the state
52
+ opens a new round. Leaving the state any other way (a Timer, a person) cancels open tasks.
53
+
54
+ Example: `examples/definitions/equipment-loan/equipment-manager-approval.assignment.json`.
55
+
56
+ ## MCP tools
57
+
58
+ | Tool | Scope | Use |
59
+ | --- | --- | --- |
60
+ | `list_my_assignments` | `<namespace>:assignment:read` (read only) | Tasks of the person the connection acts for, with responses and instance data (as `$userContent`) |
61
+
62
+ There is no tool to respond: a response takes a transition (approve, reject) and stays a human
63
+ step in the App. Register from the App: `assignmentMcpTools.registerInto(registry, { scopeNamespace })`.
64
+
65
+ ## HTTP API (people)
66
+
67
+ | Route | Purpose |
68
+ | --- | --- |
69
+ | `GET /assignments/mine?status=OPEN` | Your tasks |
70
+ | `GET /assignments/:id` | One of your tasks with the instance |
71
+ | `POST /assignments/:id/respond` `{ response, comment? }` | Respond; may take the transition |
72
+
73
+ ## Events
74
+
75
+ `assignment.opened` (`assignmentCode`, `round`, `dueAt`, `assigneeIds`) and `assignment.closed`
76
+ (`assignmentCode`, `round`, `outcome`: the response key or `CANCELLED`), on the state-machine
77
+ runtime's event channel. Timer uses them for `ASSIGNMENT_DUE`.
78
+
79
+ ## Adapters
80
+
81
+ None. Roles resolve through `haneinfo.rbac-policy` (`userIdsWithRole`); assignees are notified through
82
+ `haneinfo.notification-inbox` when it is installed.
83
+
84
+ ## Common error codes and fixes
85
+
86
+ | Code | Fix |
87
+ | --- | --- |
88
+ | `UNKNOWN_STATE` / `ASSIGNMENT_ON_FINAL_STATE` | `onEnter` must be a non-FINAL state of the machine |
89
+ | `UNKNOWN_TRANSITION` / `TRANSITION_NOT_FROM_STATE` | A response's transition must leave `onEnter` |
90
+ | `JOINT_NEEDS_ONE_AGREEMENT` | Mark all but one JOINT response as `decisive` |
91
+ | `SINGLE_MAY_RESOLVE_MANY` (warning) | Use `ANY_ONE` for roles |
92
+ | `NOT_A_USER_FIELD` / `NO_SUBJECT_FORM` | `FORM_FIELD_USER` needs a `user_select` field of the subject Form |
93
+ | `INVALID_DURATION` | `dueIn` is a positive duration without months or years |
94
+ | `ASSIGNEE_UNRESOLVED` (runtime) | The resolvers produced nobody; see `details.unresolved` |
95
+ | `TASK_NOT_OPEN` (runtime) | Someone else already decided, or the instance moved on |
@@ -0,0 +1,53 @@
1
+ import { type InteractivePrincipal } from '@haneinfo/plugin-api';
2
+ import { AssignmentService } from './assignment.service';
3
+ /** A person's tasks. Responding — which takes a transition — is only possible here, never through MCP. */
4
+ export declare class AssignmentController {
5
+ private readonly assignments;
6
+ constructor(assignments: AssignmentService);
7
+ mine(user: InteractivePrincipal, query: unknown): Promise<{
8
+ tasks: import("./assignment.service").AssignmentTaskView[];
9
+ }>;
10
+ get(user: InteractivePrincipal, id: string): Promise<import("./assignment.service").AssignmentTaskView>;
11
+ respond(user: InteractivePrincipal, id: string, body: unknown): Promise<{
12
+ completed: boolean;
13
+ task: {
14
+ status: "RESPONDED";
15
+ response: string;
16
+ id: string;
17
+ instanceId: string;
18
+ assignmentCode: string;
19
+ assignmentVersion: number;
20
+ round: number;
21
+ assigneeId: string;
22
+ title: string;
23
+ comment: string | null;
24
+ dueAt: Date | null;
25
+ respondedAt: Date | null;
26
+ createdAt: Date;
27
+ };
28
+ instance?: undefined;
29
+ } | {
30
+ completed: boolean;
31
+ task: {
32
+ status: "RESPONDED";
33
+ response: string;
34
+ id: string;
35
+ instanceId: string;
36
+ assignmentCode: string;
37
+ assignmentVersion: number;
38
+ round: number;
39
+ assigneeId: string;
40
+ title: string;
41
+ comment: string | null;
42
+ dueAt: Date | null;
43
+ respondedAt: Date | null;
44
+ createdAt: Date;
45
+ };
46
+ instance: {
47
+ id: string;
48
+ state: string;
49
+ revision: number;
50
+ };
51
+ }>;
52
+ }
53
+ //# sourceMappingURL=assignment.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assignment.controller.d.ts","sourceRoot":"","sources":["../src/assignment.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,oBAAoB,EAAkB,MAAM,sBAAsB,CAAC;AAajF,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAwBzD,0GAA0G;AAC1G,qBAEa,oBAAoB;IACnB,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAAX,WAAW,EAAE,iBAAiB;IAG3D,IAAI,CAAgB,IAAI,EAAE,oBAAoB,EAAW,KAAK,EAAE,OAAO;;;IAUvE,GAAG,CAAgB,IAAI,EAAE,oBAAoB,EAAe,EAAE,EAAE,MAAM;IAKtE,OAAO,CACU,IAAI,EAAE,oBAAoB,EAC5B,EAAE,EAAE,MAAM,EACf,IAAI,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAYxB"}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.AssignmentController = void 0;
16
+ const plugin_api_1 = require("@haneinfo/plugin-api");
17
+ const plugin_host_nest_1 = require("@haneinfo/plugin-host-nest");
18
+ const common_1 = require("@nestjs/common");
19
+ const zod_1 = require("zod");
20
+ const assignment_service_1 = require("./assignment.service");
21
+ const respondBody = zod_1.z.object({
22
+ response: zod_1.z.string().min(1),
23
+ comment: zod_1.z.string().max(2000).optional(),
24
+ });
25
+ const listQuery = zod_1.z.object({
26
+ status: zod_1.z.enum(['OPEN', 'RESPONDED', 'CLOSED', 'CANCELLED']).optional(),
27
+ });
28
+ async function run(work) {
29
+ try {
30
+ return await work();
31
+ }
32
+ catch (error) {
33
+ if (error instanceof plugin_api_1.MechanismError)
34
+ throw new common_1.HttpException(error.toJSON(), error.status);
35
+ if (error instanceof zod_1.z.ZodError)
36
+ throw new common_1.HttpException({ code: 'INVALID_INPUT', message: 'Invalid request', issues: error.issues }, 400);
37
+ throw error;
38
+ }
39
+ }
40
+ /** A person's tasks. Responding — which takes a transition — is only possible here, never through MCP. */
41
+ let AssignmentController = class AssignmentController {
42
+ constructor(assignments) {
43
+ this.assignments = assignments;
44
+ }
45
+ mine(user, query) {
46
+ return run(async () => ({
47
+ tasks: await this.assignments.listMine(user.sub, listQuery.parse(query ?? {}).status ?? 'OPEN'),
48
+ }));
49
+ }
50
+ get(user, id) {
51
+ return run(() => this.assignments.getMine(user.sub, id));
52
+ }
53
+ respond(user, id, body) {
54
+ return run(() => {
55
+ const parsed = respondBody.parse(body);
56
+ return this.assignments.respond({
57
+ taskId: id,
58
+ response: parsed.response,
59
+ comment: parsed.comment,
60
+ userId: user.sub,
61
+ });
62
+ });
63
+ }
64
+ };
65
+ exports.AssignmentController = AssignmentController;
66
+ __decorate([
67
+ (0, common_1.Get)('mine'),
68
+ __param(0, (0, plugin_host_nest_1.CurrentUser)()),
69
+ __param(1, (0, common_1.Query)()),
70
+ __metadata("design:type", Function),
71
+ __metadata("design:paramtypes", [Object, Object]),
72
+ __metadata("design:returntype", void 0)
73
+ ], AssignmentController.prototype, "mine", null);
74
+ __decorate([
75
+ (0, common_1.Get)(':id'),
76
+ __param(0, (0, plugin_host_nest_1.CurrentUser)()),
77
+ __param(1, (0, common_1.Param)('id')),
78
+ __metadata("design:type", Function),
79
+ __metadata("design:paramtypes", [Object, String]),
80
+ __metadata("design:returntype", void 0)
81
+ ], AssignmentController.prototype, "get", null);
82
+ __decorate([
83
+ (0, common_1.Post)(':id/respond'),
84
+ __param(0, (0, plugin_host_nest_1.CurrentUser)()),
85
+ __param(1, (0, common_1.Param)('id')),
86
+ __param(2, (0, common_1.Body)()),
87
+ __metadata("design:type", Function),
88
+ __metadata("design:paramtypes", [Object, String, Object]),
89
+ __metadata("design:returntype", void 0)
90
+ ], AssignmentController.prototype, "respond", null);
91
+ exports.AssignmentController = AssignmentController = __decorate([
92
+ (0, common_1.Controller)('assignments'),
93
+ (0, common_1.UseGuards)(plugin_host_nest_1.InteractiveAuthGuard),
94
+ __metadata("design:paramtypes", [assignment_service_1.AssignmentService])
95
+ ], AssignmentController);
96
+ //# sourceMappingURL=assignment.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assignment.controller.js","sourceRoot":"","sources":["../src/assignment.controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { type DefinitionRegistryPort } from '@haneinfo/plugin-api';
2
+ import { type OnModuleInit } from '@nestjs/common';
3
+ export declare class AssignmentKindRegistration implements OnModuleInit {
4
+ private readonly registry;
5
+ constructor(registry: DefinitionRegistryPort);
6
+ onModuleInit(): void;
7
+ }
8
+ export declare class AssignmentModule {
9
+ }
10
+ //# sourceMappingURL=assignment.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assignment.module.d.ts","sourceRoot":"","sources":["../src/assignment.module.ts"],"names":[],"mappings":"AACA,OAAO,EAAuB,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,EAA8B,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAQ/E,qBACa,0BAA2B,YAAW,YAAY;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,sBAAsB;IAE1F,YAAY;CAGb;AAED,qBAca,gBAAgB;CAAG"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.AssignmentModule = exports.AssignmentKindRegistration = void 0;
16
+ const common_1 = require("@haneinfo/common");
17
+ const plugin_api_1 = require("@haneinfo/plugin-api");
18
+ const common_2 = require("@nestjs/common");
19
+ const assignment_controller_1 = require("./assignment.controller");
20
+ const assignment_service_1 = require("./assignment.service");
21
+ const kind_1 = require("./kind");
22
+ const mcp_tools_1 = require("./mcp-tools");
23
+ const prisma_store_1 = require("./prisma-store");
24
+ const store_1 = require("./store");
25
+ let AssignmentKindRegistration = class AssignmentKindRegistration {
26
+ constructor(registry) {
27
+ this.registry = registry;
28
+ }
29
+ onModuleInit() {
30
+ this.registry.registerKind(kind_1.assignmentDefinitionKind);
31
+ }
32
+ };
33
+ exports.AssignmentKindRegistration = AssignmentKindRegistration;
34
+ exports.AssignmentKindRegistration = AssignmentKindRegistration = __decorate([
35
+ (0, common_2.Injectable)(),
36
+ __param(0, (0, common_2.Inject)(plugin_api_1.DEFINITION_REGISTRY)),
37
+ __metadata("design:paramtypes", [Object])
38
+ ], AssignmentKindRegistration);
39
+ let AssignmentModule = class AssignmentModule {
40
+ };
41
+ exports.AssignmentModule = AssignmentModule;
42
+ exports.AssignmentModule = AssignmentModule = __decorate([
43
+ (0, common_2.Module)({
44
+ controllers: [assignment_controller_1.AssignmentController],
45
+ providers: [
46
+ AssignmentKindRegistration,
47
+ {
48
+ provide: store_1.ASSIGNMENT_STORE,
49
+ useFactory: (prisma) => new prisma_store_1.PrismaAssignmentStore(prisma),
50
+ inject: [common_1.PrismaService],
51
+ },
52
+ assignment_service_1.AssignmentService,
53
+ mcp_tools_1.AssignmentMcpTools,
54
+ ],
55
+ exports: [assignment_service_1.AssignmentService, mcp_tools_1.AssignmentMcpTools],
56
+ })
57
+ ], AssignmentModule);
58
+ //# sourceMappingURL=assignment.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assignment.module.js","sourceRoot":"","sources":["../src/assignment.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,6CAAiD;AACjD,qDAAwF;AACxF,2CAA+E;AAC/E,mEAA+D;AAC/D,6DAAyD;AACzD,iCAAkD;AAClD,2CAAiD;AACjD,iDAAuD;AACvD,mCAA2C;AAGpC,IAAM,0BAA0B,GAAhC,MAAM,0BAA0B;IACrC,YAA0D,QAAgC;QAAhC,aAAQ,GAAR,QAAQ,CAAwB;IAAG,CAAC;IAE9F,YAAY;QACV,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,+BAAwB,CAAC,CAAC;IACvD,CAAC;CACF,CAAA;AANY,gEAA0B;qCAA1B,0BAA0B;IADtC,IAAA,mBAAU,GAAE;IAEE,WAAA,IAAA,eAAM,EAAC,gCAAmB,CAAC,CAAA;;GAD7B,0BAA0B,CAMtC;AAgBM,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;CAAG,CAAA;AAAnB,4CAAgB;2BAAhB,gBAAgB;IAd5B,IAAA,eAAM,EAAC;QACN,WAAW,EAAE,CAAC,4CAAoB,CAAC;QACnC,SAAS,EAAE;YACT,0BAA0B;YAC1B;gBACE,OAAO,EAAE,wBAAgB;gBACzB,UAAU,EAAE,CAAC,MAAqB,EAAE,EAAE,CAAC,IAAI,oCAAqB,CAAC,MAAM,CAAC;gBACxE,MAAM,EAAE,CAAC,sBAAa,CAAC;aACxB;YACD,sCAAiB;YACjB,8BAAkB;SACnB;QACD,OAAO,EAAE,CAAC,sCAAiB,EAAE,8BAAkB,CAAC;KACjD,CAAC;GACW,gBAAgB,CAAG"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * The assignment runtime. It listens to the state-machine runtime:
3
+ *
4
+ * - `onStarted`: pin the published Assignment definitions that hang off this machine, so a later
5
+ * publish never changes a running instance.
6
+ * - `onStateEntered`: cancel open tasks of assignments whose state was left, then open tasks for the
7
+ * assignments whose `onEnter` is the new state.
8
+ *
9
+ * A response that completes the assignment takes its transition through the runtime, in the same
10
+ * transaction, with an ASSIGNMENT trigger (which skips the transition's person permission: the
11
+ * assignment itself is the authorization).
12
+ */
13
+ import { type DefinitionRegistryPort, type NotificationInboxPort, type RbacPolicyPort, type StateMachineInstanceView, type StateMachineListener, type StateMachineRuntimePort } from '@haneinfo/plugin-api';
14
+ import { type OnModuleInit } from '@nestjs/common';
15
+ import { type AssignmentStore, type TaskRecord } from './store';
16
+ import type { AssignmentResponse, AssignmentSpec } from './types';
17
+ export declare const ASSIGNMENT_CLOCK: unique symbol;
18
+ export declare const ASSIGNMENT_APP_NAME: unique symbol;
19
+ export interface AssignmentTaskView extends TaskRecord {
20
+ responses: Pick<AssignmentResponse, 'key' | 'label'>[];
21
+ policy: AssignmentSpec['policy'];
22
+ instance: Pick<StateMachineInstanceView, 'id' | 'machine' | 'state' | 'data' | 'submitterId' | 'revision'> | null;
23
+ }
24
+ export declare class AssignmentService implements OnModuleInit {
25
+ private readonly store;
26
+ private readonly runtime;
27
+ private readonly registry;
28
+ private readonly rbac?;
29
+ private readonly notifications?;
30
+ private readonly appName;
31
+ private readonly now;
32
+ readonly listener: StateMachineListener;
33
+ constructor(store: AssignmentStore, runtime: StateMachineRuntimePort, registry: DefinitionRegistryPort, rbac?: RbacPolicyPort | undefined, notifications?: NotificationInboxPort | undefined, clock?: () => Date, appName?: string);
34
+ onModuleInit(): void;
35
+ private pin;
36
+ private onStateEntered;
37
+ private cancelOpen;
38
+ private open;
39
+ /** A person responds to their task. Human interface only (decision 202610-00b3, point 16 by analogy). */
40
+ respond(input: {
41
+ taskId: string;
42
+ response: string;
43
+ userId: string;
44
+ comment?: string;
45
+ }): Promise<{
46
+ completed: boolean;
47
+ task: {
48
+ status: "RESPONDED";
49
+ response: string;
50
+ id: string;
51
+ instanceId: string;
52
+ assignmentCode: string;
53
+ assignmentVersion: number;
54
+ round: number;
55
+ assigneeId: string;
56
+ title: string;
57
+ comment: string | null;
58
+ dueAt: Date | null;
59
+ respondedAt: Date | null;
60
+ createdAt: Date;
61
+ };
62
+ instance?: undefined;
63
+ } | {
64
+ completed: boolean;
65
+ task: {
66
+ status: "RESPONDED";
67
+ response: string;
68
+ id: string;
69
+ instanceId: string;
70
+ assignmentCode: string;
71
+ assignmentVersion: number;
72
+ round: number;
73
+ assigneeId: string;
74
+ title: string;
75
+ comment: string | null;
76
+ dueAt: Date | null;
77
+ respondedAt: Date | null;
78
+ createdAt: Date;
79
+ };
80
+ instance: {
81
+ id: string;
82
+ state: string;
83
+ revision: number;
84
+ };
85
+ }>;
86
+ listMine(userId: string, status?: TaskRecord['status'] | undefined): Promise<AssignmentTaskView[]>;
87
+ getMine(userId: string, taskId: string): Promise<AssignmentTaskView>;
88
+ /** Every task of an instance, for its history view. */
89
+ tasksOf(instanceId: string, tx?: unknown): Promise<TaskRecord[]>;
90
+ private view;
91
+ }
92
+ //# sourceMappingURL=assignment.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assignment.service.d.ts","sourceRoot":"","sources":["../src/assignment.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAEL,KAAK,sBAAsB,EAG3B,KAAK,qBAAqB,EAG1B,KAAK,cAAc,EAGnB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAsB,KAAK,YAAY,EAAY,MAAM,gBAAgB,CAAC;AAEjF,OAAO,EAEL,KAAK,eAAe,EAGpB,KAAK,UAAU,EAChB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAElE,eAAO,MAAM,gBAAgB,eAA0C,CAAC;AACxE,eAAO,MAAM,mBAAmB,eAA6C,CAAC;AAE9E,MAAM,WAAW,kBAAmB,SAAQ,UAAU;IACpD,SAAS,EAAE,IAAI,CAAC,kBAAkB,EAAE,KAAK,GAAG,OAAO,CAAC,EAAE,CAAC;IACvD,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IACjC,QAAQ,EAAE,IAAI,CACZ,wBAAwB,EACxB,IAAI,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,CACjE,GAAG,IAAI,CAAC;CACV;AAED,qBACa,iBAAkB,YAAW,YAAY;IASxB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACjB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IACf,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;IAE9B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAdnE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAa;IAEjC,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAGrC;gBAG2C,KAAK,EAAE,eAAe,EACjB,OAAO,EAAE,uBAAuB,EAClC,QAAQ,EAAE,sBAAsB,EAC5B,IAAI,CAAC,EAAE,cAAc,YAAA,EACd,aAAa,CAAC,EAAE,qBAAqB,YAAA,EACxD,KAAK,CAAC,EAAE,MAAM,IAAI,EACE,OAAO,GAAE,MAAc;IAKnF,YAAY;YAME,GAAG;YAaH,cAAc;YAcd,UAAU;YAmBV,IAAI;IA2ElB,yGAAyG;IACnG,OAAO,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8FrF,QAAQ,CACZ,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,UAAU,CAAC,QAAQ,CAAC,GAAG,SAAkB,GAChD,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAO1B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAS1E,uDAAuD;IACjD,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,OAAO;YAIhC,IAAI;CA4BnB"}