Skip to content

Commit 82d2202

Browse files
os-zhuangclaude
andauthored
feat(spec): add element:metadata_viewer component (ADR-0051 P1) (#1942)
Read-only SDUI component a ```metadata doc fence compiles to — the inline form of ADR-0046 §3.5 "derived content is rendered, never written". Renders a state_machine | flow | permission view live and permission-projected at read time; the props carry no expressions or actions, so the embed stays on the data side of the §3.4 trust boundary (embeddableInDoc). - New ElementMetadataViewerPropsSchema placed in Content Elements (read-only), not Interactive — reinforces the content-embeddable vs interactive-not boundary. - Registered as 'element:metadata_viewer' in ComponentPropsMap. - `detail` is the authored altitude (business collapses technical flow nodes); permission projection is automatic and render-time, not here. - `object` embeds deferred (ADR-0051 §5). Spec-only; the fence parser, resolver, publish lint and console render land in follow-ups. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 52dc3e9 commit 82d2202

1 file changed

Lines changed: 28 additions & 0 deletions

File tree

packages/spec/src/ui/component.zod.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,33 @@ export const ElementImagePropsSchema = lazySchema(() => z.object({
216216
aria: AriaPropsSchema.optional().describe('ARIA accessibility attributes'),
217217
}));
218218

219+
/**
220+
* Read-only, synthesized view of a metadata item, embedded inline in content
221+
* (ADR-0051). This is the *inline form* of ADR-0046 §3.5 ("derived content is
222+
* rendered, never written") and the component a ` ```metadata ` doc fence
223+
* compiles to. Because it renders the platform's *own* metadata via the
224+
* platform's *own* viewer, it carries no expressions or actions — it stays on
225+
* the data side of the §3.4 trust boundary and is safe to embed in inert docs
226+
* (`embeddableInDoc`). The view is resolved live at read time, then projected
227+
* to the reader's permissions automatically (see `detail` for the distinct,
228+
* author-controlled altitude projection). `object` embeds are deferred
229+
* (ADR-0051 §5).
230+
*/
231+
export const ElementMetadataViewerPropsSchema = lazySchema(() => z.object({
232+
type: z.enum(['state_machine', 'flow', 'permission'])
233+
.describe('Metadata view kind (ADR-0051): state_machine | flow | permission'),
234+
name: z.string()
235+
.describe('Target metadata item name; resolved package-scoped (ADR-0048), then dependencies (ADR-0046 §3.3)'),
236+
object: z.string().optional()
237+
.describe('Owning object — required for object-scoped kinds: state_machine is a rule ON an object (ADR-0020), permission renders a matrix FOR one; omit for top-level flow'),
238+
mode: z.enum(['diagram', 'matrix', 'summary']).optional()
239+
.describe('Render form; defaults per type (diagram for flow/state_machine, matrix for permission)'),
240+
detail: z.enum(['business', 'technical']).optional().default('business')
241+
.describe('Authoring altitude (ADR-0051 §3.4): business collapses technical flow nodes to business steps + approvals. NOT access (cf. book.audience); permission projection is automatic and render-time, never set here'),
242+
/** ARIA accessibility */
243+
aria: AriaPropsSchema.optional().describe('ARIA accessibility attributes'),
244+
}));
245+
219246
/**
220247
* ----------------------------------------------------------------------
221248
* 4. Interactive Element Components (Phase B — Element Library)
@@ -311,6 +338,7 @@ export const ComponentPropsMap = {
311338
'element:text': ElementTextPropsSchema,
312339
'element:number': ElementNumberPropsSchema,
313340
'element:image': ElementImagePropsSchema,
341+
'element:metadata_viewer': ElementMetadataViewerPropsSchema, // ADR-0051: inline read-only metadata view (embeddableInDoc)
314342
'element:divider': EmptyProps,
315343

316344
// Interactive Elements

0 commit comments

Comments
 (0)