Date: 2026-06-11. Scope: residual after the 57-task 2026-06-10 ground-truth wave (A-phase telegram hardening, B5 real Sophia grounding, B12 effects port, C8(c) template rendering, E3 policy enrichment all verified present in current code). Method: static reading of live source, delegation chains followed end-to-end; comments/tests/docs not trusted as proof.
What checks out (not findings): real provider transports for
SendGrid/SMTP/Twilio/FCM/APNs/Expo/WebPush/Meta/Slack/Discord
(libs/oshun/messaging-channels/src/transports.ts, smtp-email-transport.ts,
web-push-transport.ts with real RFC 8291 aes128gcm + RFC 8292 VAPID, real
ES256 P1363 APNs JWT, real HTTP/2 transport for APNs); reminder PRODUCERS now
exist and are wired into the worker (streaks/nyx/assignments/sessions/
content-drops over durable event-fed stores — the prior "no domain bulk
enumeration" gap is substantially closed for the BFF's known users,
server.ts:626–700); E3 policy enrichment is real (timezone quiet-hours with
overnight wrap, verified-binding gate, live crisis frame,
reminders-route.ts:224–312); C8(c) approved lifecycle templates render into
deliveries (reminders-route.ts:145–216); B5 Telegram grounding is the real
nisaba retrieval seam with honest abstention
(telegram/sophia-grounder-bridge.ts); B12 effects are real durable writes
(telegram/effects-adapter.ts, telegram/user-state-store.ts); web push
registration is a complete loop (settings UI → push-registration.ts →
POST /v1/device-tokens → durable token store → resolveDevicePushBinding →
per-token-type transport; sw.js has push + notificationclick handlers);
channel-binding verify lifecycle (hashing, expiry, attempt lock) and its profile
UI exist; DSAR export includes the reminder inbox
(data-export/bundle-builder.ts:106).
1. The Telegram bot still has no runway — replies are computed and then discarded; the deliverable bot service has zero callers#
Severity: P0-STRUCT
Evidence:
apps/oshun/bff/src/routes/telegram.ts:207–245—POST /telegram/webhookcallshandleBffTelegramWebhookand returnsreply.send({ ok: true, responses: decision.responses, ... }). That is the END of the chain: noctx.api.sendMessage, no POST tohttps://api.telegram.org/bot<token>/sendMessage, nothing. The only outbound Telegram API call in the entire lib/BFF isgetFileinside the STT provider (libs/.../telegram/stt-provider.ts:53).- Telegram's "answer the webhook directly" mechanism requires the method payload
at the TOP LEVEL of the response body
(
{"method":"sendMessage", "chat_id":...,"text":...}) and supports exactly one method per update. The BFF's{ok, responses:[...]}envelope is not that shape — Telegram discards it. Every user-visible reply (grounded answers, crisis copy with hotline buttons,/saveconfirmations, abstentions, rate-limit notices) is dropped. - The component that CAN speak —
apps/oshun/telegram-bot/src/index.ts:203–236createOshunGrammyBotwith realctx.api.sendMessage/answerInlineQuery/ answerCallbackQuerydelivery — has ZERO callers in the repo (grep:createOshunGrammyBotappears only in its own file + tests), no entrypoint that callsbot.start()or mountswebhookCallback, no serve target inproject.json(build/typecheck/test only), and no deploy manifest. It is a library that is never run. - Even if the grammY app were started, it diverges from the BFF webhook: it
wires NO
effectsport (index.ts:121–132— so/save,/quiet,/stop,/voicereply "not connected" on that path), falls back tocreateFixtureSophiaGrounderunless a retriever is passed (index.ts:89–98; no caller passes one), and has no/start link-<nonce>account-link completion (that lives only inroutes/telegram.ts:213–223).
Spec promise: features.md 5797–5816 — bot delivery of grounded answers with inline citation buttons, command surface, crisis replies; 5882–5886 (account-link/binding flows reach the user in chat).
What the code actually does: two half-bots. The BFF half has the brains (real grounding, real effects, link-nonce completion, payments, crisis copy) and no mouth; the grammY half has the mouth and neither brains-wiring nor an entrypoint. End-to-end, a Telegram user who messages the bot receives nothing, ever. This also makes the bot's session "multi-turn" question moot — there is no turn one. (Per-update handling is otherwise stateless: no conversation state beyond the rate-limiter and the effects store; crisis "suppression for the conversation" is not persisted between updates either.)
Fix sketch: pick ONE runway. Either (a) make the BFF webhook deliver: after
handleBffTelegramWebhook, POST each BotResponse to the Bot API with
OSHUN_TELEGRAM_BOT_TOKEN (sendMessage/answerCallbackQuery/answerInlineQuery,
mapping inlineButtons → reply_markup), keeping the HTTP 200 body inert; or
(b) give createOshunGrammyBot a real entrypoint + serve target and wire it
with createTelegramEffectsPort, createBffSophiaRetriever, and the link-nonce
completion. Delete or fold in the loser.
2. /v1/notifications fabricates seven canonical notifications for every user — fake billing, safety, and moderation events on the live in-app center#
Severity: P0-HONESTY
Evidence: apps/oshun/bff/src/routes/notifications.ts:336–480
(buildCanonicalLaneNotifications) — hardcoded items injected into every
response of the live /v1/notifications route (line 214), filtered only by
domain scope, with synthetic staggered timestamps derived from generatedAt
(line 472) so they always look fresh. Among them: "Billing review needs your
confirmation — Support flagged a renewal mismatch on your Veritas upgrade",
"Safety review requires attention — A protected account event needs
confirmation", "Admin moderation follow-up is pending", "Data export package is
ready — Your last export request finished successfully". The web notification
center renders this route verbatim
(apps/oshun/web/src/components/NotificationsCenterPanel.tsx:964).
Spec promise: features.md 5770–5772 (channel-aware delivery routed by real user state); the web/in-app channel is held to the same honesty bar as every other surface — nothing in the spec authorizes demonstration notifications.
What the code actually does: tells every user that support flagged their billing, that a safety event needs their confirmation, and that a data export they never requested is ready. These are result-faking fixtures on a live path — the exact class the quality standard bans — and the safety/billing ones actively train users to ignore real alerts.
Fix sketch: delete buildCanonicalLaneNotifications and source lane items from
the real stores that exist (reminder inbox, data-export job state, abuse
report/moderation stores, billing events); serve honest emptiness for lanes with
no real events.
3. Channel-binding verification codes are never sent — which makes the email/SMS/WhatsApp reminder legs permanently unreachable in production#
Severity: P1 (structural consequence chain)
Evidence: apps/oshun/bff/src/routes/channel-bindings.ts:96–104 — the bind
route mints + hashes a code and then unconditionally reports
delivery: 'missing-config' in production ("no transport wired yet" per the
header comment, lines 10–14). It never attempts delivery. But the transports ARE
wired elsewhere in this very BFF: the signup email-verify flow resolves
SendGrid/SMTP from the same env and actually sends
(auth/verification-email-sender.ts:86–145), and deliverWithEnvProviders
covers Twilio SMS + WhatsApp. Consequence: in prod no member can ever produce a
status:'verified' binding → E3's gate (reminders/reminders-route.ts:272–300)
sets userOptIns: [] for every email/sms/whatsapp reminder → the dispatcher
suppresses them all — even on a deployment with full SendGrid/Twilio/WhatsApp
credentials.
Spec promise: features.md 5772–5773 ("channel binding requires verified ownership" — i.e., verification must be completable), 5917–5926 (email/SMS for verified-identity flows: login codes etc.).
What the code actually does: honest about the non-send (good), but the "deferred deploy-bound piece" framing is wrong — the missing piece is ~20 lines of in-repo wiring to transports that already exist and are already used by the auth flow next door. As shipped, external-channel reminder parity is structurally zero regardless of creds.
Fix sketch: in the bind route, dispatch the code through
deliverWithEnvProviders (email → SendGrid/SMTP config, sms → Twilio, whatsapp
→ Meta template) and report the real transport outcome; keep missing-config
only when the env genuinely lacks the channel's creds.
4. Telegram /quiet (and the notification-preferences PATCH) write a quiet-hours flag the dispatcher never reads#
Severity: P1
Evidence: the bot's /quiet effect writes
notificationPreferencesStore.updateSettings(userId, { quietHours: { enabled: true } })
(telegram/effects-adapter.ts:58–65) and replies "Quiet hours are on for your
account." But the reminder dispatcher discards that store's enabled flag:
reminders-route.ts:286–289 builds
{ ...preferences.quietHours, enabled: consumerRecord.preferences.notifications.quietHoursEnabled }
— the enabled bit comes ONLY from consumerProfileStateStore (written by
routes/profile.ts:367). The same override happens in the preferences API's own
GET/PATCH responses (routes/notifications-preferences.ts:97–100, 272–275), so
PATCH /v1/notifications/preferences { quietHours: { enabled } } is a dead
write too (the web UI only works because its toggle double-writes the profile
master flag, NotificationPreferences.tsx:975–983; the Telegram path has no
such second write).
Spec promise: features.md 5778 (quiet-hours respect per channel); 5800 (/quiet
as a real command).
What the code actually does: B12's stated rationale ("the shared
notification-preference store for /quiet, so it actually gates delivery") was
true until E3 re-pointed the enabled flag at the consumer-profile store.
Post-E3, a Telegram /quiet changes nothing about delivery while the bot
affirms it did — a fabricated outcome by composition of two honest halves.
Fix sketch: make one store authoritative for quietHours.enabled (simplest:
have the effects adapter also write consumerProfileStateStore
notifications.quietHoursEnabled, or have the dispatcher OR the two flags); fix
the PATCH endpoint the same way.
5. Notification preference toggles (master push, domain modalities, kinds) are stored, surfaced in the UI, and never enforced on any actual send#
Severity: P1
Evidence: the preference model has per-domain kinds.reminder and
modalities: { inApp, push, emailDigest } plus a profile master pushEnabled
(notifications/preferences-store.ts:14–50;
routes/notifications-preferences.ts:92–96 even reports modality "availability"
from the master flags). Enforcement audit: the ONLY consumer is the in-app feed
filter (routes/notifications.ts:482–514, inApp modality + kinds, feed items
only). The reminder pipeline never reads any of it —
enrichReminderWithLivePolicy (reminders-route.ts:280–312) reads quiet hours,
bindings, crisis, nothing else; resolveDevicePushBinding
(routes/device-tokens.ts:185–195) returns the push target unconditionally;
producers set channel:'push' with no preference read
(reminders/streak-reminder-producer.ts:91–99); and the planner DEFAULTS to
opted-in when userOptIns is absent (v3-session-reminders.ts:308–313
toChannelSet(channels ?? [fallback])) — the inverse of the spec's "default-off
opt-in".
Spec promise: features.md 5769–5773 ("dispatcher routing by user preference... per-user channel preferences with default-off opt-in").
What the code actually does: a user who turns off push (master or per-domain) or turns off the "reminder" kind keeps receiving push reminders on every registered device; the settings screen is a comprehensive control panel for switches connected to nothing on the send path.
Fix sketch: in enrichReminderWithLivePolicy, drop userOptIns to [] when
the recipient's master pushEnabled is false or the relevant domain
modalities.push/kinds.reminder is false (map reminder producer → domain);
make the planner's no-opt-in default suppress rather than allow for external
channels.
6. WhatsApp leg: the message content is dropped on the floor; template registry, 24-hour session window, and status-webhook ingestion have zero runtime callers and no inbound route#
Severity: P1
Evidence:
transports.ts:333–370sendWhatsAppViaMetaCloudsends only{ type:'template', template: { name, language } }— nocomponents, so the computedbody(session title, start time, link, disclosure copy, provenance footer — assembled atdelivery.ts:185and passed to every other channel) is silently discarded;delivery.ts:310–324never passes it.- One global template for everything:
provider-config-env.tsreads a singleOSHUN_WHATSAPP_TEMPLATE+OSHUN_WHATSAPP_LANGUAGEfor all message kinds and locales. - The lib's WhatsApp domain logic —
planWhatsAppTemplateDelivery(per-locale- use-case approval gating, 24-hour customer-initiated session window,
cost-ledger entry) and
ingestWhatsAppStatusWebhook(libs/.../whatsapp/index.ts:86–130) — has zero callers outside its tests, and the BFF has no WhatsApp inbound webhook route at all (grep ofapps/oshun/bff/src/routes+app.ts: nothing).
- use-case approval gating, 24-hour customer-initiated session window,
cost-ledger entry) and
Spec promise: features.md 5897–5912 — approved-template messaging WITH content (receipts, reminders, scheduled-event nudges), template registry with per-locale approval as a release gate, 24-hour session-window handling, message-status webhook ingestion, cost ledger.
What the code actually does: a WhatsApp "reminder" delivers whatever static copy
the one Meta-approved template contains — never the session it is reminding
about — and Meta delivery/opt-out statuses are never ingested, so a
failed/opted_out recipient keeps being messaged.
Fix sketch: extend sendWhatsAppViaMetaCloud to accept
components: [{ type:'body', parameters: [...] }] and map title/startsAt/link
into them; route sends through planWhatsAppTemplateDelivery's registry/window
checks; add POST /v1/webhooks/whatsapp feeding ingestWhatsAppStatusWebhook
into the deliverability/suppression store.
7. FCM push is configured with a static OAuth access token that expires after ~1 hour#
Severity: P1
Evidence: provider-config-env.ts:106–115 reads OSHUN_FCM_ACCESS_TOKEN
straight from env into config.push.accessToken; transports.ts:132–165 sends
it as the Bearer to FCM HTTP v1
(fcm.googleapis.com/v1/projects/<p>/messages:send). FCM v1 does not have
long-lived server keys — the Bearer must be a Google OAuth2 access token minted
from a service-account key, valid ~3600s. There is no token-mint flow anywhere
in the repo (no JWT-bearer grant, no google-auth dependency on this path;
contrast APNs, which correctly mints its ES256 provider JWT per send at
transports.ts:183–199).
Spec promise: features.md 5917–5920 (push adapter covering FCM as a working production channel).
What the code actually does: any deployment can satisfy the env contract only
for the first hour after manually minting a token; after that every push-fcm
send fails 401. The channel is structurally un-operable as configured, not
merely cred-gated.
Fix sketch: accept OSHUN_FCM_SERVICE_ACCOUNT_JSON (or key path), mint and
cache the OAuth token via the JWT-bearer grant (sign with node:crypto, POST to
oauth2.googleapis.com/token, refresh before expiry) — mirroring the APNs JWT
pattern already in the file.
8. The always-available in-app reminder inbox has no UI — reminders "deliver" into a store no user can see#
Severity: P1
Evidence: GET /v1/reminders/inbox (reminders-route.ts:470–493) is the read
side of the in-app sink that makes the whole reminder subsystem
"always-available without creds" (reminder-scheduler.ts:136–154). Repo-wide
grep for reminders/inbox outside the BFF: zero hits — not in apps/oshun/web,
not in apps/oshun/mobile. The web notification center fetches only
/v1/notifications (NotificationsCenterPanel.tsx:964), which does not merge
the reminder inbox.
Spec promise: features.md 5769–5771 (delivery dispatcher with per-channel fall-through — in-app is the terminal fallback channel; a fallback nobody can read is not delivery).
What the code actually does: on a creds-less deployment (the current default),
every produced reminder — at-risk streaks, upcoming sessions, due assignments,
content drops, Nyx events — lands exclusively in a Map only the DSAR export ever
reads. The "recipient was still reached" accounting at
reminder-scheduler.ts:174–176 is false in user-experience terms.
Fix sketch: merge readReminderInbox(userId) items into the /v1/notifications
payload (kind reminder, lane by tenant/domain, read state via the existing
read-state store), or add an inbox section to NotificationsCenterPanel.
9. Stored Telegram controls that nothing enforces: /stop's "scheduled sends cancelled" claim, the voice-replies toggle, and the unlink cascade#
Severity: P2
Evidence:
/stop: bot replies "Telegram delivery stopped and scheduled sends cancelled" (bot.ts:254–258); the adapter sets adeliveryStoppedflag (effects-adapter.ts:67–70), but the only reader is theGET /telegram/capturesecho (routes/telegram.ts:339) — no delivery or scheduling path consults it, and nothing is cancelled./voice:toggleVoiceRepliespersists a flag;BotResponse.methodincludes'sendVoice'(bot.ts:49) but no code path ever emits it,synthesizeTelegramVoiceis an optional interface member with no implementation, andisVoiceRepliesEnabledis only echoed back (routes/telegram.ts:338). The spec's "TTS-back reply option" (5806–5807) is a stored toggle with no behavior.- Unlink: spec 5887–5890 requires revocation to cascade (terminate Mini App
sessions, remove scheduled sends, post revocation notice).
unlinkTelegramByTelegramUserId(user-state-store.ts:267–292) only marks the link record revoked; minted Mini App session JWTs stay valid to expiry and no scheduled-send teardown occurs.
Spec promise: features.md 5800 (/stop), 5806–5807 (TTS-back), 5887–5890
(revocation cascade), 5963–5967 (consent-revocation cascade).
What the code actually does: honest writes with overclaiming copy and no downstream consumers — config stored, never enforced.
Fix sketch: have the reminder cycle and any future Telegram delivery check
isDeliveryStopped; soften /stop copy to what actually happens until then;
either implement TTS-back (ElevenLabs provider exists in the BFF) or remove the
/voice toggle; on unlink, blacklist the Telegram-derived session ids and purge
the user's scheduled reminders for telegram channels.
10. Orphaned engines: email bounce/suppression, deliverability metrics, digest scheduler, lib preference/opt-in model, channel audit envelopes — tested, exported, zero runtime callers#
Severity: P2
Evidence (repo-wide grep over apps/, excluding tests — zero callers each):
ingestEmailWebhookEvent/buildTransactionalEmail(list-unsubscribe headers, bounce→suppression) —libs/.../email/index.ts:29–115; no SendGrid event webhook route exists, so bounces/complaints never suppress anything (spec 5914–5916).computeChannelDeliverability/summarizeDeliverabilityAcrossChannels(deliverability.ts) — no delivery result is ever recorded into it; the spec's deliverability monitoring (5921–5923) has an engine and no feed.apps/oshun/bff/src/notifications/digest.ts— a complete digest scheduling engine with ZERO importers; the digest preferences users edit in the web UI (frequency, delivery time, includeRead) configure a worker that does not exist (spec 5914–5917 locale-aware email templates/digest).libs/.../preferences.ts(recordBinding/activeOptIns) — superseded by the BFF's own binding store; dead parallel model.buildChannelAuditEnvelope— envelopes are built per Telegram response (bot.ts:114–137) but only ever serialized into the webhook HTTP response body; never written to the audit-events store, so the spec's "channel-aware audit envelope on every send/receive" (5968–5971) is constructed and discarded. Telegram editorial channel publishing is the same shape:synthesizeTelegramChannelPost/takedownTelegramChannelPostfeed the admin UI (apps/oshun/admin/src/app/messaging/telegram-channels/) but no code posts to a Telegram channel or calls edit-message for takedown (5840–5855) — subsumed by finding 1's "no outbound Telegram transport".
Spec promise: lines cited inline above.
What the code actually does: the "strong lib (223 tests)" half of the 06-10 headline remains accurate in both directions — strong, and substantially unconsumed at the edges listed here.
Fix sketch: add the SendGrid/Twilio status webhook routes feeding
ingestEmailWebhookEvent + a suppression check in deliverDispatchedMessage;
record each MessageDeliveryResult into the deliverability store and expose it
on the admin messaging console; either start a digest worker tick (compose from
the read-state store, deliver via the email transport) or remove the digest UI;
persist BotResponse.auditEvent to the audit-events store at the webhook.
11. UX cohesion — settings promise more than the system delivers#
Severity: UX
Evidence: NotificationPreferences.tsx exposes per-domain kind/modality
matrices, digest cadence, persona push toggles, and a per-device push
registration flow; /profile exposes channel binding + verification with
outcome-specific error copy; profile/telegram/page.tsx exposes the deep-link
account-link flow. Each is a polished front for a gap above: domain/kind/push
toggles unenforced (finding 5), digest never generated (finding 10), binding
codes undeliverable in prod (finding 3), and the Telegram link deep-link points
at a bot that cannot reply (finding 1) — the link COMPLETION works (webhook
side-channel, routes/telegram.ts:213–223) but the user receives no in-chat
confirmation, so the flow feels dead even when it succeeded.
Fix sketch: fixing findings 1, 3, 5, 10 resolves this; until then the honest UX move is to mark unenforced toggles and the digest section as not yet active rather than silently accepting input.
12. Deploy-bound (recorded for completeness, not findings)#
Severity: DEPLOY
- Channel creds:
OSHUN_SENDGRID_API_KEY/OSHUN_SMTP_*,OSHUN_TWILIO_*,OSHUN_FCM_*(after finding 7 is fixed),OSHUN_APNS_*,OSHUN_WEBPUSH_VAPID_*+NEXT_PUBLIC_VAPID_PUBLIC_KEY,OSHUN_WHATSAPP_*,OSHUN_TELEGRAM_BOT_TOKEN/_WEBHOOK_SECRET, STT key. OSHUN_REMINDER_WORKER_INTERVAL_MSto enable the delivery worker (fail-closed off by default — correct posture).- Telegram
setWebhookregistration (no automation in repo; must point at whichever runway finding 1 selects).
Severity counts#
| Severity | Count | Findings |
|---|---|---|
| P0-SEC | 0 | — |
| P0-HONESTY | 1 | #2 fabricated notification-center events |
| P0-STRUCT | 1 | #1 Telegram bot has no runway (replies never delivered; deliverable service never run) |
| P1 | 6 | #3 binding codes never sent → email/SMS/WhatsApp legs dead; #4 /quiet writes a flag the dispatcher ignores; #5 preference toggles unenforced on sends; #6 WhatsApp content dropped + no status ingestion; #7 static FCM v1 token cannot work; #8 in-app reminder inbox has no UI |
| P2 | 2 | #9 /stop//voice/unlink stored-not-enforced; #10 orphaned engines (email webhooks, deliverability, digest, audit envelopes, channel publishing) |
| UX | 1 | #11 settings/binding/link surfaces front unenforced or unreachable behavior |
| DEPLOY | 1 | #12 creds + worker interval + setWebhook |