@orangecheck/me-client 0.16.0 → 0.18.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.
@@ -0,0 +1,427 @@
1
+ 'use strict';
2
+
3
+ // src/types.ts
4
+ var PLATFORM_FEE_POLICY = {
5
+ /** Fraction of every gross_fee that OC retains. */
6
+ pct: 0.2,
7
+ /** Absolute minimum platform fee, in sats. */
8
+ min_floor_sats: 1,
9
+ /** Date this policy was last ratified. Changes require a versioned
10
+ * @orangecheck/me-client release. */
11
+ ratified: "2026-04-30"
12
+ };
13
+ var MIN_INTEGRATOR_PRICE_SATS = 5;
14
+ function computeFees(cfg, payment_amount_sats) {
15
+ let gross = 0;
16
+ if (cfg.site_pays.kind === "fixed_sats") {
17
+ gross = Math.max(MIN_INTEGRATOR_PRICE_SATS, Math.round(cfg.site_pays.sats));
18
+ } else {
19
+ if (payment_amount_sats == null) {
20
+ throw new Error("percent_of_amount config requires payment_amount_sats");
21
+ }
22
+ gross = Math.max(
23
+ MIN_INTEGRATOR_PRICE_SATS,
24
+ Math.round(payment_amount_sats * cfg.site_pays.pct)
25
+ );
26
+ }
27
+ const platform_fee_sats = Math.max(
28
+ PLATFORM_FEE_POLICY.min_floor_sats,
29
+ Math.round(gross * PLATFORM_FEE_POLICY.pct)
30
+ );
31
+ const user_share = Math.min(0.8, Math.max(0, cfg.user_share_pct));
32
+ const user_earned_sats = Math.round(gross * user_share);
33
+ const site_rebate_sats = Math.max(0, gross - platform_fee_sats - user_earned_sats);
34
+ return { gross_fee_sats: gross, platform_fee_sats, user_earned_sats, site_rebate_sats };
35
+ }
36
+ function validateIntegratorConfig(cfg) {
37
+ const errors = [];
38
+ if (!cfg.project_key) errors.push({ message: "project_key is required" });
39
+ if (!cfg.display_name) errors.push({ message: "display_name is required" });
40
+ if (!cfg.domain) errors.push({ message: "domain is required" });
41
+ for (const [key, eventCfg] of Object.entries(cfg.events)) {
42
+ if (!eventCfg) continue;
43
+ const subtype = key;
44
+ if (!eventCfg.enabled) continue;
45
+ if (eventCfg.site_pays.kind === "fixed_sats") {
46
+ if (eventCfg.site_pays.sats < MIN_INTEGRATOR_PRICE_SATS) {
47
+ errors.push({
48
+ subtype,
49
+ message: `site_pays.sats (${eventCfg.site_pays.sats}) is below MIN_INTEGRATOR_PRICE_SATS (${MIN_INTEGRATOR_PRICE_SATS})`
50
+ });
51
+ }
52
+ } else {
53
+ const pct = eventCfg.site_pays.pct;
54
+ if (!(pct > 0 && pct <= 1)) {
55
+ errors.push({
56
+ subtype,
57
+ message: `site_pays.pct (${pct}) must be in (0, 1]`
58
+ });
59
+ }
60
+ }
61
+ const u = eventCfg.user_share_pct;
62
+ if (u < 0 || u > 0.8) {
63
+ errors.push({
64
+ subtype,
65
+ message: `user_share_pct (${u}) must be in [0, 0.8]; max is 0.8 because platform_fee is ${PLATFORM_FEE_POLICY.pct}`
66
+ });
67
+ }
68
+ }
69
+ return { ok: errors.length === 0, errors };
70
+ }
71
+
72
+ // src/subtypes.ts
73
+ var EVENT_SUBTYPES = {
74
+ // ── Class A · durable state transitions ──
75
+ account_creation: {
76
+ id: "account_creation",
77
+ class: "A",
78
+ label: "account creation",
79
+ fires_when: "a new oc identity creates a durable account record on your surface (first sign-in, profile row inserted)",
80
+ example: "user signed up via email-OTP and your account row was inserted in your DB",
81
+ common_use_cases: ["onboarding", "signup", "registration", "first-login"],
82
+ typical_price_hint: "~1300 sats (~$1.24)"
83
+ },
84
+ account_recovery: {
85
+ id: "account_recovery",
86
+ class: "A",
87
+ label: "account recovery",
88
+ fires_when: "a user re-binds an existing account to a new device or recovery method",
89
+ example: "user lost their device and recovered the account via email OTP + recovery code",
90
+ common_use_cases: ["recovery", "device-rebind", "restore-access"],
91
+ typical_price_hint: "~650 sats (~$0.62)"
92
+ },
93
+ attest_bond_increased: {
94
+ id: "attest_bond_increased",
95
+ class: "A",
96
+ label: "attest bond increased",
97
+ fires_when: "a user upgrades their bond size (locks more sats to attest_tier=bonded with higher cap)",
98
+ example: "user moved from 10k-sat bond to 100k-sat bond to clear your higher-trust gate",
99
+ common_use_cases: ["bond-upgrade", "tier-promotion", "sybil-resistance"],
100
+ typical_price_hint: "~1600 sats (~$1.52) \xB7 OFF by default"
101
+ },
102
+ payment_method_connected: {
103
+ id: "payment_method_connected",
104
+ class: "A",
105
+ label: "payment method connected",
106
+ fires_when: "a user connects a Lightning address, BIP-322 wallet, or payment-routing channel to their account",
107
+ example: "user pasted a lightning@address.com receive address into their profile",
108
+ common_use_cases: ["payment-setup", "wallet-connect", "payout-config"],
109
+ typical_price_hint: "~320 sats (~$0.30)"
110
+ },
111
+ agent_delegation_issued: {
112
+ id: "agent_delegation_issued",
113
+ class: "A",
114
+ label: "agent delegation issued",
115
+ fires_when: "a user signs an oc-agent delegation envelope authorizing an AI agent to act on their behalf",
116
+ example: 'user delegated a "summarize my emails" agent for 24 hours with scope email:read',
117
+ common_use_cases: ["agent-grant", "ai-delegation", "scoped-authorization"],
118
+ typical_price_hint: "~320 sats \xB7 OFF by default (power-user)"
119
+ },
120
+ recovery_method_updated: {
121
+ id: "recovery_method_updated",
122
+ class: "A",
123
+ label: "recovery method updated",
124
+ fires_when: "a user changes their recovery email, recovery key, or social-recovery contacts",
125
+ example: "user rotated their recovery email after a phone change",
126
+ common_use_cases: ["recovery-rotation", "security-update"],
127
+ typical_price_hint: "~160 sats (~$0.15)"
128
+ },
129
+ // ── Class B · action-bound ──
130
+ payment_authorization: {
131
+ id: "payment_authorization",
132
+ class: "B",
133
+ label: "payment authorized",
134
+ fires_when: "a user authorizes a payment of underlying value (Lightning, on-chain BTC, or fiat-quoted)",
135
+ example: "user paid $5.00 (\u22485260 sats) for a premium feature on your site",
136
+ common_use_cases: ["payment", "checkout", "paywall", "subscription"],
137
+ typical_price_hint: "0.75% of payment amount (percent_of_amount)"
138
+ },
139
+ scoped_action_authorization: {
140
+ id: "scoped_action_authorization",
141
+ class: "B",
142
+ label: "scoped action authorized",
143
+ fires_when: "a user takes a specific action your site bills on (post, vote, comment, claim) where each instance is meaningful",
144
+ example: "user posted a long-form review that earns them sats from your editorial budget",
145
+ common_use_cases: ["post", "vote", "comment", "claim", "submit"],
146
+ typical_price_hint: "~100 sats (~$0.10)"
147
+ },
148
+ attest_verification_at_gate: {
149
+ id: "attest_verification_at_gate",
150
+ class: "B",
151
+ label: "attest verification",
152
+ fires_when: "your site's gate consulted the user's attest_tier and admitted them (counted only when admitted)",
153
+ example: "admin gate checked attest_tier=bonded with bond\u226510k sats and granted access",
154
+ common_use_cases: ["gate-check", "tier-gate", "sybil-filter"],
155
+ typical_price_hint: "~280 sats (~$0.27) \xB7 OFF by default"
156
+ },
157
+ stamp_signing: {
158
+ id: "stamp_signing",
159
+ class: "B",
160
+ label: "stamp signed",
161
+ fires_when: "a user signs an oc-stamp envelope (provenance attestation, review credential, content stamp)",
162
+ example: "user stamped their published recipe with their oc identity for downstream verification",
163
+ common_use_cases: ["provenance", "review", "credential", "attestation"],
164
+ typical_price_hint: "~55 sats (~$0.05) \xB7 OFF by default"
165
+ },
166
+ pledge_resolution: {
167
+ id: "pledge_resolution",
168
+ class: "B",
169
+ label: "pledge resolved",
170
+ fires_when: "an oc-pledge bonded commitment resolves (paid out, slashed, or refunded) on your surface",
171
+ example: "user staked 50k sats on a prediction; market resolved and the pledge paid out",
172
+ common_use_cases: ["pledge", "staking", "resolution", "commit-reveal"],
173
+ typical_price_hint: "1% of pledge amount (percent_of_amount) \xB7 OFF by default"
174
+ },
175
+ // ── Class C · session ──
176
+ session_creation: {
177
+ id: "session_creation",
178
+ class: "C",
179
+ label: "session opened",
180
+ fires_when: "a fresh authenticated session is opened for a returning user (sign-in within an existing session is FREE)",
181
+ example: "user signed in after their last session expired; new session token issued",
182
+ common_use_cases: ["sign-in", "session", "authenticate"],
183
+ typical_price_hint: "~55 sats (~$0.05)"
184
+ }
185
+ };
186
+ function subtypesForClass(cls) {
187
+ return Object.values(EVENT_SUBTYPES).filter((m) => m.class === cls);
188
+ }
189
+ var ALL_EVENT_SUBTYPES = [
190
+ ...subtypesForClass("A"),
191
+ ...subtypesForClass("B"),
192
+ ...subtypesForClass("C")
193
+ ];
194
+
195
+ // src/templates.ts
196
+ var FIXED = (sats) => ({
197
+ kind: "fixed_sats",
198
+ sats
199
+ });
200
+ var PCT = (pct) => ({
201
+ kind: "percent_of_amount",
202
+ pct
203
+ });
204
+ var ARCHETYPE_TEMPLATES = [
205
+ {
206
+ id: "saas-paywall",
207
+ label: "SaaS \xB7 paywall",
208
+ summary: "Subscription product \xB7 users sign up, sign in, sometimes pay for premium tiers. Default cashback to encourage signup + retention.",
209
+ examples: ["Notion-like notes app", "Linear-like project tracker", "Figma-like editor"],
210
+ events: {
211
+ account_creation: {
212
+ enabled: true,
213
+ site_pays: FIXED(1300),
214
+ user_share_pct: 0.65
215
+ },
216
+ session_creation: {
217
+ enabled: true,
218
+ site_pays: FIXED(55),
219
+ user_share_pct: 0.65
220
+ },
221
+ payment_authorization: {
222
+ enabled: true,
223
+ site_pays: PCT(75e-4),
224
+ user_share_pct: 0.65
225
+ },
226
+ payment_method_connected: {
227
+ enabled: true,
228
+ site_pays: FIXED(320),
229
+ user_share_pct: 0.65
230
+ }
231
+ }
232
+ },
233
+ {
234
+ id: "marketplace",
235
+ label: "marketplace",
236
+ summary: "Two-sided marketplace \xB7 buyers + sellers transact. Heavy on payment_authorization and scoped_action_authorization for listings.",
237
+ examples: ["Stripe-like checkout", "Etsy-like marketplace", "Uber-like ride-hailing"],
238
+ events: {
239
+ account_creation: {
240
+ enabled: true,
241
+ site_pays: FIXED(1300),
242
+ user_share_pct: 0.65
243
+ },
244
+ session_creation: {
245
+ enabled: true,
246
+ site_pays: FIXED(55),
247
+ user_share_pct: 0.65
248
+ },
249
+ payment_authorization: {
250
+ enabled: true,
251
+ site_pays: PCT(75e-4),
252
+ user_share_pct: 0.65
253
+ },
254
+ scoped_action_authorization: {
255
+ enabled: true,
256
+ site_pays: FIXED(100),
257
+ user_share_pct: 0.65
258
+ },
259
+ payment_method_connected: {
260
+ enabled: true,
261
+ site_pays: FIXED(320),
262
+ user_share_pct: 0.65
263
+ },
264
+ attest_verification_at_gate: {
265
+ enabled: true,
266
+ site_pays: FIXED(280),
267
+ user_share_pct: 0.65
268
+ }
269
+ }
270
+ },
271
+ {
272
+ id: "content-platform",
273
+ label: "content platform",
274
+ summary: "User-generated content \xB7 posts, reviews, votes, comments. Each meaningful action is scoped_action_authorization; stamp_signing for credentialed reviews.",
275
+ examples: ["Reddit-like forum", "YouTube-like video host", "Substack-like publishing"],
276
+ events: {
277
+ account_creation: {
278
+ enabled: true,
279
+ site_pays: FIXED(1300),
280
+ user_share_pct: 0.7
281
+ },
282
+ session_creation: {
283
+ enabled: true,
284
+ site_pays: FIXED(55),
285
+ user_share_pct: 0.7
286
+ },
287
+ scoped_action_authorization: {
288
+ enabled: true,
289
+ site_pays: FIXED(100),
290
+ user_share_pct: 0.7
291
+ },
292
+ stamp_signing: {
293
+ enabled: true,
294
+ site_pays: FIXED(55),
295
+ user_share_pct: 0.7
296
+ }
297
+ }
298
+ },
299
+ {
300
+ id: "gaming",
301
+ label: "gaming",
302
+ summary: "Game with monetized actions \xB7 pledges + scoped actions are core. Higher cashback ratios reward in-game engagement.",
303
+ examples: [
304
+ "on-chain prediction markets",
305
+ "skill-staking tournaments",
306
+ "PvP wager games"
307
+ ],
308
+ events: {
309
+ account_creation: {
310
+ enabled: true,
311
+ site_pays: FIXED(1300),
312
+ user_share_pct: 0.7
313
+ },
314
+ session_creation: {
315
+ enabled: true,
316
+ site_pays: FIXED(55),
317
+ user_share_pct: 0.7
318
+ },
319
+ scoped_action_authorization: {
320
+ enabled: true,
321
+ site_pays: FIXED(100),
322
+ user_share_pct: 0.7
323
+ },
324
+ payment_authorization: {
325
+ enabled: true,
326
+ site_pays: PCT(5e-3),
327
+ user_share_pct: 0.7
328
+ },
329
+ pledge_resolution: {
330
+ enabled: true,
331
+ site_pays: PCT(0.01),
332
+ user_share_pct: 0.7
333
+ },
334
+ attest_verification_at_gate: {
335
+ enabled: true,
336
+ site_pays: FIXED(280),
337
+ user_share_pct: 0.7
338
+ }
339
+ }
340
+ },
341
+ {
342
+ id: "agent-only",
343
+ label: "agent-only",
344
+ summary: "AI-agent surface \xB7 oc-agent delegations are the primary auth pattern. Session_creation off (delegations replace sessions); agent_delegation_issued + scoped_action_authorization carry the activity.",
345
+ examples: [
346
+ "AI assistant calling APIs on user behalf",
347
+ "autonomous trading bot",
348
+ "agent-driven customer support"
349
+ ],
350
+ events: {
351
+ account_creation: {
352
+ enabled: true,
353
+ site_pays: FIXED(1300),
354
+ user_share_pct: 0.65
355
+ },
356
+ agent_delegation_issued: {
357
+ enabled: true,
358
+ site_pays: FIXED(320),
359
+ user_share_pct: 0.65
360
+ },
361
+ scoped_action_authorization: {
362
+ enabled: true,
363
+ site_pays: FIXED(100),
364
+ user_share_pct: 0.65
365
+ }
366
+ }
367
+ }
368
+ ];
369
+ var ARCHETYPES_BY_ID = Object.fromEntries(
370
+ ARCHETYPE_TEMPLATES.map((t) => [t.id, t])
371
+ );
372
+ var ALL_SUBTYPES = [
373
+ "account_creation",
374
+ "account_recovery",
375
+ "attest_bond_increased",
376
+ "payment_method_connected",
377
+ "agent_delegation_issued",
378
+ "recovery_method_updated",
379
+ "payment_authorization",
380
+ "scoped_action_authorization",
381
+ "attest_verification_at_gate",
382
+ "stamp_signing",
383
+ "pledge_resolution",
384
+ "session_creation"
385
+ ];
386
+ var DEFAULT_DISABLED = {
387
+ enabled: false,
388
+ site_pays: { kind: "fixed_sats", sats: 100 },
389
+ user_share_pct: 0.65
390
+ };
391
+ function fromTemplate(useCase, identity) {
392
+ const template = ARCHETYPES_BY_ID[useCase];
393
+ if (!template) {
394
+ throw new Error(
395
+ `oc.config.fromTemplate: unknown archetype "${useCase}". Valid: ${Object.keys(
396
+ ARCHETYPES_BY_ID
397
+ ).join(", ")}`
398
+ );
399
+ }
400
+ const events = {};
401
+ for (const sub of ALL_SUBTYPES) {
402
+ events[sub] = template.events[sub] ?? DEFAULT_DISABLED;
403
+ }
404
+ return {
405
+ project_key: identity.project_key,
406
+ domain: identity.domain,
407
+ display_name: identity.display_name,
408
+ updated_at: (/* @__PURE__ */ new Date()).toISOString(),
409
+ events
410
+ };
411
+ }
412
+ function getArchetypeTemplate(id) {
413
+ return ARCHETYPES_BY_ID[id];
414
+ }
415
+
416
+ exports.ALL_EVENT_SUBTYPES = ALL_EVENT_SUBTYPES;
417
+ exports.ARCHETYPE_TEMPLATES = ARCHETYPE_TEMPLATES;
418
+ exports.EVENT_SUBTYPES = EVENT_SUBTYPES;
419
+ exports.MIN_INTEGRATOR_PRICE_SATS = MIN_INTEGRATOR_PRICE_SATS;
420
+ exports.PLATFORM_FEE_POLICY = PLATFORM_FEE_POLICY;
421
+ exports.computeFees = computeFees;
422
+ exports.configFromTemplate = fromTemplate;
423
+ exports.getArchetypeTemplate = getArchetypeTemplate;
424
+ exports.subtypesForClass = subtypesForClass;
425
+ exports.validateIntegratorConfig = validateIntegratorConfig;
426
+ //# sourceMappingURL=integrator.js.map
427
+ //# sourceMappingURL=integrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/subtypes.ts","../src/templates.ts"],"names":[],"mappings":"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","file":"integrator.js","sourcesContent":["/**\n * Canonical types for me.ochk.io integrators.\n *\n * Mirrors the source of truth at oc-me-web/src/lib/events/types.ts. Two\n * layers:\n * - Platform-level (PLATFORM_FEE_POLICY, MIN_INTEGRATOR_PRICE_SATS) —\n * fixed by OC, surfaced as constants here so integrators can validate\n * their config client-side before posting it.\n * - Integrator-level (IntegratorPriceConfig) — every integrator declares\n * their own per-event prices and user-share splits.\n *\n * Per Addendum 01: every chargeable event is in exactly one of three\n * classes. Sites pay for sessions and actions, not for clicks. Free\n * events never instantiate a BillableEvent.\n */\n\n// ── platform constants (fixed by OC) ──────────────────────────────────────\n\nexport const PLATFORM_FEE_POLICY = {\n /** Fraction of every gross_fee that OC retains. */\n pct: 0.2,\n /** Absolute minimum platform fee, in sats. */\n min_floor_sats: 1,\n /** Date this policy was last ratified. Changes require a versioned\n * @orangecheck/me-client release. */\n ratified: '2026-04-30',\n} as const;\n\n/** Anti-spam price floor. No integrator can configure a per-event price\n * below this. */\nexport const MIN_INTEGRATOR_PRICE_SATS = 5;\n\n// ── event taxonomy ────────────────────────────────────────────────────────\n\nexport type EventClass = 'A' | 'B' | 'C';\n\nexport type ClassASubtype =\n | 'account_creation'\n | 'account_recovery'\n | 'attest_bond_increased'\n | 'payment_method_connected'\n | 'agent_delegation_issued'\n | 'recovery_method_updated';\n\nexport type ClassBSubtype =\n | 'payment_authorization'\n | 'scoped_action_authorization'\n | 'attest_verification_at_gate'\n | 'stamp_signing'\n | 'pledge_resolution';\n\nexport type ClassCSubtype = 'session_creation';\n\nexport type EventSubtype = ClassASubtype | ClassBSubtype | ClassCSubtype;\n\n/** AttestTier · what an integrator's gate can read about an oc identity.\n *\n * me.ochk does NOT do KYC. Sybil resistance is bounded by three\n * composable mechanisms, none of which involve OC handling PII:\n * 1. paid-action history · billable events cost real sats\n * 2. BIP-322 sat-bonding · bond size + age via signed attestation\n * 3. integrator-defined gates · per-site threat-model overlays\n *\n * Tier itself is intentionally simple — anonymous | bonded.\n * Granularity (bond_sats, bond_locked_at, etc) carried separately. */\nexport type AttestTier = 'anonymous' | 'bonded';\n\n/** The shape of a per-event fee — either a fixed sats amount or a percent\n * of the underlying transaction amount (used for payments + pledges). */\nexport type SiteFeeShape =\n | { kind: 'fixed_sats'; sats: number }\n | { kind: 'percent_of_amount'; pct: number };\n\n/** What an integrator declares for a single event subtype. */\nexport interface IntegratorEventConfig {\n /** Whether this site bills this event subtype at all. */\n enabled: boolean;\n /** The per-event fee the site pays. */\n site_pays: SiteFeeShape;\n /** Fraction of post-platform-fee that flows to the user (0–0.8 since\n * platform_fee is 20%). The remainder is a rebate to the site's OC\n * project balance. */\n user_share_pct: number;\n}\n\n/** A complete integrator pricing config. Posted to me.ochk.io once at\n * integration time, mutable via the configurator UI or this SDK any time\n * after. */\nexport interface IntegratorPriceConfig {\n project_key: string;\n display_name: string;\n domain: string;\n /** ISO-8601 timestamp the config was last updated. */\n updated_at: string;\n /** Per-subtype configs. Subtypes not listed are disabled by default. */\n events: Partial<Record<EventSubtype, IntegratorEventConfig>>;\n}\n\n/** A computed fee breakdown for a single event. site_rebate_sats is what\n * flows back to the integrator's OC balance after OC's platform fee and\n * the user's cashback. */\nexport interface ComputedFees {\n gross_fee_sats: number;\n platform_fee_sats: number;\n user_earned_sats: number;\n site_rebate_sats: number;\n}\n\n/** Compute the four-way fee split for an event given an integrator's\n * config and (for percent_of_amount events) the underlying payment\n * amount.\n *\n * Invariants (verified by tests in oc-me-web/src/lib/events/types.test.ts):\n * 1. gross_fee_sats >= MIN_INTEGRATOR_PRICE_SATS\n * 2. platform_fee_sats >= PLATFORM_FEE_POLICY.min_floor_sats\n * 3. user_share_pct is clamped to [0, 0.8]\n * 4. site_rebate_sats >= 0\n * 5. gross == platform + user + rebate (exact, modulo rounding into rebate)\n */\nexport function computeFees(\n cfg: IntegratorEventConfig,\n payment_amount_sats?: number\n): ComputedFees {\n let gross = 0;\n if (cfg.site_pays.kind === 'fixed_sats') {\n gross = Math.max(MIN_INTEGRATOR_PRICE_SATS, Math.round(cfg.site_pays.sats));\n } else {\n if (payment_amount_sats == null) {\n throw new Error('percent_of_amount config requires payment_amount_sats');\n }\n gross = Math.max(\n MIN_INTEGRATOR_PRICE_SATS,\n Math.round(payment_amount_sats * cfg.site_pays.pct)\n );\n }\n const platform_fee_sats = Math.max(\n PLATFORM_FEE_POLICY.min_floor_sats,\n Math.round(gross * PLATFORM_FEE_POLICY.pct)\n );\n const user_share = Math.min(0.8, Math.max(0, cfg.user_share_pct));\n const user_earned_sats = Math.round(gross * user_share);\n const site_rebate_sats = Math.max(0, gross - platform_fee_sats - user_earned_sats);\n return { gross_fee_sats: gross, platform_fee_sats, user_earned_sats, site_rebate_sats };\n}\n\n/** Result of validating an IntegratorPriceConfig. */\nexport interface ValidationResult {\n ok: boolean;\n errors: { subtype?: EventSubtype; message: string }[];\n}\n\n/**\n * Validate an integrator's pricing config against the platform's\n * non-negotiable rules. Run client-side before posting; the server runs\n * the same checks and rejects anything that fails.\n */\nexport function validateIntegratorConfig(cfg: IntegratorPriceConfig): ValidationResult {\n const errors: ValidationResult['errors'] = [];\n\n if (!cfg.project_key) errors.push({ message: 'project_key is required' });\n if (!cfg.display_name) errors.push({ message: 'display_name is required' });\n if (!cfg.domain) errors.push({ message: 'domain is required' });\n\n for (const [key, eventCfg] of Object.entries(cfg.events)) {\n if (!eventCfg) continue;\n const subtype = key as EventSubtype;\n if (!eventCfg.enabled) continue;\n\n if (eventCfg.site_pays.kind === 'fixed_sats') {\n if (eventCfg.site_pays.sats < MIN_INTEGRATOR_PRICE_SATS) {\n errors.push({\n subtype,\n message: `site_pays.sats (${eventCfg.site_pays.sats}) is below MIN_INTEGRATOR_PRICE_SATS (${MIN_INTEGRATOR_PRICE_SATS})`,\n });\n }\n } else {\n const pct = eventCfg.site_pays.pct;\n if (!(pct > 0 && pct <= 1)) {\n errors.push({\n subtype,\n message: `site_pays.pct (${pct}) must be in (0, 1]`,\n });\n }\n }\n\n const u = eventCfg.user_share_pct;\n if (u < 0 || u > 0.8) {\n errors.push({\n subtype,\n message: `user_share_pct (${u}) must be in [0, 0.8]; max is 0.8 because platform_fee is ${PLATFORM_FEE_POLICY.pct}`,\n });\n }\n }\n\n return { ok: errors.length === 0, errors };\n}\n\n// ── canonical envelope ────────────────────────────────────────────────────\n\nexport interface BillableEvent {\n id: string;\n occurred_at: string;\n class: EventClass;\n subtype: EventSubtype;\n site: { domain: string; display_name: string };\n gross_fee_sats: number;\n platform_fee_sats: number;\n user_earned_sats: number;\n site_rebate_sats: number;\n verify_url: string;\n /** Per OCHK-V3-PLAN §7 phase-1 · true when the event was fired by\n * an oc-agent delegation rather than a human session. The\n * integrator's IntegratorEventConfig.agent block may price\n * these differently or refuse them. Optional · canonical encoder\n * branches to v=3 only when present, so legacy human-fired\n * events keep their v=2 hash + signature. */\n is_agent?: boolean;\n}\n\n// ── webhook payload ───────────────────────────────────────────────────────\n\n/**\n * The exact JSON body delivered to a registered webhook endpoint when\n * a billable event fires. Imported by integrator backends so the\n * receive handler is type-checked end-to-end without re-declaring the\n * shape.\n *\n * import type { WebhookPayload } from '@orangecheck/me-client';\n *\n * export async function POST(req: Request) {\n * const payload = (await req.json()) as WebhookPayload;\n * if (payload.subtype === 'payment_authorization') {\n * creditUser(payload.sub, payload.user_earned_sats);\n * }\n * }\n *\n * Headers carry the signature and metadata (see WebhookHeaders below).\n * Verify the signature with `oc.webhook.verify({ body, headers, jwks })`.\n *\n * Privacy contract · the master oc identity is NEVER in the payload.\n * Integrators see `sub` (per-integrator anonymous id) plus any\n * `scopes` the user explicitly granted. See PRIVACY-ARCHITECTURE.md.\n */\nexport interface WebhookPayload extends BillableEvent {\n /** Discriminator · identifies the payload kind for routing on\n * the integrator's side. Always 'oc-billable-event' today; future\n * webhook payload kinds (refunds, charters, etc) will use\n * distinct discriminator values. */\n kind: 'oc-billable-event';\n /** Per-integrator anonymous subject id · stable across events for\n * the same (oc_identity, project_key) pair. Key your user records\n * on this; OC will never give you the master address unless the\n * user explicitly grants `bitcoin_address` or `email` scope. */\n sub: string;\n /** Resolved scoped fields · only present for scopes the user has\n * granted to this project. Wire format is string-keyed (every\n * value is stringified · ints stringified, addresses as-is). */\n scopes?: Partial<\n Record<\n | 'bitcoin_address'\n | 'email'\n | 'attest_tier'\n | 'display_name'\n | 'cross_integrator_event_count'\n | 'cross_integrator_human_event_count'\n | 'trust_attestation_count'\n | 'trust_attestations_bundle',\n string\n >\n >;\n}\n\n/**\n * HTTP headers OC sends with every webhook delivery. Capture these in\n * the receive handler · `OC-Signature` is what verifies the body.\n */\nexport interface WebhookHeaders {\n /** Ed25519 signature over the raw response body, hex-encoded. */\n 'OC-Signature': string;\n /** Stable kid of the signing key · resolves against\n * ochk.io/.well-known/jwks.json. */\n 'OC-Key-Id': string;\n /** Envelope id · matches payload.id; useful for idempotent\n * receive handlers that dedupe on this header without parsing\n * the body. */\n 'OC-Envelope-Id': string;\n /** Subtype · matches payload.subtype; lets routers branch on the\n * header before parsing. */\n 'OC-Subtype': EventSubtype;\n /** Class · matches payload.class. */\n 'OC-Class': EventClass;\n /** 1-indexed delivery attempt count. >1 means the prior attempt\n * did not return a 2xx within the timeout · idempotency key on\n * payload.id is critical. */\n 'OC-Delivery-Attempt': string;\n}\n\n// ── session lifecycle ────────────────────────────────────────────────────\n\nexport interface SessionPolicy {\n duration_seconds: number;\n refresh: 'sliding' | 'rolling' | 'none';\n sensitive_actions?: 're-auth' | 'none';\n}\n\nexport interface Session {\n id: string;\n identity: string;\n opens_at: string;\n expires_at: string;\n policy: SessionPolicy;\n scope: string[];\n}\n\nexport interface SignInOptions {\n scope: string[];\n sessionPolicy?: Partial<SessionPolicy>;\n returnTo?: string;\n}\n\nexport interface PaymentAuthorizeOptions {\n identity: string;\n amount_sats?: number;\n usd_cents?: number;\n description: string;\n external_ref?: string;\n}\n\nexport interface PaymentResult {\n id: string;\n status: 'authorized' | 'failed' | 'cancelled';\n sats_charged?: number;\n user_envelope_id?: string;\n verify_url?: string;\n}\n\nexport interface TelemetryEvent {\n code:\n | 'session.intra_signin'\n | 'session.token_refresh'\n | 'session.navigation'\n | 'auth.signin_failed'\n | 'auth.signin_cancelled'\n | 'auth.signin_rejected'\n | 'verify.passive_check';\n timestamp: string;\n session_id?: string;\n}\n\n// ── federation directory ───────────────────────────────────────────────\n//\n// The SDK consumes the federation directory at runtime so multi-federation\n// routing is a directory write, not a code change. v1 has one live\n// federation; the directory is plural-shaped so federation #2 lights up\n// without an SDK release.\n\nexport type FederationStatus = 'recruiting' | 'forming' | 'binding' | 'live';\n\n/** Federation directory entry. Mirrors `oc-me-web/src/lib/federations/registry.ts`\n * field-for-field; this package is the public consumption shape. */\nexport interface Federation {\n slug: string;\n name: string;\n status: FederationStatus;\n threshold: string;\n target_guardian_count: number;\n /** Fedimint invite code; null until status === 'live'. */\n invite: string | null;\n /** SHA-256 of the canonical federation charter, hex-encoded. */\n charter_hash: string | null;\n /** ISO-8601 of the most recent ongoing-attestation envelope. */\n last_attestation_at: string | null;\n geography_hint: string;\n // Operator-recruiting fields (present on slots in 'recruiting' /\n // 'forming' / 'binding' state). Nullable so one shape spans the\n // lifecycle.\n geography_requirements?: string;\n charter_status?: string;\n ceremony_window?: string;\n why_this_one?: string;\n apply_cta?: string;\n apply_href?: string;\n}\n\n/** SigningMethod discriminator on the user identity. Federation-agnostic\n * by construction — the OC identity (did:email or BIP-322 address)\n * remains stable across all three states. Transitions are recorded as\n * anchored \"rebind\" envelopes on the canonical event log. Graduation\n * is the product thesis; this discriminator is the structural primitive\n * that records where a user is on the custody-state graph. */\nexport type SigningMethod = 'fedimint_threshold' | 'fedimint_client' | 'bip322';\n","/**\n * Rich metadata for every billable event subtype.\n *\n * The SDK already exports the `EventSubtype` union (closed enum, type-\n * checked), but a new integrator picking between\n * `'scoped_action_authorization'` and `'stamp_signing'` and\n * `'attest_verification_at_gate'` has no inline guidance on which fits\n * their flow. This file is the canonical \"when do I use this subtype\"\n * reference, programmatically accessible:\n *\n * import { oc, EVENT_SUBTYPES } from '@orangecheck/me-client';\n *\n * for (const meta of Object.values(EVENT_SUBTYPES)) {\n * console.log(`${meta.id} (class ${meta.class}) — ${meta.fires_when}`);\n * }\n *\n * Or per-subtype:\n *\n * const meta = EVENT_SUBTYPES.account_creation;\n * console.log(meta.example); // → \"user signed up via email-OTP and the account row was inserted\"\n *\n * Used by `oc.config.fromTemplate()` to assemble archetype configs and\n * by /me/projects/* dashboards to drive consent prompts and config\n * editor labels from a single source.\n */\n\nimport type { EventClass, EventSubtype } from './types';\n\nexport interface EventSubtypeMetadata {\n id: EventSubtype;\n class: EventClass;\n /** Short label · matches SUBTYPE_LABELS on the server. */\n label: string;\n /** When this fires · imperative-mood plain English. The integrator\n * reads this to know which event in their codebase should call\n * `oc.event.fire()` with this subtype. */\n fires_when: string;\n /** A concrete example from a typical SaaS · helps integrators map\n * an unfamiliar subtype name to a real flow they recognize. */\n example: string;\n /** Common use cases · lets integrators search their own product\n * for matching flows. Two-three terms each, lowercase. */\n common_use_cases: readonly string[];\n /** What an integrator typically pays for this subtype, anchored at\n * $1 ≈ 1052 sats. Returns null for percent-of-amount subtypes\n * where the price scales with the underlying transaction. */\n typical_price_hint: string;\n}\n\nexport const EVENT_SUBTYPES: Record<EventSubtype, EventSubtypeMetadata> = {\n // ── Class A · durable state transitions ──\n account_creation: {\n id: 'account_creation',\n class: 'A',\n label: 'account creation',\n fires_when:\n 'a new oc identity creates a durable account record on your surface (first sign-in, profile row inserted)',\n example: 'user signed up via email-OTP and your account row was inserted in your DB',\n common_use_cases: ['onboarding', 'signup', 'registration', 'first-login'],\n typical_price_hint: '~1300 sats (~$1.24)',\n },\n account_recovery: {\n id: 'account_recovery',\n class: 'A',\n label: 'account recovery',\n fires_when:\n 'a user re-binds an existing account to a new device or recovery method',\n example: 'user lost their device and recovered the account via email OTP + recovery code',\n common_use_cases: ['recovery', 'device-rebind', 'restore-access'],\n typical_price_hint: '~650 sats (~$0.62)',\n },\n attest_bond_increased: {\n id: 'attest_bond_increased',\n class: 'A',\n label: 'attest bond increased',\n fires_when:\n 'a user upgrades their bond size (locks more sats to attest_tier=bonded with higher cap)',\n example: 'user moved from 10k-sat bond to 100k-sat bond to clear your higher-trust gate',\n common_use_cases: ['bond-upgrade', 'tier-promotion', 'sybil-resistance'],\n typical_price_hint: '~1600 sats (~$1.52) · OFF by default',\n },\n payment_method_connected: {\n id: 'payment_method_connected',\n class: 'A',\n label: 'payment method connected',\n fires_when:\n 'a user connects a Lightning address, BIP-322 wallet, or payment-routing channel to their account',\n example: 'user pasted a lightning@address.com receive address into their profile',\n common_use_cases: ['payment-setup', 'wallet-connect', 'payout-config'],\n typical_price_hint: '~320 sats (~$0.30)',\n },\n agent_delegation_issued: {\n id: 'agent_delegation_issued',\n class: 'A',\n label: 'agent delegation issued',\n fires_when:\n 'a user signs an oc-agent delegation envelope authorizing an AI agent to act on their behalf',\n example: 'user delegated a \"summarize my emails\" agent for 24 hours with scope email:read',\n common_use_cases: ['agent-grant', 'ai-delegation', 'scoped-authorization'],\n typical_price_hint: '~320 sats · OFF by default (power-user)',\n },\n recovery_method_updated: {\n id: 'recovery_method_updated',\n class: 'A',\n label: 'recovery method updated',\n fires_when:\n 'a user changes their recovery email, recovery key, or social-recovery contacts',\n example: 'user rotated their recovery email after a phone change',\n common_use_cases: ['recovery-rotation', 'security-update'],\n typical_price_hint: '~160 sats (~$0.15)',\n },\n\n // ── Class B · action-bound ──\n payment_authorization: {\n id: 'payment_authorization',\n class: 'B',\n label: 'payment authorized',\n fires_when:\n 'a user authorizes a payment of underlying value (Lightning, on-chain BTC, or fiat-quoted)',\n example: 'user paid $5.00 (≈5260 sats) for a premium feature on your site',\n common_use_cases: ['payment', 'checkout', 'paywall', 'subscription'],\n typical_price_hint: '0.75% of payment amount (percent_of_amount)',\n },\n scoped_action_authorization: {\n id: 'scoped_action_authorization',\n class: 'B',\n label: 'scoped action authorized',\n fires_when:\n 'a user takes a specific action your site bills on (post, vote, comment, claim) where each instance is meaningful',\n example: 'user posted a long-form review that earns them sats from your editorial budget',\n common_use_cases: ['post', 'vote', 'comment', 'claim', 'submit'],\n typical_price_hint: '~100 sats (~$0.10)',\n },\n attest_verification_at_gate: {\n id: 'attest_verification_at_gate',\n class: 'B',\n label: 'attest verification',\n fires_when:\n \"your site's gate consulted the user's attest_tier and admitted them (counted only when admitted)\",\n example: 'admin gate checked attest_tier=bonded with bond≥10k sats and granted access',\n common_use_cases: ['gate-check', 'tier-gate', 'sybil-filter'],\n typical_price_hint: '~280 sats (~$0.27) · OFF by default',\n },\n stamp_signing: {\n id: 'stamp_signing',\n class: 'B',\n label: 'stamp signed',\n fires_when:\n 'a user signs an oc-stamp envelope (provenance attestation, review credential, content stamp)',\n example: 'user stamped their published recipe with their oc identity for downstream verification',\n common_use_cases: ['provenance', 'review', 'credential', 'attestation'],\n typical_price_hint: '~55 sats (~$0.05) · OFF by default',\n },\n pledge_resolution: {\n id: 'pledge_resolution',\n class: 'B',\n label: 'pledge resolved',\n fires_when:\n 'an oc-pledge bonded commitment resolves (paid out, slashed, or refunded) on your surface',\n example: 'user staked 50k sats on a prediction; market resolved and the pledge paid out',\n common_use_cases: ['pledge', 'staking', 'resolution', 'commit-reveal'],\n typical_price_hint: '1% of pledge amount (percent_of_amount) · OFF by default',\n },\n\n // ── Class C · session ──\n session_creation: {\n id: 'session_creation',\n class: 'C',\n label: 'session opened',\n fires_when:\n 'a fresh authenticated session is opened for a returning user (sign-in within an existing session is FREE)',\n example: 'user signed in after their last session expired; new session token issued',\n common_use_cases: ['sign-in', 'session', 'authenticate'],\n typical_price_hint: '~55 sats (~$0.05)',\n },\n};\n\n/** All subtypes for a given class · convenience accessor. */\nexport function subtypesForClass(cls: EventClass): EventSubtypeMetadata[] {\n return Object.values(EVENT_SUBTYPES).filter((m) => m.class === cls);\n}\n\n/** All subtypes as a flat list, ordered class A → B → C. */\nexport const ALL_EVENT_SUBTYPES: readonly EventSubtypeMetadata[] = [\n ...subtypesForClass('A'),\n ...subtypesForClass('B'),\n ...subtypesForClass('C'),\n];\n","/**\n * Archetype templates for `oc.config.fromTemplate(useCase, ...)`.\n *\n * A new integrator with a 30-second decision shouldn't have to fill\n * 12 IntegratorEventConfig entries by hand. Pick the archetype that\n * matches your site, get a sensible starting config, tweak whatever\n * you want, submit:\n *\n * import { oc } from '@orangecheck/me-client';\n *\n * const config = oc.config.fromTemplate('saas-paywall', {\n * project_key: 'pk_live_yourcompany',\n * domain: 'yoursite.com',\n * display_name: 'Your Site',\n * });\n * await oc.config.save(config);\n *\n * Templates differ on which subtypes are enabled (a content platform\n * doesn't need payment_authorization; a marketplace does) and on the\n * sat price + user_share_pct per subtype. Every template's prices\n * anchor at $1 ≈ 1052 sats. user_share_pct=0.65 means the user gets\n * 65% of gross — the platform fee is 20% (fixed), the integrator\n * rebate is the remainder (15% with 0.65 user share).\n *\n * To customize after picking a template:\n *\n * const config = oc.config.fromTemplate('marketplace', { ... });\n * config.events.payment_authorization!.site_pays = {\n * kind: 'percent_of_amount',\n * pct: 0.005, // 0.5% instead of the template's 0.75%\n * };\n */\n\nimport type {\n EventSubtype,\n IntegratorEventConfig,\n IntegratorPriceConfig,\n} from './types';\n\nexport type IntegratorArchetype =\n | 'saas-paywall'\n | 'marketplace'\n | 'content-platform'\n | 'gaming'\n | 'agent-only';\n\ninterface ProjectIdentity {\n project_key: string;\n domain: string;\n display_name: string;\n}\n\n/** Template descriptor · what each archetype enables and prices.\n * Exposed so dashboards can render \"you're using the X template\"\n * state and offer one-click swaps. */\nexport interface ArchetypeTemplate {\n id: IntegratorArchetype;\n label: string;\n /** One-sentence summary shown next to the picker. */\n summary: string;\n /** Concrete examples of sites this archetype fits. */\n examples: readonly string[];\n /** Per-subtype config the template emits. Subtypes not listed are\n * emitted as `enabled: false` (the SDK fills them with a\n * conservative default to keep the type happy without firing). */\n events: Partial<Record<EventSubtype, IntegratorEventConfig>>;\n}\n\nconst FIXED = (sats: number): IntegratorEventConfig['site_pays'] => ({\n kind: 'fixed_sats',\n sats,\n});\nconst PCT = (pct: number): IntegratorEventConfig['site_pays'] => ({\n kind: 'percent_of_amount',\n pct,\n});\n\n/**\n * The full archetype catalog. Add new templates here · one record per\n * common integrator pattern. Keep the list curated (≤8 archetypes) —\n * if there are too many, none feel like the obvious default and\n * integrators stall on the picker.\n */\nexport const ARCHETYPE_TEMPLATES: readonly ArchetypeTemplate[] = [\n {\n id: 'saas-paywall',\n label: 'SaaS · paywall',\n summary:\n 'Subscription product · users sign up, sign in, sometimes pay for premium tiers. Default cashback to encourage signup + retention.',\n examples: ['Notion-like notes app', 'Linear-like project tracker', 'Figma-like editor'],\n events: {\n account_creation: {\n enabled: true,\n site_pays: FIXED(1300),\n user_share_pct: 0.65,\n },\n session_creation: {\n enabled: true,\n site_pays: FIXED(55),\n user_share_pct: 0.65,\n },\n payment_authorization: {\n enabled: true,\n site_pays: PCT(0.0075),\n user_share_pct: 0.65,\n },\n payment_method_connected: {\n enabled: true,\n site_pays: FIXED(320),\n user_share_pct: 0.65,\n },\n },\n },\n {\n id: 'marketplace',\n label: 'marketplace',\n summary:\n 'Two-sided marketplace · buyers + sellers transact. Heavy on payment_authorization and scoped_action_authorization for listings.',\n examples: ['Stripe-like checkout', 'Etsy-like marketplace', 'Uber-like ride-hailing'],\n events: {\n account_creation: {\n enabled: true,\n site_pays: FIXED(1300),\n user_share_pct: 0.65,\n },\n session_creation: {\n enabled: true,\n site_pays: FIXED(55),\n user_share_pct: 0.65,\n },\n payment_authorization: {\n enabled: true,\n site_pays: PCT(0.0075),\n user_share_pct: 0.65,\n },\n scoped_action_authorization: {\n enabled: true,\n site_pays: FIXED(100),\n user_share_pct: 0.65,\n },\n payment_method_connected: {\n enabled: true,\n site_pays: FIXED(320),\n user_share_pct: 0.65,\n },\n attest_verification_at_gate: {\n enabled: true,\n site_pays: FIXED(280),\n user_share_pct: 0.65,\n },\n },\n },\n {\n id: 'content-platform',\n label: 'content platform',\n summary:\n 'User-generated content · posts, reviews, votes, comments. Each meaningful action is scoped_action_authorization; stamp_signing for credentialed reviews.',\n examples: ['Reddit-like forum', 'YouTube-like video host', 'Substack-like publishing'],\n events: {\n account_creation: {\n enabled: true,\n site_pays: FIXED(1300),\n user_share_pct: 0.7,\n },\n session_creation: {\n enabled: true,\n site_pays: FIXED(55),\n user_share_pct: 0.7,\n },\n scoped_action_authorization: {\n enabled: true,\n site_pays: FIXED(100),\n user_share_pct: 0.7,\n },\n stamp_signing: {\n enabled: true,\n site_pays: FIXED(55),\n user_share_pct: 0.7,\n },\n },\n },\n {\n id: 'gaming',\n label: 'gaming',\n summary:\n 'Game with monetized actions · pledges + scoped actions are core. Higher cashback ratios reward in-game engagement.',\n examples: [\n 'on-chain prediction markets',\n 'skill-staking tournaments',\n 'PvP wager games',\n ],\n events: {\n account_creation: {\n enabled: true,\n site_pays: FIXED(1300),\n user_share_pct: 0.7,\n },\n session_creation: {\n enabled: true,\n site_pays: FIXED(55),\n user_share_pct: 0.7,\n },\n scoped_action_authorization: {\n enabled: true,\n site_pays: FIXED(100),\n user_share_pct: 0.7,\n },\n payment_authorization: {\n enabled: true,\n site_pays: PCT(0.005),\n user_share_pct: 0.7,\n },\n pledge_resolution: {\n enabled: true,\n site_pays: PCT(0.01),\n user_share_pct: 0.7,\n },\n attest_verification_at_gate: {\n enabled: true,\n site_pays: FIXED(280),\n user_share_pct: 0.7,\n },\n },\n },\n {\n id: 'agent-only',\n label: 'agent-only',\n summary:\n 'AI-agent surface · oc-agent delegations are the primary auth pattern. Session_creation off (delegations replace sessions); agent_delegation_issued + scoped_action_authorization carry the activity.',\n examples: [\n 'AI assistant calling APIs on user behalf',\n 'autonomous trading bot',\n 'agent-driven customer support',\n ],\n events: {\n account_creation: {\n enabled: true,\n site_pays: FIXED(1300),\n user_share_pct: 0.65,\n },\n agent_delegation_issued: {\n enabled: true,\n site_pays: FIXED(320),\n user_share_pct: 0.65,\n },\n scoped_action_authorization: {\n enabled: true,\n site_pays: FIXED(100),\n user_share_pct: 0.65,\n },\n },\n },\n];\n\nconst ARCHETYPES_BY_ID: Record<IntegratorArchetype, ArchetypeTemplate> = Object.fromEntries(\n ARCHETYPE_TEMPLATES.map((t) => [t.id, t])\n) as Record<IntegratorArchetype, ArchetypeTemplate>;\n\n/** All 12 subtypes — used to fill `enabled: false` defaults for any\n * subtype the chosen archetype doesn't list. */\nconst ALL_SUBTYPES: readonly EventSubtype[] = [\n 'account_creation',\n 'account_recovery',\n 'attest_bond_increased',\n 'payment_method_connected',\n 'agent_delegation_issued',\n 'recovery_method_updated',\n 'payment_authorization',\n 'scoped_action_authorization',\n 'attest_verification_at_gate',\n 'stamp_signing',\n 'pledge_resolution',\n 'session_creation',\n];\n\nconst DEFAULT_DISABLED: IntegratorEventConfig = {\n enabled: false,\n site_pays: { kind: 'fixed_sats', sats: 100 },\n user_share_pct: 0.65,\n};\n\n/**\n * Build a complete IntegratorPriceConfig from an archetype id + the\n * project's identity fields. Every subtype gets an entry — the\n * archetype's listed subtypes get the template's pricing; everything\n * else gets `enabled: false` with conservative defaults so the config\n * is type-complete and the integrator can flip-on later subtypes\n * without re-deriving prices.\n *\n * Throws synchronously if `useCase` isn't a known archetype id.\n */\nexport function fromTemplate(\n useCase: IntegratorArchetype,\n identity: ProjectIdentity\n): IntegratorPriceConfig {\n const template = ARCHETYPES_BY_ID[useCase];\n if (!template) {\n throw new Error(\n `oc.config.fromTemplate: unknown archetype \"${useCase}\". Valid: ${Object.keys(\n ARCHETYPES_BY_ID\n ).join(', ')}`\n );\n }\n const events: IntegratorPriceConfig['events'] = {};\n for (const sub of ALL_SUBTYPES) {\n events[sub] = template.events[sub] ?? DEFAULT_DISABLED;\n }\n return {\n project_key: identity.project_key,\n domain: identity.domain,\n display_name: identity.display_name,\n updated_at: new Date().toISOString(),\n events,\n };\n}\n\n/** Look up a template's metadata · used by config-editor UIs to render\n * \"you're on the X template · here's what it enables\" copy. */\nexport function getArchetypeTemplate(id: IntegratorArchetype): ArchetypeTemplate {\n return ARCHETYPES_BY_ID[id];\n}\n"]}