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.
-
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¶
- A member of staff with
news.articles.writewrites 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. - Images go straight to the media bucket with a signed URL; the backend checks each one before it can be used.
- The writer submits it; a member of staff with
news.articles.publishpublishes it now or schedules it. Every change of status is an audit event. - Publishing emits
article.published.v1.news-consumerreceives 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. - 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¶
- A reader opens
news.moonitoring.com/it/<slug>, a static page cached at the edge. - 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.
- A slug changed after publication answers a permanent redirect to the new one; an unpublished article answers 410 Gone.
- Called by: Console (REST); access (gRPC
CatalogService); farm (gRPCCatalogService); moochat (gRPCCatalogService). - Calls: access (gRPC
OrganizationsService); farm (gRPCEntitlementsService). - 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. |