Cosmic Story v2 architecture — a deep dive.

For engineers, PMs, journalists, and partnership scouts. The full pipeline, four MongoDB collections, EDA events, V-Model rigor, performance targets, security, and accessibility — all on one page.

  • Soulwise-story is a new NestJS module alongside the existing cosmic-story module. Zero direct imports between feature modules.
  • Four MongoDB collections: soulwise_persons, soulwise_chapters, soulwise_journal_entries, soulwise_resonances. AES-256 encrypted bodies, indexed for the queries each serves.
  • Async generation via BullMQ queue with 28 s timeout. Events emitted via EventEmitter2 only after database commit — no phantom inbox items.
  • V-Model spec: 119 requirements, zero gaps. Backend coverage target 85% statement on services; frontend 90% on Pinia stores.

The pipeline, again, with engineering detail

Each step has a service, a contract, and an event.

  1. Trigger

    A user action — 'generate today's chapter for Sister' — or a scheduled cron, like the Sunday 9 a.m. recap, or the every-6-hours weather refresh.

  2. Queue

    The job lands on a BullMQ queue named soulwise-chapter-generation, with a hard 28-second timeout. Long-running jobs are killed and reported as 'try again' to the user.

  3. Compose

    The ChapterGenerationService assembles the four-factor prompt — person context, astrology, signal, cadence — into a single input. No raw user PII goes into the prompt verbatim; everything is scrubbed first.

  4. Generate

    An AI provider is called via the AI_GENERATION_ADAPTER symbol token — the provider is swappable. The response is checked for length, shape, and safety before continuing.

  5. Post-process

    Four things happen: a crisis classifier checks for crisis language; an aspect-chip extractor pulls one to three astrology chips; an anti-claim filter strips forbidden phrasings; the body is AES-256 encrypted with a platform-managed key.

  6. Persist

    The artifact is written to the appropriate MongoDB collection — chapters, journal entries, resonances — with userId and personId indexes for fast lookup. Soft-delete first; hard-delete of PII at 30 days.

  7. Notify

    An EventEmitter2 event — CHAPTER_COMPLETED, JOURNAL_CREATED — fires after the database commit. The notifications module picks it up, creates an inbox item, and optionally sends a push (capped at one a day, quiet hours respected).

  8. Surface

    The frontend pulls the artifact via an authenticated API call. The Hub re-renders with the new content. If the user was offline, the cache serves yesterday's view and the new artifact appears on reconnect.

Seven steps from trigger to surface, each one named after what it actually does.

The four collections

Indexed for the queries each one answers.

soulwise_persons

Album entries. Indexes on userId, status, deletedAt. Soft-delete first; hard-delete of PII at 30 days.

soulwise_chapters

AI-written chapters, encrypted body. Indexes on personId, userId, generatedAt. Aspect chips stored as a separate array for fast filtering.

soulwise_journal_entries

User-written reflections, encrypted body. Indexes on userId, personId, createdAt. Text-indexed body for search. Per-entry 'private — do not feed to Luminara' flag.

soulwise_resonances

Four-dimension scores per bond. Unique index on personId. Recomputed via service call after chapter or journal write.

EDA events

Strict rule: events fire only after the database commit. Cross-module dependencies via Symbol injection tokens, never via forwardRef. No direct service-to-service imports between feature modules.

  • SoulwiseEvents.CHAPTER_COMPLETED — SoulwiseEvents.CHAPTER_COMPLETED — fired after a chapter is encrypted and persisted. Notifications-v2 listens; creates inbox item; optionally sends push.
  • SoulwiseEvents.JOURNAL_CREATED — SoulwiseEvents.JOURNAL_CREATED — fired after a journal entry is encrypted and persisted. Resonance service listens; triggers recompute.
  • SoulwiseEvents.PERSON_BIRTH_UPDATED — SoulwiseEvents.PERSON_BIRTH_UPDATED — fired after a person's birth-data changes. Synastry cache invalidates.
  • SoulwiseEvents.PUSH_REQUESTED — SoulwiseEvents.PUSH_REQUESTED — per notifications-v2 contract; respects push budget and quiet hours.

V-Model spec rigor

119 traceable requirements, zero gaps. Each requirement maps forward to a test case (UTP, ITP, STP, E2E) and backward to a user story. 20 user stories. 15 functional requirements. 12 non-functional categories. 8 global acceptance gates.

Performance contract

Chapter generation 30 seconds or better for 95% of requests, measured against BullMQ job duration distribution. API p99 GET latency 500 ms or better at 1,000 concurrent users, measured via k6 load test. Frontend TTI 3 seconds or better on simulated 4G, measured via Lighthouse CI.

Security contract

AES-256 encryption at rest with platform-managed keys for journal and chapter bodies. TLS 1.2+ in transit; HTTP→HTTPS redirect. JWT access tokens with 1-hour lifetime, refresh tokens with 30-day lifetime, rotation on refresh. Soft-delete with 30-day window before hard-delete of PII.

Accessibility contract

prefers-reduced-motion globally respected — GSAP animations become opacity-only fades. VoiceOver and TalkBack labels on every interactive element. Manually verified on iOS and Android before each release.

Why a separate soulwise-story module instead of extending cosmic-story?

Because the upstream spec rebuilds the feature, and rebuilding inside an existing module would either break the v1 experience or fork-then-merge later. A new module keeps v1 untouched, lets v2 prove out, and migrates cleanly when ready.

Why MongoDB and not Postgres?

The existing My Zodiac AI backend is on MongoDB; switching would mean an infrastructure decision unrelated to this feature. The document model also fits chapters and journal entries well — nested, varying-length, encrypted-as-blob.

Why is BullMQ the queue choice?

BullMQ runs on Redis, which is already in the stack for session and rate-limit. No new infrastructure. Built-in retry, timeout, and observability cover the chapter-generation needs without custom plumbing.

Where is the upstream spec actually written down?

Internal repo. The numbers and contracts on this page paraphrase the upstream V-Model artifacts. Public-facing engineering blog posts on My Zodiac AI's blog cluster (tagged 'cosmic-story-v2') go deeper into specific parts of the build.

Try My Zodiac AI today

While Soulwise opens its waves, our flagship astrology app is already in your hands.

Astrology content is for reflection and entertainment. Cosmic Story v2 features described here are in development; availability is subject to change without notice.