@bunizao/contracts 0.11.0 → 0.13.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/dist/admin.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { ClientFingerprint, CommentAuthAtWrite, CommentClaimMethod, CommentsMode, CommentStatus, CommentSurface, Interaction } from './comments';
2
2
  import type { MessageLocale, MessageState } from './messages';
3
- import type { DeliveryMode, NotifyAuditEventType, NotifyChannel, SubscriberRecord, SubscriberStatus } from './notify';
3
+ import type { DeliveryMode, NotifyAuditEventType, NotifyChannel, SubscriberRecord, SubscriberStatus, SubscriptionSource } from './notify';
4
4
  export interface SubscriberChannelCount {
5
5
  total: number;
6
6
  pendingCount: number;
@@ -24,6 +24,8 @@ export interface SubscriberListResult {
24
24
  activeCount: number;
25
25
  unsubscribedCount: number;
26
26
  channelCounts?: SubscriberChannelCounts;
27
+ /** Acquisition counts, kept separate from the subscribed channels. */
28
+ acquisitionCounts?: Record<SubscriptionSource | 'unknown', SubscriberChannelCount>;
27
29
  }
28
30
  export interface AuditEntry {
29
31
  id: number;
@@ -64,7 +64,8 @@ export interface ReaderMe {
64
64
  has been handed out -- the client then draws from the name. */
65
65
  avatarSeed: number | null;
66
66
  notifyReplies: boolean;
67
- /** Whether this address holds an active newsletter subscription. */
67
+ /** Whether this address holds an active subscription that includes the blog
68
+ channel -- the reader switch is "latest posts", so mood alone reads false. */
68
69
  subscribed: boolean;
69
70
  }
70
71
  export interface ReaderMeResult {
@@ -453,8 +454,9 @@ export interface CommentPolicy {
453
454
  Independent of `mode`: a post can take reactions with comments off, and
454
455
  an open thread can refuse them. */
455
456
  reactions: boolean;
456
- /** Accept a comment only from an address that has been verified. Anonymous
457
- and unverified-email writers are refused rather than held. */
457
+ /** Publish a comment only from an address that has been verified. An
458
+ anonymous writer must give an address, and the comment is held until
459
+ they confirm it; one with no address is refused. */
458
460
  requireVerifiedEmail: boolean;
459
461
  }
460
462
  export declare const DEFAULT_COMMENT_POLICY: CommentPolicy;
@@ -464,8 +466,9 @@ export declare const COMMENT_POLICY_TAGS: {
464
466
  readonly 'no-comments': (policy: CommentPolicy) => CommentPolicy;
465
467
  readonly 'reactions-off': (policy: CommentPolicy) => {
466
468
  mode: CommentsMode;
467
- /** Accept a comment only from an address that has been verified. Anonymous
468
- and unverified-email writers are refused rather than held. */
469
+ /** Publish a comment only from an address that has been verified. An
470
+ anonymous writer must give an address, and the comment is held until
471
+ they confirm it; one with no address is refused. */
469
472
  requireVerifiedEmail: boolean;
470
473
  reactions: false;
471
474
  };
package/dist/content.d.ts CHANGED
@@ -1,5 +1,22 @@
1
1
  export declare const CONTENT_DOCUMENT_SOURCES: readonly ['mood', 'post'];
2
2
  export type ContentDocumentSource = (typeof CONTENT_DOCUMENT_SOURCES)[number];
3
+ /** Public read aggregates since analytics collection began. */
4
+ export interface BlogStats {
5
+ generatedAt: string;
6
+ /** Null until the first event has been recorded. */
7
+ since: string | null;
8
+ totals: {
9
+ reads: number;
10
+ readers: number;
11
+ completed: number;
12
+ };
13
+ posts: {
14
+ slug: string;
15
+ reads: number;
16
+ completed: number;
17
+ medianDwellMs: number;
18
+ }[];
19
+ }
3
20
  export interface PostLocaleTag {
4
21
  locale: string;
5
22
  canonicalSlug?: string;
package/dist/index.js CHANGED
@@ -131,6 +131,7 @@ var MOOD_AI_MODELS = ["gpt-5.5", "gpt-5", "claude-sonnet-4.6"];
131
131
  var MOOD_COMMENT_ORIGINS = ["telegram", "web"];
132
132
  // src/notify.ts
133
133
  var NOTIFY_CHANNELS = ["mood", "blog", "privacy", "announcement"];
134
+ var SUBSCRIPTION_SOURCES = ["desk", "blog", "mood"];
134
135
  // src/routes.ts
135
136
  var API_PREFIX = "/api";
136
137
  var HEALTH_PATH = "/health";
@@ -319,6 +320,7 @@ export {
319
320
  READER_RESEND_PATH,
320
321
  READER_VERIFY_OUTCOMES,
321
322
  READER_VERIFY_PATH,
323
+ SUBSCRIPTION_SOURCES,
322
324
  TELEGRAM_OPS_BASE_PATH,
323
325
  TELEGRAM_OPS_BROADCASTS_PATH,
324
326
  TELEGRAM_OPS_BROADCAST_CHANNELS,
@@ -1,3 +1,18 @@
1
+ /** Site playback totals in a rolling seven-day window, not Apple Music history. */
2
+ export interface ListeningStats {
3
+ generatedAt: string;
4
+ window: {
5
+ from: string;
6
+ to: string;
7
+ };
8
+ totals: {
9
+ plays: number;
10
+ };
11
+ topArtist: {
12
+ name: string;
13
+ plays: number;
14
+ } | null;
15
+ }
1
16
  export interface ListeningAccent {
2
17
  hue: number;
3
18
  chromaLight: number;
package/dist/mood.d.ts CHANGED
@@ -22,16 +22,9 @@ export interface MoodStatsActivityBucket {
22
22
  date: string;
23
23
  count: number;
24
24
  }
25
- export interface MoodStatsSentimentBucket {
26
- bucketStart: string;
27
- avgValence: number | null;
28
- dominantLabel: MoodSentimentLabel | null;
29
- scoredCount: number;
30
- }
31
25
  export interface MoodStatsSnapshot {
32
26
  activity: MoodStatsActivityBucket[];
33
27
  rhythm: number[][];
34
- sentimentTimeline: MoodStatsSentimentBucket[];
35
28
  streaks: {
36
29
  current: number;
37
30
  longest: number;
package/dist/notify.d.ts CHANGED
@@ -1,8 +1,32 @@
1
+ import type { ClientEvidence } from './comments';
1
2
  export type SubscriberStatus = 'pending' | 'active' | 'unsubscribed';
2
3
  export type DeliveryMode = 'immediate' | 'every_5h' | 'daily';
3
4
  export type NotifyChannel = 'mood' | 'blog' | 'privacy' | 'announcement';
4
5
  export type NotifyAuditEventType = 'subscribe_requested' | 'subscription_confirmed' | 'unsubscribed' | 'email_change_requested' | 'email_changed' | 'admin_create' | 'admin_update' | 'admin_delete' | 'admin_resend_confirm' | 'broadcast_sent';
5
6
  export declare const NOTIFY_CHANNELS: readonly NotifyChannel[];
7
+ export declare const SUBSCRIPTION_SOURCES: readonly ['desk', 'blog', 'mood'];
8
+ export type SubscriptionSource = (typeof SUBSCRIPTION_SOURCES)[number];
9
+ /** Public counts of active, confirmed, deliverable email subscriptions. */
10
+ export interface SubscriberCounts {
11
+ generatedAt: string;
12
+ channels: {
13
+ blog: number;
14
+ mood: number;
15
+ };
16
+ }
17
+ /** Optional risk evidence preserves compatibility with existing clients. */
18
+ export interface SubscribeRequest extends ClientEvidence {
19
+ email: string;
20
+ turnstileToken?: string;
21
+ channels?: NotifyChannel[];
22
+ deliveryMode?: DeliveryMode;
23
+ timezone?: string;
24
+ dailyHour?: number;
25
+ website?: string;
26
+ dwellToken?: string;
27
+ /** First subscription surface. Unknown values are ignored by the server. */
28
+ source?: SubscriptionSource;
29
+ }
6
30
  export interface SubscriberRecord {
7
31
  email: string;
8
32
  emailHash: string;
@@ -20,6 +44,8 @@ export interface SubscriberRecord {
20
44
  updatedAt: string;
21
45
  confirmedAt?: string;
22
46
  lastConfirmSentAt?: string;
47
+ /** First recorded subscription surface; absent for historical subscribers. */
48
+ source?: SubscriptionSource;
23
49
  }
24
50
  export interface RetryRecord {
25
51
  postId: string;
package/dist/notify.js CHANGED
@@ -1,5 +1,7 @@
1
1
  // src/notify.ts
2
2
  var NOTIFY_CHANNELS = ["mood", "blog", "privacy", "announcement"];
3
+ var SUBSCRIPTION_SOURCES = ["desk", "blog", "mood"];
3
4
  export {
4
- NOTIFY_CHANNELS
5
+ NOTIFY_CHANNELS,
6
+ SUBSCRIPTION_SOURCES
5
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bunizao/contracts",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "Shared TypeScript contracts for buxx.me services and clients.",
5
5
  "type": "module",
6
6
  "sideEffects": false,