refactor(domain): introduce the Feed aggregate as the write-path API

Add a Feed aggregate class owning config + the email index, with create,
ingest, removeEmails, isExpired and accepts delegating to the existing
pure invariant functions. FeedRepository gains load/save/saveMetadata
that reconstitute and persist the aggregate.

All write paths now go through it: createFeedRecord (Feed.create),
email ingestion (feed.ingest), and every email deletion in the admin UI
and REST API (feed.removeEmails) — no route mutates metadata.emails
directly anymore. KV key strings unchanged.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
Julien HerrandClaude Opus 4.7 committed 2026-05-24 00:33:14 +02:00
1 parent a31ff42f59
commit c45f6677fe
8 files changed
+415 -131

No files matched your search

+4
View File
@@ -815,6 +815,10 @@ describe("Admin Routes", () => {
"feeds:list",
JSON.stringify({ feeds: [{ id: feedId, title: "F" }] }),
);
await r2Env.EMAIL_STORAGE.put(
`feed:${feedId}:config`,
JSON.stringify({ title: "F", language: "en", created_at: 1 }),
);
const emailKey = `feed:${feedId}:1`;
await r2Env.EMAIL_STORAGE.put(
emailKey,