Skip to content

5.11.1 Introduction

news is MooNitoring News: the articles staff write in the Console and the public site where readers find them. It belongs to the Content domain of the platform. It has a small backend and a static site at news.moonitoring.com (decided 2026-11-05, D12 reopened): the backend keeps the articles, their translations and images, and the site is built from what is published and served as static pages, so readers never reach a backend and every article is an HTML page that search engines read at once.

Proposal for review

The contracts of this system are a proposal, not confirmed design: endpoints, events and calls were written from the refined requirements, the data model and the flows, and wait for review. What needs a decision is collected in Open Decisions.

5.11.1.1 Host Names

Environment Public site Backend
Prod news.moonitoring.com none: console.moonitoring.com/api/news/
Stage stage-news.moonitoring.com, testers only and never indexed none: stage-console.moonitoring.com/api/news/

news.moonitoring.com is the public site (decided 2026-11-05): the static files, served from Cloudflare Pages. The site and the system live in two repositories: the backend parts of news (news-backend, news-consumer, news-relay, news-sweeper, news-migrate, in Rust) in moonitoring-system-news, and the site, a Nuxt app like every interface, in moonitoring-app-news. Neither is part of the website at www.moonitoring.com. The backend has no host of its own, the one exception to the host name rule: only the Console calls it, through /api/news/ on its own host, and the site build and the preview service reach it inside Google Cloud with their own identities. How every public page is written for search and for link previews is in Public Web Pages.

5.11.1.2 Domains

Each domain of news is one API, with its own contract and its own version.

  • 5.11.2.1 Articles

    Drafts and their translations, review, publication and scheduling, previews on the Console host, and images uploaded by signed URL. /articles/v1

5.11.1.3 How It Is Used

Writing and publishing

  1. A member of staff with news.articles.write writes an article in the Console: one tab per language, Markdown beside a live preview, and a side panel with the slug, the summary, the cover with its alt text and how the link will look when shared.
  2. Images go straight to the media bucket with a signed URL; the backend checks each one before it can be used.
  3. The writer submits it; a member of staff with news.articles.publish publishes it now or schedules it. Every change of status is an audit event.
  4. Publishing emits article.published.v1. news-consumer receives it by Pub/Sub push and starts the build of the site, which reads every published article from the backend, renders each page, the sitemap and the feeds, and deploys the files. Readers see the article within minutes.
  5. A scheduled article is published by news-sweeper, which Cloud Scheduler calls every five minutes.

Previewing

"Full preview" in the Console opens the real page before it is public: news-preview, the same Nuxt app of moonitoring-app-news built as a server and deployed as a Cloud Run service, which renders the site's pages on request, answers on console.moonitoring.com/preview/news/ behind Identity-Aware Proxy, and reads the draft with a preview link that lasts 30 minutes. It uses the same components as the public build, so what staff see is what readers will get; preview pages are never indexed.

Reading

  1. A reader opens news.moonitoring.com/it/<slug>, a static page cached at the edge.
  2. A language with no translation shows the first ready translation in the site's order (Italian, then English): the address of the missing language redirects to it, and the page says which language it is in. Pages link only to translations that exist.
  3. A slug changed after publication answers a permanent redirect to the new one; an unpublished article answers 410 Gone.
flowchart LR staff{{Staff}} -->|Console| api[news-backend] api --> db[(news database)] api -->|signed URL| media[(media bucket)] api -->|article.published.v1| consumer[news-consumer] consumer -->|starts| build[Site build] build -->|reads published| api build -->|static files| site[Public site] reader{{Reader}} -->|news.moonitoring.com| site staff -->|Full preview| preview[news-preview] preview --> api
  • Called by: Console (REST); access (gRPC CatalogService); farm (gRPC CatalogService); moochat (gRPC CatalogService).
  • Calls: access (gRPC OrganizationsService); farm (gRPC EntitlementsService).
  • Publishes events consumed by: nobody yet.
  • Consumes events of: access (1 entry).
  • Reads no other system's database: everything above goes through a contract on this page or an event.

5.11.1.4 Synchronous Calls Between Systems

None. The site build and the preview service are components of news: they read published content and previews from news-backend with their own service accounts, through internal endpoints that are not part of the public contract.

5.11.1.5 Events

Events are facts in the past tense, published through the outbox and delivered at least once on the topic news.events.v1; the envelope and the guarantees are in common/v1/events.yaml. Today only news itself consumes them, to rebuild the site.

Publishes (contract: events/v1/asyncapi.yaml):

Event Published when Consumers Outside
article.published.v1 An article was published, or its scheduled time came; the site is rebuilt with it. none yet no
article.updated.v1 A published article changed in a way readers can see; the site is rebuilt. none yet no
article.unpublished.v1 An article was unpublished; its pages answer 410 Gone after the next build. none yet no

Consumes:

Event From Why
staff_membership.changed.v1, staff_role.updated.v1 access Authorizes the staff who write and publish, and shows authors by their public name.