Everything on this page also renders in pipeline A's text primitive
(format: "markdown"), except footnotes — those are pipeline-B only. See the
Overview for the full comparison table.
Tables
Source:
| Method | Process | Owner |
| :--- | :---: | ---: |
| Traditional | Code → Test → Docs | Platform |
| Modern | Test → Code → Docs | Product |Rendered:
| Method | Process | Owner |
|---|---|---|
| Traditional | Code → Test → Docs | Platform |
| Modern | Test → Code → Docs | Product |
A wide table (long cells, many columns) scrolls inside its own container instead of
forcing the whole page to scroll horizontally — the wrapper is
.aup-markdown-table-wrap / .docs-table-wrap.
Task lists
Source:
- [x] Write the content pipeline
- [x] Ship GFM support
- [ ] Document every extension in one placeRendered:
- Write the content pipeline
- Ship GFM support
- Document every extension in one place
Checkboxes render disabled — this is a static reference, not an interactive to-do
list; checked state reflects what the author wrote in the source, not a live toggle.
Strikethrough
Source:
~~This approach is deprecated.~~ Use the new one instead.Rendered:
This approach is deprecated. Use the new one instead.
Code highlighting
Source:
```typescript
export function greet(name: string): string {
return `Hello, ${name}!`;
}
```Rendered:
export function greet(name: string): string {
return `Hello, ${name}!`;
}Fenced code blocks get a language label and a copy-to-clipboard button
(.aup-code-toolbar); the <code> element carries a language-<lang> class for
syntax-highlighting CSS to hook into.
Footnotes (pipeline B only)
Source:
Every request carries a signed capability token.[^cap]
[^cap]: See `docs/architecture/capability-tokens.md` for the token format.Rendered:
Every request carries a signed capability token.[1]
Footnotes are collected once per document and rendered in a single end-of-document section, numbered by first-reference order (not definition order). An unreferenced definition produces no footnotes section at all — it's silently dropped, matching this pipeline's general degrade-not-break posture for authoring mistakes.
Pipeline A does not support footnotes at all — [^1] inside an AUP
format: "markdown" text field renders as literal text, not a numbered reference.
Raw HTML (sanitized in both pipelines, different allowlists)
Inline and block-level raw HTML in the markdown source is allowed through an
allowlist of safe tags/attributes (content-reader.ts's sanitizeRawHtml) —
neither passed through verbatim (a storage-XSS vector) nor silently dropped.
Pipeline A also sanitizes raw HTML, but via a different mechanism. The AUP
text primitive's format: "markdown" renderer (renderMarkdown() in
providers/runtime/ui/src/web-page/core.ts) pipes marked.parse(raw) through
DOMPurify.sanitize(...) — a generic sanitizer with its own (broader,
library-default) allowlist, not the fixed, hand-curated tag list this
pipeline's sanitizeRawHtml uses. Both pipelines are safe against
storage-XSS; the exact set of surviving tags/attributes differs between them,
so don't assume a page that renders here renders identically through the AUP
text primitive.
Source:
<div class="callout"><strong>Note:</strong> this box is authored as raw HTML.</div>
<img src="https://example.com/diagram.png" onerror="alert(1)" alt="A diagram">
<script>alert("this never runs")</script>Rendered:

Only a fixed tag/attribute allowlist survives (div, details/summary,
headings, table, a/img with their safe attributes, and a handful of inline
tags): the <div>/<img> above render, but onerror is stripped from the
<img> (open the source of this page to confirm it's gone from the rendered
attribute list) and the whole <script> tag — including its body — disappears
without a trace. Each raw-HTML block converts independently: a multi-line
tag like <details>…<summary>…</summary>\n\nbody\n</details> with a blank line
inside it does NOT nest correctly — the blank line splits it into separate
paragraphs, breaking the <details>/<summary> structure. Keep raw HTML blocks
to a single line (or accept the broken nesting) rather than assuming multi-line
block HTML round-trips the way it would in the source. This is a genuinely new
capability (landed the same week as this reference, arc#2537/#2599) — check
content-reader.ts's RAW_HTML_ALLOWED_TAGS for the exact current allowlist
rather than assuming it matches this list forever.
docs/architecture/capability-tokens.md for the token format. ↩