@happyvertical/smrt-timesheets 0.55.6 → 0.55.8

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.
@@ -3,12 +3,12 @@
3
3
  "sensitiveFieldsExcluded": true,
4
4
  "generatedAt": "1970-01-01T00:00:00.000Z",
5
5
  "packageName": "@happyvertical/smrt-timesheets",
6
- "packageVersion": "0.55.6",
6
+ "packageVersion": "0.55.8",
7
7
  "sourceManifestPath": "dist/manifest.json",
8
8
  "agentDocPath": "AGENTS.md",
9
9
  "sourceHashes": {
10
- "manifest": "dca77590390720e2538030f3de93961230cdbffeb295bf70856666998768c05e",
11
- "packageJson": "b5603254e13ce010538aa70aa50285fca380f95904a423d1717b9172103b2883",
10
+ "manifest": "692d7363f11574b95c854605f49dd62c91e02a539c1a969498b2449a31873b4e",
11
+ "packageJson": "2263f0db0c684223c4f6ea65602f43c114a6aa3b52d51d0e33282017eebf2b1e",
12
12
  "agents": "46a4e8437424b494645e90ce4a4869be04956c5da6a42f89697cbd3ab2199a7e",
13
13
  "moduleDoc:agents/period-rollup.md": "5fb741659d81dbef2e4850c10c2d65f09e3f5a83e8a88e2e0f19585f25158a6a"
14
14
  },
@@ -65,6 +65,7 @@
65
65
  "name": "AttendancePunch",
66
66
  "qualifiedName": "@happyvertical/smrt-timesheets:AttendancePunch",
67
67
  "collection": "attendancepunches",
68
+ "description": "A tenant-scoped interval of attendance, independent of billable work.",
68
69
  "tableName": "attendance_punches",
69
70
  "packageName": "@happyvertical/smrt-timesheets",
70
71
  "extends": "SmrtObject",
@@ -235,6 +236,7 @@
235
236
  "name": "AttendanceBreak",
236
237
  "qualifiedName": "@happyvertical/smrt-timesheets:AttendanceBreak",
237
238
  "collection": "attendancebreaks",
239
+ "description": "A paid or unpaid break inside one attendance punch.",
238
240
  "tableName": "attendance_breaks",
239
241
  "packageName": "@happyvertical/smrt-timesheets",
240
242
  "extends": "SmrtObject",
@@ -369,6 +371,7 @@
369
371
  "name": "AttendanceReplay",
370
372
  "qualifiedName": "@happyvertical/smrt-timesheets:AttendanceReplay",
371
373
  "collection": "attendancereplays",
374
+ "description": "Durable offline-tap outcome; never exposed through generated operations.",
372
375
  "tableName": "attendance_replays",
373
376
  "packageName": "@happyvertical/smrt-timesheets",
374
377
  "extends": "SmrtObject",
@@ -466,6 +469,7 @@
466
469
  "name": "AttendancePunchCollection",
467
470
  "qualifiedName": "@happyvertical/smrt-timesheets:AttendancePunchCollection",
468
471
  "collection": "attendancepunches",
472
+ "description": "Punches for attendance and period rollup.",
469
473
  "tableName": "attendance_punches",
470
474
  "packageName": "@happyvertical/smrt-timesheets",
471
475
  "extends": "SmrtCollection",
@@ -483,6 +487,7 @@
483
487
  "name": "AttendanceBreakCollection",
484
488
  "qualifiedName": "@happyvertical/smrt-timesheets:AttendanceBreakCollection",
485
489
  "collection": "attendancebreaks",
490
+ "description": "Break intervals for net duration and period clipping.",
486
491
  "tableName": "attendance_breaks",
487
492
  "packageName": "@happyvertical/smrt-timesheets",
488
493
  "extends": "SmrtCollection",
@@ -500,6 +505,7 @@
500
505
  "name": "AttendanceReplayCollection",
501
506
  "qualifiedName": "@happyvertical/smrt-timesheets:AttendanceReplayCollection",
502
507
  "collection": "attendancereplays",
508
+ "description": "Internal durable replay ledger.",
503
509
  "tableName": "attendance_replays",
504
510
  "packageName": "@happyvertical/smrt-timesheets",
505
511
  "extends": "SmrtCollection",
@@ -520,6 +526,7 @@
520
526
  "@happyvertical/smrt-projects:ServiceChargeSnapshot"
521
527
  ],
522
528
  "collection": "servicechargesnapshots",
529
+ "description": "Immutable client-charge snapshot for one approved time entry. Money is integer minor units, consistent with smrt-commerce (#2401).",
523
530
  "tableName": "service_charge_snapshots",
