@orangecheck/me-client 0.28.0 → 0.29.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 CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  Client for [me.ochk.io](https://me.ochk.io). Popup sign-in for any site, framework-agnostic server-side verification, session lifecycle hooks, payment authorization, webhook signature verification, the canonical billable-event taxonomy as TypeScript types. `OcSignInButton` rides the family cookie, so it works only on orangecheck's own sites; anywhere else, sign people in with `signInWithOc()` from `/popup`.
8
8
 
9
- > You pay for sessions and actions, not for clicks.
9
+ > Sign-in is free. Paying your users is optional: always, in promos you schedule, or never.
10
10
 
11
11
  ## Three entry points, three audiences
12
12
 
@@ -73,6 +73,24 @@ export default withOcAuth(handler, {
73
73
 
74
74
  Or set it in code with `requireBond: { minSats: 100_000, minDays: 30, maxAgeSecs: 3600 }`. ochk.io re-checks the coin when its last check is over ten minutes old; `maxAgeSecs` refuses a claim checked longer ago than you accept. From 0.28.0, an account below the floor gets `403 { ok: false, reason: 'bond_required', need: { min_sats, min_days }, have: { sats_floor, days_floor } | null, back_url }`: link the person to `back_url` to back their account. If the project's setting can't be read and never has been, the request gets `503 { reason: 'bond_policy_unavailable' }` rather than being let through unchecked. `readBondClaim(session)` and `bondMeets(session, { minSats, minDays, maxAgeSecs })` are exported for your own checks.
75
75
 
76
+ ## Pay your users, when you choose to
77
+
78
+ Paying the people who use your app is optional. In your project's dashboard you turn it on, schedule promos ("Launch week", Oct 20 to 27), or leave it off. While a pay period runs, each event you send earns the person their share and takes its fee from your balance. Outside every period an event earns and costs nothing, and me.ochk.io records nothing, so you can fire events from code that runs all the time:
79
+
80
+ ```ts
81
+ const res = await oc.event.fire({
82
+ project_key: 'pk_live_yourcompany',
83
+ subtype: 'account_creation',
84
+ signingSecret: process.env.OC_SIGNING_SECRET,
85
+ userAddress: didOc,
86
+ });
87
+ if (!res.earned) {
88
+ // res.reason === 'not_paying'; res.next_pay_period says when paying starts, if scheduled
89
+ }
90
+ ```
91
+
92
+ `fireBatch` answers `not_paying` per event. `GET /api/integrator/config` publishes the project's `pay_periods`, past ones included, and `payingAt(periods, date)` tells you whether a project pays at a moment. Pass them to `oc.event.verify(envelope, config, amount, { payPeriods })` to flag a receipt billed outside every period.
93
+
76
94
  ## Session lifecycle
77
95
 
78
96
  Sessions are the billable atom for me.ochk.io: your server fires one `session_creation` event per real session with `oc.event.fire`. `oc.session.create` opens a session and records no charge, and a signin within a still-valid session is **free**. Site declares the policy at integration time; the OC verifier enforces it both client-side and server-side.
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { v as verifyActivityAttestation, r as refreshEnvelopeJwks } from './identity-1VYMOhzV.mjs';
2
2
  export { A as ActivityAttestation, a as ActivityAttestationBundle, b as ActivityVerifyCheck, c as ActivityVerifyResult, V as VerifyActivityOptions, i as identity } from './identity-1VYMOhzV.mjs';
3
- import { E as EventKey, B as BillableEvent, I as IntegratorPriceConfig, S as SessionPolicy, a as Session, T as TelemetryEvent, b as SignInOptions, P as PaymentAuthorizeOptions, c as PaymentResult, V as ValidationResult, f as fromTemplate, g as getArchetypeTemplate, A as ArchetypeTemplate, F as Federation } from './integrator-BVzzkZ6l.mjs';
3
+ import { B as BillableEvent, E as EventKey, I as IntegratorPriceConfig, S as SessionPolicy, a as Session, T as TelemetryEvent, b as SignInOptions, P as PaymentAuthorizeOptions, c as PaymentResult, V as ValidationResult, f as fromTemplate, g as getArchetypeTemplate, A as ArchetypeTemplate, F as Federation } from './integrator-BVzzkZ6l.mjs';
4
4
  export { d as ALL_EVENT_SUBTYPES, e as ARCHETYPE_TEMPLATES, h as AgentClassOverride, i as AttestTier, C as ClassASubtype, j as ClassBSubtype, k as ClassCSubtype, l as ComputedFees, D as DropCadence, m as DropClosedWebhookPayload, n as DropResponseBlock, o as DropScheduleSummary, p as EVENT_SUBTYPES, q as EventClass, r as EventSubtype, s as EventSubtypeMetadata, t as FederationStatus, u as IntegratorArchetype, v as IntegratorEventConfig, M as MAX_DROP_WINDOW_DAYS, w as MIN_INTEGRATOR_PRICE_SATS, x as PLATFORM_FEE_POLICY, y as SigningMethod, z as SiteFeeShape, G as SystemWebhookPayload, W as WebhookHeaders, H as WebhookPayload, J as computeFees, K as subtypesForClass, L as validateIntegratorConfig } from './integrator-BVzzkZ6l.mjs';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
6
  import * as React from 'react';
@@ -79,6 +79,21 @@ declare const webhook: {
79
79
  fetchJwks: typeof fetchJwksForce;
80
80
  };
81
81
 
82
+ interface PayPeriod {
83
+ id: string;
84
+ name: string;
85
+ starts_at: string;
86
+ ends_at: string | null;
87
+ }
88
+ type PayingState = {
89
+ paying: true;
90
+ period: PayPeriod;
91
+ } | {
92
+ paying: false;
93
+ next: PayPeriod | null;
94
+ };
95
+ declare function payingAt(periods: readonly PayPeriod[], at?: Date): PayingState;
96
+
82
97
  interface FireEventOptions {
83
98
  project_key: string;
84
99
  subtype: EventKey;
@@ -91,7 +106,22 @@ interface FireEventOptions {
91
106
  bearerToken?: string;
92
107
  idempotencyKey?: string;
93
108
  }
94
- declare function fire(options: FireEventOptions): Promise<BillableEvent>;
109
+ type FireEventResult = {
110
+ ok: true;
111
+ earned: true;
112
+ event: BillableEvent;
113
+ webhooks_fired: number;
114
+ escrow_mode: 'simulation' | 'live';
115
+ idempotent_replay?: boolean;
116
+ simulation_mode_note?: string;
117
+ } | {
118
+ ok: true;
119
+ earned: false;
120
+ reason: 'not_paying';
121
+ detail: string;
122
+ next_pay_period: PayPeriod | null;
123
+ };
124
+ declare function fire(options: FireEventOptions): Promise<FireEventResult>;
95
125
  interface BatchEventInput {
96
126
  subtype: EventKey;
97
127
  payment_amount_sats?: number;
@@ -112,6 +142,9 @@ type BatchEventResult = {
112
142
  index: number;
113
143
  status: 'rejected';
114
144
  reason: string;
145
+ } | {
146
+ index: number;
147
+ status: 'not_paying';
115
148
  };
116
149
  interface FireBatchOptions {
117
150
  project_key: string;
@@ -122,6 +155,7 @@ interface FireBatchOptions {
122
155
  interface FireBatchResponse {
123
156
  ok: boolean;
124
157
  results: BatchEventResult[];
158
+ next_pay_period?: PayPeriod | null;
125
159
  escrow_mode: 'simulation' | 'live';
126
160
  simulation_mode_note?: string;
127
161
  }
@@ -129,7 +163,7 @@ declare function fireBatch(options: FireBatchOptions): Promise<FireBatchResponse
129
163
  interface VerifyEventResult {
130
164
  ok: boolean;
131
165
  issues: Array<{
132
- field: 'gross_fee_sats' | 'platform_fee_sats' | 'user_earned_sats' | 'site_rebate_sats' | 'subtype_disabled' | 'subtype_unconfigured' | 'percent_amount_missing';
166
+ field: 'gross_fee_sats' | 'platform_fee_sats' | 'user_earned_sats' | 'site_rebate_sats' | 'subtype_disabled' | 'subtype_unconfigured' | 'percent_amount_missing' | 'outside_pay_period';
133
167
  expected: number | null;
134
168
  actual: number | null;
135
169
  message: string;
@@ -141,7 +175,9 @@ interface VerifyEventResult {
141
175
  site_rebate_sats: number;
142
176
  } | null;
143
177
  }
144
- declare function verify(envelope: BillableEvent, config: IntegratorPriceConfig, payment_amount_sats?: number): VerifyEventResult;
178
+ declare function verify(envelope: BillableEvent, config: IntegratorPriceConfig, payment_amount_sats?: number, opts?: {
179
+ payPeriods?: readonly PayPeriod[];
180
+ }): VerifyEventResult;
145
181
  declare const event: {
146
182
  fire: typeof fire;
147
183
  fireBatch: typeof fireBatch;
@@ -224,9 +260,11 @@ declare const oc: {
224
260
  authorize: (opts: PaymentAuthorizeOptions) => Promise<PaymentResult>;
225
261
  };
226
262
  event: {
227
- fire: (options: FireEventOptions) => Promise<BillableEvent>;
263
+ fire: (options: FireEventOptions) => Promise<FireEventResult>;
228
264
  fireBatch: (options: FireBatchOptions) => Promise<FireBatchResponse>;
229
- verify: (envelope: BillableEvent, config: IntegratorPriceConfig, payment_amount_sats?: number) => VerifyEventResult;
265
+ verify: (envelope: BillableEvent, config: IntegratorPriceConfig, payment_amount_sats?: number, opts?: {
266
+ payPeriods?: readonly PayPeriod[];
267
+ }) => VerifyEventResult;
230
268
  };
231
269
  config: {
232
270
  validate: (cfg: IntegratorPriceConfig) => ValidationResult;
@@ -258,4 +296,4 @@ declare const oc: {
258
296
  };
259
297
  };
260
298
 
261
- export { ArchetypeTemplate, BillableEvent, EventKey, type FamilyScopesOptions, type FamilyScopesResult, type FamilyVerb, Federation, type FireEventOptions, type GrantedOptions, type GrantedResult, IntegratorPriceConfig, MeClientError, type OcPublicJwk, OcSignInButton, type OcSignInButtonProps, PaymentAuthorizeOptions, PaymentResult, type RequestOptions, type Scope, Session, SessionPolicy, SignInOptions, TelemetryEvent, type TrustAttestationCount, ValidationResult, type VerifyEventResult, type VerifyOptions, type VerifyResult, type WithRateLimitRetryOptions, clearBearerToken, config, fromTemplate as configFromTemplate, event, family, federations, getArchetypeTemplate, getBearerToken, getOrigin, oc, onTelemetry, parseTrustAttestationCount, payment, refreshEnvelopeJwks, scope, session, setBearerToken, setOrigin, verifyActivityAttestation, webhook, withRateLimitRetry };
299
+ export { ArchetypeTemplate, type BatchEventResult, BillableEvent, EventKey, type FamilyScopesOptions, type FamilyScopesResult, type FamilyVerb, Federation, type FireBatchResponse, type FireEventOptions, type FireEventResult, type GrantedOptions, type GrantedResult, IntegratorPriceConfig, MeClientError, type OcPublicJwk, OcSignInButton, type OcSignInButtonProps, type PayPeriod, type PayingState, PaymentAuthorizeOptions, PaymentResult, type RequestOptions, type Scope, Session, SessionPolicy, SignInOptions, TelemetryEvent, type TrustAttestationCount, ValidationResult, type VerifyEventResult, type VerifyOptions, type VerifyResult, type WithRateLimitRetryOptions, clearBearerToken, config, fromTemplate as configFromTemplate, event, family, federations, getArchetypeTemplate, getBearerToken, getOrigin, oc, onTelemetry, parseTrustAttestationCount, payingAt, payment, refreshEnvelopeJwks, scope, session, setBearerToken, setOrigin, verifyActivityAttestation, webhook, withRateLimitRetry };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { v as verifyActivityAttestation, r as refreshEnvelopeJwks } from './identity-1VYMOhzV.js';
2
2
  export { A as ActivityAttestation, a as ActivityAttestationBundle, b as ActivityVerifyCheck, c as ActivityVerifyResult, V as VerifyActivityOptions, i as identity } from './identity-1VYMOhzV.js';
3
- import { E as EventKey, B as BillableEvent, I as IntegratorPriceConfig, S as SessionPolicy, a as Session, T as TelemetryEvent, b as SignInOptions, P as PaymentAuthorizeOptions, c as PaymentResult, V as ValidationResult, f as fromTemplate, g as getArchetypeTemplate, A as ArchetypeTemplate, F as Federation } from './integrator-BVzzkZ6l.js';
3
+ import { B as BillableEvent, E as EventKey, I as IntegratorPriceConfig, S as SessionPolicy, a as Session, T as TelemetryEvent, b as SignInOptions, P as PaymentAuthorizeOptions, c as PaymentResult, V as ValidationResult, f as fromTemplate, g as getArchetypeTemplate, A as ArchetypeTemplate, F as Federation } from './integrator-BVzzkZ6l.js';
4
4
  export { d as ALL_EVENT_SUBTYPES, e as ARCHETYPE_TEMPLATES, h as AgentClassOverride, i as AttestTier, C as ClassASubtype, j as ClassBSubtype, k as ClassCSubtype, l as ComputedFees, D as DropCadence, m as DropClosedWebhookPayload, n as DropResponseBlock, o as DropScheduleSummary, p as EVENT_SUBTYPES, q as EventClass, r as EventSubtype, s as EventSubtypeMetadata, t as FederationStatus, u as IntegratorArchetype, v as IntegratorEventConfig, M as MAX_DROP_WINDOW_DAYS, w as MIN_INTEGRATOR_PRICE_SATS, x as PLATFORM_FEE_POLICY, y as SigningMethod, z as SiteFeeShape, G as SystemWebhookPayload, W as WebhookHeaders, H as WebhookPayload, J as computeFees, K as subtypesForClass, L as validateIntegratorConfig } from './integrator-BVzzkZ6l.js';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
6
  import * as React from 'react';
@@ -79,6 +79,21 @@ declare const webhook: {
79
79
  fetchJwks: typeof fetchJwksForce;
80
80
  };
81
81
 
82
+ interface PayPeriod {
83
+ id: string;
84
+ name: string;
85
+ starts_at: string;
86
+ ends_at: string | null;
87
+ }
88
+ type PayingState = {
89
+ paying: true;
90
+ period: PayPeriod;
91
+ } | {
92
+ paying: false;
93
+ next: PayPeriod | null;
94
+ };
95
+ declare function payingAt(periods: readonly PayPeriod[], at?: Date): PayingState;
96
+
82
97
  interface FireEventOptions {
83
98
  project_key: string;
84
99
  subtype: EventKey;
@@ -91,7 +106,22 @@ interface FireEventOptions {
91
106
  bearerToken?: string;
92
107
  idempotencyKey?: string;
93
108
  }
94
- declare function fire(options: FireEventOptions): Promise<BillableEvent>;
109
+ type FireEventResult = {
110
+ ok: true;
111
+ earned: true;
112
+ event: BillableEvent;
113
+ webhooks_fired: number;
114
+ escrow_mode: 'simulation' | 'live';
115
+ idempotent_replay?: boolean;
116
+ simulation_mode_note?: string;
117
+ } | {
118
+ ok: true;
119
+ earned: false;
120
+ reason: 'not_paying';
121
+ detail: string;
122
+ next_pay_period: PayPeriod | null;
123
+ };
124
+ declare function fire(options: FireEventOptions): Promise<FireEventResult>;
95
125
  interface BatchEventInput {
96
126
  subtype: EventKey;
97
127
  payment_amount_sats?: number;
@@ -112,6 +142,9 @@ type BatchEventResult = {
112
142
  index: number;
113
143
  status: 'rejected';
114
144
  reason: string;
145
+ } | {
146
+ index: number;
147
+ status: 'not_paying';
115
148
  };
116
149
  interface FireBatchOptions {
117
150
  project_key: string;
@@ -122,6 +155,7 @@ interface FireBatchOptions {
122
155
  interface FireBatchResponse {
123
156
  ok: boolean;
124
157
  results: BatchEventResult[];
158
+ next_pay_period?: PayPeriod | null;
125
159
  escrow_mode: 'simulation' | 'live';
126
160
  simulation_mode_note?: string;
127
161
  }
@@ -129,7 +163,7 @@ declare function fireBatch(options: FireBatchOptions): Promise<FireBatchResponse
129
163
  interface VerifyEventResult {
130
164
  ok: boolean;
131
165
  issues: Array<{
132
- field: 'gross_fee_sats' | 'platform_fee_sats' | 'user_earned_sats' | 'site_rebate_sats' | 'subtype_disabled' | 'subtype_unconfigured' | 'percent_amount_missing';
166
+ field: 'gross_fee_sats' | 'platform_fee_sats' | 'user_earned_sats' | 'site_rebate_sats' | 'subtype_disabled' | 'subtype_unconfigured' | 'percent_amount_missing' | 'outside_pay_period';
133
167
  expected: number | null;
134
168
  actual: number | null;
135
169
  message: string;
@@ -141,7 +175,9 @@ interface VerifyEventResult {
141
175
  site_rebate_sats: number;
142
176
  } | null;
143
177
  }
144
- declare function verify(envelope: BillableEvent, config: IntegratorPriceConfig, payment_amount_sats?: number): VerifyEventResult;
178
+ declare function verify(envelope: BillableEvent, config: IntegratorPriceConfig, payment_amount_sats?: number, opts?: {
179
+ payPeriods?: readonly PayPeriod[];
180
+ }): VerifyEventResult;
145
181
  declare const event: {
146
182
  fire: typeof fire;
147
183
  fireBatch: typeof fireBatch;
@@ -224,9 +260,11 @@ declare const oc: {
224
260
  authorize: (opts: PaymentAuthorizeOptions) => Promise<PaymentResult>;
225
261
  };
226
262
  event: {
227
- fire: (options: FireEventOptions) => Promise<BillableEvent>;
263
+ fire: (options: FireEventOptions) => Promise<FireEventResult>;
228
264
  fireBatch: (options: FireBatchOptions) => Promise<FireBatchResponse>;
229
- verify: (envelope: BillableEvent, config: IntegratorPriceConfig, payment_amount_sats?: number) => VerifyEventResult;
265
+ verify: (envelope: BillableEvent, config: IntegratorPriceConfig, payment_amount_sats?: number, opts?: {
266
+ payPeriods?: readonly PayPeriod[];
267
+ }) => VerifyEventResult;
230
268
  };
231
269
  config: {
232
270
  validate: (cfg: IntegratorPriceConfig) => ValidationResult;
@@ -258,4 +296,4 @@ declare const oc: {
258
296
  };
259
297
  };
260
298
 
261
- export { ArchetypeTemplate, BillableEvent, EventKey, type FamilyScopesOptions, type FamilyScopesResult, type FamilyVerb, Federation, type FireEventOptions, type GrantedOptions, type GrantedResult, IntegratorPriceConfig, MeClientError, type OcPublicJwk, OcSignInButton, type OcSignInButtonProps, PaymentAuthorizeOptions, PaymentResult, type RequestOptions, type Scope, Session, SessionPolicy, SignInOptions, TelemetryEvent, type TrustAttestationCount, ValidationResult, type VerifyEventResult, type VerifyOptions, type VerifyResult, type WithRateLimitRetryOptions, clearBearerToken, config, fromTemplate as configFromTemplate, event, family, federations, getArchetypeTemplate, getBearerToken, getOrigin, oc, onTelemetry, parseTrustAttestationCount, payment, refreshEnvelopeJwks, scope, session, setBearerToken, setOrigin, verifyActivityAttestation, webhook, withRateLimitRetry };
299
+ export { ArchetypeTemplate, type BatchEventResult, BillableEvent, EventKey, type FamilyScopesOptions, type FamilyScopesResult, type FamilyVerb, Federation, type FireBatchResponse, type FireEventOptions, type FireEventResult, type GrantedOptions, type GrantedResult, IntegratorPriceConfig, MeClientError, type OcPublicJwk, OcSignInButton, type OcSignInButtonProps, type PayPeriod, type PayingState, PaymentAuthorizeOptions, PaymentResult, type RequestOptions, type Scope, Session, SessionPolicy, SignInOptions, TelemetryEvent, type TrustAttestationCount, ValidationResult, type VerifyEventResult, type VerifyOptions, type VerifyResult, type WithRateLimitRetryOptions, clearBearerToken, config, fromTemplate as configFromTemplate, event, family, federations, getArchetypeTemplate, getBearerToken, getOrigin, oc, onTelemetry, parseTrustAttestationCount, payingAt, payment, refreshEnvelopeJwks, scope, session, setBearerToken, setOrigin, verifyActivityAttestation, webhook, withRateLimitRetry };
package/dist/index.js CHANGED
@@ -339,6 +339,18 @@ function validateIntegratorConfig(cfg) {
339
339
  return { ok: errors.length === 0, errors };
340
340
  }
341
341
 
342
+ // src/pay-periods.ts
343
+ var ms = (iso) => Date.parse(iso);
344
+ function payingAt(periods, at = /* @__PURE__ */ new Date()) {
345
+ const t = at.getTime();
346
+ const current = periods.find(
347
+ (p) => ms(p.starts_at) <= t && (p.ends_at === null || t < ms(p.ends_at))
348
+ );
349
+ if (current) return { paying: true, period: current };
350
+ const next = periods.filter((p) => ms(p.starts_at) > t).sort((a, b) => ms(a.starts_at) - ms(b.starts_at))[0];
351
+ return { paying: false, next: next ?? null };
352
+ }
353
+
342
354
  // src/event.ts
343
355
  async function hmacSha256Hex(secret, message) {
344
356
  const enc = new TextEncoder();
@@ -421,14 +433,23 @@ async function fireBatch(options) {
421
433
  bearerToken: options.bearerToken
422
434
  });
423
435
  }
424
- function verify(envelope, config2, payment_amount_sats) {
436
+ function verify(envelope, config2, payment_amount_sats, opts = {}) {
425
437
  const issues = [];
438
+ if (opts.payPeriods && !payingAt(opts.payPeriods, new Date(envelope.occurred_at)).paying) {
439
+ issues.push({
440
+ field: "outside_pay_period",
441
+ expected: null,
442
+ actual: null,
443
+ message: `billed at ${envelope.occurred_at}, when ${config2.project_key} wasn't paying its users`
444
+ });
445
+ }
426
446
  const eventCfg = config2.events[envelope.subtype];
427
447
  if (!eventCfg) {
428
448
  return {
429
449
  ok: false,
430
450
  expected: null,
431
451
  issues: [
452
+ ...issues,
432
453
  {
433
454
  field: "subtype_unconfigured",
434
455
  expected: null,
@@ -443,6 +464,7 @@ function verify(envelope, config2, payment_amount_sats) {
443
464
  ok: false,
444
465
  expected: null,
445
466
  issues: [
467
+ ...issues,
446
468
  {
447
469
  field: "subtype_disabled",
448
470
  expected: null,
@@ -457,6 +479,7 @@ function verify(envelope, config2, payment_amount_sats) {
457
479
  ok: false,
458
480
  expected: null,
459
481
  issues: [
482
+ ...issues,
460
483
  {
461
484
  field: "percent_amount_missing",
462
485
  expected: null,
@@ -1574,6 +1597,7 @@ exports.identity = identity;
1574
1597
  exports.oc = oc;
1575
1598
  exports.onTelemetry = onTelemetry;
1576
1599
  exports.parseTrustAttestationCount = parseTrustAttestationCount;
1600
+ exports.payingAt = payingAt;
1577
1601
  exports.payment = payment;
1578
1602
  exports.refreshEnvelopeJwks = refreshEnvelopeJwks;
1579
1603
  exports.scope = scope;