@happyvertical/smrt-bookings 0.60.8 → 0.60.9
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.
- package/AGENTS.md +3 -0
- package/README.md +76 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +393 -46
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +1 -1
- package/dist/migration.d.ts +6 -0
- package/dist/migration.d.ts.map +1 -1
- package/dist/service.d.ts +18 -7
- package/dist/service.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +7 -7
- package/dist/types.d.ts +89 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/windows.d.ts +29 -2
- package/dist/windows.d.ts.map +1 -1
- package/package.json +2 -2
package/AGENTS.md
CHANGED
|
@@ -7,3 +7,6 @@ and plan relationships. Commerce and payment state are separate.
|
|
|
7
7
|
Use service commands for writes; keep this package out of generated CRUD. Apply
|
|
8
8
|
its explicit PostgreSQL migration during deployment, outside request handling.
|
|
9
9
|
See [README.md](README.md) for the transaction and verification contracts.
|
|
10
|
+
|
|
11
|
+
V2 is additive: a proposal's `windows` array is the reservation and the
|
|
12
|
+
allocation stores only its span.
|
package/README.md
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
# s-m-r-t Bookings
|
|
2
2
|
|
|
3
|
-
`@happyvertical/smrt-bookings` reserves
|
|
4
|
-
operator-declared local supervision window. It does not
|
|
5
|
-
payment, send notifications, or write Commerce records.
|
|
3
|
+
`@happyvertical/smrt-bookings` reserves dedicated developer time (an hour, day,
|
|
4
|
+
week or month) or one operator-declared local supervision window. It does not
|
|
5
|
+
start agents, collect payment, send notifications, or write Commerce records.
|
|
6
6
|
|
|
7
|
-
Apply `migrateBookingsV1`
|
|
8
|
-
using a PostgreSQL database handle.
|
|
7
|
+
Apply `migrateBookingsV1` and then `migrateBookingsV2` once each through the
|
|
8
|
+
host's deployment migration ledger using a PostgreSQL database handle. V2 is
|
|
9
|
+
additive: it adds offering units, prices and display fields, booking quantity,
|
|
10
|
+
and per-proposal windows and frozen prices, backfilling existing rows without
|
|
11
|
+
dropping data. Like V1 it is not idempotent. Use an ordinary PostgreSQL connection or
|
|
9
12
|
pool for `BookingService`; the service owns its transaction and explicitly uses
|
|
10
13
|
READ COMMITTED. It does not create schema on demand. No ORM collection, CRUD
|
|
11
14
|
route, or generated CLI or MCP write is registered.
|
|
@@ -37,6 +40,38 @@ route, or generated CLI or MCP write is registered.
|
|
|
37
40
|
Booking and historical proposal reads are scoped to the named contact or
|
|
38
41
|
an operator. Booking audit history is operator-only.
|
|
39
42
|
|
|
43
|
+
## Offerings, units and prices
|
|
44
|
+
|
|
45
|
+
An offering has a `kind` and a `unit` (`hour`, `day`, `week` or `month`). The
|
|
46
|
+
kind is the reservation semantics and the unit is the sales granularity; both
|
|
47
|
+
are frozen once the offering exists. `developer-hour` keeps its name for schema
|
|
48
|
+
compatibility but means dedicated, exclusive attention for any unit: it blocks
|
|
49
|
+
every overlapping reservation and needs no project or approved plan.
|
|
50
|
+
`supervision-day` is shared supervision capacity, always a one-day unit with
|
|
51
|
+
quantity one.
|
|
52
|
+
|
|
53
|
+
An offering may carry `priceCents` (integer minor units) and an ISO 4217
|
|
54
|
+
`currency`, set together or both null for an unpriced offering. Prices, `title`
|
|
55
|
+
(120 characters), `description` (2000 characters) and `public` may be changed
|
|
56
|
+
later. A request has a `quantity` (default 1, at most 1000). A proposal freezes
|
|
57
|
+
the offering's `unitPriceCents` and `currency` and the `totalCents`
|
|
58
|
+
(`unitPriceCents * quantity`) at proposal time, so later price changes do not
|
|
59
|
+
alter an offered or confirmed booking. Payment and invoicing remain host-owned.
|
|
60
|
+
|
|
61
|
+
A dedicated proposal gives either `window` (the v1 single window) or `windows`,
|
|
62
|
+
sorted, non-overlapping segments in one zone. The proposal `window` is the span
|
|
63
|
+
from the first start to the last end and `windows` are the reserved segments;
|
|
64
|
+
confirmation checks and the allocation reserves every segment. The segments must
|
|
65
|
+
measure exactly the quantity of the unit:
|
|
66
|
+
|
|
67
|
+
- `hour`: the segments' elapsed UTC time sums to `quantity` hours, so a split
|
|
68
|
+
hour is fine and a DST fold counts as elapsed time.
|
|
69
|
+
- `day`: every segment lies in the local span of `quantity` days from the first
|
|
70
|
+
segment's date and the segments touch exactly `quantity` distinct days.
|
|
71
|
+
- `week` and `month`: every segment lies in the half-open local span
|
|
72
|
+
`[D0, D0 + quantity weeks or months)`, with month ends constrained to the
|
|
73
|
+
target month's length. A segment may end at `T00:00` of the day after the span.
|
|
74
|
+
|
|
40
75
|
Windows use an IANA zone and local timestamps of the form
|
|
41
76
|
`2027-11-07T01:30-04:00`. For example, use that offset with America/New_York. The offset must be valid for that instant in the zone.
|
|
42
77
|
During a DST fold the offsets identify different instants; a nonexistent wall
|
|
@@ -49,15 +84,50 @@ Use `listBookings` to find the same booking views returned by `get`. An
|
|
|
49
84
|
optional project UUID narrows the results within the caller's existing scope.
|
|
50
85
|
Operators see all bookings in their tenant. Other callers see only bookings
|
|
51
86
|
for the contact the host maps to their actor. `listOfferings` exposes the
|
|
52
|
-
offering ID, kind
|
|
87
|
+
offering ID, kind, unit, price, title, description, `public` and enabled flag.
|
|
88
|
+
There are three reader classes: operators see every offering, readers mapped to a
|
|
89
|
+
contact see enabled offerings, and a reader with no contact mapping (an anonymous
|
|
90
|
+
or prospect actor the host vouches for) sees only enabled public offerings.
|
|
91
|
+
`public` only affects discovery; `request` still needs a contact mapping.
|
|
92
|
+
`listBookings` also accepts a `contactId` filter: operators may narrow to any
|
|
93
|
+
contact and other callers may only name their own.
|
|
53
94
|
Operators can use `listAvailability` to inspect existing provider windows
|
|
54
95
|
before replacing a declaration. All three methods use the `read` authority.
|
|
55
96
|
|
|
97
|
+
`listOpenSlots` returns candidate slots for one offering between `from` and `to`
|
|
98
|
+
(at most 400 days apart), optionally for one provider and a `quantity`. It is a
|
|
99
|
+
pure read: it reserves nothing and takes no retry key, and confirmation still
|
|
100
|
+
re-checks capacity under the provider lock. Each slot carries the `windows` to
|
|
101
|
+
pass to `propose`. Hourly offerings step by the hour inside each declared
|
|
102
|
+
window; day, week and month offerings bundle the declared windows that measure
|
|
103
|
+
the quantity from each start date; supervision offerings list each declared
|
|
104
|
+
supervision window with its remaining shared units. Occupied segments are
|
|
105
|
+
excluded. Results are ordered by first start then provider and paged with the
|
|
106
|
+
opaque `nextCursor`, passed back as `after`. The host decides who may read via
|
|
107
|
+
`access(..., 'read')`; offerings follow the same three reader classes as
|
|
108
|
+
`listOfferings`, and an offering the reader cannot discover is `not-found`.
|
|
109
|
+
|
|
56
110
|
Lists return up to 50 items by default and accept a limit from 1 to 100.
|
|
57
111
|
Results are ordered by ascending UUID. Pass the returned `nextCursor` as
|
|
58
112
|
`afterId` with the same filters to fetch another page. A null cursor means
|
|
59
113
|
the page reached the end of the results.
|
|
60
114
|
|
|
115
|
+
## Lead-bound requests
|
|
116
|
+
|
|
117
|
+
A dedicated booking may exist before the contact has a project. When the host's
|
|
118
|
+
authority implements the optional `verifyContact(context, contactId)`, a request
|
|
119
|
+
with no project calls it to confirm that the contact exists in the tenant and the
|
|
120
|
+
actor may act for it, and `verifyReferences` never receives that contact. The
|
|
121
|
+
same applies to propose, assent and confirm for such a booking, where
|
|
122
|
+
`verifyReferences` still checks the provider. Without `verifyContact` the contact
|
|
123
|
+
is passed to `verifyReferences` as before. Supervision always requires a project.
|
|
124
|
+
An operator later binds the project with
|
|
125
|
+
`attachProject(context, key, { bookingId, projectId })`: it needs an active
|
|
126
|
+
booking, verifies the contact and project together, is idempotent for the same
|
|
127
|
+
project, refuses a different one with `conflict`, and is recorded in history as
|
|
128
|
+
`attach-project`. Dedicated allocations never carry a project, so attaching does
|
|
129
|
+
not touch reserved capacity.
|
|
130
|
+
|
|
61
131
|
Use an authenticated tenant/actor context from the host, never from a request
|
|
62
132
|
body. The host's `BookingAuthority` supplies current operator permission and
|
|
63
133
|
the actor's named contact mapping, and must verify that external references
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { BookingError } from './errors.js';
|
|
2
|
-
export { migrateBookingsV1 } from './migration.js';
|
|
2
|
+
export { migrateBookingsV1, migrateBookingsV2 } from './migration.js';
|
|
3
3
|
export { BookingService } from './service.js';
|
|
4
4
|
export type * from './types.js';
|
|
5
5
|
export { resolveBookingWindow } from './windows.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,mBAAmB,YAAY,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC"}
|