524
531
  "packageName": "@happyvertical/smrt-timesheets",
525
532
  "extends": "SmrtObject",
@@ -686,6 +693,7 @@
686
693
  "@happyvertical/smrt-projects:ServiceCompensationSnapshot"
687
694
  ],
688
695
  "collection": "servicecompensationsnapshots",
696
+ "description": "Immutable provider-compensation snapshot for one approved time entry, kept separate from the client charge so the margin is charge - compensation.",
689
697
  "tableName": "service_compensation_snapshots",
690
698
  "packageName": "@happyvertical/smrt-timesheets",
691
699
  "extends": "SmrtObject",
@@ -837,6 +845,7 @@
837
845
  "name": "ServiceChargeSnapshotCollection",
838
846
  "qualifiedName": "@happyvertical/smrt-timesheets:ServiceChargeSnapshotCollection",
839
847
  "collection": "servicechargesnapshots",
848
+ "description": "Collection over service_charge_snapshots.",
840
849
  "tableName": "service_charge_snapshots",
841
850
  "packageName": "@happyvertical/smrt-timesheets",
842
851
  "extends": "SmrtCollection",
@@ -854,6 +863,7 @@
854
863
  "name": "ServiceCompensationSnapshotCollection",
855
864
  "qualifiedName": "@happyvertical/smrt-timesheets:ServiceCompensationSnapshotCollection",
856
865
  "collection": "servicecompensationsnapshots",
866
+ "description": "Collection over service_compensation_snapshots.",
857
867
  "tableName": "service_compensation_snapshots",
858
868
  "packageName": "@happyvertical/smrt-timesheets",
859
869
  "extends": "SmrtCollection",
@@ -874,6 +884,7 @@
874
884
  "@happyvertical/smrt-projects:ServiceTimeEntry"
875
885
  ],
876
886
  "collection": "servicetimeentries",
887
+ "description": "A person or agent worked this long on this thing, and someone approved it.",
877
888
  "tableName": "service_time_entries",
878
889
  "packageName": "@happyvertical/smrt-timesheets",
879
890
  "extends": "SmrtObject",
@@ -1245,6 +1256,7 @@
1245
1256
  "name": "ServiceTimeEntryCollection",
1246
1257
  "qualifiedName": "@happyvertical/smrt-timesheets:ServiceTimeEntryCollection",
1247
1258
  "collection": "servicetimeentries",
1259
+ "description": "Collection over service_time_entries.",
1248
1260
  "tableName": "service_time_entries",
1249
1261
  "packageName": "@happyvertical/smrt-timesheets",
1250
1262
  "extends": "SmrtCollection",
@@ -1322,6 +1334,7 @@
1322
1334
  "name": "PeriodTimecard",
1323
1335
  "qualifiedName": "@happyvertical/smrt-timesheets:PeriodTimecard",
1324
1336
  "collection": "periodtimecards",
1337
+ "description": "One person's immutable-on-confirmation period snapshot, in integer seconds.",
1325
1338
  "tableName": "period_timecards",
1326
1339
  "packageName": "@happyvertical/smrt-timesheets",
1327
1340
  "extends": "SmrtObject",
@@ -1503,6 +1516,7 @@
1503
1516
  "name": "TimecardAdjustment",
1504
1517
  "qualifiedName": "@happyvertical/smrt-timesheets:TimecardAdjustment",
1505
1518
  "collection": "timecardadjustments",
1519
+ "description": "Attributed append-only signed seconds; the confirmed base card never changes.",
1506
1520
  "tableName": "timecard_adjustments",
1507
1521
  "packageName": "@happyvertical/smrt-timesheets",
1508
1522
  "extends": "SmrtObject",
@@ -1632,6 +1646,7 @@
1632
1646
  "name": "PeriodTimecardCollection",
1633
1647
  "qualifiedName": "@happyvertical/smrt-timesheets:PeriodTimecardCollection",
1634
1648
  "collection": "periodtimecards",
1649
+ "description": "Scoped persistence collection; mutations must use PeriodRollupService.",
1635
1650
  "tableName": "period_timecards",
1636
1651
  "packageName": "@happyvertical/smrt-timesheets",
1637
1652
  "extends": "SmrtCollection",
@@ -1649,6 +1664,7 @@
1649
1664
  "name": "TimecardAdjustmentCollection",
1650
1665
  "qualifiedName": "@happyvertical/smrt-timesheets:TimecardAdjustmentCollection",
1651
1666
  "collection": "timecardadjustments",
