Skip to content

guide

tit.server.routes.guide

/api/guide/* — the fixed, packaged guide scene (plan R4).

The shape mirrors /api/scene/* on purpose, minus everything that made the scene routes project routes: there is no subject parameter, no cache state, no 202, no build. Every answer here is a read of a file that shipped with the installation (:mod:tit.scene.guide), so the pane paints on a machine with no project bound, no head model built, and no subject selected.

Three rules, each with the failure it prevents:

  • No client string ever reaches the filesystem. part, atlas and net are checked against the packaged manifest's own ids before anything is opened, and the manifest's relative paths are resolved back inside the package directory. A traversal segment cannot survive a membership test against a list the server wrote itself.
  • Binary payloads are cached hard; the catalog is refreshed. ETag is the file's SHA-256 out of the manifest and Cache-Control is a year: unlike a subject's surface, this URL's content cannot change under a client without the installation itself changing. The manifest is not cached, so installation updates do not leave the atlas selector using an obsolete catalog.
  • The space is guide-ras, and it is in every response. A consumer that mistakes it for a research subject's RAS writes a silently wrong coordinate; saying so on the wire is what lets the desktop pane disable click-to-config instead of trusting a comment.

manifest

manifest(guide_id: str | None = GuideQuery) -> Any

The packaged manifest, minus the per-file bookkeeping a client never uses.

files/*_meta/sha256 describe the package (the gate test reads them off disk); what crosses the wire is the same shape the scene manifest has, so one pane component can consume either.

Source code in tit/server/routes/guide.py
@router.get(
    "/api/guide/manifest",
    summary="Everything the fixed guide scene contains (no subject, no build, no cache state)",
)
def manifest(guide_id: str | None = GuideQuery) -> Any:
    """The packaged manifest, minus the per-file bookkeeping a client never uses.

    ``files``/``*_meta``/``sha256`` describe the *package* (the gate test reads
    them off disk); what crosses the wire is the same shape the scene manifest
    has, so one pane component can consume either.
    """
    guide_id = _guide_id(guide_id)
    body = _manifest(guide_id)
    parts = [
        {k: v for k, v in part.items() if k != "files"}
        for part in body.get("parts", [])
    ]
    atlases = [
        {
            k: v
            for k, v in atlas.items()
            if k not in ("files", "legend_file", "legend_meta")
        }
        for atlas in body.get("atlases", [])
    ]
    nets = [
        {k: v for k, v in net.items() if k not in ("file", "sha256", "bytes")}
        for net in body.get("nets", [])
    ]
    return _json_response(
        {
            "guide": body.get("guide", {}),
            # Which packaged guide answered, and which ones this installation
            # has — the pane's Subject | MNI switch offers only what is here.
            "guide_id": guide_id,
            "guides": _installed(),
            "guide_version": body.get("guide_version", guide.GUIDE_VERSION),
            "space": body.get("space", guide.GUIDE_SPACE),
            "bbox": body.get("bbox"),
            "focus_bbox": body.get("focus_bbox"),
            "parts": parts,
            "nets": nets,
            "atlases": atlases,
            "volumes": body.get("volumes", []),
            "provenance": body.get("provenance", {}),
            "cache": {"state": "ready", "built_ms": 0.0},
        },
        cache_control="private, no-store",
    )