Files
ARCADIA-Studio/docs/api.html
T
Codex e2ecfea69b
Rust checks / check (ubuntu-latest) (push) Canceled after 0s
Rust checks / check (windows-latest) (push) Canceled after 0s
Checkpoint source 7 workflows and in-progress diagram authoring redesign
Preserve current core, source, REST, desktop, recovery, documentation and validation work, including AGENTS.md and the development summary. This is a work-in-progress checkpoint: the new compact palette has outstanding compilation errors and native acceptance; earlier passing gates retain their documented scope.
2026-09-10 10:06:55 -07:00

1347 lines
71 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="utf-8" />
<meta name="generator" content="Docutils 0.22.2: https://docutils.sourceforge.io/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Arcadia Studio model REST API</title>
<style type="text/css">
/* Minimal style sheet for the HTML output of Docutils. */
/* */
/* :Author: Günter Milde, based on html4css1.css by David Goodger */
/* :Id: $Id: minimal.css 10018 2025-03-06 16:19:15Z milde $ */
/* :Copyright: © 2015, 2021 Günter Milde. */
/* :License: Released under the terms of the `2-Clause BSD license`_, */
/* in short: */
/* */
/* Copying and distribution of this file, with or without modification, */
/* are permitted in any medium without royalty provided the copyright */
/* notice and this notice are preserved. */
/* */
/* This file is offered as-is, without any warranty. */
/* */
/* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause */
/* This CSS3 stylesheet defines rules for Docutils elements without */
/* HTML equivalent. It is required to make the document semantics visible. */
/* */
/* .. _validates: http://jigsaw.w3.org/css-validator/validator$link */
/* titles */
p.topic-title,
p.admonition-title,
p.system-message-title {
font-weight: bold;
}
p.sidebar-title,
p.rubric {
font-weight: bold;
font-size: larger;
}
p.rubric {
color: maroon;
}
p.subtitle,
p.section-subtitle,
p.sidebar-subtitle {
font-weight: bold;
margin-top: -0.5em;
}
h1 + p.subtitle {
font-size: 1.6em;
}
a.toc-backref {
color: inherit;
text-decoration: none;
}
/* Warnings, Errors */
.system-messages h2,
.system-message-title,
pre.problematic,
span.problematic {
color: red;
}
/* Inline Literals */
.docutils.literal {
font-family: monospace;
white-space: pre-wrap;
}
/* do not wrap at hyphens and similar: */
.literal > span.pre { white-space: nowrap; }
/* keep line-breaks (\n) visible */
.pre-wrap { white-space: pre-wrap; }
/* Lists */
/* compact and simple lists: no margin between items */
.simple li, .simple ul, .simple ol, .simple > li p,
.compact li, .compact ul, .compact ol, .compact > li p,
dl.simple > dd, dl.compact > dd, dl.docinfo > dd {
margin-top: 0;
margin-bottom: 0;
}
/* Nested Paragraphs */
p:first-child { margin-top: 0; }
p:last-child { margin-bottom: 0; }
details > p:last-child { margin-bottom: 1em; }
/* Table of Contents */
.contents ul.auto-toc { /* section numbers present */
list-style-type: none;
}
/* Enumerated Lists */
ol.arabic { list-style: decimal }
ol.loweralpha { list-style: lower-alpha }
ol.upperalpha { list-style: upper-alpha }
ol.lowerroman { list-style: lower-roman }
ol.upperroman { list-style: upper-roman }
/* Definition Lists and Derivatives */
dt .classifier { font-style: italic }
dt .classifier:before {
font-style: normal;
margin: 0.5em;
content: ":";
}
/* Field Lists and similar */
/* bold field name, content starts on the same line */
dl.field-list,
dl.option-list,
dl.docinfo {
display: flow-root;
}
dl.field-list > dt,
dl.option-list > dt,
dl.docinfo > dt {
font-weight: bold;
clear: left;
float: left;
margin: 0;
padding: 0;
padding-right: 0.25em;
}
/* Offset for field content (corresponds to the --field-name-limit option) */
dl.field-list > dd,
dl.option-list > dd,
dl.docinfo > dd {
margin-left: 9em; /* ca. 14 chars in the test examples, fit all Docinfo fields */
}
/* start nested lists on new line */
dd > dl:first-child,
dd > ul:first-child,
dd > ol:first-child {
clear: left;
}
/* start field-body on a new line after long field names */
dl.field-list > dd > *:first-child,
dl.option-list > dd > *:first-child
{
display: inline-block;
width: 100%;
margin: 0;
}
/* Bibliographic Fields (docinfo) */
dl.docinfo pre.address {
font: inherit;
margin: 0;
}
dl.docinfo > dd.authors > p { margin: 0; }
/* Option Lists */
dl.option-list > dt { font-weight: normal; }
span.option { white-space: nowrap; }
/* Footnotes and Citations */
.footnote, .citation { margin: 1em 0; } /* default paragraph skip (Firefox) */
/* hanging indent */
.citation { padding-left: 2em; }
.footnote { padding-left: 1.7em; }
.footnote.superscript { padding-left: 1.0em; }
.citation > .label { margin-left: -2em; }
.footnote > .label { margin-left: -1.7em; }
.footnote.superscript > .label { margin-left: -1.0em; }
.footnote > .label + *,
.citation > .label + * {
display: inline-block;
margin-top: 0;
vertical-align: top;
}
.footnote > .backrefs + *,
.citation > .backrefs + * {
margin-top: 0;
}
.footnote > .label + p, .footnote > .backrefs + p,
.citation > .label + p, .citation > .backrefs + p {
display: inline;
vertical-align: inherit;
}
.backrefs { user-select: none; }
.backrefs > a { font-style: italic; }
/* superscript footnotes */
a[role="doc-noteref"].superscript,
.footnote.superscript > .label,
.footnote.superscript > .backrefs {
vertical-align: super;
font-size: smaller;
line-height: 1;
}
a[role="doc-noteref"].superscript > .fn-bracket,
.footnote.superscript > .label > .fn-bracket {
/* hide brackets in display but leave for copy/paste */
display: inline-block;
width: 0;
overflow: hidden;
}
[role="doc-noteref"].superscript + [role="doc-noteref"].superscript {
padding-left: 0.15em; /* separate consecutive footnote references */
/* TODO: unfortunately, "+" also selects with text between the references. */
}
/* Alignment */
.align-left {
text-align: left;
margin-right: auto;
}
.align-center {
text-align: center;
margin-left: auto;
margin-right: auto;
}
.align-right {
text-align: right;
margin-left: auto;
}
.align-top { vertical-align: top; }
.align-middle { vertical-align: middle; }
.align-bottom { vertical-align: bottom; }
/* reset inner alignment in figures and tables */
figure.align-left, figure.align-right,
table.align-left, table.align-center, table.align-right {
text-align: inherit;
}
/* Text Blocks */
.topic { margin: 1em 2em; }
.sidebar,
.admonition,
.system-message {
margin: 1em 2em;
border: thin solid;
padding: 0.5em 1em;
}
div.line-block { display: block; }
div.line-block div.line-block, pre { margin-left: 2em; }
/* Code line numbers: don't copy with drag-and-drop */
pre.code .ln { display: none; }
pre.code code:before {
content: attr(data-lineno);
font-size: small;
color: gray;
}
/* Tables */
table {
border-collapse: collapse;
}
td, th {
border: thin solid silver;
padding: 0 1ex;
}
.borderless td, .borderless th {
border: 0;
padding: 0;
padding-right: 0.5em /* separate table cells */
}
table > caption, figcaption {
text-align: left;
margin-top: 0.2em;
margin-bottom: 0.2em;
}
table.captionbelow {
caption-side: bottom;
}
/* MathML (see "math.css" for --math-output=HTML) */
math .boldsymbol { font-weight: bold; }
math.boxed, math .boxed {padding: 0.25em; border: thin solid; }
/* style table similar to AMS "align" or "aligned" environment: */
mtable.cases > mtr > mtd { text-align: left; }
mtable.ams-align > mtr > mtd { padding-left: 0; padding-right: 0; }
mtable.ams-align > mtr > mtd:nth-child(2n) { text-align: left; }
mtable.ams-align > mtr > mtd:nth-child(2n+1) { text-align: right; }
mtable.ams-align > mtr > mtd:nth-child(2n+3) { padding-left: 2em; }
.mathscr mi, mi.mathscr {
font-family: STIX, XITSMathJax_Script, rsfs10,
"Asana Math", Garamond, cursive;
}
/* Document Header and Footer */
header { border-bottom: 1px solid black; }
footer { border-top: 1px solid black; }
/* Images are block-level by default in Docutils */
/* New HTML5 block elements: set display for older browsers */
img, svg, header, footer, main, aside, nav, section, figure, video, details {
display: block;
}
svg { width: auto; height: auto; } /* enable scaling of SVG images */
/* inline images */
p img, p svg, p video,
h1 img, h2 img, h3 img, h4 img, h5 img, h6 img,
h1 svg, h2 svg, h3 svg, h4 svg, h5 svg, h6 svg {
display: inline;
}
</style>
<style type="text/css">
/* CSS31_ style sheet for the output of Docutils HTML writers. */
/* Rules for easy reading and pre-defined style variants. */
/* */
/* :Author: Günter Milde, based on html4css1.css by David Goodger */
/* :Id: $Id: plain.css 10079 2025-04-10 12:01:48Z milde $ */
/* :Copyright: © 2015 Günter Milde. */
/* :License: Released under the terms of the `2-Clause BSD license`_, */
/* in short: */
/* */
/* Copying and distribution of this file, with or without modification, */
/* are permitted in any medium without royalty provided the copyright */
/* notice and this notice are preserved. */
/* */
/* This file is offered as-is, without any warranty. */
/* */
/* .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause */
/* .. _CSS3: https://www.w3.org/Style/CSS/ */
/* Document Structure */
/* ****************** */
/* "page layout" */
body {
margin: 0;
background-color: #dbdbdb;
--field-indent: 9em; /* default indent of fields in field lists */
}
main, footer, header {
line-height:1.6;
/* avoid long lines --> better reading */
/* optimum is 45…75 characters/line <http://webtypography.net/2.1.2> */
/* OTOH: lines should not be too short because of missing hyphenation, */
max-width: 50rem;
padding: 1px 2%; /* 1px on top avoids grey bar above title (mozilla) */
margin: auto;
}
main {
counter-reset: table figure;
background-color: white;
}
footer, header {
font-size: smaller;
padding: 0.5em 2%;
border: none;
}
/* Table of Contents */
ul.auto-toc > li > p {
padding-left: 1em;
text-indent: -1em;
}
nav.contents ul {
padding-left: 1em;
}
main > nav.contents ul ul ul ul:not(.auto-toc) {
list-style-type: '\2B29\ ';
}
main > nav.contents ul ul ul ul ul:not(.auto-toc) {
list-style-type: '\2B1D\ ';
}
/* Transitions */
hr.docutils {
width: 80%;
margin-top: 1em;
margin-bottom: 1em;
clear: both;
}
/* Paragraphs */
/* vertical space (parskip) */
p, ol, ul, dl, li,
.footnote, .citation,
div > math,
table {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
h1, h2, h3, h4, h5, h6,
dd, details > p:last-child {
margin-bottom: 0.5em;
}
/* Lists */
/* ===== */
/* Definition Lists */
/* Indent lists nested in definition lists */
dd > ul:only-child, dd > ol:only-child { padding-left: 1em; }
/* Description Lists */
/* styled like in most dictionaries, encyclopedias etc. */
dl.description {
display: flow-root;
}
dl.description > dt {
font-weight: bold;
clear: left;
float: left;
margin: 0;
padding: 0;
padding-right: 0.3em;
}
dl.description > dd:after {
display: table;
content: "";
clear: left; /* clearfix for empty descriptions */
}
/* Field Lists */
dl.field-list > dd,
dl.docinfo > dd {
margin-left: var(--field-indent); /* adapted in media queries or HTML */
}
/* example for custom field-name width */
dl.field-list.narrow > dd {
--field-indent: 5em;
}
/* run-in: start field-body on same line after long field names */
dl.field-list.run-in > dd p {
display: block;
}
/* Bibliographic Fields */
/* generally, bibliographic fields use dl.docinfo */
/* but dedication and abstract are placed into divs */
div.abstract p.topic-title {
text-align: center;
}
div.dedication {
margin: 2em 5em;
text-align: center;
font-style: italic;
}
div.dedication p.topic-title {
font-style: normal;
}
/* disclosures */
details { padding-left: 1em; }
summary { margin-left: -1em; }
/* Text Blocks */
/* =========== */
/* Literal Blocks */
pre.literal-block, pre.doctest-block,
pre.math, pre.code {
font-family: monospace;
}
/* Block Quotes and Topics */
bockquote { margin: 1em 2em; }
blockquote p.attribution {
text-align: right;
margin-left: 20%;
}
/* Tables */
/* ====== */
/* th { vertical-align: bottom; } */
table tr { text-align: left; }
/* "booktabs" style (no vertical lines) */
table.booktabs {
border: 0;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.booktabs * {
border: 0;
}
table.booktabs th {
border-bottom: thin solid;
}
/* numbered tables (counter defined in div.document) */
table.numbered > caption:before {
counter-increment: table;
content: "Table " counter(table) ": ";
font-weight: bold;
}
/* Explicit Markup Blocks */
/* ====================== */
/* Footnotes and Citations */
/* ----------------------- */
/* line on the left */
.footnote-list {
border-left: solid thin;
padding-left: 0.25em;
}
/* Directives */
/* ---------- */
/* Body Elements */
/* ~~~~~~~~~~~~~ */
/* Images and Figures */
/* let content flow to the side of aligned images and figures */
figure.align-left,
img.align-left,
svg.align-left,
video.align-left,
div.align-left,
object.align-left {
clear: left;
float: left;
margin-right: 1em;
}
figure.align-right,
img.align-right,
svg.align-right,
video.align-right,
div.align-right,
object.align-right {
clear: right;
float: right;
margin-left: 1em;
}
/* Stop floating sidebars, images and figures */
h1, h2, h3, h4, footer, header { clear: both; }
/* Numbered figures */
figure.numbered > figcaption > p:before {
counter-increment: figure;
content: "Figure " counter(figure) ": ";
font-weight: bold;
}
/* Admonitions and System Messages */
.caution p.admonition-title,
.attention p.admonition-title,
.danger p.admonition-title,
.error p.admonition-title,
.warning p.admonition-title,
div.error {
color: red;
}
/* Sidebar */
/* Move right. In a layout with fixed margins, */
/* it can be moved into the margin. */
aside.sidebar {
width: 30%;
max-width: 26em;
float: right;
clear: right;
margin-left: 1em;
margin-right: -1%;
background-color: #fffffa;
}
/* Code */
pre.code { padding: 0.7ex }
pre.code, code { background-color: #eeeeee }
/* basic highlighting: for a complete scheme, see */
/* https://docutils.sourceforge.io/sandbox/stylesheets/ */
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
/* Epigraph */
/* Highlights */
/* Pull-Quote */
/* Compound Paragraph */
/* Container */
/* Inline Markup */
/* ============= */
sup, sub { line-height: 0.8; } /* do not add leading for lines with sup/sub */
/* Inline Literals */
/* possible values: normal, nowrap, pre, pre-wrap, pre-line */
/* span.docutils.literal { white-space: pre-wrap; } */
/* Hyperlink References */
a { text-decoration: none; }
/* External Targets */
/* span.target.external */
/* Internal Targets */
/* span.target.internal */
/* Footnote References */
/* a[role="doc-noteref"] */
/* Citation References */
/* a.citation-reference */
</style>
</head>
<body>
<main id="arcadia-studio-model-rest-api">
<h1 class="title">Arcadia Studio model REST API</h1>
<p>This is the HTTP contract for <span class="docutils literal"><span class="pre">oa-server</span></span>. The normative engineering model
and source language belong to <span class="docutils literal">language.rst</span>. <span class="docutils literal">openapi.json</span> describes the
JSON records and closed command vocabulary. The server uses the same Rust
<span class="docutils literal">Project</span>, <span class="docutils literal">Command</span>, parser/printer and validation implementation as the
desktop.</p>
<section id="identity-revision-and-writes">
<h2>Identity, revision and writes</h2>
<p>All model routes begin with <span class="docutils literal">/api/v1</span>. A hosted project's immutable service
<span class="docutils literal">resource_id</span> is different from its editable <span class="docutils literal">model.id</span>. Each stored file
contains <span class="docutils literal">{resource_id, revision, model, source_project}</span>. <span class="docutils literal">source_project</span>
is the accepted entry filename and map of authored source files; compiling it
must reproduce <span class="docutils literal">model</span>. The revision starts at 1, increments once per changed
accepted model/source pair, and does not change for an exact no-op. Comment-only
edits and file/entry changes count as changes even when the model is unchanged.</p>
<p>Existing-project writes require the exact quoted ETag returned by a project
read, for example:</p>
<pre class="literal-block">If-Match: &quot;p-6f7162cc-094c-4f30-9b70-3f6f355f0c7f-r1&quot;</pre>
<p>Missing preconditions return 428; stale preconditions return 412. Weak ETags,
wildcards and lists are not accepted on writes. GET of the envelope, model and
source/source-project supports <span class="docutils literal"><span class="pre">If-None-Match</span></span> and returns an empty 304 when unchanged.
Use ETags as opaque strings; revisions are unsigned integer counters in JSON.</p>
<p>Every accepted changed write is persisted before the response. A worker captures
a revision-qualified snapshot, then parses and validates its candidate outside
the catalog lock. Commit rechecks the exact ETag and atomically installs the
envelope under the lock. Another accepted edit during preparation therefore
returns 412 even when the original snapshot passed its initial revision check.
Malformed or rejected inputs preserve the accepted model. Incomplete-model
warnings permit work and are returned in <span class="docutils literal">issues</span>.</p>
<p>There is no retained revision history, idempotency receipt, tombstone or
server undo. DELETE permanently removes the hosted envelope. Source/JSON
interchange exports contain the current model only; source-project export also
preserves the authored file layout and comments. They preserve persistent
aliases, diagrams, artifact references and OA/SA trace data. Artifact revision
strings refer to external artifacts, not past server snapshots.</p>
<p>A lost connection or 504 can occur after an admitted write has begun. That
write may still complete. Read current state before choosing a new action.
Do not automatically retry POST create/import or regenerate random IDs and
assume the original request failed.</p>
</section>
<section id="routes">
<h2>Routes</h2>
<p>Health and schema routes are public. All model routes require the configured
bearer token, if any. Non-loopback binding requires a configured token.</p>
<table>
<caption>Endpoints</caption>
<colgroup>
<col style="width: 12.0%" />
<col style="width: 41.0%" />
<col style="width: 47.0%" />
</colgroup>
<thead>
<tr><th class="head"><p>Method</p></th>
<th class="head"><p>Path</p></th>
<th class="head"><p>Behavior</p></th>
</tr>
</thead>
<tbody>
<tr><td><p>GET</p></td>
<td><p><span class="docutils literal">/health</span>, <span class="docutils literal">/health/live</span>, <span class="docutils literal">/health/ready</span></p></td>
<td><p>Responding process with successfully opened store.</p></td>
</tr>
<tr><td><p>GET</p></td>
<td><p><span class="docutils literal">/openapi.json</span>, <span class="docutils literal">/api/v1/openapi.json</span></p></td>
<td><p>OpenAPI 3.1 contract.</p></td>
</tr>
<tr><td><p>POST</p></td>
<td><p><span class="docutils literal">/api/v1/projects</span></p></td>
<td><p>Create from <span class="docutils literal"><span class="pre">{&quot;name&quot;:&quot;...&quot;}</span></span>; 201 + Location/ETag.</p></td>
</tr>
<tr><td><p>GET</p></td>
<td><p><span class="docutils literal">/api/v1/projects</span></p></td>
<td><p>Summaries; <span class="docutils literal">limit</span>, <span class="docutils literal">after</span>, name substring <span class="docutils literal">q</span>.</p></td>
</tr>
<tr><td><p>GET</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}</span></span></p></td>
<td><p>Complete current stored envelope.</p></td>
</tr>
<tr><td><p>PATCH</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}</span></span></p></td>
<td><p>Conditional rename using <span class="docutils literal"><span class="pre">{&quot;name&quot;:&quot;...&quot;}</span></span>.</p></td>
</tr>
<tr><td><p>DELETE</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}</span></span></p></td>
<td><p>Conditional permanent removal; 204.</p></td>
</tr>
<tr><td><p>POST</p></td>
<td><p><span class="docutils literal">/api/v1/projects/import</span></p></td>
<td><p>Raw model JSON or Arcadia source; new service ID.</p></td>
</tr>
<tr><td><p>POST</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/import-source-project</span></span></p></td>
<td><p>Complete source bundle as JSON; stabilize missing IDs and create a resource.</p></td>
</tr>
<tr><td><p>GET / PUT</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/model</span></span></p></td>
<td><p>Export or conditionally replace native model JSON.</p></td>
</tr>
<tr><td><p>GET / PUT</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/source</span></span></p></td>
<td><p>Export or conditionally replace canonical UTF-8 source.</p></td>
</tr>
<tr><td><p>GET / PUT</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/source-project</span></span></p></td>
<td><p>Export exact authored files or conditionally replace the complete bundle.</p></td>
</tr>
<tr><td><p>GET</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/elements</span></span></p></td>
<td><p>Filter by <span class="docutils literal">kind</span>, <span class="docutils literal">layer</span>, <span class="docutils literal">alias</span>, name <span class="docutils literal">q</span>.</p></td>
</tr>
<tr><td><p>GET</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/relations</span></span></p></td>
<td><p>Filter by <span class="docutils literal">kind</span>, <span class="docutils literal">source</span>, <span class="docutils literal">target</span>, <span class="docutils literal">incident_to</span>.</p></td>
</tr>
<tr><td><p>GET</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/artifact-links</span></span></p></td>
<td><p>Artifact links; optional owner <span class="docutils literal">object</span> filter.</p></td>
</tr>
<tr><td><p>GET</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/traces</span></span></p></td>
<td><p>OA/SA traces; optional endpoint <span class="docutils literal">object</span> filter.</p></td>
</tr>
<tr><td><p>POST</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/query</span></span></p></td>
<td><p>Bounded directed neighborhood, no mutation.</p></td>
</tr>
<tr><td><p>GET / POST</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/validation</span></span></p></td>
<td><p>Validate current model or a submitted candidate.</p></td>
</tr>
<tr><td><p>POST</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/transactions</span></span></p></td>
<td><p>Conditional typed command batch, optional dry run.</p></td>
</tr>
<tr><td><p>POST</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/transitions/preview</span></span></p></td>
<td><p>Preview a core transition against If-Match; return plan/base_revision.</p></td>
</tr>
<tr><td><p>POST</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/transitions/apply</span></span></p></td>
<td><p>Conditionally apply that client-held plan and base_revision.</p></td>
</tr>
<tr><td><p>POST</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/semantic-transitions/query</span></span></p></td>
<td><p>Read selected traces' typed facts, own drift and linked impacts.</p></td>
</tr>
<tr><td><p>POST</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/semantic-transitions/preview</span></span></p></td>
<td><p>Prepare typed semantic decisions and source writeback without writing.</p></td>
</tr>
<tr><td><p>POST</p></td>
<td><p><span class="docutils literal"><span class="pre">/api/v1/projects/{id}/semantic-transitions/apply</span></span></p></td>
<td><p>Apply that prepared candidate under its original shared revision/ETag.</p></td>
</tr>
</tbody>
</table>
<p><span class="docutils literal"><span class="pre">Content-Type:</span> application/json</span> is required for JSON requests.
<span class="docutils literal">text/plain; <span class="pre">charset=utf-8</span></span> is used for Arcadia source. The service does not
guess formats from a filename. Unknown DTO fields, invalid UUIDs/enums, duplicate
model map keys and unsupported schemas are rejected. Maximum body size is
8 MiB. Accepted serialized model JSON and serialized source-bundle JSON each
have an 8 MiB cap, including IDs inserted during compilation. The stored
envelope allows both bounded representations plus small framing overhead.
Compressed or encoded request bodies and browser Origin requests are
not supported.</p>
<p>Model admission permits at most 5,000 elements plus relations, 20,000 total
persistent records (including the project, views, placements, routes and manual
port anchors), and 50,000 ordered step references. Source declaration counts and decoded JSON record
counts are checked before structural validation. Legacy import counts the
occurrences and placements migration will generate before validating or
migrating that model. Exceeding these budgets returns <span class="docutils literal">422 model_limit</span>;
candidate validation reports the same diagnostic in its 200 response.
Parsing, validation and query processing use snapshot workers, so this work
does not hold the catalog lock or serialize unrelated model preparation.</p>
<p>Import accepts schema-1 JSON through the shared explicit migration adapter,
as well as schema-2, schema-3, schema-4, schema-5, schema-6 and current schema-7 JSON. Source import uses the shared language parser
and its supported migrations. Export uses schema 7 / arcadia 7. Native JSON
replacement accepts supported older schemas through the same explicit migration.
Only documented query parameters are accepted. In particular, appending
<span class="docutils literal"><span class="pre">?revision=...</span></span> to model/source export is an error, not historical retrieval.</p>
</section>
<section id="authored-source-projects">
<h2>Authored source projects</h2>
<p>A source bundle contains <span class="docutils literal">entry</span> and a map of <span class="docutils literal">files</span>. For example:</p>
<pre class="literal-block">{
&quot;entry&quot;: &quot;rescue.arcadia&quot;,
&quot;files&quot;: {
&quot;rescue.arcadia&quot;: &quot;arcadia 7; project rescue \&quot;Rescue\&quot; { include \&quot;oa/work.arcadia\&quot;; }\n&quot;,
&quot;oa/work.arcadia&quot;: &quot;// Engineering rationale\noa_activity assess \&quot;Assess assistance\&quot; {}\n&quot;
}
}</pre>
<p>The entry is a root filename. All keys are canonical, portable, slash-separated
relative paths ending in <span class="docutils literal">.arcadia</span>. Includes resolve only against these
submitted strings. They never read the service filesystem, URLs, artifact
targets or another hosted resource. All submitted files must be reachable;
missing files, cycles, duplicate keys, case collisions and escaping paths are
rejected. The bundle permits at most 256 files, 32 include edges along a path,
and 1,024 include edges in total. Model and source-byte budgets apply across
the complete bundle, not separately per file. Current bundle syntax is source7; source3/4/5/6 bundles migrate explicitly while
preserving their files/includes/comments. V1/V2 single-file migration remains
available through interchange import.</p>
<p>Compilation inserts UUIDs into headers that omit them. Import returns 201 with
Location/ETag; GET source-project retrieves the stabilized accepted bundle.
PUT returns <span class="docutils literal">revision</span>, <span class="docutils literal">changed</span>, located <span class="docutils literal">issues</span> and that accepted
<span class="docutils literal">source_project</span>. Preserve the returned IDs before subsequent editing.
With explicit IDs, untouched text, comments, line endings, entry name and module
ownership are preserved exactly. Re-submitting the same accepted bundle is a
no-op. Removing a file means submitting a complete valid bundle without that
file and its includes; no files are created or deleted on the service host.</p>
<p>All typed command, transition, rename and model-interchange writes update this
same accepted source project. Existing declarations and reference comments
follow command identity correspondence, including UUID swaps. Full-model
replacement uses common UUIDs as its correspondence boundary. It preserves
the accepted source layout; canonical interchange formatting/comments are not
adopted as a replacement authored workspace. Use source-project PUT for
authoring file layout and comments. A failed source writeback rejects the whole
write and never falls back to discarding authored files.</p>
<p>Old model-only envelopes are migrated to a deterministic source bundle in
memory when opened. Reading or an exact no-op does not rewrite their files or
advance revisions. Their next changed write persists both representations.
Startup rejects already-coupled envelopes whose source/model disagree or whose
source lacks stable IDs. The 256 MiB store budget charges complete accepted
envelopes, including the generated source of old envelopes before their next
save; an over-capacity old store is reported rather than silently pruned.</p>
</section>
<section id="queries-and-pagination">
<h2>Queries and pagination</h2>
<p>List filters combine using AND. Enum spelling is case-sensitive and comes
from the shared schema: examples include <span class="docutils literal">kind=Activity</span> and <span class="docutils literal">layer=Oa</span>.
Aliases match exactly; <span class="docutils literal">q</span> is a Unicode-lowercase substring match on the
display name. Empty or invalid enum values are request errors.</p>
<p>Lists are ordered by UUID. <span class="docutils literal">limit</span> defaults to 100 and accepts 1 through
1000. <span class="docutils literal">after</span> is an exclusive last UUID. <span class="docutils literal">next_after</span> is null at the end.
Project-scoped lists return a revision. Include that revision on following
pages to detect a changed model; 409 <span class="docutils literal">snapshot_changed</span> means restart the
query. Supplying a past revision does not retrieve history. The project catalog
is a live list and does not have a multi-page snapshot guarantee.</p>
<p>A neighborhood request is:</p>
<pre class="literal-block">{
&quot;roots&quot;: [&quot;1b37b9d7-9a95-4a51-8707-010878a82419&quot;],
&quot;direction&quot;: &quot;both&quot;,
&quot;relation_kinds&quot;: [&quot;Allocation&quot;, &quot;Interaction&quot;],
&quot;max_depth&quot;: 2,
&quot;max_objects&quot;: 200,
&quot;revision&quot;: 3
}</pre>
<p>Roots may identify elements or relations. The service traverses relation
source/target adjacency in the selected direction (incoming/outgoing/both),
preserves distinct parallel relations, and returns <span class="docutils literal">elements</span>, <span class="docutils literal">relations</span>,
<span class="docutils literal">revision</span> and <span class="docutils literal">truncated</span>. Empty kind filters permit all relation kinds.
Every returned relation includes its endpoint closure, including the endpoints
of a referenced relation. Closure records count against the object bound but
do not add traversal depth. Model ownership, process occurrence order and
non-endpoint references remain available in the returned records and complete
model; they are not silently treated as additional graph edges.</p>
<p>Use 1–100 roots, depth 0–4, and 1–1000 total returned objects. The cap must fit
the roots and their endpoint closure. A root closure that cannot fit is an
error; further omitted edges set <span class="docutils literal">truncated: true</span>. A missing root is 422.
Deterministic UUID iteration makes repeated queries of one snapshot stable.</p>
</section>
<section id="transactions">
<h2>Transactions</h2>
<p>The <span class="docutils literal">commands</span> array contains the shared externally tagged Serde command
representation. It is not RFC 6902 JSON Patch. For example:</p>
<pre class="literal-block">{
&quot;commands&quot;: [
{&quot;Rename&quot;: [&quot;1b37b9d7-9a95-4a51-8707-010878a82419&quot;, &quot;Assess assistance&quot;]},
{&quot;Describe&quot;: [&quot;1b37b9d7-9a95-4a51-8707-010878a82419&quot;, &quot;Review the request.&quot;]}
],
&quot;dry_run&quot;: true
}</pre>
<p>One-field variants use <span class="docutils literal"><span class="pre">{&quot;Delete&quot;:&quot;uuid&quot;}</span></span>; tuple variants use arrays;
named-field variants use objects. For a new typed OA activity:</p>
<pre class="literal-block">{
&quot;CreateElement&quot;: {
&quot;id&quot;: &quot;1b37b9d7-9a95-4a51-8707-010878a82419&quot;,
&quot;alias&quot;: &quot;assess&quot;,
&quot;name&quot;: &quot;Assess assistance&quot;,
&quot;description&quot;: &quot;Review the request.&quot;,
&quot;parent&quot;: null,
&quot;body&quot;: {&quot;Oa&quot;: &quot;Activity&quot;}
}
}</pre>
<p><span class="docutils literal">CreateArtifact</span>/<span class="docutils literal">EditArtifact</span> and <span class="docutils literal">CreateTrace</span>/<span class="docutils literal">EditTrace</span> use the same
transaction boundary as engineering edits. Artifact URI, revision and fragment
strings are opaque references. No URI is fetched or verified by the service.
Model references and alias uniqueness are checked by the core.</p>
<p>At most 200 commands are allowed, counting nested Batch wrappers. Explicit
creation identities allow later commands in the batch to reference earlier
creations. The shared <span class="docutils literal">execute_batch</span> applies all operations to one candidate
and validates the final state. A rejected operation or final structural error
rejects the whole request. Reference rewrites/deletion cleanup follow the same
core logic as desktop editing. Command preparation retains original-to-candidate
identity correspondence through UUID edits, swaps, deletion and reuse. Source
writeback uses that correspondence to preserve declaration ownership and comments.</p>
<p>Dry run still requires <span class="docutils literal"><span class="pre">If-Match</span></span>. Its response includes <span class="docutils literal">revision</span>,
<span class="docutils literal">dry_run</span>, <span class="docutils literal">changed</span>, <span class="docutils literal">issues</span> and the proposed <span class="docutils literal">model</span> and
<span class="docutils literal">source_project</span>. It validates source writeback as well as semantics and neither writes
nor reserves IDs. A committed response omits the proposed model and source
project. Commit must check the revision again. A no-op is successful with
<span class="docutils literal">changed: false</span> and the original ETag.</p>
</section>
<section id="diagram-port-positions">
<h2>Diagram port positions</h2>
<p><span class="docutils literal">NodePlacement.port_anchors</span> is an optional list of
<span class="docutils literal"><span class="pre">{&quot;port&quot;:&quot;&lt;port</span> <span class="pre">UUID&gt;&quot;,&quot;side&quot;:&quot;Top&quot;,&quot;offset&quot;:0.25}</span></span> records. Side is
Left, Right, Top, or Bottom; offset is a finite fraction from 0 through 1,
measured from top on vertical edges and from left on horizontal edges.
The port must be a direct child of the placement's semantic element and occur
at most once in its anchor list. Placement is presentation state; it changes
neither semantic ownership nor port direction. Other diagrams are independent.</p>
<p>The existing transaction endpoint accepts:</p>
<pre class="literal-block">{&quot;commands&quot;:[{&quot;SetPortAnchor&quot;:{
&quot;diagram&quot;:&quot;&lt;diagram UUID&gt;&quot;,&quot;node&quot;:&quot;&lt;placement UUID&gt;&quot;,
&quot;anchor&quot;:{&quot;port&quot;:&quot;&lt;port UUID&gt;&quot;,&quot;side&quot;:&quot;Top&quot;,&quot;offset&quot;:0.25}
}}]}</pre>
<p><span class="docutils literal">SetPortAnchor</span> upserts by port UUID. <span class="docutils literal">RemovePortAnchor</span> takes
<span class="docutils literal">{diagram,node,port}</span> and restores automatic positioning. Repeating a reset
is a no-op only while the referenced port still belongs to that placement's
element; missing or stale owners are rejected. Remove old anchors before
reparenting in the same atomic batch. Both commands support ordinary dry run,
ETag checks and source-project writeback. Rejected batches preserve the model,
authored files and revision. JSON/source imports may omit <span class="docutils literal">port_anchors</span>;
it defaults to <span class="docutils literal">[]</span> and empty lists are omitted on export. The normative
diagram semantics and source spelling are in <span class="docutils literal">language.rst</span> section 5.</p>
</section>
<section id="contextual-process-and-chain-topology">
<h2>Contextual process and chain topology</h2>
<p>Operational processes and system functional chains can combine work
contributions, exchange contributions, explicit controls and references to
reusable sequences. Each contribution is an ordinary <span class="docutils literal">Occurrence</span> element
owned directly by the process/chain, with its stable ID in that owner's
<span class="docutils literal">steps</span> list. <span class="docutils literal">OccurrenceBody</span> includes, for example:</p>
<pre class="literal-block">{&quot;Action&quot;:{&quot;action&quot;:&quot;&lt;work UUID&gt;&quot;,&quot;lifeline&quot;:null}}
{&quot;Control&quot;:{&quot;kind&quot;:&quot;Choice&quot;}}
{&quot;SequenceReference&quot;:{&quot;sequence&quot;:&quot;&lt;process or chain UUID&gt;&quot;}}</pre>
<p><span class="docutils literal">ControlKind</span> is <span class="docutils literal">Choice</span>, <span class="docutils literal">Merge</span>, <span class="docutils literal">Fork</span>, <span class="docutils literal">Join</span> or <span class="docutils literal">Loop</span>.
<span class="docutils literal">RelationBody.SequenceLink</span> connects contribution IDs in one owner and
contains <span class="docutils literal">source</span>, <span class="docutils literal">target</span> and a string <span class="docutils literal">guard</span>. Conditions belong to
choice/loop paths; an explicit <span class="docutils literal">else</span> guard can describe the other path.
The readable order of the <span class="docutils literal">steps</span> list remains persistent, while links
express the explicit alternative, parallel and loop topology. The core checks
owner context, work/exchange endpoint agreement and recursive sequence reuse;
engineering diagnostics identify incomplete branch cardinality or paths.
Old exchange-only sequences without explicit links retain their linear meaning.</p>
<p>These records use the same create/edit transaction commands and source/model
replacement routes as other engineering records. For example,
<span class="docutils literal">GET <span class="pre">/api/v1/projects/{id}/relations?kind=SequenceLink</span></span> queries the links.
The source representation uses <span class="docutils literal">sequence &#64;alias</span> references. The service
does not execute conditions or simulate a process.</p>
</section>
<section id="caller-qualified-process-and-chain-links">
<h2>Caller-qualified process and chain links</h2>
<p>Schema 7 adds the closed <span class="docutils literal">RelationBody.ContextualLink</span> payload:</p>
<pre class="literal-block">{
&quot;ContextualLink&quot;: {
&quot;owner&quot;: &quot;&lt;caller process UUID&gt;&quot;,
&quot;source&quot;: {&quot;references&quot;: [], &quot;occurrence&quot;: &quot;&lt;direct X occurrence UUID&gt;&quot;},
&quot;target&quot;: {&quot;references&quot;: [&quot;&lt;R1 reference occurrence UUID&gt;&quot;],
&quot;occurrence&quot;: &quot;&lt;B occurrence UUID in referenced definition&gt;&quot;},
&quot;purpose&quot;: {&quot;Precedence&quot;: {&quot;guard&quot;: &quot;check accepted&quot;}}
}
}</pre>
<p><span class="docutils literal">references</span> is an ordered path of reference-occurrence IDs, never sequence
definition IDs; at most 64entries per endpoint. The explicit owner determines
context and source placement. <span class="docutils literal">purpose</span> is exactly Precedence with string
guard, Exchange with work-exchange UUID, or CommonWork with work UUID. Only
Precedence contributes ordering; the other purposes preserve assembly incidence.
Both paths empty with Precedence must use the existing SequenceLink constructor.
Query these records with <span class="docutils literal"><span class="pre">relations?kind=ContextualLink</span></span>. Ordinary create/edit,
source replacement and JSON replacement share the same owner/path/purpose checks.</p>
<p>R1.B and R2.B remain separate caller contributions even if B has one definition
UUID. Deleting a typed path/leaf/owner/purpose dependency removes the whole link;
retargeting an invalid surviving link requires explicit repair. No path shortening,
implicit work duplication or fallback to a whole reference is permitted. Authored
path entries count toward the 50,000 ordered-reference budget. Resolver cache state
does not change validity. Contextual analysis has separate 50,000 node/100,000 edge
limits and explicitly reports incomplete expansion. See language.rst4.2.1 for
caller-qualified diagnostics and synthetic-boundary rules.</p>
</section>
<section id="typed-scenarios-and-message-values">
<h2>Typed scenarios and message values</h2>
<p>Scenario bodies store an explicit <span class="docutils literal">viewpoint</span>. Occurrence Exchange bodies
store <span class="docutils literal">message_kind</span>, optional correlated-call <span class="docutils literal">reply_to</span> and contextual
<span class="docutils literal">values</span>. Message kinds are Asynchronous, Call, Reply, Create, Delete, or
<span class="docutils literal"><span class="pre">{&quot;Timer&quot;:{&quot;expression&quot;:&quot;after</span> 5 <span class="pre">s&quot;}}</span></span>. Each value record contains a
carried DataField UUID in <span class="docutils literal">field</span>, enclosing field UUID list <span class="docutils literal">path</span> (default
[]) and textual <span class="docutils literal">expression</span>. Identity is (path, field), allowing repeated uses
of a Record. Operation Call/Reply direction checks use the direct parameter;
Reference storage stops nested payload traversal. Expressions do not change the
shared exchange item's type or evaluate server-side.</p>
<p><span class="docutils literal">ScenarioUse</span> contains a referenced <span class="docutils literal">scenario</span> and one-to-one lifeline
<span class="docutils literal">bindings</span> records with <span class="docutils literal">referenced</span> and <span class="docutils literal">local</span> UUIDs. The core validates
viewpoint/layer compatibility, call/reply order and reversal, lifetime order,
carried fields, binding identity and recursive reuse through the same candidate
boundary used by the desktop. The normative details are in <span class="docutils literal">language.rst</span>.</p>
<p>Existing schema-2 files may omit the new fields: missing viewpoint maps to
MixedLegacy and missing message fields to Asynchronous, null and []. Source
exports make those compatibility defaults explicit. This preserves original V2
models while the release schema is being integrated; it does not silently
reinterpret old mixed lifelines as a strict new viewpoint.</p>
</section>
<section id="data-and-interface-contracts">
<h2>Data and interface contracts</h2>
<p>Schema4 uses typed bounded DataTypeDefinition and DataValue constructors, field
storage/defaults/directions, and single specialization. Exact JSON shapes are in
<span class="docutils literal">openapi.json</span> and semantic rules and runnable source in <span class="docutils literal">language.rst</span> section 4.5.
Interface membership is an identified InterfaceItemAllocation relation with
independent order/transmission/acquisition. DataAssociation relates Record types
with named, navigable, multiplicity-bearing ends; it does not add carried fields.</p>
<p>Use ordinary relation queries, transactions and artifact links, for example
<span class="docutils literal">GET <span class="pre">/api/v1/projects/{id}/relations?kind=InterfaceItemAllocation</span></span>. The service
and desktop use the same inheritance/path/default validation. Invalid bounds,
defaults, directions, cycles or contract-breaking deletions reject atomically,
preserving the accepted source/model, revision and stored bytes. Correct a related
contract in the same transaction when removing a used interface allocation.</p>
<p>Explicit schema1/2/3 migration preserves prior identities and typed ports. Reports
add semantic defaults, generated interface allocations and unresolved message
values. Old source3 bundles retain files/includes/comments during upgrade; all
current exports use schema7/source7. Reading an old envelope does not write it or
advance its ETag. Canonical exports omit transient migration reports.</p>
</section>
<section id="validation">
<h2>Validation</h2>
<p>GET returns current-model diagnostics. POST accepts either:</p>
<pre class="literal-block">{&quot;format&quot;:&quot;json&quot;, &quot;model&quot;: {&quot;...&quot;:&quot;complete native Project record&quot;}}</pre>
<p>or:</p>
<pre class="literal-block">{&quot;format&quot;:&quot;arcadia&quot;, &quot;source&quot;:&quot;complete source document&quot;}</pre>
<p>or:</p>
<pre class="literal-block">{&quot;format&quot;:&quot;source-project&quot;, &quot;source_project&quot;:{&quot;entry&quot;:&quot;rescue.arcadia&quot;, &quot;files&quot;:{&quot;rescue.arcadia&quot;:&quot;arcadia 7; project rescue \&quot;Rescue\&quot; {}&quot;}}}</pre>
<p>A well-formed validation request returns 200 with <span class="docutils literal">valid</span> and <span class="docutils literal">issues</span> even
if its candidate is invalid, including a model record that fails typed decoding.
Malformed request JSON or an invalid format/payload envelope is a 400.
Source diagnostics include one-based line and column according to the
shared language parser. Candidate validation does not replace current state.
Source-project validation locations refer to the submitted bytes before UUID
insertion. Successful source-project PUT diagnostics refer to the returned
accepted bundle. Missing IDs are not saved or adopted by validation.</p>
</section>
<section id="typed-state-machines-and-events">
<h2>Typed state machines and events</h2>
<p>OA and SA Event records use the same <span class="docutils literal"><span class="pre">SharedBody::Event</span></span> and <span class="docutils literal">EventBody</span>
contract as source and graphical editing. Signal carries same-layer item
references; Time specifies After/At and an expression; Change specifies a
condition expression. State vertices include Choice, Junction, Fork, Join,
ShallowHistory, DeepHistory, EntryPoint, ExitPoint and Terminate, as well as
State, Mode, Initial and Final. Query these through the ordinary <span class="docutils literal">kind</span>
filters. No timer or executable state-machine service is implied.</p>
<p>StateTransition keeps <span class="docutils literal">trigger</span>, <span class="docutils literal">guard</span> and <span class="docutils literal">effect</span> prose and adds
<span class="docutils literal">transition_kind</span> (External/Local/Internal), <span class="docutils literal">triggers</span> (Event or work UUIDs)
and <span class="docutils literal">effects</span> (work UUIDs). The reference lists use UUIDs in JSON and aliases
in source. Missing new properties in staged schema-2 input hydrate as
External/[]/[] without changing prior text. These defaults are compatibility
behavior pending the distinct release schema, not a versionless expansion of
every future input contract.</p>
<p>Use one ordinary transaction to create an event and edit its referring
transition. Reidentification updates references, and deletion prunes signal
items and effect references. Removing the last typed trigger with no prior
trigger prose leaves a descriptive replacement reminder; it does not silently
introduce a completion transition. Invalid typed references reject the whole
candidate and preserve revision/ETag. All writes retain the same conditional
commit and disk persistence contract as other semantic records.</p>
</section>
<section id="state-diagram-representation">
<h2>State diagram representation</h2>
<p><span class="docutils literal">Diagram.projection</span> keeps the existing string values <span class="docutils literal">Overview</span>,
<span class="docutils literal">Decomposition</span>, <span class="docutils literal">Allocation</span>, <span class="docutils literal">Traceability</span>, <span class="docutils literal">FunctionalDataflow</span> and
<span class="docutils literal">Capabilities</span>. A dedicated state view instead uses the required payload:</p>
<pre class="literal-block">{&quot;StateMachine&quot;:{&quot;machine&quot;:&quot;11111111-1111-4111-8111-111111111111&quot;}}</pre>
<p>The UUID MUST identify an existing StateMachine in the diagram's layer.
Only that machine, its Regions and its state vertices may be placed, including
nested members. Empty and partial views are valid. No machine, Region, vertex
or placement is synthesized by accepting or reading a diagram. Source uses
<span class="docutils literal">projection { StateMachine { machine &#64;modes; }; };</span> with the same reference.</p>
<p>Use the ordinary <span class="docutils literal">CreateDiagram</span> or <span class="docutils literal">EditDiagram</span> transaction commands,
JSON model import/replacement, or source/source-project writes. A bare
<span class="docutils literal">&quot;StateMachine&quot;</span>, missing or null <span class="docutils literal">machine</span>, malformed UUID, or additional
payload field is malformed JSON model data (400). A missing, wrong-kind or
cross-layer machine produces the semantic issue <span class="docutils literal">state_diagram_context</span>;
an incompatible placement produces <span class="docutils literal">state_diagram_member</span>. These reject
writes with 422. Transaction rejections use the <span class="docutils literal">command_rejected</span> problem
code and include the first core failure in <span class="docutils literal">detail</span>; candidate validation
provides the structured <span class="docutils literal">issues</span> collection.
Source syntax errors use the source rejection response (422) with locations.
The validation endpoint returns 200 with <span class="docutils literal">valid:false</span> for a well-formed
invalid candidate, as described above.</p>
<p>When changing a diagram's machine or selecting StateMachine for an existing
diagram, remove or relocate incompatible placements in the same transaction.
Other projections continue to preserve hidden placements. Rejected writes
retain the accepted model, source bundle, revision and ETag. Reading a state
view has no semantic or persistence side effects.</p>
</section>
<section id="source-6-communication-and-saved-views">
<h2>Source-6 communication and saved views</h2>
<p>The same import, replacement and command endpoints admit OA
<span class="docutils literal">CommunicationMean { source, target, oriented, items }</span> and root-level
<span class="docutils literal">ExchangeCategory { family, exchanges }</span> records. Communication means join
distinct OA entities/actors. Categories group same-layer exchanges as <span class="docutils literal">Work</span>
or <span class="docutils literal">Participant</span> without owning them. Existing legacy OA boundary exchanges
retain their identities and contracts; migration does not silently replace them.</p>
<p><span class="docutils literal">Diagram.view_options</span> is an optional closed object with defaults: empty
<span class="docutils literal">hidden_edges</span>, <span class="docutils literal">All</span> for <span class="docutils literal">relation_kinds</span>, both category selections,
<span class="docutils literal">coverage</span> and <span class="docutils literal">work_contexts</span>, and <span class="docutils literal">Name</span> for <span class="docutils literal">exchange_labels</span>.
<span class="docutils literal"><span class="pre">{&quot;Only&quot;:[]}</span></span> hides all relation and trace lines; <span class="docutils literal"><span class="pre">{&quot;Any&quot;:[]}</span></span> preserves
an explicit empty category/context selection. Category members union within
each family, and independent filters intersect. <span class="docutils literal">Traceability</span> permits
references from both layers; ordinary projections require the diagram's layer.
These presentation choices preserve semantic records, routes, placements and
the automatic port positions derived from unfiltered eligible exchanges.</p>
<p>Schema/source versions 1–5 reject the new constructors, category review
facts and explicit <span class="docutils literal">view_options</span> field, including an empty object. Their
frozen readers migrate accepted content to schema/source 7 with default view
options. The OpenAPI document describes current records; it is not a permissive
union of historical input formats. Source-7 integration and release acceptance
are tracked separately in the release coverage audit.</p>
</section>
<section id="explicit-interface-operation-identity">
<h2>Explicit interface-operation identity</h2>
<p><span class="docutils literal">OccurrenceBody.Exchange.operation</span> is optional. Absent/null retains ordinary
channel semantics and is omitted in canonical output. <span class="docutils literal"><span class="pre">{&quot;allocation&quot;:null}</span></span>
(or an empty object) retains explicit unresolved operation intent. A selected
<span class="docutils literal"><span class="pre">{&quot;allocation&quot;:&quot;&lt;InterfaceItemAllocation</span> <span class="pre">UUID&gt;&quot;}</span></span> identifies that exact
allocation, including for parameterless operations sharing one channel. These
records are closed; unknown fields are rejected. Earlier schema/source versions
reject the operation field even when explicitly null and reject ContextualLink
and their new semantic facets. Migration never guesses an operation from names,
message values or a channel's item set.</p>
<p>Selection is valid only for SA BoundaryInterface Call/Asynchronous messages.
Core proves actual Standard component-port Requires/Provides roles, compatible
interfaces exposing the same allocation, actual channel direction and allowed
transmission protocol. Reply stores no operation and derives it from its exact
Call; a separate return channel still needs its own valid carried-item/endpoint
contract, including a void return. Selected message values use the exact operation
signature. Unresolved intent preserves live expressions and checks their paths
with an incomplete-signature warning; it does not substitute the channel union.</p>
<p>Allocation deletion clears selection to unresolved only within an otherwise
valid whole candidate. Removing the sole allocation can refuse atomically while
a channel still carries its now-unadmitted item; repair every affected channel
explicitly in the same batch. A surviving same-item allocation may keep a channel
valid, but is never silently selected. Reselection validates retained values
without pruning them. The service uses the same source/history boundary as
graphical editing. See language.rst4.3.1 for the complete contract.</p>
</section>
<section id="cross-layer-transitions">
<h2>Cross-layer transitions</h2>
<p>Preview accepts the shared <span class="docutils literal">TransitionRequest</span> record, including direction
(<span class="docutils literal">OaToSa</span> or <span class="docutils literal">SaToOa</span>), sources, dependency scope, mappings, selected fields,
conflict resolutions and optional destination diagram. All fields are explicit
in OpenAPI. At most 100 sources, 200 mappings, 200 communication endpoint
decisions, 200 operation omissions and 400 field resolutions are
accepted. A conflict-free plan must fit the same 200-command transaction limit
and model/source-capacity limits. A conflict-free preview also checks source
writeback, so its commands can update the same accepted authored workspace.</p>
<p>SA→OA abstraction of explicit operation intent requires <span class="docutils literal">operation_omissions</span>
(omitted means empty). Each closed record contains the selected invocation's
<span class="docutils literal">source</span> UUID and a nonempty <span class="docutils literal">rationale</span> string. Missing, duplicate,
irrelevant or wrong-direction omissions reject. Reply derives its Call's
abstraction and has no second writable operation choice. Source operation
identity/values remain intact; target facts are mapped and validated. Preview
and Apply enforce the same 200 omission limit for ordinary and semantic transitions.</p>
<p>OA <span class="docutils literal">CommunicationMean</span> maps to an SA <span class="docutils literal">BoundaryExchange</span> through an explicit
<span class="docutils literal">communication_endpoints</span> array (omitted means empty). Each decision identifies
the source communication means and both <span class="docutils literal">source_port</span> and <span class="docutils literal">target_port</span>.
Each port choice is either <span class="docutils literal"><span class="pre">{&quot;Reuse&quot;:{&quot;port&quot;:&quot;port-uuid&quot;}}</span></span> or
<span class="docutils literal"><span class="pre">{&quot;Create&quot;:{&quot;id&quot;:&quot;new-port-uuid&quot;,&quot;alias&quot;:&quot;radio_port&quot;,&quot;name&quot;:&quot;Radio</span> port&quot;, <span class="pre">&quot;description&quot;:&quot;&quot;,&quot;kind&quot;:&quot;Standard&quot;,&quot;orientation&quot;:&quot;Unset&quot;}}</span></span>. Created or
reused SA component ports must belong to the explicitly mapped participants.
These per-exchange choices do not replace participant correspondence with port
IDs. Missing or incompatible choices remain preview conflicts. Interface and
functional-port allocations use their existing explicit workflows; an engineer
may omit an unresolved allocation from this transition. Reverse transition maps
boundary ports through their owners to OA participants.</p>
<p><span class="docutils literal">ExchangeCategory</span> transitions preserve their family and map only explicitly
corresponding member exchanges. Missing member mappings are conflicts, not new
fabricated exchanges. Typed review exposes <span class="docutils literal">Category.Family</span> and the
<span class="docutils literal">CategoryExchanges</span> member collection; historical review facts remain exact.</p>
<p>The preview response is <span class="docutils literal"><span class="pre">{&quot;base_revision&quot;:1,&quot;plan&quot;:{...}}</span></span>. It contains
planned changes, conflicts, warnings and exact commands/IDs. It does not write
the model or persist a server-side plan. Apply accepts that entire response and
requires the original ETag in <span class="docutils literal"><span class="pre">If-Match</span></span>. It checks both base_revision and the
core's snapshot fingerprint before executing the shared transition validator.
Stale revisions fail with 412 and unresolved conflicts with 422. Successful
apply increments the revision once, preserving the planned identities.</p>
<p>A supplied plan is a client-owned command proposal. It is not cryptographically
authenticated as an untouched server preview; the same authenticated client
can submit ordinary typed commands. The core fingerprint is a change detector,
not a security digest. There is no plan token, expiration store or receipt.</p>
</section>
<section id="typed-semantic-transition-review">
<h2>Typed semantic transition review</h2>
<p>The sibling <span class="docutils literal"><span class="pre">semantic-transitions</span></span> routes use the <a class="reference external" href="language.html#typed-semantic-review-facts">typed review semantics</a> in <span class="docutils literal">language.rst</span> sections 5.1–5.5.
The original prose transition routes keep
their existing contract. All new routes use JSON and the existing authentication,
capacity, worker and error boundaries.</p>
<p>Query accepts <span class="docutils literal"><span class="pre">{&quot;traces&quot;:[&quot;trace-uuid&quot;],&quot;references&quot;:{},&quot;revision&quot;:1}</span></span>.
<span class="docutils literal">references</span> is an optional map of canonical OA UUIDs to SA UUIDs, including
historical deleted identities. It never guesses correspondences from names.
<span class="docutils literal">revision</span> is optional; a mismatch returns 409. Select 1–100 unique existing
trace IDs; an empty or duplicate selection returns 400 and a missing trace
returns 404. The response includes the current revision and items containing
<span class="docutils literal">trace</span>, <span class="docutils literal">oa</span>, <span class="docutils literal">sa</span>, typed <span class="docutils literal">facets</span>, <span class="docutils literal">drift</span> and <span class="docutils literal">linked_impacts</span>.
Own and linked drift and their unreviewed flags remain distinct. Query reads one
immutable snapshot, does not refresh baselines, and does not fetch artifact URIs.</p>
<p>Preview accepts <span class="docutils literal">SemanticTransitionRequest</span>:</p>
<pre class="literal-block">{
&quot;transition&quot;: {
&quot;direction&quot;: &quot;OaToSa&quot;,
&quot;sources&quot;: [&quot;40000000-0000-4000-8000-000000000002&quot;],
&quot;scope&quot;: &quot;SelectedOnly&quot;,
&quot;mappings&quot;: [{
&quot;source&quot;: &quot;40000000-0000-4000-8000-000000000002&quot;,
&quot;target&quot;: &quot;40000000-0000-4000-8000-000000000003&quot;,
&quot;target_kind&quot;: null
}],
&quot;fields&quot;: [], &quot;resolutions&quot;: [], &quot;destination_diagram&quot;: null
},
&quot;traces&quot;: {}, &quot;references&quot;: {},
&quot;reviews&quot;: [{
&quot;source&quot;: &quot;40000000-0000-4000-8000-000000000002&quot;,
&quot;resolutions&quot;: [
{&quot;facet&quot;:{&quot;Header&quot;:&quot;Name&quot;}, &quot;decision&quot;:&quot;TakeSource&quot;},
{&quot;facet&quot;:{&quot;Data&quot;:&quot;Unit&quot;}, &quot;decision&quot;:&quot;KeepTarget&quot;}
],
&quot;reset&quot;: []
}],
&quot;candidates&quot;: [], &quot;accepted_impacts&quot;: []
}</pre>
<p>The example maps an existing OA data type to its traced SA counterpart, takes
only its name and acknowledges intentionally different units. Other facets stay
unreviewed or retain their earlier drift. Select an explicit trace through the
<span class="docutils literal">traces</span> map (source UUID to trace UUID) when multiple trace kinds connect the
pair. <span class="docutils literal">reset</span> deliberately invalidates exact old selectors after changed
correspondence. The optional collections default to empty. Semantic header
decisions use typed facets; leave legacy <span class="docutils literal">transition.fields</span> and
<span class="docutils literal">transition.resolutions</span> empty.</p>
<p>Facet selectors are closed enums, for example <span class="docutils literal"><span class="pre">{&quot;Data&quot;:&quot;IntegerMinimum&quot;}</span></span>
or <span class="docutils literal"><span class="pre">{&quot;Member&quot;:{&quot;collection&quot;:&quot;SignalItems&quot;,&quot;keys&quot;:{&quot;oa&quot;:&quot;oa-uuid&quot;,&quot;sa&quot;:&quot;sa-uuid&quot;}}}</span></span>.
Annotation keys contain the entire path and field; enum literal keys are exact
strings. <span class="docutils literal">KeepTarget</span>, <span class="docutils literal">TakeSource</span> and <span class="docutils literal">Candidate</span> operate on independently
selected facts. Candidate records use existing Element/Relation/ArtifactLink
types, must preserve identity/alias, and must equal precisely the result of
the selected facets. Constructor review covers its coupled introduced/removed
fields. Membership review does not silently acknowledge order; target-only
members remain independent. OpenAPI defines every selector and typed payload.</p>
<p>Preview requires <span class="docutils literal"><span class="pre">If-Match</span></span> and returns <span class="docutils literal"><span class="pre">{&quot;base_revision&quot;:1,&quot;plan&quot;:{...}}</span></span>.
The plan contains the original typed request, mapping plan, review facts,
acknowledged/retired selectors, linked impacts, exact prepared impacts, conflicts,
commands, and base/prepared fingerprints. A conflict-free preview also prepares
the complete authored source bundle and checks its model equivalence and capacity.
No preview changes the model, source, revision or stored bytes.</p>
<p>If ordinary preparation induces additional cleanup, the plan reports exact typed
before/after impacts and a conflict. Review those impacts, place the accepted
records in <span class="docutils literal">accepted_impacts</span>, and request another preview. Acceptance cannot
override a contradictory selected facet. Missing mappings, ambiguous order,
duplicate decisions, invalid candidates or unresolved impacts cannot be applied.
This is the shared core planner and command preparation, with no server-specific
semantic mutation engine.</p>
<p>Apply accepts the entire preview envelope under the same <span class="docutils literal"><span class="pre">If-Match</span></span>. It checks
<span class="docutils literal">base_revision</span>, the model fingerprint, unresolved conflicts, the prepared
candidate fingerprint, ordinary model validation and coupled source preparation,
then atomically stores one accepted model/source revision. The final store check
also catches a concurrent edit during preparation. Source-only edits invalidate
the preview through the shared ETag even when the model fingerprint is unchanged.
Stale ETag/revision returns 412; semantic rejection returns 422 with code
<span class="docutils literal">semantic_transition_rejected</span>. Exact no-op candidates preserve revision.
Read and preview again after a successful changed apply before reviewing further.</p>
<p>A supplied plan remains a client-owned candidate. Fingerprints detect stale or
inconsistent proposals; they are not tamper-proof signatures, authentication
receipts or proof of original review authorship. Apply preserves preview-generated
identities and does not rerun the planner with fresh random IDs. Authenticated
clients already have ordinary model/source editing privileges. The server does
not persist plans, tokens or review sessions.</p>
<p>Requests allow 100 sources, trace choices and reviews; 200 mappings, candidates
and accepted impacts; 5,000 canonical reference mappings; and 5,000 facet
resolutions plus resets across all reviews. The legacy 400 prose-resolution
limit, 200 communication endpoint decisions, 200 operation omissions and
200-command transaction limit still apply. Query has the same 5,000
reference-map limit. Core bounded linked traversal errors remain observable as
semantic rejection; no truncated result silently claims complete review.</p>
<p>Schema/source 5 adds <span class="docutils literal">TraceBaseline.semantic</span>. Absence or null is Unreviewed;
migrating older prose baselines does not fabricate semantic history. The persisted
baseline contains only closed typed <span class="docutils literal">FacetReview</span> facts, not whole candidate
records or a generic JSON value tree. Historical UUIDs remain historical, including
after deletion, and source uses explicit <span class="docutils literal">uuid</span> tokens for them.</p>
</section>
<section id="error-contract">
<h2>Error contract</h2>
<p>All errors have <span class="docutils literal"><span class="pre">Content-Type:</span> application/problem+json</span>. Example:</p>
<pre class="literal-block">{
&quot;type&quot;:&quot;urn:arcadia:problem:revision_conflict&quot;,
&quot;title&quot;:&quot;Precondition Failed&quot;,
&quot;status&quot;:412,
&quot;code&quot;:&quot;revision_conflict&quot;,
&quot;detail&quot;:&quot;Project changed. Reload and review the current model before retrying.&quot;,
&quot;current_revision&quot;:3
}</pre>
<p><span class="docutils literal">issues</span> contain severity, code and message, and may include field,
object_id, line, column, source <span class="docutils literal">path</span>, half-open UTF-8 byte <span class="docutils literal">span</span>
(<span class="docutils literal">start</span>, <span class="docutils literal">end</span>), and <span class="docutils literal">related</span> source locations (path/span). Lines and
columns are one-based; columns count Unicode scalars. Use
<span class="docutils literal">code</span> for client decisions, not the English message. <span class="docutils literal"><span class="pre">X-Request-ID</span></span> is a
response correlation UUID. This is not an idempotency key or receipt address.</p>
<ul class="simple">
<li><p>400: malformed JSON/envelope/query/UUID or unsupported ETag form.</p></li>
<li><p>401: missing or incorrect configured bearer token; includes WWW-Authenticate.</p></li>
<li><p>403: browser Origin is unsupported, or unauthenticated Host is not loopback.</p></li>
<li><p>404: missing project or route.</p></li>
<li><p>405: unsupported HTTP method.</p></li>
<li><p>409: requested query revision changed or revision counter exhausted.</p></li>
<li><p>412: stale write precondition.</p></li>
<li><p>413: body, serialized model, stabilized source bundle or envelope exceeds its size limit.</p></li>
<li><p>415: unsupported Content-Type or Content-Encoding.</p></li>
<li><p>422: rejected source/model/command, model count limit, or missing graph root.</p></li>
<li><p>428: missing If-Match.</p></li>
<li><p>503: work slots full or filesystem/storage unavailable; Retry-After is present.</p></li>
<li><p>504: request deadline; an admitted write outcome may be unknown.</p></li>
<li><p>507: fixed store cap of 128 models or 256 MiB serialized envelopes reached.</p></li>
<li><p>500: unexpected server/worker failure.</p></li>
</ul>
<p>Deployment and persistence limitations are documented in <span class="docutils literal">server.md</span>.</p>
</section>
</main>
</body>
</html>