@odla-ai/chapter 0.20.2 → 0.22.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.
- package/README.md +147 -32
- package/dist/{chunk-LME2IHY5.js → chunk-ILGUJXSB.js} +1 -1
- package/dist/chunk-ILGUJXSB.js.map +1 -0
- package/dist/chunk-IWW5VAAC.js +1666 -0
- package/dist/chunk-IWW5VAAC.js.map +1 -0
- package/dist/chunk-VZPBTTO3.js +91 -0
- package/dist/chunk-VZPBTTO3.js.map +1 -0
- package/dist/index.cjs +72 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +78 -19
- package/dist/index.d.ts +78 -19
- package/dist/index.js +72 -6
- package/dist/index.js.map +1 -1
- package/dist/{types-D2fGiNG8.d.ts → types-CgWUQ2MH.d.ts} +50 -8
- package/dist/ui/admin/index.d.ts +150 -83
- package/dist/ui/admin/index.js +14 -2
- package/dist/ui/index.d.ts +3 -2
- package/dist/ui/index.js +15 -3
- package/dist/ui/member/index.d.ts +3 -1
- package/dist/ui/member/index.js +2 -2
- package/dist/worker/index.cjs +28 -16
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +50 -8
- package/dist/worker/index.d.ts +50 -8
- package/dist/worker/index.js +28 -16
- package/dist/worker/index.js.map +1 -1
- package/package.json +3 -3
- package/runbooks/adopt-existing.md +22 -4
- package/runbooks/greenfield.md +19 -9
- package/dist/chunk-LME2IHY5.js.map +0 -1
- package/dist/chunk-MKXHZMAP.js +0 -51
- package/dist/chunk-MKXHZMAP.js.map +0 -1
- package/dist/chunk-UIWFEESI.js +0 -922
- package/dist/chunk-UIWFEESI.js.map +0 -1
package/dist/worker/index.d.cts
CHANGED
|
@@ -32,8 +32,50 @@ interface Rule {
|
|
|
32
32
|
}
|
|
33
33
|
/** Namespace → rule set. */
|
|
34
34
|
type DbRules = Record<string, Rule>;
|
|
35
|
-
/**
|
|
35
|
+
/** Typed semantic roles shared by the public site and application surfaces. */
|
|
36
|
+
interface ChapterBrandTokens {
|
|
37
|
+
background?: string;
|
|
38
|
+
surface?: string;
|
|
39
|
+
surface2?: string;
|
|
40
|
+
text?: string;
|
|
41
|
+
textMuted?: string;
|
|
42
|
+
textFaint?: string;
|
|
43
|
+
border?: string;
|
|
44
|
+
borderStrong?: string;
|
|
45
|
+
accent?: string;
|
|
46
|
+
accentStrong?: string;
|
|
47
|
+
accentSoft?: string;
|
|
48
|
+
onAccent?: string;
|
|
49
|
+
good?: string;
|
|
50
|
+
warn?: string;
|
|
51
|
+
danger?: string;
|
|
52
|
+
chart1?: string;
|
|
53
|
+
chart2?: string;
|
|
54
|
+
chart3?: string;
|
|
55
|
+
chart4?: string;
|
|
56
|
+
chart5?: string;
|
|
57
|
+
chart6?: string;
|
|
58
|
+
chartPositive?: string;
|
|
59
|
+
chartNegative?: string;
|
|
60
|
+
/** Admin/application content width, e.g. `"960px"`. */
|
|
61
|
+
contentWidth?: string;
|
|
62
|
+
panelRadius?: string;
|
|
63
|
+
panelShadow?: string;
|
|
64
|
+
masterDetailColumns?: string;
|
|
65
|
+
masterDetailMinHeight?: string;
|
|
66
|
+
/** Chapter-admin page padding shorthand. */
|
|
67
|
+
pagePadding?: string;
|
|
68
|
+
/** Chapter-admin workspace-tab padding shorthand. */
|
|
69
|
+
workspacePadding?: string;
|
|
70
|
+
}
|
|
71
|
+
/** Brand tokens that theme the site: theme, semantic roles, fonts, and logos. */
|
|
36
72
|
interface ChapterBrand {
|
|
73
|
+
/** Preloaded @odla-ai/ui theme name used by ThemeScope. */
|
|
74
|
+
theme?: string;
|
|
75
|
+
/** Admin/application color mode. Explicit light is the safe default. */
|
|
76
|
+
colorScheme?: "light" | "dark" | "system";
|
|
77
|
+
tokens?: ChapterBrandTokens;
|
|
78
|
+
tokensDark?: ChapterBrandTokens;
|
|
37
79
|
/** Palette overrides written into styles.css :root (e.g. `{ moss: "#2F3E34" }`
|
|
38
80
|
* or `--ui-*` token names). Applies in BOTH light and dark unless overridden
|
|
39
81
|
* by {@link paletteDark}. */
|
|
@@ -67,7 +109,7 @@ interface ChapterNetworkTarget {
|
|
|
67
109
|
id: string;
|
|
68
110
|
/** Human-facing site name. Defaults to `id`. */
|
|
69
111
|
name?: string;
|
|
70
|
-
/** Absolute follower origin, e.g. `https://
|
|
112
|
+
/** Absolute follower origin, e.g. `https://chapter.example.com`. */
|
|
71
113
|
url: string;
|
|
72
114
|
/** Leader-vault key holding this follower's share secret. Defaults to
|
|
73
115
|
* `network_share_<id-with-underscores>`. */
|
|
@@ -138,10 +180,10 @@ interface ChapterScheduling {
|
|
|
138
180
|
}
|
|
139
181
|
/** How a signed-in user's role is determined.
|
|
140
182
|
*
|
|
141
|
-
* - `"claim"` reads a role ladder from a JWT claim (
|
|
183
|
+
* - `"claim"` reads a role ladder from a JWT claim (the member-site model:
|
|
142
184
|
* `provisional → member → admin`). Admin is the last (highest) rung; the
|
|
143
185
|
* read-only `superAdmins` tier sits above it.
|
|
144
|
-
* - `"table"` gates on the deny-all `admins` allowlist (
|
|
186
|
+
* - `"table"` gates on the deny-all `admins` allowlist (the hub model):
|
|
145
187
|
* a binary "email is an admin or isn't", set only in odla Studio.
|
|
146
188
|
*
|
|
147
189
|
* Defaults: `"claim"` in `chapter` mode, `"table"` in `hub` mode. */
|
|
@@ -168,7 +210,7 @@ interface ResolvedAuth {
|
|
|
168
210
|
}
|
|
169
211
|
/** The application status pipeline. Which statuses exist, and the subsets a site
|
|
170
212
|
* allows a call to be booked from / an application approved from. Defaults to
|
|
171
|
-
*
|
|
213
|
+
* the reference pipeline. Status never moves backwards (package-enforced). */
|
|
172
214
|
interface ChapterPipeline {
|
|
173
215
|
stages?: readonly string[];
|
|
174
216
|
bookableFrom?: readonly string[];
|
|
@@ -185,8 +227,8 @@ interface ResolvedPipeline {
|
|
|
185
227
|
}
|
|
186
228
|
/** The application (join form) validation surface — which string fields are
|
|
187
229
|
* required vs accepted, their max lengths, and the request body cap. Drives
|
|
188
|
-
* submit validation + the CRM slot projection; defaults to
|
|
189
|
-
* The `applications` schema attrs stay fixed
|
|
230
|
+
* submit validation + the CRM slot projection; defaults to the reference form.
|
|
231
|
+
* The `applications` schema attrs stay fixed; this is
|
|
190
232
|
* validation config, not schema generation. */
|
|
191
233
|
interface ChapterApplication {
|
|
192
234
|
required?: readonly string[];
|
|
@@ -258,7 +300,7 @@ interface ChapterConfig {
|
|
|
258
300
|
/** `notificationEmail` required in `chapter` mode. */
|
|
259
301
|
emails?: ChapterEmails;
|
|
260
302
|
scheduling?: ChapterScheduling;
|
|
261
|
-
/** Application status pipeline (stages + bookable/approvable subsets).
|
|
303
|
+
/** Application status pipeline (stages + bookable/approvable subsets). */
|
|
262
304
|
pipeline?: ChapterPipeline;
|
|
263
305
|
/** Join-form validation (required/optional fields, max lengths, body cap). */
|
|
264
306
|
application?: ChapterApplication;
|
package/dist/worker/index.d.ts
CHANGED
|
@@ -32,8 +32,50 @@ interface Rule {
|
|
|
32
32
|
}
|
|
33
33
|
/** Namespace → rule set. */
|
|
34
34
|
type DbRules = Record<string, Rule>;
|
|
35
|
-
/**
|
|
35
|
+
/** Typed semantic roles shared by the public site and application surfaces. */
|
|
36
|
+
interface ChapterBrandTokens {
|
|
37
|
+
background?: string;
|
|
38
|
+
surface?: string;
|
|
39
|
+
surface2?: string;
|
|
40
|
+
text?: string;
|
|
41
|
+
textMuted?: string;
|
|
42
|
+
textFaint?: string;
|
|
43
|
+
border?: string;
|
|
44
|
+
borderStrong?: string;
|
|
45
|
+
accent?: string;
|
|
46
|
+
accentStrong?: string;
|
|
47
|
+
accentSoft?: string;
|
|
48
|
+
onAccent?: string;
|
|
49
|
+
good?: string;
|
|
50
|
+
warn?: string;
|
|
51
|
+
danger?: string;
|
|
52
|
+
chart1?: string;
|
|
53
|
+
chart2?: string;
|
|
54
|
+
chart3?: string;
|
|
55
|
+
chart4?: string;
|
|
56
|
+
chart5?: string;
|
|
57
|
+
chart6?: string;
|
|
58
|
+
chartPositive?: string;
|
|
59
|
+
chartNegative?: string;
|
|
60
|
+
/** Admin/application content width, e.g. `"960px"`. */
|
|
61
|
+
contentWidth?: string;
|
|
62
|
+
panelRadius?: string;
|
|
63
|
+
panelShadow?: string;
|
|
64
|
+
masterDetailColumns?: string;
|
|
65
|
+
masterDetailMinHeight?: string;
|
|
66
|
+
/** Chapter-admin page padding shorthand. */
|
|
67
|
+
pagePadding?: string;
|
|
68
|
+
/** Chapter-admin workspace-tab padding shorthand. */
|
|
69
|
+
workspacePadding?: string;
|
|
70
|
+
}
|
|
71
|
+
/** Brand tokens that theme the site: theme, semantic roles, fonts, and logos. */
|
|
36
72
|
interface ChapterBrand {
|
|
73
|
+
/** Preloaded @odla-ai/ui theme name used by ThemeScope. */
|
|
74
|
+
theme?: string;
|
|
75
|
+
/** Admin/application color mode. Explicit light is the safe default. */
|
|
76
|
+
colorScheme?: "light" | "dark" | "system";
|
|
77
|
+
tokens?: ChapterBrandTokens;
|
|
78
|
+
tokensDark?: ChapterBrandTokens;
|
|
37
79
|
/** Palette overrides written into styles.css :root (e.g. `{ moss: "#2F3E34" }`
|
|
38
80
|
* or `--ui-*` token names). Applies in BOTH light and dark unless overridden
|
|
39
81
|
* by {@link paletteDark}. */
|
|
@@ -67,7 +109,7 @@ interface ChapterNetworkTarget {
|
|
|
67
109
|
id: string;
|
|
68
110
|
/** Human-facing site name. Defaults to `id`. */
|
|
69
111
|
name?: string;
|
|
70
|
-
/** Absolute follower origin, e.g. `https://
|
|
112
|
+
/** Absolute follower origin, e.g. `https://chapter.example.com`. */
|
|
71
113
|
url: string;
|
|
72
114
|
/** Leader-vault key holding this follower's share secret. Defaults to
|
|
73
115
|
* `network_share_<id-with-underscores>`. */
|
|
@@ -138,10 +180,10 @@ interface ChapterScheduling {
|
|
|
138
180
|
}
|
|
139
181
|
/** How a signed-in user's role is determined.
|
|
140
182
|
*
|
|
141
|
-
* - `"claim"` reads a role ladder from a JWT claim (
|
|
183
|
+
* - `"claim"` reads a role ladder from a JWT claim (the member-site model:
|
|
142
184
|
* `provisional → member → admin`). Admin is the last (highest) rung; the
|
|
143
185
|
* read-only `superAdmins` tier sits above it.
|
|
144
|
-
* - `"table"` gates on the deny-all `admins` allowlist (
|
|
186
|
+
* - `"table"` gates on the deny-all `admins` allowlist (the hub model):
|
|
145
187
|
* a binary "email is an admin or isn't", set only in odla Studio.
|
|
146
188
|
*
|
|
147
189
|
* Defaults: `"claim"` in `chapter` mode, `"table"` in `hub` mode. */
|
|
@@ -168,7 +210,7 @@ interface ResolvedAuth {
|
|
|
168
210
|
}
|
|
169
211
|
/** The application status pipeline. Which statuses exist, and the subsets a site
|
|
170
212
|
* allows a call to be booked from / an application approved from. Defaults to
|
|
171
|
-
*
|
|
213
|
+
* the reference pipeline. Status never moves backwards (package-enforced). */
|
|
172
214
|
interface ChapterPipeline {
|
|
173
215
|
stages?: readonly string[];
|
|
174
216
|
bookableFrom?: readonly string[];
|
|
@@ -185,8 +227,8 @@ interface ResolvedPipeline {
|
|
|
185
227
|
}
|
|
186
228
|
/** The application (join form) validation surface — which string fields are
|
|
187
229
|
* required vs accepted, their max lengths, and the request body cap. Drives
|
|
188
|
-
* submit validation + the CRM slot projection; defaults to
|
|
189
|
-
* The `applications` schema attrs stay fixed
|
|
230
|
+
* submit validation + the CRM slot projection; defaults to the reference form.
|
|
231
|
+
* The `applications` schema attrs stay fixed; this is
|
|
190
232
|
* validation config, not schema generation. */
|
|
191
233
|
interface ChapterApplication {
|
|
192
234
|
required?: readonly string[];
|
|
@@ -258,7 +300,7 @@ interface ChapterConfig {
|
|
|
258
300
|
/** `notificationEmail` required in `chapter` mode. */
|
|
259
301
|
emails?: ChapterEmails;
|
|
260
302
|
scheduling?: ChapterScheduling;
|
|
261
|
-
/** Application status pipeline (stages + bookable/approvable subsets).
|
|
303
|
+
/** Application status pipeline (stages + bookable/approvable subsets). */
|
|
262
304
|
pipeline?: ChapterPipeline;
|
|
263
305
|
/** Join-form validation (required/optional fields, max lengths, body cap). */
|
|
264
306
|
application?: ChapterApplication;
|
package/dist/worker/index.js
CHANGED
|
@@ -1138,7 +1138,7 @@ function createStripeProvider(config) {
|
|
|
1138
1138
|
"expand[0]": "latest_invoice.confirmation_secret",
|
|
1139
1139
|
metadata: meta
|
|
1140
1140
|
},
|
|
1141
|
-
//
|
|
1141
|
+
// Hardening: one subscription per application, so a client
|
|
1142
1142
|
// retry between create and the db write can't orphan a second one.
|
|
1143
1143
|
`sub:${input.applicationId}`
|
|
1144
1144
|
);
|
|
@@ -1709,18 +1709,30 @@ var handleAdminPeopleRole = async (req, url, env, ctx) => {
|
|
|
1709
1709
|
};
|
|
1710
1710
|
|
|
1711
1711
|
// src/series.ts
|
|
1712
|
-
function
|
|
1713
|
-
const
|
|
1714
|
-
const
|
|
1715
|
-
const
|
|
1716
|
-
const
|
|
1717
|
-
for (const
|
|
1718
|
-
if (!Number.isFinite(
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1712
|
+
function periodSeries(points, now, count, periodMs) {
|
|
1713
|
+
const start = now - count * periodMs;
|
|
1714
|
+
const previousStart = start - count * periodMs;
|
|
1715
|
+
const current = Array.from({ length: count }, () => 0);
|
|
1716
|
+
const previous = Array.from({ length: count }, () => 0);
|
|
1717
|
+
for (const point of points) {
|
|
1718
|
+
if (!Number.isFinite(point.t) || !Number.isFinite(point.v)) continue;
|
|
1719
|
+
if (point.t >= start && point.t <= now) {
|
|
1720
|
+
const index = Math.min(count - 1, Math.floor((point.t - start) / periodMs));
|
|
1721
|
+
current[index] = (current[index] ?? 0) + point.v;
|
|
1722
|
+
} else if (point.t >= previousStart && point.t < start) {
|
|
1723
|
+
const index = Math.min(count - 1, Math.floor((point.t - previousStart) / periodMs));
|
|
1724
|
+
previous[index] = (previous[index] ?? 0) + point.v;
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
const labels = current.map((_, index) => new Date(start + index * periodMs).toISOString().slice(5, 10));
|
|
1728
|
+
return { labels, current, previous };
|
|
1729
|
+
}
|
|
1730
|
+
function dashboardMetricData(points, now) {
|
|
1731
|
+
const DAY = 864e5;
|
|
1732
|
+
return {
|
|
1733
|
+
wow: periodSeries(points, now, 7, DAY),
|
|
1734
|
+
mom: periodSeries(points, now, 4, 7 * DAY)
|
|
1735
|
+
};
|
|
1724
1736
|
}
|
|
1725
1737
|
function subAnnualCents(sub) {
|
|
1726
1738
|
const items = sub.items?.data ?? [];
|
|
@@ -1803,8 +1815,8 @@ var handleAdminDashboard = async (req, url, env, ctx) => {
|
|
|
1803
1815
|
if (subsRes.ok) {
|
|
1804
1816
|
const subs = rows(subsRes.body.data);
|
|
1805
1817
|
const subMs = (s) => (s.created ?? 0) * 1e3;
|
|
1806
|
-
membersSeries =
|
|
1807
|
-
revenueSeries =
|
|
1818
|
+
membersSeries = dashboardMetricData(subs.map((s) => ({ t: subMs(s), v: 1 })), now);
|
|
1819
|
+
revenueSeries = dashboardMetricData(subs.map((s) => ({ t: subMs(s), v: subAnnualCents(s) })), now);
|
|
1808
1820
|
const active = subs.filter((s) => s.status === "active");
|
|
1809
1821
|
revenue = {
|
|
1810
1822
|
billingReady: true,
|
|
@@ -1816,7 +1828,7 @@ var handleAdminDashboard = async (req, url, env, ctx) => {
|
|
|
1816
1828
|
};
|
|
1817
1829
|
}
|
|
1818
1830
|
}
|
|
1819
|
-
const applicationsSeries =
|
|
1831
|
+
const applicationsSeries = dashboardMetricData(apps.map((a) => ({ t: a.createdAt || 0, v: 1 })), now);
|
|
1820
1832
|
return json({ applications, applicationsSeries, pipeline, pipelineDelta, calls, agenda, timezone, revenue, revenueSeries, membersSeries });
|
|
1821
1833
|
};
|
|
1822
1834
|
var handleAdminBilling = async (req, url, env, ctx) => {
|