@happyvertical/smrt-timesheets 0.0.0-stage → 0.53.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 (65) hide show
  1. package/AGENTS.md +105 -0
  2. package/CLAUDE.md +1 -0
  3. package/LICENSE +7 -0
  4. package/README.md +242 -2
  5. package/dist/__smrt-register__.d.ts +2 -0
  6. package/dist/__smrt-register__.d.ts.map +1 -0
  7. package/dist/index.d.ts +20 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +495 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/manifest.json +1412 -0
  12. package/dist/models/index.d.ts +3 -0
  13. package/dist/models/index.d.ts.map +1 -0
  14. package/dist/models/json.d.ts +6 -0
  15. package/dist/models/json.d.ts.map +1 -0
  16. package/dist/models/service-snapshots.d.ts +66 -0
  17. package/dist/models/service-snapshots.d.ts.map +1 -0
  18. package/dist/models/service-time-entry.d.ts +66 -0
  19. package/dist/models/service-time-entry.d.ts.map +1 -0
  20. package/dist/services/index.d.ts +2 -0
  21. package/dist/services/index.d.ts.map +1 -0
  22. package/dist/services/service-evidence-service.d.ts +67 -0
  23. package/dist/services/service-evidence-service.d.ts.map +1 -0
  24. package/dist/smrt-knowledge.json +1016 -0
  25. package/dist/svelte/components/DurationDisplay.svelte +81 -0
  26. package/dist/svelte/components/DurationDisplay.svelte.d.ts +20 -0
  27. package/dist/svelte/components/DurationDisplay.svelte.d.ts.map +1 -0
  28. package/dist/svelte/components/TimeEntryApprovalQueue.svelte +253 -0
  29. package/dist/svelte/components/TimeEntryApprovalQueue.svelte.d.ts +15 -0
  30. package/dist/svelte/components/TimeEntryApprovalQueue.svelte.d.ts.map +1 -0
  31. package/dist/svelte/components/TimeEntryCard.svelte +304 -0
  32. package/dist/svelte/components/TimeEntryCard.svelte.d.ts +25 -0
  33. package/dist/svelte/components/TimeEntryCard.svelte.d.ts.map +1 -0
  34. package/dist/svelte/components/TimeEntryList.svelte +360 -0
  35. package/dist/svelte/components/TimeEntryList.svelte.d.ts +24 -0
  36. package/dist/svelte/components/TimeEntryList.svelte.d.ts.map +1 -0
  37. package/dist/svelte/components/TimeSummary.svelte +176 -0
  38. package/dist/svelte/components/TimeSummary.svelte.d.ts +30 -0
  39. package/dist/svelte/components/TimeSummary.svelte.d.ts.map +1 -0
  40. package/dist/svelte/components/__tests__/DurationDisplay.test.js +57 -0
  41. package/dist/svelte/components/__tests__/TimeEntryApprovalQueue.test.js +114 -0
  42. package/dist/svelte/components/__tests__/TimeEntryCard.test.js +45 -0
  43. package/dist/svelte/components/__tests__/TimeEntryList.test.js +50 -0
  44. package/dist/svelte/components/__tests__/TimeSummary.test.js +39 -0
  45. package/dist/svelte/components/utils.d.ts +51 -0
  46. package/dist/svelte/components/utils.d.ts.map +1 -0
  47. package/dist/svelte/components/utils.js +58 -0
  48. package/dist/svelte/i18n.d.ts +31 -0
  49. package/dist/svelte/i18n.d.ts.map +1 -0
  50. package/dist/svelte/i18n.js +31 -0
  51. package/dist/svelte/index.d.ts +25 -0
  52. package/dist/svelte/index.d.ts.map +1 -0
  53. package/dist/svelte/index.js +27 -0
  54. package/dist/svelte/types.d.ts +41 -0
  55. package/dist/svelte/types.d.ts.map +1 -0
  56. package/dist/svelte/types.js +28 -0
  57. package/dist/types.d.ts +29 -0
  58. package/dist/types.d.ts.map +1 -0
  59. package/dist/types.js +16 -0
  60. package/dist/types.js.map +1 -0
  61. package/dist/ui.d.ts +17 -0
  62. package/dist/ui.d.ts.map +1 -0
  63. package/dist/ui.js +68 -0
  64. package/dist/ui.js.map +1 -0
  65. package/package.json +85 -3