1667
+ "description": "Scoped append-only adjustment collection.",
1652
1668
  "tableName": "timecard_adjustments",
1653
1669
  "packageName": "@happyvertical/smrt-timesheets",
1654
1670
  "extends": "SmrtCollection",
@@ -1921,5 +1937,15 @@
1921
1937
  "module": "period-rollup",
1922
1938
  "content": "# Period timecards\n\n`@happyvertical/smrt-timesheets/rollup` exports `PeriodRollupService`,\n`PeriodTimecard`, `TimecardAdjustment`, their collections, and resolver types.\nThe package root also exports them. SQLite and PostgreSQL are supported.\nCreate application tables through normal migrations; neither service provisions\nschema. The attendance option additionally requires the attendance tables.\n\nConstruct a service only after authenticating and authorizing its trusted\n`{ tenantId, profileId }` scope. A conflicting ambient tenant is rejected.\n`options.actorProfileId` records a separately authorized supervisor; it defaults\nto the subject profile for self confirmation/correction. Never accept this\ntrusted scope or attribution unchecked from request input. Profile authorization\nis consumer-owned; the service filters every source/card/adjustment read by its\ntrusted subject and tenant. Generic API, CLI and MCP surfaces are closed by\ndefault; consumer registry overrides may further restrict them (#3318).\n\n## Resolver contract\n\n`periodFor(at, actor)` supplies half-open UTC `startsAt`/`endsAt`, an IANA\n`timezone`, a nonempty policy `version`, and a JSON `rules` snapshot.\nThe consumer owns period length, calendar start day, timezone and DST, overtime\nthresholds, holidays and classification. The requested instant must be inside\nthe window. Overlapping windows for existing cards are rejected: introduce a new\ncalendar at a boundary after existing windows, and use adjustments for already\nconfirmed periods.\n\n`classify(period, sources, actor)` returns nonnegative safe integer\n`regularSeconds` and `overtimeSeconds`, whose sum must equal source seconds.\nInputs are detached so resolver mutation cannot rewrite evidence. Resolver\nexceptions, malformed windows, invalid timezone, fractional/unsafe totals and\nnonconserving classification abort the transaction. No Alberta or other\njurisdiction rule is assumed, and no pay rate or money is stored.\n\nA configurable UTC calendar example (illustrative policy, not payroll advice):\n\n```ts\nimport { PeriodRollupService, type PeriodRulesResolver } from\n '@happyvertical/smrt-timesheets/rollup';\n\nconst settings = {\n lengthDays: 14, startDay: 1, timezone: 'UTC', // 0 = Sunday\n anchor: '2026-01-05T00:00:00Z', // aligned Monday; anchors fortnight phase\n thresholdSeconds: 80 * 3600,\n holidays: ['2026-12-25'],\n};\nconst resolver: PeriodRulesResolver = {\n async periodFor(at) {\n const anchor = new Date(settings.anchor);\n if (anchor.getUTCDay() !== settings.startDay || settings.timezone !== 'UTC')\n throw new Error('Use a timezone-aware calendar resolver for local periods');\n const length = settings.lengthDays * 86400000;\n const start = anchor.getTime() +\n Math.floor((at.getTime() - anchor.getTime()) / length) * length;\n return {\n startsAt: new Date(start), endsAt: new Date(start + length),\n timezone: settings.timezone, version: 'shop-policy-v1', rules: settings,\n };\n },\n async classify(period, sources) {\n const rules = period.rules as typeof settings;\n // This example assigns a contribution to its clipped start's UTC date.\n // Local daily rules should split contributions at their own local midnight.\n let regular = 0;\n let holiday = 0;\n for (const source of sources) {\n if (rules.holidays.includes(source.startsAt.slice(0, 10))) holiday += source.seconds;\n else regular += source.seconds;\n }\n return {\n regularSeconds: Math.min(regular, rules.thresholdSeconds),\n overtimeSeconds: holiday + Math.max(0, regular - rules.thresholdSeconds),\n };\n },\n};\nconst rollups = new PeriodRollupService(db, authorizedSubject, resolver,\n { attendance: true, actorProfileId: authenticatedSupervisorProfileId });\nconst card = await rollups.rollup(new Date());\nawait rollups.confirm(card.id!);\nawait rollups.adjust(card.id!, {\n operationId: requestId, regularSeconds: 900, overtimeSeconds: 0,\n reason: 'Approved correction after confirmation',\n});\nconst effectiveSeconds = await rollups.totals(card.id!);\n```\n\nA timezone-aware resolver must compute each local boundary separately: a local\nday crossing DST is not necessarily 86400 seconds. Resolvers can use an app's\nexisting calendar library; no new timezone dependency or implicit default is\nintroduced here.\n\n## Evidence and immutability\n\nDecimal-hours-only entries have no measured integer seconds. The seconds-only\nrollup rejects these sources explicitly when their approval instant falls in the\nrequested period; it never rounds them or counts null as\nzero. Use an hours-aware consumer policy for that source representation.\n\nOnly approved human `ServiceTimeEntry` rows for the subject count; corrected\nancestors do not. Correction chains must remain within that subject/tenant and\npoint to corrected parents. Multiple approved descendants of one root are\nrejected as ambiguous rather than double-counted. Entries with both `startedAt`\nand `endedAt` allocate their declared seconds\nproportionally across the period using exact integer prefix division, preserving\nseconds over adjacent periods. Unbounded entries count at `startedAt`, or, when\nabsent, `approvedAt`; an end-only timestamp does not create an interval. Missing\nboth attribution timestamps is an error. This is time attribution, not a\nclaim that a manual entry has a continuous wall-clock duration.\n\nWith `attendance: true`, closed punches without `reviewRequired` count, excluding\nunpaid breaks and retaining paid breaks. Open/review-required punches do not\ncount. Linked attendance is authoritative: its evidence entry and any approved\ncorrection descendants are excluded, including when the punch is still under\nreview or outside the requested period. Unlinked approved work entries and\nattendance both count; consumers must link overlapping evidence explicitly.\nSource snapshots preserve each paid attendance segment and entry identity.\n\nRepeated rollup updates one open card per tenant/person/start; a confirmed card\ncannot be recomputed. Confirmation is attributed and idempotent. Model save,\ncollection create/update/upsert and object/collection delete cannot bypass the\nservice. Model mutation capabilities are per-instance and not exported.\nDirect SQL is a trusted administrative boundary, not an exposed application API.\nProfile/card foreign keys restrict deletion to preserve history.\n\nAdjustments contain signed integer regular/overtime deltas, reason, operation\nkey and actor attribution. A retry reuses its row only for the exact same\npayload and actor. Effective totals may never become negative or unsafe.\nAdjustments never alter the confirmed row or source snapshot. Undo an adjustment\nwith a separately attributed compensating adjustment, never deletion.\n\nAll service mutations use a root transaction, transaction-bound collections,\nembedded writer serialization or a PostgreSQL tenant/person advisory lock.\nOutputs are reloaded on the root executor after commit. Rollup reads are an\napplication snapshot: subsequent source approvals/corrections appear on the\nnext open rollup, and confirmed cards require explicit adjustments.\n"
