This page covers Regulation (EU) 2024/1689 (the AI Act) as it applies to a SaaS built on this boilerplate. It is an implementation baseline, not legal advice — classification under Annex III is a determination about your product, and no config flag can make it for you.

Deadlines

DateWhat applies
2 Feb 2025Prohibited practices (Art. 5) and AI literacy (Art. 4)
2 Aug 2025GPAI model provider obligations — these bind OpenAI/Anthropic/Google, not you
2 Aug 2026Transparency obligations (Art. 50). In force now.
2 Dec 2026Art. 50(2) output marking, for systems already on the market on 2 Aug 2026
2 Dec 2027Annex III high-risk obligations (deferred by the Digital Omnibus)

Article 50 was excluded from the Digital Omnibus deferral that moved high-risk obligations to December 2027. If you expose a chat assistant to natural persons in the EU, you are in scope today. Penalties reach EUR 15 000 000 or 3 % of worldwide annual turnover.

What the boilerplate implements

ArticleObligationImplementation
50(1)Inform people they are interacting with an AI systemAiDisclosureNotice in both chat surfaces — empty state and above the composer — plus the public /[locale]/ai-transparency page. Strings in ai.disclosure.*.
50(2)Mark generated output machine-readable and detectablechat_messages.ai_generated + chat_messages.ai_provider (durable), and X-AI-Generated / X-AI-Model / X-AI-Provider / X-AI-Notice-Version response headers on the SSE stream (in-transit). AiGeneratedBadge is the human-readable counterpart.
50(4)Disclose AI-generated public-interest textaiActConfig.publishesPublicInterestTextan operator decision, off by default. See below.
4AI literacyThe transparency page's purpose, limitations, and provider sections; this documentation set.
5Prohibited practicesTerms of service section 6 forbids the Art. 5 practices and makes the user responsible for their own outputs.

What you must do yourself

1. Classify your use case

AI_ACT_RISK_TIER defaults to limited, never minimal — a product that ships a chat assistant interacts directly with natural persons by construction. Set it to high only after a real assessment, and declare the categories:

bash
AI_ACT_ANNEX_III_USE_CASES=employment-worker-management,creditworthiness-scoring

Declaring any Annex III category escalates riskTier to high regardless of AI_ACT_RISK_TIER, because a configuration that claims both is contradictory and the safe reading is the stricter one.

The Annex III categories recognised by config/ai-act.ts:

biometric-identification, critical-infrastructure, education-vocational-training, employment-worker-management, essential-services-and-benefits, creditworthiness-scoring, life-health-insurance-pricing, law-enforcement, migration-asylum-border-control, administration-of-justice, democratic-processes

The single most common failure mode is shipping an HR-screening or credit-scoring feature on a "it's just a chatbot" mental model. If you are unsure whether your feature lands in one of these, that uncertainty is itself the signal to get advice.

Setting high does not make you compliant. It makes the product surface the additional notices. High-risk status brings risk management, data governance, technical documentation, logging, human oversight, accuracy and robustness requirements, conformity assessment, CE marking, and registration in the EU database — none of which a boilerplate can provide.

2. Decide whether Art. 50(4) applies to you

The boilerplate ships a CMS and a blog. If you auto-publish model-written posts intended to inform the public on matters of public interest, set:

bash
AI_ACT_PUBLISHES_PUBLIC_INTEREST_TEXT=true

and label that content as AI-generated — unless it went through substantive human review with an identified person holding editorial responsibility. Review is the exemption; a rubber stamp is not review.

3. Keep the provider disclosure accurate

AI_PROVIDER_DISCLOSURES in config/ai-act.ts describes each provider as a legal entity and processing region. The transparency page renders only the providers whose API key is actually configured, so the published notice tracks the real data flow. Review these entries whenever you sign or change a provider DPA, and bump AI_TRANSPARENCY_NOTICE_VERSION when you do.

4. Do not disable the disclosure casually

Art. 50(1) permits omission only where AI involvement is "obvious to a reasonably well-informed person". That exemption is narrow and contested. aiActConfig.disclosure.enabled exists so the choice is explicit — if you turn it off, record why.

Environment variables

VariableDefaultPurpose
AI_ACT_RISK_TIERlimitedminimal | limited | high
AI_ACT_ANNEX_III_USE_CASES(empty)Comma-separated Annex III categories; any value forces high
AI_ACT_PUBLISHES_PUBLIC_INTEREST_TEXTfalseArt. 50(4) gate for published AI text

Verifying the marking works

bash
curl -N -X POST https://your-app/api/ai/stream -D - -o /dev/null \
  -H 'Content-Type: application/json' \
  -H 'Cookie: <session>' \
  --data '{"accountId":"<uuid>","message":"hello"}'

The response headers must include X-AI-Generated: true. In the database, every assistant row must satisfy ai_generated = true:

sql
select count(*) from chat_messages where role = 'assistant' and ai_generated = false;

A non-zero count means output was written through a path that bypasses recordAiStreamUsage — fix the path rather than backfilling, or the gap reappears on the next message.

Known gaps

  • Text-only marking. The X-AI-* headers and the database flag cover text. If you add image, audio, or video generation, Art. 50(2) expects a marking that travels with the file — C2PA / Content Credentials — which is not implemented here.
  • No conformity assessment tooling. If you declare high, everything in Chapter III is on you.
  • RAG uploads. Documents you add to the knowledge base are sent to the embedding provider. This is disclosed on the transparency page but there is no per-upload interstitial.