package/AGENTS.md ADDED
@@ -0,0 +1,105 @@
1
+ # smrt-timesheets
2
+
3
+ Shared time entries: who (a `smrt-profiles` Profile, or an agent) worked how
4
+ long on what (a generic work reference), whether it was approved, and the
5
+ immutable charge / compensation snapshots taken at approval. Moved out of
6
+ `smrt-projects` / `smrt-support` in #3288 so shops, builders, and service
7
+ desks share one model instead of re-implementing it.
8
+
9
+ This package is **layer 1 (entry)**. Attendance (punches, breaks, offline
10
+ replay) and period rollup (per-person timecards) are planned as later modules
11
+ of this same package; do not add them to projects or support.
12
+
13
+ ## Models
14
+
15
+ | Model | Table | Notes |
16
+ |---|---|---|
17
+ | `ServiceTimeEntry` | `service_time_entries` | `workRefType` + `workRefId`, `participantKind` (`human` \| `agent`), `participantProfileId` / `agentRef`, `source`, `startedAt` / `endedAt` / `durationSeconds`, status machine, `correctionOfId` |
18
+ | `ServiceChargeSnapshot` | `service_charge_snapshots` | Client charge, integer minor units (#2401), one per entry |
19
+ | `ServiceCompensationSnapshot` | `service_compensation_snapshots` | Provider earning, integer minor units, one per entry |
20
+
21
+ `ServiceEvidenceService` records, submits, approves (writing both snapshots
22
+ through a `ServiceCommercialResolver`), and corrects. `smrt-projects` supplies
23
+ `SubscriptionServiceCommercialResolver` for #1925 pricing.
24
+
25
+ ## Invariants
26
+
27
+ - **No domain foreign key on the base.** Work context is the generic
28
+ `workRefType` (qualified class name) + `workRefId`. A domain adds its own
29
+ context by subclassing over the same table — smrt-support's
30
+ `ServiceTimeEntry` adds `caseId` / `specialistId` and extends
31
+ `frozenFieldNames()` so they freeze on approval.
32
+ - **Entries carry no rate.** Money lives only on the snapshots, `= 0`
33
+ integer initializers (INTEGER columns). Never `= 0.0`. Snapshot `save()`
34
+ rejects an `amount` that is not a safe integer (`VALIDATION_INVALID_VALUE`),
35
+ so SQLite cannot silently store `19.99`; fix a fractional resolver at its
36
+ source rather than rounding here.
37
+ - **Approved evidence never changes.** `save()` enforces
38
+ `SERVICE_TIME_ENTRY_STATUS_TRANSITIONS` and compares the frozen fields with
39
+ the stored row. A correction is a new row (`correctionOfId`), the original
40
+ flips to `corrected`. Snapshots are immutable after their first save.
41
+ - **Old qualified names are aliases.** Each model declares its pre-#3288
42
+ `@happyvertical/smrt-projects:*` name in `previousQualifiedNames` (#3338;
43
+ `packages/core/agents/model-moves.md`). smrt-projects must never list these
44
+ classes in its manifests again (`CONFIG_QUALIFIED_NAME_ALIAS_COLLISION`),
45
+ and no subtype (smrt-support's, or a consumer's closing subclass) may
46
+ redeclare an alias (two claimants). Known gap: a same-named subtype that
47
+ replaces a moved class drops that class's alias, and the replaced class's
48
+ own `@happyvertical/smrt-timesheets:*` name stops resolving too — guidance
49
+ for apps with smrt-support must name `@happyvertical/smrt-support:ServiceTimeEntry`.
50
+ Support's vitest environment keeps both classes registered, so verify this
51
+ against built packages, not package tests. `projects/src/__tests__/legacy-qualified-identity.test.ts` pins
52
+ the projects-only contract.
53
+ - **Table names are a compatibility contract.** `service_time_entries` and the
54
+ two snapshot tables hold existing production rows from smrt-projects /
55
+ smrt-support; renaming any of them, or adding a discriminator, is a data
56
+ migration.
57
+
58
+ ## One table family
59
+
60
+ Classes may share a table only as one inheritance chain, and the registry
61
+ resolves a chain of same-named classes by "child wins" on the simple name.
62
+ That works for exactly one subtype level per table (base → subtype); a third
63
+ same-named level makes the middle class look like it extends its own child on
64
+ the manifest path (`CONFIG_TABLE_NAME_COLLISION`). Therefore:
65
+
66
+ - `smrt-projects` **re-exports** these classes (no projects subclass).
67
+ - `smrt-support` subclasses `ServiceTimeEntry` directly from this package.
68
+ - A consumer that needs its own surface (e.g. teamworks-os closing every
69
+ generated route with `api: { include: [] }` and
70
+ `@TenantScoped({ mode: 'required' })`) declares a same-named subclass over
71
+ `service_time_entries`; its manifest entry replaces the package's. It cannot
72
+ also install smrt-support's subtype on the same table.
73
+ The same applies to both snapshots;
74
+ `src/__tests__/consumer-closed-surface.test.ts` holds that contract for all
75
+ three models. The snapshots' explicit `time_entry_id` conflict key is not
76
+ rewritten when a consumer requires tenancy; widening it is the consumer's
77
+ schema change, never a package default.
78
+
79
+ Subclasses restate their fields: package-isolated manifest scanning does not
80
+ read dependency sources, so an unrestated subclass manifest has no columns.
81
+
82
+ ## Svelte UI
83
+
84
+ `./svelte` exports `TimeEntryCard`, `TimeEntryList`, `TimeSummary`,
85
+ `DurationDisplay`, and `TimeEntryApprovalQueue` (props-driven, plain view
86
+ objects, `smrt-ui` primitives, `smrtRawPrimitives: "strict"`). smrt-projects
87
+ and smrt-support re-export them from their own `./svelte` subpaths.
88
+ Card/list/summary message keys keep their `projects.*` namespace: tenant
89
+ language overrides are stored by key, and renaming would orphan them. New
90
+ keys use `timesheets.*`.
91
+
92
+ ## Validation
93
+
94
+ ```sh
95
+ pnpm --filter @happyvertical/smrt-timesheets test
96
+ pnpm --filter @happyvertical/smrt-timesheets test:postgres
97
+ pnpm --filter @happyvertical/smrt-timesheets typecheck
98
+ pnpm --filter @happyvertical/smrt-timesheets build
99
+ pnpm --filter @happyvertical/smrt-projects test
100
+ pnpm --filter @happyvertical/smrt-support test
101
+ ```
102
+
103
+ Schema-affecting edits must keep `service-time-entry-compat.test.ts` (projects,
104
+ support) and `service-time-entry-migration-plan.test.ts` (support) green: a
105
+ pre-move table must plan no DDL.
package/CLAUDE.md ADDED
@@ -0,0 +1 @@
1
+ @AGENTS.md
package/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright <2025> <Happy Vertical Corporation>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,243 @@
1
- # Temporary Holding Version
1
+ # @happyvertical/smrt-timesheets
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Shared time entries for s-m-r-t: who worked how long on what, whether someone
4
+ approved it, and what it was charged and paid at approval. One model for
5
+ professional services, shop floors, and job sites, instead of one per vertical.
6
+
7
+ - **Who** — a `smrt-profiles` Profile (`participantKind: 'human'`) or an agent
8
+ (`participantKind: 'agent'`, `agentRef`).
9
+ - **What** — a generic work reference: `workRefType` (a qualified class name)
10
+ and `workRefId`. No domain-specific foreign key on the base entry.
11
+ - **How long** — `startedAt`, `endedAt`, `durationSeconds`, and the `source`
12
+ (`timer`, `manual`, `import`, `agent`).
13
+ - **Approval** — `draft → submitted → approved | rejected`; approved entries
14
+ never change. A correction is a new row whose `correctionOfId` points at the
15
+ entry it corrects, which flips to `corrected`.
16
+ - **Money** — never on the entry. Approval writes one immutable
17
+ `ServiceChargeSnapshot` and one `ServiceCompensationSnapshot`, in integer
18
+ minor units (`$19.99` is `1999`), consistent with
19
+ [`smrt-commerce`](../commerce/README.md).
20
+
21
+ See [AGENTS.md](./AGENTS.md) for invariants and extension rules.
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ pnpm add @happyvertical/smrt-timesheets
27
+ ```
28
+
29
+ Add `svelte` for the optional UI components. Application schemas are created
30
+ by migrations (`smrt db:migrate`); the package never creates tables at
31
+ runtime.
32
+
33
+ ## Record, approve, and correct time
34
+
35
+ ```ts
36
+ import { ServiceEvidenceService } from '@happyvertical/smrt-timesheets';
37
+
38
+ const timesheets = await ServiceEvidenceService.create({ db }, {
39
+ // Your pricing and pay rules; amounts are integer minor units.
40
+ priceClient: async (entry) => ({
41
+ amount: Math.round(entry.durationHours() * 9500),
42
+ version: 'rates-2026',
43
+ terms: { hourlyRate: 9500 },
44
+ }),
45
+ compensateProvider: async (entry) => ({
46
+ amount: Math.round(entry.durationHours() * 6000),
47
+ version: 'pay-2026',
48
+ terms: { hourlyRate: 6000 },
49
+ }),
50
+ });
51
+
52
+ const entry = await timesheets.record({
53
+ workRefType: '@acme/jobs:WorkPackage',
54
+ workRefId: 'wp-7',
55
+ participantKind: 'human',
56
+ participantProfileId: profile.id,
57
+ source: 'timer',
58
+ description: 'Framed the north wall',
59
+ startedAt: new Date('2026-07-01T08:00:00Z'),
60
+ endedAt: new Date('2026-07-01T10:30:00Z'),
61
+ });
62
+
63
+ await timesheets.submit(entry, profile.id);
64
+ await timesheets.approve(entry, { approvalPath: 'operator' });
65
+ ```
66
+
67
+ `record()` rejects a missing or half work reference, a human entry without a
68
+ Profile, an agent entry without `agentRef`, a reversed period, and a
69
+ non-positive duration. `correct(entry, input)` records the replacement and
70
+ marks the approved entry `corrected`.
71
+
72
+ ## Svelte components
73
+
74
+ ```svelte
75
+ <script lang="ts">
76
+ import { TimeEntryList, TimeSummary } from '@happyvertical/smrt-timesheets/svelte';
77
+ </script>
78
+
79
+ <TimeSummary totalHours={12.5} totalAmount={118750} currency="CAD" />
80
+ <TimeEntryList {entries} selectable />
81
+ ```
82
+
83
+ `TimeEntryCard`, `TimeEntryList`, `TimeSummary`, `DurationDisplay`, and
84
+ `TimeEntryApprovalQueue` are props-driven: hosts load entries and pass plain
85
+ view objects (`TimeEntry`, `TimeEntryApprovalView`).
86
+
87
+ ## Closing the generated surface
88
+
89
+ The entry and both snapshots expose generated `list` / `get` on REST, CLI,
90
+ and MCP, with optional tenant scoping. An application that routes all time
91
+ and money through its own permission-gated services declares a same-named
92
+ subclass over each table and closes it:
93
+
94
+ ```ts
95
+ import {
96
+ ServiceChargeSnapshot as SharedServiceChargeSnapshot,
97
+ ServiceCompensationSnapshot as SharedServiceCompensationSnapshot,
98
+ ServiceTimeEntry as SharedServiceTimeEntry,
99
+ } from '@happyvertical/smrt-timesheets';
100
+
101
+ const CLOSED = { include: [] };
102
+
103
+ @TenantScoped({ mode: 'required' })
104
+ @smrt({
105
+ tableName: 'service_time_entries',
106
+ api: CLOSED,
107
+ cli: CLOSED,
108
+ mcp: CLOSED,
109
+ })
110
+ export class ServiceTimeEntry extends SharedServiceTimeEntry {
111
+ // restate the fields — see AGENTS.md
112
+ }
113
+
114
+ @TenantScoped({ mode: 'required' })
115
+ @smrt({
116
+ tableName: 'service_charge_snapshots',
117
+ conflictColumns: ['time_entry_id'],
118
+ api: CLOSED,
119
+ cli: CLOSED,
120
+ mcp: CLOSED,
121
+ })
122
+ export class ServiceChargeSnapshot extends SharedServiceChargeSnapshot {
123
+ // restate the fields — see AGENTS.md
124
+ }
125
+
126
+ @TenantScoped({ mode: 'required' })
127
+ @smrt({
128
+ tableName: 'service_compensation_snapshots',
129
+ conflictColumns: ['time_entry_id'],
130
+ api: CLOSED,
131
+ cli: CLOSED,
132
+ mcp: CLOSED,
133
+ })
134
+ export class ServiceCompensationSnapshot extends SharedServiceCompensationSnapshot {
135
+ // restate the fields — see AGENTS.md
136
+ }
137
+ ```
138
+
139
+ Do not copy `previousQualifiedNames` into these subclasses: an old name may
140
+ have only one claimant. Replacing the timesheets classes drops their
141
+ smrt-projects aliases (see the known gap under "Stored and declared class
142
+ names").
143
+
144
+ Restate `conflictColumns` exactly as shown unless you mean to change it. The
145
+ snapshots' conflict key is `time_entry_id` alone — one snapshot per entry —
146
+ and, being an explicit key, it is never rewritten to lead with `tenant_id`
147
+ when you require tenancy. That is safe as long as entry ids are unique across
148
+ tenants (they are UUIDs). Widening it to `['tenant_id', 'time_entry_id']` is
149
+ your decision, and it is a schema change for your database (a new unique
150
+ index replacing `service_*_snapshots_time_entry_id_idx`), so it goes through
151
+ `smrt db:migrate` like any other key change; the package default stays
152
+ `['time_entry_id']`.
153
+
154
+ ## Migrating from smrt-projects / smrt-support
155
+
156
+ `ServiceTimeEntry`, its collection, `ServiceChargeSnapshot`,
157
+ `ServiceCompensationSnapshot`, their collections, and
158
+ `ServiceEvidenceService` moved here in #3288.
159
+
160
+ **Consumers already holding `service_time_entries` rows need no schema change
161
+ and no data migration.** The table names, columns, indexes, and conflict keys
162
+ are unchanged, and the tables carry no type discriminator, so existing rows
163
+ load through every package's classes as they are. References stored under
164
+ the old smrt-projects class names keep resolving as deprecated aliases (see
165
+ "Stored and declared class names" below; one gap applies with smrt-support).
166
+
167
+ > **pnpm: add a direct `@happyvertical/smrt-timesheets` dependency.** The
168
+ > CLI's manifest discovery (`smrt db:migrate`, `db:status`, `db:diff`) reads
169
+ > only packages installed at the top level of `node_modules`. Under pnpm a
170
+ > transitive dependency is not there, so an application that depends on
171
+ > smrt-projects or smrt-support but not on smrt-timesheets stops planning
172
+ > `service_time_entries`, `service_charge_snapshots`, and
173
+ > `service_compensation_snapshots`: a fresh database never gets them (and
174
+ > `ServiceEvidenceService` then fails the runtime table check), and an
175
+ > existing one reports them as orphan tables. Add
176
+ > `pnpm add @happyvertical/smrt-timesheets`. npm and Yarn hoist the package
177
+ > and are unaffected.
178
+
179
+ | Before | After |
180
+ |---|---|
181
+ | `@happyvertical/smrt-projects` / `@happyvertical/smrt-support` in `dependencies` | Also add `@happyvertical/smrt-timesheets` under pnpm, or the CLI stops planning the three time tables (see the note above) |
182
+ | `ServiceTimeEntry`, `ServiceEvidenceService`, snapshots from `@happyvertical/smrt-projects` | Same names, still exported from smrt-projects (re-exports); new code imports `@happyvertical/smrt-timesheets` |
183
+ | `ServiceTimeEntry` from `@happyvertical/smrt-support` | Unchanged: support's subtype, now extending the timesheets entry |
184
+ | `caseId` / `specialistId`, `forCase()` / `forSpecialist()` on the projects export | Support subtype only — import `ServiceTimeEntry` / `ServiceTimeEntryCollection` from smrt-support |
185
+ | `ServiceEvidenceService.record({ caseId })` | Requires `workRefType` + `workRefId`; record case time through smrt-support's `ServiceTimeEntryService` |
186
+ | `@happyvertical/smrt-projects:ServiceTimeEntry` (and the two snapshot names) stored in `meta_type` or declared in `@crossPackageRef` / playbook `model:` | Resolves as a deprecated alias of `@happyvertical/smrt-timesheets:*`; move declarations to the class that is registered in your app — `@happyvertical/smrt-timesheets:*`, except `@happyvertical/smrt-support:ServiceTimeEntry` when smrt-support is installed (or your own closing subclass) — and optionally backfill stored rows with `smrt db:migrate-qualified-names` (see below) |
187
+ | `TimeEntryList`, `TimeEntryCard`, `TimeSummary`, `DurationDisplay` from `@happyvertical/smrt-projects/svelte`; `TimeEntryApprovalQueue` from `@happyvertical/smrt-support/svelte` | Still exported there; canonical home `@happyvertical/smrt-timesheets/svelte` |
188
+
189
+ An application with smrt-projects but not smrt-support keeps its existing
190
+ `case_id` / `specialist_id` columns: `db:migrate` reports them as orphan
191
+ columns and never alters or drops them, and saves through the shared entry
192
+ leave their values untouched.
193
+
194
+ ### Stored and declared class names
195
+
196
+ The moved models' registered names changed from
197
+ `@happyvertical/smrt-projects:*` to `@happyvertical/smrt-timesheets:*`. Each
198
+ class declares its old name in `previousQualifiedNames` (#3338), so references
199
+ that stored or declared it keep resolving as a **deprecated alias**:
200
+ polymorphic association rows (`metaType`, including smrt-assets
201
+ `AssetAssociation`), `ObjectRegistry.getClassByQualifiedName()`,
202
+ `@crossPackageRef` and relationship targets, and playbook step `model:`
203
+ names. The first resolution of each old name per process logs a deprecation
204
+ warning; new association writes store the current name. Generated routes,
205
+ MCP tool names, and permission slugs derive from simple and collection names
206
+ and are unchanged.
207
+
208
+ - `smrt doctor --db` counts stored references that still use an old name
209
+ ("Deprecated Qualified Names").
210
+ - `smrt db:migrate-qualified-names` is an opt-in backfill that rewrites them
211
+ to the current names (`--dry-run` first); it is never run automatically.
212
+ - Move source references — `@crossPackageRef(...)`, relationship targets,
213
+ playbook `model:` names — to the name of the class your application
214
+ actually registers, now. That is `@happyvertical/smrt-timesheets:*`, except
215
+ where a same-named subclass replaces the timesheets class: with smrt-support
216
+ installed, reference `@happyvertical/smrt-support:ServiceTimeEntry` (the
217
+ timesheets name is not registered there, so a `@crossPackageRef` to it
218
+ fails to load and an association stored under it hydrates to `null`); with
219
+ your own closing subclass, reference your subclass's qualified name. The
220
+ snapshots keep their timesheets names unless you subclass them. The aliases
221
+ will be removed in a later **breaking** release, once `smrt doctor --db`
222
+ reports no stored references.
223
+
224
+ > **Known gap: same-named subtypes drop the alias.** A same-named subclass
225
+ > over a moved table — smrt-support's `ServiceTimeEntry`, or an
226
+ > application's closing subclass (see "Closing the generated surface") —
227
+ > replaces the timesheets class in the registry, and that class's alias does
228
+ > not carry over to it yet. With smrt-support installed,
229
+ > `@happyvertical/smrt-projects:ServiceTimeEntry` therefore does not resolve
230
+ > (hydration returns `null`) and `smrt doctor --db` /
231
+ > `db:migrate-qualified-names` do not see it; the snapshot aliases still work
232
+ > unless the application subclasses the snapshots too. A subclass must not
233
+ > redeclare the alias (two claimants of one old name collide). Until core
234
+ > carries aliases across the replacement, rewrite affected stored references
235
+ > (typically `meta_type` columns) to the replacing class's current name, e.g.
236
+ > `@happyvertical/smrt-support:ServiceTimeEntry`.
237
+
238
+ ## Related packages
239
+
240
+ - [`smrt-projects`](../projects/README.md) — delivery work and
241
+ `SubscriptionServiceCommercialResolver` pricing for these entries.
242
+ - [`smrt-support`](../support/README.md) — support-case time on the same table.
243
+ - [`smrt-profiles`](../profiles/README.md) — the participants.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=__smrt-register__.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"__smrt-register__.d.ts","sourceRoot":"","sources":["../src/__smrt-register__.ts"],"names":[],"mappings":""}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @happyvertical/smrt-timesheets
3
+ *
4
+ * Shared time entries: who (a smrt-profiles Profile or an agent) worked how
5
+ * long on what (a generic work reference), approval and correction, and the
6
+ * immutable charge / compensation snapshots taken at approval.
7
+ *
8
+ * `smrt-projects` re-exports all of these classes unchanged under their
9
+ * existing names. `smrt-support` subclasses only `ServiceTimeEntry` (adding
10
+ * `caseId` / `specialistId`) over the same table; the snapshots and
11
+ * `ServiceEvidenceService` are used from this package as they are.
12
+ *
13
+ * @packageDocumentation
14
+ */
15
+ import './__smrt-register__.js';
16
+ export * from './models/index.js';
17
+ export * from './services/index.js';
18
+ export { SERVICE_TIME_ENTRY_STATUS_TRANSITIONS, type ServiceEvidence, type ServiceParticipantKind, type ServiceTimeEntrySource, type ServiceTimeEntryStatus, } from './types.js';
19
+ export { TIMESHEETS_MODULE_META, TIMESHEETS_UI_SLOTS } from './ui.js';
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,wBAAwB,CAAC;AAEhC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACL,qCAAqC,EACrC,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC5B,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC"}