feat(feed): optional per-feed sender-in-title toggle

Add a per-feed senderInTitle flag (domain FeedState.senderInTitle ↔
FeedConfig.sender_in_title). When set, the feed generator prefixes each
entry title with [Sender] (display name, falling back to the address).
Exposed as an admin edit-form checkbox and across the REST API
create/update/response schemas.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Julien Herr
2026-05-25 15:48:31 +02:00
parent 7086526670
commit e86beeeb8a
14 changed files with 234 additions and 2 deletions
+12
View File
@@ -13,6 +13,8 @@ export interface CreateFeedInput {
language: string;
allowedSenders: string[];
blockedSenders: string[];
/** When true, render entry titles as `[Sender] Subject` in the feed output. */
senderInTitle?: boolean;
/** Raw client-requested lifetime; the application resolves it into a `Lifetime`. */
lifetimeHours?: number;
}
@@ -23,6 +25,7 @@ export interface UpdateFeedInput {
language?: string;
allowedSenders?: string[];
blockedSenders?: string[];
senderInTitle?: boolean;
lifetimeHours?: number;
}
@@ -95,6 +98,7 @@ export class Feed {
description: input.description,
language: input.language,
mailboxId: deps.mailboxId.value,
senderInTitle: input.senderInTitle,
allowedSenders: input.allowedSenders,
blockedSenders: input.blockedSenders,
createdAt: now,
@@ -134,6 +138,11 @@ export class Feed {
return this._state.language;
}
/** Whether entry titles render as `[Sender] Subject` in the feed output. */
get senderInTitle(): boolean {
return this._state.senderInTitle ?? false;
}
/** The inbound mailbox (`noun.noun.NN`) — the feed's email address is `mailboxId@domain`. */
get mailboxId(): MailboxId {
return MailboxId.unchecked(this._state.mailboxId);
@@ -341,6 +350,9 @@ export class Feed {
this._state.description = patch.description;
}
if (patch.language !== undefined) this._state.language = patch.language;
if (patch.senderInTitle !== undefined) {
this._state.senderInTitle = patch.senderInTitle;
}
if (patch.allowedSenders !== undefined) {
this._state.allowedSenders = patch.allowedSenders;
}