@odla-ai/chapter 0.53.0 → 0.54.1
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/README.md +30 -2
- package/dist/{chunk-PTC43J7F.js → chunk-NDZCR3OW.js} +5 -5
- package/dist/chunk-NDZCR3OW.js.map +1 -0
- package/dist/{chunk-TEHCORNC.js → chunk-SPEL4OGE.js} +57 -23
- package/dist/chunk-SPEL4OGE.js.map +1 -0
- package/dist/index.cjs +219 -106
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -10
- package/dist/index.d.ts +30 -10
- package/dist/index.js +219 -106
- package/dist/index.js.map +1 -1
- package/dist/ui/admin/index.js +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +8 -2
- package/dist/ui/member/index.d.ts +32 -1
- package/dist/ui/member/index.js +7 -1
- package/dist/worker/index.cjs +297 -128
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +92 -9
- package/dist/worker/index.d.ts +92 -9
- package/dist/worker/index.js +297 -128
- package/dist/worker/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-PTC43J7F.js.map +0 -1
- package/dist/chunk-TEHCORNC.js.map +0 -1
package/README.md
CHANGED
|
@@ -1735,12 +1735,39 @@ These bite silently — a smoke test won't catch them:
|
|
|
1735
1735
|
Neither helper installs a cron or provisions infrastructure by itself.
|
|
1736
1736
|
|
|
1737
1737
|
The member area exposes the authenticated purchaser's named-seat checkout
|
|
1738
|
-
only when configured
|
|
1738
|
+
only when configured, and as soon as the membership is paid: `/api/me`
|
|
1739
|
+
reports `namedSeatsEnabled` for a paid application whose interview is still
|
|
1740
|
+
ahead, so a member who skipped the seat at checkout finds it on her members
|
|
1741
|
+
page rather than after approval. The authority still decides eligibility on
|
|
1742
|
+
every read. Recipient hosts pass `initialNamedSeatId` from the
|
|
1739
1743
|
invitation's `seat` query parameter and an authenticated `namedSeatClaimApi`
|
|
1740
1744
|
to `JoinIsland`; the recipient completes their own application and acceptance
|
|
1741
1745
|
without a second subscription checkout. A primary cancellation also governs
|
|
1742
1746
|
seat renewal; buying a seat does not restore canceled auto-renewal.
|
|
1743
1747
|
|
|
1748
|
+
An offering may price the seat at zero (`seatPriceCents: 0`): the membership
|
|
1749
|
+
then **includes** the seat. `GET /api/named-seat` reports `included: true`
|
|
1750
|
+
with `amountCents: 0`, and `POST /api/named-seat/checkout` grants the seat in
|
|
1751
|
+
the same request, with no PaymentIntent, no publishable key and no renewal
|
|
1752
|
+
line: the seat lands in `pending_acceptance` with its entitlement and the
|
|
1753
|
+
invitation effect, exactly where a paid seat lands after payment, and its
|
|
1754
|
+
term follows the primary's renewal. The receipt carries `included: true` and
|
|
1755
|
+
no `clientSecret`, so a host skips the card form (`NamedSeatPurchase` asks
|
|
1756
|
+
for the same consent and then sends the invitation). Refunding an included
|
|
1757
|
+
seat closes it with `refundedCents: 0` and revokes an active recipient; the
|
|
1758
|
+
provider is never asked for anything. `lowerSeatPrice` and
|
|
1759
|
+
`POST /api/admin/membership-seats/reprice` (`{ chapterId, runtime, skuId }`,
|
|
1760
|
+
super admin, network owner) move a SKU's existing memberships down to the
|
|
1761
|
+
current published offering's seat price, so a member who paid before the
|
|
1762
|
+
change gets the included seat too; it only ever lowers, skips a seat already
|
|
1763
|
+
paid for, and names every membership it left alone.
|
|
1764
|
+
|
|
1765
|
+
The offer's `seat` also carries `recipientState` (`payment_pending`,
|
|
1766
|
+
`invited`, `accepted`, `joined`, `declined`, `refunded`, `canceled`) with
|
|
1767
|
+
`purchasedAt`, `acceptedAt` and `joinedAt`, so a members page can say who was
|
|
1768
|
+
named and whether that person joined without folding the seat status machine
|
|
1769
|
+
itself; `NamedSeatRecipientLine` renders it.
|
|
1770
|
+
|
|
1744
1771
|
Delivery logs distinguish sent, logged-only, in-flight, uncertain and
|
|
1745
1772
|
retry-approved outcomes. The authenticated operator resolution route
|
|
1746
1773
|
`/api/admin/email/log/:id/resolve` records evidence against the exact attempt;
|
|
@@ -1752,7 +1779,8 @@ These bite silently — a smoke test won't catch them:
|
|
|
1752
1779
|
included, and the offer reports `purchaseWindowed: false`. Memberships frozen
|
|
1753
1780
|
under an earlier windowed offering keep their window until the network owner
|
|
1754
1781
|
lifts it once per chapter with `POST /api/admin/membership-seats/lift-purchase-window`
|
|
1755
|
-
(super admin; only ever widens)
|
|
1782
|
+
(super admin; only ever widens), or from a script with `liftSeatPurchaseWindow`
|
|
1783
|
+
(exported from `@odla-ai/chapter/worker` beside `lowerSeatPrice`).
|
|
1756
1784
|
|
|
1757
1785
|
On the payment step, a difference between the standard and due amounts is
|
|
1758
1786
|
labelled a founding discount only when the quote carries `founding` from the
|
|
@@ -780,11 +780,11 @@ function SeatPanel(props) {
|
|
|
780
780
|
" \xB7 ",
|
|
781
781
|
seat.recipientEmail,
|
|
782
782
|
" \xB7 ",
|
|
783
|
-
seat.status.replaceAll("_", " ")
|
|
783
|
+
(seat.recipientState ?? seat.status).replaceAll("_", " ")
|
|
784
784
|
] }),
|
|
785
785
|
/* @__PURE__ */ jsxs7("p", { className: "muted", style: { margin: 0 }, children: [
|
|
786
|
-
money5
|
|
787
|
-
"
|
|
786
|
+
data.amountCents === 0 ? "Included with the membership; nothing was charged." : `${money5} paid in full.`,
|
|
787
|
+
" The seat waits for its recipient and is never refunded automatically."
|
|
788
788
|
] }),
|
|
789
789
|
data.refundable ? /* @__PURE__ */ jsx7("div", { children: /* @__PURE__ */ jsx7(Button3, { variant: "danger", mini: true, disabled: busy, onClick: () => void refund(), children: busy ? "Refunding\u2026" : "Refund seat" }) }) : null
|
|
790
790
|
] }),
|
|
@@ -3545,7 +3545,7 @@ var offeringColumns = [
|
|
|
3545
3545
|
{ key: "sku", header: "SKU", cell: (row) => /* @__PURE__ */ jsx38("code", { children: row.baseSkuId }) },
|
|
3546
3546
|
{ key: "list", header: "List price", cell: (row) => `${money4(row.basePriceCents, row.currency)} / ${row.interval}` },
|
|
3547
3547
|
{ key: "term", header: "Term", cell: (row) => row.term.kind === "fixed_end" ? `Ends ${day(row.term.endsAt)}` : `Rolling ${row.term.months} months` },
|
|
3548
|
-
{ key: "seat", header: "Seat", cell: (row) => `${money4(row.seatPriceCents, row.currency)} \xB7 ${row.seatPurchaseWindowCalendarMonths === void 0 ? "no window" : `${row.seatPurchaseWindowCalendarMonths}-month window`}` },
|
|
3548
|
+
{ key: "seat", header: "Seat", cell: (row) => `${row.seatPriceCents === 0 ? "Included" : money4(row.seatPriceCents, row.currency)} \xB7 ${row.seatPurchaseWindowCalendarMonths === void 0 ? "no window" : `${row.seatPurchaseWindowCalendarMonths}-month window`}` },
|
|
3549
3549
|
{ key: "effectiveFrom", header: "Effective from", cell: (row) => day(row.effectiveFrom), sortAs: "number", sortValue: (row) => row.effectiveFrom },
|
|
3550
3550
|
{ key: "effectiveUntil", header: "Effective until", cell: (row) => row.effectiveUntil === void 0 ? "Open" : day(row.effectiveUntil) },
|
|
3551
3551
|
{ key: "supersededAt", header: "Superseded", cell: superseded },
|
|
@@ -3704,4 +3704,4 @@ export {
|
|
|
3704
3704
|
NetworkSeatBilling,
|
|
3705
3705
|
MembershipPolicyVersions
|
|
3706
3706
|
};
|
|
3707
|
-
//# sourceMappingURL=chunk-
|
|
3707
|
+
//# sourceMappingURL=chunk-NDZCR3OW.js.map
|