diff --git a/apps/mana/apps/web/src/lib/data/privacy/exposed-records.ts b/apps/mana/apps/web/src/lib/data/privacy/exposed-records.ts index 39a4db592..257e6aeb2 100644 --- a/apps/mana/apps/web/src/lib/data/privacy/exposed-records.ts +++ b/apps/mana/apps/web/src/lib/data/privacy/exposed-records.ts @@ -235,6 +235,18 @@ const TABLES: TableConfig[] = [ return decksStore.setVisibility(id, next); }, }, + { + module: 'augur', + collection: 'augurEntries', + moduleLabel: 'Augur (Omen / Wahrsagungen)', + encrypted: true, + title: (r) => asString(r.claim), + href: (id) => `/augur/entry/${id}`, + setVisibility: async (id, next) => { + const { augurStore } = await import('$lib/modules/augur/stores/entries.svelte'); + return augurStore.setVisibility(id, next); + }, + }, ]; /** diff --git a/apps/mana/apps/web/src/lib/modules/website/embeds.ts b/apps/mana/apps/web/src/lib/modules/website/embeds.ts index f104a1ad4..60c2da77f 100644 --- a/apps/mana/apps/web/src/lib/modules/website/embeds.ts +++ b/apps/mana/apps/web/src/lib/modules/website/embeds.ts @@ -37,6 +37,7 @@ import type { LocalSocialEvent } from '$lib/modules/events/types'; import type { LocalMemo } from '$lib/modules/memoro/types'; import type { LocalDeck as LocalCardDeck } from '$lib/modules/cards/types'; import type { LocalDeck as LocalPresiDeck } from '$lib/modules/presi/types'; +import type { LocalAugurEntry } from '$lib/modules/augur/types'; import type { LocalTimeBlock } from '$lib/data/time-blocks/types'; export interface ResolvedEmbed { @@ -96,6 +97,9 @@ export async function resolveEmbed(props: ModuleEmbedProps): Promise }; }); } + +/** + * Augur (omens / fortunes / hunches): public-divination teaser. + * Returns entries flipped to 'public' with the kind + vibe + outcome + * status as subtitle. + * + * Whitelist: claim + "{kind} · {vibe} · {outcome}". The personal + * fields — feltMeaning, expectedOutcome, expectedBy, source name, + * outcomeNote, related dream/decision links, livingOracleSnapshot — + * all stay private. Augur captures are by default private (the + * store stamps `'private'` rather than space-default), so a flip + * to 'public' is an explicit "I want to share this prediction". + * + * Filters: optional `status` maps to AugurOutcome ('open' / + * 'fulfilled' / 'partly' / 'not-fulfilled') so the user can build + * "predictions I got right" or "still open" widgets. + */ +async function resolveAugurEntries(props: ModuleEmbedProps): Promise { + const KIND_LABEL: Record = { + omen: 'Omen', + fortune: 'Wahrsagung', + hunch: 'Bauchgefühl', + }; + const VIBE_LABEL: Record = { + good: 'Gutes Zeichen', + bad: 'Warnung', + mysterious: 'Rätselhaft', + }; + const OUTCOME_LABEL: Record = { + open: 'Offen', + fulfilled: 'Eingetreten', + partly: 'Teilweise', + 'not-fulfilled': 'Nicht eingetreten', + }; + + let entries = await db.table('augurEntries').toArray(); + entries = entries.filter( + (e) => !e.deletedAt && !e.isArchived && canEmbedOnWebsite(e.visibility ?? 'private') + ); + + if (props.filter?.status) { + entries = entries.filter((e) => e.outcome === props.filter?.status); + } + + if (entries.length === 0) return []; + + const decrypted = (await decryptRecords('augurEntries', entries)) as LocalAugurEntry[]; + + // Resolved-first then by encounteredAt desc — fulfilled predictions + // rank above open ones, which is the more interesting public signal. + decrypted.sort((a, b) => { + const aOpen = a.outcome === 'open' ? 1 : 0; + const bOpen = b.outcome === 'open' ? 1 : 0; + if (aOpen !== bOpen) return aOpen - bOpen; + return (b.encounteredAt ?? '').localeCompare(a.encounteredAt ?? ''); + }); + + return decrypted.map((e) => { + const parts = [ + KIND_LABEL[e.kind] ?? e.kind, + VIBE_LABEL[e.vibe] ?? e.vibe, + OUTCOME_LABEL[e.outcome] ?? e.outcome, + ]; + return { + title: e.claim, + subtitle: parts.join(' · '), + }; + }); +} diff --git a/packages/website-blocks/src/moduleEmbed/ModuleEmbedInspectorFallback.svelte b/packages/website-blocks/src/moduleEmbed/ModuleEmbedInspectorFallback.svelte index 1887ca32e..2f92144b3 100644 --- a/packages/website-blocks/src/moduleEmbed/ModuleEmbedInspectorFallback.svelte +++ b/packages/website-blocks/src/moduleEmbed/ModuleEmbedInspectorFallback.svelte @@ -31,6 +31,7 @@ + diff --git a/packages/website-blocks/src/moduleEmbed/schema.ts b/packages/website-blocks/src/moduleEmbed/schema.ts index a4b1d6ec3..4a964fa06 100644 --- a/packages/website-blocks/src/moduleEmbed/schema.ts +++ b/packages/website-blocks/src/moduleEmbed/schema.ts @@ -42,6 +42,7 @@ export const EmbedSourceSchema = z.enum([ 'memoro.memos', 'cards.decks', 'presi.decks', + 'augur.entries', ]); export type EmbedSource = z.infer;