1923
1939
  }
1924
- ]
1940
+ ],
1941
+ "browser": {
1942
+ "status": "server-only",
1943
+ "issues": [
1944
+ "#3624"
1945
+ ],
1946
+ "reason": "node:crypto",
1947
+ "via": [
1948
+ "@happyvertical/smrt-tenancy"
1949
+ ]
1950
+ }
1925
1951
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-timesheets",
3
- "version": "0.55.6",
3
+ "version": "0.55.8",
4
4
  "smrtJsdoc": "strict",
5
5
  "description": "Shared time entries for the SMRT framework: who worked how long on what, approval and correction, with immutable charge and compensation snapshots",
6
6
  "type": "module",
@@ -39,11 +39,11 @@
39
39
  }
40
40
  },
41
41
  "dependencies": {
42
- "@happyvertical/smrt-core": "0.55.6",
43
- "@happyvertical/smrt-tenancy": "0.55.6",
44
- "@happyvertical/smrt-types": "0.55.6",
45
- "@happyvertical/smrt-ui": "0.55.6",
46
- "@happyvertical/sql": "^0.102.4"
42
+ "@happyvertical/smrt-core": "0.55.8",
43
+ "@happyvertical/smrt-tenancy": "0.55.8",
44
+ "@happyvertical/smrt-types": "0.55.8",
45
+ "@happyvertical/smrt-ui": "0.55.8",
46
+ "@happyvertical/sql": "^0.103.1"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "svelte": "^5.57.0"
@@ -54,7 +54,7 @@
54
54
  }
55
55
  },
56
56
  "devDependencies": {
57
- "@happyvertical/smrt-vitest": "0.55.6",
57
+ "@happyvertical/smrt-vitest": "0.55.8",
58
58
  "@sveltejs/package": "^2.5.8",
59
59
  "@sveltejs/vite-plugin-svelte": "^7.3.0",
60
60
  "@types/node": "24.13.6",