@substrat-run/engine-absence 0.0.0 → 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.
@@ -0,0 +1,313 @@
1
+ import { z } from 'zod';
2
+ import { type EntityRef } from '@substrat-run/contracts';
3
+ import { type ModuleRegistration, type OperationContext } from '@substrat-run/kernel';
4
+ export declare const PERM: {
5
+ read: string & z.$brand<"PermissionKey">;
6
+ request: string & z.$brand<"PermissionKey">;
7
+ approve: string & z.$brand<"PermissionKey">;
8
+ configure: string & z.$brand<"PermissionKey">;
9
+ };
10
+ export declare const absenceManifest: {
11
+ id: string & z.$brand<"ModuleId">;
12
+ version: string;
13
+ kernelContract: string;
14
+ permissions: {
15
+ key: string & z.$brand<"PermissionKey">;
16
+ description: string;
17
+ }[];
18
+ events: {
19
+ emits: {
20
+ type: string;
21
+ schemaVersion: number;
22
+ }[];
23
+ consumes: {
24
+ type: string;
25
+ schemaVersion: number;
26
+ }[];
27
+ };
28
+ migrations: {
29
+ journalDir: string;
30
+ compatibleFrom: string;
31
+ };
32
+ attachmentTargets: {
33
+ entityType: string;
34
+ readPermission: string & z.$brand<"PermissionKey">;
35
+ writePermission?: (string & z.$brand<"PermissionKey">) | undefined;
36
+ }[];
37
+ entityRelations?: {
38
+ entityType: string;
39
+ parentType: string;
40
+ }[] | undefined;
41
+ guards?: {
42
+ before: string;
43
+ predicate: string;
44
+ config: Record<string, unknown>;
45
+ }[] | undefined;
46
+ schedules?: {
47
+ operation: string;
48
+ cadence: {
49
+ everyMinutes: number;
50
+ };
51
+ input?: Record<string, unknown> | undefined;
52
+ permissions: (string & z.$brand<"PermissionKey">)[];
53
+ }[] | undefined;
54
+ withdraws?: string[] | undefined;
55
+ entitlementKey: string;
56
+ envSpec?: {
57
+ key: string;
58
+ label?: string | undefined;
59
+ description: string;
60
+ placeholder?: string | undefined;
61
+ required: boolean;
62
+ secret: boolean;
63
+ default?: string | undefined;
64
+ group?: string | undefined;
65
+ }[] | undefined;
66
+ ownerGrants?: (string & z.$brand<"PermissionKey">)[] | undefined;
67
+ entitlements?: string[] | undefined;
68
+ provides?: string[] | undefined;
69
+ requires?: string[] | undefined;
70
+ api?: string | undefined;
71
+ searchables?: {
72
+ entityType: string;
73
+ fields: string[];
74
+ }[] | undefined;
75
+ ui?: {
76
+ routes?: {
77
+ path: string;
78
+ screen: string;
79
+ permission: string & z.$brand<"PermissionKey">;
80
+ }[] | undefined;
81
+ nav?: {
82
+ label: string;
83
+ icon?: string | undefined;
84
+ to: string;
85
+ permission: string & z.$brand<"PermissionKey">;
86
+ }[] | undefined;
87
+ entityViews?: {
88
+ entityType: string;
89
+ view: string;
90
+ }[] | undefined;
91
+ widgets?: {
92
+ slot: string;
93
+ component: string;
94
+ permission: string & z.$brand<"PermissionKey">;
95
+ }[] | undefined;
96
+ settingsPanels?: {
97
+ label: string;
98
+ component: string;
99
+ permission: string & z.$brand<"PermissionKey">;
100
+ }[] | undefined;
101
+ } | undefined;
102
+ };
103
+ export declare const absenceMigrations: {
104
+ version: string;
105
+ sql: string;
106
+ }[];
107
+ /** Every write names its subject: the vertical's opaque noun + the erasure key. */
108
+ export declare const absenceSubject: z.ZodObject<{
109
+ ref: z.ZodObject<{
110
+ entityType: z.ZodString;
111
+ entityId: z.ZodString;
112
+ }, z.core.$strip>;
113
+ dataSubjectId: z.core.$ZodBranded<z.ZodString, "DataSubjectId", "out">;
114
+ }, z.core.$strip>;
115
+ export type AbsenceSubject = z.infer<typeof absenceSubject>;
116
+ export interface LeaveType {
117
+ key: string;
118
+ floor: string;
119
+ active: boolean;
120
+ createdAt: string;
121
+ }
122
+ interface EntryRow {
123
+ id: string;
124
+ subject_type: string;
125
+ subject_id: string;
126
+ data_subject_id: string;
127
+ leave_type_key: string;
128
+ entry_kind: 'accrual' | 'booking' | 'correction' | 'carryover' | 'reversal';
129
+ delta: string;
130
+ effective_date: string;
131
+ request_id: string | null;
132
+ note: string | null;
133
+ created_by: string;
134
+ created_at: string;
135
+ }
136
+ export interface AbsenceEntry {
137
+ id: string;
138
+ subject: EntityRef;
139
+ leaveTypeKey: string;
140
+ entryKind: EntryRow['entry_kind'];
141
+ delta: string;
142
+ effectiveDate: string;
143
+ requestId: string | null;
144
+ note: string | null;
145
+ createdBy: string;
146
+ createdAt: string;
147
+ }
148
+ interface RequestRow {
149
+ id: string;
150
+ subject_type: string;
151
+ subject_id: string;
152
+ data_subject_id: string;
153
+ leave_type_key: string;
154
+ start_date: string;
155
+ end_date: string;
156
+ days: string;
157
+ status: 'requested' | 'approved' | 'rejected' | 'cancelled';
158
+ note: string | null;
159
+ decided_by: string | null;
160
+ decided_at: string | null;
161
+ created_by: string;
162
+ created_at: string;
163
+ }
164
+ export interface AbsenceRequest {
165
+ id: string;
166
+ subject: EntityRef;
167
+ leaveTypeKey: string;
168
+ startDate: string;
169
+ endDate: string;
170
+ days: string;
171
+ status: RequestRow['status'];
172
+ note: string | null;
173
+ decidedBy: string | null;
174
+ decidedAt: string | null;
175
+ createdBy: string;
176
+ createdAt: string;
177
+ }
178
+ export declare const configureLeaveTypeInput: z.ZodObject<{
179
+ key: z.ZodString;
180
+ floor: z.ZodOptional<z.ZodString>;
181
+ active: z.ZodOptional<z.ZodBoolean>;
182
+ }, z.core.$strip>;
183
+ export type ConfigureLeaveTypeInput = z.infer<typeof configureLeaveTypeInput>;
184
+ export declare function configureLeaveType(ctx: OperationContext, rawInput: ConfigureLeaveTypeInput): LeaveType;
185
+ export declare function listLeaveTypes(ctx: OperationContext): LeaveType[];
186
+ /**
187
+ * The one write that bypasses the request flow, restricted to accrual /
188
+ * correction / carryover — 'booking' and 'reversal' are mintable only through
189
+ * decideAbsence/cancelAbsence, which is what makes "only an approved request
190
+ * touches the ledger" a construction rather than a convention.
191
+ *
192
+ * No floor check here: a correction is the administrator's escape hatch, and
193
+ * accrual/carryover only ever add. The floor guards bookings (D-D).
194
+ */
195
+ export declare const recordEntryInput: z.ZodObject<{
196
+ subject: z.ZodObject<{
197
+ ref: z.ZodObject<{
198
+ entityType: z.ZodString;
199
+ entityId: z.ZodString;
200
+ }, z.core.$strip>;
201
+ dataSubjectId: z.core.$ZodBranded<z.ZodString, "DataSubjectId", "out">;
202
+ }, z.core.$strip>;
203
+ leaveTypeKey: z.ZodString;
204
+ entryKind: z.ZodEnum<{
205
+ accrual: "accrual";
206
+ carryover: "carryover";
207
+ correction: "correction";
208
+ }>;
209
+ delta: z.ZodString;
210
+ effectiveDate: z.ZodString;
211
+ note: z.ZodOptional<z.ZodString>;
212
+ }, z.core.$strip>;
213
+ export type RecordEntryInput = z.infer<typeof recordEntryInput>;
214
+ export declare function recordEntry(ctx: OperationContext, rawInput: RecordEntryInput): AbsenceEntry;
215
+ /** Balance = pure fold over entries with effective_date <= asOf. No counter exists. */
216
+ export declare function balanceAsOf(ctx: OperationContext, input: {
217
+ subject: EntityRef;
218
+ leaveTypeKey: string;
219
+ asOf?: string;
220
+ }): string;
221
+ export declare const requestAbsenceInput: z.ZodObject<{
222
+ subject: z.ZodObject<{
223
+ ref: z.ZodObject<{
224
+ entityType: z.ZodString;
225
+ entityId: z.ZodString;
226
+ }, z.core.$strip>;
227
+ dataSubjectId: z.core.$ZodBranded<z.ZodString, "DataSubjectId", "out">;
228
+ }, z.core.$strip>;
229
+ leaveTypeKey: z.ZodString;
230
+ startDate: z.ZodString;
231
+ endDate: z.ZodString;
232
+ days: z.ZodString;
233
+ note: z.ZodOptional<z.ZodString>;
234
+ }, z.core.$strip>;
235
+ export type RequestAbsenceInput = z.infer<typeof requestAbsenceInput>;
236
+ export declare function requestAbsence(ctx: OperationContext, rawInput: RequestAbsenceInput): AbsenceRequest;
237
+ export declare const decideAbsenceInput: z.ZodObject<{
238
+ requestId: z.ZodString;
239
+ decision: z.ZodEnum<{
240
+ approve: "approve";
241
+ reject: "reject";
242
+ }>;
243
+ note: z.ZodOptional<z.ZodString>;
244
+ }, z.core.$strip>;
245
+ export type DecideAbsenceInput = z.infer<typeof decideAbsenceInput>;
246
+ export declare function decideAbsence(ctx: OperationContext, rawInput: DecideAbsenceInput): {
247
+ request: AbsenceRequest;
248
+ booking: AbsenceEntry | null;
249
+ };
250
+ /**
251
+ * requested → cancelled (withdraw; no ledger touch), or approved → cancelled
252
+ * with a COMPENSATING reversal entry — "Hugo came back" is a new entry, never
253
+ * an edit (D-E). Rejected/cancelled rows are terminal.
254
+ */
255
+ export declare const cancelAbsenceInput: z.ZodObject<{
256
+ requestId: z.ZodString;
257
+ reason: z.ZodOptional<z.ZodString>;
258
+ }, z.core.$strip>;
259
+ export type CancelAbsenceInput = z.infer<typeof cancelAbsenceInput>;
260
+ export declare function cancelAbsence(ctx: OperationContext, rawInput: CancelAbsenceInput): {
261
+ request: AbsenceRequest;
262
+ reversal: AbsenceEntry | null;
263
+ };
264
+ /**
265
+ * A DATE-TRIGGERED rule with no caller but the passage of time (#383): a
266
+ * request still 'requested' once its start date has passed can no longer be
267
+ * approved, so the platform sweep cancels it — attributed to the schedule
268
+ * (`{ system }`), never to a manager who never touched it. Idempotent (only
269
+ * 'requested' rows past their start) and paged (a bounded batch per pass).
270
+ */
271
+ export declare function expireStaleRequests(ctx: OperationContext): {
272
+ expired: number;
273
+ };
274
+ export declare function listRequests(ctx: OperationContext, input?: {
275
+ subject?: EntityRef;
276
+ status?: RequestRow['status'];
277
+ }): AbsenceRequest[];
278
+ export declare function listEntries(ctx: OperationContext, input: {
279
+ subject: EntityRef;
280
+ leaveTypeKey?: string;
281
+ }): AbsenceEntry[];
282
+ /**
283
+ * Cross-subject window read — the payroll/export composition: "all bookings in
284
+ * this pay period", regardless of subject. In-scope only (no default binding):
285
+ * the callers are vertical exports that hold their own permission gate.
286
+ */
287
+ export declare function entriesInWindow(ctx: OperationContext, input: {
288
+ from: string;
289
+ to: string;
290
+ entryKind?: EntryRow['entry_kind'];
291
+ }): AbsenceEntry[];
292
+ export interface AbsenceDay {
293
+ date: string;
294
+ leaveTypeKey: string;
295
+ requestId: string;
296
+ }
297
+ /**
298
+ * The planner's read (D-C): every calendar day in an APPROVED request's
299
+ * inclusive range, clamped to [from, to]. The verdict is "an approved absence
300
+ * covers this date" — the engine does not know weekends or red days; the
301
+ * vertical composes this with its own holiday calendar.
302
+ */
303
+ export declare function availability(ctx: OperationContext, input: {
304
+ subject: EntityRef;
305
+ from: string;
306
+ to: string;
307
+ }): {
308
+ days: AbsenceDay[];
309
+ requests: AbsenceRequest[];
310
+ };
311
+ export declare const absenceModule: ModuleRegistration;
312
+ export {};
313
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,645 @@
1
+ import { z } from 'zod';
2
+ import { addDecimal, compareDecimal, dataSubjectId, entityRef, moduleManifest, permissionKey, } from '@substrat-run/contracts';
3
+ import { assertAllowed, ulid, } from '@substrat-run/kernel';
4
+ // ============================================================================
5
+ // The absence engine (docs/design/engine-absence.md). Owns an APPEND-ONLY entry
6
+ // ledger over an OPAQUE subject ref, balance-as-of-date as a pure fold, a
7
+ // per-leave-type balance floor, and the approval state machine that is the only
8
+ // mint for 'booking' and 'reversal' entries.
9
+ //
10
+ // It knows NOTHING about who a subject is (the vertical owns the directory),
11
+ // nor about weekends, red days, holiday calendars, accrual formulas, carryover
12
+ // caps, or what 'vab' means — all vertical policy. The `days` decimal on a
13
+ // request is vertical-computed; the engine folds it, it never derives it.
14
+ // Dates are calendar days, INCLUSIVE on both ends (absence is day-shaped) —
15
+ // deliberately unlike engine-booking's half-open instants.
16
+ // ============================================================================
17
+ export const PERM = {
18
+ read: permissionKey.parse('absence:read'),
19
+ request: permissionKey.parse('absence:request'),
20
+ approve: permissionKey.parse('absence:approve'),
21
+ configure: permissionKey.parse('absence:configure'),
22
+ };
23
+ export const absenceManifest = moduleManifest.parse({
24
+ id: '@substrat-run/engine-absence',
25
+ version: '0.0.1',
26
+ kernelContract: '^0.0.1',
27
+ permissions: [
28
+ { key: 'absence:read', description: 'Read balances, requests, entries and availability' },
29
+ { key: 'absence:request', description: 'Request absence (entity-narrowed: for one subject)' },
30
+ { key: 'absence:approve', description: 'Decide requests; cancel an approved absence' },
31
+ { key: 'absence:configure', description: 'Configure leave types; record accrual/correction/carryover entries' },
32
+ ],
33
+ events: {
34
+ emits: [
35
+ { type: 'absence.leave-type-configured', schemaVersion: 1 },
36
+ { type: 'absence.entry-recorded', schemaVersion: 1 },
37
+ { type: 'absence.requested', schemaVersion: 1 },
38
+ { type: 'absence.decided', schemaVersion: 1 },
39
+ { type: 'absence.cancelled', schemaVersion: 1 },
40
+ { type: 'absence.expired', schemaVersion: 1 },
41
+ ],
42
+ consumes: [],
43
+ },
44
+ migrations: { journalDir: './migrations', compatibleFrom: '0.0.1' },
45
+ attachmentTargets: [],
46
+ entityRelations: [],
47
+ entitlementKey: 'absence',
48
+ // A request still 'requested' past its start date can no longer be approved —
49
+ // a date-triggered rule (#383): the sweep cancels it under the system actor,
50
+ // never under a manager who never touched it.
51
+ schedules: [
52
+ {
53
+ operation: 'absence/expire-stale',
54
+ cadence: { everyMinutes: 1440 },
55
+ permissions: ['absence:approve'],
56
+ },
57
+ ],
58
+ });
59
+ export const absenceMigrations = [
60
+ {
61
+ version: '0001-init',
62
+ sql: `
63
+ CREATE TABLE absence_leave_types (
64
+ key TEXT PRIMARY KEY,
65
+ floor TEXT NOT NULL DEFAULT '0',
66
+ active INTEGER NOT NULL DEFAULT 1,
67
+ created_at TEXT NOT NULL
68
+ );
69
+ CREATE TABLE absence_ledger (
70
+ id TEXT PRIMARY KEY,
71
+ subject_type TEXT NOT NULL,
72
+ subject_id TEXT NOT NULL,
73
+ data_subject_id TEXT NOT NULL,
74
+ leave_type_key TEXT NOT NULL,
75
+ entry_kind TEXT NOT NULL CHECK (entry_kind IN
76
+ ('accrual','booking','correction','carryover','reversal')),
77
+ delta TEXT NOT NULL,
78
+ effective_date TEXT NOT NULL,
79
+ request_id TEXT,
80
+ note TEXT,
81
+ created_by TEXT NOT NULL,
82
+ created_at TEXT NOT NULL
83
+ );
84
+ CREATE TABLE absence_requests (
85
+ id TEXT PRIMARY KEY,
86
+ subject_type TEXT NOT NULL,
87
+ subject_id TEXT NOT NULL,
88
+ data_subject_id TEXT NOT NULL,
89
+ leave_type_key TEXT NOT NULL,
90
+ start_date TEXT NOT NULL,
91
+ end_date TEXT NOT NULL,
92
+ days TEXT NOT NULL,
93
+ status TEXT NOT NULL CHECK (status IN
94
+ ('requested','approved','rejected','cancelled')),
95
+ note TEXT,
96
+ decided_by TEXT,
97
+ decided_at TEXT,
98
+ created_by TEXT NOT NULL,
99
+ created_at TEXT NOT NULL
100
+ );
101
+ `,
102
+ },
103
+ ];
104
+ // ---------------------------------------------------------------------------
105
+ // Schemas & shapes
106
+ // ---------------------------------------------------------------------------
107
+ const isoDate = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'must be YYYY-MM-DD');
108
+ const posDecimal = z.string().regex(/^\d+(\.\d{1,6})?$/, 'must be a non-negative decimal');
109
+ const signedDecimal = z.string().regex(/^-?\d+(\.\d{1,6})?$/, 'must be a decimal');
110
+ /** Every write names its subject: the vertical's opaque noun + the erasure key. */
111
+ export const absenceSubject = z.object({
112
+ ref: entityRef,
113
+ dataSubjectId,
114
+ });
115
+ const toEntry = (r) => ({
116
+ id: r.id,
117
+ subject: { entityType: r.subject_type, entityId: r.subject_id },
118
+ leaveTypeKey: r.leave_type_key,
119
+ entryKind: r.entry_kind,
120
+ delta: r.delta,
121
+ effectiveDate: r.effective_date,
122
+ requestId: r.request_id,
123
+ note: r.note,
124
+ createdBy: r.created_by,
125
+ createdAt: r.created_at,
126
+ });
127
+ const toRequest = (r) => ({
128
+ id: r.id,
129
+ subject: { entityType: r.subject_type, entityId: r.subject_id },
130
+ leaveTypeKey: r.leave_type_key,
131
+ startDate: r.start_date,
132
+ endDate: r.end_date,
133
+ days: r.days,
134
+ status: r.status,
135
+ note: r.note,
136
+ decidedBy: r.decided_by,
137
+ decidedAt: r.decided_at,
138
+ createdBy: r.created_by,
139
+ createdAt: r.created_at,
140
+ });
141
+ const toLeaveType = (r) => ({
142
+ key: r.key,
143
+ floor: r.floor,
144
+ active: r.active === 1,
145
+ createdAt: r.created_at,
146
+ });
147
+ /** Negate a signed decimal string ('5' → '-5', '-5' → '5', '0' → '0'). */
148
+ const negate = (d) => compareDecimal(d, '0') === 0 ? '0' : d.startsWith('-') ? d.slice(1) : `-${d}`;
149
+ function getRequestRow(ctx, requestId) {
150
+ const row = ctx.sql.query('SELECT * FROM absence_requests WHERE id = ?', [
151
+ requestId,
152
+ ])[0];
153
+ if (!row)
154
+ throw new Error(`absence request not found: ${requestId}`);
155
+ return row;
156
+ }
157
+ function getLeaveTypeRow(ctx, key) {
158
+ const row = ctx.sql.query('SELECT * FROM absence_leave_types WHERE key = ?', [
159
+ key,
160
+ ])[0];
161
+ if (!row)
162
+ throw new Error(`leave type not found: ${key}`);
163
+ return row;
164
+ }
165
+ function getEntryRow(ctx, id) {
166
+ return ctx.sql.query('SELECT * FROM absence_ledger WHERE id = ?', [id])[0];
167
+ }
168
+ const subjectRefOf = (r) => ({
169
+ entityType: r.subject_type,
170
+ entityId: r.subject_id,
171
+ });
172
+ function insertEntry(ctx, input) {
173
+ const id = ulid();
174
+ ctx.sql.exec(`INSERT INTO absence_ledger
175
+ (id, subject_type, subject_id, data_subject_id, leave_type_key,
176
+ entry_kind, delta, effective_date, request_id, note, created_by, created_at)
177
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
178
+ id,
179
+ input.subject.ref.entityType,
180
+ input.subject.ref.entityId,
181
+ input.subject.dataSubjectId,
182
+ input.leaveTypeKey,
183
+ input.entryKind,
184
+ input.delta,
185
+ input.effectiveDate,
186
+ input.requestId ?? null,
187
+ input.note ?? null,
188
+ ctx.principal,
189
+ new Date().toISOString(),
190
+ ]);
191
+ const entry = toEntry(getEntryRow(ctx, id));
192
+ ctx.emit({
193
+ type: 'absence.entry-recorded',
194
+ schemaVersion: 1,
195
+ entity: input.subject.ref,
196
+ piiClass: 'pseudonymous',
197
+ subjectId: input.subject.dataSubjectId,
198
+ payload: {
199
+ entryId: id,
200
+ subject: input.subject.ref,
201
+ leaveTypeKey: input.leaveTypeKey,
202
+ entryKind: input.entryKind,
203
+ delta: input.delta,
204
+ effectiveDate: input.effectiveDate,
205
+ requestId: input.requestId ?? null,
206
+ },
207
+ });
208
+ return entry;
209
+ }
210
+ // ---------------------------------------------------------------------------
211
+ // In-scope functions (K-16) — composable from vertical operations, same
212
+ // transaction. The registered operations below are their default bindings.
213
+ // The CALLER is responsible for the permission check.
214
+ // ---------------------------------------------------------------------------
215
+ export const configureLeaveTypeInput = z.object({
216
+ key: z.string().min(1),
217
+ floor: signedDecimal.optional(),
218
+ active: z.boolean().optional(),
219
+ });
220
+ export function configureLeaveType(ctx, rawInput) {
221
+ const input = configureLeaveTypeInput.parse(rawInput);
222
+ ctx.sql.exec(`INSERT INTO absence_leave_types (key, floor, active, created_at)
223
+ VALUES (?, ?, ?, ?)
224
+ ON CONFLICT(key) DO UPDATE SET
225
+ floor = COALESCE(?, floor),
226
+ active = COALESCE(?, active)`, [
227
+ input.key,
228
+ input.floor ?? '0',
229
+ input.active === false ? 0 : 1,
230
+ new Date().toISOString(),
231
+ input.floor ?? null,
232
+ input.active === undefined ? null : input.active ? 1 : 0,
233
+ ]);
234
+ const row = getLeaveTypeRow(ctx, input.key);
235
+ ctx.emit({
236
+ type: 'absence.leave-type-configured',
237
+ schemaVersion: 1,
238
+ entity: { entityType: 'absence-leave-type', entityId: input.key },
239
+ piiClass: 'none',
240
+ payload: { key: row.key, floor: row.floor, active: row.active === 1 },
241
+ });
242
+ return toLeaveType(row);
243
+ }
244
+ export function listLeaveTypes(ctx) {
245
+ return ctx.sql
246
+ .query('SELECT * FROM absence_leave_types ORDER BY key')
247
+ .map(toLeaveType);
248
+ }
249
+ /**
250
+ * The one write that bypasses the request flow, restricted to accrual /
251
+ * correction / carryover — 'booking' and 'reversal' are mintable only through
252
+ * decideAbsence/cancelAbsence, which is what makes "only an approved request
253
+ * touches the ledger" a construction rather than a convention.
254
+ *
255
+ * No floor check here: a correction is the administrator's escape hatch, and
256
+ * accrual/carryover only ever add. The floor guards bookings (D-D).
257
+ */
258
+ export const recordEntryInput = z.object({
259
+ subject: absenceSubject,
260
+ leaveTypeKey: z.string().min(1),
261
+ entryKind: z.enum(['accrual', 'correction', 'carryover']),
262
+ delta: signedDecimal,
263
+ effectiveDate: isoDate,
264
+ note: z.string().optional(),
265
+ });
266
+ export function recordEntry(ctx, rawInput) {
267
+ const input = recordEntryInput.parse(rawInput);
268
+ getLeaveTypeRow(ctx, input.leaveTypeKey);
269
+ return insertEntry(ctx, input);
270
+ }
271
+ /** Balance = pure fold over entries with effective_date <= asOf. No counter exists. */
272
+ export function balanceAsOf(ctx, input) {
273
+ const asOf = input.asOf === undefined ? undefined : isoDate.parse(input.asOf);
274
+ const rows = asOf
275
+ ? ctx.sql.query(`SELECT delta FROM absence_ledger
276
+ WHERE subject_type = ? AND subject_id = ? AND leave_type_key = ? AND effective_date <= ?`, [input.subject.entityType, input.subject.entityId, input.leaveTypeKey, asOf])
277
+ : ctx.sql.query(`SELECT delta FROM absence_ledger
278
+ WHERE subject_type = ? AND subject_id = ? AND leave_type_key = ?`, [input.subject.entityType, input.subject.entityId, input.leaveTypeKey]);
279
+ return rows.reduce((sum, r) => addDecimal(sum, r.delta), '0');
280
+ }
281
+ export const requestAbsenceInput = z.object({
282
+ subject: absenceSubject,
283
+ leaveTypeKey: z.string().min(1),
284
+ startDate: isoDate,
285
+ endDate: isoDate,
286
+ days: posDecimal.refine((d) => compareDecimal(d, '0') > 0, 'days must be positive'),
287
+ note: z.string().optional(),
288
+ });
289
+ export function requestAbsence(ctx, rawInput) {
290
+ const input = requestAbsenceInput.parse(rawInput);
291
+ if (input.endDate < input.startDate) {
292
+ throw new Error(`endDate ${input.endDate} precedes startDate ${input.startDate}`);
293
+ }
294
+ const leaveType = getLeaveTypeRow(ctx, input.leaveTypeKey);
295
+ if (leaveType.active !== 1) {
296
+ throw new Error(`leave type '${input.leaveTypeKey}' is inactive`);
297
+ }
298
+ const id = ulid();
299
+ ctx.sql.exec(`INSERT INTO absence_requests
300
+ (id, subject_type, subject_id, data_subject_id, leave_type_key,
301
+ start_date, end_date, days, status, note, created_by, created_at)
302
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'requested', ?, ?, ?)`, [
303
+ id,
304
+ input.subject.ref.entityType,
305
+ input.subject.ref.entityId,
306
+ input.subject.dataSubjectId,
307
+ input.leaveTypeKey,
308
+ input.startDate,
309
+ input.endDate,
310
+ input.days,
311
+ input.note ?? null,
312
+ ctx.principal,
313
+ new Date().toISOString(),
314
+ ]);
315
+ ctx.emit({
316
+ type: 'absence.requested',
317
+ schemaVersion: 1,
318
+ entity: input.subject.ref,
319
+ piiClass: 'pseudonymous',
320
+ subjectId: input.subject.dataSubjectId,
321
+ payload: {
322
+ requestId: id,
323
+ subject: input.subject.ref,
324
+ leaveTypeKey: input.leaveTypeKey,
325
+ startDate: input.startDate,
326
+ endDate: input.endDate,
327
+ days: input.days,
328
+ },
329
+ });
330
+ return toRequest(getRequestRow(ctx, id));
331
+ }
332
+ export const decideAbsenceInput = z.object({
333
+ requestId: z.string().min(1),
334
+ decision: z.enum(['approve', 'reject']),
335
+ note: z.string().optional(),
336
+ });
337
+ export function decideAbsence(ctx, rawInput) {
338
+ const input = decideAbsenceInput.parse(rawInput);
339
+ const req = getRequestRow(ctx, input.requestId);
340
+ // The state machine cannot skip: only a 'requested' absence can be decided.
341
+ if (req.status !== 'requested') {
342
+ throw new Error(`absence request ${req.id} is '${req.status}' — only a requested absence can be decided`);
343
+ }
344
+ const now = new Date().toISOString();
345
+ const subject = {
346
+ ref: subjectRefOf(req),
347
+ dataSubjectId: dataSubjectId.parse(req.data_subject_id),
348
+ };
349
+ if (input.decision === 'reject') {
350
+ ctx.sql.exec(`UPDATE absence_requests SET status = 'rejected', decided_by = ?, decided_at = ?, note = COALESCE(?, note) WHERE id = ?`, [ctx.principal, now, input.note ?? null, req.id]);
351
+ ctx.emit({
352
+ type: 'absence.decided',
353
+ schemaVersion: 1,
354
+ entity: subject.ref,
355
+ piiClass: 'pseudonymous',
356
+ subjectId: subject.dataSubjectId,
357
+ payload: {
358
+ requestId: req.id,
359
+ subject: subject.ref,
360
+ leaveTypeKey: req.leave_type_key,
361
+ decision: 'rejected',
362
+ bookingId: null,
363
+ },
364
+ });
365
+ return { request: toRequest(getRequestRow(ctx, req.id)), booking: null };
366
+ }
367
+ // Approve. Re-fold at decision time — the world may have changed since the
368
+ // request. A booking that would take the fold below the type's floor is
369
+ // rejected by the engine, not the UI (D-D).
370
+ const leaveType = getLeaveTypeRow(ctx, req.leave_type_key);
371
+ const balance = balanceAsOf(ctx, { subject: subject.ref, leaveTypeKey: req.leave_type_key });
372
+ if (compareDecimal(addDecimal(balance, negate(req.days)), leaveType.floor) < 0) {
373
+ throw new Error(`insufficient balance: ${balance} day(s) of '${req.leave_type_key}' (floor ${leaveType.floor}), request needs ${req.days}`);
374
+ }
375
+ const booking = insertEntry(ctx, {
376
+ subject,
377
+ leaveTypeKey: req.leave_type_key,
378
+ entryKind: 'booking',
379
+ delta: negate(req.days),
380
+ effectiveDate: req.start_date,
381
+ requestId: req.id,
382
+ note: input.note,
383
+ });
384
+ ctx.sql.exec(`UPDATE absence_requests SET status = 'approved', decided_by = ?, decided_at = ? WHERE id = ?`, [ctx.principal, now, req.id]);
385
+ ctx.emit({
386
+ type: 'absence.decided',
387
+ schemaVersion: 1,
388
+ entity: subject.ref,
389
+ piiClass: 'pseudonymous',
390
+ subjectId: subject.dataSubjectId,
391
+ payload: {
392
+ requestId: req.id,
393
+ subject: subject.ref,
394
+ leaveTypeKey: req.leave_type_key,
395
+ decision: 'approved',
396
+ bookingId: booking.id,
397
+ days: req.days,
398
+ startDate: req.start_date,
399
+ endDate: req.end_date,
400
+ },
401
+ });
402
+ return { request: toRequest(getRequestRow(ctx, req.id)), booking };
403
+ }
404
+ /**
405
+ * requested → cancelled (withdraw; no ledger touch), or approved → cancelled
406
+ * with a COMPENSATING reversal entry — "Hugo came back" is a new entry, never
407
+ * an edit (D-E). Rejected/cancelled rows are terminal.
408
+ */
409
+ export const cancelAbsenceInput = z.object({
410
+ requestId: z.string().min(1),
411
+ reason: z.string().optional(),
412
+ });
413
+ export function cancelAbsence(ctx, rawInput) {
414
+ const input = cancelAbsenceInput.parse(rawInput);
415
+ const req = getRequestRow(ctx, input.requestId);
416
+ if (req.status !== 'requested' && req.status !== 'approved') {
417
+ throw new Error(`absence request ${req.id} is '${req.status}' — only requested or approved can be cancelled`);
418
+ }
419
+ const now = new Date().toISOString();
420
+ const subject = {
421
+ ref: subjectRefOf(req),
422
+ dataSubjectId: dataSubjectId.parse(req.data_subject_id),
423
+ };
424
+ let reversal = null;
425
+ if (req.status === 'approved') {
426
+ const booking = ctx.sql.query(`SELECT * FROM absence_ledger WHERE request_id = ? AND entry_kind = 'booking'`, [req.id])[0];
427
+ if (!booking)
428
+ throw new Error(`approved request ${req.id} has no booking entry — ledger integrity violated`);
429
+ reversal = insertEntry(ctx, {
430
+ subject,
431
+ leaveTypeKey: req.leave_type_key,
432
+ entryKind: 'reversal',
433
+ delta: negate(booking.delta),
434
+ effectiveDate: booking.effective_date,
435
+ requestId: req.id,
436
+ note: input.reason,
437
+ });
438
+ }
439
+ ctx.sql.exec(`UPDATE absence_requests SET status = 'cancelled', decided_at = ?, note = COALESCE(?, note) WHERE id = ?`, [now, input.reason ?? null, req.id]);
440
+ ctx.emit({
441
+ type: 'absence.cancelled',
442
+ schemaVersion: 1,
443
+ entity: subject.ref,
444
+ piiClass: 'pseudonymous',
445
+ subjectId: subject.dataSubjectId,
446
+ payload: {
447
+ requestId: req.id,
448
+ subject: subject.ref,
449
+ leaveTypeKey: req.leave_type_key,
450
+ priorStatus: req.status,
451
+ reversalId: reversal?.id ?? null,
452
+ },
453
+ });
454
+ return { request: toRequest(getRequestRow(ctx, req.id)), reversal };
455
+ }
456
+ /**
457
+ * A DATE-TRIGGERED rule with no caller but the passage of time (#383): a
458
+ * request still 'requested' once its start date has passed can no longer be
459
+ * approved, so the platform sweep cancels it — attributed to the schedule
460
+ * (`{ system }`), never to a manager who never touched it. Idempotent (only
461
+ * 'requested' rows past their start) and paged (a bounded batch per pass).
462
+ */
463
+ export function expireStaleRequests(ctx) {
464
+ const today = new Date().toISOString().slice(0, 10);
465
+ const stale = ctx.sql.query(`SELECT * FROM absence_requests
466
+ WHERE status = 'requested' AND start_date < ?
467
+ ORDER BY start_date LIMIT 100`, [today]);
468
+ const now = new Date().toISOString();
469
+ for (const req of stale) {
470
+ ctx.sql.exec(`UPDATE absence_requests
471
+ SET status = 'cancelled', decided_at = ?,
472
+ note = COALESCE(note, 'auto-expired: start date passed before approval')
473
+ WHERE id = ?`, [now, req.id]);
474
+ ctx.emit({
475
+ type: 'absence.expired',
476
+ schemaVersion: 1,
477
+ entity: subjectRefOf(req),
478
+ piiClass: 'pseudonymous',
479
+ subjectId: dataSubjectId.parse(req.data_subject_id),
480
+ payload: { requestId: req.id, subject: subjectRefOf(req), startDate: req.start_date },
481
+ });
482
+ }
483
+ return { expired: stale.length };
484
+ }
485
+ // ---------------------------------------------------------------------------
486
+ // Reads
487
+ // ---------------------------------------------------------------------------
488
+ export function listRequests(ctx, input) {
489
+ const where = [];
490
+ const params = [];
491
+ if (input?.subject) {
492
+ where.push('subject_type = ? AND subject_id = ?');
493
+ params.push(input.subject.entityType, input.subject.entityId);
494
+ }
495
+ if (input?.status) {
496
+ where.push('status = ?');
497
+ params.push(input.status);
498
+ }
499
+ const sql = `SELECT * FROM absence_requests${where.length ? ` WHERE ${where.join(' AND ')}` : ''} ORDER BY created_at DESC, id DESC`;
500
+ return ctx.sql.query(sql, params).map(toRequest);
501
+ }
502
+ export function listEntries(ctx, input) {
503
+ const rows = input.leaveTypeKey
504
+ ? ctx.sql.query(`SELECT * FROM absence_ledger
505
+ WHERE subject_type = ? AND subject_id = ? AND leave_type_key = ?
506
+ ORDER BY effective_date, id`, [input.subject.entityType, input.subject.entityId, input.leaveTypeKey])
507
+ : ctx.sql.query(`SELECT * FROM absence_ledger
508
+ WHERE subject_type = ? AND subject_id = ?
509
+ ORDER BY effective_date, id`, [input.subject.entityType, input.subject.entityId]);
510
+ return rows.map(toEntry);
511
+ }
512
+ /**
513
+ * Cross-subject window read — the payroll/export composition: "all bookings in
514
+ * this pay period", regardless of subject. In-scope only (no default binding):
515
+ * the callers are vertical exports that hold their own permission gate.
516
+ */
517
+ export function entriesInWindow(ctx, input) {
518
+ const from = isoDate.parse(input.from);
519
+ const to = isoDate.parse(input.to);
520
+ const rows = input.entryKind
521
+ ? ctx.sql.query(`SELECT * FROM absence_ledger
522
+ WHERE effective_date >= ? AND effective_date <= ? AND entry_kind = ?
523
+ ORDER BY subject_id, effective_date, id`, [from, to, input.entryKind])
524
+ : ctx.sql.query(`SELECT * FROM absence_ledger
525
+ WHERE effective_date >= ? AND effective_date <= ?
526
+ ORDER BY subject_id, effective_date, id`, [from, to]);
527
+ return rows.map(toEntry);
528
+ }
529
+ /** Walk YYYY-MM-DD dates inclusively without timezone drift (UTC arithmetic). */
530
+ function* eachDate(from, to) {
531
+ const end = Date.UTC(Number(to.slice(0, 4)), Number(to.slice(5, 7)) - 1, Number(to.slice(8, 10)));
532
+ let cur = Date.UTC(Number(from.slice(0, 4)), Number(from.slice(5, 7)) - 1, Number(from.slice(8, 10)));
533
+ while (cur <= end) {
534
+ yield new Date(cur).toISOString().slice(0, 10);
535
+ cur += 86_400_000;
536
+ }
537
+ }
538
+ /**
539
+ * The planner's read (D-C): every calendar day in an APPROVED request's
540
+ * inclusive range, clamped to [from, to]. The verdict is "an approved absence
541
+ * covers this date" — the engine does not know weekends or red days; the
542
+ * vertical composes this with its own holiday calendar.
543
+ */
544
+ export function availability(ctx, input) {
545
+ const from = isoDate.parse(input.from);
546
+ const to = isoDate.parse(input.to);
547
+ if (to < from)
548
+ throw new Error(`to ${to} precedes from ${from}`);
549
+ const rows = ctx.sql.query(`SELECT * FROM absence_requests
550
+ WHERE subject_type = ? AND subject_id = ? AND status = 'approved'
551
+ AND start_date <= ? AND end_date >= ?
552
+ ORDER BY start_date, id`, [input.subject.entityType, input.subject.entityId, to, from]);
553
+ const days = [];
554
+ for (const req of rows) {
555
+ const start = req.start_date < from ? from : req.start_date;
556
+ const end = req.end_date > to ? to : req.end_date;
557
+ for (const date of eachDate(start, end)) {
558
+ days.push({ date, leaveTypeKey: req.leave_type_key, requestId: req.id });
559
+ }
560
+ }
561
+ return { days, requests: rows.map(toRequest) };
562
+ }
563
+ // ---------------------------------------------------------------------------
564
+ // Default operation bindings — each starts with the permission check.
565
+ // ---------------------------------------------------------------------------
566
+ const configureLeaveTypeOp = async (ctx, input) => {
567
+ assertAllowed(await ctx.check(PERM.configure));
568
+ return configureLeaveType(ctx, input);
569
+ };
570
+ const listLeaveTypesOp = async (ctx) => {
571
+ assertAllowed(await ctx.check(PERM.read));
572
+ return listLeaveTypes(ctx);
573
+ };
574
+ const recordEntryOp = async (ctx, input) => {
575
+ assertAllowed(await ctx.check(PERM.configure));
576
+ return recordEntry(ctx, input);
577
+ };
578
+ const requestOp = async (ctx, raw) => {
579
+ const input = requestAbsenceInput.parse(raw);
580
+ // Entity-narrowed: a subject requests for THEMSELVES through a grant on their
581
+ // own ref, holding no role; an unnarrowed holder may request for anyone.
582
+ assertAllowed(await ctx.check(PERM.request, input.subject.ref));
583
+ return requestAbsence(ctx, input);
584
+ };
585
+ const decideOp = async (ctx, input) => {
586
+ assertAllowed(await ctx.check(PERM.approve));
587
+ return decideAbsence(ctx, input);
588
+ };
589
+ const cancelOp = async (ctx, raw) => {
590
+ const input = cancelAbsenceInput.parse(raw);
591
+ // An approver cancels anything cancellable; the subject may WITHDRAW their
592
+ // own still-requested row through the same entity-narrowed grant they
593
+ // requested with.
594
+ const asApprover = await ctx.check(PERM.approve);
595
+ if (!asApprover.allowed) {
596
+ const req = getRequestRow(ctx, input.requestId);
597
+ if (req.status !== 'requested')
598
+ assertAllowed(asApprover);
599
+ assertAllowed(await ctx.check(PERM.request, subjectRefOf(req)));
600
+ }
601
+ return cancelAbsence(ctx, input);
602
+ };
603
+ const expireStaleOp = async (ctx) => {
604
+ assertAllowed(await ctx.check(PERM.approve));
605
+ return expireStaleRequests(ctx);
606
+ };
607
+ const balanceOp = async (ctx, input) => {
608
+ assertAllowed(await ctx.check(PERM.read, entityRef.parse(input.subject)));
609
+ return { balance: balanceAsOf(ctx, input) };
610
+ };
611
+ const availabilityOp = async (ctx, input) => {
612
+ assertAllowed(await ctx.check(PERM.read, entityRef.parse(input.subject)));
613
+ return availability(ctx, input);
614
+ };
615
+ const listRequestsOp = async (ctx, input) => {
616
+ if (input?.subject) {
617
+ assertAllowed(await ctx.check(PERM.read, entityRef.parse(input.subject)));
618
+ }
619
+ else {
620
+ assertAllowed(await ctx.check(PERM.read));
621
+ }
622
+ return listRequests(ctx, input);
623
+ };
624
+ const listEntriesOp = async (ctx, input) => {
625
+ assertAllowed(await ctx.check(PERM.read, entityRef.parse(input.subject)));
626
+ return listEntries(ctx, input);
627
+ };
628
+ export const absenceModule = {
629
+ manifest: absenceManifest,
630
+ migrations: absenceMigrations,
631
+ operations: {
632
+ 'absence/configure-leave-type': configureLeaveTypeOp,
633
+ 'absence/list-leave-types': listLeaveTypesOp,
634
+ 'absence/record-entry': recordEntryOp,
635
+ 'absence/request': requestOp,
636
+ 'absence/decide': decideOp,
637
+ 'absence/cancel': cancelOp,
638
+ 'absence/expire-stale': expireStaleOp,
639
+ 'absence/balance': balanceOp,
640
+ 'absence/availability': availabilityOp,
641
+ 'absence/list-requests': listRequestsOp,
642
+ 'absence/list-entries': listEntriesOp,
643
+ },
644
+ };
645
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@substrat-run/engine-absence",
3
- "version": "0.0.0",
3
+ "version": "0.1.0",
4
4
  "description": "Substrat engine: approved absence — an append-only entry ledger over an opaque subject, balance as a fold, approval as a state machine",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
@@ -24,19 +24,19 @@
24
24
  "publishConfig": {
25
25
  "access": "public"
26
26
  },
27
- "scripts": {
28
- "build": "tsc -p tsconfig.json",
29
- "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
30
- "test": "vitest run"
31
- },
32
27
  "dependencies": {
33
- "@substrat-run/contracts": "workspace:^",
34
- "@substrat-run/kernel": "workspace:^",
35
- "zod": "^4.4.3"
28
+ "zod": "^4.4.3",
29
+ "@substrat-run/contracts": "^0.65.0",
30
+ "@substrat-run/kernel": "^0.65.0"
36
31
  },
37
32
  "devDependencies": {
38
33
  "typescript": "^7.0.0",
39
- "@substrat-run/engine-test-kit": "workspace:^",
40
- "vitest": "^3.0.0"
34
+ "vitest": "^3.0.0",
35
+ "@substrat-run/engine-test-kit": "^0.0.63"
36
+ },
37
+ "scripts": {
38
+ "build": "tsc -p tsconfig.json",
39
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
40
+ "test": "vitest run"
41
41
  }
42
- }
42
+ }